From 039ed9cb7f3edd2cae640065979aed4a7eb31103 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 22 Aug 2008 15:40:41 +0000 Subject: [PATCH 01/10] svn merge -r 16215:16231 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- .../blender/blenkernel/BKE_blenkernel.vcproj | 6 + release/text/copyright.txt | 2 +- source/blender/blenkernel/BKE_deform.h | 1 + source/blender/blenkernel/intern/modifier.c | 5 +- source/blender/blenkernel/intern/shrinkwrap.c | 15 +- source/blender/blenlib/BLI_winstuff.h | 8 + source/blender/include/BDR_gpencil.h | 1 - source/blender/include/BIF_drawgpencil.h | 5 +- source/blender/makesdna/DNA_gpencil_types.h | 4 +- source/blender/makesdna/DNA_space_types.h | 1 + source/blender/python/api2_2x/Particle.c | 6 +- source/blender/src/drawgpencil.c | 208 +++++++++++------- source/blender/src/gpencil.c | 60 ++++- .../Converter/KX_ConvertActuators.cpp | 8 +- source/gameengine/Ketsji/KX_PythonInit.cpp | 133 +++++------ .../gameengine/Physics/Bullet/CMakeLists.txt | 4 + source/gameengine/PyDoc/GameLogic.py | 13 +- 17 files changed, 305 insertions(+), 175 deletions(-) diff --git a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj index 0ea3503a289..42dcc843091 100644 --- a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj +++ b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj @@ -494,6 +494,9 @@ + + @@ -708,6 +711,9 @@ + + diff --git a/release/text/copyright.txt b/release/text/copyright.txt index 6082af3033f..9f49dd4587a 100644 --- a/release/text/copyright.txt +++ b/release/text/copyright.txt @@ -56,7 +56,7 @@ information, claims of third parties, damages as a result of injury to any person, or any other loss) arising out of or in connection with the license granted under this License Agreement or the use of or inability - to use the Software, even if VF has been advised of the possibility of + to use the Software, even if BF has been advised of the possibility of such damages. 5. User warning and indemnification diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 73a9b2b5d4e..e982806a6cc 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -38,6 +38,7 @@ struct Object; struct ListBase; struct bDeformGroup; +struct MDeformVert; void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2); struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index f33f33d9d46..e8453ef934c 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -3,7 +3,7 @@ * * ***** BEGIN GPL LICENSE BLOCK ***** * -* This program is free software; you can redistribute it and/orw +* 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. @@ -7405,7 +7405,6 @@ static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *for dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier"); } - /***/ static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES]; @@ -7733,7 +7732,6 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode; - mti->initData = shrinkwrapModifier_initData; mti->copyData = shrinkwrapModifier_copyData; mti->requiredDataMask = shrinkwrapModifier_requiredDataMask; @@ -7757,7 +7755,6 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->foreachObjectLink = simpledeformModifier_foreachObjectLink; mti->updateDepgraph = simpledeformModifier_updateDepgraph; - typeArrInit = 0; #undef INIT_TYPE } diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 5c020bf2339..292a800e9cd 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -63,7 +63,7 @@ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) /* Benchmark macros */ -#ifndef _WIN32 +#if !defined(_WIN32) && 0 #include @@ -166,11 +166,6 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array calc.target = CDDM_copy( object_get_derived_final(smd->target, CD_MASK_BAREMESH) ); - if(!calc.target) - { - printf("Target derived mesh is null! :S\n"); - } - //TODO there might be several "bugs" on non-uniform scales matrixs.. because it will no longer be nearest surface, not sphere projection //because space has been deformed space_transform_setup(&calc.local2target, ob, smd->target); @@ -182,12 +177,6 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM //Projecting target defined - lets work! if(calc.target) { - - printf("Shrinkwrap (%s)%d over (%s)%d\n", - calc.ob->id.name, calc.numVerts, - calc.smd->target->id.name, calc.target->getNumVerts(calc.target) - ); - switch(smd->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: @@ -447,7 +436,7 @@ do { float *co = calc->vertexCos[i]; float tmp_co[3], tmp_no[3]; - float lim = 1000; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that + float lim = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup); if(weight == 0.0f) continue; diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 11150075bac..3bb63506c95 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -61,6 +61,10 @@ // These definitions are also in arithb for simplicity +#ifdef __cplusplus +extern "C" { +#endif + #ifndef M_PI #define M_PI 3.14159265358979323846 #endif @@ -116,5 +120,9 @@ int closedir (DIR *dp); void get_default_root(char *root); int check_file_chars(char *filename); +#ifdef __cplusplus +} +#endif + #endif /* __WINSTUFF_H__ */ diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index eb749cf28ec..7340a2e44e0 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -43,7 +43,6 @@ struct bGPDframe; /* Temporary 'Stroke Point' data */ typedef struct tGPspoint { short x, y; /* x and y coordinates of cursor (in relative to area) */ - float xf, yf; /* same as x and y, but as floats */ float pressure; /* pressure of tablet at this point */ } tGPspoint; diff --git a/source/blender/include/BIF_drawgpencil.h b/source/blender/include/BIF_drawgpencil.h index 418446313df..eacafce058d 100644 --- a/source/blender/include/BIF_drawgpencil.h +++ b/source/blender/include/BIF_drawgpencil.h @@ -28,15 +28,18 @@ #ifndef BIF_DRAWGPENCIL_H #define BIF_DRAWGPENCIL_H + +struct bGPdata; struct ScrArea; struct View3D; struct SpaceNode; struct SpaceSeq; -struct bGPdata; struct uiBlock; +struct ImBuf; short draw_gpencil_panel(struct uiBlock *block, struct bGPdata *gpd, struct ScrArea *sa); +void draw_gpencil_2dimage(struct ScrArea *sa, struct ImBuf *ibuf); void draw_gpencil_2dview(struct ScrArea *sa, short onlyv2d); void draw_gpencil_3dview(struct ScrArea *sa, short only3d); void draw_gpencil_oglrender(struct View3D *v3d, int winx, int winy); diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index dca4e28688d..13d412c2c42 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -59,8 +59,10 @@ typedef struct bGPDstroke { #define GP_STROKE_3DSPACE (1<<0) /* stroke is in 2d-space */ #define GP_STROKE_2DSPACE (1<<1) + /* stroke is in 2d-space (but with special 'image' scaling) */ +#define GP_STROKE_2DIMAGE (1<<2) /* stroke is an "eraser" stroke */ -#define GP_STROKE_ERASER (1<<2) +#define GP_STROKE_ERASER (1<<15) /* Grease-Pencil Annotations - 'Frame' diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index a8694dfb7f5..39d457058c1 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -247,6 +247,7 @@ typedef struct SpaceImage { float xof, yof; /* user defined offset, image is centered */ float centx, centy; /* storage for offset while render drawing */ + struct bGPdata *gpd; /* grease pencil data */ } SpaceImage; typedef struct SpaceNla { diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index 2c2e724129e..bc65426e16c 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -804,7 +804,7 @@ static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ) { ParticleSystem *psys = 0L; Object *ob = 0L; - PyObject *partlist,*seglist; + PyObject *partlist,*seglist=0L; ParticleCacheKey **cache,*path; PyObject* loc = 0L; ParticleKey state; @@ -1107,7 +1107,7 @@ static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ) ParticleSystem *psys = 0L; ParticleData *data; Object *ob = 0L; - PyObject *partlist,*tuple; + PyObject *partlist,*tuple=0L; DerivedMesh* dm; float vm[4][4],wm[4][4]; float size; @@ -1217,7 +1217,7 @@ static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ) ParticleSystem *psys = 0L; ParticleData *data; Object *ob = 0L; - PyObject *partlist,*tuple; + PyObject *partlist,*tuple=0L; DerivedMesh* dm; float vm[4][4],wm[4][4]; float life; diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index ee28049e2c0..f60d53a9c5d 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -37,6 +37,9 @@ #include "MEM_guardedalloc.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #include "BMF_Api.h" #include "BLI_arithb.h" @@ -317,6 +320,7 @@ enum { GP_DRAWDATA_NOSTATUS = (1<<0), /* don't draw status info */ GP_DRAWDATA_ONLY3D = (1<<1), /* only draw 3d-strokes */ GP_DRAWDATA_ONLYV2D = (1<<2), /* only draw 'canvas' strokes */ + GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */ }; /* ----- Tool Buffer Drawing ------ */ @@ -446,7 +450,7 @@ static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thicknes static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) { /* if thickness is less than 3, 'smooth' opengl lines look better */ - if ((thickness < 3) || (G.rt==0)) { + if (thickness < 3) { bGPDspoint *pt; int i; @@ -466,18 +470,18 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, } else { /* tesselation code: currently only enabled with rt != 0 */ bGPDspoint *pt1, *pt2; - float p0[2], p1[2], pm[2]; + float pm[2]; int i; glShadeModel(GL_FLAT); - glBegin(GL_QUAD_STRIP); + glBegin(GL_QUADS); for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) { float s0[2], s1[2]; /* segment 'center' points */ float t0[2], t1[2]; /* tesselated coordinates */ float m1[2], m2[2]; /* gradient and normal */ - float pthick, dist; /* thickness at segment point, and length of segment */ - float sminorang; /* minor angle between strokes */ + float mt[2], sc[2]; /* gradient for thickness, point for end-cap */ + float pthick; /* thickness at segment point */ /* get x and y coordinates from points */ if (sflag & GP_STROKE_2DSPACE) { @@ -494,91 +498,123 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, /* calculate gradient and normal - 'angle'=(ny/nx) */ m1[1]= s1[1] - s0[1]; m1[0]= s1[0] - s0[0]; - dist = Vec2Lenf(s0, s1); - m2[1]= -(m1[0]) / dist; - m2[0]= m1[1] / dist; + Normalize2(m1); + m2[1]= -m1[0]; + m2[0]= m1[1]; - /* if the first segment, initialise the first segment using segment's normal */ - if (i == 0) { - pthick= (pt1->pressure * thickness); + /* always use pressure from first point here */ + pthick= (pt1->pressure * thickness); + + /* if the first segment, start of segment is segment's normal */ + if (i == 0) { + /* draw start cap first + * - make points slightly closer to center (about halfway across) + */ + mt[0]= m2[0] * pthick * 0.5; + mt[1]= m2[1] * pthick * 0.5; + sc[0]= s0[0] - (m1[0] * pthick * 0.75); + sc[1]= s0[1] - (m1[1] * pthick * 0.75); - // TODO: also draw/do a round end-cap first + t0[0]= sc[0] - mt[0]; + t0[1]= sc[1] - mt[1]; + t1[0]= sc[0] + mt[0]; + t1[1]= sc[1] + mt[1]; - p0[0]= s0[0] - (pthick * m2[0]); - p0[1]= s0[1] - (pthick * m2[1]); - p1[0]= s1[0] + (pthick * m2[0]); - p1[1]= s1[1] + (pthick * m2[1]); + glVertex2fv(t0); + glVertex2fv(t1); - Vec2Copyf(pm, m1); + /* calculate points for start of segment */ + mt[0]= m2[0] * pthick; + mt[1]= m2[1] * pthick; + + t0[0]= s0[0] - mt[0]; + t0[1]= s0[1] - mt[1]; + t1[0]= s0[0] + mt[0]; + t1[1]= s0[1] + mt[1]; + + /* draw this line twice (first to finish off start cap, then for stroke) */ + glVertex2fv(t1); + glVertex2fv(t0); + glVertex2fv(t0); + glVertex2fv(t1); } - - /* if the minor angle between the current segment and the previous one is less than 90 degrees */ - if (i) - sminorang= NormalizedVecAngle2_2D(pm, m1); - else - sminorang= 0.0f; - - if ((IS_EQ(sminorang, 0)==0) && (abs(sminorang) < M_PI_2) ) - { - float closep[2]; + /* if not the first segment, use bisector of angle between segments */ + else { + float mb[2]; /* bisector normal */ + float athick, dfac; /* actual thickness, difference between thicknesses */ - /* recalculate startpoint of segment, where the new start-line: - * - starts a new gl-quad-strip - * - uses the vert of old startpoint closer to our endpoint - * - distance between new startpoints = distance between old startpoints - * - new startpoints occur on same gradient as old segment does (has potential for some 'minor' overlap, but ok) + /* calculate gradient of bisector (as average of normals) */ + mb[0]= (pm[0] + m2[0]) / 2; + mb[1]= (pm[1] + m2[1]) / 2; + Normalize2(mb); + + /* calculate gradient to apply + * - as basis, use just pthick * bisector gradient + * - if cross-section not as thick as it should be, add extra padding to fix it */ + mt[0]= mb[0] * pthick; + mt[1]= mb[1] * pthick; + athick= Vec2Length(mt); + dfac= pthick - (athick * 2); + if ( ((athick * 2) < pthick) && (IS_EQ(athick, pthick)==0) ) + { + mt[0] += (mb[0] * dfac); + mt[1] += (mb[1] * dfac); + } - /* find the closer vertex, and distance between startpoints */ - if (Vec2Lenf(p0, s1) > Vec2Lenf(p1, s1)) - Vec2Copyf(closep, p1); - else - Vec2Copyf(closep, p0); - - /* determine which side this closer vertex should be on */ - pthick= (pt1->pressure * thickness * 2); - if ( ((closep[0] - s0[0]) > 0) || ((closep[1] - s0[1]) > 0) ) { - /* assumes this is the 'second' point, (i.e. the 'plus' one), so the other is subtracting */ - p0[0]= closep[0] - (pthick * pm[0]); - p0[1]= closep[1] - (pthick * pm[1]); - p1[0]= closep[0]; - p1[1]= closep[1]; - } - else if ( ((closep[0] - s0[0]) < 0) || ((closep[1] - s0[1]) < 0) ) { - /* assumes this is the 'first' point, (i.e. the 'minus' one), so the other is adding */ - p0[0]= closep[0]; - p0[1]= closep[1]; - p1[0]= closep[0] + (pthick * pm[0]); - p1[1]= closep[1] + (pthick * pm[1]); - } + /* calculate points for start of segment */ + t0[0]= s0[0] - mt[0]; + t0[1]= s0[1] - mt[1]; + t1[0]= s0[0] + mt[0]; + t1[1]= s0[1] + mt[1]; - /* reset gl-states! */ - glEnd(); - glBegin(GL_QUAD_STRIP); + /* draw this line twice (once for end of current segment, and once for start of next) */ + glVertex2fv(t1); + glVertex2fv(t0); + glVertex2fv(t0); + glVertex2fv(t1); } - /* do the end of this segment */ - pthick= (pt2->pressure * thickness); - t0[0] = s1[0] - (pthick * m2[0]); - t0[1] = s1[1] - (pthick * m2[1]); - t1[0] = s1[0] + (pthick * m2[0]); - t1[1] = s1[1] + (pthick * m2[1]); - - /* draw this segment */ - glVertex2f(p0[0], p0[1]); - glVertex2f(p1[0], p1[1]); - glVertex2f(t0[0], t0[1]); - glVertex2f(t1[0], t1[1]); - - // TODO: draw end cap if last segment + /* if last segment, also draw end of segment (defined as segment's normal) */ if (i == totpoints-2) { - + /* for once, we use second point's pressure (otherwise it won't be drawn) */ + pthick= (pt2->pressure * thickness); + + /* calculate points for end of segment */ + mt[0]= m2[0] * pthick; + mt[1]= m2[1] * pthick; + + t0[0]= s1[0] - mt[0]; + t0[1]= s1[1] - mt[1]; + t1[0]= s1[0] + mt[0]; + t1[1]= s1[1] + mt[1]; + + /* draw this line twice (once for end of stroke, and once for endcap)*/ + glVertex2fv(t1); + glVertex2fv(t0); + glVertex2fv(t0); + glVertex2fv(t1); + + + /* draw end cap as last step + * - make points slightly closer to center (about halfway across) + */ + mt[0]= m2[0] * pthick * 0.5; + mt[1]= m2[1] * pthick * 0.5; + sc[0]= s1[0] + (m1[0] * pthick * 0.75); + sc[1]= s1[1] + (m1[1] * pthick * 0.75); + + t0[0]= sc[0] - mt[0]; + t0[1]= sc[1] - mt[1]; + t1[0]= sc[0] + mt[0]; + t1[1]= sc[1] + mt[1]; + + glVertex2fv(t1); + glVertex2fv(t0); } - /* store current points for next segment to use */ - Vec2Copyf(p0, t0); - Vec2Copyf(p1, t1); - Vec2Copyf(pm, m1); + /* store stroke's 'natural' normal for next stroke to use */ + Vec2Copyf(pm, m2); } glEnd(); @@ -626,6 +662,10 @@ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, shor continue; if (!(dflag & GP_DRAWDATA_ONLYV2D) && (gps->flag & GP_STROKE_2DSPACE)) continue; + if ((dflag & GP_DRAWDATA_ONLYI2D) && !(gps->flag & GP_STROKE_2DIMAGE)) + continue; + if (!(dflag & GP_DRAWDATA_ONLYI2D) && (gps->flag & GP_STROKE_2DIMAGE)) + continue; if ((gps->points == 0) || (gps->totpoints < 1)) continue; @@ -796,6 +836,22 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* ----- Grease Pencil Sketches Drawing API ------ */ +/* draw grease-pencil sketches to specified 2d-view that uses ibuf corrections */ +void draw_gpencil_2dimage (ScrArea *sa, ImBuf *ibuf) +{ + bGPdata *gpd; + int dflag = 0; + + /* check that we have grease-pencil stuff to draw */ + if (ELEM(NULL, sa, ibuf)) return; + gpd= gpencil_data_getactive(sa); + if (gpd == NULL) return; + + /* draw it! */ + dflag = (GP_DRAWDATA_ONLYI2D|GP_DRAWDATA_NOSTATUS); + gp_draw_data(gpd, sa->winx, sa->winy, dflag); +} + /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly * Note: this gets called twice - first time with onlyv2d=1 to draw 'canvas' strokes, second time with onlyv2d=0 for screen-aligned strokes */ diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index eef21323a44..9b250fc3ec0 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -39,6 +39,9 @@ #include "BMF_Api.h" +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -312,11 +315,17 @@ bGPdata *gpencil_data_getactive (ScrArea *sa) { SpaceSeq *sseq= sa->spacedata.first; - /* only applicable for "Image Preview" mode */ + /* only applicable for image modes */ if (sseq->mainb) return sseq->gpd; } break; + case SPACE_IMAGE: + { + SpaceImage *sima= sa->spacedata.first; + return sima->gpd; + } + break; } /* nothing found */ @@ -379,6 +388,17 @@ short gpencil_data_setactive (ScrArea *sa, bGPdata *gpd) } } break; + case SPACE_IMAGE: + { + SpaceImage *sima= sa->spacedata.first; + + if (sima->gpd) + free_gpencil_data(sima->gpd); + sima->gpd= gpd; + + return 1; + } + break; } /* failed to add */ @@ -589,7 +609,7 @@ void gpencil_layer_delactive (bGPdata *gpd) } /* ************************************************** */ -/* GREASE-PENCIL EDITING MODE - Tools */ +/* GREASE-PENCIL EDITING - Tools */ /* --------- Data Deletion ---------- */ @@ -679,6 +699,7 @@ void gpencil_delete_menu (void) typedef struct tGPsdata { ScrArea *sa; /* area where painting originated */ View2D *v2d; /* needed for GP_STROKE_2DSPACE */ + ImBuf *ibuf; /* needed for GP_STROKE_2DIMAGE */ bGPdata *gpd; /* gp-datablock layer comes from */ bGPDlayer *gpl; /* layer we're working on */ @@ -800,6 +821,16 @@ static void gp_session_initpaint (tGPsdata *p) } } break; + case SPACE_IMAGE: + { + SpaceImage *sima= curarea->spacedata.first; + + /* set the current area */ + p->sa= curarea; + p->v2d= &sima->v2d; + //p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + } + break; /* unsupported views */ default: { @@ -869,6 +900,7 @@ static short gp_stroke_filtermval (tGPsdata *p, short mval[2], short pmval[2]) return 1; /* check if the distance since the last point is significant enough */ + // future optimisation: sqrt here may be too slow? else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX) return 1; @@ -884,7 +916,7 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) /* in 3d-space - pt->x/y/z are 3 side-by-side floats */ if (gpd->sbuffer_sflag & GP_STROKE_3DSPACE) { - short mx=mval[0], my=mval[1]; + const short mx=mval[0], my=mval[1]; float *fp= give_cursor(); float dvec[3]; @@ -904,6 +936,26 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) out[1]= y; } + /* 2d - on image 'canvas' (asume that p->v2d is set) */ + else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && + (p->v2d) && (p->ibuf) ) + { + ImBuf *ibuf= p->ibuf; + float x, y; + + /* convert to 'canvas' coordinates, then adjust for view */ + areamouseco_to_ipoco(p->v2d, mval, &x, &y); + + if (ibuf) { + out[0]= x*ibuf->x; + out[1]= y*ibuf->y; + } + else { + out[0]= x; + out[1]= y; + } + } + /* 2d - relative to screen (viewport area) */ else { out[0] = (float)(mval[0]) / (float)(p->sa->winx) * 1000; @@ -927,8 +979,6 @@ static short gp_stroke_addpoint (tGPsdata *p, short mval[2], float pressure) /* store settings */ pt->x= mval[0]; pt->y= mval[1]; - pt->xf= (float)mval[0]; - pt->yf= (float)mval[0]; pt->pressure= pressure; /* increment counters */ diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index cb2521de9a4..b1f86afa4ee 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -384,8 +384,12 @@ void BL_ConvertActuators(char* maggiename, else { /* but we need to convert the samplename into absolute pathname first */ - BLI_convertstringcode(soundact->sound->name, maggiename); - samplename = soundact->sound->name; + char fullpath[sizeof(soundact->sound->name)]; + + /* dont modify soundact->sound->name, only change a copy */ + BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); + BLI_convertstringcode(fullpath, maggiename); + samplename = fullpath; /* and now we can load it */ if (soundscene->LoadSample(samplename, NULL, 0) > -1) diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 472ae759d65..5d2126ca37a 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -30,7 +30,13 @@ #include "GL/glew.h" +// directory header for py function getBlendFileList #include +#ifndef WIN32 + #include +#else + #include "BLI_winstuff.h" +#endif #ifdef WIN32 #pragma warning (disable : 4786) @@ -112,9 +118,7 @@ static PyObject* gPyGetRandomFloat(PyObject*) return PyFloat_FromDouble(MT_random()); } -static PyObject* gPySetGravity(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetGravity(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); if (PyVecArgTo(args, vec)) @@ -138,9 +142,7 @@ file to make a full path name (doesn't change during the game, even if you load\ other .blend).\n\ The function also converts the directory separator to the local file system format."; -static PyObject* gPyExpandPath(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyExpandPath(PyObject*, PyObject* args) { char expanded[FILE_MAXDIR + FILE_MAXFILE]; char* filename; @@ -185,9 +187,7 @@ static PyObject* gPyGetSpectrum(PyObject*) -static PyObject* gPyStartDSP(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyStartDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); @@ -205,9 +205,7 @@ static PyObject* gPyStartDSP(PyObject*, -static PyObject* gPyStopDSP(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyStopDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); @@ -223,9 +221,7 @@ static PyObject* gPyStopDSP(PyObject*, return NULL; } -static PyObject* gPySetLogicTicRate(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) { float ticrate; if (PyArg_ParseTuple(args, "f", &ticrate)) @@ -242,9 +238,7 @@ static PyObject* gPyGetLogicTicRate(PyObject*) return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate()); } -static PyObject* gPySetPhysicsTicRate(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; if (PyArg_ParseTuple(args, "f", &ticrate)) @@ -257,9 +251,7 @@ static PyObject* gPySetPhysicsTicRate(PyObject*, return NULL; } -static PyObject* gPySetPhysicsDebug(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) { int debugMode; if (PyArg_ParseTuple(args, "i", &debugMode)) @@ -278,6 +270,44 @@ static PyObject* gPyGetPhysicsTicRate(PyObject*) return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep()); } +static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) +{ + char cpath[sizeof(G.sce)]; + char *searchpath = NULL; + PyObject* list; + + DIR *dp; + struct dirent *dirp; + + if (!PyArg_ParseTuple(args, "|s", &searchpath)) + return NULL; + + list = PyList_New(0); + + if (searchpath) { + BLI_strncpy(cpath, searchpath, FILE_MAXDIR + FILE_MAXFILE); + BLI_convertstringcode(cpath, G.sce); + } else { + /* Get the dir only */ + BLI_split_dirfile_basic(G.sce, cpath, NULL); + } + + if((dp = opendir(cpath)) == NULL) { + /* todo, show the errno, this shouldnt happen anyway if the blendfile is readable */ + fprintf(stderr, "Could not read directoty () failed, code %d (%s)\n", cpath, errno, strerror(errno)); + return list; + } + + while ((dirp = readdir(dp)) != NULL) { + if (BLI_testextensie(dirp->d_name, ".blend")) { + PyList_Append(list, PyString_FromString(dirp->d_name)); + } + } + + closedir(dp); + return list; +} + static STR_String gPyGetCurrentScene_doc = "getCurrentScene()\n" "Gets a reference to the current scene.\n"; @@ -377,14 +407,13 @@ static struct PyMethodDef game_methods[] = { {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, "Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, "Gets the physics tic rate"}, {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, "Sets the physics tic rate"}, + {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, "Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, "Prints GL Extension Info"}, {NULL, (PyCFunction) NULL, 0, NULL } }; -static PyObject* gPyGetWindowHeight(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { int height = (gp_Canvas ? gp_Canvas->GetHeight() : 0); @@ -394,9 +423,7 @@ static PyObject* gPyGetWindowHeight(PyObject*, -static PyObject* gPyGetWindowWidth(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) { @@ -411,9 +438,7 @@ static PyObject* gPyGetWindowWidth(PyObject*, // temporarility visibility thing, will be moved to rasterizer/renderer later bool gUseVisibilityTemp = false; -static PyObject* gPyEnableVisibility(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) { int visible; if (PyArg_ParseTuple(args,"i",&visible)) @@ -429,9 +454,7 @@ static PyObject* gPyEnableVisibility(PyObject*, -static PyObject* gPyShowMouse(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyShowMouse(PyObject*, PyObject* args) { int visible; if (PyArg_ParseTuple(args,"i",&visible)) @@ -455,9 +478,7 @@ static PyObject* gPyShowMouse(PyObject*, -static PyObject* gPySetMousePosition(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetMousePosition(PyObject*, PyObject* args) { int x,y; if (PyArg_ParseTuple(args,"ii",&x,&y)) @@ -472,9 +493,7 @@ static PyObject* gPySetMousePosition(PyObject*, Py_Return; } -static PyObject* gPySetEyeSeparation(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) { float sep; if (PyArg_ParseTuple(args, "f", &sep)) @@ -496,9 +515,7 @@ static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*) return NULL; } -static PyObject* gPySetFocalLength(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetFocalLength(PyObject*, PyObject* args) { float focus; if (PyArg_ParseTuple(args, "f", &focus)) @@ -518,9 +535,7 @@ static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) return NULL; } -static PyObject* gPySetBackgroundColor(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) { MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.); @@ -538,9 +553,7 @@ static PyObject* gPySetBackgroundColor(PyObject*, -static PyObject* gPySetMistColor(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetMistColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); @@ -558,9 +571,7 @@ static PyObject* gPySetMistColor(PyObject*, -static PyObject* gPySetMistStart(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetMistStart(PyObject*, PyObject* args) { float miststart; @@ -579,9 +590,7 @@ static PyObject* gPySetMistStart(PyObject*, -static PyObject* gPySetMistEnd(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetMistEnd(PyObject*, PyObject* args) { float mistend; @@ -599,9 +608,7 @@ static PyObject* gPySetMistEnd(PyObject*, } -static PyObject* gPySetAmbientColor(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); @@ -620,9 +627,7 @@ static PyObject* gPySetAmbientColor(PyObject*, -static PyObject* gPyMakeScreenshot(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) { char* filename; if (PyArg_ParseTuple(args,"s",&filename)) @@ -638,9 +643,7 @@ static PyObject* gPyMakeScreenshot(PyObject*, Py_Return; } -static PyObject* gPyEnableMotionBlur(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) { float motionblurvalue; if (PyArg_ParseTuple(args,"f",&motionblurvalue)) @@ -656,9 +659,7 @@ static PyObject* gPyEnableMotionBlur(PyObject*, Py_Return; } -static PyObject* gPyDisableMotionBlur(PyObject*, - PyObject* args, - PyObject*) +static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args) { if(gp_Rasterizer) { diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index b610fd1bbb0..6c733786caf 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -30,6 +30,10 @@ SET(INC . ../common ../../../../extern/bullet2/src + ../../../../intern/moto/include + ../../../kernel/gen_system + ../../../../intern/string + ../../Rasterizer ) BLENDERLIB(bf_bullet "${SRC}" "${INC}") diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index c911ce8ec60..b65bc0f3ce8 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -14,8 +14,7 @@ Documentation for the GameLogic Module. Examples:: # To get a controller: - import GameLogic - co = GameLogic.getCurrentController() + co = GameLogic.getCurrentController() # GameLogic is automatically imported # To get the game object associated with this controller: obj = co.getOwner() @@ -237,3 +236,13 @@ def expandPath(path): @return: The converted string @rtype: string """ + +def getBlendFileList(path = "//"): + """ + Returns a list of blend files in the same directory as the open blend file, or from using the option argument. + + @param path: Optional directory argument, will be expanded (like expandPath) into the full path. + @type path: string + @return: A list of filenames, with no directory prefix + @rtype: list + """ \ No newline at end of file From a1d611e9bd3379dd2c002cd5a895c788962a19a5 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 15 Sep 2008 14:20:31 +0000 Subject: [PATCH 02/10] svn merge -r 16231:16536 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- CMake/macros.cmake | 4 + CMakeLists.txt | 21 +- blenderplayer/CMakeLists.txt | 2 + config/darwin-config.py | 1 - config/linux2-config.py | 2 + .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 126 +- extern/bullet2/readme.txt | 5 + extern/bullet2/src/Bullet-C-Api.h | 140 +- .../BroadphaseCollision/btAxisSweep3.cpp | 638 +-- .../BroadphaseCollision/btAxisSweep3.h | 870 +++- .../btBroadphaseInterface.h | 28 +- .../BroadphaseCollision/btBroadphaseProxy.h | 57 +- .../btCollisionAlgorithm.cpp | 2 +- .../btCollisionAlgorithm.h | 11 +- .../BroadphaseCollision/btDbvt.cpp | 1289 +++++ .../BroadphaseCollision/btDbvt.h | 1111 +++++ .../BroadphaseCollision/btDbvtBroadphase.cpp | 344 ++ .../BroadphaseCollision/btDbvtBroadphase.h | 103 + .../BroadphaseCollision/btDispatcher.h | 22 +- .../btMultiSapBroadphase.cpp | 466 ++ .../btMultiSapBroadphase.h | 144 + .../btOverlappingPairCache.cpp | 535 +- .../btOverlappingPairCache.h | 351 +- .../btOverlappingPairCallback.h | 40 + .../BroadphaseCollision/btQuantizedBvh.cpp | 1025 ++++ .../BroadphaseCollision/btQuantizedBvh.h | 486 ++ .../btSimpleBroadphase.cpp | 234 +- .../BroadphaseCollision/btSimpleBroadphase.h | 94 +- .../src/BulletCollision/CMakeLists.txt | 93 + .../SphereTriangleDetector.cpp | 15 +- .../SphereTriangleDetector.h | 6 +- .../btBoxBoxCollisionAlgorithm.cpp | 85 + .../btBoxBoxCollisionAlgorithm.h | 66 + .../CollisionDispatch/btBoxBoxDetector.cpp | 683 +++ .../CollisionDispatch/btBoxBoxDetector.h | 44 + .../btCollisionConfiguration.h | 47 + .../CollisionDispatch/btCollisionCreateFunc.h | 2 +- .../btCollisionDispatcher.cpp | 237 +- .../CollisionDispatch/btCollisionDispatcher.h | 62 +- .../CollisionDispatch/btCollisionObject.cpp | 12 +- .../CollisionDispatch/btCollisionObject.h | 89 +- .../CollisionDispatch/btCollisionWorld.cpp | 644 ++- .../CollisionDispatch/btCollisionWorld.h | 202 +- .../btCompoundCollisionAlgorithm.cpp | 217 +- .../btCompoundCollisionAlgorithm.h | 33 +- .../btConvexConcaveCollisionAlgorithm.cpp | 27 +- .../btConvexConcaveCollisionAlgorithm.h | 24 +- .../btConvexConvexAlgorithm.cpp | 20 +- .../btConvexConvexAlgorithm.h | 25 +- .../btConvexPlaneCollisionAlgorithm.cpp | 108 + .../btConvexPlaneCollisionAlgorithm.h | 71 + .../btDefaultCollisionConfiguration.cpp | 291 ++ .../btDefaultCollisionConfiguration.h | 115 + .../btEmptyCollisionAlgorithm.h | 10 +- .../CollisionDispatch/btManifoldResult.cpp | 30 +- .../CollisionDispatch/btManifoldResult.h | 29 +- .../btSimulationIslandManager.cpp | 129 +- .../btSimulationIslandManager.h | 14 +- .../btSphereBoxCollisionAlgorithm.cpp | 19 +- .../btSphereBoxCollisionAlgorithm.h | 23 +- .../btSphereSphereCollisionAlgorithm.cpp | 19 +- .../btSphereSphereCollisionAlgorithm.h | 18 +- .../btSphereTriangleCollisionAlgorithm.cpp | 18 +- .../btSphereTriangleCollisionAlgorithm.h | 18 +- .../CollisionDispatch/btUnionFind.cpp | 4 +- .../CollisionDispatch/btUnionFind.h | 6 +- .../CollisionShapes/btBoxShape.cpp | 23 +- .../CollisionShapes/btBoxShape.h | 104 +- .../btBvhTriangleMeshShape.cpp | 223 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 40 +- .../CollisionShapes/btCapsuleShape.cpp | 36 +- .../CollisionShapes/btCapsuleShape.h | 78 +- .../CollisionShapes/btCollisionShape.cpp | 9 +- .../CollisionShapes/btCollisionShape.h | 45 +- .../CollisionShapes/btCompoundShape.cpp | 169 +- .../CollisionShapes/btCompoundShape.h | 93 +- .../CollisionShapes/btConcaveShape.h | 6 +- .../CollisionShapes/btConeShape.h | 12 +- .../CollisionShapes/btConvexHullShape.h | 20 +- .../CollisionShapes/btConvexInternalShape.cpp | 78 + .../CollisionShapes/btConvexInternalShape.h | 98 + .../CollisionShapes/btConvexShape.cpp | 59 - .../CollisionShapes/btConvexShape.h | 93 +- .../btConvexTriangleMeshShape.cpp | 115 +- .../btConvexTriangleMeshShape.h | 24 +- .../CollisionShapes/btCylinderShape.cpp | 14 +- .../CollisionShapes/btCylinderShape.h | 20 +- .../CollisionShapes/btEmptyShape.cpp | 2 +- .../CollisionShapes/btEmptyShape.h | 14 +- .../btHeightfieldTerrainShape.cpp | 115 +- .../btHeightfieldTerrainShape.h | 17 +- .../CollisionShapes/btMaterial.h | 34 + .../CollisionShapes/btMinkowskiSumShape.cpp | 6 +- .../CollisionShapes/btMinkowskiSumShape.h | 12 +- .../CollisionShapes/btMultiSphereShape.cpp | 4 +- .../CollisionShapes/btMultiSphereShape.h | 13 +- .../btMultimaterialTriangleMeshShape.cpp | 45 + .../btMultimaterialTriangleMeshShape.h | 124 + .../CollisionShapes/btOptimizedBvh.cpp | 657 +-- .../CollisionShapes/btOptimizedBvh.h | 299 +- .../btPolyhedralConvexShape.cpp | 42 +- .../CollisionShapes/btPolyhedralConvexShape.h | 38 +- .../btScaledBvhTriangleMeshShape.cpp | 103 + .../btScaledBvhTriangleMeshShape.h | 57 + .../CollisionShapes/btShapeHull.cpp | 164 + .../CollisionShapes/btShapeHull.h | 56 + .../CollisionShapes/btSphereShape.cpp | 2 +- .../CollisionShapes/btSphereShape.h | 20 +- .../CollisionShapes/btStaticPlaneShape.cpp | 5 +- .../CollisionShapes/btStaticPlaneShape.h | 16 +- .../btStridingMeshInterface.cpp | 6 +- .../CollisionShapes/btStridingMeshInterface.h | 12 +- .../CollisionShapes/btTetrahedronShape.h | 6 +- .../CollisionShapes/btTriangleBuffer.cpp | 9 +- .../CollisionShapes/btTriangleBuffer.h | 10 +- .../CollisionShapes/btTriangleCallback.h | 4 +- .../btTriangleIndexVertexArray.cpp | 45 +- .../btTriangleIndexVertexArray.h | 40 +- .../btTriangleIndexVertexMaterialArray.cpp | 86 + .../btTriangleIndexVertexMaterialArray.h | 84 + .../CollisionShapes/btTriangleMesh.cpp | 117 +- .../CollisionShapes/btTriangleMesh.h | 60 +- .../CollisionShapes/btTriangleMeshShape.cpp | 19 +- .../CollisionShapes/btTriangleMeshShape.h | 27 +- .../CollisionShapes/btTriangleShape.h | 18 +- .../CollisionShapes/btUniformScalingShape.cpp | 114 + .../CollisionShapes/btUniformScalingShape.h | 88 + .../btContinuousConvexCollision.cpp | 41 +- .../btContinuousConvexCollision.h | 6 +- .../NarrowPhaseCollision/btConvexCast.h | 18 +- .../btConvexPenetrationDepthSolver.h | 4 +- .../btDiscreteCollisionDetectorInterface.h | 6 +- .../NarrowPhaseCollision/btGjkConvexCast.cpp | 166 +- .../NarrowPhaseCollision/btGjkConvexCast.h | 10 +- .../NarrowPhaseCollision/btGjkEpa.cpp | 10 +- .../NarrowPhaseCollision/btGjkEpa.h | 8 +- .../NarrowPhaseCollision/btGjkEpa2.cpp | 943 ++++ .../NarrowPhaseCollision/btGjkEpa2.h | 71 + .../btGjkEpaPenetrationDepthSolver.cpp | 13 +- .../btGjkEpaPenetrationDepthSolver.h | 2 +- .../btGjkPairDetector.cpp | 11 +- .../NarrowPhaseCollision/btGjkPairDetector.h | 12 +- .../NarrowPhaseCollision/btManifoldPoint.h | 26 +- .../btMinkowskiPenetrationDepthSolver.cpp | 7 +- .../btMinkowskiPenetrationDepthSolver.h | 2 +- .../btPersistentManifold.cpp | 38 +- .../btPersistentManifold.h | 62 +- .../btRaycastCallback.cpp | 66 +- .../NarrowPhaseCollision/btRaycastCallback.h | 24 +- .../btSimplexSolverInterface.h | 4 +- .../btSubSimplexConvexCast.cpp | 82 +- .../btVoronoiSimplexSolver.cpp | 2 +- .../bullet2/src/BulletDynamics/CMakeLists.txt | 20 +- .../btConeTwistConstraint.cpp | 48 +- .../ConstraintSolver/btConeTwistConstraint.h | 3 + .../ConstraintSolver/btConstraintSolver.h | 13 +- .../ConstraintSolver/btContactConstraint.cpp | 32 +- .../ConstraintSolver/btContactConstraint.h | 4 +- .../ConstraintSolver/btContactSolverInfo.h | 56 +- .../btGeneric6DofConstraint.cpp | 821 ++-- .../btGeneric6DofConstraint.h | 463 +- .../ConstraintSolver/btHingeConstraint.cpp | 270 +- .../ConstraintSolver/btHingeConstraint.h | 97 +- .../ConstraintSolver/btJacobianEntry.h | 4 +- .../btPoint2PointConstraint.cpp | 15 +- .../btPoint2PointConstraint.h | 18 +- .../btSequentialImpulseConstraintSolver.cpp | 824 ++-- .../btSequentialImpulseConstraintSolver.h | 48 +- .../ConstraintSolver/btSliderConstraint.cpp | 415 ++ .../ConstraintSolver/btSliderConstraint.h | 218 + .../btSolve2LinearConstraint.h | 4 +- .../ConstraintSolver/btSolverBody.h | 64 +- .../ConstraintSolver/btSolverConstraint.h | 21 +- .../ConstraintSolver/btTypedConstraint.cpp | 15 +- .../ConstraintSolver/btTypedConstraint.h | 38 +- .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 294 +- .../Dynamics/btContinuousDynamicsWorld.cpp | 193 + .../Dynamics/btContinuousDynamicsWorld.h | 46 + .../Dynamics/btDiscreteDynamicsWorld.cpp | 535 +- .../Dynamics/btDiscreteDynamicsWorld.h | 44 +- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 84 +- .../BulletDynamics/Dynamics/btRigidBody.cpp | 222 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 189 +- .../Dynamics/btSimpleDynamicsWorld.cpp | 52 +- .../Dynamics/btSimpleDynamicsWorld.h | 32 +- .../Vehicle/btRaycastVehicle.cpp | 72 +- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 14 +- .../Vehicle/btVehicleRaycaster.h | 2 +- .../src/BulletDynamics/Vehicle/btWheelInfo.h | 4 +- .../bullet2/src/BulletSoftBody/CMakeLists.txt | 21 + .../bullet2/src/BulletSoftBody/btSoftBody.cpp | 2590 ++++++++++ .../bullet2/src/BulletSoftBody/btSoftBody.h | 810 ++++ .../btSoftBodyConcaveCollisionAlgorithm.cpp | 410 ++ .../btSoftBodyConcaveCollisionAlgorithm.h | 118 + .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 653 +++ .../src/BulletSoftBody/btSoftBodyHelpers.h | 107 + .../src/BulletSoftBody/btSoftBodyInternals.h | 896 ++++ ...oftBodyRigidBodyCollisionConfiguration.cpp | 108 + ...tSoftBodyRigidBodyCollisionConfiguration.h | 48 + .../btSoftRigidCollisionAlgorithm.cpp | 79 + .../btSoftRigidCollisionAlgorithm.h | 75 + .../btSoftRigidDynamicsWorld.cpp | 126 + .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 73 + .../btSoftSoftCollisionAlgorithm.cpp | 46 + .../btSoftSoftCollisionAlgorithm.h | 69 + .../bullet2/src/BulletSoftBody/btSparseSDF.h | 306 ++ extern/bullet2/src/LinearMath/CMakeLists.txt | 29 +- extern/bullet2/src/LinearMath/btAabbUtil2.h | 83 +- .../src/LinearMath/btAlignedAllocator.cpp | 185 +- .../src/LinearMath/btAlignedAllocator.h | 28 +- .../src/LinearMath/btAlignedObjectArray.h | 69 +- extern/bullet2/src/LinearMath/btConvexHull.h | 242 + .../src/LinearMath/btDefaultMotionState.h | 2 +- .../bullet2/src/LinearMath/btGeometryUtil.cpp | 9 +- .../bullet2/src/LinearMath/btGeometryUtil.h | 1 + extern/bullet2/src/LinearMath/btIDebugDraw.h | 16 + extern/bullet2/src/LinearMath/btMatrix3x3.h | 96 +- extern/bullet2/src/LinearMath/btMinMax.h | 12 +- extern/bullet2/src/LinearMath/btMotionState.h | 2 +- .../bullet2/src/LinearMath/btPoolAllocator.h | 97 + extern/bullet2/src/LinearMath/btQuadWord.h | 71 +- extern/bullet2/src/LinearMath/btQuaternion.h | 10 +- extern/bullet2/src/LinearMath/btQuickprof.cpp | 302 +- extern/bullet2/src/LinearMath/btQuickprof.h | 822 +--- extern/bullet2/src/LinearMath/btScalar.h | 268 +- extern/bullet2/src/LinearMath/btStackAlloc.h | 19 +- extern/bullet2/src/LinearMath/btTransform.h | 19 +- .../bullet2/src/LinearMath/btTransformUtil.h | 12 +- extern/bullet2/src/LinearMath/btVector3.h | 51 + extern/bullet2/src/SConscript | 73 +- extern/bullet2/src/btBulletCollisionCommon.h | 11 +- extern/bullet2/src/btBulletDynamicsCommon.h | 6 +- extern/glew/SConscript | 2 +- extern/glew/include/GL/glew.h | 7 +- extern/glew/src/glew.c | 2 + intern/SoundSystem/SoundDefines.h | 2 +- .../SoundSystem/openal/SND_OpenALDevice.cpp | 4 + intern/ghost/GHOST_ISystem.h | 4 +- intern/ghost/GHOST_Types.h | 10 + intern/ghost/intern/GHOST_SystemCarbon.cpp | 3 +- intern/ghost/intern/GHOST_SystemCarbon.h | 4 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 8 +- intern/ghost/intern/GHOST_SystemWin32.h | 3 +- intern/ghost/intern/GHOST_SystemX11.cpp | 13 +- intern/ghost/intern/GHOST_SystemX11.h | 6 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 8 +- intern/ghost/intern/GHOST_WindowX11.cpp | 67 +- intern/ghost/intern/GHOST_WindowX11.h | 2 + intern/guardedalloc/MEM_guardedalloc.h | 10 +- intern/guardedalloc/intern/mallocn.c | 21 +- intern/iksolver/CMakeLists.txt | 2 +- intern/iksolver/SConscript | 3 +- intern/memutil/MEM_Allocator.h | 1 + intern/memutil/MEM_CacheLimiter.h | 12 +- .../memutil/intern/MEM_CacheLimiterC-Api.cpp | 8 +- intern/moto/include/GEN_Map.h | 13 + intern/moto/include/MT_Matrix4x4.h | 1 + intern/moto/include/MT_Matrix4x4.inl | 14 +- intern/opennl/superlu/BLO_sys_types.h | 2 + .../blender/BPY_python/BPY_python.vcproj | 8 +- projectfiles_vc7/blender/blender.sln | 22 + projectfiles_vc7/blender/blender.vcproj | 10 +- .../blender/blenkernel/BKE_blenkernel.vcproj | 20 +- projectfiles_vc7/blender/gpu/BL_gpu.vcproj | 372 ++ projectfiles_vc7/blender/nodes/nodes.vcproj | 8 +- .../blender/radiosity/BRA_radiosity.vcproj | 4 +- projectfiles_vc7/blender/src/BL_src.vcproj | 10 +- .../blenderhook/KX_blenderhook.vcproj | 4 +- .../gameengine/converter/KX_converter.vcproj | 12 +- .../expression/EXP_expressions.vcproj | 12 +- .../gameengine/gamelogic/SCA_GameLogic.vcproj | 12 +- .../gameplayer/ghost/GP_ghost.vcproj | 4 +- .../gameengine/ketsji/KX_ketsji.vcproj | 18 +- .../PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj | 10 +- .../RAS_openglrasterizer.vcproj | 12 +- release/datafiles/blenderbuttons | Bin 69599 -> 68242 bytes release/scripts/mesh_cleanup.py | 32 +- release/scripts/object_find.py | 26 +- release/scripts/sysinfo.py | 2 + source/Makefile | 9 +- source/blender/CMakeLists.txt | 2 +- source/blender/Makefile | 2 +- source/blender/SConscript | 1 + source/blender/blenkernel/BKE_DerivedMesh.h | 49 +- source/blender/blenkernel/BKE_action.h | 2 +- .../blender/blenkernel/BKE_bad_level_calls.h | 4 - source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_colortools.h | 1 + source/blender/blenkernel/BKE_global.h | 9 +- source/blender/blenkernel/BKE_mesh.h | 1 - source/blender/blenkernel/BKE_node.h | 8 + source/blender/blenkernel/BKE_particle.h | 1 + source/blender/blenkernel/BKE_suggestions.h | 93 + source/blender/blenkernel/BKE_text.h | 29 +- source/blender/blenkernel/BKE_texture.h | 1 + source/blender/blenkernel/BKE_utildefines.h | 2 + source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/SConscript | 1 + .../blenkernel/bad_level_call_stubs/stubs.c | 32 +- .../blender/blenkernel/intern/DerivedMesh.c | 407 +- source/blender/blenkernel/intern/Makefile | 4 + source/blender/blenkernel/intern/action.c | 4 +- source/blender/blenkernel/intern/anim.c | 21 +- source/blender/blenkernel/intern/armature.c | 21 +- source/blender/blenkernel/intern/blender.c | 36 +- .../blender/blenkernel/intern/cdderivedmesh.c | 138 +- source/blender/blenkernel/intern/colortools.c | 21 + source/blender/blenkernel/intern/constraint.c | 108 +- source/blender/blenkernel/intern/depsgraph.c | 15 +- source/blender/blenkernel/intern/effect.c | 15 +- source/blender/blenkernel/intern/exotic.c | 14 +- source/blender/blenkernel/intern/image.c | 11 +- source/blender/blenkernel/intern/ipo.c | 27 +- source/blender/blenkernel/intern/material.c | 7 + source/blender/blenkernel/intern/mesh.c | 39 - source/blender/blenkernel/intern/modifier.c | 14 +- source/blender/blenkernel/intern/node.c | 114 + source/blender/blenkernel/intern/object.c | 15 +- source/blender/blenkernel/intern/particle.c | 33 +- .../blenkernel/intern/particle_system.c | 635 ++- source/blender/blenkernel/intern/shrinkwrap.c | 14 +- source/blender/blenkernel/intern/softbody.c | 76 +- .../blender/blenkernel/intern/subsurf_ccg.c | 179 +- .../blender/blenkernel/intern/suggestions.c | 254 + source/blender/blenkernel/intern/text.c | 564 ++- source/blender/blenkernel/intern/texture.c | 12 + source/blender/blenlib/BLI_arithb.h | 2 + source/blender/blenlib/BLI_blenlib.h | 2 +- source/blender/blenlib/BLI_kdopbvh.h | 3 +- source/blender/blenlib/SConscript | 2 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 36 +- source/blender/blenlib/intern/arithb.c | 30 + source/blender/blenlib/intern/util.c | 43 + source/blender/blenloader/BLO_readfile.h | 2 +- source/blender/blenloader/BLO_sys_types.h | 14 +- source/blender/blenloader/intern/readfile.c | 36 +- source/blender/blenloader/intern/writefile.c | 14 +- source/blender/gpu/CMakeLists.txt | 34 + source/blender/gpu/GPU_draw.h | 116 + source/blender/gpu/GPU_extensions.h | 144 + source/blender/gpu/GPU_material.h | 169 + source/blender/gpu/Makefile | 37 + source/blender/gpu/SConscript | 11 + source/blender/gpu/intern/Makefile | 53 + source/blender/gpu/intern/gpu_codegen.c | 1441 ++++++ source/blender/gpu/intern/gpu_codegen.h | 87 + source/blender/gpu/intern/gpu_draw.c | 1168 +++++ source/blender/gpu/intern/gpu_extensions.c | 987 ++++ source/blender/gpu/intern/gpu_material.c | 1496 ++++++ .../gpu/intern/gpu_shader_material.glsl | 1555 ++++++ .../gpu/intern/gpu_shader_material.glsl.c | 1032 ++++ .../blender/gpu/intern/gpu_shader_vertex.glsl | 12 + .../gpu/intern/gpu_shader_vertex.glsl.c | 13 + source/blender/imbuf/intern/bmp.c | 4 +- .../blender/imbuf/intern/dds/ColorBlock.cpp | 37 +- source/blender/imbuf/intern/dds/ColorBlock.h | 2 + .../imbuf/intern/dds/DirectDrawSurface.cpp | 307 +- .../imbuf/intern/dds/DirectDrawSurface.h | 4 + source/blender/imbuf/intern/dds/dds_api.cpp | 1 + source/blender/include/BDR_drawmesh.h | 43 +- source/blender/include/BDR_drawobject.h | 3 +- source/blender/include/BDR_gpencil.h | 3 + source/blender/include/BDR_imagepaint.h | 4 +- source/blender/include/BIF_drawseq.h | 2 + source/blender/include/BIF_drawtext.h | 6 +- source/blender/include/BIF_editaction.h | 2 +- source/blender/include/BIF_editarmature.h | 4 +- source/blender/include/BIF_editview.h | 1 + source/blender/include/BIF_gl.h | 15 +- source/blender/include/BIF_glutil.h | 1 + source/blender/include/BIF_keyframing.h | 99 + source/blender/include/BIF_keyval.h | 3 + source/blender/include/BIF_meshlaplacian.h | 2 +- source/blender/include/BIF_meshtools.h | 2 + source/blender/include/BIF_resources.h | 10 +- source/blender/include/BIF_space.h | 4 + source/blender/include/BSE_drawipo.h | 3 + source/blender/include/BSE_drawview.h | 6 +- source/blender/include/BSE_editipo.h | 13 +- source/blender/include/blendef.h | 8 + source/blender/include/transform.h | 2 +- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/makesdna/DNA_actuator_types.h | 14 +- source/blender/makesdna/DNA_brush_types.h | 4 +- source/blender/makesdna/DNA_gpencil_types.h | 2 +- source/blender/makesdna/DNA_group_types.h | 2 +- source/blender/makesdna/DNA_image_types.h | 4 +- source/blender/makesdna/DNA_ipo_types.h | 28 +- source/blender/makesdna/DNA_lamp_types.h | 16 +- source/blender/makesdna/DNA_material_types.h | 11 +- source/blender/makesdna/DNA_meshdata_types.h | 1 + source/blender/makesdna/DNA_object_types.h | 8 +- source/blender/makesdna/DNA_particle_types.h | 1 + source/blender/makesdna/DNA_scene_types.h | 3 +- source/blender/makesdna/DNA_sensor_types.h | 9 +- source/blender/makesdna/DNA_space_types.h | 14 +- source/blender/makesdna/DNA_text_types.h | 25 +- source/blender/makesdna/DNA_texture_types.h | 1 + source/blender/makesdna/DNA_userdef_types.h | 2 + source/blender/makesdna/DNA_view3d_types.h | 3 +- source/blender/makesdna/DNA_world_types.h | 4 +- source/blender/nodes/CMakeLists.txt | 2 +- source/blender/nodes/SConscript | 1 + .../nodes/intern/CMP_nodes/CMP_tonemap.c | 9 +- .../blender/nodes/intern/CMP_nodes/Makefile | 1 + source/blender/nodes/intern/Makefile | 2 + .../blender/nodes/intern/SHD_nodes/Makefile | 2 + .../nodes/intern/SHD_nodes/SHD_camera.c | 10 +- .../nodes/intern/SHD_nodes/SHD_curves.c | 24 +- .../blender/nodes/intern/SHD_nodes/SHD_geom.c | 16 +- .../nodes/intern/SHD_nodes/SHD_hueSatVal.c | 9 +- .../nodes/intern/SHD_nodes/SHD_invert.c | 8 +- .../nodes/intern/SHD_nodes/SHD_mapping.c | 17 +- .../nodes/intern/SHD_nodes/SHD_material.c | 79 +- .../blender/nodes/intern/SHD_nodes/SHD_math.c | 43 +- .../nodes/intern/SHD_nodes/SHD_mixRgb.c | 14 +- .../nodes/intern/SHD_nodes/SHD_normal.c | 11 +- .../nodes/intern/SHD_nodes/SHD_output.c | 16 +- .../blender/nodes/intern/SHD_nodes/SHD_rgb.c | 11 +- .../nodes/intern/SHD_nodes/SHD_sepcombRGB.c | 16 +- .../nodes/intern/SHD_nodes/SHD_squeeze.c | 8 +- .../nodes/intern/SHD_nodes/SHD_texture.c | 17 +- .../nodes/intern/SHD_nodes/SHD_valToRgb.c | 20 +- .../nodes/intern/SHD_nodes/SHD_value.c | 9 +- .../nodes/intern/SHD_nodes/SHD_vectMath.c | 31 +- source/blender/nodes/intern/SHD_util.h | 2 + source/blender/python/BPY_extern.h | 5 +- source/blender/python/BPY_interface.c | 138 +- source/blender/python/BPY_menus.c | 40 +- source/blender/python/BPY_menus.h | 2 + source/blender/python/CMakeLists.txt | 6 +- source/blender/python/SConscript | 4 + source/blender/python/api2_2x/BGL.h | 9 +- source/blender/python/api2_2x/Blender.c | 22 +- source/blender/python/api2_2x/Camera.c | 1 + source/blender/python/api2_2x/Constraint.c | 3 +- source/blender/python/api2_2x/Draw.c | 110 +- source/blender/python/api2_2x/Group.c | 31 + source/blender/python/api2_2x/Image.c | 4 +- source/blender/python/api2_2x/Ipo.c | 1 + source/blender/python/api2_2x/Ipocurve.c | 1 + source/blender/python/api2_2x/Lamp.c | 122 +- source/blender/python/api2_2x/MTex.c | 347 +- source/blender/python/api2_2x/MTex.h | 8 +- source/blender/python/api2_2x/Makefile | 6 + source/blender/python/api2_2x/Material.c | 296 +- source/blender/python/api2_2x/Mathutils.c | 2 +- source/blender/python/api2_2x/Mathutils.h | 2 +- source/blender/python/api2_2x/Mesh.c | 5 +- source/blender/python/api2_2x/Object.c | 3 +- source/blender/python/api2_2x/Particle.c | 14 +- source/blender/python/api2_2x/Pose.c | 1 + source/blender/python/api2_2x/Text.c | 409 +- source/blender/python/api2_2x/Text.h | 2 + source/blender/python/api2_2x/Texture.c | 7 + source/blender/python/api2_2x/Window.c | 13 +- source/blender/python/api2_2x/World.c | 103 + source/blender/python/api2_2x/bpy_data.c | 15 +- source/blender/python/api2_2x/doc/Draw.py | 8 +- source/blender/python/api2_2x/doc/Group.py | 2 + source/blender/python/api2_2x/doc/Lamp.py | 2 + source/blender/python/api2_2x/doc/Material.py | 62 +- source/blender/python/api2_2x/doc/Mesh.py | 3 +- source/blender/python/api2_2x/doc/Text.py | 103 +- source/blender/python/api2_2x/doc/Texture.py | 151 +- source/blender/python/api2_2x/doc/World.py | 2 + source/blender/python/api2_2x/gen_utils.h | 1 + source/blender/python/api2_2x/sceneSequence.c | 115 +- source/blender/radiosity/CMakeLists.txt | 2 +- source/blender/radiosity/SConscript | 2 +- .../blender/radiosity/intern/source/Makefile | 1 + .../readblenfile/intern/BLO_readblenfile.c | 2 +- .../render/intern/include/render_types.h | 3 +- .../render/intern/source/convertblender.c | 20 +- .../render/intern/source/imagetexture.c | 8 +- .../blender/render/intern/source/pipeline.c | 27 +- .../blender/render/intern/source/rayshade.c | 5 +- .../blender/render/intern/source/rendercore.c | 30 +- .../render/intern/source/renderdatabase.c | 14 +- source/blender/render/intern/source/shadbuf.c | 4 +- .../render/intern/source/shadeoutput.c | 16 +- source/blender/render/intern/source/zbuf.c | 92 +- source/blender/src/CMakeLists.txt | 2 +- source/blender/src/Makefile | 1 + source/blender/src/SConscript | 3 +- source/blender/src/blenderbuttons.c | 4310 ++++++++--------- source/blender/src/buttons_editing.c | 25 +- source/blender/src/buttons_logic.c | 397 +- source/blender/src/buttons_object.c | 47 +- source/blender/src/buttons_scene.c | 8 +- source/blender/src/buttons_shading.c | 139 +- source/blender/src/drawaction.c | 13 + source/blender/src/drawarmature.c | 3 + source/blender/src/drawgpencil.c | 223 +- source/blender/src/drawimage.c | 56 +- source/blender/src/drawipo.c | 11 +- source/blender/src/drawmesh.c | 771 +-- source/blender/src/drawobject.c | 325 +- source/blender/src/drawseq.c | 17 +- source/blender/src/drawtext.c | 2783 ++++++++--- source/blender/src/drawview.c | 510 +- source/blender/src/editaction.c | 3 +- source/blender/src/editarmature.c | 103 + source/blender/src/editdeform.c | 2 +- source/blender/src/editface.c | 7 +- source/blender/src/editipo.c | 1475 +----- source/blender/src/editipo_lib.c | 10 +- source/blender/src/editipo_mods.c | 1 - source/blender/src/editkey.c | 5 +- source/blender/src/editlattice.c | 2 +- source/blender/src/editmesh.c | 4 + source/blender/src/editmesh_add.c | 152 +- source/blender/src/editmesh_loop.c | 6 +- source/blender/src/editmesh_mods.c | 17 +- source/blender/src/editmesh_tools.c | 399 +- source/blender/src/editmode_undo.c | 40 +- source/blender/src/editnode.c | 6 +- source/blender/src/editobject.c | 35 +- source/blender/src/editscreen.c | 7 +- source/blender/src/editsound.c | 15 + source/blender/src/editview.c | 5 +- source/blender/src/filesel.c | 22 +- source/blender/src/glutil.c | 79 +- source/blender/src/gpencil.c | 588 ++- source/blender/src/header_image.c | 11 +- source/blender/src/header_info.c | 115 +- source/blender/src/header_ipo.c | 2 +- source/blender/src/header_node.c | 6 +- source/blender/src/header_text.c | 215 +- source/blender/src/header_view3d.c | 48 +- source/blender/src/headerbuttons.c | 7 +- source/blender/src/imagepaint.c | 309 +- source/blender/src/keyframing.c | 1838 +++++++ source/blender/src/keyval.c | 195 + source/blender/src/meshlaplacian.c | 10 +- source/blender/src/meshtools.c | 5 +- source/blender/src/mywindow.c | 12 - source/blender/src/playanim.c | 20 +- source/blender/src/poselib.c | 2 +- source/blender/src/poseobject.c | 2 + source/blender/src/previewrender.c | 32 + source/blender/src/renderwin.c | 17 +- source/blender/src/resources.c | 2 + source/blender/src/sculptmode.c | 7 +- source/blender/src/sequence.c | 13 +- source/blender/src/space.c | 86 +- source/blender/src/toets.c | 9 +- source/blender/src/toolbox.c | 14 +- source/blender/src/transform_conversions.c | 138 +- source/blender/src/transform_generics.c | 47 +- source/blender/src/transform_numinput.c | 14 + source/blender/src/transform_orientations.c | 2 +- source/blender/src/usiblender.c | 42 +- source/blender/src/verse_image.c | 4 +- source/blender/src/view.c | 135 +- source/blender/yafray/intern/export_File.cpp | 2 +- .../blender/yafray/intern/export_Plugin.cpp | 2 +- source/creator/CMakeLists.txt | 7 +- source/creator/Makefile | 2 + source/creator/SConscript | 2 +- source/creator/creator.c | 44 +- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 41 +- .../gameengine/BlenderRoutines/CMakeLists.txt | 1 + .../BlenderRoutines/KX_BlenderGL.cpp | 75 - .../gameengine/BlenderRoutines/KX_BlenderGL.h | 3 - .../BlenderRoutines/KX_BlenderRenderTools.cpp | 280 +- .../BlenderRoutines/KX_BlenderRenderTools.h | 71 +- source/gameengine/BlenderRoutines/Makefile | 5 +- source/gameengine/BlenderRoutines/SConscript | 5 +- .../Converter/BL_ActionActuator.cpp | 1 + .../Converter/BL_ArmatureObject.cpp | 80 +- .../gameengine/Converter/BL_ArmatureObject.h | 9 +- .../Converter/BL_BlenderDataConversion.cpp | 203 +- .../Converter/BL_DeformableGameObject.cpp | 8 +- .../gameengine/Converter/BL_MeshDeformer.cpp | 89 +- source/gameengine/Converter/BL_MeshDeformer.h | 3 +- .../Converter/BL_ShapeActionActuator.cpp | 2 +- .../gameengine/Converter/BL_ShapeDeformer.cpp | 3 - .../gameengine/Converter/BL_ShapeDeformer.h | 11 - .../gameengine/Converter/BL_SkinDeformer.cpp | 47 +- source/gameengine/Converter/BL_SkinDeformer.h | 16 +- .../Converter/BL_SkinMeshObject.cpp | 74 +- .../gameengine/Converter/BL_SkinMeshObject.h | 45 +- source/gameengine/Converter/CMakeLists.txt | 1 + .../Converter/KX_BlenderSceneConverter.cpp | 72 +- .../Converter/KX_BlenderSceneConverter.h | 2 + .../Converter/KX_ConvertActuators.cpp | 132 +- .../Converter/KX_ConvertSensors.cpp | 22 +- source/gameengine/Converter/Makefile | 1 + source/gameengine/Converter/SConscript | 2 +- source/gameengine/Expressions/Makefile | 1 + .../gameengine/Expressions/PyObjectPlus.cpp | 4 +- source/gameengine/Expressions/PyObjectPlus.h | 39 + source/gameengine/Expressions/Value.cpp | 30 +- .../GameLogic/Joystick/SCA_Joystick.cpp | 203 +- .../GameLogic/Joystick/SCA_Joystick.h | 214 +- .../GameLogic/Joystick/SCA_JoystickDefines.h | 8 +- .../GameLogic/Joystick/SCA_JoystickEvents.cpp | 56 +- .../GameLogic/Joystick/SCA_JoystickPrivate.h | 4 - source/gameengine/GameLogic/Makefile | 1 + .../GameLogic/SCA_2DFilterActuator.cpp | 8 +- .../gameengine/GameLogic/SCA_IController.cpp | 2 + .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 1 + source/gameengine/GameLogic/SCA_ISensor.cpp | 48 +- source/gameengine/GameLogic/SCA_ISensor.h | 13 +- .../GameLogic/SCA_JoystickManager.cpp | 35 +- .../GameLogic/SCA_JoystickManager.h | 4 +- .../GameLogic/SCA_JoystickSensor.cpp | 162 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 43 +- .../GameLogic/SCA_KeyboardSensor.cpp | 2 +- .../gameengine/GameLogic/SCA_LogicManager.cpp | 31 +- .../gameengine/GameLogic/SCA_LogicManager.h | 2 + .../GameLogic/SCA_PythonController.cpp | 13 +- .../GameLogic/SCA_PythonController.h | 6 + source/gameengine/GamePlayer/CMakeLists.txt | 4 + .../GamePlayer/common/CMakeLists.txt | 2 +- .../GamePlayer/common/GPC_RenderTools.cpp | 546 +-- .../GamePlayer/common/GPC_RenderTools.h | 156 +- source/gameengine/GamePlayer/common/Makefile | 5 +- .../gameengine/GamePlayer/common/SConscript | 2 +- .../common/unix/GPU_PolygonMaterial.h | 4 +- .../GamePlayer/ghost/CMakeLists.txt | 1 + .../GamePlayer/ghost/GPG_Application.cpp | 113 +- .../GamePlayer/ghost/GPG_Application.h | 9 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 96 +- source/gameengine/GamePlayer/ghost/Makefile | 5 +- source/gameengine/GamePlayer/ghost/SConscript | 4 +- source/gameengine/Ketsji/BL_BlenderShader.cpp | 124 +- source/gameengine/Ketsji/BL_BlenderShader.h | 10 +- source/gameengine/Ketsji/BL_Material.h | 6 +- source/gameengine/Ketsji/BL_Shader.cpp | 12 +- source/gameengine/Ketsji/BL_Shader.h | 2 +- source/gameengine/Ketsji/CMakeLists.txt | 1 + .../KXNetwork/KX_NetworkMessageSensor.cpp | 68 +- .../KXNetwork/KX_NetworkMessageSensor.h | 10 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 126 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 3 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 2 + .../Ketsji/KX_ConstraintActuator.cpp | 50 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 5 +- .../Ketsji/KX_ConstraintWrapper.cpp | 1 + .../Ketsji/KX_ConvertPhysicsObject.h | 1 + .../Ketsji/KX_ConvertPhysicsObjects.cpp | 165 +- source/gameengine/Ketsji/KX_GameActuator.cpp | 66 + source/gameengine/Ketsji/KX_GameActuator.h | 2 + source/gameengine/Ketsji/KX_GameObject.cpp | 351 +- source/gameengine/Ketsji/KX_GameObject.h | 109 +- .../gameengine/Ketsji/KX_IPO_SGController.cpp | 2 +- source/gameengine/Ketsji/KX_ISceneConverter.h | 4 + source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 204 +- source/gameengine/Ketsji/KX_KetsjiEngine.h | 13 +- source/gameengine/Ketsji/KX_Light.cpp | 64 +- source/gameengine/Ketsji/KX_Light.h | 11 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 46 +- source/gameengine/Ketsji/KX_MeshProxy.h | 2 + .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 17 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 6 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 2 + .../Ketsji/KX_PhysicsObjectWrapper.cpp | 2 + .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 50 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 2 - .../Ketsji/KX_PyConstraintBinding.cpp | 2 + source/gameengine/Ketsji/KX_PythonInit.cpp | 658 ++- source/gameengine/Ketsji/KX_PythonInit.h | 6 +- source/gameengine/Ketsji/KX_RayCast.cpp | 85 +- source/gameengine/Ketsji/KX_RayCast.h | 60 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 58 +- source/gameengine/Ketsji/KX_RaySensor.h | 8 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 122 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 30 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 41 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 2 +- .../KX_SG_BoneParentNodeRelationship.cpp | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 33 +- source/gameengine/Ketsji/KX_Scene.h | 10 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 64 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 2 + .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 2 + source/gameengine/Ketsji/KX_VertexProxy.cpp | 14 +- .../Ketsji/KX_VisibilityActuator.cpp | 10 +- .../gameengine/Ketsji/KX_VisibilityActuator.h | 2 + source/gameengine/Ketsji/Makefile | 11 +- source/gameengine/Ketsji/SConscript | 5 +- .../Physics/BlOde/OdePhysicsEnvironment.cpp | 3 +- .../Physics/BlOde/OdePhysicsEnvironment.h | 3 +- .../Physics/Bullet/CcdPhysicsController.cpp | 89 +- .../Physics/Bullet/CcdPhysicsController.h | 29 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 208 +- .../Physics/Bullet/CcdPhysicsEnvironment.h | 7 +- source/gameengine/Physics/Bullet/Makefile | 5 + .../Physics/Dummy/DummyPhysicsEnvironment.cpp | 3 +- .../Physics/Dummy/DummyPhysicsEnvironment.h | 3 +- .../Physics/Sumo/SumoPhysicsEnvironment.cpp | 31 +- .../Physics/Sumo/SumoPhysicsEnvironment.h | 3 +- .../Physics/common/PHY_IPhysicsEnvironment.h | 47 +- source/gameengine/PyDoc/GameKeys.py | 9 + source/gameengine/PyDoc/GameLogic.py | 9 +- source/gameengine/PyDoc/KX_GameObject.py | 90 +- source/gameengine/PyDoc/KX_MeshProxy.py | 15 + source/gameengine/PyDoc/KX_ObjectActuator.py | 4 +- .../PyDoc/KX_SCA_AddObjectActuator.py | 17 + .../PyDoc/KX_SCA_ReplaceMeshActuator.py | 5 +- source/gameengine/PyDoc/KX_TrackToActuator.py | 2 +- source/gameengine/PyDoc/Rasterizer.py | 39 +- source/gameengine/PyDoc/SCA_DelaySensor.py | 2 +- source/gameengine/PyDoc/SCA_ISensor.py | 7 +- source/gameengine/Rasterizer/Makefile | 4 - .../Rasterizer/RAS_BucketManager.cpp | 264 +- .../gameengine/Rasterizer/RAS_BucketManager.h | 21 +- .../Rasterizer/RAS_FramingManager.h | 15 +- .../Rasterizer/RAS_IPolygonMaterial.cpp | 25 +- .../Rasterizer/RAS_IPolygonMaterial.h | 9 +- .../gameengine/Rasterizer/RAS_IRasterizer.h | 50 +- .../Rasterizer/RAS_IRenderTools.cpp | 24 +- .../gameengine/Rasterizer/RAS_IRenderTools.h | 39 +- .../Rasterizer/RAS_MaterialBucket.cpp | 604 ++- .../Rasterizer/RAS_MaterialBucket.h | 219 +- .../gameengine/Rasterizer/RAS_MeshObject.cpp | 993 ++-- source/gameengine/Rasterizer/RAS_MeshObject.h | 242 +- .../RAS_OpenGLRasterizer/CMakeLists.txt | 1 + .../Rasterizer/RAS_OpenGLRasterizer/Makefile | 5 +- .../RAS_ListRasterizer.cpp | 84 +- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 24 +- .../RAS_OpenGLRasterizer.cpp | 790 +-- .../RAS_OpenGLRasterizer.h | 49 +- .../RAS_VAOpenGLRasterizer.cpp | 234 +- .../RAS_VAOpenGLRasterizer.h | 18 +- .../RAS_OpenGLRasterizer/SConscript | 5 +- source/gameengine/Rasterizer/RAS_Polygon.cpp | 87 +- source/gameengine/Rasterizer/RAS_Polygon.h | 56 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 30 +- source/gameengine/Rasterizer/RAS_TexVert.h | 28 +- source/gameengine/Rasterizer/SConscript | 5 +- source/kernel/gen_system/GEN_Map.h | 13 + source/nan_definitions.mk | 11 +- tools/Blender.py | 13 +- tools/btools.py | 6 +- 737 files changed, 56049 insertions(+), 18144 deletions(-) create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletSoftBody/CMakeLists.txt create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBody.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBody.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSparseSDF.h create mode 100644 extern/bullet2/src/LinearMath/btConvexHull.h create mode 100644 extern/bullet2/src/LinearMath/btPoolAllocator.h create mode 100644 projectfiles_vc7/blender/gpu/BL_gpu.vcproj create mode 100644 source/blender/blenkernel/BKE_suggestions.h create mode 100644 source/blender/blenkernel/intern/suggestions.c create mode 100644 source/blender/gpu/CMakeLists.txt create mode 100644 source/blender/gpu/GPU_draw.h create mode 100644 source/blender/gpu/GPU_extensions.h create mode 100644 source/blender/gpu/GPU_material.h create mode 100644 source/blender/gpu/Makefile create mode 100644 source/blender/gpu/SConscript create mode 100644 source/blender/gpu/intern/Makefile create mode 100644 source/blender/gpu/intern/gpu_codegen.c create mode 100644 source/blender/gpu/intern/gpu_codegen.h create mode 100644 source/blender/gpu/intern/gpu_draw.c create mode 100644 source/blender/gpu/intern/gpu_extensions.c create mode 100644 source/blender/gpu/intern/gpu_material.c create mode 100644 source/blender/gpu/intern/gpu_shader_material.glsl create mode 100644 source/blender/gpu/intern/gpu_shader_material.glsl.c create mode 100644 source/blender/gpu/intern/gpu_shader_vertex.glsl create mode 100644 source/blender/gpu/intern/gpu_shader_vertex.glsl.c create mode 100644 source/blender/include/BIF_keyframing.h create mode 100644 source/blender/src/keyframing.c diff --git a/CMake/macros.cmake b/CMake/macros.cmake index 6b6837d25f0..95799a2c1fd 100644 --- a/CMake/macros.cmake +++ b/CMake/macros.cmake @@ -38,6 +38,10 @@ MACRO(BLENDERLIB ENDMACRO(BLENDERLIB) MACRO(SETUP_LIBDIRS) + # see "cmake --help-policy CMP0003" + if(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) + endif(COMMAND cmake_policy) LINK_DIRECTORIES(${PYTHON_LIBPATH} ${SDL_LIBPATH} ${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${ICONV_LIBPATH} ${OPENEXR_LIBPATH} ${QUICKTIME_LIBPATH} ${FFMPEG_LIBPATH}) IF(WITH_INTERNATIONAL) LINK_DIRECTORIES(${GETTEXT_LIBPATH}) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b86ca8f21e..4c1b863178f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) +OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Mozilla-Unix only)" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -248,7 +249,11 @@ IF(WIN32) SET(GETTEXT ${LIBDIR}/gettext) SET(GETTEXT_INC ${GETTEXT}/include) - SET(GETTEXT_LIB gnu_gettext) + IF(CMAKE_CL_64) + SET(GETTEXT_LIB gettextlib) + ELSE(CMAKE_CL_64) + SET(GETTEXT_LIB gnu_gettext) + ENDIF(CMAKE_CL_64) SET(GETTEXT_LIBPATH ${GETTEXT}/lib) SET(FREETYPE ${LIBDIR}/freetype) @@ -279,7 +284,12 @@ IF(WIN32) SET(FFMPEG_LIB avcodec-51 avformat-52 avdevice-52 avutil-49 swscale-0) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) + IF(CMAKE_CL_64) + SET(LLIBS kernel32 user32 vfw32 winmm ws2_32 ) + ELSE(CMAKE_CL_64) SET(LLIBS kernel32 user32 gdi32 comdlg32 advapi32 shell32 ole32 oleaut32 uuid ws2_32 vfw32 winmm) + ENDIF(CMAKE_CL_64) + IF(WITH_OPENAL) SET(LLIBS ${LLIBS} dxguid) ENDIF(WITH_OPENAL) @@ -317,7 +327,7 @@ IF(WIN32) SET(WINTAB_INC ${LIBDIR}/wintab/include) IF(CMAKE_CL_64) - SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib;MSVCRT.lib ") + SET(PLATFORM_LINKFLAGS "/MACHINE:X64 /NODEFAULTLIB:libc.lib;MSVCRT.lib ") ELSE(CMAKE_CL_64) SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib ") ENDIF(CMAKE_CL_64) @@ -447,6 +457,13 @@ SUBDIRS( # Blender Application SUBDIRS(source/creator) +#----------------------------------------------------------------------------- +# Blender WebPlugin +IF(WITH_WEBPLUGIN) + SET(MOZILLA_DIR "${CMAKE_SOURCE_DIR}/../gecko-sdk/" CACHE PATH "Gecko SDK path") + SET(WITH_PLAYER ON) +ENDIF(WITH_WEBPLUGIN) + #----------------------------------------------------------------------------- # Blender Player IF(WITH_PLAYER) diff --git a/blenderplayer/CMakeLists.txt b/blenderplayer/CMakeLists.txt index d90639562d2..9786b7e61b2 100644 --- a/blenderplayer/CMakeLists.txt +++ b/blenderplayer/CMakeLists.txt @@ -86,10 +86,12 @@ IF(UNIX) bf_oglrasterizer bf_expressions bf_scenegraph + bf_IK bf_moto bf_soundsystem bf_kernel bf_nodes + bf_gpu bf_imbuf bf_avi kx_network diff --git a/config/darwin-config.py b/config/darwin-config.py index 8fd6c3251ba..48455d2ce8c 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -143,7 +143,6 @@ BF_FTGL_LIB = 'extern_ftgl' WITH_BF_GAMEENGINE='true' WITH_BF_PLAYER='true' -WITH_BF_GLEXT= '1' WITH_BF_ODE = 'false' BF_ODE = LIBDIR + '/ode' diff --git a/config/linux2-config.py b/config/linux2-config.py index fe4325361a8..36cbac6df10 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -6,10 +6,12 @@ BF_VERSE_INCLUDE = "#extern/verse/dist" BF_PYTHON = '/usr' BF_PYTHON_VERSION = '2.5' +WITH_BF_STATICPYTHON = 'false' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] +BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a' WITH_BF_OPENAL = 'true' BF_OPENAL = '/usr' diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 6de2fd3a2bd..7a6b58b2ed7 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -394,12 +394,24 @@ ECHO Done + + + + + + + + @@ -410,6 +422,12 @@ ECHO Done + + + + @@ -482,18 +500,45 @@ ECHO Done + + + + + + + + + + + + + + + + + + @@ -534,6 +579,12 @@ ECHO Done + + + + @@ -589,6 +640,21 @@ ECHO Done + + + + + + + + + + @@ -628,6 +694,18 @@ ECHO Done + + + + + + + + @@ -731,6 +809,12 @@ ECHO Done + + + + @@ -761,12 +845,21 @@ ECHO Done + + + + + + @@ -785,6 +878,18 @@ ECHO Done + + + + + + + + @@ -827,6 +932,12 @@ ECHO Done + + + + @@ -842,6 +953,12 @@ ECHO Done + + + + + + @@ -886,6 +1006,9 @@ ECHO Done + + @@ -904,9 +1027,6 @@ ECHO Done - - diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt index 4d1a4c11706..02430cb5c0e 100644 --- a/extern/bullet2/readme.txt +++ b/extern/bullet2/readme.txt @@ -1,3 +1,8 @@ +*** +Apply bullet_compound_raycast.patch if not already applied in Bullet source +This patch is needed to return correct raycast results on compound shape. +/ben + *** These files in extern/bullet2 are NOT part of the Blender build yet *** diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index 078dcae63bb..8074aed3038 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -23,15 +23,153 @@ subject to the following restrictions: #ifndef BULLET_C_API_H #define BULLET_C_API_H +#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifdef BT_USE_DOUBLE_PRECISION +typedef double plReal; +#else +typedef float plReal; +#endif + +typedef plReal plVector3[3]; +typedef plReal plQuaternion[4]; + #ifdef __cplusplus extern "C" { #endif -double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); +/* Particular physics SDK */ + PL_DECLARE_HANDLE(plPhysicsSdkHandle); + +/* Dynamics world, belonging to some physics SDK */ + PL_DECLARE_HANDLE(plDynamicsWorldHandle); + +/* Rigid Body that can be part of a Dynamics World */ + PL_DECLARE_HANDLE(plRigidBodyHandle); + +/* Collision Shape/Geometry, property of a Rigid Body */ + PL_DECLARE_HANDLE(plCollisionShapeHandle); + +/* Constraint for Rigid Bodies */ + PL_DECLARE_HANDLE(plConstraintHandle); + +/* Triangle Mesh interface */ + PL_DECLARE_HANDLE(plMeshInterfaceHandle); + +/* Broadphase Scene/Proxy Handles */ + PL_DECLARE_HANDLE(plCollisionBroadphaseHandle); + PL_DECLARE_HANDLE(plBroadphaseProxyHandle); + PL_DECLARE_HANDLE(plCollisionWorldHandle); + +/* + Create and Delete a Physics SDK +*/ + + extern plPhysicsSdkHandle plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc. + extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk); + +/* Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */ + + typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2); + + extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback); + + extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp); + + extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + + extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle); + + extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + +/* todo: add pair cache support with queries like add/remove/find pair */ + + extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk); + +/* todo: add/remove objects */ + + +/* Dynamics World */ + + extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk); + + extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world); + + extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep); + + extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + +/* Rigid Body */ + + extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ); + + extern void plDeleteRigidBody(plRigidBodyHandle body); + + +/* Collision Shape definition */ + + extern plCollisionShapeHandle plNewSphereShape(plReal radius); + extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z); + extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCompoundShape(); + extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn); + + extern void plDeleteShape(plCollisionShapeHandle shape); + + /* Convex Meshes */ + extern plCollisionShapeHandle plNewConvexHullShape(); + extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z); +/* Concave static triangle meshes */ + extern plMeshInterfaceHandle plNewMeshInterface(); + extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); + extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling); + +/* SOLID has Response Callback/Table/Management */ +/* PhysX has Triggers, User Callbacks and filtering */ +/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */ + +/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */ +/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */ + + /* get world transform */ + extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + extern void plGetPosition(plRigidBodyHandle object,plVector3 position); + extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation); + + /* set world transform (position/orientation) */ + extern void plSetPosition(plRigidBodyHandle object, const plVector3 position); + extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation); + extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient); + + typedef struct plRayCastResult { + plRigidBodyHandle m_body; + plCollisionShapeHandle m_shape; + plVector3 m_positionWorld; + plVector3 m_normalWorld; + } plRayCastResult; + + extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res); + + /* Sweep API */ + + /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */ + + /* Continuous Collision Detection API */ + + // needed for source/blender/blenkernel/intern/collision.c + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); #ifdef __cplusplus } #endif + #endif //BULLET_C_API_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp index be4a11506df..d7eea33ea41 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -21,640 +21,18 @@ #include -#ifdef DEBUG_BROADPHASE -#include -void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache) { - int numEdges = m_pHandles[0].m_maxEdges[axis]; - printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); - - int i; - for (i=0;im_handle); - int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; - char beginOrEnd; - beginOrEnd=pEdge->IsMax()?'E':'B'; - printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); - } - - if (checkCardinality) - assert(numEdges == m_numHandles*2+1); -} -#endif //DEBUG_BROADPHASE - - -btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) -{ - (void)shapeType; - BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask); - - Handle* handle = getHandle(handleId); - - return handle; -} - -void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy) -{ - Handle* handle = static_cast(proxy); - removeHandle(handle->m_handleId); -} - -void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax) -{ - Handle* handle = static_cast(proxy); - updateHandle(handle->m_handleId,aabbMin,aabbMax); - -} - - - - - - -btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles) -:btOverlappingPairCache() -{ - m_invalidPair = 0; - //assert(bounds.HasVolume()); - // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES); - - // init bounds - m_worldAabbMin = worldAabbMin; - m_worldAabbMax = worldAabbMax; - - btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; - - BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL; - - m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; - - // allocate handles buffer and put all handles on free list - m_pHandles = new Handle[maxHandles]; - m_maxHandles = maxHandles; - m_numHandles = 0; - - // handle 0 is reserved as the null index, and is also used as the sentinel - m_firstFreeHandle = 1; - { - for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) - m_pHandles[i].SetNextFree(i + 1); - m_pHandles[maxHandles - 1].SetNextFree(0); - } - - { - // allocate edge buffers - for (int i = 0; i < 3; i++) - m_pEdges[i] = new Edge[maxHandles * 2]; - } - //removed overlap management - - // make boundary sentinels - - m_pHandles[0].m_clientObject = 0; - - for (int axis = 0; axis < 3; axis++) - { - m_pHandles[0].m_minEdges[axis] = 0; - m_pHandles[0].m_maxEdges[axis] = 1; - - m_pEdges[axis][0].m_pos = 0; - m_pEdges[axis][0].m_handle = 0; - m_pEdges[axis][1].m_pos = BP_HANDLE_SENTINEL; - m_pEdges[axis][1].m_handle = 0; -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - - } + btAssert(maxHandles > 1 && maxHandles < 32767); } -btAxisSweep3::~btAxisSweep3() + +bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache ) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache) { - - for (int i = 2; i >= 0; i--) - delete[] m_pEdges[i]; - delete[] m_pHandles; -} - -void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const -{ - btPoint3 clampedPoint(point); - - - - clampedPoint.setMax(m_worldAabbMin); - clampedPoint.setMin(m_worldAabbMax); - - btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; - out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & BP_HANDLE_MASK) | isMax); - out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax); - out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax); - -} - - - -BP_FP_INT_TYPE btAxisSweep3::allocHandle() -{ - assert(m_firstFreeHandle); - - BP_FP_INT_TYPE handle = m_firstFreeHandle; - m_firstFreeHandle = getHandle(handle)->GetNextFree(); - m_numHandles++; - - return handle; -} - -void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle) -{ - assert(handle > 0 && handle < m_maxHandles); - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numHandles--; -} - - - -BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask) -{ - // quantize the bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // allocate a handle - BP_FP_INT_TYPE handle = allocHandle(); - assert(handle!= 0xcdcd); - - Handle* pHandle = getHandle(handle); - - pHandle->m_handleId = handle; - //pHandle->m_pOverlaps = 0; - pHandle->m_clientObject = pOwner; - pHandle->m_collisionFilterGroup = collisionFilterGroup; - pHandle->m_collisionFilterMask = collisionFilterMask; - - // compute current limit of edge arrays - BP_FP_INT_TYPE limit = m_numHandles * 2; - - - // insert new edges just inside the max boundary edge - for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) - { - - m_pHandles[0].m_maxEdges[axis] += 2; - - m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; - - m_pEdges[axis][limit - 1].m_pos = min[axis]; - m_pEdges[axis][limit - 1].m_handle = handle; - - m_pEdges[axis][limit].m_pos = max[axis]; - m_pEdges[axis][limit].m_handle = handle; - - pHandle->m_minEdges[axis] = limit - 1; - pHandle->m_maxEdges[axis] = limit; - } - - // now sort the new edges to their correct position - sortMinDown(0, pHandle->m_minEdges[0], false); - sortMaxDown(0, pHandle->m_maxEdges[0], false); - sortMinDown(1, pHandle->m_minEdges[1], false); - sortMaxDown(1, pHandle->m_maxEdges[1], false); - sortMinDown(2, pHandle->m_minEdges[2], true); - sortMaxDown(2, pHandle->m_maxEdges[2], true); - - - return handle; -} - - -void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle) -{ - - Handle* pHandle = getHandle(handle); - - //explicitly remove the pairs containing the proxy - //we could do it also in the sortMinUp (passing true) - //todo: compare performance - removeOverlappingPairsContainingProxy(pHandle); - - - // compute current limit of edge arrays - int limit = m_numHandles * 2; - - int axis; - - for (axis = 0;axis<3;axis++) - { - m_pHandles[0].m_maxEdges[axis] -= 2; - } - - // remove the edges by sorting them up to the end of the list - for ( axis = 0; axis < 3; axis++) - { - Edge* pEdges = m_pEdges[axis]; - BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; - pEdges[max].m_pos = BP_HANDLE_SENTINEL; - - sortMaxUp(axis,max,false); - - - BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; - pEdges[i].m_pos = BP_HANDLE_SENTINEL; - - - sortMinUp(axis,i,false); - - pEdges[limit-1].m_handle = 0; - pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL; - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis,false); -#endif //DEBUG_BROADPHASE - - - } - - - // free the handle - freeHandle(handle); - - -} - -extern int gOverlappingPairs; - - -void btAxisSweep3::refreshOverlappingPairs() -{ - -} -void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback) -{ - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - //remove the 'invalid' ones -#ifdef USE_POPBACK_REMOVAL - while (m_invalidPair>0) - { - m_invalidPair--; - m_overlappingPairArray.pop_back(); - } -#else - m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; -#endif - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - cleanOverlappingPair(pair); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } -} - - -bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - const Handle* pHandleA = static_cast(proxy0); - const Handle* pHandleB = static_cast(proxy1); - - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - return true; -} - -bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) -{ - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (axis != ignoreAxis) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - } - - //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) - - /*for (int axis = 0; axis < 3; axis++) - { - if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || - m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) - { - return false; - } - } - */ - - return true; -} - -void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax) -{ -// assert(bounds.IsFinite()); - //assert(bounds.HasVolume()); - - Handle* pHandle = getHandle(handle); - - // quantize the new bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // update changed edges - for (int axis = 0; axis < 3; axis++) - { - BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; - BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; - - int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; - int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; - - m_pEdges[axis][emin].m_pos = min[axis]; - m_pEdges[axis][emax].m_pos = max[axis]; - - // expand (only adds overlaps) - if (dmin < 0) - sortMinDown(axis, emin); - - if (dmax > 0) - sortMaxUp(axis, emax); - - // shrink (only removes overlaps) - if (dmin > 0) - sortMinUp(axis, emin); - - if (dmax < 0) - sortMaxDown(axis, emax); - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - } - - -} - - - - -// sorting a min edge downwards can only ever *add* overlaps -void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (pPrev->IsMax()) - { - // if previous edge is a maximum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) - { - addOverlappingPair(pHandleEdge,pHandlePrev); - - //AddOverlap(pEdge->m_handle, pPrev->m_handle); - - } - - // update edge reference in other handle - pHandlePrev->m_maxEdges[axis]++; - } - else - pHandlePrev->m_minEdges[axis]++; - - pHandleEdge->m_minEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a min edge upwards can only ever *remove* overlaps -void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (pNext->IsMax()) - { - // if next edge is maximum remove any overlap between the two handles - if (updateOverlaps) - { - /* - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - btBroadphasePair tmpPair(*handle0,*handle1); - removeOverlappingPair(tmpPair); - */ - - } - - // update edge reference in other handle - pHandleNext->m_maxEdges[axis]--; - } - else - pHandleNext->m_minEdges[axis]--; - - pHandleEdge->m_minEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - - -} - -// sorting a max edge downwards can only ever *remove* overlaps -void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (!pPrev->IsMax()) - { - // if previous edge was a minimum remove any overlap between the two handles - if (updateOverlaps) - { - //this is done during the overlappingpairarray iteration/narrowphase collision - /* - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pPrev->m_handle); - btBroadphasePair* pair = findPair(handle0,handle1); - //assert(pair); - - if (pair) - { - removeOverlappingPair(*pair); - } - */ - - } - - // update edge reference in other handle - pHandlePrev->m_minEdges[axis]++;; - } - else - pHandlePrev->m_maxEdges[axis]++; - - pHandleEdge->m_maxEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a max edge upwards can only ever *add* overlaps -void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (!pNext->IsMax()) - { - // if next edge is a minimum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - addOverlappingPair(handle0,handle1); - } - - // update edge reference in other handle - pHandleNext->m_minEdges[axis]--; - } - else - pHandleNext->m_maxEdges[axis]--; - - pHandleEdge->m_maxEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 2147483647); } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index 57bbb368672..d0ad09a385a 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -19,34 +19,26 @@ #ifndef AXIS_SWEEP_3_H #define AXIS_SWEEP_3_H -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btVector3.h" #include "btOverlappingPairCache.h" +#include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" - - -//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects -//#define BP_USE_FIXEDPOINT_INT_32 1 - -#ifdef BP_USE_FIXEDPOINT_INT_32 - #define BP_FP_INT_TYPE unsigned int - #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles - #define BP_HANDLE_SENTINEL 0x7fffffff - #define BP_HANDLE_MASK 0xfffffffe -#else - #define BP_FP_INT_TYPE unsigned short int - #define BP_MAX_HANDLES 32767 - #define BP_HANDLE_SENTINEL 0xffff - #define BP_HANDLE_MASK 0xfffe -#endif //BP_USE_FIXEDPOINT_INT_32 +#include "btOverlappingPairCallback.h" //#define DEBUG_BROADPHASE 1 +#define USE_OVERLAP_TEST_ON_REMOVES 1 -/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. -/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats. -/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos -class btAxisSweep3 : public btOverlappingPairCache +/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. +/// It uses quantized integers to represent the begin and end points for each of the 3 axis. +/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. +template +class btAxisSweep3Internal : public btBroadphaseInterface { +protected: + + BP_FP_INT_TYPE m_bpHandleMask; + BP_FP_INT_TYPE m_handleSentinel; public: @@ -57,47 +49,57 @@ public: BP_FP_INT_TYPE m_pos; // low bit is min/max BP_FP_INT_TYPE m_handle; - BP_FP_INT_TYPE IsMax() const {return m_pos & 1;} + BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);} }; public: - class Handle : public btBroadphaseProxy + class Handle : public btBroadphaseProxy { public: - + BT_DECLARE_ALIGNED_ALLOCATOR(); + // indexes into the edge arrays BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 - BP_FP_INT_TYPE m_handleId; +// BP_FP_INT_TYPE m_uniqueId; BP_FP_INT_TYPE m_pad; //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject - inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} - inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry -private: +protected: btPoint3 m_worldAabbMin; // overall system bounds btPoint3 m_worldAabbMax; // overall system bounds btVector3 m_quantize; // scaling factor for quantization BP_FP_INT_TYPE m_numHandles; // number of active handles - int m_maxHandles; // max number of handles + BP_FP_INT_TYPE m_maxHandles; // max number of handles Handle* m_pHandles; // handles pool + BP_FP_INT_TYPE m_firstFreeHandle; // free handles list Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) + void* m_pEdgesRawPtr[3]; - int m_invalidPair; + btOverlappingPairCache* m_pairCache; + + ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. + btOverlappingPairCallback* m_userPairCallback; + + bool m_ownsPairCache; + + int m_invalidPair; // allocation/deallocation BP_FP_INT_TYPE allocHandle(); void freeHandle(BP_FP_INT_TYPE handle); - bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); + bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1); #ifdef DEBUG_BROADPHASE void debugPrintAxis(int axis,bool checkCardinality=true); @@ -108,29 +110,803 @@ private: void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const; - void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); public: - btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384); - virtual ~btAxisSweep3(); - virtual void refreshOverlappingPairs(); + btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0); + + virtual ~btAxisSweep3Internal(); + + BP_FP_INT_TYPE getNumHandles() const + { + return m_numHandles; + } + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); - void removeHandle(BP_FP_INT_TYPE handle); - void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax); - inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); + void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher); + SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} void processAllOverlappingPairs(btOverlapCallback* callback); //Broadphase Interface - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); - virtual void destroyProxy(btBroadphaseProxy* proxy); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); - bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) + { + m_userPairCallback = pairCallback; + } + const btOverlappingPairCallback* getOverlappingPairUserCallback() const + { + return m_userPairCallback; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_worldAabbMin; + aabbMax = m_worldAabbMax; + } + + virtual void printStats() + { +/* printf("btAxisSweep3.h\n"); + printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(), + m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ()); + */ + + } + +}; + +//////////////////////////////////////////////////////////////////// + + + + +#ifdef DEBUG_BROADPHASE +#include + +template +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +{ + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + assert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + +template +btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); + + Handle* handle = getHandle(handleId); + + return handle; +} + + + +template +void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + removeHandle(static_cast(handle->m_uniqueId), dispatcher); +} + +template +void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher); + +} + + + + + +template +btAxisSweep3Internal::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache ) +:m_bpHandleMask(handleMask), +m_handleSentinel(handleSentinel), +m_pairCache(pairCache), +m_userPairCallback(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle + + if (!m_pairCache) + { + void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16); + m_pairCache = new(ptr) btHashedOverlappingPairCache(); + m_ownsPairCache = true; + } + + //assert(bounds.HasVolume()); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = m_handleSentinel; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer, using btAlignedAlloc, and put all handles on free list + m_pHandles = new Handle[maxHandles]; + + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + { + m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); + m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2]; + } + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = m_handleSentinel; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +template +btAxisSweep3Internal::~btAxisSweep3Internal() +{ + + for (int i = 2; i >= 0; i--) + { + btAlignedFree(m_pEdgesRawPtr[i]); + } + delete [] m_pHandles; + + if (m_ownsPairCache) + { + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + +template +void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const +{ + btPoint3 clampedPoint(point); + + + + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); + +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() +{ + assert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +template +void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) +{ + assert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + + + Handle* pHandle = getHandle(handle); + + pHandle->m_uniqueId = static_cast(handle); + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + pHandle->m_multiSapParentProxy = multiSapProxy; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2); + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = static_cast(limit - 1); + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); + sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); + sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); + sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); + sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); + sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); + + + return handle; +} + + +template +void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + //todo: compare performance + if (!m_pairCache->hasDeferredRemoval()) + { + m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); + } + + // compute current limit of edge arrays + int limit = static_cast(m_numHandles * 2); + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = m_handleSentinel; + + sortMaxUp(axis,max,dispatcher,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = m_handleSentinel; + + + sortMinUp(axis,i,dispatcher,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = m_handleSentinel; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +extern int gOverlappingPairs; +//#include + +template +void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + + if (m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + + + + + +} + + +template +bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +template +bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || + pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] || + pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] || + pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) + { + return false; + } + return true; +} + +template +void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher) +{ +// assert(bounds.IsFinite()); + //assert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin,dispatcher,true); + + if (dmax > 0) + sortMaxUp(axis, emax,dispatcher,true); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin,dispatcher,true); + + if (dmax < 0) + sortMaxDown(axis, emax,dispatcher,true); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2)) + { + m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + } + + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + //this is done during the overlappingpairarray iteration/narrowphase collision + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + m_pairCache->addOverlappingPair(handle0,handle1); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + +} + + + +//////////////////////////////////////////////////////////////////// + + +/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. +/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. +class btAxisSweep3 : public btAxisSweep3Internal +{ +public: + + btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0); + +}; + +/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. +/// This comes at the cost of more memory per handle, and a bit slower performance. +/// It uses arrays rather then lists for storage of the 3 axis. +class bt32BitAxisSweep3 : public btAxisSweep3Internal +{ +public: + + bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0); }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index b6ace03c07a..200ac365329 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -20,20 +20,34 @@ subject to the following restrictions: struct btDispatcherInfo; class btDispatcher; -struct btBroadphaseProxy; -#include "../../LinearMath/btVector3.h" +#include "btBroadphaseProxy.h" +class btOverlappingPairCache; -///BroadphaseInterface for aabb-overlapping object pairs +#include "LinearMath/btVector3.h" + +///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. +///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase. +///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class. class btBroadphaseInterface { public: virtual ~btBroadphaseInterface() {} - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0; - virtual void destroyProxy(btBroadphaseProxy* proxy)=0; - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; - virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0; + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; + + virtual btOverlappingPairCache* getOverlappingPairCache()=0; + virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void printStats() = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index 40d9748ffa9..e0bb67f8521 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -16,7 +16,8 @@ subject to the following restrictions: #ifndef BROADPHASE_PROXY_H #define BROADPHASE_PROXY_H -#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btAlignedAllocator.h" /// btDispatcher uses these types @@ -38,6 +39,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE, CONE_SHAPE_PROXYTYPE, CONVEX_SHAPE_PROXYTYPE, CYLINDER_SHAPE_PROXYTYPE, + UNIFORM_SCALING_SHAPE_PROXYTYPE, MINKOWSKI_SUM_SHAPE_PROXYTYPE, MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, //concave shapes @@ -50,6 +52,8 @@ CONCAVE_SHAPES_START_HERE, TERRAIN_SHAPE_PROXYTYPE, ///Used for GIMPACT Trimesh integration GIMPACT_SHAPE_PROXYTYPE, +///Multimaterial mesh + MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, EMPTY_SHAPE_PROXYTYPE, STATIC_PLANE_PROXYTYPE, @@ -57,13 +61,18 @@ CONCAVE_SHAPES_END_HERE, COMPOUND_SHAPE_PROXYTYPE, + SOFTBODY_SHAPE_PROXYTYPE, + MAX_BROADPHASE_COLLISION_TYPES }; -///btBroadphaseProxy -struct btBroadphaseProxy +///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. +///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody. +ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy { + +BT_DECLARE_ALIGNED_ALLOCATOR(); ///optional filtering to cull potential collisions enum CollisionFilterGroups @@ -73,44 +82,60 @@ struct btBroadphaseProxy KinematicFilter = 4, DebrisFilter = 8, SensorTrigger = 16, - AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger + AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger }; //Usually the client btCollisionObject or Rigidbody class void* m_clientObject; + short int m_collisionFilterGroup; short int m_collisionFilterMask; - //used for memory pools - btBroadphaseProxy() :m_clientObject(0){} + void* m_multiSapParentProxy; - btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) + + int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + + SIMD_FORCE_INLINE int getUid() const + { + return m_uniqueId; + } + + //used for memory pools + btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) + { + } + + btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) :m_clientObject(userPtr), m_collisionFilterGroup(collisionFilterGroup), m_collisionFilterMask(collisionFilterMask) { + m_multiSapParentProxy = multiSapParentProxy; } - static inline bool isPolyhedral(int proxyType) + + + static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) { return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); } - static inline bool isConvex(int proxyType) + static SIMD_FORCE_INLINE bool isConvex(int proxyType) { return (proxyType < CONCAVE_SHAPES_START_HERE); } - static inline bool isConcave(int proxyType) + static SIMD_FORCE_INLINE bool isConcave(int proxyType) { return ((proxyType > CONCAVE_SHAPES_START_HERE) && (proxyType < CONCAVE_SHAPES_END_HERE)); } - static inline bool isCompound(int proxyType) + static SIMD_FORCE_INLINE bool isCompound(int proxyType) { return (proxyType == COMPOUND_SHAPE_PROXYTYPE); } - static inline bool isInfinite(int proxyType) + static SIMD_FORCE_INLINE bool isInfinite(int proxyType) { return (proxyType == STATIC_PLANE_PROXYTYPE); } @@ -124,8 +149,9 @@ struct btBroadphaseProxy; -/// contains a pair of aabb-overlapping objects -struct btBroadphasePair +///The btBroadphasePair class contains a pair of aabb-overlapping objects. +///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes. +ATTRIBUTE_ALIGNED16(struct) btBroadphasePair { btBroadphasePair () : @@ -136,6 +162,8 @@ struct btBroadphasePair { } +BT_DECLARE_ALIGNED_ALLOCATOR(); + btBroadphasePair(const btBroadphasePair& other) : m_pProxy0(other.m_pProxy0), m_pProxy1(other.m_pProxy1), @@ -181,6 +209,7 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa */ + class btBroadphasePairSortPredicate { public: diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp index 2ad0c86d8a2..c95d1be0f2c 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -18,6 +18,6 @@ subject to the following restrictions: btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) { - m_dispatcher = ci.m_dispatcher; + m_dispatcher = ci.m_dispatcher1; } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h index 55cec386a7b..1618ad9fdd3 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -16,7 +16,8 @@ subject to the following restrictions: #ifndef COLLISION_ALGORITHM_H #define COLLISION_ALGORITHM_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" struct btBroadphaseProxy; class btDispatcher; @@ -25,21 +26,22 @@ class btCollisionObject; struct btDispatcherInfo; class btPersistentManifold; +typedef btAlignedObjectArray btManifoldArray; struct btCollisionAlgorithmConstructionInfo { btCollisionAlgorithmConstructionInfo() - :m_dispatcher(0), + :m_dispatcher1(0), m_manifold(0) { } btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) - :m_dispatcher(dispatcher) + :m_dispatcher1(dispatcher) { (void)temp; } - btDispatcher* m_dispatcher; + btDispatcher* m_dispatcher1; btPersistentManifold* m_manifold; int getDispatcherId(); @@ -71,6 +73,7 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp new file mode 100644 index 00000000000..7c41c8d8f71 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -0,0 +1,1289 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvt implementation by Nathanael Presson + +#include "btDbvt.h" + +// +typedef btAlignedObjectArray tNodeArray; +typedef btAlignedObjectArray tConstNodeArray; + +// +struct btDbvtNodeEnumerator : btDbvt::ICollide +{ +tConstNodeArray nodes; +void Process(const btDbvtNode* n) { nodes.push_back(n); } +}; + +// +static DBVT_INLINE int indexof(const btDbvtNode* node) +{ +return(node->parent->childs[1]==node); +} + +// +static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a, + const btDbvtVolume& b) +{ +#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE +DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)]; +btDbvtVolume& res=*(btDbvtVolume*)locals; +#else +btDbvtVolume res; +#endif +Merge(a,b,res); +return(res); +} + +// volume+edge lengths +static DBVT_INLINE btScalar size(const btDbvtVolume& a) +{ +const btVector3 edges=a.Lengths(); +return( edges.x()*edges.y()*edges.z()+ + edges.x()+edges.y()+edges.z()); +} + +// +static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth) +{ +if(node->isinternal()) + { + getmaxdepth(node->childs[0],depth+1,maxdepth); + getmaxdepth(node->childs[0],depth+1,maxdepth); + } else maxdepth=btMax(maxdepth,depth); +} + +// +static DBVT_INLINE void deletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ +btAlignedFree(pdbvt->m_free); +pdbvt->m_free=node; +} + +// +static void recursedeletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ +if(!node->isleaf()) + { + recursedeletenode(pdbvt,node->childs[0]); + recursedeletenode(pdbvt,node->childs[1]); + } +if(node==pdbvt->m_root) pdbvt->m_root=0; +deletenode(pdbvt,node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + void* data) +{ +btDbvtNode* node; +if(pdbvt->m_free) + { node=pdbvt->m_free;pdbvt->m_free=0; } + else + { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); } +node->parent = parent; +node->data = data; +node->childs[1] = 0; +return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume, + void* data) +{ +btDbvtNode* node=createnode(pdbvt,parent,data); +node->volume=volume; +return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume0, + const btDbvtVolume& volume1, + void* data) +{ +btDbvtNode* node=createnode(pdbvt,parent,data); +Merge(volume0,volume1,node->volume); +return(node); +} + +// +static void insertleaf( btDbvt* pdbvt, + btDbvtNode* root, + btDbvtNode* leaf) +{ +if(!pdbvt->m_root) + { + pdbvt->m_root = leaf; + leaf->parent = 0; + } + else + { + if(!root->isleaf()) + { + do { + root=root->childs[Select( leaf->volume, + root->childs[0]->volume, + root->childs[1]->volume)]; + } while(!root->isleaf()); + } + btDbvtNode* prev=root->parent; + btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0); + if(prev) + { + prev->childs[indexof(root)] = node; + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + do { + if(!prev->volume.Contain(node->volume)) + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + else + break; + node=prev; + } while(0!=(prev=node->parent)); + } + else + { + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + pdbvt->m_root = node; + } + } +} + +// +static btDbvtNode* removeleaf( btDbvt* pdbvt, + btDbvtNode* leaf) +{ +if(leaf==pdbvt->m_root) + { + pdbvt->m_root=0; + return(0); + } + else + { + btDbvtNode* parent=leaf->parent; + btDbvtNode* prev=parent->parent; + btDbvtNode* sibling=parent->childs[1-indexof(leaf)]; + if(prev) + { + prev->childs[indexof(parent)]=sibling; + sibling->parent=prev; + deletenode(pdbvt,parent); + while(prev) + { + const btDbvtVolume pb=prev->volume; + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + if(NotEqual(pb,prev->volume)) + { + prev=prev->parent; + } else break; + } + return(prev?prev:pdbvt->m_root); + } + else + { + pdbvt->m_root=sibling; + sibling->parent=0; + deletenode(pdbvt,parent); + return(pdbvt->m_root); + } + } +} + +// +static void fetchleaves(btDbvt* pdbvt, + btDbvtNode* root, + tNodeArray& leaves, + int depth=-1) +{ +if(root->isinternal()&&depth) + { + fetchleaves(pdbvt,root->childs[0],leaves,depth-1); + fetchleaves(pdbvt,root->childs[1],leaves,depth-1); + deletenode(pdbvt,root); + } + else + { + leaves.push_back(root); + } +} + +// +static void split( const tNodeArray& leaves, + tNodeArray& left, + tNodeArray& right, + const btVector3& org, + const btVector3& axis) +{ +left.resize(0); +right.resize(0); +for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) + left.push_back(leaves[i]); + else + right.push_back(leaves[i]); + } +} + +// +static btDbvtVolume bounds( const tNodeArray& leaves) +{ +#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE +DBVT_ALIGN char locals[sizeof(btDbvtVolume)]; +btDbvtVolume& volume=*(btDbvtVolume*)locals; +volume=leaves[0]->volume; +#else +btDbvtVolume volume=leaves[0]->volume; +#endif +for(int i=1,ni=leaves.size();ivolume,volume); + } +return(volume); +} + +// +static void bottomup( btDbvt* pdbvt, + tNodeArray& leaves) +{ +while(leaves.size()>1) + { + btScalar minsize=SIMD_INFINITY; + int minidx[2]={-1,-1}; + for(int i=0;ivolume,leaves[j]->volume)); + if(szvolume,n[1]->volume,0); + p->childs[0] = n[0]; + p->childs[1] = n[1]; + n[0]->parent = p; + n[1]->parent = p; + leaves[minidx[0]] = p; + leaves.swap(minidx[1],leaves.size()-1); + leaves.pop_back(); + } +} + +// +static btDbvtNode* topdown(btDbvt* pdbvt, + tNodeArray& leaves, + int bu_treshold) +{ +static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; +if(leaves.size()>1) + { + if(leaves.size()>bu_treshold) + { + const btDbvtVolume vol=bounds(leaves); + const btVector3 org=vol.Center(); + tNodeArray sets[2]; + int bestaxis=-1; + int bestmidp=leaves.size(); + int splitcount[3][2]={{0,0},{0,0},{0,0}}; + int i; + for( i=0;ivolume.Center()-org; + for(int j=0;j<3;++j) + { + ++splitcount[j][dot(x,axis[j])>0?1:0]; + } + } + for( i=0;i<3;++i) + { + if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) + { + const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1])); + if(midp=0) + { + sets[0].reserve(splitcount[bestaxis][0]); + sets[1].reserve(splitcount[bestaxis][1]); + split(leaves,sets[0],sets[1],org,axis[bestaxis]); + } + else + { + sets[0].reserve(leaves.size()/2+1); + sets[1].reserve(leaves.size()/2); + for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold); + node->childs[1]=topdown(pdbvt,sets[1],bu_treshold); + node->childs[0]->parent=node; + node->childs[1]->parent=node; + return(node); + } + else + { + bottomup(pdbvt,leaves); + return(leaves[0]); + } + } +return(leaves[0]); +} + +// +static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r) +{ +btDbvtNode* p=n->parent; +btAssert(n->isinternal()); +if(p>n) + { + const int i=indexof(n); + const int j=1-i; + btDbvtNode* s=p->childs[j]; + btDbvtNode* q=p->parent; + btAssert(n==p->childs[i]); + if(q) q->childs[indexof(p)]=n; else r=n; + s->parent=n; + p->parent=n; + n->parent=q; + p->childs[0]=n->childs[0]; + p->childs[1]=n->childs[1]; + n->childs[0]->parent=p; + n->childs[1]->parent=p; + n->childs[i]=p; + n->childs[j]=s; + btSwap(p->volume,n->volume); + return(p); + } +return(n); +} + +// +static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) +{ +while(n&&(count--)) n=n->parent; +return(n); +} + +// +// Api +// + +// + btDbvt::btDbvt() +{ +m_root = 0; +m_free = 0; +m_lkhd = -1; +m_leaves = 0; +m_opath = 0; +} + +// + btDbvt::~btDbvt() +{ +clear(); +} + +// +void btDbvt::clear() +{ +if(m_root) recursedeletenode(this,m_root); +btAlignedFree(m_free); +m_free=0; +} + +// +void btDbvt::optimizeBottomUp() +{ +if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + bottomup(this,leaves); + m_root=leaves[0]; + } +} + +// +void btDbvt::optimizeTopDown(int bu_treshold) +{ +if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + m_root=topdown(this,leaves,bu_treshold); + } +} + +// +void btDbvt::optimizeIncremental(int passes) +{ +if(passes<0) passes=m_leaves; +if(m_root&&(passes>0)) + { + do { + btDbvtNode* node=m_root; + unsigned bit=0; + while(node->isinternal()) + { + node=sort(node,m_root)->childs[(m_opath>>bit)&1]; + bit=(bit+1)&(sizeof(unsigned)*8-1); + } + update(node); + ++m_opath; + } while(--passes); + } +} + +// +btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data) +{ +btDbvtNode* leaf=createnode(this,0,volume,data); +insertleaf(this,m_root,leaf); +++m_leaves; +return(leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,int lookahead) +{ +btDbvtNode* root=removeleaf(this,leaf); +if(root) + { + if(lookahead>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } +insertleaf(this,root,leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume) +{ +btDbvtNode* root=removeleaf(this,leaf); +if(root) + { + if(m_lkhd>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } +leaf->volume=volume; +insertleaf(this,root,leaf); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin) +{ +if(leaf->volume.Contain(volume)) return(false); +volume.Expand(btVector3(margin,margin,margin)); +volume.SignedExpand(velocity); +update(leaf,volume); +return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity) +{ +if(leaf->volume.Contain(volume)) return(false); +volume.SignedExpand(velocity); +update(leaf,volume); +return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin) +{ +if(leaf->volume.Contain(volume)) return(false); +volume.Expand(btVector3(margin,margin,margin)); +update(leaf,volume); +return(true); +} + +// +void btDbvt::remove(btDbvtNode* leaf) +{ +removeleaf(this,leaf); +deletenode(this,leaf); +--m_leaves; +} + +// +void btDbvt::write(IWriter* iwriter) const +{ +btDbvtNodeEnumerator nodes; +nodes.nodes.reserve(m_leaves*2); +enumNodes(m_root,nodes); +iwriter->Prepare(m_root,nodes.nodes.size()); +for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent); + if(n->isinternal()) + { + const int c0=nodes.nodes.findLinearSearch(n->childs[0]); + const int c1=nodes.nodes.findLinearSearch(n->childs[1]); + iwriter->WriteNode(n,i,p,c0,c1); + } + else + { + iwriter->WriteLeaf(n,i,p); + } + } +} + +// +void btDbvt::clone(btDbvt& dest,IClone* iclone) const +{ +dest.clear(); +if(m_root!=0) + { + btAlignedObjectArray stack; + stack.reserve(m_leaves); + stack.push_back(sStkCLN(m_root,0)); + do { + const int i=stack.size()-1; + const sStkCLN e=stack[i]; + btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data); + stack.pop_back(); + if(e.parent!=0) + e.parent->childs[i&1]=n; + else + dest.m_root=n; + if(e.node->isinternal()) + { + stack.push_back(sStkCLN(e.node->childs[0],n)); + stack.push_back(sStkCLN(e.node->childs[1],n)); + } + else + { + iclone->CloneLeaf(n); + } + } while(stack.size()>0); + } +} + +// +int btDbvt::maxdepth(const btDbvtNode* node) +{ +int depth=0; +if(node) getmaxdepth(node,1,depth); +return(depth); +} + +// +int btDbvt::countLeaves(const btDbvtNode* node) +{ +if(node->isinternal()) + return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); + else + return(1); +} + +// +void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves) +{ +if(node->isinternal()) + { + extractLeaves(node->childs[0],leaves); + extractLeaves(node->childs[1],leaves); + } + else + { + leaves.push_back(node); + } +} + +// +#if DBVT_ENABLE_BENCHMARK + +#include +#include +#include "LinearMath/btQuickProf.h" + +/* +q6600,2.4ghz + +/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32" +/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch" +/Fo"..\..\out\release8\build\libbulletcollision\\" +/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb" +/W3 /nologo /c /Wp64 /Zi /errorReport:prompt + +Benchmarking dbvt... + World scale: 100.000000 + Extents base: 1.000000 + Extents range: 4.000000 + Leaves: 8192 + sizeof(btDbvtVolume): 32 bytes + sizeof(btDbvtNode): 44 bytes +[1] btDbvtVolume intersections: 3499 ms (-1%) +[2] btDbvtVolume merges: 1934 ms (0%) +[3] btDbvt::collideTT: 5485 ms (-21%) +[4] btDbvt::collideTT self: 2814 ms (-20%) +[5] btDbvt::collideTT xform: 7379 ms (-1%) +[6] btDbvt::collideTT xform,self: 7270 ms (-2%) +[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s) +[8] insert/remove: 2093 ms (0%),(1001983 ir/s) +[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) +[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) +[11] optimize (incremental): 2514 ms (0%),(1668000 o/s) +[12] btDbvtVolume notequal: 3659 ms (0%) +[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) +[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) +[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) +[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) +[17] btDbvtVolume select: 3419 ms (0%) +*/ + +struct btDbvtBenchmark +{ +struct NilPolicy : btDbvt::ICollide + { + NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} + void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*,btScalar depth) + { + ++m_pcount; + if(m_checksort) + { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); } + } + int m_pcount; + btScalar m_depth; + bool m_checksort; + }; +struct P14 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf,btScalar depth) + { + Node n; + n.leaf = leaf; + n.depth = depth; + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + }; +struct P15 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf) + { + Node n; + n.leaf = leaf; + n.depth = dot(leaf->volume.Center(),m_axis); + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + btVector3 m_axis; + }; +static btScalar RandUnit() + { + return(rand()/(btScalar)RAND_MAX); + } +static btVector3 RandVector3() + { + return(btVector3(RandUnit(),RandUnit(),RandUnit())); + } +static btVector3 RandVector3(btScalar cs) + { + return(RandVector3()*cs-btVector3(cs,cs,cs)/2); + } +static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) + { + return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); + } +static btTransform RandTransform(btScalar cs) + { + btTransform t; + t.setOrigin(RandVector3(cs)); + t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized()); + return(t); + } +static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt) + { + dbvt.clear(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark5_Iterations); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark6_Iterations); + for(int i=0;i rayorg; + btAlignedObjectArray raydir; + btDbvtBenchmark::NilPolicy policy; + rayorg.resize(cfgBenchmark7_Iterations); + raydir.resize(cfgBenchmark7_Iterations); + for(int i=0;i leaves; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + dbvt.extractLeaves(dbvt.m_root,leaves); + printf("[9] updates (teleport): "); + wallclock.reset(); + for(int i=0;i(leaves[rand()%cfgLeaves]), + btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale)); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time); + } +if(cfgBenchmark10_Enable) + {// Benchmark 10 + srand(380843); + btDbvt dbvt; + btAlignedObjectArray leaves; + btAlignedObjectArray vectors; + vectors.resize(cfgBenchmark10_Iterations); + for(int i=0;i(leaves[rand()%cfgLeaves]); + btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d); + dbvt.update(l,v); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time); + } +if(cfgBenchmark11_Enable) + {// Benchmark 11 + srand(380843); + btDbvt dbvt; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + printf("[11] optimize (incremental): "); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i vectors; + btDbvtBenchmark::NilPolicy policy; + vectors.resize(cfgBenchmark13_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P14 policy; + vectors.resize(cfgBenchmark14_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P15 policy; + vectors.resize(cfgBenchmark15_Iterations); + for(int i=0;i batch; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + batch.reserve(cfgBenchmark16_BatchCount); + printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + btAlignedObjectArray indices; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + indices.resize(cfgLeaves); + for(int i=0;i= 1400) + #define DBVT_USE_TEMPLATE 1 + #else + #define DBVT_USE_TEMPLATE 0 +#endif +#else +#define DBVT_USE_TEMPLATE 0 +#endif + +// Use only intrinsics instead of inline asm +#define DBVT_USE_INTRINSIC_SSE 1 + +// Using memmov for collideOCL +#define DBVT_USE_MEMMOVE 1 + +// Enable benchmarking code +#define DBVT_ENABLE_BENCHMARK 0 + +// Inlining +#define DBVT_INLINE SIMD_FORCE_INLINE +// Align +#ifdef WIN32 +#define DBVT_ALIGN __declspec(align(16)) +#else +#define DBVT_ALIGN +#endif + +// Specific methods implementation + +#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds +#define DBVT_SELECT_IMPL DBVT_IMPL_SSE +#define DBVT_MERGE_IMPL DBVT_IMPL_SSE +#define DBVT_INT0_IMPL DBVT_IMPL_SSE +#else +#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC +#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC +#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC +#endif + +#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_INT0_IMPL==DBVT_IMPL_SSE) +#include +#endif + +// +// Auto config and checks +// + +#if DBVT_USE_TEMPLATE +#define DBVT_VIRTUAL +#define DBVT_VIRTUAL_DTOR(a) +#define DBVT_PREFIX template +#define DBVT_IPOLICY T& policy +#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0; +#else +#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} +#define DBVT_VIRTUAL virtual +#define DBVT_PREFIX +#define DBVT_IPOLICY ICollide& policy +#define DBVT_CHECKTYPE +#endif + +#if DBVT_USE_MEMMOVE +#ifndef __CELLOS_LV2__ +#include +#endif +#include +#endif + +#ifndef DBVT_USE_TEMPLATE +#error "DBVT_USE_TEMPLATE undefined" +#endif + +#ifndef DBVT_USE_MEMMOVE +#error "DBVT_USE_MEMMOVE undefined" +#endif + +#ifndef DBVT_ENABLE_BENCHMARK +#error "DBVT_ENABLE_BENCHMARK undefined" +#endif + +#ifndef DBVT_SELECT_IMPL +#error "DBVT_SELECT_IMPL undefined" +#endif + +#ifndef DBVT_MERGE_IMPL +#error "DBVT_MERGE_IMPL undefined" +#endif + +#ifndef DBVT_INT0_IMPL +#error "DBVT_INT0_IMPL undefined" +#endif + +// +// Defaults volumes +// + +/* btDbvtAabbMm */ +struct btDbvtAabbMm +{ +DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); } +DBVT_INLINE btVector3 Lengths() const { return(mx-mi); } +DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); } +DBVT_INLINE const btVector3& Mins() const { return(mi); } +DBVT_INLINE const btVector3& Maxs() const { return(mx); } +static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e); +static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); +static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); +static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); +static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); +DBVT_INLINE void Expand(const btVector3& e); +DBVT_INLINE void SignedExpand(const btVector3& e); +DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; +DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; +DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + const btTransform& xform); +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btVector3& b); +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btVector3& org, + const btVector3& invdir, + const unsigned* signs); +DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +DBVT_INLINE friend int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +DBVT_INLINE friend void Merge( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + btDbvtAabbMm& r); +DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +private: +DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; +private: +btVector3 mi,mx; +}; + +// Types +typedef btDbvtAabbMm btDbvtVolume; + +/* btDbvtNode */ +struct btDbvtNode +{ + btDbvtVolume volume; + btDbvtNode* parent; + DBVT_INLINE bool isleaf() const { return(childs[1]==0); } + DBVT_INLINE bool isinternal() const { return(!isleaf()); } + union { + btDbvtNode* childs[2]; + void* data; + }; +}; + +///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). +///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. +///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. +struct btDbvt + { + /* Stack element */ + struct sStkNN + { + const btDbvtNode* a; + const btDbvtNode* b; + sStkNN() {} + sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {} + }; + struct sStkNP + { + const btDbvtNode* node; + int mask; + sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {} + }; + struct sStkNPS + { + const btDbvtNode* node; + int mask; + btScalar value; + sStkNPS() {} + sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} + }; + struct sStkCLN + { + const btDbvtNode* node; + btDbvtNode* parent; + sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {} + }; + // Policies/Interfaces + + /* ICollide */ + struct ICollide + { + DBVT_VIRTUAL_DTOR(ICollide) + DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); } + DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); } + DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); } + }; + /* IWriter */ + struct IWriter + { + virtual ~IWriter() {} + virtual void Prepare(const btDbvtNode* root,int numnodes)=0; + virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0; + virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0; + }; + /* IClone */ + struct IClone + { + virtual ~IClone() {} + virtual void CloneLeaf(btDbvtNode*) {} + }; + + // Constants + enum { + SIMPLE_STACKSIZE = 64, + DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 + }; + + // Fields + btDbvtNode* m_root; + btDbvtNode* m_free; + int m_lkhd; + int m_leaves; + unsigned m_opath; + // Methods + btDbvt(); + ~btDbvt(); + void clear(); + bool empty() const { return(0==m_root); } + void optimizeBottomUp(); + void optimizeTopDown(int bu_treshold=128); + void optimizeIncremental(int passes); + btDbvtNode* insert(const btDbvtVolume& box,void* data); + void update(btDbvtNode* leaf,int lookahead=-1); + void update(btDbvtNode* leaf,const btDbvtVolume& volume); + bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin); + bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity); + bool update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin); + void remove(btDbvtNode* leaf); + void write(IWriter* iwriter) const; + void clone(btDbvt& dest,IClone* iclone=0) const; + static int maxdepth(const btDbvtNode* node); + static int countLeaves(const btDbvtNode* node); + static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves); + #if DBVT_ENABLE_BENCHMARK + static void benchmark(); + #else + static void benchmark(){} + #endif + // DBVT_IPOLICY must support ICollide policy/interface + DBVT_PREFIX + static void enumNodes( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + static void enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTV( const btDbvtNode* root, + const btDbvtVolume& volume, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideRAY( const btDbvtNode* root, + const btVector3& origin, + const btVector3& direction, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fullsort=true); + DBVT_PREFIX + static void collideTU( const btDbvtNode* root, + DBVT_IPOLICY); + // Helpers + static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) + { + int m=0; + while(l>1; + if(a[i[m]].value>=v) l=m+1; else h=m; + } + return(h); + } + static DBVT_INLINE int allocate( btAlignedObjectArray& ifree, + btAlignedObjectArray& stock, + const sStkNPS& value) + { + int i; + if(ifree.size()>0) + { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; } + else + { i=stock.size();stock.push_back(value); } + return(i); + } + // + private: + btDbvt(const btDbvt&) {} + }; + +// +// Inline's +// + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) +{ +btDbvtAabbMm box; +box.mi=c-e;box.mx=c+e; +return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r) +{ +return(FromCE(c,btVector3(r,r,r))); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx) +{ +btDbvtAabbMm box; +box.mi=mi;box.mx=mx; +return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n) +{ +btDbvtAabbMm box; +box.mi=box.mx=pts[0]; +for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); +if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); +if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); +} + +// +DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const +{ +return( (mi.x()<=a.mi.x())&& + (mi.y()<=a.mi.y())&& + (mi.z()<=a.mi.z())&& + (mx.x()>=a.mx.x())&& + (mx.y()>=a.mx.y())&& + (mx.z()>=a.mx.z())); +} + +// +DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const +{ +btVector3 pi,px; +switch(s) + { + case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z()); + pi=btVector3(mx.x(),mx.y(),mx.z());break; + case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z()); + pi=btVector3(mi.x(),mx.y(),mx.z());break; + case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z()); + pi=btVector3(mx.x(),mi.y(),mx.z());break; + case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z()); + pi=btVector3(mi.x(),mi.y(),mx.z());break; + case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z()); + pi=btVector3(mx.x(),mx.y(),mi.z());break; + case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z()); + pi=btVector3(mi.x(),mx.y(),mi.z());break; + case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z()); + pi=btVector3(mx.x(),mi.y(),mi.z());break; + case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z()); + pi=btVector3(mi.x(),mi.y(),mi.z());break; + } +if((dot(n,px)+o)<0) return(-1); +if((dot(n,pi)+o)>=0) return(+1); +return(0); +} + +// +DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const +{ +const btVector3* b[]={&mx,&mi}; +const btVector3 p( b[(signs>>0)&1]->x(), + b[(signs>>1)&1]->y(), + b[(signs>>2)&1]->z()); +return(dot(p,v)); +} + +// +DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const +{ +for(int i=0;i<3;++i) + { + if(d[i]<0) + { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; } + else + { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; } + } +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_INT0_IMPL == DBVT_IMPL_SSE +const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), + _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); +const __int32* pu((const __int32*)&rt); +return((pu[0]|pu[1]|pu[2])==0); +#else +return( (a.mi.x()<=b.mx.x())&& + (a.mx.x()>=b.mi.x())&& + (a.mi.y()<=b.mx.y())&& + (a.mx.y()>=b.mi.y())&& + (a.mi.z()<=b.mx.z())&& + (a.mx.z()>=b.mi.z())); +#endif +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + const btTransform& xform) +{ +const btVector3 d0=xform*b.Center()-a.Center(); +const btVector3 d1=d0*xform.getBasis(); +btScalar s0[2]={0,0}; +btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]}; +a.AddSpan(d0,s0[0],s0[1]); +b.AddSpan(d1,s1[0],s1[1]); +if(s0[0]>(s1[1])) return(false); +if(s0[1]<(s1[0])) return(false); +return(true); +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btVector3& b) +{ +return( (b.x()>=a.mi.x())&& + (b.y()>=a.mi.y())&& + (b.z()>=a.mi.z())&& + (b.x()<=a.mx.x())&& + (b.y()<=a.mx.y())&& + (b.z()<=a.mx.z())); +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btVector3& org, + const btVector3& invdir, + const unsigned* signs) +{ +#if 0 +const btVector3 b0((a.mi-org)*invdir); +const btVector3 b1((a.mx-org)*invdir); +const btVector3 tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2])); +const btVector3 tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2])); +const btScalar tin=btMax(tmin[0],btMax(tmin[1],tmin[2])); +const btScalar tout=btMin(tmax[0],btMin(tmax[1],tmax[2])); +return(tinx()-org[0])*invdir[0]; +btScalar txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0]; +const btScalar tymin=(bounds[ signs[1]]->y()-org[1])*invdir[1]; +const btScalar tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1]; +if((txmin>tymax)||(tymin>txmax)) return(false); +if(tymin>txmin) txmin=tymin; +if(tymaxz()-org[2])*invdir[2]; +const btScalar tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2]; +if((txmin>tzmax)||(tzmin>txmax)) return(false); +if(tzmin>txmin) txmin=tzmin; +if(tzmax0); +#endif +} + +// +DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); +return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); +} + +// +DBVT_INLINE int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE +static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; + // TODO: the intrinsic version is 11% slower + #if DBVT_USE_INTRINSIC_SSE + __m128 omi(_mm_load_ps(o.mi)); + omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); + __m128 ami(_mm_load_ps(a.mi)); + ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); + ami=_mm_sub_ps(ami,omi); + ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); + __m128 bmi(_mm_load_ps(b.mi)); + bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); + bmi=_mm_sub_ps(bmi,omi); + bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); + __m128 t0(_mm_movehl_ps(ami,ami)); + ami=_mm_add_ps(ami,t0); + ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); + __m128 t1(_mm_movehl_ps(bmi,bmi)); + bmi=_mm_add_ps(bmi,t1); + bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); + return(_mm_cmple_ss(bmi,ami).m128_u32[0]&1); + #else + DBVT_ALIGN __int32 r[1]; + __asm + { + mov eax,o + mov ecx,a + mov edx,b + movaps xmm0,[eax] + movaps xmm5,mask + addps xmm0,[eax+16] + movaps xmm1,[ecx] + movaps xmm2,[edx] + addps xmm1,[ecx+16] + addps xmm2,[edx+16] + subps xmm1,xmm0 + subps xmm2,xmm0 + andps xmm1,xmm5 + andps xmm2,xmm5 + movhlps xmm3,xmm1 + movhlps xmm4,xmm2 + addps xmm1,xmm3 + addps xmm2,xmm4 + pshufd xmm3,xmm1,1 + pshufd xmm4,xmm2,1 + addss xmm1,xmm3 + addss xmm2,xmm4 + cmpless xmm2,xmm1 + movss r,xmm2 + } + return(r[0]&1); + #endif +#else +return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; + } +#endif +} + +// +DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +return( (a.mi.x()!=b.mi.x())|| + (a.mi.y()!=b.mi.y())|| + (a.mi.z()!=b.mi.z())|| + (a.mx.x()!=b.mx.x())|| + (a.mx.y()!=b.mx.y())|| + (a.mx.z()!=b.mx.z())); +} + +// +// Inline's +// + +// +DBVT_PREFIX +inline void btDbvt::enumNodes( const btDbvtNode* root, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +policy.Process(root); +if(root->isinternal()) + { + enumNodes(root->childs[0],policy); + enumNodes(root->childs[1],policy); + } +} + +// +DBVT_PREFIX +inline void btDbvt::enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root->isinternal()) + { + enumLeaves(root->childs[0],policy); + enumLeaves(root->childs[1],policy); + } + else + { + policy.Process(root); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root0&&root1) + { + btAlignedObjectArray stack; + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=sStkNN(root0,root1); + do { + sStkNN p=stack[--depth]; + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + stack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); + } + } + else if(Intersect(p.a->volume,p.b->volume)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stack[depth++]=sStkNN(p.a->childs[0],p.b); + stack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a,p.b->childs[0]); + stack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root0&&root1) + { + btAlignedObjectArray stack; + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=sStkNN(root0,root1); + do { + sStkNN p=stack[--depth]; + if(Intersect(p.a->volume,p.b->volume,xform)) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-4; + } + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stack[depth++]=sStkNN(p.a->childs[0],p.b); + stack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a,p.b->childs[0]); + stack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY) +{ +const btTransform xform=xform0.inverse()*xform1; +collideTT(root0,root1,xform,policy); +} + +// +DBVT_PREFIX +inline void btDbvt::collideTV( const btDbvtNode* root, + const btDbvtVolume& vol, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) + { + if(n->isinternal()) + { + stack.push_back(n->childs[0]); + stack.push_back(n->childs[1]); + } + else + { + policy.Process(n); + } + } + } while(stack.size()>0); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideRAY( const btDbvtNode* root, + const btVector3& origin, + const btVector3& direction, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + const btVector3 normal=direction.normalized(); + const btVector3 invdir( 1/normal.x(), + 1/normal.y(), + 1/normal.z()); + const unsigned signs[]={ direction.x()<0, + direction.y()<0, + direction.z()<0}; + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* node=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(node->volume,origin,invdir,signs)) + { + if(node->isinternal()) + { + stack.push_back(node->childs[0]); + stack.push_back(node->childs[1]); + } + else + { + policy.Process(node); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + const int inside=(1< stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(sStkNP(root,0)); + do { + sStkNP se=stack[stack.size()-1]; + bool out=false; + stack.pop_back(); + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(!out) + { + if((se.mask!=inside)&&(se.node->isinternal())) + { + stack.push_back(sStkNP(se.node->childs[0],se.mask)); + stack.push_back(sStkNP(se.node->childs[1],se.mask)); + } + else + { + if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fsort) +{ +DBVT_CHECKTYPE +if(root) + { + const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ + (sortaxis[1]>=0?2:0)+ + (sortaxis[2]>=0?4:0); + const int inside=(1< stock; + btAlignedObjectArray ifree; + btAlignedObjectArray stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stock.reserve(SIMPLE_STACKSIZE); + stack.reserve(SIMPLE_STACKSIZE); + ifree.reserve(SIMPLE_STACKSIZE); + stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); + do { + const int id=stack[stack.size()-1]; + sStkNPS se=stock[id]; + stack.pop_back();ifree.push_back(id); + if(se.mask!=inside) + { + bool out=false; + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(out) continue; + } + if(policy.Descent(se.node)) + { + if(se.node->isinternal()) + { + const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]}; + sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), + sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; + const int q=nes[0].value0)) + { + /* Insert 0 */ + j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); + stack.push_back(0); + #if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); + #else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; + #endif + stack[j]=allocate(ifree,stock,nes[q]); + /* Insert 1 */ + j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); + stack.push_back(0); + #if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); + #else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; + #endif + stack[j]=allocate(ifree,stock,nes[1-q]); + } + else + { + stack.push_back(allocate(ifree,stock,nes[q])); + stack.push_back(allocate(ifree,stock,nes[1-q])); + } + } + else + { + policy.Process(se.node,se.value); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTU( const btDbvtNode* root, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(policy.Descent(n)) + { + if(n->isinternal()) + { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } + else + { policy.Process(n); } + } + } while(stack.size()>0); + } +} + +// +// PP Cleanup +// + +#undef DBVT_USE_MEMMOVE +#undef DBVT_USE_TEMPLATE +#undef DBVT_VIRTUAL_DTOR +#undef DBVT_VIRTUAL +#undef DBVT_PREFIX +#undef DBVT_IPOLICY +#undef DBVT_CHECKTYPE +#undef DBVT_IMPL_GENERIC +#undef DBVT_IMPL_SSE +#undef DBVT_USE_INTRINSIC_SSE +#undef DBVT_SELECT_IMPL +#undef DBVT_MERGE_IMPL +#undef DBVT_INT0_IMPL + +#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp new file mode 100644 index 00000000000..c6086f28f19 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -0,0 +1,344 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvtBroadphase implementation by Nathanael Presson + +#include "btDbvtBroadphase.h" + +// +// Profiling +// + +#if DBVT_BP_PROFILE +#include +struct ProfileScope + { + ProfileScope(btClock& clock,unsigned long& value) + { + m_clock=&clock; + m_value=&value; + m_base=clock.getTimeMicroseconds(); + } + ~ProfileScope() + { + (*m_value)+=m_clock->getTimeMicroseconds()-m_base; + } + btClock* m_clock; + unsigned long* m_value; + unsigned long m_base; + }; +#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_) +#else +#define SPC(_value_) +#endif + +// +// Helpers +// + +// +template +static inline void listappend(T* item,T*& list) +{ +item->links[0]=0; +item->links[1]=list; +if(list) list->links[0]=item; +list=item; +} + +// +template +static inline void listremove(T* item,T*& list) +{ +if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1]; +if(item->links[1]) item->links[1]->links[0]=item->links[0]; +} + +// +template +static inline int listcount(T* root) +{ +int n=0; +while(root) { ++n;root=root->links[1]; } +return(n); +} + +// +template +static inline void clear(T& value) +{ +static const struct ZeroDummy : T {} zerodummy; +value=zerodummy; +} + +// +// Colliders +// + +/* Tree collider */ +struct btDbvtTreeCollider : btDbvt::ICollide +{ +btDbvtBroadphase* pbp; + btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} +void Process(const btDbvtNode* na,const btDbvtNode* nb) + { + btDbvtProxy* pa=(btDbvtProxy*)na->data; + btDbvtProxy* pb=(btDbvtProxy*)nb->data; + #if DBVT_BP_DISCRETPAIRS + if(Intersect(pa->aabb,pb->aabb)) + #endif + { + if(pa>pb) btSwap(pa,pb); + pbp->m_paircache->addOverlappingPair(pa,pb); + } + } +}; + +// +// btDbvtBroadphase +// + +// +btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) +{ +m_releasepaircache = (paircache!=0)?false:true; +m_predictedframes = 2; +m_stageCurrent = 0; +m_fupdates = 1; +m_dupdates = 1; +m_paircache = paircache? + paircache : + new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); +m_gid = 0; +m_pid = 0; +for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } +#if DBVT_BP_PROFILE +clear(m_profiling); +#endif +} + +// +btDbvtBroadphase::~btDbvtBroadphase() +{ +if(m_releasepaircache) +{ + m_paircache->~btOverlappingPairCache(); + btAlignedFree(m_paircache); +} +} + +// +btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, + const btVector3& aabbMax, + int /*shapeType*/, + void* userPtr, + short int collisionFilterGroup, + short int collisionFilterMask, + btDispatcher* /*dispatcher*/, + void* /*multiSapProxy*/) +{ +btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr, + collisionFilterGroup, + collisionFilterMask); +proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); +proxy->leaf = m_sets[0].insert(proxy->aabb,proxy); +proxy->stage = m_stageCurrent; +proxy->m_uniqueId = ++m_gid; +listappend(proxy,m_stageRoots[m_stageCurrent]); +return(proxy); +} + +// +void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy, + btDispatcher* dispatcher) +{ +btDbvtProxy* proxy=(btDbvtProxy*)absproxy; +if(proxy->stage==STAGECOUNT) + m_sets[1].remove(proxy->leaf); + else + m_sets[0].remove(proxy->leaf); +listremove(proxy,m_stageRoots[proxy->stage]); +m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); +btAlignedFree(proxy); +} + +// +void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) +{ +btDbvtProxy* proxy=(btDbvtProxy*)absproxy; +btDbvtVolume aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); +if(NotEqual(aabb,proxy->leaf->volume)) + { + if(proxy->stage==STAGECOUNT) + {/* fixed -> dynamic set */ + m_sets[1].remove(proxy->leaf); + proxy->leaf=m_sets[0].insert(aabb,proxy); + } + else + {/* dynamic set */ + if(Intersect(proxy->leaf->volume,aabb)) + {/* Moving */ + const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center(); + #ifdef DBVT_BP_MARGIN + m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes,DBVT_BP_MARGIN); + #else + m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes); + #endif + } + else + {/* Teleporting */ + m_sets[0].update(proxy->leaf,aabb); + } + } + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->aabb = aabb; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + } +} + +// +void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ +collide(dispatcher); +#if DBVT_BP_PROFILE +if(0==(m_pid%DBVT_BP_PROFILING_RATE)) + { + printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs()); + unsigned int total=m_profiling.m_total; + if(total<=0) total=1; + printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE); + printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE); + printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE); + printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE); + const unsigned long sum=m_profiling.m_ddcollide+ + m_profiling.m_fdcollide+ + m_profiling.m_cleanup; + printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE); + printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE)); + clear(m_profiling); + m_clock.reset(); + } +#endif +} + +// +void btDbvtBroadphase::collide(btDispatcher* dispatcher) +{ +SPC(m_profiling.m_total); +/* optimize */ +m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); +m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); +/* dynamic -> fixed set */ +m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; +btDbvtProxy* current=m_stageRoots[m_stageCurrent]; +if(current) + { + btDbvtTreeCollider collider(this); + do { + btDbvtProxy* next=current->links[1]; + listremove(current,m_stageRoots[current->stage]); + listappend(current,m_stageRoots[STAGECOUNT]); + btDbvt::collideTT(m_sets[1].m_root,current->leaf,collider); + m_sets[0].remove(current->leaf); + current->leaf = m_sets[1].insert(current->aabb,current); + current->stage = STAGECOUNT; + current = next; + } while(current); + } +/* collide dynamics */ + { + btDbvtTreeCollider collider(this); + { + SPC(m_profiling.m_fdcollide); + btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider); + } + { + SPC(m_profiling.m_ddcollide); + btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider); + } + } +/* clean up */ + { + SPC(m_profiling.m_cleanup); + btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); + if(pairs.size()>0) + { + for(int i=0,ni=pairs.size();iaabb,pb->aabb)) + { + if(pa>pb) btSwap(pa,pb); + m_paircache->removeOverlappingPair(pa,pb,dispatcher); + --ni;--i; + } + } + } + } +++m_pid; +} + +// +void btDbvtBroadphase::optimize() +{ +m_sets[0].optimizeTopDown(); +m_sets[1].optimizeTopDown(); +} + +// +btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() +{ +return(m_paircache); +} + +// +const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const +{ +return(m_paircache); +} + +// +void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds; + +if(!m_sets[0].empty()) + if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume, + m_sets[1].m_root->volume,bounds); + else + bounds=m_sets[0].m_root->volume; +else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume; + else + bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0); +aabbMin=bounds.Mins(); +aabbMax=bounds.Maxs(); +} + +// +void btDbvtBroadphase::printStats() +{} + +#if DBVT_BP_PROFILE +#undef SPC +#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h new file mode 100644 index 00000000000..3f19075552b --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvtBroadphase implementation by Nathanael Presson +#ifndef BT_DBVT_BROADPHASE_H +#define BT_DBVT_BROADPHASE_H + +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +// +// Compile time config +// + +#define DBVT_BP_PROFILE 0 +#define DBVT_BP_DISCRETPAIRS 1 +#define DBVT_BP_MARGIN (btScalar)0.05 + +#if DBVT_BP_PROFILE + #define DBVT_BP_PROFILING_RATE 256 + #include "LinearMath/btQuickprof.h" +#endif + +// +// btDbvtProxy +// +struct btDbvtProxy : btBroadphaseProxy +{ +/* Fields */ +btDbvtAabbMm aabb; +btDbvtNode* leaf; +btDbvtProxy* links[2]; +int stage; +/* ctor */ +btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : + btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask) + { + links[0]=links[1]=0; + } +}; + +typedef btAlignedObjectArray btDbvtProxyArray; + +///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt). +///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other. +///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3. +struct btDbvtBroadphase : btBroadphaseInterface +{ +/* Config */ +enum { + DYNAMIC_SET = 0, /* Dynamic set index */ + FIXED_SET = 1, /* Fixed set index */ + STAGECOUNT = 2 /* Number of stages */ + }; +/* Fields */ +btDbvt m_sets[2]; // Dbvt sets +btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list +btOverlappingPairCache* m_paircache; // Pair cache +btScalar m_predictedframes; // Frames predicted +int m_stageCurrent; // Current stage +int m_fupdates; // % of fixed updates per frame +int m_dupdates; // % of dynamic updates per frame +int m_pid; // Parse id +int m_gid; // Gen id +bool m_releasepaircache; // Release pair cache on delete +#if DBVT_BP_PROFILE +btClock m_clock; +struct { + unsigned long m_total; + unsigned long m_ddcollide; + unsigned long m_fdcollide; + unsigned long m_cleanup; + unsigned long m_jobcount; + } m_profiling; +#endif +/* Methods */ +btDbvtBroadphase(btOverlappingPairCache* paircache=0); +~btDbvtBroadphase(); +void collide(btDispatcher* dispatcher); +void optimize(); +/* btBroadphaseInterface Implementation */ +btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); +void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); +void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); +void calculateOverlappingPairs(btDispatcher* dispatcher); +btOverlappingPairCache* getOverlappingPairCache(); +const btOverlappingPairCache* getOverlappingPairCache() const; +void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; +void printStats(); +}; + +#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 3d958cc8fef..6db71a0170e 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef _DISPATCHER_H #define _DISPATCHER_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" class btCollisionAlgorithm; struct btBroadphaseProxy; @@ -43,7 +43,9 @@ struct btDispatcherInfo m_useContinuous(false), m_debugDraw(0), m_enableSatConvex(false), - m_enableSPU(false), + m_enableSPU(true), + m_useEpa(true), + m_allowedCcdPenetration(btScalar(0.04)), m_stackAllocator(0) { @@ -51,17 +53,19 @@ struct btDispatcherInfo btScalar m_timeStep; int m_stepCount; int m_dispatchFunc; - btScalar m_timeOfImpact; + mutable btScalar m_timeOfImpact; bool m_useContinuous; class btIDebugDraw* m_debugDraw; bool m_enableSatConvex; bool m_enableSPU; + bool m_useEpa; + btScalar m_allowedCcdPenetration; btStackAlloc* m_stackAllocator; }; -/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs. -/// For example for pairwise collision detection or user callbacks (game logic). +///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. +///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). class btDispatcher { @@ -81,12 +85,18 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0; + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0; virtual int getNumManifolds() const = 0; virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; + virtual btPersistentManifold** getInternalManifoldPointer() = 0; + + virtual void* allocateCollisionAlgorithm(int size) = 0; + + virtual void freeCollisionAlgorithm(void* ptr) = 0; + }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp new file mode 100644 index 00000000000..3f866ab7c5f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -0,0 +1,466 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btMultiSapBroadphase.h" + +#include "btSimpleBroadphase.h" +#include "LinearMath/btAabbUtil2.h" +#include "btQuantizedBvh.h" + +/// btSapBroadphaseArray m_sapBroadphases; + +/// btOverlappingPairCache* m_overlappingPairs; +extern int gOverlappingPairs; + +/* +class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache +{ +public: + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); + } +}; + +*/ + +btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) +:m_overlappingPairs(pairCache), +m_optimizedAabbTree(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + if (!m_overlappingPairs) + { + m_ownsPairCache = true; + void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); + m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); + } + + struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback + { + virtual ~btMultiSapOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const + { + btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; + btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; + + bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; + collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); + + return collides; + } + }; + + void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); + m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); + + m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); +// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); +// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); +} + +btMultiSapBroadphase::~btMultiSapBroadphase() +{ + if (m_ownsPairCache) + { + m_overlappingPairs->~btOverlappingPairCache(); + btAlignedFree(m_overlappingPairs); + } +} + + +void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) +{ + m_optimizedAabbTree = new btQuantizedBvh(); + m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); + QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray(); + for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + int partId = 0; + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; + nodes.push_back(node); + } + m_optimizedAabbTree->buildInternal(); +} + +btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) +{ + //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested + + void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); + btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); + m_multiSapProxies.push_back(proxy); + + ///this should deal with inserting/removal into child broadphases + setAabb(proxy,aabbMin,aabbMax,dispatcher); + return proxy; +} + +void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) +{ + ///not yet + btAssert(0); + +} + + +void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase) +{ + void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); + btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; + bridgeProxyRef->m_childProxy = childProxy; + bridgeProxyRef->m_childBroadphase = childBroadphase; + parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); +} + + +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) +{ +return +amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && +amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && +amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); +} + + + + + + +//#include + +void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + multiProxy->m_aabbMin = aabbMin; + multiProxy->m_aabbMax = aabbMax; + + +// bool fullyContained = false; +// bool alreadyInSimple = false; + + + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btMultiSapBroadphase* m_multiSap; + btMultiSapProxy* m_multiProxy; + btDispatcher* m_dispatcher; + + MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) + :m_multiSap(multiSap), + m_multiProxy(multiProxy), + m_dispatcher(dispatcher) + { + + } + + virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) + { + btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; + + int containingBroadphaseIndex = -1; + //already found? + for (int i=0;im_bridgeProxies.size();i++) + { + + if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + break; + } + } + if (containingBroadphaseIndex<0) + { + //add it + btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); + m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); + + } + } + }; + + MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); + + + + + m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + int i; + + for ( i=0;im_bridgeProxies.size();i++) + { + btVector3 worldAabbMin,worldAabbMax; + multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + if (!overlapsBroadphase) + { + //remove it now + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + + } + } + + + /* + + if (1) + { + + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + + // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + int containingBroadphaseIndex = -1; + + //if already contains this + + for (int i=0;im_bridgeProxies.size();i++) + { + if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + } + alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); + } + + if (overlapsBroadphase) + { + if (containingBroadphaseIndex<0) + { + btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,childBroadphase); + } + } else + { + if (containingBroadphaseIndex>=0) + { + //remove + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + } + } + } + + + ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) + ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) + if (0)//!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } + } + + if (!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } +*/ + + + //update + for ( i=0;im_bridgeProxies.size();i++) + { + btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; + bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); + } + +} +bool stopUpdating=false; + + + +class btMultiSapBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) + { + btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; + + return aProxy0 > bProxy0 || + (aProxy0 == bProxy0 && aProxy1 > bProxy1) || + (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); + } +}; + + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb +void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + +// m_simpleBroadphase->calculateOverlappingPairs(dispatcher); + + if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); + + // quicksort(overlappingPairArray,0,overlappingPairArray.size()); + + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;im_multiSapParentProxy : 0; + btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; + + bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); + + previousPair = pair; + + bool needsRemoval = false; + + if (!isDuplicate) + { + bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); + + if (hasOverlap) + { + needsRemoval = false;//callback->processOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + + +} + + +bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) +{ + btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; + btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; + + return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, + multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); + +} + + +void btMultiSapBroadphase::printStats() +{ +/* printf("---------------------------------\n"); + + printf("btMultiSapBroadphase.h\n"); + printf("numHandles = %d\n",m_multiSapProxies.size()); + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;iprintStats(); + + } + */ + +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h new file mode 100644 index 00000000000..a0c002de856 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h @@ -0,0 +1,144 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_MULTI_SAP_BROADPHASE +#define BT_MULTI_SAP_BROADPHASE + +#include "btBroadphaseInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCache.h" + + +class btBroadphaseInterface; +class btSimpleBroadphase; + + +typedef btAlignedObjectArray btSapBroadphaseArray; + +///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. +///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. +///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. +///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 +///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 +class btMultiSapBroadphase :public btBroadphaseInterface +{ + btSapBroadphaseArray m_sapBroadphases; + + btSimpleBroadphase* m_simpleBroadphase; + + btOverlappingPairCache* m_overlappingPairs; + + class btQuantizedBvh* m_optimizedAabbTree; + + + bool m_ownsPairCache; + + btOverlapFilterCallback* m_filterCallback; + + int m_invalidPair; + + struct btBridgeProxy + { + btBroadphaseProxy* m_childProxy; + btBroadphaseInterface* m_childBroadphase; + }; + + +public: + + struct btMultiSapProxy : public btBroadphaseProxy + { + + ///array with all the entries that this proxy belongs to + btAlignedObjectArray m_bridgeProxies; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + int m_shapeType; + +/* void* m_userPtr; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; +*/ + btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) + :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax), + m_shapeType(shapeType) + { + m_multiSapParentProxy =this; + } + + + }; + +protected: + + + btAlignedObjectArray m_multiSapProxies; + +public: + + btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); + + + btSapBroadphaseArray& getBroadphaseArray() + { + return m_sapBroadphases; + } + + const btSapBroadphaseArray& getBroadphaseArray() const + { + return m_sapBroadphases; + } + + virtual ~btMultiSapBroadphase(); + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + + void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + virtual btOverlappingPairCache* getOverlappingPairCache() + { + return m_overlappingPairs; + } + virtual const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_overlappingPairs; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-1e30f,-1e30f,-1e30f); + aabbMax.setValue(1e30f,1e30f,1e30f); + } + + void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + + virtual void printStats(); + + void quicksort (btBroadphasePairArray& a, int lo, int hi); + +}; + +#endif //BT_MULTI_SAP_BROADPHASE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp index 60f0a41a9d7..ff65cdde79f 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -1,4 +1,3 @@ - /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -21,44 +20,43 @@ subject to the following restrictions: #include "btDispatcher.h" #include "btCollisionAlgorithm.h" +#include + int gOverlappingPairs = 0; -btOverlappingPairCache::btOverlappingPairCache(): -m_blockedForChanges(false), -m_overlapFilterCallback(0) -//m_NumOverlapBroadphasePair(0) +int gRemovePairs =0; +int gAddedPairs =0; +int gFindPairs =0; + + + + +btHashedOverlappingPairCache::btHashedOverlappingPairCache(): + m_overlapFilterCallback(0), + m_blockedForChanges(false) { + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); + growTables(); } -btOverlappingPairCache::~btOverlappingPairCache() + + +btHashedOverlappingPairCache::~btHashedOverlappingPairCache() { //todo/test: show we erase/delete data, or is it automatic } -void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair) -{ - - int findIndex = m_overlappingPairArray.findLinearSearch(findPair); - if (findIndex < m_overlappingPairArray.size()) - { - gOverlappingPairs--; - btBroadphasePair& pair = m_overlappingPairArray[findIndex]; - cleanOverlappingPair(pair); - - m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1); - m_overlappingPairArray.pop_back(); - } -} - -void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) +void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) { if (pair.m_algorithm) { { - delete pair.m_algorithm;; + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); pair.m_algorithm=0; } } @@ -67,60 +65,20 @@ void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) - -void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - //don't add overlap with own - assert(proxy0 != proxy1); - - if (!needsBroadphaseCollision(proxy0,proxy1)) - return; - - - btBroadphasePair pair(*proxy0,*proxy1); - - m_overlappingPairArray.push_back(pair); - gOverlappingPairs++; - -} - -///this findPair becomes really slow. Either sort the list to speedup the query, or -///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. -///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) -///Also we can use a 2D bitmap, which can be useful for a future GPU implementation - btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; - - btBroadphasePair tmpPair(*proxy0,*proxy1); - int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); - - if (findIndex < m_overlappingPairArray.size()) - { - //assert(it != m_overlappingPairSet.end()); - btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; - return pair; - } - return 0; -} - - - - - -void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) +void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) { class CleanPairCallback : public btOverlapCallback { btBroadphaseProxy* m_cleanProxy; btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; public: - CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache) + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :m_cleanProxy(cleanProxy), - m_pairCache(pairCache) + m_pairCache(pairCache), + m_dispatcher(dispatcher) { } virtual bool processOverlap(btBroadphasePair& pair) @@ -128,22 +86,23 @@ void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { - m_pairCache->cleanOverlappingPair(pair); + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); } return false; } }; - CleanPairCallback cleanPairs(proxy,this); + CleanPairCallback cleanPairs(proxy,this,dispatcher); - processAllOverlappingPairs(&cleanPairs); + processAllOverlappingPairs(&cleanPairs,dispatcher); } -void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy) + +void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) { class RemovePairCallback : public btOverlapCallback @@ -166,12 +125,346 @@ void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseP RemovePairCallback removeCallback(proxy); - processAllOverlappingPairs(&removeCallback); + processAllOverlappingPairs(&removeCallback,dispatcher); } -void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback) + + +btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + gFindPairs++; + if(proxy0>proxy1) btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + if (hash >= m_hashTable.size()) + { + return NULL; + } + + int index = m_hashTable[hash]; + while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if (index == BT_NULL_PAIR) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; +} + +//#include + +void btHashedOverlappingPairCache::growTables() +{ + + int newCapacity = m_overlappingPairArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_NULL_PAIR; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_NULL_PAIR; + } + + for(i=0;igetUid(); + int proxyId2 = pair.m_pProxy1->getUid(); + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + m_next[i] = m_hashTable[hashValue]; + m_hashTable[hashValue] = i; + } + + + } +} + +btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + if(proxy0>proxy1) btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair != NULL) + { + return pair; + } + /*for(int i=0;i%u\r\n",proxyId1,proxyId2); + internalFindPair(proxy0, proxy1, hash); + } + }*/ + int count = m_overlappingPairArray.size(); + int oldCapacity = m_overlappingPairArray.capacity(); + void* mem = &m_overlappingPairArray.expand(); + int newCapacity = m_overlappingPairArray.capacity(); + + if (oldCapacity < newCapacity) + { + growTables(); + //hash with new capacity + hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + } + + pair = new (mem) btBroadphasePair(*proxy0,*proxy1); +// pair->m_pProxy0 = proxy0; +// pair->m_pProxy1 = proxy1; + pair->m_algorithm = 0; + pair->m_userInfo = 0; + + + m_next[count] = m_hashTable[hash]; + m_hashTable[hash] = count; + + return pair; +} + + + +void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) +{ + gRemovePairs++; + if(proxy0>proxy1) btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair == NULL) + { + return 0; + } + + cleanOverlappingPair(*pair,dispatcher); + + void* userData = pair->m_userInfo; + + btAssert(pair->m_pProxy0->getUid() == proxyId1); + btAssert(pair->m_pProxy1->getUid() == proxyId2); + + int pairIndex = int(pair - &m_overlappingPairArray[0]); + btAssert(pairIndex < m_overlappingPairArray.size()); + + // Remove the pair from the hash table. + int index = m_hashTable[hash]; + btAssert(index != BT_NULL_PAIR); + + int previous = BT_NULL_PAIR; + while (index != pairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == pairIndex); + m_next[previous] = m_next[pairIndex]; + } + else + { + m_hashTable[hash] = m_next[pairIndex]; + } + + // We now move the last pair into spot of the + // pair being removed. We need to fix the hash + // table indices to support the move. + + int lastPairIndex = m_overlappingPairArray.size() - 1; + + // If the removed pair is the last pair, we are done. + if (lastPairIndex == pairIndex) + { + m_overlappingPairArray.pop_back(); + return userData; + } + + // Remove the last pair from the hash table. + const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; + /* missing swap here too, Nat. */ + int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1)); + + index = m_hashTable[lastHash]; + btAssert(index != BT_NULL_PAIR); + + previous = BT_NULL_PAIR; + while (index != lastPairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == lastPairIndex); + m_next[previous] = m_next[lastPairIndex]; + } + else + { + m_hashTable[lastHash] = m_next[lastPairIndex]; + } + + // Copy the last pair into the remove pair's spot. + m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; + + // Insert the last pair into the hash table + m_next[pairIndex] = m_hashTable[lastHash]; + m_hashTable[lastHash] = pairIndex; + + m_overlappingPairArray.pop_back(); + + return userData; +} +//#include + +void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + +// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); + for (i=0;iprocessOverlap(*pair)) + { + removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); + + gOverlappingPairs--; + } else + { + i++; + } + } +} + + + +void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher ) +{ + if (!hasDeferredRemoval()) + { + btBroadphasePair findPair(*proxy0,*proxy1); + + int findIndex = m_overlappingPairArray.findLinearSearch(findPair); + if (findIndex < m_overlappingPairArray.size()) + { + gOverlappingPairs--; + btBroadphasePair& pair = m_overlappingPairArray[findIndex]; + void* userData = pair.m_userInfo; + cleanOverlappingPair(pair,dispatcher); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); + m_overlappingPairArray.pop_back(); + return userData; + } + } + + return 0; +} + + + + + + + + +btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + //don't add overlap with own + assert(proxy0 != proxy1); + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + void* mem = &m_overlappingPairArray.expand(); + btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + gOverlappingPairs++; + gAddedPairs++; + return pair; + +} + +///this findPair becomes really slow. Either sort the list to speedup the query, or +///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. +///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) +///Also we can use a 2D bitmap, which can be useful for a future GPU implementation + btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + btBroadphasePair tmpPair(*proxy0,*proxy1); + int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); + + if (findIndex < m_overlappingPairArray.size()) + { + //assert(it != m_overlappingPairSet.end()); + btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; + return pair; + } + return 0; +} + + + + + + + + + + +//#include + +void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) { int i; @@ -182,9 +475,9 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb btBroadphasePair* pair = &m_overlappingPairArray[i]; if (callback->processOverlap(*pair)) { - cleanOverlappingPair(*pair); + cleanOverlappingPair(*pair,dispatcher); - m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); m_overlappingPairArray.pop_back(); gOverlappingPairs--; } else @@ -194,3 +487,93 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb } } + + + +btSortedOverlappingPairCache::btSortedOverlappingPairCache(): + m_blockedForChanges(false), + m_hasDeferredRemoval(true), + m_overlapFilterCallback(0) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); +} + +btSortedOverlappingPairCache::~btSortedOverlappingPairCache() +{ + //todo/test: show we erase/delete data, or is it automatic +} + +void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) +{ + if (pair.m_algorithm) + { + { + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + pair.m_algorithm=0; + gRemovePairs--; + } + } +} + + +void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + + +void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index a81fe3264df..66679bd218a 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -1,4 +1,3 @@ - /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -20,9 +19,13 @@ subject to the following restrictions: #include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCallback.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; + +typedef btAlignedObjectArray btBroadphasePairArray; struct btOverlapCallback { @@ -30,6 +33,7 @@ struct btOverlapCallback {} //return true for deletion of the pair virtual bool processOverlap(btBroadphasePair& pair) = 0; + }; struct btOverlapFilterCallback @@ -40,38 +44,261 @@ struct btOverlapFilterCallback virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; }; -///btOverlappingPairCache maintains the objects with overlapping AABB + + + + + + +extern int gRemovePairs; +extern int gAddedPairs; +extern int gFindPairs; + +const int BT_NULL_PAIR=0xffffffff; + +///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. +///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. +class btOverlappingPairCache : public btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor + + virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0; + + virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0; + + virtual btBroadphasePairArray& getOverlappingPairArray() = 0; + + virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; + + virtual int getNumOverlappingPairs() const = 0; + + virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; + + virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; + + virtual bool hasDeferredRemoval() = 0; + +}; + +/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com +class btHashedOverlappingPairCache : public btOverlappingPairCache +{ + btBroadphasePairArray m_overlappingPairArray; + btOverlapFilterCallback* m_overlapFilterCallback; + bool m_blockedForChanges; + + +public: + btHashedOverlappingPairCache(); + virtual ~btHashedOverlappingPairCache(); + + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + // Add a pair and return the new pair. If the pair already exists, + // no new pair is created and the old one is returned. + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + gAddedPairs++; + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + return internalAddPair(proxy0,proxy1); + } + + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); + + int GetCount() const { return m_overlappingPairArray.size(); } +// btBroadphasePair* GetPairs() { return m_pairs; } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } +private: + + btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + void growTables(); + + SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) + { + return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; + } + + /* + // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm + // This assumes proxyId1 and proxyId2 are 16-bit. + SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) + { + int key = (proxyId2 << 16) | proxyId1; + key = ~key + (key << 15); + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key * 2057; + key = key ^ (key >> 16); + return key; + } + */ + + + + SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) + { + int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); + // Thomas Wang's hash + + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return static_cast(key); + } + + + + + + SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) + { + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + #endif + + int index = m_hashTable[hash]; + + while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if ( index == BT_NULL_PAIR ) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; + } + + virtual bool hasDeferredRemoval() + { + return false; + } + +public: + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + +}; + + + + +///btSortedOverlappingPairCache maintains the objects with overlapping AABB ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase -class btOverlappingPairCache : public btBroadphaseInterface +class btSortedOverlappingPairCache : public btOverlappingPairCache { protected: //avoid brute-force finding all the time - btAlignedObjectArray m_overlappingPairArray; - + btBroadphasePairArray m_overlappingPairArray; + //during the dispatch, check that user doesn't destroy/create proxy bool m_blockedForChanges; + + ///by default, do the removal during the pair traversal + bool m_hasDeferredRemoval; //if set, use the callback instead of the built in filter in needBroadphaseCollision btOverlapFilterCallback* m_overlapFilterCallback; + public: - btOverlappingPairCache(); - virtual ~btOverlappingPairCache(); + btSortedOverlappingPairCache(); + virtual ~btSortedOverlappingPairCache(); - virtual void processAllOverlappingPairs(btOverlapCallback*); + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); - void removeOverlappingPair(btBroadphasePair& pair); + void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); - void cleanOverlappingPair(btBroadphasePair& pair); + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); - void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - void cleanProxyFromPairs(btBroadphaseProxy* proxy); + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy); + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const @@ -84,10 +311,19 @@ class btOverlappingPairCache : public btBroadphaseInterface return collides; } - + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + - virtual void refreshOverlappingPairs() =0; btBroadphasePair* getOverlappingPairArrayPtr() { @@ -114,7 +350,88 @@ class btOverlappingPairCache : public btBroadphaseInterface m_overlapFilterCallback = callback; } + virtual bool hasDeferredRemoval() + { + return m_hasDeferredRemoval; + } + + }; + + + +///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing. +class btNullPairCache : public btOverlappingPairCache +{ + + btBroadphasePairArray m_overlappingPairArray; + +public: + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual int getNumOverlappingPairs() const + { + return 0; + } + + virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) + { + } + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) + { + } + + virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual bool hasDeferredRemoval() + { + return true; + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) + { + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) + { + } + + +}; + + #endif //OVERLAPPING_PAIR_CACHE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h new file mode 100644 index 00000000000..9c7b6f81367 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h @@ -0,0 +1,40 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef OVERLAPPING_PAIR_CALLBACK_H +#define OVERLAPPING_PAIR_CALLBACK_H + +class btDispatcher; +struct btBroadphasePair; + +///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. +class btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0; + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0; + +}; + +#endif //OVERLAPPING_PAIR_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp new file mode 100644 index 00000000000..a30bd1fd9e1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @@ -0,0 +1,1025 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btQuantizedBvh.h" + +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" + + +btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false), + //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) + m_traversalMode(TRAVERSAL_STACKLESS) + //m_traversalMode(TRAVERSAL_RECURSIVE) + ,m_subtreeHeaderCount(0) //PCK: add this line +{ + +} + + + + + +void btQuantizedBvh::buildInternal() +{ + ///assumes that caller filled in the m_quantizedLeafNodes + m_useQuantization = true; + int numLeafNodes = 0; + + if (m_useQuantization) + { + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); +} + + + +///just for debugging, to visualize the individual patches/subtrees +#ifdef DEBUG_PATCH_COLORS +btVector3 color[4]= +{ + btVector3(255,0,0), + btVector3(0,255,0), + btVector3(0,0,255), + btVector3(0,255,255) +}; +#endif //DEBUG_PATCH_COLORS + + + +void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +{ + //enlarge the AABB to avoid division by zero when initializing the quantization values + btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); + m_bvhAabbMin = bvhAabbMin - clampValue; + m_bvhAabbMax = bvhAabbMax + clampValue; + btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; + m_useQuantization = true; +} + + + + +btQuantizedBvh::~btQuantizedBvh() +{ +} + +#ifdef DEBUG_TREE_BUILDING +int gStackDepth = 0; +int gMaxStackDepth = 0; +#endif //DEBUG_TREE_BUILDING + +void btQuantizedBvh::buildTree (int startIndex,int endIndex) +{ +#ifdef DEBUG_TREE_BUILDING + gStackDepth++; + if (gStackDepth > gMaxStackDepth) + gMaxStackDepth = gStackDepth; +#endif //DEBUG_TREE_BUILDING + + + int splitAxis, splitIndex, i; + int numIndices =endIndex-startIndex; + int curIndex = m_curNodeIndex; + + assert(numIndices>0); + + if (numIndices==1) + { +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); + + m_curNodeIndex++; + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + splitAxis = calcSplittingAxis(startIndex,endIndex); + + splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); + + int internalNodeIndex = m_curNodeIndex; + + setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin); + setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax); + + for (i=startIndex;im_escapeIndex; + + int leftChildNodexIndex = m_curNodeIndex; + + //build left child tree + buildTree(startIndex,splitIndex); + + int rightChildNodexIndex = m_curNodeIndex; + //build right child tree + buildTree(splitIndex,endIndex); + +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + int escapeIndex = m_curNodeIndex - curIndex; + + if (m_useQuantization) + { + //escapeIndex is the number of nodes of this subtree + const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); + const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; + if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) + { + updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); + } + } + + setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); + +} + +void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) +{ + btAssert(m_useQuantization); + + btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; + int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); + int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; + int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); + int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(leftChildNode); + subtree.m_rootNodeIndex = leftChildNodexIndex; + subtree.m_subtreeSize = leftSubTreeSize; + } + + if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(rightChildNode); + subtree.m_rootNodeIndex = rightChildNodexIndex; + subtree.m_subtreeSize = rightSubTreeSize; + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); +} + + +int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) +{ + int i; + int splitIndex =startIndex; + int numIndices = endIndex - startIndex; + btScalar splitValue; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + for (i=startIndex;i splitValue) + { + //swap + swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + (void)unbal; + btAssert(!unbal); + + return splitIndex; +} + + +int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex) +{ + int i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + int numIndices = endIndex-startIndex; + + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (aabbOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +/* +///this was the original recursive traversal, before we optimized towards stackless traversal +void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); + if (aabbOverlap) + { + isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); + if (isLeafNode) + { + nodeCallback->processNode(rootNode); + } else + { + walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); + walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); + } + } + +} +*/ + +void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); + isLeafNode = currentNode->isLeafNode(); + + //PCK: unsigned instead of bool + if (aabbOverlap != 0) + { + if (isLeafNode) + { + nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex()); + } else + { + //process left and right children + const btQuantizedBvhNode* leftChildNode = currentNode+1; + walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + + const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); + walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + } + } +} + + + + + +void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned boxBoxOverlap = 0; + unsigned rayBoxOverlap = 0; + + btScalar lambda_max = 1.0; +#define RAYAABB2 +#ifdef RAYAABB2 + btVector3 rayFrom = raySource; + btVector3 rayDirection = (rayTarget-raySource); + rayDirection.normalize (); + lambda_max = rayDirection.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0]; + rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1]; + rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2]; + unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0}; +#endif + + /* Quick pruning by quantized box */ + btVector3 rayAabbMin = raySource; + btVector3 rayAabbMax = raySource; + rayAabbMin.setMin(rayTarget); + rayAabbMax.setMax(rayTarget); + + /* Add box cast extents to bounding box */ + rayAabbMin += aabbMin; + rayAabbMax += aabbMax; + + unsigned short int quantizedQueryAabbMin[3]; + unsigned short int quantizedQueryAabbMax[3]; + quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0); + quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1); + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + assert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + // only interested if this is closer than any previous hit + btScalar param = 1.0; + rayBoxOverlap = 0; + boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + if (boxBoxOverlap) + { + btVector3 bounds[2]; + bounds[0] = unQuantize(rootNode->m_quantizedAabbMin); + bounds[1] = unQuantize(rootNode->m_quantizedAabbMax); + /* Add box cast extents */ + bounds[0] += aabbMin; + bounds[1] += aabbMax; + btVector3 normal; +#if 0 + bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max); + bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal); + if (ra2 != ra) + { + printf("functions don't match\n"); + } +#endif +#ifdef RAYAABB2 + ///careful with this check: need to check division by zero (above) and fix the unQuantize method + ///thanks Joerg/hiker for the reproduction case! + ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + + rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max); +#else + rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal); +#endif + } + + if (isLeafNode && rayBoxOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + assert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +//This traversal can be called from Playstation 3 SPU +void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + int i; + + + for (i=0;im_SubtreeHeaders.size();i++) + { + const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) + { + walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + subtree.m_rootNodeIndex, + subtree.m_rootNodeIndex+subtree.m_subtreeSize); + } + } +} + + +void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const +{ + bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS; + if (fast_path) + { + walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex); + } else { + /* Otherwise fallback to AABB overlap test */ + btVector3 aabbMin = raySource; + btVector3 aabbMax = raySource; + aabbMin.setMin(rayTarget); + aabbMax.setMax(rayTarget); + reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax); + } +} + + +void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS; + if (fast_path) + { + walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } else { + /* Slow path: + Construct the bounding box for the entire box cast and send that down the tree */ + btVector3 qaabbMin = raySource; + btVector3 qaabbMax = raySource; + qaabbMin.setMin(rayTarget); + qaabbMax.setMax(rayTarget); + qaabbMin += aabbMin; + qaabbMax += aabbMax; + reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax); + } +} + + +void btQuantizedBvh::swapLeafNodes(int i,int splitIndex) +{ + if (m_useQuantization) + { + btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; + m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; + m_quantizedLeafNodes[splitIndex] = tmp; + } else + { + btOptimizedBvhNode tmp = m_leafNodes[i]; + m_leafNodes[i] = m_leafNodes[splitIndex]; + m_leafNodes[splitIndex] = tmp; + } +} + +void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) +{ + if (m_useQuantization) + { + m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; + } else + { + m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; + } +} + +//PCK: include +#include + +//PCK: consts +static const unsigned BVH_ALIGNMENT = 16; +static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; + +static const unsigned BVH_ALIGNMENT_BLOCKS = 2; + + + +unsigned int btQuantizedBvh::getAlignmentSerializationPadding() +{ + return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; +} + +unsigned btQuantizedBvh::calculateSerializeBufferSize() +{ + unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding(); + baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + if (m_useQuantization) + { + return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); + } + return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); +} + +bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) +{ + assert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + +/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + ///check alignedment for buffer? + btAssert(0); + return false; + } +*/ + + btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer; + + // construct the class so the virtual function table, etc will be set up + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (targetBvh) btQuantizedBvh; + + if (i_swapEndian) + { + targetBvh->m_curNodeIndex = static_cast(btSwapEndian(m_curNodeIndex)); + + + btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); + btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); + btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); + + targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); + targetBvh->m_subtreeHeaderCount = static_cast(btSwapEndian(m_subtreeHeaderCount)); + } + else + { + targetBvh->m_curNodeIndex = m_curNodeIndex; + targetBvh->m_bvhAabbMin = m_bvhAabbMin; + targetBvh->m_bvhAabbMax = m_bvhAabbMax; + targetBvh->m_bvhQuantization = m_bvhQuantization; + targetBvh->m_traversalMode = m_traversalMode; + targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; + } + + targetBvh->m_useQuantization = m_useQuantization; + + unsigned char *nodeData = (unsigned char *)targetBvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = m_curNodeIndex; + + if (m_useQuantization) + { + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; + + + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex)); + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart)); + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex)); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize)); + } + } + else + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); + targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i]; + } + } + + nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + + return true; +} + +btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +{ + + if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + return NULL; + } + btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer; + + if (i_swapEndian) + { + bvh->m_curNodeIndex = static_cast(btSwapEndian(bvh->m_curNodeIndex)); + + btUnSwapVector3Endian(bvh->m_bvhAabbMin); + btUnSwapVector3Endian(bvh->m_bvhAabbMax); + btUnSwapVector3Endian(bvh->m_bvhQuantization); + + bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); + bvh->m_subtreeHeaderCount = static_cast(btSwapEndian(bvh->m_subtreeHeaderCount)); + } + + unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize(); + btAssert(calculatedBufSize <= i_dataBufferSize); + + if (calculatedBufSize > i_dataBufferSize) + { + return NULL; + } + + unsigned char *nodeData = (unsigned char *)bvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = bvh->m_curNodeIndex; + + // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (bvh) btQuantizedBvh(*bvh, false); + + if (bvh->m_useQuantization) + { + bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex)); + bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart)); + bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) + { + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex)); + bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize)); + } + } + + return bvh; +} + +// Constructor that prevents btVector3's default constructor from being called +btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) : +m_bvhAabbMin(self.m_bvhAabbMin), +m_bvhAabbMax(self.m_bvhAabbMax), +m_bvhQuantization(self.m_bvhQuantization) +{ + + +} + + + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h new file mode 100644 index 00000000000..8a149b533fa --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -0,0 +1,486 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef QUANTIZED_BVH_H +#define QUANTIZED_BVH_H + +//#define DEBUG_CHECK_DEQUANTIZATION 1 +#ifdef DEBUG_CHECK_DEQUANTIZATION +#ifdef __SPU__ +#define printf spu_printf +#endif //__SPU__ + +#include +#include +#endif //DEBUG_CHECK_DEQUANTIZATION + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" + + +//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp + + +//Note: currently we have 16 bytes per quantized node +#define MAX_SUBTREE_SIZE_IN_BYTES 2048 + +// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one +// actually) triangles each (since the sign bit is reserved +#define MAX_NUM_PARTS_IN_BITS 10 + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrTriangleIndex; + + bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrTriangleIndex >= 0); + } + int getEscapeIndex() const + { + btAssert(!isLeafNode()); + return -m_escapeIndexOrTriangleIndex; + } + int getTriangleIndex() const + { + btAssert(isLeafNode()); + // Get only the lower bits where the triangle index is stored + return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); + } + int getPartId() const + { + btAssert(isLeafNode()); + // Get only the highest bits where the part index is stored + return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); + } +} +; + +/// btOptimizedBvhNode contains both internal and leaf node information. +/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. +ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //32 bytes + btVector3 m_aabbMinOrg; + btVector3 m_aabbMaxOrg; + + //4 + int m_escapeIndex; + + //8 + //for child nodes + int m_subPart; + int m_triangleIndex; + int m_padding[5];//bad, due to alignment + + +}; + + +///btBvhSubtreeInfo provides info to gather a subtree of limited size +ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo +{ +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes, points to the root of the subtree + int m_rootNodeIndex; + //4 bytes + int m_subtreeSize; + int m_padding[3]; + + btBvhSubtreeInfo() + { + //memset(&m_padding[0], 0, sizeof(m_padding)); + } + + + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) + { + m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; + m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; + m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; + m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; + m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; + m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; + } +} +; + + +class btNodeOverlapCallback +{ +public: + virtual ~btNodeOverlapCallback() {}; + + virtual void processNode(int subPart, int triangleIndex) = 0; +}; + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" + + + +///for code readability: +typedef btAlignedObjectArray NodeArray; +typedef btAlignedObjectArray QuantizedNodeArray; +typedef btAlignedObjectArray BvhSubtreeInfoArray; + + +///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. +///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. +///It is recommended to use quantization for better performance and lower memory requirements. +ATTRIBUTE_ALIGNED16(class) btQuantizedBvh +{ +protected: + + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + + QuantizedNodeArray m_quantizedLeafNodes; + + QuantizedNodeArray m_quantizedContiguousNodes; + + int m_curNodeIndex; + + + //quantization data + bool m_useQuantization; + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + enum btTraversalMode + { + TRAVERSAL_STACKLESS = 0, + TRAVERSAL_STACKLESS_CACHE_FRIENDLY, + TRAVERSAL_RECURSIVE + }; +protected: + + btTraversalMode m_traversalMode; + + BvhSubtreeInfoArray m_SubtreeHeaders; + + //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray + int m_subtreeHeaderCount; + + + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) + ///this might be refactored into a virtual, it is usually not calculated at run-time + void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; + + } + } + void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; + } + } + + btVector3 getAabbMin(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMinOrg; + + } + btVector3 getAabbMax(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMaxOrg; + + } + + + void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) + { + if (m_useQuantization) + { + m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; + } + else + { + m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; + } + + } + + void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) + { + if (m_useQuantization) + { + unsigned short int quantizedAabbMin[3]; + unsigned short int quantizedAabbMax[3]; + quantize(quantizedAabbMin,newAabbMin,0); + quantize(quantizedAabbMax,newAabbMax,1); + for (int i=0;i<3;i++) + { + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; + + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; + + } + } else + { + //non-quantized + m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); + m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); + } + } + + void swapLeafNodes(int firstIndex,int secondIndex); + + void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + +protected: + + + + void buildTree (int startIndex,int endIndex); + + int calcSplittingAxis(int startIndex,int endIndex); + + int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); + + void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; + void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; + + ///tree traversal designed for small-memory processors like PS3 SPU + void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; + + +#define USE_BANCHLESS 1 +#ifdef USE_BANCHLESS + //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) + SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + return static_cast(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0)); + } +#else + SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } +#endif //USE_BANCHLESS + + void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); + +public: + btQuantizedBvh(); + + virtual ~btQuantizedBvh(); + + + ///***************************************** expert/internal use only ************************* + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); + QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; } + ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized + void buildInternal(); + ///***************************************** expert/internal use only ************************* + + void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const; + void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const; + + SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const + { + + btAssert(m_useQuantization); + + btAssert(point.getX() <= m_bvhAabbMax.getX()); + btAssert(point.getY() <= m_bvhAabbMax.getY()); + btAssert(point.getZ() <= m_bvhAabbMax.getZ()); + + btAssert(point.getX() >= m_bvhAabbMin.getX()); + btAssert(point.getY() >= m_bvhAabbMin.getY()); + btAssert(point.getZ() >= m_bvhAabbMin.getZ()); + + btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization; + ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative + ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly) + ///todo: double-check this + if (isMax) + { + out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); + out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1)); + } else + { + out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe)); + out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe)); + } + + +#ifdef DEBUG_CHECK_DEQUANTIZATION + btVector3 newPoint = unQuantize(out); + if (isMax) + { + if (newPoint.getX() < point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() < point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() < point.getZ()) + { + + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } else + { + if (newPoint.getX() > point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() > point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() > point.getZ()) + { + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } +#endif //DEBUG_CHECK_DEQUANTIZATION + + } + + + SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const + { + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point2); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + quantize(out,clampedPoint,isMax); + + } + + SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const + { + btVector3 vecOut; + vecOut.setValue( + (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), + (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), + (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); + vecOut += m_bvhAabbMin; + return vecOut; + } + + ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. + void setTraversalMode(btTraversalMode traversalMode) + { + m_traversalMode = traversalMode; + } + + + SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() + { + return m_quantizedContiguousNodes; + } + + + SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() + { + return m_SubtreeHeaders; + } + + + /////Calculate space needed to store BVH for serialization + unsigned calculateSerializeBufferSize(); + + /// Data buffer MUST be 16 byte aligned + virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + static unsigned int getAlignmentSerializationPadding(); + + SIMD_FORCE_INLINE bool isQuantized() + { + return m_useQuantization; + } + +private: + // Special "copy" constructor that allows for in-place deserialization + // Prevents btVector3's default constructor from being called, but doesn't inialize much else + // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) + btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory); + +} +; + + +#endif //QUANTIZED_BVH_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index 30bcbe0c5f1..a57952ffa06 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -14,83 +14,84 @@ subject to the following restrictions: */ #include "btSimpleBroadphase.h" -#include -#include +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" #include "LinearMath/btMatrix3x3.h" #include +extern int gOverlappingPairs; void btSimpleBroadphase::validate() { - for (int i=0;i=0;i--) + if (m_ownsPairCache) { - BP_Proxy* proxy = m_pProxies[i]; - destroyProxy(proxy); + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); } - */ } -btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask) +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) { - if (m_numProxies >= m_maxProxies) + if (m_numHandles >= m_maxHandles) { - assert(0); + btAssert(0); return 0; //should never happen, but don't let the game crash ;-) } - assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]); + assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); - int freeIndex= m_freeProxies[m_firstFreeProxy]; - btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); - m_firstFreeProxy++; - - btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; - - int index = int(proxy - proxy1); - btAssert(index == freeIndex); - - m_pProxies[m_numProxies] = proxy; - m_numProxies++; - //validate(); + int newHandleIndex = allocHandle(); + btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); return proxy; } @@ -124,34 +125,19 @@ protected: }; }; -void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg) +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) { - int i; - btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); - btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; - - int index = int(proxy0 - proxy1); - btAssert (index < m_maxProxies); - m_freeProxies[--m_firstFreeProxy] = index; + freeHandle(proxy0); + + m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); - removeOverlappingPairsContainingProxy(proxyOrg); - - for (i=0;im_min = aabbMin; @@ -186,37 +172,129 @@ public: } }; -void btSimpleBroadphase::refreshOverlappingPairs() +void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) { //first check for new overlapping pairs int i,j; - for (i=0;i= 0) { - btBroadphaseProxy* proxy0 = m_pProxies[i]; - for (j=i+1;jfindPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } else + { + if (!m_pairCache->hasDeferredRemoval()) + { + if ( m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } } } + } + + if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: +#define CLEAN_INVALID_PAIRS 1 +#ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif//CLEAN_INVALID_PAIRS } } - - - CheckOverlapCallback checkOverlap; - - processAllOverlappingPairs(&checkOverlap); - - } +bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + return aabbOverlap(p0,p1); +} + + + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index fb155e7047c..e2ebb825725 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -24,35 +24,69 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy { btVector3 m_min; btVector3 m_max; + int m_nextFree; + +// int m_handleId; + btSimpleBroadphaseProxy() {}; - btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) - :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), + btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) + :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy), m_min(minpt),m_max(maxpt) { (void)shapeType; } + + SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} + SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} + + + }; -///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks -class btSimpleBroadphase : public btOverlappingPairCache +///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead. +///It is a brute force aabb culling broadphase based on O(n^2) aabb checks +class btSimpleBroadphase : public btBroadphaseInterface { protected: - btSimpleBroadphaseProxy* m_proxies; - int* m_freeProxies; - int m_firstFreeProxy; - - btSimpleBroadphaseProxy** m_pProxies; - int m_numProxies; - + int m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + btSimpleBroadphaseProxy* m_pHandles; // handles pool + + void* m_pHandlesRawPtr; + int m_firstFreeHandle; // free handles list + + int allocHandle() + { + btAssert(m_numHandles < m_maxHandles); + int freeHandle = m_firstFreeHandle; + m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); + m_numHandles++; + return freeHandle; + } + + void freeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy-m_pHandles); + btAssert(handle >= 0 && handle < m_maxHandles); + + proxy->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; + } + + btOverlappingPairCache* m_pairCache; + bool m_ownsPairCache; + + int m_invalidPair; - int m_maxProxies; inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) @@ -67,26 +101,48 @@ protected: protected: - virtual void refreshOverlappingPairs(); + + public: - btSimpleBroadphase(int maxProxies=16384); + btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); virtual ~btSimpleBroadphase(); static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - virtual void destroyProxy(btBroadphaseProxy* proxy); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - - + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-1e30f,-1e30f,-1e30f); + aabbMax.setValue(1e30f,1e30f,1e30f); + } + virtual void printStats() + { +// printf("btSimpleBroadphase.h\n"); +// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + } }; diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt index e565bf7edea..d77ca6444c7 100644 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -5,56 +5,149 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletCollision BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btAxisSweep3.h BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btBroadphaseProxy.h BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btCollisionAlgorithm.h BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btDispatcher.h + BroadphaseCollision/btDbvtBroadphase.cpp + BroadphaseCollision/btDbvtBroadphase.h + BroadphaseCollision/btDbvt.cpp + BroadphaseCollision/btDbvt.h + BroadphaseCollision/btMultiSapBroadphase.cpp + BroadphaseCollision/btMultiSapBroadphase.h BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btOverlappingPairCache.h + BroadphaseCollision/btOverlappingPairCallback.h + BroadphaseCollision/btQuantizedBvh.cpp + BroadphaseCollision/btQuantizedBvh.h BroadphaseCollision/btSimpleBroadphase.cpp + BroadphaseCollision/btSimpleBroadphase.h CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionDispatcher.h CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionObject.h CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCollisionWorld.h CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.h CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.h + CollisionDispatch/btDefaultCollisionConfiguration.cpp + CollisionDispatch/btDefaultCollisionConfiguration.h CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.h + CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxCollisionAlgorithm.h + CollisionDispatch/btBoxBoxDetector.cpp + CollisionDispatch/btBoxBoxDetector.h CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.h + CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + CollisionDispatch/btConvexPlaneCollisionAlgorithm.h + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.h CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.h CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.h CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btManifoldResult.h CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btSimulationIslandManager.h CollisionDispatch/btUnionFind.cpp + CollisionDispatch/btUnionFind.h + CollisionDispatch/SphereTriangleDetector.cpp + CollisionDispatch/SphereTriangleDetector.h CollisionShapes/btBoxShape.cpp + CollisionShapes/btBoxShape.h CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btBvhTriangleMeshShape.h + CollisionShapes/btCapsuleShape.cpp + CollisionShapes/btCapsuleShape.h CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCollisionShape.h CollisionShapes/btCompoundShape.cpp + CollisionShapes/btCompoundShape.h CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConcaveShape.h CollisionShapes/btConeShape.cpp + CollisionShapes/btConeShape.h CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexHullShape.h CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvexShape.h + CollisionShapes/btConvexInternalShape.cpp + CollisionShapes/btConvexInternalShape.h CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btConvexTriangleMeshShape.h CollisionShapes/btCylinderShape.cpp + CollisionShapes/btCylinderShape.h CollisionShapes/btEmptyShape.cpp + CollisionShapes/btEmptyShape.h + CollisionShapes/btHeightfieldTerrainShape.cpp + CollisionShapes/btHeightfieldTerrainShape.h CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMinkowskiSumShape.h + CollisionShapes/btMaterial.h + CollisionShapes/btMultimaterialTriangleMeshShape.cpp + CollisionShapes/btMultimaterialTriangleMeshShape.h CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btMultiSphereShape.h CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btOptimizedBvh.h CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btPolyhedralConvexShape.h + CollisionShapes/btScaledBvhTriangleMeshShape.cpp + CollisionShapes/btScaledBvhTriangleMeshShape.h CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btTetrahedronShape.h CollisionShapes/btSphereShape.cpp + CollisionShapes/btSphereShape.h + CollisionShapes/btShapeHull.h + CollisionShapes/btShapeHull.cpp CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStaticPlaneShape.h CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btStridingMeshInterface.h CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleCallback.h CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleBuffer.h CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleIndexVertexArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.cpp CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMesh.h CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btTriangleMeshShape.h + CollisionShapes/btUniformScalingShape.cpp + CollisionShapes/btUniformScalingShape.h NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btContinuousConvexCollision.h NarrowPhaseCollision/btGjkEpa.cpp + NarrowPhaseCollision/btGjkEpa.h + NarrowPhaseCollision/btGjkEpa2.cpp + NarrowPhaseCollision/btGjkEpa2.h NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btConvexCast.h NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.h NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btGjkPairDetector.h NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btPersistentManifold.h NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btRaycastCallback.h NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.h NarrowPhaseCollision/btVoronoiSimplexSolver.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.h ) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index 81133670f0c..f6c1e32ac7c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -26,7 +26,7 @@ m_triangle(triangle) } -void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) { (void)debugDraw; @@ -42,7 +42,16 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) { - output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + if (swapResults) + { + btVector3 normalOnB = transformB.getBasis()*normal; + btVector3 normalOnA = -normalOnB; + btVector3 pointOnA = transformB*point+normalOnB*depth; + output.addContactPoint(normalOnA,pointOnA,depth); + } else + { + output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + } } } @@ -53,6 +62,8 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res // See also geometrictools.com // Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest); + btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { btVector3 diff = p - from; btVector3 v = to - from; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h index b32806a6846..26dabaa480e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_DETECTOR_H #define SPHERE_TRIANGLE_DETECTOR_H -#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btPoint3.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "LinearMath/btPoint3.h" class btSphereShape; @@ -28,7 +28,7 @@ class btTriangleShape; /// sphere-triangle to match the btDiscreteCollisionDetectorInterface struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface { - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp new file mode 100644 index 00000000000..cd0c028012c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp @@ -0,0 +1,85 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btBoxBoxDetector.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); + m_ownManifold = true; + } +} + +btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + btCollisionObject* col0 = body0; + btCollisionObject* col1 = body1; + btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape(); + btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape(); + + + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); +#ifndef USE_PERSISTENT_CONTACTS + m_manifoldPtr->clearManifold(); +#endif //USE_PERSISTENT_CONTACTS + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = 1e30f; + input.m_transformA = body0->getWorldTransform(); + input.m_transformB = body1->getWorldTransform(); + + btBoxBoxDetector detector(box0,box1); + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + +#ifdef USE_PERSISTENT_CONTACTS + // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } +#endif //USE_PERSISTENT_CONTACTS + +} + +btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h new file mode 100644 index 00000000000..35afaf175a1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BOX_BOX__COLLISION_ALGORITHM_H +#define BOX_BOX__COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; + +///box-box collision detection +class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btBoxBoxCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btBoxBoxCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //BOX_BOX__COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp new file mode 100644 index 00000000000..45ebff5dc45 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp @@ -0,0 +1,683 @@ + +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + Bullet Continuous Collision Detection and Physics Library + Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///ODE box-box collision detection is adapted to work with Bullet + +#include "btBoxBoxDetector.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" + +#include +#include + +btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2) +: m_box1(box1), +m_box2(box2) +{ + +} + + +// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and +// generate contact points. this returns 0 if there is no contact otherwise +// it returns the number of contacts generated. +// `normal' returns the contact normal. +// `depth' returns the maximum penetration depth along that normal. +// `return_code' returns a number indicating the type of contact that was +// detected: +// 1,2,3 = box 2 intersects with a face of box 1 +// 4,5,6 = box 1 intersects with a face of box 2 +// 7..15 = edge-edge contact +// `maxc' is the maximum number of contacts allowed to be generated, i.e. +// the size of the `contact' array. +// `contact' and `skip' are the contact array information provided to the +// collision functions. this function only fills in the position and depth +// fields. +struct dContactGeom; +#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) +#define dInfinity FLT_MAX + + +/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); } +PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); } +PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); } +*/ +static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); } +static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); } +static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); } +#define dMULTIPLYOP1_331(A,op,B,C) \ +{\ + (A)[0] op dDOT41((B),(C)); \ + (A)[1] op dDOT41((B+1),(C)); \ + (A)[2] op dDOT41((B+2),(C)); \ +} + +#define dMULTIPLYOP0_331(A,op,B,C) \ +{ \ + (A)[0] op dDOT((B),(C)); \ + (A)[1] op dDOT((B+4),(C)); \ + (A)[2] op dDOT((B+8),(C)); \ +} + +#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) +#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) + +typedef btScalar dMatrix3[4*3]; + +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta); +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta) +{ + btVector3 p; + p[0] = pb[0] - pa[0]; + p[1] = pb[1] - pa[1]; + p[2] = pb[2] - pa[2]; + btScalar uaub = dDOT(ua,ub); + btScalar q1 = dDOT(ua,p); + btScalar q2 = -dDOT(ub,p); + btScalar d = 1-uaub*uaub; + if (d <= btScalar(0.0001f)) { + // @@@ this needs to be made more robust + *alpha = 0; + *beta = 0; + } + else { + d = 1.f/d; + *alpha = (q1 + uaub*q2)*d; + *beta = (uaub*q1 + q2)*d; + } +} + + + +// find all the intersection points between the 2D rectangle with vertices +// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), +// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). +// +// the intersection points are returned as x,y pairs in the 'ret' array. +// the number of intersection points is returned by the function (this will +// be in the range 0 to 8). + +static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16]) +{ + // q (and r) contain nq (and nr) coordinate points for the current (and + // chopped) polygons + int nq=4,nr=0; + btScalar buffer[16]; + btScalar *q = p; + btScalar *r = ret; + for (int dir=0; dir <= 1; dir++) { + // direction notation: xy[0] = x axis, xy[1] = y axis + for (int sign=-1; sign <= 1; sign += 2) { + // chop q along the line xy[dir] = sign*h[dir] + btScalar *pq = q; + btScalar *pr = r; + nr = 0; + for (int i=nq; i > 0; i--) { + // go through all points in q and all lines between adjacent points + if (sign*pq[dir] < h[dir]) { + // this point is inside the chopping line + pr[0] = pq[0]; + pr[1] = pq[1]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + btScalar *nextq = (i > 1) ? pq+2 : q; + if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { + // this line crosses the chopping line + pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / + (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); + pr[dir] = sign*h[dir]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + pq += 2; + } + q = r; + r = (q==ret) ? buffer : ret; + nq = nr; + } + } + done: + if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar)); + return nr; +} + + +#define M__PI 3.14159265f + +// given n points in the plane (array p, of size 2*n), generate m points that +// best represent the whole set. the definition of 'best' here is not +// predetermined - the idea is to select points that give good box-box +// collision detection behavior. the chosen point indexes are returned in the +// array iret (of size m). 'i0' is always the first entry in the array. +// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be +// in the range [0..n-1]. + +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]); +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) +{ + // compute the centroid of the polygon in cx,cy + int i,j; + btScalar a,cx,cy,q; + if (n==1) { + cx = p[0]; + cy = p[1]; + } + else if (n==2) { + cx = btScalar(0.5)*(p[0] + p[2]); + cy = btScalar(0.5)*(p[1] + p[3]); + } + else { + a = 0; + cx = 0; + cy = 0; + for (i=0; i<(n-1); i++) { + q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; + a += q; + cx += q*(p[i*2]+p[i*2+2]); + cy += q*(p[i*2+1]+p[i*2+3]); + } + q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; + a = 1.f/(btScalar(3.0)*(a+q)); + cx = a*(cx + q*(p[n*2-2]+p[0])); + cy = a*(cy + q*(p[n*2-1]+p[1])); + } + + // compute the angle of each point w.r.t. the centroid + btScalar A[8]; + for (i=0; i M__PI) a -= 2*M__PI; + btScalar maxdiff=1e9,diff; +#if defined(DEBUG) || defined (_DEBUG) + *iret = i0; // iret is not allowed to keep this value +#endif + for (i=0; i M__PI) diff = 2*M__PI - diff; + if (diff < maxdiff) { + maxdiff = diff; + *iret = i; + } + } + } +#if defined(DEBUG) || defined (_DEBUG) + btAssert (*iret != i0); // ensure iret got set +#endif + avail[*iret] = 0; + iret++; + } +} + + + +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output); +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output) +{ + const btScalar fudge_factor = btScalar(1.05); + btVector3 p,pp,normalC; + const btScalar *normalR = 0; + btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, + Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l; + int i,j,invert_normal,code; + + // get vector from centers of box 1 to box 2, relative to box 1 + p = p2 - p1; + dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1 + + // get side lengths / 2 + A[0] = side1[0]*btScalar(0.5); + A[1] = side1[1]*btScalar(0.5); + A[2] = side1[2]*btScalar(0.5); + B[0] = side2[0]*btScalar(0.5); + B[1] = side2[1]*btScalar(0.5); + B[2] = side2[2]*btScalar(0.5); + + // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 + R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); + R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); + R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); + + Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13); + Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23); + Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33); + + // for all 15 possible separating axes: + // * see if the axis separates the boxes. if so, return 0. + // * find the depth of the penetration along the separating axis (s2) + // * if this is the largest depth so far, record it. + // the normal vector will be set to the separating axis with the smallest + // depth. note: normalR is set to point to a column of R1 or R2 if that is + // the smallest depth normal so far. otherwise normalR is 0 and normalC is + // set to a vector relative to body 1. invert_normal is 1 if the sign of + // the normal should be flipped. + +#define TST(expr1,expr2,norm,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > 0) return 0; \ + if (s2 > s) { \ + s = s2; \ + normalR = norm; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } + + s = -dInfinity; + invert_normal = 0; + code = 0; + + // separating axis = u1,u2,u3 + TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); + TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); + TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); + + // separating axis = v1,v2,v3 + TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); + TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); + TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); + + // note: cross product axes need to be scaled when s is computed. + // normal (n1,n2,n3) is relative to box 1. +#undef TST +#define TST(expr1,expr2,n1,n2,n3,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > 0) return 0; \ + l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ + if (l > 0) { \ + s2 /= l; \ + if (s2*fudge_factor > s) { \ + s = s2; \ + normalR = 0; \ + normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } \ + } + + // separating axis = u1 x (v1,v2,v3) + TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); + TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); + TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); + + // separating axis = u2 x (v1,v2,v3) + TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); + TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); + TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); + + // separating axis = u3 x (v1,v2,v3) + TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); + TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); + TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); + +#undef TST + + if (!code) return 0; + + // if we get to this point, the boxes interpenetrate. compute the normal + // in global coordinates. + if (normalR) { + normal[0] = normalR[0]; + normal[1] = normalR[4]; + normal[2] = normalR[8]; + } + else { + dMULTIPLY0_331 (normal,R1,normalC); + } + if (invert_normal) { + normal[0] = -normal[0]; + normal[1] = -normal[1]; + normal[2] = -normal[2]; + } + *depth = -s; + + // compute contact point(s) + + if (code > 6) { + // an edge from box 1 touches an edge from box 2. + // find a point pa on the intersecting edge of box 1 + btVector3 pa; + btScalar sign; + for (i=0; i<3; i++) pa[i] = p1[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0); + for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; + } + + // find a point pb on the intersecting edge of box 2 + btVector3 pb; + for (i=0; i<3; i++) pb[i] = p2[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0); + for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; + } + + btScalar alpha,beta; + btVector3 ua,ub; + for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; + for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; + + dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); + for (i=0; i<3; i++) pa[i] += ua[i]*alpha; + for (i=0; i<3; i++) pb[i] += ub[i]*beta; + + { + + //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]); + //contact[0].depth = *depth; + btVector3 pointInWorld; + +#ifdef USE_CENTER_POINT + for (i=0; i<3; i++) + pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5); + output.addContactPoint(-normal,pointInWorld,-*depth); +#else + output.addContactPoint(-normal,pb,-*depth); +#endif // + *return_code = code; + } + return 1; + } + + // okay, we have a face-something intersection (because the separating + // axis is perpendicular to a face). define face 'a' to be the reference + // face (i.e. the normal vector is perpendicular to this) and face 'b' to be + // the incident face (the closest face of the other box). + + const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb; + if (code <= 3) { + Ra = R1; + Rb = R2; + pa = p1; + pb = p2; + Sa = A; + Sb = B; + } + else { + Ra = R2; + Rb = R1; + pa = p2; + pb = p1; + Sa = B; + Sb = A; + } + + // nr = normal vector of reference face dotted with axes of incident box. + // anr = absolute values of nr. + btVector3 normal2,nr,anr; + if (code <= 3) { + normal2[0] = normal[0]; + normal2[1] = normal[1]; + normal2[2] = normal[2]; + } + else { + normal2[0] = -normal[0]; + normal2[1] = -normal[1]; + normal2[2] = -normal[2]; + } + dMULTIPLY1_331 (nr,Rb,normal2); + anr[0] = btFabs (nr[0]); + anr[1] = btFabs (nr[1]); + anr[2] = btFabs (nr[2]); + + // find the largest compontent of anr: this corresponds to the normal + // for the indident face. the other axis numbers of the indicent face + // are stored in a1,a2. + int lanr,a1,a2; + if (anr[1] > anr[0]) { + if (anr[1] > anr[2]) { + a1 = 0; + lanr = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + else { + if (anr[0] > anr[2]) { + lanr = 0; + a1 = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + + // compute center point of incident face, in reference-face coordinates + btVector3 center; + if (nr[lanr] < 0) { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; + } + else { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; + } + + // find the normal and non-normal axis numbers of the reference box + int codeN,code1,code2; + if (code <= 3) codeN = code-1; else codeN = code-4; + if (codeN==0) { + code1 = 1; + code2 = 2; + } + else if (codeN==1) { + code1 = 0; + code2 = 2; + } + else { + code1 = 0; + code2 = 1; + } + + // find the four corners of the incident face, in reference-face coordinates + btScalar quad[8]; // 2D coordinate of incident face (x,y pairs) + btScalar c1,c2,m11,m12,m21,m22; + c1 = dDOT14 (center,Ra+code1); + c2 = dDOT14 (center,Ra+code2); + // optimize this? - we have already computed this data above, but it is not + // stored in an easy-to-index format. for now it's quicker just to recompute + // the four dot products. + m11 = dDOT44 (Ra+code1,Rb+a1); + m12 = dDOT44 (Ra+code1,Rb+a2); + m21 = dDOT44 (Ra+code2,Rb+a1); + m22 = dDOT44 (Ra+code2,Rb+a2); + { + btScalar k1 = m11*Sb[a1]; + btScalar k2 = m21*Sb[a1]; + btScalar k3 = m12*Sb[a2]; + btScalar k4 = m22*Sb[a2]; + quad[0] = c1 - k1 - k3; + quad[1] = c2 - k2 - k4; + quad[2] = c1 - k1 + k3; + quad[3] = c2 - k2 + k4; + quad[4] = c1 + k1 + k3; + quad[5] = c2 + k2 + k4; + quad[6] = c1 + k1 - k3; + quad[7] = c2 + k2 - k4; + } + + // find the size of the reference face + btScalar rect[2]; + rect[0] = Sa[code1]; + rect[1] = Sa[code2]; + + // intersect the incident and reference faces + btScalar ret[16]; + int n = intersectRectQuad2 (rect,quad,ret); + if (n < 1) return 0; // this should never happen + + // convert the intersection points into reference-face coordinates, + // and compute the contact position and depth for each point. only keep + // those points that have a positive (penetrating) depth. delete points in + // the 'ret' array as necessary so that 'point' and 'ret' correspond. + btScalar point[3*8]; // penetrating contact points + btScalar dep[8]; // depths for those points + btScalar det1 = 1.f/(m11*m22 - m12*m21); + m11 *= det1; + m12 *= det1; + m21 *= det1; + m22 *= det1; + int cnum = 0; // number of penetrating contact points found + for (j=0; j < n; j++) { + btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); + btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); + for (i=0; i<3; i++) point[cnum*3+i] = + center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; + dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3); + if (dep[cnum] >= 0) { + ret[cnum*2] = ret[j*2]; + ret[cnum*2+1] = ret[j*2+1]; + cnum++; + } + } + if (cnum < 1) return 0; // this should never happen + + // we can't generate more contacts than we actually have + if (maxc > cnum) maxc = cnum; + if (maxc < 1) maxc = 1; + + if (cnum <= maxc) { + // we have less contacts than we need, so we use them all + for (j=0; j < cnum; j++) { + + //AddContactPoint... + + //dContactGeom *con = CONTACT(contact,skip*j); + //for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i]; + //con->depth = dep[j]; + + btVector3 pointInWorld; + for (i=0; i<3; i++) + pointInWorld[i] = point[j*3+i] + pa[i]; + output.addContactPoint(-normal,pointInWorld,-dep[j]); + + } + } + else { + // we have more contacts than are wanted, some of them must be culled. + // find the deepest point, it is always the first contact. + int i1 = 0; + btScalar maxdepth = dep[0]; + for (i=1; i maxdepth) { + maxdepth = dep[i]; + i1 = i; + } + } + + int iret[8]; + cullPoints2 (cnum,ret,maxc,i1,iret); + + for (j=0; j < maxc; j++) { +// dContactGeom *con = CONTACT(contact,skip*j); + // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; + // con->depth = dep[iret[j]]; + + btVector3 posInWorld; + for (i=0; i<3; i++) + posInWorld[i] = point[iret[j]*3+i] + pa[i]; + output.addContactPoint(-normal,posInWorld,-dep[iret[j]]); + } + cnum = maxc; + } + + *return_code = code; + return cnum; +} + +void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/) +{ + + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + int skip = 0; + dContactGeom *contact = 0; + + dMatrix3 R1; + dMatrix3 R2; + + for (int j=0;j<3;j++) + { + R1[0+4*j] = transformA.getBasis()[j].x(); + R2[0+4*j] = transformB.getBasis()[j].x(); + + R1[1+4*j] = transformA.getBasis()[j].y(); + R2[1+4*j] = transformB.getBasis()[j].y(); + + + R1[2+4*j] = transformA.getBasis()[j].z(); + R2[2+4*j] = transformB.getBasis()[j].z(); + + } + + + + btVector3 normal; + btScalar depth; + int return_code; + int maxc = 4; + + + dBoxBox2 (transformA.getOrigin(), + R1, + 2.f*m_box1->getHalfExtentsWithMargin(), + transformB.getOrigin(), + R2, + 2.f*m_box2->getHalfExtentsWithMargin(), + normal, &depth, &return_code, + maxc, contact, skip, + output + ); + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h new file mode 100644 index 00000000000..605294d47bd --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h @@ -0,0 +1,44 @@ +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BOX_BOX_DETECTOR_H +#define BOX_BOX_DETECTOR_H + + +class btBoxShape; +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + + +/// btBoxBoxDetector wraps the ODE box-box collision detector +/// re-distributed under the Zlib license with permission from Russell L. Smith +struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface +{ + btBoxShape* m_box1; + btBoxShape* m_box2; + +public: + + btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2); + + virtual ~btBoxBoxDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + +}; + +#endif //BT_BOX_BOX_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h new file mode 100644 index 00000000000..fad770ac26d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -0,0 +1,47 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_CONFIGURATION +#define BT_COLLISION_CONFIGURATION +struct btCollisionAlgorithmCreateFunc; + +class btStackAlloc; +class btPoolAllocator; + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator size, default collision algorithms and persistent manifold pool size +///todo: describe the meaning +class btCollisionConfiguration +{ + +public: + + virtual ~btCollisionConfiguration() + { + } + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() = 0; + + virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; + + virtual btStackAlloc* getStackAllocator() = 0; + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; + +}; + +#endif //BT_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h index d51a59af7f0..c6728918d16 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_CREATE_FUNC #define COLLISION_CREATE_FUNC -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" typedef btAlignedObjectArray btCollisionObjectArray; class btCollisionAlgorithm; class btCollisionObject; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index b535fac6563..a031a9f9784 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -19,69 +19,39 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" + #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btPoolAllocator.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" int gNumManifold = 0; +#ifdef BT_DEBUG #include +#endif - -btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms): -m_count(0), -m_useIslands(true), -m_convexConvexCreateFunc(0), -m_convexConcaveCreateFunc(0), -m_swappedConvexConcaveCreateFunc(0), -m_compoundCreateFunc(0), -m_swappedCompoundCreateFunc(0), -m_emptyCreateFunc(0) -{ - (void)noDefaultAlgorithms; - int i; - setNearCallback(defaultNearCallback); - - m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc; - for (i=0;igetCollisionAlgorithmPool(); + + m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); for (i=0;igetCollisionAlgorithmCreateFunc(i,j); assert(m_doubleDispatch[i][j]); } } @@ -89,8 +59,6 @@ btCollisionDispatcher::btCollisionDispatcher (): }; -#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION - void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) { @@ -99,12 +67,6 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox btCollisionDispatcher::~btCollisionDispatcher() { - delete m_convexConvexCreateFunc; - delete m_convexConcaveCreateFunc; - delete m_swappedConvexConcaveCreateFunc; - delete m_compoundCreateFunc; - delete m_swappedCompoundCreateFunc; - delete m_emptyCreateFunc; } btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) @@ -117,7 +79,18 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) btCollisionObject* body0 = (btCollisionObject*)b0; btCollisionObject* body1 = (btCollisionObject*)b1; - btPersistentManifold* manifold = new btPersistentManifold (body0,body1); + void* mem = 0; + + if (m_persistentManifoldPoolAllocator->getFreeCount()) + { + mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); + } else + { + mem = btAlignedAlloc(sizeof(btPersistentManifold),16); + + } + btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); + manifold->m_index1a = m_manifoldsPtr.size(); m_manifoldsPtr.push_back(manifold); return manifold; @@ -137,13 +110,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) //printf("releaseManifold: gNumManifold %d\n",gNumManifold); clearManifold(manifold); - ///todo: this can be improved a lot, linear search might be slow part! - int findIndex = m_manifoldsPtr.findLinearSearch(manifold); - if (findIndex < m_manifoldsPtr.size()) + int findIndex = manifold->m_index1a; + btAssert(findIndex < m_manifoldsPtr.size()); + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr[findIndex]->m_index1a = findIndex; + m_manifoldsPtr.pop_back(); + + manifold->~btPersistentManifold(); + if (m_persistentManifoldPoolAllocator->validPtr(manifold)) { - m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); - m_manifoldsPtr.pop_back(); - delete manifold; + m_persistentManifoldPoolAllocator->freeMemory(manifold); + } else + { + btAlignedFree(manifold); } } @@ -152,99 +131,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) { - -#ifdef USE_DISPATCH_REGISTRY_ARRAY btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = this; + + ci.m_dispatcher1 = this; ci.m_manifold = sharedManifold; - btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()] - ->CreateCollisionAlgorithm(ci,body0,body1); -#else - btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1); -#endif //USE_DISPATCH_REGISTRY_ARRAY + btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); + return algo; } -#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION - -btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1) -{ - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_convexConvexCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_convexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) - { - return m_swappedConvexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isCompound(proxyType0)) - { - return m_compoundCreateFunc; - } else - { - if (btBroadphaseProxy::isCompound(proxyType1)) - { - return m_swappedCompoundCreateFunc; - } - } - - //failed to find an algorithm - return m_emptyCreateFunc; -} - -#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION -#ifndef USE_DISPATCH_REGISTRY_ARRAY - -btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) -{ - m_count++; - - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = this; - - if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() ) - { - return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1); - } - - if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave()) - { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); - } - - if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave()) - { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); - } - - if (body0->getCollisionShape()->isCompound()) - { - return new btCompoundCollisionAlgorithm(ci,body0,body1,false); - } else - { - if (body1->getCollisionShape()->isCompound()) - { - return new btCompoundCollisionAlgorithm(ci,body0,body1,true); - } - } - - //failed to find an algorithm - return new btEmptyAlgorithm(ci); - -} -#endif //USE_DISPATCH_REGISTRY_ARRAY bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) { @@ -264,13 +163,19 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO bool needsCollision = true; - //broadphase filtering already deals with this - if ((body0->isStaticObject() || body0->isKinematicObject()) && - (body1->isStaticObject() || body1->isKinematicObject())) +#ifdef BT_DEBUG + if (!m_staticWarningReported) { - printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + //broadphase filtering already deals with this + if ((body0->isStaticObject() || body0->isKinematicObject()) && + (body1->isStaticObject() || body1->isKinematicObject())) + { + m_staticWarningReported = true; + printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + } } - +#endif //BT_DEBUG + if ((!body0->isActive()) && (!body1->isActive())) needsCollision = false; else if (!body0->checkCollideWith(body1)) @@ -286,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO ///this is useful for the collision dispatcher. class btCollisionPairCallback : public btOverlapCallback { - btDispatcherInfo& m_dispatchInfo; + const btDispatcherInfo& m_dispatchInfo; btCollisionDispatcher* m_dispatcher; public: - btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) :m_dispatchInfo(dispatchInfo), m_dispatcher(dispatcher) { } - btCollisionPairCallback& operator=(btCollisionPairCallback& other) + /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) { m_dispatchInfo = other.m_dispatchInfo; m_dispatcher = other.m_dispatcher; return *this; } + */ + virtual ~btCollisionPairCallback() {} @@ -316,13 +223,14 @@ public: }; -void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo) + +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) { //m_blockedForChanges = true; btCollisionPairCallback collisionCallback(dispatchInfo,this); - pairCache->processAllOverlappingPairs(&collisionCallback); + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); //m_blockedForChanges = false; @@ -332,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa //by default, Bullet will use this near callback -void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; @@ -365,3 +273,26 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, } } + + +void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) +{ + if (m_collisionAlgorithmPoolAllocator->getFreeCount()) + { + return m_collisionAlgorithmPoolAllocator->allocate(size); + } + + //warn user for overflow? + return btAlignedAlloc(static_cast(size), 16); +} + +void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) +{ + if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) + { + m_collisionAlgorithmPoolAllocator->freeMemory(ptr); + } else + { + btAlignedFree(ptr); + } +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index ca5aba8f01c..a9c9cd414c1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -16,17 +16,18 @@ subject to the following restrictions: #ifndef COLLISION__DISPATCHER_H #define COLLISION__DISPATCHER_H -#include "../BroadphaseCollision/btDispatcher.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "../CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btAlignedObjectArray.h" class btIDebugDraw; class btOverlappingPairCache; - +class btPoolAllocator; +class btCollisionConfiguration; #include "btCollisionCreateFunc.h" @@ -34,7 +35,7 @@ class btOverlappingPairCache; class btCollisionDispatcher; ///user can override this nearcallback for collision filtering and more finegrained control over collision detection -typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. @@ -46,26 +47,22 @@ class btCollisionDispatcher : public btDispatcher btAlignedObjectArray m_manifoldsPtr; bool m_useIslands; + + bool m_staticWarningReported; btManifoldResult m_defaultManifoldResult; btNearCallback m_nearCallback; + btPoolAllocator* m_collisionAlgorithmPoolAllocator; + + btPoolAllocator* m_persistentManifoldPoolAllocator; + btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; - btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1); - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionConfiguration* m_collisionConfiguration; -#ifndef USE_DISPATCH_REGISTRY_ARRAY - btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); -#endif //USE_DISPATCH_REGISTRY_ARRAY public: @@ -92,11 +89,7 @@ public: return m_manifoldsPtr[index]; } - ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support - btCollisionDispatcher (); - - ///a special constructor that doesn't create/register the default collision algorithms - btCollisionDispatcher(bool noDefaultAlgorithms); + btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); virtual ~btCollisionDispatcher(); @@ -114,7 +107,7 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo); + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; void setNearCallback(btNearCallback nearCallback) { @@ -127,7 +120,26 @@ public: } //by default, Bullet will use this near callback - static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + + virtual void* allocateCollisionAlgorithm(int size); + + virtual void freeCollisionAlgorithm(void* ptr); + + btCollisionConfiguration* getCollisionConfiguration() + { + return m_collisionConfiguration; + } + + const btCollisionConfiguration* getCollisionConfiguration() const + { + return m_collisionConfiguration; + } + + void setCollisionConfiguration(btCollisionConfiguration* config) + { + m_collisionConfiguration = config; + } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp index d4c0a4e8cb3..eebd0c99fcb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -13,18 +13,25 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ + #include "btCollisionObject.h" btCollisionObject::btCollisionObject() : m_broadphaseHandle(0), m_collisionShape(0), - m_collisionFlags(0), + m_rootCollisionShape(0), + m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), + m_islandTag1(-1), + m_companionId(-1), m_activationState1(1), m_deactivationTime(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), m_userObjectPointer(0), + m_internalType(CO_COLLISION_OBJECT), m_hitFraction(btScalar(1.)), m_ccdSweptSphereRadius(btScalar(0.)), - m_ccdSquareMotionThreshold(btScalar(0.)), + m_ccdMotionThreshold(btScalar(0.)), m_checkCollideWith(false) { @@ -55,3 +62,4 @@ void btCollisionObject::activate(bool forceActivation) } + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index 9fb6a67c4a3..eb297ef4a3b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_OBJECT_H #define COLLISION_OBJECT_H -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btTransform.h" //island management, m_activationState1 #define ACTIVE_TAG 1 @@ -27,7 +27,8 @@ subject to the following restrictions: struct btBroadphaseProxy; class btCollisionShape; -#include "../../LinearMath/btMotionState.h" +#include "LinearMath/btMotionState.h" +#include "LinearMath/btAlignedAllocator.h" @@ -50,6 +51,11 @@ protected: btVector3 m_interpolationAngularVelocity; btBroadphaseProxy* m_broadphaseHandle; btCollisionShape* m_collisionShape; + + ///m_rootCollisionShape is temporarily used to store the original collision shape + ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes + ///If it is NULL, the m_collisionShape is not temporarily replaced. + btCollisionShape* m_rootCollisionShape; int m_collisionFlags; @@ -65,8 +71,9 @@ protected: ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer void* m_userObjectPointer; - ///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead. - void* m_internalOwner; + ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc. + ///do not assign your own m_internalType unless you write a new dynamics object class. + int m_internalType; ///time of impact calculation btScalar m_hitFraction; @@ -74,21 +81,23 @@ protected: ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: btScalar m_ccdSweptSphereRadius; - /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold - btScalar m_ccdSquareMotionThreshold; + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + btScalar m_ccdMotionThreshold; /// If some object should have elaborate collision filtering by sub-classes bool m_checkCollideWith; char m_pad[7]; - virtual bool checkCollideWithOverride(btCollisionObject* co) + virtual bool checkCollideWithOverride(btCollisionObject* /* co */) { return true; } public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + enum CollisionFlags { CF_STATIC_OBJECT= 1, @@ -97,29 +106,35 @@ public: CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) }; + enum CollisionObjectTypes + { + CO_COLLISION_OBJECT =1, + CO_RIGID_BODY, + CO_SOFT_BODY + }; - inline bool mergesSimulationIslands() const + SIMD_FORCE_INLINE bool mergesSimulationIslands() const { ///static objects, kinematic and object without contact response don't merge islands return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); } - inline bool isStaticObject() const { + SIMD_FORCE_INLINE bool isStaticObject() const { return (m_collisionFlags & CF_STATIC_OBJECT) != 0; } - inline bool isKinematicObject() const + SIMD_FORCE_INLINE bool isKinematicObject() const { return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; } - inline bool isStaticOrKinematicObject() const + SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const { return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; } - inline bool hasContactResponse() const { + SIMD_FORCE_INLINE bool hasContactResponse() const { return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; } @@ -131,20 +146,35 @@ public: void setCollisionShape(btCollisionShape* collisionShape) { m_collisionShape = collisionShape; + m_rootCollisionShape = collisionShape; } - const btCollisionShape* getCollisionShape() const + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - btCollisionShape* getCollisionShape() + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { return m_collisionShape; } - + SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const + { + return m_rootCollisionShape; + } + SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape() + { + return m_rootCollisionShape; + } + + ///Avoid using this internal API call + ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape. + void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape) + { + m_collisionShape = collisionShape; + } int getActivationState() const { return m_activationState1;} @@ -186,14 +216,9 @@ public: } ///reserved for Bullet internal usage - void* getInternalOwner() + int getInternalType() const { - return m_internalOwner; - } - - const void* getInternalOwner() const - { - return m_internalOwner; + return m_internalType; } btTransform& getWorldTransform() @@ -307,16 +332,22 @@ public: m_ccdSweptSphereRadius = radius; } + btScalar getCcdMotionThreshold() const + { + return m_ccdMotionThreshold; + } + btScalar getCcdSquareMotionThreshold() const { - return m_ccdSquareMotionThreshold; + return m_ccdMotionThreshold*m_ccdMotionThreshold; } - /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold - void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold) + + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + void setCcdMotionThreshold(btScalar ccdMotionThreshold) { - m_ccdSquareMotionThreshold = ccdSquareMotionThreshold; + m_ccdMotionThreshold = ccdMotionThreshold*ccdMotionThreshold; } ///users can point to their objects, userPointer is not used by Bullet @@ -331,6 +362,7 @@ public: m_userObjectPointer = userPointer; } + inline bool checkCollideWith(btCollisionObject* co) { if (m_checkCollideWith) @@ -338,9 +370,6 @@ public: return true; } - - -} -; +}; #endif //COLLISION_OBJECT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index b49036a5b50..d8674a320a7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -4,8 +4,8 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. @@ -18,59 +18,57 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" - +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting -#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" + #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "LinearMath/btAabbUtil2.h" #include "LinearMath/btQuickprof.h" #include "LinearMath/btStackAlloc.h" + //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" -btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize) +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) :m_dispatcher1(dispatcher), m_broadphasePairCache(pairCache), -m_ownsDispatcher(false), -m_ownsBroadphasePairCache(false) +m_debugDrawer(0) { - m_stackAlloc = new btStackAlloc(stackSize); + m_stackAlloc = collisionConfiguration->getStackAllocator(); m_dispatchInfo.m_stackAllocator = m_stackAlloc; } btCollisionWorld::~btCollisionWorld() { - m_stackAlloc->destroy(); - delete m_stackAlloc; //clean up remaining objects int i; for (i=0;igetBroadphaseHandle(); if (bp) { // // only clear the cached algorithms // - getBroadphase()->cleanProxyFromPairs(bp); - getBroadphase()->destroyProxy(bp); + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); } } - if (m_ownsDispatcher) - delete m_dispatcher1; - if (m_ownsBroadphasePairCache) - delete m_broadphasePairCache; } @@ -105,66 +103,105 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho type, collisionObject, collisionFilterGroup, - collisionFilterMask + collisionFilterMask, + m_dispatcher1,0 )) ; - + } +void btCollisionWorld::updateAabbs() +{ + BT_PROFILE("updateAabbs"); + + btTransform predictedTrans; + for ( int i=0;iisActive()) + { + btPoint3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + //need to increase the aabb for contact thresholds + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; + + //moving objects should be moderately sized, probably something wrong if not + if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + { + bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + } else + { + //something went wrong, investigate + //this assert is unwanted in 3D modelers (danger of loosing work) + colObj->setActivationState(DISABLE_SIMULATION); + + static bool reportMe = true; + if (reportMe && m_debugDrawer) + { + reportMe = false; + m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); + m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); + m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); + m_debugDrawer->reportErrorWarning("Thanks.\n"); + } + } + } + } + +} void btCollisionWorld::performDiscreteCollisionDetection() { + BT_PROFILE("performDiscreteCollisionDetection"); + btDispatcherInfo& dispatchInfo = getDispatchInfo(); - BEGIN_PROFILE("perform Broadphase Collision Detection"); + updateAabbs(); - - //update aabb (of all moved objects) - - btVector3 aabbMin,aabbMax; - for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); - m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); + BT_PROFILE("calculateOverlappingPairs"); + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); } - m_broadphasePairCache->refreshOverlappingPairs(); - - - END_PROFILE("perform Broadphase Collision Detection"); - - BEGIN_PROFILE("performDiscreteCollisionDetection"); btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); - - END_PROFILE("performDiscreteCollisionDetection"); + { + BT_PROFILE("dispatchAllCollisionPairs"); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + } } + void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) { - - + + //bool removeFromBroadphase = false; - + { - + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); if (bp) { // // only clear the cached algorithms // - getBroadphase()->cleanProxyFromPairs(bp); - getBroadphase()->destroyProxy(bp); + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); collisionObject->setBroadphaseHandle(0); } } @@ -181,172 +218,412 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback,short int collisionFilterMask) + RayResultCallback& resultCallback) { - btSphereShape pointShape(btScalar(0.0)); pointShape.setMargin(0.f); + const btConvexShape* castShape = &pointShape; - objectQuerySingle(&pointShape,rayFromTrans,rayToTrans, - collisionObject, - collisionShape, - colObjWorldTransform, - resultCallback,collisionFilterMask); + if (collisionShape->isConvex()) + { + btConvexCast::CastResult castResult; + castResult.m_fraction = resultCallback.m_closestHitFraction; + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; +#define USE_SUBSIMPLEX_CONVEX_CAST 1 +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); +#else + //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST + + castResult.m_normal.normalize(); + btCollisionWorld::LocalRayResult localRayResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localRayResult, normalInWorldSpace); + + } + } + } + } else { + if (collisionShape->isConcave()) + { + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + ///optimized version for btBvhTriangleMeshShape + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): + btTriangleRaycastCallback(from,to), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitFraction); + + bool normalInWorldSpace = false; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + } + + }; + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); + } else + { + btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): + btTriangleRaycastCallback(from,to), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitFraction); + + bool normalInWorldSpace = false; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + + + } + + }; + + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + + btVector3 rayAabbMinLocal = rayFromLocal; + rayAabbMinLocal.setMin(rayToLocal); + btVector3 rayAabbMaxLocal = rayFromLocal; + rayAabbMaxLocal.setMax(rayToLocal); + + triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + } + } else { + //todo: use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); + rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback); + // restore + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); + } + } + } + } } -void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans, +void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback,short int collisionFilterMask) + ConvexResultCallback& resultCallback, btScalar allowedPenetration) { - - if (collisionShape->isConvex()) + { + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = btScalar(1.);//?? + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + + btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); + //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); + //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); + + btConvexCast* castPtr = &convexCaster1; + + + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) { - btConvexCast::CastResult castResult; - castResult.m_fraction = btScalar(1.);//?? - - btConvexShape* convexShape = (btConvexShape*) collisionShape; - btVoronoiSimplexSolver simplexSolver; - btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); - - if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + if (castResult.m_fraction < resultCallback.m_closestHitFraction) { - //add hit - if (castResult.m_normal.length2() > btScalar(0.0001)) - { - castResult.m_normal.normalize(); - if (castResult.m_fraction < resultCallback.m_closestHitFraction) - { - - btCollisionWorld::LocalRayResult localRayResult + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult ( - collisionObject, + collisionObject, 0, castResult.m_normal, + castResult.m_hitPoint, castResult.m_fraction ); - resultCallback.AddSingleResult(localRayResult); + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); - } - } } } - else + } + } else { + if (collisionShape->isConcave()) + { + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) { - - if (collisionShape->isConcave()) - { + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); - btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; - - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; - btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); - btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); - - //ConvexCast::CastResult - - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) { - btCollisionWorld::RayResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, - btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } - - - virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - - btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitFraction); - - return m_resultCallback->AddSingleResult(rayResult); - - - } - - }; - - - BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); - rcb.m_hitFraction = resultCallback.m_closestHitFraction; - - btVector3 rayAabbMinLocal = rayFromLocal; - rayAabbMinLocal.setMin(rayToLocal); - btVector3 rayAabbMaxLocal = rayFromLocal; - rayAabbMaxLocal.setMax(rayToLocal); - - triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); - - } else - { - //todo: use AABB tree or other BVH acceleration structure! - if (collisionShape->isCompound()) - { - const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - objectQuerySingle(castShape, rayFromTrans,rayToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback, collisionFilterMask); - - } - - } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = true; + + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); + } else + { + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = false; + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + + btVector3 rayAabbMinLocal = convexFromLocal; + rayAabbMinLocal.setMin(convexToLocal); + btVector3 rayAabbMaxLocal = convexFromLocal; + rayAabbMaxLocal.setMax(convexToLocal); + rayAabbMinLocal += boxMinLocal; + rayAabbMaxLocal += boxMaxLocal; + triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); } + } else { + //todo: use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback, allowedPenetration); + // restore + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); + } + } + } + } } -void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const { - + btTransform rayFromTrans,rayToTrans; rayFromTrans.setIdentity(); rayFromTrans.setOrigin(rayFromWorld); rayToTrans.setIdentity(); - + rayToTrans.setOrigin(rayToWorld); /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) - + int i; for (i=0;igetBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { + if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); btVector3 collisionObjectAabbMin,collisionObjectAabbMax; collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); - btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btScalar hitLambda = resultCallback.m_closestHitFraction; btVector3 hitNormal; if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) { @@ -355,7 +632,52 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r collisionObject->getCollisionShape(), collisionObject->getWorldTransform(), resultCallback); - } + } + } + + } + +} + +void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const +{ + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + } + + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + getDispatchInfo().m_allowedCcdPenetration); + } } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index b6d80233ab7..7557691a9a9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -68,12 +68,12 @@ class btStackAlloc; class btCollisionShape; class btConvexShape; class btBroadphaseInterface; -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" #include "btCollisionObject.h" #include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray -#include "../BroadphaseCollision/btOverlappingPairCache.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btAlignedObjectArray.h" ///CollisionWorld is interface and container for the collision detection class btCollisionWorld @@ -90,18 +90,22 @@ protected: btStackAlloc* m_stackAlloc; - btOverlappingPairCache* m_broadphasePairCache; - - bool m_ownsDispatcher; - bool m_ownsBroadphasePairCache; + btBroadphaseInterface* m_broadphasePairCache; + btIDebugDraw* m_debugDrawer; + + public: //this constructor doesn't own the dispatcher and paircache/broadphase - btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); + btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); virtual ~btCollisionWorld(); + void setBroadphase(btBroadphaseInterface* pairCache) + { + m_broadphasePairCache = pairCache; + } btBroadphaseInterface* getBroadphase() { @@ -110,7 +114,7 @@ public: btOverlappingPairCache* getPairCache() { - return m_broadphasePairCache; + return m_broadphasePairCache->getOverlappingPairCache(); } @@ -119,6 +123,24 @@ public: return m_dispatcher1; } + const btDispatcher* getDispatcher() const + { + return m_dispatcher1; + } + + virtual void updateAabbs(); + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + } + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + ///LocalShapeInfo gives extra information for complex shapes ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart struct LocalShapeInfo @@ -153,28 +175,43 @@ public: ///RayResultCallback is used to report new raycast results struct RayResultCallback { + btScalar m_closestHitFraction; + btCollisionObject* m_collisionObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + virtual ~RayResultCallback() { } - btScalar m_closestHitFraction; - bool HasHit() + bool hasHit() const { - return (m_closestHitFraction < btScalar(1.)); + return (m_collisionObject != 0); } RayResultCallback() - :m_closestHitFraction(btScalar(1.)) + :m_closestHitFraction(btScalar(1.)), + m_collisionObject(0), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) { } - virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0; + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; }; struct ClosestRayResultCallback : public RayResultCallback { ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) :m_rayFromWorld(rayFromWorld), - m_rayToWorld(rayToWorld), - m_collisionObject(0) + m_rayToWorld(rayToWorld) { } @@ -183,24 +220,121 @@ public: btVector3 m_hitNormalWorld; btVector3 m_hitPointWorld; - btCollisionObject* m_collisionObject; - - virtual btScalar AddSingleResult(LocalRayResult& rayResult) + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) { - -//caller already does the filter on the m_closestHitFraction - assert(rayResult.m_hitFraction <= m_closestHitFraction); + //caller already does the filter on the m_closestHitFraction + btAssert(rayResult.m_hitFraction <= m_closestHitFraction); m_closestHitFraction = rayResult.m_hitFraction; m_collisionObject = rayResult.m_collisionObject; - m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + if (normalInWorldSpace) + { + m_hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); return rayResult.m_hitFraction; } }; - + struct LocalConvexResult + { + LocalConvexResult(btCollisionObject* hitCollisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + const btVector3& hitPointLocal, + btScalar hitFraction + ) + :m_hitCollisionObject(hitCollisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitPointLocal(hitPointLocal), + m_hitFraction(hitFraction) + { + } + + btCollisionObject* m_hitCollisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btVector3 m_hitPointLocal; + btScalar m_hitFraction; + }; + + ///RayResultCallback is used to report new raycast results + struct ConvexResultCallback + { + btScalar m_closestHitFraction; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + ConvexResultCallback() + :m_closestHitFraction(btScalar(1.)), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) + { + } + + virtual ~ConvexResultCallback() + { + } + + bool hasHit() const + { + return (m_closestHitFraction < btScalar(1.)); + } + + + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0; + }; + + struct ClosestConvexResultCallback : public ConvexResultCallback + { + ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld) + :m_convexFromWorld(convexFromWorld), + m_convexToWorld(convexToWorld), + m_hitCollisionObject(0) + { + } + + btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_convexToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + btCollisionObject* m_hitCollisionObject; + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) + { +//caller already does the filter on the m_closestHitFraction + btAssert(convexResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = convexResult.m_hitFraction; + m_hitCollisionObject = convexResult.m_hitCollisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = convexResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + m_hitPointWorld = convexResult.m_hitPointLocal; + return convexResult.m_hitFraction; + } + }; int getNumCollisionObjects() const { @@ -209,7 +343,12 @@ public: /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. - void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback + // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. + void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback) const; + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. @@ -218,16 +357,16 @@ public: btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback, short int collisionFilterMask=-1); + RayResultCallback& resultCallback); /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback, short int collisionFilterMask=-1); + ConvexResultCallback& resultCallback, btScalar allowedPenetration); - void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); + void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); btCollisionObjectArray& getCollisionObjectArray() { @@ -249,6 +388,11 @@ public: return m_dispatchInfo; } + const btDispatcherInfo& getDispatchInfo() const + { + return m_dispatchInfo; + } + }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 92f4c8b28a6..57812818007 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -16,11 +16,17 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" - +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btAabbUtil2.h" btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -:m_isSwapped(isSwapped) +:btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_sharedManifold(ci.m_manifold) { + m_ownsManifold = false; + btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; assert (colObj->getCollisionShape()->isCompound()); @@ -32,11 +38,17 @@ btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlg m_childCollisionAlgorithms.resize(numChildren); for (i=0;igetChildShape(i); - btCollisionShape* orgShape = colObj->getCollisionShape(); - colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj); - colObj->setCollisionShape( orgShape ); + if (compoundShape->getDynamicAabbTree()) + { + m_childCollisionAlgorithms[i] = 0; + } else + { + btCollisionShape* tmpShape = colObj->getCollisionShape(); + btCollisionShape* childShape = compoundShape->getChildShape(i); + colObj->internalSetTemporaryCollisionShape( childShape ); + m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold); + colObj->internalSetTemporaryCollisionShape( tmpShape ); + } } } @@ -47,10 +59,109 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() int i; for (i=0;i~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + } } } + + + +struct btCompoundLeafCallback : btDbvt::ICollide +{ + +public: + + btCollisionObject* m_compoundColObj; + btCollisionObject* m_otherObj; + btDispatcher* m_dispatcher; + const btDispatcherInfo& m_dispatchInfo; + btManifoldResult* m_resultOut; + btCollisionAlgorithm** m_childCollisionAlgorithms; + btPersistentManifold* m_sharedManifold; + + + + + btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold) + :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), + m_childCollisionAlgorithms(childCollisionAlgorithms), + m_sharedManifold(sharedManifold) + { + + } + + + void ProcessChildShape(btCollisionShape* childShape,int index) + { + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + + + //backup + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(index); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + + m_compoundColObj->setWorldTransform( newChildWorldTrans); + m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans); + + //the contactpoint is still projected back using the original inverted worldtrans + btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape(); + m_compoundColObj->internalSetTemporaryCollisionShape( childShape ); + + if (!m_childCollisionAlgorithms[index]) + m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold); + + m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); + } + + //revert back transform + m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape); + m_compoundColObj->setWorldTransform( orgTrans ); + m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans); + } + } + void Process(const btDbvtNode* leaf) + { + int index = int(long(leaf->data)); + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + btCollisionShape* childShape = compoundShape->getChildShape(index); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); + m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); + } + ProcessChildShape(childShape,index); + + } +}; + + + + + + void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) { btCollisionObject* colObj = m_isSwapped? body1 : body0; @@ -59,33 +170,69 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt assert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps - //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals - //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: - //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 - //then use each overlapping node AABB against Tree0 - //and vise versa. + btDbvt* tree = compoundShape->getDynamicAabbTree(); + //use a dynamic aabb tree to cull potential child-overlaps + btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;igetChildShape(i); - //backup - btTransform orgTrans = colObj->getWorldTransform(); - btCollisionShape* orgShape = colObj->getCollisionShape(); + btVector3 localAabbMin,localAabbMax; + btTransform otherInCompoundSpace; + otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform(); + otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); + + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //process all children, that overlap with the given AABB bounds + tree->collideTV(tree->m_root,bounds,callback); + + } else + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i),i); + } + } + + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btManifoldArray manifoldArray; + + for (i=0;igetChildShape(i); + //if not longer overlapping, remove the algorithm + btTransform orgTrans = colObj->getWorldTransform(); + btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(i); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + m_childCollisionAlgorithms[i] = 0; + } + + } + + } + + - const btTransform& childTrans = compoundShape->getChildTransform(i); - //btTransform newChildWorldTrans = orgTrans*childTrans ; - colObj->setWorldTransform( orgTrans*childTrans ); - //the contactpoint is still projected back using the original inverted worldtrans - colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); - //revert back - colObj->setCollisionShape( orgShape); - colObj->setWorldTransform( orgTrans ); } } @@ -117,20 +264,20 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* //backup btTransform orgTrans = colObj->getWorldTransform(); - btCollisionShape* orgShape = colObj->getCollisionShape(); - + const btTransform& childTrans = compoundShape->getChildTransform(i); //btTransform newChildWorldTrans = orgTrans*childTrans ; colObj->setWorldTransform( orgTrans*childTrans ); - colObj->setCollisionShape( childShape ); + btCollisionShape* tmpShape = colObj->getCollisionShape(); + colObj->internalSetTemporaryCollisionShape( childShape ); btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); if (fracsetCollisionShape( orgShape); + colObj->internalSetTemporaryCollisionShape( tmpShape); colObj->setWorldTransform( orgTrans); } return hitFraction; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 7091b233b46..624a3cf10f5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -16,22 +16,25 @@ subject to the following restrictions: #ifndef COMPOUND_COLLISION_ALGORITHM_H #define COMPOUND_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btDispatcher.h" -#include "../BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes -/// Place holder, not fully implemented yet class btCompoundCollisionAlgorithm : public btCollisionAlgorithm { btAlignedObjectArray m_childCollisionAlgorithms; bool m_isSwapped; + + class btPersistentManifold* m_sharedManifold; + bool m_ownsManifold; public: @@ -43,11 +46,22 @@ public: btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + int i; + for (i=0;igetAllContactManifolds(manifoldArray); + } + } + struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btCompoundCollisionAlgorithm(ci,body0,body1,false); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); } }; @@ -55,7 +69,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btCompoundCollisionAlgorithm(ci,body0,body1,true); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 24ceacfd40d..6d28904cb03 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -29,7 +29,7 @@ subject to the following restrictions: btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) : btCollisionAlgorithm(ci), m_isSwapped(isSwapped), -m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped) +m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) { } @@ -37,6 +37,13 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() { } +void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) +{ + if (m_btConvexTriangleCallback.m_manifoldPtr) + { + manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); + } +} btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): @@ -79,7 +86,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i //aabb filter is already applied! btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = m_dispatcher; + ci.m_dispatcher1 = m_dispatcher; btCollisionObject* ob = static_cast(m_triBody); @@ -109,13 +116,11 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i { btTriangleShape tm(triangle[0],triangle[1],triangle[2]); tm.setMargin(m_collisionMarginTriangle); - btCollisionShape* tmpShape = ob->getCollisionShape(); - ob->setCollisionShape( &tm ); + ob->internalSetTemporaryCollisionShape( &tm ); - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); ///this should use the btDispatcher, so the actual registered algorithm is used // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); @@ -123,12 +128,11 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - delete colAlgo; - ob->setCollisionShape( tmpShape ); - + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape); } - } @@ -188,9 +192,10 @@ void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* bod concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); + resultOut->refreshContactPoints(); } - + } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index 4915b6c20c8..34b9a107be9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -16,13 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btDispatcher.h" -#include "../BroadphaseCollision/btBroadphaseInterface.h" -#include "../CollisionShapes/btTriangleCallback.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. @@ -55,11 +55,11 @@ int m_triangleCount; void clearCache(); - inline const btVector3& getAabbMin() const + SIMD_FORCE_INLINE const btVector3& getAabbMin() const { return m_aabbMin; } - inline const btVector3& getAabbMax() const + SIMD_FORCE_INLINE const btVector3& getAabbMax() const { return m_aabbMax; } @@ -88,13 +88,16 @@ public: btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray); + void clearCache(); struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); } }; @@ -102,7 +105,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index 9105fe20b49..cb830f889be 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -15,7 +15,7 @@ subject to the following restrictions: #include "btConvexConvexAlgorithm.h" -#include +//#include #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" @@ -33,7 +33,6 @@ subject to the following restrictions: -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -48,26 +47,16 @@ subject to the following restrictions: -btConvexConvexAlgorithm::CreateFunc::CreateFunc() -{ - m_ownsSolvers = true; - m_simplexSolver = new btVoronoiSimplexSolver(); - m_pdSolver = new btGjkEpaPenetrationDepthSolver; -} + btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) { - m_ownsSolvers = false; m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } btConvexConvexAlgorithm::CreateFunc::~CreateFunc() { - if (m_ownsSolvers){ - delete m_simplexSolver; - delete m_pdSolver; - } } btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) @@ -152,6 +141,11 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); #endif + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index cbea9a92b75..a0030e6793d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -16,12 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONVEX_ALGORITHM_H #define CONVEX_CONVEX_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../NarrowPhaseCollision/btGjkPairDetector.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" class btConvexPenetrationDepthSolver; @@ -46,6 +47,14 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + void setLowLevelOfDetail(bool useLowLevel); @@ -58,15 +67,15 @@ public: { btConvexPenetrationDepthSolver* m_pdSolver; btSimplexSolverInterface* m_simplexSolver; - bool m_ownsSolvers; CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); - CreateFunc(); + virtual ~CreateFunc(); virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); + return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp new file mode 100644 index 00000000000..391cf6c7bc4 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp @@ -0,0 +1,108 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConvexPlaneCollisionAlgorithm.h" + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + +//#include + +btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ + btCollisionObject* convexObj = m_isSwapped? col1 : col0; + btCollisionObject* planeObj = m_isSwapped? col0 : col1; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj); + m_ownManifold = true; + } +} + + +btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + + + +void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + if (!m_manifoldPtr) + return; + + btCollisionObject* convexObj = m_isSwapped? body1 : body0; + btCollisionObject* planeObj = m_isSwapped? body0: body1; + + btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + btTransform planeInConvex; + planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; + + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); + } + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } +} + +btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h new file mode 100644 index 00000000000..7b258554171 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H +#define CONVEX_PLANE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + +public: + + btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btConvexPlaneCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp new file mode 100644 index 00000000000..1c317080544 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -0,0 +1,291 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btDefaultCollisionConfiguration.h" + +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" + + + +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btPoolAllocator.h" + + + + + +btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) +{ + + void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); + m_simplexSolver = new (mem)btVoronoiSimplexSolver(); + +#define USE_EPA 1 +#ifdef USE_EPA + mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); + m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; +#else + mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); + m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; +#endif//USE_EPA + + + //default CreationFunctions, filling the m_doubleDispatch table + mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); + m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); + m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); + m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); + m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); + m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; + m_boxSphereCF->m_swapped = true; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + m_triangleSphereCF->m_swapped = true; + + mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); + m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; + + //convex versus plane + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + m_planeConvexCF->m_swapped = true; + + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + int maxSize = sizeof(btConvexConvexAlgorithm); + int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); + int maxSize3 = sizeof(btCompoundCollisionAlgorithm); + int maxSize4 = sizeof(btEmptyAlgorithm); + + int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4); + + if (constructionInfo.m_stackAlloc) + { + m_ownsStackAllocator = false; + this->m_stackAlloc = constructionInfo.m_stackAlloc; + } else + { + m_ownsStackAllocator = true; + void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); + m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize); + } + + if (constructionInfo.m_persistentManifoldPool) + { + m_ownsPersistentManifoldPool = false; + m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; + } else + { + m_ownsPersistentManifoldPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); + } + + if (constructionInfo.m_collisionAlgorithmPool) + { + m_ownsCollisionAlgorithmPool = false; + m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; + } else + { + m_ownsCollisionAlgorithmPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + + +} + +btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() +{ + if (m_ownsStackAllocator) + { + m_stackAlloc->destroy(); + m_stackAlloc->~btStackAlloc(); + btAlignedFree(m_stackAlloc); + } + if (m_ownsCollisionAlgorithmPool) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + } + if (m_ownsPersistentManifoldPool) + { + m_persistentManifoldPool->~btPoolAllocator(); + btAlignedFree(m_persistentManifoldPool); + } + + m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConvexCreateFunc); + + m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConcaveCreateFunc); + m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedConvexConcaveCreateFunc); + + m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_compoundCreateFunc); + + m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedCompoundCreateFunc); + + m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_emptyCreateFunc); + + m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereSphereCF); + +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereBoxCF); + m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxSphereCF); +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereTriangleCF); + m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_triangleSphereCF); + m_boxBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxBoxCF); + + m_convexPlaneCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexPlaneCF); + m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_planeConvexCF); + + m_simplexSolver->~btVoronoiSimplexSolver(); + btAlignedFree(m_simplexSolver); + + m_pdSolver->~btConvexPenetrationDepthSolver(); + + btAlignedFree(m_pdSolver); + + +} + + +btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_sphereSphereCF; + } +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) + { + return m_sphereBoxCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_boxSphereCF; + } +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) + { + return m_sphereTriangleCF; + } + + if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_triangleSphereCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) + { + return m_boxBoxCF; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) + { + return m_convexPlaneCF; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) + { + return m_planeConvexCF; + } + + + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h new file mode 100644 index 00000000000..4f5af5f048c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -0,0 +1,115 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DEFAULT_COLLISION_CONFIGURATION +#define BT_DEFAULT_COLLISION_CONFIGURATION + +#include "btCollisionConfiguration.h" +class btVoronoiSimplexSolver; +class btConvexPenetrationDepthSolver; + +struct btDefaultCollisionConstructionInfo +{ + btStackAlloc* m_stackAlloc; + btPoolAllocator* m_persistentManifoldPool; + btPoolAllocator* m_collisionAlgorithmPool; + int m_defaultMaxPersistentManifoldPoolSize; + int m_defaultMaxCollisionAlgorithmPoolSize; + int m_defaultStackAllocatorSize; + + btDefaultCollisionConstructionInfo() + :m_stackAlloc(0), + m_persistentManifoldPool(0), + m_collisionAlgorithmPool(0), + m_defaultMaxPersistentManifoldPoolSize(65535), + m_defaultMaxCollisionAlgorithmPoolSize(65535), + m_defaultStackAllocatorSize(5*1024*1024) + { + } +}; + + + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator, pool memory allocators +///todo: describe the meaning +class btDefaultCollisionConfiguration : public btCollisionConfiguration +{ + + int m_persistentManifoldPoolSize; + + btStackAlloc* m_stackAlloc; + bool m_ownsStackAllocator; + + btPoolAllocator* m_persistentManifoldPool; + bool m_ownsPersistentManifoldPool; + + btPoolAllocator* m_collisionAlgorithmPool; + bool m_ownsCollisionAlgorithmPool; + + //default simplex/penetration depth solvers + btVoronoiSimplexSolver* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionAlgorithmCreateFunc* m_sphereSphereCF; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + btCollisionAlgorithmCreateFunc* m_sphereBoxCF; + btCollisionAlgorithmCreateFunc* m_boxSphereCF; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; + btCollisionAlgorithmCreateFunc* m_triangleSphereCF; + btCollisionAlgorithmCreateFunc* m_planeConvexCF; + btCollisionAlgorithmCreateFunc* m_convexPlaneCF; + +public: + + + btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btDefaultCollisionConfiguration(); + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() + { + return m_persistentManifoldPool; + } + + virtual btPoolAllocator* getCollisionAlgorithmPool() + { + return m_collisionAlgorithmPool; + } + + virtual btStackAlloc* getStackAllocator() + { + return m_stackAlloc; + } + + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + + +}; + +#endif //BT_DEFAULT_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h index b1a193d2cfd..e54721dec21 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -15,8 +15,9 @@ subject to the following restrictions: #ifndef EMPTY_ALGORITH #define EMPTY_ALGORITH -#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" #define ATTRIBUTE_ALIGNED(a) @@ -33,13 +34,18 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + } + struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { (void)body0; (void)body1; - return new btEmptyAlgorithm(ci); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); + return new(mem) btEmptyAlgorithm(ci); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index 490acc0b611..d5b12598be2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -79,12 +79,30 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b } btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); - + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); + //BP mod, store contact triangles. + newPt.m_partId0 = m_partId0; + newPt.m_partId1 = m_partId1; + newPt.m_index0 = m_index0; + newPt.m_index1 = m_index1; + + ///todo, check this for any side effects + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + insertIndex = m_manifoldPtr->addManifoldPoint(newPt); + } + //User can override friction and/or restitution if (gContactAddedCallback && //and if either of the two bodies requires custom material @@ -94,16 +112,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b //experimental feature info, for per-triangle material etc. btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; - (*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); + (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); } - if (insertIndex >= 0) - { - //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); - m_manifoldPtr->replaceContactPoint(newPt,insertIndex); - } else - { - m_manifoldPtr->AddManifoldPoint(newPt); - } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 77192625513..5aac9a46f6a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -18,12 +18,12 @@ subject to the following restrictions: #define MANIFOLD_RESULT_H class btCollisionObject; -class btPersistentManifold; +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btManifoldPoint; #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btTransform.h" typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); extern ContactAddedCallback gContactAddedCallback; @@ -60,6 +60,15 @@ public: m_manifoldPtr = manifoldPtr; } + const btPersistentManifold* getPersistentManifold() const + { + return m_manifoldPtr; + } + btPersistentManifold* getPersistentManifold() + { + return m_manifoldPtr; + } + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) { m_partId0=partId0; @@ -70,6 +79,22 @@ public: virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + SIMD_FORCE_INLINE void refreshContactPoints() + { + btAssert(m_manifoldPtr); + if (!m_manifoldPtr->getNumContacts()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + + if (isSwapped) + { + m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); + } else + { + m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); + } + } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index ac2e8554c3a..1cc78f76acd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -1,3 +1,17 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ #include "LinearMath/btScalar.h" @@ -7,7 +21,7 @@ #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" -#include +//#include #include "LinearMath/btQuickprof.h" btSimulationIslandManager::btSimulationIslandManager() @@ -25,17 +39,17 @@ void btSimulationIslandManager::initUnionFind(int n) } -void btSimulationIslandManager::findUnions(btDispatcher* dispatcher) +void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) { { - for (int i=0;igetNumManifolds();i++) - { - const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); - //static objects (invmass btScalar(0.)) don't merge ! + btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); - const btCollisionObject* colObj0 = static_cast(manifold->getBody0()); - const btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + for (int i=0;igetPairCache()->getNumOverlappingPairs();i++) + { + const btBroadphasePair& collisionPair = pairPtr[i]; + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && ((colObj1) && ((colObj1)->mergesSimulationIslands()))) @@ -71,7 +85,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld } // do the union find - findUnions(dispatcher); + findUnions(dispatcher,colWorld); @@ -129,30 +143,13 @@ class btPersistentManifoldSortPredicate }; - - - -// -// todo: this is random access, it can be walked 'cache friendly'! -// -void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) +void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects) { + BT_PROFILE("islandUnionFindAndQuickSort"); - - /*if (0) - { - int maxNumManifolds = dispatcher->getNumManifolds(); - btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher; - btPersistentManifold** manifold = colDis->getInternalManifoldPointer(); - callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0); - return; - } - */ + m_islandmanifold.resize(0); - - BEGIN_PROFILE("islandUnionFindAndHeapSort"); - //we are going to sort the unionfind array, and store the element id in the size //afterwards, we clean unionfind, to make sure no-one uses it anymore @@ -183,7 +180,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { - printf("error in island management\n"); +// printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -210,7 +207,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { - printf("error in island management\n"); +// printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -231,7 +228,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { - printf("error in island management\n"); +// printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -247,11 +244,17 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, } } - btAlignedObjectArray islandmanifold; + int i; int maxNumManifolds = dispatcher->getNumManifolds(); - islandmanifold.reserve(maxNumManifolds); +#define SPLIT_ISLANDS 1 +#ifdef SPLIT_ISLANDS + + +#endif //SPLIT_ISLANDS + + for (i=0;igetManifoldByIndexInternal(i); @@ -265,29 +268,52 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, { //kinematic objects don't merge islands, but wake up all connected objects - if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) { colObj1->activate(); } - if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) { colObj0->activate(); } - - //filtering for response +#ifdef SPLIT_ISLANDS + // //filtering for response if (dispatcher->needsResponse(colObj0,colObj1)) - islandmanifold.push_back(manifold); + m_islandmanifold.push_back(manifold); +#endif //SPLIT_ISLANDS } } +} - int numManifolds = int (islandmanifold.size()); + +// +// todo: this is random access, it can be walked 'cache friendly'! +// +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) +{ + + buildIslands(dispatcher,collisionObjects); + + int endIslandIndex=1; + int startIslandIndex; + int numElem = getUnionFind().getNumElements(); + + BT_PROFILE("processIslands"); + +#ifndef SPLIT_ISLANDS + btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); + + callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); +#else // Sort manifolds, based on islands // Sort the vector using predicate and std::sort //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); + int numManifolds = int (m_islandmanifold.size()); + //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) - islandmanifold.heapSort(btPersistentManifoldSortPredicate()); + m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) @@ -296,10 +322,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, //int islandId; - END_PROFILE("islandUnionFindAndHeapSort"); - - btAlignedObjectArray islandBodies; + +// printf("Start Islands\n"); //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated for ( startIslandIndex=0;startIslandIndexisActive()) islandSleeping = true; } @@ -325,12 +350,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, if (startManifoldIndexProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); + callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); +// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); } if (numIslandManifolds) @@ -350,8 +376,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, startManifoldIndex = endManifoldIndex; } - islandBodies.resize(0); + m_islandBodies.resize(0); } +#endif //SPLIT_ISLANDS + - } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index d91ed1c20eb..5f4d54cd803 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -16,18 +16,26 @@ subject to the following restrictions: #ifndef SIMULATION_ISLAND_MANAGER_H #define SIMULATION_ISLAND_MANAGER_H -#include "../CollisionDispatch/btUnionFind.h" +#include "BulletCollision/CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" + class btCollisionObject; class btCollisionWorld; class btDispatcher; +class btPersistentManifold; + ///SimulationIslandManager creates and handles simulation islands, using btUnionFind class btSimulationIslandManager { btUnionFind m_unionFind; + btAlignedObjectArray m_islandmanifold; + btAlignedObjectArray m_islandBodies; + + public: btSimulationIslandManager(); virtual ~btSimulationIslandManager(); @@ -42,7 +50,7 @@ public: virtual void storeIslandActivationState(btCollisionWorld* world); - void findUnions(btDispatcher* dispatcher); + void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); @@ -55,6 +63,8 @@ public: void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); + void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects); + }; #endif //SIMULATION_ISLAND_MANAGER_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp index 05556bd34e2..1e4bbce451d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -68,18 +68,25 @@ void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,b btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); + resultOut->setPersistentManifold(m_manifoldPtr); + if (dist < SIMD_EPSILON) { btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); } - + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } } @@ -102,8 +109,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* box btVector3 bounds[2]; btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); - bounds[0] = -boxShape->getHalfExtents(); - bounds[1] = boxShape->getHalfExtents(); + bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); + bounds[1] = boxShape->getHalfExtentsWithoutMargin(); margins = boxShape->getMargin();//also add sphereShape margin? @@ -209,6 +216,10 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* btVector3 p0, tmp, prel, n[6], normal; btScalar fSep = btScalar(-10000000.0), fSepThis; + // set p0 and normal to a default value to shup up GCC + p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h index 07592909200..158f0ffcc74 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -16,11 +16,13 @@ subject to the following restrictions: #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H #define SPHERE_BOX_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; -#include "../../LinearMath/btVector3.h" +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" /// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -40,6 +42,14 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); @@ -48,12 +58,13 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); if (!m_swapped) { - return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); } else { - return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); } } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp index 424ff432f84..c9256473c00 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -46,6 +46,8 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 if (!m_manifoldPtr) return; + resultOut->setPersistentManifold(m_manifoldPtr); + btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); @@ -54,23 +56,34 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 btScalar radius0 = sphere0->getRadius(); btScalar radius1 = sphere1->getRadius(); + //m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting + ///iff distance positive, don't generate a new contact if ( len > (radius0+radius1)) + { return; - + } ///distance (negative means penetration) btScalar dist = len - (radius0+radius1); - btVector3 normalOnSurfaceB = diff / len; + btVector3 normalOnSurfaceB(1,0,0); + if (len > SIMD_EPSILON) + { + normalOnSurfaceB = diff / len; + } + ///point on A (worldspace) btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; ///point on B (worldspace) btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); + + resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); + //no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new) + } btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h index 7a19ff31edf..afdc2ee7fa0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -16,9 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H #define SPHERE_SPHERE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + class btPersistentManifold; /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. @@ -39,6 +41,13 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } virtual ~btSphereSphereCollisionAlgorithm(); @@ -46,7 +55,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); + return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index b011b707e3f..fdbd4abef27 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -48,8 +48,11 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co if (!m_manifoldPtr) return; - btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape(); - btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape(); + btCollisionObject* sphereObj = m_swapped? col1 : col0; + btCollisionObject* triObj = m_swapped? col0 : col1; + + btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); /// report a contact. internally this will be kept persistent, and contact reduction is done resultOut->setPersistentManifold(m_manifoldPtr); @@ -57,11 +60,16 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co btDiscreteCollisionDetectorInterface::ClosestPointInput input; input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds - input.m_transformA = col0->getWorldTransform(); - input.m_transformB = col1->getWorldTransform(); + input.m_transformA = sphereObj->getWorldTransform(); + input.m_transformB = triObj->getWorldTransform(); - detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + bool swapResults = m_swapped; + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); + + if (m_ownManifold) + resultOut->refreshContactPoints(); + } btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h index 57c6e6af619..bbaf228c44c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -16,10 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; +#include "btCollisionDispatcher.h" /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -40,6 +41,13 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } virtual ~btSphereTriangleCollisionAlgorithm(); @@ -49,7 +57,9 @@ public: virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); + + return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp index 62254335796..bb01b60fa85 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -18,6 +18,7 @@ subject to the following restrictions: + btUnionFind::~btUnionFind() { Free(); @@ -76,8 +77,7 @@ void btUnionFind::sortIslands() // Sort the vector using predicate and std::sort //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate); - //perhaps use radix sort? - m_elements.heapSort(btUnionFindElementSortPredicate()); + m_elements.quickSort(btUnionFindElementSortPredicate()); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h index 236cc33b94f..820c8bc858e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef UNION_FIND_H #define UNION_FIND_H -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" #define USE_PATH_COMPRESSION 1 @@ -46,11 +46,11 @@ class btUnionFind void reset(int N); - inline int getNumElements() const + SIMD_FORCE_INLINE int getNumElements() const { return int(m_elements.size()); } - inline bool isRoot(int x) const + SIMD_FORCE_INLINE bool isRoot(int x) const { return (x == m_elements[x].m_id); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp index 636b0046c13..8bc2cfa6ffa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -15,35 +15,20 @@ subject to the following restrictions: #include "btBoxShape.h" -btVector3 btBoxShape::getHalfExtents() const -{ - return m_implicitShapeDimensions * m_localScaling; -} + //{ void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { - btVector3 halfExtents = getHalfExtents(); - - btMatrix3x3 abs_b = t.getBasis().absolute(); - btPoint3 center = t.getOrigin(); - btVector3 extent = btVector3(abs_b[0].dot(halfExtents), - abs_b[1].dot(halfExtents), - abs_b[2].dot(halfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - - aabbMin = center - extent; - aabbMax = center + extent; - - + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); } -void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //btScalar margin = btScalar(0.); - btVector3 halfExtents = getHalfExtents(); + btVector3 halfExtents = getHalfExtentsWithMargin(); btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h index bc42f146c7c..4d4fbefea37 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -18,11 +18,11 @@ subject to the following restrictions: #include "btPolyhedralConvexShape.h" #include "btCollisionMargin.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btSimdMinMax.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btMinMax.h" -///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box +///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. class btBoxShape: public btPolyhedralConvexShape { @@ -31,47 +31,52 @@ class btBoxShape: public btPolyhedralConvexShape public: - btVector3 getHalfExtents() const; - + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included + } + + virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} virtual btVector3 localGetSupportingVertex(const btVector3& vec) const { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; - btVector3 halfExtents = getHalfExtents(); - - btVector3 supVertex; - supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); - - return supVertex; + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); } - virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - btVector3 halfExtents = getHalfExtents(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents -= margin; - - return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); } virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { - btVector3 halfExtents = getHalfExtents(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents -= margin; - - + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + for (int i=0;icalculateAabbBruteForce(bvhAabbMin,bvhAabbMax); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + if(meshInterface->hasPremadeAabb()) + { + meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax); + } + else + { + meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); + } + + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } #endif //DISABLE_BVH } -btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) -:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) { //construct bvh from meshInterface #ifndef DISABLE_BVH - m_bvh = new btOptimizedBvh(); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } #endif //DISABLE_BVH @@ -58,16 +82,140 @@ void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btV } -void btBvhTriangleMeshShape::refitTree() +void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax) { - m_bvh->refit( m_meshInterface ); + m_bvh->refit( m_meshInterface, aabbMin,aabbMax ); recalcLocalAabb(); } btBvhTriangleMeshShape::~btBvhTriangleMeshShape() { - delete m_bvh; + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } +} + +void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget); +} + +void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); } //perform bvh tree traversal and report overlapping triangles to 'callback' @@ -118,13 +266,14 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co indicestype, nodeSubPart); - int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); const btVector3& meshScaling = m_meshInterface->getScaling(); for (int j=2;j>=0;j--) { - int graphicsindex = gfxbase[j]; + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; #ifdef DEBUG_TRIANGLE_MESH @@ -157,17 +306,37 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co } - -void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) { - if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) - { - btTriangleMeshShape::setLocalScaling(scaling); - delete m_bvh; - ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work - m_bvh = new btOptimizedBvh(); - //rebuild the bvh... - m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); - - } + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } + ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new(mem) btOptimizedBvh(); + //rebuild the bvh... + m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); + m_ownsBvh = true; + } } + +void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling) +{ + btAssert(!m_bvh); + btAssert(!m_ownsBvh); + + m_bvh = bvh; + m_ownsBvh = false; + // update the scaling without rebuilding the bvh + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + } +} + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index 4914d9f959c..6e587340dc1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -18,45 +18,55 @@ subject to the following restrictions: #include "btTriangleMeshShape.h" #include "btOptimizedBvh.h" +#include "LinearMath/btAlignedAllocator.h" -///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. -///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. + +///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage. +///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method. +///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk. +///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example. ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape { btOptimizedBvh* m_bvh; bool m_useQuantizedAabbCompression; - bool m_pad[12];////need padding due to alignment + bool m_ownsBvh; + bool m_pad[11];////need padding due to alignment public: - btBvhTriangleMeshShape() :btTriangleMeshShape(0) {}; - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression); + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {}; + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); virtual ~btBvhTriangleMeshShape(); - - /* + bool getOwnsBvh () const + { + return m_ownsBvh; + } + virtual int getShapeType() const { return TRIANGLE_MESH_SHAPE_PROXYTYPE; } - */ - - + + void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget); + void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax); virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - void refitTree(); + void refitTree(const btVector3& aabbMin,const btVector3& aabbMax); ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); //debugging - virtual char* getName()const {return "BVHTRIANGLEMESH";} + virtual const char* getName()const {return "BVHTRIANGLEMESH";} virtual void setLocalScaling(const btVector3& scaling); @@ -65,6 +75,10 @@ public: { return m_bvh; } + + + void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1)); + bool usesQuantizedAabbCompression() const { return m_useQuantizedAabbCompression; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index b7e15172da2..26ba276b900 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -21,6 +21,7 @@ subject to the following restrictions: btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) { + m_upAxis = 1; m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); } @@ -50,7 +51,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) { - btVector3 pos(0,getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = getHalfHeight(); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -60,7 +63,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } } { - btVector3 pos(0,-getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -88,7 +93,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) btVector3 vtx; btScalar newDot; { - btVector3 pos(0,getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = getHalfHeight(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -98,7 +104,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } } { - btVector3 pos(0,-getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -112,7 +119,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } -void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //as an approximation, take the inertia of the box that bounds the spheres @@ -122,7 +129,8 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) btScalar radius = getRadius(); - btVector3 halfExtents(radius,radius+getHalfHeight(),radius); + btVector3 halfExtents(radius,radius,radius); + halfExtents[getUpAxis()]+=getHalfHeight(); btScalar margin = CONVEX_DISTANCE_MARGIN; @@ -140,6 +148,22 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) } +btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) +{ + m_upAxis = 0; + m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); +} + + + + + + +btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) +{ + m_upAxis = 2; + m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h index 27da8adefa5..d4b046d40c9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -16,20 +16,27 @@ subject to the following restrictions: #ifndef BT_CAPSULE_SHAPE_H #define BT_CAPSULE_SHAPE_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -///btCapsuleShape represents a capsule around the Y axis -///A more general solution that can represent capsules is the btMultiSphereShape -class btCapsuleShape : public btConvexShape +///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis. +///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres. +class btCapsuleShape : public btConvexInternalShape { +protected: + int m_upAxis; + +protected: + ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. + btCapsuleShape() {}; public: btCapsuleShape(btScalar radius,btScalar height); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -38,23 +45,76 @@ public: virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const + { + btVector3 halfExtents(getRadius(),getRadius(),getRadius()); + halfExtents[m_upAxis] = getRadius() + getHalfHeight(); + halfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btPoint3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + + aabbMin = center - extent; + aabbMax = center + extent; + } + + virtual const char* getName()const { return "CapsuleShape"; } + int getUpAxis() const + { + return m_upAxis; + } + btScalar getRadius() const { - return m_implicitShapeDimensions.getX(); + int radiusAxis = (m_upAxis+2)%3; + return m_implicitShapeDimensions[radiusAxis]; } btScalar getHalfHeight() const { - return m_implicitShapeDimensions.getY(); + return m_implicitShapeDimensions[m_upAxis]; } }; +///btCapsuleShapeX represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeX : public btCapsuleShape +{ +public: + + btCapsuleShapeX(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleX"; + } + + + +}; + +///btCapsuleShapeZ represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeZ : public btCapsuleShape +{ +public: + btCapsuleShapeZ(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleZ"; + } + + +}; + #endif //BT_CAPSULE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp index 81d82428f4c..39e621aa946 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -21,7 +21,12 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" void btBulletCollisionProbe () {} +extern "C" +{ +void btBulletCollisionProbe (); + +void btBulletCollisionProbe () {} +} @@ -46,7 +51,7 @@ btScalar btCollisionShape::getAngularMotionDisc() const return disc; } -void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) +void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const { //start with static aabb getAabb(curTrans,temporalAabbMin,temporalAabbMax); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h index 96268734a83..3a352b90777 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -16,18 +16,21 @@ subject to the following restrictions: #ifndef COLLISION_SHAPE_H #define COLLISION_SHAPE_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btMatrix3x3.h" -#include "../../LinearMath/btPoint3.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btPoint3.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types -///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. +///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. class btCollisionShape { + + void* m_userPointer; + public: - btCollisionShape() + btCollisionShape() : m_userPointer(0) { } virtual ~btCollisionShape() @@ -45,30 +48,30 @@ public: ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) ///result is conservative - void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax); + void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const; #ifndef __SPU__ - inline bool isPolyhedral() const + SIMD_FORCE_INLINE bool isPolyhedral() const { return btBroadphaseProxy::isPolyhedral(getShapeType()); } - inline bool isConvex() const + SIMD_FORCE_INLINE bool isConvex() const { return btBroadphaseProxy::isConvex(getShapeType()); } - inline bool isConcave() const + SIMD_FORCE_INLINE bool isConcave() const { return btBroadphaseProxy::isConcave(getShapeType()); } - inline bool isCompound() const + SIMD_FORCE_INLINE bool isCompound() const { return btBroadphaseProxy::isCompound(getShapeType()); } ///isInfinite is used to catch simulation error (aabb check) - inline bool isInfinite() const + SIMD_FORCE_INLINE bool isInfinite() const { return btBroadphaseProxy::isInfinite(getShapeType()); } @@ -76,11 +79,11 @@ public: virtual int getShapeType() const=0; virtual void setLocalScaling(const btVector3& scaling) =0; virtual const btVector3& getLocalScaling() const =0; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; //debugging support - virtual char* getName()const =0 ; + virtual const char* getName()const =0 ; #endif //__SPU__ @@ -88,6 +91,18 @@ public: virtual void setMargin(btScalar margin) = 0; virtual btScalar getMargin() const = 0; + + ///optional user data pointer + void setUserPointer(void* userPtr) + { + m_userPointer = userPtr; + } + + void* getUserPointer() const + { + return m_userPointer; + } + }; #endif //COLLISION_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index a4712b3e925..f08b810eadb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -14,29 +14,42 @@ subject to the following restrictions: */ #include "btCompoundShape.h" - - #include "btCollisionShape.h" - +#include "BulletCollision/BroadphaseCollision/btDbvt.h" btCompoundShape::btCompoundShape() :m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), -m_aabbTree(0), m_collisionMargin(btScalar(0.)), -m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_dynamicAabbTree(0) { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); } btCompoundShape::~btCompoundShape() { + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->~btDbvt(); + btAlignedFree(m_dynamicAabbTree); + } } void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) { - m_childTransforms.push_back(localTransform); - m_childShapes.push_back(shape); + //m_childTransforms.push_back(localTransform); + //m_childShapes.push_back(shape); + btCompoundShapeChild child; + child.m_transform = localTransform; + child.m_childShape = shape; + child.m_childShapeType = shape->getShapeType(); + child.m_childMargin = shape->getMargin(); + + m_children.push_back(child); //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; @@ -53,39 +66,100 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio } } + if (m_dynamicAabbTree) + { + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + int index = m_children.size()-1; + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + } +void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) +{ + btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); + } + m_children.swap(childShapeIndex,m_children.size()-1); + m_children.pop_back(); + +} + +void btCompoundShape::removeChildShape(btCollisionShape* shape) +{ + // Find the children containing the shape specified, and remove those children. + //note: there might be multiple children using the same shape! + for(int i = m_children.size()-1; i >= 0 ; i--) + { + if(m_children[i].m_childShape == shape) + { + m_children.swap(i,m_children.size()-1); + m_children.pop_back(); + //remove it from the m_dynamicAabbTree too + //m_dynamicAabbTree->remove(m_aabbProxies[i]); + //m_aabbProxies.swap(i,m_children.size()-1); + //m_aabbProxies.pop_back(); + } + } - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + + recalculateLocalAabb(); +} + +void btCompoundShape::recalculateLocalAabb() +{ + // Recalculate the local aabb + // Brute force, it iterates over all the shapes left. + m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + + //extend the local aabbMin/aabbMax + for (int j = 0; j < m_children.size(); j++) + { + btVector3 localAabbMin,localAabbMax; + m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + m_localAabbMin[i] = localAabbMin[i]; + if (m_localAabbMax[i] < localAabbMax[i]) + m_localAabbMax[i] = localAabbMax[i]; + } + } +} + +///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - + btMatrix3x3 abs_b = trans.getBasis().absolute(); btPoint3 center = trans(localCenter); btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center-extent; + aabbMax = center+extent; - aabbMin = center - extent; - aabbMax = center + extent; } -void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //approximation: take the inertia from the aabb for now btTransform ident; ident.setIdentity(); btVector3 aabbMin,aabbMax; getAabb(ident,aabbMin,aabbMax); - + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); - + btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); btScalar lz=btScalar(2.)*(halfExtents.z()); @@ -96,5 +170,62 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) } - - + + + +void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const +{ + int n = m_children.size(); + + btScalar totalMass = 0; + btVector3 center(0, 0, 0); + for (int k = 0; k < n; k++) + { + center += m_children[k].m_transform.getOrigin() * masses[k]; + totalMass += masses[k]; + } + center /= totalMass; + principal.setOrigin(center); + + btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); + for (int k = 0; k < n; k++) + { + btVector3 i; + m_children[k].m_childShape->calculateLocalInertia(masses[k], i); + + const btTransform& t = m_children[k].m_transform; + btVector3 o = t.getOrigin() - center; + + //compute inertia tensor in coordinate system of compound shape + btMatrix3x3 j = t.getBasis().transpose(); + j[0] *= i[0]; + j[1] *= i[1]; + j[2] *= i[2]; + j = t.getBasis() * j; + + //add inertia tensor + tensor[0] += j[0]; + tensor[1] += j[1]; + tensor[2] += j[2]; + + //compute inertia tensor of pointmass at o + btScalar o2 = o.length2(); + j[0].setValue(o2, 0, 0); + j[1].setValue(0, o2, 0); + j[2].setValue(0, 0, o2); + j[0] += o * -o.x(); + j[1] += o * -o.y(); + j[2] += o * -o.z(); + + //add inertia tensor of pointmass + tensor[0] += masses[k] * j[0]; + tensor[1] += masses[k] * j[1]; + tensor[2] += masses[k] * j[2]; + } + + tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); +} + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index 86dc1f80947..3624749f768 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -18,58 +18,97 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" -class btOptimizedBvh; +//class btOptimizedBvh; +struct btDbvt; + +ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTransform m_transform; + btCollisionShape* m_childShape; + int m_childShapeType; + btScalar m_childMargin; + struct btDbvtNode* m_node; +}; + +SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) +{ + return ( c1.m_transform == c2.m_transform && + c1.m_childShape == c2.m_childShape && + c1.m_childShapeType == c2.m_childShapeType && + c1.m_childMargin == c2.m_childMargin ); +} /// btCompoundShape allows to store multiple other btCollisionShapes -/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. -class btCompoundShape : public btCollisionShape +/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. +ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape { - btAlignedObjectArray m_childTransforms; - btAlignedObjectArray m_childShapes; + //btAlignedObjectArray m_childTransforms; + //btAlignedObjectArray m_childShapes; + btAlignedObjectArray m_children; btVector3 m_localAabbMin; btVector3 m_localAabbMax; - btOptimizedBvh* m_aabbTree; + //btOptimizedBvh* m_aabbTree; + btDbvt* m_dynamicAabbTree; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btCompoundShape(); virtual ~btCompoundShape(); void addChildShape(const btTransform& localTransform,btCollisionShape* shape); + /// Remove all children shapes that contain the specified shape + virtual void removeChildShape(btCollisionShape* shape); + + void removeChildShapeByIndex(int childShapeindex); + + int getNumChildShapes() const { - return int (m_childShapes.size()); + return int (m_children.size()); } btCollisionShape* getChildShape(int index) { - return m_childShapes[index]; + return m_children[index].m_childShape; } const btCollisionShape* getChildShape(int index) const { - return m_childShapes[index]; + return m_children[index].m_childShape; } - btTransform& getChildTransform(int index) + btTransform getChildTransform(int index) { - return m_childTransforms[index]; + return m_children[index].m_transform; } - const btTransform& getChildTransform(int index) const + const btTransform getChildTransform(int index) const { - return m_childTransforms[index]; + return m_children[index].m_transform; + } + + + btCompoundShapeChild* getChildList() + { + return &m_children[0]; } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. + Use this yourself if you modify the children or their transforms. */ + virtual void recalculateLocalAabb(); virtual void setLocalScaling(const btVector3& scaling) { @@ -80,8 +119,8 @@ public: return m_localScaling; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); - + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} virtual void setMargin(btScalar margin) @@ -92,7 +131,7 @@ public: { return m_collisionMargin; } - virtual char* getName()const + virtual const char* getName()const { return "Compound"; } @@ -100,11 +139,19 @@ public: //this is optional, but should make collision queries faster, by culling non-overlapping nodes void createAabbTreeFromChildren(); - const btOptimizedBvh* getAabbTree() const + btDbvt* getDynamicAabbTree() { - return m_aabbTree; + return m_dynamicAabbTree; } + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform + ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. + void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; + + private: btScalar m_collisionMargin; protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h index 73f974e4ee9..f3f57206ab7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -17,12 +17,12 @@ subject to the following restrictions: #define CONCAVE_SHAPE_H #include "btCollisionShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "btTriangleCallback.h" -///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB. -///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface. +///The btConcaveShape class provides an interface for non-moving (static) concave shapes. +///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. class btConcaveShape : public btCollisionShape { protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h index 3ccda5b12c6..685369742e4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef CONE_MINKOWSKI_H #define CONE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -///btConeShape implements a Cone shape, around the Y axis -class btConeShape : public btConvexShape +///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis. +class btConeShape : public btConvexInternalShape { @@ -42,7 +42,7 @@ public: btScalar getHeight() const { return m_height;} - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { btTransform identity; identity.setIdentity(); @@ -72,7 +72,7 @@ public: virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual const char* getName()const { return "Cone"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h index 3fd5e382525..c029ca19403 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -17,18 +17,17 @@ subject to the following restrictions: #define CONVEX_HULL_SHAPE_H #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" -///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) -///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. -///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash. -///(memory is much slower then the cpu) +///The btConvexHullShape implements an implicit convex hull of an array of vertices. +///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex. ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape { btAlignedObjectArray m_points; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. @@ -43,7 +42,12 @@ public: return &m_points[0]; } - int getNumPoints() + const btPoint3* getPoints() const + { + return &m_points[0]; + } + + int getNumPoints() const { return m_points.size(); } @@ -56,7 +60,7 @@ public: virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } //debugging - virtual char* getName()const {return "Convex";} + virtual const char* getName()const {return "Convex";} virtual int getNumVertices() const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp new file mode 100644 index 00000000000..f828d28e18c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp @@ -0,0 +1,78 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConvexInternalShape.h" + + +btConvexInternalShape::btConvexInternalShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexInternalShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + + + +void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +}; + + +btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + return btVector3(0,0,0); +#endif //__SPU__ + + } + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h new file mode 100644 index 00000000000..9388ccf31f2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -0,0 +1,98 @@ + +#ifndef BT_CONVEX_INTERNAL_SHAPE_H +#define BT_CONVEX_INTERNAL_SHAPE_H + +#include "btConvexShape.h" + +///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. +class btConvexInternalShape : public btConvexShape +{ + + protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding; + +public: + + btConvexInternalShape(); + + virtual ~btConvexInternalShape() + { + + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; + + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; +#endif //#ifndef __SPU__ + + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } + + + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + + + +}; + + +#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp index 7edf1ea6db8..7afcccf8b03 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -16,62 +16,3 @@ subject to the following restrictions: #include "btConvexShape.h" -btConvexShape::btConvexShape() -: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_collisionMargin(CONVEX_DISTANCE_MARGIN) -{ -} - - -void btConvexShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} - - - -void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const -{ - - btScalar margin = getMargin(); - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - - btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); - - btVector3 tmp = trans(sv); - maxAabb[i] = tmp[i]+margin; - vec[i] = btScalar(-1.); - tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); - minAabb[i] = tmp[i]-margin; - } -}; - - -btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const -{ -#ifndef __SPU__ - - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; - -#else - return btVector3(0,0,0); -#endif //__SPU__ - - } - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h index 746f383dfc7..e4eb7f6dbf6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -18,37 +18,25 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" +#include "LinearMath/btAlignedAllocator.h" //todo: get rid of this btConvexCastResult thing! struct btConvexCastResult; #define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 -/// btConvexShape is an abstract shape interface. -/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface. -/// used in combination with GJK or btConvexCast +/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc. +/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector. ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape { -protected: - - //local scaling. collisionMargin is not scaled ! - btVector3 m_localScaling; - - btVector3 m_implicitShapeDimensions; - - btScalar m_collisionMargin; - - btScalar m_padding[2]; - - - public: - btConvexShape(); + + BT_DECLARE_ALIGNED_ALLOCATOR(); virtual ~btConvexShape() { @@ -56,7 +44,7 @@ public: } - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0; #ifndef __SPU__ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; @@ -64,63 +52,24 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; #endif //#ifndef __SPU__ - const btVector3& getImplicitShapeDimensions() const - { - return m_implicitShapeDimensions; - } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - getAabbSlow(t,aabbMin,aabbMax); - } + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + + virtual void setMargin(btScalar margin)=0; + + virtual btScalar getMargin() const=0; + + virtual int getNumPreferredPenetrationDirections() const=0; - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const - { - return m_localScaling; - } - - const btVector3& getLocalScalingNV() const - { - return m_localScaling; - } - - virtual void setMargin(btScalar margin) - { - m_collisionMargin = margin; - } - virtual btScalar getMargin() const - { - return m_collisionMargin; - } - - btScalar getMarginNV() const - { - return m_collisionMargin; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 0; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - (void)penetrationVector; - (void)index; - btAssert(0); - } - - - -} -; +}; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp index 6941030b15f..02a293e82ba 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -19,10 +19,11 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" -btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface) +btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) :m_stridingMesh(meshInterface) { - recalcLocalAabb(); + if ( calcAabb ) + recalcLocalAabb(); } @@ -203,3 +204,113 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const { return m_stridingMesh->getScaling(); } + +void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const +{ + class CenterCallback: public btInternalTriangleIndexCallback + { + bool first; + btVector3 ref; + btVector3 sum; + btScalar volume; + + public: + + CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + if (first) + { + ref = triangle[0]; + first = false; + } + else + { + btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); + sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); + volume += vol; + } + } + + btVector3 getCenter() + { + return (volume > 0) ? sum / volume : ref; + } + + btScalar getVolume() + { + return volume * btScalar(1. / 6); + } + + }; + + class InertiaCallback: public btInternalTriangleIndexCallback + { + btMatrix3x3 sum; + btVector3 center; + + public: + + InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + btMatrix3x3 i; + btVector3 a = triangle[0] - center; + btVector3 b = triangle[1] - center; + btVector3 c = triangle[2] - center; + btVector3 abc = a + b + c; + btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); + for (int j = 0; j < 3; j++) + { + for (int k = 0; k <= j; k++) + { + i[j][k] = i[k][j] = volNeg * (center[j] * center[k] + + btScalar(0.25) * (center[j] * abc[k] + center[k] * abc[j]) + + btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); + } + } + btScalar i00 = -i[0][0]; + btScalar i11 = -i[1][1]; + btScalar i22 = -i[2][2]; + i[0][0] = i11 + i22; + i[1][1] = i22 + i00; + i[2][2] = i00 + i11; + sum[0] += i[0]; + sum[1] += i[1]; + sum[2] += i[2]; + } + + btMatrix3x3& getInertia() + { + return sum; + } + + }; + + CenterCallback centerCallback; + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); + btVector3 center = centerCallback.getCenter(); + principal.setOrigin(center); + volume = centerCallback.getVolume(); + + InertiaCallback inertiaCallback(center); + m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); + + btMatrix3x3& i = inertiaCallback.getInertia(); + i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(i[0][0], i[1][1], i[2][2]); + inertia /= volume; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h index 34ee7af744c..6ff0bf5d43b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -3,20 +3,24 @@ #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. -/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data. +/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape. +/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead. class btConvexTriangleMeshShape : public btPolyhedralConvexShape { class btStridingMeshInterface* m_stridingMesh; public: - btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); + btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true); - class btStridingMeshInterface* getStridingMesh() + class btStridingMeshInterface* getMeshInterface() + { + return m_stridingMesh; + } + const class btStridingMeshInterface* getMeshInterface() const { return m_stridingMesh; } @@ -28,7 +32,7 @@ public: virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } //debugging - virtual char* getName()const {return "ConvexTrimesh";} + virtual const char* getName()const {return "ConvexTrimesh";} virtual int getNumVertices() const; virtual int getNumEdges() const; @@ -42,6 +46,13 @@ public: virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" + ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. This method also computes the volume of the convex mesh. + void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; + }; @@ -49,3 +60,4 @@ public: #endif //CONVEX_TRIANGLEMESH_SHAPE_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp index 1666afb3b88..3afef1c7550 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -45,7 +45,7 @@ void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& } -inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) { const int cylinderUpAxis = 0; const int XX = 1; @@ -163,24 +163,24 @@ const int ZZ = 1; btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportX(getHalfExtents(),vec); + return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); } btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportZ(getHalfExtents(),vec); + return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); } btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportY(getHalfExtents(),vec); + return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); } void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { for (int i=0;i=0); btAssert(y>=0); - btAssert(xstartX) startX = quantizedAabbMin[1]; @@ -243,10 +240,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback } case 1: { - quantizedAabbMin[0]+=m_width/2-1; - quantizedAabbMax[0]+=m_width/2+1; - quantizedAabbMin[2]+=m_length/2-1; - quantizedAabbMax[2]+=m_length/2+1; + quantizedAabbMin[0]+=m_heightStickWidth/2-1; + quantizedAabbMax[0]+=m_heightStickWidth/2+1; + quantizedAabbMin[2]+=m_heightStickLength/2-1; + quantizedAabbMax[2]+=m_heightStickLength/2+1; if (quantizedAabbMin[0]>startX) startX = quantizedAabbMin[0]; @@ -260,10 +257,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback }; case 2: { - quantizedAabbMin[0]+=m_width/2-1; - quantizedAabbMax[0]+=m_width/2+1; - quantizedAabbMin[1]+=m_length/2-1; - quantizedAabbMax[1]+=m_length/2+1; + quantizedAabbMin[0]+=m_heightStickWidth/2-1; + quantizedAabbMax[0]+=m_heightStickWidth/2+1; + quantizedAabbMin[1]+=m_heightStickLength/2-1; + quantizedAabbMax[1]+=m_heightStickLength/2+1; if (quantizedAabbMin[0]>startX) startX = quantizedAabbMin[0]; @@ -290,7 +287,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback for(int x=startX; xlocalGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); + btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(-vec*m_transA.getBasis())); btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis())); - return supVertexA + supVertexB; + return supVertexA - supVertexB; } void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const @@ -49,7 +49,7 @@ btScalar btMinkowskiSumShape::getMargin() const } -void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; btAssert(0); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h index 198faaff9f9..f9c8427c2f3 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef MINKOWSKI_SUM_SHAPE_H #define MINKOWSKI_SUM_SHAPE_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -/// btMinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes. -class btMinkowskiSumShape : public btConvexShape +/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes. +class btMinkowskiSumShape : public btConvexInternalShape { btTransform m_transA; @@ -37,7 +37,7 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; void setTransformA(const btTransform& transA) { m_transA = transA;} void setTransformB(const btTransform& transB) { m_transB = transB;} @@ -53,7 +53,7 @@ public: const btConvexShape* getShapeA() const { return m_shapeA;} const btConvexShape* getShapeB() const { return m_shapeB;} - virtual char* getName()const + virtual const char* getName()const { return "MinkowskiSum"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp index 6015a618082..c709205efc2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -47,7 +47,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons btVector3 vec = vec0; btScalar lenSqr = vec.length2(); - if (lenSqr < btScalar(0.0001)) + if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON)) { vec.setValue(1,0,0); } else @@ -116,7 +116,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons -void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //as an approximation, take the inertia of the box that bounds the spheres diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h index 1897b474057..45968f3947f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -16,13 +16,14 @@ subject to the following restrictions: #ifndef MULTI_SPHERE_MINKOWSKI_H #define MULTI_SPHERE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types #define MAX_NUM_SPHERES 5 -///btMultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex) -class btMultiSphereShape : public btConvexShape +///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes. +///It is possible to animate the spheres for deformation. +class btMultiSphereShape : public btConvexInternalShape { @@ -39,7 +40,7 @@ public: btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -63,7 +64,7 @@ public: virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual const char* getName()const { return "MultiSphere"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp new file mode 100644 index 00000000000..fc47e86411d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp @@ -0,0 +1,45 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/// This file was created by Alex Silverman + +#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h" +//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" + + +///Obtains the material for a specific triangle +const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex) +{ + const unsigned char * materialBase = 0; + int numMaterials; + PHY_ScalarType materialType; + int materialStride; + const unsigned char * triangleMaterialBase = 0; + int numTriangles; + int triangleMaterialStride; + PHY_ScalarType triangleType; + + ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, + &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID); + + // return the pointer to the place with the friction for the triangle + // TODO: This depends on whether it's a moving mesh or not + // BUG IN GIMPACT + //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]); + int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)])); + btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride])); + return (matVal); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h new file mode 100644 index 00000000000..2f108020cdf --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h @@ -0,0 +1,124 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/// This file was created by Alex Silverman + +#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H + +#include "btBvhTriangleMeshShape.h" +#include "btMaterial.h" + +///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution. +ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape +{ + btAlignedObjectArray m_materialList; + int ** m_triangleMaterials; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {} + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16)); + } + } + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16)); + } + } + + virtual ~btMultimaterialTriangleMeshShape() + { +/* + for(int i = 0; i < m_meshInterface->getNumSubParts(); i++) + { + btAlignedFree(m_materialValues[i]); + m_materialLookup[i] = NULL; + } + btAlignedFree(m_materialValues); + m_materialLookup = NULL; +*/ + } + virtual int getShapeType() const + { + return MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; + } + + //debugging + virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";} + + ///Obtains the material for a specific triangle + const btMaterial * getMaterialProperties(int partID, int triIndex); + +} +; + +#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp index 44438a24455..a248c55b571 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -19,13 +19,12 @@ subject to the following restrictions: #include "LinearMath/btIDebugDraw.h" - -btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false), - m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) - //m_traversalMode(TRAVERSAL_STACKLESS) - //m_traversalMode(TRAVERSAL_RECURSIVE) +btOptimizedBvh::btOptimizedBvh() { +} +btOptimizedBvh::~btOptimizedBvh() +{ } @@ -80,7 +79,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback { QuantizedNodeArray& m_triangleNodes; - const btOptimizedBvh* m_optimizedTree; // for quantization + const btQuantizedBvh* m_optimizedTree; // for quantization QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) { @@ -89,14 +88,16 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized return *this; } - QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree) + QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree) :m_triangleNodes(triangleNodes),m_optimizedTree(tree) { } virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) { - btAssert(partId==0); + // The partId and triangle index must fit in the same (positive) integer + btAssert(partId < (1<=0); @@ -111,10 +112,29 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized aabbMin.setMin(triangle[2]); aabbMax.setMax(triangle[2]); - m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); - m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); + //PCK: add these checks for zero dimensions of aabb + const btScalar MIN_AABB_DIMENSION = btScalar(0.002); + const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); + if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) + { + aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); + aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) + { + aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); + aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) + { + aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); + aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); + } - node.m_escapeIndexOrTriangleIndex = triangleIndex; + m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; m_triangleNodes.push_back(node); } @@ -170,10 +190,45 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized subtree.m_rootNodeIndex = 0; subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); } + +void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_useQuantization) + { + + setQuantizationValues(aabbMin,aabbMax); + + updateBvhNodes(meshInterface,0,m_curNodeIndex,0); + + ///now update all subtree headers + + int i; + for (i=0;im_SubtreeHeaders.size();i++) { btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) { updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); @@ -212,36 +268,23 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b } -///just for debugging, to visualize the individual patches/subtrees -#ifdef DEBUG_PATCH_COLORS -btVector3 color[4]= -{ - btVector3(255,0,0), - btVector3(0,255,0), - btVector3(0,0,255), - btVector3(0,255,255) -}; -#endif //DEBUG_PATCH_COLORS - - void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) { (void)index; btAssert(m_useQuantization); - int nodeSubPart=0; + int curNodeSubPart=-1; //get access info to trianglemesh data - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + const unsigned char *vertexbase = 0; + int numverts = 0; + PHY_ScalarType type = PHY_INTEGER; + int stride = 0; + const unsigned char *indexbase = 0; + int indexstride = 0; + int numfaces = 0; + PHY_ScalarType indicestype = PHY_INTEGER; btVector3 triangleVerts[3]; btVector3 aabbMin,aabbMax; @@ -256,16 +299,26 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f if (curNode.isLeafNode()) { //recalc aabb from triangle data + int nodeSubPart = curNode.getPartId(); int nodeTriangleIndex = curNode.getTriangleIndex(); + if (nodeSubPart != curNodeSubPart) + { + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + + curNodeSubPart = nodeSubPart; + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + } //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, - int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); for (int j=2;j>=0;j--) { - int graphicsindex = gfxbase[j]; + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); #ifdef DEBUG_PATCH_COLORS btVector3 mycolor = color[index&3]; @@ -292,8 +345,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f aabbMin.setMin(triangleVerts[2]); aabbMax.setMax(triangleVerts[2]); - quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin); - quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax); + quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0); + quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1); } else { @@ -321,525 +374,17 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f } - meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); } -void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' +btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) { - //enlarge the AABB to avoid division by zero when initializing the quantization values - btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); - m_bvhAabbMin = bvhAabbMin - clampValue; - m_bvhAabbMax = bvhAabbMax + clampValue; - btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; - m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize; -} - - -void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface) -{ - if (m_useQuantization) - { - //calculate new aabb - btVector3 aabbMin,aabbMax; - meshInterface->calculateAabbBruteForce(aabbMin,aabbMax); - - setQuantizationValues(aabbMin,aabbMax); - - updateBvhNodes(meshInterface,0,m_curNodeIndex,0); - - ///now update all subtree headers - - int i; - for (i=0;i gMaxStackDepth) - gMaxStackDepth = gStackDepth; -#endif //DEBUG_TREE_BUILDING - - - int splitAxis, splitIndex, i; - int numIndices =endIndex-startIndex; - int curIndex = m_curNodeIndex; - - assert(numIndices>0); - - if (numIndices==1) - { -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); - - m_curNodeIndex++; - return; - } - //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian); - splitAxis = calcSplittingAxis(startIndex,endIndex); - - splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); - - int internalNodeIndex = m_curNodeIndex; - - setInternalNodeAabbMax(m_curNodeIndex,btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30))); - setInternalNodeAabbMin(m_curNodeIndex,btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30))); - - for (i=startIndex;im_escapeIndex; - - int leftChildNodexIndex = m_curNodeIndex; - - //build left child tree - buildTree(startIndex,splitIndex); - - int rightChildNodexIndex = m_curNodeIndex; - //build right child tree - buildTree(splitIndex,endIndex); - -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - int escapeIndex = m_curNodeIndex - curIndex; - - if (m_useQuantization) - { - //escapeIndex is the number of nodes of this subtree - const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); - const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; - if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) - { - updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); - } - } - - setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); - -} - -void btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) -{ - btAssert(m_useQuantization); - - btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; - int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); - int leftSubTreeSizeInBytes = leftSubTreeSize * sizeof(btQuantizedBvhNode); - - btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; - int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); - int rightSubTreeSizeInBytes = rightSubTreeSize * sizeof(btQuantizedBvhNode); - - if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(leftChildNode); - subtree.m_rootNodeIndex = leftChildNodexIndex; - subtree.m_subtreeSize = leftSubTreeSize; - } - - if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(rightChildNode); - subtree.m_rootNodeIndex = rightChildNodexIndex; - subtree.m_subtreeSize = rightSubTreeSize; - } -} - - -int btOptimizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) -{ - int i; - int splitIndex =startIndex; - int numIndices = endIndex - startIndex; - btScalar splitValue; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - for (i=startIndex;i splitValue) - { - //swap - swapLeafNodes(i,splitIndex); - splitIndex++; - } - } - - //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex - //otherwise the tree-building might fail due to stack-overflows in certain cases. - //unbalanced1 is unsafe: it can cause stack overflows - //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); - - //unbalanced2 should work too: always use center (perfect balanced trees) - //bool unbalanced2 = true; - - //this should be safe too: - int rangeBalancedIndices = numIndices/3; - bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); - - if (unbalanced) - { - splitIndex = startIndex+ (numIndices>>1); - } - - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - btAssert(!unbal); - - return splitIndex; -} - - -int btOptimizedBvh::calcSplittingAxis(int startIndex,int endIndex) -{ - int i; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); - int numIndices = endIndex-startIndex; - - for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); - isLeafNode = rootNode->m_escapeIndex == -1; - - if (isLeafNode && aabbOverlap) - { - nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); - } - - if (aabbOverlap || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->m_escapeIndex; - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -/* -///this was the original recursive traversal, before we optimized towards stackless traversal -void btOptimizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); - if (aabbOverlap) - { - isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); - if (isLeafNode) - { - nodeCallback->processNode(rootNode); - } else - { - walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); - walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); - } - } - -} -*/ - -void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - bool aabbOverlap, isLeafNode; - - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); - isLeafNode = currentNode->isLeafNode(); - - if (aabbOverlap) - { - if (isLeafNode) - { - nodeCallback->processNode(0,currentNode->getTriangleIndex()); - } else - { - //process left and right children - const btQuantizedBvhNode* leftChildNode = currentNode+1; - walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - - const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); - walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - } - } -} - - - - - - - -void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const -{ - btAssert(m_useQuantization); - - int curIndex = startNodeIndex; - int walkIterations = 0; - int subTreeSize = endNodeIndex - startNodeIndex; - - const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; - int escapeIndex; - - bool aabbOverlap, isLeafNode; - - while (curIndex < endNodeIndex) - { - -//#define VISUALLY_ANALYZE_BVH 1 -#ifdef VISUALLY_ANALYZE_BVH - //some code snippet to debugDraw aabb, to visually analyze bvh structure - static int drawPatch = 0; - //need some global access to a debugDrawer - extern btIDebugDraw* debugDrawerPtr; - if (curIndex==drawPatch) - { - btVector3 aabbMin,aabbMax; - aabbMin = unQuantize(rootNode->m_quantizedAabbMin); - aabbMax = unQuantize(rootNode->m_quantizedAabbMax); - btVector3 color(1,0,0); - debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); - } -#endif//VISUALLY_ANALYZE_BVH - - //catch bugs in tree data - assert (walkIterations < subTreeSize); - - walkIterations++; - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); - isLeafNode = rootNode->isLeafNode(); - - if (isLeafNode && aabbOverlap) - { - nodeCallback->processNode(0,rootNode->getTriangleIndex()); - } - - if (aabbOverlap || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->getEscapeIndex(); - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -//This traversal can be called from Playstation 3 SPU -void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - int i; - - - for (i=0;im_SubtreeHeaders.size();i++) - { - const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - - bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) - { - walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, - subtree.m_rootNodeIndex, - subtree.m_rootNodeIndex+subtree.m_subtreeSize); - } - } -} - - - - -void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - (void)nodeCallback; - (void)aabbMin; - (void)aabbMax; - //not yet, please use aabb - btAssert(0); -} - - -void btOptimizedBvh::quantizeWithClamp(unsigned short* out, const btVector3& point) const -{ - - btAssert(m_useQuantization); - - btVector3 clampedPoint(point); - clampedPoint.setMax(m_bvhAabbMin); - clampedPoint.setMin(m_bvhAabbMax); - - btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; - out[0] = (unsigned short)(v.getX()+0.5f); - out[1] = (unsigned short)(v.getY()+0.5f); - out[2] = (unsigned short)(v.getZ()+0.5f); -} - -btVector3 btOptimizedBvh::unQuantize(const unsigned short* vecIn) const -{ - btVector3 vecOut; - vecOut.setValue( - (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), - (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), - (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); - vecOut += m_bvhAabbMin; - return vecOut; -} - - -void btOptimizedBvh::swapLeafNodes(int i,int splitIndex) -{ - if (m_useQuantization) - { - btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; - m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; - m_quantizedLeafNodes[splitIndex] = tmp; - } else - { - btOptimizedBvhNode tmp = m_leafNodes[i]; - m_leafNodes[i] = m_leafNodes[splitIndex]; - m_leafNodes[splitIndex] = tmp; - } -} - -void btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) -{ - if (m_useQuantization) - { - m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; - } else - { - m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; - } + //we don't add additional data so just do a static upcast + return static_cast(bvh); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h index d5159586344..d7536417d7e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -16,315 +16,48 @@ subject to the following restrictions: #ifndef OPTIMIZED_BVH_H #define OPTIMIZED_BVH_H - -#include "../../LinearMath/btVector3.h" - - -//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp - - +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" class btStridingMeshInterface; -//Note: currently we have 16 bytes per quantized node -#define MAX_SUBTREE_SIZE_IN_BYTES 2048 - -///btQuantizedBvhNode is a compressed aabb node, 16 bytes. -///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). -ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface. +ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh { - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes - int m_escapeIndexOrTriangleIndex; - - bool isLeafNode() const - { - //skipindex is negative (internal node), triangleindex >=0 (leafnode) - return (m_escapeIndexOrTriangleIndex >= 0); - } - int getEscapeIndex() const - { - btAssert(!isLeafNode()); - return -m_escapeIndexOrTriangleIndex; - } - int getTriangleIndex() const - { - btAssert(isLeafNode()); - return m_escapeIndexOrTriangleIndex; - } -} -; - -/// btOptimizedBvhNode contains both internal and leaf node information. -/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. -ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode -{ - //32 bytes - btVector3 m_aabbMinOrg; - btVector3 m_aabbMaxOrg; - - //4 - int m_escapeIndex; - - //8 - //for child nodes - int m_subPart; - int m_triangleIndex; - int m_padding[5];//bad, due to alignment - - -}; - - -///btBvhSubtreeInfo provides info to gather a subtree of limited size -ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo -{ public: - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes, points to the root of the subtree - int m_rootNodeIndex; - //4 bytes - int m_subtreeSize; - int m_padding[3]; - - - void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) - { - m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; - m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; - m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; - m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; - m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; - m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; - } -} -; - - -class btNodeOverlapCallback -{ -public: - virtual ~btNodeOverlapCallback() {}; - - virtual void processNode(int subPart, int triangleIndex) = 0; -}; - -#include "../../LinearMath/btAlignedAllocator.h" -#include "../../LinearMath/btAlignedObjectArray.h" - - - -///for code readability: -typedef btAlignedObjectArray NodeArray; -typedef btAlignedObjectArray QuantizedNodeArray; -typedef btAlignedObjectArray BvhSubtreeInfoArray; - - -///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future) -ATTRIBUTE_ALIGNED16(class) btOptimizedBvh -{ - NodeArray m_leafNodes; - NodeArray m_contiguousNodes; - - QuantizedNodeArray m_quantizedLeafNodes; - - QuantizedNodeArray m_quantizedContiguousNodes; - - int m_curNodeIndex; - - - //quantization data - bool m_useQuantization; - btVector3 m_bvhAabbMin; - btVector3 m_bvhAabbMax; - btVector3 m_bvhQuantization; - - enum btTraversalMode - { - TRAVERSAL_STACKLESS = 0, - TRAVERSAL_STACKLESS_CACHE_FRIENDLY, - TRAVERSAL_RECURSIVE - }; - - btTraversalMode m_traversalMode; - - - - - BvhSubtreeInfoArray m_SubtreeHeaders; - - - ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) - ///this might be refactored into a virtual, it is usually not calculated at run-time - void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) - { - if (m_useQuantization) - { - quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; - - } - } - void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) - { - if (m_useQuantization) - { - quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; - } - } - - btVector3 getAabbMin(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMinOrg; - - } - btVector3 getAabbMax(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMaxOrg; - - } - - void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); - - void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) - { - if (m_useQuantization) - { - m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; - } - else - { - m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; - } - - } - - void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) - { - if (m_useQuantization) - { - unsigned short int quantizedAabbMin[3]; - unsigned short int quantizedAabbMax[3]; - quantizeWithClamp(quantizedAabbMin,newAabbMin); - quantizeWithClamp(quantizedAabbMax,newAabbMax); - for (int i=0;i<3;i++) - { - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; - - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; - - } - } else - { - //non-quantized - m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); - m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); - } - } - - void swapLeafNodes(int firstIndex,int secondIndex); - - void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + BT_DECLARE_ALIGNED_ALLOCATOR(); protected: - - - void buildTree (int startIndex,int endIndex); - - int calcSplittingAxis(int startIndex,int endIndex); - - int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); - - void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; - - ///tree traversal designed for small-memory processors like PS3 SPU - void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; - - - inline bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const - { - bool overlap = true; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; - return overlap; - } - - void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); - public: + btOptimizedBvh(); virtual ~btOptimizedBvh(); void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); - void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void quantizeWithClamp(unsigned short* out, const btVector3& point) const; - - btVector3 unQuantize(const unsigned short* vecIn) const; - - ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. - void setTraversalMode(btTraversalMode traversalMode) - { - m_traversalMode = traversalMode; - } - - void refit(btStridingMeshInterface* triangles); + void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax); void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); - - QuantizedNodeArray& getQuantizedNodeArray() - { - return m_quantizedContiguousNodes; - } - - BvhSubtreeInfoArray& getSubtreeInfoArray() + /// Data buffer MUST be 16 byte aligned + virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) { - return m_SubtreeHeaders; + return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + } -} -; + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + +}; #endif //OPTIMIZED_BVH_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp index bbc4ba62af6..71c3af38a02 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -13,7 +13,7 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" btPolyhedralConvexShape::btPolyhedralConvexShape() :m_localAabbMin(1,1,1), @@ -95,7 +95,7 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin( -void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //not yet, return box inertia @@ -128,10 +128,46 @@ void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMi +void btPolyhedralConvexShape::setLocalScaling(const btVector3& scaling) +{ + btConvexInternalShape::setLocalScaling(scaling); + recalcLocalAabb(); +} void btPolyhedralConvexShape::recalcLocalAabb() { m_isLocalAabbValid = true; + + #if 1 + static const btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + for ( int i = 0; i < 3; ++i ) + { + m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; + m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; + } + + #else for (int i=0;i<3;i++) { @@ -143,6 +179,8 @@ void btPolyhedralConvexShape::recalcLocalAabb() tmp = localGetSupportingVertex(vec); m_localAabbMin[i] = tmp[i]-m_collisionMargin; } + #endif } + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h index c35f7512663..4c4ce7feaa7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -16,13 +16,14 @@ subject to the following restrictions: #ifndef BU_SHAPE #define BU_SHAPE -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btMatrix3x3.h" -#include "btConvexShape.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAabbUtil2.h" +#include "btConvexInternalShape.h" -///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. -class btPolyhedralConvexShape : public btConvexShape +///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes. +class btPolyhedralConvexShape : public btConvexInternalShape { protected: @@ -38,7 +39,7 @@ public: virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const @@ -46,33 +47,14 @@ public: //lazy evaluation of local aabb btAssert(m_isLocalAabbValid); - - btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX()); - btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY()); - btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ()); - - - btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(margin,margin,margin); - - aabbMin = center - extent; - aabbMax = center + extent; - - + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); } virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + void recalcLocalAabb(); virtual int getNumVertices() const = 0 ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp new file mode 100644 index 00000000000..5a17b4e2df0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btScaledBvhTriangleMeshShape.h" + +btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling) +:m_bvhTriMeshShape(childShape), +m_localScaling(localScaling) +{ + +} + +btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape() +{ +} + + +class btScaledTriangleCallback : public btTriangleCallback +{ + btTriangleCallback* m_originalCallback; + + btVector3 m_localScaling; + +public: + + btScaledTriangleCallback(btTriangleCallback* originalCallback,btVector3 localScaling) + :m_originalCallback(originalCallback), + m_localScaling(localScaling) + { + } + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btVector3 newTriangle[3]; + newTriangle[0] = triangle[0]*m_localScaling; + newTriangle[1] = triangle[1]*m_localScaling; + newTriangle[2] = triangle[2]*m_localScaling; + m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex); + } +}; + +void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + btScaledTriangleCallback scaledCallback(callback,m_localScaling); + + btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ()); + btVector3 scaledAabbMin = aabbMin * invLocalScaling; + btVector3 scaledAabbMax = aabbMax * invLocalScaling; + m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax); +} + + +void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin(); + btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax(); + localAabbMin *= m_localScaling; + localAabbMax *= m_localScaling; + + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + btScalar margin = m_bvhTriMeshShape->getMargin(); + localHalfExtents += btVector3(margin,margin,margin); + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center - extent; + aabbMax = center + extent; + +} + +void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + +const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const +{ + return m_localScaling; +} + +void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///don't make this a movable object! + btAssert(0); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h new file mode 100644 index 00000000000..8e1d29fc005 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -0,0 +1,57 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" + + +///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape. +///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling' +ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape +{ + + + btVector3 m_localScaling; + + btBvhTriangleMeshShape* m_bvhTriMeshShape; + +public: + + + btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling); + + virtual ~btScaledBvhTriangleMeshShape(); + + virtual int getShapeType() const + { + //use un-used 'FAST_CONCAVE_MESH_PROXYTYPE' for now, later add SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE to btBroadphaseProxy.h + return FAST_CONCAVE_MESH_PROXYTYPE; + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + //debugging + virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} + +}; + +#endif //BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp new file mode 100644 index 00000000000..a87b87f1a6f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp @@ -0,0 +1,164 @@ +/* +btbtShapeHull implemented by John McCutchan. + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btShapeHull.h" +#include "LinearMath/btConvexHull.h" + +#define NUM_UNITSPHERE_POINTS 42 + +static btVector3 btUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = +{ + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) +}; + +btShapeHull::btShapeHull (const btConvexShape* shape) +{ + m_shape = shape; + m_vertices.clear (); + m_indices.clear(); + m_numIndices = 0; +} + +btShapeHull::~btShapeHull () +{ + m_indices.clear(); + m_vertices.clear (); +} + +bool +btShapeHull::buildHull (btScalar /*margin*/) +{ + int numSampleDirections = NUM_UNITSPHERE_POINTS; + { + int numPDA = m_shape->getNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + btUnitSpherePoints[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + for (i = 0; i < numSampleDirections; i++) + { + supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]); + } + + HullDesc hd; + hd.mFlags = QF_TRIANGLES; + hd.mVcount = static_cast(numSampleDirections); + +#ifdef BT_USE_DOUBLE_PRECISION + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof(btVector3); +#else + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof (btVector3); +#endif + + HullLibrary hl; + HullResult hr; + if (hl.CreateConvexHull (hd, hr) == QE_FAIL) + { + return false; + } + + m_vertices.resize (static_cast(hr.mNumOutputVertices)); + + + for (i = 0; i < static_cast(hr.mNumOutputVertices); i++) + { + m_vertices[i] = hr.m_OutputVertices[i]; + } + m_numIndices = hr.mNumIndices; + m_indices.resize(static_cast(m_numIndices)); + for (i = 0; i < static_cast(m_numIndices); i++) + { + m_indices[i] = hr.m_Indices[i]; + } + + // free temporary hull result that we just copied + hl.ReleaseResult (hr); + + return true; +} + +int +btShapeHull::numTriangles () const +{ + return static_cast(m_numIndices / 3); +} + +int +btShapeHull::numVertices () const +{ + return m_vertices.size (); +} + +int +btShapeHull::numIndices () const +{ + return static_cast(m_numIndices); +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h new file mode 100644 index 00000000000..583c6b99eb6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h @@ -0,0 +1,56 @@ +/* +btShapeHull implemented by John McCutchan. + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SHAPE_HULL_H +#define _SHAPE_HULL_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + + +///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices. +///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object. +///It approximates the convex hull using the supporting vertex of 42 directions. +class btShapeHull +{ +public: + btShapeHull (const btConvexShape* shape); + ~btShapeHull (); + + bool buildHull (btScalar margin); + + int numTriangles () const; + int numVertices () const; + int numIndices () const; + + const btVector3* getVertexPointer() const + { + return &m_vertices[0]; + } + const unsigned int* getIndexPointer() const + { + return &m_indices[0]; + } + +protected: + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_indices; + unsigned int m_numIndices; + const btConvexShape* m_shape; +}; + +#endif //_SHAPE_HULL_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp index ca65dd03f3e..15cfe432e27 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -68,7 +68,7 @@ void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& a -void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin(); inertia.setValue(elem,elem,elem); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h index 66521664087..83421d69e0d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h @@ -16,15 +16,17 @@ subject to the following restrictions: #ifndef SPHERE_MINKOWSKI_H #define SPHERE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -///btSphereShape implements an implicit (getSupportingVertex) Sphere -ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexShape +///The btSphereShape implements an implicit sphere, centered around a local origin with radius. +ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape { public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btSphereShape (btScalar radius); @@ -34,26 +36,26 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual int getShapeType() const { return SPHERE_SHAPE_PROXYTYPE; } - btScalar getRadius() const { return m_implicitShapeDimensions.getX();} + btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();} //debugging - virtual char* getName()const {return "SPHERE";} + virtual const char* getName()const {return "SPHERE";} virtual void setMargin(btScalar margin) { - btConvexShape::setMargin(margin); + btConvexInternalShape::setMargin(margin); } virtual btScalar getMargin() const { //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case //this means, non-uniform scaling is not supported anymore - return m_localScaling.getX() * getRadius() + btConvexShape::getMargin(); + return getRadius(); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp index 4fbaafa1b93..3c98ca08ddc 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp @@ -19,10 +19,11 @@ subject to the following restrictions: btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant) -:m_planeNormal(planeNormal), +:m_planeNormal(planeNormal.normalized()), m_planeConstant(planeConstant), m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.)) { + // btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) ); } @@ -86,7 +87,7 @@ void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const } -void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h index f59cc0c3347..ddebca73dea 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -19,8 +19,7 @@ subject to the following restrictions: #include "btConcaveShape.h" -///StaticPlaneShape simulates an 'infinite' plane by dynamically reporting triangles approximated by intersection of the plane with the AABB. -///Assumed is that the other objects is not also infinite, so a reasonable sized AABB. +///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane. class btStaticPlaneShape : public btConcaveShape { protected: @@ -46,14 +45,23 @@ public: virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; + const btVector3& getPlaneNormal() const + { + return m_planeNormal; + } + + const btScalar& getPlaneConstant() const + { + return m_planeConstant; + } //debugging - virtual char* getName()const {return "STATICPLANE";} + virtual const char* getName()const {return "STATICPLANE";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp index 03ca1ae7736..752a5fc1dfa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -51,7 +51,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde { for (gfxindex=0;gfxindexprocessAllTriangles(&triBuf,aabbMin, aabbMax); -// for (int i=0;iprocessAllTriangles(&triBuf,aabbMin, aabbMax); +/// for (int i=0;i IndexedMeshArray; -///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. +///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays. ///Additional meshes can be added using addIndexedMesh ///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. ///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface { +protected: IndexedMeshArray m_indexedMeshes; - int m_pad[3]; + int m_pad[2]; + int m_hasAabb; // using int instead of bool to maintain alignment + btVector3 m_aabbMin; + btVector3 m_aabbMax; - public: - btTriangleIndexVertexArray() + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexArray() : m_hasAabb(0) { } + virtual ~btTriangleIndexVertexArray(); + //just to be backwards compatible - btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); + btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); - void addIndexedMesh(const btIndexedMesh& mesh) + void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER) { m_indexedMeshes.push_back(mesh); + m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType; } @@ -91,6 +105,10 @@ public: virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateIndices(int numindices){(void) numindices;} + virtual bool hasPremadeAabb() const; + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ); + virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const; + } ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp new file mode 100644 index 00000000000..492854ff646 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///This file was created by Alex Silverman + +#include "btTriangleIndexVertexMaterialArray.h" + +btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride) : +btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride) +{ + btMaterialProperties mat; + + mat.m_numMaterials = numMaterials; + mat.m_materialBase = materialBase; + mat.m_materialStride = materialStride; +#ifdef BT_USE_DOUBLE_PRECISION + mat.m_materialType = PHY_DOUBLE; +#else + mat.m_materialType = PHY_FLOAT; +#endif + + mat.m_numTriangles = numTriangles; + mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase; + mat.m_triangleMaterialStride = materialIndexStride; + mat.m_triangleType = PHY_INTEGER; + + addMaterialProperties(mat); +} + + +void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} + +void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (const unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h new file mode 100644 index 00000000000..69a2e631458 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///This file was created by Alex Silverman + +#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btTriangleIndexVertexArray.h" + + +ATTRIBUTE_ALIGNED16( struct) btMaterialProperties +{ + ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution + int m_numMaterials; + const unsigned char * m_materialBase; + int m_materialStride; + PHY_ScalarType m_materialType; + ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're + /// padding the structure, it can be reproduced at no real cost + ///m_triangleMaterials =====> 1 integer value makes up one entry + /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5 + int m_numTriangles; + const unsigned char * m_triangleMaterialsBase; + int m_triangleMaterialStride; + ///m_triangleType <========== Automatically set in addMaterialProperties + PHY_ScalarType m_triangleType; +}; + +typedef btAlignedObjectArray MaterialArray; + +///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray +///The addition of a material array allows for the utilization of the partID and +///triangleIndex that are returned in the ContactAddedCallback. As with +///TriangleIndexVertexArray, no duplicate is made of the material data, so it +///is the users responsibility to maintain the array during the lifetime of the +///TriangleIndexVertexMaterialArray. +ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray +{ +protected: + MaterialArray m_materials; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexMaterialArray() + { + } + + btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride); + + virtual ~btTriangleIndexVertexMaterialArray() {} + + void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER) + { + m_materials.push_back(mat); + m_materials[m_materials.size()-1].m_triangleType = triangleType; + } + + virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0); + + virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0); + +} +; + +#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp index 98c54ef45f8..bcea97052d6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp @@ -14,47 +14,102 @@ subject to the following restrictions: */ #include "btTriangleMesh.h" -#include -btTriangleMesh::btTriangleMesh () + +btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices) +:m_use32bitIndices(use32bitIndices), +m_use4componentVertices(use4componentVertices) { + btIndexedMesh meshIndex; + meshIndex.m_numTriangles = 0; + meshIndex.m_numVertices = 0; + meshIndex.m_indexType = PHY_INTEGER; + meshIndex.m_triangleIndexBase = 0; + meshIndex.m_triangleIndexStride = 3*sizeof(int); + meshIndex.m_vertexBase = 0; + meshIndex.m_vertexStride = sizeof(btVector3); + m_indexedMeshes.push_back(meshIndex); + + if (m_use32bitIndices) + { + m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3; + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; + m_indexedMeshes[0].m_indexType = PHY_INTEGER; + m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int); + } else + { + m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3; + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; + m_indexedMeshes[0].m_indexType = PHY_SHORT; + m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int); + } + + if (m_use4componentVertices) + { + m_indexedMeshes[0].m_numVertices = m_4componentVertices.size(); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; + m_indexedMeshes[0].m_vertexStride = sizeof(btVector3); + } else + { + m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3; + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; + m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar); + } + } -void btTriangleMesh::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) + +void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) { - (void)subpart; - numverts = m_vertices.size(); - *vertexbase = (unsigned char*)&m_vertices[0]; - type = PHY_FLOAT; - stride = sizeof(btVector3); + m_indexedMeshes[0].m_numTriangles++; + m_indexedMeshes[0].m_numVertices+=3; - numfaces = m_indices.size()/3; - *indexbase = (unsigned char*) &m_indices[0]; - indicestype = PHY_INTEGER; - indexstride = 3*sizeof(int); + if (m_use4componentVertices) + { + m_4componentVertices.push_back(vertex0); + m_4componentVertices.push_back(vertex1); + m_4componentVertices.push_back(vertex2); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; + } else + { + m_3componentVertices.push_back(vertex0.getX()); + m_3componentVertices.push_back(vertex0.getY()); + m_3componentVertices.push_back(vertex0.getZ()); + m_3componentVertices.push_back(vertex1.getX()); + m_3componentVertices.push_back(vertex1.getY()); + m_3componentVertices.push_back(vertex1.getZ()); + + m_3componentVertices.push_back(vertex2.getX()); + m_3componentVertices.push_back(vertex2.getY()); + m_3componentVertices.push_back(vertex2.getZ()); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; + } + + if (m_use32bitIndices) + { + int curIndex = m_32bitIndices.size(); + m_32bitIndices.push_back(curIndex++); + m_32bitIndices.push_back(curIndex++); + m_32bitIndices.push_back(curIndex++); + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; + } else + { + short curIndex = static_cast(m_16bitIndices.size()); + m_16bitIndices.push_back(curIndex++); + m_16bitIndices.push_back(curIndex++); + m_16bitIndices.push_back(curIndex++); + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; + } } -void btTriangleMesh::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const +int btTriangleMesh::getNumTriangles() const { - (void)subpart; - numverts = m_vertices.size(); - *vertexbase = (unsigned char*)&m_vertices[0]; - type = PHY_FLOAT; - stride = sizeof(btVector3); - - numfaces = m_indices.size()/3; - *indexbase = (unsigned char*) &m_indices[0]; - indicestype = PHY_INTEGER; - indexstride = 3*sizeof(int); - -} - - - -int btTriangleMesh::getNumSubParts() const -{ - return 1; + if (m_use32bitIndices) + { + return m_32bitIndices.size() / 3; + } + return m_16bitIndices.size() / 3; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index 525f5336b48..e4d41d5ede0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -17,54 +17,42 @@ subject to the following restrictions: #ifndef TRIANGLE_MESH_H #define TRIANGLE_MESH_H -#include "btStridingMeshInterface.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "btTriangleIndexVertexArray.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" -///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the btTriangleMeshShape. -class btTriangleMesh : public btStridingMeshInterface +///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape. +///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices. +///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface. +///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same. +class btTriangleMesh : public btTriangleIndexVertexArray { - btAlignedObjectArray m_vertices; - btAlignedObjectArray m_indices; + btAlignedObjectArray m_4componentVertices; + btAlignedObjectArray m_3componentVertices; + + btAlignedObjectArray m_32bitIndices; + btAlignedObjectArray m_16bitIndices; + bool m_use32bitIndices; + bool m_use4componentVertices; + public: - btTriangleMesh (); + btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); - void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) + bool getUse32bitIndices() const { - int curIndex = m_indices.size(); - m_vertices.push_back(vertex0); - m_vertices.push_back(vertex1); - m_vertices.push_back(vertex2); - - m_indices.push_back(curIndex++); - m_indices.push_back(curIndex++); - m_indices.push_back(curIndex++); + return m_use32bitIndices; } - int getNumTriangles() const + bool getUse4componentVertices() const { - return m_indices.size() / 3; + return m_use4componentVertices; } - - -//StridingMeshInterface interface implementation - - virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); - - virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; - - /// unLockVertexBase finishes the access to a subpart of the triangle mesh - /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished - virtual void unLockVertexBase(int subpart) {(void) subpart;} - - virtual void unLockReadOnlyVertexBase(int subpart) const { (void) subpart;} - - /// getNumSubParts returns the number of seperate subparts - /// each subpart has a continuous array of vertices and indices - virtual int getNumSubParts() const; + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2); + int getNumTriangles() const; + virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateIndices(int numindices){(void) numindices;} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp index ed81897b515..0a2c77096d1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -20,12 +20,18 @@ subject to the following restrictions: #include "LinearMath/btAabbUtil2.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "stdio.h" btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) : m_meshInterface(meshInterface) { - recalcLocalAabb(); + if(meshInterface->hasPremadeAabb()) + { + meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax); + } + else + { + recalcLocalAabb(); + } } @@ -41,6 +47,7 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); btMatrix3x3 abs_b = trans.getBasis().absolute(); @@ -50,12 +57,10 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), abs_b[1].dot(localHalfExtents), abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - aabbMin = center - extent; aabbMax = center + extent; - + } void btTriangleMeshShape::recalcLocalAabb() @@ -138,6 +143,7 @@ const btVector3& btTriangleMeshShape::getLocalScaling() const //#define DEBUG_TRIANGLE_MESH + void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const { struct FilteredCallback : public btInternalTriangleIndexCallback @@ -174,8 +180,7 @@ void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const - -void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; //moving concave objects not supported diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index e6173e47640..c9eabafe290 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -20,17 +20,19 @@ subject to the following restrictions: #include "btStridingMeshInterface.h" -///Concave triangle mesh. Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. class btTriangleMeshShape : public btConcaveShape { protected: btVector3 m_localAabbMin; btVector3 m_localAabbMax; btStridingMeshInterface* m_meshInterface; - + + ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. + ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! + btTriangleMeshShape(btStridingMeshInterface* meshInterface); public: - btTriangleMeshShape(btStridingMeshInterface* meshInterface); virtual ~btTriangleMeshShape(); @@ -44,16 +46,11 @@ public: void recalcLocalAabb(); - virtual int getShapeType() const - { - return TRIANGLE_MESH_SHAPE_PROXYTYPE; - } - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; @@ -68,9 +65,19 @@ public: return m_meshInterface; } + const btVector3& getLocalAabbMin() const + { + return m_localAabbMin; + } + const btVector3& getLocalAabbMax() const + { + return m_localAabbMax; + } + + //debugging - virtual char* getName()const {return "TRIANGLEMESH";} + virtual const char* getName()const {return "TRIANGLEMESH";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h index c2e240c051c..ba7aa0c32a0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -27,7 +27,6 @@ public: btVector3 m_vertices1[3]; - virtual int getNumVertices() const { return 3; @@ -84,14 +83,13 @@ public: - btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) - { - m_vertices1[0] = p0; - m_vertices1[1] = p1; - m_vertices1[2] = p2; - } + btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) + { + m_vertices1[0] = p0; + m_vertices1[1] = p1; + m_vertices1[2] = p2; + } - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const { @@ -116,7 +114,7 @@ public: planeSupport = m_vertices1[0]; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; btAssert(0); @@ -155,7 +153,7 @@ public: return false; } //debugging - virtual char* getName()const + virtual const char* getName()const { return "Triangle"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp new file mode 100644 index 00000000000..ef340286cb0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp @@ -0,0 +1,114 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btUniformScalingShape.h" + +btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): +m_childConvexShape(convexChildShape), +m_uniformScalingFactor(uniformScalingFactor) +{ +} + +btUniformScalingShape::~btUniformScalingShape() +{ +} + + +btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 tmpVertex; + tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); + return tmpVertex*m_uniformScalingFactor; +} + +void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); + int i; + for (i=0;ilocalGetSupportingVertex(vec); + return tmpVertex*m_uniformScalingFactor; +} + + +void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + btVector3 tmpInertia; + m_childConvexShape->calculateLocalInertia(mass,tmpInertia); + inertia = tmpInertia * m_uniformScalingFactor; +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabb(t,aabbMin,aabbMax); + btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); + btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; + + aabbMin = aabbCenter - scaledAabbHalfExtends; + aabbMax = aabbCenter + scaledAabbHalfExtends; + +} + +void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); + btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); + btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; + + aabbMin = aabbCenter - scaledAabbHalfExtends; + aabbMax = aabbCenter + scaledAabbHalfExtends; +} + +void btUniformScalingShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btUniformScalingShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btUniformScalingShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btUniformScalingShape::getMargin() const +{ + return m_childConvexShape->getMargin() * m_uniformScalingFactor; +} + +int btUniformScalingShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h new file mode 100644 index 00000000000..1e17fc8e198 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h @@ -0,0 +1,88 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_UNIFORM_SCALING_SHAPE_H +#define BT_UNIFORM_SCALING_SHAPE_H + +#include "btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way. +///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it. +class btUniformScalingShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + btScalar m_uniformScalingFactor; + + public: + + btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); + + virtual ~btUniformScalingShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btScalar getUniformScalingFactor() const + { + return m_uniformScalingFactor; + } + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "UniformScalingShape"; + } + + virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; } + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp index 2c565734e97..6551cfb92fe 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -16,7 +16,6 @@ subject to the following restrictions: #include "btContinuousConvexCollision.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "LinearMath/btTransformUtil.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -26,7 +25,7 @@ subject to the following restrictions: -btContinuousConvexCollision::btContinuousConvexCollision ( btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_simplexSolver(simplexSolver), m_penetrationDepthSolver(penetrationDepthSolver), m_convexA(convexA),m_convexB(convexB) @@ -35,7 +34,7 @@ m_convexA(convexA),m_convexB(convexB) /// This maximum should not be necessary. It allows for untested/degenerate cases in production code. /// You don't want your game ever to lock-up. -#define MAX_ITERATIONS 1000 +#define MAX_ITERATIONS 64 bool btContinuousConvexCollision::calcTimeOfImpact( const btTransform& fromA, @@ -52,10 +51,18 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); + btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + + btScalar relLinVelocLength = (linVelB-linVelA).length(); + + if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) + return false; + btScalar radius = btScalar(0.001); @@ -93,7 +100,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btGjkPairDetector::ClosestPointInput input; //we don't use margins during CCD - gjk.setIgnoreMargin(true); + // gjk.setIgnoreMargin(true); input.m_transformA = fromA; input.m_transformB = fromB; @@ -108,25 +115,31 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btScalar dist; dist = pointCollector1.m_distance; n = pointCollector1.m_normalOnBInWorld; + + btScalar projectedLinearVelocity = relLinVel.dot(n); //not close enough while (dist > radius) { numIter++; if (numIter > maxIter) + { return false; //todo: report a failure - + } btScalar dLambda = btScalar(0.); + projectedLinearVelocity = relLinVel.dot(n); + //calculate safe moving fraction from distance / (linear+rotational velocity) //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); //btScalar clippedDist = dist; - btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); + + lambda = lambda + dLambda; if (lambda > btScalar(1.)) @@ -135,9 +148,14 @@ bool btContinuousConvexCollision::calcTimeOfImpact( if (lambda < btScalar(0.)) return false; + //todo: next check with relative epsilon if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); break; + } lastLambda = lambda; @@ -163,11 +181,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact( { //degenerate ?! result.m_fraction = lastLambda; - result.m_normal = n; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n;//.setValue(1,1,1);// = n; + result.m_hitPoint = pointCollector.m_pointInWorld; return true; } c = pointCollector.m_pointInWorld; - + n = pointCollector.m_normalOnBInWorld; dist = pointCollector.m_distance; } else { @@ -177,8 +197,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact( } + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) + return false; + result.m_fraction = lambda; result.m_normal = n; + result.m_hitPoint = c; return true; } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h index 9901bab4b45..28c2b4d6156 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -30,13 +30,13 @@ class btContinuousConvexCollision : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; btConvexPenetrationDepthSolver* m_penetrationDepthSolver; - btConvexShape* m_convexA; - btConvexShape* m_convexB; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; public: - btContinuousConvexCollision (btConvexShape* shapeA,btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); virtual bool calcTimeOfImpact( const btTransform& fromA, diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h index 3101b59993d..0edf4dcd496 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -17,11 +17,11 @@ subject to the following restrictions: #ifndef CONVEX_CAST_H #define CONVEX_CAST_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" class btMinkowskiSumShape; -#include "../../LinearMath/btIDebugDraw.h" +#include "LinearMath/btIDebugDraw.h" /// btConvexCast is an interface for Casting class btConvexCast @@ -42,19 +42,21 @@ public: CastResult() :m_fraction(btScalar(1e30)), - m_debugDrawer(0) + m_debugDrawer(0), + m_allowedPenetration(btScalar(0)) { } virtual ~CastResult() {}; - btVector3 m_normal; - btScalar m_fraction; btTransform m_hitTransformA; btTransform m_hitTransformB; - + btVector3 m_normal; + btVector3 m_hitPoint; + btScalar m_fraction; //input and output btIDebugDraw* m_debugDrawer; + btScalar m_allowedPenetration; }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h index 7caeba4be45..99690921317 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -21,7 +21,7 @@ class btStackAlloc; class btVector3; #include "btSimplexSolverInterface.h" class btConvexShape; -#include "../../LinearMath/btPoint3.h" +#include "LinearMath/btPoint3.h" class btTransform; ///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. @@ -31,7 +31,7 @@ public: virtual ~btConvexPenetrationDepthSolver() {}; virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* convexA,btConvexShape* convexB, + const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, btVector3& v, btPoint3& pa, btPoint3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h index 15000c1ab61..db797d5141f 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H #define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" class btStackAlloc; /// This interface is made to be used by an iterative approach to do TimeOfImpact calculations @@ -58,7 +58,7 @@ struct btDiscreteCollisionDetectorInterface // give either closest points (distance > 0) or penetration (distance) // the normal always points from B towards A // - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) = 0; + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0; }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp index 93edffeafd6..bef697a0a11 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -17,12 +17,17 @@ subject to the following restrictions: #include "btGjkConvexCast.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "btGjkPairDetector.h" #include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif -btGjkConvexCast::btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), m_convexA(convexA), m_convexB(convexB) @@ -38,120 +43,113 @@ bool btGjkConvexCast::calcTimeOfImpact( { - btMinkowskiSumShape combi(m_convexA,m_convexB); - btMinkowskiSumShape* convex = &combi; + m_simplexSolver->reset(); - btTransform rayFromLocalA; - btTransform rayToLocalA; - - rayFromLocalA = fromA.inverse()* fromB; - rayToLocalA = toA.inverse()* toB; - - - btTransform trA,trB; - trA = btTransform(fromA); - trB = btTransform(fromB); - trA.setOrigin(btPoint3(0,0,0)); - trB.setOrigin(btPoint3(0,0,0)); - - convex->setTransformA(trA); - convex->setTransformB(trB); - - - - - btScalar radius = btScalar(0.01); + /// compute linear velocity for this interval, to interpolate + //assume no rotation/angular velocity, assert here? + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); + btScalar radius = btScalar(0.001); btScalar lambda = btScalar(0.); - btVector3 s = rayFromLocalA.getOrigin(); - btVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin(); - btVector3 x = s; + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + btVector3 n; - n.setValue(0,0,0); + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); bool hasResult = false; btVector3 c; + btVector3 r = (linVelA-linVelB); btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + int numIter = 0; //first solution, using GJK - //no penetration support for now, perhaps pass a pointer when we really want it - btConvexPenetrationDepthSolver* penSolverPtr = 0; btTransform identityTrans; identityTrans.setIdentity(); - btSphereShape raySphere(btScalar(0.0)); - raySphere.setMargin(btScalar(0.)); - btTransform sphereTr; - sphereTr.setIdentity(); - sphereTr.setOrigin( rayFromLocalA.getOrigin()); +// result.drawCoordSystem(sphereTr); - result.drawCoordSystem(sphereTr); - { - btPointCollector pointCollector1; - btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); + btPointCollector pointCollector; - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = sphereTr; - input.m_transformB = identityTrans; - gjk.getClosestPoints(input,pointCollector1,0); + + btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; - hasResult = pointCollector1.m_hasResult; - c = pointCollector1.m_pointInWorld; - n = pointCollector1.m_normalOnBInWorld; - } + //we don't use margins during CCD + // gjk.setIgnoreMargin(true); - + input.m_transformA = fromA; + input.m_transformB = fromB; + gjk.getClosestPoints(input,pointCollector,0); + + hasResult = pointCollector.m_hasResult; + c = pointCollector.m_pointInWorld; if (hasResult) { btScalar dist; - dist = (c-x).length(); - if (dist < radius) - { - //penetration - lastLambda = btScalar(1.); - } + dist = pointCollector.m_distance; + n = pointCollector.m_normalOnBInWorld; + + //not close enough while (dist > radius) { - - n = x - c; - btScalar nDotr = n.dot(r); + numIter++; + if (numIter > maxIter) + { + return false; //todo: report a failure + } + btScalar dLambda = btScalar(0.); - if (nDotr >= -(SIMD_EPSILON*SIMD_EPSILON)) + btScalar projectedLinearVelocity = r.dot(n); + + dLambda = dist / (projectedLinearVelocity); + + lambda = lambda - dLambda; + + if (lambda > btScalar(1.)) return false; - - lambda = lambda - n.dot(n) / nDotr; - if (lambda <= lastLambda) - break; + if (lambda < btScalar(0.)) + return false; + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); + break; + } lastLambda = lambda; - x = s + lambda * r; - - sphereTr.setOrigin( x ); - result.drawCoordSystem(sphereTr); - btPointCollector pointCollector; - btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = sphereTr; - input.m_transformB = identityTrans; + //interpolate to next lambda + result.DebugDraw( lambda ); + input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + gjk.getClosestPoints(input,pointCollector,0); if (pointCollector.m_hasResult) { if (pointCollector.m_distance < btScalar(0.)) { - //degeneracy, report a hit result.m_fraction = lastLambda; - result.m_normal = n; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n; + result.m_hitPoint = pointCollector.m_pointInWorld; return true; } - c = pointCollector.m_pointInWorld; - dist = (c-x).length(); + c = pointCollector.m_pointInWorld; + n = pointCollector.m_normalOnBInWorld; + dist = pointCollector.m_distance; } else { //?? @@ -160,15 +158,19 @@ bool btGjkConvexCast::calcTimeOfImpact( } - if (lastLambda < btScalar(1.)) - { - - result.m_fraction = lastLambda; - result.m_normal = n; - return true; - } + //is n normalized? + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (n.dot(r)>=-result.m_allowedPenetration) + return false; + + result.m_fraction = lambda; + result.m_normal = n; + result.m_hitPoint = c; + return true; } return false; + + } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h index 3905c45e6d6..a977c9e83f7 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -18,9 +18,9 @@ subject to the following restrictions: #ifndef GJK_CONVEX_CAST_H #define GJK_CONVEX_CAST_H -#include "../CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btConvexCast.h" class btConvexShape; class btMinkowskiSumShape; @@ -30,12 +30,12 @@ class btMinkowskiSumShape; class btGjkConvexCast : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; - btConvexShape* m_convexA; - btConvexShape* m_convexB; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; public: - btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); /// cast a convex against another convex object virtual bool calcTimeOfImpact( diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp index 8abdfdbb7e5..36cdeeaefdb 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp @@ -26,7 +26,7 @@ Nov.2006 #include "btGjkEpa.h" #include //for memset -#include +#include "LinearMath/btStackAlloc.h" #if defined(DEBUG) || defined (_DEBUG) #include //for debug printf @@ -580,8 +580,8 @@ using namespace gjkepa_impl; // -bool btGjkEpaSolver::Collide(btConvexShape *shape0,const btTransform &wtrs0, - btConvexShape *shape1,const btTransform &wtrs1, +bool btGjkEpaSolver::Collide(const btConvexShape *shape0,const btTransform &wtrs0, + const btConvexShape *shape1,const btTransform &wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results) @@ -602,13 +602,13 @@ GJK gjk(stackAlloc, wtrs1.getBasis(),wtrs1.getOrigin(),shape1, radialmargin+EPA_accuracy); const Z collide(gjk.SearchOrigin()); -results.gjk_iterations = gjk.iterations+1; +results.gjk_iterations = static_cast(gjk.iterations+1); if(collide) { /* Then EPA for penetration depth */ EPA epa(&gjk); const F pd(epa.EvaluatePD()); - results.epa_iterations = epa.iterations+1; + results.epa_iterations = static_cast(epa.iterations+1); if(pd>0) { results.status = sResults::Penetrating; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h index 759b30bb17f..1c256f41939 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h @@ -21,7 +21,7 @@ Nov.2006 #ifndef _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ #define _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ -#include "../CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" class btStackAlloc; @@ -35,7 +35,7 @@ struct sResults Separated, /* Shapes doesnt penetrate */ Penetrating, /* Shapes are penetrating */ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ - EPA_Failed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ } status; btVector3 witnesses[2]; btVector3 normal; @@ -43,8 +43,8 @@ struct sResults int epa_iterations; int gjk_iterations; }; -static bool Collide(btConvexShape* shape0,const btTransform& wtrs0, - btConvexShape* shape1,const btTransform& wtrs1, +static bool Collide(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp new file mode 100644 index 00000000000..ccfc22ee673 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -0,0 +1,943 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "btGjkEpa2.h" + +#if defined(DEBUG) || defined (_DEBUG) +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +#endif //__SPU__ +#endif + +namespace gjkepa2_impl +{ + +// Config + + /* GJK */ +#define GJK_MAX_ITERATIONS 128 +#define GJK_ACCURARY ((btScalar)0.0001) +#define GJK_MIN_DISTANCE ((btScalar)0.0001) +#define GJK_DUPLICATED_EPS ((btScalar)0.0001) +#define GJK_SIMPLEX2_EPS ((btScalar)0.0) +#define GJK_SIMPLEX3_EPS ((btScalar)0.0) +#define GJK_SIMPLEX4_EPS ((btScalar)0.0) + + /* EPA */ +#define EPA_MAX_VERTICES 64 +#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) +#define EPA_MAX_ITERATIONS 255 +#define EPA_ACCURACY ((btScalar)0.0001) +#define EPA_FALLBACK (10*EPA_ACCURACY) +#define EPA_PLANE_EPS ((btScalar)0.00001) +#define EPA_INSIDE_EPS ((btScalar)0.01) + + +// Shorthands +typedef unsigned int U; +typedef unsigned char U1; + +// MinkowskiDiff +struct MinkowskiDiff + { + const btConvexShape* m_shapes[2]; + btMatrix3x3 m_toshape1; + btTransform m_toshape0; + btVector3 (btConvexShape::*Ls)(const btVector3&) const; + void EnableMargin(bool enable) + { + if(enable) + Ls=&btConvexShape::localGetSupportingVertex; + else + Ls=&btConvexShape::localGetSupportingVertexWithoutMargin; + } + inline btVector3 Support0(const btVector3& d) const + { + return(((m_shapes[0])->*(Ls))(d)); + } + inline btVector3 Support1(const btVector3& d) const + { + return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); + } + inline btVector3 Support(const btVector3& d) const + { + return(Support0(d)-Support1(-d)); + } + btVector3 Support(const btVector3& d,U index) const + { + if(index) + return(Support1(d)); + else + return(Support0(d)); + } + }; + +typedef MinkowskiDiff tShape; + + +// GJK +struct GJK +{ +/* Types */ +struct sSV + { + btVector3 d,w; + }; +struct sSimplex + { + sSV* c[4]; + btScalar p[4]; + U rank; + }; +struct eStatus { enum _ { + Valid, + Inside, + Failed };}; +/* Fields */ +tShape m_shape; +btVector3 m_ray; +btScalar m_distance; +sSimplex m_simplices[2]; +sSV m_store[4]; +sSV* m_free[4]; +U m_nfree; +U m_current; +sSimplex* m_simplex; +eStatus::_ m_status; +/* Methods */ + GJK() + { + Initialize(); + } +void Initialize() + { + m_ray = btVector3(0,0,0); + m_nfree = 0; + m_status = eStatus::Failed; + m_current = 0; + m_distance = 0; + } +eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess) + { + U iterations=0; + btScalar sqdist=0; + btScalar alpha=0; + btVector3 lastw[4]; + U clastw=0; + /* Initialize solver */ + m_free[0] = &m_store[0]; + m_free[1] = &m_store[1]; + m_free[2] = &m_store[2]; + m_free[3] = &m_store[3]; + m_nfree = 4; + m_current = 0; + m_status = eStatus::Valid; + m_shape = shapearg; + m_distance = 0; + /* Initialize simplex */ + m_simplices[0].rank = 0; + m_ray = guess; + const btScalar sqrl= m_ray.length2(); + appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0)); + m_simplices[0].p[0] = 1; + m_ray = m_simplices[0].c[0]->w; + sqdist = sqrl; + lastw[0] = + lastw[1] = + lastw[2] = + lastw[3] = m_ray; + /* Loop */ + do { + const U next=1-m_current; + sSimplex& cs=m_simplices[m_current]; + sSimplex& ns=m_simplices[next]; + /* Check zero */ + const btScalar rl=m_ray.length(); + if(rlw; + bool found=false; + for(U i=0;i<4;++i) + { + if((w-lastw[i]).length2()w, + cs.c[1]->w, + weights,mask);break; + case 3: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + weights,mask);break; + case 4: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + cs.c[3]->w, + weights,mask);break; + } + if(sqdist>=0) + {/* Valid */ + ns.rank = 0; + m_ray = btVector3(0,0,0); + m_current = next; + for(U i=0,ni=cs.rank;iw*weights[i]; + } + else + { + m_free[m_nfree++] = cs.c[i]; + } + } + if(mask==15) m_status=eStatus::Inside; + } + else + {/* Return old simplex */ + removevertice(m_simplices[m_current]); + break; + } + m_status=((++iterations)rank) + { + case 1: + { + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + appendvertice(*m_simplex, axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 2: + { + const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + const btVector3 p=cross(d,axis); + if(p.length2()>0) + { + appendvertice(*m_simplex, p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + } + break; + case 3: + { + const btVector3 n=cross(m_simplex->c[1]->w-m_simplex->c[0]->w, + m_simplex->c[2]->w-m_simplex->c[0]->w); + if(n.length2()>0) + { + appendvertice(*m_simplex,n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 4: + { + if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, + m_simplex->c[1]->w-m_simplex->c[3]->w, + m_simplex->c[2]->w-m_simplex->c[3]->w))>0) + return(true); + } + break; + } + return(false); + } +/* Internals */ +void getsupport(const btVector3& d,sSV& sv) const + { + sv.d = d/d.length(); + sv.w = m_shape.Support(sv.d); + } +void removevertice(sSimplex& simplex) + { + m_free[m_nfree++]=simplex.c[--simplex.rank]; + } +void appendvertice(sSimplex& simplex,const btVector3& v) + { + simplex.p[simplex.rank]=0; + simplex.c[simplex.rank]=m_free[--m_nfree]; + getsupport(v,*simplex.c[simplex.rank++]); + } +static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c) + { + return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()- + a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+ + a.x()*b.y()*c.z()-a.z()*b.y()*c.x()); + } +static btScalar projectorigin( const btVector3& a, + const btVector3& b, + btScalar* w,U& m) + { + const btVector3 d=b-a; + const btScalar l=d.length2(); + if(l>GJK_SIMPLEX2_EPS) + { + const btScalar t(l>0?-dot(a,d)/l:0); + if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); } + else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); } + else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); } + } + return(-1); + } +static btScalar projectorigin( const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar* w,U& m) + { + static const U imd3[]={1,2,0}; + const btVector3* vt[]={&a,&b,&c}; + const btVector3 dl[]={a-b,b-c,c-a}; + const btVector3 n=cross(dl[0],dl[1]); + const btScalar l=n.length2(); + if(l>GJK_SIMPLEX3_EPS) + { + btScalar mindist=-1; + btScalar subw[2]; + U subm; + for(U i=0;i<3;++i) + { + if(dot(*vt[i],cross(dl[i],n))>0) + { + const U j=imd3[i]; + const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm)); + if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) + { + btScalar mindist=-1; + btScalar subw[3]; + U subm; + for(U i=0;i<3;++i) + { + const U j=imd3[i]; + const btScalar s=vl*dot(d,cross(dl[i],dl[j])); + if(s>0) + { + const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm); + if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; + fb->e[eb]=(U1)ea;fb->f[eb]=fa; + } +static inline void append(sList& list,sFace* face) + { + face->l[0] = 0; + face->l[1] = list.root; + if(list.root) list.root->l[0]=face; + list.root = face; + ++list.count; + } +static inline void remove(sList& list,sFace* face) + { + if(face->l[1]) face->l[1]->l[0]=face->l[0]; + if(face->l[0]) face->l[0]->l[1]=face->l[1]; + if(face==list.root) list.root=face->l[1]; + --list.count; + } + + +void Initialize() + { + m_status = eStatus::Failed; + m_normal = btVector3(0,0,0); + m_depth = 0; + m_nextsv = 0; + for(U i=0;i1)&&gjk.EncloseOrigin()) + { + + /* Clean up */ + while(m_hull.root) + { + sFace* f = m_hull.root; + remove(m_hull,f); + append(m_stock,f); + } + m_status = eStatus::Valid; + m_nextsv = 0; + /* Orient simplex */ + if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, + simplex.c[1]->w-simplex.c[3]->w, + simplex.c[2]->w-simplex.c[3]->w)<0) + { + btSwap(simplex.c[0],simplex.c[1]); + btSwap(simplex.p[0],simplex.p[1]); + } + /* Build initial hull */ + sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), + newface(simplex.c[1],simplex.c[0],simplex.c[3],true), + newface(simplex.c[2],simplex.c[1],simplex.c[3],true), + newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; + if(m_hull.count==4) + { + sFace* best=findbest(); + sFace outer=*best; + U pass=0; + U iterations=0; + bind(tetra[0],0,tetra[1],0); + bind(tetra[0],1,tetra[2],0); + bind(tetra[0],2,tetra[3],0); + bind(tetra[1],1,tetra[3],2); + bind(tetra[1],2,tetra[2],1); + bind(tetra[2],2,tetra[3],1); + m_status=eStatus::Valid; + for(;iterationspass = (U1)(++pass); + gjk.getsupport(best->n,*w); + const btScalar wdist=dot(best->n,w->w)-best->d; + if(wdist>EPA_ACCURACY) + { + for(U j=0;(j<3)&&valid;++j) + { + valid&=expand( pass,w, + best->f[j],best->e[j], + horizon); + } + if(valid&&(horizon.nf>=3)) + { + bind(horizon.cf,1,horizon.ff,2); + remove(m_hull,best); + append(m_stock,best); + best=findbest(); + if(best->p>=outer.p) outer=*best; + } else { m_status=eStatus::InvalidHull;break; } + } else { m_status=eStatus::AccuraryReached;break; } + } else { m_status=eStatus::OutOfVertices;break; } + } + const btVector3 projection=outer.n*outer.d; + m_normal = outer.n; + m_depth = outer.d; + m_result.rank = 3; + m_result.c[0] = outer.c[0]; + m_result.c[1] = outer.c[1]; + m_result.c[2] = outer.c[2]; + m_result.p[0] = cross( outer.c[1]->w-projection, + outer.c[2]->w-projection).length(); + m_result.p[1] = cross( outer.c[2]->w-projection, + outer.c[0]->w-projection).length(); + m_result.p[2] = cross( outer.c[0]->w-projection, + outer.c[1]->w-projection).length(); + const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; + m_result.p[0] /= sum; + m_result.p[1] /= sum; + m_result.p[2] /= sum; + return(m_status); + } + } + /* Fallback */ + m_status = eStatus::FallBack; + m_normal = -guess; + const btScalar nl=m_normal.length(); + if(nl>0) + m_normal = m_normal/nl; + else + m_normal = btVector3(1,0,0); + m_depth = 0; + m_result.rank=1; + m_result.c[0]=simplex.c[0]; + m_result.p[0]=1; + return(m_status); + } +sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) + { + if(m_stock.root) + { + sFace* face=m_stock.root; + remove(m_stock,face); + append(m_hull,face); + face->pass = 0; + face->c[0] = a; + face->c[1] = b; + face->c[2] = c; + face->n = cross(b->w-a->w,c->w-a->w); + const btScalar l=face->n.length(); + const bool v=l>EPA_ACCURACY; + face->p = btMin(btMin( + dot(a->w,cross(face->n,a->w-b->w)), + dot(b->w,cross(face->n,b->w-c->w))), + dot(c->w,cross(face->n,c->w-a->w))) / + (v?l:1); + face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; + if(v) + { + face->d = dot(a->w,face->n)/l; + face->n /= l; + if(forced||(face->d>=-EPA_PLANE_EPS)) + { + return(face); + } else m_status=eStatus::NonConvex; + } else m_status=eStatus::Degenerated; + remove(m_hull,face); + append(m_stock,face); + return(0); + } + m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; + return(0); + } +sFace* findbest() + { + sFace* minf=m_hull.root; + btScalar mind=minf->d*minf->d; + btScalar maxp=minf->p; + for(sFace* f=minf->l[1];f;f=f->l[1]) + { + const btScalar sqd=f->d*f->d; + if((f->p>=maxp)&&(sqdp; + } + } + return(minf); + } +bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon) + { + static const U i1m3[]={1,2,0}; + static const U i2m3[]={2,0,1}; + if(f->pass!=pass) + { + const U e1=i1m3[e]; + if((dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) + { + sFace* nf=newface(f->c[e1],f->c[e],w,false); + if(nf) + { + bind(nf,0,f,e); + if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; + horizon.cf=nf; + ++horizon.nf; + return(true); + } + } + else + { + const U e2=i2m3[e]; + f->pass = (U1)pass; + if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& + expand(pass,w,f->f[e2],f->e[e2],horizon)) + { + remove(m_hull,f); + append(m_stock,f); + return(true); + } + } + } + return(false); + } + +}; + +// +static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + btGjkEpaSolver2::sResults& results, + tShape& shape, + bool withmargins) +{ +/* Results */ +results.witnesses[0] = +results.witnesses[1] = btVector3(0,0,0); +results.status = btGjkEpaSolver2::sResults::Separated; +/* Shape */ +shape.m_shapes[0] = shape0; +shape.m_shapes[1] = shape1; +shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis()); +shape.m_toshape0 = wtrs0.inverseTimes(wtrs1); +shape.EnableMargin(withmargins); +} + +} + +// +// Api +// + +using namespace gjkepa2_impl; + +// +int btGjkEpaSolver2::StackSizeRequirement() +{ +return(sizeof(GJK)+sizeof(EPA)); +} + +// +bool btGjkEpaSolver2::Distance( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ +tShape shape; +Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); +if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + results.normal = w0-w1; + results.distance = results.normal.length(); + results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; + return(true); + } + else + { + results.status = gjk_status==GJK::eStatus::Inside? + sResults::Penetrating : + sResults::GJK_Failed ; + return(false); + } +} + +// +bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins) +{ +tShape shape; +Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); +switch(gjk_status) + { + case GJK::eStatus::Inside: + { + EPA epa; + EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); + if(epa_status!=EPA::eStatus::Failed) + { + btVector3 w0=btVector3(0,0,0); + for(U i=0;id,0)*epa.m_result.p[i]; + } + results.status = sResults::Penetrating; + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); + results.normal = -epa.m_normal; + results.distance = -epa.m_depth; + return(true); + } else results.status=sResults::EPA_Failed; + } + break; + case GJK::eStatus::Failed: + results.status=sResults::GJK_Failed; + break; + } +return(false); +} + +// +btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, + btScalar margin, + const btConvexShape* shape0, + const btTransform& wtrs0, + sResults& results) +{ +tShape shape; +btSphereShape shape1(margin); +btTransform wtrs1(btQuaternion(0,0,0,1),position); +Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1)); +if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + const btVector3 delta= results.witnesses[1]- + results.witnesses[0]; + const btScalar margin= shape0->getMargin()+ + shape1.getMargin(); + const btScalar length= delta.length(); + results.normal = delta/length; + results.witnesses[0] += results.normal*margin; + return(length-margin); + } + else + { + if(gjk_status==GJK::eStatus::Inside) + { + if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results)) + { + const btVector3 delta= results.witnesses[0]- + results.witnesses[1]; + const btScalar length= delta.length(); + if (length >= SIMD_EPSILON) + results.normal = delta/length; + return(-length); + } + } + } +return(SIMD_INFINITY); +} + +// +bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ +if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) + return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); + else + return(true); +} + +/* Symbols cleanup */ + +#undef GJK_MAX_ITERATIONS +#undef GJK_ACCURARY +#undef GJK_MIN_DISTANCE +#undef GJK_DUPLICATED_EPS +#undef GJK_SIMPLEX2_EPS +#undef GJK_SIMPLEX3_EPS +#undef GJK_SIMPLEX4_EPS + +#undef EPA_MAX_VERTICES +#undef EPA_MAX_FACES +#undef EPA_MAX_ITERATIONS +#undef EPA_ACCURACY +#undef EPA_FALLBACK +#undef EPA_PLANE_EPS +#undef EPA_INSIDE_EPS diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h new file mode 100644 index 00000000000..a55214203d3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ +#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +///btGjkEpaSolver contributed under zlib by Nathanael Presson +struct btGjkEpaSolver2 +{ +struct sResults + { + enum eStatus + { + Separated, /* Shapes doesnt penetrate */ + Penetrating, /* Shapes are penetrating */ + GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ + } status; + btVector3 witnesses[2]; + btVector3 normal; + btScalar distance; + }; + +static int StackSizeRequirement(); + +static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); + +static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins=true); + +static btScalar SignedDistance( const btVector3& position, + btScalar margin, + const btConvexShape* shape, + const btTransform& wtrs, + sResults& results); + +static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); +}; + +#endif diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp index 87330493b60..c4f84ed4d75 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -18,9 +18,10 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexShape.h" #include "btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* pConvexA, btConvexShape* pConvexB, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) @@ -32,10 +33,20 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim const btScalar radialmargin(btScalar(0.)); +//#define USE_ORIGINAL_GJK 1 +#ifdef USE_ORIGINAL_GJK btGjkEpaSolver::sResults results; if(btGjkEpaSolver::Collide( pConvexA,transformA, pConvexB,transformB, radialmargin,stackAlloc,results)) +#else + btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin()); + btGjkEpaSolver2::sResults results; + if(btGjkEpaSolver2::Penetration(pConvexA,transformA, + pConvexB,transformB, + guessVector,results)) + +#endif { // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h index 3916ba0776c..2dc069ce5cf 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -26,7 +26,7 @@ class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver public : bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* pConvexA, btConvexShape* pConvexB, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index f1f3f7f7f6c..01fb1a4b068 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -35,7 +35,7 @@ int gNumGjkChecks = 0; -btGjkPairDetector::btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_cachedSeparatingAxis(btScalar(0.),btScalar(0.),btScalar(1.)), m_penetrationDepthSolver(penetrationDepthSolver), m_simplexSolver(simplexSolver), @@ -47,7 +47,7 @@ m_catchDegeneracies(1) { } -void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) { btScalar distance=btScalar(0.); btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); @@ -144,6 +144,13 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& break; } + if(m_cachedSeparatingAxis.length2() @@ -169,7 +162,7 @@ int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const return nearestPoint; } -void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) +int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) { assert(validContactDistance(newPoint)); @@ -182,7 +175,7 @@ void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) #else insertIndex = 0; #endif - + clearUserCache(m_pointCache[insertIndex]); } else { @@ -190,7 +183,9 @@ void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) } - replaceContactPoint(newPoint,insertIndex); + btAssert(m_pointCache[insertIndex].m_userPersistentData==0); + m_pointCache[insertIndex] = newPoint; + return insertIndex; } btScalar btPersistentManifold::getContactBreakingThreshold() const @@ -198,10 +193,20 @@ btScalar btPersistentManifold::getContactBreakingThreshold() const return gContactBreakingThreshold; } + + void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) { int i; - +#ifdef DEBUG_PERSISTENCY + printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", + trA.getOrigin().getX(), + trA.getOrigin().getY(), + trA.getOrigin().getZ(), + trB.getOrigin().getX(), + trB.getOrigin().getY(), + trB.getOrigin().getZ()); +#endif //DEBUG_PERSISTENCY /// first refresh worldspace positions and distance for (i=getNumContacts()-1;i>=0;i--) { @@ -232,6 +237,11 @@ void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btT if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) { removeContactPoint(i); + } else + { + //contact point processed callback + if (gContactProcessedCallback) + (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1); } } } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index a5918b84db3..c122eb865e8 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -17,9 +17,10 @@ subject to the following restrictions: #define PERSISTENT_MANIFOLD_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" #include "btManifoldPoint.h" +#include "LinearMath/btAlignedAllocator.h" struct btCollisionResult; @@ -27,6 +28,7 @@ struct btCollisionResult; extern btScalar gContactBreakingThreshold; typedef bool (*ContactDestroyedCallback)(void* userPersistentData); +typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1); extern ContactDestroyedCallback gContactDestroyedCallback; @@ -34,8 +36,13 @@ extern ContactDestroyedCallback gContactDestroyedCallback; #define MANIFOLD_CACHE_SIZE 4 -///btPersistentManifold maintains contact points, and reduces them to 4. -///It does contact filtering/contact reduction. +///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. +///Those contact points are created by the collision narrow phase. +///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. +///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) +///reduces the cache to 4 points, when more then 4 points are added, using following rules: +///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points +///note that some pairs of objects might have more then one contact manifold. ATTRIBUTE_ALIGNED16( class) btPersistentManifold { @@ -55,20 +62,23 @@ ATTRIBUTE_ALIGNED16( class) btPersistentManifold public: - int m_index1; + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_index1a; btPersistentManifold(); - btPersistentManifold(void* body0,void* body1) + btPersistentManifold(void* body0,void* body1,int bla) : m_body0(body0),m_body1(body1),m_cachedPoints(0) { + (void)bla; } - inline void* getBody0() { return m_body0;} - inline void* getBody1() { return m_body1;} + SIMD_FORCE_INLINE void* getBody0() { return m_body0;} + SIMD_FORCE_INLINE void* getBody1() { return m_body1;} - inline const void* getBody0() const { return m_body0;} - inline const void* getBody1() const { return m_body1;} + SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;} + SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;} void setBodies(void* body0,void* body1) { @@ -82,15 +92,15 @@ public: void DebugPersistency(); #endif // - inline int getNumContacts() const { return m_cachedPoints;} + SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} - inline const btManifoldPoint& getContactPoint(int index) const + SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const { btAssert(index < m_cachedPoints); return m_pointCache[index]; } - inline btManifoldPoint& getContactPoint(int index) + SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) { btAssert(index < m_cachedPoints); return m_pointCache[index]; @@ -101,7 +111,7 @@ public: int getCacheEntry(const btManifoldPoint& newPoint) const; - void AddManifoldPoint( const btManifoldPoint& newPoint); + int addManifoldPoint( const btManifoldPoint& newPoint); void removeContactPoint (int index) { @@ -114,6 +124,11 @@ public: m_pointCache[index] = m_pointCache[lastUsedIndex]; //get rid of duplicated userPersistentData pointer m_pointCache[lastUsedIndex].m_userPersistentData = 0; + m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f; + m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f; + m_pointCache[lastUsedIndex].m_lifeTime = 0; } btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); @@ -126,12 +141,20 @@ public: #define MAINTAIN_PERSISTENCY 1 #ifdef MAINTAIN_PERSISTENCY int lifeTime = m_pointCache[insertIndex].getLifeTime(); + btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse; + btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1; + btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2; + btAssert(lifeTime>=0); void* cache = m_pointCache[insertIndex].m_userPersistentData; m_pointCache[insertIndex] = newPoint; m_pointCache[insertIndex].m_userPersistentData = cache; + m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; + m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; + m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; + m_pointCache[insertIndex].m_lifeTime = lifeTime; #else clearUserCache(m_pointCache[insertIndex]); @@ -147,7 +170,16 @@ public: /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin void refreshContactPoints( const btTransform& trA,const btTransform& trB); - void clearManifold(); + + SIMD_FORCE_INLINE void clearManifold() + { + int i; + for (i=0;i +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "btRaycastCallback.h" btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to) @@ -29,8 +36,6 @@ btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) { - - const btVector3 &vert0=triangle[0]; const btVector3 &vert1=triangle[1]; const btVector3 &vert2=triangle[2]; @@ -99,3 +104,60 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, } } } + + +btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin) +{ + m_convexShape = convexShape; + m_convexShapeFrom = convexShapeFrom; + m_convexShapeTo = convexShapeTo; + m_triangleToWorld = triangleToWorld; + m_hitFraction = 1.0; + m_triangleCollisionMargin = triangleCollisionMargin; +} + +void +btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex) +{ + btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]); + triangleShape.setMargin(m_triangleCollisionMargin); + + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + +//#define USE_SUBSIMPLEX_CONVEX_CAST 1 +//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver); +#else + //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver); + btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + btConvexCast::CastResult castResult; + castResult.m_fraction = btScalar(1.); + if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < m_hitFraction) + { +/* btContinuousConvexCast's normal is already in world space */ +/* +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST +*/ + castResult.m_normal.normalize(); + + reportHit (castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction, + partId, + triangleIndex); + } + } + } +} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h index a0bbc9f8fe9..d2b4b80f8ba 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -16,15 +16,16 @@ subject to the following restrictions: #ifndef RAYCAST_TRI_CALLBACK_H #define RAYCAST_TRI_CALLBACK_H -#include "../CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "LinearMath/btTransform.h" struct btBroadphaseProxy; - +class btConvexShape; class btTriangleRaycastCallback: public btTriangleCallback { public: - //input + //input btVector3 m_from; btVector3 m_to; @@ -38,5 +39,22 @@ public: }; +class btTriangleConvexcastCallback : public btTriangleCallback +{ +public: + const btConvexShape* m_convexShape; + btTransform m_convexShapeFrom; + btTransform m_convexShapeTo; + btTransform m_triangleToWorld; + btScalar m_hitFraction; + btScalar m_triangleCollisionMargin; + + btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin); + + virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0; +}; + #endif //RAYCAST_TRI_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h index 58393b2eab9..cf65f46505b 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -18,8 +18,8 @@ subject to the following restrictions: #ifndef SIMPLEX_SOLVER_INTERFACE_H #define SIMPLEX_SOLVER_INTERFACE_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btPoint3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btPoint3.h" #define NO_VIRTUAL_INTERFACE 1 #ifdef NO_VIRTUAL_INTERFACE diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp index 687738b7fa9..4c709a8c3a9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -16,9 +16,11 @@ subject to the following restrictions: #include "btSubSimplexConvexCast.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" + #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" - +#include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), @@ -41,34 +43,24 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( CastResult& result) { - btMinkowskiSumShape combi(m_convexA,m_convexB); - btMinkowskiSumShape* convex = &combi; - - btTransform rayFromLocalA; - btTransform rayToLocalA; - - rayFromLocalA = fromA.inverse()* fromB; - rayToLocalA = toA.inverse()* toB; - - m_simplexSolver->reset(); - convex->setTransformB(btTransform(rayFromLocalA.getBasis())); - - //btScalar radius = btScalar(0.01); + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); btScalar lambda = btScalar(0.); - //todo: need to verify this: - //because of minkowski difference, we need the inverse direction - - btVector3 s = -rayFromLocalA.getOrigin(); - btVector3 r = -(rayToLocalA.getOrigin()-rayFromLocalA.getOrigin()); - btVector3 x = s; - btVector3 v; - btVector3 arbitraryPoint = convex->localGetSupportingVertex(r); - - v = x - arbitraryPoint; + btTransform interpolatedTransA = fromA; + btTransform interpolatedTransB = fromB; + + ///take relative motion + btVector3 r = (linVelA-linVelB); + btVector3 v; + + btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis())); + btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis())); + v = supVertexA-supVertexB; int maxIter = MAX_ITERATIONS; btVector3 n; @@ -90,11 +82,17 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( while ( (dist2 > epsilon) && maxIter--) { - p = convex->localGetSupportingVertex( v); - w = x - p; + supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis())); + supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis())); + w = supVertexA-supVertexB; btScalar VdotW = v.dot(w); + if (lambda > btScalar(1.0)) + { + return false; + } + if ( VdotW > btScalar(0.)) { VdotR = v.dot(r); @@ -104,20 +102,25 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( else { lambda = lambda - VdotW / VdotR; - x = s + lambda * r; - m_simplexSolver->reset(); + //interpolate to next lambda + // x = s + lambda * r; + interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + //m_simplexSolver->reset(); //check next line - w = x-p; + w = supVertexA-supVertexB; lastLambda = lambda; n = v; hasResult = true; } } - m_simplexSolver->addVertex( w, x , p); + m_simplexSolver->addVertex( w, supVertexA , supVertexB); if (m_simplexSolver->closest(v)) { dist2 = v.length2(); hasResult = true; + //todo: check this normal for validity + //n=v; //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); //printf("DIST2=%f\n",dist2); //printf("numverts = %i\n",m_simplexSolver->numVertices()); @@ -129,11 +132,26 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( //int numiter = MAX_ITERATIONS - maxIter; // printf("number of iterations: %d", numiter); - result.m_fraction = lambda; - result.m_normal = n; + + //don't report a time of impact when moving 'away' from the hitnormal + + result.m_fraction = lambda; + if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON)) + result.m_normal = n.normalized(); + else + result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (result.m_normal.dot(r)>=-result.m_allowedPenetration) + return false; + + btVector3 hitA,hitB; + m_simplexSolver->compute_points(hitA,hitB); + result.m_hitPoint=hitB; return true; } + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp index 105b7eccefa..cf8a3ab5eb1 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -26,7 +26,7 @@ subject to the following restrictions: #include "btVoronoiSimplexSolver.h" #include -#include +//#include #define VERTA 0 #define VERTB 1 diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt index 8598575799a..58b023e9775 100644 --- a/extern/bullet2/src/BulletDynamics/CMakeLists.txt +++ b/extern/bullet2/src/BulletDynamics/CMakeLists.txt @@ -5,16 +5,32 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletDynamics ConstraintSolver/btContactConstraint.cpp + ConstraintSolver/btContactConstraint.h + ConstraintSolver/btConeTwistConstraint.cpp + ConstraintSolver/btConeTwistConstraint.h ConstraintSolver/btGeneric6DofConstraint.cpp + ConstraintSolver/btGeneric6DofConstraint.h ConstraintSolver/btHingeConstraint.cpp + ConstraintSolver/btHingeConstraint.h ConstraintSolver/btPoint2PointConstraint.cpp + ConstraintSolver/btPoint2PointConstraint.h ConstraintSolver/btSequentialImpulseConstraintSolver.cpp + ConstraintSolver/btSequentialImpulseConstraintSolver.h + ConstraintSolver/btSliderConstraint.cpp + ConstraintSolver/btSliderConstraint.h ConstraintSolver/btSolve2LinearConstraint.cpp + ConstraintSolver/btSolve2LinearConstraint.h ConstraintSolver/btTypedConstraint.cpp - Dynamics/btDiscreteDynamicsWorld.cpp - Dynamics/btSimpleDynamicsWorld.cpp + ConstraintSolver/btTypedConstraint.h Dynamics/Bullet-C-API.cpp + Dynamics/btDiscreteDynamicsWorld.cpp + Dynamics/btDiscreteDynamicsWorld.h + Dynamics/btSimpleDynamicsWorld.cpp + Dynamics/btSimpleDynamicsWorld.h Dynamics/btRigidBody.cpp + Dynamics/btRigidBody.h Vehicle/btRaycastVehicle.cpp + Vehicle/btRaycastVehicle.h Vehicle/btWheelInfo.cpp + Vehicle/btWheelInfo.h ) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index 2289621e8e3..61dad522a5b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -19,24 +19,20 @@ Written by: Marcus Hennix #include "btConeTwistConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" -#include "LinearMath/btSimdMinMax.h" +#include "LinearMath/btMinMax.h" #include btConeTwistConstraint::btConeTwistConstraint() +:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) { } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame,const btTransform& rbBFrame) - :btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false) { - // flip axis for correct angles - m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - m_swingSpan1 = btScalar(1e30); m_swingSpan2 = btScalar(1e30); m_twistSpan = btScalar(1e30); @@ -49,20 +45,11 @@ btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) - :btTypedConstraint(rbA),m_rbAFrame(rbAFrame), + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), m_angularOnly(false) { m_rbBFrame = m_rbAFrame; - // flip axis for correct angles - m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - - m_rbBFrame.getBasis()[2][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - m_swingSpan1 = btScalar(1e30); m_swingSpan2 = btScalar(1e30); m_twistSpan = btScalar(1e30); @@ -127,22 +114,39 @@ void btConeTwistConstraint::buildJacobian() btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + btScalar swx=btScalar(0.),swy = btScalar(0.); + btScalar thresh = btScalar(10.); + btScalar fact; + // Get Frame into world space if (m_swingSpan1 >= btScalar(0.05f)) { b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); - swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); +// swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis2); + swing1 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing1 *= fact; + } if (m_swingSpan2 >= btScalar(0.05f)) { b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); - swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); +// swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis3); + swing2 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing2 *= fact; } btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); - btScalar EllipseAngle = btFabs(swing1)* RMaxAngle1Sq + btFabs(swing2) * RMaxAngle2Sq; + btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq; if (EllipseAngle > 1.0f) { @@ -246,7 +250,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, 0.0f ); + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); impulseMag = m_accSwingLimitImpulse - temp; btVector3 impulse = m_swingAxis * impulseMag; @@ -264,7 +268,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, 0.0f ); + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); impulseMag = m_accTwistLimitImpulse - temp; btVector3 impulse = m_twistAxis * impulseMag; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index 874669c80b3..f121919c8f9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -30,6 +30,9 @@ class btRigidBody; ///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) class btConeTwistConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btTransform m_rbAFrame; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h index 7e8458c2c7b..7a8e9c1953d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef CONSTRAINT_SOLVER_H #define CONSTRAINT_SOLVER_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" class btPersistentManifold; class btRigidBody; @@ -26,7 +26,7 @@ struct btContactSolverInfo; struct btBroadphaseProxy; class btIDebugDraw; class btStackAlloc; - +class btDispatcher; /// btConstraintSolver provides solver interface class btConstraintSolver { @@ -35,8 +35,15 @@ public: virtual ~btConstraintSolver() {} - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0; + virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;} + ///solve a group of constraints + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0; + + virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */, btStackAlloc* /* stackAlloc */) {;} + + ///clear internal cached data and reset random seed + virtual void reset() = 0; }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index bb3fe832592..4d7cd05feb7 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -192,8 +192,8 @@ btScalar resolveSingleFriction( j1 = -vrel * cpd->m_jacDiagABInvTangent0; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; - GEN_set_min(cpd->m_accumulatedTangentImpulse0, limit); - GEN_set_max(cpd->m_accumulatedTangentImpulse0, -limit); + btSetMin(cpd->m_accumulatedTangentImpulse0, limit); + btSetMax(cpd->m_accumulatedTangentImpulse0, -limit); j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; } @@ -206,8 +206,8 @@ btScalar resolveSingleFriction( j2 = -vrel * cpd->m_jacDiagABInvTangent1; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; - GEN_set_min(cpd->m_accumulatedTangentImpulse1, limit); - GEN_set_max(cpd->m_accumulatedTangentImpulse1, -limit); + btSetMin(cpd->m_accumulatedTangentImpulse1, limit); + btSetMax(cpd->m_accumulatedTangentImpulse1, -limit); j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; } @@ -233,6 +233,12 @@ btScalar resolveSingleFriction( } +btScalar resolveSingleFrictionOriginal( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo); + btScalar resolveSingleFrictionOriginal( btRigidBody& body1, btRigidBody& body2, @@ -270,8 +276,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; btScalar total = cpd->m_accumulatedTangentImpulse0 + j; - GEN_set_min(total, limit); - GEN_set_max(total, -limit); + btSetMin(total, limit); + btSetMax(total, -limit); j = total - cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); @@ -290,8 +296,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; btScalar total = cpd->m_accumulatedTangentImpulse1 + j; - GEN_set_min(total, limit); - GEN_set_max(total, -limit); + btSetMin(total, limit); + btSetMax(total, -limit); j = total - cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); @@ -388,8 +394,8 @@ btScalar resolveSingleCollisionCombined( (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; - GEN_set_min(friction_impulse, normal_impulse); - GEN_set_max(friction_impulse, -normal_impulse); + btSetMin(friction_impulse, normal_impulse); + btSetMax(friction_impulse, -normal_impulse); body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); } @@ -400,6 +406,12 @@ btScalar resolveSingleCollisionCombined( return normalImpulse; } +btScalar resolveSingleFrictionEmpty( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo); + btScalar resolveSingleFrictionEmpty( btRigidBody& body1, btRigidBody& body2, diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index 0834deddeac..826e79f78bd 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -19,8 +19,8 @@ subject to the following restrictions: //todo: make into a proper class working with the iterative constraint solver class btRigidBody; -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" struct btContactSolverInfo; class btManifoldPoint; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index c3c73e300f4..916d4581f79 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -16,21 +16,17 @@ subject to the following restrictions: #ifndef CONTACT_SOLVER_INFO #define CONTACT_SOLVER_INFO - -struct btContactSolverInfo +enum btSolverMode { + SOLVER_RANDMIZE_ORDER = 1, + SOLVER_FRICTION_SEPARATE = 2, + SOLVER_USE_WARMSTARTING = 4, + SOLVER_CACHE_FRIENDLY = 8 +}; - inline btContactSolverInfo() - { - m_tau = btScalar(0.6); - m_damping = btScalar(1.0); - m_friction = btScalar(0.3); - m_restitution = btScalar(0.); - m_maxErrorReduction = btScalar(20.); - m_numIterations = 10; - m_erp = btScalar(0.4); - m_sor = btScalar(1.3); - } +struct btContactSolverInfoData +{ + btScalar m_tau; btScalar m_damping; @@ -40,8 +36,40 @@ struct btContactSolverInfo int m_numIterations; btScalar m_maxErrorReduction; btScalar m_sor; - btScalar m_erp; + btScalar m_erp;//used as Baumgarte factor + btScalar m_erp2;//used in Split Impulse + int m_splitImpulse; + btScalar m_splitImpulsePenetrationThreshold; + btScalar m_linearSlop; + btScalar m_warmstartingFactor; + + int m_solverMode; + }; +struct btContactSolverInfo : public btContactSolverInfoData +{ + + + + inline btContactSolverInfo() + { + m_tau = btScalar(0.6); + m_damping = btScalar(1.0); + m_friction = btScalar(0.3); + m_restitution = btScalar(0.); + m_maxErrorReduction = btScalar(20.); + m_numIterations = 10; + m_erp = btScalar(0.2); + m_erp2 = btScalar(0.1); + m_sor = btScalar(1.3); + m_splitImpulse = false; + m_splitImpulsePenetrationThreshold = -0.02f; + m_linearSlop = btScalar(0.0); + m_warmstartingFactor=btScalar(0.85); + m_solverMode = SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY | SOLVER_USE_WARMSTARTING; + } +}; + #endif //CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index 747d10d1f8b..077b326d13a 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -4,14 +4,20 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +/* +2007-09-09 +Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ #include "btGeneric6DofConstraint.h" @@ -19,371 +25,504 @@ subject to the following restrictions: #include "LinearMath/btTransformUtil.h" #include + static const btScalar kSign[] = { btScalar(1.0), btScalar(-1.0), btScalar(1.0) }; static const int kAxisA[] = { 1, 0, 0 }; static const int kAxisB[] = { 2, 2, 1 }; #define GENERIC_D6_DISABLE_WARMSTARTING 1 -btGeneric6DofConstraint::btGeneric6DofConstraint() +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) { -} - -btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) -: btTypedConstraint(rbA, rbB) -, m_frameInA(frameInA) -, m_frameInB(frameInB) -{ - //free means upper < lower, - //locked means upper == lower - //limited means upper > lower - //so start all locked - for (int i=0; i<6;++i) - { - m_lowerLimit[i] = btScalar(0.0); - m_upperLimit[i] = btScalar(0.0); - m_accumulatedImpulse[i] = btScalar(0.0); - } - -} - - -void btGeneric6DofConstraint::buildJacobian() -{ - btVector3 localNormalInA(0,0,0); - - const btVector3& pivotInA = m_frameInA.getOrigin(); - const btVector3& pivotInB = m_frameInB.getOrigin(); - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - int i; - //linear part - for (i=0;i<3;i++) - { - if (isLimited(i)) - { - localNormalInA[i] = 1; - btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; - - - // Create linear atom - new (&m_jacLinear[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*pivotInB - m_rbB.getCenterOfMassPosition(), - normalWorld, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - - //optionally disable warmstarting -#ifdef GENERIC_D6_DISABLE_WARMSTARTING - m_accumulatedImpulse[i] = btScalar(0.); -#endif //GENERIC_D6_DISABLE_WARMSTARTING - - // Apply accumulated impulse - btVector3 impulse_vector = m_accumulatedImpulse[i] * normalWorld; - - m_rbA.applyImpulse( impulse_vector, rel_pos1); - m_rbB.applyImpulse(-impulse_vector, rel_pos2); - - localNormalInA[i] = 0; - } - } - - // angular part - for (i=0;i<3;i++) - { - if (isLimited(i+3)) - { - btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); - btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); - - // Dirk: This is IMO mathematically the correct way, but we should consider axisA and axisB being near parallel maybe - btVector3 axis = kSign[i] * axisA.cross(axisB); - - // Create angular atom - new (&m_jacAng[i]) btJacobianEntry(axis, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - -#ifdef GENERIC_D6_DISABLE_WARMSTARTING - m_accumulatedImpulse[i + 3] = btScalar(0.); -#endif //GENERIC_D6_DISABLE_WARMSTARTING - - // Apply accumulated impulse - btVector3 impulse_vector = m_accumulatedImpulse[i + 3] * axis; - - m_rbA.applyTorqueImpulse( impulse_vector); - m_rbB.applyTorqueImpulse(-impulse_vector); - } - } -} - -btScalar getMatrixElem(const btMatrix3x3& mat,int index) -{ - int row = index%3; - int col = index / 3; - return mat[row][col]; + int i = index%3; + int j = index/3; + return mat[i][j]; } ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool MatrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) { - // rot = cy*cz -cy*sz sy - // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx - // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +// // rot = cy*cz -cy*sz sy +// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx +// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +// + + if (btGetMatrixElem(mat,2) < btScalar(1.0)) + { + if (btGetMatrixElem(mat,2) > btScalar(-1.0)) + { + xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); + xyz[1] = btAsin(btGetMatrixElem(mat,2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + + } -/// 0..8 - if (getMatrixElem(mat,2) < btScalar(1.0)) - { - if (getMatrixElem(mat,2) > btScalar(-1.0)) - { - xyz[0] = btAtan2(-getMatrixElem(mat,5),getMatrixElem(mat,8)); - xyz[1] = btAsin(getMatrixElem(mat,2)); - xyz[2] = btAtan2(-getMatrixElem(mat,1),getMatrixElem(mat,0)); - return true; - } - else - { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); - xyz[1] = -SIMD_HALF_PI; - xyz[2] = btScalar(0.0); - return false; - } - } - else - { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); - xyz[1] = SIMD_HALF_PI; - xyz[2] = 0.0; - - } - return false; } -void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) + +//////////////////////////// btRotationalLimitMotor //////////////////////////////////// + + +int btRotationalLimitMotor::testLimitValue(btScalar test_value) { - btScalar tau = btScalar(0.1); - btScalar damping = btScalar(1.0); - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 localNormalInA(0,0,0); - int i; - - // linear - for (i=0;i<3;i++) - { - if (isLimited(i)) - { - btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); - btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - localNormalInA.setValue(0,0,0); - localNormalInA[i] = 1; - btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; - - btScalar jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); - - //velocity error (first order error) - btScalar rel_vel = m_jacLinear[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normalWorld); - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - //handle the limits - if (m_lowerLimit[i] < m_upperLimit[i]) - { - { - if (depth > m_upperLimit[i]) - { - depth -= m_upperLimit[i]; - lo = btScalar(0.); - - } else - { - if (depth < m_lowerLimit[i]) - { - depth -= m_lowerLimit[i]; - hi = btScalar(0.); - } else - { - continue; - } - } - } - } - - btScalar normalImpulse= (tau*depth/timeStep - damping*rel_vel) * jacDiagABInv; - btScalar oldNormalImpulse = m_accumulatedImpulse[i]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[i] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[i] - oldNormalImpulse; - - btVector3 impulse_vector = normalWorld * normalImpulse; - m_rbA.applyImpulse( impulse_vector, rel_pos1); - m_rbB.applyImpulse(-impulse_vector, rel_pos2); - - localNormalInA[i] = 0; - } - } - - btVector3 axis; - btScalar angle; - btTransform frameAWorld = m_rbA.getCenterOfMassTransform() * m_frameInA; - btTransform frameBWorld = m_rbB.getCenterOfMassTransform() * m_frameInB; - - btTransformUtil::calculateDiffAxisAngle(frameAWorld,frameBWorld,axis,angle); - btQuaternion diff(axis,angle); - btMatrix3x3 diffMat (diff); - btVector3 xyz; - ///this is not perfect, we can first check which axis are limited, and choose a more appropriate order - MatrixToEulerXYZ(diffMat,xyz); - - // angular - for (i=0;i<3;i++) + if(m_loLimit>m_hiLimit) { - if (isLimited(i+3)) - { - btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); - btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - btScalar jacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); - - //velocity error (first order error) - btScalar rel_vel = m_jacAng[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - - //positional error (zeroth order error) - btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); - btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); - - btScalar rel_pos = kSign[i] * axisA.dot(axisB); - - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - //handle the twist limit - if (m_lowerLimit[i+3] < m_upperLimit[i+3]) - { - //clamp the values - btScalar loLimit = m_lowerLimit[i+3] > -3.1415 ? m_lowerLimit[i+3] : btScalar(-1e30); - btScalar hiLimit = m_upperLimit[i+3] < 3.1415 ? m_upperLimit[i+3] : btScalar(1e30); - - btScalar projAngle = btScalar(-1.)*xyz[i]; - - if (projAngle < loLimit) - { - hi = btScalar(0.); - rel_pos = (loLimit - projAngle); - } else - { - if (projAngle > hiLimit) - { - lo = btScalar(0.); - rel_pos = (hiLimit - projAngle); - } else - { - continue; - } - } - } - - //impulse - - btScalar normalImpulse= -(tau*rel_pos/timeStep + damping*rel_vel) * jacDiagABInv; - btScalar oldNormalImpulse = m_accumulatedImpulse[i+3]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[i+3] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[i+3] - oldNormalImpulse; - - // Dirk: Not needed - we could actually project onto Jacobian entry here (same as above) - btVector3 axis = kSign[i] * axisA.cross(axisB); - btVector3 impulse_vector = axis * normalImpulse; - - m_rbA.applyTorqueImpulse( impulse_vector); - m_rbB.applyTorqueImpulse(-impulse_vector); - } + m_currentLimit = 0;//Free from violation + return 0; } + + if (test_value < m_loLimit) + { + m_currentLimit = 1;//low limit violation + m_currentLimitError = test_value - m_loLimit; + return 1; + } + else if (test_value> m_hiLimit) + { + m_currentLimit = 2;//High limit violation + m_currentLimitError = test_value - m_hiLimit; + return 2; + }; + + m_currentLimit = 0;//Free from violation + return 0; + +} + + +btScalar btRotationalLimitMotor::solveAngularLimits( + btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, + btRigidBody * body0, btRigidBody * body1) +{ + if (needApplyTorques()==false) return 0.0f; + + btScalar target_velocity = m_targetVelocity; + btScalar maxMotorForce = m_maxMotorForce; + + //current error correction + if (m_currentLimit!=0) + { + target_velocity = -m_ERP*m_currentLimitError/(timeStep); + maxMotorForce = m_maxLimitForce; + } + + maxMotorForce *= timeStep; + + // current velocity difference + btVector3 vel_diff = body0->getAngularVelocity(); + if (body1) + { + vel_diff -= body1->getAngularVelocity(); + } + + + + btScalar rel_vel = axis.dot(vel_diff); + + // correction velocity + btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + + + if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) + { + return 0.0f;//no need for applying force + } + + + // correction impulse + btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; + + // clip correction impulse + btScalar clippedMotorImpulse; + + //todo: should clip against accumulated impulse + if (unclippedMotorImpulse>0.0f) + { + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; + } + else + { + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; + } + + + // sort with accumulated impulses + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + btScalar oldaccumImpulse = m_accumulatedImpulse; + btScalar sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + + + btVector3 motorImp = clippedMotorImpulse * axis; + + + body0->applyTorqueImpulse(motorImp); + if (body1) body1->applyTorqueImpulse(-motorImp); + + return clippedMotorImpulse; + + +} + +//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// +btScalar btTranslationalLimitMotor::solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos) +{ + +///find relative velocity +// btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); +// btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); + btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel = axis_normal_on_a.dot(vel); + + + +/// apply displacement correction + +//positional error (zeroth order error) + btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + btScalar minLimit = m_lowerLimit[limit_index]; + btScalar maxLimit = m_upperLimit[limit_index]; + + //handle the limits + if (minLimit < maxLimit) + { + { + if (depth > maxLimit) + { + depth -= maxLimit; + lo = btScalar(0.); + + } + else + { + if (depth < minLimit) + { + depth -= minLimit; + hi = btScalar(0.); + } + else + { + return 0.0f; + } + } + } + } + + btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; + + + + + btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; + + btVector3 impulse_vector = axis_normal_on_a * normalImpulse; + body1.applyImpulse( impulse_vector, rel_pos1); + body2.applyImpulse(-impulse_vector, rel_pos2); + return normalImpulse; +} + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + + +btGeneric6DofConstraint::btGeneric6DofConstraint() + :btTypedConstraint(D6_CONSTRAINT_TYPE), + m_useLinearReferenceFrameA(true) +{ +} + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) + , m_frameInA(frameInA) + , m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + +} + + + + + +void btGeneric6DofConstraint::calculateAngleInfo() +{ + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); + + matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + + + + // in euler angle mode we do not actually constrain the angular velocity + // along the axes axis[0] and axis[2] (although we do use axis[1]) : + // + // to get constrain w2-w1 along ...not + // ------ --------------------- ------ + // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] + // d(angle[1])/dt = 0 ax[1] + // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] + // + // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. + // to prove the result for angle[0], write the expression for angle[0] from + // GetInfo1 then take the derivative. to prove this for angle[2] it is + // easier to take the euler rate expression for d(angle[2])/dt with respect + // to the components of w and set that to 0. + + btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); + btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); + + m_calculatedAxis[1] = axis2.cross(axis0); + m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); + m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); + + +// if(m_debugDrawer) +// { +// +// char buff[300]; +// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", +// m_calculatedAxisAngleDiff[0], +// m_calculatedAxisAngleDiff[1], +// m_calculatedAxisAngleDiff[2]); +// m_debugDrawer->reportErrorWarning(buff); +// } + +} + +void btGeneric6DofConstraint::calculateTransforms() +{ + m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + + calculateAngleInfo(); +} + + +void btGeneric6DofConstraint::buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW) +{ + new (&jacLinear) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + +} + +void btGeneric6DofConstraint::buildAngularJacobian( + btJacobianEntry & jacAngular,const btVector3 & jointAxisW) +{ + new (&jacAngular) btJacobianEntry(jointAxisW, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +} + +bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) +{ + btScalar angle = m_calculatedAxisAngleDiff[axis_index]; + + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); +} + +void btGeneric6DofConstraint::buildJacobian() +{ + + // Clear accumulated impulses for the next simulation step + m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + int i; + for(i = 0; i < 3; i++) + { + m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); + } + //calculates transform + calculateTransforms(); + +// const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); +// const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); + calcAnchorPos(); + btVector3 pivotAInW = m_AnchorPos; + btVector3 pivotBInW = m_AnchorPos; + +// not used here +// btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); +// btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 normalWorld; + //linear part + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + if (m_useLinearReferenceFrameA) + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + else + normalWorld = m_calculatedTransformB.getBasis().getColumn(i); + + buildLinearJacobian( + m_jacLinear[i],normalWorld , + pivotAInW,pivotBInW); + + } + } + + // angular part + for (i=0;i<3;i++) + { + //calculates error angle + if (testAngularLimitMotor(i)) + { + normalWorld = this->getAxis(i); + // Create angular atom + buildAngularJacobian(m_jacAng[i],normalWorld); + } + } + + +} + + +void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) +{ + m_timeStep = timeStep; + + //calculateTransforms(); + + int i; + + // linear + + btVector3 pointInA = m_calculatedTransformA.getOrigin(); + btVector3 pointInB = m_calculatedTransformB.getOrigin(); + + btScalar jacDiagABInv; + btVector3 linear_axis; + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); + + if (m_useLinearReferenceFrameA) + linear_axis = m_calculatedTransformA.getBasis().getColumn(i); + else + linear_axis = m_calculatedTransformB.getBasis().getColumn(i); + + m_linearLimits.solveLinearAxis( + m_timeStep, + jacDiagABInv, + m_rbA,pointInA, + m_rbB,pointInB, + i,linear_axis, m_AnchorPos); + + } + } + + // angular + btVector3 angular_axis; + btScalar angularJacDiagABInv; + for (i=0;i<3;i++) + { + if (m_angularLimits[i].needApplyTorques()) + { + + // get axis + angular_axis = getAxis(i); + + angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); + + m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); + } + } } void btGeneric6DofConstraint::updateRHS(btScalar timeStep) { - (void)timeStep; + (void)timeStep; } -btScalar btGeneric6DofConstraint::computeAngle(int axis) const +btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const +{ + return m_calculatedAxis[axis_index]; +} + +btScalar btGeneric6DofConstraint::getAngle(int axis_index) const +{ + return m_calculatedAxisAngleDiff[axis_index]; +} + +void btGeneric6DofConstraint::calcAnchorPos(void) +{ + btScalar imA = m_rbA.getInvMass(); + btScalar imB = m_rbB.getInvMass(); + btScalar weight; + if(imB == btScalar(0.0)) { - btScalar angle = btScalar(0.f); - - switch (axis) - { - case 0: - { - btVector3 v1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(1); - btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); - btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); - - btScalar s = v1.dot(w2); - btScalar c = v1.dot(v2); - - angle = btAtan2( s, c ); - } - break; - - case 1: - { - btVector3 w1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(2); - btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); - btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); - - btScalar s = w1.dot(u2); - btScalar c = w1.dot(w2); - - angle = btAtan2( s, c ); - } - break; - - case 2: - { - btVector3 u1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(0); - btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); - btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); - - btScalar s = u1.dot(v2); - btScalar c = u1.dot(u2); - - angle = btAtan2( s, c ); - } - break; - default: - btAssert ( 0 ) ; - - break ; - } - - return angle; + weight = btScalar(1.0); } + else + { + weight = imA / (imA + imB); + } + const btVector3& pA = m_calculatedTransformA.getOrigin(); + const btVector3& pB = m_calculatedTransformB.getOrigin(); + m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight); + return; +} // btGeneric6DofConstraint::calcAnchorPos() diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index b114e54fa69..f0718d2d4a0 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -4,116 +4,433 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +/* +2007-09-09 +btGeneric6DofConstraint Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + #ifndef GENERIC_6DOF_CONSTRAINT_H #define GENERIC_6DOF_CONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; +//! Rotation Limit structure for generic joints +class btRotationalLimitMotor +{ +public: + //! limit_parameters + //!@{ + btScalar m_loLimit;//!< joint limit + btScalar m_hiLimit;//!< joint limit + btScalar m_targetVelocity;//!< target motor velocity + btScalar m_maxMotorForce;//!< max force on motor + btScalar m_maxLimitForce;//!< max force on limit + btScalar m_damping;//!< Damping. + btScalar m_limitSoftness;//! Relaxation factor + btScalar m_ERP;//!< Error tolerance factor when joint is at limit + btScalar m_bounce;//!< restitution factor + bool m_enableMotor; + + //!@} + + //! temp_variables + //!@{ + btScalar m_currentLimitError;//! How much is violated this limit + int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit + btScalar m_accumulatedImpulse; + //!@} + + btRotationalLimitMotor() + { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 0.1f; + m_maxLimitForce = 300.0f; + m_loLimit = -SIMD_INFINITY; + m_hiLimit = SIMD_INFINITY; + m_ERP = 0.5f; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + } + + btRotationalLimitMotor(const btRotationalLimitMotor & limot) + { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_ERP = limot.m_ERP; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } + + + + //! Is limited + bool isLimited() + { + if(m_loLimit>=m_hiLimit) return false; + return true; + } + + //! Need apply correction + bool needApplyTorques() + { + if(m_currentLimit == 0 && m_enableMotor == false) return false; + return true; + } + + //! calculates error + /*! + calculates m_currentLimit and m_currentLimitError. + */ + int testLimitValue(btScalar test_value); + + //! apply the correction impulses for two bodies + btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); + + +}; + + + +class btTranslationalLimitMotor +{ +public: + btVector3 m_lowerLimit;//!< the constraint lower limits + btVector3 m_upperLimit;//!< the constraint upper limits + btVector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + btScalar m_limitSoftness;//!< Softness for linear limit + btScalar m_damping;//!< Damping for linear limit + btScalar m_restitution;//! Bounce parameter for linear limit + //!@} + + btTranslationalLimitMotor() + { + m_lowerLimit.setValue(0.f,0.f,0.f); + m_upperLimit.setValue(0.f,0.f,0.f); + m_accumulatedImpulse.setValue(0.f,0.f,0.f); + + m_limitSoftness = 0.7f; + m_damping = btScalar(1.0f); + m_restitution = btScalar(0.5f); + } + + btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) + { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; + + m_limitSoftness = other.m_limitSoftness ; + m_damping = other.m_damping; + m_restitution = other.m_restitution; + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + inline bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + + + btScalar solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos); + + +}; /// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space -/// btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked' -/// Work in progress (is still a Hinge actually) +/*! +btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. +currently this limit supports rotational motors
+
    +
  • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. +At this moment translational motors are not supported. May be in the future.
  • + +
  • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. +This is accessible through btGeneric6DofConstraint.getLimitMotor method, +This brings support for limit parameters and motors.
  • + +
  • Angulars limits have these possible ranges: + +AXIS + + + + + + + + + + + + +
    MIN ANGLEMAX ANGLEX-PIPIY-PI/2PI/2Z-PI/2PI/2
    +
  • +
+ +*/ class btGeneric6DofConstraint : public btTypedConstraint { - btJacobianEntry m_jacLinear[3]; // 3 orthogonal linear constraints - btJacobianEntry m_jacAng[3]; // 3 orthogonal angular constraints +protected: - btTransform m_frameInA; // the constraint space w.r.t body A - btTransform m_frameInB; // the constraint space w.r.t body B + //! relative_frames + //!@{ + btTransform m_frameInA;//!< the constraint space w.r.t body A + btTransform m_frameInB;//!< the constraint space w.r.t body B + //!@} + + //! Jacobians + //!@{ + btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints + //!@} + + //! Linear_Limit_parameters + //!@{ + btTranslationalLimitMotor m_linearLimits; + //!@} + + + //! hinge_parameters + //!@{ + btRotationalLimitMotor m_angularLimits[3]; + //!@} + + +protected: + //! temporal variables + //!@{ + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + + btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes + + bool m_useLinearReferenceFrameA; + + //!@} + + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + + + + void buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW); + + void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + + + //! calcs the euler angles between the two bodies. + void calculateAngleInfo(); - btScalar m_lowerLimit[6]; // the constraint lower limits - btScalar m_upperLimit[6]; // the constraint upper limits - btScalar m_accumulatedImpulse[6]; - btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } - public: - btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ); + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btGeneric6DofConstraint(); + btGeneric6DofConstraint(); - - virtual void buildJacobian(); + //! Calcs global transform of the offsets + /*! + Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. + \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo + */ + void calculateTransforms(); - virtual void solveConstraint(btScalar timeStep); + //! Gets the global transform of the offset for body A + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformA() const + { + return m_calculatedTransformA; + } - void updateRHS(btScalar timeStep); + //! Gets the global transform of the offset for body B + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformB() const + { + return m_calculatedTransformB; + } - btScalar computeAngle(int axis) const; + const btTransform & getFrameOffsetA() const + { + return m_frameInA; + } - void setLinearLowerLimit(const btVector3& linearLower) - { - m_lowerLimit[0] = linearLower.getX(); - m_lowerLimit[1] = linearLower.getY(); - m_lowerLimit[2] = linearLower.getZ(); - } + const btTransform & getFrameOffsetB() const + { + return m_frameInB; + } - void setLinearUpperLimit(const btVector3& linearUpper) - { - m_upperLimit[0] = linearUpper.getX(); - m_upperLimit[1] = linearUpper.getY(); - m_upperLimit[2] = linearUpper.getZ(); - } - void setAngularLowerLimit(const btVector3& angularLower) - { - m_lowerLimit[3] = angularLower.getX(); - m_lowerLimit[4] = angularLower.getY(); - m_lowerLimit[5] = angularLower.getZ(); - } + btTransform & getFrameOffsetA() + { + return m_frameInA; + } - void setAngularUpperLimit(const btVector3& angularUpper) - { - m_upperLimit[3] = angularUpper.getX(); - m_upperLimit[4] = angularUpper.getY(); - m_upperLimit[5] = angularUpper.getZ(); - } + btTransform & getFrameOffsetB() + { + return m_frameInB; + } - //first 3 are linear, next 3 are angular - void SetLimit(int axis, btScalar lo, btScalar hi) - { - m_lowerLimit[axis] = lo; - m_upperLimit[axis] = hi; - } - //free means upper < lower, - //locked means upper == lower - //limited means upper > lower - //limitIndex: first 3 are linear, next 3 are angular - bool isLimited(int limitIndex) - { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } + //! performs Jacobian calculation, and also calculates angle differences and axis + virtual void buildJacobian(); - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + //! Get the rotation axis in global coordinates + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btVector3 getAxis(int axis_index) const; + + //! Get the relative Euler angle + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btScalar getAngle(int axis_index) const; + + //! Test angular limit. + /*! + Calculates angular correction and returns true if limit needs to be corrected. + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + bool testAngularLimitMotor(int axis_index); + + void setLinearLowerLimit(const btVector3& linearLower) + { + m_linearLimits.m_lowerLimit = linearLower; + } + + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_linearLimits.m_upperLimit = linearUpper; + } + + void setAngularLowerLimit(const btVector3& angularLower) + { + m_angularLimits[0].m_loLimit = angularLower.getX(); + m_angularLimits[1].m_loLimit = angularLower.getY(); + m_angularLimits[2].m_loLimit = angularLower.getZ(); + } + + void setAngularUpperLimit(const btVector3& angularUpper) + { + m_angularLimits[0].m_hiLimit = angularUpper.getX(); + m_angularLimits[1].m_hiLimit = angularUpper.getY(); + m_angularLimits[2].m_hiLimit = angularUpper.getZ(); + } + + //! Retrieves the angular limit informacion + btRotationalLimitMotor * getRotationalLimitMotor(int index) + { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + btTranslationalLimitMotor * getTranslationalLimitMotor() + { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, btScalar lo, btScalar hi) + { + if(axis<3) + { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } + else + { + m_angularLimits[axis-3].m_loLimit = lo; + m_angularLimits[axis-3].m_hiLimit = hi; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + bool isLimited(int limitIndex) + { + if(limitIndex<3) + { + return m_linearLimits.isLimited(limitIndex); + + } + return m_angularLimits[limitIndex-3].isLimited(); + } + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + virtual void calcAnchorPos(void); // overridable }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index 27e30987549..a0523a8c76b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -17,58 +17,185 @@ subject to the following restrictions: #include "btHingeConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" #include -btHingeConstraint::btHingeConstraint(): + +btHingeConstraint::btHingeConstraint() +: btTypedConstraint (HINGE_CONSTRAINT_TYPE), m_enableAngularMotor(false) { } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - btVector3& axisInA,btVector3& axisInB) -:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), -m_axisInA(axisInA), -m_axisInB(-axisInB), -m_angularOnly(false), -m_enableAngularMotor(false) + btVector3& axisInA,btVector3& axisInB) + :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), + m_angularOnly(false), + m_enableAngularMotor(false) { + m_rbAFrame.getOrigin() = pivotInA; + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + + btVector3 rbAxisA2; + btScalar projection = axisInA.dot(rbAxisA1); + if (projection >= 1.0f - SIMD_EPSILON) { + rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else if (projection <= -1.0f + SIMD_EPSILON) { + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else { + rbAxisA2 = axisInA.cross(rbAxisA1); + rbAxisA1 = rbAxisA2.cross(axisInA); + } + + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.getOrigin() = pivotInB; + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),-axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),-axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),-axisInB.getZ() ); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) -:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), -m_axisInA(axisInA), -//fixed axis in worldspace -m_axisInB(rbA.getCenterOfMassTransform().getBasis() * -axisInA), +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) +{ + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + // fixed axis in worldspace + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + btScalar projection = rbAxisA1.dot(axisInA); + if (projection > SIMD_EPSILON) + rbAxisA1 = rbAxisA1*projection - axisInA; + else + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + + btVector3 rbAxisA2 = axisInA.cross(rbAxisA1); + + m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + + btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + + m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +} + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false), m_enableAngularMotor(false) { - + // flip axis + m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), +m_angularOnly(false), +m_enableAngularMotor(false) +{ + ///not providing rigidbody B means implicitly using worldspace for body B + + // flip axis + m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; } void btHingeConstraint::buildJacobian() { m_appliedImpulse = btScalar(0.); - btVector3 normal(0,0,0); - if (!m_angularOnly) { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + for (int i=0;i<3;i++) { - normal[i] = 1; new (&m_jac[i]) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), - normal, + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], m_rbA.getInvInertiaDiagLocal(), m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); - normal[i] = 0; } } @@ -79,12 +206,12 @@ void btHingeConstraint::buildJacobian() btVector3 jointAxis0local; btVector3 jointAxis1local; - btPlaneSpace1(m_axisInA,jointAxis0local,jointAxis1local); + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); - getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; - btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); new (&m_jacAng[0]) btJacobianEntry(jointAxis0, m_rbA.getCenterOfMassTransform().getBasis().transpose(), @@ -105,44 +232,73 @@ void btHingeConstraint::buildJacobian() m_rbB.getInvInertiaDiagLocal()); + // Compute limit information + btScalar hingeAngle = getHingeAngle(); + + //set bias, sign, clear accumulator + m_correction = btScalar(0.); + m_limitSign = btScalar(0.); + m_solveLimit = false; + m_accLimitImpulse = btScalar(0.); + +// if (m_lowerLimit < m_upperLimit) + if (m_lowerLimit <= m_upperLimit) + { +// if (hingeAngle <= m_lowerLimit*m_limitSoftness) + if (hingeAngle <= m_lowerLimit) + { + m_correction = (m_lowerLimit - hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } +// else if (hingeAngle >= m_upperLimit*m_limitSoftness) + else if (hingeAngle >= m_upperLimit) + { + m_correction = m_upperLimit - hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } + + //Compute K = J*W*J' for hinge axis + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA)); } void btHingeConstraint::solveConstraint(btScalar timeStep) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 normal(0,0,0); btScalar tau = btScalar(0.3); - btScalar damping = btScalar(1.); -//linear part + //linear part if (!m_angularOnly) { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + for (int i=0;i<3;i++) { - normal[i] = 1; + const btVector3& normal = m_jac[i].m_linearJointAxis; btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; btScalar rel_vel; rel_vel = normal.dot(vel); //positional error (zeroth order error) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - damping * rel_vel * jacDiagABInv * damping; + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; m_appliedImpulse += impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); - - normal[i] = 0; } } @@ -151,8 +307,8 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) ///solve angular part // get axes in world space - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; - btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_axisInB; + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); @@ -174,7 +330,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) getRigidBodyB().computeAngularImpulseDenominator(normal); // scale for mass and relaxation //todo: expose this 0.9 factor to developer - velrelOrthog *= (btScalar(1.)/denom) * btScalar(0.9); + velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; } //solve angular positional correction @@ -190,10 +346,28 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); m_rbB.applyTorqueImpulse(velrelOrthog-angularError); + + // solve limit + if (m_solveLimit) + { + btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; + + btScalar impulseMag = amplitude * m_kHinge; + + // Clamp the accumulated impulse + btScalar temp = m_accLimitImpulse; + m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); + impulseMag = m_accLimitImpulse - temp; + + + btVector3 impulse = axisA * impulseMag * m_limitSign; + m_rbA.applyTorqueImpulse(impulse); + m_rbB.applyTorqueImpulse(-impulse); + } } //apply motor - if (m_enableAngularMotor) + if (m_enableAngularMotor) { //todo: add limits too btVector3 angularLimit(0,0,0); @@ -204,10 +378,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) btScalar desiredMotorVel = m_motorTargetVelocity; btScalar motor_relvel = desiredMotorVel - projRelVel; - btScalar denom3 = getRigidBodyA().computeAngularImpulseDenominator(axisA) + - getRigidBodyB().computeAngularImpulseDenominator(axisA); - - btScalar unclippedMotorImpulse = (btScalar(1.)/denom3) * motor_relvel;; + btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; //todo: should clip against accumulated impulse btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; @@ -227,3 +398,12 @@ void btHingeConstraint::updateRHS(btScalar timeStep) } +btScalar btHingeConstraint::getHingeAngle() +{ + const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); + + return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1) ); +} + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 5c1ceafbc5b..4fa9972f6d8 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -13,39 +13,61 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ + #ifndef HINGECONSTRAINT_H #define HINGECONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; - /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /// axis defines the orientation of the hinge axis class btHingeConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - btVector3 m_pivotInA; - btVector3 m_pivotInB; - btVector3 m_axisInA; - btVector3 m_axisInB; + btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransform m_rbBFrame; + + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + btScalar m_lowerLimit; + btScalar m_upperLimit; + + btScalar m_kHinge; + + btScalar m_limitSign; + btScalar m_correction; + + btScalar m_accLimitImpulse; bool m_angularOnly; - - btScalar m_motorTargetVelocity; - btScalar m_maxMotorImpulse; bool m_enableAngularMotor; + bool m_solveLimit; + public: - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,btVector3& axisInA,btVector3& axisInB); + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB); btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); + + btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame); btHingeConstraint(); @@ -76,6 +98,61 @@ public: m_maxMotorImpulse = maxMotorImpulse; } + void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { + m_lowerLimit = low; + m_upperLimit = high; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + + } + + btScalar getLowerLimit() const + { + return m_lowerLimit; + } + + btScalar getUpperLimit() const + { + return m_upperLimit; + } + + + btScalar getHingeAngle(); + + + const btTransform& getAFrame() { return m_rbAFrame; }; + const btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveLimit() + { + return m_solveLimit; + } + + inline btScalar getLimitSign() + { + return m_limitSign; + } + + inline bool getAngularOnly() + { + return m_angularOnly; + } + inline bool getEnableAngularMotor() + { + return m_enableAngularMotor; + } + inline btScalar getMotorTargetVelosity() + { + return m_motorTargetVelocity; + } + inline btScalar getMaxMotorImpulse() + { + return m_maxMotorImpulse; + } + }; #endif //HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h index aae3ed0373f..bfeb24c2dfb 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef JACOBIAN_ENTRY_H #define JACOBIAN_ENTRY_H -#include "../../LinearMath/btVector3.h" -#include "../Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" //notes: diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index aacb0a3ea66..2b69ad90438 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -21,18 +21,19 @@ subject to the following restrictions: btPoint2PointConstraint::btPoint2PointConstraint() +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) -:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) { } @@ -99,6 +100,16 @@ void btPoint2PointConstraint::solveConstraint(btScalar timeStep) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal btScalar impulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; + + btScalar impulseClamp = m_setting.m_impulseClamp; + if (impulseClamp > 0) + { + if (impulse < -impulseClamp) + impulse = -impulseClamp; + if (impulse > impulseClamp) + impulse = impulseClamp; + } + m_appliedImpulse+=impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index 71da8ac0347..c9d5968530c 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef POINT2POINTCONSTRAINT_H #define POINT2POINTCONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" @@ -26,16 +26,21 @@ struct btConstraintSetting { btConstraintSetting() : m_tau(btScalar(0.3)), - m_damping(btScalar(1.)) + m_damping(btScalar(1.)), + m_impulseClamp(btScalar(0.)) { } btScalar m_tau; btScalar m_damping; + btScalar m_impulseClamp; }; /// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space class btPoint2PointConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btVector3 m_pivotInA; @@ -70,6 +75,15 @@ public: m_pivotInB = pivotB; } + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 14b36ad44fd..b8afbd6aac5 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -13,6 +13,9 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +//#define COMPUTE_IMPULSE_DENOM 1 +//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. +//#define FORCE_REFESH_CONTACT_MANIFOLDS 1 #include "btSequentialImpulseConstraintSolver.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -30,11 +33,9 @@ subject to the following restrictions: #include "btSolverBody.h" #include "btSolverConstraint.h" + #include "LinearMath/btAlignedObjectArray.h" -#ifdef USE_PROFILE -#include "LinearMath/btQuickprof.h" -#endif //USE_PROFILE int totalCpd = 0; @@ -64,7 +65,7 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2() int btSequentialImpulseConstraintSolver::btRandInt2 (int n) { // seems good; xor-fold and modulus - const unsigned long un = n; + const unsigned long un = static_cast(n); unsigned long r = btRand2(); // note: probably more aggressive than it needs to be -- might be @@ -91,12 +92,12 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n) - +bool MyContactDestroyedCallback(void* userPersistentData); bool MyContactDestroyedCallback(void* userPersistentData) { assert (userPersistentData); btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; - delete cpd; + btAlignedFree(cpd); totalCpd--; //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); return true; @@ -105,8 +106,7 @@ bool MyContactDestroyedCallback(void* userPersistentData) btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() -:m_solverMode(SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY), //not using SOLVER_USE_WARMSTARTING, -m_btSeed2(0) +:m_btSeed2(0) { gContactDestroyedCallback = &MyContactDestroyedCallback; @@ -121,27 +121,42 @@ m_btSeed2(0) } } - -void initSolverBody(btSolverBody* solverBody, btRigidBody* rigidbody) +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() { -/* int size = sizeof(btSolverBody); - int sizeofrb = sizeof(btRigidBody); - int sizemanifold = sizeof(btPersistentManifold); - int sizeofmp = sizeof(btManifoldPoint); - int sizeofPersistData = sizeof (btConstraintPersistentData); -*/ - solverBody->m_angularVelocity = rigidbody->getAngularVelocity(); - solverBody->m_centerOfMassPosition = rigidbody->getCenterOfMassPosition(); - solverBody->m_friction = rigidbody->getFriction(); -// solverBody->m_invInertiaWorld = rigidbody->getInvInertiaTensorWorld(); - solverBody->m_invMass = rigidbody->getInvMass(); - solverBody->m_linearVelocity = rigidbody->getLinearVelocity(); - solverBody->m_originalBody = rigidbody; - solverBody->m_angularFactor = rigidbody->getAngularFactor(); } -btScalar penetrationResolveFactor = btScalar(0.9); +void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); +void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) +{ + btRigidBody* rb = btRigidBody::upcast(collisionObject); + if (rb) + { + solverBody->m_angularVelocity = rb->getAngularVelocity() ; + solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin(); + solverBody->m_friction = collisionObject->getFriction(); + solverBody->m_invMass = rb->getInvMass(); + solverBody->m_linearVelocity = rb->getLinearVelocity(); + solverBody->m_originalBody = rb; + solverBody->m_angularFactor = rb->getAngularFactor(); + } else + { + solverBody->m_angularVelocity.setValue(0,0,0); + solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin(); + solverBody->m_friction = collisionObject->getFriction(); + solverBody->m_invMass = 0.f; + solverBody->m_linearVelocity.setValue(0,0,0); + solverBody->m_originalBody = 0; + solverBody->m_angularFactor = 1.f; + } + solverBody->m_pushVelocity.setValue(0.f,0.f,0.f); + solverBody->m_turnVelocity.setValue(0.f,0.f,0.f); +} + + +int gNumSplitImpulseRecoveries = 0; + +btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) { btScalar rest = restitution * -rel_vel; @@ -149,30 +164,95 @@ btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) } +void resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo); + +//SIMD_FORCE_INLINE +void resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo) +{ + (void)solverInfo; + + if (contactConstraint.m_penetration < solverInfo.m_splitImpulsePenetrationThreshold) + { + + gNumSplitImpulseRecoveries++; + btScalar normalImpulse; + + // Optimized version of projected relative velocity, use precomputed cross products with normal + // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + // btVector3 vel = vel1 - vel2; + // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); + + btScalar rel_vel; + btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_pushVelocity) + + contactConstraint.m_relpos1CrossNormal.dot(body1.m_turnVelocity); + btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_pushVelocity) + + contactConstraint.m_relpos2CrossNormal.dot(body2.m_turnVelocity); + + rel_vel = vel1Dotn-vel2Dotn; + btScalar positionalError = -contactConstraint.m_penetration * solverInfo.m_erp2/solverInfo.m_timeStep; + // btScalar positionalError = contactConstraint.m_penetration; + + btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; + + btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; + normalImpulse = penetrationImpulse+velocityImpulse; + + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse + btScalar oldNormalImpulse = contactConstraint.m_appliedPushImpulse; + btScalar sum = oldNormalImpulse + normalImpulse; + contactConstraint.m_appliedPushImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + + normalImpulse = contactConstraint.m_appliedPushImpulse - oldNormalImpulse; + + body1.internalApplyPushImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); + + body2.internalApplyPushImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); + + } + +} //velocity + friction //response between two dynamic objects with friction -SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( + +btScalar resolveSingleCollisionCombinedCacheFriendly( btSolverBody& body1, btSolverBody& body2, - btSolverConstraint& contactConstraint, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo); + +//SIMD_FORCE_INLINE +btScalar resolveSingleCollisionCombinedCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo) { (void)solverInfo; - btScalar normalImpulse(0.f); - { - if (contactConstraint.m_penetration < 0.f) - return 0.f; + btScalar normalImpulse; - // Optimized version of projected relative velocity, use precomputed cross products with normal - // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); - // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - // btVector3 vel = vel1 - vel2; - // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); + { + + + // Optimized version of projected relative velocity, use precomputed cross products with normal + // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + // btVector3 vel = vel1 - vel2; + // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); btScalar rel_vel; btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) @@ -182,50 +262,51 @@ SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( rel_vel = vel1Dotn-vel2Dotn; + btScalar positionalError = 0.f; + if (!solverInfo.m_splitImpulse || (contactConstraint.m_penetration > solverInfo.m_splitImpulsePenetrationThreshold)) + { + positionalError = -contactConstraint.m_penetration * solverInfo.m_erp/solverInfo.m_timeStep; + } - btScalar positionalError = contactConstraint.m_penetration; btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; - btScalar normalImpulse = penetrationImpulse+velocityImpulse; + normalImpulse = penetrationImpulse+velocityImpulse; + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; btScalar sum = oldNormalImpulse + normalImpulse; contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; - btScalar velocitySum = oldVelocityImpulse + velocityImpulse; - contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; - normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, + + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); - } - } - - return normalImpulse; } #ifndef NO_FRICTION_TANGENTIALS -SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( +btScalar resolveSingleFrictionCacheFriendly( btSolverBody& body1, btSolverBody& body2, - btSolverConstraint& contactConstraint, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo, + btScalar appliedNormalImpulse); + +//SIMD_FORCE_INLINE +btScalar resolveSingleFrictionCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo, btScalar appliedNormalImpulse) { @@ -252,22 +333,42 @@ SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( // calculate j that moves us to zero relative velocity j1 = -rel_vel * contactConstraint.m_jacDiagABInv; +#define CLAMP_ACCUMULATED_FRICTION_IMPULSE 1 +#ifdef CLAMP_ACCUMULATED_FRICTION_IMPULSE btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; - GEN_set_min(contactConstraint.m_appliedImpulse, limit); - GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + + if (limit < contactConstraint.m_appliedImpulse) + { + contactConstraint.m_appliedImpulse = limit; + } else + { + if (contactConstraint.m_appliedImpulse < -limit) + contactConstraint.m_appliedImpulse = -limit; + } j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; +#else + if (limit < j1) + { + j1 = limit; + } else + { + if (j1 < -limit) + j1 = -limit; + } + +#endif //CLAMP_ACCUMULATED_FRICTION_IMPULSE + + //GEN_set_min(contactConstraint.m_appliedImpulse, limit); + //GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + + } - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); - } + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); + + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); } return 0.f; @@ -309,7 +410,6 @@ btScalar resolveSingleFrictionCacheFriendly( const btVector3& rel_pos2 = contactConstraint.m_rel_posB; - //if (contactConstraint.m_appliedVelocityImpulse > 0.f) if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) { lat_rel_vel = btSqrt(lat_rel_vel); @@ -319,7 +419,7 @@ btScalar resolveSingleFrictionCacheFriendly( btVector3 temp2 = body2.m_invInertiaWorld * rel_pos2.cross(lat_vel); btScalar friction_impulse = lat_rel_vel / (body1.m_invMass + body2.m_invMass + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); - btScalar normal_impulse = contactConstraint.m_appliedVelocityImpulse * combinedFriction; + btScalar normal_impulse = contactConstraint.m_appliedImpulse * combinedFriction; GEN_set_min(friction_impulse, normal_impulse); GEN_set_max(friction_impulse, -normal_impulse); @@ -333,39 +433,111 @@ btScalar resolveSingleFrictionCacheFriendly( #endif //NO_FRICTION_TANGENTIALS -btAlignedObjectArray tmpSolverBodyPool; -btAlignedObjectArray tmpSolverConstraintPool; -btAlignedObjectArray tmpSolverFrictionConstraintPool; -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) + + +void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation) { + + btRigidBody* body0=btRigidBody::upcast(colObj0); + btRigidBody* body1=btRigidBody::upcast(colObj1); + + btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = normalAxis; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + solverConstraint.m_originalContactPoint = 0; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedPushImpulse = 0.f; + solverConstraint.m_penetration = 0.f; + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0); + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0); + } + +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (body0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = body0->getInvMass() + normalAxis.dot(vec); + } + if (body1) + { + vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = body1->getInvMass() + normalAxis.dot(vec); + } + + +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + + +} + + + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** /*bodies */,int /*numBodies */,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) +{ + BT_PROFILE("solveGroupCacheFriendlySetup"); (void)stackAlloc; (void)debugDrawer; + if (!(numConstraints + numManifolds)) { // printf("empty\n"); return 0.f; } + btPersistentManifold* manifold = 0; + btCollisionObject* colObj0=0,*colObj1=0; + + //btRigidBody* rb0=0,*rb1=0; + + +#ifdef FORCE_REFESH_CONTACT_MANIFOLDS BEGIN_PROFILE("refreshManifolds"); int i; + + + for (i=0;igetBody0(); - btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); - + manifold = manifoldPtr[i]; + rb1 = (btRigidBody*)manifold->getBody1(); + rb0 = (btRigidBody*)manifold->getBody0(); + manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); } - + END_PROFILE("refreshManifolds"); +#endif //FORCE_REFESH_CONTACT_MANIFOLDS + + - BEGIN_PROFILE("gatherSolverData"); //int sizeofSB = sizeof(btSolverBody); //int sizeofSC = sizeof(btSolverConstraint); @@ -382,10 +554,12 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio //todo: use stack allocator for this temp memory - int minReservation = numManifolds*2; +// int minReservation = numManifolds*2; - tmpSolverBodyPool.reserve(minReservation); + //m_tmpSolverBodyPool.reserve(minReservation); + //don't convert all bodies, only the one we need so solver the constraints +/* { for (int i=0;igetIslandTag() >= 0)) { btAssert(rb->getCompanionId() < 0); - int solverBodyId = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); + int solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); initSolverBody(&solverBody,rb); rb->setCompanionId(solverBodyId); } } } - +*/ - tmpSolverConstraintPool.reserve(minReservation); - tmpSolverFrictionConstraintPool.reserve(minReservation); + //m_tmpSolverConstraintPool.reserve(minReservation); + //m_tmpSolverFrictionConstraintPool.reserve(minReservation); + { int i; for (i=0;igetBody0(); - btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); - + manifold = manifoldPtr[i]; + colObj0 = (btCollisionObject*)manifold->getBody0(); + colObj1 = (btCollisionObject*)manifold->getBody1(); int solverBodyIdA=-1; int solverBodyIdB=-1; @@ -422,61 +596,108 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio - if (rb0->getIslandTag() >= 0) + if (colObj0->getIslandTag() >= 0) { - solverBodyIdA = rb0->getCompanionId(); + if (colObj0->getCompanionId() >= 0) + { + //body has already been converted + solverBodyIdA = colObj0->getCompanionId(); + } else + { + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj0); + colObj0->setCompanionId(solverBodyIdA); + } } else { //create a static body - solverBodyIdA = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb0); + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj0); } - if (rb1->getIslandTag() >= 0) + if (colObj1->getIslandTag() >= 0) { - solverBodyIdB = rb1->getCompanionId(); + if (colObj1->getCompanionId() >= 0) + { + solverBodyIdB = colObj1->getCompanionId(); + } else + { + solverBodyIdB = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj1); + colObj1->setCompanionId(solverBodyIdB); + } } else { //create a static body - solverBodyIdB = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb1); + solverBodyIdB = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj1); } } + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + for (int j=0;jgetNumContacts();j++) { btManifoldPoint& cp = manifold->getContactPoint(j); - - int frictionIndex = tmpSolverConstraintPool.size(); - + if (cp.getDistance() <= btScalar(0.)) { const btVector3& pos1 = cp.getPositionWorldOnA(); const btVector3& pos2 = cp.getPositionWorldOnB(); - btVector3 rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); + rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); - btScalar relaxation = 1.f; + relaxation = 1.f; + btScalar rel_vel; + btVector3 vel; + + int frictionIndex = m_tmpSolverConstraintPool.size(); { - btSolverConstraint& solverConstraint = tmpSolverConstraintPool.expand(); + btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand(); + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; - + solverConstraint.m_originalContactPoint = &cp; + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0 : btVector3(0,0,0); + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1 : btVector3(0,0,0); { - //can be optimized, the cross products are already calculated +#ifdef COMPUTE_IMPULSE_DENOM btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } + if (rb1) + { + vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); solverConstraint.m_jacDiagABInv = denom; } @@ -486,121 +707,115 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB); - btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); + btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; + vel = vel1 - vel2; + rel_vel = cp.m_normalWorldOnB.dot(vel); + solverConstraint.m_penetration = btMin(cp.getDistance()+infoGlobal.m_linearSlop,btScalar(0.)); + //solverConstraint.m_penetration = cp.getDistance(); - solverConstraint.m_penetration = cp.getDistance();///btScalar(infoGlobal.m_numIterations); solverConstraint.m_friction = cp.m_combinedFriction; - btScalar rest = restitutionCurve(rel_vel, cp.m_combinedRestitution); - if (rest <= btScalar(0.)) + solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (solverConstraint.m_restitution <= btScalar(0.)) { - rest = 0.f; + solverConstraint.m_restitution = 0.f; }; + btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; - if (rest > penVel) - { - rest = btScalar(0.); - } - solverConstraint.m_restitution = rest; - solverConstraint.m_penetration *= -(infoGlobal.m_erp/infoGlobal.m_timeStep); - - solverConstraint.m_appliedImpulse = 0.f; - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; - } - - //create 2 '1d axis' constraints for 2 tangential friction directions - - //re-calculate friction direction every frame, todo: check if this is really needed - btVector3 frictionTangential0a, frictionTangential1b; - - btPlaneSpace1(cp.m_normalWorldOnB,frictionTangential0a,frictionTangential1b); - - { - btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = frictionTangential0a; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; + if (solverConstraint.m_restitution > penVel) { - btVector3 ftorqueAxis0 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis0; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis0; + solverConstraint.m_penetration = btScalar(0.); } + + + + ///warm starting (or zero if disabled) + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) { - btVector3 ftorqueAxis0 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis0; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis0; + solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + if (rb0) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); + } else + { + solverConstraint.m_appliedImpulse = 0.f; } - } - - - { - - btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = frictionTangential1b; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; + solverConstraint.m_appliedPushImpulse = 0.f; + + solverConstraint.m_frictionIndex = m_tmpSolverFrictionConstraintPool.size(); + if (!cp.m_lateralFrictionInitialized) { - btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (lat_rel_vel > SIMD_EPSILON)//0.0f) + { + cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize();//?? + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } else + { + //re-calculate friction direction every frame, todo: check if this is really needed + + btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); } + cp.m_lateralFrictionInitialized = true; + + } else { - btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; + if (rb0) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); + } else + { + frictionConstraint1.m_appliedImpulse = 0.f; } } + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; + if (rb0) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse); + } else + { + frictionConstraint2.m_appliedImpulse = 0.f; + } + } + } + } } } } } - END_PROFILE("gatherSolverData"); - - BEGIN_PROFILE("prepareConstraints"); - + btContactSolverInfo info = infoGlobal; { @@ -612,57 +827,60 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio } } - btAlignedObjectArray gOrderTmpConstraintPool; - btAlignedObjectArray gOrderFrictionConstraintPool; + - int numConstraintPool = tmpSolverConstraintPool.size(); - int numFrictionPool = tmpSolverFrictionConstraintPool.size(); + int numConstraintPool = m_tmpSolverConstraintPool.size(); + int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints - gOrderTmpConstraintPool.resize(numConstraintPool); - gOrderFrictionConstraintPool.resize(numFrictionPool); + m_orderTmpConstraintPool.resize(numConstraintPool); + m_orderFrictionConstraintPool.resize(numFrictionPool); { int i; for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); } - constraint->solveConstraint(info.m_timeStep); + constraint->solveConstraint(infoGlobal.m_timeStep); if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); } } { - int numPoolConstraints = tmpSolverConstraintPool.size(); + int numPoolConstraints = m_tmpSolverConstraintPool.size(); for (j=0;jm_appliedImpulse = solveManifold.m_appliedImpulse; + pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; + + //do a callback here? + } - END_PROFILE("solveConstraints"); + if (infoGlobal.m_splitImpulse) + { + for ( i=0;igetBody0(), (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); } + } } - END_PROFILE("solveConstraints"); - - -#ifdef USE_PROFILE - btProfiler::endBlock("solve"); -#endif //USE_PROFILE - @@ -878,13 +1140,14 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop { +#ifdef FORCE_REFESH_CONTACT_MANIFOLDS manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); - +#endif //FORCE_REFESH_CONTACT_MANIFOLDS int numpoints = manifoldPtr->getNumContacts(); gTotalContactPoints += numpoints; - btVector3 color(0,1,0); + for (int i=0;igetContactPoint(i); @@ -925,7 +1188,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol } else { - cpd = new btConstraintPersistentData; + //todo: should this be in a pool? + void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); + cpd = new (mem)btConstraintPersistentData; assert(cpd); totalCpd ++; @@ -972,10 +1237,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol cpd->m_penetration = btScalar(0.); } - btScalar relaxation = info.m_damping; - if (m_solverMode & SOLVER_USE_WARMSTARTING) + if (info.m_solverMode & SOLVER_USE_WARMSTARTING) { cpd->m_appliedImpulse *= relaxation; } else @@ -1060,16 +1324,12 @@ btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRig { - btVector3 color(0,1,0); + { if (cp.getDistance() <= btScalar(0.)) { - if (iter == 0) - { - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } + { @@ -1098,16 +1358,12 @@ btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBo { - btVector3 color(0,1,0); + { if (cp.getDistance() <= btScalar(0.)) { - if (iter == 0) - { - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } + { @@ -1136,7 +1392,7 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b { - btVector3 color(0,1,0); + { if (cp.getDistance() <= btScalar(0.)) @@ -1156,3 +1412,11 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b } return btScalar(0.); } + + +void btSequentialImpulseConstraintSolver::reset() +{ + m_btSeed2 = 0; +} + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 13e70c41be4..7143bc41991 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -19,7 +19,8 @@ subject to the following restrictions: #include "btConstraintSolver.h" class btIDebugDraw; #include "btContactConstraint.h" - +#include "btSolverBody.h" +#include "btSolverConstraint.h" /// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses @@ -29,29 +30,29 @@ class btIDebugDraw; class btSequentialImpulseConstraintSolver : public btConstraintSolver { + btAlignedObjectArray m_tmpSolverBodyPool; + btAlignedObjectArray m_tmpSolverConstraintPool; + btAlignedObjectArray m_tmpSolverFrictionConstraintPool; + btAlignedObjectArray m_orderTmpConstraintPool; + btAlignedObjectArray m_orderFrictionConstraintPool; + + protected: btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer); + void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation); ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; - //choose between several modes, different friction model etc. - int m_solverMode; + ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction unsigned long m_btSeed2; public: - enum eSolverMode - { - SOLVER_RANDMIZE_ORDER = 1, - SOLVER_FRICTION_SEPARATE = 2, - SOLVER_USE_WARMSTARTING = 4, - SOLVER_CACHE_FRIENDLY = 8 - }; - + btSequentialImpulseConstraintSolver(); ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody @@ -68,25 +69,22 @@ public: m_frictionDispatch[type0][type1] = func; } - virtual ~btSequentialImpulseConstraintSolver() {} + virtual ~btSequentialImpulseConstraintSolver(); - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc); + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + + + ///clear internal cached data and reset random seed + virtual void reset(); btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); - void setSolverMode(int mode) - { - m_solverMode = mode; - } - - int getSolverMode() const - { - return m_solverMode; - } - + unsigned long btRand2(); int btRandInt2 (int n); @@ -102,7 +100,9 @@ public: }; - +#ifndef BT_PREFER_SIMD +typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered; +#endif #endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp new file mode 100644 index 00000000000..4128f504bf1 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -0,0 +1,415 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 +*/ + +//----------------------------------------------------------------------------- + +#include "btSliderConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + +//----------------------------------------------------------------------------- + +void btSliderConstraint::initParams() +{ + m_lowerLinLimit = btScalar(1.0); + m_upperLinLimit = btScalar(-1.0); + m_lowerAngLimit = btScalar(0.); + m_upperAngLimit = btScalar(0.); + m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirLin = btScalar(0.); + m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirAng = btScalar(0.); + m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; + + m_poweredLinMotor = false; + m_targetLinMotorVelocity = btScalar(0.); + m_maxLinMotorForce = btScalar(0.); + m_accumulatedLinMotorImpulse = btScalar(0.0); + + m_poweredAngMotor = false; + m_targetAngMotorVelocity = btScalar(0.); + m_maxAngMotorForce = btScalar(0.); + m_accumulatedAngMotorImpulse = btScalar(0.0); + +} // btSliderConstraint::initParams() + +//----------------------------------------------------------------------------- + +btSliderConstraint::btSliderConstraint() + :btTypedConstraint(SLIDER_CONSTRAINT_TYPE), + m_useLinearReferenceFrameA(true) +{ + initParams(); +} // btSliderConstraint::btSliderConstraint() + +//----------------------------------------------------------------------------- + +btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB) + , m_frameInA(frameInA) + , m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + initParams(); +} // btSliderConstraint::btSliderConstraint() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::buildJacobian() +{ + if(m_useLinearReferenceFrameA) + { + buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB); + } + else + { + buildJacobianInt(m_rbB, m_rbA, m_frameInB, m_frameInA); + } +} // btSliderConstraint::buildJacobian() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) +{ + //calculate transforms + m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA; + m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB; + m_realPivotAInW = m_calculatedTransformA.getOrigin(); + m_realPivotBInW = m_calculatedTransformB.getOrigin(); + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + m_delta = m_realPivotBInW - m_realPivotAInW; + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + m_relPosA = m_projPivotInW - rbA.getCenterOfMassPosition(); + m_relPosB = m_realPivotBInW - rbB.getCenterOfMassPosition(); + btVector3 normalWorld; + int i; + //linear part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + new (&m_jacLin[i]) btJacobianEntry( + rbA.getCenterOfMassTransform().getBasis().transpose(), + rbB.getCenterOfMassTransform().getBasis().transpose(), + m_relPosA, + m_relPosB, + normalWorld, + rbA.getInvInertiaDiagLocal(), + rbA.getInvMass(), + rbB.getInvInertiaDiagLocal(), + rbB.getInvMass() + ); + m_jacLinDiagABInv[i] = btScalar(1.) / m_jacLin[i].getDiagonal(); + m_depth[i] = m_delta.dot(normalWorld); + } + testLinLimits(); + // angular part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + new (&m_jacAng[i]) btJacobianEntry( + normalWorld, + rbA.getCenterOfMassTransform().getBasis().transpose(), + rbB.getCenterOfMassTransform().getBasis().transpose(), + rbA.getInvInertiaDiagLocal(), + rbB.getInvInertiaDiagLocal() + ); + } + testAngLimits(); + btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0); + m_kAngle = btScalar(1.0 )/ (rbA.computeAngularImpulseDenominator(axisA) + rbB.computeAngularImpulseDenominator(axisA)); + // clear accumulator for motors + m_accumulatedLinMotorImpulse = btScalar(0.0); + m_accumulatedAngMotorImpulse = btScalar(0.0); +} // btSliderConstraint::buildJacobianInt() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::solveConstraint(btScalar timeStep) +{ + m_timeStep = timeStep; + if(m_useLinearReferenceFrameA) + { + solveConstraintInt(m_rbA, m_rbB); + } + else + { + solveConstraintInt(m_rbB, m_rbA); + } +} // btSliderConstraint::solveConstraint() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) +{ + int i; + // linear + btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA); + btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB); + btVector3 vel = velA - velB; + for(i = 0; i < 3; i++) + { + const btVector3& normal = m_jacLin[i].m_linearJointAxis; + btScalar rel_vel = normal.dot(vel); + // calculate positional error + btScalar depth = m_depth[i]; + // get parameters + btScalar softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin); + btScalar restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin); + btScalar damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin); + // calcutate and apply impulse + btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i]; + btVector3 impulse_vector = normal * normalImpulse; + rbA.applyImpulse( impulse_vector, m_relPosA); + rbB.applyImpulse(-impulse_vector, m_relPosB); + if(m_poweredLinMotor && (!i)) + { // apply linear motor + if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce) + { + btScalar desiredMotorVel = m_targetLinMotorVelocity; + btScalar motor_relvel = desiredMotorVel + rel_vel; + normalImpulse = -motor_relvel * m_jacLinDiagABInv[i]; + // clamp accumulated impulse + btScalar new_acc = m_accumulatedLinMotorImpulse + btFabs(normalImpulse); + if(new_acc > m_maxLinMotorForce) + { + new_acc = m_maxLinMotorForce; + } + btScalar del = new_acc - m_accumulatedLinMotorImpulse; + if(normalImpulse < btScalar(0.0)) + { + normalImpulse = -del; + } + else + { + normalImpulse = del; + } + m_accumulatedLinMotorImpulse = new_acc; + // apply clamped impulse + impulse_vector = normal * normalImpulse; + rbA.applyImpulse( impulse_vector, m_relPosA); + rbB.applyImpulse(-impulse_vector, m_relPosB); + } + } + } + // angular + // get axes in world space + btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0); + btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0); + + const btVector3& angVelA = rbA.getAngularVelocity(); + const btVector3& angVelB = rbB.getAngularVelocity(); + + btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); + btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB); + + btVector3 angAorthog = angVelA - angVelAroundAxisA; + btVector3 angBorthog = angVelB - angVelAroundAxisB; + btVector3 velrelOrthog = angAorthog-angBorthog; + //solve orthogonal angular velocity correction + btScalar len = velrelOrthog.length(); + if (len > btScalar(0.00001)) + { + btVector3 normal = velrelOrthog.normalized(); + btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal); + velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; + } + //solve angular positional correction + btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep); + btScalar len2 = angularError.length(); + if (len2>btScalar(0.00001)) + { + btVector3 normal2 = angularError.normalized(); + btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2); + angularError *= (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; + } + // apply impulse + rbA.applyTorqueImpulse(-velrelOrthog+angularError); + rbB.applyTorqueImpulse(velrelOrthog-angularError); + btScalar impulseMag; + //solve angular limits + if(m_solveAngLim) + { + impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / m_timeStep; + impulseMag *= m_kAngle * m_softnessLimAng; + } + else + { + impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / m_timeStep; + impulseMag *= m_kAngle * m_softnessDirAng; + } + btVector3 impulse = axisA * impulseMag; + rbA.applyTorqueImpulse(impulse); + rbB.applyTorqueImpulse(-impulse); + //apply angular motor + if(m_poweredAngMotor) + { + if(m_accumulatedAngMotorImpulse < m_maxAngMotorForce) + { + btVector3 velrel = angVelAroundAxisA - angVelAroundAxisB; + btScalar projRelVel = velrel.dot(axisA); + + btScalar desiredMotorVel = m_targetAngMotorVelocity; + btScalar motor_relvel = desiredMotorVel - projRelVel; + + btScalar angImpulse = m_kAngle * motor_relvel; + // clamp accumulated impulse + btScalar new_acc = m_accumulatedAngMotorImpulse + btFabs(angImpulse); + if(new_acc > m_maxAngMotorForce) + { + new_acc = m_maxAngMotorForce; + } + btScalar del = new_acc - m_accumulatedAngMotorImpulse; + if(angImpulse < btScalar(0.0)) + { + angImpulse = -del; + } + else + { + angImpulse = del; + } + m_accumulatedAngMotorImpulse = new_acc; + // apply clamped impulse + btVector3 motorImp = angImpulse * axisA; + m_rbA.applyTorqueImpulse(motorImp); + m_rbB.applyTorqueImpulse(-motorImp); + } + } +} // btSliderConstraint::solveConstraint() + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +void btSliderConstraint::calculateTransforms(void){ + if(m_useLinearReferenceFrameA) + { + m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + } + else + { + m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB; + m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA; + } + m_realPivotAInW = m_calculatedTransformA.getOrigin(); + m_realPivotBInW = m_calculatedTransformB.getOrigin(); + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + m_delta = m_realPivotBInW - m_realPivotAInW; + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + btVector3 normalWorld; + int i; + //linear part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + m_depth[i] = m_delta.dot(normalWorld); + } +} // btSliderConstraint::calculateTransforms() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::testLinLimits(void) +{ + m_solveLinLim = false; + m_linPos = m_depth[0]; + if(m_lowerLinLimit <= m_upperLinLimit) + { + if(m_depth[0] > m_upperLinLimit) + { + m_depth[0] -= m_upperLinLimit; + m_solveLinLim = true; + } + else if(m_depth[0] < m_lowerLinLimit) + { + m_depth[0] -= m_lowerLinLimit; + m_solveLinLim = true; + } + else + { + m_depth[0] = btScalar(0.); + } + } + else + { + m_depth[0] = btScalar(0.); + } +} // btSliderConstraint::testLinLimits() + +//----------------------------------------------------------------------------- + + +void btSliderConstraint::testAngLimits(void) +{ + m_angDepth = btScalar(0.); + m_solveAngLim = false; + if(m_lowerAngLimit <= m_upperAngLimit) + { + const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); + const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); + const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); + btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); + if(rot < m_lowerAngLimit) + { + m_angDepth = rot - m_lowerAngLimit; + m_solveAngLim = true; + } + else if(rot > m_upperAngLimit) + { + m_angDepth = rot - m_upperAngLimit; + m_solveAngLim = true; + } + } +} // btSliderConstraint::testAngLimits() + + +//----------------------------------------------------------------------------- + + + +btVector3 btSliderConstraint::getAncorInA(void) +{ + btVector3 ancorInA; + ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis; + ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA; + return ancorInA; +} // btSliderConstraint::getAncorInA() + +//----------------------------------------------------------------------------- + +btVector3 btSliderConstraint::getAncorInB(void) +{ + btVector3 ancorInB; + ancorInB = m_frameInB.getOrigin(); + return ancorInB; +} // btSliderConstraint::getAncorInB(); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h new file mode 100644 index 00000000000..580dfa1178d --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -0,0 +1,218 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +TODO: + - add clamping od accumulated impulse to improve stability + - add conversion for ODE constraint solver +*/ + +#ifndef SLIDER_CONSTRAINT_H +#define SLIDER_CONSTRAINT_H + +//----------------------------------------------------------------------------- + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +//----------------------------------------------------------------------------- + +class btRigidBody; + +//----------------------------------------------------------------------------- + +#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) + +//----------------------------------------------------------------------------- + +class btSliderConstraint : public btTypedConstraint +{ +protected: + btTransform m_frameInA; + btTransform m_frameInB; + // use frameA fo define limits, if true + bool m_useLinearReferenceFrameA; + // linear limits + btScalar m_lowerLinLimit; + btScalar m_upperLinLimit; + // angular limits + btScalar m_lowerAngLimit; + btScalar m_upperAngLimit; + // softness, restitution and damping for different cases + // DirLin - moving inside linear limits + // LimLin - hitting linear limit + // DirAng - moving inside angular limits + // LimAng - hitting angular limit + // OrthoLin, OrthoAng - against constraint axis + btScalar m_softnessDirLin; + btScalar m_restitutionDirLin; + btScalar m_dampingDirLin; + btScalar m_softnessDirAng; + btScalar m_restitutionDirAng; + btScalar m_dampingDirAng; + btScalar m_softnessLimLin; + btScalar m_restitutionLimLin; + btScalar m_dampingLimLin; + btScalar m_softnessLimAng; + btScalar m_restitutionLimAng; + btScalar m_dampingLimAng; + btScalar m_softnessOrthoLin; + btScalar m_restitutionOrthoLin; + btScalar m_dampingOrthoLin; + btScalar m_softnessOrthoAng; + btScalar m_restitutionOrthoAng; + btScalar m_dampingOrthoAng; + + // for interlal use + bool m_solveLinLim; + bool m_solveAngLim; + + btJacobianEntry m_jacLin[3]; + btScalar m_jacLinDiagABInv[3]; + + btJacobianEntry m_jacAng[3]; + + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + + btVector3 m_sliderAxis; + btVector3 m_realPivotAInW; + btVector3 m_realPivotBInW; + btVector3 m_projPivotInW; + btVector3 m_delta; + btVector3 m_depth; + btVector3 m_relPosA; + btVector3 m_relPosB; + + btScalar m_linPos; + + btScalar m_angDepth; + btScalar m_kAngle; + + bool m_poweredLinMotor; + btScalar m_targetLinMotorVelocity; + btScalar m_maxLinMotorForce; + btScalar m_accumulatedLinMotorImpulse; + + bool m_poweredAngMotor; + btScalar m_targetAngMotorVelocity; + btScalar m_maxAngMotorForce; + btScalar m_accumulatedAngMotorImpulse; + + //------------------------ + void initParams(); +public: + // constructors + btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btSliderConstraint(); + // overrides + virtual void buildJacobian(); + virtual void solveConstraint(btScalar timeStep); + // access + const btRigidBody& getRigidBodyA() const { return m_rbA; } + const btRigidBody& getRigidBodyB() const { return m_rbB; } + const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } + const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } + const btTransform & getFrameOffsetA() const { return m_frameInA; } + const btTransform & getFrameOffsetB() const { return m_frameInB; } + btTransform & getFrameOffsetA() { return m_frameInA; } + btTransform & getFrameOffsetB() { return m_frameInB; } + btScalar getLowerLinLimit() { return m_lowerLinLimit; } + void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } + btScalar getUpperLinLimit() { return m_upperLinLimit; } + void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } + btScalar getLowerAngLimit() { return m_lowerAngLimit; } + void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; } + btScalar getUpperAngLimit() { return m_upperAngLimit; } + void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; } + bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; } + btScalar getSoftnessDirLin() { return m_softnessDirLin; } + btScalar getRestitutionDirLin() { return m_restitutionDirLin; } + btScalar getDampingDirLin() { return m_dampingDirLin ; } + btScalar getSoftnessDirAng() { return m_softnessDirAng; } + btScalar getRestitutionDirAng() { return m_restitutionDirAng; } + btScalar getDampingDirAng() { return m_dampingDirAng; } + btScalar getSoftnessLimLin() { return m_softnessLimLin; } + btScalar getRestitutionLimLin() { return m_restitutionLimLin; } + btScalar getDampingLimLin() { return m_dampingLimLin; } + btScalar getSoftnessLimAng() { return m_softnessLimAng; } + btScalar getRestitutionLimAng() { return m_restitutionLimAng; } + btScalar getDampingLimAng() { return m_dampingLimAng; } + btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; } + btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; } + btScalar getDampingOrthoLin() { return m_dampingOrthoLin; } + btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; } + btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; } + btScalar getDampingOrthoAng() { return m_dampingOrthoAng; } + void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; } + void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } + void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; } + void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; } + void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } + void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; } + void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; } + void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } + void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; } + void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; } + void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } + void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; } + void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } + void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } + void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } + void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } + void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } + void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } + void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } + bool getPoweredLinMotor() { return m_poweredLinMotor; } + void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } + btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } + void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } + btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; } + void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } + bool getPoweredAngMotor() { return m_poweredAngMotor; } + void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } + btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } + void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } + btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } + btScalar getLinearPos() { return m_linPos; } + + // access for ODE solver + bool getSolveLinLimit() { return m_solveLinLim; } + btScalar getLinDepth() { return m_depth[0]; } + bool getSolveAngLimit() { return m_solveAngLim; } + btScalar getAngDepth() { return m_angDepth; } + // internal + void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB); + void solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB); + // shared code used by ODE solver + void calculateTransforms(void); + void testLinLimits(void); + void testAngLimits(void); + // access for PE Solver + btVector3 getAncorInA(void); + btVector3 getAncorInB(void); +}; + +//----------------------------------------------------------------------------- + +#endif //SLIDER_CONSTRAINT_H + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h index e7d26645c6a..057d3fac827 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SOLVE_2LINEAR_CONSTRAINT_H #define SOLVE_2LINEAR_CONSTRAINT_H -#include "../../LinearMath/btMatrix3x3.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h index 0ab536f42b3..b3f0c9d7444 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -19,38 +19,78 @@ subject to the following restrictions: class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btTransformUtil.h" - - +///btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. ATTRIBUTE_ALIGNED16 (struct) btSolverBody { - btVector3 m_centerOfMassPosition; - btVector3 m_linearVelocity; + BT_DECLARE_ALIGNED_ALLOCATOR(); + btVector3 m_angularVelocity; - btRigidBody* m_originalBody; + float m_angularFactor; float m_invMass; float m_friction; - float m_angularFactor; - - inline void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const + btRigidBody* m_originalBody; + btVector3 m_linearVelocity; + btVector3 m_centerOfMassPosition; + + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + + + SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const { velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { - m_linearVelocity += linearComponent*impulseMagnitude; - m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + if (m_invMass) + { + m_linearVelocity += linearComponent*impulseMagnitude; + m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + if (m_invMass) + { + m_pushVelocity += linearComponent*impulseMagnitude; + m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } } + void writebackVelocity() { if (m_invMass) { m_originalBody->setLinearVelocity(m_linearVelocity); m_originalBody->setAngularVelocity(m_angularVelocity); + + //m_originalBody->setCompanionId(-1); + } + } + + + void writebackVelocity(btScalar timeStep) + { + if (m_invMass) + { + m_originalBody->setLinearVelocity(m_linearVelocity); + m_originalBody->setAngularVelocity(m_angularVelocity); + + //correct the position/orientation based on push/turn recovery + btTransform newTransform; + btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform); + m_originalBody->setWorldTransform(newTransform); + + //m_originalBody->setCompanionId(-1); } } @@ -69,3 +109,5 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody }; #endif //BT_SOLVER_BODY_H + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h index f1f40ffdf19..2c71360c5b9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -1,5 +1,3 @@ - - /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -27,24 +25,34 @@ class btRigidBody; ///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint { + BT_DECLARE_ALIGNED_ALLOCATOR(); + btVector3 m_relpos1CrossNormal; - btVector3 m_relpos2CrossNormal; btVector3 m_contactNormal; + + btVector3 m_relpos2CrossNormal; btVector3 m_angularComponentA; + btVector3 m_angularComponentB; - btScalar m_appliedVelocityImpulse; + mutable btScalar m_appliedPushImpulse; + + mutable btScalar m_appliedImpulse; int m_solverBodyIdA; int m_solverBodyIdB; + btScalar m_friction; btScalar m_restitution; btScalar m_jacDiagABInv; btScalar m_penetration; - btScalar m_appliedImpulse; + + int m_constraintType; int m_frictionIndex; - int m_unusedPadding[2]; + void* m_originalContactPoint; + int m_unusedPadding[1]; + enum btSolverConstraintType { @@ -61,3 +69,4 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint #endif //BT_SOLVER_CONSTRAINT_H + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp index a15b3e026cd..6e8b552dbbc 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -19,18 +19,20 @@ subject to the following restrictions: static btRigidBody s_fixed(0, 0,0); -btTypedConstraint::btTypedConstraint() -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(s_fixed), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); } -btTypedConstraint::btTypedConstraint(btRigidBody& rbA) -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(rbA), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) @@ -40,9 +42,10 @@ m_appliedImpulse(btScalar(0.)) } -btTypedConstraint::btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB) -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(rbA), m_rbB(rbB), m_appliedImpulse(btScalar(0.)) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index dfee6e80d0e..c50ec6ec579 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -17,7 +17,17 @@ subject to the following restrictions: #define TYPED_CONSTRAINT_H class btRigidBody; -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" + +enum btTypedConstraintType +{ + POINT2POINT_CONSTRAINT_TYPE, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + VEHICLE_CONSTRAINT_TYPE, + SLIDER_CONSTRAINT_TYPE +}; ///TypedConstraint is the baseclass for Bullet constraints and vehicles class btTypedConstraint @@ -25,6 +35,8 @@ class btTypedConstraint int m_userConstraintType; int m_userConstraintId; + btTypedConstraintType m_constraintType; + btTypedConstraint& operator=(btTypedConstraint& other) { btAssert(0); @@ -40,11 +52,11 @@ protected: public: - btTypedConstraint(); + btTypedConstraint(btTypedConstraintType type); virtual ~btTypedConstraint() {}; - btTypedConstraint(btRigidBody& rbA); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); - btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); virtual void buildJacobian() = 0; @@ -59,7 +71,7 @@ public: return m_rbB; } - btRigidBody& getRigidBodyA() + btRigidBody& getRigidBodyA() { return m_rbA; } @@ -83,14 +95,26 @@ public: m_userConstraintId = uid; } - int getUserConstraintId() + int getUserConstraintId() const { return m_userConstraintId; } - btScalar getAppliedImpulse() + + int getUid() const + { + return m_userConstraintId; + } + + btScalar getAppliedImpulse() const { return m_appliedImpulse; } + + btTypedConstraintType getConstraintType () const + { + return m_constraintType; + } + }; #endif //TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp index 248c582dcd8..c2fd71d67fe 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -25,6 +25,7 @@ subject to the following restrictions: #include "LinearMath/btAlignedAllocator.h" + #include "LinearMath/btVector3.h" #include "LinearMath/btScalar.h" #include "LinearMath/btMatrix3x3.h" @@ -39,18 +40,296 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" - #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "LinearMath/btStackAlloc.h" -extern "C" +/* + Create and Delete a Physics SDK +*/ + +struct btPhysicsSdk +{ + +// btDispatcher* m_dispatcher; +// btOverlappingPairCache* m_pairCache; +// btConstraintSolver* m_constraintSolver + + btVector3 m_worldAabbMin; + btVector3 m_worldAabbMax; + + + //todo: version, hardware/optimization settings etc? + btPhysicsSdk() + :m_worldAabbMin(-1000,-1000,-1000), + m_worldAabbMax(1000,1000,1000) + { + + } + + +}; + +plPhysicsSdkHandle plNewBulletSdk() +{ + void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); + return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; +} + +void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) +{ + btPhysicsSdk* phys = reinterpret_cast(physicsSdk); + btAlignedFree(phys); +} + + +/* Dynamics World */ +plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle) +{ + btPhysicsSdk* physicsSdk = reinterpret_cast(physicsSdkHandle); + void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16); + btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration(); + mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16); + btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration); + mem = btAlignedAlloc(sizeof(btAxisSweep3),16); + btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); + mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver(); + + mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16); + return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration); +} +void plDeleteDynamicsWorld(plDynamicsWorldHandle world) +{ + //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAlignedFree(dynamicsWorld); +} + +void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + dynamicsWorld->stepSimulation(timeStep); +} + +void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->addRigidBody(body); +} + +void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->removeRigidBody(body); +} + +/* Rigid Body */ + +plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) +{ + btTransform trans; + trans.setIdentity(); + btVector3 localInertia(0,0,0); + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + void* mem = btAlignedAlloc(sizeof(btRigidBody),16); + btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia); + btRigidBody* body = new (mem)btRigidBody(rbci); + body->setWorldTransform(trans); + body->setUserPointer(user_data); + return (plRigidBodyHandle) body; +} + +void plDeleteRigidBody(plRigidBodyHandle cbody) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); + assert(body); + btAlignedFree( body); +} + + +/* Collision Shape definition */ + +plCollisionShapeHandle plNewSphereShape(plReal radius) +{ + void* mem = btAlignedAlloc(sizeof(btSphereShape),16); + return (plCollisionShapeHandle) new (mem)btSphereShape(radius); + +} + +plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) +{ + void* mem = btAlignedAlloc(sizeof(btBoxShape),16); + return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); +} + +plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) +{ + //capsule is convex hull of 2 spheres, so use btMultiSphereShape + btVector3 inertiaHalfExtents(radius,height,radius); + const int numSpheres = 2; + btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; + btScalar radi[numSpheres] = {radius,radius}; + void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16); + return (plCollisionShapeHandle) new (mem)btMultiSphereShape(inertiaHalfExtents,positions,radi,numSpheres); +} +plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btConeShape),16); + return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); +} + +plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); + return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); +} + +/* Convex Meshes */ +plCollisionShapeHandle plNewConvexHullShape() +{ + void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); + return (plCollisionShapeHandle) new (mem)btConvexHullShape(); +} + + +/* Concave static triangle meshes */ +plMeshInterfaceHandle plNewMeshInterface() +{ + return 0; +} + +plCollisionShapeHandle plNewCompoundShape() +{ + void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); + return (plCollisionShapeHandle) new (mem)btCompoundShape(); +} + +void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn) +{ + btCollisionShape* colShape = reinterpret_cast(compoundShapeHandle); + btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE); + btCompoundShape* compoundShape = reinterpret_cast(colShape); + btCollisionShape* childShape = reinterpret_cast(childShapeHandle); + btTransform localTrans; + localTrans.setIdentity(); + localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2])); + localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3])); + compoundShape->addChildShape(localTrans,childShape); +} + +void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient) +{ + btQuaternion orn; + orn.setEuler(yaw,pitch,roll); + orient[0] = orn.getX(); + orient[1] = orn.getY(); + orient[2] = orn.getZ(); + orient[3] = orn.getW(); + +} + + +// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); +// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + +void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) +{ + btCollisionShape* colShape = reinterpret_cast( cshape); + (void)colShape; + btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); + btConvexHullShape* convexHullShape = reinterpret_cast( cshape); + convexHullShape->addPoint(btPoint3(x,y,z)); + +} + +void plDeleteShape(plCollisionShapeHandle cshape) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btAlignedFree(shape); +} +void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); + shape->setLocalScaling(scaling); +} + + + +void plSetPosition(plRigidBodyHandle object, const plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btVector3 pos(position[0],position[1],position[2]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setOrigin(pos); + body->setWorldTransform(worldTrans); +} + +void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setRotation(orn); + body->setWorldTransform(worldTrans); +} + +void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + body->getWorldTransform().getOpenGLMatrix(matrix); + +} + +void plGetPosition(plRigidBodyHandle object,plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btVector3& pos = body->getWorldTransform().getOrigin(); + position[0] = pos.getX(); + position[1] = pos.getY(); + position[2] = pos.getZ(); +} + +void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btQuaternion& orn = body->getWorldTransform().getRotation(); + orientation[0] = orn.getX(); + orientation[1] = orn.getY(); + orientation[2] = orn.getZ(); + orientation[3] = orn.getW(); +} + + + +//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]) { btVector3 vp(p1[0], p1[1], p1[2]); @@ -118,3 +397,4 @@ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float } return -1.0f; } + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp new file mode 100644 index 00000000000..19443adc723 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp @@ -0,0 +1,193 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btContinuousDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + + + +#include + +btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ +} + +btContinuousDynamicsWorld::~btContinuousDynamicsWorld() +{ +} + + +void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) +{ + + startProfiling(timeStep); + + + ///update aabbs information + updateAabbs(); + //static int frame=0; +// printf("frame %d\n",frame++); + + ///apply gravity, predict motion + predictUnconstraintMotion(timeStep); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_debugDraw = getDebugDrawer(); + + ///perform collision detection + performDiscreteCollisionDetection(); + + calculateSimulationIslands(); + + + getSolverInfo().m_timeStep = timeStep; + + + + ///solve contact and other joint constraints + solveConstraints(getSolverInfo()); + + ///CallbackTriggers(); + calculateTimeOfImpacts(timeStep); + + btScalar toi = dispatchInfo.m_timeOfImpact; +// if (toi < 1.f) +// printf("toi = %f\n",toi); + if (toi < 0.f) + printf("toi = %f\n",toi); + + + ///integrate transforms + integrateTransforms(timeStep * toi); + + ///update vehicle simulation + updateVehicles(timeStep); + + + updateActivationState( timeStep ); + + if(0 != m_internalTickCallback) { + (*m_internalTickCallback)(this, timeStep); + } +} + +void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) +{ + ///these should be 'temporal' aabbs! + updateTemporalAabbs(timeStep); + + ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually. + ///so we handle the case moving versus static properly, and we cheat for moving versus moving + btScalar toi = 1.f; + + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_timeOfImpact = 1.f; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS; + + ///calculate time of impact for overlapping pairs + + + btDispatcher* dispatcher = getDispatcher(); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + + toi = dispatchInfo.m_timeOfImpact; + + dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; + +} + +void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) +{ + + btVector3 temporalAabbMin,temporalAabbMax; + + for ( int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax); + const btVector3& linvel = body->getLinearVelocity(); + + //make the AABB temporal + btScalar temporalAabbMaxx = temporalAabbMax.getX(); + btScalar temporalAabbMaxy = temporalAabbMax.getY(); + btScalar temporalAabbMaxz = temporalAabbMax.getZ(); + btScalar temporalAabbMinx = temporalAabbMin.getX(); + btScalar temporalAabbMiny = temporalAabbMin.getY(); + btScalar temporalAabbMinz = temporalAabbMin.getZ(); + + // add linear motion + btVector3 linMotion = linvel*timeStep; + + if (linMotion.x() > 0.f) + temporalAabbMaxx += linMotion.x(); + else + temporalAabbMinx += linMotion.x(); + if (linMotion.y() > 0.f) + temporalAabbMaxy += linMotion.y(); + else + temporalAabbMiny += linMotion.y(); + if (linMotion.z() > 0.f) + temporalAabbMaxz += linMotion.z(); + else + temporalAabbMinz += linMotion.z(); + + //add conservative angular motion + btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep; + btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); + temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); + temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); + + temporalAabbMin -= angularMotion3d; + temporalAabbMax += angularMotion3d; + + m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1); + } + } + + //update aabb (of all moved objects) + + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); + + + +} + + + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h new file mode 100644 index 00000000000..61c8dea03eb --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H +#define BT_CONTINUOUS_DYNAMICS_WORLD_H + +#include "btDiscreteDynamicsWorld.h" + +///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld. +///This copes with fast moving objects that otherwise would tunnel/miss collisions. +///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead. +class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld +{ + + void updateTemporalAabbs(btScalar timeStep); + + public: + + btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + virtual ~btContinuousDynamicsWorld(); + + ///time stepping with calculation of time of impact for selected fast moving objects + virtual void internalSingleStepSimulation( btScalar timeStep); + + virtual void calculateTimeOfImpacts(btScalar timeStep); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_CONTINUOUS_DYNAMICS_WORLD; + } + +}; + +#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 1017c8af6ea..e46c4e6136b 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -21,7 +21,8 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" -#include +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btQuickprof.h" //rigidbody & constraints #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -41,6 +42,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btSphereShape.h" #include "BulletCollision/CollisionShapes/btTriangleCallback.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" #include "LinearMath/btIDebugDraw.h" @@ -57,17 +59,29 @@ subject to the following restrictions: -btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) -:btDynamicsWorld(dispatcher,pairCache), -m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver), -m_debugDrawer(0), +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_constraintSolver(constraintSolver), m_gravity(0,-10,0), m_localTime(btScalar(1.)/btScalar(60.)), m_profileTimings(0) { - m_islandManager = new btSimulationIslandManager(); + if (!m_constraintSolver) + { + void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; + m_ownsConstraintSolver = true; + } else + { + m_ownsConstraintSolver = false; + } + + { + void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); + m_islandManager = new (mem) btSimulationIslandManager(); + } + m_ownsIslandManager = true; - m_ownsConstraintSolver = (constraintSolver==0); } @@ -75,9 +89,16 @@ btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() { //only delete it when we created it if (m_ownsIslandManager) - delete m_islandManager; + { + m_islandManager->~btSimulationIslandManager(); + btAlignedFree( m_islandManager); + } if (m_ownsConstraintSolver) - delete m_constraintSolver; + { + + m_constraintSolver->~btConstraintSolver(); + btAlignedFree(m_constraintSolver); + } } void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) @@ -102,14 +123,35 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) } } -void btDiscreteDynamicsWorld::synchronizeMotionStates() +void btDiscreteDynamicsWorld::debugDrawWorld() { - //debug vehicle wheels - - + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) { + int numManifolds = getDispatcher()->getNumManifolds(); + btVector3 color(0,0,0); + for (int i=0;igetManifoldByIndexInternal(i); + //btCollisionObject* obA = static_cast(contactManifold->getBody0()); + //btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } + } + } + + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)) + { + int i; + //todo: iterate over awake simulation islands! - for ( int i=0;igetDebugMode() & btIDebugDraw::DBG_DrawWireframe) @@ -135,26 +177,17 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); } - btRigidBody* body = btRigidBody::upcast(colObj); - if (body && body->getMotionState() && !body->isStaticOrKinematicObject()) + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) { - //we need to call the update at least once, even for sleeping objects - //otherwise the 'graphics' transform never updates properly - //so todo: add 'dirty' flag - //if (body->getActivationState() != ISLAND_SLEEPING) - { - btTransform interpolatedTransform; - btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime,interpolatedTransform); - body->getMotionState()->setWorldTransform(interpolatedTransform); - } + btPoint3 minAabb,maxAabb; + btVector3 colorvec(1,0,0); + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); } - } - } - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) - { - for ( int i=0;im_vehicles.size();i++) + } + + for ( i=0;im_vehicles.size();i++) { for (int v=0;vgetNumWheels();v++) { @@ -166,10 +199,7 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() { wheelColor.setValue(255,0,255); } - - //synchronize the wheels with the (interpolated) chassis worldtransform - m_vehicles[i]->updateWheelTransform(v,true); - + btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); btVector3 axle = btVector3( @@ -186,12 +216,87 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() } } } +} + +void btDiscreteDynamicsWorld::clearForces() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } + } +} + +///apply gravity, call this once per timestep +void btDiscreteDynamicsWorld::applyGravity() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iisActive()) + { + body->applyGravity(); + } + } +} + + + +void btDiscreteDynamicsWorld::synchronizeMotionStates() +{ + { + //todo: iterate over awake simulation islands! + for ( int i=0;igetMotionState() && !body->isStaticOrKinematicObject()) + { + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + //so todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } + } + } + } + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) + { + for ( int i=0;im_vehicles.size();i++) + { + for (int v=0;vgetNumWheels();v++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicles[i]->updateWheelTransform(v,true); + } + } + } } int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) { + startProfiling(timeStep); + + BT_PROFILE("stepSimulation"); + int numSimulationSubSteps = 0; if (maxSubSteps) @@ -229,6 +334,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, saveKinematicState(fixedTimeStep); + applyGravity(); + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; @@ -242,16 +349,19 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, synchronizeMotionStates(); + clearForces(); + +#ifndef BT_NO_PROFILE + CProfileManager::Increment_Frame_Counter(); +#endif //BT_NO_PROFILE + return numSimulationSubSteps; } void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) { - startProfiling(timeStep); - - ///update aabbs information - updateAabbs(); + BT_PROFILE("internalSingleStepSimulation"); ///apply gravity, predict motion predictUnconstraintMotion(timeStep); @@ -286,8 +396,9 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) updateActivationState( timeStep ); - - + if(0 != m_internalTickCallback) { + (*m_internalTickCallback)(this, timeStep); + } } void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) @@ -304,6 +415,11 @@ void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) } } +btVector3 btDiscreteDynamicsWorld::getGravity () const +{ + return m_gravity; +} + void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) { @@ -343,19 +459,18 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) { - BEGIN_PROFILE("updateVehicles"); - + BT_PROFILE("updateVehicles"); + for ( int i=0;iupdateVehicle( timeStep); } - END_PROFILE("updateVehicles"); } void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) { - BEGIN_PROFILE("updateActivationState"); + BT_PROFILE("updateActivationState"); for ( int i=0;igetActivationState() == ACTIVE_TAG) body->setActivationState( WANTS_DEACTIVATION ); + if (body->getActivationState() == ISLAND_SLEEPING) + { + body->setAngularVelocity(btVector3(0,0,0)); + body->setLinearVelocity(btVector3(0,0,0)); + } + } } else { @@ -382,7 +503,6 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) } } } - END_PROFILE("updateActivationState"); } void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) @@ -412,7 +532,7 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) m_vehicles.remove(vehicle); } -inline int btGetConstraintIslandId(const btTypedConstraint* lhs) +SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) { int islandId; @@ -442,6 +562,7 @@ class btSortConstraintOnIslandPredicate void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { + BT_PROFILE("solveConstraints"); struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback { @@ -452,7 +573,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) int m_numConstraints; btIDebugDraw* m_debugDrawer; btStackAlloc* m_stackAlloc; - + btDispatcher* m_dispatcher; InplaceSolverIslandCallback( btContactSolverInfo& solverInfo, @@ -460,13 +581,15 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer, - btStackAlloc* stackAlloc) + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) :m_solverInfo(solverInfo), m_solver(solver), m_sortedConstraints(sortedConstraints), m_numConstraints(numConstraints), m_debugDrawer(debugDrawer), - m_stackAlloc(stackAlloc) + m_stackAlloc(stackAlloc), + m_dispatcher(dispatcher) { } @@ -479,30 +602,42 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) } virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) { - //also add all non-contact constraints/joints for this island - btTypedConstraint** startConstraint = 0; - int numCurConstraints = 0; - int i; - - //find the first constraint for this island - for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } else { - if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId) + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc); + ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive + if (numManifolds + numCurConstraints) + { + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + + } } }; @@ -520,18 +655,18 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) - sortedConstraints.heapSort(btSortConstraintOnIslandPredicate()); + sortedConstraints.quickSort(btSortConstraintOnIslandPredicate()); btTypedConstraint** constraintsPtr = getNumConstraints() ? &sortedConstraints[0] : 0; - InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc); - + InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc,m_dispatcher1); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); - + m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); } @@ -539,7 +674,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) void btDiscreteDynamicsWorld::calculateSimulationIslands() { - BEGIN_PROFILE("calculateSimulationIslands"); + BT_PROFILE("calculateSimulationIslands"); getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); @@ -569,66 +704,85 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() //Store the island id in each body getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); - END_PROFILE("calculateSimulationIslands"); - + } -void btDiscreteDynamicsWorld::updateAabbs() +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { - BEGIN_PROFILE("updateAabbs"); - - btVector3 colorvec(1,0,0); - btTransform predictedTrans; - for ( int i=0;i=-m_allowedPenetration) + return 1.f; + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + //don't collide with itself + if (proxy0->m_clientObject == m_me) + return false; + + ///don't do CCD when the collision filters are not matching + if (!btCollisionWorld::ClosestConvexResultCallback::needsCollision(proxy0)) + return false; + + ///don't do CCD when there are already contact points (touching contact/penetration) + btAlignedObjectArray manifoldArray; + btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); + if (collisionPair) { - // if (body->IsActive() && (!body->IsStatic())) + if (collisionPair->m_algorithm) { - btPoint3 minAabb,maxAabb; - colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); - btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; - - //moving objects should be moderately sized, probably something wrong if not - if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + manifoldArray.resize(0); + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + for (int j=0;jsetAabb(body->getBroadphaseHandle(),minAabb,maxAabb); - } else - { - //something went wrong, investigate - //this assert is unwanted in 3D modelers (danger of loosing work) - body->setActivationState(DISABLE_SIMULATION); - - static bool reportMe = true; - if (reportMe && m_debugDrawer) - { - reportMe = false; - m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); - m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); - m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); - m_debugDrawer->reportErrorWarning("Thanks.\n"); - } - - - } - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); + btPersistentManifold* manifold = manifoldArray[j]; + if (manifold->getNumContacts()>0) + return false; } } } + return true; } - - END_PROFILE("updateAabbs"); -} + +}; + +///internal debugging variable. this value shouldn't be too high +int gNumClampedCcdMotions=0; + +//#include "stdio.h" void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { - BEGIN_PROFILE("integrateTransforms"); + BT_PROFILE("integrateTransforms"); btTransform predictedTrans; for ( int i=0;isetHitFraction(1.f); + if (body->isActive() && (!body->isStaticOrKinematicObject())) { body->predictIntegratedTransform(timeStep, predictedTrans); + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + + if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + { + BT_PROFILE("CCD motion clamping"); + if (body->getCollisionShape()->isConvex()) + { + gNumClampedCcdMotions++; + + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache()); + btConvexShape* convexShape = static_cast(body->getCollisionShape()); + btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults); + if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) + { + body->setHitFraction(sweepResults.m_closestHitFraction); + body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); + body->setHitFraction(0.f); +// printf("clamped integration to hit fraction = %f\n",fraction); + } + } + } + body->proceedToTransform( predictedTrans); } } } - END_PROFILE("integrateTransforms"); } void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { - BEGIN_PROFILE("predictUnconstraintMotion"); + BT_PROFILE("predictUnconstraintMotion"); for ( int i=0;iisActive()) { - body->applyForces( timeStep); body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } } } - END_PROFILE("predictUnconstraintMotion"); } void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) { (void)timeStep; - #ifdef USE_QUICKPROF +#ifndef BT_NO_PROFILE + CProfileManager::Reset(); +#endif //BT_NO_PROFILE - //toggle btProfiler - if ( m_debugDrawer && m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_ProfileTimings) - { - if (!m_profileTimings) - { - m_profileTimings = 1; - // To disable profiling, simply comment out the following line. - static int counter = 0; - - char filename[128]; - sprintf(filename,"quickprof_bullet_timings%i.csv",counter++); - btProfiler::init(filename, btProfiler::BLOCK_CYCLE_SECONDS);//BLOCK_TOTAL_MICROSECONDS - } else - { - btProfiler::endProfilingCycle(); - } - - } else - { - if (m_profileTimings) - { - btProfiler::endProfilingCycle(); - - m_profileTimings = 0; - btProfiler::destroy(); - } - } -#endif //USE_QUICKPROF } @@ -827,27 +980,52 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = capsuleShape->getRadius(); btScalar halfHeight = capsuleShape->getHalfHeight(); + + int upAxis = capsuleShape->getUpAxis(); + + + btVector3 capStart(0.f,0.f,0.f); + capStart[upAxis] = -halfHeight; + + btVector3 capEnd(0.f,0.f,0.f); + capEnd[upAxis] = halfHeight; // Draw the ends { + btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * btVector3(0,halfHeight,0); + childTransform.getOrigin() = worldTransform * capStart; debugDrawSphere(radius, childTransform, color); } { btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * btVector3(0,-halfHeight,0); + childTransform.getOrigin() = worldTransform * capEnd; debugDrawSphere(radius, childTransform, color); } // Draw some additional lines btVector3 start = worldTransform.getOrigin(); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(-radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(-radius,-halfHeight,0), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(radius,-halfHeight,0), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,-radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,-radius), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,radius), color); + + capStart[(upAxis+1)%3] = radius; + capEnd[(upAxis+1)%3] = radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + capStart[(upAxis+1)%3] = -radius; + capEnd[(upAxis+1)%3] = -radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + + capStart[(upAxis+1)%3] = 0.f; + capEnd[(upAxis+1)%3] = 0.f; + + capStart[(upAxis+2)%3] = radius; + capEnd[(upAxis+2)%3] = radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + capStart[(upAxis+2)%3] = -radius; + capEnd[(upAxis+2)%3] = -radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + + break; } case CONE_SHAPE_PROXYTYPE: @@ -856,9 +1034,10 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); btScalar height = coneShape->getHeight();//+coneShape->getMargin(); btVector3 start = worldTransform.getOrigin(); - // insert here Bullet 2.69 that fixes representation of cone + int upAxis= coneShape->getConeUpIndex(); + btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = height * btScalar(0.5); btVector3 offsetRadius(0,0,0); @@ -871,11 +1050,8 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color); getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color); - // buggy code that does not take into account the direction of the cone - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color); - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color); - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color); - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color); + + break; } @@ -884,7 +1060,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, const btCylinderShape* cylinder = static_cast(shape); int upAxis = cylinder->getUpAxis(); btScalar radius = cylinder->getRadius(); - btScalar halfHeight = cylinder->getHalfExtents()[upAxis]; + btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; btVector3 start = worldTransform.getOrigin(); btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = halfHeight; @@ -894,6 +1070,25 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); break; } + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + getDebugDrawer()->drawLine(worldTransform*pt0,worldTransform*pt1,color); + getDebugDrawer()->drawLine(worldTransform*pt2,worldTransform*pt3,color); + break; + + } default: { @@ -918,7 +1113,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); //DebugDrawcallback drawCallback; DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - convexMesh->getStridingMesh()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); } @@ -950,12 +1145,18 @@ void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - delete m_constraintSolver; + btAlignedFree( m_constraintSolver); } m_ownsConstraintSolver = false; m_constraintSolver = solver; } +btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} + + int btDiscreteDynamicsWorld::getNumConstraints() const { return int(m_constraints.size()); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index 83b90bfeebc..d9e2652aaf6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -23,11 +23,11 @@ class btOverlappingPairCache; class btConstraintSolver; class btSimulationIslandManager; class btTypedConstraint; -#include "../ConstraintSolver/btContactSolverInfo.h" + class btRaycastVehicle; class btIDebugDraw; -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" ///btDiscreteDynamicsWorld provides discrete rigid body simulation @@ -42,7 +42,6 @@ protected: btAlignedObjectArray m_constraints; - btIDebugDraw* m_debugDrawer; btVector3 m_gravity; @@ -53,16 +52,14 @@ protected: bool m_ownsIslandManager; bool m_ownsConstraintSolver; - btContactSolverInfo m_solverInfo; - - + btAlignedObjectArray m_vehicles; int m_profileTimings; - void predictUnconstraintMotion(btScalar timeStep); + virtual void predictUnconstraintMotion(btScalar timeStep); - void integrateTransforms(btScalar timeStep); + virtual void integrateTransforms(btScalar timeStep); void calculateSimulationIslands(); @@ -86,14 +83,13 @@ public: ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those - btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); virtual ~btDiscreteDynamicsWorld(); ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - virtual void updateAabbs(); void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); @@ -118,17 +114,9 @@ public: return this; } - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - } - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } virtual void setGravity(const btVector3& gravity); + virtual btVector3 getGravity () const; virtual void addRigidBody(btRigidBody* body); @@ -138,7 +126,11 @@ public: void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); + virtual void debugDrawWorld(); + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); virtual int getNumConstraints() const; @@ -146,11 +138,21 @@ public: virtual const btTypedConstraint* getConstraint(int index) const; - btContactSolverInfo& getSolverInfo() + + virtual btDynamicsWorldType getWorldType() const { - return m_solverInfo; + return BT_DISCRETE_DYNAMICS_WORLD; } + + ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep. + virtual void clearForces(); + ///apply gravity, call this once per timestep + virtual void applyGravity(); + + virtual void setNumTasks(int numTasks) + { + } }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 65b63fad4b5..929e24d337c 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -16,20 +16,39 @@ subject to the following restrictions: #ifndef BT_DYNAMICS_WORLD_H #define BT_DYNAMICS_WORLD_H -#include "../../BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + class btTypedConstraint; class btRaycastVehicle; class btConstraintSolver; +class btDynamicsWorld; +/// Type for the callback for each tick +typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); -///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous +enum btDynamicsWorldType +{ + BT_SIMPLE_DYNAMICS_WORLD=1, + BT_DISCRETE_DYNAMICS_WORLD=2, + BT_CONTINUOUS_DYNAMICS_WORLD=3 +}; + +///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. class btDynamicsWorld : public btCollisionWorld { - public: + +protected: + btInternalTickCallback m_internalTickCallback; + void* m_worldUserInfo; + + btContactSolverInfo m_solverInfo; + +public: - btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) - :btCollisionWorld(dispatcher,pairCache) + btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) + :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0) { } @@ -37,34 +56,37 @@ class btDynamicsWorld : public btCollisionWorld { } - ///stepSimulation proceeds the simulation over timeStep units - ///if maxSubSteps > 0, it will interpolate time steps + ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds. + ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'. + ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'. + ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant. virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; - virtual void updateAabbs() = 0; + virtual void debugDrawWorld() = 0; - virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;}; + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) + { + (void)constraint; (void)disableCollisionsBetweenLinkedBodies; + } - virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}; + virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} - virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; + virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} - virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; - - - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0; - - virtual btIDebugDraw* getDebugDrawer() = 0; + virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} //once a rigidbody is added to the dynamics world, it will get this gravity assigned //existing rigidbodies in the world get gravity assigned too, during this method virtual void setGravity(const btVector3& gravity) = 0; + virtual btVector3 getGravity () const = 0; virtual void addRigidBody(btRigidBody* body) = 0; virtual void removeRigidBody(btRigidBody* body) = 0; virtual void setConstraintSolver(btConstraintSolver* solver) = 0; + + virtual btConstraintSolver* getConstraintSolver() = 0; virtual int getNumConstraints() const { return 0; } @@ -72,7 +94,35 @@ class btDynamicsWorld : public btCollisionWorld virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } + virtual btDynamicsWorldType getWorldType() const=0; + + virtual void clearForces() = 0; + + /// Set the callback for when an internal tick (simulation substep) happens, optional user info + void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0) + { + m_internalTickCallback = cb; + m_worldUserInfo = worldUserInfo; + } + + void setWorldUserInfo(void* worldUserInfo) + { + m_worldUserInfo = worldUserInfo; + } + + void* getWorldUserInfo() const + { + return m_worldUserInfo; + } + + btContactSolverInfo& getSolverInfo() + { + return m_solverInfo; + } + + }; #endif //BT_DYNAMICS_WORLD_H + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index 9ed3579d89c..e2afb687ac6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -20,36 +20,53 @@ subject to the following restrictions: #include "LinearMath/btMotionState.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -btScalar gLinearAirDamping = btScalar(1.); //'temporarily' global variables btScalar gDeactivationTime = btScalar(2.); bool gDisableDeactivation = false; - -btScalar gLinearSleepingThreshold = btScalar(0.8); -btScalar gAngularSleepingThreshold = btScalar(1.0); static int uniqueId = 0; -btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_angularFactor(btScalar(1.)), - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_optionalMotionState(motionState), - m_contactSolverType(0), - m_frictionSolverType(0) + +btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + setupRigidBody(constructionInfo); +} + +btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) +{ + btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); + setupRigidBody(cinfo); +} + +void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) { - if (motionState) + m_internalType=CO_RIGID_BODY; + + m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + m_angularFactor = btScalar(1.); + m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearDamping = btScalar(0.); + m_angularDamping = btScalar(0.5); + m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; + m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; + m_optionalMotionState = constructionInfo.m_motionState; + m_contactSolverType = 0; + m_frictionSolverType = 0; + m_additionalDamping = constructionInfo.m_additionalDamping; + m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor; + m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; + m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; + m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; + + if (m_optionalMotionState) { - motionState->getWorldTransform(m_worldTransform); + m_optionalMotionState->getWorldTransform(m_worldTransform); } else { - m_worldTransform = btTransform::getIdentity(); + m_worldTransform = constructionInfo.m_startWorldTransform; } m_interpolationWorldTransform = m_worldTransform; @@ -57,90 +74,21 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionS m_interpolationAngularVelocity.setValue(0,0,0); //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; + m_friction = constructionInfo.m_friction; + m_restitution = constructionInfo.m_restitution; - m_collisionShape = collisionShape; + setCollisionShape( constructionInfo.m_collisionShape ); m_debugBodyId = uniqueId++; - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); + setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); + setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); updateInertiaTensor(); } -#ifdef OBSOLETE_MOTIONSTATE_LESS -btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_optionalMotionState(0), - m_contactSolverType(0), - m_frictionSolverType(0) -{ - - m_worldTransform = worldTransform; - m_interpolationWorldTransform = m_worldTransform; - m_interpolationLinearVelocity.setValue(0,0,0); - m_interpolationAngularVelocity.setValue(0,0,0); - - //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; - - m_collisionShape = collisionShape; - m_debugBodyId = uniqueId++; - - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); - updateInertiaTensor(); - -} - -#endif //OBSOLETE_MOTIONSTATE_LESS - - - - -//#define EXPERIMENTAL_JITTER_REMOVAL 1 -#ifdef EXPERIMENTAL_JITTER_REMOVAL -//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate -//doesn't work very well yet (value 0 disabled this damping) -//note there this influences deactivation thresholds! -btScalar gClippedAngvelThresholdSqr = btScalar(0.01); -btScalar gClippedLinearThresholdSqr = btScalar(0.01); -#endif //EXPERIMENTAL_JITTER_REMOVAL - -btScalar gJitterVelocityDampingFactor = btScalar(0.7); void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) { - -#ifdef EXPERIMENTAL_JITTER_REMOVAL - //if (wantsSleeping()) - { - //clip to avoid jitter - if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) && - (m_linearVelocity.length2() < gClippedLinearThresholdSqr)) - { - m_angularVelocity *= gJitterVelocityDampingFactor; - m_linearVelocity *= gJitterVelocityDampingFactor; - } - } - -#endif //EXPERIMENTAL_JITTER_REMOVAL - btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); } @@ -191,50 +139,63 @@ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) -#include + +///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping +void btRigidBody::applyDamping(btScalar timeStep) +{ + m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + + if (m_additionalDamping) + { + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && + (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) + { + m_angularVelocity *= m_additionalDampingFactor; + m_linearVelocity *= m_additionalDampingFactor; + } + + + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + } +} -void btRigidBody::applyForces(btScalar step) +void btRigidBody::applyGravity() { if (isStaticOrKinematicObject()) return; applyCentralForce(m_gravity); - - m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); -#define FORCE_VELOCITY_DAMPING 1 -#ifdef FORCE_VELOCITY_DAMPING - btScalar speed = m_linearVelocity.length(); - if (speed < m_linearDamping) - { - btScalar dampVel = btScalar(0.005); - if (speed > dampVel) - { - btVector3 dir = m_linearVelocity.normalized(); - m_linearVelocity -= dir * dampVel; - } else - { - m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } - - btScalar angSpeed = m_angularVelocity.length(); - if (angSpeed < m_angularDamping) - { - btScalar angDampVel = btScalar(0.005); - if (angSpeed > angDampVel) - { - btVector3 dir = m_angularVelocity.normalized(); - m_angularVelocity -= dir * angDampVel; - } else - { - m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } -#endif //FORCE_VELOCITY_DAMPING - } void btRigidBody::proceedToTransform(const btTransform& newTrans) @@ -285,7 +246,6 @@ void btRigidBody::integrateVelocities(btScalar step) m_angularVelocity *= (MAX_ANGVEL/step) /angvel; } - clearForces(); } btQuaternion btRigidBody::getOrientation() const diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index 0707595d48e..4596f90a00f 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -16,27 +16,29 @@ subject to the following restrictions: #ifndef RIGIDBODY_H #define RIGIDBODY_H -#include "../../LinearMath/btAlignedObjectArray.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btTransform.h" -#include "../../BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "../../BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" class btCollisionShape; class btMotionState; class btTypedConstraint; -extern btScalar gLinearAirDamping; - extern btScalar gDeactivationTime; extern bool gDisableDeactivation; -extern btScalar gLinearSleepingThreshold; -extern btScalar gAngularSleepingThreshold; -/// btRigidBody class for btRigidBody Dynamics -/// +///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. +///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. +///There are 3 types of rigid bodies: +///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. +///- B) Fixed objects with zero mass. They are not moving (basically collision objects) +///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. +///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. +///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) class btRigidBody : public btCollisionObject { @@ -53,7 +55,16 @@ class btRigidBody : public btCollisionObject btScalar m_linearDamping; btScalar m_angularDamping; - + + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; //m_optionalMotionState allows to automatic synchronize the world transform for active objects btMotionState* m_optionalMotionState; @@ -63,12 +74,85 @@ class btRigidBody : public btCollisionObject public: -#ifdef OBSOLETE_MOTIONSTATE_LESS - //not supported, please use btMotionState - btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); -#endif //OBSOLETE_MOTIONSTATE_LESS - btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); + ///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. + ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) + ///You can use the motion state to synchronize the world transform between physics and graphics objects. + ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, + ///m_startWorldTransform is only used when you don't provide a motion state. + struct btRigidBodyConstructionInfo + { + btScalar m_mass; + + ///When a motionState is provided, the rigid body will initialize its world transform from the motion state + ///In this case, m_startWorldTransform is ignored. + btMotionState* m_motionState; + btTransform m_startWorldTransform; + + btCollisionShape* m_collisionShape; + btVector3 m_localInertia; + btScalar m_linearDamping; + btScalar m_angularDamping; + + ///best simulation results when friction is non-zero + btScalar m_friction; + ///best simulation results using zero restitution. + btScalar m_restitution; + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): + m_mass(mass), + m_motionState(motionState), + m_collisionShape(collisionShape), + m_localInertia(localInertia), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), + m_linearSleepingThreshold(btScalar(0.8)), + m_angularSleepingThreshold(btScalar(1.f)), + m_additionalDamping(false), + m_additionalDampingFactor(btScalar(0.005)), + m_additionalLinearDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingFactor(btScalar(0.01)) + { + m_startWorldTransform.setIdentity(); + } + }; + + ///btRigidBody constructor using construction info + btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); + + ///btRigidBody constructor for backwards compatibility. + ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) + btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); + + + virtual ~btRigidBody() + { + //No constraints should point to this rigidbody + //Remove constraints from the dynamics world before you delete the related rigidbodies. + btAssert(m_constraintRefs.size()==0); + } + +protected: + + ///setupRigidBody is only used internally by the constructor + void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); + +public: void proceedToTransform(const btTransform& newTrans); @@ -76,11 +160,15 @@ public: ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast static const btRigidBody* upcast(const btCollisionObject* colObj) { - return (const btRigidBody*)colObj->getInternalOwner(); + if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY) + return (const btRigidBody*)colObj; + return 0; } static btRigidBody* upcast(btCollisionObject* colObj) { - return (btRigidBody*)colObj->getInternalOwner(); + if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY) + return (btRigidBody*)colObj; + return 0; } /// continuous collision detection needs prediction @@ -88,8 +176,7 @@ public: void saveKinematicState(btScalar step); - - void applyForces(btScalar step); + void applyGravity(); void setGravity(const btVector3& acceleration); @@ -99,12 +186,34 @@ public: } void setDamping(btScalar lin_damping, btScalar ang_damping); - - inline const btCollisionShape* getCollisionShape() const { + + btScalar getLinearDamping() const + { + return m_linearDamping; + } + + btScalar getAngularDamping() const + { + return m_angularDamping; + } + + btScalar getLinearSleepingThreshold() const + { + return m_linearSleepingThreshold; + } + + btScalar getAngularSleepingThreshold() const + { + return m_angularSleepingThreshold; + } + + void applyDamping(btScalar timeStep); + + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - inline btCollisionShape* getCollisionShape() { + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { return m_collisionShape; } @@ -134,6 +243,12 @@ public: m_invInertiaLocal = diagInvInertia; } + void setSleepingThresholds(btScalar linear,btScalar angular) + { + m_linearSleepingThreshold = linear; + m_angularSleepingThreshold = angular; + } + void applyTorque(const btVector3& torque) { m_totalTorque += torque; @@ -142,7 +257,7 @@ public: void applyForce(const btVector3& force, const btVector3& rel_pos) { applyCentralForce(force); - applyTorque(rel_pos.cross(force)); + applyTorque(rel_pos.cross(force)*m_angularFactor); } void applyCentralImpulse(const btVector3& impulse) @@ -168,7 +283,7 @@ public: } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { if (m_inverseMass != btScalar(0.)) { @@ -238,7 +353,7 @@ public: - inline btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const + SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const { btVector3 r0 = pos - getCenterOfMassPosition(); @@ -250,19 +365,19 @@ public: } - inline btScalar computeAngularImpulseDenominator(const btVector3& axis) const + SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const { btVector3 vec = axis * getInvInertiaTensorWorld(); return axis.dot(vec); } - inline void updateDeactivation(btScalar timeStep) + SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) { if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) return; - if ((getLinearVelocity().length2() < gLinearSleepingThreshold*gLinearSleepingThreshold) && - (getAngularVelocity().length2() < gAngularSleepingThreshold*gAngularSleepingThreshold)) + if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && + (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) { m_deactivationTime += timeStep; } else @@ -273,7 +388,7 @@ public: } - inline bool wantsSleeping() + SIMD_FORCE_INLINE bool wantsSleeping() { if (getActivationState() == DISABLE_DEACTIVATION) @@ -348,6 +463,16 @@ public: void addConstraintRef(btTypedConstraint* c); void removeConstraintRef(btTypedConstraint* c); + btTypedConstraint* getConstraintRef(int index) + { + return m_constraintRefs[index]; + } + + int getNumConstraintRefs() + { + return m_constraintRefs.size(); + } + int m_debugBodyId; }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 4ebcb8e7517..3be04d1a4ad 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -27,16 +27,19 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" void btBulletDynamicsProbe () {} +extern "C" +{ + void btBulletDynamicsProbe (); + void btBulletDynamicsProbe () {} +} -btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) -:btDynamicsWorld(dispatcher,pairCache), +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), m_constraintSolver(constraintSolver), m_ownsConstraintSolver(false), -m_debugDrawer(0), m_gravity(0,0,-10) { @@ -46,7 +49,7 @@ m_gravity(0,0,-10) btSimpleDynamicsWorld::~btSimpleDynamicsWorld() { if (m_ownsConstraintSolver) - delete m_constraintSolver; + btAlignedFree( m_constraintSolver); } int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) @@ -74,8 +77,9 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b btContactSolverInfo infoGlobal; infoGlobal.m_timeStep = timeStep; - - m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc); + m_constraintSolver->prepareSolve(0,numManifolds); + m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1); + m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc); } ///integrate transforms @@ -85,10 +89,27 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b synchronizeMotionStates(); + clearForces(); + return 1; } +void btSimpleDynamicsWorld::clearForces() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } + } +} + void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) { @@ -104,6 +125,11 @@ void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) } } +btVector3 btSimpleDynamicsWorld::getGravity () const +{ + return m_gravity; +} + void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) { removeCollisionObject(body); @@ -133,7 +159,7 @@ void btSimpleDynamicsWorld::updateAabbs() btPoint3 minAabb,maxAabb; colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); btBroadphaseInterface* bp = getBroadphase(); - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); } } } @@ -171,8 +197,9 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { if (body->isActive()) { - body->applyForces( timeStep); + body->applyGravity(); body->integrateVelocities( timeStep); + body->applyDamping(timeStep); body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } @@ -204,8 +231,13 @@ void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - delete m_constraintSolver; + btAlignedFree(m_constraintSolver); } m_ownsConstraintSolver = false; m_constraintSolver = solver; } + +btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h index 25f4ccd8e68..5c56fdf1327 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -22,11 +22,8 @@ class btDispatcher; class btOverlappingPairCache; class btConstraintSolver; -///btSimpleDynamicsWorld demonstrates very basic usage of Bullet rigid body dynamics -///It can be used for basic simulations, and as a starting point for porting Bullet -///btSimpleDynamicsWorld lacks object deactivation, island management and other concepts. -///For more complicated simulations, btDiscreteDynamicsWorld and btContinuousDynamicsWorld are recommended -///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +///btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. +///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished). class btSimpleDynamicsWorld : public btDynamicsWorld { protected: @@ -35,8 +32,6 @@ protected: bool m_ownsConstraintSolver; - btIDebugDraw* m_debugDrawer; - void predictUnconstraintMotion(btScalar timeStep); void integrateTransforms(btScalar timeStep); @@ -48,25 +43,17 @@ public: ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver - btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); virtual ~btSimpleDynamicsWorld(); ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - }; - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } - virtual void setGravity(const btVector3& gravity); + virtual btVector3 getGravity () const; + virtual void addRigidBody(btRigidBody* body); virtual void removeRigidBody(btRigidBody* body); @@ -77,6 +64,15 @@ public: virtual void setConstraintSolver(btConstraintSolver* solver); + virtual btConstraintSolver* getConstraintSolver(); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SIMPLE_DYNAMICS_WORLD; + } + + virtual void clearForces(); + }; #endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp index d53de7f3687..fe65245c2a1 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -23,12 +23,11 @@ #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" - - static btRigidBody s_fixedObject( 0,0,0); btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) -:m_vehicleRaycaster(raycaster), +: btTypedConstraint(VEHICLE_CONSTRAINT_TYPE), +m_vehicleRaycaster(raycaster), m_pitchControl(btScalar(0.)) { m_chassisBody = chassis; @@ -487,6 +486,7 @@ struct btWheelContactPoint }; +btScalar calcRollingFriction(btWheelContactPoint& contactPoint); btScalar calcRollingFriction(btWheelContactPoint& contactPoint) { @@ -507,8 +507,8 @@ btScalar calcRollingFriction(btWheelContactPoint& contactPoint) // calculate j that moves us to zero relative velocity j1 = -vrel * contactPoint.m_jacDiagABInv; - GEN_set_min(j1, maxImpulse); - GEN_set_max(j1, -maxImpulse); + btSetMin(j1, maxImpulse); + btSetMax(j1, -maxImpulse); return j1; } @@ -525,11 +525,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) if (!numWheel) return; - - btVector3* forwardWS = new btVector3[numWheel]; - btVector3* axle = new btVector3[numWheel]; - btScalar* forwardImpulse = new btScalar[numWheel]; - btScalar* sideImpulse = new btScalar[numWheel]; + m_forwardWS.resize(numWheel); + m_axle.resize(numWheel); + m_forwardImpulse.resize(numWheel); + m_sideImpulse.resize(numWheel); int numWheelsOnGround = 0; @@ -541,8 +540,8 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; if (groundObject) numWheelsOnGround++; - sideImpulse[i] = btScalar(0.); - forwardImpulse[i] = btScalar(0.); + m_sideImpulse[i] = btScalar(0.); + m_forwardImpulse[i] = btScalar(0.); } @@ -561,25 +560,25 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) const btTransform& wheelTrans = getWheelTransformWS( i ); btMatrix3x3 wheelBasis0 = wheelTrans.getBasis(); - axle[i] = btVector3( + m_axle[i] = btVector3( wheelBasis0[0][m_indexRightAxis], wheelBasis0[1][m_indexRightAxis], wheelBasis0[2][m_indexRightAxis]); const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS; - btScalar proj = axle[i].dot(surfNormalWS); - axle[i] -= surfNormalWS * proj; - axle[i] = axle[i].normalize(); + btScalar proj = m_axle[i].dot(surfNormalWS); + m_axle[i] -= surfNormalWS * proj; + m_axle[i] = m_axle[i].normalize(); - forwardWS[i] = surfNormalWS.cross(axle[i]); - forwardWS[i].normalize(); + m_forwardWS[i] = surfNormalWS.cross(m_axle[i]); + m_forwardWS[i].normalize(); resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS, *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, - btScalar(0.), axle[i],sideImpulse[i],timeStep); + btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep); - sideImpulse[i] *= sideFrictionStiffness2; + m_sideImpulse[i] *= sideFrictionStiffness2; } @@ -608,7 +607,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) { btScalar defaultRollingFrictionImpulse = 0.f; btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; - btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,forwardWS[wheel],maxImpulse); + btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse); rollingFriction = calcRollingFriction(contactPt); } } @@ -618,7 +617,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) - forwardImpulse[wheel] = btScalar(0.); + m_forwardImpulse[wheel] = btScalar(0.); m_wheelInfo[wheel].m_skidInfo= btScalar(1.); if (groundObject) @@ -631,10 +630,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btScalar maximpSquared = maximp * maximpSide; - forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; + m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; - btScalar x = (forwardImpulse[wheel] ) * fwdFactor; - btScalar y = (sideImpulse[wheel] ) * sideFactor; + btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor; + btScalar y = (m_sideImpulse[wheel] ) * sideFactor; btScalar impulseSquared = (x*x + y*y); @@ -658,12 +657,12 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) { for (int wheel = 0;wheel < getNumWheels(); wheel++) { - if (sideImpulse[wheel] != btScalar(0.)) + if (m_sideImpulse[wheel] != btScalar(0.)) { if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) { - forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; - sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; } } } @@ -678,11 +677,11 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS - m_chassisBody->getCenterOfMassPosition(); - if (forwardImpulse[wheel] != btScalar(0.)) + if (m_forwardImpulse[wheel] != btScalar(0.)) { - m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos); + m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); } - if (sideImpulse[wheel] != btScalar(0.)) + if (m_sideImpulse[wheel] != btScalar(0.)) { class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; @@ -690,7 +689,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) groundObject->getCenterOfMassPosition(); - btVector3 sideImp = axle[wheel] * sideImpulse[wheel]; + btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; rel_pos[2] *= wheelInfo.m_rollInfluence; m_chassisBody->applyImpulse(sideImp,rel_pos); @@ -701,10 +700,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) } } - delete []forwardWS; - delete [] axle; - delete[]forwardImpulse; - delete[] sideImpulse; + } @@ -716,11 +712,11 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& m_dynamicsWorld->rayTest(from, to, rayCallback); - if (rayCallback.HasHit()) + if (rayCallback.hasHit()) { btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); - if (body) + if (body && body->hasContactResponse()) { result.m_hitPointInWorld = rayCallback.m_hitPointWorld; result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index f4249599615..8361dcabe4b 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -11,11 +11,11 @@ #ifndef RAYCASTVEHICLE_H #define RAYCASTVEHICLE_H -#include "../Dynamics/btRigidBody.h" -#include "../ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" #include "btVehicleRaycaster.h" class btDynamicsWorld; -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" #include "btWheelInfo.h" class btVehicleTuning; @@ -23,6 +23,12 @@ class btVehicleTuning; ///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. class btRaycastVehicle : public btTypedConstraint { + + btAlignedObjectArray m_forwardWS; + btAlignedObjectArray m_axle; + btAlignedObjectArray m_forwardImpulse; + btAlignedObjectArray m_sideImpulse; + public: class btVehicleTuning { @@ -114,7 +120,7 @@ public: void updateSuspension(btScalar deltaTime); - void updateFriction(btScalar timeStep); + virtual void updateFriction(btScalar timeStep); diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h index 64a47fcaada..5112ce6d420 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -11,7 +11,7 @@ #ifndef VEHICLE_RAYCASTER_H #define VEHICLE_RAYCASTER_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" /// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting struct btVehicleRaycaster diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h index 2e349b3fde4..ac2729f4fd7 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -11,8 +11,8 @@ #ifndef WHEEL_INFO_H #define WHEEL_INFO_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletSoftBody/CMakeLists.txt b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt new file mode 100644 index 00000000000..a725e10ff77 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt @@ -0,0 +1,21 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src } +) + +ADD_LIBRARY(LibBulletSoftBody + btSoftBody.cpp + btSoftBody.h + btSoftBodyHelpers.cpp + btSparseSDF.h + btSoftBodyHelpers.h + btSoftBodyRigidBodyCollisionConfiguration.cpp + btSoftRigidCollisionAlgorithm.cpp + btSoftRigidCollisionAlgorithm.h + btSoftSoftCollisionAlgorithm.cpp + btSoftSoftCollisionAlgorithm.h + btSoftBodyConcaveCollisionAlgorithm.cpp + btSoftBodyConcaveCollisionAlgorithm.h + btSoftRigidDynamicsWorld.h + btSoftRigidDynamicsWorld.cpp +) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp new file mode 100644 index 00000000000..2553009fec2 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -0,0 +1,2590 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#include "btSoftBodyInternals.h" + +// +btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) +:m_worldInfo(worldInfo) +{ + /* Init */ + m_internalType = CO_SOFT_BODY; + m_cfg.aeromodel = eAeroModel::V_Point; + m_cfg.kVCF = 1; + m_cfg.kDG = 0; + m_cfg.kLF = 0; + m_cfg.kDP = 0; + m_cfg.kPR = 0; + m_cfg.kVC = 0; + m_cfg.kDF = (btScalar)0.2; + m_cfg.kMT = 0; + m_cfg.kCHR = (btScalar)1.0; + m_cfg.kKHR = (btScalar)0.1; + m_cfg.kSHR = (btScalar)1.0; + m_cfg.kAHR = (btScalar)0.7; + m_cfg.kSRHR_CL = (btScalar)0.1; + m_cfg.kSKHR_CL = (btScalar)1; + m_cfg.kSSHR_CL = (btScalar)0.5; + m_cfg.kSR_SPLT_CL = (btScalar)0.5; + m_cfg.kSK_SPLT_CL = (btScalar)0.5; + m_cfg.kSS_SPLT_CL = (btScalar)0.5; + m_cfg.maxvolume = (btScalar)1; + m_cfg.timescale = 1; + m_cfg.viterations = 0; + m_cfg.piterations = 1; + m_cfg.diterations = 0; + m_cfg.citerations = 4; + m_cfg.collisions = fCollision::Default; + m_pose.m_bvolume = false; + m_pose.m_bframe = false; + m_pose.m_volume = 0; + m_pose.m_com = btVector3(0,0,0); + m_pose.m_rot.setIdentity(); + m_pose.m_scl.setIdentity(); + m_tag = 0; + m_timeacc = 0; + m_bUpdateRtCst = true; + m_bounds[0] = btVector3(0,0,0); + m_bounds[1] = btVector3(0,0,0); + m_worldTransform.setIdentity(); + setSolver(eSolverPresets::Positions); + /* Default material */ + Material* pm=appendMaterial(); + pm->m_kLST = 1; + pm->m_kAST = 1; + pm->m_kVST = 1; + pm->m_flags = fMaterial::Default; + /* Collision shape */ + ///for now, create a collision shape internally + setCollisionShape(new btSoftBodyCollisionShape(this)); + m_collisionShape->setMargin(0.25); + /* Nodes */ + const btScalar margin=getCollisionShape()->getMargin(); + m_nodes.resize(node_count); + for(int i=0,ni=node_count;i0?1/n.m_im:0; + n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); + n.m_material= pm; + } + updateBounds(); + + +} + +// +btSoftBody::~btSoftBody() +{ + //for now, delete the internal shape + delete m_collisionShape; + int i; + + for(i=0;i0) + *pm=*m_materials[0]; + else + ZeroInitialize(*pm); +m_materials.push_back(pm); +return(pm); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + const btVector4& c, + Node* n0, + Node* n1, + Node* n2, + Node* n3) +{ +Note n; +ZeroInitialize(n); +n.m_rank = 0; +n.m_text = text; +n.m_offset = o; +n.m_coords[0] = c.x(); +n.m_coords[1] = c.y(); +n.m_coords[2] = c.z(); +n.m_coords[3] = c.w(); +n.m_nodes[0] = n0;n.m_rank+=n0?1:0; +n.m_nodes[1] = n1;n.m_rank+=n1?1:0; +n.m_nodes[2] = n2;n.m_rank+=n2?1:0; +n.m_nodes[3] = n3;n.m_rank+=n3?1:0; +m_notes.push_back(n); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Node* feature) +{ +appendNote(text,o,btVector4(1,0,0,0),feature); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Link* feature) +{ +static const btScalar w=1/(btScalar)2; +appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0], + feature->m_n[1]); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Face* feature) +{ +static const btScalar w=1/(btScalar)3; +appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0], + feature->m_n[1], + feature->m_n[2]); +} + +// +void btSoftBody::appendNode( const btVector3& x,btScalar m) +{ +if(m_nodes.capacity()==m_nodes.size()) + { + pointersToIndices(); + m_nodes.reserve(m_nodes.size()*2+1); + indicesToPointers(); + } +const btScalar margin=getCollisionShape()->getMargin(); +m_nodes.push_back(Node()); +Node& n=m_nodes[m_nodes.size()-1]; +ZeroInitialize(n); +n.m_x = x; +n.m_q = n.m_x; +n.m_im = m>0?1/m:0; +n.m_material = m_materials[0]; +n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); +} + +// +void btSoftBody::appendLink(int model,Material* mat) +{ +Link l; +if(model>=0) + l=m_links[model]; + else + { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; } +m_links.push_back(l); +} + +// +void btSoftBody::appendLink( int node0, + int node1, + Material* mat, + bool bcheckexist) +{ + appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist); +} + +// +void btSoftBody::appendLink( Node* node0, + Node* node1, + Material* mat, + bool bcheckexist) +{ + if((!bcheckexist)||(!checkLink(node0,node1))) + { + appendLink(-1,mat); + Link& l=m_links[m_links.size()-1]; + l.m_n[0] = node0; + l.m_n[1] = node1; + l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); + m_bUpdateRtCst=true; + } +} + +// +void btSoftBody::appendFace(int model,Material* mat) +{ +Face f; +if(model>=0) + { f=m_faces[model]; } + else + { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; } +m_faces.push_back(f); +} + +// +void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) +{ + appendFace(-1,mat); + Face& f=m_faces[m_faces.size()-1]; + btAssert(node0!=node1); + btAssert(node1!=node2); + btAssert(node2!=node0); + f.m_n[0] = &m_nodes[node0]; + f.m_n[1] = &m_nodes[node1]; + f.m_n[2] = &m_nodes[node2]; + f.m_ra = AreaOf( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + m_bUpdateRtCst=true; +} + +// +void btSoftBody::appendAnchor(int node,btRigidBody* body) +{ + Anchor a; + a.m_node = &m_nodes[node]; + a.m_body = body; + a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x; + a.m_node->m_battach = 1; + m_anchors.push_back(a); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1) +{ +LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint(); +pj->m_bodies[0] = body0; +pj->m_bodies[1] = body1; +pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position; +pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position; +pj->m_cfm = specs.cfm; +pj->m_erp = specs.erp; +pj->m_split = specs.split; +m_joints.push_back(pj); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body) +{ +appendLinearJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) +{ +appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1) +{ +AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint(); +pj->m_bodies[0] = body0; +pj->m_bodies[1] = body1; +pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis; +pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis; +pj->m_cfm = specs.cfm; +pj->m_erp = specs.erp; +pj->m_split = specs.split; +pj->m_icontrol = specs.icontrol; +m_joints.push_back(pj); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body) +{ +appendAngularJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) +{ +appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::addForce(const btVector3& force) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_f += force; + } +} + +// +void btSoftBody::addVelocity(const btVector3& velocity) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_v += velocity; + } +} + +// +void btSoftBody::setMass(int node,btScalar mass) +{ + m_nodes[node].m_im=mass>0?1/mass:0; + m_bUpdateRtCst=true; +} + +// +btScalar btSoftBody::getMass(int node) const +{ + return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); +} + +// +btScalar btSoftBody::getTotalMass() const +{ + btScalar mass=0; + for(int i=0;im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + for(int j=0;j<3;++j) + { + f.m_n[j]->m_im+=twicearea; + } + } + for( i=0;igetMargin(); + for(int i=0,ni=m_nodes.size();igetMargin(); + for(int i=0,ni=m_nodes.size();i0 ? + 1/(m_nodes[i].m_im*tmass) : + kmass/tmass; + } + /* Pos */ + const btVector3 com=evaluateCom(); + m_pose.m_pos.resize(m_nodes.size()); + for( i=0,ni=m_nodes.size();i0) + { + int i,ni; + + const btVector3 org=m_nodes[0].m_x; + for(i=0,ni=m_faces.size();im_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); + } + vol/=(btScalar)6; + } + return(vol); +} + +// +int btSoftBody::clusterCount() const +{ +return(m_clusters.size()); +} + +// +btVector3 btSoftBody::clusterCom(const Cluster* cluster) +{ +btVector3 com(0,0,0); +for(int i=0,ni=cluster->m_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; + } +return(com*cluster->m_imass); +} + +// +btVector3 btSoftBody::clusterCom(int cluster) const +{ +return(clusterCom(m_clusters[cluster])); +} + +// +btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) +{ +return(cluster->m_lv+cross(cluster->m_av,rpos)); +} + +// +void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ +const btVector3 li=cluster->m_imass*impulse; +const btVector3 ai=cluster->m_invwi*cross(rpos,impulse); +cluster->m_vimpulses[0]+=li;cluster->m_lv+=li; +cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; +cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ +const btVector3 li=cluster->m_imass*impulse; +const btVector3 ai=cluster->m_invwi*cross(rpos,impulse); +cluster->m_dimpulses[0]+=li; +cluster->m_dimpulses[1]+=ai; +cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse) +{ +if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity); +if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift); +} + +// +void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse) +{ +const btVector3 ai=cluster->m_invwi*impulse; +cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; +cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse) +{ +const btVector3 ai=cluster->m_invwi*impulse; +cluster->m_dimpulses[1]+=ai; +cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse) +{ +if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity); +if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift); +} + +// +void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse) +{ +cluster->m_dimpulses[0]+=impulse*cluster->m_imass; +cluster->m_ndimpulses++; +} + +// +int btSoftBody::generateBendingConstraints(int distance,Material* mat) +{ + int i,j; + + if(distance>1) + { + /* Build graph */ + const int n=m_nodes.size(); + const unsigned inf=(~(unsigned)0)>>1; + unsigned* adj=new unsigned[n*n]; +#define IDX(_x_,_y_) ((_y_)*n+(_x_)) + for(j=0;jsum) + { + adj[IDX(i,j)]=adj[IDX(j,i)]=sum; + } + } + } + } + /* Build links */ + int nlinks=0; + for(j=0;jm_leaf) m_cdbvt.remove(m_clusters[i]->m_leaf); + btAlignedFree(m_clusters[i]); + } +m_clusters.resize(btMin(k,m_nodes.size())); + + + +for(i=0;im_collide= true; + } +k=m_clusters.size(); +if(k>0) + { + /* Initialize */ + btAlignedObjectArray centers; + btVector3 cog(0,0,0); + int i; + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + cog/=(btScalar)m_nodes.size(); + centers.resize(k,cog); + /* Iterate */ + const btScalar slope=16; + bool changed; + int iterations=0; + do { + const btScalar w=2-btMin(1,iterations/slope); + changed=false; + iterations++; + int i; + + for(i=0;im_nodes.size();++j) + { + c+=m_clusters[i]->m_nodes[j]->m_x; + } + if(m_clusters[i]->m_nodes.size()) + { + c /= (btScalar)m_clusters[i]->m_nodes.size(); + c = centers[i]+(c-centers[i])*w; + changed |= ((c-centers[i]).length2()>SIMD_EPSILON); + centers[i] = c; + m_clusters[i]->m_nodes.resize(0); + } + } + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + } while(changed&&(iterations cids; + cids.resize(m_nodes.size(),-1); + for(i=0;im_nodes.size();++j) + { + cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; + } + } + for(i=0;im_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) + { + m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); + } + } + } + } + } + /* Master */ + if(m_clusters.size()>1) + { + Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); + pmaster->m_collide = false; + pmaster->m_nodes.reserve(m_nodes.size()); + for(int i=0;im_nodes.push_back(&m_nodes[i]); + m_clusters.push_back(pmaster); + btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]); + } + /* Terminate */ + for(i=0;im_nodes.size()==0) + { + btAlignedFree(m_clusters[i]); + btSwap(m_clusters[i],m_clusters[m_clusters.size()-1]); + m_clusters.pop_back(); + --i; + } + } + + initializeClusters(); + updateClusters(); + return(m_clusters.size()); + } +return(0); +} + +// +void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut) +{ +const Node* nbase = &m_nodes[0]; +int ncount = m_nodes.size(); +btSymMatrix edges(ncount,-2); +int newnodes=0; +int i,j,k,ni; + +/* Filter out */ +for(i=0;iEval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x))) + { + btSwap(m_links[i],m_links[m_links.size()-1]); + m_links.pop_back();--i; + } + } + } +/* Fill edges */ +for(i=0;i0) + { + const btVector3 x=Lerp(a.m_x,b.m_x,t); + const btVector3 v=Lerp(a.m_v,b.m_v,t); + btScalar m=0; + if(a.m_im>0) + { + if(b.m_im>0) + { + const btScalar ma=1/a.m_im; + const btScalar mb=1/b.m_im; + const btScalar mc=Lerp(ma,mb,t); + const btScalar f=(ma+mb)/(ma+mb+mc); + a.m_im=1/(ma*f); + b.m_im=1/(mb*f); + m=mc*f; + } + else + { a.m_im/=0.5;m=1/a.m_im; } + } + else + { + if(b.m_im>0) + { b.m_im/=0.5;m=1/b.m_im; } + else + m=0; + } + appendNode(x,m); + edges(i,j)=m_nodes.size()-1; + m_nodes[edges(i,j)].m_v=v; + ++newnodes; + } + } + } + } +nbase=&m_nodes[0]; +/* Refine links */ +for(i=0,ni=m_links.size();i0) + { + appendLink(i); + Link* pft[]={ &m_links[i], + &m_links[m_links.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[0]]; + pft[0]->m_n[1]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[1]]; + } + } + } +/* Refine faces */ +for(i=0;i0) + { + appendFace(i); + const int l=(k+1)%3; + Face* pft[]={ &m_faces[i], + &m_faces[m_faces.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[l]]; + pft[0]->m_n[1]=&m_nodes[idx[j]]; + pft[0]->m_n[2]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[k]]; + pft[1]->m_n[2]=&m_nodes[idx[l]]; + appendLink(ni,idx[l],pft[0]->m_material); + --i;break; + } + } + } + } +/* Cut */ +if(cut) + { + btAlignedObjectArray cnodes; + const int pcount=ncount; + int i; + ncount=m_nodes.size(); + cnodes.resize(ncount,0); + /* Nodes */ + for(i=0;i=pcount)||(btFabs(ifn->Eval(x))0) { m*=0.5;m_nodes[i].m_im/=0.5; } + appendNode(x,m); + cnodes[i]=m_nodes.size()-1; + m_nodes[cnodes[i]].m_v=v; + } + } + nbase=&m_nodes[0]; + /* Links */ + for(i=0,ni=m_links.size();iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)Eval(n[0]->m_x)Eval(n[1]->m_x)Eval(n[2]->m_x) ranks; + btAlignedObjectArray todelete; + ranks.resize(nnodes,0); + for(i=0,ni=m_links.size();i=0;--i) + { + if(!ranks[i]) todelete.push_back(i); + } + if(todelete.size()) + { + btAlignedObjectArray& map=ranks; + for(int i=0;im_v=v; +pn[1]->m_v=v; +for(i=0,ni=m_links.size();im_n[1]=pn[mtch]; + pft[1]->m_n[0]=pn[1-mtch]; + done=true; + } + } +for(i=0,ni=m_faces.size();im_n[l]=pn[mtch]; + pft[1]->m_n[k]=pn[1-mtch]; + appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + } + } + } +if(!done) + { + m_ndbvt.remove(pn[0]->m_leaf); + m_ndbvt.remove(pn[1]->m_leaf); + m_nodes.pop_back(); + m_nodes.pop_back(); + } +return(done); +} + +// +bool btSoftBody::rayCast(const btVector3& org, + const btVector3& dir, + sRayCast& results, + btScalar maxtime) +{ +if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree(); +results.body = this; +results.time = maxtime; +results.feature = eFeature::None; +results.index = -1; +return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0); +} + +// +void btSoftBody::setSolver(eSolverPresets::_ preset) +{ +m_cfg.m_vsequence.clear(); +m_cfg.m_psequence.clear(); +m_cfg.m_dsequence.clear(); +switch(preset) + { + case eSolverPresets::Positions: + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + m_cfg.m_psequence.push_back(ePSolver::Linear); + break; + case eSolverPresets::Velocities: + m_cfg.m_vsequence.push_back(eVSolver::Linear); + + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + + m_cfg.m_dsequence.push_back(ePSolver::Linear); + break; + } +} + +// +void btSoftBody::predictMotion(btScalar dt) +{ + int i,ni; + + /* Update */ + if(m_bUpdateRtCst) + { + m_bUpdateRtCst=false; + updateConstants(); + m_fdbvt.clear(); + if(m_cfg.collisions&fCollision::VF_SS) + { + initializeFaceTree(); + } + } + + /* Prepare */ + m_sst.sdt = dt*m_cfg.timescale; + m_sst.isdt = 1/m_sst.sdt; + m_sst.velmrg = m_sst.sdt*3; + m_sst.radmrg = getCollisionShape()->getMargin(); + m_sst.updmrg = m_sst.radmrg*(btScalar)0.25; + /* Forces */ + addVelocity(m_worldInfo->m_gravity*m_sst.sdt); + applyForces(); + /* Integrate */ + for(i=0,ni=m_nodes.size();im_v+ + f.m_n[1]->m_v+ + f.m_n[2]->m_v)/3; + m_fdbvt.update( f.m_leaf, + VolumeOf(f,m_sst.radmrg), + v*m_sst.velmrg, + m_sst.updmrg); + } + } + /* Pose */ + updatePose(); + /* Match */ + if(m_pose.m_bframe&&(m_cfg.kMT>0)) + { + const btMatrix3x3 posetrs=m_pose.m_rot; + for(int i=0,ni=m_nodes.size();i0) + { + const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com; + n.m_x=Lerp(n.m_x,x,m_cfg.kMT); + } + } + } + /* Clear contacts */ + m_rcontacts.resize(0); + m_scontacts.resize(0); + /* Optimize dbvt's */ + m_ndbvt.optimizeIncremental(1); + m_fdbvt.optimizeIncremental(1); + m_cdbvt.optimizeIncremental(1); +} + +// +void btSoftBody::solveConstraints() +{ +/* Apply clusters */ +applyClusters(false); +/* Prepare links */ + +int i,ni; + +for(i=0,ni=m_links.size();im_q-l.m_n[0]->m_q; + l.m_c2 = 1/(l.m_c3.length2()*l.m_c0); + } +/* Prepare anchors */ +for(i=0,ni=m_anchors.size();igetWorldTransform().getBasis()*a.m_local; + a.m_c0 = ImpulseMatrix( m_sst.sdt, + a.m_node->m_im, + a.m_body->getInvMass(), + a.m_body->getInvInertiaTensorWorld(), + ra); + a.m_c1 = ra; + a.m_c2 = m_sst.sdt*a.m_node->m_im; + a.m_body->activate(); + } +/* Solve velocities */ +if(m_cfg.viterations>0) + { + /* Solve */ + for(int isolve=0;isolve0) + { + for(int isolve=0;isolve0) + { + const btScalar vcf=m_cfg.kVCF*m_sst.isdt; + for(i=0,ni=m_nodes.size();i& bodies) +{ +const int nb=bodies.size(); +int iterations=0; +int i; + +for(i=0;im_cfg.citerations); + } +for(i=0;iprepareClusters(iterations); + } +for(i=0;isolveClusters(sor); + } + } +for(i=0;icleanupClusters(); + } +} + +// +void btSoftBody::integrateMotion() +{ + /* Update */ + updateNormals(); +} + +// + btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt) +{ +o = org; +d = dir; +mint = mxt; +face = 0; +tests = 0; +} + +// +void btSoftBody::RayCaster::Process(const btDbvtNode* leaf) +{ +btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; +const btScalar t=rayTriangle( o,d, + f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + mint); +if((t>0)&&(tteps)&&(tceps) && + (dot(n,cross(b-hit,c-hit))>ceps) && + (dot(n,cross(c-hit,a-hit))>ceps)) + { + return(t); + } + } + } + return(-1); +} + +// +void btSoftBody::pointersToIndices() +{ +#define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) + btSoftBody::Node* base=&m_nodes[0]; + int i,ni; + + for(i=0,ni=m_nodes.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_links.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_anchors.size();idata=&m_nodes[i]; + } + } + for(i=0,ni=m_links.size();idata=&m_faces[i]; + } + } + for(i=0,ni=m_anchors.size();im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Face; + index=i; + mint=t; + } + } + } + } + else + {/* Use dbvt */ + RayCaster collider(org,dir,mint); + btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider); + if(collider.face) + { + mint=collider.mint; + feature=btSoftBody::eFeature::Face; + index=(int)(collider.face-&m_faces[0]); + cnt=1; + } + } + return(cnt); +} + +// +void btSoftBody::initializeFaceTree() +{ +m_fdbvt.clear(); +for(int i=0;igetCollisionShape(); + const btTransform& wtr=prb->getInterpolationWorldTransform(); + btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x), + shp, + nrm, + margin); + if(dst<0) + { + cti.m_body = prb; + cti.m_normal = wtr.getBasis()*nrm; + cti.m_offset = -dot( cti.m_normal, + x-cti.m_normal*dst); + return(true); + } + return(false); +} + +// +void btSoftBody::updateNormals() +{ + const btVector3 zv(0,0,0); + int i,ni; + + for(i=0,ni=m_nodes.size();im_x-f.m_n[0]->m_x, + f.m_n[2]->m_x-f.m_n[0]->m_x); + f.m_normal=n.normalized(); + f.m_n[0]->m_n+=n; + f.m_n[1]->m_n+=n; + f.m_n[2]->m_n+=n; + } + for(i=0,ni=m_nodes.size();iSIMD_EPSILON) + m_nodes[i].m_n /= len; + } +} + +// +void btSoftBody::updateBounds() +{ + if(m_ndbvt.m_root) + { + const btVector3& mins=m_ndbvt.m_root->volume.Mins(); + const btVector3& maxs=m_ndbvt.m_root->volume.Maxs(); + const btScalar csm=getCollisionShape()->getMargin(); + const btVector3 mrg=btVector3( csm, + csm, + csm)*1; // ??? to investigate... + m_bounds[0]=mins-mrg; + m_bounds[1]=maxs+mrg; + if(0!=getBroadphaseHandle()) + { + m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), + m_bounds[0], + m_bounds[1], + m_worldInfo->m_dispatcher); + } + } + else + { + m_bounds[0]= + m_bounds[1]=btVector3(0,0,0); + } +} + + +// +void btSoftBody::updatePose() +{ + if(m_pose.m_bframe) + { + btSoftBody::Pose& pose=m_pose; + const btVector3 com=evaluateCom(); + /* Com */ + pose.m_com = com; + /* Rotation */ + btMatrix3x3 Apq; + const btScalar eps=SIMD_EPSILON; + Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); + Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); + for(int i=0,ni=m_nodes.size();i1) + { + const btScalar idet=Clamp( 1/pose.m_scl.determinant(), + 1,m_cfg.maxvolume); + pose.m_scl=Mul(pose.m_scl,idet); + } + + } +} + +// +void btSoftBody::updateConstants() +{ + int i,ni; + + /* Links */ + for(i=0,ni=m_links.size();im_x-l.m_n[1]->m_x).length(); + l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST; + l.m_c1 = l.m_rl*l.m_rl; + } + /* Faces */ + for(i=0,ni=m_faces.size();im_x,f.m_n[1]->m_x,f.m_n[2]->m_x); + } + /* Area's */ + btAlignedObjectArray counts; + counts.resize(m_nodes.size(),0); + for(i=0,ni=m_nodes.size();im_area+=btFabs(f.m_ra); + } + } + for(i=0,ni=m_nodes.size();i0) + m_nodes[i].m_area/=(btScalar)counts[i]; + else + m_nodes[i].m_area=0; + } +} + +// +void btSoftBody::initializeClusters() +{ + int i; + +for( i=0;im_im>0?1/c.m_nodes[j]->m_im:0; + c.m_imass += c.m_masses[j]; + } + c.m_imass = 1/c.m_imass; + c.m_com = btSoftBody::clusterCom(&c); + c.m_lv = btVector3(0,0,0); + c.m_av = btVector3(0,0,0); + c.m_leaf = 0; + /* Inertia */ + btMatrix3x3& ii=c.m_locii; + ii[0]=ii[1]=ii[2]=btVector3(0,0,0); + { + int i,ni; + + for(i=0,ni=c.m_nodes.size();im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=c.m_masses[i]; + ii[0][0] += m*(q[1]+q[2]); + ii[1][1] += m*(q[0]+q[2]); + ii[2][2] += m*(q[0]+q[1]); + ii[0][1] -= m*k[0]*k[1]; + ii[0][2] -= m*k[0]*k[2]; + ii[1][2] -= m*k[1]*k[2]; + } + } + ii[1][0]=ii[0][1]; + ii[2][0]=ii[0][2]; + ii[2][1]=ii[1][2]; + ii=ii.inverse(); + /* Frame */ + c.m_framexform.setIdentity(); + c.m_framexform.setOrigin(c.m_com); + c.m_framerefs.resize(c.m_nodes.size()); + { + int i; + for(i=0;im_x-c.m_com; + } + } + } +} + +// +void btSoftBody::updateClusters() +{ +BT_PROFILE("UpdateClusters"); +int i; + +for(i=0;im_x-c.m_com; + const btVector3& b=c.m_framerefs[i]; + m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b; + } + PolarDecompose(m,r,s); + c.m_framexform.setOrigin(c.m_com); + c.m_framexform.setBasis(r); + /* Inertia */ + #if 1/* Constant */ + c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose(); + #else + #if 0/* Sphere */ + const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass); + const btVector3 inertia(rk,rk,rk); + const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0, + btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0, + btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0); + + c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose(); + #else/* Actual */ + c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0); + for(int i=0;im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=1/c.m_nodes[i]->m_im; + c.m_invwi[0][0] += m*(q[1]+q[2]); + c.m_invwi[1][1] += m*(q[0]+q[2]); + c.m_invwi[2][2] += m*(q[0]+q[1]); + c.m_invwi[0][1] -= m*k[0]*k[1]; + c.m_invwi[0][2] -= m*k[0]*k[2]; + c.m_invwi[1][2] -= m*k[1]*k[2]; + } + c.m_invwi[1][0]=c.m_invwi[0][1]; + c.m_invwi[2][0]=c.m_invwi[0][2]; + c.m_invwi[2][1]=c.m_invwi[1][2]; + c.m_invwi=c.m_invwi.inverse(); + #endif + #endif + /* Velocities */ + c.m_lv=btVector3(0,0,0); + c.m_av=btVector3(0,0,0); + { + int i; + + for(i=0;im_v*c.m_masses[i]; + c.m_lv += v; + c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v); + } + } + c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping); + c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping); + c.m_vimpulses[0] = + c.m_vimpulses[1] = btVector3(0,0,0); + c.m_dimpulses[0] = + c.m_dimpulses[1] = btVector3(0,0,0); + c.m_nvimpulses = 0; + c.m_ndimpulses = 0; + /* Matching */ + if(c.m_matching>0) + { + for(int j=0;jm_x; + btVector3 mx=mi; + for(int j=1;jm_x); + mx.setMax(c.m_nodes[j]->m_x); + } + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); + if(c.m_leaf) + m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); + else + c.m_leaf=m_cdbvt.insert(bounds,&c); + } + } + } +} + +// +void btSoftBody::cleanupClusters() +{ +for(int i=0;iTerminate(m_sst.sdt); + if(m_joints[i]->m_delete) + { + btAlignedFree(m_joints[i]); + m_joints.remove(m_joints[i--]); + } + } +} + +// +void btSoftBody::prepareClusters(int iterations) +{ +for(int i=0;iPrepare(m_sst.sdt,iterations); + } +} + + +// +void btSoftBody::solveClusters(btScalar sor) +{ +for(int i=0,ni=m_joints.size();iSolve(m_sst.sdt,sor); + } +} + +// +void btSoftBody::applyClusters(bool drift) +{ +BT_PROFILE("ApplyClusters"); +const btScalar f0=m_sst.sdt; +const btScalar f1=f0/2; +btAlignedObjectArray deltas; +btAlignedObjectArray weights; +deltas.resize(m_nodes.size(),btVector3(0,0,0)); +weights.resize(m_nodes.size(),0); +int i; + +if(drift) + { + for(i=0;im_x; + const btScalar q=c.m_masses[j]; + deltas[idx] += (v+cross(w,x-c.m_com))*q; + weights[idx] += q; + } + } + } + for(i=0;i0) m_nodes[i].m_x+=deltas[i]/weights[i]; + } +} + +// +void btSoftBody::dampClusters() +{ + int i; + +for(i=0;i0) + { + for(int j=0;j0) + { + const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com); + n.m_v += c.m_ndamping*(vx-n.m_v); + } + } + } + } +} + +// +void btSoftBody::Joint::Prepare(btScalar dt,int) +{ +m_bodies[0].activate(); +m_bodies[1].activate(); +} + +// +void btSoftBody::LJoint::Prepare(btScalar dt,int iterations) +{ +static const btScalar maxdrift=4; +Joint::Prepare(dt,iterations); +m_rpos[0] = m_bodies[0].xform()*m_refs[0]; +m_rpos[1] = m_bodies[1].xform()*m_refs[1]; +m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt; +m_rpos[0] -= m_bodies[0].xform().getOrigin(); +m_rpos[1] -= m_bodies[1].xform().getOrigin(); +m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0], + m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]); +if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } +m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor) +{ +const btVector3 va=m_bodies[0].velocity(m_rpos[0]); +const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); +const btVector3 vr=va-vb; +btSoftBody::Impulse impulse; +impulse.m_asVelocity = 1; +impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor; +m_bodies[0].applyImpulse(-impulse,m_rpos[0]); +m_bodies[1].applyImpulse( impulse,m_rpos[1]); +} + +// +void btSoftBody::LJoint::Terminate(btScalar dt) +{ +if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::AJoint::Prepare(btScalar dt,int iterations) +{ +static const btScalar maxdrift=SIMD_PI/16; +m_icontrol->Prepare(this); +Joint::Prepare(dt,iterations); +m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0]; +m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1]; +m_drift = NormalizeAny(cross(m_axis[1],m_axis[0])); +m_drift *= btMin(maxdrift,btAcos(Clamp(dot(m_axis[0],m_axis[1]),-1,+1))); +m_drift *= m_erp/dt; +m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia()); +if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } +m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor) +{ +const btVector3 va=m_bodies[0].angularVelocity(); +const btVector3 vb=m_bodies[1].angularVelocity(); +const btVector3 vr=va-vb; +const btScalar sp=dot(vr,m_axis[0]); +const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp); +btSoftBody::Impulse impulse; +impulse.m_asVelocity = 1; +impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor; +m_bodies[0].applyAImpulse(-impulse); +m_bodies[1].applyAImpulse( impulse); +} + +// +void btSoftBody::AJoint::Terminate(btScalar dt) +{ +if(m_split>0) + { + m_bodies[0].applyDAImpulse(-m_sdrift); + m_bodies[1].applyDAImpulse( m_sdrift); + } +} + +// +void btSoftBody::CJoint::Prepare(btScalar dt,int iterations) +{ +Joint::Prepare(dt,iterations); +const bool dodrift=(m_life==0); +m_delete=(++m_life)>m_maxlife; +if(dodrift) + { + m_drift=m_drift*m_erp/dt; + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift/=(btScalar)iterations; + } + else + { + m_drift=m_sdrift=btVector3(0,0,0); + } +} + +// +void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor) +{ +const btVector3 va=m_bodies[0].velocity(m_rpos[0]); +const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); +const btVector3 vrel=va-vb; +const btScalar rvac=dot(vrel,m_normal); +btSoftBody::Impulse impulse; +impulse.m_asVelocity = 1; +impulse.m_velocity = m_drift; +if(rvac<0) + { + const btVector3 iv=m_normal*rvac; + const btVector3 fv=vrel-iv; + impulse.m_velocity += iv+fv*m_friction; + } +impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor; +m_bodies[0].applyImpulse(-impulse,m_rpos[0]); +m_bodies[1].applyImpulse( impulse,m_rpos[1]); +} + +// +void btSoftBody::CJoint::Terminate(btScalar dt) +{ +if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::applyForces() +{ + BT_PROFILE("SoftBody applyForces"); + const btScalar dt=m_sst.sdt; + const btScalar kLF=m_cfg.kLF; + const btScalar kDG=m_cfg.kDG; + const btScalar kPR=m_cfg.kPR; + const btScalar kVC=m_cfg.kVC; + const bool as_lift=kLF>0; + const bool as_drag=kDG>0; + const bool as_pressure=kPR!=0; + const bool as_volume=kVC>0; + const bool as_aero= as_lift || + as_drag ; + const bool as_vaero= as_aero && + (m_cfg.aeromodel=btSoftBody::eAeroModel::F_TwoSided); + const bool use_medium= as_aero; + const bool use_volume= as_pressure || + as_volume ; + btScalar volume=0; + btScalar ivolumetp=0; + btScalar dvolumetv=0; + btSoftBody::sMedium medium; + if(use_volume) + { + volume = getVolume(); + ivolumetp = 1/btFabs(volume)*kPR; + dvolumetv = (m_pose.m_volume-volume)*kVC; + } + /* Per vertex forces */ + int i,ni; + + for(i=0,ni=m_nodes.size();i0) + { + if(use_medium) + { + EvaluateMedium(m_worldInfo,n.m_x,medium); + /* Aerodynamics */ + if(as_vaero) + { + const btVector3 rel_v=n.m_v-medium.m_velocity; + const btScalar rel_v2=rel_v.length2(); + if(rel_v2>SIMD_EPSILON) + { + btVector3 nrm=n.m_n; + /* Setup normal */ + switch(m_cfg.aeromodel) + { + case btSoftBody::eAeroModel::V_Point: + nrm=NormalizeAny(rel_v);break; + case btSoftBody::eAeroModel::V_TwoSided: + nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break; + } + const btScalar dvn=dot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = n.m_area*dvn*rel_v2/2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + ApplyClampedForce(n,force,dt); + } + } + } + } + /* Pressure */ + if(as_pressure) + { + n.m_f += n.m_n*(n.m_area*ivolumetp); + } + /* Volume */ + if(as_volume) + { + n.m_f += n.m_n*(n.m_area*dvolumetv); + } + } + } + /* Per face forces */ + for(i=0,ni=m_faces.size();im_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; + const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; + EvaluateMedium(m_worldInfo,x,medium); + const btVector3 rel_v=v-medium.m_velocity; + const btScalar rel_v2=rel_v.length2(); + if(rel_v2>SIMD_EPSILON) + { + btVector3 nrm=f.m_normal; + /* Setup normal */ + switch(m_cfg.aeromodel) + { + case btSoftBody::eAeroModel::F_TwoSided: + nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break; + } + const btScalar dvn=dot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = f.m_ra*dvn*rel_v2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + force /= 3; + for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + } + } + } + } +} + +// +void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti) +{ + const btScalar kAHR=psb->m_cfg.kAHR*kst; + const btScalar dt=psb->m_sst.sdt; + for(int i=0,ni=psb->m_anchors.size();im_anchors[i]; + const btTransform& t=a.m_body->getInterpolationWorldTransform(); + Node& n=*a.m_node; + const btVector3 wa=t*a.m_local; + const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; + const btVector3 impulse=a.m_c0*vr; + n.m_x+=impulse*a.m_c2; + a.m_body->applyImpulse(-impulse,a.m_c1); + } +} + +// +void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti) +{ + const btScalar dt=psb->m_sst.sdt; + const btScalar mrg=psb->getCollisionShape()->getMargin(); + for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; + const sCti& cti=c.m_cti; + const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt; + const btVector3 vb=c.m_node->m_x-c.m_node->m_q; + const btVector3 vr=vb-va; + const btScalar dn=dot(vr,cti.m_normal); + if(dn<=SIMD_EPSILON) + { + const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg); + const btVector3 fv=vr-cti.m_normal*dn; + const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst); + c.m_node->m_x-=impulse*c.m_c2; + c.m_cti.m_body->applyImpulse(impulse,c.m_c1); + } + } +} + +// +void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) +{ +for(int i=0,ni=psb->m_scontacts.size();im_scontacts[i]; + const btVector3& nr=c.m_normal; + Node& n=*c.m_node; + Face& f=*c.m_face; + const btVector3 p=BaryEval( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + c.m_weights); + const btVector3 q=BaryEval( f.m_n[0]->m_q, + f.m_n[1]->m_q, + f.m_n[2]->m_q, + c.m_weights); + const btVector3 vr=(n.m_x-n.m_q)-(p-q); + btVector3 corr(0,0,0); + if(dot(vr,nr)<0) + { + const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p)); + corr+=c.m_normal*j; + } + corr -= ProjectOnPlane(vr,nr)*c.m_friction; + n.m_x += corr*c.m_cfm[0]; + f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x()); + f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y()); + f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z()); + } +} + +// +void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) +{ + for(int i=0,ni=psb->m_links.size();im_links[i]; + if(l.m_c0>0) + { + Node& a=*l.m_n[0]; + Node& b=*l.m_n[1]; + const btVector3 del=b.m_x-a.m_x; + const btScalar len=del.length2(); + const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst; + const btScalar t=k*a.m_im; + a.m_x-=del*(k*a.m_im); + b.m_x+=del*(k*b.m_im); + } + } +} + +// +void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) +{ +for(int i=0,ni=psb->m_links.size();im_links[i]; + Node** n=l.m_n; + const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst; + n[0]->m_v+= l.m_c3*(j*n[0]->m_im); + n[1]->m_v-= l.m_c3*(j*n[1]->m_im); + } +} + +// +btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver) +{ +switch(solver) + { + case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors); + case ePSolver::Linear: return(&btSoftBody::PSolve_Links); + case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts); + case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts); + } +return(0); +} + +// +btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) +{ +switch(solver) + { + case eVSolver::Linear: return(&btSoftBody::VSolve_Links); + } +return(0); +} + +// +void btSoftBody::defaultCollisionHandler(btCollisionObject* pco) +{ +switch(m_cfg.collisions&fCollision::RVSmask) + { + case fCollision::SDF_RS: + { + btSoftColliders::CollideSDF_RS docollide; + btRigidBody* prb=btRigidBody::upcast(pco); + const btTransform wtr=prb->getInterpolationWorldTransform(); + const btTransform ctr=prb->getWorldTransform(); + const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length(); + const btScalar basemargin=getCollisionShape()->getMargin(); + btVector3 mins; + btVector3 maxs; + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(), + mins, + maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(basemargin,basemargin,basemargin)); + docollide.psb = this; + docollide.prb = prb; + docollide.dynmargin = basemargin+timemargin; + docollide.stamargin = basemargin; + btDbvt::collideTV(m_ndbvt.m_root,volume,docollide); + } + break; + case fCollision::CL_RS: + { + btSoftColliders::CollideCL_RS collider; + collider.Process(this,btRigidBody::upcast(pco)); + } + break; + } +} + +// +void btSoftBody::defaultCollisionHandler(btSoftBody* psb) +{ +const int cf=m_cfg.collisions&psb->m_cfg.collisions; +switch(cf&fCollision::SVSmask) + { + case fCollision::CL_SS: + { + btSoftColliders::CollideCL_SS docollide; + docollide.Process(this,psb); + } + break; + case fCollision::VF_SS: + { + btSoftColliders::CollideVF_SS docollide; + /* common */ + docollide.mrg= getCollisionShape()->getMargin()+ + psb->getCollisionShape()->getMargin(); + /* psb0 nodes vs psb1 faces */ + docollide.psb[0]=this; + docollide.psb[1]=psb; + btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + /* psb1 nodes vs psb0 faces */ + docollide.psb[0]=psb; + docollide.psb[1]=this; + btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + } + break; + } +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h new file mode 100644 index 00000000000..834199c668a --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -0,0 +1,810 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_H +#define _BT_SOFT_BODY_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btSparseSDF.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" + +class btBroadphaseInterface; +class btCollisionDispatcher; + +/* btSoftBodyWorldInfo */ +struct btSoftBodyWorldInfo +{ + btScalar air_density; + btScalar water_density; + btScalar water_offset; + btVector3 water_normal; + btBroadphaseInterface* m_broadphase; + btCollisionDispatcher* m_dispatcher; + btVector3 m_gravity; + btSparseSdf<3> m_sparsesdf; +}; + + +/// btSoftBody is work-in-progress +class btSoftBody : public btCollisionObject +{ +public: + // + // Enumerations + // + + ///eAeroModel + struct eAeroModel { enum _ { + V_Point, ///Vertex normals are oriented toward velocity + V_TwoSided, ///Vertex normals are fliped to match velocity + V_OneSided, ///Vertex normals are taken as it is + F_TwoSided, ///Face normals are fliped to match velocity + F_OneSided, ///Face normals are taken as it is + END + };}; + + ///eVSolver : velocities solvers + struct eVSolver { enum _ { + Linear, ///Linear solver + END + };}; + + ///ePSolver : positions solvers + struct ePSolver { enum _ { + Linear, ///Linear solver + Anchors, ///Anchor solver + RContacts, ///Rigid contacts solver + SContacts, ///Soft contacts solver + END + };}; + + ///eSolverPresets + struct eSolverPresets { enum _ { + Positions, + Velocities, + Default = Positions, + END + };}; + + ///eFeature + struct eFeature { enum _ { + None, + Node, + Link, + Face, + END + };}; + + typedef btAlignedObjectArray tVSolverArray; + typedef btAlignedObjectArray tPSolverArray; + + // + // Flags + // + + ///fCollision + struct fCollision { enum _ { + RVSmask = 0x000f, ///Rigid versus soft mask + SDF_RS = 0x0001, ///SDF based rigid vs soft + CL_RS = 0x0002, ///Cluster vs convex rigid vs soft + + SVSmask = 0x00f0, ///Rigid versus soft mask + VF_SS = 0x0010, ///Vertex vs face soft vs soft handling + CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling + /* presets */ + Default = SDF_RS, + END + };}; + + ///fMaterial + struct fMaterial { enum _ { + DebugDraw = 0x0001, /// Enable debug draw + /* presets */ + Default = DebugDraw, + END + };}; + + // + // API Types + // + + /* sRayCast */ + struct sRayCast + { + btSoftBody* body; /// soft body + eFeature::_ feature; /// feature type + int index; /// feature index + btScalar time; /// time of impact (rayorg+raydir*time) + }; + + /* ImplicitFn */ + struct ImplicitFn + { + virtual btScalar Eval(const btVector3& x)=0; + }; + + // + // Internal types + // + + typedef btAlignedObjectArray tScalarArray; + typedef btAlignedObjectArray tVector3Array; + + /* sCti is Softbody contact info */ + struct sCti + { + btRigidBody* m_body; /* Rigid body */ + btVector3 m_normal; /* Outward normal */ + btScalar m_offset; /* Offset from origin */ + }; + + /* sMedium */ + struct sMedium + { + btVector3 m_velocity; /* Velocity */ + btScalar m_pressure; /* Pressure */ + btScalar m_density; /* Density */ + }; + + /* Base type */ + struct Element + { + void* m_tag; // User data + Element() : m_tag(0) {} + }; + /* Material */ + struct Material : Element + { + btScalar m_kLST; // Linear stiffness coefficient [0,1] + btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] + btScalar m_kVST; // Volume stiffness coefficient [0,1] + int m_flags; // Flags + }; + + /* Feature */ + struct Feature : Element + { + Material* m_material; // Material + }; + /* Node */ + struct Node : Feature + { + btVector3 m_x; // Position + btVector3 m_q; // Previous step position + btVector3 m_v; // Velocity + btVector3 m_f; // Force accumulator + btVector3 m_n; // Normal + btScalar m_im; // 1/mass + btScalar m_area; // Area + btDbvtNode* m_leaf; // Leaf data + int m_battach:1; // Attached + }; + /* Link */ + struct Link : Feature + { + Node* m_n[2]; // Node pointers + btScalar m_rl; // Rest length + int m_bbending:1; // Bending link + btScalar m_c0; // (ima+imb)*kLST + btScalar m_c1; // rl^2 + btScalar m_c2; // |gradient|^2/c0 + btVector3 m_c3; // gradient + }; + /* Face */ + struct Face : Feature + { + Node* m_n[3]; // Node pointers + btVector3 m_normal; // Normal + btScalar m_ra; // Rest area + btDbvtNode* m_leaf; // Leaf data + }; + /* RContact */ + struct RContact + { + sCti m_cti; // Contact infos + Node* m_node; // Owner node + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + btScalar m_c3; // Friction + btScalar m_c4; // Hardness + }; + /* SContact */ + struct SContact + { + Node* m_node; // Node + Face* m_face; // Face + btVector3 m_weights; // Weigths + btVector3 m_normal; // Normal + btScalar m_margin; // Margin + btScalar m_friction; // Friction + btScalar m_cfm[2]; // Constraint force mixing + }; + /* Anchor */ + struct Anchor + { + Node* m_node; // Node pointer + btVector3 m_local; // Anchor position in body space + btRigidBody* m_body; // Body + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + }; + /* Note */ + struct Note : Element + { + const char* m_text; // Text + btVector3 m_offset; // Offset + int m_rank; // Rank + Node* m_nodes[4]; // Nodes + btScalar m_coords[4]; // Coordinates + }; + /* Pose */ + struct Pose + { + bool m_bvolume; // Is valid + bool m_bframe; // Is frame + btScalar m_volume; // Rest volume + tVector3Array m_pos; // Reference positions + tScalarArray m_wgh; // Weights + btVector3 m_com; // COM + btMatrix3x3 m_rot; // Rotation + btMatrix3x3 m_scl; // Scale + btMatrix3x3 m_aqq; // Base scaling + }; + /* Cluster */ + struct Cluster + { + btAlignedObjectArray m_nodes; + tScalarArray m_masses; + tVector3Array m_framerefs; + btTransform m_framexform; + btScalar m_idmass; + btScalar m_imass; + btMatrix3x3 m_locii; + btMatrix3x3 m_invwi; + btVector3 m_com; + btVector3 m_vimpulses[2]; + btVector3 m_dimpulses[2]; + int m_nvimpulses; + int m_ndimpulses; + btVector3 m_lv; + btVector3 m_av; + btDbvtNode* m_leaf; + btScalar m_ndamping; + btScalar m_ldamping; + btScalar m_adamping; + btScalar m_matching; + bool m_collide; + Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {} + }; + /* Impulse */ + struct Impulse + { + btVector3 m_velocity; + btVector3 m_drift; + int m_asVelocity:1; + int m_asDrift:1; + Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} + Impulse operator -() const + { + Impulse i=*this; + i.m_velocity=-i.m_velocity; + i.m_drift=-i.m_drift; + return(i); + } + Impulse operator*(btScalar x) const + { + Impulse i=*this; + i.m_velocity*=x; + i.m_drift*=x; + return(i); + } + }; + /* Body */ + struct Body + { + Cluster* m_soft; + btRigidBody* m_rigid; + Body() : m_soft(0),m_rigid(0) {} + Body(Cluster* p) : m_soft(p),m_rigid(0) {} + Body(btRigidBody* p) : m_soft(0),m_rigid(p) {} + void activate() const + { + if(m_rigid) m_rigid->activate(); + } + const btMatrix3x3& invWorldInertia() const + { + static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); + if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); + if(m_soft) return(m_soft->m_invwi); + return(iwi); + } + btScalar invMass() const + { + if(m_rigid) return(m_rigid->getInvMass()); + if(m_soft) return(m_soft->m_imass); + return(0); + } + const btTransform& xform() const + { + static const btTransform identity=btTransform::getIdentity(); + if(m_rigid) return(m_rigid->getInterpolationWorldTransform()); + if(m_soft) return(m_soft->m_framexform); + return(identity); + } + btVector3 linearVelocity() const + { + if(m_rigid) return(m_rigid->getLinearVelocity()); + if(m_soft) return(m_soft->m_lv); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity(const btVector3& rpos) const + { + if(m_rigid) return(cross(m_rigid->getAngularVelocity(),rpos)); + if(m_soft) return(cross(m_soft->m_av,rpos)); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity() const + { + if(m_rigid) return(m_rigid->getAngularVelocity()); + if(m_soft) return(m_soft->m_av); + return(btVector3(0,0,0)); + } + btVector3 velocity(const btVector3& rpos) const + { + return(linearVelocity()+angularVelocity(rpos)); + } + void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); + } + void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); + } + void applyImpulse(const Impulse& impulse,const btVector3& rpos) const + { + if(impulse.m_asVelocity) applyVImpulse(impulse.m_velocity,rpos); + if(impulse.m_asDrift) applyDImpulse(impulse.m_drift,rpos); + } + void applyVAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); + } + void applyDAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); + } + void applyAImpulse(const Impulse& impulse) const + { + if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); + if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); + } + void applyDCImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyCentralImpulse(impulse); + if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); + } + }; + /* Joint */ + struct Joint + { + struct eType { enum _ { + Linear, + Angular, + Contact, + };}; + struct Specs + { + Specs() : erp(1),cfm(1),split(1) {} + btScalar erp; + btScalar cfm; + btScalar split; + }; + Body m_bodies[2]; + btVector3 m_refs[2]; + btScalar m_cfm; + btScalar m_erp; + btScalar m_split; + btVector3 m_drift; + btVector3 m_sdrift; + btMatrix3x3 m_massmatrix; + bool m_delete; + virtual ~Joint() {} + Joint() : m_delete(false) {} + virtual void Prepare(btScalar dt,int iterations); + virtual void Solve(btScalar dt,btScalar sor)=0; + virtual void Terminate(btScalar dt)=0; + virtual eType::_ Type() const=0; + }; + /* LJoint */ + struct LJoint : Joint + { + struct Specs : Joint::Specs + { + btVector3 position; + }; + btVector3 m_rpos[2]; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Linear); } + }; + /* AJoint */ + struct AJoint : Joint + { + struct IControl + { + virtual void Prepare(AJoint*) {} + virtual btScalar Speed(AJoint*,btScalar current) { return(current); } + static IControl* Default() { static IControl def;return(&def); } + }; + struct Specs : Joint::Specs + { + Specs() : icontrol(IControl::Default()) {} + btVector3 axis; + IControl* icontrol; + }; + btVector3 m_axis[2]; + IControl* m_icontrol; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Angular); } + }; + /* CJoint */ + struct CJoint : Joint + { + int m_life; + int m_maxlife; + btVector3 m_rpos[2]; + btVector3 m_normal; + btScalar m_friction; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Contact); } + }; + /* Config */ + struct Config + { + eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) + btScalar kVCF; // Velocities correction factor (Baumgarte) + btScalar kDP; // Damping coefficient [0,1] + btScalar kDG; // Drag coefficient [0,+inf] + btScalar kLF; // Lift coefficient [0,+inf] + btScalar kPR; // Pressure coefficient [-inf,+inf] + btScalar kVC; // Volume conversation coefficient [0,+inf] + btScalar kDF; // Dynamic friction coefficient [0,1] + btScalar kMT; // Pose matching coefficient [0,1] + btScalar kCHR; // Rigid contacts hardness [0,1] + btScalar kKHR; // Kinetic contacts hardness [0,1] + btScalar kSHR; // Soft contacts hardness [0,1] + btScalar kAHR; // Anchors hardness [0,1] + btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) + btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only) + btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) + btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar maxvolume; // Maximum volume ratio for pose + btScalar timescale; // Time scale + int viterations; // Velocities solver iterations + int piterations; // Positions solver iterations + int diterations; // Drift solver iterations + int citerations; // Cluster solver iterations + int collisions; // Collisions flags + tVSolverArray m_vsequence; // Velocity solvers sequence + tPSolverArray m_psequence; // Position solvers sequence + tPSolverArray m_dsequence; // Drift solvers sequence + }; + /* SolverState */ + struct SolverState + { + btScalar sdt; // dt*timescale + btScalar isdt; // 1/sdt + btScalar velmrg; // velocity margin + btScalar radmrg; // radial margin + btScalar updmrg; // Update margin + }; + /* RayCaster */ + struct RayCaster : btDbvt::ICollide + { + btVector3 o; + btVector3 d; + btScalar mint; + Face* face; + int tests; + RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt); + void Process(const btDbvtNode* leaf); + static inline btScalar rayTriangle(const btVector3& org, + const btVector3& dir, + const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar maxt=SIMD_INFINITY); + }; + + // + // Typedef's + // + + typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); + typedef void (*vsolver_t)(btSoftBody*,btScalar); + typedef btAlignedObjectArray tClusterArray; + typedef btAlignedObjectArray tNoteArray; + typedef btAlignedObjectArray tNodeArray; + typedef btAlignedObjectArray tLeafArray; + typedef btAlignedObjectArray tLinkArray; + typedef btAlignedObjectArray tFaceArray; + typedef btAlignedObjectArray tAnchorArray; + typedef btAlignedObjectArray tRContactArray; + typedef btAlignedObjectArray tSContactArray; + typedef btAlignedObjectArray tMaterialArray; + typedef btAlignedObjectArray tJointArray; + typedef btAlignedObjectArray tSoftBodyArray; + + // + // Fields + // + + Config m_cfg; // Configuration + SolverState m_sst; // Solver state + Pose m_pose; // Pose + void* m_tag; // User data + btSoftBodyWorldInfo* m_worldInfo; // World info + tNoteArray m_notes; // Notes + tNodeArray m_nodes; // Nodes + tLinkArray m_links; // Links + tFaceArray m_faces; // Faces + tAnchorArray m_anchors; // Anchors + tRContactArray m_rcontacts; // Rigid contacts + tSContactArray m_scontacts; // Soft contacts + tJointArray m_joints; // Joints + tMaterialArray m_materials; // Materials + btScalar m_timeacc; // Time accumulator + btVector3 m_bounds[2]; // Spatial bounds + bool m_bUpdateRtCst; // Update runtime constants + btDbvt m_ndbvt; // Nodes tree + btDbvt m_fdbvt; // Faces tree + btDbvt m_cdbvt; // Clusters tree + tClusterArray m_clusters; // Clusters + + // + // Api + // + + /* ctor */ + btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, + const btVector3* x, + const btScalar* m); + /* dtor */ + virtual ~btSoftBody(); + /* Check for existing link */ + bool checkLink( int node0, + int node1) const; + bool checkLink( const Node* node0, + const Node* node1) const; + /* Check for existring face */ + bool checkFace( int node0, + int node1, + int node2) const; + /* Append material */ + Material* appendMaterial(); + /* Append note */ + void appendNote( const char* text, + const btVector3& o, + const btVector4& c=btVector4(1,0,0,0), + Node* n0=0, + Node* n1=0, + Node* n2=0, + Node* n3=0); + void appendNote( const char* text, + const btVector3& o, + Node* feature); + void appendNote( const char* text, + const btVector3& o, + Link* feature); + void appendNote( const char* text, + const btVector3& o, + Face* feature); + /* Append node */ + void appendNode( const btVector3& x,btScalar m); + /* Append link */ + void appendLink(int model=-1,Material* mat=0); + void appendLink( int node0, + int node1, + Material* mat=0, + bool bcheckexist=false); + void appendLink( Node* node0, + Node* node1, + Material* mat=0, + bool bcheckexist=false); + /* Append face */ + void appendFace(int model=-1,Material* mat=0); + void appendFace( int node0, + int node1, + int node2, + Material* mat=0); + /* Append anchor */ + void appendAnchor( int node, + btRigidBody* body); + /* Append linear joint */ + void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); + void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); + void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); + /* Append linear joint */ + void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); + void appendAngularJoint(const AJoint::Specs& specs,Body body=Body()); + void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); + /* Add force (or gravity) to the entire body */ + void addForce( const btVector3& force); + /* Add force (or gravity) to a node of the body */ + void addForce( const btVector3& force, + int node); + /* Add velocity to the entire body */ + void addVelocity( const btVector3& velocity); + /* Add velocity to a node of the body */ + void addVelocity( const btVector3& velocity, + int node); + /* Set mass */ + void setMass( int node, + btScalar mass); + /* Get mass */ + btScalar getMass( int node) const; + /* Get total mass */ + btScalar getTotalMass() const; + /* Set total mass (weighted by previous masses) */ + void setTotalMass( btScalar mass, + bool fromfaces=false); + /* Set total density */ + void setTotalDensity(btScalar density); + /* Transform */ + void transform( const btTransform& trs); + /* Translate */ + void translate( const btVector3& trs); + /* Rotate */ + void rotate( const btQuaternion& rot); + /* Scale */ + void scale( const btVector3& scl); + /* Set current state as pose */ + void setPose( bool bvolume, + bool bframe); + /* Return the volume */ + btScalar getVolume() const; + /* Cluster count */ + int clusterCount() const; + /* Cluster center of mass */ + static btVector3 clusterCom(const Cluster* cluster); + btVector3 clusterCom(int cluster) const; + /* Cluster velocity at rpos */ + static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); + /* Cluster impulse */ + static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); + static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); + static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); + /* Generate bending constraints based on distance in the adjency graph */ + int generateBendingConstraints( int distance, + Material* mat=0); + /* Randomize constraints to reduce solver bias */ + void randomizeConstraints(); + /* Generate clusters (K-mean) */ + int generateClusters(int k,int maxiterations=8192); + /* Refine */ + void refine(ImplicitFn* ifn,btScalar accurary,bool cut); + /* CutLink */ + bool cutLink(int node0,int node1,btScalar position); + bool cutLink(const Node* node0,const Node* node1,btScalar position); + /* Ray casting */ + bool rayCast(const btVector3& org, + const btVector3& dir, + sRayCast& results, + btScalar maxtime=SIMD_INFINITY); + /* Solver presets */ + void setSolver(eSolverPresets::_ preset); + /* predictMotion */ + void predictMotion(btScalar dt); + /* solveConstraints */ + void solveConstraints(); + /* staticSolve */ + void staticSolve(int iterations); + /* solveCommonConstraints */ + static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); + /* solveClusters */ + static void solveClusters(const btAlignedObjectArray& bodies); + /* integrateMotion */ + void integrateMotion(); + /* defaultCollisionHandlers */ + void defaultCollisionHandler(btCollisionObject* pco); + void defaultCollisionHandler(btSoftBody* psb); + + // + // Cast + // + + static const btSoftBody* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (const btSoftBody*)colObj; + return 0; + } + static btSoftBody* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (btSoftBody*)colObj; + return 0; + } + + // + // ::btCollisionObject + // + + virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_bounds[0]; + aabbMax = m_bounds[1]; + } + // + // Private + // + void pointersToIndices(); + void indicesToPointers(const int* map=0); + int rayCast(const btVector3& org,const btVector3& dir, + btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; + void initializeFaceTree(); + btVector3 evaluateCom() const; + bool checkContact(btRigidBody* prb,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; + void updateNormals(); + void updateBounds(); + void updatePose(); + void updateConstants(); + void initializeClusters(); + void updateClusters(); + void cleanupClusters(); + void prepareClusters(int iterations); + void solveClusters(btScalar sor); + void applyClusters(bool drift); + void dampClusters(); + void applyForces(); + static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti); + static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); + static void VSolve_Links(btSoftBody* psb,btScalar kst); + static psolver_t getSolver(ePSolver::_ solver); + static vsolver_t getSolver(eVSolver::_ solver); + +}; + + + +#endif //_BT_SOFT_BODY_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp new file mode 100644 index 00000000000..5e3211ed73b --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -0,0 +1,410 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" + + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletSoftBody/btSoftBody.h" + +#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.3) + +btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +: btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) +{ +} + + + +btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() +{ +} + + + +btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): + m_dispatcher(dispatcher), + m_dispatchInfoPtr(0) +{ + m_softBody = (btSoftBody*) (isSwapped? body1:body0); + m_triBody = isSwapped? body0:body1; + + // + // create the manifold from the dispatcher 'manifold pool' + // +// m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); + + clearCache(); +} + +btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() +{ + clearCache(); +// m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btSoftBodyTriangleCallback::clearCache() +{ + //m_dispatcher->clearManifold(m_manifoldPtr); +}; + + +static const int maxParts = 1; +static const int maxTriangleIndex = 100*100; + +btCollisionShape* shapeCache[maxParts][maxTriangleIndex]; + + +void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + static bool hackedFirst = true; + if (hackedFirst) + { + hackedFirst = false; + int i,j; + for (i=0;i(m_triBody); + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) + { + btVector3 color(255,255,0); + btTransform& tr = ob->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + + //btVector3 center = triangle[0] + triangle[1]+triangle[2]; + //center *= btScalar(0.333333); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); + + } + + if (shapeCache[partId][triangleIndex]) + { + btCollisionShape* tm = shapeCache[partId][triangleIndex]; + + //copy over user pointers to temporary shape + tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); + + colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape); + return; + } + + //aabb filter is already applied! + + + + + + + + + //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); + +// if (m_softBody->getCollisionShape()->getShapeType()== + { +// btVector3 other; + btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + normal.normalize(); + normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; +// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; +// other+=normal*22.f; + btVector3 pts[6] = {triangle[0]+normal, + triangle[1]+normal, + triangle[2]+normal, + triangle[0]-normal, + triangle[1]-normal, + triangle[2]-normal}; + + btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6); + + +// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); + + //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + // tm.setMargin(m_collisionMarginTriangle); + + //copy over user pointers to temporary shape + tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); + ///this should use the btDispatcher, so the actual registered algorithm is used + // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); + + //m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex); + // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); +// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape ); +// delete tm; + + shapeCache[partId][triangleIndex] = tm; + + } + + + +} + + + +void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle; + m_resultOut = resultOut; + + //recalc aabbs +// btTransform softbodyInTriangleSpace; +// softbodyInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_softBody->getWorldTransform(); +// btCollisionShape* convexShape = static_cast(m_convexBody->getCollisionShape()); + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; + m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); + + btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); + btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5); + + btTransform triInverse = m_triBody->getWorldTransform().inverse(); + + btMatrix3x3 abs_b = triInverse.getBasis().absolute(); + btPoint3 center = softBodyCenter + triInverse.getOrigin(); + + btVector3 extent = btVector3(abs_b[0].dot(halfExtents), + abs_b[1].dot(halfExtents), + abs_b[2].dot(halfExtents)); +// extent += btVector3(getMargin(),getMargin(),getMargin()); + + m_aabbMin = center - extent; + m_aabbMax = center + extent; + + btScalar extraMargin = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); + btVector3 extra(extraMargin,extraMargin,extraMargin); + + m_aabbMax += extra; + m_aabbMin -= extra; + +/* btVector3 extra(2,2,2); + m_aabbMin = aabbWorldSpaceMin-extra; + m_aabbMax = aabbWorldSpaceMax+extra; +*/ + +} + +void btSoftBodyConcaveCollisionAlgorithm::clearCache() +{ + m_btSoftBodyTriangleCallback.clearCache(); + +} + +void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + btCollisionObject* convexBody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + if (triBody->getCollisionShape()->isConcave()) + { + + + btCollisionObject* triOb = triBody; + btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); + + // if (convexBody->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + +// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); + + //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. + //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + +// m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); + + + concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); + + // resultOut->refreshContactPoints(); + + } + + } + +} + + +btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h new file mode 100644 index 00000000000..adb91329a4c --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h @@ -0,0 +1,118 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#define SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btSoftBody; + +///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called. +class btSoftBodyTriangleCallback : public btTriangleCallback +{ + btSoftBody* m_softBody; + btCollisionObject* m_triBody; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + btManifoldResult* m_resultOut; + + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + +public: +int m_triangleCount; + +// btPersistentManifold* m_manifoldPtr; + + btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual ~btSoftBodyTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + SIMD_FORCE_INLINE const btVector3& getAabbMin() const + { + return m_aabbMin; + } + SIMD_FORCE_INLINE const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes. +class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm +{ + + bool m_isSwapped; + + btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback; + +public: + + btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btSoftBodyConcaveCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp new file mode 100644 index 00000000000..d9919967233 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -0,0 +1,653 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBodyHelpers.cpp by Nathanael Presson + +#include "btSoftBodyInternals.h" +#include +#include +#include "btSoftBodyHelpers.h" +#include "LinearMath/btConvexHull.h" + +// +static void drawVertex( btIDebugDraw* idraw, + const btVector3& x,btScalar s,const btVector3& c) + { + idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); + idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); + idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); + } + +// +static void drawBox( btIDebugDraw* idraw, + const btVector3& mins, + const btVector3& maxs, + const btVector3& color) +{ +const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), + btVector3(maxs.x(),mins.y(),mins.z()), + btVector3(maxs.x(),maxs.y(),mins.z()), + btVector3(mins.x(),maxs.y(),mins.z()), + btVector3(mins.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),maxs.y(),maxs.z()), + btVector3(mins.x(),maxs.y(),maxs.z())}; +idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); +idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); +idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); +idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); +idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); +idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); +} + +// +static void drawTree( btIDebugDraw* idraw, + const btDbvtNode* node, + int depth, + const btVector3& ncolor, + const btVector3& lcolor, + int mindepth, + int maxdepth) +{ +if(node) + { + if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); + } + if(depth>=mindepth) + { + const btScalar scl=(btScalar)(node->isinternal()?1:1); + const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; + const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; + drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); + } + } +} + +// +template +static inline T sum(const btAlignedObjectArray& items) +{ +T v; +if(items.size()) + { + v=items[0]; + for(int i=1,ni=items.size();i +static inline void add(btAlignedObjectArray& items,const Q& value) +{ +for(int i=0,ni=items.size();i +static inline void mul(btAlignedObjectArray& items,const Q& value) +{ +for(int i=0,ni=items.size();i +static inline T average(const btAlignedObjectArray& items) +{ +const btScalar n=(btScalar)(items.size()>0?items.size():1); +return(sum(items)/n); +} + +// +static inline btScalar tetravolume(const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(dot(a,cross(b,c))); +} + +// +#if 0 +static btVector3 stresscolor(btScalar stress) + { + static const btVector3 spectrum[]= { btVector3(1,0,1), + btVector3(0,0,1), + btVector3(0,1,1), + btVector3(0,1,0), + btVector3(1,1,0), + btVector3(1,0,0), + btVector3(1,0,0)}; + static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; + static const btScalar one=1; + stress=btMax(0,btMin(1,stress))*ncolors; + const int sel=(int)stress; + const btScalar frc=stress-sel; + return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); + } +#endif + +// +void btSoftBodyHelpers::Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags) +{ + const btScalar scl=(btScalar)0.1; + const btScalar nscl=scl*5; + const btVector3 lcolor=btVector3(0,0,0); + const btVector3 ncolor=btVector3(1,1,1); + const btVector3 ccolor=btVector3(1,0,0); + int i,j,nj; + + /* Nodes */ + if(0!=(drawflags&fDrawFlags::Nodes)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); + idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); + idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); + } + } + /* Links */ + if(0!=(drawflags&fDrawFlags::Links)) + { + for(i=0;im_links.size();++i) + { + const btSoftBody::Link& l=psb->m_links[i]; + if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); + } + } + /* Normals */ + if(0!=(drawflags&fDrawFlags::Normals)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 d=n.m_n*nscl; + idraw->drawLine(n.m_x,n.m_x+d,ncolor); + idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); + } + } + /* Contacts */ + if(0!=(drawflags&fDrawFlags::Contacts)) + { + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + for(i=0;im_rcontacts.size();++i) + { + const btSoftBody::RContact& c=psb->m_rcontacts[i]; + const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* + (dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); + const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); + const btVector3 y=cross(x,c.m_cti.m_normal).normalized(); + idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); + idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); + idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); + } + } + /* Anchors */ + if(0!=(drawflags&fDrawFlags::Anchors)) + { + for(i=0;im_anchors.size();++i) + { + const btSoftBody::Anchor& a=psb->m_anchors[i]; + const btVector3 q=a.m_body->getWorldTransform()*a.m_local; + drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); + drawVertex(idraw,q,0.25,btVector3(0,1,0)); + idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); + } + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + if(n.m_im<=0) + { + drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); + } + } + } + /* Faces */ + if(0!=(drawflags&fDrawFlags::Faces)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col(0,(btScalar)0.7,0); + for(i=0;im_faces.size();++i) + { + const btSoftBody::Face& f=psb->m_faces[i]; + if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2])/3; + idraw->drawTriangle((x[0]-c)*scl+c, + (x[1]-c)*scl+c, + (x[2]-c)*scl+c, + col,alp); + } + } + /* Clusters */ + if(0!=(drawflags&fDrawFlags::Clusters)) + { + srand(1806); + for(i=0;im_clusters.size();++i) + { + if(psb->m_clusters[i]->m_collide) + { + btVector3 color( rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX); + color=color.normalized()*0.75; + btAlignedObjectArray vertices; + vertices.resize(psb->m_clusters[i]->m_nodes.size()); + for(j=0,nj=vertices.size();jm_clusters[i]->m_nodes[j]->m_x; + } + HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); + HullResult hres; + HullLibrary hlib; + hdsc.mMaxVertices=vertices.size(); + hlib.CreateConvexHull(hdsc,hres); + const btVector3 center=average(hres.m_OutputVertices); + add(hres.m_OutputVertices,-center); + mul(hres.m_OutputVertices,(btScalar)1); + add(hres.m_OutputVertices,center); + for(j=0;j<(int)hres.mNumFaces;++j) + { + const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]}; + idraw->drawTriangle(hres.m_OutputVertices[idx[0]], + hres.m_OutputVertices[idx[1]], + hres.m_OutputVertices[idx[2]], + color,1); + } + hlib.ReleaseResult(hres); + } + /* Velocities */ + #if 0 + for(int j=0;jm_clusters[i].m_nodes.size();++j) + { + const btSoftBody::Cluster& c=psb->m_clusters[i]; + const btVector3 r=c.m_nodes[j]->m_x-c.m_com; + const btVector3 v=c.m_lv+cross(c.m_av,r); + idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0)); + } + #endif + /* Frame */ + btSoftBody::Cluster& c=*psb->m_clusters[i]; + idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0)); + idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0)); + idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1)); + } + } + /* Notes */ + if(0!=(drawflags&fDrawFlags::Notes)) + { + for(i=0;im_notes.size();++i) + { + const btSoftBody::Note& n=psb->m_notes[i]; + btVector3 p=n.m_offset; + for(int j=0;jm_x*n.m_coords[j]; + } + idraw->draw3dText(p,n.m_text); + } + } + /* Node tree */ + if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw); + /* Face tree */ + if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw); + /* Cluster tree */ + if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw); + /* Joints */ + if(0!=(drawflags&fDrawFlags::Joints)) + { + for(i=0;im_joints.size();++i) + { + const btSoftBody::Joint* pj=psb->m_joints[i]; + switch(pj->Type()) + { + case btSoftBody::Joint::eType::Linear: + { + const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj; + const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1]; + idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0)); + idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1)); + drawVertex(idraw,a0,0.25,btVector3(1,1,0)); + drawVertex(idraw,a1,0.25,btVector3(0,1,1)); + } + break; + case btSoftBody::Joint::eType::Angular: + { + const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj; + const btVector3 o0=pj->m_bodies[0].xform().getOrigin(); + const btVector3 o1=pj->m_bodies[1].xform().getOrigin(); + const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1]; + idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0)); + idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0)); + idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1)); + idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1)); + } + } + } + } +} + +// +void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool /*stress*/) +{ + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + char text[2048]={0}; + char buff[1024]; + if(masses) + { + sprintf(buff," M(%.2f)",1/n.m_im); + strcat(text,buff); + } + if(areas) + { + sprintf(buff," A(%.2f)",n.m_area); + strcat(text,buff); + } + if(text[0]) idraw->draw3dText(n.m_x,text); + } +} + +// +void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw) +{ + if(psb->m_pose.m_bframe) + { + static const btScalar ascl=10; + static const btScalar nscl=(btScalar)0.1; + const btVector3 com=psb->m_pose.m_com; + const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; + const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); + const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); + const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); + idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); + idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); + idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); + for(int i=0;im_pose.m_pos.size();++i) + { + const btVector3 x=com+trs*psb->m_pose.m_pos[i]; + drawVertex(idraw,x,nscl,btVector3(1,0,1)); + } + } +} + +// +btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, + const btVector3& to, + int res, + int fixeds) +{ + /* Create nodes */ + const int r=res+2; + btVector3* x=new btVector3[r]; + btScalar* m=new btScalar[r]; + int i; + + for(i=0;isetMass(0,0); + if(fixeds&2) psb->setMass(r-1,0); + delete[] x; + delete[] m; + /* Create links */ + for(i=1;iappendLink(i-1,i); + } + /* Finished */ + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags) +{ +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + int iy; + + for(iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + delete[] x; + delete[] m; + /* Create links and faces */ + for(iy=0;iyappendLink(idx,IDX(ix+1,iy)); + if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); + if(mdx&&mdy) + { + if((ix+iy)&1) + { + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); + } + } + else + { + psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); + psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); + } + } + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, + const btVector3& radius, + int res) +{ + struct Hammersley + { + static void Generate(btVector3* x,int n) + { + for(int i=0;i>=1) if(j&1) t+=p; + btScalar w=2*t-1; + btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; + btScalar s=btSqrt(1-w*w); + *x++=btVector3(s*btCos(a),s*btSin(a),w); + } + } + }; + btAlignedObjectArray vtx; + vtx.resize(3+res); + Hammersley::Generate(&vtx[0],vtx.size()); + for(int i=0;i chks; + btAlignedObjectArray vtx; + chks.resize(maxidx*maxidx,false); + vtx.resize(maxidx); + for(i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); + } + } +#undef IDX + psb->appendFace(idx[0],idx[1],idx[2]); + } + psb->randomizeConstraints(); + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, + int nvertices) +{ + HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); + HullResult hres; + HullLibrary hlib;/*??*/ + hdsc.mMaxVertices=nvertices; + hlib.CreateConvexHull(hdsc,hres); + btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0],0); + for(int i=0;i<(int)hres.mNumFaces;++i) + { + const int idx[]={ hres.m_Indices[i*3+0], + hres.m_Indices[i*3+1], + hres.m_Indices[i*3+2]}; + if(idx[0]appendLink( idx[0],idx[1]); + if(idx[1]appendLink( idx[1],idx[2]); + if(idx[2]appendLink( idx[2],idx[0]); + psb->appendFace(idx[0],idx[1],idx[2]); + } + hlib.ReleaseResult(hres); + psb->randomizeConstraints(); + return(psb); +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h new file mode 100644 index 00000000000..e9c6cb20657 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_BODY_HELPERS_H +#define SOFT_BODY_HELPERS_H + +#include "btSoftBody.h" + +// +// Helpers +// + +/* fDrawFlags */ +struct fDrawFlags { enum _ { + Nodes = 0x0001, + Links = 0x0002, + Faces = 0x0004, + Tetras = 0x0008, + Normals = 0x0010, + Contacts = 0x0020, + Anchors = 0x0040, + Notes = 0x0080, + Clusters = 0x0100, + NodeTree = 0x0200, + FaceTree = 0x0400, + ClusterTree = 0x0800, + Joints = 0x1000, + /* presets */ + Std = Links+Faces+Tetras+Anchors+Notes+Joints, + StdTetra = Std-Faces+Tetras, +};}; + +struct btSoftBodyHelpers +{ + /* Draw body */ + static void Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags=fDrawFlags::Std); + /* Draw body infos */ + static void DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool stress); + /* Draw node tree */ + static void DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw face tree */ + static void DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw cluster tree */ + static void DrawClusterTree(btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw rigid frame */ + static void DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw); + /* Create a rope */ + static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, + const btVector3& from, + const btVector3& to, + int res, + int fixeds); + /* Create a patch */ + static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags); + /* Create an ellipsoid */ + static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, + const btVector3& center, + const btVector3& radius, + int res); + /* Create from trimesh */ + static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, + const btScalar* vertices, + const int* triangles, + int ntriangles); + /* Create from convex-hull */ + static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, + const btVector3* vertices, + int nvertices); +}; + +#endif //SOFT_BODY_HELPERS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h new file mode 100644 index 00000000000..1a7be2cb840 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h @@ -0,0 +1,896 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_INTERNALS_H +#define _BT_SOFT_BODY_INTERNALS_H + +#include "btSoftBody.h" + +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +// +// btSymMatrix +// +template +struct btSymMatrix +{ + btSymMatrix() : dim(0) {} + btSymMatrix(int n,const T& init=T()) { resize(n,init); } +void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); } +int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r store; +int dim; +}; + +// +// btSoftBodyCollisionShape +// +class btSoftBodyCollisionShape : public btConcaveShape +{ +public: + btSoftBody* m_body; + + btSoftBodyCollisionShape(btSoftBody* backptr) + { + m_body=backptr; + } + + virtual ~btSoftBodyCollisionShape() + { + + } + + void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const + { + //not yet + btAssert(0); + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + /* t should be identity, but better be safe than...fast? */ + const btVector3 mins=m_body->m_bounds[0]; + const btVector3 maxs=m_body->m_bounds[1]; + const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),maxs.y(),maxs.z()), + t*btVector3(mins.x(),maxs.y(),maxs.z())}; + aabbMin=aabbMax=crns[0]; + for(int i=1;i<8;++i) + { + aabbMin.setMin(crns[i]); + aabbMax.setMax(crns[i]); + } + } + + virtual int getShapeType() const + { + return SOFTBODY_SHAPE_PROXYTYPE; + } + virtual void setLocalScaling(const btVector3& /*scaling*/) + { + ///na + btAssert(0); + } + virtual const btVector3& getLocalScaling() const + { + static const btVector3 dummy(1,1,1); + return dummy; + } + virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const + { + ///not yet + btAssert(0); + } + virtual const char* getName()const + { + return "SoftBody"; + } + +}; + +// +// btSoftClusterCollisionShape +// +class btSoftClusterCollisionShape : public btConvexInternalShape +{ +public: + const btSoftBody::Cluster* m_cluster; + + btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btSoftBody::Node* const * n=&m_cluster->m_nodes[0]; + btScalar d=dot(vec,n[0]->m_x); + int j=0; + for(int i=1,ni=m_cluster->m_nodes.size();im_x); + if(k>d) { d=k;j=i; } + } + return(n[j]->m_x); + } + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + return(localGetSupportingVertex(vec)); + } + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + {} + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const + {} + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + {} + + virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } + + //debugging + virtual const char* getName()const {return "SOFTCLUSTER";} + + virtual void setMargin(btScalar margin) + { + btConvexInternalShape::setMargin(margin); + } + virtual btScalar getMargin() const + { + return getMargin(); + } +}; + +// +// Inline's +// + +// +template +static inline void ZeroInitialize(T& value) +{ +static const T zerodummy; +value=zerodummy; +} +// +template +static inline bool CompLess(const T& a,const T& b) +{ return(a +static inline bool CompGreater(const T& a,const T& b) +{ return(a>b); } +// +template +static inline T Lerp(const T& a,const T& b,btScalar t) +{ return(a+(b-a)*t); } +// +template +static inline T InvLerp(const T& a,const T& b,btScalar t) +{ return((b+a*t-b*t)/(a*b)); } +// +static inline btMatrix3x3 Lerp( const btMatrix3x3& a, + const btMatrix3x3& b, + btScalar t) +{ +btMatrix3x3 r; +r[0]=Lerp(a[0],b[0],t); +r[1]=Lerp(a[1],b[1],t); +r[2]=Lerp(a[2],b[2],t); +return(r); +} +// +static inline btVector3 Clamp(const btVector3& v,btScalar maxlength) +{ +const btScalar sql=v.length2(); +if(sql>(maxlength*maxlength)) + return((v*maxlength)/btSqrt(sql)); + else + return(v); +} +// +template +static inline T Clamp(const T& x,const T& l,const T& h) +{ return(xh?h:x); } +// +template +static inline T Sq(const T& x) +{ return(x*x); } +// +template +static inline T Cube(const T& x) +{ return(x*x*x); } +// +template +static inline T Sign(const T& x) +{ return((T)(x<0?-1:+1)); } +// +template +static inline bool SameSign(const T& x,const T& y) +{ return((x*y)>0); } +// +static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y) +{ +const btVector3 d=x-y; +return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); +} +// +static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) +{ + const btScalar xx=a.x()*a.x(); + const btScalar yy=a.y()*a.y(); + const btScalar zz=a.z()*a.z(); + const btScalar xy=a.x()*a.y(); + const btScalar yz=a.y()*a.z(); + const btScalar zx=a.z()*a.x(); + btMatrix3x3 m; + m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx); + m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz); + m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s); + return(m); +} +// +static inline btMatrix3x3 Cross(const btVector3& v) +{ + btMatrix3x3 m; + m[0]=btVector3(0,-v.z(),+v.y()); + m[1]=btVector3(+v.z(),0,-v.x()); + m[2]=btVector3(-v.y(),+v.x(),0); + return(m); +} +// +static inline btMatrix3x3 Diagonal(btScalar x) +{ + btMatrix3x3 m; + m[0]=btVector3(x,0,0); + m[1]=btVector3(0,x,0); + m[2]=btVector3(0,0,x); + return(m); +} +// +static inline btMatrix3x3 Add(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]+b[i]; + return(r); +} +// +static inline btMatrix3x3 Sub(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]-b[i]; + return(r); +} +// +static inline btMatrix3x3 Mul(const btMatrix3x3& a, + btScalar b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]*b; + return(r); +} +// +static inline void Orthogonalize(btMatrix3x3& m) +{ +m[2]=cross(m[0],m[1]).normalized(); +m[1]=cross(m[2],m[0]).normalized(); +m[0]=cross(m[1],m[2]).normalized(); +} +// +static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r) +{ + const btMatrix3x3 cr=Cross(r); + return(Sub(Diagonal(im),cr*iwi*cr)); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar dt, + btScalar ima, + btScalar imb, + const btMatrix3x3& iwi, + const btVector3& r) +{ + return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse()); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra, + btScalar imb,const btMatrix3x3& iib,const btVector3& rb) +{ +return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); +} + +// +static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, + const btMatrix3x3& iib) +{ +return(Add(iia,iib).inverse()); +} + +// +static inline btVector3 ProjectOnAxis( const btVector3& v, + const btVector3& a) +{ + return(a*dot(v,a)); +} +// +static inline btVector3 ProjectOnPlane( const btVector3& v, + const btVector3& a) +{ + return(v-ProjectOnAxis(v,a)); +} + +// +static inline void ProjectOrigin( const btVector3& a, + const btVector3& b, + btVector3& prj, + btScalar& sqd) +{ +const btVector3 d=b-a; +const btScalar m2=d.length2(); +if(m2>SIMD_EPSILON) + { + const btScalar t=Clamp(-dot(a,d)/m2,0,1); + const btVector3 p=a+d*t; + const btScalar l2=p.length2(); + if(l2SIMD_EPSILON) + { + const btVector3 n=q/btSqrt(m2); + const btScalar k=dot(a,n); + const btScalar k2=k*k; + if(k20)&& + (dot(cross(b-p,c-p),q)>0)&& + (dot(cross(c-p,a-p),q)>0)) + { + prj=p; + sqd=k2; + } + else + { + ProjectOrigin(a,b,prj,sqd); + ProjectOrigin(b,c,prj,sqd); + ProjectOrigin(c,a,prj,sqd); + } + } + } +} + +// +template +static inline T BaryEval( const T& a, + const T& b, + const T& c, + const btVector3& coord) +{ + return(a*coord.x()+b*coord.y()+c*coord.z()); +} +// +static inline btVector3 BaryCoord( const btVector3& a, + const btVector3& b, + const btVector3& c, + const btVector3& p) +{ +const btScalar w[]={ cross(a-p,b-p).length(), + cross(b-p,c-p).length(), + cross(c-p,a-p).length()}; +const btScalar isum=1/(w[0]+w[1]+w[2]); +return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum)); +} + +// +static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, + const btVector3& a, + const btVector3& b, + const btScalar accuracy, + const int maxiterations=256) +{ +btScalar span[2]={0,1}; +btScalar values[2]={fn->Eval(a),fn->Eval(b)}; +if(values[0]>values[1]) + { + btSwap(span[0],span[1]); + btSwap(values[0],values[1]); + } +if(values[0]>-accuracy) return(-1); +if(values[1]<+accuracy) return(-1); +for(int i=0;iEval(Lerp(a,b,t)); + if((t<=0)||(t>=1)) break; + if(btFabs(v)SIMD_EPSILON) + return(v/l); + else + return(btVector3(0,0,0)); +} + +// +static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f, + btScalar margin) +{ +const btVector3* pts[]={ &f.m_n[0]->m_x, + &f.m_n[1]->m_x, + &f.m_n[2]->m_x}; +btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3); +vol.Expand(btVector3(margin,margin,margin)); +return(vol); +} + +// +static inline btVector3 CenterOf( const btSoftBody::Face& f) +{ +return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3); +} + +// +static inline btScalar AreaOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 cr=cross(a,b); + const btScalar area=cr.length(); + return(area); +} + +// +static inline btScalar VolumeOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(dot(a,cross(b,c))); +} + +// +static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, + const btVector3& x, + btSoftBody::sMedium& medium) +{ + medium.m_velocity = btVector3(0,0,0); + medium.m_pressure = 0; + medium.m_density = wfi->air_density; + if(wfi->water_density>0) + { + const btScalar depth=-(dot(x,wfi->water_normal)+wfi->water_offset); + if(depth>0) + { + medium.m_density = wfi->water_density; + medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); + } + } +} + +// +static inline void ApplyClampedForce( btSoftBody::Node& n, + const btVector3& f, + btScalar dt) +{ + const btScalar dtim=dt*n.m_im; + if((f*dtim).length2()>n.m_v.length2()) + {/* Clamp */ + n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim; + } + else + {/* Apply */ + n.m_f+=f; + } +} + +// +static inline int MatchEdge( const btSoftBody::Node* a, + const btSoftBody::Node* b, + const btSoftBody::Node* ma, + const btSoftBody::Node* mb) +{ +if((a==ma)&&(b==mb)) return(0); +if((a==mb)&&(b==ma)) return(1); +return(-1); +} + +// +// btEigen : Extract eigen system, +// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html +// outputs are NOT sorted. +// +struct btEigen +{ +static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) + { + static const int maxiterations=16; + static const btScalar accuracy=(btScalar)0.0001; + btMatrix3x3& v=*vectors; + int iterations=0; + vectors->setIdentity(); + do { + int p=0,q=1; + if(btFabs(a[p][q])accuracy) + { + const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]); + const btScalar z=btFabs(w); + const btScalar t=w/(z*(btSqrt(1+w*w)+z)); + if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ + { + const btScalar c=1/btSqrt(t*t+1); + const btScalar s=c*t; + mulPQ(a,c,s,p,q); + mulTPQ(a,c,s,p,q); + mulPQ(v,c,s,p,q); + } else break; + } else break; + } while((++iterations)accuracy) det=ndet; else break; + } + /* Final orthogonalization */ + Orthogonalize(q); + /* Compute 'S' */ + s=q.transpose()*m; + } + else + { + q.setIdentity(); + s.setIdentity(); + } +return(i); +} + +// +// btSoftColliders +// +struct btSoftColliders +{ + // + // ClusterBase + // + struct ClusterBase : btDbvt::ICollide + { + btScalar erp; + btScalar idt; + btScalar margin; + btScalar friction; + btScalar threshold; + ClusterBase() + { + erp =(btScalar)1; + idt =0; + margin =0; + friction =0; + threshold =(btScalar)0; + } + bool SolveContact( const btGjkEpaSolver2::sResults& res, + btSoftBody::Body ba,btSoftBody::Body bb, + btSoftBody::CJoint& joint) + { + if(res.distancedata; + btSoftClusterCollisionShape cshape(cluster); + const btConvexShape* rshape=(const btConvexShape*)prb->getCollisionShape(); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), + rshape,prb->getInterpolationWorldTransform(), + btVector3(1,0,0),res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cluster,prb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;psb->m_joints.push_back(pj); + if(prb->isStaticOrKinematicObject()) + { + pj->m_erp *= psb->m_cfg.kSKHR_CL; + pj->m_split *= psb->m_cfg.kSK_SPLT_CL; + } + else + { + pj->m_erp *= psb->m_cfg.kSRHR_CL; + pj->m_split *= psb->m_cfg.kSR_SPLT_CL; + } + } + } + } + void Process(btSoftBody* ps,btRigidBody* pr) + { + psb = ps; + prb = pr; + idt = ps->m_sst.isdt; + margin = ps->getCollisionShape()->getMargin()+ + pr->getCollisionShape()->getMargin(); + friction = btMin(psb->m_cfg.kDF,prb->getFriction()); + btVector3 mins; + btVector3 maxs; + + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + pr->getCollisionShape()->getAabb(pr->getInterpolationWorldTransform(),mins,maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(1,1,1)*margin); + btDbvt::collideTV(ps->m_cdbvt.m_root,volume,*this); + } + }; + // + // CollideCL_SS + // + struct CollideCL_SS : ClusterBase + { + btSoftBody* bodies[2]; + void Process(const btDbvtNode* la,const btDbvtNode* lb) + { + btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data; + btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; + btSoftClusterCollisionShape csa(cla); + btSoftClusterCollisionShape csb(clb); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(), + &csb,btTransform::getIdentity(), + cla->m_com-clb->m_com,res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cla,clb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;bodies[0]->m_joints.push_back(pj); + pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL); + pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2; + } + } + } + void Process(btSoftBody* psa,btSoftBody* psb) + { + idt = psa->m_sst.isdt; + margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2; + friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF); + bodies[0] = psa; + bodies[1] = psb; + btDbvt::collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); + } + }; + // + // CollideSDF_RS + // + struct CollideSDF_RS : btDbvt::ICollide + { + void Process(const btDbvtNode* leaf) + { + btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; + DoNode(*node); + } + void DoNode(btSoftBody::Node& n) const + { + const btScalar m=n.m_im>0?dynmargin:stamargin; + btSoftBody::RContact c; + if( (!n.m_battach)&& + psb->checkContact(prb,n.m_x,m,c.m_cti)) + { + const btScalar ima=n.m_im; + const btScalar imb=prb->getInvMass(); + const btScalar ms=ima+imb; + if(ms>0) + { + const btTransform& wtr=prb->getInterpolationWorldTransform(); + const btMatrix3x3& iwi=prb->getInvInertiaTensorWorld(); + const btVector3 ra=n.m_x-wtr.getOrigin(); + const btVector3 va=prb->getVelocityInLocalPoint(ra)*psb->m_sst.sdt; + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=vb-va; + const btScalar dn=dot(vr,c.m_cti.m_normal); + const btVector3 fv=vr-c.m_cti.m_normal*dn; + const btScalar fc=psb->m_cfg.kDF*prb->getFriction(); + c.m_node = &n; + c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra); + c.m_c1 = ra; + c.m_c2 = ima*psb->m_sst.sdt; + c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc; + c.m_c4 = prb->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; + psb->m_rcontacts.push_back(c); + prb->activate(); + } + } + } + btSoftBody* psb; + btRigidBody* prb; + btScalar dynmargin; + btScalar stamargin; + }; + // + // CollideVF_SS + // + struct CollideVF_SS : btDbvt::ICollide + { + void Process(const btDbvtNode* lnode, + const btDbvtNode* lface) + { + btSoftBody::Node* node=(btSoftBody::Node*)lnode->data; + btSoftBody::Face* face=(btSoftBody::Face*)lface->data; + btVector3 o=node->m_x; + btVector3 p; + btScalar d=SIMD_INFINITY; + ProjectOrigin( face->m_n[0]->m_x-o, + face->m_n[1]->m_x-o, + face->m_n[2]->m_x-o, + p,d); + const btScalar m=mrg+(o-node->m_q).length()*2; + if(d<(m*m)) + { + const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]}; + const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o); + const btScalar ma=node->m_im; + btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w); + if( (n[0]->m_im<=0)|| + (n[1]->m_im<=0)|| + (n[2]->m_im<=0)) + { + mb=0; + } + const btScalar ms=ma+mb; + if(ms>0) + { + btSoftBody::SContact c; + c.m_normal = p/-btSqrt(d); + c.m_margin = m; + c.m_node = node; + c.m_face = face; + c.m_weights = w; + c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF); + c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR; + c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR; + psb[0]->m_scontacts.push_back(c); + } + } + } + btSoftBody* psb[2]; + btScalar mrg; + }; +}; + +#endif //_BT_SOFT_BODY_INTERNALS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp new file mode 100644 index 00000000000..e62f35567b0 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp @@ -0,0 +1,108 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftBodyRigidBodyCollisionConfiguration.h" +#include "btSoftRigidCollisionAlgorithm.h" +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "btSoftSoftCollisionAlgorithm.h" + +#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1 + +btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +:btDefaultCollisionConfiguration(constructionInfo) +{ + void* mem; + + mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16); + m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + m_swappedSoftRigidConvexCreateFunc->m_swapped=true; + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc; + m_swappedSoftRigidConcaveCreateFunc->m_swapped=true; +#endif + +} + +btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() +{ + m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softSoftCreateFunc); + + m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConvexCreateFunc); + + m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConvexCreateFunc); + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConcaveCreateFunc); + + m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConcaveCreateFunc); +#endif +} + +///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation +btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + ///try to handle the softbody interactions first + + if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE)) + { + return m_softSoftCreateFunc; + } + + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_softRigidConvexCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConvexCreateFunc; + } + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_softRigidConcaveCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConcaveCreateFunc; + } +#endif + + ///fallback to the regular rigid collision shape + return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h new file mode 100644 index 00000000000..41c3af96939 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION +#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +class btVoronoiSimplexSolver; +class btGjkEpaPenetrationDepthSolver; + + +///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration +class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration +{ + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; + +public: + + btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btSoftBodyRigidBodyCollisionConfiguration(); + + ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + +}; + +#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp new file mode 100644 index 00000000000..835a03b8e3c --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp @@ -0,0 +1,79 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftRigidCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btSoftBody.h" +///TODO: include all the shapes that the softbody can collide with +///alternatively, implement special case collision algorithms (just like for rigid collision shapes) + +//#include + +btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*col0*/,btCollisionObject* /*col1*/, bool isSwapped) +: btCollisionAlgorithm(ci), +//m_ownManifold(false), +//m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ +} + + +btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() +{ + + //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); + + /*if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } + */ + +} + + +#include + +void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + //printf("btSoftRigidCollisionAlgorithm\n"); + + btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0; + btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1; + + softBody->defaultCollisionHandler(rigidCollisionObject); + + +} + +btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + + diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h new file mode 100644 index 00000000000..74327e6c635 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_RIGID_COLLISION_ALGORITHM_H +#define SOFT_RIGID_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" +class btSoftBody; + +/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody +class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm +{ +// bool m_ownManifold; +// btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody; + btCollisionObject* m_rigidCollisionObject; + + ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean + bool m_isSwapped; + +public: + + btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btSoftRigidCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //SOFT_RIGID_COLLISION_ALGORITHM_H + + diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp new file mode 100644 index 00000000000..01b9fc0fd35 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -0,0 +1,126 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSoftRigidDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//softbody & helpers +#include "btSoftBody.h" +#include "btSoftBodyHelpers.h" + +btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ +m_drawFlags = fDrawFlags::Std; +m_drawNodeTree = true; +m_drawFaceTree = false; +m_drawClusterTree = false; +} + +btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() +{ + +} + +void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep); + + for ( int i=0;ipredictMotion(timeStep); + } +} + +void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) +{ + btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); + + ///solve soft bodies constraints + solveSoftBodiesConstraints(); + + ///update soft bodies + updateSoftBodies(); + +} + +void btSoftRigidDynamicsWorld::updateSoftBodies() +{ + BT_PROFILE("updateSoftBodies"); + + for ( int i=0;iintegrateMotion(); + } +} + +void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints() +{ + BT_PROFILE("solveSoftConstraints"); + + if(m_softBodies.size()) + { + btSoftBody::solveClusters(m_softBodies); + } + + for(int i=0;isolveConstraints(); + } +} + +void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body) +{ + m_softBodies.push_back(body); + + btCollisionWorld::addCollisionObject(body, + btBroadphaseProxy::DefaultFilter, + btBroadphaseProxy::AllFilter); + +} + +void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body) +{ + m_softBodies.remove(body); + + btCollisionWorld::removeCollisionObject(body); +} + +void btSoftRigidDynamicsWorld::debugDrawWorld() +{ + btDiscreteDynamicsWorld::debugDrawWorld(); + + if (getDebugDrawer()) + { + int i; + for ( i=0;im_softBodies.size();i++) + { + btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; + btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); + btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); + if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); + if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); + } + } + } +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h new file mode 100644 index 00000000000..d0010b65aad --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -0,0 +1,73 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H +#define BT_SOFT_RIGID_DYNAMICS_WORLD_H + +class btSoftBody; +typedef btAlignedObjectArray btSoftBodyArray; + +class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld +{ + + btSoftBodyArray m_softBodies; + int m_drawFlags; + bool m_drawNodeTree; + bool m_drawFaceTree; + bool m_drawClusterTree; + +protected: + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void updateSoftBodies(); + + void solveSoftBodiesConstraints(); + + + +public: + + btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btSoftRigidDynamicsWorld(); + + virtual void debugDrawWorld(); + + void addSoftBody(btSoftBody* body); + + void removeSoftBody(btSoftBody* body); + + int getDrawFlags() const { return(m_drawFlags); } + void setDrawFlags(int f) { m_drawFlags=f; } + + + btSoftBodyArray& getSoftBodyArray() + { + return m_softBodies; + } + + const btSoftBodyArray& getSoftBodyArray() const + { + return m_softBodies; + } + +}; + +#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp new file mode 100644 index 00000000000..85a727944e0 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftSoftCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btSoftBody.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*obj0*/,btCollisionObject* /*obj1*/) +: btCollisionAlgorithm(ci) +//m_ownManifold(false), +//m_manifoldPtr(mf) +{ +} + +btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm() +{ +} + +void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + btSoftBody* soft0 = (btSoftBody*)body0; + btSoftBody* soft1 = (btSoftBody*)body1; + soft0->defaultCollisionHandler(soft1); +} + +btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h new file mode 100644 index 00000000000..7ca9c3415c9 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_SOFT_COLLISION_ALGORITHM_H +#define SOFT_SOFT_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; +class btSoftBody; + +///collision detection between two btSoftBody shapes +class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody0; + btSoftBody* m_softBody1; + + +public: + btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btSoftSoftCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btSoftSoftCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //SOFT_SOFT_COLLISION_ALGORITHM_H + + diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h new file mode 100644 index 00000000000..eafe74be1ae --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h @@ -0,0 +1,306 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSparseSdf implementation by Nathanael Presson + +#ifndef _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ +#define _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +// Modified Paul Hsieh hash +template +unsigned int HsiehHash(const void* pdata) + { + const unsigned short* data=(const unsigned short*)pdata; + unsigned hash=DWORDLEN<<2,tmp; + for(int i=0;i>11; + } + hash^=hash<<3;hash+=hash>>5; + hash^=hash<<4;hash+=hash>>17; + hash^=hash<<25;hash+=hash>>6; + return(hash); + } + +template +struct btSparseSdf + { + // + // Inner types + // + struct IntFrac + { + int b; + int i; + btScalar f; + }; + struct Cell + { + btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]; + int c[3]; + int puid; + unsigned hash; + btCollisionShape* pclient; + Cell* next; + }; + // + // Fields + // + + btAlignedObjectArray cells; + btScalar voxelsz; + int puid; + int ncells; + int nprobes; + int nqueries; + + // + // Methods + // + + // + void Initialize(int hashsize=2383) + { + cells.resize(hashsize,0); + Reset(); + } + // + void Reset() + { + for(int i=0,ni=cells.size();inext; + delete pc; + pc=pn; + } + } + voxelsz =0.25; + puid =0; + ncells =0; + nprobes =1; + nqueries =1; + } + // + void GarbageCollect(int lifetime=256) + { + const int life=puid-lifetime; + for(int i=0;inext; + if(pc->puidnext=pn; else root=pn; + delete pc;pc=pp;--ncells; + } + pp=pc;pc=pn; + } + } + //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries); + nqueries=1; + nprobes=1; + ++puid; /* TODO: Reset puid's when int range limit is reached */ + /* else setup a priority list... */ + } + // + int RemoveReferences(btCollisionShape* pcs) + { + int refcount=0; + for(int i=0;inext; + if(pc->pclient==pcs) + { + if(pp) pp->next=pn; else root=pn; + delete pc;pc=pp;++refcount; + } + pp=pc;pc=pn; + } + } + return(refcount); + } + // + btScalar Evaluate( const btVector3& x, + btCollisionShape* shape, + btVector3& normal, + btScalar margin) + { + /* Lookup cell */ + const btVector3 scx=x/voxelsz; + const IntFrac ix=Decompose(scx.x()); + const IntFrac iy=Decompose(scx.y()); + const IntFrac iz=Decompose(scx.z()); + const unsigned h=Hash(ix.b,iy.b,iz.b,shape); + Cell*& root=cells[static_cast(h%cells.size())]; + Cell* c=root; + ++nqueries; + while(c) + { + ++nprobes; + if( (c->hash==h) && + (c->c[0]==ix.b) && + (c->c[1]==iy.b) && + (c->c[2]==iz.b) && + (c->pclient==shape)) + { break; } + else + { c=c->next; } + } + if(!c) + { + ++nprobes; + ++ncells; + c=new Cell(); + c->next=root;root=c; + c->pclient=shape; + c->hash=h; + c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b; + BuildCell(*c); + } + c->puid=puid; + /* Extract infos */ + const int o[]={ ix.i,iy.i,iz.i}; + const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+1][o[2]+1], + c->d[o[0]+0][o[1]+1][o[2]+1]}; + /* Normal */ + #if 1 + const btScalar gx[]={ d[1]-d[0],d[2]-d[3], + d[5]-d[4],d[6]-d[7]}; + const btScalar gy[]={ d[3]-d[0],d[2]-d[1], + d[7]-d[4],d[6]-d[5]}; + const btScalar gz[]={ d[4]-d[0],d[5]-d[1], + d[7]-d[3],d[6]-d[2]}; + normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f), + Lerp(gx[2],gx[3],iy.f),iz.f)); + normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f), + Lerp(gy[2],gy[3],ix.f),iz.f)); + normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f), + Lerp(gz[2],gz[3],ix.f),iy.f)); + normal = normal.normalized(); + #else + normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); + #endif + /* Distance */ + const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), + Lerp(d[3],d[2],ix.f),iy.f); + const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f), + Lerp(d[7],d[6],ix.f),iy.f); + return(Lerp(d0,d1,iz.f)-margin); + } + // + void BuildCell(Cell& c) + { + const btVector3 org=btVector3( (btScalar)c.c[0], + (btScalar)c.c[1], + (btScalar)c.c[2]) * + CELLSIZE*voxelsz; + for(int k=0;k<=CELLSIZE;++k) + { + const btScalar z=voxelsz*k+org.z(); + for(int j=0;j<=CELLSIZE;++j) + { + const btScalar y=voxelsz*j+org.y(); + for(int i=0;i<=CELLSIZE;++i) + { + const btScalar x=voxelsz*i+org.x(); + c.d[i][j][k]=DistanceToShape( btVector3(x,y,z), + c.pclient); + } + } + } + } + // + static inline btScalar DistanceToShape(const btVector3& x, + btCollisionShape* shape) + { + btTransform unit; + unit.setIdentity(); + if(shape->isConvex()) + { + btGjkEpaSolver2::sResults res; + btConvexShape* csh=static_cast(shape); + return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res)); + } + return(0); + } + // + static inline IntFrac Decompose(btScalar x) + { + /* That one need a lot of improvements... */ + /* Remove test, faster floor... */ + IntFrac r; + x/=CELLSIZE; + const int o=x<0?(int)(-x+1):0; + x+=o;r.b=(int)x; + const btScalar k=(x-r.b)*CELLSIZE; + r.i=(int)k;r.f=k-r.i;r.b-=o; + return(r); + } + // + static inline btScalar Lerp(btScalar a,btScalar b,btScalar t) + { + return(a+(b-a)*t); + } + + + + // + static inline unsigned int Hash(int x,int y,int z,btCollisionShape* shape) + { + struct btS + { + int x,y,z; + void* p; + }; + + btS myset; + + myset.x=x;myset.y=y;myset.z=z;myset.p=shape; + const void* ptr = &myset; + + unsigned int result = HsiehHash (ptr); + + + return result; + } +}; + + +#endif diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt index 207eed94a3e..02ffaad7228 100644 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -4,7 +4,32 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ) ADD_LIBRARY(LibLinearMath -btQuickprof.cpp -btGeometryUtil.cpp + btAlignedObjectArray.h + btList.h + btPoolAllocator.h + btRandom.h + btVector3.h + btDefaultMotionState.h + btMatrix3x3.h + btQuadWord.h + btHashMap.h + btScalar.h + btAabbUtil2.h + btConvexHull.h + btConvexHull.cpp + btMinMax.h + btQuaternion.h + btStackAlloc.h + btGeometryUtil.h + btMotionState.h + btTransform.h + btAlignedAllocator.h + btIDebugDraw.h + btPoint3.h + btQuickprof.h + btTransformUtil.h + btQuickprof.cpp + btGeometryUtil.cpp + btAlignedAllocator.cpp ) diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 429163c8138..275c4914628 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -17,12 +17,18 @@ subject to the following restrictions: #ifndef AABB_UTIL2 #define AABB_UTIL2 +#include "btTransform.h" #include "btVector3.h" -#include "btSimdMinMax.h" +#include "btMinMax.h" - -#define btMin(a,b) ((a < b ? a : b)) -#define btMax(a,b) ((a > b ? a : b)) +SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, + btVector3& aabbMax, + const btVector3& expansionMin, + const btVector3& expansionMax) +{ + aabbMin = aabbMin + expansionMin; + aabbMax = aabbMax + expansionMax; +} /// conservative test for overlap between two aabbs @@ -67,6 +73,41 @@ SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) } +SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, + const btVector3& rayInvDirection, + const unsigned int raySign[3], + const btVector3 bounds[2], + btScalar& tmin, + btScalar lambda_min, + btScalar lambda_max) +{ + btScalar tmax, tymin, tymax, tzmin, tzmax; + tmin = (bounds[raySign[0]][0] - rayFrom[0]) * rayInvDirection[0]; + tmax = (bounds[1-raySign[0]][0] - rayFrom[0]) * rayInvDirection[0]; + tymin = (bounds[raySign[1]][1] - rayFrom[1]) * rayInvDirection[1]; + tymax = (bounds[1-raySign[1]][1] - rayFrom[1]) * rayInvDirection[1]; + + if ( (tmin > tymax) || (tymin > tmax) ) + return false; + + if (tymin > tmin) + tmin = tymin; + + if (tymax < tmax) + tmax = tymax; + + tzmin = (bounds[raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; + tzmax = (bounds[1-raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; + + if ( (tmin > tzmax) || (tzmin > tmax) ) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ( (tmin < lambda_max) && (tmax > lambda_min) ); +} + SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, const btVector3& rayTo, const btVector3& aabbMin, @@ -123,5 +164,39 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, } + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin), + abs_b[1].dot(halfExtentsWithMargin), + abs_b[2].dot(halfExtentsWithMargin)); + aabbMinOut = center - extent; + aabbMaxOut = center + extent; +} + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btAssert(localAabbMin.getX() <= localAabbMax.getX()); + btAssert(localAabbMin.getY() <= localAabbMax.getY()); + btAssert(localAabbMin.getZ() <= localAabbMax.getZ()); + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + localHalfExtents+=btVector3(margin,margin,margin); + + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + btMatrix3x3 abs_b = trans.getBasis().absolute(); + btVector3 center = trans(localCenter); + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMinOut = center-extent; + aabbMaxOut = center+extent; +} + + #endif + diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp index 1f5877fa37e..e120289e061 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -15,56 +15,187 @@ subject to the following restrictions: #include "btAlignedAllocator.h" +int gNumAlignedAllocs = 0; +int gNumAlignedFree = 0; +int gTotalBytesAlignedAllocs = 0;//detect memory leaks -#if defined (BT_HAS_ALIGNED_ALOCATOR) - +#if defined (BT_HAS_ALIGNED_ALLOCATOR) #include -void* btAlignedAlloc (int size, int alignment) +static void *btAlignedAllocDefault(size_t size, int alignment) { - return _aligned_malloc(size,alignment); + return _aligned_malloc(size, (size_t)alignment); } -void btAlignedFree (void* ptr) +static void btAlignedFreeDefault(void *ptr) { _aligned_free(ptr); } - -#else - -#ifdef __CELLOS_LV2__ - +#elif defined(__CELLOS_LV2__) #include -int numAllocs = 0; -int numFree = 0; - -void* btAlignedAlloc (int size, int alignment) +static inline void *btAlignedAllocDefault(size_t size, int alignment) { - numAllocs++; return memalign(alignment, size); } -void btAlignedFree (void* ptr) +static inline void btAlignedFreeDefault(void *ptr) +{ + free(ptr); +} +#else +static inline void *btAlignedAllocDefault(size_t size, int alignment) +{ + void *ret; + char *real; + unsigned long offset; + + real = (char *)malloc(size + sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); + ret = (void *)((real + sizeof(void *)) + offset); + *((void **)(ret)-1) = (void *)(real); + } else { + ret = (void *)(real); + } + return (ret); +} + +static inline void btAlignedFreeDefault(void *ptr) +{ + void* real; + + if (ptr) { + real = *((void **)(ptr)-1); + free(real); + } +} +#endif + +static void *btAllocDefault(size_t size) +{ + return malloc(size); +} + +static void btFreeDefault(void *ptr) { - numFree++; free(ptr); } +static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; +static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; +static btAllocFunc *sAllocFunc = btAllocDefault; +static btFreeFunc *sFreeFunc = btFreeDefault; + +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) +{ + sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault; + sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault; +} + +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) +{ + sAllocFunc = allocFunc ? allocFunc : btAllocDefault; + sFreeFunc = freeFunc ? freeFunc : btFreeDefault; +} + +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS +//this generic allocator provides the total allocated number of bytes +#include + +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) +{ + void *ret; + char *real; + unsigned long offset; + + gTotalBytesAlignedAllocs += size; + gNumAlignedAllocs++; + + + real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & +(alignment-1); + ret = (void *)((real + 2*sizeof(void *)) + offset); + *((void **)(ret)-1) = (void *)(real); + *((int*)(ret)-2) = size; + + } else { + ret = (void *)(real);//?? + } + + printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); + + int* ptr = (int*)ret; + *ptr = 12; + return (ret); +} + +void btAlignedFreeInternal (void* ptr,int line,char* filename) +{ + + void* real; + gNumAlignedFree++; + + if (ptr) { + real = *((void **)(ptr)-1); + int size = *((int*)(ptr)-2); + gTotalBytesAlignedAllocs -= size; + + printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); + + sFreeFunc(real); + } else + { + printf("NULL ptr\n"); + } +} + +#else //BT_DEBUG_MEMORY_ALLOCATIONS + +void* btAlignedAllocInternal (size_t size, int alignment) +{ + gNumAlignedAllocs++; + void* ptr; +#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) + ptr = sAlignedAllocFunc(size, alignment); #else -///todo -///will add some multi-platform version that works without _aligned_malloc/_aligned_free + char *real; + unsigned long offset; -void* btAlignedAlloc (int size, int alignment) -{ - return new char[size]; + real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); + ptr = (void *)((real + sizeof(void *)) + offset); + *((void **)(ptr)-1) = (void *)(real); + } else { + ptr = (void *)(real); + } +#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) +// printf("btAlignedAllocInternal %d, %x\n",size,ptr); + return ptr; } -void btAlignedFree (void* ptr) +void btAlignedFreeInternal (void* ptr) { - delete [] (char*) ptr; + if (!ptr) + { + return; + } + + gNumAlignedFree++; +// printf("btAlignedFreeInternal %x\n",ptr); +#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) + sAlignedFreeFunc(ptr); +#else + void* real; + + if (ptr) { + real = *((void **)(ptr)-1); + sFreeFunc(real); + } +#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) } -#endif // - -#endif +#endif //BT_DEBUG_MEMORY_ALLOCATIONS diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h index 07585717f45..a252f324d77 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h @@ -21,15 +21,39 @@ subject to the following restrictions: ///that is better portable and more predictable #include "btScalar.h" +//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS -void* btAlignedAlloc (int size, int alignment); +#define btAlignedAlloc(a,b) \ + btAlignedAllocInternal(a,b,__LINE__,__FILE__) -void btAlignedFree (void* ptr); +#define btAlignedFree(ptr) \ + btAlignedFreeInternal(ptr,__LINE__,__FILE__) +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); +void btAlignedFreeInternal (void* ptr,int line,char* filename); + +#else + void* btAlignedAllocInternal (size_t size, int alignment); + void btAlignedFreeInternal (void* ptr); + + #define btAlignedAlloc(a,b) btAlignedAllocInternal(a,b) + #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) + +#endif typedef int size_type; +typedef void *(btAlignedAllocFunc)(size_t size, int alignment); +typedef void (btAlignedFreeFunc)(void *memblock); +typedef void *(btAllocFunc)(size_t size); +typedef void (btFreeFunc)(void *memblock); +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); + +///The btAlignedAllocator is a portable class for aligned memory allocations. +///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. template < typename T , unsigned Alignment > class btAlignedAllocator { diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h index 8bef5eb5d06..5598f0d7236 100644 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -39,8 +39,8 @@ subject to the following restrictions: #endif //BT_USE_PLACEMENT_NEW -///btAlignedObjectArray uses a subset of the stl::vector interface for its methods -///It is developed to replace stl::vector to avoid STL alignment issues to add SIMD/SSE data +///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods +///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data template //template class btAlignedObjectArray @@ -50,6 +50,8 @@ class btAlignedObjectArray int m_size; int m_capacity; T* m_data; + //PCK: added this line + bool m_ownsMemory; protected: SIMD_FORCE_INLINE int allocSize(int size) @@ -69,6 +71,8 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void init() { + //PCK: added this line + m_ownsMemory = true; m_data = 0; m_size = 0; m_capacity = 0; @@ -92,7 +96,11 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void deallocate() { if(m_data) { - m_allocator.deallocate(m_data); + //PCK: enclosed the deallocation in this block + if (m_ownsMemory) + { + m_allocator.deallocate(m_data); + } m_data = 0; } } @@ -223,6 +231,9 @@ class btAlignedObjectArray destroy(0,size()); deallocate(); + + //PCK: added this line + m_ownsMemory = true; m_data = s; @@ -242,6 +253,46 @@ class btAlignedObjectArray } }; + template + void quickSortInternal(L CompareFunc,int lo, int hi) + { + // lo is the lower index, hi is the upper index + // of the region of array a that is to be sorted + int i=lo, j=hi; + T x=m_data[(lo+hi)/2]; + + // partition + do + { + while (CompareFunc(m_data[i],x)) + i++; + while (CompareFunc(x,m_data[j])) + j--; + if (i<=j) + { + swap(i,j); + i++; j--; + } + } while (i<=j); + + // recursion + if (lo + void quickSort(L CompareFunc) + { + //don't sort 0 or 1 elements + if (size()>1) + { + quickSortInternal(CompareFunc,0,size()-1); + } + } + ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ template @@ -360,8 +411,16 @@ class btAlignedObjectArray } } + //PCK: whole function + void initializeFromBuffer(void *buffer, int size, int capacity) + { + clear(); + m_ownsMemory = false; + m_data = (T*)buffer; + m_size = size; + m_capacity = capacity; + } + }; #endif //BT_OBJECT_ARRAY__ - - diff --git a/extern/bullet2/src/LinearMath/btConvexHull.h b/extern/bullet2/src/LinearMath/btConvexHull.h new file mode 100644 index 00000000000..8bb80de0225 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btConvexHull.h @@ -0,0 +1,242 @@ + +/* +Stan Melax Convex Hull Computation +Copyright (c) 2008 Stan Melax http://www.melax.com/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///includes modifications/improvements by John Ratcliff, see BringOutYourDead below. + +#ifndef CD_HULL_H +#define CD_HULL_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" + +typedef btAlignedObjectArray TUIntArray; + +class HullResult +{ +public: + HullResult(void) + { + mPolygons = true; + mNumOutputVertices = 0; + mNumFaces = 0; + mNumIndices = 0; + } + bool mPolygons; // true if indices represents polygons, false indices are triangles + unsigned int mNumOutputVertices; // number of vertices in the output hull + btAlignedObjectArray m_OutputVertices; // array of vertices + unsigned int mNumFaces; // the number of faces produced + unsigned int mNumIndices; // the total number of indices + btAlignedObjectArray m_Indices; // pointer to indices. + +// If triangles, then indices are array indexes into the vertex list. +// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc.. +}; + +enum HullFlag +{ + QF_TRIANGLES = (1<<0), // report results as triangles, not polygons. + QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices. + QF_DEFAULT = QF_TRIANGLES +}; + + +class HullDesc +{ +public: + HullDesc(void) + { + mFlags = QF_DEFAULT; + mVcount = 0; + mVertices = 0; + mVertexStride = sizeof(btVector3); + mNormalEpsilon = 0.001f; + mMaxVertices = 4096; // maximum number of points to be considered for a convex hull. + mMaxFaces = 4096; + }; + + HullDesc(HullFlag flag, + unsigned int vcount, + const btVector3 *vertices, + unsigned int stride = sizeof(btVector3)) + { + mFlags = flag; + mVcount = vcount; + mVertices = vertices; + mVertexStride = stride; + mNormalEpsilon = btScalar(0.001); + mMaxVertices = 4096; + } + + bool HasHullFlag(HullFlag flag) const + { + if ( mFlags & flag ) return true; + return false; + } + + void SetHullFlag(HullFlag flag) + { + mFlags|=flag; + } + + void ClearHullFlag(HullFlag flag) + { + mFlags&=~flag; + } + + unsigned int mFlags; // flags to use when generating the convex hull. + unsigned int mVcount; // number of vertices in the input point cloud + const btVector3 *mVertices; // the array of vertices. + unsigned int mVertexStride; // the stride of each vertex, in bytes. + btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on. + unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull! + unsigned int mMaxFaces; +}; + +enum HullError +{ + QE_OK, // success! + QE_FAIL // failed. +}; + +class btPlane +{ + public: + btVector3 normal; + btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0 + btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){} + btPlane():normal(),dist(0){} + +}; + + + +class ConvexH +{ + public: + class HalfEdge + { + public: + short ea; // the other half of the edge (index into edges list) + unsigned char v; // the vertex at the start of this edge (index into vertices list) + unsigned char p; // the facet on which this edge lies (index into facets list) + HalfEdge(){} + HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){} + }; + ConvexH() + { + int i; + i=0; + } + ~ConvexH() + { + int i; + i=0; + } + btAlignedObjectArray vertices; + btAlignedObjectArray edges; + btAlignedObjectArray facets; + ConvexH(int vertices_size,int edges_size,int facets_size); +}; + + +class int4 +{ +public: + int x,y,z,w; + int4(){}; + int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + +class PHullResult +{ +public: + + PHullResult(void) + { + mVcount = 0; + mIndexCount = 0; + mFaceCount = 0; + mVertices = 0; + } + + unsigned int mVcount; + unsigned int mIndexCount; + unsigned int mFaceCount; + btVector3* mVertices; + TUIntArray m_Indices; +}; + + + +///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method. +///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape. +class HullLibrary +{ + + btAlignedObjectArray m_tris; + +public: + + HullError CreateConvexHull(const HullDesc& desc, // describes the input request + HullResult& result); // contains the resulst + HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. + +private: + + bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit); + + class Tri* allocateTriangle(int a,int b,int c); + void deAllocateTriangle(Tri*); + void b2bfix(Tri* s,Tri*t); + + void removeb2b(Tri* s,Tri*t); + + void checkit(Tri *t); + + Tri* extrudable(btScalar epsilon); + + int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit); + + int calchullgen(btVector3 *verts,int verts_count, int vlimit); + + int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow); + + class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice); + + void extrude(class Tri* t0,int v); + + ConvexH* test_cube(); + + //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. + //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud. + //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull. + //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation. + void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount); + + bool CleanupVertices(unsigned int svcount, + const btVector3* svertices, + unsigned int stride, + unsigned int &vcount, // output number of vertices + btVector3* vertices, // location to store the results. + btScalar normalepsilon, + btVector3& scale); +}; + + +#endif + diff --git a/extern/bullet2/src/LinearMath/btDefaultMotionState.h b/extern/bullet2/src/LinearMath/btDefaultMotionState.h index d4ec8e8879c..d758f77ed81 100644 --- a/extern/bullet2/src/LinearMath/btDefaultMotionState.h +++ b/extern/bullet2/src/LinearMath/btDefaultMotionState.h @@ -1,7 +1,7 @@ #ifndef DEFAULT_MOTION_STATE_H #define DEFAULT_MOTION_STATE_H -///btDefaultMotionState provides a common implementation to synchronize world transforms with offsets +///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets. struct btDefaultMotionState : public btMotionState { btTransform m_graphicsWorldTrans; diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp index 3d0fb122a6b..5ac230f712f 100644 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp @@ -22,7 +22,12 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" void btBulletMathProbe () {} +extern "C" +{ + void btBulletMathProbe (); + + void btBulletMathProbe () {} +} bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin) @@ -57,6 +62,8 @@ bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const return true; } +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations); + bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) { int numbrushes = planeEquations.size(); diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.h b/extern/bullet2/src/LinearMath/btGeometryUtil.h index 766cd75c383..a4b13b45609 100644 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.h +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.h @@ -19,6 +19,7 @@ subject to the following restrictions: #include "btVector3.h" #include "btAlignedObjectArray.h" +///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices. class btGeometryUtil { public: diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h index 5f40ca39157..563615a9a32 100644 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -31,6 +31,9 @@ DEALINGS IN THE SOFTWARE. #include "btVector3.h" +///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations. +///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld. +///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum. class btIDebugDraw { public: @@ -55,11 +58,24 @@ class btIDebugDraw virtual ~btIDebugDraw() {}; virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; + + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha) + { + drawTriangle(v0,v1,v2,color,alpha); + } + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/) + { + drawLine(v0,v1,color); + drawLine(v1,v2,color); + drawLine(v2,v0,color); + } virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; virtual void reportErrorWarning(const char* warningString) = 0; + virtual void draw3dText(const btVector3& location,const char* textString) = 0; + virtual void setDebugMode(int debugMode) =0; virtual int getDebugMode() const = 0; diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h index 94f53c3c0a5..14aa4ae2348 100644 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -22,6 +22,9 @@ subject to the following restrictions: #include "btQuaternion.h" + +///The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3. +///Make sure to only include a pure orthogonal matrix without scaling. class btMatrix3x3 { public: btMatrix3x3 () {} @@ -281,6 +284,91 @@ class btMatrix3x3 { } + ///diagonalizes this matrix by the Jacobi method. rot stores the rotation + ///from the coordinate system in which the matrix is diagonal to the original + ///coordinate system, i.e., old_this = rot * new_this * rot^T. The iteration + ///stops when all off-diagonal elements are less than the threshold multiplied + ///by the sum of the absolute values of the diagonal, or when maxSteps have + ///been executed. Note that this matrix is assumed to be symmetric. + void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps) + { + rot.setIdentity(); + for (int step = maxSteps; step > 0; step--) + { + // find off-diagonal element [p][q] with largest magnitude + int p = 0; + int q = 1; + int r = 2; + btScalar max = btFabs(m_el[0][1]); + btScalar v = btFabs(m_el[0][2]); + if (v > max) + { + q = 2; + r = 1; + max = v; + } + v = btFabs(m_el[1][2]); + if (v > max) + { + p = 1; + q = 2; + r = 0; + max = v; + } + + btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2])); + if (max <= t) + { + if (max <= SIMD_EPSILON * t) + { + return; + } + step = 1; + } + + // compute Jacobi rotation J which leads to a zero for element [p][q] + btScalar mpq = m_el[p][q]; + btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq); + btScalar theta2 = theta * theta; + btScalar cos; + btScalar sin; + if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON)) + { + t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2)) + : 1 / (theta - btSqrt(1 + theta2)); + cos = 1 / btSqrt(1 + t * t); + sin = cos * t; + } + else + { + // approximation for large theta-value, i.e., a nearly diagonal matrix + t = 1 / (theta * (2 + btScalar(0.5) / theta2)); + cos = 1 - btScalar(0.5) * t * t; + sin = cos * t; + } + + // apply rotation to matrix (this = J^T * this * J) + m_el[p][q] = m_el[q][p] = 0; + m_el[p][p] -= t * mpq; + m_el[q][q] += t * mpq; + btScalar mrp = m_el[r][p]; + btScalar mrq = m_el[r][q]; + m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq; + m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp; + + // apply rotation to rot (rot = rot * J) + for (int i = 0; i < 3; i++) + { + btVector3& row = rot[i]; + mrp = row[p]; + mrq = row[q]; + row[p] = cos * mrp - sin * mrq; + row[q] = cos * mrq + sin * mrp; + } + } + } + + protected: btScalar cofac(int r1, int c1, int r2, int c2) const @@ -356,7 +444,7 @@ class btMatrix3x3 { m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), - m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].x()); + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); } SIMD_FORCE_INLINE btMatrix3x3 @@ -406,5 +494,11 @@ class btMatrix3x3 { } */ +SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ + return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] && + m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] && + m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] ); +} #endif diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h index 1b8a3633f38..5e27d62a4a4 100644 --- a/extern/bullet2/src/LinearMath/btMinMax.h +++ b/extern/bullet2/src/LinearMath/btMinMax.h @@ -18,15 +18,15 @@ subject to the following restrictions: #define GEN_MINMAX_H template -SIMD_FORCE_INLINE const T& GEN_min(const T& a, const T& b) +SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) { - return b < a ? b : a; + return a < b ? a : b ; } template -SIMD_FORCE_INLINE const T& GEN_max(const T& a, const T& b) +SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) { - return a < b ? b : a; + return a > b ? a : b; } template @@ -36,7 +36,7 @@ SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub) } template -SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) +SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) { if (b < a) { @@ -45,7 +45,7 @@ SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) } template -SIMD_FORCE_INLINE void GEN_set_max(T& a, const T& b) +SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) { if (a < b) { diff --git a/extern/bullet2/src/LinearMath/btMotionState.h b/extern/bullet2/src/LinearMath/btMotionState.h index 1975e5ff900..94318140902 100644 --- a/extern/bullet2/src/LinearMath/btMotionState.h +++ b/extern/bullet2/src/LinearMath/btMotionState.h @@ -18,7 +18,7 @@ subject to the following restrictions: #include "btTransform.h" -///btMotionState allows the dynamics world to synchronize the updated world transforms with graphics +///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics ///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) class btMotionState { diff --git a/extern/bullet2/src/LinearMath/btPoolAllocator.h b/extern/bullet2/src/LinearMath/btPoolAllocator.h new file mode 100644 index 00000000000..e9620ac5faa --- /dev/null +++ b/extern/bullet2/src/LinearMath/btPoolAllocator.h @@ -0,0 +1,97 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef _BT_POOL_ALLOCATOR_H +#define _BT_POOL_ALLOCATOR_H + +#include "btScalar.h" +#include "btAlignedAllocator.h" + +///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. +class btPoolAllocator +{ + int m_elemSize; + int m_maxElements; + int m_freeCount; + void* m_firstFree; + unsigned char* m_pool; + +public: + + btPoolAllocator(int elemSize, int maxElements) + :m_elemSize(elemSize), + m_maxElements(maxElements) + { + m_pool = (unsigned char*) btAlignedAlloc( static_cast(m_elemSize*m_maxElements),16); + + unsigned char* p = m_pool; + m_firstFree = p; + m_freeCount = m_maxElements; + int count = m_maxElements; + while (--count) { + *(void**)p = (p + m_elemSize); + p += m_elemSize; + } + *(void**)p = 0; + } + + ~btPoolAllocator() + { + btAlignedFree( m_pool); + } + + int getFreeCount() const + { + return m_freeCount; + } + + void* allocate(int size) + { + // release mode fix + (void)size; + btAssert(!size || size<=m_elemSize); + btAssert(m_freeCount>0); + void* result = m_firstFree; + m_firstFree = *(void**)m_firstFree; + --m_freeCount; + return result; + } + + bool validPtr(void* ptr) + { + if (ptr) { + if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) + { + return true; + } + } + return false; + } + + void freeMemory(void* ptr) + { + if (ptr) { + btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); + + *(void**)ptr = m_firstFree; + m_firstFree = ptr; + ++m_freeCount; + } + } + + +}; + +#endif //_BT_POOL_ALLOCATOR_H diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h index 961ac484d20..2e80fc2ca47 100644 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -17,19 +17,31 @@ subject to the following restrictions: #define SIMD_QUADWORD_H #include "btScalar.h" +#include "btMinMax.h" +#include +///The btQuadWordStorage class is base class for btVector3 and btQuaternion. +///Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. todo: look into this +///ATTRIBUTE_ALIGNED16(class) btQuadWordStorage +class btQuadWordStorage +{ +protected: + + btScalar m_x; + btScalar m_y; + btScalar m_z; + btScalar m_unusedW; + +public: + +}; + ///btQuadWord is base-class for vectors, points -class btQuadWord +class btQuadWord : public btQuadWordStorage { - protected: - btScalar m_x; - btScalar m_y; - btScalar m_z; - btScalar m_unusedW; - public: // SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } @@ -61,6 +73,8 @@ class btQuadWord SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } + + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) { m_x=x; @@ -89,47 +103,36 @@ class btQuadWord { } - SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) - :m_x(x),m_y(y),m_z(z) - //todo, remove this in release/simd ? - ,m_unusedW(btScalar(0.)) + SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) { + *((btQuadWordStorage*)this) = q; + } + + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_x = x, m_y = y, m_z = z, m_unusedW = 0.0f; } SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) - :m_x(x),m_y(y),m_z(z),m_unusedW(w) { + m_x = x, m_y = y, m_z = z, m_unusedW = w; } SIMD_FORCE_INLINE void setMax(const btQuadWord& other) { - if (other.m_x > m_x) - m_x = other.m_x; - - if (other.m_y > m_y) - m_y = other.m_y; - - if (other.m_z > m_z) - m_z = other.m_z; - - if (other.m_unusedW > m_unusedW) - m_unusedW = other.m_unusedW; + btSetMax(m_x, other.m_x); + btSetMax(m_y, other.m_y); + btSetMax(m_z, other.m_z); + btSetMax(m_unusedW, other.m_unusedW); } SIMD_FORCE_INLINE void setMin(const btQuadWord& other) { - if (other.m_x < m_x) - m_x = other.m_x; - - if (other.m_y < m_y) - m_y = other.m_y; - - if (other.m_z < m_z) - m_z = other.m_z; - - if (other.m_unusedW < m_unusedW) - m_unusedW = other.m_unusedW; + btSetMin(m_x, other.m_x); + btSetMin(m_y, other.m_y); + btSetMin(m_z, other.m_z); + btSetMin(m_unusedW, other.m_unusedW); } diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h index 50334970ba6..264751b33e7 100644 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -19,6 +19,7 @@ subject to the following restrictions: #include "btVector3.h" +///The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. class btQuaternion : public btQuadWord { public: btQuaternion() {} @@ -158,7 +159,7 @@ public: btQuaternion inverse() const { - return btQuaternion(m_x, m_y, m_z, -m_unusedW); + return btQuaternion(-m_x, -m_y, -m_z, m_unusedW); } SIMD_FORCE_INLINE btQuaternion @@ -285,7 +286,7 @@ slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) } SIMD_FORCE_INLINE btVector3 -quatRotate(btQuaternion& rotation, btVector3& v) +quatRotate(const btQuaternion& rotation, const btVector3& v) { btQuaternion q = rotation * v; q *= rotation.inverse(); @@ -293,7 +294,7 @@ quatRotate(btQuaternion& rotation, btVector3& v) } SIMD_FORCE_INLINE btQuaternion -shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized { btVector3 c = v0.cross(v1); btScalar d = v0.dot(v1); @@ -308,7 +309,7 @@ shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make } SIMD_FORCE_INLINE btQuaternion -shortestArcQuatNormalize(btVector3& v0,btVector3& v1) +shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) { v0.normalize(); v1.normalize(); @@ -319,3 +320,4 @@ shortestArcQuatNormalize(btVector3& v0,btVector3& v1) + diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp index 37a0c8c3be5..e5b1196149b 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.cpp +++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp @@ -1,38 +1,282 @@ /* -Copyright (c) 2006 Tyler Streeter -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. +/*************************************************************************************************** +** +** profile.cpp +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). #include "LinearMath/btQuickprof.h" -#ifdef USE_QUICKPROF -// Note: We must declare these private static variables again here to -// avoid link errors. -bool btProfiler::mEnabled = false; -btClock btProfiler::mClock; -unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0; -unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0; -std::map btProfiler::mProfileBlocks; -std::ofstream btProfiler::mOutputFile; -bool btProfiler::mFirstFileOutput = true; -btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; -unsigned long int btProfiler::mCycleNumber = 0; -#endif //USE_QUICKPROF +#ifdef USE_BT_CLOCK + +static btClock gProfileClock; + +inline void Profile_Get_Ticks(unsigned long int * ticks) +{ + *ticks = gProfileClock.getTimeMicroseconds(); +} + +inline float Profile_Get_Tick_Rate(void) +{ +// return 1000000.f; + return 1000.f; + +} + + + +/*************************************************************************************************** +** +** CProfileNode +** +***************************************************************************************************/ + +/*********************************************************************************************** + * INPUT: * + * name - pointer to a static string which is the name of this profile node * + * parent - parent pointer * + * * + * WARNINGS: * + * The name is assumed to be a static pointer, only the pointer is stored and compared for * + * efficiency reasons. * + *=============================================================================================*/ +CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : + Name( name ), + TotalCalls( 0 ), + TotalTime( 0 ), + StartTime( 0 ), + RecursionCounter( 0 ), + Parent( parent ), + Child( NULL ), + Sibling( NULL ) +{ + Reset(); +} + + +void CProfileNode::CleanupMemory() +{ + delete ( Child); + Child = NULL; + delete ( Sibling); + Sibling = NULL; +} + +CProfileNode::~CProfileNode( void ) +{ + delete ( Child); + delete ( Sibling); +} + + +/*********************************************************************************************** + * INPUT: * + * name - static string pointer to the name of the node we are searching for * + * * + * WARNINGS: * + * All profile names are assumed to be static strings so this function uses pointer compares * + * to find the named node. * + *=============================================================================================*/ +CProfileNode * CProfileNode::Get_Sub_Node( const char * name ) +{ + // Try to find this sub node + CProfileNode * child = Child; + while ( child ) { + if ( child->Name == name ) { + return child; + } + child = child->Sibling; + } + + // We didn't find it, so add it + + CProfileNode * node = new CProfileNode( name, this ); + node->Sibling = Child; + Child = node; + return node; +} + + +void CProfileNode::Reset( void ) +{ + TotalCalls = 0; + TotalTime = 0.0f; + gProfileClock.reset(); + + if ( Child ) { + Child->Reset(); + } + if ( Sibling ) { + Sibling->Reset(); + } +} + + +void CProfileNode::Call( void ) +{ + TotalCalls++; + if (RecursionCounter++ == 0) { + Profile_Get_Ticks(&StartTime); + } +} + + +bool CProfileNode::Return( void ) +{ + if ( --RecursionCounter == 0 && TotalCalls != 0 ) { + unsigned long int time; + Profile_Get_Ticks(&time); + time-=StartTime; + TotalTime += (float)time / Profile_Get_Tick_Rate(); + } + return ( RecursionCounter == 0 ); +} + + +/*************************************************************************************************** +** +** CProfileIterator +** +***************************************************************************************************/ +CProfileIterator::CProfileIterator( CProfileNode * start ) +{ + CurrentParent = start; + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::First(void) +{ + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::Next(void) +{ + CurrentChild = CurrentChild->Get_Sibling(); +} + + +bool CProfileIterator::Is_Done(void) +{ + return CurrentChild == NULL; +} + + +void CProfileIterator::Enter_Child( int index ) +{ + CurrentChild = CurrentParent->Get_Child(); + while ( (CurrentChild != NULL) && (index != 0) ) { + index--; + CurrentChild = CurrentChild->Get_Sibling(); + } + + if ( CurrentChild != NULL ) { + CurrentParent = CurrentChild; + CurrentChild = CurrentParent->Get_Child(); + } +} + + +void CProfileIterator::Enter_Parent( void ) +{ + if ( CurrentParent->Get_Parent() != NULL ) { + CurrentParent = CurrentParent->Get_Parent(); + } + CurrentChild = CurrentParent->Get_Child(); +} + + +/*************************************************************************************************** +** +** CProfileManager +** +***************************************************************************************************/ + +CProfileNode CProfileManager::Root( "Root", NULL ); +CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; +int CProfileManager::FrameCounter = 0; +unsigned long int CProfileManager::ResetTime = 0; + + +/*********************************************************************************************** + * CProfileManager::Start_Profile -- Begin a named profile * + * * + * Steps one level deeper into the tree, if a child already exists with the specified name * + * then it accumulates the profiling; otherwise a new child node is added to the profile tree. * + * * + * INPUT: * + * name - name of this profiling record * + * * + * WARNINGS: * + * The string used is assumed to be a static string; pointer compares are used throughout * + * the profiling code for efficiency. * + *=============================================================================================*/ +void CProfileManager::Start_Profile( const char * name ) +{ + if (name != CurrentNode->Get_Name()) { + CurrentNode = CurrentNode->Get_Sub_Node( name ); + } + + CurrentNode->Call(); +} + + +/*********************************************************************************************** + * CProfileManager::Stop_Profile -- Stop timing and record the results. * + *=============================================================================================*/ +void CProfileManager::Stop_Profile( void ) +{ + // Return will indicate whether we should back up to our parent (we may + // be profiling a recursive function) + if (CurrentNode->Return()) { + CurrentNode = CurrentNode->Get_Parent(); + } +} + + +/*********************************************************************************************** + * CProfileManager::Reset -- Reset the contents of the profiling system * + * * + * This resets everything except for the tree structure. All of the timing data is reset. * + *=============================================================================================*/ +void CProfileManager::Reset( void ) +{ + Root.Reset(); + Root.Call(); + FrameCounter = 0; + Profile_Get_Ticks(&ResetTime); +} + + +/*********************************************************************************************** + * CProfileManager::Increment_Frame_Counter -- Increment the frame counter * + *=============================================================================================*/ +void CProfileManager::Increment_Frame_Counter( void ) +{ + FrameCounter++; +} + + +/*********************************************************************************************** + * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset * + *=============================================================================================*/ +float CProfileManager::Get_Time_Since_Reset( void ) +{ + unsigned long int time; + Profile_Get_Ticks(&time); + time -= ResetTime; + return (float)time / Profile_Get_Tick_Rate(); +} + +#endif //USE_BT_CLOCK + diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h index a885967c5fa..b033940ca5c 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.h +++ b/extern/bullet2/src/LinearMath/btQuickprof.h @@ -1,20 +1,11 @@ -/* -Copyright (c) 2006 Tyler Streeter -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. +/*************************************************************************************************** +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). @@ -23,9 +14,10 @@ subject to the following restrictions: #define QUICK_PROF_H #include "btScalar.h" - -//#define USE_QUICKPROF 1 -//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes. +#include "LinearMath/btAlignedAllocator.h" +#include +//To disable built-in profiling, please comment out next line +//#define BT_NO_PROFILE 1 //if you don't need btClock, you can comment next line @@ -34,678 +26,332 @@ subject to the following restrictions: #ifdef USE_BT_CLOCK #ifdef __CELLOS_LV2__ #include +#include #include -typedef uint64_t __int64; #endif #if defined (SUNOS) || defined (__SUNOS__) - #include +#include #endif #if defined(WIN32) || defined(_WIN32) - #define USE_WINDOWS_TIMERS - #define WIN32_LEAN_AND_MEAN - #define NOWINRES - #define NOMCX - #define NOIME +#define USE_WINDOWS_TIMERS +#define WIN32_LEAN_AND_MEAN +#define NOWINRES +#define NOMCX +#define NOIME #ifdef _XBOX - #include +#include #else - #include +#include #endif - #include +#include #else - #include +#include #endif #define mymin(a,b) (a > b ? a : b) -/// basic clock +///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. class btClock +{ +public: + btClock() { - public: - btClock() - { #ifdef USE_WINDOWS_TIMERS - QueryPerformanceFrequency(&mClockFrequency); + QueryPerformanceFrequency(&mClockFrequency); #endif - reset(); - } + reset(); + } - ~btClock() - { - } + ~btClock() + { + } - /// Resets the initial reference time. - void reset() - { + /// Resets the initial reference time. + void reset() + { #ifdef USE_WINDOWS_TIMERS - QueryPerformanceCounter(&mStartTime); - mStartTick = GetTickCount(); - mPrevElapsedTime = 0; + QueryPerformanceCounter(&mStartTime); + mStartTick = GetTickCount(); + mPrevElapsedTime = 0; #else #ifdef __CELLOS_LV2__ - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - mStartTime = newTime; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + mStartTime = newTime; #else - gettimeofday(&mStartTime, 0); + gettimeofday(&mStartTime, 0); #endif #endif - } + } - /// Returns the time in ms since the last call to reset or since - /// the btClock was created. - unsigned long int getTimeMilliseconds() - { + /// Returns the time in ms since the last call to reset or since + /// the btClock was created. + unsigned long int getTimeMilliseconds() + { #ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + + // Recompute the number of millisecond ticks elapsed. + msecTicks = (unsigned long)(1000 * elapsedTime / mClockFrequency.QuadPart); + } - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; - // Recompute the number of millisecond ticks elapsed. - msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - } - - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; - - return msecTicks; + return msecTicks; #else - + #ifdef __CELLOS_LV2__ - __int64 freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq) / 1000.0; - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - - return (newTime-mStartTime) / dFreq; + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq) / 1000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + SYS_TIMEBASE_GET( newTime ); + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (unsigned long int)((double(newTime-mStartTime)) / dFreq); #else - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + - (currentTime.tv_usec - mStartTime.tv_usec) / 1000; + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + + (currentTime.tv_usec - mStartTime.tv_usec) / 1000; #endif //__CELLOS_LV2__ #endif + } + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds() + { +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; } - /// Returns the time in us since the last call to reset or since - /// the Clock was created. - unsigned long int getTimeMicroseconds() - { -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + mClockFrequency.QuadPart); - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - } - - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; - - // Convert to microseconds. - unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / - mClockFrequency.QuadPart); - - return usecTicks; + return usecTicks; #else #ifdef __CELLOS_LV2__ - __int64 freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq)/ 1000000.0; - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - - return (newTime-mStartTime) / dFreq; + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + + return (unsigned long int)((double(newTime-mStartTime)) / dFreq); #else - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + - (currentTime.tv_usec - mStartTime.tv_usec); + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + + (currentTime.tv_usec - mStartTime.tv_usec); #endif//__CELLOS_LV2__ #endif - } + } - private: +private: #ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER mClockFrequency; - DWORD mStartTick; - LONGLONG mPrevElapsedTime; - LARGE_INTEGER mStartTime; + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; #else #ifdef __CELLOS_LV2__ - uint64_t mStartTime; + uint64_t mStartTime; #else - struct timeval mStartTime; + struct timeval mStartTime; #endif #endif //__CELLOS_LV2__ - }; +}; #endif //USE_BT_CLOCK -#ifdef USE_QUICKPROF -#include -#include -#include -#include +///A node in the Profile Hierarchy Tree +class CProfileNode { +public: + CProfileNode( const char * name, CProfileNode * parent ); + ~CProfileNode( void ); + CProfileNode * Get_Sub_Node( const char * name ); + CProfileNode * Get_Parent( void ) { return Parent; } + CProfileNode * Get_Sibling( void ) { return Sibling; } + CProfileNode * Get_Child( void ) { return Child; } -namespace hidden -{ - /// A simple data structure representing a single timed block - /// of code. - struct ProfileBlock - { - ProfileBlock() - { - currentBlockStartMicroseconds = 0; - currentCycleTotalMicroseconds = 0; - lastCycleTotalMicroseconds = 0; - totalMicroseconds = 0; - } + void CleanupMemory(); + void Reset( void ); + void Call( void ); + bool Return( void ); - /// The starting time (in us) of the current block update. - unsigned long int currentBlockStartMicroseconds; + const char * Get_Name( void ) { return Name; } + int Get_Total_Calls( void ) { return TotalCalls; } + float Get_Total_Time( void ) { return TotalTime; } - /// The accumulated time (in us) spent in this block during the - /// current profiling cycle. - unsigned long int currentCycleTotalMicroseconds; +protected: - /// The accumulated time (in us) spent in this block during the - /// past profiling cycle. - unsigned long int lastCycleTotalMicroseconds; - - /// The total accumulated time (in us) spent in this block. - unsigned long int totalMicroseconds; - }; + const char * Name; + int TotalCalls; + float TotalTime; + unsigned long int StartTime; + int RecursionCounter; + CProfileNode * Parent; + CProfileNode * Child; + CProfileNode * Sibling; }; -/// A static class that manages timing for a set of profiling blocks. -class btProfiler +///An iterator to navigate through the tree +class CProfileIterator { public: - /// A set of ways to retrieve block timing data. - enum BlockTimingMethod - { - /// The total time spent in the block (in seconds) since the - /// profiler was initialized. - BLOCK_TOTAL_SECONDS, + // Access all the children of the current parent + void First(void); + void Next(void); + bool Is_Done(void); + bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } - /// The total time spent in the block (in ms) since the - /// profiler was initialized. - BLOCK_TOTAL_MILLISECONDS, + void Enter_Child( int index ); // Make the given child the new parent + void Enter_Largest_Child( void ); // Make the largest child the new parent + void Enter_Parent( void ); // Make the current parent's parent the new parent - /// The total time spent in the block (in us) since the - /// profiler was initialized. - BLOCK_TOTAL_MICROSECONDS, + // Access the current child + const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } + int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } + float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } - /// The total time spent in the block, as a % of the total - /// elapsed time since the profiler was initialized. - BLOCK_TOTAL_PERCENT, + // Access the current parent + const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } + int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } + float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle. - BLOCK_CYCLE_SECONDS, +protected: - /// The time spent in the block (in ms) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MILLISECONDS, + CProfileNode * CurrentParent; + CProfileNode * CurrentChild; - /// The time spent in the block (in us) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MICROSECONDS, - - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle, as a % of the total cycle time. - BLOCK_CYCLE_PERCENT - }; - - /// Initializes the profiler. This must be called first. If this is - /// never called, the profiler is effectively disabled; all other - /// functions will return immediately. The first parameter - /// is the name of an output data file; if this string is not empty, - /// data will be saved on every profiling cycle; if this string is - /// empty, no data will be saved to a file. The second parameter - /// determines which timing method is used when printing data to the - /// output file. - inline static void init(const std::string outputFilename="", - BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS); - - /// Cleans up allocated memory. - inline static void destroy(); - - /// Begins timing the named block of code. - inline static void beginBlock(const std::string& name); - - /// Updates the accumulated time spent in the named block by adding - /// the elapsed time since the last call to startBlock for this block - /// name. - inline static void endBlock(const std::string& name); - - /// Returns the time spent in the named block according to the - /// given timing method. See comments on BlockTimingMethod for details. - inline static double getBlockTime(const std::string& name, - BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS); - - /// Defines the end of a profiling cycle. Use this regularly if you - /// want to generate detailed timing information. This must not be - /// called within a timing block. - inline static void endProfilingCycle(); - - /// A helper function that creates a string of statistics for - /// each timing block. This is mainly for printing an overall - /// summary to the command line. - inline static std::string createStatsString( - BlockTimingMethod method=BLOCK_TOTAL_PERCENT); - -//private: - inline btProfiler(); - - inline ~btProfiler(); - - /// Prints an error message to standard output. - inline static void printError(const std::string& msg) - { - //btAssert(0); - std::cout << "[QuickProf error] " << msg << std::endl; - } - - /// Determines whether the profiler is enabled. - static bool mEnabled; - - /// The clock used to time profile blocks. - static btClock mClock; - - /// The starting time (in us) of the current profiling cycle. - static unsigned long int mCurrentCycleStartMicroseconds; - - /// The duration (in us) of the most recent profiling cycle. - static unsigned long int mLastCycleDurationMicroseconds; - - /// Internal map of named profile blocks. - static std::map mProfileBlocks; - - /// The data file used if this feature is enabled in 'init.' - static std::ofstream mOutputFile; - - /// Tracks whether we have begun print data to the output file. - static bool mFirstFileOutput; - - /// The method used when printing timing data to an output file. - static BlockTimingMethod mFileOutputMethod; - - /// The number of the current profiling cycle. - static unsigned long int mCycleNumber; + CProfileIterator( CProfileNode * start ); + friend class CProfileManager; }; -btProfiler::btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} +///The Manager for the Profile system +class CProfileManager { +public: + static void Start_Profile( const char * name ); + static void Stop_Profile( void ); -btProfiler::~btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} - -void btProfiler::init(const std::string outputFilename, - BlockTimingMethod outputMethod) -{ - mEnabled = true; - - if (!outputFilename.empty()) + static void CleanupMemory(void) { - mOutputFile.open(outputFilename.c_str()); + Root.CleanupMemory(); } - mFileOutputMethod = outputMethod; + static void Reset( void ); + static void Increment_Frame_Counter( void ); + static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } + static float Get_Time_Since_Reset( void ); - mClock.reset(); + static CProfileIterator * Get_Iterator( void ) + { + + return new CProfileIterator( &Root ); + } + static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } - // Set the start time for the first cycle. - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} +private: + static CProfileNode Root; + static CProfileNode * CurrentNode; + static int FrameCounter; + static unsigned long int ResetTime; +}; -void btProfiler::destroy() -{ - if (!mEnabled) - { - return; + +///ProfileSampleClass is a simple way to profile a function's scope +///Use the BT_PROFILE macro at the start of scope to time +class CProfileSample { +public: + CProfileSample( const char * name ) + { + CProfileManager::Start_Profile( name ); } - if (mOutputFile.is_open()) - { - mOutputFile.close(); + ~CProfileSample( void ) + { + CProfileManager::Stop_Profile(); } +}; - // Destroy all ProfileBlocks. - while (!mProfileBlocks.empty()) - { - delete (*mProfileBlocks.begin()).second; - mProfileBlocks.erase(mProfileBlocks.begin()); - } -} - -void btProfiler::beginBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - if (name.empty()) - { - printError("Cannot allow unnamed profile blocks."); - return; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // Create a new ProfileBlock. - mProfileBlocks[name] = new hidden::ProfileBlock(); - block = mProfileBlocks[name]; - } - - // We do this at the end to get more accurate results. - block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds(); -} - -void btProfiler::endBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - // We do this at the beginning to get more accurate results. - unsigned long int endTick = mClock.getTimeMicroseconds(); - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return; - } - - unsigned long int blockDuration = endTick - - block->currentBlockStartMicroseconds; - block->currentCycleTotalMicroseconds += blockDuration; - block->totalMicroseconds += blockDuration; -} - -double btProfiler::getBlockTime(const std::string& name, - BlockTimingMethod method) -{ - if (!mEnabled) - { - return 0; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return 0; - } - - double result = 0; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - result = (double)block->totalMicroseconds * (double)0.000001; - break; - case BLOCK_TOTAL_MILLISECONDS: - result = (double)block->totalMicroseconds * (double)0.001; - break; - case BLOCK_TOTAL_MICROSECONDS: - result = (double)block->totalMicroseconds; - break; - case BLOCK_TOTAL_PERCENT: - { - double timeSinceInit = (double)mClock.getTimeMicroseconds(); - if (timeSinceInit <= 0) - { - result = 0; - } - else - { - result = 100.0 * (double)block->totalMicroseconds / - timeSinceInit; - } - break; - } - case BLOCK_CYCLE_SECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.000001; - break; - case BLOCK_CYCLE_MILLISECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.001; - break; - case BLOCK_CYCLE_MICROSECONDS: - result = (double)block->lastCycleTotalMicroseconds; - break; - case BLOCK_CYCLE_PERCENT: - { - if (0 == mLastCycleDurationMicroseconds) - { - // We have not yet finished a cycle, so just return zero - // percent to avoid a divide by zero error. - result = 0; - } - else - { - result = 100.0 * (double)block->lastCycleTotalMicroseconds / - mLastCycleDurationMicroseconds; - } - break; - } - default: - break; - } - - return result; -} - -void btProfiler::endProfilingCycle() -{ - if (!mEnabled) - { - return; - } - - // Store the duration of the cycle that just finished. - mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() - - mCurrentCycleStartMicroseconds; - - // For each block, update data for the cycle that just finished. - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - hidden::ProfileBlock* block = (*iter).second; - block->lastCycleTotalMicroseconds = - block->currentCycleTotalMicroseconds; - block->currentCycleTotalMicroseconds = 0; - } - - if (mOutputFile.is_open()) - { - // Print data to the output file. - if (mFirstFileOutput) - { - // On the first iteration, print a header line that shows the - // names of each profiling block. - mOutputFile << "#cycle, "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << (*iter).first << ", "; - } - - mOutputFile << std::endl; - mFirstFileOutput = false; - } - - mOutputFile << mCycleNumber << ", "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << getBlockTime((*iter).first, mFileOutputMethod) - << ", "; - } - - mOutputFile << std::endl; - } - - ++mCycleNumber; - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} - -std::string btProfiler::createStatsString(BlockTimingMethod method) -{ - if (!mEnabled) - { - return ""; - } - - std::string s; - std::string suffix; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - suffix = "s"; - break; - case BLOCK_TOTAL_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_TOTAL_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_TOTAL_PERCENT: - { - suffix = "%"; - break; - } - case BLOCK_CYCLE_SECONDS: - suffix = "s"; - break; - case BLOCK_CYCLE_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_CYCLE_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_CYCLE_PERCENT: - { - suffix = "%"; - break; - } - default: - break; - } - - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - if (iter != mProfileBlocks.begin()) - { - s += "\n"; - } - - char blockTime[64]; - sprintf(blockTime, "%lf", getBlockTime((*iter).first, method)); - - s += (*iter).first; - s += ": "; - s += blockTime; - s += " "; - s += suffix; - } - - return s; -} +#if !defined(BT_NO_PROFILE) +#define BT_PROFILE( name ) CProfileSample __profile( name ) +#else +#define BT_PROFILE( name ) +#endif -#define BEGIN_PROFILE(a) btProfiler::beginBlock(a) -#define END_PROFILE(a) btProfiler::endBlock(a) -#else //USE_QUICKPROF -#define BEGIN_PROFILE(a) -#define END_PROFILE(a) - -#endif //USE_QUICKPROF #endif //QUICK_PROF_H diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 01ad93e786a..3c96857d4eb 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -18,57 +18,123 @@ subject to the following restrictions: #define SIMD___SCALAR_H #include +#include //size_t for MSVC 6.0 #include #include #include +#define BT_BULLET_VERSION 272 + +inline int btGetVersion() +{ + return BT_BULLET_VERSION; +} + +#if defined(DEBUG) || defined (_DEBUG) +#define BT_DEBUG +#endif + + #ifdef WIN32 #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED128(a) a #else - #define BT_HAS_ALIGNED_ALOCATOR - #pragma warning(disable:4530) - #pragma warning(disable:4996) - #pragma warning(disable:4786) + #define BT_HAS_ALIGNED_ALLOCATOR + #pragma warning(disable : 4324) // disable padding warning +// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. +// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines +// #pragma warning(disable:4786) // Disable the "debug name too long" warning + #define SIMD_FORCE_INLINE __forceinline #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a + #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a #ifdef _XBOX #define BT_USE_VMX128 + + #include + #define BT_HAVE_NATIVE_FSEL + #define btFsel(a,b,c) __fsel((a),(b),(c)) #else #define BT_USE_SSE #endif #endif //__MINGW32__ #include +#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert +#else + #define btAssert(x) +#endif //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + #else #if defined (__CELLOS_LV2__) #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) #ifndef assert #include #endif #define btAssert assert //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + #else +#ifdef USE_LIBSPE2 + + #define SIMD_FORCE_INLINE __inline + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif + #define btAssert assert + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + + #define btLikely(_c) __builtin_expect((_c), 1) + #define btUnlikely(_c) __builtin_expect((_c), 0) + + +#else //non-windows systems #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED128(a) a #ifndef assert #include #endif + +#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot #define btFullAssert(x) + #define btLikely(_c) _c + #define btUnlikely(_c) _c + + +#endif // LIBSPE2 + #endif //__CELLOS_LV2__ #endif @@ -81,6 +147,7 @@ subject to the following restrictions: #endif #endif +///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. #if defined(BT_USE_DOUBLE_PRECISION) typedef double btScalar; #else @@ -88,6 +155,19 @@ typedef float btScalar; #endif + +#define BT_DECLARE_ALIGNED_ALLOCATOR() \ + SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ + + + #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } @@ -105,12 +185,34 @@ SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } #else -SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrtf(x); } +SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) +{ +#ifdef USE_APPROXIMATION + double x, z, tempf; + unsigned long *tfptr = ((unsigned long *)&tempf) + 1; + + tempf = y; + *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ + x = tempf; + z = y*btScalar(0.5); /* hoist out the “/2” */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + return x*y; +#else + return sqrtf(y); +#endif +} SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { + btAssert(x <= btScalar(1.)); + return acosf(x); +} SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } @@ -159,14 +261,6 @@ SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { return (!((a) <= eps)); } -/*SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } -SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } -SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } -SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } -SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } -SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } -*/ SIMD_FORCE_INLINE int btIsNegative(btScalar x) { return x < btScalar(0.0) ? 1 : 0; @@ -177,5 +271,151 @@ SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +#ifndef btFsel +SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) +{ + return a >= 0 ? b : c; +} +#endif +#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) + + +SIMD_FORCE_INLINE bool btMachineIsLittleEndian() +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + return true; + else + return false; +} + + + +///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 +///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html +SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) +{ + // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero + // Rely on positive value or'ed with its negative having sign bit on + // and zero value or'ed with its negative (which is still zero) having sign bit off + // Use arithmetic shift right, shifting the sign bit through all 32 bits + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) +{ + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return static_cast((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) +{ +#ifdef BT_HAVE_NATIVE_FSEL + return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); +#else + return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; +#endif +} + +template SIMD_FORCE_INLINE void btSwap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +//PCK: endian swapping functions +SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) +{ + return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) +{ + return static_cast(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); +} + +SIMD_FORCE_INLINE unsigned btSwapEndian(int val) +{ + return btSwapEndian((unsigned)val); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) +{ + return btSwapEndian((unsigned short) val); +} + +///btSwapFloat uses using char pointers to swap the endianness +////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values +///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. +///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. +///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. +///so instead of returning a float/double, we return integer/long long integer +SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) +{ + unsigned int a = 0; + unsigned char *dst = (unsigned char *)&a; + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + return a; +} + +// unswap using char pointers +SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) +{ + float d = 0.0f; + unsigned char *src = (unsigned char *)&a; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + + return d; +} + + +// swap using char pointers +SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) +{ + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + +} + +// unswap using char pointers +SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) +{ + double d = 0.0; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + + return d; +} + #endif //SIMD___SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h index d219b453537..050d44bdfe9 100644 --- a/extern/bullet2/src/LinearMath/btStackAlloc.h +++ b/extern/bullet2/src/LinearMath/btStackAlloc.h @@ -21,6 +21,7 @@ Nov.2006 #define BT_STACK_ALLOC #include "btScalar.h" //for btAssert +#include "btAlignedAllocator.h" struct btBlock { @@ -28,7 +29,7 @@ struct btBlock unsigned char* address; }; -///StackAlloc provides some fast stack-based memory allocator (LIFO last-in first-out) +///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out) class btStackAlloc { public: @@ -39,7 +40,7 @@ public: inline void create(unsigned int size) { destroy(); - data = new unsigned char[size]; + data = (unsigned char*) btAlignedAlloc(size,16); totalsize = size; } inline void destroy() @@ -49,12 +50,20 @@ public: if(usedsize==0) { - if(!ischild) delete[] data; + if(!ischild && data) + btAlignedFree(data); + data = 0; usedsize = 0; } } + + int getAvailableMemory() const + { + return static_cast(totalsize - usedsize); + } + unsigned char* allocate(unsigned int size) { const unsigned int nus(usedsize+size); @@ -68,7 +77,7 @@ public: return(0); } - inline btBlock* beginBlock() + SIMD_FORCE_INLINE btBlock* beginBlock() { btBlock* pb = (btBlock*)allocate(sizeof(btBlock)); pb->previous = current; @@ -76,7 +85,7 @@ public: current = pb; return(pb); } - inline void endBlock(btBlock* block) + SIMD_FORCE_INLINE void endBlock(btBlock* block) { btAssert(block==current); //Raise(L"Unmatched blocks"); diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h index 2d55fec83a4..a8cdb428100 100644 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -21,7 +21,8 @@ subject to the following restrictions: #include "btMatrix3x3.h" -///btTransform supports rigid transforms (only translation and rotation, no scaling/shear) +///The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear. +///It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. class btTransform { @@ -92,13 +93,7 @@ public: m_basis.getRotation(q); return q; } - template - void setValue(const Scalar2 *m) - { - m_basis.setValue(m); - m_origin.setValue(&m[12]); - } - + void setFromOpenGLMatrix(const btScalar *m) { @@ -194,8 +189,13 @@ btTransform::operator*(const btTransform& t) const { return btTransform(m_basis * t.m_basis, (*this)(t.m_origin)); -} +} +SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) +{ + return ( t1.getBasis() == t2.getBasis() && + t1.getOrigin() == t2.getOrigin() ); +} #endif @@ -204,3 +204,4 @@ btTransform::operator*(const btTransform& t) const + diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h index bc42fd166b6..86ee1da5edf 100644 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -25,7 +25,7 @@ subject to the following restrictions: #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ -inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) { return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), @@ -33,7 +33,7 @@ inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& sup } -inline void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) +SIMD_FORCE_INLINE void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) { if (btFabs(n.z()) > SIMDSQRT12) { // choose p in y-z plane @@ -70,7 +70,9 @@ public: predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); predictedOrn.normalize(); #else - //exponential map + //Exponential map + //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia + btVector3 axis; btScalar fAngle = angvel.length(); //limit the angular motion @@ -121,6 +123,10 @@ public: dmat.getRotation(dorn); #endif//USE_QUATERNION_DIFF + ///floating point inaccuracy can lead to w component > 1..., which breaks + + dorn.normalize(); + angle = dorn.getAngle(); axis = btVector3(dorn.x(),dorn.y(),dorn.z()); axis[3] = btScalar(0.); diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h index 74d41ad2a19..96548c6ba60 100644 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -27,6 +27,10 @@ class btVector3 : public btQuadWord { public: SIMD_FORCE_INLINE btVector3() {} + SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q) + : btQuadWord(q) + { + } SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) @@ -43,6 +47,7 @@ public: SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) { + m_x += v.x(); m_y += v.y(); m_z += v.z(); return *this; } @@ -399,4 +404,50 @@ public: }; + +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) +{ + #ifdef BT_USE_DOUBLE_PRECISION + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[7]; + dest[1] = src[6]; + dest[2] = src[5]; + dest[3] = src[4]; + dest[4] = src[3]; + dest[5] = src[2]; + dest[6] = src[1]; + dest[7] = src[0]; +#else + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[3]; + dest[1] = src[2]; + dest[2] = src[1]; + dest[3] = src[0]; +#endif //BT_USE_DOUBLE_PRECISION +} +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) +{ + for (int i=0;i<4;i++) + { + btSwapScalarEndian(sourceVec[i],destVec[i]); + } + +} + +///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) +{ + + btVector3 swappedVec; + for (int i=0;i<4;i++) + { + btSwapScalarEndian(vector[i],swappedVec[i]); + } + vector = swappedVec; +} + #endif //SIMD__VECTOR3_H diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 19702782b0d..59b823982f5 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -22,74 +22,11 @@ elif sys.platform=='darwin': cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] linearmath_src = env.Glob("LinearMath/*.cpp") -bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", - "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", - "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", - "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", - "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", - "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", - "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", - "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", - "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp", - "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp", - "BulletDynamics/Dynamics/btRigidBody.cpp", - "BulletDynamics/Vehicle/btRaycastVehicle.cpp", - "BulletDynamics/Dynamics/Bullet-C-API.cpp", - "BulletDynamics/Vehicle/btWheelInfo.cpp"] -collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp", - "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", - "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", - "BulletCollision/BroadphaseCollision/btDispatcher.cpp", - "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", - "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", - "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", - "BulletCollision/CollisionDispatch/btCollisionObject.cpp", - "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", - "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btManifoldResult.cpp", - "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", - "BulletCollision/CollisionDispatch/btUnionFind.cpp", - "BulletCollision/CollisionShapes/btBoxShape.cpp", - "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCollisionShape.cpp", - "BulletCollision/CollisionShapes/btCompoundShape.cpp", - "BulletCollision/CollisionShapes/btConcaveShape.cpp", - "BulletCollision/CollisionShapes/btConeShape.cpp", - "BulletCollision/CollisionShapes/btConvexHullShape.cpp", - "BulletCollision/CollisionShapes/btConvexShape.cpp", - "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCylinderShape.cpp", - "BulletCollision/CollisionShapes/btEmptyShape.cpp", - "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", - "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", - "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", - "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", - "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", - "BulletCollision/CollisionShapes/btSphereShape.cpp", - "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", - "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", - "BulletCollision/CollisionShapes/btTriangleCallback.cpp", - "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", - "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", - "BulletCollision/CollisionShapes/btTriangleMesh.cpp", - "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", - "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", - "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", - "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", - "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"] + +bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") + +collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") +collision_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") incs = '. BulletCollision BulletDynamics LinearMath' diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h index 8417ccc671f..4b14f6d00f3 100644 --- a/extern/bullet2/src/btBulletCollisionCommon.h +++ b/extern/bullet2/src/btBulletCollisionCommon.h @@ -32,23 +32,28 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexHullShape.h" #include "BulletCollision/CollisionShapes/btTriangleMesh.h" #include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btTetrahedronShape.h" #include "BulletCollision/CollisionShapes/btEmptyShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" ///Narrowphase Collision Detector #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" + +//btSphereBoxCollisionAlgorithm is broken, use gjk for now +//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" ///Dispatching and generation of collision pairs (broadphase) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" - +#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" ///Math library & Utils #include "LinearMath/btQuaternion.h" diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h index 25f016cba8a..b95972cd15d 100644 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -20,6 +20,8 @@ subject to the following restrictions: #include "btBulletCollisionCommon.h" #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h" + #include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -27,9 +29,11 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" - +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + ///Vehicle simulation, with wheel contact simulated by raycasts #include "BulletDynamics/Vehicle/btRaycastVehicle.h" diff --git a/extern/glew/SConscript b/extern/glew/SConscript index 32b3b478113..3badbeb040e 100644 --- a/extern/glew/SConscript +++ b/extern/glew/SConscript @@ -9,4 +9,4 @@ sources = ['src/glew.c'] defs = '' incs = 'include' -env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['intern', 'player'], priority=[25, 50]) +env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['blender', 'player'], priority=[50, 50]) diff --git a/extern/glew/include/GL/glew.h b/extern/glew/include/GL/glew.h index fd3fe10b938..6b88e6eb4c9 100644 --- a/extern/glew/include/GL/glew.h +++ b/extern/glew/include/GL/glew.h @@ -58,8 +58,11 @@ ** version 1.2.1 Specification. */ -/* added this here for blender, should be moved elsewhere */ +#define BLENDER_CHANGES + +#ifdef BLENDER_CHANGES #define GLEW_STATIC +#endif #ifndef __glew_h__ #define __glew_h__ @@ -1805,6 +1808,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuin typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); +#ifndef BLENDER_CHANGES #define glAttachShader GLEW_GET_FUN(__glewAttachShader) #define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) #define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) @@ -1898,6 +1902,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint si #define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) #define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) #define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) +#endif #define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) diff --git a/extern/glew/src/glew.c b/extern/glew/src/glew.c index 593f0e58f7c..f20463630dc 100644 --- a/extern/glew/src/glew.c +++ b/extern/glew/src/glew.c @@ -1836,6 +1836,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; +#ifndef BLENDER_CHANGES r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r; r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r; r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r; @@ -1929,6 +1930,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r; r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r; r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r; +#endif return r; } diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h index 5d425a8dc94..450fde187b5 100644 --- a/intern/SoundSystem/SoundDefines.h +++ b/intern/SoundSystem/SoundDefines.h @@ -44,7 +44,7 @@ enum /* general stuff */ #define NUM_BUFFERS 128 -#define NUM_SOURCES 16 +#define NUM_SOURCES 24 /* 24 is the limit for openal on windows, was 16 in 2.47 and previous */ /* openal related stuff */ #define AL_LOOPING 0x1007 diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp index 82ed1c8a808..c660e9aecba 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.cpp +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -294,6 +294,10 @@ SND_OpenALDevice::SND_OpenALDevice() // let openal generate its sources if (alc_error == ALC_NO_ERROR) { + int i; + + for (i=0;i" because it conflits with Window defined in winlay.h +typedef int GHOST_TEmbedderWindowID; +#endif // _WIN32 + /** * A timer task callback routine. * @param task The timer task object. diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index 78c25997806..067c8deee32 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -402,7 +402,8 @@ GHOST_IWindow* GHOST_SystemCarbon::createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual + bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow ) { GHOST_IWindow* window = 0; diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h index 2afc8e0885a..2a1d6325784 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -103,6 +103,7 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( @@ -113,7 +114,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index f5c7c08ebfe..feb0fe39040 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -169,7 +169,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual) + bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow ) { GHOST_Window* window = 0; window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual); @@ -917,8 +917,12 @@ GHOST_TUns8* GHOST_SystemWin32::getClipboard(int flag) const char *buffer; char *temp_buff; - if ( OpenClipboard(NULL) ) { + if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) { HANDLE hData = GetClipboardData( CF_TEXT ); + if (hData == NULL) { + CloseClipboard(); + return NULL; + } buffer = (char*)GlobalLock( hData ); temp_buff = (char*) malloc(strlen(buffer)+1); diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index c26ef25e366..00f7af00162 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -109,13 +109,14 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual); + const bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** ** Event management functionality diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 3003e0b8b14..1b90831986d 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -191,6 +191,7 @@ getMainDisplayDimensions( * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -203,14 +204,18 @@ createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual + bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow ){ GHOST_WindowX11 * window = 0; if (!m_display) return 0; + + + window = new GHOST_WindowX11 ( - this,m_display,title, left, top, width, height, state, type, stereoVisual + this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual ); if (window) { @@ -511,7 +516,9 @@ GHOST_SystemX11::processEvent(XEvent *xe) } break; } - + + case DestroyNotify: + ::exit(-1); // We're not interested in the following things.(yet...) case NoExpose : case GraphicsExpose : diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 726cdfb2fff..c67f7d81e60 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -108,6 +108,7 @@ public: * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -119,9 +120,10 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0 ); - + /** * @section Interface Inherited from GHOST_ISystem */ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index fef58d071a4..c30b915c019 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -437,7 +437,13 @@ GHOST_TSuccess GHOST_WindowWin32::swapBuffers() // adding a glFinish() here is to prevent Geforce in 'full scene antialias' mode // from antialising the Blender window. Officially a swapbuffers does a glFinish // itself, so this feels really like a hack... but it won't harm. (ton) - glFinish(); + // + // disabled this because it is a performance killer for the game engine, glFinish + // forces synchronization with the graphics card and calling it is strongly + // discouraged for good performance. (brecht) + // + // glFinish(); + return ::SwapBuffers(m_hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index a98a59377c7..7b0606c40b7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -138,6 +138,7 @@ GHOST_WindowX11( GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type, const bool stereoVisual ) : @@ -205,21 +206,57 @@ GHOST_WindowX11( // create the window! - m_window = - XCreateWindow( - m_display, - RootWindow(m_display, m_visual->screen), - left, - top, - width, - height, - 0, // no border. - m_visual->depth, - InputOutput, - m_visual->visual, - CWBorderPixel|CWColormap|CWEventMask, - &xattributes - ); + ; + if (parentWindow == 0) { + m_window = + XCreateWindow( + m_display, + RootWindow(m_display, m_visual->screen), + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + } else { + + Window root_return; + int x_return,y_return; + unsigned int w_return,h_return,border_w_return,depth_return; + GHOST_TInt32 screen_x, screen_y; + + XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return, + &w_return, &h_return, &border_w_return, &depth_return ); + + left = 0; + top = 0; + width = w_return; + height = h_return; + + + m_window = XCreateWindow( + m_display, + parentWindow, // reparent against embedder + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + + XSelectInput(m_display , parentWindow, SubstructureNotifyMask); + + } // Are we in fullscreen mode - then include diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 1203dbde80d..abb5c131cb7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -64,6 +64,7 @@ public: * @param width The width the window. * @param height The height the window. * @param state The state the window is initially opened with. + * @param parentWindow Parent (embedder) window * @param type The type of drawing context installed in this window. * @param stereoVisual Stereo visual for quad buffered stereo. */ @@ -76,6 +77,7 @@ public: GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false ); diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index d004e7952cc..1d4c753802b 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -58,8 +58,8 @@ #ifndef MEM_MALLOCN_H #define MEM_MALLOCN_H -/* Needed for FILE* */ -#include "stdio.h" +#include "stdio.h" /* needed for FILE* */ +#include "BLO_sys_types.h" /* needed for uintptr_t */ #ifdef __cplusplus extern "C" { @@ -123,6 +123,12 @@ extern "C" { /** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */ void MEM_set_memory_debug(void); + /* Memory usage stats + * - MEM_get_memory_in_use is all memory + * - MEM_get_mapped_memory_in_use is a subset of all memory */ + uintptr_t MEM_get_memory_in_use(void); + uintptr_t MEM_get_mapped_memory_in_use(void); + int MEM_get_memory_blocks_in_use(void); #ifdef __cplusplus } diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index a36549d0cc7..7bdca7339fc 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -49,8 +49,6 @@ #include "MEM_guardedalloc.h" -#include "BLO_sys_types.h" // needed for intptr_t - /* --------------------------------------------------------------------- */ /* Data definition */ /* --------------------------------------------------------------------- */ @@ -113,8 +111,8 @@ static const char *check_memlist(MemHead *memh); /* --------------------------------------------------------------------- */ -volatile int totblock= 0; -volatile uintptr_t mem_in_use= 0, mmap_in_use= 0; +static volatile int totblock= 0; +static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0; static volatile struct localListBase _membase; static volatile struct localListBase *membase = &_membase; @@ -698,4 +696,19 @@ static const char *check_memlist(MemHead *memh) return(name); } +uintptr_t MEM_get_memory_in_use(void) +{ + return mem_in_use; +} + +uintptr_t MEM_get_mapped_memory_in_use(void) +{ + return mmap_in_use; +} + +int MEM_get_memory_blocks_in_use(void) +{ + return totblock; +} + /* eof */ diff --git a/intern/iksolver/CMakeLists.txt b/intern/iksolver/CMakeLists.txt index da69f2a3332..736a2a78bb2 100644 --- a/intern/iksolver/CMakeLists.txt +++ b/intern/iksolver/CMakeLists.txt @@ -28,5 +28,5 @@ SET(INC intern ../moto/include ../memutil) FILE(GLOB SRC intern/*.cpp) -BLENDERLIB_NOLIST(blender_IK "${SRC}" "${INC}") +BLENDERLIB(bf_IK "${SRC}" "${INC}") #, libtype=['blender'], priority = [10] ) diff --git a/intern/iksolver/SConscript b/intern/iksolver/SConscript index 81bf61dfcd8..543ee46487c 100644 --- a/intern/iksolver/SConscript +++ b/intern/iksolver/SConscript @@ -5,4 +5,5 @@ sources = env.Glob('intern/*.cpp') incs = 'intern ../moto/include ../memutil' -env.BlenderLib ('blender_IK', sources, Split(incs), [], libtype='blender', priority=10 ) +env.BlenderLib ('bf_IK', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] ) + diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h index d5ae94cc6b8..b2c3c5e82e2 100644 --- a/intern/memutil/MEM_Allocator.h +++ b/intern/memutil/MEM_Allocator.h @@ -25,6 +25,7 @@ #define __MEM_Allocator_h_included__ 1 #include "guardedalloc/MEM_guardedalloc.h" +#include "guardedalloc/BLO_sys_types.h" #ifdef _MSC_VER #if _MSC_VER < 1300 // 1200 == VC++ 6.0 according to boost diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h index cada06ae523..43149efc977 100644 --- a/intern/memutil/MEM_CacheLimiter.h +++ b/intern/memutil/MEM_CacheLimiter.h @@ -61,11 +61,8 @@ class MEM_CacheLimiter; #ifndef __MEM_cache_limiter_c_api_h_included__ extern "C" { - extern void MEM_CacheLimiter_set_maximum(int m); - extern int MEM_CacheLimiter_get_maximum(); - // this is rather _ugly_! - extern int mem_in_use; - extern int mmap_in_use; + extern void MEM_CacheLimiter_set_maximum(intptr_t m); + extern intptr_t MEM_CacheLimiter_get_maximum(); }; #endif @@ -141,7 +138,10 @@ public: delete handle; } void enforce_limits() { - int max = MEM_CacheLimiter_get_maximum(); + intptr_t max = MEM_CacheLimiter_get_maximum(); + intptr_t mem_in_use= MEM_get_memory_in_use(); + intptr_t mmap_in_use= MEM_get_mapped_memory_in_use(); + if (max == 0) { return; } diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp index 4cf0ef305d4..d998c9a3e80 100644 --- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp +++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp @@ -27,18 +27,18 @@ #include "MEM_CacheLimiter.h" #include "MEM_CacheLimiterC-Api.h" -static int & get_max() +static intptr_t & get_max() { - static int m = 32*1024*1024; + static intptr_t m = 32*1024*1024; return m; } -void MEM_CacheLimiter_set_maximum(int m) +void MEM_CacheLimiter_set_maximum(intptr_t m) { get_max() = m; } -int MEM_CacheLimiter_get_maximum() +intptr_t MEM_CacheLimiter_get_maximum() { return get_max(); } diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h index 9f56924419e..d85e9af175b 100644 --- a/intern/moto/include/GEN_Map.h +++ b/intern/moto/include/GEN_Map.h @@ -50,6 +50,19 @@ public: m_buckets[i] = 0; } } + + GEN_Map(const GEN_Map& map) + { + m_num_buckets = map.m_num_buckets; + m_buckets = new Entry *[m_num_buckets]; + + for (int i = 0; i < m_num_buckets; ++i) { + m_buckets[i] = 0; + + for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) + insert(entry->m_key, entry->m_value); + } + } int size() { int count=0; diff --git a/intern/moto/include/MT_Matrix4x4.h b/intern/moto/include/MT_Matrix4x4.h index 823541347b7..b4ee84a718b 100644 --- a/intern/moto/include/MT_Matrix4x4.h +++ b/intern/moto/include/MT_Matrix4x4.h @@ -212,6 +212,7 @@ public: MT_Matrix4x4 transposed() const; void transpose(); + MT_Matrix4x4 inverse() const; void invert(); protected: diff --git a/intern/moto/include/MT_Matrix4x4.inl b/intern/moto/include/MT_Matrix4x4.inl index a2aa893a6b3..074bd6e4b05 100644 --- a/intern/moto/include/MT_Matrix4x4.inl +++ b/intern/moto/include/MT_Matrix4x4.inl @@ -52,14 +52,14 @@ GEN_INLINE void MT_Matrix4x4::invert() { } } -/* We do things slightly different here, because the invert() modifies - * the buffer itself. This makes it impossible to make this op right - * away. Like other, still missing facilities, I will repair this - * later. */ -/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */ -/* { */ -/* } */ +GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::inverse() const +{ + MT_Matrix4x4 invmat = *this; + invmat.invert(); + + return invmat; +} GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m) { diff --git a/intern/opennl/superlu/BLO_sys_types.h b/intern/opennl/superlu/BLO_sys_types.h index 5ed3117c890..411a8582f96 100644 --- a/intern/opennl/superlu/BLO_sys_types.h +++ b/intern/opennl/superlu/BLO_sys_types.h @@ -54,6 +54,7 @@ extern "C" { /* The __intXX are built-in types of the visual complier! So we don't * need to include anything else here. */ + typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; @@ -102,6 +103,7 @@ typedef unsigned long uintptr_t; #endif /* ifdef platform for types */ + #ifdef _WIN32 #ifndef htonl #define htonl(x) correctByteOrder(x) diff --git a/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj index 97f70a26db4..01a29d2d24e 100644 --- a/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj +++ b/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj @@ -21,7 +21,7 @@ + + @@ -723,6 +726,9 @@ + + diff --git a/projectfiles_vc7/blender/gpu/BL_gpu.vcproj b/projectfiles_vc7/blender/gpu/BL_gpu.vcproj new file mode 100644 index 00000000000..a780bfc9e0c --- /dev/null +++ b/projectfiles_vc7/blender/gpu/BL_gpu.vcproj @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projectfiles_vc7/blender/nodes/nodes.vcproj b/projectfiles_vc7/blender/nodes/nodes.vcproj index 3e19417de9f..e08a2e04f98 100644 --- a/projectfiles_vc7/blender/nodes/nodes.vcproj +++ b/projectfiles_vc7/blender/nodes/nodes.vcproj @@ -19,7 +19,7 @@ + + @@ -746,6 +749,9 @@ + + diff --git a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj index edf0faf4ab7..faa7f184197 100644 --- a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj +++ b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj @@ -21,7 +21,7 @@ + + @@ -621,6 +624,9 @@ + + diff --git a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj index 76fde7612e3..19394024d5f 100644 --- a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj +++ b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj @@ -19,7 +19,7 @@ eh9TI)opD9K@>k)QzpfcaitS`7f;z(WXtf&~8RjUTiAcjm4pCka%I zk^KQrkjy^FNdqtcUU}^$N#GS!7kOQG06@q8_l5u&Sw!GPDTXux(4Sv;Xlf` z7|BD^Uvd=cf8(V!7~p+UQCFKZ7($eRNF-QlS+%`4HU2A^-c<|9{2^ zP6+71PZbMuWZZA6QY@4*vP5tlWRJP#;k;zx-~ixw$#xvZA6QNZLrr zpQ&Xs)?_Y@_+?*^7Ihi5HXpx0ypZG}zS?*>@vxxe$#=p{7zmQF%;tAB8>upEweZ}l zZS_1Jvc+XhtpA(+rD5K4@D(8;98je8XRQq1RZl2e(Br?Uai@j4-d8d)OFupAM+e8U zg>YZL);@d=QG>gUc*o-bEXa-G=Ug~~M|1Irvlu>F|SC}=8{UUhjq#`bi3)6?lyVDJXT{|XMH)l)M68v-H}l9-~yA`o+Jme;KU?Y);y3*@7w zrl#lOQrFtkbFi|qQbM=aA60XHp+8+ZvcYGe5rqpfBS04@R8!VGoT-?#xzGJZzNZ4I z!TWJsU-l|^snPy*s*@pB?)7tNM_KnnM3g1#@}|>!Dz&m?W)>D{Q&Z~e)3vyTdg~?) zI@l~!URE}YNOJ8-2krM{?x+%=-TP48&1 zQ&cAfaw6diXP_EL@hy~cJ^XU6GaTXAq>m#x$Q5Z1?LYRr9!#ZxcJQ8+@O~nWKi)_8 z2q#4AN9RSnEBJc_ff}j0KSe(~W#!{pD-g0`ZXtPU+K347FJ3OF({rzMZY~Z|Wi2p0gs}x< zcobmswdSfiIw)lti<=ip^!0y9Yin!C047>mT44c!7H%G%tA=_>qA-YJrrp=IoX5+H z3mkItW3>W2eEj15k5|y$Qf9U^sZXD{(*-@4_^d|0`JIsSyTEq;)cA;GrLJZ5 zKsHp5RsT~l?LR8P{TPIecJ8JGyR%zUGVZv%oHyUXJH}8PSzD z^|~YE)$3JzJ0D);KfEOv-1QX?=N+S;i;CX71F+%GYFjH1Tmq+x72T|N{Og|aBdfU4 zYzieRpzm35&hG3&zTu%=v5b#r=F`#RcOIplAHL%y$?>x-UP!;uVoG_beag+vHU4va ztZ3V)H~X9}5rP!3Jo2j}ugqu2%i_uS=O@(cfXAbD$cZ<^ZlF_5JM>i?TUpEbW0iKW ziiw&XjVIgkfdZXkZl2zq(uMTBX_iPvj%Cm!}roILXR8|lQHm0qKur>@_R9THw( zpVebPP`t-%Yeu>IW_LDumi>bS{-%?X-r&f;VJE_1WMmX?*+BbA)z)QQ>2%h2AX?jq ze^@Wz)bP%1u1bJ!iP-i_b9Pn8RlBplzpxxiE#?mQPJp9h`qt&0BGV=K_=A8XEDGUU z=TyrWPmhT4t@E~|#6+XT2HPp4@aPsBNauxCs16m5kGlV6|GBggOI*J-Dq`x{C|R8K zcI~gcopg^?Nyy#iyiw0`aym;Sd5LPiN~wn+IXs|OnHq4j;$@HW5`r!2U08M%@OOW* z-tooS+PZ{KjDz63 zZ~c6uX60UXSGUKVPBR;&yOv?M`|vYt`$cH!Z){c3ueZJH)igne-^Avi3;=yb-?~Id zhScEt52uyLO8q8D`lJ~$HYVY$kMvRw4i1=iOKTsMl(Yn=I5?sg%U6+ z;`_=tfB*UP(XhPpdx%|hbL*!+pT|T4CsJ1Www{oiKThz{nf;mF0aT=(dEa$|ImpdH zK|JD~5Q&9sGchrL27HW}uB}5~f1|-Wt#UNW`2XnJ{Q5{qK%xp~k{1JptRn9CpatiA z-++{)DpAHc6AT>MwtfnsckcIXAJf-}><4jQW`aV`P6007P5nT&nVheh>V^g)LGF}<=7hF!x zDV>Jz!^N~PNB>tJVP{dPhZX+IRvXy?2CS)U5YWnI>=y2qA3-Q;mz?@kuUXU)@W7kN z5@`PGX-)UtD&10IrgynDUqu~G!w0?c(fg)^!0fd$0qm2N#qYng4@W2ViAozWG-fc8 zN&2p|bd|R|+f$rhUak)3@->)V>L_SMM99_32!7;s3YtF|`1%TB_y(vG08Tw&n2c{( zL!tdrI)}53122r5o*`LU$B?P4flwcYOl0!yU(5TBci4G?i!pm-k52XFL* z`zdGgR#GuAFg)Dt<>p>LoOZ4y)k}0q99@43cz5AXwuV(aeturXdP#H+e$%z#WxQCfc%zgUw=g%LumczM# zA6WEBsK?zsrkt6iG(p;ecxrKnomK~C<~h-R1i+$()N_ea&S$0SaM{9Oh3}u$$|@`u zTF{o*#qs-|R5f)&|NBotLu*h~R}(y9($Lgn`R%mQD&_RFrg=yS+~1rA%^loahsDLc z^AGUPpR_T{lz(=@Mkc7pLhPEd$B8yw->V9?eXtjYQhIih#1*XYu~U2C!(O7&UU3je z;IRd3m4|kjK$S|QoSfK1AJ2MxDQ_<7d{nAhq*hP#X0Go(WC=S*CT`eeR?;zWaV5QZ z^Jacv&2bzdcboyEXIc|&-HruTte9Cv|K`o#l{TNtfkL^s`&bH*`=Xe~N~AZ^G`QLt z8gJ&CoQ>yTFqk?R>CC0dvs~&qrb2QalNiLDZ=N@M#VA$nc`60^enCG+aHz=^PL^sH zejFvi%=o>@xw|Lgr>=(>o;=ksmValIdsVH%cnhrW?ai5mBbJ6$yi~sU&K2;atyFo8 z&*(t^<*+J0A0FTXZ0%pc&ilKm5*6oWR2_hFm31y`!ap-jYxE^1CX(2%$=-X0qQ}U> zhjf|DMLc@gW{E7}J(!vifgpq1nJW;|5pdsa!Y*FT2g{q=T5|3PJ{GVh@zv8K@%?lP zNgDi8u3i0^W0H~et>dh4W48VrOHHNW`aHY|=VuQ6C)2n8xnNi?zdVS38Msabz~pQ zx{jZkqP+aq+Sb?Vdqx#e$Di%Lz%tEcgNIXt0!}m2)8GGaT$0VW?PyE}yav|7ZdUzH zAJvsbcpQ5pUm1>P3-NuVNjS^#zj#lB7XhndA?9;hzPr2JyZJLyK6jF4+GYAhaOY>UElA$Hh99nOIXw}xP8u2y z&okSJNh>8;gO--vBv`@rJY4dQCeNPvSHLBK=jg4f)zqrPwsZZnVY+3FxlHG-sg9(} zpWk%zO!kI1b>dV|aVl{c8N|LA(i^Iw2>I`7Y#?@rAYp#)viY)_7v4p(T*Rjn2AQog zjB0V;6Fm6XJUy-PZPY4DGyn;%qt|h%#oc5$mE)0G^B!LqEyjn|K{&U=Wy4h&fTmG`k-$YT@(6LVpB3%&Dce3Rfl$&ylt<@>)z zLl_JJ;NRfX)z?3D+#i%<1MAae>LI?@M=dYT`M^Bkv(Mk9(O4Eg?P7$)Z1g5KctR`* zm(y9EBI7Nkc9k#?2wDz)*i{LXApmpjeqIL6F8PGDj44BK0J-7x?r90bdd}M8b*8f^ zJCR9IOr9-CSy@>OYhus$;^Nt?nhIjG2<*SU@N9-{C>`PezGBbt61x5m2S{AMl$jX~ zMZjOxs{j7m0IH{_r=P&K<&&(eY$>brK?VGJqP_b@cPPK-5z&9;<*Jo4l7(9OgT|OK zdLed-JPn@Y9b7)I$;n4|c6MfTUal13KY8L(9U469S(?%YEX@}(mlG^%-NFNu?=qyddl5PhX@7gaVL*FxZz%`NE@NmHkRQH>E4|zew0cY2#K7m6fIDq|XUITgU zXUOV9yUKMER^*OXb;d{fXd(_c0EdFHtD5+@_M#{A_9%KaLB>Ih6$|sp`NkoZG(gLJ zw9+}2Lj0G0+_^dhUZj6>)25pLgGUY9duTU2S(gn0~9FG2M(J1P6_I z1l#5Fyy0>!iti;Q?&D+Lg!Xe)^|9$(I?XPog;Qw;1`^|D0_4K`HuVuF;3#S*B_$1W zadLWtqsWe!UM3iU2fO4yXE6_?L&ncJA9O zhY2_T>xU6@@7{Z9>VA9NK!Q1Kp(dzeg&jmM*ybklt8%)shQM%Km z(+(DCF6mHSYm=N;=+BXlkL7&uH24fk(F-YyG&gWmKyx^SFN)vI36IYET*P&cTw!d* zFjje&lVyRdnTsGQTYd1>Edre0x7vQG(h=GgO>obELDEdqOch|d+m(HZ7FXu zSs>FK_~cvvy*GU)z_2&H=@mcx2b28)1k^x*Nkmg4(Oa%lte=AKpOvONQ-6}NwJ5KF zl)wquB5!?LLnqTl(47<1Lj=Rg8}FnQkKJjR|9q_i?x*Df-<-3xg~hy9scB+TQl? za#;S4BZT|k%M{)O!2hy^utMN}*+S$Ol<5pam+K?lCR+7Fbo##om;du}S2HS{lGcX` zE8qEU&vY|axBbR~!a*l~&iF(rlOHC1$}&C%sHmt~&!0TuSBqk5M(D^980fS> zo?4ksib8Lh1`|F|FVt-mSm8BTQQOV{2Ltz=K6kaNhk(gOQTRZ2Ng?99xIa6y88p`) zCPBJxcG17&?Y6V_X{LMSQ}K`kmd|p4io>&-%%2E`oUaS5Ue!mG6MYypEQDUhJ`IXB zUk{cAlPRekqdc~JOr@h=4x+@f5|@Hwe)B#t*A@%l%4os z?z@vYYH-^lrGMvfEO-Q!mwq++p7?L>OCox6;cpS@^`u}ZUEwpm6IIo9w zP+-$!e^AlTGU(EV#k?*L1A%0l4$T^SQ=Qzv>G};-GfQb^Q=1zX(cCX;f+>->w9z1s zSD2g09_Do5%wPWg3*fzczwmnD)AxULw(H(lgW@NE_NMn=|pk-=;Phx zDRmGa|KUSawpdWdu+~`LT-zzNJzx@q@(VnqENuf(n<%oN**d4CwdfcO89aDs)Yq@; zi;edEV5{#A;$MS0Ctpz@fqNE7H)~96b#34rtKn-d?D7@?T+(LZ;~#EYAvf+Jf-LSs zf+rJf6&@dv-`*@{5%=vlw-2!To090E->tO^J?K{WZ&^AmEWe(23KW$EY*qxnIkUd_ zx?1f`W%u;7!{wyorSrO~`9X$jf5&UloW>c8CGeh>1+Ixc>tqgmMLFFJdUtYs!kd0g zD$~+nn+!ipIl7K&<4OS?8TptPAFp!R{^bioRYyKPv#n6226r-+kbvUJ{?TAi*Jnf` z0k=0dht-`wX(OFvw;EX(8Eq0X*D#w%veW>11%=3u3JQx!$;rv~UPs`en=R>%@@!DI zvSI4x&23Ur_bYfm&-EtE(^B5ALRy(u#}T<+`hp__eaS0mxA##olCOQ1SrPL@pw7TA zeX*q`sz7w4n%@7i$dK7*eJPeP>Plb{=f6{{0RCWVpbGfv*8j7%WrCK5#_YH$7wMTKQH2U z&7Trpscew!Y6iL2K(W{D`LbD4b?bAX_?{*qwjF19ndEfBkz`6@NCt(jY0cl`XKi+z zO6gDUXz!HV{x;m~NnY{K7hH0K*;Dt3#g_t9<&6K73mAXW zys%3KTKu^=ISFjg?)Zu|rW2;#V8i}FOTG0t1u-=OfeiJ#ci3`q6doT^7aT;LuK;d2 z;V5agv{MW;G~dOT(?#L243G#h0ui><4H9q7WAx znDF5qgW|xEIPd{Ds@3`{GJ7e`w?hu8c`eQfy#iKihJ=6rQrK{Q`s;**PO61&|K2=x z7XFtM5DT$!)Xd58*ck?yY)-%7e}Prk(9kdszIFWQs90H9d6}6%>_!XweaOxzfX%dX zxplKYY;;}~DqKRRqI>UyXl$7y8T_9=#2j!^Usy_GR;lmCeQnX6s_(e?O(%&>*R#>LyB&GD zrP|J2;@BHBjk-KyDEw2UfDP2=)80SJ_SJ1Jbj2YJ62Da$dBAe=uIP&5qIr<7v~Yld zDmmrWn-pXYNF}?ME?>FD$XA->sSq2wn)mZdWhwQ+FPq=Zl_a<3A;kNN9#UM1>?I33 z*{_R)M_rH%P0=TK8h)ptl?vXa2?7BGWRV7SQhUKUh9!vtcEo7Iv#l(yQWQ2B&*Z=q zMh+kVfDFR1goH#bTVNVCz-2u~02vq>8#}3USl}$K!XqIgiU~2;ConzaExj(s zWuRX;Io&%_*FM4`1p6re?#%lbmD*9<+mt07CDv-G?5a3kMNC#6^Y=0zBGt0pdG!~| zEc5SI!pkvh8IZhry>vndN?jn{p@;U(;u9a#9+-vTz&OK3f!h(^_O}o3;t*6ICK_A` zN9e$6Q{WHozX)fvP`S#SH9+jB0;!X?D%|ip;2hBr2MU?&nW5{6P^oP04y1rGMp*D7#d@ zxO6@>Q2s~D(99(i#Af%=;N;YC@5`5a4+m1*Uhntwv9y%RfB&$v`}iNSDfb~Z#+)!$ zJCQpVC>9?g>Xn48Rv_$XWDkstBnx~aRyh@6Ff)3_t%pxcf=|fu*KTRV^>UB*6hVt# zN)_vOWlulBTEM0hU7j^sPI1ITL7-2yjMEo^D5}EQg^BLCwSc(ExDa|uNKa3HPcG{3 zE#v9w36A)4hGCmGN6_W&=>G5T=l~TbCmu)wd`M&Cp%nbYDEjv8pBY)Yy6Db@5$OzK zcjcso>0G%4M(SL=2t;9?wGZA)OKD!=47<^06z{%{PdGYd-K}_mETvO_yMP)%QLh(% z&2QCyf>sRiCQq$Ryn#GIh93vTD)!V4pKO(eF5%eG#S^cVZMe~3vOogi(puncLX^|?OE66+bM715Nai@qY} zAUsCU(Y_U4P$O2B?a(6e<5p*i3h=fJ*-@9|Di?k6cb~Yv{LaUh`&P?|KhV&xa0I4G zh8Qvy9f?Nb(~EXl)vY#~qi;DxE<=|Vmy#0KV#^&c9sjWtcIJ6+C$mH`8K=S>L8j|_ zCl_E6-&7=Z6Zncu-8JXzQBo&$XQidkt1n7>j>j;Uv`s6y6@P2IsOr13&yy6St#y1ld0HR>AVM+6~?ku9ukXy8UyL`RvPc0(T6AqHnC ze%2KMDMr{c`fE1-ixh364d0s+MZjb*k#1nT=}1<&Zi_N&B?F3{m zgI0&j1MSRo$Ku`3)_-(&AC6}#?y~2Io2}#4M&hArCeN2=5qfKW##^!KwF;5doKg7k zaOAhE-q}iivnvlFf?rq3whynE%SOb8wE}n$4W6@)DOb;}E=~s4Bv5!j19Mqh_f*-P zR+%E0E^J-uaF158)ZkpJdJxCnH%w=I%P<)qg$fqYGn1d34`kyooc*sCKxxwn!6jj4 zYD+6i&M>O8N)D!3BZg3L+3ajLCKUHjyeclLy*)#XKlaK8?5B1>)!OC$uWf_PT43hGO`A=Ql}U8F{rJ`22Ny7KC6;V1~f=hu}{rC52&RQ8vj%` zdepDgGeT1#NU*ng(T#W_pCMHX*En!5pF=}v5Pi{>*?KuPalV?nLTNtKL_r&Jsv`sb z6+&LOXQtr&L$~<-AJ6+iZtkn1s(UL20a|DR4(BGwErgw&oi)?@dcXn04#43a2H>Eg z63-QuVRv(~^8MlF^u-RG>f8I1g%+UXmK6g|N6#COi;UuV#M=r_AnJ=!y=Nizk-WJ#z zHn#cV4pw0y?y1i#d9EIU|>)oG6^OF4|Dj< z%}ulVx;m18V9;8jV>h(o>USM3uA)VkccRm=bWzO6@3oyR;zx*!i`(pf=cbrV%ZV7+QlOzWb0>U&6u*n`a;djeKf4JA;of|2B-%3jMCR=m8}YAYc@3ZR!9=aK=tvEn zek{C1?=?+&_1$vQ(~_>_7Y>346ANd!cFM{Z6-Ja};$0ENGL8WB^3Bi0F&BxeJpb(+XD$Mu8V6T zH8C?{AcOJKN@bq_M2xB9X!Sw^wzaKoFJfQ^^o%5mTurM_GHX@roAYKyNYh9d7?1_t z?YstY!*#3A^>S~V;pzU03lzu%IH{>OlsW^S4zyvrZ@4((q8Fyiy(nMQ8I-FYv&T0x{+wi)JB2yut_fL(d_`i%fN=uV zy38S7lU}g1Dy8F(HVL+*5hzN?MiT`Or@dRFb1mccJe;kp1F6Jcbu7$L z(b3yFsi8*I{o`UU(fj-R^I*X>!(46e#MXh0Rhgo_vKJfdxudu~sp7)I&Tzq8m2nkp zaEj~`h;tu1Pwr$t`(p5;|UeQKjXg^53X|%~y8lxLM+=&2!+wAvW^kVbYcY zvUJjxbcv!tgheNEVP#I*k+gQF?PZuiR_qpBtSc(C92+xPnMj@P$6XTTzy3NK0=7cCr%oJPd=?*!eOHyHnD*B;(9_kDnC zqYTyl{`z<=*eW{C7^Gck^mWeQfUgp+Anhvhii9MwXA6Dpd3-bZKshzw$WwN<1ZXpz z3G0JzMu3&%oE|so9i7*V&??)3!YFa-zMC}xlVps(SqGXV?HGu=sMv0I?hPy9+@ibbFl0DE>+9D`c=A zI%+_D3sjTvY&%8}M zsIam?J0GbfcZZnLQX6|w%TT`quQmh*g}`StP{o5%S!qL{U@I(k!tPr(1PXEt+>dwZ z8(P`O>B?;XgoUS=!KDT_V-0=$nG{=CDYI!dV4@M`+s7S6RRcjOBS56PU-rJBhM zzA+Zc5C5S5K=w(0WMW;Mt2vydIKOH^S zZJNcXr^}+;0fez*}oG}}Vc}~L8q8JD9KaTAm z%9C_g9_s}6Sn1I9mldEvuZ4dYxOc84AWnc?;u;0J39Qh1EX%e|yu~1p9i%aeLDb#< z3`n+w0bML7|q6*ByDHh_Ln8**SS?Vv&pI+6%ibg`%P{o+f7N z4{0}EP=gXb$QdUD#k4Dh1mo{+U0tO6Z0zvcwwpWWEg$%a#M1xU-9!o%X9WO!g-x`1~!A2 z@|_jF-jcTpL_9JONtB!{{_<5(3($o)dR1i!$h*gPX5-aNhW5i(9?L&?9aG+3Y5dxa z{&qg_U_E@9_njGV6JSUiw&u|sQ+Gbu1J)N3L&ab@6U|B3tEEAS?C)sDC#;t2PW*T^}>tmCCg0s>2&6_IF?j+h*6CR}S!bHe^NqX5Cd#Rl}a znf=DPp1S4v3aLG}<&-(Uvv1!51CWMKl2g0&H)AsC5NmxHu79#tx2$=ca5GsAtYdLT z@L~H?Akxr#yB)}ER<&)vq>)}utcP1XiwZ-r-(XY)#ZHCz8ppK}GFMNQS+PC^2w`|< zT$-bw*xv^RH4PlcHoPDw+!#DGYnClttd_QU^=K*wJb&0eR~;wN)!y#y>ystMK$3BC zs=AQqs2)ZWm(n2*83P1ibxPu0k7Ua(*T{Vsr#MnDnm1G^E#cz>tLZ}UJ+j#Fg)@V` zpGZ+tLmgJ5u=_#RB=TIV#O$rz0`Q>7RQ51*6sG*YbZ}12R2=W|DDfP|+CU|Lp zV7wr2d@jaFxc-cM{PX;uh22FjRst-g)1d+U#t~?N5XoEbOX_5m^-DluKyGY&GAm+> z+Nm401ikG>z1+OJr)RRtTqu3j1c5FQpf^!kEF)@HimHBom2?Tb8cgMly9*+&N)4SF zXK1S*AcaX)(iy$HWo134$BBaZ`UIeu1nh>tonfVeFYt|yY;iqz3Gl;wq&=_!dHy@A zsp4Upe3kCHiq59ExbZIxxqsorL1%|MEB7b?@P>h*ew1o#d~GdA0(1v4L`fHT(t$tU zzkg@2&3FdHgGn#o;NaoY#4ZMC85vnp17<2hMl&!4YUy3y{-X$Zqma--~KwQ4V zuF2fRr+&M&`AYa^`7z^x0P!)k6}OV6+tQ(tg!_ZbzKYY)VvHO~Jkembs4MQTVQgzQ z!mZ`rz4Muy&go@KU6Z4Ud~pwAz?i_G89|~Pz##qop?I37pdJT}is1f=7&^Nu+2BYQ zX6%9kC)0sKa7nd(Zo-+FZ=sX*->0_a-QU_v?sz$Hfks9swy!Y6#NN3i6JzLOa*cq3 zzhwFBv5HFz`dsZ2UyP^1)7G5JbI0l#Hj1=-xd~`KL6I>-!AR}BD=13fY>|wRGg>Cn zH*iCbtfSG$9(F0h;9q$kog*N~>u2s6i(hwAj;ErdGXQ~VFwwEf759y1JGLkQ0ejjT6~WBVK9t)|oBS z{&>_V=4PNBiNDPzlJo7`*Gkld7*YI8LqFz33P`FpD__k7SE}2Lo){Mra$Zz*o~lo| zR^^b-%~g{mgHq16Is1O?{Z?FQqx~Go?pQV{*1DE^Q#5+7+EuSf?aRByM%ovn&veH3X*?}{iDnWkz_;^LOd`48nb@LbM-gs^<`g-RW8Yl?Z zwAxJ4fV_b#Neq47m?K4&zGkB?C_yd!G=keBfX;B(U=L$?3jHkHRdoj;b6h-hC^MFq#faHX=c^_9=ba*O(LAZ_2u%;tgR2gzmu z_uXIMu+7q?gCg@F=)$-+@$L*{kB|m+9CK^sbiB0Z9_$6SXHhLyT{ZWP^{1PJAD?Us z_r|_fN}XhR)Dt=V-NzDv7%0CVoNkqWZfW|Be`#5|O*#mHeYVN#vjxfq{) zHdc_6PFc*amzkY@)1~)ZudKZ8m8zgyjt9M&nw{1vc-@8sc;8&LI5{#L6W%Sw6K{9- z6dK|kk23H#{guJ#)M7UlL*BX)OL#X&<7?cazIG~R0-MyGN~B3L@};J_Y(3R2(@zjfLh%SQG*S+*6TG=EqN{*33o4uj~bs^SWI9(~27 zl?Am*N`>!uO-?J_pr?}EYJ|vXA2L|czdiBNG^0N?6LJQ!*MhT#`!5BGRkD3pSFqy)WH^AqldN^Bg$HD)S9KVvK0> z*H5y^MlW2RYpI$7n2u=!ZoqJzi7ug4J+UkV8J{D#*ml1S17Jq#O*bWUD=o&H_)jyY znDtjbim37D^>vd^2h*sgmB{eIXjYfDDp`0)tnggrG7GE%lAoDz$=ER{tL_DMADmB9 z=s4Kdqf?*~2pOCb%-e-}G=MP`f{rr|g+!wkvWzY+ni6G5TQd>M@aIi$C(VrN*)`29 zWA7cr{wIs$nSKngwToKyzZ_iv+gt+bH(;@~<)_2zb>Y@TGp-dzRBiGPJSC06zh-uZ_p-sOV~jwNCetHvRt5DfekycSREd}8C*sJ0Tf$Qo^k8vlULIA0(+UabDuV^XBU`XFw0r^Sqo4*b z+Ic{$h@moyDa0RXodb|Vq5fdHV7$W$e8^5{vO8I(3}bi`ztZXzGQKB8pR}>u;=Vs! zh7Yb73Nvc=H3jkd5%jV-r_h@I3w!`JJbdUWE)M)Ml#ixY#W6alXjgS71oX&L}_eY}KALK5k9}KsbkT< zpl}CZAgSI1`RJlHA_WN!UhyUf-P_vA*Cqn<3+E%l(0LT2k3%v|yUH=Jl!Dj{|VIyhzBJB)mw=53TV0^n9qS@_YeA z5B(<|2Z(wHN|+Grd|lPXa_$JF^v2q?SZVgGJh+U0@qD`PG~SweC&qm5Fe7)`dAHbx zIxMDx6;aJ6i$NR)GIIe>4!`T2I_qN|9rr*xVxJVY$TTkOll96o=>LUB!Y~=N;xhiO z)@8%pZNt5Ju`?V$Xz|Yn2CAH(rT9xam$hKhY*|D^MDE8N;RR=q3Jm;$Lk;Z#Gyo*v zc2MbD7$q-_)<v5sXb-Xx@^MPAtO#)Fu2M_#>QAR(`9NeWS}Zvu zW?coXXdrRmC2>edP_ntrxVSLQ6LCkU|3r|3*q^_na%|74xo5oD_$d7;F8H~bafsCc zNa9$-b%V0fp5#F7SM2s#lnFw_uDQ9_I~Pbd!(m2Vp};!Z^EDl#og*u4@XQNp$Rt8U z91)Hl0YZ#kOukh3=791Vk3(z?w@xZ{n5hXjiR$QHu(CSLk%#CVk`*<&5-cRPAGvTw z!q$O*c5qG(J&cpS=H*cl|>BsEH`b^zlKp_yT{++O}Keyr( zSc&vZDT~Dnn)fXq?~ms;d4HCaCA&p^1aaQ(SE{VO^lG)u-m}GN5LpxEcbBW(7)GGLq z_Y1C}il`jMB(1vX*b;XABA&B~=$@&x)pqv?uaV|Y&y&U3;o+sjsdux)W^yrjSQLWW zt?+(9K93iT{?HvN!U%SUb@ro$c4YJZ*d4H=J^iGuGIt>6vJO-kcPhc-fZSqY4(P#X zh>ni7CLeqYE*R{OC5J$nSXh36{#YDh;)v2xMn(cOuwn*>918^#Q^vyL4X729Rx=W$ zB!ByM`_Bs$0Gj)E`q@W5;6+#z7*!i14$tn@Fah=^3)yk9v{Orna1v^}Z9b%wSg6#m z&|jM|4x5dhtQeFj-O!vk4R?TYbJQVm*v7-{EtRnFa=!(q1QiayZ$S0$-@mK)oL9eS zmD8bx76|2z$C(oq_nz=;t>K6hL1U8&XpI~xk3`7nMJ9N#tR?9;5?YKUjLQ(l$6wdY zyeFF6;zP(DCqbnu$fw-jp2G^tS~J~qnSf*0#Y)2UPemS5*c1x-)D|`Hj84{feX7}y zvICC;z;O_nh0S2~CI7hu#8WR$mXSz5r|-aO2pGd4GNk#1EFN;>TV0uxQk8q+2nb;P zBFLpu<>=j{9%f~Va|SygVy{5Uu*3J3258OUMkh@^a#LAI;6lIZl>W6!*4)qI;k+Ul zB;c6CAi;I>lAp7fkfKWqp%Fg2BZHlH(Vk=qYDZR07}B<)WxGD`6=ilgVIPA|5mdm5 zO|PM}v$Hb@s_>mj;k|1>_y{;e9W_oXf?$qae9mwi&EQ$U_BiCdpWYcp&Mc=M0sY;x zPK`uMNov%c-Cpq2{toiftr z)#8T!ob7}^h4wHN#t*mN-QE|d0D#f|6ptX1(?ufV(nDzblgZx`_Hg{|671i=cnG4Wf!E@_3P@L)RlYVzkVl} zUkmPa?jwhm2GaBif+i=<8F{(R^ph&tIaNhsgCwN8Iq3Twzs44TRSXjvL$BhZ0 zR?xQ}j(e*s=h=mVw4j}2K*Sxxygz#5nv#G0Ec>|f8LY0T*x1I3SLAl$Mw*_MpMD{)e#f>m(E;4lAv$y^%l^o1WH6ZgJx>xG({+ZK(L+2tGuSx}O`V zmrv5cu%mICQ!iNsdxf>kVd*yb2ze@wHAgB!yjH-Qt__{W^AaR{;U9cmtL|h7X5vKW zMEjeCJVrpU3IaaHS%Qw|o0WDi^k@F`snQRLmbxgmA|G)+7ZAZr{>*=*$B#yWc>6<4 z0RCA{X`Ht)aBhdWs(D;B>*pvRqfwD)(Hr~JuoYR57YE?{p$zN6?~uN(Vx+R0v*O*kXZo)=q?C(jD%m#U~UKmmONQHXe=_pHDkmBo)UrG^s}_i0Cf~0E0gm3_YsI^ z(*-h7eV|>+2BOijQwNsYRr*aQ!(cBYuiyAz3!CE%6YKyH#Rms7tk^c)@hEr7=BzsC z3BB(>rg@q*LEV&B!INK6@#&M(Qqz>(`+ht1QK#!sKxKsy_yg{_%anaezfY6cGTI7Y zAi={uK2Z}!ns9Qh^J9TQ!L8V1!5M5hGS;Xb>$5rdf2Xjltx)&8#+fThK3Z^>l`#qGJ~tLII8}&kYETKRjM$i!p%EWcSe)&9E@U;@;V@@U{OI} z&cOXF?deS;=Rzd3t<5Xfl*k{W##l>xyp;B|3|trxAZ$O&0(ybq{jQH7J?!Ct@Yb(G zb%?N03bvxu!^5co%CKD(B%||Z+`(Kml?Lk8Y24 zGHBj3>qDx-Ogm>m)rv4!j@rnFKr&^|qF{7n80s4g63kgu8e?6I4iut?ZPNM2KjDPt zs@7k0u^$r1bMPts4Fdl9!a1o z=)qWNmK}FB`5L+&(?EASZZjcOGL`@HCkaU-8c7Ti=-S7anVC4e!qk4YgKO`?0Jq99 z1jR;Nv>03k9?X)VL-p3qV#^IC4;%H^HYo* zt!$cCwuhH@oS#UwZq2Wn-|kGj<5B2JDPXReZE*p})z#IMWm4j`S4v_h**4M>!z}@ z^lqvQTJT8l@Cv+fB8T=T$sI1M>s9<1(1@oH={%Po3IMDA|>AQ^h@5$;lrb2l0&_A40g)BSQf| zf(l`}H8Ocb$Ci|e%AZn_gcvGY8t{g6olep^a(knpYC=-ZQ!%V7rPKm%Ik<>FcDG2GgUX zqvskL8jKKYvdz;+32d+LZY~4x8iIGicsX}(!7vyT6&I(d{VZJTiQbF1$X-b1ZM`!- z%GBd}XWES9-s2g}- zB-wZ}@Khqce!*5KpCFbl(Ec95AhUj3D|7?)@*%7kRuzKruW^I1xdAE~{bu!6<)v(P z*+Fje%grfdAEiyVyMfj=#&hjIUvK7R+l-@@Q|REHD-v=@U-X3?wUskcHuQZS45IK3 z7AWUU86vy=bsCmCs5BQx<4`CAn|w7XxOu&T;Yadw|s*LgWC`X=Eh!KhQ?NU@*{n z0Qeg9sRl#nUoi4v;^TWL>|zMMh(kRLnXfBhR)~J)yH%J1|NZ-ScPJrthpN6UY|fRz zWeF>Rt*N5Lj(l(G>R+vx^&H36Pcc`bmoHzI8I}jYlBdyBz3U%eUZL0WaQt|kh3|w4 zcX6RR2;!<=tTby+|53sSL1;#?i>VxwRB9+cF-9JpJ9KX_H;1+Mw!1Q6QrkjIE*-^a zqWF)pFNQ{?T>>K%bj@aN=IyF~e`e`}WCqe-zc9eIZy^q2m#zROVTTeXWfU22ngtOS>^s7rrJVGeG3@lO-YMDfzwmWI85KrSF>gv0 zL>gR2p+nON#)vAfV*U-fa$sOCPsF7hNo#VytdWeW4xXAv3Tw)kSM!^ro+ZJdVgx)f zgQCOWvRPbpK5HiCm0||i5jmi@5rWWxGI;N~lG0;|mt&tqnn1;83a!0bO;9`IGHvmi z=}+R&+GfltJLU1)DX&j%J)JO`s<9*ZSMSh1Fh5h)J;K4#WQi~#v{s6m!prh!Kv~>8F($Rt^7@UT+n7~q1 z3OGb9O)V{g)r}2b2G6<^NRRXfs8aq6J!UjAJ*uxI)m|y)m>R0Y?e3jru(ZAsmPMaehdA+L{j0*-p-Q z^3q&J9yf9w{|OK`GbxuUR;A|Zmxja>#?e8&&1va|D?|J9&A*RGvU`U1#H)eH%kOaE zda6ha^tFf))x6Qd!c!iTg>Oz7J*udm!0=m6gi{rW3@~omTbd@P#lt{P2eSnaYRKD_vDyuKP1_UDmbqm&N(jo?gU5og~5AUt|Pq z`lAM7ddIja_PIu=G}m9fuHpX3x5uL_^gi};A5>fp_ecjGQ5%t?dJ)_2=EVvIgufC`G-$*jY?_W{GXgbH`A1@ao6&XWWx}avl4_X%w6`8Nh7F zW8CUf*9$;gen=uEG4WsK$smVb#UD=77X5E;)|Aw+ziTkMy1KeA{97)qobf{}JVeju zb`FF(;ul(N9?&GVTR~F(GeqT&%gm%-$;o}+07YF8q}Dw5+M5x23&sN{z{F(2Ne?vW zAiK2y4uA!T^{hl|N&5Z=`;t`p@3{Mj$5i4qZ@G=Rc@)11)-PLu;#IY)6i97JY@*ba4;C+p>aQ}aUaP*r;~M+Aesmcl4hgI0{sfco?&h$`CZOJL~+ z^x1cyRL#>ZJp#OXF6d=}?J+meP%T@cFI=9mm4^)Zu#T6A59K7)y z=9PVLG!5dBYE$d#X>V5cp>)^;9x2#M~v7*IQTi_PN3beEB)Q(0Bsz z)seuOkL%YU)Q%573$q$jnXWu?Z4=1ln$O>BVn?Or_oF5zWmv$&()bA@G56>A#|?&7 zdi97P0MZLTe3Wsj22)pp9O@~HA$jw#advs#GhNl;n;B`-1e3u=!yGty=Qr&FslC94A8_<^3sl*058~W2dH6)B_UFZ+OzImKqk8XX??@xpY`b? zM)}Gd!M`(vw1-3P_rmhVc*F_VbsuKi?`&V`*H^^p=;?J@^8awC%lCfGt5j#Gd+Elg z@h~v(q|ymSSyO3BR&#>fVhQZ^GN^So_->c|5k-vG&Qzk+Yb*bk!6iyZaZz>x?c8l zy1P|yMA~4Csb+P6zy*)-4fKlln7?K~M!+QK{ivG&sWlWv4H%VTAj+f#oD0kM@89qF zN)SX~lLR`u9C1(l#>U3zXa9W%`_c+f02_M+**siaCUxMDy@I2(cDkSyeJi^V+nV;| zcv6&ie4)7$^Mn4yxrXU@T|U!jhJnE)c}S4hAaDK|T-L&ZL<}}(gYr)h?JxO>&Cp?OSsgEJyVPFT@O z{cN1JG7PofE!TzL(7d>&fFXV|MzKz19^#rm6!t_G?$Vl)9q*jCPYB8(m#r(R`WO31 z{0<2q8Vou07s`#Ad38#3O}J+LStD{3n+Y~0TG zbM-TWf}_~jKC?f0SVoTHqbUFLaj5jWmG=F=y1j`i)7LxPy-QWS-)R=l@0v;{T>bNo z%mN&ke-`BUn0nk<;yas)7oa0Td;>M=eLq$1>Mj^m&iWs(_8khhR)$@S`$`^!on4$N zj7!oVf>AS2hdoKf*7oyhM>T1!!+gJc;d?!h&onEdRCp{NCTDTH?s-o-Q$cBbR_KF$ zeX>CA1H`gF0JRsZTW%?q67kIj_#3Xu|1s_l8K>I`2@{k06uu|dc`6l;l6CK|;hsW-;FPzsv z8=jYy$0cI*`;1x2a|F+ru!Hj zUmcRZ$bJrYSY!8KrdP~Z&pdU`x@#fJxs>lQu7`W{1hq=PGQOTEmsmW;@S2(GO+v|t zpl46J()+ZYm_f8)>}6(3c5Qg8;JeYHb0^eew>}YNX@>PI~;z_mbGye*CF91Nrpxs@^HYTsbznv?LupfG`xE`qT#v8m0VSyy> ze>((&ARGGMpXnsL;2q#K`1#QO%^%DclJ47y!x|a;!C2njEfS^+D9n`$o3GpMyu4dl zq?08ou@JvymbfJFBx2a&dPA`K>t~-#<7Xb|u_pyV*}wqtQxP6yo|=#;pSqJ;@EEq}89k+nBVVxx;?q5ql$e>3y& zkCs~B+5UX#61#w)VC_U$a4>wblaxIv@-^p*Bs0u??Zk!M8>FbvwSrl2wXBR2k^w5$ z8jzhM?&oB-5unEA-a^0YeP&Xf!$S8{VAA7I;ZoWIaJJ>Z)7;twlCpq?C-=)2Z0McS ze3K3>C8d`}iMA9-h}oW3ItG!CrVmg-hsqx&mv^)-!k(nWl`>${_8%hO^pQm>P(zCx zU_iOb6tnmZAaS9%;#;BY%n;zmMi4@tDX6_&8jQv2nwr6YD<>r* zJDsVqQ+uabvRk6gioKIC39u0GJ%xtNgV-v-np2&3_4cAbv9#i!&k7d>|GQoR2Irlo z)v3}BJydk`Wq|n+M#%G0#oUh!AZVl7y6+?U=?V}~z!0f`z}bt4jcq#x!$Q5Xs_Hu# z2K(P%ZIoeNHzi5ZzC%fKiBY`-3KrcrHFGT z**!N;LPr-H8X8JJTl?|}_-}fBEnF8$x#gIcm{_lkfpyLN9L0P#tY+4%=(iJDR5ur7 z4kSgX!cJ7+@7~EN zvo~FXaWB*XVObiQnwBj&RtX?UbA4k&t5B28-IGgPJi`<)=xQGjv6?fbY)OHRH%eVS zm1PN(a};oyx!kssHU>#alX=Sj%mGJCfQMzzii`e)t8_7C-6pB;)AIxx-2hEZVyZ6} zS>=IAN>4%39h+8(wvYrIuM;%Jm=G~7EtlJ=;A@(zOj030jY*gOR8Tr+gS z-RJgTsL^ImT3Ok}(ywzM1HbJb;GCpXSgi&trrt8C;BXb$I6B!LF9m^`6v;ehvD_w2 zx!^Mn9%U!U{34{J#DoYjsjQ1VQvqO^7aE95-@h>{O(C^!Q-@LrM z@R%5#jn!3kyES@h>e7IJql!m}gO9V#LG9-#Bktf&4u2{tQbgHYBqdlXyU1!63By1% zUHwDG#oD2HmE)bQ)mp|7079+W`Bldy~ zKBw%!qq*DgdDI@rB$gTAQn@SOq&jK8T&M2pniA&Uo~mXB*6H)Awa@L~6eOie_Ino= zwglE8QRj~Ha%Z}RCFRHh6LDZZdr~H)0ukcmzF=lUz9UB918hI3^<+pqAC&oin7m}M z%0^okG&js3BaRghOxmyfl1A%Z>8WH0;{l&jNF^T(6}nw|Pd{fm*Xk>>JJ|w^BK=mB zGkX%){3*i4*_j(RAZvw)gd}8YO8@;a$Y67`if=y07W2fnK8N&R3W zJ%0SyaC@(%^*!?8iW~%TB%7kLuEAM+zqx?kiGer*1b)2-Th{#Ycx`0s?XzdkF1*+J zlM2XrOv}!4tzX5%)c9aD+cb0@&|4J@FQ0|@_;`!)@p0aaK~bN7tf+7pSaNm_4vRWN z+JovoYdLp!p=;Ii)BozZMFRc&TA1k=I5}~FUk~q5zG^AF;p{0Fg3yyRf?} z+ymICs^1||{<4_m_=8RD zzv#V@r3vxeJDx^V)rk-E=4+Z^6=ro)7MGRaN7ubJ62x^3Mi?r1ATez~!c=D*)W(YJ zsl9_W)ZH1Bn*B$d2SDxTN$oYK2Q(vvx}{mI(7B|!00##S2;hr^$;g8^|p7O>Wk>&urfgruaX($dl( z>`Gn9qFNsaHZ1tl%&YY?v2L@ju+uU!jF_SLEd1AJn4)GbtbUl7iGSQX#U6D~^H%}? zpGqn(44myxfyfG|bHTp|YG&T=ttyKj=)BRB_|vNQ%h_b!33psxF}QFj6esve52BhvlBA<#Q84~?$O;M5;=Ya# zw$h_}H6oxOFV6rl9grxwIoBv~FCwlRFVuddlqDe=lYcXPd6A#bl(tiMU(D~r}wF$3BHPpi)9Q99w;d*gVGYQz3t%PEK)9&R?$Ci!cemF1*)iOzADLZ zTVTkop0!%(iHTP##Kgqx0C8&|0T7(6;qAA3F82v@$(#nuTrhiSxAk8;T1Beez*p48 zj*KOUJg$$yQDQ5-ftiCTe>;kT$49)b|06W@9I^AZ!=~uK8yXUnxkSeK&mB)+v4k1} zRfh@=4vsQYC@PU$`t-p3f3NZ2j>PcS(!mh5(d8_er#ypj9`#N?s0}4HEOz_{^wbT zpnD0Aj{e7bV%h~&CD-C$<#KMVL;}B*O3gGbNF1H5cPXf{dYK2X7!eGExp` z6RTZU6k34Uj4-O35EGRUTTI+qd@xh&WF5GLK`dzyfz$<}F2H3OX3&!fQg5ckkU(5( z2?PTC&?Y#AGf_~epTXCEtefVbn&Ts$U98`=L*}Kofhw;sVO1-F2zMwOb|`@uJg?cG zeirB{i>N4t_9sc9)8iZZr?a?nZE?}d>jIOBwbo__-SGy>EL*&-n?PlzPjEReX>1(lNrDf{8_hD z@+|A$zkj#Dr%IUxlD&b9h6XfVU~7H{t>3RqF%rY_GeZXlhm^y^*PlLr{@BnUsv?&%XyuDb`}m(pjDo@8SbNmKE4C9|3i4e0Sb;3 zAb2&^WF@ure6F}H2Ne6@wFBy{w>aA0vdum2!0kEd-BLJ}ukngRz*ps4AgFy|FG%&% znjbun0)racp92FSG7NvWVGQ@j21wt0OC#k+8F)Rr2r-a$;LQypM^=-i#oIt&3^>Sw z_w2rcYUHl3PYD_lc`L~XYA4@PbAM>0s{|PlCy)mT7bVGniC`f3wR$}Hvw3PO1>lP(6!<{SdqA2Jp)}b zf5M(kDLhPzPB`|Y`bB$k1-3=tb5OVfmb)VE%g4Q<-3GLgU%}r{J>J)#Lr|R>zh7QS zb<0^o{?rGy|5DIyF~v}D+9$~`J;ImMCmL_|yB=61tw4`I$_ zH-^8}&t)!s@sd#i4ob@kf&*5-|bPbVnx1V-}Vgx2haewY0FeG{~q_4f{9WuyTtX3&jg1I7GsrR`BalT zhu!}a(wen0GL#Np+%jE`1@8@7A-y$&oEESrW88G*>96Jk!T0PcE+phmpjV2N@|q1V ztuMm=-W!41)!pr1tj(SfaIy5>4Wu3Jet}BIBSEt(SM*z!JB1m9aDa$QFXO+1u{=Ya zfnW}hQBhHeIqLc?N=i?!=H}*RQ^6fz_8Sua@dA|GE3KI0#SQh6XSbkW8{5>91^SvG8H$3JTAFwl$jun%ayNw{<;weKXBev!vDV)|35?`?meNcSG5UW zoHR?QAKCwa6w=>LE)qOHf;x0bOzC3aja%?)dlWXbJG+^8YCF^OlKrP+R~H^eEAdP1>CJ^>kyE=$WR@w>~z z1ktyfghd{g1JQbgxQyG%6g*(t<^f^9{X~n{w}(z^a}^1XUVJ%Pe)RC+cymgyWOKgS z?YsHn2+f(Q0G7!KKOG&$wt+}}l+ad(>+EKjXm#;Y%;PQ9!Q+Q@>;D7_HJ_jQv^s)8 zVta1R_~+B|kv2DK?JbTa7hbCiqe`pQF1D%57fc>BqPcY99%Z|*&F==}QHA#dZygB6 zUk2xSriAzLJZSL1K+La@r*6Npyj*t5g#~i%I6S59mZNx5C6N&aqc109S_D3+WmsL` zwc6}F*eap(S1e};wI{=VdI$Dvna5a%FV&s3Gm}didXb|Q=t_ACa*`D4wmv<|{aL{( z`##oW{81^I@)h0_jTGUpE*^K^BQU#E(e}o(B#F&ur8w~Ei^8+8|83)QUKLwJX3Xb) z%A4++`w-Fdah6bBi7lBZo?xdHLtlaSGWaIQ;FZ7LrB?GXeFVsndwu0JQ%zAa{RfAA z{KcoDY2pcMlNOLBQWrI%oWjyaKDaT#ZPgQ9y}#I=1Blb_07HBA-w)TYI5utC!PU>q zTH7dj=D)*4MD1j!N@HU@K>z<+6t$xyd$*b7jhw0~zM#>!V(I9#XxQ&{nK^Ds!kL6y z12%KAPQw>`cjNl2{!PSS_}Ae`>ZjUr&Vb0@SNct3MIZCm`~5~^SoMKD285%gmhuQJ$dymcb9rQZCHY3jj2@6^RFd-2u=#hYvCfa zYGSJ?oSZ6IX=xE4S?=amy69;0!b=F+UP~@Y+)?CC@ePPd zncijv(A1kokPr*N9F<*U(4R&Lk}IwRVFh2%^UF2?`;ZVLs!M>%;mOhmQNIh`qDALv z{uhr0`SF<*=DNUvXt**nz=N{Vi-NQ9utYELd-)6fwaQU@P$@pEq``w^MhI=p297;N z7)X{gj$H)h%g~`Rlji%x&$=w?#1ZRmF|R|0HZMleG7Ll^M=4Nl zF1bMQX!xXAR>)VBw4Z%_8XQSVZ0Y#_2?z*$0kf|qs3f2S-47jrx&=+%b`=n;1x_8T zkP?ELgQkdobB?6L`sq@{L-BXbhV0^IF$WsF#zxXEelr^Cqc`;!qgA2piWg;bw-kRt zvzRr!SkTJrCHNJiV^k^Q>_&a;c66VMjK0nJR8#z8csOSN=ZEe}YD%pyW=s5*bhfmz z=yjq>e;p#vXL+fk<6AC?g1d;dBiQpQzl2I-eyOA=L0%3A_Jeu}JSYd`SWFxuJR z%l~)ntjK`IQ0^;6OOZE-Z0jhukbb+G!Qx(+_0VI?a~ZYXLs#Ou@$Kzd`xnp5JBWk) zCi>Y+QDJ{?O0$C+Cqlt%9{QgXw;L!q&vd>w=XP)xw}}JVGriuQ<~;%ZJO9OCpMm-- zl16QAmqPS5=ulwnchJwD&6CKZxaLKQA!W^L49=v%0Dte+HS456aPtZ11f-BRCkpN( z5Mtb+y!__n?E#N~f!@lR-TT+2bA$f)(m8v|$h*3YsWi4GD#1mEtROTTa?uJN{VE7N zf3)9L6Z1%i_QfoTCDQXXxA{Ip(J-S+aF&g8EBIyH;mQ%~vd^H5_Xx!uMh!RJU_$w*gM7a#bLI>F@v=5>ayV2%VrF<7hb zxq`j@CI@8dsWIX1gTh)^-pso-h94JAlJY52wq%H4@j%e(yc%hqJ!i%$sL#C1hvtk0 zRgPrPxxYAXIKkzmdCVm4g1PnagMLoFW15>7Mp2tMN}=Xf(rE`fM#vHdC2mIUcu&kfX_12gwa4!_^`HwNeBcB4zo6n<4V%Kd{^1_ z)!=R*8D?Q2O!TlmJ#ST40C&?L>C_;T+*)H~wTNSCEwe0Ux-3sGa=6O{*d~${{rLV$LVdCe6lsd zw=%G3Ukl+4Z=|~!SE1AF9sXZVC1;^0-qlVx>vy+7bdm@?)5g-9fv8&z)7`juM8;`9 zxLu0an*V`943*B0(}SBM8>NnU-yNLg%=LOK##l9zjb&2o7^aDnOfN^rvYD*47Jwpk z_4G`D`*HfN4NAIzhM$((YvZxil8>{8apoh{rGQdfzCv^OjX8S@`r26GR4z{tw@>lP zl?ZYgL9pP1w-jai{kF8H^A8hJ=YMi%RoUJ6d3GJ~33(4e1#>GXn`E*$j<=GL1>POmg3 z7M|)+a6R9wvNBLKW+lw8m4i57ksQ&vJ!xG4p$tA|@j{UpJrS0>>EJYGl zWYcGeRZlNgF7NOyiF@6hQ^hxzonw5jn<9V1daYL_Sj(1N|4GxM67kC<5!D(KSPDNu z?T{-k{+g=cEDYBj)+ME0t-or0EXL(18yq92AECvN(@T+?d`bYWmU>(4D&ghIE&mT+ z<&%&$`?zccPx2?Zn0NwY$gE4xQtSjh?TZcb>Qy*Yk>#*xP3tj`J^ZIKMrT6(j`JNl zPj{760wLKOe4{f?Jzs(FXd1DPpFe%dZSWE_tb2^GEx!)d#C~TXipI3I25W4z+fyV% ze1aQF@>+-QsdxwOk&BfitMkP0MA^Dg zR4ykSUeAflywG^K$FK8s?|CoGi;`drRQIn9z`J9Z^AS#~g#FgEPUyPvRrd^)>6;t& zn;~+U)JiK!NNB%O`S0b81Wmge%0|WN@{g5HrkOp;kJBH>k^Sx)Q?uMXD~j++!arg+!3!G>$X^y<$oFLU^!Uazx%-zl z_TLFt{eOcHgd|7LyP6QPzNQD<5S;|5i zfS?~%S6)t+?Yzf?wKJ5c^x_DigXw4c!0jd0cn34@mQGICpNDM>cSi}IOGE!QWve~7 zMhflF=%{_DpC~N$obaTHri@N6+r|C(@q-8uf1ocD@*wl|o6M{R`Q>TiVS9)9<)$%! zXmk4-Y8H6wE<}BKfDcC5vNg2V@1Ja(@VZSHXHL~(DJOH5BxF{ti38i(HqI3FUi z;+`P=IWz>`?I~}XSmFK~j<*K6*}wUX`+{m@3AhJ$$E~8!iJ8mS|&_Xh#AHQCzCAw=%ExD{1*V zulD_Oa6cC+5HWm~1R$V=BXW`~X}MIXXJJ3f8*lVg0@BMrY$M`z>#hih{a zu}CQ{Yw;Jvgf?E*IBLPT+u=@vTEm0G%w@P~#uzTCrFvyOtev{`V4cQpb^gouAd<(p zrkO@H+?%u)29=$|K6vyJ59LiwvpB!G>7vJ9iAt6&b=`E z3_<;otZ;VvkhjT%$QqT^i~k(GAA~j^spU|A2-c&RPLyUuZT~crj@U^LBwuRvnc&=b z^!H>KB)U0eBifN!kLL~&HBrG0T695s{)t)V$cvS@4+#k&Knq|EV#~$E9sr#QImn+( zFO$@Nx-s-ITRKn*lQA=ikrDOuL&Q~u*h-Zd7UpkUv-WGE^gR^?M@LRm+i6PZX zJs&PWMehS1?|BZ8H&d!troVJ{d;OUKN90=K-N=Y~8t67t)c<(KguHp{m6@NPZ><_h z4Cw77@5Ah9DzP`#Q7tVJ_mE%}T%J`Vv!Gz&&fC!OyTIq?rYI|u2d^R)J$Zg4 zXtWZsS`bp22eq3CWd}HaB|}VHz6XBZ?Dc$_Qb-g$Wv>wl2nyFMag++Y^ZS(}O%FvQ z!>=(^p4whqEB{qq>0A4DxP&O;4#B2uK_+xgUu}dUz<1ba0KNSaeBwhpluW*2JWZR) z@q4+&G-?2yHnOx--9mWfo$SFy&goKEHEQW1iTSB7Tpd#eD`ct!wNj1DY9dj1bD@>C zjL`e`XIbf@w`p7UCmHv?c$RGN($|;3uW|&q#pNEnebWb?C#OP{zApaY!cWt0wu4ml*cqj# z2dh36WJMixM&)ywQ`A^Nnndb@Q^6~%q+5-%PPeIOzr1T!hZC#>XX|cB`I(M2)x}? ze^5xetBrW?qf8VbA9p{ch=GJ60EpjH;(*T?0lJ4;$LTSxH3O6ItnT6A;X}*0qOW+p z7%SVS{Ixj53}09}SLRvaMzyRk^AbfDfE`MFnvni$@gP?&uNc&;00>To9TtM-5xKuf za$=Km)wlMBJ$o(uhDG%RNr$oO>FG4;M{`1hyY7&yytv-aPIo^mCOiuas@kW+$5(yYX6Q1&wQZ*~-4ClhHy- zx*tBoTNcM9upo|;ytLUUb#b1Yk~b&z{^SN(8f8gH{LxW*Y^qNam$lBo3VQnN89$4` z_4&TrYOU9$jm#tF1~*AepDffQ8_S!959W7%k*}Vvg-26GCWbhu>Q;AKy8b$6VVUjU zE<20@LKbc9E(4@E8*V?Z3Rj^LTX_9*1ju7u2baKA65(|CptiV%k+A4mx*O=qV4jPK z%VGXnTO+K)4`RrDaMdD;MITEW;yG>Oi-OUqX@I6t>ai)J9a)jpwDcS2<>qXCz>JE%E1uDFmqMoOslQj>8H~;VQ|EPNwL0O&}6xhBBb6Nm1Avf-Qa#yR9N`3ffd=+ zB`=3*F!R-BKY}DDe_n8 z*3ol?Q%cV2tQ=>_L~p)qf_J#n4QQHWh}vZ`g^JQQt@|&Hb`ieu+KPdqRYR}`)sB1u z8s5FBd~)PEM5+IIyiWy2?9OKO)ItZ%oWIl3Z1QbhJ}TNfe!#&F^W-jRwtx@(PGHL{ z3(q>#+LXbFXp`+>1pLcGe zpN;V0@a`@i>j?4nH|%EMabq&x3yu%R^=!;_qW5@guwdmcrx#1KO#iW_ajxYWN;;65 zbM8j(JPfFsu`?3ioL$hUoth)}CP{w0m>cGbSWAEm!^w*Z{!X;~0J7T*!j zb1Q@ECf##b)?6w%I1rLR<3@8aZI|-^+;?Xp1TLG|;1>`;+VWCH0+mwv#lPQbb;dht zpk_l7{DS;nU(A(>8uzv5XGwAF_x-!2CUH)F^&T&l&dO<$?IzH;{N_p%XZD)XbvdUi z2LJW#(2DFs=+uCsjWtkr`p*a6cO+Q)-pBFiP}*bG$nR!wTA?5I!atPC?a4?({ruTl zo^!7{doRvYLI)F;&2C2`f+m%caUER%#XJa)i=%iS8mjNI&=P^>@6yB`ID{;y2$huT z%w8LQ@v+G8{Pol2STQQdTCUw@%*5`lLUk5SNO+IaIreT52pT6z&!$91DQe|L*99!8 z9ymS|?Ks2GTwJH}D9t9_xl-aDN~NaWsFnl__%onI zYJGn|&srEtD3`@NlO+jT_z8%;bilW9>Q{BhvZk|>?H6kl@OlpT`01Ml!$z4qYH_|L z^~pPx_%gzYFlD>oen|~fTnYpVK-AV6JL7_xS?23*ZT*Q;NT^QMJt-l9#0@AfUIAs| zb%L7IWgL(W&6(Can_!z~yg8I3MPazl#eC8>TlIkm=cYo<=cOhR@BrIwz)6J#1@A_- zXU;Q(M=1vNhQPS@1I@5xLa;(G)_!=)Tpd|ceNg+TT%PiE{K|p(7dcK7!GqA(ZlCJ0 z>qmn%rannSf69cM<529?@%@sN>VVD)8;D!LwGegNIjXCci6_YAZ4GF|zEAm)nfVIm zc0gMn#i|tF?fp7i%)Sq{1WWA4Uhtxkq@~IJk4a6+TOJ0xm`i)N<(YTt-|giMnYN!GAT=;UGkpXo zE|DDE+!NQi7g;<0)iW>lz}=BSMf0)Hq4#sEIX4~)twYi%DJAE( z)7hH0KBH})eGM>T>b4@~@Dqf6^WZ4q!?`{4($C=*_UPx9gR{I}p<`r15 zw7TC(cLKk!BYs7Bs_6bBU>*@v@RvO5A{n=>5ko`V0r{0nJaJ4^6!SqlQc8#_2CAy8 zxYn&Oeh%b7yBB6>+8w8{dlj8o68k(2J`LfO*O({wa@n{?K@Viepy$lguGt>At1Sf# zaqm(5td9SO%|c^D*aBk+>>IS-GlrpiIB<9Onl|EpB(*n3gdICLbS)T&|5e!j?IeNz zm-t#4j-}$x`X5T`!wz@qp==6;@K1uf03exDHm{pW4#PslrDUqQwZX)+kcl7+CFJF` z>g6V4EyT1i?94cx7GVGOjtfyl^9>c{kw@R;5B)$O)}`Z#OX(f(_s3aR z+i!jT(=oBJe74U*bj3f<Yo#MpU)G-ywgEXdSYOBtzMc{YGVkE_6B-XgVQbAOS zg%)?kOW8i_3dn^X*P>+8x^xHa%_Sn&a16ZuRqt<7&JbTta(iGoEaH`m8y@cPw1aEI z8&O}hFee*x(^qPic!<$TulW5caQ>CWT(thh?JFZur$cESWg#ucc-Bmu!c%t)zq&i= zz^SYuODn5!aETGbi27=xOhZIL6%wX}Dv<}$Elehf!MrN|doQwP6P$iG_tiUmt2r48 zm!P6>6qaG(fr-FJw9WTxxM`#(P_bd5aH4lliEEvH$go=fWg*Vh6AgJaIY>#|nX40y z+D_*Pg9t~I)E&Z#NISL6vQz_yf5}hAW*z#@@O`3wF)}|YyE{qKih-|)T(Zhr$P3Q2 za=!7+y-+OC{(=JBN#Jq`YjG7Ugg1MVLlNkufhHN_&Yq`xS5)kj#DUQ|y7(4n&7w4ZbZ^eA8MsH0%kriT0Sd1z^AU)RNdQ&jyoqWd0*Qc#ZYn zt&kn9%kamosq_AzN#awwh&gaW#kMG&h%*h)QfnRX#ral(U~w^$px1vc3;$0G;DaTz z{oySxJ(2e!w$mxM_@|RWsn*bFbtp?W{LJa8{h}_ou7T)3CPq#890X3jDk${@d)9@+(keb_PV}$>{fV&EK-zEt}38albm{%m$>7t_h?>=fUcmM zcvHyk=L!{Lbi7Bn4^1amMuEKNdo6DetIA>0_@?j*sH298#=%W2z5DZX7^q7Hm%B{m(^o`3FG&QbX%b(6ctNd5jYM0MKp=<&dxhtN_O7Y=JWuw z%KzKtLV0KXN$`}{Gyj+&r0#BSRyE`l6)<-buXrHw`Ga(pgc>94M-ZdXUE6%UE z1Aw6Uky^G&z2h|8!>aI#G~1tJ&TuU*GV+tDi4Gfa%@mgdfxXVQ3e;`dR4W z(6=BNR(ZD%3*;Ch(cq7`Ni6hY%VDk#r^}Y(%G}7vSm3OB5y;EkKxyhrNTnC8ZBE^tx!JK&;=3yA*= z&rFoId!~q&pcE>ybg)QFEX~*Cz7siQ(wtwWf>QnsZdna6b`oRW8u`$ugw;ZW8Fj&V zW6?EsHLe9!q#`&R>IPh$%z3uYZcu*?^>-J{H?Q;z@@uCXy{5{|n!j_;I`?>-%bnKt z)3O{1$gw|<+g~rq<+MQi9xQLO#GN@Suvv zKK^_0oDnd7h*|f3$x9=AcJ}R|j_GoL-!CF0+PcZ#Err|yhJadb;>BZJbk)e7@zaCY z2m4diKQ8Z9KOe#y+>XRK0RBUm6*>e0M z@9!gFCf{N_ItX1})=W&I&K=jue_DD+d3Le#^Vxhztb%~jfYNAu5JTm{J+4;9#+YC#(ky8IiY^C$vEk-7{cCT4@Qb`x zc*VUNwSiqvPfZ7`a5|n}LE;#|4aXY-Kxj%GOA&@Ll|J!b$L>j+O!z*bf$f7GCbYxYtv`IiC8cX zHg%CVFc5N{A6x2)5ohJ8RCpSOMMkEudHN_ZIngIk$HYlNCkgFQ0?}Yb)Tmf38XS%S zgDmEo^R;@(F&!9Th2*KfbhY(%z_LCEbc_$6S5Mhbz%(#KUgEF3^tiIppa$K{|1@dR z2v6KeeCMJHyDm2uF)#U>V^0`J>e3SvQSFYwY5Nm+9ky@hftyDb6E+)n?<#?K?{S&Z zp9ZBlt*UJ9#v6yVLS)Dp&;-oCRO`i8KXJM&;yy;Gn0Q@@Nhf`(2)XK>zjq zgJ#E!m*H@TfwZK!Db%As#;&#$9)R2&*MFND^^?F}CQ6X}ILlcOx+jSRY=6DZ6y6smJsVfV$#MFGs|wPxb4x37t|o) zq+@uPUIb@A7PT|8e{=VvOPLN7(;A%1{ff4M8m9xGOL8RC)KT}W$uWD?Z``&DPGEm} zgNKvs-wuZMqi%{1iHY(JA0fSg#mn^4qE0ffip&sjm;mZyW}#9D7)Y-5@DRXhAzm?A zpY;lCb02VL&esA(r-Lr=WWb%QF8sP-_k`G>6mlf*iRAy|>${_|j^DpOZd+z%GRxk{ z&dlB;*%_&j%(7=jLPoZ1vXY3bvdK({D0|D^dp(!$@B2H?AI~|@InF8FPPjksab2(L zH9RjZ2Sa!tH6@h|nR|T-eku4#)6mv&a8WH8XOc!Bpj}paWLAHOX}pMH7AUi0`e(4~gClpB5zZ7}Dbm-`(j;(4 zzEU)r+StG@iboC3#BMtbeY$ObU+W*QEdvwEr2efU&vV`L{g+^Jf9$dcBZ6^>l2?|Z zZDf>`8&>h+h+3)$3D_4oj@{GKdj*v4)v=n`2R!bRcS?MwbRfpG;IH|u6Va0RyUWur zBGjnSjI^+1b8*EQIJEw0-G8hAJ0xtK%5nAyW_p|pTC`EgM-@xkIn$bmQv0Y(<0=h6 z*#f5$D0csm1XbEKGi)6wDl21Zq}IMZ4dDN>F}RpTD}6OyMFr>4M;;fw4|~OdT(_=Sn)6(4DIEcb>ZHIN&&ejh-{ihj&RpwL|`#qCcX5}DBYOP7POoS|$2 zT3Pq;rOiaU=+G}-PEH72Z-h=04KedQVnzy5vh4FJ0596z2qiAWKz?Bs1&y~!&n6-U=C62cmCpa>j$bACOG zDgSm7DzYHk8V|N=?SR2ASNh_yEqY(66BYNqa7}HVIL9a_$7?ThEDHZ+MTOD|>B@x9 zcik+TuA=Z*jp!&TvGsWyVZbAUBV&?!*KT+*i8fyv*eCPgbMJThVX_c7y`&A|GGKlp~mtcqCbT+4M2V+x^iT9uLUy%$_R zo)ZVu<*(46jLoA>St4{gD86Th(O&$E0|p5V&lR^Zjc8>;T=Ai4q{2EO{IhUycFMF# zdSWp%fB{v*DKo~%Lo|L3fspS{WfnCidRE|o^1OM0_agaQe@;1$)fMjyN^oPW#3I1& zf`X(B5^_v>z8(RQFJDeUK@TYSe#6guC4?)htCQ3+Bz;OG%%o#oe(vtRP={aR&DjL8 z;iSWuTwcR5f6rHUI$`IMmlil&6nLS2IL%%M-_y-vMTeInM)i^_4_|%#(DlaGr-gXr zvmhL30qbgnJdfw68=EGbiv4HY7Ys8-mSmLAEyrnAcYM&L7T9Ny!v>c>SMKO< zSwnT}b55AKaRTq@+rNJoEZ7ib_lV#f9`_(m^;^+M*I)CtE`@4+Iu#db8o3(D+XIbW{7>unqt;f>lZm$02z9}Q`j4M#)A z5<#60l^B_b$&btZGIY0}20Xn3o zRvQTND=y)p?v=z}&A^qjzUkOU$3?sYqu;Bv4XypMjTP3wA7;>kLe zh#tnA{j+VW9kQ_l#g;!-c>*8if3_py227be^Beu>n^s6L_lFEV2(n=0X4i?tVI&Ek zVx^e*yG0gfL^9TeUmo1}wBir8RIhujEhbAXn__S&_K47x)^6S)^MT6SgjdbWPJ?b! zrnshwsA8l>9#yqtmo(FpJSvOq<8G=D4CH8K^;mJ?B)MK&y&p^({%&mf;NG1LQ6TxR_mvGU4)YKUN59SltPLD3A zhn6bl(zR%<<<=Aw!R;{eLnNwU!1fC5B)aU#o%)MSyNAVIqaCI@Yz`OizFpgC<2oJN zI;%XkJ=CfHI%Rvb9Pn*hLh8ZvmRs`jgMT9xoS#hV!kWr(BX^|yN@^GP77H7gf?lai za=hbbwd?+w@dFL19Ueu)!AZ198Swfx;5DZ-iqS_|-knG)Ki zM3x{XcbMV^-}^e*t*VVNazxAh?1Sd^eu)RVC57+0mWkQ3-b26rPvW(qAG{i3-y41{ ziSyyq)ng|kF(myPgzD1yqANv`g+}uD-usLOA}LA?`LHr9xv9W1aydgNLR9{K(aBtm z(@_!5^cs1h`NY>xfOH^QC|2O(&lB+-rt-N*3qR`)Bo@b>_hKSHsK!@n29e%QqU?Mo z)Z!ert&*L$0K&k!*qLa?#_$tkF3X>ZG`g3YO?u>16Ah_L@IH|1=H}oC8~JRBEkLba zJbO1wi;kQ;7})Gm#RKRkb$xk%pLAL4K3a^#pCTd?W9r^r0o z9ZVV4$0YCjGM5*({=J@$Yc@xUJpSu*duw=+#Qb65e%Lv_;;f{A@cXZyiX0+y_x!ex zPT%QCYcq7d+Xp6m&q43>*ISj@Xqn16?{w3?cHvnQU?I{KSqi2pSsOVI7T4drrboW+ zT?=}?9r$FXWaVqSq3?_Qx47m>A=oi-Dx&JA;D_DOe=Jt)xivoI(7MFzm&G8AzGl4F z))rND$0P)Z#HN$r-l2Yug-|2wh*E??3u&m_>({S|N4GJ=Eif9$hW506?N_9C1+4s| z6!jS$cRp)CPWQjKsDa!iuKdcT0ZGn11Hd3eV4Pa-u`?MO3KEuRpb~?0?p%|LLUo}h zrTyPo*CYO)z?C__G8OOJGC^zyviQT|gFFv3K9u#tudA3yDhSC45jxZ5S{|J>^0RBd zW+?BuR0v~_V8?q35t#50DdeDqeR!%yb07xBO24(5^GuFR4gQ1_KlbAm$J{6Pf84GA z`uokcZexM%m*1kXW0)+M(C8BV8#J+B*iY)Dr@qiC^W1y-IY*^2jGVKTR#v0?n@cr1 zPdl60XXo5U3nBDkOtOZq^fxk)Lw7GU|D%B+mk8r8l`8}y)CY{7@_w(}CTXr93!28m z#UqIe(XKu7&i%C>&mC(_K-L zn1qIBfnR@J^{h$QzX+cAxGcq<}wk?xP;;9#=UzSLwq9KP}0f$wP7{9JY z(=jCGB;)7gQS#`>ihJ@^0u4TzvPH*=!n0G~#JPVQd}}{EAd&P$y;#o@{(J`|3oe>F zib2?JaF@GFCUsFMaA}q%KYeY|0EPpC!8k46+TUOv>WM__q-7 z-S3|C+K}i3`PseILCS})lZ=lEye#i71mCV*P``eC!qWj9<_-><%s^c{ObD-EpMbyk zAdbs}g`T6>vHN-hk~obTH`3wkyB87@Inx|(yI@HjK`~iupfBO0L#Fzt_ZA%<%H->d z!s^MsTib-(=nRgt{!Gea4Sw{Aw|S(k7-V9|P~Ky=UK}db7}+`=5@FiQOSIpoGF`Al1Wb3%KK${czKW}I8`%0`1>^}sV9jJVB!=2|Sfd#EizJ9+zS|{$_%SJMJ?Z=M;3!##z7I>S4 zdDJo~^_Tq`*daJ07&64}NAroaJmqt9b0HlUAlwEaS+<8+$uMY5uWti+$+IpA9@I(c zWT~)%FX^3>#OP@M41KQoWO0Qj+nP#BjXrbkzk-P zG1InP2st$8zQOnAx1y*vAym4F>)?iF)bK|WTojz!2%do)eCFrcMpvE0{lmx4NklM$ zO&>UP>3=d=(z;n8e=e|9M4nqgh9Unr{((m&HR*UXoFKzDs(bGEJ$?}dV|$R$N`uA0 zp|_+64dLKZLGZI_njaEyR-`Z<*%>wcVdRV9rSBbi`MB4oqr@%IDqCT6Q#dfiA7>SQ zYBQrxHlYx*5TTX(OL~e2d86=c3)$~-XgWr(_B`kM`eh9xxWE3FQtU;~O~oyE_{mYM z?D0xE9B;YLcq2`|1^uiWLFMizKA{sSDRw_r44jjpqs_|ufY^~7j__MY-0zEi8tttq zurf(1n^%>+YWRG&xIP;*c9wim8Qik{DYy0yV=?t>o@CnC`;O;#av))y%{#ahc-pKkMa zcZZ0pbkm=ocfO8{baj8-7qiJ8cH`gt`{Wr=;gUzPg8I`tE6bJCID%}(ajAzq~#^J-2m?;uIt@n|GggF zdNz^vCOrmcZZrwgyySHML5{yy<3AaUA^Hvlf3xdv)>Qd8q(;Uw-k*9cJz5SI$xKGI z4hCnQpO80d2PzrMxpBBqJn0b8^x&Ly)TJ)U;)V-i%uYn`D@|IS65oqFRyki@>5d(A zhcBpm`1cAjhA*C#$Hu7Sk`;e(5~0x|%e~FsPfZw-lg$Q_!B8x<5}1{$LhNqR`!8Q~ z)8pcFa}Jr9vjC#}*OwI-B)Nd|;me$2?8Qd@*`%Vtf)+JqUYpf2f#;b@F-bTgQbG0o zy2C#@(IZIx$QQ9ZGbT(X#&`+oDWS=qIBW!{X?3WebVN^9QvjB8+mH>TzXsx7qVT2| z@XLL5O-;qScTvsd<)UEggZP8YtX8O$wN?VtpvK9eAIdAs;g5#5NBj3(H>$pGE^`H0 zof!V9aL4=VV)KSl!Pli4_;OGrmX;U3W-20ktZ>hSO|>A|ZPQyEcF zL=ZuPANaCn`^&8(3~wX!nZ9>tYO)b0^aY~(N5js#|7fnqbn<@0)qD20gWgnk}A!=J1cB5W3j(mvq_RgxJyS52=n(c@Fy#yz91W2td&MbHa_QZ#U7 zv9Eq7O2UkI7bn~Uh^YwD#Xf+iop*-C2uk2wc-B|l+}yyprg?mv7Ce#Uz=9}@bcQ+# z+#b$8xHLFYwP3sG{7mS@Z)*VY4L+|_&SU_3GO+E?(vNRO0WtXIX#2xV1WPu zsq8)5$r(=>+L?DKYdamhakJ|Om2JOBrH#)^cGqnGP7o^P>O|aJ<9;%T)KX2LnU2>& z4lgA!9-sX}L*GhT29-p4let_|9X8g;cK%y8;ry(Ugb$XMTV!k)rH>1>@_t6VM{XMC zU=U+$uB4As-F6j61yU#9k?wlw);Uj>_57Ro&UyHQv7WCMQ5t`zoM{eF2H#HX(%f2) zt6UF8#T-Nv>m)Bdtic`1sF;FDIlH?0&+0kIL&49`)f&fqBdqtWGp5!Y;wiW};2rw+ z%_gTSoNl>$?u82SVwn>A;sx!H|8T_sYFo2t=uv^buc4uQ<(McouPH%!yV(h7g9J%U9r; z5TXS(;lyN{GuQ?w-R3cEEDC(}ySkGNUZA|sL5nX|?6cyx_tYun$-$h=IbL}}e|};< zyFwxY8+YQCYW>r_r){Rl$k!5Hsy_CWiu5UJ#Y>YIh@{2AKtT*3BO6->4Ov0IwU)N_ zbTo>1r-$%Vzzmf!B;7?mmBZ}pzFkdqvQ^c=x^dI@Z~l~XQg=@A#pb3KMulC3g3QaQ z=Qvb2c;8h7yNU#0*Aj*MwOpqiZ5+LWtjnlp@p85YqmOE9C#>i)pFiFTXDqT?I~JLZe}%F{5?&gVm)HIR8|^{a!IDXUi{6?p!DSr?Oqe;;tGToXyruMrGabU~VxZtHEKk zvZvONK4*GkgQ!r~NS`%{C=-RS!X*tp`?hpDL_|c`TIHwvKYc>kN`4g}T&YAVwExQm zfV)LOab$GEtD&*<==QCLtqd4=)de@$m>w@oug0T7UV9$DFGwsaFLU>BdoJz3vW;z9 zA(hhV;PZn5LSNx|jD2-g{`Ix6!DOy2uwN;F0f!ia_+}bf*bNJTd2}rsf$H>R0?A2x zU19uV{udiB+RNG-vCB8idx!QHKKw54wmW^>-*2%pNpV@kAyaXC4n?#*0gZKc^qs1dUPd$co%){Re=-Yf8M>(Md_J{6LQ7(zs(wyF>F;O0#oezKua+ zKT3g%i+gFll~rjs4webkTW}}8868atGI~({v?7xx3QhG@Cop zXsR_k_{uY8R5n)}GL-H2Q>z<&vk9A?nEas3@lFYuxG)dC!d1^elEvQqS-*=>oV2$A z6G{QSvzZ08)R@D)Do=Xe-FFBy0vF$E%Z~AeV!wNJBjti$@+6(u{AFLZF!p~Nbvb&9 zWr`RNHOzA%L>Fy@ZyUH*Ciy?OcC5w|zSURHH;9CrzPhF+x!5m;sV5_n12LYVnDTDI zbr<@Cd%QE_r0p$rWdbFv8#f==&Dc20cilIy_=4ixv^v2D8!L?vMMwYpH}xrxR3KDp zaNYAX3`?EjZAqQskmG*Av5Dl=zi5P~oXR1EB$56iJ#nDLCc~1ZdYxl4EbVmsS=4zk zpJ+xgdZpko^_8jVX_A)NEqh~nv&v_N+}-quQN`0>04yEKtS;s#CrZfIE{-mGUir5x zIy&?-O?u-%PzyJ=FF5DrgMbWHLiPDbf*T`tWK=_dXZ1SsvX zpnn)ZN06O`9@QgXcE+rN{_P=k^r?9s>3klGe}gsG-Dxt7?Bv$#_}}N!#JPJ`kDj6D zss#7x9c1?7sT&$U{qR<)08Jk4F*(W~sTIfnNBu4^c5&6}bNQEZZf@VVn#dTNg!$pO zhTGe#lR3G24mMi@?PZ@#`OLbRy3=#7B1pvbVYZuK@wmCaFZAt#RvWQqMh+T+lCVyY!Rv6_q?FSPy!WvfmzKl%DS8u$1tyA>7v{an^trA8I zQz&b{q2B%bK2l&X(7!TVLV0|6D9w{-33y?=SlYUv{yCA|*1*6#4FQIlk`jZOvM;sT zIbtre>e@YK`U<#^A7VQn)w!*WxF{Fu3iYqp<|P}&`sHh+!Q6M_txn1H;JQb~p%kE)_U3o6?>d-_jk(ifCOx`OJ3m2pBbqF8XgNA9En;Rh{3@>| z5sZe$?OVukga5d=X9h+3mkiT3O*gg#*6hh?qU~-v;QuNpVe}*24N4g&`!C9hazMY&JwN>|3@O=_G-C74Mn zlqN~G^S6#e%q%pCh`dGe0#&;lG?X-dj8|Q06~5xccKDd9q+Vy`)PUZMOHWrsj)pbi zN&ey1D~5(sp)l2rX_-9MY6XW~pU+aRsS{grcLXUPpWLZ}D}fP1hUN_Xw}KsNw-j^Vm`2`PFeL4zo8OuS^P7 zICYG%oxYQ0!TmAFFj`R6=0P)ONo_!Q6&~@QyywOH`yU}R8IUnM^-O0)hNhMb^G&|!E!M9(? z z?o&M4z$vA?*XK{K{7ilE;MT(2T$29DfUO|W+lHI1nzLpS;wE~&h;*yZQx@NMryFeX zF`p&tl~6hqoE)j1`;!#(7604^5r10!WY*OzwlEMeKjB5rXc3sKTdbT|wiUvB_VFdj zX%VXFHZ-N@d-T;0movgUJLkc7>?!hG%{XwP9jql!P}Zb>^2$|8epjcA7&9Z7{wv(* zW0Sy7B)tERF{8xKq;(@Mdwy<@%f!F5luu#KVHmOdr{WWZ+WjM`ernCIHDEaqmhH_J zwoO7tHpmc8kKil(ve=M?2JoJU5ARTB`~Cy@)2Pf-9E56NTE@`mY}~`1;KsQh)%k~y zAKyF-2N(|SF8*Y-{f04}c=$mKA{9NW@Es4HKirc-6kr zL{SBBOO0;R=ppH(0&JafFn6W$f83>|eE05MydqA?Yu*RrZX1^|1EU~YUc|#d73hA@ ze9Zq>2kY7&gVXWPTF9Gc%HrdfP&`QJ`M!5fs$3-{jrzuxMFvh+6JUHa_8I1^e#m{~ zjpo;${yBPDT6J*AB?n2vBTjYnEfWH?q>gVg4U-kNi7xey9bA<3SfpqLVrmQ#rbp2OZ*~KQcCs5xcX=5cg^XRwWCM zno6#*zQ*F7tpq=kBe3W}2AO`B7Nj~`)#81*E3XVdVAq1tVnG28NWCGoT}E5Ge+z1MC2&1XnVGti z_3uR~hKxBxUQvm=mp%d`*EjR4qX#KRC;$2#{)|^)?DJs zXeX<+Iki4C^L$ZwbaM9Iivb5UD(Q+XJ#|vm;3dJwM~syE>8x_RUcu9Y~!cZo63coMG!-)*X<3BkX114|kl)2{E{$zsEU zgs~aUM z$Y|*l(xXt3HD72z3?#`WDtaU$uPq0=DeUH)8Rb694|x+48l{+4fI+UYlO@a%At8jc zBarcpAeXW=etZZV0=p`K?>&55{6ixUk}Eplo!cffw*MK&VQ+eNz#@asmj#+Fd@4Q! z-o=IULC>5Liw~<{u^KDg!@q(|t(i8Ld7^hVm}2^~6akp}d_-AwrBge*;-8$!IJ+Sy zI*$v%DAiR*ssy~?&SO8im1~dxCc`j2NfQ!SZtGEjl~@%={IVTkNJ}y}z>(o$Ld@p$ z!U7gu6gGSa3k$=WSMd8OpA#cU)bzZ8!X_$1OeN(j&K8y(FaGfKa0~IDn|mZWdVf&! zJnw+>vu@0io5Rv?=e7U<_ZieSFu`)gC6vDs{1ryntV^vPf>pLGxL_oXLGAU$b~thw z6n1}~KQub)XWxb*^%_n964KHHVw}d->z4Cx-P0IwY9WpWYk={AuC8vb0aqJ5s}ArP z|KsD@eP4NlbsQas;XJ3IoWkMc53RNjX41t-{+o^P(D~lEcd!6BAla}GB5rPk2A z5@b=mX;{+Q5SY;jy8oW`j|Xc87h^3UL{ShIj&N8`jkU0 z!J>t1Dj4H6uPvE~>U?}Qn>pi4Sbb@Pam+XY{B@MKuO&}V_7i)+8Rz$UEHzk~A@h3F3;KXc5 zp7@M~*o+X9lix>c6uxx}bi5=FRfB6K2MsQWN-TA5(;&|#U7Hv^2)={ivLj%(M(uCN z-OT%95pB%L;aw4{ia&zaX*%AVuIwR6AN`vDgX+OrC1CXPLQ~P`EZK*}IJG34zj{1x+|K{^vl4{*;B}c_L-OlnXm|+C%+K$F2e3FO z>_wh0;6o;>mWc^|g%N@0o49PY%Yd>9BL!Lf7vlxtW29HF!l~alc)Q$T(qSQ@vtFX0 z*V`cc-%^kBA*F4WewAj++-Tldg$Xd z2(ibteLQTqJ(w@1y{76+p*~r zc0I@ZH82ng465wq5y!X;n}D!;H?-!-r3D+cuW5P2pzmdP>!#WSwT!;Xgh>nG)_@eP zI7>wAK8DECquvau45P9~q22aF>EicT=gYb}U*H!@{`wq!pF3VfVnu9&i>v+oK^BHV z%6X42dyZka*jeha9sgE<%&Fhq`vkC(~m zZ)|VJM!iI^0?{sM1p=4ehb6-;)&gQ=X6ATCMLV^*i^&h>e9h&!) zNNdE{N4t)zL?R(K{SFPjwcVL<*K-Q^-f{iba!|9lfRyzH7uTC#D|=uZO~6?3?q_0q z%O$sSeN6OJV!gLkgC5LF9N|VnYwVUg=0G60Loo-~!|o{~*cQiMINgt;y0`Q;LW(c` zW$6BKQXmS;?(=!*X7b1NrF&}IeNRs@#v^?Z7k3ZN%@3StvOQ+8$f0=VR6TFx;;ZY! zcDxHyVJwgZu4oDLJVA<|p`?4ETfIMj4*kyvKIi>= z4DkEcD%6D!K!X)v>Ia7;jQqfjI7#3|07I$Qfqe*BrPVb6z$=7Qe?SoBvzp#VKmN8Q z`EhsGF>0Sw`l@P^eTFYfY(uS1)QwIHjpZm3by*9%BmEK-9IVZxJOd3mh`Ti;b{ZCm zpe$vTUf;!(*M1!ye!C%O@HSIYq_>=$TrC;`EI~{bOzCevUfwxN1Np*YPBR#ncTelv zROBFb{U!3!{mP2pOcaOXq>lN?HClj9f|)}ayjERA#l=%qInhdb`2BTGka&ax&7NHA z2oZUah0E2Ek(i$T$)a;o@@RAqF^D=bZbRpDDQ9A0dY^;}n$t^XvbysoWUjvjmFJ|C zSnUVC;@-@l%jzCD46rGhyl?L}vh3ElW_AU9@fS8O&Nlom9dD67w5fqsA_R)CihQI% zR#rAkr!aG1>2f2#lt$>Hto9M0I)Gss>}5!Mesf(|qwF%gU?ZxMe@)HyJE*SLIPe7V zdUC?i92aT@x$;gVg24au2o@SMuv^(RzYq>voEbO2HSquX(a#DVBGEE1F=2)Np?vWh zT$Zj#h>JtY!Hh2b&XE;5WDuhsx*^C^$D%3Ku?smCK9#>iLMkG!{icrm@@59F4{3yL z;mbtaWe+4wms@G>7@h0|#Kev%lK~N*b3%HX{B(97(XeNSJew z;A))m8N}w`;n6q;*P(}yTJ_VjyEP%5)H8#SD%DXU26lvAT0=hRIha^fYebF1rAg)W zq^k?-9>VuXNeGf1>=Y6c69`dSgpIxpzYFiNUcTKyh2^IxM1w151j^z&LB*q0-2m6+Yc$tIOY z8>=FNP{Q)X9}2Ts>eNa46;F(KA8b&^DD%PM9oaLy=bkXpwAQs?eUlAKJfP{Gq<>Wz zne@%__C_Nc^XVY$M(3{?zXgOi7#W)^5(_bHzRk69&-d?KWDG31^kRJMsvjczEcR1k z@EVMp0@YYXZ#zykCWGw;Cq(mtbNr862m*`q4MZerkzpz>4@5J{GJ!>7JSzmbmq{*7 z5?$kO&3Ysqg<8H%FD83PL{gi^lfr-#;QZ=TJsrkvb|eT_0P30rl;#WDz3u6z4}cjZYM(#eRK`Tl{r&vHPc?yfi;rwIK8J3G7QElCfzHQX~y%FV;WlyGD^3Z%@yj=ZOJdn026T>sU={5_sd z!M|LPq_w0t)GI?12Bf*h{$sAndlQ2}D{rr|OjLtZdya9onHsou?B4}C?s4pub82$z zSu&|HUF}a}lGi4Ku{)HgX>>bPt)(SJPuGNlP9qe6g{on2I>c~rR^L$fm_=GYOEUP! zT{QDYXR7TXWalxVd1d2Ow(>_r2ILyF8T%-E3F0it64EQ!5=b7UqKNY;u5l*2=HD}7 zLW3W!WN({zzLh|vvr?+khH**olNMBQuh?TU0hV|b0^~J-MWJ91JpZ(U8ulXS&|-F1 z{|+o2fZd;cH@lUFM+BVs`ygr=%m1K#yiI|3(UxDwy>Wh=2_9n z=nJWK*O5|aEt~J#MJx#-S|BSBvK!HY?QQ-0134JOnfw}dn&85QqV3ERf9+M%FXn+C zle9faOB}F*o!3Guc;ZEEelf)k%P-(Invbv*>Z%x-%=V#oyH46a?UeXZBqbq{7ER|B z{;>0cgbnE>rXEwu7&@K(R9~Vv73}eT{t5N0@I^al1~N9UGlu3Ho2na%zSI7s!S%5s z67%s&YUj3w2c1~V$-zd-q$2o5c29(=RVKu!}zJo*C(7Gtib63&s!Y40;nd3xRj z`vAY*X~)KSXZjdL-XC%?g5|Z#MqD924KA`Q#;gn57@11wc^W=a->-QMXcIbWS+S=dP#ZuI!rkwfINd?}g_m9xGbUVGIqEY@a1k6G62UxG4 znLGC?@@&wD?{OxChL@x^Aq@{bZp+f~7Yd2w?m@ z)QMYVgVbZ*dwlac_@wT!*qfmUK#$xF5@;2wP3*ao1(vQyDD33@e)<+tT3y#hB-}O> zK`{mWq0u+j;zOWt!8j*j3^o_IN!V$fnN``>88GaIluTZ6e(dt{(fHSl??w7|5>70@ zsd@&)nzP_JC<5+PcV%U7fmZ+1{FoQ(TxYq1Rn`L~<4sHyj0I1ACnZsdj_PFGBWf%U zVw8RL=eK(#oy5~Bi(eRa>SI5fe{a*F;b1F|+CMd1NE!Tv|9s?CtF<9>p->1~wt^QD;h2VH5$ZTVNC% z+c4Nh7TP-^RMascrts!~UbHnfAI{asf_wSR#r>R}i)WpQ*^% zUSp{-mgq6=^}@!9w*g1->b*!X_po%-9W-t?SoS`a$v>~yCgamVKHjSu8TDJ8yMV#g zpqILbhbW?@7Kgn1c>QUy6rM*yLc^7heu~N|?1tZr(&sA@G7$f=vUfjT17)gLUbg4x z_O-R`xovUs(9dht?u;GCuZ(~cDa!k~-mgCl{!99-Q_sw!xBYWf-h~4VLuLx5LQ^|O z?t8!Wd)}`>vkpV@uxtpcvEZZ1gawqCh+Si1x){?%Lx}BJM|bVowSSWhQn1!AP%jPX ziV>){Aj)7Ch*m%rSg=5`fQ9YV=QSoC@a6%f4Mb>?GwVpSq_2l`AMJ`oiu(7hh10KSWT42G_vRs(4Xtuou z%Qhs!>Ss`g1l8~OngZRigw|FyH5tg8l#KRe3zj!c+89XoXj&-A@9o0B)WIdX&) z8|h5dcVL&;8E;llTWc=L6ivNU{VEe%D_`&XTc>mIT4e~j^?^6^_>k|#@Ky;JMgaLY z&2IhBYf#9Mv9Ms&NEJbYhd>w-cszG4LIDy-$zdr4R#gcH-DUhwH;(>7j21Fwwua68 zWQu+Vw9h76qOE3KnrUAbw(o$%o4~Fv6~L+l?8n^a!Tqs6Uz0u^YLtJkul67l+9*dT@+ zH|$9{kogJunHF0f=zo-+6@E8+vf&q}mVR1!?`#Ry{G8wU5v%0MYPkwe;tDqz-sLw2 zwJ)@l*^rq)_(dFLT)uA6TZ~#g@wr`Xf_na>Ue?u?ro&L!mT~9~N7Q#xMn7BTUkN%> zyIlUPb+vZBHH)tQ%LM@DC-Z(~yWQm;;Q4Z#98-Dw5rOJTYGt3gGaKvt@4wn7C#-iK zpOqL@sE9*c%ZE>vLyOA+^Lv-m4&#h+Nj(RT2NJxzTm^DBdFe(xwWly+rs}q-#lPCU zENCYpK78F+q9>cnpUtcvJb3u^UZ=AN&8E9JOnRq5Qh2$VU|dQCaQYj(=SUAJBQo9BhUT8QRXz&}-MO`OouuXz8BX?n_|Sj_fJ?D?RA{IBXqf zD=PBN8y|L|r66^WZr+?31hv3CzEd+zEEr;xFHfISCmx0U(%?@n%RnqWfN z0uS{v+6^4*+T(s*sVd!#;xuS@(Zo!rPZ0STZ<6~Wxcs&tZ7>a;srxi$!s86m%~a+? z)(ZFUH_J;e{)RQ)yr%DvS(IM-e2g*oGP-OA_Izh~S=q8UxLUR;QTRMCGNSJ4>Y9UJ zBK}8;zGeKVm>zwtV6M`S-df-c3IZZ>optjEhy)V+0*)!?|at$wJ(ba+6|Fw^p{36cztt!m6O z82?a9e(2`ZO8lVlhF)soR{#sdjIE6NJ<--Fds#Y`F67a8)9GT^szUf*dRoO#+ATyR z3=FIwlJ&&)Z9}o;PX59Z~Zj$r>0 zzm0_*$>vxS*Zln<`lkeHEhF~^(~{KOt8f%L9jrfqp#{3My2%env(~odYN+4x3}EGRyLVFV0uj*tW@mjzx+YGGmd>D zuj5gfE;0#>1`Eg}dGh@;Y*jH97q6|E?>PUea)-T9py?hm*AKvI-wBNVejrnSH>#H7stS50zZNluK&9%B-BVvUSOS|aFAR52 z&+Pj}dY4ekY~@vyVRz2r!F7Brn1*PP1ygVvWoBj~>hA>5AQV-vC|D!^_62Y3^ktqR z^dgWzMSFB~3eM=m&do9 zFT`=u%2E@C--SBM-eh2qt_KIpa>{(joVtwjQ+uzD!l{hk?4ZU9q{i|Ql%tDaBs;on zZW2^-U&)74U>bC^Kxvqz#rBW=4Uq-ZWxDV<3h5*~wO}wmzmcOD)drO=8Uo!%3Gkk! zU>+fL3}+E`a@^l+`S1c@8fiQDY%-dT`=EBt1u5u##AvA>2(FL)3{;>yU&V}eucWy=kPLSV}@`Zg%EwWF^n#R_ z?gDVv53@7R!$vJrQ`1Y>VG`2&`r%R->;1CM!a^5RRmF;h?`=pvG%Nq+$edp{2<^N4 z<0PRSPOhcDgc8)EB}{-Bryj3=+c03BV%NraHeG0VWlFi1!||0r?e|wP)R@gN1xuEi zfwlR+bIj*)GikPvK2SQEc4f*0GC}3@VJB(6=Gffh3_gE~dGc3Guf&CIGx~+y)z|fC zsM@)9#e0m{sIUMnTWM8Ix-ND+{SO2ky3~CiwGpERfl>{_FTXW4_iX=`F$3oKYJ1xm zCVQFL*(msZAec<}g;<&>t28__PEzP!Fl4}qhYa8rP}H+=aNKorx&@Y*(AHj7;M>bx zoaV)GnAq5=z=pUCiezGDX5{83SYKbiY>@h4>Ku4C%aL%v#tT;4B>foMzqM$V`hxm1 zR{mI_OolbLL)osnY>5B`;UkG7!stM|~ z^P>i4rV}4z2_1-0~r@oC7XoMyF`V_pcE>lv?zlV{3yt+wcA-e8B6va)N$!SHN z6mwF|M4BmKz&hg;e055t%(X&XzxHW0gG6aON@j5Svm?&ss{DMOHvbv)J;`s?j>U|J zZ^z3(N_HCi&SWwoYjnez%%64om0mgx85OQ0ruch`Ygvph8PF&hC9tPvb64&y--8-d z0{R+2Is@T&$t)|o3Vd^MDag=mnw+GE-lqj>j2>B3B_uxf7-B%WJ5Fp09emALx{c;t zAfs!;&Rbqy78@-SOwJJZ;AaMBpWiSRrms@M(Cvqg2L!o%Mqr9Y!`=-$uMH}c`>yL_ z9vQ*4G4NlPoPzoDHLI0m@aF1zCkVkjuLxQIubzWGNg8U4+S=MVDEFxNAL00(A6WrH z7rRwgcX57)UFxD%IlDiuX_!}ced#yKbb>qUBgdZx_f9OiIzg&YDOcgdSnhDU*4HFT zYHD)6zLNQnMn@fi1x@P!)<6WDO5m~uboYnDf^zr1m9lW(6QC6p_2c1^ohnA*m zfxaUujXk2CV5}js2V&`@0U7Yxocgv=kB%(E$o1LCChL1Lab-+@n4;I_UWq7mJ|Kp5s72#CVB>1-uXCJ*CE0e%HW-CA9Ws1!S-*T%>p2HqEl$7fLNdtGB7uz3F zyz%KJX`m>3uCx%x9;@@H%;jO41|!M+g^oHO*{SuvWb5hbPIG_Ii369bszFSxrj{la z51n$$Ym%EUz>?cLhUsle%1WssJ_6vVno{nqxPyupKa#d2--T2z`U$W2I1eoMq{f>> z+;i~&#C#A&64NUy;ZV5)bs?Gw7x)w2J3Yde8-34&&q)ASwHHD<*yCha|s+aKfwcUd$a^g3V5AHBz8fMN7 z2#)HwzE`hWk+&VlBY->CiY{u=xdwRU3xjnDEg0NJU!*VJag< zK(e2es7s$SBLg4>K$E)(Jg;efJ`d~b{lw4+7?=lwHp&nj1M7G|U&9WZ5gaKJinsZp`tYgMA4T)K@=9&Y6_oJvjV= z?N4}|qYvsQTr?SCs3zKFw=ZLygMu)2Dim`1*PR;y)dMCOM(n>sD+4h0d5};3l3Hid z|D7Y3&QG~?Wy2eYIe?afP+W&vwx?#ilX~1WD9ciU8^WY~Go*z?RP6L_V8wa{4|Aiv z;@YZM^M4WKa4SlhN}T@>1ux(}^50h}dNH5&psL-svIj^~D+6#1JwA%-O+06h@;oD8 z_q|ZZ0%p_a_~IyTDLqqItUbdJ0(n(4rFQYmN8}^Y7x69q|FreiK~a8j-|)3dm!yC+ zNVkL{5)0BHr2^8Rf`sq`X@R8#q(SKp0ZD13mXJn3QaYu(Yk3a${XFkqud_1_><%+~ z#ks!clbfk^EtdLe!b0gMtHoI0<2ds~sF~-CN)X#`Rt@*|48!9-=P&EziA|Ls*0uLR zBj7Sn$V1Sr$Oiy6W+^IX$_+u|b5Z8)dkol!o>-M!)`@rNyhXR6;MODgB!_79b;ee7 zwWK=%<~0IK8aQM<-bR2RA@89*kPaYkznob9>oJQhb*OXQAhK`L_`z|h zWSa*^^gSh6k>=XM(h}I))O7z&t^W#=2aL4~jw0?0<;MQh`dcIX-xEdu22YAtBFrRz zUIkY(XGYoexV@q&hCU>Vh-q+5A9T793SOnHzke|9dXIt3ejsa$TU1>~^ zW8R$8Wf6}qujeYN$;5oB%4W`Nixy)jEAi1sFHFwT!Hjuhg5Skk2Plk7@90v)A6r4h zmcRAQG-f*)pHa+pOE3v=_o0$W5pxbqId`MJK3y1jEK0U=k6Lmh*_vEj`(UZZ?l)N? z51&u#r!9^wOdyz8$c}uDiw|eH@B1sX@IQb^gU(lg$cR{vD0$DLU|?Z-Q4U%pf_mPA z#cmNaOf!jz={14*%N!^WAtntFfPcB$90~04Vi!dpAti|qX&6QKZKN1~?+^G@f&Pl= zT1h39@8@A5bwrc*=kp&S;{Y~bu(w$%nr_jNg1Jp<+6X%)Z(jM&h7CysuUx=#OY1ga zkKK=8-@Y&u%1{jYL7KTXR!0iIl4C-krgV^lB%mm6f(GN#+1^>?-T10dV$l!DL{}l= zuFD`@^KlhZN7liX;N!k^wo7B)64Amup#^2N`IJ@mj6dIpAKN2zoHU`E*P27-2=<-!1) z?(7w1IBK`KJIZZMV)b3lByQdZ@Y3*LQ=>zVD_IB3Mi<}46&y|YzKYAWe@~%Z< z5nNdGC79TF{n0DSkhXBYVFl~z=%g(dP7!=hqzq-zKB~$=RRajMO5I5IDjs+cls*us z)a9Q{i^FVpMMCzcWC(nM7;IL>CFTDp&v5c{KkyXF7=pVVAc4J43(s~6r|$|LY=nQb z4s*y?QQ~m6p#6^Z(`B3c{Q5M)Y6LeyEIOzo+@uwxxv>GUDU(739T)J*QiC?^{{TDy z62Ww&-cO6|gYx9(0lMIg9HVOt`8&b1oDg;IE)dr$1NfZlEhgo%288(V zp|TAh^o1n37w#s+_QzQ%9U6nfRl5xg^q|4G$Kdr_UlaWh_QXd_=%peF&ihaKowV_k z0Mhq`OD7*JG~&f_gF*>(7Tg0#Yl(CfI7vtA8Z-GWMAkea>%-}fJh6VzD@nEwU=DnT zBmPbpvY(O8GOjF6<NN%*Ay^(kit=U{O(}QAlG*0&ZCxFs5Khx*|>-{fGnXW|sJ37ywzaHlyr>74G zVrM7=$hDj)cl|O#r2iL;(I}U8I7v{qDm9czmc9|;^ULw~WtG_oXFA5lOjVO-Ydap> zWSMS8U#OyccuFN4*--a(WuJDNJo=v6&&S2yUEuliFHhIMlg$JZ{c3wATW+X5;2`Ls zC0-DWS)4mE-_n!&3z2nvdVevjr}ydj)H!i-RQKzK4)v$vqIO$&pW)gA%L{uyZ0V%p z!n4Tka(;t$=QGp zr-)rrNJ>hI_#5Dwu8(VG+lZCFFC~@6?peWtu%~R-NGS0nd-i1WWZ+0I)yhPhdwl(P z5WMcG^KiznDrJ)@+zF>G0o2L+y>)&uACY!8lEC|`qs**nnVrA;9y>anLn3t?cSN|0Y;RYH8RPM{y z$>KoH_`mBFnR8zB-!wmja5v=;C>%m;Q!5|TI6>EMtWQMHE78(AG+s78+k74MH5WIx zV?O=M7Y|Il9)a%;!UevmsUUM*=R@L+0JTuCwPoA-_i)UiJ{7Cj7{{;IKROEm2~sPs z5wUV+leQNp^VjX(F4Ka7nrIM2pe%KLG)!Un71}hTPz;%Ru?#xZZ~Hi6Xlho?0!=4= zn$7PHw4$$T`lByTI(FW<@7lWSF;myO@)|4gbkxkHz2@CbS3--V<>^Dm(fMtdQz)(o z=U%V&3cO&vl?XJ>?Zfu~p9p?ELwbI*?d5LxeDw0>@{S;(AZINL4c^Wo4S&9VSY0@7 zZM0X5W(=2|{diu_q?S0)BI6FH_NI8*kpX0!8 zWMXK%S)8XO_7ADkYmfa~iM{1-$<^6I@3d8k)yMmiW+Fp-$H#v0N|>^^>=E036Az3K zT8MLczE{;pFyzz;rqrOX?7|DbG$W)|TVLw60c^08gJc>W1(I2bKuS$~Nx~+T(S5_t zxB(ki#;dn~v1`rRJ|%$e@7pqT>8m~ei^kL0SmoS57Z#T4?6F&|fi4?0vp?^A&eD82 zMi1g!I&xL3LI>&i5nH$-AdC32R6N8R_Ef0@<(prjsX%_P0ih0zUcstV>SJ#FwqCng^RF1&Ju z;dMRUOwu$iOm28rL_fP*x8>j5d(WS*J5Epv6dEsG)_GeZ&;O0vWg&G|eRF(ZMvNl$*K_A2B$p5i>7GSXT@x+l_Bu8G z=6=)aSQ|)zW{OU@d<}L0XQ0|`)ZP6pzh0w7=N2mm7_V+tc1v>uoE2BDNKtz=& z=??ZeDLzwHBIs>K!-waJa&jb|J|DjZwpMSyc0F>=|FfAnN~>up(uz>a7p2xL9?xbK zdH(NN{q^-VAh(#N8r+3{xq9Y_4n5&n%EkoMvF-2fQ3)U=4=fFCJ}&>g?^As&fMh%; zz(+|UbnLlUO|blt6LzhGr|cr?F4j91~Y}@ zcdxF59kvqiQpHnm8J!WJ)_c7>+qjXELO0#uPEIU&MDk4|oxiuQug~dAdk_gr#VS@A zcDCCdRs|-?7~hJ&jPC*@Z1&8i7hgn>NH{R{C`$QFy`tZt-pCN9(XtTC)Gk##&hH## z=kAd&WeNm?Xa*qW%K=lhQg`29{iwQUS_?kmKN&aeYX97uNIv(@ja7ggCzZan) zrKawh`dlS<4Uz+dca5q{6Qvd3eEb4wj9@_Wj*e;GYnp$5{jhkQ3$T}wPMlmx&&5Br z{|OD3StYiX%e7Gfu>aGOm(m8GDuhbBta>+q>!)m3NEfw?TboRgKgdUr)=i31!Dn^D z6pN8&dJVVL?!EH9A_|n%LNEM09d^32qj$C%zQJ$Q=1=;hn!wMWwN@vyt-!=SYrcn` zf|8Ps{*m_uKQx}wO}Hzim!OLG%}hU)^)zKxSUCbvoyx zJ5@0Ov?5>t`^;xhy~o15S>-e4xv0X6d*5YTc6Hd^ z(5H9!fG%2^_M)}~>OA)GTpsvTb|2Nmfl4!cXgqqHNw&xpM#p~+OCS6(_D&*i&*+g z{)HQ_*Q>nHc=z1>JF%DHSFrgIjx-b)$o94>I3UO$o2Ydu@-)8jVx#bQ`D!Ur`XHtb zEU6OEb6ZavA33I?ejyd+w3h33JhL(_07!AXN21Hz?HBW!~)V0bU9ovby?xb|S z-kquu7|v)WfBB0K+9QRiFGt5Gr}1Mny%X^XrDYiv$!)4vFLh24!qsYv6lNJX7m!dY<)eWlY!iMDJ!J} zVg_bnf{!0Rx`4Xck3aOTXrbKr`1sFR`N!bTs*@l2La=bndMncXJ^!)SPH7ct$N-Yd z=6>NvB0q4CzDO8T7I8cPe@0tVbN-9r3jno&JsGI3tVncpMqiz$3{Y4u7wcCjJoG_- zJO)~X(U+f*st0QXz04ce52dc35knaQyv>F5C*H}r%^%N=p-jB8>kR$4D=kJj7fE7N z5hm~f9nvIMM!tS<*XK*N0%OtG2o^%B1Wx~yGazVy^~DSEt%)Dm`W#2g?uW+M>XGVc zk9OZcz0+}zTxSmhzICz=RPhaHsl0We2d(n`sZVy_Bs~lVNbGE{N8|fMB6*o*l@gps znU-@tfS`D;ktie|2ZU*>5re=i)7#kC$hZ#(vDV&R9z9kvWgQ(Id7$-5u@g!(6Sz0=s`0*1~_lN_UZVeFXucbxG%Wob@zp0{VYU>$~S<6nJZ_AQD8wuy>A?KYgo0;#&4cl|{ zc^!mn3vm*Gvdnkz)&+N?E(AsMeR9%AV~1Sd~6$`1M7H0_(H?C{X7!)C*0lMEo=G?CR-p+`Lr(&cwmdsaLN3 zGyE148WbT4=FTV`mf7NgtuX=k71)ka#NYlB?!NOnRoW-*R%Vmd00sgUA)y$@DlfgX zh`aX9vJ=}*tCQEmf82cLjA=|u@F9+a)!TygJm*@Hc*z5kD(kzTtjD(aL+!}=vK)oX z=1xXybIt_i4d4s7AXD^|fzuCm8^vY&eL}ISNpO=)PPSV1OnCL_rrjs-8G63M@$1bu zoT&H2pXXOq7g{t0rhh(dGd+@Z$C7zNB-4^E!UUf@OMi3GxsX$KbjASG9 zQe|B5oE_xIw?w}%k{)nxwJ3Pb{RRZoS<42u?E++4@AwINVUN9#B7`;~Del~i+v}F$N!vOpl zW%XprXU~&AK~oIuUyknP`J09o6)XQ8Do09|-Te$io`u=j*|fFj^PWrd%#oetlM!no z%f}#@J$V246>c={-YEw6cdHRnKS&y1oMv#0^n*1I+zyl9L>QQFm9~{0C!Zc9B<$f_ zkD5PdIjs29`kIB4Z#etR18d%i$h*b4R_g>uZc)XsR?|1GC1OQ1^?c6yoP0oH=@Od= zQ^4EEA?1q&pML_wW7g9zpxU(f1uI^)K4GE%7UcwUN=L0XJEMMFRe=1n z@Pg9PU59Xm;R@YSV}L~@fGSh4}`K?6Nv*xfy zP*|t*-w1>@Q1@jEmZ(Lgc-ne6PB>tKbSt{yOKI+VUKf z%juH?Y`4Rz2}$+Joz}$@SFe|$a2Xurq>Z;jzRdYZ<-3Jr|3;_PXZXpVNNhA9-Ey$f z+aP|IM2YH_eYumz+Vab&%kgHar~%lE4#v-QhcfG_L?-KBRINgLe1!7 zTPa{~x8OHvvORo+fx$CMQ;ci(3M+Hb1tk9RI9$nbmCUh{;EZHhjMG@z*k>9@V~C%A zZ;OaLeBgetoB$Am>DbGD^B<9EV$QEFW8zvkMd04qow5|uKZ%T9h*F}MKNZ2wfMuz% z!krP7P}{9Db;D*IQYeazDJeoT>)T?dR^_?^gQyO01mFKz=GqR47vL6kULzMJ{6on% zWo08u^jegPdNVzX6GUZ2LnvSojRs2W*qE5Ce^1dWxqoW1vdq7=n39}dUM@u|GPD5L z6<`Y(fwI0~VT9m`y#%~bXCTgNA7}uxfaSw3Okv5tYzb{yk4WW%fraZCj-hODY_V4B`lm%>*ylrs9DQe=MO0eDTPiNkCzTuWX5DxU0wcjk3w9i|%8 zQZh!4g;HjEzIv6t0@(z=AqukrHy`ch@lWpRYPeJ^!3ozMu25AYO&=d3D*TeAlWiI~g~W`Zdzpp8G6t&ImDGdQNC09Kp3@;0?to=;`z}T0 z)n7JM)+c%tWDU#C>)XEw;u5*J@BHX`HSi{^F;}K{wc)3pdoK_;p4Fz6>d1BZ|rp~_08rJ#WQb|5VrNCf;y{D36}Z_ejN65y(#KvQ)4 z3g5T=Cjuj_lN{t{YdoX_MD1VmvYJRyOo%CE&fN7hk;pdx2Z=E0eqn)wz z+;qZjJ~mPC%*`Mxni*t(JJWsT?xnFwb;HZz>j&PgnqeTJ-F|3&aGVdw=mEBYT4*ER zU-+r&wipu1%DW|#lY4%+m^U3XhhiymaBHI%7rF9LfH48@mC#sHW)&IYM=?>T>MUD- zDDyR#9ksu!KZSl!kNi$OJu*+s_W=!0Z0zi0ma`=&dBEZ?3(m=|G^ZFZq2lg=XpY8j)b^KiEyx3-7WFi9 zP1LPD+y7P2r-k-`;|GpbJeO1@-VL?U5*)_JS&U0!Y6_Z3JgR52$H8H4yp$%~x`*!# zbhs<~4sGb0NvWvDIniATypZsk5iG^H(rU;7h)mW&L(=ElTm(=X`s@3PLWCB@E$%~u#B}AaJ7IeUGA{AtIe_6~`ikf!3P|$JN;c7KI*Ujcg=Zp|B zkY{PJvH$f#B8s<$t`c!IwkZgi`aWz|DSeOY-f)(!pkh*?(YQM zS8Rxm`?p#aQFt;i_Xoq&f{u)tEA-HpBfo)jc!h zDz;@RlsARgrO%5r#;DSHN3BGJlg{^ZL6*l<{#O5^Iabfp9eEd*hpU;8!yVK*@D?2b z^Ct)JSd`GWONjEJTQ7aP`m!u zv1sP_w2chOCxFZ=_EBITXG0RSee(727Wadqw6yXi-R~s1KAPRG$>|*0Uhia%PAI*( za_=;#NE}!p?^BUOhg6(x-Bh>vtdWe+gbhB8RAiu^$d{sWA6N5`_=}bwu4?k)A{b}p+n!6=P4@flH$>&IkbFjID1lwV2EQ=ihQRpoEW4R6-HCjS z7J9MDh>UE-YsEnFJ7;*j);VMP?!7&i`Ucu8MxIn-i#ybh#Wp)bOiS99Jt=Mwr;Tdg zO!w7-;*v$loLI)UsXrv{7*cWWLkM!}aD=m{?<_=3^fs5tEatDLMduq0dE(H>g8C{G z`g_Vtd#CK0Ec2z>_+--am;Oj&RbLiFbI?akZMCH#MT_XKUw^IZ*_;bTRZ{hj?|vsk zSPhHmY(C7wI5MKNCT0qNS88d^>V|#$uVIT9f${^jsJOA_f$%iW1dMtd8> z%T}=Va*hXr&hCA{C29rQv!JtDGb_fscyjW79^M{LbE#1M+I%Ok8J`9XGVL75UXh6A z(`I2i+dPjfZBYDn)Vdkz4PB%pUaj(`tj9>$@ZuRB^!IFhwMaVf{h$gf+xpv_M>-Mq zwNSf&IyAmqD@bs8p!~DDZzBPcYsu!^00(-dX>to4RK0oZA1m?jeCjjaJkP+rKSIt9 z?4Wmtr_`AwurtdGfg!l|?(B2_%=2RAd|?u5bp-k`xtfS?1)rxr5NdBvX}gJZ5X7b* z$f}FVIJ0FGd?T3+N4?IN=Znc$d>9@heO!A*TZ4Q6&diZJ;#AOd#s)QgYNP{KDt_Ce zs)cbH^m;oUJJOAM8&;VI4G-P#N`0K&p;?&Nr^rxTn0j@!CIgI2$5oX^%?nmbs+q+B zekY5O6Neo|H2&3b6%FF4E(Zaf3JeK1J09(>gsO>GbXzRB8`5NQLs}lWe2!YGoR&cuC1)F?Vmof|JBpi*A5bLGDodJ zoQI~aE)ED>6HZjq4~Wu^7^_nJSKZu822By58s6Vov?O6*@MA0GSeW-s-#gxk-Md?Z zN@sJ`EfWtsQAlmVCzd~MpFCnM`sj)w;0}g2uMNbsWfubO zLL%I`IKROOVpW(q>HI2|Qlsxr>-?7&(7F@u)hn2Hv0Lf&6tm9+lg%^YPon1rotS%H zJN>Ux0ZYm>(jGr{Xx(GGz{vmZ3B?nPxkvtUm?(bRyFw8tp zRNE9J2-}A4PuzW!sbFHnhvN`nsmu7_UEvDVT*?Qgqek9$oh|n>>f9*Oo4;u4==K`S zlBQO_Z2EWX!w4AA8l~(YBE^<-Q0@6nLETP0oX5^aTTJQXDJXWW+rr+%$Hx~h9<`PR z`u~k-AQ;5W9$MR8TJkR{;sw$sZ1L1PU_k{IAjcOD4tuVzicfTszKPB!z@q4*P~*op zt_E;ZPnZOA=htaiwV<&S#nQ@CfC-M9(e@-Sr#Vtpk~>>k3p#o6q7P@ZYo_8#G&ov1 zO#6<~-8Bep;wg~-%C7A67~8)~rj=`Nd0^IhKoaWcuyTu)S&l8Crh}AU@V&2jL!>I% z7^ES{`{)0vyxHdm8g`@u;~O@tWwqkoxTw62+dm{me*1)->3epjw>4SSyYAK%a6{S5A1Niz^0h9oKN#&f7s8BjYNjBlE^ii z!j+)0=C7HB#c8?VD*h>+NE_bKreG2N(aYnNg1UOY8l+hCrVfElL-^ktO}a{~rFV%k z1;V`h?!P=5XX8n<)rTv!OUG{jIWqPwE6eW{h}(Pt(ra#mmkVvItwlTAwOODo++2Aq zlAuAcP`EuOcuc=&9Mdd`g&HQZDkmt9;(XKl>K_KN;;~aV<=PnW-s7WA@>z(gqkYHI zbp?ntBgggX$oB^VE1gGQ7)fwx80gIWdKxz!owTvRfBLsV4Tk!ro*b;i3P0?0G3#A% z1PETzx7&ih$A9l4fRoWjHaO(ly10MKo_~Bi6&qQ|N7&gP5u(`cI|i2`Ony$W=0agkz3oN!oqhTSnm&X00Fatb&l%{^dCl#AkMghAP+u z3E?pO4~cMAk1*GQTT$+ZI)KDydx)O5^j&5>AQ%3JW4ID#f-}8ovS^gjJqiu6E#qT{|rD@|FEx(pqWZ zcA;MeeOleFjFtm|$~LJm{hz}Bo7UMyW2MQ~B+SN^#VAn%El ze`lwpb<38-QUxhoWLzQsb|6zSI5KyTN_L_MXXBZGN zS)4v>QryW*{_a!9=|7C)8q0r)9P#xWLl4E5jN}q4HXq!;@=B8}9N!Bv5boDMU`T7g zjuBM$#XAW4fRr_7_K5fP&qcV=d3fPFI>rdTpJs3WmCN#EYFf916Ry#GB~oDJOl$MC zkaUZYaMH>zVx)i={lRMb!|>8;w|3mWphhi)8!l}5n-!#`JiL6a3CEl!Xz%PCAGqiA zukY4*L*p<2!eMCXo~`iKeGzsyjQlR;bx~OrkIKe}O3z>hc@yq%+OItcRMTontsFrQ z6?;>`7c~XtWsv60+=&Lc_bf7lQp})|-g^y`+*|JNzgRIHy$G(t>W5Pp4kzPIYvVP< zR`8T3mfl3uUj6)ec&iVX={o%v#ThEz_QR1EHxENnv!G6Cbq3EZsOkFUjuxA#-&N*h zP7bS&DS3I5OZddhkG)j=8%WUEn%&W{?VbesT*G7dEVDz=gV~>F25ZgggvP`>R>vYnlbOyM;&7h9fkGPfs zP@b6-=uMEq*_&$IVLZ_%1_xBe#l;2VS)!!p!?V}?&g`XV_kkW3kjh6vbzs?3^c9JX zj{r;w(CEM+kWPg3ng|0KpL??xPKuOZEKGcrtNq^zre3=9Zg7A}Sx#%^KUfq02>`1e z7sn#A9*FGun3N}J6 z1p$&UPv-H`J=1v4$#PfOcGd?EhWOV(Ryh&S=0`r47 zZhT`IqFoOg$L>@moDlRrmSnOW_tDnAv$*(k(>U^u9v*3^0-$C7du&kGEyw0+G+( z`xDo@!U}9B(2flo=&XPIt-L&DKdx@{H-Kv1K66!$kj>%-z=rI*)#FE7R6;w098xBbZ0?(j-vj*$8aP*9^Mbtt1%^&2Tpz8Mt(h% zw$Ffo^+cQy{<^saJ*`Co&wk#QE^U$u(v3F#9gBzuK!tq7A1ZCSo}}YUKs}dkku}Q? zedo9VCPb&0b4#rUBK7f4#V?!JsL{}5&B@cD9TwqpoGL*9*qPh@dmHdj3u`1abstd0 zR!5dW^KJJ~PE*KgH0l@r)XM7ao=v)>d_?5Y)wG7`;S9RPY_nMvq}o zgaOetLMe@yZwXAyhX1UVqwNXanYcad=6HJ1=i_Cl8(cvk=F|MrAe3}Cs4)8pp?sPfC+My3@qYuhHH}pS(#*`hVosoFyScd~W*>yPjo22Z7s~cUNgsOX zY%D4mBRykqkX0w2fhYxJ7M4W&p@3fa>wo=DyS&sPkRRvyO+^9V>vw@vG z#P?ZC*qu{p9&UOhG%~MhdZ--wwi=QeDDofbk{;3r_ZCBa`dN%L^u-I_P(|vNLGIvG zN`24ZD4}Y``?0`bnp<4^M2q*MCgVVq5?;=Xaf@zY+S3~;=Cud=^v{-Ba@Qr|@HwIO z&sSWZ&W!ZOSFIPEe5FbX`w!@NG?2p6ob|pxLM%upSg6^1g4^b9kQ+%f?Y}ygO3Q_| z`lbUP5B%O(?+4tdKIyUoIK6Ar zC17dn-n3)Vhm&7zw(Z>6y`VFUU`z)XLJ{P~a!c&>{lwf{N?QeOA0{2Odx>>np_Y@g zjvF8j%Mih$ z-keRVPcH9*(V!G$lj7}0h3*~g;@2Q(ThEQT2{DjTbu+fvb2IbE|@xSxgx9uwTKmXX8s43y#ky7Ex-yiRiuK@A#JV#-;j-st;7T7?dRUujQ@80Mh}XI9brUanesqEk3zKz zD1g`~GSB~Q{g%G3$8mZ^Jf@1OsznO@kvwiDwV!4E1xP=%jq}uoF}=)Da`WB+qZH|J z4#@B2voOb?-bKjC1tjV7Ta|>2$2wGx4V0r(&3ii3qRt$q=}t&qSzum$EAij&FhOV% zxW)T~G_Ic`z4MI%jJCEg5(tqs|v%?wr%ME4?8IU6*&%@}ZF|rju zC>qYm>%}&~s18b(0=4`#ld2fMx_*~%mY#UU?VvJf+j`1+J{8@K2b_D)L2h7T(qBzx z2nmj{Oo|b5YpeAl71}a{Rlk3f^vx^_CQG}p$&cIS!u|Qx&`M&Oo`s%v^z4J zj48esge3bFX{1YS0K2C`dQe~>U`J&>T}rT{j5g=g1t0^nHE5m?*$s&?zL}(0CKdy* zj9K6ElAcvb5=``iIJiy9y7gQGlQ=VbJt?iv@31dvpNn5sN~g+e!VWL(86A6i2m1{y{xGG z-eIl{wbzb#-oKBR#nb$MF_0@x$;Y)Z&8eOveCB)YcYJeFfEY3(dSw8U@U11)Rdp9)D(-i!qCF-tZ?9p;ME1?`$fe7H9ex|FEbs6;UAQZ zL;n;LK#cZ?5sAdqP*FswOYGzLM?pAXbgg=Ov6lJh)t?sPkygc+Iv4)2UCHpkCB}}T z(`HoV&8d(229e{35PcIKGiA73U17@4r483*ETx`q=IX9=yXz-Ut?D)DBvSkrhzWyy zkQ5^7Oe_k66j-vjYM6q5Fo9-kQibT`x}4ZNHsN&4Y|{u@%PcbM=)`>lFe zxI55hsBg}_ShN&;Gx~B1F6jM+H`p4M-#I?7X7)J$Weew7MUU4^xv^?~@uIQ(qWOYNRp*19K_!p0PiF0P5rK))P+z?QU6inA$fwl^_&^)w zxp15`ln3(#vZm}$(hnt!C0PV`e(Z`oU;mB>ft*xGY1qkOb|NgOMCS z=&eQ<*WBn|#Ltwb(Dre{Vs*XYF?f}UxpK2S!+Q=JtH?-VIP2ouI^z=tAA?e(J`7V# zrgG3g*1uo-*z0I8M)%>HAc0ijYI!TAFb33LphJrjWMtd?<0e=$T{G8{80@3_ z)vm}V~X}xavH}Db@ ztX+l|CE4N3W37x}FfxH;`&8b_6FZS(0_;pM88 zC0Sh6Fp!QYTkxC)#PBupsp1fxM>;ypJT!Z(raXiB^eNpJo&FDpm#=nu-^8)R%4WJv zs{d%Rm^~9SDR?dwlbjqnJ#9!2RD%QL?HYBlG!yr_In=a8s0EtZw?o)`|Nn%S`;dXu zglw@<{lmALJ;k`27a25=xAbYU?P7vhj=j>rRKzxamGJ%h{xl#qE87T$?cY+oc`BlR zGn{q3i}5E1u*v5fhM^pB6x0Gp=X;h|s6@8kZQ8EK3LNUZb2@W1Tmpa}1C~RNip$V# zvxS0;Wl>V*xyV>eCM1oMtoLX5JPyaD=i`V@#=5$?zK0p#K}<+B*!47>J~ermJ2e|y z4*J>)76X4VY+}4jySdn%P~oR=Apq90n>WDgXc&@8zX6000jB6#}3jfj@fUMlJt4a?y~J1jXX6-Sj5BERZ<(Z!hyMW1YFfev#l!0Wyzo2pjShz zHuJ@Me}C%Qyt46dL8O?DTO?4#L&TAYvo{I(HFX0>tM@PA9?6$Np;yC_Re(4 z+sW5}e-EhA1=0`!>SGkx|9RD+ffo3mxBd69062DI z@Gbt&1JeKdhO-o4<=SMq#q-a{pS8Ag%e=`QBRku+h^|NTwf;KyzpJaQ4GhSgcKWhX zP8J(oIEdN`3z-@&x<_ubw_WCeTOlcyBwjDr+wW1Xo37>h^_W4}>!Sj5=N{LG|KwFw zq5LWe3ipb_Ln7W|HS^eXDlyNBDJ0=9Dq(J|I1u>#Dx$mjdOc6#av+hawL#9Z{FYoDp{h+^BYZ3R2F5# zz;E6iV;yNepo2XFvs4Qzs#}5p&@nR7($M7eT$ZWosL~F-&bWWNHQu1;Cwldm)e0E) zsxaYCb8HD!FOIh0_G9?Di2K+S8Jf2vU-h8R|t+($mSa;^N|#;`g<@Ya#w2 z53P6}JJCd8DIF=hJ(9&0GjFf-=x;h1OI`@8Hx5aG|1P-t8Cs&IPxj5do;^UD&v<&J zuzP_SI>7z*?P^`fkrYEhJb1-=nwmjBf4)9ksITbu!kukN9|&TwVGKDVGwd6@nCa*Ylf=ki%eCQ_rraT|g<7YYmGBj{J?EnVH$4 zGdLy;@3`mZ9Fc&U4v+V5G4HcNs9?l0QQceh%#)Loo7UFW6hB*k=U0i$!^FCu z>iBrebQLKvB3IkvF8Mis`4e|D(nx>M?hD7UF>7+=*>f=B7Pvih5S$2ccY;9!@O(;+ z3n6jw@iZ&fCwy_|%Nm|$X0NRkA=Rj2fTneEfVjz7r+YS=rucnD47~;W$1pL$=sMXB zcr0NU_#p*_hPpRcGNzoO#Sq(WLKb-@ofgSKkN2rh9bn|>Hf-|quO-AIlIv) zR>NAlWX=%Va&4)zKF(`xgm=r*JIuk`xkip|Rb>V0O~c682j3wAwAiW4!SzQ*N0&Jz z$_-hQNF^C@dG5Pb!O2#MckHmbnaMIuI}1~(&QiZ2z1!luGRu@N;NDZ#C`x?C_xTTD zZEfvKZQIz`SjG9}rNy)jkEQoWe>|<2>$~Vgjpi;D6y5Pz%fb4cr<=VgwzXvS@3R*ae?b=;AiyqIVYxT6E4A9x#};8@vnX7o zx~2N{$1$FeQD`A#_3OX7yyPVl;zd$T8_Fs>9m^CU>kh$i2`^}Ef>%I|%vrvp@({Ut)AhQE=AGKt zu8iQ%XEzsb+#x6)m`=5!r|{xgk=jlhNA%{iEq+}zyEGzhO=z52y|W7{*O zDyH22cs|6t<*A|)!wK6%#-e=0>T~iU!`Zy>5LN|VqN1ah%wrkbxw1HMB6{Eg`V-dh zs0Q&o9fc{gXwmt*_|z#?$2P)LM!2nogW!*VPZY(!1-2P0hmu=kOO4X{9cf+B+{#2J|N4{d;1HLmPR$gY zJZjJ%T4a2+XxelRV}h<~1$R;r9gqKqe}R4;Z?fx=;NvXRbbcF;`q z@r9|z0s(-HW{0X2xO`t=nV%IsUtKlPhZ4r{GAN6zB}<0Kyz@fJT|T@!zyNzzWc!3w zkX~7cLeag{#UDGaynjfWrT%~G*hfCmf>m7BHO7Vh$Lx)8tMGi{Hn{GNCmUV2HAByY zP^8)Z2JJuqqeg9~w(NPkN_t_ejbQhHVw-|VZuesYn|T3uz+m2SjxhZ61>)j6 zu)qPZ8eBcr=h?$EseQsBwc(JaPW%xKt9kc}j!|fdVqEhP5e_2#8V4NUKW0^mH%o;^ z_2cv=6^gdKO-I=uXdP{p-ofFZ4GgPxCVzzU6J6DY_QXh> zfBycBYdcroGoB-Lw(NaEBPd9!S5{XP`kANbr1(^bWxV_ga*c(2Lsvq2`XcpX`E>O5 zpLPkmTc1j{13Pz^yOGf{!C7V&!bD$7gn{n&psf-OuIv#j<3AEx`u|xmW`IxiZsvc znN`c&Uj2P==zMUYNxfqRN7V1QfXl(3^7Nv!+%mz@caBH6!3?jXeP}3Rw_FOBApmR$ zDg}YyRB~|ONM_fcJ=~(CoJAS@SkSZZv10!Ej@NgYoua;{->O`{gCsL32;p0LdepC9 zbRZh+-0J_6V(j-`r_L#D_%~ZR1sXOPnK!+FfaflFrd}!$uW2C~nzf*hkL)ol;M{BV zdulQ{S#I@xdU{gr?d>Ie*Y{CdzfVT?QazedL~w7t$N1z!@y84%TZ_(){(X{Gql!5e z_43V2!H?EX0uLLM|Dh1Wn(#J-mS)RSZ*WLZU8$8Zlk7f!4=17G|7EDQ$%t#c>tS>;@0&g`@o57n zDJf6S&%f5E5Vf=jtK}AkBggp`NIkKy`AG0Y5iQH`IE&+IfBo}}jCeBEGfiMD#byFP zRvw)p-6V%ky0BSHC_}v#nAqB!4snmwG`$-Mq15SxJxlgu~jxA+{ z^O)bN+v@#3x6TrrEKVFlEQaD=s@ap(nDlS{?=+d+wkRaM=Xo$yV6YApO!{rPD23! ztJ63+)lB|3=5xm{>>_UK(gl%s?co)PgyT@LXQOXT`%e(vX7`HyrIMRiqnu1RGjnrg zN3Japbn$zhTTC~(9W2l6xqiI?8&RNP^Oq40cJ|ihu8CO=Sck1lVO7wx{Toq!V%D>? z4Wm%{KQ9Y=k*5b_L9bSXgQEKU;`Fi@#>RH$${4jO^>*#DhH@BvRnT zfv6uH!N=t<@7uSya}g10dU_FM`t99^|FAYzI|HYAamV%G=@JHl0G%SuL7p9m0Qbj< z{kxs*ZArrlYp#w&7W%|NL8hcDj?k{M<@QhX;wk6>AhF;Rj6uPYYk%IBaB4Sf3bIWO zlbbpq?@aaX6{o|OcpWd!Mkqyxo72*=XnIypwD0Z~4I>%iH9>|UYrJ5+JNg)x_>tdO z4Fh*IwuD}x`sT!fNPMasC@4U-sRb&s-+QdEU4qTZ*yjwfH}=KX;BO~mHw+cy{#c!w zr9n;+!{bXr8&qI?{BbDF=pe$ReinLCymL}a<5X}mXNFMYNht2&aXSk(Z=|fDA;k%s zTB*%*DcpFSKb9zgQlXfhSj1c=ADo@f{aIL9kGu}5Ek`!}79Td&a->4p-&Nitmv0;E z4iXSl0)@m;PL3yS)-*Jo-X1<{^)J4*jcW_hWNf}Z?B<*O@l*_SbN~RJB|a%>>taUR zm>m(8z^EES&hNO|CKe1axf(rr`J#AW6oU5wu51>1*)@SezE~u2X)pC+sr7i6xHWI& zqETjju+lEZVbCxxuVZ6tiw0cU91E3~w=T}Q@`}71@vZz<=g{$P6D|{QR4W;uwH(u5 znS~S8=uvPOwxG0$1G$|5mMWIrQWJqN<(Qy*+l;p%2xUc!G;QJrENH;f=puI%jcIt?55I`pzGmRf%Hlh5IU-0zWMnft zXX#IWPz6DPE>C#Jgoo$M%J{Viw@@dCyiHU{Vc`_ zXLG>VsFnVw>Z@DGg*d-$_p+;6diB)0UEfK~%muVu*)jM)Wx1jZXPj~iy4n$tRhU@Z zN^2GptI3=MDGi?q4GGZ-2@XzTO&YvNN=m}yL;b*@x(3*Zcx_5M9R95mlc&Qqh8x6@ z>~N}4DbecZ+#x7wTWaXc`LcXJ3|xrs=fhut3&nL7IC63S$u-G{{^ZQ1T2dV>k4MbA z_U{+KnsGYce6Oj+8-(Hw5qGN<_<8x)JoYK)`^+VYy24&=tVqO6$(+vpuhz~cfubWLhWA~*1<{)8~-p-YLw7i8*-{gePg4e?Qbmkd~Q$k zy&>;>jt^1)6Qe9FEvL%#>v{DG`v#8`JYymwX=P_oatHsG-z@9xuKa6-d}dn!{<1x~ zoRGE0Dr(e!@FJ4|km?+Kl6#YX;)`ECJnJ|&VSR;Y5*AK0yF-BvM#aZB*3w+B8McHj z7emMH;9`bTNkP#8dt*@`or*nAQKGY-6PtsRf zO}xe@B&^fdBiCJ?(@pnO4&dg(LZ`@L>wMnu#ok{FHdbAdG)C@OF}gb_99paE(}VNR ze>j4TwJQo;lr`yFw;wb^mWxoNyh$No*IXCVh0yt*LiM!^P0NsA&1bv(R<%Jk+jx#$ASkTWY_8aphmdwhyH)1$Fm!_4L^kc)ggI-|06+yI%GZM zf0avz1`Oc;N|TNooB^`c!1hSm&Uydz_I7ylogn23C_RFoC$HUKdmqcOOg91Fk+Ub= z^X`9^4SrAe&EMLtM`N46w_oRn3qCx~r;RPOHQfDJJ3tkOh@)iJ<>rl9!*@iti_TUU zpZKBpbKlaagu^w0l% zp|aeU-f0%tjl%)>p1raYdFS{4&Y*P6*V-N#af1Y@VR(30mNim2m5b)NBLJS`BdBa# ze!lzm?VBKiu^bXj&?O3njJl^lSy@@_@!0A#ZeU&SdJ#p5B1)&r?^aKe$pNXh9Q?tn zhx1JRcjj~usXNr97|g7@mMMMb&!0Z^=%%FCKDt{s{sSp5`;GmQRYBuP)8Ic!AN!@Z zf0L{RGO%Anys!HUR5I=@`9@10Dpw}TFWr|t0?u%6-+EQWP0iWdfr{e;s5mZs3hi7# zhh5{NXg8*B(FSo5vMMPuZwcz%&nucNbOV*V`*qgzLA%U(KkKAXQE2c1tunnCtG-G^ zG{XK@G}(!`mSpt6YTFIeHS>ECGpJd(HbLxE+r*^sgEbU3yk*93jc@>%GrUkiLR|a5 z`#b2Mm-=^jvI3xE;3#X`g}m#S1aI@AQ_&m?on+npsd0<;1r4a*fA_+;n(zYITn7gl zS@6N`2Zzi;^44ejo_3KaSaRD&u}&Sbv9t4AkmZv%FM*6o~1*zdES$ zy!b3=IZD26L5cS1t!{H^N~_1&dSg*hQMr~CRpd@Z8=jlT)Q{TXTvMENqHmN$A(vPi z7w=JWi%QIUPLO30N7*xzKB zKi0vYxF=4A8WQ}CfeSI!J0YWcQzNyd!7SgJ~yU;}wRnsAJNVJ!8Dz5E#4V21onI zpz@M$_NH*o_FIXf zZShtM4u>1X>ZV)oL7l)Q5mYLO*mPhY3REVt{O(_Y7Kc;vATcdq&y#x1P_cc35~ z1wStT-&Ii8Mtctj?u`&8u$b=XP+IGiK#rvh%{UjMY#e@TrtDv8{N)H@*5&j^n-%12QP!92V zegJ@E!0#+_ynW5=yeeH1?dVg1GH=M#$vQSV5$g3S_#=^X7-M%I+Q#dN9@Vc0jdJ0$ z;sakBV@cM*s`R5=X3G6&@wd`+MA$yt^8C(hptOL94e-lR`o5u}S+_9wWz zXql+RH3!u5p8N0!_B}VAQ{fih9YXc_GI-!h=l;gfR=Q`j9@Q@-fbwtL06u^pr|>k9 zZY30v9EGYVov*BprGK{4>Rq31O3Z~G2*Q-L-HF`j^C9(ArF>z^Sj$9(JfH7Mv$JPx z-}d+SPvGI!fEJ*G`wPEH2a9FSLnUI0)tRhK)&K#HFhtl?K&%oYB)DR$ zj1kD=ru>42gHHqF1K5%VERbB;qJTK~Y&;r^5_;7(Yn$;Ji)@R}p9k%`pV0`}toZAE z+ihlwJt9rVZKA=}n79zK_gxp&;Gg+&aQyqne2JRIlc&z%!Ni4y@d5!+Tl3!GZyJ_& zOnFWqiR(@ma5)7@*6Q$gZl{TfiGRu!IFUW)pzI-pTM~QVb4X;6iHBUl$pK5WUbnKu zLZhlO_{twp-YlH$a-jdO_a-9S2EHz^Bvqnn$X9^M;}9~X~lq;R9ekl8UkJoAN%>!2!T zs- z(9w~)b#v7E>!j$ikwDF)q#hXwskb0Me=y^gg9^y>Ie)JX>V%)Qw6qH76_YEWtyfyK zhMl3|2F1)EHdMFAIT zKcaTGx^2G4vy?BP!x((KO@StLg|e?NqBNU9nk*Q(iOGT+ow$;e)nQl203pO<8dvf? zlA02VXR^k9G~Vkc5bZGM*`mZwPkD&LkiAGvG=A48fAws1>47D%VNG(@y{CJ}c+u{r)9G zulDPo@70&qXmR4c?R$B=_4$Q4G|TK$lxucE;4?`nJoeK~q;J`?_kHq*-#S(A|cDYFy*RMRB=C zq(XxwNkdyIpW>CWh<~*QytVZapM0f=u)hMc&b50qrO+3)7)p`-Z@2m;_$UYrF&i;& z(9P{~aj?yNKNuRaW1*ubf*nGz$wfk z#pcdVE+{QCadP%GpS0O}Jsj010K#NsWDmNLQRD}*bdv6GXae>XTkulYYy#Acf5@w6MuV>c&sUC?cx&XO1@l8BQbxtGoX^dp^Hjbd?VWo!P9M>l@? zU?f^BCN6(nk&}NLumiU#h zz8~o2)J^U~QZKzk^!4<9kPs4nt|8L3Lu6S9+~2p+H8EKY1i@ZR%|n}DM)?@X*9%6| z_+l|Bg;N15Z2$kSF8wxE_#99`oa+0qW6uyG;u zuPrvDHs>J<10AkKlqhyBw6&JhX-mGhd$+y|mIDE;BfMX<9Tq*ZMHMb3B_(s4EGhAs&UB%Yl-kx=6V`I zQd{Wtk)fE$YW59=pt5f>@qhM`e4d8wx{$6>DErhQ>CbF{5L>dTL%0hE_)$B~{_`Ae z82+-HXU#goHu=DaI>=`ll?uWI-{CCeV+^k&jdC}ra&L#G%s;$AVP@f$n1#AHMyvbUi%{qLns}UE3LB>Ec zn>Ajyu<9cbkc&cd0eM6)aaY`fAHLYt-#w6>7ne7mKu}bEb9x#V*|Sb~*ENVy#Hm-Yo}dw8SBOdThD>_ZxA4@k>zP! z#Y0eWCj20D^edlVTAv;XJ21R6Sz!(NQ!jd_;v0s#c-f85FYWO2f*;53pK5B}&1 z>+?<>9@@pZR-5{)vO|>&es7VYh$zT zfZRR=SJ)5Q7h;#=Qr#fC2~AaEcpWd#W!i;sxYABV-beH1O?=z!dL$hSi-MSWZxkgD z4^O?TprK;K@Uz$6V7^3P=xwI3)B01j&vSOBh?n0U9+mHrsBR}M1=OG z0@bW;P-(Y)aF2ci)_biY0u1@WwOt1|fp{#x7S61@dbKTKrVV*qn51_sM)X74miUYe zc<{$%nga|!w}J_Xflj~+;I|LGsM%`5u36+8=xB+`ZO>a+rHORh(Qmk5@6!h!fr}`3 zL?Do&O*gq;N-Q$oB5m|7paHb&mOm|Ht|)SiIXM1e?S}6V1=5Z-`;>r}+D9?l1knI` z&MCkL)g*lD;&-y&DJYrz3&O?+S#lXSf`TZ306Leb9wE<>hM2F^`yyO|YTm&052Pu+gbRTV!&7LLE5T z(9pwgss!fzpQQ^|+98WnaDxy}MZ}uS3(4qNWYo9lQhi4e(6Yb!pB?RxD_h-TE8760 z*);xNI|QZ%g^kS#YQ-8=hu-xLOHEti-@T|{md{Y0*xAfwLQQq8zzBVo)4Q3>E7Sqe zA`A@q-Ndgk0x8PYv-->e7Y+L6S)ONqpB+|@Azj=(Mws`-_R=m+g6V>b-HH&dCW0DPHjA*Z&+gwUbH%Z(Ew@>lT4@e3gm@i<5H2v^fK9?>0%HJ; zJk3v^@|Fboyl0iJ`&z~P1YLJ4Gm*5!?rffu3L1ZYEda#PLokn*ZY<>G9eHCpeU93p z>=iFxat}lXM@Rrp{n8v}fCF-Bv+eE8M(K?Uizhs@;~jiOjoYDxi~+M5x@yt7T?Y)D z;!YyA?kUPnM-WfxU}#)pY7MhN`VME$S=AohWC4V72B&P44;#QwHua$G$)Xycwox+# zJGxGUy?Qc9h5k-s&4{>YG*lo%qLu&>-tW zIkx}Xx^t$wwxUq52M(ty#59^5zZNN3KJ1rD&o!p?KN>47wjXUTv?(X8Q`Nxy;M}*q z|7Ig5?epTzGk=^VWkS8WLx+1GdUj%+Vw;|T62k``Kw3_&-dcjXH61EyFrHt#BiLq+bA+9cDgNo8j9|-brQO>Qh%Y!eI$b&e zvUuhzC(i8-M{DyEzlGy5_Ua<8@FJWHYIJ~0@vnk{zBkqLmV3+B+Yj8?*_-*IzxC^* zFP4pOeqE(YblA;WH~4P#^st1YPTgPC>|Y}Neta+{JT~%O8QowU%zSmdmH!qZ>X!%? zq}H0bH7Jlhn7#9;FjNyF&p4S1hAE*76rhGgzM`IKENAfQbnNSUMNRih%1>`e7?Tu) zz!l^7?(XixLLfH}&y@)X1rxyPAj{wabQCx70WPoM-7O%QueEZIm`3i6!()Gz$#I1J zSFX!r?!u9q#dJuvOF(EH?(2!>yXW6N(IzUQZce4 z+b8Gd#uMC_R-)XnC6EEvF)>1w5L94vcY4<7nI$Ur@D~XDA&r1?D?u&2LBFPrxxbTe z!sae12?xq?E}pG-LiCyb$tdD|+?2yrIqecxsMY+#%eM)~Nb)~_{(PpCvRDEY`%_O? zXc%l`*xt2u*6?Y`aRa(Q*+3OQ=J4p-@dL=~Wx01abMKCB=O(_P{ol0l|BuRF5he>F zjQ>&jN495Y9b!)WSNtjYtmL7dJLRTlEM0=)~A){g`o?&xuK!+VVnJKf_H*M_;-~k`5o5Nvu>O~k397%(Bj@~Zn4Nx*ei0wp=c_p?T3#B$QaxI# zai}mq=D9I#TMQMi9ZI=TYfO_K4^r&+geBaSd+3%EK7xqXO`@W)?$>?Qx{b6kF?j0U z%nN!G;(jr|9rn!~V_6RmtS~yCMYaK`lT&;bMV5Mw8cMkI*RNmUTwk3@V6UJVHa&D2 zucN7&!F6+Gr@tb_p>nI=S9`PgY;fN6m1kOCBlHceSLaXyR!$Hk3zIzXol@fJx&Hk-JvB3y~c0Umi3?8r8`1#5O zi{wBzt}+2x*KZz=^))p$S>kMPJ8Mzk_zL_n7gv|(=U$HcnpmmYl?R2iLS+-5%gdxSil+PK=G-Mfpl%r^{j;1Nyn&3G z5mcHqzAI_1!ewQ(x4(P?V`$Lx>M>EWXHb1xY;s)ddXu4YQ?A6&yo%EI{Pb|P(N95K zeX~peM!zaNy}Zo8s8E6BXu80oDjvj2;?Xnn^>bKX@3r25da;n#-7I5DodQ;vw@Zl*p8`KX{zaMz4uicNU{j_9+>5_LI0A5kfJydQ+_Q2MhD? zC5^GMsL~sCqArMD0xH@TR!#-_AXrf(@Y5;qr?Q>Fir5HuG+!>MJh-_z-6xAeE}#8@o@@C_VVYpiGyK`t zsOfnWHg)WzUMCihUzoa!gqyycRkqw@H{6~+WAQ`r8Rz)jJQWmB>*y_Oy_9{lHp=9Y zZofloCHo|Xeq4OCzvCp^3Kd=cs&%JTZt(r7SFs{QDecXYV!_n<29}r!7!WB-6Z7{Y zhNT@D-drCoq*S`>j4E|B@*q3AxLB*J>L}=$N#H@#vMWyYBGgXxsGW$~Ge2v^NSpa^|n4j9Q@LJMMya z3Qhg>3iWUeY?cjHq}Umu72;$jsnB8N*O z1cnDIn8)3aEHwvrIZdM&tm-jidR%)%M~13 z&)C%@o4vBSe0u#YySxo|D``t@dg-gW-0Ip|!0M{baJpZB!^*$a%UXg$z+eQR6h zSFXlnm9UWtgTZ_x!(ucB!5s1p6B84PlA_{JrjWY>kv7_Iu6M3qx}kv6vv{+N&}>28 z#7?F+$Fh$48vahKfWRb}D&n9ZBS6fR4+3pJC+?GGC|usVA!h9u>{6edjF1gPXnXX> zleUHZDv@_QaLJsixnQuWe~{(Zt5+h(a7+em!paA~Zg(&#`N#Y8EQNb;6F+K+7Zu7} z_N!Bh`PI_c4t{tcM!DEVEDP{8-LrYl<)+${3kh}68aqAun8n+)yM#EFhS8p~-6tmM z_I2tG)KvL&`XMR?>8tp)j9IIX&8mU72%VZ9l=of6@y5Bmr>z8-zWy0XUoHvuTtp~e zc0Tx7r?qc%b$5TKAJXo4$e_Pn3#C$^^4g_IL7yND^6vue2rQjgkX|0gITvXbH-P&g z`lDrOy{`6yL9eHCZjJ~{KQ?$?Fq9iMhotdAC;tPB-rn9q>8ju?zxTaax;Yz6Vy(v{ z<2^JlsRD%&qTzIb1UhPq)-L63pY7v)D{XiHg2 z8yagzh=Ioq#RUw3OPC5&d=egy=Gwf{dPtNDJ??o)Hj(g|^hM3U;(Duk#Kj4Jl^>J5 zuhZhK1ZOrEE-g9|{5wiP7+zowLuwHI6%xhtV3XDq;b9(f7N>-X3ANYFarC%KE^bY99>HV>UX}G8KcjOKRK6MpZ|=2mOSs|IIDwxq=ouVe9!I>lnz$ zxr5?Nz@9@foF?R1lf#BKTdG^V1@my_1Hr&BO?~uJuh4mwukTf zji%4QDenTLvdYLPedvVhi5NECI6U?CS?0B>Fe>>9W=6a=e2ZY`ew4fLc$8UhD{*(` z)VdthjrWztLmg==9p&^%DjoMF5E&~u)cx4`B5O=^>gXzk$m}Y_jYv*b?#AF|PcSxx zuq|T5T-Fp!u*ZsksphnKrbj0bx!5_TvYB2HnJlv`abS}3Q)6Lb_Ews9>x7uzZtt=o z2Z)2+1aRG-el=Ha*c||myvc1j>RMP1N@|;S zPZ;Cpgi~o7vInP()L1N{^iE)$|P_;gww+@6&o(oPh?W-5O z4Vc*L_(?9@Dd4(S{->b6%P^?S^jZ=O&*#03v6y-Y< zkdzaYXjhEFVT;+FuJX!39s}&G6;N@4g8q~lwd!%8yb5<=z%{`Sryf73@_qOc6cl9A z`zL(X3UKR1Y4}hX(Wb;uZGY={d%9LRk()pzJ+vUZU>20s?k`5!y-M}|ePP*$pTF}- z;UH8#ZFlt8DAeCPvb8;KL$y^iL|42$q82Ill77DSX@2sr_k5g{?cByy$ybEq zOS8}Mn&o{|a>q+a$uK7r#!(w8#b&|JAG+DxW%pA!>SNt9@?(Xiu z*t4XP68hlKP<&dN;*lFNSP1_>jgOVeV-->X`oQ--k7s?7sqX9}2-p}GNS0KcEg26I zsqVt|NzfhE3Oma2b}`+ILdJ4s`&W@xsMArPNNhr11N;eQ^ zT>daE6MHQA2JJ`$ADn1H+xl^uQrU26(tQ)9j>U+a|ChZ@H?x)B*+A)lub=tjykQ(HJwFFZT2poo#YmCcu`re7faJY$y5pAnj+y16z9MPzDJ5B92s z6nlvbDjYbj&Dr*kh(vz-eNHG~ABn18AUn{gc>C#u#=_wiJG9P0{C(#~$7z(9IHWcA z{Otv_iv{?sF=UuN;BfcwkmBL(eL%#n=Zd=xF-IS^{j}3O*#3Fs$27Qi01%gUbPUT= zO`pq5>Snp0m50Hvy&wQOwKfFhiAkp5oUfFHKR-VQ0HICieNZX$c(8A|9~Ht_^F8oB zsJd#UUGr!C{TtQ#!&$w^=pf7EEDoiZ=u5j`Af+%RRyzS^~Uu*tAv%@I-L5dyr z<1I?_jYN;j4fV-EYzNl<;;H(72lB%mp(|cadu0FWBSS+A`WTH%Cwf-AD;%d&C(v;inYn^(B3<#i-&Tks0kQd88 zS*xb0i7+(#M+xKuZ@IbSQ&Ny?^)P}Z1HhP5PD2ARpTnYfETsteu4$H)7S9Vxe-L1; z#70J5fEDyBRyOypK>GCn(rJ+rgFairz&`MZ)qx@z7N=ojH?o&1=Ks7Q#->v#z)KfY ziAH1=)d@>z{xShB*ae^7{#yX!YPcP}pey{FZ3x^;f@W%JY9yOmrF)k3&KeiY6o5OU z!JWc#;I`Zqux7-|wD5u@C$h$NR4WPm8x3NRseG_05J%h~L2$b~z8*K0&4^y30qSU% z88Gh7DW{dkitMst#IZiI^H{3B28b9fHK&U(?3n#Y9GX>rOAif=Zq2E4#Uq8}Qu@Ro z_iCKDKbssoL}a8-I!m;QpLK98*kgxp@gl&)(UVgLpe2_C7B8bv;)sut znr0(`bBubk0~;2`KW(kdR52}HW|@Z3%k^j41i(IT&Lnozo1U45(FmX3;b;4th8_;FNXn4;Z*%T__MC5U}a7=Z-3xe%n*<#^$3fGgPn7|mZjVB0yn zE>;Z&ut_M5oQ~Ex?FZ+AHa~6FbMHBMyZbRiW94DorZ2Ll|Ln79_rp_YB8bf#Sc?ba zjLny&Ro;C@jZkJ2)}n$YNfl|{htru|#)M%Tvo=mNHvJ~8rp%ySapA(F;?z%Sa~UiD z)gLA=EPC-~GjpJG^k`wv6~0+MV#TR9R9u5P3*xcFr0M zqPO3J$Thlb>1D3Mr3|W+pY$MC%oa=xFD|xtXJ>^sQz*pDl1=wK_ z)0_8P_*C|e)kF&!L-|~`kRGUHi>WZ}iwSig#X>k8zWCGvN^P9+G5%#67x zDT&M2;qQ0N_6o5e{{06T4qE-_bS?|=?adxs+E9O%^RT$KOPk=|iQ9fVI;#>Z3pM7^ z{)89*kcDvGK+RpNU}tA1EnS9X$4P%NG6WUPA#|m2L5F|smzQFPA-LzbDT!9o%7)|jt{#j>4*W0_j zN89s_G|Bwl{#?sF49?hl4_bmD^hoN?_|n$)&onirXS=hBCOI*(G zMEPSbZtjYCfFW%WV|6uhC)$O*yv&^kO?{~y5NJ{&u%KSZ2aU6eyroh-pJ#M$B%hz! zLdOfk!EkI`d@NuugVexnv7_E;eF+GJCz?I^wc|xm78b{LrwLJwuHBk!IQ)?|D=n=# zd-6+Q1&!>t;29GDdg4ktxTiiOnv1vB(kV|*rjtLiBkq#zDCkDNaQJG5My34x0-fMF zCl!YRqp1xCvcn>jC-LL^XuDAL&r)_YLlhCt6LY%@Gja$y{clGWs!vp!^qAsN_>Yp= z$8GyNVOmRSu*?S&)t)p#s$O&3H_}ilib7&cc;~?|1U((cZrj8uetR72_te67obtE- z-LVim4+ZY#)>el4m}IuPWPU+#NeeZwp|1WgR81dEy#E>_%P1I^&KSznw3bNu6*8rJ zbeCj9!iz=1>&#YQgH!ir)RBT*$rvW_0wrKk0uz-9HCyCs-F#(aWfk?G?(VC|jmU4J zf)j8nxc@7Mi%aw1mcHeKHvV-jGK2xEW|07%(aBb6>#aJlGUzx(wSD7c>`KFsmUe|n zSXuphMfC_Kl{plG57+>>5$P zwcSNyocH9(u^Ah#?l4;G-*p#U5t_YufiIZ9C{POu3e@xq5xSYa;H#j8dQ<4BM)h4< zGi#*%_o>@?VV$HJ2~w9|x>?&5L>Z{QDC&9iEJ{d=pS)3%m(b|NG&E+^+{Ll$hDI3u z_IxG6u#?$*vnr}a{IJ6$G6tn|uwFJiwXUge6_3HRR{WxzZLW(^l*KZzH6y`nkx^0zA3K=)+~tA~bdB0fY#>@dXtI1;dkn zsP7g}8}5+wQm2UZTdv8ore`@<%`(r^{P9_yOe73ajQz4DtH{JLuz)y$m+x?8Mo_?M zlgN?x3V%!lC-S8?&LaEc4^LX5{!YSxprG&G;}6a~ZpPiL|FY)g@3$)L+$()=Re+WF zm5z>JxG|X%a4~Rx{HJ!jGfi5oTkR)9FA1h+E~7RGK&rq!+n@~IyBMf_$HB;Gd8TFP z{d8#KW9iuAtt?eAGNvqVfD>Gb#BEv zbiCEwWe(d9G-Zpx0Db?5Y@w##N2iJSUlgU_caKsuSP0+fvOp3E>~DjBjp#Pxrnp7E zln&4EMv_*cEo$xQ>SeVdK>schOy0HpmHV@BDX7rmjDZ2#|3xe^EC@63CbstNT=B9_U@@-a)Bc9%E|DlDP3S#{f8?@ zhU;}7?VVo#cR736h<2=$u^`7{)KwwuUw!O#KC|J4 zDE%Sj&4aXlZg63sU;o3KaZ&V`Ne0R_t3eJg2%~aWJ z?}~x(=q7f^2iWyeC&9fLgUI5|{n<#A14eD$Ey^JoiPqhc!hv4zOf^-6d{(!1jn{dU zEM%%G8rBwN&}=sMXXkH83Y)0tqn@y^!j{QuZ15lYsCxq(ECI`3FOu~e)%5hjU!$VR z*>l^=;y{p)$ML^hJ;k&uaX!BI1YuGLOEs0fOt+Xb`Q@Midq;Jjmcz}jH+rp(#8VZv zc}yI^ilwzZ0~#7eQF^<@xW!?^;v~;h?zAz|u^?f){aOB$6++TBO2*G-%E|*IdFVLJ zA8^zY}n8!GBJj{GeRMZ?AP4N865bG^wm~fi}FGB8!1>ors7? z4KF}};bqbj(0o&2(1E&r_VU>cso@F@<4A?MvR=bSOeg>Z64bfuP+XqvMS?vADCn=R zy*P1@r7)fWyD0G3dBo*wu*~x&_h-f`t)h`u_}Bp&a{~wtKHsZ~@TJJ0d6;&(21}_& z^jWDiNnh0EVGjGX#d79w8pGK@FJf&F6VUaQZ{ECNR?0pUiDZ_6jP`8iM4E=_dUxffHFwku zbj;6)zZTc&Wyss(@sE}}i9Cy65t@5JM~FUQ3b{~K8?BGo={5UcvUlvTV*co&pAqdm z@=$vofM2OOK?^BkkWpf57nOYqfQ;Lkzpw?0Y9Y`?M0TDY&caCt@wo!kR+fy*AWf{1 zB&6hCG%1XbuWdHS#|%cAhpnF)H9qr^;zpQj;|E{Omk{AkXrqOHzULn_=w25QAl*Ew&(id=mYR^90Y5f2=w8DqWJ1++#@w6B9k7Tb_b~5>kH)kXmFi)d6jipyRbN+rGhYSywn#T zEw&=BxEM8?C|3QO@PRO!#lu|+!mVOl{hn_Q(C?dyzuVxqv)?V%Ym}xBhY9vs34ciP zkkV}vo}IU(lBPSaw{y?P;ap_kpq?Qio31i>dI(H;yWr%Ui2EVKfGrrW8xFnx zD6K|xI$;Ga9e9Gxt+C7?yB%?Ve}5WIiU=AYoY`~#b=CD|4tb!&&}nZ% zab=zb@zD)`uf#3T23s`;yn)TWLa)g#Ysw@aA00I#P&?cxxj(CR(yrG3`r`X%7_IvY zcfG6XrK%OKr~KJEj@!0fc%#*tH)V~wvoz%Nb@E09xYg=84NX(u5dYx1z_cJGoB%VU|4h-r3AN<+SVXSaqHCe+3c{`pLpc<(?S~OL{vJeD{_c1oY zMr@prhDH?>WSK}RL3(NtH_q?f zg%c*el59bPsVBiVnVydl(A!22U26x5Sw{n}>v!hES~X*d3`=`a2j>nBlb~1_Q;bN? z@#Yeh$bw}5!Mu_g-_(npOUIFag|zrVNG~vMPmu12zI=Lk8ST0zLW^pu*2rgHX<=NZ z^AQ@&JU3!U6lDKf$cBvqWxIS2f=o8mP^eby2aqrj>r?$JBU*}UJ@#save+4>#vIv1 ze5|s?sCfl7KVVp_=CnivZ0=iM(Dpn}?L4E#l143=$|s89SO|5PT5y*HDlLqJjkOaS zyZgYVW72*gK1JMf?jcf`kzv8&rxa}nAOnLN9~-~}-r3!K3)G2&=^&kE5hP2Ut{Stk z&Q@7}naV)Pb7w+|&+6>VD!I9u-rX2g-usuyFrrWJDNE+6a_84$=D{$I7A9l_ov7#B zM>dx>gdBm)-CVP{DOtD6VQ!if$h`7wp5I@zeV;407c_EGUS3}EckGXIkr)#aBU;3x z=XOW%mI|8NjVeis#PO)#IgKBb08ySlj+wEKx?-i9|I zP`h_|+fBHj6n3}O(WB54RjSm|U_TSkxuYs3W_ve_d^z8EamD`gW|dR@_3PSVyEciV z?-;)?Pp9qgj&^G2yPq;J9JbT}!Zl*@KC=;YVe}xt2Y4tju(5^pb#%y`uFpS!>d6J> zQ1GTNR~~7f+uE|<*4SBdat_M7i?b4ip0)J(>=T=g;E=&R;+m`MdzV{&IWZwscbS`i zCsj#nv3gGS)sS3nM1{8QyBgE`J|aY;9bzsAnvpvEs*bn7-;-wOc70&UV{OgR%N=W9 znAva)8Tm0O_=P1Da(XPiSZZuS=XE^^ZQpz|57}`+bVb#2GSzrroZlO--W^VBV*n2a zeL#q=Jrk@9HiFjTYh0q>eToZ%!VFWTWu+Rc?agwI4_&k099pvDD?PsmSKG z93hm7WVm)a8&y9yYy;5@A*FdaoEG^&D2z^yY}IIwwUcq1O-;>rOfS>75MtMJf=W5N z*T%_CPHt&d>+31vc8%84udS{(`UnE72_nmvKW%sRR@UixY2ZQtjw^jX4J_w(W$^PN zloyHIs4Y2X)dU0XwaN_D9e4>g_7@0ou$j_8oT#X%+o?@dRd%C<5%~krU%#HqnwTtU z?WfMwKS<)YFY!74E3XJbe?SAxc6f9IvW6ZF6IDZ0W>;{mK&jZ|4Hl_laI{~xq&W2M;G~D~37L&U2u) zjpqlT>A#5-$(XD;!f|(#!g%*^6m!akRZi7yX74jTT$O_mKESHRWRTnTMuvy7mtBU&7v}b2q{I4x0ZPAJ@2NZv)BN_N?WK1V6 zzS!RE=1Y9RncS~Jzl_1A_H-}|dnow0!{vC=aPEcE0-oz zlyZjthY!8^uGLzJ93EXY%6`k)8x%Nx6e?GnUHe1q#My`y(=YmuJg5p zlU;byd)A7+2Yr~U&BagXRtA__(E*x>j7uN^A))LuB0aS7gOXrKhj_FI2!_D~Uc|ru z3BH5`62^aCy8j2(e_sNxJ50Y~jB+FJt`Dm~9{zJ+;LO9oz<^rRWt$9e6N;@qHx%rV9bf=nR5XC# zCU_9K;n0^u#n@#P1L;-c8^xw0EtWMl7jA6iC zQ6hfeF%O=LgZVp;KWetziU0N&JMJSriu4<6fYs9Zy_LQj(2iLA{@T7}P-@T|3hbo| zDu3S5wBe4ZqJ3n2h=f`+@it`dc~dTrkK3OIX=VkZ{5V;|xvGzOct!*<>Z{OcY{SOp zOT-aiHcJA5HnpgLW*6E3h7iiwc{1QX`U^~ay*WTM^H9fbs!DM*=Orajy*w03`TSB< zb-rkLBS%(7<~&w59N!O26YcdWU%!St5_WN$ISsm0LP%w#gPrQ<@84N^CJctXtrZpA zwVr3Y?2rU~G_8ODnYp=nUS6Jrwl>*)%Ha;c7sa`_${7)?sR1Wj<9LA24*A>?ePR#X zNX~zB>Ky1SdkgLrJV!^T!PkOC+U4Ifr2pum-qQ2%5HYHJLnu7)o3sNhjj$R>z5}^n zlZ=8|Tg1H{0Ln#$R>W`5mp}i_lsEJS)YUY|zy!weJbfxVtSty9(Q+Aya(%D8gIap|R62JUtXBc{sNcU|Xeo!3Ryz;Z=soM% zoo!^MTgh3zUFe~KYqSC%%+Ei6x>tI?Bxl{Y?9M2H&=hIr?4P~8uhv&q&a=|L0kQ;$ zD$I~LP0GK5uo6koY_M&lUN!ATb-kNs!Bzq$i6ZXY zgoK0`5Qx9w@8tz?%qp8@{}gm|5_wozmGw0>8BRt`T!TTtQw;cR0@Cn?K<|A50=T?l z3Wqm}2nYz4UMBOkFXHBb`||?aOuiHq{%7>`CTBZdEmRwgr{;lDl7deo7-BDn_%lFevvaJp3etiI5?ISE zdYQsohVgN6+3&;Gdr`;Gx|QbU5Mc2#S ze2yy$Y`Rq#%JFR0X)!U}C*?iV(m=rufsC);c9RvWB-!fL2O2n5;KG`kAW)~i^1Y)F zM}EqJ1snmJAQU)HgQesq8~lrnitmGkF~7&~-RHR|*NfDMptbTFO#G%%r8Y3&%v-4< zIL=o4>_skrtJqzdd3~uOK7;XTyai#OizJ z#^msk8ixrqx64G(vLQV8N87au75T=g4pu!@R$Yk>i)1Lz+Nw!Sbj zFpPcrRKM49wdsa-UUxIgG&`byx0D*T^%21cW@J-EAe?~iqX9r%D#&H~(|{+HfggZB zVaEr!7cXFS24SuSh0p3^;9!})UF~uXZKHWA@hkyQypoh#xK^PbhD^$h_7~cLu#}A3 z4CC0N*~vye^RE%`%9J@i{pnqKU2fJJ^8ozskb=h!d%YYiGb11xx?5GAc!|>wT-OAY zlwtq=S>XUrEpRZ(bVtL%6b=CVG_tr1C>3d672NzIhdC7J71Z*EC2kxxa)<6>CwBhW zA4-}(tDMwoQ8sJJ)YVX?p z(f@+DV1`$h6sF!E#_m8ROL1PyR?jbDZicAjBB|Ly8ptb8VSA8)Mn)#DIm+%)#Tm)NL88!ga7|m^=GCIK&CFID zfFrhWG!zKIq-gQm?D#qW?_{pC?rB%94H)P;*D2etZqm>00gW6L7k@NdM-Pd*<4N$%4{#NOpx~#O?M~O?0d9C3? zfyUi>Hx>$%I>13hK1vQF!jk349`gKj*~(pKgGf|1Y_P^!;GjfyU}QmhZt*)kjD)?R zm-rvvh4|%*;XlJ0Czr{7*8+uxz@vIE!;HJuFNSONfkkRf5g|9cVgMP6FoJ^017Tp| z;&$1VHlsx=tcaw3`-TIBgoLz#{F!q2-EA|N=dYzphO3+P*Y9TO`1op6vb%%E2$K6P ztg3ZK#>VK`*l@sy08m;$1m z;j+;@AJcs&pwjy+(R&UV1ke-H(a`~21<1a^z{L$z$?e!2Eo|p(=^_O&ixs9yO1~}u zGGq++fO}Uwls*f1;*!f@l?Q>anXg?DZ(3qn3mJ_-rgR1P2nvw?^WCpsN)dQBlSOJw z7LfLqB&LGH#SFOwd?FzWZ9(c9cab9z(*baB6*(9f$Ky(_kD?OTbcU=B*E!t=CAKFE zyBnJ6RI+LJ^wQ*JP3`R1LPJBNQc@zohh*HJ#OtH2ukp(pV5hc(hwDXmV4v2xG0l`? z)eblPpB5k@#@y0Uc)%J9l!&|wkF<|MvwLL&*p(pKstsHn60|j53SxklRVo2of&~V< z7WO@aZB?uAYPfyk8gSzHgMmgUUHBWw5Y#;D8&A!Ajh53dQ8_-;fW-CHV3Ac&zyP`xqzF0x!9leq5Ir;jR2Qz0!|0c%1M-;K6=sUBqr@Qv!9#S!{e1#$V_y|_ed$GIkjEPkBPQwt`%<}e%9Y{&rg0JhTpp!G+9JqsKD`nXH zFIOCPHnvW1i;O^q2MrDQ;|LHj_98`y80eydBxo0kA;1}bT=^+3E>2_LbbtnZOa)!Q zDkzIF-dCr*HaM#yND*{*6BF9MPAWm+0MMpHd{R=u?qnq+NMUux#5taR2(0UCu&M!?Z1LB*MGo*ow5u9 zlMfZ=Kzo&fCE?=22N1rkBCP$@+wmfuOf&@OK|4ARENbV6nyX zzI-DuFAvVOP#5z>oWvrmp)uiDgg-vE3=^@(8=`V>~$@k zQoaws7{kCGdYdz916r%V=io?_d&PZdD3+R%VBu_Tugm+}*4v8K%MUQG-uV;3d23~N z!KVw^2?qD_oBKxtOp16QvYxjL99Kz16A@$><9H5QhKL;6 zJK+z5Uxi&uw!s2>$uew=o1d)CAn!Ia2K(8~e96r_SppXR?^I0ZqK%c#m!HxKNXZ zbuDP3ma&Ba&J1k$&p?a_L}}>X#(Ta8hCR?wICnp^UsePC3Ofr+%&6-Dzhf^A0&VtY z42ZInp|8e~X-l_W>M*^BcOoYvum22yVbs8|vaU{GsMg-_66BMLHi7(?J;4fnU|REv zxLkMG74>eH;aq==B|@Uce}ibb>JxsNgHQDPVUSaCy9u2_7ibFTXzGe6GDV(4W0KG29G_PZ2DM9H=Is**%M&vjy$QpKh5;esdf| zqu6%u^s;oCIJo2C7NB+VsLje+5d>E!{;`->!=PiMStUjWvSi^3yw`<@tFLc2s@9W---1n<+jeKfW9;1>4=;E!uRc70B; z(H~IJf@^AhidEd2h`z}vmaT2v;pmy$16e3;)!)$`P?3>^ApaK)S+GZA z7)1FWNTLQHlm82nAYlK+P1@4%H6gona@anKaXRLIe{AXr!H-n9LC#<6<7cz7&Ym&r z?{3OV50fr0{{xon9{TuXPwe@c4>syM6s|ta03@w0#Y`VP)&Z7w%e<6Ml7Lv#*!i8_z2m{gUX8C&`n9 z75i+MXxxoH_3iWkhivwAt-V%mtI7QB`*{VhbNY`vO(uA%{lfn)=6v`BsHPe|ZunXB zCqL#grrKL?0MLLC$9oqS5bTKsxJsWh$`ZBLa&mIZm-;bd2fi>`3C*m#3X=rnzp4}B zq{V0t2JEk;Q@omYPt0qVPI#p-Mz>BXKn!y}$eW6KV)Mx*MK@E^UZ$))lmI)mGw;*u z@{=$eyU9v<(f2a~laB@iRj2K0PC*sgMj#<~0-935apfl~umL>;#62BjfE9E0Tn?;2 zpT9_x^~kn;Kvd`tMF1RkXIjX99G#N?QQYlN=KR+)s>5eOL}+{q*5}FfpS=3#_mru< z414Em-Y4_4ILq^X3Y9Z{i8|%_ub`%k@7uK*?yrWbc-#~>aSqvqGF?ee=k*$ta~IMu zZ}C@ID##wr=xZF-R3DsBl_-)^ey4E%)o`Tr9~sdI?Lt{84jRaag@s|}T&I5QDXMOf zyd9Ce%`Ai8`P{c9TdsT5Wnrfq&rx)A5oZ~%$b%5dOM~*nu36Algb+C2CTX1H zL^=?bt1bTz=2T*?>`g!Rtz&4ze`(Z&5}T6Ak5$THb&6LnzeJ`s-GYZLSk zFLe~JS4&jP2BP8#U8fzOox)wWH{6~VZaJy!8)9#5S=4Z2I5uSS+)sQELG8eAKgR}6 zcS=q&CTrS%_HA_Fe55@j~!+M`xaO7!!ITy(y6+dQckn64?lf7oh=A4*_hVJ!)RRIX?L zmA9&-ihKeI`<*>KwT9I;qtmZ*UbqjTqe_&)2gVJ>xCaMM9jc*W((#2kNt&fZ_t$|m zY(@WS_Wi4eGtpmaefQ=0SrV`-l#`pC{mS(!xq(&>s%=AFxQrUx(SG~)ret?9v^Ldj zJ>0E3!A9lD^XFe2trhFo6J;fQ?H`jaW;pd5DYTC@OOI zcwd?qJFN^5h(kzxxLYn3?91&mILSnwITWdY=!J@SO0Wb^#L|9i>1; zvtg*j%W}WZHV!V2t68jV)IE9knGt&q|L{5OCL)&YTfLW$ zjt0yNpWhC@?k-CaF<_Lx1)V7xXd+g=s3vWr0<=%%u(Xhf$x1G0-SukjB611d$OO&+`y#AQ55H-lw`Ke9VpT(&z^^a7~Pzi$lwSOZJ?L>QBfCYYXfQX zS^gEZ8k5h=l$o*@Q%Gf}u+K__vLtp*!w(9ZrhvQW?Gxs5$)F=!=>}wODQZJR`0%?q~sCpVHK^ zCRsD16EksC17WRR&O~I3Ud3*{kG=hk*&)BFsW&0v8g#6z*ezKHR1_mpvpHjEy-T@9 zjU|C6L(Ujo^a1!tQlFp<7#+PV;lBb_2lqWm=ZUNgDcy{`9l(OKS z^SSm%S!{g(d$%+ zBWk47DE$Vl6WS^OI$!~!4>{&V>P1*;FVvUb)L)Q0d#x0nuQcjdb$>*IL{98famXkl zs?*ktR`2FCSmiI*g`S|OiNJpg{+k6V*@;^FG%e8YkPpk)7;zv>^XjH>M1_#k;0DOm z6hM3%^0_7qy!QK+`}9u#X1X*bgz<15q;YA-JI5Rc;Zjn(q%D~~>7{|1qQxOIrnmr@ zI?M_Xt(4p6MSba|Ah(kMR&;H*`jU%-^?7W`EirSp#trbn3b}d#$XmPI1eKecds8#| zaa6;X1Y=cW*34KNkWbl*Rywe`B-?v^?LJi>RlM{n2aJywpCF)8Mr&Y25V7`}{+O{W~qv}51Ujtq#c@h&5dF@Zx zmY&=IBU-0LB{?88`;+;D4NBz!WAQyRv%Uc}wdhVw3PYJWqNvVoA(y|E?bEf10lL+R zNk|}$keq_UY6E#F{4JM}f}NEmM`{3wulmIdEAcMR7(klwa9A-k6f|nWrPpiT6MFxr zlU&SD!oq@~`pcaV%0gQ6_M0~uQ}4blZm`SSk5c9HDh`ssr9(G7z5DvIM5X{sd^U=i}u4170A;{ z8+X-NgS{JG<7d3kN|;vW#3M6egqPr_-)M6d^!XEzJ5FZ)?)}0Dj@L5=d;eD@#*!A%g$IoOiaI3C9c@gmeA2ltbcMnf|2lp)=@XpcDv5sa2)$b zvtbbpP6}@Ok{}M~N(8kGm}m0=*HfrjTreDbba*(Dnv(%yMx}m6-Ot+qFtP%&@4z}$ zu?rcnT9?^|^#E-FoLIyvps`;MA$Tn0`RWOoltMygeey4ry>D=z+rEvRTDD!pymDY( z5dq?e~3$>0$S}dP)Z1sM(?wkNImC<0F;5BB|zMEhx4?oQMVg zLcL&rJF?Gdg-2+2jR5oz=K9dOY4N<-4f6SA;;C~@aFYfKLGuG_>p&2g*X-2{#Zd6l z&tKA%G)Dz(O&NVGqYCcVM1h!YvuEFJl~KBS6{U)*=m4UsQ?@B|(VOwH*r5R5uA985 z3*nul8Q}Jh@8Ng%3+*bqdh~wX6Xa|noQ{1g85U-w(9q8x9%3T0&~!yPKjwL>8q@7> z(>*dw- z+lr@vQf-^f-QE2LzzToAzpZ^g(c;~hQBk1|+Q6N;2R+w4U?efcplgp+&!prE4-?7x zH^RX>cdn&W882F~?=<%Cd_5kP zy^gqNtNwvHr!Iy`M2kY)wZA$E7|6jAyvEjhVx&2N zx>u8c;=hS6E`KX&$K^L+(!^yD0?@kWhKb34%B@mT7iYwBYZsR$)xQZjP-*?qnmPU4 zxcj^jru#;Yz+@YFgN=?_ht2Ue+y2`F*bh$$kAHJiB3y=_Lz+Zs0~W53PvzSZK*2cP z)KM*m#4b<-oVs^0-Hu*ver$cM1W3+BZxol~SIPZo07bcf@PW;#3&1h}p0NgqByd3*0a^wR^S28=si?si{tlq&@n2{{HyU5(P624GqU~ z2q6Rx@Gvu&djC7`RiUkJrk0t;FHF#+ys7 z`%Eq`K+-A%w_TE9=4_CN1X0scviY)pWjAu*qXblo7oHmoE+u&&MVJ&+GF0ej+ST&-|Y2Cp5(oMkj_DNfXEKChU0@HuQ8bwv*q3PJj*uS}EcI^=8 z+@-n@-XI7jKp$NHUEt=h-?Dxm#U%4dQ1n?i>;!qA!5tc)+wIFRp zhq7^`L}Rjby*n_C6FhwQdVLR^PWa=keRH64!nvpUO#gTzJ$t_^Hrw;(uWP(69BTvm z$1hz!h|Uw`w!N!lYb83hkZPlNfnU7^>k{6h7385>OwwCF(799Srlh$>5A18{-n!{A zQj+1{o@*ipu*m!Q*5F~Hf77LD;n+4SMBL*WnKD2S0B`p{YfyW0Z0=_6EdB*#(<+t-p#G9w%c^8w-N}$$f;jmDb!r% z(h0ybu-2qyqBbVq+9LPn$dnO4p(tfyj$3k|h2AN?SE*pEDT*j}D=ShT~b{W5Qe(qYWRH>6s4la;;Nh#3{N>}FH& zUoi=^z{N@M+fcnWayl2LJz?}?&$6K0MmkRQY)k1Fl>687*b4>BzR7r zLw}h#S_!@}T5xpyuId@SQC&VXzmh1@U^&~5PCk8U@u-Ux%qBBgotK&D-nwyrN8A?j zPm|cOLXiuWA;hBhPU68WuRYfT>b)>LK9yj{t=BfIGCnA`onC_UkKdF8u~q2`GW9#w zu`pLu#JKe)UH{B9JNu(gRMvQF&h58F`XhZ@(Wr>f^oGK(-ibN1uYik9?7?uZ%Cb4} zv>o5NSF4hFtEScu4pvrhkXquvt~cP!$%E=YX*}nS?TmaPL7`*~B&wv5kiAx2p>3R1HF9&0FC`~`urzv^J_)OVl*r&h4zY&2=s6)PW{W~~$ zpaL9nvBB_^_GJbnF#_#t=q5RBq*qf4HQ`$+?zGLSv{o(5~HnA_pHbXCvWB*Ei+1 zkMq6radtDfx?XVzmSPnP%;-E;auO{YTPO^bPe~HGHhAr;E=|motw%^njr>q{lgID( z3IF9vZ>2=(t|mshJ<&y@iwj)e0BlGVMMb$I5=d3L#r0WPGIcyizkkeTa+c0Z<`Q>n zc>ik>5C{pbgV%Fs6y*6ZI+QOAFMq73Y56`6-MM=$PiZ+y9wqXk-Q<`ok zsAUL~l*O-2$l~qv*7Q=>h|Tt&txs!@JP#Y>KA&?KG+{t>j;o==&mB%S->kQ7;>9XG zT_i*rP3!1aW5G=Gf=bS>j|R3nVQhviGnRm1G(N`$>3FPN>wk+q@yawGhK!;aACXvz zxnU&XHlP>HVI{Yt*i<9&kzi~2Ao7QEL3&qRoTWZZ`q#Y~JIL zahU{6*DOii(gu`4F2~!GPJ^I_wQB*&h<8#_KcvBfT?)4RLvZvC^F3p5lCdKT3H9Jo zjtRZfr1+yRlI!iIIrUSzaXibgWb6SAw~+6*SEoirPTp(K;zfRRsb3;}+j1S$czQ^oMXs z$G?g>Cs|yMSZC>-m5*rZ7c;=x)F^S(-vvey{Ag1!Th93%6h&A%o){G+vD>iq%%gBl zys5=0*4*~&B)GPcQop!jp>`ihCC)^wlZxdl$@+}BUF1+1J7$IV7laucP!Qakyc zbT9%8$xfJ8YB>&j_X9~_+_@VZY5wMX-+58<*?qMG2Hs2bd-0a*vk6obN=r=GvYq2F*k|Lj*683==WO-~q{ zo8B9f@Zv(W_wQ%i`FWzaUmP#*+AW2wsAZPZB2#8CQ@@ILC+2>m?9t5KleAjL0k^%E zF>#SSb(D$;%{UQTJ+s{aomPW>JV3TRmpJp;jq1vvK(d!X+-q2pRQzKSiGJ_*MIvym zc;~&jM?0yWDm5nK&z%2G&(kT65H5aR5|#5Ob|P)UkyLn6Q~GLYToYxPBD!|oqVmT$ zS^A|CM8i6-EF2BUA;ZkroU_f*t-ixU$7Vn|j@o3izpeS`p#cK@!8x|WVJnhzd7$c* zY5FZbMr-t(7{G&5Fa8@8)w1NbNq?#H&M`q+}!cBO|9x?8M>Kanr z8ztZQ&abrNw30sZvR{N^AxG@BzwaFDukThIFYb7|PIwn@VsZr5HGjMxMgB~5b@KTs zuM%H}%TR!l5O0^c?t61e9^=2n5gbk@2Cbc;HE9WU$VCIGOg5`hmzCUk%&A%Z|!69(OH8m=1j1@ZH&7&M3* zL;)ihNbcpr`|G~M66}!TL&^_xSZD_&Ok{0o$iBhk|NWUCzQl9t6?=qeNMrsvLe^+< z-mv5`>VGJ-{c&jp1P2Vm?f)m&Bp|r!$cGIeC+pe6P;u?@-2LeO*WVwX>LV)s2UP8` z7Pc3(Ms4`MH}D_?aE@W@*cusk#lNFhQzGcC3WyvhMM)>#MiLn<<2b8m(l`(aCn9It~fYrl`RAVy-LV04IU@)6XV038>LI(TYr4C0ApI~2jS$pND?8Q z%gl$^0WK8lNGI(#M3BsgpYh`!qO{u`#@9M;-i7z8Vb|+XKS<|J55BFBzUhZ&i#E8v zHf+?K&I?e5(<^`wb^RlVXEPOibEASz1?~$^G&-UqskCLG_@xM!Q~Y>Bb^a>v(?e_- zg%@Ru5PnJNu^v*O4Z*IV3z`|z*zIHZTSE%ax zF$AlpYw3&rk11#A!UufU`!{C*sUoiR^lnnhZV(4LFv{AL*w|x)-m`fUH{Pb@TEjOZ zx}JJ`JMFtR@$B;E=$V%*&Y)jd%Y(QqBYdwsz@$Q*!gVD5Q=P$n5hSzSZ6%7U#C z#L@#mo6>7e&yQx@&Q}i?DM1(ZXMJ0joC}eInt&VS-#7!g#-bzIX{PaZX)KWfAt_%B zpvVM{b$;^L|;K~M=uKU@%cfr?nS7)WjA1>HQ* zGMrtn8ic03;Zev7jN;0y84FVK=G=Y6+m(Ad|Me!WO16yT?yC@)expd<`@i%!B!$Gl zyDdK*gUuxJHozaf>f?Dx@U=$?n5Rd~9a@Ib_k9`vU5IiuNf!`jb zfx}VZ%^uj?#?gnX5=)uzz3roumedBC#!V=9I^+dYNst-!g z@aii@_x0BC-^Ju(&%Q}&JUPns_JM2F#WV|Nw-ur^^}_SEsGkSLclc1asfcPJj+^<8ZZa6l}cC$GAXn6->Qk z{|+33xa0g3&Tkc$nrd+H1Dj*JW%e}@ZuA{c_lyA1YEvmYgOK{8(Hg8`-JtKL8o~hq zLFsjMM0}KCc@O$OT%YL`iM?TZ>EjjO(+;#VH^-wdN_cnSrMIrSLPs>$#Bst@>TL#Ip&ek={d{+|f(p>z?2>23TG&IQ zPiKjSvF%%L_`tdEuQQzv`c@sKFz)3($6rm;q;+*EoY(2Jn?0&ySs$#Ze0sw~RF$Do zQgTAY1e_*ABM}EuBMJP+s}$GA29-jcG;L|am!Fy9jdT|EN^SC+)hPbn zV~7fyQa?#WVLTfwkQ480&Z_3W?D8%wE#>rg2FP3psvz|mgk1qOtB6}Eyl+mCta5Uu zJwj^9b_N$0JF1`JqP?;p8r1P*elPt)iP3i4VFo*02Y1`{AL#TA|9L+Fy&u=#yfgnA zTxMK|<+VI<63Bys+}b{U`vx*Chy+pOBvasIrxn8zT2YsD*CBqVfs?KtT4_#c@s0os ziLHT^Pja{#O2*%fRXLnC!6BClyrvd9$!XKt4|uru%tUpX+YLOYmqAWRuOmf_XQHGv zy}$k7#ze`J@b#md@mXA_+bBtJJG(gj=DzyQ+`18Pa~y^?zDK5I3ASEU=9FlUVcd=JNKJK6S?l z3;L;Rcg|}W6r;J8bm9)lxqPRuaX&~nnlL#ko>}@(A-uDn_I`?Ng^|;9*ZTf=hZ7Ra40~hK?;=jqF--1p zewKOXUetVGp@O_+qNz+STr9S^;1V(+#nZ>EP1%ZsToL%pm82g&sQj$YrzLkLgY6mT zegN68TLk3AION64?>`h?_lo8B-M&8XQ+}Y%kR~uFM6o&Hk!8{8Y_i2U=FI!w_Oxlp zj`2Ant+tjC1k1JdI(~kB^}m17&;3I-0;kibWZ}8Eykn7kp+rVbS75HLE98bt<>ab= z%`Q&+(oS4A70^Yr%_pMH#b;}0U!?cLX38ky!K3SB{qyF|!c)@1R- zTx9i}9Q)pdb{pWe%-@p?={pCd*<83UI}}3~$p>?^d@G*5yrzw6Xg`W$Xkb9o3g)Lq zuibz=BPuOD9(&3b-~AnwauyY@1cf8+9YByHCx^>xlBY znUt2FGdxhJpJ@t`9y@8{mTYWnwfOhJ6f!Kl!+P`PSXBdLl^?+*feu_q6^ou=_Ob!9 z6#yP{t@U-0pdFKvZfu{7B1s)j>% zItxsm7}q^;UR-niyEVx~CB>wqh^PIFCcV(Ce_25Gcez94+qYymxVZDXv9@FiIHmzt z1r|m*a}fz%xC*z2r8KTlqXk6~Lhf4=iM2!mgT(Zx0++5B9#{TR(A{41ls#U_P*G7~ z^`XeBEIv*Cy8Y~H6iDdERkH`X`d|`6p_r8E9~~Vn22XrvPmlKhG~#bY6+#bQ0X|q| z8_ZTxD{~?(3<@*|ChHS<(|j?en>gEh#0Ajsu!m2se5h_lG~QyGd7aHi-1|@MT^QDn zlu9_T^`yDOPU~&--xPNNeu|(UC3+=v-Ts?1XRpO>3D%3*e8xS^2(7<$A+3G6+?5!NZV^C_~#APDNj+8MyzulUD(G#7~T@F-2 z)6fXA-y(Tl0y3Mgf<~22gJ%yw$~R*65qioRCMNZX9G-{|V0H(T`KC-3h{oZTjaIwz zK?}Bh;!Q6^Nne9x9qr}i<=iT>Vh}$zEIB>Ja4epWo$T&>$vHhcnAk9WcAw||SY`ku zud&);;Zhc{f9vEjwX&wC)itA3US9t3m0JMK!SOBP^(CrjRQ!54M1)*5}_t)xHL){2p~jp?JAnV1U%-(=8bC;6-%D3oa88 zi}6HhsuHp(<-d7xqW)LPqPN#Am;ieFo>k`z!IW;ES5fuA z^7}tNSHx)y&u2rh=@khG*i_Uua#hvThN^i8_D8Vl+b>;<`j~@#P0;>v79OeX+G`2{ zPaoC=#Kg^=Y{bMHYPk?V^NOvX5Vy#4zNq)&6j~V>M}B;~^%%iPPE3c>X@yqeyxkr5 zB2>xMNm8#U@7%%L@|RfWe9gQMh9;EihR5mRRlkSaVDqi9`cAIx5{Klvc5ONLm+gg$ zwZJkdvv6eHT$ElI*k6c7s9Zw9$N2R2)aWtdv91m3wb zXVHI^GXC*=2+Ko7U52o`EVP~-$7;)cTG(hj)(?d`H3UiftiHi)5A4%Z;tA39CUcQ{ zL$*Xj6>3xg5S5K*f_|FnOC3n|BQa~(X@eB&?`GmkWUbMbhbd=A{HZK>J70r?E;nH? z>JdvWi>S?8TQCCtZttyW`^SJAFWtyv+ADf4?x!zKaKud$;p-5}0jl5}FF1ND2O z2sEW0!|;B<$pHgK%nkqzT8#pv%^d;Tj>#8zMlMoIGevr|X$Ux@0ot4j`Q%rTAlR$_ZXY<2a+UsB~z|G!pZeUS!J{c#! zvanc(kd?k~t2Wx!n-P9IhzghHyJ>Bx3Fj3Wx&=)hX6A>DWC8y7+!#;Pk-?Idm|wq$ zf0tAHvuQHkW^%-)Y136KXe{;9y%C2U%YkXGD^bJ!R2u0(xZ zJOQjLCOYS?6dN0I&ya8TO|5=XG@J*DJDb1lzA8kU$6cR;f2E=$^<2cTGj8scDK*kK zRsPjtP|&5s+rvGWdwWaDH9X`^Y@(*0H%OmJRHXPd$P^AMvu?BL zQVC6=^s*L`z)cpDXgob#*h`9){D$?jn1Y(9f+mV#LGy~0CWFPN#r5MX zI$W7+AEBZ3dvA(>-|L^L(7pLT>VCr2T$0xhic%{q`ln4kZP$6P$DkJ$tlp=l78;d5 z|JXh$O-8)9=61)oIMsT3{)fJ8$$2BQfr&oJpcu!(E^Vv(7R6gl=d31u5^0qR{cj`% zR7mC2sa@~A*a`Ov^NrSy(~=3_BjzAR^!R;3n}}0iF9e20e)h-OHDX*`<(HRU%bv8o zy?^!Xy*3rPhYCF5UumT`NU-8uhaURX_h&^TDZYGeV%-YXF;D;S$40b7oXLd;Dc&Jb zaf-RAEKe)q?@hHe?A<+7r#z5hQkz0ol7Sr?^7kuEq1>a&B7L0(^b*_tcWs6B7WbMz zPFXz2TbF0x3bNU7$fFTRES%FQ1@6E6|NS)q(SJTfK*lPsfxx-=3I06*#L55taHaH5 zGpa^lA7S^-{M9j(9^JL>O9a(3t!uC+BJbr87R)Eg^;OP-mo`^7aYK;0 zSg-19xr!A$=43#e^hJjzFSG&@xA z^;q8sRl!muV02^nOfGCC^0B-sA!O1)7YnV&?+}+)onuE3>9EO;8Qzpef~BLL>}_o_ zUrO@_++3s9{nQC8L}N4$wzI_C+a+nvY_1vj3DFoh^bvu+MC0Ila#r*0u_ygcPDIWi z+J$t#O%Q>=6YxHXD^JwP&4l3tz!fgPf%B=lk`fL8#O$jWUz3S!0Fv!iCP~PjznOM| zk5ns&+%zauv)V+~z&mjT2I2W&r#2*}6-twokvZLyUxczD^1`W<0srpZeeH3pF6K_n(xZfileqY}nLyoNYh~LO`Z1Ac?z4RTkQ&xI6-qMCkne)r-fnyYr*75ZIlTisW^?!mWh>&foPw&*2A(Jc z%YE0GA2h`-ZCVBXL!++h`Ne-vQ#G?G(WPo!-BKMDEwfH%es?%$?Uk|R6LoqulXZN> z_}$jAS$_x!+|R=*ClCREvh!0I5{|Malp)NzH^$Sk(d<+VJDv0 zMihkQRcEr=L*WD#?k!B~)Ob0niYu?+kTW>5r;k1G$Cns~`bn-Y7YjquF{O_){Wo2BjP(?y4rVnHUgP&y9CshzSa{CVvq{Ivo_uj?EQb}xvdCnpj z5tVPe9nV}j4yRZoriN_A?4Q>&{@;fU#-@=ZZ}lUT&Mn$F@%3|+#%eD*8sG_RiMOX|t%6c)n z7K7nM>f~yVWh{HDPj4-=SuoOXrn~WGE6v46z~ic+)Xplx&WJEV)ftae`(8_(LSH`nCjf-M&p1h@4X$E&RhnB|xn)vCSfY~l z7i*_9opy1gcW#eL@aW0@0h0**ANyps_a1@^)9?oCN`lYHsER!1-@KO5e)fQ-lz=E@ zq3k{ntBa4AH_V+;ue0rQL9e9*U?lpJKv=lw6lFh4*w}Q zo0v>lLvIO2>K~VXeB{63-a@y)p)RK7kJ;f~}us9rUo?qaK^^!%wwDCg72hNCedKr(RLciN3B_+35#2p5P217_g=f}&-A9`Duyz+EE zaGy?d-=3NTga`8)cnt&)AZTp3r@46J;%4Krp`&Ed-dte_~cv@XSUM7@2c z(f3h+?4NPO`g;UWt7BW*Z{@5`vEhjjVuR{<^S2nI^b1-Y=}U2$fYWUn4dJp?qpq1g z*Wlv0Jwh^qxYFc1DR7%hV1Inq{o46Dzl`s7ScKpWRLd~&|I*n_k?Oa9IYo^w)c=O* z^P!x5yzIwB?^FUqLkR#kq>wdulPVkWy+J)!GB8ZpBFuDw6oE3`XF2u#g)&-bs4F1pi%MRRq2pV0 zolZ6JxqlR|Olp&|a;U5FK`4+NhgivmMuPHTUAczVkQ=U`m}2g)--sDVNf*O<>oU$= zXjt(Emu#*+zeEQP1OiV*>0>dB%jQR*{cOG4HHBFGs_dvSikyB6{hH`x3F!9KXkN*-1j_VGX#Rp&{OVpxTpc*_IV-k^<*QJ@#9W3yKIuB@ix_SV{)Y}5#)=bBxvpI# zX=`q+ZkB0oBOyb0vq4~AtpD9*263?M-_F+wfz+}_IxMt7{++XBuS;DK@R>td8wkJ7 zg#AB#3GfbCfn=8v8{-vGz?+Gwho~E*eGj964;RR%ya2xOeLL>6YGak8&R@<^UXsXpD zt_dPy{@5Gd2dgIn5fl_OdNwJs%Xf7|@1jw8{d$ks6r7;SKi!<)+`LKgXS}N0W-{}# z#?uAg?I%>RMPnQLE@e#OiA?c=CT}H{KYDqQ;y5;M2H_QOhqndzP1e{cQj!<(2ff1e z8?9hD_t|tUqLg&`$Nz@;hzjcGAQdGi$9NCQGmDUbZEXPgz zet*$hWFa?33uOKMCdWD0)q)?o?7sV)faWvNK_1#ROi)l(5`B)~(yJ*W5Pp;_?8!a* z%P*-0UlzEu6*>d=uy!W32WFiPGlecfdw>IB zo7d2ZoWPftv29)e6v-#*AZx|}`~TGf1O;7yZqT3DzZ4abA;6e|kdYK2ykahrcWk9K z7D0C-4%{MM{tfe+YfBYmQ(A9|9Qw@X4N-TdP4b<$TSq_!q>#`>Uf4eZI0YoM4}>G` zxM-y2%O6+Z`8ndXmhdZDY3glK5+iA`YL5#?X3hMorLe&={JIia*D*npB%N0+LOD;3 ziri|9JxxdW65<|tp~G zW<;fV=Q8I^yV;1H4Xm*i4>wIED|_-ZeD3#J?2&;WMO_@`=b6c?rk{yP)LJLhir9X_TU%q?#^yw>(bMR`kmOY!lHC5hxU8(VDZKj+I7XJM%vMCA1 zw(&mX3%V~dvJCxyC_H<6NGMIOm)+;I5MD+i(A_kGqU%-S)KX-W0ft#*9=ym135pO+ zqBtxPa9faJ`RuupFefLyjw{YLqF~*(EPQ@ND>&uA$jx_akgs)-a~)-RMM>@Bw8X;d z)`8m;%lh=-URUdjXT;}2?=3!XOoJ_Nr1hdVS2~%&F$8tf$FDttZWR+zF?%o_zK~An zF>ks(R~PGfh%()1uYGi{@}E7k?Mtszt3-Ie2Q--jd#vT2myT_25g{O7b3YSJXvlhO zc*(IC^{`ML8y9U(J472nCXC}&gUz2=RNBiqz|p|m{ zl8_RYn%soZ75ex%VJou_E~8{v@S^Wa<`zpcs@6+%=pU$G#m2L$6MttkPYTNwG>}O? zss#ga90;A&@3G(<3xStsnuvkvQ8Y?WhpmJn?d-CL^+!CY=DFlfxC)9!iu{f)kqMtJ z0=@^0Bn;ggAk4QgRO})fB~5O+GE5ZCzWY>3sg;$p{Q7fkDaNVet2wy> zxIp;d{V!VPuOKKzWYz*>6;AO1r14ZcxfpF?nSCp-wisk4oT-$%?*o` z&3h(SNg$?noqq^to`!$HeAb5_bwHS6h|79;xbX~gvW-Ll+vYK7nT$_XGNP*a@7!8o zVPL4S2Ny{?lz5*2+dNaXoRR^Kc3L%_Nr!L!%rOJ0rxi<|=v`0n6Ub=Qb`Ll`+=HF~ z?B#P>8am$Y9Nf70l?O12EQntgCIK=K;^!!*2d=yrVoCM8*eSI93O>MB4}W%V1?#P(%iPx-t#O-3MfTv9rU1Bs=$HG^u$X7mGo$;T zw|^g0eyi#$UA$S&`?qGh_Jsd+gMegIVZ+MOKytKKa!V73EGu=}@sl%e4nHmRs|Xyc zGj9eP*#5B)Q^RsIM$6OHu6BC-)G={!&9hEvPrBp2=H)3t2;Ta5tekngsdTum$w=A~ z)=uxIS)oxTy-I$DZNUdEpB4?-xN!V->?`Cj5!m3Oz%lBkCqP z`r1szzTA^7MU_v;J2-jW(ouzSKFluDU5(8lCv)HXna*q*pdj=Re8Q`79X}MuW83&M zrj}ItP9MJK-m|x_1b0d>$eEE`VOpyke+9OHM*??8c*ym>5{gCOxN)MTB8s$)+DKW3 z%$6bwDy)7|Q&SIkS+HI#?NYv$4~SWAC0%?cJtDOqFW)=>SBCWpXgFBkselB)AKX^I zxic4gj(pYgzmv8~lfhm8hDmPqI@?vaRfT~3q^I@AYq@N0(hXD(0KVWrk!6QW!WWwP zJB#fUb#(5!_1I@R^HQZ#W4VB_A}kqy!sO;Rix(6^tuo94aZC$6=vf@jsQTn2iCyBJ zvbnA<`{~bYwFTBPQ4DWSC)>;*$-LE8*0<3hLQv6l|cJgOplz#jFx@-#W@rP1msTB}*^4I}(o4JMYaVGDW?cNt&l65&|2Ph0}C2JwB-*T4H_L zmrCB|rCmekbmIPYing?M6K_Lj_f4KPpwqzDZ8R*`T~g41;YFktdJr~HZY${7JsmKu z)C=6TdwPW}I<0z*NQv10!z_*8Qr`K${#nUKFPYtPsYHq?@m|qQ+mf)}6KfLOUH-lO zF3Y6l7}Y?^ap~JOebn?DmR7i>ctd`Oq9Qx;@}#lLL!(H~`y2d{$layEi(>BZy&U4l zO1a)iOD|TV!6oeMpf|#4cb>oMNe}t)Jg{~_Mx6iVs|R6(HtfhEB&Ea0LJ+OLsG3;6 zS+7^)c73?Ocs#F(k(n9u0|foIIoR2Oh(pH26bV8@GR26dBvHw50PLh<^#;nL-ebK| z$6TDt-yfT-_u45#$cIg}9{;UnPamN9UFJt2R)C)PK012js039IV`TSs^So=CMxHB< zT|j_jVhw$~mkx`y9N)=ImHYHv`)70(90s$8VfR0j%3Oj4gp;gfseT#b>wYuf+DvaF zxN3e|!Pg>-*pCh^*Qn7~e)jr{);MioNT-u&q0+=isbDLynb1wARa+{eZ`0Y$ino0* zucR`r5Hb}uKY#b?#huHzlrL^@LvY9w1hV<|=1Q^?@`PmnHV6nE*QY1vbd}oW746Yy zQAfRO|IQdD^HJ{MsnTx$4$Vi(d~!Cb_>hR7)n!_A**Q6iN=kv-PBT$TDMkJB~G zzyj+RbB%}@?AFtskdUqgcbP9LA|mikMiVT!`#QP%O=cLD-nr$t?xRGq4@pUCFRO(` zX`zR}SiHx^%}j-t4|*%+T0kUcKoE~T$oxgL9_}^(U{AhR^xg!6Jz72N)vTi~U`FpCL^h)vYyr z4}tyrZpgepK67K?)7SkaE`50On{d4&5VvMP>4eGKcqM!!XTFr1YTg=p1;{LWIX1Yt z3X)eFQ_CIH*eGH`4euV;sv@!F;h`SZbk#o!|M!i^$$CIjl`Z-^8C_Eio;W9Yn7Af8 z;c<_1f#17Hg3-tVVvje6XU5@eRmXkIauKB+q#WYn)QgLY$SWwT=Z1QooOgHIevI7e z@b~?l_PxewHo&ezF0svr>FDJ4DWmlP>1BfxBtrjBK=|R!T{%vA}6N9&>5Z`M9Btn(6cE(wd`Lj|E;_nYqj01! zEruHB1chTsXeRW16|aesnYkW>r2@~tB%Ohxk%1`9rMp))Qat?TXTRE2j7iM##eDwttbh*6+9IuVs`vnU>pm&RDX3g2{Tjj|?}qe(2_0j5j| zACT1Sx$rXRrZ#{3oQC;mr ze7SVpdHn)AM2tu^&Jm@zr!MuD5&3jmO@;Dw;w*|o+g;+E>GNa4$}m-g;B7u(;YTVP z|DEDsVLBQK)c<#q^Z%Li@crL85Bq-kz+Vkqs=)7tRxY?9nj$oBG#f?wL} zm0GKdCVA6KI$g>!tcLR&z#Rs__CpA#ybH_6Pv-zo=nTGtVc+xK1IRhbflRy%>$Rcm ztq?IF)m_#joT0oR$QC@#GA+3{Po|z1e&27DcK4erl!<*n68jP2jL`s96IU%i>s&JatF ztd;hwzLXBi+dhstt@hV8-oQ<^0J8FkEMyNH2JAkUcmn7pyu$Zh0qQk=bAGX+ zUW!cWxW5Evj-Nn8P5b5zK!@m*l->(Y{NJopKgHG62lC1>jcb1I8?Jr$!nF%eoRzh; zrXz(7tMqNL5ygY6eLYksi9Y7I)EzP& z1Qq4y8Vla)IAcSp@>EWa`D_j>S7D+#^10hDUDY!if#0di=$M-b9Hg*oQ*H#;AteMlU{hdU`qu7{#jq)J~7% zIA1c;`o|8eYb@Z-^?y>H;TTLlMVi6<&T!3m_7Pm;3UK_8!|ZI)?wiM({#ZWUxnlgJ za`WL*A~go~woCIV%f1i6a|bUn4!oN8KnOWP<9^xniJ+`(GH%j%9&AP`L5*uYoabCr zh&Oq#0UAHKHkp476*l}t0moBw_Y?8gfH4mk5e?xe1m90r0U?O9y@x~-{5?RaJnFgy zl}#;GJFG?$;9=ztHvd3(!#WLswlIQytHMbZ-Ui>`7m)P>oKKVcpS(WK#6Sx95Sijz z5Xit5^Y%hY0F45WEmdJMu6%j@<$FW@b?phxEzAb=p&!GgHDE1z{|$b&f)gw!Oetap z(zq=J>;94h`_Xg%is|7}qGLOw)JyILSdhS9C@Lx%bHS}e^L-a#-8HTExkNc6bStF`0?0qNJ6lop$#fm#TPFI&7**K_6)%)CbnPg zXL$bcg;G^smj>z^?mc}JcdDGaOY2l&jj)-QObG-yj}swYeRk{wp7OJ0`2?qQ#dY>IqE$JI;P zx$F46Br+&1{5kyH%efLyV zKPB{8m=|KG0`u`0dy{qO-Z35f5_4(_^S_~%^hg&p(JyELonL6hlV4b;j}bDmNQ?mn z%6ZWbTMnkXYc1pod!n##z6S*xx_;wO!=|N3<4KHPNS zQoMcp3N>{w;3<{v+$jP4u^I$1Fr!YLM_l1F3(|=ogZwX%8#+{$Wd@Ice+t=tot-M3 zRwARDZW^kyPLgJ22Ii$>Ffl*v65OFGQB_xO+ayc)6HB%tD0!822D4w-KJKvg{o8SE zVxyI}!THu}E7tGmlwp+CYaY{GnlL3%c6KZ$uAwW4A&5qSMFqseL@V_-EmircEt>*x zC10+PVM0&#wg;zCP~*3Rkm94ABwMQPAb^H^I~TG=lr&V0yTnsn=lG^g!=Ak=tiU|Q zjE7#vf1VceX*$C1gTxDF!k3etX{u;jH?A|kCwD_Hdo^yIj_@P0X}Rl%v1$Y_J6ZYZ z3jj%x46gnAc@(2h9twT;Y9l-Y@$1vFaJB)Ep(3d00;r>x*#u_}kD*q}Ugm?-`=SnR zWj+DHH;RzS9wvbsHz=U5>iDxza`)lAdjJU~LYRS!T0JZb_-i84j3i)~fBg8dJY)<& z6byVb6Ou0+$$+mK(%h)S+hQq)IK!?409Lz!vRs-D7;g4EFFJtK8?%*q)S4t~iAjm` zb}9K+=j(p4Oo9;jYt;oUrFL21%_&`Q`u;_*{`Y5>fy4Cga|45)s(VR5mI1M+g2 zi%iQ9nUp{eagxob!}nO;WP_)Y9HEwatFF=nS>$uHc&r1Yd&e^Py)t0ewmjAU;$eTH zO-7dIUW$2I>lkQbaJgQ_tj(oQHsr~4gD>9_)s-w9nZqQeAxgp(87{_8fNIG9s`GZ=%-?8<)IZ>k8*c|7EN2!UEFcO$a+iN9=?xS_x{4pGTPnWtYPW`3#J>2#tF4+d4Jye3qpJ zTAbdV*V5F~EI+)FjOZOb|Hk${m|BjTTBZWwY-u=M5}*(G=gXo#2A4YX5cdf;NQmfg z=O`mi_T31ab`MHu7_`YGN%KBLEy|fSqStqkr_TMJ@7>5c$Fx$G@LtxM9334gM7vjT zVVr}WNJ=;ZF*(I!ju7$o#YkmpZt6GsmOntPmn-;XTgpU&560H#;)#4)j^c^N_lc`o z8=+pe_54foJ~>%^y$*5t*d7pG?u@V(*VbxFNaHu&;GbFd6m>Pp*BPYZ)3IUp-VpYI zR0*W4OW$I}#BwBqgzZ51uMcZ21I!R0DT~6$)SqKc?u?&+O71@%o|9AAXV1n&uiJ~Z zNAM^d|6E=_ixwdd8`5%`O;lL2vJ|uI?*MB2@EzsEZ$MPE=_{1BV^n=ry`MmK)X)rfp~k95wuu z-Nc=`D?VDP@^|jweUxxyz8rYUz=^1qb+7m=kE%mN@@~-x7&-CS_*}kxps~1r(BoK; zlbxLo$Ahhf^PDydg?sl1r65Xx>z-KTjl=AZ-(S?5BW?_(Ud)?Vy<`f&_pSvpo&n}UN>DICi;oF0~&CVfYahQjX z{bjV|QwEtaa;Db!KVC2BZvC9>@qf*nYZ*eVK|=Kcc|eQT(m&Dx@~8 z;QW9ae?tP+$wm(IcM|k22l(`OHa{j=RA?LPYV)ogiMkdP8(s~}O8|_10=(7ZpEY^- zsV{A~NrU$o0s%nG@pfr>pcHVZ_O`aXV^uEKdcJ>GfXBJA8sxo;Rc04)*Dsp`3Bes; zSNeTAdSN%2=;K4j38=SG$g<`fZfpu-hnn zj+YWOV#na)KyrivW?s`;>GQ1$!|EzsEMn>e&CcO`!{zw>!UvlMyMLa2>*>6S@4iL% zCsnQ5d#X-SE2j|-3~8F#tgHmg2!u_u!eUED=}zP~7a_6;6zyIMqHfoEpIw z)^HDMH~bX4d^07`E){m#v0}@R-GR*e^q}GjY4JbVs(Ba-r`4T3W`F}gK}{^tf=`)H z)qfLFe`~K;a=o;Lf&5LXvUR0+b8g@g$EK9G5ES%ZXmSHlg0;)7Fey4*3_ zGvhJiRxqrn_C_4x}%c9AhyzaO;DHQ+BVKU)VSSRUwdCyhU@{MPGN7ETl;B|EP7zC@ZshVED-MEcuG8+dVlpkz3l<ZDDm?W;u4*T6*9&IK_ zAW8c0;R9(@jyJMP3j#@SApXa|ymr#_qSb?;`Lo-NdzpSKQUdS&xT;B0Hzi_<_7Kk* z#qw3AKr;!%LGX{(h?wV;G4n*+s`Iq-dA&itTk<^L0qROb*#mvdI5HxXcjQ~CY5TL^ zbRlb>w674pV!eEM-jkd}})1Nj|rX1#1x z!hfk|k_5g1bqj=-@YxnKp$Y2a$G&owJ9pU<&^NulzrUK-F#)(z1IP=&`G)X?4_x-^ zThv7Lk*a6niBjV{iMlzt?P*&xDJ9M%8mG;UnfNTajh2BEP&< z3fC~?3Hme~$b47l84<-&b_5$!S)}269LT{Ae9YSh6fmRD*Wal$3K4T>LYzm@_$JWa zDt(SbMCsKt40&%5V*|Dfx^8BNJG0OXxKQ4BCSk$h3r2ZP8>7M>daN6WZagb9$W-AR z0NE+@UOwgJZDa%Ja-?fj!{wG7aQCk;BFZ${3cuM+?gmPo3qf0pn|E(1Lf@7>xDmV z`5vd`Z^*HmW6UJ+izOS9GvEE>eik-tlirR zvFVW9nXT#GyQ`kaRM$Z53A6c`1klvppbkfC2SVhhd#39mBWsX1U zD*9OrKA*BO-u`{fgzNdib`2%YEjGj!${Vx)7csFaq^rw)SC7Q5ONnHHg7D>rJlh&a zQ009ZmFw1eewD=cBWc-nuv{?9^wy`PygD1QjEz;xaDE8?`js1)X|M{ZWNL=CS;YT> z+U=31W&l)|psau}?k@{B8A%xB{1_or<~B&^7hc?iLojTtP#8nK=Z86Z3e_oQCih131cX|0?4Unp^EiDq;h9mg~8)5I2z^pp=f z2G*MCokh+@-<9Kd_&h-!3dm$a{mx5nwHbQC~N>=#;@pE=Yy*MccnR ze`&zY!m8v1NWZ|qzzgw$&959P3row3b2zm7!0=wBh!e>}nG%P3_AGk|^jRwtRX5rr z8A8Al2Zu%rsDUm>_IIsIKe}&P5vzL4qIvluQeWb&&w?{P zoc!tNl=h+Z3?a?fAAE?7cwSyD>mM->R_lbs#Bd(1FGj?qq)$PEMs$gY=mJp>=UP@a zwkAQ(ZI)ZF+(|LPW!v>HAM=a&I}gom# z>0}X${zs*6(c+|v@=Ta|Y4%C3a3NZ-u-SECSc7h7L`#8QdTW(x<`t~Jiy#aX1qxLp zvy0pa&6J zcL;oZq;Ge7+va0%6c%gr_lwAdBnUGCZ49sr6oF?5CrL18lZGi_Wk3GCU_zASj@H8B z&g2Go`pcK1bMx~TQDYFu0;*?dfv98-;PH{xs`E`GLfzj3o!Os|k|%RG^9szYpKRw^ z!*U?W3pUw{%s{0_kNV9JwR40pkg2(!YfCm+CP@B%Ic+)cXhqnZS?bmfci!XH@ALaU z>n<#!ApV=(($;=>`UCD$(aTj$2z2=y^VCG%k}Pbo>+1@0!tiGBvriUYXdw%qzhQVT zav0i+@Au;clp)FQuxqdAbT#g}p^#N48AN6`a3GH0%Hdu3j5?xNLcUu;4NY<9Pi*}D z$&=cHJ)S(z`Jl$9E%Mp z6bj&^j`fk7{!Z{E6Sg2^lgqh;ZBTXF(AiZK&}bc!@v-aQlb-p5J0mV8#-_5zm|mKi zpchs$P_n8+3sGA&Q*(T@_)b{voCt}Ln7N_~!9Qc`{_+OmwGCUg6L`U zDBH?NxLb)g#74-*0tdDVa9|ZQs`a=6Qz}JR8q)_?opxpvbor-sYg5SPcCnmxxic@e zBoMVnLjR_SA0Ry>VM=obR~tL9FTzn^69UT+;?JKyy#MtF5YvmQxWfOV=VB-^vJOYV zZVc4vW^_EiuX1H5`(V+&!+9O5_mWl=Nkh8y$z%%G^aXcj7le4KJ39+Q*9d*#xrIb+ zH|R*g>vZ)cR2Tn_J#Vmyh>-6Sz0TnI_`;Le!s4XaHd{e?(Oi$ex?eoeoE0qrmR({5 zcb(hi{asF{@xNbqz`HG&4HL!=03clyatJeUc(C<$celVQ(D83|@M)Hu@6orZ&^B+s zHbaz_iqvgfalcZ0Iu_qZ`%BAd_s6LC2TgCkd>Qc;$0MY1a&!B-X=XnoqHnam z5IVyFbvS|=wSMR8yo#OnV^hrc&*&GB9=zC1MwkxWn-})-xVShVYT8A2Bw$0e0j-os zlR{lj>A3gr2Ubd@HJ>O(#6#U?LvG;i zSlioQf8pX{+_eBjtmXdI!g^FDcv-9-eh_L>#sI1kyVP^fnme{D4Dl*9+A0DBE{n41*wl31row3oA{>+WnjbGgTMP{;bCSsspSe8)T@zU3q+G(=Y@Ah}O zpC6>|o~DdpmN%KbC98Ybuy#%O+XoMr|Jjm_Yf%K+$t3O-LKcl~^qkkoDE zClcDWFps!k2)55UL3c442EF$zg=is87axKKWjfv8to=;KrX7Ag*K+i={snzr3tn_R zW4zxn$*>gDwL%J(#o*g&Y7xOt^y9N!V1T#)Oy{rH?5X9GDgy4N6pgDFjT37GmIoVM zxs2vUjzS_P{X7>bq@phpaeLM+!yA4)_B6F0hGWNtsI&EPIOM7&Nxs{|Td8Awi!L`YHR2`gPn5I`N(Tqc8f$k*#a8`M&kTD9c?U6TgqtwWlG{(|e_Y50#1* zs$RJqp>|iEa*`dOV942B;>bVM$K>8HOyjdidPu>n!5jM<+~<0WCQ0q%#qv&Y3Yr0) zzQfGgfm>exwtEf!q@psxHFTtA(vW^JCJ)z?nY*cPIY+|+i?@d)>4t_;nFej1xVF|p z+x4DOgM1i&UECBeFjEz-C|g1*vq1BbN{w*y62T;d4ce9kkOjax{0Zi~@q(szw6&=q z{sRY$EYL(R)-#&^69k!R+F(U{!y@-)yWyM}5Zk|=!=rTo34(B<-f6@pO@lR_Ylq*8 zf`K8CoQ5f^>yzo9lir6;r!~JMkBspIFqL#7!HWx2C+|6^!^@nVopZngb%ExDz>0q8 zie}cZYitvm4Hue5rO0|8pW5r(zigY+r^rsI9KN!Z@UzJ6t%_o7pwO!-yXM@z^rH>B zh*gJ~n5FfdN%v`mbd5A%60ZzpQ>?Y%yCpw(3X!+ZAo}}*i0#nV>pmwACR6V4=e2~s zdleCOb~4l7&>Qq_^pS~9kmtjO;3xME(ongLu?vtDFjz6|XQ+YYK%v~o;E-5{aM;fY zkS7>5CH85_man7`bKkK3?o!d5Ix5Nl#oXjf-HC8LbxqB+ro_AHRi4PL6hvQx&lP6o z0!ZKcW($}4KQ)0>O^vaf*IyfLk3*L3-C8EQ0jZdv9IuLJVd=sm6D(Ji4R2!8Wxh4s zSRvyIexrG6T{QnPnQ7CYEp70OgCVv}|7=3D0TM>j9H;AluD<+QP;kf9Rjj$CMc8A< zOfO$YR~_9>kf_D=T$}-*3Mwk-?^cSi;exFmbjWXDvE=0BgcEknf|!nOqZUtic(|4; z=yObJE3*4*x@%K)yLTHbvU^mFKw*D=vP-DO3G7&r?d|el|Ec;| zQli!XJQnU4Ki~&8H=xiw;!JRGo1~sGH8ecq|G6~uc;*AD$`z89%A*K)AaM!&KY zc;<>Fa%nARr*<2oH}u6p9S}=mTL5eeTp4tYjU&Lx>NTJv2mY>kG7L~_wxF9UA#tC` zA2m-n87rGF?{c}g=;)e;96CMfa7l>oS|fPc$8-ZKpnSk+00j^sf_0wl@0eAvTMYrq z8)tW0e($=B3s_UJek(z&;by<~3(Z3yUR|QSA2TU_q}?-}^QMJPEwq$F$7`p@@`-2N zF`6lC-hE~UfDs?6?6Oy>74*jr-hW$wEpxafrM5pxjKCF^rA*4TqkLtH8KTP8H7kJG zdyj~lG|%NX*3Tx^CmDJW7$a~90w8HDz(o`)$2wd^nnqX6%Z)&+fgRYZ$AQ}sH_JRe zK}5&>$jbaKyQ`!2fuwVXE9y`v`D> ze0!Gn)1cn#nq|No8Fi^O3k3Cu*UXY308L)Lx8S{bS9v$wrUvu_3;{$=03Ly{+iDZ6 zm-4_V`6B>4DFNzt8*9hJ$r*LxQ9Ttm={&Q`Ro#HYlTRXKv#?D}Hw5#p?KGb?J0||9 zt=^R~5bo#3P5?;RDxgaTGmG8Ocehk=M1Zs`))Z*})EH6QVP`=Nl^ zhRtgSpIK37W`!3SsPOn`p6ysBj%$jUsV7;vM7$&Vu7hKkK_2N$TN+LO;n3!ZxD=En z?%j?GL9-D^127H4do|0jKGSs&wnPa!{a-!iWj<|I8;yCh>`tZd<|!H2gfWAyLyIs02E-%t*DNbOXrpAc$3eugJ8J zEaMCTP6H)C#fg&dTkWK1M0Dhr3zBh{k5a#v50)bx%IB7EpJZYw68K` zG}C*vCt$JeN}%_Mi;7D6axVrf!Y~+%y7V53i0N(j( zoYiXf1V#5fW}DLh1V_nZRwD}_d*G!HuwMHI*}0TfNh z)C)s7{V>wVqq$T`ZS^d#nG2?E>mIKY1j4_Svl58rWUhZ*SfO?BO@1F*R5i?cNcE)d zu_8r`XTmmDyWL;D55B(NYg~$>HSVr^z0^?yR&q{YYWLnr0IgPl)>Qm%*|7-)OOf5$ zVBVl}ONU1g_^^D9hq?s;0)0@xqmD1e4LkpKR;_3)a$8{zCWYBpYm@xI%DAnhIw$&>nUoA0N#SH2~tg6u+^ zm8}&rFLql_OaS@~fpv4Q^zw_u`3b$O;>q02;B;_v%IZ6nw6L&%B)%uV?^T&JOB1C5 zLO&_Sky}1ONa@_hr|8nOxcw01s(#YbX!Ge z4)~ZT7#O_c?#KZJ3~tT=1Pp7ZoB(e(hm{n|22^yV&H)O3rjW11zVrAqjx{jpf;o9sJZd>_w3nC5X3$RbJ?Yjj9XU*T==`z?>|Rt z;kiu|8*n`Ov99D)$8Gz@WA|4_dj05$#6v8Y962%ZdoG6PdWIdd_a=#S38_5;_(vnYp&?eJvjb-Zi zhGD$_LQ)c&{q23h)!xjLt5&amUuR}Q5D^bjlIS68a5|=x@VU2X(7ruHp#Q0xh=L{$ z-JU5;L-}TeMD*Y1_`}2JZxV_A{0(+tLaIopK$MA^<)X-3$B9;t#$tl@?3tUpZUcXg zCcXM-ul%Y0-WT_>w$vS3SGn{@c$Zd;qB=UTMLpgP+Sn-UgyYl6kf0oRF|_Yq$G%Ip zQ0%^Qry_;)a6^l+s15;S8j+L-Cj|fYGDt{zAE9l_*@F_tFf3xXYqA#q=K$vH%L8_c zwjj%e)m2QOAOz{j>ma&!0ZR^e;llJREqUVNCTeY@Ku}UDQ`fYxJ#PO|sCwah>8ZM)!pIlTkDb|{ei9zt%93chzrWwPjl<~7 z7l6a(PDyk~r1SFi{QOf^A1*DsA1j?7v{jp*qZl@+wkNqJZFr*@QhJJyNnk*|->H6I zIM>CPffL)LDxcsM;590Jt;iHoSy^d&0Ys)#b(PNnihFif0{IhE8qYUJHHm3yH3LDQ zJCqB+x(-rp$q-;4_^icFyH5inveRJ<_9#cA;o}aqAhG$M8pENk9~FCNte=Sl0NtGQvSri?|-r{ zODIzpalGX2&%?Wrb`KKep=y5lw8{4JGxg;Gl`O{}T#h*MwI!S|477rdknL#dyAN6{ z`K<>PGw5Eb;KNccq?zG6zIJ{A0d^NY6o(syib2vkrkwJgo_wLNUftF>!0K*kbrrBL zl!q#+eT}u}e6I#r5h)xzJgf;a*J3H>A7BjZ<^-~AgKd-X zfEyz`CR!c!rdUAaFTnfG~6Ob|-0s472>7`DG`VA+zV1xQ;2l z!3cCSgLBV>;GQ{pY#fC6fWb}>+!YXmK?yvn0I!j(wG~CG9XY=$3I{m)J2n;;9RP^@ zPEDl*BaP3lm5Dl;3$8p}|CGZ-Lqo&NGjVx5<-rWTyrZS1MILMpx;-ExH_27i2N)V6 zkY>CoF}qR70Q*J&1hyN>-j?KN1A1vZ`SEUPtowwQ+oGL^`k%;Jc*zwk^k3~z1S>2h zbwpQu(&m;`{lK#wc(|quu+vyFa&qNK{{cRc@po0VP8x@{4to0o?P(IqqZ8H51gF4$oo6H4t2qB-Iwq2GQEXr)xzVNI z!5xurGc!_c6%7B^wqAdP1TJ)nE;?$9c= z65OvwMgs@(dOPRJc-JND=g908T|uowSAF5b*I&m4k7#Mwd802cUtyeHG=vb%qZT$F z>umU1#!>!_sIau~yi(?|eA%GKK!QCeI*5CH{VjXYW5}6=)!2Yi6z}mLsOcCM-GR8C z;Xq(O36gk+g!v348+GLLv;>#x6}Ey5pqUTWWN~8<(%loj z*5DxH!oVv+eR1%AaXuSB@pM@&)zqBp{jZW$k4RwqWg_JWz{fuTe@yQVTI`DZZo;6E z%9m%kQNhy;WKIDW@$%(EvJ6B>tk=0usHxL2%7^7X6%183Tj&ZtFX|hc9vppj*?cU4=3TEP#JRY*ChtZ6R^0ES3l4bO2Eai9RX}oZ*j(-Mm^iCs!0+tum&Zbf6Uh_FJiyY=e zKe*wie`F3gTnhmyN}%^(#UFI(SDcYSgMiCPLx2vq-r&_5T{qhZi_X{4B@RtYoUQl! zm;WGutw+>t@{f45A{KD@?psgCSCUm>3Ra0kC`@lpp#7cWMT)^})7RL)Zq(?I(o)x$ zalE>aSega`S*+-MSEgWy^1(9}>{_oAaB1UBu1545cQVWFJ7S`*H+@*OpSRQ9{&61(}|fw z-w{^TLd0KB!@*wiLP>Ub^k02Y0XZl&EHJD`%kegNzTHPxJ0yg^42P+&qT#N>>2}UP z-Jro-WSB0{{&E<$~4(%4^Ww;pN?|^1!7ND}B0iv${;pUjO_>z7`tlaTv%B=i2B-jVPJ136Fnj5axc&?T;kf}Qu zmitx~k(U^nyf&CSlxtM3oYvO%=STd3kGD6vlJ0L}X62HsU1`F%>>B zVkR6yrH;x&b=X*Isnt1!uvQz{UdPzc(#?V~k|4{iAM0_YlRHo7 z;GgDF89Cy{KFo>28kY$BQ6N075xaseOXI&n zdnmf|T~hp_;I<^aZfO?bs868ys6h~#@(BT!jZDb^+|Cqk(1U)-u`)Cv1Fv`Qv(8EM zTMr2Z_TA{hsRG!ie***AP;W|6DH(^^Z3J0E>@1I*H)|&a5vb(LDLVq$7cUzA^z^7a zy*#CdkTDbzcHbjmYrhL|SxB$}m$MMmBbjEMP9FSkNk{28C28{x~PCh?8Gc93P$;y!;rO5i8we&A)AjtUn3d+g+ z*)jV05f-)EX9`r(=g*8Pi=;W07`fSTEwEQ?D}XElFc$z%A(JJwaM(=%urmv}1v_Ykdz`FQnm9o^Dq zE$N8Os~<8{B7Tx@`MdCugve)*nowcja%d!f@F&-Y`@^G0gGu{plpP}@!oeU&^iL{( zd}TdgvAh)HXkZoG@zB^OWz)z7Q%Y65{Ut<4tBo*`h9uAGVB?N31jGf_fBJw0fU^+N zNnYE|pTOt;|7$-O>ObEDl2vpFTmzrKy`q5r|1)NS45nEbJQc8y`>F*rS)a{s*TzYS zWQ^B*YH4n6R)wO0?Qz8T6u@LyG=~YQf6N7MJ9>y9HQinYX+bQ5?B%+0ZRxL398vgl zbj>X?O;SLAP5mGhEv3*P{;RJ{Ql^0>139x-0dDC*Pft%wFUb5A+wjNVE`QWw2Eq&S zKRX22=pWQn2aTDP0`$G@Yq6CGG2uyAq~ z7fjPzuC~0{@0%nvl0ly*#2m*>z4_f^_42wqLOZ=`6(Nh;Lp70^J1{-&z0jW0c6Pc* zm=hW#$WBf0bII}Yu2-`tL7kz34%r=cA}kCnM5tVaeL|SJ{wQ1FJ0t(J3zai@$jHs`s z8)IoAcYQY9I<=n5n|Klf2^Tixc?Ui+xyw{qF&*+Iy{O1zD{MTK>u|5Y^YWBYPrso3 z!^5|ehFHB;^?R&?hf8O;6s?D6Kj_=s>sruptr&!8rGme;r$}4b{mu@5O@$9Re+zwm zf2hWNKNMUxvzttYM3($NlR9@??1Hw64tU@c#9!<$y$p!OdEIW3q$(uGLL$XWhSP$8 zhnRzgj5TQK4QxCYe|+R;@oAV9IxT#ND9Si*6QReLsj|bgnVJJ_uBVNkfOGc4tutxD z9~}y0Lyfk+2q7k^#L^GBPsH{ZpPKNt%Fcsu=|<) z!tx)1S>nx`G?KFEGFwAqx?f}he2S6&tlzk`A9{XJ#dVO9dqtfXPLa2kAFnTzdw3r4 zVZ)KV-j}?ivWceA2e)g4MA)Bj5cN8pjnDydE__9vQcRZ%+k;MHB2grAVb|upJ+4w(hZa!kkYN`Mkca`4oL!*~SFk zdt^XE1oULpw);!n<&%6&Orgz3qvilw`#j#tl=S$G$vrv_@)!zmmK_5fHIJ|LH=e=oE zErQpB%?RYqiw1ds^XC)T#`6@2Lw|zh?4=5z;%<`XJ)tHtkeewA9XEv!W)oo{ZsiBU z<6_UAFjDn*5XxwXc+BE?9Xs}CMuBxh?`t+a^lnaE8*gAB+og^*-I^Dlj~fQ|g$X8M z;gJn~*T|l`XO%z`2Vhn=UH4KfRl4MdgJ1|{l=Q;sfμ9qM%fZ^TAnH2G&6r-1c{ zi&OhyI9=<%!BC##doNDa9ly+R_N$!XtY0J&@%EF^?Nj{qVa1O#ij*)!jCdnD+lGiO*1{yS9`FECo$ z)FdRKfLS2VLbC8yTRKDwn1{)|+FMMJx%F`q^IE|RlV5NW&vGwe%>b-px1H6pqgSq2 z#=I%&SC^MS6B$D=2%!E4yYIh^e?7Xu)6J0yp0#Zwrl#gvR$Bqx2xGuh2j>X|=L90L zr~5=NHnYyw{&W|PI2|3SEnWIiJ1sqPRy)~Q^0&=DYrR4_2inn@#O=KO%NRvTV5w@- zvp3;OGkTmzTf>oo+wK3QAgtW zHAeIpIP%|k`HKx&bU+L+X?$L+32!Gk%nlN`m7TnK|A2&u8#|*aSl`}F<5zMxdha(K z9nic~hX0xMHRVo>|e+SxUTo$C!c0 zcyYRc%g@jB>zI+}@o~`NzqYHsGhymIv-B08&BNj`Hx^SkL_)YLdcE7-_Moz{OkrT6 z*quUcAoYurw~7cbA?l~g_UL`F&$%i%#+7uc_+_eX?qSu@bg%M$?|XCNS@9LBsDuO+ zz?2FyG9rJc=HNvmkR1%#y`>`FK0b8jR#tN|LPBJ~mjEpEemf1Thgl8EuK-cLAU7BK zFDOG;s7IwS{Jabd`bUkYYgaXPKM0HzyvUR|>%;f(-KO@hJ`Q>Yfu1F3NooY`?Cuhp zV>bi#Bk;!c!447pbpLM#{uDTbnS|kQ3|TySevAQ{iDC4jHyU3a1>PAWC0!73zx%H3 z()PF3$|)HR#Or3FfMLAVr5{kIKtY1BoWBe~DTX}@fb0>Y-nn*h7#eV761@AM_IZ%* z(4twE)oiwv=gOgyA|9>F!IfQ4VyI31oSu;E_Ypf^p`pnbu=O{!=45g*uMya@tw~h$ zhAxrY1hxFI(u`$>xpp@KMnq_k+R4b>HVzb!M=Wh#YTqyoaq^-L%GAvdu!GO8;SD-OEziv zJ;y2Qy^r}EN-a@-H)KjSfbPU1Elme3yCPy@)a^kKM=0(YnrB5xiN9IF5SE3dCBIEO z0_1Gt0BjBXEub@r2CO|jmwpmof~dz^k?2eCQDe5P@L2%y23U%e;lpk@oMrvhJQ2`W z_nD1EMu?D*@CgVBZJ%~J{@TPNFKebJzf)!rMF`FB*-U3qMT{uOrz;%Wpn*f`7U!Df z3mP!gLk`^}9HF5_-@tJHdqAvCudM3ILVo`R#f?0%Q9^cD2(vQdsXOOr0D)5R4<5WX zs*!4iwj-^-A1dtq8U81BzG=GEe}(M1+Qekb8kiLU0^wvwIiPB1U3j zKWoT*_PxwIe7ZXM5k{CTi}nt_-?6gea473nyPNp%g2-P*IQ?wAwv!i`6s^)vB=nk%)?CW(`&@`^JXD8hEZaQBs4L>$f zf?3Q=TLrJbS99J^jFFGPx|U^aC|@vMNg`aQ~bKJekgm-8Mpbte~qS<6EsQApXgL$$Ngh9RsB3 z#v!uvE`6t<2j3fQ@A&vu%9h!FNb8M-(j!CB?an=7)G;+2xttYsqr>>v_rtHij#uXV zuK$iq{2QhF^Txr!^^h2IiauY}J*{GcH`!7WiyOiW_n62`&Zr+2F{Hz6U~BMJ>|UHGp3g0L<8%_}DEz?0Qrd>G(Ys_N;zc}FEEL=Fq5B@v|a*nA0v z9|Fs6&MQ77Wg5-y?vX(CbwPf95g?V?@=)8lP2{o4uZrK@J1jlg+hs$MV%ru`!w7wG z;3eIgm?0&wB4g4&+}In22q74Pe8obh@e`#XdDgDZ)K+E+SvQE>ZdKFcak_yb6(zA^>RTI z%8@v@6zG8PZoAda*GW+gkVXL}npiDh0#-34{oLNHZ0iCg(q6CNfHlZF%H_ZTM4S-4 zVnqP{)tK=BX8{#`GKV9W=aTDryfng^6K5W4ch1Ol{4*?AJ^S@Wi84bV&j#ULl~4aV zGGr=Mtzwv*oOEvd=+K;GqB}NyZT9Ag9k(qT4I=p$ZFNnSUf1S0*j%1g`K=B+_;EWE zw4x8*6gyQNSKo{5e3UBgCf2%Qy}L*#VxxG;&@A!z4$i0gZ`=z%$bX#It9c4pg&^Dd zmMsV|38OzhD~!1VJE4e%C=-}7m`^`0nlM+($|zWBU#27;bvvvX!)nOTUBh8_X-5Zo zdYHp!Wk`wnEQtuswIIY(1P*U=lbyOI{z@*J5LamtsZW|2yW;AuF)HR8`7 zA|h%(KN9pPL}Xl6G%#rT()e-fNI<}?V!Kok;htp`XrmOaPe5E_ZAJ4UglN)aD!$J<&+=|EV2H%+1JCkWvvtsqdKwN z>Hv0);J;L#GH-%9*QY1BoSjPUfg(Fo>?s_q=q^WDVPS~3ny_3VRPjiuG2uVZue58Q zw+cMElO1?$T4r8XF%e@0>~=~@N_0R1iHN;B)vo^%m$4} zgs=YWQjeliPA4((DDdFtjTDJD!RqmR@SM)*N9g7CgGn}G9Ti16xsZ{GC19tLRF*;} z?kjJ!dxiXp%++RR`E(-Z7$k{q|0W=mVRFR=S}a7aBx9s+-g6Kz6+ENShV11xG|~#O zka@U%l(=xTMnzCZsAB3*Q9T0c)tF|G$5|d zm#e+~@!j!HXspn6{X@CG@U1EQqW5GRaJ+a=`3Yfa(5RBLu(;dFMrw5IPi1<>^m$2t zN(svI=5OSc4z)a#BHzG3CBWZxgh%nZc=Km&5sQOe0N$x-S=~}Wf>M$H<~_)#JLLO3 z_QCzhcja0;*`cL%CFzmqp1x1Rn@TB(7ZjAtTUq(HFW1t`yc|bCVfOMs>X+g!IJG?K zMk`12JOh#xZ@|9U#d#%s1xDIXu-jRP8i3dqjnA|B<{%Eh-CKw581T#9HRt(mCnR$ts z@H#>8bp;8|uY)%0O&70CpGJ?3mx-3U7)LRO`=brzyTa z!ueqQOXpiBuZE95gMo2gdHW@x|Gr{kWP~}sLGUY9VtAGSVhbzR`;rJ9j(7Eq8!5JK zv&~e%d^1e1I83cj-p-C09F7gdvv?zjp1tks7Izj#y%IoJQ=(hX)?xk=TpRvDSox9F z?xeyhsbv|F*_rh(V4{V%Ec+VVxeB@OpRZ5%3hbM6t{<=mw6@Z5h#UX8d@+vX12wptPc*Ydk{1bV5+sz>(}oFvwkBy4Dn`K|iam zq5@+IYWE~I4+?;0eD^fXuNw1EW2lMm&_kL)^;j@b;z5&`vXd+*rGVwEN*Wm>D$usD zb7Y>rJ&-6oCA`(OBEfuRc3t`PYh;hqg1%JbRm2}O)C%{qULwI0l%H#a%r;E|q%4 zm+2qZ{Xh3YKUvUi<+m*4ZwM!ekTzr};%yi89Z26#$cKzBj&|fQ=ZgAkVat=_D2W03 zLBB=9w@fo|Q6saM^p%D70#w9U$XDp+RY8vJIYHCG80-Ncim7m=&*Rra z#=$AEM*5=40=dTw{7-RgZEefGs(`iaVIaxgbF^RXXuSQ9CQ^%p!4l&`w;Krz6RfhX za<CWs1UIiIU+mV2y=}`Y2apc`PF!&7XD>Omk|`&8 zN4}-t$?w&b%eGUKgT!O2ePm}K=r;jiF2JrpnIrlO3u5|@vv-y(!_R}0lU-AD^NYX# z7JoDWy3V^%=UV)ck&!x({t;LR)Sj%s2Ab25>wQM8**1?nmJ1BUf-Vq=Gyc2vx5ySQ zt^1Vj;`Q;QF6V0ksoA095-#+ggTILU#tExsYI!xlOFs_OKL5$v%RU?s198}^#+)S&JxFY_+M`ER4lE|Z0pNV0xY`cvZ-!dRcT~(RBBe&yu1cmG+~gEt|DltpV`Te1JD2%9^QML zj-ffs5N2{ArB*u9NFx7SNK@2VDE&%4FOdWb(GO)lNe|chL<;6sl~L(-#qfGR&C9wz zQP|%FN@CAK10|o`=}?zD!g~kKkFU2J3%TJhB?^LXu8q1I%eU~U1i~6kM^#5()}VE^ z&AB_=um3~{M?*7B3O4_y7f*KERG6cC3t9?9ho ze;Nt@Ai3Wx@W*I>DduO1BCupnKAs3!S%MY=90`6lm;ei^r@9;&UZ}Q_E=A>~ant9+Mu>29E?L;BcJ|wNZ2FkNpuEhTHej?=+qeVTntGrc zqmqFQ@lT-v&0pU{eQ}>HWh#^IVw}i0NjVSA;%8#A*co86U~g~F(Ywvlf7j_r`Nw|` zj@O29Ay4(fP@{>W`(-7t+_?*+x;sK)AM>!Gv!SdOKp={;>(!e;pBHKTCmVtYZf>~% z%O^RNEjOXP^-`37>uRO$a&l4aC&a|*zyuy@eVtyJvqpqHficu=N{(z8EUmBsc?&5v zHdP-n%sdSBE&tV0US7*y-pf197A>+a-a1LjojX>+(GyL(P68sHnFdTrCU@Y#*NaIr z>9r9Z@qM`8<@;OsnfxYWV|a@g%3L8#o$Txu^1!05^Q#o_io=EaD%rYo@*&)lR~l^036fuM1x(8nlw>Vj6%~Nz8h2t; zrmOpR_qBy7_5BsVWC892pBi z94S4)i^XliXMzr0Ou4V2TUHx@U?C(5B}?fpf|lEP^HEwfB03sJ34oKEs>pwjPLfqq zoz-4H(a5(@*a8MBMhV?LJ$6dhpo(;S7!0IAKY#v2=E+*Wq6_q2P<9Xw$`mEFEPBdu zW=jnJglVfS@m2=u*p7(=y49~7PE2Uw%kjrsJjDFNbStXCSLa9I$7Q$b^Tv;Q9->-E zb@YAbHa%A>NGoL7e0IbahysS4lTBZWR7LRB#=3gLlo{MXk(I<4)deEit%S8#W+&kMvX^@dw(dLMT=Y&Yle!f!A-QWiVHY?5u(r`Dg*!%kM#`OZ( zX$qKbWdXqr+I7JR`NL5ru`4(H8nd0KejxchFm-Km238+;_D0QejkV`TefULQ7I#hW z_NI6>9z@v*8q#PTa}PX%o$z5#pI?(^7)d5DqFoK%zqT~m{zq5Px+rHlSI5htEUsUTASmYJtZJDl%ico|Z z!QZ_GdbbzuJq<^SF|skS?S|UMX+E-Za44J^15Sj{7C8)@an3IkUk+>cU zYUsO1`-Ri&)U$H5^vJ=ed=6vC2I_~c0go(a$e?@qnRL07%5WYQh=$% z-_;dzJ8pjwk8J2hCQGV#!3%j%ekUvKSFSC=(D>EHGnVEXSdH!?1AN}6o-#mf2ZCyJ zadRJRqLpmUJ$Oqt#Sz0gopvm9&u>MXx8FSUJZA*Nz+3D@Vj+3{T7wzyFPzB-Q~AX; zFa4cX^qD#oCFsa|O4A(BRX6qOvHNISLB3hC5tfNLZDK}dOlmJ>?=&9E>c-qE+v>A; z_@83ug~i|KW`<~yNbB!ElWz4p8wG^YiGyL*{cpYIXF6%{y}buFYCL^6@Zx0chL4O4 z4QowkQQq>_-1|<}1z5m*h7I_x0&19j%syC^n53j=!5+WO2A_;RjRWryO!;bIoIUQt z#Vg^#h--GVdW1C}@-DPFSfl@`a0ek0{`-amj!Gp;m0F#6>HcI?2+h$iB#r22FTQm? z8kq1nj`g`M;*V6?CrxA)ud1tr?Y12gzf0E(v%xL-2zUj@WX-QJ=O?K0C2l&76L6rs z#Dm(YFF5U#pRCSg@CY&C6l6@j+f){Q9N4EPB-P8?cVJ+ZM4b{}5ef4muwNxxAF1Rl zT71Lr%@DdP>gAK)_@#^S4xEr10)jC$Pza^XVAo}>Aa|8#{o0&06)8O2hu`IfQHvE8G{qvUz`*IV(|Sp2a!qMwQVQuhQi^ZBSTjm+`5U7xqt+8|^5p=fw18elz{TCD=G zzv$f!vMi_-D=*OO=K8G1`NJhUo@=-NWX%%;aLcIxu@UeA%>o|*8Zj^yQwm55ek-a~ zyFA{;xD^TKOU1id+EvbOr{#bqabi~qAz%=d?C9XYnL5};^^~Cnz-^)2*i(}a#r>&r z^G-aXPpR@cmS1Y8Ooyy&nb*Izny0A40a(Vv6(&UA4Uy;=4?I&5nHwk|VO5GLANZ-7 z*CPQ7*p?~JY!&G))72PPVu(Ey0j-7{H<{O+3DU6*^p_L~Ehm~y8gveb$NF^8uSZXv zwTtHT$QT;Bt3}y@6?W&SF9WZtE@XMTj;V3SwA^!_z+pq7A32ERbD5FJY=h3VI!0r5 zKdNYnHos@G7gAT^sG9Q;=wGTQy@+kW_hLeFpV3UJtE)2uLa`#?i0xuuydeR_Y%a6k zbv!xzV{>poKBPII$byW3nvW?`FEJr`s1ef)q8vEaR#S7P^A#n-4By@UH}AIoleQLb zF!RKN`=4NHl`U-$VsGt2U-k=mNO~a*TSlvoCxf7QNzQefFkp4f4OI9sQo&g2o4HR z^L$7kt&9e0`$*%!fh2=igNfNK$CA5t)#)HF;t+sYtH-^T2Q8Y=QYi(dH7rga{FdOw zmw6a=%C4w`m#O9)`0Ri}GlpCWgfGj+oAVlR9> zWCADZt15;)LDz=?MMN+D3rVTX_429fCj7>UNkP&8&AZc`Ew~2Mcd!_VV!jvYiOm1p zm9e|3qhX+B@K*i%`L?96>A<*W_FW1SB}EK1{hS+|1vI2oNoeh--F3J;DtUJ@LjtwO zj|^&Q!$EOF@nF-V^-C=cxK&}^Rt?LrHN<@-=-G*&9JKe%DX`Q^zl0b51h6z2Q) z6L@)egjoch0ACQNT}Nz$S5ywc8boIhI>++FUx38KG|70NP0z6 za1gXDx!PCBn9|b;@bj4=fvj51?V-^m$mI-x-#p=n-lR5AON~3u@V_Oc5?n2 zs!4m(KD7GSJ$7QKVdp_R6;hQqrOllP9`Nf?#!zLTE?AY>mzI}rZNJfFe;+!D{u9)N z%r|?fyS1~}T%O)F{_FESQT9LF^GvNvic|HWsY8B;?gpH%2QcOExDV9S)J$V7Z3M7y zgq+a4{DQ~t(=|j`c*Nv19iZ$N0vgb?vmsKsplTE2nULwtgyV%Tw5NWlp$LoZF~Nmg zvc=4`XGXP>+?dD%qJ9l2{ul=gKW1<%nL5sK@bGHZ>(a4)Ezl~fP+o|@d?D}iuuC#@ z6#D4c$(JVy+~EK9HhxJ*p->fIFYc$!;M1& diff --git a/release/scripts/mesh_cleanup.py b/release/scripts/mesh_cleanup.py index 608201acb98..27adca335cb 100644 --- a/release/scripts/mesh_cleanup.py +++ b/release/scripts/mesh_cleanup.py @@ -121,25 +121,29 @@ def rem_unused_materials(me): material_users= dict( [(i,0) for i in xrange(len_materials)] ) for f in me.faces: + f_mat = f.mat # Make sure the face index isnt too big. this happens sometimes. - if f.mat >= len_materials: - f.mat=0 - material_users[f.mat] += 1 + if f_mat >= len_materials: + f_mat = f.mat = 0 + material_users[f_mat] += 1 - mat_idx_subtract= 0 - reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) - i= len_materials - while i: - i-=1 - + # mat_idx_subtract= 0 + # reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) + + reindex_mapping_ls = range(len_materials) + for i in range(len_materials-1, -1, -1): if material_users[i] == 0: - mat_idx_subtract+=1 - reindex_mapping[i]= mat_idx_subtract - materials.pop(i) + del reindex_mapping_ls[i] + del materials[i] rem_materials+=1 + reindex_mapping= {} + + for i, mat in enumerate(reindex_mapping_ls): + reindex_mapping[mat] = i + for f in me.faces: - f.mat= f.mat - reindex_mapping[f.mat] + f.mat= reindex_mapping[f.mat] me.materials= materials return rem_materials @@ -449,4 +453,4 @@ def main(): if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/release/scripts/object_find.py b/release/scripts/object_find.py index 0cfd6ad1d92..f12af07e3e4 100644 --- a/release/scripts/object_find.py +++ b/release/scripts/object_find.py @@ -61,8 +61,20 @@ def get_object_images(ob): me.activeUVLayer = orig_uvlayer + + # Now get material images + for mat in me.materials: + if mat: + for mtex in mat.getTextures(): + if mtex: + tex = mtex.tex + i = tex.getImage() + if i: unique_images[i.name] = i + return unique_images.values() + + # Todo, support other object types, materials return [] @@ -118,7 +130,7 @@ def main(): def activate(ob, scn): bpy.data.scenes.active = scn scn.objects.selected = [] - scn.Layers = ob.Layers + scn.Layers = ob.Layers & (1<<20)-1 ob.sel = 1 def name_cmp(name_search, name_found): @@ -195,11 +207,13 @@ def main(): activate(ob, scn) return if NAME_TEXTURE: - for tex in mat.getTextures(): - if tex: - if name_cmp(NAME_MATERIAL, tex.name): - activate(ob, scn) - return + for mtex in mat.getTextures(): + if mtex: + tex = mtex.tex + if tex: + if name_cmp(NAME_TEXTURE, tex.name): + activate(ob, scn) + return Draw.PupMenu('No Objects Found') diff --git a/release/scripts/sysinfo.py b/release/scripts/sysinfo.py index 9f24885829c..3a671e7221e 100644 --- a/release/scripts/sysinfo.py +++ b/release/scripts/sysinfo.py @@ -94,6 +94,8 @@ output = Blender.Text.New(output_filename) output.write(header + "\n\n") +output.write("%s\n\n" % Blender.Get('buildinfo')) + output.write("Platform: %s\n========\n\n" % sys.platform) output.write("Python:\n======\n\n") diff --git a/source/Makefile b/source/Makefile index d06962cbe3f..99155206987 100644 --- a/source/Makefile +++ b/source/Makefile @@ -100,10 +100,13 @@ COMLIB += $(OCGDIR)/blender/nodes_cmp/$(DEBUG_DIR)libnodes_cmp.a COMLIB += $(OCGDIR)/blender/nodes/$(DEBUG_DIR)libnodes.a COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a +COMLIB += $(NAN_IKSOLVER)/lib/libiksolver.a COMLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a COMLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a COMLIB += $(NAN_JPEG)/lib/libjpeg.a +COMLIB += $(OCGDIR)/blender/gpu/$(DEBUG_DIR)libgpu.a +COMLIB += $(NAN_GLEW)/lib/libglew.a ifneq ($(NAN_NO_KETSJI),true) COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a @@ -157,7 +160,6 @@ COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a COMLIB += $(NAN_PNG)/lib/libpng.a COMLIB += $(OCGDIR)/blender/yafray/$(DEBUG_DIR)libyafrayexport.a COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a -COMLIB += $(NAN_GLEW)/lib/libglew.a ifeq ($(WITH_QUICKTIME), true) COMLIB += $(OCGDIR)/blender/blenderqt/$(DEBUG_DIR)libblenderqt.a @@ -226,8 +228,7 @@ ifeq ($(WITH_OPENEXR), true) COMLIB += $(NAN_OPENEXR_LIBS) endif -PULIB = $(NAN_IKSOLVER)/lib/libiksolver.a -PULIB += $(NAN_MOTO)/lib/libmoto.a +PULIB = $(NAN_MOTO)/lib/libmoto.a PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a @@ -241,6 +242,7 @@ endif SPLIB1 = $(OCGDIR)/gameengine/GamePlayer/ghost/$(DEBUG_DIR)libghost.a SPLIB1 += $(OCGDIR)/gameengine/GamePlayer/common/$(DEBUG_DIR)libcommon.a +SPLIB1 += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a SPLIB1 += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a SPLIB1 += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a @@ -250,6 +252,7 @@ SPLIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a # but somehow it consistently fails to resolve these symbols... or # can I just not check them? nm claims they aren't... SPLIB += $(OCGDIR)/blender/blenkernel/blenkernel_blc/$(DEBUG_DIR)libblenkernel_blc.a +SPLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a # These three need to be explicitly mentioned on the cl, because # if they are offered as a lib, they are optimized away. (nzc) diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 966bf5f7be4..a21eadf15fa 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -24,7 +24,7 @@ # # ***** END GPL LICENSE BLOCK ***** -SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon makesdna python radiosity readblenfile render src yafray) +SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon gpu makesdna python radiosity readblenfile render src yafray) IF(WITH_INTERNATIONAL) SUBDIRS(ftfont) diff --git a/source/blender/Makefile b/source/blender/Makefile index 937512f34bd..52abd2cdddb 100644 --- a/source/blender/Makefile +++ b/source/blender/Makefile @@ -33,7 +33,7 @@ include nan_definitions.mk DIRS = blenloader readblenfile DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi DIRS += makesdna src yafray -DIRS += python nodes +DIRS += python nodes gpu ifeq ($(WITH_FREETYPE2), true) DIRS += ftfont diff --git a/source/blender/SConscript b/source/blender/SConscript index 56a661238f8..25745c0e51a 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -7,6 +7,7 @@ SConscript(['avi/SConscript', 'blenlib/SConscript', 'blenloader/SConscript', 'blenpluginapi/SConscript', + 'gpu/SConscript', 'imbuf/SConscript', 'imbuf/intern/cineon/SConscript', 'makesdna/SConscript', diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 7dc10c53e22..171a73f72c4 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -55,6 +55,7 @@ struct EditMesh; struct ModifierData; struct MCol; struct ColorBand; +struct GPUVertexAttribs; /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 @@ -198,7 +199,8 @@ struct DerivedMesh { * * Also called for *final* editmode DerivedMeshes */ - void (*drawFacesSolid)(DerivedMesh *dm, int (*setMaterial)(int)); + void (*drawFacesSolid)(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs)); /* Draw all faces * o If useTwoSided, draw front and back using col arrays @@ -215,6 +217,13 @@ struct DerivedMesh { int (*setDrawOptions)(struct MTFace *tface, struct MCol *mcol, int matnr)); + /* Draw all faces with GLSL materials + * o setMaterial is called for every different material nr + * o Only if setMaterial returns true + */ + void (*drawFacesGLSL)(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs)); + /* Draw mapped faces (no color, or texture) * o Only if !setDrawOptions or * setDrawOptions(userData, mapped-face-index, drawSmooth_r) @@ -241,6 +250,15 @@ struct DerivedMesh { int index), void *userData); + /* Draw mapped faces with GLSL materials + * o setMaterial is called for every different material nr + * o setDrawOptions is called for every face + * o Only if setMaterial and setDrawOptions return true + */ + void (*drawMappedFacesGLSL)(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs), + int (*setDrawOptions)(void *userData, int index), void *userData); + /* Draw mapped edges as lines * o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge) * returns true @@ -437,6 +455,35 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb); /* determines required DerivedMesh data according to view and edit modes */ CustomDataMask get_viewedit_datamask(); +/* convert layers requested by a GLSL material to actually available layers in + * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */ +typedef struct DMVertexAttribs { + struct { + struct MTFace *array; + int emOffset, glIndex; + } tface[MAX_MTFACE]; + + struct { + struct MCol *array; + int emOffset, glIndex; + } mcol[MAX_MCOL]; + + struct { + float (*array)[3]; + int emOffset, glIndex; + } tang; + + struct { + float (*array)[3]; + int emOffset, glIndex; + } orco; + + int tottface, totmcol, tottang, totorco; +} DMVertexAttribs; + +void DM_vertex_attributes_from_gpu(DerivedMesh *dm, + struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs); + void DM_add_tangent_layer(DerivedMesh *dm); #endif diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 716eac81b55..4a13fa31f6c 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -159,7 +159,7 @@ float get_action_frame(struct Object *ob, float cframe); /* map strip time to global time (frame nr) */ float get_action_frame_inv(struct Object *ob, float cframe); /* builds a list of NlaIpoChannel with ipo values to write in datablock */ -void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, char *name, float ctime); +void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, const char *name, float ctime); /* write values returned by extract_ipochannels_from_action, returns the number of value written */ int execute_ipochannels(ListBase *lb); diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 3e45749c26a..8dee9a27f49 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -115,10 +115,6 @@ void free_editArmature(void); void docenter_new(void); int saveover(char *str); -/* image.c */ -#include "DNA_image_types.h" -void free_realtime_image(Image *ima); // has to become a callback, opengl stuff - /* ipo.c */ void copy_view3d_lock(short val); // was a hack, to make scene layer ipo's possible diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index e403fc33e06..0591937ea4c 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 247 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 2 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index e78882220a9..555b467b1d6 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -57,6 +57,7 @@ void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf); void curvemapping_premultiply(struct CurveMapping *cumap, int restore); int curvemapping_RGBA_does_something(struct CurveMapping *cumap); void curvemapping_initialize(struct CurveMapping *cumap); +void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); #endif diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 8c9634cba06..1cc336db69e 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -218,8 +218,15 @@ typedef struct Global { #define G_FILE_NO_UI (1 << 10) #define G_FILE_GAME_TO_IPO (1 << 11) #define G_FILE_GAME_MAT (1 << 12) -#define G_FILE_DIAPLAY_LISTS (1 << 13) +#define G_FILE_DISPLAY_LISTS (1 << 13) #define G_FILE_SHOW_PHYSICS (1 << 14) +#define G_FILE_GAME_MAT_GLSL (1 << 15) +#define G_FILE_GLSL_NO_LIGHTS (1 << 16) +#define G_FILE_GLSL_NO_SHADERS (1 << 17) +#define G_FILE_GLSL_NO_SHADOWS (1 << 18) +#define G_FILE_GLSL_NO_RAMPS (1 << 19) +#define G_FILE_GLSL_NO_NODES (1 << 20) +#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index d4ae76e8984..2ca4b3aa39a 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -68,7 +68,6 @@ void mball_to_mesh(struct ListBase *lb, struct Mesh *me); void nurbs_to_mesh(struct Object *ob); void free_dverts(struct MDeformVert *dvert, int totvert); void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */ -int update_realtime_texture(struct MTFace *tface, double time); void mesh_delete_material_index(struct Mesh *me, int index); void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b3b68a9b3ff..01c54663c6d 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -47,6 +47,9 @@ struct rctf; struct ListBase; struct RenderData; struct Scene; +struct GPUMaterial; +struct GPUNode; +struct GPUNodeStack; #define SOCK_IN 1 #define SOCK_OUT 2 @@ -91,6 +94,9 @@ typedef struct bNodeType { void *pynode; /* holds pointer to python script */ void *pydict; /* holds pointer to python script dictionary (scope)*/ + /* gpu */ + int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out); + } bNodeType; /* node->exec, now in use for composites (#define for break is same as ready yes) */ @@ -252,6 +258,8 @@ void nodeShaderSynchronizeID(struct bNode *node, int copyto); extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *)); +void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); + /* ************** COMPOSITE NODES *************** */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 944a9081679..ea1dc7407db 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -302,6 +302,7 @@ int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int #define PSYS_RESET_ALL 1 #define PSYS_RESET_DEPSGRAPH 2 #define PSYS_RESET_CHILDREN 3 +#define PSYS_RESET_CACHE_MISS 4 /* ParticleEffectorCache->type */ #define PSYS_EC_EFFECTOR 1 diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h new file mode 100644 index 00000000000..d58b8f58bf5 --- /dev/null +++ b/source/blender/blenkernel/BKE_suggestions.h @@ -0,0 +1,93 @@ +/** + * $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. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef BKE_SUGGESTIONS_H +#define BKE_SUGGESTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* **************************************************************************** +Suggestions should be added in sorted order although a linear sorting method is +implemented. The list is then divided up based on the prefix provided by +update_suggestions: + +Example: + Prefix: ab + aaa <-- first + aab + aba <-- firstmatch + abb <-- lastmatch + baa + bab <-- last +**************************************************************************** */ + +struct Text; + +typedef struct SuggItem { + struct SuggItem *prev, *next; + char *name; + char type; +} SuggItem; + +typedef struct SuggList { + SuggItem *first, *last; + SuggItem *firstmatch, *lastmatch; + SuggItem *selected; + int top; +} SuggList; + +/* Free all text tool memory */ +void free_texttools(); + +/* Used to identify which Text object the current tools should appear against */ +void texttool_text_set_active(Text *text); +void texttool_text_clear(); +short texttool_text_is_active(Text *text); + +/* Suggestions */ +void texttool_suggest_add(const char *name, char type); +void texttool_suggest_prefix(const char *prefix); +void texttool_suggest_clear(); +SuggItem *texttool_suggest_first(); +SuggItem *texttool_suggest_last(); +void texttool_suggest_select(SuggItem *sel); +SuggItem *texttool_suggest_selected(); +int *texttool_suggest_top(); + +/* Documentation */ +void texttool_docs_show(const char *docs); +char *texttool_docs_get(); +void texttool_docs_clear(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 6f891ab4887..002c804f17f 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -52,20 +52,24 @@ void txt_free_cut_buffer (void); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); void txt_order_cursors (struct Text *text); -int txt_find_string (struct Text *text, char *findstr); +int txt_find_string (struct Text *text, char *findstr, int wrap); int txt_has_sel (struct Text *text); int txt_get_span (struct TextLine *from, struct TextLine *to); void txt_move_up (struct Text *text, short sel); void txt_move_down (struct Text *text, short sel); void txt_move_left (struct Text *text, short sel); void txt_move_right (struct Text *text, short sel); +void txt_jump_left (struct Text *text, short sel); +void txt_jump_right (struct Text *text, short sel); void txt_move_bof (struct Text *text, short sel); void txt_move_eof (struct Text *text, short sel); void txt_move_bol (struct Text *text, short sel); void txt_move_eol (struct Text *text, short sel); void txt_move_toline (struct Text *text, unsigned int line, short sel); +void txt_move_to (struct Text *text, unsigned int line, unsigned int ch, short sel); void txt_pop_sel (struct Text *text); void txt_delete_char (struct Text *text); +void txt_delete_word (struct Text *text); void txt_copy_sel (struct Text *text); void txt_sel_all (struct Text *text); void txt_sel_line (struct Text *text); @@ -80,8 +84,10 @@ void txt_do_undo (struct Text *text); void txt_do_redo (struct Text *text); void txt_split_curline (struct Text *text); void txt_backspace_char (struct Text *text); +void txt_backspace_word (struct Text *text); int txt_add_char (struct Text *text, char add); -void txt_find_panel (struct SpaceText *st, int again); +int txt_replace_char (struct Text *text, char add); +void find_and_replace (struct SpaceText *st, short mode); void run_python_script (struct SpaceText *st); int jumptoline_interactive (struct SpaceText *st); void txt_export_to_object (struct Text *text); @@ -94,6 +100,17 @@ int setcurr_tab (struct Text *text); void convert_tabs (struct SpaceText *st, int tab); void txt_copy_clipboard (struct Text *text); void txt_paste_clipboard (struct Text *text); + +void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, char color[4], int group, int flags); +short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); +short txt_clear_markers (struct Text *text, int group, int flags); +struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); +struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); +struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker); +struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker); +struct TextMarker *txt_prev_marker_color (struct Text *text, struct TextMarker *marker); +struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker *marker); + /* Undo opcodes */ /* Simple main cursor movement */ @@ -135,6 +152,14 @@ void txt_paste_clipboard (struct Text *text); #define UNDO_COMMENT 034 #define UNDO_UNCOMMENT 035 +/* Find and replace flags */ +#define TXT_FIND_WRAP 0x01 +#define TXT_FIND_ALLTEXTS 0x02 + +/* Marker flags */ +#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */ +#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */ + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index c162a04e055..cfcae3c44bc 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -53,6 +53,7 @@ void free_plugin_tex(struct PluginTex *pit); void init_colorband(struct ColorBand *coba, int rangetype); struct ColorBand *add_colorband(int rangetype); int do_colorband(struct ColorBand *coba, float in, float out[4]); +void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size); void default_tex(struct Tex *tex); struct Tex *add_texture(char *name); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index f389521ffa0..d647a74c6e2 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -55,6 +55,8 @@ #define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) #define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) #define ELEM9(a, b, c, d, e, f, g, h, i, j) ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) ) +#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) ) +#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) ) /* shift around elements */ #define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9088b410e27..0345711c9c3 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -32,7 +32,7 @@ SET(INC ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern ../../../intern/iksolver/extern ../blenloader ../quicktime ../../../intern/bmfont ../../../extern/bullet2/src - ../nodes + ../nodes ../../../extern/glew/include ../gpu ${SDL_INC} ${ZLIB_INC} ${PYTHON_INC} diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1bb98239a68..db67251f44e 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime' incs += ' #/extern/bullet2/src' incs += ' #/intern/bmfont' incs += ' #/intern/opennl/extern' +incs += ' ../gpu #/extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 561d8d7c2a6..f4beca262d7 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -60,7 +60,7 @@ struct EditFace; char *getIpoCurveName( struct IpoCurve * icu ); void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e); +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f); void elbeemDebugOut(char *msg); void fluidsimSettingsFree(struct FluidsimSettings* sb); void fluidsimSettingsCopy(struct FluidsimSettings* sb); @@ -88,7 +88,7 @@ void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast) } -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e) +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f) { return 0; } @@ -176,10 +176,6 @@ void free_editMesh(struct EditMesh *em){} void docenter_new(void){} int saveover(char *str){ return 0;} -/* image.c */ -#include "DNA_image_types.h" -void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff - /* ipo.c */ void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible @@ -220,30 +216,6 @@ struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2) { retur void countall(void) {} - -/* IKsolver stubs */ -#include "IK_solver.h" - -IK_Segment *IK_CreateSegment(int flag) { return 0; } -void IK_FreeSegment(IK_Segment *seg) {} - -void IK_SetParent(IK_Segment *seg, IK_Segment *parent) {} -void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length) {} -void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) {} -void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) {}; -void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lower, float upper) {}; -void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) {}; - -IK_Solver *IK_CreateSolver(IK_Segment *root) { return 0; } -void IK_FreeSolver(IK_Solver *solver) {}; - -void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) {} -void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) {} -void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle) {} -float IK_SolverGetPoleAngle(IK_Solver *solver) { return 0.0f; } - -int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) { return 0; } - /* exotic.c */ int BPY_call_importloader(char *name) { diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 1dabab98a6e..328dcada01a 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -88,6 +88,10 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + // headers for fluidsim bobj meshes #include #include "LBM_fluidsim.h" @@ -411,6 +415,8 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices) CustomData_swap(&dm->faceData, index, corner_indices); } +/// + static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -894,6 +900,162 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } +static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs), + int (*setDrawOptions)(void *userData, int index), void *userData) +{ + EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditMesh *em= emdm->em; + float (*vertexCos)[3]= emdm->vertexCos; + float (*vertexNos)[3]= emdm->vertexNos; + EditVert *eve; + EditFace *efa; + DMVertexAttribs attribs; + GPUVertexAttribs gattribs; + MTFace *tf; + int transp, new_transp, orig_transp, tfoffset; + int i, b, matnr, new_matnr, dodraw, layer; + + dodraw = 0; + matnr = -1; + + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); + tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; + + memset(&attribs, 0, sizeof(attribs)); + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + for (i=0,eve=em->verts.first; eve; eve= eve->next) + eve->tmp.l = (long) i++; + +#define PASSATTRIB(efa, eve, vert) { \ + if(attribs.totorco) { \ + float *orco = attribs.orco.array[eve->tmp.l]; \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[i*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { + int drawSmooth= (efa->flag & ME_SMOOTH); + + if(setDrawOptions && !setDrawOptions(userData, i)) + continue; + + new_matnr = efa->mat_nr + 1; + if(new_matnr != matnr) { + dodraw = setMaterial(matnr = new_matnr, &gattribs); + if(dodraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + if(tfoffset != -1) { + tf = (MTFace*)((char*)efa->data)+tfoffset; + new_transp = tf->transp; + + if(new_transp != transp) { + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + } + } + + if(dodraw) { + glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + if (!drawSmooth) { + if(vertexCos) glNormal3fv(emdm->faceNos[i]); + else glNormal3fv(efa->n); + + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + else glVertex3fv(efa->v1->co); + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + else glVertex3fv(efa->v2->co); + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + else glVertex3fv(efa->v3->co); + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + else glVertex3fv(efa->v4->co); + } + } else { + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + } + else { + glNormal3fv(efa->v1->no); + glVertex3fv(efa->v1->co); + } + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + } + else { + glNormal3fv(efa->v2->no); + glVertex3fv(efa->v2->co); + } + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + } + else { + glNormal3fv(efa->v3->no); + glVertex3fv(efa->v3->co); + } + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + } + else { + glNormal3fv(efa->v4->no); + glVertex3fv(efa->v4->co); + } + } + } + glEnd(); + } + } +} + +static void emDM_drawFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs)) +{ + dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1099,6 +1261,43 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) } } +static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) +{ + EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditMesh *em= emdm->em; + EditFace *efa; + char *data, *emdata; + void *datalayer; + int index, offset, size; + + datalayer = DM_get_face_data_layer(dm, type); + if(datalayer) + return datalayer; + + /* layers are store per face for editmesh, we convert to a temporary + * data layer array in the derivedmesh when these are requested */ + if(type == CD_MTFACE || type == CD_MCOL) { + index = CustomData_get_layer_index(&em->fdata, type); + + if(index != -1) { + offset = em->fdata.layers[index].offset; + size = CustomData_sizeof(type); + + DM_add_face_layer(dm, type, CD_CALLOC, NULL); + index = CustomData_get_layer_index(&dm->faceData, type); + dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; + + data = datalayer = DM_get_face_data_layer(dm, type); + for(efa=em->faces.first; efa; efa=efa->next, data+=size) { + emdata = CustomData_em_get(&em->fdata, efa->data, type); + memcpy(data, emdata, size); + } + } + } + + return datalayer; +} + static void emDM_release(DerivedMesh *dm) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1134,6 +1333,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, emdm->dm.copyVertArray = emDM_copyVertArray; emdm->dm.copyEdgeArray = emDM_copyEdgeArray; emdm->dm.copyFaceArray = emDM_copyFaceArray; + emdm->dm.getFaceDataArray = emDM_getFaceDataArray; emdm->dm.foreachMappedVert = emDM_foreachMappedVert; emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; @@ -1144,7 +1344,9 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; emdm->dm.drawMappedFaces = emDM_drawMappedFaces; emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; + emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; emdm->dm.drawFacesTex = emDM_drawFacesTex; + emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; emdm->dm.drawUVEdges = emDM_drawUVEdges; emdm->dm.release = emDM_release; @@ -1574,7 +1776,7 @@ static void vDM_drawUVEdges(DerivedMesh *dm) } /* draw all VerseFaces */ -static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) +static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { VDerivedMesh *vdm = (VDerivedMesh*)dm; struct VerseFace *vface; @@ -1674,6 +1876,8 @@ static void vDM_drawMappedFacesTex( int (*setDrawParams)(void *userData, int index), void *userData) { + /* not supported yet */ + vDM_drawFacesTex(dm, NULL); } /**/ @@ -1815,19 +2019,23 @@ CustomDataMask get_viewedit_datamask() ScrArea *sa; /* check if we need tfaces & mcols due to face select or texture paint */ - if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) { + if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - } else { - /* check if we need tfaces & mcols due to view mode */ - for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { - if(sa->spacetype == SPACE_VIEW3D) { - View3D *view = sa->spacedata.first; - if(view->drawtype == OB_SHADED) { - /* this includes normals for mesh_create_shadedColors */ - mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; - } - if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { - mask |= CD_MASK_MTFACE | CD_MASK_MCOL; + + /* check if we need tfaces & mcols due to view mode */ + for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { + if(sa->spacetype == SPACE_VIEW3D) { + View3D *view = sa->spacedata.first; + if(view->drawtype == OB_SHADED) { + /* this includes normals for mesh_create_shadedColors */ + mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; + } + if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { + mask |= CD_MASK_MTFACE | CD_MASK_MCOL; + + if((G.fileflags & G_FILE_GAME_MAT) && + (G.fileflags & G_FILE_GAME_MAT_GLSL)) { + mask |= CD_MASK_ORCO; } } } @@ -1840,13 +2048,41 @@ CustomDataMask get_viewedit_datamask() return mask; } -static DerivedMesh *create_orco_dm(Object *ob, Mesh *me) +static float *get_editmesh_orco_verts(EditMesh *em) +{ + EditVert *eve; + float *orco; + int a, totvert; + + /* these may not really be the orco's, but it's only for preview. + * could be solver better once, but isn't simple */ + + totvert= 0; + for(eve=em->verts.first; eve; eve=eve->next) + totvert++; + + orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco"); + + for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3) + VECCOPY(orco+a, eve->co); + + return orco; +} + +static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em) { DerivedMesh *dm; float (*orco)[3]; - dm= CDDM_from_mesh(me, ob); - orco= (float(*)[3])get_mesh_orco_verts(ob); + if(em) { + dm= CDDM_from_editmesh(em, me); + orco= (float(*)[3])get_editmesh_orco_verts(em); + } + else { + dm= CDDM_from_mesh(me, ob); + orco= (float(*)[3])get_mesh_orco_verts(ob); + } + CDDM_apply_vert_coords(dm, orco); CDDM_calc_normals(dm); MEM_freeN(orco); @@ -1854,7 +2090,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me) return dm; } -static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) +static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm) { float (*orco)[3], (*layerorco)[3]; int totvert; @@ -1869,8 +2105,10 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) else dm->getVertCos(dm, orco); } - else - orco= (float(*)[3])get_mesh_orco_verts(ob); + else { + if(em) orco= (float(*)[3])get_editmesh_orco_verts(em); + else orco= (float(*)[3])get_mesh_orco_verts(ob); + } transform_mesh_orco_verts(ob->data, orco, totvert, 0); @@ -2016,7 +2254,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if(dm && mti->requiredDataMask) { mask = mti->requiredDataMask(md); if(mask & CD_MASK_ORCO) - add_orco_dm(ob, dm, orcodm); + add_orco_dm(ob, NULL, dm, orcodm); } /* How to apply modifier depends on (a) what we already have as @@ -2069,7 +2307,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], mask= (CustomDataMask)curr->link; if(mask & CD_MASK_ORCO) { if(!orcodm) - orcodm= create_orco_dm(ob, me); + orcodm= create_orco_dm(ob, me, NULL); mask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, mask); @@ -2146,10 +2384,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], /* add an orco layer if needed */ if(dataMask & CD_MASK_ORCO) { - add_orco_dm(ob, finaldm, orcodm); + add_orco_dm(ob, NULL, finaldm, orcodm); if(deform_r && *deform_r) - add_orco_dm(ob, *deform_r, NULL); + add_orco_dm(ob, NULL, *deform_r, NULL); } *final_r = finaldm; @@ -2205,7 +2443,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, EditMesh *em = G.editMesh; ModifierData *md; float (*deformedVerts)[3] = NULL; - DerivedMesh *dm; + CustomDataMask mask; + DerivedMesh *dm, *orcodm = NULL; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL); LinkNode *datamasks, *curr; @@ -2230,6 +2469,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, if(!editmesh_modifier_is_enabled(md, dm)) continue; + /* add an orco layer if needed by this modifier */ + if(dm && mti->requiredDataMask) { + mask = mti->requiredDataMask(md); + if(mask & CD_MASK_ORCO) + add_orco_dm(ob, em, dm, orcodm); + } + /* How to apply modifier depends on (a) what we already have as * a result of previous modifiers (could be a DerivedMesh or just * deformed vertices) and (b) what type the modifier is. @@ -2280,6 +2526,23 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, } } + /* create an orco derivedmesh in parallel */ + mask= (CustomDataMask)curr->link; + if(mask & CD_MASK_ORCO) { + if(!orcodm) + orcodm= create_orco_dm(ob, ob->data, em); + + mask &= ~CD_MASK_ORCO; + DM_set_only_copy(orcodm, mask); + ndm = mti->applyModifierEM(md, ob, em, orcodm); + + if(ndm) { + /* if the modifier returned a new dm, release the old one */ + if(orcodm && orcodm != ndm) orcodm->release(orcodm); + orcodm = ndm; + } + } + /* set the DerivedMesh to only copy needed data */ DM_set_only_copy(dm, (CustomDataMask)curr->link); @@ -2338,6 +2601,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, deformedVerts = NULL; } + /* add an orco layer if needed */ + if(dataMask & CD_MASK_ORCO) + add_orco_dm(ob, em, *final_r, orcodm); + + if(orcodm) + orcodm->release(orcodm); + if(deformedVerts) MEM_freeN(deformedVerts); } @@ -2632,7 +2902,7 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c old->release(old); if(dataMask & CD_MASK_ORCO) - add_orco_dm(ob, *dm, NULL); + add_orco_dm(ob, NULL, *dm, NULL); /* Restore the original verts */ me->mr->newlvl= BLI_countlist(&me->mr->levels); @@ -2847,6 +3117,8 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo return numleft; } +/* ******************* GLSL ******************** */ + void DM_add_tangent_layer(DerivedMesh *dm) { /* mesh vars */ @@ -2967,6 +3239,91 @@ void DM_add_tangent_layer(DerivedMesh *dm) MEM_freeN(vtangents); } +void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs) +{ + CustomData *vdata, *fdata, *tfdata = NULL; + int a, b, layer; + + /* From the layers requested by the GLSL shader, figure out which ones are + * actually available for this derivedmesh, and retrieve the pointers */ + + memset(attribs, 0, sizeof(DMVertexAttribs)); + + vdata = &dm->vertData; + fdata = &dm->faceData; + + /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we + * can use offsets instead */ + if(dm->release == emDM_release) + tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata; + else + tfdata = fdata; + + /* add a tangent layer if necessary */ + for(b = 0; b < gattribs->totlayer; b++) + if(gattribs->layer[b].type == CD_TANGENT) + if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1) + DM_add_tangent_layer(dm); + + for(b = 0; b < gattribs->totlayer; b++) { + if(gattribs->layer[b].type == CD_MTFACE) { + /* uv coordinates */ + if(gattribs->layer[b].name[0]) + layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE, + gattribs->layer[b].name); + else + layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE); + + if(layer != -1) { + a = attribs->tottface++; + + attribs->tface[a].array = tfdata->layers[layer].data; + attribs->tface[a].emOffset = tfdata->layers[layer].offset; + attribs->tface[a].glIndex = gattribs->layer[b].glindex; + } + } + else if(gattribs->layer[b].type == CD_MCOL) { + /* vertex colors */ + if(gattribs->layer[b].name[0]) + layer = CustomData_get_named_layer_index(tfdata, CD_MCOL, + gattribs->layer[b].name); + else + layer = CustomData_get_active_layer_index(tfdata, CD_MCOL); + + if(layer != -1) { + a = attribs->totmcol++; + + attribs->mcol[a].array = tfdata->layers[layer].data; + attribs->mcol[a].emOffset = tfdata->layers[layer].offset; + attribs->mcol[a].glIndex = gattribs->layer[b].glindex; + } + } + else if(gattribs->layer[b].type == CD_TANGENT) { + /* tangents */ + layer = CustomData_get_layer_index(fdata, CD_TANGENT); + + if(layer != -1) { + attribs->tottang = 1; + + attribs->tang.array = fdata->layers[layer].data; + attribs->tang.emOffset = fdata->layers[layer].offset; + attribs->tang.glIndex = gattribs->layer[b].glindex; + } + } + else if(gattribs->layer[b].type == CD_ORCO) { + /* original coordinates */ + layer = CustomData_get_layer_index(vdata, CD_ORCO); + + if(layer != -1) { + attribs->totorco = 1; + + attribs->orco.array = vdata->layers[layer].data; + attribs->orco.emOffset = vdata->layers[layer].offset; + attribs->orco.glIndex = gattribs->layer[b].glindex; + } + } + } +} /* ************************* fluidsim bobj file handling **************************** */ diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 74c6c551a83..8921ea5d3b7 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) # OpenGL and Python +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) @@ -74,6 +75,9 @@ CPPFLAGS += -I$(NAN_ZLIB)/include #path to nodes CPPFLAGS += -I../../nodes +#path to gpu +CPPFLAGS += -I../../gpu + # path to our own external headerfiles CPPFLAGS += -I.. diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 5b96bf11056..043ede5987a 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -347,6 +347,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); QUATCOPY(pchan->quat, chan->quat); + Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat); + Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat); pchan->flag= chan->flag; con= chan->constraints.first; @@ -860,7 +862,7 @@ typedef struct NlaIpoChannel { int type; } NlaIpoChannel; -void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime) +void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) { bActionChannel *achan= get_action_channel(act, name); IpoCurve *icu; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 1592c3e5504..ceb0e132ff9 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -303,7 +303,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4]; + float mat[4][4], tmat[4][4]; if(ob->dup_group==NULL) return; group= ob->dup_group; @@ -320,7 +320,15 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if(go->ob!=ob) { - Mat4MulMat4(mat, go->ob->obmat, ob->obmat); + /* Group Dupli Offset, should apply after everything else */ + if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) { + Mat4CpyMat4(tmat, go->ob->obmat); + VecSubf(tmat[3], tmat[3], group->dupli_ofs); + Mat4MulMat4(mat, tmat, ob->obmat); + } else { + Mat4MulMat4(mat, go->ob->obmat, ob->obmat); + } + dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); dob->no_draw= (dob->origlay & group->layer)==0; @@ -775,6 +783,10 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ hair= (totchild == 0 || psys->childcache) && psys->pathcache; if(!hair) return; + + /* we use cache, update totchild according to cached data */ + totchild = psys->totchildcache; + totpart = psys->totcached; } psys->lattice = psys_get_lattice(par, psys); @@ -857,6 +869,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ } VECCOPY(pamat[3], cache->co); + pamat[3][3]= 1.0f; + } else if(step_nbr) { /* other keys */ @@ -1059,7 +1073,8 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, } } -/* note; group dupli's already set transform matrix. see note in group_duplilist() */ +/* Returns a list of DupliObject + * note; group dupli's already set transform matrix. see note in group_duplilist() */ ListBase *object_duplilist(Scene *sce, Object *ob) { ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index fb7d59c137a..720ed0513ed 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1690,7 +1690,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) were executed & assigned. Now as last we do an IK pass */ static void execute_posetree(Object *ob, PoseTree *tree) { - float R_parmat[3][3]; + float R_parmat[3][3], identity[3][3]; float iR_parmat[3][3]; float R_bonemat[3][3]; float goalrot[3][3], goalpos[3]; @@ -1699,7 +1699,8 @@ static void execute_posetree(Object *ob, PoseTree *tree) float irest_basis[3][3], full_basis[3][3]; float end_pose[4][4], world_pose[4][4]; float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - int a, flag, hasstretch=0; + float resultinf=0.0f; + int a, flag, hasstretch=0, resultblend=0; bPoseChannel *pchan; IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; @@ -1844,6 +1845,12 @@ static void execute_posetree(Object *ob, PoseTree *tree) Mat4MulMat4(goal, rootmat, goalinv); VECCOPY(polepos, goal[3]); poleconstrain= 1; + + /* for pole targets, we blend the result of the ik solver + * instead of the target position, otherwise we can't get + * a smooth transition */ + resultblend= 1; + resultinf= target->con->enforce; if(data->flag & CONSTRAINT_IK_GETANGLE) { poleangledata= data; @@ -1853,7 +1860,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) } /* do we need blending? */ - if (target->con->enforce!=1.0) { + if (!resultblend && target->con->enforce!=1.0) { float q1[4], q2[4], q[4]; float fac= target->con->enforce; float mfac= 1.0-fac; @@ -1903,7 +1910,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); if(hasstretch) ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - + for(a=0; atotchannel; a++) { IK_GetBasisChange(iktree[a], tree->basis_change[a]); @@ -1931,6 +1938,12 @@ static void execute_posetree(Object *ob, PoseTree *tree) VecMulf(tree->basis_change[a][1], stretch); VecMulf(tree->basis_change[a][2], stretch); } + + if(resultblend && resultinf!=1.0f) { + Mat3One(identity); + Mat3BlendMat3(tree->basis_change[a], identity, + tree->basis_change[a], resultinf); + } IK_FreeSegment(iktree[a]); } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index aca51e56c6e..1fe6447752e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -525,6 +525,7 @@ typedef struct UndoElem { char str[FILE_MAXDIR+FILE_MAXFILE]; char name[MAXUNDONAME]; MemFile memfile; + uintptr_t undosize; } UndoElem; static ListBase undobase={NULL, NULL}; @@ -555,6 +556,7 @@ static int read_undosave(UndoElem *uel) /* name can be a dynamic string */ void BKE_write_undo(char *name) { + uintptr_t maxmem, totmem, memused; int nr, success; UndoElem *uel; @@ -616,8 +618,36 @@ void BKE_write_undo(char *name) if(curundo->prev) prevfile= &(curundo->prev->memfile); + memused= MEM_get_memory_in_use(); success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err); - + curundo->undosize= MEM_get_memory_in_use() - memused; + } + + if(U.undomemory != 0) { + /* limit to maximum memory (afterwards, we can't know in advance) */ + totmem= 0; + maxmem= ((uintptr_t)U.undomemory)*1024*1024; + + /* keep at least two (original + other) */ + uel= undobase.last; + while(uel && uel->prev) { + totmem+= uel->undosize; + if(totmem>maxmem) break; + uel= uel->prev; + } + + if(uel) { + if(uel->prev && uel->prev->prev) + uel= uel->prev; + + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + BLI_remlink(&undobase, first); + /* the merge is because of compression */ + BLO_merge_memfile(&first->memfile, &first->next->memfile); + MEM_freeN(first); + } + } } } @@ -683,14 +713,14 @@ char *BKE_undo_menu_string(void) UndoElem *uel; DynStr *ds= BLI_dynstr_new(); char *menu; - + BLI_dynstr_append(ds, "Global Undo History %t"); for(uel= undobase.first; uel; uel= uel->next) { BLI_dynstr_append(ds, "|"); BLI_dynstr_append(ds, uel->name); } - + menu= BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 472df3d0f26..9d5dcb8109b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -58,6 +58,10 @@ #include "MEM_guardedalloc.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + #include #include @@ -243,7 +247,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) glEnd(); } -static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) +static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; @@ -271,7 +275,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) || new_shademodel != shademodel) { glEnd(); - drawCurrentMat = setMaterial(matnr = new_matnr); + drawCurrentMat = setMaterial(matnr = new_matnr, NULL); glShadeModel(shademodel = new_shademodel); glBegin(glmode = new_glmode); @@ -556,6 +560,134 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } +static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) dm; + GPUVertexAttribs gattribs; + DMVertexAttribs attribs; + MVert *mvert = cddm->mvert; + MFace *mface = cddm->mface; + MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); + float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + int a, b, dodraw, smoothnormal, matnr, new_matnr; + int transp, new_transp, orig_transp; + int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + + matnr = -1; + smoothnormal = 0; + dodraw = 0; + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + + memset(&attribs, 0, sizeof(attribs)); + + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + + for(a = 0; a < dm->numFaceData; a++, mface++) { + new_matnr = mface->mat_nr + 1; + + if(new_matnr != matnr) { + glEnd(); + + dodraw = setMaterial(matnr = new_matnr, &gattribs); + if(dodraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + + glBegin(GL_QUADS); + } + + if(!dodraw) { + continue; + } + else if(setDrawOptions) { + orig = index[a]; + + if(orig == ORIGINDEX_NONE) + continue; + else if(!setDrawOptions(userData, orig)) + continue; + } + + if(tf) { + new_transp = tf[a].transp; + + if(new_transp != transp) { + glEnd(); + + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + + glBegin(GL_QUADS); + } + } + + smoothnormal = (mface->flag & ME_SMOOTH); + + if(!smoothnormal) { + if(nors) { + glNormal3fv(nors[a]); + } + else { + /* TODO ideally a normal layer should always be available */ + float nor[3]; + if(mface->v4) { + CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, mvert[mface->v4].co, + nor); + } else { + CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, nor); + } + glNormal3fv(nor); + } + } + +#define PASSVERT(index, vert) { \ + if(attribs.totorco) \ + glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = &attribs.tface[b].array[a]; \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[a*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ + if(smoothnormal) \ + glNormal3sv(mvert[index].no); \ + glVertex3fv(mvert[index].co); \ +} + + PASSVERT(mface->v1, 0); + PASSVERT(mface->v2, 1); + PASSVERT(mface->v3, 2); + if(mface->v4) + PASSVERT(mface->v4, 3) + else + PASSVERT(mface->v3, 2) + +#undef PASSVERT + } + glEnd(); + + glShadeModel(GL_FLAT); +} + +static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) +{ + dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -713,8 +845,10 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->drawFacesSolid = cdDM_drawFacesSolid; dm->drawFacesColored = cdDM_drawFacesColored; dm->drawFacesTex = cdDM_drawFacesTex; + dm->drawFacesGLSL = cdDM_drawFacesGLSL; dm->drawMappedFaces = cdDM_drawMappedFaces; dm->drawMappedFacesTex = cdDM_drawMappedFacesTex; + dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL; dm->foreachMappedVert = cdDM_foreachMappedVert; dm->foreachMappedEdge = cdDM_foreachMappedEdge; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 295b8fe3552..45b8bb7935c 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -730,3 +730,24 @@ void curvemapping_initialize(CurveMapping *cumap) curvemap_make_table(cumap->cm+a, &cumap->clipr); } } + +void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size) +{ + int a; + + *size = CM_TABLE+1; + *array = MEM_callocN(sizeof(float)*(*size)*4, "CurveMapping"); + curvemapping_initialize(cumap); + + for(a=0; a<*size; a++) { + if(cumap->cm[0].table) + (*array)[a*4+0]= cumap->cm[0].table[a].y; + if(cumap->cm[1].table) + (*array)[a*4+1]= cumap->cm[1].table[a].y; + if(cumap->cm[2].table) + (*array)[a*4+2]= cumap->cm[2].table[a].y; + if(cumap->cm[3].table) + (*array)[a*4+3]= cumap->cm[3].table[a].y; + } +} + diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 1d7d4d1fda0..5f72bf316ab 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -369,19 +369,12 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */ { /* world to pose */ - if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_LOCAL || to==CONSTRAINT_SPACE_PARLOCAL) { - Mat4Invert(imat, ob->obmat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, imat); - } + Mat4Invert(imat, ob->obmat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, imat); - /* pose to local */ - if (to == CONSTRAINT_SPACE_LOCAL) { - /* call self with slightly different values */ - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); - } - /* pose to local + parent */ - else if (to == CONSTRAINT_SPACE_PARLOCAL) { + /* use pose-space as stepping stone for other spaces... */ + if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } @@ -447,68 +440,65 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 break; case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ { - /* local to pose */ - if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) { - /* do inverse procedure that was done for pose to local */ - if (pchan->bone) { - /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ - if (pchan->parent) { - float offs_bone[4][4]; + /* local to pose - do inverse procedure that was done for pose to local */ + if (pchan->bone) { + /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ + if (pchan->parent) { + float offs_bone[4][4]; + + /* construct offs_bone the same way it is done in armature.c */ + Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); + VECCOPY(offs_bone[3], pchan->bone->head); + offs_bone[3][1]+= pchan->bone->parent->length; + + if (pchan->bone->flag & BONE_HINGE) { + /* pose_mat = par_pose-space_location * chan_mat */ + float tmat[4][4]; - /* construct offs_bone the same way it is done in armature.c */ - Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); - VECCOPY(offs_bone[3], pchan->bone->head); - offs_bone[3][1]+= pchan->bone->parent->length; - if (pchan->bone->flag & BONE_HINGE) { - /* pose_mat = par_pose-space_location * chan_mat */ - float tmat[4][4]; - - /* the rotation of the parent restposition */ - Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat); - - /* the location of actual parent transform */ - VECCOPY(tmat[3], offs_bone[3]); - offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; - Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]); - - Mat4MulMat4(diff_mat, offs_bone, tmat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, diff_mat); - } - else { - /* pose_mat = par_pose_mat * bone_mat * chan_mat */ - Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, diff_mat); - } + /* the rotation of the parent restposition */ + Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat); + /* the location of actual parent transform */ + VECCOPY(tmat[3], offs_bone[3]); + offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; + Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]); + + Mat4MulMat4(diff_mat, offs_bone, tmat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, diff_mat); } else { - Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); - + /* pose_mat = par_pose_mat * bone_mat * chan_mat */ + Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat); Mat4CpyMat4(tempmat, mat); Mat4MulMat4(mat, tempmat, diff_mat); } } + else { + Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); + + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, diff_mat); + } } - /* local to world */ - if (to == CONSTRAINT_SPACE_WORLD) { + + /* use pose-space as stepping stone for other spaces */ + if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); - } + } } break; case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */ { - /* local to pose */ - if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) { - if (pchan->bone) { - Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, diff_mat, tempmat); - } + /* local + parent to pose */ + if (pchan->bone) { + Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, diff_mat, tempmat); } - /* local to world */ - if (to == CONSTRAINT_SPACE_WORLD) { + + /* use pose-space as stepping stone for other spaces */ + if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 80f450000bb..1be0a2aafdb 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1924,8 +1924,10 @@ static void dag_object_time_update_flags(Object *ob) } } } - else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; - else if(ob->parent) { + + if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; + + if(ob->parent) { /* motion path or bone child */ if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB; } @@ -1946,10 +1948,11 @@ static void dag_object_time_update_flags(Object *ob) } } } - else if(modifiers_isSoftbodyEnabled(ob)) ob->recalc |= OB_RECALC_DATA; - else if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; - else if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; - else { + + if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; + if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; + + { Mesh *me; Curve *cu; Lattice *lt; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 0842e55a0ea..327008c60de 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -267,7 +267,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) hit.dist = len + FLT_EPSILON; // check if the way is blocked - if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0) + if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) { // visibility is only between 0 and 1, calculated from 1-absorption visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01))); @@ -406,12 +406,15 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); + Normalize(mag_vec); + VecMulf(mag_vec,force_val*falloff); VecAddf(field,field,mag_vec); break; case PFIELD_VORTEX: Crossf(mag_vec,eff_vel,vec_to_part); + Normalize(mag_vec); VecMulf(mag_vec,force_val*distance*falloff); @@ -425,6 +428,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, /* magnetic field of a moving charge */ Crossf(temp,eff_vel,vec_to_part); + Normalize(temp); + Crossf(temp2,velocity,temp); VecAddf(mag_vec,mag_vec,temp2); @@ -437,6 +442,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); + Normalize(mag_vec); + VecMulf(mag_vec,force_val*falloff); VecSubf(field,field,mag_vec); @@ -451,6 +458,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); + Normalize(mag_vec); + VecMulf(mag_vec,charge*force_val*falloff); VecAddf(field,field,mag_vec); break; @@ -535,10 +544,6 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float where_is_object_time(ob,cur_time); /* use center of object for distance calculus */ - obloc= ob->obmat[3]; - VECSUB(vect_to_vert, obloc, opco); - distance = VecLength(vect_to_vert); - VecSubf(vec_to_part, opco, ob->obmat[3]); distance = VecLength(vec_to_part); diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index fb48c875995..479be2ee644 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -2632,17 +2632,17 @@ static void write_videoscape_mesh(Object *ob, char *str) if(evl->v4==0) { fprintf(fp, "3 %ld %ld %ld 0x%x\n", - evl->v1->tmp.l, - evl->v2->tmp.l, - evl->v3->tmp.l, + (long int) evl->v1->tmp.l, + (long int) evl->v2->tmp.l, + (long int) evl->v3->tmp.l, kleur[evl->mat_nr]); } else { fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - evl->v1->tmp.l, - evl->v2->tmp.l, - evl->v3->tmp.l, - evl->v4->tmp.l, + (long int) evl->v1->tmp.l, + (long int) evl->v2->tmp.l, + (long int) evl->v3->tmp.l, + (long int) evl->v4->tmp.l, kleur[evl->mat_nr]); } evl= evl->next; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 07537e3a81c..27fa00ac239 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -53,6 +53,7 @@ #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_camera_types.h" +#include "DNA_sequence_types.h" #include "DNA_texture_types.h" #include "DNA_userdef_types.h" @@ -77,15 +78,15 @@ #include "RE_pipeline.h" -/* bad level; call to free_realtime_image */ -#include "BKE_bad_level_calls.h" - /* for stamp drawing to an image */ #include "BMF_Api.h" #include "blendef.h" #include "BSE_time.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + #include "BLO_sys_types.h" // for intptr_t support /* max int, to indicate we don't store sequences in ibuf */ @@ -240,7 +241,7 @@ static void image_free_buffers(Image *ima) ima->rr= NULL; } - free_realtime_image(ima); + GPU_free_image(ima); ima->ok= IMA_OK; } @@ -620,7 +621,7 @@ void free_old_images() This gives textures a "second chance" to be used before dying. */ if(ima->bindcode || ima->repbind) { - free_realtime_image(ima); + GPU_free_image(ima); ima->lastused = ctime; } /* Otherwise, just kill the buffers */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 4af25ee99e7..e8a25aaaf80 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1390,6 +1390,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= ma->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= ma->mtex[9]; + else if(icu->adrcode & MA_MAP12) mtex= ma->mtex[11]; + else if(icu->adrcode & MA_MAP11) mtex= ma->mtex[10]; + else if(icu->adrcode & MA_MAP13) mtex= ma->mtex[12]; + else if(icu->adrcode & MA_MAP14) mtex= ma->mtex[13]; + else if(icu->adrcode & MA_MAP15) mtex= ma->mtex[14]; + else if(icu->adrcode & MA_MAP16) mtex= ma->mtex[15]; + else if(icu->adrcode & MA_MAP17) mtex= ma->mtex[16]; + else if(icu->adrcode & MA_MAP18) mtex= ma->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); @@ -1479,7 +1487,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= wo->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= wo->mtex[9]; - + else if(icu->adrcode & MA_MAP11) mtex= wo->mtex[10]; + else if(icu->adrcode & MA_MAP12) mtex= wo->mtex[11]; + else if(icu->adrcode & MA_MAP13) mtex= wo->mtex[12]; + else if(icu->adrcode & MA_MAP14) mtex= wo->mtex[13]; + else if(icu->adrcode & MA_MAP15) mtex= wo->mtex[14]; + else if(icu->adrcode & MA_MAP16) mtex= wo->mtex[15]; + else if(icu->adrcode & MA_MAP17) mtex= wo->mtex[16]; + else if(icu->adrcode & MA_MAP18) mtex= wo->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); } @@ -1524,6 +1539,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= la->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= la->mtex[9]; + else if(icu->adrcode & MA_MAP11) mtex= la->mtex[10]; + else if(icu->adrcode & MA_MAP12) mtex= la->mtex[11]; + else if(icu->adrcode & MA_MAP13) mtex= la->mtex[12]; + else if(icu->adrcode & MA_MAP14) mtex= la->mtex[13]; + else if(icu->adrcode & MA_MAP15) mtex= la->mtex[14]; + else if(icu->adrcode & MA_MAP16) mtex= la->mtex[15]; + else if(icu->adrcode & MA_MAP17) mtex= la->mtex[16]; + else if(icu->adrcode & MA_MAP18) mtex= la->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); @@ -1672,6 +1695,8 @@ void set_icu_vars(IpoCurve *icu) icu->ymax= 5.0; break; case MA_ADD: icu->ymax= 1.0; break; + case MA_EMIT: + icu->ymax= 2.0; break; default: icu->ymax= 1.0; break; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 3983eecdaba..f05b84f6e90 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -61,6 +61,8 @@ #include "BPY_extern.h" +#include "GPU_material.h" + /* used in UI and render */ Material defmaterial; @@ -96,6 +98,9 @@ void free_material(Material *ma) ntreeFreeTree(ma->nodetree); MEM_freeN(ma->nodetree); } + + if(ma->gpumaterial.first) + GPU_material_free(ma); } void init_material(Material *ma) @@ -207,6 +212,8 @@ Material *copy_material(Material *ma) if(ma->nodetree) { man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */ } + + man->gpumaterial.first= man->gpumaterial.last= NULL; return man; } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 43e48c3bacd..77b9ea4fa2d 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -79,45 +79,6 @@ #include "BLI_editVert.h" #include "BLI_arithb.h" -int update_realtime_texture(MTFace *tface, double time) -{ - Image *ima; - int inc = 0; - float diff; - int newframe; - - ima = tface->tpage; - - if (!ima) - return 0; - - if (ima->lastupdate<0) - ima->lastupdate = 0; - - if (ima->lastupdate>time) - ima->lastupdate=(float)time; - - if(ima->tpageflag & IMA_TWINANIM) { - if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; - - /* check: is the bindcode not in the array? Then free. (still to do) */ - - diff = (float)(time-ima->lastupdate); - - inc = (int)(diff*(float)ima->animspeed); - - ima->lastupdate+=((float)inc/(float)ima->animspeed); - - newframe = ima->lastframe+inc; - - if (newframe > (int)ima->twend) - newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); - - ima->lastframe = newframe; - } - return inc; -} - void mesh_update_customdata_pointers(Mesh *me) { me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index e8453ef934c..97e3bc9e9bd 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -794,12 +794,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { Curve *cu = amd->curve_ob->data; if(cu) { + float tmp_mat[3][3]; + float scale; + + object_to_mat3(amd->curve_ob, tmp_mat); + scale = Mat3ToScalef(tmp_mat); + if(!cu->path) { cu->flag |= CU_PATH; // needed for path & bevlist makeDispListCurveTypes(amd->curve_ob, 0); } if(cu->path) - length = cu->path->totdist; + length = scale*cu->path->totdist; } } @@ -5288,6 +5294,11 @@ static void softbodyModifier_deformVerts( sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); } +static int softbodyModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + /* Cloth */ @@ -7637,6 +7648,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_RequiresOriginalData; mti->deformVerts = softbodyModifier_deformVerts; + mti->dependsOnTime = softbodyModifier_dependsOnTime; mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_Nonconstructive; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 4e36df35a14..94a21cdd5df 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -68,6 +68,9 @@ #include "SHD_node.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + static ListBase empty_list = {NULL, NULL}; ListBase node_all_composit = {NULL, NULL}; ListBase node_all_shaders = {NULL, NULL}; @@ -2352,6 +2355,117 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeEndExecTree(ntree); } +/* GPU material from shader nodes */ + +static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) +{ + bNodeSocket *sock; + int i; + + for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { + memset(&gs[i], 0, sizeof(gs[i])); + + QUATCOPY(gs[i].vec, ns[i]->vec); + gs[i].link= ns[i]->data; + + if (sock->type == SOCK_VALUE) + gs[i].type= GPU_FLOAT; + else if (sock->type == SOCK_VECTOR) + gs[i].type= GPU_VEC3; + else if (sock->type == SOCK_RGBA) + gs[i].type= GPU_VEC4; + else + gs[i].type= GPU_NONE; + + gs[i].name = ""; + gs[i].hasinput= ns[i]->hasinput && ns[i]->data; + gs[i].hasoutput= ns[i]->hasinput && ns[i]->data; + gs[i].sockettype= ns[i]->sockettype; + } + + gs[i].type= GPU_NONE; +} + +static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) +{ + bNodeSocket *sock; + int i; + + for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { + ns[i]->data= gs[i].link; + ns[i]->hasinput= gs[i].hasinput && gs[i].link; + ns[i]->hasoutput= gs[i].hasoutput; + ns[i]->sockettype= gs[i].sockettype; + } +} + +static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out) +{ + bNode *node; + bNodeTree *ntree= (bNodeTree *)gnode->id; + bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ + bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ + GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; + int doit = 0; + + if(ntree==NULL) return; + + stack+= gnode->stack_index; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->gpufunc) { + group_node_get_stack(node, stack, nsin, nsout, in, out); + + doit = 0; + + /* for groups, only execute outputs for edited group */ + if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { + if(gnode->flag & NODE_GROUP_EDIT) + if(node->flag & NODE_DO_OUTPUT) + doit = 1; + } + else + doit = 1; + + if(doit) { + gpu_from_node_stack(&node->inputs, nsin, gpuin); + gpu_from_node_stack(&node->outputs, nsout, gpuout); + if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) + data_from_gpu_stack(&node->outputs, nsout, gpuout); + } + } + } +} + +void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) +{ + bNode *node; + bNodeStack *stack; + bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ + bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ + GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; + + if((ntree->init & NTREE_EXEC_INIT)==0) + ntreeBeginExecTree(ntree); + + stack= ntree->stack; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->gpufunc) { + node_get_stack(node, stack, nsin, nsout); + gpu_from_node_stack(&node->inputs, nsin, gpuin); + gpu_from_node_stack(&node->outputs, nsout, gpuout); + if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) + data_from_gpu_stack(&node->outputs, nsout, gpuout); + } + else if(node->type==NODE_GROUP && node->id) { + node_get_stack(node, stack, nsin, nsout); + gpu_node_group_execute(stack, mat, node, nsin, nsout); + } + } + + ntreeEndExecTree(ntree); +} /* **************** call to switch lamploop for material node ************ */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7b36e46d45e..e63d6047cc6 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -112,6 +112,8 @@ #include "BPY_extern.h" +#include "GPU_material.h" + #include "blendef.h" /* Local function protos */ @@ -268,6 +270,7 @@ void free_object(Object *ob) } if(ob->soft) sbFree(ob->soft); if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings); + if(ob->gpulamp.first) GPU_lamp_free(ob); } static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin) @@ -694,9 +697,11 @@ float dof_camera(Object *ob) if (cam->dof_ob) { /* too simple, better to return the distance on the view axis only * return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */ + float mat[4][4], obmat[4][4]; - float mat[4][4]; - Mat4Invert(ob->imat, ob->obmat); + Mat4CpyMat4(obmat, ob->obmat); + Mat4Ortho(obmat); + Mat4Invert(ob->imat, obmat); Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat); return fabs(mat[3][2]); } @@ -918,7 +923,7 @@ Object *add_only_object(int type, char *name) QuatOne(ob->dquat); #endif - ob->col[0]= ob->col[1]= ob->col[2]= 0.0; + ob->col[0]= ob->col[1]= ob->col[2]= 1.0; ob->col[3]= 1.0; ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0; @@ -955,7 +960,8 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[0] = 1.0f; ob->anisotropicFriction[1] = 1.0f; ob->anisotropicFriction[2] = 1.0f; - ob->gameflag= OB_PROP; + ob->gameflag= OB_PROP|OB_PHYSICS; + ob->margin = 0.0; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; @@ -1226,6 +1232,7 @@ Object *copy_object(Object *ob) obn->vnode = NULL; #endif + obn->gpulamp.first = obn->gpulamp.last = NULL; return obn; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2f4696fc442..db3576f0c50 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -379,8 +379,11 @@ void psys_free_children(ParticleSystem *psys) } /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) -{ +{ if(psys){ + int nr = 0; + ParticleSystem * tpsys; + if(ob->particlesystem.first == NULL && G.f & G_PARTICLEEDIT) G.f &= ~G_PARTICLEEDIT; @@ -406,6 +409,21 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->effectors.first) psys_end_effectors(psys); + + // check if we are last non-visible particle system + for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){ + if(tpsys->part) + { + if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + { + nr++; + break; + } + } + } + // clear do-not-draw-flag + if(!nr) + ob->transflag &= ~OB_DUPLIPARTS; if(psys->part){ psys->part->id.us--; @@ -417,7 +435,7 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->pointcache) BKE_ptcache_free(psys->pointcache); - + MEM_freeN(psys); } } @@ -3823,7 +3841,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { - float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; + float loc[3], nor[3], vec[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; VecSubf(vec, (cache+cache->steps-1)->co, cache->co); @@ -3848,14 +3866,9 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys Mat4MulMat4(mat, obrotmat, qmat); } else { - Crossf(side, nor, vec); - Normalize(side); - Crossf(nor, vec, side); - + Normalize(nor); Mat4One(mat); - VECCOPY(mat[0], vec); - VECCOPY(mat[1], side); - VECCOPY(mat[2], nor); + VECCOPY(mat[2], nor); // mat[2] is normal/direction } *scale= len; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index ef8373ee977..df193bc3802 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -53,12 +53,14 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_kdtree.h" +#include "BLI_kdopbvh.h" #include "BLI_linklist.h" #include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" +#include "BKE_collision.h" #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_particle.h" @@ -76,6 +78,8 @@ #include "BKE_modifier.h" #include "BKE_scene.h" +#include "PIL_time.h" + #include "BSE_headerbuttons.h" #include "blendef.h" @@ -146,6 +150,14 @@ void psys_reset(ParticleSystem *psys, int mode) BLI_freelistN(&psys->reactevents); } } + else if(mode == PSYS_RESET_CACHE_MISS) { + /* set all particles to be skipped */ + ParticleData *pa = psys->particles; + int p=0; + + for(; ptotpart; p++, pa++) + pa->flag = PARS_NO_DISP; + } /* reset children */ if(psys->child) { @@ -2301,7 +2313,15 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy } } else if(pd->forcefield) + { type |= PSYS_EC_EFFECTOR; + + if(pd->forcefield == PFIELD_WIND) + { + pd->rng = rng_new(1); + rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed + } + } } if(pd && pd->deflect) @@ -2413,13 +2433,16 @@ void psys_end_effectors(ParticleSystem *psys) if(ec->tree) BLI_kdtree_free(ec->tree); + + if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND)) + rng_free(ec->ob->pd->rng); } BLI_freelistN(lb); } } -static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -2459,96 +2482,20 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } - else if(ec->type==PSYS_EC_DEFLECT){ - DerivedMesh *dm; - MFace *mface=0; - MVert *mvert=0; - int i, totface; - float v1[3],v2[3],v3[3],v4[4], *min, *max; - - if(ob==ec->ob) - dm=psmd->dm; - else{ - psys_disable_all(ec->ob); - - dm=mesh_get_derived_final(ec->ob,0); - - psys_enable_all(ec->ob); - } - - if(dm){ - totvert=dm->getNumVerts(dm); - totface=dm->getNumFaces(dm); - mface=dm->getFaceDataArray(dm,CD_MFACE); - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* Decide which is faster to calculate by the amount of*/ - /* matrice multiplications needed to convert spaces. */ - /* With size deflect we have to convert allways because */ - /* the object can be scaled nonuniformly (sphere->ellipsoid). */ - if(totvert<2*psys->totpart || part->flag & PART_SIZE_DEFL){ - co=ec->vert_cos=MEM_callocN(sizeof(float)*3*totvert,"Particle deflection vert cos"); - /* convert vert coordinates to global (particle) coordinates */ - for(i=0; iob->obmat,co); - } - co=ec->vert_cos; - } - else - ec->vert_cos=0; - - INIT_MINMAX(ec->ob_minmax,ec->ob_minmax+3); - - min=ec->face_minmax=MEM_callocN(sizeof(float)*6*totface,"Particle deflection face minmax"); - max=min+3; - - for(i=0; iv1); - VECCOPY(v2,co+3*mface->v2); - VECCOPY(v3,co+3*mface->v3); - } - else{ - VECCOPY(v1,mvert[mface->v1].co); - VECCOPY(v2,mvert[mface->v2].co); - VECCOPY(v3,mvert[mface->v3].co); - } - INIT_MINMAX(min,max); - DO_MINMAX(v1,min,max); - DO_MINMAX(v2,min,max); - DO_MINMAX(v3,min,max); - - if(mface->v4){ - if(co){ - VECCOPY(v4,co+3*mface->v4); - } - else{ - VECCOPY(v4,mvert[mface->v4].co); - } - DO_MINMAX(v4,min,max); - } - - DO_MINMAX(min,ec->ob_minmax,ec->ob_minmax+3); - DO_MINMAX(max,ec->ob_minmax,ec->ob_minmax+3); - } - } - else - ec->face_minmax=0; - } else if(ec->type==PSYS_EC_PARTICLE){ + Object *eob = ec->ob; + ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); + ParticleSettings *epart = epsys->part; + ParticleData *epa = epsys->particles; + int totepart = epsys->totpart; + if(psys->part->phystype==PART_PHYS_BOIDS){ - Object *eob = ec->ob; - ParticleSystem *epsys; - ParticleSettings *epart; ParticleData *epa; ParticleKey state; PartDeflect *pd; - int totepart, p; - epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); - epart= epsys->part; + int p; + pd= epart->pd; - totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && totepart){ KDTree *tree; @@ -2563,6 +2510,11 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } + else if(ec->type==PSYS_EC_DEFLECT) { + CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); + if(collmd) + collision_move_object(collmd, 1.0, 0.0); + } } } @@ -2665,7 +2617,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size); } } - else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ + else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ psys_get_particle_state(eob,epsys,p,&estate,1); VECADD(vel,vel,estate.vel); @@ -3011,37 +2963,124 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, } return intersect; } + +/* container for moving data between deflet_particle and particle_intersect_face */ +typedef struct ParticleCollision +{ + struct Object *ob, *ob_t; // collided and current objects + struct CollisionModifierData *md; // collision modifier for ob_t; + float nor[3]; // normal at collision point + float vel[3]; // velocity of collision point + float co1[3], co2[3]; // ray start and end points + float ray_len; // original length of co2-co1, needed for collision time evaluation + float t; // time of previous collision, needed for substracting face velocity +} +ParticleCollision; + +static void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + ParticleCollision *col = (ParticleCollision *) userdata; + MFace *face = col->md->mfaces + index; + MVert *x = col->md->x; + MVert *v = col->md->current_v; + float dir[3], vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], dist, t, threshold; + int ret=0; + + float *t0, *t1, *t2, *t3; + t0 = x[ face->v1 ].co; + t1 = x[ face->v2 ].co; + t2 = x[ face->v3 ].co; + t3 = face->v4 ? x[ face->v4].co : NULL; + + /* calculate average velocity of face */ + VECCOPY(vel, v[ face->v1 ].co); + VECADD(vel, vel, v[ face->v2 ].co); + VECADD(vel, vel, v[ face->v3 ].co); + VecMulf(vel, 0.33334f); + + /* substract face velocity, in other words convert to + a coordinate system where only the particle moves */ + VECADDFAC(co1, col->co1, vel, -col->t); + VECSUB(co2, col->co2, vel); + + do + { + if(ray->radius == 0.0f) { + if(LineIntersectsTriangle(co1, co2, t0, t1, t2, &t, uv)) { + if(t >= 0.0f && t < hit->dist/col->ray_len) { + hit->dist = col->ray_len * t; + hit->index = index; + + /* calculate normal that's facing the particle */ + CalcNormFloat(t0, t1, t2, col->nor); + VECSUB(temp, co2, co1); + if(Inpf(col->nor, temp) > 0.0f) + VecMulf(col->nor, -1.0f); + + VECCOPY(col->vel,vel); + + col->ob = col->ob_t; + } + } + } + else { + if(SweepingSphereIntersectsTriangleUV(co1, co2, ray->radius, t0, t1, t2, &t, ipoint)) { + if(t >=0.0f && t < hit->dist/col->ray_len) { + hit->dist = col->ray_len * t; + hit->index = index; + + VecLerpf(temp, co1, co2, t); + + VECSUB(col->nor, temp, ipoint); + Normalize(col->nor); + + VECCOPY(col->vel,vel); + + col->ob = col->ob_t; + } + } + } + + t1 = t2; + t2 = t3; + t3 = NULL; + + } while(t2); +} /* particle - mesh collision code */ /* in addition to basic point to surface collisions handles friction & damping,*/ /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float dfra, float cfra, ParticleKey *state, int *pa_die){ - Object *ob, *min_ob; - MFace *mface; - MVert *mvert; - DerivedMesh *dm; +static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){ + Object *ob; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; - ParticleKey cstate; - float imat[4][4]; - float co1[3],co2[3],def_loc[3],def_nor[3],unit_nor[3],def_tan[3],dvec[3],def_vel[3],dave[3],dvel[3]; - float pa_minmax[6]; - float min_w[4], zerovec[3]={0.0,0.0,0.0}, ipoint[3]; - float min_d,dotprod,damp,frict,o_len,d_len,radius=-1.0f; - int min_face=0, intersect=1, through=0; - short deflections=0, global=0; + ParticleKey reaction_state; + ParticleCollision col; + CollisionModifierData *collmd; + BVHTreeRayHit hit; + float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; + float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f); + int deflections=0, max_deflections=10; - VECCOPY(def_loc,pa->state.co); - VECCOPY(def_vel,pa->state.vel); + VECCOPY(col.co1, pa->state.co); + VECCOPY(col.co2, state->co); + col.t = 0.0f; /* 10 iterations to catch multiple deflections */ - if(lb->first) while(deflections<10){ - intersect=0; - global=0; - min_d=20000.0; - min_ob=NULL; + if(lb->first) while(deflections < max_deflections){ /* 1. */ + + VECSUB(ray_dir, col.co2, col.co1); + hit.index = -1; + hit.dist = col.ray_len = VecLength(ray_dir); + + /* even if particle is stationary we want to check for moving colliders */ + /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */ + if(hit.dist == 0.0f) + hit.dist = col.ray_len = 0.000001f; + for(ec=lb->first; ec; ec=ec->next){ if(ec->type & PSYS_EC_DEFLECT){ ob= ec->ob; @@ -3049,263 +3088,165 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part if(part->type!=PART_HAIR) where_is_object_time(ob,cfra); - if(ob==pob){ - dm=psmd->dm; - /* particles should not collide with emitter at birth */ - if(pa->time < cfra && pa->time >= psys->cfra) - continue; - } - else - dm=0; - - VECCOPY(co1,def_loc); - VECCOPY(co2,state->co); + /* particles should not collide with emitter at birth */ + if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) + continue; - if(ec->vert_cos==0){ - /* convert particle coordinates to object coordinates */ - Mat4Invert(imat,ob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - } + col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); + col.ob_t = ob; - INIT_MINMAX(pa_minmax,pa_minmax+3); - DO_MINMAX(co1,pa_minmax,pa_minmax+3); - DO_MINMAX(co2,pa_minmax,pa_minmax+3); - if(part->flag&PART_SIZE_DEFL){ - pa_minmax[0]-=pa->size; - pa_minmax[1]-=pa->size; - pa_minmax[2]-=pa->size; - pa_minmax[3]+=pa->size; - pa_minmax[4]+=pa->size; - pa_minmax[5]+=pa->size; - - radius=pa->size; - } - - if(ec->face_minmax==0 || AabbIntersectAabb(pa_minmax,pa_minmax+3,ec->ob_minmax,ec->ob_minmax+3)) { - if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w, - ec->face_minmax,pa_minmax,radius,ipoint)){ - - min_ob=ob; - - if(ec->vert_cos) - global=1; - else - global=0; - } - } + if(col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); } } /* 2. */ - if(min_ob){ - BLI_srandom((int)cfra+p); - ob=min_ob; + if(hit.index>=0) { + PartDeflect *pd = col.ob->pd; + int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; + float co[3]; /* point of collision */ + float vec[3]; /* movement through collision */ + float vel[3]; /* velocity after collision */ + float t = hit.dist/col.ray_len; /* time of collision between this iteration */ + float dt = col.t + t * (1.0f - col.t); /* time of collision between frame change*/ - if(ob==pob){ - dm=psmd->dm; - } - else{ - psys_disable_all(ob); + VecLerpf(co, col.co1, col.co2, t); + VECSUB(vec, col.co2, col.co1); - dm=mesh_get_derived_final(ob,0); + VecMulf(col.vel, 1.0f-col.t); - psys_enable_all(ob); - } - - mface=dm->getFaceDataArray(dm,CD_MFACE); - mface+=min_face; - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* permeability check */ - if(BLI_frand()pd->pdef_perm) - through=1; - else - through=0; - - if(through==0 && (part->flag & PART_DIE_ON_COL || ob->pd->flag & PDEFLE_KILL_PART)){ - pa->dietime = cfra-(1.0f-min_d)*dfra; - VecLerpf(def_loc,def_loc,state->co,min_d); - - VECCOPY(state->co,def_loc); - VecLerpf(state->vel,pa->state.vel,state->vel,min_d); - QuatInterpol(state->rot,pa->state.rot,state->rot,min_d); - VecLerpf(state->ave,pa->state.ave,state->ave,min_d); - - *pa_die=1; + /* particle dies in collision */ + if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) { + pa->alive = PARS_DYING; + pa->dietime = pa->state.time + (cfra - pa->state.time) * dt; + VECCOPY(state->co, co); + VecLerpf(state->vel, pa->state.vel, state->vel, dt); + QuatInterpol(state->rot, pa->state.rot, state->rot, dt); + VecLerpf(state->ave, pa->state.ave, state->ave, dt); /* particle is dead so we don't need to calculate further */ - deflections=10; + deflections=max_deflections; /* store for reactors */ - copy_particle_key(&cstate,state,0); + copy_particle_key(&reaction_state,state,0); if(part->flag & PART_STICKY){ pa->stick_ob=ob; pa->flag |= PARS_STICKY; } } - else{ - VECCOPY(co1,def_loc); - VECCOPY(co2,state->co); - - if(global==0){ - /* convert particle coordinates to object coordinates */ - Mat4Invert(imat,ob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - } - - VecLerpf(def_loc,co1,co2,min_d); - - if(radius>0.0f){ - VECSUB(unit_nor,def_loc,ipoint); - } - else{ - /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,0,min_w,ipoint,unit_nor,0,0,0,0); - if(global){ - Mat4Mul3Vecfl(ob->obmat,unit_nor); - Mat4MulVecfl(ob->obmat,ipoint); - } - } - - Normalize(unit_nor); - - VECSUB(dvec,co1,co2); - /* scale to remaining length after deflection */ - VecMulf(dvec,1.0f-min_d); - - /* flip normal to face particle */ - if(Inpf(unit_nor,dvec)<0.0f) - VecMulf(unit_nor,-1.0f); - - /* store for easy velocity calculation */ - o_len=VecLength(dvec); - - /* project particle movement to normal & create tangent */ - dotprod=Inpf(dvec,unit_nor); - VECCOPY(def_nor,unit_nor); - VecMulf(def_nor,dotprod); - VECSUB(def_tan,def_nor,dvec); - - damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); - - /* create location after deflection */ - VECCOPY(dvec,def_nor); - damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); + else { + float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; + float damp, frict; + float inp, inp_v; + + /* get damping & friction factors */ + damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); CLAMP(damp,0.0,1.0); - VecMulf(dvec,1.0f-damp); - if(through) - VecMulf(dvec,-1.0); - - frict=ob->pd->pdef_frict+ob->pd->pdef_rfrict*2.0f*(BLI_frand()-0.5f); + + frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f); CLAMP(frict,0.0,1.0); - VECADDFAC(dvec,dvec,def_tan,1.0f-frict); - /* store for easy velocity calculation */ - d_len=VecLength(dvec); + /* treat normal & tangent components separately */ + inp = Inpf(col.nor, vec); + inp_v = Inpf(col.nor, col.vel); - /* just to be sure we don't hit the current face again */ - if(through){ - VECADDFAC(ipoint,ipoint,unit_nor,-0.0001f); - VECADDFAC(def_loc,def_loc,unit_nor,-0.0001f); + VECADDFAC(tan_vec, vec, col.nor, -inp); + VECADDFAC(tan_vel, col.vel, col.nor, -inp_v); + if((part->flag & PART_ROT_DYN)==0) + VecLerpf(tan_vec, tan_vec, tan_vel, frict); - if(part->flag & PART_ROT_DYN){ - VECADDFAC(def_tan,def_tan,unit_nor,-0.0001f); - VECADDFAC(def_nor,def_nor,unit_nor,-0.0001f); - } - } - else{ - VECADDFAC(ipoint,ipoint,unit_nor,0.0001f); - VECADDFAC(def_loc,def_loc,unit_nor,0.0001f); + VECCOPY(nor_vec, col.nor); + inp *= 1.0f - damp; - if(part->flag & PART_ROT_DYN){ - VECADDFAC(def_tan,def_tan,unit_nor,0.0001f); - VECADDFAC(def_nor,def_nor,unit_nor,0.0001f); - } + if(through) + inp_v *= damp; + + /* special case for object hitting the particle from behind */ + if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v linear velocity - slightly more physical and looks even nicer than before */ + if(part->flag & PART_ROT_DYN) { + float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3]; + + /* apparent velocity along collision surface */ + VECSUB(surface_vel, tan_vec, tan_vel); + + /* direction of rolling friction */ + Crossf(rot_vel, state->ave, col.nor); + /* convert to current dt */ + VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t)); + VecMulf(rot_vel, pa->size); + + /* apply sliding friction */ + VECSUB(surface_vel, surface_vel, rot_vel); + VECCOPY(friction, surface_vel); + + VecMulf(surface_vel, 1.0 - frict); + VecMulf(friction, frict); + + /* sliding changes angular velocity */ + Crossf(dave, col.nor, friction); + VecMulf(dave, 1.0f/MAX2(pa->size, 0.001)); + + /* we assume rolling friction is around 0.01 of sliding friction */ + VecMulf(rot_vel, 1.0 - frict*0.01); + + /* change in angular velocity has to be added to the linear velocity too */ + Crossf(dvel, dave, col.nor); + VecMulf(dvel, pa->size); + VECADD(rot_vel, rot_vel, dvel); + + VECADD(surface_vel, surface_vel, rot_vel); + VECADD(tan_vec, surface_vel, tan_vel); + + /* convert back to normal time */ + VecMulf(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); + + VecMulf(state->ave, 1.0 - frict*0.01); + VECADD(state->ave, state->ave, dave); } - /* lets get back to global space */ - if(global==0){ - Mat4Mul3Vecfl(ob->obmat,dvec); - Mat4MulVecfl(ob->obmat,ipoint); - Mat4MulVecfl(ob->obmat,def_loc);/* def_loc remains as intersection point for next iteration */ - } + /* combine components together again */ + VECADD(vec, nor_vec, tan_vec); - /* store for reactors */ - VECCOPY(cstate.co,ipoint); - VecLerpf(cstate.vel,pa->state.vel,state->vel,min_d); - QuatInterpol(cstate.rot,pa->state.rot,state->rot,min_d); + /* calculate velocity from collision vector */ + VECCOPY(vel, vec); + VecMulf(vel, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - /* slightly unphysical but looks nice enough */ - if(part->flag & PART_ROT_DYN){ - if(global==0){ - Mat4Mul3Vecfl(ob->obmat,def_nor); - Mat4Mul3Vecfl(ob->obmat,def_tan); - } + /* make sure we don't hit the current face again */ + VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - Normalize(def_tan); - Normalize(def_nor); - VECCOPY(unit_nor,def_nor); + /* store state for reactors */ + VECCOPY(reaction_state.co, co); + VecLerpf(reaction_state.vel, pa->state.vel, state->vel, dt); + QuatInterpol(reaction_state.rot, pa->state.rot, state->rot, dt); - /* create normal velocity */ - VecMulf(def_nor,Inpf(pa->state.vel,def_nor)); + /* set coordinates for next iteration */ + VECCOPY(col.co1, co); + VECADDFAC(col.co2, co, vec, 1.0f - t); + col.t = dt; - /* create tangential velocity */ - VecMulf(def_tan,Inpf(pa->state.vel,def_tan)); - - /* angular velocity change due to tangential velocity */ - Crossf(dave,unit_nor,def_tan); - VecMulf(dave,1.0f/pa->size); - - /* linear velocity change due to angular velocity */ - VecMulf(unit_nor,pa->size); /* point of impact from particle center */ - Crossf(dvel,pa->state.ave,unit_nor); - - if(through) - VecMulf(def_nor,-1.0); - - VecMulf(def_nor,1.0f-damp); - VECSUB(dvel,dvel,def_nor); - - VecMulf(dvel,1.0f-frict); - VecMulf(dave,1.0f-frict); - } - - if(d_len<0.001 && VecLength(pa->state.vel)<0.001){ + if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) { /* kill speed to stop slipping */ VECCOPY(state->vel,zerovec); - VECCOPY(state->co,def_loc); - if(part->flag & PART_ROT_DYN) + VECCOPY(state->co, co); + if(part->flag & PART_ROT_DYN) { VECCOPY(state->ave,zerovec); - deflections=10; - } - else{ - - /* apply new coordinates */ - VECADD(state->co,def_loc,dvec); - - Normalize(dvec); - - /* we have to use original velocity because otherwise we get slipping */ - /* when forces like gravity balance out damping & friction */ - VecMulf(dvec,VecLength(pa->state.vel)*(d_len/o_len)); - VECCOPY(state->vel,dvec); - - if(part->flag & PART_ROT_DYN){ - VECADD(state->vel,state->vel,dvel); - VecMulf(state->vel,0.5); - VECADD(state->ave,state->ave,dave); - VecMulf(state->ave,0.5); } } + else { + VECCOPY(state->co, col.co2); + VECCOPY(state->vel, vel); + } } deflections++; - cstate.time=cfra-(1.0f-min_d)*dfra; - //particle_react_to_collision(min_ob,pob,psys,pa,p,&cstate); - push_reaction(pob,psys,p,PART_EVENT_COLLIDE,&cstate); + reaction_state.time = cfra - (1.0f - dt) * dfra; + push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); } else return; @@ -3469,7 +3410,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l } } /* determines the acceleration that the boid tries to acchieve */ -static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc, int *pa_die) +static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc) { ParticleData *pars=psys->particles; KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1]; @@ -3536,7 +3477,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS distance=Normalize(dvec); if(part->flag & PART_DIE_ON_COL && distance < pd->mindist){ - *pa_die=1; + pa->alive = PARS_DYING; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3565,7 +3506,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){ + if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0 && ec->tree){ count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); for(p=0; pflag & PART_DIE_ON_COL && distance < (epsys->particles+ptn2[p].index)->size){ - *pa_die=1; + pa->alive = PARS_DYING; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3712,7 +3653,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){ + if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0 && ec->tree){ count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); for(p=0; pvel[2]=0.0; state->co[2]=part->groundz; - if(psys->keyed_ob){ + if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ Object *zob=psys->keyed_ob; int min_face; float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; @@ -3984,7 +3925,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); Material *ma=give_current_material(ob,part->omat); float timestep; - int p, totpart, pa_die; + int p, totpart; /* current time */ float ctime, ipotime; /* frame & time changes */ @@ -4064,7 +4005,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); if(part->phystype==PART_PHYS_BOIDS){ /* create particle tree for fast inter-particle comparisons */ @@ -4093,15 +4034,13 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); - pa_die=0; - birthtime = pa->time + pa->loop * pa->lifetime; + /* allways reset particles to emitter before birth */ if(pa->alive==PARS_UNBORN || pa->alive==PARS_KILLED || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ - /* allways reset particles to emitter before birth */ reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); copy_particle_key(key,&pa->state,1); } @@ -4126,32 +4065,31 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi /* particle dies some time between this and last step */ pa_dfra = dietime - psys->cfra; pa_dtime = pa_dfra * timestep; - pa_die = 1; + pa->alive = PARS_DYING; } else if(dietime < cfra){ - /* TODO: figure out if there's something to be done when particle is dead */ + /* nothing to be done when particle is dead */ } copy_particle_key(key,&pa->state,1); - if(dfra>0.0 && pa->alive==PARS_ALIVE){ + if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra,key); - + /* deflection */ - deflect_particle(ob,psmd,psys,part,pa,p,pa_dfra,cfra,key,&pa_die); + deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key); /* rotations */ rotate_particle(part,pa,pa_dfra,timestep,key); - break; case PART_PHYS_BOIDS: { float acc[3]; - boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc,&pa_die); - if(pa_die==0) + boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); + if(pa->alive != PARS_DYING) boid_body(&bvf,pa,psys,part,timestep,acc,key); break; } @@ -4159,7 +4097,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi push_reaction(ob,psys,p,PART_EVENT_NEAR,key); - if(pa_die){ + if(pa->alive == PARS_DYING){ push_reaction(ob,psys,p,PART_EVENT_DEATH,key); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ @@ -4181,6 +4119,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } } } + /* apply outstates to particles */ for(p=0, pa=psys->particles, key=outstate; pstate,key,1); @@ -4260,7 +4199,7 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); if(psys_in_edit_mode(psys)) PE_recalc_world_cos(ob, psys); @@ -4288,7 +4227,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); //} disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; @@ -4542,7 +4481,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(usecache) { /* frame clamping */ if(framenr < startframe) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra = cfra; psys->recalc = 0; return; @@ -4622,14 +4561,14 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier return; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; return; } if(framenr != startframe && framedelta != 1) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra = cfra; psys->recalc = 0; return; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 292a800e9cd..76af9a763ee 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -113,23 +113,23 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float void space_transform_apply(const SpaceTransform *data, float *co) { - VecMat4MulVecfl(co, data->local2target, co); + VecMat4MulVecfl(co, ((SpaceTransform*)data)->local2target, co); } void space_transform_invert(const SpaceTransform *data, float *co) { - VecMat4MulVecfl(co, data->target2local, co); + VecMat4MulVecfl(co, ((SpaceTransform*)data)->target2local, co); } void space_transform_apply_normal(const SpaceTransform *data, float *no) { - Mat4Mul3Vecfl(data->local2target, no); + Mat4Mul3Vecfl( ((SpaceTransform*)data)->local2target, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } void space_transform_invert_normal(const SpaceTransform *data, float *no) { - Mat4Mul3Vecfl(data->target2local, no); + Mat4Mul3Vecfl(((SpaceTransform*)data)->target2local, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } @@ -291,7 +291,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa space_transform_apply_normal( transf, tmp_no ); no = tmp_no; - hit_tmp.dist *= Mat4ToScalef( transf->local2target ); + hit_tmp.dist *= Mat4ToScalef( ((SpaceTransform*)transf)->local2target ); } else { @@ -301,7 +301,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa hit_tmp.index = -1; - BLI_bvhtree_ray_cast(tree, co, no, &hit_tmp, callback, userdata); + BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); if(hit_tmp.index != -1) { @@ -318,7 +318,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa space_transform_invert( transf, hit_tmp.co ); space_transform_invert_normal( transf, hit_tmp.no ); - hit_tmp.dist = VecLenf( vert, hit_tmp.co ); + hit_tmp.dist = VecLenf( (float*)vert, hit_tmp.co ); } memcpy(hit, &hit_tmp, sizeof(hit_tmp) ); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index d465c058d30..508b2233536 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1622,23 +1622,23 @@ void *exec_scan_for_ext_spring_forces(void *data) void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func()) { - ListBase *do_effector = NULL; + ListBase *do_effector = NULL; ListBase threads; SB_thread_context *sb_threads; int i, totthread,left,dec; - int lowsprings =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ + int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ do_effector= pdInitEffectors(ob,NULL); /* figure the number of threads while preventing pretty pointless threading overhead */ - if(totsprings < lowsprings) {totthread=1;} - else{ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; - else - totthread= BLI_system_thread_count(); + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); + /* what if we got zillions of CPUs running but less to spread*/ + while ((totsprings/totthread < lowsprings) && (totthread > 1)) { + totthread--; } - /*left to do--> what if we got zillions of CPUs running but 'totsprings' tasks to spread*/ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread"); memset(sb_threads, 0, sizeof(SB_thread_context)*totthread); @@ -2279,6 +2279,11 @@ int _softbody_calc_forces_slice_in_a_thread(Object *ob, float forcetime, float t float kd = 1.0f; if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ + if (intrusion < 0.0f){ + sb->scratch->flag |= SBF_DOFUZZY; + bp->flag |= SBF_DOFUZZY; + bp->choke = sb->choke*0.01f; + } VECSUB(cfforce,bp->vec,vel); Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); @@ -2326,17 +2331,19 @@ void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow,int tot ListBase threads; SB_thread_context *sb_threads; int i, totthread,left,dec; - int lowpoints =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ + int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ /* figure the number of threads while preventing pretty pointless threading overhead */ - if(totpoint < lowpoints) {totthread=1;} - else{ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; - else - totthread= BLI_system_thread_count(); + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); + /* what if we got zillions of CPUs running but less to spread*/ + while ((totpoint/totthread < lowpoints) && (totthread > 1)) { + totthread--; } - /*left to do--> what if we got zillions of CPUs running but 'totpoint' tasks to spread*/ + + /* printf("sb_cf_threads_run spawning %d threads \n",totthread); */ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread"); memset(sb_threads, 0, sizeof(SB_thread_context)*totthread); @@ -2425,7 +2432,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags) { /* redirection to the new threaded Version */ - if (G.rt !=16){ + if (!(G.rt & 0x10)){ // 16 softbody_calc_forcesEx(ob, forcetime, timenow, nl_flags); return; } @@ -2433,6 +2440,10 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int /* so the following will die */ /* |||||||||||||||||||||||||| */ /* VVVVVVVVVVVVVVVVVVVVVVVVVV */ + /*backward compatibility note: + fixing bug [17428] which forces adaptive step size to tiny steps + in some situations + .. keeping G.rt==17 0x11 option for old files 'needing' the bug*/ /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2681,14 +2692,25 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ if ((!nl_flags)&&(intrusion < 0.0f)){ - /*bjornmose: uugh.. what an evil hack - violation of the 'don't touch bp->pos in here' rule - but works nice, like this--> - we predict the solution beeing out of the collider - in heun step No1 and leave the heun step No2 adapt to it - so we kind of introduced a implicit solver for this case - */ - Vec3PlusStVec(bp->pos,-intrusion,facenormal); + if(G.rt & 0x01){ // 17 we did check for bit 0x10 before + /*fixing bug [17428] this forces adaptive step size to tiny steps + in some situations .. keeping G.rt==17 option for old files 'needing' the bug + */ + /*bjornmose: uugh.. what an evil hack + violation of the 'don't touch bp->pos in here' rule + but works nice, like this--> + we predict the solution beeing out of the collider + in heun step No1 and leave the heun step No2 adapt to it + so we kind of introduced a implicit solver for this case + */ + Vec3PlusStVec(bp->pos,-intrusion,facenormal); + } + else{ + + VECSUB(cfforce,bp->vec,vel); + Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); + } + sb->scratch->flag |= SBF_DOFUZZY; bp->flag |= SBF_DOFUZZY; @@ -4040,7 +4062,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime) if(sb->solverflags & SBSO_MONITOR ){ sct=PIL_check_seconds_timer(); - if (sct-sst > 0.5f) printf(" solver time %f sec %s \n",sct-sst,ob->id.name); + if ((sct-sst > 0.5f) || (G.f & G_DEBUG)) printf(" solver time %f sec %s \n",sct-sst,ob->id.name); } } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index bba79bd6d28..e6797186b53 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -61,6 +61,10 @@ #include "BIF_gl.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + #include "CCGSubSurf.h" typedef struct _VertData { @@ -696,6 +700,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, for(index = 0; index < totedge; index++) { CCGEdge *e = edgeMap2[index]; unsigned int flags = 0; + char bweight = 0; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ss, e)); if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE; @@ -706,12 +711,14 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, dm->getEdge(dm, edgeIdx, &origMed); flags |= origMed.flag; + bweight = origMed.bweight; } for(x = 0; x < edgeSize - 1; x++) { med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); med->flag = flags; + med->bweight = bweight; *origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e); ++med; ++origIndex; @@ -973,7 +980,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) memset(mv, 0, sizeof(*mv)); - if(vertNum < ccgdm->edgeMap[0].startVert) { + if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { /* this vert comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -1014,7 +1021,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) x = offset % gridSideVerts + 1; VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y)); } - } else if(vertNum < ccgdm->vertMap[0].startVert) { + } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) { /* this vert comes from edge data */ CCGEdge *e; int lastedge = ccgSubSurf_getNumEdges(ss) - 1; @@ -1599,7 +1606,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { +static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); @@ -1621,7 +1628,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { mat_nr= 0; } - if (!setMaterial(mat_nr+1)) + if (!setMaterial(mat_nr+1, NULL)) continue; glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); @@ -1666,6 +1673,168 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { ccgFaceIterator_free(fi); } + + /* Only used by non-editmesh types */ +static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = ccgdm->ss; + CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); + GPUVertexAttribs gattribs; + DMVertexAttribs attribs; + MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + int edgeSize = ccgSubSurf_getEdgeSize(ss); + int transp, orig_transp, new_transp; + char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS); + int a, b, i, doDraw, numVerts, matnr, new_matnr, totface; + + doDraw = 0; + numVerts = 0; + matnr = -1; + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + + memset(&attribs, 0, sizeof(attribs)); + +#define PASSATTRIB(dx, dy, vert) { \ + if(attribs.totorco) { \ + index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \ + glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = &attribs.tface[b].array[a]; \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[a*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + totface = ccgSubSurf_getNumFaces(ss); + for(a = 0, i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int S, x, y, drawSmooth; + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); + int origIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f); + + numVerts = ccgSubSurf_getFaceNumVerts(ss, f); + + if(faceFlags) { + drawSmooth = (faceFlags[index*4] & ME_SMOOTH); + new_matnr= faceFlags[index*4 + 1] + 1; + } + else { + drawSmooth = 1; + new_matnr= 1; + } + + if(new_matnr != matnr) { + doDraw = setMaterial(matnr = new_matnr, &gattribs); + if(doDraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) { + a += gridFaces*gridFaces*numVerts; + continue; + } + + if(tf) { + new_transp = tf[i].transp; + + if(new_transp != transp) { + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + } + } + + glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); + for (S=0; Sno); + glVertex3fv(vda->co); + + PASSATTRIB(0, 1, 1); + glNormal3fv(vdb->no); + glVertex3fv(vdb->co); + + if(x != gridFaces-1) + a++; + } + + vda = &faceGridData[(y+0)*gridSize + x]; + vdb = &faceGridData[(y+1)*gridSize + x]; + + PASSATTRIB(0, 0, 3); + glNormal3fv(vda->no); + glVertex3fv(vda->co); + + PASSATTRIB(0, 1, 2); + glNormal3fv(vdb->no); + glVertex3fv(vdb->co); + + glEnd(); + + a++; + } + } else { + glBegin(GL_QUADS); + for (y=0; ydrawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; @@ -2143,8 +2312,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid; ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored; ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex; + ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL; ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; + ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL; ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c new file mode 100644 index 00000000000..6530909336c --- /dev/null +++ b/source/blender/blenkernel/intern/suggestions.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) 2008, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Ian Thompson. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "DNA_text_types.h" +#include "BKE_text.h" +#include "BKE_suggestions.h" + +/**********************/ +/* Static definitions */ +/**********************/ + +static Text *activeToolText = NULL; +static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; +static char *documentation = NULL; +//static int doc_lines = 0; + +static int txttl_cmp(const char *first, const char *second, int len) { + int cmp, i; + for (cmp=0, i=0; iprev; + MEM_freeN(item); + } + suggestions.first = suggestions.last = NULL; + suggestions.firstmatch = suggestions.lastmatch = NULL; + suggestions.selected = NULL; + suggestions.top = 0; +} + +static void txttl_free_docs() { + if (documentation) { + MEM_freeN(documentation); + documentation = NULL; + } +} + +/**************************/ +/* General tool functions */ +/**************************/ + +void free_texttools() { + txttl_free_suggest(); + txttl_free_docs(); +} + +void texttool_text_set_active(Text *text) { + if (activeToolText == text) return; + texttool_text_clear(); + activeToolText = text; +} + +void texttool_text_clear() { + free_texttools(); + activeToolText = NULL; +} + +short texttool_text_is_active(Text *text) { + return activeToolText==text ? 1 : 0; +} + +/***************************/ +/* Suggestion list methods */ +/***************************/ + +void texttool_suggest_add(const char *name, char type) { + SuggItem *newitem, *item; + int len, cmp; + + newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + if (!newitem) { + printf("Failed to allocate memory for suggestion.\n"); + return; + } + + newitem->name = (char *) (newitem + 1); + len = strlen(name); + strncpy(newitem->name, name, len); + newitem->name[len] = '\0'; + newitem->type = type; + newitem->prev = newitem->next = NULL; + + /* Perform simple linear search for ordered storage */ + if (!suggestions.first || !suggestions.last) { + suggestions.first = suggestions.last = newitem; + } else { + cmp = -1; + for (item=suggestions.last; item; item=item->prev) { + cmp = txttl_cmp(name, item->name, len); + + /* Newitem comes after this item, insert here */ + if (cmp >= 0) { + newitem->prev = item; + if (item->next) + item->next->prev = newitem; + newitem->next = item->next; + item->next = newitem; + + /* At last item, set last pointer here */ + if (item == suggestions.last) + suggestions.last = newitem; + break; + } + } + /* Reached beginning of list, insert before first */ + if (cmp < 0) { + newitem->next = suggestions.first; + suggestions.first->prev = newitem; + suggestions.first = newitem; + } + } + suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL; + suggestions.top= 0; +} + +void texttool_suggest_prefix(const char *prefix) { + SuggItem *match, *first, *last; + int cmp, len = strlen(prefix), top = 0; + + if (!suggestions.first) return; + if (len==0) { + suggestions.selected = suggestions.firstmatch = suggestions.first; + suggestions.lastmatch = suggestions.last; + return; + } + + first = last = NULL; + for (match=suggestions.first; match; match=match->next) { + cmp = txttl_cmp(prefix, match->name, len); + if (cmp==0) { + if (!first) { + first = match; + suggestions.top = top; + } + } else if (cmp<0) { + if (!last) { + last = match->prev; + break; + } + } + top++; + } + if (first) { + if (!last) last = suggestions.last; + suggestions.firstmatch = first; + suggestions.lastmatch = last; + suggestions.selected = first; + } else { + suggestions.firstmatch = NULL; + suggestions.lastmatch = NULL; + suggestions.selected = NULL; + suggestions.top = 0; + } +} + +void texttool_suggest_clear() { + txttl_free_suggest(); +} + +SuggItem *texttool_suggest_first() { + return suggestions.firstmatch; +} + +SuggItem *texttool_suggest_last() { + return suggestions.lastmatch; +} + +void texttool_suggest_select(SuggItem *sel) { + suggestions.selected = sel; +} + +SuggItem *texttool_suggest_selected() { + return suggestions.selected; +} + +int *texttool_suggest_top() { + return &suggestions.top; +} + +/*************************/ +/* Documentation methods */ +/*************************/ + +void texttool_docs_show(const char *docs) { + int len; + + if (!docs) return; + + len = strlen(docs); + + if (documentation) { + MEM_freeN(documentation); + documentation = NULL; + } + + /* Ensure documentation ends with a '\n' */ + if (docs[len-1] != '\n') { + documentation = MEM_mallocN(len+2, "Documentation"); + strncpy(documentation, docs, len); + documentation[len++] = '\n'; + } else { + documentation = MEM_mallocN(len+1, "Documentation"); + strncpy(documentation, docs, len); + } + documentation[len] = '\0'; +} + +char *texttool_docs_get() { + return documentation; +} + +void texttool_docs_clear() { + txttl_free_docs(); +} diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 53b7bb975a3..5f1a1e63da4 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -30,6 +30,8 @@ */ #include /* strstr */ +#include +#include #include "MEM_guardedalloc.h" @@ -81,12 +83,19 @@ The st->top determines at what line the top of the text is displayed. If the user moves the cursor the st containing that cursor should be popped ... other st's retain their own top location. -*/ /***************/ +Markers +-- +The mrk->flags define the behaviour and relationships between markers. The +upper two bytes are used to hold a group ID, the lower two are normal flags. If +TMARK_EDITALL is set the group ID defines which other markers should be edited. +The mrk->clr field is used to visually group markers where the flags may not +match. A template system, for example, may allow editing of repeating tokens +(in one group) but include other marked positions (in another group) all in the +same template with the same colour. -/****************/ /* - Undo - +Undo +-- Undo/Redo works by storing events in a queue, and a pointer to the current position in the @@ -145,6 +154,7 @@ void free_text(Text *text) } BLI_freelistN(&text->lines); + BLI_freelistN(&text->markers); if(text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -169,10 +179,11 @@ Text *add_empty_text(char *name) ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM; ta->lines.first= ta->lines.last= NULL; + ta->markers.first= ta->markers.last= NULL; tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(1, "textline_string"); - tmp->format= (char*) MEM_mallocN(2, "Syntax_format"); + tmp->format= NULL; tmp->line[0]=0; tmp->len= 0; @@ -209,11 +220,12 @@ static void cleanup_textline(TextLine * tl) int reopen_text(Text *text) { FILE *fp; - int i, llen, len; + int i, llen, len, res; unsigned char *buffer; TextLine *tmp; char sfile[FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE]; + struct stat st; if (!text || !text->name) return 0; @@ -242,7 +254,7 @@ int reopen_text(Text *text) text->undo_len= TXT_INIT_UNDO; text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); - text->flags= TXT_ISDIRTY | TXT_ISTMP; + text->flags= TXT_ISTMP; fseek(fp, 0L, SEEK_END); len= ftell(fp); @@ -256,6 +268,9 @@ int reopen_text(Text *text) len = fread(buffer, 1, len, fp); fclose(fp); + + res= stat(str, &st); + text->mtime= st.st_mtime; text->nlines=0; i=0; @@ -264,7 +279,7 @@ int reopen_text(Text *text) if (buffer[i]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); tmp->line[llen]=0; @@ -284,7 +299,7 @@ int reopen_text(Text *text) if (llen!=0 || text->nlines==0) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); @@ -307,12 +322,13 @@ int reopen_text(Text *text) Text *add_text(char *file) { FILE *fp; - int i, llen, len; + int i, llen, len, res; unsigned char *buffer; TextLine *tmp; Text *ta; char sfile[FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE]; + struct stat st; BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE); if (G.scene) /* can be NULL (bg mode) */ @@ -326,6 +342,7 @@ Text *add_text(char *file) ta->id.us= 1; ta->lines.first= ta->lines.last= NULL; + ta->markers.first= ta->markers.last= NULL; ta->curl= ta->sell= NULL; /* ta->flags= TXT_ISTMP | TXT_ISEXT; */ @@ -348,6 +365,9 @@ Text *add_text(char *file) len = fread(buffer, 1, len, fp); fclose(fp); + + res= stat(str, &st); + ta->mtime= st.st_mtime; ta->nlines=0; i=0; @@ -356,7 +376,7 @@ Text *add_text(char *file) if (buffer[i]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); tmp->line[llen]=0; @@ -376,7 +396,7 @@ Text *add_text(char *file) if (llen!=0 || ta->nlines==0) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); @@ -410,6 +430,7 @@ Text *copy_text(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP; tan->lines.first= tan->lines.last= NULL; + tan->markers.first= tan->markers.last= NULL; tan->curl= tan->sell= NULL; tan->nlines= ta->nlines; @@ -419,7 +440,7 @@ Text *copy_text(Text *ta) while (line) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(line->len+1, "textline_string"); - tmp->format= MEM_mallocN(line->len+2, "Syntax_format"); + tmp->format= NULL; strcpy(tmp->line, line->line); @@ -440,14 +461,14 @@ Text *copy_text(Text *ta) /* Editing utility functions */ /*****************************/ -static void make_new_line (TextLine *line, char *newline, char *newformat) +static void make_new_line (TextLine *line, char *newline) { if (line->line) MEM_freeN(line->line); if (line->format) MEM_freeN(line->format); line->line= newline; line->len= strlen(newline); - line->format= newformat; + line->format= NULL; } static TextLine *txt_new_line(char *str) @@ -458,7 +479,7 @@ static TextLine *txt_new_line(char *str) tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(strlen(str)+1, "textline_string"); - tmp->format= MEM_mallocN(strlen(str)+2, "Syntax_format"); + tmp->format= NULL; strcpy(tmp->line, str); @@ -476,7 +497,7 @@ static TextLine *txt_new_linen(char *str, int n) tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(n+1, "textline_string"); - tmp->format= MEM_mallocN(n+2, "Syntax_format"); + tmp->format= NULL; BLI_strncpy(tmp->line, str, n+1); @@ -553,6 +574,19 @@ static void txt_make_dirty (Text *text) if (text->compiled) BPY_free_compiled_text(text); } +/* 0:whitespace, 1:punct, 2:alphanumeric */ +static short txt_char_type (char ch) +{ + if (ch <= ' ') return 0; + if (ch <= '/') return 1; + if (ch <= '9') return 2; + if (ch <= '@') return 1; + if (ch <= 'Z') return 2; + if (ch <= '`') return 1; + if (ch <= 'z') return 2; + return 1; +} + /****************************/ /* Cursor utility functions */ /****************************/ @@ -606,8 +640,7 @@ void txt_move_up(Text *text, short sel) if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); } } else { - *charp= 0; - if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); + txt_move_bol(text, sel); } if(!sel) txt_pop_sel(text); @@ -632,8 +665,7 @@ void txt_move_down(Text *text, short sel) } else if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); } else { - *charp= (*linep)->len; - if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); + txt_move_eol(text, sel); } if(!sel) txt_pop_sel(text); @@ -689,6 +721,68 @@ void txt_move_right(Text *text, short sel) if(!sel) txt_pop_sel(text); } +void txt_jump_left(Text *text, short sel) +{ + TextLine **linep, *oldl; + int *charp, oldc, count, i; + unsigned char oldu; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + + oldl= *linep; + oldc= *charp; + oldu= undoing; + undoing= 1; /* Don't push individual moves to undo stack */ + + count= 0; + for (i=0; i<3; i++) { + if (count < 2) { + while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) { + txt_move_left(text, sel); + count++; + } + } + } + if (count==0) txt_move_left(text, sel); + + undoing= oldu; + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +void txt_jump_right(Text *text, short sel) +{ + TextLine **linep, *oldl; + int *charp, oldc, count, i; + unsigned char oldu; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + + oldl= *linep; + oldc= *charp; + oldu= undoing; + undoing= 1; /* Don't push individual moves to undo stack */ + + count= 0; + for (i=0; i<3; i++) { + if (count < 2) { + while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) { + txt_move_right(text, sel); + count++; + } + } + } + if (count==0) txt_move_right(text, sel); + + undoing= oldu; + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + void txt_move_bol (Text *text, short sel) { TextLine **linep; @@ -760,6 +854,11 @@ void txt_move_eof (Text *text, short sel) } void txt_move_toline (Text *text, unsigned int line, short sel) +{ + txt_move_to(text, line, 0, sel); +} + +void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel) { TextLine **linep, *oldl; int *charp, oldc; @@ -777,10 +876,12 @@ void txt_move_toline (Text *text, unsigned int line, short sel) if ((*linep)->next) *linep= (*linep)->next; else break; } - *charp= 0; + if (ch>(*linep)->len) + ch= (*linep)->len; + *charp= ch; if(!sel) txt_pop_sel(text); - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -865,7 +966,9 @@ int txt_has_sel(Text *text) static void txt_delete_sel (Text *text) { TextLine *tmpl; - char *buf, *format; + TextMarker *mrk; + char *buf; + int move, lineno; if (!text) return; if (!text->curl) return; @@ -882,13 +985,33 @@ static void txt_delete_sel (Text *text) } buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string"); - format= MEM_mallocN(text->curc+(text->sell->len - text->selc)+2, "Syntax_format"); + if (text->curl != text->sell) { + txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); + move= txt_get_span(text->curl, text->sell); + } else { + mrk= txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); + if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) + txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); + move= 0; + } + + mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0, 0); + if (mrk) { + lineno= mrk->lineno; + do { + mrk->lineno -= move; + if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; + mrk->end -= text->selc - text->curc; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } + strncpy(buf, text->curl->line, text->curc); strcpy(buf+text->curc, text->sell->line + text->selc); buf[text->curc+(text->sell->len - text->selc)]=0; - make_new_line(text->curl, buf, format); + make_new_line(text->curl, buf); tmpl= text->sell; while (tmpl != text->curl) { @@ -995,22 +1118,31 @@ char *txt_to_buf (Text *text) return buf; } -int txt_find_string(Text *text, char *findstr) +int txt_find_string(Text *text, char *findstr, int wrap) { TextLine *tl, *startl; char *s= NULL; + int oldcl, oldsl, oldcc, oldsc; if (!text || !text->curl || !text->sell) return 0; txt_order_cursors(text); + oldcl= txt_get_span(text->lines.first, text->curl); + oldsl= txt_get_span(text->lines.first, text->sell); tl= startl= text->sell; + oldcc= text->curc; + oldsc= text->selc; s= strstr(&tl->line[text->selc], findstr); while (!s) { tl= tl->next; - if (!tl) - tl= text->lines.first; + if (!tl) { + if (wrap) + tl= text->lines.first; + else + break; + } s= strstr(tl->line, findstr); if (tl==startl) @@ -1018,10 +1150,10 @@ int txt_find_string(Text *text, char *findstr) } if (s) { - text->curl= text->sell= tl; - text->curc= (int) (s-tl->line); - text->selc= text->curc + strlen(findstr); - + int newl= txt_get_span(text->lines.first, tl); + int newc= (int)(s-tl->line); + txt_move_to(text, newl, newc, 0); + txt_move_to(text, newl, newc + strlen(findstr), 1); return 1; } else return 0; @@ -1621,7 +1753,6 @@ void txt_do_undo(Text *text) case UNDO_SWAP: txt_curs_swap(text); - txt_do_undo(text); /* swaps should appear transparent */ break; case UNDO_DBLOCK: @@ -1736,6 +1867,19 @@ void txt_do_undo(Text *text) break; } + + /* next undo step may need evaluating */ + if (text->undo_pos>=0) { + switch (text->undo_buf[text->undo_pos]) { + case UNDO_STO: + txt_do_undo(text); + txt_do_redo(text); /* selections need restoring */ + break; + case UNDO_SWAP: + txt_do_undo(text); /* swaps should appear transparent */ + break; + } + } undoing= 0; } @@ -1810,7 +1954,7 @@ void txt_do_redo(Text *text) case UNDO_SWAP: txt_curs_swap(text); - txt_do_undo(text); /* swaps should appear transparent a*/ + txt_do_redo(text); /* swaps should appear transparent a*/ break; case UNDO_CTO: @@ -1947,22 +2091,37 @@ void txt_do_redo(Text *text) void txt_split_curline (Text *text) { TextLine *ins; - char *left, *right, *fleft, *fright; + TextMarker *mrk; + char *left, *right; + int lineno= -1; if (!text) return; if (!text->curl) return; - txt_delete_sel(text); + txt_delete_sel(text); + + /* Move markers */ + + lineno= txt_get_span(text->lines.first, text->curl); + mrk= text->markers.first; + while (mrk) { + if (mrk->lineno==lineno && mrk->start>text->curc) { + mrk->lineno++; + mrk->start -= text->curc; + mrk->end -= text->curc; + } else if (mrk->lineno > lineno) { + mrk->lineno++; + } + mrk= mrk->next; + } /* Make the two half strings */ left= MEM_mallocN(text->curc+1, "textline_string"); - fleft= MEM_mallocN(text->curc+2, "Syntax_format"); if (text->curc) memcpy(left, text->curl->line, text->curc); left[text->curc]=0; right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string"); - fright= MEM_mallocN(text->curl->len - text->curc+2, "Syntax_format"); if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc); right[text->curl->len - text->curc]=0; @@ -1973,11 +2132,11 @@ void txt_split_curline (Text *text) ins= MEM_mallocN(sizeof(TextLine), "textline"); ins->line= left; - ins->format= fleft; + ins->format= NULL; ins->len= text->curc; text->curl->line= right; - text->curl->format= fright; + text->curl->format= NULL; text->curl->len= text->curl->len - text->curc; BLI_insertlinkbefore(&text->lines, text->curl, ins); @@ -1993,9 +2152,23 @@ void txt_split_curline (Text *text) static void txt_delete_line (Text *text, TextLine *line) { + TextMarker *mrk=NULL, *nxt; + int lineno= -1; + if (!text) return; if (!text->curl) return; + lineno= txt_get_span(text->lines.first, line); + mrk= text->markers.first; + while (mrk) { + nxt= mrk->next; + if (mrk->lineno==lineno) + BLI_freelinkN(&text->markers, mrk); + else if (mrk->lineno > lineno) + mrk->lineno--; + mrk= nxt; + } + BLI_remlink (&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2009,21 +2182,35 @@ static void txt_delete_line (Text *text, TextLine *line) static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb) { - char *tmp, *format; + char *tmp; + TextMarker *mrk= NULL; + int lineno=-1; if (!text) return; if(!linea || !lineb) return; + + mrk= txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); + if (mrk) { + lineno= mrk->lineno; + do { + mrk->lineno--; + mrk->start += linea->len; + mrk->end += linea->len; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } + if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb); + if (!mrk) mrk= text->markers.first; tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string"); - format= MEM_mallocN(linea->len+lineb->len+1, "Syntax_format"); strcpy(tmp, linea->line); strcat(tmp, lineb->line); - make_new_line(linea, tmp, format); + make_new_line(linea, tmp); - txt_delete_line(text, lineb); + txt_delete_line(text, lineb); txt_make_dirty(text); txt_clean_text(text); @@ -2037,8 +2224,9 @@ void txt_delete_char (Text *text) if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ - txt_delete_sel(text); - return; + txt_delete_sel(text); + txt_make_dirty(text); + return; } else if (text->curc== text->curl->len) { /* Appending two lines */ if (text->curl->next) { @@ -2047,6 +2235,25 @@ void txt_delete_char (Text *text) } } else { /* Just deleting a char */ int i= text->curc; + + TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0, 0); + if (mrk) { + int lineno= mrk->lineno; + if (mrk->end==i) { + if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { + txt_clear_markers(text, mrk->group, TMARK_TEMP); + } else { + //TextMarker *nxt= mrk->next; + BLI_freelinkN(&text->markers, mrk); + } + return; + } + do { + if (mrk->start>i) mrk->start--; + mrk->end--; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } c= text->curl->line[i]; while(i< text->curl->len) { @@ -2064,6 +2271,12 @@ void txt_delete_char (Text *text) if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c); } +void txt_delete_word (Text *text) +{ + txt_jump_right(text, 1); + txt_delete_sel(text); +} + void txt_backspace_char (Text *text) { char c='\n'; @@ -2072,8 +2285,9 @@ void txt_backspace_char (Text *text) if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ - txt_delete_sel(text); - return; + txt_delete_sel(text); + txt_make_dirty(text); + return; } else if (text->curc==0) { /* Appending two lines */ if (!text->curl->prev) return; @@ -2083,19 +2297,38 @@ void txt_backspace_char (Text *text) txt_combine_lines(text, text->curl, text->curl->next); txt_pop_sel(text); - } + } else { /* Just backspacing a char */ - int i= text->curc-1; + int i= text->curc-1; + + TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0, 0); + if (mrk) { + int lineno= mrk->lineno; + if (mrk->start==i+1) { + if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { + txt_clear_markers(text, mrk->group, TMARK_TEMP); + } else { + //TextMarker *nxt= mrk->next; + BLI_freelinkN(&text->markers, mrk); + } + return; + } + do { + if (mrk->start>i) mrk->start--; + mrk->end--; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } - c= text->curl->line[i]; - while(i< text->curl->len) { - text->curl->line[i]= text->curl->line[i+1]; - i++; - } - text->curl->len--; - text->curc--; - - txt_pop_sel(text); + c= text->curl->line[i]; + while(i< text->curl->len) { + text->curl->line[i]= text->curl->line[i+1]; + i++; + } + text->curl->len--; + text->curc--; + + txt_pop_sel(text); } txt_make_dirty(text); @@ -2104,10 +2337,17 @@ void txt_backspace_char (Text *text) if(!undoing) txt_undo_add_charop(text, UNDO_BS, c); } +void txt_backspace_word (Text *text) +{ + txt_jump_left(text, 1); + txt_delete_sel(text); +} + int txt_add_char (Text *text, char add) { - int len; - char *tmp, *format; + int len, lineno; + char *tmp; + TextMarker *mrk; if (!text) return 0; if (!text->curl) return 0; @@ -2119,8 +2359,17 @@ int txt_add_char (Text *text, char add) txt_delete_sel(text); + mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0, 0); + if (mrk) { + lineno= mrk->lineno; + do { + if (mrk->start>text->curc) mrk->start++; + mrk->end++; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } + tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - format= MEM_mallocN(text->curl->len+4, "Syntax_format"); if(text->curc) memcpy(tmp, text->curl->line, text->curc); tmp[text->curc]= add; @@ -2128,7 +2377,7 @@ int txt_add_char (Text *text, char add) len= text->curl->len - text->curc; if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp, format); + make_new_line(text->curl, tmp); text->curc++; @@ -2141,10 +2390,42 @@ int txt_add_char (Text *text, char add) return 1; } +int txt_replace_char (Text *text, char add) +{ + char del; + + if (!text) return 0; + if (!text->curl) return 0; + + /* If text is selected or we're at the end of the line just use txt_add_char */ + if (text->curc==text->curl->len || txt_has_sel(text) || add=='\n') { + TextMarker *mrk; + int i= txt_add_char(text, add); + mrk= txt_find_marker(text, text->curl, text->curc, 0, 0); + if (mrk && mrk->end==text->curc) mrk->end--; + return i; + } + + del= text->curl->line[text->curc]; + text->curl->line[text->curc]= (unsigned char) add; + text->curc++; + txt_pop_sel(text); + + txt_make_dirty(text); + txt_clean_text(text); + + /* Should probably create a new op for this */ + if(!undoing) { + txt_undo_add_charop(text, UNDO_DEL, del); + txt_undo_add_charop(text, UNDO_INSERT, add); + } + return 1; +} + void indent(Text *text) { int len, num; - char *tmp, *format; + char *tmp; char add = '\t'; if (!text) return; @@ -2155,7 +2436,6 @@ void indent(Text *text) while (TRUE) { tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - format= MEM_mallocN(text->curl->len+3, "Syntax_format"); text->curc = 0; if(text->curc) memcpy(tmp, text->curl->line, text->curc); @@ -2165,7 +2445,7 @@ void indent(Text *text) if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp, format); + make_new_line(text->curl, tmp); text->curc++; @@ -2246,7 +2526,7 @@ void unindent(Text *text) void comment(Text *text) { int len, num; - char *tmp, *format; + char *tmp; char add = '#'; if (!text) return; @@ -2257,7 +2537,6 @@ void comment(Text *text) while (TRUE) { tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - format = MEM_mallocN(text->curl->len+3, "Syntax_format"); text->curc = 0; if(text->curc) memcpy(tmp, text->curl->line, text->curc); @@ -2267,7 +2546,7 @@ void comment(Text *text) if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp, format); + make_new_line(text->curl, tmp); text->curc++; @@ -2398,3 +2677,148 @@ int setcurr_tab (Text *text) return i; } +/*********************************/ +/* Text marker utility functions */ +/*********************************/ + +static int color_match(TextMarker *a, TextMarker *b) { + return (a->color[0]==b->color[0] && + a->color[1]==b->color[1] && + a->color[2]==b->color[2] && + a->color[3]==b->color[3]); +} + +/* Creates and adds a marker to the list maintaining sorted order */ +void txt_add_marker(Text *text, TextLine *line, int start, int end, char color[4], int group, int flags) { + TextMarker *tmp, *marker; + + marker= MEM_mallocN(sizeof(TextMarker), "text_marker"); + + marker->lineno= txt_get_span(text->lines.first, line); + marker->start= MIN2(start, end); + marker->end= MAX2(start, end); + marker->group= group; + marker->flags= flags; + + marker->color[0]= color[0]; + marker->color[1]= color[1]; + marker->color[2]= color[2]; + marker->color[3]= color[3]; + + for (tmp=text->markers.last; tmp; tmp=tmp->prev) + if (tmp->lineno < marker->lineno || (tmp->lineno==marker->lineno && tmp->start < marker->start)) + break; + + if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); + else BLI_addhead(&text->markers, marker); +} + +/* Returns the first matching marker on the specified line between two points. + If the group or flags fields are non-zero the returned flag must be in the + specified group and have at least the specified flags set. */ +TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) { + TextMarker *marker, *next; + int lineno= txt_get_span(text->lines.first, line); + + for (marker=text->markers.first; marker; marker=next) { + next= marker->next; + + if (group && marker->group != group) continue; + else if ((marker->flags & flags) != flags) continue; + else if (marker->lineno < lineno) continue; + else if (marker->lineno > lineno) break; + + if ((marker->start==marker->end && start<=marker->start && marker->start<=end) || + (marker->startend>start)) + return marker; + } + return NULL; +} + +/* Clears all markers on the specified line between two points. If the group or + flags fields are non-zero the returned flag must be in the specified group + and have at least the specified flags set. */ +short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) { + TextMarker *marker, *next; + int lineno= txt_get_span(text->lines.first, line); + short cleared= 0; + + for (marker=text->markers.first; marker; marker=next) { + next= marker->next; + + if (group && marker->group != group) continue; + else if ((marker->flags & flags) != flags) continue; + else if (marker->lineno < lineno) continue; + else if (marker->lineno > lineno) break; + + if ((marker->start==marker->end && start<=marker->start && marker->start<=end) || + (marker->startend>start)) { + BLI_freelinkN(&text->markers, marker); + cleared= 1; + } + } + return cleared; +} + +/* Clears all markers in the specified group (if given) with at least the + specified flags set. Useful for clearing temporary markers (group=0, + flags=TMARK_TEMP) */ +short txt_clear_markers(Text *text, int group, int flags) { + TextMarker *marker, *next; + short cleared= 0; + + for (marker=text->markers.first; marker; marker=next) { + next= marker->next; + + if ((!group || marker->group==group) && + (marker->flags & flags) == flags) { + BLI_freelinkN(&text->markers, marker); + cleared= 1; + } + } + return cleared; +} + +/* Finds the marker at the specified line and cursor position with at least the + specified flags set in the given group (if non-zero). */ +TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) { + TextMarker *marker; + int lineno= txt_get_span(text->lines.first, line); + + for (marker=text->markers.first; marker; marker=marker->next) { + if (group && marker->group != group) continue; + else if ((marker->flags & flags) != flags) continue; + else if (marker->lineno < lineno) continue; + else if (marker->lineno > lineno) break; + + if (marker->start <= curs && curs <= marker->end) + return marker; + } + return NULL; +} + +/* Finds the previous marker in the same group. If no other is found, the same + marker will be returned */ +TextMarker *txt_prev_marker(Text *text, TextMarker *marker) { + TextMarker *tmp= marker; + while (tmp) { + if (tmp->prev) tmp= tmp->prev; + else tmp= text->markers.last; + if (tmp->group == marker->group) + return tmp; + } + return NULL; /* Only if marker==NULL */ +} + +/* Finds the next marker in the same group. If no other is found, the same + marker will be returned */ +TextMarker *txt_next_marker(Text *text, TextMarker *marker) { + TextMarker *tmp= marker; + while (tmp) { + if (tmp->next) tmp= tmp->next; + else tmp= text->markers.first; + if (tmp->group == marker->group) + return tmp; + } + return NULL; /* Only if marker==NULL */ +} diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 936381c85cc..bb726887d32 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -53,6 +53,7 @@ #include "DNA_world_types.h" #include "DNA_brush_types.h" #include "DNA_node_types.h" +#include "DNA_color_types.h" #include "DNA_scene_types.h" #include "IMB_imbuf_types.h" @@ -390,6 +391,17 @@ int do_colorband(ColorBand *coba, float in, float out[4]) return 1; /* OK */ } +void colorband_table_RGBA(ColorBand *coba, float **array, int *size) +{ + int a; + + *size = CM_TABLE+1; + *array = MEM_callocN(sizeof(float)*(*size)*4, "ColorBand"); + + for(a=0; a<*size; a++) + do_colorband(coba, (float)a/(float)CM_TABLE, &(*array)[a*4]); +} + /* ******************* TEX ************************ */ void free_texture(Tex *tex) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index c22b6f79e08..6e54fae58d0 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -164,6 +164,7 @@ void Mat3Inv(float m1[][3], float m2[][3]); void Mat3CpyMat4(float m1[][3],float m2[][4]); void Mat4CpyMat3(float m1[][4], float m2[][3]); +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight); void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight); float Det2x2(float a,float b,float c, float d); @@ -260,6 +261,7 @@ void Vec2Mulf(float *v1, float f); void Vec2Addf(float *v, float *v1, float *v2); void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); +void Vec2Lerpf(float *target, float *a, float *b, float t); void AxisAngleToQuat(float *q, float *axis, float angle); void vectoquat(float *vec, short axis, short upflag, float *q); diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index e24ccad12fb..a1db7adf33d 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -73,7 +73,6 @@ extern ListBase fillvertbase; * @attention Defined in scanfill.c */ extern ListBase filledgebase; -extern int totblock; extern char btempdir[]; /* creator.c temp dir used instead of U.tempdir, set with BLI_where_is_temp( btempdir, 1 ); */ @@ -152,6 +151,7 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds */ int BLI_convertstringcode(char *path, const char *basepath); int BLI_convertstringframe(char *path, int frame); +int BLI_convertstringcwd(char *path); void BLI_makestringcode(const char *relfile, char *file); diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6d9a17efebf..e3591a84e98 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -54,6 +54,7 @@ typedef struct BVHTreeRay { float origin[3]; /* ray origin */ float direction[3]; /* ray direction */ + float radius; /* radius around ray */ } BVHTreeRay; typedef struct BVHTreeRayHit @@ -90,7 +91,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index 649d3cb5659..65cebf02f62 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -24,4 +24,4 @@ if env['OURPLATFORM'] == 'linux2': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [85,195], compileflags =cflags ) +env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core', 'intern', 'player'], priority = [85,150,195], compileflags =cflags ) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index c41c3d8c3ab..30472beb3e6 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -51,6 +51,7 @@ typedef struct BVHNode { struct BVHNode **children; + struct BVHNode *parent; // some user defined traversed need that 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 @@ -82,7 +83,7 @@ typedef struct BVHOverlapData typedef struct BVHNearestData { BVHTree *tree; - float *co; + const float *co; BVHTree_NearestPointCallback callback; void *userdata; float proj[13]; //coordinates projection over axis @@ -481,7 +482,7 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; for(i=0; iindex, node - tree->nodearray); + printf(" - %d (%ld): ", node->index, node - tree->nodearray); for(i=2*tree->start_axis; i<2*tree->stop_axis; i++) printf("%.3f ", node->bv[i]); printf("\n"); @@ -496,10 +497,10 @@ static void bvhtree_info(BVHTree *tree) printf("BVHTree info\n"); printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %dbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); + printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv)); - printf("Total memory = %dbytes\n", sizeof(BVHTree) + printf("Total memory = %ldbytes\n", sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + MEM_allocN_len(tree->nodechild) @@ -700,6 +701,10 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHBuildHelper data; int depth; + + // set parent from root node to NULL + BVHNode *tmp = branches_array+0; + tmp->parent = NULL; //Most of bvhtree code relies on 1-leaf trees having at least one branch //We handle that special case here @@ -709,7 +714,8 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, refit_kdop_hull(tree, root, 0, num_leafs); root->main_axis = get_largest_axis(root->bv) / 2; root->totnode = 1; - root->children[0] = leafs_array[0]; + root->children[0] = leafs_array[0]; + root->children[0]->parent = root; return; } @@ -772,9 +778,15 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); if(child_leafs_end - child_leafs_begin > 1) + { parent->children[k] = branches_array + child_index; + parent->children[k]->parent = parent; + } else if(child_leafs_end - child_leafs_begin == 1) + { parent->children[k] = leafs_array[ child_leafs_begin ]; + parent->children[k]->parent = parent; + } else break; @@ -1096,7 +1108,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) BVHOverlapData **data; // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) - if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) + if((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18)) return 0; // fast check root nodes for collision before doing big splitting + traversal @@ -1248,7 +1260,6 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) { - int i; float nearest[3], sdist; sdist = calc_nearest_point(data, node, nearest); if(sdist >= data->nearest.dist) return; @@ -1403,14 +1414,14 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) if(data->ray_dot_axis[i] == 0.0f) { //axis aligned ray - if(data->ray.origin[i] < bv[0] - || data->ray.origin[i] > bv[1]) + if(data->ray.origin[i] < bv[0] - data->ray.radius + || data->ray.origin[i] > bv[1] + data->ray.radius) return FLT_MAX; } else { - float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; + float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; if(data->ray_dot_axis[i] > 0.0f) { @@ -1469,7 +1480,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; @@ -1482,6 +1493,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTr VECCOPY(data.ray.origin, co); VECCOPY(data.ray.direction, dir); + data.ray.radius = radius; Normalize(data.ray.direction); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index c1edb7d3ac1..844c0cc909a 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -758,6 +758,28 @@ void Mat4MulSerie(float answ[][4], float m1[][4], } } +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float rmat[3][3], smat[3][3]; + + Mat3ToQuat(dst, dquat); + Mat3ToSize(dst, dsize); + + Mat3ToQuat(src, squat); + Mat3ToSize(src, ssize); + + /* do blending */ + QuatInterpol(fquat, dquat, squat, srcweight); + VecLerpf(fsize, dsize, ssize, srcweight); + + /* compose new matrix */ + QuatToMat3(fquat, rmat); + SizeToMat3(fsize, smat); + Mat3MulMat3(out, rmat, smat); +} + void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight) { float squat[4], dquat[4], fquat[4]; @@ -2112,6 +2134,14 @@ void VecLerpf(float *target, float *a, float *b, float t) target[2]= s*a[2] + t*b[2]; } +void Vec2Lerpf(float *target, float *a, float *b, float t) +{ + float s = 1.0f-t; + + target[0]= s*a[0] + t*b[0]; + target[1]= s*a[1] + t*b[1]; +} + void VecMidf(float *v, float *v1, float *v2) { v[0]= 0.5f*(v1[0]+ v2[0]); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index a31121148e3..c27efcb7934 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1211,6 +1211,49 @@ int BLI_convertstringcode(char *path, const char *basepath) return wasrelative; } + +/* + * Should only be done with command line paths. + * this is NOT somthing blenders internal paths support like the // prefix + */ +int BLI_convertstringcwd(char *path) +{ + int wasrelative = 1; + int filelen = strlen(path); + +#ifdef WIN32 + if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) + wasrelative = 0; +#else + if (filelen >= 2 && path[0] == '/') + wasrelative = 0; +#endif + + if (wasrelative==1) { + char cwd[FILE_MAXDIR + FILE_MAXFILE]; + BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + + if (cwd[0] == '\0') { + printf( "Could not get the current working directory - $PWD for an unknown reason."); + } else { + /* uses the blend path relative to cwd important for loading relative linked files. + * + * cwd should contain c:\ etc on win32 so the relbase can be NULL + * relbase being NULL also prevents // being misunderstood as relative to the current + * blend file which isnt a feature we want to use in this case since were dealing + * with a path from the command line, rather then from inside Blender */ + + char origpath[FILE_MAXDIR + FILE_MAXFILE]; + BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE); + + BLI_make_file_string(NULL, path, cwd, origpath); + } + } + + return wasrelative; +} + + /* copy di to fi, filename only */ void BLI_splitdirstring(char *di, char *fi) { diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index ff2a256f606..4aa2a229dcc 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -237,7 +237,7 @@ void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode); void BLO_library_append_(BlendHandle **libfiledata, struct direntry* filelist, int totfile, char *dir, char* file, short flag, int idcode); void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Scene *scene); -BlendFileData* blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r); +BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r); #ifdef __cplusplus } diff --git a/source/blender/blenloader/BLO_sys_types.h b/source/blender/blenloader/BLO_sys_types.h index a9d29375eac..49155260b31 100644 --- a/source/blender/blenloader/BLO_sys_types.h +++ b/source/blender/blenloader/BLO_sys_types.h @@ -49,6 +49,7 @@ extern "C" { /* The __intXX are built-in types of the visual complier! So we don't * need to include anything else here. */ + typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; @@ -59,13 +60,23 @@ typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; +#ifndef _INTPTR_T_DEFINED #ifdef _WIN64 typedef __int64 intptr_t; -typedef unsigned __int64 uintptr_t; #else typedef long intptr_t; +#endif +#define _INTPTR_T_DEFINED +#endif + +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else typedef unsigned long uintptr_t; #endif +#define _UINTPTR_T_DEFINED +#endif #elif defined(__linux__) @@ -87,6 +98,7 @@ typedef unsigned long uintptr_t; #endif /* ifdef platform for types */ + #ifdef _WIN32 #define htonl(x) correctByteOrder(x) #define ntohl(x) correctByteOrder(x) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 35ca42a4949..8e792426998 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -970,9 +970,11 @@ FileData *blo_openblenderfile(char *name, BlendReadError *error_r) } else { FileData *fd = filedata_new(); fd->gzfiledes = gzfile; - BLI_strncpy(fd->filename, name, sizeof(fd->filename)); // now only in use by library append fd->read = fd_read_gzip_from_file; + /* needed for library_append and read_libraries */ + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); + return blo_decode_and_check(fd, error_r); } } @@ -1138,6 +1140,8 @@ void blo_make_image_pointer_map(FileData *fd) Link *ibuf= ima->ibufs.first; for(; ibuf; ibuf= ibuf->next) oldnewmap_insert(fd->imamap, ibuf, ibuf, 0); + if(ima->gputexture) + oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -1172,8 +1176,11 @@ void blo_end_image_pointer_map(FileData *fd) if(NULL==newimaadr(fd, ibuf)) { /* so was restored */ BLI_remlink(&ima->ibufs, ibuf); ima->bindcode= 0; + ima->gputexture= NULL; } } + + ima->gputexture= newimaadr(fd, ima->gputexture); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -2280,6 +2287,7 @@ static void direct_link_text(FileData *fd, Text *text) */ link_list(fd, &text->lines); + link_list(fd, &text->markers); text->curl= newdataadr(fd, text->curl); text->sell= newdataadr(fd, text->sell); @@ -2346,8 +2354,10 @@ static void direct_link_image(FileData *fd, Image *ima) ima->ibufs.first= ima->ibufs.last= NULL; /* if not restored, we keep the binded opengl index */ - if(ima->ibufs.first==NULL) + if(ima->ibufs.first==NULL) { ima->bindcode= 0; + ima->gputexture= NULL; + } ima->anim= NULL; ima->rr= NULL; @@ -2558,6 +2568,7 @@ static void direct_link_material(FileData *fd, Material *ma) direct_link_nodetree(fd, ma->nodetree); ma->preview = direct_link_preview_image(fd, ma->preview); + ma->gpumaterial.first = ma->gpumaterial.last = NULL; } /* ************ READ PARTICLE SETTINGS ***************** */ @@ -3396,6 +3407,7 @@ static void direct_link_object(FileData *fd, Object *ob) ob->bb= NULL; ob->derivedDeform= NULL; ob->derivedFinal= NULL; + ob->gpulamp.first= ob->gpulamp.last= NULL; } /* ************ READ SCENE ***************** */ @@ -4170,6 +4182,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sima->cumap= newdataadr(fd, sima->cumap); if(sima->cumap) direct_link_curvemapping(fd, sima->cumap); + sima->gpd= newdataadr(fd, sima->gpd); + if (sima->gpd) + link_gpencil(fd, sima->gpd); sima->iuser.ok= 1; } else if(sl->spacetype==SPACE_NODE) { @@ -7754,14 +7769,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if(main->versionfile <= 246 && main->subversionfile < 1){ + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) { Mesh *me; for(me=main->mesh.first; me; me= me->id.next) alphasort_version_246(fd, lib, me); } - if(main->versionfile <= 246 && main->subversionfile < 1){ + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)){ Object *ob; for(ob = main->object.first; ob; ob= ob->id.next) { if(ob->pd && (ob->pd->forcefield == PFIELD_WIND)) @@ -7769,6 +7784,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 2)){ + Object *ob; + for(ob = main->object.first; ob; ob= ob->id.next) { + ob->gameflag |= OB_PHYSICS; + ob->margin = 0.06; + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ @@ -9124,7 +9147,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) /* reading runtime */ -BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r) +BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r) { BlendFileData *bfd = NULL; FileData *fd = filedata_new(); @@ -9132,6 +9155,9 @@ BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadErr fd->buffersize = actualsize; fd->read = fd_read_from_file; + /* needed for library_append and read_libraries */ + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); + fd = blo_decode_and_check(fd, error_r); if (!fd) return NULL; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d596f57990f..44634a7468c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1698,7 +1698,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceImage", 1, sl); if(sima->cumap) - write_curvemapping(wd, sima->cumap); + write_curvemapping(wd, sima->cumap); + if(sima->gpd) + write_gpencil(wd, sima->gpd); } else if(sl->spacetype==SPACE_IMASEL) { writestruct(wd, DATA, "SpaceImaSel", 1, sl); @@ -1849,6 +1851,7 @@ static void write_texts(WriteData *wd, ListBase *idbase) { Text *text; TextLine *tmp; + TextMarker *mrk; text= idbase->first; while(text) { @@ -1872,7 +1875,16 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } + + /* write markers */ + mrk= text->markers.first; + while (mrk) { + writestruct(wd, DATA, "TextMarker", 1, mrk); + mrk= mrk->next; + } } + + text= text->id.next; } diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt new file mode 100644 index 00000000000..4d376f47d91 --- /dev/null +++ b/source/blender/gpu/CMakeLists.txt @@ -0,0 +1,34 @@ +# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ +# ***** 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/*.c) + +SET(INC + . ../blenlib ../blenkernel ../makesdna ../include + ../../../extern/glew/include ../../../intern/guardedalloc ../imbuf) + +BLENDERLIB(bf_gpu "${SRC}" "${INC}") + diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h new file mode 100644 index 00000000000..2399e7b6a8c --- /dev/null +++ b/source/blender/gpu/GPU_draw.h @@ -0,0 +1,116 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef GPU_GAME_H +#define GPU_GAME_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct MTFace; +struct Image; +struct Scene; +struct Object; + +/* OpenGL drawing functions related to shading. These are also + * shared with the game engine, where there were previously + * duplicates of some of these functions. */ + +/* Initialize + * - sets the default Blender opengl state, if in doubt, check + * the contents of this function + * - this is called when starting Blender, for opengl rendering, + * and for switching back from the game engine for example. */ + +void GPU_state_init(void); + +/* Material drawing + * - first the state is initialized by a particular object and + * it's materials + * - after this, materials can be quickly enabled by their number, + * GPU_enable_material returns 0 if drawing should be skipped + * - after drawing, the material must be disabled again */ + +void GPU_set_object_materials(struct Scene *scene, struct Object *ob, + int glsl, int *do_alpha_pass); +int GPU_enable_material(int nr, void *attribs); +void GPU_disable_material(void); + +void GPU_set_material_blend_mode(int blendmode); +int GPU_get_material_blend_mode(void); + +/* TexFace drawing + * - this is mutually exclusive with material drawing, a mesh should + * be drawn using one or the other + * - passing NULL clears the state again */ + +int GPU_set_tpage(struct MTFace *tface); + +/* Lights + * - returns how many lights were enabled + * - this affects fixed functions materials and texface, not glsl */ + +int GPU_default_lights(void); +int GPU_scene_object_lights(struct Scene *scene, struct Object *ob, + int lay, float viewmat[][4]); + +/* Text render + * - based on moving uv coordinates */ + +void GPU_render_text(struct MTFace *tface, int mode, + const char *textstr, int textlen, unsigned int *col, + float *v1, float *v2, float *v3, float *v4, int glattrib); + +/* Mipmap settings + * - these will free textures on changes */ + +void GPU_set_mipmap(int mipmap); +void GPU_set_linear_mipmap(int linear); +void GPU_paint_set_mipmap(int mipmap); + +/* Image updates and free + * - these deal with images bound as opengl textures */ + +void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h); +void GPU_update_images_framechange(void); +int GPU_update_image_time(struct Image *ima, double time); +int GPU_verify_image(struct Image *ima, int tftile, int tfmode, int compare); +void GPU_free_image(struct Image *ima); +void GPU_free_images(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h new file mode 100644 index 00000000000..d3faa81ebb1 --- /dev/null +++ b/source/blender/gpu/GPU_extensions.h @@ -0,0 +1,144 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef GPU_EXTENSIONS_H +#define GPU_EXTENSIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* GPU extensions support */ + +struct Image; +struct ImageUser; + +struct GPUTexture; +typedef struct GPUTexture GPUTexture; + +struct GPUFrameBuffer; +typedef struct GPUFrameBuffer GPUFrameBuffer; + +struct GPUShader; +typedef struct GPUShader GPUShader; + +void GPU_extensions_init(void); /* call this before running any of the functions below */ +void GPU_extensions_exit(void); +int GPU_extensions_minimum_support(void); +int GPU_print_error(char *str); + +/* GPU Texture + - always returns unsigned char RGBA textures + - if texture with non square dimensions is created, depending on the + graphics card capabilities the texture may actually be stored in a + larger texture with power of two dimensions. the actual dimensions + may be querd with GPU_texture_opengl_width/height. GPU_texture_coord_2f + calls glTexCoord2f with the coordinates adjust for this. + - can use reference counting: + - reference counter after GPU_texture_create is 1 + - GPU_texture_ref increases by one + - GPU_texture_free decreases by one, and frees if 0 + - if created with from_blender, will not free the texture +*/ + +GPUTexture *GPU_texture_create_1D(int w, float *pixels); +GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels); +GPUTexture *GPU_texture_create_depth(int w, int h); +GPUTexture *GPU_texture_from_blender(struct Image *ima, + struct ImageUser *iuser, double time); +void GPU_texture_free(GPUTexture *tex); + +void GPU_texture_ref(GPUTexture *tex); + +void GPU_texture_bind(GPUTexture *tex, int number); +void GPU_texture_unbind(GPUTexture *tex); + +GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); + +int GPU_texture_target(GPUTexture *tex); +int GPU_texture_opengl_width(GPUTexture *tex); +int GPU_texture_opengl_height(GPUTexture *tex); + +/* GPU Framebuffer + - this is a wrapper for an OpenGL framebuffer object (FBO). in practice + multiple FBO's may be created, to get around limitations on the number + of attached textures and the dimension requirements. + - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must + be called before rendering to the window framebuffer again */ + +GPUFrameBuffer *GPU_framebuffer_create(); +int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_free(GPUFrameBuffer *fb); + +void GPU_framebuffer_restore(); + +/* GPU Shader + - only for fragment shaders now + - must call texture bind before setting a texture as uniform! */ + +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib); +GPUShader *GPU_shader_create_lib(const char *code); +void GPU_shader_free(GPUShader *shader); + +void GPU_shader_bind(GPUShader *shader); +void GPU_shader_unbind(); + +int GPU_shader_get_uniform(GPUShader *shader, char *name); +void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, + int arraysize, float *value); +void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex); + +int GPU_shader_get_attribute(GPUShader *shader, char *name); + +/* Vertex attributes for shaders */ + +#define GPU_MAX_ATTRIB 32 + +typedef struct GPUVertexAttribs { + struct { + int type; + int glindex; + char name[32]; + } layer[GPU_MAX_ATTRIB]; + + int totlayer; +} GPUVertexAttribs; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h new file mode 100644 index 00000000000..ccc687858f4 --- /dev/null +++ b/source/blender/gpu/GPU_material.h @@ -0,0 +1,169 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __GPU_MATERIAL__ +#define __GPU_MATERIAL__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Image; +struct ImageUser; +struct Material; +struct Object; +struct Lamp; +struct bNode; +struct LinkNode; +struct Scene; +struct GPUVertexAttribs; +struct GPUNode; +struct GPUNodeLink; +struct GPUNodeStack; +struct GPUMaterial; +struct GPUTexture; +struct GPULamp; + +typedef struct GPUNode GPUNode; +typedef struct GPUNodeLink GPUNodeLink; +typedef struct GPUMaterial GPUMaterial; +typedef struct GPULamp GPULamp; + +/* Functions to create GPU Materials nodes */ + +typedef enum GPUType { + GPU_NONE = 0, + GPU_FLOAT = 1, + GPU_VEC2 = 2, + GPU_VEC3 = 3, + GPU_VEC4 = 4, + GPU_MAT3 = 9, + GPU_MAT4 = 16, + GPU_TEX1D = 1001, + GPU_TEX2D = 1002, + GPU_SHADOW2D = 1003, + GPU_ATTRIB = 3001 +} GPUType; + +typedef enum GPUBuiltin { + GPU_VIEW_MATRIX = 1, + GPU_OBJECT_MATRIX = 2, + GPU_INVERSE_VIEW_MATRIX = 4, + GPU_INVERSE_OBJECT_MATRIX = 8, + GPU_VIEW_POSITION = 16, + GPU_VIEW_NORMAL = 32, + GPU_OBCOLOR = 64 +} GPUBuiltin; + +typedef enum GPUBlendMode { + GPU_BLEND_SOLID = 0, + GPU_BLEND_ADD = 1, + GPU_BLEND_ALPHA = 2, + GPU_BLEND_CLIP = 4 +} GPUBlendMode; + +typedef struct GPUNodeStack { + GPUType type; + char *name; + float vec[4]; + struct GPUNodeLink *link; + short hasinput; + short hasoutput; + short sockettype; +} GPUNodeStack; + +GPUNodeLink *GPU_attribute(int type, char *name); +GPUNodeLink *GPU_uniform(float *num); +GPUNodeLink *GPU_dynamic_uniform(float *num); +GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_texture(int size, float *pixels); +GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex); +GPUNodeLink *GPU_socket(GPUNodeStack *sock); +GPUNodeLink *GPU_builtin(GPUBuiltin builtin); + +int GPU_link(GPUMaterial *mat, char *name, ...); +int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...); + +void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); +void GPU_material_enable_alpha(GPUMaterial *material); +GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[4]); + +/* High level functions to create and use GPU materials */ + +GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma); +void GPU_material_free(struct Material *ma); + +void GPU_materials_free(); + +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time); +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]); +void GPU_material_unbind(GPUMaterial *material); +int GPU_material_bound(GPUMaterial *material); + +void GPU_material_vertex_attributes(GPUMaterial *material, + struct GPUVertexAttribs *attrib); + +/* Exported shading */ + +typedef struct GPUShadeInput { + GPUMaterial *gpumat; + struct Material *mat; + + GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref; + GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb; +} GPUShadeInput; + +typedef struct GPUShadeResult { + GPUNodeLink *diff, *spec, *combined, *alpha; +} GPUShadeResult; + +void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi); +void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr); + +/* Lamps */ + +GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par); +void GPU_lamp_free(struct Object *ob); + +int GPU_lamp_has_shadow_buffer(GPULamp *lamp); +void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]); +void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); + +void GPU_lamp_update(GPULamp *lamp, int lay, float obmat[][4]); +int GPU_lamp_shadow_layer(GPULamp *lamp); + +#ifdef __cplusplus +} +#endif + +#endif /*__GPU_MATERIAL__*/ + diff --git a/source/blender/gpu/Makefile b/source/blender/gpu/Makefile new file mode 100644 index 00000000000..b9bde147115 --- /dev/null +++ b/source/blender/gpu/Makefile @@ -0,0 +1,37 @@ +# +# $Id$ +# +# ***** 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. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# Makes module object directory and bounces make to subdirectories. + +SOURCEDIR = source/blender/gpu +DIRS = intern + +include nan_subdirs.mk diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript new file mode 100644 index 00000000000..8ccd4b7b24c --- /dev/null +++ b/source/blender/gpu/SConscript @@ -0,0 +1,11 @@ +#!/usr/bin/python +Import ('env') + +sources = env.Glob('intern/*.c') + +incs = '../blenlib ../blenkernel ../makesdna ../include' +incs += ' #/extern/glew/include #intern/guardedalloc ../imbuf .' + +incs += ' ' + env['BF_OPENGL_INC'] + +env.BlenderLib ( 'bf_gpu', sources, Split(incs), [], libtype=['core', 'player'], priority=[65, 20] ) diff --git a/source/blender/gpu/intern/Makefile b/source/blender/gpu/intern/Makefile new file mode 100644 index 00000000000..733ee3f764c --- /dev/null +++ b/source/blender/gpu/intern/Makefile @@ -0,0 +1,53 @@ +# +# $Id$ +# +# ***** 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. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# + +LIBNAME = gpu +DIR = $(OCGDIR)/blender/$(LIBNAME) + +include nan_compile.mk + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) + CFLAGS += -funsigned-char +endif + +CFLAGS += $(LEVEL_1_C_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) + +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../blenkernel +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_GLEW)/include +CPPFLAGS += -I../ + diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c new file mode 100644 index 00000000000..00efe6e1572 --- /dev/null +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -0,0 +1,1441 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GL/glew.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_customdata_types.h" +#include "DNA_image_types.h" +#include "DNA_listBase.h" +#include "DNA_material_types.h" + +#include "BLI_dynstr.h" +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_heap.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" + +#include "GPU_material.h" +#include "GPU_extensions.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "gpu_codegen.h" + +#include +#include + +#ifdef _WIN32 +#ifndef vsnprintf +#define vsnprintf _vsnprintf +#endif +#ifndef snprintf +#define snprintf _snprintf +#endif +#endif + +extern char datatoc_gpu_shader_material_glsl[]; +extern char datatoc_gpu_shader_vertex_glsl[]; + +/* structs and defines */ + +typedef enum GPUDataSource { + GPU_SOURCE_VEC_UNIFORM, + GPU_SOURCE_BUILTIN, + GPU_SOURCE_TEX_PIXEL, + GPU_SOURCE_TEX, + GPU_SOURCE_ATTRIB +} GPUDataSource; + +static char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", + 0, 0, 0, 0, "mat3", 0, 0, 0, 0, 0, 0, "mat4"}; + +struct GPUNode { + struct GPUNode *next, *prev; + + char *name; + int tag; + + ListBase inputs; + ListBase outputs; +}; + +struct GPUNodeLink { + GPUNodeStack *socket; + + int attribtype; + char *attribname; + + int image; + + int texture; + int texturesize; + + void *ptr1, *ptr2; + + int dynamic; + + int type; + int users; + + GPUTexture *dynamictex; + + GPUBuiltin builtin; + + struct GPUOutput *output; +}; + +typedef struct GPUOutput { + struct GPUOutput *next, *prev; + + GPUNode *node; + int type; /* data type = length of vector/matrix */ + GPUNodeLink *link; /* output link */ + int id; /* unique id as created by code generator */ +} GPUOutput; + +typedef struct GPUInput { + struct GPUInput *next, *prev; + + GPUNode *node; + + int type; /* datatype */ + int source; /* data source */ + + int id; /* unique id as created by code generator */ + int texid; /* number for multitexture */ + int attribid; /* id for vertex attributes */ + int bindtex; /* input is responsible for binding the texture? */ + int definetex; /* input is responsible for defining the pixel? */ + int textarget; /* GL_TEXTURE_* */ + int textype; /* datatype */ + + struct Image *ima; /* image */ + struct ImageUser *iuser;/* image user */ + float *dynamicvec; /* vector data in case it is dynamic */ + GPUTexture *tex; /* input texture, only set at runtime */ + int shaderloc; /* id from opengl */ + char shadername[32]; /* name in shader */ + + float vec[16]; /* vector data */ + GPUNodeLink *link; + int dynamictex; /* dynamic? */ + int attribtype; /* attribute type */ + char attribname[32]; /* attribute name */ + int attribfirst; /* this is the first one that is bound */ + GPUBuiltin builtin; /* builtin uniform */ +} GPUInput; + +struct GPUPass { + struct GPUPass *next, *prev; + + ListBase inputs; + struct GPUOutput *output; + struct GPUShader *shader; +}; + +/* Strings utility */ + +static void BLI_dynstr_printf(DynStr *dynstr, const char *format, ...) +{ + va_list args; + int retval; + char str[2048]; + + va_start(args, format); + retval = vsnprintf(str, sizeof(str), format, args); + va_end(args); + + if (retval >= sizeof(str)) + fprintf(stderr, "BLI_dynstr_printf: limit exceeded\n"); + else + BLI_dynstr_append(dynstr, str); +} + +/* GLSL code parsing for finding function definitions. + * These are stored in a hash for lookup when creating a material. */ + +static GHash *FUNCTION_HASH= NULL; +static char *FUNCTION_PROTOTYPES= NULL; +static GPUShader *FUNCTION_LIB= NULL; + +static int gpu_str_prefix(char *str, char *prefix) +{ + while(*str && *prefix) { + if(*str != *prefix) + return 0; + + str++; + prefix++; + } + + return (*prefix == '\0'); +} + +static char *gpu_str_skip_token(char *str, char *token, int max) +{ + int len = 0; + + /* skip a variable/function name */ + while(*str) { + if(ELEM6(*str, ' ', '(', ')', ',', '\t', '\n')) + break; + else { + if(token && len < max-1) { + *token= *str; + token++; + len++; + } + str++; + } + } + + if(token) + *token= '\0'; + + /* skip the next special characters: + * note the missing ')' */ + while(*str) { + if(ELEM5(*str, ' ', '(', ',', '\t', '\n')) + str++; + else + break; + } + + return str; +} + +static void gpu_parse_functions_string(GHash *hash, char *code) +{ + GPUFunction *function; + int i, type, qual; + + while((code = strstr(code, "void "))) { + function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); + + code = gpu_str_skip_token(code, NULL, 0); + code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME); + + /* get parameters */ + while(*code && *code != ')') { + /* test if it's an input or output */ + qual = FUNCTION_QUAL_IN; + if(gpu_str_prefix(code, "out ")) + qual = FUNCTION_QUAL_OUT; + if(gpu_str_prefix(code, "inout ")) + qual = FUNCTION_QUAL_INOUT; + if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in ")) + code = gpu_str_skip_token(code, NULL, 0); + + /* test for type */ + type= 0; + for(i=1; i<=16; i++) { + if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) { + type= i; + break; + } + } + + if(!type && gpu_str_prefix(code, "sampler2DShadow")) + type= GPU_SHADOW2D; + if(!type && gpu_str_prefix(code, "sampler1D")) + type= GPU_TEX1D; + if(!type && gpu_str_prefix(code, "sampler2D")) + type= GPU_TEX2D; + + if(type) { + /* add paramater */ + code = gpu_str_skip_token(code, NULL, 0); + code = gpu_str_skip_token(code, NULL, 0); + function->paramqual[function->totparam]= qual; + function->paramtype[function->totparam]= type; + function->totparam++; + } + else { + fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name); + break; + } + } + + if(strlen(function->name) == 0 || function->totparam == 0) { + fprintf(stderr, "GPU functions parse error.\n"); + MEM_freeN(function); + break; + } + + BLI_ghash_insert(hash, function->name, function); + } +} + +static char *gpu_generate_function_prototyps(GHash *hash) +{ + DynStr *ds = BLI_dynstr_new(); + GHashIterator *ghi; + GPUFunction *function; + char *name, *prototypes; + int a; + + /* automatically generate function prototypes to add to the top of the + * generated code, to avoid have to add the actual code & recompile all */ + ghi = BLI_ghashIterator_new(hash); + + for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) { + name = BLI_ghashIterator_getValue(ghi); + function = BLI_ghashIterator_getValue(ghi); + + BLI_dynstr_printf(ds, "void %s(", name); + for(a=0; atotparam; a++) { + if(function->paramqual[a] == FUNCTION_QUAL_OUT) + BLI_dynstr_append(ds, "out "); + else if(function->paramqual[a] == FUNCTION_QUAL_INOUT) + BLI_dynstr_append(ds, "inout "); + + if(function->paramtype[a] == GPU_TEX1D) + BLI_dynstr_append(ds, "sampler1D"); + else if(function->paramtype[a] == GPU_TEX2D) + BLI_dynstr_append(ds, "sampler2D"); + else if(function->paramtype[a] == GPU_SHADOW2D) + BLI_dynstr_append(ds, "sampler2DShadow"); + else + BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); + + BLI_dynstr_printf(ds, " param%d", a); + + if(a != function->totparam-1) + BLI_dynstr_append(ds, ", "); + } + BLI_dynstr_append(ds, ");\n"); + } + + BLI_dynstr_append(ds, "\n"); + + prototypes = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return prototypes; +} + +GPUFunction *GPU_lookup_function(char *name) +{ + if(!FUNCTION_HASH) { + FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl); + FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH); + FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl); + } + + return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, name); +} + +void GPU_extensions_exit(void) +{ + extern Material defmaterial; // render module abuse... + + if(defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); + + if(FUNCTION_HASH) { + BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN); + FUNCTION_HASH = NULL; + } + if(FUNCTION_PROTOTYPES) { + MEM_freeN(FUNCTION_PROTOTYPES); + FUNCTION_PROTOTYPES = NULL; + } + if(FUNCTION_LIB) { + GPU_shader_free(FUNCTION_LIB); + FUNCTION_LIB = NULL; + } +} + +/* GLSL code generation */ + +static void codegen_convert_datatype(DynStr *ds, int from, int to, char *tmp, int id) +{ + char name[1024]; + + snprintf(name, sizeof(name), "%s%d", tmp, id); + + if (from == to) { + BLI_dynstr_append(ds, name); + } + else if (to == GPU_FLOAT) { + if (from == GPU_VEC4) + BLI_dynstr_printf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name); + else if (from == GPU_VEC3) + BLI_dynstr_printf(ds, "dot(%s, vec3(0.33))", name); + else if (from == GPU_VEC2) + BLI_dynstr_printf(ds, "%s.r", name); + } + else if (to == GPU_VEC2) { + if (from == GPU_VEC4) + BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name); + else if (from == GPU_VEC3) + BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name); + else if (from == GPU_FLOAT) + BLI_dynstr_printf(ds, "vec2(%s, 1.0)", name); + } + else if (to == GPU_VEC3) { + if (from == GPU_VEC4) + BLI_dynstr_printf(ds, "%s.rgb", name); + else if (from == GPU_VEC2) + BLI_dynstr_printf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_printf(ds, "vec3(%s, %s, %s)", name, name, name); + } + else { + if (from == GPU_VEC3) + BLI_dynstr_printf(ds, "vec4(%s, 1.0)", name); + else if (from == GPU_VEC2) + BLI_dynstr_printf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_printf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); + } +} + +static void codegen_print_datatype(DynStr *ds, int type, float *data) +{ + int i; + + BLI_dynstr_printf(ds, "%s(", GPU_DATATYPE_STR[type]); + + for(i=0; ilink) + return 0; + else if(input->ima) + return 1; + else + return input->tex != 0; +} + +char *GPU_builtin_name(GPUBuiltin builtin) +{ + if(builtin == GPU_VIEW_MATRIX) + return "unfviewmat"; + else if(builtin == GPU_OBJECT_MATRIX) + return "unfobmat"; + else if(builtin == GPU_INVERSE_VIEW_MATRIX) + return "unfinvviewmat"; + else if(builtin == GPU_INVERSE_OBJECT_MATRIX) + return "unfinvobmat"; + else if(builtin == GPU_VIEW_POSITION) + return "varposition"; + else if(builtin == GPU_VIEW_NORMAL) + return "varnormal"; + else if(builtin == GPU_OBCOLOR) + return "unfobcolor"; + else + return ""; +} + +static void codegen_set_unique_ids(ListBase *nodes) +{ + GHash *bindhash, *definehash; + GPUNode *node; + GPUInput *input; + GPUOutput *output; + int id = 1, texid = 0; + + bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + for (node=nodes->first; node; node=node->next) { + for (input=node->inputs.first; input; input=input->next) { + /* set id for unique names of uniform variables */ + input->id = id++; + input->bindtex = 0; + input->definetex = 0; + + /* set texid used for settings texture slot with multitexture */ + if (codegen_input_has_texture(input) && + ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) { + if (input->link) { + /* input is texture from buffer, assign only one texid per + buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->link)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link)); + } + else if(input->ima) { + /* input is texture from image, assign only one texid per + buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->ima)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima)); + } + else { + /* input is user created texture, we know there there is + only one, so assign new texid */ + input->bindtex = 1; + input->texid = texid++; + } + + /* make sure this pixel is defined exactly once */ + if (input->source == GPU_SOURCE_TEX_PIXEL) { + if(input->ima) { + if (!BLI_ghash_haskey(definehash, input->ima)) { + input->definetex = 1; + BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid)); + } + } + else { + if (!BLI_ghash_haskey(definehash, input->link)) { + input->definetex = 1; + BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid)); + } + } + } + } + } + + for (output=node->outputs.first; output; output=output->next) + /* set id for unique names of tmp variables storing output */ + output->id = id++; + } + + BLI_ghash_free(bindhash, NULL, NULL); + BLI_ghash_free(definehash, NULL, NULL); +} + +static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) +{ + GPUNode *node; + GPUInput *input; + char *name; + int builtins = 0; + + /* print uniforms */ + for (node=nodes->first; node; node=node->next) { + for (input=node->inputs.first; input; input=input->next) { + if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) { + /* create exactly one sampler for each texture */ + if (codegen_input_has_texture(input) && input->bindtex) + BLI_dynstr_printf(ds, "uniform %s samp%d;\n", + (input->textype == GPU_TEX1D)? "sampler1D": + (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow", + input->texid); + } + else if(input->source == GPU_SOURCE_BUILTIN) { + /* only define each builting uniform/varying once */ + if(!(builtins & input->builtin)) { + builtins |= input->builtin; + name = GPU_builtin_name(input->builtin); + + if(gpu_str_prefix(name, "unf")) { + BLI_dynstr_printf(ds, "uniform %s %s;\n", + GPU_DATATYPE_STR[input->type], name); + } + else { + BLI_dynstr_printf(ds, "varying %s %s;\n", + GPU_DATATYPE_STR[input->type], name); + } + } + } + else if (input->source == GPU_SOURCE_VEC_UNIFORM) { + if(input->dynamicvec) { + /* only create uniforms for dynamic vectors */ + BLI_dynstr_printf(ds, "uniform %s unf%d;\n", + GPU_DATATYPE_STR[input->type], input->id); + } + else { + /* for others use const so the compiler can do folding */ + BLI_dynstr_printf(ds, "const %s cons%d = ", + GPU_DATATYPE_STR[input->type], input->id); + codegen_print_datatype(ds, input->type, input->vec); + BLI_dynstr_append(ds, ";\n"); + } + } + else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + BLI_dynstr_printf(ds, "varying %s var%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + } + } + } + + BLI_dynstr_append(ds, "\n"); +} + +static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) +{ + GPUNode *node; + GPUInput *input; + GPUOutput *output; + + for (node=nodes->first; node; node=node->next) { + /* load pixels from textures */ + for (input=node->inputs.first; input; input=input->next) { + if (input->source == GPU_SOURCE_TEX_PIXEL) { + if (codegen_input_has_texture(input) && input->definetex) { + BLI_dynstr_printf(ds, "\tvec4 tex%d = texture2D(", input->texid); + BLI_dynstr_printf(ds, "samp%d, gl_TexCoord[%d].st);\n", + input->texid, input->texid); + } + } + } + + /* declare temporary variables for node output storage */ + for (output=node->outputs.first; output; output=output->next) + BLI_dynstr_printf(ds, "\t%s tmp%d;\n", + GPU_DATATYPE_STR[output->type], output->id); + } + + BLI_dynstr_append(ds, "\n"); +} + +static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput) +{ + GPUNode *node; + GPUInput *input; + GPUOutput *output; + + for (node=nodes->first; node; node=node->next) { + BLI_dynstr_printf(ds, "\t%s(", node->name); + + for (input=node->inputs.first; input; input=input->next) { + if (input->source == GPU_SOURCE_TEX) { + BLI_dynstr_printf(ds, "samp%d", input->texid); + if (input->link) + BLI_dynstr_printf(ds, ", gl_TexCoord[%d].st", input->texid); + } + else if (input->source == GPU_SOURCE_TEX_PIXEL) { + if (input->link && input->link->output) + codegen_convert_datatype(ds, input->link->output->type, input->type, + "tmp", input->link->output->id); + else + codegen_convert_datatype(ds, input->link->output->type, input->type, + "tex", input->texid); + } + else if(input->source == GPU_SOURCE_BUILTIN) + BLI_dynstr_printf(ds, "%s", GPU_builtin_name(input->builtin)); + else if(input->source == GPU_SOURCE_VEC_UNIFORM) { + if(input->dynamicvec) + BLI_dynstr_printf(ds, "unf%d", input->id); + else + BLI_dynstr_printf(ds, "cons%d", input->id); + } + else if (input->source == GPU_SOURCE_ATTRIB) + BLI_dynstr_printf(ds, "var%d", input->attribid); + + BLI_dynstr_append(ds, ", "); + } + + for (output=node->outputs.first; output; output=output->next) { + BLI_dynstr_printf(ds, "tmp%d", output->id); + if (output->next) + BLI_dynstr_append(ds, ", "); + } + + BLI_dynstr_append(ds, ");\n"); + } + + BLI_dynstr_append(ds, "\n\tgl_FragColor = "); + codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); + BLI_dynstr_append(ds, ";\n"); +} + +static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *name) +{ + DynStr *ds = BLI_dynstr_new(); + char *code; + + BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); + + codegen_set_unique_ids(nodes); + codegen_print_uniforms_functions(ds, nodes); + + //if(G.f & G_DEBUG) + // BLI_dynstr_printf(ds, "/* %s */\n", name); + + BLI_dynstr_append(ds, "void main(void)\n"); + BLI_dynstr_append(ds, "{\n"); + + codegen_declare_tmps(ds, nodes); + codegen_call_functions(ds, nodes, output); + + BLI_dynstr_append(ds, "}\n"); + + /* create shader */ + code = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + //if(G.f & G_DEBUG) printf("%s\n", code); + + return code; +} + +static char *code_generate_vertex(ListBase *nodes) +{ + DynStr *ds = BLI_dynstr_new(); + GPUNode *node; + GPUInput *input; + char *code; + + for (node=nodes->first; node; node=node->next) { + for (input=node->inputs.first; input; input=input->next) { + if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + BLI_dynstr_printf(ds, "attribute %s att%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + BLI_dynstr_printf(ds, "varying %s var%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + } + } + } + + BLI_dynstr_append(ds, "\n"); + BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl); + + for (node=nodes->first; node; node=node->next) + for (input=node->inputs.first; input; input=input->next) + if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + if(input->attribtype == CD_TANGENT) /* silly exception */ + BLI_dynstr_printf(ds, "\tvar%d = gl_NormalMatrix * ", input->attribid); + else + BLI_dynstr_printf(ds, "\tvar%d = ", input->attribid); + + BLI_dynstr_printf(ds, "att%d;\n", input->attribid); + } + + BLI_dynstr_append(ds, "}\n\n"); + + code = BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + + //if(G.f & G_DEBUG) printf("%s\n", code); + + return code; +} + +/* GPU pass binding/unbinding */ + +GPUShader *GPU_pass_shader(GPUPass *pass) +{ + return pass->shader; +} + +void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) +{ + GPUShader *shader = pass->shader; + GPUNode *node; + GPUInput *next, *input; + ListBase *inputs = &pass->inputs; + int extract, z; + + memset(inputs, 0, sizeof(*inputs)); + + if(!shader) + return; + + GPU_shader_bind(shader); + + for (node=nodes->first; node; node=node->next) { + z = 0; + for (input=node->inputs.first; input; input=next, z++) { + next = input->next; + + /* attributes don't need to be bound, they already have + * an id that the drawing functions will use */ + if(input->source == GPU_SOURCE_ATTRIB || + input->source == GPU_SOURCE_BUILTIN) + continue; + + if (input->ima || input->tex) + snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); + else + snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); + + /* pass non-dynamic uniforms to opengl */ + extract = 0; + + if(input->ima || input->tex) { + if (input->bindtex) + extract = 1; + } + else if(input->dynamicvec) + extract = 1; + + if(extract) + input->shaderloc = GPU_shader_get_uniform(shader, input->shadername); + + /* extract nodes */ + if(extract) { + BLI_remlink(&node->inputs, input); + BLI_addtail(inputs, input); + } + } + } + + GPU_shader_unbind(shader); +} + +void GPU_pass_bind(GPUPass *pass, double time) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + GPU_shader_bind(shader); + + /* now bind the textures */ + for (input=inputs->first; input; input=input->next) { + if (input->ima) + input->tex = GPU_texture_from_blender(input->ima, input->iuser, time); + + if(input->ima || input->tex) { + if(input->tex) { + GPU_texture_bind(input->tex, input->texid); + GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); + } + } + } +} + +void GPU_pass_update_uniforms(GPUPass *pass) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + /* pass dynamic inputs to opengl, others were removed */ + for (input=inputs->first; input; input=input->next) + if(!(input->ima || input->tex)) + GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, + input->dynamicvec); +} + +void GPU_pass_unbind(GPUPass *pass) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + for (input=inputs->first; input; input=input->next) { + if (input->tex) + if(input->bindtex) + GPU_texture_unbind(input->tex); + if (input->ima) + input->tex = 0; + } + + GPU_shader_unbind(shader); +} + +/* Node Link Functions */ + +GPUNodeLink *GPU_node_link_create(int type) +{ + GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink"); + link->type = type; + link->users++; + + return link; +} + +void GPU_node_link_free(GPUNodeLink *link) +{ + link->users--; + + if (link->users < 0) + fprintf(stderr, "GPU_node_link_free: negative refcount\n"); + + if (link->users == 0) { + if (link->output) + link->output->link = NULL; + MEM_freeN(link); + } +} + +/* Node Functions */ + +GPUNode *GPU_node_begin(char *name) +{ + GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode"); + + node->name = name; + + return node; +} + +void GPU_node_end(GPUNode *node) +{ + /* empty */ +} + +static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) +{ + GPUInput *input; + GPUNode *outnode; + char *name; + + if(link->output) { + outnode = link->output->node; + name = outnode->name; + + if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { + input = MEM_dupallocN(outnode->inputs.first); + input->type = type; + if(input->link) + input->link->users++; + BLI_addtail(&node->inputs, input); + return; + } + } + + input = MEM_callocN(sizeof(GPUInput), "GPUInput"); + input->node = node; + + if(link->builtin) { + /* builtin uniform */ + input->type = type; + input->source = GPU_SOURCE_BUILTIN; + input->builtin = link->builtin; + + MEM_freeN(link); + } + else if(link->output) { + /* link to a node output */ + input->type = type; + input->source = GPU_SOURCE_TEX_PIXEL; + input->link = link; + link->users++; + } + else if(link->dynamictex) { + /* dynamic texture, GPUTexture is updated/deleted externally */ + input->type = type; + input->source = GPU_SOURCE_TEX; + + input->tex = link->dynamictex; + input->textarget = GL_TEXTURE_2D; + input->textype = type; + input->dynamictex = 1; + MEM_freeN(link); + } + else if(link->texture) { + /* small texture created on the fly, like for colorbands */ + input->type = GPU_VEC4; + input->source = GPU_SOURCE_TEX; + input->textype = type; + + if (type == GPU_TEX1D) { + input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1); + input->textarget = GL_TEXTURE_1D; + } + else { + input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2); + input->textarget = GL_TEXTURE_2D; + } + + MEM_freeN(link->ptr1); + MEM_freeN(link); + } + else if(link->image) { + /* blender image */ + input->type = GPU_VEC4; + input->source = GPU_SOURCE_TEX; + + input->ima = link->ptr1; + input->textarget = GL_TEXTURE_2D; + input->textype = GPU_TEX2D; + MEM_freeN(link); + } + else if(link->attribtype) { + /* vertex attribute */ + input->type = type; + input->source = GPU_SOURCE_ATTRIB; + + input->attribtype = link->attribtype; + BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname)); + MEM_freeN(link); + } + else { + /* uniform vector */ + input->type = type; + input->source = GPU_SOURCE_VEC_UNIFORM; + + memcpy(input->vec, link->ptr1, type*sizeof(float)); + if(link->dynamic) + input->dynamicvec= link->ptr1; + MEM_freeN(link); + } + + BLI_addtail(&node->inputs, input); +} + +static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock) +{ + GPUNodeLink *link; + + if(sock->link) { + gpu_node_input_link(node, sock->link, sock->type); + } + else { + link = GPU_node_link_create(0); + link->ptr1 = sock->vec; + gpu_node_input_link(node, link, sock->type); + } +} + +void GPU_node_output(GPUNode *node, int type, char *name, GPUNodeLink **link) +{ + GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput"); + + output->type = type; + output->node = node; + + if (link) { + *link = output->link = GPU_node_link_create(type); + output->link->output = output; + + /* note: the caller owns the reference to the linkfer, GPUOutput + merely points to it, and if the node is destroyed it will + set that pointer to NULL */ + } + + BLI_addtail(&node->outputs, output); +} + +void GPU_inputs_free(ListBase *inputs) +{ + GPUInput *input; + + for(input=inputs->first; input; input=input->next) { + if(input->link) + GPU_node_link_free(input->link); + else if(input->tex && !input->dynamictex) + GPU_texture_free(input->tex); + } + + BLI_freelistN(inputs); +} + +void GPU_node_free(GPUNode *node) +{ + GPUOutput *output; + + GPU_inputs_free(&node->inputs); + + for (output=node->outputs.first; output; output=output->next) + if (output->link) { + output->link->output = NULL; + GPU_node_link_free(output->link); + } + + BLI_freelistN(&node->outputs); + MEM_freeN(node); +} + +void GPU_nodes_free(ListBase *nodes) +{ + GPUNode *node; + + while (nodes->first) { + node = nodes->first; + BLI_remlink(nodes, node); + GPU_node_free(node); + } +} + +/* vertex attributes */ + +void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs) +{ + GPUNode *node; + GPUInput *input; + int a; + + /* convert attributes requested by node inputs to an array of layers, + * checking for duplicates and assigning id's starting from zero. */ + + memset(attribs, 0, sizeof(*attribs)); + + for(node=nodes->first; node; node=node->next) { + for(input=node->inputs.first; input; input=input->next) { + if(input->source == GPU_SOURCE_ATTRIB) { + for(a=0; atotlayer; a++) { + if(attribs->layer[a].type == input->attribtype && + strcmp(attribs->layer[a].name, input->attribname) == 0) + break; + } + + if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) { + input->attribid = attribs->totlayer++; + input->attribfirst = 1; + + attribs->layer[a].type = input->attribtype; + attribs->layer[a].glindex = input->attribid; + BLI_strncpy(attribs->layer[a].name, input->attribname, + sizeof(attribs->layer[a].name)); + } + else + input->attribid = attribs->layer[a].glindex; + } + } + } +} + +void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin) +{ + GPUNode *node; + GPUInput *input; + + *builtin= 0; + + for(node=nodes->first; node; node=node->next) + for(input=node->inputs.first; input; input=input->next) + if(input->source == GPU_SOURCE_BUILTIN) + *builtin |= input->builtin; +} + +/* varargs linking */ + +GPUNodeLink *GPU_attribute(int type, char *name) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->attribtype= type; + link->attribname= name; + + return link; +} + +GPUNodeLink *GPU_uniform(float *num) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->ptr1= num; + link->ptr2= NULL; + + return link; +} + +GPUNodeLink *GPU_dynamic_uniform(float *num) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->ptr1= num; + link->ptr2= NULL; + link->dynamic= 1; + + return link; +} + +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->image= 1; + link->ptr1= ima; + link->ptr2= iuser; + + return link; +} + +GPUNodeLink *GPU_texture(int size, float *pixels) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->texture = 1; + link->texturesize = size; + link->ptr1= pixels; + + return link; +} + +GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->dynamic = 1; + link->dynamictex = tex; + + return link; +} + +GPUNodeLink *GPU_socket(GPUNodeStack *sock) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->socket= sock; + + return link; +} + +GPUNodeLink *GPU_builtin(GPUBuiltin builtin) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->builtin= builtin; + + return link; +} + +int GPU_link(GPUMaterial *mat, char *name, ...) +{ + GPUNode *node; + GPUFunction *function; + GPUNodeLink *link, **linkptr; + va_list params; + int i; + + function = GPU_lookup_function(name); + if(!function) { + fprintf(stderr, "GPU failed to find function %s\n", name); + return 0; + } + + node = GPU_node_begin(name); + + va_start(params, name); + for(i=0; itotparam; i++) { + if(function->paramqual[i] != FUNCTION_QUAL_IN) { + linkptr= va_arg(params, GPUNodeLink**); + GPU_node_output(node, function->paramtype[i], "", linkptr); + } + else { + link= va_arg(params, GPUNodeLink*); + gpu_node_input_link(node, link, function->paramtype[i]); + } + } + va_end(params); + + GPU_node_end(node); + + gpu_material_add_node(mat, node); + + return 1; +} + +int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...) +{ + GPUNode *node; + GPUFunction *function; + GPUNodeLink *link, **linkptr; + va_list params; + int i, totin, totout; + + function = GPU_lookup_function(name); + if(!function) { + fprintf(stderr, "GPU failed to find function %s\n", name); + return 0; + } + + node = GPU_node_begin(name); + totin = 0; + totout = 0; + + if(in) { + for(i = 0; in[i].type != GPU_NONE; i++) { + gpu_node_input_socket(node, &in[i]); + totin++; + } + } + + if(out) { + for(i = 0; out[i].type != GPU_NONE; i++) { + GPU_node_output(node, out[i].type, out[i].name, &out[i].link); + totout++; + } + } + + va_start(params, out); + for(i=0; itotparam; i++) { + if(function->paramqual[i] != FUNCTION_QUAL_IN) { + if(totout == 0) { + linkptr= va_arg(params, GPUNodeLink**); + GPU_node_output(node, function->paramtype[i], "", linkptr); + } + else + totout--; + } + else { + if(totin == 0) { + link= va_arg(params, GPUNodeLink*); + if(link->socket) + gpu_node_input_socket(node, link->socket); + else + gpu_node_input_link(node, link, function->paramtype[i]); + } + else + totin--; + } + } + va_end(params); + + GPU_node_end(node); + + gpu_material_add_node(mat, node); + + return 1; +} + +int GPU_link_changed(GPUNodeLink *link) +{ + GPUNode *node; + GPUInput *input; + char *name; + + if(link->output) { + node = link->output->node; + name = node->name; + + if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { + input = node->inputs.first; + return (input->link != NULL); + } + + return 1; + } + else + return 0; +} + +/* Pass create/free */ + +void gpu_nodes_tag(GPUNodeLink *link) +{ + GPUNode *node; + GPUInput *input; + + if(!link->output) + return; + + node = link->output->node; + if(node->tag) + return; + + node->tag= 1; + for(input=node->inputs.first; input; input=input->next) + if(input->link) + gpu_nodes_tag(input->link); +} + +void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) +{ + GPUNode *node, *next; + + for(node=nodes->first; node; node=node->next) + node->tag= 0; + + gpu_nodes_tag(outlink); + + for(node=nodes->first; node; node=next) { + next = node->next; + + if(!node->tag) { + BLI_remlink(nodes, node); + GPU_node_free(node); + } + } +} + +GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name) +{ + GPUShader *shader; + GPUPass *pass; + char *vertexcode, *fragmentcode; + + if(!FUNCTION_LIB) { + GPU_nodes_free(nodes); + return NULL; + } + + /* prune unused nodes */ + gpu_nodes_prune(nodes, outlink); + + gpu_nodes_get_vertex_attributes(nodes, attribs); + gpu_nodes_get_builtin_flag(nodes, builtins); + + /* generate code and compile with opengl */ + fragmentcode = code_generate_fragment(nodes, outlink->output, name); + vertexcode = code_generate_vertex(nodes); + shader = GPU_shader_create(vertexcode, fragmentcode, FUNCTION_LIB); + MEM_freeN(fragmentcode); + MEM_freeN(vertexcode); + + /* failed? */ + if (!shader) { + memset(attribs, 0, sizeof(*attribs)); + memset(builtins, 0, sizeof(*builtins)); + GPU_nodes_free(nodes); + return NULL; + } + + /* create pass */ + pass = MEM_callocN(sizeof(GPUPass), "GPUPass"); + + pass->output = outlink->output; + pass->shader = shader; + + /* extract dynamic inputs and throw away nodes */ + GPU_nodes_extract_dynamic_inputs(pass, nodes); + GPU_nodes_free(nodes); + + return pass; +} + +void GPU_pass_free(GPUPass *pass) +{ + GPU_shader_free(pass->shader); + GPU_inputs_free(&pass->inputs); + MEM_freeN(pass); +} + diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h new file mode 100644 index 00000000000..53b52f24f16 --- /dev/null +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -0,0 +1,87 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __GPU_CODEGEN_H__ +#define __GPU_CODEGEN_H__ + +#include "DNA_listBase.h" + +struct ListBase; +struct GPUShader; +struct GPUOutput; +struct GPUNode; +struct GPUVertexAttribs; + +#define MAX_FUNCTION_NAME 64 +#define MAX_PARAMETER 32 + +#define FUNCTION_QUAL_IN 0 +#define FUNCTION_QUAL_OUT 1 +#define FUNCTION_QUAL_INOUT 2 + +typedef struct GPUFunction { + char name[MAX_FUNCTION_NAME]; + int paramtype[MAX_PARAMETER]; + int paramqual[MAX_PARAMETER]; + int totparam; +} GPUFunction; + +GPUFunction *GPU_lookup_function(char *name); + +/* Pass Generation + - Takes a list of nodes and a desired output, and makes a pass. This + will take ownership of the nodes and free them early if unused or + at the end if used. +*/ + +struct GPUPass; +typedef struct GPUPass GPUPass; + +GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, + struct GPUVertexAttribs *attribs, int *builtin, const char *name); + +struct GPUShader *GPU_pass_shader(GPUPass *pass); + +void GPU_pass_bind(GPUPass *pass, double time); +void GPU_pass_update_uniforms(GPUPass *pass); +void GPU_pass_unbind(GPUPass *pass); + +void GPU_pass_free(GPUPass *pass); + +/* Material calls */ + +char *GPU_builtin_name(GPUBuiltin builtin); +void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node); +int GPU_link_changed(struct GPUNodeLink *link); + +#endif + diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c new file mode 100644 index 00000000000..fe47fa3c60e --- /dev/null +++ b/source/blender/gpu/intern/gpu_draw.c @@ -0,0 +1,1168 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "GL/glew.h" + +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BKE_bmfont.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "GPU_extensions.h" +#include "GPU_material.h" +#include "GPU_draw.h" + +/* These are some obscure rendering functions shared between the + * game engine and the blender, in this module to avoid duplicaten + * and abstract them away from the rest a bit */ + +/* Text Rendering */ + +static void gpu_mcol(unsigned int ucol) +{ + /* mcol order is swapped */ + char *cp= (char *)&ucol; + glColor3ub(cp[3], cp[2], cp[1]); +} + +void GPU_render_text(MTFace *tface, int mode, + const char *textstr, int textlen, unsigned int *col, + float *v1, float *v2, float *v3, float *v4, int glattrib) +{ + if (mode & TF_BMFONT) { + Image* ima; + int characters, index, character; + float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; + + characters = textlen; + + ima = (Image*)tface->tpage; + if (ima == NULL) + characters = 0; + + // color has been set + if (tface->mode & TF_OBCOL) + col= NULL; + else if (!col) + glColor3f(1.0f, 1.0f, 1.0f); + + glPushMatrix(); + for (index = 0; index < characters; index++) { + float uv[4][2]; + + // lets calculate offset stuff + character = textstr[index]; + + // space starts at offset 1 + // character = character - ' ' + 1; + matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, + &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + + uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx; + uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy; + uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx; + uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy; + uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx; + uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy; + + glBegin(GL_POLYGON); + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]); + else glTexCoord2fv(uv[0]); + if(col) gpu_mcol(col[0]); + glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); + + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[1]); + else glTexCoord2fv(uv[1]); + if(col) gpu_mcol(col[1]); + glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); + + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[2]); + else glTexCoord2fv(uv[2]); + if(col) gpu_mcol(col[2]); + glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); + + if(v4) { + uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx; + uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy; + + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]); + else glTexCoord2fv(uv[3]); + if(col) gpu_mcol(col[3]); + glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); + } + glEnd(); + + glTranslatef(advance, 0.0, 0.0); + } + glPopMatrix(); + } +} + +/* Checking powers of two for images since opengl 1.x requires it */ + +static int is_pow2(int num) +{ + /* (n&(n-1)) zeros the least significant bit of n */ + return ((num)&(num-1))==0; +} + +static int smaller_pow2(int num) +{ + while (!is_pow2(num)) + num= num&(num-1); + + return num; +} + +static int is_pow2_limit(int num) +{ + /* take texture clamping into account */ + if (U.glreslimit != 0 && num > U.glreslimit) + return 0; + + return ((num)&(num-1))==0; +} + +static int smaller_pow2_limit(int num) +{ + /* take texture clamping into account */ + if (U.glreslimit != 0 && num > U.glreslimit) + return U.glreslimit; + + return smaller_pow2(num); +} + +/* Current OpenGL state caching for GPU_set_tpage */ + +static struct GPUTextureState { + int curtile, tile; + int curtilemode, tilemode; + int curtileXRep, tileXRep; + int curtileYRep, tileYRep; + Image *ima, *curima; + + int domipmap, linearmipmap; + + int alphamode; + MTFace *lasttface; +} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, NULL}; + +/* Mipmap settings */ + +void GPU_set_mipmap(int mipmap) +{ + if (GTS.domipmap != (mipmap != 0)) { + GPU_free_images(); + GTS.domipmap = mipmap != 0; + } +} + +void GPU_set_linear_mipmap(int linear) +{ + if (GTS.linearmipmap != (linear != 0)) { + GPU_free_images(); + GTS.linearmipmap = linear != 0; + } +} + +static int gpu_get_mipmap(void) +{ + return GTS.domipmap && (!(G.f & G_TEXTUREPAINT)); +} + +static GLenum gpu_get_mipmap_filter() +{ + return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST; +} + +/* Set OpenGL state for an MTFace */ + +static void gpu_make_repbind(Image *ima) +{ + ImBuf *ibuf; + + ibuf = BKE_image_get_ibuf(ima, NULL); + if(ibuf==NULL) + return; + + if(ima->repbind) { + glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); + MEM_freeN(ima->repbind); + ima->repbind= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } + + ima->totbind= ima->xrep*ima->yrep; + + if(ima->totbind>1) + ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); +} + +static void gpu_clear_tpage() +{ + if(GTS.lasttface==0) + return; + + GTS.lasttface= 0; + GTS.curtile= 0; + GTS.curima= 0; + if(GTS.curtilemode!=0) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + GTS.curtilemode= 0; + GTS.curtileXRep=0; + GTS.curtileYRep=0; + GTS.alphamode= -1; + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_ALPHA_TEST); +} + +static void gpu_set_blend_mode(GPUBlendMode blendmode) +{ + if(blendmode == GPU_BLEND_SOLID) { + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else if(blendmode==GPU_BLEND_ADD) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glDisable(GL_ALPHA_TEST); + } + else if(blendmode==GPU_BLEND_ALPHA) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* if U.glalphaclip == 1.0, some cards go bonkers... + * turn off alpha test in this case */ + + /* added after 2.45 to clip alpha */ + if(U.glalphaclip == 1.0) { + glDisable(GL_ALPHA_TEST); + } + else { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, U.glalphaclip); + } + } + else if(blendmode==GPU_BLEND_CLIP) { + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + } +} + +static void gpu_verify_alpha_mode(MTFace *tface) +{ + /* verify alpha blending modes */ + if(GTS.alphamode == tface->transp) + return; + + gpu_set_blend_mode(tface->transp); + GTS.alphamode= tface->transp; +} + +static void gpu_verify_reflection(Image *ima) +{ + if (ima && (ima->flag & IMA_REFLECT)) { + /* enable reflection mapping */ + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + } + else { + /* disable reflection mapping */ + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + } +} + +int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare) +{ + ImBuf *ibuf = NULL; + unsigned int *bind = NULL; + int rectw, recth, tpx=0, tpy=0, y; + unsigned int *rectrow, *tilerectrow; + unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL; + short texwindx, texwindy, texwinsx, texwinsy; + + /* initialize tile mode and number of repeats */ + GTS.ima = ima; + GTS.tilemode= (tfmode & TF_TILES) || (ima && (ima->tpageflag & IMA_TWINANIM)); + GTS.tileXRep = 0; + GTS.tileYRep = 0; + + /* setting current tile according to frame */ + if(ima && (ima->tpageflag & IMA_TWINANIM)) + GTS.tile= ima->lastframe; + else + GTS.tile= tftile; + + if(ima) { + GTS.tileXRep = ima->xrep; + GTS.tileYRep = ima->yrep; + } + + /* if same image & tile, we're done */ + if(compare && ima == GTS.curima && GTS.curtile == GTS.tile && + GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep && + GTS.curtileYRep == GTS.tileYRep) + return (ima!=0); + + /* if tiling mode or repeat changed, change texture matrix to fit */ + if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep || + GTS.curtileYRep != GTS.tileYRep) { + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + if((tfmode & TF_TILES) && ima!=NULL) + glScalef(ima->xrep, ima->yrep, 1.0); + + glMatrixMode(GL_MODELVIEW); + } + + /* check if we have a valid image */ + if(ima==NULL || ima->ok==0) + return 0; + + /* check if we have a valid image buffer */ + ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf==NULL) + return 0; + + /* ensure we have a char buffer and not only float */ + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); + + if(GTS.tilemode) { + /* tiled mode */ + if(ima->repbind==0) gpu_make_repbind(ima); + if(GTS.tile>=ima->totbind) GTS.tile= 0; + + /* this happens when you change repeat buttons */ + if(ima->repbind) bind= &ima->repbind[GTS.tile]; + else bind= &ima->bindcode; + + if(*bind==0) { + + texwindx= ibuf->x/ima->xrep; + texwindy= ibuf->y/ima->yrep; + + if(GTS.tile>=ima->xrep*ima->yrep) + GTS.tile= ima->xrep*ima->yrep-1; + + texwinsy= GTS.tile / ima->xrep; + texwinsx= GTS.tile - texwinsy*ima->xrep; + + texwinsx*= texwindx; + texwinsy*= texwindy; + + tpx= texwindx; + tpy= texwindy; + + rect= ibuf->rect + texwinsy*ibuf->x + texwinsx; + } + } + else { + /* regular image mode */ + bind= &ima->bindcode; + + if(*bind==0) { + tpx= ibuf->x; + tpy= ibuf->y; + rect= ibuf->rect; + } + } + + if(*bind != 0) { + /* enable opengl drawing with textures */ + glBindTexture(GL_TEXTURE_2D, *bind); + return *bind; + } + + rectw = tpx; + recth = tpy; + + /* for tiles, copy only part of image into buffer */ + if (GTS.tilemode) { + tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); + + for (y=0; yx]; + tilerectrow= &tilerect[y*rectw]; + + memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); + } + + rect= tilerect; + } + + /* scale if not a power of two */ + if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { + rectw= smaller_pow2_limit(rectw); + recth= smaller_pow2_limit(recth); + + scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); + gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); + rect= scalerect; + } + + /* create image */ + glGenTextures(1, (GLuint *)bind); + glBindTexture( GL_TEXTURE_2D, *bind); + + if (!gpu_get_mipmap()) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else { + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + ima->tpageflag |= IMA_MIPMAP_COMPLETE; + } + + /* set to modulate with vertex color */ + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + /* clean up */ + if (tilerect) + MEM_freeN(tilerect); + if (scalerect) + MEM_freeN(scalerect); + + return *bind; +} + +static void gpu_verify_repeat(Image *ima) +{ + /* set either clamp or repeat in X/Y */ + if (ima->tpageflag & IMA_CLAMP_U) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + + if (ima->tpageflag & IMA_CLAMP_V) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +} + +int GPU_set_tpage(MTFace *tface) +{ + Image *ima; + + /* check if we need to clear the state */ + if(tface==0) { + gpu_clear_tpage(); + return 0; + } + + ima= tface->tpage; + GTS.lasttface= tface; + + gpu_verify_alpha_mode(tface); + gpu_verify_reflection(ima); + + if(GPU_verify_image(ima, tface->tile, tface->mode, 1)) { + GTS.curtile= GTS.tile; + GTS.curima= GTS.ima; + GTS.curtilemode= GTS.tilemode; + GTS.curtileXRep = GTS.tileXRep; + GTS.curtileYRep = GTS.tileYRep; + + glEnable(GL_TEXTURE_2D); + } + else { + glDisable(GL_TEXTURE_2D); + + GTS.curtile= 0; + GTS.curima= 0; + GTS.curtilemode= 0; + GTS.curtileXRep = 0; + GTS.curtileYRep = 0; + + return 0; + } + + gpu_verify_repeat(ima); + + /* Did this get lost in the image recode? */ + /* tag_image_time(ima);*/ + + return 1; +} + +/* these two functions are called on entering and exiting texture paint mode, + temporary disabling/enabling mipmapping on all images for quick texture + updates with glTexSubImage2D. images that didn't change don't have to be + re-uploaded to OpenGL */ +void GPU_paint_set_mipmap(int mipmap) +{ + Image* ima; + + if(!GTS.domipmap) + return; + + if(mipmap) { + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + GPU_free_image(ima); + } + } + + } + else { + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + } + } +} + +void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) +{ + ImBuf *ibuf; + + ibuf = BKE_image_get_ibuf(ima, NULL); + + if (ima->repbind || gpu_get_mipmap() || !ima->bindcode || !ibuf || + (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || + (w == 0) || (h == 0)) { + /* these cases require full reload still */ + GPU_free_image(ima); + } + else { + /* for the special case, we can do a partial update + * which is much quicker for painting */ + GLint row_length, skip_pixels, skip_rows; + + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); + + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei(GL_UNPACK_SKIP_ROWS, y); + + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_UNSIGNED_BYTE, ibuf->rect); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } +} + +void GPU_update_images_framechange(void) +{ + Image *ima; + + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) + ima->twend= ima->xrep*ima->yrep-1; + + /* check: is bindcode not in the array? free. (to do) */ + + ima->lastframe++; + if(ima->lastframe > ima->twend) + ima->lastframe= ima->twsta; + } + } +} + +int GPU_update_image_time(Image *ima, double time) +{ + int inc = 0; + float diff; + int newframe; + + if (!ima) + return 0; + + if (ima->lastupdate<0) + ima->lastupdate = 0; + + if (ima->lastupdate>time) + ima->lastupdate=(float)time; + + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; + + /* check: is the bindcode not in the array? Then free. (still to do) */ + + diff = (float)(time-ima->lastupdate); + inc = (int)(diff*(float)ima->animspeed); + + ima->lastupdate+=((float)inc/(float)ima->animspeed); + + newframe = ima->lastframe+inc; + + if(newframe > (int)ima->twend) { + if(ima->twend-ima->twsta != 0) + newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); + else + newframe = ima->twsta; + } + + ima->lastframe = newframe; + } + + return inc; +} + +void GPU_free_image(Image *ima) +{ + /* free regular image binding */ + if(ima->bindcode) { + glDeleteTextures(1, (GLuint *)&ima->bindcode); + ima->bindcode= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } + + /* free glsl image binding */ + if(ima->gputexture) { + GPU_texture_free(ima->gputexture); + ima->gputexture= NULL; + } + + /* free repeated image binding */ + if(ima->repbind) { + glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); + + MEM_freeN(ima->repbind); + ima->repbind= NULL; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } +} + +void GPU_free_images(void) +{ + Image* ima; + + if(G.main) + for(ima=G.main->image.first; ima; ima=ima->id.next) + GPU_free_image(ima); +} + +/* OpenGL Materials */ + +/* materials start counting at # one.... */ +#define MAXMATBUF (MAXMAT+1) + +/* OpenGL state caching for materials */ + +static struct GPUMaterialState { + float matbuf[MAXMATBUF][2][4]; + int totmat; + + Material *gmatbuf[MAXMATBUF]; + Material *gboundmat; + Object *gob; + Scene *gscene; + + GPUBlendMode blendmode[MAXMATBUF]; + int alphapass; + + int lastmatnr, lastretval; + GPUBlendMode lastblendmode; +} GMS; + +Material *gpu_active_node_material(Material *ma) +{ + if(ma && ma->use_nodes && ma->nodetree) { + bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); + + if(node) + return (Material *)node->id; + else + return NULL; + } + + return ma; +} + +void GPU_set_object_materials(Scene *scene, Object *ob, int glsl, int *do_alpha_pass) +{ + extern Material defmaterial; /* from material.c */ + Material *ma; + GPUMaterial *gpumat; + GPUBlendMode blendmode; + int a; + + /* initialize state */ + memset(&GMS, 0, sizeof(GMS)); + GMS.lastmatnr = -1; + GMS.lastretval = -1; + GMS.lastblendmode = GPU_BLEND_SOLID; + + GMS.gob = ob; + GMS.gscene = scene; + GMS.totmat= ob->totcol; + + GMS.alphapass = (G.vd && G.vd->transp); + if(do_alpha_pass) + *do_alpha_pass = 0; + + /* no materials assigned? */ + if(ob->totcol==0) { + GMS.matbuf[0][0][0]= defmaterial.r; + GMS.matbuf[0][0][1]= defmaterial.g; + GMS.matbuf[0][0][2]= defmaterial.b; + GMS.matbuf[0][0][3]= 1.0; + + GMS.matbuf[0][1][0]= defmaterial.specr; + GMS.matbuf[0][1][1]= defmaterial.specg; + GMS.matbuf[0][1][2]= defmaterial.specb; + GMS.matbuf[0][1][3]= 1.0; + + /* do material 1 too, for displists! */ + QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]); + QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]); + + if(glsl) { + GMS.gmatbuf[0]= &defmaterial; + GPU_material_from_blender(GMS.gscene, &defmaterial); + } + + GMS.blendmode[0]= GPU_BLEND_SOLID; + } + + /* setup materials */ + for(a=1; a<=ob->totcol; a++) { + /* find a suitable material */ + ma= give_current_material(ob, a); + if(!glsl) ma= gpu_active_node_material(ma); + if(ma==NULL) ma= &defmaterial; + + /* this shouldn't happen .. */ + if(a>=MAXMATBUF) + continue; + + /* create glsl material if requested */ + gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; + + if(gpumat) { + /* do glsl only if creating it succeed, else fallback */ + GMS.gmatbuf[a]= ma; + blendmode = GPU_material_blend_mode(gpumat, ob->col); + } + else { + /* fixed function opengl materials */ + if (ma->mode & MA_SHLESS) { + GMS.matbuf[a][0][0]= ma->r; + GMS.matbuf[a][0][1]= ma->g; + GMS.matbuf[a][0][2]= ma->b; + } else { + GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r; + GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; + GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; + + GMS.matbuf[a][1][0]= ma->spec*ma->specr; + GMS.matbuf[a][1][1]= ma->spec*ma->specg; + GMS.matbuf[a][1][2]= ma->spec*ma->specb; + GMS.matbuf[a][1][3]= 1.0; + } + + blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + if(do_alpha_pass && GMS.alphapass) + GMS.matbuf[a][0][3]= ma->alpha; + else + GMS.matbuf[a][0][3]= 1.0f; + } + + /* setting do_alpha_pass = 1 indicates this object needs to be + * drawn in a second alpha pass for improved blending */ + if(do_alpha_pass) { + GMS.blendmode[a]= blendmode; + if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass) + *do_alpha_pass= 1; + } + } + + /* let's start with a clean state */ + GPU_disable_material(); +} + +int GPU_enable_material(int nr, void *attribs) +{ + GPUVertexAttribs *gattribs = attribs; + GPUMaterial *gpumat; + GPUBlendMode blendmode; + + /* prevent index to use un-initialized array items */ + if(nr>GMS.totmat) + nr= GMS.totmat; + + if(gattribs) + memset(gattribs, 0, sizeof(*gattribs)); + + /* keep current material */ + if(nr>=MAXMATBUF || nr==GMS.lastmatnr) + return GMS.lastretval; + + /* unbind glsl material */ + if(GMS.gboundmat) { + if(GMS.alphapass) glDepthMask(0); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); + GMS.gboundmat= NULL; + } + + /* draw materials with alpha in alpha pass */ + GMS.lastmatnr = nr; + GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); + if(GMS.alphapass) + GMS.lastretval = !GMS.lastretval; + + if(GMS.lastretval) { + if(gattribs && GMS.gmatbuf[nr]) { + /* bind glsl material and get attributes */ + Material *mat = GMS.gmatbuf[nr]; + + gpumat = GPU_material_from_blender(GMS.gscene, mat); + GPU_material_vertex_attributes(gpumat, gattribs); + GPU_material_bind(gpumat, GMS.gob->lay, G.vd->lay, 1.0); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, G.vd->viewmat, G.vd->viewinv, GMS.gob->col); + GMS.gboundmat= mat; + + if(GMS.alphapass) glDepthMask(1); + } + else { + /* or do fixed function opengl material */ + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]); + } + + /* set (alpha) blending mode */ + blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID; + GPU_set_material_blend_mode(blendmode); + } + + return GMS.lastretval; +} + +void GPU_set_material_blend_mode(int blendmode) +{ + if(GMS.lastblendmode == blendmode) + return; + + gpu_set_blend_mode(blendmode); + GMS.lastblendmode = blendmode; +} + +int GPU_get_material_blend_mode(void) +{ + return GMS.lastblendmode; +} + +void GPU_disable_material(void) +{ + GMS.lastmatnr= -1; + GMS.lastretval= 1; + + if(GMS.gboundmat) { + if(GMS.alphapass) glDepthMask(0); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); + GMS.gboundmat= NULL; + } + + GPU_set_material_blend_mode(GPU_BLEND_SOLID); +} + +/* Lights */ + +int GPU_default_lights(void) +{ + int a, count = 0; + + /* initialize */ + if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { + U.light[0].flag= 1; + U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; + U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; + U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; + U.light[0].spec[3]= 1.0; + + U.light[1].flag= 0; + U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; + U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; + U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; + U.light[1].spec[3]= 1.0; + + U.light[2].flag= 0; + U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; + U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; + U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; + U.light[2].spec[3]= 1.0; + } + + glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); + glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); + glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); + + glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); + glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); + glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); + + glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); + glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); + glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); + + for(a=0; a<8; a++) { + if(a<3) { + if(U.light[a].flag) { + glEnable(GL_LIGHT0+a); + count++; + } + else + glDisable(GL_LIGHT0+a); + + // clear stuff from other opengl lamp usage + glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); + glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); + } + else + glDisable(GL_LIGHT0+a); + } + + glDisable(GL_LIGHTING); + + glDisable(GL_COLOR_MATERIAL); + + return count; +} + +int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4]) +{ + Base *base; + Lamp *la; + int count; + float position[4], direction[4], energy[4]; + + /* disable all lights */ + for(count=0; count<8; count++) + glDisable(GL_LIGHT0+count); + + count= 0; + + for(base=scene->base.first; base; base=base->next) { + if(base->object->type!=OB_LAMP) + continue; + + if(!(base->lay & lay) || !(base->lay & ob->lay)) + continue; + + la= base->object->data; + + /* setup lamp transform */ + glPushMatrix(); + glLoadMatrixf((float *)viewmat); + + where_is_object_simul(base->object); + + if(la->type==LA_SUN) { + /* sun lamp */ + VECCOPY(position, base->object->obmat[2]); + direction[3]= 0.0; + + glLightfv(GL_LIGHT0+count, GL_POSITION, direction); + } + else { + /* other lamps with attenuation */ + VECCOPY(position, base->object->obmat[3]); + position[3]= 1.0f; + + glLightfv(GL_LIGHT0+count, GL_POSITION, position); + glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); + glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); + + if(la->type==LA_SPOT) { + /* spot lamp */ + direction[0]= -base->object->obmat[2][0]; + direction[1]= -base->object->obmat[2][1]; + direction[2]= -base->object->obmat[2][2]; + glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction); + glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0); + glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend); + } + else + glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); + } + + /* setup energy */ + energy[0]= la->energy*la->r; + energy[1]= la->energy*la->g; + energy[2]= la->energy*la->b; + energy[3]= 1.0; + + glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); + glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy); + glEnable(GL_LIGHT0+count); + + glPopMatrix(); + + count++; + if(count==8) + break; + } + + return count; +} + +/* Default OpenGL State */ + +void GPU_state_init(void) +{ + /* also called when doing opengl rendering and in the game engine */ + float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; + float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + float mat_shininess[] = { 35.0 }; + int a, x, y; + GLubyte pat[32*32]; + const GLubyte *patc= pat; + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + GPU_default_lights(); + + /* no local viewer, looks ugly in ortho mode */ + /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ + + glDepthFunc(GL_LEQUAL); + /* scaling matrices */ + glEnable(GL_NORMALIZE); + + glShadeModel(GL_FLAT); + + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_LOGIC_OP); + glDisable(GL_STENCIL_TEST); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + + /* default on, disable/enable should be local per function */ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glPixelTransferi(GL_MAP_COLOR, GL_FALSE); + glPixelTransferi(GL_RED_SCALE, 1); + glPixelTransferi(GL_RED_BIAS, 0); + glPixelTransferi(GL_GREEN_SCALE, 1); + glPixelTransferi(GL_GREEN_BIAS, 0); + glPixelTransferi(GL_BLUE_SCALE, 1); + glPixelTransferi(GL_BLUE_BIAS, 0); + glPixelTransferi(GL_ALPHA_SCALE, 1); + glPixelTransferi(GL_ALPHA_BIAS, 0); + + glPixelTransferi(GL_DEPTH_BIAS, 0); + glPixelTransferi(GL_DEPTH_SCALE, 1); + glDepthRange(0.0, 1.0); + + a= 0; + for(x=0; x<32; x++) { + for(y=0; y<4; y++) { + if( (x) & 1) pat[a++]= 0x88; + else pat[a++]= 0x22; + } + } + + glPolygonStipple(patc); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glDisable(GL_CULL_FACE); +} + diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c new file mode 100644 index 00000000000..d900f9c63f2 --- /dev/null +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -0,0 +1,987 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GL/glew.h" + +#include "DNA_listBase.h" +#include "DNA_image_types.h" +#include "DNA_userdef_types.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_image.h" +#include "BKE_global.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BLI_blenlib.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" + +#include +#include +#include + +/* Extensions support */ + +/* extensions used: + - texture border clamp: 1.3 core + - fragement shader: 2.0 core + - framebuffer object: ext specification + - multitexture 1.3 core + - arb non power of two: 2.0 core + - pixel buffer objects? 2.1 core + - arb draw buffers? 2.0 core +*/ + +struct GPUGlobal { + GLint maxtextures; + GLuint currentfb; + int minimumsupport; +} GG = {1, 0, 0}; + +void GPU_extensions_init() +{ + glewInit(); + + /* glewIsSupported("GL_VERSION_2_0") */ + + if (GLEW_ARB_multitexture) + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures); + + GG.minimumsupport = 1; + if (!GLEW_ARB_multitexture) GG.minimumsupport = 0; + if (!GLEW_ARB_vertex_shader) GG.minimumsupport = 0; + if (!GLEW_ARB_fragment_shader) GG.minimumsupport = 0; +} + +int GPU_extensions_minimum_support() +{ + return GG.minimumsupport; +} + +int GPU_print_error(char *str) +{ + GLenum errCode; + + if (G.f & G_DEBUG) { + if ((errCode = glGetError()) != GL_NO_ERROR) { + fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode)); + return 1; + } + } + + return 0; +} + +static void GPU_print_framebuffer_error(GLenum status) +{ + fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d\n", + (int)status); + + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + fprintf(stderr, "Incomplete attachment.\n"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + fprintf(stderr, "Unsupported framebuffer format.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + fprintf(stderr, "Missing attachment.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + fprintf(stderr, "Attached images must have same dimensions.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + fprintf(stderr, "Attached images must have same format.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + fprintf(stderr, "Missing draw buffer.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + fprintf(stderr, "Missing read buffer.\n"); + break; + default: + fprintf(stderr, "Unknown.\n"); + break; + } +} + +/* GPUTexture */ + +struct GPUTexture { + int w, h; /* width/height */ + int number; /* number for multitexture binding */ + int refcount; /* reference count */ + GLenum target; /* GL_TEXTURE_* */ + GLuint bindcode; /* opengl identifier for texture */ + int fromblender; /* we got the texture from Blender */ + + GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ + int depth; /* is a depth texture? */ +}; + +#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) +static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels) +{ + unsigned char *pixels, *p; + float *fp; + int a, len; + + len = 4*length; + fp = fpixels; + p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels"); + + for (a=0; aw = w; + tex->h = h; + tex->number = -1; + tex->refcount = 1; + tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; + tex->depth = depth; + + glGenTextures(1, &tex->bindcode); + + if (!tex->bindcode) { + fprintf(stderr, "GPUTexture: texture create failed: %d\n", + (int)glGetError()); + GPU_texture_free(tex); + return NULL; + } + + if (!GLEW_ARB_texture_non_power_of_two) { + tex->w = larger_pow2(tex->w); + tex->h = larger_pow2(tex->h); + } + + tex->number = 0; + glBindTexture(tex->target, tex->bindcode); + + if(depth) { + type = GL_UNSIGNED_BYTE; + format = GL_DEPTH_COMPONENT; + internalformat = GL_DEPTH_COMPONENT; + } + else { + type = GL_UNSIGNED_BYTE; + format = GL_RGBA; + internalformat = GL_RGBA8; + + if (fpixels) + pixels = GPU_texture_convert_pixels(w*h, fpixels); + } + + if (tex->target == GL_TEXTURE_1D) { + glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, 0); + + if (fpixels) { + glTexSubImage1D(tex->target, 0, 0, w, format, type, + pixels? pixels: fpixels); + + if (tex->w > w) + GPU_glTexSubImageEmpty(tex->target, format, w, 0, + tex->w-w, 1); + } + } + else { + glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, + format, type, 0); + + if (fpixels) { + glTexSubImage2D(tex->target, 0, 0, 0, w, h, + format, type, pixels? pixels: fpixels); + + if (tex->w > w) + GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); + if (tex->h > h) + GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); + } + } + + if (pixels) + MEM_freeN(pixels); + + if(depth) { + glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); + } + else { + glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (tex->target != GL_TEXTURE_1D) { + /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */ + GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER; + glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode); + glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode); + +#if 0 + float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); +#endif + } + else + glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + return tex; +} + +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time) +{ + GPUTexture *tex; + GLint w, h, border, lastbindcode, bindcode; + + glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); + + GPU_update_image_time(ima, time); + bindcode = GPU_verify_image(ima, 0, 0, 0); + + if(ima->gputexture) { + ima->gputexture->bindcode = bindcode; + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return ima->gputexture; + } + + if(!bindcode) { + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return NULL; + } + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_2D; + tex->fromblender = 1; + + ima->gputexture= tex; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error("Blender Texture"); + } + else { + glBindTexture(GL_TEXTURE_2D, tex->bindcode); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border); + + tex->w = w - border; + tex->h = h - border; + } + + glBindTexture(GL_TEXTURE_2D, lastbindcode); + + return tex; +} + +GPUTexture *GPU_texture_create_1D(int w, float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +GPUTexture *GPU_texture_create_depth(int w, int h) +{ + GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +void GPU_texture_bind(GPUTexture *tex, int number) +{ + GLenum arbnumber; + + if (number >= GG.maxtextures) { + GPU_print_error("Not enough texture slots."); + return; + } + + if(number == -1) + return; + + GPU_print_error("Pre Texture Bind"); + + arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number); + if (number != 0) glActiveTextureARB(arbnumber); + glBindTexture(tex->target, tex->bindcode); + glEnable(tex->target); + if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); + + tex->number = number; + + GPU_print_error("Post Texture Bind"); +} + +void GPU_texture_unbind(GPUTexture *tex) +{ + GLenum arbnumber; + + if (tex->number >= GG.maxtextures) { + GPU_print_error("Not enough texture slots."); + return; + } + + if(tex->number == -1) + return; + + GPU_print_error("Pre Texture Unbind"); + + arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); + if (tex->number != 0) glActiveTextureARB(arbnumber); + glBindTexture(tex->target, 0); + glDisable(tex->target); + if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); + + tex->number = -1; + + GPU_print_error("Post Texture Unbind"); +} + +void GPU_texture_free(GPUTexture *tex) +{ + tex->refcount--; + + if (tex->refcount < 0) + fprintf(stderr, "GPUTexture: negative refcount\n"); + + if (tex->refcount == 0) { + if (tex->fb) + GPU_framebuffer_texture_detach(tex->fb, tex); + if (tex->bindcode && !tex->fromblender) + glDeleteTextures(1, &tex->bindcode); + + MEM_freeN(tex); + } +} + +void GPU_texture_ref(GPUTexture *tex) +{ + tex->refcount++; +} + +int GPU_texture_target(GPUTexture *tex) +{ + return tex->target; +} + +int GPU_texture_opengl_width(GPUTexture *tex) +{ + return tex->w; +} + +int GPU_texture_opengl_height(GPUTexture *tex) +{ + return tex->h; +} + +GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex) +{ + return tex->fb; +} + +/* GPUFrameBuffer */ + +struct GPUFrameBuffer { + GLuint object; + GPUTexture *colortex; + GPUTexture *depthtex; +}; + +GPUFrameBuffer *GPU_framebuffer_create() +{ + GPUFrameBuffer *fb; + + if (!GLEW_EXT_framebuffer_object) + return NULL; + + fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); + glGenFramebuffersEXT(1, &fb->object); + + if (!fb->object) { + fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n", + (int)glGetError()); + GPU_framebuffer_free(fb); + return NULL; + } + + return fb; +} + +int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex) +{ + GLenum status; + GLenum attachment; + + if(tex->depth) + attachment = GL_DEPTH_ATTACHMENT_EXT; + else + attachment = GL_COLOR_ATTACHMENT0_EXT; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object); + GG.currentfb = fb->object; + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + tex->target, tex->bindcode, 0); + + if(tex->depth) { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + else { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_NONE); + } + + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + GPU_framebuffer_restore(); + GPU_print_framebuffer_error(status); + return 0; + } + + if(tex->depth) + fb->depthtex = tex; + else + fb->colortex = tex; + + tex->fb= fb; + + return 1; +} + +void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) +{ + GLenum attachment; + + if(!tex->fb) + return; + + if(GG.currentfb != tex->fb->object) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); + GG.currentfb = tex->fb->object; + } + + if(tex->depth) { + fb->depthtex = NULL; + attachment = GL_DEPTH_ATTACHMENT_EXT; + } + else { + fb->colortex = NULL; + attachment = GL_COLOR_ATTACHMENT0_EXT; + } + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + tex->target, 0, 0); + + tex->fb = NULL; +} + +void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex) +{ + /* push attributes */ + glPushAttrib(GL_ENABLE_BIT); + glPushAttrib(GL_VIEWPORT_BIT); + glDisable(GL_SCISSOR_TEST); + + /* bind framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); + + /* push matrices and set default viewport and matrix */ + glViewport(0, 0, tex->w, tex->h); + GG.currentfb = tex->fb->object; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); +} + +void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex) +{ + /* restore matrix */ + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + /* restore attributes */ + glPopAttrib(); + glPopAttrib(); + glEnable(GL_SCISSOR_TEST); +} + +void GPU_framebuffer_free(GPUFrameBuffer *fb) +{ + if(fb->depthtex) + GPU_framebuffer_texture_detach(fb, fb->depthtex); + if(fb->colortex) + GPU_framebuffer_texture_detach(fb, fb->colortex); + + if(fb->object) { + glDeleteFramebuffersEXT(1, &fb->object); + + if (GG.currentfb == fb->object) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + GG.currentfb = 0; + } + } + + MEM_freeN(fb); +} + +void GPU_framebuffer_restore() +{ + if (GG.currentfb != 0) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + GG.currentfb = 0; + } +} + +/* GPUShader */ + +struct GPUShader { + GLhandleARB object; /* handle for full shader */ + GLhandleARB vertex; /* handle for vertex shader */ + GLhandleARB fragment; /* handle for fragment shader */ + GLhandleARB lib; /* handle for libment shader */ + int totattrib; /* total number of attributes */ +}; + +static void shader_print_errors(char *task, char *log, const char *code) +{ + const char *c, *pos, *end = code + strlen(code); + int line = 1; + + fprintf(stderr, "GPUShader: %s error:\n", task); + + if(G.f & G_DEBUG) { + c = code; + while ((c < end) && (pos = strchr(c, '\n'))) { + fprintf(stderr, "%2d ", line); + fwrite(c, (pos+1)-c, 1, stderr); + c = pos+1; + line++; + } + + fprintf(stderr, "%s", c); + } + + fprintf(stderr, "%s\n", log); +} + +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib) +{ + GLint status; + GLcharARB log[5000]; + GLsizei length = 0; + GPUShader *shader; + + if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) + return NULL; + + shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); + + if(vertexcode) + shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + if(fragcode) + shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + shader->object = glCreateProgramObjectARB(); + + if (!shader->object || + (vertexcode && !shader->vertex) || + (fragcode && !shader->fragment)) { + fprintf(stderr, "GPUShader, object creation failed.\n"); + GPU_shader_free(shader); + return NULL; + } + + if(lib && lib->lib) + glAttachObjectARB(shader->object, lib->lib); + + if(vertexcode) { + glAttachObjectARB(shader->object, shader->vertex); + glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL); + + glCompileShaderARB(shader->vertex); + glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glValidateProgramARB(shader->vertex); + glGetInfoLogARB(shader->vertex, sizeof(log), &length, log); + shader_print_errors("compile", log, vertexcode); + + GPU_shader_free(shader); + return NULL; + } + } + + if(fragcode) { + glAttachObjectARB(shader->object, shader->fragment); + glShaderSourceARB(shader->fragment, 1, (const char**)&fragcode, NULL); + + glCompileShaderARB(shader->fragment); + glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glValidateProgramARB(shader->fragment); + glGetInfoLogARB(shader->fragment, sizeof(log), &length, log); + shader_print_errors("compile", log, fragcode); + + GPU_shader_free(shader); + return NULL; + } + } + + glLinkProgramARB(shader->object); + glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status); + if (!status) { + glGetInfoLogARB(shader->object, sizeof(log), &length, log); + shader_print_errors("linking", log, fragcode); + + GPU_shader_free(shader); + return NULL; + } + + return shader; +} + +GPUShader *GPU_shader_create_lib(const char *code) +{ + GLint status; + GLcharARB log[5000]; + GLsizei length = 0; + GPUShader *shader; + + if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) + return NULL; + + shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); + + shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + + if (!shader->lib) { + fprintf(stderr, "GPUShader, object creation failed.\n"); + GPU_shader_free(shader); + return NULL; + } + + glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL); + + glCompileShaderARB(shader->lib); + glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glValidateProgramARB(shader->lib); + glGetInfoLogARB(shader->lib, sizeof(log), &length, log); + shader_print_errors("compile", log, code); + + GPU_shader_free(shader); + return NULL; + } + + return shader; +} + +void GPU_shader_bind(GPUShader *shader) +{ + GPU_print_error("Pre Shader Bind"); + glUseProgramObjectARB(shader->object); + GPU_print_error("Post Shader Bind"); +} + +void GPU_shader_unbind() +{ + GPU_print_error("Pre Shader Unbind"); + glUseProgramObjectARB(0); + GPU_print_error("Post Shader Unbind"); +} + +void GPU_shader_free(GPUShader *shader) +{ + if (shader->lib) + glDeleteObjectARB(shader->lib); + if (shader->vertex) + glDeleteObjectARB(shader->vertex); + if (shader->fragment) + glDeleteObjectARB(shader->fragment); + if (shader->object) + glDeleteObjectARB(shader->object); + MEM_freeN(shader); +} + +int GPU_shader_get_uniform(GPUShader *shader, char *name) +{ + return glGetUniformLocationARB(shader->object, name); +} + +void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, float *value) +{ + if(location == -1) + return; + + GPU_print_error("Pre Uniform Vector"); + + if (length == 1) glUniform1fvARB(location, arraysize, value); + else if (length == 2) glUniform2fvARB(location, arraysize, value); + else if (length == 3) glUniform3fvARB(location, arraysize, value); + else if (length == 4) glUniform4fvARB(location, arraysize, value); + else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value); + else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value); + + GPU_print_error("Post Uniform Vector"); +} + +void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex) +{ + GLenum arbnumber; + + if (tex->number >= GG.maxtextures) { + GPU_print_error("Not enough texture slots."); + return; + } + + if(tex->number == -1) + return; + + if(location == -1) + return; + + GPU_print_error("Pre Uniform Texture"); + + arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); + + if (tex->number != 0) glActiveTextureARB(arbnumber); + glBindTexture(tex->target, tex->bindcode); + glUniform1iARB(location, tex->number); + glEnable(tex->target); + if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); + + GPU_print_error("Post Uniform Texture"); +} + +int GPU_shader_get_attribute(GPUShader *shader, char *name) +{ + int index; + + GPU_print_error("Pre Get Attribute"); + + index = glGetAttribLocationARB(shader->object, name); + + GPU_print_error("Post Get Attribute"); + + return index; +} + +#if 0 +/* GPUPixelBuffer */ + +typedef struct GPUPixelBuffer { + GLuint bindcode[2]; + GLuint current; + int datasize; + int numbuffers; + int halffloat; +} GPUPixelBuffer; + +void GPU_pixelbuffer_free(GPUPixelBuffer *pb) +{ + if (pb->bindcode[0]) + glDeleteBuffersARB(pb->numbuffers, pb->bindcode); + MEM_freeN(pb); +} + +GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers) +{ + GPUPixelBuffer *pb; + + if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object) + return NULL; + + pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO"); + pb->datasize = x*y*4*((halffloat)? 16: 8); + pb->numbuffers = numbuffers; + pb->halffloat = halffloat; + + glGenBuffersARB(pb->numbuffers, pb->bindcode); + + if (!pb->bindcode[0]) { + fprintf(stderr, "GPUPixelBuffer allocation failed\n"); + GPU_pixelbuffer_free(pb); + return NULL; + } + + return pb; +} + +void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb) +{ + void *pixels; + int i; + + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); + + for (i = 0; i < pb->numbuffers; i++) { + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]); + glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL, + GL_STREAM_DRAW_ARB); + + pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); + /*memcpy(pixels, _oImage.data(), pb->datasize);*/ + + if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { + fprintf(stderr, "Could not unmap opengl PBO\n"); + break; + } + } + + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); +} + +static int pixelbuffer_map_into_gpu(GLuint bindcode) +{ + void *pixels; + + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); + pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); + + /* do stuff in pixels */ + + if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { + fprintf(stderr, "Could not unmap opengl PBO\n"); + return 0; + } + + return 1; +} + +static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode) +{ + GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE; + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); + + glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, + GL_RGBA, type, NULL); + + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); +} + +void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb) +{ + int newbuffer; + + if (pb->numbuffers == 1) { + pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]); + pixelbuffer_map_into_gpu(pb->bindcode[0]); + } + else { + pb->current = (pb->current+1)%pb->numbuffers; + newbuffer = (pb->current+1)%pb->numbuffers; + + pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]); + pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]); + } +} +#endif + diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c new file mode 100644 index 00000000000..d4da2866d96 --- /dev/null +++ b/source/blender/gpu/intern/gpu_material.c @@ -0,0 +1,1496 @@ +/** + * $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): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "GL/glew.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" +#include "DNA_listBase.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_anim.h" +#include "BKE_colortools.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "GPU_extensions.h" +#include "GPU_material.h" + +#include "gpu_codegen.h" + +#include + +/* Structs */ + +typedef enum DynMatProperty { + DYN_LAMP_CO = 1, + DYN_LAMP_VEC = 2, + DYN_LAMP_IMAT = 4, + DYN_LAMP_PERSMAT = 8, +} DynMatProperty; + +struct GPUMaterial { + Scene *scene; + Material *ma; + + /* for creating the material */ + ListBase nodes; + GPUNodeLink *outlink; + + /* for binding the material */ + GPUPass *pass; + GPUVertexAttribs attribs; + int bound; + int builtins; + int alpha, obcolalpha; + int dynproperty; + + /* for passing uniforms */ + int viewmatloc, invviewmatloc; + int obmatloc, invobmatloc; + int obcolloc; + + ListBase lamps; +}; + +struct GPULamp { + Scene *scene; + Object *ob; + Object *par; + Lamp *la; + + int type, mode, lay; + + float dynenergy, dyncol[3]; + float energy, col[3]; + + float co[3], vec[3]; + float dynco[3], dynvec[3]; + float obmat[4][4]; + float imat[4][4]; + float dynimat[4][4]; + + float spotsi, spotbl, k; + float dist, att1, att2; + + float bias, d, clipend; + int size; + + int falloff_type; + struct CurveMapping *curfalloff; + + float winmat[4][4]; + float viewmat[4][4]; + float persmat[4][4]; + float dynpersmat[4][4]; + + GPUFrameBuffer *fb; + GPUTexture *tex; + + ListBase materials; +}; + +/* Functions */ + +static GPUMaterial *GPU_material_construct_begin(Material *ma) +{ + GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); + + material->ma= ma; + + return material; +} + +static void gpu_material_set_attrib_id(GPUMaterial *material) +{ + GPUVertexAttribs *attribs; + GPUShader *shader; + GPUPass *pass; + char name[32]; + int a, b; + + attribs= &material->attribs; + pass= material->pass; + if(!pass) { + attribs->totlayer = 0; + return; + } + + shader= GPU_pass_shader(pass); + if(!shader) { + attribs->totlayer = 0; + return; + } + + /* convert from attribute number to the actual id assigned by opengl, + * in case the attrib does not get a valid index back, it was probably + * removed by the glsl compiler by dead code elimination */ + + for(a=0, b=0; atotlayer; a++) { + sprintf(name, "att%d", attribs->layer[a].glindex); + attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name); + + if(attribs->layer[a].glindex >= 0) { + attribs->layer[b] = attribs->layer[a]; + b++; + } + } + + attribs->totlayer = b; +} + +static int GPU_material_construct_end(GPUMaterial *material) +{ + if (material->outlink) { + GPUNodeLink *outlink; + GPUShader *shader; + + outlink = material->outlink; + material->pass = GPU_generate_pass(&material->nodes, outlink, + &material->attribs, &material->builtins, material->ma->id.name); + + if(!material->pass) + return 0; + + gpu_material_set_attrib_id(material); + + shader = GPU_pass_shader(material->pass); + + if(material->builtins & GPU_VIEW_MATRIX) + material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX)); + if(material->builtins & GPU_INVERSE_VIEW_MATRIX) + material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX)); + if(material->builtins & GPU_OBJECT_MATRIX) + material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX)); + if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) + material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX)); + if(material->builtins & GPU_OBCOLOR) + material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR)); + + return 1; + } + + return 0; +} + +void GPU_material_free(Material *ma) +{ + LinkData *link; + LinkData *nlink, *mlink, *next; + + for(link=ma->gpumaterial.first; link; link=link->next) { + GPUMaterial *material = link->data; + + if(material->pass) + GPU_pass_free(material->pass); + + for(nlink=material->lamps.first; nlink; nlink=nlink->next) { + GPULamp *lamp = nlink->data; + + for(mlink=lamp->materials.first; mlink; mlink=next) { + next = mlink->next; + if(mlink->data == ma) + BLI_freelinkN(&lamp->materials, mlink); + } + } + + BLI_freelistN(&material->lamps); + + MEM_freeN(material); + } + + BLI_freelistN(&ma->gpumaterial); +} + +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time) +{ + if(material->pass) { + LinkData *nlink; + GPULamp *lamp; + + /* handle layer lamps */ + for(nlink=material->lamps.first; nlink; nlink=nlink->next) { + lamp= nlink->data; + + if((lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))) { + lamp->dynenergy = lamp->energy; + VECCOPY(lamp->dyncol, lamp->col); + } + else { + lamp->dynenergy = 0.0f; + lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; + } + } + + GPU_pass_bind(material->pass, time); + material->bound = 1; + } +} + +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]) +{ + if(material->pass) { + GPUShader *shader = GPU_pass_shader(material->pass); + LinkData *nlink; + GPULamp *lamp; + float invmat[4][4], col[4]; + + /* handle builtins */ + if(material->builtins & GPU_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); + } + if(material->builtins & GPU_INVERSE_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); + } + if(material->builtins & GPU_OBJECT_MATRIX) { + GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); + } + if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) { + Mat4Invert(invmat, obmat); + GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat); + } + if(material->builtins & GPU_OBCOLOR) { + QUATCOPY(col, obcol); + CLAMP(col[3], 0.0f, 1.0f); + GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); + } + + /* update lamps */ + for(nlink=material->lamps.first; nlink; nlink=nlink->next) { + lamp= nlink->data; + + if(material->dynproperty & DYN_LAMP_VEC) { + VECCOPY(lamp->dynvec, lamp->vec); + Normalize(lamp->dynvec); + VecMulf(lamp->dynvec, -1.0f); + Mat4Mul3Vecfl(viewmat, lamp->dynvec); + } + + if(material->dynproperty & DYN_LAMP_CO) { + VECCOPY(lamp->dynco, lamp->co); + Mat4MulVecfl(viewmat, lamp->dynco); + } + + if(material->dynproperty & DYN_LAMP_IMAT) + Mat4MulMat4(lamp->dynimat, viewinv, lamp->imat); + if(material->dynproperty & DYN_LAMP_PERSMAT) + Mat4MulMat4(lamp->dynpersmat, viewinv, lamp->persmat); + } + + GPU_pass_update_uniforms(material->pass); + } +} + +void GPU_material_unbind(GPUMaterial *material) +{ + if (material->pass) { + material->bound = 0; + GPU_pass_unbind(material->pass); + } +} + +int GPU_material_bound(GPUMaterial *material) +{ + return material->bound; +} + +void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs) +{ + *attribs = material->attribs; +} + +void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) +{ + if(!material->outlink) + material->outlink= link; +} + +void GPU_material_enable_alpha(GPUMaterial *material) +{ + material->alpha= 1; +} + +GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[3]) +{ + if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f)) + return GPU_BLEND_ALPHA; + else + return GPU_BLEND_SOLID; +} + +void gpu_material_add_node(GPUMaterial *material, GPUNode *node) +{ + BLI_addtail(&material->nodes, node); +} + +/* Code generation */ + +static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) +{ + GPUNodeLink *visifac, *inpr; + + /* from get_lamp_visibility */ + if(lamp->type==LA_SUN || lamp->type==LA_HEMI) { + mat->dynproperty |= DYN_LAMP_VEC; + GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec), lv, dist, &visifac); + return visifac; + } + else { + mat->dynproperty |= DYN_LAMP_CO; + GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), lv, dist, &visifac); + + if(lamp->type==LA_AREA) + return visifac; + + switch(lamp->falloff_type) + { + case LA_FALLOFF_CONSTANT: + break; + case LA_FALLOFF_INVLINEAR: + GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac); + break; + case LA_FALLOFF_INVSQUARE: + GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac); + break; + case LA_FALLOFF_SLIDERS: + GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac); + break; + case LA_FALLOFF_CURVE: + { + float *array; + int size; + + curvemapping_table_RGBA(lamp->curfalloff, &array, &size); + GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac); + } + break; + } + + if(lamp->mode & LA_SPHERE) + GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac); + + if(lamp->type == LA_SPOT) { + if(lamp->mode & LA_SQUARE) { + mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT; + GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec), GPU_dynamic_uniform((float*)lamp->dynimat), *lv, &inpr); + } + else { + mat->dynproperty |= DYN_LAMP_VEC; + GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec), *lv, &inpr); + } + + GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac); + } + + GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); + + return visifac; + } +} + +#if 0 +static void area_lamp_vectors(LampRen *lar) +{ + float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; + + /* make it smaller, so area light can be multisampled */ + multifac= 1.0f/sqrt((float)lar->ray_totsamp); + xsize *= multifac; + ysize *= multifac; + + /* corner vectors */ + lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; + lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; + lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + + /* corner vectors */ + lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; + lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; + lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + + /* corner vectors */ + lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; + lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; + lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + + /* corner vectors */ + lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; + lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; + lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + /* only for correction button size, matrix size works on energy */ + lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize); +} +#endif + +static void ramp_blend(GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type, GPUNodeLink **outcol) +{ + static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", + "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", + "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", + "mix_val", "mix_color"}; + + GPU_link(mat, names[type], fac, col1, col2, outcol); +} + +static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type, GPUNodeLink *incol, GPUNodeLink **outcol) +{ + GPUNodeLink *tmp, *alpha, *col; + float *array; + int size; + + /* do colorband */ + colorband_table_RGBA(coba, &array, &size); + GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp); + + /* use alpha in fac */ + GPU_link(mat, "mtex_alpha_from_col", col, &alpha); + GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac); + + /* blending method */ + ramp_blend(mat, fac, incol, col, type, outcol); +} + +static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *fac; + + if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS)) { + if(ma->ramp_col) { + if(ma->rampin_col==MA_RAMP_IN_RESULT) { + GPU_link(mat, "ramp_rgbtobw", *diff, &fac); + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff); + } + } + } +} + +static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb, GPUNodeLink **diff) +{ + GPUNodeLink *fac, *tmp, *addcol; + + if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS) && + ma->ramp_col && (ma->mode & MA_RAMP_COL)) { + /* MA_RAMP_IN_RESULT is exceptional */ + if(ma->rampin_col==MA_RAMP_IN_RESULT) { + addcol = shi->rgb; + } + else { + /* input */ + switch(ma->rampin_col) { + case MA_RAMP_IN_ENERGY: + GPU_link(mat, "ramp_rgbtobw", rgb, &fac); + break; + case MA_RAMP_IN_SHADER: + fac= is; + break; + case MA_RAMP_IN_NOR: + GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); + break; + default: + GPU_link(mat, "set_value_zero", &fac); + break; + } + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol); + } + } + else + addcol = shi->rgb; + + /* output to */ + GPU_link(mat, "shade_madd", *diff, rgb, addcol, diff); +} + +static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *fac; + + if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS) && + ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) { + GPU_link(mat, "ramp_rgbtobw", *spec, &fac); + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); + } +} + +static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *fac, *tmp; + + *spec = shi->specrgb; + + /* MA_RAMP_IN_RESULT is exception */ + if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { + + /* input */ + switch(ma->rampin_spec) { + case MA_RAMP_IN_ENERGY: + fac = t; + break; + case MA_RAMP_IN_SHADER: + fac = is; + break; + case MA_RAMP_IN_NOR: + GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); + break; + default: + GPU_link(mat, "set_value_zero", &fac); + break; + } + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); + } +} + +void add_user_list(ListBase *list, void *data) +{ + LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData"); + link->data = data; + BLI_addtail(list, link); +} + +static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view; + GPUNodeLink *outcol, *specfac, *t, *shadfac; + float one = 1.0f; + + if((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW)) + return; + + vn= shi->vn; + view= shi->view; + + visifac= lamp_get_visibility(mat, lamp, &lv, &dist); + + /*if(ma->mode & MA_TANGENT_V) + GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/ + + GPU_link(mat, "shade_inp", vn, lv, &inp); + + if(lamp->mode & LA_NO_DIFF) { + GPU_link(mat, "shade_is_no_diffuse", &is); + } + else if(lamp->type == LA_HEMI) { + GPU_link(mat, "shade_is_hemi", inp, &is); + } + else { + if(lamp->type == LA_AREA) { + float area[4][4], areasize; + + memset(&area, 0, sizeof(area)); + memset(&areasize, 0, sizeof(areasize)); + mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO; + GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), GPU_dynamic_uniform(lamp->dynvec), vn, GPU_uniform((float*)area), + GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp); + } + + is= inp; /* Lambert */ + + if(!(G.fileflags & G_FILE_GLSL_NO_SHADERS)) { + if(ma->diff_shader==MA_DIFF_ORENNAYAR) + GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is); + else if(ma->diff_shader==MA_DIFF_TOON) + GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); + else if(ma->diff_shader==MA_DIFF_MINNAERT) + GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is); + else if(ma->diff_shader==MA_DIFF_FRESNEL) + GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); + } + } + + if(!(G.fileflags & G_FILE_GLSL_NO_SHADERS)) + if(ma->shade_flag & MA_CUBIC) + GPU_link(mat, "shade_cubic", is, &is); + + i = is; + GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i); + + vn = shi->vn; + /*if(ma->mode & MA_TANGENT_VN) + GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/ + + /* this replaces if(i > 0.0) conditional until that is supported */ + // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); + + if((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) { + if(!(G.fileflags & G_FILE_GLSL_NO_SHADOWS)) { + mat->dynproperty |= DYN_LAMP_PERSMAT; + + GPU_link(mat, "test_shadowbuf", + GPU_builtin(GPU_VIEW_POSITION), + GPU_dynamic_texture(lamp->tex), + GPU_dynamic_uniform((float*)lamp->dynpersmat), + GPU_uniform(&lamp->bias), inp, &shadfac); + + if(lamp->mode & LA_ONLYSHADOW) { + GPU_link(mat, "shade_only_shadow", i, shadfac, + GPU_dynamic_uniform(&lamp->dynenergy), &shadfac); + + if(!(lamp->mode & LA_NO_DIFF)) + GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb, + shr->diff, &shr->diff); + + if(!(lamp->mode & LA_NO_SPEC)) + GPU_link(mat, "shade_only_shadow_specular", shadfac, shi->specrgb, + shr->spec, &shr->spec); + + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, ma); + return; + } + + GPU_link(mat, "math_multiply", i, shadfac, &i); + } + } + else if((G.fileflags & G_FILE_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) { + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, ma); + return; + } + else + GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac); + + if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) { + if(!(lamp->mode & LA_NO_DIFF)) { + GPUNodeLink *rgb; + GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol), &rgb); + add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff); + } + } + + if(G.fileflags & G_FILE_GLSL_NO_SHADERS); + else if(!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) && + (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) { + if(lamp->type == LA_HEMI) { + GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t); + GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol); + GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); + } + else { + if(ma->spec_shader==MA_SPEC_PHONG) + GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac); + else if(ma->spec_shader==MA_SPEC_COOKTORR) + GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac); + else if(ma->spec_shader==MA_SPEC_BLINN) + GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac); + else if(ma->spec_shader==MA_SPEC_WARDISO) + GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac); + else + GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac); + + if(lamp->type==LA_AREA) + GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac); + + GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t); + + if(ma->mode & MA_RAMP_SPEC) { + GPUNodeLink *spec; + do_specular_ramp(shi, specfac, t, &spec); + GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), spec, &outcol); + GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); + } + else { + GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol); + GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); + } + } + } + + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, ma); +} + +static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) +{ + Base *base; + Object *ob; + Scene *sce; + GPULamp *lamp; + + for(SETLOOPER(shi->gpumat->scene, base)) { + ob= base->object; + + if(ob->type==OB_LAMP) { + lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL); + if(lamp) + shade_one_light(shi, shr, lamp); + } + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(shi->gpumat->scene, ob); + + for(dob=lb->first; dob; dob=dob->next) { + Object *ob = dob->ob; + + if(ob->type==OB_LAMP) { + Mat4CpyMat4(ob->obmat, dob->mat); + + lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, base->object); + if(lamp) + shade_one_light(shi, shr, lamp); + } + } + + free_object_duplilist(lb); + } + } +} + +static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in) +{ + switch(blendtype) { + case MTEX_BLEND: + GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in); + break; + case MTEX_MUL: + GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in); + break; + case MTEX_SCREEN: + GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in); + break; + case MTEX_OVERLAY: + GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in); + break; + case MTEX_SUB: + GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in); + break; + case MTEX_ADD: + GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in); + break; + case MTEX_DIV: + GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in); + break; + case MTEX_DIFF: + GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in); + break; + case MTEX_DARK: + GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in); + break; + case MTEX_LIGHT: + GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in); + break; + case MTEX_BLEND_HUE: + GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in); + break; + case MTEX_BLEND_SAT: + GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in); + break; + case MTEX_BLEND_VAL: + GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in); + break; + case MTEX_BLEND_COLOR: + GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in); + break; + default: + GPU_link(mat, "set_rgb_zero", &in); + break; + } +} + +static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, int flip, GPUNodeLink **in) +{ + float flipf = (flip)? 1.0f: 0.0; + + switch(blendtype) { + case MTEX_BLEND: + GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_MUL: + GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_SCREEN: + GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_SUB: + GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_ADD: + GPU_link(mat, "mtex_value_add", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_DIV: + GPU_link(mat, "mtex_value_div", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_DIFF: + GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_DARK: + GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_LIGHT: + GPU_link(mat, "mtex_value_light", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + default: + GPU_link(mat, "set_value_zero", &in); + break; + } +} + +static void do_material_tex(GPUShadeInput *shi) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + MTex *mtex; + Tex *tex; + GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac; + GPUNodeLink *texco_norm, *texco_orco, *texco_object, *texco_tangent; + GPUNodeLink *texco_global, *texco_uv = NULL; + GPUNodeLink *colfac, *newnor, *varfac, *orn; + char *lastuvname = NULL; + float one = 1.0f, norfac, ofs[3]; + int tex_nr, rgbnor, talpha; + + GPU_link(mat, "set_value", GPU_uniform(&one), &stencil); + + GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm); + GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco); + GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), + GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), + GPU_builtin(GPU_VIEW_POSITION), &texco_object); + GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); + GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), + GPU_builtin(GPU_VIEW_POSITION), &texco_global); + + orn= texco_norm; + + /* go over texture slots */ + for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { + mtex= ma->mtex[tex_nr]; + + tex= mtex->tex; + if(tex==0) continue; + + /* which coords */ + if(mtex->texco==TEXCO_ORCO) + texco= texco_orco; + else if(mtex->texco==TEXCO_OBJECT) + texco= texco_object; + else if(mtex->texco==TEXCO_NORM) + texco= texco_norm; + else if(mtex->texco==TEXCO_TANGENT) + texco= texco_object; + else if(mtex->texco==TEXCO_GLOB) + texco= texco_global; + else if(mtex->texco==TEXCO_REFL) + texco= shi->ref; + else if(mtex->texco==TEXCO_UV) { + if(1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) { + GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv); + lastuvname = mtex->uvname; + } + texco= texco_uv; + } + else + continue; + + /* in case of uv, this would just undo a multiplication in texco_uv */ + if(mtex->texco != TEXCO_UV) + GPU_link(mat, "mtex_2d_mapping", texco, &texco); + + if(mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) + GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco); + + ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0]; + ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1]; + ofs[2] = 0.0f; + if(ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) + GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); + + talpha = 0; + rgbnor = 0; + + if(tex && tex->type == TEX_IMAGE && tex->ima) { + GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, NULL), &tin, &trgb, &tnor); + rgbnor= TEX_RGB; + + if(tex->imaflag & TEX_USEALPHA) + talpha= 1; + } + else continue; + + /* texture output */ + if((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { + GPU_link(mat, "mtex_rgbtoint", trgb, &tin); + rgbnor -= TEX_RGB; + } + + if(mtex->texflag & MTEX_NEGATIVE) { + if(rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgb_invert", trgb, &trgb); + else + GPU_link(mat, "mtex_value_invert", tin, &tin); + } + + if(mtex->texflag & MTEX_STENCIL) { + if(rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb); + else + GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin); + } + + /* mapping */ + if(mtex->mapto & (MAP_COL+MAP_COLSPEC)) { + /* stencil maps on the texture control slider, not texture intensity value */ + if(mtex->colfac == 1.0f) + colfac = stencil; + else + GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac); + + if((rgbnor & TEX_RGB)==0) { + GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol); + } + else { + GPU_link(mat, "set_rgba", trgb, &tcol); + + if(mtex->mapto & MAP_ALPHA) + GPU_link(mat, "set_value", stencil, &tin); + else if(talpha) + GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); + else + GPU_link(mat, "set_value_one", &tin); + } + + if(mtex->mapto & MAP_COL) + texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb); + + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) + texture_rgb_blend(mat, tcol, shi->specrgb, tin, colfac, mtex->blendtype, &shi->specrgb); + } + + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) { + if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; + else tex->norfac= mtex->norfac; + + if((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) { + tex->norfac = mtex->norfac; + + if(mtex->maptoneg & MAP_NORM) + GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor); + + if(mtex->normapspace == MTEX_NSPACE_TANGENT) + GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor); + else + newnor = tnor; + + norfac = MIN2(mtex->norfac, 1.0); + if(norfac == 1.0f && !GPU_link_changed(stencil)) { + shi->vn = newnor; + } + else { + tnorfac = GPU_uniform(&norfac); + + if(GPU_link_changed(stencil)) + GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); + + GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn); + } + } + + GPU_link(mat, "vec_math_negate", shi->vn, &orn); + GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); + } + + if((mtex->mapto & MAP_VARS)) { + if(mtex->varfac == 1.0f) + varfac = stencil; + else + GPU_link(mat, "math_multiply", GPU_uniform(&mtex->varfac), stencil, &varfac); + + if(rgbnor & TEX_RGB) { + if(talpha) + GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); + else + GPU_link(mat, "mtex_rgbtoint", trgb, &tin); + } + + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) { + int flip= mtex->maptoneg & MAP_REF; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->refl, tin, varfac, mtex->blendtype, flip, &shi->refl); + GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) { + int flip= mtex->maptoneg & MAP_SPEC; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->spec, tin, varfac, mtex->blendtype, flip, &shi->spec); + GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) { + int flip= mtex->maptoneg & MAP_EMIT; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->emit, tin, varfac, mtex->blendtype, flip, &shi->emit); + GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) { + int flip= mtex->maptoneg & MAP_HAR; + GPU_link(mat, "mtex_har_divide", shi->har, &shi->har); + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->har, tin, varfac, mtex->blendtype, flip, &shi->har); + GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har); + } + if(mtex->mapto & MAP_ALPHA) { + int flip= mtex->maptoneg & MAP_ALPHA; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, varfac, mtex->blendtype, flip, &shi->alpha); + GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) { + int flip= mtex->maptoneg & MAP_AMB; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->amb, tin, varfac, mtex->blendtype, flip, &shi->amb); + GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb); + } + } + } + } +} + +void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) +{ + float hard = ma->har; + + memset(shi, 0, sizeof(*shi)); + + shi->gpumat = mat; + shi->mat = ma; + + GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb); + GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb); + GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn); + GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha); + GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl); + GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec); + GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit); + GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har); + GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb); + GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view); + GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol); + GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); +} + +void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) +{ + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac; + Material *ma= shi->mat; + World *world= mat->scene->world; + float linfac, logfac, misttype; + + memset(shr, 0, sizeof(*shr)); + + if(ma->mode & MA_VERTEXCOLP) + shi->rgb = shi->vcol; + + do_material_tex(shi); + + if(ma->mode & MA_ZTRA) + GPU_material_enable_alpha(mat); + + if((G.fileflags & G_FILE_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) { + shr->combined = shi->rgb; + shr->alpha = shi->alpha; + } + else { + if(GPU_link_changed(shi->emit) || ma->emit != 0.0f) { + if((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) { + GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit); + GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff); + } + else + GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff); + } + else + GPU_link(mat, "set_rgb_zero", &shr->diff); + + GPU_link(mat, "set_rgb_zero", &shr->spec); + + material_lights(shi, shr); + + shr->combined = shr->diff; + shr->alpha = shi->alpha; + + if(world) { + /* exposure correction */ + if(world->exp!=0.0f || world->range!=1.0f) { + linfac= 1.0 + pow((2.0*world->exp + 0.5), -10); + logfac= log((linfac-1.0)/linfac)/world->range; + + GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac); + GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac); + + GPU_link(mat, "shade_exposure_correct", shr->combined, + ulinfac, ulogfac, &shr->combined); + GPU_link(mat, "shade_exposure_correct", shr->spec, + ulinfac, ulogfac, &shr->spec); + } + + /* ambient color */ + if(world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) { + if(GPU_link_changed(shi->amb) || ma->amb != 0.0f) + GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), + GPU_uniform(&world->ambr), &shr->combined); + } + } + + if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined); + if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec); + + if(GPU_link_changed(shi->spec) || ma->spec != 0.0f) + GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined); + } + + GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined); + + if(ma->shade_flag & MA_OBCOLOR) + GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); + + if(world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) { + misttype = world->mistype; + + GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION), + GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist), + GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac); + + GPU_link(mat, "mix_blend", mistfac, shr->combined, + GPU_uniform(&world->horr), &shr->combined); + } + + if(!(ma->mode & MA_ZTRA)) { + if(world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f)) + GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr), + shr->combined, &shr->combined); + + GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined); + } + + if(ma->shade_flag & MA_OBCOLOR) { + mat->obcolalpha = 1; + GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); + } +} + +GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) +{ + GPUShadeInput shi; + GPUShadeResult shr; + + GPU_shadeinput_set(mat, ma, &shi); + GPU_shaderesult_set(&shi, &shr); + + return shr.combined; +} + +GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) +{ + GPUMaterial *mat; + GPUNodeLink *outlink; + LinkData *link; + + for(link=ma->gpumaterial.first; link; link=link->next) + if(((GPUMaterial*)link->data)->scene == scene) + return link->data; + + mat = GPU_material_construct_begin(ma); + mat->scene = scene; + + if(!(G.fileflags & G_FILE_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) { + ntreeGPUMaterialNodes(ma->nodetree, mat); + } + else { + outlink = GPU_blender_material(mat, ma); + GPU_material_output_link(mat, outlink); + } + + /*if(!GPU_material_construct_end(mat)) { + GPU_material_free(mat); + mat= NULL; + return 0; + }*/ + + GPU_material_construct_end(mat); + + link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); + link->data = mat; + BLI_addtail(&ma->gpumaterial, link); + + return mat; +} + +void GPU_materials_free() +{ + Object *ob; + Material *ma; + extern Material defmaterial; + + for(ma=G.main->mat.first; ma; ma=ma->id.next) + GPU_material_free(ma); + + GPU_material_free(&defmaterial); + + for(ob=G.main->object.first; ma; ma=ma->id.next) + GPU_lamp_free(ob); +} + +/* Lamps and shadow buffers */ + +void GPU_lamp_update(GPULamp *lamp, int lay, float obmat[][4]) +{ + float mat[4][4]; + + lamp->lay = lay; + + Mat4CpyMat4(mat, obmat); + Mat4Ortho(mat); + + VECCOPY(lamp->vec, mat[2]); + VECCOPY(lamp->co, mat[3]); + Mat4CpyMat4(lamp->obmat, mat); + Mat4Invert(lamp->imat, mat); +} + +static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) +{ + float temp, angle, pixsize, wsize; + + lamp->scene = scene; + lamp->ob = ob; + lamp->par = par; + lamp->la = la; + + /* add_render_lamp */ + lamp->mode = la->mode; + lamp->type = la->type; + + lamp->energy = la->energy; + if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy; + + lamp->col[0]= la->r*lamp->energy; + lamp->col[1]= la->g*lamp->energy; + lamp->col[2]= la->b*lamp->energy; + + GPU_lamp_update(lamp, ob->lay, ob->obmat); + + lamp->spotsi= la->spotsize; + if(lamp->mode & LA_HALO) + if(lamp->spotsi > 170.0) + lamp->spotsi = 170.0; + lamp->spotsi= cos(M_PI*lamp->spotsi/360.0); + lamp->spotbl= (1.0 - lamp->spotsi)*la->spotblend; + lamp->k= la->k; + + lamp->dist= la->dist; + lamp->falloff_type= la->falloff_type; + lamp->att1= la->att1; + lamp->att2= la->att2; + lamp->curfalloff= la->curfalloff; + + /* initshadowbuf */ + lamp->bias = 0.02f*la->bias; + lamp->size = la->bufsize; + lamp->d= la->clipsta; + lamp->clipend= la->clipend; + + /* arbitrary correction for the fact we do no soft transition */ + lamp->bias *= 0.25f; + + /* makeshadowbuf */ + angle= saacos(lamp->spotsi); + temp= 0.5f*lamp->size*cos(angle)/sin(angle); + pixsize= (lamp->d)/temp; + wsize= pixsize*0.5f*lamp->size; + + i_window(-wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend, lamp->winmat); +} + +static void gpu_lamp_shadow_free(GPULamp *lamp) +{ + if(lamp->tex) + GPU_texture_free(lamp->tex); + if(lamp->fb) + GPU_framebuffer_free(lamp->fb); +} + +GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) +{ + Lamp *la; + GPULamp *lamp; + LinkData *link; + + for(link=ob->gpulamp.first; link; link=link->next) { + lamp = (GPULamp*)link->data; + + if(lamp->par == par && lamp->scene == scene) + return link->data; + } + + lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); + + link = MEM_callocN(sizeof(LinkData), "GPULampLink"); + link->data = lamp; + BLI_addtail(&ob->gpulamp, link); + + la = ob->data; + gpu_lamp_from_blender(scene, ob, par, la, lamp); + + if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF)) { + /* opengl */ + lamp->fb = GPU_framebuffer_create(); + if(!lamp->fb) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size); + if(!lamp->tex) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if(!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + GPU_framebuffer_restore(); + } + + return lamp; +} + +void GPU_lamp_free(Object *ob) +{ + GPULamp *lamp; + LinkData *link; + LinkData *nlink; + Material *ma; + + for(link=ob->gpulamp.first; link; link=link->next) { + lamp = link->data; + + while(lamp->materials.first) { + nlink = lamp->materials.first; + ma = nlink->data; + BLI_freelinkN(&lamp->materials, nlink); + + if(ma->gpumaterial.first) + GPU_material_free(ma); + } + + gpu_lamp_shadow_free(lamp); + + MEM_freeN(lamp); + } + + BLI_freelistN(&ob->gpulamp); +} + +int GPU_lamp_has_shadow_buffer(GPULamp *lamp) +{ + return (!(G.fileflags & G_FILE_GLSL_NO_SHADOWS) && + !(G.fileflags & G_FILE_GLSL_NO_LIGHTS) && + lamp->tex && lamp->fb); +} + +void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]) +{ + float rangemat[4][4], persmat[4][4]; + + /* initshadowbuf */ + Mat4Invert(lamp->viewmat, lamp->obmat); + Normalize(lamp->viewmat[0]); + Normalize(lamp->viewmat[1]); + Normalize(lamp->viewmat[2]); + + /* makeshadowbuf */ + Mat4MulMat4(persmat, lamp->viewmat, lamp->winmat); + + /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ + Mat4One(rangemat); + rangemat[0][0] = 0.5f; + rangemat[1][1] = 0.5f; + rangemat[2][2] = 0.5f; + rangemat[3][0] = 0.5f; + rangemat[3][1] = 0.5f; + rangemat[3][2] = 0.5f; + + Mat4MulMat4(lamp->persmat, persmat, rangemat); + + /* opengl */ + GPU_framebuffer_texture_bind(lamp->fb, lamp->tex); + + /* set matrices */ + Mat4CpyMat4(viewmat, lamp->viewmat); + Mat4CpyMat4(winmat, lamp->winmat); + *winsize = lamp->size; +} + +void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) +{ + GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); + GPU_framebuffer_restore(); +} + +int GPU_lamp_shadow_layer(GPULamp *lamp) +{ + if(lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW))) + return lamp->lay; + else + return -1; +} + diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl b/source/blender/gpu/intern/gpu_shader_material.glsl new file mode 100644 index 00000000000..16ed38cb47d --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_material.glsl @@ -0,0 +1,1555 @@ + +float exp_blender(float f) +{ + return pow(2.71828182846, f); +} + +void rgb_to_hsv(vec4 rgb, out vec4 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax-cmin; + + v = cmax; + if (cmax!=0.0) + s = cdelta/cmax; + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax, cmax, cmax) - rgb.xyz)/cdelta; + + if (rgb.x==cmax) h = c[2] - c[1]; + else if (rgb.y==cmax) h = 2.0 + c[0] - c[2]; + else h = 4.0 + c[1] - c[0]; + + h /= 6.0; + + if (h<0.0) + h += 1.0; + } + + outcol = vec4(h, s, v, rgb.w); +} + +void hsv_to_rgb(vec4 hsv, out vec4 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if(s==0.0) { + rgb = vec3(v, v, v); + } + else { + if(h==1.0) + h = 0.0; + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v*(1.0-s); + q = v*(1.0-(s*f)); + t = v*(1.0-(s*(1.0-f))); + + if (i == 0.0) rgb = vec3(v, t, p); + else if (i == 1.0) rgb = vec3(q, v, p); + else if (i == 2.0) rgb = vec3(p, v, t); + else if (i == 3.0) rgb = vec3(p, q, v); + else if (i == 4.0) rgb = vec3(t, p, v); + else rgb = vec3(v, p, q); + } + + outcol = vec4(rgb, hsv.w); +} + +#define M_PI 3.14159265358979323846 + +/*********** SHADER NODES ***************/ + +void vcol_attribute(vec4 attvcol, out vec4 vcol) +{ + vcol = vec4(attvcol.x/255.0, attvcol.y/255.0, attvcol.z/255.0, 1.0); +} + +void uv_attribute(vec2 attuv, out vec3 uv) +{ + uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); +} + +void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol, out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv, out vec3 normal, out vec4 vcol, out float frontback) +{ + local = co; + view = normalize(local); + global = (viewinvmat*vec4(local, 1.0)).xyz; + orco = attorco; + uv_attribute(attuv, uv); + normal = -normalize(nor); /* blender render normal is negated */ + vcol_attribute(attvcol, vcol); + frontback = 1.0; +} + +void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec) +{ + outvec = (mat * vec4(vec, 1.0)).xyz; + if(domin == 1.0) + outvec = max(outvec, minvec); + if(domax == 1.0) + outvec = min(outvec, maxvec); +} + +void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) +{ + outdepth = abs(co.z); + outdist = length(co); + outview = normalize(co); +} + +void math_add(float val1, float val2, out float outval) +{ + outval = val1 + val2; +} + +void math_subtract(float val1, float val2, out float outval) +{ + outval = val1 - val2; +} + +void math_multiply(float val1, float val2, out float outval) +{ + outval = val1 * val2; +} + +void math_divide(float val1, float val2, out float outval) +{ + if (val2 == 0.0) + outval = 0.0; + else + outval = val1 / val2; +} + +void math_sine(float val, out float outval) +{ + outval = sin(val); +} + +void math_cosine(float val, out float outval) +{ + outval = cos(val); +} + +void math_tangent(float val, out float outval) +{ + outval = tan(val); +} + +void math_asin(float val, out float outval) +{ + if (val <= 1.0 && val >= -1.0) + outval = asin(val); + else + outval = 0.0; +} + +void math_acos(float val, out float outval) +{ + if (val <= 1.0 && val >= -1.0) + outval = acos(val); + else + outval = 0.0; +} + +void math_atan(float val, out float outval) +{ + outval = atan(val); +} + +void math_pow(float val1, float val2, out float outval) +{ + if (val1 >= 0.0) + outval = pow(val1, val2); + else + outval = 0.0; +} + +void math_log(float val1, float val2, out float outval) +{ + if(val1 > 0.0 && val2 > 0.0) + outval= log2(val1) / log2(val2); + else + outval= 0.0; +} + +void math_max(float val1, float val2, out float outval) +{ + outval = max(val1, val2); +} + +void math_min(float val1, float val2, out float outval) +{ + outval = min(val1, val2); +} + +void math_round(float val, out float outval) +{ + outval= floor(val + 0.5); +} + +void math_less_than(float val1, float val2, out float outval) +{ + if(val1 < val2) + outval = 1.0; + else + outval = 0.0; +} + +void math_greater_than(float val1, float val2, out float outval) +{ + if(val1 > val2) + outval = 1.0; + else + outval = 0.0; +} + +void squeeze(float val, float width, float center, out float outval) +{ + outval = 1.0/(1.0 + pow(2.71828183, -((val-center)*width))); +} + +void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = v1 + v2; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0; +} + +void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = v1 - v2; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0; +} + +void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = v1 + v2; + outval = length(outvec); + outvec = normalize(outvec); +} + +void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = vec3(0, 0, 0); + outval = dot(v1, v2); +} + +void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = cross(v1, v2); + outval = length(outvec); +} + +void vec_math_normalize(vec3 v, out vec3 outvec, out float outval) +{ + outval = length(v); + outvec = normalize(v); +} + +void vec_math_negate(vec3 v, out vec3 outv) +{ + outv = -v; +} + +void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot) +{ + outnor = dir; + outdot = -dot(dir, nor); +} + +void curves_vec(vec3 vec, sampler1D curvemap, out vec3 outvec) +{ + outvec.x = texture1D(curvemap, (vec.x + 1.0)*0.5).x; + outvec.y = texture1D(curvemap, (vec.y + 1.0)*0.5).y; + outvec.z = texture1D(curvemap, (vec.z + 1.0)*0.5).z; +} + +void curves_rgb(vec4 col, sampler1D curvemap, out vec4 outcol) +{ + outcol.r = texture1D(curvemap, texture1D(curvemap, col.r).a).r; + outcol.g = texture1D(curvemap, texture1D(curvemap, col.g).a).g; + outcol.b = texture1D(curvemap, texture1D(curvemap, col.b).a).b; + outcol.a = col.a; +} + +void set_value(float val, out float outval) +{ + outval = val; +} + +void set_rgb(vec3 col, out vec3 outcol) +{ + outcol = col; +} + +void set_rgba(vec4 col, out vec4 outcol) +{ + outcol = col; +} + +void set_value_zero(out float outval) +{ + outval = 0.0; +} + +void set_value_one(out float outval) +{ + outval = 1.0; +} + +void set_rgb_zero(out vec3 outval) +{ + outval = vec3(0.0); +} + +void set_rgba_zero(out vec4 outval) +{ + outval = vec4(0.0); +} + +void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col2, fac); + outcol.a = col1.a; +} + +void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 + col2, fac); + outcol.a = col1.a; +} + +void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 * col2, fac); + outcol.a = col1.a; +} + +void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = vec4(1.0) - (vec4(facm) + fac*(vec4(1.0) - col2))*(vec4(1.0) - col1); + outcol.a = col1.a; +} + +void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if(outcol.r < 0.5) + outcol.r *= facm + 2.0*fac*col2.r; + else + outcol.r = 1.0 - (facm + 2.0*fac*(1.0 - col2.r))*(1.0 - outcol.r); + + if(outcol.g < 0.5) + outcol.g *= facm + 2.0*fac*col2.g; + else + outcol.g = 1.0 - (facm + 2.0*fac*(1.0 - col2.g))*(1.0 - outcol.g); + + if(outcol.b < 0.5) + outcol.b *= facm + 2.0*fac*col2.b; + else + outcol.b = 1.0 - (facm + 2.0*fac*(1.0 - col2.b))*(1.0 - outcol.b); +} + +void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 - col2, fac); + outcol.a = col1.a; +} + +void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if(col2.r != 0.0) outcol.r = facm*outcol.r + fac*outcol.r/col2.r; + if(col2.g != 0.0) outcol.g = facm*outcol.g + fac*outcol.g/col2.g; + if(col2.b != 0.0) outcol.b = facm*outcol.b + fac*outcol.b/col2.b; +} + +void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, abs(col1 - col2), fac); + outcol.a = col1.a; +} + +void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = min(col1.rgb, col2.rgb*fac); + outcol.a = col1.a; +} + +void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = max(col1.rgb, col2.rgb*fac); + outcol.a = col1.a; +} + +void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = col1; + + if(outcol.r != 0.0) { + float tmp = 1.0 - fac*col2.r; + if(tmp <= 0.0) + outcol.r = 1.0; + else if((tmp = outcol.r/tmp) > 1.0) + outcol.r = 1.0; + else + outcol.r = tmp; + } + if(outcol.g != 0.0) { + float tmp = 1.0 - fac*col2.g; + if(tmp <= 0.0) + outcol.g = 1.0; + else if((tmp = outcol.g/tmp) > 1.0) + outcol.g = 1.0; + else + outcol.g = tmp; + } + if(outcol.b != 0.0) { + float tmp = 1.0 - fac*col2.b; + if(tmp <= 0.0) + outcol.b = 1.0; + else if((tmp = outcol.b/tmp) > 1.0) + outcol.b = 1.0; + else + outcol.b = tmp; + } +} + +void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float tmp, facm = 1.0 - fac; + + outcol = col1; + + tmp = facm + fac*col2.r; + if(tmp <= 0.0) + outcol.r = 0.0; + else if((tmp = (1.0 - (1.0 - outcol.r)/tmp)) < 0.0) + outcol.r = 0.0; + else if(tmp > 1.0) + outcol.r = 1.0; + else + outcol.r = tmp; + + tmp = facm + fac*col2.g; + if(tmp <= 0.0) + outcol.g = 0.0; + else if((tmp = (1.0 - (1.0 - outcol.g)/tmp)) < 0.0) + outcol.g = 0.0; + else if(tmp > 1.0) + outcol.g = 1.0; + else + outcol.g = tmp; + + tmp = facm + fac*col2.b; + if(tmp <= 0.0) + outcol.b = 0.0; + else if((tmp = (1.0 - (1.0 - outcol.b)/tmp)) < 0.0) + outcol.b = 0.0; + else if(tmp > 1.0) + outcol.b = 1.0; + else + outcol.b = tmp; +} + +void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if(hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2; + rgb_to_hsv(outcol, hsv); + + if(hsv.y != 0.0) { + rgb_to_hsv(col2, hsv2); + + hsv.y = facm*hsv.y + fac*hsv2.y; + hsv_to_rgb(hsv, outcol); + } +} + +void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + vec4 hsv, hsv2; + rgb_to_hsv(col1, hsv); + rgb_to_hsv(col2, hsv2); + + hsv.z = facm*hsv.z + fac*hsv2.z; + hsv_to_rgb(hsv, outcol); +} + +void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if(hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv.y = hsv2.y; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void valtorgb(float fac, sampler1D colormap, out vec4 outcol, out float outalpha) +{ + outcol = texture1D(colormap, fac); + outalpha = outcol.a; +} + +void rgbtobw(vec4 color, out float outval) +{ + outval = color.r*0.35 + color.g*0.45 + color.b*0.2; +} + +void invert(float fac, vec4 col, out vec4 outcol) +{ + outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac); + outcol.w = col.w; +} + +void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) +{ + vec4 hsv; + + rgb_to_hsv(col, hsv); + + hsv[0] += (hue - 0.5); + if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0; + hsv[1] *= sat; + if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0; + hsv[2] *= value; + if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0; + + hsv_to_rgb(hsv, outcol); + + outcol = mix(col, outcol, fac); +} + +void separate_rgb(vec4 col, out float r, out float g, out float b) +{ + r = col.r; + g = col.g; + b = col.b; +} + +void combine_rgb(float r, float g, float b, out vec4 col) +{ + col = vec4(r, g, b, 1.0); +} + +void output_node(vec4 rgb, float alpha, out vec4 outrgb) +{ + outrgb = vec4(rgb.rgb, alpha); +} + +/*********** TEXTURES ***************/ + +void texture_flip_blend(vec3 vec, out vec3 outvec) +{ + outvec = vec.yxz; +} + +void texture_blend_lin(vec3 vec, out float outval) +{ + outval = (1.0+vec.x)/2.0; +} + +void texture_blend_quad(vec3 vec, out float outval) +{ + outval = max((1.0+vec.x)/2.0, 0.0); + outval *= outval; +} + +void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal) +{ + float a = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)*20.0; + float wi = 0.5 + 0.5*sin(a); + + value = wi; + color = vec4(wi, wi, wi, 1.0); + normal = vec3(0.0, 0.0, 0.0); +} + +void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) +{ + color = texture2D(ima, (vec.xy + vec2(1.0, 1.0))*0.5); + value = 1.0; + + normal.x = 2.0*(color.r - 0.5); + normal.y = 2.0*(0.5 - color.g); + normal.z = 2.0*(color.b - 0.5); +} + +/************* MTEX *****************/ + +void texco_orco(vec3 attorco, out vec3 orco) +{ + orco = attorco; +} + +void texco_uv(vec2 attuv, out vec3 uv) +{ + /* disabled for now, works together with leaving out mtex_2d_mapping + uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */ + uv = vec3(attuv, 0.0); +} + +void texco_norm(vec3 normal, out vec3 outnormal) +{ + /* corresponds to shi->orn, which is negated so cancels + out blender normal negation */ + outnormal = normalize(normal); +} + +void texco_tangent(vec3 tangent, out vec3 outtangent) +{ + outtangent = normalize(tangent); +} + +void texco_global(mat4 viewinvmat, vec3 co, out vec3 global) +{ + global = (viewinvmat*vec4(co, 1.0)).xyz; +} + +void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object) +{ + object = (obinvmat*(viewinvmat*vec4(co, 1.0))).xyz; +} + +void texco_refl(vec3 vn, vec3 view, out vec3 ref) +{ + ref = view - 2.0*dot(vn, view)*vn; +} + +void shade_norm(vec3 normal, out vec3 outnormal) +{ + /* blender render normal is negated */ + outnormal = -normalize(normal); +} + +void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-fact; + + incol = fact*texcol + facm*outcol; +} + +void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-facg; + + incol = (facm + fact*texcol)*outcol; +} + +void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-facg; + + incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol); +} + +void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-facg; + + if(outcol.r < 0.5) + incol.r = outcol.r*(facm + 2.0*fact*texcol.r); + else + incol.r = 1.0 - (facm + 2.0*fact*(1.0 - texcol.r))*(1.0 - outcol.r); + + if(outcol.g < 0.5) + incol.g = outcol.g*(facm + 2.0*fact*texcol.g); + else + incol.g = 1.0 - (facm + 2.0*fact*(1.0 - texcol.g))*(1.0 - outcol.g); + + if(outcol.b < 0.5) + incol.b = outcol.b*(facm + 2.0*fact*texcol.b); + else + incol.b = 1.0 - (facm + 2.0*fact*(1.0 - texcol.b))*(1.0 - outcol.b); +} + +void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + incol = -fact*facg*texcol + outcol; +} + +void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + incol = fact*facg*texcol + outcol; +} + +void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-fact; + + if(texcol.r != 0.0) incol.r = facm*outcol.r + fact*outcol.r/texcol.r; + if(texcol.g != 0.0) incol.g = facm*outcol.g + fact*outcol.g/texcol.g; + if(texcol.b != 0.0) incol.b = facm*outcol.b + fact*outcol.b/texcol.b; +} + +void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-fact; + + incol = facm*outcol + fact*abs(texcol - outcol); +} + +void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm, col; + + fact *= facg; + facm = 1.0-fact; + + col = fact*texcol.r; + if(col < outcol.r) incol.r = col; else incol.r = outcol.r; + col = fact*texcol.g; + if(col < outcol.g) incol.g = col; else incol.g = outcol.g; + col = fact*texcol.b; + if(col < outcol.b) incol.b = col; else incol.b = outcol.b; +} + +void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm, col; + + fact *= facg; + facm = 1.0-fact; + + col = fact*texcol.r; + if(col > outcol.r) incol.r = col; else incol.r = outcol.r; + col = fact*texcol.g; + if(col > outcol.g) incol.g = col; else incol.g = outcol.g; + col = fact*texcol.b; + if(col > outcol.b) incol.b = col; else incol.b = outcol.b; +} + +void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_hue(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_sat(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_val(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_color(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_value_vars(inout float fact, float facg, out float facm, float flip) +{ + fact *= facg; + facm = 1.0-fact; + + if(flip != 0.0) { + float tmp = fact; + fact = facm; + facm = tmp; + } +} + +void mtex_value_blend(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + incol = fact*texcol + facm*outcol; +} + +void mtex_value_mul(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + facm = 1.0 - facg; + incol = (facm + fact*texcol)*outcol; +} + +void mtex_value_screen(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + facm = 1.0 - facg; + incol = 1.0 - (facm + fact*(1.0 - texcol))*(1.0 - outcol); +} + +void mtex_value_sub(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + fact = -fact; + incol = fact*texcol + outcol; +} + +void mtex_value_add(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + fact = fact; + incol = fact*texcol + outcol; +} + +void mtex_value_div(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + if(texcol != 0.0) + incol = facm*outcol + fact*outcol/texcol; + else + incol = 0.0; +} + +void mtex_value_diff(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + incol = facm*outcol + fact*abs(texcol - outcol); +} + +void mtex_value_dark(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + float col = fact*texcol; + if(col < outcol) incol = col; else incol = outcol; +} + +void mtex_value_light(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + float col = fact*texcol; + if(col > outcol) incol = col; else incol = outcol; +} + +void mtex_value_clamp_positive(float fac, out float outfac) +{ + outfac = max(fac, 0.0); +} + +void mtex_value_clamp(float fac, out float outfac) +{ + outfac = clamp(fac, 0.0, 1.0); +} + +void mtex_har_divide(float har, out float outhar) +{ + outhar = har/128.0; +} + +void mtex_har_multiply_clamp(float har, out float outhar) +{ + har *= 128.0; + + if(har < 1.0) outhar = 1.0; + else if(har > 511.0) outhar = 511.0; + else outhar = har; +} + +void mtex_alpha_from_col(vec4 col, out float alpha) +{ + alpha = col.a; +} + +void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol) +{ + outcol = vec4(col.rgb, alpha); +} + +void mtex_rgbtoint(vec4 rgb, out float intensity) +{ + intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb); +} + +void mtex_value_invert(float invalue, out float outvalue) +{ + outvalue = 1.0 - invalue; +} + +void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb) +{ + outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a); +} + +void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity) +{ + float fact = intensity; + outintensity = intensity*stencil; + outstencil = stencil*fact; +} + +void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb) +{ + float fact = rgb.a; + outrgb = vec4(rgb.rgb, rgb.a*stencil); + outstencil = stencil*fact; +} + +void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco) +{ + outtexco = texco + ofs; +} + +void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco) +{ + outtexco = size*texco; +} + +void mtex_2d_mapping(vec3 vec, out vec3 outvec) +{ + outvec = vec3(vec.xy*0.5 + vec2(0.5, 0.5), vec.z); +} + +void mtex_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) +{ + color = texture2D(ima, vec.xy); + value = 1.0; + + normal = 2.0*(vec3(color.r, -color.g, color.b) - vec3(0.5, -0.5, 0.5)); +} + +void mtex_negate_texnormal(vec3 normal, out vec3 outnormal) +{ + outnormal = vec3(-normal.x, -normal.y, normal.z); +} + +void mtex_nspace_tangent(vec3 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) +{ + tangent = normalize(tangent); + vec3 B = cross(normal, tangent); + + outnormal = texnormal.x*tangent + texnormal.y*B + texnormal.z*normal; + outnormal = normalize(outnormal); +} + +void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) +{ + outnormal = (1.0 - norfac)*normal + norfac*newnormal; + outnormal = normalize(outnormal); +} + +/******* MATERIAL *********/ + +void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac) +{ + lv = lampvec; + dist = 1.0; + visifac = 1.0; +} + +void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac) +{ + lv = co - lampco; + dist = length(lv); + lv = normalize(lv); + visifac = 1.0; +} + +void lamp_falloff_invlinear(float lampdist, float dist, out float visifac) +{ + visifac = lampdist/(lampdist + dist); +} + +void lamp_falloff_invsquare(float lampdist, float dist, out float visifac) +{ + visifac = lampdist/(lampdist + dist*dist); +} + +void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac) +{ + float lampdistkw = lampdist*lampdist; + + visifac = lampdist/(lampdist + ld1*dist); + visifac *= lampdistkw/(lampdistkw + ld2*dist*dist); +} + +void lamp_falloff_curve(float lampdist, sampler1D curvemap, float dist, out float visifac) +{ + visifac = texture1D(curvemap, dist/lampdist).x; +} + +void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac) +{ + float t= lampdist - dist; + + outvisifac= visifac*max(t, 0.0)/lampdist; +} + +void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr) +{ + if(dot(lv, lampvec) > 0.0) { + vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz; + float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z)); + + inpr = 1.0/sqrt(1.0 + x*x); + } + else + inpr = 0.0; +} + +void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr) +{ + inpr = dot(lv, lampvec); +} + +void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac) +{ + float t = spotsi; + + if(inpr <= t) { + outvisifac = 0.0; + } + else { + t = inpr - t; + + /* soft area */ + if(spotbl != 0.0) + inpr *= smoothstep(0.0, 1.0, t/spotbl); + + outvisifac = visifac*inpr; + } +} + +void lamp_visibility_clamp(float visifac, out float outvisifac) +{ + outvisifac = (visifac < 0.001)? 0.0: visifac; +} + +void shade_view(vec3 co, out vec3 view) +{ + /* handle perspective/orthographic */ + view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(co): vec3(0.0, 0.0, -1.0); +} + +void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn) +{ + vec3 c = cross(lv, tang); + vec3 vnor = cross(c, tang); + + vn = -normalize(vnor); +} + +void shade_inp(vec3 vn, vec3 lv, out float inp) +{ + inp = dot(vn, lv); +} + +void shade_is_no_diffuse(out float is) +{ + is = 0.0; +} + +void shade_is_hemi(float inp, out float is) +{ + is = 0.5*inp + 0.5; +} + +float area_lamp_energy(mat4 area, vec3 co, vec3 vn) +{ + vec3 vec[4], c[4]; + float rad[4], fac; + + vec[0] = normalize(co - area[0].xyz); + vec[1] = normalize(co - area[1].xyz); + vec[2] = normalize(co - area[2].xyz); + vec[3] = normalize(co - area[3].xyz); + + c[0] = normalize(cross(vec[0], vec[1])); + c[1] = normalize(cross(vec[1], vec[2])); + c[2] = normalize(cross(vec[2], vec[3])); + c[3] = normalize(cross(vec[3], vec[0])); + + rad[0] = acos(dot(vec[0], vec[1])); + rad[1] = acos(dot(vec[1], vec[2])); + rad[2] = acos(dot(vec[2], vec[3])); + rad[3] = acos(dot(vec[3], vec[0])); + + fac= rad[0]*dot(vn, c[0]); + fac+= rad[1]*dot(vn, c[1]); + fac+= rad[2]*dot(vn, c[2]); + fac+= rad[3]*dot(vn, c[3]); + + return max(fac, 0.0); +} + +void shade_inp_area(vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k, out float inp) +{ + vec3 co = position; + vec3 vec = co - lampco; + + if(dot(vec, lampvec) < 0.0) { + inp = 0.0; + } + else { + float intens = area_lamp_energy(area, co, vn); + + inp = pow(intens*areasize, k); + } +} + +void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is) +{ + vec3 h = normalize(v + l); + float nh = max(dot(n, h), 0.0); + float nv = max(dot(n, v), 0.0); + float realnl = dot(n, l); + + if(realnl < 0.0) { + is = 0.0; + } + else if(nl < 0.0) { + is = 0.0; + } + else { + float vh = max(dot(v, h), 0.0); + float Lit_A = acos(realnl); + float View_A = acos(nv); + + vec3 Lit_B = normalize(l - realnl*n); + vec3 View_B = normalize(v - nv*n); + + float t = max(dot(Lit_B, View_B), 0.0); + + float a, b; + + if(Lit_A > View_A) { + a = Lit_A; + b = View_A; + } + else { + a = View_A; + b = Lit_A; + } + + float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33))); + float B = 0.45*((rough*rough)/((rough*rough) + 0.09)); + + b *= 0.95; + is = nl*(A + (B * t * sin(a) * tan(b))); + } +} + +void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is) +{ + float rslt = dot(n, l); + float ang = acos(rslt); + + if(ang < size) is = 1.0; + else if(ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0; + else is = 1.0 - ((ang - size)/tsmooth); +} + +void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is) +{ + if(nl <= 0.0) { + is = 0.0; + } + else { + float nv = max(dot(n, v), 0.0); + + if(darkness <= 1.0) + is = nl*pow(max(nv*nl, 0.1), darkness - 1.0); + else + is = nl*pow(1.0001 - nv, darkness - 1.0); + } +} + +float fresnel_fac(vec3 view, vec3 vn, float grad, float fac) +{ + float t1, t2; + float ffac; + + if(fac==0.0) { + ffac = 1.0; + } + else { + t1= dot(view, vn); + if(t1>0.0) t2= 1.0+t1; + else t2= 1.0-t1; + + t2= grad + (1.0-grad)*pow(t2, fac); + + if(t2<0.0) ffac = 0.0; + else if(t2>1.0) ffac = 1.0; + else ffac = t2; + } + + return ffac; +} + +void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is) +{ + is = fresnel_fac(lv, vn, fac_i, fac); +} + +void shade_cubic(float is, out float outis) +{ + if(is>0.0 && is<1.0) + outis= smoothstep(0.0, 1.0, is); + else + outis= is; +} + +void shade_visifac(float i, float visifac, float refl, out float outi) +{ + /*if(i > 0.0)*/ + outi = max(i*visifac*refl, 0.0); + /*else + outi = i;*/ +} + +void shade_tangent_v_spec(vec3 tang, out vec3 vn) +{ + vn = tang; +} + +void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol) +{ + if(i > 0.0) + outcol = i*lampcol*col; + else + outcol = vec3(0.0, 0.0, 0.0); +} + +void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t) +{ + lv += view; + lv = normalize(lv); + + t = dot(vn, lv); + t = 0.5*t + 0.5; + + t = visifac*spec*pow(t, hard); +} + +void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) +{ + vec3 h = normalize(l + v); + float rslt = max(dot(h, n), 0.0); + + specfac = pow(rslt, hard); +} + +void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) +{ + vec3 h = normalize(v + l); + float nh = dot(n, h); + + if(nh < 0.0) { + specfac = 0.0; + } + else { + float nv = max(dot(n, v), 0.0); + float i = pow(nh, hard); + + i = i/(0.1+nv); + specfac = i; + } +} + +void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac) +{ + if(refrac < 1.0) { + specfac = 0.0; + } + else if(spec_power == 0.0) { + specfac = 0.0; + } + else { + if(spec_power<100.0) + spec_power= sqrt(1.0/spec_power); + else + spec_power= 10.0/spec_power; + + vec3 h = normalize(v + l); + float nh = dot(n, h); + if(nh < 0.0) { + specfac = 0.0; + } + else { + float nv = max(dot(n, v), 0.01); + float nl = dot(n, l); + if(nl <= 0.01) { + specfac = 0.0; + } + else { + float vh = max(dot(v, h), 0.01); + + float a = 1.0; + float b = (2.0*nh*nv)/vh; + float c = (2.0*nh*nl)/vh; + + float g = 0.0; + + if(a < b && a < c) g = a; + else if(b < a && b < c) g = b; + else if(c < a && c < b) g = c; + + float p = sqrt(((refrac * refrac)+(vh*vh)-1.0)); + float f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1.0+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0)))); + float ang = acos(nh); + + specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0); + } + } + } +} + +void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac) +{ + vec3 h = normalize(l + v); + float nh = max(dot(n, h), 0.001); + float nv = max(dot(n, v), 0.001); + float nl = max(dot(n, l), 0.001); + float angle = tan(acos(nh)); + float alpha = max(rms, 0.001); + + specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp_blender(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl))); +} + +void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac) +{ + vec3 h = normalize(l + v); + float rslt = dot(h, n); + float ang = acos(rslt); + + if(ang < size) rslt = 1.0; + else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0; + else rslt = 1.0 - ((ang - size)/tsmooth); + + specfac = rslt; +} + +void shade_spec_area_inp(float specfac, float inp, out float outspecfac) +{ + outspecfac = specfac*inp; +} + +void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t) +{ + t = shadfac*spec*visifac*specfac; +} + +void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol) +{ + outcol = t*lampcol*speccol; +} + +void shade_add(vec4 col1, vec4 col2, out vec4 outcol) +{ + outcol = col1 + col2; +} + +void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) +{ + outcol = col + col1*col2; +} + +void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol) +{ + outcol = col + f*col1; +} + +void shade_mul(vec4 col1, vec4 col2, out vec4 outcol) +{ + outcol = col1*col2; +} + +void shade_mul_value(float fac, vec4 col, out vec4 outcol) +{ + outcol = col*fac; +} + +void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) +{ + outcol = vec4(col.rgb*obcol.rgb, col.a); +} + +void ramp_rgbtobw(vec3 color, out float outval) +{ + outval = color.r*0.3 + color.g*0.58 + color.b*0.12; +} + +void shade_only_shadow(float i, float shadfac, float energy, out float outshadfac) +{ + outshadfac = i*energy*(1.0 - shadfac); +} + +void shade_only_shadow_diffuse(float shadfac, vec3 rgb, vec4 diff, out vec4 outdiff) +{ + outdiff = diff - vec4(rgb*shadfac, 0.0); +} + +void shade_only_shadow_specular(float shadfac, vec3 specrgb, vec4 spec, out vec4 outspec) +{ + outspec = spec - vec4(specrgb*shadfac, 0.0); +} + +void test_shadowbuf(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp, out float result) +{ + if(inp <= 0.0) { + result = 0.0; + } + else { + vec4 co = shadowpersmat*vec4(rco, 1.0); + + //float bias = (1.5 - inp*inp)*shadowbias; + co.z -= shadowbias*co.w; + + result = shadow2DProj(shadowmap, co).x; + } +} + +void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol) +{ + outcol = linfac*(1.0 - exp(col*logfac)); +} + +void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac) +{ + float fac, zcor; + + zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; + + fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0); + if(misttype == 0.0) fac *= fac; + else if(misttype == 1.0); + else fac = sqrt(fac); + + outfac = 1.0 - (1.0-fac)*(1.0-misi); +} + +void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol) +{ + float fac = clamp(col.a, 0.0, 1.0); + outcol = vec4(mix(hor, col.rgb, fac), col.a); +} + +void shade_alpha_opaque(vec4 col, out vec4 outcol) +{ + outcol = vec4(col.rgb, 1.0); +} + +void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) +{ + outcol = vec4(col.rgb, col.a*obcol.a); +} + diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl.c b/source/blender/gpu/intern/gpu_shader_material.glsl.c new file mode 100644 index 00000000000..8287efe84ea --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_material.glsl.c @@ -0,0 +1,1032 @@ +/* DataToC output of file */ + +int datatoc_gpu_shader_material_glsl_size= 32828; +char datatoc_gpu_shader_material_glsl[]= { + 10,102,108,111, 97,116, 32,101,120,112, 95, 98,108,101,110,100,101,114, 40,102,108,111, 97,116, 32,102, 41, 10, +123, 10, 9,114,101,116,117,114,110, 32,112,111,119, 40, 50, 46, 55, 49, 56, 50, 56, 49, 56, 50, 56, 52, 54, 44, 32,102, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,114,103, 98, 95,116,111, 95,104,115,118, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117, +116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, 99,109, 97,120, 44, 32, 99,109, +105,110, 44, 32,104, 44, 32,115, 44, 32,118, 44, 32, 99,100,101,108,116, 97, 59, 10, 9,118,101, 99, 51, 32, 99, 59, 10, 10, 9, + 99,109, 97,120, 32, 61, 32,109, 97,120, 40,114,103, 98, 91, 48, 93, 44, 32,109, 97,120, 40,114,103, 98, 91, 49, 93, 44, 32,114, +103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,109,105,110, 32, 61, 32,109,105,110, 40,114,103, 98, 91, 48, 93, 44, 32,109,105,110, + 40,114,103, 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,100,101,108,116, 97, 32, 61, 32, 99,109, 97, +120, 45, 99,109,105,110, 59, 10, 10, 9,118, 32, 61, 32, 99,109, 97,120, 59, 10, 9,105,102, 32, 40, 99,109, 97,120, 33, 61, 48, + 46, 48, 41, 10, 9, 9,115, 32, 61, 32, 99,100,101,108,116, 97, 47, 99,109, 97,120, 59, 10, 9,101,108,115,101, 32,123, 10, 9, + 9,115, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 10, 9,105,102, 32, 40,115, 32, + 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, + 9, 9, 99, 32, 61, 32, 40,118,101, 99, 51, 40, 99,109, 97,120, 44, 32, 99,109, 97,120, 44, 32, 99,109, 97,120, 41, 32, 45, 32, +114,103, 98, 46,120,121,122, 41, 47, 99,100,101,108,116, 97, 59, 10, 10, 9, 9,105,102, 32, 40,114,103, 98, 46,120, 61, 61, 99, +109, 97,120, 41, 32,104, 32, 61, 32, 99, 91, 50, 93, 32, 45, 32, 99, 91, 49, 93, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, + 40,114,103, 98, 46,121, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 50, 46, 48, 32, 43, 32, 99, 91, 48, 93, 32, 45, 32, 32, + 99, 91, 50, 93, 59, 10, 9, 9,101,108,115,101, 32,104, 32, 61, 32, 52, 46, 48, 32, 43, 32, 99, 91, 49, 93, 32, 45, 32, 99, 91, + 48, 93, 59, 10, 10, 9, 9,104, 32, 47, 61, 32, 54, 46, 48, 59, 10, 10, 9, 9,105,102, 32, 40,104, 60, 48, 46, 48, 41, 10, 9, + 9, 9,104, 32, 43, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,104, + 44, 32,115, 44, 32,118, 44, 32,114,103, 98, 46,119, 41, 59, 10,125, 10, 10,118,111,105,100, 32,104,115,118, 95,116,111, 95,114, +103, 98, 40,118,101, 99, 52, 32,104,115,118, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, + 9,102,108,111, 97,116, 32,105, 44, 32,102, 44, 32,112, 44, 32,113, 44, 32,116, 44, 32,104, 44, 32,115, 44, 32,118, 59, 10, 9, +118,101, 99, 51, 32,114,103, 98, 59, 10, 10, 9,104, 32, 61, 32,104,115,118, 91, 48, 93, 59, 10, 9,115, 32, 61, 32,104,115,118, + 91, 49, 93, 59, 10, 9,118, 32, 61, 32,104,115,118, 91, 50, 93, 59, 10, 10, 9,105,102, 40,115, 61, 61, 48, 46, 48, 41, 32,123, + 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,118, 44, 32,118, 41, 59, 10, 9,125, 10, 9,101,108,115,101, + 32,123, 10, 9, 9,105,102, 40,104, 61, 61, 49, 46, 48, 41, 10, 9, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9, 10, 9, + 9,104, 32, 42, 61, 32, 54, 46, 48, 59, 10, 9, 9,105, 32, 61, 32,102,108,111,111,114, 40,104, 41, 59, 10, 9, 9,102, 32, 61, + 32,104, 32, 45, 32,105, 59, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,102, 44, 32,102, 44, 32,102, 41, 59, 10, 9, + 9,112, 32, 61, 32,118, 42, 40, 49, 46, 48, 45,115, 41, 59, 10, 9, 9,113, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, +102, 41, 41, 59, 10, 9, 9,116, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, 40, 49, 46, 48, 45,102, 41, 41, 41, 59, 10, + 9, 9, 10, 9, 9,105,102, 32, 40,105, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, + 32,116, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 49, 46, 48, 41, 32,114,103, 98, + 32, 61, 32,118,101, 99, 51, 40,113, 44, 32,118, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, + 61, 32, 50, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,118, 44, 32,116, 41, 59, 10, 9, 9,101,108, +115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 51, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,113, + 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 52, 46, 48, 41, 32,114,103, 98, 32, 61, + 32,118,101, 99, 51, 40,116, 44, 32,112, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,114,103, 98, 32, 61, 32,118,101, 99, + 51, 40,118, 44, 32,112, 44, 32,113, 41, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,114, +103, 98, 44, 32,104,115,118, 46,119, 41, 59, 10,125, 10, 10, 35,100,101,102,105,110,101, 32, 77, 95, 80, 73, 32, 51, 46, 49, 52, + 49, 53, 57, 50, 54, 53, 51, 53, 56, 57, 55, 57, 51, 50, 51, 56, 52, 54, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, 68, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10, +118,111,105,100, 32,118, 99,111,108, 95, 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 41, 10,123, 10, 9,118, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, + 97,116,116,118, 99,111,108, 46,120, 47, 50, 53, 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46,121, 47, 50, 53, 53, 46, 48, + 44, 32, 97,116,116,118, 99,111,108, 46,122, 47, 50, 53, 53, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,117,118, 95, 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, + 99, 51, 32,117,118, 41, 10,123, 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32, +118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,103,101, +111,109, 40,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,109, 97,116, 52, 32,118,105,101,119,105, +110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 97,116,116,111,114, 99,111, 44, 32,118,101, 99, 50, 32, 97,116,116,117,118, 44, + 32,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 44, 32, +111,117,116, 32,118,101, 99, 51, 32,108,111, 99, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,114, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,102,114,111,110,116, 98, 97, 99,107, 41, 10,123, 10, 9,108,111, 99, 97,108, 32, 61, 32, 99,111, 59, 10, 9, +118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,111, 99, 97,108, 41, 59, 10, 9,103,108,111, 98, 97,108, + 32, 61, 32, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40,108,111, 99, 97,108, 44, 32, 49, 46, 48, 41, 41, + 46,120,121,122, 59, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99,111, 59, 10, 9,117,118, 95, 97,116,116,114,105, + 98,117,116,101, 40, 97,116,116,117,118, 44, 32,117,118, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32, 45,110,111,114,109, + 97,108,105,122,101, 40,110,111,114, 41, 59, 9, 47, 42, 32, 98,108,101,110,100,101,114, 32,114,101,110,100,101,114, 32,110,111, +114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,118, 99,111,108, 95, 97,116,116,114,105, 98,117, +116,101, 40, 97,116,116,118, 99,111,108, 44, 32,118, 99,111,108, 41, 59, 10, 9,102,114,111,110,116, 98, 97, 99,107, 32, 61, 32, + 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,109, + 97,116, 52, 32,109, 97,116, 44, 32,118,101, 99, 51, 32,109,105,110,118,101, 99, 44, 32,118,101, 99, 51, 32,109, 97,120,118,101, + 99, 44, 32,102,108,111, 97,116, 32,100,111,109,105,110, 44, 32,102,108,111, 97,116, 32,100,111,109, 97,120, 44, 32,111,117,116, + 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 40,109, 97,116, 32, 42, + 32,118,101, 99, 52, 40,118,101, 99, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,105,102, 40,100,111,109,105,110, 32, + 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32,109, 97,120, 40,111,117,116,118,101, 99, 44, 32,109, +105,110,118,101, 99, 41, 59, 10, 9,105,102, 40,100,111,109, 97,120, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118, +101, 99, 32, 61, 32,109,105,110, 40,111,117,116,118,101, 99, 44, 32,109, 97,120,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105, +100, 32, 99, 97,109,101,114, 97, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,105, +101,119, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,101,112,116,104, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,100,105,115,116, 41, 10,123, 10, 9,111,117,116,100,101,112,116,104, 32, 61, 32, 97, 98,115, 40, 99,111, 46, +122, 41, 59, 10, 9,111,117,116,100,105,115,116, 32, 61, 32,108,101,110,103,116,104, 40, 99,111, 41, 59, 10, 9,111,117,116,118, +105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116, +104, 95, 97,100,100, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, + 32, 43, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,115,117, 98,116,114, 97, 99,116, 40,102, +108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, + 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 45, 32,118, 97,108, 50, + 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,117,108,116,105,112,108,121, 40,102,108,111, 97,116, 32,118, 97, +108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 42, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111, +105,100, 32,109, 97,116,104, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, + 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40, +118, 97,108, 50, 32, 61, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, +115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 47, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111, +105,100, 32,109, 97,116,104, 95,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,115,105,110, 40,118, 97,108, 41, 59, 10, +125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 99,111,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,115, + 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,116, 97,110,103,101,110,116, 40,102,108,111, 97, +116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, + 97,108, 32, 61, 32,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,115,105,110, + 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, + 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, + 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97,115,105,110, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117, +116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97, 99,111,115, 40,102,108, +111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, + 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, 9, 9,111, +117,116,118, 97,108, 32, 61, 32, 97, 99,111,115, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97, +108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,116, 97,110, 40,102,108,111, 97,116, + 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97, +108, 32, 61, 32, 97,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,112,111,119, 40, +102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40,118, 97,108, 49, 32, 62, 61, 32, 48, 46, 48, 41, 10, 9, 9, +111,117,116,118, 97,108, 32, 61, 32,112,111,119, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, + 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,111,103, + 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32, 48, 46, 48, 32, 32, 38, 38, 32, +118, 97,108, 50, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 61, 32,108,111,103, 50, 40,118, 97,108, 49, 41, + 32, 47, 32,108,111,103, 50, 40,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 61, 32, 48, + 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109, 97,120, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, + 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,109, 97,116,104, 95,109,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, + 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, + 32, 61, 32,109,105,110, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, + 95,114,111,117,110,100, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, + 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 61, 32,102,108,111,111,114, 40,118, 97,108, 32, 43, 32, 48, 46, 53, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,101,115,115, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97, +108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 60, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, + 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111, +105,100, 32,109, 97,116,104, 95,103,114,101, 97,116,101,114, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, + 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, + 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32, +115,113,117,101,101,122,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,102,108,111, 97,116, 32,119,105,100,116,104, 44, 32, +102,108,111, 97,116, 32, 99,101,110,116,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, +123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, 47, 40, 49, 46, 48, 32, 43, 32,112,111,119, 40, 50, 46, 55, 49, 56, + 50, 56, 49, 56, 51, 44, 32, 45, 40, 40,118, 97,108, 45, 99,101,110,116,101,114, 41, 42,119,105,100,116,104, 41, 41, 41, 59, 10, +125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,100,100, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, + 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, 32,118, 50, 59, 10, 9, +111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98,115, 40,111, +117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, 46, 48, 59, + 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,115,117, 98, 40,118,101, 99, 51, 32,118, 49, 44, 32,118, +101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 45, 32,118, 50, 59, 10, + 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98,115, 40, +111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, 46, 48, + 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,118,101,114, 97,103,101, 40,118,101, 99, 51, 32, +118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, + 32,118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10, 9, +111,117,116,118,101, 99, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,100,111,116, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, + 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117, +116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 44, 32, 48, 44, 32, 48, 41, 59, + 10, 9,111,117,116,118, 97,108, 32, 61, 32,100,111,116, 40,118, 49, 44, 32,118, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +118,101, 99, 95,109, 97,116,104, 95, 99,114,111,115,115, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, + 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, + 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 99,114,111,115,115, 40,118, 49, 44, 32,118, 50, 41, 59, 10, 9, +111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,118,101, 99, 95,109, 97,116,104, 95,110,111,114,109, 97,108,105,122,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32, +118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,118, 41, 59, 10, 9,111,117,116,118,101, 99, 32, 61, 32, +110,111,114,109, 97,108,105,122,101, 40,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,110, +101,103, 97,116,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118, 41, 10,123, 10, 9, +111,117,116,118, 32, 61, 32, 45,118, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,100, +105,114, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32,111,117,116,100,111,116, 41, 10,123, 10, 9,111,117,116,110,111,114, 32, 61, 32,100,105,114, + 59, 10, 9,111,117,116,100,111,116, 32, 61, 32, 45,100,111,116, 40,100,105,114, 44, 32,110,111,114, 41, 59, 10,125, 10, 10,118, +111,105,100, 32, 99,117,114,118,101,115, 95,118,101, 99, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, + 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, + 9,111,117,116,118,101, 99, 46,120, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, + 40,118,101, 99, 46,120, 32, 43, 32, 49, 46, 48, 41, 42, 48, 46, 53, 41, 46,120, 59, 10, 9,111,117,116,118,101, 99, 46,121, 32, + 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 40,118,101, 99, 46,121, 32, 43, 32, 49, + 46, 48, 41, 42, 48, 46, 53, 41, 46,121, 59, 10, 9,111,117,116,118,101, 99, 46,122, 32, 61, 32,116,101,120,116,117,114,101, 49, + 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 40,118,101, 99, 46,122, 32, 43, 32, 49, 46, 48, 41, 42, 48, 46, 53, 41, 46,122, + 59, 10,125, 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,115, + 97,109,112,108,101,114, 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118, +101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46,114, 41, + 46, 97, 41, 46,114, 59, 10, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114, +118,101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46,103, + 41, 46, 97, 41, 46,103, 59, 10, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117, +114,118,101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46, + 98, 41, 46, 97, 41, 46, 98, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118, +111,105,100, 32,115,101,116, 95,118, 97,108,117,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 59, 10,125, 10, 10,118, +111,105,100, 32,115,101,116, 95,114,103, 98, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111, +117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32, +115,101,116, 95,114,103, 98, 97, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, + 95,118, 97,108,117,101, 95,122,101,114,111, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, + 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, + 95,111,110,101, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, + 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 95,122,101,114,111, 40,111,117,116, + 32,118,101, 99, 51, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, + 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 97, 95,122,101,114,111, 40,111,117,116, 32,118, +101, 99, 52, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 52, 40, 48, 46, 48, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, +118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, +117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, + 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 50, 44, 32, +102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105, +100, 32,109,105,120, 95, 97,100,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32, +118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, + 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99, +111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, + 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105, +120, 95,109,117,108,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, + 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, + 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, + 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 42, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9, +111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, + 99,114,101,101,110, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, + 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, + 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, + 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, + 49, 46, 48, 41, 32, 45, 32, 40,118,101, 99, 52, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99, 42, 40,118,101, 99, 52, 40, 49, + 46, 48, 41, 32, 45, 32, 99,111,108, 50, 41, 41, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 49, 41, 59, + 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, + 95,111,118,101,114,108, 97,121, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, +101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, + 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, +108, 49, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111, +108, 46,114, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,101, +108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, + 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117, +116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9, +111,117,116, 99,111,108, 46,103, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46, +103, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99, +109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,103, 41, 41, 42, 40, 49, 46, 48, + 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, + 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, + 99,111,108, 50, 46, 98, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, + 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46, 98, 41, 41, + 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, +117, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111, +108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, + 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105, +120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 45, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99, +111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,118, 40,102, +108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, +102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, + 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99, +111,108, 50, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,114, 32, 61, 32,102, 97, 99,109, 42,111,117, +116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,114, 47, 99,111,108, 50, 46,114, 59, 10, 9,105, +102, 40, 99,111,108, 50, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, + 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,103, 47, 99,111,108, 50, 46,103, 59, + 10, 9,105,102, 40, 99,111,108, 50, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46, 98, 32, 61, 32,102, + 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46, 98, 47, 99,111,108, 50, + 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,102,102, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, +118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, +117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, + 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 97, 98,115, 40, 99,111, +108, 49, 32, 45, 32, 99,111,108, 50, 41, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111, +108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,102, 97, 99, + 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, + 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109,105,110, 40, 99,111,108, 49, 46,114, +103, 98, 44, 32, 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99, +111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,108,105,103,104,116, 40,102,108,111, 97,116, 32,102, + 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, + 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109, 97,120, 40, 99,111,108, 49, + 46,114,103, 98, 44, 32, 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, + 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,111,100,103,101, 40,102,108,111, 97,116, + 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32, +118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, + 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, + 40,111,117,116, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, + 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, + 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105, +102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46,114, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, + 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111, +108, 46,114, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, + 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, + 50, 46,103, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, +103, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, + 46,103, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, + 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9, +105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109, +112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, + 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, + 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, + 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, + 99,111,108, 46, 98, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,117,114,110, + 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109, +112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,116,109,112, 44, 32,102, 97, + 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, + 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40, +116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9,101, +108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99, +111,108, 46,114, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, + 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111, +108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,109, +112, 59, 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,105, +102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, 10, + 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117, +116, 99,111,108, 46,103, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, + 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, + 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, +116,109,112, 59, 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, + 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, 48, + 59, 10, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32, +111,117,116, 99,111,108, 46, 98, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, + 98, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111, +117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, + 61, 32,116,109,112, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,104,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, + 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, + 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, + 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115, +118, 50, 44, 32,116,109,112, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, + 59, 10, 10, 9,105,102, 40,104,115,118, 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, + 95,104,115,118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, + 50, 46,120, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, 10, 9, + 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, 41, 59, + 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, + 32,109,105,120, 95,115, 97,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, +101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, + 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, +108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115, +118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 46,121, 32, 33, 61, 32, 48, 46, + 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, + 9, 9,104,115,118, 46,121, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,121, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46, +121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 9,125, + 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,118, 97,108, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, + 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, + 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, + 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 49, 44, 32,104, +115,118, 41, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9, +104,115,118, 46,122, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,122, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,122, 59, + 10, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111, +105,100, 32,109,105,120, 95, 99,111,108,111,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, + 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, + 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102, +108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, + 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109,112, 59, 10, 9, +114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, 40,104,115,118, + 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99,111, +108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, 9,104,115,118, + 46,121, 32, 61, 32,104,115,118, 50, 46,121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116, +109,112, 41, 59, 32, 10, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109, +112, 44, 32,102, 97, 99, 41, 59, 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, + 10,125, 10, 10,118,111,105,100, 32,118, 97,108,116,111,114,103, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,115, 97,109, +112,108,101,114, 49, 68, 32, 99,111,108,111,114,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, 97,108,112,104, 97, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, + 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,111,108,111,114,109, 97,112, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, + 97,108,112,104, 97, 32, 61, 32,111,117,116, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98,116,111, 98, +119, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, +123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 53, 32, 43, 32, 99,111,108,111,114, + 46,103, 42, 48, 46, 52, 53, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 50, 59, 10,125, 10, 10,118,111,105,100, 32,105, +110,118,101,114,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118, +101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,120,121,122, 32, 61, 32,109,105,120, 40, + 99,111,108, 46,120,121,122, 44, 32,118,101, 99, 51, 40, 49, 46, 48, 44, 32, 49, 46, 48, 44, 32, 49, 46, 48, 41, 32, 45, 32, 99, +111,108, 46,120,121,122, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46,119, 32, 61, 32, 99,111,108, 46,119, 59, + 10,125, 10, 10,118,111,105,100, 32,104,117,101, 95,115, 97,116, 40,102,108,111, 97,116, 32,104,117,101, 44, 32,102,108,111, 97, +116, 32,115, 97,116, 44, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118, +101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,118,101, 99, + 52, 32,104,115,118, 59, 10, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, + 9,104,115,118, 91, 48, 93, 32, 43, 61, 32, 40,104,117,101, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,105,102, 40,104,115,118, 91, + 48, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 48, 93, 45, 61, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, + 91, 48, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 48, 93, 43, 61, 32, 49, 46, 48, 59, 10, 9,104,115,118, 91, 49, 93, 32, 42, + 61, 32,115, 97,116, 59, 10, 9,105,102, 40,104,115,118, 91, 49, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 49, + 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 49, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, + 48, 46, 48, 59, 10, 9,104,115,118, 91, 50, 93, 32, 42, 61, 32,118, 97,108,117,101, 59, 10, 9,105,102, 40,104,115,118, 91, 50, + 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 50, 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, + 50, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 50, 93, 61, 32, 48, 46, 48, 59, 10, 10, 9,104,115,118, 95,116,111, 95,114,103, + 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99, +111,108, 44, 32,111,117,116, 99,111,108, 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,112, 97,114, 97, +116,101, 95,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, 98, 41, 10,123, 10, 9,114, 32, 61, 32, 99, +111,108, 46,114, 59, 10, 9,103, 32, 61, 32, 99,111,108, 46,103, 59, 10, 9, 98, 32, 61, 32, 99,111,108, 46, 98, 59, 10,125, 10, + 10,118,111,105,100, 32, 99,111,109, 98,105,110,101, 95,114,103, 98, 40,102,108,111, 97,116, 32,114, 44, 32,102,108,111, 97,116, + 32,103, 44, 32,102,108,111, 97,116, 32, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 41, 10,123, 10, 9, 99,111, +108, 32, 61, 32,118,101, 99, 52, 40,114, 44, 32,103, 44, 32, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +111,117,116,112,117,116, 95,110,111,100,101, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, + 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32, +118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 32, 84, 69, 88, 84, 85, 82, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, + 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,102,108,105,112, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,118,101, + 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, +118,101, 99, 46,121,120,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,108, +105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 59, 10,125, 10, 10,118, +111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,113,117, 97,100, 40,118,101, 99, 51, 32,118,101, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, + 97,120, 40, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10, 9,111,117,116,118, 97, +108, 32, 42, 61, 32,111,117,116,118, 97,108, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,119,111,111, +100, 95,115,105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, + 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, + 41, 10,123, 10, 9,102,108,111, 97,116, 32, 97, 32, 61, 32,115,113,114,116, 40,118,101, 99, 46,120, 42,118,101, 99, 46,120, 32, + 43, 32,118,101, 99, 46,121, 42,118,101, 99, 46,121, 32, 43, 32,118,101, 99, 46,122, 42,118,101, 99, 46,122, 41, 42, 50, 48, 46, + 48, 59, 10, 9,102,108,111, 97,116, 32,119,105, 32, 61, 32, 48, 46, 53, 32, 43, 32, 48, 46, 53, 42,115,105,110, 40, 97, 41, 59, + 10, 10, 9,118, 97,108,117,101, 32, 61, 32,119,105, 59, 10, 9, 99,111,108,111,114, 32, 61, 32,118,101, 99, 52, 40,119,105, 44, + 32,119,105, 44, 32,119,105, 44, 32, 49, 46, 48, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, + 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,105,109, + 97,103,101, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114, +101, 50, 68, 40,105,109, 97, 44, 32, 40,118,101, 99, 46,120,121, 32, 43, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, + 41, 41, 42, 48, 46, 53, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 10, 9,110,111,114,109, 97,108, 46, +120, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108,111,114, 46,114, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,110,111,114,109, 97,108, + 46,121, 32, 61, 32, 50, 46, 48, 42, 40, 48, 46, 53, 32, 45, 32, 99,111,108,111,114, 46,103, 41, 59, 10, 9,110,111,114,109, 97, +108, 46,122, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108,111,114, 46, 98, 32, 45, 32, 48, 46, 53, 41, 59, 10,125, 10, 10, 47, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 77, 84, 69, 88, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 47, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,111,114, 99,111, 40,118,101, 99, 51, 32, 97,116,116,111,114, + 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,114, 99,111, 41, 10,123, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116, +111,114, 99,111, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,117,118, 40,118,101, 99, 50, 32, 97,116,116,117, +118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 41, 10,123, 10, 9, 47, 42, 32,100,105,115, 97, 98,108,101,100, 32,102, +111,114, 32,110,111,119, 44, 32,119,111,114,107,115, 32,116,111,103,101,116,104,101,114, 32,119,105,116,104, 32,108,101, 97,118, +105,110,103, 32,111,117,116, 32,109,116,101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 10, 9, 32, 32, 32,117,118, 32, 61, + 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, + 44, 32, 48, 46, 48, 41, 59, 32, 42, 47, 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 44, 32, 48, 46, 48, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97, +108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 99,111,114, +114,101,115,112,111,110,100,115, 32,116,111, 32,115,104,105, 45, 62,111,114,110, 44, 32,119,104,105, 99,104, 32,105,115, 32,110, +101,103, 97,116,101,100, 32,115,111, 32, 99, 97,110, 99,101,108,115, 10, 9, 32, 32, 32,111,117,116, 32, 98,108,101,110,100,101, +114, 32,110,111,114,109, 97,108, 32,110,101,103, 97,116,105,111,110, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97,108, 32, + 61, 32,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, + 99,111, 95,116, 97,110,103,101,110,116, 40,118,101, 99, 51, 32,116, 97,110,103,101,110,116, 44, 32,111,117,116, 32,118,101, 99, + 51, 32,111,117,116,116, 97,110,103,101,110,116, 41, 10,123, 10, 9,111,117,116,116, 97,110,103,101,110,116, 32, 61, 32,110,111, +114,109, 97,108,105,122,101, 40,116, 97,110,103,101,110,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95, +103,108,111, 98, 97,108, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, + 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 41, 10,123, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118, +105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10,125, 10, + 10,118,111,105,100, 32,116,101,120, 99,111, 95,111, 98,106,101, 99,116, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, + 97,116, 44, 32,109, 97,116, 52, 32,111, 98,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32, +118,101, 99, 51, 32,111, 98,106,101, 99,116, 41, 10,123, 10, 9,111, 98,106,101, 99,116, 32, 61, 32, 40,111, 98,105,110,118,109, + 97,116, 42, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 41, 46,120, +121,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,114,101,102,108, 40,118,101, 99, 51, 32,118,110, 44, 32, +118,101, 99, 51, 32,118,105,101,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102, 41, 10,123, 10, 9,114,101,102, 32, + 61, 32,118,105,101,119, 32, 45, 32, 50, 46, 48, 42,100,111,116, 40,118,110, 44, 32,118,105,101,119, 41, 42,118,110, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 98,108,101,110,100,101,114, + 32,114,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,111,117, +116,110,111,114,109, 97,108, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, + 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, + 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, +102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, + 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32, +102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,109,117, +108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99, +111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99, +103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32, 40, +102, 97, 99,109, 32, 43, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115, 99,114,101,101,110, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, + 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32, +102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, + 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, + 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32, 40,118,101, + 99, 51, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99,116, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,116,101,120, + 99,111,108, 41, 41, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,111,118,101,114,108, 97,121, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, + 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, +102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, + 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105, +110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, + 99,116, 42,116,101,120, 99,111,108, 46,114, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,114, 32, 61, 32, + 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101, +120, 99,111,108, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40, +111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99, +111,108, 46,103, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 41, 59, + 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, + 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,103, 41, 41, 42, 40, 49, 46, 48, + 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, + 53, 41, 10, 9, 9,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 42, 40,102, 97, 99,109, 32, 43, 32, + 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111, +108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, + 48, 32, 45, 32,116,101,120, 99,111,108, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115,117, 98, 40,118,101, 99, 51, 32,111,117,116, 99,111, +108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, + 32, 61, 32, 45,102, 97, 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, + 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 97,100,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, + 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32, +102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,100,105,118, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, + 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, + 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, + 99,116, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46, +114, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46, +114, 47,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, + 32,105,110, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99,116, 42, +111,117,116, 99,111,108, 46,103, 47,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46, 98, 32, + 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, + 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46, 98, 47,116,101,120, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105, +100, 32,109,116,101,120, 95,114,103, 98, 95,100,105,102,102, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, + 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, + 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99, +116, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, + 97, 98,115, 40,116,101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, +101,120, 95,114,103, 98, 95,100, 97,114,107, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, +120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, + 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, + 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99, +111,108, 32, 60, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108, +115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, + 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46,103, 41, + 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111, +117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9, +105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, + 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111, +105,100, 32,109,116,101,120, 95,114,103, 98, 95,108,105,103,104,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118, +101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, + 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, +109, 44, 32, 99,111,108, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, + 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, + 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99, +111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111, +108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, + 99,111,108, 46,103, 41, 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, + 46,103, 32, 61, 32,111,117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111, +108, 46, 98, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, + 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,104,117,101, 40,118,101, 99, 51, 32,111,117,116, 99,111, +108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, + 99,111,108, 59, 10, 10, 9,109,105,120, 95,104,117,101, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111, +117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, + 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115, 97,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, + 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, + 10, 9,109,105,120, 95,115, 97,116, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, + 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, + 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109, +116,101,120, 95,114,103, 98, 95,118, 97,108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, +120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, + 95,118, 97,108, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, + 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99, +111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, +103, 98, 95, 99,111,108,111,114, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111, +108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95, 99,111, +108,111,114, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, + 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111, +108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97, +108,117,101, 95,118, 97,114,115, 40,105,110,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32,102,108,111, 97,116, 32,102,108,105, +112, 41, 10,123, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45, +102, 97, 99,116, 59, 10, 10, 9,105,102, 40,102,108,105,112, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97, +116, 32,116,109,112, 32, 61, 32,102, 97, 99,116, 59, 10, 9, 9,102, 97, 99,116, 32, 61, 32,102, 97, 99,109, 59, 10, 9, 9,102, + 97, 99,109, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, + 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111, +108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, + 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, + 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42, +116,101,120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, +101,120, 95,118, 97,108,117,101, 95,109,117,108, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, + 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, + 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, + 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, + 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, + 49, 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, 99, +116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, + 97,108,117,101, 95,115, 99,114,101,101,110, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32, +116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, +102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9, +102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99, +116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, + 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, + 43, 32,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117, +116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,117, 98, 40,102,108, +111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32, +102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109, +116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, + 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32, 45,102, 97, 99,116, 59, 10, 9,105,110, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109, +116,101,120, 95,118, 97,108,117,101, 95, 97,100,100, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97, +116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, + 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, + 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, + 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, + 32,102, 97, 99,116, 59, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117, +116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,118, 40,102,108,111, + 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, + 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116, +101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32, +102,108,105,112, 41, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, 9,105,110, 99, +111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 47,116, +101,120, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,102,102, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, + 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, + 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95, +118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9, +105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116, +101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97, +108,117,101, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, + 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, + 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, + 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32, +102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 41, 32, +105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, + 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,108,105,103,104,116, 40,102,108,111, 97,116, + 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, + 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108, +105,112, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, + 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 41, 32,105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101, +108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 95,112,111,115,105,116,105,118,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32,109, + 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, + 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, + 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, + 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, 97,114, 95,100,105,118,105,100,101, 40,102,108, +111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,111,117, +116,104, 97,114, 32, 61, 32,104, 97,114, 47, 49, 50, 56, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, + 97,114, 95,109,117,108,116,105,112,108,121, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,104, 97,114, 32, 42, 61, 32, 49, 50, 56, 46, 48, 59, 10, + 10, 9,105,102, 40,104, 97,114, 32, 60, 32, 49, 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101, +108,115,101, 32,105,102, 40,104, 97,114, 32, 62, 32, 53, 49, 49, 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 53, 49, 49, + 46, 48, 59, 10, 9,101,108,115,101, 32,111,117,116,104, 97,114, 32, 61, 32,104, 97,114, 59, 10,125, 10, 10,118,111,105,100, 32, +109,116,101,120, 95, 97,108,112,104, 97, 95,102,114,111,109, 95, 99,111,108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 41, 10,123, 10, 9, 97,108,112,104, 97, 32, 61, 32, 99,111,108, 46, 97, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108,112,104, 97, 95,116,111, 95, 99,111,108, 40,118,101, 99, 52, 32, + 99,111,108, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 97,108,112, +104, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98,116,111,105,110,116, 40,118,101, 99, 52, 32, +114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,105,110,116, +101,110,115,105,116,121, 32, 61, 32,100,111,116, 40,118,101, 99, 51, 40, 48, 46, 51, 53, 44, 32, 48, 46, 52, 53, 44, 32, 48, 46, + 50, 41, 44, 32,114,103, 98, 46,114,103, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, + 95,105,110,118,101,114,116, 40,102,108,111, 97,116, 32,105,110,118, 97,108,117,101, 44, 32,111,117,116, 32,102,108,111, 97,116, + 32,111,117,116,118, 97,108,117,101, 41, 10,123, 10, 9,111,117,116,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 32, 45, 32,105, +110,118, 97,108,117,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,105,110,118,101,114,116, 40, +118,101, 99, 52, 32,105,110,114,103, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9, +111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,105,110,114,103, 98, 46, +114,103, 98, 44, 32,105,110,114,103, 98, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117, +101, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116,101,110, 99,105,108, 44, 32,102,108,111, 97,116, 32,105, +110,116,101,110,115,105,116,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,116, 32, 61, 32,105,110,116,101,110,115,105,116,121, 59, 10, 9,111,117,116,105,110,116,101,110,115,105,116,121, + 32, 61, 32,105,110,116,101,110,115,105,116,121, 42,115,116,101,110, 99,105,108, 59, 10, 9,111,117,116,115,116,101,110, 99,105, +108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, +103, 98, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116,101,110, 99,105,108, 44, 32,118,101, 99, 52, 32,114, +103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,116, 32, 61, 32,114,103, 98, 46, 97, + 59, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, 44, 32,114,103, 98, 46, 97, 42, +115,116,101,110, 99,105,108, 41, 59, 10, 9,111,117,116,115,116,101,110, 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42, +102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97,112,112,105,110,103, 95,111,102,115, 40,118, +101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,111,102,115, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117, +116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, 32, 61, 32,116,101,120, 99,111, 32, 43, 32,111,102, +115, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97,112,112,105,110,103, 95,115,105,122,101, 40,118,101, 99, + 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,115,105,122,101, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, +116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, 32, 61, 32,115,105,122,101, 42,116,101,120, 99,111, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, + 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, +118,101, 99, 51, 40,118,101, 99, 46,120,121, 42, 48, 46, 53, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, + 44, 32,118,101, 99, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,105,109, 97,103,101, 40,118,101, 99, + 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32, +110,111,114,109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, + 44, 32,118,101, 99, 46,120,121, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 9, 10, 9,110,111,114,109, + 97,108, 32, 61, 32, 50, 46, 48, 42, 40,118,101, 99, 51, 40, 99,111,108,111,114, 46,114, 44, 32, 45, 99,111,108,111,114, 46,103, + 44, 32, 99,111,108,111,114, 46, 98, 41, 32, 45, 32,118,101, 99, 51, 40, 48, 46, 53, 44, 32, 45, 48, 46, 53, 44, 32, 48, 46, 53, + 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,110,101,103, 97,116,101, 95,116,101,120,110,111,114,109, 97, +108, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97, +108, 41, 10,123, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 45,110,111,114,109, 97,108, 46,120, + 44, 32, 45,110,111,114,109, 97,108, 46,121, 44, 32,110,111,114,109, 97,108, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +109,116,101,120, 95,110,115,112, 97, 99,101, 95,116, 97,110,103,101,110,116, 40,118,101, 99, 51, 32,116, 97,110,103,101,110,116, + 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,116,101,120,110,111,114,109, 97,108, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,116, 97,110,103,101,110,116, 32, 61, 32, +110,111,114,109, 97,108,105,122,101, 40,116, 97,110,103,101,110,116, 41, 59, 10, 9,118,101, 99, 51, 32, 66, 32, 61, 32, 99,114, +111,115,115, 40,110,111,114,109, 97,108, 44, 32,116, 97,110,103,101,110,116, 41, 59, 10, 10, 9,111,117,116,110,111,114,109, 97, +108, 32, 61, 32,116,101,120,110,111,114,109, 97,108, 46,120, 42,116, 97,110,103,101,110,116, 32, 43, 32,116,101,120,110,111,114, +109, 97,108, 46,121, 42, 66, 32, 43, 32,116,101,120,110,111,114,109, 97,108, 46,122, 42,110,111,114,109, 97,108, 59, 10, 9,111, +117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,108,101,110,100, 95,110,111,114,109, 97,108, 40,102,108,111, 97,116, + 32,110,111,114,102, 97, 99, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,110,101,119,110,111, +114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,111,117,116, +110,111,114,109, 97,108, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32,110,111,114,102, 97, 99, 41, 42,110,111,114,109, 97,108, 32, 43, + 32,110,111,114,102, 97, 99, 42,110,101,119,110,111,114,109, 97,108, 59, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32, +110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, + 42, 32, 77, 65, 84, 69, 82, 73, 65, 76, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,108, 97,109,112, + 95,118,105,115,105, 98,105,108,105,116,121, 95,115,117,110, 95,104,101,109,105, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, + 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32,108, 97,109,112,118, +101, 99, 59, 10, 9,100,105,115,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, + 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,111,116,104,101,114, 40,118, +101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105, +102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 9,100,105,115,116, 32, + 61, 32,108,101,110,103,116,104, 40,108,118, 41, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,118, + 41, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95, +102, 97,108,108,111,102,102, 95,105,110,118,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, + 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, + 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, + 32, 43, 32,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,105, +110,118,115,113,117, 97,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100, +105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, + 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,100,105,115,116, 42,100, +105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,115,108,105,100,101, +114,115, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,108,100, 49, 44, 32,102,108, +111, 97,116, 32,108,100, 50, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, +105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116,107,119, 32, 61, 32,108, 97, +109,112,100,105,115,116, 42,108, 97,109,112,100,105,115,116, 59, 10, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109, +112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,108,100, 49, 42,100,105,115,116, 41, 59, 10, 9,118,105, +115,105,102, 97, 99, 32, 42, 61, 32,108, 97,109,112,100,105,115,116,107,119, 47, 40,108, 97,109,112,100,105,115,116,107,119, 32, + 43, 32,108,100, 50, 42,100,105,115,116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, + 97,108,108,111,102,102, 95, 99,117,114,118,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,115, 97,109, +112,108,101,114, 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,116,101,120, +116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,100,105,115,116, 47,108, 97,109,112,100,105,115,116, 41, 46, +120, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,104,101,114, +101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,102,108, +111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, + 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 61, 32,108, 97,109,112,100,105,115,116, 32, 45, 32,100,105,115,116, 59, 10, + 10, 9,111,117,116,118,105,115,105,102, 97, 99, 61, 32,118,105,115,105,102, 97, 99, 42,109, 97,120, 40,116, 44, 32, 48, 46, 48, + 41, 47,108, 97,109,112,100,105,115,116, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108, +105,116,121, 95,115,112,111,116, 95,115,113,117, 97,114,101, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,109, 97, +116, 52, 32,108, 97,109,112,105,109, 97,116, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +105,110,112,114, 41, 10,123, 10, 9,105,102, 40,100,111,116, 40,108,118, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 62, 32, 48, + 46, 48, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,118,114,111,116, 32, 61, 32, 40,108, 97,109,112,105,109, 97,116, 42,118, +101, 99, 52, 40,108,118, 44, 32, 48, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,109, + 97,120, 40, 97, 98,115, 40,108,118,114,111,116, 46,120, 47,108,118,114,111,116, 46,122, 41, 44, 32, 97, 98,115, 40,108,118,114, +111,116, 46,121, 47,108,118,114,111,116, 46,122, 41, 41, 59, 10, 10, 9, 9,105,110,112,114, 32, 61, 32, 49, 46, 48, 47,115,113, +114,116, 40, 49, 46, 48, 32, 43, 32,120, 42,120, 41, 59, 10, 9,125, 10, 9,101,108,115,101, 10, 9, 9,105,110,112,114, 32, 61, + 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112, +111,116, 95, 99,105,114, 99,108,101, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,108,118, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, 10,123, 10, 9,105,110,112,114, 32, 61, 32,100,111,116, 40,108, +118, 44, 32,108, 97,109,112,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105, +108,105,116,121, 95,115,112,111,116, 40,102,108,111, 97,116, 32,115,112,111,116,115,105, 44, 32,102,108,111, 97,116, 32,115,112, +111,116, 98,108, 44, 32,102,108,111, 97,116, 32,105,110,112,114, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32, +116, 32, 61, 32,115,112,111,116,115,105, 59, 10, 10, 9,105,102, 40,105,110,112,114, 32, 60, 61, 32,116, 41, 32,123, 10, 9, 9, +111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, + 32, 61, 32,105,110,112,114, 32, 45, 32,116, 59, 10, 10, 9, 9, 47, 42, 32,115,111,102,116, 32, 97,114,101, 97, 32, 42, 47, 10, + 9, 9,105,102, 40,115,112,111,116, 98,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,105,110,112,114, 32, 42, 61, 32,115, +109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, 46, 48, 44, 32,116, 47,115,112,111,116, 98,108, 41, 59, 10, 10, + 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32,118,105,115,105,102, 97, 99, 42,105,110,112,114, 59, 10, 9,125, 10, +125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95, 99,108, 97,109,112, 40,102,108, +111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, + 99, 41, 10,123, 10, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 40,118,105,115,105,102, 97, 99, 32, 60, 32, 48, 46, + 48, 48, 49, 41, 63, 32, 48, 46, 48, 58, 32,118,105,115,105,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, +101, 95,118,105,101,119, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 41, 10,123, + 10, 9, 47, 42, 32,104, 97,110,100,108,101, 32,112,101,114,115,112,101, 99,116,105,118,101, 47,111,114,116,104,111,103,114, 97, +112,104,105, 99, 32, 42, 47, 10, 9,118,105,101,119, 32, 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97, +116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, 48, 41, 63, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, + 41, 58, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 45, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, 40,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,116, + 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,101, 99, 51, 32, 99, 32, 61, 32, 99,114, +111,115,115, 40,108,118, 44, 32,116, 97,110,103, 41, 59, 10, 9,118,101, 99, 51, 32,118,110,111,114, 32, 61, 32, 99,114,111,115, +115, 40, 99, 44, 32,116, 97,110,103, 41, 59, 10, 10, 9,118,110, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,118,110, +111,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,110,112, 40,118,101, 99, 51, 32,118,110, 44, 32, +118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10,123, 10, 9,105,110,112, 32, 61, + 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,110, +111, 95,100,105,102,102,117,115,101, 40,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, + 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,104,101,109,105, 40,102,108,111, 97,116, + 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 53, 42, +105,110,112, 32, 43, 32, 48, 46, 53, 59, 10,125, 10, 10,102,108,111, 97,116, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110, +101,114,103,121, 40,109, 97,116, 52, 32, 97,114,101, 97, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,118,110, + 41, 10,123, 10, 9,118,101, 99, 51, 32,118,101, 99, 91, 52, 93, 44, 32, 99, 91, 52, 93, 59, 10, 9,102,108,111, 97,116, 32,114, + 97,100, 91, 52, 93, 44, 32,102, 97, 99, 59, 10, 9, 10, 9,118,101, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122, +101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 48, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 49, 93, 32, 61, 32,110, +111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 49, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, + 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 50, 93, 46,120,121,122, + 41, 59, 10, 9,118,101, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, + 91, 51, 93, 46,120,121,122, 41, 59, 10, 10, 9, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111, +115,115, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, 41, 59, 10, 9, 99, 91, 49, 93, 32, 61, 32,110,111,114, +109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9, + 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 50, 93, 44, 32,118, +101, 99, 91, 51, 93, 41, 41, 59, 10, 9, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, + 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,114, 97,100, 91, 48, 93, 32, 61, 32, 97, 99, +111,115, 40,100,111,116, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 49, 93, + 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9,114, + 97,100, 91, 50, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, + 41, 59, 10, 9,114, 97,100, 91, 51, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, + 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,102, 97, 99, 61, 32, 32,114, 97,100, 91, 48, 93, 42,100,111,116, 40,118,110, 44, 32, 99, + 91, 48, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 49, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 49, 93, + 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 50, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 50, 93, 41, 59, 10, + 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 51, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 51, 93, 41, 59, 10, 10, 9,114, +101,116,117,114,110, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,105,110,112, 95, 97,114,101, 97, 40,118,101, 99, 51, 32,112,111,115,105,116,105,111,110, 44, 32,118,101, 99, 51, 32, +108, 97,109,112, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,109, + 97,116, 52, 32, 97,114,101, 97, 44, 32,102,108,111, 97,116, 32, 97,114,101, 97,115,105,122,101, 44, 32,102,108,111, 97,116, 32, +107, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10,123, 10, 9,118,101, 99, 51, 32, 99,111, 32, 61, 32,112, +111,115,105,116,105,111,110, 59, 10, 9,118,101, 99, 51, 32,118,101, 99, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, + 59, 10, 10, 9,105,102, 40,100,111,116, 40,118,101, 99, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 60, 32, 48, 46, 48, 41, 32, +123, 10, 9, 9,105,110,112, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97, +116, 32,105,110,116,101,110,115, 32, 61, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110,101,114,103,121, 40, 97,114,101, 97, + 44, 32, 99,111, 44, 32,118,110, 41, 59, 10, 10, 9, 9,105,110,112, 32, 61, 32,112,111,119, 40,105,110,116,101,110,115, 42, 97, +114,101, 97,115,105,122,101, 44, 32,107, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105, +102,102,117,115,101, 95,111,114,101,110, 95,110, 97,121,101,114, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32, +110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108, +105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40, +110, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, + 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,114,101, 97,108,110,108, 32, 61, 32,100,111, +116, 40,110, 44, 32,108, 41, 59, 10, 10, 9,105,102, 40,114,101, 97,108,110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, +105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105,102, 40,110,108, 32, 60, 32, 48, 46, 48, 41, 32, +123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, + 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, + 97,116, 32, 76,105,116, 95, 65, 32, 61, 32, 97, 99,111,115, 40,114,101, 97,108,110,108, 41, 59, 10, 9, 9,102,108,111, 97,116, + 32, 86,105,101,119, 95, 65, 32, 61, 32, 97, 99,111,115, 40,110,118, 41, 59, 10, 10, 9, 9,118,101, 99, 51, 32, 76,105,116, 95, + 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 45, 32,114,101, 97,108,110,108, 42,110, 41, 59, 10, 9, 9,118, +101, 99, 51, 32, 86,105,101,119, 95, 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 45, 32,110,118, 42,110, 41, + 59, 10, 10, 9, 9,102,108,111, 97,116, 32,116, 32, 61, 32,109, 97,120, 40,100,111,116, 40, 76,105,116, 95, 66, 44, 32, 86,105, +101,119, 95, 66, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,102,108,111, 97,116, 32, 97, 44, 32, 98, 59, 10, 10, 9, 9,105, +102, 40, 76,105,116, 95, 65, 32, 62, 32, 86,105,101,119, 95, 65, 41, 32,123, 10, 9, 9, 9, 97, 32, 61, 32, 76,105,116, 95, 65, + 59, 10, 9, 9, 9, 98, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, + 9, 97, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9, 9, 98, 32, 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9,125, 10, 10, + 9, 9,102,108,111, 97,116, 32, 65, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 48, 46, 53, 42, 40, 40,114,111,117,103,104, 42,114, +111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, 46, 51, 51, 41, 41, 41, 59, 10, + 9, 9,102,108,111, 97,116, 32, 66, 32, 61, 32, 48, 46, 52, 53, 42, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, + 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, 46, 48, 57, 41, 41, 59, 10, 10, 9, 9, 98, 32, 42, 61, + 32, 48, 46, 57, 53, 59, 10, 9, 9,105,115, 32, 61, 32,110,108, 42, 40, 65, 32, 43, 32, 40, 66, 32, 42, 32,116, 32, 42, 32,115, +105,110, 40, 97, 41, 32, 42, 32,116, 97,110, 40, 98, 41, 41, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,100,105,102,102,117,115,101, 95,116,111,111,110, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32, +118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116, +104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, + 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115, +108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,105,115, 32, 61, 32, 49, 46, 48, 59, 10, + 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 32, 40,115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32, +124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, +115,101, 32,105,115, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111, +111,116,104, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,109,105,110,110, + 97,101,114,116, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,118, 44, 32,102, +108,111, 97,116, 32,100, 97,114,107,110,101,115,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9, +105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9, +101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, + 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,105,102, 40,100, 97,114,107,110,101,115,115, 32, 60, 61, 32, 49, 46, 48, 41, 10, + 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40,109, 97,120, 40,110,118, 42,110,108, 44, 32, 48, 46, 49, 41, 44, 32, +100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,105,115, 32, 61, 32, +110,108, 42,112,111,119, 40, 49, 46, 48, 48, 48, 49, 32, 45, 32,110,118, 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, + 46, 48, 41, 59, 10, 9,125, 10,125, 10, 10,102,108,111, 97,116, 32,102,114,101,115,110,101,108, 95,102, 97, 99, 40,118,101, 99, + 51, 32,118,105,101,119, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,102,108,111, 97,116, 32,103,114, 97,100, 44, 32,102,108,111, + 97,116, 32,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 49, 44, 32,116, 50, 59, 10, 9,102,108,111, 97,116, 32, +102,102, 97, 99, 59, 10, 10, 9,105,102, 40,102, 97, 99, 61, 61, 48, 46, 48, 41, 32,123, 10, 9, 9,102,102, 97, 99, 32, 61, 32, + 49, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, 49, 61, 32,100,111,116, 40,118,105,101,119, 44, 32, +118,110, 41, 59, 10, 9, 9,105,102, 40,116, 49, 62, 48, 46, 48, 41, 32, 32,116, 50, 61, 32, 49, 46, 48, 43,116, 49, 59, 10, 9, + 9,101,108,115,101, 32,116, 50, 61, 32, 49, 46, 48, 45,116, 49, 59, 10, 10, 9, 9,116, 50, 61, 32,103,114, 97,100, 32, 43, 32, + 40, 49, 46, 48, 45,103,114, 97,100, 41, 42,112,111,119, 40,116, 50, 44, 32,102, 97, 99, 41, 59, 10, 10, 9, 9,105,102, 40,116, + 50, 60, 48, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40,116, 50, 62, + 49, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,102,102, 97, 99, 32, 61, 32,116, + 50, 59, 10, 9,125, 10, 10, 9,114,101,116,117,114,110, 32,102,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,100,105,102,102,117,115,101, 95,102,114,101,115,110,101,108, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, + 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 95,105, 44, 32,102,108,111, + 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32,102,114, +101,115,110,101,108, 95,102, 97, 99, 40,108,118, 44, 32,118,110, 44, 32,102, 97, 99, 95,105, 44, 32,102, 97, 99, 41, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,117, 98,105, 99, 40,102,108,111, 97,116, 32,105,115, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,111,117,116,105,115, 41, 10,123, 10, 9,105,102, 40,105,115, 62, 48, 46, 48, 32, 38, 38, 32,105,115, + 60, 49, 46, 48, 41, 10, 9, 9,111,117,116,105,115, 61, 32,115,109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, + 46, 48, 44, 32,105,115, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,105,115, 61, 32,105,115, 59, 10,125, 10, 10,118, +111,105,100, 32,115,104, 97,100,101, 95,118,105,115,105,102, 97, 99, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, + 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32,114,101,102,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +111,117,116,105, 41, 10,123, 10, 9, 47, 42,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, 42, 47, 10, 9, 9,111,117,116,105, 32, + 61, 32,109, 97,120, 40,105, 42,118,105,115,105,102, 97, 99, 42,114,101,102,108, 44, 32, 48, 46, 48, 41, 59, 10, 9, 47, 42,101, +108,115,101, 10, 9, 9,111,117,116,105, 32, 61, 32,105, 59, 42, 47, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, +116, 97,110,103,101,110,116, 95,118, 95,115,112,101, 99, 40,118,101, 99, 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, + 99, 51, 32,118,110, 41, 10,123, 10, 9,118,110, 32, 61, 32,116, 97,110,103, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95, 97,100,100, 95,116,111, 95,100,105,102,102,117,115,101, 40,102,108,111, 97,116, 32,105, 44, 32,118,101, 99, 51, 32, +108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,105, 42, +108, 97,109,112, 99,111,108, 42, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, + 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,104,101,109,105, 95,115,112,101, 99, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, + 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32, +102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,108, +118, 32, 43, 61, 32,118,105,101,119, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,118, 41, 59, 10, + 10, 9,116, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10, 9,116, 32, 61, 32, 48, 46, 53, 42,116, 32, 43, 32, + 48, 46, 53, 59, 10, 10, 9,116, 32, 61, 32,118,105,115,105,102, 97, 99, 42,115,112,101, 99, 42,112,111,119, 40,116, 44, 32,104, + 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,112,104,111,110,103, 95,115,112,101, 99, 40,118, +101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114, +100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, + 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, + 61, 32,109, 97,120, 40,100,111,116, 40,104, 44, 32,110, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, + 32, 61, 32,112,111,119, 40,114,115,108,116, 44, 32,104, 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, +101, 95, 99,111,111,107,116,111,114,114, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32, +118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112, +101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, + 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 10, 9,105,102, + 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, + 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, + 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,105, 32, 61, 32,112,111,119, 40,110,104, 44, 32,104, + 97,114,100, 41, 59, 10, 10, 9, 9,105, 32, 61, 32,105, 47, 40, 48, 46, 49, 43,110,118, 41, 59, 10, 9, 9,115,112,101, 99,102, + 97, 99, 32, 61, 32,105, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 98,108,105,110,110, 95,115, +112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97, +116, 32,114,101,102,114, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 95,112,111,119,101,114, 44, 32,111,117,116, 32, +102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,105,102, 40,114,101,102,114, 97, 99, 32, 60, 32, 49, 46, + 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105, +102, 40,115,112,101, 99, 95,112,111,119,101,114, 32, 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, + 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,105,102, 40,115,112,101, 99, 95,112,111,119, +101,114, 60, 49, 48, 48, 46, 48, 41, 10, 9, 9, 9,115,112,101, 99, 95,112,111,119,101,114, 61, 32,115,113,114,116, 40, 49, 46, + 48, 47,115,112,101, 99, 95,112,111,119,101,114, 41, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,115,112,101, 99, 95,112,111, +119,101,114, 61, 32, 49, 48, 46, 48, 47,115,112,101, 99, 95,112,111,119,101,114, 59, 10, 10, 9, 9,118,101, 99, 51, 32,104, 32, + 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,110,104, 32, 61, + 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 9, 9,105,102, 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, 9, +115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9,102, +108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, + 9, 9, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9, 9, 9,105,102, 40,110, +108, 32, 60, 61, 32, 48, 46, 48, 49, 41, 32,123, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, + 9, 9, 9,125, 10, 9, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97, +120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97, + 32, 61, 32, 49, 46, 48, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 98, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,118, + 41, 47,118,104, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 99, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,108, 41, 47, +118,104, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,103, 32, 61, 32, 48, 46, 48, 59, 10, 10, 9, 9, 9, 9,105,102, 40, + 97, 32, 60, 32, 98, 32, 38, 38, 32, 97, 32, 60, 32, 99, 41, 32,103, 32, 61, 32, 97, 59, 10, 9, 9, 9, 9,101,108,115,101, 32, +105,102, 40, 98, 32, 60, 32, 97, 32, 38, 38, 32, 98, 32, 60, 32, 99, 41, 32,103, 32, 61, 32, 98, 59, 10, 9, 9, 9, 9,101,108, +115,101, 32,105,102, 40, 99, 32, 60, 32, 97, 32, 38, 38, 32, 99, 32, 60, 32, 98, 41, 32,103, 32, 61, 32, 99, 59, 10, 10, 9, 9, + 9, 9,102,108,111, 97,116, 32,112, 32, 61, 32,115,113,114,116, 40, 40, 40,114,101,102,114, 97, 99, 32, 42, 32,114,101,102,114, + 97, 99, 41, 43, 40,118,104, 42,118,104, 41, 45, 49, 46, 48, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,102, 32, 61, + 32, 40, 40, 40,112, 45,118,104, 41, 42, 40,112, 45,118,104, 41, 41, 47, 40, 40,112, 43,118,104, 41, 42, 40,112, 43,118,104, 41, + 41, 41, 42, 40, 49, 46, 48, 43, 40, 40, 40, 40,118,104, 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 42, 40, 40,118,104, + 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 41, 47, 40, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, + 41, 42, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, 41, 41, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97, +116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,110,104, 41, 59, 10, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, + 32,109, 97,120, 40,102, 42,103, 42,101,120,112, 95, 98,108,101,110,100,101,114, 40, 40, 45, 40, 97,110,103, 42, 97,110,103, 41, + 47, 40, 50, 46, 48, 42,115,112,101, 99, 95,112,111,119,101,114, 42,115,112,101, 99, 95,112,111,119,101,114, 41, 41, 41, 44, 32, + 48, 46, 48, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, +119, 97,114,100,105,115,111, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, + 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,109,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, + 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, + 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 48, + 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, + 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,108, 41, + 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103,108,101, 32, 61, 32,116, 97,110, 40, 97, 99,111, +115, 40,110,104, 41, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,108,112,104, 97, 32, 61, 32,109, 97,120, 40,114,109,115, 44, 32, + 48, 46, 48, 48, 49, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 61, 32,110,108, 32, 42, 32, 40, 49, 46, 48, 47, 40, 52, 46, + 48, 42, 77, 95, 80, 73, 42, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 42, 40,101,120,112, 95, 98,108,101,110,100,101, +114, 40, 45, 40, 97,110,103,108,101, 42, 97,110,103,108,101, 41, 47, 40, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 47, + 40,115,113,114,116, 40,110,118, 42,110,108, 41, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116,111, +111,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32, +102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108, +105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,100,111,116, 40,104, 44, + 32,110, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9, +105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, + 32,105,102, 40, 97,110,103, 32, 62, 61, 32, 40,115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116, +115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,115,108,116, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, + 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111, +111,116,104, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,114,115,108,116, 59, 10,125, 10, 10,118,111,105,100, 32, +115,104, 97,100,101, 95,115,112,101, 99, 95, 97,114,101, 97, 95,105,110,112, 40,102,108,111, 97,116, 32,115,112,101, 99,102, 97, + 99, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,112,101, 99,102, + 97, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99,102, 97, 99, 32, 61, 32,115,112,101, 99,102, 97, 99, 42,105,110,112, 59, + 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115,112,101, 99, 95,116, 40,102,108,111, 97,116, 32,115,104, 97,100, +102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32, +102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,116, + 32, 61, 32,115,104, 97,100,102, 97, 99, 42,115,112,101, 99, 42,118,105,115,105,102, 97, 99, 42,115,112,101, 99,102, 97, 99, 59, + 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 95,115,112,101, 99, 40,102,108,111, 97,116, 32,116, 44, + 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32,115,112,101, 99, 99,111,108, 44, 32,111,117,116, + 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,116, 42,108, 97,109,112, + 99,111,108, 42,115,112,101, 99, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 40,118, +101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117, +116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, + 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 32, 43, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10, +125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100,102, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108, +111, 97,116, 32,102, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 32, 43, 32,102, 42, 99,111,108, 49, 59, 10,125, 10, 10, +118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99, +111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, + 61, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 95,118, + 97,108,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 42,102, 97, 99, 59, 10, +125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32, +118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9, +111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 42,111, 98, 99,111,108, 46,114,103, 98, 44, + 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,114, 97,109,112, 95,114,103, 98,116,111, 98,119, 40,118,101, + 99, 51, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111, +117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 32, 43, 32, 99,111,108,111,114, 46,103, 42, 48, 46, + 53, 56, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 49, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,111,110,108,121, 95,115,104, 97,100,111,119, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, 32,115,104, 97,100, +102, 97, 99, 44, 32,102,108,111, 97,116, 32,101,110,101,114,103,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, +115,104, 97,100,102, 97, 99, 41, 10,123, 10, 9,111,117,116,115,104, 97,100,102, 97, 99, 32, 61, 32,105, 42,101,110,101,114,103, +121, 42, 40, 49, 46, 48, 32, 45, 32,115,104, 97,100,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,100,105,102,102,117,115,101, 40,102,108,111, 97,116, 32,115,104, 97,100,102, + 97, 99, 44, 32,118,101, 99, 51, 32,114,103, 98, 44, 32,118,101, 99, 52, 32,100,105,102,102, 44, 32,111,117,116, 32,118,101, 99, + 52, 32,111,117,116,100,105,102,102, 41, 10,123, 10, 9,111,117,116,100,105,102,102, 32, 61, 32,100,105,102,102, 32, 45, 32,118, +101, 99, 52, 40,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115, +104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,115,112,101, 99,117,108, 97,114, 40,102,108,111, 97,116, 32, +115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,115,112,101, 99,114,103, 98, 44, 32,118,101, 99, 52, 32,115,112,101, 99, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,115,112,101, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99, 32, 61, + 32,115,112,101, 99, 32, 45, 32,118,101, 99, 52, 40,115,112,101, 99,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, + 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,115,116, 95,115,104, 97,100,111,119, 98,117,102, 40,118,101, 99, 51, 32, +114, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 83,104, 97,100,111,119, 32,115,104, 97,100,111,119,109, 97,112, 44, 32, +109, 97,116, 52, 32,115,104, 97,100,111,119,112,101,114,115,109, 97,116, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,111,119, + 98,105, 97,115, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108, +116, 41, 10,123, 10, 9,105,102, 40,105,110,112, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,101,115,117,108,116, 32, + 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,115,104, + 97,100,111,119,112,101,114,115,109, 97,116, 42,118,101, 99, 52, 40,114, 99,111, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9, 9, 47, + 47,102,108,111, 97,116, 32, 98,105, 97,115, 32, 61, 32, 40, 49, 46, 53, 32, 45, 32,105,110,112, 42,105,110,112, 41, 42,115,104, + 97,100,111,119, 98,105, 97,115, 59, 10, 9, 9, 99,111, 46,122, 32, 45, 61, 32,115,104, 97,100,111,119, 98,105, 97,115, 42, 99, +111, 46,119, 59, 10, 10, 9, 9,114,101,115,117,108,116, 32, 61, 32,115,104, 97,100,111,119, 50, 68, 80,114,111,106, 40,115,104, + 97,100,111,119,109, 97,112, 44, 32, 99,111, 41, 46,120, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,101,120,112,111,115,117,114,101, 95, 99,111,114,114,101, 99,116, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,102,108,111, 97, +116, 32,108,105,110,102, 97, 99, 44, 32,102,108,111, 97,116, 32,108,111,103,102, 97, 99, 44, 32,111,117,116, 32,118,101, 99, 51, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,108,105,110,102, 97, 99, 42, 40, 49, 46, 48, + 32, 45, 32,101,120,112, 40, 99,111,108, 42,108,111,103,102, 97, 99, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,109,105,115,116, 95,102, 97, 99,116,111,114, 40,118,101, 99, 51, 32, 99,111, 44, 32,102,108,111, 97,116, 32,109,105, +115,116,115,116, 97, 44, 32,102,108,111, 97,116, 32,109,105,115,116,100,105,115,116, 44, 32,102,108,111, 97,116, 32,109,105,115, +116,116,121,112,101, 44, 32,102,108,111, 97,116, 32,109,105,115,105, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, +102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 44, 32,122, 99,111,114, 59, 10, 10, 9,122, 99,111,114, 32, + 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, + 48, 46, 48, 41, 63, 32,108,101,110,103,116,104, 40, 99,111, 41, 58, 32, 45, 99,111, 91, 50, 93, 59, 10, 9, 10, 9,102, 97, 99, + 32, 61, 32, 99,108, 97,109,112, 40, 40,122, 99,111,114, 45,109,105,115,116,115,116, 97, 41, 47,109,105,115,116,100,105,115,116, + 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105,102, 40,109,105,115,116,116,121,112,101, 32, 61, 61, 32, 48, 46, 48, + 41, 32,102, 97, 99, 32, 42, 61, 32,102, 97, 99, 59, 10, 9,101,108,115,101, 32,105,102, 40,109,105,115,116,116,121,112,101, 32, + 61, 61, 32, 49, 46, 48, 41, 59, 10, 9,101,108,115,101, 32,102, 97, 99, 32, 61, 32,115,113,114,116, 40,102, 97, 99, 41, 59, 10, + 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 45,102, 97, 99, 41, 42, 40, 49, 46, 48, 45, +109,105,115,105, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,119,111,114,108,100, 95,109,105,120, 40,118, +101, 99, 51, 32,104,111,114, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, 99,111,108, 46, 97, 44, 32, + 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,109,105,120, 40,104,111, +114, 44, 32, 99,111,108, 46,114,103, 98, 44, 32,102, 97, 99, 41, 44, 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105, +100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111,112, 97,113,117,101, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111, +117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, + 40, 99,111,108, 46,114,103, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108, +112,104, 97, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118, +101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 99,111,108, 46, 97, 42,111, 98, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10, + 0}; + diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl b/source/blender/gpu/intern/gpu_shader_vertex.glsl new file mode 100644 index 00000000000..ba9ef7dead6 --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_vertex.glsl @@ -0,0 +1,12 @@ + +varying vec3 varposition; +varying vec3 varnormal; + +void main() +{ + vec4 co = gl_ModelViewMatrix * gl_Vertex; + + varposition = co.xyz; + varnormal = gl_NormalMatrix * gl_Normal; + gl_Position = gl_ProjectionMatrix * co; + diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl.c b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c new file mode 100644 index 00000000000..a89de776864 --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c @@ -0,0 +1,13 @@ +/* DataToC output of file */ + +int datatoc_gpu_shader_vertex_glsl_size= 217; +char datatoc_gpu_shader_vertex_glsl[]= { + 10,118, 97,114,121,105,110,103, 32,118,101, 99, 51, 32,118, 97,114,112,111,115,105,116,105,111,110, + 59, 10,118, 97,114,121,105,110,103, 32,118,101, 99, 51, 32,118, 97,114,110,111,114,109, 97,108, 59, 10, 10,118,111,105,100, 32, +109, 97,105,110, 40, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,103,108, 95, 77,111,100,101,108, 86,105,101,119, + 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 86,101,114,116,101,120, 59, 10, 10, 9,118, 97,114,112,111,115,105,116,105,111, +110, 32, 61, 32, 99,111, 46,120,121,122, 59, 10, 9,118, 97,114,110,111,114,109, 97,108, 32, 61, 32,103,108, 95, 78,111,114,109, + 97,108, 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 78,111,114,109, 97,108, 59, 10, 9,103,108, 95, 80,111,115,105,116,105, +111,110, 32, 61, 32,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 32, 42, 32, 99,111, 59, 10, 10, +}; + diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 2aa276a5f53..141b8a985cf 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -164,9 +164,9 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags) } } else if (depth == 32) { for (i = x * y; i > 0; i--) { - rect[0] = bmp[0]; + rect[0] = bmp[2]; rect[1] = bmp[1]; - rect[2] = bmp[2]; + rect[2] = bmp[0]; rect[3] = bmp[3]; rect += 4; bmp += 4; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index d298e8b5ea8..043fba9d675 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -53,6 +53,14 @@ ColorBlock::ColorBlock() { } +/// Init the color block from an array of colors. +ColorBlock::ColorBlock(const uint * linearImage) +{ + for(uint i = 0; i < 16; i++) { + color(i) = Color32(linearImage[i]); + } +} + /// Init the color block with the contents of the given block. ColorBlock::ColorBlock(const ColorBlock & block) { @@ -125,9 +133,36 @@ void ColorBlock::splatY() /// Returns true if the block has a single color. bool ColorBlock::isSingleColor() const { + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = m_color[0].u & mask.u; + for(int i = 1; i < 16; i++) { - if (m_color[0] != m_color[i]) + if (u != (m_color[i].u & mask.u)) + { + return false; + } + } + + return true; +} + +/// Returns true if the block has a single color, ignoring transparent pixels. +bool ColorBlock::isSingleColorNoAlpha() const +{ + Color32 c; + int i; + for(i = 0; i < 16; i++) + { + if (m_color[i].a != 0) c = m_color[i]; + } + + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = c.u & mask.u; + + for(; i < 16; i++) + { + if (u != (m_color[i].u & mask.u)) { return false; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 141411f37af..537c17346a1 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -41,6 +41,7 @@ struct ColorBlock { ColorBlock(); + ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); ColorBlock(const Image * img, uint x, uint y); @@ -51,6 +52,7 @@ struct ColorBlock void splatY(); bool isSingleColor() const; + bool isSingleColorNoAlpha() const; uint countUniqueColors() const; Color32 averageColor() const; bool hasAlpha() const; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 01838281dee..0981ae88db6 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -80,6 +80,10 @@ static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); +static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y'); + +static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0'); + // 32 bit RGB formats. static const uint D3DFMT_R8G8B8 = 20; static const uint D3DFMT_A8R8G8B8 = 21; @@ -279,6 +283,144 @@ static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, }; + + const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) + { +#define CASE(format) case DXGI_FORMAT_##format: return #format + switch(dxgiFormat) + { + CASE(UNKNOWN); + + CASE(R32G32B32A32_TYPELESS); + CASE(R32G32B32A32_FLOAT); + CASE(R32G32B32A32_UINT); + CASE(R32G32B32A32_SINT); + + CASE(R32G32B32_TYPELESS); + CASE(R32G32B32_FLOAT); + CASE(R32G32B32_UINT); + CASE(R32G32B32_SINT); + + CASE(R16G16B16A16_TYPELESS); + CASE(R16G16B16A16_FLOAT); + CASE(R16G16B16A16_UNORM); + CASE(R16G16B16A16_UINT); + CASE(R16G16B16A16_SNORM); + CASE(R16G16B16A16_SINT); + + CASE(R32G32_TYPELESS); + CASE(R32G32_FLOAT); + CASE(R32G32_UINT); + CASE(R32G32_SINT); + + CASE(R32G8X24_TYPELESS); + CASE(D32_FLOAT_S8X24_UINT); + CASE(R32_FLOAT_X8X24_TYPELESS); + CASE(X32_TYPELESS_G8X24_UINT); + + CASE(R10G10B10A2_TYPELESS); + CASE(R10G10B10A2_UNORM); + CASE(R10G10B10A2_UINT); + + CASE(R11G11B10_FLOAT); + + CASE(R8G8B8A8_TYPELESS); + CASE(R8G8B8A8_UNORM); + CASE(R8G8B8A8_UNORM_SRGB); + CASE(R8G8B8A8_UINT); + CASE(R8G8B8A8_SNORM); + CASE(R8G8B8A8_SINT); + + CASE(R16G16_TYPELESS); + CASE(R16G16_FLOAT); + CASE(R16G16_UNORM); + CASE(R16G16_UINT); + CASE(R16G16_SNORM); + CASE(R16G16_SINT); + + CASE(R32_TYPELESS); + CASE(D32_FLOAT); + CASE(R32_FLOAT); + CASE(R32_UINT); + CASE(R32_SINT); + + CASE(R24G8_TYPELESS); + CASE(D24_UNORM_S8_UINT); + CASE(R24_UNORM_X8_TYPELESS); + CASE(X24_TYPELESS_G8_UINT); + + CASE(R8G8_TYPELESS); + CASE(R8G8_UNORM); + CASE(R8G8_UINT); + CASE(R8G8_SNORM); + CASE(R8G8_SINT); + + CASE(R16_TYPELESS); + CASE(R16_FLOAT); + CASE(D16_UNORM); + CASE(R16_UNORM); + CASE(R16_UINT); + CASE(R16_SNORM); + CASE(R16_SINT); + + CASE(R8_TYPELESS); + CASE(R8_UNORM); + CASE(R8_UINT); + CASE(R8_SNORM); + CASE(R8_SINT); + CASE(A8_UNORM); + + CASE(R1_UNORM); + + CASE(R9G9B9E5_SHAREDEXP); + + CASE(R8G8_B8G8_UNORM); + CASE(G8R8_G8B8_UNORM); + + CASE(BC1_TYPELESS); + CASE(BC1_UNORM); + CASE(BC1_UNORM_SRGB); + + CASE(BC2_TYPELESS); + CASE(BC2_UNORM); + CASE(BC2_UNORM_SRGB); + + CASE(BC3_TYPELESS); + CASE(BC3_UNORM); + CASE(BC3_UNORM_SRGB); + + CASE(BC4_TYPELESS); + CASE(BC4_UNORM); + CASE(BC4_SNORM); + + CASE(BC5_TYPELESS); + CASE(BC5_UNORM); + CASE(BC5_SNORM); + + CASE(B5G6R5_UNORM); + CASE(B5G5R5A1_UNORM); + CASE(B8G8R8A8_UNORM); + CASE(B8G8R8X8_UNORM); + + default: + return "UNKNOWN"; + } +#undef CASE + } + + const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) + { + switch(resourceDimension) + { + default: + case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; + case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; + } + } + /*** implementation ***/ void mem_read(Stream & mem, DDSPixelFormat & pf) @@ -451,7 +593,16 @@ void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3) // set fourcc pixel format. this->pf.flags = DDPF_FOURCC; this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3); - this->pf.bitcount = 0; + + if (this->pf.fourcc == FOURCC_ATI2) + { + this->pf.bitcount = FOURCC_A2XY; + } + else + { + this->pf.bitcount = 0; + } + this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; @@ -508,7 +659,8 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask void DDSHeader::setDX10Format(uint format) { - this->pf.flags = 0; + //this->pf.flags = 0; + this->pf.fourcc = FOURCC_DX10; this->header10.dxgiFormat = format; } @@ -520,12 +672,18 @@ void DDSHeader::setNormalFlag(bool b) bool DDSHeader::hasDX10Header() const { - return this->pf.flags == 0; + return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD + //return this->pf.flags == 0; // @@ This is according to MS } DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() { mem_read(stream, header); + + // some ATI2 compressed normal maps do not have their + // normal flag set, so force it here (the original nvtt don't do + // this, but the decompressor has a -forcenormal flag) + if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true); } DirectDrawSurface::~DirectDrawSurface() @@ -539,7 +697,7 @@ bool DirectDrawSurface::isValid() const return false; } - const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); + const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); if( (header.flags & required) != required ) { return false; } @@ -560,40 +718,46 @@ bool DirectDrawSurface::isValid() const bool DirectDrawSurface::isSupported() const { - if (header.pf.flags & DDPF_FOURCC) + if (header.hasDX10Header()) { - if (header.pf.fourcc != FOURCC_DXT1 && - header.pf.fourcc != FOURCC_DXT2 && - header.pf.fourcc != FOURCC_DXT3 && - header.pf.fourcc != FOURCC_DXT4 && - header.pf.fourcc != FOURCC_DXT5 && - header.pf.fourcc != FOURCC_RXGB && - header.pf.fourcc != FOURCC_ATI1 && - header.pf.fourcc != FOURCC_ATI2) - { - // Unknown fourcc code. - return false; - } - } - else if (header.pf.flags & DDPF_RGB) - { - // All RGB formats are supported now. } else { - return false; - } + if (header.pf.flags & DDPF_FOURCC) + { + if (header.pf.fourcc != FOURCC_DXT1 && + header.pf.fourcc != FOURCC_DXT2 && + header.pf.fourcc != FOURCC_DXT3 && + header.pf.fourcc != FOURCC_DXT4 && + header.pf.fourcc != FOURCC_DXT5 && + header.pf.fourcc != FOURCC_RXGB && + header.pf.fourcc != FOURCC_ATI1 && + header.pf.fourcc != FOURCC_ATI2) + { + // Unknown fourcc code. + return false; + } + } + else if (header.pf.flags & DDPF_RGB) + { + // All RGB formats are supported now. + } + else + { + return false; + } + + if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) + { + // Cubemaps must contain all faces. + return false; + } - if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) - { - // Cubemaps must contain all faces. - return false; - } - - if (isTexture3D()) - { - // @@ 3D textures not supported yet. - return false; + if (isTexture3D()) + { + // @@ 3D textures not supported yet. + return false; + } } return true; @@ -641,14 +805,37 @@ bool DirectDrawSurface::hasAlpha() const } } +bool DirectDrawSurface::isTexture1D() const +{ + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + return false; +} + bool DirectDrawSurface::isTexture2D() const { - return !isTexture3D() && !isTextureCube(); + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; + } + else + { + return !isTexture3D() && !isTextureCube(); + } } bool DirectDrawSurface::isTexture3D() const { + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; + } + else + { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; + } } bool DirectDrawSurface::isTextureCube() const @@ -656,6 +843,11 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } +void DirectDrawSurface::setNormalFlag(bool b) +{ + header.setNormalFlag(b); +} + void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { stream.seek(offset(face, mipmap)); @@ -709,7 +901,13 @@ void DirectDrawSurface::readLinearImage(Image * img) return; } - if (header.pf.amask != 0) + // set image format: RGB or ARGB + // alpha channel exists if and only if the alpha mask is non-zero + if (header.pf.amask == 0) + { + img->setFormat(Image::Format_RGB); + } + else { img->setFormat(Image::Format_ARGB); } @@ -735,6 +933,20 @@ void DirectDrawSurface::readLinearImage(Image * img) void DirectDrawSurface::readBlockImage(Image * img) { + + // set image format: RGB or ARGB + if (header.pf.fourcc == FOURCC_RXGB || + header.pf.fourcc == FOURCC_ATI1 || + header.pf.fourcc == FOURCC_ATI2 || + header.pf.flags & DDPF_NORMAL) + { + img->setFormat(Image::Format_RGB); + } + else + { + img->setFormat(Image::Format_ARGB); + } + const uint w = img->width(); const uint h = img->height(); @@ -971,8 +1183,23 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); - printf("\tBit count: %d\n", header.pf.bitcount); + printf("\tFourCC: '%c%c%c%c'\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF)); + if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) + { + printf("\tSwizzle: '%c%c%c%c'\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF); + } + else + { + printf("\tBit count: %d\n", header.pf.bitcount); + } printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); @@ -1003,11 +1230,11 @@ void DirectDrawSurface::printInfo() const printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); - if (header.pf.flags == 0) + if (header.hasDX10Header()) { printf("DX10 Header:\n"); - printf("\tDXGI Format: %u\n", header.header10.dxgiFormat); - printf("\tResource dimension: %u\n", header.header10.resourceDimension); + printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); + printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); printf("\tMisc flag: %u\n", header.header10.miscFlag); printf("\tArray size: %u\n", header.header10.arraySize); } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index d8abfc69167..28fcc95fe83 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -142,9 +142,13 @@ public: uint width() const; uint height() const; uint depth() const; + bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; + + void setNormalFlag(bool b); + bool hasAlpha() const; /* false for DXT1, true for all other DXTs */ void mipmap(Image * img, uint f, uint m); diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index b41b940dca7..cf2f6c16d08 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -94,6 +94,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) } /* convert DDS into ImBuf */ + // TODO use the image RGB or RGBA tag to determine the bits per pixel if (dds.hasAlpha()) bits_per_pixel = 32; else bits_per_pixel = 24; ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0); diff --git a/source/blender/include/BDR_drawmesh.h b/source/blender/include/BDR_drawmesh.h index 93e08ab452d..34351549345 100644 --- a/source/blender/include/BDR_drawmesh.h +++ b/source/blender/include/BDR_drawmesh.h @@ -30,52 +30,11 @@ #ifndef BDR_DRAWMESH_H #define BDR_DRAWMESH_H -struct Image; -struct MTFace; struct Object; struct DerivedMesh; -struct Mesh; -struct EdgeHash; - -/** - * Enables or disable mipmapping for realtime images (textures). - * Note that this will will destroy all texture bindings in OpenGL. - * @see free_realtime_image() - * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0). - */ -void set_mipmap(int mipmap); - -/** - * Enables or disable linear mipmap setting for realtime images (textures). - * Note that this will will destroy all texture bindings in OpenGL. - * @see free_realtime_image() - * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0). - */ -void set_linear_mipmap(int linear); - -/** - * Returns the current setting for linear mipmapping. - */ -int get_linear_mipmap(void); - -/** - * Resets the realtime image cache variables. - */ -void clear_realtime_image_cache(void); - - -void update_realtime_image(struct Image *ima, int x, int y, int w, int h); -void free_realtime_image(struct Image *ima); -void free_all_realtime_images(void); -void make_repbind(struct Image *ima); -int set_tpage(struct MTFace *tface); - -void texpaint_enable_mipmap(void); -void texpaint_disable_mipmap(void); void draw_mesh_textured(struct Object *ob, struct DerivedMesh *dm, int facesel); -struct EdgeHash *get_tface_mesh_marked_edge_info(struct Mesh *me); -void init_realtime_GL(void); +void draw_mesh_text(struct Object *ob, int glsl); #endif /* BDR_DRAWMESH_H */ diff --git a/source/blender/include/BDR_drawobject.h b/source/blender/include/BDR_drawobject.h index de28db64c3b..635b73af80c 100644 --- a/source/blender/include/BDR_drawobject.h +++ b/source/blender/include/BDR_drawobject.h @@ -47,8 +47,7 @@ struct EditVert; struct EditFace; struct EditEdge; -int set_gl_material(int nr); -int init_gl_materials(struct Object *ob, int check_alpha); +int draw_glsl_material(struct Object *ob, int dt); void mesh_foreachScreenVert(void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts); void mesh_foreachScreenEdge(void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts); diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index 7340a2e44e0..9b9294b0343 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -76,6 +76,9 @@ void gpencil_delete_laststroke(struct bGPdata *gpd); void gpencil_delete_operation(short mode); void gpencil_delete_menu(void); +void gpencil_convert_operation(short mode); +void gpencil_convert_menu(void); + //short gpencil_paint(short mousebutton); short gpencil_do_paint(struct ScrArea *sa, short mousebutton); diff --git a/source/blender/include/BDR_imagepaint.h b/source/blender/include/BDR_imagepaint.h index 26f2375e60a..bd1ac301416 100644 --- a/source/blender/include/BDR_imagepaint.h +++ b/source/blender/include/BDR_imagepaint.h @@ -34,8 +34,8 @@ void imagepaint_redraw_tool(void); void imagepaint_pick(short mousebutton); void imagepaint_paint(short mousebutton, short texturepaint); -void imagepaint_undo(); -void free_imagepaint(); +void undo_imagepaint_step(int step); +void undo_imagepaint_clear(void); #endif /* BDR_IMAGEPAINT_H */ diff --git a/source/blender/include/BIF_drawseq.h b/source/blender/include/BIF_drawseq.h index 462075cdf3d..85a6c7a9e2d 100644 --- a/source/blender/include/BIF_drawseq.h +++ b/source/blender/include/BIF_drawseq.h @@ -33,6 +33,8 @@ struct ScrArea; struct Sequence; +#define SEQ_ZOOM_FAC(szoom) (szoom > 0)? (szoom) : (szoom == 0)? (1.0) : (-1.0/szoom) + void drawprefetchseqspace(struct ScrArea *sa, void *spacedata); void drawseqspace(struct ScrArea *sa, void *spacedata); void set_special_seq_update(int val); diff --git a/source/blender/include/BIF_drawtext.h b/source/blender/include/BIF_drawtext.h index a75e0f1bd86..51000f8c81a 100644 --- a/source/blender/include/BIF_drawtext.h +++ b/source/blender/include/BIF_drawtext.h @@ -33,19 +33,21 @@ struct ScrArea; struct SpaceText; struct Text; +struct TextLine; void unlink_text(struct Text *text); void free_textspace(struct SpaceText *st); +int txt_file_modified(struct Text *text); void txt_write_file(struct Text *text); void add_text_fs(char *file); void free_txt_data(void); void pop_space_text(struct SpaceText *st); -void get_format_string(struct SpaceText *st); -void do_brackets(void); +void txt_format_text(struct SpaceText *st); +void txt_format_line(struct SpaceText *st, struct TextLine *line, int do_next); #endif diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 77c2f19bb9b..1425cf6a67c 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -78,7 +78,7 @@ enum { #define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT)) #define NLA_ACTION_SCALED (G.saction->mode==SACTCONT_ACTION && G.saction->pin==0 && OBACT && OBACT->action) -#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) +#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo && G.sipo->pin==0 && G.sipo->actname) /* constants for setting ipo-interpolation type */ enum { diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 07fc8f08b4a..fdd00a67465 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -91,6 +91,7 @@ void free_editArmature(void); int join_armature(void); void separate_armature(void); +void apply_armature_pose2bones(void); void load_editArmature(void); void make_bone_parent(void); @@ -99,13 +100,14 @@ struct Bone *get_indexed_bone (struct Object *ob, int index); void make_editArmature(void); void make_trans_bones (char mode); +void remake_editArmature(void); +void editbones_to_armature(struct ListBase *list, struct Object *ob); int do_pose_selectbuffer(struct Base *base, unsigned int *buffer, short hits); void generateSkeleton(void); void mouse_armature(void); -void remake_editArmature(void); void selectconnected_armature(void); void selectconnected_posearmature(void); void armature_select_hierarchy(short direction, short add_to_sel); diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h index d2c6c56d01a..204733a19d6 100644 --- a/source/blender/include/BIF_editview.h +++ b/source/blender/include/BIF_editview.h @@ -40,6 +40,7 @@ void arrows_move_cursor(unsigned short event); void lasso_select_boundbox(struct rcti *rect, short mcords[][2], short moves); int lasso_inside(short mcords[][2], short moves, short sx, short sy); int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1); +int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2); void borderselect(void); void circle_select(void); void deselectall(void); diff --git a/source/blender/include/BIF_gl.h b/source/blender/include/BIF_gl.h index 2468abdff60..c1b3b056d62 100644 --- a/source/blender/include/BIF_gl.h +++ b/source/blender/include/BIF_gl.h @@ -49,20 +49,7 @@ #endif #endif -#ifdef __APPLE__ - #include - #include -#else -/* #if defined (__sun) || defined (__sun__) - #include - #include - #else -*/ - #include - #include -/* #endif */ -#endif - +#include "GL/glew.h" /* * these should be phased out. cpack should be replaced in diff --git a/source/blender/include/BIF_glutil.h b/source/blender/include/BIF_glutil.h index f530e7ba8d0..ed9096549ca 100644 --- a/source/blender/include/BIF_glutil.h +++ b/source/blender/include/BIF_glutil.h @@ -204,6 +204,7 @@ void bglVertex2fv(float *vec); /* intel gfx cards frontbuffer problem */ void bglFlush(void); int is_a_really_crappy_intel_card(void); +int is_a_really_crappy_nvidia_card(void); void set_inverted_drawing(int enable); diff --git a/source/blender/include/BIF_keyframing.h b/source/blender/include/BIF_keyframing.h new file mode 100644 index 00000000000..eeaef957b90 --- /dev/null +++ b/source/blender/include/BIF_keyframing.h @@ -0,0 +1,99 @@ +/** + * $Id: BIF_keyframing.h 14444 2008-04-16 22:40:48Z aligorith $ + * + * ***** 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 + * This is a new part of Blender (with some old code) + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_KEYFRAMING_H +#define BIF_KEYFRAMING_H + +struct ListBase; +struct ID; + +struct IpoCurve; +struct BezTriple; + +/* ************ Keyframing Management **************** */ + +/* Lesser Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it already + * exists, and there is a beztriple that can be directly copied into the array. + */ +int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + */ +void insert_vert_icu(struct IpoCurve *icu, float x, float y, short flag); + + +/* flags for use in insert_key(), and insert_vert_icu() */ +enum { + INSERTKEY_NEEDED = (1<<0), /* only insert keyframes where they're needed */ + INSERTKEY_MATRIX = (1<<1), /* insert 'visual' keyframes where possible/needed */ + INSERTKEY_FAST = (1<<2), /* don't recalculate handles,etc. after adding key */ + INSERTKEY_FASTR = (1<<3), /* don't realloc mem (or increase count, as array has already been set out) */ + INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */ +} eInsertKeyFlags; + +/* -------- */ + +/* Main Keyframing API calls: + * Use this to create any necessary animation data,, and then insert a keyframe + * using the current value being keyframed, in the relevant place. Returns success. + */ + // TODO: adapt this for new data-api -> this blocktype, etc. stuff is evil! +short insertkey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); + +/* Main Keyframing API call: + * Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case. + */ +short deletekey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); + + +/* Main Keyframe Management calls: + * These handle keyframes management from various spaces. They will handle the menus + * required for each space. + */ +void common_insertkey(void); +void common_deletekey(void); + +/* ************ Keyframe Checking ******************** */ + +/* Checks whether a keyframe exists for the given ID-block one the given frame */ +short id_cfra_has_keyframe(struct ID *id, short filter); + +/* filter flags fr id_cfra_has_keyframe */ +enum { + /* general */ + ANIMFILTER_ALL = 0, /* include all available animation data */ + ANIMFILTER_LOCAL = (1<<0), /* only include locally available anim data */ + + /* object specific */ + ANIMFILTER_MAT = (1<<1), /* include material keyframes too */ + ANIMFILTER_SKEY = (1<<2), /* shape keys (for geometry) */ +} eAnimFilterFlags; + +#endif /* BIF_KEYFRAMING_H */ diff --git a/source/blender/include/BIF_keyval.h b/source/blender/include/BIF_keyval.h index 70d248ded91..9693684e425 100644 --- a/source/blender/include/BIF_keyval.h +++ b/source/blender/include/BIF_keyval.h @@ -31,6 +31,9 @@ #define BIF_KEYVAL_H char *key_event_to_string(unsigned short event); +int decode_key_string(char *str, unsigned short *key, unsigned short *qual); #endif + + diff --git a/source/blender/include/BIF_meshlaplacian.h b/source/blender/include/BIF_meshlaplacian.h index 9fb8aad0eb6..71db8d0bba2 100644 --- a/source/blender/include/BIF_meshlaplacian.h +++ b/source/blender/include/BIF_meshlaplacian.h @@ -47,7 +47,7 @@ struct EditMesh; struct LaplacianSystem; typedef struct LaplacianSystem LaplacianSystem; -LaplacianSystem *laplacian_construct_begin(int totvert, int totface); +LaplacianSystem *laplacian_construct_begin(int totvert, int totface, int lsq); void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned); void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3); diff --git a/source/blender/include/BIF_meshtools.h b/source/blender/include/BIF_meshtools.h index d809d1f21f9..a894d66cb10 100644 --- a/source/blender/include/BIF_meshtools.h +++ b/source/blender/include/BIF_meshtools.h @@ -30,6 +30,8 @@ #ifndef BIF_MESHTOOLS_H #define BIF_MESHTOOLS_H +#include "BLO_sys_types.h" + struct Object; struct EditVert; diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index 0d27804dd1a..b6a9882309d 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -57,8 +57,8 @@ typedef enum { ICON_TRIA_UP, ICON_FONTPREVIEW, ICON_BLANK4, - ICON_BLANK5, - ICON_BLANK6, + ICON_WORDWRAP, + ICON_WORDWRAP_OFF, ICON_ORTHO, ICON_PERSP, @@ -108,7 +108,7 @@ typedef enum { ICON_FF, ICON_REW, ICON_PYTHON, - ICON_BLANK11, + ICON_PYTHON_ON, ICON_BLANK12, ICON_BLANK13, ICON_BLANK14, @@ -266,8 +266,8 @@ typedef enum { ICON_WINDOW_WINDOW, ICON_PANEL_CLOSE, ICON_PHYSICS, - ICON_BLANK36, - ICON_BLANK37, + ICON_LAYER_USED, + ICON_LAYER_ACTIVE, ICON_BLANK38, ICON_BLENDER, diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index 4b2b8e14bb6..c7d0f4a1ada 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -65,6 +65,7 @@ struct SpaceOops; #define IMAGE_HANDLER_PREVIEW 33 #define IMAGE_HANDLER_GAME_PROPERTIES 34 #define IMAGE_HANDLER_VIEW_PROPERTIES 35 +#define IMAGE_HANDLER_GREASEPENCIL 36 /*#define IMAGE_HANDLER_TRANSFORM_PROPERTIES 36*/ /* action handler codes */ @@ -83,6 +84,9 @@ struct SpaceOops; /* nodes handler codes */ #define NODES_HANDLER_GREASEPENCIL 80 +/* text handler codes */ +#define TEXT_HANDLER_FIND 90 + /* theme codes */ #define B_ADD_THEME 3301 #define B_DEL_THEME 3302 diff --git a/source/blender/include/BSE_drawipo.h b/source/blender/include/BSE_drawipo.h index 932f103a579..b8388b2172a 100644 --- a/source/blender/include/BSE_drawipo.h +++ b/source/blender/include/BSE_drawipo.h @@ -42,6 +42,7 @@ struct ScrArea; struct EditIpo; struct View2D; struct rctf; +struct SpaceLink; void calc_ipogrid(void); void draw_ipogrid(void); @@ -50,6 +51,8 @@ void areamouseco_to_ipoco (struct View2D *v2d, short *mval, float *x, float *y); void ipoco_to_areaco (struct View2D *v2d, float *vec, short *mval); void ipoco_to_areaco_noclip (struct View2D *v2d, float *vec, short *mval); +struct View2D *spacelink_get_view2d(struct SpaceLink *sl); + void view2d_do_locks (struct ScrArea *cursa, int flag); void view2d_zoom (struct View2D *v2d, float factor, int winx, int winy); void view2d_getscale (struct View2D *v2d, float *x, float *y); diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index e6f22a4fb67..1b2834b2e3b 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -36,8 +36,6 @@ struct rctf; struct ScrArea; struct ImBuf; -void default_gl_light(void); -void init_gl_stuff(void); void circf(float x, float y, float rad); void circ(float x, float y, float rad); @@ -55,8 +53,8 @@ struct ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax); unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict, unsigned int (*indextest)(unsigned int index)); void drawview3dspace(struct ScrArea *sa, void *spacedata); -void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]); -void draw_depth(struct ScrArea *sa, void *spacedata); +void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int winy, float winmat[][4], int shadow); +void draw_depth(struct ScrArea *sa, void *spacedata, int (*func)(void *) ); void view3d_update_depths(struct View3D *v3d); int update_time(int cfra); diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index e7445efc63e..807e338f514 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -86,13 +86,10 @@ void do_ipo_selectbuttons(void); /* gets ipo curve, creates if needed */ -struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); -struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *); +struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); +struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *, short); int texchannel_to_adrcode(int channel); -int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); -void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -void add_vert_ipo(void); void add_duplicate_editipo(void); void remove_doubles_ipo(void); @@ -121,10 +118,8 @@ void paste_editipo(void); void set_exprap_ipo(int mode); void set_speed_editipo(float speed); -void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast); -void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode); void insertkey_editipo(void); -void common_insertkey(void); +void add_vert_ipo(void); void free_ipokey(struct ListBase *lb); void add_to_ipokey(struct ListBase *lb, struct BezTriple *bezt, int nr, int len); void make_ipokey(void); @@ -163,8 +158,6 @@ void duplicate_ipo_keys(struct Ipo *ipo); void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val); void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, int (*select_function)(struct BezTriple *)); -int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode); -void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey); void select_ipo_key(struct Ipo *ipo, float selx, int sel); void select_icu_key(struct IpoCurve *icu, float selx, int selectmode); void setexprap_ipoloop(struct Ipo *ipo, int code); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 6f8b94d7cd1..a7f7bc2e4b8 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -241,6 +241,7 @@ #define B_SEL_END 168 #define B_MAN_MODE 169 #define B_NDOF 170 +#define B_VIEW_BUTSEDIT 171 /* IPO: 200 */ #define B_IPOHOME 201 @@ -377,6 +378,13 @@ #define B_TEXTLINENUM 507 #define B_TAB_NUMBERS 508 #define B_SYNTAX 509 +#define B_WORDWRAP 510 +#define B_TEXTPLUGINS 511 +#define B_PASTEFIND 512 +#define B_PASTEREPLACE 513 +#define B_TEXTREPLACE 514 +#define B_TEXTFIND 515 +#define B_TEXTMARKALL 516 /* SCRIPT: 525 */ #define B_SCRIPTBROWSE 526 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 720b856a149..51fa39ff9d6 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -466,7 +466,6 @@ int validSnappingNormal(TransInfo *t); /*********************** Generics ********************************/ void initTrans(TransInfo *t); -void initTransModeFlags(TransInfo *t, int mode); void postTrans (TransInfo *t); void drawLine(float *center, float *dir, char axis, short options); @@ -498,6 +497,7 @@ TransInfo * BIF_GetTransInfo(void); /*********************** NumInput ********************************/ +void initNumInput(NumInput *n); void outputNumInput(NumInput *n, char *str); short hasNumInput(NumInput *n); void applyNumInput(NumInput *n, float *vec); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 2e8d95335cc..4a10ecf2368 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -277,7 +277,9 @@ typedef enum POSE_FLAG { /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ POSE_DO_UNLOCK = (1<<2), /* pose has constraints which depend on time (used when depsgraph updates for a new frame) */ - POSE_CONSTRAINTS_TIMEDEPEND = (1<<3) + POSE_CONSTRAINTS_TIMEDEPEND = (1<<3), + /* recalculate bone paths */ + POSE_RECALCPATHS = (1<<4), } POSE_FLAG; /* PoseChannel (transform) flags */ diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 7444ce95f56..750bdf2cfff 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -81,7 +81,9 @@ typedef struct bEditObjectActuator { struct Mesh *me; char name[32]; float linVelocity[3]; /* initial lin. velocity on creation */ - short localflag; /* flag for the lin. vel: apply locally */ + float angVelocity[3]; /* initial ang. velocity on creation */ + float pad; + short localflag; /* flag for the lin & ang. vel: apply locally */ short dyn_operation; } bEditObjectActuator; @@ -191,7 +193,8 @@ typedef struct bGameActuator { } bGameActuator; typedef struct bVisibilityActuator { - /** bit 0: Is this object visible? */ + /** bit 0: Is this object visible? + ** bit 1: Apply recursively */ int flag; } bVisibilityActuator; @@ -298,6 +301,7 @@ typedef struct FreeCamera { #define ACT_NEW 4 #define ACT_LINKED 8 #define ACT_VISIBLE 16 +#define ACT_PIN 32 /* link codes */ #define LINK_SENSOR 0 @@ -384,6 +388,9 @@ typedef struct FreeCamera { #define ACT_EDOB_TRACK_TO 3 #define ACT_EDOB_DYNAMICS 4 +/* editObjectActuator->localflag */ +#define ACT_EDOB_LOCAL_LINV 2 +#define ACT_EDOB_LOCAL_ANGV 4 /* editObjectActuator->flag */ @@ -438,10 +445,13 @@ typedef struct FreeCamera { #define ACT_GAME_START 1 #define ACT_GAME_RESTART 2 #define ACT_GAME_QUIT 3 +#define ACT_GAME_SAVECFG 4 +#define ACT_GAME_LOADCFG 5 /* visibilityact->flag */ /* Set means the object will become invisible */ #define ACT_VISIBILITY_INVISIBLE (1 << 0) +#define ACT_VISIBILITY_RECURSIVE (1 << 1) /* twodfilter->type */ #define ACT_2DFILTER_ENABLED -2 diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 1c272105067..c7196763358 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -33,7 +33,7 @@ #include "DNA_ID.h" #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif struct MTex; @@ -58,7 +58,7 @@ typedef struct Brush { float alpha; /* opacity */ short texact, pad; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ struct BrushClone clone; } Brush; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 13d412c2c42..cc0c9912057 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -61,7 +61,7 @@ typedef struct bGPDstroke { #define GP_STROKE_2DSPACE (1<<1) /* stroke is in 2d-space (but with special 'image' scaling) */ #define GP_STROKE_2DIMAGE (1<<2) - /* stroke is an "eraser" stroke */ + /* only for use with stroke-buffer (while drawing eraser) */ #define GP_STROKE_ERASER (1<<15) diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h index 1bb18ca2ca2..0987050261d 100644 --- a/source/blender/makesdna/DNA_group_types.h +++ b/source/blender/makesdna/DNA_group_types.h @@ -54,7 +54,7 @@ typedef struct Group { * the objects that show in the group can change depending * on the last used scene */ unsigned int layer; - int pad; + float dupli_ofs[3]; } Group; diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 42b651a7555..e1d79f0f875 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -37,6 +37,7 @@ struct PackedFile; struct anim; struct ImBuf; struct RenderResult; +struct GPUTexture; /* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ @@ -62,7 +63,8 @@ typedef struct Image { char name[240]; /* file path */ - ListBase ibufs; /* not written in file */ + ListBase ibufs; /* not written in file */ + struct GPUTexture *gputexture; /* not written in file */ /* sources from: */ struct anim *anim; diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index 1e30f3f7640..2659de2f067 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -142,16 +142,24 @@ typedef short IPO_Channel; #define MA_FRESTRAI 25 #define MA_ADD 26 -#define MA_MAP1 0x20 -#define MA_MAP2 0x40 -#define MA_MAP3 0x80 -#define MA_MAP4 0x100 -#define MA_MAP5 0x200 -#define MA_MAP6 0x400 -#define MA_MAP7 0x800 -#define MA_MAP8 0x1000 -#define MA_MAP9 0x2000 -#define MA_MAP10 0x4000 +#define MA_MAP1 (1<<5) +#define MA_MAP2 (1<<6) +#define MA_MAP3 (1<<7) +#define MA_MAP4 (1<<8) +#define MA_MAP5 (1<<9) +#define MA_MAP6 (1<<10) +#define MA_MAP7 (1<<11) +#define MA_MAP8 (1<<12) +#define MA_MAP9 (1<<13) +#define MA_MAP10 (1<<14) +#define MA_MAP11 (1<<15) +#define MA_MAP12 (1<<16) +#define MA_MAP13 (1<<17) +#define MA_MAP14 (1<<18) +#define MA_MAP15 (1<<19) +#define MA_MAP16 (1<<20) +#define MA_MAP17 (1<<21) +#define MA_MAP18 (1<<22) #define TEX_TOTNAM 14 diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index c00dae08eb4..2a39580bb5c 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -35,7 +35,7 @@ #include "DNA_scriptlink_types.h" #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif struct MTex; @@ -45,7 +45,8 @@ struct CurveMapping; typedef struct Lamp { ID id; - short type, mode; + short type, pad3; + int mode; short colormodel, totex; float r, g, b, k; @@ -55,10 +56,9 @@ typedef struct Lamp { float att1, att2; /* Quad1 and Quad2 attenuation */ - int pad2; struct CurveMapping *curfalloff; short falloff_type; - short pad3; + short pad2; float clipsta, clipend, shadspotsize; float bias, soft; @@ -99,7 +99,7 @@ typedef struct Lamp { float YF_glowint, YF_glowofs; short YF_glowtype, YF_pad2; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ struct Ipo *ipo; /* preview */ @@ -137,6 +137,12 @@ typedef struct Lamp { /* yafray: lamp shadowbuffer flag, softlight */ /* Since it is used with LOCAL lamp, can't use LA_SHAD */ #define LA_YF_SOFT 16384 +#define LA_LAYER_SHADOW 32768 + +/* layer_shadow */ +#define LA_LAYER_SHADOW_BOTH 0 +#define LA_LAYER_SHADOW_CAST 1 +#define LA_LAYER_SHADOW_RECEIVE 2 /* sun effect type*/ #define LA_SUN_EFFECT_SKY 1 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 9412a09d0f4..c92a33bbcbb 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -36,7 +36,7 @@ #include "DNA_listBase.h" #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif struct MTex; @@ -88,11 +88,11 @@ typedef struct Material { float sbias; /* shadow bias to prevent terminator prob */ float lbias; /* factor to multiply lampbias with (0.0 = no mult) */ float shad_alpha; /* in use for irregular shadowbuffer */ - float padf; /* free padding, take me! */ + int septex; /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; - short pr_back, pr_lamp, septex, ml_flag; /* ml_flag is for disable base material */ + short pr_back, pr_lamp, pad4, ml_flag; /* ml_flag is for disable base material */ /* shaders */ short diff_shader, spec_shader; @@ -110,7 +110,7 @@ typedef struct Material { short ramp_show, pad3; float rampfac_col, rampfac_spec; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ struct bNodeTree *nodetree; struct Ipo *ipo; struct Group *group; /* light group */ @@ -133,6 +133,8 @@ typedef struct Material { int YF_dsmp, YF_preset, YF_djit; ScriptLink scriptlink; + + ListBase gpumaterial; /* runtime */ } Material; /* **************** MATERIAL ********************* */ @@ -203,6 +205,7 @@ typedef struct Material { /* shade_flag */ #define MA_CUBIC 1 +#define MA_OBCOLOR 2 /* diff_shader */ #define MA_DIFF_LAMBERT 0 diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 4e427ed733c..fc686a4cc10 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -82,6 +82,7 @@ typedef struct MLoopUV{ typedef struct MLoopCol{ char a, r, g, b; + int pad; /*waste!*/ }MLoopCol; typedef struct MSticky { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 85c49a03569..3708db3fd38 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -156,7 +156,9 @@ typedef struct Object { float formfactor; float rdamping, sizefac; - + float margin, pad3; + + char dt, dtx; char totcol; /* copy of mesh or curve or meta */ char actcol; /* currently selected material in the user interface */ @@ -223,6 +225,8 @@ typedef struct Object { /*#ifdef WITH_VERSE*/ void *vnode; /* pointer at object VerseNode */ /*#endif*/ + + ListBase gpulamp; /* runtime, for lamps only */ } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -425,6 +429,8 @@ extern Object workob; #define OB_PROP 16384 #define OB_MAINACTOR 32768 +#define OB_PHYSICS 65536 + /* ob->gameflag2 */ #define OB_NEVER_DO_ACTIVITY_CULLING 1 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 363f0075e23..8618bee3638 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -416,6 +416,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PARS_DEAD 1 #define PARS_UNBORN 2 #define PARS_ALIVE 3 +#define PARS_DYING 4 /* psys->vg */ #define PSYS_TOT_VG 12 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 75affbfa7f5..32522d1e866 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -464,7 +464,7 @@ typedef struct SculptData struct SculptSession *session; /* Pointers to all of sculptmodes's textures */ - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* Editable brush shape */ struct CurveMapping *cumap; @@ -790,6 +790,7 @@ typedef struct Scene { /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 #define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */ +#define UVCALC_TRANSFORM_CORRECT 4 /* adjust UV's while transforming to avoid distortion */ /* toolsettings->edge_mode */ #define EDGE_MODE_SELECT 0 diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index b5d8511c698..1fd97fe0158 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -164,7 +164,7 @@ typedef struct bSensor { typedef struct bJoystickSensor { char name[32]; short type; - short pad; + short joyindex; int axis; int axisf; int button; @@ -218,6 +218,7 @@ typedef struct bJoystickSensor { #define SENS_NEW 4 #define SENS_NOT 8 #define SENS_VISIBLE 16 +#define SENS_PIN 32 /* sensor->pulse */ #define SENS_PULSE_CONT 0 @@ -237,6 +238,9 @@ typedef struct bJoystickSensor { * */ /* #define SENS_COLLISION_PROPERTY 0 */ #define SENS_COLLISION_MATERIAL 1 +/* ray specific mode */ +/* X-Ray means that the ray will traverse objects that don't have the property/material */ +#define SENS_RAY_XRAY 2 /* Some stuff for the mouse sensor Type: */ #define BL_SENS_MOUSE_LEFT_BUTTON 1 @@ -263,6 +267,7 @@ typedef struct bJoystickSensor { #define SENS_JOY_HAT_DIR 0 #define SENS_DELAY_REPEAT 1 - +// should match JOYINDEX_MAX in SCA_JoystickDefines.h */ +#define SENS_JOY_MAXINDEX 8 #endif diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 39d457058c1..c59cafc1ef0 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -276,22 +276,23 @@ typedef struct SpaceText { struct Text *text; int top, viewlines; - short flags, menunr; - - int font_id; + short flags, menunr; + int font_id; + int lheight; int left; int showlinenrs; - int tabnumber; + int currtab_set; int showsyntax; - int unused_padd; - + int overwrite; float pix_per_line; struct rcti txtscroll, txtbar; + int wordwrap, doplugins; + } SpaceText; typedef struct Script { @@ -537,6 +538,7 @@ typedef struct SpaceImaSel { #define SI_DRAW_TILE 1<<19 #define SI_SMOOTH_UV 1<<20 #define SI_DRAW_STRETCH 1<<21 +#define SI_DISPGP 1<<22 /* SpaceIpo->flag */ #define SIPO_LOCK_VIEW 1<<0 diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index d1859d22115..48ecccd517a 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -38,25 +38,36 @@ typedef struct TextLine { struct TextLine *next, *prev; char *line; - char *format; - int len, blen; + char *format; /* may be NULL if syntax is off or not yet formatted */ + int len, blen; /* blen unused */ } TextLine; +typedef struct TextMarker { + struct TextMarker *next, *prev; + + int lineno, start, end, pad1; /* line number and start/end character indices */ + + int group, flags; /* see BKE_text.h for flag defines */ + char color[4], pad[4]; /* draw color of the marker */ +} TextMarker; + typedef struct Text { ID id; char *name; - + int flags, nlines; ListBase lines; TextLine *curl, *sell; int curc, selc; + ListBase markers; char *undo_buf; int undo_pos, undo_len; void *compiled; + double mtime; } Text; @@ -74,4 +85,12 @@ typedef struct Text { #define TXT_READONLY 0x0100 #define TXT_FOLLOW 0x0200 /* always follow cursor (console) */ +/* format continuation flags */ +#define TXT_NOCONT 0x00 /* no continuation */ +#define TXT_SNGQUOTSTR 0x01 /* single quotes */ +#define TXT_DBLQUOTSTR 0x02 /* double quotes */ +#define TXT_TRISTR 0x04 /* triplets of quotes: """ or ''' */ +#define TXT_SNGTRISTR 0x05 /*(TXT_TRISTR | TXT_SNGQUOTSTR)*/ +#define TXT_DBLTRISTR 0x06 /*(TXT_TRISTR | TXT_DBLQUOTSTR)*/ + #endif diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 8a79ce845d7..111dc08ee02 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -367,6 +367,7 @@ typedef struct TexMapping { #define MTEX_BLEND_SAT 11 #define MTEX_BLEND_VAL 12 #define MTEX_BLEND_COLOR 13 +#define MTEX_NUM_BLENDTYPES 14 /* **************** EnvMap ********************* */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 856324695a9..981591dc810 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -188,6 +188,7 @@ typedef struct UserDef { char fontname[256]; // FILE_MAXDIR+FILE length struct ListBase themes; short undosteps; + short undomemory, pad[3]; short curssize; short tb_leftmouse, tb_rightmouse; struct SolidLight light[3]; @@ -267,6 +268,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_GLOBALUNDO (1 << 13) #define USER_ORBIT_SELECTION (1 << 14) // old flag for #define USER_KEYINSERTAVAI (1 << 15) +#define USER_ORBIT_ZBUF (1 << 15) #define USER_HIDE_DOT (1 << 16) #define USER_SHOW_ROTVIEWICON (1 << 17) #define USER_SHOW_VIEWPORTNAME (1 << 18) diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 135272b9ac2..b30a7162b93 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -86,7 +86,8 @@ typedef struct View3D { float winmat1[4][4]; // persp(1) storage, for swap matrices float viewmat1[4][4]; - float viewquat[4], dist, zfac, pad0; /* zfac is initgrabz() result */ + float viewquat[4], dist, zfac; /* zfac is initgrabz() result */ + int lay_used; /* used while drawing */ short persp; short view; diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 26b3f051944..ab7e25190ad 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -38,7 +38,7 @@ struct Ipo; struct MTex; #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif @@ -108,7 +108,7 @@ typedef struct World { struct Ipo *ipo; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ /* previews */ struct PreviewImage *preview; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 2cb855ed440..cf83804b999 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -30,7 +30,7 @@ SET(INC ../python ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/iksolver/extern ../blenloader ../quicktime - ../blenkernel + ../blenkernel ../../../extern/glew/include ../gpu ${SDL_INC} ${ZLIB_INC} ${PYTHON_INC} diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 8682f626b80..8af7b67520e 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -11,6 +11,7 @@ incs += ' ../python ../render/extern/include ' incs += ' ../imbuf ../avi ' incs += ' ../blenloader ../quicktime' incs += ' ../blenkernel ../renderconverter ' +incs += ' ../gpu #/extern/glew/include ' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c index 5e1803a6774..950ad97a397 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c @@ -130,13 +130,16 @@ static void node_composit_exec_tonemap(void *data, bNode *node, bNodeStack **in, if ((img==NULL) || (out[0]->hasoutput==0)) return; if (img->type != CB_RGBA) - new = typecheck_compbuf(img, CB_RGBA); - else - new = dupalloc_compbuf(img); + img = typecheck_compbuf(img, CB_RGBA); + + new = dupalloc_compbuf(img); tonemap(node->storage, new, img); out[0]->data = new; + + if(img!=in[0]->data) + free_compbuf(img); } static void node_composit_init_tonemap(bNode* node) diff --git a/source/blender/nodes/intern/CMP_nodes/Makefile b/source/blender/nodes/intern/CMP_nodes/Makefile index 61b03f237db..8a8d323ac5b 100644 --- a/source/blender/nodes/intern/CMP_nodes/Makefile +++ b/source/blender/nodes/intern/CMP_nodes/Makefile @@ -42,4 +42,5 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/Makefile b/source/blender/nodes/intern/Makefile index 7cf2411ed84..6167cf6bc72 100644 --- a/source/blender/nodes/intern/Makefile +++ b/source/blender/nodes/intern/Makefile @@ -42,4 +42,6 @@ CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../include CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../render/extern/include +CPPFLAGS += -I../../gpu +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index 1917e9ba15c..ae3cae029d2 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -44,4 +44,6 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I../../../gpu +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c index 63260ff91ed..20136d75540 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c @@ -46,8 +46,13 @@ static void node_shader_exec_camera(void *data, bNode *node, bNodeStack **in, bN VECCOPY(out[0]->vec, shi->co); /* get view vector */ out[1]->vec[0]= fabs(shi->co[2]); /* get view z-depth */ out[2]->vec[0]= Normalize(out[0]->vec); /* get view distance */ - } } +} + +static int gpu_shader_camera(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION)); +} bNodeType sh_node_camera= { /* *next,*prev */ NULL, NULL, @@ -63,6 +68,7 @@ bNodeType sh_node_camera= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_camera }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c index b6f1f8d52cd..d277547b636 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c @@ -56,6 +56,15 @@ static void node_shader_init_curve_vec(bNode* node) node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); } +static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_curve_vec= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_VEC, @@ -70,7 +79,8 @@ bNodeType sh_node_curve_vec= { /* initfunc */ node_shader_init_curve_vec, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_curve_vec }; @@ -100,6 +110,15 @@ static void node_shader_init_curve_rgb(bNode *node) node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } +static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_curve_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_RGB, @@ -114,6 +133,7 @@ bNodeType sh_node_curve_rgb= { /* initfunc */ node_shader_init_curve_rgb, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_curve_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c index 24395059c60..bc345759b98 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c @@ -29,6 +29,7 @@ #include "../SHD_util.h" +#include "DNA_customdata_types.h" /* **************** GEOMETRY ******************** */ @@ -124,6 +125,18 @@ static void node_shader_init_geometry(bNode *node) node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); } +static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname); + GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname); + + return GPU_stack_link(mat, "geom", in, out, + GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol); +} + /* node type definition */ bNodeType sh_node_geom= { /* *next,*prev */ NULL, NULL, @@ -139,6 +152,7 @@ bNodeType sh_node_geom= { /* initfunc */ node_shader_init_geometry, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_geom }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c index 67dfc619080..1b7b2dfb8e7 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c @@ -71,6 +71,12 @@ static void node_shader_exec_hue_sat(void *data, bNode *node, bNodeStack **in, b do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec); } + +static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "hue_sat", in, out); +} + bNodeType sh_node_hue_sat= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_HUE_SAT, @@ -85,7 +91,8 @@ bNodeType sh_node_hue_sat= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_hue_sat }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c index 4d1ce282fce..72ee1483ecf 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c @@ -64,6 +64,11 @@ bNodeStack **out) VECCOPY(out[0]->vec, col); } +static int gpu_shader_invert(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "invert", in, out); +} + bNodeType sh_node_invert= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_INVERT, @@ -78,6 +83,7 @@ bNodeType sh_node_invert= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_invert }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c index 589954c8f7b..c081929a2fc 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c @@ -69,6 +69,20 @@ static void node_shader_init_mapping(bNode *node) node->storage= add_mapping(); } +static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + TexMapping *texmap= node->storage; + float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; + float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0; + GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat); + GPUNodeLink *tmin = GPU_uniform(texmap->min); + GPUNodeLink *tmax = GPU_uniform(texmap->max); + GPUNodeLink *tdomin = GPU_uniform(&domin); + GPUNodeLink *tdomax = GPU_uniform(&domax); + + return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax); +} + bNodeType sh_node_mapping= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MAPPING, @@ -83,7 +97,8 @@ bNodeType sh_node_mapping= { /* initfunc */ node_shader_init_mapping, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_mapping }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index 9396410f850..c0a2534ac4a 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -182,6 +182,77 @@ static void node_shader_init_material(bNode* node) node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; } +static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + if(node->id) { + GPUShadeInput shi; + GPUShadeResult shr; + + GPU_shadeinput_set(mat, (Material*)node->id, &shi); + + /* write values */ + if(in[MAT_IN_COLOR].hasinput) + shi.rgb = in[MAT_IN_COLOR].link; + + if(in[MAT_IN_SPEC].hasinput) + shi.specrgb = in[MAT_IN_SPEC].link; + + if(in[MAT_IN_REFL].hasinput) + shi.refl = in[MAT_IN_REFL].link; + + /* retrieve normal */ + if(in[MAT_IN_NORMAL].hasinput) { + GPUNodeLink *tmp; + shi.vn = in[MAT_IN_NORMAL].link; + GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); + } + + /* custom option to flip normal */ + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + + if (node->type == SH_NODE_MATERIAL_EXT) { + if(in[MAT_IN_AMB].hasinput) + shi.amb= in[MAT_IN_AMB].link; + if(in[MAT_IN_EMIT].hasinput) + shi.emit= in[MAT_IN_EMIT].link; + if(in[MAT_IN_ALPHA].hasinput) + shi.alpha= in[MAT_IN_ALPHA].link; + } + + GPU_shaderesult_set(&shi, &shr); /* clears shr */ + + /* write to outputs */ + if(node->custom1 & SH_NODE_MAT_DIFF) { + if(node->custom1 & SH_NODE_MAT_SPEC) + out[MAT_OUT_COLOR].link= shr.combined; + else + out[MAT_OUT_COLOR].link= shr.diff; + } + else if(node->custom1 & SH_NODE_MAT_SPEC) { + out[MAT_OUT_COLOR].link= shr.spec; + } + else + GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); + + GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); + + out[MAT_OUT_ALPHA].link = shr.alpha; // + + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + out[MAT_OUT_NORMAL].link = shi.vn; + + if (node->type == SH_NODE_MATERIAL_EXT) { + out[MAT_OUT_DIFFUSE].link = shr.diff; + out[MAT_OUT_SPEC].link = shr.spec; + } + + return 1; + } + + return 0; +} bNodeType sh_node_material= { /* *next,*prev */ NULL, NULL, @@ -197,8 +268,8 @@ bNodeType sh_node_material= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL - + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_material }; bNodeType sh_node_material_ext= { @@ -215,7 +286,7 @@ bNodeType sh_node_material_ext= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL - + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_material }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c index 2e156cf12bf..050c2cdcc95 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c @@ -194,6 +194,46 @@ bNodeStack **out) } } +static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"math_add", "math_subtract", "math_multiply", + "math_divide", "math_sine", "math_cosine", "math_tangnet", "math_asin", + "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", + "math_round", "math_less_than", "math_greater_than"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 10: + case 11: + case 12: + case 13: + case 15: + case 16: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 14: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + bNodeType sh_node_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MATH, @@ -208,6 +248,7 @@ bNodeType sh_node_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_math }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c index dba70253fda..2da1dee5623 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c @@ -60,6 +60,17 @@ static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, b VECCOPY(out[0]->vec, col); } +static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", + "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", + "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", + "mix_val", "mix_color"}; + + return GPU_stack_link(mat, names[node->custom1], in, out); +} + + bNodeType sh_node_mix_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MIX_RGB, @@ -74,6 +85,7 @@ bNodeType sh_node_mix_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_mix_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c index f1ffd3446af..9d4ea1ccf67 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c @@ -57,6 +57,14 @@ static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bN out[1]->vec[0]= -INPR(out[0]->vec, vec); } +static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + + return GPU_stack_link(mat, "normal", in, out, vec); +} + bNodeType sh_node_normal= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_NORMAL, @@ -71,6 +79,7 @@ bNodeType sh_node_normal= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_normal }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_output.c b/source/blender/nodes/intern/SHD_nodes/SHD_output.c index 0a9a30c452b..76856cfd2e8 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_output.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_output.c @@ -62,6 +62,19 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN } } +static int gpu_shader_output(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + GPUNodeLink *outlink; + + /*if(in[1].hasinput) + GPU_material_enable_alpha(mat);*/ + + GPU_stack_link(mat, "output_node", in, out, &outlink); + GPU_material_output_link(mat, outlink); + + return 1; +} + bNodeType sh_node_output= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_OUTPUT, @@ -76,7 +89,8 @@ bNodeType sh_node_output= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_output }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c index 4e56e26d3ad..1aa1a2ffc33 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c @@ -42,6 +42,14 @@ static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNode VECCOPY(out[0]->vec, sock->ns.vec); } +static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + + return GPU_stack_link(mat, "set_rgba", in, out, vec); +} + bNodeType sh_node_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGB, @@ -56,6 +64,7 @@ bNodeType sh_node_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c index 2b52a8e2229..6d5df2a1321 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c @@ -48,6 +48,11 @@ static void node_shader_exec_seprgb(void *data, bNode *node, bNodeStack **in, bN out[2]->vec[0] = in[0]->vec[2]; } +static int gpu_shader_seprgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "separate_rgb", in, out); +} + bNodeType sh_node_seprgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SEPRGB, @@ -62,7 +67,8 @@ bNodeType sh_node_seprgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_seprgb }; @@ -86,6 +92,11 @@ static void node_shader_exec_combrgb(void *data, bNode *node, bNodeStack **in, b out[0]->vec[2] = in[2]->vec[0]; } +static int gpu_shader_combrgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "combine_rgb", in, out); +} + bNodeType sh_node_combrgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_COMBRGB, @@ -100,6 +111,7 @@ bNodeType sh_node_combrgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_combrgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c index 30abad666c4..d3480a6ae9d 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c @@ -54,6 +54,11 @@ bNodeStack **out) out[0]->vec[0] = 1.0f / (1.0f + pow(2.71828183,-((vec[0]-vec[2])*vec[1]))) ; } +static int gpu_shader_squeeze(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "squeeze", in, out); +} + bNodeType sh_node_squeeze= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SQUEEZE, @@ -68,6 +73,7 @@ bNodeType sh_node_squeeze= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_squeeze }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c index ace11a20d42..31dbde940fd 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c @@ -27,6 +27,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "DNA_texture_types.h" + #include "../SHD_util.h" /* **************** TEXTURE ******************** */ @@ -110,6 +112,18 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b } } +static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + Tex *tex = (Tex*)node->id; + + if(tex && tex->type == TEX_IMAGE && tex->ima) { + GPUNodeLink *texlink = GPU_image(tex->ima, NULL); + return GPU_stack_link(mat, "texture_image", in, out, texlink); + } + else + return 0; +} + bNodeType sh_node_texture= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_TEXTURE, @@ -124,7 +138,8 @@ bNodeType sh_node_texture= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_texture }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c index cf7e33d9dca..301c0cb7031 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c @@ -59,6 +59,15 @@ static void node_shader_init_valtorgb(bNode *node) node->storage= add_colorband(1); } +static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + colorband_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_valtorgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VALTORGB, @@ -73,7 +82,8 @@ bNodeType sh_node_valtorgb= { /* initfunc */ node_shader_init_valtorgb, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_valtorgb }; @@ -96,6 +106,11 @@ static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, b out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f; } +static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "rgbtobw", in, out); +} + bNodeType sh_node_rgbtobw= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGBTOBW, @@ -110,7 +125,8 @@ bNodeType sh_node_rgbtobw= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_rgbtobw }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_value.c b/source/blender/nodes/intern/SHD_nodes/SHD_value.c index 57ef7226066..768ef3cda3d 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_value.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_value.c @@ -42,7 +42,13 @@ static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNo out[0]->vec[0]= sock->ns.vec[0]; } +static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + return GPU_stack_link(mat, "set_value", in, out, vec); +} bNodeType sh_node_value= { /* *next,*prev */ NULL, NULL, @@ -58,7 +64,8 @@ bNodeType sh_node_value= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_value }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c index 8d0a4b3abe3..96db8db18a6 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c @@ -99,6 +99,34 @@ static void node_shader_exec_vect_math(void *data, bNode *node, bNodeStack **in, } +static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"vec_math_add", "vec_math_subtract", + "vec_math_average", "vec_math_dot", "vec_math_cross", + "vec_math_normalize"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 4: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 5: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + bNodeType sh_node_vect_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VECT_MATH, @@ -113,6 +141,7 @@ bNodeType sh_node_vect_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_vect_math }; diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h index bdb2bb3707d..eda985529c1 100644 --- a/source/blender/nodes/intern/SHD_util.h +++ b/source/blender/nodes/intern/SHD_util.h @@ -88,6 +88,8 @@ #include "RE_pipeline.h" #include "RE_shader_ext.h" +#include "GPU_material.h" + #include "butspace.h" #include "blendef.h" #include "mydevice.h" diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index f6a27b80733..4b96ef3fdf0 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -48,6 +48,7 @@ struct bPythonConstraint; /* DNA_constraint_types.h */ struct bConstraintOb; /* DNA_constraint_types.h */ struct bConstraintTarget; /* DNA_constraint_types.h*/ struct Script; /* DNA_screen_types.h */ +struct BPyMenu; #ifdef __cplusplus extern "C" { #endif @@ -91,7 +92,9 @@ extern "C" { int BPY_txt_do_python_Text( struct Text *text ); int BPY_menu_do_python( short menutype, int event ); - void BPY_run_python_script( char *filename ); + int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers ); + int BPY_menu_invoke( struct BPyMenu *pym, short menutype ); + void BPY_run_python_script( const char *filename ); int BPY_run_script(struct Script *script); void BPY_free_compiled_text( struct Text *text ); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 69bff059356..041ba069928 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -292,7 +292,7 @@ void syspath_append( char *dirname ) short ok=1; PyErr_Clear( ); - dir = Py_BuildValue( "s", dirname ); + dir = PyString_FromString( dirname ); mod_sys = PyImport_ImportModule( "sys" ); /* new ref */ @@ -308,32 +308,29 @@ void syspath_append( char *dirname ) } if (PySequence_Contains(path, dir)==0) { /* Only add if we need to */ - if (ok && PyList_Append( path, dir ) != 0) + if (ok && PyList_Append( path, dir ) != 0) /* decref below */ ok = 0; /* append failed */ if( (ok==0) || PyErr_Occurred( ) ) Py_FatalError( "could import or build sys.path, can't continue" ); } + Py_DECREF( dir ); Py_XDECREF( mod_sys ); } void init_syspath( int first_time ) { - PyObject *path; PyObject *mod, *d; char *progname; char execdir[FILE_MAXDIR]; /*defines from DNA_space_types.h */ int n; - - - path = Py_BuildValue( "s", bprogname ); mod = PyImport_ImportModule( "Blender.sys" ); if( mod ) { d = PyModule_GetDict( mod ); - EXPP_dict_set_item_str( d, "progname", path ); + EXPP_dict_set_item_str( d, "progname", PyString_FromString( bprogname ) ); Py_DECREF( mod ); } else printf( "Warning: could not set Blender.sys.progname\n" ); @@ -556,6 +553,7 @@ void BPY_Err_Handle( char *script_name ) if( exception && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) { /* no traceback available when SyntaxError */ + PyErr_NormalizeException( &exception, &err, &tb ); PyErr_Restore( exception, err, tb ); /* takes away reference! */ PyErr_Print( ); v = PyObject_GetAttrString( err, "lineno" ); @@ -722,13 +720,23 @@ int BPY_txt_do_python_Text( struct Text *text ) * automatically. The script can be a file or a Blender Text in the current * .blend. ****************************************************************************/ -void BPY_run_python_script( char *fn ) +void BPY_run_python_script( const char *fn ) { + char filename[FILE_MAXDIR + FILE_MAXFILE]; Text *text = NULL; int is_blender_text = 0; - - if (!BLI_exists(fn)) { /* if there's no such filename ... */ - text = G.main->text.first; /* try an already existing Blender Text */ + + BLI_strncpy(filename, fn, FILE_MAXDIR + FILE_MAXFILE); + + if (!BLI_exists(filename)) + BLI_convertstringcwd(filename); + + if (!BLI_exists(filename)) { /* if there's no such filename ... */ + /* try an already existing Blender Text. + * use 'fn' rather then filename for this since were looking for + * internal text + */ + text = G.main->text.first; while (text) { if (!strcmp(fn, text->id.name + 2)) break; @@ -743,11 +751,14 @@ void BPY_run_python_script( char *fn ) } else { - text = add_text(fn); + /* use filename here since we know it exists, + * 'fn' may have been a relative path + */ + text = add_text(filename); if (text == NULL) { printf("\nError in BPY_run_python_script:\n" - "couldn't create Blender text from %s\n", fn); + "couldn't create Blender text from \"%s\"\n", filename); /* Chris: On Windows if I continue I just get a segmentation * violation. To get a baseline file I exit here. */ exit(2); @@ -764,13 +775,8 @@ void BPY_run_python_script( char *fn ) /* We can't simply free the text, since the script might have called * Blender.Load() to load a new .blend, freeing previous data. * So we check if the pointer is still valid. */ - Text *txtptr = G.main->text.first; - while (txtptr) { - if (txtptr == text) { - free_libblock(&G.main->text, text); - break; - } - txtptr = txtptr->id.next; + if (BLI_findindex(&G.main->text, text) != -1) { + free_libblock(&G.main->text, text); } } } @@ -780,9 +786,6 @@ int BPY_run_script(Script *script) PyObject *py_dict, *py_res, *pyarg; Text *text = NULL; BPy_constant *info; - int len; - - FILE *fp = NULL; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -827,12 +830,8 @@ int BPY_run_script(Script *script) Py_INCREF( Py_None ); pyarg = Py_None; } else { - if (BLI_exists(script->scriptname)) { - fp = fopen( script->scriptname, "rb" ); - } - - if( !fp ) { - printf( "Error loading script: couldn't open file %s\n", script->scriptname ); + if (!BLI_exists(script->scriptname)) { + printf( "Script does not exit %s\n", script->scriptname ); free_libblock( &G.main->script, script ); PyGILState_Release(gilstate); return 0; @@ -877,51 +876,17 @@ int BPY_run_script(Script *script) if (text) { py_res = RunPython( text, py_dict ); } else { + char pystring[sizeof(script->scriptname) + 15]; + sprintf(pystring, "execfile(r'%s')", script->scriptname); + py_res = PyRun_String( pystring, Py_file_input, py_dict, py_dict ); + } + + if( !py_res ) { /* Failed execution of the script */ /* Previously we used PyRun_File to run directly the code on a FILE * object, but as written in the Python/C API Ref Manual, chapter 2, * 'FILE structs for different C libraries can be different and * incompatible'. * So now we load the script file data to a buffer */ - char *buffer=NULL, *buffer_ofs=NULL, *b_to, *b_from; - - fseek( fp, 0L, SEEK_END ); - len = ftell( fp ); - fseek( fp, 0L, SEEK_SET ); - - buffer = buffer_ofs = MEM_mallocN( len + 2, "pyfilebuf" ); /* len+2 to add '\n\0' */ - len = fread( buffer, 1, len, fp ); - - buffer[len] = '\n'; /* fix syntax error in files w/o eol */ - buffer[len + 1] = '\0'; - - - /* fast clean-up of dos cr/lf line endings, remove convert '\r\n's to '\n' */ - if (*buffer_ofs == '\r' && *(buffer_ofs+1) == '\n') { - buffer_ofs++; - } - b_from = b_to = buffer_ofs; - - while(*b_from != '\0') { - if (*b_from == '\r' && *( b_from+1 ) == '\n') { - b_from++; - } - if (b_from != b_to) { - *b_to = *b_from; - } - b_to++; - b_from++; - } - *b_to = '\0'; - /* done cleaning the string */ - - fclose( fp ); - - py_res = PyRun_String( buffer_ofs, Py_file_input, py_dict, py_dict ); - MEM_freeN( buffer ); - } - - if( !py_res ) { /* Failed execution of the script */ - BPY_Err_Handle( script->id.name + 2 ); ReleaseGlobalDictionary( py_dict ); script->py_globaldict = NULL; @@ -965,8 +930,38 @@ int BPY_run_script(Script *script) *****************************************************************************/ int BPY_menu_do_python( short menutype, int event ) { - char *argstr = NULL; BPyMenu *pym; + pym = BPyMenu_GetEntry( menutype, ( short ) event ); + return BPY_menu_invoke( pym, menutype ); +} + +/**************************************************************************** +* Description: This function executes the script by its shortcut. +* Notes: It is called by the ui code in src/???.c when a user presses an +* unassigned key combination. Scripts are searched in the BPyMenuTable, +* using the given menutype and event values to know which one to invoke. +*****************************************************************************/ +int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short qual ) +{ + BPyMenu *pym; + pym = BPyMenu_GetEntry( menutype, 0 ); + + while ( pym ) { + if ( pym->key && pym->key == key && pym->qual == qual ) { + return BPY_menu_invoke( pym, menutype ); + } + pym = pym->next; + } + + return 0; +} + +/**************************************************************************** +* Description: This function executes the script described by a menu item. +*****************************************************************************/ +int BPY_menu_invoke( BPyMenu *pym, short menutype ) +{ + char *argstr = NULL; BPySubMenu *pysm; char scriptname[21]; Script *script = NULL; @@ -974,8 +969,6 @@ int BPY_menu_do_python( short menutype, int event ) PyGILState_STATE gilstate; char filestr[FILE_MAX]; - pym = BPyMenu_GetEntry( menutype, ( short ) event ); - if( !pym ) return 0; @@ -1059,6 +1052,7 @@ int BPY_menu_do_python( short menutype, int event ) case PYMENU_RENDER: case PYMENU_WIZARDS: case PYMENU_SCRIPTTEMPLATE: + case PYMENU_TEXTPLUGIN: case PYMENU_MESHFACEKEY: break; diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c index 82da9edbee6..69b50e5c47a 100644 --- a/source/blender/python/BPY_menus.c +++ b/source/blender/python/BPY_menus.c @@ -42,6 +42,7 @@ #endif #include "BKE_global.h" #include "BKE_utildefines.h" +#include "BIF_keyval.h" #include "BLI_blenlib.h" #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" /* for U.pythondir */ @@ -106,6 +107,8 @@ static int bpymenu_group_atoi( char *str ) return PYMENU_ARMATURE; else if( !strcmp( str, "ScriptTemplate" ) ) return PYMENU_SCRIPTTEMPLATE; + else if( !strcmp( str, "TextPlugin" ) ) + return PYMENU_TEXTPLUGIN; else if( !strcmp( str, "MeshFaceKey" ) ) return PYMENU_MESHFACEKEY; else if( !strcmp( str, "AddMesh" ) ) @@ -184,6 +187,9 @@ char *BPyMenu_group_itoa( short menugroup ) case PYMENU_SCRIPTTEMPLATE: return "ScriptTemplate"; break; + case PYMENU_TEXTPLUGIN: + return "TextPlugin"; + break; case PYMENU_MESHFACEKEY: return "MeshFaceKey"; break; @@ -328,6 +334,23 @@ static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip ) return; } +static void bpymenu_set_shortcut( BPyMenu * pymenu, char *combi ) +{ + unsigned short key, qual; + + if( !pymenu ) + return; + + if (!decode_key_string(combi, &key, &qual)) { + return; /* TODO: Print some error */ + } + + pymenu->key = key; + pymenu->qual = qual; + + 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. @@ -688,6 +711,7 @@ void BPyMenu_PrintAllEntries( void ) * # Blender: short int (minimal Blender version) * # Group: 'group name' (defines menu) * # Submenu: 'submenu name' related_1word_arg + * # Shortcut: Modifier+Key (optional shortcut combination for supported groups) * # Tooltip: 'tooltip for the menu' * # \"\"\" * @@ -796,13 +820,19 @@ static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir) if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) { bpymenu_AddSubEntry(scriptMenu, middle, tail); } else { - /* Tooltip: 'tooltip for the menu */ + /* Shortcut: 'key+combination' */ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); - if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) || - (strstr(head, "Tip:") != NULL))) { - bpymenu_set_tooltip(scriptMenu, middle); + if ((matches == 3) && (strstr(head, "Shortcut:") != NULL)) { + bpymenu_set_shortcut(scriptMenu, middle); + } 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; } - parser_state = 0; } break; diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h index 1b557f79286..576d7b8dcd6 100644 --- a/source/blender/python/BPY_menus.h +++ b/source/blender/python/BPY_menus.h @@ -59,6 +59,7 @@ typedef struct BPyMenu { char *name; char *filename; char *tooltip; + unsigned short key, qual; /* Registered shortcut key */ short version; /* Blender version */ int dir; /* 0: default, 1: U.pythondir */ struct BPySubMenu *submenus; @@ -99,6 +100,7 @@ typedef enum { PYMENU_UVCALCULATION, PYMENU_ARMATURE, PYMENU_SCRIPTTEMPLATE, + PYMENU_TEXTPLUGIN, PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/ PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */ PYMENU_HELPWEBSITES,/* Help -> Websites submenu */ diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 0106ab77843..63a1e67236e 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -34,7 +34,7 @@ SET(INC api2_2x ../blenkernel ../blenlib ../blenloader ../render/extern/include ../radiosity/extern/include ../makesdna ../../../intern/guardedalloc ../../../intern/bmfont ../imbuf ../include - ${PYTHON_INC} + ${PYTHON_INC} ../../../extern/glew/include ../gpu ) IF(WITH_QUICKTIME) @@ -50,5 +50,9 @@ IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) +IF(BF_BUILDINFO) + ADD_DEFINITIONS(-DNAN_BUILDINFO) +ENDIF(BF_BUILDINFO) + BLENDERLIB_NOLIST(blender_python "${SRC}" "${INC}") #env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] ) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 481fdcbe13e..27dd510f944 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -6,6 +6,7 @@ sources = Split('BPY_interface.c BPY_menus.c') + env.Glob('api2_2x/*.c') incs = 'api2_2x ../blenkernel ../nodes ../blenlib ../blenloader' incs += ' ../render/extern/include ../radiosity/extern/include' incs += ' ../makesdna #intern/guardedalloc #intern/bmfont ../imbuf ../include' +incs += ' #extern/glew/include ../gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] @@ -23,4 +24,7 @@ if env['WITH_BF_OPENEXR'] == 1: if env['WITH_BF_FFMPEG'] == 1: defs.append('WITH_FFMPEG') +if env['BF_BUILDINFO'] == 1: + defs.append('NAN_BUILDINFO') + env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] ) diff --git a/source/blender/python/api2_2x/BGL.h b/source/blender/python/api2_2x/BGL.h index ce972795322..461f5bc9372 100644 --- a/source/blender/python/api2_2x/BGL.h +++ b/source/blender/python/api2_2x/BGL.h @@ -323,8 +323,13 @@ typedef struct _Buffer { #define ret_def_GLstring const unsigned char *ret_str; #define ret_set_GLstring ret_str= -#define ret_ret_GLstring return PyString_FromString(ret_str); - +#define ret_ret_GLstring \ + if (ret_str) {\ + return PyString_FromString(ret_str);\ + } else {\ + PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\ + return NULL;\ + } #endif /* EXPP_BGL_H */ diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 2b190a6c828..47e7bcb2007 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -34,7 +34,7 @@ struct ID; /*keep me up here */ /* for open, close in Blender_Load */ #include #include "BDR_editobject.h" /* exit_editmode() */ -#include "BDR_drawmesh.h" /* set_mipmap() */ +#include "GPU_draw.h" /* GPU_set_mipmap() */ #include "BIF_usiblender.h" #include "BLI_blenlib.h" #include "BLI_bpath.h" @@ -314,8 +314,8 @@ static PyObject *Blender_Set( PyObject * self, PyObject * args ) else U.gameflags |= USER_DISABLE_MIPMAP; - set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); - }else + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + } else return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "value given is not a blender setting" ) ); Py_RETURN_NONE; @@ -543,7 +543,21 @@ static PyObject *Blender_Get( PyObject * self, PyObject * value ) } /* End 'quick hack' part. */ else if(StringEqual( str, "version" )) ret = PyInt_FromLong( G.version ); - + else if(StringEqual( str, "buildinfo" )) { +#ifdef NAN_BUILDINFO + char buffer[1024]; + extern char * build_date; + extern char * build_time; + extern char * build_rev; + extern char * build_platform; + extern char * build_type; + + sprintf(buffer, "Built on %s %s, Rev-%s Version %s %s", build_date, build_time, build_rev, build_platform, build_type); + ret = PyString_FromString( buffer ); +#else + ret = PyString_FromString( "No Build Info" ); +#endif + } else if(StringEqual( str, "compressfile" )) ret = PyInt_FromLong( (U.flag & USER_FILECOMPRESS) >> 15 ); else if(StringEqual( str, "mipmap" )) diff --git a/source/blender/python/api2_2x/Camera.c b/source/blender/python/api2_2x/Camera.c index b35fcf410a4..87c605ef612 100644 --- a/source/blender/python/api2_2x/Camera.c +++ b/source/blender/python/api2_2x/Camera.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" /* for M_PI */ #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "gen_utils.h" diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index a62a5ee7ed8..b0b9aa04a08 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -44,6 +44,7 @@ #include "BKE_constraint.h" #include "BLI_blenlib.h" #include "BIF_editconstraint.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" @@ -441,7 +442,7 @@ static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * value ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "constraint doesn't belong to anything" ); } - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index bd19a6a6a3e..b04366d5579 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -928,6 +928,11 @@ static PyObject *Method_Register( PyObject * self, PyObject * args ) Script *script; int startspace = 0; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Register() in background mode." ); + } + if( !PyArg_ParseTuple ( args, "O|OO", &newdrawc, &neweventc, &newbuttonc ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1008,6 +1013,10 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) { int after = 0; + if (G.background) { + Py_RETURN_NONE; + } + if( !PyArg_ParseTuple( args, "|i", &after ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected int argument (or nothing)" ); @@ -1022,6 +1031,10 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) static PyObject *Method_Draw( PyObject * self ) { + if (G.background) { + Py_RETURN_NONE; + } + /*@ If forced drawing is disable queue a redraw event instead */ if( EXPP_disable_force_draw ) { scrarea_queue_winredraw( curarea ); @@ -1089,6 +1102,11 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args ) PyObject *result = NULL; ListBase listb= {NULL, NULL}; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.UIBlock() in background mode." ); + } + if ( !PyArg_ParseTuple( args, "O", &val ) || !PyCallable_Check( val ) ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected 1 python function and 2 ints" ); @@ -1201,6 +1219,11 @@ static PyObject *Method_Button( PyObject * self, PyObject * args ) int x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Button() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiii|sO", &name, &event, &x, &y, &w, &h, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1225,6 +1248,11 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Menu() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1255,6 +1283,11 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Toggle() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1322,6 +1355,11 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args ) PyObject *mino, *maxo, *inio; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Sider() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiiOOO|isO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip, &callback ) ) @@ -1395,6 +1433,11 @@ static PyObject *Method_Scrollbar( PyObject * self, PyObject * args ) float ini, min, max; uiBut *ubut; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Scrollbar() in background mode." ); + } + if( !PyArg_ParseTuple( args, "iiiiiOOO|isO", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1454,6 +1497,11 @@ static PyObject *Method_ColorPicker( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.ColorPicker() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1504,6 +1552,11 @@ static PyObject *Method_Normal( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Normal() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1546,6 +1599,11 @@ static PyObject *Method_Number( PyObject * self, PyObject * args ) PyObject *callback=NULL; uiBut *ubut= NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Number() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiiOOO|sO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1617,6 +1675,11 @@ static PyObject *Method_String( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.String() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiisi|sO", &info_arg, &event, &x, &y, &w, &h, &newstr, &len, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1693,6 +1756,11 @@ static PyObject *Method_Text( PyObject * self, PyObject * args ) char *font_str = NULL; struct BMF_Font *font; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Text() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|s", &text, &font_str ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected one or two string arguments" ); @@ -1724,6 +1792,11 @@ static PyObject *Method_Label( PyObject * self, PyObject * args ) char *text; int x, y, w, h; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Label() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiii", &text, &x, &y, &w, &h ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and four ints" ); @@ -1740,7 +1813,12 @@ static PyObject *Method_PupMenu( PyObject * self, PyObject * args ) char *text; int maxrow = -1; PyObject *ret; - + + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupMenu() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|i", &text, &maxrow ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and optionally an int as arguments" ); @@ -1827,6 +1905,11 @@ static PyObject *Method_PupTreeMenu( PyObject * self, PyObject * args ) ListBase storage = {NULL, NULL}; TBitem *tb; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupMenuTree() in background mode." ); + } + if( !PyArg_ParseTuple( args, "O!", &PyList_Type, ¤t_menu ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "Expected a list" ); @@ -1857,6 +1940,11 @@ static PyObject *Method_PupIntInput( PyObject * self, PyObject * args ) short var = 0; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupIntInput() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|hii", &text, &var, &min, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 1 string and 3 int arguments" ); @@ -1879,6 +1967,11 @@ static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args ) float min = 0, max = 1, var = 0, a1 = 10, a2 = 2; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupFloatInput() in background mode." ); + } + if( !PyArg_ParseTuple ( args, "s|fffff", &text, &var, &min, &max, &a1, &a2 ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1903,6 +1996,11 @@ static PyObject *Method_PupStrInput( PyObject * self, PyObject * args ) char max = 20; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupStrInput() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ss|b", &textMsg, &text, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 strings and 1 int" ); @@ -1937,6 +2035,11 @@ static PyObject *Method_PupBlock( PyObject * self, PyObject * args ) int len, i; char *title; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupBlock() in background mode." ); + } + if (!PyArg_ParseTuple( args, "sO", &title, &pyList ) || !PySequence_Check( pyList )) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and a sequence" ); @@ -2070,6 +2173,11 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) int clipX = 0, clipY = 0, clipW = -1, clipH = -1; /*GLfloat scissorBox[4];*/ + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Image() in background mode." ); + } + /* parse the arguments passed-in from Python */ if( !PyArg_ParseTuple( args, "O!ff|ffiiii", &Image_Type, &pyObjImage, &originX, &originY, &zoomX, &zoomY, diff --git a/source/blender/python/api2_2x/Group.c b/source/blender/python/api2_2x/Group.c index 3e7f02c3797..3152d3a973f 100644 --- a/source/blender/python/api2_2x/Group.c +++ b/source/blender/python/api2_2x/Group.c @@ -46,6 +46,8 @@ #include "gen_utils.h" #include "gen_library.h" +#include "vector.h" + /* checks for the group being removed */ #define GROUP_DEL_CHECK_PY(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Group has been removed" ) ) #define GROUP_DEL_CHECK_INT(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Group has been removed" ) ) @@ -200,6 +202,31 @@ static int Group_setObjects( BPy_Group * self, PyObject * args ) return 0; } +static PyObject *Group_getDupliOfs( BPy_Group * self ) +{ + GROUP_DEL_CHECK_PY(self); + return newVectorObject( self->group->dupli_ofs, 3, Py_WRAP ); +} + +static int Group_setDupliOfs( BPy_Group * self, PyObject * value ) +{ + VectorObject *bpy_vec; + GROUP_DEL_CHECK_INT(self); + if (!VectorObject_Check(value)) + return ( EXPP_ReturnIntError( PyExc_TypeError, + "expected a vector" ) ); + + bpy_vec = (VectorObject *)value; + + if (bpy_vec->size != 3) + return ( EXPP_ReturnIntError( PyExc_ValueError, + "can only assign a 3D vector" ) ); + + self->group->dupli_ofs[0] = bpy_vec->vec[0]; + self->group->dupli_ofs[1] = bpy_vec->vec[1]; + self->group->dupli_ofs[2] = bpy_vec->vec[2]; + return 0; +} /*****************************************************************************/ @@ -251,6 +278,10 @@ static PyGetSetDef BPy_Group_getseters[] = { (getter)Group_getObjects, (setter)Group_setObjects, "objects in this group", NULL}, + {"dupliOffset", + (getter)Group_getDupliOfs, (setter)Group_setDupliOfs, + "offset to use when instancing this group as a DupliGroup", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; diff --git a/source/blender/python/api2_2x/Image.c b/source/blender/python/api2_2x/Image.c index 94da5a77170..5ef2cbadbdc 100644 --- a/source/blender/python/api2_2x/Image.c +++ b/source/blender/python/api2_2x/Image.c @@ -29,7 +29,6 @@ */ #include "Image.h" /*This must come first */ -#include "BDR_drawmesh.h" /* free_realtime_image */ #include "BKE_main.h" #include "BKE_global.h" #include "BKE_library.h" @@ -48,6 +47,7 @@ #include "BKE_icons.h" #include "IMB_imbuf.h" #include "IDProp.h" +#include "GPU_draw.h" /* used so we can get G.scene->r.cfra for getting the current image frame, some images change frame if they are a sequence */ @@ -1003,7 +1003,7 @@ static PyObject *Image_glFree( BPy_Image * self ) { Image *image = self->image; - free_realtime_image( image ); + GPU_free_image( image ); /* remove the nocollect flag, image is available for garbage collection again */ image->flag &= ~IMA_NOCOLLECT; Py_RETURN_NONE; diff --git a/source/blender/python/api2_2x/Ipo.c b/source/blender/python/api2_2x/Ipo.c index 68768fc9346..7c2e18bcdf6 100644 --- a/source/blender/python/api2_2x/Ipo.c +++ b/source/blender/python/api2_2x/Ipo.c @@ -36,6 +36,7 @@ #include "BKE_object.h" #include "BKE_ipo.h" #include "BLI_blenlib.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Ipocurve.c b/source/blender/python/api2_2x/Ipocurve.c index b9bfb77d19e..4a8cba30e8e 100644 --- a/source/blender/python/api2_2x/Ipocurve.c +++ b/source/blender/python/api2_2x/Ipocurve.c @@ -35,6 +35,7 @@ #include "BKE_depsgraph.h" #include "BKE_ipo.h" #include "BKE_utildefines.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 53d25a6429d..38968b64cf5 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -34,15 +34,19 @@ #include "BKE_global.h" #include "BKE_object.h" #include "BKE_library.h" +#include "BKE_texture.h" #include "BLI_blenlib.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "mydevice.h" #include "Ipo.h" +#include "MTex.h" #include "constant.h" #include "gen_utils.h" #include "gen_library.h" #include "BKE_utildefines.h" +#include "MEM_guardedalloc.h" /*****************************************************************************/ /* Python BPy_Lamp defaults: */ @@ -84,6 +88,8 @@ #define EXPP_LAMP_MODE_NODIFFUSE 2048 #define EXPP_LAMP_MODE_NOSPECULAR 4096 #define EXPP_LAMP_MODE_SHAD_RAY 8192 +#define EXPP_LAMP_MODE_LAYER_SHADOW 32768 + /* Lamp MIN, MAX values */ #define EXPP_LAMP_SAMPLES_MIN 1 @@ -204,6 +210,7 @@ static PyObject *Lamp_getQuad2( BPy_Lamp * self ); static PyObject *Lamp_getCol( BPy_Lamp * self ); static PyObject *Lamp_getIpo( BPy_Lamp * self ); static PyObject *Lamp_getComponent( BPy_Lamp * self, void * closure ); +static PyObject *Lamp_getTextures( BPy_Lamp * self ); static PyObject *Lamp_clearIpo( BPy_Lamp * self ); static PyObject *Lamp_insertIpoKey( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_oldsetIpo( BPy_Lamp * self, PyObject * args ); @@ -251,6 +258,7 @@ static int Lamp_setHaloInt( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad1( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad2( BPy_Lamp * self, PyObject * args ); static int Lamp_setCol( BPy_Lamp * self, PyObject * args ); +static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_getScriptLinks( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_addScriptLink( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ); @@ -498,6 +506,10 @@ static PyGetSetDef BPy_Lamp_getseters[] = { (getter)Lamp_getComponent, (setter)Lamp_setComponent, "Lamp color blue component", (void *)EXPP_LAMP_COMP_B}, + {"textures", + (getter)Lamp_getTextures, (setter)Lamp_setTextures, + "The Lamp's texture list as a tuple", + NULL}, {"Modes", (getter)Lamp_getModesConst, (setter)NULL, "Dictionary of values for 'mode' attribute", @@ -780,6 +792,8 @@ static PyObject *Lamp_ModesDict( void ) PyInt_FromLong( EXPP_LAMP_MODE_NOSPECULAR ) ); PyConstant_Insert( c, "RayShadow", PyInt_FromLong( EXPP_LAMP_MODE_SHAD_RAY ) ); + PyConstant_Insert( c, "LayerShadow", + PyInt_FromLong( EXPP_LAMP_MODE_LAYER_SHADOW ) ); } return Modes; @@ -1011,8 +1025,8 @@ static int Lamp_setType( BPy_Lamp * self, PyObject * value ) static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) { - short param; - static short bitmask = EXPP_LAMP_MODE_SHADOWS + int param; + static int bitmask = EXPP_LAMP_MODE_SHADOWS | EXPP_LAMP_MODE_HALO | EXPP_LAMP_MODE_LAYER | EXPP_LAMP_MODE_QUAD @@ -1022,14 +1036,15 @@ static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) | EXPP_LAMP_MODE_SQUARE | EXPP_LAMP_MODE_NODIFFUSE | EXPP_LAMP_MODE_NOSPECULAR - | EXPP_LAMP_MODE_SHAD_RAY; + | EXPP_LAMP_MODE_SHAD_RAY + | EXPP_LAMP_MODE_LAYER_SHADOW; if( !PyInt_Check ( value ) ) { char errstr[128]; sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask ); return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - param = (short)PyInt_AS_LONG ( value ); + param = PyInt_AS_LONG ( value ); if ( ( param & bitmask ) != param ) return EXPP_ReturnIntError( PyExc_ValueError, @@ -1373,7 +1388,8 @@ static PyObject *Lamp_getModesConst( void ) EXPP_LAMP_MODE_SQUARE, "NoDiffuse", EXPP_LAMP_MODE_NODIFFUSE, "NoSpecular", EXPP_LAMP_MODE_NOSPECULAR, "RayShadow", - EXPP_LAMP_MODE_SHAD_RAY); + EXPP_LAMP_MODE_SHAD_RAY, "LayerShadow", + EXPP_LAMP_MODE_LAYER_SHADOW); } static PyObject *Lamp_getTypesConst( void ) @@ -1387,6 +1403,100 @@ static PyObject *Lamp_getTypesConst( void ) "Photon", EXPP_LAMP_TYPE_YF_PHOTON ); } +static PyObject *Lamp_getTextures( BPy_Lamp * self ) +{ + int i; + PyObject *tuple; + + /* build a texture list */ + tuple = PyTuple_New( MAX_MTEX ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->lamp->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_LA ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } + + return tuple; +} + +static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_LA ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing lamp MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->lamp->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->lamp->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->lamp->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->lamp->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} + /* #####DEPRECATED###### */ static PyObject *Lamp_oldsetSamples( BPy_Lamp * self, PyObject * args ) @@ -1597,6 +1707,8 @@ static PyObject *Lamp_oldsetMode( BPy_Lamp * self, PyObject * args ) flag |= ( short ) EXPP_LAMP_MODE_NOSPECULAR; else if( !strcmp( name, "RayShadow" ) ) flag |= ( short ) EXPP_LAMP_MODE_SHAD_RAY; + else if( !strcmp( name, "LayerShadow" ) ) + flag |= ( short ) EXPP_LAMP_MODE_LAYER_SHADOW; else return EXPP_ReturnPyObjError( PyExc_AttributeError, "unknown lamp flag argument" ); diff --git a/source/blender/python/api2_2x/MTex.c b/source/blender/python/api2_2x/MTex.c index b9a8f7fff65..4db9715a465 100644 --- a/source/blender/python/api2_2x/MTex.c +++ b/source/blender/python/api2_2x/MTex.c @@ -22,10 +22,11 @@ * * This is a new part of Blender. * - * Contributor(s): Alex Mole, Yehoshua Sapir + * Contributor(s): Alex Mole, Yehoshua Sapir, Ken Hughes * * ***** END GPL LICENSE BLOCK ***** */ + #include "MTex.h" /*This must come first*/ #include "BKE_utildefines.h" @@ -35,7 +36,8 @@ #include "gen_utils.h" #include "gen_library.h" -#include +#include "DNA_material_types.h" +#include "DNA_world_types.h" /*****************************************************************************/ /* Python BPy_MTex methods declarations: */ @@ -94,6 +96,7 @@ MTEXGETSET(ProjX) MTEXGETSET(ProjY) MTEXGETSET(ProjZ) MTEXGETSET(MapToFlag) +MTEXGETSET(WorldMapToFlag) /*****************************************************************************/ /* Python get/set methods table */ @@ -154,8 +157,14 @@ static PyGetSetDef MTex_getseters[] = { "Projection of Y axis to Texture space", NULL }, { "zproj", (getter) MTex_getProjZ, (setter) MTex_setProjZ, "Projection of Z axis to Texture space", NULL }, + + /* MapTo for Material and Lamp MTex */ + { "mtCol", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to color", (void*) MAP_COL }, + + /* MapTo for Material MTex */ + { "mtNor", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to normals", (void*) MAP_NORM }, { "mtCsp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, @@ -182,6 +191,18 @@ static PyGetSetDef MTex_getseters[] = { "How texture maps to displacement", (void*) MAP_DISPLACE }, { "mtWarp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to warp", (void*) MAP_WARP }, + + /* MapTo for World MTex */ + + { "mtBlend", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color progression of background", (void*) WOMAP_BLEND }, + { "mtHoriz", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the horizon", (void*) WOMAP_HORIZ }, + { "mtZenUp", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the zenith above", (void*) WOMAP_ZENUP }, + { "mtZenDown", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the zenith below", (void*) WOMAP_ZENDOWN }, + { NULL, NULL, NULL, NULL, NULL } }; @@ -252,7 +273,7 @@ PyObject *MTex_Init( void ) return submodule; } -PyObject *MTex_CreatePyObject( MTex * mtex ) +PyObject *MTex_CreatePyObject( MTex * mtex, unsigned short type ) { BPy_MTex *pymtex; @@ -262,6 +283,7 @@ PyObject *MTex_CreatePyObject( MTex * mtex ) "couldn't create BPy_MTex PyObject" ); pymtex->mtex = mtex; + pymtex->type = type; return ( PyObject * ) pymtex; } @@ -286,7 +308,12 @@ static int MTex_compare( BPy_MTex * a, BPy_MTex * b ) static PyObject *MTex_repr( BPy_MTex * self ) { - return PyString_FromFormat( "[MTex]" ); + if( self->type == ID_MA ) + return PyString_FromFormat( "[MTex (Material)]" ); + else if( self->type == ID_LA ) + return PyString_FromFormat( "[MTex (Lamp)]" ); + else + return PyString_FromFormat( "[MTex (World)]" ); } @@ -316,19 +343,37 @@ static int MTex_setTexCo( BPy_MTex *self, PyObject *value, void *closure) { int texco; - if( !PyInt_Check( value ) ) { + if( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.TexCo dictionary" ); - } texco = PyInt_AsLong( value ) ; - if (texco != TEXCO_ORCO && texco != TEXCO_REFL && texco != TEXCO_NORM && - texco != TEXCO_GLOB && texco != TEXCO_UV && texco != TEXCO_OBJECT && - texco != TEXCO_STRESS && texco != TEXCO_TANGENT && texco != TEXCO_WINDOW && - texco != TEXCO_VIEW && texco != TEXCO_STICKY ) - return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be a member of Texture.TexCo dictionary" ); + switch ( self->type ) { + case ID_MA : + if( texco != TEXCO_ORCO && texco != TEXCO_REFL && + texco != TEXCO_NORM && texco != TEXCO_GLOB && + texco != TEXCO_UV && texco != TEXCO_OBJECT && + texco != TEXCO_STRESS && texco != TEXCO_TANGENT && + texco != TEXCO_WINDOW && texco != TEXCO_VIEW && + texco != TEXCO_STICKY ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + case ID_LA : + if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && + texco != TEXCO_OBJECT ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + default: /* ID_WO */ + if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && + texco != TEXCO_ANGMAP && texco != TEXCO_OBJECT && + texco != TEXCO_H_SPHEREMAP && texco != TEXCO_H_TUBEMAP ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + } self->mtex->texco = (short)texco; @@ -350,6 +395,10 @@ static int MTex_setObject( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getUVLayer( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a Material MTex object" ); + return PyString_FromString(self->mtex->uvname); } @@ -364,6 +413,10 @@ static int MTex_setUVLayer( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapTo( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a Material MTex object" ); + return PyInt_FromLong( self->mtex->mapto ); } @@ -371,18 +424,20 @@ static int MTex_setMapTo( BPy_MTex *self, PyObject *value, void *closure) { int mapto; - if( !PyInt_Check( value ) ) { + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + + if( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "expected an int" ); - } + "expected an int" ); mapto = PyInt_AsLong( value ); /* This method is deprecated anyway. */ - if ( mapto < 0 || mapto > 16383 ) { + if ( mapto < 0 || mapto > 16383 ) return EXPP_ReturnIntError( PyExc_ValueError, "Value must be a sum of values from Texture.MapTo dictionary" ); - } self->mtex->mapto = (short)mapto; @@ -400,11 +455,9 @@ static int MTex_setCol( BPy_MTex *self, PyObject *value, void *closure) float rgb[3]; int i; - if( !PyArg_ParseTuple( value, "fff", - &rgb[0], &rgb[1], &rgb[2] ) ) - + if( !PyArg_ParseTuple( value, "fff", &rgb[0], &rgb[1], &rgb[2] ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple of 3 floats" ); + "expected tuple of 3 floats" ); for( i = 0; i < 3; ++i ) if( rgb[i] < 0 || rgb[i] > 1 ) @@ -453,18 +506,13 @@ static int MTex_setBlendMode( BPy_MTex *self, PyObject *value, void *closure) if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "Value must be member of Texture.BlendModes dictionary" ); + "Value must be member of Texture.BlendModes dictionary" ); n = PyInt_AsLong(value); -/* if (n != MTEX_BLEND && n != MTEX_MUL && n != MTEX_ADD && - n != MTEX_SUB && n != MTEX_DIV && n != MTEX_DARK && - n != MTEX_DIFF && n != MTEX_LIGHT && n != MTEX_SCREEN)*/ if (n < 0 || n > 8) - { return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be member of Texture.BlendModes dictionary" ); - } + "Value must be member of Texture.BlendModes dictionary" ); self->mtex->blendtype = (short)n; @@ -478,117 +526,84 @@ static PyObject *MTex_getColFac( BPy_MTex *self, void *closure ) static int MTex_setColFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; - - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->colfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->colfac, 0.0f, 1.0f ); } static PyObject *MTex_getNorFac( BPy_MTex *self, void *closure ) { + if( self->type == ID_LA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material or world MTex object" ); + return PyFloat_FromDouble(self->mtex->norfac); } static int MTex_setNorFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; - - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 25) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,25]" ); - - self->mtex->norfac = f; - - return 0; + switch( self->type ) + { + case ID_WO: + return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 1.0f ); + case ID_MA: + return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 25.0f ); + default: + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material or world MTex object" ); + } } static PyObject *MTex_getVarFac( BPy_MTex *self, void *closure ) { + if( self->type == ID_LA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material or world MTex object" ); + return PyFloat_FromDouble(self->mtex->varfac); } static int MTex_setVarFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type == ID_LA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material or world MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->varfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->varfac, 0.0f, 1.0f ); } static PyObject *MTex_getDispFac( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyFloat_FromDouble(self->mtex->dispfac); } static int MTex_setDispFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->dispfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->dispfac, 0.0f, 1.0f ); } static PyObject *MTex_getWarpFac( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyFloat_FromDouble(self->mtex->warpfac); } static int MTex_setWarpFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->warpfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->warpfac, 0.0f, 1.0f ); } static PyObject *MTex_getOfs( BPy_MTex *self, void *closure ) @@ -601,16 +616,24 @@ static int MTex_setOfs( BPy_MTex *self, PyObject *value, void *closure) { float f[3]; int i; + float max; if( !PyArg_ParseTuple( value, "fff", &f[0], &f[1], &f[2] ) ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected tuple of 3 floats" ); + if( self->type == ID_MA ) + max = 10.0f; + else + max = 20.0f; + for( i = 0; i < 3; ++i ) - if( f[i] < -10 || f[i] > 10 ) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [-10,10]" ); + if( f[i] < -max || f[i] > max ) { + char errstr[64]; + sprintf( errstr, "values must be in range [-%6.0f,%6.0f]", + max, max ); + return EXPP_ReturnIntError( PyExc_ValueError, errstr ); + } self->mtex->ofs[0] = f[0]; self->mtex->ofs[1] = f[1]; @@ -649,6 +672,10 @@ static int MTex_setSize( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapping( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->mapping ); } @@ -656,6 +683,11 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) { int n; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + + if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be member of Texture.Mappings dictionary" ); @@ -664,8 +696,7 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) /* if (n != MTEX_FLAT && n != MTEX_TUBE && n != MTEX_CUBE && n != MTEX_SPHERE) */ - if (n < 0 || n > 3) - { + if (n < 0 || n > 3) { return EXPP_ReturnIntError( PyExc_ValueError, "Value must be member of Texture.Mappings dictionary" ); } @@ -677,25 +708,43 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getFlag( BPy_MTex *self, void *closure ) { - return PyBool_FromLong( self->mtex->texflag & ((int) closure) ); + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_MA && + flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "attribute only vaild for material MTex object" ); + + return PyBool_FromLong( self->mtex->texflag & flag ); } static int MTex_setFlag( BPy_MTex *self, PyObject *value, void *closure) { + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_MA && + flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute only vaild for material MTex object" ); + if ( !PyBool_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected a bool"); if ( value == Py_True ) - self->mtex->texflag |= (int)closure; + self->mtex->texflag |= flag; else - self->mtex->texflag &= ~((int) closure); + self->mtex->texflag &= ~flag; return 0; } static PyObject *MTex_getProjX( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projx ); } @@ -703,6 +752,10 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -722,6 +775,10 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getProjY( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projy ); } @@ -729,6 +786,10 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -748,6 +809,10 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) static PyObject *MTex_getProjZ( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projz ); } @@ -755,6 +820,10 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -774,29 +843,45 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapToFlag( BPy_MTex *self, void *closure ) { - int flag = (int) closure; + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type == ID_LA && flag != MAP_COL ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "attribute not available for a lamp MTex" ); if ( self->mtex->mapto & flag ) - { return PyInt_FromLong( ( self->mtex->maptoneg & flag ) ? -1 : 1 ); - } else { + else return PyInt_FromLong( 0 ); - } +} + +static PyObject *MTex_getWorldMapToFlag( BPy_MTex *self, void *closure ) +{ + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_WO ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a world MTex object" ); + + return PyInt_FromLong( (long)( (self->mtex->mapto & flag) != 0 ) ); } static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) { - int flag = (int) closure; + int flag = GET_INT_FROM_POINTER(closure); int intVal; + if( self->type == ID_LA && flag != MAP_COL ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute not available for a lamp MTex" ); + if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected an int"); - intVal = PyInt_AsLong( value ); + intVal = PyInt_AsLong( value ) ; - if (flag == MAP_COL || flag == MAP_COLSPEC || flag == MAP_COLMIR || - flag == MAP_WARP) { + if( flag & ( MAP_COL | MAP_COLSPEC | MAP_COLMIR | MAP_WARP ) ) { if (intVal < 0 || intVal > 1) { return EXPP_ReturnIntError( PyExc_ValueError, "value for that mapping must be 0 or 1" ); @@ -828,3 +913,31 @@ static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) return 0; } + +static int MTex_setWorldMapToFlag( BPy_MTex *self, PyObject *value, void *closure) +{ + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_WO ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute only available for a world MTex" ); + + if ( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected an int"); + + switch( PyInt_AsLong( value ) ) { + case 0: + self->mtex->mapto &= ~flag; + break; + case 1: + self->mtex->mapto |= flag; + break; + default: + return EXPP_ReturnIntError( PyExc_ValueError, + "value for mapping must be 0 or 1" ); + } + + return 0; +} + diff --git a/source/blender/python/api2_2x/MTex.h b/source/blender/python/api2_2x/MTex.h index 5e67ebc47ca..b6c98a40d2e 100644 --- a/source/blender/python/api2_2x/MTex.h +++ b/source/blender/python/api2_2x/MTex.h @@ -38,22 +38,26 @@ /* Python BPy_MTex structure definition */ /*****************************************************************************/ +#define MATERIAL_MTEX_TYPE 1 +#define WORLD_MTEX_TYPE 2 +#define LAMP_MTEX_TYPE 3 + typedef struct { PyObject_HEAD MTex * mtex; + unsigned short type; } BPy_MTex; extern PyTypeObject MTex_Type; #define BPy_MTex_Check(v) ((v)->ob_type == &MTex_Type) - /*****************************************************************************/ /* Module Blender.Texture.MTex - public functions */ /*****************************************************************************/ PyObject *MTex_Init( void ); -PyObject *MTex_CreatePyObject( struct MTex *obj ); +PyObject *MTex_CreatePyObject( struct MTex *obj, unsigned short type ); MTex *MTex_FromPyObject( PyObject * py_obj ); diff --git a/source/blender/python/api2_2x/Makefile b/source/blender/python/api2_2x/Makefile index 7c831952042..a2b77bf8c98 100644 --- a/source/blender/python/api2_2x/Makefile +++ b/source/blender/python/api2_2x/Makefile @@ -37,6 +37,10 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) +ifdef NAN_BUILDINFO + CPPFLAGS += -DNAN_BUILDINFO +endif + ifeq ($(WITH_FFMPEG), true) CPPFLAGS += -DWITH_FFMPEG endif @@ -45,6 +49,7 @@ ifeq ($(WITH_OPENEXR),true) CPPFLAGS += -DWITH_OPENEXR endif +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../makesdna @@ -52,6 +57,7 @@ CPPFLAGS += -I../../blenkernel CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader CPPFLAGS += -I../../include +CPPFLAGS += -I../../gpu CPPFLAGS += -I../../render/extern/include CPPFLAGS += -I../../radiosity/extern/include CPPFLAGS += -I$(NAN_BMFONT)/include diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 20747a167e6..b118bdb30e7 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -37,11 +37,13 @@ #include "BKE_library.h" #include "BKE_material.h" #include "BKE_texture.h" +#include "BKE_node.h" #include "BKE_idprop.h" #include "BKE_utildefines.h" /* for CLAMP */ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "constant.h" @@ -154,6 +156,8 @@ #define EXPP_MAT_SPECTRANS_MAX 1.0 #define EXPP_MAT_MIRRTRANSADD_MIN 0.0 #define EXPP_MAT_MIRRTRANSADD_MAX 1.0 +#define EXPP_MAT_COLORBAND_FACTOR_MIN 0.0 +#define EXPP_MAT_COLORBAND_FACTOR_MAX 1.0 /* closure values for getColorComponent()/setColorComponent() */ @@ -402,19 +406,62 @@ static PyObject *Material_ShadersDict( void ) return Shaders; } +static PyObject *Material_ColorRampMethodsDict( void ) +{ + PyObject *Methods = PyConstant_New( ); + if( Methods ) { + BPy_constant *c = (BPy_constant * ) Methods; + + PyConstant_Insert(c, "BLEND", PyInt_FromLong(MA_RAMP_BLEND)); + PyConstant_Insert(c, "MIX", PyInt_FromLong(MA_RAMP_BLEND)); /* This one is added to solve confusion between Blend-Mix name. */ + PyConstant_Insert(c, "ADD", PyInt_FromLong(MA_RAMP_ADD)); + PyConstant_Insert(c, "MULT", PyInt_FromLong(MA_RAMP_MULT)); + PyConstant_Insert(c, "SUB", PyInt_FromLong(MA_RAMP_SUB)); + PyConstant_Insert(c, "SCREEN", PyInt_FromLong(MA_RAMP_SCREEN)); + PyConstant_Insert(c, "DIV", PyInt_FromLong(MA_RAMP_DIV)); + PyConstant_Insert(c, "DIFF", PyInt_FromLong(MA_RAMP_DIFF)); + PyConstant_Insert(c, "DARK", PyInt_FromLong(MA_RAMP_DARK)); + PyConstant_Insert(c, "LIGHT", PyInt_FromLong(MA_RAMP_LIGHT)); + PyConstant_Insert(c, "OVERLAY", PyInt_FromLong(MA_RAMP_OVERLAY)); + PyConstant_Insert(c, "DODGE", PyInt_FromLong(MA_RAMP_DODGE)); + PyConstant_Insert(c, "BURN", PyInt_FromLong(MA_RAMP_BURN)); + PyConstant_Insert(c, "HUE", PyInt_FromLong(MA_RAMP_HUE)); + PyConstant_Insert(c, "SAT", PyInt_FromLong(MA_RAMP_SAT)); + PyConstant_Insert(c, "VAL", PyInt_FromLong(MA_RAMP_VAL)); + PyConstant_Insert(c, "COLOR", PyInt_FromLong(MA_RAMP_COLOR)); + + } + return Methods; +} + +static PyObject *Material_ColorRampInputDict( void ) +{ + PyObject *Inputs = PyConstant_New( ); + if( Inputs ) { + BPy_constant *c = (BPy_constant * ) Inputs; + + PyConstant_Insert(c, "SHADER", PyInt_FromLong(MA_RAMP_IN_SHADER)); + PyConstant_Insert(c, "ENERGY", PyInt_FromLong(MA_RAMP_IN_ENERGY)); + PyConstant_Insert(c, "NORMAL", PyInt_FromLong(MA_RAMP_IN_NOR)); + PyConstant_Insert(c, "RESULT", PyInt_FromLong(MA_RAMP_IN_RESULT)); + } + return Inputs; +} /*****************************************************************************/ /* Function: Material_Init */ /*****************************************************************************/ PyObject *Material_Init( void ) { - PyObject *submodule, *Modes, *Shaders; + PyObject *submodule, *Modes, *Shaders, *ColorbandInput, *ColorbandMethod; if( PyType_Ready( &Material_Type ) < 0) return NULL; Modes = Material_ModesDict( ); Shaders = Material_ShadersDict( ); + ColorbandMethod = Material_ColorRampMethodsDict( ); + ColorbandInput = Material_ColorRampInputDict( ); submodule = Py_InitModule3( "Blender.Material", M_Material_methods, M_Material_doc ); @@ -423,6 +470,10 @@ PyObject *Material_Init( void ) PyModule_AddObject( submodule, "Modes", Modes ); if( Shaders ) PyModule_AddObject( submodule, "Shaders", Shaders ); + if( ColorbandMethod ) + PyModule_AddObject( submodule, "ColorbandMethod", ColorbandMethod ); + if( ColorbandInput ) + PyModule_AddObject( submodule, "ColorbandInput", ColorbandInput ); PyModule_AddIntConstant( submodule, "RGB", IPOKEY_RGB ); PyModule_AddIntConstant( submodule, "ALPHA", IPOKEY_ALPHA ); @@ -555,6 +606,7 @@ static int Material_setSssFront( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setTexChannel( BPy_Material * self, PyObject * value ); +static int Material_setTextures( BPy_Material * self, PyObject * value ); static PyObject *Material_getColorComponent( BPy_Material * self, void * closure ); @@ -648,6 +700,21 @@ static PyObject *Material_insertIpoKey( BPy_Material * self, PyObject * args ); static PyObject *Material_getColorband( BPy_Material * self, void * type); int Material_setColorband( BPy_Material * self, PyObject * value, void * type); static PyObject *Material_copy( BPy_Material * self ); +static PyObject *Material_freeNodes( BPy_Material * self ); + +static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ); +static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ); +static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ); +static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ); +static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value); +static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value); +static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ); +static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value); +static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value); + /*****************************************************************************/ @@ -886,6 +953,8 @@ static PyMethodDef BPy_Material_methods[] = { "() - Return a copy of the material."}, {"copy", ( PyCFunction ) Material_copy, METH_NOARGS, "() - Return a copy of the material."}, + {"freeNodes", ( PyCFunction ) Material_freeNodes, METH_NOARGS, + "() - Free this materials nodes."}, {NULL, NULL, 0, NULL} }; @@ -1168,7 +1237,35 @@ static PyGetSetDef BPy_Material_getseters[] = { (getter)Material_getColorband, (setter)Material_setColorband, "The specular colorband for this material", (void *) 1}, - + {"textures", + (getter)Material_getTextures, (setter)Material_setTextures, + "The Material's texture list as a tuple", + NULL}, + {"colorbandSpecularFactor", + (getter)Material_getColorbandSpecularFactor, (setter)Material_setColorbandSpecularFactor, + "The specular colorband factor for this material", + NULL}, + {"colorbandSpecularMethod", + (getter)Material_getColorbandSpecularMethod, (setter)Material_setColorbandSpecularMethod, + "The specular colorband method for this material", + NULL}, + {"colorbandSpecularInput", + (getter)Material_getColorbandSpecularInput, (setter)Material_setColorbandSpecularInput, + "The specular colorband input for this material", + NULL}, + {"colorbandDiffuseFactor", + (getter)Material_getColorbandDiffuseFactor, (setter)Material_setColorbandDiffuseFactor, + "The diffuse colorband factor for this material", + NULL}, + {"colorbandDiffuseMethod", + (getter)Material_getColorbandDiffuseMethod, (setter)Material_setColorbandDiffuseMethod, + "The diffuse colorband method for this material", + NULL}, + {"colorbandDiffuseInput", + (getter)Material_getColorbandDiffuseInput, (setter)Material_setColorbandDiffuseInput, + "The diffuse colorband input for this material", + NULL}, + /* SSS settings */ {"enableSSS", (getter)Material_getSssEnable, (setter)Material_setSssEnable, @@ -1737,28 +1834,23 @@ static PyObject* Material_getSssBack( BPy_Material * self ) static PyObject *Material_getTextures( BPy_Material * self ) { int i; - struct MTex *mtex; - PyObject *t[MAX_MTEX]; PyObject *tuple; /* build a texture list */ - for( i = 0; i < MAX_MTEX; ++i ) { - mtex = self->material->mtex[i]; - - if( mtex ) { - t[i] = MTex_CreatePyObject( mtex ); - } else { - Py_INCREF( Py_None ); - t[i] = Py_None; - } - } - - /* turn the array into a tuple */ - tuple = Py_BuildValue( "NNNNNNNNNN", t[0], t[1], t[2], t[3], - t[4], t[5], t[6], t[7], t[8], t[9] ); + tuple = PyTuple_New( MAX_MTEX ); if( !tuple ) return EXPP_ReturnPyObjError( PyExc_MemoryError, - "Material_getTextures: couldn't create PyTuple" ); + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->material->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_MA ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } return tuple; } @@ -2433,14 +2525,86 @@ static PyObject *Material_setTexture( BPy_Material * self, PyObject * args ) Py_RETURN_NONE; } +static int Material_setTextures( BPy_Material * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_MA ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing material MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->material->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->material->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->material->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->material->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} + static PyObject *Material_clearTexture( BPy_Material * self, PyObject * value ) { int texnum = (int)PyInt_AsLong(value); struct MTex *mtex; /* non ints will be -1 */ - if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected int in [0,9]" ); + if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) { + char errstr[64]; + sprintf( errstr, "expected int in [0,%d]", MAX_MTEX ); + return EXPP_ReturnPyObjError( PyExc_TypeError, errstr ); + } mtex = self->material->mtex[texnum]; if( mtex ) { @@ -2519,6 +2683,22 @@ static PyObject *Material_copy( BPy_Material * self ) return ( PyObject * ) pymat; } +/* mat.freeNodes() */ +static PyObject *Material_freeNodes( BPy_Material * self ) +{ + if (self->material->nodetree) { + if(self->material->nodetree) { + ntreeFreeTree(self->material->nodetree); + MEM_freeN(self->material->nodetree); + } + self->material->nodetree = NULL; + self->material->use_nodes = 0; + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + /* mat_a==mat_b or mat_a!=mat_b*/ static int Material_compare( BPy_Material * a, BPy_Material * b ) { @@ -3221,3 +3401,75 @@ static PyObject *Material_clearIpo( BPy_Material * self ) return EXPP_incr_ret_False(); /* no ipo found */ } +/* RampCol Factor */ + +static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ) +{ + return PyFloat_FromDouble( (double) self->material->rampfac_col); +} + +static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ) +{ + return PyFloat_FromDouble( (double) self->material->rampfac_spec); +} + +static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ) +{ + return EXPP_setFloatClamped(value, &self->material->rampfac_col, + EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); +} + +static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ) +{ + return EXPP_setFloatClamped(value, &self->material->rampfac_spec, + EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); +} + +/* RampCol Method */ + +static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampblend_col); +} + +static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampblend_spec); +} + +static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampblend_col, + MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); +} + +static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampblend_spec, + MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); +} + +/* RampCol Input */ + +static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampin_col); +} + +static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampin_spec); +} + +static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampin_col, + MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); +} + +static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampin_spec, + MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); +} + diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index 217e096060f..f0b51285376 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -108,7 +108,7 @@ struct PyMethodDef M_Mathutils_methods[] = { }; /*----------------------------MODULE INIT-------------------------*/ /* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */ -PyObject *Mathutils_Init(char *from) +PyObject *Mathutils_Init(const char *from) { PyObject *submodule; diff --git a/source/blender/python/api2_2x/Mathutils.h b/source/blender/python/api2_2x/Mathutils.h index 76d53cb6c4c..0db83216178 100644 --- a/source/blender/python/api2_2x/Mathutils.h +++ b/source/blender/python/api2_2x/Mathutils.h @@ -38,7 +38,7 @@ #include "euler.h" #include "point.h" -PyObject *Mathutils_Init( char * from ); +PyObject *Mathutils_Init( const char * from ); PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat); diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index b3e8fefdb7b..6471fb16e92 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -4163,6 +4163,7 @@ static int MFace_setMode( BPy_MFace *self, PyObject *value ) { int param; static short bitmask = TF_DYNAMIC + | TF_ALPHASORT | TF_TEX | TF_SHAREDVERT | TF_LIGHT @@ -8696,11 +8697,11 @@ static PyObject *M_Mesh_FaceModesDict( void ) if( FM ) { BPy_constant *d = ( BPy_constant * ) FM; - PyConstant_Insert( d, "BILLBOARD", - PyInt_FromLong( TF_BILLBOARD2 ) ); + PyConstant_Insert( d, "BILLBOARD", PyInt_FromLong( TF_BILLBOARD2 ) ); PyConstant_Insert( d, "ALL", PyInt_FromLong( 0xffff ) ); PyConstant_Insert( d, "HALO", PyInt_FromLong( TF_BILLBOARD ) ); PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( TF_DYNAMIC ) ); + PyConstant_Insert( d, "ALPHASORT", PyInt_FromLong( TF_ALPHASORT ) ); PyConstant_Insert( d, "INVISIBLE", PyInt_FromLong( TF_INVISIBLE ) ); PyConstant_Insert( d, "LIGHT", PyInt_FromLong( TF_LIGHT ) ); PyConstant_Insert( d, "OBCOL", PyInt_FromLong( TF_OBCOL ) ); diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index dc70921492c..45d6bfa3c01 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -81,6 +81,7 @@ struct rctf; #include "BIF_editarmature.h" #include "BIF_editaction.h" #include "BIF_editnla.h" +#include "BIF_keyframing.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -2734,7 +2735,7 @@ static PyObject *Object_setConstraintInfluenceForBone( BPy_Object * self, "expects bonename, constraintname, influenceval" ); icu = verify_ipocurve((ID *)self->object, ID_CO, boneName, constName, NULL, - CO_ENFORCE); + CO_ENFORCE, 1); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index bc65426e16c..893ee077d67 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -526,15 +526,18 @@ throws NameError if name not found PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) { +#if 1 + return EXPP_ReturnPyObjError( PyExc_NotImplementedError, + "Particle.Get() not implemented" ); +#else ParticleSettings *psys_iter; char *name = NULL; -#if 0 ParticleSystem *blparticlesys = 0; Object *ob; PyObject *partsyslist,*current; -#endif + if( !PyArg_ParseTuple( args, "|s", &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected string argument" ); @@ -577,7 +580,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } while( psys_iter ){ -#if 0 pyobj = ParticleSystem_CreatePyObject( psys_iter); if( !pyobj){ Py_DECREF( pylist ); @@ -586,7 +588,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) "could not create ParticleSystem PyObject"); } PyList_SET_ITEM( pylist, index, pyobj); -#endif printf("name is %s\n", psys_iter->id.name+2); psys_iter = psys_iter->id.next; index++; @@ -596,10 +597,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } - - -#if 0 - for( ob = G.main->particlesystem.first; ob; ob = ob->id.next ) if( !strcmp( name, ob->id.name + 2 ) ) break; @@ -626,7 +623,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } return partsyslist; - #endif } diff --git a/source/blender/python/api2_2x/Pose.c b/source/blender/python/api2_2x/Pose.c index 1021eac5fc4..52ede1cb3ee 100644 --- a/source/blender/python/api2_2x/Pose.c +++ b/source/blender/python/api2_2x/Pose.c @@ -43,6 +43,7 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" //1 - this order #include "BSE_editipo.h" //2 +#include "BIF_keyframing.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "Mathutils.h" diff --git a/source/blender/python/api2_2x/Text.c b/source/blender/python/api2_2x/Text.c index 308ad094c7b..9719daaa3d4 100644 --- a/source/blender/python/api2_2x/Text.c +++ b/source/blender/python/api2_2x/Text.c @@ -34,9 +34,13 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BIF_drawtext.h" +#include "BIF_screen.h" #include "BKE_text.h" +#include "BKE_suggestions.h" #include "BLI_blenlib.h" +#include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "MEM_guardedalloc.h" #include "gen_utils.h" #include "gen_library.h" #include "../BPY_extern.h" @@ -90,9 +94,20 @@ struct PyMethodDef M_Text_methods[] = { static PyObject *Text_getFilename( BPy_Text * self ); static PyObject *Text_getNLines( BPy_Text * self ); static PyObject *Text_clear( BPy_Text * self ); +static PyObject *Text_reset( BPy_Text * self ); +static PyObject *Text_readline( BPy_Text * self ); static PyObject *Text_write( BPy_Text * self, PyObject * value ); +static PyObject *Text_insert( BPy_Text * self, PyObject * value ); +static PyObject *Text_delete( BPy_Text * self, PyObject * value ); static PyObject *Text_set( BPy_Text * self, PyObject * args ); -static PyObject *Text_asLines( BPy_Text * self ); +static PyObject *Text_asLines( BPy_Text * self, PyObject * args ); +static PyObject *Text_getCursorPos( BPy_Text * self ); +static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ); +static PyObject *Text_getSelectPos( BPy_Text * self ); +static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args ); +static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ); +static PyObject *Text_suggest( BPy_Text * self, PyObject * args ); +static PyObject *Text_showDocs( BPy_Text * self, PyObject * args ); /*****************************************************************************/ /* Python BPy_Text methods table: */ @@ -109,12 +124,34 @@ static PyMethodDef BPy_Text_methods[] = { "(str) - Change Text Object name"}, {"clear", ( PyCFunction ) Text_clear, METH_NOARGS, "() - Clear Text buffer"}, + {"reset", ( PyCFunction ) Text_reset, METH_NOARGS, + "() - Moves the IO pointer back to the start of the Text buffer for reading"}, + {"readline", ( PyCFunction ) Text_readline, METH_NOARGS, + "() - Reads a line of text from the buffer and returns it incrementing the internal IO pointer."}, {"write", ( PyCFunction ) Text_write, METH_O, "(line) - Append string 'str' to Text buffer"}, + {"insert", ( PyCFunction ) Text_insert, METH_O, + "(line) - Insert string 'str' to Text buffer at cursor location"}, + {"delete", ( PyCFunction ) Text_delete, METH_O, + "(chars) - Deletes a number of characters to the left (chars<0) or right (chars>0)"}, {"set", ( PyCFunction ) Text_set, METH_VARARGS, "(name, val) - Set attribute 'name' to value 'val'"}, - {"asLines", ( PyCFunction ) Text_asLines, METH_NOARGS, - "() - Return text buffer as a list of lines"}, + {"asLines", ( PyCFunction ) Text_asLines, METH_VARARGS, + "(start=0, end=nlines) - Return text buffer as a list of lines between start and end"}, + {"getCursorPos", ( PyCFunction ) Text_getCursorPos, METH_NOARGS, + "() - Return cursor position as (row, col) tuple"}, + {"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS, + "(row, col) - Set the cursor position to (row, col)"}, + {"getSelectPos", ( PyCFunction ) Text_getSelectPos, METH_NOARGS, + "() - Return the selection cursor position as (row, col) tuple"}, + {"setSelectPos", ( PyCFunction ) Text_setSelectPos, METH_VARARGS, + "(row, col) - Set the selection cursor position to (row, col)"}, + {"markSelection", ( PyCFunction ) Text_markSelection, METH_VARARGS, + "(group, (r, g, b), flags) - Places a marker over the current selection. Group: number > 0, flags: TMARK_TEMP, TMARK_EDITALL, etc."}, + {"suggest", ( PyCFunction ) Text_suggest, METH_VARARGS, + "(list, prefix='') - Presents a list of suggestions. List is of strings, or tuples. Tuples must be of the form (name, type) where type is one of 'm', 'v', 'f', 'k' for module, variable, function and keyword respectively or '?' for other types"}, + {"showDocs", ( PyCFunction ) Text_showDocs, METH_VARARGS, + "(docs) - Documentation string"}, {NULL, NULL, 0, NULL} }; @@ -302,7 +339,7 @@ static PyObject *M_Text_unlink( PyObject * self, PyObject * args ) /*****************************************************************************/ PyObject *Text_Init( void ) { - PyObject *submodule; + PyObject *submodule, *dict; if( PyType_Ready( &Text_Type ) < 0 ) return NULL; @@ -310,6 +347,19 @@ PyObject *Text_Init( void ) submodule = Py_InitModule3( "Blender.Text", M_Text_methods, M_Text_doc ); + dict = PyModule_GetDict( submodule ); + +#define EXPP_ADDCONST(x) \ + EXPP_dict_set_item_str(dict, #x, PyInt_FromLong(x)) + + /* So, for example: + * EXPP_ADDCONST(LEFTMOUSE) becomes + * EXPP_dict_set_item_str(dict, "LEFTMOUSE", PyInt_FromLong(LEFTMOUSE)) + */ + + EXPP_ADDCONST( TMARK_TEMP ); + EXPP_ADDCONST( TMARK_EDITALL ); + return ( submodule ); } @@ -327,6 +377,8 @@ PyObject *Text_CreatePyObject( Text * txt ) "couldn't create BPy_Text PyObject" ); pytxt->text = txt; + pytxt->iol = NULL; + pytxt->ioc = -1; return ( PyObject * ) pytxt; } @@ -376,25 +428,49 @@ static PyObject *Text_clear( BPy_Text * self) Py_RETURN_NONE; } -static PyObject *Text_set( BPy_Text * self, PyObject * args ) +static PyObject *Text_reset( BPy_Text * self ) { - int ival; - char *attr; - - if( !PyArg_ParseTuple( args, "si", &attr, &ival ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a string and an int as arguments" ); - - if( strcmp( "follow_cursor", attr ) == 0 ) { - if( ival ) - self->text->flags |= EXPP_TEXT_MODE_FOLLOW; - else - self->text->flags &= EXPP_TEXT_MODE_FOLLOW; - } + self->iol = NULL; + self->ioc = -1; Py_RETURN_NONE; } +static PyObject *Text_readline( BPy_Text * self ) +{ + PyObject *tmpstr; + + if( !self->text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + /* Reset */ + if (!self->iol && self->ioc == -1) { + self->iol = self->text->lines.first; + self->ioc = 0; + } + + if (!self->iol) { + PyErr_SetString( PyExc_StopIteration, "End of buffer reached" ); + return PyString_FromString( "" ); + } + + if (self->ioc > self->iol->len) { + self->iol = NULL; + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Line length exceeded, text may have changed while reading" ); + } + + tmpstr = PyString_FromString( self->iol->line + self->ioc ); + if (self->iol->next) + PyString_ConcatAndDel( &tmpstr, PyString_FromString("\n") ); + + self->iol = self->iol->next; + self->ioc = 0; + + return tmpstr; +} + static PyObject *Text_write( BPy_Text * self, PyObject * value ) { char *str = PyString_AsString(value); @@ -413,35 +489,324 @@ static PyObject *Text_write( BPy_Text * self, PyObject * value ) txt_move_eof( self->text, 0 ); txt_set_undostate( oldstate ); + Text_reset( self ); + Py_RETURN_NONE; } -static PyObject *Text_asLines( BPy_Text * self ) +static PyObject *Text_insert( BPy_Text * self, PyObject * value ) { - TextLine *line; - PyObject *list, *tmpstr; + char *str = PyString_AsString(value); + int oldstate; if( !self->text ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); + if( !str ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected string argument" ); + + oldstate = txt_get_undostate( ); + txt_insert_buf( self->text, str ); + txt_set_undostate( oldstate ); + + Text_reset( self ); + + Py_RETURN_NONE; +} + +static PyObject *Text_delete( BPy_Text * self, PyObject * value ) +{ + int num = PyInt_AsLong(value); + int oldstate; + + if( !self->text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + if( !num ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected non-zero int argument" ); + + oldstate = txt_get_undostate( ); + while (num<0) { + txt_backspace_char(self->text); + num++; + } + while (num>0) { + txt_delete_char(self->text); + num--; + } + txt_set_undostate( oldstate ); + + Text_reset( self ); + + Py_RETURN_NONE; +} + +static PyObject *Text_set( BPy_Text * self, PyObject * args ) +{ + int ival; + char *attr; + + if( !PyArg_ParseTuple( args, "si", &attr, &ival ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a string and an int as arguments" ); + + if( strcmp( "follow_cursor", attr ) == 0 ) { + if( ival ) + self->text->flags |= EXPP_TEXT_MODE_FOLLOW; + else + self->text->flags &= EXPP_TEXT_MODE_FOLLOW; + } + + Py_RETURN_NONE; +} + +static PyObject *Text_asLines( BPy_Text * self, PyObject * args ) +{ + TextLine *line; + PyObject *list, *tmpstr; + int start=0, end=-1, i; + + if( !self->text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + if( !PyArg_ParseTuple( args, "|ii", &start, &end ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected upto two optional ints as arguments" ); + + if (start<0) + start=0; + line = self->text->lines.first; + for (i = 0; i < start && line->next; i++) + line= line->next; + list = PyList_New( 0 ); if( !list ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyList" ); - while( line ) { + while( line && (i < end || end == -1) ) { tmpstr = PyString_FromString( line->line ); PyList_Append( list, tmpstr ); Py_DECREF(tmpstr); line = line->next; + i++; } return list; } +static PyObject *Text_getCursorPos( BPy_Text * self ) +{ + Text *text; + TextLine *linep; + int row, col; + + text = self->text; + if( !text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + for (row=0,linep=text->lines.first; linep!=text->curl; linep=linep->next) + row++; + col= text->curc; + + return Py_BuildValue( "ii", row, col ); +} + +static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ) +{ + int row, col; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "ii", &row, &col)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected two ints as arguments."); + if (row<0) row=0; + if (col<0) col=0; + + txt_move_to(self->text, row, col, 0); + + if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) + pop_space_text(st); + + Py_RETURN_NONE; +} + +static PyObject *Text_getSelectPos( BPy_Text * self ) +{ + Text *text; + TextLine *linep; + int row, col; + + text = self->text; + if( !text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + for (row=0,linep=text->lines.first; linep!=text->sell; linep=linep->next) + row++; + col= text->selc; + + return Py_BuildValue( "ii", row, col ); +} + +static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args ) +{ + int row, col; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "ii", &row, &col)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected two ints as arguments."); + if (row<0) row=0; + if (col<0) col=0; + + txt_move_to(self->text, row, col, 1); + + if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) + pop_space_text(st); + + Py_RETURN_NONE; +} + +static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ) +{ + int group = 0, flags = 0,r, g, b; + Text *text; + char color[4]; + + text = self->text; + if (!text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "i(iii)i", &group, &r, &g, &b, &flags)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected int, 3-tuple of ints and int as arguments."); + + if (text->curl != text->sell) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Cannot mark multi-line selection."); + + color[0] = (char) (r&0xFF); + color[1] = (char) (g&0xFF); + color[2] = (char) (b&0xFF); + color[3] = 255; + + group &= 0xFFFF; + + txt_add_marker(text, text->curl, text->curc, text->selc, color, group, flags); + + Py_RETURN_NONE; +} + +static PyObject *Text_suggest( BPy_Text * self, PyObject * args ) +{ + PyObject *item = NULL, *tup1 = NULL, *tup2 = NULL; + PyObject *list = NULL; + int list_len, i; + char *prefix = NULL, *name, type; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + /* Parse args for a list of strings/tuples */ + if (!PyArg_ParseTuple(args, "O!|s", &PyList_Type, &list, &prefix)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected list of strings or tuples followed by an optional string"); + + if (curarea->spacetype != SPACE_TEXT) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active space type is not text"); + + st = curarea->spacedata.first; + if (!st || !st->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active text area has no Text object"); + + texttool_suggest_clear(); + texttool_text_set_active(st->text); + list_len = PyList_Size(list); + + for (i = 0; i < list_len; i++) { + item = PyList_GetItem(list, i); + + if (PyString_Check(item)) { + name = PyString_AsString(item); + type = '?'; + } else if (PyTuple_Check(item) && PyTuple_GET_SIZE(item) == 2) { + tup1 = PyTuple_GetItem(item, 0); + tup2 = PyTuple_GetItem(item, 1); + if (PyString_Check(tup1) && PyString_Check(tup2)) { + name = PyString_AsString(tup1); + type = PyString_AsString(tup2)[0]; + } else + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "list must contain tuples of two strings only: (name, type)" ); + } else + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "list must contain only individual strings or tuples of size 2" ); + + if (!strlen(name) || (type!='m' && type!='v' && type!='f' && type!='k' && type!='?')) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "names must be non-empty and types in ['m', 'v', 'f', 'k', '?']" ); + + texttool_suggest_add(name, type); + } + if (!prefix) + prefix = ""; + texttool_suggest_prefix(prefix); + scrarea_queue_redraw(curarea); + + Py_RETURN_NONE; +} + +static PyObject *Text_showDocs( BPy_Text * self, PyObject * args ) +{ + char *docs; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "s", &docs)) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a string as argument" ); + + if (curarea->spacetype != SPACE_TEXT) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active space type is not text"); + + st = curarea->spacedata.first; + if (!st || !st->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active text area has no Text object"); + + texttool_text_set_active(st->text); + texttool_docs_show(docs); + scrarea_queue_redraw(curarea); + + Py_RETURN_NONE; +} + /*****************************************************************************/ /* Function: Text_compare */ /* Description: This is a callback function for the BPy_Text type. It */ diff --git a/source/blender/python/api2_2x/Text.h b/source/blender/python/api2_2x/Text.h index 0c5e2607f03..73943ddb9cd 100644 --- a/source/blender/python/api2_2x/Text.h +++ b/source/blender/python/api2_2x/Text.h @@ -41,6 +41,8 @@ extern PyTypeObject Text_Type; typedef struct { PyObject_HEAD Text * text; /* libdata must be second */ + TextLine * iol; /* current line being read or NULL if reset */ + int ioc; /* character offset in line being read */ } BPy_Text; PyObject *Text_Init( void ); diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 7ba8ad88ea6..141b36a05d6 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -42,6 +42,7 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "MTex.h" #include "Image.h" @@ -1142,6 +1143,11 @@ static PyObject *M_Texture_TexCoDict( void ) PyConstant_Insert(d, "STICK", PyInt_FromLong(TEXCO_STICKY)); PyConstant_Insert(d, "STRESS", PyInt_FromLong(TEXCO_STRESS)); PyConstant_Insert(d, "TANGENT", PyInt_FromLong(TEXCO_TANGENT)); + + /* World TexCo Settings */ + PyConstant_Insert(d, "ANGMAP", PyInt_FromLong(TEXCO_ANGMAP)); + PyConstant_Insert(d, "HSPHERE", PyInt_FromLong(TEXCO_H_SPHEREMAP)); + PyConstant_Insert(d, "HTUBE", PyInt_FromLong(TEXCO_H_TUBEMAP)); } return TexCo; } @@ -1195,6 +1201,7 @@ static PyObject *M_Texture_ExtendModesDict( void ) PyConstant_Insert(d, "CLIP", PyInt_FromLong(TEX_CLIP)); PyConstant_Insert(d, "CLIPCUBE", PyInt_FromLong(TEX_CLIPCUBE)); PyConstant_Insert(d, "REPEAT", PyInt_FromLong(TEX_REPEAT)); + PyConstant_Insert(d, "CHECKER", PyInt_FromLong(TEX_CHECKER)); } return ExtendModes; } diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index fe789fb4811..41a4e4e215f 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -1249,9 +1249,10 @@ static PyObject *M_Window_TestBreak( PyObject * self ) static PyObject *M_Window_GetMouseCoords( PyObject * self ) { - short mval[2]; + short mval[2] = {0, 0}; - getmouse( mval ); + if (!G.background) + getmouse( mval ); return Py_BuildValue( "hh", mval[0], mval[1] ); } @@ -1283,16 +1284,12 @@ static PyObject *M_Window_SetMouseCoords( PyObject * self, PyObject * args ) static PyObject *M_Window_GetMouseButtons( PyObject * self ) { - short mbut = get_mbut( ); - - return Py_BuildValue( "h", mbut ); + return PyInt_FromLong(G.background ? 0 : (int)get_mbut() ); } static PyObject *M_Window_GetKeyQualifiers( PyObject * self ) { - short qual = get_qual( ); - - return Py_BuildValue( "h", qual ); + return PyInt_FromLong( (int)get_qual() ); } static PyObject *M_Window_SetKeyQualifiers( PyObject * self, PyObject * args ) diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 6021f8552ad..0c57488a266 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -47,13 +47,17 @@ #include "BKE_world.h" #include "BKE_main.h" #include "BKE_library.h" +#include "BKE_texture.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "Ipo.h" +#include "MTex.h" #include "gen_utils.h" #include "gen_library.h" +#include "MEM_guardedalloc.h" #define IPOKEY_ZENITH 0 #define IPOKEY_HORIZON 1 @@ -99,6 +103,8 @@ static PyObject *World_getScriptLinks( BPy_World * self, PyObject * value ); static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ); static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_setCurrent( BPy_World * self ); +static PyObject *World_getTextures( BPy_World * self ); +static int World_setTextures( BPy_World * self, PyObject * value ); static PyObject *World_copy( BPy_World * self ); @@ -250,6 +256,9 @@ static PyGetSetDef BPy_World_getseters[] = { "world mist settings", NULL}, {"ipo", (getter)World_getIpo, (setter)World_setIpo, "world ipo", NULL}, + {"textures", (getter)World_getTextures, (setter)World_setTextures, + "The World's texture list as a tuple", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -1029,3 +1038,97 @@ static PyObject *World_insertIpoKey( BPy_World * self, PyObject * args ) Py_RETURN_NONE; } + +static PyObject *World_getTextures( BPy_World * self ) +{ + int i; + PyObject *tuple; + + /* build a texture list */ + tuple = PyTuple_New( MAX_MTEX ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->world->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_WO ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } + + return tuple; +} + +static int World_setTextures( BPy_World * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_WO ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing world MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->world->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->world->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->world->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->world->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} diff --git a/source/blender/python/api2_2x/bpy_data.c b/source/blender/python/api2_2x/bpy_data.c index 4705c1bdd03..47232c6707a 100644 --- a/source/blender/python/api2_2x/bpy_data.c +++ b/source/blender/python/api2_2x/bpy_data.c @@ -263,9 +263,12 @@ PyObject *LibBlockSeq_getActive(BPy_LibBlockSeq *self) } break; case ID_TXT: { - SpaceText *st= curarea->spacedata.first; + SpaceText *st = NULL; - if (st->spacetype!=SPACE_TEXT || st->text==NULL) { + if (curarea) + st = curarea->spacedata.first; + + if (st==NULL || st->spacetype!=SPACE_TEXT || st->text==NULL) { Py_RETURN_NONE; } else { return Text_CreatePyObject( st->text ); @@ -330,9 +333,15 @@ static int LibBlockSeq_setActive(BPy_LibBlockSeq *self, PyObject *value) return EXPP_ReturnIntError(PyExc_TypeError, "Must be a text" ); } else { - SpaceText *st= curarea->spacedata.first; + SpaceText *st= NULL; Text *data = ((BPy_Text *)value)->text; + if (curarea==NULL) { + return 0; + } else { + st= curarea->spacedata.first; + } + if( !data ) return EXPP_ReturnIntError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); diff --git a/source/blender/python/api2_2x/doc/Draw.py b/source/blender/python/api2_2x/doc/Draw.py index 18234754315..97e22797902 100644 --- a/source/blender/python/api2_2x/doc/Draw.py +++ b/source/blender/python/api2_2x/doc/Draw.py @@ -357,12 +357,14 @@ def PupTreeMenu( menu ): """ Create a popup menu tree. - Each item in the list is a menu item - (str, event), separator - None or submenu - (str, [...]). + Each item in the list is: a menu item - (str, event); a separator - None; + or submenu - (str, [...]). - Submenus list uses the same syntax as the menu list. + Submenus list uses the same syntax as the menu list. To add a title to the + main menu, end the first entry str with '%t' - the event is ignored. Example:: - result = Draw.PupTreeMenu( [ ("Menu Item 1", 10), ("Menu Item 2", 12), ("SubMenu", [("Menu Item 3", 100), ("MenuItem4", 101) ] ) ] ) + result = Draw.PupTreeMenu( [ ("Title%t", 0), ("Menu Item 1", 10), ("Menu Item 2", 12), ("SubMenu", [("Menu Item 3", 100), ("MenuItem4", 101) ] ) ] ) @type menu: string @param menu: A menu list diff --git a/source/blender/python/api2_2x/doc/Group.py b/source/blender/python/api2_2x/doc/Group.py index 6bd6e105ec3..1266d2efb6e 100644 --- a/source/blender/python/api2_2x/doc/Group.py +++ b/source/blender/python/api2_2x/doc/Group.py @@ -105,6 +105,8 @@ class Group: This object gives access to Groups in Blender. @ivar layers: Layer bitmask for this group. @type layers: int + @ivar dupliOffset: Object offset when instanced as a dupligroup + @type dupliOffset: vector @ivar objects: Objects that this group uses. This is a sequence with-list like access so use list(grp.objects) if you need to use a list (where grp is a group). The groups objects can be set by assigning a list or iterator of objects to the groups objects. diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index a7a1fb94620..162d94ccff3 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -161,6 +161,8 @@ class Lamp: @type type: int @ivar falloffType: Lamp falloff type. See L{Falloffs} for values. @type falloffType: int + @type textures: a tuple of Blender MTex objects. + @ivar textures: The Lamp's texture list. Empty texture channels contains None. @warning: Most member variables assume values in some [Min, Max] interval. When trying to set them, the given parameter will be clamped to lie in diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 02f7edd77f5..fa6a9f7047a 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -80,6 +80,35 @@ Example:: - SPEC_BLINN - Make Material use the Blinn specular shader. - SPEC_TOON - Make Material use the toon specular shader. - SPEC_WARDISO - Make Material use the Ward-iso specular shader. + +@type ColorbandMethod: readonly dictionary +@var ColorbandMethod: The available Colorband mixing methods. + - ADD - Make Material use the Add method. + - BLEND - Make Material use the Blend/Mix method. + - BURN - Make Material use the Burn method. + - COLOR - Make Material use the Color method. + - DARK - Make Material use the Darken method. + - DIFF - Make Material use the Difference method. + - DIV - Make Material use the Divide method. + - DODGE - Make Material use the Dodge method. + - HUE - Make Material use the Hue method. + - LIGHT - Make Material use the Lighten method. + - MIX - Make Material use the Blend/Mix method. + - MULT - Make Material use the Multiply method. + - OVERLAY - Make Material use the Overlay method. + - SAT - Make Material use the Saturation method. + - SCREEN - Make Material use the Screen method. + - SUB - Make Material use the Substract method. + - VAL - Make Material use the Value method. + +@type ColorbandInput: readonly dictionary +@var ColorbandInput: The available Colorband Input sources. + - ENERGY - Make Material use the Energy input. + - NORMAL - Make Material use the Normal input. + - RESULT - Make Material use the Result input. + - SHADER - Make Material use the Shader input. + + """ def New (name = 'Mat'): @@ -323,6 +352,28 @@ class Material: each color a list of 5 floats [0 - 1], [r,g,b,a,pos]. The colorband can have between 1 and 31 colors. @type colorbandSpecular: list + @ivar colorbandDiffuseInput: Material Diffuse colorband input. + The integer result must be compared with L{ColorbandInput} + dictionary. + @type colorbandDiffuseInput: int + @ivar colorbandDiffuseMethod: Material Diffuse colorband method. + The integer result must be compared with L{ColorbandMethod} + dictionary. + @type colorbandDiffuseMethod: int + @ivar colorbandDiffuseFactor: Material Diffuse colorband factor. + Value is clamped to the range [0.0,1.0]. + @type colorbandDiffuseFactor: float + @ivar colorbandSpecularInput: Material Specular colorband input. + The integer result must be compared with L{ColorbandInput} + dictionary. + @type colorbandSpecularInput: int + @ivar colorbandSpecularMethod: Material Specular colorband method. + The integer result must be compared with L{ColorbandMethod} + dictionary. + @type colorbandSpecularMethod: int + @ivar colorbandSpecularFactor: Material Specular colorband factor. + Value is clamped to the range [0.0,1.0]. + @type colorbandSpecularFactor: float @type enabledTextures: list of integers @ivar enabledTextures: The texture channels enabled in this material. The attribute returns is list of integers in the range [0, 9], each @@ -338,7 +389,9 @@ class Material: ch.append(4) mat.enabledTextures = ch print mat.enabledTextures # will print: [0, 4, 6] - + + @type textures: a tuple of Blender MTex objects. + @ivar textures: the Material's Texture list. Empty texture channels contains None. @ivar enableSSS: If True, subsurface scattering will be rendered on this material. @type enableSSS: bool @ivar sssScale: If True, subsurface scattering will be rendered on this material. @@ -1085,5 +1138,12 @@ class Material: @return: a copy of this material """ + def freeNodes (): + """ + Removes the node tree from this material. + @rtype: bool + @return: true if nodes were freed from this material. + """ + import id_generics Material.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index 4a53f869283..e48f41e8f9c 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -69,6 +69,7 @@ done once. - BILLBOARD - always orient after camera. - HALO - halo face, always point to camera. - DYNAMIC - respond to collisions. + - ALPHASORT - game engine sorts these faces only. - INVISIBLE - invisible face. - LIGHT - dynamic lighting. - OBCOL - use object color instead of vertex colors. @@ -635,7 +636,7 @@ class MFaceSeq: This object provides sequence and iterator access to the mesh's faces. """ - def extend(vertseq,ignoreDups=True,indexList=True): + def extend(vertseq,ignoreDups=True,indexList=True,smooth=False): """ Add zero or more faces and edges to the mesh. Faces which already exist in the mesh, or faces which contain the same vertex multiple times are diff --git a/source/blender/python/api2_2x/doc/Text.py b/source/blender/python/api2_2x/doc/Text.py index 98ecb664b71..022205573aa 100644 --- a/source/blender/python/api2_2x/doc/Text.py +++ b/source/blender/python/api2_2x/doc/Text.py @@ -100,6 +100,19 @@ class Text: Clear this Text object: its buffer becomes empty. """ + def reset(): + """ + Reset the read IO pointer to the start of the buffer. + """ + + def readline(): + """ + Reads a line of text from the buffer from the current IO pointer + position to the end of the line. If the text has changed since the last + read, reset() *must* be called. + @rtype: string + """ + def set(attribute, value): """ Set this Text's attributes. @@ -118,12 +131,94 @@ class Text: @param data: The string to append to the text buffer. """ - def asLines(): + def insert(data): """ - Retrieve the contents of this Text buffer as a list of strings. + Inserts a string into this Text buffer at the cursor. + @type data: string + @param data: The string to insert into the text buffer. + """ + + def asLines(start=0, end=-1): + """ + Retrieve the contents of this Text buffer as a list of strings between + the start and end lines specified. If end < 0 all lines from start will + be included. + @type start int + @param start: Optional index of first line of the span to return + @type end int + @param end: Optional index of the line to which the span is taken or + -1 to include all lines from start @rtype: list of strings - @return: A list of strings, one for each line in the buffer + @return: A list of strings, one for each line in the buffer between + start and end. + """ + + def getCursorPos(): + """ + Retrieve the position of the cursor in this Text buffer. + @rtype: (int, int) + @return: A pair (row, col) indexing the line and character of the + cursor. + """ + + def setCursorPos(row, col): + """ + Set the position of the cursor in this Text buffer. Any selection will + be cleared. Use setSelectPos to extend a selection from the point + specified here. + @type row: int + @param row: The index of the line in which to position the cursor. + @type col: int + @param col: The index of the character within the line to position the + cursor. + """ + + def getSelectPos(): + """ + Retrieve the position of the selection cursor in this Text buffer. + @rtype: (int, int) + @return: A pair (row, col) indexing the line and character of the + selection cursor. + """ + + def setSelectPos(row, col): + """ + Set the position of the selection cursor in this Text buffer. This + method should be called after setCursorPos to extend the selection to + the specified point. + @type row: int + @param row: The index of the line in which to position the cursor. + @type col: int + @param col: The index of the character within the line to position the + cursor. + """ + + def suggest(list, prefix=''): + """ + Suggest a list of names. If list is a list of tuples (name, type) the + list will be formatted to syntax-highlight each entry type. Types must + be strings in the list ['m', 'f', 'v', 'k', '?']. It is recommended that + the list be sorted, case-insensitively by name. + + @type list: list of tuples or strings + @param list: List of pair-tuples of the form (name, type) where name is + the suggested name and type is one of 'm' (module or class), 'f' + (function or method), 'v' (variable), 'k' (keyword), '?' (other). + Lists of plain strings are also accepted where the type is always + '?'. + @type prefix: string + @param prefix: The optional prefix used to limit what is suggested from + the list. This is usually whatever precedes the cursor so that + backspace will update it. + """ + + def showDocs(docs): + """ + Displays a word-wrapped message box containing the specified + documentation when this Text object is visible. + @type docs: string + @param docs: The documentation string to display. """ import id_generics -Text.__doc__ += id_generics.attributes \ No newline at end of file +Text.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index cebb7de7011..b5b82b1a519 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -195,20 +195,23 @@ Example:: - DN_CELLNOISE - Steven Worley's cellular basis algorithm (1996) @var TexCo: Flags for MTex.texco. - - ORCO - Use the original coordinates of the mesh - - REFL - Use reflection vector as texture coordinates - - NOR - Use normal vector as texture coordinates + - ORCO - Use the original coordinates of the mesh (material texture only) + - REFL - Use reflection vector as texture coordinates (material texture only) + - NOR - Use normal vector as texture coordinates (material texture only) - GLOB - Use global coordinates for the texture coordinates - - UV - Use UV coordinates for texture coordinates + - UV - Use UV coordinates for texture coordinates (material texture only) - OBJECT - Use linked object's coordinates for texture coordinates - - WIN - Use screen coordinates as texture coordinates - - VIEW - Pass camera view vector on to the texture (World texture only!) - - STICK - Use mesh sticky coordinates for the texture coordinates - - STRESS - Use mesh stress coordinates for the texture coordinates - - TANGENT - Use mesh tangent coordinates for the texture coordinates + - WIN - Use screen coordinates as texture coordinates (material texture only) + - VIEW - Use view coordinates for the texture (world and lamp texture only) + - STICK - Use mesh sticky coordinates for the texture coordinates (material texture only) + - STRESS - Use mesh stress coordinates for the texture coordinates (material texture only) + - TANGENT - Use mesh tangent coordinates for the texture coordinates (material texture only) + - ANGMAP - Uses 360 degree angular coordinates, e.g. for spherical light probes (world texture only) + - HSPHERE - For 360 degree panorama sky, spherical mapped, only top half (world texture only) + - HTUBE - For 360 degree panorama sky, cylindrical mapped, only top half (world texture only) @type TexCo: readonly dictionary -@var MapTo: Flags for MTex.mapto. +@var MapTo: Flags for MTex.mapto - COL - Make the texture affect the basic color of the material - NOR - Make the texture affect the rendered normal - CSP - Make the texture affect the specularity color @@ -500,48 +503,92 @@ class MTex: This object links a material to a texture. It allows the same texture to be used in several different ways. - @ivar tex: The Texture this is linked to. - @type tex: Blender Texture - @ivar texco: Texture coordinates ("Map input"). See L{TexCo} - @ivar mapto: "Map to" field of texture. OR'd values of L{MapTo} - @ivar object: Object whose space to use when texco is Object - @type object: Blender Object - @ivar col: Color that the texture blends with - @ivar dvar: Value that the texture blends with when not blending colors - @ivar blendmode: Texture blending mode. L{BlendModes} - @ivar colfac: Factor by which texture affects color - @ivar norfac: Factor by which texture affects normal - @ivar varfac: Factor by which texture affects most variables - @ivar dispfac: Factor by which texture affects displacement - @ivar warpfac: Factor by which texture affects warp - @ivar ofs: Offset to adjust texture space - @ivar size: Size to scale texture space - @ivar mapping: Mapping of texture coordinates (flat, cube, etc.). L{Mappings} - @ivar stencil: Stencil mode - @ivar neg: Negate texture values mode - @ivar noRGB: Convert texture RGB values to intensity values - @ivar correctNor: Correct normal mapping for Texture space and Object space - @ivar fromDupli: Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent - @ivar fromOrig: Dupli's derive their object coordinates from the original objects transformation - @ivar xproj: Projection of X axis to Texture space. L{Proj} - @ivar yproj: Projection of Y axis to Texture space. L{Proj} - @ivar zproj: Projection of Z axis to Texture space. L{Proj} - @ivar mtCol: How texture maps to color - @ivar mtNor: How texture maps to normals - @ivar mtCsp: How texture maps to specularity color - @ivar mtCmir: How texture maps to mirror color - @ivar mtRef: How texture maps to reflectivity - @ivar mtSpec: How texture maps to specularity - @ivar mtEmit: How texture maps to emit value - @ivar mtAlpha: How texture maps to alpha value - @ivar mtHard: How texture maps to hardness - @ivar mtRayMir: How texture maps to RayMir value - @ivar mtTranslu: How texture maps to translucency - @ivar mtAmb: How texture maps to ambient value - @ivar mtDisp: How texture maps to displacement - @ivar mtWarp: How texture maps to warp - @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) - @type uvlayer: string + @ivar blendmode: Texture blending mode. See L{BlendModes} + @type blendmode: int + @ivar col: Color that the texture blends with. + @type col: tuple + @ivar colfac: Factor by which texture affects color. + @type colfac: float + @ivar correctNor: Correct normal mapping for Texture space and Object space (material only). + @type correctNor: boolean + @ivar dispfac: Factor by which texture affects displacement (material only). + @type dispfac: float + @ivar dvar: Value that the texture blends with when not blending colors. + @type dvar: float + @ivar fromDupli: Duplis instanced from verts, faces or particles, inherit texture coordinate from their parent (material only). + @type fromDupli: boolean + @ivar fromOrig: Duplis derive their object coordinates from the original objects transformation (material only). + @type fromOrig: boolean + @ivar mapping: Mapping of texture coordinates (flat, cube, etc.) (material only). See L{Mappings}. + @type mapping: int + @ivar mapto: "Map to" field of texture (material only). OR'd values of L{MapTo}. + @type mapto: int + @ivar mtCol: How texture maps to color (material and lamp only). + @type mtCol: int + @ivar mtAlpha: How texture maps to alpha value (material only). + @type mtAlpha: int + @ivar mtAmb: How texture maps to ambient value (material only). + @type mtAmb: int + @ivar mtCmir: How texture maps to mirror color (material only). + @type mtCmir: int + @ivar mtCsp: How texture maps to specularity color (material only). + @type mtCsp: int + @ivar mtDisp: How texture maps to displacement (material only). + @type mtDisp: int + @ivar mtEmit: How texture maps to emit value (material only). + @type mtEmit: int + @ivar mtHard: How texture maps to hardness (material only). + @type mtHard: int + @ivar mtNor: How texture maps to normals (material only). + @type mtNor: int + @ivar mtRayMir: How texture maps to RayMir value (material only). + @type mtRayMir: int + @ivar mtRef: How texture maps to reflectivity (material only). + @type mtRef: int + @ivar mtSpec: How texture maps to specularity (material only). + @type mtSpec: int + @ivar mtTranslu: How texture maps to translucency (material only). + @type mtTranslu: int + @ivar mtWarp: How texture maps to warp (material only). + @type mtWarp: int + @ivar mtBlend: Texture affects color progression of background (world only). + @type mtBlend: int + @ivar mtHoriz: Texture affects color of the horizon (world only). + @type mtHoriz: int + @ivar mtZenUp: Texture affects color of the zenith above (world only). + @type mtZenUp: int + @ivar mtZenDown: Texture affects color of the zenith below (world only). + @type mtZenDown: int + @ivar neg: Negate texture values mode. + @type neg: boolean + @ivar norfac: Factor by which texture affects normal (material and world only). + @type norfac: float + @ivar noRGB: Convert texture RGB values to intensity values. + @type noRGB: boolean + @ivar object: Object whose space to use when texco is Object. + @type object: Blender Object or None + @ivar ofs: Offset to adjust texture space. + @type ofs: tuple + @ivar size: Size to scale texture space. + @type size: tuple + @ivar stencil: Stencil mode. + @type stencil: boolean + @ivar tex: The Texture this is linked to. + @type tex: Blender Texture + @ivar texco: Texture coordinates ("Map input"). See L{TexCo}. + @type texco: int + @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) (material only). + @type uvlayer: string + @ivar varfac: Factor by which texture affects most variables (material and world only). + @type varfac: float + @ivar warpfac: Factor by which texture affects warp (material only). + @type warpfac: float + @ivar xproj: Projection of X axis to Texture space (material only). See L{Proj} + @type xproj: int + @ivar yproj: Projection of Y axis to Texture space (material only). See L{Proj} + @type yproj: int + @ivar zproj: Projection of Z axis to Texture space (material only). See L{Proj} + @type zproj: int """ def getIpo(): diff --git a/source/blender/python/api2_2x/doc/World.py b/source/blender/python/api2_2x/doc/World.py index d9e9bae750d..d8052c609cd 100644 --- a/source/blender/python/api2_2x/doc/World.py +++ b/source/blender/python/api2_2x/doc/World.py @@ -82,6 +82,8 @@ class World: @ivar mist: the mist parameters of a world object. See getMist for the semantics of these parameters. @type ipo: Blender Ipo @ivar ipo: The world type ipo linked to this world object. + @type textures: a tuple of Blender MTex objects. + @ivar textures: The World's texture list. Empty texture channels contains None. """ def getRange(): diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h index 1f2fd55cf1b..f33dc69d703 100644 --- a/source/blender/python/api2_2x/gen_utils.h +++ b/source/blender/python/api2_2x/gen_utils.h @@ -45,6 +45,7 @@ Py_RETURN_NONE Python 2.4 macro. defined here until we switch to 2.4 + also in PyObjectPlus.h for gameengine */ #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_BuildValue("O", Py_None) diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 0d3ad3fcb44..ddc4eb6aea8 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -33,12 +33,14 @@ #include "DNA_scene_types.h" /* for Base */ #include "BKE_mesh.h" +#include "BKE_image.h" // RFS: openanim #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_scene.h" #include "BIF_editseq.h" /* get_last_seq */ +#include "BIF_editsound.h" // RFS: sound_open_hdaudio #include "BLI_blenlib.h" #include "BSE_sequence.h" #include "Ipo.h" @@ -48,6 +50,9 @@ #include "Sound.h" #include "gen_utils.h" +#include "IMB_imbuf_types.h" // RFS: IB_rect +#include "IMB_imbuf.h" // RFS: IMB_anim_get_duration + enum seq_consts { EXPP_SEQ_ATTR_TYPE = 0, EXPP_SEQ_ATTR_CHAN, @@ -145,7 +150,6 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) seq->len = PyList_Size( list ); - /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= seq->len; @@ -185,12 +189,103 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->us= 1; strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 4) { + // MOVIE or AUDIO_HD + char *filename; + char *dir; + char *fullpath; + char *type; + int totframe; + + if (!PyArg_ParseTuple( py_data, "ssss", &filename, &dir, &fullpath, &type )) { + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "movie/audio hd data needs to be a tuple of a string and a list of images - (filename, dir, fullpath, type)" ); + } + + // RFS - Attempting to support Movie and Audio (HD) strips +#define RFS +#ifdef RFS + // Movie strips + if( strcmp( type, "movie" ) == 0 ) + { + /* open it as an animation */ + struct anim * an = openanim(fullpath, IB_rect); + if(an==0) { + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "invalid movie strip" ); + } + + /* get the length in frames */ + totframe = IMB_anim_get_duration( an ); + + /* set up sequence */ + seq->type= SEQ_MOVIE; + seq->len= totframe; + seq->anim= an; + seq->anim_preseek = IMB_anim_get_preseek(an); + + calc_sequence(seq); + + /* strip and stripdata */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len= totframe; + strip->us= 1; + strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + + /* name movie in first strip */ + strncpy(se->name, filename, FILE_MAXFILE-1); // ???? + } + + // Audio (HD) strips + if( strcmp( type, "audio_hd" ) == 0 ) + { + struct hdaudio *hdaudio; + + totframe= 0; + + /* is it a sound file? */ + hdaudio = sound_open_hdaudio( fullpath ); + if(hdaudio==0) { + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + fullpath ); + } + + totframe= sound_hdaudio_get_duration(hdaudio, FPS); + + /* set up sequence */ + seq->type= SEQ_HD_SOUND; + seq->len= totframe; + seq->hdaudio= hdaudio; + + calc_sequence(seq); + + /* strip and stripdata - same as for MOVIE */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len= totframe; + strip->us= 1; + strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + + /* name movie in first strip */ + strncpy(se->name, filename, FILE_MAXFILE-1); // ???? + } +#endif + } else if (BPy_Sound_Check(py_data)) { - /* sound */ + /* RAM sound */ int totframe; bSound *sound = (( BPy_Sound * )py_data)->sound; - seq->type= SEQ_RAM_SOUND; seq->sound = sound; @@ -198,7 +293,6 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) sound->flags |= SOUND_FLAGS_SEQUENCE; - /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= totframe; @@ -225,18 +319,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->len= seq->len; strip->us= 1; } else { - /* movie, pydata is a path to a movie file */ - char *name = PyString_AsString ( py_data ); - if (!name) { - /* only free these 2 because other stuff isnt set */ - BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expects a string for chan/bone name and an int for the frame where to put the new key" ); - } - - seq->type= SEQ_MOVIE; + // RFS: REMOVED MOVIE FROM HERE } strncpy(seq->name+2, "Untitled", 21); intern_pos_update(seq); diff --git a/source/blender/radiosity/CMakeLists.txt b/source/blender/radiosity/CMakeLists.txt index 941da41a5b2..502acf1e211 100644 --- a/source/blender/radiosity/CMakeLists.txt +++ b/source/blender/radiosity/CMakeLists.txt @@ -29,7 +29,7 @@ FILE(GLOB SRC intern/source/*.c) SET(INC extern/include ../blenlib ../blenkernel ../makesdna ../include ../../../intern/guardedalloc ../render/extern/include - ../render/intern/include ../blenloader + ../render/intern/include ../blenloader ../../../extern/glew/include ) BLENDERLIB_NOLIST(blender_radiosity "${SRC}" "${INC}") diff --git a/source/blender/radiosity/SConscript b/source/blender/radiosity/SConscript index a86b76bb4b1..82d84f5ef16 100644 --- a/source/blender/radiosity/SConscript +++ b/source/blender/radiosity/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('intern/source/*.c') incs = 'extern/include ../blenlib ../blenkernel ../makesdna ../include' incs += ' #/intern/guardedalloc ../render/extern/include' -incs += ' ../render/intern/include ../blenloader' +incs += ' ../render/intern/include ../blenloader #/extern/glew/include' incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile index e5ff8c40d08..5912cdba590 100644 --- a/source/blender/radiosity/intern/source/Makefile +++ b/source/blender/radiosity/intern/source/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) # not very neat.... diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c index 6e5bf149c7a..ec71611b31d 100644 --- a/source/blender/readblenfile/intern/BLO_readblenfile.c +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -159,7 +159,7 @@ blo_read_runtime( } else { //printf("starting to read runtime from %s at datastart %d\n", path, datastart); lseek(fd, datastart, SEEK_SET); - bfd = blo_read_blendafterruntime(fd, actualsize-datastart, error_r); + bfd = blo_read_blendafterruntime(fd, path, actualsize-datastart, error_r); fd= -1; // file was closed in blo_read_blendafterruntime() } diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index f83bbd7e8b2..7e2194549cc 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -418,7 +418,8 @@ typedef struct LampRen { float xs, ys, dist; float co[3]; - short type, mode; + short type; + int mode; float r, g, b, k; float energy, haint; int lay; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index e4a5ad67631..322d2066a6c 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1565,7 +1565,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; int i, a, k, max_k=0, totpart, totuv=0, totcol=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0; - int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; + int path_possible=0, keys_possible=0, baked_keys=0, totchild=0; int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num; int totface, *origindex = 0; char **uv_name=0; @@ -1573,6 +1573,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem /* 1. check that everything is ok & updated */ if(psys==NULL) return 0; + + totchild=psys->totchild; part=psys->part; pars=psys->particles; @@ -1764,7 +1766,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem psys->lattice=psys_get_lattice(ob,psys); /* 3. start creating renderable things */ - for(a=0,pa=pars; amode & MA_HALO) + if(totmaterial) { + for(a= 0; a<*totmaterial; a++) { + ma= give_current_material(obd, a); + if(ma && (ma->mode & MA_HALO)) return 0; + } } for(psys=obd->particlesystem.first; psys; psys=psys->next) diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index c2d27f8f3a7..b9a2acb8b1c 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -577,10 +577,10 @@ static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float max if(texres->talpha==0) texres->ta= 1.0; if(alphaclip!=1.0) { - /* this is for later investigation, premul or not? */ - /* texres->tr*= alphaclip; */ - /* texres->tg*= alphaclip; */ - /* texres->tb*= alphaclip; */ + /* premul it all */ + texres->tr*= alphaclip; + texres->tg*= alphaclip; + texres->tb*= alphaclip; texres->ta*= alphaclip; } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 3cd7bdc6772..bf2a72b4f9b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -138,7 +138,7 @@ static void print_error(char *str) {printf("ERROR: %s\n", str);} static void stats_background(RenderStats *rs) { - extern uintptr_t mem_in_use; + uintptr_t mem_in_use= MEM_get_memory_in_use(); float megs_used_memory= mem_in_use/(1024.0*1024.0); char str[400], *spos= str; @@ -1889,6 +1889,7 @@ static void do_render_fields_blur_3d(Render *re) re->result->tilerect= re->disprect; /* this copying sequence could become function? */ + /* weak is: it chances disprect from border */ re->disprect.xmin= re->disprect.ymin= 0; re->disprect.xmax= re->winx; re->disprect.ymax= re->winy; @@ -2346,6 +2347,12 @@ static int is_rendering_allowed(Render *re) if(re->osa==0) re->r.scemode &= ~R_FULL_SAMPLE; + /* no fullsample and edge */ + if((re->r.scemode & R_FULL_SAMPLE) && (re->r.mode & R_EDGE)) { + re->error("Full Sample doesn't support Edge Enhance"); + return 0; + } + } else re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ @@ -2407,7 +2414,7 @@ static int is_rendering_allowed(Render *re) } /* evaluating scene options for general Blender render */ -static int render_initialize_from_scene(Render *re, Scene *scene) +static int render_initialize_from_scene(Render *re, Scene *scene, int anim) { int winx, winy; rcti disprect; @@ -2435,6 +2442,12 @@ static int render_initialize_from_scene(Render *re, Scene *scene) re->scene= scene; + /* not too nice, but it survives anim-border render */ + if(anim) { + re->disprect= disprect; + return 1; + } + /* check all scenes involved */ tag_scenes_for_render(re); @@ -2466,7 +2479,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) scene->r.cfra= frame; - if(render_initialize_from_scene(re, scene)) { + if(render_initialize_from_scene(re, scene, 0)) { do_render_all_options(re); } @@ -2551,8 +2564,8 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype); int cfrao= scene->r.cfra; - /* do not call for each frame, it initializes & pops output window */ - if(!render_initialize_from_scene(re, scene)) + /* do not fully call for each frame, it initializes & pops output window */ + if(!render_initialize_from_scene(re, scene, 0)) return; /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ @@ -2580,6 +2593,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) } else { for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) { char name[FILE_MAX]; + + /* only border now, todo: camera lens. (ton) */ + render_initialize_from_scene(re, scene, 1); + if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index c352a83d0f4..0fd9365477c 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -2056,7 +2056,10 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; - if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) + isec.lay= lar->lay; + else + isec.lay= -1; /* only when not mir tracing, first hit optimm */ if(shi->depth==0) { diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 4a2ad995b39..bda02bea8d7 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -158,7 +158,7 @@ static int calchalo_z(HaloRen *har, int zz) { if(har->type & HA_ONLYSKY) { - if(zz!=0x7FFFFFFF) zz= - 0x7FFFFF; + if(zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */ } else { zz= (zz>>8); @@ -931,17 +931,23 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) } } - -static void convert_to_key_alpha(RenderPart *pa, float *rectf) +static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl) { - int y; + RenderLayer *rlpp[RE_MAX_OSA]; + int y, sample, totsample; - for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { - if(rectf[3] >= 1.0f); - else if(rectf[3] > 0.0f) { - rectf[0] /= rectf[3]; - rectf[1] /= rectf[3]; - rectf[2] /= rectf[3]; + totsample= get_sample_layers(pa, rl, rlpp); + + for(sample= 0; samplerectf; + + for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { + if(rectf[3] >= 1.0f); + else if(rectf[3] > 0.0f) { + rectf[0] /= rectf[3]; + rectf[1] /= rectf[3]; + rectf[2] /= rectf[3]; + } } } } @@ -1229,7 +1235,7 @@ void zbufshadeDA_tile(RenderPart *pa) /* de-premul alpha */ if(R.r.alphamode & R_ALPHAKEY) - convert_to_key_alpha(pa, rl->rectf); + convert_to_key_alpha(pa, rl); /* free stuff within loop! */ MEM_freeN(pa->rectdaps); pa->rectdaps= NULL; @@ -1393,7 +1399,7 @@ void zbufshade_tile(RenderPart *pa) /* de-premul alpha */ if(R.r.alphamode & R_ALPHAKEY) - convert_to_key_alpha(pa, rl->rectf); + convert_to_key_alpha(pa, rl); if(edgerect) MEM_freeN(edgerect); edgerect= NULL; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 98b1426e8ff..d44b49cc706 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -483,16 +483,16 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) DerivedMesh which stores the layers is freed */ CustomDataLayer *layer; - int numlayers, i, mtfn, mcn; + int numtf = 0, numcol = 0, i, mtfn, mcn; if (CustomData_has_layer(data, CD_MTFACE)) { - numlayers= CustomData_number_of_layers(data, CD_MTFACE); - obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numlayers, "mtfacenames"); + numtf= CustomData_number_of_layers(data, CD_MTFACE); + obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames"); } if (CustomData_has_layer(data, CD_MCOL)) { - numlayers= CustomData_number_of_layers(data, CD_MCOL); - obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numlayers, "mcolnames"); + numcol= CustomData_number_of_layers(data, CD_MCOL); + obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames"); } for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { @@ -500,12 +500,12 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) if (layer->type == CD_MTFACE) { strcpy(obr->mtface[mtfn++], layer->name); - obr->actmtface= layer->active_rnd; + obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf); obr->bakemtface= layer->active; } else if (layer->type == CD_MCOL) { strcpy(obr->mcol[mcn++], layer->name); - obr->actmcol= layer->active_rnd; + obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol); } } } diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index f477df3ed8c..c53a2b68c9c 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -296,7 +296,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) minz= 1.0e30f; maxz= -1.0e30f; Mat4CpyMat4(viewmat, lar->shb->viewmat); - if(lar->mode & LA_LAYER) lay= lar->lay; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; maxtotvert= 0; for(obr=re->objecttable.first; obr; obr=obr->next) @@ -1520,7 +1520,7 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) minmaxf[2]= (2.0f*root->box.ymin - size-2.0f)/size; minmaxf[3]= (2.0f*root->box.ymax - size+2.0f)/size; - if(lar->mode & LA_LAYER) lay= lar->lay; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; /* (ab)use zspan, since we use zbuffer clipping code */ zbuf_alloc_span(&zspan, size, size, re->clipcrop); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 5b69323667e..5a80173d1f1 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1761,7 +1761,21 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) if(shi->combinedflag & SCE_PASS_SPEC) VECADD(shr->combined, shr->combined, shr->spec); + /* modulate by the object color */ + if((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { + if(!(ma->sss_flag & MA_DIFF_SSS) || !has_sss_tree(&R, ma)) { + float obcol[4]; + + QUATCOPY(obcol, shi->obr->ob->col); + CLAMP(obcol[3], 0.0f, 1.0f); + + shr->combined[0] *= obcol[0]; + shr->combined[1] *= obcol[1]; + shr->combined[2] *= obcol[2]; + shr->alpha *= obcol[3]; + } + } + shr->combined[3]= shr->alpha; } - diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 29aa6e3be29..76a47a11338 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2410,7 +2410,7 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4]; int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1; - if(lar->mode & LA_LAYER) lay= lar->lay; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; /* 1.0f for clipping in clippyra()... bad stuff actually */ zbuf_alloc_span(&zspan, size, size, 1.0f); @@ -2981,10 +2981,11 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * { ZSpan zspan; DrawBufPixel *rectdraw, *dr; - static float jit[16][2]; + static float jit[256][2]; float v1[3], v2[3], v3[3], v4[3], fx, fy; - float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz, *minvecbufrect= NULL; - float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed; + float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz; + float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro; + float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed, totfac; int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples; int tsktsk= 0; static int firsttime= 1; @@ -3003,6 +3004,9 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * rectmove= MEM_mapallocN(xsize*ysize, "rectmove"); rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw"); zspan.rectp= (int *)rectdraw; + + rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight"); + rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max"); /* debug... check if PASS_VECTOR_MAX still is in buffers */ dvec1= vecbufrect; @@ -3142,7 +3146,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dm= rectmove; dvec1= vecbufrect; for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) { - if(dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f) + if((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f)) *dm= 255; } @@ -3151,9 +3155,12 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ if(firsttime) { firsttime= 0; - BLI_initjit(jit[0], 16); + BLI_initjit(jit[0], 256); } + memset(newrect, 0, sizeof(float)*xsize*ysize*4); + totfac= 0.0f; + /* accumulate */ samples/= 2; for(step= 1; step<=samples; step++) { @@ -3161,7 +3168,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * int side; for(side=0; side<2; side++) { - float blendfac= 1.0f/((ABS(step)*2+side)+1), ipodata[4]; + float blendfac, ipodata[4]; /* clear zbuf, if we draw future we fill in not moving pixels */ if(0) @@ -3193,30 +3200,32 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata); - for(fy= -0.5f+jit[step & 15][0], y=0; y1) { + float jfx = fx + 0.5f; + float jfy = fy + 0.5f; DrawBufPixel col; /* make vertices */ if(nbd->curved) { /* curved */ quad_bezier_2d(v1, dz1, dz1+2, ipodata); - v1[0]+= fx; v1[1]+= fy; v1[2]= *dz; + v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz; quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata); - v2[0]+= fx+1.0f; v2[1]+= fy; v2[2]= *dz; + v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz; quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata); - v3[0]+= fx+1.0f; v3[1]+= fy+1.0f; v3[2]= *dz; + v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz; quad_bezier_2d(v4, dz2, dz2+2, ipodata); - v4[0]+= fx; v4[1]+= fy+1.0f; v4[2]= *dz; + v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz; } else { - v1[0]= speedfac*dz1[0]+fx; v1[1]= speedfac*dz1[1]+fy; v1[2]= *dz; - v2[0]= speedfac*dz1[4]+fx+1.0f; v2[1]= speedfac*dz1[5]+fy; v2[2]= *dz; - v3[0]= speedfac*dz2[4]+fx+1.0f; v3[1]= speedfac*dz2[5]+fy+1.0f; v3[2]= *dz; - v4[0]= speedfac*dz2[0]+fx; v4[1]= speedfac*dz2[1]+fy+1.0f; v4[2]= *dz; + v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz; + v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz; + v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz; + v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz; } if(*dm==255) col.alpha= 1.0f; else if(*dm<2) col.alpha= 0.0f; @@ -3229,26 +3238,59 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dz1+=4; dz2+=4; } - + + /* blend with a falloff. this fixes the ugly effect you get with + * a fast moving object. then it looks like a solid object overlayed + * over a very transparent moving version of itself. in reality, the + * whole object should become transparent if it is moving fast, be + * we don't know what is behind it so we don't do that. this hack + * overestimates the contribution of foreground pixels but looks a + * bit better without a sudden cutoff. */ + blendfac= ((samples - step)/(float)samples); + /* smoothstep to make it look a bit nicer as well */ + blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f); + /* accum */ - for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4) { + rw= rectweight; + rm= rectmax; + for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) { if(dr->colpoin) { - float bfac= dr->alpha*blendfac*dr->colpoin[3]; - float mf= 1.0f - bfac; + float bfac= dr->alpha*blendfac; - dz2[0]= mf*dz2[0] + bfac*dr->colpoin[0]; - dz2[1]= mf*dz2[1] + bfac*dr->colpoin[1]; - dz2[2]= mf*dz2[2] + bfac*dr->colpoin[2]; - dz2[3]= mf*dz2[3] + bfac*dr->colpoin[3]; + dz2[0] += bfac*dr->colpoin[0]; + dz2[1] += bfac*dr->colpoin[1]; + dz2[2] += bfac*dr->colpoin[2]; + dz2[3] += bfac*dr->colpoin[3]; + + *rw += bfac; + *rm= MAX2(*rm, bfac); } } } } + /* blend between original images and accumulated image */ + rw= rectweight; + rm= rectmax; + ro= imgrect; + dm= rectmove; + for(dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) { + float mfac = *rm; + float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw); + float nfac = 1.0f - mfac; + + dz2[0]= fac*dz2[0] + nfac*ro[0]; + dz2[1]= fac*dz2[1] + nfac*ro[1]; + dz2[2]= fac*dz2[2] + nfac*ro[2]; + dz2[3]= fac*dz2[3] + nfac*ro[3]; + } + MEM_freeN(rectz); MEM_freeN(rectmove); MEM_freeN(rectdraw); MEM_freeN(rectvz); + MEM_freeN(rectweight); + MEM_freeN(rectmax); if(minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */ zbuf_free_span(&zspan); } diff --git a/source/blender/src/CMakeLists.txt b/source/blender/src/CMakeLists.txt index 342579fb3b0..d95551940f8 100644 --- a/source/blender/src/CMakeLists.txt +++ b/source/blender/src/CMakeLists.txt @@ -35,7 +35,7 @@ SET(INC ../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue ../quicktime ../../../intern/elbeem/extern ../../../intern/ghost ../../../intern/opennl/extern - ../nodes ../../../extern/glew/include + ../nodes ../../../extern/glew/include ../gpu ${PYTHON_INC} ${SDL_INC} ) diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile index 001efc58b5d..46e916b0437 100644 --- a/source/blender/src/Makefile +++ b/source/blender/src/Makefile @@ -68,6 +68,7 @@ CPPFLAGS += -I.. CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../../gameengine/SoundSystem CPPFLAGS += -I../ftfont +CPPFLAGS += -I../gpu # Only used by py_demo.c !!! CPPFLAGS += -I../radiosity/extern/include diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index 229cc87ef37..c8c517e15ff 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -26,7 +26,8 @@ incs += ' #/intern/bsp/extern ../radiosity/extern/include' incs += ' #/intern/decimation/extern ../blenloader ../python' incs += ' ../../kernel/gen_system #/intern/SoundSystem ../readstreamglue ../nodes' incs += ' ../quicktime #/intern/elbeem/extern' -incs += ' #/intern/ghost #/intern/opennl/extern #/extern/glew/include' +incs += ' #/intern/ghost #/intern/opennl/extern' +incs += ' ../gpu #extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/blender/src/blenderbuttons.c b/source/blender/src/blenderbuttons.c index e15ef3fd898..f29397b2156 100644 --- a/source/blender/src/blenderbuttons.c +++ b/source/blender/src/blenderbuttons.c @@ -1,2181 +1,2139 @@ /* DataToC output of file */ -int datatoc_blenderbuttons_size= 69599; +int datatoc_blenderbuttons_size= 68242; char datatoc_blenderbuttons[]= { -137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144, -206,103, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167, -147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0,154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,216, - 5, 19, 11, 8, 1, 11,126, 22,156, 0, 0, 32, 0, 73, 68, 65, 84,120,218,236,125,121, 92, 84,229,254,255,251, 57,179,179,239, -168,184,128,138,251,130,224, 26,106, 80,168,201,215, 52, 21, 48,179,237,214,189, 78,150,173,150,102,117,111,245,203, 43,106,218, -170,233,216,162, 89,106, 9,106,120,115, 5, 29,212,144,220, 21, 75, 19, 5, 17, 65,144,109, 96,134,217,207,156,231,247,199,204, -208,128,192, 44,160, 81,205,251,197,188,152,115,230,204,123,158,115,158,229,253,249,124,158,141, 68, 69, 69, 81,184,225,134, 27, -110,184,225,134, 27,127, 43, 48,238, 71,224,134, 27,110,184,225,134, 27,127, 31,156, 57,155, 5, 0, 32,238, 8,128, 27,110,184, -225,134, 27,110,184, 35, 0,110,184,225,134, 27,110,184,225,134,219, 0,112,195, 13, 55,220,112,195, 13, 55,220, 6,128, 27,110, -184,225,134, 27,110,184,241,151, 0,223,246, 96,222,188,121,196, 85,162,181,107,215,222, 54,150,192,205,231,230,107, 5,116,237, -218,181,127, 88,250,178,179,179,105, 92, 92, 28,113,231,199,159,151,239,220,185,115, 46, 23,190,168,168, 40,184,243,195,205,247, - 87,230,115,218, 0,248, 59, 67, 42,149, 54,122,128, 50,153,140,116,228,116,174, 91,183, 14,132, 16,226,206, 57,215,242,120,246, -236,217, 72, 79, 79,111, 56, 78, 74, 74,250, 75, 60,203, 61,123,207,180,218, 16, 36, 78,142,254, 75,151, 25,137,255, 78,136,117, -189, 17, 1, 3,234,177, 23,249,218,183, 58,108, 89,236,168,109,140, 27,127,211, 8,192,221, 40,172,123,246,236,137,203,200,200, -144, 91,143,167, 77,155, 22,159,152,152,152,221, 17, 30, 6,165,230,182,179,163,234,170, 84, 42,165, 69, 69, 69, 0,128,240,240, -112, 0,248, 83, 52, 34, 77,141, 43,139,129,213,162,103,238, 40,239,214,173, 91, 29, 54,212,164, 82, 41,221,182,109, 91,195,241, -206,157, 59, 49, 97,194,132,134,227,244,244,116,250, 71, 25, 1, 49, 49, 49, 20, 0, 78,159, 62, 77,218,227,186,140, 31,100,173, - 24, 0,178, 54,231, 95, 88, 68, 55, 0,192, 45,157, 14,172, 86,111, 62, 89,171, 4, 0, 36, 39, 39, 35, 33, 33,161,197,244,173, - 79, 88, 79, 35,203, 34,157,250,253,248, 95,227, 29,200, 23, 9,252,159,189, 0, 93,198, 78, 40, 20,211,161, 0, 16, 45,121, 31, -111, 73, 78,163,155, 24,168,212, 21,224, 45,109,138, 83,191,155,149,149, 21,151,150,150, 38,183, 61,151,156,156, 28,159,144,144, -144,221,145,234, 86,123,181, 1,127,134,251,189, 19,120,231,141, 23,136,151,192,151,232,197, 66,170,175,213, 50,245, 90, 37,247, -193, 39,171,255, 22,179,227,236, 26, 0,123,246,236,137,179,254,111,171, 80, 91, 27,146,119,183, 45,129, 87, 55, 95,212,223,168, -195,219, 41,111,201, 51, 50, 50,224,182,134,237, 67, 38,147,145,240,240,112, 90, 84, 84,132,162,162, 34,236,219,183,175,195,122, - 18,214,188,150,201,100, 68, 38,147, 9,164, 82,169,113,197,138, 21, 39, 1, 96,225,194,133, 35, 90,251,238,244,233,211, 27,222, -179,172, 9, 6,163, 30, 6,189, 1, 6,131,249,197,178, 44, 22, 46, 92,232, 84, 90,108,197,191, 57, 76,152, 48,225, 15, 53, 2, - 28, 49,126, 98, 98, 98,236,114, 36, 78,142, 38,174,136,188,195,240,243, 65, 94,225,119,144,160, 43, 76,200, 65,197, 23,103,112, -190,160, 26, 51,150,109,112,232,235,145,101,145, 14, 10,186, 25,242,129,114,187, 13,177, 36,241, 45, 4, 76,123, 26,165, 47, 69, - 3, 90, 69,195,249, 51,218,215,112, 6, 0,180,192,120, 73, 50, 14,250,159,134, 31,128, 24, 69,140,195,229,183, 41,210,210,210, -228,105,105,105, 29,162,189,178,166,177, 61,218,128, 63,195,253,182, 55, 54,173, 89, 75, 30, 13,139,224,191,144,244, 56, 47,164, -127, 24,195, 39, 33, 68, 83, 87,199,137, 17,106, 98,186,116, 53,233,110, 94, 51, 57,248,236,110, 58,209,134,119,113,128,111,129, - 19,124,171,238,168, 1,144,145,145, 33,223,246,239, 55,144,242,222, 82,121, 98, 98, 34,105, 75, 1,179, 10, 63, 0, 84,105,170, -129, 64, 96,241,193,119,160, 44, 84, 64,250,175,142, 37,100, 45, 85,136, 63, 58,141,182, 70,192, 3, 15, 60,128,162,162, 34,132, -135,135,119,184,103, 39,151,155, 29,137,248,248,120, 42,147,201, 24,153, 76, 22, 38,149, 74, 75, 87,172, 88,113,218, 81, 30,150, -101, 97, 48, 24, 27,132,223, 86,252, 79,157, 58,133,225,195,135, 59,149,174,148,148,223, 61,192,217,179,103, 35, 51, 51,179,145, - 1,208, 30,101,197,149,124, 56,125,250, 52,201,206,206,166, 19, 39, 78,188,237,179, 3, 7, 14, 96,235,214,173, 13,199,173,141, - 91,184,205,120,111,199,238,128,176,136,110, 40, 85,212, 97,199, 51, 51, 17, 72, 98, 81,240,249,171,232, 57,189, 39, 50,157, 16, -127, 43,230,206,157, 75, 1, 96,253,250,245,109, 46,179, 97,219,114,160,185, 94,143, 82,105, 68,171,215, 93, 16,103,225,221,193, -183,144,122,225,205, 54,229,103,123,136,110,123,114,180, 71, 36,224, 78,223,111,123, 33, 39, 39,199, 3,192, 61, 0,188,108, 78, -215, 2,200,139,141,141,173,113,148, 71,203,105, 25, 67,149, 94, 48,121,234,116,177, 2, 70,177, 64,192,231, 43,117, 98, 70, 40, -212,114, 60, 31, 79,214, 32, 49, 26,249,229, 55,245, 98,158, 72,167, 51,233, 77, 82,169,148, 52, 55,102,196, 22,181,181,181,255, -181,190,207,207,207,175,242,244,244,100,212,106, 53,103,123,205,200,145, 35, 63,116, 52,141,148, 82,187,194, 78, 8, 89,208,214, -103,202,183,231,253,247,233,211, 7,145, 94, 62,104, 75, 20,192, 86,252,171, 52,213, 72,189,255,157,134,207,254,145,241, 44, 16, - 2, 76, 95,145,226, 84, 33,107, 73,160,219, 75,164,111,220,184, 1, 0,232,214,173, 91,163,247,214,223,181, 87, 32,238,100,136, -207,214, 8, 48, 26, 89,172, 91,183,238,142,121, 1,206,114, 54, 17,127,219,239,223,148,201,100,254, 82,169, 84,225,176,248, 27, -141, 48, 24,244,208, 27, 12, 48, 54, 17,127,202, 57, 23,161, 75, 73, 73,193,169, 83,167, 26,142, 87,173, 90,133,164,164,164,134, -227,244,244,244, 54, 27, 59, 54, 6, 79,155,203,159,173,240,207,158, 61, 27,195,134, 13,115,137,167,189,186, 3, 74, 10,139,161, -222,249, 31,120, 61,245, 49,194, 34,186, 33, 52, 80,130,194,157,133,102,241,247,243, 49,119, 1, 8,120, 14,113,181,135,240, 3, - 64,159,139, 87,113,227,237, 37,208,166,109,108, 61, 66, 32,145, 64,167,211,161,160,160, 0, 21,186,203,232,131,176, 22,175,205, -202,202,138,107,173,236,203,100, 50, 98,173, 39, 89, 89, 89,113,206,132,199,109,163, 98,214,250,106,123,206, 89, 71,160, 37,225, -118,166, 45,104,238,126, 51, 51, 51, 41, 33, 4, 9, 9, 9,164, 45,247,107,197,211, 79, 63, 77,191,252,242,203, 54,229,121, 78, - 78,142, 47,128,233, 7, 15, 30,252, 15,199,113,122, 27, 17,228,243,120, 60, 79, 0,255,140,141,141,221, 99,143, 39,191, 48,159, - 47, 17,138,197, 2,129,200,147,225, 19, 31,202, 19,121,112, 60, 30,159, 35, 12, 56,194, 55, 81, 30, 79,207,227,136, 78,205, 51, -105, 60,133, 2,194,235,213, 77, 39,158, 26,194,161,216,126, 26, 21, 10,133, 82,163,209,176, 0,160, 86,171,185, 55,222,120,163, - 65,240,151, 46, 93,250,114, 91,203,251,132, 9, 19,158,177,190,207,204,204, 92,215, 30,117,136,177,231,253, 47,153,149, 4, 93, -101, 37, 94, 29,216, 15,182,125,247, 14,123, 33,150, 46, 4, 91,241,159, 54,109, 90,188, 76, 38, 35,211,166, 77,139,223, 48,237, - 51,115,100,177,111, 80,163,235, 29,193,194, 53,249, 88,184, 38, 31,207,173,188,132, 39,222,251, 5, 51, 22,159,107,243, 3, 41, - 41, 41,113,200, 48,184, 91,226, 95, 84, 84,212,162, 48,135,135,135,195,104, 48, 96,212,200,145,109,254, 29,107,152,124,219,182, -109,144,203,229, 13,175,214, 12,173,150,196, 48, 62, 62,190,169,248, 55, 24,202,142, 52, 76, 44,107, 50,123,254,122,115,232,191, -169,248,155, 76, 38,168,181,106,167,238,209, 26, 49,104, 26, 53, 72, 79, 79, 71,122,122,122, 35, 99,192,169,251,205,110,220, 30, -202,179,179,157,122,102,173,137,255,236,217,179,177, 98,197,138, 6,241, 23,240, 5, 78,241, 36, 78,142, 38,150, 46,152,102, 95, -206,112,105, 81,140,250,233,163, 64,211, 94, 69, 73, 97, 49,232,244,254,191,123, 43,105,175,130,223, 57, 24,240,243,187,171, 30, -161,186,170, 0,218,180,141,160,148,226,194,133, 11, 24, 63,126, 60, 36, 18, 73, 35,225,247,247,247,135, 86,171,133, 86,171, 69, -105,105, 41, 30,209,190,128, 47,252, 95,106,145,211,218, 7,222,218,243,177,126,214,180,191,220, 81,225,110, 47,103,197,250,221, -166,226,111,207, 65,106,237,126, 51, 51, 51,105,122,122, 58,210,210,210,144,149,149, 69,219,122,191, 79, 63,253, 52,229,243,249, -120,250,233,167, 93,174, 19, 57, 57, 57, 98, 0,255,202,202,202,122,227,189,247,222, 59, 78, 8, 9,183,190, 0,116, 13, 12, 12, -244, 56,116,232,208,218,156,156,156,241,173,241,152, 40,199,227, 17,129,200,192, 82, 31,189,222, 24, 98,226,184,174, 38,142,139, - 48, 17,210, 29, 60, 94, 32, 33,196, 15,132,231,195, 81, 4, 80, 3,231,167,212, 26, 61, 67,124, 88, 30, 51, 82,229, 80, 30,105, - 52, 26,182,169,215,223,209,193, 56,226,253,107,202,203, 48,121, 88,180,211, 2,109, 53, 34,222,221,182, 4, 0, 26,196,223, 26, - 69, 72, 76, 76,204,182, 26, 1, 37,202,155,136, 94, 56,218, 41, 35, 67,173, 53, 65,173, 53,161,172, 90,143,210, 74, 29,110,220, -210,185, 36,124,214,202, 98, 79,252,255, 40,180,100, 4, 0,128,206,160,135, 78,167,115,153,219, 42,218,214, 62,242,224,224, 96, - 91,111, 22,142, 54, 38, 77, 61,225,150, 66,137,142, 52,122, 6,163,222,236,249,235, 13, 48, 24, 27,139,191,209,104,132, 90,173, -134, 74,169,250, 67,243,196,108, 48,165,217, 6,228,172,127,216,182, 45,205,101, 35,192, 86,252,173,194,207, 48, 12,196, 98, 49, - 60,189, 60,218,148,230, 61,123,207,208,150, 94,246,190,187,111,241, 59, 8, 68, 44,216,132,231, 1, 0, 94,185, 87,113,190,160, -218,108,176, 37, 60, 15,227,133,119,129,170,106,167,210, 51,119,238, 92,106,237, 14,112, 5,158,168, 2, 0,108,220,184, 17, 25, - 25, 25,120,255,253,247,113,226,196, 9,232,245,122, 84, 84, 84, 88,189,178,134,235,195,194,194,160, 5,192,195,181, 63,164,188, -180, 84,238,155,122,243,174, 26, 20,205,117, 11, 56,203,103, 27, 9, 75, 75, 75,107,211, 61, 91,197, 31, 0, 92, 53, 2,114,114, -114, 58, 89,196,127,238,215, 95,127,125,241,173,183,222,122,104,203,150, 45,232,211,167, 15, 0,160, 71,143, 30,168,171,171, 19, -189,251,238,187,167, 15, 29, 58,244,109, 78, 78, 78,120,179, 68, 4, 0, 71, 9, 56, 86,108, 50,177, 1, 38,214,212,213,104, 50, -246,230, 49,164,139,144,207, 8,196, 2,158,150,239, 33,172,245,244,230, 41,121, 98,202,138,121, 60, 79, 62,107,240,185,118,230, -172,232,177,224,143,236,166, 59, 63, 63,191, 74,173, 86,115,205,133,249,135, 14, 29,122,217, 96, 48,180, 91, 89, 26, 58,116,104, -187,113,241, 91, 19,238,207,231, 62,253,187,216,150,220,192,171, 3,251, 97,101, 70,134,211, 99, 1,172,222,191, 85,244, 27,121, - 41,137,137,217, 25, 25, 25, 0,128,192,193,157,156, 74,124,189,214, 4,149,134,133, 82,205,162,174,158, 69,173,138,117,250, 1, - 52, 55,242,223,214,203,183,125, 95, 88, 88,136,218,218,218,187,214,104,172, 91,183, 14,225,225,225,176, 14,250,179,237,235,151, - 74,165,116,221,186,117,208,105,181, 46, 27, 0, 82,169,148,110,216,176, 1, 37,165,165, 16,240,120, 8,237,212,169,145,248,223, -127,255,253, 72, 73, 73,113,168,113,146,201,100, 36, 62, 62,190,145, 17,208, 52,146,225,232, 88, 5,131,222, 0,131, 94, 15,163, -209, 0,150, 53, 53,136,191, 94,175,135, 70,163, 65,125,125, 61, 84, 42,231, 13, 0,219, 46, 0, 43, 92,245,252,183,165,109, 3, - 40, 80,101, 17, 26,106, 46, 68, 32,148,154,141,128,180, 52,164, 36, 39, 59,221, 29,208, 84,252, 5, 2, 1, 68, 34, 17,196, 98, - 49,196, 98,177, 75,247,221,168, 94,183,208, 37, 96,175, 75,107,198,186,237,160, 83, 35,112,107, 76, 52, 2, 17, 11,201,204, 79, -193,150, 85, 2,126, 62,224, 87,111,197,143, 31,157, 6,120, 60,167,210,210,214,174, 0, 53,207,220,166,164,166,166,162,178,178, - 18,107,215,174,197,208,161, 67,241,222,123,239, 33, 58, 58, 26, 90,173,182,169,135,102, 53,169,239,170,240, 59, 42,208,174,118, - 7,180,100, 72,184,194,147,156,156,220, 32,252,174,212,141,230,196,191, 65,108,248,124,176, 44,235,108,119,128,119, 94, 94,222, - 39,243,230,205, 59, 50,120,240, 96, 31, 0,120,231,157,119,144,159,159, 15, 0, 24, 61,122, 52,118,236,216,129,177, 99,199,122, - 62,242,200, 35, 5,217,217,217, 89, 60, 30,239,145,219, 27,122, 32, 32, 48,128, 43, 44, 44, 96,179,229, 7,247,246,238, 29,153, - 29,209, 35,252, 34,207, 91, 82,193, 35, 66, 53, 35, 18,104, 24,177,135,202,192,231, 25, 64,141, 60, 78,108,244, 86,149, 86,123, -157, 56,116,110,100,144,127,232, 14,187,198,168, 77,159,255,206,157, 59,159,152, 62,125,250,215,214,176,191, 82,169,100,132, 66, - 97,155,203, 82,123,133,253,237, 70, 0,172, 94,254,240, 94,145,208, 85, 86, 66, 93, 98, 22,193,241, 22,239,208,217, 40, 64,225, - 47, 87,111,227,110,238,184,250, 66,185, 83,137,111,171,248,219, 10, 63,165, 20,221,186,117,107,244,153,209,104,108,120,213,214, -214, 66,173, 86,163,166,166,230,174, 53, 30,214,121,254,251,246,237,107, 20, 9,176,138,255,144, 33, 67,160,211,105, 27, 26, 58, -106,181,102, 28,108,152,214,124,182, 6, 70,163, 17, 93,195,194, 96, 52,153,154, 21,127,103, 26, 18,139, 17,112,155, 87, 98,157, -186,216, 90, 36,227, 54, 3,192, 96,108, 16,255,147, 39, 78, 66,163,213, 66,165, 82,161,174,174, 14,181,181,181,141, 60, 59,103, - 97,237, 6,112,181,223, 31, 0,170,171,170, 81, 93, 93,133,170,234, 26, 84, 85, 87,163,186,186, 26,213, 85,102,143,180, 95,255, -254,168,177,188,119,214,251, 7,128, 97,195,134,253,238,245,123,122,194,203,203, 27,222, 94,222, 80,169, 84,241,109, 41, 79,173, -117, 9,216,251,110,193,251,115, 33,152,249, 41, 2, 17, 11,126,238,167, 48,110,127, 30,240,243,193,174,103,147,112,125,215, 53, - 60,184, 98, 19,192,191,203,203,138,232,174, 67, 18, 38,129, 90,173,134, 78,167,131, 70,163, 65,110,110, 46,150, 45, 91,214,236, -229, 30, 30,214, 8,202, 85,167,197,219, 85,175,218,246,249, 54,125,222, 45, 29,183,197,200,104,174, 91,192, 25,158,132,132, 4, -146,156,156,140,164,164, 36, 76,152, 48,193,229,200,196,151, 95,126, 73, 88,182,113,155,204,178, 44,156, 29, 11, 16, 27, 27,123, - 37, 57, 57,121,232,150, 45, 91,198, 31, 61,122,212, 59, 33, 33,225,132, 85,252, 45,142, 42, 68, 34, 17,189,126,253,186, 96,239, -222,189,125,253,253,253, 79,198,198,198, 22, 52,199, 85, 87, 91,199, 69, 70,244, 81,141, 30, 61, 58,233,226,197, 95,239, 83,170, - 85,157, 40,107,100,193,192,200,234, 25,189, 94,175,215, 42, 81,174,228,244, 58, 85,105,113, 57,251,227,238, 61,203,131, 2,131, - 43, 12, 6,141, 93,247,189, 57,239, 95,161, 80,240, 1,192,199,199,167,195,118, 11, 48, 45,121,255,219,254,253,134,217,106, 46, - 47,107,244,153,179, 99, 1,166, 77,155, 22,191,230, 95, 31, 3, 48, 15,248,203,200,200,144,219, 78, 45,204,200,200,144, 79,248, -230, 33, 0,192,153, 21, 63, 99,218,180,105,241,119,235,230,109, 43, 73, 73, 73, 73,131,183,111, 21,125,155,204,133, 74,165,130, - 78,167,179,105, 68,238, 94, 26,159,121,198, 60,246,195,200,178,184,120,241, 34,206,158, 57,131,161, 67,134, 66,167,211, 65,171, -213, 65,167,213,226,219,111,190,129,245, 58, 71, 42,250,170, 85,171, 48,160,255, 0, 24,141, 70, 92,185,114, 5,172,209,128,210, -146,210,118,125,166,214, 99,203,154, 5, 8, 15, 15,119,168, 97, 50, 24,245, 96, 77,230,176,255,241,227, 63, 67,173, 85,163, 94, -165, 68, 93, 93, 29, 20,181,181, 80, 40,106,218,100,136, 89, 35, 1,109,241,112,142, 28, 57, 2,149, 74, 5,149, 74,105,249,175, - 66, 80, 96, 32,250,245,239,143,223, 46, 93,194,225, 35, 71,156,230,180,122,255,124,190, 0, 30, 30, 30,240,242,242,130,183,151, - 23,188,188, 60, 80,163,168,137, 7,144,125,167, 67,253, 45,225,124, 65, 53,140, 23,222, 69, 53,114, 64, 18, 87,130,196,254, 7, - 5,239,207,197,212, 21, 95, 67, 44, 96, 0, 1,223,252,114, 1,174,118, 5,148, 78,249, 12, 1, 91,167, 64,163,209, 32, 32, 32, - 0, 10,133, 2, 10,133, 2,199,142, 29, 67, 89, 89, 89, 67,152,184,225,250,210, 82, 60,235, 47, 65,144, 71,101,107, 30,112,188, -173,168,218, 14,146,179,190,183,126,102,189,214, 21,239,220,209,238, 1, 71,197,223, 85,207,191,185,251, 77, 72, 72, 32, 19, 38, - 76, 32,109,185,223,166, 70,128, 43,226,111, 69, 80, 80, 80,222, 67, 15, 61,244, 72,106,106,106,223,243,231,207,199, 74, 36, 18, -222,212,169, 83,137, 72, 36, 2,199,113, 36, 49, 49, 49,239,197, 23, 95, 28, 50,104,208,160, 93,255,252,231, 63,159, 48,153, 76, -213,173,196,188,185, 95, 47, 93, 57, 57,104,240,144, 71, 79,158, 56, 49, 99,215,238,255, 45, 61,117,226, 68,167,139,249,191,137, -175,148, 22,208,111, 63,254, 94,146,186,234,253, 1, 89,187,119,175,234,221,171,247,143, 94,161,158, 71, 98, 99, 99, 77,112, 48, -229, 9, 9, 9, 56,121,242,100,212,186,117,235,222,213,233,116,130,247,222,123,239,131, 93,187,118,205, 46, 45, 45,189,187,194, -209,214, 46,128,192,107, 69,168,177,132,254,109, 49, 62, 56, 24, 43,241,155,227, 94,135, 37,196,255,219,233,139,240,235, 27,132, - 9,223, 60,132,140,199,126,144, 91,195,254, 86,241,183,122,255,206,204, 50,216,145,218, 62, 35,241, 9, 33,184,116,233, 18,172, -133,181,105,152, 85, 32, 16, 64, 32, 16,160,178,178, 18,137,137,137,119, 61,147,172,163,254,215,173, 91,135,145, 35, 71, 66,167, -215, 67,171,211, 66,103, 25,220,164,213,153,187, 1, 86,175, 94,109,183, 49,145, 74,165,116,197,138, 21, 48,153, 76, 56,125,250, - 12, 4,124,115,216, 54, 50, 50, 18,215,138,138, 80, 90, 90,138,173, 91,191,195,236,217, 15,227,224,193,131,212, 54, 18,208, 90, - 3, 36,147,201,132, 0, 88,169, 84,202, 53,231, 1, 57, 51, 85,209,234,249,231,230,230, 66, 93,175,105, 48,192,148, 42, 37,148, -202, 58, 40,149,245, 46,135,194,173,222,191,101, 37, 64,151, 12,129,217,179,103, 55, 58,142, 8, 15, 71,191,254,230, 65,113,191, - 93,186,132,107,150,136, 71,211,235, 28,193,152,123,198, 64, 36, 20, 65, 34,145, 64, 44, 22, 67, 36, 18,161,188,188,220, 97,241, -183, 23,234,119,117,141,128, 25,203, 54, 96, 7,128, 7, 82,255, 15, 52,237, 85,144,148, 85, 56, 95, 80, 13, 18,224,143,171, 37, - 74,179,247,239,100, 23, 64,211,174, 0,167,167, 7,106,181, 0,175,160, 73,120,223, 44,244, 70,163, 17, 95,124,241, 5,198,143, -255,125, 92,216,193, 39,195,128, 10, 13,250,238, 81, 32, 42,184, 71, 75, 13,120,118,147,190,111, 57,208,208,252,203,155, 94,235, -138, 96,183,214,111,239,170,231,239,170, 33,113,167,239,215, 98, 4,180,121, 22, 64,120,120,248,214,177, 99,199, 6,159,203,203, - 75,209,106,181, 67,228,242, 67, 18,145, 88,196,103, 8,131, 67,135, 14,121, 15, 24, 48, 96, 83,114,114,242,127, 42, 43, 43,237, -122,235,179,103,205,228,126,220,251,227,225,161, 67,135, 45, 52,176,250, 7,174,230, 95, 89,202, 21, 21,176, 0,168, 24,140,113, -112,239,190,105, 33, 33,193,123,120,124,225,183,255,125,107,185,225,219,141, 27, 44,125,124, 45, 99,228,200,145, 31, 38, 36, 36, - 0, 0, 42, 43, 43,145,149,149,229,243,213, 87, 95, 45, 5,128,147, 39, 79,142, 28, 56,112,224,190, 63,133, 1, 96,245,206,239, -255,118, 75,235, 94,134, 19, 83, 2,173,214,111,244,194,209, 8, 28,220,169, 65,244,109, 67,255,103, 86,252,236,148,229,218, 94, -115, 82,173,105,235,223,191, 63, 46, 92,184,208, 72, 88,106,107,107, 11, 0,244,106,238, 59,174,174,189,220,214,116, 54, 61,255, -237, 55,223, 66,167,211, 65,111,208,195, 96, 48, 96,197,138, 21,176, 39,254, 86,112,156, 9, 98,137, 23,180, 90, 29, 46, 93,188, - 8,190, 64, 0,163,193, 0, 15, 79, 15,108,221,186, 21, 60, 30,207, 58,119,190,213,123, 93,177, 98,197, 62,169, 84,106,144,201, -100, 33,214,116, 54, 89, 7,192,169,208,230,194,133, 11,145,147,147,131,250,250,122,212,171,213, 80, 41,149, 22,241, 87, 66,165, - 84,161, 94, 85, 15,181, 77,131,239,200,179, 27, 62,124, 56, 61,117,234, 84,131,247,223,220, 52, 64, 71, 23, 1,138,139,139,187, - 45, 47,172,162,127,246,236,217, 6,111,222,209,123,142,137,137,161,214, 69,126,188, 60,188, 32,150,136,161, 82,169,226,109,250, -176,157,106,120,239,212, 98, 64, 86, 35, 96,122,234, 87,160,219,129,160, 39,101,200,126, 41, 9, 99,151,111, 6, 4, 2,120,138, -219,214,207,217,212, 16, 0, 0,121,142,189, 96,227, 45, 12,222,231,129,242,255,105,160, 88,242,251, 89,163,209,136,113,227,198, - 1, 0,194,252, 37,248, 73,214, 13,239, 47,187,129,207,206,104, 91,101,179,245,248, 1,243, 64, 56,107,195,222,116, 80,156,179, -211,226,108,199,239,180,213,243,111,174, 77,112,133,235, 78,222,175,173, 17,208, 30,229,111,224,192,129,159,168,148,170,189, 35, - 98,134,143, 84, 41,149, 1,172,137,213,135,134,134, 86,134,133,133,149, 43,149,202,243,149,149,149, 14, 55, 10, 83, 38, 79,225, - 0,108, 61,122,228, 68,110,236,216,177, 63, 72, 36, 18, 95, 2,202, 17, 66,192,113,180, 78,171, 86,200, 47,231, 21,171,190,221, -184,193,161,118,222,250,204, 0,243, 64,234,166, 3,245,150, 45, 91,246,159, 63,133, 1,144,152,152,152,221,150, 5,127, 28, 41, -172, 86, 67,192, 42,252,237, 41,232,109, 73,219,224,193,131,113,242,228, 73, 84, 86, 54,132, 8,123, 1, 64,117,181, 57,162,244, -216, 99,143,253,161,153,213,244, 25, 81, 74,233,163,143, 61,138,213,171,215, 88,250,204, 89,248,250,250, 18, 71,191,111,133, 68, - 34,182,242,153,189, 41,181,198,246, 59, 0,236,110, 54,209,127,197,138, 21, 87,164, 82,105,133, 76, 38,227,217, 14, 8,180, 76, - 11,116,184,161,179,206,125,143,141,141,109,247,103, 55,124,248,240,166,123, 1, 52,124,238,236, 10,128, 50,153,140,100,103,103, -211,173, 91,183, 54, 90,168,199,202,237, 74,121,142,139,139, 35, 70,214, 8,163,202,216,174,247,222, 90,232,223,217,189, 1,102, - 44,219, 0,216, 44,252,115,239, 27,191,143, 75, 82,183, 83,122, 27, 69, 0, 6,182,110,124,150,198,150,162, 20, 64,244,251,254, - 88,114,186, 15,130, 1, 84, 22,168,209,187,119,111, 0,192, 39, 75,252, 49,105, 68, 48, 34, 38,229, 59,244,219,206, 76,117, 75, - 75, 75,147,183,182,236,177,189,246,166, 61,218,188,182,114,221,141,251,109, 79,140, 30, 51,250, 10,128, 43,183, 69,172, 3, 3, - 93,226, 27, 55,126,100, 17,154, 29, 21, 26,134,222,125, 6, 57, 99, 72,181,235,125,182,199, 34, 63, 46, 25, 0,119, 90,192,246, -236,217, 19,151,177,162,227,237, 5, 96,173, 72, 35, 70,140,192,158, 61,123,116, 22,209,231, 0,120,220,137,200, 67, 59, 21, 18, - 34,147,201, 26, 60,251,214,196,255, 78, 98,225,194,133,182,241,212,134, 6,219, 58,141,208, 25,111,231, 78, 62, 95, 91,238,236, -236,236, 54, 47,251, 27, 23, 23, 71,226,226,226,218,156, 46,123,107,251,183, 7,218,210, 37,176,104,209, 34, 20, 22, 22,182, 91, - 90, 28, 89,222,215, 89,156,121, 77,129, 51, 48, 15, 12, 29,159, 44,193,254,227,125, 16,234,225,133, 95, 79,221, 66, 95, 7,197, -223, 94,249,235,168,203,225,182,199, 90, 2,127,166,251,237,128,207,191, 75, 59,243,173,186, 91,105,191,235,187, 1,222,169, 8, - 67,123, 26, 1,137,137,137,226, 63, 89, 1, 36,127,240,111, 91, 87,168, 97,173, 6,128,187,241,232, 56,104,107,151, 64,207,158, - 61, 73,207,158, 61,219,165,189,113,102, 31, 0, 87,113, 36, 77,139, 35,105,249,238, 58,235,134, 27,246,156,200,168,168, 40,234, -126, 12,110,184,225,134, 27,110,184,241,247, 2,227,126, 4,110,184,225,134, 27,110,184,225, 54, 0,220,112,195, 13, 55,220,112, -195, 13,183, 1,224,134, 27,110,184,225,134, 27,110,184, 13, 0, 55,220,112,195, 13, 55,220,112,227, 47,129, 70,179, 0,230,205, -155,231,242,200,212,230,230,137,187,249, 58, 30,223,220,185,115, 93,226, 27, 54,108,216,109,124,103,207,158,117, 57,125,205,241, -253, 89,242,195,217,103,184,126,253,250,187,146,190,246,206,143,187,153,191,246,166,137, 58,251,252,218,155,207,221,190,184,249, -154,225,235, 10, 64, 1, 64, 8,160,182,163,165,207,105, 3,192,141,191, 62,214,175, 95,239,126, 8,127, 51,248,249,249, 49, 48, - 79,207,228,215,213,213,113,148, 82, 83, 71, 74,159,117,223,249,172,172, 44,218, 30, 11,205,180,215, 74,123,110,220, 57,236,218, -181, 43,110,234,212,169,217,127,242,219,176,174,125, 37,113,214, 0,232,144, 17, 0, 55,254,122,160,148, 54,218,234,216,213, 8, -192,218,181,107,237, 94, 51,113,226,196,184,204,204,204, 70, 43,139, 77,152, 48, 33,254,192,129, 3, 46, 85,244,244,244,244,102, -249,146,146,146, 58, 4, 95, 71, 6, 33,132,244, 8, 13, 69, 81,121, 57,173,173,173,181,238,207,224,212, 18,131,182,198,226,169, - 29,171, 75, 8,193,115,178,189,121, 25,210,201, 67,190,161, 20,202,245,251,242,158, 91, 52, 99, 36, 1, 67,249, 10,149,142, 14, -159,249,188,211, 91,114,102,101,101,197, 89,151,156,181,252,119,105,185,217,166,226,111, 45,247,109,221,104,167,185,239,186,202, -217, 30,124,109,221, 50,216,149,104,201,157, 16,255, 61,123,246,200,167, 78,157,250,103, 55,206,172,251,176,223,209,174,244,119, -222,120,129,241, 18,248, 50,122,177,144,211,215,106,249,245, 90, 37,251,193, 39,171,219,101,135,193,219, 12,128,246, 20, 8, 87, -185,156,229, 35,132, 48, 22, 43, 76, 75, 41,229, 58, 90,250,218, 75, 96,219,195, 0,176, 54,234,182,105, 37,132,232, 41,165,162, -182, 68, 10, 8, 33, 20, 0, 86,173, 90,213,104,199,176, 5, 11, 22,200, 9, 33,160,148, 18,103, 27, 37, 0,224,190,247,111,116, -158,153,149, 41,207,204,204,116,186, 1,108, 79,190, 63, 67, 20,133, 82, 74,227,123, 69,208,248, 94, 17, 0,128,114, 3, 59,167, -147,144,191,217,250,249,111,202,122, 81,153, 3, 27,167, 0,192,201,237,159,230,115, 28,194,238, 25, 19,228,243,193, 75, 99, 15, - 12, 25,226,119,253,185,229, 35,255, 11, 0,183,234, 52,255, 39,224,147,255, 1,228,226,220,185,115, 7, 58,251,108,154, 46, 69, -219,150,229,102,109,197,191, 61,140,128,150,190,227,170, 88,182, 7, 95,114,114, 50,210,210,210, 28,186, 39,103, 34, 42,173,241, -181, 87,100,198, 86,252, 57,142,195,250,245,235,177,121,243,102, 58,103,206, 28,226,100, 30, 11,101, 50, 89,187,172,151,189,120, -241,226,185,169,169,169,174, 86,104, 31,139,231,175,190, 19,117,120,211,154,181,204,163, 97, 17,226, 23,146, 30, 23,134,244, 15, -227,243, 73, 8,163,169,171, 99,197, 8, 53, 48, 93,186, 26,116, 55,175, 25,218,250, 27,124, 71, 26, 55,169, 84, 26, 12, 96, 56, -128, 83, 50,153,172,178,131,121, 58, 62, 0, 18, 0, 76, 7,176,147, 16,146, 69, 41, 85,182, 3,239,119,148,210,135, 93, 21,216, -142, 2,134, 97, 90, 53, 82, 8, 33, 35, 1, 8, 9, 33, 33,148,210,138,150,174,107,205, 64, 33,132,208, 23, 95,124, 17,221,187, -119,191,109,187,208, 85,171, 86,197, 23, 23, 23,203, 9, 33,212, 81, 35, 64, 42,149,210,141,207,123,226,241,177,183,111, 46,195, -125,239,143, 77, 63, 25,240,164,147, 94, 83,123,242,213,213,213,197,189,254,250,235,242,148,148, 20,196,199,155, 87,182, 59,119, -238, 92,220,218,181,107,229,221,187,119, 7,199,113,208,106,181,136,139,139,195,196,137, 19,237,114, 10,235,212,113,125, 95,223, - 38,207,140,238, 26,223,233, 95, 19,178, 1,128, 45,103,227, 46,191,205,202, 77,221,125,160,228, 60,161,208,250,160,194,247,100, -252,211,139, 66,236,122,199,189,186,117,234,212, 93, 40, 41,123,254,185,199,244,161, 18,161, 80, 89,163, 37, 43,190,218,178,249, -141,103, 30,133,191, 68, 66,117, 70, 19,253,247,234,175,244, 0, 72,231,206, 65,252,242,242,106, 38, 42,170,249,157, 53, 71,132, - 28,136,188, 25,230,225, 23,123, 79,240,170, 97, 49, 1,130,141, 27,175,134, 7, 7, 73,170, 62,124,233,248,170,162,235,195, 76, -147, 39,117,206,205,191,162, 42,126,242,241, 94,137,214,114,227, 76, 29,176,221, 32,167, 45, 94,104, 83,241,111, 90, 63, 93,225, -239,136, 17, 0,139, 16, 83,171, 17,144,156,156,108,123,190,145,104,219,110,236,227,170, 81, 97,229, 73, 75, 75,107,115,148,192, - 86,252, 23, 44, 88,128, 83,167, 78,209,159,126,250, 9,115,230,204,113,150,202, 32,149, 74, 5, 50,153,140,109,135, 38,178,124, -241,226,197,211, 83, 83, 83,119,186,240,221, 48, 0, 53, 0,194, 1,156,203,201,201,233, 1,224, 51, 0, 1,182,252, 0, 62,137, -141,141,117,120,207, 5, 45,167,229, 27,170,244, 30,147,167, 78,247, 85,192,232, 43, 16,240, 69, 74,157,152, 47, 20,106, 89,158, -143,167,222, 32, 49,106,249,229, 55, 85, 98,158,168, 86,103,210, 27,164, 82,105,139,245,183,205, 17, 0, 66, 72, 55, 0,159, 3, - 40, 5,240,162, 84, 42,253, 23,165,244,198,221,242, 96,237,136,116, 32,128, 77, 0,110, 2, 56, 6,224, 1, 0, 79, 19, 66, 30, -167,148, 86,183,145,126, 22, 33,100,142,189,254,210,187, 25, 98,191, 67, 24, 13,224, 50,128, 8, 0, 21,196,162,212,142, 26, 52, - 19, 39, 78,140, 3,208, 72,252, 23, 44, 88, 32,183,141, 6, 88, 62,147, 79,156, 56, 49,206, 94,119, 64,122,122,122, 28,128, 70, - 98,205,204, 82,192,214,123,127,124,172, 16, 79,126,170, 70,122,122,122,156,189,240,125,123,243, 1,192,241,227,199,229, 98,177, - 24,185,185,185,141,246, 59, 96, 24, 6,111,190,249, 38,177, 54,118,187,119,239,150, 79,156, 56,209,110, 6,116, 58,126, 81, 78, -197, 2, 12,169, 20,202, 43,126,223,138, 21,132,161, 24,242,166,129, 0, 6, 92, 56,114, 61,238,230,246, 41,114,224, 68,171,141, -112,124,175, 8,218, 93, 40,193, 43,207,206,209,135,122, 9,133, 85, 23,114,136, 39,195,199, 11,227, 34,209,197, 79,130,235,185, - 71,137,214, 64,201,130,185,143, 25,226,123, 69,208,126, 30,222, 40,163, 85,100,216,176, 97,205,242, 5, 5, 9,239, 21, 10, 25, -241,177, 99,101, 47,178, 38,221, 71,161, 93,123, 26,253,130, 4, 68,169,188,234,209, 51,194, 35, 40, 32, 64, 84,201, 81,165,254, -199, 19, 21,234,121,227,254,152, 2,220, 52,236,111, 91, 55,157, 53, 2,172,215,216,142, 35,176,119,157,189,237,183,219,147,207, -214, 8,144,201, 20, 0, 20,144, 74,253,209,156,104, 59,138,150,140, 10, 75, 68,166, 77, 81, 15, 91,241,223,189,123,183,156, 97, - 24, 48, 12,131,113,227,198,225,232,209,163,141,242,203, 81,152, 76,166, 60, 30,143,103,148, 74,165,124,153, 76,214,214,241, 44, -146,234,234,234,239, 3, 3, 3,103,166,166,166,110,119,242,187, 90,152,247,139, 81,229,228,228, 12, 2,176,253,224,193,131,125, - 56,142,179,213, 40,240,120,188,135, 0,100,199,198,198,198,219, 35,204, 47,204, 23, 75,132, 98, 95,129, 64, 20,204,240, 73,103, -202, 19,249,113, 60,158,136, 35, 12, 56,194, 55, 82, 30,175,158,199, 17,149,154,103,170,241, 20, 10, 8,175, 87,183, 58,241,212, - 16, 22,197,119, 46, 2,240, 17,128,131, 22,203,230, 89, 0, 31,173, 95,191,126,166,139,130,237, 15,224, 69, 0, 35, 0, 36, 2, -216, 3,224, 36,128,143, 41,165, 10, 23, 40,143, 88,210,181,150, 82,202, 17, 66, 60, 1, 60, 97, 57, 63,176, 13,134,133,175,229, -173, 39, 0,165, 51, 30,118, 11, 17, 20, 33,128, 55, 0, 44,149,201,100, 6,116, 44,140, 0,144, 3,160, 19, 33,100,171, 37, 79, -190,105,106,208,180,100,160,100,102,102,202,109,195,254, 11, 22, 44,104, 56,182,125,191,106,213,170,120,139, 97,208,106,141,207, -204,204,148,219,134,233,153, 89, 10, 92,217, 99,222,133,145, 73,252,166, 65,180,185,239,253,193,204,202,148,219,219,208,167, 57, - 62,107, 99,198,204,146, 82,103,249, 40,165,113,199,142, 29,195,156, 57,115,240,197, 23, 95,224,204,153, 51,113,209,209,209,217, - 77,175, 17,139,197,242,206,157, 59, 59, 18,171,143,235,124,236, 23, 92,158, 19, 7,175, 47, 46,128,148,105,226,104,103, 15, 11, - 31,177, 92,130, 56,129,174,187, 60,160,115,235, 91,217,198,247,138,160,115,255, 57,203, 16,234, 41, 20, 24,175,158, 18,250, 7, -123, 19,121,153, 18, 51,163,186,161, 95,152, 31,132,181,151, 33, 87,105,209, 77, 32,130, 31,225, 9, 22, 63, 61,135,214, 11, 69, -249,241,189, 34, 40,124,252,154,229, 84,212,170, 2, 70,142,244, 90,165,100, 71, 45,242,246,175, 20,233, 24, 79, 78,226,101,208, - 7, 4, 5, 50, 30,126, 98,190,162,166, 76,164,172, 99, 33,168,211, 19,219, 50,211,154, 65,107,233,247,151,219, 19,206,228,228, -228,120,123,227, 1,154,243,252,155, 26, 2,206, 24, 1,214,207, 90, 19, 99,219,243,246,132,177, 41, 31,221,230,127,123,123,147, -162,128,163,124,173,133,251,219, 34,218, 77,141, 10, 0, 8, 8,200,106, 23,241,159, 55,111,158,185,251,141,227,240,234,171,175, -226,163,143, 62,106, 16,255,181,107,215, 58,205,205, 48, 12, 12, 6,195, 89,161, 80,200,182, 67, 36,160, 6, 0,170,171,171,183, - 7, 6, 6,198,167,166,166,202,157,248, 46, 31, 0,158,124,242, 73, 81, 78, 78, 78,102, 86, 86, 86,167, 37, 75,150,176,111,189, -245, 86, 35, 93, 13, 12, 12,196,161, 67,135,226, 0,164,197,198,198, 38,183, 70,200, 35, 2, 31, 3, 75,187,112,156, 49, 66,200, -227,245,160,132,132, 16, 62,159,240,121,188, 58, 66,136, 22,132,167,228, 40,252,169,129,243, 80,154,140,232,229,195,106,153,145, - 42,174,221, 12,128, 38,125,195, 97, 0,186, 81, 74,173,130,255, 62, 33,228,132, 84, 42, 13,163,148,150, 58,227,193, 18, 66, 30, -179,136,245, 7, 0, 22, 1,120,212, 18, 66, 73, 6, 80, 76, 8,121,150, 82,250,141, 19, 34,253, 31, 0, 87, 41,165,107, 8, 33, - 34, 75,133,103, 41,165,159, 17, 66, 38, 17, 66,254, 67, 41,253,127, 46, 22,138,241, 0, 42, 1,220, 11,224,127,206,124,177,185, - 8,128, 84, 42,125, 10,192,219, 0,202,231,206,157,187,174,131, 69, 0, 6, 90,210, 54, 1,192,100, 0,215,237, 25, 52, 45,193, - 86,240,109, 69,191,233,184, 0,135, 43,186,141,248, 3,192,149, 61,143, 53, 50, 2, 92,225,179,109,204,100, 50, 25,177, 53, 2, - 28,193,225,195,135, 97, 48, 24, 16, 19, 19, 19,255,211, 79, 63,201,139,138,138,228,209,209,230, 45,117, 57,142, 67,106,106, 42, -173,175,175,135, 64, 32,192,140, 25, 51,236,222,183, 46,247, 36, 24, 3,139,218,152,240,120,193, 79, 55,229, 87, 55, 28, 70,175, - 55, 38,155, 69,139,163,200, 75, 21,210,154,122,111,104, 5, 94,152, 48,239,138,253,231,200,240,234, 43, 47,228,250,234,244, 38, -198, 87, 34,162, 73, 81,221,225, 35, 17,144,146,234,122,120, 50,124,164, 12,235, 78,143,255, 90,129,159,255,183, 15, 61, 60,189, -232,121,149,242, 58,128,190, 45,209,229,158,237,242,220,232, 97, 85,135,189,248, 17,172,144,189,213,107,252,152, 20, 47,157,193, -115, 10,207,235, 36,163,172,173,241, 40,186,116, 50,194,104,184, 84, 89, 88,160,246,177,212, 25,187, 66,229,168,119,106, 29, 31, -208, 82,255,115, 75,222,180, 61,175, 82, 42,149, 82, 87, 67,166, 29, 9, 77, 61,127,179,120, 3,105,105,237, 55, 72,176, 61, 60, -127, 74, 41, 88,246,119,141, 30, 59,118, 44,142, 30, 61,234,146,248, 91, 96, 20, 8, 4, 38,142,227,142, 49, 12, 99,108,163, 17, - 16, 98,125, 83, 93, 93, 45, 15, 12, 12,148,166,166,166, 58,186,115, 86, 81, 74, 74,138,207,225,195,135, 83,179,178,178, 58,125, -253,245,215,220, 19, 79, 60,193,223,178,101, 11,222,121,231, 29,228,231,231,163, 71,143, 30, 40, 47, 47,199,187,239,190,107,122, -251,237,183,147, 0, 60, 27, 27, 27,251, 89,139,140, 28,235,107, 2,211,131,112, 24,104, 4, 23,233, 33, 16, 9,133,124,166, 76, - 44,224, 41,121, 18, 97,149, 72,196,171,215,155, 56, 15,190,145, 31, 96, 96,245,166,107,103,206, 42, 30, 11,254, 72,115, 28,174, -233,135,189, 8,192, 36, 0, 57, 77, 6,142,229, 0,152,180,126,253,250,175,156, 16,235, 71, 0,188, 4, 32,188, 73,104, 94, 1, -224, 23, 66,200, 39, 0, 14, 16, 66, 76,148,210, 45, 14,240,121, 0, 19, 92,166, 19, 0, 0, 32, 0, 73, 68, 65, 84,152,107,245, -242, 41,165,250, 38,151, 60, 14,224, 87, 66,200, 74, 74,169,198,149,240, 63,128,175, 44,255,157, 50, 0,154, 10,166, 84, 42,253, - 7,128,231, 44,207,114, 21, 33, 68, 47,147,201, 54,116,132, 6,132, 16,210,219, 18,194,250, 17, 64, 6, 0,107, 62,193,209, 8, -192,223, 13,165,165,165,242, 81,163, 70,129, 16,146, 61,106,212, 40,252,240,195, 15,120,232,161,135,226, 58,117,234, 36,103, 24, - 6,139, 23, 47, 38,150,198, 36,110,235,214,173,114,189, 94,143, 17, 35, 70,180,216,208,141,185,118, 83, 94, 62,170, 63, 64, 72, -246,175,161,166,248,129,231, 2,228, 58, 14,241,230, 46, 0, 96,200, 98, 3, 1,170,161,174,174,139, 59,180,181,183, 92,237,125, - 34,254,225, 39,124,154,245,138, 75, 12,236,202,245,235,183,188, 26, 28, 36, 41,170, 83, 27,124,195,253, 61, 5,201, 67,123,122, - 12, 11, 23, 17,157,198, 4,141,150,195, 85,162, 53,101, 20,149,106, 10,202,235, 77,157,132,226,178,114,131,110,226, 13,189,241, - 3,111,224,149,230, 56,125,252,195,186,106,235,175,116, 25,144,112, 31,115,241,120,217,248,210,223,126,184,209,123,248,220, 16, - 94,255,168,146,179, 71,191,175, 35, 60,159, 17, 28,199,213,220,186,165,181,107, 69, 53, 21,108,123,199, 86,111, 54, 45, 45,173, - 69,193,182, 13,175, 55,141, 4, 56,114,253,159, 21, 9, 9, 9,196,214,235,183,133,109, 8,191, 45,104, 15,158,250,250,122, 57, - 0,240,249,124,188,252,242,203, 56,117,234, 20,126,250,233,167,182,210,234, 1,152,244,122, 61, 91, 90, 90,154, 25, 22, 22,102, -180, 23, 89,108, 5, 42,219,131,234,234,106, 89, 96, 96,224,131,169,169,169,142,180,251,190, 58,157,174,207,194,133, 11,167,206, -155, 55,143, 14, 30, 60,152, 0,104, 16,127, 0, 24, 61,122, 52,118,236,216,129,177, 99,199, 50,143, 60,242, 8,205,206,206, 94, -195,227,241,180, 30, 30, 30,208,104,110,151, 38,142,163,186,108,249,193,244,222,189, 35,139, 35,122,132, 95,225,121, 75,202,120, - 68, 88,199,136, 4,117,140,216,163,194,192,231,105, 64,141, 2, 78,108, 12, 81,149, 86, 7,157, 56,116,238,205, 32,255,208,183, - 92,125,144,173, 70, 0,164, 82,233, 68, 0,155,155,120,181,135, 0,204,153, 59,119,238, 87,142,120,176,132, 16,158, 37,252, 61, -173,165,126,121, 74,105, 53, 33, 36, 5, 64, 6, 33,228,123, 7,230, 41, 63, 2,224, 0,165,180,174, 5,190, 58, 66,200, 1,203, -117, 95, 56, 41,138,247, 1, 8, 4, 48, 31,192, 86, 66,200,125,148,210, 67,174, 68, 0, 8, 33, 73, 0,222, 7,208,131, 82,170, - 38,132,140, 6,112, 93, 42,149,170, 40,165,233,142, 70, 0,164,102, 83,223,145, 70,139,200,172,110,128, 99, 24, 3,224, 4,165, -148, 18,179,219,116, 29,128,154, 16,210,205, 58,206,195,153, 8, 64, 83,143,191, 45,222,127, 67, 88, 62,241,155,134, 40, 64,100, - 27,188,255,223,195,252,191,135,111,165, 82,231,188,127,163,209, 72, 79,157, 58, 5,111,111,111,228,229,229, 81,147,201, 4,165, - 82,137, 75,151, 46,201, 3, 3, 3,209, 36,236,151, 61, 96,192,128,248,109,219,182,201, 71,140, 24,209,124,184,207,104,164,221, - 78, 93,128,208, 59, 12,130,188,106, 26,106,242,134, 74,201,192,116,169, 30, 8,108,188, 35,181,103, 32,155,221,125,248,233,248, -125,219,103,201,129,189,205, 54,118, 87,110,220,120, 45,178, 91, 55,160, 74,251, 42, 0,228,107,149,216, 45, 42,173, 28,112,239, -248,224, 1,134, 60,252,114, 93,129,221,231,110,241, 11, 42,235,125, 0,160,220,160,243,191,161, 55, 38, 23,148,150,238,136, 10, - 14,110,214, 0,184,119, 74, 10,227, 33,156, 56,152, 85,255, 82,220,189,127, 66,159,186, 27,219, 13, 87,127,201,172, 53,114, 94, -183, 42,138,127,174, 80,214,120,142, 0,195,144, 26,149,206, 87, 58, 43,186,155,236,251, 51, 55, 90, 42, 51, 50,153,140,216, 70, - 0,108,189,203,166,225,118,171, 72, 39, 39, 39, 35, 33, 33,129, 52,183,208, 73, 91, 70,227,187,186,112, 74, 71,131,181,186, 75, -165,254,183, 69, 4, 92,141, 42,164,165,165,181,139,248,111,222,188,153, 30, 57,114, 4,116,155, 63, 72,138, 2, 31,126,248, 33, - 40,165, 96, 24, 6,235,214,173,115, 57,178,160, 80, 40,244, 1, 1, 1,241, 71,142, 28,217, 59,126,252,248,201,205,149, 31, 39, -224,103,169,175,115,171,171,171,215, 7, 6, 6, 62, 6,160,102,241,226,197,255, 72, 77, 77,181,231,168,213,237,218,181,171,116, -223,190,125, 95,197,199,199, 63,213,175, 95, 63, 36, 36, 36,208,172,172,172,134,116,100,100,100, 64, 36, 18,225,250,245,235,216, -187,119, 47,233,210,165, 11, 27, 27, 27,251,211,165, 75,151,154, 37,140,140,232, 83,166,213,234,230, 30, 57,114,100,125, 96, 80, -160,210,215,199,167, 24, 66,161,158,213, 51,245, 44, 79, 95,171,227, 43,171, 60,245,158,226,155, 21,149,190,135,246,237, 93, 63, - 96,224,160,247, 13, 58, 77,125,187, 24, 0, 82,169,148, 72,165, 82,107,226, 59, 89, 94,135, 45,211,236, 26,162,160, 0, 22, 16, - 66,186,192, 60,194, 17, 0,154,181,208, 45,162,242, 2,204, 3,244,174, 53,225,105,138,107,150,235, 94, 32,132,124,212, 10, 31, - 1, 48, 3,192,114, 59,124, 95, 3, 88, 68, 8,249,202, 78,250,108, 11, 77, 56,204,227, 29, 98, 96,238,251,127, 19,192,105, 66, - 72, 47, 0, 69,182, 54,134, 3,124, 15, 3,120,218, 34,178, 90, 75, 90,181,150,227,117,132, 16, 33,128,239, 90,227,179,228,197, - 99, 0,230, 57,106, 0, 72,165,210,181, 0,190,105,137,207,194,185, 18,128, 55, 0, 95, 0,187, 44,105, 19,195, 60, 79,252, 23, - 0,163, 8, 33,243, 1,252, 4, 96,119, 75,233, 3,204,243,232, 91,232,235, 71,211,177, 1, 19, 38, 76,176,107, 12, 76,152, 48, - 33,158,153,245,123,191,189,213, 8,176,190,183, 13,231,187,204, 55,235,246, 41,129,142,240,157, 59,119, 14,221,187,119,199,203, - 47,191,220, 80,102, 54,109,218, 68,115,115,115, 49,101,202,148,219,174,247,240,240,144,139,197,226, 22,249,194,207,157, 67,109, -247,206, 56,254,242, 83, 13,124,151, 95,219, 17, 23,145, 91, 39,103,166,136,111, 75, 75,113,190, 1, 34,113,235,179,159,174,150, -148, 44, 68,215,174, 63, 3, 24, 77, 65,121,184, 86,249,178,134,101,193,234,204, 65,178,139,149,149,184,166, 51,108,226, 19,162, - 2, 33,198,171, 37, 37,233, 0,208,210, 32,192, 46,225,253, 22, 2, 88,145,127,244,197, 34,113,232, 12, 69,105,185,184,107,121, -201, 73, 49, 4, 1,189,139,174,155,194,170,203,111, 64, 40, 20,132, 12, 12,245,124,164, 86,101,252, 22,192, 13,123,158, 43,128, -184,166,211,255, 90,240, 64,227, 93, 89, 19,160,185,254,255,191, 3,218, 58, 85,207,250,253,180,180, 52,218, 86,190, 45, 91, 54, -211,236,236,108,144,116,179, 97,124,224, 45,111, 76, 92,162,194,248,241,227,225,204,180,191,230, 16, 16, 16, 16, 15, 0,247,220, -115,143,166, 29,186, 41, 20,129,129,129,115, 0, 88,157, 83,125,106,106,234,110, 7,191,203, 2,168,200,200,200,144, 63,244,208, - 67,195, 83, 83, 83,135,152, 76, 38, 34,145, 72, 48, 97,194, 4,236,223,191, 31, 28,199, 33, 49, 49,145,190,248,226,139, 36, 42, - 42, 74, 63, 99,198,140, 30, 53, 53, 53,183,116, 58, 93, 75,138,204,254,122,233,202,166, 65,131,135,248,158, 60,113,226,253,179, -124,254,160,158, 61,122,126,233, 19, 24, 92, 34, 8, 22,211,195,123, 15,249,215, 40,170,199,133, 5, 4,191,221,167, 79,159,195, - 94,161,158,107,251,119,141, 49,228,229,229,181, 75, 4,128, 7,243,116,191, 88, 0,239, 1,120,222, 34, 60,158,182,245, 9,230, - 65, 98, 87, 1,252,219,210, 37,112,170, 5,126, 6,230, 65,102, 7, 0,120, 56,144,158, 99, 0, 38,162,229,133, 21, 24, 0,193, - 0,122, 0, 56,109,135,243,180,229,186, 16,180,220, 55,201,192,188,140,163,191,165,219,224, 33,139,112,231, 91,184,243, 45,199, - 91, 0,252, 0,243,140, 3, 5, 0,131, 29,190, 89,150,200, 67, 63,139,145,100,155,206, 50, 0, 82, 0,191, 89,174,253,222, 14, -223, 75, 48,207,110,112,164, 43,195, 3,192, 62, 0,155,237,228,199, 76, 0,255,181,252, 63,107,147, 62,129, 37, 47,211, 0,124, - 10, 96,137,229,243,178,150,126,240,192,129, 3,217,132, 16, 20, 23, 23,203,173, 51, 1,154,122,253,197,197,197,114,235,181,246, -110, 32, 41, 41, 41, 59, 51, 51, 19,155,126, 50, 52,140,220,111,234,165,111,250,201,208,112,237,221,228,203,205,205,197,184,113, -141,135,186,135,135,135,199,111,219,182, 77,222,179,103,207,120,142,227,228, 75,151, 46,165,214,105,128,132, 16, 12, 31, 62,188, - 69,163,162,111,110, 46,190, 11, 12,137,247,177, 57,215,127,254, 68,168,223,191, 1,220, 31, 2,202, 1,121, 75, 5,180,158,243, - 66,141,214, 7, 10, 50, 12, 67,199,237,138,111,173,216, 91,102,112,108, 7,176,189,119,143,176,190, 0, 94,214,155, 56,164,231, - 21, 97, 92,168,185,187,147, 80,170, 82,177,236,123,183,110,221,186,229, 64,153,122, 31,128,103,254,111, 53,143,214,158,222, 22, - 84, 81, 86,131,138, 91, 42,240,249,213,158,245, 10,138, 90,165,137,134, 4, 11,253,248, 28,166,107,245,166,239,150,188, 28,235, - 23,210,255,137, 90, 59, 66,147,109, 79, 92,218,220,135,157,176,205,252, 63, 43,197, 73, 15,248,206,206, 2, 32, 41, 10,180,133, -175, 37,143, 61, 38, 38,166,195, 24, 34, 13,131, 29,173,226,159,199, 98,131,220, 92,199,218, 42,254,214,178,241,236,179,207, 6, -243,249,252,138, 99,199,142,125,121,207, 61,247,180,101,138, 98,247,212,212,212, 53,150, 40,192, 44,203,140,128, 89,169,169,169, -223, 59, 18, 84, 4, 80, 15,160, 42, 60, 60,124,232,216,177, 99, 75,207,229,229,117,214,106,181, 68, 46, 63, 4,145, 88, 4,134, - 48, 56,116,232, 16, 25, 48, 96,128, 38, 57, 57,121, 84,101,101,165,221, 58, 55,123,214, 76,246,199,189, 63,126, 58,116,232,176, -158, 6, 86, 63,249,106,254,149,167,185,162,130,167, 0, 64, 12,134, 14,238,221,247,100, 72, 72,112, 54,143, 47,124,237,191,111, - 45,175,255,118,163,235, 61,202,205, 25, 0, 47, 91,172,161, 41, 0, 46, 1,240,106,230,123,123, 44, 30,123, 18,128,145, 22,241, -108, 54,202, 9, 32, 18,192, 86, 7, 13,128,106,203,245,188, 86,248,226, 0, 92,113,144,239,138,229,250, 29,173,240,205, 5,240, - 36,128, 11, 48,207, 80,184,214,132, 91,110,241,254,159,179,120,195, 27,129, 22, 71, 92,240, 44, 30,251,227, 0,162, 44, 81,132, -230,210,169,180,124,190,206, 98, 4,108,108,133,239,107,139,209,229,200,253, 82,203,245,173, 61,191, 15, 44,145,141, 3, 22,163, - 6, 77,184,247, 3, 24, 96,201,139,124,139, 33,213,173,213, 31, 53,247, 32, 80, 0,242,230, 22, 2,178, 94,227, 76, 5,127, 82, - 42,165, 79,126,170,110,102,225, 30,133,211, 2,209, 94,124, 47,188,240,194,109,215,140, 31, 63, 62,123,252,248,241, 4, 0,238, -187,239, 62,167, 26,161, 61, 47,188, 64,124,154,182, 40, 61,188,178, 37,171,251, 19, 0, 24, 40, 19, 16,115, 80,198, 58, 50,251, -186,131,197,192,146, 47, 38, 90, 4, 62,192,171, 71,131,248, 91, 92,228, 91, 98,177,216,209,217, 40, 4,192, 59, 71,179,206,122, -132,118,237,241, 32, 7,143,200,146,226,114,158, 81, 87, 75, 59,133,120, 17, 47, 79, 1, 97,141, 28, 20,181, 6,150, 72,136,164, - 78,197,246, 14,105,217, 33,104, 86, 44,154,190,255, 35,151,239,189,211,179, 0,218,202,215,146,199,222,179,103,207, 14, 35,254, -220,247,254, 56,144,103, 30,147,183, 81,110,192,119,199, 12,160,148,182, 75,190, 90, 57, 76, 38, 83, 53, 0, 68, 71, 71,183,105, - 65, 32,171,248, 91, 80,101,249,239,104,221, 16, 90, 28,179, 51, 0, 48,112,224,192, 48,149, 82,181,104, 68,204,240,199, 84, 74, -165, 47,107, 98,141,161,161,161,183,194,194,194,174, 40,149,202, 37,149,149,149,249,142,166,107,202,228, 41, 44,128,231,143, 30, - 57, 49, 54,118,236,216, 41, 18,137, 36,136,128,154, 8, 33,224, 56, 90,173, 85, 43,214, 92,206, 43, 46,251,118,227,134, 54,173, - 8,216,212, 0, 48, 1,248, 71, 43, 2, 98,139,147,150,151,201,242,106, 14, 38,152, 71,212,243, 28, 76,143, 28, 64,150, 29,190, - 12,152, 7,173, 57,130, 71, 29, 72,223,122, 0, 95,218,225,249, 21,230, 41,144,112,128,239, 27, 75,196,192, 30,138, 44,158,189, - 35,233,227, 57,145,167,235,237,240,221,239, 0,159, 53,218,176,209,242,108,236,206,181,165,148,146,137, 19, 39,198, 89, 5,223, - 54, 4,239,202, 82,192, 50,153,140,164,167,167,199, 49,179,218,103,233,222,246,230,251, 51,160,160,228,166, 62,178, 91,183,141, -243,222, 95,247,164,245,156, 65,192,108,214,105,184,125,229,197,197, 42,135, 10,211,250,245,180,234,244, 6,178,252,251, 95, 22, -238, 94,125,223,206,227, 39,202,158, 9,246,229,166, 50, 1, 62,126,148, 2,132, 80,189,158,229,202, 57,160,202,160,231,252, 74, -203,180,134, 72, 39,210,152,156,156, 28,111,219, 29,144,156,156, 28,223, 81,158, 95, 71, 92, 9,240,207,130, 73, 75, 84,119,244, - 30,101, 50, 25, 39,149, 74, 59,139,197,226,178,232,232,232,251,219,131, 51, 53, 53,245, 96, 96, 96,224,147,169,169,169, 27,157, - 48, 0, 88, 75,228, 20, 0, 48,122,204,232,229, 0,150, 55,189,176,233, 24, 33, 71, 49,110,252,200,159, 96,238,138,109,130, 48, -244,238, 51,168,205,247,220,156, 1,160,115,129,135,182, 18, 34,209,187,249,254,178,124,141, 96, 17,250,118,171,232, 73, 73, 73, -217,246,230,229,255,145,124,127, 6,212,104, 52, 79, 1, 30, 70, 0,193, 28,104,169, 78,103,216, 82, 94, 94,121,158, 82,234,240, -180,169,160,152,127,208,140, 15, 39,147, 91,158, 15,231,118, 29,139,220,172,175, 62,120, 57, 32, 64,180,136,207, 35,180,172, 90, -119,185,204,192,110,146, 8, 24,177,132,207,227, 25, 89, 78,236, 76,250,172,125,252,214,129,103,174,238, 3,112,219,212, 63,155, -208,191, 43,139,205, 52,245,204, 29, 57,127,183,249,238,182,225,227, 40,152, 89, 10, 16, 66, 48,117,218,239, 3,162,247,236, 61, -211,208,134, 36, 78,142,110,175, 41,138,229,237,217,222, 88,140,128,141, 78, 92,238,111, 49, 0,212,127,214,246,129,223,228,129, - 82, 71, 27,251,166,104,110, 20,187,155,239,175,205,231, 70,199, 71,117,117, 53,133,185,155,171, 77,184,229, 57,157, 2,192,209, -205, 31,147,132,167, 94,249,240,241,185,121,159, 62, 63,251,216, 0,131,154, 68, 4, 8,248, 65, 32, 68,227, 37,225, 87, 14,234, -231,147,239, 44,119, 66, 66, 2, 73, 75, 75,115,121,189,249, 59, 37,158,127,150, 8, 64,199, 51, 30,204,177,161,191, 65,245, 10, -179, 56,204,222,248,147,238, 6, 72,162,162,162,254, 30, 67,100,221,112,195, 13,240,121,128,135,136,128,227,204,109,116,189,214, - 93,253,221,112,227,111,219, 30,184, 31,129, 27,110,252,125,192,154, 0,165,198, 42,250,110,241,119,195,141,191, 51, 24,247, 35, -112,195, 13, 55,220,112,195, 13,183, 1,224,134, 27,110,184,225,134, 27,110,184, 13, 0, 55,220,112,195, 13, 55,220,112,227,175, -136, 70, 99, 0,230,205,155,231,242,200,205,230,214,214,110,142,239,127,223,127, 30, 55,104, 72,111,121,231,174, 97,241, 42,173, - 90,126, 88,158, 27,159, 52,235,217,108, 87,249, 86,127,181, 61, 46,106,200, 40,249,173,210, 82,120, 74, 60,113,163,164, 32,254, - 95, 79, 77,115,153,175,189,239,247,194,225,121,113,163, 71,245,148, 75, 60,121,224,243, 24, 16, 49, 65,153,242, 69,226, 42,223, -153, 91, 67,226, 70,140, 26, 33,247,245,226, 1,124,160,230,220,122,226,104,250, 34, 39, 69,186,124,191, 87,246, 95,185,141,111, -228,200,145, 46,243,157, 56,113,226,118,190, 72,215,211,119,226,202,237,233, 27,213,167,143,203,124,199,243,243,255,116,124,147, - 90,201,223,229,203,211,232,162, 69,201, 45,126,190,191,153,252,141,124, 96,146,235,229,101,223,254,219,203,243, 36,215,203,203, -242,204,106,234,195, 21, 52, 58, 23, 20,249,176,203,124, 85, 87,190,187, 45,125,103,223,184,238,114, 67, 58,108,105,143,219,206, -125, 24, 84,234, 50,223,203, 85, 97,248, 35,218,171,191, 59,159, 84, 42,229, 55,183,179,160, 35,124,251,247,239, 7, 0, 40, 20, -138, 8,157, 78,167,120,242,201, 39,107,255,200,251,117,218, 0,104, 9,186,173,210, 72, 0, 61, 97, 94, 39,160, 64, 60, 91,118, -205,209, 31,216,254,205,242, 56, 2, 14,193,126, 1,200, 61,124, 70,254,245,215, 31, 35, 54, 33, 22,172, 90, 35, 31,208,111, 60, - 56, 14,242, 95, 35,190,142, 31, 54,108, 8,174, 94,189,142,186, 90, 53, 6,143,153,147,221, 18,223,250,111,229,113, 20, 4, 61, -122,247,148, 75, 95, 89,130,234, 79,182,227,155,207, 63, 3, 32,198,158,243, 37, 96, 24,200, 63,126,231, 45,228,231, 95, 70,120, -120, 15,136, 36,124,220, 44,201,111,113,113,145,194, 29,159, 81,161, 80, 8,137, 68,130,130,130, 2,116, 9,241, 65, 16,223, 11, - 93,186,251,193, 95,226, 11, 79, 98, 2,195, 48,160,156, 9, 26, 17, 31,117,183,234, 80, 49,220,254, 92,242,186,130, 53,212, 91, - 82,135, 49, 35,122,193,203,147, 15,161,132, 1,159, 7, 48, 66, 62,250,134,125, 78,141,148,135,194,155, 79, 57,156,225,171,247, -234,226,194,194,194, 16,123, 79, 87,185, 86,167, 7, 35,146, 0, 70, 32,175, 62, 58, 78,171, 81, 99, 84,200,229,236, 63,202,138, - 92,191,126, 61,157, 59,119,238,223,106,126,125, 71,133, 61,161,111,227,245,158, 0, 70,116,146,120,252,183,180,180,180,159, 64, - 44, 2,231,225,177, 12,230,149, 49,235, 59,202, 51, 40,248,117,111,220,181,139,135,111,219,107, 32, 33,121,217, 95,165,140,146, -111, 54,109,250, 77, 36, 20, 74, 56,142,243,245,244,242,242,122,112,234, 84, 15,152, 87,176,235,168, 35, 59,173,209,102,174,173, - 68, 82,169,212,199,215,215,119, 65,223,190,125,103,136, 68,162,174, 37, 37, 37, 37,165,165,165, 39, 12, 6,195, 82,153, 76, 86, -224, 2,159,159,191,191,255,146,251,238,187,111,242,179,207, 62, 27,254,197, 23, 95,220,186,112,225,194, 49,157, 78,247,174, 76, - 38,187,224, 8,199,254,253,251,241,227,200, 29, 24,179,247,222, 21,225,225,225,175,121,122,122, 98,251,246,237,167,103,206,156, - 57,252, 79, 19, 1,104, 65,252,121,158, 34,254,136,199,198,246, 90,201, 81,170, 59,122,249,214, 39,151,182, 74, 15,136,103,203, - 46,218,251,110,242,212,222,116,234,125,203, 97,172,175, 5,223,196,224,151,139,151,241,196, 19, 47,254, 94, 34, 24,224,231,220, -141, 8,234, 30, 38,231,234,149, 48,112, 4,135, 14,229,198,151,104, 91,202,168,165, 20, 66, 95, 16, 15, 31,156,185, 88,140,243, - 23,255,129,175,190,219,223,240, 57,199, 1, 15,140, 25, 3,212,151, 3,240, 70,193,133, 75, 16, 4,249, 33,118,244, 32,121,173, -166, 21,155,133, 48, 0, 97, 16, 53, 36, 26,157, 60,133,232, 18, 36,134, 79, 96, 0,252, 69,222,240, 23,243, 32,224,241, 96, 52, -153, 80,203,114, 56, 89,117,218,238, 67, 45, 63,191,132, 6,248, 2, 62, 30, 30, 8, 14, 10,132,143,143, 7, 40, 99, 2,203,213, -195, 4, 19,188,188, 60, 16,212,169, 43,122, 70,254, 68,179, 14,143,109,181, 81, 90,151,105,160,190,222,158,232, 25, 17,130,224, -160, 64,168,213,106, 8, 69, 98, 8,116,230,197,249, 34,194,123,200,107, 20,181,248, 62,183, 40,190,184,228, 38, 20,229,215,177, -244,217,232, 86,141,129,180,229,105, 14, 55, 18, 9, 79, 38,196,251,135,250,103,183, 38,254,119,195, 8,120,227,253,247, 41, 0, - 44,125,237,181,118,249,141,197, 43, 86, 80, 0, 72, 93,184,208,101,190, 31,115,114,158, 48, 24, 12, 27, 1, 96, 70,124, 60,227, - 74,227, 43,219,182,205,188, 70,188,205,180,105, 74, 41, 8, 33, 13,255,173,231,172,215,205, 77,110, 89,176, 23, 45, 74, 38,142, -138,186,147,226, 63,192,211,200,110,247,246,243,237, 7, 0, 66,137, 24, 6,173, 14,156, 90,179,226,216,145,195,239,220, 59,115, -102,127, 0,197,246, 72,244, 60, 33,133,121,241, 20,214, 34, 10,156,165, 29,106,182, 45, 26,122,239,100,252,118, 40,195,169, 60, -186,118,241,176,188,247,160,184,248,240,254, 15, 56,111, 20, 39,215, 56,117,121, 74, 74, 10,182, 37,103,181,122, 77,124, 86,227, -173, 72, 6,248,153,111,181, 66,199, 65,203,154,243, 85,109,249, 47, 27,229,135, 62,222,130, 86,249, 86,174, 92,153,253,198, 75, -175,134, 76,155, 49,221, 75,167,211,226,227, 15, 63, 96, 86,175, 94,173,155, 63,127,126, 24,128,155,237, 93,247,246,237,219,151, -176,115,231,206, 76,192,185, 53, 7,114,115,115,105, 81, 81, 17,170,171,171,161, 82,169,224,237,237,141,192,192, 64,132,135,135, - 99,204,152, 49, 46,213, 59,169, 84, 58, 62, 58, 58,122,211, 43,175,188,114,181,111,223,190, 27,135, 13, 27,118,233,214,173, 91, - 93,115,115,115,163,159,122,234,169,221, 82,169,116,133, 76, 38,251,202, 9,190,248, 25, 51,102,164, 45, 95,190, 60,208,104, 52, - 66, 34,145,192,211,211,179,179, 90,173,158, 57,109,218,180, 7,165, 82,233,124,153, 76,246,121,107, 28,207, 43,164,192, 72, 96, -202,137, 25,240,236,238,217,101,209,162, 69, 56,117,234, 20, 85,169, 84,126, 54,191, 3, 0,188,153, 51,103,154, 38, 78,156,120, - 87,196,253,220,185,115,141,142,155,219,208,141,223,130,232,119, 3,208, 11,230, 37, 99, 77,106, 61,123, 35,247, 74,197, 71, 99, - 34, 67, 94,188,111, 64,231,119, 58,249, 74,186,200,183, 74,183, 2,184, 44,158, 45,107,113,147, 26,125,125, 13, 58,245,190, 31, - 75, 94,155,129,141,178,223,235,226,225, 99,235,160,214,232,145,152,240, 34,238,137,125, 18, 15,167,220, 7,137, 68, 4,131,137, -133, 74, 99,144,247, 25,221,187,133,194,113, 29, 48, 0, 51,230,172,197,191, 94,121,166,225,236, 3,247,196, 65, 44, 22,225,135, - 67,251,177, 39, 39, 23,155, 54,124, 6,157, 86, 15, 33,143, 15, 47, 15, 33,212,213, 37,241,181, 37,104,118,247, 49, 74, 41, 64, - 57,243,139,225, 64, 41,133,222, 32, 50, 55, 79, 34,128, 26, 76, 48,241, 0, 19, 76, 48, 25, 56,176,166,214, 13,216,130, 19,169, -180,107, 48,133,143,183, 39,194,186, 70,160,223,224,222,240,246,146,160,174,190, 18,229,149,229, 80,212,221,130, 81, 71,224,225, -225,129,224,224, 88,204,156,126,129,110,223,217,183,249, 48,254,230, 27,212,228,237, 13, 45, 31, 16,138,133,208,106,132, 48,104, -132,208,137, 69,224, 19, 22, 20, 60,232,180,245,208,106, 84,232,218,181,139, 92,200,227,163, 6, 74,124,244,209, 17,136, 68,173, - 23,142,247, 55,189,111,183, 0,189,246,248,107,173,126,174, 80, 40,104,147,227,152,128,128,128,124, 66,136,142, 82,202,247,247, -247,247, 40, 40, 40, 8, 76, 75, 75,203,158, 59,119,110, 23, 87, 11,178, 48, 52,116,118,195,111, 0,113,254, 64,187, 69, 59,214, -167,165,209,231,158,123, 46,222, 88, 81,225, 20,231,143, 57, 57,210,145, 35, 71, 46, 29, 27, 21, 5,163, 72,132, 85,171, 86,113, - 51,239,187,111, 2,165, 52,203, 41, 87,142, 16,172,124,231,157,134,227, 5,111,191,141, 85,239,190,219,234,177, 61, 52, 53, 2, -150, 47, 79,163, 49, 49, 49,200,202, 42,164, 9, 9, 61, 7, 2, 40, 92,190, 60, 77,235,164,248,231, 14, 30, 56,208,199, 90,103, - 60,197, 18,148, 85, 86, 64,169,168, 69,244,200, 81, 30, 63,126,181, 33,107,202, 83,255, 24, 8,243,230, 5,173,129,125, 97,233, -106,254,163, 51, 31,228, 71,134,135,115, 86,207,240,237, 85,159, 54,186,232,221, 5,207,155, 13,191,151,230,199, 63, 62,117,130, -211,249,234,146,248, 55, 88,200, 1, 78, 92,156,224, 20,181, 39,159,224,252,187, 79,131,248, 4,193, 84,120, 30,250,194, 95,145, - 95,163,198,240,189, 21, 14,125,127,157, 76,118,244, 21,233,115, 61, 30,255,231, 83,126,105,155,191,227,194,195,195,153, 37,203, - 87,192,251,157, 37,248,225,135, 31, 74, 31,122,232, 33,151, 12,209, 22,132,127,194,206,157, 59, 15, 88,143,167, 79,159,238,144, -114,169, 84,170,184, 3, 7, 14,200,141, 70, 35,122,245,234,133,113,227,198,193,215,215, 23,181,181,181,184,121,243, 38,174, 93, -187,134,155, 55,111,210,137, 19, 39,198,123,123,123, 59,156, 79, 82,169,116,250,125,247,221,247,241,202,149, 43,183, 14, 27, 54, -236, 99,171,177,211,165, 75, 23,204,156, 57,147, 36, 37, 37,121, 1,200,149, 74,165,185, 45,237, 94,218,148,111,254,252,249,233, -207, 61,247, 28,115,250,244,105, 16, 66, 16, 24, 24,216,240,218,187,119,175,112,244,232,209,159, 73,165,210,227, 45,241, 61,175, -144, 98,202,137, 25, 0, 64,182,167,236,160,247,126, 54,190,123,126,126, 62, 10, 11, 11, 73, 93, 93, 93, 47,169, 84,202,159, 54, -109,154, 9, 0,157, 54,109,154,137,101, 89,220, 13, 52, 21,127,235,185,166,247,193,111, 70,252, 3,135, 71, 4, 62, 30,213, 35, - 96, 14, 33, 68, 64, 41, 53,114,230,151,193,100,212,105,133, 12,215,101,112, 39,241,107, 65, 62,189,122,239, 60,121,237, 59,221, - 86,233, 81,241,108, 89, 89, 43,205, 55, 6,244,239, 11,134,201, 70,126,109, 53,128, 75,168, 43,189, 2,129, 88,132,140,221,159, - 64, 83,101,194,156,127,188, 12,142, 3,166, 62, 56, 6, 38,190,151,221,155,203,207,191, 4,142, 3, 18,135, 18, 0, 93, 0,244, -128, 78,111, 64,210, 3, 19, 33,246, 99,176,105,203, 62, 48, 12,144,254,221, 70,148, 22,254, 26,255, 80, 92,100,246,229,179,205, -115,113, 20,224, 56, 14, 28,199,193,100, 50, 65, 47,160, 48, 18, 35, 12, 6, 3, 52, 30, 58,128, 19,131,161, 38,152,132, 20,245, - 6, 29,212,202,186, 86,211, 22,236,165, 7,159, 47, 65, 96, 96, 32,122,247,238,141,208, 78,163, 0, 30, 3,147,233, 52, 24, 90, - 11,157,154,133,137, 83,163,252,102, 13,130, 3,171, 16,232, 23, 11,133,106,113, 92,115,155,188, 72,116, 44,168,190, 10,208,137, - 96, 96,140, 80, 11,249,168,151, 8,192, 23, 8, 1,206, 19,132, 71, 80,175,214, 64, 81,126, 29, 5,167,115, 80, 83, 92, 12,142, -227,192, 80,158, 75,133,230,171,181,191, 27,206, 79,205,123,202,126, 59,105,217,215,221, 90,116,210,210,210, 22,189,242,202, 43, -207, 20, 23, 23, 51,132,144, 96,153, 76,246, 29,204,155, 59,121,180,161, 44, 11,214,172, 89,179,229,214,173, 91, 72, 79, 79,199, -240,190,125,121,254,131, 7,183,185,130,164, 46, 92, 72, 20, 64, 28,165, 84,190,122,245,106, 57, 0, 72, 83, 82, 28,246, 74, 12, - 6,195,186,177,150,202, 36, 20, 10,209,167, 79, 31,108, 63,116, 40,211, 18, 13,112,152,231, 78,109, 85,187,104, 81, 50,201,202, - 42,164,167, 79,155, 35, 86, 54,255,127,189,247,222,123, 75, 23, 45, 74,246,117, 84,179, 60,141,236,246,193, 3, 7,250,240, 24, - 6,207, 62, 58, 7, 90,157, 30,171,190,252, 18, 30, 18, 9,116, 58, 29,116, 90, 45,134, 14,139,138,220,191,121,243,115,147,230, -204,249,200, 94,212,241,221, 5,207,115, 0,152, 43, 69, 69, 76, 83,193,111, 90, 61, 93,185,247,110,253,198,199,103,165,189, 78, - 39, 76,125, 58,158,138, 34, 93, 50, 4,108,119,237,163,219,252,237,158,183,107, 65,249,241,113,189,222,132,195, 19,130, 33,120, - 81, 6,229,156, 8,240,253, 67,156, 18,255,131, 7, 15,150,135,119,238,114,243,159,207, 62,211,237,245,151, 23, 98,245,134,117, - 23, 71, 70, 71,247, 92,247,233, 58,143,151, 22,190,138,205, 99, 70, 97,203,150, 45,143, 61,242,200, 35,155,218, 40,252,113, 59, -119,238,108,112,152, 44, 97,245, 23, 96,222, 42,221, 46, 14, 28, 56, 32, 15, 14, 14,198,176, 97,195, 88,134, 97,248,230,232, 44, - 7,129, 64,128,128,128, 0,116,234,212, 9,215,174, 93,195,129, 3, 7,228, 51,103,206,116,168,174, 72,165,210,228, 41, 83,166, -124,176,114,229,202, 79,251,246,237,187,150, 16,194, 1,248, 12,192, 36, 0, 71, 0,188, 75, 41, 45, 34,132,188, 10,224, 93, 71, -248, 86,206,159,255,253,216,228,100,178,107,215, 46,240,249,124,200,229,114,156, 63,127, 30,189,123,247,198,123,239,189,135, 65, -131, 6,225,153,103,158,225,191,249,230,155, 43, 91,244,252, 45,216,158,178,131, 2,128,135,135, 71,153,159,159, 31,196, 98, 49, -132, 66, 97,189,112, 25, 88,122,140,146,105,211,166, 97,217,178,101, 56,127,254, 60,182,110,221,122, 87,196,127,238,162,101,191, - 59, 58,203, 95,111,214, 8,104, 46, 2,192,240,121, 12,159,229,168,138,229, 76, 58,137,128,223,213, 75,200,244, 7,199, 2,145, -247, 2,157,122, 3,183,174,160,243,229,156,233,143,197, 70,132,103,156, 43, 19,215,108,149,102,152, 55,183,107,190, 14,243,120, - 86, 65,242, 1,208, 21,190, 97,125,113,253,114, 58,214,202, 54,128,209,123, 96, 98,124, 44,246, 29,204,129, 70, 3,120, 4,180, -220, 46, 73, 60,250, 66,171,185, 12,147,201,118,111,154,114, 0, 55,193,240,226,240,248, 19, 79,131, 19,169,241,227,238,175, 48, -245,193,167,224,225, 9,168,235,203, 44, 26,212, 60,140,224, 65, 96, 17,127, 35,107,130, 94,105,132,198,168, 65,173,132, 15,163, - 70, 0, 61,223, 8,158,145,128, 53,113, 80,106, 89,212,212,179, 45,170,217,121,249,114,218,179, 19, 1,143, 71, 64, 24, 17, 76, - 38, 10, 86, 83, 12,189,201,136,210,242, 58,212, 40,234, 81,167, 50,129,209,233,192,162, 28, 60,193, 57,116,233,174,196,168,232, - 24,249,119,223, 94,106,150,147, 7,128,170,116,208,170,110,194,116,171, 14,188, 94, 93,193, 48, 12, 76,172, 30,181,229, 69,184, -124, 34, 23,149,215,139, 45, 66,194, 7,195, 7,192,187, 59,221,128,214,144,255,250,245,235,245, 73, 73, 73,253,163,162,162, 88, -145, 72,164,254,224,131, 15, 70,194,188, 41, 81, 31,180,113,166,137, 48, 52,116, 1, 0,140, 30, 52, 8,161,161,161, 21,171, 87, -175,206, 2, 16, 63,108,240,224, 54, 71, 1,252,129,108,105, 74, 10, 17,132,132,196,173, 94,189, 90, 46, 8, 9,137,115, 38, 18, - 96, 20,137, 32,208,235,177,125,251,118,132,132,132, 96,198,196,137,214,104, 0,117,198, 8,184, 83,176,138,190, 76, 38,179,109, -248,112,248,240,225,176,209,163,147, 31, 68,203,219, 70,219, 98,132,159,191,127, 63, 30,195,224, 31, 73, 73,168,173, 83,162,178, -166, 26, 2, 1, 31,124,190,249, 37, 16, 8, 32,146,120,160, 87,120,248,135, 87, 79,157, 62,223,123,120,140,220, 30,233,149,162, - 34,124,187,253,127,183,121,252,214, 72,192,168,232, 33, 72,140,191,215,201, 59, 86,197, 1,222,217,125, 7, 39,102,247,237, 19, - 25,159,185,235, 75, 57,208, 49,250,254,243,190,254, 8,250,125, 27, 16,242,249, 25, 12,240,227,131,231, 19, 0, 86, 81,129,225, -123, 43,224,201, 39, 80,179, 20, 60, 59, 53,229,218,213,171,213,123,118,237,238,251,245,231, 95,227,147, 47, 63,187,190,238,131, -143,222, 14, 8, 12,168, 93,178,116,201,193, 77, 91, 54, 99,220,232, 88,124,155,182,245,235,110, 61,186,125, 61, 46,118,156, 75, -247,220, 84,252,119,237,218,133,174, 93,187,246, 58,121,242,228, 28,152,183, 26,183, 27,246, 55, 26,141,136,142,142,230, 88,150, -229,171, 84, 42,136,197, 98,112, 28,135,223,126,251, 13,249,249,249,240,242,242, 66, 76, 76, 12,202,203,203,145,155,155, 75,237, -117, 7, 72,165,210,217, 41, 41, 41, 43, 31,120,224, 1,175,181,107,215,250,124,252,241,199, 66,152,119, 45,205, 4, 16, 13,243, - 6,103, 31,193,188,157,251, 65,152,119, 60,109,149,111,231, 43,175,108, 30,208,191, 63, 89,157,148, 4,114,255,253,216,126,244, - 40, 87, 90, 90,186, 4,192,234, 27, 55,110, 76, 91,180,104,209,231, 63,252,240, 3, 98, 99, 99,225,233,233, 57,166, 37,174, 41, - 39,102, 96,199,142, 29, 88, 63,201, 92,199,252,252,228, 85,157, 58,117,130,151,151, 23,245,244,244,188, 97,120, 29, 32,211, 8, - 93,182,108, 25,172,134, 70, 99,253,186, 59,152,187,104, 89,131, 17,208, 72,236,155,158, 16,207,150, 85,254,124,181,114,221,198, - 35, 87, 95,254,173,180,238, 0, 3,202, 7, 40, 48,229, 61,252, 28,243, 1,254,171, 72,194,161,129, 43,128, 73,139,225, 45,224, -134, 61, 16, 21, 62,199,210, 93,112, 27,118, 29,170, 33,128, 18,211,158,120, 17, 28, 7, 0, 53, 48, 47,155,108, 68,143,190,209, - 16,139,248, 48,177,122, 80,131, 57, 44,226,237,237,141,234, 26, 69,139, 55,241,209,135,175, 16, 0,184,248,243,151, 96,152,198, - 78, 2,167,253, 21, 58,189, 17, 60,129, 24, 68,104,238, 67, 83, 41,149, 24, 51,102, 76,235,238, 8,103, 0,199,113, 96, 89, 22, -122,189, 30,245, 28,139, 58,131, 17,202, 50, 37,234,110,214, 65, 89, 94,131, 26,101, 45,202,117, 26, 40,213,181,168,213,183, 60, -214,201,219, 75, 13,150,229,160, 55,152, 80, 91,167, 68,254,213, 98,156, 56,157,135,159, 79,228,225,210,111, 5, 40,185, 81,133, -122,181, 1,170,122, 61,202, 74,235,112,225,215,107,200,205, 61,139,146,178,242, 22, 57,109,139, 10, 91,167, 70,201,185, 75,248, -101,239, 33,100,110,248, 16,135,182,110, 64, 73,193, 85,112,212, 8,142,144, 6,225,119,166,230,219, 11,243,219, 3,159,207, 7, -128, 91, 0,110,249,251,251,151,120,123,123,235, 23, 45, 90,116, 18,230, 1, 99, 12,204,107,101,231,187,202,191,102,205,154,212, -164,164, 36, 0, 64, 68,112,112,136,165, 79,156,215,158,149,195, 42,250,214, 72,128, 3,225,255, 4, 0, 88,181,106, 21,174,148, -149, 97,198,196,137,176, 70, 3,242,242,242, 0, 0, 59,228,114,234,104, 86, 44,120,251,109,188,250,206, 59, 13,225,125,235,123, -235,177,245,189, 35,225,127, 43,178,178, 10,105, 83,241,183, 61,206,202, 42,252,214, 17, 30, 63, 62,255,191, 58,131, 30, 60, 30, - 15,191, 21, 22,160,176,228, 6,142,159, 59, 15,131,193, 8, 6, 4,124, 62, 31,132, 16,112, 38, 19,180,106, 13,242, 14,103, 31, -114,128,150,177, 21,255, 71,103, 62,120,155,199,127,252, 76, 30,108, 35, 4,142,193, 38,156, 44,138,204,182, 10,127, 86,218,235, - 84,192, 94,137,251, 67, 45,128,154, 50, 8,187,247, 65,197,115,247, 32,239,235,143,192, 15,234,220,240, 81,197,115,247, 32, 72, -204,192,135,223,122,113,233, 27,217,183,139,135,135,167,199, 39, 95,172,209,197,223,123,175,112,212,152,209,155,175, 93,189,198, -253,118, 53, 31,224, 40,196, 34, 17, 98, 99, 98,177,123,215,110,236,220,185,211, 41, 47, 96,223,190,125,113, 82,169,148, 90,197, -255,192,129, 3, 88,183,110,157, 1, 0, 78,156, 56, 97,144, 74,165,143, 56,210,181, 80, 84, 84, 4,203,214,196, 76, 81, 81, 17, - 50, 51, 51,145,151,151, 7,181, 90, 13,133, 66,129, 83,167, 78,161,184,184, 24, 55,110,220, 64,143, 30, 61, 80, 84, 84,212, 42, -223,188,121,243, 30,127,248,225,135,223,143,139,139,243, 58,121,242,164,143, 70,163,249,167, 68, 34,201, 6,240,169, 76, 38, 91, - 44,147,201,234, 0,252, 15,192, 8, 66,136,144, 82,106,108,205,233,152, 63,127,254,227, 63, 44, 88,176, 57, 54, 36,132,176, 11, - 23, 98,140,193,128,147,187,118,209,210,210,210,167,101, 50,217,219, 50,153,172, 18,192,198,139, 23, 47,178, 44,203,194,203,203, - 11, 97, 97, 97, 94, 70,163,177, 89,241,159, 52,105, 18,100, 50, 25,164, 82, 41,164, 82,169, 71,105,105,105,223, 27, 55,110, 64, -173, 86, 19,133, 66,209,159,207,231, 79,176, 21,127,185, 92,142, 7, 31,124, 16, 29, 5,205,117, 1,132, 2,232, 53,125,120,247, -103,187, 5,122,206,129, 81, 11,244,157,128, 51,193,211,113,223,252,175,160,173,170, 5,207,199, 27,242,143, 31,199,184, 1, 63, - 35, 32, 47,115, 60,128,238, 45,253, 64,111,159,174,248, 37,111,135,141,189,161,182,116, 19, 26, 1,163, 30,124,142, 7,198, 82, -239,119,254, 96,238,110,138,157,156,210,114, 65,189, 64,241,192, 48,219,109, 16,137,229, 54, 4,128, 64, 12,150,152,192, 89,218, -221, 89,115, 94, 0, 0,249,245, 99,235, 91,172, 89, 38,142,130,229, 24, 48, 44, 11,198,160,135,198, 98, 89,104,121, 60,120,178, - 90, 40,181, 20, 68, 64, 96, 50,153,160, 49, 1, 21,106, 3, 90,234,204,102, 13, 28,116, 2, 30, 56, 13, 11,150,171,131,170,222, - 8, 30, 17, 64,207, 26, 97,160, 6,176, 70, 3, 32,228,192, 16,128,136, 56,212,105, 77, 40,175,212, 64,173,103,155, 13,198, 48, -196,212, 96, 0, 16,242,187,158, 24,117, 90,212,213,212,128, 33, 60,240,249, 20,160,124,240,136,235, 29,127,151,175, 95, 54,244, -237,209, 87,232, 72,216,191, 81,152,148, 16, 72, 36, 18, 0,208, 2, 48,240,249,124, 20, 22, 22, 98,249,242,229, 15, 2,184,177, -104,209,162, 97,190,190,190,126,117,117,117,215,107,107,107,157, 14,119, 11, 67, 67,159, 2,128, 78,157, 58,217, 86,224,218, 79, - 63,253, 52, 11, 64,194,176,193,131, 15,182, 87, 69,152, 63,127,126,188, 35, 6,192,143, 57, 57,113, 35, 71,142, 12,150, 42,201, -129, 0, 0, 32, 0, 73, 68, 65, 84, 27, 27, 21, 5,226,237,141,229,203,151, 99,225,194,133, 16, 8, 4, 48, 42, 20,240,245,245, -197,235,243,231, 55,140, 11,112,100,112, 96,211, 62,126,123, 99, 2, 90,194,114, 39, 6,119,158, 62,125, 26,167, 79,159,110,184, -190,165, 62, 78, 69, 77, 77, 63, 47,111,111, 84, 41, 20,144, 31, 63, 14, 62,195,131,222,104,132, 70,171, 5,199,113, 13,131, 21, - 89,163, 1, 6,189,222,145, 60,230, 0, 48,150,110, 0,206,166,224,235, 44,231,241,246,170, 79,133, 0, 16, 25, 30, 94,113,237, -226, 47,109,202,215,132,228,101,228,183, 51,233,113,123,119,126, 41,111,143, 72,128, 51, 97,255, 70, 97,217,109,159, 35,234,137, -151, 33,138, 24, 98,110, 43,170,202,144, 95, 99,222, 68, 78, 52,102, 10,138, 77, 44, 60, 86, 31,111,149, 67,169, 84,250,137, 36, - 98,244,142,136, 16, 95, 43,185,209,185,186,178, 26,179, 30,157, 35,223,115, 48, 19, 31, 47, 91,149,190,115,207,174,164,200,136, - 72, 60, 62,243, 49,228,158,201,193,206,237,219,233,116, 7, 66,236,182, 94,255,129, 3, 7, 48, 97,194, 4,171,177, 40,188,121, -243, 38,158,121,230, 25,161,245,246,237,113, 85, 87, 87, 99,220,184,113, 48,153, 76, 40, 42, 42, 66, 78, 78, 14, 6, 12, 24, 0, - 95, 95, 95,116,235,214, 13, 81, 81, 81, 96, 24, 6, 12,195,160,115,231,206, 13, 81,170, 22, 60,245, 1, 67,134, 12,249,104,204, -152, 49,188,188,188, 60, 31,147,201, 84,190,125,251,118,165, 86,171, 93, 46,147,201,108, 13,216,103, 39, 79,158, 92,188,103,207, -158, 8, 66, 72, 25, 90,216,209, 86, 42,149, 14,155, 31, 31,191,113, 20,159, 79, 42,151, 46, 5, 53, 26, 33,231,241,184, 92,141, -230, 73,153, 76,246,141,173,221,241,214, 91,111,241, 25,134, 65, 77, 77, 13, 10, 11, 11, 43, 6, 13, 26, 20,210,148,111,210,164, - 73,183,253, 70, 88, 88, 88,128,137, 82,104, 53, 26, 92,188,120, 17, 44,203,146,142, 42,254,183, 25, 0,186,173,210,200, 80, 95, -201,216,201, 67,195,158,241,145, 8, 70,178, 38, 78,193,167, 38, 31,248,117,230,149,213,234,160,173,170, 3,132,124,152,106, 85, - 40, 81, 24,128,192,238, 96, 56,131, 24,173,204, 38,184,170, 84,162,143,159, 15, 88, 61,112, 53,251, 91,244,142,155,212,224,192, - 25, 13, 70, 8,192,160, 94,103,222,161,246,129,184,104, 72, 2,195, 90, 77,240, 3,131, 9,246,156,167, 16,136, 1, 97,247, 73, - 48, 20, 31,109,112, 28, 4, 66, 17,140,208,193, 75, 98,222,145,116,215,158,173,248,229, 68,118,252,156,137, 49, 45,183, 70, 28, - 7,161, 65, 11, 35,132, 96, 24, 22,208,153, 27, 54,163,209, 8,189, 78, 0, 30, 95, 0,232, 0,202,153,187, 8,122,132, 71,180, -200,165,209,113,224,241, 8,140,172, 17, 58, 61, 7,165,202, 92, 14,141, 28,133, 65,207, 1,124,128, 39,224,129, 47, 6,136,214, - 4,142,176,224,160,133, 74,107, 9, 72,219,129, 9, 0,195, 1,148, 0, 12,195,129, 16, 30, 56, 74,192, 48,150,177, 84, 28, 3, -142, 97, 64, 56,199, 28,100, 27,239, 95,232,106, 1,242,240,240,128,197,219, 15, 46, 44, 44,172, 88,190,124,121, 60,128,135, 22, - 45, 90, 52,177,103,207,158,106,149, 74, 85,205,178,108,131, 80, 56,163,255,107,214,172,249, 50, 41, 41, 9,225, 65, 65, 13, 39, -195,131,130,252, 44, 81,128,224, 63,162,194, 24, 12, 6,185,213,219,167, 42, 21,254,253,239,127, 67, 95, 93,221, 48,242,173,183, -197, 88, 17,232,245,120,240,193, 7, 43, 74, 43, 42, 30, 9,243,240,216,124, 55,210,102, 59,168,207,182,255,191, 57,196,196,196, - 32, 33,161,103,195,245,205,173, 3, 0, 0,172,222,128, 90, 67, 13,116, 58, 29,252,124,125, 33, 22,138, 96, 52,177,160,148,194, -100, 50,193, 96, 48,192,104, 52,130, 99, 77,142,230, 47,119,165,168,136,137, 12, 15,183,122, 4,220,149,162, 34,230,219,237,255, - 19,219, 70, 4, 34,195,195,107,209, 78,131,217,250, 69, 39,101,151, 20,156,106,151,103,236,234, 24,128,123, 51, 43, 81, 17,158, - 14, 97,247, 62, 32, 17, 67,208, 99,195, 89, 84,233, 56,120,242, 9, 12, 63,253,128,203,133,215,236,238,159,167,101, 13, 56,157, -123, 2, 31,173,252, 16,247,196,141,197, 91,255,239, 29,236,223,187, 31,155, 55,125,131, 49,227,199, 38,117, 11,239, 14,190,135, - 0, 7,143, 30,196,150,175,191,193,142, 31,182, 99,247,238,221,244,255,254,239,255, 72, 43, 34, 75,155, 10,191, 21,181,181,206, -111,112,167, 82,169,224,235,235,123, 28,192,168,240,240,112,196,196,196,128,199,227,129,227, 56,244,232,209, 3, 34,145, 8,117, -117,117, 8, 15, 15,135,183,183,247,117,149, 74,213,163, 37, 46,153, 76,118, 81, 42,149,166,238,216,177, 35, 49, 50, 50,178,223, -246,237,219,235, 21, 10,197,187, 50,153,108,139, 77,250,167,223,123,239,189,175,108,216,176, 97, 27,128, 10, 0,201, 0,126, 6, - 48,180, 25,190,179, 82,169, 52,213,239,212,169, 55, 30,102, 89,124, 8,112, 95,214,215, 63,214,132,239,161, 23, 94,120,225,195, -185,115,231,226,218,181,107,216,189,123, 55, 88,150, 61, 4,224,225,214,238,219, 18, 5, 96,252,120,188,106, 47,131, 1,234,179, -103,105, 48,199,169,174, 2,170,187, 45,254, 81, 81, 81, 56,119,238, 92,179, 33,127,123, 93, 0, 61,167, 15,239,190,196, 71, 34, - 24, 89,169,212,237, 63,118,165,114, 57,120, 34,224,242, 81,220, 31, 78,177,248,249, 7, 17, 51, 48, 28, 47, 72, 39, 99,106, 47, - 3,112,225, 0,168, 64,194,162,213,193, 58,181,200,175, 45, 6, 95, 4, 60, 48,245,101,108,249,100, 25, 0, 3,160,209,195,164, - 5,126,144,159, 67,214, 73,243,140,194,174,221, 35,192,240,237,139, 87,226, 80, 2,163, 14,216,181,123, 31,134, 79,124,222,236, -253, 67, 0,158, 4, 72,153,146,140,196,241,211, 0, 0, 37,215, 11,192,234, 12,173, 91,244,148,130, 37,102,129,215, 27,204,131, -255,244, 58, 45, 52, 26, 13,234,235,235,161, 82,214, 65,165, 82, 65,169,170,135,174,190, 30, 90,173,182,229,194, 95, 79,160,213, -153,160,213,153,160,214, 24,161,170,215, 67,161,210,163, 86,105, 64,157,202,136,218, 90,243,255,154,106, 22, 53, 10, 22, 53,117, - 44,170,106, 12,184, 85,213,114, 26, 25, 74, 97, 2, 64, 76, 4,132,225, 64, 9, 5, 40, 5,165, 60,152,184,223,179,143,179,180, - 30,206,198,198,251,143,233,143,156, 61, 57,216,127,104,127,131, 81,112,249,250,101,135,190,203,227,241,192, 55,231, 87, 24,128, - 94, 43, 86,172, 56, 15, 96,245,235,175,191,254, 82,207,158, 61, 89,115,144,192,156, 48, 39,197,159, 8, 67, 67,119, 2, 64,104, -104,232,109, 31, 62,247,220,115,236,169,203,151,183,158,189,112,161,221,194,186,171, 87,175,150, 59,186,111,188,209,102,138,197, -247,223,127,143,171,229,230, 46,156, 31,179,179, 27,125,118,249,242,229,144,224,224, 96,197, 31, 97,168, 36, 36,244,100, 44, 13, - 90,211, 6,191,209,231,118, 13, 60, 31,239,223, 56,147, 9,202, 26, 5,170,170,170, 80, 93,171,128, 90,163,129, 90,163,129,170, -190, 30,234, 58, 37, 84,181,255,159,189, 43,143,111,162,218,254,223, 59, 89,154,182, 64, 23,118,202, 90,164,236,178, 20,161, 5, -129, 4, 82,168, 34, 42, 74, 1,225,137,125, 5,155,226, 6, 34, 62, 84, 84,220, 80,121, 63, 11,184,210,212, 39,130,239,129, 64, -139, 11,155, 44,129,164,178,180,212,130, 11,139, 64,161,208, 66, 89, 10, 77,186, 37,105,182,185,191, 63,146, 9,105, 73,147, 73, - 90, 4, 53,223,207,167,144, 89,114, 50,115,231,206,253,158,115,238,185,231, 84,160,214,104,128,185,182, 22,172,213,235,252, 38, -211,163,107, 87,110,204, 96, 1,152, 93,167, 3, 0,224,127,155,182, 96,113,250,199,225, 0,218,250,122,223,191, 31,201,150,170, -178, 94,170,211,217,206, 30,255,225,246,186,255, 1, 92,158,218, 21, 93,190,252, 25,164,219,221, 48,229,100,163,248,159,131, 16, - 42, 36,216,151,208, 26,214,202,107, 24,178,163, 12, 94,102, 0, 48,121,242,100,242,228,220, 57, 56,115,234, 20,114, 53,251, 16, -214, 60, 12,143, 77,125, 12,225, 45, 35,113, 36,191, 0,205,196, 18,132,134,134,162,125,215, 14,248,122,253,215,120,105,209, 43, -168,169,240,191, 74,237,224,193,131,125,254, 78,243,230,205, 81, 89, 89, 57,140, 97, 24,115,167, 78,157, 48,116,232, 80,244,237, -219, 23,173, 90,181,130, 68, 34, 65,215,174, 93, 49, 96,192, 0,132,135,135,163,186,186,186, 75,243,230,205,225,133, 88,255, 47, - 39, 39,103,247, 87, 95,125, 37,210,233,116,175,214, 35,235,164,145, 35, 71,174,248,242,203, 47, 87,181,109,219,246, 93, 66, 72, - 51, 0, 47, 1, 88,236, 65,222,162,119,170,171,255,111,150,213,106,251,194,104,156, 94, 79,222,228,105,138,215,191,121,118,222, - 11,130, 83,167, 78,225,208,161, 67,248,242,203, 47,107, 0,188,204,243,246,153, 16,147, 73, 66,127,255, 29,157, 84, 42, 18, 85, - 90, 42, 0, 64,151, 45, 91,134,173, 91,183,254,161,253,173,190, 71,175, 33, 15, 95,253, 65, 32, 72,192,144,230, 37,229,250,181, - 95,231,158,123,249,151, 98,109,190,209, 70,206,224,250, 57, 72,190,121, 10,239,142,168, 70,193,155, 67,241,161,172, 6,161,223, - 61, 13,104, 47,162,134, 74,142, 58, 52,175, 6,112, 35,170,255,215,223,182,224,245,215,191,194, 93, 45,250,227,248,193, 95,177, - 75,253, 59,100,241,125,145, 48,210,222,209,168, 64, 8,179, 15,241, 17,137,131,122,225,157,255,123, 31, 59,142, 86,161, 89,215, - 62,120,224,129,137,216,185,247, 91,108,219,105,143,178,100,108, 22, 4,137, 60,143,115,148,181,193,198,218,173, 25, 56,172, 25, -179,217,140,218,218, 90, 24,141, 70,232, 13, 70, 24, 13,122, 24, 13,122, 24, 76,181, 48,155,106, 27,118,127, 25,155,163,178,198, -134, 42, 35,139, 42, 35,107,255, 92,205,162, 70,111, 69,141,193, 10,157,214,134,114,173, 5,229, 58, 11,202,203, 45,184,126,221, -140,171,215, 45, 30, 21,128, 27,238,127,151,107,230,220, 55, 2, 10, 1, 33,160,245,162,254, 41,241, 78,182, 47,206,124, 17,189, -227,123, 59,183, 85,171, 85, 78,143,192,129,237, 7,112,170,248, 20,175,100, 79, 44,107,255,173,236,236,236,253,148,210,126,147, - 39, 79,158,217,173, 91,183,214, 0, 24,150,101,131, 44, 22, 75,132,213,106,109,225, 70, 1, 96, 61,184,254, 23,127,250,233,167, -247, 79,158, 60, 25,221, 90,183,230, 53,117,213, 24,136,218,180,145, 2,192,144, 94,189,100,222,206,237,209,174,157, 44, 61, 61, - 29,199,139,139,171,190,217,181, 11, 39, 79,158,116, 90,253, 61,123,246,132,227,152,249,155, 93,187, 80, 92, 92,140, 83, 5, 5, - 70,111, 50,111, 69, 12, 0, 0, 58,122,244,232,167, 92, 73,159,251, 63, 54, 54,150,151, 59, 23, 0, 10, 79,158, 45,176, 90,173, - 48,155, 77,208, 94, 45,195,181,203, 87,112,253,202, 85, 92,191,114, 21,218,178,107,168, 40, 47,135, 73,175,183,199,207, 84, 84, - 96,144, 92,238,173, 13,173,139,211, 63, 22, 46, 78,255, 88, 8,160, 10, 0, 59,108,240,221, 55,157,228, 18, 23,192, 27, 39,142, -100, 75, 75,207, 22,168, 7, 12,189,113, 13,231,206, 28,148, 86, 92, 43, 82, 55,166,127,144, 41,186, 58,150,191, 63, 56,173,213, -163,100,246, 61,160,231,126, 67,155,207,143, 32,116,229, 97, 92,158,218, 21,177, 59,202, 64, 68, 65, 16, 18, 64,200,120, 87, 64, -159,126,230, 25,242,218,251,239,224,185, 5,243, 97, 97,109, 56,121,190, 16, 51, 30,155, 14,177, 68,130,239,191,219, 12, 88,108, - 48,213,154,176,175,224, 32,140,198, 26,164, 38, 39,231, 20, 20, 20, 80, 15,132, 72, 38, 77,154, 36, 27, 55,110, 28, 8, 33,216, -189,123,247, 77, 46,253, 23, 95,228, 31, 39,212,178,101, 75, 92,186,116, 9, 0,132, 25, 25, 25,184,118,237, 26,250,247,239,143, -240,240,112, 48, 12,131,252,252,124, 48, 12, 3, 66, 8, 46, 93,186,132,150, 45, 91,122,149,169, 84, 42,223, 53,155,205,163,148, - 74,229, 6, 23,178,126,108,228,200,145,233,179,103,207,142,200,200,200,144, 16, 66, 24, 0,223, 2, 88,160, 84, 42,175,122,145, -247,175, 67, 22,203,144,250,242,166, 45,252,102,227,163,211,159, 38,247,207,201,128,230,208, 9,164,167,167,179, 85, 85, 85, 41, - 74,165,242, 60,143, 41, 68, 0, 96,239,106,222, 60,188,211,149, 43,184,215, 96, 64,123,145, 40, 52, 84, 32, 96, 74, 75, 75,111, -138,197,249,163,148, 0,238,143,215, 20, 0,128,179, 95, 31, 60,247,140, 86,111, 58, 12,123,224, 86,251,220,194,107,153,163,122, -181, 93, 36, 60,119, 40, 18, 95, 62, 14, 4,133, 2, 38, 61, 64, 41, 44, 2,201,213,125,199, 47,127, 1,160,193,236, 75,235,214, -126, 38,155, 62, 99,166, 26, 0,244,172, 5,103, 42, 74, 0,216,112, 87,139,110,144,201,238, 70,219, 86,237, 80, 94, 89,101,247, - 21,152,173,184, 92,161, 71,111, 15, 55,213,177,115, 60, 46,150,228, 58,222, 76, 33, 18, 7,216, 99, 0,118, 28,181, 96,231,214, -108, 92,189,126, 9, 45,195,237, 43, 9,194,197, 34,220, 61,196,243,122, 80, 51,132, 16,179, 86,216, 32, 0, 75, 8, 24, 27, 11, - 88,172,176,137,132, 0, 97,192,189,147, 44,133, 61, 87,128, 7, 60, 60,237, 37,242,221,127, 23,208, 16, 49,133, 80,228,226, 97, -176, 0, 86, 10,212,154, 1,155,201, 6, 66, 8,136,152,192,106, 3,244, 38, 96, 86,242,191,137,187, 84,142, 54, 23, 13,141,101, - 88, 16,135,251,223,174, 20, 16,216, 88, 6,140,192,110,245, 51, 0,168,128, 2,148,159, 23,192,149,252,221,109, 31,216,126,160, -155,215, 41, 9,155, 13, 38,147, 9,147, 39, 79,238,155,157,157,189, 28,192,192,236,236,236, 29,217,217,217,251, 38, 79,158,252, - 76,247,238,221, 45,132,144,150, 31,126,248,225,174,151, 94,122,105,134, 86,171,205,241,160,124, 58,251,228,130, 5, 11, 22, 47, - 88,176, 0, 59,118,236,128,254,234,205,239,114,183,214,173,113,238,220, 57, 0, 80,243, 73, 12,212, 80,210, 31, 81,155, 54,210, - 79, 63,253, 84, 77, 41,197,144,158, 61,101,131,121,172, 44,232,223,187,183,134, 48,204,248,147, 63,253,212, 21, 64, 16,128,143, -184,213, 0, 61,218,183,199,252,249,243,113,224,192,129,165, 49, 49, 49, 57,253,162,162,188,198, 40,184,203, 3,224,111, 12,128, - 43,184, 60, 0,113,113, 73, 63,229,229,149, 29, 80, 40, 20, 98,199, 52,193,112, 0,185,124,147, 0,117, 29,208,231, 21,227,229, - 43,227, 88,171,173,151,190,178, 18,149,215,175,129, 16, 6,148,178,168,173,173, 5,165, 20,148, 82,156, 59,241, 59, 44,102, 19, -238, 26, 18,235,173, 13, 93,199,156,112, 0,204,253,178,209,236,253,178,209,117,130,254, 28, 83, 4,188,113,242,151,111,164,151, -206, 22,168, 1,160,107,151, 46,248,190,158, 23,160,117,231,193, 50,220, 70, 12,249,161, 12, 5,247, 1, 3, 99,229, 40,123,122, - 56,218,125,118, 16,167,181,122, 68,136, 9,202,181, 58, 8, 9,241,234, 1,224, 48,115,230,204, 58,103,110,217,178,133,222, 63, -225, 62,108,221,188, 21, 27, 55,110,196, 27,139, 94,195, 46,205, 30, 8,132, 2, 68,117,140, 26, 93, 89,233,121,233,114, 98, 98, -162, 38, 49, 49,145,236,216,177, 67, 58,110,220,184, 58,177, 0,187,119,239,198,153, 51,103,106,149, 74,101,123, 62,215,214,181, -107, 87, 20, 21, 21,161, 79,159, 62,214,121,243,230,137,215,175, 95,143,176,176, 48,156, 60,121,242, 38,207,107, 81, 81, 17,186, -242,124,206, 74,229,141,196,115, 10,133,226,241,123,238,185,231,173,199, 30,123, 44,172,160,160,160,121,109,109,237, 63,131,131, -131, 31, 48, 26,141, 31, 40,149,202,239,121,202,251,197, 85,222, 3,207,174, 95,115,239,216, 73,228,223, 42,128,116,120, 16,239, -174,120,133,106, 11, 79,166, 40,149,202, 44,111,178, 92,188,108,164,218, 98,169, 16, 7, 5,161,133, 88,140, 96,155,205,164,183, -217,108,183,131,252,249,162,142, 2, 32,121, 76,121, 92,251,181,226,180,228, 49, 37, 55,165, 89,114,236,107,197, 15,213,181, 86, -253,176,187, 90,221, 31, 25, 34,184, 71, 96,170, 13,181, 82,166,186,188,218,156,151,123,230,202,206, 82,173, 33, 71,242,152,242, - 50, 86,174,116,251, 3, 53,250,214,154,180,167,231,200, 0,168, 89, 1, 55,205, 39,192,153,170,203,120,253,153, 20, 24, 12, 38, - 84, 25,237, 49, 0,102, 38, 8, 99, 18, 61,167,217,125,109, 81, 50,217,177,109,136,253,229,182,113,150,179, 21,137,253, 9,166, - 61,181, 12, 33, 33, 65,104, 17, 44,145, 1, 80, 23, 30, 59, 34,139,239,231, 57, 33,136,144, 90, 97, 38,118, 37, 0,132,192, 70, -169, 93, 17,224, 18, 54, 16, 6, 66,150,133,149, 91,118,224, 69, 9,168, 48,134,195,104, 42,135, 88,200, 56,211,156, 89, 89,192, - 98,161,176, 88, 41,106,140, 44,136,128,192, 6, 2, 11,123,195,117,239,150, 96, 89, 6, 12,177,129,216, 8, 40, 67,157,238,127, -210,128,241,204, 73,122,238,121, 25, 89,185,242,164, 71, 11,239,247,220,223, 27,219,119,204,148, 82, 24,141, 70,244,239,223,255, -114,116,116,244,164,243,231,207,247,216,184,113, 99, 62,128,135,178,179,179, 31,114, 61,249,253,247,223,215,188,244,210, 75, 50, -173, 86,235,141, 32,156, 13,146,150,150,214,224, 73,143, 62,241, 4, 0,223, 18, 3,113, 89,247,234, 99,104,239,222, 62, 45, 43, -236,215,179,231, 46, 87, 79, 70,122,122,250, 39, 19, 39, 78,180,158, 58,117, 74, 88, 92, 92,140,174, 45, 91,230, 70,133,132,240, - 10, 80,188, 21,121, 0,234,145,251,213,156,156, 28,215, 24,143,163, 14, 69,128,111,198, 64,125,112,251,118,143,158,220,179, 55, - 55, 60, 52,180, 69,149,174, 2, 86,171, 21,212,241, 30,232,174,150,161, 74,167, 3,165,148,143,245,111,127, 89,111,196,156, 48, -142,229,128,140, 99,217,159, 51, 49, 80,225,249,243,252,149, 0,195,175,210,139,133,249, 78, 43,255,251, 44,251,242,191,214,209, - 35,100, 3, 98, 39,106,110,223,240, 74,111, 86, 2,240, 57, 6,166,189,142, 43, 44,139, 1,171,243,145,159,216, 22,125,183, 94, -133,144, 0,205, 69,254,173,152,157, 56,113, 34,217,171,217, 75,199, 36,140,197,230, 77,223,225,237,165,239, 99, 97,101, 37, 40, -203, 98,195,134, 77, 40, 45, 45,125, 0,128, 87, 31,180, 59, 69, 0, 0, 38, 77,154,244, 11,128,106, 62,215, 18, 31, 31, 79, 46, - 93,186, 68,143, 28, 57, 34, 30, 60,120, 48,198,142, 29, 11,181, 90,141,206,157, 59,195,100, 50, 97,244,232,209,160,148,178, 71, -142, 28, 97, 68, 34,145,207, 25, 1, 21, 10, 69,159,176,176,176,229, 83,167, 78, 21,157, 56,113,162,133,201,100,106, 40, 48,144, -175,188, 65, 81, 3,167,172, 25, 56,106, 42,249, 34, 7,168, 50, 2,230,115, 59, 88,109,161,186,126, 96,160, 39,101,130, 83, 2, -132,218,202, 74,171,216, 98,129, 65, 44,134,208,158,245,135,253,163,123, 29,151, 7,192,213,242,119,183,207,173, 43,213,133,252, -185,237,223,139,191, 86,148, 20, 95,175,201, 5,208,222,241,242,154, 0,148, 2, 40,146, 60,166,244,234,226, 28, 60,224, 65,205, -241,223, 74,100, 54,218, 76,237,250,114,212,232,171, 32, 16,134, 1, 76, 8,254,245, 1,255, 20,147,137, 19,250,145,119,230, 60, - 32, 5, 99, 80,187, 54,111,179,102, 97,176, 89,116, 0,213,163,248, 96, 38,153, 57, 45,209,171, 44, 11, 4, 0,165,118,162,134, - 0, 98,234, 80, 4, 28,228,111,207, 1, 8,128,231,218,205,228,212, 87, 73,230,199,111, 80,171, 69, 11,161, 99, 97, 47,165, 20, - 54, 43, 69,173, 5,168,170,182,194, 2, 10, 43,101, 32, 20, 17, 44,121,235,147, 6,239,123,246,108,123,144,214,154,213,103, 40, -177,216,173,127, 10,128, 82, 2, 80,135,197, 64, 5, 32, 2, 22, 44, 43,196, 11, 11,198,241,106,195,217,111,207,150,157, 63,123, -222, 19, 1,139, 96, 95,170,225,137,157, 88, 0, 48,153, 76,208,233,116,186,176,176, 48,196,198,198,254, 58,116,232,208,160,107, -215,174,225,236,217,179,246,229, 97, 44, 43,221,180,105,147,218,161, 4,168,121, 40, 1,150,164,196,196,164,174,253,251,219,238, -233,213, 75,239,232,163, 38,212, 93, 17,137,164, 68,251,179,237,202, 35, 41,208,139, 47,190, 40, 3,128, 33, 61,123,222,116, 44, -118,192,128, 70, 17, 68,255,222,189, 63, 99, 24,198,118,242,167,159, 66,219,182,109,123,189,223,240,225,107,110,167, 70,239,134, -212,245,177,177,177,174,209,214,206,117,172, 62, 40, 1, 39, 6,141, 29, 51,108,243,127,190,216, 20,221,173,107, 31,147,169, 22, - 54,139, 21, 44,203,162,121, 68, 4, 42,181, 90, 12,146,203,101, 60,172,127, 0,168,120,243,133,103,219, 0, 48, 23,158, 63, 47, -230,230,255, 15, 29,249, 13,247,203, 70,179,139,211, 63,246,150, 28,200,137,152,246, 58,122,242,212, 73,217,222,157,223,215,113, -241,143, 25,255,144,140,105, 17,223,168,231,218, 80,128,159,251,253,252, 57,108,200, 15,101,192, 15,207, 56,183,239,250,254,198, - 18,224, 74,139,255,235,195,199, 72,199,144,175, 74,190,186,111,220,132,196,237, 79, 62, 62,107,255,221, 3,250,223,187,249,251, - 45,200,253,229, 48, 82, 83, 83,183,173,108,192, 64,243,162, 8,204,250,246,219,111,255,243,237,183,223,198, 37, 38, 38,242,190, -184,113,227,198,141,217,181,107,215,222,173, 91,183, 34, 58, 58, 26, 9, 9, 9, 8, 11, 11, 59, 93, 89, 89, 25,115,252,248,113, - 20, 21, 21, 49, 34,145, 8,227,198,141,147,251,122,159,142,192,192,165, 91,182,108,105, 48, 48,208, 71,121, 63, 43, 20,138,247, -190,203,126,240, 21, 99,212, 12, 24,127,122,149,189,180,111,201,227,190,202,115, 40, 1,181,197,101,101,162, 23, 78,159,190,104, - 51, 24,152, 95, 25, 70,212, 78, 32,184,162, 80, 40,110,203, 20,128,187,108,128,222,166, 0,220, 66,242,152, 82, 15,224, 55,199, -159, 95,120,252,241,103, 52,105,105, 47,201, 50,148,111,171,163,186,244, 0, 96,130, 40, 72,130,139,151,171, 48,122,226, 76,226, -187,188, 7, 53,119,245,138,193,234, 85,223, 0,108, 49, 0, 33,172,181, 70, 68,181, 15,147,117,110, 97,229,255,242,219, 88, 8, - 25, 22, 22, 34,132,136, 90,111, 40, 2,176, 2,212, 6,190,129, 97,174, 72,125,246, 13, 2, 0,139, 95,158, 67, 69, 66,187,181, -111,101,237, 46,243,138,106, 10,155, 21, 16, 8, 89,124,246, 41, 63,165,231,137,100,123,106,228, 85, 95,156,162,224,114,194, 51, - 0, 75,236,238,254,249, 11, 30,240,233, 34, 43,107, 42, 53, 17,109, 35, 26,219,191, 24,192,190,138,194,104, 52,194,102,179,161, -170,170, 10, 2,129, 0, 54,155, 13,237,218,181,131,197, 98,129, 82,169, 84,215,243, 4,168,189,213, 12, 24,212,191,127, 54, 0, - 52, 69,198, 63, 0,136, 36, 68, 3, 0,145, 3, 6,220, 18, 51,175,111,207,158, 25,141, 17,240,194,226,197,117, 86, 73, 44,120, -227,141, 58,158, 1, 95,230,254,221,144,185,222,211,106, 0, 31,210, 1,159,124,112,246,172,126, 0, 4, 39,115,114, 44,181, 6, - 35, 88,155, 13,189, 99, 99,101,237, 99,250,160,235,128, 62,252,222, 57, 74,166,238,252, 97,155,115,115,120,159,104,231,231,157, - 63,108,187,105,219, 83,104,252,233,203, 17,132,105, 17,143,177,227,137,236,196,201,179,184, 92,124, 84, 13, 0,123,119,126,175, -110,219,249,172,172,255,176,127,248,172, 4, 76,153, 50, 5,190,166,247,181, 17,207,121,183, 75, 38,181,195, 15,151,106,111,249, -128, 63,115,230,204, 31, 0, 48, 5, 5, 5,236,158,188, 28,180,108,213, 18,141,169,207,145,152,152,248, 69, 98, 98,226, 87,240, -158,222,185, 14,154, 55,111,174,126,244,209, 71, 73,110,110, 46, 61,123,246, 44,242,243,243, 81, 93, 93, 29,211, 20,181, 0, 28, -100,251,127, 10,133, 66,148,155,155,219,223,108, 54,191,234, 58,151,239,167,188, 69, 10,197, 63, 68, 97,221,191,154, 95,121,118, -215,140, 70,200,179,174, 63,116,232, 1, 0, 9, 0,126, 6,203, 86, 3,184, 58,109,225, 55, 72, 13,123, 4,153,149,127,140, 18, -192,173, 2,112,183,223, 47, 5,192,215,169,132, 6, 93, 85,143, 60,161,217,182,243, 12,121,120, 66, 8,109, 19,213, 9,218,106, - 43, 70, 79,120,220,239,142, 16,127, 79, 47, 18,127,207, 43, 80, 40, 94,167,192, 85, 68, 52, 23,162,115, 36,235,211, 75, 63,228, -159, 11,110, 89,150,176, 55,223, 91, 73, 0, 96,238,188,103,168,217,104, 1, 11,251,178,185,229,159, 46,247,235, 55, 83,102,217, -107, 6,172,250,207, 73,202, 82, 1, 94,126,233,161,219,153,225, 76,236,234,198, 54,153, 76, 48,155,205, 78, 34,227, 8, 44, 80, - 37,208,139, 11,210,135,244,195,126,194,188,112, 97, 82,144,195,131,210,216, 20,100, 20,128,181,215,232,209,117,174,185,107,251, -118,188, 5, 4,177, 38,205, 19, 19,125, 54,252, 80,191, 20,112, 29,251,187, 69,156,166,239,208, 56,244, 29,138, 70,183,165,183, -194, 62,245,117, 96, 43, 9,130,145,241,188, 34,245,108,181, 21, 49,205,249, 12,145, 77,210, 21,232,144, 33, 67,154,178, 79, 89, -252,253, 98,124,124, 60,241,150,136,173, 17,164,253,174, 66,161,248,206, 53, 54,160,145,242,254,165, 80, 40,214,185,198, 6,248, - 33,195, 2,160, 2, 64,189,184,129,107,127, 24,249,123, 34,123,183, 61,110,224,192,129,119,106,249,200, 0,254, 68,232,209,163, - 7, 10, 11, 11, 3, 13, 17, 64, 0, 1, 4,240, 39, 1, 19,104,130, 0,154, 2, 1,242, 15, 32,128, 0, 2, 8, 40, 0, 1, 4, - 16, 64, 0, 1, 4, 16, 64, 64, 1, 8, 32,128, 0, 2, 8, 32,128, 0, 2, 10, 64, 0, 1, 4, 16, 64, 0, 1, 4,112,219, 81, - 39, 52,117,206,156, 57,126, 71,143,186,203,100, 23,144, 23,144, 23,144,119,103,200, 83, 40, 20, 84,169,108,120,217,105,160,253, - 2,242, 2,242,254, 90,242,124, 86, 0,184,129,194, 87, 33,158, 6,150,166,150, 23,192,157, 9,111, 4, 19,192,157,249, 28,124, - 60, 63, 20,192, 61,251,247,239, 95, 34, 16, 8,134, 7, 5, 5,193, 96, 48, 28,188,247,222,123, 23, 1,200, 7, 96,184, 19,218, - 64,165, 82, 73,179,178,178,212,127,197,113,229,216,177, 99,200,207,207,247,122, 94, 94, 94, 30, 61,118,236, 24, 50, 51, 51, 73, -191,126,253, 26, 45,143,195,208,161, 67,225, 73, 94, 0,127, 98, 15, 0, 7, 95,210,147,242, 73,148,227, 78, 94, 67,229, 97,253, - 73,188,243, 87, 31,208,249,158, 59,126,252,120,217, 35,143, 60,162,225, 43, 51, 42,234,230,210,203,165,165,165,117,182,147,146, -146, 32,151,203, 9, 31,121,183, 82, 9, 24, 63,126, 60, 5,128,157, 59,119,146, 59, 65,158, 94,175, 31,187,105,211, 38,213,233, -211,167, 1, 0,209,209,209, 15,166,164,164,108,241,247,249,186,246,123, 74,169,243,253,224,246,115,239, 10, 33, 4, 25, 25, 25, -196,147,242,204,247, 57,248,248,188,250, 28, 59,118,108, 83, 85, 85, 85,175, 46, 93,186,224,250,245,235,168,173,173, 5,128,225, -155, 54,109, 82,135,134,134,158, 76, 76, 76,124, 24,128,199, 82,146, 35, 70,140,240,201, 32, 56,112,224,128, 12, 60, 83, 61,115, -200,202,202, 82, 39, 37, 37,201,228,114,185,198,215,231,145,154,154,234,211,245, 77,153, 50,133,247,251,193,161, 75, 23,123, 5, -220,234,234,106,152, 76, 38,174, 63,241,122,223,242,243,243,241,223,255,122,206, 80,107, 50,153,232,240,225,195,209,187,119,111, -172, 93,187,182,204,100, 50,117,110,104, 93,120,126,126, 62,102,204,152,193,235, 94,175, 94,189,138, 37, 75,150,224, 78,206,109, - 31,192, 13,212, 79, 6,116, 43, 19, 1, 5,172,216, 91,136,239, 51,188,167, 52,126,120,206, 14,159,100,170,213, 55, 12,164,211, -167, 79, 35, 52, 52,212, 57, 8,185,180, 7, 31,107,139,214,223,174, 63,128,169, 84, 42,154,149,149,229,183, 5,182,110,221, 58, -233,248,241,227, 27,148,223, 24,164,165,165,209, 81,163, 70,201,166, 79,159,238, 19, 89,108,218,180, 73,213,166, 77, 27,204,156, - 57, 19, 58,157,142, 77, 79, 79,223,172,211,233,166, 69, 68, 68,248,148, 69,140, 16,130, 31,126,248,193,185,157,152,152,136, 29, - 59,118,120,220,246,134,250, 74,128, 66,161,160,177,177,177,200,204,204,164, 92, 98, 38, 95,201,191,178,178, 50,183,123,247,238, - 45, 0, 64, 34,145, 32, 56, 56, 24,101,101,101,168,168,168, 64, 88, 88, 24,202,202,202,122,237,216,177, 35, 63, 49, 49,177, 39, -128, 43,158,132,245,235,215, 15, 73, 73, 73,136,142,190,145,245,111,233,210,165,117,206, 89,184,112, 33,103,201,170,167, 79,159, -238,243,243,246,135,252, 57,172, 88,177,162,161, 67,206, 90, 5,254, 34, 52, 52, 20, 39, 78,156,128, 72, 36,130,217,108,198,142, - 29, 59, 80, 88, 88,136,151, 95,126,217, 39, 57, 87,235, 21,201,122,240,193, 7, 5, 0,228, 63,254,248,227,142,209,163, 71, 95, -125,248,225,135,219,170, 84, 42, 8, 4,130,214,225,225,225, 2, 95,100, 53,132,243,231,207, 7, 72,226, 79, 74,254,220, 62,175, -181, 0,254,172, 88,181,106,149, 52, 37, 37, 69,211, 88, 57,127, 22, 87,118,212,144,119,110, 88,237, 5,175,250, 37, 67,167,211, -193, 96, 48, 56, 45,144,204,204, 76, 87, 75,136,175,181,117,211,182, 92, 46,199,238,221,187, 41, 33,228,166,227,254,224,199, 31, -127, 84,191,248,226,139,200,206,206,198,228,201,147,155,164,253,118,238,220, 73,246,236,217, 67, 41,165,200,201,201, 81,231,228, -228,248,164,160,156, 62,125, 26, 51,103,206,100, 1, 48, 98,177,152,137,137,137, 65,122,122,250,122, 0,235,163,163,163, 39,164, -164,164,108,231, 35,231, 86, 20, 3,226,148,128,204,204, 76,202,165, 1,230,254, 87, 40, 20, 52, 41, 41,201,151,123, 13,213,233, -116,155, 36, 18, 73, 11, 0,120,250,233,167, 81, 91, 91,139,140,140, 12, 4, 7, 7, 59,203,102, 11, 4, 2, 84, 86, 86,182, 0, -144, 14,224, 31,158, 4,114,228, 94, 84, 84,116,211,190,166, 64, 82, 82,146,204,113,159, 50,127, 21,129,231,159,127,222,249,121, -249,242,229,220, 71,166,222,126,222, 10, 1,231, 53,121,245,213, 87, 17, 26, 26,138,236,236,108,140, 30, 61,218, 47,242,175,143, -145, 35, 71, 2,246, 44,141,255,124,252,241,199,209,163, 71,143,182, 59,118,236, 64,121,121, 57, 87,114,215,236,229, 93,104,234, -238, 39,157, 48, 97,130,122,219,182,109,238,188, 55,210, 49, 99,198,168, 9, 33,216,179,103, 79,192,221,123,139,201, 63,117,225, -251, 0,128,204,165, 47,185, 85, 2,254, 16, 5, 32, 51, 51,211,221,131,166, 13,237,247,231, 55, 14, 29, 58,164, 6, 32,107,172, - 18, 48, 99,198,140,191,205,124,182,193, 96,184,201,234,247,135,104, 56, 98,153, 60,121, 50, 18, 18, 18, 8, 0,100,103,103, 55, -201, 53,174, 91,183, 78,234,176,232, 72, 89, 89,153, 52, 43, 43, 75, 93, 86, 86, 38,245,213, 98,119,135,177, 99,199,146,177, 99, -199, 98,221,186,117,210,156,156, 28,245,186,117,235,124,146,171,211,233,172, 17, 17, 17,226, 77,155, 54,193,225, 13,168,213,233, -116, 76,122,122,250, 54,157, 78, 55, 46, 34, 34, 98,247,237,124,190, 28,233,187,246,101,133, 66, 65, 57, 37,141, 39,238, 41, 44, - 44,236,213,191,127,127,204,154, 53, 11,149,149,149, 40, 47, 47,135, 72, 36,130, 80, 40,132, 80, 40,132, 72, 36, 66,112,112, 48, -180, 90, 45, 84, 42,213,116,185, 92,254,172, 55,161, 69, 69, 69,117,148, 67, 78, 1,224, 60, 1,177,177,177,190, 92,163, 59,235, - 95,150,149,149,165,110,140,231,201, 5,214, 6,198, 74,222,222,128,243,231,207, 35, 39, 39, 7, 19, 38, 76, 64,151, 46, 93,208, -170, 85, 43,228,228,228,224,229,151, 95,118,122,223, 4, 2,129,207, 23, 54,114,228, 72, 44, 90,180, 8, 75,150, 44,105,159,146, -146, 50,245,177,199, 30, 67, 66, 66, 2, 0, 64, 32, 16,204,108,217,178,229, 22,165, 82,105,241, 84, 12,104,221,186,117,188,188, - 0,165,165,165,152, 54,109, 26, 63, 3, 37, 42, 10,169,169,169,234,162,162, 34,168, 84, 42,174,253,165,169,169,169,106, 78,129, - 14,224,214,130, 35,127,238, 51,167, 4,252,225, 30,128,134,230,177,253, 9, 16,188,213, 74,192,253,247,223,223,104, 79,128, 47, -247,229,203,111, 60,250,204, 78,108,250,100,124,147,180, 21,247, 2, 54, 84,169,234,224,193,131,141, 86, 12,154,226,249,254,248, -227,143,106,206,234,159, 62,125,186,230,199, 31,127, 68,155, 54,109,212,104,162,196,233,156,220,156,156, 28,228,228,228,120,117, - 55,235,245,250,251, 55,109,218,180, 13, 0,210,211,211,197,209,209,209, 72, 73, 73,225, 14, 75,126,251,205, 94, 47, 43, 61, 61, -125, 87,116,116,244,195, 41, 41, 41, 94,235,147, 39, 38, 38,214,137,137,185,239,190,251,234,120, 6,248,184,253,221, 40,221,212, - 93,255,226,158,139,235,116,128, 39,236,216,177, 99, 73, 76, 76, 12, 0,224,204,153, 51,160,148,226,212,169, 83,206,186, 15, 66, -161, 16,132, 16,216,108, 54, 24, 12, 6,124,251,237,183,144,203,229, 94,171, 46,185,146,127, 82, 82,146, 91,229,197,117,138,192, - 31, 37, 64, 46,151, 19,133, 66, 65, 27,235, 13,104,138,113,210, 98,177, 96,240,224,193,208,104, 52, 24, 50,100, 8,244,122,189, -115,106, 71,163,209, 96,252,248,241,176,114, 37,200,125,179,252,177,100,201,146, 14, 41, 41, 41, 23,191,248,226, 11,231,177, 14, - 29, 58, 96,217,178,101,255,229, 75,216, 77, 12,205,225,195,135, 17, 27, 27,139,232,232,104, 12, 30, 60,152, 30, 57,114, 68,198, -145,127, 81, 81, 17, 52, 26, 13,159, 24,149,161, 0,158, 1,240, 79,165, 82,105,243,112,222, 4, 0, 81, 0,190, 85, 42,149,215, - 2,212,255, 7,118,108, 62,248, 35,131, 0,155, 66, 9,232,218,181,107,163, 60, 1,220, 32,187,118,237, 90,183,199,183,111,223, -142,181,107,215,250,101,153,228,157,235,131,184,110, 39,252,118,251,115,112,157,243, 87,169, 84,144,203,229, 78,183,255,193,131, - 7,209,169, 83,167, 38, 81,250, 26, 99,125,113,214,255,245,235,215,157,117,230,165, 82,169,172, 41,189, 0, 28, 70,143, 30, 45, -203,201,201, 81,123, 59,111,211,166, 77,219,184,185,127,189, 94,143,165, 75,151,162,166,166, 6, 34,145, 8, 65, 65, 65, 56,119, -238, 28,222,121,231, 29,232,116, 58,164,167,167,127,167,211,233,198, 68, 68, 68,168,189,144,108, 29,178,247, 22, 19,208, 20,138, -231,225,195,135,235,156,223, 80,144, 88,100,100,228,112,147,201, 4,171,213,138,131, 7, 15, 66, 32, 16,192,108, 54,195,104, 52, -130,101, 89,231,123,108,177, 88, 96, 50,153,184,119,218,107,152,120, 67, 46,255,133, 11, 23, 58,189, 0,209,209,209, 40, 43, 43, -107,180, 34,202,173, 10,240, 33,118, 68, 11, 32,210,221, 1,151,233, 0,159,144,158,158,142, 23, 95,124, 17,131, 6, 13,114,122, - 64,184,244,217,131, 6, 13,194,169, 83,167,208,166, 77, 27,159,100,238,219,183, 15, 35, 71,142,236,146,146,146,114,158, 35,127, -199,248, 25,181, 97,195,134, 75,245, 3,122,249, 42, 20, 13,253,150,143,222, 39,114,248,240, 97,105,106,106,170,122,200,144, 33, - 24, 50,100,136, 26, 0, 78,157, 58,133,156,156, 28,190,207,225, 23, 0,193, 0,214, 43, 20,138,105,238,148, 0,133, 66,241, 12, -128,143, 29,155,139, 20, 10, 69, 47,165,210,123,137,250,191, 50,184,106,128,153, 75, 95,186,105, 10,224, 47, 27, 3,112, 39, 42, - 1, 51,102,204,160,139, 22, 45,186,201, 21,232, 15,249, 63,250, 76,211,206,211,233,245,250,155,130,252, 56,171, 95, 36, 18,225, -202,149, 43,183,149,252, 93,173,127, 87,203,109,218,180,105, 26,141, 70,211,228, 94, 0, 95, 60, 39, 51,103,206, 52, 0, 8, 9, - 13, 13,197,107,175,189, 6,145, 72,228, 60,158,156,156, 12, 0,136,136,136,192,196,137, 19,177,127,255,254,189, 19, 39, 78,252, - 67,174,211,181,189, 93,231,255,221, 33, 54, 54,182, 78,165,198,134,214, 17,155,205,102,104,181, 90,212,214,214, 34, 44, 44, 12, - 65, 65, 65,176, 90,173,160,148,194,102,179,193,108, 54,195, 98,177,192,102,179,185, 42,244,215, 61, 93,103, 81, 81, 81, 29,235, -190,254,116, 64,253, 0,193,198, 66, 46,151,107,124,140, 69,145, 52,116,160,129,216, 0,175,120,231,157,119, 48, 97,194, 4,116, -237,218, 21, 33, 33, 33,144, 74,165,208,106,181, 8, 13, 13,133, 78,167,195,234,213,171,193, 48,190,197, 23,142, 28, 57,178, 99, - 74, 74,202,249,121,243,230, 97,243,230,205,120,232,161,135, 0,160,221,190,125,251,174,250,211, 78, 14,133, 2,220,152,197,141, - 85,190,146,191,171, 39, 96,195,134, 13,178,169, 83,167,170, 1, 96,195,134, 13,178,202,202, 74,141, 15,253,217,172, 80, 40,102, - 0, 88,235, 65, 9, 72,112,249,220, 25, 64,127,216,151,164, 6,224, 66,252, 13,225, 47,153, 9,112,216,176, 97,178,166, 8, 8, -244,215, 74,119, 29,144,151, 44, 89,210,104,242,231, 48,120,208, 64,236,217,171,198,186,189, 33, 78,165, 32,239, 92,159, 70,221, - 99,108,108, 44,138,138,138,144,157,157,141, 78,157, 58, 97,205,154, 53,126, 88, 93, 84,202,125, 74, 75, 75,107, 18,242,231,172, -255,178,178, 50, 89,253, 99,163, 70, 43, 88,140, 99, 0, 0, 32, 0, 73, 68, 65, 84,141,146,101,103,103, 59,207,105, 10,228,228, -228,168,249,122,159,116, 58,221,239,176,207, 11,179, 27, 54,108,192,234,213,171, 1, 0,235,215,175,135, 78,167,227, 78,179,158, - 58,117, 10,173, 91,183,190, 45,239,128,107,180,191, 59,229,140,111,153,230,162,162,162,131, 54,155, 13, 58,157, 14,215,175, 95, -119, 6,142, 26, 12, 6,212,212,212,160,170,170, 10,149,149,149, 48, 26,141, 48,153, 76,176,217,108, 0,144,235, 73,102,125,114, -119, 23, 72, 90,127, 85, 0, 95,168, 84, 42,105,253,123, 86,169, 84,190,246,147,144,166,126, 30,107,214,172,129, 84, 42, 69, 72, - 72, 8, 78,156, 56, 1,141, 70,131,208,208, 80,188,254,250,235,216,191,127, 63, 94,126,249,101,159, 20,128,145, 35, 71,182, 75, - 73, 73,185, 48,109,218, 52,124,243,205, 55, 28,249,119, 0,112,213,147, 37,207, 71, 9, 88,178,100, 73, 83,144, 63, 0, 72, 57, -242, 7,128,169, 83,167,170, 71,143, 30, 77,125, 28, 67,205, 0,184,117,138,235, 21, 10, 69,253, 64,137, 51, 46,159, 75, 0, 28, - 13,208,190,203, 56,176,240,253, 58,177, 0,245,241,151, 9, 2,108,106,242,119,172,119,109,180,229,198, 77, 7,204,152, 49,195, -111,242,127,244,153,157, 24, 60,232,134,235,102,211, 55,223, 98,211, 55,246,207,123,246,170,129, 49, 50, 0,190, 45, 3, 84, 40, - 20,136,141,141, 5, 96, 15, 6, 60,124,248, 48,118,239,182,199,172, 29, 61,122, 20,163, 71,143,246, 65, 26,209, 0, 55, 2,255, - 26, 27,169,191,110,221, 58,169, 59,235,191, 62,154,202, 11,192, 41, 18, 82,169, 84,230,237,220,232,232,232,113,233,233,233,187, - 38, 78,156,136, 83,167, 78,225,244,233,211,120,231,157,119,172, 0,132, 6,131, 1,233,233,233,112, 28, 19, 22, 23, 23,227,241, -199, 31,247, 42,243, 86,196, 0,112,150,116, 86, 86,150,211,139,197, 17, 35,247,220,249, 32, 38, 38,166,192, 96, 48, 12, 55,155, -205,184,118,237, 26,130,130,130, 32, 20, 10,157, 30, 0,189, 94, 15,131,193, 0,147,201,132,202,202, 74,110, 62,255,162, 39,153, - 28,185,115,211, 0,177,177,177,168,239,173,112, 23, 23,192,135,252,185, 28, 0,245,247, 53,166,127,112, 86,191, 27,139,223,202, -119, 12, 45, 44, 44,196,169, 83,167, 96, 48, 24, 16, 31, 31, 15,131,193,128,172,172, 44, 76,157, 58, 21,155, 55,111,134, 64, 32, -224,173, 0,196,196,196,116,228,200, 63, 63, 63, 31,111,188,241, 6, 0,116,158, 49, 99,198,229,181,107,215,146,125,251,246, 53, -106, 12,229, 60, 1,141, 33,255,216,216, 88,202,245,179, 35, 71,142,160,160,160, 64,150,154,154,170,238,217,179, 39, 68, 34, 17, -117, 9, 12,244,219, 19,160, 80, 40,230, 2,152, 0, 96, 50,128, 54,176,199, 0,252,173,221,255,192,141, 85, 0,238,130, 0,111, -203, 42,128, 63, 42, 8,240, 78, 35,255,250, 74, 64, 99, 44,127, 79,219,123,246,170,253,121, 65,111,152, 59, 33, 33,232,221,187, -119,157,227,135, 14, 29,242, 73,222,228,201,147,157, 10, 64,118,118, 54,178,179,179,235,172, 10,240,229,254,215,172, 89,163, 6, -128, 29, 59,118,184, 37,207,233,211,167,107,214,172, 89, 3,128,223, 18,166,134,146,254,112,138, 6,165, 20,163, 71,143,150, 77, -155, 54,205,107,223, 73, 73, 73,217,173,213,106,199, 30, 56,112, 96, 79, 76, 76, 12, 78,159, 62, 13,157, 78, 39,140,136,136, 64, - 74, 74, 10,180, 90,109,241,129, 3, 7,186,196,196,196, 96,230,204,153, 94,239,215, 93, 30, 0,127, 99, 0,234,191, 91, 74,165, -146,200,229,114,168, 84, 42, 90,127, 90,134,239,243,136,139,139,123, 69,163,209, 60,103,179,217, 80, 85, 85, 5,139,197,226, 84, - 86,106,107,107, 65, 41,173, 19, 24, 40,151,203, 31,115, 16, 35,111,200,229,114,200,229,242, 58,203, 2,125,157, 2,112, 37,122, -185, 92,174,169, 63,182,184, 42, 5, 77, 8,222,227, 39,183,212,239,133, 23, 94,128, 70,163,129, 76, 38, 67, 97, 97, 33,154, 53, -107,134,146,146, 18,222, 10,192,161, 67,135, 72, 74, 74,202,133,199, 31,127, 28,251,246,237,195,235,175,191, 14, 0, 81, 51,102, -204,184,212, 20,228,239,170, 4, 52,198,242,231,198,151,162,162, 34, 20, 20, 20, 16,135, 33, 40, 75, 77, 77, 85, 71, 71, 71, 67, - 42,149, 82, 62,129,128,245,148,128,105, 0,214, 59,148,128,131, 0, 20, 0,164, 74,165,242, 10, 2,104,186, 14,220,212,217,248, -220, 5,252, 44, 93,186,180,193,253,183,147,252,103,204,152,113, 75, 82,134, 54, 70,230,133,139,222,251,119,112,176,111, 94, 75, - 79,243,195,254, 64, 46,151,203, 18, 18, 18, 52,123,246,236,161, 27, 55,110,172,163, 8,212, 39, 37,190, 50,211,210,210, 26,212, -108,184,164, 36,190, 36, 6,106, 72,225,148,201,100,188,200,159, 67,100,100,164,115, 94,255,196,137, 19,255, 72, 79, 79,255, 47, -231, 17, 40, 46, 46,238,242,234,171,175,202, 8, 33,188,228,221,138, 60, 0,245,219,217,221,252,183, 15, 74,169,126,244,232,209, -139,183,111,223,254,166,213,106, 69, 69, 69,133, 51, 6, 0, 0,174, 93,187,134,138,138, 10, 80, 74, 57,171,221,167,201,118,110, -254,191,254,178,191,250,113, 2,124,201,223,245, 57,223,105, 75,121, 57, 37,224,165,151, 94, 66, 78, 78, 14, 38, 78,156,136,247, -222,123, 15, 11, 22, 44,128, 80, 40,132, 68, 34,241,246, 92, 9,165,148,157, 53,107, 22,254,251,223,255, 98,213,170, 85, 0,208, -105,223,190,125,151, 28, 22,187, 95,157,201,101,218,170,201, 80, 90, 90, 10, 55,121, 0, 52,153,153,153,178, 49, 99,198,168,253, - 89,242,232,176,250,167, 1,216, 10, 96, 46,128,184, 0,249, 55, 12,119, 65,128,188, 20, 0, 95,146,114,248, 75,216, 77,141,166, - 32,255, 59,113,208,152, 59,119,174,236,228,201,147, 77, 42,211, 97, 13,169,155, 82, 38, 71,120,220,218,122, 0,206,100, 64, 44, -203, 98,211,166, 77,188,149,128, 23, 95,124,145,187,206,155, 98, 0, 24,134, 1,203,178,248,215,191,254,165,230, 75,158,158,228, - 53,118, 37, 65, 74, 74,202,255,180, 90,237,181, 3, 7, 14,236,224,107,245,223,106,111, 91,253,246,117,231, 98,247, 69, 9, 32, -132,188, 53, 97,194,132,236,181,107,215, 30, 23,139,197,224, 86, 5,176, 44,139,240,240,112,232,116, 58, 46,133,109, 8, 0, 27, - 95,131,192, 53,248,239,240,225,195,144,203,229,117,198, 19,111,227, 80, 81, 81, 17, 45, 42, 42,146,213,119,241, 55,114,201, 31, -128, 6,221,253,214,229,203,151, 75, 0,152, 97,143,159,226,254,124, 82, 2, 92, 19,255, 60,245,212, 83,206,207, 85, 85, 85, 94, - 95,179,184,184, 56,210,183,111, 95,250,213, 87, 95, 61,188,126,253,250,239, 57,178, 93,191,126, 61,124,141,250,231,112,233,210, - 37,103, 74,226, 38,130,102,219,182,109, 13,245, 41,205,222,189,123,125,170, 85,225,225,240,101,119,217, 74,255,238, 53, 73,184, - 85, 0,238,136,159,215, 42,128,166, 38,245,134,228,221, 41,202,195,157,220,113,250,244,233,163,233,211,167, 79,147,202,116, 12, -142,183,252, 94, 93,221,255,245, 95,234,134,150,157, 57,174,143,207,181, 17, 31,238,247,150,222,107,100,100,228,206,198, 68,250, - 55,101, 12,128,187, 62,236,201,219,227, 67,159, 63, 49, 99,198,140,102,187,118,237,122,183,164,164,228, 57,163,209, 8,155,205, -134,129, 3, 7, 98,200,144, 33,233,114,185,124, 33, 31,242, 7,128,188,188, 60,231,103,215, 88,147,188,188,188,155,182, 61, 33, - 58, 58,154, 56,188, 4, 50, 0,106, 78,153,112,153, 10,240,249,153, 76,153, 50,165,161, 67, 66,151,241, 82,124, 59,198, 21,165, - 82,201, 30, 59,118, 12, 31,127,252, 49, 1,192, 43, 41,207,179,207,122,206,201, 52,116,232, 80, 76,154, 52,137,247, 53,120,147, - 23,192,157,167, 4, 52, 68,254,110, 21,128,166, 38,193, 64,133,184, 0,220,245, 1,127,203, 87,254, 29,218,230, 14,254, 13,253, -184,113,227,230,194,238,126,245, 11, 7, 14, 28, 32,211,167, 79,191, 37, 10,173,191,153, 3,255, 72,101,177,177,232,215,175, 95, -147, 22,227,105,106,121,127, 7,163,236,207,164, 4,120,181,162, 6, 14, 28, 24, 24,136, 3, 8, 32,128, 0, 2, 8,224,111, 6, - 38,208, 4, 1, 4, 16, 64, 0, 1, 4, 16, 80, 0, 2, 8, 32,128, 0, 2, 8, 32,128,128, 2, 16, 64, 0, 1, 4, 16,192,159, - 16, 86, 0,108,160, 25, 2,240, 4, 97,160, 9, 2, 8, 32,128, 0, 2, 99,123, 0,127,243, 78, 50,103,206, 28,191, 35, 46,221, - 69,117,123,146,231,109,253,177,175,242,154,250,250, 2,242, 2,242,254,238,242,126,126,165,216,239,129,101,208,187, 93,112,171, -229, 29,126,217,127,121,177,239,221, 44, 47, 45, 45,141, 0, 0, 33, 68,106,177, 88,112,238,220, 57,181,217,108,134, 80, 40,196, -197,139, 23,241, 88, 88, 87,236, 44, 40,128,241,238, 78,136,139,139,147, 9, 4, 2, 80, 74, 53, 0,144,145,145,113,203,159, 7, -119,125,174, 32,132,244, 1,208,230,248,241,227,219, 58,116,232,192,104,181, 90, 73,135, 14, 29,222, 9, 14, 14, 94, 9,224,146, - 99, 57, 41,147,145,145, 97,243, 32,175,185,195, 91, 96, 32,132, 80, 0,184,112,236,127,159, 43, 70,150,164,172, 43,136, 57, 39, -108, 51, 46,174, 89,243, 22, 53, 0, 40,165, 84, 8, 32, 34, 35, 35,227, 66,224,125,187,179,229,221, 82, 45,145,111,182, 45, 95, -179,191,249,147, 50,183, 98,245, 55, 82, 97,100,152,250,236,233, 51,178,187,130,154, 33,244,217, 25,154, 59, 73,203,106, 40, 31, -121, 96,137,203,237,199,230,205,155,165,219,183,111, 87,167,191, 98,223,254,110,223, 72,204,152, 49,131,215,115,217,151,123, 80, -202, 16,162, 62,117,242, 36,116, 58, 29,186,116,233,130,102,205,155, 35, 49, 97, 28,239,231,186,123,247,238, 58, 47,110,118,118, -182,199, 90, 10,217,217,217,126,247, 27,174, 80, 83, 70, 70, 70,227,250, 93,146,214,241,129, 2, 32, 64, 86,164,255,178, 98,151, - 3,209, 79,216, 63, 23,173, 6, 14,207,111,252, 67,157,124,189,238,245,101,183,226,245, 53, 66, 8,213,235,245,178, 93,187,118, -169,139,138,138,144, 36,106,137,118,157, 90,163, 86,111, 68,176,193,138, 17, 11,158,196,168,137, 83,177,245,139, 12,108,217,179, - 71, 61,110,220, 56,217, 29,208,133, 79,219,108,182,246, 69, 69, 69,236,128, 1, 3,196, 49, 49, 49, 56,114,228,200, 43,181,181, -181, 19,122,244,232, 33, 39,132,104, 41,165,222,166, 2,170, 93, 55,172, 86, 43,243,107,193,207, 61, 58,206, 26,132,127, 13,237, -219, 58,111,215, 7, 27, 55, 29,149,254,210,163,223,152,247, 28,242, 46, 58, 20, 6, 54,224,105,248,155,185,137,124,205,223,239, - 75, 30,124, 95,201,223,182,110,155, 52,190,117, 71, 53,137,138, 70, 97, 77, 5,218,119,232,170,182,176, 54,156,252,100, 13,202, -186,180,150, 13,157,120, 63, 47, 69,224,176, 90, 65,123,117,231,182, 4,248,118, 23,139,125, 63, 81,164, 78, 3,122,117, 7,230, - 47,105, 28,113,115, 5, 74, 26,155,157,204,157, 50,209, 84,114, 27,131,212,212, 84,138,197, 4,228,173,134,207,161,148, 2,139, - 9,166,252,158,116,199,172,181,190, 65,254,212, 65,254,163,176,127,255,126,204,152, 49,195,235,119,239, 30,176,139,246,233, 51, - 4, 89, 89,151,113, 40,215,158,176,230,244,201, 83, 0,128,217,255,252,134,158, 58, 51, 89, 22, 42,225,247, 92, 18, 18, 18,216, -221,187,119, 51,217,217,217,216,187,119,175,199, 66, 76,254,164, 80,245,244,222,166, 41, 20, 52,195, 15,133,130, 75, 23,222,232, - 84,198,209, 79,212, 45,182,211, 20, 10,128, 75, 59, 57,170, 19,242,194,217,179,103,161,217,184, 81,253,150,124, 10, 6,206,120, - 10,226,182, 17,128,208,145,236,143,165, 0, 43, 2,107,162,184,255,137, 84,148,124,244, 62, 14, 30, 60,168, 30, 62,124,184,140, -243, 2,220, 38,216, 24,134,105,211,170, 85, 43,104, 52, 26,225,128, 1, 3, 48,116,232, 80,230,202,149, 43,131,126,253,245,215, - 99,119,223,125,247, 96, 66,200, 21, 7, 89, 51, 60,219,174,217,216, 49, 9,209,239, 45,219,204, 44, 76, 62,218, 34, 46,113,142, - 44,110,152,106,228,130,143, 47, 62, 16,115,207,204, 88, 66, 72, 53,236, 49, 6, 76, 67,253,204, 53,177,149,183,126,212,104,133, - 52,128, 58,168,159, 0,168, 62,252, 42, 6,228, 58,128, 12,156,217, 31,115, 70, 60,195,128,103,229,190,250, 74,128, 66,161,160, -177,177,177,200,204,204,164,174,101, 75,125, 34,214,156,195,210,233,131,226,213, 98, 27, 11, 27, 40,130, 43, 66,112,229,218, 53, - 92,169,174, 68,183,160,102, 48, 21, 94, 82, 31,218,178, 93, 54,140,135, 18,208,171, 59,112,242, 44, 3, 74, 37,176,145, 32, 60, -156, 96,193,164,113, 70,220,136,161,105,124,170,132,198,146, 52, 71,252, 11, 23, 46, 68, 65, 65, 1, 0, 96,219, 73, 17,106, 45, - 22,181,226,159, 67,124, 82, 4,124, 81,226, 28, 41, 94, 61, 63,151,197,246,195,177,177,177, 13,231,111, 95,236,223, 59,190,245, -179,203,210, 45,191,190,225, 84,120, 38,244, 95, 44,123,240,153, 14,141, 30,112, 55,111,222, 44,221,182,109,155,154, 97, 24,188, -240, 46,156,213,207,248,212,193,136,136,248, 81, 26, 55, 44, 13,192, 22,140, 28,249, 81,157, 99,211,167, 3,247,223, 15,220,143, -108,245,242,143,192, 75, 9,224,200, 95,163,177,159, 58,117,234, 84,103, 97, 37, 95, 8,204,147,229,207,165,100,118,189,191,180, - 52,255,200,191,201, 16,187, 12, 0,176, 98,197,138, 27, 10,192,224,116,224,200, 11,183,229,114,246,238,221,139,149,147, 82,209, -109, 76, 2, 32, 48,129,136, 24, 16, 33, 3, 34, 16,129, 82, 2, 86,111, 5,181,217, 64,205, 54, 60,249,196, 83,120,234,245,185, - 56,219,182,173,186,123,247,238,183,211, 19, 64, 10, 10, 10,226, 59,117,234, 36, 46, 42, 42, 66, 78, 78, 14, 78,158, 60,137,132, -132, 4,196,199,199,183, 95,181,106,213,219, 83,166, 76,121,210, 7, 5, 64,176,127,207,215, 95, 62, 50,208,208,246,112,181, 0, -211, 23,215,224,222, 65, 31,226,153,121, 83,133, 31, 44,172,232,182,240,131,181,211,163, 7, 77, 87,162,129, 52,200,174,132,238, - 58,166,167,165,165, 81,119,251,155,186, 32, 92, 0,183,192, 3,224,250,144,214,237, 88, 91,209,253,174,238,225,138,183,158,100, -231,140,120,198,151,106, 78, 36, 51, 51,147,114,105, 73,185,255, 21, 10, 5, 77, 74, 74,242,205,170,222,113, 80, 58, 62,166,175, - 90, 92,107, 69,240, 7, 47,194,106, 48, 67,242,194, 18,132,137, 37,168, 21, 25,161,175, 53, 34, 24, 4,166, 11,101,234,202,202, - 74, 89, 88, 88,152,199, 65,248,228, 89, 32,115, 61, 11,192,224,248, 3, 70,222,195, 96,210, 56, 2,215, 64,218,212,105, 64,230, -122, 63, 60,166, 73, 73, 50,199,125,250,101,173,115,228,207, 17, 63, 0, 40,247, 91, 96, 52,235, 1, 0, 99, 23,238, 70,214,210, - 4, 53, 0,222,242,207,190,127, 22, 34, 82,120,163, 35,144, 82,144, 86,189, 92,182,203,208,250,159,252, 82,132,146,183,236,228, -239,169,198, 60, 81,100, 81,251, 57,252,172,255, 35,219, 44,210,204,205,207,170, 41, 40,222,155,247, 29,134, 73, 99,176,238,179, -125,248,207,174, 52,245, 54, 5,197,156,127,188, 33, 27, 56,178,189, 95,138, 64, 77,177,130,142, 25, 0,100,125,117, 28,148, 82, - 52,111,115,183,147,252, 87,174, 92,233,241,250,244,181, 42,105,106, 82,123, 53,240, 41,128,239,112,232, 16, 48,108,216,141,227, -111,191,125,227,243,243,207,101,171, 51,254,211, 83,198,176,157, 60, 94, 39, 71,254,163, 71,143, 6,203,178,248,228,147, 79,154, -236, 5, 87, 40, 20, 78,242,175,171, 20, 40,104, 70,134,231,119,142,153,162,171,163,254, 18,199, 63,108,146,155,243,136,227, 68, - 98,255, 48, 96,192,205,115,236,204, 84,157,211, 43, 15, 0, 44,155,140,121,243,230, 57,143,207,155, 55, 15, 43, 86,172, 0,211, - 99,214,141, 95,117,156,239, 78,158,112,170,251,235,179, 90,221,156,199,227,250,106,107,107,209,174, 75, 87,128, 53,131, 9, 2, -136, 80, 0,107,117, 37,106,139,206,225,218,197, 82,116, 28, 46, 5, 17,135,131, 88,204,128,128,193,210, 57, 11,144,144,249, 6, -230,207,159,223,164,131,178,183, 84,217, 46,100, 75, 40,165,225, 70,163,113,120,100,100, 36, 78,157, 58, 5,150,101,113,238,220, - 57,172, 94,189, 26,189,123,247, 70, 84, 84,212, 76, 0, 79,214, 35,107,182, 33,242,166,148,182,234,194, 28,146,182,239,156, 40, -174,200, 57,138, 74, 93, 16,254,187,213,138,237,121,255,195,115, 73,193, 66,161,129,141, 5,166, 55, 88, 7,225, 86, 20,183, 10, -192, 55, 52,212,119,220,121, 6,132,124,137,159, 82, 10,217, 43,163,145,153,163, 12, 79,133, 2,191,124,117, 20, 24,225,124,173, -120,129, 35,125,131, 97, 45, 0,130,218,218, 85,136,140, 84, 33, 43, 43, 11,190,164,241, 28, 26,212, 66,221,166,214, 6,201,226, -167, 96,187,174,133,245,210,117, 8,197, 34,132, 16, 1, 66,137, 0,161, 2, 33, 34, 69, 18,232,170, 43,112,121,239, 65,117,216, -164,251, 60, 14,116,238, 72,125,223, 79,172, 67, 1, 0,150, 45, 34,160, 4,176,135,199,248,222,193, 29,164, 44,203,202,202, 82, -103,101,101,249, 53,133,224, 74,254, 16, 10, 80,116,217, 62,248,149, 92,173, 69,231,182, 18,244, 72,222,130,172,213, 19,213,124, -221,235, 34, 82, 8, 33, 41,133,128, 92,135,141,182, 66, 80, 27,130,208,105,151,192,178, 90,212,214,102,193, 86,240, 47,223, 60, -185, 60, 42,183,249, 82,226, 85,185,249, 25,117,124,228,171,248,228,187, 89,104,198,116, 6, 0, 60,245,108, 79, 12, 24, 26,141, -181,159,230, 96,229,255,222, 84, 43, 71,250,231, 58, 36, 4, 80, 60,127,204, 57,232,221,123,239,189,216,183,111,159, 87,242, 7, -128, 25,211, 68,106, 96, 47,128, 99,168,184,218, 12, 61, 58, 3,159,127, 94, 3,181, 26,232,209, 3,136,142,182,139,168,184,218, -204,254, 50,246,255, 93,253,219,175,157,136, 39,242,223,187,119, 47, 88,150,117,146,244,134, 13, 27, 26, 77, 32,174,219,245,201, - 31, 0,188,145, 63, 0,100, 40,149,132, 2, 82, 2,104, 82, 83, 83, 27,236,248,172,203,160,175,204,204,148, 17, 2,172,252,108, -229, 77, 49, 47, 43, 51,148,174,254, 21, 41,165, 84,253,225,135, 31, 58,119,124,248,225,135, 88,177, 98, 5, 50, 50, 50,234, 86, -145, 35,144,186,147,151, 97, 79, 97, 43,163,148,106,158,124,242,201, 6,175,207,234,226, 69,201,252,252,115, 25, 33, 64,198,202, - 12,181, 59,242, 18, 54,111, 14,136, 4,176, 25, 42,240,251,246, 61, 88,187, 49, 27,159, 93, 58, 7, 0,200,127,179, 5,122,140, -186, 31,166,146, 11, 56,254,235, 97, 28, 61,119, 26,149, 87,174,224,216,177, 99, 77, 86, 88,107,245,234,213, 82,126,125,152,132, - 81, 74,123, 21, 20, 20,124,240,218,107,175,245,253,224,131, 15,196,102,179, 25, 2,129, 0,205,155, 55,135, 94,175, 71,126,126, - 62,162,163,163,185,186, 5,158,172,255, 80, 66, 8, 75, 41,141,172,184,120,224,167, 55,191, 44,137,252, 98, 94, 7,104,245, 98, -136,133, 12, 58, 70, 72,112,229,186, 25,138,127, 91, 49, 96, 72,108,104,103, 47,158,132,180,180, 52,202, 41, 2,174,125,177,161, -207, 1,220,122,112,228, 95, 95, 57, 96,188, 13, 34, 92,189,239, 58,110,206,196, 25, 62, 95, 64,102,102, 38,181,147,255, 58, 39, -249, 75,126, 58, 15,195,206,187,234, 28,247,106,185, 42,215, 73,195,180,213, 96,197, 66,152, 15, 31,135,233,247, 34,212,238,218, - 7, 24, 77, 16, 83,138, 16, 8, 32, 4,129,137,181, 66,107,170,197,103,187,183,122,149,185,108,145,221,186,119,133,125,155, 51, - 87, 40, 78,157,161,152,191,196,255, 62, 43,151,203, 53,174,110, 47,149, 74,197,235, 69, 87,169, 84,206,218,218, 28, 30, 91,113, - 17,123, 14,235, 80,114,181,214,169, 4, 20, 94, 52, 2,242,141, 80,169, 84,188,220,145, 66, 98,175, 28, 38,170, 62,138,208,208, - 51, 8,146, 84,131,101,181,176, 88, 14, 67, 32,136,134, 89, 95,126,219, 58,235,158,111,143, 73, 1, 82,135,252, 47,159,162, 24, - 60, 81,128,103,223, 73,192,189, 9,125, 1, 80,199,121,190, 97,221,186,117,244,133,119, 9,154,181,238, 15, 10, 32,113,210, 28, -236,223,191,159,215,119, 89,230, 2,109,211,230, 55, 39,249, 87,151,219, 75, 48, 15, 24, 96, 39,127,174, 16,160,253, 88, 48,170, -203,131, 17, 25,114,217,163,204,201,147, 39, 67, 38,147, 97,204,152, 49,152, 58,117, 42, 4, 2,193, 77,127,174,251,249,194,221, -123,235,151,178,228, 66,196,132, 16,231, 95, 67,251, 8,160, 1,133,166, 1, 89, 55,222,175,212, 84,181, 59,203,121,222,188,121, - 72, 77, 77,173, 75,168, 13,200,251, 78,169,196,177, 99,199,212,132, 16, 41,128, 58,109,230,244,103,215,219,231,233,250,196,148, -130, 9, 9,130,229, 74, 49,148,175,190,138,213,250, 10,232, 70,199, 57,143,127,241,191,213,120, 99,193,108,196,204,127, 12,111, - 29,221,139,141,186,115, 72,120,240, 65, 68, 71, 71,251, 60, 5,176,122,245,106,169, 66,161,160,171, 86,173,170,211,135,243,242, -242,212,158,166,161, 8, 33, 34, 66,200,144,163, 71,143,150,228,228,228,104, 94,120,225,133,184, 79, 62,249, 68, 82, 83, 83,227, - 44,211, 92, 91, 91,139,102,205,154, 21, 78,153, 50,165,231,136, 17, 35, 58,123, 81, 36, 24, 66, 72,151,163,185,155,202, 78,239, -156,127,126,254,203,233,237,183, 44,238,128,223, 75,133,168,172, 17,128, 37, 64,121,141, 25,180,101,247,218,231, 95, 89,210,247, -129,135,255,225,117, 58, 33, 35, 35,131,112, 99,157, 82,169,244,250, 57,128,219, 67,254,110, 61, 0,174,196,207,103,156,241,197, - 18,185,225,106, 91,229,214, 59, 80, 39,206,160, 1, 55, 70,223, 86,109,213, 90,106,129,184, 92, 11,201,119,123, 65,132, 12, 80, -107, 6,173,214,131, 88,173, 16, 1,176, 81, 22,181, 54, 43,170,173,102,128,245, 62,135,202, 5,249, 45, 91,212,240, 48,104, 15, - 18,108,252,128,170, 84, 42, 9,231,210,231, 99,173,223,100,253, 3,248,250,153,246,117,182,135,188, 84, 4, 17,189, 14, 11,105, -133,172,172,172,189,124,189, 0,146, 26, 53, 34,223,250, 31,174,189,144,134,235,218, 96,116,176, 28,135,205, 86, 4, 0, 40,254, -165,221,109,235,176, 27,119,124,172,158, 61, 78, 89,135,252, 57,196, 69,188,138,225,125, 39, 35, 62,242, 56, 54,238,120, 71, 61, -118, 18,255, 65,100,237,218,181,244,199, 31,127, 68,121,249, 88,180,108,185, 7,205, 90,245, 3,165, 20, 12,195,240, 10, 68, 42, - 41, 1,138,138,142,113, 19, 9,128,164, 6, 90, 61, 48,116,168,125, 79, 97, 33,240,233,167, 64,117, 21,160,175, 1,106,244, 64, -104, 68, 21,175,107,107,104,174,255,236,217,179, 0,128,119,223,125, 23, 0, 16, 19, 19,211,100,110,102,215, 62,201,231, 59,115, -231,206,133,171,197, 94,159,184,125,128, 20,184, 49,247,239, 10,206, 11,224, 56, 71,227, 73,200,172,168, 24,156, 62,126, 2,165, - 17, 17,106,134, 97,240,220,115,207,225,163,143, 62,242,251,250, 70,154,194, 65,217, 26,204,126,119, 17,250, 79,158, 12,229,187, -239,130, 97,110,240,156,178,240,216, 13, 15,225,190,125,216,189,123, 55,206,157, 59,231,115, 16,224,234,213,171,165,185,185,185, -106, 0,200,207,207, 87, 51, 12, 35, 75, 78, 78,214,172, 90,181, 74, 74, 41, 69,124,124,188,204,104, 52,170, 27, 80,236, 44,121, -121,121,253,103,204,152,209,162, 91,183,110,216,190,125,187,161,178,178, 82,104, 52, 26,237,222, 14,199,252,199,248,241,227, 99, - 8, 33,193,148, 82,163, 27, 49,140,139, 60,166,232,212, 47, 43,222,248, 87, 74,179,150, 61,178,240,115,214, 19,248,237, 2, 65, -201, 85, 33, 64, 25,152,204, 22,104,105,203,210,167,103, 61, 21, 71, 8, 41,165, 77,160, 85,242,137,179, 9,224,143, 65,131, 83, - 0, 57, 57, 57, 55,237,171, 40,213,249, 76,118,174, 30, 0,251, 20,128,189,255, 72,126, 58,143,160, 99,165,176,133,219,173,168, -250,115,200, 13,173,107, 60,113,177, 4,134,160, 96, 68, 91,173,232, 24,220, 12, 33, 34, 49,136,197, 2,176, 20, 86,155, 13,213, - 54, 51, 12, 54, 43, 76,212, 6, 27, 40,168, 15,157,109,254,146, 27, 74,128, 61, 46,224, 6,233, 47, 91, 36, 64,250, 34,130, 23, -150, 88, 27,221,232,114,185, 92,195,149, 46,229,131,133, 89,246,118, 95,154, 20,225, 36,124,167, 43,159, 94,135, 8,128,144,234, -240,213,236, 8,235, 99, 42,126,113, 29,162,171, 63,193, 6,187,155,250, 3, 97, 24, 30,187, 90,140,130,127,119, 68,104,187,222, -168, 44, 45,197,149,243,151,110,107,199, 28, 48, 52, 26,122, 71,119, 51, 4,159, 64,136,177, 15,190,121,211,226, 60, 62, 66,222, - 23,185, 27,125,179,252, 39,141,250, 17,223,125, 39, 71,120,174, 10,203, 23, 1,207, 47,161, 24, 53,106, 20,239,101,127, 93, 59, -118, 34,221,187,215,213, 2,183,110,181, 7,254,173, 91, 7,244,232, 65,177, 98, 5,193, 91,111,213,216, 21, 4, 0, 61,122, 70, -224,133,231,249, 93, 35,103,165, 78,158, 60, 25, 27, 54,108,168, 99,201, 38, 38, 38, 54, 72,110,254, 42,162, 62,122,240,100, 43, - 86,172, 80, 55,164, 0, 44, 91,182, 12,153,153,153,188, 44,225, 39,159,124, 82,205, 69,254,187,195,243,207, 63,143,229,203,151, -171, 51, 51, 51, 61, 94,227,143, 39, 74,240,202, 91, 11, 48,107,241,191,240,178,217,140, 15, 63,252,176,193, 54, 90,182,108, 25, - 84, 42, 21, 8, 33,210,134, 8,123, 84,159,206, 88,245,197,167,136,157, 62, 29,111,190,249,166, 71,165, 97,222,188,121, 88,182, -108, 25, 62,255,252,115,141,175,109,159,155,155,171,230,130,229, 20, 10, 5,205,203,203, 83, 39, 39, 39,147, 67,135, 14,169, 9, - 33, 72, 78, 78,214,172, 92,185,178,193,239, 27, 12,134,240,173, 91,183, 98,236,216,177, 40, 44, 44, 12,209,235,245,176, 88, 44, - 96, 24, 6,102,179, 25, 73, 73, 73,196, 65,238, 70, 62,142, 45,147,201, 36, 62,188,105, 58, 70, 61,242, 22,118,230,156,197,185, -203, 2, 84,233, 25, 8,132, 64,169, 62, 24,207,189,180, 40, 30,192, 69,190,220,207,197,157, 0,252,166, 3, 2,184, 61,214, 63, -220,185,113, 56,215,140, 84, 42,133, 84, 42,197,175,191,254,234,252, 43,250,169, 24,149,198, 74,180, 28,234,251,186, 95,142,220, - 67, 66,102, 64,242,211,121,136,138,203, 65, 9,129,120, 86,121,157,227, 94,137, 75, 44,128,141, 2, 23,245, 21, 40,169,212,226, - 90,149, 14,149,181,181,208,153,141,184,102, 50,226,114,173, 1,165,181, 53,208, 90, 76,208,177, 22,152, 89,239,217, 48, 71,222, -227,102,192,115,137, 11,152, 61,181, 25, 40,196,160,190,149, 1,119,186,240,235,119,118,190,238,127,167,229,121,181, 22,123, 14, -235,234, 16, 63, 71,254, 65,108, 49,130,216, 98,188, 49, 94,136,146,146, 18, 51, 95,153,155,206,177,104,157,158,225,220, 62,167, -183,225,226,217, 82,156, 58,112, 28, 87,206, 87,220,246,142,187,238, 51,187, 2, 90, 85, 70, 17, 98,236, 3,233, 44, 33, 30, 89, - 44,114,254,165,111,156, 14, 2,194,123, 64,122,232,222, 28, 60, 49, 95,142,136,188, 61, 32,132,224,251, 3,246, 71,192,151,252, - 57,196,244,234, 89, 79,177, 0, 62,249, 4, 56,115,198,238, 9,120,243, 77,234,116,191, 83, 74, 17, 17, 17,225,125, 4,118,244, - 81,155,205, 6,155,205,134,119,223,125, 23,103,207,158,197,233,211,167,113,250,244,105,168, 84, 42, 44, 88,176, 0, 37, 37, 37, -183,243,145,104, 26,178,164,231,206,157,203, 89,117,188,200,144, 16,226,214,250,231,224,233,152, 43,246, 5, 85,128, 48,205,240, -159, 87,150,160,217, 86, 21, 82, 83, 83,225, 90,106, 88,209,163, 31,230,198, 14, 71, 72, 72, 8, 70,141, 26,133,215, 94,123, 13, - 42,149, 74,173,211,233,220,190,127, 95,148,158,198,229,190,125, 16, 21, 21, 37, 99, 89,182, 65,111, 7,231,169,240,215,243,226, - 26, 41, 31, 31, 31, 47,227,136, 18, 0,226,226,226,100, 94,218,110,204,168, 81,163, 90,148,148,148, 96,223,190,125,184,235,174, -187, 32, 20, 10,157,202, 98, 84, 84, 20,223,233, 8,214, 33,143,116,239, 53,104, 97,230,174,112,252,182,125, 49, 70,198,247, 70, -168,132, 65,104,136, 13,193, 65, 38,220,247,208, 20, 22,128,182,190,174,234, 77,185,228,238,143,207,116, 64, 0,183, 15,140,167, -135,168, 84, 42,155,207,157, 59, 23,115,231,206, 5, 0,243,219,105,111,195, 82,102, 69,112,176,196,175,100, 36, 73, 73,246,240, -225,144,241,103, 64, 5, 12, 94,251,198,224,180,254,249, 34, 36, 42, 74,102,109, 22, 2, 29,181,225,132, 94,135, 99,149,229, 56, - 94,117, 29,199,171,180, 56,161,215,226,140, 65,135,114, 83, 45,106,172, 86, 92, 50,232,157,191,233, 9,147,198, 17, 44, 91, 36, -192,178, 69, 2, 80, 8, 64, 9,131,212,105, 4, 79, 78, 19, 99,214,212,214,232,222,189, 45, 88,136, 0,248,118,203,156,171, 63, - 41, 41, 73, 86,127,159, 15,109, 38, 43,188,104, 87,228, 11,222,183, 7,209,237,124, 49,204,238,190,161, 58, 8,168, 30, 38,198, - 30,209,172,213,106, 67,146,146,146,124, 42,138, 30, 27, 27, 11,149, 74,133,117, 53,122, 24,205, 12,158, 88,255, 31,148, 73,130, - 97, 52,223,190, 50, 17, 19, 7,188, 33,203,213, 46,193,186,255,222, 48,241,191,121,211,130,184,136, 87,111, 40,148, 15,124, 42, -203, 80,102,240,202, 45,177,252, 85, 32,121,254, 88,132,231,169, 32,251,247,104, 48, 19, 0,141, 70,227, 87, 31,238,210,165,110, -244,248,152, 49, 64,120, 56, 16, 29, 13, 12, 27,208, 28, 18,177, 0, 2,230,134, 88, 73,112,176,215, 1,153, 97, 24,231, 92,255, -217,179,103, 17, 19, 19, 83,231,239,173,183,222,194, 91,111,189,133, 75,151,248,123,101,220,205,215,187, 34, 45,205,119, 11, 44, - 51, 51, 83,182,124,249,114,183,132,205,215,250,119,113, 61,223, 20,167,192,109,179, 44,191, 20,246,102, 66,192, 26, 76, 16,181, -235, 2,197, 59,239, 32, 57, 52, 28,225,154, 92,231,241, 89,255, 72,198, 27, 31,252, 7,133,203,190,198,235,253,199, 96, 74, 68, - 55,236,222,188, 25, 69, 69, 69,110,223,191,135,211, 20,232,219,175,159,140, 11,106,228, 20, 50,215,233, 25,119,251, 60, 88, 95, - 52, 45, 45,141,114,129,125,220,124,191, 43,201, 39, 39, 39,107,226,226,226,100,156,235, 63, 57, 57, 89,227,165,221,114, 68, 34, -209, 93, 15, 63,252,240,217,202,202, 74,232,116, 58, 4, 7, 7,163,117,235,214, 8, 15, 15, 71,120,120,184,183,198, 99,235,201, -179, 5, 5, 5, 25, 30, 77,251, 72,182,250,167, 33, 56,127,161, 10,109,195, 4,136,239, 73,112,119, 55,138,208, 22, 45, 42, 0, -216, 60,240, 70,160,222,192,159,212,250, 7,188, 47, 3,172, 81, 42,149, 65, 0, 66, 21, 10,133, 83, 11,236, 56,186,131, 95,154, -175, 82,169, 36,114,185, 28, 42,149,138,138,103,101,213,113, 69,242,205, 3,208,242,193,177,154,242,172,237, 48, 88, 77,168,210, - 27,112,214, 98,129,136,181, 59,234, 43, 45,181, 96, 41, 5, 5,176,253,234, 57,232,173, 22, 0,224, 49, 48, 17,204, 95, 82,183, -143,219,167, 2, 88,216, 96,194,239,103,170,177,106, 67,149, 79,247,235, 74,244,114,185, 92, 83,223, 11,224,170, 20,120,130, 92, - 46,215,100, 41,166, 64, 52,246, 51, 0,209, 40, 47,191, 17,156, 39,102, 47,195,204,180,199,211,253, 79,227,242,101,251, 64,172, - 84, 42,247,240,145,155,246, 77,102, 29,197, 43, 43, 43, 11,220,164,196,250,163, 7,125, 90,149,209,212,120,224,169,246,154, 45, - 10,138, 3,170,227, 0,128,225,125,237,153,241,254, 53,111, 49, 14, 30,239,139, 15, 54, 78,135,114,235, 83,106,229, 68,126, 4, -254,196,124, 57, 34, 35, 85,174,134, 44,180, 90, 57, 40,205,114,184, 42, 41,178,178,146,120,201,154,252,200,163,100,247,206, 93, - 20,176,187,254,101, 50,130,235, 23,194,160,215, 73, 96,172, 18, 99,253, 26,130,185,115, 41,138,203,170, 49, 44, 62, 14,211,167, - 78,227,101, 21,219,108, 54,231,124,191, 74,101,191, 86, 87,194, 47, 43, 43, 67, 89, 89,153,207,238,125,133, 66, 65, 25,134,185, -137, 84, 51, 50,148,196,143, 36, 64, 26, 74,105,157, 88, 0, 23,143, 0,111, 87,184,171,107,191,126,244,190, 55,183,127,125, 37, -199, 90, 93, 13, 81,171, 72, 8, 66,154,161,239,163,147,241,214,184, 4,188,194, 45,219, 27, 52, 24, 54, 99, 45, 68, 45,219,162, -127,156, 20, 93, 59,118,195, 71,191,231,162, 95,191,126,178,159,126,250,233, 38, 37, 32, 77,161, 0, 64,212, 0,240, 84, 90,154, -115,233,160,181, 30,217, 11,133, 2,128,222, 88,168, 72, 0, 12,112, 51,200, 14, 28, 56,144, 80, 74,157, 46,254,252,252,124,167, -139,223,245, 60,199,182, 87,242,119, 24,236,175,134,135,135,247,141,139,139,235,126,242,228, 73, 28, 57,114, 4, 54,155, 13,161, -161,161, 48, 24, 12,101,145,145,145,231,125, 49,250, 8, 33, 76,219,182,109,119, 63,244,208, 67,109,243,246,231, 99, 69,214,110, -180, 32, 98,244,108,107,194,153,235,161,184,183,167,229, 28, 0, 11,167,160, 57, 20, 74,155,167,103,226, 58,214, 5,166, 0,238, -108,240,153, 47, 54, 3, 48,187, 18,245,197,156, 75,192,116,223,201,223,149,108,220, 13, 90,124,149,128, 42,173, 78,102, 9,145, -168, 43, 25, 22, 87,106,107, 0,139, 5, 54, 74, 65, 0,252, 94, 83,129, 82, 67, 21, 40,165, 92, 18, 27, 30, 3, 19, 69,234, 52, -130,204,245, 55,250,228,201,179, 64,175,238, 86, 8,160,111, 20,249,187,118,118,127, 93, 94, 73, 73, 73,178,172,172,167,212, 64, - 1,180, 90,173,185,164,164, 68,184, 52, 1,204,194,221,163, 48,175,223, 65,167, 21,198, 87,169,112,231,117,169,191,205,145, 16, - 95,107, 14,139, 9,134,100, 22, 81,192,253,114, 63,103, 38, 64, 21, 40,159, 32,197,180,137,159,201,148, 91,158, 86,231,110,164, -136,143, 60,142, 17,242,190,216,191,251, 56,242,116,239,128,128, 64, 49,241, 83,222,247, 26, 25,169, 2, 33, 4,147, 38, 77,194, -231,159, 87,129, 51,138,237,255, 83, 71, 27,103,213, 25,144, 60, 76,193, 98,244, 24,153, 44,103,175, 90, 61,102, 12, 96,190,210, - 9, 23, 42,130,192, 58,102, 91,219,235,219,226,197,212,106,236,206,235,137,230, 29,123,242,186, 70,142,248, 47, 94,188, 8, 0, -184,114,229,138,211, 51,112,245,234, 85,231,192,234, 15,148, 74, 37,225, 18, 1,213,159,195,205, 80, 42, 9,159,124, 0,174,248, -252,243,207,235,196, 2, 44, 95,190,220,103,235,191, 62, 97,248, 11,137, 68,130, 43,197,231,209,173,123, 15,176, 86, 19,136,213, - 6, 97,243, 22,104, 62,120, 8,154, 13,186, 7,172,222, 10,155,193, 4,106,181, 1, 54, 22, 11, 87,126,128,169,211,167, 66, 34, -145,184,149,103, 93, 31,193,235,119,221,157, 23,251,158,251,115,227,227,227,101,121,121,121,106,110, 12, 24, 49, 98,132,219,182, -226, 65,254, 32,132,176, 0,118,244,236,217,115,208,199, 31,127,108,190,118,237, 90,109, 66, 66,194, 67, 5, 5, 5,175, 27, 12, -134,242, 86,173, 90, 41,250,244,233,163,245,161,237, 69, 0, 58,199, 13, 27,214, 58,109, 86, 26,206, 93, 60,167,125,124, 86,218, -200, 67,187,215,164, 95,174,214, 14, 31, 50, 58,129,109,219, 49,230, 17, 55, 94, 3,214,211, 88,224,202, 21, 13, 37,255, 9, 36, - 2,250,243, 40, 0, 13, 90, 23,254,144, 63, 71, 54, 92, 78, 0,127,148,128,110,138, 25, 26, 0,164, 84,185,154, 34, 88, 2, 29, -181,194,108,181,130,165, 44, 90,134,133,225,162,190,146, 95, 6, 59, 7,220, 45,239,187, 17, 3,224, 91, 38, 54,119, 46,254,198, -166,235,117,124,119,226,144, 33, 67,182, 44, 92,184, 80, 28, 25, 25,201, 94,190,124, 25,243,250, 93,174, 67,254,190,252,134,187, -246,247, 27,142, 44,127,245,147, 60,185, 59,135, 47, 6, 61, 32,208,100, 60,144, 65, 54,127,114, 73,186,237,232,155,234,220,141, - 0, 1,193,196, 1,111,200, 30,120,138,127, 2, 32,174, 47,217, 9,190,202, 49, 72, 1,238,120,103,117,186,221,121, 18,218, 57, -131, 0, 13, 23,215,152, 62,117,154,102,250,212,105,164, 92,247,177,212, 86, 93,173, 38, 2,192, 80, 27, 12, 82,109,133,144, 17, -194,192, 72,100,227,166,204,134,144, 18,175,215,153,144,144, 64,238,186,235, 46,122,171,222, 63,187,181,159, 65,210,210,210,168, -107, 68,187,171, 39,192, 71,113, 26,206,242,119, 81, 40, 52,183, 99,240, 26, 51,102, 12,158,222,152,137,183,170, 43, 48,112,244, -189, 96,218, 70,216,175,201, 66,237,169,123, 33, 2, 17, 8, 65,196, 2,124,158,177, 12, 45,198, 14, 65,247,238,221,255,208,212, -189,156,117,159,155,155,171, 30, 54,108,152,108,230,204,153,141,250,237,179,103,207,202,247,236,217, 83, 44, 16, 8, 54,143, 28, - 57,242,109,134, 97,174,197,197,197,229, 56, 45, 25, 23,143, 18, 33, 4,238,158,185,139, 39, 64,117,228,200,145,161, 95,173, 94, -195,136, 5, 65, 23, 38, 63, 54,121, 0,195, 48,186,123,239,159, 61, 1, 64,152,131,248,171, 1, 80,171,213,234,148, 87, 79,105, - 11,148,148,191, 3,193,199,253,239,151, 2,208, 20, 10,131, 39,242,241,101,128,147, 10,122,251,182, 0, 0, 32, 0, 73, 68, 65, - 84, 41,146,137,106,183, 74,202,158, 42, 84,235, 77,102, 88,109, 54,116, 31, 58, 24, 49,214, 97, 62,145, 97, 83, 6,163,112, 73, -127, 0,168, 57, 79,135,203, 84, 0,105,132,220,173,114,185, 92,168, 82,169,230, 47, 93,186,244,223, 46,202,197, 24,165, 82,233, - 83, 34, 18,135,167,160,201,146,151, 76,249, 61,201,209,142, 13,223,223, 20,149,202, 47, 77,255,193,103, 58,104, 30, 68,227,159, -143,157,220, 9,158,152, 63,198,153,167,156, 27,199, 86,167,239, 65,104,231, 12, 18,218, 57,201, 39,153,225, 45,158,213, 28, 40, - 6, 97,153, 11, 82,163,193, 94, 7, 32, 84, 34,215,132, 69,193,167, 21,163, 46,253, 79,228,208, 56,155,124, 94,149, 83, 2,154, - 66,150, 35, 22, 64,205,125,110,172, 60,127, 87,150,117,239,222, 29,237,158,123, 78,182, 98,215, 46,117,209,219,223, 33, 73,212, - 18,225,142,226, 61, 70,131, 21,115, 23,188, 12, 65, 72, 36,182,175, 81,226,215, 86, 4,227, 26,145,183,223,102,179,194,215, 24, -160,250, 74, 0, 31, 43,223, 75, 59,145,211,167, 79, 95,163,148,166,247,234,213,235,203,242,242,114,189, 80, 40,132,213,106,165, - 45, 91,182,116,122, 84,244,122, 61,196, 98,177,211,139,228, 65,222,168,252,252,124,176, 86,130,225, 35, 6,188,113,241,226, 69, -157, 86,171, 69,100,100, 36,219,177, 99, 71, 29,247,108, 42, 43, 43, 33,145, 72, 64, 8, 65, 80, 80, 16, 47,163,143, 83, 18,234, -127,174,239, 21, 13,224, 79,230, 1,184, 85, 74,129,223,196,152, 32,215, 32, 65,126, 71, 69,147, 58,148, 0,114, 11,230,209,109, -114,185,252,255,228,114,249,255, 53,197,245, 53,225,253,146,166, 56,231, 86,194,110,213, 3,142, 20,251,245,142, 37, 53, 74, 54, -195,118,210,132, 74, 58, 53,197,101, 90,110,101, 27, 52, 97,209, 21,141, 47,115,245, 94,148, 9,191,229, 80, 74, 73, 72, 72, 8, - 38, 77,154, 4, 71,249, 94,148,184,148,239, 61,176,103,183,179,124,239,216,184,177,112, 40,189, 13,254,222,231,186,247,200,147, - 17, 47,223, 76, 76, 60,171, 9,242, 80, 2, 26,141,123,238,185,199,100,181, 90,115, 0,232, 89,150,165,102,179,125,225,207,181, -107,215, 0, 0,205,154,217,151,246,114,251, 69, 34,145,199,246,123,224,129, 7, 56, 25,187, 88,150, 69,120,120, 56, 88,150,117, -174, 56,113,172, 98, 33,181,181,181, 20, 0,196, 98, 49, 8, 33,204, 31, 49,182, 7,224, 63,248,164,146, 6, 0, 50,112,224,192, -128, 38, 22, 64, 0, 1, 4,240,231,129, 21, 64, 45, 0, 73, 19, 27,113,222, 10, 6,241,174, 40, 24,192,159, 3,129,135, 25, 64, - 0, 1, 4,240,231,130, 16, 64, 51, 30,228,111,128, 61,136,187,169,248,128, 69, 96,217,223, 95,174, 35, 5, 16, 64, 0, 1, 4, -240,215, 67, 72,128, 47, 2, 8,120, 0, 2, 8, 32,128, 0, 2, 8, 32,128,128, 2, 16, 64, 0, 1, 4, 16, 64, 0,127,119,212, -113,233,204,153, 51,199,239, 8, 78,119,197,123,238,116,121,209,131,131, 16, 28,116, 5, 34,113, 5, 88,214,190, 44, 76, 32, 96, -192, 16,129,253,127,134,128, 16, 6,148, 8,237,107, 96, 97,197,150,109, 34, 80, 74, 17,201,180,132,143,215, 23, 4,160, 21,236, - 1, 60,213,176, 47,247,178,192, 49,167,246,103,108,191,128,188,128,188,128,188,128,188,128,188, 59, 83,158,207, 10,192,223, 13, - 63,238, 63,131,161, 67, 44,136, 8, 7,180, 58,130,159,127,149, 64,200, 8,113,255,120, 27,118,171, 91,131, 16, 6,132, 97, 32, -105, 14,140, 25, 90, 1, 64,136,123,227, 41,242, 11,132,118, 26,231, 1,245,193,253, 20, 0, 68,212,130, 97, 35,199, 20,159,254, -237, 39, 83, 89, 85,109,140,205, 80, 11,185, 92, 30, 14,160, 50,160,135,254,185,145,253,205,127,165, 61,186,119, 83, 95,187, 86, -219,168,132, 79,127, 34, 72, 83, 83, 83, 93,243, 0, 52,234,158, 83, 83, 83,253, 78, 7, 28, 64, 0, 1, 52,145, 7,128,195,154, -175,190,224,173, 77, 60, 49,115,150,215,151,181,169,229, 53, 37,242, 11, 68, 72, 76,176,225,215,223,130, 33, 22, 9, 33, 20, 8, - 33, 18, 81, 4, 9, 44,128,176, 57,132, 48, 98,104, 95, 43, 36,226, 32, 80, 0,237,219, 2, 15,222,207, 98,207,102,126,228,127, -230,247,211,184,171, 79,119,116,136, 10,199,197,226,147, 93,194,218,117, 67,171, 14, 54,252,240,253,247, 80,169, 84, 21,183,123, -125,188, 74,165,186, 63, 43, 43,107, 27,183,157,148,148,244,128, 92, 46,223, 22,120, 53,188,227,183, 95, 85,212, 90,123, 92, 54, -237,193,238,106,150, 45, 71,101, 7,163,250,228,177,141,168, 49,181,199,144,216,145,127, 89, 18, 75, 77, 77, 85,207,155, 55, 15, -132, 16, 94,101,123,249,128, 75, 22,211, 4,229,230, 3,104,164, 2,230, 17,148, 34,243,243,207, 27,124,222, 92,130, 31,215,108, -129, 92, 13, 1,151, 90, 2,206,231,236, 90, 25, 49,128,166, 5,151, 13,144,131,187,220, 0,119,148, 7,128,193, 31,219, 15,238, - 31,103, 1,133, 0, 66,129, 8,195,135, 17,180,105,205, 64, 40,100, 16, 36, 18,160, 87, 12,131,226, 11, 86, 12,141,101,208, 50, - 82,130, 31,246,182, 0, 0, 8,168, 17,246, 84,216, 54,175,228,255, 91, 65, 1,186,118,232,136,223,114,243,112,200,108,129,238, -186, 14,226,160,230,232, 61,104, 4, 6,140, 24, 7,245,150, 44, 0,252,114,227,223, 2,226, 31,147,149,149,181,103,225,194,133, - 40, 40, 40,224, 58, 76, 5,128,231,102,207,158,189, 53, 41, 41, 73, 46,151,203,247,252,229, 94,138,159, 85, 52, 72,168,133,144, - 49,163,182,214,134, 74,125, 48,238, 29, 53,197,167,246,223,152,253,149,180, 69,176, 22,255,152, 58, 24, 93,187, 60,168,110,209, - 34, 12, 22,171, 21,215,174, 93, 71,219,146, 11, 40, 60, 91,132,131, 7,180,116,248,136,135,252,122,174,153,153,153,212,101,112, -190,211, 6, 71, 41,112,163, 28,174,163, 58,160, 20,183, 41, 29,240, 31,248,190,208, 77,155, 54,221, 92, 79,225,182,145, 23,149, - 18, 16,208, 38,104,119, 90,242, 13,200,161,217,174, 28,239,200,146,233,168,134,228,130,217, 25,122, 12,157,250,177, 71, 69,238, -135, 31,126,112,110, 39, 38, 38, 98,199,142, 29, 30,183, 3,184,245,228,239,186,207, 85, 17,240,168, 0, 28,216,127, 8, 35,238, - 29,246,135, 93, 52,235, 67,254, 84,215, 84,146,254,102,159, 98,132, 2,232,180, 66,180,107, 35, 66,187, 54, 98,212,212,136, 32, - 17, 9, 97, 19, 6, 97,112,127,130,129,119, 11,192, 16,145, 61, 5,166, 72, 12, 17, 99, 2,145,136, 97, 53, 0, 86,232, 61,146, -255,254,189,123,208,173,125,107, 28,251,245, 24, 22,189,253, 70,157,235, 91,242,230,187,148, 17, 16, 12,142, 29,140, 31,118,236, -241,169,242, 30,203,178,210,130,130, 2,245,153, 51,103, 16, 28, 28,140,224,224, 96, 89, 98, 98,162,198,199,193, 76,150,149,149, -181,135, 35,126,151,206, 17, 14, 96,220,127,254,243,159,235,179,103,207, 86, 1, 72,144,203,229,170, 59,177,131,175, 90,181, 74, -154,146,146,194,251,190,191,222,176, 70,218, 47,166,185,186, 75,251, 90,132,181, 8, 2,195,132,192,104,180,162, 92,107, 68,142, -106, 5,149,180, 24,140, 97, 67, 71,241,234, 71, 34, 92,193,164, 7,238, 86,247,237,219, 27,151,175,232,112,248,231, 35,168,169, -209, 35, 44,172, 57,162,163,187,128, 17,136, 96,179,149,224,231, 95,246,211, 65, 3,239,253, 75, 89, 55,169,169,169,234,231,159, -127,222,185, 61,111,222, 60, 44, 95,190, 92,253,185, 7,171,208, 39, 50,186, 67, 61, 0, 14, 37,157,102,103,103,195, 93, 97,165, - 63, 18,174, 86,182, 82,153, 33,163,180,113, 74, 0,211,229, 81, 39,121,231,191,215,204,173, 25,214, 46,156, 65, 84, 36,243,167, -125,126,127, 87,184,146,189, 59,165,192,171, 7,224,192,254, 67, 0,208,104, 69, 96,255,115,133, 30,143,223,251, 81, 15,191, 7, - 11, 66,136, 95,213,246, 84,154, 54, 16, 9, 69,232,212,161, 6,213,213, 34, 28, 62,214, 9, 2,129, 0, 2, 34,128, 88,100, 69, -223, 30, 6,244,236, 33, 0, 1, 3,177, 40, 8, 98, 1, 65,236,221,102, 68, 70,176, 88,247,165,103,217,189,187,181, 69,241,217, -178,155,200, 31, 0, 22, 45,126,133,188,251,246,191,105,251,248,187, 17, 17,222,156,247,245, 26,141, 70,233,242,229,203,213,197, -197,197,117,244, 13,147,201,132,135, 30,226,111,109,102,101,101,237,117, 37,127, 55,104,149,158,158, 94,241,194, 11, 47,236,190, -221, 83, 20, 13,145,255,161, 67,135,212, 41, 41, 41,188,175, 45, 38, 58, 82, 29,213,182, 10,173, 90,134,162, 99, 84, 59,132,132, -134,160,184,184, 20, 54, 27,139,168, 14,205,113,252,247, 92,172, 62, 85, 40, 77,126,124,150,199,193,244,232,209,253,244,145,137, -189,209,185,115, 71,156,248,189, 24,135, 15,255,142,107,215,171, 65, 41, 16, 17, 17, 12,131,161, 6,131, 6,245, 69, 69, 69, 37, - 74, 15,255,140,175,254,119, 90, 58,243, 31,252, 21,149, 59, 28, 82,192, 94,124,138,195,135, 31,126,200,109,251,228, 5, 72, 77, - 77,165,174, 46, 97, 87, 11,210,213, 37,221, 20,211, 11,111,191,253, 54,237,212,169, 83,163,115,241,203,229,114, 66, 8,161, 27, - 55,110,244,152, 99,159, 67, 90, 90, 26,117,231, 33, 88,189,122,181,148, 43, 14,228, 78,137, 85, 40, 20,180,161, 84,174,174,245, - 28, 40,165, 80, 40,210,212,141,241, 66,212,151, 55,244,229, 26,252,244, 94,179, 58,196, 31,192,159,211,250,175,223,135, 26, 53, - 5,208, 88, 69,224,222,143,122, 52,168, 4,248, 67,254, 28,114,114,114, 80, 90, 90, 10, 0,136,138,138,162,190, 40, 1, 2,106, -132,144,216, 32, 22,137,240,243,177,214, 16, 8,133,104, 46,210,219,227, 0,154, 49, 40, 45,109,142,187,251,178, 32,132, 32,233, - 65, 43, 40,203, 0, 36,200,238,120, 67,117,131,114, 13, 21, 23,112, 69, 91,131, 23, 94,127,189,193,107,169,168,212, 66,119,237, -138, 67, 22,111,226,174, 79,254, 0,128,237,219,183,195,102,179, 73, 31,121,228, 17,175, 3,156, 74,165, 26, 83,191,244, 47,215, - 97, 42, 43,235,196, 35,134, 47, 94,188, 24, 42,149,106,236,157, 52, 21,192,145,191, 47,223,249,122,195, 26,233,221, 49, 38, 4, - 7,135, 67, 18, 36, 70,183,110, 93,209,169,107, 87, 84, 85,105,160,213,214, 64, 44, 22, 32, 50, 66, 2, 97,112,184,199, 92,241, - 0, 32,164,165,104,222,172, 37, 12, 70, 43,142, 29, 43,196,165, 43,149,184,124,165, 6, 70,147, 4,157,163,172,144, 4, 9, 80, -120,186, 8,119,117,239,142, 75,151,171, 96,180,182,240, 42,211, 65,116,212,219,126, 95,167, 3, 26,146,233,143, 44,206,250,159, - 55,111,222, 77,251,159,127,254,121,191, 98, 1,220,145,104,253,185,227,166,242, 42,228,230,230,170,209,200,130, 60,123,246,236, -161, 89, 89, 89, 72, 74, 74,130,187,233, 0, 62,158, 42,142,252, 1, 32, 63, 63, 95,205, 48, 76,157,107, 90,189,122,181,148,143, -209, 19, 31, 31, 47,227,228, 52,133,199,101,227,243,161,152,178, 92,239,150,248,163, 34, 25,199, 40,197,239,241, 38, 38, 38,214, -241,146,220,119,223,125,117,218, 42,224,246,191,115,224,115, 12, 64, 83,121, 4,154, 18,133,133,118,197,162,180,180,212, 39, 37, - 64, 40, 20, 66, 36, 16, 65, 36, 34, 24, 53, 2, 48,232, 77, 56,119, 86, 12,145, 80, 4,161, 77,136,184, 97, 20, 98,145, 8, 2, - 1, 3, 80, 2,173, 14,248,233,136, 16, 44,203, 2,184,214,160,220, 35, 63,159, 69, 77, 77,195, 25, 56,223, 95,188,152, 6, 5, - 73, 96, 52, 86,194,198, 90,121,223,231,145, 35, 71, 26, 86, 58, 12, 6, 94, 68, 83,223,245,239, 78, 51,220,178,101,139,235,249, -170,219,225, 5,112,231,226,119, 37,255,248,248,120,222, 85,232, 58, 70,181, 85, 51,204, 5, 88,109, 44,204, 22, 43,174, 93,215, - 66, 36,150,192,100,178,192, 98,181,193,106,101, 97,181, 81, 84,232,174,123,149, 37, 22,233, 33, 9,238,136,242,242, 74, 84, 85, - 27,160,213, 25,209,162,229, 0, 12,191,251,110,228, 31,216,129, 14,102, 43, 42,171, 42,209,179,103,119, 4,137,133,208, 87,107, -255, 42, 99,133,148, 82,234,156,251,119,197,138, 21, 43,252,138, 5,152, 55,111, 94, 29,111, 66,253, 99,124, 21, 0,123,169,103, -206,162,141,196,216,177, 99,235,244, 87,206, 64, 40, 41, 41, 81,171, 84, 42,191, 10, 83,169, 84, 42, 39,249,115,211, 1,155, 54, -109,242, 74,174,245, 61, 85,185,185,185,106, 46,240, 77,161, 80,208,188,188, 60,117,114,114,178,243,120, 94, 94,158,154, 16,207, -151, 23, 31, 31, 47,115, 45, 51,156,150,150, 70, 61,181,149,183,241, 48, 41, 41, 9,147,227, 85,216, 0, 96,234,114, 61,238,121, -185,198, 99,219, 15,157,234,185,173,234,207,241,123,139, 9, 8,224,214,123, 3, 26,242, 0,252,161,254, 29,119,150,126, 99,172, -255,122, 22, 43, 10, 11, 11,177, 98,197, 10,222,165, 38, 5, 2, 33,226,134,178, 16, 48, 66,252, 84, 32,193,169, 66, 9, 38,140, - 7, 30,184, 15,152,152, 72,208,190,173, 24, 18,113, 16, 36,226, 32, 4, 75,130, 16,213, 62, 8, 18,177, 4, 18,177,231,146,152, -175, 45,122,149, 44,125,239, 45,210,208, 64,210,189, 91, 23,132,133,135, 66,194,154, 81, 99,176,252,225,157, 98,255,254,253,123, -246,239,223, 95,135,240, 93,255, 0,160,188,188, 28, 19, 39, 78,188,109, 86,126,126,126,190,218,213, 26,226,246, 1,192,176, 97, -195,124,178,228,108, 54, 64,111,176, 64,175, 55,163,170,202,132,171, 87,117,184,116,233, 58,170,171, 77,168,169,177,160,166,198, - 12,189,222,130,202, 10,239, 43, 50, 77, 38, 43,106,107,109,176, 88,204,104,222, 92,140, 78, 81, 45, 16, 18, 26, 10, 0,136,238, -222, 21, 29, 59,180, 64, 88, 11, 9, 40,181,193, 98,101, 97, 50,233,255, 18, 3, 73,106,106,170,122,254,252,249, 30,201,156, 91, - 26,200,211, 59, 33,115, 40, 13,110,177,124,249,114,124,254,249,231, 62,151, 26,182,187,197, 21,212,245,143, 35,212,210,210, 82, -100,101,101,249, 92,138,118,207,158, 61, 52, 59, 59,219,149,252, 33,151,203,201,228,201,147, 61,126,111,206,156, 57, 32,132, 56, -173,250, 85,171, 86, 73, 1, 32, 46, 46, 78,230,170,196,186, 30,167,148, 58,143,243,184,219, 58, 86,188, 59,197,193,155, 50, 1, - 0,173, 90,181, 2,113,177, 30, 26, 43, 47,128, 59,143,252,221,109,251,229, 1,184,147, 44,255, 27, 3,188, 13, 2,129,192,231, -239,141, 24,202,162, 77,235, 32, 84, 85, 9, 17, 36,180, 34, 72, 44,128,230,144, 24, 19,100, 34,136, 69, 34, 84, 85,137,112,160, - 32, 20, 45, 36, 4, 12,195, 32, 81,110,198, 67, 19, 40, 24,134,226,157, 95,124,191, 78,149, 74, 69, 5, 33, 18,104, 69,173, 16, - 98,185,136, 51,165, 20, 99,164,163,120,127,127,208,160, 65, 56,120,240,160,219, 99, 33, 33, 33,188, 7, 75,157, 78, 55,214, 49, -240, 32, 57, 57,217,185,191,188,188,220,249, 57, 57, 57, 25,101,101,101,183,229,121,166,164,164,104,242,243,243,145,155,155,171, -102, 89, 86,198, 48, 12, 56,203,191,161,121, 83, 79, 40,185,112, 73,214,186,133, 65, 29, 36, 22,192,108, 97, 81,107,186,136, 11, - 23,203,161,213, 85, 65,171, 53,160, 92,107, 68,185,214,136,240,200,174, 94,101, 93,189, 78,113,229,234,117,244,238,221, 29, 21, - 58, 29, 68, 66, 6, 85,213, 23,161,175, 96,209,231, 46, 61,218,182,110,141,144,144, 16, 4, 5, 5,227,242,149,106, 16, 65, 4, - 95,130, 37, 46,228,216, 36,171, 0,154,122, 5, 65, 67,214, 58, 80, 39, 22,128, 47, 52, 0, 48,119,238,220,155,188, 10, 46,211, - 12, 26,127,174,115,202,148, 41,117, 44,216,172,172, 44, 39,121, 61,250,232,163, 72, 72, 72, 32,124, 19,167,184,177,252,157,168, -239,105,168,143,129, 3, 7, 18, 74,169,211,202,207,207,207, 87, 19, 66,156,165,129,147,147,147, 53,185,185,185,200,205,205, 85, - 39, 39, 39,147, 67,135, 14, 57,143,175, 92,185,178, 65,185,185,185,185,106,134, 33,178,188, 60,251, 59, 49,103,206, 28,252,242, -203,207, 50,142,194,243,242,242,212,220,253,243, 81, 38, 86,174, 92,137, 79,101, 17,152,186,194, 0,192, 62, 29,224,138,169, 43, - 12,206,246, 76,145,137, 2,204,250,103, 81,218, 23,190, 95, 87,233, 94,250, 18,126,249,229, 23,254,171, 0,110, 5,241,187,198, - 2, 52,198,250,175,107,201,215, 37,255,196,196, 68, 40, 20, 10,175, 83, 1,173, 90, 9,192, 16, 1, 90,183, 18,160, 71,119,138, - 75,151,132, 96, 4, 4, 34,161, 16, 34,161, 8,191, 29, 13, 69,100,168, 8, 2,129, 0, 35,134,217, 16, 28, 28, 4,150,165, 0, -181,249, 69,254,205,218,118,194,213, 26, 10,253, 25, 13,132, 68,128, 23, 23, 47, 34, 62, 14,108,178, 11, 23, 46,168, 47, 92,184, -112,211,253, 78,154, 52,137,215, 96,153,148,148,148, 80, 94, 94,190,155, 35,121, 0,152, 56,113, 34, 86,175, 94,237, 60,167,170, -170, 10,101,101,101,216,186,117, 43,146,146,146,198,220,142,206, 27, 23, 23, 39,203,205,205, 85,231,231,231,171,185, 96,177,184, -184, 56,191,230,112,103,254, 35,229,255,217,251,242,240,166,170,252,253,247,220,236, 93,105, 75, 41, 75,217,165,130,108, 5, 42, - 32,107, 2, 5, 20,176, 34,180,200, 38, 95,100,102, 26, 24, 87, 96, 20, 69,231,231,204,168, 40, 46,128, 35, 35,180,140,138, 11, - 21,105, 21, 44, 88, 4, 10, 9,139,136,149,138,128, 44,178,148,181,133,174,105,211, 52,123,238,249,253,145,222,152,134,180,185, - 73,195, 58,247,125,158, 60, 77,238,189,249, 52,247,220,115,206,251,217,206,231,104, 55,124,153, 9, 90,172,135,209,100,131, 78, -102, 6,133, 14,102,179, 29,122,189, 5,101, 21, 70,148, 92, 53, 96,184,170,163, 79, 89, 38,107, 75, 20,157, 47, 71,151,206, 29, -208,185,115, 60, 42, 43, 43, 16,213,194,129,110,221, 34,209, 42,182, 11,228, 10, 5,170,171, 13, 40,252,229, 20,174, 20,235,209, - 58,190,231, 29, 59,129, 80,128, 18, 2, 21,199,165,238,164,218,212,186,125, 90,159, 44,120,189,249,136, 6,171,202, 50, 51, 51, - 85, 43, 87,174,212,120, 42, 0,203,151, 47,231, 10, 12, 53, 41,143, 82, 74, 9, 33, 68,173,142,114,251, 77,244, 58, 98,206,206, -118,134, 8, 82, 83, 83,121,185,255, 27,134, 20,118,121, 37,127,190,120,224,129, 7, 84, 7, 15, 30,212,112, 94,135,161, 67,135, -170,188,157,231,146,241,124, 17, 54, 23, 91,255,225,135, 3, 26, 66, 8, 8, 33, 72, 76,236,171, 74, 76, 76,212,186, 41, 8,245, -215, 2,190,198, 11, 39,143,153,170, 3, 39, 47,109, 84,167, 6, 15,106,234,138, 19, 46,121,124, 32,228, 0,220, 57,240,169, 0, -220,142, 22, 63,135,105,211,166, 53,235,251, 12,195, 64, 36,114,190,122, 36, 48,232,215,219, 1,153, 84,238, 84, 0, 36, 18, 12, - 25, 4,200,100,128, 68, 36, 67,203,150,114,136, 68,117,112, 56, 88,176,172,255,110,123, 99,213, 53,200,227,187,227,124,254, 23, -136, 21, 51,120,252,229, 37,126, 79, 40, 10,133, 66,187,100,201, 18, 85,115,150, 1, 38, 39, 39,231,171,213,106, 60,245,212, 83, -174, 99,156,165,175,215,235, 97, 52, 26, 49,119,238, 92, 0,192,135, 31,126,136,140,140, 12,205,173,120,182,115,230,204,209,178, - 44,171,226, 44,255,129, 3, 7, 54, 43,129, 43,190,227,189, 56,116,112, 59, 90,181, 12, 65, 72,136,179,219, 91, 44, 14,232,107, -173,168,210,153,208,190,115, 79, 12, 27, 50,210,231, 51, 25, 63,126, 10,217,177,237, 19,122,176,224, 56,134, 15,237,139,142, 29, - 59,194,102, 53,163, 95, 98, 31,132, 70, 70,226, 98,209, 37, 20,151, 84,227,135, 31, 79, 66, 87, 27,137, 71, 31, 24,121,199,250, - 76,231,207, 83, 3,128, 6, 32,152,175, 86,187, 8,156,245, 32,125,134, 33, 78,109,161,158,151, 9,128,190, 94,226,141,243,212, -106, 10, 10,183, 76, 21,130,244,244,244, 6, 94,128,103,159,125, 22,132, 16,204,155,167,214,112,236, 15, 2,244,237,155,232,141, -188, 92,238,120, 95, 36,199,151,252, 61,145,154,154,138,209,163, 71,171,154,211,143, 81, 31,171, 31, 52,104,144,106,246,236,217, -218,198,206,187,197,246, 27, 5,151, 59,192, 41, 95,206, 48, 2,209,122, 42, 21,124,127,159,167,188,141, 11,194,156,141, 46,143, -115, 93,179,113,193, 37,151, 66,176,253, 72,211,115,159,183, 58, 0, 66, 14,192, 29,170, 0, 12, 25, 58,240,134,196,124,130,101, -249,187,119,164, 64, 80,165, 35,104, 19,199,184, 74,254,238,216,229,140,239,203,100,114,200,164, 50, 60,252, 16,129, 92, 38,133, - 66, 78, 80, 85, 41, 66, 65, 97, 56, 28,172, 3,237,227,253,139,235,230,231,231,211,106,163, 9,186, 67,121,232,214, 94,130,223, -138, 3,143, 11, 51, 12,163, 29, 56,112, 32, 25, 56,112, 96,192, 50,210,210,210, 84,171, 86,173,210,112,110,254,202,202,202,199, - 6, 13, 26,100,216,185,115,231,119,143, 60,242,200,216,202,202, 74,242,248,227,143,111, 79, 75, 75, 83,221,202,206, 89,239,234, - 87,185,189, 15,188,207, 57,201,157,158, 62,117, 2, 37, 69, 23,193, 48, 4, 14, 7,133, 92, 17,141,132, 30,189,240,232,164, 52, -222, 29,189,164,156, 85, 85, 85,150,104,204,102, 59,122,247,234,130,118,109, 91,226,210,229, 82,232,142,157,195,239,167, 47, 97, -215,238,163,184, 88, 76,241,231,191, 60, 29,208,224,185, 93,138,255,176, 95, 69, 5,124, 93,191,165, 60,229,157,251, 4, 43, 87, -174,116, 41, 0, 43, 87,174, 4,138,214, 93,119,173, 55,121,141,120, 5,174,155,179,154, 91,172,135, 16,210,172,190,199,145,124, - 99,228,238,235,188, 55,175,130,199,119,189,201,227,255,156, 47,126,141,156,149,179,157,115,195,168, 14, 13,200, 31, 0,210,198, -223,239,124,163,251,213,167, 2, 32,212, 1,184,125,144,185,236,197,235,194, 0,126, 41, 0,183,115,194, 71,160,197,127,220,113, -232, 23, 25,228, 82, 41, 30, 30, 79,192, 16,130,129, 73,118, 28,251, 77, 1,134, 56, 99,254,213,213, 12,218,182, 22,129, 33, 82, - 28, 57, 38,133, 92, 6, 88,109, 86, 92,188,164,240,139,252,207,157, 62,140, 65,163, 39, 66,220,114, 16,206,157, 46,128,248, 90, - 14, 94,120,254, 37,250,246, 59,111,222,146, 6,174,175, 87,175, 74, 74, 74,210, 44, 94,188, 24,189,122,245, 42,211,233,116, 72, - 74, 74, 82,233,116, 58, 60,243,204, 51,154,180,180,180,219,162,174,125,115,137,223, 83, 9, 24, 54,100, 36,214,125,254,145,178, - 77,235, 54,154,208,208, 80, 94, 86,255,117, 19,236,236, 63,105, 1,144,245, 95,100,208, 19,191,255,132, 54,113, 97,144,203, 37, - 48, 24,172, 40,190,170, 7, 17,183,199,159,255, 50, 91,200,150,226,131, 95, 22, 1, 93,159, 64,131,229,133,133, 11,155, 67,214, -205,254, 73,243,230, 69,187, 41, 18,193, 33, 52, 95,164,236, 15,105, 55,183,158,129,183, 54, 75,123, 64,230,188, 87,211, 85,231, - 75,192, 29,139,196,196, 68, 87,194, 95,230,178, 23,175, 59,231, 83, 1, 8,118, 61,254,155, 93,223,223,175,206, 15, 2,157,142, - 32,164, 53, 65, 76, 52, 65, 82,127, 27,228, 82, 17,100, 82, 27, 98,162,229,245,147, 0,193,224, 36, 7, 10,126,145, 56,189, 5, - 60, 39,153,252,252,124,218,243,222, 8, 44,122,246, 95, 48, 73,227,241, 77,126, 49,186, 38, 56, 45,247,176,159,183, 98,209,223, - 94,162,239,189,123,235,148,128,228,228,100,146,159,159,175, 92,182,108,153,198,221, 59, 16, 12,229,234,118, 70,125,177,159,102, -223,227,204, 89,106,178,255,192, 30, 90, 94, 89, 14,211, 53, 35,228,242, 24,196,119,238, 19,144, 82,113,167,193, 89, 14, 59, 72, -183, 89,180, 14,174, 21, 1, 69,159,222,242,123,243,149,220,119,183, 97,236,196,199,252,178,220,125,249, 30,133, 28,128,219, 75, - 9,104,140,252,125,122, 0,254, 23, 64,225,204,234, 39, 12, 5, 5, 69,116, 11,138, 61,251,197,144, 75, 37,144, 73,197, 72, 25, - 79, 65, 41,139,168, 24, 59,236, 14, 2,150,117,212, 79,126,190,209,167,147, 1, 19,166,164,193, 32,238,134, 86, 97,161,152,241, -104, 52,178, 54, 29,115, 41, 1, 54,199, 55,183,252,254, 57, 69, 64, 24, 50,129,123, 21,238,214,123,203,212,189, 69,210,163, 94, -188,158, 25,178,163, 3,149,135,244,168, 23,175, 63, 81,184,176, 89, 86,191,128,230, 33,245,201, 85, 65,235,195,119,187,241,112, -167, 41, 1, 62, 13,224,196,196, 68, 33,104, 35, 64,128, 0, 1, 2, 4,252,143, 65, 40,244, 44, 64,128, 0, 1, 2, 4, 8, 10, -128, 0, 1, 2, 4, 8, 16, 32, 64, 80, 0, 4, 8, 16, 32, 64,128, 0, 1,130, 2, 32, 64,128, 0, 1, 2, 4, 8,184, 59,208, - 96, 21,192,252,249,243, 3,206,224,244, 86, 91, 59,216,242,102,206,157,231,243,123,117, 85,215, 92,239, 67,163, 91,187,222,175, -255,120,205,117,215,198,170,254,236, 83,222,206, 21,127, 84,204, 27,179, 96,149,235,125,185,230,191, 8,228,247, 53,134, 64,127, - 95, 99,240,246,251, 38, 61,174,246,249,189, 67,154,239,208,169, 83, 39, 92,184,112, 1, 73,170, 9,174,227,155, 63,207,184,225, -237,247,231,171, 87,155,236, 47, 22,177, 88,185,168,184,216,181,100,113, 85, 92,156,235,250,255,182,105,115,195,251,159,167,188, -220,220, 92,101, 94, 94, 94,131, 74,137,227,199,143, 87,165,164,164,104,111,197,248, 56,124,248,112,192,242,250,245,235,119,163, -127, 31,153, 63,127, 62,110,231,249,229, 86,200,203,202,202,154,222,187,119,239,172, 99,199,142, 77,153, 49, 99,198, 55,205,149, -231,190,209,145,123, 70,254,221,218,126,130,188,198,229,249,173, 0,120,194,110,183, 43,205,102, 51,136, 72, 2, 66, 8, 28,118, - 27,164, 18, 49,100, 50,153,182,185,154,135,221,110, 87, 2,128, 88, 44,110,150,172,186,170,107, 8,141,110,237, 34,254,214,237, - 59, 1, 0,174, 93,190, 16,144,188,157, 43,158,194,152, 5,171, 92,196,245,159,220, 2, 0,192,147, 41, 3,113, 55,226,144,230, - 59, 36,169, 38,224,144,230, 59, 0,192,132,212,153, 0,128, 11, 23,110,125,251,253,187,180, 84,121, 26,208, 36, 0,170,211,128, -115, 15,245,197, 47, 0, 0, 6, 46,123,251,150,182,155, 86,171,165,121,121,121, 48,155,205, 13,142,203,229,114, 77, 68, 68, 4, -148, 74,229,109,185, 28,138, 16, 50,236,222,206,237, 62,165, 14,135,241,244,165,107, 47, 81, 74,183, 10,118, 80, 19, 74,167,197, - 50,234,240,225,195, 17, 37, 37, 37,173,163,163,163, 91, 12, 24, 48,160, 56, 60, 60,252,243, 64,229,101,101,101,141,158, 49, 99, -198,158,172,172,172, 63, 3,136,156,246,196,188,185, 0,216, 99,199,142,205, 6,176, 25, 0,235,143, 60,110,207, 19,142,248,155, - 51,222, 60,119, 73, 12,214,146,190,198,148, 18, 1,183,153, 7,192, 29,250, 90,131,178, 77,194,253,154,145,189,187, 35, 68, 38, - 1,165, 20, 14, 7,197,111,103, 46,226,252,209,125, 42,133, 76, 2,145, 72, 20, 16,121,135,201, 47, 40,123,118, 43,210,252,118, -186,139,170,206,210, 41, 96,226, 7, 0, 69,100, 12,234,170,174,185,136,191, 41,143, 0, 31, 75,117,224,204, 23,177,115,197, 83, -174,129,212,216,117, 77,173,177,244,252,159, 82,169, 20,128,179, 76, 38,203, 58,199,183,195,225,112,253,126, 70, 36,225,109, 69, - 3, 64,155, 86,206, 82,157, 86,125, 53, 44,118, 59, 0,192, 96,119,202,235, 60,246, 79,184,167,103, 63, 94,196, 15, 0,125,135, -140,198, 33,205,119, 46,226,111,236,186,155,217,126, 0,240, 84,105, 41, 5,128,113,161,161,216, 94, 87,167,225,136, 31, 0,126, -223,177,243,186,235, 18,219,180,225,245, 59,107, 66, 43,148,133, 21, 63,163,248,210, 17,116,235, 56, 24,131,229, 74,191,251,112, -110,110,238, 35,219,182,109,227,200,223, 14,192, 12, 32, 4, 0,107, 54,155,197, 10,133, 2,122,189, 94,233,205, 19,112,139,201, - 63,238,254,196,222,219,182,127,185, 38,172,174,248, 36,134,165,205,207, 34,132,204,166,148,110,190,221, 38,166,252,252,124,218, -156,250, 20,124, 54, 3,107, 10, 54,155, 77, 89, 80, 80,160, 57,126,252,184,235, 88, 69, 69, 5, 78,159, 62,141, 54,109,218,124, -166, 84, 42, 85,225,225,225,124,159, 47,147,149,149,245, 79, 0, 15, 12, 27, 55, 73,145,149,149, 21, 55,237,137,121,225, 0, 28, - 0,184,142,123,111,253,117, 35,248,222, 31, 55,222,212,106, 53,109,108,188,113,215,249, 26,111,106,181,154,238,253,177, 0, 34, -145, 24, 14,135, 29, 53,181, 6,204,152,242, 8,125,247,221,119,155, 69,216,158, 74, 69,115,159,139, 0,223,240,182,237, 47, 7, - 94,149, 0,235, 76, 86,229,232,148, 25,154,246,173, 34, 17, 34, 23,131,101, 89, 56, 88, 64, 44, 34,136,142,236,142,158,221, 58, -104,242,183,127,167,114,216,234,148,254, 42, 1, 86,171, 85,217,163,231,121, 77,223,238,231, 33, 98, 28, 26,237,161,118, 42,169, - 68,226,151,140,186,170,107, 80, 68,198, 32, 50, 34, 28, 0, 92,127,189, 93,215,186,125, 39,159,222,128,157, 43,158,194,192,153, - 47,226,255, 30,155, 12, 0,174,191,222,174,251, 79,110,129, 95,218,181, 72, 36, 66,124,124, 60, 68, 34, 17,172, 86, 43,234,234, -234,224,112, 56,160,211,233, 2,122,184, 97, 98, 17, 62, 94,185, 9,178, 72,160,244, 2,240,179,161, 24,229,215,206,226,243, 21, - 47,249,101,245,247, 29, 50, 26,241,109,157, 33,146,120, 47,228,223,169, 83, 39, 87, 56, 0, 0,174, 92,185, 18,148,246,227, 83, - 92,245,169,210, 82, 58, 46, 52, 20,175, 61,245, 36, 0,224, 53, 55,226,255,226,244,233,134,228,239, 71,181,214, 61, 23,190, 80, -118,124, 66,172,121,177,195, 44, 88,216,100,200, 88,138,147, 21,187,240,201, 59, 27, 85,169,125, 50,248,246, 65,113, 94, 94,222, -102,147,201,132,117,235,214,153,231,204,153, 35, 7, 16, 6,128, 93,183,110,157,117,206,156, 57, 98,147,201, 4,185, 92,174, 73, - 73, 73,105,214, 68,247,205, 55,223, 40,119,236,216,161,105,110, 45,123, 87,223,145, 50,255,239,131,215, 94, 80,180, 56,241, 37, - 20,191,239,198, 63, 70, 69,133, 63,179,165,252, 95,245,150,231,109, 69,254, 27, 55,110,132, 78, 55,134,102,103,167,249,125,239, - 31,127,252,177,178, 57,100, 83, 87, 87,167,204,205,205,213,212,214,214,122, 61,127,245,234, 85,228,228,228,104,122,244,232,161, - 26, 60,120,176,175,126, 67,178,178,178, 62, 31, 54,110,210,212,211,135, 15,136,227,219,182,182, 79,123, 98, 94,131,121,119,247, -119,223,160,119,239,222,221,179,178,178, 30,234,221,187,119, 46, 0,236,223,191,191, 73, 82,229, 51,222,212,106, 53, 5, 33,128, -143, 42,127,107,214,172,161,215,202, 42,112,248,183, 19,174, 99,102,179, 5,111,127,144,105, 80,207,153, 46, 16,246, 93,140,235, -146, 0,107,107,107,149,195,198, 62,170,233,222, 33, 6, 50, 9, 3,150,101,113,237,218, 53, 28, 59,114, 24, 86, 59, 11,150,165, -136,137, 12,193,216,135, 38,106, 76, 22,187,223,255, 80, 38, 41, 67,215, 14,215, 0, 17,193,125,221, 46, 67, 38, 46,245,219,242, -119, 39,255,235, 44, 60,125, 45,174, 93,190, 0, 69,100, 76,163, 94,129,166,200,203, 19,159,126,245, 13,158, 76, 25,136,129, 51, - 95,108,212,170,245, 6,169, 84, 10,145, 72,132,136,136, 8, 20, 21, 21, 65,167,211, 57, 21,169, 0,201,191, 77,171, 56,132,137, - 69,120,244,233,215,241,208,140, 33,216,250, 91, 49,174,153,208,108,242,247,196,149,146,107, 56,126,232, 7,196, 70, 69, 56,201, - 95, 44, 10, 74,251, 61, 56,229,255, 0, 0, 81, 98,137, 95,228, 15, 0,127, 95,245, 31,252,125,213,127, 92,228,191,189,174, 14, -207,143,157,232, 60, 25, 43,229,117,223,159, 94,124, 75,249,151, 69, 15,104,158,232,248, 87, 72,152, 48,132, 34, 4, 12, 68,104, - 23, 55, 20, 79,189,182, 80, 83,212,118, 5, 47, 53, 66,171,213,218, 0,224,211, 79, 63, 53, 2,144,115,219, 40,175, 91,183,142, - 5, 16,226,190,173,178, 86,171, 13, 40, 46,103, 52, 26,149,254, 28,231, 97,249, 15,187,191,127,162, 49,251,155, 77,234,126,189, - 18, 68,117, 39,118,225, 66, 89, 45,174, 86, 27,193, 82, 26, 80, 34,112,122,122, 58, 77, 75,203,166,235,215,175, 15,106, 33, 49, - 55,242, 71,116,116,126, 64, 50, 10, 10, 10, 52, 25, 25, 25,132, 16,226, 82, 6,252,252, 13,215,145,255,161, 67,135, 48, 99,198, - 12,119, 15, 1, 78,157, 58,165, 49, 26,141, 77,110,152,149,149,149,245,212,176,113,147, 38,190,177,100,129, 56, 59, 59, 27,255, -253,224, 93,113,189,199,200, 69,254,217,217,217, 88,181,106, 21,122,247,238,157,235,107,188,121,146,127, 99,227,237,161,161,245, - 94,192,240, 80,159,242,222,251, 96,181,139,252,203, 42, 42, 81, 86, 81,137,154, 90, 3, 36, 18,113,216,234,117, 95,154, 61,173, -120, 1,119, 6, 18, 19, 19,175,123, 53,169, 0, 56, 28, 14, 26,211,169, 15, 58,181,110, 1,179,205, 1, 66,128,237,219,191,199, -103,159,174,195,209, 35, 71,240,252,194,231, 32, 18, 49, 96, 29, 44, 34, 66,100,232,212,103,152,198,100, 50,241, 30, 96, 54,155, - 77,217,179,219, 69, 77, 68,152, 17, 31,127, 90, 6,134, 80, 12,236,253,187,198,102,179,249, 53, 72,189,145, 63, 71,252,166,154, -202, 6, 10, 66,141,190,214,167, 60,111,131,137, 27, 72, 5,235,223,106, 64,112,159,126,197,175,124,111,215,174, 93, 17, 19, 19, - 3,189, 94, 15,169, 84, 10,134, 97, 96, 50,153,160,211,233, 32, 18,137,184,137,153,247, 61,127,189,121, 19,158, 91,185, 3,155, - 62,120, 5,109, 90,197, 33, 36, 52, 26,151, 29,197,248,124,197, 75, 8,171,159, 52, 68, 60,229,121, 35,127,142,248,107, 74,206, -161,123,124, 43,212, 26,205,144,133,200, 0,135,195,103, 62,128,175,246,123,105,237, 86, 28,255,229, 71,244,234,114, 31,106, 28, -190,149, 70,142,252,127,223,177, 19,127, 95,245, 31,215,241,237,117,117,216, 94, 87,135, 34,245, 63,177,227,196, 81,244, 28,216, - 5,168,244,189, 53,115,214,153,101,202,249,207,140,214,196,134,246,128,137,214, 2,150, 50, 72, 45, 85,176, 56,106, 97,102, 77, - 96,165, 97,104, 55, 60, 9, 57,191, 46,245, 53,209,145, 13, 27, 54,192,108, 54, 67,173, 86,135,168,213,106,192, 25, 2,128, 90, -173, 70,253,231,122, 11,202,140, 13, 27, 54,248, 61,104, 79,157, 58,165, 92,184,112,161,230,253,247,223,167,132, 16, 13, 0,236, -219,183,143, 46, 93,186,148,190,242,202, 43, 1,109,205, 28, 46, 99,214,253,231,197, 39, 20,227,218, 89, 68, 7, 78, 93,195,214, - 11, 12, 94,220, 86,106,249,167,214, 80, 83,103,195,255, 5, 34, 83,167, 27,115, 35, 45,127, 68, 71,231, 99,230,204,153,126,239, - 70,233, 78,248,107,214,172, 33,220,118,210,124,113,224,192, 1,101,105, 41, 63,163,196,106,181,226,216,177, 99,187,155,234, 47, - 0,148,241,109, 91, 75,211,210,210, 0, 0,133,133,133,216,253,221, 55,242, 43, 37,215, 88,142,252, 1, 32, 45, 45,205, 53,222, -142, 29, 59,182,162, 57,227,237,237, 57, 19,241,219,185,203,104,221,165, 13, 80,103,228,125,239,101, 21,149,176,217,236,245,115, -181, 29, 54,155, 29,151, 47, 94,144, 55,231,153,122,122, 15, 4,111,194,237,133, 6,174, 40,139,197,130,126,221,187,107, 66, 20, - 18,176, 44,133,131, 5,126,216,183, 31,255,124,237,117,176, 20, 56,115,246, 44,142, 30,249, 21,189,122,245,133, 72, 68,112,111, -151,120, 20,253, 98,135,130,231,230,120, 82,113, 25, 18, 58,149, 0, 98,130,203, 87,109,128,152,160, 79,247,139, 40, 56, 86, 6, -138,118, 1,221,128,187,123,223,155,103,192, 84, 83,217, 96, 53,128, 47,184,187,247,189,105,218, 5,235,223,194,152, 5,171,188, -102,177,187,195,110,183, 35, 36, 36, 4, 12,195, 32, 42, 42, 10, 70,163, 17,117,117,206,109,128, 99, 99, 99, 81, 89, 89,233,215, - 6, 28,102, 29, 48, 80,161,192,243, 31,236,195,152,190,192,197,195,192,207,245,231,158,255, 96, 31,254,189, 64, 5, 7,235,240, -187,253,142, 31,250,193,245,126,244,128,238, 16,135, 51,216,174, 61,129,126,221,219, 35, 34, 76,134, 79,115,242,145,164,154,128, - 43, 94, 86, 1,248,106,191,220, 19, 20,184, 10,164,140, 38, 88,187,181, 8, 49, 81,157, 49,121, 40,225,213,126,156,187,127,123, -221, 31, 91, 39,211,127,172, 0,218,213,128,252,229, 85,208,127,190, 6, 48, 38,144,130,165, 88, 21, 23, 71,254,219, 68, 32,160, -235,148, 48, 77,199, 22, 3,160,119, 24, 96,209,157,197,231,151,178,176, 63, 69,135,251,254,172,194,216,167,195,160,136,186, 23, -114,113, 20,196, 41, 53,248,249,155,159,233,253, 73,247, 55, 54, 73,185,254, 7,195, 48,160,148, 90,235,149,104, 51,195, 48, 70, - 74,105, 52,156, 73, 92, 1, 47,175,237,222,189,187,118,236,216,177,170,202,202, 74,205,246,237,219,157,138,207,246,237,232,209, -163, 7,186,119,239, 30,208,246,204,181, 22,246,153,185,127,255,247,150,119, 38,180,102,168,185, 6,127, 89,127,218,102,183,217, - 86, 89, 28, 88, 74, 41,173, 10, 68,230,164, 73,214, 27, 78,254, 35, 70,140,208,250, 43,167,160,160,160, 65,200,132,243, 2,240, -221, 85,210,225,112,248,165, 48,156, 63,127, 30,131, 6, 13,106,172,191,200, 1,220, 7, 64, 60,106,194,228,234,162,162,162, 22, -133,102, 28,210,109, 0, 0, 32, 0, 73, 68, 65, 84,133,133,200,206,206,198,128,162, 34,166,176,176, 16, 0, 48, 96,192, 0, 60, - 56, 50, 9, 17, 97, 50,172,250,100, 83,217,140, 25, 51,150,172, 94,189,122,129,191,227,237,234,230,183, 16,222, 83,142,176,110, -207, 97,227, 91,127, 70,223, 94,173,113,239,196,215,145,145,145, 65,154,202, 18,175,209,215, 66, 46,151, 1, 0, 36, 18, 49,140, - 70,115, 80,159,173, 64,250,183, 6,126,111, 6,196,178, 44, 66,100, 82, 88,237, 20, 12, 1, 24, 2,188,250,175,215,225, 96,129, -186, 58, 3,174, 93,187,138,184,184,214,160,148,133,221, 14,200, 37, 98,136, 36,252, 92,176,118,187, 93,121, 95,215, 43,154,150, - 81,122,128, 16,167,110, 76, 0, 66, 40,250,247, 60,163,249,233,104,156,202,223, 21, 1,156,117,223, 88, 72,128,143,245,239,169, - 69, 55, 70,252,254, 88,255,128, 51, 97,168, 85,171, 86,144,201,100, 46,151, 33,151,248, 23, 25, 25, 9,137, 68,130,203,151, 47, - 67,194, 83,222, 39,249,123,240,231,137, 35,193,153, 55,167,237, 78,247, 63, 0, 40, 19,128,136,215, 53, 88,240,183, 33,136,242, -227,126,175,148, 56,147, 21, 59,180,138,134,206, 98,129, 56, 66, 4,115,185, 17, 96, 24,180,233, 24,143, 29,187,127, 14,168,253, -254,111,209, 27, 56,255,195, 46,136,175, 1,213,113, 64, 8,195, 96,112,167,206, 24, 53, 50,142,151, 28,207, 88,255, 23,143,253, - 25, 95, 91,126, 7,238, 49, 3, 63,137,129, 48, 49,240,240, 0,196, 63,204,207,120,237,218, 46, 26, 86,107, 21, 36,118, 27, 62, -191,148,133, 31,231, 68, 98,196,163,143,160,123,171, 30,170,223,118,104, 53,253,210,234, 32,177,214,193,222,157, 69,121, 41,191, -164,209,122,229,205, 60,103,206,156, 48, 0, 58, 74,169, 4, 0,230,204,153,211,236,218, 26,147, 39, 79,214,238,223,191, 95,117, -242,228, 73, 77, 72, 72, 8, 66, 66, 66, 48,115,230,204,128, 38, 81, 66, 72,235,137, 19, 39,174,253,219,223,254,198, 60,191,224, - 25,182, 23,123,150,177, 88,109,117, 86, 7,253,155, 63,114,210,211,211,169, 78, 55, 6,147, 38, 89, 49,115,230, 76, 18,232,239, -185,145,228,239,205,221,191,102,205, 26,162, 86,171,233,220,185,115,121,253, 94,131,193,208,192,237,239,142,133, 11, 23, 98,225, - 66,231,166, 69, 73, 73, 73,238,215,203, 26, 17,215, 22, 64,167,122,165, 48,228,193, 41,179,204, 93,186,116,145,103,103,103,131, - 35,255,180,180, 52,196,181,105,227, 62,222,182,194, 45, 68,192,103,188,165, 63, 60, 2, 7, 75,202, 16,222, 55, 28,197,219,207, - 1,114, 25,166, 60, 61, 27,209,241, 19,121,206,205, 14, 20, 95, 45,181, 75, 36, 98, 49,231, 1, 0,128,203, 23, 47, 52,235,185, - 54, 22, 58, 16, 20,130, 91,167, 16,120, 42, 1,140, 55, 19,135, 82, 10,150, 2, 14,214,169, 4, 16, 2,124,243,117, 14, 30,157, -156,138,150,177,173, 92, 19, 32,245, 99,175,108, 17, 83,134,158,247, 92,118,125,238,211, 43,196,229, 36,235,127, 95, 17, 68, 76, -153,223, 55,228,233,238,247,118,222, 31,235,223,211,221,239,237,188,251, 90,246,166,160,215,235, 81, 91, 91, 11,139,197, 2,150, -101, 81, 94, 94,238,114,255, 27,141, 70, 24, 12, 6,191, 66, 0,155, 62,120, 5,218,223,128,154, 11,128,205, 4,252,123,177,202, -229,254,255,229, 48,240,235,213, 31, 32,242,179,253,106, 74,206, 33, 58, 50, 20, 49,209,161,184, 55,161, 7,138,206,151,227,116, -113, 37, 58,196, 68,194, 82, 90,134,179,103,206, 54,168, 5,192,167,253,134, 40, 31,193, 48,213,116,108,218,178, 17,154,189, 27, -145,181,124, 17,166, 44, 90,138,163, 54,160,188,178,140, 87,251,185,199,250,159, 24, 50, 8, 51,239,235,136,141,155,118,227,232, -209, 11, 88,126,172, 16, 27,198,204, 6, 62, 58,128,226,226,242, 6,181, 0, 26, 67,188, 89, 6,135,181, 2, 86,107, 13, 0, 32, -174, 93,123,116,239,209, 67,165, 87, 56,115, 49, 76,172, 17,140,165, 14,138, 58, 17, 74,175, 94,243, 69,168, 78,143,140,217, 12, -179,217, 44, 7, 96, 5, 16,110, 54,155, 35, 60,151, 4, 6, 10,163,209,168,220,187,119,175,166, 71,143, 30,152, 53,107,150,170, -162,162, 2,219,183,111,231, 61,216, 8, 33,195,100, 50,153, 33, 60, 60,220, 62,102,204,152,171,139, 23, 47,110,187,100,201,146, -162,159, 15, 31, 29,191,225,184,229,148,141,133,223,251,177,222, 8,151,127, 48,201,223,211,250,231,114, 20,220,189, 0,124,100, - 72, 36,127,168,228,203,151, 47,119,189,188,125, 6, 92, 43,124, 26,123, 54,210,250, 23, 3, 64, 92, 83,114,206,171, 59,157, 27, -111,135,127, 57,124,126,198,140, 25,233,254,140,183,225,247,223,139,228,161, 9,120,227, 95,239,226,189,149,121,248,127, 95,236, -198,188, 81, 73,184,246,109, 30,106,116,122,159,100,155,145,145, 65,210, 82, 30,132,205,102, 63,108,179,217,237,238, 10, 0, 0, - 44,125,245,165,128, 9, 91, 32,250, 91, 11,111,177,127, 79,175, 64, 3, 5,128, 97, 24,212, 24,140, 16, 49, 4,118,187, 3, 44, -165,176,179,206, 36,210, 35,191, 30,198,168,209,227,156,110, 50, 74, 33, 98, 68,168, 53, 90, 97,183, 90,124,107,152, 14,135,178, -115,187,171,154,216,232, 26,151,150, 49,100, 96,152,115,216, 16, 2, 66, 40,250,245, 56,171,177, 59, 28, 74,190, 55,199, 89,247, - 77, 37, 3, 6,100,189, 54,145, 92,227, 15,162,162,162, 80, 94, 94, 14,153, 76,134,218,218, 90,196,198,198,186,146, 2,205,102, - 51,170,171,171,253, 82, 0,210,223,216,128,127, 47, 86, 33,178, 19,160,253, 13,120,102,153, 6, 97, 98, 17, 38, 63,251, 38,174, -176,215,176,126,249, 11, 16, 49,252,229,113,214,255,128, 1, 9,136,237,210, 9,173, 98, 91, 66,202, 16,216, 9, 69,121,157, 9, -186, 90,115, 64,237,247,222, 91,155, 49,169, 71,103, 68, 68,196, 32, 36,182, 45,108, 85, 58, 28,222,250, 37,170,171, 46, 5,212, -137, 63,126,235, 41, 96, 65, 50,196,118, 43, 58,213, 1,101, 34, 61,254,125,245,103, 64, 26,193, 91,198, 47, 91, 14,170, 42, 24, - 19, 46, 73,141, 72,186, 71,133,251,102,135,161, 40, 74,171,137,141, 61,172,105, 63,184, 8, 53, 76, 45, 44,212, 4,227, 23, 44, -228, 97,225,124, 44,127,247, 9,158, 91, 5, 32, 13,214,192,253,254,251,239, 1, 0, 51,103,206, 84,117,239,222, 93,251,232,163, -143,186, 44, 70, 62,228, 31, 27, 27,187,109,237,218,181,161, 25, 25, 25,162, 5, 11, 22,224,185,231,158,163, 7, 14, 28, 24, 76, - 41,221,110,180,209, 30,148,210,159,252,183,230,162, 26,117,251, 7,154, 16, 24, 76,242,247, 36,120,119,133,101,205,154, 53,164, -160,160,128,151,107,255,202,149, 43, 7,184,247, 89, 89, 89,174,151,231, 49, 14,209,209,209, 0,208,216, 36,120, 5, 64, 53, 0, -230, 74,201, 53,252,248,227,143,174,152,255,128, 1, 3, 0, 0,217,217,217,248, 42, 55, 15,186, 90,179, 17,192, 82, 56,151, 6, -242, 30,111,223,110,250, 7,198, 45,126, 26,227,199,143, 70, 75,153, 8,181,132, 98,251,233,203,248,241,183, 98,191,136,122,254, -156,233,247, 23,157, 61, 43,190,124,241, 2,184,215,210, 87, 95,106,210,146, 23,112,123, 19,191,231, 49,111,104, 16, 2,144,201, -100, 56,115,226,168,170, 83,219,104,141, 66, 34,134,195,193,130, 16, 2, 66,128,116,245,147,160,148,133,163,190, 30,128,209,108, -198,201,211, 69,144, 74,125, 59,177,237,182, 42,244,187,239,188,251, 44,138,191, 46, 56,143,175,191,232,230,210,157,147,122,157, -195,193, 35, 61, 32, 22,197,250,101,253,123, 35,126, 83, 77, 37, 0, 4,100,253,123, 27,104, 5,235,223, 2, 0,222,214, 63,224, - 92,231,223,186,117,107, 88, 44, 22,148,150,150,194,225,112,160,101,203,150,168,172,172, 68,203,150, 45,235,219,149, 63, 97,151, - 95, 59,139, 87, 94,215,160,230, 2,240,206,162,225, 48,216, 29, 88,184, 44, 27,239, 47, 78,195,162,229, 91, 33, 38, 4,126,240, - 63,106, 74,206,161, 77,203, 22,144, 64, 2, 7, 8,174,158, 63,142,139,101, 53,232, 26, 27,141,111,127, 57,128,147, 39,224,183, -245, 63,101,238, 66, 72,162, 1, 70, 4,172,203, 59,143,175, 63,124, 30,115,223,202,192,194,135,251,226,201,209, 29,253,106,191, -237,117,117,120, 47,101, 42, 80, 45, 7,136, 4,120,239, 93,164,254,188, 15, 59, 70,207, 7,121,243,105,144,131, 47,240,178,254, - 1,224,215,171, 49, 24,100,170,129, 65, 33,130, 81, 46, 71,215, 41, 18, 88,168, 9, 53,140, 4,118, 36,128, 58,140,176, 85, 92, -197, 15, 31,212, 96,230,140,174,183,100,208, 22, 22, 22,210,122, 98, 32,147, 39, 79,214, 58,125, 99, 78, 12, 31, 62,156, 12, 31, - 62,156, 15,249, 15,109,219,182,237,247,111,190,249,102,232,153, 51,103, 32,145, 72, 16, 17, 17,129,163, 71,143,218, 40,165,229, -205,249,125, 77,173,201, 15,196, 59, 16, 76,242,247,180,254,157,196,122,253,242, 65, 62,185, 0,105,105,105,103,190,250,234,171, - 33,118, 59,191, 21, 78,114,185,124,110, 19,167,107, 1,156, 7, 48,224,244,225, 3,112,143,249,255,117,238, 84,124,223,165, 11, -184,112,192,182, 46, 93, 66,102,204,152,241,137, 63,227,237,177,228, 65,136,100,163, 96,132, 4, 95,175,120, 26, 31,110,253, 21, -207, 63, 56, 12,115,150,103, 33,117,233,231,126, 89,224,238,197,132,188, 29, 19,214,239,223,157,104,224, 1, 16,137, 68,164,250, -234, 89,156,187, 92, 9,177, 68, 4,187,131,133,205,238,192, 47,191, 20,226,179,207, 62,129,213, 65, 97,115,176,144,138, 25,148, -233, 12, 40, 62,249,163, 74,161, 80,104,125, 16,161,178, 71,215,139,127, 88,255,206,169, 10, 95,127,145,224,156,227, 24, 10, 48, - 20, 12,195, 98,112,223,147, 26, 7, 15, 47,128, 55,235,223,125, 21, 64,104,116,107,191,200,223,155,245,239,158, 85, 59,102,193, - 42,191,200,203, 57, 41,234, 96, 48, 24, 32,145, 72, 92,214, 63,203,178,174,191,254, 42, 0,159,175,120, 9,191, 20,239, 65, 88, -107,103,210, 95,184, 88,132,242,107,103, 17, 33,147,160,186,234, 10, 68, 12,129,152,225, 23,126,230,172,255,246,209,225, 56, 81, -116, 30,118,171, 21, 50,177, 20, 6,131, 25,223,106, 14, 32, 73, 53,193, 47,242,231,218,239,145,167, 94,195,250,127,191, 15, 35, - 11,180,239, 26,143,223,142, 31,196,194,135,251, 6,212,126, 0,176,176,107, 18,182,156,217, 13,212,216, 1,121, 75,236, 44, 56, - 1,242,230,211, 88, 21, 23, 71,248,146, 63, 0,204,232,182, 88,251,195,206, 2,192, 90, 11, 3,169,133,142, 49,160, 70,108,131, -205,161,135,204,108,132,188,228, 60, 54, 44, 57,131, 78,137, 9,104, 34, 1,176, 1, 20,110,153,175,114,185, 28,114,185,220,235, - 57,190, 88,187,118, 45,214,174, 93,219,172,193, 28, 30, 30,254,204,217,179,103, 67, 35, 34, 34,160, 80, 40, 16, 29, 29,141,242, -242,114, 16, 66,140,193,156, 52, 56,139, 63, 63, 63,159, 2,206,132, 64,127,146, 2,131, 77,254, 31,127,252,177,146,250, 94,235, -206,107, 69, 64,104,104,104,186, 88, 44, 62,231,121,124,249,242,229, 13, 44,127, 0,232,216,177, 35,146,147,147,215,249,178,127, -174,148, 92,107,144,237,255,202,223, 23, 64, 38,150, 34, 46, 46, 14,220,234,128,250,243,161,254,140,183, 63, 43,251,224,185,119, -223, 71,109,105, 25, 98, 35, 90,225,248,137, 75,152,179, 60, 11, 25, 25, 25, 36, 16,178,230,190,231,254,125,119, 57,130, 39,224, -206,192,175,191,254,218,100, 49,160, 70, 61, 0,245,147,136,182, 80,187, 89, 69,105,138,166, 83,219, 24,132,135,200,112, 95,175, - 68,220,215,179, 47,196, 12, 96, 48, 57,112,233,106, 21, 10,180,223,169,194, 66, 67,124,254,131, 58,163, 17, 9, 29,175,194,108, -145,131,114, 70, 13, 5, 20,114, 51, 40, 5,170,170,101, 0, 1,194, 67,237,232,157,112, 1,251, 14,245, 67,120,120, 56,111,235, -223,221,226, 87, 68,198, 64, 66,109,128,253,143,249,206, 33,246,253, 27,221,173,127,119,139,159, 59,118,246,248, 97,215,181,124, -170,236,185, 43, 1, 0,208,186,181, 83, 25,169,170,170, 66, 68, 68,132,203,253,239,143, 2,192, 41, 1,192,155,152,159, 54, 18, -248,247, 62,124,248,242, 4,164, 46,122, 31, 89,111, 61, 9, 49, 33,144,202,248,173,216,225,172,255, 19,151,202,112, 79,251,150, -248,232,191, 27,208,169, 83, 39, 68,182,237,138,190,109,187,194,102,249,195,253, 47,225, 33,147,179,254, 95,159, 59, 26,207,188, -186, 14,237,187,144,102,181, 31,103,253,143,221,244, 49,118,204,156, 14, 18, 63, 24,128,179, 42, 32,224, 44, 17,204, 93,251, 76, - 92, 28, 47,226,232, 99,121,129,100,189,187, 76,217,117,114,173,166, 83,183, 94,208, 43,128,243,184,136,218, 11,229, 40, 95,234, -128, 65, 23,143, 5,179, 23,241,126, 32,171, 87,175, 38, 10,133,130,154, 76, 38,184, 89,158, 84,161, 80, 96,245,234,213,126,148, - 39, 10, 30,106,107,107,223,121,242,201, 39, 83,214,174, 93, 43,143,140,140,132, 70,163,193,202,149, 43,245, 86,171,245,193, 96, -254, 31,206,226,231,150,203,249,155, 16,152,156,156, 76,116,186, 49, 52, 24,228, 15, 0, 28,177,243, 33, 40, 30, 21, 6,173,179, -103,207, 30,188,113,227,198,163,117,117,117,109,108, 54,231, 50, 83, 79,242,191,239,190,251, 48,120,240,224,137, 60,158,179,184, -166,228, 28,222,248,199, 43,248,102,203, 54,140, 27,214, 31,187,242, 15, 58, 13,152,182, 93, 17,217,182, 43, 6, 20, 21,225,193, - 41,179, 42, 46, 85, 26,199,118,136, 9,201,225,107,253, 63,151,185, 5, 75,254, 52, 22,109, 91, 43, 93,202, 5,119,143,124, 60, - 55,129,120, 7, 4, 79,192,157,171, 20,240, 82, 0, 0, 32, 34, 60, 76,251,139,118,179,234,124,252,189,232,210,173,135, 38, 34, - 84, 1,150, 2, 38,139, 21, 69, 69, 69, 40, 47,250, 85, 21, 30, 22, 10,134, 97,124, 14, 92,133, 92,142,141,223,143, 84,113, 25, -240, 77,186, 35, 24, 6,161,161,252,173, 39,110, 9, 96,104,116,107,176, 14,155,147,252,235, 97, 35, 18,159, 37,118, 61,193, 45, -169, 25,179, 96, 85, 3,210, 10,132,252,221,149, 0,247,194, 63, 85, 85, 85,190, 31,128, 15, 37,224,115,183, 85,194,107,151,254, -245,143, 15, 54, 3,194,120,202,105, 31, 29,142,141,135,126,197,111,167,126, 71,146,106, 66, 3,210,247,135,252, 57, 60,242,212, -107,248,186,127, 40,158,122,180,123, 80,218,111, 97,215, 36, 44,202,221, 8,242,198,171,216, 22, 55, 8, 43, 13,191, 53, 56, 63, - 57,178, 5,226,229,254,237, 73, 49,163,219, 98,237,182,220, 28, 92,209,157, 67,121,229, 85,148,158, 14,131,200, 17,129,161,125, -134, 67, 53, 91,117, 75, 39,181, 96, 84,251,163,148, 30, 34,132,140, 33,132,236,124,255,253,247,229,147, 38, 77,210, 27,141,198, -177,129,196,252,155, 66, 48,150, 0,170,213, 81, 65, 33,127, 79, 43, 53, 72,168,152, 58,117,106,215,218,218,218, 55, 10, 11, 11, - 23, 20, 23, 23,163,174,174, 14, 82,169, 20,109,218,180, 65,108,108,236,164,254,253,251,127,203, 83,214, 73, 0, 3,218, 71,135, -227,129, 7, 30,192,175,103,138,209,178,115,207, 6,227,237,193, 41,179,140, 0, 62,224, 67,254, 28,254,172,236,131, 49,249, 63, - 97,230,171,159, 97,196,136, 17,136,139,139,243,170,104, 5,171, 65, 56, 37,192,159,182,110, 76, 33, 19,148,136, 91, 71,250,188, - 74, 1, 3, 64, 68, 68,132,214, 82,117, 89,249,139,246,180, 10,112,102,210, 82, 74, 33,147,201, 16, 25,193,187, 6, 54, 36, 18, -137, 54, 82, 34, 9,250,205,113,174,126,145,221, 8,216,141,174, 12,120,142,248,253, 93,139,197,185,250,207, 30, 63,140,179,199, - 15, 35, 54, 54, 22,229,229,229, 1, 17,127,100,108, 91, 88,121, 36, 71,242,197,204,215, 62,199,129,125,218,160,201,187,112,225, -130,107,183, 63,155,197,124, 29,249,251, 67,252, 28,102,247, 15, 13, 90,251, 1, 0, 89,241,130,139,248, 57,242, 63, 95, 87,167, -154, 28,217, 2, 15,243,180,250,189,225,161,206,169, 4,157,235, 63, 4,144,216,190,102,205, 26,194, 85,251, 91,189,122, 53,113, -175,252,183,110,221, 58,178,122,245,106,215,251, 53,107,214,220,244, 65, 79, 41,221, 79, 8, 25,145,147,147,179, 80,175,215,175, -160,148, 22, 4,251,127, 4, 99, 9, 96, 48,201,233, 6,193, 20, 30, 30,190, 80,169, 84, 46,108,166,156,253,199,142, 29, 27, 10, -160,115,203,206, 61,141, 54,139, 57,164,126,188,233, 1,212, 0, 56,217, 33, 38,228, 49, 56,147, 5,121, 99,204, 43,107,111, 10, -241, 55, 71,209, 18, 72,254,214, 32, 49, 49,145, 23,249,251, 52, 64,197, 98,177,214,151, 59,254,102,131,139,237,115,196,143,102, - 18, 63, 23,155,174, 41,187,130,154,178, 43,136,141,141,109,150,197, 15, 0,118, 7,235,183,247,161, 41,148, 85,213, 4,252, 91, - 60,193,197,246,131, 69,252,193,110, 63, 46,182,191,197, 96,160,238, 86,127, 63,177,164, 89,196,255,191, 4, 74,233,207, 0,166, - 11, 45,113,235, 49, 99,198,140, 12, 0,159, 93,170, 52, 26,109, 22,179,123, 60, 50,162, 67, 76, 72, 20,252,220,253,143, 35, 85, -119, 55,255, 29,164, 84, 9,184,137, 74, 0, 47, 67, 43, 49, 49, 81, 72,236, 16, 32, 64,128, 0, 1, 2,254,199,192, 8, 77, 32, - 64,128, 0, 1, 2, 4, 8, 10,128, 0, 1, 2, 4, 8, 16, 32, 64, 80, 0, 4, 8, 16, 32, 64,128, 0, 1,130, 2, 32, 64,128, - 0, 1, 2, 4, 8,184, 43,208, 96, 21,192,252,249,243, 3,206, 34,245,182,221,228,237, 46,239,240,225,195, 1,203,235,215,175, -223, 13,151, 23,236,251,109,217, 50, 49, 96,121, 21, 21,191,222,234,231, 75,234, 21, 86, 22, 94,138,175,220,137,253,239,102,201, -171, 47, 76,196,212,183, 33, 5, 64,231,207,159,207, 10,237, 39,200,187,147,228,101,102,102,138,211,211,211,237, 0,240,209, 71, - 31,209,110,221,186, 97,196,136, 17, 68,104, 63,239,242,252, 86, 0,238, 6, 52,183,200,196,212,169, 83,149, 0,220, 75,134,170, - 54,110,220,168, 21,116,197, 91,131,154,154,154,199,143, 29, 59,214, 87, 36, 18, 45,146,201,100, 48, 26,141, 47, 12, 27, 54,236, - 93, 4,161,210, 30,165,212,239,106,140,119, 34,230,207,159, 79,193,115,147, 25, 1,183, 14,185,185,185,202,148,148, 20,109,128, -223, 85,229,229,229,237, 14, 70, 65,169,122,121,143,229,229,229,109, 88,179,102, 77, 52,156,123, 26, 56,112, 11,170, 91,186,131, - 35,255,189,123,247,210,159,126,250, 9, 73, 73, 73, 24, 49, 98,132,208,113,130,229, 1,184,211,145,159,159,175,108,206,247,167, - 78,157,170,220,184,113,163,102,234,212,169,238,135, 53, 83,167, 78, 13, 88, 9,224, 20,138,236,236,108,174, 84,167, 95,178,210, -211,211,169,159,255,175,201,245,192, 59,119,126,226,175, 60,149, 78, 23,122, 43, 20, 32,242,219,111,191,189,163,215,235,255,212, -177, 99,199, 22, 21, 21, 21,168,223,110,247,237,175,191,254,250,237,208,208,208, 81, 15, 62,248,160,166, 89,255, 32, 0,242, 87, -171,231,251, 61, 9,102,100,172, 38, 55, 79, 94,211,229,112, 27,219,244,133,239,248,218,184,113,163, 6,175, 18,144,127,121, 87, -168,240, 42,193,212,147,105,126,183,235,184,113,227, 40, 0,108,223,190, 61, 40, 4,198,109, 5,172, 86, 71, 5,125,125,124,110, -110,174, 50, 47, 47, 79,227, 15,217,254,229, 47,233,148, 82,231,214,234,222,240,240,195, 19, 85,121,121,121,154,148,148, 20, 18, - 64, 63, 30,181,109,219,182, 93, 35, 71,142,196,188,121,243,104, 86, 86,214, 24,189, 94,159,239,207,111,243,162, 52, 98,218, 16, - 41,212,243,212, 85, 47,124,177,248,219,183,166,191,245, 8,119,110,237,218,204, 38,127,227,172, 89,179, 40, 0,132,134, 54,190, -181, 65, 93, 93, 29, 0, 96,206,156, 57, 1, 61,159, 83,135, 84,200,207, 60,130,228,244, 76,154,158,158, 46,212, 63,224, 1,174, - 56,144,123,141, 0,177,143, 1,239,181,110, 54,143,122,218,183, 10,205, 34, 4,119,242,223,184,113, 35,153, 58,117, 42,117,147, -235,247,253,114, 10, 5, 71, 52,245, 27,126,248,175, 80,100, 71,251,241, 95,147,125, 94, 81,247,240, 95,249,139,243,115, 95,155, -198, 8,200, 79,175, 12,169,169,169,249,170, 87,175, 94, 83, 0, 48,148, 82, 40, 20, 10,148,149,149,161,186,186, 26,145,145,145, - 40, 43, 43,219,253,253,247,223,171, 30,124,240, 65,191,148,147,252,252,124,202,109,204, 66, 8,193,148, 41, 83,144,156,156,172, - 34,132,240,150,147,155,187,217,245, 62, 37,101,146,207,207,190, 96, 58,240,212, 31,205, 61,100, 85,131,207,158,199, 20, 67,124, -111,170,196,109, 39,236,142,189,123,247, 98,233,210,165,215, 61,139, 47,190,248,130,242,108, 55,101,118,118,182, 6,175,146,122, -130, 77,187,126,226,126,149, 52,219, 66,188,141,231,150, 6,150,118, 70, 70,134,138, 82,138,245,235,215,211,253,251,247,163, 79, -159, 62, 62,191,123,160,145,154,140,155,178, 23, 33, 47, 47, 79,195,178, 44, 50, 51, 51,225,107, 91,101, 66,136,146, 82,234,234, -175,223,126,251,109, 8, 33, 4,211,167, 79, 47, 5, 16, 55, 99,198,140,157,107,214,172, 97,252,177,216,223,221,249,174,235,253, -181,237, 87, 65, 8, 65,214,179, 33, 0, 8,222,153,245,246, 35, 45, 91,182, 4, 0,124,249,105, 22,230,141,156,199, 75,230,128, - 1, 3,208,165, 75,151,160,180,123,102,102, 38,147,158,158,206,126,244,209, 71,244,167,159,126, 66,233,233, 78, 64, 69,148,192, -234,126,146,191, 39,152,166, 38,242,236,236,108,100,102,102, 82,111, 19,104, 32, 59, 67, 53,215, 66,247, 37,207,205,202, 14,216, - 40,220,184,113, 35,217,184,113, 35,225,148, 0, 0,170,230, 40, 20,132, 16,164,165,165,129, 82, 74,220,126,155,223,138, 10,153, -170,115,189,248, 28,247,133,176,173,171, 93, 47, 62,199,253, 33,127, 74, 41,184,221,217,124,237,210,230,173, 79,234,116,186,207, - 34, 35, 35,167, 0, 96,230,206,157,139,153, 51,103, 66, 42,149, 66,161, 80, 64, 46,151,131, 16, 2,145, 72,132,154,154, 26,222, -237,152,147,147,163, 84,171,213, 52, 39, 39, 7,110,207, 4, 95,127,253, 53,230,205,155,167,201,201,201, 81,222,142, 3,215,155, - 66,112, 43, 60,107,217,217,217,154,140,140, 12,242,216,169,169, 94, 45,124,181, 90, 77,167,158, 76, 83,121,243, 12,248,194,188, -121,243,232,243,207, 63,143,206,157, 59, 7,229,247,206,155, 55,143,170,213, 81,136,137,217, 21,212,118,216,188,121,243,232,252, -252,252,221,125,251,246, 37, 31,126,248,161,150, 35,255,230, 96, 83,246, 34,172, 88,177, 2, 44,203, 98,209,162, 69,224, 35,211, -157,252, 1, 96,219,182,109, 91,234, 93,225, 81,211,167, 79,183,143, 28, 57, 18,106,181,154,229,107,180,120,142,209,149, 43, 87, -226,177, 7,156,182, 97,214,179, 10, 76, 27, 34,197, 11,227,158,231,125, 79,161,161,161, 24, 49, 98, 4,210,211,211, 73,114,114, -178,215, 23,119, 13, 95,101, 47, 61, 61,157, 5,156,219,172, 3, 64, 68, 72,133,192,234,205, 36,255, 38, 21, 0,142,172, 10, 11, - 11, 93,101, 39,221,173, 39,127,137,214,101, 65, 4,121, 82,242,162, 12,168,130,217,120, 27, 55,110,212, 4, 65,134, 75,161, 72, - 75, 75, 83,113,109,120, 55,193,157,252, 1,160,184,184,216,117,238,202,149, 43,188, 21,198,154,154,154, 55,141, 70,227, 44,134, - 97,152, 25, 51,102,160,166,166, 6, 37, 37, 37,144, 72, 36, 16,139,197, 16,139,197,144, 72, 36, 80, 40, 20, 48,153, 76, 94, 75, -162,122,153,224,148, 59,119,238,212, 16, 66,144,154,154,138, 53,107,214,144,228,228,100,146,145,145, 65, 82, 83, 83,185,254,163, - 17,166,138,166,201,191,190, 45, 85,220, 36,238,254,236,211,210,210, 84,201,201,201, 90, 32,176,146,180,201,201,201,100,205,154, - 53, 36, 59, 59, 27,148,210,160, 40, 99, 47,189,244, 18,178,179,179,121,245, 17, 95,248,230,155,111,198, 28, 58,116, 40,191, 83, -167, 78, 48, 24, 12, 52, 52, 52,148,238,219,183, 15,128, 43,201, 50, 32,242, 95,190,124, 57, 8, 33, 96, 24, 6,135, 14, 29, 2, - 39,211, 15,143,196, 35,132, 16, 76,155, 54,205, 94,127,200, 58,125,250,116,189, 82,169,196,188,121,243,216,111,191,253,214,231, -189,187,135,194,174,109,191, 10, 16, 96,253, 51,127, 84, 45,206,122, 54, 4,211,135,202,176,248,193, 23,120,255, 46, 62,150, 63, -159,107,246,238,221, 75, 51, 51, 51, 93,175, 67,135, 14,193,112,105, 0, 96, 53,129,132,217,145,255,250, 73,184,159,231, 94,194, -200,109, 72,254,233,139,223,242,122, 94,220,212,128, 44, 42, 42,162,133,133,133,200,206,206, 6,247,158,115,237,248, 51,200,111, - 52,249,187, 91,213,220, 36,116,187,194, 61, 36,112,183,129, 82,138,226,226, 98, 92,187,118,205,117,204,243,179, 15,136,126,252, -241,199,241, 9, 9, 9, 16,137, 68, 56,123,246, 44, 40,165,248,253,247,223, 97,181, 90, 65, 8,129, 88, 44, 6, 33, 4, 14,135, - 3, 70,163, 17,155, 54,109, 66,114,114,211, 97,143, 93,187,118,105, 0, 32, 53, 53,245,186,126, 91,255,153,114, 68,193,167, 95, -123,186,245,125,125,230, 99,229,115,104, 44, 28,192,199,245,239,101,242,108,118,146,148, 43,230,239,166,192,113, 10, 44, 23,243, -207,119, 35,255, 64,172,117, 78, 9,227,200,104,215,174, 93,154, 64,195, 0,156,188,110,221,186, 93, 71,110,129, 96,245,234,213, - 56,121,242, 36,141,141,141, 69,187,118,237, 92,219, 62, 95,184,112, 1, 34,145, 8,255,249,207,127, 2,250, 7, 35,135, 58,183, - 47, 99, 89, 22,127,251,219,223,176,114,229, 74,236,219,183, 15,132, 16, 60,156,242, 23, 92,188,192,111, 3,199,109,219,182,109, -174,127,198,102, 56, 87,200,176, 0, 48,125,250,244,106, 0, 45,242,242,242, 64, 8,225,173, 80, 57,173,255,235,247, 49,113,134, - 3,128, 47,179, 14, 35,183, 38,247,166,121,203, 78,157, 58,133, 67,135, 14, 53, 56,230,168, 62, 15,187,141, 5, 72, 45, 90, 60, -104,195, 33,143,205,174,147,146,146, 4,230,231, 65,254, 77, 42, 0,245,110, 23,194, 89,253, 28,249,123,141,253,249, 65,214, 77, - 89,130,124,226,196,190,228,121,158,191, 85, 59, 82, 77,157, 58,213, 61,214, 76,189,157,231, 60, 3,205, 34,221,141,193,141,131, - 25, 38,206, 15,200,242,111,108,178,141,143,143,191,238,218, 38,158, 73,139,232,232,232, 94, 22,139, 5, 85, 85, 85, 56,112,224, - 0, 68, 34, 17,172, 86, 43, 76, 38, 19, 88,150,117,237, 74,105,179,217, 96,177, 88,120,133, 24,184,231,208, 88,191, 77, 78, 78, - 38, 57, 57, 57, 52, 59, 59,219,167, 50,225,180,186,110, 76, 14,128, 98,200,170,235,136,158,251, 28,136, 34, 48, 98,196,136,230, - 43, 1, 30, 49,255,252,252,124,165,139,236,255,136,249, 7,148, 35,227,161,132, 1,112,238,182,168, 86,171, 41,159,231,192,215, - 11, 80,159,251,224,119,110, 1,183,179, 99,187,118,237, 16, 17, 17, 65, 60,149,221, 94,189,122, 5,108,249, 83, 74, 97,183,219, - 93,199,134, 13, 27,134,125,251,246, 97,207, 15, 14,188,187,140, 95,140, 61, 55, 55,119, 92,125,236,255, 4,128,150, 0,220, 55, - 27, 42, 1,208, 2, 0,242,242,242, 52,125,251,246,245, 41,175, 97,236,223,139,167,160,254, 47, 95,121,193, 64,122,122, 58, 73, - 74, 74,162,154,207, 98, 97,175,254, 21,132,173, 6, 28,206,157, 86, 25,145, 29,250,125, 12, 36, 82, 49, 44,142, 22, 56,120,161, - 47, 94, 89,174,195,161, 67,135,136,183,101,213, 2,252, 84, 0, 60, 61, 1,254, 90,254, 69, 69, 69, 52,152,238,110, 95,242,234, -195, 18, 65,243, 52,100,102,102,146,244,244,244,128,190,235,249, 59, 51, 50, 50, 12,106,181, 58,172,177,243,129,194, 61,246, 31, - 12,101,192, 61,246,207, 87, 25,152, 57,115, 38, 66, 67, 67, 17, 22, 22,134,240,240,112, 68, 70, 70,178, 81, 81, 81, 76, 94, 94, - 30, 30,127,252,113,215,117,114,185, 28, 99,199,142,133, 90,173,166,141,236, 86, 21, 99,181, 90, 81, 85, 85, 5,179,217,140,200, -200, 72,200,100, 50,216,237,118, 80, 74,225,112, 56, 96,181, 90, 97,179,217,224,112, 56,252,202, 47,240, 21,178, 74, 77, 77,197, -237, 16,154,241,149, 16,232, 47, 56, 37, 32,224,254,245,175,198,219,110,234,201,180,250,188,155,192,100,123, 90,255,238,138,100, - 32,201,128,158,214,127, 83,138, 41, 95,242, 23,137, 68, 52, 34, 34, 2,112, 38,212, 17, 0,212,102,179,161,166,166, 6,173, 90, -181, 10,232,190, 57, 99, 74, 44, 22, 99,193,130, 5, 56,116,232, 16,254,136,251,243,239,211,223,127,255,253,247,195,135, 15, 7, -128,112, 56,195,185, 70, 0,216,176, 97, 67,171, 61,123,246, 68, 80, 74, 93,202, 54,159,117,226, 43,223, 95,137,105,131,175,183, -254,103,254,219,136, 13, 7,108,160,148,162,223,140,126,152, 55,114, 30, 9,116,221,121,160, 74,128,106,118, 38,253,126,101, 71, -136, 13,122,192,238,252,215, 44, 0,169, 24, 40,190,214, 2,187, 47, 13,112,100,126, 89, 46, 58,116,232, 16, 73, 74, 74,146,227, -127, 28,124,172,127,128, 71, 37,192,252,252,124,151,235,223, 61, 31,128, 15,186,116,233, 66,210,210,210,130, 22,147,231, 33, 47, -224,248,250,212,169, 83,169,231, 43, 63, 63,159,229, 86, 5,184,173, 8, 8,180, 19,135,221,205, 29, 46, 51, 51, 19,203,151, 47, -111,208,175, 56,242, 79, 73, 73, 65, 74, 74, 10, 0, 96,207,158, 61, 77,137,137, 46, 42, 42, 50, 59, 28, 14,232,116, 58, 84, 84, - 84, 64,167,211,193,104, 52,194,104, 52,194, 96, 48, 64,175,215,163,166,166, 6, 38,147, 9, 22,139,197,149, 20,212, 36,137, 17, -130,156,156, 28,191, 20,182, 59, 25,123,247,238,109,240,114,199,169, 83,167,148,238,159,249,196,156, 61, 99,254,158,150,123,115, -178,246,189,125,119,205,154, 53, 36, 39, 39, 39,168,185, 0, 57, 57, 57,188,231, 46,142,252, 25,134,161,245,253,203,229,250,103, - 89, 22,165,165,165,232,214,173, 27,153, 63,127,190,223,191,229,229,197, 35,177,103,207, 30,176, 95,181, 0,165, 20, 43, 86,172, -112, 61,163,189, 7,120,231,237, 33, 55, 55,119, 18, 0, 76,159, 62,189,184, 94, 1,176,124,249,229,250, 86,243,231,207,111,181, -103,207, 30, 60,244,208, 67, 99,252, 89,166,120,109,251, 85, 16, 16,172,119,179,254,103,188,111,132,104, 90, 13,190, 60, 96,197, -115,207, 61,135,101,223,191,125, 43,230, 21, 17,167, 4, 60,248,156, 29,212, 20, 9,232, 1,232, 1, 81, 45,160, 47, 5,182, 29, -110,131,204, 47,203, 69,245,222, 2,113,122,122,186, 89, 32,127,223,228,239,211, 3,144,153,153,217, 32,238,239,158, 15,192,119, -237,101,189,187, 80,197,185,229,155,235,146,247, 38,143,115,251, 39, 39, 39,107,131,181,132, 40, 57, 57,249,183,252,252,252, 94, -183,227, 3,230,172,254, 96,185,255, 57,171,223, 95,247, 63,135,245,235,215,187,222,255,243,159,255,196, 39,159,124, 2, 0, 86, - 0, 82,142,248, 1, 96,236,216,177,190, 20, 0, 83, 66, 66, 2,140, 70, 35,172, 86, 43,202,203,203, 33,147,201, 32, 22,139, 93, - 30,128,186,186, 58, 24,141, 70, 88, 44, 22,212,212,212, 96,202,148, 41, 62, 21, 76,206,186,111,106, 89, 43,119, 29, 31,220,200, - 28,128, 64,206,123,130, 91,238,231, 13, 43, 86,172,208, 44, 88,176, 64,213,189,123,119,237,173,236,195,141, 89,255,238,240, 39, - 23,160, 49,235, 63, 80,203,159, 97, 24,202,178, 44, 1,240, 15,174,107, 59, 28,142, 87, 67, 67, 67, 17, 31, 31, 31,208, 28,243, -202,139, 35,161,213,106, 65,114, 98, 0, 0, 59, 94, 9,199,216,215,107, 49, 98,196, 8,188,177,108,143, 95,133,169,182,109,219, -182,105,228,200,145, 0, 80,190, 97, 67, 86,187, 61,123,246,181,160,132, 98,252, 67,227, 83, 82, 82, 82,182,248, 51,157, 0,206, -216,255,180, 33,146,134, 22, 63, 40, 22, 60,183, 0,113, 99, 91,223,178,130, 89,233,233,233, 13, 52,124, 90, 11,200,172, 0, 75, - 9,236, 14, 10, 25, 5,226, 20,140,251,245,118, 8,112,242,247,178, 23, 27, 85, 16, 56, 15,172,152,143,229, 63, 96,192,128,235, -242, 1,252,113,209,121,146,118, 16,200,217, 83,158,230, 6,116,188, 94,249,249,249, 65,147,119,183, 38,254,113,133,101, 56, 55, -113,118,118, 54,158,120,226, 9, 0,144,114,215,184,159,171,159,180, 26,195,241,193,131, 7, 63,174,213,106,179, 29, 14, 7,244, -122, 61,108, 54,155, 43,238,111, 54,155, 93, 75, 12,185,196,192,177, 99,199,106,121,244, 23,146,157,157, 77,235,189, 0, 13,250, -109,126,126, 62,119, 28,201,201,201,188,188, 85, 55, 59, 7,192, 51, 44,224,235,121, 52,117, 94,173, 86,211, 21, 43, 86,104, 30, -123,236, 49,124,245,213, 87, 1, 61,115,207,229,183,220,231,141, 27, 55,106,210,139,213,152,234,195,210, 30, 55,110, 28, 61,127, -254, 60,190,255,254,251, 70,219,251,252,249,243, 0,128,237,219,183,251,252, 61,105,105,217, 52, 45,109, 52,198,140, 41, 66, 81, - 81,145,215,236,242,202,202,209, 0,116, 80,171, 27,159,183, 56,242,183, 90,173, 84, 42,149,114,215,252,163, 94, 33,120,245,226, -197,139,232,216,177, 99, 64,150, 63,195, 16,167,194,206,145,255, 81, 59, 62,209, 88, 1, 0,111, 44,219,227,247, 28,193,141,137, -249,243,231, 39, 82, 74, 49, 97,226,132, 41, 15, 79,124,248,155, 64,166,166, 73,143, 62,114,130, 16,114, 31,165,128,104, 90, 13, - 40,165, 88,176,112, 1, 90,143,109,243, 71,224, 35,112,112,236, 76,209,140, 74,130,153,153,153,116,227,139,109, 17, 86,121, 30, -231,244,241,232, 44, 43, 7, 66,227, 32,174, 43, 69, 68, 93, 37,128, 86, 46,143,129,167,210, 32, 32, 0, 15,128,251,114, 63, 15, - 87, 31,205,206,206, 6,223,132, 41, 79,210, 14,214, 15,119,151, 23,132,245,255, 2,154, 9,119, 23,186, 59, 9,113,245, 36, 60, -207, 53, 18, 67,180, 3,248,122,228,200,145, 79,231,229,229,125, 96,183,219, 81, 93, 93,237,202, 1, 0,128,242,242,114, 84, 87, - 87,131, 82, 10,127,194, 75, 99,198,140, 81,237,220,185, 83,147,157,157,141,156,156, 28,234, 25,243, 31, 51,102,140, 95,197,128, -110, 4, 76, 7,158,242,155,240,189, 17,124, 83, 74, 64, 70, 70, 6,153, 55,111, 30, 13,132,252, 27, 36, 0,186, 61,119,183,164, - 64,127,189, 0,141, 42,238, 23, 46, 92,112, 41,104,124, 13, 13,247, 80,229,245,247,205,111,174,170,169,169,161,145,145,145,238, -228,255,170,197, 98, 65, 73, 73, 9, 58,119,238, 28, 16,249,171,213,106,202,126, 21,133, 29, 71,157,198,233, 58,141, 21, 27, 14, - 88, 65, 41,197,190, 31, 3,143, 44,238,221,187, 23, 15, 61,244,144, 42,208,242,193, 28, 65,179, 44, 43, 1,128,175,126,180,225, -185,231,158, 67,235,113,109, 60,252, 3,254,129,171,242, 55, 98,196, 8, 10,120, 95,238,231, 86, 9,144,247,243,237,200,212, 1, -177,137,120,124,109, 13,128, 56,103, 27, 60,217, 18, 29,196,151,241,122,114, 25, 62,213,104,132,170,128,104, 88,233,207,211,242, -247, 60, 47,110,106,162,200,204,204,164,222,150, 77,249, 19, 2,240, 66,218, 65,131,135,188,160,174,255,247, 40, 7,236, 55,210, -210,210,192, 35, 97,145, 55, 26,115,247, 7, 26, 6,104,204,221, 31, 72, 24,192,189,188,172, 39,249, 52,117,174,177, 91, 37,132, -172,154, 48, 97,194,154,245,235,215,219,164, 82, 41, 44, 22, 11,236,118, 59, 88,150, 69,139, 22, 45,160,211,233,144,230,231,210, -179,212,212, 84,109,106,106, 42,217,185,115, 39,205,201,201, 65,118,118, 54,184,186, 0,183,115,229,185, 96, 99,247,238,221,116, -194,132, 9,216,186,117,107,179,201,223,147,228,242,157, 10,153, 79,111,220,243,207, 63,127,157,113,225,137, 23, 94,120,129,242, - 77,242, 84,171,163,124,202, 83,171,249,197,255, 21, 10, 87,233, 75, 74, 41,133,209,104, 68, 73, 73, 73,192, 49,255, 6,158,143, -215,107, 27,124,110, 14,249,127,248,225,135,193,234,179,108,238,183, 91,186,185, 87, 2, 12, 22,154, 82,200,214,173, 91,231,151, -245,175, 78,237, 90,242,241,105,180,205,200, 57, 7,119,238, 25,241,159, 76,186,123,222,189, 56, 83,170,192,153, 51,103,160, 82, -169, 32, 32, 8, 30, 0, 0,104,140,228,111, 71, 45,235,118, 91,255, 31,140, 37,126,127, 40, 34,201, 65,251, 93, 83,167, 78, 85, -249, 91,222,215, 7, 49, 80,119,133,198, 91,162,149,231, 57,158,132,107,159, 57,115, 38,217,177, 99,135,242,210,165, 75, 26,147, -201, 4,135,195,129,251,238,187, 79,149,148,148, 20,240,243, 30, 51,102, 12, 25, 51,102, 12, 55,195, 7, 20,154,185,209, 57, 0, -190, 62,243,177, 56,235,179,195, 27, 18,142,159, 69,102,184, 54,194,171,132,230, 35,237, 58,123, 48, 61, 61,157,166, 23,171, 65, - 26, 22, 2, 34, 0,112,230,204, 25,218,196, 88,245,217,232,163, 71,143, 38,126,140,125, 18,140,107, 0,160,170,170, 10, 10,133, -130, 18, 66,208,177, 99, 71, 16, 66, 72,183,110,221,208, 92,242,103, 30,211,129, 16,130,148, 71,156,171,138, 8, 33,174,229,126, -156, 59,255, 22,129, 29, 48,171,127, 80, 5,206,153, 51,135, 83,254,195,234,189,122,118, 56,221,255,172,219, 53,126,221,112, 70, -206,185,182,238,220,195,185,250,211,211,211,137,122,195, 61,135,103, 0, 0, 32, 0, 73, 68, 65, 84,151,134,158, 57,115, 70, 96, -243, 96, 43, 0,119, 10,130,177,214, 63, 88,132,125, 3, 20,155,160,254,174, 96,111,236,115,163,173,231,250, 24,191,215,255, 97, -181, 90, 33, 18,137, 32, 18,137,110, 98, 95, 91, 77,110,111,121,141,143,133, 89,179,102,249, 47,240,213, 63,246,177,200,206,206, -110, 48,105,167, 23,171,221, 45,111,237,221, 48,151,180,110,221,154,252, 49, 86,156,201,182,205, 37,127,231, 51,105,106, 43,160, -235,177,122,245, 79, 55, 77, 35,152, 55,114, 30,185,217,115,130,159,243, 70, 40,156, 57, 69, 54, 55,229,211, 21,231, 87,169, 84, - 68,176,252,125,195, 91,104,128, 36, 38, 38, 10, 5, 19, 4, 8, 16, 32, 64,128,128,255, 49, 48, 66, 19, 8, 16, 32, 64,128, 0, - 1,130, 2, 32, 64,128, 0, 1, 2, 4, 8, 16, 20, 0, 1, 2, 4, 8, 16, 32, 64,128,160, 0, 8, 16, 32, 64,128, 0, 1, 2, -238, 10, 52, 88, 5, 48,127,254,252,128,179, 65,189, 21,118, 17,228, 9,242, 4,121, 55, 79,222,146, 37, 75, 26,106,247, 12,227, - 90,230,232,190,212,140,171,166,232,190,244,204, 91,249,224,176,176, 48,200,229,114,215,247, 25,134,113,173,184,112,151,199,109, -204,196,178,206, 85, 94,220,102, 57,194,243,245, 71, 30, 81,138,196, 50, 80,214, 14,150,181,107, 3,145, 71, 41, 85, 29, 57,114, - 68,156,152,152,152, 15,143,170,123, 1,202, 83, 30, 57,114, 4,137,137,137, 90, 97,188,221,121,242,252, 86, 0,254, 23,241,242, -203, 5, 13, 26,238,141, 55, 6,146,219, 74, 94,193,203, 20, 0,222, 24,248, 6,113,127, 31,168, 60,174, 82,156, 90,173, 70, 70, - 70, 70, 83,215, 53,121,222, 93, 30,220,150,233,113,223,113,255,190, 90,173,118,157,227, 43,247,127, 17,140,181, 78, 89,254,219, - 1,140,136, 42,215,180,179, 95,198,105,218, 25,135,234,162, 85, 17, 9,131, 32, 13, 13,215,250,250,254,254,253,251, 49,108,216, - 48, 23,241,115,132, 77, 8,185,142,176, 89,150,117,189, 46, 94,188,232, 85,222, 47,191,252,130, 1, 3, 6, 64,161, 80, 64, 44, - 22, 67, 36, 18, 53,144,201,145,190,195,225,112,189, 44, 22, 11, 10, 11, 11,113,207, 61,247,220,141,143,136, 56,121,145, 42,127, -255,253,119,156, 57,115, 70,211,162, 69, 11, 12, 31, 62,188, 89, 99,156, 16, 70, 41,147, 71,163, 69,212,189,154, 58, 67,177,202, - 80,123, 89,233,175, 12,150,101,149, 57, 57, 57,187, 79,159, 62,141,173, 91,183, 66,161, 80, 96,209,162, 69, 34,184,173,189, 15, - 64,158,166,232,220, 89,236,220,177, 29, 82,153, 12,207, 61,183, 96, 20,165, 84, 35,140,212,187,212, 3,112, 39, 33, 39, 39,199, -167,198,147,154,154,234,115, 96,114, 4,237, 73,220,129, 34,216,242,130, 13,183,202,124,188, 38, 45, 62,165,101,249,202,171, 87, - 4,154, 85, 93,156,171, 42,232,254,255,239,248, 81, 72,169,242,196,254, 29,136, 56,255,163,198,104,180,192, 54,136,129, 34,158, -160,219,165,163,184, 63,156,106,116,229, 63,227,215,144,217,170, 10,210,174, 73, 37,224,196,137, 19, 16,137, 68, 24, 62,124, 56, -196, 98,177,235,197, 41, 4,156,213,111,183,219,225,112, 56, 96,179,217,112,241,226, 69,236,222,189,219,171, 60,163,209,136,195, -135, 15, 99,240,224,193,144, 74,165,144, 72, 36, 13,100,178, 44, 11,187,221, 14,187,221, 14,155,205, 6,147,201,132,195,135, 15, -195, 96, 48,220, 22,250, 84,125, 63, 99,240, 71, 33,154,128, 57,122,201,146, 37,172,199,220,130,218,218, 90,196,196,196, 4,180, - 0,125,201,146, 37, 13,126,207,231, 89,133, 80, 40, 90, 65, 36,146,106, 12,181,151,253,150, 89, 80, 80, 0,131,193,128,193,131, - 7, 95, 76, 78, 78,110, 83, 89, 89,137, 29, 59,118, 56,162,163,163,145,148,148,212,228, 24,153, 51,110,244,117,109,115,236,212, - 41,104,195, 67,176,112,197,191, 46,247,235,223,171,253,213, 43,101,216,145,167,221,221,169, 87,191,100,189,190,102,151, 64,157, -183, 63,184,210,191,238,240,172, 5, 32,110,106,146,229, 38, 87, 95,159,111, 5,249,255,245,175,127,109,242, 26,157, 78,135, 47, -191,252,146,242, 81, 2, 56,178,110,174,181,126, 35,228,185, 91,254,205,181,254,221, 72,152, 0,160,106,181,218,231,198, 49, 60, -201,154,112,196,206, 89,251,238,150,191, 59,213,241,237, 51,110,158, 10,234, 94, 78, 24, 0,170,170,156,149, 17,163,163,243,239, -138,129,122,225,167,124,220,115, 89,163,185,108,100, 49,249, 30, 17,238,141,181,131,141,166,144, 68,139, 80, 91, 41,133,162,214, -132, 30, 71, 86,105, 10, 19,230,169,140, 33, 29,181,141, 91,146, 4, 39, 79,158,132, 84, 42,197,168, 81,163, 92,164, 45,145, 72, -192, 48, 12, 40,165,176,217,108,176,219,237,176, 88, 44,184,124,249, 50, 52, 26, 77,163, 91, 42, 51, 12, 3,155,205,134, 35, 71, -142, 96,248,240,225, 80, 40, 20,144,201,100, 46,121,156, 2, 96,177, 88, 96, 48, 24,112,236,216, 49,152,205,102,191, 10, 51,105, -181, 90,165, 72, 36,210,212,214,214, 66, 42,149,162,172,172,236,169,201,147, 39,215,202,229,242,207, 3, 33,109,173, 86, 59, 85, - 36, 18,125,229, 38,239,244,228,201,147,127,151,203,229,169,112,238, 80,233,183, 37,252,202, 43,175,104,150, 46, 93, 90,134,250, - 29,103,150, 44, 89,130, 19, 39, 78,160, 85,171, 86,141,214, 93,247, 69,254, 31,207,157,139,241,253,250, 1, 0, 90, 63,253, 52, - 20, 33,113, 48,232, 47, 65, 95,115, 78, 69,169, 67,235,175,204, 62,125,250,160,172,172, 12,251,247,239,239,200, 48, 12,142, 29, - 59,134,232,232,104,236,221,187, 23, 86,171,213,103, 59, 86,190,185,176,193,231, 48,171, 13,109,237,102, 60,247,252,171,237, 87, -188,251, 79,188,243,238,135,104,199, 56,240,225,187,203,243, 71, 77,155, 33,176,235, 29, 72,254,220,113, 94,123, 1, 0,215,215, -255,246,245,249,102, 34,152, 59,245,221, 9,112, 87, 2,154,233, 1,224, 8,150, 0,160,159, 60,250,153, 87, 66,126, 98,211,108, -222,100, 93,239,218, 39, 94, 38,108,247,239,187, 20, 4, 62, 33, 0,238,127,123,254,245,244, 0,220,233, 48, 87, 87, 40, 71, 88, - 14,107,202, 68, 14,220, 19, 9,116,236, 64, 33,234, 35,133,184, 75, 23, 72, 45,102, 88,126,184, 12, 75,141, 24, 34, 86, 2,115, -254,231, 26,102,252,179, 42, 86,236, 61, 28,192,185,231,207,158, 61,139,168,168, 40,168, 84, 42,200,229,114, 72,165, 82,136,197, - 98,151,213,111, 54,155, 81, 82, 82,130, 61,123,246,128, 97, 24, 48, 12,131,166,228, 57, 28, 14, 28, 63,126, 28,195,134, 13, 67, - 68, 68, 4,228,114, 57, 68, 34, 17,236,118, 59,172, 86, 43,244,122, 61,126,254,249,103, 88, 44, 22,136,197, 98, 87, 46,128, 47, -124,241,197, 23, 74,131,193,160, 57,127,254, 60,244,122, 61,164, 82, 41, 90,183,110,189,106,223,190,125, 24, 50,100,136, 56, 52, - 52,244, 19,127,148,128, 47,190,248,226, 81,131,193,240,149,135,188,132,125,251,246, 37, 12, 25, 50,228,203,208,208,208, 84,190, -242, 88,150, 85, 90,173, 86, 84, 85, 85,105,220, 60, 10, 0,128,165, 75,151, 22, 47, 89,178,164, 93,106,106,234, 40,185, 92,238, -215,252,199,136,164, 74,207, 99,215, 62,248, 0,173, 39,197,227,157,119,222, 87,217,108,117, 1,205,167,251,247,239,215,252,244, -211, 79,120,241,197, 23,245, 34,145, 40, 66, 46,151, 99,200,144, 33,208,104, 52,200,203,203, 67,187,118,237,252,240,119, 16,124, -113,246, 42,190, 62, 83,140,220,111, 63,133, 72, 68,176,240,233,199,217,190,173, 91, 50,153,207,189,138,181,254,202, 19,112, 75, -200,223, 83, 57,245,166, 20, 4,188, 10,224, 86,111,111,219,165, 75, 23,149,175,215,205,182,214,111,132,188, 96, 88,253,141,225, -147, 71, 63, 35, 79,108,154, 77,189,145, 63,248,135, 8, 26, 88,250, 85, 85,201, 46, 11, 29,127,108, 1,234,183,219,191, 41,162, -143,142,206, 15,200,250,183,219,237,202,159,127,254,153, 54,118,204,243, 92, 99,112,191,222,110,183, 43, 61,207,121, 30,107, 10, - 85,199,127,209,148, 20,235,209, 42, 92,140, 46,225, 20,226,150, 44,196, 15, 60,136,208,190,159, 67,209,255, 61,200, 34, 21,144, - 26, 76, 48, 26, 29,232, 32, 50, 98,239,250,198,149, 39,134, 97, 32, 22,139, 33,145, 72,112,230,204, 25, 28, 59,118, 12, 17, 17, - 17,136,137,137, 65, 76, 76, 12, 90,182,108,137, 22, 45, 90,160,166,166, 6,123,247,238,133, 72, 36,114,197,246,189,129, 59, 47, -149, 74,225,112, 56,112,250,244,105,132,132,132,160,101,203,150,104,213,170, 21, 98, 99, 99, 17, 22, 22,134,211,167, 79,195,102, -179,185, 66, 4,141, 41, 20,158,150,127,105,105,169,230,220,185,115,232,220,185, 51,198,141, 27,135,129, 3, 7,194,104, 52, 98, -247,238,221, 56,114,228,200, 71,102,179,153,119,237, 98,173, 86,171, 42, 45, 43,255,166,232,106, 13,194,239, 25,140,132,113,127, - 66,187,129, 41,208, 89, 24,236,204,223,133, 35, 71,142, 76, 54,155,205,127,225, 75,254,122,189, 30, 71,143, 30,213,236,223,191, - 31,125,250,244,193,146, 37, 75, 90,162, 62,158,190,100,201,146,118, 0,224, 15,249, 51, 34,169, 50, 52,172,173, 50, 58,166,151, -102,253,134,163,152,251,241,199,200, 59,124, 24,121,135, 15,163,245,211, 79, 3, 0,108,182,186, 61,129,140,227,188,188, 60,154, -155,155,139, 41, 83,166, 92, 12, 15, 15,103, 66, 66, 66, 10, 11, 10, 10,176,127,255,126, 84, 84, 84, 32, 33, 33,193, 47,121,239, - 31, 62,131,119, 15,254,134,181,239,190,116, 84, 44, 50,129,113,212,226,237,149, 31, 51, 95,237, 45, 68, 9, 35,198,189,247,222, - 43,176,236, 93, 2, 38, 80,130,191,133,155, 87,220, 24, 11,251,229, 2, 26,204,184,125,176,229,221, 72, 69,224,137, 77,179,169, -251,171, 49,175,128, 47,175,194,117,228,214, 80, 25,240,215, 83, 65, 26, 59,238,233, 21,224,131,218,218, 90,229,174, 93,187, 52, - 5, 5, 5,141, 30,115, 63,215, 20,220,175,223,181,107,151,166,182,182, 86,233,126,206,243, 88, 83,136, 48, 87, 34,239,146, 25, -219,206,179,184,172, 35, 40, 45, 7, 24,113, 36, 24, 18, 3, 98,150,161,174,148,224,232, 37, 22,199, 46,153, 81, 89,107, 67,239, -104,153,134,143, 2, 32,147,201,112,238,220, 57,156, 58,117, 10,209,209,209,136,138,138, 66, 84, 84, 20,140, 70, 35,246,239,223, - 15,137, 68, 2,169, 84,218,228, 94, 10,156,119,128, 83, 2, 40,165, 40, 42, 42, 66,116,116, 52,226,227,227, 17, 27, 27,139,162, -162, 34, 56, 28, 14,200,100, 50, 72,165,210, 6, 43, 15,188, 77, 43,220,155,242,242,114,205,149, 43, 87,208,179,103, 79, 60,248, -224,131,152, 56,113,162,106,226,196,137,170,225,195,135,195,225,112,224,199, 31,127, 68, 81, 81,209, 96, 0,188,226, 9,229,229, -229,187, 75,171,106, 16,221,181, 47, 18,146,231,160,231,132,249,232, 49, 97, 30, 58, 62,240, 40,172, 84,196,201,227,245,124,235, -115, 31, 52,103,206,156,225,238, 85, 85, 79,252,204,146, 37, 75,176,116,233, 82, 44, 93,186,244,148,103, 94, 64, 99, 16,137,229, -202,168,232, 30,154,214,237,134,105,162, 98,122,128, 48, 98,124,244,137, 6,115, 63,254, 24,115, 63,254, 24, 75,151, 46, 69,121, -121, 57,248,202,243,176,252,233,150, 45, 91, 48,100,200, 16,244,239,223,191, 35, 0,249,174, 93,187, 6, 92,184,112, 1,199,143, - 31,135,201,100,194,132, 9, 19, 70,241,149,151,245,251,101,188,247,243, 41,172,121,227,249,170,248,123, 59,246, 49, 26,116,200, -250,102, 23,142, 30,251, 29,123,191,219,137,154,107,165,152, 48, 97,124, 50, 4,220,182, 72, 76, 76,108,212,250,231,149, 3,144, -145,145, 65,242,243,243,149,124, 63,223,201, 8,166,165,126, 35,228, 1,193,115,255, 55,106,133,186,197,212,253, 37,127,206, 11, -224,110,157, 7, 3,190,146, 15,253,129, 86,171, 85,150,148,148,104,184,205, 93, 26, 59, 22, 8,206,158, 61,139,202,202, 74, 77, -219,182,109, 85, 74,165, 82,219,216,177, 70,137,171,226, 50, 14, 92, 53, 97, 66, 72, 8,246, 93,102,209,182,191, 12,157, 45,133, -208,157,248, 43, 54,189,125, 20,236,133, 26, 24,172, 20,197,181, 14, 40,196, 12,236, 53,215, 16,217,132,210,238,174, 4,200,229, -114, 92,188,120, 17,167, 78,157, 66,207,158, 61,161,211,233,112,240,224, 65, 87, 44,223, 87,188,158, 16,226,242, 2,112,242, 40, -165,184,124,249, 50,122,247,238,141,252,252,124,176, 44, 11,185, 92, 14,137, 68,226, 90, 37,192,199, 3,112,233,210, 37,152,205, -102, 12, 24, 48, 0,241,241,241, 42,145, 72,132,136,136, 8, 12, 26, 52, 72,117,240,224, 65,205,165, 75,151,160,215,235,143,129, -167,203,254,210,165, 75, 96, 25, 41,218, 37, 38,163, 69,124, 2, 24,145, 4,138,136, 88,116, 24, 52, 1, 23, 15,230,162, 94,222, - 5, 95,114, 40,165,202,234,234,106, 77,113,113, 49, 58,116,232,128,161, 67,135,170, 68, 34,145,118,216,176, 97,100,201,146, 37, -116,240,224,193,246,250,121, 51, 33, 50, 50, 18,245, 10,138,163, 41,153,114,121, 12, 98, 98,251,194,106,169, 65, 69,229, 97, 88, - 44,186,209, 54,155, 97, 32,128, 55, 7, 15, 30, 12, 0, 40,189,118, 13,245,242, 36,112,219,244,166, 41,252,242,203, 47,169,235, -215,175,199,204,153, 51, 49,108,216, 48, 0, 96,119,236,216, 33,206,203,203,195,220,185,115,199,246,233,211,103,167, 63,125,249, -180,222,136,197,123,126,197, 91,127, 83, 99,248,196,228,232, 58, 67, 5, 54,126,179, 7, 25, 31,125,141,109, 11,231,160, 75,217, - 21, 44,211, 95, 67,116,116,140,144, 4,120,135,192,221,237,239, 45, 95,165,209, 28, 0,207,216,190,175,207,119, 35,130,189, 4, - 47, 80,188,126,255,235, 42, 66,200,109,217,222, 30, 75,253, 26,228, 1,120, 42, 3,193, 92,254,199, 87, 57,200,205,205, 85,150, -150,150,106,172, 86,107,147,199,154, 3,157, 78,135,186,186, 58,141, 94,175, 87,121, 59,150,146,146,210,232,179, 59, 82,101, 66, -141,149,197,145,114, 59, 74,170,237,136, 59, 40, 70,159,141,103,113,241,194,113,252,254,147, 21,118,177, 8, 86, 22, 48, 91, 41, -116,148, 69,108, 20,109,146,176,221,151,255,113, 25,251,165,165,165,232,216,177, 35, 46, 92,184,224,114,249,139,197, 98,215,245, -254,134,243,220,107, 8,112,127,111, 80, 72,176, 26,205,203,222,191,206, 24,247,117, 1,203,178,168,171,171,115, 78,142, 98,177, - 74, 36, 18,105, 61, 60, 73,226,220,220, 92,164,164,164, 48,139, 23, 47, 46, 93,182,108,153,125,241,226,197, 77,222, 60, 33, 78, -133,200,100, 44,133,161,246,178,202,225, 48,107, 1,236, 5,240,102,109,109, 45,114,115,115, 93,202,228, 61,247,220, 99,245, 37, -175,190,127,165,228,228,228,100, 79,152, 48,193, 69,254, 63,252,240, 3,179,121,243,102, 40,149,202,137,254,146,255, 85,163, 5, -143,231, 29,196,115, 83, 39, 32,245,241, 41, 48,154,245,216,148,171,197,202, 15,179,240,217,216,251,209,165,236,138,192,166,119, -129, 50,224,169, 4,220,148, 74,128,106,181,154,186,199,116,125,125, 22,112,221,196,126, 67,201, 63,208,152, 58, 71,252,158,217, -254, 30,174,127, 82,255,242,122,109, 99,253,197, 87,191,224,219, 95, 82, 82, 82,180,221,186,117, 83, 69, 69, 69, 53,121,172, 57, -136,138,138, 66,183,110,221, 26, 16,189,183, 99,222, 96,114, 68,192, 70,128, 67, 21, 22,148, 57, 28,216, 85,100,198,198,108, 51, -118, 95,137,197, 89,105, 36,174,212,216,112,185,150, 69,157, 29, 48,218, 41,100, 49,173,125, 18, 51,183,190,223,225,112,192,110, -183, 35, 38, 38, 6, 97, 97, 97,232,216,177, 35,108, 54,155,235,184,183,130, 64,158,242,184,245,253,118,187, 29, 38,147, 9,148, - 82,180,111,223, 30,197,197,197,104,211,166, 13,196, 98, 49, 44, 22, 11,172, 86,171,235,255,242, 9, 15,118,232,208, 1,114,185, - 28,133,133,133,184,114,229,138,198,225,112, 64,175,215,147,159,126,250, 73, 99, 48, 24,208,161, 67, 7, 68, 68, 68, 60,200,119, -142,234,208,161, 3, 24,214,138,226,195,249,168,190,114, 26,172,195, 6,147,190, 28,151,126,250, 14,214, 58, 29, 39,175, 19, 31, -229,134, 67, 76, 76,140,134,101, 89,151,167,115,233,210,165,228,248,241,227,168, 39,109, 22, 64,156,183,130, 71,158,176,219, 77, -176,219, 12, 80,132,182,134, 92, 17, 13,128, 40, 1,216,151, 46, 93, 26,227, 38, 15,107,215,174,229, 10, 40,121,189,231,202,202, - 74,250,217,103,159,209,140,140, 12,250,175,127,253,235,219,148,148, 20, 76,156, 56,145,243, 6,232,183,108,217,130,212,212,212, -148,169, 83,167,126,199,167,205, 42, 43, 43,233,231,159,127, 78,167,253,245, 41,140,202,217,131,191,205,158,140,103, 94,152, 15, -179,213,128,243,231, 46, 35, 35, 99, 35, 54, 63, 60, 4,202,246,173, 2, 30, 27,155, 55,111, 22,230,245, 91, 8,207,112,128,103, - 34,224, 77, 45, 5,236, 25, 54,240,245,249,166, 89,250,141,196,234, 61,173,125,190,214,127, 99,242, 10, 94,126,153, 22,188,252, -135, 59,223,243,179, 47, 79, 68,176,228,185,131,115,249,127,242,232,103, 36, 16,247,127, 70, 70,134,203,178,111, 44,222,207, 29, -119,191,214, 23,124,229, 15,248, 19, 30, 80, 42,149,218,135, 31,126, 88,229, 94,156,198,219,177, 64,112,207, 61,247,224,225,135, - 31,110,224,234,247,118,172,209,239,119,187, 7,221, 66, 69, 8, 39,128,141, 82,156,212, 89,177,254,172, 5, 95, 30, 40,193,207, -231,170, 80, 98, 2, 42,205, 14,156, 51, 80, 92,181, 80, 24,172, 54, 85, 83,228,197, 45,205,179, 90,173, 48,153, 76,104,211,166, - 13,122,245,234, 85,175,232, 69, 99,224,192,129, 46,194,230, 72,187, 49,194,230, 8,221,102,179,193,106,181,130, 16,130,174, 93, -187,162,186,186, 26,151, 47, 95, 70, 85, 85, 21, 58,117,234, 4,134, 97, 96,181, 90, 97,177, 88, 92,223,241,133,216,216, 88, 85, -124,124, 60,142, 31, 63,142,239,191,255, 30, 91,183,110,213,108,221,186,117,247,190,125,251, 32, 18,137,240,192, 3, 15,160, 75, -151, 46, 38,240, 44,100, 19, 27, 27,155, 18, 23, 29,137,202,162, 95,241,251,206, 79,112,252,187,213, 56,249, 93, 6, 46,254,184, - 25, 50,134,229,228, 21,251,146, 35, 22,139,181,113,113,113,170,136,136, 8, 28, 57,114, 4, 87,174, 92,209, 24,141, 70,165,187, - 34, 80,239, 9, 96,214,175, 95,143,158, 61,123,250,252,109, 86, 75, 13,106,170,207, 66, 34, 9, 69,139,232,238,154,208,176,118, -144, 72, 66,149,132, 48,131,185,107,194,171,243,161,249,236, 25,140,233,110,224,148,230,235,240,221,119,223, 65,161, 80,160,103, -207,158,232,212,169, 19,234,195, 7,118,157, 78,103,200,201,201,105,145,152,152,152, 50,106,212,168, 45,124,251,110, 94,222,119, -136,136, 8,195,136,145,131,140,137,253,251,224,209,191,206,133,145,216, 81, 94, 86,133,121, 79,191,134,101, 73,247,160,127,171, -192,149,228,205,155, 55,211,183,223,126, 91, 80, 2,110, 19, 69,192, 27,110,155,189, 0,110,245,170,130, 64, 8,216, 95, 12,124, -195,169, 64,184, 19, 53,119,236,102,201,115,183,194,159,216, 52, 27, 79,108,154,221,224,189,251, 49,190, 22,187,187, 39,193,155, - 71,161,185,121, 1,238,158, 0,207,191,124, 17, 30, 30,174, 29, 61,122,180,106,224,192,129,141, 30,115, 63,215,100,187,187, 93, - 63,122,244,104, 85,120,248, 31,203,242,188, 29,107,210, 58,148,133,170,122,183,105,137,161, 49, 50,220, 31, 37, 69, 91, 57, 3, - 25,165,144, 91,236,232, 16, 38,134,142, 82,252,102,176,227,116,157, 29,237, 90,197,160,211,253, 35, 27,149,197, 89,253,220, 82, -191, 14, 29, 58,160,111,223,190,208,233,116,168,174,174, 70,117,117, 53,194,195,195, 49,120,240, 96, 88,173, 86, 87, 77,128,198, - 8,155, 83, 38,108, 54, 27, 8, 33, 72, 72, 72,128,201,100, 66,121,121, 57,202,202,202, 80, 94, 94,142,186,186, 58, 36, 36, 36, - 64, 44, 22,187,228, 53, 86, 87,192, 83, 41,139,139,139, 83,117,237,218, 21,231,207,159,199,246,237,219, 81, 80, 80,128,144,144, - 16,140, 26, 53, 10,125,251,246,253, 78, 46,151, 47, 4,207, 16,128, 82,169,220, 18,215, 42,118, 86,215, 54, 45, 96, 56,247, 19, - 78,111,255, 8,197, 5,223, 34, 74,230, 64,242,232, 81,232,219,183,239, 28,185, 92,158,203, 71, 86, 68, 68, 4,250,247,239, 15, - 74, 41, 14, 28, 56,128,194,194, 66, 77,113,113,177,166,170,170, 74,185,100,201, 18, 21, 87, 57, 49, 41, 41, 9,123,247,238,245, - 41,143,101,109,218, 26,221, 89, 85, 85,249, 49,200,228,209,104,221,246, 1, 77,108,235,129,154,240,136, 78,223,189,243,238,191, - 31,230,228,125,249,108, 8, 54,252, 96, 65, 99, 74,207,233,211,167,209,178,101, 75, 12, 27, 54,140,189,255,254,251, 97, 52, 26, - 81, 87, 87,135, 85,171, 86,133,117,239,222,125,210,180,105,211,182,248, 51, 38,126,255,253, 52, 58,118,136,199,180,105, 41, 33, -175,188,252, 28, 42,107,107, 80, 81, 89,129,244,103, 94,195,107,143,142,198,232, 14,113,205, 34,255,149, 43, 87,162, 87,175, 94, -248,224,131, 15, 4, 37,224, 38,226,215, 95,127,109,180, 14,192,117, 10,239,237, 66,240,254,172, 42, 72, 77, 77, 37,193,170, 4, -232, 11,158,133,120,130,161, 4, 4,131,252, 3,149,215, 88,169, 94, 79,203,220,159,146,189, 30, 74,130,171, 40, 80,115,238,203, - 93,105,112,183,246, 3, 89, 1,224,110,221,221,127,255,253,164,177, 99,158,231, 26, 67, 83,215,243,149,193,225, 1,229, 40,109, -145,152,194, 94,144,135, 11, 53, 64, 24,145,160, 99, 24,131, 98, 7,129, 72, 38,198,222, 50, 7,204, 44, 16, 43, 19,161,107,210, - 8,200,187, 37,105,155, 82, 0,108, 54, 27, 68, 34, 17, 58,119,238,140,254,253,251, 67,175,215,195,108, 54,187,214,231, 91,173, - 86, 68, 71, 71, 99,216,176, 97,216,178,101,139, 43, 36,224, 13, 14,135,195,149,213,223,163, 71, 15,212,187,233, 97, 54,155, 93, -227,153,243, 36,244,232,209, 3, 85, 85, 85, 48, 24, 12, 77,141,229, 6, 39,102,205,154,165,213,106,181,163,122,246,236,185,219, -173,112, 79,245,240,225,195,119,203,229,242,153, 0,204,254,180,229,172, 89,179,214,107,181, 90,125,207,158, 61,115,221,228, 85, - 12, 31, 62,124,149, 92, 46,255,148,175, 28,134, 97,180,109,219,182, 85,141, 27, 55, 14,231,207,159,215,156, 58,117, 10,151, 46, - 93, 66,120,120,184,166, 69,139, 22, 24, 51,102, 12,254,251,223,255, 34, 41, 41,137,247,111,179,219,141,218,106,221,239, 42,179, -185, 10, 45,162, 18, 52, 97,225,237, 17, 30,209, 1,117,181,197, 91,222, 90,246, 17,166, 79, 75,198,151,207,134,120,109, 39, 14, -227,199,143, 71, 94, 94, 30,174, 92,185,194, 84, 85, 85,193,108, 54, 99,239,222,189,226,122,165, 83,239,239,120,152, 48, 97, 60, - 54,109,218, 2,125,117, 37,174,148, 92,197,179, 79,206,182, 62,255,226, 82,233,163,163,134, 96,152, 69, 15, 72, 2,163,135,205, -155, 55,211,127,252,227, 31,174,114,208, 93,187,118,197,219,111,191,141, 23, 94,120,129, 78,154, 52,233,206,175,220,121,135, 42, - 5,183, 76, 1,184, 17,171, 10,130, 65,238, 28, 42, 42, 62,194,203, 5,223, 54, 89,109,207,159,228,191,138,138,143, 80,240,242, - 31,242,220,137,217,211,101,207,135,180, 43, 62,170, 64,193,183, 47, 7, 77, 94, 48,193,199, 67,192,237, 1,224, 79,127,249, 95, - 26,156,157,134,168, 84, 71, 45,118, 77,249,238, 93,144,216, 77, 56, 90, 75,145, 95,107,135,148, 16,196, 80, 10, 85,155, 22,136, -106, 29,171,138, 31,164,244, 97,105, 58, 61, 0,157, 58,117,194,192,129, 3, 97, 50,153, 96,179,217, 32,149, 74, 93,132,205, 89, -233,177,177,177, 24, 58,116, 40,182,111,223,222,164, 7, 64, 44, 22,163,111,223,190, 32,132,192,104, 52,186,188, 11,156,210,206, - 85, 23,100, 89, 22,189,123,247,198,193,131, 7,225, 79,114,165, 82,169,212,224,143, 60,145, 48, 56,171,237, 93, 2,207, 76,120, -111,158, 0, 55, 89,209, 0,170, 0,248, 93,155,152, 97, 24,109,139, 22, 45,208,187,119,111,149, 68, 34,225,150, 63,106, 0,160, -184,184, 24, 15, 61,244, 16,150, 47, 95,238,151, 76,135,195,162,173, 51, 20, 43,173,214, 26,149, 66,127, 65, 19,209,162, 43, 66, -194,218, 34, 36,172, 45,118,236, 42, 5, 25,221,180,197, 61,100,200, 16, 34,149, 74,105, 85, 85, 21,198,143, 31,111,141,137,137, -145,178, 44,139, 75,151, 46, 1, 1, 36, 75, 62,240,192, 16, 34,147,201,104,196,137, 66, 60,249,228,159, 16,159,208, 77,250,246, -115,127, 98,215,125,248, 41,179, 74,100, 14,168, 47,111,222,188,153, 46, 94,188, 24, 45, 90,180, 64, 73, 73, 9, 20, 10, 5, 88, -150, 69,104,104, 40,222,120,227, 13,188,252,242,203,130, 18,112,131,145,152,152,216,168, 23,128,215, 50,192, 27,129,219,121, 85, - 65, 83,132, 19,136,245,223,152, 60, 79, 75,157,115,221,251, 34,237, 96,203,115,247, 4, 4,122,190, 41,175,130,231,230, 63,254, -202,251, 95, 3,195, 48,218,196,209,227, 72, 85,157, 73, 25,105,183,104, 68, 23,139,112,143,237, 42,194, 99,226, 48,164,119,119, -196,180,107,169,138, 76, 28,233,115,124, 80, 74,209,185,115,103, 12, 27, 54,204, 21,143, 23,137, 68,176, 88, 44,174,210,189,238, - 97,130,246,237,219, 99,232,208,161,208,106,189,139, 86, 40, 20, 72, 76, 76,132, 88, 44,134,213,106,117,125,207,125,233,160,251, - 70, 64, 12,195,160, 95,191,126, 40, 44, 44, 12,164, 25, 40,128,218,250, 87, 48, 96, 8,132,248,189,121,141,122,245,234,197,229, - 81, 16,150,101,149, 70,163, 17, 22,139, 5,221,187,119,199,138, 21, 43,252,220, 28,135,106,109,214, 90,216,172, 6,149,201, 84, - 14,153, 44, 10, 18,105,184,134, 97,196,248, 98,253,119,170, 89, 51, 39, 52, 41,175,190,174, 63,121,239,189,247, 88,147,201, 4, - 0, 72, 72, 72,240,171,252,178, 59,250,247, 31, 64, 68,247,223,255,208,220,127,188,151,231,148, 71,153,132,132,123,145, 48,105, -210, 44,177, 88,188, 62, 16,153,203,150, 45, 19, 6,245,109,162, 4, 52, 69,254, 55, 85, 1,184, 83, 17,204,101,127,158,196,220, - 92,107, 61, 88,242,154, 99,113,187, 19, 59,247,222,195,101, 47,116, 34,158, 24,149, 50, 73, 91,111,189, 98, 68, 0,223, 79, 75, - 75, 67, 84, 84,148, 43,195,159,101, 89,151, 11,159,243, 0,112, 73,127,220,142,128, 93,187,118, 5, 33, 4, 27, 54,108,184, 78, -222,202,149, 43,145,157,157,237,186,214,225,112,248,220, 14, 88, 42,149, 34, 41, 41, 9,124,178,227,239, 84,101, 45, 44, 44, 12, - 97, 97, 97,136,137,137,105,198,216,225, 20,129, 90, 48,140, 24,206,116, 44, 86,195, 83, 30, 93,180,104, 17,169,127,158,148, 97, -152,102,205, 35, 14, 7,187,109,193,130, 5, 4, 0,195,178,172,131, 97, 24, 5,252, 12,191,112, 16,172,251,219, 75, 9,240, 5, -146,152,152, 40, 36,103, 8, 16, 32, 64,128, 0, 1,255, 99, 96,132, 38, 16, 32, 64,128, 0, 1, 2, 4, 5, 64,128, 0, 1, 2, - 4, 8, 16, 32, 40, 0, 2, 4, 8, 16, 32, 64,128, 0, 65, 1, 16, 32, 64,128, 0, 1, 2, 4,220, 21,104,176, 10, 96,254,252, -249, 1,103,112,174, 94,189,250,186,100, 66, 65,158, 32, 79,144,119,247,201, 83,171,213,244,145, 73,106,124,187, 57, 3, 25, 25, - 25, 12,188,172, 65, 23,218, 79,144,247,198, 27,111,184,174,121,249,229,151,137,208,126, 55, 87,158,223, 10, 0, 55,184, 27,187, - 56,144, 37, 47,119,178,188, 64,100,222,238,247,235, 5, 82, 0, 17, 0, 66,234,251, 3, 11,160, 2, 65, 88, 67, 29, 76,112,237, - 16,140,123,246,214,166,183,170,248, 80,109,237,255,111,239,202,195,154,184,214,247, 59, 73, 8, 1, 65, 22, 17, 17,149, 42, 32, -138,184, 32,238, 90,149, 88,144,130,128, 91,209,254,106,123,107, 55,162,183,215,122, 91, 84,172,116,177, 11,173,120,181,155,183, -173,161,183, 85,219,122,111, 43,181,130, 59,149, 26, 92,170, 86,197, 21,180, 42,224, 86, 65,169,202, 78, 66,150, 57,191, 63,194, - 96, 8, 89,102,146, 32,216,206,251, 60, 60, 9, 39,147, 47, 51,231,204,156,247,253,190,115,206,119,106, 35, 15, 29, 58,164,216, -183,111, 31, 0, 96,226,196,137, 24, 59,118, 44,235, 84,194,237,209, 14, 83,167,201, 16, 23, 27,161, 5,100, 34,153, 76, 70,255, -213, 18, 55,241,176,142,244,244,116,146,144, 16,212,226,127,107, 34,128, 71, 59, 71, 0, 24,144, 77,173, 55,128,160,102,217,190, -111,186,169, 14,194,158,221,255, 28,109,207,212,245,218,115,205, 29,253,122, 25,226, 47, 58,115, 96, 93, 81,209,233, 71,252,122, - 4,117,171,174,214,192,195,195, 9, 55,111,148,208, 97, 97, 67,238,134, 13, 30, 63, 18,192,101, 46, 6, 79, 28,254,140,148,150, - 92, 68,201, 21, 21,174,151, 19,244,234, 78, 33,168,183, 4,129, 65, 33,136, 24,243,247, 14,241,240,155, 18, 18,204, 94, 3,237, - 65,100,103,207,158, 85,132,135,239,198,218,181, 13,200,207, 7,222,124,243, 39, 92,191,126, 93,225,231,231, 7,137, 68,130,178, -178, 50,233,244,233,211,225, 8, 65,112,224,192, 1, 82, 93, 93, 45,141,142,142,134,179,179,179, 45,246, 4, 0, 16, 23, 27, 65, - 39, 39, 39,139,128, 76,228,100,235, 31, 21, 56,118,219, 94, 30,127, 2,168,213,169,200,205, 77, 70, 76, 76, 38, 18, 18, 50,154, - 35, 2,188, 16,184, 63,224, 19, 1,113,128, 33,217, 83, 20, 64,127,239,245,167,189, 86,141,186,254,169,220,221,223, 47, 11, 14, -238,219,127,198,180,137,232,213,163, 51, 60, 61,156, 81, 89,165,194,141,242, 94,130, 75,165,149, 62,219,183,126,165,136,121,116, -246,106, 39,113,167, 53,214,236,157, 59,187, 47,242,242,197,237, 10, 33,106, 48,123, 10, 48,110, 24, 16,244, 16, 80,124,133,224, -224,113, 37,118, 42, 78, 99,199,230,197,164, 79, 72,188,116,192, 32,235, 25,237,218, 42,218, 97, 46,138, 32,151,203,169,246, 18, - 1,119,239,222,197, 75, 47, 53,160,107, 87, 32, 41, 9, 88,177,162, 14, 39, 79,158,132, 86,171,133, 68, 34,129,175,175,175, 98, -251,246,237,232,219,183,175,116,248,240,225,249, 28, 59,128,200,194,194, 66,116,235,214, 77, 17, 29, 29, 77,125,251,237,183, 0, -160,200,203,203,195, 19, 79, 60,129,145, 35, 71,114,189, 86, 49, 0,236,220,117, 66, 0,100,210,250, 87,189,134,230,123, 16, 30, -134,222, 62, 0,204,156,185, 25,185,185,250,215,228,228, 18, 48, 17, 1, 62, 26,112,127,137,223,176,188,221, 82, 1,119,116,144, - 77, 94,205, 34,224,207, 76,254, 0, 68,123,114, 55,189, 38,157, 16, 17, 50, 98,104,119, 80,148, 62,171, 27, 77, 19,116,118,115, - 70,167, 32, 49,122,247,242, 64, 15, 63,183,135,246,228,110,122, 45, 46,225,153, 44, 0, 55, 45, 25,188,124,113,187, 98,252,176, - 26,252,243, 25, 64, 40,212, 11, 40,141, 22,232,228, 10,132, 6, 3,163,195,129,237,138, 26, 28, 57,189, 93, 49, 96,208, 68,155, - 30,124, 71, 13, 1,152,251, 62, 35, 2,238,119, 99,120,123,123, 99,251,118, 23,244,234,165, 68,126, 62, 80, 89, 41, 66,112,112, - 48,130,131,131, 81, 87, 87,135,210,210, 82,228,231,231,163,166,166, 70,209,175, 95, 63,214, 67, 3, 63,254,248, 99,164, 82,169, - 84,136,197, 98, 84, 86,182,140,100, 41,149, 74,124,249,229,151, 40, 45, 45, 37,143, 63,254, 56,151,250,164, 1, 32, 39, 91, 14, - 64, 38,208,191,218,142, 99,199,142, 53,215, 55,179,137,146,169, 50, 54,247,133, 97,219,178, 45,179,234, 20, 16, 18,137, 11, 23, - 48,178,174, 78,209,229,198, 13,252,238,235,139, 19,157, 59, 75,157, 6, 12, 0,161,168,124, 91,175,153,235,134, 81,108,108,176, - 45,107,107,123,134,161,255,228,228, 92, 36, 36, 4, 53,191, 50, 72, 72, 8,226, 69,192,125,128, 49,217, 51,251, 3, 24,150,243, -171, 0,140, 31,250, 63,249,245, 21,157, 57,176, 34, 56, 56, 56,100,100, 68,247, 22,229, 2, 1, 5,177, 88, 8, 23,137, 8, 78, - 78, 2, 4,245,241, 66, 80, 80,176,111,209,153, 3,219, 45, 9,197, 19,135, 63, 35, 66,212,224,229,103, 1, 85, 35,112,249, 58, - 80, 89, 13, 84,213, 0,255,221, 10, 44, 88, 14, 44, 91, 5,140,141, 0, 4,164, 6, 39, 14,127,198,123,139, 6, 24, 52,104,144, - 52, 39, 39, 20,190,190,192, 19, 79,136,224,231, 55, 2, 19, 39, 78,148, 38, 36, 36, 80,241,241,241,210,152,152, 24,116,235,214, - 13, 39, 78,156,192,247,223,127,175,248,233,167,159, 34, 27, 27, 27, 35, 45,217,252,246,219,111, 35, 27, 27, 27, 21, 78, 78, 78, - 22,127, 91,161, 80, 96,211,166, 77,145,108, 72,118,255,254,253, 4,128, 90, 46,151,139,239,137,128,123,100,186,127,255,126,194, - 85, 64, 29, 61,122,180,249,207, 82,153, 45,162,142,109,153, 37,242, 15,252,237, 55,197,244, 83,167, 20,189, 46, 22, 67, 92, 83, -131,238, 23,127, 67,228,145,195,138,174,167, 79, 43, 64, 72,164, 45,237,125,244,232, 81, 28, 59,118,140, 20, 22, 22, 70,218,122, -207, 48, 54,216,148,177,181,103, 76,244,108,202,172,129, 33,125,230, 85,157, 16,204, 63,240,247,137,248,217,164, 1,126, 96, 35, - 0,109,233,169,145, 54, 60, 63, 71,133,152, 25,251,230,126,199,210,111, 20,157, 59, 29, 59,107,134,180,153,244, 77, 65,226, 44, - 66, 85,117, 35, 66,130,188,145,181, 69, 17, 20, 54,120,188,135, 57,123,165, 37, 23, 49,123,138,254,253,238,253,192,167,223, 0, -147,199, 3,113,145,192,111,197,192,201, 34, 2, 23, 9,133,161, 97, 64,204, 68,224,199,220,139,136, 24,227, 56,207,221,150,186, -107,163, 57, 21, 54,193,221,221, 61,191,174, 78, 63,223,242,137, 39,158,192,184,113,227, 40,195,207,238,222,189, 43, 13, 13, 21, - 41, 18, 19, 1,138, 58,142,138,138, 6,197,239,191, 7, 89, 10,255, 69, 82, 20,165, 96,187, 57, 76, 69, 69,133,194,154,238,157, - 51,103, 14, 54,110,220,136,141, 27, 55,146, 57,115,230,180,104,139,253,251,247,147,141, 27, 55, 54, 31,215, 81,250, 3,182,101, -230,208, 88, 88,136, 62, 5, 5, 80, 11, 4,112,162, 0, 45, 77, 64,107,116,160,181, 90,116, 61,176, 31,197,132,160,243,208,161, - 54, 19,184,171,171,171,226,248,241,227,210,185,115,231,230,219,106, 3, 64, 11,143,220, 84,153, 45,209, 5,123,201,223, 28,209, -231, 26, 69, 2,120,180, 63, 76, 10, 0,115,147,223,108, 33, 28,107,132,200,213,222,253, 30,163,181,101,198,184,165, 73,133,182, -216, 51,245, 29, 27, 39, 46,138,252,252,131, 6,248,251,185,129, 16,224,192,225,235,104, 80,234,119, 93,141, 24,226,135,174, 93, - 92,112,253, 70, 45, 93,124,185, 82, 32, 18, 9,208, 55,208, 11,254,254,193,158,208,111,209,106, 18, 37, 87, 84, 24, 55, 12,104, -212, 0,187,246, 1,138,195, 4,254,221, 40, 4, 6, 0,143, 60, 12,244, 15,162, 32, 18,234,183, 22, 31, 29, 14,252, 75,174, 98, - 85,223,134, 33,121, 54,239,217, 40, 94,195,177,126,195,122,119,228, 10, 3, 91,208,180,157, 43, 6, 15, 30, 44, 53,254, 76, 40, - 20, 42, 6, 12,168,192,178,101,122,121,250,222,123, 23,113,229, 74,152, 89, 91, 42,149,202,170,231,111,136, 43, 87,174, 88, 61, -102,194,132, 9,212,132, 9, 19,154,201,126,227,198,141,196, 88, 32, 76,152, 48,161, 93,234,174, 45,188,127, 0,232,123,251,142, - 66,173,209, 64, 32, 16,128, 8,133,160,105, 26, 26,154, 6,173,211, 65,167,163,209,179,188, 92, 81, 51,116,168,205,215,220,208, -208, 0, 0,138, 99,199,142,129,162, 40,206,243, 59,218, 66, 4, 56,202,243,207, 77,206, 69, 76,102, 12,102,110, 6,146,115,245, -239,115,147,115,155,197,129,120, 91, 49,207,188,247, 17,134,115, 2, 88,205, 1, 48,183, 10,192,214,213, 1,230, 60, 46, 91, 60, - 49, 75,162,193, 86,129, 98,233,186,141,191,203,214,139, 48, 55,169,208, 22,123,150,190,195,252, 14, 5,128,222,100,117,238, 2, -173,159,237,239, 12, 0,184, 94, 86, 3,165, 82, 11, 0, 8, 14,244, 66,215, 46, 46, 56, 93, 84, 33,184,112,233, 46, 36, 18, 33, -130,250,120,162,178, 90, 13, 0,102, 13, 95, 47, 39, 8,122, 72,255,251,143, 78, 0,194, 7, 80,112, 22, 3, 90,173, 62, 18,224, -233, 14,148, 94, 3, 98, 38, 0, 15,245,212, 31,223,158, 48, 36,125, 91,198,133, 59, 58, 42, 42, 42,218, 44,138,210, 68,242,205, - 30,127,123,147,191, 33, 50, 50, 50, 72,106,106, 42,101,235,231,198,112, 42, 41, 70,163, 70, 13, 74, 40,130,142, 16, 80, 0,180, - 58, 26, 26, 45, 13,162,211,129,186,116, 1, 64,156,221,231, 93, 88, 88, 8, 31, 31, 31, 69,117,117,181,212,195,195,195,102, 17, - 96,173,236,126,145,127, 90, 90, 26,149,158,158, 78,102,110,110, 41, 8, 0, 32, 38, 51, 6,226,109,197,216,182,173,164,121, 37, - 0, 51, 97,208,219,219,155,103,234,251, 76,254,102, 5, 64, 71,135, 37, 66,180,133, 96,237, 89,226,104,209,110, 27,175, 38,160, -102, 85,114,253, 13,202,195,195, 9,149, 85, 42,248,120,187, 34, 41,177, 63,180, 58, 26,206,206, 66, 8, 5, 2, 16, 66, 16, 63, - 57, 8, 83,162,131, 64, 81,192,157, 74, 37, 60, 60,156, 0,224,174, 57,131,189,186, 83, 40,185, 74,189,136,105, 47, 0, 0, 32, - 0, 73, 68, 65, 84,208, 63, 8,152, 52, 70,223,235,252, 86, 12, 12,238, 15,120,117, 6, 98, 35, 1,154, 6, 68, 66,224,226,101, -253,241,108,219,150,203,123, 91, 19, 97, 88, 19,164,109, 13,154,166, 35,123,244,232,129,146,146, 18,236,223,191, 95, 49,126,252, -120,169,155,155, 27, 4, 2, 65, 62, 0,232,116, 58,233,185,115,190,138,183,222,186, 1,138,162, 80, 81, 17,130,144,144,222,184, -120,241,162, 57,123, 38,203, 55,109,218,212, 58,138, 68, 8,102,207,158,205,233,154, 13, 69, 64, 71, 34,127, 71,136, 4, 67,220, -237,217, 3,226,223, 46,128, 56, 1, 98,154,232, 39,182,234,180, 80, 19, 29, 26,180, 90, 40,131,251, 59,228,220, 7, 14, 28, 8, -138,162,108, 34,127, 0, 24, 57,114, 36, 70,140, 24, 65, 29, 61,122,148, 88, 42,179,134,166,136, 65, 11,194, 55, 85,198, 5,201, -185,247,136, 31, 64, 43,207,159,153, 48,184,109, 91, 9,207,212,237, 64,254, 15,172, 0,104,107, 65,225, 40, 66, 32, 4, 16,204, -174,108, 51, 17,192,172, 92, 16,204,170,100,227,253, 3,128,232,230,141,146,219,215,111,244,244,241,241,118,197, 7,159, 31,195, -132,177,189, 16, 49,184, 27, 40, 39,170,121, 69, 64,211,214,241,184,126,163, 22, 55,111,148, 92, 6, 96,214,173, 12,234, 45,193, - 47, 5, 74,244, 15, 2,124,134, 1, 75,231, 3, 11,231, 2, 30,238,250,176,255, 91,159, 0,203, 23,234,143,253,165, 64,127,188, -173, 4,237, 40, 79,189, 35,229, 2, 56,119,238, 28, 36, 18,125,157,236,216,177, 3,215,174, 93, 83,244,235,215, 79, 58,105,210, - 36,212,214,214, 70,122,123,123, 43, 14, 30,212, 34, 63, 31, 24, 49, 98, 56, 2, 2, 2,164, 61,123,246, 4, 0,133, 41,123,157, - 58,117,130, 90,173,102,245,219, 90,173,246,129,127,118, 13,201,159,141, 16, 96, 43, 2, 74,186,250, 74,157,207,156, 81,208,132, -160,147, 64, 4,161,144,130,150,232,208,160,209,160, 86,173, 70,153,191,191,212,199,142,243,118,117,117, 5, 69, 81,210, 17, 35, - 70,228,219,106,131, 33,122,107,101,247, 91, 4,164,165,165, 81,201, 77,158,189, 49,249, 27,122,255, 60,218,151,252,121, 1,112, - 63, 60,188, 54, 94, 82,216, 44, 2,216, 9, 13,109, 88,216,144,178,226,203,149, 62, 67,194,124,177,116,225,104,172,255,223, 89, -184, 72, 68, 8, 31,232, 11,138,162, 12, 60, 73,130,226,203,149, 8, 11, 27, 82, 8,160,214,156,193,192,160, 16,236,216,123, 26, -115,103, 2,164, 20, 24, 61, 3, 8,236, 5,108,204, 49, 56,104, 33,160,211, 1, 59,246,234,143,111, 47, 88,138, 20,181,215, 50, -192,187,119,239, 42, 66, 67, 47, 99,221, 58, 0,208,225,237,183,207,224,228,201, 6, 69, 67, 67, 3,106,107,107, 81, 90, 90,138, - 91,183,110, 33, 34, 34, 2,179,103,207,182,186, 12,144, 16, 34,165,105, 90, 33, 16, 88, 95,224,195, 8, 15,174, 96,134, 0, 54, -110,220,136, 9, 19, 38,180,235,243,149,154,154, 74, 49,196,111,109, 8,192,218, 49,134,240, 26, 58, 20,119,212,106,232, 20,249, - 80,139,157,224, 70, 68, 80,209, 52,170,213,106,212, 78,122, 4, 62,195,134,217, 24, 21,164, 48, 98,196, 8,155,199,253, 13,109, - 24, 18,189,169, 50,123, 68,192,177, 99,199, 44,150,177,129, 41,242,103, 60,127, 0,252,132,192,118, 38,127, 94, 0, 60,224,104, - 30,255,103, 63, 12,160, 11, 27, 60,126,210,246,173, 95, 29,252,181,192,189,255,168, 97,254,136,141, 10,196,238,159, 75,177,227, - 39,253,195,249, 90,202, 88,208, 52,193,175, 5,101, 40, 41, 41,190, 26,159,248,236, 63, 0,104,204, 25,140, 24,243,119,106,199, -230,197,228,195,175,244, 75, 1,215,190,171, 95,250, 23, 53, 78,191, 20,240,195,215,245,228,255,225, 87,128, 14,157,109,206, 8, -104,175,103,110, 45,130,208, 94,171, 0,234,235,235, 49,116,168, 10, 35, 70,232,255, 31, 62,156, 96,247,238, 82, 92,188,120,145, - 73, 4,132,200,200, 72,244,237,219,151, 85, 14,128,201,147, 39,231,103,103,103, 91,141, 2,104,181, 90,120,122,122, 74,185,158, -111,211,114,192,230,149, 1,251,247,239, 39,182, 14, 3,140, 28, 57,146, 85, 25, 23, 17, 96,237, 56,214, 70, 5,130,124,245,168, - 81,210,243, 78, 78,232, 85, 94,174,112,187,118, 13,170, 62,125,112,197,215, 87,234, 29, 17, 1, 52, 13,209,216, 64,176,142, 32, -233, 86, 54, 76,149,177,173, 75,227,227, 24,194,183, 86,102, 11,140, 73,159,137, 8,216, 59,132,199,163, 53,216, 76,140,230, 5, - 64, 27,122,230, 29,244, 55,238,196, 60, 58,251,163,220,221,223, 47,254,189,188, 54, 40,184,143, 23,166, 76, 14,130,151,167, 4, -149, 85, 42,156, 60,123, 11,197,151, 43, 81, 82, 82,124, 40,230,209,217, 63, 2,184,110,205, 96,159,144,120,233,129,130,237,138, - 67, 5, 53,152, 50, 9,248,226,125,125, 38,192,146,171,192,151,155,244,158,191, 14,157,209, 39, 36, 94,106,235,181,218, 51, 4, -192,150,252,219, 99, 14, 64,121,121,185,212,203,203, 71,113,252,248, 31, 0,128,139, 23, 59, 99,196,136, 1,232,210,165, 11, 36, - 18, 9,202,203,203,165,241,241,241,156, 82, 1,247,238,221, 91,122,225,194, 5,133, 97, 68,199,152,252,131,131,131, 49,114,228, - 72, 78, 36,198,172, 2, 48, 24,251,103, 38, 4,218, 36, 2, 76, 17,161,173,228,104,141,220, 57,145,191,129, 8,232, 50,124, 56, - 26, 0,170,161,169,200,222,169,106,246,146, 63,151,122, 99,251, 91,142,182,199,150,252,213, 9,193, 0, 63,254,127, 95, 34, 1, -230,132, 1,167,101,128,182, 78,150,227,186, 12,208, 86,123,182,218,116,244,249, 89,170, 39, 71,157,159, 61, 19, 23,157,196,157, -228,241,137,207,126, 87,116,230,192,103, 91,114,246, 5,250,245, 8, 26,109,176, 23,192,145,176,176, 33, 71,227, 19,159, 93, 6, -160,158,141,189, 1,131, 38,230, 15, 24, 52,145, 58,113,248, 51,242,253,142,139,120,239,211,142,183, 23, 64, 71, 36,127, 0,120, -252,241,199,113,250,244,105, 60,243,204,241,166, 8,192,112,204,154, 53, 68,234,234,234,154,111,171,205,240,240,240,252,240,240, -112,106,235,214,173,145,181,181,181, 10,161, 80, 8,129, 64, 0,173, 86, 11,177, 88, 12, 55, 55, 55,169, 3,200,223, 33, 34,128, -199,159, 19,105,105,105, 84,122,114, 58,241, 95,224, 47, 69,111,211,199,148, 37,231, 42,248,249, 0,237, 11, 17,219,142,210,209, - 29,111, 91,216,179,229,183, 30,228,235,181, 19,213, 97,131,199, 63, 25, 54,120, 60,147, 49,198, 13,128, 15,128,114, 0, 74, 52, -165,125,229,130,136, 49,127,167,108, 73,242,211,214,245,208,145,242, 74, 24,195,213,213, 53,127,204,152, 49,212,152, 49,142,175, -184,196,196,196,124, 56, 40,185, 37, 51,238,111, 76,242, 19, 38, 76,160, 54,110,220, 72, 58,194,124, 0, 30, 29, 79, 4, 88, 62, - 0, 60,249,183, 1,216,102, 1, 4, 0, 42, 60, 60,156, 31,123,225,193,131, 7, 15, 30, 60,254, 98,224,247, 2,224,193,131, 7, - 15, 30, 60,120, 1,192,131, 7, 15, 30, 60,120,240,224, 5, 0, 15, 30, 60,120,240,224,193,131, 23, 0, 60,120,240,224,193,131, - 7,143, 63, 7, 90,172, 2,152, 63,127,190,205,179, 50, 77, 37,114,224,237,181,141, 61, 54,155,216,180,167,189,188,188,188, 72, - 0,138,172,172, 44,135,216,219,187,119,111, 36, 77,211, 14,179,199,223,127,237,102,111, 54,128, 77,109,124,126, 78, 0, 36,208, - 39,173, 81, 65,191,154,133,192, 40,137, 13,223, 30,188,189, 63,187, 61,206, 2,192, 26, 57,152, 3,151,165, 84,142,182,119, 63, -145,156, 84, 77, 32, 22, 35,115,163, 11,171,243,203,203,203,139,204,202,202, 82, 56,234,122, 13,237,173, 94,189, 90,154,146,146, -162,176,101,123, 97, 83,246, 10, 63,237,140,129, 47,214,192, 30,123, 12,166,141,216,169, 56,125, 65, 7, 0,200,204,204, 36,201, -201,201,118,181,103, 72,183,239,161,212,122,195,197,197, 5, 89, 89, 89, 36, 41, 41,169,163,220, 31, 93,231,189,146,242,205,218, - 15, 86, 63, 5,224, 15, 7,216, 11,152,255,210,203, 95,124,254,201,135, 79,154,177,231, 4, 64, 11,203, 25,217,156,160,207,220, -216,117,225,194,151,191,249,248,227, 15,159,130,126, 51, 39, 26, 14,200,228,102,252, 28,115,188, 55, 14,183, 85, 67, 80, 20, 21, - 39, 16, 8, 6, 8, 4,130, 72,138,162, 66, 0,184,170,213,234, 92,161, 80,232, 73,211,116, 5, 33,228,117, 0,119, 28, 89, 7, - 60,120,152,194, 83, 37, 37,228,155,160, 32,135,245, 81,201, 50, 25,201,108, 35, 78, 20, 89,123,200, 9, 33,150, 30, 58,206, 29, -134,163,236,113,245, 96, 29,137, 61,123,246, 88,237, 68, 24,114, 77, 77, 77,133,175,175,175,201, 12,120, 41, 41, 41, 10,182,191, -201,216, 99,136,255,200,145, 35,205, 66,192, 30,123,244,185, 55, 32, 24,240, 54,190,222,171, 79, 29, 75,159,123,163,249, 24,193, -128,183, 57,213, 75,231,154, 87, 8, 77,128,239,118,235,109,197, 78,116, 66, 88,112, 17, 50, 51, 51, 9, 0,112, 21, 2,213,218, -239, 34,171,174,220,129,146,154,168,168,111,236,132,216,152, 42,244,240,163,112,252,248, 33, 82, 83,163,194,164, 73,147,218, 85, - 8,204, 95,184,240, 37,208,244,228,249, 11, 23,190,244,249,199, 31,191,110,183,189, 5, 11, 95, 32, 52, 29, 61,127,193,194,151, - 62, 95, 99,210,158,134,133, 25, 13, 0,106,193,130,133, 47,209,180,110,242,130, 5, 11, 95, 90, 99,218,150, 0, 54,228,122,176, - 19,106,195,251,239,135, 31,126, 80,204,152, 49, 67, 58,121,242,228,124,123,140, 10,133,194, 88,145, 72, 52, 65, 36, 18, 61, 46, - 20, 10,189, 4, 2,129, 91, 70, 70,134, 96,241,226,197,207,234,116, 58,104,245,120, 92,167,211, 37, 0,248,165, 73, 4,168,155, -250,191, 54, 31, 6,221,177, 99, 7, 97,219,223,197,197,197,113,186,167,119,238,220, 73,236,249, 62, 15,199,195,101,229, 74, 64, - 46,119,152, 61,229,146, 37,118,125,159,201, 8,200,105, 59, 96, 54,228, 63,108,216, 48, 20, 20, 20,112,242,248, 45,145, 60, 27, -123,166,236,167,166,166,162,180,180, 20, 89, 89, 89, 14,221,214, 53, 57, 33,147,192, 37, 4,153,155, 34, 41, 0,200,204,242,160, -184,144,255,234,213,171,165, 21, 21, 21, 10,115,228,159,154,154,138,140,140, 12, 78,228, 15, 0, 73, 73, 73, 24, 61,122,180,116, -244,232,209,118,217, 99,200,158,121, 93,241, 14, 90,144,255,146,153, 18,172,220,172, 98, 85, 87, 30,202, 20, 50, 48, 68,136,122, - 37,193, 43, 79, 73,112,164, 72, 11,101, 61, 65,131, 26,144,134, 23,161,232,162,142, 83, 52,160,244,250,135,164,234,102, 39,184, -119, 22,195,175,187, 27,186,118, 11,198,213, 18, 53,122, 15,208,192, 73, 82,129,188, 45,183,177,101,203, 22, 50,125,250,244,118, -233,240,100, 50,153,179, 79,143, 30, 11,191, 61,114,148,138,237,215,247, 37,153, 76,246,174, 92, 46,111,180,199, 94, 87,191, 30, - 11,191,219,123,132,138, 14,239,103,151, 61,153, 76, 38,246,243,235,190,240, 39,197, 1,106,248,144, 48,115,182,232,118,168,182, -230,237, 7,179,178,178, 20, 9, 9, 9,216,188,121,179, 98,242,228,201,173,218, 48, 34, 34,130,188,245,214, 91, 72, 72, 72,176, -216,190, 34,145,104,146, 88, 44, 30, 40, 22,139, 23,136,197, 98,215,235,215,175,163,111,223,190, 16, 10,133,112,119,119, 71,113, -113, 49,220,220,220, 68,199,142, 29,243, 60,124,248,240,129, 23, 95,124,177, 55,128,171, 0,196,230,234, 32, 57, 57,185,149,179, - 98,216,111, 49,229, 20, 69, 33, 51, 51,211,234,253,183,117,235, 86,179, 54, 12,203, 9, 33,136,139,139,227, 84,161, 57, 57, 57, -118,125,191, 45,113,234,212,169,200,240,240,240,124, 71,216,186,117,235, 22,161,105, 26, 16, 84, 65,221,168,130,216, 89, 2,208, -158, 16, 8, 4,232,214,173, 27, 53,216, 56,114,105, 33, 25,206,195, 15, 63, 76, 54,111,222, 12,115,246,102,206,156,137,131, 7, - 15, 82,182,158, 31, 0,148,223, 58, 79, 12,207,207,158,107,183, 37,154, 96, 46, 13, 48, 43, 1,192,150,252,217, 34, 53, 53,213, -234, 49,108,136,203, 28,249,175, 88,177, 2, 75,151, 46,109, 81,110,171, 8, 72, 30,150, 73,208, 37, 4,153, 63, 69, 82,134, 30, -127,116,116, 52, 5, 0,204,107,113,113, 49, 97, 67,214,150,200,191, 41, 50, 96,213,107,103,194,244,134, 30,190,241,208,130, 45, -246, 44,121,248, 75,102,178,223, 41,206, 71,249, 10,233,251,144, 16, 46,206, 20, 30,242, 23,226,118, 37, 13,141, 86,136, 59, 85, - 4,213,117, 4,197,191,211,128, 0,240,113, 61,131,188,188,188,200,168,168, 40,139,157,194,213,107, 31, 68,134, 6, 7,225,240, -205, 91,232, 19,208, 21, 3, 7, 7, 66,232,236,141,135,250, 84,162, 82,169, 66,197, 77, 29,126,191,165,130,171,168, 20,121,121, -238, 86,237,181, 17,230, 60,181,120,177,184,180,187, 63,156,135, 13, 23,168, 14,236,159, 3,224, 43, 27,236, 48,158,248,156,167, - 95, 90, 36,254, 93,236, 7,183,144, 8, 65, 77,225, 65, 91,237, 1,192,156, 23, 23,190, 44,134,179, 59,250,244, 11, 19, 92, 56, -123,194, 30, 91,142, 4,205, 60, 35, 20, 69, 65, 34,145, 72, 1, 40,140,239,137, 97,195,134,177, 34,127, 0,112,114,114,242,148, - 72, 36,115,111,223,190,237, 26, 18, 18,130,161, 67,135, 66, 36, 18,225,147, 79, 62,129, 78,167,195,160, 65,131,240,227,143, 63, -226,216,177, 99, 56,115,230, 12,132, 66,225,103, 58,157,110,170, 37,155, 83,167, 78,109,238,231,172,245,131,108, 8, 87, 46,151, - 75,253,252,252, 20,132, 16,139, 14,208,205,155, 55, 57,239,149,193,216,182,245,251, 12, 81,159, 63,127,222, 98,191, 17, 26, 26, - 42,229, 74,230,231,207,159, 87, 84, 87, 87,195,195,195, 67,106,143, 16, 56,113,242, 16,121,235,157,249,232,212,201,165,213,103, -245,245, 74,228,252,120, 26,103,228,114,106, 74,247,238,228,122, 98,162,249,190,253,192,106,125, 99, 30, 88,141,238,147,226, 33, -137, 24, 14, 93, 72, 88,203,240,217,119, 27,224,245,254,116, 12, 48, 24, 42, 82, 62,250, 60, 62,183,114,126,203,210,230,193,187, -139,171,190,224,141,143,144,178,232, 25, 0,192,221, 59, 13,120, 47,125, 45,137, 24, 58,214,102, 17,224,232, 33, 5,139, 2,128, -241,216,173,121,234, 29, 5,165,165,165, 88,186,116,169, 77, 2,194, 18,244,158,126, 50,181,103,207, 30,146,149, 57, 18, 16, 43, - 9,155,177,127, 83,100,109, 76,202,150,134, 5,204,193, 80, 80, 28, 57,114, 68, 49,122,244,232, 22,161,127,174,246,254,187,216, -205,108,231, 54,103, 85, 61,107, 59, 52, 77, 71, 58,187, 82, 16, 8, 0, 87, 23,160,170,134, 70, 35, 33,232,228, 66, 65, 69, 3, -202, 70,130,158, 93, 5,160,181,192,165,235, 58,148,150,150, 42, 96, 33, 61,237,185,162, 31, 34, 7, 14,236,175, 16,139, 9, 94, -152, 59, 10, 58, 29,193,205, 10, 53,174,221,168, 2,156,174,195,197,171, 17,229, 21, 87, 32, 16, 87,227,220,185, 42,120,120, 89, -182,215, 86,112,246,246,126,227,241,191,253,205,249, 53, 26,240, 90,154,230,118,235,244,169,215,109, 36, 89, 2, 0, 18, 15,239, - 55,254,239,201,191, 57,175,186,172, 67,207,217,169,110, 23, 74,207,152,178,103,117, 71, 54,153, 76,134,206, 30,158,111,204,121, -242, 41,231, 51,215, 42,145,248, 68,178,219,191,223, 73,177,245,220,204, 70,242,204,149, 91, 17,222, 58,230, 25,137,143,143, 71, - 84, 84, 84,126, 86, 86, 22,148, 74,101,115, 27, 50,158,127,124,124, 60,171, 54,117,118,118, 30, 91, 95, 95,223, 63, 52, 52, 20, - 82,169, 20, 41, 41, 41,120,238,185,231,244,157,185, 70,131,245,235,215,163,160,160, 0, 39, 78,156,192,247,223,127, 15,165, 82, - 25, 76,211,116,172, 37,155, 83,166, 76,113,232,253,180, 99,199, 14, 86, 67,115, 20, 69, 41,184,134,240, 13,109,219,242,253,166, -208,112,126,117,117, 53,202,202,202, 76,126,238,239,239, 15, 91, 9,188,172,172, 12,101,101,101,118, 9,129, 51,167, 47,226,155, - 13,219, 49,126,252, 88,132, 13,234,209, 92, 94,116,246, 6, 14, 28, 56,132, 31, 55,255, 76,178, 94,125, 21,215, 19, 19,225, 50, -110, 28,148,191,252, 98,210, 78,230,248, 20, 10, 0, 46,109, 88, 67, 6, 87,236,198, 83,123,183, 67, 23, 18, 6,229,162,229, 0, - 0,151, 85,203,225,118,177, 8,139, 75,197,232,251,244,130,123,245, 88,127,239, 57,181,116,126, 81,209,227, 90,157, 95,222,158, - 95,112,230,244, 69, 68, 12, 29,107,243,253, 99,203,144,130, 97,184,223, 82, 52, 64,196,213, 99,119, 52,209,218,139,172,172, 44, -187,190,159,156, 41, 35,232, 14,100, 38,232, 59,174,204,130,228, 22, 97,126,189,199, 95, 77,140, 35, 1,108,201,186,162,162,162, - 5, 57,219, 66,214,108,193,136, 14,153, 76, 70,172,229,131,182,228,217, 48, 96,194,255,230,236, 17, 66,200,237,115,175,160,123, - 83,232,191, 89, 49,235, 8, 84,106, 64,211, 84,166,209, 18, 16,129,254,253,217, 51, 5,204, 42, 1,147,112,119,175, 86,212, 43, - 5,240,241,246, 68,213,221, 6, 84, 85, 87,225,200,241,155,184,113,139, 64,220,169, 1, 61,130,235,160,108,184,141,190,131, 53, -232, 29,218,136,239,191, 40,192,238,221,187, 35,239,227, 45, 39,144,201,100, 81, 51, 95, 72,238, 86,230,225,133, 18, 45,224, 18, - 53, 25, 2,175, 46, 62, 50,153,108,178, 92, 46,255,201,128,172,157, 96, 48,238,109,174,223,151,201,100,209, 73,115, 95,232,246, -135,192, 3, 87,235, 52,240,140,136,130,200,221,203,216, 30,192,110, 2, 91,204,180,233, 51,186, 17,161, 51,170,235, 27, 49,112, -216, 24,184,117,246, 48,101,171, 93,192,120,255, 20, 69, 97,219,182,109, 36, 62, 62, 30,219,183,111,135,139,139, 75,100,106,106, -170,130, 11,249, 3,112,174,170,170,122, 90,163,209, 8, 92, 93, 93, 49, 97,194, 4,172, 90,181, 10, 78, 78, 78,144,201,100,216, -176, 97, 3, 10, 10, 10,112,228,200, 17,252,252,243,207, 56,123,246, 44,124,124,124,124,180, 90,237, 67,176, 50, 4,146,156,156, - 76,172, 13, 1,124,241,197, 23,172,206,179, 45,135, 0,182,110,221,234,144, 33, 0, 15, 15, 15,105, 89, 89,153,194,220,103,246, -182,187, 45, 66, 64, 90, 82, 66,238,172, 92,137, 15, 0,224,240, 97,220,157, 25,135,213, 67, 66,154, 67,246, 97, 3, 6, 96,214, -236, 41,232, 93,121, 27,215, 19, 19,209,101,201, 18, 40,130,130,168,193,191,252, 98,241, 57, 17, 75, 31, 70, 72,108, 36, 22, 47, -121, 23,255, 66, 17, 86,143,158,132,129, 35, 70, 33,248,110, 41,214,123, 14, 69,169,199, 45, 12,146, 72,136, 74,165, 98,213,190, -210, 73, 67,240,212,211,241, 56,250,235, 89,236,206,253, 9,111, 2, 88,189,106, 29,194, 6, 12,192, 83, 79,199,163, 65,121, 7, - 18, 14,246,140, 97,239, 28, 0, 78, 17,128, 7, 9,114,185,156,114,196,172,117,134,220,179,150, 94, 6,132, 98, 36, 79,238, 13, -120,246, 70,102,211,130, 37,182, 99,255,142,134,225,181, 49,147,254, 12, 61,127, 99, 48,115, 3,204, 77, 6,180,101, 39,194,141, -139, 58,153,141, 8,184,215,164,224,138,154,224,230,109, 26,128, 0,110,174,250, 16,167, 70, 75,160,106, 4, 84,106, 64,213, 8, -168, 53,128, 74, 9,168, 27,239, 69, 73, 76, 9, 10, 55,237, 43,228,198,181, 0,244,234,227, 6,226, 36,194,109,165, 18,138,125, -215,113,174,248, 6,238,222,173, 67,216, 48, 29,234, 85, 90,168, 26,117, 80, 54,208,184,121, 13, 80,214, 3, 91,182,108, 81,112, -217, 0,195,206, 54,161,133,158,158,111, 60,243,234,171,146,239, 13, 40,196,235,213, 52,183,187, 75, 23,189, 14,224, 39, 3,178, - 86,179, 48, 73, 68,110,158,111, 60,247,242, 82,201,174, 27,186,230,194,158,143, 47,117,187,250,229,171,134,246, 88, 69, 1, 92, -221,220, 95,127,233,149, 69,146,146,178,123,187, 69, 38, 60,145,236,246, 93,230,106, 83,182, 56, 61,107,166,238, 37,142,207, 26, - 97,188,127,137, 68, 34,141,138,138,202,103,150,140, 42,149, 74, 69, 65, 65, 1, 21, 31, 31,207,214,150, 22, 64, 48, 0, 58, 60, - 60,156,150, 72, 36,130, 13, 27, 54,224,217,103,159,197,251,239,191, 15, 66, 8,126,253,245, 87,236,219,183, 15,103,206,156, 65, -117,117, 53,250,246,237,139,154,154, 26, 87,129, 64,224,107,205,248,180,105,211,204,138,100,102,104, 96,202,148, 41,156,194,244, - 29,117, 8,192, 82, 20,192, 30,239,223, 94, 33, 80, 89, 85,213,252,222, 55,109, 30, 6,166,205,199,120,163, 99, 46, 63,250, 28, -122,238, 63,142,146, 69, 47,224, 87,127,127,184, 0, 56, 35,151, 83, 48,177, 44, 78,169, 84,146,158, 61, 59,227,234, 53, 32, 44, - 34, 20, 88,249, 26, 94,254,114, 11,230, 6,157,198,144,198, 98, 44,190, 37,198, 59, 27,151,225,253,244,207,113,230,236, 65,244, -234, 25, 70, 92, 92,204, 71,125, 13,237,121,119,113,197,163,113,163,240,104,220, 40,188, 69,127, 4,117,227, 82,156, 60, 9,156, - 60, 9, 28, 56, 16,143,127,175,185,136,184,184, 88, 18, 16,240, 16,130,130,190,225,196, 79,121, 15,191,134,146,131, 34, 43,125, -247,231,127, 13, 1, 32,147,201, 72, 82, 82,146,148, 25, 51, 52, 22, 1,134, 29, 18, 51, 30,111,235,124, 0,134,244,163,163,163, - 41,253, 48,128, 24,153, 27,239,239,245, 50,179,254,163,162,162,168,188,188, 60, 98, 45, 26, 98,109,217,161, 37, 66,231, 58, 28, -240,244,171,245,240,239, 38,192, 19, 9, 98,168, 26, 1, 15,119, 10, 2,170,201,235, 7,129,170, 1,168, 87, 19,212, 43, 9,234, - 85, 4, 52, 1, 4, 22,230, 92, 63,189,176, 30,131,134,148,194,175,255, 93,236,217, 85,129,187,119, 85, 8, 31, 83,131,193,222, -117,128, 83, 35, 84, 13, 52, 42,110, 16,212,215, 83,208,106, 41,120,251, 80, 0,117,223,231,178,133, 13, 29, 50,100,184, 87, 64, - 0, 14,233, 12,196,203, 19, 79,226,110,106,202, 48,153, 76, 54, 64, 46,151,159,227,112, 63,135,142, 24, 55,113,120, 23,255, 0, - 28, 63,218, 60, 71, 14, 93,165,255,135,171, 95, 44, 53,101,207,210, 86,216, 3,198,141, 27, 63,220,223,191, 39,206,157,184,220, - 92, 62,238,145, 41,248,159,124, 21,231,115,107, 3, 52,159, 59,243,252, 50,195, 0, 12,182,111,223,222,106,254,145,137,185, 0, - 76,163, 7, 3, 56,181,100,201,146,177, 34,145,200,237,235,175,191,198,186,117,235,240,204, 51,207, 96,197,138, 21,160, 40, 10, - 87,174, 92,129, 82,169, 68,106,106, 42,180, 90, 45,230,205,155, 71, 83, 20,101,245, 1,112,228,108,250,142, 62, 4, 96, 41, 10, -224, 8,239,223, 86,108,216,176, 1,127, 75,158,133,234,170, 70, 32,125, 45,234, 15, 28, 71,167,241,195,155, 63,175, 72, 95,139, - 34,103,103, 80,255,120, 30, 3,103, 63,138,195,235,119, 97,240,224, 17,102,237, 93,186, 84,136, 49,227, 98, 81, 88,228,133,181, -159,101, 97,252,248,177,120,231,211,101,120, 43,106, 14,190, 5,208,255,169,103,177,246,179, 44,136,197, 94,152, 58,109, 56,190, -230, 96,239,227, 15, 54, 97, 68,252, 32,188, 59,104, 21, 10,167,184,193, 43,225,199, 22,199,250,184, 74,112, 52, 95,129,128,191, -205,229, 92, 15, 7, 15,138,176,114,165,139, 21, 1,247, 23,138, 0, 24,143, 35,155, 35,248,166,227, 88, 35,179, 64, 63, 67, 93, - 79,252,151,144,245,201,101,232, 87, 1,180, 20, 5,108,134, 1, 28, 29,214,207,203,203, 35,134,222, 63, 19, 17, 48,252, 63, 41, - 41, 9, 76,178, 28,115,137, 33,184,144, 63,179, 10,192,156, 61,173, 14,168,111, 32,104, 84,235, 39,251, 53,170, 9, 68,206,247, - 62, 83, 53, 0, 74, 13,193,157,187, 4,127, 84, 18,156, 56,167, 5, 77, 3, 73, 73, 73,210, 75,151, 46,181,106, 27,173, 22, 40, -187,174,198,245,146, 74, 28, 60, 92, 9, 66, 40,156,251,141, 70,252, 19, 90,136, 69, 4,127,220, 2, 14,254, 4,212,212, 16, 16, - 26,120,120, 18, 5,137, 4,136,141,157,138,171, 87,175,178,186,166,236,245, 50, 50,109,174,237,171, 68, 4,110,157, 95,125, 97, - 69,134, 83, 14, 17,180, 96, 98, 31,103,103, 56,253, 99,161,211,149, 53, 31, 45, 3,240, 36, 91,123, 66, 23,183,101,243, 95, 95, -225,244, 83, 25,105, 97,175, 75, 39,103, 12,156,253,162,211,185, 77,159, 24,219, 51, 27, 1,144,184,116, 90,182,244,141,229, 78, -151,111, 86,183, 56,160,179,123, 39, 76,127,226, 25,167,156,255,126,197,233,220,218, 42,106,103,170, 44, 34, 34,130,156, 56,113, - 2,219,182,109,107,245,157,132,132, 4,147, 77, 1,160, 16,192,169,213,171, 87, 15,241,244,244,116, 99,194,224, 95,125,245, 21, -158,125,246, 89,172, 91,183,174,217,139, 95,189,122, 53,170,170,170, 80, 83, 83, 83,215,208,208, 80,218, 20, 65, 16, 91, 58,215, - 23, 94,120,129, 24,135,232, 25,239,159,109,248,255, 65, 25, 2, 48, 21, 5,112,180,247,207,216,100, 59, 4,112,110,204, 24, 80, - 47,204,134, 39, 0, 50,105, 24, 26, 78, 20,162, 62,125,237,189,122, 75,158,133,190, 79,205,130, 68,162,191,254,162,162, 98,139, -132, 93, 84, 84, 12, 0,136,141,211,139,136,130,227,103,240,237, 55,223,193,117,212, 72, 52,104,180, 80, 67,141, 9, 19,135,182, - 56,158,173,189,235, 58, 53,158,232,246, 34,232, 19,141, 72,250,215, 36,136, 31, 59,130, 1, 97, 3, 16, 54, 48,184,249,252, 82, - 23,175, 65, 80,144,144,245,125,243,200,255, 61, 18,117, 14,231,246,224,127,223, 80,214,166, 0,124,254, 57,218, 38, 17, 80, 71, - 68, 65, 65,129,213,217,228,121,121,121,145,172,151, 20, 58,119, 66, 86,239,253,128,182,128,160, 79, 39, 36,167,247, 65,102,126, - 60, 5,100,146,123,130, 32,218,230, 97, 0,227,165,128,230,150, 6,154,235, 44,101, 50, 89, 51,249, 27, 79, 0,100, 66,234, 76, -153,165, 8,128,161, 61, 71,117,230, 59,119,238,140,188, 81,190, 75, 65,119,165, 33, 16, 1, 78, 2,253,253,173,161, 9,180, 90, -160,182,150, 64,173, 1,180, 26,189, 40,152, 58, 77, 31,189,185,116,233,146, 89,123,141,183,119, 42,194,194,104, 28,216,167, 3, - 37, 0,254,184, 73, 65,226, 2,236,219, 13,168,149, 20, 40, 2, 12,142,112, 66,217, 53, 26, 19, 39, 78, 65, 92, 92, 28,197, 38, - 19, 86,246,122, 25, 89,249, 34,176,228, 83,219, 69, 0,161,117, 49,186, 46, 62,130, 93,244, 61, 22,234, 6,192,143, 2,148,195, -134,137, 46,107,117, 49,156,236, 17, 58, 6,238,222, 2,197, 77, 93,179,189,174, 18,192, 71, 66,193,117,208, 48, 81,209,119,116, -140, 57, 47,218,148,173, 78,238,158,130,171,183,170,154,136, 5,112,119,113,134,187,171, 24, 17,225, 67, 69, 91,190, 37, 49,237, -252,232,154,172,115,102,214,127,124,124,124,243, 61,202, 68,239,102,206,156,105,201, 3,173, 3,112,249,228,201,147,117,227,199, -143,239, 10,131, 53,253, 95,125,245, 85, 51,201,106, 52, 26,232,116, 58, 92,186,116, 9, 93,187,118,189, 77,211, 52, 43,181, 56, -109,218, 52,179, 67, 0, 92,136,246, 65, 24, 2, 48, 21, 5,112,164,247,207,133,248, 25,116,247,247,196, 23, 95,236, 69, 98,194, - 24,116, 27, 22, 6, 12, 11, 3,245,194,236,150,162, 23,192,173,155, 74,108,221,118, 24,221,253, 61,217,219,243,115,193,176,225, -125, 49,108,120,223, 86,199,113,181, 55, 97, 70, 40,210, 38,126, 2,186, 80, 79,254,207, 45,126,218, 38,123,198,120,213,253,213, - 61,239,215,190, 31, 93,142,242, 54,123, 32,237, 18, 0, 5, 5, 5,247, 61,107, 31,227,229, 50, 68, 23, 21, 21, 69,153, 32,127, -194,132, 21,147,146,146,108,250, 29,195, 85, 0, 76, 25, 87,207,223,120, 2, 96, 19,154,203, 82, 82, 82, 20, 73, 73, 73,172, 31, - 50, 67,242, 55, 53, 39,128,171, 61,107, 88,185, 89, 5,107,246,226,226,226,242,151,165,110,197, 35,163,157, 64, 3,208,168,105, - 56,139,245,213, 84, 91, 79,208,168, 33,208,234,128,130, 66, 29,116, 52,129,181, 37,123,113,113,113,249,111,188,182, 21, 19, 35, -133,152, 62, 71,136,186, 90,130,218,106,160,190,150, 66,159,190, 4, 58, 13, 5,145, 64,130,170,187, 52,202,126, 87, 99,209,203, -236, 38,140,101,175,151,145,143, 22, 2, 33, 1,192,154, 87,128, 5, 31,216, 38, 2, 72, 67,253,140,127, 12, 27,186,211, 47,103, -167,155,215,184,135,209, 13, 64, 55, 10,208, 29, 58,136,188,167,159,172,211, 52,212, 79,231, 98,143, 86, 53, 76,127, 33,106,248, -174,208,183,178,221,124, 7,143,133,143, 51,133,174, 18, 10,202,243,191, 96,235,107,115,235, 52,202, 6,214,246, 26, 85,202,233, -113,143,140,223,149,146,254,153,219,128, 33,195,224,238, 42,134,187,139, 51, 74,206,157,194, 27,169, 47,213, 41, 57,216,178,197, -147,103,115,185,166,200,127,249,242,229,173,194,252, 63,252,240,131, 34, 33, 33, 1,102,146, 4, 49, 68,175, 6,112,170, 95,191, -126, 37, 42,149,170,135, 80, 40,148,184,186,234,151, 98,109,222,188, 25, 51,103,206,132, 82,169,132, 74,165, 66, 99, 99, 35,220, -220,220, 84, 58,157, 46,135, 16,114,147,205,201, 58,106, 53,192,131, 50, 4, 96, 24, 5, 96,222,183, 7,241, 51,232,211,199, 15, -175,166, 37, 99,247,174, 95,145,189,229, 4,156,197,157,241,123,217,189, 17,172,158,254, 3,208,168,174, 65,196,176,254,248,240, -163,100,188,159,254, 57, 39,123,190,190, 30, 40, 58, 87,212,252,121,216,128, 48, 84, 84, 84,115,178, 55,101,225,116,204, 20, 60, -137,198,194, 58,140, 94, 48, 16,244, 96, 9,190,248,226,251,230,243,171,174,174,198,216,135, 67, 89,217, 51, 70, 84,102, 20,245, - 51,126,110, 83, 62,181, 89, 0,180, 5,249,179,177, 25, 21, 21, 69,101,101,101,145, 38,111, 23, 89, 89, 89,196,112, 89,162,177, -215,111, 74, 32,180,142,195, 82,128, 88, 0,184, 8, 1, 55, 17,208, 88,139,172,247,157, 0,151,163, 36,249,177, 62,128,139, 55, - 50,191,225,238,245, 91,154,237,207,144, 53,219, 53,236,198,228,111, 60, 39,128,171, 61,182,228,207,198,222,123, 25,107,169, 87, - 22,206, 35, 18, 9, 64,211,192,160,126,194,123,237,113, 86, 7,141,142, 64, 71, 11, 49, 99,198, 12, 86,226,228,237,119,215, 82, -139, 22,205, 35, 90, 45,160,214, 16,232,180,128,128, 2, 34,167, 0,181, 85, 20,126, 59,173,132, 82, 37, 64, 98,194, 12,214, 97, -255,229,207, 1,193, 61,245,255, 7,245, 0,108,141, 4,200,229,242, 35, 50,153, 44,246,230,212,184, 93, 1, 91,119,186, 5,140, -123, 24,154, 67, 7,241, 99, 66, 92,157,186,182, 54, 86, 46,151, 31,228,104,239,160, 76, 38,139, 61,255,230,180, 93,254,255,202, -113,235, 49, 98, 28,234,207, 31,194,198,127, 76,173,107,108,224,102,143,177,181, 58,237,239,187,222,249,248, 75,183,209, 99,198, -162,184,232, 20, 94, 74,126,178,174,161,174,142,243,185,181, 53,204, 37,251,145,201,100, 36, 62, 62,158,205,106, 0,161,167,167, -231, 41,165, 82,249,109,105,105,105,239, 33, 67,134, 4,106,181, 90,145,147,147, 19,114,114,114, 16, 29, 29, 13,149, 74,133,134, -134, 6, 92,186,116,169,198,203,203,107,175, 82,169,252,154,166,233,122,176,204, 0,200, 36, 5, 98, 66,236, 92, 66,255, 15,218, - 16,128, 97, 20,192, 17,237,107, 75,238, 0, 83,120, 52,118, 20, 30,141, 29,213,244,159,253, 26,182,165,189,105,246,137, 59,207, - 31,208,120,186, 14, 79,127, 54, 5,239,236, 93,102,247,185, 41,159, 81, 18, 47,173, 23, 84,223,168,238,139, 99,109,147, 0,104, - 15,207,223,216,251, 48, 12, 99,155, 11,245, 59,242, 28,185,140,253, 59,154,252, 13,196,142, 97, 34, 32, 70, 4, 41,154, 34, 29, -156,236, 89,155, 11,192,213,222, 7, 31,175,165,100, 50, 25, 17, 8,128,131, 5,250,177,126,102,194,159,126,220,127, 6, 39,123, -171, 86,173,165,230,205,111,202, 73, 33,208,219, 56,186, 31,168,175,163, 65,104, 32, 49,113, 10, 98, 98, 98,172,182, 71,246,122, - 25, 73,125, 18,240,116, 3,202,110, 3, 46,206, 0, 77,128, 78, 18, 32, 93, 6,164,201,109, 18, 1, 7,101, 50, 89,108, 65, 98, -220, 46,143,229,111,187,229, 47,127,163,174,209, 6,242, 55,182,151,191,100,234, 46,151,127,188,233,150,251,239,183, 56,147,191, -161,173, 23, 95,124, 49,238,141,127,190,176,115, 65, 74,170,219,103, 31,102, 48,228,127,218,196,179,175,229, 98,219,218,208, 17, -215,231,205, 20,249,207,155, 55,143, 48, 43, 1,182,109,219, 70, 40,138,178, 36, 4,220,212,106,117,157, 64, 32,200,243,247,247, -239, 89, 91, 91,251,226,241,227,199,187, 15, 29, 58,148,214,106,181, 13,213,213,213,183, 78,159, 62,125,165, 79,159, 62, 37, 93, -186,116, 41, 85, 42,149,155,181, 90,237, 45, 66, 8,107, 1,192, 36, 5, 50,136, 10,216,210,190,210, 54,236, 11, 29,110,219, 81, -227,254,246,218, 81, 41,133, 14, 61,222,209,246,170, 42, 5,200,208,202, 16,120,216, 15,179, 63,181, 46, 76,170, 42, 5,120, 40, -192,242, 49,247,147,252,205, 10, 0,107,107,253,185, 62,232,108,115, 7,112,177, 43,151,203, 41,115,155,237,112, 33,175,204,100, -185, 62,204,127, 17,192, 69,227, 79,171,155,254, 46,195,134,235, 85, 56,138, 92, 13,235, 69, 38,147, 17, 38,207, 64, 74, 74,138, - 77, 43, 28,140,237,109, 92,212,169, 89, 20,216, 35,154,140,219,132,153,240,103,107, 84, 98,237,231, 45,237,213,213,232, 59,224, -196,196, 68,110,247,223,183, 14,125,102, 52,134,164,189,111,249,155, 27, 26,107,107,159,182,215,187,102,236,253,244,217, 91, 27, - 84, 13,181,115,229,114,249, 33, 91,109,125,250,233,167, 7,100, 50, 89,236,103, 31,173,220, 80, 87, 87,103,238,220,180,184,255, -104,209,163, 26,147,127, 94, 94, 94, 36, 33, 4,219,183,111, 55, 60,198,146,189,107,106,181,218,153, 16, 82, 75,211,180, 92,173, - 86,255, 26, 16, 16,224, 83, 85, 85, 69,189,254,250,235, 53,213,213,213,119,122,244,232, 81, 91, 87, 87, 87,175, 86,171,107, 52, - 26, 77,163, 78,167, 83,114, 57, 97, 7, 13, 3,228,183, 97,157,230,227, 79,138,126,253, 6, 83,111,190,150, 73,102, 61, 30,141, -176,129,125,204, 30, 87, 84,120, 25,155,190,219,131,126,253, 6, 83,247,211,222,144, 33, 67,168,212, 69,114, 50,235,241,104,203, - 14,243,241, 82,108,250,110, 15,134, 12, 25, 98,245, 94,186,159,228,111, 82, 0, 56,218,179,111,203, 72, 65, 84, 84, 84, 62,171, - 16,191, 21, 56,114, 86,255,253,136,140,112,217,244,199, 17,209, 0,174,109, 98,184,172,203,222, 33, 9, 99,123, 92,201,223,158, - 25,255,108, 72, 27, 64, 80, 71,180,231,232,115,115,208,189, 77, 1, 0, 69, 81, 68, 32, 16,128,249, 99, 66,216, 83,166, 76, 65, -108,108, 44,104,154, 6, 77,211, 32,132, 88,251, 61, 74,171,213,186, 18, 66,116, 52, 77, 55,106, 52,154,253, 66,161,144, 18, 8, - 4,206, 0,156,105,154,134, 78,167, 19,106,181, 90,177, 86,171,237,174,211,233,206, 27,124,183,205, 55, 1,226,225, 24, 17,112, -165, 84, 69,118,239,220,130,107, 21, 53,240,243,106,104,254,236,102,165, 43, 2,124, 59,163,127,255,254, 86,201,186,173,236, 13, - 25, 50,132,186, 89,214, 72,214,124,180, 3,197,191,223,110,101, 47,184,167, 15, 2, 3, 3, 89,145,127, 91,193, 82,142, 20, 42, - 60, 60,156,223, 30,147, 7, 15, 30, 15, 42, 26, 12, 8,157, 54,112,108, 68, 6,229,229, 0, 60,160,159, 52,206, 19, 63, 15, 30, -230, 34, 0, 60,120,240,224,241, 0, 65,210, 36, 2,104, 3,226, 23,224,222, 16,135, 8, 64,247,166,247, 52, 95, 93, 60,120,240, - 2,128, 7, 15, 30,127, 14, 8, 0,184, 25,252,207, 16,191,216,128,244,233,166,227,120,239,159, 7, 15, 94, 0,240,224,193,227, - 47,210,167,241,164,207,131,135, 5,245,204,131, 7, 15, 30, 60,120,240,248, 43,171,229,249,243,231, 27,110,164, 67, 12,103,216, -203,100, 50, 98,180,209,206,181,168,168,168,230, 85,141,166, 82,177, 26,218,227,138, 63,163, 61,227,101,139,134,245,201,215, 31, -223, 30, 29,221, 94,122,122,122,243, 49,105,105,105,148, 13,246, 0, 51,233,128,249,251,217,186, 77,254,249,229,237,113,177,199, - 89, 0,112, 68, 87, 54, 7, 49,187,247, 57, 74,177, 24, 39, 35, 49,181, 27,160,169, 99,218, 67, 93, 49, 4,147,148,148, 36,101, -136,134,201, 0,102, 41, 39,248,253,196,246,237,219, 35,183,109,219,214, 76,130, 83,166, 76,145, 38, 38, 38,230,255, 25,213,174, -169,246, 56,127, 94,191, 50, 44, 52, 52,180, 93,207, 77, 38,147,145,169,211,100,200,201,150,155,188,103,119,238, 58, 65,114,178, -229, 22,239,229,157,187, 78, 88,236, 4,226, 98, 35,108,190,233,210,211,211, 73, 66, 66, 80,139,255,173,137, 0,107,168,173,171, -141,220,250,211, 86, 4,134, 5, 42, 64, 1,231, 79,158,147,142, 9, 31,139,208,126,161,156,238,191, 67,135, 14,181,186,238,177, - 99,199, 82,224,193,131, 71,155, 9, 0, 49,219, 3, 71,143, 30,205,217,184,169,205, 98, 24,152, 34, 81,227,141, 54,216, 18,173, - 45, 27,227,176, 17, 20,140,221,212,212, 84,100,100,100, 40,204,237, 45,206, 28,103,105,173,166,241, 57,246,232,211, 11, 0,112, - 75,165,130, 86,217,168, 47,172,170, 1,160,223,251,128, 75,110, 4, 67,242, 7,244,185,197,185,172,181,151,201,100, 68, 64,233, -179,235, 49,175,128,136, 87,212,158, 0, 0, 14,255, 73, 68, 65, 84,229,247,159,175,189,255,130,204,184, 61, 24,226,183,181, 61, - 28, 41, 42, 25,242,143,139,141, 80, 1, 50, 73, 78,182,220,230,223, 96, 4,132,105, 1, 32,183,235, 60,213,234, 84,228,230, 38, - 35, 38, 38, 19, 9, 9, 25,205, 17, 1, 91,132,192,193,162,131,228,161,161,189,240,161,124, 21,188, 92,189, 64,107,117, 80,145, - 70,197,238, 95,127,138,217,187,239,103, 50, 54,112,156, 84, 34,145, 88, 21, 2,135, 14, 29, 34, 77,145,133, 86, 30, 17, 47, 2, -120,252,149,113,234,212,169, 22,255,155,234,211,236, 17, 0,156,230, 15,152,218,197,206, 17, 32, 64,164,221, 54, 8,123, 13,192, -198,115,151,201,100, 36, 53, 53, 21, 43, 86,172, 0,128,230, 87, 83,199, 89,219, 33,172, 21, 60, 59,227, 76,233,119,112, 65, 79, -232,240, 11, 42,254,115, 2,167, 75,238, 96,198,138,117,237,118,163,157, 57, 91,136,193,131, 6,130, 38, 64, 97,161,254, 61,112, -239,189, 97, 57,205,178,170, 13,115,176, 91, 66,102,102, 38,197,182, 61,230,206,157, 11, 0,205,175, 38,201,159,162, 0, 11,247, -131, 76, 38, 35,143, 60,178, 11, 50, 89,172, 67, 69, 64, 92,108, 68, 67,114,114,178, 43,144,137,156,108,110,196,110,232,225,219, - 75,242,230,188,127, 0,152, 57,115, 51,114,115,245,175,201,201, 37, 96, 34, 2, 92,162, 1,132,144, 72,197,133,189,138, 23,255, - 49, 31,195,187, 14,133,139,135, 7,136, 90, 11,154,232, 32, 20,137, 17, 28, 21,156,251,219,176, 11, 88,145,153,161, 24,229, 51, - 90,234,234,234,106, 85, 4,220,190,125,187,197,255, 83,198,119,194,168,133,191,224,241, 12, 85,139,134,156, 52,105,146,205,237, -149,157,157, 77,166, 77,155,230,176,246,118,180,189, 54, 38,146, 72,123,211,250,158, 58,117, 42,178,137,132,108,181, 51,248,149, - 87, 94, 41,175,175,175, 15, 0, 48, 25,250, 77, 56, 67, 1,156,130,126, 83, 40, 0,216, 40,151,203,127,227,169,191, 53,249, 51, -101,198, 34,160,133, 0, 40, 45, 45, 37,165,165,165, 0,128,192,192, 64, 24,110, 54, 3,160,197,255,166, 62, 55,135,138,138, 10, - 69, 86, 86, 22,235, 72,128,241, 94,247,150, 72,152,106, 74,133,105, 76,162, 92, 67,236,153,153,153, 86,143,201,203,203, 99, 69, -254, 73, 73, 73,102, 73,127,233,210,165,200,200,200,128,161, 64, 96,131, 30,125,122,225, 70,101, 53,126,156, 55, 19, 93,168,113, - 40,249, 98, 17, 2,167, 7, 98, 79, 59,147, 63,128,102,194, 7,128,129, 3, 7,182, 40,103, 34, 3,134,229,142,246,236, 45, 17, - 49,211, 30,230, 72,127,253,250,245,200,200,200, 64,236,184,161,216,245,203, 73,192,189, 19, 80, 83,119,223,235,112,231,174, 19, -174, 64, 38,118,238, 58,225, 16,123,211,106,150, 89,124, 54,179, 59,191,199,234, 1, 49, 12,253, 39, 39,231, 34, 33, 33,168,249, -149, 65, 66, 66, 16,107, 17,240,197,255,190,192,251,159,190,139,241,125, 35,161,107,108,132, 86,167, 5, 37,162, 0, 8, 65, 64, -227,214, 31,101, 8,237,218, 31,203,230, 45,195,187, 43,223, 85, 60, 50,208,122, 52,203,184,179,155,226,191,222, 36,225,239,221, -187,151,216, 34, 2,178,179,179,201,206,215,119, 33,238, 29, 56,132,180,179,179,179,201,202,149, 43,177,100,201,146, 14, 45, 2, - 78,157, 58, 21, 89, 93, 93,173, 40, 43, 43, 67,120,120,184, 93,231, 89, 93, 93,173,184,215,101,219,244,156,151, 2,152, 11,224, - 36,128,175, 1, 68, 3,120, 20,192,223, 13, 4,192,237, 63, 41,159, 83,176,176, 13,184, 69, 71, 42, 85,207, 49,153, 25, 75, 77, -126,222, 66, 0, 4, 6, 6, 82,129,129,129,205,100,111, 24, 74,206,202,202,106,241,191,241,231,151, 46, 93, 50,123,130,140,168, - 72, 73, 73, 81,164,166,166,194,120,163, 28,227,205,115,178,178,178,204,134, 96, 77,117,246,198,101,237,185, 81, 17, 0,108,218, -180,201, 44,241, 3,104, 65,254, 75,151, 46,101,101,243,247,210,107,168,223,242, 6,220,158,253, 24, 61,250,244, 66,183, 46, 46, - 40,221, 82,170, 39,127,207,206,250, 33, 0, 39, 33,231,115, 77, 72, 72,144, 26, 14, 3, 36, 36, 36,112,142,210,208, 4, 8,232, - 4,252,251, 73,224,249,245, 64, 87, 87,224,124,149,233,242,162, 74,142,119,190, 25, 33,199, 37,106,243,246,219,111,155, 37,126, - 0, 88, 57, 55, 30,107,118, 31,129, 95, 96,119,220,188,122,203,170,247, 15, 0,108,162, 0, 92,194,248,122, 15, 95,102,210,211, -103,198,246,185,222,215, 43,255,107,190,142, 66,230,193,134,123, 37,168,197,171, 58, 33, 24,226,109,197,172,191,223,160,108,192, -184,217, 99, 21,163,187,143, 66, 99,125, 61, 68,206,206, 16,137,238,117, 65,165,197,197,216,154,147,115,227,217,103,230,246,232, -237, 28,128,161, 19,195,163,126,205,253, 53,114,212,240, 81,156,188,198,244,157,115,177,111,223, 62, 60,246, 88,203,242, 73,147, - 38, 81, 92, 69, 0, 67,254,232,253, 33,118,190,254,178,221, 34, 32, 59, 59,155,124,244,209, 71, 8, 9, 9,193,154, 53,107,176, - 96,193,130, 14, 39, 2, 12,137,223, 81,246, 24, 91,118, 68, 19,164, 0, 38, 2, 88, 79, 8,169,163, 40,202, 15,192, 5, 0, 87, -229,114,185, 22,127,110, 16,142,245,221,130,252,153,247,153, 25, 75, 91, 69, 1,238, 75, 30,128,172,172, 44,102,236, 21,165,165, -165,240,245,245,109, 37, 16,152,178,138,138, 10, 86,121,238,173, 77, 6,228,210, 97,206,154, 53,171,237,164,155, 1,129,153,242, -250, 51, 50, 50, 32,151,203, 41,107,179, 56,149,184,134,186,233,163, 64,220, 23, 1, 81,175,163, 14,255, 3,254,163,247, 22, 73, -214, 34, 56,253,109, 13,180, 90,238,137,206,226,227,227,243, 89,108,187,106, 57,194,243, 21,240,214, 90,160, 87, 79,224,214,118, - 49, 54,124,169,198,220,239,204,151,115,186,243,137, 99, 51, 85, 27, 78,246, 43,207, 94, 1,247, 48, 9,220,250,254, 19,155, 86, - 60,143, 33, 3,253,208, 47,254, 93, 86,237,193,230,254,100, 59, 84,192,220,187,134,228, 47,151,203, 41,102,226,159, 77, 68,211, -249, 61,202, 22,146, 55, 5,117, 66,176,201,242, 92,163, 72,128, 53,148, 87,148, 99,114,210,100,184,119,246,130,142,210,226,192, -190,253,168,173,171, 67, 66, 98, 34,254,168,168,192, 15,155,127,196,115,207,204,237,225, 44,113,134,128, 56, 33, 38, 34, 38,239, -130, 98,141, 77, 94, 99,101,101,165,221,215,109, 72,254, 0,236, 22, 1,217,217,217,100,249,242,229, 8, 14,214,215,103, 80, 80, - 16, 58, 82, 36,192,209,196,111,194,251,103,222,219,114,173, 3,154,136,208,137,162, 40, 87, 0, 97, 0,206, 1,232, 33,147,201, -106, 0, 84,201,229,114, 62,173, 61, 71,220,183, 68, 64,190,190,190,210,164,164,164, 86, 67, 1, 71,142, 28, 81, 52,109,246,194, -121,142,128,185,201,128,150, 60, 71,115, 2,165, 45,192,120,247,230,194,253,108,189,127, 0,216,253,234,114, 36,188,255, 1,180, - 81,227, 32, 2,224,118,184, 24,123, 74,238, 0, 0,180, 81, 11,160, 57,235, 3,170,235,223, 57,147, 20,219, 40,139, 37,220,153, -246, 63, 44,120,230, 58, 46,206, 91,130,250,159,213,240,243,177, 92,238,136, 8,128, 45,226, 96,253,250,245,122, 53,156, 48, 1, - 71,202, 42,224, 62,196, 29, 55,114, 75, 0,137, 51,102, 46,248, 27,188,123,198,183,219,131,104,110,214,191,163,162, 90,150, 86, - 8, 88, 91, 29,144,155,156,139,152,204, 24,204,220, 12, 36,231,234,223,231, 38,231,114,142, 2,212,169,106,225,227,210, 5, 90, - 85, 3,136,128, 96,196,200,145,216,178,101,139,234,163, 15, 62,144,208,132, 96,206,147,115,224,221,197, 27, 13,117,117,208,234, -180,112,119,234, 12,141, 64, 99,211,245, 86, 85, 85,181, 88, 29,192,117, 66, 96, 43,242,103, 96,163, 8,200,206,206, 38,169,169, -169, 24, 57,114,100,139,242,129, 3, 7, 34, 61, 61, 29,105,105,105,237, 38, 2,218,138,248,141,189,127, 0, 40, 43, 43,179, 53, - 10,240, 43,244,227,253, 53,208,135,254, 39, 3,184, 4, 96, 48,128, 28, 0,235,208,180, 83,167,165,238, 4, 54,134,210,255, 18, - 2,192,152, 16,152, 61,231,217,124,110,105,214, 52, 3,102,120,129,153, 16,200,204, 13, 96,162, 3,129,129,129, 10,102,184,160, -189, 58, 94, 71,194,218, 88, 63,227,253,179,177, 53, 99,237,102,144,196, 62,184, 53, 38, 2, 93, 48, 14, 46, 51,215, 64, 91,254, - 7,224,217, 25,162, 59,255,195,246,143, 10, 0,161,144,243,181,219,178, 10,194, 24,167, 95,249, 63, 12, 15, 7, 2, 23, 20, 34, -204,237, 25, 92,120, 40, 9,248,247, 18,179,229,237, 21, 1,200,200,200,192,248, 17,253, 16, 53, 46, 4, 9,131,150, 96,245, 71, -159,227, 92,193, 13,204,155, 52, 28, 55,115,118,162,186,178,198, 33,247,131,169,161, 2,107,207,135, 37,111,223, 81,247,168, 57, -251,150, 38, 14,166,165,165, 81,233,233,233,100,230,230,150,130, 0, 0, 98, 50, 99, 32,222, 86,140,109,219, 74,154, 87, 2, 48, - 19, 6,189,189,189, 77,246,191, 52, 77, 67, 71, 3,132,214,194,217, 69,130, 39,159,122, 74,242,214,155,111,162, 91,183,110,116, - 15, 63, 63,129,170,190, 14, 58, 2, 16, 90, 7,154,182, 30,209, 26, 59,118, 44,245,195, 15, 63,144, 59,119,238,160,166,166,166, -133,112, 52, 92, 29,192,101, 85, 64,118,118, 54, 89,253,124, 17, 32, 9, 6,110,126,218,250, 0, 73, 48, 86, 63, 95,132,148,255, -176, 19, 1,217,217,217,100,234,212,169,210,129, 3, 7, 42,238,220,185,211,234,243,128,128, 0, 76,157, 58, 85,250, 32, 77, 12, -180,197,251,183, 39, 10, 32,151,203,243, 13,158,175,238, 0, 78, 3,152, 46,151,203,185,108,101,202,147,191, 37, 1, 96,148,232, -199, 90, 34,160, 22,159, 91, 10,153, 38, 37, 37,153,140, 2, 48,100,239,235,235, 43, 77, 77, 77, 85, 48, 99,178, 73, 73, 73, 22, -151, 1, 90,242, 14,185, 78,254,107,171,101,128,140,119,111,105, 50, 32, 23,148,252, 43, 25, 78, 51,215, 64, 89,118, 17,162,195, -107,160,217,188, 0, 84,220, 42,108,253,251, 99,184,186,245, 50, 18, 86,126, 13,136,218, 39,179,243,146, 44, 32,119,229, 22,132, - 93,141, 1,110,215, 99,113,244, 18,139,229,142,136, 0,216,234,253,231,108, 89, 14, 97,143, 1,112, 67, 8,174,237,203, 68, 45, - 69,112,244,226,117, 68, 21,222, 96,217,238,215,154,255,159, 53, 75,222,130,236, 1,224,231,159, 99, 77, 30,103,233,249,176, 22, -234,119,196,178, 67, 71,172, 16, 72,206,189, 71,252, 0, 90,121,254,204,132,193,109,219, 74, 76,126,223,221,197, 29,101,213,101, - 24,217,123, 20,148,141, 42, 64,169,130, 86,173,193,178,212, 84, 80, 2, 8, 26,234,235, 64,211, 58,104,117, 4,206, 34, 39,252, - 81,247, 7,156,116,214, 87, 27, 63,246,216, 99,205,117,115,232,208, 33,194,244, 55,134,171, 3,202,203,203, 89, 95,231,180,105, -211,168,148,255,128,172,126,190, 8,161,125, 90,255,254,249,203,106,164,252, 39, 12,108,201,122,218,180,105, 84,118,118, 54, 25, - 57,114, 36, 2, 2, 2, 90,125, 94, 88, 88,136,156,156, 28, 69,123,145,127,147, 55, 78,181,229,216,191, 33,236,136, 2, 48,152, - 12,253,228,239, 70,158,194, 29, 40, 0,218, 10,140,231, 15, 0,163, 71,143,150,102,101,101, 41,152,208,191, 25,113, 32,189,116, -233,146,130, 43, 9,219,218, 73, 58,122, 25,160,161,247,111,138,248, 25,161,195,229,124, 79,151,220,129,230,236, 91,184,133, 95, -224, 23,183, 10,168,174, 65, 73,230, 34, 4,205,255, 16, 55,215, 45, 2,156, 68,128,160,125, 50, 59, 95,171, 7, 66,125,167,179, - 46,111,143, 8, 64, 70, 70, 70,221,236,168, 81,229, 30,180, 87,175, 6, 56, 73, 54,127,184, 0,159,109, 63,133,197,143, 62,140, -185, 31,252, 23,143,189,247, 77,187, 76, 30,101, 4,104, 83, 30, 0,202, 94,113,106, 79,168,223, 82, 20, 32,185,201,179, 55, 38, -127, 67,239,223, 26,252,125,253,177,251, 64, 46,198,246, 26, 11,215, 78,110,160,105, 2, 1,209,130,166, 40, 16, 66,160, 35,128, -150, 38,208,106,181, 80, 86,215, 99,199,177, 29, 16,235,196,156, 39,165, 26,175, 10, 72, 91, 48, 14, 83,252, 75,145,121,140,189, - 13,115, 34,128, 43,249, 27,218, 75, 75, 75, 35, 43, 87,174, 68,247,238,221,239, 9,251,146, 18,100,100,100,160, 35,120,254,142, - 22, 2,166,188,127,123,162, 0, 77,207, 68, 36,128,135, 0,188,246, 23,152,252, 7, 0, 66, 0,186, 7, 90, 0, 24,207,250, 79, - 74, 74,106, 30,119, 55, 20, 7,134,239,237,241,224,109,233,200, 29,181, 12,208,156,247,111, 43,241, 51,152,177, 98, 29,126, 4, -240,232,251, 83, 64,178, 22,129,154,181, 26,167, 75,238,128,242,246, 66,241,239, 53,122,239, 95, 40,108,151, 59,212,220,122,127, -123,242, 0,176, 17, 92,108,197,193,250,245,235,213, 0,106,159,143, 28, 92,243,207, 85, 31,171, 95, 93,150,170,234,218,217,247, - 78,209,185,107,221,230,158,251,175, 91,123,175, 26, 49, 71,206,134, 67, 52,220, 87, 20,152,250, 13,251, 34, 0,166,200,159,241, -252, 1, 88,157, 16, 40,145, 72,168,115, 91,207, 39, 42,198,229,231, 36, 13,122, 12, 53,170, 26, 80, 2, 64,159, 82,132,134, 78, - 71, 64,107,181,232,228,236,142, 67,213, 39,113,233,112, 49,162, 35,162,243,237,174,220,146, 23, 0,112, 95, 6,216, 66, 4,116, -191,134,243,229, 1, 54,145,191,161,189, 37, 75,150,144, 53,107,214,192,211,211, 19,119,238,220,193,242,229,203,209,209,194,254, -142, 16, 2,230,188,127, 91,162, 0, 50,153,172, 27, 0,191,166, 27,101, 40,128, 20, 0, 37,127, 17, 39, 93,215,150,198,239, 75, - 30, 0,115, 17,129,213,171, 87, 75,141,133, 66, 82, 82,146,130,171, 61, 67, 34,232, 8, 41,118, 13,189,127,227,229,127,165,165, -165, 45,234,141, 75,214, 62, 70, 4, 76,127,255, 43,144,205,128,207, 92, 57,242,255,249, 24, 30,206,216, 8, 56, 57,161,147, 68, -220, 46,215,107,184,198,223,212,123, 27,243, 0,104, 1, 8,154,218, 86, 96,103,123,220,154, 29, 53,170,236,159,153,219,250, 44, -123,110,114,103,127,191, 72, 53,128, 51, 73, 73, 73, 30, 0,220,108,109,143,123, 36, 29, 75, 30,121,100,151, 65,248,159,219,247, - 45,121,240,134,233,129,217, 10,137,182, 72, 6,100, 14,198,164,207, 68, 4,204, 13,121, 60, 61,235,233,173,219,254,187, 13,186, -217,218, 51, 19,123, 77, 28,220,197,189, 11, 84, 26, 21, 8, 33, 16,139,196,168, 82, 54,224,200,239, 63, 99,253,183, 27, 32, 29, - 32,117, 72,226,176,244,157,115,177, 97,195, 6, 44, 90,196, 61, 7,192, 61, 17, 0,187,200,223,208,222,130, 5, 11,152, 60, 0, -232,200, 99,254,134, 66,192,150,239,218,155, 59,192,240, 49,128,126,189,191, 10,192, 43, 0,142,201,229,114, 29,120,152,171,123, -156, 58,117, 10,153, 25, 75, 91,229, 1,176,152, 8,168,173,242, 0,152,138, 8,152, 35,122, 91,162, 0,246,162,173,150, 1, 50, - 98, 68, 46,151, 35, 47, 47,143, 46, 45, 45, 53, 36, 50,105, 84, 84, 20,103,239,102,198,138,117,128, 65,226,159,137,203,214, 54, -191,175,111,135,155,173,173,188,103,138,162, 62, 2,112, 23,250,229, 63, 79,218,105,238,230,243,145,131, 27,163,243,126,237, 60, -231,205,175, 33,151,203,197,121,121,121,221,209, 50,157,181, 77,237,209,214,145, 0,107,249,253,173,161, 45,134, 4,204,145,191, - 58, 33, 24,216,102,221, 49,147, 14,158, 68,237,251,225, 0, 57, 28,112, 4,227, 70,141, 67, 15,247, 30, 0, 77,240,135,234, 14, - 14,157, 56,132,155, 69, 55, 49, 41,116,146,212,217,217,185,221,219,195, 80, 4, 56,138,172,153, 72,192,131, 50,225,207,222, 44, -128, 14,232, 99, 50, 1,100,130, 7,103,152, 75, 0,100, 82, 0,180, 21, 82, 82, 82, 76,146,189,225, 78,108, 70, 80,176, 89, 85, -224, 40,175,191, 45,150, 1, 54,205,240,215,230,229,229,137,154,134, 14, 24,242,159, 20, 21, 21,197, 41,202,209,180,153,146,194, -209,231,104,110,140,217,209,185,238, 57,194, 25,128, 72, 46,151,191,110, 16, 2,123,202, 94,155,209,175,125, 81, 32,151,203, 39, -228,229,229, 33, 47, 47, 79, 5, 64,210,244,103, 55,241, 51, 81, 0, 91,235,204, 26,201, 79,157, 38,107,113, 28, 87,226,118,196, -144, 64, 90, 90, 26,149,158,156, 78,252, 23,248, 75,209,219,244, 49,101,201,185, 10,182,243, 1, 70,134,141,164, 26, 26, 26, 34, -215,189,191, 14, 1,193, 15, 41, 0,224, 66,225,111,210,248,232, 4,132,134,135,218,220, 30, 99,199,142,165, 54,111,222,220,106, - 85,128, 70,163,177,235, 6,114, 52, 89,255,217,102,251,119, 0,240, 75,252, 76, 68, 1,140,203, 88, 11, 0,107,158, 56, 91, 79, -221,214, 78,145,109, 34, 22,123,137,202,209, 68,199,216,203,203,203, 35,121,121,121, 34,195,250, 10, 12, 12,180,233,183,154, 8, -202,225, 29, 70, 71, 24,251, 54, 1,119, 0,117,250,132,252, 20, 5,192, 5,214,215,247,178,105,143, 43,121,121,121,204,186,178, -154,192,192,192,174,129,129,129,206, 29,161, 46,237,245,196,173,217,118,212,144,128, 85,114, 79,227,118,143,186,186,186,230,207, -154, 58,155,233,188, 49, 58,108,180, 67,206,115,230,204,153, 60,185,254,249,201,222,144,195, 52, 14, 38,127, 9,244,195, 13, 15, -188, 8,176, 90,145,225,225,225,188,106,226,193,131, 7, 15, 30, 60,254, 98, 16,240, 85,192,131, 7, 15, 30, 60,120,240, 2,128, - 7, 15, 30, 60,120,240,224,241, 23,192,255, 3,211,238,250, 72,118, 88, 93,170, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, +137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, + 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144,206,103, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, + 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167,147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0, +154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,216, 9, 7, 16, 32, 48, 13, 5,217, 84, 0, 0, 32, 0, 73, 68, 65, 84,120,218, +236,125,121, 92, 84, 85,255,255,251,220,217,217, 23, 1, 21,133,193,125, 95,201, 37, 55, 40, 49, 51,205, 52,192,212, 36,219,196, +210,180,178,180,111,249, 60,233, 79,159, 12,148,202,212,132,158, 74,179,210, 18,151,180, 92, 18,116, 80, 83, 82,209, 92,202, 5, + 69, 1, 65,145,101, 86,102,187,115,231,222,223, 31, 51,131, 3, 2,179,128, 73, 61,243,126,113, 95,195, 93,230, 51,231,158,237, +253,249,124,206,231,156, 67,250,245,235,199,193, 3, 15, 60,240,192, 3, 15, 60,248,159, 2,229,201, 2, 15, 60,240,192, 3, 15, + 60,248,223,193,153,223,179, 1, 0,196,227, 1,240,192, 3, 15, 60,240,192, 3,143, 7,192, 3, 15, 60,240,192, 3, 15, 60,240, + 40, 0, 30,120,224,129, 7, 30,120,224,129, 71, 1,240,192, 3, 15, 60,240,192, 3, 15,254, 17,224,219,159,156, 61,123,150,184, + 43,168,190, 88, 2,143, 60,143,188,134,144,145,145,193,173, 95,191,254,129,165,111,234,212,169,220,150, 45, 91,136,167, 60,254, +214,242,208, 4,121,240,228,159, 71,222, 63, 89,158,203, 10,192,255, 56,234,102, 32,105,201,233, 76, 79, 79,199,236,217,179,137, +167,216,220, 47,227,184,184,184,154,243,172,172,172,127, 68, 94, 78,124, 42,185,209,142, 96,215,143, 25,255,232, 58, 35, 9,220, + 9,177,161, 19,162, 64,163, 26,251,144,175, 95,220,146,235,162,167,253,122,208,114, 60, 0,127, 69,101,157, 56,113, 98,204,174, + 93,187,100,118,231,177,187,118,237,202,105, 17, 45,146,179,244,157,132,180,216,118,201, 21, 22, 22, 2, 0,164, 82,233,223,169, + 19,113, 90, 59,157, 58,117,170,211,207,110,217,178,197, 21, 69,141,219,186,117,107,205,201,206,157, 59, 17, 23, 23, 87,235,254, +131, 82, 2,242,242,242, 56, 0,136,142,142, 38,205,241,220,174, 31, 51,238,107,249,133, 71,181, 7, 0,220, 49, 24,192,232,141, +150,139, 74, 53, 0, 32, 33, 33, 1,153,153,153, 13,166,111, 96,193, 64,174,243,237,206, 46,253,248,247,195,191,119,162, 92, 36, + 8,124,245, 2, 12,187,118, 66,161,152, 4, 5,128, 1,146,149, 88, 44, 57,141,246, 98,160,194, 80,128,197,250, 68,151,126, 55, + 33, 33, 33, 38, 51, 51, 83, 86,231, 90,108,102,102,102, 78, 11,107, 91,205, 82,111,255, 38,239,219,236,104, 19, 44, 34, 62, 2, +127, 98, 20, 11, 57,163, 82, 79, 85,235,213,172,214,104,250,159,152, 29,231, 80, 1,176, 18,182,237,179,169, 21,129,219,181,107, + 23,150,110, 93, 14,159,246,254,168,190,169,194,251,137,139,101, 45,220,226,110, 73, 32, 82,169,148, 43, 44, 44, 68, 97, 97, 33, +246,239,223,143,217,179,103,183, 84, 37,192,214,128, 72, 70, 70,134, 32, 57, 57,217,148,154,154,122, 10, 0, 22, 46, 92,248, 80, + 99, 95,156, 52,105, 82,205,255, 12, 99, 6,109, 50,130, 54,210,160,105,203,193, 48, 12, 22, 46, 92,232, 82, 90,236,201,191, 62, + 88,149, 1,238, 65,122, 2, 92, 81,126, 30,152,133, 31,224,135,243,215,191,135, 4,237, 96,198, 49,148,127,113, 6,231, 10,170, + 48,249,195, 13, 78,125,189,243,237,206, 78, 18,186, 5,207,252,250,140,195, 60,145,140, 91,140,160,137, 47,162,244,245, 1,128, + 94, 81,115,253,140,254,109,156, 1, 0, 61, 48, 82,146,128,131,129,167, 17, 0, 96,160, 98,160, 83,117, 38, 51, 51,243,158,139, +118, 4, 73, 90, 80, 27,107,142, 62,224,239,240,190,205,138, 97,125,250,145,103,195,163,248,202,136, 86,188,208,238,225, 20,159, +132, 18,157, 74,197,138, 17,102,166,250,183, 51, 63, 55, 97,140,217, 73, 81,183, 92,248,217,182, 78, 60,179,192, 5,121,105,247, + 85, 1,216,181,107,151,108,235,191,222, 69,226,178, 15,100, 77,172, 4,156,141,248, 1,160, 82, 87, 5, 4, 3,255,119,112, 9, +212,215, 21, 88,247,242,234,150, 70,100, 13,117, 60, 15, 58,141, 53, 74,192,216,177, 99, 81, 88, 88, 8,169, 84,218,226,242, 78, + 38,179,244, 27,177,177,177, 28, 0, 42, 35, 35, 35, 60, 57, 57,185, 52, 53, 53,245,180,179, 66, 24,134, 1, 77,155,106,136,223, +158,252,243,242,242, 16, 29, 29,237, 82,162, 18, 19, 19,237,201, 22, 89, 89, 89,117, 21,128,230,168, 43, 46,151, 67,116,116, 52, +153, 58,117, 42, 55,102,204,152,123,238, 29, 56,112,192,230,233,176,121, 61,156,150,223,156,195, 1,225, 81,237, 81,170, 80, 97, +199,236,167, 17, 76,134,161,224,191,111,161,195,164, 14,200,114,129,252,107, 50,203,234,106, 35,205,224,106, 11,223,122, 12,186, +162,106,148, 38, 71, 53,250,220, 5,113, 54,150,246,190,131, 21, 23,222,107,106,121, 54, 7,233, 54,167, 12, 52,179,172,251,241, +190,205,130,164,164, 36, 47, 0, 15, 3,240,177,187,172, 4,112,126,211,166, 77,114,103,229,124,178,254, 19,138,174, 52, 10,104, +163, 65,172,128, 73, 44, 16,240,249,106,131,152, 18, 10,245, 44,207,207,155,161, 37, 38, 19,191,236,150,241,235, 47, 54, 26,158, +123,105,166,217,153,247, 86, 42,149,255,177,253,159,159,159, 95,233,237,237, 77,105,181, 90,214,254,153, 65,131, 6,125,220,204, +196,190,160,169,121,202,119,100,253, 95,186,116, 9,157,125,252,236,189, 1,238,120, 1,106,200,191, 82, 87,133, 21,143, 46,169, +185,241,252,174, 87,129, 80, 96, 82,106, 34,118, 46,220,234, 74, 37,107,172,115,107,114, 69,189,121,243, 38, 0,160,125,251,246, +181,254,135, 11,238,236,102, 84, 68, 72, 67, 74,128,201,196,216,226, 1,154,197, 10,104,134,188,180, 39,127, 0, 32,201,201,201, + 0,112, 43, 35, 35, 35, 48, 57, 57, 89,225, 52,249,155, 76,160,105, 35,140, 52, 13, 83, 29,242,231, 88,215,138, 33, 49, 49, 17, +121,121,121,119, 91, 87, 90, 26,226,227,227,107,206,183,109,219,214,100,101,199, 78,225,105,114,253,179, 39,254,169, 83,167,162, +127,255,254, 54, 5,192, 85,143, 64,179, 84,194,146,235,197,208,238,252, 55,124, 94, 88,141,240,168,246, 8, 11,150,224,250,206, +235, 22,242, 15,240,179, 12, 1, 8,120,206,105,176,205, 52,198,214,229,226, 53,220,124,127, 57,244,153, 27, 27,247, 16, 72, 36, + 48, 24, 12, 40, 40, 40, 64,185,225, 10,186, 32,188,193,103,173,110,240,198,234, 62,177,181, 19,235,179, 57,110,180, 47, 98,215, +174, 57, 55,219, 25,105,132,184,157,174,131,245,189,111,124,124, 60, 71, 8,177, 13,229, 52,229,125,109,109,153,227,243,249, 77, + 42,243,164,164, 36,127, 0,147, 14, 30, 60,248,111,150,101,141,118,117,137,207,227,241,188,147,146,146, 94,218,180,105,211, 94, +135,140,185,104, 1,191,242, 86,133, 88, 32, 16,121, 83,124,226,199,241, 68, 94, 44,143,199,103, 9, 5,150,240,205, 28,143,103, +228,177,196,160,229,153,117,222, 66, 1,249,226,216, 94,195,220,148,153, 44,138, 29,167, 81,161, 80,168,117, 58, 29, 3, 0, 90, +173,150,125,247,221,119,107, 8,255,131, 15, 62,120,163,169,245,125,244,232,209,179,109,255,103,103,103,167, 55, 71, 27,162, 28, + 89,255,203,167,196,195, 80, 81,129,183,122,118,131,253,216,189,211, 86,200,196,137, 49, 0,106,145,255,196,137, 19, 99, 1,144, +137, 19, 39,198,110,152,248,153,197,179,216,181, 85,173,231,157,193,194,117,249, 88,184, 46, 31,115, 86, 93,194,115,203,254,192, +228,255, 59,219,244,142,174,164,196, 41,197,224,175, 34,127,235,152, 63,215,128, 39, 0, 38,154,198,224, 65,131,154, 67,201,224, +182,110,221,138,173, 91,183, 66, 38,147,213, 28, 46, 42, 60,156, 76, 38, 67,108,108,108, 13,249,219,223, 76, 78, 78, 86, 58,211, + 49, 49,140,217, 98,249, 27, 45,174,255,186,228,111, 54,155,161,213,107, 93,122, 65,155,199,160,174,215, 96,219,182,109,216,182, +109, 91, 45,101,192,165,247,205,169,221, 31, 90,207,155,164, 36,218,200,127,234,212,169, 72, 77, 77,173, 33,127, 1, 95,224, 42, +249,219, 58,240,134, 14,167,161, 71, 49,170, 39, 13, 6,151,249, 22, 74,174, 23,131,155,212,253,110, 38,100,190, 5,126,155, 16, + 32, 32,224, 47,213,140,181,149, 5,208,103,110, 4,199,113,184,112,225, 2, 70,142, 28, 9,137, 68, 82,139,248, 3, 3, 3,161, +215,235,161,215,235, 81, 90, 90,138,105,250,121,248, 34,240,245, 6,101, 58,233,242, 38,117,158,117,149,184,155,203, 88, 33, 13, +144,191,211,117,176,238,251,198,199,199,115,219,182,109, 67,102,102, 38, 18, 18, 18,184,166,190,175,149,252,193, 48,140,219,109, + 34, 41, 41, 73, 12,224,229,236,236,236,119,151, 45, 91,118,130, 16, 34,181, 29, 0,218, 5, 7, 7,123, 29, 58,116,104,125, 82, + 82,210,200,198,228,124,150,190,158,199, 35, 2, 17,205,112,126, 70,163, 41,212,204,178,237,204, 44, 27,101, 38, 36, 2, 60, 94, + 48, 33, 36, 0,132,231,199,114, 8,226,104, 54, 64,173, 55,121,135,250, 49, 60,106,144,198,169, 50,210,233,116, 76, 93,171,191, +165,131,106,140,184,187,116,233,130,206, 62,126,208,149,221,198,227,253, 7,184, 76,208, 54, 37, 98,233,214,229, 0, 80, 67,254, + 54, 47,194,174, 93,187,114,108, 74, 64,137,250, 22, 6, 44, 28,226,146,146,161,213,155,161,213,155,113,187,202,136,210, 10, 3, +110,222, 49,184, 69,124,182,198,226,136,252, 31, 20, 26, 81, 2, 96,160,141, 48, 24, 12, 77, 17,207,201,100, 50,216,198,200, 67, + 66, 66,236,173, 89,184,208,153,212,178,132, 27,113, 37, 58,236,244,104,147,209, 98,249, 27,105,208,166,218,228,111, 50,153,160, +213,106,161, 81,107, 30,116,177,112, 91,183,102,214,126, 37,203, 31,172,215,221,234,240,236,201,223, 70,252, 20, 69, 65, 44, 22, +195,219,199,171, 73, 9,158,248, 84, 50,215,208,225,232,187,251,255,111, 9,130, 49, 12,204,232,215, 0, 0, 62,185,215,112,174, +160,202,210,201,143,126, 13,166, 11, 75,129,202, 42,215, 50,208, 10,119,223,199, 27,149, 0,128,141, 27, 55, 98,215,174, 93, 88, +185,114, 37, 78,158, 60, 9,163,209,136,242,242,114,155, 85, 86,243,124,120,120, 56,244, 0,120,184,241, 64,234, 75, 35,245,158, + 52, 65,105, 36,141,120,240, 92,150,105,239, 9,171, 47, 38,192, 29,242, 7, 0,119,149,128,164,164,164,214, 86,242,159,245,245, +215, 95, 95, 92,188,120,241, 83,155, 55,111, 70,151, 46, 93, 0, 0,145,145,145, 80,169, 84,162,165, 75,151,158, 62,116,232,208, +183, 73, 73, 73,210, 6,115,137,229, 8, 88, 70,108, 54, 51, 65,102,198,220,206,100, 54,117,226, 81,164,173,144, 79, 9,196, 2, +158,158,239, 37, 84,122,251,242,212, 60, 49,199,136,121, 60,111, 62, 67,251,221, 56,243,187,104, 70,200, 39, 14,211,157,159,159, + 95,169,213,106,217,250,220,252,125,251,246,189, 66,211,116,179, 85,164,190,125,251, 54,155, 44,126, 99,196,253,223, 89, 47,222, + 37,219,146,155,120,171,103, 55,172,178, 16,180, 75, 90,171,205,250,183,145,126,157,223,169, 57, 15,238,221,218,165,196, 87,235, +205,208,232, 24,168,181, 12, 84,213, 12,148, 26,198,245, 86, 89, 79,228,191,189,149,111,255,255,245,235,215,161, 84, 42,255,178, + 30, 35, 61, 61, 29, 82,169, 20,182,160,191, 58, 99,253, 92,122,122, 58, 12,122,125, 83, 20, 0,110,195,134, 13, 40, 41, 45,133, +128,199, 67, 88,235,214,181,200,255,209, 71, 31,197,193,131, 7,157,237,156, 72,108,108,108, 93, 37,160,150, 39,195,217, 88, 5, +218, 72,131, 54, 26, 97, 50,209, 96, 24,115, 13,249, 27,141, 70,232,116, 58, 84, 87, 87, 67,163,113, 93, 1,176, 31, 2,176,193, + 93,203,127,107,230, 86,128, 3, 42,173, 68, 99, 29,212, 6,225, 56,139, 18,144,153,137, 68,139, 5,229, 82, 91,169, 75,254, 2, +129, 0, 34,145, 8, 98,177, 24, 98,177,184,201,117,170,161, 33,129,250,230,197,219, 99,114,250,118,112, 79, 70,225,206,208, 1, + 8,198, 48, 72,158, 94, 3,230,118, 5, 16,224, 7,126,213, 22,252,252,201,105,128,199,115, 41, 45, 77, 29, 10,208,242, 44,125, +202,138, 21, 43, 80, 81, 81,129,245,235,215,163,111,223,190, 88,182,108, 25, 6, 12, 24, 0,189, 94, 95,215, 66,179,169,212,127, + 53,241, 59, 75,208,238, 14, 7, 52,164, 72,184, 44,199, 58,139,163,166,109,184, 59, 52,102, 79,254, 53,100, 99, 85, 2, 92, 28, + 14,240, 61,127,254,252,167,175,188,242,202,145,222,189,123,251, 1,192,146, 37, 75,144,159,159, 15, 0, 24, 50,100, 8,118,236, +216,129,225,195,135,123, 79,155, 54,173, 32, 39, 39, 39,251,249,231,159,159,246,251,239,191,223,147,179, 65,193, 65,236,245,235, + 5, 76,142,236,224,190, 78,157, 58,231, 68, 69, 74, 47,242,124, 37,229, 60, 34,212, 82, 34,129,142, 18,123,105,104, 62,143, 6, +103,226,177, 98,147,175,166,180,202,231,228,161,179,131, 90, 5,134,237,112,168,140,218,141,249,239,220,185,243,185, 73,147, 38, +125,109,115,251,171,213,106, 74, 40, 20, 54,185, 34,217,220,254,217,217,217,247,215, 3, 96,179,242,163, 59,118,134,161,162, 2, +218, 18, 11, 9,142,180, 90,135,174,122, 1,174,255,113,237, 30,217,245,157, 87, 93, 40,115, 41,241, 77, 37,127,123,226,231, 56, +206, 54,198, 95, 3,147,201, 84,115, 40,149, 74,104,181, 90,200,229,242,191,172,231,176,205,243,223,191,127,127, 93, 79, 0,151, +158,158,142, 62,125,250,192, 96,208,215,116,116,233,233,233, 46,185,235,215,125,182, 14, 38,147, 9,237,194,195, 97, 50,155, 27, + 34,127, 87, 58, 18, 82,143,235,191,102,234, 98, 99,158,140,123, 20, 0,218, 84, 67,254,167, 78,158,130, 78,175,135, 70,163,129, + 74,165,130, 82,169,172,101,217,185, 10,219, 48, 64, 19,198,253, 81, 85, 89,133,170,170, 74, 84, 86,201, 81, 89, 85,133,170,170, + 42, 84, 85, 90, 44,210,110,221,187, 67,110,253,223, 85,235, 31, 0,250,247,239,127,215,234,247,246,134,143,143, 47,124,125,124, +161,209,104, 98,155, 72,254,110, 15, 7, 20,172,156, 5,193,211,107, 16,140, 97,224,231,174,129,105,251,107, 64,128, 31,118,191, + 26,143,162,221, 55, 48, 33,117, 19,192,255,139,151, 21, 49, 20, 65, 18, 46,129, 86,171,133,193, 96,128, 78,167, 67,110,110, 46, + 62,252,240,195,122, 31,247,242,178,121, 80,174,185, 67,222,238, 90,213,246,249, 75,156, 60,111,138,146,225,106,155,173, 37, 39, + 51, 51,147, 36, 36, 36,216,200,223,109,207, 4,159,207, 39, 12,195,212, 85, 10,224,106, 44,192,166, 77,155,174, 38, 36, 36,244, +221,188,121,243,200,163, 71,143,250,142, 30, 61,250,164,141,252,173, 6, 36, 68, 34, 17, 87, 84, 84, 36,216,183,111, 95,215,192, +192,192, 83,195,134, 13, 43,168, 79,214, 51, 83,158, 97, 59, 71,117,209, 12, 25, 50, 36,254,226,197, 63, 31, 81,107, 53,173, 57, +198,196,128,130,137, 49, 82, 70,163,209,168, 87,163, 76,205, 26, 13,154,210,226, 50,230,231, 61,123, 83, 90, 5,135,148,211,180, +206,161,249, 94,159,245,175, 80, 40,248, 0,224,231,231,215, 98,135, 5,168,134,172,255,173,255,122,215,162, 53,151,221,174,117, +207,213, 88,128,137, 19, 39,198,174,123,121, 53, 0, 75,192,223,174, 93,187,100, 54,210,183,173, 9, 16,247,205, 83, 0,128, 51, +169,191,217,226, 3,254, 42,212, 84,198,146,146,146, 26,107,223, 70,250,118,133, 11,141, 70, 3,131,193, 96,215,137,252,117,105, +156, 61,219, 18,251, 97, 98, 24, 92,188,120, 17,191,159, 57,131,190,125,250,194, 96, 48, 64,175, 55,192,160,215,227,219,111,190, +129,237, 57,103, 26,122, 90, 90, 26,122,116,239, 1,147,201,132,171, 87,175,130, 49,209, 40, 45, 41,109,214, 60,181,157, 91,215, + 44,176,173, 93,224,216, 3, 96, 50,130, 49, 91,220,254, 39, 78,252, 6,173, 94,139,106,141, 26, 42,149, 10, 10,165, 18, 10,133, +188, 73,138,152,205, 19,224,166,245, 15, 0, 56,114,228, 8, 52, 26, 13, 52, 26,181,245, 83,131, 86,193,193,232,214,189, 59, 46, + 95,186,132,195, 71,142,184, 44,211,102,253,243,249, 2,120,121,121,193,199,199, 7,190, 62, 62,240,241,241,130, 92, 33,143, 77, + 78, 78,206,113,170,205, 53,193,213,223, 16,206, 21, 84,193,116, 97, 41,170,112, 12,100,220, 42,144, 97,255, 70,193,202, 89,120, + 50,245,107,136, 5, 20, 32,224, 91, 14,119, 88,199,205,161,128,210,241,159, 33,104,203,120,232,116, 58, 4, 5, 5, 65,161, 80, + 64,161, 80,224,248,241,227,184,125,251,118,141,155,184,230,249,210, 82,188, 26, 40, 65, 43,175,138,198, 44,224, 88,123, 82, 77, + 72, 72,136,177,187, 23, 83,231, 94,172,139,237,130,107,132,192,155, 99, 70,129,203,150,127,125,239,155,153,153, 73,182,109,219, + 70,154,248,190,181,148, 0,119,200,223,134,247,222,123,239,252, 83, 79, 61, 53,109,197,138, 21, 93,207,157, 59, 55, 76, 34,145, +240,158,124,242, 73, 34, 18,137,192,178, 44, 25, 55,110,220,249,249,243,231,247,233,213,171,215,238,151, 94,122,233,185,151, 94, +122,169,193,177,168,228, 57,201,236,159,151,174,158,234,213,187,207,179,167, 78,158,156,188,123,207, 79, 31,228,157, 60,217,250, + 98,254,101,241,213,210, 2,238,219,213, 63, 72, 86,164,173,236,145,189,103, 79, 90,167,142,157,126,246, 9,243, 62,178,105,211, + 38,179,179, 57, 58,122,244,104,156, 58,117,170, 95,122,122,250, 82,131,193, 32, 88,182,108,217, 71,187,119,239,158, 90, 90, 90, +250,151, 19,135, 83,101,212,208,141,224, 27,133,144, 3, 53,214,191, 13, 35, 67, 66,176, 10,151,157,183, 58,172, 46,254,203,167, + 47, 34,160,107, 43,196,125,243, 20,118,205,248, 81,102,211,222,108,228,111,179,254, 93,153,101,176, 99, 69,191,230, 97, 88, 66, +112,233,210, 37,216, 42,107, 93,247,178, 64, 32,128, 64, 32, 64, 69, 69, 5,198,141, 27,247, 32,202,137, 72,165, 82, 46, 61, 61, + 29,131, 6, 13,130,193,104,132,222,160,135,193, 26,220,164, 55, 88,134, 1,214,174, 93,139,185,115,231, 58,234, 76,184,212,212, + 84,152,205,102,156, 62,125, 6, 2,190,197,109,219,185,115,103,220, 40, 44, 68,105,105, 41,182,108,249, 30, 83,167, 62, 3, 0, + 92, 29, 79, 64,131, 29, 80, 70, 70,134, 16, 0,147,156,156,204,214,103, 1,185, 50, 85,209,102,249,231,230,230, 66, 91,173,171, + 81,192,212, 26, 53,212,106, 21,212,106,247,134, 0,236,173,255,169, 83,167,214,120, 0, 92, 85, 4,166, 78,157, 90,235, 60, 74, + 42, 69,183,238,150,160,184,203,151, 46,225,134,213,227, 49,117,234, 84,151,163,246,135, 62, 60, 20, 34,161, 8, 18,137, 4, 98, +177, 24, 34,145, 8,101,101,101, 78,147,191,157,181,223,172, 21,112,242,135, 27,176, 3,192,216, 21, 79,128,203,124, 11, 36, 49, + 13,231, 10,170, 64,130, 2,113,173, 68,109,177,254, 93, 28, 2,176,107,127,196,166, 8,216,159, 59,132, 94, 15,240, 44,198,222, + 93,247,190,133,232, 77, 38, 19,190,248,226, 11,140, 28,121, 55, 46,236,224,204,112,160, 92,135,174,123, 21,232, 23, 18, 89,175, +200,122,162,220,237,135, 60,101, 14,158,117,150,176, 73, 19, 60, 10,141,121, 35, 92, 86, 36,238,247,251, 90,149,128, 38,207, 2, + 88,177, 98,197,150,121,243,230,133,156, 61,127, 62, 81,175,215,247,145,201, 14, 73, 68, 98, 17,159, 34, 20, 14, 29, 58,228,219, +163, 71,143, 77, 9, 9, 9,255,158, 60,121,178, 67,107, 61,231,208, 1,118,194, 83, 19, 14,247,237,219,127, 33,205, 24,199, 94, +203,191,250, 1, 91, 88,192, 0,224,196,160, 76,189, 59,117,205, 12, 13, 13,217,203,227, 11,191,253,207,226, 20,250,147,101, 31, + 59, 44,165, 65,131, 6,125, 60,122,244,104, 0, 64, 69, 69, 5,178,179,179,253,190,250,234,171, 15, 0,224,212,169, 83,131,122, +246,236,185,255,111,161, 0,216, 22,254,121,244,219,205,142, 44,123, 87,166, 4,146,157, 11,183,114, 3, 22, 14, 65,112,239,214, + 53,164, 95,227, 78,189, 80,134, 51,169,191,185,234,182,106,174, 57,169, 4, 0,215,189,123,119, 92,184,112,161, 22,177, 40,149, +202, 2, 0, 29, 93,212,230,239,167, 39,224,158,223,252,246,155,111, 97, 48, 24, 96,164,141,160,105, 26,169,169,169,141, 45,146, +195,165,166,166,214,156,176,172, 25, 98,137, 15,244,122, 3, 46, 93,188, 8,190, 64, 0, 19, 77,195,203,219, 11, 91,182,108, 1, +143,199, 67, 98, 98, 34, 30,125,244, 81,174,170,170,225, 0,175,212,212,212,253,201,201,201,116, 70, 70, 70,168, 45,111,234,172, + 3,224,146,107,115,225,194,133, 56,118,236, 24,170,171,171, 81,173,213, 66,163, 86, 91,201, 95, 13,141, 90,131,106, 77, 53,180, +118, 29,190, 51,121, 23, 29, 29,205,229,229,229,213, 88,255,245, 77, 3,116,118, 17, 32,235, 92,252, 90,101, 97, 35,125,219,216, +163, 43,171, 20,218, 86,248, 3, 0, 31, 47, 31,136, 37, 98,104, 52,154, 88,219,208,142, 27,228,127, 95,230,107,219,148,128, 73, + 43,190, 2,183, 29,104, 53, 51, 3, 57,175,199, 99,120,202,119,128, 64, 0,111,113,211,198, 57,235, 42, 2, 0, 48,245,216, 84, + 7,223,186,131,222,251,189, 80,246,147, 14,138,229,119,175,154, 76, 38,140, 24, 49, 2, 0, 16, 30, 40,193,175, 25,237,177,242, +195,155,248,236,140,222,145, 69,108, 63, 45, 14, 13,253,111,247,108,142, 27,125, 86,115,205,173,111,142, 49,255,251,249,190, 53, + 74, 64,115,212,191, 79, 63,253,244,211,231,103, 62,191,239,161,129,209,131, 52,106,117, 16, 99,102,140, 97, 97, 97, 21,225,225, +225,101,106,181,250,220,228,201,147,157,238, 20,126,250,241, 39, 22,192,150,103,167,191,152, 59,108,248,240, 31, 37, 18,137, 63, + 1,199, 18, 66,192,178,156, 74,175, 85,200,174,156, 47,214,120,139,132, 78,245,243, 54,242, 7, 44,129,212,117, 3,245, 62,252, +240,195,127,255, 45, 20, 0, 43,169, 59, 44,176, 93,187,118,185, 92, 89,207,164,254,198, 1,128, 77, 17,176, 35,254,230, 36,116, +183, 27, 82,239,222,189,113,234,212, 41, 84, 84,212,184, 8, 59, 2,128,141,252,102,204,152,241,160,203,171, 86, 30,165,167,167, +115,207,206,120, 22,107,215,174,179,142,153, 51, 88,184,112, 97,163,211,151, 92, 92, 65,207, 98, 57, 29, 60,232,104,179,137,238, +169,169,169, 87,147,147,147,203, 51, 50, 50,120,201,201,201, 53, 1,129,214,105,129, 78,119,116, 54,139,121,216,176, 97,205,158, +119,209,209,209,156,189, 21,111, 31, 3,224,198, 10,128, 4, 0,183,101,203,150,123,172,124,171,135,192,229,250,188,101,203, 22, +226,170,199,192, 25, 52,230,250,119, 85, 89,152,252,225, 6,192,110,225,159, 81,239,222,157,142,172,109,174,130,178,243, 0, 56, + 90, 9,176,116, 88, 41, 74, 1, 12, 88, 25,136,229,167,187, 32, 4, 64, 69,129, 22,157, 58,117,178,144,198,242, 64, 60,246, 80, + 8,162, 30,203,119,214, 34,118,122,120,211,250, 44,113,183,191,105,166, 62,175, 73,178,254,162,247,109, 54,108,216,184,225, 42, +128,171,205, 37,239,219,239,190, 44, 68, 51, 68,133, 54,103, 96,158, 21, 11,254,138,252,252,171, 55, 3, 34, 19, 39, 78,140,217, +149,218, 34,247, 2, 32, 0,184,135, 30,122, 8,123,247,238, 53, 88, 73,159, 5,224,117,159, 60, 15, 77,134, 45, 72,112,238,220, + 57,156,213,242,127, 32,105, 91,184,112, 97,100,125,110, 73,187,105,132,174, 88, 59,228, 62,151,113, 77,122,154,186,236,111, 67, +171,242,185, 74,226,142,214,246,111, 14, 52,101, 72, 96,209,162, 69,184,126,253,122,179,165,197,153,229,125, 93,197,153,183, 21, + 56, 3, 75, 96,232,200, 4, 9,126, 57,209, 5, 97, 94, 62,248, 51,239, 14,186, 58, 73,254, 78,212,191,150,186, 28, 46,185, 79, +223,245, 44,207,238, 28,218, 54,179,188,180,191, 42,225,127,249,110,128,117, 61, 12,110,120, 18,238,187, 18, 48,110,220, 56,241, +223,172, 2,186,101,217, 55,215,111,103,100,100,216, 86,168, 97,146,147,147,155, 58,149,201,131,230, 39,255, 38,149, 69, 74, 74, + 74,179,148,101, 70, 70, 6, 63,121,120,242,125,175, 23, 71, 50,245, 56,146,153,223,226,219,172,167,102,122,240,192, 43,161,187, +251, 8,123,224,129, 7, 30,120,224,129, 7,127, 95, 80,158, 44,240,192, 3, 15, 60,240,192, 3,143, 2,224,129, 7, 30,120,224, +129, 7, 30,120, 20, 0, 15, 60,240,192, 3, 15, 60,240,192,163, 0,120,224,129, 7, 30,120,224,129, 7,255, 8,212,154, 5,112, +246,236, 89,183, 35, 83,235, 11, 38,244,200,243,200,243,200,243,200,115, 82, 94,163,211, 68, 91,128, 60, 79,249,122,228,213,194, + 43,175,188,210, 14,128, 2,128,208,186,213,121,139, 74,159,199, 3,224,129, 7, 30,192,223,223,159,242,247,247, 39,254,254,254, + 2, 0,188,150,150, 62,219,190,243,118,251,207, 55, 21,245,173,143,239, 65, 11,194, 19, 79, 60, 17,243, 15,120, 13,219,218, 87, +146,191,235, 11,120, 20,128,127, 56,154,176,221,186,203,136,139,139,139,177,118,186, 53,135,245,218, 63, 82, 94, 11, 7,137, 12, + 11, 35, 0,160, 82,169, 88,149, 74,197,169, 84, 42, 19, 0,179, 59,194, 94,126,172,119,201,172,177,189, 39, 2,192,172,177,189, +191,121,249,177,222,235, 0, 96,225,164,135,200,194,167,163, 5, 47,143,233,229,214,154, 34,246, 75,209,102,102,102,214,218,124, +167, 41,228,111, 87,239,155,115,173,253,166,202,108, 14,121,220,125, 80,108,254, 82, 69,233,137, 39,158,136,217,187,119,175,236, + 31,208,198, 12,176, 44, 22,119, 95,121,180, 77,176,136,234,220, 58,148, 31, 33,109, 71,133, 5, 4, 11,189, 69,130,102,251, 61, + 62,254, 25,160,172, 90,152,222, 90, 32, 30,216, 41, 0, 78,236,173, 98, 4, 32,106,234, 79,101,101,101, 33, 45, 45,173,214,242, +127, 11, 22, 44,176, 53,116,226,142, 60,246,135,192,218, 5, 61, 37,171,165,200,107,241, 69, 31,229, 45,225,162, 58, 72, 1, 0, +101, 52, 51,189,181,144,255,157,237,230,101,117,181,168,172,178,146,118, 70,208, 75, 99,122,229,155,205, 92,248,195, 67, 91,249, +117,237, 58,236,128, 72, 68, 21,205, 73, 25,244,159,255,146, 11,184,163,210, 61, 33,224,147,159, 0,114, 17, 64, 79, 87, 19, 89, +119, 41,218, 38, 46, 55, 91,139,252,237,234,190,187, 75,229, 18, 23,175,223,119,121, 9, 9, 9,182, 53,250, 29,190, 83, 66, 66, + 2,151,153,153, 73, 92,200, 59,210, 12,114,156, 34,127,150,101, 65, 8,193,200,145, 35,185, 35, 71,142, 16, 23,203, 88, 8,192, +212, 28,233, 9, 10, 10,154, 37,151,203, 63,119,243,235,126, 0,148,104,190, 85,176,107, 97, 88,159,126,212,179,225, 81, 98,101, + 68, 43, 97,104,247,112, 62,159,132, 82, 58,149,138, 17, 35,140,166,250,183,163,159,155, 48,134,110,234,111, 56,171, 73,132, 0, +120,220,250,217,210,224, 7,224, 41, 0,233,214, 79,191,102,146,251,125, 75,179,176,221, 42, 96,202, 97, 17, 15,178, 54,168,208, +166,144,205,252,249,243,239, 33,127, 0, 72, 75, 75,139,157, 63,127,190,203, 86,206,198,215,188,239, 33,107, 0, 96,127, 8,196, +198,215,188, 31,168,188,212,212,212, 24,138,162,184,103,158,185,187,164,237, 43,175,188, 18, 3,128,139,136,136,224,218,181,107, +199, 5, 7, 7,115, 79, 63,253,180, 83, 50, 55,164,126, 20,115,156, 26,194, 45,141,142,175,177,126,215, 45, 93, 23, 51, 15,171, +185, 57, 17, 27,184, 25,237,182,114,227,131,247,115,131, 58, 44,115,202, 58,238,208, 46,172,117, 76, 7, 41,247,218,156, 25,198, +229,111,189,200, 45,124, 97, 26, 90, 11,249,223,189, 59,251, 89,172,124,227,101,110,217,220, 23,216,110,126, 62, 70, 0,104,221, + 58,152,111, 45,255,122,113,102,231,211,157,195,195,189, 2,158,153, 18,153, 54,113, 82,123, 1,203,177,210,144, 86, 34,239,143, + 95, 63,145, 54,239,169,126,223, 62,254, 88,155,200,136, 8,239,226,127, 47,238,237,238, 54,153,246, 27, 69,185,180,105,148, 3, +203, 31,205,224, 9,104,113, 30,128,204,204, 76,146,144,144, 80,243,189,132,132, 4,174,190,161, 19, 43,105, 59,173, 84, 52,148, + 14, 59, 57, 77,238,232,236,201,127,193,130, 5, 24, 57,114, 36,247,235,175,191,186, 35,138,110, 70,227,181, 44, 40, 40,104,146, +155,223, 13,183, 26,156, 82, 0, 72, 74, 74,138, 76, 74, 74,218,147,148,148,148,107,119,236, 76, 74, 74,114,105, 27,229, 79,214, +127,194, 79, 93,150,226,247,248,147,147,194, 21, 3,123,118,224,183, 13,239,168, 54,136, 59, 86,155,245,237,137,159,119, 91, 58, +204, 20,198,148,221, 10,248,250,139,141, 66, 23,121,220, 45, 5,160, 61,128,111, 0,196, 91, 63,219,183, 32,126, 11, 6,176,197, +170,156, 28, 7, 48,214,122, 30,220, 12,178,167,192,137,241,210,150,174, 0, 56,129, 33, 0,174, 0,136,114,199,186,177,185,208, + 35, 34, 34, 98,237,173,126, 59,203,191,230,158, 51,238,118,219, 51, 73,195,133,118, 86,186, 2,212, 20, 69,205,185,237,222,131, +144, 7, 0, 39, 78,156,144,137,197, 98,228,230,230,222,163,108, 21, 23, 23,147,146,146, 18, 50,100,200,144,216, 61,123,246, 56, +149,135,173, 79, 92,148,113, 98, 1,250, 84, 8,107, 89,195,132,226,176,174,248,121,242, 77, 73, 34,145,142,189, 16,203,220, 26, +239,208,109, 26,211, 65,202, 69, 8, 37,183,223,124,117,186,177,157,143, 80,168,186,120,140,120,149,159,199,188, 17,157,209, 54, + 64,130,242, 51, 71,201,157,211,199,168, 5,179,102,208, 49, 29,164, 92, 55, 47, 95,147,181, 67,173, 23,173, 90, 9, 71, 9,133, +148,248,248,241,219,243, 79,157,188,213, 61,172, 93, 7, 83, 64,171,118,196,215, 23, 94, 29,162,188,162,130,130, 68,157, 88,142, + 51,254,124,178, 92,251, 0,235, 48,103,111,241,219, 14, 55,149, 0,174,158,207,186, 71,125,207,253, 85,242,106,148, 0,185,124, + 52, 50, 50, 20,104, 10,249, 55,166, 84,212,145,211, 36, 15,192, 19, 79, 60, 17,179,103,207, 30, 25, 33, 4, 20, 69, 33, 47, 47, + 15, 71,143, 30,117, 75,150,217,108, 62,111,245, 0, 52, 71, 60,139, 68, 46,151,239, 12, 10, 10,122,218,141,239,218, 60,206,154, +164,164,164, 94, 0, 14, 28, 60,120,112, 92, 86, 86,214, 16,219,145,157,157,253,148, 76, 38, 59,148,148,148,228,212,144,199,130, + 69, 11,196,149,183, 42,130,245,156, 49,130,227,147,110,156, 72,212,157, 21, 8,187,179,132,234,204, 18,126, 39,134,199,139,100, + 89, 18,174, 37,230, 80, 70, 72, 5,126,113,108,175, 88,252,100,232,125, 85, 0, 62, 1,112, 16,192, 60,235,231, 39, 77,200,236, + 64, 0, 75, 0,236,177, 86,244, 61,214,243, 64, 55,229, 29, 1,176, 23, 64, 50,128,245, 0,222,176,202, 60,210,196, 74,225,111, +253,244,110, 6, 11, 27, 86, 11,107, 73, 99,150,214, 3,196, 67, 0,142, 1,104,109, 85,158,158,117,229,203, 89, 89, 89, 50,123, +203,127,193,130, 5,178,180,180,180,216,180,180,180, 88,123, 37, 32, 45, 45, 45, 54, 43, 43, 75,230,140, 60,123, 75,157,154,162, +192,213,189, 51,112,117,239,140, 90,164,205,254, 16, 8,119,229,217, 44, 77,119,228,165,167,167,199, 28, 63,126, 28,211,167, 79, + 71,113,113, 49,146,147,147, 99,234,123, 70, 44, 22,203,218,180,105,227, 48,255, 50,210,211, 99,218, 28,255, 3, 37,211,135, 65, + 88,172,194,231, 75, 62,142,169,109, 28, 3,233,233, 25, 49, 2, 67,132, 44,168,141,222, 33,249,207,122,105, 10,253,175,249, 51, + 56, 97,209, 25, 97,224,157, 11,228,194,109, 53,194, 67,188,241,112,143, 48,180, 85, 94,193,117,141, 30,124,150, 67, 0,225, 9, +254,239,197,233,220,107,175,188,112, 37,166,131,180, 65,210, 81, 40, 53, 65,131, 6,249,164,245, 30,242,184,201, 55,168,163,200, + 39, 32,148,149,248,120, 27,131, 90, 5, 27, 66,194,219,243, 21,114,141, 72,173, 98,160, 80, 25, 93,113, 99,199, 56, 67,156, 78, +198, 3,220, 99,249,215,167,148,187,160, 4,144,122, 62,235, 30,245, 61,231,148, 60,110,107,224, 61,135,139,242, 26,202,211, 38, +145,118, 93,165, 34, 35, 67,129,230, 34,127,138,162,184,125,251,246,201, 88,150,197,235,175,191, 14, 66, 8,142, 30, 61, 10,203, +214,187, 44,113, 67, 30,104,154,254, 29, 0,211, 12,158, 0, 57, 0,200,229,242,237, 65, 65, 65,177, 46,126,151, 15, 0, 51,103, +206, 20, 1,200,202,206,206,238,178,108,217, 50,166,174, 18, 26, 28, 28,140, 67,135, 14,197, 36, 37, 37, 57,212,202,120, 68,224, + 71, 51, 92, 91,163,209,212,197,204,178,189,204, 44, 59,192, 76, 72, 47,240,120,237, 9, 33,109, 64,120, 97, 44,135, 8,142,102, +219,169,245,166,144, 80, 63, 70, 72, 13,210,220, 55, 5, 32,220,106,241,175,132,101,156, 99,165,245, 60,220,141,223,154, 1,160, +216, 90,153, 22, 1, 8,178,126, 18,235,117, 87,247,218,253, 55,128,107, 0,214, 1, 16,192, 50,134,205, 0,248,204,122,189, 41, +251, 47,143, 4, 80, 1, 96, 84, 51,145,236, 11, 0,222,183,126,182, 52,244, 4,240, 35,128, 71,173,158,148,158,238, 10,178,145, +191, 61,233,219, 43, 1, 46, 87, 78, 43,249,219, 80, 87, 9,112, 71, 94,157,206,140,184, 42,239,240,225,195,160,105, 26, 3, 7, + 14,140,237,214,173, 27, 10, 11, 11,107,222,143,101, 89, 72,165, 82,110,241,226,197,178,227,199,143, 99,220,184,113, 14, 59, 20, + 67,238, 41, 80, 52, 3,229, 64,105,172,177, 91, 48,174,109, 56,124,151,180, 88, 14,115,164, 27,184,195,139,131,101, 55,142,251, + 35,238,249,171,142, 59, 40,138, 87, 93,113, 33,151, 45, 83, 26, 80, 85, 77,115,241,253, 34, 56,127,137, 16,183,148, 90, 84,168, +244, 72,236, 31,193, 81,132,112,191,253,180, 31,170, 35, 39,184, 51, 59,127, 46,106, 76, 92,238,239,109,231,132,132,250,117,108, + 27, 17,197,120, 73,216,142, 35, 31, 79,244,233, 48, 48,121,124,235, 46, 79,198, 5,181,141,238, 43,175,110, 29,111,162, 77,166, +235, 5, 90,167,134,222,172, 4,229, 84,157,200,204,204,148, 57,152, 25, 80,239, 61, 39, 98, 94,254, 17,179, 3,146,147, 3,145, +156,124, 87,185,181, 17,119,115,144,118, 61, 10,140,219,150, 63,199,113, 48,153,238, 14,217, 15, 31, 62,220,214, 94,220,149,109, + 18, 8, 4, 38,150,101,143, 91, 61, 1, 77, 81, 2,106,134, 62,229,114,185, 44, 40, 40, 40,217,133,239, 22, 38, 38, 38,250, 29, + 62,124,120, 69,118,118,118,235,175,191,254,154, 93,188,120, 49,127,243,230,205,232,210,165, 11, 0, 32, 50, 50, 18, 42,149, 10, + 75,151, 46, 53, 31, 58,116, 40, 62, 41, 41,233,213, 70, 37,178,140,191,217,204, 68,154, 25,115, 79,147,217,212,159, 71,145, 40, + 33,159, 18,137, 5, 60, 53,223, 75,120,219,219,151,119,135, 39,230,140, 98, 30, 47,136,207,208,109,110,156,249,221,119, 70,200, + 39,110,199,189, 57, 82, 0, 30,179, 90,135,246, 56,102,189,238, 10,166, 1,120, 29,150,177,146,247, 1,252, 1,203,252,201, 63, +172,231, 82,235,253,105, 78,202,243, 2, 48, 11, 64,146,245,220,104,119,192,122,125, 22,238,221,202,215, 89, 76, 1,240,149,245, +179,169,120, 30,192, 28,107,158,205,177,158,183, 20,116,178,186,176,126, 6, 48, 23,192,108, 0, 49,240,160, 65,148,150,150,202, + 6, 15, 30,140,217,179,103,231, 12, 30, 60, 24, 39, 78,156,192,250,245,235, 99, 90,183,110, 45,163, 40, 10,133,133,133,164,178, +178,146,188,246,218,107,177, 71,142, 28,145,189,244,210, 75,141,146,205,208, 27,183,100,101,131,187, 35,121,246,236,156, 63,195, +204,177, 61, 85, 65,178,140,245, 25, 49, 22,237, 4, 88, 87,248, 60,217, 82, 25, 79, 70,190, 86, 26,123, 52, 83, 42,139,125,120, +101,131,229, 83, 66, 51,171, 62,255,124,115,208,246,243,165, 55, 55,159, 41, 86,110, 56,126, 93,123,163,204,192, 81, 28, 5,131, +206,140,138, 10, 26,121,197, 10,243,174,194, 82,205,158, 91,101,202, 29, 69, 37,151,143,149,149,143,185,105, 52,125,212,144, 76, +191,192,240,118,250,106, 69,219, 30,209,143, 80, 52,137, 28, 89,122,249, 71,125, 96,144,183,164, 67,247,126, 21, 28, 83,113,158, +240,252, 66, 88,150,229,221,185,163,119,198,139, 87,215, 53, 93,159, 27,188, 86,148,187, 19,227,207,164,174,165,111, 59,238, 7, +161,181, 20, 52, 22,148,103,231,206,111, 18,154, 67, 78,117,117,181, 12, 0,248,124, 62,222,122,235, 45,228,229,229,193,205,113, +127,123, 24, 1, 24,141, 70,163,177,180,180, 52, 11, 77, 11, 8,212,212,114, 7,200,229, 25, 65, 65, 65, 19,156,245, 20, 27, 12, +134,254, 11, 23, 46,124,242,149, 87, 94,225,122,247,238, 77, 0, 96,201,146, 37,200,207,183,236, 70, 57,100,200, 16,176, 44,139, +225,195,135, 83,211,166, 77,227, 46, 95,190,188,238,249,231,159,127,222,203,171,126,106, 98, 89,206,144,115,240,224,182,194,194, +235,207,155, 77,230, 48,158, 64, 98,224, 17,177,138, 18, 9, 85,148,216,171,156, 22,120, 85,130, 18,221,102,197,102,131, 70, 85, +213, 74,182,251,236,123,230, 83,191,187, 29,247,230, 72, 1, 24, 3,224, 80,157,107,135,172,215,157, 5, 15,192,187, 0, 18, 1, + 84, 53,240, 76,149,245,254,187,112,110, 92,103, 26,128, 3, 0, 84, 13,220, 87, 89,239, 79,115, 35, 79, 30,129, 37,134,224, 67, +235,231, 35, 77,168, 92,241, 86,175,201, 16,107,122,134, 88,207,227, 93,148, 19, 8, 32,192,137,195,213,161,148,161, 0,157, 16, + 39,240, 0, 0, 32, 0, 73, 68, 65, 84, 78,226,110, 4,112,145,213,211,227, 86,156, 71, 93,139,191,174, 71,192, 85,176, 63, 4, +162,243,184,111,106,206, 59,143,251,166,222, 64, 62, 87,228,213, 33, 19,206, 21,121,107,215,174,229,242,242,242,112,250,244,105, +180,107,215,142,251,229,151, 95,160, 86,171,113,233,210,165,123, 44,218,119,223,125, 55,167, 71,143, 30,177, 91,183,110,109, 80, +222, 23,107,215,114,237,243, 46, 32,244,116, 62,100,237,198,113,189,175, 48, 50, 74,109,130,249, 82,245, 61,207,190,249,238,139, + 57, 17,209,167, 99,139,254,152,210,160,245,124,173,164,228,237, 18,154, 89, 85, 81,169,151,210,122,115, 96,254, 45,181,207,158, +203,165, 85,198,200,190,232, 17, 26, 4, 0,216,115,246, 14,191,160,172,218, 15, 64, 96, 25,109,232,113,211,104, 74, 40, 40, 45, +125,187, 33,153,163,198, 39, 82,221, 70,126,208,155,209,254, 81, 28,209,125,180, 68, 32, 48,211,215,254,200, 82,150, 22, 95,186, + 83, 94,252, 91,177, 90, 94, 10, 80, 20,145,107,104,255, 89,137,253, 29,213, 27, 82,135, 84,234,115,171,215, 10, 4,180, 62,255, + 87, 69,227,255,237, 96,111,245,215,245, 8,184,235, 85, 8, 10,202,110,178, 28, 0, 24, 57,114, 36,119,248,240, 97,176, 63, 4, +128,227, 56,124,252,241,199, 56,114,228,136, 77, 81,115,187, 12, 20, 10,133,145, 16, 50,226,212,169, 83,134,240,240,240,184, 38, +122,117, 2, 0,203,108, 0,235,231, 12, 0,108, 80, 80,144, 51,134,154,106,247,238,221,165,251,247,239,255,106,243,230,205,228, +232,209,163,100,244,232,209,156,141,252, 1,203,118,247, 34,145, 8, 69, 69, 69,216,183,111, 31, 9, 12, 12,100,134, 13, 27,246, + 43,203,214,111,180,119,142,234,114,123,200,144, 33,179, 46, 94,252, 51, 66,173,213,132,113,140,201, 4, 10, 70,198, 72, 85, 27, +141, 70,165, 26,101,183, 88,163,225, 78,105,113,153,241,231, 61,123,215,180, 10, 14, 41,162,105, 93,181,187,121,201,175,167, 97, +216, 10,166,181,245, 56, 92, 71, 81, 56, 12, 96, 1,128,182, 0,202, 28,100, 62,129, 37,118,224, 56,128, 27, 14, 20,142, 27,214, +231,230,161,225, 56, 3, 91,250, 38, 3, 72,113, 32,239,107, 88,134, 24,190,114,144, 62,251,138, 40,133, 37,206, 97, 32, 0, 53, +128,247, 0,156, 6,208, 17, 64,161, 19, 46, 68,123,121,207, 0,120,209, 74,178,122,107, 90,245,214,243,116, 88,226, 1,190,119, + 66,222, 12, 0,175, 56, 89,193, 9, 44,177, 16,223, 56, 72,223, 42, 0,190,176,196, 58,236,182,166, 77,108,213,164,255, 0, 48, +216,234, 17,248, 21,119,227, 53,234, 69, 92, 92, 92,172, 61,209,219, 43, 1,117, 99, 3,226,226,226, 98,179,178,178, 26,125,129, +184,184,184, 88,106,202,221,113,123,246,135, 64, 80, 86, 37,160,238, 88,190,219,242,166, 40, 56,119,228,157, 61,123, 22, 17, 17, + 17,184,124,249,114, 77,157, 25, 54,108, 24,151,155,155,139,241,227,199,223,235,166,242,242,146,137,197, 98,168,213,234,122,229, + 73,207,158,133, 50,162, 13,250, 93, 62, 81, 35,239, 77,191,199, 98,162,114, 85, 50,106,188,248, 30,197,169, 56,159,134, 72,108, +178,212,204,134,149,128,133,104,215,238, 55, 0, 67, 56,112, 60,220,168,120, 67,199, 48, 96, 12, 22,231,216,197,138, 10,220, 48, +208,155,248,132,104, 64,136,169,160,180,116, 91, 99,249,215, 86,218,109, 33,128,212,252,163,243, 11,197, 97,147, 21,165,101,226, +118,101, 37,167,196, 16, 4,117, 42, 44, 50,135, 87,149,221,132, 80, 40, 8,237, 25,230, 61, 77,169, 49,125, 11,224,166, 35,203, +213, 58,247,223,225, 48, 64, 66, 66, 66,108,102,102,102,142,203,236, 94,103, 8,224, 31, 16,168,219,100,175,128,139,223,231,154, + 42,111,212,168,145,156, 76,150, 3,178,205, 18,143,125, 96,177, 47,198, 44,215, 96,228,200,145,112,113,218,223, 61,176,141,213, + 63,252,240,195,186,102, 80,232, 20, 65, 65, 65,211,237,140, 83,163, 92, 46,223,227,228,119, 25, 0,229,187,118,237,146, 61,245, +212, 83,209, 43, 86,172,232, 99, 54,155,137, 68, 34, 65, 92, 92, 28,126,249,229, 23,176, 44,139,113,227,198,113,243,231,207, 39, +253,250,245, 51, 78,158, 60, 57, 50, 33, 33,225, 78,191,126,253,234, 87,192,230, 36, 51, 49,143,140,217,212,171,119, 31,255, 83, + 39, 79,174,252,157,207,239,213, 33,178,195,151,126,193, 33, 37,130, 16, 49,119,120,223,161, 64,185,162,106, 68,120, 80,200,251, + 93,186,116, 57,236, 19,230,189,254,147,101,159,211, 13,201,115, 85, 1,224, 1,136, 6, 48, 12,192, 50, 0,175, 89, 43,131,119, + 29,242,251, 6,150,113,246,127,193, 50, 36,144,215,136,135,225, 33,171,245,235,140, 59,254,184,213,187, 64, 53, 34, 47, 4, 64, +164,149,152, 27,147,121,218,250, 92, 40, 44,227,249, 13,201, 19, 90, 45,231, 36, 88,166, 17, 62, 3, 32,223, 42, 59,223,122,190, + 25,150,113,242, 77,176, 12, 93,208, 14,228, 77, 1,240, 5,128,110, 86, 37,201, 62,157,183, 97, 9, 90,188,108,125,246, 7, 7, +242, 94,135,101,118,131,206,137,252,243, 2,176, 31,192,119, 14,202,227,105, 0,255,177,126,254,110,151, 62,129,181, 44, 51, 1, +172, 1,176,220,122,255,118, 67, 63,152,149,149,149, 3, 0,197,197,197, 50, 91,180,127, 93,171,191,184,184, 88,102,255,108, 99, +176, 61,179,233, 87,186, 38, 58,191,174,149,190,233, 87, 26, 15, 66, 94,110,110, 46, 70,140, 24,129,203,151, 47,223, 37,113,169, + 52,118,235,214,173,178, 14, 29, 58,196,178, 44, 43,139,140,140,228, 88,150,133, 94,175,199,207, 63,255,140,232,232,232,216,125, +251,246,213, 43,175,107,110, 46,190, 15, 14,173,149, 87,221,231,142,129,118,229, 77,224,209, 80,112, 44, 48, 39,242, 43,174,154, +245,129, 92,239, 7,121,126, 16,250,142,216, 29,123,105, 71,227,110,246,107, 37, 37,219, 1,108,239, 24,209,182, 43,128, 55,140, +102, 22,219,206, 23, 98, 68,152,101,184,147,112,156, 70,195, 48,203,202,203,203,239, 56, 65,166, 43, 57,142,243,206,191, 44,127, + 86,121,122,107,171,242,219,114,148,223,209,128,207,175,242,174, 86,112, 80,170,205, 92,104,136, 48,128,207, 98,146,222,104,254, +126,217,235, 15, 7,252,235,147,227, 74, 7, 68,147,227, 68,167, 77, 92,137,100,191, 7,163,173,158,151,236, 68, 87,191,105,243, +134, 57,138,202,183,127,142, 56, 43,143, 36, 42,208, 68,121,247, 88,236,153,153,153, 24, 56,112, 96, 75,210, 69,184,156, 57, 23, + 0, 27,249,159,103,176, 65,102,105, 99, 77, 37,127, 91,221,224,241,120, 33,124, 62,191,252,248,241,227, 95, 62,252,240,195,238, +174,243, 0, 0, 17,114,185,124,157, 85,177,152, 34,151,203,127,176,125, 58,227, 84, 4, 80, 13,160,114,197,138, 21,125,231,205, +155, 87,122,246,252,249, 54,122,189,158,200,100,135, 32, 18,139, 64, 17, 10,135, 14, 29, 34, 61,122,244,208, 37, 36, 36, 12,158, + 60,121,178,195, 54,151,115,232, 0, 51,225,169, 9,107,250,246,237,223,129,102,140,143, 95,203,191,250, 34, 91, 88,240, 2, 0, +136, 65,113,189, 59,117, 61, 21, 26, 26,146,195,227, 11,223,254,207,226,148,234, 79,150,125,236,118, 70,214,167, 0,188, 97,213, +134,198, 3,184, 4,192,167,158,239,237,181, 90,236,241,176,204, 35, 79,106,196,253,223, 25,150,232,114,103, 20,128, 42,235,243, +188, 70,228,197, 0,184,234,164,188,171,214,231,119, 52, 34,111, 22,128,153, 0, 46, 0,152,111,125, 47,123,217, 50,171,245, 63, +199,106, 13,111,180, 90,217, 13,201,155, 97,205,143,126, 86, 47, 66,125,233, 84, 91,239,219, 60, 1, 27, 27,145,247,181,181, 83, +240,114,178,243,250,218, 65,254,125,100,245,108, 28,176, 42, 53,168, 35,251, 23, 0, 61,172,101,145,111, 85,164, 28,186,118, 87, +175, 94,205, 1,144, 53,211, 66, 64,100,230, 26, 45, 55,115,141,182,158,133,123,220, 10,114,106, 22,121,127,254,249, 39,249,243, +207, 63,107, 93,251,238,187,239,114, 0,144, 31,126,248, 1, 0, 72, 81, 81,237,152,186,134,200, 31, 0,218,255,249, 39, 1,106, +203,123,249,131, 5, 22,114,252,208,154,166,186, 33,122, 59, 92,232,133,205, 92, 33,248, 0,175, 26, 53,228,111,101,245, 59, 98, +177,216,169, 69, 68, 56,142, 35,132,144, 37, 11, 19,123,122,133,181,139,156,192,194,171,115, 73,113, 25,207,100, 80,114,173, 67, +125,136,143,183,128, 48, 38, 22, 10, 37,205, 16, 9,145,168, 52, 76,167, 70, 12,130,134,234,108,221,255, 31,164,139,222,126, 56, +162, 33, 98,225,224,222, 44,128,230,144, 87,175,197,222,161, 67, 7,156, 62,125,186, 69,144, 63,251, 67, 32, 14,156,103, 0, 0, + 27,101, 52,190, 63, 78,219,188, 48,164,185,202,199,108, 54, 87, 1,192,128, 1, 3,154,180, 32,144,141,252,173,168,180,126, 58, +187,192,142,208,106,152,157, 1,128, 79, 63,253, 52,252,249,153,207, 47,122,104, 96,244, 12,141, 90,237,207,152, 25, 83, 88, 88, +216,157,240,240,240,171,106,181,122,249,228,201,147,243,157, 77,215, 79, 63,254,196, 0,120,237,217,233, 47, 14, 31, 54,124,248, +120,137, 68,210,138,128, 51, 91,102, 78,112, 85,122,173, 98,221,149,243,197,183,189, 69,194, 38, 45,124, 87, 87, 1, 48,195, 18, +164,230,204, 56,252, 41,235, 97, 70,195,203,139,154, 97,137,168,119,118,190,166, 12, 64,182, 3,121,187, 96, 9, 90,115, 6,207, + 58,145,190,207, 1,124,233,168,239, 7,240,170,221,119, 26,147,247,141,213, 99,224, 8,133, 86,203,222,153,244,185, 50,223,245, +115, 7,242, 30,117, 66,158,205,219,176,209,154, 55,206, 44, 31, 75,226,226,226, 98,234, 70,253, 91,221,234, 57,238, 52,244,184, +184,184, 24,187,149,250, 90,154,188, 22,143,235,165,183,141, 84,187,118, 27, 95, 89,153, 62,211,118,141, 22, 80,223, 25,116,236, +254,178,226, 98,141, 83,153, 70, 8,247,159, 89, 67,200,123,159,255,182,240,231, 53,161, 59, 79,156,188, 61, 59,196,159,125,146, + 10,242, 11,224, 56,128, 16,206,104,100,216, 50, 22,168,164,141,108, 64,233,109,189, 75,171,147, 89,221,252,178, 58,231, 45, 37, + 11, 91,220, 74,128,127, 23, 60,182, 92,115,191,223,145, 5,208, 70, 44, 22,223, 30, 48, 96,192,163,103,206,156,105,178, 64,185, + 92,126, 48, 40, 40,104,166, 92, 46,223,232,130, 2,192, 88, 61,167, 0,128, 13, 27, 55,164,192, 50, 60,221, 44,248,246,187, 47, +127,133,101, 40,246,190,160, 62, 5,192,224,142,214,215, 72, 33, 25, 61,242,254,177,242,106,193, 74,164,164,206, 53,183, 43,103, + 75,151,247,119,128, 92,167,123, 1,240, 50, 1, 8, 97,193,149, 26, 12,244,230,178,178,138,115,214,142,203, 41,188,247,249,111, +220,143, 31,141, 37,227, 95,219,159, 11, 32, 55, 97,112,215, 55,130,130, 68,139,248, 60,194,221,174, 50, 92,185, 77, 51,155, 36, + 2, 74, 44,225,243,120, 38,134, 21,187,146,190,204,204,204, 28,219,242,182,214, 79,183,148,177,123,166,254,217,185,254,157,152, + 22,216, 88,189, 39, 46, 92,255,171,229,221, 55,197,167, 41, 74, 24, 53, 69, 1, 66, 8,158,156, 56,171,222, 62,100,215,143, 25, +205,245,174,101, 0, 72,115,144,191,157, 18,176,209,133,199, 3,173,237, 72,251,119,237, 31,248,245, 84,196,230,140,152,241,200, +251,103,203,243,160,165, 43, 0,114, 57, 39,151,203,103, 53, 85,206, 83,111,238,231, 0,224,217,145, 61,200,183, 71, 46,126,172, +231,230,172,121,109,234,241, 30,180,150, 68, 5, 9,248,173, 64,136,206, 71,194,175,232,213,205, 47,127,219, 1,215,100, 91, 93, +217, 77, 89,111,254,126,145,231,223,197, 3, 64, 90,146,215, 36, 35, 35,157, 75, 78,158, 77,118,253,152,241, 79,111, 94,225, 86, +131,217, 23,150, 61, 1,254,118, 32,238,238, 35,236,129, 7, 30,252, 13, 53,126, 30,224, 37, 34, 96, 89, 14, 32, 4,213,122, 79, +243,247,192,131,255,217,254,192,147, 5, 30,120,240,191, 3,198, 12,168,117, 78, 47, 59,239,129, 7, 30,252,131, 65,121,178,192, + 3, 15, 60,240,192, 3, 15, 60, 10,128, 7, 30,120,224,129, 7, 30,120,224, 81, 0, 60,240,192, 3, 15, 60,240,192,131,127, 34, +106,197, 0,156, 61,123,214,237,104,212,250,130, 9,235,147, 55,254,145,232,152, 94,125, 58,201,218,180, 11,143,213,232,181,178, +195,178,220,216,172, 67,231,114,220,149,215,123,240,152,152,126,125, 6,203,238,148,150,194, 91,226,141,155, 37, 5,177,121, 39, +246,186, 45,175,185,223,119,238, 52, 42,102,200,224, 14, 50,137, 55, 15,124, 30, 5, 34, 38,120,114,234, 69,226,174,188,228,255, +151, 27,243,208,224,135,100,254, 62, 60,128, 15, 36, 12,174,127,142,211,131,122, 95,143,188, 22, 43,175,209,169,102, 45,253,125, + 59, 12,120,154,243, 99, 11,238,107,250,126,127,183,200,237,142,180,255, 7,145,247, 92,251,184, 85,169,219,242,222,168,188,119, +195, 85, 79,125,254, 75,228,241, 81,207, 20, 89, 87,228,197,198,198, 70, 25, 12, 6, 69,110,110,174,242, 65,190,175,203, 10, 64, + 67, 88, 29,131,206, 0, 58,192,178, 78, 64,193,252, 28,220,112,246, 7,198, 12,239, 16, 67,192, 34, 36, 32, 8,185,135,207,200, +222,153, 59, 3,195, 70, 15, 3,163,213,201,122,116, 27, 9,150,133,108,222,139, 15,199,246,239,223, 7,215,174, 21, 65,165,212, + 98,237,198, 35, 57, 13,201, 27, 56,226,153, 24, 14, 4,145,157, 58,200,146,223, 92,142, 23,158,121, 12,223,252,247, 51, 0, 98, +236, 61, 87, 2,138,130,108,245,146,197,200,207,191, 2,169, 52, 18, 34, 9, 31,183, 74,242, 99,161,171, 63,201,139, 30,235,203, + 9,133, 66, 72, 36, 18, 20, 20, 20,160,109,168, 31, 90,241,125,208, 54, 34, 0,129, 18,127,120, 19, 51, 40,138, 2,199,154,161, + 19,241,161,186,163,194,164,255,102, 57, 44,168,212,133,125, 56, 95,137, 10,126, 1, 66,248,120,243, 33,148, 80,224,243, 0, 74, +200, 71,206,207,209,156,137,227, 33,110,194, 9,167, 11,188,247, 83,171, 99,194,195,195,209,174, 99, 59,153,222, 96, 4, 37,146, + 0, 38, 96, 78,218,169, 24,189, 78,139,175,254, 21,147,243, 0, 21,201,150, 54,143,249,127, 25,174,150,133,211,207, 39,188,179, +200, 27,192, 67,173, 37, 94,255, 41, 45, 45,237, 38, 16,139,192,122,121,125, 8, 96,125,230,135, 41,213, 45, 37, 3,162,122,140, +138,185,113,241,112,125,123, 13,252, 35,234,104, 70, 70, 6,249,102,211,166,203, 34,161, 80,194,178,172,191,183,143,143,207,132, + 39,159,244, 2, 64, 39, 39, 39,115, 45, 52,205, 20, 0, 36, 39, 39,179,205, 32,206,207,223,223,127, 65,215,174, 93, 39,139, 68, +162,118, 37, 37, 37, 37,165,165,165, 39,105,154,254, 0, 64,129, 27,242, 2, 2, 3, 3,151, 63,242,200, 35,143,135,133,133, 73, + 79,157, 58,117,231,194,133, 11,199, 13, 6,195, 82, 88, 86,136,117, 26,163, 70,141, 74,141,136,136,120,219,219,219, 27,190,190, +190,167, 15, 28, 56, 16,253,183,241, 0, 52, 64,254, 60,111, 17,255,161, 25,195, 59,174, 98, 57,206,112,244,202,157, 79, 87,199, +168, 14,204,207,193, 69, 71,223,149,223, 62,200, 25,171,229, 48, 85, 43,193, 55, 83,248,227,226, 21, 60,247,220,252,154,251, 20, + 5,252,150,187, 17,173, 34,194,101,108,181, 26, 52, 75,112,232, 80,110,236,218,141, 71, 26,144, 24,201,157, 62,113, 17,196,203, + 15,103, 46, 22,227,220,197,231,241,213,247,191,212,220,101, 89, 96,236,208,161, 64,117, 25, 0, 95, 20, 92,184, 4, 65,171, 0, + 12, 27,210, 75,166,212, 53,162,179, 16, 10, 32, 20,250,245, 25,128,214,222, 66,180,109, 37,134, 95,112, 16, 2, 69,190, 8, 20, +243, 32,224,241, 96, 50,155,161,100, 88,156,170,116,188,220,230,210, 87,219,115, 18,158, 2,126, 94, 94, 8,105, 21, 12, 63, 63, + 47,112,148, 25, 12, 91, 13, 51,204,240,241,241, 66,171,214,237, 80,112,185, 11,215,177,219, 55,141,118, 74,253,227,215,112,254, +190,222,240, 15, 8, 68, 72,171, 96,104,181, 90, 8, 69, 98, 8, 12,150,197,249,162,164,145, 50,185, 66,137, 71, 94,220, 24, 91, + 92,114, 11,138,178, 34, 84,157,203,112,164, 12, 56,221, 73,140,158, 57, 58, 54,123, 99,118,142, 19,178,238,171, 18, 80, 88, 88, +200, 1,128, 84, 42, 37, 45, 69, 94,120,120,248,115, 52, 77,111, 4,128,201,177,177, 84,198,214,173,238,116,190,150, 53, 82,237, + 28, 57, 28,199,129, 16, 82,243,105,187,102,123,206,193, 78,106,174,172, 39,239, 10,249,247,240, 54, 49,219,125, 3,252,187, 1, +128, 80, 34, 6,173, 55,128,213,234, 82,143, 31, 57,188, 36,225,157, 69,221, 51, 63, 76, 41,118, 36,231,211,119,231,114, 86, 11, +139,129,101, 8,146,181,246, 67,245,246, 69,125, 71, 61,142, 81,143, 61,225, 82, 25,221,184,120, 88,214,169, 87, 76,236,181, 63, +114, 92, 87,138, 19,228, 46, 61,158,152,152,136,173, 9,217,141, 62, 19,155, 93,123, 43,146, 30, 1,150, 87, 45, 55,176,208, 51, +150,114,213, 90, 63, 51, 6, 7,160,139,175,160, 81,121,171, 86,173,202,121,247,245,183, 66, 39, 78,158,228, 99, 48,232,177,250, +227,143,168,181,107,215, 26,230,206,157, 27, 14,224, 86,115,183,189, 73,147, 38,141,222,185,115,103,150,171, 74,212,204,153, 51, +185,194,194, 66, 84, 85, 85, 97,197,138, 21,240,245,245, 69, 76, 76, 12,164, 82, 41, 54,110,220,232,110,187, 27, 57, 96,192,128, + 77,111,190,249,230,181,174, 93,187,110,236,223,191,255,165, 59,119,238,180,203,205,205, 29,240,194, 11, 47,236, 81,171,213,169, +176,108, 0,231, 44, 98, 39, 79,158,156,153,146,146, 18,108, 50,153, 32,145, 72,224,237,237,221, 70,171,213, 62, 61,113,226,196, + 9,231,207,159,159, 11,224,191,206, 10,139,136,136,104,187,104,209, 34,228,229,229,113, 26,141, 38,160,206,109, 30,156, 91, 85, +181, 89,112,246,236,217,186, 94, 2,231, 20,128,213, 49,104, 15,203, 14,120, 60, 0,102,173,145,185,153,123,181,252,147,161,157, + 67,231, 63,210,163,205,146,214,254,146,182,171, 81,182, 5,192,149,249, 57, 13,111, 82, 99,172,150,163,117,167, 71,177,252,237, +201,216,104,199, 73,135,143,167, 67,171, 51, 98,220,232,249,120,120,216, 76, 60,147,248, 8, 36, 18, 17,104, 51, 3,141,142,150, + 53, 92,201,138, 0, 26,152, 60,125, 61, 94,126,115,118,205,213,177, 15,199, 64, 44, 22,225,199, 67,191, 96,239,177, 92,108,218, +240, 25, 12,122, 35,132, 60, 62,124,188,132,208, 86,149,196, 42, 75, 80,239,238, 99, 28,199, 1, 28,107, 57, 40, 22, 28,199,193, + 72,139, 44,221,147, 8,224,104, 51,204, 60,192, 12, 51,204, 52, 11,198,220,184, 2,187,240, 69, 41, 23,232,199,192,207,215, 27, +225,237,162,208,173,119, 39,248,250, 72,160,170,174, 64, 89, 69, 25, 20,170, 59, 48, 25, 8,188,188,188, 16, 18, 50, 12,149,229, + 33, 92,171,208,143,234,119,227,143, 92,204, 49,122, 29,244,124, 64, 40, 22, 66,175, 19,130,214, 9, 97, 16,139,192, 39, 12, 56, +240, 96,208, 87, 67,175,211,160, 93,187,182, 50, 33,143, 15, 57,212, 8,165,167,163,238, 26,243,117,177,114,211, 74,135, 21,232, +237,164,183, 27,239, 43, 19, 18,106,237,239,158,144,144, 48, 48, 40, 40, 40,159, 16, 98,224, 56,142, 31, 24, 24,232, 85, 80, 80, + 16,108, 93,221,173,173,187, 21,121,238,220,185, 83,237,126, 35,198,221,213,226,234,101, 75, 66,184, 57,115,230,196,174, 93,187, +214, 37,153,225,225,225,201,131, 6, 13,250, 96,120,191,126, 48,137, 68, 72, 75, 75, 99,103, 79,153, 18,151,254,195, 15,217, 46, +254, 62, 86, 45, 89, 82,115,190,224,253,247,145,182,116,105,163,231,206,136,173, 67,238,156,117,179, 24,110,244,232, 14, 61, 1, + 92, 79, 73,201,212,187, 72,254,185,189,123,246,244,179,181, 25,111,177, 4,183, 43,202,161, 86, 40, 49, 96,208, 96,175,159,191, +218,144,157,240,206,162,158,153, 31,166, 56, 90,155,157,153,247,193, 90,254,179, 79, 79,224,119,150, 74, 89,171, 18,128,247,211, +214,212, 86,162, 23,188, 6, 0,120,247,245,185,110,109, 39,237, 22,249,219,144, 25,228,194,195,163, 93, 18,237,205, 39, 56,183, +244, 69, 16,191, 86, 48, 95, 63, 7,227,245, 63,145, 47,215, 34,122, 95,185, 83,223,239, 63, 96,192,209, 89,211,146, 34,147, 94, +122, 33, 32,243,187,239, 89,169, 84, 74, 45, 79, 73,133,239,146,229,248,241,199, 31, 75, 51, 50, 50,168,230,242, 2, 76,154, 52, + 41,110,231,206,157, 7,118,238,220,105, 59, 31, 99,251,223,129,130, 18,115,224,192, 1, 89, 81, 81, 17, 58,118,236,136, 17, 35, + 70,192,223,223, 31, 74,165, 18,183,110,221,194,141, 27, 55, 48,102,204, 24,110,204,152, 49,177,111,189,245,150, 43,229, 52,233, +145, 71, 30, 89,189,106,213,170, 45,253,251,247, 95, 77, 8,185,101,215,143,147,248,248,120, 31, 0,185,214,195, 41,121,115,231, +206,221, 54,103,206, 28,234,244,233,211, 32,132, 32, 56, 56,184,230,216,183,111,159,112,200,144, 33,159,221,188,121,243,132, 35, + 65,147, 39, 79, 38, 59,118,236,224,138,138,138, 34,242,243,243,113,253,250,117,162, 82,169, 58, 2,224, 79,156, 56,209,188,107, +215, 46,238, 65,146,191,237, 90, 93, 37,128, 95, 15,249, 7, 71, 71, 5, 39,245,139, 12,154, 78, 8, 17,112, 28,103, 98, 45, 7, +109, 54, 25,244, 66,138,109,219,187,181,248,237, 86,126, 29, 59,237, 60,117,227,251,213, 49,236,209,249, 57, 13,239, 22, 7, 8, +209,163,123, 87, 80, 84, 14,242,149, 85, 0, 46, 65, 85,122, 21, 2,177, 8,187,246,124, 10, 93,165, 25,211,159,127, 3, 44, 11, + 60, 57, 97, 40,204,124, 31,135, 47,151,159,127, 9, 44, 11,140,235, 75,172,188, 18, 9,131,145, 70,252,216, 49, 16, 7, 80,216, +180,121, 63, 40, 10,216,246,253, 70,148, 94,255, 51,118,223,150, 85, 57, 13,109,151,200,114, 0,203,178, 96, 89, 22,102,179, 25, + 70, 1, 7, 19, 49,129,166,105,232,188, 12, 0, 43, 6,197,153, 97, 22,114,168,166, 13,208,170, 85,141,166, 45,196,199, 8, 62, + 95,130,224,224, 96,116,234,212, 9, 97,173, 7, 3, 60, 10,102,243,105, 80,156, 18, 6, 45, 3, 51,171, 69,217, 45, 57, 66,130, + 43, 17, 28, 48, 12, 31,174,250, 57,230,251,111,239,149, 37, 49, 48,224,140,149,128, 65, 4,154, 50, 65, 43,228,163, 90, 34, 0, + 95, 32, 4, 88,111, 16, 30, 65,181, 86, 7, 69, 89, 17, 10, 78, 31,131,188,184, 24, 44,203,130,226,120,110, 85,154,175,214,223, + 85,156, 95,120,229, 5,199,253,100,237,213,199, 12,153,153,153,139,222,124,243,205,217,197,197,197, 20, 33, 36, 36, 35, 35,227, +123, 88, 54,119,242,114,183, 34,207, 74, 72, 16,172, 91,183,110,243,157, 59,119,176,109,219, 54, 68,119,237,202,107,142, 6, 34, +149, 74, 73, 98, 98, 98, 12,199,113,178,181,107,215,186,188, 97, 17, 77,211,233,195,173,117, 74, 40, 20,162, 75,151, 46,216,126, +232, 80, 86, 72, 72, 8, 42, 42, 42,156,150,115, 31,183,170, 37, 3, 7, 14,228,108, 27,196,216,125,254, 57,106,212,168,210, 69, +139, 18,252, 83, 82, 28,175, 30,151,240,206, 34,111,111, 19,179,189,119,207,158,126, 60,138,194,171,207, 78,135,222, 96, 68,218, +151, 95,194, 75, 34,129,193, 96,128, 65,175, 71,223,254,253, 58,255,242,221,119,115,208,240, 86,222, 53,125,206,210, 5,175,177, + 0,168,171,133,133, 84, 93,194,175,219, 60,221,121,241,246,221, 70,198,222,188,124,132,139,123,242,197,216,172,221, 95,186,165, + 8,216,239,218,199,109, 13,116,120,221, 17,122, 4,240, 81, 84,109,198,225,184, 16, 8,230,103, 64, 61, 61, 10,252,192, 80,151, +200, 63, 49, 49,177,204,164,213,221,122,233,213,217,237,223,121, 99, 33,214,110, 72,191, 56,104,192,128, 14,233,107,210,189, 94, + 95,248, 22,190, 27, 58, 24,155, 55,111,158, 1,203,174,165, 77, 33,254,152,157, 59,119,202,108,100,159,145,145, 81, 0,203, 54, +237, 7,157, 81, 0, 14, 28, 56, 32, 11, 9, 9, 65,255,254,253, 25,138,162,248, 22,239, 44, 11,129, 64,128,160,160, 32,180,110, +221, 26, 55,110,220,192,129, 3, 7,100, 46,180,185,132,241,227,199,127,180,106,213,170, 53, 93,187,118, 93, 79, 8, 97, 1,124, + 6,224, 49, 0, 71, 8, 33, 75, 97,217, 95,229, 45, 0, 75,157,145,183,106,238,220, 31,134, 39, 36,144,221,187,119,131,207,231, + 67, 38,147,225,220,185,115,232,212,169, 19,150, 45, 91,134, 94,189,122, 97,246,236,217,252,247,222,123,111,149, 35, 97, 59,118, +236,224, 0,192,203,203,235,118, 64, 64, 0,196, 98, 49,132, 66, 97, 53, 0,198,129,199,238,190,145,255,172, 69, 31,214, 92,251, + 60,229,157,122,149,128,250,102, 1, 80,124, 30,197,103, 88, 78,163, 55, 49,183, 8, 33, 34, 31, 17,175,143,159, 16,209,146,158, +163, 58, 34,246,101,160,219, 8,180,241,230, 38,205, 24, 22,245, 78,144,159, 87,220,234, 24,248, 55,156, 28, 22, 60,158,173,207, +246, 3,208, 14,254,225,227,161, 55, 27,176, 62, 99, 3,190,217,188, 13, 99, 98,135, 1, 0,116, 58,128,199,111, 88,148,196,171, + 43, 0,192,108,182, 87,164,202, 0,228,130,226,137,144,244,220,139,136, 79, 76,196,207,123, 44, 68,230,229, 13,104,171,111, 55, +154, 89, 38,240,106,200,223,196,152, 97, 84,155,160, 83,234,160, 52,209,144,235,104, 40,140, 26, 40, 53,213, 80,148,107, 32, 87, + 26, 32,175,110,120, 9,245, 87,159,233,192, 17, 66,192,227, 17, 16, 74, 4,179,153, 3,163, 43,134, 86,121, 21,165,101, 42,200, + 21,213, 80,105,204,144, 43, 12, 40, 41, 41,195,197,203,103,161, 84,157,197,224, 1, 3, 27,220, 27,157, 7,128,210, 24,160,191, +118, 11, 85,127, 92, 66, 85,113, 17,212, 42, 57,212, 42, 57,138, 46,158,198,241,204,175,144,187,117, 19, 42,174, 93,131,153,102, + 45,173,137,247,151, 13, 3, 18,235, 65,199,199,199,119, 95,190,124,249,155,109,218,180,209,110,219,182,173, 79,102,102,230, 79, + 0,250, 91, 11,221,237, 5,167,132, 97, 97, 11, 0, 96, 72,175, 94,152, 51,103, 78,249,169,203,151,179, 31,234,214, 45,166, 57, + 18,191,117,235,214, 28, 0,100,238, 92,139,149, 57,119,238, 92,151,228,154, 68, 34, 0,192,246,237,219, 17, 26, 26,138,119,230, +206,197,130, 5, 11, 16, 18, 18,210, 34,198, 97,109,164,159,145,145, 81,115, 0,192,225,195,135,195, 1, 76,112, 82,204, 67, 1, +129,129,221,120, 20,133,231,227,227,161, 84,169, 81,114,251, 22, 4, 2, 62,248,124,203, 33, 16, 8, 32,146,120,161,163, 84,250, +113,255,209,163,157,178,216,175, 22, 22,226,219,237, 63,213, 28, 54,188,159,182, 6,239,167,173,193, 94,217, 97,151,223,119,116, +194,123, 49, 0,112,243,242,145,156,209, 22,242,151,161,133,172,118,116,254,235, 79, 80,254,242, 0,140,202,170, 64,143, 0, 62, +120,126, 65, 96, 20,229,136,222, 87, 14,111,190,133, 31,120, 14,230,100,221,184,118,173,234,243,140,255,118,253,250,191, 95,227, +211, 47, 63, 43,250,108,213, 71,239,191,249,218,188, 9,203, 63, 88, 14,137,175, 55, 70, 12, 25,134, 83, 39, 79,125,253,108,210, +179,110,191,179,141,252,109,231,187,119,239,198, 67, 15, 61,212, 17,192,116,103,221,254, 38,147, 9, 3, 6, 12, 96,205,102, 51, + 95,165, 82,193,104, 52,194,104, 52,226,242,229,203,144,201,100, 56,118,236, 24,218,180,105, 3,147,201,132,153, 51,103, 58,147, +214,169,137,137,137,159, 76,158, 60,217,111,253,250,245,126,132, 16, 33,128,195, 0, 84, 0, 6, 0,248,201, 78,241, 60, 8,160, +151, 35,121, 59,223,124,243,135, 9,125,251,146,239,226,227, 81,250,251,239,248,232,163,143,216,159,127,254,249,255,221,188,121, + 51, 84, 38,147,189,188,104,209, 34,152, 76, 38, 12, 27, 54, 12,222,222,222, 67,157,205,191,128,128,128,202,214,173, 91,195,199, +199,135,243,246,246,190,105,205,195, 7, 94, 7,237,149,129, 70, 61, 0,243,115, 80,177, 26, 21,233,191, 93,171,200,138,142, 10, +142, 29, 40, 13,178,172, 35, 62,126, 25,126,243, 25,131,131,127,148, 99,104,207, 64, 60, 34,253, 25,190,191,124,208,127,108, 63, +233,244,205, 71, 46,254, 81,159,240, 54,157, 19, 8,199,149,112, 19,159,155,143, 5,175,125, 6, 64, 14,203,178,201, 70, 68,118, + 29, 0,177,136, 15,189,214, 8,208, 22, 5,193,215,215, 23,229,242, 6,247,203,134, 94,119,133, 0,224, 46,254,246, 37, 40,106, +109, 45, 35,129,213,255, 9,131,209, 4,137,143, 24, 16, 90, 20, 4,141, 90,141,161, 67,135,226,200, 79,223, 53,108,142,176, 52, + 88,150, 15,134, 97, 96, 52, 26, 81,205,231,129, 79, 83,192,109, 53, 24, 47, 6,102, 33, 11, 78,192,131,142,199, 7,163,213, 65, +105,108, 56,214,201,215, 71, 11,134, 33, 48,210,102, 40, 85,106,228, 95, 43, 70,201,237, 74,232,105, 19,212,213,114, 84,107,148, + 48,152,105, 16, 62,129, 86,167,130, 90,119, 3, 69,165, 42, 84,105, 26,222, 75,194,108,167,165, 49, 42, 45, 74,206, 94,194,157, + 75, 55,160,214, 92,131, 70,169, 4, 7, 62, 4, 60, 2,142, 8, 64, 81, 22,175,175, 43,234,230,219, 73,111, 59, 53, 28,224, 0, +119, 0,220, 89,188,120,177, 30, 0, 22, 45, 90,116, 42, 37, 37,197,219,154,116, 3,128, 98,119, 5,175, 91,183,110, 69,124,124, + 60, 0, 32, 42, 36, 36,212, 58, 38,206,107,206,198, 97,115,255, 91, 61, 1, 14,179, 47, 60, 60,124, 52, 77,211, 72, 75, 75,195, +211, 79, 63,141,201, 99,198,220,237,232,207,159,183,120,130, 66, 66, 56,103,227, 2, 22,188,255,126,205,152, 63, 0,188,181,100, + 73, 45,207,128,147,110,255, 90,176, 89,255, 54,210,183, 33, 35, 35, 3,201,201,201,200,206,190,254, 45,128,239, 28,118,104,124, +254,127, 12,180, 17, 60, 30, 15,151,175, 23,128,227, 56, 92,204,191, 10,154, 54,129, 2, 1,159,207, 7, 33, 4,172,217, 12,189, + 86,135,171,191,253,118,200,137, 60,164,236, 73,255,217,167, 39,216, 91,252, 20, 0,156, 56,115, 30,157,163, 34, 93,154,166,156, +157,249,159, 26,107, 63,219, 98,249,219,134, 66,184,199, 39,189, 24,187,111,167,123,222,128,102,129,252, 54,132, 17, 93, 80, 62, + 71, 12,209, 35, 83, 97,206,219, 15,179,218, 18,111, 80, 62,231, 97, 68,102,228,194,204, 54, 94, 85,186,118,238,218,214,203,203, +219,235,211, 47,214, 25, 98, 71,141, 18, 14, 30, 58,228,187, 3,123,127,121,252,242,181,124,128,229, 32, 22,137, 48,108,224, 48, +236,217,189, 7, 99,199,142,229,246,239,223,239,116, 87, 80,215,234, 63,112,224, 0,174, 95,191, 78, 3, 16,158, 60,121,146,158, + 61,123,246,180,140,140,140,103, 29,201, 41, 44, 44, 68,199,142, 29, 1,128, 42, 44, 44,196,185,115,231, 16, 25, 25,137,168,168, + 40, 40, 20, 10,228,229,229,161, 67,135, 14, 8, 13, 13, 69,100,100, 36, 10, 11, 11, 27,175, 40, 20,149,148,152,152,248,193,200, +145, 35,125, 78,157, 58,229,199, 48,204, 75, 18,137,100,162, 94,175, 95, 5,203,214,231,176, 42, 0,107, 96,217,157,143, 70, 35, +211,219, 5, 2, 65, 82,230,188,121, 27, 31, 14, 9, 33, 21, 11, 23, 98, 40,203, 98,205,238,221, 92,169, 78,247, 34,238,110,203, +190,241,226,197,139,235, 25,134,225,251,248,248, 32, 60, 60,220,199,100, 50, 65, 32, 16, 56,122,125,175,210,210,210,174, 55,111, +222,132, 86,171, 37, 10,133,162, 59,159,207,143, 99, 24,166,197,238, 56, 86,223, 16, 64, 24,128,142,147,162, 35, 94,109, 31,236, + 61, 29, 38, 61,208, 53, 14,103, 66, 38,225,145,185, 95, 65, 95,169, 4,207,207, 23,178,213, 73, 24,209,227, 55, 4,157,207, 26, + 9, 32,162,161, 31,232,228,215, 14,127,156,223, 97,231,112,208, 2, 48, 89, 14,147, 17,124,150, 7,202, 74,226, 59,127,116,188, +139,200,254, 11, 28,198,246,239, 85,199, 8,229, 3, 16, 0, 2, 49, 24, 98,134,213, 14,198,148,233,243, 0, 64,150,242,238,220, + 6, 27,130,153,229,192,176, 20, 40,134, 1, 69, 27,161,163, 44,117, 71,207,227,193,155,209, 67,173,231, 64, 4, 4,102,179, 25, + 58, 51, 80,174,109,120,183, 83,134,102, 97, 16,240,192,234, 24, 48,172, 10,154,106, 19,120, 68, 0, 35, 99, 2,205,209, 96, 76, + 52, 32,100, 65, 17,128,136, 88,168,244,102,148, 85,232,160, 53, 50,245, 26,201, 20, 49,215, 12, 26, 17,114,119, 72,215,100,208, + 67, 37,151,131, 34, 60,240,249, 28,192,241,193, 35,238,155, 58, 87,138,174,208, 93, 35,187, 10,157,113,251, 55,164,155,193,110, + 15,237,148,148,148, 9, 0,110, 46, 90,180,168,191,191,191,127,128, 74,165, 42, 74, 73,113,125,135,204,185,115,231,190,176,110, +221, 58,180,110,221,218,254,154,114,205,154, 53,217, 15,117,235, 54,250,212,229,203, 7,155,171, 33,204,157, 59, 55,214,110, 40, +160, 49,242,143, 25, 52,104, 80,248,240,126,253, 64,124,125,145,146,146,130,133, 11, 23, 66, 32, 16,192,164, 80,192,223,223, 31, +239,204,157, 91, 19, 23,144,156,152,232, 80, 9,168, 59,198,239, 40, 38,160,177, 17,133,186,214,191, 3,239,128,195, 42,163,144, +203,187,249,248,250,162, 82,161,128,236,196, 9,240, 41, 30,140, 38, 19,116,122, 61, 88,150,173, 81, 92, 24, 19, 13,218,104,116, +102, 72,131, 5, 64, 89,135, 1, 88,187,138,111,176, 94,199,251,105,107,132, 0,208, 89, 42, 45,191, 81,191,109,225,146,151,170, + 93,199,232,152,125, 59,191,116,197,221,220,112, 6,187,224,246,175,229,150,221,250, 95,244,123,238, 13,136,162,250, 88,250,138, +202,219,200,151, 91, 20,127,209,208,241, 40, 54, 51,240, 90,219,248, 80,179, 90,173, 14, 16, 73,196,232, 20, 21, 37,190, 81,114, +179, 77, 85, 69, 21,166, 60, 59, 93,182,247, 96, 22, 86,127,152,182,109,231,222,221,241,157,163, 58, 35,233,233, 25,200, 61,115, + 12, 99,199,140,225,246, 31, 56,224,240,157,237,173,254, 3, 7, 14, 32, 46, 46,206,166, 44, 10,111,221,186,133,217,179,103, 11, + 1,192,153,216,130,170,170, 42,140, 24, 49, 2,102,179, 25,133,133,133, 56,118,236, 24,122,244,232, 1,127,127,127,180,111,223, + 30,253,250,245, 3, 69, 81,160, 40, 10,109,218,180,113, 84, 79,123,244,234,213,235,147,161, 67,135,242,206,159, 63,239,103, 54, +155,203,182,111,223,174,214,235,245, 41, 0,236, 7, 77, 95,125,252,241,199,139,247,238,221, 27, 69, 8,185,141,134,119,180,237, +159, 60,124,248,198,193,124, 62,169,248,224, 3,112, 38, 19,100, 60, 30,155,171,211,205,132,101, 27,119, 27, 94, 89,188,120, 49, +159,162, 40,200,229,114, 92,191,126,189,188, 87,175, 94,161,206,148,115,120,120,120,144,153,227,160,215,233,112,241,226, 69, 48, + 12,211,162,103,158,240,235,144,127,231, 48,127,201,240,199,251,134,207,246,147, 8, 6, 49,102, 86,193,231,204,126, 8,104,195, +187,173, 52, 64, 95,169, 2,132,124,152,149, 26,148, 40,104, 32, 56, 2, 20, 75,139, 27,115,241, 94, 83,171,209, 37,192, 15,140, + 17,184,150,243, 45, 58,197, 60, 86, 99,192,153,104, 19, 4,160, 80,109,176,236, 80, 59, 54,102, 0, 36,193,225, 88,181,241,167, + 6, 19, 60,182, 55,193,222,115, 28, 4, 98, 64, 24,241, 24,232,226,163, 53, 94, 0,129, 80, 4, 19, 12,240,145, 88,118, 36,221, +189,119, 11,254, 56,153,211,168, 75,146,101, 89, 8,105, 61, 76, 16,130,162, 24,192, 96,233,216, 76, 38, 19,140, 6, 1,120,124, + 1, 96, 0, 56,214, 50, 68, 16, 41,141, 2,114,235,159, 81,160, 51,176,224,241, 8, 76,140, 9, 6, 35, 11,181,198, 82, 15, 77, + 44, 7,218,200, 2,124,128, 39,224,129, 47, 6,136,222, 12,150, 48, 96,161,135, 70, 15, 88,118,150,108, 28,102, 0, 20, 11,112, + 4,160, 40, 22,132,240,192,114, 4, 20,101, 53,156, 88, 10, 44, 69,129,176,206, 25,200,118, 65,126,194, 38,214, 35,111, 0, 33, +139, 22, 45, 42, 79, 73, 73,137, 5,240,212,162, 69,139,198,164,164,164,104, 1, 84,185,229,178, 74, 72, 16,174, 91,183,238,203, +248,248,120, 72, 91,181,170,185, 46,109,213, 42,192,234, 5, 8,121, 16, 13,134,166,105,153,109,236,159,211,104,240,175,127,253, + 11,198,170, 42,216, 34,223, 58, 89,149, 21,129,209,136, 9, 19, 38,148,151,150,151, 79,115,198,210,110,198, 33,153, 90, 30,128, + 70, 60, 4, 56,125,250, 52,169, 79,121,168,165,212, 26,105, 40,105, 57, 12, 6, 3, 2,252,253, 33, 22,138, 96, 50, 51,224, 56, + 14,102,179, 25, 52, 77,195,100, 50,129,101,204,206,198, 51,176, 87, 11, 11,169,206, 82,169,205, 34, 96,175, 22, 22, 82,223,110, +255, 73,108,239, 17,232, 44,149, 42,155,203,125, 95, 82,144,215,108,150,191,187, 49, 0,163,178, 42, 80, 46,221, 6, 97, 68, 23, +144,168, 62,136,220,240, 59, 42, 13, 44,188,249, 4,244,175, 63,226,202,245, 27,112,180,107,177,158,161,113, 58,247, 36, 62, 89, +245, 49, 30,142, 25,142,197,255,111, 9,126,217,247, 11,190,219,244, 13,134,142, 28, 30,223, 94, 26, 1,190,151, 0, 7,143, 30, +196,230,175,191,193,142, 31,183, 67, 40, 22,115,187,119,239,110,116,125,136,157, 59,119,214, 34,126, 27,148, 74,215, 55,184,211, +104, 52,240,247,247, 63, 1, 96,176, 84,103, 60,227,177, 0, 0, 32, 0, 73, 68, 65, 84, 42,197,192,129, 3,193,227, 89,134, 89, + 35, 35, 35, 33, 18,137,160, 82,169, 32,149, 74,225,235,235, 91,164,209,104, 34, 27, 17,119,241,252,249,243, 43,118,236,216, 49, +174,115,231,206,221,182,111,223, 94,173, 80, 40,150, 2,216,108,175,191,140, 26, 53,234,205, 13, 27, 54,108, 5, 80, 14, 32, 1, +192,111, 0,250,214, 35,239,247,181, 50,217,138,128,188,188,119,159, 97, 24,124, 12,176, 95, 86, 87,207,168, 35,239,169,121,243, +230,125, 60,107,214, 44,220,184,113, 3,123,246,236, 1,195, 48,135, 0, 60,227,196,235, 83, 1, 60, 94,149, 15, 77, 67,251,251, +239, 92, 8,203,106,174, 1,154,191,186,143,234,215,175, 31,206,158, 61, 91, 51,238,223,104,130,235,156,119,152, 20, 29,177,220, + 79, 34, 24, 84,161, 54,252,114,252,106, 69, 10,120, 34,224,202, 81, 60, 42,229,240,127,175, 77,192,192,158, 82,204, 75,126, 28, + 79,118,164,129, 11, 7,192, 9, 36, 12, 26, 13,214, 81, 34, 95, 89, 12,190, 8, 24,251,228, 27,216,252,233,135, 22, 99, 81,103, +132, 89, 15,252, 40, 59,139,236, 83,150, 25,133,237, 34,162, 64,241, 29,147,215,184,190, 4, 38, 3,176,123,207,126, 68,143,121, +205, 98,253, 67, 0,158, 4, 72, 28,159,128,113, 35, 39, 90, 26,126, 81, 1, 24, 3,221,184, 70,207,113, 96,136,133,224,141,180, + 37,248,207,104,208, 67,167,211,161,186,186, 26, 26,181, 10, 26,141, 6,106, 77, 53, 12,213,213,208,235,245, 13, 87,254,106, 2, +189,193, 12,189,193, 12,173,206, 4, 77,181, 17, 10,141, 17, 74, 53, 13,149,198, 4,165,210,242, 41,175, 98, 32, 87, 48,144,171, + 24, 84,202,105,220,169,108, 56,141, 20,199,193, 12,128,152, 9, 8,197,130, 35, 28,192,113,224, 56, 30,204,236,221,226, 99,173, +189,135,171,190,241,238, 67,187,227,216,222, 99,248,229,208, 47, 53, 74,193,149,162, 43,174,214,185,112, 0, 29, 83, 83, 83,207, + 1, 88,251,206, 59,239,188,222,161, 67, 7, 38, 35, 35,131,164,165,165,185,172, 1,207, 74, 72, 32,194,176,176,157, 0, 16, 22, + 22,118,207,253, 57,115,230, 48,121, 87,174,108,105,174, 88, 0,155,251,223,217,125,227,109, 99,255, 0,240,195, 15, 63,224, 90, + 89, 25, 0,224,231,156,156, 90,247,174, 92,185, 18, 26, 18, 18,162,120, 16,138,202,232,209, 29,108,243,174,107, 93,183,157,219, +238, 59,244,105,250,249, 94,102,205,102,168,229, 10, 84, 86, 86,162, 74,169,128, 86,167,131, 86,167,131,166,186, 26, 90,149, 26, + 26,165, 18, 6,189, 14,180,193, 0,150,113, 24,232, 76,117,150, 74,109,125, 6, 11,128,182, 31, 14, 0,128,111,183,255,132,247, +211,214, 4, 0, 8,115,185, 34,118,140,142,169,171, 56, 68,245, 24, 21,131, 7,140,219, 83,164,136,220,240, 59, 72, 84, 31, 24, + 15,111, 67,209,243,253,225,205, 39, 56, 26, 23, 2, 70, 85,129,232,253,229,224, 59,168,126, 89, 89, 89,228,229,249,175,224,218, +149, 43,200,205, 57, 10,127, 95,127, 76,157, 50, 21, 1,193, 65, 56,115, 50, 15, 62, 66, 49,188,189,189,209, 70,218, 22, 91,190, +223,130,119,222,123, 23,213, 74,247,119,169, 29, 48, 96,128,203,223,241,245,245,133, 74,165, 26, 76, 81, 20,221,190,125,123, 12, + 26, 52, 8, 61,123,246, 68,171, 86,173, 32, 22,139, 33,149, 74,209,183,111, 95, 4, 4, 4, 64,163,209, 68,250,250,250, 58, 18, +185,242,240,225,195, 89,155, 54,109, 18, 40, 20,138,197,117,200, 58, 97,196,136, 17,159,108,216,176,225,171,176,176,176, 15, 8, + 33, 62, 0,222, 1,208,152,155,236,189,229, 26,205,202, 23, 25,198,252,165, 94, 63,173,142,188,248,103,146,255,189,227,181,215, + 23,240,174, 92,185,130, 19, 39, 78, 96,195,134, 13,213, 0,254,207,201,215,167,188,140, 70, 49,119,233, 18,218,103,103,147,240, +210, 82, 30, 30, 80, 12, 74,221,160,247,134,130,224,235,118, 2, 34, 30, 69,124,139,171,180,223,109,201,189,241,127,103,139,228, + 39,245,102,114, 13,149, 55, 32,222,241, 42, 62, 24,166, 65,222,210, 65, 88, 29, 91, 13,239, 31,231, 0,242, 18, 84,115,226, 11, + 86,205,171, 1,220,141,234, 63,119,254, 39,252,251,223,155,208,201,175, 55,254, 60,126, 14, 7,100,151, 16, 59,180, 39,226, 70, + 88, 42, 26,199,227,131,118, 97,162,196,216,254,221,176,124,229,135,216,127, 65, 13, 31,105, 15,140, 31, 63, 1,191, 28,218,137, + 61,191,108,177,188,156,217, 4,145,160,241,126,142, 99,205, 48,179, 22,107, 6, 86,107,134,166,105, 24, 12, 6,232,245,122,104, +117,122,232,117, 90,232,117, 90,232,140, 6,208, 70, 67,195,238, 47,189, 47, 84,213,102,168,245, 44,212,122,214,242,191,134, 69, +181,150, 65,181,142,129, 66,110, 70,149,220,132, 42,133, 9, 85, 85, 38, 84, 86,210,184, 83,105,106, 84, 1,184,235,254,191,215, + 84,227,243, 56,240, 8, 1, 87, 39,234,159, 35,142,235,220,219, 73,111,163,251,208,238, 53,231,217, 27,179,107, 60, 2,199,246, + 30,195,149,162, 43, 55, 92,169,112,219,182,109,251,149,227,184, 94,241,241,241, 73, 81, 81, 81, 33, 0, 40,150,101, 69, 38,147, + 41,112,254,252,249,126, 13,184,130,235,133, 48, 44,236,253,117,235,214,141,139,143,143, 71, 84, 72,136, 83, 67, 87, 77,116,255, +199, 0, 64,116,183,110, 14, 3,216, 58,183,110, 29,155,150,150,134, 63,139,138,212, 59, 14, 28,192,229,203,151,107,172,254,174, + 93,187,194,122,143,222,113,224, 0,138,138,138,112, 37, 47, 79,239, 72,230,130,247,223,199, 91, 75,150,212,184,247,109,255,219, +206,109,255,187, 18, 11,144,146,146,201,141, 26, 53,234, 85,123,210,183,125, 14, 28, 56, 16, 41, 41,153, 78,117, 76, 87, 47, 23, +228, 49, 12, 3,154, 54, 66,126,167, 28, 21,183,203, 80, 89,118, 7,149,101,119, 32, 47,175,128,178,170, 10, 70,173,214, 18, 63, +163, 84,194,137, 32, 64,230,253,180, 53,252,247,211,214,240, 1,168, 1,176,131, 7,244,185,231, 33,187,184, 0,167,209,182, 99, +116, 76,105, 65,158,172,239,160,187,105,232,216,255,201, 24,101,197,117, 89, 83,234, 7, 73, 84,212,178,252,221, 65,190, 92,139, +226,151, 30, 2,119,227, 60, 66,255,123, 6,222,235, 79,227,246, 20, 41, 6,238, 47, 7, 17,136,192, 39, 0,159,114,172,128,158, +191,112,129,252,235,195,229,152,247,214,155, 48,177,102, 92, 46,188,138,233, 83,167, 65, 40, 22, 99,215,143,187, 1,147, 25, 70, +131, 17, 71,243,142, 67,175,175,198,172,153, 51, 15,191,252,242,203,141,149, 53,153, 52,105, 82,236,152, 49, 99, 64, 8, 65, 86, + 86,214, 61, 46,253,183,223,126,219,233,247, 12, 14, 14,198,173, 91,183, 0,128,159,158,158,142,138,138, 10,244,238,221, 27, 1, + 1, 1,160, 40, 10, 39, 79,158, 4, 69, 81, 32,132,224,214,173, 91, 8, 14, 14,118, 70,236, 7, 52, 77,143, 4,240,131,221,181, +169, 35, 70,140, 72,123,233,165,151, 2,211,211,211,197,132, 16, 10,192, 78, 88,102, 1,220,113, 32,111,225, 9,147, 41,186,174, +188,103, 22,237,216,250,244,180, 57,100,220, 43,233,200, 57,113, 17,105,105,105,172, 90,173,126, 1,150,217, 5, 78,121,183, 58, +249,250, 6,180, 47, 43,195,112,157, 14,109, 4, 2,111,111, 30,239,129, 45,183,223,175, 95,191,154,195,169, 33, 0, 0, 5, 91, +142,223,152, 43,215, 26, 79, 3,200, 7,208, 38,247,106,197,231, 35,187,133,189,199,191,113, 34, 8, 27,102, 0, 34,111,192,168, + 5, 56, 14, 38,158,248,206,209, 63,111,127,137, 70, 86, 95,218,252,221,103,177,211,166, 39,201, 0, 64,203,154,112, 77, 89, 12, +192,140, 78,126, 81,136,141,237,131,176, 86,255,159,189, 43, 13,107,234,218,218,239, 62, 25, 8,160, 34, 56,139, 86,197,138, 90, +181, 14, 88, 17,181,146, 40, 90,171,181,195, 87,163,182, 94, 91, 63,109, 9,106,175, 83, 7,180,181,215,222, 94, 91,245,222,139, +218, 81, 98,135, 79,219, 91,111, 53, 88, 91,167, 58,160, 9, 42, 34,136, 86,235, 12,130,138,160,136,146, 48, 37, 64,166,253,253, + 72, 78, 12, 33,144,147,128,162,237,121,159, 39, 15, 57, 67, 22,251,236,189,207, 94,239, 90,123,237,181,219,163,184,180,204,230, + 43, 48,154,113,179, 68, 95,239, 67,117,122, 36, 10,249,121,246,101,158, 68,136,113,253,109, 49, 0,123,206,152,176,119,103, 18, +110,221,185,129, 86, 45,109, 43, 9, 90,138, 69,120,124,240, 0,168,127,174,199,165, 11, 33,196, 86, 51, 44, 16,192, 74, 8, 24, +139, 21, 48,153, 97, 17, 9, 1,194,128,125, 39,173, 20,182, 92, 1,245,224, 87,245, 21,242,244,136,230, 52, 64, 76, 33, 20, 57, +121, 24, 76,128,153, 2, 85, 70,192, 82,109, 1, 33, 4, 68, 76, 96,182, 0,250,106, 32, 35,173,148, 12, 24,208,153,186,117,249, +179, 61,139,177,130,216,221,255, 54, 82, 64, 96,177, 50, 96, 4,246,149, 2, 0,168,128, 2,148,155, 23,192, 89,249,187, 59, 78, +221,157,218,141,107, 71,155, 52,105, 82,159,164,164,164, 53, 0, 6, 36, 37, 37,237, 73, 74, 74, 58, 60,105,210,164, 55,186,119, +239,110, 34,132,180,250,228,147, 79,246, 45, 94,188,120,218,202,149, 43, 83,234, 33,159,172,245, 47,124,235,173,183,150,189,245, +214, 91,216,179,103, 15,244,183,106,191,203,221,218,180,193,149, 43, 87, 0, 64,205, 37,145, 79, 93, 73,127,222,120,227, 13,233, + 23, 95,124,161,254,252,243,207, 49,184,103, 79,217,241, 11, 23, 60,186,138,143,158, 57,163, 25,222,191,255, 83, 23,143, 31,239, + 10,192, 15,192,167, 38, 63, 63,136,170,171,209,163, 67, 7, 44, 90,180, 8,169,169,169,171,194,195,195, 83, 82, 83, 83, 15,228, +231,231,123, 32,119,181,243, 0, 52, 32, 6,160, 6, 15, 76, 73, 73, 33,241,241,242,227,199,142, 21,165, 42, 20, 10, 49, 0,196, +199,203,135,173, 90,165, 74, 3,199, 36, 64, 93,251, 63,246,110,229,205,194,177, 86,179,165,151,190,180, 20,165,119,110,131, 16, + 6,148, 90, 81, 85, 85, 5, 74, 41, 40,165,184,114,254, 2, 76,198,106,252,150,156,236,169, 14,157,199,156,150, 0,152,241,178, +104,235,120, 89, 52,156,151, 5,218,167, 8, 56,163, 83,143, 33,210,252,236, 12, 53, 0,116,237,210, 5,167, 51,108, 60, 57,231, +183,237, 0,128, 54,143, 12,146,221,206, 59,217,100, 30,128,193,191, 22, 33,243,105, 96, 64, 68, 12,138,230, 14, 67,251, 47,143, + 34, 75,171, 71,176,152,160, 88,171,131,144, 16,143, 30, 0,199,187,153,154, 90,227,206,238,221,187,211,241, 19,158,198,206,237, + 59,177,101,203, 22,124,240,222,251,216,167, 57, 0,129, 80,128,208, 78,161,209,165,165,245, 47, 93,222,182,109,155,198, 78, 4, +164, 99,199,142,173, 17, 11,176,127,255,126, 92,190,124,185, 74,169, 84,118,112,245, 38,185,237, 47, 93,187, 34, 55, 55, 23,143, + 61,246,152,121,193,130, 5,226, 31,127,252, 17, 65, 65, 65,184,120,241, 98, 45,207,107,110,110, 46,186,114,111,103,231,196,115, +211,159,120,226,137, 15, 95,122,233,165,160,204,204,204,230, 85, 85, 85,255,235,239,239,255,140, 61, 48,240, 23,142,242,156, 23, +202, 79,127,230,175, 63,110, 28, 49,250, 5,242,207,100,128,116,124, 22, 31,175,125,151,106,179, 47,206, 4,160,242,162,153, 73, +185,201, 84, 34,246,243, 67, 11,177, 24,254, 22, 75,181,190,230,146,181, 7, 14, 53, 8,192,124, 13,206,125, 34,173,206,154,175, +113, 76,105,230,125, 34, 45,249,181,188,202,172,143,124,180,245,248,144, 0,193, 19,130,234,170, 64, 51,101,202,139,203,141,199, +210, 46, 23,238, 45,208, 26, 82,230,107,112,179, 46,146, 49,237, 47, 75, 53,135,142,166,201, 0,168,173, 2,118,154, 79,128,203, +101, 55,241,183, 55,102,194, 96,168, 70, 89,165, 45, 6,192,200,248, 97,243,182,250,211,236,230,231,165,145, 23,158,253,171, 77, + 89, 90, 88,203,217,140,113,253, 8,166,206, 89,141,128, 0, 63,180,240,151,200, 0,168,179,207,158,148,109,248,108, 91,189, 3, +146,144,154, 97, 36, 54, 18, 0, 66, 96,161,212, 70, 4,204,246,229,126,132,129,208,106,133,217, 30, 28,232,137, 4,148, 84,182, + 68,101,117, 49,196, 66,198,145,230,204,108, 5, 76, 38, 10,147,153,162,162,210, 10, 34, 32,176,128,192,100,189,235,186,119, 7, +139,149, 1, 67, 44, 32, 22, 2,202, 80,135,251,159,212, 97, 60,179,146,206, 93,252,145,120,202, 13,125, 33,237, 66, 67,251,142, +195,109,209,175, 95,191,155, 97, 97, 97, 47, 92,189,122,181,199,150, 45, 91, 50, 0, 60,151,148,148,244,156,243,205, 43, 87,174, +212, 44, 94,188, 88,182,114,229, 74, 79, 10,194, 81, 33,113,113,113,117,222,244,226,171,175,218,124,128,222, 37, 6,162, 46,110, +127, 0,192,144,222,189,101, 25, 28,148,191, 99, 0, 62,125,218, 17,173, 58,172, 95, 63,107, 66, 66,194,231, 19, 39, 78, 52, 95, +186,116, 73,120,237,218, 53,116,109,213, 42,109,231,206,157,156, 2, 20,239, 81, 30, 0,103,229,126, 43, 37, 37,197, 57,198,227, +140, 83, 61,123, 36, 1,170,149,171,244,242,197,241, 47, 94, 60,112, 48,173,101, 96, 96,139, 50, 93, 9,204,102, 51,168,253, 61, +208,221, 42, 66,153, 78, 7, 74, 41, 6,198,196,200,126, 75,246,152, 7,201,140,187, 49, 39,140,125, 57, 32, 19, 57,232,113,140, +151, 69, 59, 86, 1,100, 95,189,202,153, 4,196, 76,120, 73,154,188,235,191, 14, 43,255, 23,213, 55,106, 0,104, 19, 54, 92,118, + 59, 55, 85, 3, 0, 77,163,252,105,109, 18,128,175, 48, 32,238,111, 40,180, 90,209,127, 67, 6, 50,198,181, 67,159,157,183, 32, + 36, 64,115,145,111,198,226,206,157, 59,201,148,151,166,208, 81, 99, 70, 99,251,214,159,241,143, 85, 43, 17, 95, 90, 10,106,181, + 98,243,230,173, 40, 40, 40,120, 6,192, 78, 79,114,220, 17, 1, 0,120,225,133, 23, 78,129,227, 92,246,134, 13, 27,200,216,177, + 99,233,201,147, 39,197,131, 6, 13,194,232,209,163,161, 86,171,241,200, 35,143,160,186,186, 26,209,209,209,160,148, 90, 79,158, + 60,201,136, 68, 34, 95, 50, 2, 62, 22, 20, 20,180,102,202,148, 41,162,243,231,207,183,168,174,174,174, 43, 48,144, 43, 6,134, + 14,152,188,113,192,200, 41,228,155, 20,160,172, 18, 48, 94,217, 99,213,102,171,103,160,102, 96, 32, 39,125,170, 45, 45, 53,139, + 77, 38, 24,196, 98, 8,205,102, 15,211,227,247, 6,108, 30, 0,103,203,223,221, 57,183,174, 84, 39,229,207, 30, 95,248, 68, 90, +145,119,237, 78, 69, 26,128, 14,246,151,183, 26, 64, 1,128,220,249, 26,120,116,113, 42,191,220,165, 25, 49,162,159,204, 66,155, +169,157, 95,142, 10,125,153,109,221, 63, 19,128,156,114,144,181, 95,110,226,244,128,219,182,127, 70,110,107,115,165, 96, 12,106, +231,234,109,214, 44, 8, 22,147, 14,160,122,140,235,199,109, 66,215, 4, 1, 64,169, 77, 81, 67, 0, 49,181, 19, 1,187,242,183, +229, 0, 4,192,145,200,165,157,184, 78, 34,250,118,160,102,147, 22, 66,187,247,135, 82, 10,139,153,162,202, 4,148,149,155, 97, + 2,133,153, 50, 16,138, 8,238,220, 50,213, 89,206,227,199, 87, 17, 0, 24, 22,245, 54, 37, 38,155,245, 79, 1, 80, 74, 0,106, +183, 24,168, 0, 68, 96,133,213, 42, 68, 86,246, 86, 78,207,252,218, 63, 94,147, 93,205,185, 90,159, 2, 22,193,182, 84,163, 62, +237,228,168,249,101,203,150,177,254,209,211,118,171,248,174,162,126,241, 69,233,214,173, 91,213,118, 18,160,246, 68, 2,214,171, + 84,166,223,206,156,145,119,237,215,207,242, 68,175, 94,122,123, 31,173,134, 75, 22, 45,249,184,113, 54,139,163, 95, 63,207,211, + 29,111,191, 45, 3,128,193, 61,123,214,186,150,121,233,146, 38,227,130,239,100,168, 95,239,222, 95, 50, 12, 99,185,120,252,120, + 96,187,118,237,238,164,230,231,111,244,100,245,223, 7,173,227,220, 15,244,246,128, 63,118,106,160,194,165,173,185,144,128,243, +242,197,241,145,219,191,254,102,107, 88,183,174,143, 85, 87, 87,193, 98, 50,195,106,181,162,121,112, 48, 74,181, 90, 86,249,115, + 33, 81, 37,127,127,243,175,109, 1, 24,179,175, 94, 21,179,243,255,233, 39,127,199,120, 89,180,117, 89,194,103,158,146, 3, 57, + 48,103, 94, 60,189,120,233,162,204, 89,249, 3,192,168,167,158,147, 29,220,251,139,230,118,110,170,239,149, 88, 71,128,159,251, +243,220,117,216,224, 95,139,128, 95,223,112, 28, 63,250, 75,161,227,123,169,201,119, 99,113,243,127, 55,147,225,195,135, 63, 61, +118,194,184,221,175, 79,159,117,228,241,254,253, 70,108,255,101, 7,210, 78,157,192,137, 19, 39,118,213,231, 6,174,135, 8,204, +218,182,109,219,215,219,182,109, 27,186,109,219, 54,206,133, 27, 59,118,236,168,125,251,246, 29,220,185,115, 39,194,194,194, 48, +102,204, 24, 4, 5, 5,101,149,150,150,134,159, 59,119, 14,185,185,185,140, 72, 36,194,216,177, 99, 99,246,237,219,231,237,163, +158, 47, 45, 45, 93,181, 99,199,142,250, 2, 3,189,193,111, 5,167,182,172,248, 57,233,217,119, 43, 67,167,161,242,248, 82,235, +141,195, 31, 77,247, 81, 94,213,181,162, 34,209,155, 89, 89,249, 22,131,129, 57,205, 48,162,246, 2, 65, 97, 97, 19, 57, 1,220, +101, 3,244, 52, 5,224, 22,243, 53,208, 3,248,221,254,241, 9, 71,142,156,209,196,197, 45,150, 37, 42,255,161, 14,237,210, 3, + 64, 53, 68,126, 18,228,223, 44,195,166,157,169,196,123,121,187, 52, 51, 94, 91,136, 13,223,254, 4, 88,175, 1, 16,194, 92, 85, +137,208, 14, 65,178,143,222,158,197,217,154,131,197, 10, 33, 99,133,137, 8, 33,162,230,187, 68, 0,102,128, 90,192, 53, 48,204, + 25, 39,206,222, 36, 0,208, 62,132,161, 34,161,205,218, 55, 91,109, 9,140, 74,202, 41, 44,102, 64, 32,180,194, 98,230, 54,114, + 28, 77,251, 23, 1,128,200, 33,139, 40,216,156,240, 12, 96, 37, 54,119,255,165,236, 29, 94, 21,242,235,247,191,214, 52, 66,255, +226,100,174,176,202,223,201, 19,224,113, 57,214,241,139, 23,147,142,187,184, 12,235,185,215,227, 61,141,153, 58,184, 22,185,181, + 45,241, 75,180,217,214,103,124,146,209,200,121, 0, 92,235, 86,239, 97,169, 21,167,190,163, 90,185,234,162,124,113,124, 95, 0, +130,139, 41, 41,166, 42, 67, 37,172, 22, 11,122, 71, 68,200, 58,132, 63,134,227,191,238,224, 86,199,148, 76,217,251,235, 46,199, +225,176,199,194, 28,223,247,254,186,171,214,113,125,161,241, 95,126,106, 35,200,163,159,122, 94,118,254, 98, 14,110, 94, 59,163, + 6,128,131,123,127, 81,183,123,164,175,236, 86,222, 89,175,219,125,242,228,201,240, 54,189,175,133,248,213,123, 61,239,133,246, +248,245, 70,213, 61, 31,240, 83, 83, 83,127, 85, 42,149, 76,102,102,166,245,192,177, 20,180,106,221,202,117,165,135, 87,216,182, +109,219, 55, 74,165,242, 59,133, 66, 97,242,230,119,111,189,245,150, 26, 0,153, 49, 99, 6,205,201,201, 65, 70, 70, 6,202,203, +203,195,155, 55,111,142, 86,173, 90, 57,246, 2,240, 65,249,179,248, 87, 74, 74,138, 40, 45, 45,173,159,209,104, 92,138,154,115, +249,190,224,189,179,155,255, 34, 10,234,254,221,162,210,156,125,211, 26, 32,207,252, 99,122,250, 51, 0,198, 0,248, 13, 86,107, + 57, 60,199, 35, 52, 58,216, 85, 0,238,206,251, 68, 0, 60, 14,130, 74,165,112,221,186,117,158, 93, 85,123,143,106, 58,117, 29, + 77,110,229,167,209,182,161,157,161, 45, 55, 99,211,246, 35, 62,119,208, 13, 95,175,177,255,182, 29, 5,110, 33,184,185, 16, 31, + 45,121,221,171,151,254,171, 99,217,247,108,157,102,161,214, 74, 0, 64,226, 47,162,198, 74, 19,172, 0, 2, 2, 2, 96, 48, 27, +136,197,236,189,188,244, 12,219,158, 1,145, 79, 44,164, 86, 42,192,213, 43,187,155,114,141, 41,215,165,131,252, 46,129, 28,234, +199, 89,225, 55,242,180,128, 49, 62, 94,238, 7,192,178,106,149,170, 65,166,136,106,229, 42,118, 35, 31, 71,155,230,156,245,110, +157,254,188, 21,159,249, 68,198, 92,183, 2,118,198,129,189, 63,107, 92,251,218,173, 60,223,242, 7,120,218,216,199,149, 3,155, +137, 31, 42,153,250, 87,164,230,148,155, 17,222, 92,120, 95, 94, 21,251, 90,253, 70,123,231,188, 85,254, 53,198,103,223, 55,252, +225,130,143,141, 70,227,207,128,231, 77,233, 56,226,157,210,156,125,155, 80, 51, 54,192, 91,152, 0,148,192,187,184,129,123, 70, + 2, 56, 13, 62,190,238, 35,204,131,135, 51,122,244,232,129,236,236,108,190, 34,120,240,224,193,227, 33, 1,195, 87, 1,143,198, + 0,175,252,121,240,224,193,131, 39, 0, 60,120,240,224,193,131, 7, 15,158, 0,240,224,193,131, 7, 15, 30, 60,120, 2,192,131, + 7, 15, 30, 60,120,240,104,114,212, 8, 77, 61,117,234,148,207, 81,155,238,130, 9,121,121,188, 60, 94,222, 3, 35,175,222,232, +112,190,254,120,121,188,188, 63,150, 60,175, 9,128,211, 64,225, 45, 60, 13, 60,141, 41,143,199,131, 9,202,183,219, 67,217, 14, +156,239, 87, 42,149,129, 0,158, 56,114,228,200, 71, 2,129, 96,152,159,159, 31, 12, 6,195,209, 17, 35, 70,188, 7, 32, 67,161, + 80, 24, 30,132, 10,176,103,135, 84,255,153,199, 21, 74, 41, 61,123,246, 44,250,245,235,199,191,147, 60,188, 34, 0, 94,173, 67, +230,146, 40,199,157, 60,231,196, 39,222,202,251, 19, 14,232,156,240,212, 83, 79,201,246,238,221,171,225, 42, 51, 52, 52,180,214, +133,130,130, 2,215,193, 20, 42,149,138,112, 44,227, 61, 35, 1,117,229,243,111, 42,121,171, 87,175, 30,189,117,235,214,228,172, +172, 44, 0, 64, 88, 88,216,179,233,233,233, 59,124,109, 95,231,126, 79, 41,117,188, 31,236,121,246, 93,177,159, 39, 30,200, 51, +215,118,240, 70,249, 63,118,246,236,217,173,101,101,101,189,186,116,233,130, 59,119,238,160,170,170, 10, 0,134,109,221,186, 85, + 29, 24, 24,120, 81,169, 84, 62,175, 80, 40,234,221, 74,242,236,217,179, 94, 25, 4,169,169,169, 50,133, 66,161,241,230, 55, 42, +149, 74, 45,151,203,101,190, 36,128,162, 94, 38, 97,152, 60,121,178, 55,239, 7, 0,160, 75, 23,219, 14,184,229,229,229,168,174, +182,165, 65,215,235,245,222,188,111,245,226,204,153, 51,116,216,176, 97,232,221,187, 55,252,252,252,138,170,171,171, 31,225,135, +209, 63, 31, 92,147, 1,221,179, 68, 64,188, 21,123,111,241, 75,226, 56,143,247, 60, 63,123,143, 87, 50,213,234,187, 6, 82, 86, + 86, 22, 2, 3, 3, 29,131, 16, 11, 46,155,127,200,229,114,170, 82,169, 92,143, 73, 29,247,248, 84,183,209,209,119,183,115,117, + 39,191, 33, 32,132,208,145, 35, 71,202, 82, 82, 82,188, 82, 22, 91,183,110, 77,110,219,182, 45, 94,121,229, 21,232,116, 58,107, + 66, 66,194,246,149, 43, 87, 78, 93,188,120,241,102, 47,255, 63,126,253,245, 87,199,241,184,113,227,176,103,207,158,122,143,185, +136,117,233,203, 52, 34, 34, 2, 0,168, 83,102, 56,175,148,127,105,105,105, 90,247,238,221, 91, 0,128, 68, 34,129,191,191, 63, +138,138,138, 80, 82, 82,130,160,160, 32, 20, 21, 21,245,218,179,103, 79,134, 82,169,236,169, 80, 40, 10,235,147,215,183,111, 95, +200,229,114,132,133,221,205,250,183,106,213,170, 26,247,196,199,199, 3, 0,142, 29, 59,166,246,165,223, 52, 36,251,227,218,181, +107,235,186,228,216,171,192, 87, 4, 6, 6,226,252,249,243, 16,137, 68, 48, 26,141,216,179,103, 15,178,179,179,177,100,201,146, + 6,245,227,224,224, 96, 1,128,152, 67,135, 14,237,137,142,142,190,245,252,243,207,183, 75, 78, 78,134, 64, 32,104,211,178,101, + 75, 1,120,252,169,149, 63,123,206,149, 4,252, 97,130, 0, 35, 35, 35,165,247,219,226,110, 74,132, 14, 94,238,248,248, 10,157, + 78,231,176,248,245,122, 61,214,175, 95,239,248,120, 49,208,186, 61,158, 52,105, 18,149,203,229, 20, 0,117,189,199, 91, 28, 58, +116, 72,253,246,219,111,163, 91,183,110,141, 86,127, 93,187,118, 37,239,188,243, 14, 40,165, 72, 73, 73, 81,123,219,238, 89, 89, + 89, 24, 55,110,156, 21, 0,196, 98, 49, 19, 30, 30,142,132,132,132, 31,219,180,105, 67, 35, 35, 35,199,123, 97,113,222,171, 46, + 66, 34, 34, 34, 40,251, 92, 39, 78,156, 96,247, 3, 96,219,133,179,219, 95,167,211,109, 21,139,197, 45, 0, 96,238,220,185,152, + 54,109, 26,196, 98, 49,252,253,253, 33,145, 72, 64, 8,129, 64, 32, 64,105,105,105, 11, 0, 9, 74,165,178, 94,217,241,241,241, + 8, 11, 11, 67,110,110,174,227, 19, 31, 31, 95,227,211, 16,200,229,114,153,253, 57,125, 30, 19, 22, 46, 92,232,248, 56,143,151, + 46,231, 57,111,244,210,165, 75, 23, 4, 6, 6, 98,233,210,165, 8, 12, 12,196,246,237,219, 81, 89, 89,217, 40,202,223,254, 46, + 83,157, 78,247,191,211,167, 79, 71,143, 30, 61,218,237,217,179, 7,183,110,221,194,245,235,215, 81, 82, 82, 98,188,159, 99,147, + 82,169,148,230,231,231, 83,165, 82, 41,117,119, 45, 59, 59,155, 94,190,124,249, 79,145,128,142, 82,218,171, 41,149,127,108,252, + 74,196,198,175,172,147, 24,220, 23, 2, 64,220,160,190,243,190, 32, 61, 61, 93,221, 24, 36, 96,218,180,105, 15, 13, 9,104, 40, + 12, 6, 67, 45,171,223,151,230,101,149,201,164, 73,147, 28, 86,126, 82, 82, 18, 26,170,248,157,173,127,149, 74, 69, 70,142, 28, + 41, 83,169, 84, 53, 60, 2, 13,193,150, 45, 91, 8, 0, 18, 29, 29, 45,115,245, 52,112, 28,116,205,118,111, 0,218,182,109,139, +229,203,151, 87,189,249,230,155,198,220,220,220, 93, 43, 87,174, 28,211,212,237,235,180, 7, 0,113,110, 39, 47,219,229,137,236, +236,236, 94, 0, 48,107,214, 44,148,150,150,226,198,141, 27, 16,137, 68, 16, 10,133, 16, 10,133, 16,137, 68,240,247,247, 71,101, +101, 37,146,147,147, 95, 6, 16,236, 73,104,110,110, 46, 84, 42,149,227,227,236, 9, 88,181,106, 21,146,147,147,125,126,110,149, + 74,165,177, 79, 1,168, 27,233, 93,174, 43,113, 55,231,241,243,234,213,171,216,181,107, 23,150, 47, 95,142, 46, 93,186,160,117, +235,214, 72, 73, 73,193,146, 37, 75, 16, 24, 24, 8, 0, 16, 8, 26,100,168,119,152, 57,115,230,148,127,253,235, 95, 72, 79, 79, +199,141, 27, 55, 96, 54,155, 95,105,213,170, 85, 48, 0,211,253,238,123,161,161,161,136,141,141, 85,231,228,228, 80,103,229, 31, + 27, 27,171,126,244,209, 71,241,128,239,146,219,187,129,191,247, 3,208,117,213,170, 85,207,164,167,167, 71, 3,232,223, 20, 15, +225,172,248,157,191, 55,133, 7,128,186,249,212,119,190,201, 72,192,248,241,227, 27,131, 4, 80, 47, 62,156,241,226, 27,123, 27, +173, 65,178,178,178,160,215,235,235,116,243, 31, 61,122,180, 49,136, 65,131,113,232,208, 33,181,157, 88, 32, 37, 37, 69, 67, 8, + 65,219,182,109,213,141,217, 57, 89,247,191,221, 19, 80, 47, 86,175, 94, 61,126,248,240,225, 20, 0, 18, 18, 18,196,223,126,251, + 45, 94,121,229, 21,214, 53, 47,249,253,247,223,197,246,107,251, 34, 35, 35,159,227,242,255,199,141, 27,135,167,159,126,218,225, +222,103,191,179,199,236,119,142,238,127, 0,128,221,250,119,215, 14,196,229,122,189,216,179,103,207, 71,173, 91,183, 6, 0, 92, +190,124, 25,121,121,121, 56,121,242, 36,140, 70, 35, 8, 33, 16, 10,133, 32,132,192, 98,177,192, 96, 48, 96,219,182,109,224, 50, +224,185, 76, 27,185, 37, 47,185,185,185, 13, 34, 1, 78,207,222, 32,111, 0, 26, 97,170,212,100, 50, 97,208,160, 65,208,104, 52, +184,122,245, 42, 6, 15, 30,236,184,166,209,104, 16, 18, 18,226, 32, 2, 62,160,227,204,153, 51,243,191,249,230, 27,196,196,216, + 54, 50,234,216,177, 35, 44, 22,203,247,176,229,166,191,175, 80, 40, 20, 26,150,124,134,133,133,225,248,241,227,148, 85,254, 44, +249,235,217,179, 39,151,241, 97, 8,128,239, 96,219,243,172, 62, 76, 0, 16, 11,160, 77, 35, 41,255,134, 18,128, 14,115,231,206, +149,189,243,206, 59,162,182,109,219,202, 1, 68, 61,168, 76,231,190,196, 0,220,207, 32, 64, 59, 9,144,165,167,167,107,124,149, +209,181,107, 87, 76,155, 54, 13, 63,252,240,131,175, 49, 1, 4, 0,253,225,135, 31,220, 94,220,189,123, 55,236,215,188,150,125, +236,202, 99, 24,218,237, 60, 10, 50,151, 54,168,158,156,231,252,147,147,147, 17, 19, 19,131,216,216, 88,135,242,239,220,185,115, + 99,144,190, 6, 17,129,232,232,104,233,161, 67,135,112,231,206, 29, 25,123, 78, 42,149,202, 84, 42,149, 58, 58, 58, 90,234,237, +188,189,135,255, 37,227, 66, 0,182,110,221,186,139,157,251,215,235,245, 88,181,106, 21, 42, 42, 42, 32, 18,137,224,231,231,135, + 43, 87,174, 96,249,242,229,208,233,116, 72, 72, 72,248,121,229,202,149,163, 22, 47, 94,172,246,160,100,107,144, 1, 79, 49, 1, + 28,234, 28, 30,118, 0,116, 76, 7,120,122,222,144,144,144, 97,213,213,213, 48,155,205, 56,122,244, 40, 4, 2, 1,140, 70, 35, + 42, 43, 43, 97,181, 90, 29,239,177,201,100, 66,117,117, 53,251, 78,247,245, 36,183, 46, 55,127,124,124,188, 35, 30, 32, 44, 44, + 12, 69, 69, 69, 13, 38,162, 78,171, 2,184,246, 69, 45,128, 16,119, 23,214,172, 89,227, 83, 33, 18, 18, 18,240,246,219,111, 99, +224,192,129, 14, 15, 8,155, 62,123,224,192,129,184,116,233, 18,218,182,109,235,139,232, 46, 51,103,206,188,250,205, 55,223, 56, +143,159,161, 55,110,220,184,209,148,138,101,240,224,193,132, 85,250,131, 7, 15,198,224,193,131,213, 0,112,233,210, 37,244,234, +213,139,107, 59,156, 2,224, 15,224, 71, 0, 83,225,178, 37,184, 29,111, 0,248,204,254,253, 61, 0,189, 0,207, 91,212,123, 80, +254,255, 3,224, 39, 95,159,125,213,170, 85,125,223,121,231,157, 82, 0, 47,118,235,214,173,208, 78, 80, 18,239, 87,221,179,187, + 1,174, 95,181,216, 97,249,175, 95,181,216,113,237,190, 19,128,251,141, 7,133, 4, 76,155, 54,141,190,247,222,123,181, 92,129, +190, 40,255,198,180,254, 1,184,181,254, 89,171, 95, 36, 18,161,176,176,176, 73,149,191,179,245,239, 28,208,165, 86,171,157,189, + 0,247, 61, 96, 51, 43, 43, 11,175,188,242,138, 1, 64, 64, 96, 96, 32,222,127,255,125,136, 68, 34,199,245, 25, 51,102, 0, 0, +130,131,131, 49,113,226, 68, 28, 57,114,228,224,125, 44, 39,113,246, 0,212, 71, 2, 34, 34, 34, 92,183,138,117, 75, 6,140, 70, + 35,180, 90, 45,170,170,170, 16, 20, 20, 4, 63, 63, 63,152,205,102, 80, 74, 97,177, 88, 96, 52, 26, 97, 50,153, 96,177, 88,156, + 9,253,157,250, 10,153,155,155, 91, 35, 0,144,157, 14,112,246, 8, 56, 95,111, 40,124, 8, 8,148,212,117,193, 57, 38,192, 27, + 50,176,124,249,114, 76,152, 48, 1, 93,187,118, 69, 64, 64, 0,164, 82, 41,180, 90, 45, 2, 3, 3,161,211,233,176, 97,195, 6, + 48,140,215, 14,217, 78, 51,103,206,188,186, 96,193, 2,108,223,190, 29,207, 61,247, 28, 0,180, 71, 19,108, 65, 91,151, 39, 32, + 40, 40, 72, 54,101,202, 20, 53, 0,108,222,188, 89, 54,117,234, 84,111,218,194, 8, 96, 26,128, 31,234, 33, 1,206, 83,109,143, + 0,232, 7, 32,195, 71,229,255, 24,128, 23, 26,104,236,246,202,200,200,232,116,229,202, 21,185, 93,249,179, 59,104, 54, 9, 88, +197, 95, 23,254,144,153, 0, 27,170,252, 89,248,106,165, 59, 15,200, 31,125,244, 81,131,149, 63,139, 65, 3, 7,224,192, 65, 53, + 54, 29, 12,112,144,130, 99, 87, 30,107,208, 51, 70, 68, 68, 32, 55, 55, 23, 73, 73, 73,232,220,185, 51, 54,110,220,232,181,213, +165, 84, 38, 74,157, 60, 56,141,162,252,217,249,248,162,162, 34,153,235,181,145, 35, 71,202,146,146,146, 26, 45, 22, 0,176,185, +255,185,122,159,116, 58,221, 5,251, 75,109,221,188,121, 51, 54,108,216, 0, 0,248,241,199, 31,161,211,233,216,219,204,151, 46, + 93, 66,155, 54,109,154,228, 29,112,137,246,175, 69,206,184,238, 19,159,155,155,123,212, 98,177, 64,167,211,225,206,157, 59,208, +233,116, 48, 24, 12, 48, 24, 12,168,168,168, 64, 89, 89, 25, 74, 75, 75, 81, 89, 89,137,234,234,106,118,110, 55,173, 62,153,174, +202,221, 93, 32,169,235,170, 0,174,176,187,250,169,155,115,222, 32,160,177,219, 99,227,198,141,144, 74,165, 8, 8, 8,192,249, +243,231,161,209,104, 16, 24, 24,136,191,253,237,111, 56,114,228, 8,150, 44, 89,226, 45, 1,104, 63,115,230,204,235, 83,167, 78, +197, 79, 63,253,196, 42,255,142, 15,138,242,183,141, 11, 74, 41,171,252, 1, 96,202,148, 41,234,139, 23, 47,122, 59,181,202,146, + 0,216, 73,128,235,116,192,101,167,239,121, 0,206, 52, 64,249,255,143,125,220,242,217,250, 39,132, 92,140,140,140, 76, 11, 11, + 11, 75, 34,132, 4, 17, 66,154,217,203,221, 36,112, 13, 2,108, 18, 2,112, 63,130, 0, 27, 91,249,219, 21,119, 99, 88,110,228, +163,143, 62,106,144,242,127,241,141,189, 24, 52,240,174,235,102,235, 79,219, 28, 30,129, 3, 7,213, 62,145, 0,133, 66, 1,251, +210, 48, 24, 12, 6,236,223,191, 31,203,151,219, 86, 20,156, 57,115, 6,102,179,217, 11, 89,113, 26,192, 22,248, 71, 41,101,131, + 1, 27,164,252, 89,235,191, 62, 55,127, 99,197, 2,176, 68, 66, 42,149,202, 60,221, 27, 22, 22, 54, 54, 33, 33, 33, 34, 61, 61, + 93,248,221,119,223, 49, 23, 47, 94,196,140, 25, 51,204,108, 61, 38, 36, 36, 32, 61, 61, 29,223,125,247,157,240,218,181,107,136, +140,140,244, 40,243, 94,196, 0,176,150,180, 11, 9,160, 44,233,227,138,240,240,240, 76,179,217, 12,163,209,136,219,183,111,163, +176,176, 16,183,110,221,194,173, 91,183,112,251,246,109,104,181, 90, 24, 12, 6, 84, 87, 87,163,180,180,148,253,159,249,245,201, +100, 3,253,156, 73,104, 61,101,247, 74,249,179, 57, 0, 92,207, 53,164,127,184, 89, 13,224, 32,121, 92,101,100,103,103,227,210, +165, 75, 48, 24, 12,136,138,138, 66,255,254,253,177,113,227, 70,188,251,238,187, 16,139,197, 16, 8, 4, 16, 10, 57, 59,100, 59, +205,156, 57,243,230,212,169, 83,145,145,145,129, 15, 62,248,128,181,126,111,226, 1, 89,198,156,153,153, 73,217, 57,255,147, 39, + 79, 98,253,250,245, 50, 0,232,217,179, 39,156, 3, 3, 27, 72, 2,230,195,230, 94,159, 4, 96, 14,128, 72,248,230,254,191, 0, + 96,171,253,127, 76,107, 8, 1,176,227, 52,128,117, 0,158, 1,240, 60,128,205,247,179,238,217, 72,127,119, 65,128,174,171, 0, +238,215, 20, 0,245,242,252, 31, 69,249, 59, 72, 64, 3,166, 18,106, 40,127,119,199, 7, 14,122, 63,190, 57, 15,186, 1, 1, 1, +232,221,187,102,220, 75,122,122,186, 87,242, 38, 77,154,132,164,164, 36,176, 68, 0, 0,181,159,243,122,221,249,198,141, 27,213, + 0,176,103,207, 30,153,187,136,245,148,148, 20,205,213,171, 87,221, 90,143,238, 80, 87,210, 31,150,104,164,164,164, 32, 58, 58, + 90,166, 86,171, 61,246,157,244,244,244,253, 43, 86,172, 24,157,154,154,122, 32, 60, 60, 28, 89, 89, 89,208,233,116,194,224,224, + 96,204,156, 57, 19, 90,173,246, 90,106,106,106,151,240,240,112,164,166,166,146,184,184, 56, 79,228,184,214,156,127, 3, 98, 0, +106,188, 91,108,190, 4,123,238, 4,135,103,198,105,254,223, 99,123, 12, 29, 58,244, 93,141, 70, 51,207, 98,177,160,172,172, 12, + 38,147,201, 49,239, 95, 85, 85, 5, 74, 41, 40,165,184,116,233, 18,140, 70, 35, 98, 98, 98, 94, 82, 40, 20,102,119, 73, 71,234, + 66, 76, 76, 12, 98, 98, 98,106, 4,253,121, 59, 5,224,172,232,237, 46,127,234,220, 63,236,171, 2, 26,123, 92,227, 60,126,178, + 75,253,222,124,243, 77,104, 52, 26,200,100, 50,100,103,103,163, 89,179,102,200,203,203,131, 64, 32,224,234, 1, 32, 51,103,206, +188, 62,125,250,116, 28, 62,124, 24,127,251,219,223, 0, 32, 20,192, 13,220,205,255,208,228,150, 63, 59,190,228,230,230, 34, 34, + 34,130,237,103,178,216,216, 88,117, 88, 88, 24, 46, 93,186, 68, 57, 6, 2, 58,147,128,169,118, 2,240, 35,128,163, 0, 20, 0, +164, 0, 10,193,163,241, 58,112, 99,103,227,115, 23,240,179,106,213,170, 58,207, 55,165,242,183,175, 0,184, 23, 44,218,103,153, +215,243, 61,247,111,127,127,239,188,150,158,130,196,188, 69, 76, 76,140, 44, 41, 41, 73, 51,121,242,100,186,101,203,150, 26, 68, +192,133,240,113,174,135,184,184, 56,143,204,198,203,196, 64,212,133, 72,216, 70, 37,153,140,147,242,119, 26,204, 29,243,250,145, +145,145,127, 73, 72, 72,248,126,226,196,137,184,116,233, 18,174, 93,187,214,101,233,210,165,178,184,184, 56, 78,242,238, 81, 30, +128, 26,245, 92,135,226,227,148, 49, 80,161, 80,232, 19, 19, 19,151,237,222,189,251,239,102,179, 25, 37, 37, 37,142, 24, 0, 0, +184,125,251, 54, 74, 74, 74, 64, 41,101,173,118,175,180, 44, 59,255, 31, 17, 17,225,136, 96,103,207,115, 37, 1,110,172,252, 90, +211, 80,247, 64,249,123, 13,150, 4, 44, 94,188, 24, 41, 41, 41,152, 56,113, 34, 86,172, 88,129,183,222,122, 11, 66,161, 16, 18, +137,196,227, 24, 66, 41,181,206,154, 53, 11,223,127,255, 61,190,253,246, 91, 0,232,108,202,132,133,197, 0, 0, 32, 0, 73, 68, + 65, 84, 87,254,141,110, 80, 53, 4, 5, 5, 5,216,181,107, 87,141, 44,142,246,239,178, 81,163, 70,169,125, 92,242,104,177,147, +128,157,118,235,127, 40,175,252,235,134,187, 32, 64, 78, 4,192,155, 68, 28,190, 42,236,198, 70, 99, 40,255,134, 42,234,123,129, +249,243,231,203, 46, 94,188,216,168, 50,237, 46,210, 70, 93, 74,199, 42, 60,251,218,122,214, 43, 64, 9, 33,176, 90,173,216,186, +117, 43,103, 18,240,246,219,111,179,229,172, 21, 3,192, 48, 12,172, 86, 43,222,121,231, 29, 53, 87,229, 89,159,188,148,148, 20, +141,115, 86, 68, 31,250,221,127, 86,172, 88,113, 59, 53, 53,117, 15, 87,171,255, 62,120,219,136,171,183,167, 14,194,199,137, 4, +196,197,197,125,168, 84, 42,147,126,248,225,135,115, 98,177, 24,236,170, 0,171,213,138,150, 45, 91, 66,167,211, 65, 46,151, 35, + 38, 38, 38, 64,161, 80,120, 92,224,205,142, 47,206,193,127, 39, 78,156, 64, 76, 76, 76,141,241,196,211, 56, 20, 31, 31, 79,115, +115,115,101,174, 46,126, 95,211, 0, 59,195, 77,128,159, 25,128,121,205,154, 53, 18,187, 53,202, 56,125,188, 34, 1,206,137,127, +230,204,153,227,248, 94, 86, 86,230,113,108, 34,132,144,153, 51,103,210,239,190,251,238,121, 0,191, 60,136,138,199,174,232,137, +183,215,184,144,118, 23,220,124, 24,198,240,251, 13,118, 21,128, 59,197,207,105, 21, 64, 99, 43,245,186,228, 61, 40,228,225, 65, +238, 56,159,124,242,137,166,177,101,186,172,145,190,103,112,113,255,115,125,169,185,230, 66, 39, 94, 60,239, 61,125,214, 37, 75, +150,236,109, 72,125,142, 27, 55,174,198,178,216,167,159,126,186,134,103,192,203,185,127,226,165,183,135, 83,185, 21, 10,197,121, +165, 82,217,108,223,190,125, 31,231,229,229,205,171,172,172,132,197, 98,193,128, 1, 3, 48,120,240,224,132,152,152,152,120, 46, +202, 31, 0,142, 29, 59,230,248, 30, 29, 29, 93,227,188,235,177,135,113,133, 56, 19, 90,150, 76,216,227, 0,124,106,247,201,147, + 39,215,117, 73,232, 52, 94,138,239,213,184,226,193, 83, 97, 5,128,111,191,253,150,223, 48,133, 7,103, 18, 80,151,242,175,139, + 0, 52,118,231,226, 59, 43, 15,226, 37,179,255,211,213,141,179,194,191, 7,211, 2,141,242, 14, 42, 20, 10, 61,108,174,215,249, +236,185, 11, 23, 46,112, 81, 92, 14,244,237,219,183,209,199, 3,119,132,214, 87,151,255,189, 38,139, 60,120,253,113, 63, 73,128, +199,202,245,117, 31, 97, 30, 60,120,240,224,193,131,199,195, 11,134,175, 2, 30, 60,120,240,224,193,131, 39, 0, 60,120,240,224, +193,131, 7, 15,158, 0,240,224,193,131, 7,143,135, 16,102,120,177, 93, 49,143, 63, 39,132,124, 21,240,224,193,131, 7, 63,182, +243,248,147,119,146, 83,167, 78,249, 28,113,233, 46,152,208,131,188,122,215, 31,251, 32,175,177,203,199,203,227,229,253,169,229, +253,246,238, 53,159, 7,150,129, 31,119,193,189,150,119, 98,137,239,242, 34, 86,212,150,199,214,159, 82,169,148,154, 76, 38, 92, +185,114, 69,109, 52, 26, 33, 20, 10,145,159,159,143,151,130,186, 98,111,102, 38, 42, 31,239,140,161, 67,135,202, 4, 2, 1,187, +174,189,201,218, 87,169, 84, 62, 6,160,237,185,115,231,118,117,236,216,145,209,106,181,146,142, 29, 59, 46,247,247,247, 95,167, + 80, 40,110, 0, 64, 98, 98, 34,147,152,152,104,169, 75, 94, 98, 98, 98,115,187,183,192, 16, 23, 23, 71, 1, 96,233, 95,159,252, + 74,241,100,222,204, 77,153,225, 87,132,109,199, 14,109,214,188, 69, 5, 0, 74, 41, 21, 2, 8, 78, 76, 76,188,206,191,111, 15, +182,188,123,205, 18,185,110,250,226,109, 10, 92,175, 83,230,174,138,122, 74, 42, 12, 9, 82,231,100, 93,150, 61,234,215, 12,139, +206, 30,210, 60, 72, 44,171,158,124,228,252, 18,151, 38,198,132, 9, 19,164,187,119,239, 86, 39,188,107, 59,254,249,240,147, 56, +116,232, 16,167,118,249,203,140, 87,165, 12, 33,234, 75, 23, 47, 66,167,211,161, 75,151, 46,104,214,188, 57,182, 37,109,229,220, +174,147, 38, 77,170,241,226, 38, 37, 37,213,187,151,130, 61,187,162, 79,253,134,221,168,137, 82,218,176,126, 39,215,214,124, 85, + 85, 33,190,203,138, 88, 3,132,189,106,251,158,187, 1, 56,177,168,225,141, 58,233, 78,205,242, 37,181,230,244, 51,165, 82, 73, +245,122,189,108,219,182,109,234,220,220, 92,200, 69,173,208,190,115, 27, 84,233, 43,225,111, 48, 99,248, 91,175, 99,228,196, 41, +216,249, 77, 34,118, 28, 56,160, 30, 59,118,172,236, 1,232,194, 89, 22,139,165, 67,110,110,174,181,127,255,254,226,240,240,112, +156, 60,121,242,221,170,170,170, 9, 74,165, 50, 70,161, 80,104,227,226,226,172,245, 45, 9,139,139,139, 43,119, 62,254,226,139, + 47,152, 61,255,137,239,209,105,214, 64,188, 51,164, 79,155, 99,251,254,189,101,235, 25,233,169, 30,125, 71,173, 32,132,104, 21, + 10, 69,254,128, 1, 3,172,118,210,192,123, 26,254,100,110, 34,111,153, 6,167,108, 99,190, 40,255, 47,163,159,149, 70,181,233, +164, 38,160,200,174, 40, 65,135,142, 93,213, 38,171, 5, 75,250, 13, 67, 81,151, 54,178,111,118,254,194,137, 8,196, 78, 5,237, +213,157, 61, 18, 96,219, 62, 43, 14, 31,167,136,157, 10,244,234, 14, 44,250,168, 97,138,155,221,160,164,161,217,201,220,145,137, +198,146,219, 16, 80, 74, 41,150, 17,144, 15,235,189, 7, 88, 70, 48,249,130,252,129, 89,107,125, 87,249, 83,187,242, 31,137, 35, + 71,142,112,250,109,218,177, 23,169,217,212, 11, 42,213, 77,164,167,217, 18,214,100, 93,188, 4, 0,216,181,139,208, 75,151, 39, +201, 22,205,231,214, 46, 99,198,140,177,238,223,191,159, 73, 74, 74,194,193,131, 7,107, 36,195,113,133,143, 41, 84, 29,205,228, +166, 35, 83,234, 3,161, 96,211,133, 55, 56,103, 65,216,171,142,141,118,214,172, 89,211, 56, 4,192,169,158,236,187, 19,114, 66, + 78, 78, 14, 52, 91,182,168, 63,140,153,140, 1,211,230, 64,220, 46, 24, 16,218,147,253, 89, 41, 96, 21,193, 90, 77, 49,254,213, + 88,228,125,186, 18, 71,143, 30, 85, 43,149,202, 26,233,110,155, 0, 22,134, 97,218,182,110,221, 26, 26,141, 70,216,191,127,127, + 12, 25, 50,132, 41, 44, 44, 28,120,250,244,233,179, 74,165,114,144, 66,161, 40,180, 43,107,134, 99,221, 53, 27, 61,106, 76,216, +138,213,219,153,248, 25,103, 90, 12, 29, 55, 91, 54, 52, 50,249,201,183, 62,203,127, 38,252,137, 87, 34, 0,148,195, 22, 99,192, +212,165, 31,156, 19, 91,121,234, 71, 13, 38,164, 60, 92, 61, 9,158,188, 5,142,239,222, 4, 1, 82,182,113, 7,188,210, 15, 74, +165,146,241, 66, 17,186,110, 82, 65, 35, 34, 34, 16, 17, 17,225,115,158,120,229,203,177,210,151, 7, 70,169,123,118, 8, 69,247, + 14,161,120,188, 77, 71,132,250, 55,131,196, 10,116,243,107,134,160,236, 27,234,153,207, 60, 39,229, 34,171, 87,119,224, 98, 14, +131, 11,151, 3,112, 54,167, 5,158, 31, 19,136,213,239, 9,208,171, 59,105, 52, 35,189,161, 74,154,221,230, 52, 44, 44, 76,157, +153,153,137,204,204, 76,252,253, 63,167,241,232,248,120, 53, 0,234,229,150,167,148,235, 71, 46,151,123,126,139,151,217,234, 40, + 34, 34, 2,114,185,220,237,135,189,199, 91, 76,236,255,129,212,185, 60, 19,250, 45,147, 54, 70,123, 76,152, 48, 65,186,107,215, + 46, 53, 33, 4,111,126, 76,240,243,225,145, 56,124,248, 48,167,223,110,217, 50, 77, 58, 52, 50, 14, 35, 70,220,196,167,159,126, + 90,227,218,203, 47, 3,227,199, 3, 11,231, 37,169, 87,127,194,173, 77, 88,229,175,209,104,192, 48, 12,166, 76,153, 2,129, 64, +208, 16,101, 95,203,242,119, 55, 32, 19,226,155,242,111, 52, 68,172, 6, 0,172, 93,187, 22,107,215,174,181,157, 27,148,208,100, +197, 57,120,240, 32,190,120, 33, 22,131,159,147, 67,216, 42, 4, 68, 36, 0, 35, 18, 64, 32, 17,131,241,151, 0,160,160, 22, 51, +168,209,136,215, 95,157,131,178, 3,153,200,201,201, 81, 43,149, 74, 41,154, 14, 36, 51, 51, 51,170,115,231,206, 98,171,213,138, +148,148, 20,108,223,190, 29, 65, 65, 65,136,138,138,234,176,121,243,230,127,216,239,227, 20, 16,168, 84, 42, 5, 71, 14,252,247, +255, 30, 9,200,111,167, 47, 23,224,229,101, 21,248,252,223,159, 0,205,251, 10,255, 29,223,182, 91,206,201, 31, 94,118,210, 29, + 76, 29,196,144, 56, 41,117, 98, 59, 77, 28,223,157,207,223,163,189, 48,120, 52,178, 7,192,209, 74,155,246,252, 80,210,253,209, +238, 45, 21, 31,190,110,245, 82, 59,146,136,136, 8,202,166, 37,117, 74, 79, 74,189, 77,219,169,124,225, 85,233, 83,157, 31, 85, +139,171,204,240,255,247,219, 48, 27,140,144,188,249, 17,130,196, 18, 84,137, 42,161,175,170,132, 63, 8,170,175, 23,169,255,249, +207,127,202,222,121,231,157,122,149,239,197, 28, 96,253,143, 86, 0, 6,251, 7,120,242, 9, 6, 47,140, 37, 53,222,155,216,169, +192,122, 31,118,118,182, 91,233,212, 87,107,157,181,250, 51, 51, 51,239,214,193, 17, 19, 42,141,122, 0,192,232,248,253, 80,173, + 26,227,149,151, 33,103,101, 14, 68, 36,251,110, 71, 32, 5, 32,173,123, 57, 29, 23,161,205,255,190,192,173, 97, 63,116,228,155, + 39,117,165,157, 37,118,210,119,226, 4,183,118, 86, 60,251,185,116,253,246,191,170,119,156,254, 0, 43, 22,252,140, 72,105, 56, + 54,125,121, 24, 95,239,179,109, 16, 52,251, 47, 31,200,214,253,231, 3,159, 72, 85,194,187,160,192, 46,168,190, 59, 7, 74, 41, +154,183,125, 28,135, 15, 31,134,125,223,130,122,203,183,250, 19,185, 84, 46,111,165, 6,190, 0,240, 51,210,211,129,200,200,187, +215,255,241,143,187,223, 23,206, 75, 82,251, 7, 44,149,205,126,125,121,189,229,100,149,127,116,116, 52,172, 86, 43, 62,255,252, +243, 70,117,208, 0,128,213,106,173,173,252,105,253,239, 47, 51, 89, 87,227,229,103,135,112,171,220,205,125, 14, 63,159,237, 75, +255,254,181,231,216,153, 41,186, 26, 52,223,106,157,129, 5, 11, 22, 56,174, 47, 88,176, 0,107,215,174, 5,211, 99,214,221,255, +106,191,223,157, 60,225, 20,247,229,115,221,201, 90, 56,133, 91,249,170,170,170,208,190, 75, 87,192,106, 4,227, 7, 16,161, 0, +230,242, 82, 84,229, 94,193,237,252, 2,116, 26, 38, 5, 17,183, 4, 49, 25, 1, 1,131, 85,179,223,194,152,245, 31, 96,209,162, + 69,141, 61, 46,115,210,138, 74,165,146, 80, 74, 91, 86, 86, 86, 14, 11, 9, 9,193,165, 75,151, 96,181, 90,113,229,202, 21,108, +216,176, 1,189,123,247, 70,104,104,232, 43, 0, 94,119, 81,214,117,122, 3, 40,165,173,187, 48,233,210, 14,143,140, 19,151,164, +156, 65,169,206, 15,223,239, 52, 99,247,177,255, 96,158,220, 95, 40, 52, 88, 35,236, 49, 5,110, 9, 0,175,208,155, 30,117, 77, +247,184,243, 12, 48, 28, 58, 34, 59,111, 8,233,146,145, 88,159,162,108,153,115, 57, 7,167,190, 59, 3,165, 82,233,149,245,192, + 42, 7,131,225, 7, 24, 12,155,160,213,198,176,214,177, 87, 15, 56,196,175,133,186,109,149, 5,146,101,115, 96,185,163,133,249, +242, 85, 8,197, 34, 4, 16, 1, 2,137, 0,129, 2, 33, 66, 68, 18,208,114, 61,110, 30, 60,234,113,167, 23,119, 74,253,240,113, +171,227, 61, 92,253, 30, 65,194, 82, 98,247, 8,248,102,253,219,149,179, 26, 62,164,192,117, 85,254, 16, 10,144,123,179, 2, 55, +139,141, 72, 63,111,219, 64,164,199,140, 29,240,102,223,115, 17,201,134,144, 20,192,143, 57,109,251,219,150, 32,248,229, 27, 8, +154,122, 22,126,207, 47, 3, 66, 3,189,243,228,114,216,185,205,155, 45, 94,149,219,223, 80, 15, 13,121, 15, 39, 14, 93,193,255, + 76,154,136,208,214, 61, 49,231,175,175,225,179,165,251, 48, 52,120, 41,214,253,231,239, 62,239,224, 67, 8, 16,183,232,172,195, + 98, 25, 49, 98,132, 93, 33, 89, 61, 54,240,180,169, 34, 53,112, 16,192,207, 40,185,213, 12, 61, 30,105,134,175,190,178, 89,254, +203,150, 1, 97, 97, 54, 17, 37,183,154,161,228, 86, 51, 12,232,119, 65,237, 73,249, 31, 60,120, 16, 86,171,213,161,164, 55,111, +222, 12,139,197,226,149,251,186, 30, 15, 79, 45,229,111,123,159, 61,147,119, 10,144,117, 74,165,140,181,212,172,148,194,106,173, +221,125,217,243, 86, 74,177, 46, 49, 81,150,104,251,141,219,255, 73, 1, 66, 41, 72, 98,162, 82, 70, 41,197, 39,159,124,226,184, +206,126, 79, 76, 76,148, 81,106,187,143, 2,164, 46,121,137, 74, 37,236,215,136,197, 98,129,217, 98,129,217, 92,187,206,216,243, +102,139, 5, 95,174, 91, 39, 91,151,152, 88, 71,249, 40,132,205,155, 3, 34, 1, 44,134, 10,156,219,154,132,191,189,166, 64,167, + 55, 20, 24,184,242, 67, 92,249,237, 36, 4,254, 18,152,138,111,225,204, 49, 13,118, 28,222,139,210,194, 66,156, 61,123,182,209, + 54,214,138,138,138,226,228, 77, 80, 42,149, 65,148,210, 33,153,153,153,191,188,255,254,251,125,206,157, 59, 39, 54, 26,141, 16, + 8, 4,104,222,188, 57,204,102, 51, 50, 50, 50, 64, 8, 17,123, 26,235, 19, 19, 19, 3,149, 74,165,127, 98, 98, 98,104, 73,126, +234,111,127,255,191,188,144,223, 15,239,132, 86,207, 64, 44,100,208, 41, 88,130,210, 59, 98, 40,254,105,198,153, 59, 3, 3, 61, +233, 13,123,172, 9,117,238,139,118, 98, 80,235, 60,175,174,239, 15, 88,229,239, 74, 14, 24, 79, 44,148,221,239,187,134,155,115, +220, 52,239,189,125,118,119,191,193,176, 9, 0, 65, 85,213,183,144, 28,191, 10,195,222, 71,107, 92,247,132,119, 6, 69, 75,131, +180,229,176,138,133, 48,158, 56,135,234, 11,185,168,218,119, 24,168,172,134,152, 82, 4, 64, 0, 33, 8,170,173,102,104,171,171, +240,229,254,157, 30,101,174,126,207,102,221, 59,195,118,204,154, 43, 20,151, 46, 83, 44,250,200,247,254,234,146,175,156,179,203, + 94, 46,151, 59,246,214,102,241,210,218,124, 28, 56,161, 67,222,173, 42, 0, 64,222,173, 42,100,231, 87, 2, 49, 91,216,141, 81, + 60,187,126, 72,129,141, 8,148,159, 65, 96,224,101,248, 73,202, 97,181,106, 97, 50,157,128, 64, 16, 6,163,190,184,201, 58,235, +228,113,127,149, 2, 4,159,255, 60, 11,205,152, 71, 0, 0, 55, 47, 81, 12,154, 40,192, 95,151,143,193,136, 49,125, 0, 80,251, +125,222, 33, 58, 58,154,190,249, 49, 65,179, 54,253, 64, 1,140,123, 97, 54,231,121,255,117, 95, 45,165,109,219,254, 14,224, 44, + 74,110, 53, 67,121,177,109, 11,230,254,253,129, 30, 61,128, 87, 94,185,171,252,203,139,253, 81, 94,236,143,144,128,155,245,202, +156, 52,105, 18,100, 50, 25, 70,141, 26, 85,195,245,239,252,241,101, 74,192,221,123,235, 11,226,156,230,183, 9, 33,142, 79, 93, +231,226, 20, 10,141, 34,214,243,156,120,108,108,172,218,157,229,188, 96,193, 2,196,198,198,214, 80,168,117,201,251, 89,169,196, +217,179,103, 29, 46,120,231, 58, 99,225,122,110,118, 92,156, 38, 78,225,126,171,102, 49,165, 96, 2,252, 96, 42,188, 6,229,210, +165,216,160, 47,129, 46,122,168,227,250, 55,255,217,128, 15,222,122, 13,225,139, 94,194,135,103, 14, 98,139,238, 10,198, 60,251, + 44,194,194,194,188, 14, 6,180, 43,122, 26, 25, 25, 89,163, 15, 31, 59,118, 76, 93,223,118,236, 74,165, 82,164, 84, 42, 7,159, + 57,115, 38, 47, 37, 37, 69,243,230,155,111, 14,253,252,243,207, 37, 21, 21, 21,142,109,154,171,170,170,208,172, 89,179,236,201, +147, 39,247, 28, 62,124,248, 35, 30,136, 4, 67, 8,233,114, 38,109,107, 81,214,222, 69, 87, 23, 45, 73,232,176, 99, 89, 71, 92, + 40, 16,162,180, 66, 0, 43, 1,138, 43,140,160,173,186, 87, 45,124,247,163, 62,207, 60,255,151,215,225, 33,158,192,238,254,175, +225,234,247,240,157, 71, 19, 40,255,186,166, 0, 40, 87, 87,142, 66,161,240,116, 19,117,181,254,109,174,182,111,235,242, 14,120, +252,167,125, 90,183, 83,107,169, 9,226, 98, 45, 36, 63, 31, 4, 17, 50, 64,149, 17,180, 92, 15, 98, 54, 67, 4,192, 66,173,168, +178,152, 81,110, 54, 2, 86,207, 86, 20, 27,228,183,250,189, 58, 57, 45,108, 65,130,141, 66, 88,137, 83, 32,159,199, 23,160,150, +245, 15,224,191,111,116,168,113, 60,120,113, 46, 68,244, 14, 76,164, 53, 84, 42,213, 65,174, 47,150,164, 66,141,144, 15,255,131, +219,111,198,225,142,214, 31, 29, 77,231, 96,177,228, 2, 0,174,157,106,223,100, 29,118,203,158,207,212,175,141, 85,214, 80,254, + 44,134, 6, 47,197,176, 62,147, 16, 21,114, 14, 91,246, 44, 87,123, 51,136,140, 28, 57,146,166,164,164,160,184,120, 52, 90,181, + 58,128,102,173,251,130, 82, 10,134, 97, 56, 5, 34,229,229, 1,185,185,103,237, 71, 21,128,164, 2, 90, 61, 48,100,136,237, 76, +118, 54,240,197, 23, 64,121, 25,160,175, 0, 42,244, 64, 96,112, 25,167,178,213,101,237,231,228,228, 0, 0, 62,254,248, 99, 0, + 64,120,120,248,189,112, 51,115,170,195,249,243,231,215,176,216, 93, 21, 55,103,239,142, 93, 97, 59,230,253,157,240,201, 39,159, + 96,237,218,181, 80, 42,149, 82, 79,193,117,179, 66,195,145,117,238, 60, 10,130,131,213, 12,195, 96,222,188,121,181, 98, 50,188, + 41,223,147,213, 45, 65,173, 21,120,237,227,247,208,111,210, 36, 40, 63,254, 24, 12,115, 87,207, 41,179,207,222,245, 16, 30, 62, +140,253,251,247,227,202,149, 43, 50,133, 66,161,225,178,241,138,179,242, 79, 75, 75, 83, 3, 64, 70, 70,134, 58, 42, 42, 74,150, +150,150,166,137,140,140,148,166,167,167, 35, 42, 42, 74, 86, 89, 89,169,174, 99,204, 53,205,152, 49,163,223,180,105,211, 90,116, +235,214, 13,187,119,239, 54,148,150,150, 10, 43, 43, 43,109,222, 14,251,252,199,182,109,219,194,199,141, 27,231,175, 80, 40, 42, +221,136, 97,156,148, 53,147,123,233,212,218, 15,222,153,217,172, 85, 15, 21,126, 83,189,138,223,175, 19,228,221, 18, 2,148, 65, +181,209, 4, 45,109, 85, 48,119,214,156,161,132,144, 2,118,204,247,230,121,221,120, 8,248,169,130, 7, 4,117,178,184,148,148, +148, 90,159,146, 2, 29, 74, 10,116, 94,181, 53,251,185,107,197,218, 26, 94,114,252, 42,252,206, 22, 64,152,175, 99, 61, 0, 53, +238,175, 75,224,249,252, 60, 28,191,115, 3,231,174,228,226,214,149,171, 40,187,154,143,242,235, 5, 48, 27, 42, 97, 50,153, 81, +110, 49,194, 96, 49,163,154, 90, 96, 1, 5, 37,220, 73,166,115,180,255,197, 28,219,241,162,143, 88,203,159, 65,194,123,141,179, +226,197,219, 56,128,120,149, 14,241, 42, 93, 13,133,207,126,162,226, 51, 32,162,119, 32,164, 58,252,119,150,197,204,121, 10,224, +214,113, 88,244,205, 0, 0,255, 22, 6,161,250,214, 53,100,254,179, 3,178,126,152,128,227,255, 28,128,236, 75, 55,154,180, 99, +246, 31, 18, 6,189, 14,208,235, 0,131,255,121, 0,192, 79,127, 55,225,157, 5,203, 0, 0,195, 99,250,120,109,249,191, 48,242, + 16,180,218, 24, 4, 31, 59,128, 53,239,217, 72,238,200,145, 35, 57,185,254, 1, 96,197, 63,150,147,238,221, 1,231,207,197,139, + 54,247, 63, 0,244,232, 65,177,118, 45,208,165,103, 5, 30, 27,122, 27, 67, 70,223,198,243, 47,153, 56,151,209,217,226,103,143, +195,195,195, 17, 30, 30,142,121,243,230, 53,118, 21,123,124,215,156,177,126,253,122,153, 59,133,237,240,162,173, 94,141,245,235, +215,115,178,132, 95,127,253,117, 53, 27,249,239, 14, 11, 23, 46,172,229, 5,112,135, 67,231,243, 48,115,214, 92,156,216,180, 9, + 75,150, 44,169,147,156,176,229, 59,112,224, 0,234, 11,216, 27,249,216, 35,248,246,155, 47, 16,241,242,203, 88,177, 98, 5,234, + 43,227,130, 5, 11, 48,122,244,104,248,178, 2, 32, 45, 45, 77,237, 20, 44,135, 99,199,142,169, 1, 32, 61, 61, 93, 77, 8, 65, + 90, 90, 90,189, 50, 13, 6, 67,203,157, 59,119,226,252,249,243,200,206,206, 14,208,235,245, 48,153,108,253,204,104, 52, 98,207, +158, 61,196, 78, 22, 42, 57, 20,199, 90, 93, 93, 45, 62,177,245,101, 84,101,125,134,189, 41, 57,184,114, 83,128, 50, 61, 3, 11, + 5, 10,244,254,152,187,232,189,168,184,184,184,124, 14, 6,159,131, 87,176, 75, 78, 57, 78, 7,240,104, 2,235,191, 46, 2, 64, + 0, 16,169, 84, 10,169, 84,138,211,167, 79, 59, 62,185,199,175,161,180,178, 20,173,134,120,191,238,247,196,137, 19, 4, 0, 2, + 2,166, 65,114,252, 42, 68,215,138, 65, 9,129,120, 86,113,141,235, 30, 21,151, 88, 0, 11, 5,242,245, 37,200, 43,213,226,118, +153, 14,165, 85, 85,208, 25, 43,113,187,186, 18, 55,171, 12, 40,168,170,128,214, 84, 13,157,213, 4,163,213,115,240,235,147, 79, +184, 25,240,156,226, 2, 94,155,210, 12, 20, 98, 80,175,183, 1,191, 27,189,239,230, 28,103,228,221,170,194,129, 19, 58, 12, 94, +156, 91,179, 46,232, 29,248, 89,175,193,207,122, 13, 31, 60, 37, 68, 94, 94,158,145,171,204,173, 87,172,104,147,144,232, 56,190, +162,183, 32, 63,167, 0,151, 82,207,161,240,106, 73,147,119,220, 77, 95,166, 0, 0,202,138, 40, 2, 42, 31,131,116,150, 16,255, +179, 76,228,248, 36,108,121, 25,132,187,241, 79,159, 27,145,130, 87, 23,217,148, 63, 33, 4,191,164,218,154,128,235,154,127, 22, +225,189,122,214, 44,231, 38,224,243,207,129,203,151,109,158,128,191,255,157, 58,220,239,148, 82, 4, 7, 7,123, 30,129,237,125, +148,157,247,255,248,227,143,145,147,147,131,172,172, 44,100,101,101, 33, 57, 57, 25,111,189,245, 22,242,242,242,154,172, 61, 88, + 69,231,206,146,158, 63,127, 62, 8, 33,156,149, 33, 33, 4,245,145,137,250,174, 57,227,176, 95, 9, 8,211, 12, 95,191,251, 17, +154,237, 76, 70,108,108, 44, 94,102,217, 24, 0, 69,143,190,152, 31, 49, 12, 1, 1, 1, 24, 57,114, 36,222,127,255,125, 36, 39, + 39,171, 87,172, 88,225,246,253,251,166, 32, 11, 55,251, 60,134,208,208, 80,153,213,106,173,151, 80,212,119,141,131,114,116,120, +156,162,162,162,100, 78,138, 18, 67,135, 14,149,121,240,158,140, 26, 57,114,100,139,188,188, 60, 28, 62,124, 24,143, 62,250, 40, +132, 66,161, 99,138, 35, 52, 52,148,235,116,132,213,254,127, 73,247, 94, 3,227,215,239,107,137,223,119, 47,195,147, 81,189, 17, + 40, 97, 16, 24, 96,129,191, 95, 53,158,126,110,178, 21,128,214,249,135,137,137,137,158,230,162, 28,171, 0, 56, 78, 7,240,120, +208, 60, 0, 0,136, 82,169,108, 62,127,254,124,204,159, 63, 31, 0,140,255,136,251, 7, 76, 69,102,248,251, 75,224, 75,227,201, +229,182,240,225,128,167, 46,131, 10, 24,188,255,147,193,217,250,231,132,128,208, 80,153,185, 89, 0,116,212,130,243,122, 29,206, +150, 22,227, 92,217, 29,156, 43,211,226,188, 94,139,203, 6, 29,138,171,171, 80, 97, 54,227,134, 65,239,248,159,245,225,133,177, + 4,171,223, 19, 96,245,123, 2, 80, 8, 64, 9,131,216,169, 4,175, 79, 21, 99,214,148, 54,232,222,189, 29,172, 16,121,253,200, +172,171,223,121, 94,190,158,164, 64,117,201,144,101,231,219,136,124,230, 74, 91, 16,221,222,183,131, 0, 0, 66,170,131,128,234, + 81,205,216, 34,154,181, 90,109,128, 92, 46,143,241,166,140, 17, 17, 17, 72, 78, 78,198,166, 10, 61, 42,141, 12, 94,253,241,107, + 20, 73,252, 81,105,108,186,109, 34, 38,246,255, 64,150,166,253, 8,155,190,223,226, 56,247,211,223, 77, 24, 26,188,212,113, 28, +251,204, 23, 50, 10, 78,235,135,233,154,165,192,140, 69,163,209,242, 88, 50,100,255,140, 6, 51, 1,208,104, 52, 62,245,225, 46, + 93,106, 70,143,143, 26, 5,180,108, 9,132,133, 1,145,253,155, 67, 34, 22, 64,192,220, 21, 43,241,247,247, 56, 32, 51, 12,227, +176,252,115,114,114, 28, 86, 63,251,249,240,195, 15,241,225,135, 31,226,198, 13,238, 94, 25,119,243,245, 53,175,123,111,125,173, + 95,191, 94,182,102,205, 26,183, 10,155,171,245,239,228,122,174, 21,167,192, 30, 91,173,220, 82,216, 27, 9,129,213, 80, 13, 81, +251, 46, 80, 44, 95,142, 25,129, 45,209, 82,147,230,184, 62,235, 47, 51,240,193,191,191, 70,246,234,255,226,111,253, 70, 97,114, +112, 55,236,223,190, 29,185,185,185,110,223,191,231,227, 20,232,211,183,175,204,106, 47, 19, 75,200,156,167,103,220,157,171, 11, +179,103,207,166,132, 16,202, 6,246,177,243,253,206, 74, 62, 45, 45, 77, 51,116,232, 80, 25,165, 20,236, 84,128,135,122, 75, 17, +137, 68,143, 62,255,252,243, 57,165,165,165,208,233,116,240,247,247, 71,155, 54,109,208,178,101, 75,180,108,217,210, 83,229, 89, + 93,136,157,197,207,207,207,240, 98,220,167,178, 13,199, 7,227,234,245, 50,180, 11, 18, 32,170, 39,193,227,221, 40, 2, 91,180, + 40, 1, 96,169, 71,111,240,251, 13, 60,164,214, 63,224, 97, 25,160, 66,161,168, 80, 42,149,126, 0, 2, 21, 10,133,131, 5,118, +138,238,232, 19,243,101,151,250,201,229,114, 42,158,229,136,252, 39, 78,243,255, 30, 7,228,119,119,109,209,124, 28,243, 28, 12, +230,106,148,233, 13,200, 49,153, 32,178,218,126, 92,106,170,130,149, 82, 80, 0,187,111, 93,129,222,108, 2, 0, 14, 3, 19,193, +162,143,106,246,113, 91, 60,128, 21, 22, 84,227,194,229,114,124,187,185,204,171,135,117, 86,244,118,151, 63,181,127,119, 40,118, + 46,171, 31,108,191, 85, 65, 52,250, 75, 0, 97, 40, 46,190, 27,156, 39,182,222,132,145,233,128,185,253,178,112,243,166,195,114, + 58,192,165,124,113, 63,173,175, 65,188, 84, 42, 21,216,210,252,120,230, 40, 98, 98, 98,154,172,227,238, 56,109, 91,222,151,154, +124, 14, 0, 48,172,143, 45, 51,222, 59, 11,150,225,232,185, 62,248,247,150,151,161,220, 57,135,243,252,255,171,139, 98, 16, 18, +146,108, 63,210,216,201, 82, 12, 40,181, 89, 99, 0, 69, 72, 72, 50, 39, 89,251,247,238,115,228,180,120,249,101, 64, 38, 35,184, +115, 61, 8,122,157, 4,149,101, 98,252,184,145, 96,254,124,138,107, 69,229,136,140, 26,138,148,131,106, 78, 86,177,197, 98,113, +204,247, 39, 39,219,202,234,172,240,139,138,138, 80, 84, 84,196, 89,255, 59, 41, 12,202, 48, 76, 45,165, 74, 41,136,183, 73,128, + 20, 10,133,230,245,215, 95,175, 17, 11,192,122, 4,188,113,133, 19, 39, 86, 98,117, 89, 86, 64, 8,247, 57, 59, 66, 8,204,229, +229, 16,181, 14,129, 32,160, 25,250,188, 56, 9, 31,142, 29,131,119,217,101,123, 3, 7,193, 82, 89, 5, 81,171,118,232, 55, 84, +138,174,157,186,225,211, 11,105,232,219,183,175,236,248,241,227,181, 72, 64,156, 66, 1,128,168, 1, 96, 78, 92,156, 99,233,160, +217, 69,217, 11,133, 2,128,222, 93,168, 88, 87,129,215,173, 91, 71, 0, 80,187,139,159,100,100,100,184,117,241,167,165,165,105, +184, 40,255,196,196, 68, 66, 8, 89,218,178,101,203, 62, 67,135, 14,237,126,241,226, 69,156, 60,121, 18, 22,139, 5,129,129,129, + 48, 24, 12, 69, 33, 33, 33, 87,189, 49,250,148, 74, 37,211,174, 93,187,253,207, 61,247, 92,187, 99, 71, 50,176, 86,181, 31, 45, +136, 24, 61,219, 85,227,242,157, 64,140,232,105,186, 2,192,117, 30,203, 82, 95,155, 56,103,156, 34,132, 56, 31,186,230,125,225, +209,196, 16,114,120,233,141, 0,140, 78,131, 10,205, 79,241,122,126,184,134,114,175, 67,241,113,206, 24, 88,166,213,201, 76, 1, + 18,117, 41, 99, 69, 97, 85, 5, 96, 50,193, 98, 95,215,116,161,162, 4, 5,134, 50, 80, 74, 97,207, 47,160,225, 82,188,216,169, + 4,235,127,188,219, 39, 47,230, 0,189,186,155, 33,128,190, 65,202,223,165,179,123,170,131, 58,189, 0, 42,213, 28, 53,144, 9, +173, 86,107,204,203,203, 19,174, 26, 3, 38,126,255, 72, 44,232,123,212, 97,133,113, 37, 21,238,188, 46,174,199,172, 18,226,106, +205, 97, 25,193, 96,251, 74, 14,119,203,253,182,108,217, 98,203, 4, 40,151, 83, 46, 57, 31,226, 38,126, 41, 83,238,152,171, 78, +219, 66, 17, 21,114, 14,195, 99,250,224,200,254,115, 56,166, 91, 14, 2, 2,197,196, 47,100,137, 59,230,114, 42, 95, 72, 72, 50, + 8, 33,120,225,133, 23,240,213, 87,101, 96, 85,140,237, 47,101, 9, 1,173,105,217,223,169, 83, 94,244, 40,153, 44,229,160, 90, + 61,106, 20, 96, 44,236,140,235, 37,126,176,218,103, 91, 59,232,219,225,237,216,114,236, 63,214, 19,205, 59,245,148,177, 89, 2, +235, 3,171,248,243,243,243, 1, 0,133,133,133, 14,207,192,173, 91,183, 28, 3,171,143, 32, 78,110,103,215,151,146,112,201, 7, +224,140,175,190,250, 74,182,118,237, 90, 53, 75, 0,214,172, 89,227,181,245,239,170, 48,124,133, 68, 34, 65,225,181,171,232,214, +189, 7,172,230,106, 16,179, 5,194,230, 45,208,124,208, 96, 52, 27,248, 4,172,122, 51, 44,134,106, 80,179, 5,176, 88, 17,191, +238,223,152,242,242, 20, 72, 36, 18,183,242,204, 63, 6,115,250,191,238,238,139, 88,225,254,222,168,168, 40,153,157, 0, 80, 74, + 41,134, 15, 31, 46, 75, 77, 77,173,117,159, 39,229,111,175, 43, 43,128, 61, 61,123,246, 28,248,217,103,159, 25,111,223,190, 93, + 53,102,204,152,231, 50, 51, 51,255,102, 48, 24,138, 91,183,110,173,248,244,211, 79,181, 92,235, 79,169, 84,138, 0, 60, 50, 52, + 50,178, 77,220,172, 56, 92,201,191,162,157, 62, 43,238,201,244,253, 27, 19,110,150,107,135, 13,142, 30, 99,109,215, 41,252,127, + 92,173,252,250, 82, 11,219,251, 24,113,226,159,196,141, 14,112,253,206,227, 65, 37, 0,245, 89, 23,190, 40,127, 86,217,212,145, + 48,134, 19, 9, 88,121,242,144, 6, 0,153, 58, 40,138,194, 95, 2, 29, 53,195,104, 54,195, 74,173,104, 21, 20,132,124,125, 41, +188, 73, 46,228,110,121,223,221, 24, 0,239,214, 98,187,115,241, 55, 52, 93,175, 61,143,192,196,193,131, 7,239,136,143,143, 23, +135,132,132, 88,111,222,188,137, 5,125,111,186, 42,127,206,255,163,174,132, 61, 62,193,158,229,207, 77,146,167, 90,247,112, 69, +226,142, 57, 26, 0,100, 66,191,101,210, 93,103,254,174, 78,219, 2, 16, 16, 76,236,255,129,108,199,233, 15, 52, 92,149, 63,219, +151,138,139, 71, 83,160,140,181,126,225, 78,239,108, 72, 56,192,246, 7, 82,223,230, 26,118,171,158, 20,235,250, 74, 45,229,229, +106, 34, 0, 12, 85,254, 32,229,102, 8, 25, 33, 12,140, 68, 54,118,242,107,152, 27, 27,231,177, 61,146,146,146, 72, 82, 82, 18, +189,135,239, 31, 40,165,132, 16, 66,157, 35,218,157, 61, 1,222,200, 82, 40, 20,154,216,216, 88, 44, 88,176,192, 65, 40,154, 42, + 21,238,168, 81,163, 48,119,203,122,124, 88, 94,130, 1,209, 35,192,180, 11,182,149,201, 68,109,169,123, 33, 2, 17, 8, 65,196, + 2,124,149,184, 26, 45, 70, 15, 70,247,238,221,189,142,218,111, 8,156,172,123,117,100,100,164, 44, 53, 53,181, 65,117,149,147, +147, 19,115,224,192,129,107, 2,129, 96,251,147, 79, 62,249,143, 57,115,230,220, 94,183,110, 93, 10, 96,155,114,240, 66, 20, 3, + 32,249,228,201,147, 67,190,219,176,145, 17, 11,252,174, 79,122,105, 82,255,185,115,231,234,190,252,242,203, 9, 0,130,236,138, +191,156,221, 32,136,139, 71,129,199,131, 1, 46,238,127, 95, 9, 64,131, 9,131, 7,229,195,121, 64,250,241,100, 26,145, 79,146, + 75,173,151,178,213,250,106, 35,204, 22, 11,186, 15, 25,132,112,115,164,183, 10,183,209,130, 81,216,164, 63, 0,212,172, 53,110, +143, 3,104, 80, 14,124,149, 74,181, 83,169, 84, 10,147,147,147, 23,173, 90,181,234,159, 78,228, 98,148,243,255,226,234, 81, 0, +208,104,201, 75, 38, 95, 96,227, 44,234,126,190,201, 23,228, 62, 49,253, 93,103,254,174, 97,219,135,130, 98,199,233, 15,124, 42, +163, 77,185, 19,188,186,104,212, 93,179,151,220,189,182,232, 35,239,243,145,199,191,125, 86, 19, 15,144,117, 95, 45,149, 86, 26, +108,251, 0,220,205,255, 31,231,245, 59, 98,183,200, 44, 10,133,162,209,231, 85, 89, 18,208, 24,178,236,177, 0,106,246,123, 35, +148,205,167,223,117,239,222, 29,237,231,205,147,173,221,183, 79,157,251,143,159, 33, 23,181, 66, 75,251,230, 61,149, 6, 51,230, +191,181, 4,130,128, 16,236,222,168,196,233,214, 4, 99,135, 13,243, 57,111,191,197, 98,246,121,152,224,234,226,231, 64,190,200, +243,207, 63,127,155, 82,154,208,171, 87,175,255, 43, 46, 46,214,251,160,248,157,235,125,100, 70, 70, 6,172,102,130, 97,195,251, +127, 48,119,238, 92, 29, 0,204,153, 51,199, 10, 64,215,144, 38,117,242, 56,213,248,238,198, 43,202,227, 33,243, 0,220, 19, 82, +224,179, 98, 76,170,145, 96, 7, 25, 57,151,154,188, 82, 93,146,254,176,231, 26, 44, 87,161, 80, 88, 0,252,203,254,241, 89,174, +187,242, 53,240,121, 73, 99,220,115, 47, 97, 83,240, 20,139, 62, 74,110,116,217,158, 82,253,122,209,190,166,123, 89, 7,141,181, +233,138, 66,161,208, 40, 20,138, 70,145, 69, 26, 48, 7,192,150, 65,169, 84,194,190,125, 47,242,156,182,239, 77, 61,176,223,177, +125,239,232,161,163, 97, 39,189,117,254, 63,193, 20, 29,177,108, 14,174,173,152, 56,238, 38,232,137, 4, 52, 70,125, 61,241,196, + 19,213,102,179, 57, 5,128,254,253,247,223,111,144, 18,141,139,139, 35,239,191,255, 62, 53, 26,141, 0,176,175,174,251, 86,174, + 92, 73, 22, 47, 94,236,248, 95,246, 84,192,245,142,237,174,193,157, 60,238, 47,184,122,184,136,175,251, 8,243,224,193,131, 7, +143, 38,129, 25, 64, 21, 0, 73, 35, 27,113,158,118, 12,228,188,163, 32,143,135, 3,124, 99,242,224,193,131,199,195, 5, 33,128, +102, 28,148,191, 1,182, 0,238,198,210, 7, 86,240,203,254,254,112, 29,137, 7, 15, 30, 60,120,252,241, 16,192,235, 11, 30,188, + 7,128, 7, 15, 30, 60,120,240,224,193, 19, 0, 30, 60,120,240,224,193,227,207,142, 26, 46,157, 83,167, 78,249, 28,145,235, 46, +152,240, 65,151, 23, 54,200, 15,254,126,133, 16,137, 75, 96,181,218,150,133, 9, 4, 12, 24, 34,176,253,101, 8, 8, 97, 64,137, + 16,132, 16, 48, 48, 99,199, 46, 17, 40,165, 8, 97, 90,193,155,242,217, 51, 42,182,134, 45,128,167, 28,182, 4, 3, 38,118,201, +215,195, 88,127,188, 60, 94, 30, 47,143,151,199,203,123, 48,229,241, 30, 0, 15, 56,116,228, 50,116,165, 58,152, 76, 20,183,239, + 16,236, 77,246,199,190,253,129, 96,136, 8,251,213,237,177,239, 96, 7,236, 83,119,192,225,227,109, 32,132, 16, 12, 36, 24, 17, +197,192, 79,236,199,249,127, 76,125,117, 58,157,250,234,116,122, 36, 85, 93,101, 98, 72,234,185,179,153,135,212, 71,143,232,147, +147,147,171, 0, 52,231, 57,232,195,143, 49, 79,141,144,206,153, 51,157,122,187,201,211,195, 10,165, 82, 41,165,118,212,183,187, + 30, 87, 80, 23,240, 61,138, 7,143, 38,240, 0,176, 24, 54,124, 8,231,151,240,104,106,134, 71,214,210,216,242, 26, 19, 25,153, + 34,140, 27, 99,193,233,223,253, 33, 22, 9, 33, 20, 8, 33, 18, 81,248, 9, 76,128,176, 57,132,168,196,144, 62,102, 72,196,126, +160, 0, 58,180, 3,158, 29,111,197,129,237,220,148,255,229, 11, 89,120,244,177,238,232, 24,218, 18,249,215, 46,118, 9,106,223, + 13,173, 59, 90,240,235, 47,191, 32, 57, 57,185, 4, 77,188, 35,150, 92, 46, 31,175, 82,169,118, 57, 29, 63,227,124,204,163,110, +204,157, 35,167,230,170,115,178, 33, 17,193,106,171,181, 24,165, 29, 43,213,157,218,143, 70, 69,117, 7,124,181,254, 63,127,216, +157,206, 98, 99, 99,213, 11, 22, 44, 0, 33, 4,107,214,172, 81, 55, 70, 78, 0, 54, 29, 0,175,255,239, 63,188, 34, 93,148,130, + 48, 76,125,237, 77,157,219,147,109,211,187,201,183,106,182,179,243,206,136, 60, 26, 23,108, 54, 64, 39, 47, 1, 55, 2,208, 84, + 96,238,179, 46, 28, 63,214, 4, 10, 1,132, 2, 17,134, 69, 18,180,109,195, 64, 40,100,224, 39, 18,160, 87, 56,131,107,215,205, + 24, 18,193,160, 85,136, 4,191, 30,108, 1, 0, 16,208, 74, 80,106,133,167, 20,193, 83, 95,157, 78,127,207,204, 68,215,142,157, +240,123,218, 49,164, 27, 77,208,221,209, 65,236,215, 28,189, 7, 14, 71,255,225, 99,161,222,161,130,156, 99,110,252,123,160,248, + 71,169, 84,170, 3, 97, 97, 97,200,204,204,100, 59, 76, 9,128,121, 42,149,106,167, 92, 46,143, 81,169, 84, 7,254,104, 47,197, +236, 56, 57,245, 19,106, 33,100,140,168,170,178,160, 84,239,143,239,127, 56,224, 85,253,143, 30, 51, 92,218,194, 95,139, 81,195, +197,232,218,229, 89,117,139, 22, 65, 48,153,205,184,125,251, 14,218,229, 93, 71,118, 78, 46, 94,125,101, 60,221,248,221,110,159, +218, 53,194,190,167, 2,192,125,155,236,251,105,253, 3,119,183,195, 93,179,102, 13,148, 74,165,180,169,210, 1,223,199,247,133, +110,221,186,181,246,126, 10, 77,164,188,148,202, 68, 41, 1, 65,108, 35,212, 59,205,251, 9, 36,253, 53,103, 29,111,207,146,233, +216,247,202,129,215, 18,245, 30,137,220,175,191,254,234, 56, 30, 55,110, 28,246,236,217, 83,239, 49,143,123,175,252,157,207, 57, + 19,129,112,212,249,165, 0, 0, 32, 0, 73, 68, 65, 84,122, 9, 64,234,145,116, 12, 31, 17,121,223, 10,109,245, 46, 59,164,243, +205, 62,189,132,140, 80, 0,157, 86,136,246,109, 69,104,223, 86,140,138, 10, 17, 36, 34, 33, 44, 66, 63, 12,234, 71, 48,224,113, + 1, 24, 34, 2, 33, 4,126, 34, 49, 68, 76, 53,136, 68, 12,179, 1, 48, 67, 95,175,242, 63,114,240, 0,186,117,104,131,179,167, +207, 34,175,232,230,221,242,149, 87, 64,114,238, 56,101, 4, 4,131, 34, 6,225,215, 61,222,233,216,117,235,214, 73, 51, 51, 51, +213,151, 47, 95,134,191,191, 63,252,253,253,101,219,182,109,211,120, 57,152,201, 84, 42,213, 1, 86,241, 59,117,142,150, 0,198, +126,253,245,215,119, 94,123,237,181,100,185, 92, 62, 70,165, 82, 37, 63,136, 29, 60, 50, 50, 82,154,158,158,206,249,185,165,163, +134, 73,251,134, 55, 87,119,234, 80,132,160, 22,126, 96,152, 0, 84, 86,154, 81,172,173,196,203,242,222, 84,210, 98, 16,190,253, +230, 7, 78,253, 72,132, 66,188,240,204,227,234, 62,125,122,227,102,161, 14, 39,126, 59,137,138, 10, 61,130,130,154, 35, 44,172, + 11, 24,129, 8, 22, 75, 30,226,102, 79,167,137,235,190,255, 67, 89, 55,177,177,177,234,133, 11, 23, 58,142, 23, 44, 88,208,104, + 94,128, 7,217, 3,160, 82,169,136, 92, 46,167, 73, 73, 73,112,183,177,210,253, 54,218, 21,138, 56, 16, 66,176,126,189, 82, 22, + 27,219, 48, 18,192,116,121,209,161,188, 51, 86, 52,115, 59,152,182,111,201, 32, 52,132,121,104,219,239,207, 10,103,101,239,142, + 20,120,244, 0,164, 30, 73, 7,128, 6, 19,129, 35,243,178,235,189, 62,226,211, 30, 62, 15, 22, 78, 57,206,189, 26,132,146, 53, +109, 33, 18,138,208,185, 99, 5,202,203, 69, 56,113,182, 51, 4, 2, 1, 4, 68, 0,177,200,140, 62, 61, 12,232,217, 67, 0, 2, + 6, 98,145, 31,196, 2,130,136,199,141, 8, 9,182, 98,211,255,213, 47,187,119,183,118,184,150, 83, 84, 83,249,219,145,119,227, + 26, 33,140,144,118,136,122, 28,193, 45,155,163, 68,119,135, 83,121,215,174, 93, 43, 93,185,114,165,250,218,181,107,206,167,213, +227,199,143,199,238,221,220,173, 77,149, 74,117,208, 89,249,187, 65,235,132,132,132,146, 55,223,124,115, 63,154,120,138,162, 30, +229,175,246,166,108,225, 97, 33,234,208,118,101,104,221, 42, 16,157, 66,219, 35, 32, 48, 0,215,174, 21,192, 98,177, 34,180, 99, +115,156,187,144,134,168, 17, 67,164,105, 71, 50,234, 29, 76,223,120, 99, 58,125, 60, 92,135, 71, 30,233,132,243, 23,174,225,196, +137, 11,184,125,167, 28,148, 2,193,193,254, 48, 24, 42, 48,112, 96, 31,148,148,148,162,224,196,111, 24,254,100,164, 52,245, 48, +119,162,242, 32,131,181,254,237,219, 78,131,245, 4,172, 93,187,214,107, 47, 0, 59,221,239,154, 9,216,205,118,178, 13,238,127, +157, 58,117,162,157, 59,119,110,112, 46,126,149, 74, 69, 38, 79,158, 76,183,108,217, 2,118, 99,165,250, 20,158,125, 43,220, 90, +229,143,138,138,146,178,155, 3,213, 65, 98,169, 7,153,142,255,173, 80,196,169, 27,242,142,186,202, 27,178,164, 2,199, 87, 52, +171,161,248,121, 60,156,214,191,171,203,191, 65, 83, 0, 13, 37, 2, 35, 62,237, 81, 39, 9,240, 69,249,179, 72, 73, 73, 65, 65, + 65, 1, 0, 32, 52, 52,148,122,243, 50, 8,104, 37,132,196, 2,177, 72,132,223,206,182,129, 64, 40, 68,115,145,222, 22, 7,208, +140, 65, 65, 65,115, 60,222,199, 10, 66, 8,228,207,154, 65,173, 12, 64,252, 64, 64, 97, 11,228,119, 15, 67,201,117, 20,106, 43, +144, 85, 80, 80,103, 89, 74, 74,181,208,221, 46,180,203,226, 60, 0,185, 42,127, 0,192,238,221,187,241,212, 83, 79, 73,247,238, +221,235,113,128,147,203,229,163,114,115,115,221,118,152,210,210, 82,231,211, 45,151, 45, 91,134,243,231,207,143,126,144,166, 2, +156,148, 63,103, 72, 71, 13,147, 74,132, 55,225,239,223, 18, 18, 63, 49,186,117,235,138,206, 93,187,162,172, 76, 3,173,182, 2, + 98,177, 0, 33,193, 18, 8,253, 91,122, 28, 76,133,180, 0,205,155,181,130,161,210,140,179,103,179,113,163,176, 20, 55, 11, 43, + 80, 89, 45,193, 35,161,102, 72,252, 4,200,206,202,197,163,221,187,227,198,205, 50, 84,154, 91,112, 26,160,157,221,254,117,157, +247,118, 58,160, 46,153,190,200, 98,173,255, 5, 11, 22,212, 58,191,112,225, 66,159,188, 0,238,118, 39,116,157, 59,110, 44,175, + 66, 90, 90,154,186,161, 27,242, 76,158, 60,153,170, 84, 42,200,229,114,184,155, 14,224,226,169, 98,149, 63, 0,100,100,100,212, + 42,147,253,186, 71,163,135,221, 97,176,177, 60, 46, 91, 22, 6, 98,242, 26,189, 91,197, 31, 26,194,216, 71, 41,110,205, 59,110, +220,184, 26, 94,146,167,159,126,186, 70, 93,241,110,255, 7, 7, 94,199, 0, 52,150, 71,160, 49,145,157,109, 35, 22, 5, 5, 5, + 94,145, 0,161, 80, 8,145, 64, 4,145,136, 96,228,112,192,160,175,198,149, 28, 49, 68, 66, 17,132, 22, 33,134, 70, 82,136, 69, + 34, 8, 4, 12, 64, 9,180, 58,224,248, 73, 33,172, 86, 43,128,219,117,202, 61,249, 91, 14, 42, 42,234,206,192,217,173,125,123, +170, 55, 19, 84, 86,150,194, 98, 53,115,126,206,147, 39, 79,214, 77, 58, 12, 6, 78,138,198,213,245,239,142, 25,238,216,177,195, +249,254,228,166,240, 2,184,115,241, 59, 43,127,251, 0,200,205, 2, 12,109,167,102,152,235, 48, 91,172, 48,154,204,184,125, 71, + 11,145, 88,130,234,106, 19, 76,102, 11,204,102, 43,204, 22,202,201, 19, 35, 22,233, 33,241,239,132,226,226, 82,148,149, 27,160, +213, 85,162, 69,171,254, 24,246,248,227,200, 72,221,131,142, 70, 51, 74,203, 74,209,179,103,119,248,137,133,208,151,107,255, 16, + 3,133, 61,242,223, 49,247,239,226,153,242, 41, 22, 96,193,130, 5, 53,188, 9,174,215,184, 18, 0,173, 54,198,113, 99, 92, 92, + 8,182,108,217, 82,163,191,178, 6, 66, 94, 94,158,207,187,114,202,229,114,186,101,203, 22,199, 54,227,117,197, 4,184, 42, 87, + 87, 79, 85, 90, 90,154,154, 13,124,163,148,210, 99,199,142,213,184,126,236,216, 49,181, 39,167, 7, 75, 26, 88, 18,224,108,197, +215,101,232,123,120, 54, 76,138, 74,198,102, 0, 83,214,232,241,196,146,138, 6,145, 47,215, 57,126, 79, 49, 1, 60,238,189, 55, +160, 46, 15,192,125,245,239,184,179,244, 27, 98,253,187, 88,172,200,206,206,102, 7, 20, 78,189, 87, 32, 16, 98,232, 16, 43, 4, +140, 16,199, 51, 37,184,148, 45,193,132,167,128,103,158, 6, 38,142, 35,232,208, 78, 12,137,216, 15, 18,177, 31,252, 37,126, 8, +237,224, 7,137, 88, 2,137,135,101,128,249,121,215, 73,137,246, 22,169,107, 32,233,222,173, 11,130, 90, 6, 66, 98, 53,162,194, + 96,186,239,157,226,200,145, 35, 7,142, 28, 57, 82, 67,225, 59,127, 0,160,184,184, 24, 19, 39, 78,108, 50, 43,223,110, 29, 73, + 93,207,217,191,123,101,201, 89, 44,128,222, 96,130, 94,111, 68, 89, 89, 53,110,221,210,225,198,141, 59, 40, 47,175, 70, 69,133, + 9, 21, 21, 70,232,245, 38,148,150,148,122,148, 85, 93,109, 70, 85,149, 5, 38,147, 17,205,155,139,209, 57,180, 5, 2, 2, 3, + 1, 0, 97,221,187,162, 83,199, 22, 8,106, 33, 1,165, 22,152,204, 86, 84, 87,235,255, 16, 3, 73,108,108,172,122,209,162, 69, +245, 42,243,216,216, 88,206, 22,169,125, 75,225, 58,175,175, 89,179, 6, 95,125,245,149,215, 91, 13, 59,109, 59,235,248,176, 10, +181,160,160,128,221, 61,211, 43,237, 54,121,242,100,154,148,148, 4,103,242,160, 82,169,200,164, 73,147,234,253,221,236,217,179, + 65, 8, 1,219,143, 35, 35, 35,165, 0, 48,116,232, 80, 25,171,200, 89,171,159,189, 78, 41,117, 92,231,240,180, 53,172,120,119, +196,129,203, 12, 74,235,214,173, 65,156, 88, 66, 67,229,241,120,240,148,191,187, 99,159, 60, 0, 15,146,229,127,119,128,183, 64, + 32, 16,120,253,187,225, 67,172,104,219,198, 15,101,101, 66,248, 9,205,240, 19, 11,160, 73, 23, 99,130, 76, 4,177, 72,132,178, + 50, 17, 82, 51, 3,209, 66, 66,192, 48, 12,198,197, 24,241,220, 4, 10,134,161, 88,126,202,251,114,202,229,114, 42, 8,144, 64, + 43,106,141, 0, 83, 62, 46, 23, 80,140,146,142,228,188,165,239,192,129, 3,113,244,232, 81,183,215, 2, 2, 2, 56, 15,150, 58, +157,110, 52, 0,108,216,176, 1, 51,102,204,112,156, 47, 46, 46,118,124,159, 49, 99, 6,138,138,138,154,164, 61,211,211,211, 53, +132, 16,176,243,164, 12,195,128,117,119,214, 51,111, 90, 39,242,174,223,144,181,105, 97, 80,251,137, 5, 48,154,172,168,170,206, +199,245,252, 98,104,117,101,208,106, 13, 40,214, 86,162, 88, 91,137,150, 33, 93, 1,228,212, 43,235,214, 29,138,194, 91,119,208, +187,119,119,148,232,116, 16, 9, 25,148,149,231, 67, 95, 98,197, 99,143,234,209,174, 77, 27, 4, 4, 4,192,207,207, 31, 55, 11, +203, 65, 4,193,156,202,232,236,146,111,172, 85, 0,141,189,130,160, 46,107, 29,184, 27, 11,192, 21, 10,133, 66, 19, 27, 27,139, +249,243,231,215,242, 42,176,211, 12,190,174, 44,152, 60,121,114, 13, 11,150,125,191, 8, 33,120,241,197, 23,145,148,148, 68,184, +146, 0, 87,203,223,249,154,171,167,193, 21,235,214,173, 35, 0, 28, 86,126, 70, 70,134,218,222,175, 53,118,111, 0,251, 87, 13, +128,164,167,167, 59,174,215,183,157,107, 90, 90,154,122,248,240, 97,178,163, 71,109,239,196,236,217,179,113,234,212,111, 50, 86, +133, 31, 59,118, 76,205, 62,255,208,161, 67, 61,122,202,214,173, 91,135, 47,100,193,152,178,214, 96,123,174,133,129, 53,174, 79, + 89,107,112,212,231, 76,153, 8,223, 28, 52,130,199, 67, 64,218,227, 87,214, 36,221,171, 22,227,212,169, 83,220, 87, 1,220, 11, +197,239, 28, 11,208, 16,235,191,166, 37, 95, 83,249,219,221, 76, 30,167, 2, 90,183, 22,128, 33, 2,180,105, 45, 64,143,238, 20, + 55,110, 8,193, 8, 8, 68, 66, 33, 68, 66, 17,126, 63, 19,136,144, 64, 17, 4, 2, 1,134, 71, 90,224,239,239, 7,171,149, 2, +212,226,147,242,111,214,174, 51,110, 85, 80,232, 47,107, 32, 36, 2, 92,190,145, 71, 46,115, 84,254,246,129, 77,118,253,250,117, +245,245,235,215,221, 61,175,134, 99, 57,198, 20, 23, 23,239,103,149, 60, 0, 76,156, 56, 17, 27, 54,108,112,220, 83, 86, 86,134, +162,162, 34,236,220,185,147, 93, 46,120,223, 59,175,125,224, 82,103,100,100,168,217, 96, 49,251, 57,175,149, 66,234,225,116,141, + 76, 26, 1, 90, 80, 6, 67,165, 9, 58,191, 42, 80,232, 80, 85,101, 70, 89, 89, 53,138,238, 24,112,227,102, 5,158,148,117, 1, +144, 90,175,172, 74, 99,107,228, 94,185,141,176,110,143,160, 91,183, 78, 40, 46,190,131,224,150, 22,244,232, 17,132,182,109,194, + 32,241,247, 71, 73, 73, 5, 78,156,188,136,252,130, 50,180,239,212,231,161, 29, 64, 18,149, 74, 74, 8,100,172, 46,117, 86,170, +245,173,219, 79, 84, 42,165,137,235,214,113,242, 2,172, 93,187, 86,237, 74, 0, 86,175, 94,141,245,235,215,203, 60,201, 75, 76, + 76,164,113,113,113, 68,161, 8,118, 42, 19,117,167,152, 41, 0, 76,154, 52,137,147,251,223,121, 74,161, 85,171, 36,248, 58,109, +192, 90,249,118, 2, 64, 41,165, 24, 62,124,184, 44, 53, 53,181,206,235,158, 20, 54, 59,183,158,154,122, 84, 77, 8, 1, 33, 4, + 3, 6,244,151,173, 91,183, 78, 83,251,222,187, 36,195,147, 60,102,178, 14,172, 60,249,168,174, 53,248,209,228, 53,231, 29,242, +184,128,143, 1,120,120,224,145, 0, 60,136, 22, 63,139,169, 83,167, 54,232,247, 12,195, 64, 32,176,125,122,135, 51, 24,216,207, + 2, 63,177,196, 70, 0, 68, 34, 12,139, 4,252,252, 0,145,192, 15,173, 91, 75, 32, 16,232, 97,177, 88, 97,181,122,239,182, 55, +104, 11, 33,233,212, 11, 87,146,255,131, 54, 66, 6, 71,242,174,121, 61,160, 44, 88,176, 64,179,110,221, 58, 89, 67,150, 1,178, +203,250,222,120,227, 13,199, 57,214,210, 47, 43, 43,131,193, 96,192,204,153, 51, 1, 0, 95,126,249, 37, 0,168,155,162,109,211, +210,210, 52,118,107, 95, 13, 0, 67,134, 12,105, 80, 0, 87,167, 46, 61,145,121,108, 47,218,182, 14, 64, 64,128,173,219, 87, 87, + 91, 80, 86,110,132, 86, 87,137,206,221,250,224,251,141,155, 60,182,201, 47,191,236, 35, 47, 62, 63,148, 30,203, 56,135, 39,135, +247, 71,151, 46, 93, 96, 50, 86, 97,224,128,199, 17, 24, 20,132,107,185,121, 40,184, 81,130,212,180, 11,208,149, 7, 97,207,134, + 77, 15,173,207,116,118,156,194,222,254, 4,179, 21, 10,199,178,112,171,139,210,103, 24, 2, 80,135,202,160,179, 21, 10,244,119, + 99,193, 18, 2, 10, 39, 90, 30, 23, 23, 7, 87, 47,192,252,249,243, 65, 8, 65, 92,156, 66,109,215,231,152, 29,167, 64,255,254, +181,229,197,197,197, 57,220,241,158,148, 28, 87,229,239,138, 73,147, 38, 97,244,232,209, 50, 95, 73,176,243, 92,125,100,100,164, + 44, 53, 53, 85, 83,215,117, 46, 65,138,246, 85, 5,148, 37, 95, 81, 81, 81, 50,133, 34, 78,227, 74, 58,156,228,195, 27,121, 91, + 22, 54,179, 29, 74,218,221,245,116, 44,204,115, 16,130,189,167,235, 31,251,220,229, 1,224, 99, 0, 30, 82, 2, 48,108,248,144, +123, 50,231,211, 88,150,191,115, 71,242, 5, 90, 29, 65,135,118, 12, 8, 97, 64, 24, 6,251, 14,216,230,247,253,252, 36,240, 19, +251, 97,226,211, 4, 18, 63, 49,252, 37, 4,218, 98, 1, 50, 78, 52,135,197,106, 65,231, 78,222,205,235,202,229,114,122, 35,255, + 10,116,153,187,209,163,179, 8,103, 11,124,159, 23,158, 61,123,182, 6, 13, 12,202,147,203,229,178,207, 63,255, 92,205,186,249, +139,139,139,167, 68, 70, 70, 86,236,223,191,127,215,115,207, 61, 55,182,184,184,152, 76,159, 62,125,175, 61, 95, 64,147,117,206, +244,244,116, 77,100,100,164,140,253,222, 16, 89,223,111,220, 68,166,191,250, 50,205,186,120, 30, 55,114,175,129, 97, 8, 44, 22, + 10,137,127, 8,194,123,247,197,158, 95,147, 57,215,233,141,219, 86,153,182,248,134,186,170,202,140,126,125,195, 16,218,177, 53, +242,174,223,130,238, 76, 14, 46,101,229,225,192,193,223,113,173,128,226,120,230, 89,159,218,233, 65, 73,254, 99,221, 28,236,243, +125, 3, 63,230, 40, 47,231,255,176,118,237, 90, 7, 1, 88,187,118, 45,144,187,161,214,189,238,228,113, 5,165,148, 52,164, 31, +199,197,197, 53,168,239, 57, 41,121,141, 47,215,221,121, 21,156,127,235, 78,158, 87,237,124,109, 43,146,214,190, 98, 27, 27, 70, + 61, 82, 67,249, 3,128,124,252, 19,182, 47,186, 83, 30, 9, 0,159, 7,224,193,193,250, 85,139,107, 77, 3,120, 69, 0, 30,240, +128,143, 6, 23, 46,243,164, 31, 36, 98, 49, 38,142, 39, 96, 8,193,144,193,102,156, 57,235, 15,134,216,230,252, 75, 74, 24,116, +108, 47, 0, 67,196, 56,125, 70, 12,137, 31, 96, 52, 25,113, 45,207,223, 43,229,159,147,245, 27, 34, 71, 63, 3, 97,235, 72,228, +100,101, 64, 88,152,132,160, 22, 33,180,180, 76,219, 36, 21,172, 82,169, 52,114,185, 92, 54,120,240, 96,117,124,124, 60,250,246, +237, 91,164,211,233, 48,120,240, 96,153, 78,167,195,188,121,243,212,118,229,175,105,234, 70,110,168,226,119, 37, 1, 0, 16, 53, + 98,136,180, 67,251, 14,234,192,192, 64,124,191,113, 19, 57,123, 46,199,187, 1, 61, 53, 67, 3,128, 88,208,154,158,191,148,142, + 14,237,154, 65, 34, 17,161,162,194,136,130,155,101, 32,194,206, 56,158,153,202, 71, 75,113,193,201, 55,129,238,255,139, 26,203, + 11, 79, 44,106,210, 34,197,197,133, 56,165,173,109, 28,133,230, 73, 41,123,163,180, 27,154,207,192,221, 56, 47,143,242,179, 61, +107,229, 77,219,135,199, 67,139, 1, 3, 6, 56, 2,254,214,175, 90, 92,235,154, 71, 2,208,216,249,248,239,119,126,127,239, 88, + 4,129, 78, 71, 16,208,158,160, 85, 8,193,224, 65, 38, 72,196, 2,248,137, 77,104, 21, 34,177, 15, 2, 4, 67, 7, 91,144,113, + 82,100,243, 22,112, 36, 70,114,185,156,246,233,217, 2,111,206,255, 16,149,226, 78,248, 41,185, 0,221,195,135, 0, 0,154, 29, +223,137,172, 60,208,138,242,166, 35, 1, 0, 72,110,110,174,116,213,170, 85,106,103,239, 0, 0,210,148,150,255,189,134, 61,217, + 79,131,235,253,208,225,147,100,250,171, 47,211,219,197,183, 81, 89,104,128, 68,210, 10,157,186, 61,206,105, 42,225, 97,135, 45, + 29,118, 35, 61,102,238, 6, 56, 86, 4,228,110,108,242,103,243, 20,220,247, 71,195,216,103,166, 52,170,229,206,199, 0, 60, 88, + 36,160, 46,229,239,209, 3,240,103, 0,133, 45,170,159, 48, 20, 20, 20, 33, 45, 41, 82,142, 8, 33, 17,139,224, 39, 22,226,217, +241, 20,148, 90, 17,220,202, 12,179,133,192,106,181,216, 7, 63,207,120,188,107, 5, 38,188, 40, 71,133,176, 7,218, 54, 11,196, +203, 47,132, 96,211,182, 51, 14, 18, 96,178,252,132, 51, 23,155,118,157, 56, 75, 4,156,142,249,183,199, 7,175,194, 31, 17,100, +178,142,208, 45,193,181, 53,131, 42,196, 39,121,235,117, 43, 17, 27,188,184,246,133, 19,139,154,220,234,255, 51, 99,255,239,166, +198,236,195,196, 70, 16,169, 19, 89,228,167, 5,154,138, 4,120,108, 44, 95,247, 17,230,193,131, 7, 15, 30, 60,120, 60,188,224, + 19, 61,243,224,193,131, 7, 15, 30, 60, 1,224,193,131, 7, 15, 30, 60,120,240, 4,128, 7, 15, 30, 60,120,240,224,193, 19, 0, + 30, 60,120,240,224,193,131,199, 31, 3, 53, 86, 1,156, 58,117,202,231,104, 80,119,193,132,141, 45,111,218,204, 56,143,191,211, +107, 11, 29,223, 3, 67,218, 59,190,255,240,109, 98,173,123,219,200, 94,243, 40,111,255,154,187, 25,243,198, 44,252,220,241,253, +182,250,107,248, 82,190,186,224,107,249,234,130,187,242, 61, 63, 93,225,241,119,153,234, 93,232,218,181, 43,174, 94,189,138,193, +178, 9,142,243, 63,127,175,188,231,245,231,169,191, 36,132,134, 74,223, 44, 40,112,206, 76, 72,238,103,255,115,149, 55, 97,194, + 4,233,238,221,187,107,100, 74, 28, 63,126,188,108,215,174, 93,154,166,120, 63, 30,100,121, 13,145,245, 71,174,191,232,232,232, +151,250,245,235,183,233,204,153, 51, 47,166,164,164,252,212, 8,229,163, 15,202,251,193,203,107, 90,121, 94, 19, 0, 87,124,241, +197, 23,210,170,170, 42, 16,129, 8,132, 16, 88,204, 38,136, 69, 66,204,155, 55, 79,211, 80,230,241,197, 23, 95, 72, 1, 96,238, +220,185, 13,146,165,215, 22, 34, 48,164,189, 67,241,183,239,220, 21, 0, 80,120,253,170, 79,242,246,175,121, 3, 99, 22,126,238, + 80, 92, 95,108,207,248,127,246,174, 60,188,137,170,123,191,147,164, 89,186,175,148,125, 43, 84, 86, 41, 20, 17, 89, 19,217,132, + 2,202, 82,180, 84, 63, 17,161, 1, 17,101, 83,164,159,191, 15, 63, 23, 4, 69,138,178, 6, 68,224,131,178, 21, 68, 89, 10,133, + 66, 74,217,180, 82,160,236,148, 82, 74, 55,160,123,218,102, 79,102,126,127, 52, 19,211,144, 54,147, 52,172,206,251, 60,243, 36, +179,228,100,230,206,189,247, 61,231,220,115,207, 5, 0,204, 24,221,235,185,212, 0,207,201, 15,162,167, 36, 2,231,228, 7,107, + 72,109,124, 52, 0, 32, 39,231,201,151, 95, 40, 32,206, 4,228,161,128, 36, 19,144,207, 45, 40, 64,218,252, 79, 1, 0,189,150, +124,247, 68,203, 45, 42, 42,138,218,177, 99, 7, 52, 26, 77,173,227, 66,161, 80, 30, 21, 21,133,237,219,183, 63,173,211, 3,251, +189,208,166,217,102,202,104, 84,101,230,222, 95, 0,224, 0,107, 7,213,141,159,126,250,233,213, 11, 23, 46,120, 23, 22, 22, 54, +246,247,247,247, 13, 15, 15, 47,152, 55,111,222, 22,103,229, 13, 28, 56,112,208,196,137, 19, 79,108,219,182,109, 10, 0,159,183, +222,155, 54, 25, 0,121,249,242,229,127,201,100,178,223,164, 82, 41,233,160, 72, 58,185, 50,229,130,254,202,154, 68, 92, 85,135, +169, 71, 32,147,133,171, 61, 0,150,248,126,233, 15, 98,159, 22, 93,229, 3,187,118,128,187,192, 13, 20, 69,193,104,164,112,229, +214, 93,252, 16,247,163, 68, 36,112,195, 7, 31,124,224, 20,121,199,111, 94, 32,238,220, 62, 85,126, 37,179,173,196,217, 27,167, + 9, 95,228, 19, 0,101,217,125, 51,241,215,231, 17, 96, 98,169,246,138,254, 12, 71,227, 62, 52, 55,164,186,174,171,111,142,165, +245,127,242,249,252,154, 86, 64, 81, 32,201,154,246,109, 52, 26,205,247,207,225,186, 49,182,162, 1,160, 73,163,154, 84,157,186, +202, 10,104, 13, 6, 0, 64,181,161, 70, 94,155,161,239,163, 93,231,238,140,136, 31, 0,186,245, 25,132,115,242,131,102,226,175, +235,186,199, 89,126,116,167,145, 9, 96,152,135, 7,146,148, 74, 57, 77,252, 0,112,243,200,209,250, 58,173,122,241,221,214,111, +196,233, 37,127,161, 32, 55, 3,237, 91,245,198,198,143,183, 59, 92,135, 35, 34, 34, 94,223,185,115, 39, 77,254, 6, 0, 26, 0, +238, 0, 72,141, 70,195, 19,137, 68,136,136,136, 16,219,242, 4, 60, 97, 4,191, 20,214,245, 80,210,246,181,158,202,130,235,232, + 23, 57,125,219,221,114,253,191, 0,252,246,180,117, 76,145,145,145,148,179, 11,240, 88, 17,163, 83, 88,185,114,165, 56, 45, 45, + 77,190,121,243,223,137,137, 74, 74, 74,144,153,153,137,145, 35, 71,254, 79, 44, 22, 75,230,205,155,199,232,253,202,100, 50,206, +182,109,219,254, 11,224,149,126,195,222, 16,109,219,182, 45,248,173,247,166,121, 1, 48, 2,104, 98,186,236, 5, 0,156,129, 3, + 7, 14, 0, 30, 94,234,188, 46, 82,237, 21,253, 25,210,226, 23, 83,117,181, 55, 7,218, 7,149,122, 54, 13, 92, 46, 15, 70,163, + 1,138,170,106, 76, 28,247, 58, 85, 85, 85,213, 80,194,166, 92,249, 94, 88,216,135,173,101,127, 45, 60, 5,246, 21,128,101,203, + 87,136,197, 35,198,203, 91, 52,242,129,187,144, 7,146, 36, 97, 36, 1, 30,151,128,191, 79, 7,116,110,223, 82,158,156,116, 80, +178,122,245,106,177,163, 74,192,138, 21, 43,196, 29, 67, 78,203,187,117,184, 3, 46,199, 40, 95,177,114,165,100,230,135, 31, 58, + 36, 67, 89,118, 31, 34,159, 0,248,120,123, 1,128,249,211,214,117,141, 91,180,182,235, 13, 56, 26,247, 33,122, 69,127,134,119, +223, 28, 11, 0,230, 79, 91,215,173,218,151,230,144,118,205,229,114,209,188,121,115,112,185, 92,232,116, 58, 40,149, 74, 24,141, + 70,148,151,151, 59,245,114, 61,121, 92,252,178,124, 47, 4, 62,192,131, 28,224,175,234, 2, 20,223,207,194,150,184, 5, 14, 89, +253,221,250, 12, 66,243,166, 53, 67, 36,205,109,144,127,235,214,173,205,195, 1, 0,144,159,159,239,146,242, 99,152, 92,149, 26, +230,225,129,175, 62,156, 1, 0,248,202,130,248,183,102,102,214,238, 76, 28,200,214, 58,113, 65,127,113,121,175,100,249,103, 45, +223,134,150, 28, 12, 1, 73, 97,200,235, 70,108,252,126,151,228,232, 42, 48,237,204,121,211,166, 77,251, 77,173, 86, 99,211,166, + 77,154, 73,147, 38, 9, 1,120, 2, 32, 55,109,218,164,155, 52,105, 18, 79,173, 86, 67, 40, 20,202, 27,218,209, 13, 27, 54, 76, +124,228,200, 17,185,105,193,150, 6,195,147,207,249,207,138,175, 62, 21,249, 94,219, 14,209,205,227,248,226, 85, 63,175,143,246, + 23,127, 89,165,163,158, 42, 5,128, 94,130,183,188,124, 8,229,239,159,236,240,179,191,252,242,203,226, 63,255,252,211,105,178, + 89,182,108,153,120,247,238,221,242,170,170, 42,155,231,239,221,187,135,221,187,119,203,223,123,239, 61,201,198,141, 27, 83,236, +212, 23, 98,219,182,109, 91,250, 13,123, 99, 66,230,133, 51,188,230, 77, 27, 27,222,122,111, 90,173,126,247,248,193, 95,209,181, +107,215, 14,219,182,109, 27,222,181,107,215,125, 0,112,234,212,169,122,219, 7,147,246, 86,211, 62, 8,192, 78, 34,158,238,221, +187, 83,135,146,142,226,194,149,107,230, 99, 26,141, 22,223,173, 88, 87, 61,125, 82, 20, 75,216,207, 49, 30, 10, 2, 92,186,116, +169,184,223,208, 49,242, 14, 45, 3, 32,112,227,128, 36, 73,220,191,127, 31,151, 51, 46, 64,103, 32, 65,146, 20, 2,124,220, 49, +116,248, 72,185, 90,107,112,248, 15, 5,110, 69, 8,105,121, 31,224, 18,232,212, 62, 15, 2,222, 3,135, 45,127, 75,242,183,134, +162,178, 10,247,243,114, 32,242, 9,168,211, 43, 80, 31,121, 89, 99,243,206, 95, 49, 99,116, 47,244,138,254, 12,245,104,217, 15, +129,207,231,131,203,229,194,219,219, 27,217,217,217, 40, 47, 47,175, 81,164,156, 36,255, 38,141,130,225,201,227, 98,204,204,175, + 49,124, 98, 31, 28,184, 82,128,251,106, 52,152,252,173,145, 95,120, 31, 87,207,157, 70,144,159,119, 13,249,243,184, 46, 41,191, +215,198,189, 11, 0,240,227,185, 57, 68,254, 0,240,127, 43, 87,225,255, 86,174, 50,147,127,146, 82,137, 79,134,142,172, 57, 25, +196,103,244,220,125, 98,219,136,167,206,125, 69,254, 94,171, 15,224,198,241,132, 7,220,193, 1, 23,205,130,251,226,195,175,230, +200,231,239,239,192, 72,141, 72, 73, 73,209, 3,192,230,205,155, 85, 0,132,244, 50,202,155, 54,109, 34, 1,184, 91, 46,171, 28, + 21, 21,229,212,184, 92, 92, 92,156,216,145,227, 12,208,175,103,247,110,170,132, 95,247, 74,187,119, 9,229, 42,175, 29, 67, 78, + 81, 21,238, 85,168, 64, 82,148, 83,129,192, 20, 69, 81,101,101,131,169, 1, 3, 6,184, 52,145,152, 5,249,195,223, 63,217, 41, + 25,105,105,105,114, 0, 4, 65, 16,120,249,229,151, 29, 46,179,228,228,228,135,200,255,220,185,115,152, 56,113,162,121, 95,175, +215,227,198,141, 27,242,184,184,184,122,189,152,219,182,109,251,176,223,176, 55, 70,126, 19, 59,155,151,144,144,128,159, 87, 44, +229,153, 60, 70,102,242, 79, 72, 72,192,202,149, 43,209,181,107,215,125,246,218,155, 53,249,215,213,222,134,247, 53,121, 1,189, + 60,236,202,251, 97,197, 26, 51,249, 23,149,148,162,168,164, 20,138,170,106,184,185,241, 60,215,108,218,174,129,171, 22, 68, 96, +241, 88, 17, 22, 22,246,208, 86,175, 2,176,122,245,106, 42,160,245,139,104,221,216, 23, 26,189, 17, 4, 1, 36, 37, 29,198,255, + 54,111,194,165,140, 12,124, 50,103, 22,184, 92, 14, 72, 35, 9,111,119, 1, 90,191,216, 79,190,124,249,114,198, 13,108,229,202, +149,226,206,237,239,202,189, 61, 85,248,101,115, 17, 56, 4,133, 94, 93,111,202, 87,174, 92,233, 80, 35,181, 69,254, 52,241,171, + 21,165,181, 20, 4, 69,101,149, 93,121,182, 26, 19,221,144,210,226, 23,215, 34,184,205, 59,127,101,116,143, 33, 33, 33, 8, 8, + 8, 64,101,101, 37,248,124, 62, 56, 28, 14,212,106, 53,202,203,203,193,229,214, 52,114, 71, 22, 91,218,243,219, 94,204, 90,126, + 4,123, 87,124,142, 38,141,130,225,238,225,143, 60, 99, 1,182,196, 45,128,167,169,211,224, 50,148,103,139,252,105,226, 87, 20, +222, 70,135,230,141, 80,165,210, 64,224, 46, 0,140, 70,187,241, 0,246,202,111,193,250, 3,184,122,254, 44,186,180,237, 4,133, +209,190,210, 72,147,255,205, 35, 71,241,127, 43, 87,153,143, 39, 41,149, 72, 82, 42,145, 45,253, 47,142, 92,187,132,206,189,218, + 2,165,246,151,102, 30, 56,175,173,120,250, 71,131,228, 65, 30, 29,161,166,170, 0,109, 17,248,218, 50,104,141, 85,208,144,106, +144,124, 79, 52,235,223, 19, 67,166,183,162,236, 89,115,244,184,191, 84, 42,117,151, 74,165, 64,205, 16, 0,164, 82, 41, 76,251, + 38, 11, 74,131, 29, 59,118, 56,220,104,103,207,158, 45,158, 51,103,142,188, 83,167, 78, 20, 65, 16,114, 0,120,251,237,183,169, + 86,173, 90, 81,159,127,254,185, 83, 75, 51,123, 9, 56,155, 86,125,246,158,104, 88, 51, 45,247,204,141,251, 56,144,195,193,103, +135, 30,104,255,155, 82,173, 80,234,241,174, 51, 50,203,203,135, 60, 74,203, 31,254,254,201,136,142,142,118,120,136,208,146,240, + 41,138, 34,232,229,164,153,226,221,119,223, 21, 63,120,192,204, 40,209,233,116,184,124,249,242,241,250,234, 11, 0,113,243,166, +141,249,145,145,145, 0,128,244,244,116, 28, 63,248,171, 48,191,240, 62, 73,147,191,233,217,205,237,237,242,229,203,113, 13,105, +111,223, 77, 26,137, 43,183,243,208,184,109, 19, 64,169, 98,252,236, 69, 37,165,208,235, 13, 38, 5,199, 0,189,222,128,188,187, + 57,194, 6,190, 86,194,206, 62,139, 39,136, 90,174, 40,173, 86,139,238, 29, 58,200,221, 69,110, 32, 73, 10, 70, 18, 56,125,242, + 20,254,251,213,215, 32, 41,224, 86, 86, 22, 46,101, 92, 68,151, 46,221,192,229, 18,120,161,109,115,100,159,103,238, 5,224,243, +138, 16,218,186, 16,224, 17,200,187,167, 7,120, 4, 94,236,112, 23,105,151,139,156,126, 0, 75,247,190, 45,207,128, 90, 81, 90, +107, 54,128, 61, 88,186,247,109,105,218,105,241,139, 49,100,246, 74,155, 81,236,150, 48, 24, 12,112,119,119, 7,135,195,129,159, +159, 31, 84, 42, 21,148,202,154,101,128,131,130,130, 80, 90, 90,234, 80,142,108, 77, 57,208, 75, 36,194, 39, 43, 78, 98, 72, 55, +224,238, 5,224, 47,211,185, 79, 86,156,196, 79,179, 37, 48,146, 70,135,203,239,234,185,211,230,239,131,194, 59,128,231,197, 65, + 82,202, 53,116,239,208, 2,222,158, 2,108,222,157,140,158,146, 8,228,219,152, 5, 96,175,252,246, 93,163,128,123,192,232, 65, + 4,214, 31,200, 70,128, 95, 27,140,237, 75, 48, 42, 63,218,221,159,164,252,123,233,100,234,139, 56,160,153, 2,196,212,133,160, +254,251, 21,192, 81,131, 72, 91, 68,119, 42,117, 22,102,200, 56, 79,121, 43,223,112, 84, 26,171,161, 45,207,194,150,220,109, 56, + 53,186, 28,157,166, 72, 48,116,166, 39, 68,126, 47, 64,200,243, 3,111,180, 2, 83, 12, 83,168,159,215,255,108,179,147,146, 74, +165, 20,173,180,113, 56, 28, 80, 20,165, 51, 41,209, 26, 14,135,163,162, 40,202, 31, 0,137, 6, 76,175,141,139,139, 75, 25, 54, +108,152,164,180,180, 84,158,148,148, 84,163,248, 36, 37,161, 99,199,142,232,208,161,131,132, 62,230, 8,170,180,228, 71,147,255, +239,167,253,223, 71, 52,230, 80, 26, 5,166,198,103,234, 13,122,253, 74,173, 17,139, 0, 56,181, 24,197, 27,111,232, 30, 57,249, +199,199,199,167, 56, 99,253, 91, 14,153, 16, 4,129, 94,189,122,137,153,174, 42,105, 52, 26, 29, 82, 24,238,220,185, 3,153, 76, + 70,172, 89,179,198,214,105, 33,128, 78, 0,120,175, 70,140,173,200,206,206,246, 77, 79, 79, 71, 66, 66, 2,194,179,179, 57,233, +233,233, 0,128,240,240,112,188, 54,176, 39,188, 61, 5, 88,185,113,111,209,196,137, 19, 99,215,172, 89, 51,219,209,246,118,239, +183,197,240,234, 44,132,103,251, 89,216,181,120, 10,186,117,105,140, 23, 70,126,109,183,125, 40, 42,171, 32, 20, 10, 0, 0,110, +110, 60,168, 84, 26, 87,243, 12, 75,250, 79, 0, 76, 22, 3,170,213, 81,145, 36, 9,119, 1, 31, 58, 3, 5,146, 2, 56, 4,176, +240,203,175, 97, 36,129,234,234,106,220,191,127, 15,193,193,141, 65, 81, 36, 12, 6, 35,132,110, 60,112,221,152,185, 96, 87,173, + 90, 37,110,223, 58, 95, 30,232, 87, 89, 83, 29, 76, 27, 65, 80,232,209,249,150,156,158, 21,224, 8,104,235,158,118,247, 91,147, + 63, 19,235,223, 90,139,166,137,127,213,190,180,135,200,159,169,245, 15,212, 4, 12, 9, 4, 2,248,248,248,152, 93,134,116,224, +159,143,143, 15, 26, 55,110, 12,131,129,185,242,180, 49,249, 4,124, 90, 3,226,208,154,253, 76, 67,141,251, 31,168, 57,246,249, +215,114, 84,232, 28, 27,146,201, 47,172, 9, 86,108,217,200, 31, 94, 62, 30,224,121,115,161, 41, 81, 3, 28, 14,154,180,106,142, +211, 25, 57, 78,149,223,187,115,191,193,128,222,175,130,119, 31,168, 14, 6,220, 57, 28,244,110,221, 6,210,209,193,140,228, 88, +143,245,111,125,115, 10,198,188,209, 31,104,167, 1, 46,241, 0, 79, 30, 48, 42, 28,205,215,174,103,230,141,105,230, 15,157,174, + 12,132,182, 20, 91,114,183,225,236, 36, 31, 12, 24, 51, 9,253, 26,189, 38,185,114,196, 0, 3,169,132,155, 78, 9, 67, 7, 18, +197, 15,152, 5,141,154,148, 55,205,164, 73,147, 56, 0,202, 41,211, 10, 81,166,253, 6, 33, 41, 41, 41,165, 99,199,142, 18,119, +119,119, 4, 6, 6,194,221,221, 29,169,169,169, 68, 82, 82, 82,138, 19,226, 26,143, 28, 57,114,253,170,117,191,112, 22,166, 84, +147,187,207,100, 65,171,211, 43, 53, 70,204,115,132,252,173, 93,254,169,169,169, 4,189, 61, 45,228,111,203,221,239,168, 23,160, +186,186,218,252,253,220,185,115,230, 13, 0,230,204,153, 83,107,223,226,122, 65, 29,226,154, 2,104,109, 82, 10,221, 95, 27,247, +182,198,210, 19, 64, 91,254,175,244,237,107,217,222, 14, 72,165, 82,141, 35,237, 45,102,212, 0,188, 24,222, 1, 94,221,188, 80, +112, 44, 23, 16, 10, 48,110,230,191,208,235,157,159, 24, 61,179,193, 96, 68,193,189, 7, 6,218,242,167,145,119, 55,167,161,175, +150,170, 99, 99,241, 20, 40, 4,176,101,169, 80,166,206,141,164, 0, 35, 89,163, 4, 16, 4,240,235,158,221, 24, 51,118, 60, 2, +131, 26,153, 59, 64,202,129,119,201,229, 20,161,115,187, 60,243,254,139, 93,220,205,186, 97,143, 78,217,224,114, 28,247, 2, 88, +187,251,109,157,119,196,250,183,118,247,219, 58,111, 57,151,189, 62, 84, 86, 86,162,170,170, 10, 90,173, 22, 36, 73,162,184,184, +216,236,254, 87,169, 84,168,174,174,118,104, 8, 96,239,138,207,145,114, 5, 80,228, 0,122, 53,240,211,124,137,217,253,127,254, + 2,112,241,222,105,112, 29, 44, 63, 69,225,109,248,251,120, 32,192,223, 3, 47,132,118, 68,246,157, 98,100, 22,148,162,101,128, + 15,180, 15,138,144,117, 43,171, 86, 46, 0, 38,229,215, 71,252, 58,250, 73,162,176,119,255, 46,200, 83,119, 97,219,178,185, 24, + 55,119, 17, 46,233,129,226,210, 34, 70,229,103, 57,214,255, 94,159,151, 17,221,169, 21,118,237, 61,142, 75,151,114,176,236,114, + 58,118, 12,249, 23,176,225, 12, 10, 10,138, 25, 89, 23,205, 53, 2, 24,117, 37,208,233,106, 34,171,131,155,181, 64,135,142, 29, + 37,149,162,154, 88, 12, 53,169, 2, 71,171,132, 72,201,197,131,123,245, 43, 0,244, 59,211,104, 52,208,104, 52, 66, 0, 58, 0, + 94, 26,141,198,219,122, 74, 96, 3,188, 0,226,212,212, 84,121,199,142, 29,241,246,219,111, 75, 74, 74, 74, 48,118,236, 88, 71, + 58,206,126,124, 62,191,218,211,211,211, 48,100,200,144,123,243,231,207,111, 26, 27, 27,155,253,215,133, 75, 35,118, 92,213,222, +208,147,112,120, 61,214, 71,225,242,119, 37,249, 91, 91,255,180,194, 66,191, 51,166,177, 0,110,110,127,199,168, 44, 91,182,204, +188,217,218, 7,204, 51,124,234,122, 55,124,211,198, 1,192, 83, 20,222,182,233, 78,167,219,219,133,243, 23,238, 76,156, 56, 49, +198,145,246,214,255,165, 23, 48,184,111, 40,190,249,114, 41,126, 88,158,136,255,108, 61,142,105,175,246,196,253,223, 19,161, 40, +175,100,210, 62,136,200,209,175, 65,175, 55, 92,208,235, 13, 6, 75, 5, 0, 0, 22, 45, 92,208, 16, 11,158,181,252,159, 32,108, +141,253, 91, 43, 1,181, 20, 0, 14,135, 3, 69,181, 10, 92, 14, 1,131,193, 8,146,162, 96, 32,107,130, 72, 51, 46, 94,192,171, +131,134,213,184,201, 40, 10, 92, 14, 23, 85, 42, 29, 12, 58,173,125,235,127,245,106,113,155,102,247,228, 65,254, 10,179,150,209, +167,151,167, 41, 70,151, 0, 65, 80,232,222, 49, 75,190,106,245,106,198, 94, 0,218,186,175, 47, 24,208, 41,235,181,158,224, 26, + 71,224,231,231,135,226,226, 98, 8, 4, 2, 84, 85, 85, 33, 40, 40,200, 28, 20,168,209,104, 80, 81, 81,225,144, 2, 16,243,205, + 14,252, 52, 95, 2,159,214, 64,202, 21,224,163, 37,114,120,242,184, 24,251,241,183,200, 39,239, 35,126,217,167,224,114,152,203, +163,173,255,240,240, 80, 4,181,109,141, 70, 65,129,224,115, 8, 24, 8, 10,197, 74, 53,202,171, 52, 78,149,223, 15,139,127,195, + 27, 29,219,192,219, 59, 0,238, 65, 77,161, 47, 43,199,133, 3,219, 81, 81,150,235, 84, 37,254,101,241,135,192,236,193,224, 25, +116,104,173, 4,138,184,149,248,233,222, 95, 0,223,155,177,140,243,251,255,144,148,112,212,200,229,171,208,179,157, 4,157,254, +229,137,108,191, 20,121, 80,208, 5,121,139,222,217, 80,112,170,160,165,212, 80,109, 37, 33,244,244, 98, 98,249, 91,118,240,244, + 44, 0,190,171, 26,238,225,195,135, 1, 0,209,209,209,146,184,184,184,148, 49, 99,198,152, 45, 70, 38,228, 31, 20, 20,116,104, +253,250,245, 30, 50,153,140, 59,123,246,108,204,154, 53,139, 58,115,230, 76,111, 0, 73,106, 3, 58, 2,248,211,209,123,146, 74, +253,234,116,251, 59, 27, 16,232, 74,242,183, 38,120, 75,133,133,162, 40,194, 20, 24,104,191, 93,228,231,159,161,191,111,219,182, +205,188, 89, 31,163,225,239,239, 15,169, 84, 90, 87, 39,152, 15,160, 2, 0, 39,191,240, 62,206,158, 61,107, 30,243, 15, 15, 15, + 7, 80,179,252,246,206,125,137, 40,175,210,168, 0, 44,156, 15, 74, 29, 0, 0, 32, 0, 73, 68, 65, 84,146, 74,165, 70, 71,218, +219,239,123,191,192,176,249, 51, 49, 98,196, 32, 4, 10,184,168, 34, 40, 36,101,230,225,236,149, 2,135,136,122,250,164,168,151, +178,179,178,120,121,119,115, 64,111, 38,242, 7,107,181, 63,155,196,111,125,204, 22,106,197, 0, 8, 4, 2,220,186,118, 73,210, +186,169,191, 92,228,198,131,209, 72,130, 32, 8, 16, 4, 16, 35,157, 1,138, 34, 97, 52,229, 3, 80,105, 52,184,158,153, 13, 62, +223,110, 84, 55, 12,250, 50,116,239,116,199,178,199,192, 7,179,239, 96,207,214,246,230,170,213,179,203,109,252,145,209,209, 97, +235,223, 22,241,171, 21,165, 0,224,148,245,111,171,161,165,197, 47, 6, 0,198,214, 63, 80, 51,207,191,113,227,198,208,106,181, +120,240,224, 1,140, 70, 35, 2, 3, 3, 81, 90, 90,138,192,192, 64, 83,185, 50, 39,236,226,251, 89,248,252,107, 57, 20, 57,192, +247,115,251,163,218, 96,196,156, 37, 9,248,113,126, 36,230, 46, 59, 0, 30, 65,192, 1,254,135,162,240, 54,154, 4,250,194, 13, +110, 48,130,192,189, 59, 87,113,183, 72,129,144, 32,127,252,126,254, 12,174, 95,131,195,214,255,184,201,115,224,230, 15,112,184, +192,166,196, 59,216,179,250, 19, 76, 94, 44,195,156, 81,221, 48, 99, 80, 43,135,202, 47, 73,169,196, 15,163, 39, 0, 21, 66,128, +112, 3,126, 88,138,241,127,157,196,145, 65,211, 65,124, 59, 19,196, 31,159, 50,182, 48, 46,222, 11,192,203,106, 5,170, 69, 92, +168,132, 66,132,140,115,131,150, 82, 67,193,113,131, 1,161,160,140, 42,232, 75,238,225,244, 10, 5,162, 39,134, 32, 69, 46,127, +236,141, 54, 38, 38,134, 2,128,117,235,214,209,174,126, 98,246,236,154, 97,224,173, 91,183, 50,125,179,125,155, 54,109,122,248, +219,111,191,245,184,117,235, 22,220,220,220,224,237,237,141, 75,151, 46,233, 1, 20, 55,228,254,234,155,147,239,140,119,192,149, +228,111,109,253,215, 16,243,195,211, 7, 77,211, 3, 83,236,220,215,173,157, 59,119,246, 97, 58, 60, 39, 20, 10, 39,215,173, 52, + 73,171, 6, 14, 28,120, 7, 64,120,230,133, 51,176, 28,243,255, 96,242, 4, 28,110,219, 22, 9, 9, 9, 72, 79, 79,199,161,182, +109,221, 39, 78,156,184,241,196,137, 19,140,219,219,155,131, 95,134, 15,233, 7, 21,220,176, 39,110, 38, 86, 31,184,136, 79, 94, +235,135, 73,203,182, 97,252,162, 45,142, 90,224,196,162,133, 11,108, 37, 2,162, 44,148, 0,214,162,127,206, 80,203, 3,240,193, + 7, 31, 16, 21,247,178,112, 59,175, 20, 60, 55, 46, 12, 70, 18,122,131, 17,231,207,167,227,127,255,219, 8,157,145,130,222, 72, +130,207,227,160,168,188, 26, 5,215,207, 74,102,205,154, 85,111,131, 90,189,122,181,184, 99,200,221,191,173,127, 83,189,218,179, + 53,180,166, 62,113, 40,128, 67,129,195, 33,209,187,219,117,249,106, 6, 94, 0, 91,214,191,229, 44, 0, 15,255,198, 14,145,191, + 45,235,223, 50,170,118,200,236,149, 14,145, 87, 77,167, 88,142,234,234,106,184,185,185,153,173,127,146, 36,205,159,142, 42, 0, + 91,226, 22,224,124,193, 9,120, 54,174, 9,250,243,226,113, 81,124, 63, 11,222, 2, 55, 84,148,229,131,203, 33,192,227, 48, 27, +126,166,173,255, 22,254, 94,184,150,125, 7, 6,157, 14, 2, 30, 31,213,213, 26,252, 46, 63,131,158,146, 8,135,200,159, 46,191, +215, 63,252, 10,241, 63,253, 8, 21, 9,180, 8,105,142, 43, 87,255,192,156, 81,221,156, 42, 63, 0,152, 19,210, 19,251,111, 29, + 7, 20, 6, 64, 24,136,163,105,215, 64,124, 59,147,238,152, 24, 23,222,137,165,217, 41,167,143,166, 1,186, 42, 84, 19, 85, 40, +231, 84, 67,193,211, 67,111,172,132, 64,163,130,176,240, 14,118,196,222, 66,235,176, 80,212, 21, 0,104, 13,145, 72,100, 73, 2, + 16, 10,133, 54,207, 49,197,250,245,235,177,126,253,250, 6, 53,102, 47, 47,175,143,178,178,178, 60,188,189,189, 33, 18,137,224, +239,239,143,226,226, 98, 16, 4,161,114,101,167, 65, 91,252,145,145,145, 20, 80, 19, 16,232, 72, 80,160,171,201,255,229,151, 95, + 22,219, 11,168,101, 26, 11,224,225,225, 17,195,227,241,110, 91, 31, 95,182,108, 89, 45,203, 31, 0, 90,181,106,133,193,131, 7, +111,178,103,255,228, 23,222,175, 21,237,255,249,255,205,134,128,199, 71,112,112, 48,232,152, 0,211,121, 15, 71,218,219, 20,241, +139,152,181,244, 71, 84, 61, 40, 66,144,119, 35, 92,189,150,139, 73,203,182, 57,220, 62,172, 8,159,176,250,189,165, 28,214, 19, +240, 12,224,226,197,139,245, 38, 3,170,211, 3, 0, 0,243,230,205, 75,249,126, 41, 33,161,168,209,242,214, 77, 3,224,229, 46, + 64,167, 46, 97,232,212,185, 27,120, 28,160, 90,109, 68,238,189, 50,164,165, 28,148,120,122,184,219,253, 3,165, 74,133,208, 86, +247,160,209, 10, 77, 89, 91,106,170,145, 72,168, 1, 69, 1,101, 21, 2,128, 0,188, 60, 12,232, 26,154,131,147,231,236,103,177, +179,180,254, 45, 45,126,145, 79, 0,220, 40, 61, 96,248,187,191, 51,242,236,223,163,165,245,111,105,241,211,199,178,174, 94, 48, + 95,203, 36,203,158,165, 18, 0, 0,141, 27,215, 40, 35,101,101,101,240,246,246, 54,187,255, 29, 81, 0,104, 37, 0,248, 22,211, + 35, 7, 2, 63,157,196,234,127, 71, 96,252,220, 31,177,109,241, 12,240, 8, 2,124, 1,179, 25, 59,180,245,127, 45,183, 8,237, + 90, 4, 98,195,207, 59,208,186,117,107,248, 52, 13, 65,183,166, 33,208,107,255,118,255,187, 49,144, 73, 91,255, 95, 79, 30,132, +143, 22,110, 66,139,182, 68,131,202,143,182,254,135,238,253, 5, 71,162,163, 64, 52,239, 13,160, 38, 43, 32, 0,220, 81, 42,205, + 74, 98, 38,152, 37,240, 89, 53,233, 54, 49,112, 30, 37, 14, 25, 91, 37,111,221,190, 11, 42, 69,192, 29,220, 69, 85, 78, 49,138, + 23, 25, 81, 93,222, 28, 55, 78,103, 50,126, 33, 36, 73, 18, 34,145,136, 82,171,213,176,176, 60, 41,145, 72, 4,146, 36,137, 39, +209, 89, 86, 85, 85,125, 63, 99,198,140,209,235,215,175, 23,250,248,248, 64, 46,151, 99,249,242,229,149, 58,157,238, 53, 87,254, + 15,109,241,211,211,229, 28, 13, 4, 76, 72, 72, 32, 76, 73,126, 26, 76,254, 0, 96, 65,236,118,203,220, 94,134, 65,169, 84,170, +147,201,100,189,119,237,218,117, 73,169, 84, 54,209,235,107,166,153, 90,147,127,167, 78,157,208,187,119,239,145, 82,169,212,222, +127,242, 20,133,183,241,205, 23,159,227,215,253,135, 48,172, 95, 15, 28, 75,254,163,198,128,105, 26, 2,159,166, 33, 8,207,206, +198,107,227,222, 46,201, 45, 85, 13, 5,176,155,169,245, 63,107,221,126,196,190, 63, 20, 77, 27,139,205,202,133,117, 57, 52, 48, +155, 34,235, 9,120,142,148, 2, 70, 10, 0, 0,124, 50,111,110,202,247,223,147,146, 59,205, 95, 64,219,246, 29,229,222, 30, 34, +144, 20,160,214,234,144,157,157,141,226,236,139, 18, 47, 79, 15, 76,159, 62,221,110,195, 21, 9,133,216,117,120,160,132,142,128, +175,215, 29,193,225,192,195,131,185,245, 68, 79, 1,244,240,111, 12,210,168,175, 33,127, 19,244,132,155,221, 20,187,214,160,167, +212, 12,153,189,178, 22,105, 57, 67,254,150, 74,128,101,226,159,178,178, 50,251, 47,192,142, 18,176,197, 98,150,240,250, 69, 31, +252,189,163,175,134, 39, 67, 57, 45,252,189,176,235,220, 69, 92,185,113, 19, 61, 37, 17,181, 72,223, 17,242,167,241,250,135, 95, + 97, 79, 15, 15,124, 56,166,131, 75,202,111, 78, 72, 79,204,221,183, 11,196, 55, 11,113, 40,248,101, 44,175,190, 82,235,252, 88, + 31, 95, 44, 86, 84, 56, 68, 28, 39,150,102,167,248,241,134, 32,191,252, 54,138, 75,239,225, 65,166, 39,184, 70,111,244,125,177, + 63,118,156,222,241, 68, 59, 53, 23,101,251, 59,183,113,227,198, 33, 4, 65, 28,253,241,199, 31,133,111,188,241, 70,165, 74,165, + 26, 10, 39,198,252,235,131, 43,166, 0, 74,165,126, 46, 33,127, 27, 86,170, 61,229,131,193,189, 73, 75,100, 50, 89, 72, 85, 85, +213, 55,233,233,233,179, 11, 10, 10,160, 84, 42,193,231,243,209,164, 73, 19, 4, 5, 5,189, 33,147,201,126,223,178,133,209,146, + 0,215, 1,132,183,240,247,194, 43,175,188,130,139,183, 10, 16,216,166,115,173,246,246,218,184,183, 85, 0, 86,124, 19, 59,123, + 55,211,231,152, 34,126, 17, 67,146,255, 68,244,194,255, 97,192,128, 1, 8, 14, 14,182,169,104,185,240,181, 19, 78,144, 63, 85, +207,113, 86,137,120, 2,164,207, 40, 21, 48, 0,124,242,201, 39, 41,171, 86,173, 18,159, 79,201,148, 0, 53,145,180, 20, 69, 65, + 32, 16,224,211, 79,230, 49,110,180, 31, 58,152,230,151, 41,104, 87, 63,215,160, 2, 12, 42,115, 4, 60, 77,252,142,206,197,162, + 93,253, 89, 87, 47, 32,235,234, 5, 4, 5, 5,161,184,184,216, 41,226,247, 9,106, 10, 29,131,224, 72,166,136,254,106, 11,206, +156,116, 93, 49,230,228,228,152, 87,251,211,107, 53, 15,145,191, 35,196, 79,227, 95, 61, 60, 92, 86,126, 0, 64,196,125,106, 38, +126,154,252,239, 40,149,146,177, 62,190, 72, 2, 82, 22, 43, 42,156,122,246,223, 22, 31,181,232,120,212, 0,128, 29, 87,153, 39, +236,161, 40,138, 16, 8, 4,102, 47, 0,253, 29, 0, 4, 2, 1, 97,235,251, 99,198,169, 95,126,249,101,192,238,221,187,231, 84, + 86, 86,198, 1, 72,115,245, 31,184, 98,234,159,139,201,201,229,144, 74,165,106, 0,115, 76, 91,131,222,199,229,203,151,251, 2, +104, 19,216,166,179, 74,175,213,184,155,218, 91, 37, 0, 5,128,235, 45, 3,220,223,148, 74,165, 14, 85,232, 33,159,175,127, 92, +196,239,148,162,229,228,245, 44, 92,128,176,176, 48, 70,228,111,215, 0,109,232, 74,125,143, 2,244,216, 62, 77,252,104, 32,241, +211, 99,211,138,162,124, 40,138,242, 17, 20, 20,212, 32,139, 31, 0, 12, 70,210, 97,239, 67,125, 40, 42, 83, 56,125, 47,214,160, +199,246, 93, 69,252,143,160,252, 8, 0, 24,230,225, 65, 89, 90,253,221,121,110, 13, 34,254,127, 24,254,170,172,172,140, 98,139, +225,201,227,196,137, 19, 50,153, 76,246,191,220, 82,149, 74,175,213, 88,142, 71,122,183, 12,112,247,115, 98,245, 63, 2,168, 25, +202,120,214,148, 42, 22,143, 87, 9, 96, 84,153,156, 93, 71,152, 5, 11, 22, 44, 88,176, 96,241,236,130,195, 22, 1, 11, 22, 44, + 88,176, 96,193, 42, 0, 44, 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88,176, 10, 0, 11, 22, 44, 88,176, + 96,193,226,185, 64,173, 89, 0, 23, 47, 94,116, 58,138,212, 86, 48, 33, 43,143,149,231, 42,121,166,181,213, 57, 0, 72, 91,201, + 87,216,242,171, 91, 94, 88, 88, 24, 93,118,244, 92,110,234,226,197,139, 36, 91,126,172,188,103, 73, 94,120,120, 56, 47, 61, 61, +221, 0, 0,189,122,245,162,218,183,111,143,248,248,120,130, 45, 63,219,242, 28, 86, 0,158, 19, 52, 40,201, 68,100,100,164, 24, +128,101,202, 80, 73, 66, 66, 66, 10,171, 43, 62, 25,124,247,221,119,239, 92,190,124,185,219,217,179,103,231, 10, 4, 2,168, 84, +170, 79,101, 50,217, 82, 6, 25,216, 88,252,221,177, 80, 0,140,108, 73, 60,221,136,136,136, 16, 31, 60,120, 48,197,201,223, 74, + 18, 19, 19,143,187, 40,161, 20, 34, 34, 34,222, 76, 76, 76,220,177,118,237, 90,127, 0, 85, 0,140, 79,186,205,209,228, 31, 29, + 29, 77,109,221,186, 21, 61,123,246,100, 43, 77, 3,241, 92, 13, 1,152,200,187, 65,191,223,181,107,151,117,190,112,121, 67,228, + 70, 70, 70,138, 77,115,118,169,200,200, 72,202, 81, 89,148,131,176, 53, 63,184,129,242,196, 79,226, 93,202,100, 50, 98,230,204, +153, 75,175, 94,189,250, 83,171, 86,173,230, 10,133, 66,104,181, 90, 0,248,110,207,158, 61,228,152, 49, 99, 36, 79,168,201, 80, +142,111,143, 83, 94,157,107,176, 91,174,197,238,212,250,236,145,145,145, 98,138,162, 40,234, 63,182,101,211,231,236,213, 65, 91, +200,201,201,161,114,114,114, 92, 70, 48,101,101,131,107,173, 87,224,106,162, 38, 8,194, 33,185, 36, 73, 81, 70, 35, 69,145,164, +237, 45, 34, 34, 66,156,152,152,232,212, 42, 84,235,214,173,123,245,208,161, 67,199, 7, 14, 28, 8,130, 32,168,237,219,183, 15, +118,244,222,172,183, 67,135, 14,237,120,171, 15, 31,210,105,210,178,219,158,217,187,167, 78,141, 33,233,115,246,228, 41,149, 74, + 74,169, 84,214, 91, 15,233,107,156,125, 63, 55,206, 73,144,188, 46, 3,225,225,225,172, 33,192,220, 16,120, 40, 65, 16,207, 78, +131,183,153, 55,219, 94, 62,237, 39,136, 6, 45,227,182,107,215, 46,249,132, 9, 19, 0,212, 36,213,176,168,156,114,103,188, 10, +180, 66, 65,231,252, 55,165, 33,149, 71, 70, 70, 58,230, 85, 72,240,119,224, 95,237,183,125,229,168, 15,152,139,115,124, 93,155, +186, 26, 36,227,242,147,201,100,132, 66,161,216,217,165, 75,151,113, 0, 56, 20, 69, 65, 36, 18,161,168,168, 8, 21, 21, 21,240, +241,241, 65, 81, 81,209,241, 49, 99,198, 72,246,238,221,155,226,224, 59,161,232,116,176, 4, 65, 96,220,184,113, 24, 60,120,176, +100,218,180,105,140,229,236,219,247,155,249,251,232,209,111,216,221,183, 7,245,153, 15,255, 46,238, 62, 43,107,237, 91, 31, 19, +245,177,191,168, 18,189,156,176, 37, 82, 83, 83,177,104,209,162,135,222, 69,255,254,253,169,147, 39, 79, 50,170,203, 9, 9, 9, +114, 44, 36,232,253,135, 19,207, 44, 36, 26,220, 25, 63,197,125, 75, 45, 75, 91, 38,147, 73, 98, 98, 98, 48, 96,192, 0,234,212, +169, 83,140,126,123,166,142,156,140,123, 19,230, 34, 49, 49, 81, 78, 47, 18, 54, 96,192, 0,170,178,178,178, 62,194, 23,199,196, +196,152,235,235,239,191,255,238, 78, 16, 4,162,162,162, 30, 0, 8,158, 56,113,226, 81,153, 76,198,113,196, 98, 95,122,116,169, +249,251,253,164,123, 32, 8, 2,219, 62,118, 7, 64,224,251,183,191,123, 61, 48, 48, 16, 0,176,125,243, 54,198,101, 21, 30, 30, +142,182,109,219,186,164,220,195,195,195, 57,233,233,233,100,175, 94,189,168,173, 91,183,226, 65,102,107,160,196,143,101,117, 7, +200,223, 81, 15, 0,149,144,144,240,144,134,101,209,129, 82, 78, 52,110,151, 90,147,214,242, 18, 18, 18, 44, 23,196,112, 24, 4, + 65, 16, 9, 9, 9, 4,221, 1,153, 62,157,182, 52,105,242, 55,221, 19, 97,113,111, 14, 43, 42,196,132,114,243,198,228,184, 61, +120, 30, 88, 99,222,152, 28,119,132,252, 41,138, 2,189, 58, 27, 69, 57, 86, 77,100, 50, 25,167,188,188,252,127, 62, 62, 62,227, + 0,112, 38, 79,158,140,232,232,104,240,249,124,136, 68, 34, 8,133, 66, 16, 4, 1, 46,151, 11,133, 66,193,184, 28,135, 12, 25, + 34, 6, 64,237,222,189, 27,244, 59,161, 40, 10,123,246,236,193,180,105,211,228,166,243, 79, 29,108, 41, 4, 79,194,179,150,144, +144, 32, 7, 64,188,121, 99, 2, 38, 92,183,217,198,168, 9,215, 35, 37,196,151, 78,181, 59,234,147, 79, 62, 65,155, 54,109, 92, +114,191, 4, 65, 80, 82,169, 31, 2, 2,142,185,180, 28,134, 15, 31, 62, 40, 57, 57,249, 56, 69, 81, 68, 76, 76, 76,138, 35,228, + 95, 23,246, 38,204, 69, 92, 92, 28, 72,146,196,220,185,115, 25, 41, 20,150,228, 15, 0,135, 14, 29,218, 63, 96,192, 0, 0,240, +139,138,138, 50, 12, 28, 56, 16, 82,169,148, 52,197,205, 48,241, 50,214,218, 95,190,124, 57,222,124,165,198, 54,220,246,177, 8, +111,245,225,227,211, 97,159, 48,126, 38, 15, 15, 15, 12, 24, 48, 0,233,233,233,230,254,212,122,163,175, 97,170,236,165,167,167, +147, 64,205, 50,235, 0,224,237, 94,194,178,122, 3,201,191, 94, 5,128, 38,171,244,244,116,115,218, 73, 75,235,201, 81,162,181, +232, 68, 92,221, 41, 89, 43, 3, 46,117, 13,219, 24, 18,112, 24,150, 10,133,201,250,127, 30,235, 25,101,217,153, 20, 20, 20,152, + 79,228,231,231, 51, 86, 24, 21, 10,197,183, 42,149,234,109, 14,135,195,153, 56,113, 34, 20, 10, 5, 10, 11, 11,225,230,230, 6, + 30,143, 7, 30,143, 7, 55, 55, 55,136, 68, 34,168,213,106, 48,113, 33,174, 93,187, 86,124,244,232, 81, 57, 65, 16, 24, 63,126, + 60, 40,138,162,149, 60, 98,252,248,241, 0,128,228,228,100, 57,219, 85,212, 79,254,166,247, 43,177, 84,146,233,119,111,233,213, +114,198,130, 79, 72, 72, 32, 76,239, 5,107,215,174,117,137, 50,182, 96,193, 2,218, 40,104,176,103, 98,216,176, 97, 67,206,157, + 59,151,220,186,117,107,180,107,215,142,234,219,183,175,217,115, 98, 90,253,209, 41,242, 95,182,108, 25, 8,130, 0,135,195,193, +185,115,231,192,196, 27, 99,229,145,120,157, 32, 8,188,245,214, 91, 6,211, 33, 93, 84, 84, 84,165, 88, 44,198,180,105,211,200, + 17, 35, 70,216,125,118,203, 85, 73,239, 39,221, 3, 8, 32,254,163,191,179, 22,111,251,216, 29, 81,125, 5,152,255,218,167,140, +239,139,137,229,207,228,154,232,232,104, 42, 60, 60,220,188,157, 59,119, 14,213,185,225,128, 78, 13,194,211,128,228,175,175,195, +242, 60,189,177, 45,183, 54,249,199,204, 95,108,243, 60,175,190, 6, 25, 30, 30, 78,165,167,167,131,246, 4,208,196, 21, 30, 30, +238, 80, 35,127,212,228,111,105, 85, 63,237, 1,123,150, 67, 2,207,157, 6, 64, 81, 40, 40, 40,192,253,251,247,205,199,172,247, +237, 88,255,220,195,135, 15,143, 8, 13, 13, 5,151,203, 69, 86, 86, 22, 40,138,194,205,155, 55,161,211,233, 64, 16, 4,120, 60, + 30, 8,130,128,209,104,132, 74,165,194,222,189,123,237,202, 61,118,236,152, 28, 0,198,143, 31,255, 80,189,165,135,122,104,162, + 96, 82,175,173,221,250,246,246,153, 88,249, 52,234, 26, 14, 96,226,250,183, 70,106,106, 42, 76,150, 97,195, 20,224,133, 4,136, + 47,107, 20, 56, 75,229,149,162, 40, 96, 33,129, 9,215, 35,157, 14,148, 37, 8,130, 50,189, 23, 51, 25,153,222, 23,209, 16,121, +237,219,183,127,136,220,156,133, 64, 32,160,174, 94,189,138,226,226, 98,162,184,184, 24, 97, 97, 97, 84, 78, 78, 14,184, 92, 46, + 12, 6,131, 83,127, 48,176, 47,151, 86, 30, 48,111,222, 60, 44, 95,190, 28, 39, 79,158, 4, 65, 16, 24, 53,122, 42,238,230, 48, + 91,192,241,208,161, 67,191,153,222,177, 6, 0,105,218, 16, 21, 21, 85, 1,192, 55, 49, 49, 17, 17, 17, 17, 98, 75,133,188, 62, +212, 88,255, 15,175, 99, 82, 51, 28, 0,108,223,118,193, 33,121, 13,197,141, 27, 55,112,238,220,185, 90,199,140, 21,119, 96,208, +147, 0, 81, 5,223,215,244, 56,103,181,216, 53, 27, 28,200,140,252,235,245, 0,152,172,127,194,210, 19, 64, 91,254,233,233,233, + 13, 33,127,123, 1, 74, 78,201,179,240, 76,136,225, 68,128,211, 35,176,156, 40,139,206,199,124, 63,244, 49, 87, 5, 39, 81,187, +252,204,155, 43, 80, 61,114,186,121,115,192,242,167,232,206,182,121,243,230,232,217,179,167,185, 17,210,251,214,215,214, 1, 95, +127,127,255, 46, 90,173, 22,101,101,101, 56,115,230, 12,210,210,210, 80, 92, 92, 12,181, 90, 13,122,140,148,162, 40,232,245,122, +104,181, 90, 70, 67, 12,116,221,168,139,220, 19, 18, 18, 8,130, 32,192,212, 51,179,111,223,111,230,141,201,190, 61,168,207,124, + 88,139,232,233,205,114,223,242, 26,166, 24, 48, 96, 0, 82, 83, 83, 27, 86, 33, 44,198,252, 81, 51,140, 37, 49,145, 51, 65,159, + 67, 3, 99,111, 44,223, 11,237, 5,112, 21, 92,225, 5,104,214,172, 25,242,243,243, 9,107,101,215, 89,242,223,155, 48,215, 92, +135,105,244,235,215, 15, 0,112,226, 52,243,201, 26, 17, 17, 17,195, 76, 99,255,215, 0,168, 76,253, 57,189,153,181,110,166,193, +133,181,199,254,109, 40, 87, 14,202,115, 5,210,211,211,137,158, 61,123,162,234,218,112,148,159,105,130,138, 83, 34, 80,229, 21, + 64, 53,192, 81, 25, 80,121,146, 3,245,159,124, 84,156,105,132,195,219,134,160,103,207,158, 14,241,211, 63, 29, 60, 38,141,147, +246, 4, 56,106,249,207,159, 63,159, 90,178,100,137,203,110,214,158, 60, 83, 39,229,178,202,201,116, 12,173, 62,210,177,144, 85, + 45,149, 74, 61,235, 58,239, 44, 44,199,254, 93,161, 4, 88,142,253, 51, 85, 2,162,163,163,225,225,225, 1, 79, 79, 79,120,121, +121,193,199,199,135,244,243,243,227, 36, 38, 38,226,157,119,222, 49, 95, 39, 20, 10, 49,116,232, 80,212,163, 4, 4,232,116, 58, +148,149,149, 65,163,209,192,199,199, 7, 2,129, 0, 6,131, 1, 20, 69,193,104, 52, 66,167,211, 65,175,215,195,104, 52, 58, 20, + 95, 96, 10, 90,171,243,188,165, 21,250, 36, 97, 47, 32,208, 81, 52, 84, 9, 32,190,172,123,184,111,194,245, 72, 19,185, 58, 41, +219,202,250,183, 56,142,241,227,199, 59, 28, 12,104,109,253, 91,202,115, 22,225,225,225,148,209,104, 68, 88, 88, 24,117,241,226, + 69, 34, 44, 44,140,210,235,245, 80, 40, 20, 13, 33,181,154,206,151,199,195,236,217,179,113,238,220, 57,252, 61,238,207,188, 78, + 31, 62,124,248,112,255,254,253, 1,192,203, 68,250, 42, 0,216,177, 99, 71,163, 19, 39, 78,120,155,218, 7, 97,250,180, 43,120, +249,143,203,241, 86,239,135,173,255,232,159, 84,216,113, 70, 15,138,162,208,125, 98,119, 92,216,118,129,120,156,198, 85,122,122, + 58, 33,249, 87, 56,117,120,121, 43,240,170, 43, 1, 67,205, 95,147, 0,248, 60,160,224,190, 47,142,231,134, 27,215,109, 47,230, +166,167,167, 19,225,225,225, 66, 58, 86,128,181,254, 23,215,123,157,221,105,128,145,145,145, 20, 93, 97, 45,227, 1,152, 96,201, +146, 37,180,197,224, 18, 48,144,231,244,248,186,105,138, 94,173, 45, 57, 57,153,164,103, 5, 52,212, 98,143,137,137,241,124,158, + 43,220,186,117,235,176,108,217,178, 90,245,138, 38,255,209,163, 71, 99,244,232,209, 53, 22,206,137, 19,245,137,241,207,206,206, +214, 24,141, 70,148,151,151,163,164,164, 4,229,229,229, 80,169, 84, 80,169, 84,168,174,174, 70,101,101, 37, 20, 10, 5,212,106, + 53,180, 90, 45,152, 52,116,130, 32,176,123,247,110,135, 20,182,103, 25,169,169,169,181, 54, 75,204,158, 61, 91,108,185,207,100, +204,217,198,152,127, 45,203,189, 33, 81,251,182,126, 75, 81, 20,177,123,247,110,151,198, 2,236,222,189,219,225, 54,220,163, 71, + 15,202,104, 52,154, 19,180,132,133,133, 81, 36, 73,226,193,131, 7, 80, 42,149, 78, 61,243,191,231, 15,196,137, 19, 39, 64,238, +244, 5, 69, 81,136,139,139, 51,191,163,212, 51, 36,152,142,124, 68, 68, 68,188, 1, 0, 81, 81, 81, 5, 38, 5, 64,187,125,123, +124,163,233,211,167, 55, 58,113,226, 4,134, 15, 31, 62,196,145,156, 0,247,147,238,129, 0,129,120, 11,235,127,226,143, 42,112, +223, 82, 96,251, 25, 29,102,205,154,133, 37,135,191,123,236,117, 57, 60, 60,156, 75, 43, 1,175,205, 50,128, 82,251, 0,149, 0, + 42, 1,110, 21, 80,249, 0, 56,116,161, 9, 44,200,159,151,158,158,174, 97,201,223, 62,249,219,245, 0, 88,143,251, 91,198, 3, + 48,117,179, 36, 36, 36,164,152, 2,132,228, 86,158, 36,103, 59,140,135,228,209,195, 2,166,113, 72,151,184,127, 6, 15, 30,124, + 37, 57, 57,185,203,211,248,130,105,171,223, 85,110,127,218,234,119,192,237, 95, 11,241,241,241,230,239,255,253,239,127,177,113, +227, 70, 0,208, 1,224,211,196, 15, 0, 67,135, 14,181,167, 0,168, 67, 67, 67,161, 82,169,160,211,233, 80, 92, 92, 12,129, 64, + 0, 30,143,103,246, 0, 40,149, 74,168, 84, 42,104,181, 90, 40, 20, 10,140, 27, 55, 78,178,103,207,158,122,239,143,182, 50,237, + 76,107,197,248,241,227,237, 42, 10, 53, 10,205,163,139, 1,112,230,188, 53, 44,166,251, 61,132,184,184, 56,249,236,217,179, 37, +113,113,113, 41, 79,180, 14,215, 97,253, 91,194,145, 88,128,186,172,127,103,209,163, 71, 15,234,252,249,243, 68, 88, 88,216, 23, +116,213, 54, 26,141, 11, 61, 60, 60, 80, 82, 82,226, 84, 31,243,249,103, 3,145,146,146, 2, 98,119, 0, 0,224,200,231, 94, 24, +250,117, 21, 6, 12, 24,128,111,150,156, 0, 69, 81,140,189, 21,135, 14, 29,218, 59,112,224, 64, 0, 40,222,177, 99, 91,179, 19, + 39, 78,250, 82, 4,133, 17,195, 71,140, 62,120,240,224,254,131, 7, 15, 58,228,229, 92,190,124, 57,222,234,227, 86,219,226, 7, +133,217,179,102, 35,120,104, 99, 60,169,184,165,244,244,244, 90, 26, 62, 85, 5, 8,116, 0, 73, 17, 48, 24, 41, 8, 40, 32, 88, +196,177,188,222, 0, 22, 53, 70,217,146,207,234, 84, 16,194,194,194,234, 87, 0, 44, 35,254, 77,228,111, 14,150,162, 61, 1, 76, + 53,127, 27,164,221, 32,216,144,231,242, 49,169,152,152,152, 46,201,201,201,174,236,240,158,215,122, 70,160, 38, 10,220,108, 73, +191,247,222,123, 0,192,183,168, 75,230,115,166, 78,171, 46, 92,237,221,187,247, 59, 41, 41, 41, 9, 70,163, 17,149,149,149,208, +235,245,230,113,127,141, 70, 99,158, 98, 72, 7, 6,238,217,179, 39,133, 65,125, 33, 96,154, 2,104, 93,111, 35, 35, 35, 41,154, +244, 7, 15, 30, 44, 97,162, 0, 60,170, 60, 0,150, 99,255,150,228,111, 61, 44,192,224,125,212, 7, 42, 46, 46, 78,254,230,155, +111, 98,231,206,157,206,122,203,196,150,158, 19,122,159, 14, 24,156,112, 61,146,186,117,235, 86,157,191,167, 19,254, 28, 62,124, +184, 78,143,221,157, 59,119, 24,123,102,202,202, 6, 83, 0, 48,100, 72, 54,178,179,179,109, 70,151,151,150, 14, 2, 80, 14,192, +126,191,213,169, 83, 39,234,252,249,243,132,169,179,252, 2, 0, 56, 28,206,194,187,119,239,162,188,188,220,169,134,204,225, 16, + 53, 10, 59, 77,254,151, 12,216, 40,215, 1, 0,190, 89,114,194,225, 62,130,110, 19,211,167, 79, 15,163, 40, 10, 17, 35, 35,198, + 29,216,127,224, 87,166,196,111, 41,234,141, 49,175, 95, 35, 8,162, 19, 69, 1,220,183, 20,160, 40, 10,179,231,204, 70,227,161, + 77, 26,152, 87,181,102, 90, 47, 93,239, 26,146, 73, 48, 60, 60,156,218,245, 89, 83,120,150,222,193,237,202,230,104, 35, 40, 6, + 60,130,193, 83, 62,128,183,178, 20, 64, 35,179,199,192, 90,105, 96,225,132, 7,192,114,186,159,213, 52, 54, 42, 33, 33,193, 97, +151,169, 5,105,187,228,198, 45,229,209,243,255,159,211,233,117,207, 4,172,202,190,214, 20,177, 58,206, 61,212, 25, 72,165, 82, +131, 76, 38,219, 51,112,224,192,153,137,137,137, 43, 12, 6, 3, 42, 42, 42,204, 49, 0, 0, 80, 92, 92,140,138,138, 10, 80, 20, + 5, 71,234,211,144, 33, 67, 36, 71,143, 30,149, 39, 36, 36,212,178, 62,233,223, 15, 25, 50,196,161,100, 64,143, 2,234, 51, 31, + 58, 67,248, 15, 17,188,157, 46,155, 32, 8,130,114,134,252, 77,158,182, 20, 91,109, 17, 0, 44,130, 2, 25, 97,218,180,105,114, + 6,255, 73, 57, 48, 87,188,214,103,109, 34, 98,150, 28,175, 77,155, 54,212,181,107,215,104,151,255, 23, 0, 22,106,181, 90,220, +190,125, 27, 10,133,194, 89, 42,164,200,157,126, 56,114,169,198, 56,221, 36,215, 97,199, 25, 29, 40,138,194,201,179,206,143, 44, +166,166,166, 98,248,240,225,146,131, 7, 15,166, 28,216,127,192, 89, 49, 28,146, 36,221, 0, 96,231, 89, 61,102,205,154,133,198, +195,154, 48, 87, 39,109, 64,169, 84, 2, 0,178,179,179,169,117,235,214,153, 21, 50,203, 88,146, 77,155, 54, 89,246, 15,140,254, +165, 21, 71, 9, 4,133,225,157,245, 10, 0,193, 53,101, 48, 35, 16, 45,121,121,248,122,112, 17, 54,183,127,139,218,177, 99,199, + 63, 62, 0,144,182,238,109, 89,254,214,231,235, 27, 2, 32, 76, 67, 0, 15, 77,155,114,100, 8,192,102, 71,225, 58,210,177,148, +231,210,249,255,244,216,191,179,176,167,144, 56,170,176,212,229,238,119,118, 24,160, 46,119,191,147,195, 0,150, 65, 65,132, 3, +231, 96, 67, 9,160, 0,172,148,201,100,107,227,227,227,245,124, 62, 31, 90,173, 22, 6,131, 1, 36, 73,194,215,215, 23,229,229, +229,112, 52,155,226,209,163, 71, 83, 80, 51,239,159,218,189,123, 55, 76,138,128,121,106,224,209,163, 71,255, 17,157,195,155,111, +190, 73, 41,149, 74, 28, 56,112,192,209,250, 44,182, 83,222,212,132,235,145, 18, 38,222,184, 79, 62,249,228, 33,227,194, 26,159, +126,250, 41,197, 52,200, 83, 42,245,179, 43, 79, 42,245, 99, 36, 76, 36, 18,209,157, 36, 69, 81, 20, 84, 42, 21, 10, 11, 11,157, + 30,243,183,196,176,175,171,106,237, 55,132,252,141, 70, 35, 1, 0, 78, 88,252,214, 32,247,253,190,191,189,101, 38, 64, 87,161, + 62,133,204, 66, 1, 96,100,253, 75,199,135, 20,254,146,137,166,178,221,183,107, 69,249, 15, 88, 21, 78, 29,159,246, 2,110, 61, + 16,161, 62,175, 19, 11, 7, 61, 0,166, 23, 71, 56,114,252, 9, 91,160, 41, 79,217,253, 16, 14, 88,204,118, 20,145,193, 46,187, +175, 9, 19, 38, 72,156, 72,239, 91,175,133,102,195, 2,173,207, 58,101, 20, 52, 38,149, 74, 13, 0,136,113,227,198,137,115,115, +115,229,106,181, 26, 70,163, 17,157, 58,117,146,244,236,217,211,233,247,189,123,247,110,203, 41,103, 78,121,141, 30,117, 12,128, +189,125, 38,250,162, 41, 58,188, 54,225,156, 60,233,176,219,223, 52,215,159,154,112,253, 97, 5,142,162, 40,138,206, 17, 96,161, +144,153, 3,230,156,109, 27, 0,176,107,215, 46,194, 85,109,141,233, 53, 0, 80, 86, 86,134, 54,109,218, 80,149,149,149,104,213, +170, 21, 50, 50, 50, 92,210,215,113,222, 44, 7, 65, 16, 24,253,122, 12,237,134,193,210, 37,211,204,223, 29,205,152,233, 42, 72, +165, 82,114,237,137,181, 46,149, 57,105,210, 36,147,215, 69,230, 9,192, 96,218, 40,169, 84, 74, 90, 92,227,208, 3,203,118,223, +110,106,201, 61,180,171, 63, 61, 61,157,144, 30,123,139, 98,201,255, 17, 40, 0,207, 16, 26,220, 72,159,214,252,227,174,190,175, + 71,224,133,121,164,229,102, 26,227, 55,255,199,245,235,215,159,240, 27, 33,137,167, 91, 94, 77, 89, 57,154, 81,174, 78, 44,172, +181,142, 5,101,235,156,201,242, 78,121, 30, 58,146,251,247,239,155,223, 71,118,118,182,203,222,137, 76,182,150,146, 74,167, 17, +191,255, 38, 99,244, 3,103,151,119,117, 6,166,105,125, 46,239, 19,234, 83,174, 29,236, 55, 60, 80, 19, 83,164,183, 48, 66,205, +227,252,172,219, 31, 76,235,212,195, 21,243,113, 86, 52, 22, 44, 88,176, 96,193,130,197,211, 1, 14, 91, 4, 44, 88,176, 96,193, +130, 5,171, 0,176, 96,193,130, 5, 11, 22, 44, 88, 5,128, 5, 11, 22, 44, 88,176, 96,193, 42, 0, 44, 88,176, 96,193,130, 5, +139,231, 2,181,102, 1,208, 57,175,157,129,173, 96, 66, 86, 30, 43,143,149,247,248,228,197,198,198,214,214,238, 57, 28,115,118, + 57,203,169,102,116, 54, 69,203,169,103,182,210, 7,123,122,122, 66, 40, 20,154,127,207,225,112,192,229,114, 31,146, 71, 47,204, + 68,146, 53,179,188,234, 90, 44,135,125,191,117, 67, 38, 91, 39,230,242, 4,160, 72, 3,166, 78,125, 63,197, 25,121,107,215,174, +149,100,100,100,240,194,194,194,146,173,179,238, 57, 41, 79,156,145,145,129, 53,107,214,164,176,237,237,217,147,231,176, 2,240, + 79, 68, 96,224,251,181, 10,174,164,100, 3,241, 84,201,123, 63,144, 2,128,146, 13, 37,132,229,247, 6,136,108, 96,114,207, 71, + 46,239, 31,139,245, 43,150,137,139,175,156,193, 0,191, 98,121, 51, 67, 30, 50,169, 54, 56,167,244,151,120,135,190,140,153,115, +230,165,216,251,253,169, 83,167,208,175, 95, 63, 51,241,211,132, 77, 16,196, 67,132, 77,146,164,121,187,123,247,174, 77,121,231, +207,159, 71,120,120, 56, 68, 34, 17,120, 60, 30,184, 92,110, 45,153, 52,233, 27,141, 70,243,166,213,106,145,158,158,142,118,237, +218, 61,119,239, 71, 38,147, 17, 82,169,148, 90,187,118,173,248,230,205,155,184,117,235,150,220,215,215, 23, 91,183,110,109, 80, +253, 95,183,110,189, 88, 32,244,135,175,223, 11,114,101,117,129,100,221,186,159,197,171, 87, 59,150,251, 97,205,154, 53,226,132, +132,132,227,153,153,153, 56,112,224, 0, 66, 67, 67, 49,119,238, 92,174,229,220,123, 39,228,201,179,111,103,161, 93, 72, 91,240, + 5, 2,204,154, 53,251,213,152,152, 24, 57,219, 82,159, 83, 15,192,179,132, 33, 67,134,216,213,120,142, 30, 61,106,183, 97,210, + 4,109, 77,220,206,194,213,242, 30, 1, 8, 7, 73,219,110,106, 89, 23,203, 99,242,123,235,255,127,182,137,101,237, 90,241,181, + 83, 71,144,187,227,123,185, 74,165,133,254,101, 14, 68,205, 9,180,207,189,132,151,188, 40,121,121,241, 95,104,186,246, 63,146, +113,211,190,172, 87, 9,184,118,237, 26,184, 92, 46,250,247,239, 15, 30,143,103,222,104,133,128,182,250, 13, 6, 3,140, 70, 35, +244,122, 61,238,222,189,139,227,199,143,219,148,167, 82,169,112,225,194, 5,244,238,221, 27,124, 62, 31,110,110,110,181,100,146, + 36, 9,131,193, 0,131,193, 0,189, 94, 15,181, 90,141, 11, 23, 46,160,186,186,250,105, 32,107,142,169,110,112, 0, 24, 26,146, +135, 94, 38,147, 17,177,177,177,100,108,108, 44, 2, 2, 2,240,239,127,255, 27,227,199,143, 71, 85, 85, 21, 2, 2, 2,156,202, + 64, 26, 16, 16, 96,190,159, 5, 11, 62,195,150,109,233, 16,137, 26,129,203,229,203,171,171,242, 28,150,153,150,150,134,234,234, +106,244,238,221,251,238,224,193,131,155,148,150,150,226,200,145, 35,198,169, 83,167, 98,253,250,245,245,182, 17,109, 78,214, 67, +101,115,249,198, 13,164,120,185, 99, 78,220,151,121,221,123,116,105,113, 47,191, 8, 71, 18, 83,142,111,223,190, 99,112, 84,212, + 91,199, 88,234,124,250, 65,167,254,181,242, 20, 48, 82, 0,172, 83,183,218,219,127,236,228,255,193, 7, 31,212,123, 77,121,121, + 57, 0, 80, 76,148, 0,154,172, 27,106,173, 63, 10,121,150,150,191, 11,172,127, 71, 73,155, 41, 89,187, 90,158,229,181,150,159, + 0,128,178,178,154,204,136,254,254,201,207, 69, 67,205,249, 51, 25,237,242,228,242, 60, 21,137,177,237,184,120, 33,200, 0,210, +159,130,155, 63, 23, 85,165,124,136,170,212,232,152,177, 82,190, 37, 46, 86,242,206,236, 69,117, 42, 1, 4, 65,224,250,245,235, +224,243,249,120,245,213, 87,205,164,237,230,230, 6, 14,135, 3,138,162,160,215,235, 97, 48, 24,160,213,106,145,151,151, 7,185, + 92, 94,231,146,202, 28, 14, 7,122,189, 30, 25, 25, 25,232,223,191, 63, 68, 34, 17, 4, 2,129, 89, 30,173, 0,104,181, 90, 84, + 87, 87,227,242,229,203,208,104, 52,230, 97, 2, 38,136,138,138, 18,115,185, 92,121, 85, 85, 21,248,124, 62,138,138,138, 62, 28, + 59,118,108,149, 80, 40,220,226, 12,105, 71, 69, 69, 77,224,114,185, 59, 19, 19, 19,105,121,153, 99,199,142,189, 41,147,201,198, + 75,165, 82,157, 51,150,112,108,108,172,124,209,162, 69, 69, 48,173, 56, 19, 27, 27,139,107,215,174,161, 81,163, 70, 8, 11, 11, +195,230,205,155, 29, 38,255, 95, 38, 79,198,136,238,221, 1, 0,141,103,206,132,200, 61, 24,213,149,185,168, 84,220,150,196,196, + 76, 73,169, 43,159,123, 93,120,241,197, 23, 81, 84, 84,132, 83,167, 78,181,226,112, 56,184,124,249, 50,252,253,253,145,154,154, +138,119,223,125,151,202,200,200,168,247,247,165,223,206,169,181,239,169,211,163,169, 65,131, 89,159, 44,108, 17,183,244,191,248, +126,233,106, 52,227, 24,177,122,233,178,228,119,223,125, 23,246,228,177,120,250,200,159, 62,206,116, 45,128,135,242,127,219,219, +127,156,112,229, 74,125,207, 2, 44,149,128,199,228, 9,112,212, 82, 39,236, 88,231,206,200,179,245,249, 92, 37,174,250,113,201, + 55,226,208,140, 95,228, 69, 92, 35,218,249, 0,173, 90, 82,224,190,200, 7,175,109, 91,240,181, 26,104, 79,231, 65,171,224,129, + 75,186, 65,147,188, 69,190,126,213, 82,201,212, 25,182,135, 3,104,247,124, 86, 86, 22,252,252,252, 32,145, 72, 32, 20, 10,193, +231,243,193,227,241,204, 86,191, 70,163, 65, 97, 97, 33, 78,156, 56, 1, 14,135, 3, 14,135,131,250,228, 25,141, 70, 92,189,122, + 21,253,250,245,131,183,183, 55,132, 66, 33,184, 92, 46, 12, 6, 3,116, 58, 29, 42, 43, 43,241,215, 95,127, 65,171,213,130,199, +227,153, 99, 1,236,161,127,255,254,226, 27, 55,110,200,239,220,185,131,202,202, 74,240,249,124, 52,110,220,120,229,201,147, 39, +209,167, 79, 31,158, 76, 38,219,232,136, 18,208,191,127,255, 49, 55,110,220,216,105, 37, 47,244,228,201,147,161,125,250,244,217, +110, 82, 2, 24,201, 91,179,102,141, 88,167,211,225,254,253,251,180,203,219, 92, 72,139, 22, 45, 42,136,141,141,109, 54,126,252, +248, 87, 63,254,248, 99,135,250,191,245, 63,111, 20,127, 54,127, 94,173, 99,247, 87,172, 64,227, 55,154,227,251,239,127,148, 76, +158,252,182, 83,253,233,169, 83,167,228,127,254,249, 39, 62,251,236,179, 74, 46,151,235, 45, 20, 10,209,167, 79, 31,200,229,114, + 36, 38, 38,162, 89,179,102, 14,180, 60, 2, 91,179,238, 97,207,173, 2,236,251,125, 51,184, 92, 2,115,102,190, 67,118,107, 28, +200, 89, 55,107, 33,214, 59, 42,143,197, 19, 33,127,107, 37,210,150, 82,224,244, 44,128, 39,189,188,109,126,185,231,118, 0, 0, + 32, 0, 73, 68, 65, 84,219,182,109, 37,246,182,199,109,173, 63, 10,121, 46,180,250,153,146,182, 51,100, 13, 75,235,156,182,208, + 77,114, 40, 39,229,213,217, 81,251,251, 39, 59,101,253,175, 90,181, 74, 60,101,202, 20,170,174, 99,214,231,234,130,229,245,171, + 86,173, 18, 91,159,179, 62, 86,111,121, 93, 61, 47, 47, 44,168, 68, 35, 47, 30,218,122, 81,224, 5,146,224,189,242, 26, 60,186, +109,129,168,199, 15, 16,248,136,192,175, 86, 67,165, 50,162, 37, 87,133,212,248,186, 83,201,114, 56, 28,240,120, 60,184,185,185, +225,214,173, 91,184,124,249, 50,188,189,189, 17, 16, 16,128,128,128, 0, 4, 6, 6,194,215,215, 23, 10,133, 2,169,169,169,224, +114,185,230,177,125, 91,160,207,243,249,124, 24,141, 70,100,102,102,194,221,221, 29,129,129,129,104,212,168, 17,130,130,130,224, +233,233,137,204,204, 76,232,245,122,243, 16, 65, 93, 10,133,181,229,255,224,193, 3,249,237,219,183,209,166, 77, 27, 12, 27, 54, + 12,189,122,245,130, 74,165,194,241,227,199,145,145,145,177, 65,163,209,188,237,128,229, 47,121, 80, 84,252,107,246, 61, 5,188, +218,245, 70,232,176,247,209,172,215,104,148,107, 57, 56,154,124, 12, 25, 25, 25, 99, 53, 26,205, 84,166,228, 95, 89, 89,137, 75, +151, 46,201, 79,157, 58,133, 23, 95,124, 17,177,177,177,129, 0, 72,147, 7,160, 25, 0, 8,133, 66,198,100,189,254,231,141,226, +173,241,251,197,254, 1, 93,228,241, 59, 46, 97,242, 47,191, 32,241,194, 5, 36, 94,184,128,198, 51,103, 2, 0,244,122,229, 9, +103,218,220,235,175,191, 78,237,219,183, 15,227,198,141,187,235,229,229,197,113,119,119, 79, 79, 75, 75,195,169, 83,167, 80, 82, + 82,130,208,208, 80,199,148,210, 11,183,176,244,143, 43, 88,191,116,193, 37, 30, 87, 13,142,177, 10,223, 45,255,133,179, 51, 53, + 29,133, 28, 30, 94,120,225, 5,150,101,159, 19,240,156, 37,248, 39,181,120,197, 35,179,176,255,217,138,192, 35, 25, 87,111,160, +171,158,176,115,220, 33,165, 98,233,210,165,226, 99,199,142,201,179,178,178,234, 60,150,150,150,198, 72, 22,125, 93, 90, 90, 26, +202,202,202,228, 75,151, 46,149,204,155, 87, 99,149,219, 58, 86, 31,188, 53,165, 72,204,213,160, 89, 57, 23,221,189, 9, 4, 21, + 3,237,120, 62,224, 16, 1,160, 52, 15,160,124, 64,224,106, 46,137,251, 74, 13,120, 28, 14,186,250, 11,228,117, 61,183,165, 2, + 32, 16, 8,112,251,246,109, 52,107,214, 12, 67,134, 12, 1,151,203, 5, 73,146, 40, 45, 45,197,169, 83,167,224,230,230, 6, 62, +159, 15,157, 78, 87,167, 2, 64,123, 7,104, 37,128,162, 40,100,103,103,163, 93,187,118,240,241,241, 65,117,117, 53, 46, 92,184, + 0,163,209, 8,129, 64, 0,173, 86, 11,173, 86, 91,103,223, 65, 7,209, 1, 64,113,113,177, 60, 63, 63, 31,221,186,117,131, 88, + 44, 70,243,230,205, 37, 74,165, 18, 65, 65, 65,242,228,228,100,156, 61,123, 22,190,190,190,189,101, 50,217, 54,169, 84,106,119, +125,247,226,226,226,227, 15,202, 20,240, 15,237,141,182,253,223,132,111,243, 80,104,149, 21,200,253,243, 32,110, 29,219, 76,203, + 99,244,126, 77,177, 15,242,194,194, 66, 4, 7, 7, 67, 40, 20, 74, 46, 93,186, 36,143,141,141,229,152, 60, 0, 0,112, 35, 54, + 54,150,100, 82, 7,127,222,176, 89,236,235,247,130,220,215,255, 5,112, 56,110,208,235,149,216,176, 81,142,201,239, 73,104,143, + 2,166, 78,157,138,160,160, 32,210,209,182,247,206, 59,239, 80,241,241,241,232,223,191, 63,122,244,232,209, 10,128,225,216,177, + 99,225, 57, 57, 57, 16,137, 68, 16,137, 68,136,136,136,120,117,215,174, 93,199,153,200,219,118, 51, 15, 63,252,117, 3, 63, 47, +158, 95,214,252,133, 86, 47, 42,171,203,241,251,161,191,112,233,242, 77,248, 82, 36,248,247, 31, 32,226,195,232,193, 59,119,238, +250,103,185, 96,159, 33,216, 26, 62,170,203, 43, 80,151,170, 78,140, 31, 63,222,210,130, 38, 34, 35, 35,235,219,127,102, 81, 82, +178,129,176,220,158, 54,121,192, 35,113,255,215,103,181, 55,232,158,157,181,206, 29,241, 0, 56,138,168,168, 40,241,254,253,251, +107,145,191,173, 99,206, 32, 43, 43, 11,251,247,239,151, 71, 69, 69,137,235, 59, 86, 39,113,149,228,225,204, 61, 53, 84, 70, 18, + 39,243, 72,220, 55,240, 96,212,166,163,252,218, 7,216, 60, 51, 6, 7,142, 40,112,185,148,194,197, 98, 3,174,150, 26, 80, 90, +120,191, 94,175,156,165, 18, 32, 20, 10,113,247,238, 93,220,184,113, 3, 64, 77, 92,204, 31,127,252, 81,107, 44,191,190,241,122, +130, 32,204, 94, 0, 90, 30, 69, 81,200,203,203, 67,203,150, 45, 81, 88, 88, 8,146, 36, 33, 20, 10,205,178,234, 27, 82,176, 68, +110,110, 46, 52, 26, 13,194,195,195,209,188,121,115, 9,151,203,133,183,183, 55, 94,126,249,101,137,167,167, 39,114,115,115, 81, + 89, 89,121,153,105, 61,200,205,205, 5,201,225,163, 89,216, 96,248, 54, 15, 5,135,235, 6,145,119, 16, 90,190, 28, 1,190,135, + 31, 45, 47,199,158,156,181,107,215,138, 43, 42, 42,228, 5, 5, 5,104,209,162, 5, 36, 18,137,100,203,150, 45, 41,165,165,165, + 4, 0,244,238,221,219, 96,186, 52,212,199,199, 7, 50,153,204,110,192,131, 80, 24,128,128,160,110, 48, 26,180, 40,186,151,134, +251, 5,167, 6,149, 20, 95, 88, 96,146, 7, 0,120,112,255, 62, 76,242,220,152,214, 61,169, 84, 58, 62, 62, 62, 30,209,209,209, +152, 56,113, 34, 0,144, 71,142, 28,225,237,223,191, 31,147, 39, 79, 30,122,254,252,121,226,244,233,211, 68,108,108, 44,163,200, +253,204, 74, 21,230,159,184,136,111,231,198,160,255,200,193,254, 70,202,128, 93,191,158,192, 79, 43,183,224,208,236,119,177,190, + 91, 75,180,244,225, 97,193,130, 88, 54, 8,240, 25,193,197,139, 23,235, 36,255,122, 61, 0,214, 99,251,246,246,159, 71, 60,130, + 41,120, 78,225,235,151,190,150, 76,155, 54,237, 89, 40,239, 90, 67, 10,143, 56, 72,143,209,123,136,136,136, 16,223,186,117, 75, +174,211,233,234, 61,214, 16,148,151,151, 67,169, 84,202, 35, 34, 34, 36,121,121,121, 15, 29, 59,120,240, 96,157,239, 46,163, 76, + 13,133,142, 68, 70,177, 1,133, 21, 6, 4,255,193,195,139,187,178,112, 55,231, 42,110,254,169,131,129,199,133,142, 4, 52, 58, + 10,229, 20,137,160,122,150,181,167,167,251,209, 99,247,116,196,254,131, 7, 15,208,170, 85, 43,228,228,228,152, 93,254, 60, 30, +207,124,189,163,195,121,150, 57, 4,232,207, 71, 52, 36, 88, 1,215,198,124,216, 37,107,146, 36,161, 84, 42,107, 58, 71, 30, 79, +242,193, 7, 31,212,122,119, 85, 85, 85,188,125,251,246, 97,244,232,209,156,249,243,231, 63, 88,178,100,137,193, 94, 93, 36,136, + 26,133, 72,173,122,128,234,170, 60,201,148, 41,239,166,200,100,178, 84, 0,223, 86, 85, 85, 97,223,190,125,102,197,177, 93,187, +118, 58, 38,117,123,241,226,197,163,191,255,254,251,132,136,136, 8,244,235,215, 15, 0,200,211,167, 79,115,126,251,237, 55,136, +197,226,145,171, 86,173, 58,234, 72,193,220, 83,105,241, 78,226, 31,152, 53, 33, 2,227,223, 25, 7,149,166, 18,123,247,165, 96, +249,234,109,248,223,208,151,208,182, 40,159,101,211,231, 64, 25, 96,234, 1,112, 53, 40,171,134,108,111,159,133, 5, 30, 53,249, +187,208,106,175,203,163,224,236,248,127,125,245,130, 81,125, 57,120,240, 96, 74,251,246,237, 37,126,126,126,245, 30,107, 8,252, +252,252,208,190,125,251, 90, 68,111,235,152, 45,168,141,222,208, 19,192,185, 18, 45,138,140, 70, 28,203,214, 96, 87,130, 6,199, +243,131,144,197,247, 65,190, 66,143,188, 42, 18, 74, 3,160, 50, 80, 16, 4, 52,182, 75,204,244,252,126,163,209, 8,131,193,128, +128,128, 0,120,122,122,162, 85,171, 86,208,235,245,230,227,182, 18, 2, 89,203,163,231,247, 27, 12, 6,168,213,106, 80, 20,133, + 22, 45, 90,160,160,160, 0, 77,154, 52, 1,143,199,131, 86,171,133, 78,167, 51,255, 47,147,225,193,150, 45, 91, 66, 40, 20, 34, + 61, 61, 29,249,249,249,114,163,209,136,202,202, 74,226,207, 63,255,148, 87, 87, 87,163,101,203,150,240,246,246,126,141,105, 31, +213,178,101, 75,112, 72, 29, 10, 46, 36,163, 34, 63, 19,164, 81, 15,117,101, 49,114,255, 60, 8,157,178,156,150,215,154,137,114, + 67, 35, 32, 32, 64,190,102,205, 26,179, 23,167,180,180,148,184,122,245, 42, 76,164, 77, 2, 8,182,149,240,200, 26, 6,131, 26, + 6,125, 53, 68, 30,141, 33, 20,249, 67, 38, 91, 39,150, 74,165,134, 69,139, 22, 5, 88,200,195,250,245,235,161, 80, 40,232, 41, +140, 15, 97,209,162, 69, 84,223,190,125,169, 30, 61,122, 80, 95,126,249,229,239,163, 71,143,198,200,145, 35, 1, 0,231,207,159, +175,220,191,127, 63,198,143, 31, 63,250,216,177, 99, 7,153,148,217,162, 69,139,168,126,253,250, 81,111,125,240, 33, 94,221,125, + 2,243,254, 53, 22, 31,125, 58, 29, 26, 93, 53,238,220,206,131, 76,182, 11,191,141,234, 3,113,139, 70, 78,183,141,225,195,135, +179,253,250, 19, 68, 88, 88, 88, 45,210,183, 14, 4,124,172,169,128, 35, 35, 35,197,142,236, 63, 54, 75,191,142, 57,251,214,214, + 62, 83,235,191, 46,121,239, 7, 6, 82,239, 7,254,237,206,183,222,183,231,137,112,149,188, 58, 44,105,103,136,250,145,193, 74, +137,112,218, 3, 0, 0,219,183,111, 79, 25, 53,106,148,196, 50, 57,141,173, 99,206,160, 93,187,118, 24, 53,106,148,100,251,246, +237, 41,245, 29,171,243,247,237,219,161,189, 7, 23, 94, 4,160,167, 40, 92, 47,215, 33, 62, 75,139,237,103, 10,241,215,237, 50, + 20,170,129, 82,141, 17,183,171, 41,220,211, 82,168,214,233, 37,245,145, 23, 61, 53, 79,167,211, 65,173, 86,163, 73,147, 38,232, +210,165,139, 73,209,243, 71,175, 94,189,204,132, 77,147,118, 93,132, 77, 19,186, 94,175,135, 78,167, 3, 65, 16, 8, 9, 9, 65, + 69, 69, 5,242,242,242, 80, 86, 86,134,214,173, 91,131,195,225, 64,167,211, 65,171,213,154,127, 99, 15, 65, 65, 65,146,230,205, +155,227,234,213,171, 56,124,248, 48, 14, 28, 56, 32, 63,112,224,192,241,147, 39, 79,130,203,229,226,149, 87, 94, 65,219,182,109, +213, 48, 5,222, 49,144, 55, 58,216,223, 7,165,217, 23,113,243,232, 70, 92, 61,184, 6,215, 15,202,112,247,236,111, 16,112, 72, + 90, 94,129, 61, 57, 51,102,204, 72, 9, 14, 14,150,120,123,123, 35, 35, 35, 3,249,249,249,242,184,184, 56,177,165, 34, 96,242, + 4,112,226,227,227,209,185,115,103,187,247,166,211, 42,160,168,200,130,155,155, 7,124,253, 59,200, 61, 60,155,225,151, 95,182, +138, 9,130,211,155,190,198,171, 34, 25,242,255,125,132, 33, 29,170,235,172,219, 7, 15, 30,132, 72, 36, 66,231,206,157,209,186, +117,107,122,248,192, 80, 94, 94, 94,189,123,247,110,223,176,176,176,209, 59,119,238,220,207,180,238, 38, 38, 30,132,183,183, 39, + 6, 12,124, 89, 21,214,227, 69,140,249, 96, 50, 84,132, 1,197, 69,101,152, 54,243, 43, 44,233,217, 14, 61, 26, 57,175, 36, 15, + 31, 62,156,250,238,187,239, 88, 37,224, 41, 81, 4,108,225,169, 89, 11,224, 73,207, 42,112,134,128, 29,197,134,146, 26, 5,194, +146,168,233, 99, 79,131,188,167,213,163, 96,229, 9,160, 28,241, 0,208,152, 55,111, 94,202,160, 65,131, 36,189,122,245,170,243, +152,229,185,250, 96,121,253,160, 65,131,106, 5,251,217, 58, 86,175,117, 40,240,144,116,109, 18,136,190, 1, 2,188,228,199, 71, + 83, 33, 7, 2,138,130, 80,107, 64, 75, 79, 30,202, 41, 10, 87,170, 13,200, 84, 26,208,172, 81, 0, 90,191, 52,176, 78, 89,180, +213, 79, 79,245,107,217,178, 37,186,117,235,134,242,242,114, 84, 84, 84,160,162,162, 2, 94, 94, 94,232,221,187, 55,116, 58,157, + 57, 39, 64, 93,132, 77, 43, 19,122,189, 30, 4, 65, 32, 52, 52, 20,106,181, 26,197,197,197, 40, 42, 42, 66,113,113, 49,148, 74, + 37, 66, 67, 67,193,227,241,204,242,234,202, 43, 96,173,148, 5, 7, 7, 75, 66, 66, 66,112,231,206, 29, 36, 37, 37, 33, 45, 45, + 13,238,238,238,120,245,213, 87,209,173, 91,183,131, 66,161,112, 14,211,105,123,219,183,111,223, 31,220, 40,232,237,144, 38,190, +168,190,253, 39, 50,147, 54,160, 32,237,119,248, 9,140, 24, 60,232, 85,116,235,214,109,210,199, 31,127,188,143,137, 44,111,111, +111,244,232,209, 3, 20, 69,225,204,153, 51, 72, 79, 79,151, 23, 20, 20,200,191,253,246, 91,113,108,108,172,132,206,156,216,179, +103, 79,164,166,166,218,149, 55,117,234,228, 20, 69,121,150,164,172,248, 50, 4, 66,127, 52,110,250,138, 60,168,113, 47,185,151, +119,235,131,223, 47,253,105, 20, 45,111,251,199,238,216,113, 90,139,186,148,158,204,204, 76, 4, 6, 6,162, 95,191,126,228, 75, + 47,189, 4,149, 74, 5,165, 82,137,149, 43, 87,122,118,232,208,225, 13,185, 92,190,223,145, 54,113,243,102, 38, 90,181,108,142, +183,222, 26,237,254,249,191,103,161,180, 74,129,146,210, 18,196,124,244, 21,190, 26, 51, 8,131, 90, 6, 55,136,252,151, 47, 95, +142, 46, 93,186, 96,197,138, 21,172, 18,240, 24, 97, 57,238,111, 15,143, 45, 19,160, 43,103, 21,152,146,251,184, 36, 19,160, 61, + 88, 39,226,113,133, 18,224, 74,178,118,181, 60, 87,188,106,184, 32, 61,176,149, 2, 65,212,225,177,112, 8, 51,102,204, 72,177, +254,157,229,177,159,127,254,153,145, 76,250, 58, 91,215, 51,149, 65, 99,211,246,157, 41,243,223,153, 0, 67, 90, 34,114, 20,128, + 39,225,134, 86,158, 28, 20, 24, 9,112, 5, 60,164, 22, 25,161, 33,129, 32, 1, 23, 33, 61, 7,224,227,165,235, 83,234, 83, 0, +244,122, 61,184, 92, 46,218,180,105,131, 30, 61,122,160,178,178, 18, 26,141,198, 60, 63, 95,167,211,193,223,223, 31,253,250,245, +195,254,253,251,205, 67, 2,182, 96, 52, 26,205, 89, 4, 59,118,236, 8,147,155, 30, 26,141,198,220,158,105, 79, 66,199,142, 29, + 81, 86, 86,134,234,234,234, 58,219,178, 53,153,159, 60,121, 50, 37, 42, 42,234,213,206,157, 59, 31,183, 72, 4, 84,209,191,127, +255,227, 66,161, 48, 90, 42,149,106, 28, 41,203,147, 39, 79,198, 71, 69, 69, 85,118,238,220,121,159,133,188,146,254,253,251,175, +252,248,227,143, 25,103,235,153, 62,125,122,202,154, 53,107, 36,195,134, 13,195,157, 59,119,228, 55,110,220, 64,110,110, 46,188, +188,188,228,190,190,190, 24, 50,100, 8,126,254,249,103,244,236,217,147,241,189,189,255,254, 59, 41, 63,255,188, 73,162,209,148, +193,215, 47, 84,238,233,213, 2, 94,222, 45,161,172, 42,216,191,120,201, 6, 68,189, 53, 24,219, 63,118, 55,151,147, 45,139,109, +196,136, 17, 72, 76, 76, 68,126,126, 62,167,172,172, 12, 26,141, 6,169,169,169, 60,147,210, 89,121,250,244,105,135,218, 67, 68, +196, 8,236,221,187, 31,149, 21,165,200, 47,188,135,143,103,252, 75,247,201,103,139,248, 99, 94,237,131,126,218, 74,192,205, 57, +122, 24, 62,124, 56,245,197, 23, 95,152,211, 65,135,132,132,224,187,239,190, 3, 0,234,208,161, 67,108,218,240, 39,164, 20, 60, + 73, 5,128, 24, 63,126,188,165, 11,141,176,114,247, 19,142,186,255, 93, 65,238,102,146, 47,217, 0,123,217,246, 28, 9,254, 43, + 41,217, 0, 75, 87,188, 37, 49, 91,187,236,153,144,118,201,134, 18,151,202,123, 6,240,143,234, 36, 90,247,145, 72, 46,105, 13, +242,226,227,199,224,102, 80,227, 82, 21,133,228, 42, 3,248, 4,129, 0,138,130,164,137, 47,252, 26, 7, 73,154,191, 44, 6, 54, +237,180,235, 1,104,221,186, 53,122,245,234, 5,181, 90, 13,189, 94, 15, 62,159,111, 38,108,218, 74, 15, 10, 10, 66,223,190,125, +145,148,148, 84,175, 7,128,199,227,161, 91,183,110, 32, 8, 2, 42,149,202,236, 93,160,149,118, 58,187, 32, 73,146,232,218,181, + 43,254,248,227, 15, 56, 18, 92,185,125,251,118, 57, 0, 66, 38,147, 17, 0, 60, 81,147,109, 47, 87, 42,149,234,157, 41,203,237, +219,183,239, 55,201,243, 4,224, 15,160, 76, 42,149, 58,156,155,120,250,244,233, 41, 0,176,106,213, 42,137,155,155, 27,178,179, +179,225,239,239, 47, 7,128,130,130, 2, 12, 31, 62, 28,203,150, 45,115, 72,230,148, 41,147, 82,100,178,117, 98,157, 78, 33, 17, + 85,230,200,189,125, 67,224,238,217, 20,238,158, 77,113,228,216, 3, 16,131,234,183,184, 55,111,222, 76, 76,157, 58,149, 42, 43, + 43,195,136, 17, 35,116, 1, 1, 1,124,146, 36,145,155,155,235,176, 71, 12, 0, 54,109,218, 76, 72,165, 49,148,247,181,116,204, +152,241, 62,154,135,182,231,127, 55,235,125,114,211,234,205,156,149, 92,141, 83,117,121,248,240,225,212,252,249,243,225,235,235, +139,194,194, 66,136, 68, 34,144, 36, 9, 15, 15, 15,124,243,205, 55,172, 18,240, 24, 16, 22, 22, 86,167, 23,128,105, 42, 96,151, +227, 41,159, 85, 64,148,108, 40,177,121,194, 73,235,159,216, 80,242,176, 60,107, 75,157,118,221, 51, 32,109, 87,203, 99,241, 20, +193, 68, 54,196,155, 17,195,197, 62, 6,173,156,123, 55, 27,237,244,247,224, 21, 16,140, 62, 93, 59, 32,160, 89,160,228,211, 53, +219, 82,118,164, 77,183,235, 69,107,211,166, 13,250,245,235,103, 30,143,231,114,185,208,106,181,230,212,189,150,195, 4, 45, 90, +180, 64,223,190,125,145,146, 98,187,233,137, 68, 34,132,133,133,129,199,227, 65,167,211,153,127,103, 57,117,208,114, 33, 32, 14, +135,131,238,221,187, 35, 61, 61,221,225, 50, 48,121, 7,170, 76, 91,131, 97, 34,253, 6, 47, 74, 96,242, 16,153,219,225,154, 53, +107,196, 42,149, 10, 90,173, 22, 29, 58,116, 64, 92, 92,156,220,177,251,138, 73, 1, 0,153,108,157, 68,173, 46,134, 64,224, 7, + 55,190,151,156,195,225, 97,107,252, 65,201,219,209, 17,245,202, 91,191,126, 61, 33,147,201,136, 31,126,248,129, 84,171,213, 0, +128,208,208, 80,135,210, 47, 91, 66, 38, 91, 71,252,252,243,250,225,147,191,248, 33,177, 70, 30,197, 9, 13,125, 1,161,111,188, +241,246,140, 25, 51,226,157,145,185,100,201, 18,182, 81, 63, 37, 74, 64,125,228,255, 88, 21,128,103, 21,174,156,246,103, 77,204, + 13, 37,106, 23,202,115,181,194,192, 42, 32, 78, 96,231,193, 67, 41,181,202,174, 50, 23, 39,239,228, 50,254,125,100,100, 36,252, +252,252,204, 17,254, 36, 73,154, 93,248,180, 7,128, 14,250,163, 87, 4, 12, 9, 9, 1, 65, 16,216,177, 99,199, 67,242,150, 47, + 95,142,132,132, 4,243,181, 70,163,209,238,114,192,124, 62, 31, 61,123,246, 4,147,232,248,103, 88, 89,107,112, 93,167, 21,129, + 26, 82,223,128,154,112, 44, 82,206, 68,158, 73, 89, 34, 0, 96,205,154, 53,212,244,233,211,137, 99,199,156,159,154, 63,101,202, +212, 67, 38,175, 9,135, 36, 73, 35,135,195, 17, 57, 58,252, 66,131,181,238,159, 46, 37,192,110, 71,237,236, 58,194, 44, 88,176, + 96,193,130, 5,139,103, 23, 28,182, 8, 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88,176, 10, 0, 11, 22, + 44, 88,176, 96,193,130, 85, 0, 88,176, 96,193,130, 5, 11, 22,207, 5,106,205, 2,184,120,241,162,211, 17,156,182,130, 9, 89, +121,172, 60, 86,222,115, 41,143,122,253, 13, 41,126,255, 77, 6,153, 76,198,177,149,173,143, 45, 63, 86, 94,203,150, 45,205,215, +228,230,230, 18, 79,155,188,231,253,125, 56,172, 0,208,141,187,158,235,157,185,193,103, 89,158, 51, 50,159,246,231,173, 5,153, + 76,198, 7,224, 13,192,221, 84, 31, 72, 0, 37,206, 36, 79,121,196,160, 92,245,204,117,148,233, 19,153,190,180,116,233, 82,241, +153, 51,103,228, 39, 78,156, 0, 0, 12, 28, 56, 16,125,250,244, 97,156, 74,248, 73,188,135,215,223,144, 98,196,240, 30, 6, 64, +202,147, 74,165, 36,216,105,159, 44,172,208,178,101, 75,106,212,168, 16,243,254,254,253,160,236,145,182, 61,121, 11, 22,244, 55, +239,127,251,237,201, 6,201, 99, 81,183, 2, 0,106,215,195, 11, 64, 16, 19,202, 27,242, 63,132, 19,196,251,216,228,217,122,222, + 6, 62,243, 83,253,188, 52,241, 95,189,116,114,227,174,237, 43, 7, 53,110, 22, 18,172, 80,232,225,227,227,134,251, 5,183,201, +206,157,187,149,201,100,178, 94, 82,169,244,142, 35, 50,165,147,186, 81,217,183, 51,113, 59, 71,131,188,123, 20, 90, 52, 33, 16, +210, 90,136,182, 33,161,144,109,202,120, 90, 26,171, 45, 69,130, 94,107,224,177,223,227,229,203,151,229, 97, 97,135,177,118,173, + 10, 41, 41,192,194,133, 71,144,151,151, 39, 31, 53,106, 20,132, 66, 33, 10, 11, 11, 37, 99,198,140,129, 43, 20,130,183,223,126, +155, 82, 40, 20,146, 33, 67,134,224,163,143, 62, 74,113,162,206,112,164, 82, 41, 70, 12,239, 65,198,196,196,240,128,117,248,253, + 55, 64, 38,147, 17, 76,115,246,179,248,231, 64,167,155,143,164,164, 24, 12, 27,182, 14,163, 70, 45,193,254,253, 53,109,207, 89, +226,190,121,115, 14,126,253,117, 12,198,142,221,139, 5, 11,106,148,128,134,200,123,222,193, 38, 2,114,132, 97, 45,200,158, 32, + 0,114,167,223,115,251,172, 43, 87, 44,123,231,192,190, 95, 98,219,181,107,223, 97,236, 27, 3,209,162,153, 55,124,125, 4, 40, +175,208,160,224, 94, 11,206,173,236,242,192, 3,251,126,145,175, 92,177,236,135, 15,103,206, 89, 97, 79,222,199, 31, 78, 20,223, +201, 60, 32, 47, 42,204,192,155, 17, 64,223,112, 32,164, 21,144,149, 67,225,212, 57, 53, 18,229, 25, 24, 61,212,155,106, 19, 58, + 82,242,227,202,109,206, 18,153, 43, 45,127,194,134,236, 39,162, 4,148,149,149,225,163,143, 84, 8, 10, 2, 34, 35,129,197,139, +171,113,225,194, 5, 24, 12, 6, 8,133, 66, 52,106,212, 72,126,224,192, 1, 76,157, 58, 85,178,126,253,122,135,202,110,250,244, +233,226, 43, 87,174, 32, 56, 56, 88,190,123,247,110, 98,235,214,173, 0, 32, 79, 78, 78,198,251,239,191,143, 13, 27, 54, 56,250, +172,124, 0, 72, 60,116,158, 3,172, 35,107, 62, 31,206,241,207,130,181,254, 1, 96,220,184, 61, 72, 74,170,249,140,137,185, 13, +218, 35,224,168, 55,128,150,247,206, 59, 91,240,235,175, 53,159, 99,198,156, 4,237, 17, 96,189, 1,245, 19,191,229,113,107, 37, +128, 13, 2,180,225, 5,120,158,201, 95, 38,147,241,142, 38,237,250, 92, 50,160, 71,135,177, 17,161,232,214,185, 17, 2,252, 68, + 32, 64,192,219, 83,128,208, 16,127, 12, 25,216, 26, 3,251,117,111,117, 52,105,215,231, 50,153,172,177, 61,153,119, 50, 15,200, +251,135, 87, 98,215, 74, 96,114, 36,208,193,228,249,243,112, 7, 58,182, 3,190,156, 13,244,238, 86,137, 59,153, 7,228, 13,121, + 69, 13,245,122,216, 81, 36,158, 72, 7,226,239,239,143, 3, 7, 68, 40, 46, 6, 18, 18,128,242,114, 30,218,181,107,135,145, 35, + 71,210,203,189, 34, 37, 37, 5,233,233,233,242,165, 75,151,138,153,202, 29, 54,108,152,248,234,213,171,114, 62,159, 47, 47, 47, +175,237,201, 82,171,213,216,176, 97, 3, 36, 18,137,163,229, 73, 2,192,239,191,201,144,120,232, 60,231,247,223,100, 13,122,246, + 41, 83,166, 80,244, 86,223, 49,134,245,130,114,226, 88,189, 88,183,118,173,120,221,236,217,226,139, 83,167, 82,121, 35, 70, 80, +103, 39, 77,162, 86,125,244,145,120,221,218,181,226,134, 60,115, 67,235,140, 45, 25, 76,143, 61,106,121,180,235,127,212,168, 16, +196,196, 36,213,250,164, 49,106, 84, 72,173,241,124,123,242, 22, 44,232,143, 5, 11,250, 99,204,152, 95,107,125,210, 88,176,160, + 63, 99,121,255, 36,132,133,133,213,218,108, 41, 7,172, 2,240, 52,176,192, 99,196,213, 75, 39, 23,183,107,215, 46,180, 87,143, + 38,181, 43, 2,135, 0,159,207,133, 72,200,131,155, 27, 7, 33,109,252, 16, 18,210,174,209,213, 75, 39, 15,200,100,178, 58, 61, + 69,210, 73,221, 40, 46, 42, 49,123, 50,160,209, 2,119,242,128,114, 5, 80, 81, 9,108,219, 7,204,252, 2,136, 93, 10,244,233, + 1,112,168, 74, 72, 39,117, 99, 27,170, 5,186,118,237, 42,249,253,247,142,104,212, 8,152, 56,145,135,198,141, 95,194,192,129, + 3, 37, 7, 14, 28, 32, 70,142, 28, 41, 25, 54,108, 24,130,131,131,113,254,252,121,236,220,185, 83, 62,110,220, 56,241, 79, 63, +253, 84, 47, 1,245,239,223, 95,172,213,106,229,110,110,110,245,254,183, 92, 46,199,160, 65,131,152,144, 25, 21, 29, 29, 77, 73, +165, 82,157, 41,102, 4, 22,228, 79, 0, 64,116,116,180,195, 10, 90, 90, 90,154,121,171,239,152,147,205,150,104, 72,243, 94,183, +118,173,184,237,141, 27,242, 49, 23, 47,202, 91,100,102,129, 95, 89,137, 38,153, 55, 32,254,227,172, 60, 40, 35, 67, 46,115, 82, + 9, 72, 75, 75,195,148, 41, 83,168,153, 51,103, 58,173, 68,208, 50,152, 28, 99, 42,207,154,232,153, 28,179, 7,154,244,233, 79, +221,168,118, 13,106, 43, 52,233,211,159, 55,123, 5,177, 29, 72, 61,196,207, 4,207,170, 2, 64,217,216, 92, 38,248, 17,222, 31, +229,226,219,164, 28, 45,139,171,215, 50,134,135,134,248,155, 73,223,214, 50,205, 66, 1, 15, 6, 3,137,208, 16,127, 92,189,150, + 17, 2,192,167, 46,121,217,183, 51, 17,241,106,205,247,195,169,192,251,159, 1,107,183, 1,133, 15,128, 27, 89,192,133,171, 20, +146, 79, 3,199,206, 0,195, 6,214, 92,223, 0,221,140,120,132,175,248,137, 40, 38,243,230,205, 75,169,174,174,137,183,156, 56, +113, 34,206,158, 61, 75,200,100,178, 20,250, 92, 89, 89,153,164, 99, 71, 30,166, 78, 5,186,119, 63, 7,163,241,134, 60, 63, 63, +191, 78, 79,202,244,233,211,197, 4, 65,200,153, 46, 14, 83, 84, 84,100,215, 43, 19, 29, 29,141,248,248,120, 0,160, 82, 83, 83, +117, 22,239,130,160,137, 63, 62, 62, 30,209,209,209, 79,178, 63,112,246,152, 77,104,175, 92, 65,155, 63,255, 52, 45,130,164,131, +129, 36, 65,234,141, 32,245, 6, 4,157, 76, 69, 37,195,245,214,235, 34,220,191,254,250, 75,254,202, 43,175, 60,114, 37,192, 25, +239, 66, 67,201, 95, 55,170,157,205, 45, 41, 38,201,169,123,186,217, 43,200,230,246,235,152, 95, 89,182,111, 32,108, 42, 0,196, +132,242,135, 54,103, 9,135, 1, 33, 58, 42,143,168,103,123, 42,148, 13,106,151,159,205,173, 1,202,203, 67,215,219,249, 15,155, +144,201,100,188,198, 77, 67, 58, 53,109,236, 9,138, 2, 82,207,228,225,240,177,108, 28, 62,150,141,162, 18, 21, 40,138, 66,110, +126, 37,153,114, 58, 23, 89,119,202, 17, 24, 32, 66,211,166,237,124, 81,179, 68,171, 77,220,206,209,160,111, 56,160,213, 3,135, + 78, 0,242,179, 20, 86,108, 6,110,100, 3,131,250, 1, 29, 66, 8,240,184, 53, 75,139,247, 14,171,185,158,225,179, 58,243,157, +169,165,104,203, 61,252,196, 28, 64,166,229, 92,241,226,139, 47, 74,172,207,113,185, 92,121,167, 78, 69, 88,184, 16,248,207,127, + 40, 52,109,154,137,156,156,156, 58,101,105, 52, 26,187,150,191, 37,234,147, 69, 35, 62, 62,158, 38,123,179, 34, 64,111, 22,196, + 79,152,174,123, 18, 78, 59,235,246,207,244, 88,157,104, 95, 82, 42,215,233,245,208,233,245,208, 25, 77, 43, 40,146, 36, 72,163, + 17, 70, 35,137,230,247,238, 53,100, 56, 11, 42,149, 10, 74,165, 82, 62,101,202, 20,106,234,212,169, 13,242, 38,184, 74, 9,112, +149,229, 79, 19,253,184, 61,127,127,167, 63,157,241, 2,208, 68,255,206,150,191,191,211,159,172, 23,192, 62, 44,151, 6,102,180, + 28,112, 93,179, 0, 26, 48, 59,160,174, 40,118,103,162,219,169,122,254,131,114,224,255, 25, 61,183,141,223, 50,106, 92,245, 4, + 21, 58, 35,175,206,223,208,255, 67, 0, 32,119,217,141, 93, 32,107,162,253, 5, 0,128,188,194, 74,168,213, 6, 0, 64,187,182, +126, 8, 10, 16, 33,227,106, 17,231,230,173, 50, 8,133, 92,132,180,241, 69,185, 66, 7, 0,117, 10,206,187, 71, 33,164, 85,205, +255,191, 54, 0, 8,235, 68, 64,192, 7, 12, 6, 96,104,127,192,215, 11,200,206, 5,134, 13, 0, 90, 53,175,185,254, 9,163, 46, + 37,224,185, 24,253, 41, 42, 42,114,168, 29, 86, 85, 49, 95,125, 55, 62, 62,158,136,142,142,166, 76, 74,128,165,119,224,137,151, + 93,219,182,109,169,236,236,108,194,217,243,214,112,187,157, 5,173, 94, 7,130,203,131,145,162, 64, 0, 48, 24, 73,232, 13, 36, + 40,163, 17,196,173,155, 46,185,239, 43, 87,174, 32, 48, 48, 80,254,221,119,223, 73, 62,253,244,211, 20,103,149, 0,235, 97, 20, + 71,137,219, 85,228,159,155,155, 75,180,108,217,146, 26,183,231, 97,133, 96,216,186, 97,224,239,207,194,254,253,183,205,145,251, +246,198,238,105,121,239,108,121, 88, 33, 24,187,119, 44, 94, 72, 43,198,183,223,158,100, 44,239,159, 72,254, 52,158,167, 89, 0, +245,145,168,195, 4,219,192, 41,142,117,203,125,196,179, 9,136, 9,229,142,254, 7,225,227,227,134,242, 10, 13, 2,253,221, 17, +249,255,237,125,121, 92, 84,213,251,255,251, 14, 48, 12, 48, 40,184, 34, 26, 9,238,226, 26, 46,168, 89,140,185,141, 8,184,145, +125,202,210,180,152,248,148, 89,185,160,150,102,125,234,167,144, 38,159, 44,117, 76, 83,250,182,104, 35, 26,226,134, 81, 67,105, +106, 37,110,185,148, 2, 38, 38, 34,137,178, 13, 51,204,114,207,239,143,153,139,151, 97,150,123,103, 6,177, 62,247,253,122,241, + 98,230,204,153,103,206, 61,231,222,243,126,158,231, 60,231, 57,241, 61, 97, 52,209,240,245,245,130,151, 72, 4, 66, 8, 38,142, +237,130,216, 49, 93, 64, 81, 64,249, 29, 45, 90,182,244, 1,128,219,246, 4, 62,208,129, 66,225, 85,130,158, 93,128, 81,195,204, +157,253, 91, 1,208,175, 39, 16,220, 2,144,199, 0, 52, 13,120,123, 1,151,174,152,235, 23, 93, 35, 92,199,150,207,107,119, 31, +252,102,217, 6,184, 97,195,134,152,213,171, 87,163,176,176, 16, 63,252,240,131,250,189,247,222,147, 73,165,210,250, 99,103, 77, + 38,147,236,194,133,118,234,183,222,186, 14,138,162, 80, 86,214, 29,221,187,119,198,165, 75,182,151, 82,104,154,182, 89,254,216, + 99,143, 53,234, 31, 66, 8,190,251,238, 59, 94,215,204, 86, 2,238, 39,242,247,132,146,192,198,237, 78, 29, 33,254,237,119, 16, + 31, 64, 76, 19, 80, 20, 96, 48, 25,161, 39, 38,212, 26,141,208,118,237, 9, 92,248,205,237,182,247,233,211, 7, 20, 69,185, 68, +254, 0, 48,100,200, 16,108,222,188,153,234,215,175, 31,113, 84,230, 12,155, 55,111,166,172, 9,223, 86, 25, 31, 36,229,220, 37, +126, 0, 16,103, 23, 52,248,156, 9, 24,204,206, 46,228, 36,111,242,174,187,196, 15, 0, 61,126,254,171,145,188, 37, 75, 70, 98, +229,202,195, 2,243,115, 32,127, 64, 8, 2,180,229, 30,100,187, 9,221,154,220, 8, 1, 68,211,239, 52, 89,163,201, 87,193,230, +223,224,174,192,120,151, 94, 47,188,117,237,186,217,234,123,127,195, 47, 56,125,174, 12, 6, 3, 13,154, 38, 22,165,133,170,143, + 13,184,118,189, 26,165,215, 11,175, 0,176,107, 86,118,233, 44,193,143,249,230,215,109,162,128, 83,231,129,164,127, 1, 93, 31, + 52,187,253,223,249, 16, 16,251, 0, 34, 17,240, 99,190,185,190, 27, 4,237,233, 24, 10,235,241,190,231,214,195,133, 11, 23, 32, +145,152,251,100,223,190,125,248,252,243,207,213,121,121,102, 46, 88,189,122,117, 76,171, 86,173,212, 23, 47, 26,241,241,199,192, +169, 83,131,224,229,213, 83,214,169, 83, 39,153, 61,121, 1, 1, 1,156,127,219,104, 52,254,237, 31, 92, 54,249, 71, 68, 68, 16, +123,127,124,149,133,194,182,237,100,119,244,117,168,210,235,161,213, 27, 80,103, 52,194, 64, 76,168, 53, 24, 80,173,215,163, 36, + 52, 84,230, 78,187,253,253,253, 17, 16, 16, 32,219,188,121, 51,197,119,123,167, 53,209, 59, 43,227,163, 4, 12, 25, 50,196,105, + 25, 23, 47,128, 61,242,103, 91,255,124,228,217, 35,127,182,245, 47,128, 31,249, 11, 10,192, 61, 64, 83,111, 41, 36, 95, 5,131, +128,179,162, 97,140,140,236, 95, 82,112,229, 14,104,154, 96,241,188,104, 92, 42,184,141,139,151,202, 65, 81,104, 16, 16, 72,211, + 4, 5, 87,238, 32, 50,178,255, 57, 0,118,253,196, 17, 93,186, 99,223,119,128,201, 4,144, 34, 64,125, 12,200,254, 22,144, 63, + 11,200,158, 4,242,142,155,235,153, 76,192,190,239,204,245,155, 17, 4,142,115, 1,220,115,220,190,125, 91,221,171,215, 21,252, +252, 51,112,236,152, 9,157, 58,157,197,169, 83,167,212,113,113,113,100,239,222,189,234,156,156, 28,220,188,121, 19, 15, 61,244, + 16,166, 79,159, 46,203,204,204,204,115,148,196,135, 16, 34,179,231, 5,176, 6,163,120,240, 5,179, 4,192, 94, 10,104, 46,176, + 45,250,162,162, 34,202,222,159,173,250,142, 16, 60,112, 32,202, 71, 62,130,219, 90, 29,238, 24,234,160, 51, 26, 81, 99, 48,161, + 82,175, 71,245,168,199,208, 38, 42,202, 69,175, 32,133, 33, 67,134,160,111,223,190,178, 99,199,142,229,185, 35,131, 77,244,182, +202,220, 81, 2,216,115,129,173, 50, 46,176, 69,254,140,165,110,157, 41,144, 11,108,145, 63, 91, 30,123,107,160, 64,254,206,201, + 95, 80, 0,254,238,110, 11, 38, 72,147,227, 50,128, 66,161, 48, 69,246, 27, 57,170,176,176,224,183,159,242, 75, 64,211, 4,242, +209, 17, 56,123,190, 12,239,190,127, 12,239,172, 57, 90, 79,254, 63,229,151,160,176,176,224,106,100,191,145, 47, 41, 20, 10,131, + 61,153,202,109,103, 40, 19, 90, 96,237, 39,102,146,223,248, 14,240,233, 46, 64, 22, 13, 12,236, 13,228,125,105, 46, 95,251, 9, + 96, 66, 11,119, 50, 2,186, 27,232, 73,156,200,105,150,181, 67,141, 70,131,190,125,117, 24, 60, 24, 24, 60, 24, 24, 52,136,160, +168,168, 8,217,217,217, 56,126,220,172, 61,197,196,196, 32, 42, 42,138, 83,122,224,204,204,204, 60, 46,196,110, 52, 26, 17, 24, + 24,200,219,138,181, 68,253,215, 71,252, 51,239, 93,181, 96,153, 63, 71,101,124,148, 0, 79,212, 3, 0, 69,114,114,158,126,232, + 80,217,197,177, 99,100,165, 61,122,160,212,199, 7,165, 61,123,226,210,184,113, 50,211,176,104,153,194,178, 68,195, 23,131, 7, + 15,134, 59, 86, 63, 91,134,179, 50,174,125,104,203,234, 31, 60,120,176,211, 50, 87,192,228, 8,184,155, 20,168,208, 45, 11,158, +201, 17,192, 74, 10, 36,120, 4, 56,146, 63, 32,100, 2,108, 82,203,252,126,252, 13,133, 66, 81,254,225,186,247,211,115, 14,238, + 88,248,231,141,234, 46, 93,195,131, 17, 59,182, 11,130,131, 36,184, 83,161,195,169, 95,111,162,224,202, 29, 20, 22, 22, 28, 29, + 55,126,250, 46, 0,215,156,201, 12,239, 62, 81,118, 56,127,175,250,104,126, 21, 98, 71, 1, 31,175, 52,103, 2, 44,188, 10,108, +249,202,108,249,155,208, 2,225,221, 39,202,112,232, 11, 79, 16,184,167,191,219,108,187, 0,110,220,184, 33, 11, 14,110,163, 62, +113,194,108,213, 92,186,212, 2,131, 7,247, 70,235,214,173, 33,145, 72,112,227,198, 13,217,196,137, 19,121,165, 2,238,220,185, +179,236,247,223,127, 87,219,179,216,140, 70, 35,186,118,237,138, 45, 91,182,240, 34, 33,235,181,127,214,123,226, 74, 44,128, 45, +107,213, 85, 11,214, 25,185,243, 33,127,182, 18,208,224,190, 56,123,214,237,241,118,215, 66,231,211,111, 92,127,203,211,242, 28, +145, 63, 27,250,184,174, 0,199,245,127,123,228,207,134,176, 35,192,190, 39,192,158, 98,224,109,207,178,228, 83,206, 99, 2,246, +148,213, 69, 92,252,236,158,180,207, 73, 63,121,164,125,238, 4, 46,190, 52,247, 53,165, 82,169,220,126,254,236,225,245,187,179, +190,143, 8,233,216, 37,154,117, 22,192,241,200,200,254, 63, 79,140,159,189, 84,161, 80,104,184,200,179,164,247,165, 20,179,250, +147, 29,251, 46,225,255,125,100,231, 44, 0,215,201,223, 35, 14,147,251,141,252, 1,224,137, 39,158,192,153, 51,103,240,236,179, + 39, 0, 0,131, 6, 13,194,227,143,247,151,189,250,234,171,245,228,252,227,143, 63,242,146,185, 97,195,134, 60, 0, 84,108,108, +108, 76,117,117,181,218,203,203, 11, 34,145, 8, 70,163, 17, 98,177, 24, 82,169, 84,230, 46,249, 3,240,136, 18, 32,224,159,137, +226,226, 98, 42, 39, 41,135,132,206, 13,149,161,179,237, 58, 37, 73, 57,106,174,214,122,113,113, 49,181,107,242, 46,210, 45,181, +155,236,215, 32,219,117, 46, 79, 62,172, 22,172,127,126,240,230, 49, 81,122,122,226,109, 10,121,212,125,222,190,251, 65, 30,227, + 9,168, 84, 42,149, 51, 34,251,141,100, 50,198, 72, 1,180, 1,112, 3,128,214,114,202, 27, 47, 88,187,247,139,174, 17, 20, 93, +211, 2,135,207, 52,119, 63, 80,247,186,127,185,194, 66,244,245,109, 56,119,238,156,199,100,239,219,183, 47,207, 83,215,199, 90, +247,167,172,202, 41, 88,242, 1, 8, 16, 96, 77,218,197, 11,139, 61,246, 76, 23, 23, 23, 83,197,255, 42,198,253,250, 44,223, 47, +224,154, 5, 16, 0, 40, 87,207, 17, 22, 32, 64,128, 0, 1, 2, 4,252,125, 33, 4, 1, 10, 16, 32, 64,128, 0, 1,130, 2, 32, + 64,128, 0, 1, 2, 4,131, 1, 0,215, 0, 0, 32, 0, 73, 68, 65, 84, 8, 16, 20, 0, 1, 2, 4, 8, 16, 32, 64,128,160, 0, + 8, 16, 32, 64,128, 0, 1, 2,254, 25,104,176, 11,224,244,233,211, 46, 71, 81,218, 10, 38, 20,228, 53,153, 60,167,135,216, 52, +167,188,196,196,196, 24, 0,106,149, 74,229, 17,121,211,167, 79,143,161,105,218, 99,242,132,251,175,121,228, 37, 39, 39, 79, 87, + 40, 20, 95, 53,101,251,148, 74,165, 15, 0,137,229,158,214, 1,160, 1, 16,133, 66, 65,132,241, 16,228,253, 47,201,243,148, 7, +128,112,248,227, 3, 79,203,187,103, 32,183,211, 8,169, 73,231,220, 62, 11, 17,122,236,122, 89,242,176,102,205, 26,153,131,254, +228, 45,239,220, 71, 45,224,174, 60, 6,147, 6,239, 87,135,183,200, 6, 0, 68, 69, 69,185, 61,158,221,219,239,192,131,109,191, +133,159,159, 31, 70,143, 30,125,223,220, 31, 74,165,178, 45, 21, 32, 61,168, 84, 42,219,122, 72, 94,152,200,215, 63,199,158, 60, +165, 82,233,163, 84, 42, 41, 39, 50,124,152,182, 73, 36,254, 7,149, 74,101, 91,165, 82,233,229,236,123,174, 60, 14, 46,220, 27, +199,154,106, 44, 54,109,218, 52, 97,243,230,205, 11,124,124,124,118,139,197,226,124,177, 88,252, 27, 0,165,151,151,151,138,162, +168,245, 74,165,178, 77, 19,244,129, 0, 1,141, 80,187,104, 17,241,240,131,214,100,115,158,179, 76,128,132, 16,251,191,205, 51, + 55, 52,177, 8,244,148, 60, 94, 22,172, 39, 49,109,218, 52, 82, 80, 80,224,148, 92, 85, 42,149, 58, 37, 37, 5,237,218,181,179, +153,114,117,254,252,249,156,207, 20,103,228,173, 89,179, 70, 54,127,254,124,245,241,227,199,213, 86,138,128, 75,242,232, 11,203, + 33,234,253, 54, 62,253, 78, 15, 0,160, 47, 44,191,171, 29,246,126,155, 87,191,124,249, 94, 0,161, 9,176,253,160, 89,150,252, + 81, 31, 68,118, 61, 15,192,172, 4,228,231,231,243, 26,155,180,143,100, 49, 21,127,148,163, 70, 31,172,214,212, 5, 64, 62,174, + 2, 29, 67, 40,132,135,207, 36, 85, 85, 58,236,216,177,163, 89, 39,244,228,121,243, 94, 6, 77,143, 77,158, 55,239,101, 0,203, +220,150, 55,119,222,243,132,166,199, 36,207,181, 45,207, 81, 74,102,118, 29,165, 82, 73,205,157, 59,239,101,154, 54,141,157, 59, +119,222,203,122,189,110,153, 13, 69, 65,228, 74,174, 7, 55,161,103,223,127, 59,119,238, 84, 79,153, 50, 69,150,153,153,153,231, +142,208,205,155, 55,203,189,189,189, 31,241,246,246,126,194,203,203, 43, 88, 36, 18, 73, 83, 83, 83, 69, 11, 23, 46,156,109, 50, +153, 96, 52,227, 9,147,201, 20,167, 84, 42,127,180,120, 3,244,150,249,175,201,151, 65,227,227,227, 9,215,249, 46, 43, 43,139, +215, 61,157,144,144, 64,220,249,190, 0,207,195, 47, 45,205,163,242,180,139, 22, 1,110,200,100, 50, 2,242, 61, 14,216, 41,249, + 71, 69, 69, 33, 63, 63,159, 15, 57, 59, 36,121,142,242, 26,201, 79, 73, 73, 65, 81, 81, 17, 44, 46, 98,143, 29,235, 74, 74,162, + 8,252,186,131, 10,254,146, 2, 0,170,213, 34,106,218,180,105, 78,181, 49, 54, 89,151,149,149,169,237,145,127, 74, 74, 10, 82, + 83, 83,121,145,191,229, 61,162,163,163,101,209,209,209,110,201, 99,200,158,249,191,234, 63,104, 64,254,139,166, 74,144,150,169, +227,212, 87,219,211,165,164, 79,184, 8, 26, 45,193,107, 79, 75,112,252,188, 17, 90, 13, 65,173, 30,144, 13, 56,143,243,151, 76, +136,138,138, 34, 92,149,128,148, 55,122,146,194, 83, 85, 8,108, 33, 70, 72, 7, 41,218,182,239,138,171,133,122,116,238,109,128, +143,164, 12,185,187,111, 97,252,248,241,228,224,193,131,205, 53,225,249,182,106,221,122,222,103,199,127,166,228, 61,186,189, 12, +224, 29, 0,117,238,200,107,221,170,245,188,237,223, 29,167,198, 12,232,225,150, 60,133, 66, 33, 14, 9,233, 48,239,144,250, 48, + 53,168,127,164, 77, 89,205, 64,254, 0, 80,127,252,160, 74,165, 82,199,197,197, 33, 51, 51, 83,109,235,121,253,229,151, 95,200, + 91,111,189,133,189,123,247, 58, 28,223, 45, 91,182,140, 18,139,197,125,196, 98,241, 92,177, 88,236,127,237,218, 53,116,235,214, + 13, 94, 94, 94, 8, 12, 12, 68, 65, 65, 1,164, 82,169,247, 47,191,252, 18,116,236,216,177,195, 47,190,248, 98,103, 0, 87, 1, +136, 97, 94, 30,176, 59,241,177,231, 63,246,188,197,148, 83, 20, 5,138,131,213,178,103,207, 30,187, 50,216,229,142,230, 91,123, +200,202,202,114,235,251, 77,170, 32, 39, 39,199, 88,178, 82,186,141,183,223,126,155,208, 52, 13,136, 42,160,175,211, 65,236, 43, + 1,232, 32,136, 68, 34, 44, 95,190,156, 58,102,197, 51,201, 14,100,157, 63,127,158,100,102,102,194,158,188,169, 83,167, 34, 50, + 50,146,114,181,125, 88,158,142, 21,111,191, 66,216,237,115,231,218,253,211,210,120,127,223, 94, 26, 96,174, 10, 0, 39,242,231, +138,148,148, 20,167,117,184, 16,151, 61,242, 95,181,106, 21, 22, 47, 94,108,173,116,184,212,233,228, 68, 20, 65,235,238,160,194, +191,164,216, 22,255,206,157, 59, 41, 0, 96,254,219, 91,115,177, 38,107, 71,228,111,241, 12, 56,181,218, 85, 42,149,218,218,194, +103,202,216,125,204, 87,158, 35, 11,127,209, 84,238, 39,197,101,166, 7,144,110, 15,138,224,231, 75,225,193, 80, 47,220,186, 67, +195, 96,244, 66,121, 5, 65,101, 13, 65,193,159, 52, 32, 2,218,248,159,101,250,199,225,164,176,244,245, 30, 49,221,187, 68,224, + 88,233, 77,132,135,181, 69,159,126, 17,240,242,109,133, 7,195,239,224,142, 86,135,178, 82, 19,254,188,169,131,191,119, 17, 39, +121, 77,132,167,158, 94,184, 80, 92,212, 33, 20,190, 81,131, 68,186,195, 63, 60, 5,224, 19,190, 66, 88,150,248, 83, 51, 95, 94, + 32,254, 83, 28, 2,105,247,135, 68, 85,231,142,184, 36,143,105,219,139,243, 94, 21,195, 55, 16,225, 61, 34, 69,191,255,122,210, + 29, 89,158, 4,205,178,254, 33,145, 72,100, 0,212,214, 99,120,226,196, 9, 78,228, 15, 0, 62, 62, 62, 65, 18,137,100,214,173, + 91,183,252,187,119,239,142,129, 3, 7,194,219,219, 27, 31,124,240, 1, 76, 38, 19,250,246,237,139, 93,187,118,225,151, 95,126, +193,217,179,103,225,229,229,181, 94,169, 84, 38,108,216,176,193,145, 85, 93, 63,207,121,194, 99,169, 84, 42,101, 33, 33, 33,106, + 66,136,195,239,148,150,150,202, 20, 10, 5,223,251, 71, 22, 18, 18,162,118,245,251, 12, 81, 95,188,120,209,225,188,209,171, 87, + 47, 25, 95, 50,191,120,241,162,250,201, 39,159, 68,203,150, 45,101,238, 40, 2,138, 23,102,146,164,228,177, 8, 8,240,107,244, +153, 70,163,197,242,229,203, 49, 12,160,254,220,179,135, 92,139,143,183, 63,183,207,232,110, 30,204,149,147,209, 97,212, 68, 72, + 30, 26, 4, 83,247,200, 6,117, 12,219, 51, 16,188,114,242,221,186, 0,180,227,159,195,240,213, 95, 56,108,223,204,103,199,160, + 85,107,127,115,193,242,116,204, 95,240, 44, 0,224,118,121, 45,174,151, 20, 18,229,198, 12,151,149,128,218, 69,139,136, 43, 74, +128,171, 10, 0,225, 98,169,223, 47, 40, 42, 42,194,226,197,139, 93, 85, 32,236, 98,218,180,105,132, 10,221, 73, 77,155, 22, 78, + 84,155,134, 0,219, 30, 38,148,244, 21,167,131, 96,139,172,173, 73,217,209,178,128, 61,176, 21,138,227,199,143,171,163,163,163, + 27,184,254,249,202,251, 98,161,212,238,228,246,212,106, 13,103, 57, 27, 54,108,136,241,245, 90, 8,145, 8,240,247, 3, 42,170, +104,212, 17,130, 0, 63, 10, 58, 26,208,214, 17,116,106, 43, 2,109, 4, 46, 95, 51,161,168,168, 72,237, 72, 57,155,247,242,152, +152,240, 7,253,213, 98, 49,193,243,179,134,194,100, 34, 40, 45,211,163,248,122, 5,224,115, 13,126,193,117,184, 81,246, 7, 68, +226, 74, 92,184, 80,129,150,193,142,229, 53,157,249,223,106,249, 19,207, 60,227,251, 6, 13, 4, 47,126, 93,122,243,204,233,101, +116, 85,149, 43, 36, 75, 0, 64,210,178,213,242,127,205,120,198,119,245, 21, 19, 58, 77, 79,145,254, 94,116,118,153,169,182,161, + 60,165, 82, 73, 89, 7,179,217, 66,139,150, 65,203,159,154,241,180,239,217,226, 59,136,127, 50, 73,250,225,127,230, 47,211,214, +106,220, 85, 0,184,158,151,225,104, 44, 76,204, 51, 50,113,226, 68, 48,164,175,213,106,235,199,144,177,252,179,179,179, 57,141, +169,175,175,239,112,141, 70,211,179, 87,175, 94,144,201,100,152, 63,127, 62,230,204,153, 99,158,204, 13, 6,108,219,182, 13,249, +249,249, 56,121,242, 36,118,236,216, 1,173, 86,219,149,166,105,185, 19,139,221,163,247,211,190,125,251, 56, 45,205, 81, 20,197, +251, 94,102,203,118,229,251,150,103, 56,239,201, 39,159, 68, 73, 73,137,205,207, 67, 67, 67,225, 42,129,151,148,148,160,164,164, +196, 45, 69,224,236,153, 75,248,191,140,189, 24, 57,114, 56, 34,251,118,188,107,201,255,122, 29,135, 15, 31,197,176, 97,195,136, +106,201, 18, 92,139,143,135,223,136, 17,208,218, 57, 59,131,250,236, 18, 5, 0, 11,134,247, 33,253,202, 14,226,233,239,246,194, +212, 61, 18,218, 5, 43, 0, 0,126,171, 87, 64,122,233, 60, 22, 22,137,177,250,232,185,187,253,248,217, 34,135, 65,118, 76,251, + 70,143, 25,209,168,125,185,223,252,136,179,103, 46,185,117,255,184,178,164,192,118,247, 59,242, 6,120,243,181,216, 61, 77,180, +238,194,226,246,119,125, 86,139, 2, 65, 7,128,218,107,126,112,168, 65,249,212,180,105,225,245,131,189,115,231, 78, 10,155,134, + 16,107, 79, 0, 87,178, 46, 43, 43,107, 64,206,174,144, 53, 87,176,148, 14,167, 36,193,197, 93,200,114,255,219,172,188,113,227, + 70,242,215,249, 87,209,161,187, 23, 52,218,187, 85,180, 38, 2,157, 30, 48, 88,202, 12, 70, 2, 34, 50,191,254,245,108, 62, 18, + 19, 19, 99, 46, 95,190,108,243, 55, 3, 3, 43,213, 26,173, 8,109, 90, 5,161,226,118, 45, 42, 42, 43,112,252, 68, 41,174,223, + 36, 16, 7,212,162, 99,215, 26,104,107,111,161, 91, 63, 3, 58,247,170,195,142,143,243, 49,121,242,228,152, 43, 87,174,220,147, +251,205, 98,177,143,158, 56,117, 90,251,146,150,193, 40, 52, 2,126,163,199, 66, 20,220,186, 13, 93, 85, 53, 22,192, 33,134,172, + 1,248, 40, 20, 10,189,179,121, 31,192,152,184,201, 83,219,255, 37,106,137,171, 53, 6, 4, 61, 52, 26,222,129,193,109, 76,181, +119,229, 1, 0, 23,242, 7, 48,110,210,228, 41,237,137,151, 47, 42, 53,117,232, 19, 53, 12,210, 22, 45,219,104,107, 53, 13,100, + 53, 23, 24,235,159,162, 40, 76,156, 56,145, 0,192,222,189,123,145,152,152, 24,147,146,146,162,230, 67,254, 74,165,210,183,162, +162, 98,166,193, 96, 16,249,251,251,227,145, 71, 30,193,234,213,171,225,227,227, 3,133, 66,129,140,140, 12,228,231,231,227,248, +241,227,248,246,219,111,241,235,175,191,162, 77,155, 54,109,140, 70,227,131,176,227,254,103,187, 64,157, 45, 1,136, 68, 34, 78, +237,108,202, 37,128, 61,123,246,120,100, 9,160,101,203,150,178,146,146, 18,181,189,207,220, 29,119, 87, 20,129, 75,139, 22,145, +242,180, 52,224,216, 49,224,216, 49,220,158, 58, 1,107,250,119,175,119,217, 71,246,238,141,199,167,199,162,243,157, 91,184, 22, + 31,143,214,139, 22,161,123, 90, 90,163,229, 0,107,136,101, 15,163,187, 60, 6, 11, 23,189,131,247,112, 30,107,162, 71,161,207, +224,161,232,122,187, 8,219,130, 6,162,168,229, 77,100,100,100,144,153, 51,103,114, 26, 95,217,168,254,120,122,230, 68,252,252, +211,175, 56,152,115, 8,111, 2, 88,179,122, 43, 34,123,247,198,211, 51, 39,162, 86, 91,142, 23, 94,120,129,179, 60,107,184, 27, + 3,192,215, 3,240,119, 2,101,135,156,120,119,244,180,105,211,136,106,241, 21,192, 75, 12, 4,249, 0, 65,157, 65,237,180, 8, +227,184,246,223, 4, 32,108,171, 31, 0,216,150,191,141,201, 21,209,209,209, 50, 7,193,128,188,175,225,243, 5, 1,118, 61, 2, +129, 85,243,241,135,158,160,244, 22, 13, 64, 4,169,191,217,197,105, 48, 18,232,234, 0,157, 30,208,213, 1,122, 3,160,211, 2, +250,186,187, 94, 18, 91, 1, 41,159,127, 20, 64,114,143, 87,227,129,112, 41,136,143, 55,110,105,181, 80,127,127, 13, 23, 10,174, +227,246,237, 26, 68, 70,153,160,209, 25,161,171, 51, 65, 91, 75,163,180, 24,208,106,128,221,187,119,171,249, 28,128,225, 14, 20, + 10, 5,237, 21, 20,180,252,217, 37, 75, 36, 59, 88, 20, 18,188,228,117,233,237,197, 11,150,153, 42, 42, 14,177,200, 90,207,101, +140,189,165, 65,203,231,188,186, 88,114,224,186,169,190,176,211, 19,139,165, 87,183, 44, 89,102,172,169, 56,196,199, 11,224, 47, + 13, 92,246,242,107, 11, 36,133, 37,119, 79,139,140,123, 50, 73,186,125,211,154,101,181, 53,213,135,220,124,214,108,221, 75,124, +158, 53,194, 88,255, 18,137, 68,166, 82,169,242,152, 45,163, 90,173, 86, 61,104,208, 32, 62,178,140, 0,186, 2,160, 7, 12, 24, + 64, 75, 36, 18, 81, 70, 70, 6,102,207,158,141,149, 43, 87,130, 16,130,159,126,250, 9,223,127,255, 61,206,158, 61,139,202,202, + 74,116,235,214, 13, 85, 85, 85,254, 34,145,168,157, 51,225,147, 38, 77,178, 75,168,206,150, 6,236,185,233,239,215, 37, 0, 71, + 94, 0,119,172,127,119, 21,129, 59, 21, 21,245,175,219,189,254, 2,250,188,158,140,145, 86,117,174,140,159,131, 78, 63,156, 64, +225,130,231,241, 83,104, 40, 0, 96, 24, 64, 13,176, 49,215,165,167,167,147, 78,157, 90,224,228,169,159, 17,249, 80, 47, 32,237, + 13,188,186,101, 55,102,117, 57,131,254,117, 5, 88,120, 83,140,255,124,190, 20, 43,223,221,128,179,191, 30, 65,122,122, 58,121, +229, 21,251, 94, 95,182,188, 86,173,253, 49,126,194, 80,140,159, 48, 20,111,209,233,208,215, 45,198,169, 83,192,169, 83,192,225, +195, 19,241,225,186, 75,120,226,137,139, 36, 44,236, 65,164,165,249,243,226,167,220,135,223,192, 34,172,112,120,195, 29, 58, 52, +252,127, 70, 1, 32,137,137,137, 50,214,154,161,181, 18, 64,177,173, 13,139, 75,222, 37,205,139, 33,253,157, 59,119, 82,170, 77, + 67, 0,177, 24,212,206,157,247,244, 98,153,168,127,149, 74, 69, 37, 38, 38, 18,103,222, 16,235,216, 0, 62,132,110, 11,142,234, +206, 92,162, 65,104,123, 17,158,140, 19, 67, 87, 7,180, 12,164, 32,162, 44, 86, 63, 8,116,181,128, 70, 79,160,209, 18,104,116, + 4, 52, 1, 68, 14, 98,174,103,206,211,160,111,255, 34,132,244,188,141,111, 14,148,225,246,109, 29, 6, 12,171, 66,191, 86, 53, +128, 79, 29,116,181, 52,202,174, 19,104, 52, 20,140, 70, 10,173,218, 80, 0,117,207, 99,217, 34, 7,246,239, 63, 40, 56, 44, 12, + 71,239,242, 53,164, 79,206,192,237,148,249, 81, 0,122, 3,184,192, 67,161,232, 53,120,196,163,131, 90,135,134,225,196,207,245, + 49,114,104, 43,251, 23,174,126,188,184,145, 60, 39, 94,128,222, 3,251, 15, 24, 20, 26,218, 9, 23, 78,222,245,136,140,120, 44, + 22, 95, 42, 87,243,110, 91, 83, 42,180,204,243,107, 29,191, 17, 23, 23,215, 40,254,200, 70, 44, 0, 51,232, 93, 1,156, 94,180, +104,209,112,111,111,111,233,167,159,126,138,173, 91,183,226,217,103,159,197,170, 85,171, 64, 81, 20,254,248,227, 15,104,181, 90, +164,164,164,192,104, 52,226,133, 23, 94,160, 41,138,114,250, 0,120, 50,154,254,126, 95, 2,112,228, 5,240,132,245,239, 42, 50, + 50, 50,240, 76,210,227,168,172,168, 3,222,221, 8,205,225, 19, 8, 24, 57,168,254,243,178,119, 55,226,188,175, 47,168,151,158, + 67,159,233,227,113,108,219, 1,135,242, 46, 95, 62,135, 97, 35,228, 56,119, 62, 24, 27,215,171, 48,114,228,112,252,231,163,165, +120,107,244, 83,248, 12, 64,207,167,103, 99,227,122, 21,196,226, 96, 36, 76, 26,132, 79,121,200,251,239,251, 95, 97,240,196,190, +120,167,239,106,156,139,149, 34, 56,110, 87,131,186,109,252, 37,248, 57, 79,141,176,103,102,241,238,135, 35, 71,188,145,150,230, +231,176,142,171,246,207,223,210, 3, 96, 99, 29,153,114, 80,143,187,137, 51,200, 28,161, 62,109, 90, 71, 2, 92,134,234,131, 43, +128, 95,247,122, 79, 0,163, 20,112, 89, 6,240, 20, 24,107, 62, 49, 49,145,176,173,127,198, 35,192,126,159,152,152, 8, 86,178, + 28,194,151,208,173,193,218, 5, 96, 83,158,209, 4,104,106, 9,234,244,230, 96,191, 58, 61,129,183,239,221,207,116,181,128,214, + 64, 80,126,155,224,175, 59, 4, 39, 47, 24, 65,211, 64, 98, 98,162,236,242,229,203,141,198,198,104, 4, 74,174,233,113,173,240, + 14,142, 28,187, 3, 66, 40, 92,248,141,198,196, 39,141, 16,123, 19,252,117, 19, 56,114, 8,168,170, 34, 32, 52,240,240, 40, 10, + 18, 9, 32,151, 39,224,234,213,171,156,174, 73, 62, 12,228,192, 49,215, 39, 73,145,180,197,146,231, 87,165,250,100, 17, 81,131, + 14,105,227,235, 11,159,151,230,249,252,177, 46,125,169,190,170,106, 6, 87,121, 94,126,210,165,201,203, 86,249, 28, 42, 33, 13, +228,181, 14,240, 69,159,233, 47,250, 92,248,234,131,165,122, 77,205, 12, 46, 30, 0,137, 95,192,210,197,203, 87,248, 92, 41,173, +108, 32,171, 69, 96, 0, 38, 63,249,172, 79,214, 23,159, 44,213,104, 52, 51,154,249,241,165,246,238,221,219,168,236,205, 55,223, + 36,123,247,238, 69,118,118, 54,231,161, 0,112, 14,192,233, 53,107,214,244, 15, 10, 10,146, 50,110,240, 79, 62,249, 4,179,103, +207,198,214,173, 91,235, 45,245, 53,107,214,160,162,162, 2, 85, 85, 85, 53,181,181,181, 69, 22, 15,130,216,209, 15,208, 52, 77, +172, 93,244,140,245,207,213,253,207,184,233,217,114,172,221,245,247,195, 18,128, 45, 47,128,167,173,127, 70, 38,215, 37,128, 11, +195,134,129,122,126, 58,130, 0,144, 81, 81,168, 61,121, 14,154,119, 55,222,237,183,164,199,209,237,233,199, 33,145,152,175,255, +252,121,199, 91,179,153,207,229, 19,204, 74, 68,254,137,179,248,236,255,182,195,127,232, 16,212, 26,140,208, 67,143, 71, 30, 29, +216,168, 62, 23,121,215, 76,122, 60,217,254, 69,208, 39,235,144,248,222, 40,136,167, 29, 71,239,200,222,136,236,211,181,190,125, + 41, 11,215, 33, 45,237,223,156,239,155,130,170,130,209, 23,112,225,155,248, 22, 92, 60, 6,174, 37, 2,250, 91, 42, 0,249,249, +249, 78,163,191, 45,159,115, 19,232, 27, 0, 85,231, 31,128,143,194, 9,194, 3,128, 46,117,160,122,100, 83,248, 32,170,126,237, +223,157,101, 0,235,173,128,246,182, 6, 58,112,187,214,147,191,117, 0, 32,227, 82,103,202,156,120, 0, 40,107, 75,204,221,201, +252,225, 71,227, 99,174,223, 56,160,166,219,210, 16,121, 3, 62,150,121,209, 64, 19, 24,141, 64,117, 53,129,222, 0, 24, 13,102, +165, 32, 97,146,217,123, 99,199,101, 79, 69, 15,139,143,169,187,181, 95, 29, 25, 73,227,240,247, 38, 80, 34,224,175, 82, 10, 18, + 63,224,251,131,128, 94, 75,129, 34, 64,191,135,124, 80, 82, 76,227,209, 71, 99,145,149,149,197,233, 88,107,249, 48,144,180, 23, +205,215,239,170, 18, 64,104,211, 56, 83,235, 54,162, 3,244, 93, 22,106, 15, 32,132, 2,180, 81, 81,222, 87,140,166,113,188,228, + 17,122, 28, 2, 91,137,212,165,166,122,121,109, 37, 64, 27, 9, 5,255,190, 81,222,231,183,211,227,172, 60, 6,196,145,172,128, +192, 32,209,213,155, 21, 22, 98, 1, 2,253,124, 17,232, 47,198, 67, 3, 6,122,239,254,140,140,107,230, 71,215,102,159, 51, 81, +255,236, 58,140,247,110,234,212,169,178,204,204, 76,123,242,106, 0, 92, 57,117,234, 84,205,200,145, 35,219,130,181,167,255,147, + 79, 62,169, 39, 68,131,193, 0,147,201,132,203,151, 47,163,109,219,182,183,104,154,230,164, 45, 78,154, 52,201,158,165,238,146, +155,254,126, 94, 2,176,229, 5,240,164,245,207,135,248, 25,116, 8, 13,194,199, 31,127,135,248,184, 97,104, 31, 21, 9, 68, 69, +130,122,126,122, 67,165, 23,192,205, 82, 45,246,100, 31, 67,135,208, 32,238,242, 66,252, 16, 53,168, 27,162, 6,117,107, 84,143, +175,188, 71,166,244,194,235,143,126, 0,250,156,153,252,231, 44,156,233,146, 60,107, 44, 9, 92,242,205,202,234,149, 99,154,242, +129,116, 75, 1,176,236,217,191,167, 17,216,140,149,171, 82,169, 24,139,151,178, 81,135, 48,228,207,178,138,121,129,189, 11,128, + 41,227,107,249, 91, 7, 0, 90, 80, 95, 54,127,254,124,181,101, 57,131,147, 60, 54,249,219,138, 9,224, 43,207, 25,210, 50,117, +112, 38, 47, 43, 43, 43,175,117, 16,133,199,162,125, 64, 3, 48,232,105,248,138,205,221, 84,173, 33,168, 51, 16, 24, 77, 64,254, + 57, 19, 76, 52,129,179, 45,123, 89, 89, 89,121,237,219, 82,120, 52,198, 11,147,159,242, 66, 77, 53, 65,117, 37,160,169,166, 16, +222,141,192,100,160,224, 45,146,160,226, 54,141,146, 63,245,184,252, 27,183,128, 49,249, 48,144,244,121, 64,247, 48, 96,221,107, +192,220,247, 93, 83, 2, 72,173,102,202, 75, 81, 3,247,135,100,237,151, 6,143,120, 24,237, 1,180,167, 0,211,209, 35,200,157, + 57,163,198, 80,171,153,204, 71, 30,173,171,157,252,252,232, 65, 7,122,189,245,181,180, 93,191,225,104,227, 75,161,173,132,130, +246,226,143,216,243,198,172, 26,131,182,150,179,188, 58,157,118,242,132,199, 70, 30,152,255,238,122,105,239,254, 81, 8,244, 23, + 35,208,207, 23,133, 23, 78, 99,121,202,203, 53, 90, 30,178, 92, 37,115,103,151,107,139,252, 87,172, 88,209,200,205,191,115,231, + 78, 38, 79, 64,158, 29,235, 31, 48,199, 88,156,238,209,163, 71,161, 78,167,235,232,229,229, 37,241,247, 55,111,197,202,204,204, +196,212,169, 83,161,213,106,161,211,233, 80, 87, 87, 7,169, 84,170, 51,153, 76, 89,132,144, 82,142,214,181, 71,230,182,191,203, + 18, 0,219, 11,192,188,110, 14,226,103, 16, 30, 30,130, 37,175, 39,225,224,129,159,240,245,238,147,240, 21,183,192,159, 37,119, + 87,176, 58,133,246, 70,157,190, 10, 15, 69,245,196,218,244, 36,172,124,119, 3, 47,121,237,218,181,196,249, 11,231,235, 63,143, +236, 29,137,178,178, 74, 94,242, 98,231, 77,198, 84,209, 12,212,157,171, 65,244,220, 62,160,251, 73,240,241,199, 59,234,219, 87, + 89, 89,137,225, 15,247,226, 36,207, 26, 42, 74, 69,169,160, 66, 83,194,101, 5,160, 41,200,159,139, 76, 11,225, 19,203,107, 0, + 32,236,109,137,249,249,249, 13, 8,223,150,130,208,216, 15, 75, 1, 98, 17,224,231, 5, 72,189,129,186,106,168, 86,250, 0,233, +115, 8,252, 90, 1,126,173,120,175,253,219, 33,127,216, 32,107, 78, 15,134, 53,249, 91,199, 4,240,149,199,131,252,157,202, 43, +175, 32,212,190, 60, 3,145, 72, 0,154, 6,250,246,240,186, 59, 30,191,154, 96, 48, 17,152,104, 47, 76,153, 50,133,147,114,114, +243, 47, 66, 29, 56,104, 34, 70, 35,160, 55, 16,152,140,128,136, 2, 98, 98,129,234, 10, 10,191,157,209, 66,171, 19, 33, 62,110, + 10,118,237,218,197,137,252, 87,204, 1,186,118, 50,191,239,210, 17,112,213, 19,160, 84, 42,143, 43, 20, 10,121,105,194,132, 3, + 97,123,246, 75,195, 70, 60, 12,195,209, 35,216, 21, 55,161, 70, 95, 93, 45, 7,112,132,103, 87, 31, 49,105,171,229, 23,223,156, +116, 32,244,189, 44,105,199,193, 35,160,185,120, 20,159,191,148, 80, 83, 87,203, 91,222, 17,157,182, 86,190,230,245,127, 31,248, +207,127,183, 72,163,135, 13, 71,193,249,211,120, 57,105, 70, 77,109, 77,141, 43,109,107, 82, 56, 72,246, 67, 98, 99, 99,185,236, + 6,240, 10, 10, 10, 58,173,213,106, 63, 43, 42, 42,234,220,191,127,255, 8,163,209,232,237,227,227,131,172,172, 44,140, 25, 51, + 6, 58,157, 14,181,181,181,184,124,249,114, 85,112,112,240,119, 90,173,246, 83,154,166, 53,224,152, 1,144, 29,144,192,215,245, +255,119, 91, 2, 96,123, 1, 60, 33,199,149,220, 1,182, 48, 94, 62, 20,227,229, 67, 45,239,220,215, 97, 27,202,155,228,158,114, + 23,180, 19,117,103,106, 48,115,125, 44,254,243,221, 82,183,219,150,174, 79, 39,193,198, 96,204,244,159,121, 79, 12,107,151, 20, +128,230,176,252,109, 88, 31,196,170, 61,158,178, 82,236,122, 4,184,122, 0, 60, 77,254,140,178, 99,229,222, 39,236, 50,190,242, +156,197, 2,240,149,167,209, 17, 74,163, 3, 17,137,128, 35,249,230,181,126, 38,224,207,188,238, 63,133,151,188,234,106, 66, 81, +150,101,118, 74,100,150,241,243, 15,128,166,134, 6,161,129,248,248, 88,236,218,181,203,233,120,200,135,129,164,204, 0,130,164, + 64,201, 45,192,207, 23,160, 9, 16, 32, 1,222, 85,184,166, 4, 0, 56, 66, 87, 87,203,243,227, 39, 28,104,185,226,109,105,222, +138,229, 53,117,174,145,127, 3, 37, 32,111, 81,194, 1,191,151,222,148,230,124,248,150, 43,228, 95, 47,203,104,208, 79, 88,254, +202,243,251,231,206, 79,145,174, 95,155, 90, 83, 91, 83, 35, 87, 42,149,103,216,238, 97,165, 82,233,173, 80, 40,140,124, 29, 32, +158,244, 10,216, 34,127,138,162, 72,108,108, 44, 0, 96,226,196,137,132,162, 40, 71,138,128, 84,175,215,215,136, 68,162,220,208, +208,208, 78,213,213,213, 47,158, 56,113,162,195,192,129, 3,105,163,209, 88, 91, 89, 89,121,243,204,153, 51,127,132,135,135, 23, +182,110,221,186, 72,171,213,102, 26,141,198,155, 73, 73, 73,154, 1, 3, 6,112, 82, 0,152,164, 64,238, 64,169, 84,114, 38, 84, + 87,150, 0,220,249,190, 61, 47,128, 39,230, 76,119,229,232,180, 94, 30,173,239,105,121, 21,119, 68, 72, 53, 42, 16,113, 44, 4, +211, 63,114,174,152, 84,220,113,126,203,221, 75,242,183,171, 0,112,216,235,207,171,129, 60,114, 7,240,145, 75,177,162,252, 93, + 38, 47, 42, 31,212,180,240,241, 4,151, 0, 52,202,215, 80,105,249,227,183,199,220,114,189,106, 79,145,171, 85,191, 16, 38,207, +128, 37, 64,144, 98,121, 67, 92,146,247,249,130, 0,182, 82,224,138,188,122,185, 83,167,222, 29, 19, 38,224, 79,165, 82,229,185, + 34,143,208, 13,199,184,166, 10,136,141,141,197,190,125,251, 40,198,170,226, 52, 30,159,121,238,129, 97,229,227, 63, 98,168,174, +150,127,191,226,205,140,186,234,234,153, 30,176,174,143,232,107,171,229,135,214,191,149,161,171,173,158,165, 84, 42,143,186, 58, +153, 27,141,198,195, 70, 99,141,124,125,122, 90, 70, 77, 77,205, 76, 0, 71,172,101,185, 64,254,158, 64,131, 25,213,154,252,153, +184, 29,118,144, 96, 92, 92,156, 35,121,197,122,189,222,151, 16, 82, 77,211,180, 82,175,215,255, 20, 22, 22,214,166,162,162,130, + 90,182,108, 89, 85,101,101,101,121,199,142, 29,171,107,106,106, 52,122,189,190,202, 96, 48,212, 61,247,220,115, 90,158, 22, 54, +229,129,123, 38,175,169, 58,180, 41,101, 55, 55,222,127,255, 35, 10, 0,121,252,137, 49,136,236, 19,110,183,222,249,115, 87,240, +213,246,111,152,250,247, 76,222,250,245,235,235,229, 57, 52,152, 79, 20,225,171,237,223, 48,245, 29,226, 94,146,191, 61, 5,192, +211, 13,104,178, 11,178,144, 40,101,203, 90,230, 3, 15, 71,245,115,201, 22,232,214, 15,240, 57,244,199, 19,222, 0, 23,198,196, +238,123,119,229,237,219,183,143,215, 88,185, 19,241,207,133,180,117,213, 85, 93, 60, 41, 79, 91, 83,221,197, 67,150,220,145,154, +234,234, 46,247,217,179, 76, 1,192,166, 77,155,136, 72, 36, 2,243,199,118, 97,203,229,114,208, 52, 13,154,166,145,148,148, 68, + 57,217, 21, 64, 25,141, 70,127, 66,136,137,166,233, 58,131,193,240,131,151,151, 23, 37, 18,137,124, 1,248,210, 52, 13,147,201, +228,101, 52, 26,197, 70,163,177,195,115,207, 61,119,145,245,221, 38, 63, 4, 72,128,103,148,128, 33, 67, 70,146,131,251,119,163, +184,172, 10, 33,193,181,245,159,149,222,241, 71, 88,187, 22,232,217,179,167, 83,178,110, 42,121,235,215,175,167, 30,121,228, 17, +178, 46,125, 31, 10,254,188,213, 72, 94,215, 78,109, 16, 17, 17,193,137,252,155, 10,142,114,164, 80,174,158, 35, 44, 64,128, 0, + 1,247, 1,106, 89,132, 78,179, 12, 27,111, 86,249, 13, 0, 45, 97, 14, 26, 23,136, 95,128, 0, 7, 30, 0, 1, 2, 4, 8,248, +187, 64, 98, 81, 2,104, 22,241,139,112,247,228, 65,111, 0, 29, 44,175,105,161,187, 4, 8, 16, 20, 0, 1, 2, 4,252, 51, 32, + 2, 32,101,189,103,136, 95,204, 34,125,218, 82, 79,176,254, 5, 8, 16, 20, 0, 1, 2, 4,252,143,204,105, 2,233, 11, 16,224, + 64,123, 22, 32, 64,128, 0, 1, 2, 4,252, 47,107,203,167, 79,159,102, 31,164, 67,172,146,232, 16, 52, 60,104,167, 88,165, 82, +133, 49,239,109, 5, 19,178,229,241,197, 63, 81,158,141,109,139,148,208,127,194,120,252, 93,228,133,133,133,213,215, 41, 46, 46, +166,248,202, 75, 78, 78,134, 66,161,160,132,251,207, 53,153,194,243, 43,200,227, 35,143,183, 2,192, 19,109, 57,214, 35,137,137, +137,188, 51, 75,217, 59, 47, 30,141,147,145,216, 58, 13,208, 86,157,123, 14,134, 96, 44,123,225,213, 42,149,170, 62, 91, 23,223, +124,226, 77,133,184,184,184,152,236,236,236,122, 18,140,141,141,149,237,219,183, 47,239,159,168,237,218, 26,143,139, 23,205, 59, +195,122,245,234,213,220,205, 35, 9,147, 20,200,250, 90,105,243,158, 77,152,164, 32,150,207,236,222, 56, 9,147, 28,158, 20,136, +172,175,149, 46,223,116, 97, 97, 97, 36, 46,238,238,174,194,236,108, 16,103, 74,128, 51,172, 94,179, 58,102,207,161, 61,136,136, +140, 80,131, 2, 46,158,186, 32, 27, 54, 96, 56,210,223, 79,231,117,255,205,156, 57,179,209,117,103,100,100, 80, 16, 32, 64, 64, +147, 41, 0, 98,174, 21,163,163,163,121, 11,119,160, 0,216, 36, 81,235,131, 54,120, 16,173, 43,154, 19,151,201,133,168, 84, 42, +164,164,164, 32, 53, 53, 85,237, 32, 77, 39,151,223,111, 80,167, 99,248, 3, 0,128,155, 58, 29,140,218, 58,115, 97, 69, 21, 67, +114,220,210, 31,215, 79,228,217, 13,114, 10, 88,114,139,243, 58,227, 93, 68,153,179,235, 49,255, 1,167,175,155, 99,114,110, 48, + 30, 12,241,187, 49, 30,158,188, 6,146, 48, 73,129, 9,242,135,116,128, 66, 98, 33,122,151,126,131,165, 64,120, 28,122,125, 10, +114,114,146, 48,110,220, 38,196,197,165, 34, 59,219,220, 87,174, 40, 2, 79,191,252, 52,169,104,117, 27,107,149,171, 17,236, 31, + 12,218,104,130,142,212,169, 15,254,116,104,220,116,211,227,100,120,196, 8,217,188,121,243,156, 42, 2, 51,103,206, 36,201,201, +201, 54,251, 84, 80, 2, 4,220, 11,196,199,199,215,207, 25,115,230,204,193,150, 45, 91, 26,112,207,236,217,179, 27, 28, 78,229, + 44,185,148, 51,121, 92,143,170, 62,125,250,180,181,151,192,163, 10, 0,175,248, 1, 91,167,216,121, 2, 27,149,202,152, 23,220, + 76,154,194, 39,135, 54, 71,203,157,164,164,164, 96,213,170, 85, 0, 80,255,223,246, 79, 19,126,222,128,160, 22, 56, 91,180, 29, +126,232, 4, 19,126, 68,217,230,147, 56, 83, 88,142, 41,171,182, 54,219, 3,112,246,215,115,232,215,183, 15,104, 2,156, 59,103, +126, 13,220,125,205, 46,167, 9,231, 49, 33, 28,199,131,226, 58, 30,179,102,205, 2,128,250,255, 54,137,157,162, 0,199, 63, 77, + 30,123,236, 0,190,253, 86,238, 81, 37, 96,130,252,161,218,164,164, 36,127, 96, 19,178,190,118,141,216,221,177,240,157, 89,255, + 0, 48,117,106, 38,114,114,204,255,147,146, 10,193,120, 4,248,120, 3, 54,110,220, 24,163,254,253, 59,245,243,201,179, 49,168, +237, 64,248,181,108, 9,162, 55,130, 38, 38,120,121,139,209,117,116,215,156,223,162,126,199,170, 77,169,234,181,107,215,202, 94, +125,245, 85,167, 74,192,173, 91,183, 26,188,143, 29, 25,128,161,243,126,132, 78, 55,189,193, 64,238,216,177,195,229,254,145,203, +229,228,192,129, 3, 30,235, 95, 79,203,107, 74, 36, 39, 39,199,184,155,214, 55, 57, 57, 57, 6,112, 61, 61,176, 82,169,236,247, +218,107,175,221,208,104, 52, 97, 0,198,194,124, 8,103, 47, 0,167, 97, 62, 20, 10, 0, 62, 7,240,219,189,238, 31,246, 89, 15, +115,230,204, 65,118,118,118, 3, 78,153, 61,123, 54,248,100, 46,117, 38,175,254,121,207,202, 34, 9, 9, 9, 20, 23,242,103,202, +172,149,128, 6, 10, 64, 74, 74, 10, 41, 42, 42, 2, 0, 68, 68, 68,128,125,216,140, 74,165,106,240,222,250,115, 71, 22,123, 89, + 89,153, 90,165, 82,113,246, 4, 88,159,117,239,136,132, 95,176,164,194,180,230, 1,190, 46,246, 77,155, 54, 57,173,147,155,155, +203,137,187, 18, 19, 19,237,146,254,226,197,139,145,154,154, 10,182,130,192, 5, 29,195, 31,192,245, 59,149,216,245,194, 84,180, +166, 70,160,240,227, 5,136,152, 28,129,111,154,153,252, 1,212, 19, 62, 0,244,233,211,167, 65, 57,227, 25, 96,151,123,218,178, +119, 66,196, 36, 49, 49,209, 46,233,111,219,182, 13,169,169,169,144,143, 24,136, 3, 63,158, 2, 2, 3,128,170,154,123,222,135, +251, 15,156,244, 7, 54, 97,255,129,147, 30,145,119,243,189,214, 14,181,152,246, 11,203, 57, 61, 32,108,215,127, 82, 82, 14,226, +226,186,212,255,103, 16, 23,215,133,179, 18,240,241,151, 31, 99,229, 71,239, 96,100,183, 24,152,234,234, 96, 52, 25, 65,121, 83, + 0,188, 64, 64,227,230, 95, 37,232,213,182, 39,150,190,176, 20,239,164,189,195,201, 27,101, 61,217,197,134,110,179, 73,248,211, +167, 79, 39,174, 40, 1,114,185,156,236, 95,118, 0, 19,224, 25,210,150,203,229, 36, 45, 45, 13, 0,238,107, 37, 32, 57, 57, 57, +166,178,178,146,241,150,185,213,206,202,202, 74,102, 78,119, 73,142, 66,161, 40, 2, 48, 11,192, 41, 0,159, 2, 24, 3, 96, 60, +128,127,179, 20,128, 91,205,209, 79,236,227,158, 1,224,235,175, 27,107,240, 95,127,253, 53, 8, 33,152, 52,105, 18,197, 87,222, +198,141, 27, 71, 89,230, 57, 2,128, 10, 9, 9,177, 75,252,214, 72, 74, 49,115,204,166,212,197, 54, 63,111,160, 0,164,166,166, + 58, 12, 2,100,191,183,254,220, 81, 16, 2,163, 84,204,159, 63, 95,157,146,146, 2,235,131,114,172, 15,207, 81,169, 84,142,210, + 23, 82, 28,202,154,245,161,250,234,171,175,236, 18,191, 69,209,170, 39,255,197,139, 23,115,146,249,103, 81, 49, 52,187,151, 67, + 58,251,191,232, 24,254, 0,218,183,246, 67,209,238, 34, 51,249, 7,181, 48, 47, 1,248,120,241,110,107, 92, 92,156,140,189, 12, + 96,121,207, 75, 6, 77,128,176, 0,224,195, 25,192,115,219,128,182,254,192,197, 10,219,229,231,239,240,107,159, 61, 69,142,143, +215,230,237,183,223,182, 75,252, 0,144, 54,107, 34,214, 29, 60,142,144,136, 14, 40,189,122,211,169,245, 15, 0, 28,189, 0,156, +189, 4,102, 11, 95, 97,211,210,231,178,254,111, 11,105, 95,120, 54,201, 39, 67,250,204,127,125, 92, 87,136,179, 11, 56,127,191, + 86, 91,139, 17,211,135,171,163, 59, 12, 69,157, 70, 3,111, 95, 95,120,123,223,157,130,138, 10, 10,176, 39, 43,235,250,236,103, +103,117,236,236, 27,134,129,143, 14, 24, 45,213, 5,198,124,242,241, 39,188,172,198,119,247,207,194,247,223,127, 15,160, 97,219, +118,236,216, 65,241, 85, 2, 24,242, 71,231,181,216,191,236, 85,183,149, 0,185, 92, 78,210,211,211,209,189,123,119,172, 91,183, + 14,115,231,206,189,239,148, 0, 43,226,247,136, 60, 70,150, 27,222, 4, 25,128, 71, 1,108, 3, 80, 3, 32, 4,192,239, 0,174, +226,110,238,135,102,129,245,113,207,108,183,189,181, 11, 63, 33, 33,129, 56,115,225,239,223,191,191,193,146,241,158, 61,123,212, +108,171,159,171, 66,204,144, 63,243,122, 83,234,226, 70, 94,128,123,146, 7,128,181,246,138,162,162, 34,180,107,215,174,145,130, +192,148,149,149,149,113,205,115,239, 44, 24,144,243,132,249,248,227,143, 55,217,181,179, 9,204,150,213,111, 33, 33, 91,109,111, + 0, 45,138, 81, 51,121, 40, 72,224, 2, 96,244, 50,212,224, 75, 96,243, 73,139,102,182, 0, 62,207,172,131,209,200, 63,209, 89, +118,118,118, 30,187,159,248,146, 63, 0,148,125, 2,188,181, 17,120,160, 19,112,115,175, 24, 25, 91,244,152,181,221,126, 57, 47, +243,158,120,150,196,216,193,126, 55,190, 94,133,192, 72, 9,164,221, 94,193, 87,171,158, 67,255, 62, 33,232, 49,241, 29, 78,227, +193,165,233, 60,150, 10, 40, 0,196,138,252, 41,134,248, 93, 89,215,231,106,225,115,129, 62,174,171,205,242, 28, 43, 79,128, 51, +220, 40,187,129,177,137, 99, 17,216, 34, 24, 38,202,136,195,223,255,128,234,154, 26,196,197,199,227,175,178, 50,236,204,220,133, + 57,207,206,234,232, 43,241,133,136,248, 96,220, 67,227,114,127, 87,175,115, 73,161,191,115,231,142,219,215,205, 38,127, 0,110, + 43, 1,114,185,156,172, 88,177, 2, 93,187,154,251,179, 75,151, 46,184,159, 60, 1,158, 38,126, 27,214, 63,243,218,149,107,237, +109,121, 38,125, 0,248, 3,136, 4,112, 1, 64, 71, 0, 85, 0, 42, 60,240,204,186, 4,235,227,158,231,204,153, 83, 95,198,184, +240,153,185,140,139,103,218,222,114, 1,155,252,185, 40, 2, 92,112,207, 87,242, 20, 7, 0, 0, 9,178, 73, 68, 65, 84, 18, 1, +181,107,215, 78,150,152,152,216,104, 41,192,114,182, 61, 0,240,142, 17,176, 23, 12,232,200,114,180,167,160, 52, 5, 24,235,222, +158,187,159,171,245, 15, 0, 7,151,172, 64,220,202,247, 97, 28, 61, 2,222, 0,164,199, 10,240, 77, 97, 57, 0,192, 56,122, 46, + 12,191,182, 1,213,246,223,188, 73,138,135,151,197, 46,202, 39,125,137,185,207, 94,195,165, 23, 22, 65,243,173, 30, 33,109, 28, +151,123,194, 3,224,138,114,176,109,219, 54,179, 54, 28,247, 8,142,151,148, 33,176,127, 32,174,231, 20, 2, 18, 95, 76,157,251, + 12, 90,117,154,216,156,243,175,189,168,127,143,120,181, 28,237, 16,112, 22, 59,144,147,148,131,113,155,198, 97,106, 38,144,148, + 99,126,157,147,148,195,219, 11, 80,163,171, 70, 27,191,214, 48,234,106, 65, 68, 4,131,135, 12,193,238,221,187,117,233,239,191, + 47,161, 9,193, 83, 51,158, 66,171,214,173, 80, 91, 83, 3,163,201,136, 64,159, 22, 48,136, 12, 46, 93,111, 69, 69, 69,131,221, + 1,124, 3, 2, 27,145, 63, 3, 23,149, 0,185, 92, 78, 82, 82, 82, 48,100,200,144, 6,229,125,250,244,193,187,239,190,219,172, + 74, 64, 83, 17,191,181,245, 15, 0, 37, 37, 37,174,122, 1,126,130,121,189,191, 10,102,215,255, 88, 0,151, 1,244, 3,144, 5, + 96, 43, 0,135, 55,139, 82,169, 20, 41, 20, 10,143,167,131,102,187,236, 89,129,122,245,159,179,151, 4, 74, 75, 75, 99,156, 29, +244, 69, 8,161, 24,130,103,187,250, 19, 18, 18,108,150,123, 82, 1, 32, 86,164, 72,120,126,238, 16, 17, 17, 17,245,164, 31, 29, + 29, 45, 99, 98, 3, 24,239, 64, 68, 68,132,154, 89, 46,104,174,137,215,147,112,182,214,207,178,254,157, 98,202,198, 76,144,248, +112,220, 28,246, 16, 90, 99, 4,252,166,174,131,241,198, 95, 64, 80, 11,120,151,127,137,189,233,249,128,151,151, 43,215,238,182, + 38,121,230,181,127, 97,208, 0, 32, 98,238, 57, 68, 74,159,197,239, 15, 38, 2, 31, 46,178, 91,222, 92, 30,128,212,212, 84,140, + 28,220, 3,163, 71,116, 71, 92,223, 69, 88,147,190, 1, 23,242,175,227,133, 81,131, 80,154,181, 31,149,119,170, 60,117, 63,216, + 90, 42,112, 74,208,108,194,247, 36,249,219,145,201, 9,197,197,197, 84, 88, 88, 24,153,154,217, 80, 33, 0,128,113,155,198, 65, +156, 93,128,236,236,194,250,157, 0,236, 92, 1,182,110, 55,154,166, 97,162, 1, 66, 27,225,235, 39,193,140,167,159,150,188,245, +230,155,104,223,190, 61,221, 49, 36, 68,164,211,212,192, 68, 0, 66,155, 64,211,206,231,234,140,140, 12,106,204,152, 49,164,188, +188, 28, 85, 85, 85, 13, 20, 71,171,221, 1,156,119, 5,200,229,114,178,230,185,243,128,164, 43, 80,250, 81,227, 10,146,174, 88, +243,220,121,128,163, 18, 32,151,203, 73, 66, 66,130,172, 79,159, 62,234,242,242,242, 70,159,135,133,133, 33, 33, 33, 65,134,251, + 60, 38,192, 93,235,223, 77, 47, 0, 91, 97,232, 0,224, 12,128,201, 0, 56, 31,101,218, 20,228, 15, 56, 94, 2,176, 97,204,228, + 57,187,246,248,248,120,194,124, 63, 62, 62,158, 88,203,219,178,101, 11,226,227,227, 9,223, 93, 1, 92, 20, 0, 62,137,128,108, +125,110, 19,137,137,137, 54,189, 0, 12,217,183,107,215, 78,150,146,146,162,102,214,100, 19, 19, 19, 29, 6, 21, 58,178, 14, 93, +216, 95,223, 36,219, 0, 25,235,222, 81, 48, 32, 31, 20,190,151, 4,159,169,235,160, 45,185, 4,239, 99,235, 96,200,156, 11,106, +194,106,236,249,247, 52, 92,221,115, 5,113,105,159, 2,222,205,147,217,121,145, 10,200, 73,219,141,200,171,227,128, 91, 26, 44, + 28,179,200, 97,185, 39, 60, 0,174, 90,255, 89,187, 87,192,171, 99,111, 72,209, 29,197,223,111, 66, 53, 69,240,243,165,107, 24, +125,238, 58,167,230,124,251,173,220, 46,217, 3,128,229,115,155,245,184,146,191,157,123,212, 45, 98,240,196, 14,129,164,156,187, +196, 15,160,145,229,207, 4, 12,102,103, 23,218,252,126,160, 95, 32, 74, 42, 75, 48,164,243, 80,104,235,116,128, 86, 7,163,222, +128,165, 41, 41,160, 68, 16,213,106,106, 64,211, 38, 24, 77, 4,190,222, 62,248,171,230, 47,248,152,156,239, 54,254,230,155,111, +234,175,109,230,204,153,132,153,111,216,187, 3,110,220,184,193,249, 58,205, 36,108, 86, 2,122,133, 55,254,253,139, 87,244,152, +191, 57, 18, 92,201,218, 82,143, 12, 25, 50, 4, 97, 97, 97,141, 62, 63,119,238, 28,178,178,178,212,205, 69,254, 22,107,156, 98, + 60, 1, 37, 37, 37, 77, 98,253,123,192, 11,192, 96,172,133, 72,235,238, 7, 37,199,209, 18, 0,187,156,239, 18,128,167,150, 20, +248, 40, 0, 77, 2,198,242, 7,128,232,232,104,153, 74,165, 82, 51,174,127, 59,202,129,236,242,229,203,206, 98, 1, 40,142,101, + 30,181, 50,185,118, 56, 99,253,219, 34,126, 70,209,225,211,222, 51,133,229, 48,252,250, 22,110,226, 71,132, 76, 88, 13, 84, 86, +161,112,211, 2,116, 73, 94,139,210,173, 11, 0, 31,111, 64,212, 60,153,157,139, 53, 64,175,118,147, 57,151, 55,135, 7, 32, 53, + 53,181,102,250,232,161, 55, 90,210,193, 15,212,194, 71,146,185,118, 46,214,239, 61,141,133,227, 31,198,172,247,191,192,180,255, +247,127, 77,234, 13,114,116,137, 89, 95, 43, 97, 73, 2, 68,185,171,156,186,227,234,119,228, 5, 72,202,201, 33,182,200,159,109, +253, 59, 67,104,187, 80, 28, 60,156,131,225, 15, 12,135,127,128, 20, 52, 77, 32, 34, 70,208, 20, 5, 66, 8, 76, 4, 48,210, 4, + 70,163, 17,218, 74, 13,246,253,178, 15, 98,147,152,247,214, 97,235, 93, 1,175,207, 29,129,216,208, 34, 80,135,184,203,176,167, + 4,240, 37,127,107, 37, 32, 45, 45, 13, 29, 58,116,184,171,216, 23, 22, 34, 53, 53, 21,247,131,229,239,105, 69,192,150,245,239, +166, 23, 0, 0, 98, 0, 60, 8,224, 13, 52,115,240, 31, 3,165, 82,217,224, 30, 45, 45, 45,133, 82,169,116,228,137,112, 42,143, +189,164, 80, 90, 90, 26,163, 84, 42, 41, 0,164,180,180,148,218,184,113, 35, 97,121,111, 41,133, 27,219,224,239,137, 2, 96, 29, +245,111, 73, 86,211, 72, 57, 96,191,118,211,130,231,125, 99,121,112, 27,160, 77,235,223, 85,226,103, 48,101,213, 86,236, 2, 48, +126,101, 44,136,106, 1,168,199,215,224, 76, 97, 57,168, 86,193, 40,248,179,202,108,253,243, 95, 2,240, 8,236,237,247,119, 39, + 15, 0, 23,133,139,171,114,176,109,219, 54, 61,128,234,231, 98,250, 85,189,178,250,191,250, 37, 75, 83,116,109, 91,180, 43, 63, +127,161,184,253,172, 11, 95, 72,209,204,187, 70, 28,144, 51,123,137,134,231,142, 2,207,195, 22,249, 51,150, 63, 0,167, 1,129, +243,230,205,163,134, 63, 54, 60, 94, 61, 34, 47, 43,177,239, 52, 84,233,170, 64,137, 0,115, 74, 17, 26, 38, 19, 1,109, 52, 34, +192, 55, 16, 71, 43, 79,225,242,177, 2,236, 84,238,204,115,187,225,133,207, 3,224,191, 13,176,129, 18,208,161, 24, 23,111,132, +185, 68,254,214, 74,192,186,117,235, 16, 20, 20,132,242,242,114,172, 88,177, 2,247,155,219,223, 19,138,128, 61,235,223, 69, 47, + 64,123,152,163,254, 69, 0, 6, 2,152, 15,160,240,126,233, 47,133,101, 43,186,167, 96,189,164,176,103,207,158,239,155,170,237, +247, 36, 15,128, 61,143,192,154, 53,107,100,214,138, 66, 98, 98,162,154,239, 69,176,137,224,126, 72,177,203,182,254,173,183,255, + 89,250,151,221,175,156, 27,204, 40, 1,147, 87,126, 2,146, 9,180,153,165, 68,222, 43,211,240,112,234,231,128,143, 15, 2, 36, +226,102,185, 94,246, 30,127, 91,175, 93,204, 3, 96, 4, 32,178,140,173,200,205,241,184, 57,125,244,208,146, 87, 54,101,135, 47, +157, 51,182, 69,104, 72,140, 30,192,217,196,196,196,150, 48, 31, 37,235,210,120, 48,183,220,183,223,202,153,136,127, 87,148, 59, +202,153, 5,207,135,208,155, 42, 25,144, 61, 88,147, 62,227, 17,104,213,170,149, 77,237,236,232,183, 71,247,132,245,124, 0,166, +233,198,179,143, 62,240,104,191,214,129,173,161, 51,232, 64, 8,129,216, 91,140, 10,109, 45,142,255,249, 45,182,125,150, 1, 89, +111,153,108, 39,118,186,221,198,119,247,207, 66, 70, 70, 6, 46, 95,230,159, 3,224,174, 18, 0,183,200,159, 45,111,238,220,185, + 36, 45, 45, 13,139, 22, 45,194,253,188,230,207, 86, 4,242,242,242, 92,250,174,163, 58, 60,100, 38,192,188,223, 95, 7,224, 53, + 0,191, 0, 48,225, 31, 10,235, 37, 0,190, 24, 48, 96, 0, 78,159, 62,141, 77,169,139, 27,229, 1,112,152, 8,168,169,242, 0, +216,242, 8,216, 35,122, 23,189, 0,110,161,169,182, 1, 50, 3,168, 84, 42,145,155,155, 75, 23, 21, 21,177,137, 76,166, 82,169, +120,107,142, 83, 86,109, 5, 88,137,127, 30, 93,186,177,254,181,166,121,238, 87,167,119, 41, 77, 92,234,187,116, 0,183, 97,222, +254, 51,195,205, 54,150, 62, 23,211,175,110, 76,238, 79, 45,158,122,243, 83, 40,149, 74,113,110,110,110, 7, 52, 76,103,237,210, +120, 52,181, 39,192, 89,126,127,167, 51,103, 19, 44, 9,216, 35,127,125, 92, 87, 32,219,185, 97,182,253,163, 29, 84,128,151,148, + 28, 11, 59,142, 17, 67, 71,160, 99, 96, 71,128, 38,248, 75, 87,142,163, 39,143,162,244,124, 41, 70,245, 26, 37,123,249,229,151, +155,125, 60,216, 74,128,167,200,154,241, 4,252, 93, 2,254,220,205, 2,232, 1,108,178,252,253, 79,192,122, 73,193, 29, 23,191, +189, 4, 64, 54, 21,128,166,194,252,249,243,109,146,189,213, 73,108,108,168, 29, 36, 2,178, 75,180,174,162, 41,182, 1,166,166, +166, 66,169, 84, 26,115,115,115,189, 45, 75, 7, 12,249,143,114,112,221, 54, 97, 57, 76, 73,221, 4, 67, 67, 28,148, 83,205,116, +243,251, 90,238,203,101,150, 34,147, 66,161,120,218, 77,177,190, 99,222,248, 56, 95,169, 84, 62,146,155,155,139,220,220, 92, 29, + 0,137,229,207, 19,196, 79,185,147, 26,216, 25,201, 39, 76, 82, 52, 24, 47,190,196,237,137, 37,129,226,226, 98, 42, 39, 41,135, +132,206, 13,149,161,179,237, 58, 37, 73, 57,106,174,241, 0, 91, 62,216, 66,173, 93,187, 54,102,235,202,173, 8,235,250,160, 26, + 0,126, 63,247,155,108,226,152, 56,164,111, 72,207,219,142,237, 46,181, 51, 35, 35,131, 26, 59,118,108,163, 93, 1, 6,131,193, +173,235,247, 52, 89,255,211,162,253,239, 3,210,164, 20, 10, 5,249, 39, 92,139, 39,150, 20, 24, 47,128,117, 25,103, 5,192,153, + 37,206,195, 82,119,245, 70, 39, 77, 44,223, 83,223,183, 41, 47, 49, 49,145,228,230,230,122,179,251,139,237, 97,225,169,160,228, + 53, 17, 33,223,143,147, 80, 32,128, 26,115, 66,126,138, 2,224, 7, 39,251,123, 57,142,199, 31,185,185,185,204, 54,160,170,136, +136,136,182,169,169,169,190,247, 67, 95, 54,165,219,222,147,178,139,139,139,169,226,133,197, 30,235, 3, 86,158,255,250,239, 29, +253,238,152,219,237, 60,116,232,144, 64,174,255,112,178,103,115,152, 66,161, 48,120,146,252,149, 74,101,144, 66,161,168,248,187, +247, 19, 23, 35,154,114,245, 28, 97, 1, 2, 4, 8, 16, 32, 64,192,223, 23, 34,161, 11, 4, 8, 16, 32, 64,128, 0, 65, 1, 16, + 32, 64,128, 0, 1, 2, 4,252, 15,224,255, 3, 40, 50, 24,122,163,191,209,130, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, 0}; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 4682549297a..f393139ee3e 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1619,6 +1619,18 @@ static void build_uvlayer_menu_vars(CustomData *data, char **menu_string, } } +void set_wave_uvlayer(void *arg1, void *arg2) +{ + WaveModifierData *wmd=arg1; + CustomDataLayer *layer = arg2; + + /*check we have UV layers*/ + if (wmd->uvlayer_tmp < 1) return; + layer = layer + (wmd->uvlayer_tmp-1); + + strcpy(wmd->uvlayer_name, layer->name); +} + void set_displace_uvlayer(void *arg1, void *arg2) { DisplaceModifierData *dmd=arg1; @@ -1898,6 +1910,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco y -= 18; if (!isVirtual && (md->type!=eModifierType_Collision)) { + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */ + uiBlockBeginAlign(block); if (md->type==eModifierType_ParticleSystem) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object"); @@ -1913,6 +1927,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_copyModifier, ob, md); } uiBlockEndAlign(block); + + uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); } lx = x + 10; @@ -2248,7 +2264,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco 0.0, 1.0, 0, 0, "Set the UV layer to use"); MEM_freeN(strtmp); i = CustomData_get_layer_index(fdata, CD_MTFACE); - uiButSetFunc(but, set_displace_uvlayer, wmd, + uiButSetFunc(but, set_wave_uvlayer, wmd, &fdata->layers[i]); } if(wmd->texmapping == MOD_DISP_MAP_OBJECT) { @@ -2617,7 +2633,7 @@ static void editing_panel_modifiers(Object *ob) block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE); uiNewPanelHeight(block, 204); uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier"); @@ -6354,6 +6370,11 @@ static void editing_panel_mesh_uvautocalculation(void) row= 180; uiDefButBitS(block, TOGN, UVCALC_NO_ASPECT_CORRECT, B_NOP, "Image Aspect",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Scale the UV Unwrapping to correct for the current images aspect ratio"); + + row-= butHB+butS; + uiDefButBitS(block, TOG, UVCALC_TRANSFORM_CORRECT, B_NOP, "Transform Correction",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Correct for UV distortion while transforming, (only works with edge slide now)"); + + row= 180; uiBlockBeginAlign(block); uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Cube Size:",315,row,200,butH, &G.scene->toolsettings->uvcalc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size for cube mapping"); diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 2dd6d705a9e..d75eaeb2fbb 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1054,10 +1054,10 @@ static void draw_default_sensor_header(bSensor *sens, (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, &sens->invert, 0.0, 0.0, 0, 0, "Invert the level (output) of this sensor"); - uiDefButS(block, TOG, 1, "Lvl", - (short)(x + 10 + 0.70 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, + uiDefButS(block, TOG, 1, "Level", + (short)(x + 10 + 0.65 * (w-20)), (short)(y - 19), (short)(0.20 * (w-20)), 19, &sens->level, 0.0, 0.0, 0, 0, - "Level detector versus edge detector (only applicable in case of logic state transition)"); + "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); } static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) @@ -1270,15 +1270,15 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short if(ps->type == SENS_PROP_INTERVAL) { uiDefBut(block, TEX, 1, "Min: ", xco,yco-92,width/2, 19, - ps->value, 0, 31, 0, 0, "test for min value"); + ps->value, 0, 31, 0, 0, "check for min value"); uiDefBut(block, TEX, 1, "Max: ", xco+width/2,yco-92,width/2, 19, - ps->maxvalue, 0, 31, 0, 0, "test for max value"); + ps->maxvalue, 0, 31, 0, 0, "check for max value"); } else if(ps->type == SENS_PROP_CHANGED); else { uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-92,width-60, 19, - ps->value, 0, 31, 0, 0, "test for value"); + ps->value, 0, 31, 0, 0, "check for value"); } yco-= ysize; @@ -1390,9 +1390,14 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short &raySens->propname, 0, 31, 0, 0, "Only look for Objects with this property"); } - + + /* X-Ray option */ + uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X", + xco + 10,yco - 68, 0.10 * (width-20), 19, + &raySens->mode, 0.0, 0.0, 0, 0, + "Toggle X-Ray option (see through objects that don't have the property)"); /* 2. sensing range */ - uiDefButF(block, NUM, 1, "Range", xco+10, yco-68, 0.6 * (width-20), 19, + uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19, &raySens->range, 0.01, 10000.0, 100, 0, "Sense objects no farther than this distance"); @@ -1439,10 +1444,13 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short draw_default_sensor_header(sens, block, xco, yco, width); joy= sens->data; - + + uiDefButS(block, NUM, 1, "Index:", xco+10, yco-44, 0.6 * (width-120), 19, + &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, + "Specify which joystick to use"); str= "Type %t|Button %x0|Axis %x1|Hat%x2"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, 0.6 * (width-20), 19, + uiDefButS(block, MENU, B_REDR, str, xco+87, yco-44, 0.6 * (width-150), 19, &joy->type, 0, 31, 0, 0, "The type of event this joystick sensor is triggered on."); @@ -1857,7 +1865,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, &ia->flag, 0, 0, 0, 0, - "Convert Ipo to force. Force is applied in global or local coordinate according to Local flag"); + "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); uiButSetFunc(but, change_ipo_actuator, but, ia); but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, @@ -1883,12 +1891,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh else { uiDefButI(block, NUM, 0, "Sta", xco+10, yco-44, (width-80)/2, 19, - &ia->sta, 0.0, MAXFRAMEF, 0, 0, - "Start frame, (subtract 1 to match blenders frame numbers)"); + &ia->sta, 1.0, MAXFRAMEF, 0, 0, + "Start frame"); uiDefButI(block, NUM, 0, "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, - &ia->end, 0.0, MAXFRAMEF, 0, 0, - "End frame, (subtract 1 to match blenders frame numbers)"); + &ia->end, 1.0, MAXFRAMEF, 0, 0, + "End frame"); } uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, "Child", xco+10+(width-80), yco-44, 60, 19, @@ -1917,7 +1925,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property"); } else { - uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value"); + uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value, use \"\" around strings"); } yco-= ysize; @@ -2022,7 +2030,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh if(eoa->type==ACT_EDOB_ADD_OBJECT) { int wval; /* just a temp width */ - ysize = 72; + ysize = 92; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); @@ -2042,9 +2050,27 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, eoa->linVelocity+2, -100.0, 100.0, 10, 0, "Velocity upon creation, z component."); - uiDefButBitS(block, TOG, 2, 0, "L", xco+45+3*wval, yco-68, 15, 19, + uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19, &eoa->localflag, 0.0, 0.0, 0, 0, "Apply the transformation locally"); + + + uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19, + NULL, 0, 0, 0, 0, + "Angular velocity upon creation."); + uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19, + eoa->angVelocity, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, x component."); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19, + eoa->angVelocity+1, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, y component."); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19, + eoa->angVelocity+2, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, z component."); + uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19, + &eoa->localflag, 0.0, 0.0, 0, 0, + "Apply the rotation locally"); + } else if(eoa->type==ACT_EDOB_END_OBJECT) { @@ -2270,13 +2296,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file"); uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation"); } -*/ else if (gma->type == ACT_GAME_RESTART) - { - ysize = 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (gma->type == ACT_GAME_QUIT) +*/ else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) { ysize = 28; glRects(xco, yco-ysize, xco+width, yco); @@ -2284,7 +2304,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh } //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3"; - str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3"; + str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save GameLogic.globalDict %x4|Load GameLogic.globalDict %x5"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); yco -= ysize; @@ -2324,7 +2344,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh visAct = act->data; - str= "Visibility %t|Visible %x0|Invisible %x1"; + str= "Visibility %t|Visible %x0|Invisible %x1|Visible Recursive %x2|Invisible Recursive %x3"; uiDefButI(block, MENU, B_REDR, str, xco + 10, yco - 24, width - 20, 19, &visAct->flag, @@ -2816,134 +2836,158 @@ void buttons_enji(uiBlock *block, Object *ob) void buttons_ketsji(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); - - uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,185,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use Fh settings in Materials"); - uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,185,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use face normal to rotate Object"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 110, 185, 80, 19, - &ob->mass, 0.01, 10000.0, 10, 0, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 190, 185, 80, 19, - &ob->inertia, 0.01, 10.0, 10, 0, - "Bounding sphere radius"); - uiDefButF(block, NUM, B_DIFF, "Form:", 270, 185, 80, 19, - &ob->formfactor, 0.01, 100.0, 10, 0, - "Form factor"); - - uiDefButF(block, NUM, B_DIFF, "Damp:", 10, 165, 100, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUM, B_DIFF, "RotDamp:", 110, 165, 120, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); - uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", - 230, 165, 120, 19, - &ob->gameflag, 0.0, 1.0, 10, 0, - "Enable anisotropic friction"); - } - - if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { - uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 145, 114, 19, - &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the x-direction."); - uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 145, 113, 19, - &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the y-direction."); - uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 145, 113, 19, - &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the z-direction."); - } - } - - if (!(ob->gameflag & OB_GHOST)) { + uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", + 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that have a physics representation"); + if (ob->gameflag & OB_PHYSICS) { uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", - 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are evaluated by the engine "); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); + + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); + + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + + uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,145,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use Fh settings in Materials"); + uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,145,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use face normal to rotate Object"); + uiDefButF(block, NUM, B_DIFF, "Form:", 110, 145, 120, 19, + &ob->formfactor, 0.01, 100.0, 10, 0, + "Form factor"); + + uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", + 230, 145, 120, 19, + &ob->gameflag, 0.0, 1.0, 10, 0, + "Enable anisotropic friction"); + } + + if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { + uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 125, 114, 19, + &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the x-direction."); + uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 125, 113, 19, + &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the y-direction."); + uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 125, 113, 19, + &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the z-direction."); + } + } + + if (!(ob->gameflag & OB_GHOST)) { + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 105, 75, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + if (ob->gameflag & OB_BOUNDS) { + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static TriangleMesh %x4", + 85, 105, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,105,100,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); + } + uiBlockEndAlign(block); } - uiBlockEndAlign(block); } } void buttons_bullet(uiBlock *block, Object *ob) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); + uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", + 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that have a physics representation"); + if (ob->gameflag & OB_PHYSICS) { + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are detected by the Near and Radar sensor"); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 170, 19, - &ob->mass, 0.01, 10000.0, 10, 2, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 180, 185, 170, 19, - &ob->inertia, 0.01, 10.0, 10, 2, - "Bounding sphere radius"); + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius, not used for other bounding shapes"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); - uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + } } - } - uiBlockEndAlign(block); + uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", - //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", - 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); + uiBlockBeginAlign(block); + if ((ob->gameflag & (OB_ACTOR|OB_DYNAMIC)) == (OB_ACTOR|OB_DYNAMIC)) { + if (ob->margin < 0.001f) + ob->margin = 0.06f; + uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, + &ob->margin, 0.001, 1.0, 1, 0, + "Collision margin"); + } else { + uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, + &ob->margin, 0.0, 1.0, 1, 0, + "Collision margin"); + } + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 115, 105, 55, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + if (ob->gameflag & OB_BOUNDS) { + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static Mesh%x4", + //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", + 170, 105, 105, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 275,105,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); + } + uiBlockEndAlign(block); } - uiBlockEndAlign(block); } static void check_object_state(void *arg1_but, void *arg2_mask) @@ -3079,6 +3123,9 @@ void logic_buts(void) int a, iact, stbit, offset; short xco, yco, count, width, ycoo; char *pupstr, name[32]; + /* pin is a bool used for actuator and sensor drawing with states + * pin so changing states dosnt hide the logic brick */ + char pin; wrld= G.scene->world; @@ -3109,7 +3156,7 @@ void logic_buts(void) uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 90, 340, 24, + uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 70, 340, 24, NULL, 0.0, 100.0, 100, 0, ""); @@ -3118,26 +3165,26 @@ void logic_buts(void) a= 0; prop= ob->prop.first; while(prop) { - but= uiDefBut(block, BUT, 1, "Del", 10, (short)(70-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); + but= uiDefBut(block, BUT, 1, "Del", 10, (short)(50-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); uiButSetFunc(but, del_property, prop, NULL); - uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(70-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); - but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(70-20*a), 110, 20, prop->name, 0, 31, 0, 0, ""); + uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(50-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); + but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(50-20*a), 110, 20, prop->name, 0, 31, 0, 0, "Available as GameObject attributes in the game engines python api"); uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1); if(prop->type==PROP_BOOL) { - uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); - uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); } else if(prop->type==PROP_INT) - uiDefButI(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); + uiDefButI(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); else if(prop->type==PROP_FLOAT) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); else if(prop->type==PROP_STRING) - uiDefBut(block, TEX, B_REDR, "", 220, (short)(70-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); + uiDefBut(block, TEX, B_REDR, "", 220, (short)(50-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); else if(prop->type==PROP_TIME) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); - uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(70-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); + uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(50-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); a++; prop= prop->next; @@ -3264,13 +3311,13 @@ void logic_buts(void) uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); uiBlockSetEmboss(block, UI_EMBOSSP); 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 mask"); + uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)"); uiBlockSetEmboss(block, UI_EMBOSSM); if(cont->flag & CONT_SHOW) { cont->otype= cont->type; - uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type"); - but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-166), 19, cont->name, 0, 31, 0, 0, "Controller name"); + 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-136), 19, cont->name, 0, 31, 0, 0, "Controller name"); uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); ycoo= yco; @@ -3280,9 +3327,9 @@ void logic_buts(void) 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, 100, 19, cont, 0, 0, 0, 0, "Controller type"); + but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, 19, cont, 0, 0, 0, 0, "Controller type"); uiButSetFunc(but, sca_move_controller, cont, NULL); - but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-166), 19, cont, 0, 0, 0, 0, "Controller name"); + but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-136), 19, cont, 0, 0, 0, 0, "Controller name"); uiButSetFunc(but, sca_move_controller, cont, NULL); ycoo= yco; } @@ -3339,18 +3386,26 @@ void logic_buts(void) sens= ob->sensors.first; while(sens) { if (!(G.buts->scaflag & BUTS_SENS_STATE) || - sens->totlinks == 0 || /* always display sensor without links so that is can be edited */ - is_sensor_linked(block, sens)) { + (sens->totlinks == 0) || /* always display sensor without links so that is can be edited */ + (sens->flag & SENS_PIN && G.buts->scaflag & BUTS_SENS_STATE) || /* states can hide some sensors, pinned sensors ignore the visible state */ + (is_sensor_linked(block, sens)) + ) { + /* should we draw the pin? - for now always draw when there is a state */ + pin = (G.buts->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1:0 ; + sens->flag |= SENS_VISIBLE; uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); + if (pin) + uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PIN_DEHLT, (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_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &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-124), 19, sens->name, 0, 31, 0, 0, "Sensor name"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens->name, 0, 31, 0, 0, "Sensor name"); uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); sens->otype= sens->type; @@ -3362,7 +3417,7 @@ void logic_buts(void) 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, ""); uiButSetFunc(but, sca_move_sensor, sens, NULL); - but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-124), 19, sens, 0, 31, 0, 0, ""); + but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens, 0, 31, 0, 0, ""); uiButSetFunc(but, sca_move_sensor, sens, NULL); } @@ -3411,16 +3466,22 @@ void logic_buts(void) while(act) { if (!(G.buts->scaflag & BUTS_ACT_STATE) || !(act->flag & ACT_LINKED) || /* always display actuators without links so that is can be edited */ - (act->flag & ACT_VISIBLE)) { /* this actuator has visible connection, display it */ + (act->flag & ACT_VISIBLE) || /* this actuator has visible connection, display it */ + (act->flag & ACT_PIN && G.buts->scaflag & BUTS_ACT_STATE)) { + + pin = (G.buts->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 */ uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator"); - uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings"); - + if (pin) + uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PIN_DEHLT, (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"); + 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-134), 19, act->name, 0, 31, 0, 0, "Actuator name"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), 19, act->name, 0, 31, 0, 0, "Actuator name"); uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0); ycoo= yco; @@ -3432,7 +3493,7 @@ void logic_buts(void) 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"); uiButSetFunc(but, sca_move_actuator, act, NULL); - but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-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)), 19, act, 0, 0, 0, 0, "Actuator name"); uiButSetFunc(but, sca_move_actuator, act, NULL); ycoo= yco; } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 78f19ad0608..a18950157b2 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -66,6 +66,7 @@ #include "BIF_glutil.h" #include "BIF_graphics.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_keyval.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" @@ -241,9 +242,9 @@ static void enable_constraint_ipo_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname); + verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname, 1); else - verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL); + verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL, 1); /* make sure ipowin shows it */ ob->ipowin= ID_CO; @@ -268,9 +269,9 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE, 1); else - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); if (!icu) { error("Cannot get a curve from this IPO, may be dealing with linked data"); @@ -2631,19 +2632,32 @@ static void object_panel_object(Object *ob) /* all groups */ for(group= G.main->group.first; group; group= group->id.next) { if(object_in_group(ob, group)) { - xco= 160; - - uiBlockBeginAlign(block); - uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */ - but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 150, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); - uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); - uiClearButLock(); + xco= 130; if(group->id.lib) { - but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 160, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local"); + uiBlockBeginAlign(block); + uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */ + uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 100, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); + uiClearButLock(); + + but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 110, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local"); uiButSetFunc(but, group_local, group, NULL); - xco= 180; - } else { /* cant remove objects from linked groups */ + uiBlockEndAlign(block); + } else { + but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 120, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); + uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); + } + + uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, REDRAWALL, "X:", xco+5, 120-yco, 50, 20, &group->dupli_ofs[0], -100000, 100000, 100, 0, "Offset to use when instacing the group"); + uiDefButF(block, NUM, REDRAWALL, "Y:", xco+55, 120-yco, 50, 20, &group->dupli_ofs[1], -100000, 100000, 100, 0, "Offset to use when instacing the group"); + uiDefButF(block, NUM, REDRAWALL, "Z:", xco+105, 120-yco, 50, 20, &group->dupli_ofs[2], -100000, 100000, 100, 0, "Offset to use when instacing the group"); + uiBlockEndAlign(block); + uiClearButLock(); + + xco = 290; + if(group->id.lib==0) { /* cant remove objects from linked groups */ but = uiDefIconBut(block, BUT, B_NOP, VICON_X, xco, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove Group membership"); uiButSetFunc(but, group_ob_rem, group, ob); } @@ -2971,7 +2985,8 @@ void do_effects_panels(unsigned short event) psmd= (ParticleSystemModifierData*) md; psmd->psys=psys; BLI_addtail(&ob->modifiers, md); - } + } else + id->us--; idtest->us++; psys->part=(ParticleSettings*)idtest; @@ -3029,7 +3044,7 @@ void do_effects_panels(unsigned short event) if(ob && (psys=psys_get_current(ob))){ if(psys->part) { if(psys->part->id.us>1){ - if(okee("Make local")){ + if(okee("Make Single User")){ part=psys_copy_settings(psys->part); part->id.us=1; psys->part->id.us--; diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 5205be3e1b0..f2e20356f21 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -211,9 +211,15 @@ void do_soundbuts(unsigned short event) case B_SOUND_MENU_SAMPLE: if (G.buts->menunr > 0) { sample = BLI_findlink(samples, G.buts->menunr - 1); - if (sample && sound) { + if (sample && sound && sound->sample != sample) { + int wasrelative = (strncmp(sound->name, "//", 2)==0); + BLI_strncpy(sound->name, sample->name, sizeof(sound->name)); sound_set_sample(sound, sample); + + if (wasrelative) + BLI_makestringcode(G.sce, sound->name); + do_soundbuts(B_SOUND_REDRAW); } } diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 1b580381ca5..6d5e1a62ad4 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -113,6 +113,8 @@ #include "RE_pipeline.h" +#include "GPU_material.h" + /* -----includes for this file specific----- */ #include "butspace.h" // own module @@ -209,6 +211,7 @@ static void load_image_cb(char *str, void *ima_pp_v, void *iuser_v) /* called fr if(GS(tex->id.name)==ID_TE) { BIF_preview_changed(ID_TE); allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); } } @@ -1542,10 +1545,35 @@ static void texture_panel_colors(Tex *tex) uiDefButF(block, NUMSLI, B_TEXPRV, "Contr", 160,10,150,20, &tex->contrast, 0.01, 5.0, 0, 0, "Changes the contrast of the color or intensity of a texture"); } - -static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) +static int texture_channels_num_display(MTex **mtex) { - MTex *mt=NULL; + int a, num_mtex; + + if(!mtex) + return 0; + + /* compute number of texture channels to draw, 1 more + * than the last, used texture channel, and at least 10 */ + num_mtex = 0; + + for(a=MAX_MTEX-1; a>=0; a--) { + if (mtex[a]) { + num_mtex = a+1; + break; + } + } + + if (num_mtex < 10) + return 10; + else if(num_mtex < MAX_MTEX) + return num_mtex + 1; + else + return MAX_MTEX; +} + +static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) +{ + MTex **mtex, *mt; uiBlock *block; ID *id=NULL, *idfrom; int a, yco, loos; @@ -1556,17 +1584,35 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l if(uiNewPanel(curarea, block, "Texture", "Texture", 320, 0, 318, 204)==0) return; /* first do the browse but */ - if(mtex) - id= (ID *)mtex->tex; + if(actmtex) + id= (ID *)actmtex->tex; else if(node) id= node->id; - if(ma) idfrom= &ma->id; - else if(wrld) idfrom= &wrld->id; - else if(la) idfrom= &la->id; - else if(br) idfrom= &br->id; - else if(sd) idfrom= NULL; /* Not sure what this does */ - else idfrom= NULL; + if(ma) { + idfrom= &ma->id; + mtex= ma->mtex; + } + else if(wrld) { + idfrom= &wrld->id; + mtex= wrld->mtex; + } + else if(la) { + idfrom= &la->id; + mtex= la->mtex; + } + else if(br) { + idfrom= &br->id; + mtex= br->mtex; + } + else if(sd) { + idfrom= NULL; /* Not sure what this does */ + mtex= sd->mtex; + } + else { + idfrom= NULL; + mtex= NULL; + } uiBlockSetCol(block, TH_BUT_SETTING2); if(ma) { @@ -1595,15 +1641,13 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l /* CHANNELS */ if(node==NULL) { + int num_mtex; uiBlockBeginAlign(block); yco= 150; - for(a= 0; amtex[a]; - else if(wrld) mt= wrld->mtex[a]; - else if(la) mt= la->mtex[a]; - else if(br) mt= br->mtex[a]; - else if(sd) mt= sd->mtex[a]; + + num_mtex= texture_channels_num_display(mtex); + for(a=0; atex) splitIDname(mt->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2030,7 +2074,7 @@ static void world_panel_texture(World *wrld) uiBlock *block; MTex *mtex; ID *id; - int a, loos; + int a, loos, num_mtex; char str[64], *strp; block= uiNewBlock(&curarea->uiblocks, "world_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -2041,7 +2085,8 @@ static void world_panel_texture(World *wrld) /* TEX CHANNELS */ uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - for(a= 0; amtex); + for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2506,7 +2551,7 @@ static void lamp_panel_texture(Object *ob, Lamp *la) uiBlock *block; MTex *mtex; ID *id; - int a, loos; + int a, loos, num_mtex; char *strp, str[64]; block= uiNewBlock(&curarea->uiblocks, "lamp_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -2517,7 +2562,8 @@ static void lamp_panel_texture(Object *ob, Lamp *la) /* TEX CHANNELS */ uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - for(a= 0; amtex); + for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2603,9 +2649,9 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButBitI(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); if(la->type==LA_SPOT) { - uiDefButBitS(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); + uiDefButBitI(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); if(la->mode & LA_SHAD_BUF) { char *tip= "Regular buffer type"; if(la->buftype==LA_SHADBUF_IRREGULAR) @@ -2618,12 +2664,15 @@ static void lamp_panel_spot(Object *ob, Lamp *la) } uiBlockEndAlign(block); - uiDefButBitS(block, TOG, LA_ONLYSHADOW, B_LAMPPRV,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, LA_ONLYSHADOW, B_LAMPPRV,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); + uiDefButBitI(block, TOG, LA_LAYER_SHADOW, B_LAMPPRV,"Layer", 10,90,80,19,&la->mode, 0, 0, 0, 0, "Causes only objects on the same layer to cast shadows"); + uiBlockEndAlign(block); if(la->type==LA_SPOT) { uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); - uiDefButBitS(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,40,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); + uiDefButBitI(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); + uiDefButBitI(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,40,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); uiBlockBeginAlign(block); uiDefButF(block, NUMSLI,B_LAMPREDRAW,"SpotSi ", 100,180,200,19,&la->spotsize, 1.0, 180.0, 0, 0, "Sets the angle of the spotlight beam in degrees"); @@ -2747,12 +2796,12 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) /* in yafray arealights always cast shadows, so ray shadow flag not needed */ /* ray shadow also not used when halo for spot enabled */ if ((la->type!=LA_AREA) && (!((la->type==LA_SPOT) && (la->mode & LA_HALO)))) - uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButBitI(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); /* in yafray the regular lamp can use shadowbuffers (softlight), used by spot with halo as well */ /* to prevent clash with blender shadowbuf flag, a special flag is used for yafray */ if (la->type==LA_LOCAL) { - uiDefButBitS(block, TOG, LA_YF_SOFT, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets light produce shadows using shadow buffer"); + uiDefButBitI(block, TOG, LA_YF_SOFT, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets light produce shadows using shadow buffer"); uiDefButF(block, NUM, B_DIFF, "GloInt:", 100,155,200,19, &la->YF_glowint, 0.0, 1.0, 1, 0, "Sets light glow intensity, 0 is off"); uiDefButF(block, NUM, B_DIFF, "GloOfs:", 100,135,100,19, &la->YF_glowofs, 0.0, 2.0, 1, 0, "Sets light glow offset, the higher, the less 'peaked' the glow"); uiDefButS(block, NUM, B_DIFF, "GlowType:", 200,135,100,19, &la->YF_glowtype, 0, 1, 1, 0, "Sets light glow type"); @@ -2780,7 +2829,7 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) if (la->type==LA_SPOT) { - uiDefButBitS(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,50,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); + uiDefButBitI(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,50,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); @@ -2900,15 +2949,15 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButS(block, MENU, B_LAMPREDRAW, "Falloff %t|Constant %x0|Inverse Linear %x1|Inverse Square %x2|Custom Curve %x3|Lin/Quad Weighted %x4|", 10,150,100,19, &la->falloff_type, 0,0,0,0, "Lamp falloff - intensity decay with distance"); - uiDefButBitS(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); + uiDefButBitI(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); } uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButBitS(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); - uiDefButBitS(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); - uiDefButBitS(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); - uiDefButBitS(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); + uiDefButBitI(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); + uiDefButBitI(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); + uiDefButBitI(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); + uiDefButBitI(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_AUTO); @@ -3523,7 +3572,7 @@ static void material_panel_texture(Object *ob, Material *ma) ID *id; ParticleSystem *psys; int loos, psys_mapto=0; - int a; + int a, num_mtex; char str[64], *strp; block= uiNewBlock(&curarea->uiblocks, "material_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -3539,7 +3588,8 @@ static void material_panel_texture(Object *ob, Material *ma) uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - for(a= 0; amtex); + for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -3553,10 +3603,10 @@ static void material_panel_texture(Object *ob, Material *ma) /* SEPTEX */ uiBlockSetCol(block, TH_AUTO); - for(a= 0; amtex[a]; if(mtex && mtex->tex) { - but=uiDefIconButBitS(block, ICONTOGN, 1<septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel"); + but=uiDefIconButBitI(block, ICONTOGN, 1<septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel"); if(psys_mapto && ma->mtex[a]->mapto & MAP_PA_IVEL) uiButSetFunc(but, particle_recalc_material, ma, NULL); @@ -4091,13 +4141,14 @@ static void material_panel_material(Material *ma) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButBitI(block, TOG, MA_VERTEXCOL, B_MAT_VCOL_LIGHT, "VCol Light", 8,166,74,20, &(ma->mode), 0, 0, 0, 0, "Adds vertex colors as extra light"); uiDefButBitI(block, TOG, MA_VERTEXCOLP, B_MAT_VCOL_PAINT, "VCol Paint", 82,166,74,20, &(ma->mode), 0, 0, 0, 0, "Replaces material's colors with vertex colors"); - uiDefButBitI(block, TOG, MA_FACETEXTURE, B_REDR, "TexFace", 156,166,64,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); - if (ma->mode & MA_FACETEXTURE) uiDefButBitI(block, TOG, MA_FACETEXTURE_ALPHA, B_REDR, "A", 220,166,20,20, &(ma->mode), 0, 0, 0, 0, "Use alpha channel in 'TexFace' assigned images"); - uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 240,166,63,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); + uiDefButBitI(block, TOG, MA_FACETEXTURE, B_MATPRV, "TexFace", 156,166,60,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); + uiDefButBitI(block, TOG, MA_FACETEXTURE_ALPHA, B_MATPRV, "A", 216,166,20,20, &(ma->mode), 0, 0, 0, 0, "Use alpha channel in 'TexFace' assigned images"); + uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 236,166,67,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); - uiDefButBitI(block, TOG, MA_NOMIST, B_NOP, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); + uiDefButBitI(block, TOG, MA_NOMIST, B_MATPRV, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); uiDefButBitI(block, TOG, MA_ENV, B_MATPRV, "Env", 82,146,74,20, &(ma->mode), 0, 0, 0, 0, "Causes faces to render with alpha zero: allows sky/backdrop to show through (only for solid faces)"); - uiDefButF(block, NUM, B_NOP, "Shad A ", 156,146,147,19, &ma->shad_alpha, 0.001, 1.0f, 100, 0, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); + uiDefButBitS(block, TOG, MA_OBCOLOR, B_MATPRV, "ObColor", 156,146,60,20, &(ma->shade_flag), 0, 0, 0, 0, "Modulate the result with a per object color"); + uiDefButF(block, NUM, B_NOP, "Shad A ", 216,146,87,20, &ma->shad_alpha, 0.001, 1.0f, 10, 2, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); } uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 0782ccfc7ee..f36719a1c9c 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -78,6 +78,7 @@ #include "BIF_drawgpencil.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BIF_keyframing.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_mywindow.h" @@ -682,6 +683,18 @@ static void draw_channel_names(void) special= ICON_SEQUENCE; } break; + case SPACE_IMAGE: + { + SpaceImage *sima= sa->spacedata.first; + + if (sima->image) + sprintf(name, "Image: %s", sima->image->id.name+2); + else + sprintf(name, "Image: "); + + special= ICON_IMAGE_COL; + } + break; default: { diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 6d78b21dfbb..c37eaf7986c 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -2505,6 +2505,9 @@ int draw_armature(Base *base, int dt, int flag) Object *ob= base->object; bArmature *arm= ob->data; int retval= 0; + + if(G.f & G_SIMULATION) + return 1; if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) { /* we use color for solid lighting */ diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index f60d53a9c5d..fb21d94f39a 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -60,6 +60,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" +#include "BIF_drawseq.h" #include "BIF_graphics.h" #include "BIF_interface.h" #include "BIF_mywindow.h" @@ -97,6 +98,8 @@ void gp_ui_activelayer_cb (void *gpd, void *gpl) { gpencil_layer_setactive(gpd, gpl); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -108,6 +111,8 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128); gpencil_layer_setactive(gpd, gpl); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -115,6 +120,8 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) void gp_ui_addlayer_cb (void *gpd, void *dummy) { gpencil_layer_addnew(gpd); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -122,6 +129,8 @@ void gp_ui_addlayer_cb (void *gpd, void *dummy) void gp_ui_dellayer_cb (void *gpd, void *dummy) { gpencil_layer_delactive(gpd); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -132,6 +141,8 @@ void gp_ui_delstroke_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_frame_delete_laststroke(gpf); + + scrarea_queue_winredraw(curarea); } /* delete active frame of active layer */ @@ -142,9 +153,19 @@ void gp_ui_delframe_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_layer_delframe(gpl, gpf); + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } +/* convert the active layer to geometry */ +void gp_ui_convertlayer_cb (void *gpd, void *gpl) +{ + gpencil_layer_setactive(gpd, gpl); + gpencil_convert_menu(); + + scrarea_queue_winredraw(curarea); +} + /* ------- Drawing Code ------- */ /* draw the controls for a given layer */ @@ -166,7 +187,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short /* rounded header */ if (active) uiBlockSetCol(block, TH_BUT_ACTION); rb_col= (active)?-20:20; - uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); + uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); if (active) uiBlockSetCol(block, TH_AUTO); /* lock toggle */ @@ -177,7 +198,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) { char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */ - height= 26; + height= 0; /* visibility button (only if hidden but not locked!) */ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) @@ -249,8 +270,14 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short /* options */ uiBlockBeginAlign(block); - but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); - uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); + if (curarea->spacetype == SPACE_VIEW3D) { + but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)"); + uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl); + } + else { + but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); + uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); + } but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)"); uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl); @@ -297,7 +324,7 @@ short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa) /* 'view align' button (naming depends on context) */ if (sa->spacetype == SPACE_VIEW3D) uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space"); - else if (sa->spacetype != SPACE_SEQ) /* not available for sequencer yet */ + else uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas"); } @@ -323,6 +350,9 @@ enum { GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */ }; +/* thickness above which we should use special drawing */ +#define GP_DRAWTHICKNESS_SPECIAL 3 + /* ----- Tool Buffer Drawing ------ */ /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ @@ -347,23 +377,13 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick glEnd(); } else if (sflag & GP_STROKE_ERASER) { - /* draw stroke curve - just standard thickness */ - setlinestyle(4); - glLineWidth(1.0f); - - glBegin(GL_LINE_STRIP); - for (i=0, pt=points; i < totpoints && pt; i++, pt++) { - glVertex2f(pt->x, pt->y); - } - glEnd(); - - setlinestyle(0); + /* don't draw stroke at all! */ } else { float oldpressure = 0.0f; /* draw stroke curve */ - setlinestyle(2); + if (G.f & G_DEBUG) setlinestyle(2); glBegin(GL_LINE_STRIP); for (i=0, pt=points; i < totpoints && pt; i++, pt++) { @@ -381,14 +401,14 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick } glEnd(); - setlinestyle(0); + if (G.f & G_DEBUG) setlinestyle(0); } } /* ----- Existing Strokes Drawing (3D and Point) ------ */ /* draw a given stroke - just a single dot (only one point) */ -static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int winy) +static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sflag, int offsx, int offsy, int winx, int winy) { /* draw point */ if (sflag & GP_STROKE_3DSPACE) { @@ -396,18 +416,42 @@ static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int glVertex3f(points->x, points->y, points->z); glEnd(); } - else if (sflag & GP_STROKE_2DSPACE) { - glBegin(GL_POINTS); - glVertex2f(points->x, points->y); - glEnd(); - } else { - const float x= (points->x / 1000 * winx); - const float y= (points->y / 1000 * winy); + float co[2]; - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); + /* get coordinates of point */ + if (sflag & GP_STROKE_2DSPACE) { + co[0]= points->x; + co[1]= points->y; + } + else if (sflag & GP_STROKE_2DIMAGE) { + co[0]= (points->x * winx) + offsx; + co[1]= (points->y * winy) + offsy; + } + else { + co[0]= (points->x / 1000 * winx); + co[1]= (points->y / 1000 * winy); + } + + /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple opengl point will do */ + if (thickness < GP_DRAWTHICKNESS_SPECIAL) { + glBegin(GL_POINTS); + glVertex2fv(co); + glEnd(); + } + else { + /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */ + GLUquadricObj *qobj = gluNewQuadric(); + + gluQuadricDrawStyle(qobj, GLU_FILL); + + /* need to translate drawing position, but must reset after too! */ + glTranslatef(co[0], co[1], 0.); + gluDisk( qobj, 0.0, thickness, 32, 1); + glTranslatef(-co[0], -co[1], 0.); + + gluDeleteQuadric(qobj); + } } } @@ -447,10 +491,15 @@ static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thicknes /* ----- Fancy 2D-Stroke Drawing ------ */ /* draw a given stroke in 2d */ -static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) +static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, + short debug, int offsx, int offsy, int winx, int winy) { - /* if thickness is less than 3, 'smooth' opengl lines look better */ - if (thickness < 3) { + /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better + * - but NOT if Image Editor 'image-based' stroke + */ + if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || + ((curarea->spacetype==SPACE_IMAGE) && (dflag & GP_DRAWDATA_ONLYV2D)) ) + { bGPDspoint *pt; int i; @@ -459,6 +508,12 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } + else if (sflag & GP_STROKE_2DIMAGE) { + const float x= (pt->x * winx) + offsx; + const float y= (pt->y * winy) + offsy; + + glVertex2f(x, y); + } else { const float x= (pt->x / 1000 * winx); const float y= (pt->y / 1000 * winy); @@ -468,7 +523,10 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, } glEnd(); } - else { /* tesselation code: currently only enabled with rt != 0 */ + + /* tesselation code: currently only enabled with rt != 0 */ + else + { bGPDspoint *pt1, *pt2; float pm[2]; int i; @@ -488,6 +546,12 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, s0[0]= pt1->x; s0[1]= pt1->y; s1[0]= pt2->x; s1[1]= pt2->y; } + else if (sflag & GP_STROKE_2DIMAGE) { + s0[0]= (pt1->x * winx) + offsx; + s0[1]= (pt1->y * winy) + offsy; + s1[0]= (pt2->x * winx) + offsx; + s1[1]= (pt2->y * winy) + offsy; + } else { s0[0]= (pt1->x / 1000 * winx); s0[1]= (pt1->y / 1000 * winy); @@ -630,6 +694,12 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } + else if (sflag & GP_STROKE_2DIMAGE) { + const float x= (pt->x * winx) + offsx; + const float y= (pt->y * winy) + offsy; + + glVertex2f(x, y); + } else { const float x= (pt->x / 1000 * winx); const float y= (pt->y / 1000 * winy); @@ -644,8 +714,8 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, /* ----- General Drawing ------ */ /* draw a set of strokes */ -static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, short debug, - short lthick, float color[4]) +static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, + short debug, short lthick, float color[4]) { bGPDstroke *gps; @@ -671,16 +741,16 @@ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, shor /* check which stroke-drawer to use */ if (gps->totpoints == 1) - gp_draw_stroke_point(gps->points, gps->flag, winx, winy); + gp_draw_stroke_point(gps->points, lthick, gps->flag, offsx, offsy, winx, winy); else if (dflag & GP_DRAWDATA_ONLY3D) gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); else if (gps->totpoints > 1) - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy); } } /* draw grease-pencil datablock */ -static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) +static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int dflag) { bGPDlayer *gpl, *actlay=NULL; @@ -732,7 +802,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ tcolor[3] = color[3] - (i/gpl->gstep); - gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -744,7 +814,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) if ((gf->framenum - gpf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ tcolor[3] = color[3] - (i/gpl->gstep); - gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -757,12 +827,12 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->prev) { tcolor[3] = (color[3] / 7); - gp_draw_strokes(gpf->prev, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } if (gpf->next) { tcolor[3] = (color[3] / 4); - gp_draw_strokes(gpf->next, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } /* restore alpha */ @@ -772,7 +842,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* draw the strokes already in active frame */ tcolor[3]= color[3]; - gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) @@ -840,16 +910,69 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) void draw_gpencil_2dimage (ScrArea *sa, ImBuf *ibuf) { bGPdata *gpd; - int dflag = 0; + int offsx, offsy, sizex, sizey; + int dflag = GP_DRAWDATA_NOSTATUS; /* check that we have grease-pencil stuff to draw */ if (ELEM(NULL, sa, ibuf)) return; gpd= gpencil_data_getactive(sa); if (gpd == NULL) return; + /* calculate rect */ + switch (sa->spacetype) { + case SPACE_IMAGE: /* image */ + { + SpaceImage *sima= (SpaceImage *)sa->spacedata.first; + + /* just draw using standard scaling (settings here are currently ignored anyways) */ + // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled + offsx= 0; + offsy= 0; + sizex= sa->winx; + sizey= sa->winy; + + myortho2(sima->v2d.cur.xmin, sima->v2d.cur.xmax, sima->v2d.cur.ymin, sima->v2d.cur.ymax); + + dflag |= GP_DRAWDATA_ONLYV2D; + } + break; + + case SPACE_SEQ: /* sequence */ + { + SpaceSeq *sseq= (SpaceSeq *)sa->spacedata.first; + float zoom, zoomx, zoomy; + + /* calculate accessory values */ + zoom= SEQ_ZOOM_FAC(sseq->zoom); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); + zoomy = zoom; + } + else + zoomx = zoomy = zoom; + + sizex= zoomx * ibuf->x; + sizey= zoomy * ibuf->y; + offsx= (sa->winx-sizex)/2 + sseq->xof; + offsy= (sa->winy-sizey)/2 + sseq->yof; + + dflag |= GP_DRAWDATA_ONLYI2D; + } + break; + + default: /* for spacetype not yet handled */ + offsx= 0; + offsy= 0; + sizex= sa->winx; + sizey= sa->winy; + + dflag |= GP_DRAWDATA_ONLYI2D; + break; + } + + /* draw it! */ - dflag = (GP_DRAWDATA_ONLYI2D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, offsx, offsy, sizex, sizey, dflag); } /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly @@ -867,7 +990,7 @@ void draw_gpencil_2dview (ScrArea *sa, short onlyv2d) /* draw it! */ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, 0, 0, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly @@ -884,7 +1007,7 @@ void draw_gpencil_3dview (ScrArea *sa, short only3d) /* draw it! */ if (only3d) dflag |= (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, 0, 0, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to opengl render window assuming that matrices are already set correctly */ @@ -898,7 +1021,7 @@ void draw_gpencil_oglrender (View3D *v3d, int winx, int winy) if (gpd == NULL) return; /* pass 1: draw 3d-strokes ------------ > */ - gp_draw_data(gpd, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D)); + gp_draw_data(gpd, 0, 0, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D)); /* pass 2: draw 2d-strokes ------------ > */ /* adjust view matrices */ @@ -906,7 +1029,7 @@ void draw_gpencil_oglrender (View3D *v3d, int winx, int winy) glLoadIdentity(); /* draw it! */ - gp_draw_data(gpd, winx, winy, GP_DRAWDATA_NOSTATUS); + gp_draw_data(gpd, 0, 0, winx, winy, GP_DRAWDATA_NOSTATUS); } /* ************************************************** */ diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 14849cdd450..97765690ceb 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -52,6 +52,7 @@ #include "DNA_camera_types.h" #include "DNA_color_types.h" #include "DNA_image_types.h" +#include "DNA_gpencil_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_node_types.h" @@ -79,6 +80,7 @@ #include "BDR_editface.h" #include "BDR_drawobject.h" #include "BDR_drawmesh.h" +#include "BDR_gpencil.h" #include "BDR_imagepaint.h" #include "BIF_cursors.h" @@ -86,6 +88,7 @@ #include "BIF_graphics.h" #include "BIF_mywindow.h" #include "BIF_drawimage.h" +#include "BIF_drawgpencil.h" #include "BIF_resources.h" #include "BIF_interface.h" #include "BIF_interface_icons.h" @@ -1778,6 +1781,45 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PREVI } +static void image_panel_gpencil(short cntrl) // IMAGE_HANDLER_GREASEPENCIL +{ + uiBlock *block; + SpaceImage *sima; + + sima= curarea->spacedata.first; + + block= uiNewBlock(&curarea->uiblocks, "image_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL); // for close and esc + if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return; + + /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */ + if (sima->flag & SI_DISPGP) { + if (sima->gpd == NULL) + gpencil_data_setactive(curarea, gpencil_data_addnew()); + } + + if (sima->flag & SI_DISPGP) { + bGPdata *gpd= sima->gpd; + short newheight; + + /* this is a variable height panel, newpanel doesnt force new size on existing panels */ + /* so first we make it default height */ + uiNewPanelHeight(block, 204); + + /* draw button for showing gpencil settings and drawings */ + uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)"); + + /* extend the panel if the contents won't fit */ + newheight= draw_gpencil_panel(block, gpd, curarea); + uiNewPanelHeight(block, newheight); + } + else { + uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor"); + uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + } +} + static void image_blockhandlers(ScrArea *sa) { SpaceImage *sima= sa->spacedata.first; @@ -1788,7 +1830,6 @@ static void image_blockhandlers(ScrArea *sa) for(a=0; ablockhandler[a]) { - case IMAGE_HANDLER_PROPERTIES: image_panel_properties(sima->blockhandler[a+1]); break; @@ -1806,7 +1847,10 @@ static void image_blockhandlers(ScrArea *sa) break; case IMAGE_HANDLER_PREVIEW: image_panel_preview(sa, sima->blockhandler[a+1]); - break; + break; + case IMAGE_HANDLER_GREASEPENCIL: + image_panel_gpencil(sima->blockhandler[a+1]); + break; } /* clear action value for event */ sima->blockhandler[a+1]= 0; @@ -2339,9 +2383,17 @@ void drawimagespace(ScrArea *sa, void *spacedata) } draw_image_transform(ibuf, xuser_asp, yuser_asp); + + /* draw grease-pencil ('image' strokes) */ + if (sima->flag & SI_DISPGP) + draw_gpencil_2dimage(sa, ibuf); mywinset(sa->win); /* restore scissor after gla call... */ myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); + + /* draw grease-pencil (screen strokes) */ + if (sima->flag & SI_DISPGP) + draw_gpencil_2dview(sa, 0); if(G.rendering==0) { draw_image_view_tool(); diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 71854570c8c..ec6a0f0d75b 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -442,7 +442,7 @@ int in_ipo_buttons(void) else return 1; } -static View2D *spacelink_get_view2d(SpaceLink *sl) +View2D *spacelink_get_view2d(SpaceLink *sl) { if(sl->spacetype==SPACE_IPO) return &((SpaceIpo *)sl)->v2d; @@ -921,6 +921,13 @@ void drawscroll(int disptype) BIF_ThemeColor(TH_TEXT); val= ipogrid_startx; + + if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) { /* prevents printing twice same frame */ + while(ipogrid_dx < 0.9999f) { + ipogrid_dx *= 2.0f; + dfac*= 2.0f; + } + } while(fac < hor.xmax) { if(curarea->spacetype==SPACE_OOPS) { @@ -1945,7 +1952,7 @@ void do_ipobuts(unsigned short event) ei= get_active_editipo(); if(ei) { if(ei->icu==NULL) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (!ei->icu) { error("Could not add a driver to this curve, may be linked data!"); break; diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index 09f74c01c71..8f22c704fd0 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -76,534 +76,12 @@ #include "BSE_drawview.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + #include "blendef.h" #include "nla.h" -#ifndef GL_CLAMP_TO_EDGE -#define GL_CLAMP_TO_EDGE 0x812F -#endif - -//#include "glext.h" -/* some local functions */ -#if defined(GL_EXT_texture_object) && (!defined(__sun__) || (!defined(__sun))) && !defined(__APPLE__) && !defined(__linux__) && !defined(WIN32) - #define glBindTexture(A,B) glBindTextureEXT(A,B) - #define glGenTextures(A,B) glGenTexturesEXT(A,B) - #define glDeleteTextures(A,B) glDeleteTexturesEXT(A,B) - #define glPolygonOffset(A,B) glPolygonOffsetEXT(A,B) - -#else - -/* #define GL_FUNC_ADD_EXT GL_FUNC_ADD */ -/* #define GL_FUNC_REVERSE_SUBTRACT_EXT GL_FUNC_REVERSE_SUBTRACT */ -/* #define GL_POLYGON_OFFSET_EXT GL_POLYGON_OFFSET */ - -#endif - - /* (n&(n-1)) zeros the least significant bit of n */ -static int is_pow2(int num) { - return ((num)&(num-1))==0; -} -static int smaller_pow2(int num) { - while (!is_pow2(num)) - num= num&(num-1); - return num; -} - -/* These are used to enable texture clamping */ -static int is_pow2_limit(int num) { - if (U.glreslimit != 0 && num > U.glreslimit) return 0; - return ((num)&(num-1))==0; -} - -static int smaller_pow2_limit(int num) { - if (U.glreslimit != 0 && num > U.glreslimit) - return U.glreslimit; - return smaller_pow2(num); -} - -static int fCurtile=0, fCurmode=0,fCurtileXRep=0,fCurtileYRep=0; -static Image *fCurpage=0; -static short fTexwindx, fTexwindy, fTexwinsx, fTexwinsy; -static int fDoMipMap = 1; -static int fLinearMipMap = 0; - -/* local prototypes --------------- */ -void update_realtime_textures(void); - - -/* static int source, dest; also not used */ - -/** - * Enables or disable mipmapping for realtime images. - * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0). - */ -void set_mipmap(int mipmap) -{ - if (fDoMipMap != (mipmap != 0)) { - free_all_realtime_images(); - fDoMipMap = mipmap != 0; - } -} - -/** - * Returns the current setting for mipmapping. - */ -static int get_mipmap(void) -{ - return fDoMipMap && (!(G.f & G_TEXTUREPAINT)); -} - -/** - * Enables or disable linear mipmap setting for realtime images (textures). - * Note that this will will destroy all texture bindings in OpenGL. - * @see free_realtime_image() - * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0). - */ -void set_linear_mipmap(int linear) -{ - if (fLinearMipMap != (linear != 0)) { - free_all_realtime_images(); - fLinearMipMap = linear != 0; - } -} - -/** - * Returns the current setting for linear mipmapping. - */ -int get_linear_mipmap(void) -{ - return fLinearMipMap; -} - - -/** - * Resets the realtime image cache variables. - */ -void clear_realtime_image_cache() -{ - fCurpage = NULL; - fCurtile = 0; - fCurmode = 0; - fCurtileXRep = 0; - fCurtileYRep = 0; -} - -/* REMEMBER! Changes here must go into my_set_tpage() as well */ -int set_tpage(MTFace *tface) -{ - static int alphamode= -1; - static MTFace *lasttface= 0; - Image *ima; - ImBuf *ibuf; - unsigned int *rect=NULL, *bind; - int tpx=0, tpy=0, tilemode, tileXRep,tileYRep; - - /* disable */ - if(tface==0) { - if(lasttface==0) return 0; - - lasttface= 0; - fCurtile= 0; - fCurpage= 0; - if(fCurmode!=0) { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - } - fCurmode= 0; - fCurtileXRep=0; - fCurtileYRep=0; - alphamode= -1; - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glDisable ( GL_ALPHA_TEST ); - return 0; - } - lasttface= tface; - - if( alphamode != tface->transp) { - alphamode= tface->transp; - - if(alphamode) { - if(alphamode==TF_ADD) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable ( GL_ALPHA_TEST ); - /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ - } - else if(alphamode==TF_ALPHA) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* added after 2.45 to clip alpha */ - - /*if U.glalphaclip == 1.0, some cards go bonkers... turn off alpha test in this case*/ - if(U.glalphaclip == 1.0) glDisable(GL_ALPHA_TEST); - else{ - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc ( GL_GREATER, U.glalphaclip ); - } - } else if (alphamode==TF_CLIP){ - glDisable(GL_BLEND); - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc(GL_GREATER, 0.5f); - } - /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ - /* else { */ - /* glBlendFunc(GL_ONE, GL_ONE); */ - /* glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */ - /* } */ - } else { - glDisable(GL_BLEND); - glDisable ( GL_ALPHA_TEST ); - } - } - - ima= tface->tpage; - - /* Enable or disable reflection mapping */ - if (ima && (ima->flag & IMA_REFLECT)){ - -// glActiveTextureARB(GL_TEXTURE0_ARB); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - - /* Handle multitexturing here */ - } - else{ - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - } - - tilemode= tface->mode & TF_TILES; - tileXRep = 0; - tileYRep = 0; - if (ima) { - tileXRep = ima->xrep; - tileYRep = ima->yrep; - } - - - if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0; - - if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep) { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - if(tilemode && ima!=NULL) - glScalef(ima->xrep, ima->yrep, 1.0); - - glMatrixMode(GL_MODELVIEW); - } - - if(ima==NULL || ima->ok==0) { - glDisable(GL_TEXTURE_2D); - - fCurtile= tface->tile; - fCurpage= 0; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - return 0; - } - - ibuf= BKE_image_get_ibuf(ima, NULL); - if(ibuf==NULL) { - - fCurtile= tface->tile; - fCurpage= 0; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - glDisable(GL_TEXTURE_2D); - return 0; - } - - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - - if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe; - else fCurtile= tface->tile; - - if(tilemode) { - if(ima->repbind==0) make_repbind(ima); - - if(fCurtile>=ima->totbind) fCurtile= 0; - - /* this happens when you change repeat buttons */ - if(ima->repbind) bind= ima->repbind+fCurtile; - else bind= &ima->bindcode; - - if(*bind==0) { - - fTexwindx= ibuf->x/ima->xrep; - fTexwindy= ibuf->y/ima->yrep; - - if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1; - - fTexwinsy= fCurtile / ima->xrep; - fTexwinsx= fCurtile - fTexwinsy*ima->xrep; - - fTexwinsx*= fTexwindx; - fTexwinsy*= fTexwindy; - - tpx= fTexwindx; - tpy= fTexwindy; - - rect= ibuf->rect + fTexwinsy*ibuf->x + fTexwinsx; - } - } - else { - bind= &ima->bindcode; - - if(*bind==0) { - tpx= ibuf->x; - tpy= ibuf->y; - rect= ibuf->rect; - } - } - - if(*bind==0) { - int rectw= tpx, recth= tpy; - unsigned int *tilerect= NULL, *scalerect= NULL; - - /* - * Maarten: - * According to Ton this code is not needed anymore. It was used only - * in really old Blenders. - * Reevan: - * Actually it is needed for backwards compatibility. Simpledemo 6 does not display correctly without it. - */ -#if 1 - if (tilemode) { - int y; - - tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); - for (y=0; yx]; - unsigned int *tilerectrow= &tilerect[y*rectw]; - - memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); - } - - rect= tilerect; - } -#endif - if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { - rectw= smaller_pow2_limit(rectw); - recth= smaller_pow2_limit(recth); - - scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); - rect= scalerect; - } - - glGenTextures(1, (GLuint *)bind); - - if((G.f & G_DEBUG) || !*bind) { - GLenum error = glGetError(); - printf("Texture: %s\n", ima->id.name+2); - printf("name: %d, tpx: %d\n", *bind, tpx); - printf("tile: %d, mode: %d\n", fCurtile, tilemode); - if (error) - printf("error: %s\n", gluErrorString(error)); - } - glBindTexture( GL_TEXTURE_2D, *bind); - - if (!get_mipmap()) - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } else - { - int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; - - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - ima->tpageflag |= IMA_MIPMAP_COMPLETE; - } - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (tilerect) - MEM_freeN(tilerect); - if (scalerect) - MEM_freeN(scalerect); - } - else glBindTexture( GL_TEXTURE_2D, *bind); - - /* dont tile x/y as set the the game properties */ - if (ima->tpageflag & IMA_CLAMP_U) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - if (ima->tpageflag & IMA_CLAMP_V) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - /* tag_image_time(ima);*/ /* Did this get lost in the image recode? */ - - glEnable(GL_TEXTURE_2D); - - fCurpage= ima; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - return 1; -} - -void update_realtime_image(Image *ima, int x, int y, int w, int h) -{ - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - - if (ima->repbind || get_mipmap() || !ima->bindcode || !ibuf || - (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || - (w == 0) || (h == 0)) { - /* these special cases require full reload still */ - free_realtime_image(ima); - } - else { - int row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); - int skip_pixels = glaGetOneInteger(GL_UNPACK_SKIP_PIXELS); - int skip_rows = glaGetOneInteger(GL_UNPACK_SKIP_ROWS); - - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); - glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); - - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } -} - -void free_realtime_image(Image *ima) -{ - if(ima->bindcode) { - glDeleteTextures(1, (GLuint *)&ima->bindcode); - ima->bindcode= 0; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } - if(ima->repbind) { - glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - - MEM_freeN(ima->repbind); - ima->repbind= NULL; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } -} - -void free_all_realtime_images(void) -{ - Image* ima; - - for(ima=G.main->image.first; ima; ima=ima->id.next) - free_realtime_image(ima); -} - -/* these two functions are called on entering and exiting texture paint mode, - temporary disabling/enabling mipmapping on all images for quick texture - updates with glTexSubImage2D. images that didn't change don't have to be - re-uploaded to OpenGL */ -void texpaint_disable_mipmap(void) -{ - Image* ima; - - if(!fDoMipMap) - return; - - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->bindcode) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - } -} - -void texpaint_enable_mipmap(void) -{ - Image* ima; - - if(!fDoMipMap) - return; - - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->bindcode) { - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { - int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; - - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - free_realtime_image(ima); - } - } -} - -void make_repbind(Image *ima) -{ - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - - if(ibuf==NULL) return; - - if(ima->repbind) { - glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - MEM_freeN(ima->repbind); - ima->repbind= 0; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } - ima->totbind= ima->xrep*ima->yrep; - if(ima->totbind>1) { - ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); - } -} - -void update_realtime_textures() -{ - Image *ima; - - ima= G.main->image.first; - while(ima) { - if(ima->tpageflag & IMA_TWINANIM) { - if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; - - /* check: is bindcode not in the array? Free. (to do) */ - - ima->lastframe++; - if(ima->lastframe > ima->twend) ima->lastframe= ima->twsta; - - } - ima= ima->id.next; - } -} - /***/ /* Flags for marked edges */ @@ -627,7 +105,7 @@ static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flag *flags_p |= flags; } -EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) +static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) { EdgeHash *eh = BLI_edgehash_new(); int i; @@ -775,81 +253,6 @@ static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm) BLI_edgehash_free(data.eh, NULL); } -static int set_gl_light(Object *ob) -{ - Base *base; - Lamp *la; - int count; - /* float zero[4]= {0.0, 0.0, 0.0, 0.0}; */ - float vec[4]; - - vec[3]= 1.0; - - for(count=0; count<8; count++) glDisable(GL_LIGHT0+count); - - count= 0; - - base= FIRSTBASE; - while(base) { - if(base->object->type==OB_LAMP ) { - if(base->lay & G.vd->lay) { - if(base->lay & ob->lay) - { - la= base->object->data; - - glPushMatrix(); - glLoadMatrixf((float *)G.vd->viewmat); - - where_is_object_simul(base->object); - VECCOPY(vec, base->object->obmat[3]); - - if(la->type==LA_SUN) { - vec[0]= base->object->obmat[2][0]; - vec[1]= base->object->obmat[2][1]; - vec[2]= base->object->obmat[2][2]; - vec[3]= 0.0; - glLightfv(GL_LIGHT0+count, GL_POSITION, vec); - } - else { - vec[3]= 1.0; - glLightfv(GL_LIGHT0+count, GL_POSITION, vec); - glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); - /* post 2.25 engine supports quad lights */ - glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); - - if(la->type==LA_SPOT) { - vec[0]= -base->object->obmat[2][0]; - vec[1]= -base->object->obmat[2][1]; - vec[2]= -base->object->obmat[2][2]; - glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, vec); - glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0); - glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend); - } - else glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); - } - - vec[0]= la->energy*la->r; - vec[1]= la->energy*la->g; - vec[2]= la->energy*la->b; - vec[3]= 1.0; - glLightfv(GL_LIGHT0+count, GL_DIFFUSE, vec); - glLightfv(GL_LIGHT0+count, GL_SPECULAR, vec);//zero); - glEnable(GL_LIGHT0+count); - - glPopMatrix(); - - count++; - if(count>7) break; - } - } - } - base= base->next; - } - - return count; -} - static Material *give_current_material_or_def(Object *ob, int matnr) { extern Material defmaterial; // render module abuse... @@ -893,9 +296,9 @@ static int set_draw_settings_cached(int clearcache, int textured, MTFace *texfac if (textured!=c_textured || texface!=c_texface) { if (textured ) { - c_badtex= !set_tpage(texface); + c_badtex= !GPU_set_tpage(texface); } else { - set_tpage(0); + GPU_set_tpage(0); c_badtex= 0; } c_textured= textured; @@ -950,7 +353,7 @@ static void draw_textured_begin(Object *ob) } else /* draw with lights in the scene otherwise */ - Gtexdraw.islit= set_gl_light(ob); + Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat); obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); @@ -971,12 +374,12 @@ static void draw_textured_begin(Object *ob) static void draw_textured_end() { /* switch off textures */ - set_tpage(0); + GPU_set_tpage(0); glShadeModel(GL_FLAT); glDisable(GL_CULL_FACE); - /* XXX, bad patch - default_gl_light() calls + /* XXX, bad patch - GPU_default_lights() calls * glLightfv(GL_LIGHT_POSITION, ...) which * is transformed by the current matrix... we * need to make sure that matrix is identity. @@ -987,7 +390,7 @@ static void draw_textured_end() */ glPushMatrix(); glLoadIdentity(); - default_gl_light(); + GPU_default_lights(); glPopMatrix(); } @@ -1057,50 +460,71 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot return 1; } -static void draw_game_text_mesh(Object *ob, Mesh *me) +void draw_mesh_text(Object *ob, int glsl) { - DerivedMesh *ddm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); - MFace *mface= me->mface; + Mesh *me = ob->data; + DerivedMesh *ddm; + MFace *mf, *mface= me->mface; MTFace *tface= me->mtface; MCol *mcol= me->mcol; /* why does mcol exist? */ bProperty *prop = get_property(ob, "Text"); - int a, start= 0, totface= me->totface; + GPUVertexAttribs gattribs; + int a, totface= me->totface; - tface+= start; - mcol+= start*4; - for (a=start; amode; int matnr= mf->mat_nr; int mf_smooth= mf->flag & ME_SMOOTH; if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) { - int badtex= set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE); float v1[3], v2[3], v3[3], v4[3]; char string[MAX_PROPSTRING]; - int characters, index; - ImBuf *ibuf; - float curpos; + int characters, i, glattrib= -1, badtex= 0; - if (badtex) - continue; + if(glsl) { + GPU_enable_material(matnr+1, &gattribs); + + for(i=0; igetVertCo(ddm, mf->v1, v1); ddm->getVertCo(ddm, mf->v2, v2); ddm->getVertCo(ddm, mf->v3, v3); if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4); - // The BM_FONT handling code is duplicated in the gameengine - // Search for 'Frank van Beek' ;-) - // string = "Frank van Beek"; + // The BM_FONT handling is in the gpu module, shared with the + // game engine, was duplicated previously set_property_valstr(prop, string); characters = strlen(string); - ibuf= BKE_image_get_ibuf(tface->tpage, NULL); - if (ibuf == NULL) { + if(!BKE_image_get_ibuf(tface->tpage, NULL)) characters = 0; - } if (!mf_smooth) { float nor[3]; @@ -1110,46 +534,11 @@ static void draw_game_text_mesh(Object *ob, Mesh *me) glNormal3fv(nor); } - curpos= 0.0; - glBegin(mf->v4?GL_QUADS:GL_TRIANGLES); - for (index = 0; index < characters; index++) { - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - int character = string[index]; - char *cp= NULL; - - // lets calculate offset stuff - // space starts at offset 1 - // character = character - ' ' + 1; - - matrixGlyph(ibuf, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - movex+= curpos; - - if (tface->mode & TF_OBCOL) - glColor3ubv(Gtexdraw.obcol); - else if (me->mcol) cp= (char *)mcol; - else glColor3ub(255, 255, 255); - - glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - - glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(mf->v4) { - glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[15], cp[14], cp[13]); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - - curpos+= advance; - } - glEnd(); + GPU_render_text(tface, tface->mode, string, characters, + (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib); + } + if (mcol) { + mcol+=4; } } @@ -1159,7 +548,6 @@ static void draw_game_text_mesh(Object *ob, Mesh *me) void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) { Mesh *me= ob->data; - int editing= 0; /* correct for negative scale */ if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); @@ -1168,38 +556,20 @@ void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) /* draw the textured mesh */ draw_textured_begin(ob); -#ifdef WITH_VERSE - if(me->vnode) { - /* verse-blender doesn't support uv mapping of textures yet */ - dm->drawFacesTex(dm, NULL); - } - else { -#endif - if(ob==G.obedit) { - dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh); - } else if(faceselect) { - if(G.f & G_WEIGHTPAINT) - dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); - else - dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me); - } + if(ob==G.obedit) { + dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh); + } else if(faceselect) { + if(G.f & G_WEIGHTPAINT) + dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); else - dm->drawFacesTex(dm, draw_tface__set_draw); -#ifdef WITH_VERSE + dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me); } -#endif + else + dm->drawFacesTex(dm, draw_tface__set_draw); - /* draw game engine text hack - but not if we are editing the mesh */ - if (me->mtface && get_property(ob, "Text")) { - if(ob==G.obedit) - editing= 1; - else if(ob==OBACT) - if(FACESEL_PAINT_TEST) - editing= 1; - - if(!editing) - draw_game_text_mesh(ob, me); - } + /* draw game engine text hack */ + if(get_property(ob, "Text")) + draw_mesh_text(ob, 0); draw_textured_end(); @@ -1214,10 +584,3 @@ void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } -void init_realtime_GL(void) -{ - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); -} - diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 213f49528f0..4876e6cae7c 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -93,6 +93,7 @@ #include "BKE_object.h" #include "BKE_anim.h" //for the where_on_path function #include "BKE_particle.h" +#include "BKE_property.h" #include "BKE_utildefines.h" #ifdef WITH_VERSE #include "BKE_verse.h" @@ -129,6 +130,10 @@ #include "BKE_deform.h" +#include "GPU_draw.h" +#include "GPU_material.h" +#include "GPU_extensions.h" + /* pretty stupid */ /* extern Lattice *editLatt; already in BKE_lattice.h */ /* editcurve.c */ @@ -143,114 +148,37 @@ static void drawcircle_size(float size); static void draw_empty_sphere(float size); static void draw_empty_cone(float size); -/* ************* Setting OpenGL Material ************ */ +/* check for glsl drawing */ -// Materials start counting at # one.... -#define MAXMATBUF (MAXMAT + 1) -static float matbuf[MAXMATBUF][2][4]; -static int totmat_gl= 0; - -int set_gl_material(int nr) +int draw_glsl_material(Object *ob, int dt) { - static int last_gl_matnr= -1; - static int last_ret_val= 1; + if(!GPU_extensions_minimum_support()) + return 0; + if(G.f & G_PICKSEL) + return 0; + if(!CHECK_OB_DRAWTEXTURE(G.vd, dt)) + return 0; + if(ob==OBACT && (G.f & G_WEIGHTPAINT)) + return 0; - /* prevent index to use un-initialized array items */ - if(nr>totmat_gl) nr= totmat_gl; - - if(nr<0) { - last_gl_matnr= -1; - last_ret_val= 1; - } - else if(nr= OB_SHADED)); } -/* returns 1: when there's alpha needed to be drawn in a 2nd pass */ -int init_gl_materials(Object *ob, int check_alpha) +static int check_material_alpha(Base *base, Object *ob, int glsl) { - extern Material defmaterial; // render module abuse... - Material *ma; - int a, has_alpha= 0; - - if(ob->totcol==0) { - matbuf[0][0][0]= defmaterial.r; - matbuf[0][0][1]= defmaterial.g; - matbuf[0][0][2]= defmaterial.b; - matbuf[0][0][3]= 1.0; + if(base->flag & OB_FROMDUPLI) + return 0; - matbuf[0][1][0]= defmaterial.specr; - matbuf[0][1][1]= defmaterial.specg; - matbuf[0][1][2]= defmaterial.specb; - matbuf[0][1][3]= 1.0; - - /* do material 1 too, for displists! */ - QUATCOPY(matbuf[1][0], matbuf[0][0]); - QUATCOPY(matbuf[1][1], matbuf[0][1]); - } - - for(a=1; a<=ob->totcol; a++) { - ma= give_current_material(ob, a); - ma= editnode_get_active_material(ma); - if(ma==NULL) ma= &defmaterial; - - if(amode & MA_SHLESS) { - matbuf[a][0][0]= ma->r; - matbuf[a][0][1]= ma->g; - matbuf[a][0][2]= ma->b; - } else { - matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r; - matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; - matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; - } - - /* draw transparent, not in pick-select, nor editmode */ - if(check_alpha && !(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) { - if(G.vd->transp) { // drawing the transparent pass - if(ma->alpha==1.0) matbuf[a][0][3]= 0.0; // means skip solid - else matbuf[a][0][3]= ma->alpha; - } - else { // normal pass - if(ma->alpha==1.0) matbuf[a][0][3]= 1.0; - else { - matbuf[a][0][3]= 0.0; // means skip transparent - has_alpha= 1; // return value, to indicate adding to after-draw queue - } - } - } - else - matbuf[a][0][3]= 1.0; + if(G.f & G_PICKSEL) + return 0; - if (!(ma->mode & MA_SHLESS)) { - matbuf[a][1][0]= ma->spec*ma->specr; - matbuf[a][1][1]= ma->spec*ma->specg; - matbuf[a][1][2]= ma->spec*ma->specb; - matbuf[a][1][3]= 1.0; - } - } - } - - totmat_gl= ob->totcol; - set_gl_material(-1); // signal for static variable - return has_alpha; + if(G.obedit && G.obedit->data==ob->data) + return 0; + + return (glsl || (ob->dtx & OB_DRAWTRANSP)); } - /***/ static unsigned int colortab[24]= {0x0, 0xFF88FF, 0xFFBBFF, @@ -352,6 +280,9 @@ void drawaxes(float size, int flag, char drawtype) float v1[3]= {0.0, 0.0, 0.0}; float v2[3]= {0.0, 0.0, 0.0}; float v3[3]= {0.0, 0.0, 0.0}; + + if(G.f & G_SIMULATION) + return; switch(drawtype) { @@ -734,6 +665,9 @@ static void drawlamp(Object *ob) float pixsize, lampsize; float imat[4][4], curcol[4]; char col[4]; + + if(G.f & G_SIMULATION) + return; la= ob->data; @@ -1024,6 +958,9 @@ static void drawcamera(Object *ob, int flag) float vec[8][4], tmat[4][4], fac, facx, facy, depth; int i; + if(G.f & G_SIMULATION) + return; + cam= ob->data; glDisable(GL_LIGHTING); @@ -1830,6 +1767,9 @@ static void draw_verse_debug(Object *ob, EditMesh *em) struct EditFace *efa=NULL; float v1[3], v2[3], v3[3], v4[3], fvec[3], col[3]; char val[32]; + + if(G.f & G_SIMULATION) + return; if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) glDisable(GL_DEPTH_TEST); @@ -1894,6 +1834,9 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em) char conv_float[5]; /* Use a float conversion matching the grid size */ float area, col[3]; /* area of the face, color of the text to draw */ + if(G.f & G_SIMULATION) + return; + /* make the precission of the pronted value proportionate to the gridsize */ if ((G.vd->grid) < 0.01) strcpy(conv_float, "%.6f"); @@ -2054,12 +1997,20 @@ static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth EditFace *efa = EM_get_face_for_index(index); if (efa->h==0) { - set_gl_material(efa->mat_nr+1); + GPU_enable_material(efa->mat_nr+1, NULL); return 1; - } else { - return 0; } + else + return 0; } + +static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index) +{ + EditFace *efa = EM_get_face_for_index(index); + + return (efa->h==0); +} + static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt) { Mesh *me = ob->data; @@ -2082,9 +2033,21 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived EM_init_index_arrays(1, 1, 1); if(dt>OB_WIRE) { - if( CHECK_OB_DRAWTEXTURE(G.vd, dt) ) { - draw_mesh_textured(ob, finalDM, 0); - } else { + if(CHECK_OB_DRAWTEXTURE(G.vd, dt)) { + if(draw_glsl_material(ob, dt)) { + glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); + + finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material, + draw_em_fancy__setGLSLFaceOpts, NULL); + GPU_disable_material(); + + glFrontFace(GL_CCW); + } + else { + draw_mesh_textured(ob, finalDM, 0); + } + } + else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED); glEnable(GL_LIGHTING); @@ -2208,6 +2171,7 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived if(dt>OB_WIRE) { glDepthMask(1); bglPolygonOffset(0.0); + GPU_disable_material(); } EM_free_index_arrays(); @@ -2226,8 +2190,9 @@ static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) drawFacesSolid() doesn't draw the transparent faces */ if(ob->dtx & OB_DRAWTRANSP) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - dm->drawFacesSolid(dm, set_gl_material); + dm->drawFacesSolid(dm, GPU_enable_material); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + GPU_disable_material(); } else { dm->drawEdges(dm, 0); @@ -2312,7 +2277,19 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) draw_mesh_object_outline(ob, dm); } - draw_mesh_textured(ob, dm, faceselect); + if(draw_glsl_material(ob, dt)) { + glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); + + dm->drawFacesGLSL(dm, GPU_enable_material); + if(get_property(ob, "Text")) + draw_mesh_text(ob, 1); + GPU_disable_material(); + + glFrontFace(GL_CCW); + } + else { + draw_mesh_textured(ob, dm, faceselect); + } if(!faceselect) { if(base->flag & SELECT) @@ -2323,18 +2300,17 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->drawLooseEdges(dm); } } - else if(dt==OB_SOLID ) { - - if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { + else if(dt==OB_SOLID) { + if((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) draw_mesh_object_outline(ob, dm); - } glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED ); glEnable(GL_LIGHTING); glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); - dm->drawFacesSolid(dm, set_gl_material); + dm->drawFacesSolid(dm, GPU_enable_material); + GPU_disable_material(); glFrontFace(GL_CCW); glDisable(GL_LIGHTING); @@ -2352,7 +2328,8 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) if(ob==OBACT) { do_draw= 0; if( (G.f & G_WEIGHTPAINT)) { - set_gl_material(0); /* enforce defmaterial settings */ + /* enforce default material settings */ + GPU_enable_material(0, NULL); /* but set default spec */ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); @@ -2367,6 +2344,8 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1); glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); + + GPU_disable_material(); } else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) { dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1); @@ -2385,7 +2364,7 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->release(dm); shadeDispList(base); dl = find_displist(&ob->disp, DL_VERTCOL); - dm= mesh_get_derived_final(ob, get_viewedit_datamask()); + dm= mesh_get_derived_final(ob, get_viewedit_datamask()); } if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { @@ -2462,7 +2441,7 @@ static int draw_mesh_object(Base *base, int dt, int flag) { Object *ob= base->object; Mesh *me= ob->data; - int has_alpha= 0, drawlinked= 0, retval= 0; + int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha; if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) { if(ob_get_key(ob)); @@ -2478,7 +2457,12 @@ static int draw_mesh_object(Base *base, int dt, int flag) cageDM = editmesh_get_derived_cage_and_final(&finalDM, get_viewedit_datamask()); - if(dt>OB_WIRE) init_gl_materials(ob, 0); // no transp in editmode, the fancy draw over goes bad then + if(dt>OB_WIRE) { + // no transp in editmode, the fancy draw over goes bad then + glsl = draw_glsl_material(ob, dt); + GPU_set_object_materials(G.scene, ob, glsl, NULL); + } + draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt); if (G.obedit!=ob && finalDM) @@ -2491,15 +2475,22 @@ static int draw_mesh_object(Base *base, int dt, int flag) else { /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */ if(me->totface<=4 || boundbox_clip(ob->obmat, (ob->bb)? ob->bb: me->bb)) { - if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0); + glsl = draw_glsl_material(ob, dt); + check_alpha = check_material_alpha(base, ob, glsl); + + if(dt==OB_SOLID || glsl) { + GPU_set_object_materials(G.scene, ob, glsl, + (check_alpha)? &do_alpha_pass: NULL); + } + draw_mesh_fancy(base, dt, flag); if(me->totvert==0) retval= 1; } } - /* init_gl_materials did the proper checking if this is needed */ - if(has_alpha) add_view3d_after(G.vd, base, V3D_TRANSP, flag); + /* GPU_set_object_materials checked if this is needed */ + if(do_alpha_pass) add_view3d_after(G.vd, base, V3D_TRANSP, flag); return retval; } @@ -2601,9 +2592,10 @@ static int drawDispListwire(ListBase *dlbase) return 0; } -static void drawDispListsolid(ListBase *lb, Object *ob) +static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) { DispList *dl; + GPUVertexAttribs gattribs; float *data, curcol[4]; float *ndata; @@ -2667,7 +2659,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob) case DL_SURF: if(dl->index) { - set_gl_material(dl->col+1); + GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); @@ -2675,12 +2667,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob) glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index); + GPU_disable_material(); } break; case DL_INDEX3: - - set_gl_material(dl->col+1); + GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); glVertexPointer(3, GL_FLOAT, 0, dl->verts); @@ -2693,6 +2685,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob) glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index); + GPU_disable_material(); if(index3_nors_incr==0) glEnableClientState(GL_NORMAL_ARRAY); @@ -2700,12 +2693,13 @@ static void drawDispListsolid(ListBase *lb, Object *ob) break; case DL_INDEX4: - - set_gl_material(dl->col+1); + GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index); + + GPU_disable_material(); break; } @@ -2799,14 +2793,18 @@ static int drawDispList(Base *base, int dt) draw_index_wire= 1; } else { - if(dt==OB_SHADED) { + if(draw_glsl_material(ob, dt)) { + GPU_set_object_materials(G.scene, ob, 1, NULL); + drawDispListsolid(lb, ob, 1); + } + else if(dt == OB_SHADED) { if(ob->disp.first==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob, 0); + GPU_set_object_materials(G.scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob); + drawDispListsolid(lb, ob, 0); } if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) { cpack(0); @@ -2833,15 +2831,19 @@ static int drawDispList(Base *base, int dt) if(dl->nors==NULL) addnormalsDispList(ob, lb); - if(dt==OB_SHADED) { + if(draw_glsl_material(ob, dt)) { + GPU_set_object_materials(G.scene, ob, 1, NULL); + drawDispListsolid(lb, ob, 1); + } + else if(dt==OB_SHADED) { if(ob->disp.first==NULL) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob, 0); + GPU_set_object_materials(G.scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob); + drawDispListsolid(lb, ob, 0); } } else { @@ -2857,16 +2859,20 @@ static int drawDispList(Base *base, int dt) if(solid) { - if(dt==OB_SHADED) { + if(draw_glsl_material(ob, dt)) { + GPU_set_object_materials(G.scene, ob, 1, NULL); + drawDispListsolid(lb, ob, 1); + } + else if(dt == OB_SHADED) { dl= lb->first; if(dl && dl->col1==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob, 0); + GPU_set_object_materials(G.scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob); + drawDispListsolid(lb, ob, 0); } } else{ @@ -4624,9 +4630,8 @@ static void drawSolidSelect(Base *base) drawDispListwire(&ob->disp); } else if(ob->type==OB_ARMATURE) { - if(!(ob->flag & OB_POSEMODE)) { + if(!(ob->flag & OB_POSEMODE)) draw_armature(base, OB_WIRE, 0); - } } glLineWidth(1.0); @@ -5094,8 +5099,9 @@ void draw_object(Base *base, int flag) drawlattice(ob); break; case OB_ARMATURE: - if(dt>OB_WIRE) set_gl_material(0); // we use defmaterial + if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material empty_object= draw_armature(base, dt, flag); + if(dt>OB_WIRE) GPU_disable_material(); break; default: drawaxes(1.0, flag, OB_ARROWS); @@ -5138,9 +5144,8 @@ void draw_object(Base *base, int flag) } /* draw extra: after normal draw because of makeDispList */ - if(dtx) { - if(G.f & G_SIMULATION); - else if(dtx & OB_AXIS) { + if(dtx && !(G.f & G_SIMULATION)) { + if(dtx & OB_AXIS) { drawaxes(1.0f, flag, OB_ARROWS); } if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob); @@ -5411,19 +5416,6 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot } } -static int bbs_mesh_wire__setDrawOpts(void *userData, int index) -{ - struct { Mesh *me; EdgeHash *eh; int offset; } *data = userData; - MEdge *med = data->me->medge + index; - uintptr_t flags = (intptr_t)BLI_edgehash_lookup(data->eh, med->v1, med->v2); - - if (flags & 1) { - set_framebuffer_index_color(data->offset+index); - return 1; - } else - return 0; -} - /* TODO remove this - since face select mode now only works with painting */ static void bbs_mesh_solid(Object *ob) { @@ -5433,22 +5425,6 @@ static void bbs_mesh_solid(Object *ob) glColor3ub(0, 0, 0); dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0); - /* draw edges for seam marking in faceselect mode, but not when painting, - so that painting doesn't get interrupted on an edge */ - if ((G.f & G_FACESELECT) && !(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))) { - struct { Mesh *me; EdgeHash *eh; int offset; } userData; - - userData.me = me; - userData.eh = get_tface_mesh_marked_edge_info(me); - userData.offset = userData.me->totface+1; - - bglPolygonOffset(1.0); - dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOpts, (void*)&userData); - bglPolygonOffset(0.0); - - BLI_edgehash_free(userData.eh, NULL); - } - dm->release(dm); } @@ -5504,6 +5480,7 @@ void draw_object_backbufsel(Object *ob) static void draw_object_mesh_instance(Object *ob, int dt, int outline) { DerivedMesh *dm=NULL, *edm=NULL; + int glsl; if(G.obedit && ob->data==G.obedit->data) edm= editmesh_get_derived_base(); @@ -5520,8 +5497,10 @@ static void draw_object_mesh_instance(Object *ob, int dt, int outline) if(outline) draw_mesh_object_outline(ob, dm?dm:edm); - if(dm) - init_gl_materials(ob, 0); + if(dm) { + glsl = draw_glsl_material(ob, dt); + GPU_set_object_materials(G.scene, ob, glsl, NULL); + } else { glEnable(GL_COLOR_MATERIAL); BIF_ThemeColor(TH_BONE_SOLID); @@ -5532,8 +5511,10 @@ static void draw_object_mesh_instance(Object *ob, int dt, int outline) glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); glEnable(GL_LIGHTING); - if(dm) - dm->drawFacesSolid(dm, set_gl_material); + if(dm) { + dm->drawFacesSolid(dm, GPU_enable_material); + GPU_disable_material(); + } else if(edm) edm->drawMappedFaces(edm, NULL, NULL, 0); diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index 71a777c9056..d7346a1ed21 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -922,17 +922,11 @@ static void draw_image_seq(ScrArea *sa) if(ibuf->rect_float && ibuf->rect==NULL) IMB_rect_from_float(ibuf); - - if (sseq->zoom > 0) { - zoom = sseq->zoom; - } else if (sseq->zoom == 0) { - zoom = 1.0; - } else { - zoom = -1.0/sseq->zoom; - } - + /* needed for gla draw */ glaDefine2DArea(&curarea->winrct); + + zoom= SEQ_ZOOM_FAC(sseq->zoom); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); zoomy = zoom; @@ -976,7 +970,10 @@ static void draw_image_seq(ScrArea *sa) setlinestyle(0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } - + + /* draw grease-pencil (image aligned) */ + if (sseq->flag & SEQ_DRAW_GPENCIL) + draw_gpencil_2dimage(sa, ibuf); if (free_ibuf) { IMB_freeImBuf(ibuf); diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 71f0bbef7ca..3f21d32c2d4 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #ifdef HAVE_CONFIG_H #include @@ -60,6 +62,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_suggestions.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -74,32 +77,84 @@ #include "BIF_space.h" #include "BIF_mywindow.h" #include "BIF_resources.h" +#include "BIF_mainqueue.h" #include "BSE_filesel.h" #include "BPY_extern.h" +#include "BPY_menus.h" #include "mydevice.h" #include "blendef.h" #include "winlay.h" -#define TEXTXLOC 38 +/***********************/ /* + +Notes on word-wrap +-- +All word-wrap functions follow the algorithm below to maintain consistency. + line The line to wrap (tabs converted to spaces) + view_width The maximum number of characters displayable in the region + This equals region_width/font_width for the region + wrap_chars Characters that allow wrapping. This equals [' ', '\t', '-'] + +def wrap(line, view_width, wrap_chars): + draw_start = 0 + draw_end = view_width + pos = 0 + for c in line: + if pos-draw_start >= view_width: + print line[draw_start:draw_end] + draw_start = draw_end + draw_end += view_width + elif c in wrap_chars: + draw_end = pos+1 + pos += 1 + print line[draw_start:] + +*/ /***********************/ + +#define TEXTXLOC 38 + +#define SUGG_LIST_SIZE 7 +#define SUGG_LIST_WIDTH 20 +#define DOC_WIDTH 40 +#define DOC_HEIGHT 10 + +#define TOOL_SUGG_LIST 0x01 +#define TOOL_DOCUMENT 0x02 + +#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */ +#define TMARK_GRP_FINDALL 0x00020000 /* forward declarations */ void drawtextspace(ScrArea *sa, void *spacedata); void winqreadtextspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); void txt_copy_selectbuffer (Text *text); -void do_brackets(); +void draw_brackets(SpaceText *st); -void get_selection_buffer(Text *text); -int check_bracket(char *string); -static int check_delim(char *string); -static int check_numbers(char *string); -static int check_builtinfuncs(char *string); -static int check_specialvars(char *string); +static void get_selection_buffer(Text *text); +static int check_bracket(char ch); +static int check_delim(char ch); +static int check_digit(char ch); +static int check_identifier(char ch); +static int check_whitespace(char ch); -static void *last_txt_find_string= NULL; +static int get_wrap_width(SpaceText *st); +static int get_wrap_points(SpaceText *st, char *line); +static void get_suggest_prefix(Text *text, int offset); +static void confirm_suggestion(Text *text, int skipleft); + +#define TXT_MAXFINDSTR 255 +static int g_find_flags= TXT_FIND_WRAP; +static char *g_find_str= NULL; +static char *g_replace_str= NULL; + +static int doc_scroll= 0; +static double last_check_time= 0; +static int jump_to= 0; +static double last_jump= 0; static BMF_Font *spacetext_get_font(SpaceText *st) { static BMF_Font *scr12= NULL; @@ -160,7 +215,8 @@ static void temp_char_write(char c, int accum) { void free_txt_data(void) { txt_free_cut_buffer(); - if (last_txt_find_string) MEM_freeN(last_txt_find_string); + if (g_find_str) MEM_freeN(g_find_str); + if (g_replace_str) MEM_freeN(g_replace_str); if (temp_char_buf) MEM_freeN(temp_char_buf); if (temp_char_accum) MEM_freeN(temp_char_accum); } @@ -184,352 +240,279 @@ static int render_string (SpaceText *st, char *in) { return r; } -void get_format_string(SpaceText *st) +static int find_builtinfunc(char *string) { - Text *text = st->text; - TextLine *tmp; - char *in_line; - char format[2000], check[200], other[2]; - unsigned char c; - int spot, letter, tabs, mem_amount; - size_t a, b, len; - - if(!text) return; - tmp = text->lines.first; - - while(tmp) { - in_line = tmp->line; - - len = strlen(in_line); - /* weak code... but we dont want crashes (ton) */ - if(len>2000-1) { - if (tmp->format) MEM_freeN(tmp->format); - tmp->format= NULL; + int a, i; + char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def", + "del", "elif", "else", "except", "exec", "finally", + "for", "from", "global", "if", "import", "in", + "is", "lambda", "not", "or", "pass", "print", + "raise", "return", "try", "while", "yield"}; + for (a=0; a<30; a++) { + i = 0; + while (1) { + if (builtinfuncs[a][i]=='\0') { + if (check_identifier(string[i])) + i = -1; + break; + } else if (string[i]!=builtinfuncs[a][i]) { + i = -1; + break; + } + i++; } + if (i>0) break; + } + return i; +} + +static int find_specialvar(char *string) +{ + int i = 0; + if (string[0]=='d' && string[1]=='e' && string[2]=='f') + i = 3; + else if (string[0]=='c' && string[1]=='l' && string[2]=='a' && string[3]=='s' && string[4]=='s') + i = 5; + if (i==0 || check_identifier(string[i])) + return -1; + return i; +} + +static void print_format(SpaceText *st, TextLine *line) { + int i, a; + char *s, *f; + s = line->line; + f = line->format; + for (a=0; *s; s++) { + if (*s == '\t') { + for (i=st->tabnumber-(a%st->tabnumber); i>0; i--) + printf(" "), f++, a++; + } else + printf("%c", *s), f++, a++; + } + printf("\n%s [%#x]\n", line->format, (int) (f[strlen(f)+1])); +} + +/* Ensures the format string for the given line is long enough, reallocating as needed */ +static int check_format_len(TextLine *line, unsigned int len) { + if (line->format) { + if (strlen(line->format) < len) { + MEM_freeN(line->format); + line->format = MEM_mallocN(len+2, "SyntaxFormat"); + if (!line->format) return 0; + } + } else { + line->format = MEM_mallocN(len+2, "SyntaxFormat"); + if (!line->format) return 0; + } + return 1; +} + +/* Formats the specified line and if allowed and needed will move on to the + * next line. The format string contains the following characters: + * '_' Whitespace + * '#' Comment text + * '!' Punctuation and other symbols + * 'n' Numerals + * 'l' String letters + * 'v' Special variables (class, def) + * 'b' Built-in names (print, for, etc.) + * 'q' Other text (identifiers, etc.) + * It is terminated with a null-terminator '\0' followed by a continuation + * flag indicating whether the line is part of a multi-line string. + */ +void txt_format_line(SpaceText *st, TextLine *line, int do_next) { + char *str, *fmt, orig, cont, find, prev = ' '; + int len, i; + + /* Get continuation from previous line */ + if (line->prev && line->prev->format != NULL) { + fmt= line->prev->format; + cont = fmt[strlen(fmt)+1]; /* Just after the null-terminator */ + } else cont = 0; + + /* Get original continuation from this line */ + if (line->format != NULL) { + fmt= line->format; + orig = fmt[strlen(fmt)+1]; /* Just after the null-terminator */ + } else orig = 0xFF; + + render_string(st, line->line); + str = temp_char_buf; + len = strlen(str); + if (!check_format_len(line, len)) return; + fmt = line->format; + + while (*str) { + /* Handle escape sequences by skipping both \ and next char */ + if (*str == '\\') { + *fmt = prev; fmt++; str++; + if (*str == '\0') break; + *fmt = prev; fmt++; str++; + continue; + } + /* Handle continuations */ + else if (cont) { + /* Triple strings ("""...""" or '''...''') */ + if (cont & TXT_TRISTR) { + find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; + if (*str==find && *(str+1)==find && *(str+2)==find) { + *fmt = 'l'; fmt++; str++; + *fmt = 'l'; fmt++; str++; + cont = 0; + } + /* Handle other strings */ + } else { + find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; + if (*str == find) cont = 0; + } + *fmt = 'l'; + } + /* Not in a string... */ else { - - spot = 0; - tabs = 0; - //see how many tabs we have - for(a = 0; a tabnumber)-tabs)+2)+len; // +2 for good measure - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - - for (a = 0; a < len; a++) { - c = (unsigned char) in_line[a]; - - check[0] = c; - check[1] = '\0'; - - if (check_delim(check)) - { - switch (c) { - case '\"': - if(in_line[a] == '\"' && in_line[a+1] == '\"' && in_line[a+2] == '\"') { - format[spot] = format[spot+1] = format[spot+2] = 'l'; - spot +=3; - a += 3; - while(in_line[a] != '\"' || in_line[a-1] != '\"' || in_line[a-2] != '\"') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - tabs = 0; - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } else { - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - } - format[spot] = 'l'; - spot++; - } else { - format[spot] = 'l'; - a++; spot++; - while(in_line[a] != '\"') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - format[spot] = 'l'; - spot++; - } - break; - case '\'': - if(in_line[a] == '\'' && in_line[a+1] == '\'' && in_line[a+2] == '\'') { - format[spot] = format[spot+1] = format[spot+2] = 'l'; - spot +=3; - a += 3; - while(in_line[a] != '\'' || in_line[a-1] != '\'' || in_line[a-2] != '\'') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - tabs = 0; - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } else { - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - } - format[spot] = 'l'; - spot++; - } else { - format[spot] = 'l'; - a++; spot++; - while(in_line[a] != '\'') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - format[spot] = 'l'; - spot++; - } - break; - case '#': - while(atabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = '#'; - spot++; - } - a++; - } else { - format[spot] = '#'; - a++; spot++; - } - } else { - format[spot] = '#'; - a++; spot++; - } - } - break; - case ' ': - format[spot] = ' '; - spot++; - break; - case '\t': - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - break; - default: - format[spot] = 'q'; - spot++; - - break; + /* Whitespace (all ws. has been converted to spaces) */ + else if (*str == ' ') + *fmt = '_'; + /* Numbers (digits not part of an identifier and periods followed by digits) */ + else if ((prev != 'q' && check_digit(*str)) || (*str == '.' && check_digit(*(str+1)))) + *fmt = 'n'; + /* Punctuation */ + else if (check_delim(*str)) + *fmt = '!'; + /* Identifiers and other text (no previous ws. or delims. so text continues) */ + else if (prev == 'q') + *fmt = 'q'; + /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ + else { + /* Special vars(v) or built-in keywords(b) */ + if ((i=find_specialvar(str)) != -1) + prev = 'v'; + else if ((i=find_builtinfunc(str)) != -1) + prev = 'b'; + if (i>0) { + while (i>1) { + *fmt = prev; fmt++; str++; + i--; } - } else if (check_numbers(check)) { - while (a < len) { - c = (unsigned char) in_line[a]; - other[0] = c; - other[1] = '\0'; - if (check_delim(other) && c != '.') { - a--; break; - } else { - format[spot] = 'n'; - a++; spot++; - } - } - } else { - letter = 0; - while (a < len) { - c = (unsigned char) in_line[a]; - other[0] = c; - other[1] = '\0'; - if (check_delim(other)) { - a--; - break; - } else { - check[letter] = (unsigned char) in_line[a]; - letter++; - a++; - } - } - check[letter] = '\0'; - if (check_builtinfuncs(check)) { - for (b = 0; b < strlen(check); b++) { - format[spot] = 'b'; - spot++; - } - } else if (check_specialvars(check)) { /*If TRUE then color and color next word*/ - for (b = 0; b < strlen(check); b++) { - format[spot] = 'b'; - spot++; - } - a++; - format[spot] = 'q'; - spot++; a++; - letter = 0; - while (a < len) { - c = (unsigned char) in_line[a]; - other[0] = c; - other[1] = '\0'; - if (check_delim(other)) { - a--; - break; - } else { - check[letter] = (unsigned char) in_line[a]; - letter++; - a++; - } - } - check[letter] = '\0'; - for (b = 0; b < strlen(check); b++) { - format[spot] = 'v'; - spot++; - } - }else { - for (b = 0; b < strlen(check); b++) { - format[spot] = 'q'; - spot++; - } - } - } + *fmt = prev; + } else + *fmt = 'q'; } - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); } - - tmp = tmp->next; + prev = *fmt; + fmt++; + str++; + } + + /* Terminate and add continuation char */ + *fmt = '\0'; fmt++; + *fmt = cont; + + /* Debugging */ + //print_format(st, line); + + /* If continuation has changed and we're allowed, process the next line */ + if (cont!=orig && do_next && line->next) { + txt_format_line(st, line->next, do_next); } } -static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) { +void txt_format_text(SpaceText *st) +{ + TextLine *linep; + + if (!st->text) return; + + for (linep=st->text->lines.first; linep; linep=linep->next) + txt_format_line(st, linep, 0); +} + +static void format_draw_color(char formatchar) { + switch (formatchar) { + case '_': /* Whitespace */ + break; + case '!': /* Symbols */ + BIF_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f); + break; + case '#': /* Comments */ + BIF_ThemeColor(TH_SYNTAX_C); + break; + case 'n': /* Numerals */ + BIF_ThemeColor(TH_SYNTAX_N); + break; + case 'l': /* Strings */ + BIF_ThemeColor(TH_SYNTAX_L); + break; + case 'v': /* Specials: class, def */ + BIF_ThemeColor(TH_SYNTAX_V); + break; + case 'b': /* Keywords: for, print, etc. */ + BIF_ThemeColor(TH_SYNTAX_B); + break; + case 'q': /* Other text (identifiers) */ + default: + BIF_ThemeColor(TH_TEXT); + break; + } +} + +static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format) +{ + int basex, i, a, len, start, end, max, lines; + + len= render_string(st, str); + str= temp_char_buf; + max= w/spacetext_get_fontwidth(st); + if (max<8) max= 8; + basex= x; + + lines= 1; + start= 0; + end= max; + for (i=0; i= max) { + /* Draw the visible portion of text on the overshot line */ + for (a=start; ashowsyntax && format) format_draw_color(format[a]); + glRasterPos2i(x, y); + BMF_DrawCharacter(spacetext_get_font(st), str[a]); + x += BMF_GetCharacterWidth(spacetext_get_font(st), str[a]); + } + y -= st->lheight; + x= basex; + lines++; + start= end; + end += max; + } else if (str[i]==' ' || str[i]=='-') { + end = i+1; + } + } + /* Draw the remaining text */ + for (a=start; ashowsyntax && format) format_draw_color(format[a]); + glRasterPos2i(x, y); + BMF_DrawCharacter(spacetext_get_font(st), str[a]); + x += BMF_GetCharacterWidth(spacetext_get_font(st), str[a]); + } + return lines; +} + +static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) +{ int r=0, w= 0; char *in; int *acc; @@ -544,40 +527,15 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra if (draw) { if(st->showsyntax && format) { int amount, a; - char out[2]; format = format+cshift; amount = strlen(in); for(a = 0; a < amount; a++) { - out[0] = (unsigned char) in[a]; - out[1] = '\0'; - switch (format[a]) { - case 'l': - BIF_ThemeColor(TH_SYNTAX_L); - break; - case 'b': - BIF_ThemeColor(TH_SYNTAX_B); - break; - case '#': - BIF_ThemeColor(TH_SYNTAX_C); - break; - case 'v': - BIF_ThemeColor(TH_SYNTAX_V); - break; - case 'n': - BIF_ThemeColor(TH_SYNTAX_N); - break; - case 'q': - BIF_ThemeColor(TH_TEXT); - break; - default: - BIF_ThemeColor(TH_TEXT); - break; - } + format_draw_color(format[a]); glRasterPos2i(x, y); - BMF_DrawString(spacetext_get_font(st), out); - x = x+BMF_GetStringWidth(spacetext_get_font(st), out); + BMF_DrawCharacter(spacetext_get_font(st), in[a]); + x = x+BMF_GetCharacterWidth(spacetext_get_font(st), in[a]); } } else { glRasterPos2i(x, y); @@ -609,14 +567,6 @@ static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) else { linep= &text->curl; charp= &text->curc; } y= (curarea->winy - y)/st->lheight; - - y-= txt_get_span(text->lines.first, *linep) - st->top; - - if (y>0) { - while (y-- != 0) if((*linep)->next) *linep= (*linep)->next; - } else if (y<0) { - while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev; - } if(st->showlinenrs) x-= TXT_OFFSET+TEXTXLOC; @@ -626,97 +576,353 @@ static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) if (x<0) x= 0; x = (x/spacetext_get_fontwidth(st)) + st->left; - w= render_string(st, (*linep)->line); - if(xlen; - + if (st->wordwrap) { + int i, j, endj, curs, max, chop, start, end, chars, loop; + char ch; + + /* Point to first visible line */ + *linep= text->lines.first; + for (i=0; itop && (*linep)->next; i++) *linep= (*linep)->next; + + max= get_wrap_width(st); + + loop= 1; + while (loop && *linep) { + start= 0; + end= max; + chop= 1; + chars= 0; + curs= 0; + endj= 0; + for (i=0, j=0; loop; j++) { + + /* Mimic replacement of tabs */ + ch= (*linep)->line[j]; + if (ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + ch= ' '; + } else + chars= 1; + + while (chars--) { + /* Gone too far, go back to last wrap point */ + if (y<0) { + *charp= endj; + loop= 0; + break; + /* Exactly at the cursor, done */ + } else if (y==0 && i-start==x) { + *charp= curs= j; + loop= 0; + break; + /* Prepare curs for next wrap */ + } else if (i-end==x) { + curs= j; + } + if (i-start>=max) { + if (chop) endj= j; + y--; + start= end; + end += max; + chop= 1; + if (y==0 && i-start>=x) { + *charp= curs; + loop= 0; + break; + } + } else if (ch==' ' || ch=='-' || ch=='\0') { + if (y==0 && i-start>=x) { + *charp= curs; + loop= 0; + break; + } + end = i+1; + endj = j; + chop= 0; + } + i++; + } + if (ch=='\0') break; + } + if (!loop || y<0) break; + + if (!(*linep)->next) { + *charp= (*linep)->len; + break; + } + + /* On correct line but didn't meet cursor, must be at end */ + if (y==0) { + *charp= (*linep)->len; + break; + } + *linep= (*linep)->next; + y--; + } + + } else { + y-= txt_get_span(text->lines.first, *linep) - st->top; + + if (y>0) { + while (y-- != 0) if((*linep)->next) *linep= (*linep)->next; + } else if (y<0) { + while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev; + } + + + w= render_string(st, (*linep)->line); + if(xlen; + } if(!sel) txt_pop_sel(text); } -static void draw_cursor(SpaceText *st) { - int h, x, i; - Text *text= st->text; - TextLine *linef, *linel; - int charf, charl; +static int get_wrap_width(SpaceText *st) { + int x, max; + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + max= (curarea->winx-x)/spacetext_get_fontwidth(st); + return max>8 ? max : 8; +} + +/* Returns the number of wrap points (or additional lines) in the given string */ +static int get_wrap_points(SpaceText *st, char *line) { + int start, end, taboffs, i, max, count; - if (text->curl==text->sell && text->curc==text->selc) { - x= text_draw(st, text->curl->line, st->left, text->curc, 0, 0, 0, NULL); + if (!st->wordwrap) return 0; - if (x) { - h= txt_get_span(text->lines.first, text->curl) - st->top; + end= max= get_wrap_width(st); + count= taboffs= start= 0; - BIF_ThemeColor(TH_HILITE); - - glRecti(x-1, curarea->winy-st->lheight*(h)-2, x+1, curarea->winy-st->lheight*(h+1)-2); + for (i=0; line[i]!='\0'; i++) { + if (i-start+taboffs>=max) { + count++; + start= end; + end += max; + taboffs= 0; + } else if (line[i]==' ' || line[i]=='\t' || line[i]=='-') { + end = i+1; + if (line[i]=='\t') + taboffs += st->tabnumber-(i-start)%st->tabnumber; } - } else { - int span= txt_get_span(text->curl, text->sell); - - if (span<0) { - linef= text->sell; - charf= text->selc; - - linel= text->curl; - charl= text->curc; - } else if (span>0) { - linef= text->curl; - charf= text->curc; - - linel= text->sell; - charl= text->selc; - } else { - linef= linel= text->curl; - - if (text->curcselc) { - charf= text->curc; - charl= text->selc; - } else { - charf= text->selc; - charl= text->curc; - } - } - - /* Walk to the beginning of visible text */ - h= txt_get_span(text->lines.first, linef) - st->top; - while (h++<-1 && linef!=linel) linef= linef->next; - - x= text_draw(st, linef->line, st->left, charf, 0, 0, 0, NULL); + } + return count; +} - BIF_ThemeColor(TH_SHADE2); +/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */ +static void wrap_offset(SpaceText *st, TextLine *linein, int cursin, int *offl, int *offc) { + Text *text; + TextLine *linep; + int i, j, start, end, chars, max, chop; + char ch; - if(st->showlinenrs) { - if (!x) x= TXT_OFFSET + TEXTXLOC -4; - } else { - if (!x) x= TXT_OFFSET - 4; - } - - while (linef && linef != linel) { - h= txt_get_span(text->lines.first, linef) - st->top; - if (h>st->viewlines) break; - - glRecti(x, curarea->winy-st->lheight*(h)-2, curarea->winx, curarea->winy-st->lheight*(h+1)-2); - if(st->showlinenrs) - glRecti(TXT_OFFSET+TEXTXLOC-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET+TEXTXLOC, curarea->winy-st->lheight*(h+2)-2); - else - glRecti(TXT_OFFSET-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET, curarea->winy-st->lheight*(h+2)-2); + *offl= *offc= 0; - if(st->showlinenrs) - x= TXT_OFFSET + TEXTXLOC; - else - x= TXT_OFFSET; - - linef= linef->next; - } - - h= txt_get_span(text->lines.first, linef) - st->top; + if (!st->text) return; + if (!st->wordwrap) return; - i= text_draw(st, linel->line, st->left, charl, 0, 0, 0, NULL); - if(i) glRecti(x, curarea->winy-st->lheight*(h)-2, i, curarea->winy-st->lheight*(h+1)-2); + text= st->text; + /* Move pointer to first visible line (top) */ + linep= text->lines.first; + i= st->top; + while (i>0 && linep) { + if (linep == linein) return; /* Line before top */ + linep= linep->next; + i--; } - do_brackets(); - BIF_ThemeColor(TH_TEXT); + max= get_wrap_width(st); + + while (linep) { + start= 0; + end= max; + chop= 1; + chars= 0; + *offc= 0; + for (i=0, j=0; linep->line[j]!='\0'; j++) { + + /* Mimic replacement of tabs */ + ch= linep->line[j]; + if (ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + if (linep==linein && i=max) { + if (chop && linep==linein && i >= cursin) + return; + (*offl)++; + *offc -= end-start; + start= end; + end += max; + chop= 1; + } else if (ch==' ' || ch=='-') { + end = i+1; + chop= 0; + if (linep==linein && i >= cursin) + return; + } + i++; + } + } + if (linep==linein) break; + linep= linep->next; + } +} + +static int get_char_pos(SpaceText *st, char *line, int cur) { + int a=0, i; + for (i=0; itabnumber-a%st->tabnumber; + else + a++; + } + return a; +} + +static void draw_markers(SpaceText *st) { + Text *text= st->text; + TextMarker *marker, *next; + TextLine *top, *bottom, *line; + int offl, offc, i, cy, x1, x2, y1, y2, x, y; + + for (i=st->top, top= text->lines.first; top->next && i>0; i--) top= top->next; + for (i=st->viewlines-1, bottom=top; bottom->next && i>0; i--) bottom= bottom->next; + + for (marker= text->markers.first; marker; marker= next) { + next= marker->next; + for (cy= 0, line= top; line; cy++, line= line->next) { + if (cy+st->top==marker->lineno) { + /* Remove broken markers */ + if (marker->end>line->len || marker->start>marker->end) { + BLI_freelinkN(&text->markers, marker); + break; + } + + wrap_offset(st, line, marker->start, &offl, &offc); + x1= get_char_pos(st, line->line, marker->start) - st->left + offc; + y1= cy + offl; + wrap_offset(st, line, marker->end, &offl, &offc); + x2= get_char_pos(st, line->line, marker->end) - st->left + offc; + y2= cy + offl; + + glColor3ub(marker->color[0], marker->color[1], marker->color[2]); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy-3; + + if (y1==y2) { + y -= y1*st->lheight; + glBegin(GL_LINE_LOOP); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); + glEnd(); + } else { + y -= y1*st->lheight; + glBegin(GL_LINE_STRIP); + glVertex2i(curarea->winx, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); + glVertex2i(curarea->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + for (i=y1+1; iwinx, y); + glVertex2i(x, y-st->lheight); + glVertex2i(curarea->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + } + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); + glVertex2i(x, y-st->lheight); + glEnd(); + } + + break; + } + if (line==bottom) break; + } + } +} + +static void draw_cursor(SpaceText *st) { + Text *text= st->text; + int vcurl, vcurc, vsell, vselc, hidden=0; + int offl, offc, x, y, w, i; + + /* Draw the selection */ + if (text->curl!=text->sell || text->curc!=text->selc) { + + /* Convert all to view space character coordinates */ + wrap_offset(st, text->curl, text->curc, &offl, &offc); + vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl; + vcurc = get_char_pos(st, text->curl->line, text->curc) - st->left + offc; + wrap_offset(st, text->sell, text->selc, &offl, &offc); + vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; + vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + + if (vcurc<0) vcurc=0; + if (vselc<0) vselc=0, hidden=1; + + BIF_ThemeColor(TH_SHADE2); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy-2; + + if (vcurl==vsell) { + y -= vcurl*st->lheight; + if (vcurc < vselc) + glRecti(x+vcurc*spacetext_get_fontwidth(st)-1, y, x+vselc*spacetext_get_fontwidth(st), y-st->lheight); + else + glRecti(x+vselc*spacetext_get_fontwidth(st)-1, y, x+vcurc*spacetext_get_fontwidth(st), y-st->lheight); + } else { + int froml, fromc, tol, toc; + if (vcurl < vsell) { + froml= vcurl; tol= vsell; + fromc= vcurc; toc= vselc; + } else { + froml= vsell; tol= vcurl; + fromc= vselc; toc= vcurc; + } + y -= froml*st->lheight; + glRecti(x+fromc*spacetext_get_fontwidth(st)-1, y, curarea->winx, y-st->lheight); y-=st->lheight; + for (i=froml+1; iwinx, y-st->lheight), y-=st->lheight; + glRecti(x-4, y, x+toc*spacetext_get_fontwidth(st), y-st->lheight); y-=st->lheight; + } + } else { + wrap_offset(st, text->sell, text->selc, &offl, &offc); + vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; + vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + if (vselc<0) vselc=0, hidden=1; + } + + if (!hidden) { + /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + x += vselc*spacetext_get_fontwidth(st); + y= curarea->winy-2 - vsell*st->lheight; + + if (st->overwrite) { + char ch= text->sell->line[text->selc]; + if (!ch) ch= ' '; + w= BMF_GetCharacterWidth(spacetext_get_font(st), ch); + BIF_ThemeColor(TH_HILITE); + glRecti(x, y-st->lheight-1, x+w, y-st->lheight+1); + } else { + BIF_ThemeColor(TH_HILITE); + glRecti(x-1, y, x+1, y-st->lheight); + } + } } static void calc_text_rcts(SpaceText *st) @@ -859,6 +1065,38 @@ static void screen_skip(SpaceText *st, int lines) if (st->top<0) st->top= 0; } +static void cursor_skip(SpaceText *st, int lines, int sel) +{ + Text *text; + TextLine **linep; + int oldl, oldc, *charp; + + if (!st) return; + if (st->spacetype != SPACE_TEXT) return; + if (!st->text) return; + + text= st->text; + + if (sel) linep= &text->sell, charp= &text->selc; + else linep= &text->curl, charp= &text->curc; + oldl= txt_get_span(text->lines.first, *linep); + oldc= *charp; + + while (lines>0 && (*linep)->next) { + *linep= (*linep)->next; + lines--; + } + while (lines<0 && (*linep)->prev) { + *linep= (*linep)->prev; + lines++; + } + + if (*charp > (*linep)->len) *charp= (*linep)->len; + + if (!sel) txt_pop_sel(st->text); + txt_undo_add_toop(st->text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp); +} + /* * mode 1 == view scroll * mode 2 == scrollbar @@ -874,10 +1112,8 @@ static void do_textscroll(SpaceText *st, int mode) st->flags|= ST_SCROLL_SELECT; - glDrawBuffer(GL_FRONT); - uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT); - bglFlush(); - glDrawBuffer(GL_BACK); + scrarea_do_windraw(curarea); + screen_swapbuffers(); getmouseco_areawin(mval); old[0]= hold[0]= mval[0]; @@ -895,9 +1131,12 @@ static void do_textscroll(SpaceText *st, int mode) if (delta[0] || delta[1]) { screen_skip(st, delta[1]); - st->left+= delta[0]; - if (st->left<0) st->left= 0; - + if (st->wordwrap) { + st->left= 0; + } else { + st->left+= delta[0]; + if (st->left<0) st->left= 0; + } scrarea_do_windraw(curarea); screen_swapbuffers(); @@ -912,10 +1151,8 @@ static void do_textscroll(SpaceText *st, int mode) } st->flags^= ST_SCROLL_SELECT; - glDrawBuffer(GL_FRONT); - uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT); - bglFlush(); - glDrawBuffer(GL_BACK); + scrarea_do_windraw(curarea); + screen_swapbuffers(); } static void do_selection(SpaceText *st, int selecting) @@ -957,7 +1194,7 @@ static void do_selection(SpaceText *st, int selecting) scrarea_do_windraw(curarea); screen_swapbuffers(); - } else if (mval[0]<0 || mval[0]>curarea->winx) { + } else if (!st->wordwrap && (mval[0]<0 || mval[0]>curarea->winx)) { if (mval[0]>curarea->winx) st->left++; else if (mval[0]<0 && st->left>0) st->left--; @@ -986,19 +1223,409 @@ static void do_selection(SpaceText *st, int selecting) if (sell!=linep2 || selc!=charp2) txt_undo_add_toop(st->text, UNDO_STO, sell, selc, linep2, charp2); + + pop_space_text(st); +} + +static int do_suggest_select(SpaceText *st) +{ + SuggItem *item, *first, *last, *sel; + short mval[2]; + TextLine *tmp; + int l, x, y, w, h, i; + int tgti, *top; + + if (!st || !st->text) return 0; + if (!texttool_text_is_active(st->text)) return 0; + + first = texttool_suggest_first(); + last = texttool_suggest_last(); + sel = texttool_suggest_selected(); + top = texttool_suggest_top(); + + if (!last || !first) + return 0; + + /* Count the visible lines to the cursor */ + for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); + if (l<0) return 0; + + if(st->showlinenrs) { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; + } else { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; + } + y = curarea->winy - st->lheight*l - 2; + + w = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20; + h = SUGG_LIST_SIZE*st->lheight + 8; + + getmouseco_areawin(mval); + + if (mval[0]next; i++, item=item->next); + + /* Work out the target item index in the visible list */ + tgti = (y-mval[1]-4) / st->lheight; + if (tgti<0 || tgti>SUGG_LIST_SIZE) + return 1; + + for (i=tgti; i>0 && item->next; i--, item=item->next); + if (item) + texttool_suggest_select(item); + return 1; +} + +static void pop_suggest_list() { + SuggItem *item, *sel; + int *top, i; + + item= texttool_suggest_first(); + sel= texttool_suggest_selected(); + top= texttool_suggest_top(); + + i= 0; + while (item && item != sel) { + item= item->next; + i++; + } + if (i > *top+SUGG_LIST_SIZE-1) + *top= i-SUGG_LIST_SIZE+1; + else if (i < *top) + *top= i; +} + +void draw_documentation(SpaceText *st) +{ + TextLine *tmp; + char *docs, buf[DOC_WIDTH+1], *p; + int len, i, br, lines; + int boxw, boxh, l, x, y, top; + + if (!st || !st->text) return; + if (!texttool_text_is_active(st->text)) return; + + docs = texttool_docs_get(); + + if (!docs) return; + + /* Count the visible lines to the cursor */ + for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); + if (l<0) return; + + if(st->showlinenrs) { + x= spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; + } else { + x= spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; + } + if (texttool_suggest_first()) { + x += SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 50; + } + + top= y= curarea->winy - st->lheight*l - 2; + len= strlen(docs); + boxw= DOC_WIDTH*spacetext_get_fontwidth(st) + 20; + boxh= (DOC_HEIGHT+1)*st->lheight; + + /* Draw panel */ + BIF_ThemeColor(TH_BACK); + glRecti(x, y, x+boxw, y-boxh); + BIF_ThemeColor(TH_SHADE1); + glBegin(GL_LINE_LOOP); + glVertex2i(x, y); + glVertex2i(x+boxw, y); + glVertex2i(x+boxw, y-boxh); + glVertex2i(x, y-boxh); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex2i(x+boxw-10, y-7); + glVertex2i(x+boxw-4, y-7); + glVertex2i(x+boxw-7, y-2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex2i(x+boxw-10, y-boxh+7); + glVertex2i(x+boxw-4, y-boxh+7); + glVertex2i(x+boxw-7, y-boxh+2); + glEnd(); + BIF_ThemeColor(TH_TEXT); + + i= 0; br= DOC_WIDTH; lines= -doc_scroll; + for (p=docs; *p; p++) { + if (*p == '\r' && *(++p) != '\n') *(--p)= '\n'; /* Fix line endings */ + if (*p == ' ' || *p == '\t') + br= i; + else if (*p == '\n') { + buf[i]= '\0'; + if (lines>=0) { + y -= st->lheight; + text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL); + } + i= 0; br= DOC_WIDTH; lines++; + } + buf[i++]= *p; + if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */ + buf[br]= '\0'; + if (lines>=0) { + y -= st->lheight; + text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL); + } + p -= i-br-1; /* Rewind pointer to last break */ + i= 0; br= DOC_WIDTH; lines++; + } + if (lines >= DOC_HEIGHT) break; + } + if (doc_scroll > 0 && lines < DOC_HEIGHT) { + doc_scroll--; + draw_documentation(st); + } +} + +void draw_suggestion_list(SpaceText *st) +{ + SuggItem *item, *first, *last, *sel; + TextLine *tmp; + char str[SUGG_LIST_WIDTH+1]; + int w, boxw=0, boxh, i, l, x, y, b, *top; + + if (!st || !st->text) return; + if (!texttool_text_is_active(st->text)) return; + + first = texttool_suggest_first(); + last = texttool_suggest_last(); + + if (!first || !last) return; + + pop_suggest_list(); + sel = texttool_suggest_selected(); + top = texttool_suggest_top(); + + /* Count the visible lines to the cursor */ + for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); + if (l<0) return; + + if(st->showlinenrs) { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; + } else { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; + } + y = curarea->winy - st->lheight*l - 2; + + boxw = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20; + boxh = SUGG_LIST_SIZE*st->lheight + 8; + + BIF_ThemeColor(TH_SHADE1); + glRecti(x-1, y+1, x+boxw+1, y-boxh-1); + BIF_ThemeColor(TH_BACK); + glRecti(x, y, x+boxw, y-boxh); + + /* Set the top 'item' of the visible list */ + for (i=0, item=first; i<*top && item->next; i++, item=item->next); + + for (i=0; inext) { + + y -= st->lheight; + + strncpy(str, item->name, SUGG_LIST_WIDTH); + str[SUGG_LIST_WIDTH] = '\0'; + + w = BMF_GetStringWidth(spacetext_get_font(st), str); + + if (item == sel) { + BIF_ThemeColor(TH_SHADE2); + glRecti(x+16, y-3, x+16+w, y+st->lheight-3); + } + b=1; /* b=1 colour block, text is default. b=0 no block, colour text */ + switch (item->type) { + case 'k': BIF_ThemeColor(TH_SYNTAX_B); b=0; break; + case 'm': BIF_ThemeColor(TH_TEXT); break; + case 'f': BIF_ThemeColor(TH_SYNTAX_L); break; + case 'v': BIF_ThemeColor(TH_SYNTAX_N); break; + case '?': BIF_ThemeColor(TH_TEXT); b=0; break; + } + if (b) { + glRecti(x+8, y+2, x+11, y+5); + BIF_ThemeColor(TH_TEXT); + } + text_draw(st, str, 0, 0, 1, x+16, y-1, NULL); + + if (item == last) break; + } +} + +static short check_blockhandler(SpaceText *st, short handler) { + short a; + for(a=0; ablockhandler[a]==handler) return 1; + return 0; +} + +static void text_panel_find(short cntrl) // TEXT_HANDLER_FIND +{ + uiBlock *block; + + if (!g_find_str || !g_replace_str) { + g_find_str= MEM_mallocN(TXT_MAXFINDSTR+1, "find_string"); + g_replace_str= MEM_mallocN(TXT_MAXFINDSTR+1, "replace_string"); + g_find_str[0]= g_replace_str[0]= '\0'; + } + + block= uiNewBlock(&curarea->uiblocks, "text_panel_find", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(TEXT_HANDLER_FIND); // for close and esc + if(uiNewPanel(curarea, block, "Find & Replace", "Text", curarea->winx-230, curarea->winy-130, 260, 120)==0) return; + + uiBlockBeginAlign(block); + uiDefButC(block, TEX, 0, "Find: ", 0,80,220,20, g_find_str, 0,(float)TXT_MAXFINDSTR, 0,0, ""); + uiDefIconBut(block, BUT, B_PASTEFIND, ICON_TEXT, 220,80,20,20, NULL, 0,0,0,0, "Copy from selection"); + uiDefButC(block, TEX, 0, "Replace: ", 0,60,220,20, g_replace_str, 0,(float)TXT_MAXFINDSTR, 0,0, ""); + uiDefIconBut(block, BUT, B_PASTEREPLACE, ICON_TEXT, 220,60,20,20, NULL, 0,0,0,0, "Copy from selection"); + uiBlockEndAlign(block); + uiDefButBitI(block, TOG, TXT_FIND_WRAP, 0,"Wrap Around", 0,30,110,20,&g_find_flags,0,0,0,0,"Wrap search around current text"); + uiDefButBitI(block, TOG, TXT_FIND_ALLTEXTS,0,"Search All Texts", 110,30,130,20,&g_find_flags,0,0,0,0,"Search in each text"); + uiDefBut(block, BUT, B_TEXTFIND, "Find", 0,0,50,20, NULL, 0,0,0,0, "Find next"); + uiDefBut(block, BUT, B_TEXTREPLACE, "Replace/Find", 50,0,110,20, NULL, 0,0,0,0, "Replace then find next"); + uiDefBut(block, BUT, B_TEXTMARKALL, "Mark All", 160,0,80,20, NULL, 0,0,0,0, "Mark each occurrence to edit all from one"); +} + +/* mode: 0 find only, 1 replace/find, 2 mark all occurrences */ +void find_and_replace(SpaceText *st, short mode) { + char *tmp; + Text *start= NULL, *text= st->text; + int flags, first= 1; + + if (!check_blockhandler(st, TEXT_HANDLER_FIND)) { + toggle_blockhandler(st->area, TEXT_HANDLER_FIND, UI_PNL_TO_MOUSE); + return; + } + + if (!g_find_str || !g_replace_str) return; + if (g_find_str[0] == '\0') return; + flags= g_find_flags; + if (flags & TXT_FIND_ALLTEXTS) flags ^= TXT_FIND_WRAP; + + do { + if (first) + txt_clear_markers(text, TMARK_GRP_FINDALL, 0); + first= 0; + + /* Replace current */ + if (mode && txt_has_sel(text)) { + tmp= txt_sel_to_buf(text); + if (strcmp(g_find_str, tmp)==0) { + if (mode==1) { + txt_insert_buf(text, g_replace_str); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } else if (mode==2) { + char color[4]; + BIF_GetThemeColor4ubv(TH_SHADE2, color); + if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { + if (tmp) MEM_freeN(tmp), tmp=NULL; + break; + } + txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL); + } + } + MEM_freeN(tmp); + tmp= NULL; + } + + /* Find next */ + if (txt_find_string(text, g_find_str, flags & TXT_FIND_WRAP)) { + pop_space_text(st); + } else if (flags & TXT_FIND_ALLTEXTS) { + if (text==start) break; + if (!start) start= text; + if (text->id.next) + text= st->text= text->id.next; + else + text= st->text= G.main->text.first; + txt_move_toline(text, 0, 0); + pop_space_text(st); + first= 1; + } else { + okee("Text not found: %s", g_find_str); + break; + } + } while (mode==2); +} + +static void do_find_buttons(val) { + Text *text; + SpaceText *st; + int do_draw= 0; + char *tmp; + + st= curarea->spacedata.first; + if (!st || st->spacetype != SPACE_TEXT) return; + text= st->text; + if (!text) return; + + switch (val) { + case B_PASTEFIND: + if (!g_find_str) break; + tmp= txt_sel_to_buf(text); + strncpy(g_find_str, tmp, TXT_MAXFINDSTR); + MEM_freeN(tmp); + do_draw= 1; + break; + case B_PASTEREPLACE: + if (!g_replace_str) break; + tmp= txt_sel_to_buf(text); + strncpy(g_replace_str, tmp, TXT_MAXFINDSTR); + MEM_freeN(tmp); + do_draw= 1; + break; + case B_TEXTFIND: + find_and_replace(st, 0); + do_draw= 1; + break; + case B_TEXTREPLACE: + find_and_replace(st, 1); + do_draw= 1; + break; + case B_TEXTMARKALL: + find_and_replace(st, 2); + do_draw= 1; + break; + } +} + +static void text_blockhandlers(ScrArea *sa) +{ + SpaceText *st= sa->spacedata.first; + short a; + + /* warning; blocks need to be freed each time, handlers dont remove */ + uiFreeBlocksWin(&sa->uiblocks, sa->win); + + for(a=0; ablockhandler[a]) { + case TEXT_HANDLER_FIND: + text_panel_find(st->blockhandler[a+1]); + break; + } + } + uiDrawBlocksPanels(sa, 0); } void drawtextspace(ScrArea *sa, void *spacedata) { SpaceText *st= curarea->spacedata.first; Text *text; - int i; + int i, x, y; TextLine *tmp; char linenr[12]; float col[3]; int linecount = 0; if (st==NULL || st->spacetype != SPACE_TEXT) return; + + bwin_clear_viewmat(sa->win); /* clear buttons view */ + glLoadIdentity(); BIF_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); @@ -1022,23 +1649,23 @@ void drawtextspace(ScrArea *sa, void *spacedata) glRecti(23, 0, (st->lheight==15)?63:59, curarea->winy - 2); } - BIF_ThemeColor(TH_TEXT); - draw_cursor(st); tmp= text->lines.first; for (i= 0; itop && tmp; i++) { + if (st->showsyntax && !tmp->format) txt_format_line(st, tmp, 0); tmp= tmp->next; linecount++; } - - if(st->showsyntax) { - if (tmp && !tmp->format) { - get_format_string(st); + + y= curarea->winy-st->lheight; + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + + BIF_ThemeColor(TH_TEXT); + for (i=0; y>0 && iviewlines && tmp; i++, tmp= tmp->next) { + if (st->showsyntax && !tmp->format) { + txt_format_line(st, tmp, 0); } - } - - for (i=0; iviewlines && tmp; i++, tmp= tmp->next) { if(st->showlinenrs) { /*Change the color of the current line the cursor is on*/ if(tmp == text->curl) { @@ -1048,20 +1675,33 @@ void drawtextspace(ScrArea *sa, void *spacedata) } if(((float)(i + linecount + 1)/10000.0) < 1.0) { sprintf(linenr, "%4d", i + linecount + 1); - glRasterPos2i(TXT_OFFSET - 7, curarea->winy-st->lheight*(i+1)); + glRasterPos2i(TXT_OFFSET - 7, y); } else { sprintf(linenr, "%5d", i + linecount + 1); - glRasterPos2i(TXT_OFFSET - 11, curarea->winy-st->lheight*(i+1)); + glRasterPos2i(TXT_OFFSET - 11, y); } BIF_ThemeColor(TH_TEXT); BMF_DrawString(spacetext_get_font(st), linenr); - text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET + TEXTXLOC, curarea->winy-st->lheight*(i+1), tmp->format); - } else - text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET, curarea->winy-st->lheight*(i+1), tmp->format); + } + if (st->wordwrap) { + int lines = text_draw_wrapped(st, tmp->line, x, y, curarea->winx-x, tmp->format); + y -= lines*st->lheight; + } else { + text_draw(st, tmp->line, st->left, 0, 1, x, y, tmp->format); + y -= st->lheight; + } } + + draw_brackets(st); + draw_markers(st); draw_textscroll(st); - + draw_documentation(st); + draw_suggestion_list(st); + + bwin_scalematrix(sa->win, st->blockscale, st->blockscale, st->blockscale); + text_blockhandlers(sa); + curarea->win_swap= WIN_BACK_OK; } @@ -1075,15 +1715,19 @@ void pop_space_text (SpaceText *st) if(!st->text) return; if(!st->text->curl) return; - i= txt_get_span(st->text->lines.first, st->text->curl); + i= txt_get_span(st->text->lines.first, st->text->sell); if (st->top+st->viewlines <= i || st->top > i) { st->top= i - st->viewlines/2; } - x= text_draw(st, st->text->curl->line, st->left, st->text->curc, 0, 0, 0, NULL); + if (st->wordwrap) { + st->left= 0; + } else { + x= text_draw(st, st->text->sell->line, st->left, st->text->selc, 0, 0, 0, NULL); - if (x==0 || x>curarea->winx) { - st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); + if (x==0 || x>curarea->winx) { + st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); + } } if (st->top < 0) st->top= 0; @@ -1103,7 +1747,7 @@ void add_text_fs(char *file) /* bad but cant pass an as arg here */ st->top= 0; - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); } @@ -1115,6 +1759,60 @@ void free_textspace(SpaceText *st) st->text= NULL; } +/* returns 0 if file on disk is the same or Text is in memory only + returns 1 if file has been modified on disk since last local edit + returns 2 if file on disk has been deleted + -1 is returned if an error occurs +*/ +int txt_file_modified(Text *text) +{ + struct stat st; + int result; + char file[FILE_MAXDIR+FILE_MAXFILE]; + + if (!text || !text->name) + return 0; + + BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_convertstringcode(file, G.sce); + + if (!BLI_exists(file)) + return 2; + + result = stat(file, &st); + + if(result == -1) + return -1; + + if((st.st_mode & S_IFMT) != S_IFREG) + return -1; + + if (st.st_mtime > text->mtime) + return 1; + + return 0; +} + +void txt_ignore_modified(Text *text) { + struct stat st; + int result; + char file[FILE_MAXDIR+FILE_MAXFILE]; + + if (!text || !text->name) return; + + BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_convertstringcode(file, G.sce); + + if (!BLI_exists(file)) return; + + result = stat(file, &st); + + if(result == -1 || (st.st_mode & S_IFMT) != S_IFREG) + return; + + text->mtime= st.st_mtime; +} + static void save_mem_text(char *str) { SpaceText *st= curarea->spacedata.first; @@ -1141,6 +1839,9 @@ void txt_write_file(Text *text) { FILE *fp; TextLine *tmp; + int res; + struct stat st; + char file[FILE_MAXDIR+FILE_MAXFILE]; /* Do we need to get a filename? */ if (text->flags & TXT_ISMEM) { @@ -1148,19 +1849,22 @@ void txt_write_file(Text *text) activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->name, save_mem_text); else activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->id.name+2, save_mem_text); - return; + return; } + + BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_convertstringcode(file, G.sce); /* Should we ask to save over? */ if (text->flags & TXT_ISTMP) { - if (BLI_exists(text->name)) { + if (BLI_exists(file)) { if (!okee("Save over")) return; } else if (!okee("Create new file")) return; text->flags ^= TXT_ISTMP; } - fp= fopen(text->name, "w"); + fp= fopen(file, "w"); if (fp==NULL) { error("Unable to save file"); return; @@ -1175,6 +1879,9 @@ void txt_write_file(Text *text) } fclose (fp); + + res= stat(file, &st); + text->mtime= st.st_mtime; if (text->flags & TXT_ISDIRTY) text->flags ^= TXT_ISDIRTY; } @@ -1386,44 +2093,6 @@ void txt_copy_clipboard(Text *text) { } } -/* - * again==0 show find panel or find - * again==1 find text again */ -void txt_find_panel(SpaceText *st, int again) -{ - Text *text=st->text; - char *findstr= last_txt_find_string; - - if (again==0) { - findstr= txt_sel_to_buf(text); - } else if (again==1) { - char buf[256]; - - if (findstr && strlen(findstr)<(sizeof(buf)-1)) - strcpy(buf, findstr); - else - buf[0]= 0; - - if (sbutton(buf, 0, sizeof(buf)-1, "Find: ") && buf[0]) - findstr= BLI_strdup(buf); - else - findstr= NULL; - } - - if (findstr!=last_txt_find_string) { - if (last_txt_find_string) - MEM_freeN(last_txt_find_string); - last_txt_find_string= findstr; - } - - if (findstr) { - if (txt_find_string(text, findstr)) - pop_space_text(st); - else - error("Not found: %s", findstr); - } -} - void run_python_script(SpaceText *st) { char *py_filename; @@ -1458,6 +2127,580 @@ static void set_tabs(Text *text) st->currtab_set = setcurr_tab(text); } +static void wrap_move_bol(SpaceText *st, short sel) { + int offl, offc, lin; + Text *text= st->text; + + lin= txt_get_span(text->lines.first, text->sell); + wrap_offset(st, text->sell, text->selc, &offl, &offc); + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, -offc); + text->selc= -offc; + } else { + txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, -offc); + text->curc= -offc; + txt_pop_sel(text); + } +} + +static void wrap_move_eol(SpaceText *st, short sel) { + int offl, offc, lin, startl, c; + Text *text= st->text; + + lin= txt_get_span(text->lines.first, text->sell); + wrap_offset(st, text->sell, text->selc, &offl, &offc); + startl= offl; + c= text->selc; + while (offl==startl && text->sell->line[c]!='\0') { + c++; + wrap_offset(st, text->sell, c, &offl, &offc); + } if (offl!=startl) c--; + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, c); + text->selc= c; + } else { + txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, c); + text->curc= c; + txt_pop_sel(text); + } +} + +static void wrap_move_up(SpaceText *st, short sel) { + int offl, offl_1, offc, fromline, toline, c, target; + Text *text= st->text; + + wrap_offset(st, text->sell, 0, &offl_1, &offc); + wrap_offset(st, text->sell, text->selc, &offl, &offc); + fromline= toline= txt_get_span(text->lines.first, text->sell); + target= text->selc + offc; + + if (offl==offl_1) { + if (!text->sell->prev) { + txt_move_bol(text, sel); + return; + } + toline--; + c= text->sell->prev->len; /* End of prev. line */ + wrap_offset(st, text->sell->prev, c, &offl, &offc); + c= -offc+target; + } else { + c= -offc-1; /* End of prev. line */ + wrap_offset(st, text->sell, c, &offl, &offc); + c= -offc+target; + } + if (c<0) c=0; + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); + if (tolinesell= text->sell->prev; + if (c>text->sell->len) c= text->sell->len; + text->selc= c; + } else { + txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); + if (tolinecurl= text->curl->prev; + if (c>text->curl->len) c= text->curl->len; + text->curc= c; + txt_pop_sel(text); + } +} + +static void wrap_move_down(SpaceText *st, short sel) { + int offl, startoff, offc, fromline, toline, c, target; + Text *text= st->text; + + wrap_offset(st, text->sell, text->selc, &offl, &offc); + fromline= toline= txt_get_span(text->lines.first, text->sell); + target= text->selc + offc; + startoff= offl; + c= text->selc; + while (offl==startoff && text->sell->line[c]!='\0') { + c++; + wrap_offset(st, text->sell, c, &offl, &offc); + } + + if (text->sell->line[c]=='\0') { + if (!text->sell->next) { + txt_move_eol(text, sel); + return; + } + toline++; + c= target; + } else { + c += target; + if (c > text->sell->len) c= text->sell->len; + } + if (c<0) c=0; + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); + if (toline>fromline) text->sell= text->sell->next; + if (c>text->sell->len) c= text->sell->len; + text->selc= c; + } else { + txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); + if (toline>fromline) text->curl= text->curl->next; + if (c>text->curl->len) c= text->curl->len; + text->curc= c; + txt_pop_sel(text); + } +} + +static void get_suggest_prefix(Text *text, int offset) { + int i, len; + char *line, tmp[256]; + + if (!text) return; + if (!texttool_text_is_active(text)) return; + + line= text->curl->line; + for (i=text->curc-1+offset; i>=0; i--) + if (!check_identifier(line[i])) + break; + i++; + len= text->curc-i+offset; + if (len > 255) { + printf("Suggestion prefix too long\n"); + len = 255; + } + strncpy(tmp, line+i, len); + tmp[len]= '\0'; + texttool_suggest_prefix(tmp); +} + +static void confirm_suggestion(Text *text, int skipleft) { + int i, over=0; + char *line; + SuggItem *sel; + + if (!text) return; + if (!texttool_text_is_active(text)) return; + + sel = texttool_suggest_selected(); + if (!sel) return; + + line= text->curl->line; + i=text->curc-skipleft-1; + while (i>=0) { + if (!check_identifier(line[i])) + break; + over++; + i--; + } + + for (i=0; iname); + + for (i=0; itext)) return 0; + if (!st->text || st->text->id.lib) return 0; + + if (st->doplugins && texttool_text_is_active(st->text)) { + if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST; + if (texttool_docs_get()) tools |= TOOL_DOCUMENT; + } + + if (ascii) { + if (tools & TOOL_SUGG_LIST) { + if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || check_whitespace(ascii)) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + } else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) { + get_suggest_prefix(st->text, 0); + pop_suggest_list(); + swallow= 1; + draw= 1; + } + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; + + } else if (val==1 && evnt) { + switch (evnt) { + case LEFTMOUSE: + if (do_suggest_select(st)) + swallow= 1; + else { + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + } + draw= 1; + break; + case MIDDLEMOUSE: + if (do_suggest_select(st)) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + swallow= 1; + } else { + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + } + draw= 1; + break; + case ESCKEY: + draw= swallow= 1; + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); + else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + else draw= swallow= 0; + break; + case RETKEY: + if (tools & TOOL_SUGG_LIST) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + swallow= 1; + draw= 1; + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; + break; + case LEFTARROWKEY: + case BACKSPACEKEY: + if (tools & TOOL_SUGG_LIST) { + if (G.qual) + texttool_suggest_clear(); + else { + /* Work out which char we are about to delete/pass */ + if (st->text->curl && st->text->curc > 0) { + char ch= st->text->curl->line[st->text->curc-1]; + if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) { + get_suggest_prefix(st->text, -1); + pop_suggest_list(); + } + else + texttool_suggest_clear(); + } else + texttool_suggest_clear(); + } + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + break; + case RIGHTARROWKEY: + if (tools & TOOL_SUGG_LIST) { + if (G.qual) + texttool_suggest_clear(); + else { + /* Work out which char we are about to pass */ + if (st->text->curl && st->text->curc < st->text->curl->len) { + char ch= st->text->curl->line[st->text->curc+1]; + if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) { + get_suggest_prefix(st->text, 1); + pop_suggest_list(); + } + else + texttool_suggest_clear(); + } else + texttool_suggest_clear(); + } + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + break; + case PAGEDOWNKEY: + scroll= SUGG_LIST_SIZE-1; + case WHEELDOWNMOUSE: + case DOWNARROWKEY: + if (tools & TOOL_DOCUMENT) { + doc_scroll++; + swallow= 1; + draw= 1; + break; + } else if (tools & TOOL_SUGG_LIST) { + SuggItem *sel = texttool_suggest_selected(); + if (!sel) { + texttool_suggest_select(texttool_suggest_first()); + } else while (sel && sel!=texttool_suggest_last() && sel->next && scroll--) { + texttool_suggest_select(sel->next); + sel= sel->next; + } + pop_suggest_list(); + swallow= 1; + draw= 1; + break; + } + case PAGEUPKEY: + scroll= SUGG_LIST_SIZE-1; + case WHEELUPMOUSE: + case UPARROWKEY: + if (tools & TOOL_DOCUMENT) { + if (doc_scroll>0) doc_scroll--; + swallow= 1; + draw= 1; + break; + } else if (tools & TOOL_SUGG_LIST) { + SuggItem *sel = texttool_suggest_selected(); + while (sel && sel!=texttool_suggest_first() && sel->prev && scroll--) { + texttool_suggest_select(sel->prev); + sel= sel->prev; + } + pop_suggest_list(); + swallow= 1; + draw= 1; + break; + } + case RIGHTSHIFTKEY: + case LEFTSHIFTKEY: + break; + default: + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw= 1; + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; + } + } + + if (draw) { + ScrArea *sa; + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } + } + + return swallow; +} + +static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short val) { + Text *text; + TextMarker *marker, *mrk, *nxt; + int c, s, draw=0, swallow=0; + + text= st->text; + if (!text || text->id.lib || text->curl != text->sell) return 0; + + marker= txt_find_marker(text, text->sell, text->selc, 0, 0); + if (marker && (marker->start > text->curc || marker->end < text->curc)) + marker= NULL; + + if (!marker) { + /* Find the next temporary marker */ + if (evnt==TABKEY) { + int lineno= txt_get_span(text->lines.first, text->curl); + TextMarker *mrk= text->markers.first; + while (mrk) { + if (!marker && (mrk->flags & TMARK_TEMP)) marker= mrk; + if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) { + marker= mrk; + break; + } + mrk= mrk->next; + } + if (marker) { + txt_move_to(text, marker->lineno, marker->start, 0); + txt_move_to(text, marker->lineno, marker->end, 1); + pop_space_text(st); + evnt= ascii= val= 0; + draw= 1; + swallow= 1; + } + } else if (evnt==ESCKEY) { + if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow= 1; + else if (txt_clear_markers(text, 0, 0)) swallow= 1; + else return 0; + evnt= ascii= val= 0; + draw= 1; + } + if (!swallow) return 0; + } + + if (ascii) { + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt=txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + if (st->overwrite) { + if (txt_replace_char(text, ascii)) + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } else { + if (txt_add_char(text, ascii)) { + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } + } + + if (mrk==marker || mrk==nxt) break; + mrk=nxt; + } + swallow= 1; + draw= 1; + } + } else if (val) { + switch(evnt) { + case BACKSPACEKEY: + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + txt_backspace_char(text); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (mrk==marker || mrk==nxt) break; + mrk= nxt; + } + swallow= 1; + draw= 1; + } + break; + case DELKEY: + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + txt_delete_char(text); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (mrk==marker || mrk==nxt) break; + mrk= nxt; + } + swallow= 1; + draw= 1; + } + break; + case TABKEY: + if (G.qual & LR_SHIFTKEY) { + nxt= marker->prev; + if (!nxt) nxt= text->markers.last; + } else { + nxt= marker->next; + if (!nxt) nxt= text->markers.first; + } + if (marker->flags & TMARK_TEMP) { + if (nxt==marker) nxt= NULL; + BLI_freelinkN(&text->markers, marker); + } + mrk= nxt; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + pop_space_text(st); + } + swallow= 1; + draw= 1; + break; + + /* Events that should clear markers */ + case UKEY: if (!(G.qual & LR_ALTKEY)) break; + case ZKEY: if (evnt==ZKEY && !(G.qual & LR_CTRLKEY)) break; + case RETKEY: + case ESCKEY: + if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) + txt_clear_markers(text, marker->group, 0); + else + BLI_freelinkN(&text->markers, marker); + swallow= 1; + draw= 1; + break; + case RIGHTMOUSE: /* Marker context menu? */ + case LEFTMOUSE: + break; + case FKEY: /* Allow find */ + if (G.qual & LR_SHIFTKEY) swallow= 1; + break; + + default: + if (G.qual!=0 && G.qual!=LR_SHIFTKEY) + swallow= 1; /* Swallow all other shortcut events */ + } + } + + if (draw) { + ScrArea *sa; + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } + } + return swallow; +} + +static short do_modification_check(SpaceText *st) { + Text *text= st->text; + + if (last_check_time < PIL_check_seconds_timer() - 2.0) { + switch (txt_file_modified(text)) { + case 1: + /* Modified locally and externally, ahhh. Offer more possibilites. */ + if (text->flags & TXT_ISDIRTY) { + switch (pupmenu("File Modified Outside and Inside Blender %t|Load outside changes (ignore local changes) %x0|Save local changes (ignore outside changes) %x1|Make text internal (separate copy) %x2")) { + case 0: + reopen_text(text); + if (st->showsyntax) txt_format_text(st); + return 1; + case 1: + txt_write_file(text); + return 1; + case 2: + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; + return 1; + } + } else { + switch (pupmenu("File Modified Outside Blender %t|Reload from disk %x0|Make text internal (separate copy) %x1|Ignore %x2")) { + case 0: + reopen_text(text); + if (st->showsyntax) txt_format_text(st); + return 1; + case 1: + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; + return 1; + case 2: + txt_ignore_modified(text); + return 1; + } + } + break; + case 2: + switch (pupmenu("File Deleted Outside Blender %t|Make text internal %x0|Recreate file %x1")) { + case 0: + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; + return 1; + case 1: + txt_write_file(text); + return 1; + } + break; + default: + break; + } + last_check_time = PIL_check_seconds_timer(); + } + return 0; +} + void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { unsigned short event= evt->event; @@ -1528,8 +2771,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } return; } + + if (val && uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING) event= 0; + + if (st->doplugins && do_texttools(st, ascii, event, val)) return; + if (do_markers(st, ascii, event, val)) return; - if (event==LEFTMOUSE) { + if (event==UI_BUT_EVENT) { + do_find_buttons(val); + do_draw= 1; + } else if (event==LEFTMOUSE) { if (val) { short mval[2]; char *buffer; @@ -1550,20 +2801,20 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } else if (event==MIDDLEMOUSE) { if (val) { - if (U.uiflag & USER_MMB_PASTE) - { + if (U.uiflag & USER_MMB_PASTE) { do_selection(st, G.qual&LR_SHIFTKEY); get_selection_buffer(text); do_draw= 1; - } - else - { + } else { do_textscroll(st, 1); } } } else if (event==RIGHTMOUSE) { if (val) { - p= pupmenu("File %t|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); + if (txt_has_sel(text)) + p= pupmenu("Text %t|Cut%x10|Copy%x11|Paste%x12|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); + else + p= pupmenu("Text %t|Paste%x12|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); switch(p) { case 0: @@ -1589,13 +2840,48 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) run_python_script(st); do_draw= 1; break; - default: + case 10: + if (text && text->id.lib) { + error_libdata(); + break; + } + txt_copy_clipboard(text); + txt_cut_sel(text); + pop_space_text(st); + do_draw= 1; + break; + case 11: + //txt_copy_sel(text); + txt_copy_clipboard(text); + break; + case 12: + if (text && text->id.lib) { + error_libdata(); + break; + } + txt_paste_clipboard(text); + if (st->showsyntax) txt_format_text(st); + do_draw= 1; break; } } } else if (ascii) { - if (txt_add_char(text, ascii)) { - if (st->showsyntax) get_format_string(st); + if (text && text->id.lib) { + error_libdata(); + } else { + short mval[2]; + getmouseco_areawin(mval); + if (st->showlinenrs && mval[0]>2 && mval[0]<60 && mval[1]>2 && mval[1]winy-2) { + if (ascii>='0' && ascii<='9') { + double time = PIL_check_seconds_timer(); + if (last_jump < time-1) jump_to= 0; + jump_to *= 10; jump_to += (int)(ascii-'0'); + txt_move_toline(text, jump_to-1, 0); + last_jump= time; + } + } else if ((st->overwrite && txt_replace_char(text, ascii)) || txt_add_char(text, ascii)) { + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } pop_space_text(st); do_draw= 1; } @@ -1622,16 +2908,20 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } break; /* BREAK C */ case DKEY: + if (text && text->id.lib) { + error_libdata(); + break; + } if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { //uncommenting txt_order_cursors(text); uncomment(text); do_draw = 1; - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; } else if (G.qual == LR_CTRLKEY) { txt_delete_char(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_line(st, text->curl, 1); do_draw= 1; pop_space_text(st); } @@ -1640,6 +2930,10 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { switch(pupmenu("Edit %t|Cut %x0|Copy %x1|Paste %x2|Print Cut Buffer %x3")) { case 0: + if (text && text->id.lib) { + error_libdata(); + break; + } txt_copy_clipboard(text); //First copy to clipboard txt_cut_sel(text); do_draw= 1; @@ -1650,9 +2944,13 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) do_draw= 1; break; case 2: + if (text && text->id.lib) { + error_libdata(); + break; + } //txt_paste(text); txt_paste_clipboard(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); do_draw= 1; break; case 3: @@ -1687,17 +2985,17 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; } } - else if (G.qual == LR_ALTKEY) { - if (txt_has_sel(text)) { - txt_find_panel(st,0); - do_draw= 1; - } - } - else if (G.qual == (LR_ALTKEY|LR_CTRLKEY)) { /* always search button */ - txt_find_panel(st,1); + else if (G.qual & (LR_ALTKEY|LR_CTRLKEY)) { + find_and_replace(st, 0); do_draw= 1; } break; /* BREAK F */ + case HKEY: + if (G.qual & (LR_ALTKEY|LR_CTRLKEY)) { + find_and_replace(st, 1); + do_draw= 1; + } + break; /* BREAK H */ case JKEY: if (G.qual == LR_ALTKEY) { do_draw= jumptoline_interactive(st); @@ -1706,7 +3004,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case MKEY: if (G.qual == LR_ALTKEY) { txt_export_to_object(text); - do_draw= 1; + do_draw= 1; } break; /* BREAK M */ case NKEY: @@ -1716,7 +3014,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); - } break; /* BREAK N */ case OKEY: @@ -1740,7 +3037,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (okee("Reopen text")) { if (!reopen_text(text)) error("Could not reopen file"); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); } do_draw= 1; } @@ -1780,11 +3077,13 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) //txt_print_undo(text); //debug buffer in console if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { txt_do_redo(text); + pop_space_text(st); do_draw= 1; } if (G.qual == LR_ALTKEY) { txt_do_undo(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); + pop_space_text(st); do_draw= 1; } break; /* BREAK U */ @@ -1813,20 +3112,28 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } /* Support for both Alt-V and Ctrl-V for Paste, for backward compatibility reasons */ else if (G.qual & LR_ALTKEY || G.qual & LR_CTRLKEY) { + if (text && text->id.lib) { + error_libdata(); + break; + } /* Throwing in the Shift modifier Paste from the OS clipboard */ if (G.qual & LR_SHIFTKEY) txt_paste_clipboard(text); else txt_paste_clipboard(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); do_draw= 1; pop_space_text(st); } break; /* BREAK V */ case XKEY: if (G.qual == LR_ALTKEY || G.qual == LR_CTRLKEY) { + if (text && text->id.lib) { + error_libdata(); + break; + } txt_cut_sel(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); do_draw= 1; pop_space_text(st); } @@ -1838,31 +3145,40 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } else { txt_do_undo(text); } - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); + pop_space_text(st); do_draw= 1; } break; case TABKEY: - if (G.qual & LR_SHIFTKEY) { - if (txt_has_sel(text)) { - txt_order_cursors(text); - unindent(text); - - } + if (text && text->id.lib) { + error_libdata(); + break; } else { - if ( txt_has_sel(text)) { - txt_order_cursors(text); - indent(text); + if (txt_has_sel(text)) { + if (G.qual & LR_SHIFTKEY) { + txt_order_cursors(text); + unindent(text); + if (st->showsyntax) txt_format_text(st); + } else { + txt_order_cursors(text); + indent(text); + if (st->showsyntax) txt_format_text(st); + } } else { txt_add_char(text, '\t'); + if (st->showsyntax) txt_format_line(st, text->curl, 1); } } - if (st->showsyntax) get_format_string(st); pop_space_text(st); do_draw= 1; st->currtab_set = setcurr_tab(text); break; case RETKEY: + if (text && text->id.lib) { + error_libdata(); + break; + } //double check tabs before splitting the line st->currtab_set = setcurr_tab(text); txt_split_curline(text); @@ -1876,33 +3192,52 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } } - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) { + if (text->curl->prev) txt_format_line(st, text->curl->prev, 0); + txt_format_line(st, text->curl, 1); + } do_draw= 1; pop_space_text(st); break; case BACKSPACEKEY: - txt_backspace_char(text); + if (text && text->id.lib) { + error_libdata(); + break; + } + if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { + txt_backspace_word(text); + } else { + txt_backspace_char(text); + } set_tabs(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_line(st, text->curl, 1); do_draw= 1; pop_space_text(st); break; case DELKEY: - txt_delete_char(text); - if (st->showsyntax) get_format_string(st); + if (text && text->id.lib) { + error_libdata(); + break; + } + if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { + txt_delete_word(text); + } else { + txt_delete_char(text); + } + if (st->showsyntax) txt_format_line(st, text->curl, 1); do_draw= 1; pop_space_text(st); st->currtab_set = setcurr_tab(text); break; - case DOWNARROWKEY: - txt_move_down(text, G.qual & LR_SHIFTKEY); - set_tabs(text); + case INSERTKEY: + st->overwrite= !st->overwrite; do_draw= 1; - pop_space_text(st); break; case LEFTARROWKEY: if (G.qual & LR_COMMANDKEY) txt_move_bol(text, G.qual & LR_SHIFTKEY); + else if (G.qual & LR_ALTKEY) + txt_jump_left(text, G.qual & LR_SHIFTKEY); else txt_move_left(text, G.qual & LR_SHIFTKEY); set_tabs(text); @@ -1912,6 +3247,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case RIGHTARROWKEY: if (G.qual & LR_COMMANDKEY) txt_move_eol(text, G.qual & LR_SHIFTKEY); + else if (G.qual & LR_ALTKEY) + txt_jump_right(text, G.qual & LR_SHIFTKEY); else txt_move_right(text, G.qual & LR_SHIFTKEY); set_tabs(text); @@ -1919,26 +3256,38 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pop_space_text(st); break; case UPARROWKEY: - txt_move_up(text, G.qual & LR_SHIFTKEY); + if (st->wordwrap) wrap_move_up(st, G.qual & LR_SHIFTKEY); + else txt_move_up(text, G.qual & LR_SHIFTKEY); + set_tabs(text); + do_draw= 1; + pop_space_text(st); + break; + case DOWNARROWKEY: + if (st->wordwrap) wrap_move_down(st, G.qual & LR_SHIFTKEY); + else txt_move_down(text, G.qual & LR_SHIFTKEY); set_tabs(text); do_draw= 1; pop_space_text(st); break; case PAGEDOWNKEY: - screen_skip(st, st->viewlines); + cursor_skip(st, st->viewlines, G.qual & LR_SHIFTKEY); + pop_space_text(st); do_draw= 1; break; case PAGEUPKEY: - screen_skip(st, -st->viewlines); + cursor_skip(st, -st->viewlines, G.qual & LR_SHIFTKEY); + pop_space_text(st); do_draw= 1; break; case HOMEKEY: - txt_move_bol(text, G.qual & LR_SHIFTKEY); + if (st->wordwrap) wrap_move_bol(st, G.qual & LR_SHIFTKEY); + else txt_move_bol(text, G.qual & LR_SHIFTKEY); do_draw= 1; pop_space_text(st); break; case ENDKEY: - txt_move_eol(text, G.qual & LR_SHIFTKEY); + if (st->wordwrap) wrap_move_eol(st, G.qual & LR_SHIFTKEY); + else txt_move_eol(text, G.qual & LR_SHIFTKEY); do_draw= 1; pop_space_text(st); break; @@ -1953,6 +3302,15 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } + /* Run text plugin scripts if enabled */ + if (st->doplugins && event && val) { + if (BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, G.qual)) { + do_draw= 1; + } + } + + if (do_modification_check(st)) do_draw= 1; + if (do_draw) { ScrArea *sa; @@ -1966,179 +3324,150 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } -void do_brackets(void) +void draw_brackets(SpaceText *st) { - SpaceText *st = curarea->spacedata.first; + char ch; + int b, c, startc, endc, find, stack; + int viewc, viewl, offl, offc, x, y; + TextLine *startl, *endl, *linep; Text *text = st->text; - TextLine *tmp, *start; - char test[2]; - int d, pos, open, x, y, x2, y2, h=0; - - if(!text) return; - - tmp = text->curl; - start = text->curl; - test[0] = (unsigned char) tmp->line[text->curc]; - test[1] = '\0'; - - d = check_bracket(test); - if (!d) /* If not pri char */ - { - test[0] = (unsigned char) tmp->line[text->curc-1]; - test[1] = '\0'; - d = check_bracket(test); - if(!d) { - return; /*If the current char or prev is not a bracket then return*/ - } else { /* current char */ - h= txt_get_span(text->lines.first, start) - st->top; - x = text_draw(st, start->line, st->left, text->curc-1, 0, 0, 0, NULL); - y = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL); - if (d < 4) { - pos = text->curc; - } else { - pos = text->curc-2; - } - } - } else { /* is pri char */ - h= txt_get_span(text->lines.first, start) - st->top; - x = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL); - y = text_draw(st, start->line, st->left, text->curc+1, 0, 0, 0, NULL); - if (d < 4) { - pos = text->curc+1; - } else { - pos = text->curc-1; - } - } - - if (d < 4) /*reading forward*/ - { - open = 1; - while ( tmp ) { - while (pos <= tmp->len) { - test[0] = (unsigned char) tmp->line[pos]; - test[1] = '\0'; - if(check_bracket(test) == d) { - open++; - } else if (check_bracket(test) == d+3) { - open--; - if (open == 0) { - BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5); - glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2); + if (!text || !text->curl) return; - h= txt_get_span(text->lines.first, tmp) - st->top; - x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL); - y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL); - glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2); - BIF_ThemeColor(TH_TEXT); - return; + startl= text->curl; + startc= text->curc; + b= check_bracket(startl->line[startc]); + if (b==0 && startc>0) b = check_bracket(startl->line[--startc]); + if (b==0) return; + + linep= startl; + c= startc; + endl= NULL; + endc= -1; + find= -b; + stack= 0; + + /* Opening bracket, search forward for close */ + if (b>0) { + c++; + while (linep) { + while (clen) { + b= check_bracket(linep->line[c]); + if (b==find) { + if (stack==0) { + endl= linep; + endc= c; + break; } + stack--; + } else if (b==-find) { + stack++; } - pos++; + c++; } - tmp = tmp->next; - pos = 0; + if (endl) break; + linep= linep->next; + c= 0; } - } else { /* reading back */ - open = 1; - while ( tmp ) { - while (pos >= 0) { - test[0] = (unsigned char) tmp->line[pos]; - test[1] = '\0'; - if(check_bracket(test) == d) { - open++; - } else if (check_bracket(test) == d-3) { - open--; - if (open == 0) { - BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5); - glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2); - - h= txt_get_span(text->lines.first, tmp) - st->top; - x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL); - y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL); - glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2); - BIF_ThemeColor(TH_TEXT); - return; + } + /* Closing bracket, search backward for open */ + else { + c--; + while (linep) { + while (c>=0) { + b= check_bracket(linep->line[c]); + if (b==find) { + if (stack==0) { + endl= linep; + endc= c; + break; } + stack--; + } else if (b==-find) { + stack++; } - pos--; - } - tmp = tmp->prev; - if (tmp) { - pos = tmp->len; + c--; } + if (endl) break; + linep= linep->prev; + if (linep) c= linep->len-1; } } - + + if (!endl || endc==-1) return; + + BIF_ThemeColor(TH_HILITE); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy - st->lheight; + + ch= startl->line[startc]; + wrap_offset(st, startl, startc, &offl, &offc); + viewc= get_char_pos(st, startl->line, startc) - st->left + offc; + if (viewc >= 0){ + viewl= txt_get_span(text->lines.first, startl) - st->top + offl; + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st), y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st)+1, y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + } + ch= endl->line[endc]; + wrap_offset(st, endl, endc, &offl, &offc); + viewc= get_char_pos(st, endl->line, endc) - st->left + offc; + if (viewc >= 0) { + viewl= txt_get_span(text->lines.first, endl) - st->top + offl; + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st), y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st)+1, y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + } } -int check_bracket(char *string) +static int check_bracket(char ch) { - int number, a = 0; - char other[][3] = {"(", "[", "{", ")", "]", "}"}; + int a; + char opens[] = "([{"; + char close[] = ")]}"; - number = 6; - - while(a < number) { - if(strcmp(other[a], string) == 0) - { + for (a=0; a<3; a++) { + if(ch==opens[a]) return a+1; - } - a++; + else if (ch==close[a]) + return -(a+1); } return 0; } -static int check_builtinfuncs(char *string) +static int check_delim(char ch) { - int number = 30, a = 0; + int a; + char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,"; - char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def", - "del", "elif", "else", "except", "exec", "finally", - "for", "from", "global", "if", "import", "in", - "is", "lambda", "not", "or", "pass", "print", - "raise", "return", "try", "while", "yield"}; - - for( a = 0; a < number; a++) { - if(!strcmp(builtinfuncs[a], string)) + for (a=0; a<28; a++) { + if (ch==delims[a]) return 1; } return 0; } -static int check_specialvars(char *string) -{ - int number = 2, a = 0; - char specialvars[][7] = {"def", "class"}; - - for( a = 0; a < number; a++) { - if(!strcmp(specialvars[a], string)) - return a+1; - } +static int check_digit(char ch) { + if (ch < '0') return 0; + if (ch <= '9') return 1; return 0; } -static int check_delim(char *string) -{ - int number = 28, a = 0; - char other[][3] = {"(", ")", ":", "\"", "\'", " ", "~", "!", "%", "^", "&", "*", "-", "+", "=", "[", "]", "{", "}", ";", "/", "<", ">", "|", ".", "#", "\t", ","}; - - for( a = 0; a < number; a++) { - if(!strcmp(other[a], string)) - return 1; - } +static int check_identifier(char ch) { + if (ch < '0') return 0; + if (ch <= '9') return 1; + if (ch < 'A') return 0; + if (ch <= 'Z' || ch == '_') return 1; + if (ch < 'a') return 0; + if (ch <= 'z') return 1; return 0; } -static int check_numbers(char *string) -{ - int number = 10, a = 0; - char other[][2] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; - - for( a = 0; a < number; a++) { - if(!strcmp(other[a], string)) - return 1; - } +static int check_whitespace(char ch) { + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') + return 1; return 0; } @@ -2146,7 +3475,7 @@ void convert_tabs (struct SpaceText *st, int tab) { Text *text = st->text; TextLine *tmp; - char *check_line, *new_line, *format; + char *check_line, *new_line; int extra, number; //unknown for now size_t a, j; @@ -2158,7 +3487,6 @@ void convert_tabs (struct SpaceText *st, int tab) while(tmp) { check_line = tmp->line; new_line = MEM_mallocN(render_string(st, check_line)+1, "Converted_Line"); - format = MEM_mallocN(render_string(st, check_line)+1, "Converted_Syntax_format"); j = 0; for (a=0; a < strlen(check_line); a++) { //foreach char in line if(check_line[a] == '\t') { //checking for tabs @@ -2185,7 +3513,7 @@ void convert_tabs (struct SpaceText *st, int tab) tmp->line = new_line; tmp->len = strlen(new_line); - tmp->format = format; + tmp->format = NULL; tmp = tmp->next; } @@ -2213,7 +3541,6 @@ void convert_tabs (struct SpaceText *st, int tab) if ( extra > 0 ) { //got tabs make malloc and do what you have to do new_line = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Line"); - format = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Syntax_format"); extra = 0; //reuse vars for (a = 0; a < strlen(check_line); a++) { number = 0; @@ -2241,9 +3568,11 @@ void convert_tabs (struct SpaceText *st, int tab) tmp->line = new_line; tmp->len = strlen(new_line); - tmp->format = format; + tmp->format = NULL; } tmp = tmp->next; } } + + if (st->showsyntax) txt_format_text(st); } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 2030eb658de..42576c901d7 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -64,6 +64,7 @@ #include "DNA_gpencil_types.h" #include "DNA_image_types.h" #include "DNA_key_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -134,6 +135,7 @@ #include "BIF_verse.h" #endif +#include "BDR_drawaction.h" #include "BDR_drawmesh.h" #include "BDR_drawobject.h" #include "BDR_editobject.h" @@ -162,6 +164,9 @@ #include "RE_pipeline.h" // make_stars +#include "GPU_draw.h" +#include "GPU_material.h" + #include "multires.h" /* For MULTISAMPLE_ARB #define. @@ -193,132 +198,6 @@ static void star_stuff_term_func(void) glEnd(); } -void default_gl_light(void) -{ - int a; - - /* initialize */ - if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { - U.light[0].flag= 1; - U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; - U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; - U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; - U.light[0].spec[3]= 1.0; - - U.light[1].flag= 0; - U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; - U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; - U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; - U.light[1].spec[3]= 1.0; - - U.light[2].flag= 0; - U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; - U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; - U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; - U.light[2].spec[3]= 1.0; - } - - - glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); - glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); - glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); - - glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); - glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); - glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); - - glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); - glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); - glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); - - for(a=0; a<8; a++) { - if(a<3) { - if(U.light[a].flag) glEnable(GL_LIGHT0+a); - else glDisable(GL_LIGHT0+a); - - // clear stuff from other opengl lamp usage - glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); - glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); - } - else glDisable(GL_LIGHT0+a); - } - - glDisable(GL_LIGHTING); - - glDisable(GL_COLOR_MATERIAL); -} - -/* also called when render 'ogl' - keep synced with Myinit_gl_stuff in the game engine! */ -void init_gl_stuff(void) -{ - float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; - float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - float mat_shininess[] = { 35.0 }; - int a, x, y; - GLubyte pat[32*32]; - const GLubyte *patc= pat; - - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - - default_gl_light(); - - /* no local viewer, looks ugly in ortho mode */ - /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ - - glDepthFunc(GL_LEQUAL); - /* scaling matrices */ - glEnable(GL_NORMALIZE); - - glShadeModel(GL_FLAT); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - glDisable(GL_LIGHTING); - glDisable(GL_LOGIC_OP); - glDisable(GL_STENCIL_TEST); - glDisable(GL_TEXTURE_1D); - glDisable(GL_TEXTURE_2D); - - /* default on, disable/enable should be local per function */ - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glPixelTransferi(GL_MAP_COLOR, GL_FALSE); - glPixelTransferi(GL_RED_SCALE, 1); - glPixelTransferi(GL_RED_BIAS, 0); - glPixelTransferi(GL_GREEN_SCALE, 1); - glPixelTransferi(GL_GREEN_BIAS, 0); - glPixelTransferi(GL_BLUE_SCALE, 1); - glPixelTransferi(GL_BLUE_BIAS, 0); - glPixelTransferi(GL_ALPHA_SCALE, 1); - glPixelTransferi(GL_ALPHA_BIAS, 0); - - glPixelTransferi(GL_DEPTH_BIAS, 0); - glPixelTransferi(GL_DEPTH_SCALE, 1); - glDepthRange(0.0, 1.0); - - a= 0; - for(x=0; x<32; x++) { - for(y=0; y<4; y++) { - if( (x) & 1) pat[a++]= 0x88; - else pat[a++]= 0x22; - } - } - - glPolygonStipple(patc); - - - init_realtime_GL(); -} - void circf(float x, float y, float rad) { GLUquadricObj *qobj = gluNewQuadric(); @@ -1329,60 +1208,196 @@ void drawname(Object *ob) BMF_DrawString(G.font, ob->id.name+2); } +static char *get_cfra_marker_name() +{ + ListBase *markers= &G.scene->markers; + TimeMarker *m1, *m2; + + /* search through markers for match */ + for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) { + if (m1->frame==CFRA) + return m1->name; + if (m2->frame==CFRA) + return m2->name; + + if (m1 == m2) + break; + } + + return NULL; +} +// TODO: move this func into some keyframing API +short ob_cfra_has_keyframe (Object *ob) +{ + // fixme... this is slow! + if (ob) { + ListBase keys = {NULL, NULL}; + ActKeyColumn *ak, *akn; + Key *key= ob_get_key(ob); + int cfra, found= 0; + + /* check active action */ + if (ob->action) { + /* get keyframes of action */ + action_to_keylist(ob->action, &keys, NULL, NULL); + + cfra= frame_to_float(CFRA); + cfra= get_action_frame(ob, cfra); + + /* check if a keyframe occurs on current frame */ + for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { + if (cfra == ak->cfra) { + found= 1; + break; + } + else if (cfra == akn->cfra) { + found= 1; + break; + } + + if (ak == akn) + break; + } + + /* free temp list */ + BLI_freelistN(&keys); + keys.first= keys.last= NULL; + + /* return if found */ + if (found) return 1; + } + + /* accumulate keyframes for available ipo's */ + if (ob->ipo) + ipo_to_keylist(ob->ipo, &keys, NULL, NULL); + if (key) + ipo_to_keylist(key->ipo, &keys, NULL, NULL); + + if (keys.first) { + cfra= frame_to_float(CFRA); + found= 0; + + /* check if a keyframe occurs on current frame */ + for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { + if (IS_EQ(cfra, ak->cfra)) { + found= 1; + break; + } + else if (IS_EQ(cfra, akn->cfra)) { + found= 1; + break; + } + + if (ak == akn) + break; + } + + /* free temp list */ + BLI_freelistN(&keys); + keys.first= keys.last= NULL; + + /* return if found */ + if (found) return 1; + } + } + + /* couldn't find a keyframe */ + return 0; +} + +/* draw info beside axes in bottom left-corner: + * framenum, object name, bone name (if available), marker name (if available) + */ static void draw_selected_name(Object *ob) { - char info[128]; + char info[256], *markern; short offset=30; - - if(ob->type==OB_ARMATURE) { - bArmature *arm= ob->data; - char *name= NULL; - - if(ob==G.obedit) { - EditBone *ebo; - for (ebo=G.edbo.first; ebo; ebo=ebo->next){ - if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { - name= ebo->name; - break; + + /* get name of marker on current frame (if available) */ + markern= get_cfra_marker_name(); + + /* check if there is an object */ + if(ob) { + /* name(s) to display depends on type of object */ + if(ob->type==OB_ARMATURE) { + bArmature *arm= ob->data; + char *name= NULL; + + /* show name of active bone too (if possible) */ + if(ob==G.obedit) { + EditBone *ebo; + for (ebo=G.edbo.first; ebo; ebo=ebo->next){ + if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { + name= ebo->name; + break; + } } } - } - else if(ob->pose && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { - name= pchan->name; - break; + else if(ob->pose && (ob->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { + name= pchan->name; + break; + } } } + if(name && markern) + sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern); + else if(name) + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); } - if(name) - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + Key *key= NULL; + KeyBlock *kb = NULL; + char shapes[75]; + + /* try to display active shapekey too */ + shapes[0] = 0; + key = ob_get_key(ob); + if(key){ + kb = BLI_findlink(&key->block, ob->shapenr-1); + if(kb){ + sprintf(shapes, ": %s ", kb->name); + if(ob->shapeflag == OB_SHAPE_LOCK){ + sprintf(shapes, "%s (Pinned)",shapes); + } + } + } + + if(markern) + sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern); + else + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + } + else { + /* standard object */ + if (markern) + sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + } + + /* colour depends on whether there is a keyframe */ + if (ob_cfra_has_keyframe(ob)) + BIF_ThemeColor(TH_VERTEX_SELECT); else - sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + BIF_ThemeColor(TH_TEXT_HI); } - else if(ob->type==OB_MESH) { - Key *key= NULL; - KeyBlock *kb = NULL; - char shapes[75]; + else { + /* no object */ + if (markern) + sprintf(info, "(%d) <%s>", CFRA, markern); + else + sprintf(info, "(%d)", CFRA); - shapes[0] = 0; - key = ob_get_key(ob); - if(key){ - kb = BLI_findlink(&key->block, ob->shapenr-1); - if(kb){ - sprintf(shapes, ": %s ", kb->name); - if(ob->shapeflag == OB_SHAPE_LOCK){ - sprintf(shapes, "%s (Pinned)",shapes); - } - } - } - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + /* colour is always white */ + BIF_ThemeColor(TH_TEXT_HI); } - else sprintf(info, "(%d) %s", CFRA, ob->id.name+2); - - BIF_ThemeColor(TH_TEXT_HI); + if (U.uiflag & USER_SHOW_ROTVIEWICON) offset = 14 + (U.rvisize * 2); @@ -2737,7 +2752,7 @@ void add_view3d_after(View3D *v3d, Base *base, int type, int flag) } /* clears zbuffer and draws it over */ -static void view3d_draw_xray(View3D *v3d) +static void view3d_draw_xray(View3D *v3d, int clear) { View3DAfter *v3da, *next; int doit= 0; @@ -2746,7 +2761,7 @@ static void view3d_draw_xray(View3D *v3d) if(v3da->type==V3D_XRAY) doit= 1; if(doit) { - if(v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); + if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); v3d->xray= TRUE; for(v3da= v3d->afterdraw.first; v3da; v3da= next) { @@ -2768,7 +2783,7 @@ static void view3d_draw_transp(View3D *v3d) glDepthMask(0); v3d->transp= TRUE; - + for(v3da= v3d->afterdraw.first; v3da; v3da= next) { next= v3da->next; if(v3da->type==V3D_TRANSP) { @@ -2811,7 +2826,8 @@ static void draw_dupli_objects_color(View3D *v3d, Base *base, int color) tbase.object= dob->ob; /* extra service: draw the duplicator in drawtype of parent */ - dt= tbase.object->dt; tbase.object->dt= base->object->dt; + /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ + dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt); dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx; /* negative scale flag has to propagate */ @@ -2946,7 +2962,7 @@ static void draw_sculpt_depths(View3D *v3d) } } -void draw_depth(ScrArea *sa, void *spacedata) +void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *)) { View3D *v3d= spacedata; Base *base; @@ -2986,9 +3002,11 @@ void draw_depth(ScrArea *sa, void *spacedata) if(G.scene->set) { for(SETLOOPER(G.scene->set, base)) { if(v3d->lay & base->lay) { - draw_object(base, 0); - if(base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(v3d, base, TH_WIRE); + if (func == NULL || func(base)) { + draw_object(base, 0); + if(base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(v3d, base, TH_WIRE); + } } } } @@ -2996,12 +3014,13 @@ void draw_depth(ScrArea *sa, void *spacedata) for(base= G.scene->base.first; base; base= base->next) { if(v3d->lay & base->lay) { - - /* dupli drawing */ - if(base->object->transflag & OB_DUPLI) { - draw_dupli_objects(v3d, base); + if (func == NULL || func(base)) { + /* dupli drawing */ + if(base->object->transflag & OB_DUPLI) { + draw_dupli_objects(v3d, base); + } + draw_object(base, 0); } - draw_object(base, 0); } } @@ -3046,6 +3065,84 @@ void draw_depth(ScrArea *sa, void *spacedata) static void draw_viewport_fps(ScrArea *sa); +typedef struct View3DShadow{ + struct View3DShadow*next, *prev; + GPULamp *lamp; +} View3DShadow; + +static void gpu_render_lamp_update(View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows) +{ + GPULamp *lamp; + View3DShadow *shadow; + + lamp = GPU_lamp_from_blender(G.scene, ob, par); + + if(lamp) { + GPU_lamp_update(lamp, ob->lay, obmat); + + if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) { + shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow"); + shadow->lamp = lamp; + BLI_addtail(shadows, shadow); + } + } +} + +static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) +{ + ListBase shadows; + View3DShadow *shadow; + Scene *sce; + Base *base; + Object *ob; + + shadows.first= shadows.last= NULL; + + /* update lamp transform and gather shadow lamps */ + for(SETLOOPER(G.scene, base)) { + ob= base->object; + + if(ob->type == OB_LAMP) + gpu_render_lamp_update(v3d, ob, NULL, ob->obmat, &shadows); + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(G.scene, ob); + + for(dob=lb->first; dob; dob=dob->next) + if(dob->ob->type==OB_LAMP) + gpu_render_lamp_update(v3d, dob->ob, ob, dob->mat, &shadows); + + free_object_duplilist(lb); + } + } + + /* render shadows after updating all lamps, nested object_duplilist + * don't work correct since it's replacing object matrices */ + for(shadow=shadows.first; shadow; shadow=shadow->next) { + /* this needs to be done better .. */ + float viewmat[4][4], winmat[4][4]; + int drawtype, lay, winsize, flag2; + + drawtype= v3d->drawtype; + lay= v3d->lay; + flag2= v3d->flag2 & V3D_SOLID_TEX; + + v3d->drawtype = OB_SOLID; + v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); + v3d->flag2 &= ~V3D_SOLID_TEX; + + GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); + drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1); + GPU_lamp_shadow_buffer_unbind(shadow->lamp); + + v3d->drawtype= drawtype; + v3d->lay= lay; + v3d->flag2 |= flag2; + } + + BLI_freelistN(&shadows); +} void drawview3dspace(ScrArea *sa, void *spacedata) { @@ -3063,9 +3160,16 @@ void drawview3dspace(ScrArea *sa, void *spacedata) for(SETLOOPER(G.scene->set, base)) object_handle_update(base->object); // bke_object.h } - - for(base= G.scene->base.first; base; base= base->next) + + v3d->lay_used = 0; + for(base= G.scene->base.first; base; base= base->next) { object_handle_update(base->object); // bke_object.h + v3d->lay_used |= base->lay; + } + + /* shadow buffers, before we setup matrices */ + if(draw_glsl_material(NULL, v3d->drawtype)) + gpu_update_lamps_shadows(G.scene, v3d); setwinmatrixview3d(sa->winx, sa->winy, NULL); /* 0= no pick rect */ setviewmatrixview3d(); /* note: calls where_is_object for camera... */ @@ -3208,8 +3312,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata) if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID); /* Transp and X-ray afterdraw stuff */ - view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); + view3d_draw_xray(v3d, 1); // clears zbuffer if it is used! if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) { if(G.f & G_SCULPTMODE) @@ -3290,7 +3394,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } ob= OBACT; - if(ob && (U.uiflag & USER_DRAWVIEWINFO)) + if(U.uiflag & USER_DRAWVIEWINFO) draw_selected_name(ob); draw_area_emboss(sa); @@ -3328,18 +3432,29 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } - -void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]) +void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int winy, float winmat[][4], int shadow) { Base *base; Scene *sce; - float v3dwinmat[4][4]; + float v3dviewmat[4][4], v3dwinmat[4][4]; + + /* shadow buffers, before we setup matrices */ + if(!shadow && draw_glsl_material(NULL, v3d->drawtype)) + gpu_update_lamps_shadows(G.scene, v3d); if(!winmat) setwinmatrixview3d(winx, winy, NULL); - setviewmatrixview3d(); - myloadmatrix(v3d->viewmat); + if(viewmat) { + Mat4CpyMat4(v3dviewmat, viewmat); + Mat4CpyMat4(v3d->viewmat, viewmat); + } + else { + setviewmatrixview3d(); + Mat4CpyMat4(v3dviewmat, v3d->viewmat); + } + + myloadmatrix(v3dviewmat); /* when winmat is not NULL, it overrides the regular window matrix */ glMatrixMode(GL_PROJECTION); @@ -3348,12 +3463,14 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] mygetmatrix(v3dwinmat); glMatrixMode(GL_MODELVIEW); - Mat4MulMat4(v3d->persmat, v3d->viewmat, v3dwinmat); + Mat4MulMat4(v3d->persmat, v3dviewmat, v3dwinmat); Mat4Invert(v3d->persinv, v3d->persmat); Mat4Invert(v3d->viewinv, v3d->viewmat); - free_all_realtime_images(); - reshadeall_displist(); + if(!shadow) { + GPU_free_images(); + reshadeall_displist(); + } if(v3d->drawtype > OB_WIRE) { v3d->zbuf= TRUE; @@ -3431,8 +3548,8 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID); /* Transp and X-ray afterdraw stuff */ - view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); + view3d_draw_xray(v3d, !shadow); // clears zbuffer if it is used! if(v3d->flag & V3D_CLIPPING) view3d_clr_clipping(); @@ -3451,11 +3568,12 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] G.f &= ~G_SIMULATION; - glFlush(); + if(!shadow) { + glFlush(); + GPU_free_images(); + } glLoadIdentity(); - - free_all_realtime_images(); } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index c454715b1df..fe83976ee57 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -74,6 +74,7 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -2153,7 +2154,7 @@ void paste_actdata () /* loop over curves, pasting keyframes */ for (ico= ipo_src->curve.first; ico; ico= ico->next) { - icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode); + icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode, 1); if (icu) { /* just start pasting, with the the first keyframe on the current frame, and so on */ diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 35986fcff4a..5e50c8117cc 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -439,6 +439,109 @@ void docenter_armature (Object *ob, int centermode) } } +/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */ +static void applyarmature_fix_boneparents (Object *armob) +{ + Object *ob; + + /* go through all objects in database */ + for (ob= G.main->object.first; ob; ob= ob->id.next) { + /* if parent is bone in this armature, apply corrections */ + if ((ob->parent == armob) && (ob->partype == PARBONE)) { + /* apply current transform from parent (not yet destroyed), + * then calculate new parent inverse matrix + */ + apply_obmat(ob); + + what_does_parent(ob); + Mat4Invert(ob->parentinv, workob.obmat); + } + } +} + +/* set the current pose as the restpose */ +void apply_armature_pose2bones(void) +{ + Object *ob; + bArmature *arm; + bPose *pose; + bPoseChannel *pchan; + EditBone *curbone; + + /* don't check if editmode (should be done by caller) */ + ob= OBACT; + if (ob->type!=OB_ARMATURE) return; + if (object_data_is_libdata(ob)) { + error_libdata(); + return; + } + arm= get_armature(ob); + + /* helpful warnings... */ + // TODO: add warnings to be careful about actions, applying deforms first, etc. + + /* Get editbones of active armature to alter */ + if (G.edbo.first) BLI_freelistN(&G.edbo); + make_boneList(&G.edbo, &arm->bonebase, NULL); + + /* get pose of active object and move it out of posemode */ + pose= ob->pose; + + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { + curbone= editbone_name_exists(&G.edbo, pchan->name); + + /* simply copy the head/tail values from pchan over to curbone */ + VECCOPY(curbone->head, pchan->pose_head); + VECCOPY(curbone->tail, pchan->pose_tail); + + /* fix roll: + * 1. find auto-calculated roll value for this bone now + * 2. remove this from the 'visual' y-rotation + */ + { + float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3]; + float delta[3], eul[3]; + + /* obtain new auto y-rotation */ + VecSubf(delta, curbone->tail, curbone->head); + vec_roll_to_mat3(delta, 0.0, premat); + Mat3Inv(imat, premat); + + /* get pchan 'visual' matrix */ + Mat3CpyMat4(pmat, pchan->pose_mat); + + /* remove auto from visual and get euler rotation */ + Mat3MulMat3(tmat, imat, pmat); + Mat3ToEul(tmat, eul); + + /* just use this euler-y as new roll value */ + curbone->roll= eul[1]; + } + + /* clear transform values for pchan */ + pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0; + pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0; + pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1; + + /* set anim lock */ + curbone->flag |= BONE_UNKEYED; + } + + /* convert editbones back to bones */ + editbones_to_armature(&G.edbo, ob); + if (G.edbo.first) BLI_freelistN(&G.edbo); + + /* flush positions of posebones */ + where_is_pose(ob); + + /* fix parenting of objects which are bone-parented */ + applyarmature_fix_boneparents(ob); + + BIF_undo_push("Apply new restpose"); + allqueue(REDRAWVIEW3D, 0); +} + + /* Helper function for armature joining - link fixing */ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone) { diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c index 5de4c6ed23c..3f178e1ea2b 100644 --- a/source/blender/src/editdeform.c +++ b/source/blender/src/editdeform.c @@ -270,7 +270,7 @@ static void del_defgroup_update_users(Object *ob, int id) int a; /* these cases don't use names to refer to vertex groups, so when - * they get deleted the numbers get out of synce, this corrects that */ + * they get deleted the numbers get out of sync, this corrects that */ if(ob->soft) { if(ob->soft->vertgroup == id) diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 781210cd373..008ddf3b5f0 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -82,13 +82,14 @@ #include "BIF_space.h" /* for allqueue */ #include "BIF_drawimage.h" /* for allqueue */ -#include "BDR_drawmesh.h" #include "BDR_editface.h" #include "BDR_vpaint.h" #include "BDR_editface.h" #include "BDR_vpaint.h" +#include "GPU_draw.h" + #include "mydevice.h" #include "blendef.h" #include "butspace.h" @@ -1315,7 +1316,7 @@ void set_texturepaint() /* toggle */ if(G.f & G_TEXTUREPAINT) { G.f &= ~G_TEXTUREPAINT; - texpaint_enable_mipmap(); + GPU_paint_set_mipmap(1); } else if (me) { G.f |= G_TEXTUREPAINT; @@ -1324,7 +1325,7 @@ void set_texturepaint() /* toggle */ make_tfaces(me); brush_check_exists(&G.scene->toolsettings->imapaint.brush); - texpaint_disable_mipmap(); + GPU_paint_set_mipmap(0); } allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index cd6aefdb87c..09862636085 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -97,6 +97,7 @@ #include "BIF_editseq.h" #include "BIF_editview.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -1776,113 +1777,129 @@ void do_ipo_selectbuttons(void) - if bonename, the constname is the ipo to the constraint */ -/* note; check header_ipo.c, spaceipo_assign_ipo() too */ -Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename) +/* note: check header_ipo.c, spaceipo_assign_ipo() too */ +Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename, short add) { - - if(from==NULL || from->lib) return NULL; + /* lib-linked data is not appropriate here */ + if ((from==NULL) || (from->lib)) + return NULL; /* first check action ipos */ - if(actname && actname[0]) { + if (actname && actname[0]) { Object *ob= (Object *)from; bActionChannel *achan; - if(GS(from->name)!=ID_OB) { + if (GS(from->name)!=ID_OB) { printf("called ipo system for action with wrong base pointer\n"); return NULL; } - if(ob->action==NULL) + if ((ob->action==NULL) && (add)) ob->action= add_empty_action("Action"); - achan= verify_action_channel(ob->action, actname); + if (add) + achan= verify_action_channel(ob->action, actname); + else + achan= get_action_channel(ob->action, actname); - if(achan) { + if (achan) { /* automatically assign achan to act-group based on pchan's grouping */ - if (blocktype == ID_PO) + if ((blocktype == ID_PO) && (add)) verify_pchan2achan_grouping(ob->action, ob->pose, actname); /* constraint exception */ - if(blocktype==ID_CO) { - bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname); - if(conchan->ipo==NULL) { - conchan->ipo= add_ipo("CoIpo", ID_CO); + if (blocktype==ID_CO) { + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&achan->constraintChannels, constname); + else + conchan= get_constraint_channel(&achan->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; } - return conchan->ipo; } else { - if(achan->ipo==NULL) { + if ((achan->ipo==NULL) && (add)) achan->ipo= add_ipo("ActIpo", blocktype); - } - return achan->ipo; } } } else { - - switch(GS(from->name)) { + switch (GS(from->name)) { case ID_OB: { Object *ob= (Object *)from; /* constraint exception */ - if(blocktype==ID_CO) { + if (blocktype==ID_CO) { /* check the local constraint ipo */ - if(bonename && bonename[0] && ob->pose) { + if (bonename && bonename[0] && ob->pose) { bPoseChannel *pchan= get_pose_channel(ob->pose, bonename); bConstraint *con; - for(con= pchan->constraints.first; con; con= con->next) - if(strcmp(con->name, constname)==0) + + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(con->name, constname)==0) break; - if(con) { - if(con->ipo==NULL) { + } + + if (con) { + if ((con->ipo==NULL) && (add)) con->ipo= add_ipo("CoIpo", ID_CO); - } return con->ipo; } } else { /* the actionchannel */ - bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname); - if(conchan->ipo==NULL) { - conchan->ipo= add_ipo("CoIpo", ID_CO); + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&ob->constraintChannels, constname); + else + conchan= get_constraint_channel(&ob->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; } - return conchan->ipo; } } - else if(blocktype==ID_OB) { - if(ob->ipo==NULL) { + else if (blocktype==ID_OB) { + if ((ob->ipo==NULL) && (add)) ob->ipo= add_ipo("ObIpo", ID_OB); - } return ob->ipo; } - else if(blocktype==ID_KE) { + else if (blocktype==ID_KE) { Key *key= ob_get_key((Object *)from); - if(key) { - if(key->ipo==NULL) { + if (key) { + if ((key->ipo==NULL) && (add)) key->ipo= add_ipo("KeyIpo", ID_KE); - } return key->ipo; } return NULL; } - else if(blocktype== ID_FLUIDSIM) { + else if (blocktype== ID_FLUIDSIM) { Object *ob= (Object *)from; - if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { + + if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { FluidsimSettings *fss= ob->fluidsimSettings; - if(fss->ipo==NULL) { + + if ((fss->ipo==NULL) && (add)) fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM); - //fprintf(stderr,"FSIPO NEW!\n"); - } return fss->ipo; } } - else if(blocktype== ID_PA){ + else if(blocktype== ID_PA) { Object *ob= (Object *)from; ParticleSystem *psys= psys_get_current(ob); - if(psys){ - if(psys->part->ipo==0) + + if (psys) { + if ((psys->part->ipo==NULL) && (add)) psys->part->ipo= add_ipo("ParticleIpo", ID_PA); return psys->part->ipo; } @@ -1893,30 +1910,27 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char case ID_MA: { Material *ma= (Material *)from; - - if(ma->ipo==NULL) { + + if ((ma->ipo==NULL) && (add)) ma->ipo= add_ipo("MatIpo", ID_MA); - } return ma->ipo; } break; case ID_TE: { Tex *tex= (Tex *)from; - - if(tex->ipo==NULL) { + + if ((tex->ipo==NULL) && (add)) tex->ipo= add_ipo("TexIpo", ID_TE); - } return tex->ipo; } break; case ID_SEQ: { Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */ - - if(seq->ipo==NULL) { + + if ((seq->ipo==NULL) && (add)) seq->ipo= add_ipo("SeqIpo", ID_SEQ); - } update_seq_ipo_rect(seq); return seq->ipo; } @@ -1925,19 +1939,17 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Curve *cu= (Curve *)from; - if(cu->ipo==NULL) { + if ((cu->ipo==NULL) && (add)) cu->ipo= add_ipo("CuIpo", ID_CU); - } return cu->ipo; } break; case ID_WO: { World *wo= (World *)from; - - if(wo->ipo==NULL) { + + if ((wo->ipo==NULL) && (add)) wo->ipo= add_ipo("WoIpo", ID_WO); - } return wo->ipo; } break; @@ -1945,29 +1957,26 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Lamp *la= (Lamp *)from; - if(la->ipo==NULL) { + if ((la->ipo==NULL) && (add)) la->ipo= add_ipo("LaIpo", ID_LA); - } return la->ipo; } break; case ID_CA: { Camera *ca= (Camera *)from; - - if(ca->ipo==NULL) { + + if ((ca->ipo==NULL) && (add)) ca->ipo= add_ipo("CaIpo", ID_CA); - } return ca->ipo; } break; case ID_SO: { bSound *snd= (bSound *)from; - - if(snd->ipo==NULL) { + + if ((snd->ipo==NULL) && (add)) snd->ipo= add_ipo("SndIpo", ID_SO); - } return snd->ipo; } } @@ -1979,32 +1988,36 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char /* returns and creates * Make sure functions check for NULL or they will crash! * */ -IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode) +IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode, short add) { Ipo *ipo; IpoCurve *icu= NULL; /* return 0 if lib */ - /* creates ipo too */ - ipo= verify_ipo(from, blocktype, actname, constname, bonename); + /* creates ipo too (if add) */ + ipo= verify_ipo(from, blocktype, actname, constname, bonename, add); - if(ipo && ipo->id.lib==NULL && from->lib==NULL) { - - for(icu= ipo->curve.first; icu; icu= icu->next) { - if(icu->adrcode==adrcode) break; + if (ipo && ipo->id.lib==NULL && from->lib==NULL) { + /* try to find matching curve */ + for (icu= ipo->curve.first; icu; icu= icu->next) { + if (icu->adrcode==adrcode) + break; } - if(icu==NULL) { + + /* make a new one if none found (and can add) */ + if ((icu==NULL) && (add)) { icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); - icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ; - if(ipo->curve.first==NULL) icu->flag |= IPO_ACTIVE; /* first one added active */ + icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ); + if (ipo->curve.first==NULL) + icu->flag |= IPO_ACTIVE; /* first one added active */ icu->blocktype= blocktype; icu->adrcode= adrcode; set_icu_vars(icu); - BLI_addtail( &(ipo->curve), icu); + BLI_addtail(&ipo->curve, icu); switch (GS(from->name)) { case ID_SEQ: { @@ -2016,190 +2029,12 @@ IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constn } } } - + + /* return ipo-curve */ return icu; } -/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ -#define BEZT_INSERT_THRESH 0.00001 - -/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) - * Returns the index to insert at (data already at that index will be offset if replace is 0) - */ -static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) -{ - int start=0, end=arraylen; - int loopbreaker= 0, maxloop= arraylen * 2; - const float frame= (item)? item->vec[1][0] : 0.0f; - - /* initialise replace-flag first */ - *replace= 0; - - /* sneaky optimisations (don't go through searching process if...): - * - keyframe to be added is to be added out of current bounds - * - keyframe to be added would replace one of the existing ones on bounds - */ - if ((arraylen <= 0) || ELEM(NULL, array, item)) { - printf("Warning: binarysearch_bezt_index encountered invalid array \n"); - return 0; - } - else { - /* check whether to add before/after/on */ - float framenum; - - /* 'First' Keyframe (when only one keyframe, this case is used) */ - framenum= array[0].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace = 1; - return 0; - } - else if (frame < framenum) - return 0; - - /* 'Last' Keyframe */ - framenum= array[(arraylen-1)].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace= 1; - return (arraylen - 1); - } - else if (frame > framenum) - return arraylen; - } - - - /* most of the time, this loop is just to find where to put it - * 'loopbreaker' is just here to prevent infinite loops - */ - for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { - /* compute and get midpoint */ - int mid = (start + end) / 2; - float midfra= array[mid].vec[1][0]; - - /* check if exactly equal to midpoint */ - if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { - *replace = 1; - return mid; - } - - /* repeat in upper/lower half */ - if (frame > midfra) - start= mid + 1; - else if (frame < midfra) - end= mid - 1; - } - - /* print error if loop-limit exceeded */ - if (loopbreaker == (maxloop-1)) { - printf("Error: binarysearch_bezt_index was taking too long \n"); - - // include debug info - printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); - } - - /* not found, so return where to place it */ - return start; -} - -/* This function adds a given BezTriple to an IPO-Curve. It will allocate - * memory for the array if needed, and will insert the BezTriple into a - * suitable place in chronological order. - * - * NOTE: any recalculate of the IPO-Curve that needs to be done will need to - * be done by the caller. - */ -int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) -{ - BezTriple *newb; - int i= 0; - - if (icu->bezt == NULL) { - icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); - *(icu->bezt)= *bezt; - icu->totvert= 1; - } - else { - short replace = -1; - i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); - - if (replace) { - /* sanity check: 'i' may in rare cases exceed arraylen */ - if ((i >= 0) && (i < icu->totvert)) - *(icu->bezt + i) = *bezt; - } - else { - /* add new */ - newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); - - /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ - if (i > 0) - memcpy(newb, icu->bezt, i*sizeof(BezTriple)); - - /* add beztriple to paste at index i */ - *(newb + i)= *bezt; - - /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ - if (i < icu->totvert) - memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); - - /* replace (+ free) old with new */ - MEM_freeN(icu->bezt); - icu->bezt= newb; - - icu->totvert++; - } - } - - /* we need to return the index, so that some tools which do post-processing can - * detect where we added the BezTriple in the array - */ - return i; -} - -/* This function is a wrapper for insert_bezt_icu, and should be used when - * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere - * else yet. - * - * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. - */ -void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) -{ - BezTriple beztr; - int a, h1, h2; - - /* set all three points, for nicer start position */ - memset(&beztr, 0, sizeof(BezTriple)); - beztr.vec[0][0]= x; - beztr.vec[0][1]= y; - beztr.vec[1][0]= x; - beztr.vec[1][1]= y; - beztr.vec[2][0]= x; - beztr.vec[2][1]= y; - beztr.hide= IPO_BEZ; - beztr.f1= beztr.f2= beztr.f3= SELECT; - beztr.h1= beztr.h2= HD_AUTO; - - /* add temp beztriple to keyframes */ - a= insert_bezt_icu(icu, &beztr); - if (!fast) calchandles_ipocurve(icu); - - /* set handletype */ - if (icu->totvert > 2) { - BezTriple *bezt; - - h1= h2= HD_AUTO; - bezt= (icu->bezt + a); - - if (a > 0) h1= (bezt-1)->h2; - if (a < icu->totvert-1) h2= (bezt+1)->h1; - - bezt->h1= h1; - bezt->h2= h2; - - if (!fast) calchandles_ipocurve(icu); - } -} - void add_vert_ipo(void) { EditIpo *ei; @@ -2233,7 +2068,7 @@ void add_vert_ipo(void) if(ei->icu==NULL) { if(G.sipo->from) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu) ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ; /* new curve could have been added, weak... */ else @@ -2259,525 +2094,6 @@ void add_vert_ipo(void) BIF_undo_push("Add Ipo vertex"); } -static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) -{ - if (blocktype==ID_PO) { - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - *vartype= IPO_FLOAT; - return get_pchan_ipo_poin(pchan, icu->adrcode); - } - else - return NULL; - } - return NULL; - } - else if (blocktype==ID_CO) { - if ((GS(id->name)==ID_OB) && (constname && constname[0])) { - Object *ob= (Object *)id; - bConstraint *con; - - /* assume that we only want the influence (as only used for Constraint Channels) */ - if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { - for (con= ob->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - else if (ob->pose) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - for (con= pchan->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - } - } - return NULL; - } - else - return get_ipo_poin(id, icu, vartype); - -} - -#define KEYNEEDED_DONTADD 0 -#define KEYNEEDED_JUSTADD 1 -#define KEYNEEDED_DELPREV 2 -#define KEYNEEDED_DELNEXT 3 - -static int new_key_needed(IpoCurve *icu, float cFrame, float nValue) -{ - /* This function determines whether a new keyframe is needed */ - /* Cases where keyframes should not be added: - * 1. Keyframe to be added bewteen two keyframes with similar values - * 2. Keyframe to be added on frame where two keyframes are already situated - * 3. Keyframe lies at point that intersects the linear line between two keyframes - */ - - BezTriple *bezt=NULL, *prev=NULL; - int totCount, i; - float valA = 0.0f, valB = 0.0f; - - /* safety checking */ - if (!icu) return KEYNEEDED_JUSTADD; - totCount= icu->totvert; - if (totCount==0) return KEYNEEDED_JUSTADD; - - /* loop through checking if any are the same */ - bezt= icu->bezt; - for (i=0; ivec[1][0]; - beztVal= bezt->vec[1][1]; - - if (prev) { - /* there is a keyframe before the one currently being examined */ - - /* get previous time+value */ - prevPosi= prev->vec[1][0]; - prevVal= prev->vec[1][1]; - - /* keyframe to be added at point where there are already two similar points? */ - if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { - return KEYNEEDED_DONTADD; - } - - /* keyframe between prev+current points ? */ - if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { - /* is the value of keyframe to be added the same as keyframes on either side ? */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { - return KEYNEEDED_DONTADD; - } - else { - float realVal; - - /* get real value of curve at that point */ - realVal= eval_icu(icu, cFrame); - - /* compare whether it's the same as proposed */ - if (IS_EQ(realVal, nValue)) - return KEYNEEDED_DONTADD; - else - return KEYNEEDED_JUSTADD; - } - } - - /* new keyframe before prev beztriple? */ - if (cFrame < prevPosi) { - /* A new keyframe will be added. However, whether the previous beztriple - * stays around or not depends on whether the values of previous/current - * beztriples and new keyframe are the same. - */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) - return KEYNEEDED_DELNEXT; - else - return KEYNEEDED_JUSTADD; - } - } - else { - /* just add a keyframe if there's only one keyframe - * and the new one occurs before the exisiting one does. - */ - if ((cFrame < beztPosi) && (totCount==1)) - return KEYNEEDED_JUSTADD; - } - - /* continue. frame to do not yet passed (or other conditions not met) */ - if (i < (totCount-1)) { - prev= bezt; - bezt++; - } - else - break; - } - - /* Frame in which to add a new-keyframe occurs after all other keys - * -> If there are at least two existing keyframes, then if the values of the - * last two keyframes and the new-keyframe match, the last existing keyframe - * gets deleted as it is no longer required. - * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last - * keyframe is not equal to last keyframe. - */ - bezt= (icu->bezt + (icu->totvert - 1)); - valA= bezt->vec[1][1]; - - if (prev) - valB= prev->vec[1][1]; - else - valB= bezt->vec[1][1] + 1.0f; - - if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) - return KEYNEEDED_DELPREV; - else - return KEYNEEDED_JUSTADD; -} - -/* a duplicate of insertkey that does not check for routing to insertmatrixkey - to avoid recursion problems */ -static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int matset=0; - - if (matset==0) { - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - insert_vert_icu(icu, cfra, curval, 0); - } - } - } -} - -int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - int matindex=0; - /* branch on adrcode and blocktype, generating the proper matrix-based - values to send to insertfloatkey */ - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - - if ( blocktype==ID_OB ){ //working with an object - if ((ob)&&!(ob->parent)) { - if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)) { //get a rotation - float eul[3]; - switch (adrcode) { - case OB_ROT_X: - matindex=0; - break; - case OB_ROT_Y: - matindex=1; - break; - case OB_ROT_Z: - matindex=2; - break; - } - Mat4ToEul(ob->obmat, eul); - insertfloatkey(id, ID_OB, actname, NULL, adrcode, eul[matindex]*(5.72958)); - return 1; - } else if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)) {//get a translation - switch (adrcode) { - case OB_LOC_X: - matindex=0; - break; - case OB_LOC_Y: - matindex=1; - break; - case OB_LOC_Z: - matindex=2; - break; - } - insertfloatkey(id, ID_OB, actname, NULL, adrcode, ob->obmat[3][matindex]); - return 1; - } - } - } else if ( blocktype==ID_PO) { //working with a pose channel - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - if (pchan) { - if ((adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { - switch (adrcode) { - case AC_LOC_X: - matindex=0; - break; - case AC_LOC_Y: - matindex=1; - break; - case AC_LOC_Z: - matindex=2; - break; - } - if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_CONNECTED))) { /* don't use for non-connected child bones */ - float delta_mat[4][4]; - armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat); - insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, delta_mat[3][matindex]); - return 1; - } - } else if ((adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { - float tmat[4][4], trimat[3][3], localQuat[4]; - - switch (adrcode) { - case AC_QUAT_W: - matindex=0; - break; - case AC_QUAT_X: - matindex=1; - break; - case AC_QUAT_Y: - matindex=2; - break; - case AC_QUAT_Z: - matindex=3; - break; - } - - /* it should be reasonable to assume that we are keyframing on the active object, although it is not - * strictly required for this particular space conversion, arg1 must not be null for this to work - */ - Mat4CpyMat4(tmat, pchan->pose_mat); - constraint_mat_convertspace(OBACT, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); - - Mat3CpyMat4(trimat, tmat); - Mat3ToQuat_is_ok(trimat, localQuat); - insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, localQuat[matindex]); - - return 1; - } - } - } - } - /* failed to set a matrix key -- use traditional, but the non-recursing version */ - insertkey_nonrecurs(id,blocktype,actname,constname,adrcode); - return 0; -} - -static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrcode) -{ /* This function matches constraint blocks with adrcodes to see if the - visual keying method should be used. For example, an object looking to key - location and having a CopyLoc constraint would return true. */ - - Object *ob=NULL; - int foundmatch=0; - int searchtype=0; - bConstraint *conref=NULL, *con=NULL; - - /*Retrieve constraint list*/ - if( GS(id->name)==ID_OB ) - ob= (Object *)id; - if (ob) { - if (blocktype==ID_PO) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - conref=pchan->constraints.first; - } else if (blocktype==ID_OB) { - conref=ob->constraints.first; - } - - if (conref) { - /*Set search type: 1 is for translation contraints, 2 is for rotation*/ - if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)||(adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { - searchtype=1; - } else if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)||(adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { - searchtype=2; - } - - if (searchtype>0) { - for (con=conref; (con)&&(foundmatch==0); con=con->next) { - switch (con->type) { - /* match constraint types to which kinds of keying they would affect */ - case CONSTRAINT_TYPE_CHILDOF: - foundmatch=1; - break; - case CONSTRAINT_TYPE_TRACKTO: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_FOLLOWPATH: - foundmatch=1; - break; - case CONSTRAINT_TYPE_ROTLIMIT: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCLIMIT: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_ROTLIKE: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCLIKE: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCKTRACK: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_DISTLIMIT: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_MINMAX: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_TRANSFORM: - foundmatch=1; - break; - default: - break; - } - } - } - } - } - - return foundmatch; - -} - -void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int matset=0; - - if ((IS_AUTOKEY_FLAG(AUTOMATKEY))&&(match_adr_constraint(id, blocktype, actname, adrcode))) { - matset=insertmatrixkey(id, blocktype, actname, constname, adrcode); - } - if (matset==0) { - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - insert_vert_icu(icu, cfra, curval, fast); - } - } - } -} - - - -/* This function is a 'smarter' version of the insert key code. - * It uses an auxilliary function to check whether a keyframe is really needed */ -void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int insert_mode; - - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* check whether this curve really needs a new keyframe */ - insert_mode= new_key_needed(icu, cfra, curval); - - /* insert new keyframe at current frame */ - if (insert_mode) - insert_vert_icu(icu, cfra, curval, 0); - - /* delete keyframe immediately before/after newly added */ - switch (insert_mode) { - case KEYNEEDED_DELPREV: - delete_icu_key(icu, icu->totvert-2, 1); - break; - case KEYNEEDED_DELNEXT: - delete_icu_key(icu, 1, 1); - break; - } - } - } -} - -/* For inserting keys based on an arbitrary float value */ -void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float cfra; - int vartype; - - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* insert new keyframe at current frame */ - insert_vert_icu(icu, cfra, floatkey, 0); - } - } -} void insertkey_editipo(void) { @@ -2909,598 +2225,6 @@ void insertkey_editipo(void) } -void common_insertkey(void) -{ - Base *base; - Object *ob; - Material *ma; - ID *id; - IpoCurve *icu; - World *wo; - Lamp *la; - Tex *te; - int tlay, map, event; - char menustr[256]; - - if(curarea->spacetype==SPACE_IPO) { - insertkey_editipo(); - } - else if(curarea->spacetype==SPACE_ACTION) { - insertkey_action(); - } - else if(curarea->spacetype==SPACE_BUTS) { - if(G.buts->mainb==CONTEXT_SHADING) { - int tab= G.buts->tab[CONTEXT_SHADING]; - - if(tab==TAB_SHADING_MAT) { - ma = G.buts->lockpoin; - ma = editnode_get_active_material(ma); - id = (ID *)ma; - - if(id) { - event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|Halo Size%x2|Mode %x3|All Color%x10|All Mirror%x14|Ofs%x12|Size%x13|All Mapping%x11"); - if(event== -1) return; - - map= texchannel_to_adrcode(ma->texact); - - if(event==0 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_COL_R, 0); - insertkey(id, ID_MA, NULL, NULL, MA_COL_G, 0); - insertkey(id, ID_MA, NULL, NULL, MA_COL_B, 0); - } - if(event==1 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_ALPHA, 0); - } - if(event==2 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_HASIZE, 0); - } - if(event==3 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); - } - if(event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B, 0); - insertkey(id, ID_MA, NULL, NULL, MA_REF, 0); - insertkey(id, ID_MA, NULL, NULL, MA_EMIT, 0); - insertkey(id, ID_MA, NULL, NULL, MA_AMB, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC, 0); - insertkey(id, ID_MA, NULL, NULL, MA_HARD, 0); - insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); - insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU, 0); - insertkey(id, ID_MA, NULL, NULL, MA_ADD, 0); - } - if(event==14) { - insertkey(id, ID_MA, NULL, NULL, MA_RAYM, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI, 0); - } - if(event==12 || event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13 || event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z, 0); - } - if(event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_R, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_G, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_B, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP, 0); - } - } - } - else if(tab==TAB_SHADING_WORLD) { - id= G.buts->lockpoin; - wo= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13"); - if(event== -1) return; - - map= texchannel_to_adrcode(wo->texact); - - if(event==0) { - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B, 0); - } - if(event==1) { - insertkey(id, ID_WO, NULL, NULL, WO_HOR_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_HOR_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_HOR_B, 0); - } - if(event==2) { - insertkey(id, ID_WO, NULL, NULL, WO_MISI, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTDI, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTHI, 0); - } - if(event==3) { - insertkey(id, ID_WO, NULL, NULL, WO_STAR_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STAR_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STAR_B, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STARDIST, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE, 0); - } - if(event==12) { - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13) { - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z, 0); - } - } - } - else if(tab==TAB_SHADING_LAMP) { - id= G.buts->lockpoin; - la= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13"); - if(event== -1) return; - - map= texchannel_to_adrcode(la->texact); - - if(event==0) { - insertkey(id, ID_LA, NULL, NULL, LA_COL_R, 0); - insertkey(id, ID_LA, NULL, NULL, LA_COL_G, 0); - insertkey(id, ID_LA, NULL, NULL, LA_COL_B, 0); - } - if(event==1) { - insertkey(id, ID_LA, NULL, NULL, LA_ENERGY, 0); - } - if(event==2) { - insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI, 0); - } - if(event==12) { - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13) { - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z, 0); - } - - } - } - else if(tab==TAB_SHADING_TEX) { - id= G.buts->lockpoin; - te= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Clouds%x0|Marble%x1|Stucci%x2|Wood%x3|Magic%x4|Blend%x5|Musgrave%x6|Voronoi%x7|DistortedNoise%x8|ColorFilter%x9"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - } - if(event==1) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); - } - if(event==2) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - } - if(event==3) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); - } - if(event==4) { - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - } - if(event==5) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - } - if(event==6) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MGH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_LAC, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); - } - if(event==7) { - insertkey(id, ID_TE, NULL, NULL, TE_VNW1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW2, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW3, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW4, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNMEXP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VN_DISTM, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VN_COLT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_ISCA, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - } - if(event==8) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); - insertkey(id, ID_TE, NULL, NULL, TE_DISTA, 0); - } - if(event==9) { - insertkey(id, ID_TE, NULL, NULL, TE_COL_R, 0); - insertkey(id, ID_TE, NULL, NULL, TE_COL_G, 0); - insertkey(id, ID_TE, NULL, NULL, TE_COL_B, 0); - insertkey(id, ID_TE, NULL, NULL, TE_BRIGHT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_CONTRA, 0); - } - } - } - } - else if(G.buts->mainb==CONTEXT_OBJECT) { - ob= OBACT; - if(ob) { - id= (ID *) (ob); - if(id) { - if(ob->type==OB_MESH) - event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4"); - else - event= pupmenu("Insert Key %t|Force Strength%x3|Force Falloff%x4"); - if(event == -1) return; - - if(event==0) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_SDAMP, 0); - } - if(event==1) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_RDAMP, 0); - } - if(event==2) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_PERM, 0); - } - if(event==3) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FSTR, 0); - } - if(event==4) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL, 0); - } - if(event==5) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FMAXD, 0); - } - } - } - } - else if(G.buts->mainb==CONTEXT_EDITING) { - ob= OBACT; - if(ob && ob->type==OB_CAMERA) { - id= G.buts->lockpoin; - if(id) { - /* yafray: insert key extended with aperture and focal distance */ - /* qdn: FocalDistance now enabled for Blender as wel, for use with defocus node */ - if (G.scene->r.renderer==R_INTERN) - event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|FocalDistance%x3|Viewplane Shift%x4"); - else - event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|Aperture%x2|FocalDistance%x3"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_CA, NULL, NULL, CAM_LENS, 0); - } - else if(event==1) { - insertkey(id, ID_CA, NULL, NULL, CAM_STA, 0); - insertkey(id, ID_CA, NULL, NULL, CAM_END, 0); - } - else if(event==2) { - insertkey(id, ID_CA, NULL, NULL, CAM_YF_APERT, 0); - } - else if(event==3) { - insertkey(id, ID_CA, NULL, NULL, CAM_YF_FDIST, 0); - } - else if(event==4) { - insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_X, 0); - insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_Y, 0); - } - } - } - } - else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) { - if(G.ssound) { - id= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_SO, NULL, NULL, SND_VOLUME, 0); - } - if(event==1) { - insertkey(id, ID_SO, NULL, NULL, SND_PITCH, 0); - } - if(event==2) { - insertkey(id, ID_SO, NULL, NULL, SND_PANNING, 0); - } - if(event==3) { - insertkey(id, ID_SO, NULL, NULL, SND_ATTEN, 0); - } - } - } - } - - BIF_undo_push("Insert Key Buttons"); - - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - allspace(REMAKEIPO, 0); - - } - else if(curarea->spacetype==SPACE_VIEW3D) { - ob= OBACT; - - if (ob && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - - set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) - if (pchan->flag & POSE_KEY) - break; - if(pchan==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); - } - else { - base= FIRSTBASE; - while(base) { - if (TESTBASELIB(base)) break; - base= base->next; - } - if(base==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Layer%x5|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); - } - - if(ob) { - if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7"); - else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7"); - else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7"); - else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7"); - } - - event= pupmenu(menustr); - if(event== -1) return; - - if(event==7) { // ob != NULL - insert_shapekey(ob); - return; - } - - if (ob && (ob->flag & OB_POSEMODE)){ - bPoseChannel *pchan; - short recalc_bonepaths= 0; - - if (ob->action && ob->action->id.lib) { - error ("Can't key libactions"); - return; - } - - id= &ob->id; - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { - if (pchan->flag & POSE_KEY) { - /* insert relevant keyframes */ - if(event==0 || event==3 ||event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - if(event==1 || event==3 || event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - } - if(event==2 || event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); - } - if (event==9 && ob->action) { - bActionChannel *achan; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - insertkey(id, ID_PO, achan->name, NULL, icu->adrcode, 0); - } - break; - } - } - } - if(event==11 || event==13) { - int matok=0; - /* check one to make sure we're not trying to set visual loc keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - } - if(event==12 || event==13) { - int matok=0; - /* check one to make sure we're not trying to set visual rot keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - } - } - if (event==15 && ob->action) { - bActionChannel *achan; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - insertkey_smarter(id, ID_PO, achan->name, NULL, icu->adrcode); - } - break; - } - } - } - - /* clear unkeyed flag (it doesn't matter if it's set or not) */ - if (pchan->bone) - pchan->bone->flag &= ~BONE_UNKEYED; - - /* check if bone has a path */ - if (pchan->path) - recalc_bonepaths = 1; - } - } - - /* recalculate ipo handles, etc. */ - if(ob->action) - remake_action_ipos(ob->action); - - /* recalculate bone-paths on adding new keyframe? */ - // TODO: currently, there is no setting to turn this on/off globally - if (recalc_bonepaths) - pose_recalculate_paths(ob); - - - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } - else { - base= FIRSTBASE; - while(base) { - if (TESTBASELIB(base)) { - char *actname= NULL; - - id= (ID *)(base->object); - - if(base->object->ipoflag & OB_ACTION_OB) - actname= "Object"; - - /* all curves in ipo deselect */ - if(base->object->ipo || base->object->action) { - if (base->object->ipo) { - icu= base->object->ipo->curve.first; - } - else { - bActionChannel *achan; - achan= get_action_channel(base->object->action, actname); - - if (achan && achan->ipo) - icu= achan->ipo->curve.first; - else - icu= NULL; - } - - while(icu) { - icu->flag &= ~IPO_SELECT; - - switch (event) { - case 9: - insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); - break; - case 15: - insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); - break; - } - icu= icu->next; - } - } - - if(event==0 || event==3 ||event==4) { - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); - } - if(event==1 || event==3 ||event==4) { - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); - } - if(event==2 || event==4) { - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); - } - if(event==5) { - /* remove localview */ - tlay= base->object->lay; - base->object->lay &= 0xFFFFFF; - insertkey(id, ID_OB, actname, NULL, OB_LAY, 0); - base->object->lay= tlay; - } - if(event==11 || event==13) { - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_X); - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Y); - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Z); - } - if(event==12 || event==13) { - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_X); - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Y); - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Z); - } - base->object->recalc |= OB_RECALC_OB; - } - base= base->next; - } - } - - if(event==0) BIF_undo_push("Insert Loc Key"); - else if(event==1) BIF_undo_push("Insert Rot Key"); - else if(event==2) BIF_undo_push("Insert Scale Key"); - else if(event==3) BIF_undo_push("Insert LocRot Key"); - else if(event==4) BIF_undo_push("Insert LocRotScale Key"); - else if(event==5) BIF_undo_push("Insert Layer Key"); - else if(event==7) BIF_undo_push("Insert Vertex Key"); - else if(event==9) BIF_undo_push("Insert Avail Key"); - else if(event==11) BIF_undo_push("Insert VisualLoc Key"); - else if(event==12) BIF_undo_push("Insert VisualRot Key"); - else if(event==13) BIF_undo_push("Insert VisualLocRot Key"); - else if(event==15) BIF_undo_push("Insert Needed Key"); - - DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); - - allspace(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } - -} - /* ****************************************************************************** */ void add_duplicate_editipo(void) @@ -3651,6 +2375,7 @@ void remove_doubles_ipo(void) } deselectall_editipo(); + BIF_undo_push("Remove Doubles (IPO)"); } @@ -4473,7 +3198,7 @@ void paste_editipo(void) int i; /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu == NULL) return; /* Copy selected beztriples from source icu onto this edit-icu, @@ -4514,7 +3239,7 @@ void paste_editipo(void) else { /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu==NULL) return; /* clear exisiting dynamic memory (keyframes, driver) */ @@ -5629,7 +4354,7 @@ void ipo_record(void) /* make curves ready, start values */ if(ei1->icu==NULL) - ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode); + ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode, 1); if(ei1->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei1->icu, &type); @@ -5639,7 +4364,7 @@ void ipo_record(void) if(ei2) { if(ei2->icu==NULL) - ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode); + ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode, 1); if(ei2->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei2->icu, &type); diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c index e1e286e10cf..7bfd097b87f 100644 --- a/source/blender/src/editipo_lib.c +++ b/source/blender/src/editipo_lib.c @@ -392,7 +392,15 @@ int texchannel_to_adrcode(int channel) case 6: return MA_MAP7; case 7: return MA_MAP8; case 8: return MA_MAP9; - case 9: return MA_MAP10; + case 9: return MA_MAP10; + case 10: return MA_MAP11; + case 11: return MA_MAP12; + case 12: return MA_MAP13; + case 13: return MA_MAP14; + case 14: return MA_MAP15; + case 15: return MA_MAP16; + case 16: return MA_MAP17; + case 17: return MA_MAP18; default: return 0; } } diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index f03de1ff383..24bb111c8d1 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -237,7 +237,6 @@ void deselectall_editipo(void) } } - BIF_undo_push("(De)select all Ipo"); scrarea_queue_winredraw(curarea); } diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index ce798064632..dbabf9d19fb 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -70,6 +70,7 @@ #include "BIF_editkey.h" #include "BIF_editview.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -170,9 +171,9 @@ static void rvk_slider_func(void *voidob, void *voidkeynum) /* ipo on action or ob? */ if(ob->ipoflag & OB_ACTION_KEY) - icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum); + icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum, 1); else - icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum); + icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum, 1); if (icu) { /* if the ipocurve exists, try to get a bezier diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c index 0782e012f68..06b092a30ac 100644 --- a/source/blender/src/editlattice.c +++ b/source/blender/src/editlattice.c @@ -131,7 +131,7 @@ void make_editLatt(void) copy_dverts(editLatt->dvert, lt->dvert, tot); } - BIF_undo_push("original"); + BIF_undo_push("Original"); } diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 188f7476728..b75f7e07143 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -1683,6 +1683,10 @@ void separate_mesh(void) efa= em->faces.first; while(efa) { vl1= efa->next; + if (efa == G.editMesh->act_face && (efa->f & SELECT)) { + EM_set_actFace(NULL); + } + if((efa->f & SELECT)==0) { BLI_remlink(&em->faces, efa); BLI_addtail(&edvl, efa); diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index 9516f39b05c..71e04541643 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -869,6 +869,152 @@ int confirm_objectExists( Mesh **me, float mat[][3] ) return newob; } +// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker +// this hack is only used so that scons+mingw + split-sources hack works + // ------------------------------- start copied code +/* these are not the monkeys you are looking for */ +int monkeyo= 4; +int monkeynv= 271; +int monkeynf= 250; +signed char monkeyv[271][3]= { +{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92}, +{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83}, +{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102}, +{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92}, +{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74}, +{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99}, +{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105}, +{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100}, +{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100}, +{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73}, +{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45}, +{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68}, +{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68}, +{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80}, +{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96}, +{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90}, +{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85}, +{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94}, +{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96}, +{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95}, +{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84}, +{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109}, +{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88}, +{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82}, +{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96}, +{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96}, +{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100}, +{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104}, +{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71}, +{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88}, +{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84}, +{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81}, +{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99}, +{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87}, +{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100}, +{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97}, +{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86}, +{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96}, +{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79}, +{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59}, +{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37}, +{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59}, +{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7}, +{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9}, +{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52}, +{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51}, +{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55}, +{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34}, +{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30}, +{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7}, +{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57}, +{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26}, +{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16}, +{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54}, +{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52}, +{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28}, +{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57}, +{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27}, +{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35}, +{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24}, +{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41}, +{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41}, +{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62}, +{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42}, +{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48}, +{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62}, +{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63}, +{-26,-16,-42},{-17,49,-49}, +}; + +signed char monkeyf[250][4]= { +{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, +{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, +{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, +{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, +{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, +{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, +{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, +{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, +{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, +{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, +{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, +{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, +{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, +{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, +{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, +{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, +{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, +{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, +{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, +{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, +{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, +{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, +{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, +{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, +{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, +{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, +{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, +{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, +{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, +{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, +{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, +{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, +{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, +{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, +{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, +{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, +{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, +{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, +{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, +{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, +{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, +{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, +{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, +{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, +{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, +{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, +{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, +{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, +{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, +{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, +{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, +{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, +{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, +{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, +{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, +{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, +{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, +{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, +{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, +{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, +{-68,-67,24,-33}, +}; + // ------------------------------- end copied code + + void make_prim(int type, float imat[3][3], int tot, int seg, int subdiv, float dia, float d, int ext, int fill, float cent[3]) @@ -1022,9 +1168,9 @@ void make_prim(int type, float imat[3][3], int tot, int seg, break; case 13: /* Monkey */ { - extern int monkeyo, monkeynv, monkeynf; - extern signed char monkeyf[][4]; - extern signed char monkeyv[][3]; + //extern int monkeyo, monkeynv, monkeynf; + //extern signed char monkeyf[][4]; + //extern signed char monkeyv[][3]; EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); EditFace *efa; int i; diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c index 4ac5072b212..2c5386b86b6 100644 --- a/source/blender/src/editmesh_loop.c +++ b/source/blender/src/editmesh_loop.c @@ -745,9 +745,9 @@ void KnifeSubdivide(char mode) eed= eed->next; } - if (mode==KNIFE_EXACT) esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); + if(mode==KNIFE_EXACT) esubdivideflag(SELECT, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MIDPOINT) esubdivideflag(SELECT, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MULTICUT) esubdivideflag(SELECT, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); eed=em->edges.first; while(eed){ diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index c162c904776..81d0ffeeb3b 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -4202,7 +4202,7 @@ void editmesh_align_view_to_selected(View3D *v3d, int axis) void vertexsmooth(void) { EditMesh *em = G.editMesh; - EditVert *eve; + EditVert *eve, *eve_mir = NULL; EditEdge *eed; float *adror, *adr, fac; float fvec[3]; @@ -4285,13 +4285,19 @@ void vertexsmooth(void) while(eve) { if(eve->f & SELECT) { if(eve->f1) { + + if (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) { + eve_mir= editmesh_get_x_mirror_vert(G.obedit, eve->co); + } + adr = eve->tmp.p; fac= 0.5/(float)eve->f1; eve->co[0]= 0.5*eve->co[0]+fac*adr[0]; eve->co[1]= 0.5*eve->co[1]+fac*adr[1]; eve->co[2]= 0.5*eve->co[2]+fac*adr[2]; - + + /* clip if needed by mirror modifier */ if (eve->f2) { if (eve->f2 & 1) { @@ -4304,6 +4310,13 @@ void vertexsmooth(void) eve->co[2]= 0.0f; } } + + if (eve_mir) { + eve_mir->co[0]=-eve->co[0]; + eve_mir->co[1]= eve->co[1]; + eve_mir->co[2]= eve->co[2]; + } + } eve->tmp.p= NULL; } diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 3615a4ad851..4cf3b410393 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -2698,16 +2698,21 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype) free_tagged_edges_faces(em->edges.first, em->faces.first); if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) { + /* bugfix: vertex could get flagged as "not-selected" + // solution: clear flags before, not at the same time as setting SELECT flag -dg + */ for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { - eed->f |= flag; - EM_select_edge(eed,1); - - }else{ + if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) { eed->f &= !flag; EM_select_edge(eed,0); } - } + } + for(eed = em->edges.first;eed;eed = eed->next) { + if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { + eed->f |= flag; + EM_select_edge(eed,1); + } + } } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) { for(eed = em->edges.first;eed;eed = eed->next) { if(eed->f2 & EDGEINNER) { @@ -4648,6 +4653,12 @@ void bevel_menu_old() } /* *********** END BEVEL *********/ +typedef struct SlideUv { + float origuv[2]; + float *uv_up, *uv_down; + //float *fuv[4]; + LinkNode *fuv_list; +} SlideUv; typedef struct SlideVert { EditEdge *up,*down; @@ -4655,9 +4666,19 @@ typedef struct SlideVert { } SlideVert; int EdgeLoopDelete(void) { + + /* temporal flag setting so we keep UVs when deleting edge loops, + * this is a bit of a hack but it works how you would want in almost all cases */ + short uvcalc_flag_orig = G.scene->toolsettings->uvcalc_flag; + G.scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; + if(!EdgeSlide(1, 1)) { return 0; } + + /* restore uvcalc flag */ + G.scene->toolsettings->uvcalc_flag = uvcalc_flag_orig; + EM_select_more(); removedoublesflag(1,0, 0.001); EM_select_flush(); @@ -4667,22 +4688,35 @@ int EdgeLoopDelete(void) { int EdgeSlide(short immediate, float imperc) { + NumInput num; EditMesh *em = G.editMesh; EditFace *efa; EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; EditVert *ev, *nearest; LinkNode *edgelist = NULL, *vertlist=NULL, *look; GHash *vertgh; + SlideVert *tempsv; float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4]; float shiftlabda= 0.0f,len = 0.0f; int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; int wasshift = 0; + + /* UV correction vars */ + GHash **uvarray= NULL; + int uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE); + int uvlay_idx; + SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; + float uv_tmp[2]; + LinkNode *fuv_link; + short event, draw=1; short mval[2], mvalo[2]; char str[128]; float labda = 0.0f; + initNumInput(&num); + view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat); mvalo[0] = -1; mvalo[1] = -1; @@ -4982,6 +5016,99 @@ int EdgeSlide(short immediate, float imperc) look = look->next; } + + + if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + int maxnum = 0; + uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); + suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */ + suv = NULL; + + for (uvlay_idx=0; uvlay_idxverts.first;ev;ev=ev->next) { + ev->tmp.l = 0; + } + look = vertlist; + while(look) { + float *uv_new; + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + + ev = look->link; + suv = NULL; + for(efa = em->faces.first;efa;efa=efa->next) { + if (ev->tmp.l != -1) { /* test for self, in this case its invalid */ + int k=-1; /* face corner */ + + /* Is this vert in the faces corner? */ + if (efa->v1==ev) k=0; + else if (efa->v2==ev) k=1; + else if (efa->v3==ev) k=2; + else if (efa->v4 && efa->v4==ev) k=3; + + if (k != -1) { + MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx); + EditVert *ev_up, *ev_down; + + uv_new = tf->uv[k]; + + if (ev->tmp.l) { + if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) { + ev->tmp.l = -1; /* Tag as invalid */ + BLI_linklist_free(suv->fuv_list,NULL); + suv->fuv_list = NULL; + BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL); + suv = NULL; + break; + } + } else { + ev->tmp.l = 1; + suv = suv_last; + + suv->fuv_list = NULL; + suv->uv_up = suv->uv_down = NULL; + suv->origuv[0] = uv_new[0]; + suv->origuv[1] = uv_new[1]; + + BLI_linklist_prepend(&suv->fuv_list, uv_new); + BLI_ghash_insert(uvarray[uvlay_idx],ev,suv); + + suv_last++; /* advance to next slide UV */ + maxnum++; + } + + /* Now get the uvs along the up or down edge if we can */ + if (suv) { + if (!suv->uv_up) { + ev_up = editedge_getOtherVert(tempsv->up,ev); + if (efa->v1==ev_up) suv->uv_up = tf->uv[0]; + else if (efa->v2==ev_up) suv->uv_up = tf->uv[1]; + else if (efa->v3==ev_up) suv->uv_up = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3]; + } + if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */ + ev_down = editedge_getOtherVert(tempsv->down,ev); + if (efa->v1==ev_down) suv->uv_down = tf->uv[0]; + else if (efa->v2==ev_down) suv->uv_down = tf->uv[1]; + else if (efa->v3==ev_down) suv->uv_down = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3]; + } + + /* Copy the pointers to the face UV's */ + BLI_linklist_prepend(&suv->fuv_list, uv_new); + } + } + } + } + look = look->next; + } + } /* end uv layer loop */ + } /* end uvlay_tot */ + + + // we should have enough info now to slide len = 0.0f; @@ -4994,88 +5121,22 @@ int EdgeSlide(short immediate, float imperc) float v2[2], v3[2]; EditVert *centerVert, *upVert, *downVert; - - getmouseco_areawin(mval); if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) { PIL_sleep_ms(10); } else { + char *p = str;; mvalo[0] = mval[0]; mvalo[1] = mval[1]; - //Adjust Edgeloop - if(immediate) { - perc = imperc; - } - percp = perc; - if(prop) { - look = vertlist; - while(look) { - EditVert *tempev; - ev = look->link; - tempsv = BLI_ghash_lookup(vertgh,ev); - - tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); - VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); - - look = look->next; - } - } - else { - //Non prop code - look = vertlist; - while(look) { - float newlen; - ev = look->link; - tempsv = BLI_ghash_lookup(vertgh,ev); - newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); - if(newlen > 1.0) {newlen = 1.0;} - if(newlen < 0.0) {newlen = 0.0;} - if(flip == 0) { - VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); - } else{ - VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); - } - look = look->next; - } - } - tempsv = BLI_ghash_lookup(vertgh,nearest); centerVert = editedge_getSharedVert(tempsv->up, tempsv->down); upVert = editedge_getOtherVert(tempsv->up, centerVert); downVert = editedge_getOtherVert(tempsv->down, centerVert); - // Highlight the Control Edges - - scrarea_do_windraw(curarea); - persp(PERSP_VIEW); - glPushMatrix(); - mymultmatrix(G.obedit->obmat); - - glColor3ub(0, 255, 0); - glBegin(GL_LINES); - glVertex3fv(upVert->co); - glVertex3fv(downVert->co); - glEnd(); - - if(prop == 0) { - // draw start edge for non-prop - glPointSize(5); - glBegin(GL_POINTS); - glColor3ub(255,0,255); - if(flip) { - glVertex3fv(upVert->co); - } else { - glVertex3fv(downVert->co); - } - glEnd(); - } - - - glPopMatrix(); view3d_project_float(curarea, upVert->co, v2, projectMat); view3d_project_float(curarea, downVert->co, v3, projectMat); @@ -5114,18 +5175,169 @@ int EdgeSlide(short immediate, float imperc) perc = floor(perc); perc /= 10; } - if(prop) { - sprintf(str, "(P)ercentage: %f", perc); - } else { + + if(prop == 0) { len = VecLenf(upVert->co,downVert->co)*((perc+1)/2); if(flip == 1) { len = VecLenf(upVert->co,downVert->co) - len; } - sprintf(str, "Non (P)rop Length: %f, Press (F) to flip control side", len); + } + + if (hasNumInput(&num)) + { + applyNumInput(&num, &perc); + + if (prop) + { + perc = MIN2(perc, 1); + perc = MAX2(perc, -1); + } + else + { + len = MIN2(perc, VecLenf(upVert->co,downVert->co)); + len = MAX2(len, 0); + } } + //Adjust Edgeloop + if(immediate) { + perc = imperc; + } + percp = perc; + if(prop) { + look = vertlist; + while(look) { + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); + VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); + + if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + + look = look->next; + } + } + else { + //Non prop code + look = vertlist; + while(look) { + float newlen; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); + if(newlen > 1.0) {newlen = 1.0;} + if(newlen < 0.0) {newlen = 0.0;} + if(flip == 0) { + VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); + if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } else{ + VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); + + if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } + look = look->next; + } + + } + + // Highlight the Control Edges + scrarea_do_windraw(curarea); + persp(PERSP_VIEW); + glPushMatrix(); + mymultmatrix(G.obedit->obmat); + + glColor3ub(0, 255, 0); + glBegin(GL_LINES); + glVertex3fv(upVert->co); + glVertex3fv(downVert->co); + glEnd(); + + if(prop == 0) { + // draw start edge for non-prop + glPointSize(5); + glBegin(GL_POINTS); + glColor3ub(255,0,255); + if(flip) { + glVertex3fv(upVert->co); + } else { + glVertex3fv(downVert->co); + } + glEnd(); + } + glPopMatrix(); + + if(prop) { + p += sprintf(str, "(P)ercentage: "); + } else { + p += sprintf(str, "Non (P)rop Length: "); + } + + if (hasNumInput(&num)) + { + char num_str[20]; + + outputNumInput(&num, num_str); + p += sprintf(p, "%s", num_str); + } + else + { + if (prop) + { + p += sprintf(p, "%f", perc); + } + else + { + p += sprintf(p, "%f", len); + } + } + + + if (prop == 0) { + p += sprintf(p, ", Press (F) to flip control side"); + } + headerprint(str); screen_swapbuffers(); } @@ -5148,7 +5360,14 @@ int EdgeSlide(short immediate, float imperc) perc = 0; immediate = 1; } else if(event==PKEY) { - (prop == 1) ? (prop = 0):(prop = 1); + initNumInput(&num); /* reset num input */ + if (prop) { + prop = 0; + num.flag |= NUM_NO_NEGATIVE; + } + else { + prop = 1; + } mvalo[0] = -1; } else if(event==FKEY) { (flip == 1) ? (flip = 0):(flip = 1); @@ -5186,7 +5405,13 @@ int EdgeSlide(short immediate, float imperc) look = look->next; } } + + if (handleNumInput(&num, event)) + { + mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */ + } } + } } else { draw = 0; @@ -5218,6 +5443,24 @@ int EdgeSlide(short immediate, float imperc) BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); BLI_linklist_free(vertlist,NULL); BLI_linklist_free(edgelist,NULL); + + if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + for (uvlay_idx=0; uvlay_idx= slideuvs) { + if (suv->fuv_list) { + BLI_linklist_free(suv->fuv_list,NULL); + } + suv--; + } + + allqueue(REDRAWIMAGE, 0); + } if(cancel == 1) { return -1; diff --git a/source/blender/src/editmode_undo.c b/source/blender/src/editmode_undo.c index d0a44360ad5..7893dac2408 100644 --- a/source/blender/src/editmode_undo.c +++ b/source/blender/src/editmode_undo.c @@ -107,6 +107,7 @@ typedef struct UndoElem { Object *ob; // pointer to edited object int type; // type of edited object void *undodata; + uintptr_t undosize; char name[MAXUNDONAME]; void (*freedata)(void *); void (*to_editmode)(void *); @@ -138,6 +139,7 @@ void undo_editmode_push(char *name, void (*freedata)(void *), { UndoElem *uel; int nr; + uintptr_t memused, totmem, maxmem; /* at first here was code to prevent an "original" key to be insterted twice this was giving conflicts for example when mesh changed due to keys or apply */ @@ -145,9 +147,8 @@ void undo_editmode_push(char *name, void (*freedata)(void *), /* remove all undos after (also when curundo==NULL) */ while(undobase.last != curundo) { uel= undobase.last; - BLI_remlink(&undobase, uel); uel->freedata(uel->undodata); - MEM_freeN(uel); + BLI_freelinkN(&undobase, uel); } /* make new */ @@ -160,7 +161,7 @@ void undo_editmode_push(char *name, void (*freedata)(void *), uel->from_editmode= from_editmode; uel->validate_undo= validate_undo; - /* and limit amount to the maximum */ + /* limit amount to the maximum amount*/ nr= 0; uel= undobase.last; while(uel) { @@ -171,19 +172,43 @@ void undo_editmode_push(char *name, void (*freedata)(void *), if(uel) { while(undobase.first!=uel) { UndoElem *first= undobase.first; - BLI_remlink(&undobase, first); first->freedata(first->undodata); - MEM_freeN(first); + BLI_freelinkN(&undobase, first); } } /* copy */ + memused= MEM_get_memory_in_use(); curundo->undodata= curundo->from_editmode(); + curundo->undosize= MEM_get_memory_in_use() - memused; curundo->ob= G.obedit; curundo->id= G.obedit->id; curundo->type= G.obedit->type; -} + if(U.undomemory != 0) { + /* limit to maximum memory (afterwards, we can't know in advance) */ + totmem= 0; + maxmem= ((uintptr_t)U.undomemory)*1024*1024; + + uel= undobase.last; + while(uel && uel->prev) { + totmem+= uel->undosize; + if(totmem>maxmem) break; + uel= uel->prev; + } + + if(uel) { + if(uel->prev && uel->prev->prev) + uel= uel->prev; + + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + first->freedata(first->undodata); + BLI_freelinkN(&undobase, first); + } + } + } +} /* helper to remove clean other objects from undo stack */ static void undo_clean_stack(void) @@ -205,9 +230,8 @@ static void undo_clean_stack(void) } else { mixed= 1; - BLI_remlink(&undobase, uel); uel->freedata(uel->undodata); - MEM_freeN(uel); + BLI_freelinkN(&undobase, uel); } uel= next; diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 98f4f1bb46f..d3ba153e600 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -2001,7 +2001,10 @@ void node_hide(SpaceNode *snode) void node_insert_key(SpaceNode *snode) { bNode *node= editnode_get_active(snode->edittree); - + + if(node == NULL) + return; + if(node->type==CMP_NODE_TIME) { if(node->custom1custom2) { @@ -2110,6 +2113,7 @@ static void node_border_link_delete(SpaceNode *snode) mval[1]= rect.ymax; areamouseco_to_ipoco(&snode->v2d, mval, &rectf.xmax, &rectf.ymax); + glLoadIdentity(); myortho2(rectf.xmin, rectf.xmax, rectf.ymin, rectf.ymax); glSelectBuffer(256, buffer); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index fee967bcd9a..2459f7ed23c 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -172,6 +172,7 @@ #include "BDR_drawobject.h" #include "BDR_editcurve.h" #include "BDR_unwrapper.h" +#include "BDR_gpencil.h" #include #include "mydevice.h" @@ -2827,7 +2828,7 @@ void convertmenu(void) if(G.scene->id.lib) return; obact= OBACT; - if(obact==0) return; + if (obact == NULL) return; if(!obact->flag & SELECT) return; if(G.obedit) return; @@ -3022,6 +3023,10 @@ void convertmenu(void) basedel = NULL; } + /* delete object should renew depsgraph */ + if(nr==2) + DAG_scene_sort(G.scene); + /* texspace and normals */ if(!basen) BASACT= base; @@ -3278,6 +3283,9 @@ static void copymenu_logicbricks(Object *ob) base->object->scavisflag= ob->scavisflag; base->object->scaflag= ob->scaflag; + /* set the initial state */ + base->object->state= ob->state; + base->object->init_state= ob->init_state; } } base= base->next; @@ -3514,6 +3522,7 @@ void copy_attr(short event) if (ob->gameflag & OB_BOUNDS) { base->object->boundtype = ob->boundtype; } + base->object->margin= ob->margin; } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); @@ -4130,15 +4139,27 @@ void apply_object( void ) } allqueue(REDRAWVIEW3D, 0); - } else { + } + else { + ob= OBACT; + if(ob==0) return; - evt = pupmenu("Apply Object%t|Scale and Rotation to ObData|Visual Transform to Objects Loc/Scale/Rot"); + if ((ob->pose) && (ob->flag & OB_POSEMODE)) + evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3"); + else + evt = pupmenu("Apply Object%t|Scale and Rotation to ObData%x1|Visual Transform to Objects Loc/Scale/Rot%x2"); if (evt==-1) return; - if (evt==1) { - apply_objects_locrot(); - } else if (evt==2) { - apply_objects_visual_tx(); + switch (evt) { + case 1: + apply_objects_locrot(); + break; + case 2: + apply_objects_visual_tx(); + break; + case 3: + apply_armature_pose2bones(); + break; } } } diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 1cd8733a7ea..976e58ed102 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -1023,8 +1023,11 @@ int blender_test_break(void) return (G.afbreek==1); } -void reset_autosave(void) { - window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); +void reset_autosave(void) +{ + if(U.flag & USER_AUTOSAVE) { + window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); + } } /* ************ handlers ************** */ diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c index 05eb094a7c2..2d70525f971 100644 --- a/source/blender/src/editsound.c +++ b/source/blender/src/editsound.c @@ -275,6 +275,12 @@ void sound_initialize_sounds(void) bSound *sound; if(ghSoundScene) { + for(sound=G.main->sound.first; sound; sound=sound->id.next) { + if(sound->snd_sound) { + SND_RemoveSound(ghSoundScene, sound->snd_sound); + sound->snd_sound = NULL; + } + } /* clear the soundscene */ SND_RemoveAllSounds(ghSoundScene); @@ -908,7 +914,16 @@ void sound_stop_all_sounds(void) void sound_end_all_sounds(void) { #if GAMEBLENDER == 1 + bSound *sound; + if(ghSoundScene) { + for(sound=G.main->sound.first; sound; sound=sound->id.next) { + if(sound->snd_sound) { + SND_RemoveSound(ghSoundScene, sound->snd_sound); + sound->snd_sound = NULL; + } + } + sound_stop_all_sounds(); SND_RemoveAllSounds(ghSoundScene); } diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index a3fcad7885c..f95b56fe5b0 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -89,6 +89,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_previewrender.h" /* use only so fly mode can preview when its done */ #include "BIF_space.h" @@ -1631,7 +1632,7 @@ void mouse_select(void) /* ------------------------------------------------------------------------- */ -static int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2) +int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2) { int radsq= rad*rad; float v1[2], v2[2], v3[2]; @@ -2247,7 +2248,7 @@ void view3d_border_zoom(void) /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); - draw_depth(curarea, (void *)v3d); + draw_depth(curarea, (void *)v3d, NULL); /* force updating */ if (v3d->depths) { diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 2ba5745b19b..cdb001d9193 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -2062,18 +2062,20 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case XKEY: - test = get_hilited_entry(sfile); + if(sfile->type==FILE_BLENDER) { + test = get_hilited_entry(sfile); - if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ - BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); + if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ + BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); - if( okee("Remove %s", str) ) { - ret = BLI_delete(str, 0, 0); - if (ret) { - error("Command failed, see console"); - } else { - freefilelist(sfile); - do_draw= 1; + if( okee("Remove %s", str) ) { + ret = BLI_delete(str, 0, 0); + if (ret) { + error("Command failed, see console"); + } else { + freefilelist(sfile); + do_draw= 1; + } } } } diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c index c4a7b32bf8c..69e3d4c7aac 100644 --- a/source/blender/src/glutil.c +++ b/source/blender/src/glutil.c @@ -290,17 +290,66 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } +#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) { - unsigned char *uc_rect= (unsigned char*) rect; - float *f_rect= (float *)rect; - float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y); - int ltexid= glaGetOneInteger(GL_TEXTURE_2D); - int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); - int subpart_x, subpart_y, tex_w, tex_h; - int texid= get_cached_work_texture(&tex_w, &tex_h); - int nsubparts_x= (img_w+(tex_w-1))/tex_w; - int nsubparts_y= (img_h+(tex_h-1))/tex_h; + float *f_rect; + float xzoom, yzoom; + unsigned char *uc_rect; + int ltexid, lrowlength, texid, tex_w, tex_h; + int subpart_x, subpart_y, nsubparts_x, nsubparts_y; + + uc_rect= (unsigned char*) rect; + f_rect= (float *)rect; + +#ifdef __APPLE__ + /* On Nvidia, Mac OS X 10.5 this function doesn't work correct and + * can crash even, use glDrawPixels instead of textures then */ + if(is_a_really_crappy_nvidia_card()) { + float col[4], modcol[4]; + unsigned char *srect = rect; + int a; + + /* modulate with current color */ + glGetFloatv(GL_CURRENT_COLOR, col); + if(col[0]!=1.0f || col[1]!=1.0f ||col[2]!=1.0f ||col[3]!=1.0f) { + srect = MEM_callocN(4*img_w*img_h, "glDrawPixelsTexSafe"); + for(a=0; a=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf) { float *rf; @@ -717,6 +765,17 @@ int is_a_really_crappy_intel_card(void) return well_is_it; } +int is_a_really_crappy_nvidia_card(void) +{ + static int well_is_it= -1; + + /* Do you understand the implication? Do you? */ + if (well_is_it==-1) + well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); + + return well_is_it; +} + void bglFlush(void) { glFlush(); diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index 9b250fc3ec0..c7540bc4a1f 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -46,7 +46,10 @@ #include "BLI_blenlib.h" #include "DNA_listBase.h" +#include "DNA_armature_types.h" +#include "DNA_curve_types.h" #include "DNA_gpencil_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -57,10 +60,15 @@ #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_blender.h" +#include "BKE_armature.h" +#include "BKE_curve.h" +#include "BKE_image.h" #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" +#include "BIF_drawseq.h" +#include "BIF_editarmature.h" #include "BIF_editview.h" #include "BIF_graphics.h" #include "BIF_interface.h" @@ -74,6 +82,8 @@ #include "BDR_gpencil.h" #include "BIF_drawgpencil.h" +#include "BDR_editobject.h" + #include "BSE_drawipo.h" #include "BSE_headerbuttons.h" #include "BSE_view.h" @@ -214,8 +224,8 @@ bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) BLI_addtail(&gpd->layers, gpl); /* set basic settings */ - gpl->color[3]= 1.0f; - gpl->thickness = 1; + gpl->color[3]= 0.9f; + gpl->thickness = 3; /* auto-name */ sprintf(gpl->info, "GP_Layer"); @@ -237,8 +247,7 @@ bGPdata *gpencil_data_addnew (void) gpd= MEM_callocN(sizeof(bGPdata), "GreasePencilData"); /* initial settings */ - /* it is quite useful to be able to see this info, so on by default */ - gpd->flag = GP_DATA_DISPINFO; + gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); return gpd; } @@ -678,6 +687,302 @@ void gpencil_delete_menu (void) gpencil_delete_operation(mode); } +/* --------- Data Conversion ---------- */ + +/* convert the coordinates from the given stroke point into 3d-coordinates */ +static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3]) +{ + if (gps->flag & GP_STROKE_3DSPACE) { + /* directly use 3d-coordinates */ + VecCopyf(p3d, &pt->x); + } + else { + short mval[2], mx, my; + float *fp= give_cursor(); + float dvec[3]; + + /* get screen coordinate */ + if (gps->flag & GP_STROKE_2DSPACE) { + View2D *v2d= spacelink_get_view2d(curarea->spacedata.first); + ipoco_to_areaco_noclip(v2d, &pt->x, mval); + } + else { + mval[0]= (pt->x / 1000 * curarea->winx); + mval[1]= (pt->y / 1000 * curarea->winy); + } + mx= mval[0]; + my= mval[1]; + + /* convert screen coordinate to 3d coordinates + * - method taken from editview.c - mouse_cursor() + */ + project_short_noclip(fp, mval); + window_to_3d(dvec, mval[0]-mx, mval[1]-my); + VecSubf(p3d, fp, dvec); + } +} + +/* --- */ + +/* convert stroke to 3d path */ +static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu) +{ + bGPDspoint *pt; + Nurb *nu; + BPoint *bp; + int i; + + /* create new 'nurb' within the curve */ + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + + nu->pntsu= gps->totpoints; + nu->pntsv= 1; + nu->orderu= gps->totpoints; + nu->flagu= 2; /* endpoint */ + nu->resolu= 32; + + nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints"); + + /* add points */ + for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) { + float p3d[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3d); + VecCopyf(bp->vec, p3d); + + /* set settings */ + bp->f1= SELECT; + bp->radius = bp->weight = pt->pressure * gpl->thickness; + } + + /* add nurb to curve */ + BLI_addtail(&cu->nurb, nu); +} + +/* convert stroke to 3d bezier */ +static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu) +{ + bGPDspoint *pt; + Nurb *nu; + BezTriple *bezt; + int i; + + /* create new 'nurb' within the curve */ + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + + nu->pntsu= gps->totpoints; + nu->resolu= 12; + nu->resolv= 12; + nu->type= CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts"); + + /* add points */ + for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) { + float p3d[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3d); + + /* TODO: maybe in future the handles shouldn't be in same place */ + VecCopyf(bezt->vec[0], p3d); + VecCopyf(bezt->vec[1], p3d); + VecCopyf(bezt->vec[2], p3d); + + /* set settings */ + bezt->h1= bezt->h2= HD_FREE; + bezt->f1= bezt->f2= bezt->f3= SELECT; + bezt->radius = bezt->weight = pt->pressure * gpl->thickness; + } + + /* must calculate handles or else we crash */ + calchandlesNurb(nu); + + /* add nurb to curve */ + BLI_addtail(&cu->nurb, nu); +} + +/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ +static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, short mode) +{ + bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps; + Object *ob; + Curve *cu; + + /* error checking */ + if (ELEM3(NULL, gpd, gpl, gpf)) + return; + + /* only convert if there are any strokes on this layer's frame to convert */ + if (gpf->strokes.first == NULL) + return; + + /* initialise the curve */ + cu= add_curve(gpl->info, 1); + cu->flag |= CU_3D; + + /* init the curve object (remove rotation and assign curve data to it) */ + add_object_draw(OB_CURVE); + ob= OBACT; + ob->loc[0]= ob->loc[1]= ob->loc[2]= 0; + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; + ob->data= cu; + + /* add points to curve */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + switch (mode) { + case 1: + gp_stroke_to_path(gpl, gps, cu); + break; + case 2: + gp_stroke_to_bezier(gpl, gps, cu); + break; + } + } +} + +/* --- */ + +/* convert a stroke to a bone chain */ +static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones) +{ + EditBone *ebo, *prev=NULL; + bGPDspoint *pt, *ptn; + int i; + + /* add each segment separately */ + for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) { + float p3da[3], p3db[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3da); + gp_strokepoint_convertcoords(gps, ptn, p3db); + + /* allocate new bone */ + ebo= MEM_callocN(sizeof(EditBone), "eBone"); + + VecCopyf(ebo->head, p3da); + VecCopyf(ebo->tail, p3db); + + /* add new bone - note: sync with editarmature.c::add_editbone() */ + BLI_strncpy(ebo->name, "Stroke", 32); + unique_editbone_name(bones, ebo->name); + + BLI_addtail(bones, ebo); + + ebo->flag |= BONE_CONNECTED; + ebo->weight= 1.0F; + ebo->dist= 0.25F; + ebo->xwidth= 0.1; + ebo->zwidth= 0.1; + ebo->ease1= 1.0; + ebo->ease2= 1.0; + ebo->rad_head= pt->pressure * gpl->thickness * 0.1; + ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1; + ebo->segments= 1; + ebo->layer= arm->layer; + + /* set parenting */ + // TODO: also adjust roll.... + ebo->parent= prev; + } +} + +/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ +static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, short mode) +{ + bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps; + Object *ob; + bArmature *arm; + ListBase bones = {0,0}; + + /* error checking */ + if (ELEM3(NULL, gpd, gpl, gpf)) + return; + + /* only convert if there are any strokes on this layer's frame to convert */ + if (gpf->strokes.first == NULL) + return; + + /* initialise the armature */ + arm= add_armature(gpl->info); + + /* init the armature object (remove rotation and assign armature data to it) */ + add_object_draw(OB_ARMATURE); + ob= OBACT; + ob->loc[0]= ob->loc[1]= ob->loc[2]= 0; + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; + ob->data= arm; + + /* convert segments to bones, strokes to bone chains */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + gp_stroke_to_bonechain(gpl, gps, arm, &bones); + } + + /* flush editbones to armature */ + editbones_to_armature(&bones, ob); + if (bones.first) BLI_freelistN(&bones); +} + +/* --- */ + +/* convert grease-pencil strokes to another representation + * mode: 1 - Active layer to path + * 2 - Active layer to bezier + * 3 - Active layer to armature + */ +void gpencil_convert_operation (short mode) +{ + bGPdata *gpd; + float *fp= give_cursor(); + + /* get datablock to work on */ + gpd= gpencil_data_getactive(NULL); + if (gpd == NULL) return; + + /* initialise 3d-cursor correction globals */ + initgrabz(fp[0], fp[1], fp[2]); + + /* handle selection modes */ + switch (mode) { + case 1: /* active layer only (to path) */ + case 2: /* active layer only (to bezier) */ + { + bGPDlayer *gpl= gpencil_layer_getactive(gpd); + gp_layer_to_curve(gpd, gpl, mode); + } + break; + case 3: /* active layer only (to armature) */ + { + bGPDlayer *gpl= gpencil_layer_getactive(gpd); + gp_layer_to_armature(gpd, gpl, mode); + } + break; + } + + /* redraw and undo-push */ + BIF_undo_push("GPencil Convert"); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWOOPS, 0); +} + +/* display a menu for converting grease-pencil strokes */ +void gpencil_convert_menu (void) +{ + bGPdata *gpd= gpencil_data_getactive(NULL); + short mode; + + /* only show menu if it will be relevant */ + if (gpd == NULL) return; + + mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3"); + if (mode <= 0) return; + + gpencil_convert_operation(mode); +} + /* ************************************************** */ /* GREASE-PENCIL EDITING MODE - Painting */ @@ -707,6 +1012,10 @@ typedef struct tGPsdata { short status; /* current status of painting */ short paintmode; /* mode for painting */ + + short mval[2]; /* current mouse-position */ + short mvalo[2]; /* previous recorded mouse-position */ + short radius; /* radius of influence for eraser */ } tGPsdata; /* values for tGPsdata->status */ @@ -828,7 +1137,7 @@ static void gp_session_initpaint (tGPsdata *p) /* set the current area */ p->sa= curarea; p->v2d= &sima->v2d; - //p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); } break; /* unsupported views */ @@ -936,24 +1245,45 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) out[1]= y; } - /* 2d - on image 'canvas' (asume that p->v2d is set) */ - else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && - (p->v2d) && (p->ibuf) ) + /* 2d - on image 'canvas' (assume that p->v2d is set) */ + else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && (p->v2d) ) { - ImBuf *ibuf= p->ibuf; - float x, y; - - /* convert to 'canvas' coordinates, then adjust for view */ - areamouseco_to_ipoco(p->v2d, mval, &x, &y); - - if (ibuf) { - out[0]= x*ibuf->x; - out[1]= y*ibuf->y; - } - else { - out[0]= x; - out[1]= y; - } + /* for now - space specific */ + switch (p->sa->spacetype) { + case SPACE_SEQ: /* sequencer */ + { + SpaceSeq *sseq= (SpaceSeq *)p->sa->spacedata.first; + int sizex, sizey, offsx, offsy, rectx, recty; + float zoom, zoomx, zoomy; + + /* calculate zoom factor */ + zoom= SEQ_ZOOM_FAC(sseq->zoom); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); + zoomy = zoom; + } + else + zoomx = zoomy = zoom; + + /* calculate rect size */ + rectx= (G.scene->r.size*G.scene->r.xsch)/100; + recty= (G.scene->r.size*G.scene->r.ysch)/100; + sizex= zoomx * rectx; + sizey= zoomy * recty; + offsx= (p->sa->winx-sizex)/2 + sseq->xof; + offsy= (p->sa->winy-sizey)/2 + sseq->yof; + + /* calculate new points */ + out[0]= (float)(mval[0] - offsx) / (float)sizex; + out[1]= (float)(mval[1] - offsy) / (float)sizey; + } + break; + + default: /* just use raw mouse coordinates - BAD! */ + out[0]= mval[0]; + out[1]= mval[1]; + break; + } } /* 2d - relative to screen (viewport area) */ @@ -999,9 +1329,18 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) bGPDspoint *pt; tGPspoint *ptc; int i, totelem; + + /* macro to test if only converting endpoints */ + #define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (G.qual & LR_CTRLKEY)) - /* get total number of points to allocate space for */ - totelem = gpd->sbuffer_size; + /* get total number of points to allocate space for: + * - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints + * - otherwise, do whole stroke + */ + if (GP_BUFFER2STROKE_ENDPOINTS) + totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size; + else + totelem = gpd->sbuffer_size; /* exit with error if no valid points from this stroke */ if (totelem == 0) { @@ -1022,45 +1361,53 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) gps->flag= gpd->sbuffer_sflag; /* copy points from the buffer to the stroke */ - for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { - /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); - - /* copy pressure */ - pt->pressure= ptc->pressure; - - pt++; + if (GP_BUFFER2STROKE_ENDPOINTS) { + /* 'Draw Mode' + Ctrl-Modifier - only endpoints */ + { + /* first point */ + ptc= gpd->sbuffer; + + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + + pt++; + } + + if (totelem == 2) { + /* last point if applicable */ + ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1); + + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + } + } + else { + /* convert all points (normal behaviour) */ + for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + + pt++; + } } /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); + + /* undefine macro to test if only converting endpoints */ + #undef GP_BUFFER2STROKE_ENDPOINTS } /* --- 'Eraser' for 'Paint' Tool ------ */ -/* User should draw 'circles' around the parts of the sketches they wish to - * delete instead of drawing squiggles over existing lines. This should be - * easier to manage than if it was done otherwise. - */ - -/* convert gp-buffer stroke into mouse-coordinates array */ -static short (*gp_stroke_eraser_2mco (bGPdata *gpd))[2] -{ - tGPspoint *pt; - short (*mcoords)[2]; - int i; - - /* allocate memory for coordinates array */ - mcoords= MEM_mallocN(sizeof(*mcoords)*gpd->sbuffer_size,"gp_buf_mcords"); - - /* copy coordinates */ - for (pt=gpd->sbuffer, i=0; i < gpd->sbuffer_size; i++, pt++) { - mcoords[i][0]= pt->x; - mcoords[i][1]= pt->y; - } - - /* return */ - return mcoords; -} /* eraser tool - remove segment from stroke/split stroke (after lasso inside) */ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) @@ -1130,8 +1477,19 @@ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) } } +/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */ +static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1) +{ + /* simple within-radius check for now */ + if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) + return 1; + + /* not inside */ + return 0; +} + /* eraser tool - evaluation per stroke */ -static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) +static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) { bGPDspoint *pt1, *pt2; short x0=0, y0=0, x1=0, y1=0; @@ -1147,16 +1505,20 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo else if (gps->totpoints == 1) { /* get coordinates */ if (gps->flag & GP_STROKE_3DSPACE) { - // FIXME: this may not be the correct correction project_short(&gps->points->x, xyval); x0= xyval[0]; - x1= xyval[1]; + y0= xyval[1]; } else if (gps->flag & GP_STROKE_2DSPACE) { ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); x0= xyval[0]; y0= xyval[1]; } + else if (gps->flag & GP_STROKE_2DIMAGE) { + ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); + x0= xyval[0]; + y0= xyval[1]; + } else { x0= (gps->points->x / 1000 * p->sa->winx); y0= (gps->points->y / 1000 * p->sa->winy); @@ -1165,7 +1527,7 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo /* do boundbox check first */ if (BLI_in_rcti(rect, x0, y0)) { /* only check if point is inside */ - if (lasso_inside(mcoords, moves, x0, y0)) { + if ( ((x0-mval[0])*(x0-mval[0]) + (y0-mval[1])*(y0-mval[1])) <= rad*rad ) { /* free stroke */ MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); @@ -1183,10 +1545,13 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo /* get coordinates */ if (gps->flag & GP_STROKE_3DSPACE) { - // FIXME: may not be correct correction - project_short(&gps->points->x, xyval); + project_short(&pt1->x, xyval); x0= xyval[0]; - x1= xyval[1]; + y0= xyval[1]; + + project_short(&pt2->x, xyval); + x1= xyval[0]; + y1= xyval[1]; } else if (gps->flag & GP_STROKE_2DSPACE) { ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); @@ -1197,6 +1562,15 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo x1= xyval[0]; y1= xyval[1]; } + else if (gps->flag & GP_STROKE_2DIMAGE) { + ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); + x0= xyval[0]; + y0= xyval[1]; + + ipoco_to_areaco_noclip(p->v2d, &pt2->x, xyval); + x1= xyval[0]; + y1= xyval[1]; + } else { x0= (pt1->x / 1000 * p->sa->winx); y0= (pt1->y / 1000 * p->sa->winy); @@ -1209,9 +1583,8 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant - * - handled using the lasso-select checking code */ - if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) { + if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) { /* if function returns true, break this loop (as no more point to check) */ if (gp_stroke_eraser_splitdel(gpf, gps, i)) break; @@ -1221,29 +1594,24 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo } } -/* -------- */ - /* erase strokes which fall under the eraser strokes */ static void gp_stroke_doeraser (tGPsdata *p) { - bGPdata *gpd= p->gpd; bGPDframe *gpf= p->gpf; bGPDstroke *gps, *gpn; - short (*mcoords)[2]; rcti rect; - /* get buffer-stroke coordinates as shorts array, and then get bounding box */ - mcoords= gp_stroke_eraser_2mco(gpd); - lasso_select_boundbox(&rect, mcoords, gpd->sbuffer_size); + /* rect is rectangle of eraser */ + rect.xmin= p->mval[0] - p->radius; + rect.ymin= p->mval[1] - p->radius; + rect.xmax= p->mval[0] + p->radius; + rect.ymax= p->mval[1] + p->radius; /* loop over strokes, checking segments for intersections */ for (gps= gpf->strokes.first; gps; gps= gpn) { gpn= gps->next; - gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, &rect, gpf, gps); + gp_stroke_eraser_dostroke(p, p->mval, p->mvalo, p->radius, &rect, gpf, gps); } - - /* free mcoords array */ - MEM_freeN(mcoords); } /* ---------- 'Paint' Tool ------------ */ @@ -1297,6 +1665,14 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) case SPACE_SEQ: { /* for now, this is not applicable here... */ + p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE; + } + break; + case SPACE_IMAGE: + { + /* check if any ibuf available */ + if (p->ibuf) + p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE; } break; } @@ -1307,11 +1683,7 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) static void gp_paint_strokeend (tGPsdata *p) { /* check if doing eraser or not */ - if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) { - /* get rid of relevant sections of strokes */ - gp_stroke_doeraser(p); - } - else { + if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* transfer stroke to frame */ gp_stroke_newfrombuffer(p); } @@ -1345,7 +1717,6 @@ static void gp_paint_cleanup (tGPsdata *p) short gpencil_paint (short mousebutton, short paintmode) { tGPsdata p; - short prevmval[2], mval[2]; float opressure, pressure; short ok = GP_STROKEADD_NORMAL; @@ -1365,31 +1736,51 @@ short gpencil_paint (short mousebutton, short paintmode) setcursor_space(p.sa->spacetype, CURSOR_VPAINT); /* init drawing-device settings */ - getmouseco_areawin(mval); + getmouseco_areawin(p.mval); pressure = get_pressure(); - prevmval[0]= mval[0]; - prevmval[1]= mval[1]; + p.mvalo[0]= p.mval[0]; + p.mvalo[1]= p.mval[1]; opressure= pressure; + /* radius for eraser circle is thickness^2 */ + p.radius= p.gpl->thickness * p.gpl->thickness; + + /* start drawing eraser-circle (if applicable) */ + if (paintmode == GP_PAINTMODE_ERASER) + draw_sel_circle(p.mval, NULL, p.radius, p.radius, 0); // draws frontbuffer, but sets backbuf again + /* only allow painting of single 'dots' if: * - pressure is not excessive (as it can be on some windows tablets) * - draw-mode for active datablock is turned on + * - not erasing */ - if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { - gp_stroke_addpoint(&p, mval, pressure); + if (paintmode != GP_PAINTMODE_ERASER) { + if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { + gp_stroke_addpoint(&p, p.mval, pressure); + } } /* paint loop */ do { /* get current user input */ - getmouseco_areawin(mval); + getmouseco_areawin(p.mval); pressure = get_pressure(); /* only add current point to buffer if mouse moved (otherwise wait until it does) */ - if (gp_stroke_filtermval(&p, mval, prevmval)) { + if (paintmode == GP_PAINTMODE_ERASER) { + /* do 'live' erasing now */ + gp_stroke_doeraser(&p); + + draw_sel_circle(p.mval, p.mvalo, p.radius, p.radius, 0); + force_draw(0); + + p.mvalo[0]= p.mval[0]; + p.mvalo[1]= p.mval[1]; + } + else if (gp_stroke_filtermval(&p, p.mval, p.mvalo)) { /* try to add point */ - ok= gp_stroke_addpoint(&p, mval, pressure); + ok= gp_stroke_addpoint(&p, p.mval, pressure); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { @@ -1397,8 +1788,8 @@ short gpencil_paint (short mousebutton, short paintmode) gp_paint_strokeend(&p); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(&p, prevmval, opressure); - ok= gp_stroke_addpoint(&p, mval, pressure); + gp_stroke_addpoint(&p, p.mvalo, opressure); + ok= gp_stroke_addpoint(&p, p.mval, pressure); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1411,8 +1802,8 @@ short gpencil_paint (short mousebutton, short paintmode) } force_draw(0); - prevmval[0]= mval[0]; - prevmval[1]= mval[1]; + p.mvalo[0]= p.mval[0]; + p.mvalo[1]= p.mval[1]; opressure= pressure; } else @@ -1430,8 +1821,10 @@ short gpencil_paint (short mousebutton, short paintmode) setcursor_space(p.sa->spacetype, CURSOR_STD); /* check size of buffer before cleanup, to determine if anything happened here */ - if (paintmode == GP_PAINTMODE_ERASER) - ok= (p.gpd->sbuffer_size > 1); + if (paintmode == GP_PAINTMODE_ERASER) { + ok= 1; // fixme + draw_sel_circle(NULL, p.mvalo, 0, p.radius, 0); + } else ok= p.gpd->sbuffer_size; @@ -1458,7 +1851,8 @@ short gpencil_do_paint (ScrArea *sa, short mbut) /* currently, we will only 'paint' if: * 1. draw-mode on gpd is set (for accessibility reasons) - * (single 'dots' are only available via this method) + * a) single dots are only available by this method if a single click is made + * b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!) * 2. if shift-modifier is held + lmb -> 'quick paint' * * OR diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index fac9e3af1af..4ca287d81c5 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -239,8 +239,10 @@ void do_image_buttons(unsigned short event) if(ima->twsta>=nr) ima->twsta= 1; if(ima->twend>=nr) ima->twend= nr-1; if(ima->twsta>ima->twend) ima->twsta= 1; - allqueue(REDRAWIMAGE, 0); } + + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWVIEW3D, 0); } break; } @@ -475,6 +477,9 @@ static void do_image_viewmenu(void *arg, int event) G.sima->flag ^= SI_LOCAL_UV; allqueue(REDRAWIMAGE, 0); break; + case 15: /* Grease Pencil... */ + add_blockhandler(curarea, IMAGE_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -497,6 +502,8 @@ static uiBlock *image_viewmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Curves Tool...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Composite Preview...|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Grease Pencil...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + if(G.sima->flag & SI_LOCAL_UV) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "UV Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "UV Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); if(!(G.sima->flag & SI_LOCAL_UV)) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "UV Global View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); @@ -1293,7 +1300,7 @@ void image_buttons(void) uiBlockEndAlign(block); xco+= 166; } - uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enables painting textures on the image with left mouse button"); + uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enable image painting"); xco+= XIC+8; diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 8b8fd9ef266..9bacc2b6351 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -39,8 +39,6 @@ #include #endif -#include "BLO_sys_types.h" // for intptr_t support - #include "DNA_group_types.h" #include "DNA_ID.h" #include "DNA_image_types.h" @@ -120,6 +118,9 @@ #include "BPY_extern.h" #include "BPY_menus.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + #include "blendef.h" #include "interface.h" #include "mydevice.h" @@ -926,7 +927,7 @@ static void do_info_filemenu(void *arg, int event) winqueue_break= 1; /* leave queues everywhere */ BKE_reset_undo(); - BKE_write_undo("original"); /* save current state */ + BKE_write_undo("Original"); /* save current state */ refresh_interface_font(); } break; @@ -1591,20 +1592,83 @@ static uiBlock *info_addmenu(void *arg_unused) /************************** GAME *****************************/ +void do_info_game_glslmenu(void *arg, int event) +{ + switch (event) { + case G_FILE_GLSL_NO_LIGHTS: + case G_FILE_GLSL_NO_SHADERS: + case G_FILE_GLSL_NO_SHADOWS: + case G_FILE_GLSL_NO_RAMPS: + case G_FILE_GLSL_NO_NODES: + case G_FILE_GLSL_NO_EXTRA_TEX: + G.fileflags ^= event; + GPU_materials_free(); + allqueue(REDRAWINFO, 0); + allqueue(REDRAWVIEW3D, 0); + break; + default: + break; + } +} + +static uiBlock *info_game_glslmenu(void *arg_unused) +{ + uiBlock *block; + short yco= 0, menuwidth=160; + int check; + block= uiNewBlock(&curarea->uiblocks, "game_glslmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_info_game_glslmenu, NULL); + + check = (G.fileflags & G_FILE_GLSL_NO_LIGHTS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Lights", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_LIGHTS, + "Enable using lights in GLSL materials."); + check = (G.fileflags & G_FILE_GLSL_NO_SHADERS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Shaders", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_SHADERS, + "Enable using shaders other than Lambert in GLSL materials"); + check = (G.fileflags & G_FILE_GLSL_NO_SHADOWS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Shadows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_SHADOWS, + "Enable using shadows in GLSL materials"); + check = (G.fileflags & G_FILE_GLSL_NO_RAMPS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Ramps", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_RAMPS, + "Enable using ramps in GLSL materials"); + check = (G.fileflags & G_FILE_GLSL_NO_NODES)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Nodes", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_NODES, + "Enable using nodes in GLSL materials."); + check = (G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Extra Textures", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_EXTRA_TEX, + "Enable using texture channels other than Col and Alpha in GLSL materials."); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 50); + + return block; +} + static void do_info_gamemenu(void *arg, int event) { switch (event) { case G_FILE_ENABLE_ALL_FRAMES: - case G_FILE_DIAPLAY_LISTS: + case G_FILE_DISPLAY_LISTS: case G_FILE_SHOW_FRAMERATE: case G_FILE_SHOW_DEBUG_PROPS: case G_FILE_AUTOPLAY: case G_FILE_GAME_TO_IPO: - case G_FILE_GAME_MAT: case G_FILE_SHOW_PHYSICS: G.fileflags ^= event; break; + case G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL: + G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + break; + case G_FILE_GAME_MAT: + G.fileflags |= G_FILE_GAME_MAT; + G.fileflags &= ~G_FILE_GAME_MAT_GLSL; + break; + case G_FILE_GAME_MAT_GLSL: + if(!GPU_extensions_minimum_support()) + error("GLSL not supported with this graphics card or driver."); + G.fileflags |= (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + break; default: ; /* ignore the rest */ } @@ -1635,22 +1699,14 @@ static uiBlock *info_gamemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } else { - if(G.fileflags & G_FILE_DIAPLAY_LISTS) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DIAPLAY_LISTS, ""); + if(G.fileflags & G_FILE_DISPLAY_LISTS) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, ""); } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DIAPLAY_LISTS, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, ""); } uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } - if(G.fileflags & G_FILE_GAME_MAT) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); - } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); - } - - - if(G.fileflags & G_FILE_SHOW_FRAMERATE) { uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Framerate and Profile", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_FRAMERATE, ""); } else { @@ -1669,6 +1725,28 @@ static uiBlock *info_gamemenu(void *arg_unused) } else { uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Debug Properties", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_DEBUG_PROPS, ""); } + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); + + if(!(G.fileflags & G_FILE_GAME_MAT)) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Texture Face Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Texture Face Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL, ""); + } + + if((G.fileflags & G_FILE_GAME_MAT) && !(G.fileflags & G_FILE_GAME_MAT_GLSL)) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Blender Multitexture Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Blender Multitexture Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); + } + + if((G.fileflags & G_FILE_GAME_MAT) && (G.fileflags & G_FILE_GAME_MAT_GLSL)) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Blender GLSL Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Blender GLSL Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT_GLSL, ""); + } + + uiDefIconTextBlockBut(block, info_game_glslmenu, NULL, ICON_RIGHTARROW_THIN, "GLSL Material Settings", 0, yco-=20, menuwidth, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); @@ -2108,13 +2186,16 @@ static void info_text(int x, int y) { Object *ob= OBACT; extern float hashvectf[]; - extern uintptr_t mem_in_use, mmap_in_use; + uintptr_t mem_in_use, mmap_in_use; unsigned int swatch_color; float fac1, fac2, fac3; char infostr[300], memstr[64]; char *headerstr, *s; int hsize; + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + s= memstr + sprintf(memstr," | Mem:%.2fM ", ((mem_in_use-mmap_in_use)>>10)/1024.0); if(mmap_in_use) sprintf(s,"(%.2fM) ", ((mmap_in_use)>>10)/1024.0); diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 59d542e72ec..130ffa1e49f 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -1414,7 +1414,7 @@ void ipo_buttons(void) uiClearButLock(); /* ZOOMBORDER */ - uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area"); + uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area (Shift B)"); xco+=XIC/2; diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index 4c7b4aa80bc..d27a41c59f5 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -112,7 +112,7 @@ static void do_node_viewmenu(void *arg, int event) break; case 4: /* Grease Pencil */ add_blockhandler(curarea, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); - break; + break; } allqueue(REDRAWNODE, 0); } @@ -602,11 +602,11 @@ static uiBlock *node_nodemenu(void *arg_unused) if(snode->treetype==NTREE_COMPOSIT) { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Execute Composite|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Render Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl LMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl RMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c index cf6d21ff264..eeea43ec57a 100644 --- a/source/blender/src/header_text.c +++ b/source/blender/src/header_text.c @@ -42,6 +42,7 @@ #include "BMF_Api.h" #include "BIF_language.h" +#include "MEM_guardedalloc.h" #include "BSE_headerbuttons.h" @@ -52,6 +53,7 @@ #include "DNA_constraint_types.h" #include "DNA_action_types.h" +#include "BIF_gl.h" /* for glRasterPos2i */ #include "BIF_drawtext.h" #include "BIF_interface.h" #include "BIF_resources.h" @@ -128,7 +130,7 @@ void do_text_buttons(unsigned short event) st->top= 0; pop_space_text(st); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); } @@ -194,14 +196,20 @@ void do_text_buttons(unsigned short event) break; case B_TAB_NUMBERS: - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); break; case B_SYNTAX: - if (st->showsyntax) { - get_format_string(st); - } + if (st->showsyntax) txt_format_text(st); + allqueue(REDRAWTEXT, 0); + allqueue(REDRAWHEADERS, 0); + break; + case B_TEXTPLUGINS: + allqueue(REDRAWHEADERS, 0); + break; + case B_WORDWRAP: + st->left= 0; allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); break; @@ -239,6 +247,37 @@ static uiBlock *text_template_scriptsmenu (void *args_unused) return block; } +static void do_text_plugin_scriptsmenu(void *arg, int event) +{ + BPY_menu_do_python(PYMENU_TEXTPLUGIN, event); + + allqueue(REDRAWIMAGE, 0); +} + +static uiBlock *text_plugin_scriptsmenu (void *args_unused) +{ + uiBlock *block; + BPyMenu *pym; + int i= 0; + short yco = 20, menuwidth = 120; + + block= uiNewBlock(&curarea->uiblocks, "text_plugin_scriptsmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_text_plugin_scriptsmenu, NULL); + + /* note that we acount for the N previous entries with i+20: */ + for (pym = BPyMenuTable[PYMENU_TEXTPLUGIN]; pym; pym = pym->next, i++) { + + uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, + NULL, 0.0, 0.0, 1, i, + pym->tooltip?pym->tooltip:pym->filename); + } + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 60); + + return block; +} + /* action executed after clicking in File menu */ static void do_text_filemenu(void *arg, int event) { @@ -268,7 +307,7 @@ static void do_text_filemenu(void *arg, int event) if (!reopen_text(text)) { error("Could not reopen file"); } - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); } break; case 5: @@ -277,9 +316,14 @@ static void do_text_filemenu(void *arg, int event) txt_write_file(text); break; case 6: - run_python_script(st); + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; break; case 7: + run_python_script(st); + break; + case 8: { Object *ob; bConstraint *con; @@ -340,11 +384,17 @@ static void do_text_editmenu(void *arg, int event) switch(event) { case 1: txt_do_undo(text); + pop_space_text(st); break; case 2: txt_do_redo(text); + pop_space_text(st); break; case 3: + if (text && text->id.lib) { + error_libdata(); + break; + } txt_copy_clipboard(text); txt_cut_sel(text); pop_space_text(st); @@ -354,8 +404,12 @@ static void do_text_editmenu(void *arg, int event) txt_copy_clipboard(text); break; case 5: + if (text && text->id.lib) { + error_libdata(); + break; + } txt_paste_clipboard(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; case 6: txt_print_cutbuffer(); @@ -364,10 +418,11 @@ static void do_text_editmenu(void *arg, int event) jumptoline_interactive(st); break; case 8: - txt_find_panel(st,1); - break; case 9: - txt_find_panel(st,0); + find_and_replace(st, 0); + break; + case 10: + find_and_replace(st, 1); break; default: break; @@ -443,6 +498,57 @@ static void do_text_editmenu_selectmenu(void *arg, int event) } } +/* action executed after clicking in Markers menu */ +static void do_text_editmenu_markermenu(void *arg, int event) +{ + SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */ + Text *text; + TextMarker *mrk; + ScrArea *sa; + int lineno; + + if (st==NULL || st->spacetype != SPACE_TEXT) return; + + text = st->text; + + switch(event) { + case 1: + txt_clear_markers(text, 0, 0); + break; + case 2: + lineno= txt_get_span(text->lines.first, text->curl); + mrk= text->markers.first; + while (mrk && (mrk->linenolineno==lineno && mrk->start <= text->curc))) + mrk= mrk->next; + if (!mrk) mrk= text->markers.first; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + } + break; + case 3: + lineno= txt_get_span(text->lines.first, text->curl); + mrk= text->markers.last; + while (mrk && (mrk->lineno>lineno || (mrk->lineno==lineno && mrk->end > text->curc))) + mrk= mrk->prev; + if (!mrk) mrk= text->markers.last; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + } + break; + default: + break; + } + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } +} + /* action executed after clicking in Format menu */ static void do_text_formatmenu(void *arg, int event) { @@ -456,6 +562,10 @@ static void do_text_formatmenu(void *arg, int event) switch(event) { case 3: + if (text && text->id.lib) { + error_libdata(); + break; + } if (txt_has_sel(text)) { txt_order_cursors(text); indent(text); @@ -466,6 +576,10 @@ static void do_text_formatmenu(void *arg, int event) break; } case 4: + if (text && text->id.lib) { + error_libdata(); + break; + } if ( txt_has_sel(text)) { txt_order_cursors(text); unindent(text); @@ -473,18 +587,26 @@ static void do_text_formatmenu(void *arg, int event) } break; case 5: + if (text && text->id.lib) { + error_libdata(); + break; + } if ( txt_has_sel(text)) { txt_order_cursors(text); comment(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; } break; case 6: + if (text && text->id.lib) { + error_libdata(); + break; + } if ( txt_has_sel(text)) { txt_order_cursors(text); uncomment(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; } break; @@ -536,6 +658,25 @@ static uiBlock *text_editmenu_selectmenu(void *arg_unused) return block; } +/* Select menu */ +static uiBlock *text_editmenu_markermenu(void *arg_unused) +{ + uiBlock *block; + short yco = 20, menuwidth = 120; + + block= uiNewBlock(&curarea->uiblocks, "text_editmenu_markermenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_text_editmenu_markermenu, NULL); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Next Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Previous Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 60); + + return block; +} + void do_text_formatmenu_convert(void *arg, int event) { SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */ @@ -649,10 +790,12 @@ static uiBlock *text_editmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, text_editmenu_viewmenu, NULL, ICON_RIGHTARROW_THIN, "View|Alt Shift V ", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, text_editmenu_selectmenu, NULL, ICON_RIGHTARROW_THIN, "Select|Alt Shift S ", 0, yco-=20, 120, 19, ""); + uiDefIconTextBlockBut(block, text_editmenu_markermenu, NULL, ICON_RIGHTARROW_THIN, "Markers", 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, "Jump...|Alt J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find...|Alt Ctrl F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Again|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find And Replace...|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Next|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Replace|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, text_editmenu_to3dmenu, NULL, ICON_RIGHTARROW_THIN, "Text to 3d Object", 0, yco-=20, 120, 19, ""); @@ -690,17 +833,21 @@ static uiBlock *text_filemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); + if (text->name) + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Internal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); if (BPY_is_pyconstraint(text)) - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, ""); + uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, ""); if(curarea->headertype==HEADERTOP) { uiBlockSetDirection(block, UI_DOWN); @@ -715,13 +862,15 @@ static uiBlock *text_filemenu(void *arg_unused) } /* header */ +#define HEADER_PATH_MAX 260 void text_buttons(void) { uiBlock *block; SpaceText *st= curarea->spacedata.first; Text *text; short xco, xmax; - char naam[256]; + char naam[256], fname[HEADER_PATH_MAX], headtxt[HEADER_PATH_MAX+17]; + int len; if (st==NULL || st->spacetype != SPACE_TEXT) return; @@ -779,8 +928,9 @@ void text_buttons(void) else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Makes current window full screen (CTRL+Down arrow)"); uiDefIconButI(block, ICONTOG, B_TEXTLINENUM, ICON_LONGDISPLAY, xco+=XIC,0,XIC,YIC, &st->showlinenrs, 0, 0, 0, 0, "Displays line numbers"); - - uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables Syntax Highlighting"); + uiDefIconButI(block, ICONTOG, B_WORDWRAP, ICON_WORDWRAP, xco+=XIC,0,XIC,YIC, &st->wordwrap, 0, 0, 0, 0, "Enables word wrap"); + uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables syntax highlighting"); + uiDefIconButI(block, ICONTOG, B_TEXTPLUGINS, ICON_PYTHON, xco+=XIC,0,XIC,YIC, &st->doplugins, 0, 0, 0, 0, "Enables Python text plugins"); uiBlockEndAlign(block); /* STD TEXT BUTTONS */ @@ -804,9 +954,30 @@ void text_buttons(void) uiDefButI(block, MENU, B_TEXTFONT, "Screen 12 %x0|Screen 15%x1", xco,0,100,YIC, &st->font_id, 0, 0, 0, 0, "Displays available fonts"); xco+=110; - uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab"); + uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab"); xco+= XIC+50; - + + /* File info */ + if (text) { + if (text->name) { + len = strlen(text->name); + if (len > HEADER_PATH_MAX-1) + len = HEADER_PATH_MAX-1; + strncpy(fname, text->name, len); + fname[len]='\0'; + if (text->flags & TXT_ISDIRTY) + sprintf(headtxt, "File: *%s (unsaved)", fname); + else + sprintf(headtxt, "File: %s", fname); + } else { + sprintf(headtxt, text->id.lib?"Text: External":"Text: Internal"); + } + BIF_ThemeColor(TH_MENU_TEXT); + glRasterPos2i(xco+=XIC, 5); + BMF_DrawString(G.font, headtxt); + xco += BMF_GetStringWidth(G.font, headtxt); + } + /* always as last */ curarea->headbutlen= xco+2*XIC; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index fcf4caf4522..acd80f5efdd 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -106,6 +106,7 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_meshtools.h" #include "BIF_poselib.h" @@ -4370,6 +4371,9 @@ static void do_view3d_pose_armaturemenu(void *arg, int event) case 18: pose_autoside_names(event-16); break; + case 19: /* assign pose as restpose */ + apply_armature_pose2bones(); + break; } allqueue(REDRAWVIEW3D, 0); @@ -4395,6 +4399,7 @@ static uiBlock *view3d_pose_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Relax Pose|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Pose as Restpose|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -4508,7 +4513,7 @@ static void do_view3d_tpaintmenu(void *arg, int event) { switch(event) { case 0: /* undo image painting */ - imagepaint_undo(); + undo_imagepaint_step(1); break; } @@ -5383,7 +5388,11 @@ void do_view3d_buttons(short event) case B_MAN_MODE: allqueue(REDRAWVIEW3D, 1); break; - + case B_VIEW_BUTSEDIT: + allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWBUTSEDIT, 1); + break; + default: if(event>=B_LAY && eventlocalview==0) { + int ob_lay = ob ? ob->lay : 0; uiBlockBeginAlign(block); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - + for(a=0; a<5; a++) { + uiDefIconButBitI(block, TOG, 1<lay_used), (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } + for(a=0; a<5; a++) { + uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, G.vd->lay_used), (short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } xco+= 5; uiBlockBeginAlign(block); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - + for(a=5; a<10; a++) { + uiDefIconButBitI(block, TOG, 1<lay_used), (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } + for(a=5; a<10; a++) { + uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, G.vd->lay_used), (short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } uiBlockEndAlign(block); xco+= (a-2)*(XIC/2)+3; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 1a91ada1562..44044841a99 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -154,7 +154,6 @@ #include "BSE_editipo.h" #include "BSE_drawipo.h" -#include "BDR_drawmesh.h" #include "BDR_vpaint.h" #include "BDR_editface.h" #include "BDR_editobject.h" @@ -165,6 +164,8 @@ #include "BPY_extern.h" #include "BPY_menus.h" +#include "GPU_draw.h" + #include "mydevice.h" #include "blendef.h" #include "interface.h" @@ -1425,11 +1426,11 @@ void do_global_buttons(unsigned short event) show_splash(); break; case B_MIPMAPCHANGED: - set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); allqueue(REDRAWVIEW3D, 0); break; case B_GLRESLIMITCHANGED: - free_all_realtime_images(); /* force reloading with new res limit */ + GPU_free_images(); /* force reloading with new res limit */ allqueue(REDRAWVIEW3D, 0); break; case B_NEWSPACE: diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 15c289cc21c..164c368b6fa 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -44,6 +44,8 @@ #include "BLI_winstuff.h" #endif #include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" #include "PIL_time.h" #include "IMB_imbuf.h" @@ -64,10 +66,12 @@ #include "BKE_brush.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_node.h" #include "BKE_utildefines.h" +#include "BIF_interface.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -78,10 +82,11 @@ #include "BSE_trans_types.h" #include "BSE_view.h" -#include "BDR_drawmesh.h" #include "BDR_imagepaint.h" #include "BDR_vpaint.h" +#include "GPU_draw.h" + #include "GHOST_Types.h" #include "blendef.h" @@ -103,6 +108,8 @@ #define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) #define IMAPAINT_TILE_NUMBER(size) (((size)+IMAPAINT_TILE_SIZE-1) >> IMAPAINT_TILE_BITS) +#define MAXUNDONAME 64 + typedef struct ImagePaintState { Brush *brush; short tool, blend; @@ -120,48 +127,206 @@ typedef struct ImagePaintState { float uv[2]; } ImagePaintState; -typedef struct ImagePaintUndo { - Image *image; - ImBuf *tilebuf; - void **tiles; - int xtiles, ytiles; -} ImagePaintUndo; +typedef struct UndoTile { + struct UndoTile *next, *prev; + ID id; + void *rect; + int x, y; +} UndoTile; + +typedef struct UndoElem { + struct UndoElem *next, *prev; + char name[MAXUNDONAME]; + unsigned long undosize; + + ImBuf *ibuf; + ListBase tiles; +} UndoElem; typedef struct ImagePaintPartialRedraw { int x1, y1, x2, y2; int enabled; } ImagePaintPartialRedraw; -static ImagePaintUndo imapaintundo = {NULL, NULL, NULL, 0, 0}; +static ListBase undobase = {NULL, NULL}; +static UndoElem *curundo = NULL; static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0}; -static void init_imagapaint_undo(Image *ima, ImBuf *ibuf) +/* UNDO */ + +/* internal functions */ + +static void undo_copy_tile(UndoTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore) { - int xt, yt; + /* copy or swap contents of tile->rect and region in ibuf->rect */ + IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE, + tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); - imapaintundo.image = ima; - imapaintundo.xtiles = xt = IMAPAINT_TILE_NUMBER(ibuf->x); - imapaintundo.ytiles = yt = IMAPAINT_TILE_NUMBER(ibuf->y); - imapaintundo.tiles = MEM_callocN(sizeof(void*)*xt*yt, "ImagePaintUndoTiles"); - imapaintundo.tilebuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, - ibuf->depth, (ibuf->rect_float)? IB_rectfloat: IB_rect, 0); -} - -static void imapaint_copy_tile(ImBuf *ibuf, int tile, int x, int y, int swapundo) -{ - IMB_rectcpy(imapaintundo.tilebuf, ibuf, 0, 0, x*IMAPAINT_TILE_SIZE, - y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); - - if (imapaintundo.tilebuf->rect_float) - SWAP(void*, imapaintundo.tilebuf->rect_float, imapaintundo.tiles[tile]) - else - SWAP(void*, imapaintundo.tilebuf->rect, imapaintundo.tiles[tile]) + if(ibuf->rect_float) SWAP(void*, tmpibuf->rect_float, tile->rect) + else SWAP(void*, tmpibuf->rect, tile->rect) - if (swapundo) - IMB_rectcpy(ibuf, imapaintundo.tilebuf, x*IMAPAINT_TILE_SIZE, - y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); + if(restore) + IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE, + tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } +static void undo_restore(UndoElem *undo) +{ + Image *ima = NULL; + ImBuf *ibuf, *tmpibuf; + UndoTile *tile; + + if(!undo) + return; + + tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, + IB_rectfloat|IB_rect, 0); + + for(tile=undo->tiles.first; tile; tile=tile->next) { + /* find image based on name, pointer becomes invalid with global undo */ + if(ima && strcmp(tile->id.name, ima->id.name)==0); + else { + for(ima=G.main->image.first; ima; ima=ima->id.next) + if(strcmp(tile->id.name, ima->id.name)==0) + break; + } + + ibuf= BKE_image_get_ibuf(ima, NULL); + + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + continue; + + undo_copy_tile(tile, tmpibuf, ibuf, 1); + + GPU_free_image(ima); /* force OpenGL reload */ + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); /* force recreate of char rect */ + } + + IMB_freeImBuf(tmpibuf); +} + +static void undo_free(UndoElem *undo) +{ + UndoTile *tile; + + for(tile=undo->tiles.first; tile; tile=tile->next) + MEM_freeN(tile->rect); + BLI_freelistN(&undo->tiles); +} + +static void undo_imagepaint_push_begin(char *name) +{ + UndoElem *uel; + int nr; + + /* Undo push is split up in begin and end, the reason is that as painting + * happens more tiles are added to the list, and at the very end we know + * how much memory the undo used to remove old undo elements */ + + /* remove all undos after (also when curundo==NULL) */ + while(undobase.last != curundo) { + uel= undobase.last; + undo_free(uel); + BLI_freelinkN(&undobase, uel); + } + + /* make new */ + curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file"); + BLI_addtail(&undobase, uel); + + /* name can be a dynamic string */ + strncpy(uel->name, name, MAXUNDONAME-1); + + /* limit amount to the maximum amount*/ + nr= 0; + uel= undobase.last; + while(uel) { + nr++; + if(nr==U.undosteps) break; + uel= uel->prev; + } + if(uel) { + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + undo_free(first); + BLI_freelinkN(&undobase, first); + } + } +} + +static void undo_imagepaint_push_end() +{ + UndoElem *uel; + unsigned long totmem, maxmem; + + if(U.undomemory != 0) { + /* limit to maximum memory (afterwards, we can't know in advance) */ + totmem= 0; + maxmem= ((unsigned long)U.undomemory)*1024*1024; + + uel= undobase.last; + while(uel) { + totmem+= uel->undosize; + if(totmem>maxmem) break; + uel= uel->prev; + } + + if(uel) { + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + undo_free(first); + BLI_freelinkN(&undobase, first); + } + } + } +} + +/* external functions */ + +/* 1= an undo, -1 is a redo. */ +void undo_imagepaint_step(int step) +{ + UndoElem *undo; + + if(step==1) { + if(curundo==NULL) error("No more steps to undo"); + else { + if(G.f & G_DEBUG) printf("undo %s\n", curundo->name); + undo_restore(curundo); + curundo= curundo->prev; + } + } + else if(step==-1) { + if((curundo!=NULL && curundo->next==NULL) || undobase.first==NULL) error("No more steps to redo"); + else { + undo= (curundo && curundo->next)? curundo->next: undobase.first; + undo_restore(undo); + curundo= undo; + if(G.f & G_DEBUG) printf("redo %s\n", undo->name); + } + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); +} + +void undo_imagepaint_clear(void) +{ + UndoElem *uel; + + uel= undobase.first; + while(uel) { + undo_free(uel); + uel= uel->next; + } + + BLI_freelistN(&undobase); + curundo= NULL; +} + +/* Imagepaint Partial Redraw & Dirty Region */ + static void imapaint_clear_partial_redraw() { memset(&imapaintpartial, 0, sizeof(imapaintpartial)); @@ -169,7 +334,9 @@ static void imapaint_clear_partial_redraw() static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) { - int srcx= 0, srcy= 0, origx, tile, allocsize; + ImBuf *tmpibuf; + UndoTile *tile; + int srcx= 0, srcy= 0, origx, allocsize; IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); @@ -195,24 +362,36 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, origx = (x >> IMAPAINT_TILE_BITS); y = (y >> IMAPAINT_TILE_BITS); + tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, + IB_rectfloat|IB_rect, 0); + for (; y <= h; y++) { for (x=origx; x <= w; x++) { - if (ima != imapaintundo.image) { - free_imagepaint(); - init_imagapaint_undo(ima, ibuf); - } + for(tile=curundo->tiles.first; tile; tile=tile->next) + if(tile->x == x && tile->y == y && strcmp(tile->id.name, ima->id.name)==0) + break; - tile = y*imapaintundo.xtiles + x; - if (!imapaintundo.tiles[tile]) { - allocsize= (ibuf->rect_float)? sizeof(float): sizeof(char); - imapaintundo.tiles[tile]= MEM_mapallocN(allocsize*4* - IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE, "ImagePaintUndoTile"); - imapaint_copy_tile(ibuf, tile, x, y, 0); + if(!tile) { + tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); + tile->id= ima->id; + tile->x= x; + tile->y= y; + + allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; + allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); + tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); + + undo_copy_tile(tile, tmpibuf, ibuf, 0); + curundo->undosize += allocsize; + + BLI_addtail(&curundo->tiles, tile); } } } ibuf->userflags |= IB_BITMAPDIRTY; + + IMB_freeImBuf(tmpibuf); } static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) @@ -226,7 +405,7 @@ static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) if(texpaint || G.sima->lock) { int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; - update_realtime_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); + GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); } } @@ -239,7 +418,7 @@ static void imapaint_redraw(int final, int texpaint, Image *image) allqueue(REDRAWIMAGE, 0); else if(!G.sima->lock) { if(image) - free_realtime_image(image); /* force OpenGL reload */ + GPU_free_image(image); /* force OpenGL reload */ allqueue(REDRAWVIEW3D, 0); } allqueue(REDRAWHEADERS, 0); @@ -269,46 +448,6 @@ static void imapaint_redraw(int final, int texpaint, Image *image) force_draw(0); } -void imagepaint_undo() -{ - Image *ima= imapaintundo.image; - ImBuf *ibuf= BKE_image_get_ibuf(ima, G.sima?&G.sima->iuser:NULL); - int x, y, tile; - - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) - return; - - for (tile = 0, y = 0; y < imapaintundo.ytiles; y++) - for (x = 0; x < imapaintundo.xtiles; x++, tile++) - if (imapaintundo.tiles[tile]) - imapaint_copy_tile(ibuf, tile, x, y, 1); - - free_realtime_image(ima); /* force OpenGL reload */ - if(ibuf->rect_float) - imb_freerectImBuf(ibuf); /* force recreate of char rect */ - - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWVIEW3D, 0); -} - -void free_imagepaint() -{ - /* todo: does this need to be in the same places as editmode_undo_clear, - vertex paint isn't? */ - int i, size = imapaintundo.xtiles*imapaintundo.ytiles; - - if (imapaintundo.tiles) { - for (i = 0; i < size; i++) - if (imapaintundo.tiles[i]) - MEM_freeN(imapaintundo.tiles[i]); - MEM_freeN(imapaintundo.tiles); - } - if (imapaintundo.tilebuf) - IMB_freeImBuf(imapaintundo.tilebuf); - - memset(&imapaintundo, 0, sizeof(imapaintundo)); -} - /* Image Paint Operations */ static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, short set, float *rgb) @@ -580,7 +719,6 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho int breakstroke = 0, redraw = 0; if (texpaint) { - /* pick new face and image */ if (facesel_face_pick(s->me, mval, &newfaceindex, 0)) { ImBuf *ibuf; @@ -692,7 +830,7 @@ void imagepaint_paint(short mousebutton, short texpaint) } settings->imapaint.flag |= IMAGEPAINT_DRAWING; - free_imagepaint(); + undo_imagepaint_push_begin("Image Paint"); /* create painter and paint once */ painter= brush_painter_new(s.brush); @@ -741,6 +879,7 @@ void imagepaint_paint(short mousebutton, short texpaint) brush_painter_free(painter); imapaint_redraw(1, texpaint, s.image); + undo_imagepaint_push_end(); if (texpaint) { if (s.warnmultifile) diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c new file mode 100644 index 00000000000..8f887cd4756 --- /dev/null +++ b/source/blender/src/keyframing.c @@ -0,0 +1,1838 @@ +/** + * $Id: keyframing.c 14881 2008-05-18 10:41:42Z aligorith $ + * + * ***** 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 + * This is a new part of Blender (with some old code) + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" + +#include "DNA_listBase.h" +#include "DNA_ID.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" +#include "DNA_lamp_types.h" +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" +#include "DNA_vec_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" +#include "BKE_blender.h" +#include "BKE_main.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_ipo.h" +#include "BKE_object.h" + +#include "BIF_keyframing.h" +#include "BIF_butspace.h" +#include "BIF_editaction.h" +#include "BIF_editkey.h" +#include "BIF_interface.h" +#include "BIF_mywindow.h" +#include "BIF_poseobject.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_toolbox.h" +#include "BIF_toets.h" + +#include "BSE_editipo.h" +#include "BSE_node.h" +#include "BSE_time.h" +#include "BSE_view.h" + +#include "blendef.h" + +#include "PIL_time.h" /* sleep */ +#include "mydevice.h" + +/* ************************************************** */ +/* LOCAL TYPES AND DEFINES */ + +/* -------------- Keying Sets ------------------- */ + +/* keying set - a set of channels that will be keyframed together */ +// TODO: move this to a header to allow custom sets someday? +typedef struct bKeyingSet { + /* callback func to consider if keyingset should be included + * (by default, if this is undefined, item will be shown) + */ + short (*include_cb)(struct bKeyingSet *, const char *); + + char name[48]; /* name of keyingset */ + int blocktype; /* blocktype that all channels belong to */ // in future, this may be eliminated + short flag; /* flags to use when setting keyframes */ + + short chan_num; /* number of channels to insert keyframe in */ + short adrcodes[32]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */ +} bKeyingSet; + +/* keying set context - an array of keying sets and the number of them */ +typedef struct bKeyingContext { + bKeyingSet *keyingsets; /* array containing the keyingsets of interest */ + bKeyingSet *lastused; /* item that was chosen last time*/ + int tot; /* number of keyingsets in */ +} bKeyingContext; + + +/* ----------- Common KeyData Sources ------------ */ + +/* temporary struct to gather data combos to keyframe */ +typedef struct bCommonKeySrc { + struct bCommonKeySrc *next, *prev; + + /* general data/destination-source settings */ + ID *id; /* id-block this comes from */ + char *actname; /* name of action channel */ + char *constname; /* name of constraint channel */ + + /* general destination source settings */ + Ipo *ipo; /* ipo-block that id-block has (optional) */ + bAction *act; /* action-block that id-block has (optional) */ + + /* pose-level settings */ + bPoseChannel *pchan; /* pose channel */ + + /* buttons-window settings */ + int map; /* offset to apply to certain adrcodes */ +} bCommonKeySrc; + +/* ************************************************** */ +/* KEYFRAME INSERTION */ + +/* -------------- BezTriple Insertion -------------------- */ + +/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ +#define BEZT_INSERT_THRESH 0.00001 + +/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + const float frame= (item)? item->vec[1][0] : 0.0f; + + /* initialise replace-flag first */ + *replace= 0; + + /* sneaky optimisations (don't go through searching process if...): + * - keyframe to be added is to be added out of current bounds + * - keyframe to be added would replace one of the existing ones on bounds + */ + if ((arraylen <= 0) || ELEM(NULL, array, item)) { + printf("Warning: binarysearch_bezt_index encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum= array[0].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Keyframe */ + framenum= array[(arraylen-1)].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace= 1; + return (arraylen - 1); + } + else if (frame > framenum) + return arraylen; + } + + + /* most of the time, this loop is just to find where to put it + * 'loopbreaker' is just here to prevent infinite loops + */ + for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { + /* compute and get midpoint */ + int mid = (start + end) / 2; + float midfra= array[mid].vec[1][0]; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { + *replace = 1; + return mid; + } + + /* repeat in upper/lower half */ + if (frame > midfra) + start= mid + 1; + else if (frame < midfra) + end= mid - 1; + } + + /* print error if loop-limit exceeded */ + if (loopbreaker == (maxloop-1)) { + printf("Error: binarysearch_bezt_index was taking too long \n"); + + // include debug info + printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); + } + + /* not found, so return where to place it */ + return start; +} + +/* This function adds a given BezTriple to an IPO-Curve. It will allocate + * memory for the array if needed, and will insert the BezTriple into a + * suitable place in chronological order. + * + * NOTE: any recalculate of the IPO-Curve that needs to be done will need to + * be done by the caller. + */ +int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) +{ + BezTriple *newb; + int i= 0; + + if (icu->bezt == NULL) { + icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); + *(icu->bezt)= *bezt; + icu->totvert= 1; + } + else { + short replace = -1; + i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); + + if (replace) { + /* sanity check: 'i' may in rare cases exceed arraylen */ + if ((i >= 0) && (i < icu->totvert)) + *(icu->bezt + i) = *bezt; + } + else { + /* add new */ + newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); + + /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ + if (i > 0) + memcpy(newb, icu->bezt, i*sizeof(BezTriple)); + + /* add beztriple to paste at index i */ + *(newb + i)= *bezt; + + /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ + if (i < icu->totvert) + memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); + + /* replace (+ free) old with new */ + MEM_freeN(icu->bezt); + icu->bezt= newb; + + icu->totvert++; + } + } + + /* we need to return the index, so that some tools which do post-processing can + * detect where we added the BezTriple in the array + */ + return i; +} + +/* This function is a wrapper for insert_bezt_icu, and should be used when + * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere + * else yet. + * + * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. + */ +void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) +{ + BezTriple beztr; + int a, h1, h2; + + /* set all three points, for nicer start position */ + memset(&beztr, 0, sizeof(BezTriple)); + beztr.vec[0][0]= x; + beztr.vec[0][1]= y; + beztr.vec[1][0]= x; + beztr.vec[1][1]= y; + beztr.vec[2][0]= x; + beztr.vec[2][1]= y; + beztr.hide= IPO_BEZ; + beztr.f1= beztr.f2= beztr.f3= SELECT; + beztr.h1= beztr.h2= HD_AUTO; + + /* add temp beztriple to keyframes */ + a= insert_bezt_icu(icu, &beztr); + if (!fast) calchandles_ipocurve(icu); + + /* set handletype */ + if (icu->totvert > 2) { + BezTriple *bezt; + + h1= h2= HD_AUTO; + bezt= (icu->bezt + a); + + if (a > 0) h1= (bezt-1)->h2; + if (a < icu->totvert-1) h2= (bezt+1)->h1; + + bezt->h1= h1; + bezt->h2= h2; + + if (!fast) calchandles_ipocurve(icu); + } +} + +/* ------------------- Get Data ------------------------ */ + +/* Get pointer to use to get values from */ +// FIXME: this should not be possible with Data-API +static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) +{ + switch (blocktype) { + case ID_PO: /* posechannel */ + if (GS(id->name)==ID_OB) { + Object *ob= (Object *)id; + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + *vartype= IPO_FLOAT; + return get_pchan_ipo_poin(pchan, icu->adrcode); + } + } + break; + + case ID_CO: /* constraint */ + if ((GS(id->name)==ID_OB) && (constname && constname[0])) { + Object *ob= (Object *)id; + bConstraint *con; + + /* assume that we only want the influence (as only used for Constraint Channels) */ + if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { + for (con= ob->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + else if (ob->pose) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + } + } + break; + + case ID_OB: /* object */ + /* hack: layer channels for object need to be keyed WITHOUT localview flag... + * tsk... tsk... why must we just dump bitflags upon users :/ + */ + if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) { + Object *ob= (Object *)id; + static int layer = 0; + + /* init layer to be the object's layer var, then remove local view from it */ + layer = ob->lay; + layer &= 0xFFFFFF; + + /* return pointer to this static var + * - assumes that this pointer won't be stored for use later, so may not be threadsafe + * if multiple keyframe calls are made, but that is unlikely to happen in the near future + */ + return (void *)(&layer); + } + /* no break here for other ob channel-types - as they can be done normally */ + + default: /* normal data-source */ + return get_ipo_poin(id, icu, vartype); + } + + /* not valid... */ + return NULL; +} + + +/* -------------- 'Smarter' Keyframing Functions -------------------- */ +/* return codes for new_key_needed */ +enum { + KEYNEEDED_DONTADD = 0, + KEYNEEDED_JUSTADD, + KEYNEEDED_DELPREV, + KEYNEEDED_DELNEXT +} eKeyNeededStatus; + +/* This helper function determines whether a new keyframe is needed */ +/* Cases where keyframes should not be added: + * 1. Keyframe to be added bewteen two keyframes with similar values + * 2. Keyframe to be added on frame where two keyframes are already situated + * 3. Keyframe lies at point that intersects the linear line between two keyframes + */ +static short new_key_needed (IpoCurve *icu, float cFrame, float nValue) +{ + BezTriple *bezt=NULL, *prev=NULL; + int totCount, i; + float valA = 0.0f, valB = 0.0f; + + /* safety checking */ + if (icu == NULL) return KEYNEEDED_JUSTADD; + totCount= icu->totvert; + if (totCount == 0) return KEYNEEDED_JUSTADD; + + /* loop through checking if any are the same */ + bezt= icu->bezt; + for (i=0; ivec[1][0]; + beztVal= bezt->vec[1][1]; + + if (prev) { + /* there is a keyframe before the one currently being examined */ + + /* get previous time+value */ + prevPosi= prev->vec[1][0]; + prevVal= prev->vec[1][1]; + + /* keyframe to be added at point where there are already two similar points? */ + if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { + return KEYNEEDED_DONTADD; + } + + /* keyframe between prev+current points ? */ + if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { + /* is the value of keyframe to be added the same as keyframes on either side ? */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { + return KEYNEEDED_DONTADD; + } + else { + float realVal; + + /* get real value of curve at that point */ + realVal= eval_icu(icu, cFrame); + + /* compare whether it's the same as proposed */ + if (IS_EQ(realVal, nValue)) + return KEYNEEDED_DONTADD; + else + return KEYNEEDED_JUSTADD; + } + } + + /* new keyframe before prev beztriple? */ + if (cFrame < prevPosi) { + /* A new keyframe will be added. However, whether the previous beztriple + * stays around or not depends on whether the values of previous/current + * beztriples and new keyframe are the same. + */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) + return KEYNEEDED_DELNEXT; + else + return KEYNEEDED_JUSTADD; + } + } + else { + /* just add a keyframe if there's only one keyframe + * and the new one occurs before the exisiting one does. + */ + if ((cFrame < beztPosi) && (totCount==1)) + return KEYNEEDED_JUSTADD; + } + + /* continue. frame to do not yet passed (or other conditions not met) */ + if (i < (totCount-1)) { + prev= bezt; + bezt++; + } + else + break; + } + + /* Frame in which to add a new-keyframe occurs after all other keys + * -> If there are at least two existing keyframes, then if the values of the + * last two keyframes and the new-keyframe match, the last existing keyframe + * gets deleted as it is no longer required. + * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last + * keyframe is not equal to last keyframe. + */ + bezt= (icu->bezt + (icu->totvert - 1)); + valA= bezt->vec[1][1]; + + if (prev) + valB= prev->vec[1][1]; + else + valB= bezt->vec[1][1] + 1.0f; + + if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) + return KEYNEEDED_DELPREV; + else + return KEYNEEDED_JUSTADD; +} + +/* ------------------ 'Visual' Keyframing Functions ------------------ */ + +/* internal status codes for visualkey_can_use */ +enum { + VISUALKEY_NONE = 0, + VISUALKEY_LOC, + VISUALKEY_ROT +}; + +/* This helper function determines if visual-keyframing should be used when + * inserting keyframes for the given channel. As visual-keyframing only works + * on Object and Pose-Channel blocks, this should only get called for those + * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying + * settings is on. + */ +static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode) +{ + Object *ob= NULL; + bConstraint *con= NULL; + short searchtype= VISUALKEY_NONE; + + /* validate data */ + if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO))) + return 0; + + /* get first constraint and determine type of keyframe constraints to check for*/ + ob= (Object *)id; + + if (blocktype == ID_OB) { + con= ob->constraints.first; + + if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) + searchtype= VISUALKEY_LOC; + else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) + searchtype= VISUALKEY_ROT; + } + else if (blocktype == ID_PO) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + con= pchan->constraints.first; + + if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) + searchtype= VISUALKEY_LOC; + else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) + searchtype= VISUALKEY_ROT; + } + + /* only search if a searchtype and initial constraint are available */ + if (searchtype && con) { + for (; con; con= con->next) { + /* only consider constraint if it is not disabled, and has influence */ + if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->enforce == 0.0f) continue; + + /* some constraints may alter these transforms */ + switch (con->type) { + /* multi-transform constraints */ + case CONSTRAINT_TYPE_CHILDOF: + return 1; + case CONSTRAINT_TYPE_TRANSFORM: + return 1; + case CONSTRAINT_TYPE_FOLLOWPATH: + return 1; + + /* single-transform constraits */ + case CONSTRAINT_TYPE_TRACKTO: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_ROTLIMIT: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_LOCLIMIT: + if (searchtype==VISUALKEY_LOC) return 1; + break; + case CONSTRAINT_TYPE_ROTLIKE: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_LOCLIKE: + if (searchtype==VISUALKEY_LOC) return 1; + break; + case CONSTRAINT_TYPE_LOCKTRACK: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_MINMAX: + if (searchtype==VISUALKEY_LOC) return 1; + break; + + default: + break; + } + } + } + + /* when some condition is met, this function returns, so here it can be 0 */ + return 0; +} + +/* This helper function extracts the value to use for visual-keyframing + * In the event that it is not possible to perform visual keying, try to fall-back + * to using the poin method. Assumes that all data it has been passed is valid. + */ +static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu) +{ + Object *ob; + void *poin = NULL; + int index, vartype; + + /* validate situtation */ + if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0)) + return 0.0f; + + /* get object */ + ob= (Object *)id; + + /* only valid for objects or posechannels */ + if (blocktype == ID_OB) { + /* parented objects are not supported, as the effects of the parent + * are included in the matrix, which kindof beats the point + */ + if ((ob) && (ob->parent==NULL)) { + /* only Location or Rotation keyframes are supported now */ + if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) { + /* assumes that OB_LOC_Z > OB_LOC_Y > OB_LOC_X */ + index= adrcode - OB_LOC_X; + + return ob->obmat[3][index]; + } + else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) { + float eul[3]; + + /* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */ + index= adrcode - OB_ROT_X; + + Mat4ToEul(ob->obmat, eul); + return eul[index]*(5.72958); + } + } + } + else if (blocktype == ID_PO) { + bPoseChannel *pchan; + float tmat[4][4]; + + /* get data to use */ + pchan= get_pose_channel(ob->pose, actname); + + /* Although it is not strictly required for this particular space conversion, + * arg1 must not be null, as there is a null check for the other conversions to + * be safe. Therefore, the active object is passed here, and in many cases, this + * will be what owns the pose-channel that is getting this anyway. + */ + Mat4CpyMat4(tmat, pchan->pose_mat); + constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + + /* Loc, Rot/Quat keyframes are supported... */ + if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) { + /* assumes that AC_LOC_Z > AC_LOC_Y > AC_LOC_X */ + index= adrcode - AC_LOC_X; + + /* only use for non-connected bones */ + if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED)) + return tmat[3][index]; + else if (pchan->bone->parent == NULL) + return tmat[3][index]; + } + else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) { + float tmat[4][4], trimat[3][3], quat[4]; + + /* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */ + index= adrcode - AC_QUAT_W; + + Mat3CpyMat4(trimat, tmat); + Mat3ToQuat_is_ok(trimat, quat); + + return quat[index]; + } + } + + /* as the function hasn't returned yet, try reading from poin */ + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + if (poin) + return read_ipo_poin(poin, vartype); + else + return 0.0; +} + + +/* ------------------------- Insert Key API ------------------------- */ + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, + * and extra keyframe filtering. + */ +short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) +{ + IpoCurve *icu; + + /* get ipo-curve */ + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1); + + /* only continue if we have an ipo-curve to add keyframe to */ + if (icu) { + float cfra = frame_to_float(CFRA); + float curval= 0.0f; + void *poin = NULL; + int vartype; + + /* apply special time tweaking */ + if (GS(id->name) == ID_OB) { + Object *ob= (Object *)id; + + /* apply NLA-scaling (if applicable) */ + if (actname && actname[0]) + cfra= get_action_frame(ob, cfra); + + /* ancient time-offset cruft */ + if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* get pointer to data to read from */ + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + if (poin == NULL) return 0; + + /* obtain value to give keyframe */ + if ( (flag & INSERTKEY_MATRIX) && + (visualkey_can_use(id, blocktype, actname, constname, adrcode)) ) + { + /* visual-keying is only available for object and pchan datablocks, as + * it works by keyframing using a value extracted from the final matrix + * instead of using the kt system to extract a value. + */ + curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu); + } + else { + /* use kt's read_poin function to extract value (kt->read_poin should + * exist in all cases, but it never hurts to check) + */ + curval= read_ipo_poin(poin, vartype); + } + + /* only insert keyframes where they are needed */ + if (flag & INSERTKEY_NEEDED) { + short insert_mode; + + /* check whether this curve really needs a new keyframe */ + insert_mode= new_key_needed(icu, cfra, curval); + + /* insert new keyframe at current frame */ + if (insert_mode) + insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); + + /* delete keyframe immediately before/after newly added */ + switch (insert_mode) { + case KEYNEEDED_DELPREV: + delete_icu_key(icu, icu->totvert-2, 1); + break; + case KEYNEEDED_DELNEXT: + delete_icu_key(icu, 1, 1); + break; + } + } + else { + /* just insert keyframe */ + insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); + } + + /* return success */ + return 1; + } + + /* return failure */ + return 0; +} + + +/* ************************************************** */ +/* KEYFRAME DELETION */ + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will delete a keyframe at the current frame. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe deletion. These include the quick refresh options. + */ +short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) +{ + Ipo *ipo; + IpoCurve *icu; + + /* get ipo-curve + * Note: here is one of the places where we don't want new ipo + ipo-curve added! + * so 'add' var must be 0 + */ + ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0); + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0); + + /* only continue if we have an ipo-curve to remove keyframes from */ + if (icu) { + BezTriple bezt; + float cfra = frame_to_float(CFRA); + short found = -1; + int i; + + /* apply special time tweaking */ + if (GS(id->name) == ID_OB) { + Object *ob= (Object *)id; + + /* apply NLA-scaling (if applicable) */ + if (actname && actname[0]) + cfra= get_action_frame(ob, cfra); + + /* ancient time-offset cruft */ + if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* only need to set bezt->vec[1][0], as that's all binarysearch uses */ + memset(&bezt, 0, sizeof(BezTriple)); + bezt.vec[1][0]= cfra; + + /* try to find index of beztriple to get rid of */ + i = binarysearch_bezt_index(icu->bezt, &bezt, icu->totvert, &found); + if (found) { + /* delete the key at the index (will sanity check + do recalc afterwards ) */ + delete_icu_key(icu, i, 1); + + /* Only delete curve too if there isn't an ipo-driver still hanging around on an empty curve */ + if (icu->totvert==0 && icu->driver==NULL) { + BLI_remlink(&ipo->curve, icu); + free_ipo_curve(icu); + } + + /* return success */ + return 1; + } + } + + /* return failure */ + return 0; +} + +/* ************************************************** */ +/* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */ + + +/* ------------- KeyingSet Defines ------------ */ +/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */ + +/* macro for defining keyingset contexts */ +#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)} + +/* --- */ + +/* check if option not available for deleting keys */ +static short incl_non_del_keys (bKeyingSet *ks, const char mode[]) +{ + /* as optimisation, assume that it is sufficient to check only first letter + * of mode (int comparison should be faster than string!) + */ + //if (strcmp(mode, "Delete")==0) + if (mode && mode[0]=='D') + return 0; + + return 1; +} + +/* Object KeyingSets ------ */ + +/* check if include shapekey entry */ +static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[]) +{ + Object *ob= (G.obedit)? (G.obedit) : (OBACT); + char *newname= NULL; + + /* not available for delete mode */ + if (strcmp(mode, "Delete")==0) + return 0; + + /* check if is geom object that can get shapekeys */ + switch (ob->type) { + /* geometry? */ + case OB_MESH: newname= "Mesh"; break; + case OB_CURVE: newname= "Curve"; break; + case OB_SURF: newname= "Surface"; break; + case OB_LATTICE: newname= "Lattice"; break; + + /* not geometry! */ + default: + return 0; + } + + /* if ks is shapekey entry (this could be callled for separator before too!) */ + if (ks->flag == -3) + sprintf(ks->name, newname); + + /* if it gets here, it's ok */ + return 1; +} + +/* array for object keyingset defines */ +bKeyingSet defks_v3d_object[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "LocRot", ID_OB, 0, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "LocScale", ID_OB, 0, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "LocRotScale", ID_OB, 0, 9, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "RotScale", ID_OB, 0, 6, + {OB_ROT_X,OB_ROT_Y,OB_ROT_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator + + {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option... + {NULL, "Available", ID_OB, -2, 0, {0}}, + + {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry) + {incl_v3d_ob_shapekey, "", ID_OB, -3, 0, {0}} +}; + +/* PoseChannel KeyingSets ------ */ + +/* array for posechannel keyingset defines */ +bKeyingSet defks_v3d_pchan[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "LocRot", ID_PO, 0, 7, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, + AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "LocScale", ID_PO, 0, 6, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, + AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "LocRotScale", ID_PO, 0, 10, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,AC_QUAT_X, + AC_QUAT_Y,AC_QUAT_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "RotScale", ID_PO, 0, 7, + {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z, + AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator + + {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, + AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_PO, -2, 0, {0}} +}; + +/* Material KeyingSets ------ */ + +/* array for material keyingset defines */ +bKeyingSet defks_buts_shading_mat[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}}, + {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}}, + {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}}, + {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "All Color", ID_MA, 0, 18, + {MA_COL_R,MA_COL_G,MA_COL_B, + MA_ALPHA,MA_HASIZE, MA_MODE, + MA_SPEC_R,MA_SPEC_G,MA_SPEC_B, + MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD, + MA_MODE,MA_TRANSLU,MA_ADD}}, + + {NULL, "All Mirror", ID_MA, 0, 5, + {MA_RAYM,MA_FRESMIR,MA_FRESMIRI, + MA_FRESTRA,MA_FRESTRAI}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Ofs", ID_MA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_MA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_MA, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_MA, -2, 0, {0}} +}; + +/* World KeyingSets ------ */ + +/* array for world keyingset defines */ +bKeyingSet defks_buts_shading_wo[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}}, + {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}}, + {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}}, + + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Ofs", ID_WO, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_WO, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_WO, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_WO, -2, 0, {0}} +}; + +/* Lamp KeyingSets ------ */ + +/* array for lamp keyingset defines */ +bKeyingSet defks_buts_shading_la[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}}, + {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}}, + {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Ofs", ID_LA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_LA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_LA, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_LA, -2, 0, {0}} +}; + +/* Texture KeyingSets ------ */ + +/* array for texture keyingset defines */ +bKeyingSet defks_buts_shading_tex[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Clouds", ID_TE, 0, 5, + {TE_NSIZE,TE_NDEPTH,TE_NTYPE, + TE_MG_TYP,TE_N_BAS1}}, + + {NULL, "Marble", ID_TE, 0, 7, + {TE_NSIZE,TE_NDEPTH,TE_NTYPE, + TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, + + {NULL, "Stucci", ID_TE, 0, 5, + {TE_NSIZE,TE_NTYPE,TE_TURB, + TE_MG_TYP,TE_N_BAS1}}, + + {NULL, "Wood", ID_TE, 0, 6, + {TE_NSIZE,TE_NTYPE,TE_TURB, + TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, + + {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}}, + + {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}}, + + {NULL, "Musgrave", ID_TE, 0, 6, + {TE_MG_TYP,TE_MGH,TE_MG_LAC, + TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}}, + + {NULL, "Voronoi", ID_TE, 0, 9, + {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4, + TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT, + TE_ISCA,TE_NSIZE}}, + + {NULL, "Distorted Noise", ID_TE, 0, 4, + {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}}, + + {NULL, "Color Filter", ID_TE, 0, 5, + {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_TE, -2, 0, {0}} +}; + +/* Object Buttons KeyingSets ------ */ + +/* check if include particles entry */ +static short incl_buts_ob (bKeyingSet *ks, const char mode[]) +{ + Object *ob= OBACT; + /* only if object is mesh type */ + return (ob->type == OB_MESH); +} + +/* array for texture keyingset defines */ +bKeyingSet defks_buts_object[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}}, + {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}}, + {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}}, + {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too! +}; + +/* Camera Buttons KeyingSets ------ */ + +/* check if include internal-renderer entry */ +static short incl_buts_cam1 (bKeyingSet *ks, const char mode[]) +{ + /* only if renderer is internal renderer */ + return (G.scene->r.renderer==R_INTERN); +} + +/* check if include external-renderer entry */ +static short incl_buts_cam2 (bKeyingSet *ks, const char mode[]) +{ + /* only if renderer is internal renderer */ + return (G.scene->r.renderer!=R_INTERN); +} + +/* array for camera keyingset defines */ +bKeyingSet defks_buts_cam[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}}, + {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}}, + {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + + {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}}, + {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_CA, -2, 0, {0}} +}; + +/* --- */ + +/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */ +bKeyingContext ks_contexts[] = +{ + KSC_TEMPLATE(v3d_object), + KSC_TEMPLATE(v3d_pchan), + + KSC_TEMPLATE(buts_shading_mat), + KSC_TEMPLATE(buts_shading_wo), + KSC_TEMPLATE(buts_shading_la), + KSC_TEMPLATE(buts_shading_tex), + + KSC_TEMPLATE(buts_object), + KSC_TEMPLATE(buts_cam) +}; + +/* Keying Context Enumeration - Must keep in sync with definitions*/ +typedef enum eKS_Contexts { + KSC_V3D_OBJECT = 0, + KSC_V3D_PCHAN, + + KSC_BUTS_MAT, + KSC_BUTS_WO, + KSC_BUTS_LA, + KSC_BUTS_TEX, + + KSC_BUTS_OB, + KSC_BUTS_CAM, + + /* make sure this last one remains untouched! */ + KSC_TOT_TYPES +} eKS_Contexts; + + +/* ---------------- KeyingSet Tools ------------------- */ + +/* helper for commonkey_context_get() - get keyingsets for 3d-view */ +static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) +{ + Object *ob; + IpoCurve *icu; + + if ((OBACT) && (OBACT->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + + /* pose-level */ + ob= OBACT; + *ksc= &ks_contexts[KSC_V3D_PCHAN]; + set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ + + /* loop through posechannels */ + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { + if (pchan->flag & POSE_KEY) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to, and action */ + cks->id= (ID *)ob; + cks->act= ob->action; + + /* set pchan */ + cks->pchan= pchan; + cks->actname= pchan->name; + } + } + } + else { + Base *base; + + /* object-level */ + *ksc= &ks_contexts[KSC_V3D_OBJECT]; + + /* loop through bases */ + for (base= FIRSTBASE; base; base= base->next) { + if (TESTBASELIB(base)) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + ob= base->object; + cks->id= (ID *)ob; + + /* when ob's keyframes are in an action, default to using 'Object' as achan name */ + if (ob->ipoflag & OB_ACTION_OB) + cks->actname= "Object"; + + /* set ipo-flags */ + // TODO: add checks for lib-linked data + if ((ob->ipo) || (ob->action)) { + if (ob->ipo) { + cks->ipo= ob->ipo; + } + else { + bActionChannel *achan; + + cks->act= ob->action; + achan= get_action_channel(ob->action, cks->actname); + + if (achan && achan->ipo) + cks->ipo= achan->ipo; + } + + /* deselect all ipo-curves */ + for (icu= cks->ipo->curve.first; icu; icu= icu->next) { + icu->flag &= ~IPO_SELECT; + } + } + } + } + } +} + +/* helper for commonkey_context_get() - get keyingsets for buttons window */ +static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) +{ + bCommonKeySrc *cks; + + /* check on tab-type */ + switch (G.buts->mainb) { + case CONTEXT_SHADING: /* ------------- Shading buttons ---------------- */ + /* subtabs include "Material", "Texture", "Lamp", "World"*/ + switch (G.buts->tab[CONTEXT_SHADING]) { + case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */ + { + Material *ma= editnode_get_active_material(G.buts->lockpoin); + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)ma; + cks->ipo= ma->ipo; + cks->map= texchannel_to_adrcode(ma->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_MAT]; + return; + } + break; + case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */ + { + World *wo= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)wo; + cks->ipo= wo->ipo; + cks->map= texchannel_to_adrcode(wo->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_WO]; + return; + } + break; + case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */ + { + Lamp *la= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)la; + cks->ipo= la->ipo; + cks->map= texchannel_to_adrcode(la->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_LA]; + return; + } + break; + case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */ + { + Tex *tex= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)tex; + cks->ipo= tex->ipo; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_TEX]; + return; + } + break; + } + break; + + case CONTEXT_OBJECT: /* ------------- Object buttons ---------------- */ + { + Object *ob= OBACT; + + if (ob) { + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + cks->id= (ID *)ob; + cks->ipo= ob->ipo; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_OB]; + return; + } + } + break; + + case CONTEXT_EDITING: /* ------------- Editing buttons ---------------- */ + { + Object *ob= OBACT; + + if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */ + Camera *ca= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + cks->id= (ID *)ca; + cks->ipo= ca->ipo; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_CAM]; + return; + } + } + break; + } + + /* if nothing happened... */ + *ksc= NULL; +} + + +/* get keyingsets for appropriate context */ +static void commonkey_context_get (ListBase *sources, bKeyingContext **ksc) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + commonkey_context_getv3d(sources, ksc); + break; + + /* buttons view */ + case SPACE_BUTS: + commonkey_context_getsbuts(sources, ksc); + break; + } +} + +/* flush updates after all operations */ +static void commonkey_context_finish (ListBase *sources) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + { + /* either pose or object level */ + if (OBACT && (OBACT->pose)) { + Object *ob= OBACT; + + /* recalculate ipo handles, etc. */ + if (ob->action) + remake_action_ipos(ob->action); + + /* recalculate bone-paths on adding new keyframe? */ + // TODO: currently, there is no setting to turn this on/off globally + if (ob->pose->flag & POSE_RECALCPATHS) + pose_recalculate_paths(ob); + } + else { + bCommonKeySrc *cks; + + /* loop over bases (as seen in sources) */ + for (cks= sources->first; cks; cks= cks->next) { + Object *ob= (Object *)cks->id; + + /* simply set recalc flag */ + ob->recalc |= OB_RECALC_OB; + } + } + } + break; + } +} + +/* flush refreshes after undo */ +static void commonkey_context_refresh (void) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + { + /* do refreshes */ + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); + + allspace(REMAKEIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWMARKER, 0); + } + break; + } +} + +/* --- */ + +/* Build menu-string of available keying-sets (allocates memory for string) + * NOTE: mode must not be longer than 64 chars + */ +static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48]) +{ + DynStr *pupds= BLI_dynstr_new(); + bKeyingSet *ks; + char buf[64]; + char *str; + int i, n; + + /* add title first */ + BLI_snprintf(buf, 64, "%s Key %%t|", mode); + BLI_dynstr_append(pupds, buf); + + /* loop through keyingsets, adding them */ + for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) { + /* check if keyingset can be used */ + if (ks->flag == -1) { + /* optional separator? */ + if (ks->include_cb) { + if (ks->include_cb(ks, mode)) { + BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + else { + BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) { + /* entry can be included */ + BLI_dynstr_append(pupds, ks->name); + + /* check if special "shapekey" entry */ + if (ks->flag == -3) + BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") ); + else + BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + + /* convert to normal MEM_malloc'd string */ + str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); + + return str; +} + +/* Get the keying set that was chosen by the user from the menu */ +static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index) +{ + /* check if index is valid */ + if (ELEM(NULL, ksc, ksc->keyingsets)) + return NULL; + if ((index < 1) || (index > ksc->tot)) + return NULL; + + /* index starts from 1, and should directly correspond to keyingset in array */ + return (bKeyingSet *)(ksc->keyingsets + (index - 1)); +} + +/* ---------------- Keyframe Management API -------------------- */ + +/* mode for common_modifykey */ +enum { + COMMONKEY_MODE_INSERT = 0, + COMMONKEY_MODE_DELETE, +} eCommonModifyKey_Modes; + +/* Display a menu for handling the insertion of keyframes based on the active view */ +// TODO: add back an option for repeating last keytype +void common_modifykey (short mode) +{ + ListBase dsources = {NULL, NULL}; + bKeyingContext *ksc= NULL; + bCommonKeySrc *cks; + bKeyingSet *ks = NULL; + char *menustr, buf[64]; + short menu_nr; + + /* check if mode is valid */ + if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0) + return; + + /* delegate to other functions or get keyingsets to use */ + switch (curarea->spacetype) { + /* spaces with their own methods */ + case SPACE_IPO: + if (mode == COMMONKEY_MODE_INSERT) + insertkey_editipo(); + return; + case SPACE_ACTION: + if (mode == COMMONKEY_MODE_INSERT) + insertkey_action(); + return; + + /* TODO: based on UI elements? will that even be handled here??? */ + + /* default - check per view */ + default: + /* get the keyingsets and the data to add keyframes to */ + commonkey_context_get(&dsources, &ksc); + break; + } + + /* check that there is data to operate on */ + if (ELEM(NULL, dsources.first, ksc)) { + BLI_freelistN(&dsources); + return; + } + + /* get menu and process it */ + if (mode == COMMONKEY_MODE_DELETE) + menustr= build_keyingsets_menu(ksc, "Delete"); + else + menustr= build_keyingsets_menu(ksc, "Insert"); + menu_nr= pupmenu(menustr); + if (menustr) MEM_freeN(menustr); + + /* no item selected or shapekey entry? */ + if (menu_nr < 1) { + /* free temp sources */ + BLI_freelistN(&dsources); + + /* check if insert new shapekey */ + if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT)) + insert_shapekey(OBACT); + else + ksc->lastused= NULL; + + return; + } + else { + /* try to get keyingset */ + ks= get_keyingset_fromcontext(ksc, menu_nr); + + if (ks == NULL) { + BLI_freelistN(&dsources); + return; + } + } + + /* loop over each destination, applying the keying set */ + for (cks= dsources.first; cks; cks= cks->next) { + short success= 0; + + /* special hacks for 'available' option */ + if (ks->flag == -2) { + IpoCurve *icu= NULL, *icn= NULL; + + /* get first IPO-curve */ + if (cks->act && cks->actname) { + bActionChannel *achan= get_action_channel(cks->act, cks->actname); + + // FIXME: what about constraint channels? + if (achan && achan->ipo) + icu= achan->ipo->curve.first; + } + else + icu= cks->ipo->curve.first; + + /* we get adrcodes directly from IPO curves (see method below...) */ + for (; icu; icu= icn) { + short flag; + + /* get next ipo-curve in case current is deleted */ + icn= icu->next; + + /* insert mode or delete mode */ + if (mode == COMMONKEY_MODE_DELETE) { + /* local flags only add on to global flags */ + flag = 0; + + /* delete keyframe */ + success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); + } + else { + /* local flags only add on to global flags */ + flag = ks->flag; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframe */ + success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); + } + } + } + else { + int i; + + /* loop over channels available in keyingset */ + for (i=0; i < ks->chan_num; i++) { + short flag, adrcode; + + /* get adrcode + * - certain adrcodes (for MTEX channels need special offsets) // BAD CRUFT!!! + */ + adrcode= ks->adrcodes[i]; + if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) { + switch (adrcode) { + case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z: + case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z: + case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR: + case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP: + adrcode += cks->map; + break; + } + } + + /* insert mode or delete mode */ + if (mode == COMMONKEY_MODE_DELETE) { + /* local flags only add on to global flags */ + flag = 0; + + /* delete keyframe */ + success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); + } + else { + /* local flags only add on to global flags */ + flag = ks->flag; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframe */ + success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); + } + } + } + + /* special handling for some key-sources */ + if (success) { + /* set pose recalc-paths flag */ + if (cks->pchan) { + Object *ob= (Object *)cks->id; + bPoseChannel *pchan= cks->pchan; + + /* set flag to trigger path recalc */ + if (pchan->path) + ob->pose->flag |= POSE_RECALCPATHS; + + /* clear unkeyed flag (it doesn't matter if it's set or not) */ + if (pchan->bone) + pchan->bone->flag &= ~BONE_UNKEYED; + } + } + } + + /* apply post-keying flushes for this data sources */ + commonkey_context_finish(&dsources); + ksc->lastused= ks; + + /* free temp data */ + BLI_freelistN(&dsources); + + /* undo pushes */ + if (mode == COMMONKEY_MODE_DELETE) + BLI_snprintf(buf, 64, "Delete %s Key", ks->name); + else + BLI_snprintf(buf, 64, "Insert %s Key", ks->name); + BIF_undo_push(buf); + + /* queue updates for contexts */ + commonkey_context_refresh(); +} + +/* ---- */ + +/* used to insert keyframes from any view */ +void common_insertkey (void) +{ + common_modifykey(COMMONKEY_MODE_INSERT); +} + +/* used to insert keyframes from any view */ +void common_deletekey (void) +{ + common_modifykey(COMMONKEY_MODE_DELETE); +} + +/* ************************************************** */ diff --git a/source/blender/src/keyval.c b/source/blender/src/keyval.c index dab4b4ae839..5a2ba531821 100644 --- a/source/blender/src/keyval.c +++ b/source/blender/src/keyval.c @@ -27,6 +27,11 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "stdio.h" +#include "ctype.h" +#include "string.h" + +#include "BKE_global.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BIF_keyval.h" @@ -349,3 +354,193 @@ char *key_event_to_string(unsigned short event) return ""; } + +/* + * Decodes key combination strings [qual1+[qual2+[...]]]keyname + * The '+'s may be replaced by '-' or ' ' characters to support different + * formats. No additional whitespace is allowed. The keyname may be an internal + * name, like "RETKEY", or a more common name, like "Return". Decoding is case- + * insensitive. + * + * Example strings: "Ctrl+L", "ALT-ESC", "Shift A" + * + * Returns 1 if successful. + */ +int decode_key_string(char *str, unsigned short *key, unsigned short *qual) +{ + int i, prev, len, invalid=0; + + len= strlen(str); + *key= *qual= 0; + + /* Convert to upper case */ + for (i=0; i='A' && str[prev]<='Z') { + *key= str[prev]-'A'+AKEY; + } else if (str[prev]>='0' && str[prev]<='9') { + *key= str[prev]-'0'+ZEROKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) { + *key= ZEROKEY; + } else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) { + *key= ONEKEY; + } else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) { + *key= TWOKEY; + } else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) { + *key= THREEKEY; + } else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) { + *key= FOURKEY; + } else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) { + *key= FIVEKEY; + } else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) { + *key= SIXKEY; + } else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) { + *key= SEVENKEY; + } else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) { + *key= EIGHTKEY; + } else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) { + *key= NINEKEY; + + } else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) { + *key= ESCKEY; + } else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) { + *key= TABKEY; + } else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) { + *key= RETKEY; + } else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) { + *key= SPACEKEY; + } else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) { + *key= LINEFEEDKEY; + } else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) { + *key= BACKSPACEKEY; + } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { + *key= DELKEY; + + } else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) { + *key= SEMICOLONKEY; + } else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) { + *key= PERIODKEY; + } else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) { + *key= COMMAKEY; + } else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) { + *key= QUOTEKEY; + } else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) { + *key= ACCENTGRAVEKEY; + } else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) { + *key= MINUSKEY; + } else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) { + *key= SLASHKEY; + } else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) { + *key= BACKSLASHKEY; + } else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) { + *key= EQUALKEY; + } else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) { + *key= LEFTBRACKETKEY; + } else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) { + *key= RIGHTBRACKETKEY; + } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { + *key= DELKEY; + + } else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) { + *key= LEFTARROWKEY; + } else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) { + *key= DOWNARROWKEY; + } else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) { + *key= RIGHTARROWKEY; + } else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) { + *key= UPARROWKEY; + + } else if (!strncmp(str+prev, "PAD", 3)) { + + if (len-prev<=4) { + + if (str[prev]>='0' && str[prev]<='9') { + *key= str[prev]-'0'+ZEROKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) { + *key= PADPERIOD; + } else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) { + *key= PADSLASHKEY; + } else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) { + *key= PADASTERKEY; + } else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) { + *key= PADMINUS; + } else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) { + *key= PADENTER; + } else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) { + *key= PADPLUSKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) { + *key= F1KEY; + } else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) { + *key= F2KEY; + } else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) { + *key= F3KEY; + } else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) { + *key= F4KEY; + } else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) { + *key= F5KEY; + } else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) { + *key= F6KEY; + } else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) { + *key= F7KEY; + } else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) { + *key= F8KEY; + } else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) { + *key= F9KEY; + } else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) { + *key= F10KEY; + } else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) { + *key= F11KEY; + } else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) { + *key= F12KEY; + + } else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) { + *key= PAUSEKEY; + } else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) { + *key= INSERTKEY; + } else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) { + *key= HOMEKEY; + } else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) { + *key= PAGEUPKEY; + } else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) { + *key= PAGEDOWNKEY; + } else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) { + *key= ENDKEY; + + } else { + invalid= 1; + } + + if (!invalid && *key) { + return 1; + } + + return 0; +} diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index 2de6367c9ad..96349e8fb98 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -204,7 +204,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int v3= sys->verts[i3]; /* instead of *0.5 we divided by the number of faces of the edge, it still - needs to be varified that this is indeed the correct thing to do! */ + needs to be verified that this is indeed the correct thing to do! */ t1= cotan_weight(v1, v2, v3)/laplacian_edge_count(sys->edgehash, i2, i3); t2= cotan_weight(v2, v3, v1)/laplacian_edge_count(sys->edgehash, i3, i1); t3= cotan_weight(v3, v1, v2)/laplacian_edge_count(sys->edgehash, i1, i2); @@ -229,7 +229,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int } } -LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) +LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) { LaplacianSystem *sys; @@ -248,6 +248,8 @@ LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) /* create opennl context */ nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, totvert); + if(lsq) + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); sys->context= nlGetCurrent(); @@ -631,7 +633,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, } /* create laplacian */ - sys = laplacian_system_construct_begin(me->totvert, totface); + sys = laplacian_system_construct_begin(me->totvert, totface, 1); sys->heat.mesh= me; sys->heat.verts= verts; @@ -933,7 +935,7 @@ void rigid_deform_begin(EditMesh *em) } /* create laplacian */ - sys = laplacian_system_construct_begin(totvert, totface); + sys = laplacian_system_construct_begin(totvert, totface, 0); sys->rigid.mesh= em; sys->rigid.R = MEM_callocN(sizeof(float)*3*3*totvert, "RigidDeformR"); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 99833625baa..eed7737c26d 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -84,7 +84,6 @@ void sort_faces(void); #include "BIF_toolbox.h" #include "BIF_editconstraint.h" -#include "BDR_drawmesh.h" #include "BDR_editobject.h" #include "BDR_editface.h" #include "BDR_sculptmode.h" @@ -107,6 +106,8 @@ void sort_faces(void); #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "GPU_draw.h" + #include "BLO_sys_types.h" // for intptr_t support /* from rendercode.c */ @@ -1130,7 +1131,7 @@ void objects_bake_render(short event, char **error_msg) if(ima->ok==IMA_OK_LOADED) { ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { - free_realtime_image(ima); + GPU_free_image(ima); imb_freemipmapImBuf(ibuf); } } diff --git a/source/blender/src/mywindow.c b/source/blender/src/mywindow.c index cb8d233c341..6166ab18766 100644 --- a/source/blender/src/mywindow.c +++ b/source/blender/src/mywindow.c @@ -604,18 +604,6 @@ int framebuffer_to_index(unsigned int col) /* ********** END MY WINDOW ************** */ -#ifdef WIN32 -static int is_a_really_crappy_nvidia_card(void) { - static int well_is_it= -1; - - /* Do you understand the implication? Do you? */ - if (well_is_it==-1) - well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); - - return well_is_it; -} -#endif - void myswapbuffers(void) { ScrArea *sa; diff --git a/source/blender/src/playanim.c b/source/blender/src/playanim.c index 7a61368b4cd..8421101f66c 100644 --- a/source/blender/src/playanim.c +++ b/source/blender/src/playanim.c @@ -45,15 +45,6 @@ #endif #include "MEM_guardedalloc.h" -#ifdef WITH_QUICKTIME -#ifdef _WIN32 -#include -#include -#elif defined(__APPLE__) -#include -#endif /* __APPLE__ */ -#endif /* WITH_QUICKTIME */ - #include "PIL_time.h" #include @@ -77,6 +68,15 @@ #include "BMF_Api.h" +#ifdef WITH_QUICKTIME +#ifdef _WIN32 +#include +#include +#elif defined(__APPLE__) +#include +#endif /* __APPLE__ */ +#endif /* WITH_QUICKTIME */ + #include "playanim_ext.h" #include "mydevice.h" #include "blendef.h" @@ -346,6 +346,7 @@ void playanim(int argc, char **argv) int start_x= 0, start_y= 0; int sfra= -1; int efra= -1; + int totblock; while (argc > 1) { if (argv[1][0] == '-'){ @@ -823,6 +824,7 @@ void playanim(int argc, char **argv) free_blender(); window_destroy(g_window); + totblock= MEM_get_memory_blocks_in_use(); if(totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_printmemlist(); diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 6aeef7c75c2..ff54ad31e22 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -61,7 +61,7 @@ #include "BKE_global.h" #include "BKE_utildefines.h" -//#include "BIF_keyframing.h" +#include "BIF_keyframing.h" #include "BSE_editipo.h" #include "BDR_drawaction.h" diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 28b8729a247..19fb8dc2ecd 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -69,6 +69,7 @@ #include "BIF_gl.h" #include "BIF_graphics.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_space.h" #include "BIF_toolbox.h" @@ -406,6 +407,7 @@ void pose_recalculate_paths(Object *ob) waitcursor(0); CFRA= cfra; + ob->pose->flag &= ~POSE_RECALCPATHS; allqueue(REDRAWVIEW3D, 0); /* recalc tags are still there */ allqueue(REDRAWBUTSEDIT, 0); } diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index 0be63197dd1..1730bb890bc 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -97,6 +97,8 @@ #include "RE_pipeline.h" #include "BLO_readfile.h" +#include "GPU_material.h" + #include "blendef.h" /* CLAMP */ #include "interface.h" /* ui_graphics_to_window(), SOLVE! (ton) */ #include "mydevice.h" @@ -221,6 +223,36 @@ void BIF_preview_changed(short id_code) } } } + + if(ELEM4(id_code, ID_MA, ID_TE, ID_LA, ID_WO)) { + Object *ob; + Material *ma; + + if(id_code == ID_WO) { + for(ma=G.main->mat.first; ma; ma=ma->id.next) { + if(ma->gpumaterial.first) { + GPU_material_free(ma); + allqueue(REDRAWVIEW3D, 0); + } + } + } + else if(id_code == ID_LA) { + for(ob=G.main->object.first; ob; ob=ob->id.next) { + if(ob->gpulamp.first) { + GPU_lamp_free(ob); + allqueue(REDRAWVIEW3D, 0); + } + } + } else if(OBACT) { + Object *ob = OBACT; + + ma= give_current_material(ob, ob->actcol); + if(ma && ma->gpumaterial.first) { + GPU_material_free(ma); + allqueue(REDRAWVIEW3D, 0); + } + } + } } /* *************************** Preview for buttons *********************** */ diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 88f5f6efe15..33484500328 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -50,8 +50,6 @@ #endif -#include "BLO_sys_types.h" // for intptr_t support - #include #include "BLI_blenlib.h" @@ -102,6 +100,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_draw.h" + #include "blendef.h" #include "mydevice.h" #include "winlay.h" @@ -676,7 +676,7 @@ static void open_renderwin(int winpos[2], int winsize[2], int imagesize[2]) /* mywindow has to know about it too */ mywindow_build_and_set_renderwin(winpos[0], winpos[1], winsize[0], winsize[1]+RW_HEADERY); /* and we should be able to draw 3d in it */ - init_gl_stuff(); + GPU_state_init(); renderwin_draw(render_win, 1); renderwin_draw(render_win, 1); @@ -903,10 +903,13 @@ static void renderwin_progress_display_cb(RenderResult *rr, volatile rcti *rect) void make_renderinfo_string(RenderStats *rs, char *str) { extern char info_time_str[32]; // header_info.c - extern uintptr_t mem_in_use, mmap_in_use; + uintptr_t mem_in_use, mmap_in_use; float megs_used_memory, mmap_used_memory; char *spos= str; + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0); mmap_used_memory= (mmap_in_use)/(1024.0*1024.0); @@ -1304,10 +1307,10 @@ void do_ogl_view3d_render(Render *re, View3D *v3d, int winx, int winy) if(v3d->persp==V3D_CAMOB && v3d->camera) { /* in camera view, use actual render winmat */ RE_GetCameraWindow(re, v3d->camera, CFRA, winmat); - drawview3d_render(v3d, winx, winy, winmat); + drawview3d_render(v3d, NULL, winx, winy, winmat, 0); } else - drawview3d_render(v3d, winx, winy, NULL); + drawview3d_render(v3d, NULL, winx, winy, NULL, 0); } /* set up display, render the current area view in an image */ @@ -1336,7 +1339,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) if(render_win) render_win->flags &= ~RW_FLAGS_ESCAPE; - init_gl_stuff(); + GPU_state_init(); waitcursor(1); diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index acd14aae7a5..1bef10d0415 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -753,6 +753,8 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Transition Strip %%x%d|", TH_SEQ_TRANSITION); str += sprintf(str, "Meta Strip %%x%d|", TH_SEQ_META); str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); + str += sprintf(str, "Keyframe %%x%d|", TH_VERTEX_SELECT); + str += sprintf(str, "Draw Action %%x%d|", TH_BONE_POSE); break; case SPACE_SOUND: str += sprintf(str, "Grid %%x%d|", TH_GRID); diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 24f4100efdb..31d5ae4610d 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -82,7 +82,6 @@ #include "BIF_space.h" #include "BIF_toolbox.h" -#include "BDR_drawobject.h" #include "BDR_sculptmode.h" #include "BSE_drawview.h" @@ -98,6 +97,8 @@ #include "RE_render_ext.h" #include "RE_shader_ext.h" /*for multitex_ext*/ +#include "GPU_draw.h" + #include #include #include @@ -1514,7 +1515,7 @@ void sculptmode_draw_mesh(int only_damaged) mymultmatrix(OBACT->obmat); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); - init_gl_materials(OBACT, 0); + GPU_set_object_materials(G.scene, OBACT, 0, NULL); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); @@ -1532,7 +1533,7 @@ void sculptmode_draw_mesh(int only_damaged) int new_matnr= f->mat_nr + 1; if(new_matnr != matnr) - drawCurrentMat= set_gl_material(matnr = new_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 */ diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 7e2ffc3ba63..5be11a724f1 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2949,13 +2949,16 @@ void do_render_seq(RenderResult *rr, int cfra) (schlaile) */ { - extern int mem_in_use; - extern int mmap_in_use; + uintptr_t mem_in_use; + uintptr_t mmap_in_use; + uintptr_t max; + + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + max = MEM_CacheLimiter_get_maximum(); - int max = MEM_CacheLimiter_get_maximum(); if (max != 0 && mem_in_use + mmap_in_use > max) { - fprintf(stderr, "mem_in_use = %d, max = %d\n", - mem_in_use + mmap_in_use, max); + fprintf(stderr, "Memory in use > maximum memory\n"); fprintf(stderr, "Cleaning up, please wait...\n" "If this happens very often,\n" "consider " diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 8787cf9efc4..9120fc3de76 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -182,6 +182,9 @@ #include "SYS_System.h" /* for the user def menu ... should move elsewhere. */ +#include "GPU_extensions.h" +#include "GPU_draw.h" + #include "BLO_sys_types.h" // for intptr_t support /* maybe we need this defined somewhere else */ @@ -386,7 +389,7 @@ void space_set_commmandline_options(void) { SYS_WriteCommandLineInt(syshandle, "noaudio", a); a= (U.gameflags & USER_DISABLE_MIPMAP); - set_mipmap(!a); + GPU_set_mipmap(!a); SYS_WriteCommandLineInt(syshandle, "nomipmap", a); /* File specific settings: */ @@ -415,7 +418,9 @@ void space_set_commmandline_options(void) { a=(G.fileflags & G_FILE_GAME_MAT); SYS_WriteCommandLineInt(syshandle, "blender_material", a); - a=(G.fileflags & G_FILE_DIAPLAY_LISTS); + a=(G.fileflags & G_FILE_GAME_MAT_GLSL); + SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", a); + a=(G.fileflags & G_FILE_DISPLAY_LISTS); SYS_WriteCommandLineInt(syshandle, "displaylists", a); @@ -432,11 +437,10 @@ static void SaveState(void) { glPushAttrib(GL_ALL_ATTRIB_BITS); - init_realtime_GL(); - init_gl_stuff(); + GPU_state_init(); if(G.f & G_TEXTUREPAINT) - texpaint_enable_mipmap(); + GPU_paint_set_mipmap(1); waitcursor(1); } @@ -444,7 +448,7 @@ static void SaveState(void) static void RestoreState(void) { if(G.f & G_TEXTUREPAINT) - texpaint_disable_mipmap(); + GPU_paint_set_mipmap(0); curarea->win_swap = 0; curarea->head_swap=0; @@ -1024,9 +1028,9 @@ void BIF_undo(void) } else { if(G.f & G_TEXTUREPAINT) - imagepaint_undo(); + undo_imagepaint_step(1); else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL)) - imagepaint_undo(); + undo_imagepaint_step(1); else if(G.f & G_PARTICLEEDIT) PE_undo(); else { @@ -1048,9 +1052,9 @@ void BIF_redo(void) } else { if(G.f & G_TEXTUREPAINT) - imagepaint_undo(); + undo_imagepaint_step(-1); else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL)) - imagepaint_undo(); + undo_imagepaint_step(-1); else if(G.f & G_PARTICLEEDIT) PE_redo(); else { @@ -1906,6 +1910,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else copy_attr_menu(); } + else if(G.qual==(LR_ALTKEY|LR_SHIFTKEY)) + gpencil_convert_menu(); /* gpencil.c */ else if(G.qual==LR_ALTKEY) { if(ob && (ob->flag & OB_POSEMODE)) pose_clear_constraints(); /* poseobject.c */ @@ -1964,7 +1970,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.vd->drawtype= pupval; doredraw= 1; } - } + } break; case EKEY: @@ -2056,6 +2062,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT)){ G.f ^= G_FACESELECT; allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWBUTSEDIT, 1); } else if(G.f & G_PARTICLEEDIT) { PE_radialcontrol_start(RADIALCONTROL_SIZE); @@ -2641,10 +2648,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.f & G_VERTEXPAINT) BIF_undo(); else if(G.f & G_TEXTUREPAINT) - imagepaint_undo(); - else { + undo_imagepaint_step(1); + else single_user(); - } } break; @@ -3097,6 +3103,9 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if (G.qual==LR_CTRLKEY) { borderselect_markers(); } + else if (G.qual==LR_SHIFTKEY) { + do_ipo_buttons(B_IPOBORDER); + } break; case CKEY: if (G.qual == LR_SHIFTKEY) @@ -3257,7 +3266,7 @@ void initipo(ScrArea *sa) /* ******************** SPACE: INFO ********************** */ void space_mipmap_button_function(int event) { - set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); allqueue(REDRAWVIEW3D, 0); } @@ -3733,6 +3742,11 @@ void drawinfospace(ScrArea *sa, void *spacedata) "Snap objects and sub-objects to grid units when scaling"); uiBlockEndAlign(block); + uiDefButBitI(block, TOG, USER_ORBIT_ZBUF, B_DRAWINFO, "Auto Depth", + (xpos+edgsp+mpref+spref+(2*midsp)),y2,spref,buth, + &(U.uiflag), 0, 0, 0, 0, + "Use the depth under the mouse to improve view pan/rotate/zoom functionality"); + uiDefButBitI(block, TOG, USER_LOCKAROUND, B_DRAWINFO, "Global Pivot", (xpos+edgsp+mpref+spref+(2*midsp)),y1,spref,buth, &(U.uiflag), 0, 0, 0, 0, @@ -3947,20 +3961,23 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefBut(block, LABEL,0,"Transform:", - (xpos+(2*edgsp)+mpref),y5label, mpref,buth, + (xpos+(2*edgsp)+mpref),y6label, mpref,buth, 0, 0, 0, 0, 0, ""); uiDefButBitI(block, TOG, USER_DRAGIMMEDIATE, B_DRAWINFO, "Drag Immediately", - (xpos+edgsp+mpref+midsp),y4,mpref,buth, + (xpos+edgsp+mpref+midsp),y5,mpref,buth, &(U.flag), 0, 0, 0, 0, "Moving things with a mouse drag doesn't require a click to confirm (Best for tablet users)"); uiBlockEndAlign(block); uiDefBut(block, LABEL,0,"Undo:", - (xpos+(2*edgsp)+mpref),y3label, mpref,buth, + (xpos+(2*edgsp)+mpref),y4label, mpref,buth, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); uiDefButS(block, NUMSLI, B_DRAWINFO, "Steps: ", - (xpos+edgsp+mpref+midsp),y2,mpref,buth, + (xpos+edgsp+mpref+midsp),y3,mpref,buth, &(U.undosteps), 0, 64, 0, 0, "Number of undo steps available (smaller values conserve memory)"); + uiDefButS(block, NUM, B_DRAWINFO, "Memory Limit: ", + (xpos+edgsp+mpref+midsp),y2,mpref,buth, + &(U.undomemory), 0, 32767, -1, 0, "Maximum memory usage in megabytes (0 means unlimited)"); uiDefButBitI(block, TOG, USER_GLOBALUNDO, B_DRAWINFO, "Global Undo", (xpos+edgsp+mpref+midsp),y1,mpref,buth, @@ -4295,6 +4312,7 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefButI(block, NUM, 0, "Collect Rate ", (xpos+edgsp+(5*mpref)+(5*midsp)), y2, mpref, buth, &U.texcollectrate, 1.0, 3600.0, 30, 2, "Number of seconds between each run of the GL texture garbage collector."); + uiBlockEndAlign(block); /* *** */ uiDefBut(block, LABEL,0,"Color range for weight paint", @@ -4531,7 +4549,7 @@ static void winqreadinfospace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) U.light[0].flag= 1; - default_gl_light(); + GPU_default_lights(); addqueue(sa->win, REDRAW, 1); allqueue(REDRAWVIEW3D, 0); } @@ -5171,8 +5189,8 @@ static void init_seqspace(ScrArea *sa) sseq->v2d.max[0]= MAXFRAMEF; sseq->v2d.max[1]= MAXSEQ; - sseq->v2d.minzoom= 0.1f; - sseq->v2d.maxzoom= 10.0; + sseq->v2d.minzoom= 0.01f; + sseq->v2d.maxzoom= 100.0; sseq->v2d.scroll= L_SCROLL+B_SCROLL; sseq->v2d.keepaspect= 0; @@ -5327,7 +5345,15 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val==0) return; if(uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; - + + /* grease-pencil drawing before draw-tool */ + if (event == LEFTMOUSE) { + if (gpencil_do_paint(sa, L_MOUSE)) return; + } + else if (event == RIGHTMOUSE) { + if (gpencil_do_paint(sa, R_MOUSE)) return; + } + if (sima->image && (sima->flag & SI_DRAWTOOL)) { switch(event) { case CKEY: @@ -5350,7 +5376,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) event = LEFTMOUSE; } } - + /* Draw tool is inactive, editmode is enabled and the image is not a render or composite */ if (EM_texFaceCheck() && (G.sima->image==0 || (G.sima->image->type != IMA_TYPE_R_RESULT && G.sima->image->type != IMA_TYPE_COMPOSITE))) { switch(event) { @@ -5987,7 +6013,7 @@ static void init_oopsspace(ScrArea *sa) soops= MEM_callocN(sizeof(SpaceOops), "initoopsspace"); BLI_addhead(&sa->spacedata, soops); - soops->visiflag= OOPS_OB+OOPS_MA+OOPS_ME+OOPS_TE+OOPS_CU+OOPS_IP; + soops->visiflag= OOPS_OB|OOPS_MA|OOPS_ME|OOPS_TE|OOPS_CU|OOPS_IP; /* new oops is default an outliner */ soops->type= SO_OUTLINER; @@ -6058,6 +6084,10 @@ static void init_textspace(ScrArea *sa) st->lheight= 12; st->showlinenrs= 0; st->tabnumber = 4; + st->showsyntax= 0; + st->doplugins= 0; + st->overwrite= 0; + st->wordwrap= 0; st->currtab_set = 0; st->top= 0; @@ -6327,6 +6357,8 @@ void freespacelist(ScrArea *sa) SpaceImage *sima= (SpaceImage *)sl; if(sima->cumap) curvemapping_free(sima->cumap); + if(sima->gpd) + free_gpencil_data(sima->gpd); } else if(sl->spacetype==SPACE_NODE) { SpaceNode *snode= (SpaceNode *)sl; @@ -6394,6 +6426,10 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) SpaceSeq *sseq= (SpaceSeq *)sl; sseq->gpd= gpencil_data_duplicate(sseq->gpd); } + else if(sl->spacetype==SPACE_IMAGE) { + SpaceImage *sima= (SpaceImage *)sl; + sima->gpd= gpencil_data_duplicate(sima->gpd); + } sl= sl->next; } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 5f80f14d069..41ee557c9c2 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -75,6 +75,7 @@ #include "BIF_imasel.h" #include "BIF_editparticle.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" #include "BIF_renderwin.h" @@ -104,6 +105,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_draw.h" + #include "mydevice.h" #include "transform.h" @@ -790,6 +793,10 @@ int blenderqread(unsigned short event, short val) ob= OBACT; if(G.f & G_SCULPTMODE) return 1; + else if(G.qual==(LR_CTRLKEY|LR_ALTKEY)) { + common_deletekey(); + return 0; + } else if(G.qual==0) { common_insertkey(); return 0; @@ -964,7 +971,7 @@ int blenderqread(unsigned short event, short val) /* Reset lights * This isn't done when reading userdef, do it now * */ - default_gl_light(); + GPU_default_lights(); } return 0; } diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index c8a20cdc951..f38affde418 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -93,6 +93,7 @@ #include "BIF_graphics.h" #include "BIF_imasel.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" #include "BIF_renderwin.h" @@ -2282,7 +2283,7 @@ void toolbox_generic( TBitem *generic_menu ) uiBlock *block; uiBut *but; TBitem *menu; - int dx=96; + int dx=96, first=1, len; short event, mval[2]; intptr_t ypos = -5; @@ -2303,11 +2304,17 @@ void toolbox_generic( TBitem *generic_menu ) /* Add the menu */ for (menu = generic_menu; menu->icon != -1; menu++) { - if(strcmp(menu->name, "SEPR")==0) { + if (first && (len=strlen(menu->name)) > 2 && menu->name[len-2]=='%' && menu->name[len-1]=='t') { + menu->name[len-2] = '\0'; + uiSetCurFont(block, UI_HELVB); + uiDefIconTextBut(block, LABEL, 0, ICON_BLANK1, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiSetCurFont(block, UI_HELV); + ypos-=20; + } else if(strcmp(menu->name, "SEPR")==0) { uiDefBut(block, SEPR, 0, "", mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 6, NULL, 0.0, 0.0, 0, 0, ""); ypos-=6; } else { - if (menu->poin) { + if (menu->poin) { but=uiDefIconTextBlockBut(block, tb_makemenu, menu->poin, ICON_RIGHTARROW_THIN, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, ""); uiButSetFlag(but, UI_MAKE_RIGHT); @@ -2318,6 +2325,7 @@ void toolbox_generic( TBitem *generic_menu ) } ypos-=20; } + first= 0; } uiBlockSetButmFunc(block, menu->poin, NULL); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index efb86b59ed1..210a81927c8 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -108,6 +108,7 @@ #include "BIF_editsima.h" #include "BIF_editparticle.h" #include "BIF_gl.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" @@ -3562,22 +3563,25 @@ short autokeyframe_cfra_can_key(Object *ob) */ void autokeyframe_ob_cb_func(Object *ob, int tmode) { + ID *id= (ID *)(ob); IpoCurve *icu; if (autokeyframe_cfra_can_key(ob)) { char *actname = NULL; + short flag = 0; if (ob->ipoflag & OB_ACTION_OB) actname= "Object"; + + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { + /* only key on available channels */ if ((ob->ipo) || (ob->action)) { - ID *id= (ID *)(ob); - - if (ob->ipo) { - icu= ob->ipo->curve.first; - } - else { + if (ob->action && actname) { bActionChannel *achan; achan= get_action_channel(ob->action, actname); @@ -3586,19 +3590,16 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) else icu= NULL; } + else + icu= ob->ipo->curve.first; - while (icu) { + for (; icu; icu= icu->next) { icu->flag &= ~IPO_SELECT; - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); - else - insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); - icu= icu->next; + insertkey(id, ID_OB, actname, NULL, icu->adrcode, flag); } } } else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) { - ID *id= (ID *)(ob); short doLoc=0, doRot=0, doScale=0; /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ @@ -3629,35 +3630,33 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) } if (doLoc) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Z); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); } if (doRot) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Z); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); } if (doScale) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Z); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); } } else { - ID *id= (ID *)(ob); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); - - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); } remake_object_ipos(ob); @@ -3683,8 +3682,15 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) act= ob->action; if (autokeyframe_cfra_can_key(ob)) { + short flag= 0; + if (act == NULL) act= ob->action= add_empty_action("Action"); + + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { if (pchan->bone->flag & BONE_TRANSFORM) { @@ -3695,17 +3701,10 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { bActionChannel *achan; - for (achan = act->chanbase.first; achan; achan=achan->next) { - if ((achan->ipo) && !strcmp(achan->name, pchan->name)) { - for (icu = achan->ipo->curve.first; icu; icu=icu->next) { - /* only insert keyframe if needed? */ - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); - else - insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0); - } - break; - } + achan= get_action_channel(act, pchan->name); + if (achan && achan->ipo) { + for (icu= achan->ipo->curve.first; icu; icu= icu->next) + insertkey(id, ID_PO, pchan->name, NULL, icu->adrcode, flag); } } /* only insert keyframe if needed? */ @@ -3735,36 +3734,36 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } if (doLoc) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); } if (doRot) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); } if (doScale) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); } } /* insert keyframe in any channel that's appropriate */ else { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); } } } @@ -3913,13 +3912,10 @@ void special_aftertrans_update(TransInfo *t) if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 && (cancelled == 0) ) { - if (NLA_IPO_SCALED) { - actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 1); - posttrans_ipo_clean(G.sipo->ipo); - actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 1); - } - else - posttrans_ipo_clean(G.sipo->ipo); + /* NOTE: no need to do NLA scaling stuff here, as when there is NLA scaling, + * the transformed handles will get moved wrong (seem to match wrong repeat cycle) + */ + posttrans_ipo_clean(G.sipo->ipo); } } diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 656fca3cad8..a1440b8cbce 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -583,39 +583,6 @@ void recalcData(TransInfo *t) reshadeall_displist(); } -void initTransModeFlags(TransInfo *t, int mode) -{ - t->mode = mode; - t->num.flag = 0; - - /* REMOVING RESTRICTIONS FLAGS */ - t->flag &= ~T_ALL_RESTRICTIONS; - - switch (mode) { - case TFM_RESIZE: - t->flag |= T_NULL_ONE; - t->num.flag |= NUM_NULL_ONE; - t->num.flag |= NUM_AFFECT_ALL; - if (!G.obedit) { - t->flag |= T_NO_ZERO; - t->num.flag |= NUM_NO_ZERO; - } - break; - case TFM_TOSPHERE: - t->num.flag |= NUM_NULL_ONE; - t->num.flag |= NUM_NO_NEGATIVE; - t->flag |= T_NO_CONSTRAINT; - break; - case TFM_SHEAR: - case TFM_CREASE: - case TFM_BONE_ENVELOPE: - case TFM_CURVE_SHRINKFATTEN: - case TFM_BONE_ROLL: - t->flag |= T_NO_CONSTRAINT; - break; - } -} - void drawLine(float *center, float *dir, char axis, short options) { extern void make_axis_color(char *col, char *col2, char axis); // drawview.c @@ -674,19 +641,10 @@ void initTrans (TransInfo *t) t->transform = NULL; t->handleEvent = NULL; - t->total = - t->num.idx = - t->num.idx_max = - t->num.ctrl[0] = - t->num.ctrl[1] = - t->num.ctrl[2] = 0; + t->total = 0; t->val = 0.0f; - t->num.val[0] = - t->num.val[1] = - t->num.val[2] = 0.0f; - t->vec[0] = t->vec[1] = t->vec[2] = 0.0f; @@ -708,7 +666,8 @@ void initTrans (TransInfo *t) t->around = V3D_CENTER; setTransformViewMatrices(t); - initNDofInput(&(t->ndof)); + initNumInput(&t->num); + initNDofInput(&t->ndof); } /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */ diff --git a/source/blender/src/transform_numinput.c b/source/blender/src/transform_numinput.c index 9b811595a9a..89a76c097e0 100644 --- a/source/blender/src/transform_numinput.c +++ b/source/blender/src/transform_numinput.c @@ -41,6 +41,20 @@ /* ************************** NUMINPUT **************************** */ +void initNumInput(NumInput *n) +{ + n->flag = + n->idx = + n->idx_max = + n->ctrl[0] = + n->ctrl[1] = + n->ctrl[2] = 0; + + n->val[0] = + n->val[1] = + n->val[2] = 0.0f; +} + void outputNumInput(NumInput *n, char *str) { char cur; diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index 9c7a2f67b89..fc9dfbb902e 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -352,7 +352,7 @@ char * BIF_menustringTransformOrientation(char *title) { char *str_menu, *p; - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); + str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); p = str_menu; p += sprintf(str_menu, "%s", title); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 15c2664a9d8..aa49065320b 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -34,8 +34,6 @@ #include #include -#include "GL/glew.h" - #ifdef WIN32 #include /* need to include windows.h so _WIN32_IE is defined */ #ifndef _WIN32_IE @@ -69,6 +67,7 @@ #include "DNA_sound_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_text_types.h" #include "BKE_blender.h" #include "BKE_curve.h" @@ -81,6 +80,7 @@ #include "BKE_mball.h" #include "BKE_node.h" #include "BKE_packedFile.h" +#include "BKE_suggestions.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_pointcache.h" @@ -147,6 +147,9 @@ #include "PIL_time.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + /***/ /* define for setting colors in theme below */ @@ -480,9 +483,21 @@ static void init_userdef_file(void) if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile < 1)) { bTheme *btheme; for(btheme= U.themes.first; btheme; btheme= btheme->next) { - SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255); - SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255); - btheme->tipo.handle_vertex_size= 3; + char *col; + + /* IPO Editor: Handles/Vertices */ + col = btheme->tipo.vertex; + SETCOL(btheme->tipo.handle_vertex, col[0], col[1], col[2], 255); + col = btheme->tipo.vertex_select; + SETCOL(btheme->tipo.handle_vertex_select, col[0], col[1], col[2], 255); + btheme->tipo.handle_vertex_size= btheme->tipo.vertex_size; + + /* Sequence/Image Editor: colors for GPencil text */ + col = btheme->tv3d.bone_pose; + SETCOL(btheme->tseq.bone_pose, col[0], col[1], col[2], 255); + SETCOL(btheme->tima.bone_pose, col[0], col[1], col[2], 255); + col = btheme->tv3d.vertex_select; + SETCOL(btheme->tseq.vertex_select, col[0], col[1], col[2], 255); } } @@ -575,8 +590,9 @@ void BIF_read_file(char *name) if (retval!=0) G.relbase_valid = 1; undo_editmode_clear(); + undo_imagepaint_clear(); BKE_reset_undo(); - BKE_write_undo("original"); /* save current state */ + BKE_write_undo("Original"); /* save current state */ refresh_interface_font(); } @@ -648,8 +664,9 @@ int BIF_read_homefile(int from_memory) init_userdef_file(); undo_editmode_clear(); + undo_imagepaint_clear(); BKE_reset_undo(); - BKE_write_undo("original"); /* save current state */ + BKE_write_undo("Original"); /* save current state */ /* if from memory, need to refresh python scripts */ if (from_memory) { @@ -1047,8 +1064,9 @@ void BIF_init(void) BIF_filelist_init_icons(); - init_gl_stuff(); /* drawview.c, after homefile */ - glewInit(); + GPU_state_init(); + GPU_extensions_init(); + readBlog(); BLI_strncpy(G.lib, G.sce, FILE_MAX); } @@ -1061,6 +1079,7 @@ extern ListBase editelems; void exit_usiblender(void) { struct TmpFont *tf; + int totblock; BIF_clear_tempfiles(); @@ -1106,7 +1125,7 @@ void exit_usiblender(void) free_ipocopybuf(); free_actcopybuf(); free_vertexpaint(); - free_imagepaint(); + free_texttools(); /* editnurb can remain to exist outside editmode */ freeNurblist(&editNurb); @@ -1124,6 +1143,7 @@ void exit_usiblender(void) sound_exit_audio(); if(G.listener) MEM_freeN(G.listener); + GPU_extensions_exit(); libtiff_exit(); @@ -1133,6 +1153,7 @@ void exit_usiblender(void) /* undo free stuff */ undo_editmode_clear(); + undo_imagepaint_clear(); BKE_undo_save_quit(); // saves quit.blend if global undo is on BKE_reset_undo(); @@ -1158,6 +1179,7 @@ void exit_usiblender(void) BLI_freelistN(&U.themes); BIF_preview_free_dbase(); + totblock= MEM_get_memory_blocks_in_use(); if(totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_printmemlist(); diff --git a/source/blender/src/verse_image.c b/source/blender/src/verse_image.c index fe9e6137091..edb3a0a9f2c 100644 --- a/source/blender/src/verse_image.c +++ b/source/blender/src/verse_image.c @@ -43,6 +43,8 @@ #include "BIF_verse.h" #include "BIF_space.h" +#include "GPU_draw.h" + /* * unsubscribe from verse bitmap */ @@ -327,7 +329,7 @@ void post_bitmap_tile_set(VBitmapLayer *vblayer, unsigned int xs, unsigned int y rect[channel] = (char)vuint8[i]; } - free_realtime_image(image); + GPU_free_image(image); /* redraw preview of image ... uncommented, because rendering * was computed too often */ diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 12450bee9de..4c56e5ce64e 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -793,6 +793,82 @@ void viewmoveNDOFfly(int mode) BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); } +int view_autodist( float mouse_worldloc[3] ) //, float *autodist ) +{ + View3D *v3d = G.vd; + + /* Zooms in on a border drawn by the user */ + short mval[2]; + rcti rect; + + /* ZBuffer depth vars */ + bglMats mats; + float depth, depth_close= MAXFLOAT; + int had_depth = 0; + double cent[2], p[3]; + int xs, ys; + + getmouseco_areawin(mval); + + persp(PERSP_VIEW); + + rect.xmax = mval[0] + 4; + rect.ymax = mval[1] + 4; + + rect.xmin = mval[0] - 4; + rect.ymin = mval[1] - 4; + + /* Get Z Depths, needed for perspective, nice for ortho */ + bgl_get_mats(&mats); + draw_depth(curarea, (void *)v3d, NULL); + + /* force updating */ + if (v3d->depths) { + had_depth = 1; + v3d->depths->damaged = 1; + } + + view3d_update_depths(v3d); + + /* Constrain rect to depth bounds */ + if (rect.xmin < 0) rect.xmin = 0; + if (rect.ymin < 0) rect.ymin = 0; + if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1; + if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1; + + /* Find the closest Z pixel */ + for (xs=rect.xmin; xs < rect.xmax; xs++) { + for (ys=rect.ymin; ys < rect.ymax; ys++) { + depth= v3d->depths->depths[ys*v3d->depths->w+xs]; + if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) { + if (depth_close > depth) { + depth_close = depth; + } + } + } + } + + if (depth_close==MAXFLOAT) + return 0; + + if (had_depth==0) { + MEM_freeN(v3d->depths->depths); + v3d->depths->depths = NULL; + } + v3d->depths->damaged = 1; + + cent[0] = (double)mval[0]; + cent[1] = (double)mval[1]; + + if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, mats.viewport, &p[0], &p[1], &p[2])) + return 0; + + mouse_worldloc[0] = (float)p[0]; + mouse_worldloc[1] = (float)p[1]; + mouse_worldloc[2] = (float)p[2]; + return 1; +} + void viewmove(int mode) { static float lastofs[3] = {0,0,0}; @@ -825,15 +901,11 @@ void viewmove(int mode) Mat3MulVecfl(mat, upvec); VecAddf(G.vd->ofs, G.vd->ofs, upvec); } - - /* sometimes this routine is called from headerbuttons */ areawinset(curarea->win); - initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); - QUATCOPY(oldquat, G.vd->viewquat); getmouseco_areawin(mval_area); /* for zoom to mouse loc */ @@ -867,9 +939,44 @@ void viewmove(int mode) VECCOPY(obofs, lastofs); VecMulf(obofs, -1.0f); } + else if (U.uiflag & USER_ORBIT_ZBUF) { + if ((use_sel=view_autodist(obofs))) { + if (G.vd->persp==V3D_PERSP) { + float my_origin[3]; /* original G.vd->ofs */ + float my_pivot[3]; /* view */ + + VECCOPY(my_origin, G.vd->ofs); + VecMulf(my_origin, -1.0f); /* ofs is flipped */ + + /* Set the dist value to be the distance from this 3d point */ + /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */ + + /* remove dist value */ + upvec[0] = upvec[1] = 0; + upvec[2] = G.vd->dist; + Mat3CpyMat4(mat, G.vd->viewinv); + Mat3MulVecfl(mat, upvec); + VecSubf(my_pivot, G.vd->ofs, upvec); + VecMulf(my_pivot, -1.0f); /* ofs is flipped */ + + /* find a new ofs value that is allong the view axis (rather then the mouse location) */ + lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec); + dist0 = G.vd->dist = VecLenf(my_pivot, dvec); + + VecMulf(dvec, -1.0f); + VECCOPY(G.vd->ofs, dvec); + } + VecMulf(obofs, -1.0f); + VECCOPY(ofs, G.vd->ofs); + } else { + ofs[0] = ofs[1] = ofs[2] = 0.0f; + } + } else ofs[0] = ofs[1] = ofs[2] = 0.0f; - + + initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); + reverse= 1.0f; if (G.vd->persmat[2][1] < 0.0f) reverse= -1.0f; @@ -1046,9 +1153,20 @@ void viewmove(int mode) zfac*G.vd->dist < 10.0*G.vd->far) view_zoom_mouseloc(zfac, mval_area); - /* these limits are in toets.c too */ - if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; - if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; + + if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (G.vd->persp==V3D_PERSP)) { + /* Secret apricot feature, translate the view when in continues mode */ + upvec[0] = upvec[1] = 0; + upvec[2] = (dist0 - G.vd->dist) * G.vd->grid; + G.vd->dist = dist0; + Mat3CpyMat4(mat, G.vd->viewinv); + Mat3MulVecfl(mat, upvec); + VecAddf(G.vd->ofs, G.vd->ofs, upvec); + } else { + /* these limits are in toets.c too */ + if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; + if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; + } if(G.vd->persp==V3D_ORTHO || G.vd->persp==V3D_CAMOB) preview3d_event= 0; } @@ -2353,3 +2471,4 @@ void smooth_view_to_camera(View3D *v3d) v3d->persp= V3D_CAMOB; } } + diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp index f8bbdad5f65..f42e00daf6d 100644 --- a/source/blender/yafray/intern/export_File.cpp +++ b/source/blender/yafray/intern/export_File.cpp @@ -881,7 +881,7 @@ void yafrayFileRender_t::writeShader(const string &shader_name, Material* matr, ostr << "\t\t\n"; // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[9] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen"}; + const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; ostr << "\t\tblendtype] << "\" />\n"; // texture color (for use with MUL and/or no_rgb etc..) diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp index 77d53c4ed96..a7d5653892f 100644 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ b/source/blender/yafray/intern/export_Plugin.cpp @@ -782,7 +782,7 @@ void yafrayPluginRender_t::writeShader(const string &shader_name, Material* matr mparams["input"] = yafray::parameter_t(shader_name + temp); // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[9] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen"}; + const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; mparams["mode"] = yafray::parameter_t(blendtype[(int)mtex->blendtype]); // texture color (for use with MUL and/or no_rgb etc..) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index d17b94c631d..93cc0e8afb5 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -37,8 +37,10 @@ INCLUDE_DIRECTORIES(../../intern/guardedalloc ../blender/render/extern/include ../blender/python ../blender/makesdna + ../blender/gpu ../kernel/gen_messaging ../kernel/gen_system + ../../extern/glew/include ) @@ -189,7 +191,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} src blender_python blender_render blender_radiosity blender_IK bf_elbeem) +SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} src blender_python blender_render blender_radiosity bf_elbeem) IF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(BLENDER_LINK_LIBS ${BLENDER_LINK_LIBS} extern_binreloc) @@ -210,6 +212,7 @@ IF(UNIX) blender_python bf_blenkernel bf_nodes + bf_gpu bf_blenloader bf_blenpluginapi bf_imbuf @@ -223,7 +226,7 @@ IF(UNIX) bf_decimation bf_elbeem bf_yafray - blender_IK + bf_IK bf_memutil bf_guardedalloc blender_CTR diff --git a/source/creator/Makefile b/source/creator/Makefile index 8a0d20264ea..158aee1a647 100644 --- a/source/creator/Makefile +++ b/source/creator/Makefile @@ -49,9 +49,11 @@ CPPFLAGS += -I../blender/renderconverter CPPFLAGS += -I../blender/blenkernel CPPFLAGS += -I../blender/python CPPFLAGS += -I../blender/blenloader +CPPFLAGS += -I../blender/gpu CPPFLAGS += -I../kernel/gen_system CPPFLAGS += -I../kernel/gen_messaging CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_GLEW)/include ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -I$(NAN_QUICKTIME)/include -DWITH_QUICKTIME diff --git a/source/creator/SConscript b/source/creator/SConscript index cac9e895a97..a4c218f89d6 100644 --- a/source/creator/SConscript +++ b/source/creator/SConscript @@ -7,7 +7,7 @@ incs = '#/intern/guardedalloc ../blender/blenlib ../blender/blenkernel' incs += ' ../blender/include ../blender/blenloader ../blender/imbuf' incs += ' ../blender/renderconverter ../blender/render/extern/include' incs += ' ../blender/python ../blender/makesdna ../kernel/gen_messaging' -incs += ' ../kernel/gen_system' +incs += ' ../kernel/gen_system #/extern/glew/include ../blender/gpu' incs += ' ' + env['BF_OPENGL_INC'] defs = [] diff --git a/source/creator/creator.c b/source/creator/creator.c index e17b0f66977..bdd16dc6bed 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -70,14 +70,14 @@ #include "BLO_writefile.h" #include "BLO_readfile.h" -#include "BDR_drawmesh.h" - #include "IMB_imbuf.h" // for quicktime_init #include "BPY_extern.h" #include "RE_pipeline.h" +#include "GPU_draw.h" + #include "playanim_ext.h" #include "mydevice.h" #include "nla.h" @@ -600,12 +600,12 @@ int main(int argc, char **argv) /* doMipMap */ if (!strcmp(argv[a],"nomipmap")) { - set_mipmap(0); //doMipMap = 0; + GPU_set_mipmap(0); //doMipMap = 0; } /* linearMipMap */ if (!strcmp(argv[a],"linearmipmap")) { - set_linear_mipmap(1); //linearMipMap = 1; + GPU_set_linear_mipmap(1); //linearMipMap = 1; } @@ -772,44 +772,10 @@ int main(int argc, char **argv) else { /* Make the path absolute because its needed for relative linked blends to be found */ - int abs = 0; - int filelen; - char cwd[FILE_MAXDIR + FILE_MAXFILE]; char filename[FILE_MAXDIR + FILE_MAXFILE]; - cwd[0] = filename[0] = '\0'; BLI_strncpy(filename, argv[a], sizeof(filename)); - filelen = strlen(filename); - - /* relative path checks, could do more tests here... */ -#ifdef WIN32 - /* Account for X:/ and X:\ - should be enough */ - if (filelen >= 3 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/')) - abs = 1; -#else - if (filelen >= 2 && filename[0] == '/') - abs = 1 ; -#endif - if (!abs) { - BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ - - if (cwd[0] == '\0') { - printf( - "Could not get the current working directory - $PWD for an unknown reason.\n\t" - "Relative linked files will not load if the entire blend path is not used.\n\t" - "The 'Play' button may also fail.\n" - ); - } else { - /* uses the blend path relative to cwd important for loading relative linked files. - * - * cwd should contain c:\ etc on win32 so the relbase can be NULL - * relbase being NULL also prevents // being misunderstood as relative to the current - * blend file which isnt a feature we want to use in this case since were dealing - * with a path from the command line, rather then from inside Blender */ - - BLI_make_file_string(NULL, filename, cwd, argv[a]); - } - } + BLI_convertstringcwd(filename); if (G.background) { int retval = BKE_read_file(filename, NULL); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 16f8ae0095a..74fe6c68863 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -79,6 +79,8 @@ #include "DNA_scene_types.h" /***/ +#include "GPU_extensions.h" + #ifdef __cplusplus extern "C" { #endif @@ -136,7 +138,12 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool usemat = false, useglslmat = false; if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) - usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0); + usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); + + if(GPU_extensions_minimum_support()) + useglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); + else if(G.fileflags & G_FILE_GAME_MAT_GLSL) + usemat = false; // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -191,6 +198,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, // some blender stuff MT_CmMatrix4x4 projmat; MT_CmMatrix4x4 viewmat; + float camzoom; int i; for (i = 0; i < 16; i++) @@ -204,8 +212,13 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, projmat.setElem(i, projmat_linear[i]); } - float camzoom = (1.41421 + (v3d->camzoom / 50.0)); - camzoom *= camzoom; + if(v3d->persp==V3D_CAMOB) { + camzoom = (1.41421 + (v3d->camzoom / 50.0)); + camzoom *= camzoom; + } + else + camzoom = 2.0; + camzoom = 4.0 / camzoom; ketsjiengine->SetDrawType(v3d->drawtype); @@ -286,6 +299,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(projmat); ketsjiengine->SetCameraOverrideViewMatrix(viewmat); + ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } // create a scene converter, create and convert the startingscene @@ -294,23 +308,24 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); - - if(usemat) + + if(usemat && (G.fileflags & G_FILE_GAME_MAT)) sceneconverter->SetMaterials(true); - if(useglslmat) + if(useglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(keyboarddevice, mousedevice, networkdevice, audiodevice, - startscenename); + startscenename, + blscene); // some python things PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest); ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module. PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. initGameKeys(); @@ -526,8 +541,6 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, // create the ketsjiengine KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem); - int i; - Scene *blscene = NULL; if (!bfd) { @@ -543,7 +556,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, } else { blscene = bfd->curscene; } - int cframe,startFrame; + int cframe = 1, startFrame; if (blscene) { cframe=blscene->r.cfra; @@ -574,12 +587,14 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, mousedevice, networkdevice, audiodevice, - startscenename); + startscenename, + blscene); + // some python things PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest); ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 1d72fb9cde1..340a1ae310b 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -31,6 +31,7 @@ SET(INC ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader + ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ../../../extern/glew/include diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index da52be56d1b..669e7bd1b3f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -26,7 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "GL/glew.h" #include "KX_BlenderGL.h" #ifdef HAVE_CONFIG_H @@ -93,80 +92,6 @@ void BL_SwapBuffers() myswapbuffers(); } -void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface, - unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]) -{ - Image* ima; - - if(mode & TF_BMFONT) { - //char string[MAX_PROPSTRING]; - int characters, index, character; - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - -// bProperty *prop; - - // string = "Frank van Beek"; - - characters = textlen; - - ima = (struct Image*) tface->tpage; - if (ima == NULL) { - characters = 0; - } - - /* When OBCOL flag is on the color is set in IndexPrimitives_3DText */ - if (tface->mode & TF_OBCOL) { /* Color has been set */ - col= NULL; - } else { - if(!col) glColor3f(1.0f, 1.0f, 1.0f); - } - - glPushMatrix(); - for (index = 0; index < characters; index++) { - // lets calculate offset stuff - character = textstr[index]; - - // space starts at offset 1 - // character = character - ' ' + 1; - - matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - - glBegin(GL_POLYGON); - // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], ); - // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - - if(col) spack(col[0]); - // glVertex3fv(v1); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); - if(col) spack(col[1]); - // glVertex3fv(v2); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - - glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); - if(col) spack(col[2]); - // glVertex3fv(v3); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(v4) { - // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy); - glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); - if(col) spack(col[3]); - // glVertex3fv(v4); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - glEnd(); - - glTranslatef(advance, 0.0, 0.0); - } - glPopMatrix(); - - } -} - - void DisableForText() { if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h index c8e0d47afb6..b891a7343c2 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.h @@ -46,9 +46,6 @@ void BL_HideMouse(); void BL_NormalMouse(); void BL_WaitMouse(); -void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface, - unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]); - void BL_print_gamedebug_line(char* text, int xco, int yco, int width, int height); void BL_print_gamedebug_line_padded(char* text, int xco, int yco, int width, int height); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index e4eff163d5b..1797d6c1a0f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -26,8 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "KX_BlenderRenderTools.h" - #include "GL/glew.h" #include "RAS_IRenderTools.h" @@ -36,23 +34,22 @@ #include "RAS_ICanvas.h" #include "RAS_GLExtensionManager.h" -// next two includes/dependencies come from the shadow feature -// it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" - #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" - -#include "Value.h" - -#include "KX_BlenderGL.h" // for text printing -#include "STR_String.h" -#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting) - #include "KX_RayCast.h" #include "KX_IPhysicsController.h" + #include "PHY_IPhysicsEnvironment.h" -#include "KX_Scene.h" + +#include "STR_String.h" + +#include "GPU_draw.h" + +#include "KX_BlenderGL.h" // for text printing +#include "KX_BlenderRenderTools.h" + +unsigned int KX_BlenderRenderTools::m_numgllights; KX_BlenderRenderTools::KX_BlenderRenderTools() { @@ -61,81 +58,98 @@ KX_BlenderRenderTools::KX_BlenderRenderTools() m_numgllights = 8; } -/** -ProcessLighting performs lighting on objects. the layer is a bitfield that contains layer information. -There are 20 'official' layers in blender. -A light is applied on an object only when they are in the same layer. -OpenGL has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in a scene. -*/ - -int KX_BlenderRenderTools::ProcessLighting(int layer) +KX_BlenderRenderTools::~KX_BlenderRenderTools() { - - int result = false; - - if (layer < 0) - { - DisableOpenGLLights(); - result = false; - } else - { - if (m_clientobject) - { - if (layer == RAS_LIGHT_OBJECT_LAYER) - { - layer = static_cast(m_clientobject)->GetLayer(); - } - if (applyLights(layer)) - { - EnableOpenGLLights(); - result = true; - } else - { - DisableOpenGLLights(); - result = false; - } - } - } - return result; - - } - void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) { m_clientobject = NULL; - m_lastblenderobject = NULL; - m_lastblenderlights = false; - m_lastlayer = -1; + m_lastlightlayer = -1; m_lastlighting = false; - m_modified = true; DisableOpenGLLights(); - - } -void KX_BlenderRenderTools::SetClientObject(void* obj) +void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) +{ +} + +/* ProcessLighting performs lighting on objects. the layer is a bitfield that + * contains layer information. There are 20 'official' layers in blender. A + * light is applied on an object only when they are in the same layer. OpenGL + * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in + * a scene. */ + +void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) +{ + if(m_lastlightlayer == layer) + return; + + m_lastlightlayer = layer; + + bool enable = false; + + if (layer >= 0) + { + if (m_clientobject) + { + if (layer == RAS_LIGHT_OBJECT_LAYER) + layer = static_cast(m_clientobject)->GetLayer(); + + enable = applyLights(layer, viewmat); + } + } + + if(enable) + EnableOpenGLLights(); + else + DisableOpenGLLights(); +} + +void KX_BlenderRenderTools::EnableOpenGLLights() +{ + if(m_lastlighting == true) + return; + + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + + m_lastlighting = true; +} + +void KX_BlenderRenderTools::DisableOpenGLLights() +{ + if(m_lastlighting == false) + return; + + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + + m_lastlighting = false; +} + + +void KX_BlenderRenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) { if (m_clientobject != obj) { - if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) - { - glFrontFace(GL_CCW); - } else - { - glFrontFace(GL_CW); - } + bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); + rasty->SetFrontFace(ccw); + m_clientobject = obj; - m_modified = true; } } -bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { double* const oglmatrix = (double* const) data; - MT_Point3 resultpoint(hit_point); - MT_Vector3 resultnormal(hit_normal); + MT_Point3 resultpoint(result->m_hitPoint); + MT_Vector3 resultnormal(result->m_hitNormal); MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); left = (dir.cross(resultnormal)).safe_normalized(); @@ -182,7 +196,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat MT_Vector3 dir = (campos - objpos).safe_normalized(); MT_Vector3 up(0,0,1.0); - KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; + KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; // get scaling of halo object MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); @@ -218,7 +232,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat { // shadow must be cast to the ground, physics system needed here! MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; + KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; MT_Vector3 direction = MT_Vector3(0,0,-1); direction.normalize(); @@ -236,9 +250,8 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat if (parent) parent->Release(); - MT_Point3 resultpoint; - MT_Vector3 resultnormal; - if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this, oglmatrix))) + KX_RayCast::Callback callback(this, physics_controller, oglmatrix); + if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) { // couldn't find something to cast the shadow on... glMultMatrixd(oglmatrix); @@ -253,13 +266,29 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat } -/** -Render Text renders text into a (series of) polygon, using a texture font, -Each character consists of one polygon (one quad or two triangles) -*/ -void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float v1[3],float v2[3],float v3[3],float v4[3]) +void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height) +{ + STR_String tmpstr(text); + + if(mode == RAS_IRenderTools::RAS_TEXT_PADDED) + BL_print_gamedebug_line_padded(tmpstr.Ptr(), xco, yco, width, height); + else + BL_print_gamedebug_line(tmpstr.Ptr(), xco, yco, width, height); +} + +/* Render Text renders text into a (series of) polygon, using a texture font, + * Each character consists of one polygon (one quad or two triangles) */ + +void KX_BlenderRenderTools::RenderText( + int mode, + RAS_IPolyMaterial* polymat, + float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { - STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); @@ -276,68 +305,10 @@ void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float col = blenderpoly->GetMCol(); } - BL_RenderText( mode,mytext,mytext.Length(),tface,col,v1,v2,v3,v4); - + GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); } - -KX_BlenderRenderTools::~KX_BlenderRenderTools() -{ -}; - - -void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) -{ -} - - - -void KX_BlenderRenderTools::DisableOpenGLLights() -{ - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); -} - - -void KX_BlenderRenderTools::EnableOpenGLLights() -{ - glEnable(GL_LIGHTING); - - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); - if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - -} - - -/** - * Rendering text using 2D bitmap functionality. - */ -void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height) -{ - switch (mode) { - case RAS_IRenderTools::RAS_TEXT_PADDED: { - STR_String tmpstr(text); - BL_print_gamedebug_line_padded(tmpstr.Ptr(),xco,yco,width,height); - break; - } - default: { - STR_String tmpstr(text); - BL_print_gamedebug_line(tmpstr.Ptr(),xco,yco,width,height); - } - } -} - - - void KX_BlenderRenderTools::PushMatrix() { glPushMatrix(); @@ -349,14 +320,13 @@ void KX_BlenderRenderTools::PopMatrix() } - -int KX_BlenderRenderTools::applyLights(int objectlayer) +int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) { -// taken from blender source, incompatibility between Blender Object / GameObject - + // taken from blender source, incompatibility between Blender Object / GameObject + float glviewmat[16]; unsigned int count; float vec[4]; - + vec[3]= 1.0; for(count=0; count m_lights; std::vector::iterator lit = m_lights.begin(); + + viewmat.getValue(glviewmat); glPushMatrix(); - glLoadMatrixf(m_viewmat); + glLoadMatrixf(glviewmat); for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) { RAS_LightObject* lightdata = (*lit); @@ -434,7 +406,6 @@ int KX_BlenderRenderTools::applyLights(int objectlayer) glEnable((GLenum)(GL_LIGHT0+count)); count++; - } } glPopMatrix(); @@ -443,22 +414,6 @@ int KX_BlenderRenderTools::applyLights(int objectlayer) } - - -RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant,bool zsort, int lightlayer - ,bool bIsTriangle,void* clientobject,void* tface) -{ - assert(!"Deprecated"); -/* return new KX_BlenderPolyMaterial( - - texname, - ba,matname,tile,tilexrep,tileyrep,mode,transparant,zsort, lightlayer - ,bIsTriangle,clientobject,(struct MTFace*)tface);*/ - return NULL; -} - void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) { int state = rasterizer->GetMotionBlurState(); @@ -492,4 +447,3 @@ void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas) m_filtermanager.RenderFilters(canvas); } -unsigned int KX_BlenderRenderTools::m_numgllights; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index 8abce1b8c3e..a7618462c9b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -26,6 +26,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ + #ifndef __KX_BLENDERRENDERTOOLS #define __KX_BLENDERRENDERTOOLS @@ -37,67 +38,54 @@ #include "RAS_IRenderTools.h" struct KX_ClientObjectInfo; +class KX_RayCast; -/** -BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which are not -part of the (polygon) Rasterizer. -Effects like 2D text, 3D (polygon) text, lighting. -*/ +/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which + * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon) + * text, lighting. + * + * Most of this code is duplicated in GPC_RenderTools, so this should be + * moved to some common location to avoid duplication. */ class KX_BlenderRenderTools : public RAS_IRenderTools { - bool m_lastblenderlights; - void* m_lastblenderobject; - int m_lastlayer; + int m_lastlightlayer; bool m_lastlighting; static unsigned int m_numgllights; - - + public: - KX_BlenderRenderTools(); virtual ~KX_BlenderRenderTools(); - virtual void EndFrame(class RAS_IRasterizer* rasty); - virtual void BeginFrame(class RAS_IRasterizer* rasty); - void DisableOpenGLLights(); - void EnableOpenGLLights(); - int ProcessLighting(int layer); + void EndFrame(RAS_IRasterizer* rasty); + void BeginFrame(RAS_IRasterizer* rasty); - virtual void RenderText2D(RAS_TEXT_RENDER_MODE mode, + void EnableOpenGLLights(); + void DisableOpenGLLights(); + void ProcessLighting(int layer, const MT_Transform& viewmat); + + void RenderText2D(RAS_TEXT_RENDER_MODE mode, const char* text, int xco, int yco, int width, int height); - virtual void RenderText(int mode, + void RenderText(int mode, class RAS_IPolyMaterial* polymat, float v1[3], float v2[3], float v3[3], - float v4[3]); - void applyTransform(class RAS_IRasterizer* rasty, - double* oglmatrix, - int objectdrawmode ); - int applyLights(int objectlayer); - virtual void PushMatrix(); - virtual void PopMatrix(); + float v4[3], + int glattrib); - virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - void* tface); - - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); + int applyLights(int objectlayer, const MT_Transform& viewmat); + + void PushMatrix(); + void PopMatrix(); + + bool RayHit(KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo*) { return true; } virtual void MotionBlur(RAS_IRasterizer* rasterizer); @@ -105,8 +93,7 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); - virtual void SetClientObject(void* obj); - + virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); }; #endif //__KX_BLENDERRENDERTOOLS diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index a7394158a20..4b9a2a3af17 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -54,6 +54,7 @@ CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/render/extern/include CPPFLAGS += -I../../blender/blenloader CPPFLAGS += -I../../blender/blenkernel +CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I../Converter CPPFLAGS += -I../Expressions CPPFLAGS += -I../GameLogic @@ -72,9 +73,5 @@ ifeq ($(OS),windows) CPPFLAGS += -I../../blender endif -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 327f4798e04..78adbc83d9b 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -15,7 +15,7 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' incs += ' #source/gameengine/Physics/Bullet #source/gameengine/Physics/Sumo' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader' -incs += ' #extern/glew/include' +incs += ' #extern/glew/include #source/blender/gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SOLID_INC'] @@ -26,7 +26,4 @@ cxxflags = [] if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index d8b2e063a9d..119465c8726 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -50,6 +50,7 @@ #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" #include "FloatValue.h" +#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index 09f1d9d4d87..bf774bf7568 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -53,15 +53,20 @@ BL_ArmatureObject::BL_ArmatureObject( : KX_GameObject(sgReplicationInfo,callbacks), m_objArma(armature), - m_mrdPose(NULL), - m_lastframe(0.), + m_framePose(NULL), + m_lastframe(0.0), m_activeAct(NULL), - m_activePriority(999) + m_activePriority(999), + m_lastapplyframe(0.0) { m_armature = get_armature(m_objArma); - m_pose = m_objArma->pose; -} + /* we make a copy of blender object's pose, and then always swap it with + * the original pose before calling into blender functions, to deal with + * replica's or other objects using the same blender object */ + m_pose = NULL; + copy_pose(&m_pose, m_objArma->pose, 1 /* copy_constraint_channels_hack */); +} CValue* BL_ArmatureObject::GetReplica() { @@ -78,34 +83,39 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) { KX_GameObject::ProcessReplica(replica); + replica->m_pose = NULL; + copy_pose(&replica->m_pose, m_pose, 1 /* copy_constraint_channels_hack */); } BL_ArmatureObject::~BL_ArmatureObject() { - if (m_mrdPose) - free_pose(m_mrdPose); + if (m_pose) + free_pose(m_pose); +} + +bool BL_ArmatureObject::VerifyPose() +{ + if(m_lastapplyframe != m_lastframe) { + extract_pose_from_pose(m_objArma->pose, m_pose); + where_is_pose(m_objArma); + m_lastapplyframe = m_lastframe; + extract_pose_from_pose(m_pose, m_objArma->pose); + return false; + } + else + return true; } -/* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */ -/* there is only 1 unique Pose per Armature */ void BL_ArmatureObject::ApplyPose() { - if (m_pose) { - // copy to armature object - if (m_objArma->pose != m_pose)/* This should never happen but it does - Campbell */ - extract_pose_from_pose(m_objArma->pose, m_pose); - - // is this needed anymore? - //if (!m_mrdPose) - // copy_pose (&m_mrdPose, m_pose, 0); - //else - // extract_pose_from_pose(m_mrdPose, m_pose); - } + if(VerifyPose()) + extract_pose_from_pose(m_objArma->pose, m_pose); } void BL_ArmatureObject::SetPose(bPose *pose) { - m_pose = pose; + extract_pose_from_pose(m_pose, pose); + m_lastapplyframe = -1.0; } bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime) @@ -114,10 +124,15 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, m_activePriority = 9999; m_lastframe= curtime; m_activeAct = NULL; + // remember the pose at the start of the frame + m_framePose = m_pose; } if (priority<=m_activePriority) { + if (prioritySetBlendTime(0.0); /* Reset the blend timer */ m_activeAct = act; @@ -156,6 +171,7 @@ void BL_ArmatureObject::GetPose(bPose **pose) if (*pose == m_pose) // no need to copy if the pointers are the same return; + extract_pose_from_pose(*pose, m_pose); } } @@ -165,20 +181,16 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) /* If the caller supplies a null pose, create a new one. */ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */ - // is this needed anymore? - //if (!m_mrdPose){ - // copy_pose (&m_mrdPose, m_pose, 0); - //} - if (!*pose) { // must duplicate the constraints too otherwise we have corruption in free_pose_channels() // because it will free the blender constraints. // Ideally, blender should rememeber that the constraints were not copied so that // free_pose_channels() would not free them. - copy_pose(pose, m_objArma->pose, 1); + copy_pose(pose, m_pose, 1); + } + else { + extract_pose_from_pose(*pose, m_pose); } - else - extract_pose_from_pose(*pose, m_objArma->pose); } @@ -192,16 +204,18 @@ double BL_ArmatureObject::GetLastFrame() return m_lastframe; } -bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const +bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) { - Object* par_arma = m_objArma; - where_is_pose(par_arma); - bPoseChannel *pchan= get_pose_channel(par_arma->pose, bone->name); + bPoseChannel *pchan; + + ApplyPose(); + pchan = get_pose_channel(m_objArma->pose, bone->name); if(pchan) { matrix.setValue(&pchan->pose_mat[0][0]); return true; } + return false; } diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 752bd5eb365..6f2c0d2f4c9 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -59,7 +59,10 @@ public: void GetMRDPose(struct bPose **pose); void GetPose(struct bPose **pose); void SetPose (struct bPose *pose); + void ApplyPose(); + bool VerifyPose(); + bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime); struct bArmature * GetArmature() { return m_armature; } @@ -69,7 +72,7 @@ public: /// Retrieve the pose matrix for the specified bone. /// Returns true on success. - bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const; + bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix); /// Returns the bone length. The end of the bone is in the local y direction. float GetBoneLength(Bone* bone) const; @@ -79,10 +82,12 @@ protected: Object *m_objArma; struct bArmature *m_armature; struct bPose *m_pose; - struct bPose *m_mrdPose; + struct bPose *m_framePose; double m_lastframe; class BL_ActionActuator *m_activeAct; short m_activePriority; + + double m_lastapplyframe; }; #endif diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index edc14dabc70..8bdec219354 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -377,6 +377,7 @@ BL_Material* ConvertMaterial( material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; + material->flag[i] |= MIPMAP; if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; @@ -601,7 +602,6 @@ BL_Material* ConvertMaterial( (tface->mode & TF_INVISIBLE) )?POLY_VIS:0; - material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; material->tile = tface->tile; material->mode = tface->mode; @@ -617,7 +617,7 @@ BL_Material* ConvertMaterial( } else { // nothing at all - material->ras_mode |= (COLLIDER|POLY_VIS| (validmat?0:USE_LIGHT)); + material->ras_mode |= (POLY_VIS| (validmat?0:USE_LIGHT)); material->mode = default_face_mode; material->transp = TF_SOLID; material->tile = 0; @@ -627,13 +627,19 @@ BL_Material* ConvertMaterial( if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID)) material->transp = TF_ALPHA; - // always zsort alpha + add - if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) - && (material->transp != TF_CLIP)) { + // always zsort alpha + add + if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) { material->ras_mode |= ALPHA; material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; } + // collider or not? + material->ras_mode |= (material->mode & TF_DYNAMIC)? COLLIDER: 0; + + // these flags are irrelevant at this point, remove so they + // don't hurt material bucketing + material->mode &= ~(TF_DYNAMIC|TF_ALPHASORT|TF_TEX); + // get uv sets if(validmat) { @@ -644,6 +650,7 @@ BL_Material* ConvertMaterial( for (int vind = 0; vindnum_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; + if (map.uvCoName.IsEmpty()) isFirstSet = false; else @@ -673,7 +680,7 @@ BL_Material* ConvertMaterial( isFirstSet = false; uvName = layer.name; } - else + else if(strcmp(layer.name, uvName) != 0) { uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; @@ -702,7 +709,6 @@ BL_Material* ConvertMaterial( material->SetConversionUV(uvName, uv); material->SetConversionUV2(uv2Name, uv2); - material->ras_mode |= (mface->v4==0)?TRIANGLE:0; if(validmat) material->matname =(mat->id.name); @@ -767,7 +773,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); + meshobj->m_sharedvertex_map.resize(totvert); for (int f=0;fv1].co); @@ -801,8 +807,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* NormalShortToFloat(n3, mvert[mface->v4].no); no3 = n3; } - else - no3 = MT_Vector3(0.0, 0.0, 0.0); } else { float fno[3]; @@ -830,7 +834,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* ma = give_current_material(blenderobj, mface->mat_nr+1); { - bool polyvisible = true; + bool visible = true; RAS_IPolyMaterial* polymat = NULL; BL_Material *bl_mat = NULL; @@ -845,7 +849,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* bl_mat->material_index = (int)mface->mat_nr; - polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); + visible = ((bl_mat->ras_mode & POLY_VIS)!=0); collider = ((bl_mat->ras_mode & COLLIDER)!=0); /* vertex colors and uv's were stored in bl_mat temporarily */ @@ -862,7 +866,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* uv22 = uv[2]; uv23 = uv[3]; /* then the KX_BlenderMaterial */ - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer); } else { /* do Texture Face materials */ @@ -886,7 +890,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* tile = tface->tile; mode = tface->mode; - polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); uv0 = MT_Point2(tface->uv[0]); uv1 = MT_Point2(tface->uv[1]); @@ -940,15 +944,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rgb3 = KX_rgbaint2uint_new(color); } - bool istriangle = (mface->v4==0); - // only zsort alpha + add bool alpha = (transp == TF_ALPHA || transp == TF_ADD); bool zsort = (mode & TF_ALPHASORT)? alpha: 0; polymat = new KX_PolygonMaterial(imastr, ma, tile, tilexrep, tileyrep, - mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol); + mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol); if (ma) { polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; @@ -961,6 +963,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } } + /* mark face as flat, so vertices are split */ + bool flat = (mface->flag & ME_SMOOTH) == 0; + // see if a bucket was reused or a new one was created // this way only one KX_BlenderMaterial object has to exist per bucket bool bucketCreated; @@ -981,49 +986,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* polymat = bucket->GetPolyMaterial(); } - int nverts = mface->v4?4:3; - int vtxarray = meshobj->FindVertexArray(nverts,polymat); - RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); + int nverts = (mface->v4)? 4: 3; + RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts); - bool flat; - - if (skinMesh) { - /* If the face is set to solid, all fnors are the same */ - if (mface->flag & ME_SMOOTH) - flat = false; - else - flat = true; - } - else - flat = false; - - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); - - meshobj->AddPolygon(poly); - if (poly->IsCollider()) - { - RAS_TriangleIndex idx; - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v2; - idx.m_index[2] = mface->v3; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - if (nverts==4) - { - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v3; - idx.m_index[2] = mface->v4; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - } - } - -// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetVisible(visible); poly->SetCollider(collider); + //poly->SetEdgeCode(mface->edcode); + + meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1); + meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2); + meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3); + + if (nverts==4) + meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4); } if (tface) @@ -1039,13 +1014,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* layer.face++; } } - meshobj->m_xyz_index_to_vertex_index_mapping.clear(); - meshobj->UpdateMaterialList(); + meshobj->m_sharedvertex_map.clear(); // pre calculate texture generation - for(RAS_MaterialBucket::Set::iterator mit = meshobj->GetFirstMaterial(); + for(list::iterator mit = meshobj->GetFirstMaterial(); mit != meshobj->GetLastMaterial(); ++ mit) { - (*mit)->GetPolyMaterial()->OnConstruction(); + mit->m_bucket->GetPolyMaterial()->OnConstruction(); } if (layers) @@ -1305,6 +1279,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, //int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0); //bool bRigidBody = (userigidbody == 0); + // object has physics representation? + if (!(blenderobject->gameflag & OB_PHYSICS)) + return; + // get Root Parent of blenderobject struct Object* parent= blenderobject->parent; while(parent && parent->parent) { @@ -1336,6 +1314,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_isCompoundChild = isCompoundChild; objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; + objprop.m_margin = blenderobject->margin; if ((objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0)) { @@ -1490,14 +1469,9 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l lightobj.m_type = RAS_LightObject::LIGHT_NORMAL; } -#ifdef BLENDER_GLSL - if(converter->GetGLSLMaterials()) - GPU_lamp_from_blender(ob, la); - - gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, ob->gpulamp); -#else - gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, NULL); -#endif + gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, + lightobj, converter->GetGLSLMaterials()); + BL_ConvertLampIpos(la, gamelight, converter); return gamelight; @@ -1534,7 +1508,7 @@ static KX_GameObject *gameobject_from_blenderobject( gamelight->AddRef(); kxscene->GetLightList()->Add(gamelight); - + break; } @@ -1643,20 +1617,6 @@ struct parentChildLink { SG_Node* m_gamechildnode; }; - /** - * Find the specified scene by name, or the first - * scene if nothing matches (shouldn't happen). - */ -static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scenename) { - Scene *sce; - - for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) - if (scenename == (sce->id.name+2)) - return sce; - - return (Scene*) maggie->scene.first; -} - #include "DNA_constraint_types.h" #include "BIF_editconstraint.h" @@ -1755,7 +1715,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, ) { - Scene *blenderscene = GetSceneForName(maggie, scenename); + Scene *blenderscene = converter->GetBlenderSceneForName(scenename); // for SETLOOPER Scene *sce; Base *base; @@ -1990,7 +1950,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //tf.Add(gameobj->GetSGNode()); gameobj->NodeUpdateGS(0,true); - gameobj->Bucketize(); + gameobj->AddMeshUser(); } else @@ -2187,8 +2147,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //tf.Add(gameobj->GetSGNode()); gameobj->NodeUpdateGS(0,true); - gameobj->Bucketize(); - + gameobj->AddMeshUser(); } else { @@ -2230,16 +2189,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for(oit=allblobj.begin(); oit!=allblobj.end(); oit++) { Object* blenderobj = *oit; - if (blenderobj->type==OB_MESH){ + if (blenderobj->type==OB_MESH) { Mesh *me = (Mesh*)blenderobj->data; if (me->dvert){ - KX_GameObject *obj = converter->FindGameObject(blenderobj); + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)converter->FindGameObject(blenderobj); if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ KX_GameObject *par = converter->FindGameObject(blenderobj->parent); - if (par) - ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); + if (par && obj->m_pDeformer) + ((BL_SkinDeformer*)obj->m_pDeformer)->SetArmature((BL_ArmatureObject*) par); } } } @@ -2253,6 +2212,41 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { struct Object* blenderchild = pcit->m_blenderchild; + struct Object* blenderparent = blenderchild->parent; + KX_GameObject* parentobj = converter->FindGameObject(blenderparent); + KX_GameObject* childobj = converter->FindGameObject(blenderchild); + + assert(childobj); + + if (!parentobj || objectlist->SearchValue(childobj) != objectlist->SearchValue(parentobj)) + { + // special case: the parent and child object are not in the same layer. + // This weird situation is used in Apricot for test purposes. + // Resolve it by not converting the child + childobj->GetSGNode()->DisconnectFromParent(); + delete pcit->m_gamechildnode; + // Now destroy the child object but also all its descendent that may already be linked + // Remove the child reference in the local list! + // Note: there may be descendents already if the children of the child were processed + // by this loop before the child. In that case, we must remove the children also + CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj); + childrenlist->Add(childobj->AddRef()); + for ( i=0;iGetCount();i++) + { + KX_GameObject* obj = static_cast(childrenlist->GetValue(i)); + if (templist->RemoveValue(obj)) + obj->Release(); + if (sumolist->RemoveValue(obj)) + obj->Release(); + if (logicbrick_conversionlist->RemoveValue(obj)) + obj->Release(); + } + childrenlist->Release(); + // now destroy recursively + kxscene->RemoveObject(childobj); + continue; + } + switch (blenderchild->partype) { case PARVERT1: @@ -2273,8 +2267,11 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { // parent this to a bone Bone *parent_bone = get_named_bone(get_armature(blenderchild->parent), blenderchild->parsubstr); - KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); - pcit->m_gamechildnode->SetParentRelation(bone_parent_relation); + + if(parent_bone) { + KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); + pcit->m_gamechildnode->SetParentRelation(bone_parent_relation); + } break; } @@ -2289,12 +2286,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, break; } - struct Object* blenderparent = blenderchild->parent; - KX_GameObject* parentobj = converter->FindGameObject(blenderparent); - if (parentobj) - { - parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode); - } + parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode); } vec_parent_child.clear(); @@ -2511,5 +2503,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie, kxscene->DupliGroupRecurse(gameobj, 0); } } + + KX_Camera *activecam = kxscene->GetActiveCamera(); + MT_Scalar distance = (activecam)? activecam->GetCameraFar() - activecam->GetCameraNear(): 100.0f; + RAS_BucketManager *bucketmanager = kxscene->GetBucketManager(); + bucketmanager->OptimizeBuckets(distance); } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index d23274324ee..1d62a41cce9 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -41,12 +41,14 @@ BL_DeformableGameObject::~BL_DeformableGameObject() delete m_pDeformer; // __NLA : Temporary until we decide where to put this } -void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) +void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) { + BL_MeshDeformer *deformer; KX_GameObject::ProcessReplica(replica); - if (m_pDeformer){ - ((BL_DeformableGameObject*)replica)->m_pDeformer = m_pDeformer->GetReplica(); + if (m_pDeformer) { + deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(); + ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer; } } diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index 39d66a90e92..fa3b8185fe2 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -50,26 +50,26 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { - size_t i, j; + size_t i; float *co; // only apply once per frame if the mesh is actually modified if(m_pMeshObject->MeshModified() && m_lastDeformUpdate != m_gameobj->GetLastFrame()) { // For each material - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + for(list::iterator mit= m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + if(!mit->m_slots[(void*)m_gameobj]) + continue; - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - - // For each array - for (i=0; im_slots[(void*)m_gameobj]; + RAS_MeshSlot::iterator it; + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { // For each vertex - for (j=0; jmvert[v.getOrigIndex()].co; v.SetXYZ(MT_Point3(co)); } @@ -90,7 +90,17 @@ BL_MeshDeformer::~BL_MeshDeformer() delete [] m_transverts; if (m_transnors) delete [] m_transnors; -}; +} + +void BL_MeshDeformer::Relink(GEN_Map*map) +{ + void **h_obj = (*map)[m_gameobj]; + + if (h_obj) + m_gameobj = (BL_DeformableGameObject*)(*h_obj); + else + m_gameobj = NULL; +} /** * @warning This function is expensive! @@ -101,41 +111,41 @@ void BL_MeshDeformer::RecalcNormals() * gives area-weight normals which often look better anyway, and use * GL_NORMALIZE so we don't have to do per vertex normalization either * since the GPU can do it faster */ - size_t i, j; + list::iterator mit; + RAS_MeshSlot::iterator it; + size_t i; /* set vertex normals to zero */ memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert); /* add face normals to vertices. */ - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + for(mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + if(!mit->m_slots[(void*)m_gameobj]) + continue; - const vecIndexArrays& indexarrays = m_pMeshObject->GetIndexCache(mat); - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; - for (i=0; iUsesTriangles()? 3: 4; + for(slot->begin(it); !slot->end(it); slot->next(it)) { + int nvert = (int)it.array->m_type; - for(j=0; jgetLocalXYZ(); + v4 = &it.vertex[it.index[i+3]]; + co4 = v4->getXYZ(); n1[0]= co1[0]-co3[0]; n1[1]= co1[1]-co3[1]; @@ -174,7 +184,7 @@ void BL_MeshDeformer::RecalcNormals() } /* in case of flat - just assign, the vertices are split */ - if(v1.getFlag() & TV_CALCFACENORMAL) { + if(v1.getFlag() & RAS_TexVert::FLAT) { v1.SetNormal(fnor); v2.SetNormal(fnor); v3.SetNormal(fnor); @@ -186,19 +196,18 @@ void BL_MeshDeformer::RecalcNormals() } /* assign smooth vertex normals */ - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + for(mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + if(!mit->m_slots[(void*)m_gameobj]) + continue; - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; - for (i=0; ibegin(it); !slot->end(it); slot->next(it)) { + for(i=it.startvertex; itotvert; } } - + diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index e9f7f0b192f..9d3d2e78123 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -47,7 +47,7 @@ class BL_MeshDeformer : public RAS_Deformer public: void VerifyStorage(); void RecalcNormals(); - virtual void Relink(GEN_Map*map){}; + virtual void Relink(GEN_Map*map); BL_MeshDeformer(BL_DeformableGameObject *gameobj, struct Object* obj, class BL_SkinMeshObject *meshobj ): @@ -67,6 +67,7 @@ public: virtual RAS_Deformer* GetReplica(){return NULL;}; struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; + protected: class BL_SkinMeshObject* m_pMeshObject; struct Mesh* m_bmesh; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 942e3b502e0..679b0df7ec6 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -49,6 +49,7 @@ #include "BLI_arithb.h" #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" +#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include @@ -134,7 +135,6 @@ void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight) { vector::const_iterator it; float dstweight; - int i; KeyBlock *kb; dstweight = 1.0F - srcweight; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index b2e54539b19..236cd1a6667 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -111,10 +111,7 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) int type; // the shape drivers use the bone matrix as input. Must // update the matrix now - Object* par_arma = m_armobj->GetArmatureObject(); m_armobj->ApplyPose(); - where_is_pose( par_arma ); - PoseApplied(true); for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { // no need to set a specific time: this curve has a driver diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 5f0188e3a42..1465bb01e22 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -43,17 +43,6 @@ struct IpoCurve; class BL_ShapeDeformer : public BL_SkinDeformer { public: - virtual void Relink(GEN_Map*map) - { - void **h_obj = (*map)[m_gameobj]; - if (h_obj){ - m_gameobj = (BL_DeformableGameObject*)(*h_obj); - } - else - m_gameobj=NULL; - // relink the underlying skin deformer - BL_SkinDeformer::Relink(map); - }; BL_ShapeDeformer(BL_DeformableGameObject *gameobj, Object *bmeshobj, BL_SkinMeshObject *mesh) diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index f96c40c098f..d8e7a9cdadf 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -99,9 +99,26 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } +void BL_SkinDeformer::Relink(GEN_Map*map) +{ + if (m_armobj) { + void **h_obj = (*map)[m_armobj]; + + if (h_obj) + SetArmature( (BL_ArmatureObject*)(*h_obj) ); + else + m_armobj=NULL; + } + + BL_MeshDeformer::Relink(map); +} + bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) { - size_t i, j; + RAS_MeshSlot::iterator it; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + size_t i; // update the vertex in m_transverts Update(); @@ -110,16 +127,18 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) // share the same mesh (=the same cache). As the rendering is done per polymaterial // cycling through the objects, the entire mesh cache cannot be updated in one shot. - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + mmat = m_pMeshObject->GetMeshMaterial(mat); + if(!mmat->m_slots[(void*)m_gameobj]) + return true; - // For each array - for (i=0; im_slots[(void*)m_gameobj]; - // For each vertex + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { + // for each vertex // copy the untransformed data from the original mvert - for (j=0; jGetArmatureObject(); - if (!PoseApplied()){ - m_armobj->ApplyPose(); - where_is_pose( par_arma ); - } /* store verts locally */ VerifyStorage(); @@ -163,6 +178,8 @@ bool BL_SkinDeformer::Update(void) for (int v =0; vtotvert; v++) VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); + m_armobj->ApplyPose(); + // save matrix first Mat4CpyMat4(obmat, m_objMesh->obmat); // set reference matrix @@ -179,11 +196,11 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); - /* reset for next frame */ - PoseApplied(false); + /* indicate that the m_transverts and normals are up to date */ return true; } + return false; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index d3fc5ae2a81..e08de8c478a 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -50,17 +50,7 @@ class BL_SkinDeformer : public BL_MeshDeformer { public: // void SetArmatureController (BL_ArmatureController *cont); - virtual void Relink(GEN_Map*map) - { - if (m_armobj){ - void **h_obj = (*map)[m_armobj]; - if (h_obj){ - SetArmature( (BL_ArmatureObject*)(*h_obj) ); - } - else - m_armobj=NULL; - } - } + virtual void Relink(GEN_Map*map); void SetArmature (class BL_ArmatureObject *armobj); BL_SkinDeformer(BL_DeformableGameObject *gameobj, @@ -81,10 +71,6 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); - bool PoseApplied() - { return m_poseApplied; } - void PoseApplied(bool applied) - { m_poseApplied = applied; } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp index fa215df1e1c..4f9f1a434b5 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.cpp +++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp @@ -28,42 +28,69 @@ * Deformer that supports armature skinning */ -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 -#include "RAS_IPolygonMaterial.h" -#include "BL_SkinMeshObject.h" -#include "BL_DeformableGameObject.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "KX_GameObject.h" + #include "RAS_BucketManager.h" +#include "RAS_IPolygonMaterial.h" -//void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,RAS_BucketManager* bucketmgr) -void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec) -{ +#include "KX_GameObject.h" - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_bObjectColor = useObjectColor; - ms.m_RGBAcolor = rgbavec; - ms.m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();it++) +#include "BL_SkinMeshObject.h" +#include "BL_DeformableGameObject.h" + +BL_SkinMeshObject::BL_SkinMeshObject(Mesh* mesh, int lightlayer) + : RAS_MeshObject (mesh, lightlayer) +{ + m_bDeformed = true; + + if (m_mesh && m_mesh->key) { + KeyBlock *kb; + int count=0; + // initialize weight cache for shape objects + // count how many keys in this mesh + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) + count++; + m_cacheWeightIndex.resize(count,-1); + } +} - RAS_MaterialBucket* materialbucket = (*it); +BL_SkinMeshObject::~BL_SkinMeshObject() +{ + if (m_mesh && m_mesh->key) + { + KeyBlock *kb; + // remove the weight cache to avoid memory leak + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { + if(kb->weights) + MEM_freeN(kb->weights); + kb->weights= NULL; + } + } +} -// KX_ArrayOptimizer* oa = GetArrayOptimizer(materialbucket->GetPolyMaterial()); - materialbucket->SetMeshSlot(ms); +void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool useObjectColor,const MT_Vector4& rgbavec, bool visible, bool culled) +{ + list::iterator it; + list::iterator sit; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + if(!it->m_slots[clientobj]) + continue; + + RAS_MeshSlot *slot = *it->m_slots[clientobj]; + slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; } + RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled); } static int get_def_index(Object* ob, const char* vgroup) @@ -74,6 +101,7 @@ static int get_def_index(Object* ob, const char* vgroup) for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++) if (!strcmp(curdef->name, vgroup)) return index; + return -1; } diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h index c21fb64204b..8544a2b958c 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.h +++ b/source/gameengine/Converter/BL_SkinMeshObject.h @@ -33,62 +33,27 @@ #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 -#include "MEM_guardedalloc.h" + #include "RAS_MeshObject.h" #include "RAS_Deformer.h" #include "RAS_IPolygonMaterial.h" #include "BL_MeshDeformer.h" -#include "DNA_mesh_types.h" -#include "DNA_key_types.h" -#include "DNA_meshdata_types.h" - class BL_SkinMeshObject : public RAS_MeshObject { - -// enum { BUCKET_MAX_INDICES = 16384};//2048};//8192}; -// enum { BUCKET_MAX_TRIANGLES = 4096}; - protected: vector m_cacheWeightIndex; public: - void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec); -// void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr); + BL_SkinMeshObject(Mesh* mesh, int lightlayer); + ~BL_SkinMeshObject(); - BL_SkinMeshObject(Mesh* mesh, int lightlayer) : RAS_MeshObject (mesh, lightlayer) - { - m_class = 1; - if (m_mesh && m_mesh->key) - { - KeyBlock *kb; - int count=0; - // initialize weight cache for shape objects - // count how many keys in this mesh - for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) - count++; - m_cacheWeightIndex.resize(count,-1); - } - }; - - virtual ~BL_SkinMeshObject() - { - if (m_mesh && m_mesh->key) - { - KeyBlock *kb; - // remove the weight cache to avoid memory leak - for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { - if(kb->weights) - MEM_freeN(kb->weights); - kb->weights= NULL; - } - } - }; + void UpdateBuckets(void* clientobj, double* oglmatrix, + bool useObjectColor, const MT_Vector4& rgbavec, bool visible, bool culled); // for shape keys, void CheckWeightCache(struct Object* obj); - }; #endif diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index adb7304b10e..217bdb30907 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -64,6 +64,7 @@ SET(INC ../../../source/gameengine/Network/LoopBackNetwork ../../../source/blender/misc ../../../source/blender/blenloader + ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ${PYTHON_INC} diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index de91bce2ab1..7eec93dc402 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -184,20 +184,21 @@ bool KX_BlenderSceneConverter::TryAndLoadNewFile() return result; } - +Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) +{ + Scene *sce; /** * Find the specified scene by name, or the first * scene if nothing matches (shouldn't happen). */ -static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& scenename) { - Scene *sce; - for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) - if (scenename == (sce->id.name+2)) + for (sce= (Scene*) m_maggie->scene.first; sce; sce= (Scene*) sce->id.next) + if (name == (sce->id.name+2)) return sce; - return (Scene*) maggie->scene.first; + return (Scene*)m_maggie->scene.first; + } #include "KX_PythonInit.h" @@ -245,6 +246,11 @@ struct BlenderDebugDraw : public btIDebugDraw { return m_debugMode; } + ///todo: find out if Blender can do this + virtual void draw3dText(const btVector3& location,const char* textString) + { + + } }; @@ -258,7 +264,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, class RAS_ICanvas* canvas) { //find out which physics engine - Scene *blenderscene = GetSceneForName2(m_maggie, scenename); + Scene *blenderscene = GetBlenderSceneForName(scenename); e_PhysicsEngine physics_engine = UseBullet; // hook for registration function during conversion. @@ -495,7 +501,17 @@ void KX_BlenderSceneConverter::RegisterGameObject( void KX_BlenderSceneConverter::UnregisterGameObject( KX_GameObject *gameobject) { - m_map_gameobject_to_blender.remove(CHashedPtr(gameobject)); + CHashedPtr gptr(gameobject); + struct Object **bobp= m_map_gameobject_to_blender[gptr]; + if (bobp) { + CHashedPtr bptr(*bobp); + KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; + if (gobp && *gobp == gameobject) + // also maintain m_map_blender_to_gameobject if the gameobject + // being removed is matching the blender object + m_map_blender_to_gameobject.remove(bptr); + m_map_gameobject_to_blender.remove(gptr); + } } @@ -644,13 +660,13 @@ extern "C" { Ipo *add_ipo( char *name, int idcode ); char *getIpoCurveName( IpoCurve * icu ); - struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); + struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); void testhandles_ipocurve(struct IpoCurve *icu); + void insert_vert_icu(struct IpoCurve *, float, float, short); void Mat3ToEul(float tmat[][3], float *eul); - } -IpoCurve* findIpoCurve(IpoCurve* first,char* searchName) +IpoCurve* findIpoCurve(IpoCurve* first, const char* searchName) { IpoCurve* icu1; for( icu1 = first; icu1; icu1 = icu1->next ) @@ -818,7 +834,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { - KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); + //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); if (blenderObject) @@ -846,7 +862,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) - const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); + //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Point3& position = gameObj->NodeGetWorldPosition(); Ipo* ipo = blenderObject->ipo; @@ -857,27 +873,27 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); @@ -974,7 +990,7 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { - KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); + //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); if (blenderObject) @@ -1002,8 +1018,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() - const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); + //const MT_Point3& position = gameObj->NodeGetWorldPosition(); Ipo* ipo = blenderObject->ipo; if (ipo) @@ -1013,27 +1029,27 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index e5d6ccc5caf..2317e952a0a 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -45,6 +45,7 @@ class BL_Material; struct IpoCurve; struct Main; struct SpaceIpo; +struct Scene; class KX_BlenderSceneConverter : public KX_ISceneConverter { @@ -151,6 +152,7 @@ public: virtual void SetGLSLMaterials(bool val); virtual bool GetGLSLMaterials(); + struct Scene* GetBlenderSceneForName(const STR_String& name); }; #endif //__KX_BLENDERSCENECONVERTER_H diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index b1f86afa4ee..e8be8de95ed 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -74,6 +74,8 @@ #include "BKE_text.h" #include "BLI_blenlib.h" +#define FILE_MAX 240 // repeated here to avoid dependency from BKE_utildefines.h + #include "KX_NetworkMessageActuator.h" #ifdef WIN32 @@ -355,22 +357,26 @@ void BL_ConvertActuators(char* maggiename, if (soundActuatorType != KX_SoundActuator::KX_SOUNDACT_NODEF) { - SND_SoundObject* sndobj = NULL; + SND_Scene* soundscene = scene->GetSoundScene(); + STR_String samplename = ""; + bool sampleisloaded = false; - if (soundact->sound) - { - SND_Scene* soundscene = scene->GetSoundScene(); - STR_String samplename = soundact->sound->name; + if (soundact->sound) { + /* Need to convert the samplename into absolute path + * before checking if its loaded */ + char fullpath[FILE_MAX]; - bool sampleisloaded = false; + /* dont modify soundact->sound->name, only change a copy */ + BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); + BLI_convertstringcode(fullpath, maggiename); + samplename = fullpath; /* let's see if the sample was already loaded */ if (soundscene->IsSampleLoaded(samplename)) { sampleisloaded = true; } - else - { + else { /* if not, make it so */ PackedFile* pf = soundact->sound->newpackedfile; @@ -383,25 +389,33 @@ void BL_ConvertActuators(char* maggiename, /* or else load it from disk */ else { - /* but we need to convert the samplename into absolute pathname first */ - char fullpath[sizeof(soundact->sound->name)]; - - /* dont modify soundact->sound->name, only change a copy */ - BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); - BLI_convertstringcode(fullpath, maggiename); - samplename = fullpath; - - /* and now we can load it */ - if (soundscene->LoadSample(samplename, NULL, 0) > -1) + if (soundscene->LoadSample(samplename, NULL, 0) > -1) { sampleisloaded = true; + } + else { + std::cout << "WARNING: Sound actuator \"" << bact->name << + "\" from object \"" << blenderobject->id.name+2 << + "\" failed to load sample." << std::endl; + } } } - - if (sampleisloaded) - { - sndobj = new SND_SoundObject(); - sndobj->SetSampleName(samplename.Ptr()); - sndobj->SetObjectName(bact->name); + } else { + std::cout << "WARNING: Sound actuator \"" << bact->name << + "\" from object \"" << blenderobject->id.name+2 << + "\" has no sound datablock." << std::endl; + } + + /* Note, allowing actuators for sounds that are not there was added since 2.47 + * This is because python may expect the actuator and raise an exception if it dosnt find it + * better just to add a dummy sound actuator. */ + SND_SoundObject* sndobj = NULL; + if (sampleisloaded) + { + /* setup the SND_SoundObject */ + sndobj = new SND_SoundObject(); + sndobj->SetSampleName(samplename.Ptr()); + sndobj->SetObjectName(bact->name); + if (soundact->sound) { sndobj->SetRollOffFactor(soundact->sound->attenuation); sndobj->SetGain(soundact->sound->volume); sndobj->SetPitch(exp((soundact->sound->pitch / 12.0) * log(2.0))); @@ -414,8 +428,9 @@ void BL_ConvertActuators(char* maggiename, else sndobj->SetLoopMode(SND_LOOP_NORMAL); } - else + else { sndobj->SetLoopMode(SND_LOOP_OFF); + } if (soundact->sound->flags & SOUND_FLAGS_PRIORITY) sndobj->SetHighPriority(true); @@ -426,22 +441,30 @@ void BL_ConvertActuators(char* maggiename, sndobj->Set3D(true); else sndobj->Set3D(false); - - KX_SoundActuator* tmpsoundact = - new KX_SoundActuator(gameobj, - sndobj, - scene->GetSoundScene(), // needed for replication! - soundActuatorType, - startFrame, - stopFrame); - - tmpsoundact->SetName(bact->name); - baseact = tmpsoundact; - soundscene->AddObject(sndobj); - } else { - std::cout << "WARNING: Sound actuator " << bact->name << " failed to load sample." << std::endl; + } + else { + /* dummy values for a NULL sound + * see editsound.c - defaults are unlikely to change soon */ + sndobj->SetRollOffFactor(1.0); + sndobj->SetGain(1.0); + sndobj->SetPitch(1.0); + sndobj->SetLoopMode(SND_LOOP_OFF); + sndobj->SetHighPriority(false); + sndobj->Set3D(false); } } + KX_SoundActuator* tmpsoundact = + new KX_SoundActuator(gameobj, + sndobj, + scene->GetSoundScene(), // needed for replication! + soundActuatorType, + startFrame, + stopFrame); + + tmpsoundact->SetName(bact->name); + baseact = tmpsoundact; + if (sndobj) + soundscene->AddObject(sndobj); } break; } @@ -554,10 +577,16 @@ void BL_ConvertActuators(char* maggiename, originalval = converter->FindGameObject(editobact->ob); } } - MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]), + MT_Vector3 linvelvec ( + KX_BLENDERTRUNC(editobact->linVelocity[0]), KX_BLENDERTRUNC(editobact->linVelocity[1]), KX_BLENDERTRUNC(editobact->linVelocity[2])); - + + MT_Vector3 angvelvec ( + KX_BLENDERTRUNC(editobact->angVelocity[0]), + KX_BLENDERTRUNC(editobact->angVelocity[1]), + KX_BLENDERTRUNC(editobact->angVelocity[2])); + KX_SCA_AddObjectActuator* tmpaddact = new KX_SCA_AddObjectActuator( gameobj, @@ -565,7 +594,9 @@ void BL_ConvertActuators(char* maggiename, editobact->time, scene, linvelvec.getValue(), - editobact->localflag!=0 + (editobact->localflag & ACT_EDOB_LOCAL_LINV)!=0, + angvelvec.getValue(), + (editobact->localflag & ACT_EDOB_LOCAL_ANGV)!=0 ); //editobact->ob to gameobj @@ -847,6 +878,16 @@ void BL_ConvertActuators(char* maggiename, mode = KX_GameActuator::KX_GAME_QUIT; break; } + case ACT_GAME_SAVECFG: + { + mode = KX_GameActuator::KX_GAME_SAVECFG; + break; + } + case ACT_GAME_LOADCFG: + { + mode = KX_GameActuator::KX_GAME_LOADCFG; + break; + } default: ; /* flag error */ } @@ -933,10 +974,9 @@ void BL_ConvertActuators(char* maggiename, bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data; KX_VisibilityActuator * tmp_vis_act = NULL; bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0); + bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0); - tmp_vis_act = - new KX_VisibilityActuator(gameobj, - !v); + tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive); baseact = tmp_vis_act; } @@ -1035,7 +1075,7 @@ void BL_ConvertActuators(char* maggiename, { bParentActuator *parAct = (bParentActuator *) bact->data; int mode = KX_ParentActuator::KX_PARENT_NODEF; - KX_GameObject *tmpgob; + KX_GameObject *tmpgob = NULL; switch(parAct->type) { diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 4806df36090..f16855955ff 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -633,6 +633,7 @@ void BL_ConvertSensors(struct Object* blenderobject, if (eventmgr) { bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); @@ -645,6 +646,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gameobj, checkname, bFindMaterial, + bXRay, distance, axis, kxscene); @@ -711,6 +713,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gamesensor = new SCA_JoystickSensor( eventmgr, gameobj, + bjoy->joyindex, joysticktype, axis,axisf, prec, @@ -765,19 +768,26 @@ void BL_ConvertSensors(struct Object* blenderobject, logicmgr->RegisterToSensor(gamecont,gamesensor); } else { printf( - "Warning, sensor \"%s\" could not find its controller" - "(link %d of %d)\n" + "Warning, sensor \"%s\" could not find its controller " + "(link %d of %d) from object \"%s\"\n" "\tthere has been an error converting the blender controller for the game engine," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks); + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } else { printf( - "Warning, sensor \"%s\" has lost a link to a controller" - "(link %d of %d)\n" + "Warning, sensor \"%s\" has lost a link to a controller " + "(link %d of %d) from object \"%s\"\n" "\tpossible causes are partially appended objects or an error reading the file," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks); + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } + // special case: Keyboard sensor with no link + // this combination is usually used for key logging. + if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { + // Force the registration so that the sensor runs + gamesensor->IncLink(); + } + // done with gamesensor gamesensor->Release(); diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile index f312fc13221..4dd63e428bd 100644 --- a/source/gameengine/Converter/Makefile +++ b/source/gameengine/Converter/Makefile @@ -51,6 +51,7 @@ CPPFLAGS += -I../../blender/include CPPFLAGS += -I../../blender/blenlib CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/render/extern/include +CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index f5e382b471e..3be352c568b 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -16,7 +16,7 @@ incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/game incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet #source/gameengine/Physics/BlOde' incs += ' #source/gameengine/Physics/Dummy #source/gameengine/Physics/Sumo' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' -incs += ' #source/blender/misc #source/blender/blenloader' +incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SOLID_INC'] diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile index e9c02eedcf2..6736149bbcd 100644 --- a/source/gameengine/Expressions/Makefile +++ b/source/gameengine/Expressions/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I../../blender/makesdna 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 8937f481922..1eca527151a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -119,6 +119,7 @@ PyObject *PyObjectPlus::_getattr(const STR_String& attr) int PyObjectPlus::_delattr(const STR_String& attr) { + PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } @@ -126,7 +127,8 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) { //return PyObject::_setattr(attr,value); //cerr << "Unknown attribute" << endl; - return 1; + PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); + return 1; } /*------------------------------ diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index f433a08faba..ccc9af2ed79 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -43,6 +43,33 @@ * Python defines ------------------------------*/ +/* + Py_RETURN_NONE + Python 2.4 macro. + defined here until we switch to 2.4 + also in api2_2x/gen_utils.h +*/ +#ifndef Py_RETURN_NONE +#define Py_RETURN_NONE return Py_BuildValue("O", Py_None) +#endif +#ifndef Py_RETURN_FALSE +#define Py_RETURN_FALSE return PyBool_FromLong(0) +#endif +#ifndef Py_RETURN_TRUE +#define Py_RETURN_TRUE return PyBool_FromLong(1) +#endif + +/* for pre Py 2.5 */ +#if PY_VERSION_HEX < 0x02050000 +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#else +/* Py 2.5 and later */ +#define intargfunc ssizeargfunc +#define intintargfunc ssizessizeargfunc +#endif + // some basic python macros #define Py_Return { Py_INCREF(Py_None); return Py_None;} @@ -102,6 +129,12 @@ static inline void Py_Fatal(char *M) { return ((class_name*) self)->Py##method_name(self, args, kwds); \ }; \ +#define KX_PYMETHOD_VARARGS(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* args); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ + return ((class_name*) self)->Py##method_name(self, args); \ + }; \ + #define KX_PYMETHOD_NOARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self); \ static PyObject* sPy##method_name( PyObject* self) { \ @@ -150,6 +183,9 @@ static inline void Py_Fatal(char *M) { #define KX_PYMETHODTABLE(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, class_name::method_name##_doc} +#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, class_name::method_name##_doc} + /** * Function implementation macro */ @@ -157,6 +193,9 @@ static inline void Py_Fatal(char *M) { char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*) +#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \ +char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*) /*------------------------------ * PyObjectPlus diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 7bcb45228db..7296dfbec10 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -391,16 +391,23 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber) bool CValue::RemoveProperty(const STR_String & inName) { // Check if there are properties at all which can be removed - if (m_pNamedPropertyArray == NULL) - return false; - - CValue* val = GetProperty(inName); - if (NULL != val) - { - val->Release(); - m_pNamedPropertyArray->erase(inName); - return true; - } + if (m_pNamedPropertyArray) { + CValue* val = GetProperty(inName); + if (NULL != val) + { + val->Release(); + m_pNamedPropertyArray->erase(inName); + return true; + } + } + + char err[128]; + if (m_pNamedPropertyArray) + sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr()); + else + sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr()); + + PyErr_SetString(PyExc_AttributeError, err); return false; } @@ -755,7 +762,8 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) int CValue::_delattr(const STR_String& attr) { - RemoveProperty(attr); + if (!RemoveProperty(attr)) /* sets error */ + return 1; return 0; } diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index 18d7b6ffcd0..06002060bf1 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -29,9 +29,9 @@ #include "SCA_Joystick.h" #include "SCA_JoystickPrivate.h" - -SCA_Joystick::SCA_Joystick() +SCA_Joystick::SCA_Joystick(short int index) : + m_joyindex(index), m_axis10(0), m_axis11(0), m_axis20(0), @@ -52,82 +52,53 @@ SCA_Joystick::~SCA_Joystick() delete m_private; } -SCA_Joystick *SCA_Joystick::m_instance = NULL; +SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX]; int SCA_Joystick::m_refCount = 0; -SCA_Joystick *SCA_Joystick::GetInstance() +SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) { - if (m_instance == 0) + if (joyindex < 0 || joyindex >= JOYINDEX_MAX) { + echo("Error-invalid joystick index: " << joyindex); + return NULL; + } + + if (m_refCount == 0) { - m_instance = new SCA_Joystick(); - m_instance->CreateJoystickDevice(); + int i; + // do this once only + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){ + echo("Error-Initializing-SDL: " << SDL_GetError()); + return NULL; + } + for (i=0; iCreateJoystickDevice(); + } m_refCount = 1; } else { m_refCount++; } - return m_instance; + return m_instance[joyindex]; } void SCA_Joystick::ReleaseInstance() { if (--m_refCount == 0) { - DestroyJoystickDevice(); - delete m_instance; - m_instance = NULL; - } -} - - -bool SCA_Joystick::CreateJoystickDevice() -{ - bool init = false; - init = pCreateJoystickDevice(); - return init; -} - - -void SCA_Joystick::DestroyJoystickDevice() -{ - if(m_isinit) - pDestroyJoystickDevice(); -} - - -void SCA_Joystick::HandleEvents() -{ - if(m_isinit) - { - if(SDL_PollEvent(&m_private->m_event)) - { - switch(m_private->m_event.type) - { - case SDL_JOYAXISMOTION: - HANDLE_AXISMOTION(OnAxisMotion); - break; - case SDL_JOYHATMOTION: - HANDLE_HATMOTION(OnHatMotion); - break; - case SDL_JOYBUTTONUP: - HANDLE_BUTTONUP(OnButtonUp); - break; - case SDL_JOYBUTTONDOWN: - HANDLE_BUTTONDOWN(OnButtonDown); - break; - case SDL_JOYBALLMOTION: - HANDLE_BALLMOTION(OnBallMotion); - break; - default: - HANDLE_NOEVENT(OnNothing); - break; + int i; + for (i=0; iDestroyJoystickDevice(); + delete m_instance[i]; } + m_instance[i]= NULL; } + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ); } } - void SCA_Joystick::cSetPrecision(int val) { m_prec = val; @@ -226,76 +197,6 @@ int SCA_Joystick::pGetHat(int direction) return 0; } - -bool SCA_Joystick::GetJoyAxisMotion() -{ - bool result = false; - if(m_isinit){ - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYAXISMOTION: - result = true; - break; - } - } - } - return result; -} - - -bool SCA_Joystick::GetJoyButtonPress() -{ - bool result = false; - if(m_isinit){ - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYBUTTONDOWN: - result = true; - break; - } - } - } - return result; -} - - -bool SCA_Joystick::GetJoyButtonRelease() -{ - bool result = false; - if(m_isinit) - { - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYBUTTONUP: - result = true; - break; - } - } - } - return result; -} - - -bool SCA_Joystick::GetJoyHatMotion() -{ - bool result = false; - if(m_isinit){ - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYHATMOTION: - result = true; - break; - } - } - } - return 0; -} - - int SCA_Joystick::GetNumberOfAxes() { int number; @@ -334,42 +235,46 @@ int SCA_Joystick::GetNumberOfHats() return -1; } -bool SCA_Joystick::pCreateJoystickDevice() +bool SCA_Joystick::CreateJoystickDevice(void) { if(m_isinit == false){ - if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){ - echo("Error-Initializing-SDL: " << SDL_GetError()); - return false; - } - if(SDL_NumJoysticks() > 0){ - for(int i=0; im_joystick = SDL_JoystickOpen(i); - SDL_JoystickEventState(SDL_ENABLE); - m_numjoys = i; - } - echo("Joystick-initialized"); - m_isinit = true; - return true; - }else{ - echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); + if (m_joyindex>=SDL_NumJoysticks()) { + // don't print a message, because this is done anyway + //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); return false; } + + m_private->m_joystick = SDL_JoystickOpen(m_joyindex); + SDL_JoystickEventState(SDL_ENABLE); + + echo("Joystick " << m_joyindex << " initialized"); + m_isinit = true; } - return false; + return true; } -void SCA_Joystick::pDestroyJoystickDevice() +void SCA_Joystick::DestroyJoystickDevice(void) { - echo("Closing-"); - for(int i=0; im_joystick); } + m_isinit = false; } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ); } +int SCA_Joystick::Connected(void) +{ + if (m_isinit){ + if(SDL_JoystickOpened(m_joyindex)){ + return 1; + } + } + + return 0; +} void SCA_Joystick::pFillAxes() { diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h index 1e853070b09..bcbb43241c2 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h @@ -1,72 +1,37 @@ /** - * ***** 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): snailrose. - * - * ***** END GPL LICENSE BLOCK ***** - */ #ifndef _SCA_JOYSTICK_H_ - #define _SCA_JOYSTICK_H_ - - #include "SCA_JoystickDefines.h" - - - - +#include "SDL.h" /* - * Basic Joystick class * I will make this class a singleton because there should be only one joystick * even if there are more than one scene using it and count how many scene are using it. @@ -76,7 +41,7 @@ class SCA_Joystick { - static SCA_Joystick *m_instance; + static SCA_Joystick *m_instance[JOYINDEX_MAX]; static int m_refCount; class PrivateData; @@ -85,226 +50,135 @@ class SCA_Joystick int m_joyindex; - /*! - - * the number of avail joysticks - - */ - - int m_numjoys; - /* - *support for 2 axes - */ int m_axis10,m_axis11; - int m_axis20,m_axis21; - /* - + /* * Precision or range of the axes - */ - int m_prec; /* - * multiple axis values stored here - */ - int m_axisnum; - int m_axisvalue; /* - * max # of axes avail - */ - /*disabled - int m_axismax; - */ /* - * button values stored here - */ - int m_buttonnum; /* - * max # of buttons avail - */ int m_buttonmax; - /* - * hat values stored here - */ - int m_hatnum; - int m_hatdir; /* * max # of hats avail - disabled - int m_hatmax; - */ - /* is the joystick initialized ?*/ - bool m_isinit; - /* is triggered */ - bool m_istrig; /* - - * Open the joystick - - */ - - bool pCreateJoystickDevice(void); - - /* - - * Close the joystick - - */ - - void pDestroyJoystickDevice(void); - - - - /* - * event callbacks - */ - - void OnAxisMotion(void); - - void OnHatMotion(void); - - void OnButtonUp(void); - - void OnButtonDown(void); - - void OnNothing(void); - - void OnBallMotion(void){} + void OnAxisMotion(SDL_Event *sdl_event); + void OnHatMotion(SDL_Event *sdl_event); + void OnButtonUp(SDL_Event *sdl_event); + void OnButtonDown(SDL_Event *sdl_event); + void OnNothing(SDL_Event *sdl_event); + void OnBallMotion(SDL_Event *sdl_event){} /* - - * fills the axis mnember values - + * Open the joystick */ + bool CreateJoystickDevice(void); + /* + * Close the joystick + */ + void DestroyJoystickDevice(void); + + /* + * fills the axis mnember values + */ void pFillAxes(void); - - - void pFillButtons(void); /* - * returns m_axis10,m_axis11... - */ - int pGetAxis(int axisnum, int udlr); - + /* - * gets the current button - */ int pGetButtonPress(int button); /* - * returns if no button is pressed - */ - int pGetButtonRelease(int button); /* - * gets the current hat direction - */ - int pGetHat(int direction); - SCA_Joystick(); + SCA_Joystick(short int index); ~SCA_Joystick(); - bool CreateJoystickDevice(void); - - void DestroyJoystickDevice(void); - - public: - static SCA_Joystick *GetInstance(); - + static SCA_Joystick *GetInstance( short int joyindex ); + static void HandleEvents( void ); void ReleaseInstance(); - void HandleEvents(); - /* - */ bool aUpAxisIsPositive(int axis); - bool aDownAxisIsPositive(int axis); - bool aLeftAxisIsPositive(int axis); - bool aRightAxisIsPositive(int axis); - bool aButtonPressIsPositive(int button); - bool aButtonReleaseIsPositive(int button); - bool aHatIsPositive(int dir); /* - * precision is default '3200' which is overridden by input - */ void cSetPrecision(int val); - - int GetAxis10(void){ return m_axis10; @@ -312,80 +186,48 @@ public: } int GetAxis11(void){ - return m_axis11; - } int GetAxis20(void){ - return m_axis20; - } int GetAxis21(void){ - return m_axis21; - } int GetButton(void){ - return m_buttonnum; - } int GetHat(void){ - return m_hatdir; - } int GetThreshold(void){ - return m_prec; - } bool IsTrig(void){ - return m_istrig; - } - - /* - - * returns true if an event is being processed - - */ - - bool GetJoyAxisMotion(void); - - bool GetJoyButtonPress(void); - - bool GetJoyButtonRelease(void); - - bool GetJoyHatMotion(void); - - /* - * returns the # of... - */ int GetNumberOfAxes(void); - int GetNumberOfButtons(void); - int GetNumberOfHats(void); - - + /* + * Test if the joystick is connected + */ + int Connected(void); }; - +void Joystick_HandleEvents( void ); #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h index 15a421188b9..73ffe1406d9 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h @@ -38,12 +38,6 @@ #define echo(x) std::cout << x << std::endl; #endif -/* function callbacks */ -#define HANDLE_AXISMOTION(fn) ((fn)(), 0L) -#define HANDLE_HATMOTION(fn) ((fn)(), 0L) -#define HANDLE_BUTTONUP(fn) ((fn)(), 0L) -#define HANDLE_BUTTONDOWN(fn) ((fn)(), 0L) -#define HANDLE_BALLMOTION(fn) ((fn)(), 0L) -#define HANDLE_NOEVENT(fn) ((fn)(), 0L) +#define JOYINDEX_MAX 8 #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp index ab523470e21..1e064f55397 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp @@ -30,41 +30,75 @@ -void SCA_Joystick::OnAxisMotion(void) +void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event) { pFillAxes(); - m_axisnum = m_private->m_event.jaxis.axis; - m_axisvalue = m_private->m_event.jaxis.value; + m_axisnum = sdl_event->jaxis.axis; + m_axisvalue = sdl_event->jaxis.value; m_istrig = 1; } -void SCA_Joystick::OnHatMotion(void) +void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event) { - m_hatdir = m_private->m_event.jhat.value; - m_hatnum = m_private->m_event.jhat.hat; + m_hatdir = sdl_event->jhat.value; + m_hatnum = sdl_event->jhat.hat; m_istrig = 1; } -void SCA_Joystick::OnButtonUp(void) +void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event) { m_buttonnum = -2; } -void SCA_Joystick::OnButtonDown(void) +void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event) { m_buttonmax = GetNumberOfButtons(); - if(m_private->m_event.jbutton.button >= 1 || m_private->m_event.jbutton.button <= m_buttonmax) + if(sdl_event->jbutton.button >= 1 || sdl_event->jbutton.button <= m_buttonmax) { m_istrig = 1; - m_buttonnum = m_private->m_event.jbutton.button; + m_buttonnum = sdl_event->jbutton.button; } } -void SCA_Joystick::OnNothing(void) +void SCA_Joystick::OnNothing(SDL_Event* sdl_event) { m_istrig = 0; } + +/* only handle events for 1 joystick */ + +void SCA_Joystick::HandleEvents(void) +{ + SDL_Event sdl_event; + + if(SDL_PollEvent(&sdl_event)) + { + /* Note! m_instance[sdl_event.jaxis.which] + * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */ + switch(sdl_event.type) + { + case SDL_JOYAXISMOTION: + SCA_Joystick::m_instance[sdl_event.jaxis.which]->OnAxisMotion(&sdl_event); + break; + case SDL_JOYHATMOTION: + SCA_Joystick::m_instance[sdl_event.jhat.which]->OnHatMotion(&sdl_event); + break; + case SDL_JOYBUTTONUP: + SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonUp(&sdl_event); + break; + case SDL_JOYBUTTONDOWN: + SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event); + break; + case SDL_JOYBALLMOTION: + SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event); + break; + default: + printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n"); + break; + } + } +} diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h index 23fad3cd55d..bb6bfe2d4cc 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h @@ -32,10 +32,6 @@ class SCA_Joystick::PrivateData { public: - /* - * SDL events structure - */ - SDL_Event m_event; /* * The Joystick */ diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile index b3eae5d67dc..355ece6e8bd 100644 --- a/source/gameengine/GameLogic/Makefile +++ b/source/gameengine/GameLogic/Makefile @@ -42,6 +42,7 @@ CPPFLAGS += -I../Expressions CPPFLAGS += -I../Rasterizer CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += $(NAN_SDLCFLAGS) diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 96a770a553f..9ec4ea00337 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -23,8 +23,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( : SCA_IActuator(gameobj, T), m_type(type), m_flag(flag), - m_int_arg(int_arg), m_float_arg(float_arg), + m_int_arg(int_arg), m_rasterizer(rasterizer), m_rendertools(rendertools) { @@ -64,13 +64,11 @@ bool SCA_2DFilterActuator::Update() if( m_type == RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR ) { if(!m_flag) - { m_rasterizer->EnableMotionBlur(m_float_arg); - } else - { m_rasterizer->DisableMotionBlur(); - } + + return false; } else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS) { diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 8f156cc63e7..0bd20117f31 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -188,6 +188,8 @@ void SCA_IController::ApplyState(unsigned int state) for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { (*sensit)->IncLink(); + // remember that this controller just activated that sensor + (*sensit)->AddNewController(this); } SetActive(true); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index f5512664d8f..abd049e9d64 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -27,6 +27,7 @@ */ #include "SCA_ILogicBrick.h" +#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index f99b9b789d7..084b1395159 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -32,6 +32,8 @@ #include "SCA_ISensor.h" #include "SCA_EventManager.h" #include "SCA_LogicManager.h" +// needed for IsTriggered() +#include "SCA_PythonController.h" #ifdef HAVE_CONFIG_H #include @@ -132,10 +134,8 @@ void SCA_ISensor::DecLink() { } if (!m_links) { - // sensor is detached from all controllers, initialize it so that it - // is fresh as at startup when it is reattached again. + // sensor is detached from all controllers, remove it from manager UnregisterToManager(); - Init(); } } @@ -168,7 +168,9 @@ PyParentObject SCA_ISensor::Parents[] = { }; PyMethodDef SCA_ISensor::Methods[] = { {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, - METH_VARARGS, IsPositive_doc}, + METH_NOARGS, IsPositive_doc}, + {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, + METH_VARARGS, IsTriggered_doc}, {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, METH_NOARGS, GetUsePosPulseMode_doc}, {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, @@ -204,6 +206,9 @@ SCA_ISensor::_getattr(const STR_String& attr) void SCA_ISensor::RegisterToManager() { + // sensor is just activated, initialize it + Init(); + m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); m_eventmgr->RegisterSensor(this); } @@ -221,6 +226,9 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) bool result = this->Evaluate(event); if (result) { logicmgr->AddActivatedSensor(this); + // reset these counters so that pulse are synchronized with transition + m_pos_ticks = 0; + m_neg_ticks = 0; } else { /* First, the pulsing behaviour, if pulse mode is @@ -249,19 +257,47 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) } } } + if (!m_newControllers.empty()) + { + if (!IsActive() && m_level) + { + // This level sensor is connected to at least one controller that was just made + // active but it did not generate an event yet, do it now to those controllers only + for (std::vector::iterator ci=m_newControllers.begin(); + ci != m_newControllers.end(); ci++) + { + logicmgr->AddTriggeredController(*ci, this); + } + } + // clear the list. Instead of using clear, which also release the memory, + // use erase, which keeps the memory available for next time. + m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); + } } } /* Python functions: */ char SCA_ISensor::IsPositive_doc[] = "isPositive()\n" -"\tReturns whether the sensor is registered a positive event.\n"; -PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds) +"\tReturns whether the sensor is in an active state.\n"; +PyObject* SCA_ISensor::PyIsPositive(PyObject* self) { int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); } +char SCA_ISensor::IsTriggered_doc[] = +"isTriggered()\n" +"\tReturns whether the sensor has triggered the current controller.\n"; +PyObject* SCA_ISensor::PyIsTriggered(PyObject* self) +{ + // check with the current controller + int retval = 0; + if (SCA_PythonController::m_sCurrentController) + retval = SCA_PythonController::m_sCurrentController->IsTriggered(this); + return PyInt_FromLong(retval); +} + /** * getUsePulseMode: getter for the pulse mode (KX_TRUE = on) */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index fc8f0bd0011..0d65270dc7b 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -34,6 +34,8 @@ #include "SCA_ILogicBrick.h" +#include + /** * Interface Class for all logic Sensors. Implements * pulsemode,pulsefrequency */ @@ -73,9 +75,9 @@ class SCA_ISensor : public SCA_ILogicBrick /** number of connections to controller */ int m_links; - /** Pass the activation on to the logic manager.*/ - void SignalActivation(class SCA_LogicManager* logicmgr); - + /** list of controllers that have just activated this sensor because of a state change */ + std::vector m_newControllers; + public: SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, @@ -128,6 +130,8 @@ public: /** Resume sensing. */ void Resume(); + void AddNewController(class SCA_IController* controller) + { m_newControllers.push_back(controller); } void ClrLink() { m_links = 0; } void IncLink() @@ -137,7 +141,8 @@ public: { return !m_links; } /* Python functions: */ - KX_PYMETHOD_DOC(SCA_ISensor,IsPositive); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode); KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency); diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index 8ff28ba0b51..a86770a6e0a 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -40,35 +40,48 @@ SCA_JoystickManager::SCA_JoystickManager(class SCA_LogicManager* logicmgr) : SCA_EventManager(JOY_EVENTMGR), m_logicmgr(logicmgr) { - m_joystick = SCA_Joystick::GetInstance(); + int i; + for (i=0; iReleaseInstance(); + int i; + for (i=0; iReleaseInstance(); + } } void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - set::iterator it; - for (it = m_sensors.begin(); it != m_sensors.end(); it++) - { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); - if(!joysensor->IsSuspended()) + if (m_sensors.size()==0) { + return; + } + else { + set::iterator it; + + SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */ + + for (it = m_sensors.begin(); it != m_sensors.end(); it++) { - m_joystick->HandleEvents(); - joysensor->Activate(m_logicmgr, NULL); + SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); + if(!joysensor->IsSuspended()) + { + joysensor->Activate(m_logicmgr, NULL); + } } } } -SCA_Joystick *SCA_JoystickManager::GetJoystickDevice() +SCA_Joystick *SCA_JoystickManager::GetJoystickDevice( short int joyindex) { /* *Return the instance of SCA_Joystick for use */ - return m_joystick; + return m_joystick[joyindex]; } diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.h b/source/gameengine/GameLogic/SCA_JoystickManager.h index f2bb27965fa..d3a7ac95bea 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.h +++ b/source/gameengine/GameLogic/SCA_JoystickManager.h @@ -40,12 +40,12 @@ class SCA_JoystickManager : public SCA_EventManager /** * SDL Joystick Class Instance */ - SCA_Joystick *m_joystick; + SCA_Joystick *m_joystick[JOYINDEX_MAX]; public: SCA_JoystickManager(class SCA_LogicManager* logicmgr); virtual ~SCA_JoystickManager(); virtual void NextFrame(double curtime,double deltatime); - SCA_Joystick* GetJoystickDevice(void); + SCA_Joystick* GetJoystickDevice(short int joyindex); }; diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 3fb439eb25b..3c08710c6ce 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -30,8 +30,11 @@ #include "SCA_EventManager.h" #include "SCA_LogicManager.h" +#include "PyObjectPlus.h" + #include + #ifdef HAVE_CONFIG_H #include #endif @@ -39,6 +42,7 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, SCA_IObject* gameobj, + short int joyindex, short int joymode, int axis, int axisf,int prec, int button, int buttonf, @@ -53,7 +57,8 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, m_hat(hat), m_hatf(hatf), m_precision(prec), - m_joymode(joymode) + m_joymode(joymode), + m_joyindex(joyindex) { /* std::cout << " axis " << m_axis << std::endl; @@ -99,10 +104,13 @@ bool SCA_JoystickSensor::IsPositiveTrigger() bool SCA_JoystickSensor::Evaluate(CValue* event) { - SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(); + SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex); bool result = false; bool reset = m_reset && m_level; + if(js==NULL) + return false; + m_reset = false; switch(m_joymode) { @@ -118,7 +126,7 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) js->cSetPrecision(m_precision); if(m_axisf == 1){ if(js->aUpAxisIsPositive(m_axis)){ - m_istrig =1; + m_istrig = 1; result = true; }else{ if(m_istrig){ @@ -241,11 +249,31 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) printf("Error invalid switch statement\n"); break; } - if(!js->IsTrig()){ + + if (js->IsTrig()) { + /* The if below detects changes with the joystick trigger state. + * js->IsTrig() will stay true as long as the key is held. + * even though the event from SDL will only be sent once. + * (js->IsTrig() && m_istrig_lastjs) - when true it means this sensor + * had the same joystick trigger state last time, + * Setting the result false this time means it wont run the sensors + * controller every time (like a pulse sensor) + * + * This is not done with the joystick its self incase other sensors use + * it or become active. + */ + if (m_istrig_lastjs) { + result = false; + } + m_istrig_lastjs = true; + } else { m_istrig = 0; + m_istrig_lastjs = false; } + if (reset) result = true; + return result; } @@ -293,6 +321,8 @@ PyParentObject SCA_JoystickSensor::Parents[] = { PyMethodDef SCA_JoystickSensor::Methods[] = { + {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, GetIndex_doc}, + {"setIndex", (PyCFunction) SCA_JoystickSensor::sPySetIndex, METH_O, SetIndex_doc}, {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, GetAxis_doc}, {"setAxis", (PyCFunction) SCA_JoystickSensor::sPySetAxis, METH_VARARGS, SetAxis_doc}, {"getAxisValue", (PyCFunction) SCA_JoystickSensor::sPyGetRealAxis, METH_NOARGS, GetRealAxis_doc}, @@ -305,6 +335,7 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, NumberOfAxes_doc}, {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, NumberOfButtons_doc}, {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, NumberOfHats_doc}, + {"isConnected", (PyCFunction) SCA_JoystickSensor::sPyConnected, METH_NOARGS, Connected_doc}, {NULL,NULL} //Sentinel }; @@ -314,14 +345,36 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { } +/* get index ---------------------------------------------------------- */ +char SCA_JoystickSensor::GetIndex_doc[] = +"getIndex\n" +"\tReturns the joystick index to use.\n"; +PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) { + return PyInt_FromLong(m_joyindex); +} + + +/* set index ---------------------------------------------------------- */ +char SCA_JoystickSensor::SetIndex_doc[] = +"setIndex\n" +"\tSets the joystick index to use.\n"; +PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) { + int index = PyInt_AsLong( 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; + } + + m_joyindex = index; + Py_RETURN_NONE; +} + /* get axis ---------------------------------------------------------- */ char SCA_JoystickSensor::GetAxis_doc[] = "getAxis\n" "\tReturns the current state of the axis.\n"; -PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self, - PyObject* args, - PyObject* kwds) { - return Py_BuildValue("[ii]",m_axis, m_axisf); +PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) { + return PyInt_FromLong(m_joyindex); } @@ -329,9 +382,7 @@ PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self, char SCA_JoystickSensor::SetAxis_doc[] = "setAxis\n" "\tSets the current state of the axis.\n"; -PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { int axis,axisflag; if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){ @@ -339,7 +390,7 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, } m_axis = axis; m_axisf = axisflag; - Py_Return; + Py_RETURN_NONE; } @@ -347,16 +398,12 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, char SCA_JoystickSensor::GetRealAxis_doc[] = "getAxisValue\n" "\tReturns a list of the values for each axis .\n"; -PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self, - PyObject* args, - PyObject* kwds) { - int a,b,c,d; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - a = joy->GetAxis10(); - b = joy->GetAxis11(); - c = joy->GetAxis20(); - d = joy->GetAxis21(); - return Py_BuildValue("[iiii]",a,b,c,d); +PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + if(joy) + return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); + else + return Py_BuildValue("[iiii]", 0, 0, 0, 0); } @@ -364,10 +411,8 @@ PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self, char SCA_JoystickSensor::GetThreshold_doc[] = "getThreshold\n" "\tReturns the threshold of the axis.\n"; -PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self, - PyObject* args, - PyObject* kwds) { - return Py_BuildValue("i", m_precision); +PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) { + return PyInt_FromLong(m_precision); } @@ -375,15 +420,13 @@ PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self, char SCA_JoystickSensor::SetThreshold_doc[] = "setThreshold\n" "\tSets the threshold of the axis.\n"; -PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) { int thresh; if(!PyArg_ParseTuple(args, "i", &thresh)){ return NULL; } m_precision = thresh; - Py_Return; + Py_RETURN_NONE; } @@ -391,9 +434,7 @@ PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, char SCA_JoystickSensor::GetButton_doc[] = "getButton\n" "\tReturns the currently pressed button.\n"; -PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) { return Py_BuildValue("[ii]",m_button, m_buttonf); } @@ -402,16 +443,14 @@ PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self, char SCA_JoystickSensor::SetButton_doc[] = "setButton\n" "\tSets the button the sensor reacts to.\n"; -PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* args ) { int button,buttonflag; if(!PyArg_ParseTuple(args, "ii", &button, &buttonflag)){ return NULL; } m_button = button; m_buttonf = buttonflag; - Py_Return; + Py_RETURN_NONE; } @@ -419,9 +458,7 @@ PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, char SCA_JoystickSensor::GetHat_doc[] = "getHat\n" "\tReturns the current direction of the hat.\n"; -PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) { return Py_BuildValue("[ii]",m_hat, m_hatf); } @@ -430,16 +467,14 @@ PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self, char SCA_JoystickSensor::SetHat_doc[] = "setHat\n" "\tSets the hat the sensor reacts to.\n"; -PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) { int hat,hatflag; if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){ return NULL; } m_hat = hat; m_hatf = hatflag; - Py_Return; + Py_RETURN_NONE; } @@ -447,37 +482,34 @@ PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, char SCA_JoystickSensor::NumberOfAxes_doc[] = "getNumAxes\n" "\tReturns the number of axes .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self, - PyObject* args, - PyObject* kwds) { - int num; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - num = joy->GetNumberOfAxes(); - return Py_BuildValue("i",num); +PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { + 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 ); } char SCA_JoystickSensor::NumberOfButtons_doc[] = "getNumButtons\n" "\tReturns the number of buttons .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self, - PyObject* args, - PyObject* kwds) { - int num; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - num = joy->GetNumberOfButtons(); - return Py_BuildValue("i",num); +PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } char SCA_JoystickSensor::NumberOfHats_doc[] = "getNumHats\n" "\tReturns the number of hats .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self, - PyObject* args, - PyObject* kwds) { - int num; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - num = joy->GetNumberOfHats(); - return Py_BuildValue("i",num); +PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); +} + +char SCA_JoystickSensor::Connected_doc[] = +"getConnected\n" +"\tReturns True if a joystick is connected at this joysticks index.\n"; +PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + return PyBool_FromLong( joy ? joy->Connected() : 0 ); } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 69068da6494..8b74f6e0296 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -68,10 +68,20 @@ class SCA_JoystickSensor :public SCA_ISensor * Is an event triggered ? */ bool m_istrig; + /** + * Last trigger state for this sensors joystick, + * Otherwise it will trigger all the time + * this is used to see if the trigger state changes. + */ + bool m_istrig_lastjs; /** * The mode to determine axis,button or hat */ short int m_joymode; + /** + * Select which joystick to use + */ + short int m_joyindex; enum KX_JOYSENSORMODE { KX_JOYSENSORMODE_NODEF = 0, @@ -85,6 +95,7 @@ class SCA_JoystickSensor :public SCA_ISensor public: SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, SCA_IObject* gameobj, + short int joyindex, short int joymode, int axis, int axisf,int prec, int button, int buttonf, @@ -97,28 +108,36 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); + short int GetJoyIndex(void){ + return m_joyindex; + } + /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + /* Joystick Index */ + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); + KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex); /* Axes*/ - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetAxis); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetAxis); - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetRealAxis); - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetThreshold); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetThreshold); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetAxis); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetAxis); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetRealAxis); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetThreshold); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetThreshold); /* Buttons */ - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetButton); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetButton); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButton); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetButton); /* Hats */ - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetHat); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetHat); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetHat); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetHat); /* number of */ - KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfAxes); - KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfButtons); - KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfHats); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfAxes); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfButtons); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected); }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index a7a6fa93db4..fba1162993d 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -505,7 +505,7 @@ PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, PyObject* kwds) { // printf("sPyIsPositive\n"); - return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds); + return ((SCA_KeyboardSensor*) self)->PyIsPositive(self); } diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 91e66aea359..b584b37180f 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -33,6 +33,7 @@ #include "SCA_IController.h" #include "SCA_IActuator.h" #include "SCA_EventManager.h" +#include "SCA_PythonController.h" #include #ifdef HAVE_CONFIG_H @@ -232,8 +233,6 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) // for this frame, look up for activated sensors, and build the collection of triggered controllers // int numsensors = this->m_activatedsensors.size(); /*unused*/ - set triggeredControllerSet; - for (vector::const_iterator is=m_activatedsensors.begin(); !(is==m_activatedsensors.end());is++) { @@ -244,19 +243,28 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) { SCA_IController* contr = *c;//controllerarray->at(c); if (contr->IsActive()) - triggeredControllerSet.insert(SmartControllerPtr(contr,0)); + { + m_triggeredControllerSet.insert(SmartControllerPtr(contr,0)); + // So that the controller knows which sensor has activited it. + // Only needed for the python controller though. + if (contr->GetType() == &SCA_PythonController::Type) + { + SCA_PythonController* pythonController = (SCA_PythonController*)contr; + pythonController->AddTriggeredSensor(sensor); + } + } } //sensor->SetActive(false); } // int numtriggered = triggeredControllerSet.size(); /*unused*/ - for (set::iterator tit=triggeredControllerSet.begin(); - !(tit==triggeredControllerSet.end());tit++) + for (set::iterator tit=m_triggeredControllerSet.begin(); + !(tit==m_triggeredControllerSet.end());tit++) { (*tit)->Trigger(this); } - triggeredControllerSet.clear(); + m_triggeredControllerSet.clear(); } @@ -382,6 +390,17 @@ void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor) } } +void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor) +{ + m_triggeredControllerSet.insert(SmartControllerPtr(controller,0)); + // so that the controller knows which sensor has activited it + // only needed for python controller + if (controller->GetType() == &SCA_PythonController::Type) + { + SCA_PythonController* pythonController = (SCA_PythonController*)controller; + pythonController->AddTriggeredSensor(sensor); + } +} void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event) diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index e0d3d506702..50383879d8f 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -99,6 +99,7 @@ class SCA_LogicManager vector m_activatedsensors; set m_activeActuators; + set m_triggeredControllerSet; map m_sensorcontrollermapje; @@ -127,6 +128,7 @@ public: void EndFrame(); void AddActivatedSensor(SCA_ISensor* sensor); void AddActiveActuator(SCA_IActuator* sensor,class CValue* event); + void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor); SCA_EventManager* FindEventManager(int eventmgrtype); void RemoveGameObject(const STR_String& gameobjname); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index f9081c90288..6e9a0a7c6b6 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -33,8 +33,11 @@ #include "SCA_LogicManager.h" #include "SCA_ISensor.h" #include "SCA_IActuator.h" +#include "PyObjectPlus.h" #include "compile.h" #include "eval.h" +#include + #ifdef HAVE_CONFIG_H #include @@ -139,6 +142,14 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */ } +int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) +{ + if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != + m_triggeredSensors.end()) + return 1; + return 0; +} + #if 0 static char* sPyGetCurrentController__doc__; #endif @@ -294,7 +305,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) // something in this dictionary and crash? PyDict_Clear(excdict); Py_DECREF(excdict); - + m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end()); m_sCurrentController = NULL; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 39b6c68c359..1b62e7ecb53 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -36,6 +36,8 @@ #include "SCA_LogicManager.h" #include "BoolValue.h" +#include + class SCA_IObject; class SCA_PythonController : public SCA_IController { @@ -47,6 +49,7 @@ class SCA_PythonController : public SCA_IController STR_String m_scriptText; STR_String m_scriptName; PyObject* m_pythondictionary; + std::vector m_triggeredSensors; public: static SCA_PythonController* m_sCurrentController; // protected !!! @@ -64,6 +67,9 @@ class SCA_PythonController : public SCA_IController void SetScriptText(const STR_String& text); void SetScriptName(const STR_String& name); void SetDictionary(PyObject* pythondictionary); + void AddTriggeredSensor(class SCA_ISensor* sensor) + { m_triggeredSensors.push_back(sensor); } + int IsTriggered(class SCA_ISensor* sensor); static char* sPyGetCurrentController__doc__; static PyObject* sPyGetCurrentController(PyObject* self); diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt index ff1040bfb40..fc5912155cf 100644 --- a/source/gameengine/GamePlayer/CMakeLists.txt +++ b/source/gameengine/GamePlayer/CMakeLists.txt @@ -25,3 +25,7 @@ # ***** END GPL LICENSE BLOCK ***** SUBDIRS(common ghost) + +IF(WITH_WEBPLUGIN) + SUBDIRS(xembed) +ENDIF(WITH_WEBPLUGIN) diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt index e26f8b9d69a..0c6c4179e2d 100644 --- a/source/gameengine/GamePlayer/common/CMakeLists.txt +++ b/source/gameengine/GamePlayer/common/CMakeLists.txt @@ -30,7 +30,6 @@ SET(SRC GPC_Engine.cpp GPC_KeyboardDevice.cpp GPC_MouseDevice.cpp - GPC_PolygonMaterial.cpp GPC_RawImage.cpp GPC_RawLoadDotBlendArray.cpp GPC_RawLogoArrays.cpp @@ -69,6 +68,7 @@ SET(INC ../../../../source/gameengine/GamePlayer/ghost ../../../../source/blender/misc ../../../../source/blender/blenloader + ../../../../source/blender/gpu ../../../../extern/glew/include ${PYTHON_INC} ${SOLID_INC} diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 8b828393c67..78d8eaf2aa3 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -27,141 +27,256 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include - -#ifdef WIN32 -#pragma warning (disable : 4786) -#include -#endif - #include "GL/glew.h" -#include - -#include "GPC_RenderTools.h" - #include "RAS_IRenderTools.h" #include "RAS_IRasterizer.h" #include "RAS_LightObject.h" #include "RAS_ICanvas.h" #include "RAS_GLExtensionManager.h" -// next two includes/dependencies come from the shadow feature -// it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" - -#include "GPC_PolygonMaterial.h" #include "KX_PolygonMaterial.h" -#include "Value.h" - -//#include "KX_BlenderGL.h" // for text printing -//#include "KX_BlenderClientObject.h" -#include "STR_String.h" -#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting) - - -// Blender includes -/* This list includes only data type definitions */ -#include "DNA_object_types.h" -#include "DNA_material_types.h" -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_group_types.h" -#include "DNA_scene_types.h" -#include "DNA_camera_types.h" -#include "DNA_property_types.h" -#include "DNA_text_types.h" -#include "DNA_sensor_types.h" -#include "DNA_controller_types.h" -#include "DNA_actuator_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" - -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_bmfont.h" -#include "BKE_bmfont_types.h" -#include "BKE_main.h" - -#include "IMB_imbuf_types.h" -// End of Blender includes - -#include "KX_Scene.h" +#include "KX_BlenderMaterial.h" #include "KX_RayCast.h" #include "KX_IPhysicsController.h" + #include "PHY_IPhysicsEnvironment.h" -#include "KX_BlenderMaterial.h" + +#include "STR_String.h" + +#include "GPU_draw.h" + +#include "BKE_bmfont.h" // for text printing +#include "BKE_bmfont_types.h" + +#include "GPC_RenderTools.h" + +unsigned int GPC_RenderTools::m_numgllights; GPC_RenderTools::GPC_RenderTools() { m_font = BMF_GetFont(BMF_kHelvetica10); + glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); if (m_numgllights < 8) m_numgllights = 8; } - GPC_RenderTools::~GPC_RenderTools() { } +void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) +{ + m_clientobject = NULL; + m_lastlightlayer = -1; + m_lastlighting = false; + DisableOpenGLLights(); +} void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty) { } +/* ProcessLighting performs lighting on objects. the layer is a bitfield that + * contains layer information. There are 20 'official' layers in blender. A + * light is applied on an object only when they are in the same layer. OpenGL + * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in + * a scene. */ -void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) +void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) { - m_clientobject=NULL; - m_modified=true; - DisableOpenGLLights(); + if(m_lastlightlayer == layer) + return; -} + m_lastlightlayer = layer; -int GPC_RenderTools::ProcessLighting(int layer) -{ - int result = false; + bool enable = false; - if (layer < 0) - { - DisableOpenGLLights(); - result = false; - } else + if (layer >= 0) { if (m_clientobject) - { - if (applyLights(layer)) - { - EnableOpenGLLights(); - result = true; - } else - { - DisableOpenGLLights(); - result = false; - } + { + if (layer == RAS_LIGHT_OBJECT_LAYER) + layer = static_cast(m_clientobject)->GetLayer(); + + enable = applyLights(layer, viewmat); } } - return result; + + if(enable) + EnableOpenGLLights(); + else + DisableOpenGLLights(); } void GPC_RenderTools::EnableOpenGLLights() { + if(m_lastlighting == true) + return; + glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + + m_lastlighting = true; } -void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height) +void GPC_RenderTools::DisableOpenGLLights() +{ + if(m_lastlighting == false) + return; + + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + + m_lastlighting = false; +} + + +void GPC_RenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) +{ + if (m_clientobject != obj) + { + bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); + rasty->SetFrontFace(ccw); + + m_clientobject = obj; + } +} + +bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) +{ + double* const oglmatrix = (double* const) data; + MT_Point3 resultpoint(result->m_hitPoint); + MT_Vector3 resultnormal(result->m_hitNormal); + MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); + MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); + left = (dir.cross(resultnormal)).safe_normalized(); + // for the up vector, we take the 'resultnormal' returned by the physics + + double maat[16]={ + left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + resultnormal[0],resultnormal[1],resultnormal[2], 0, + 0, 0, 0, 1}; + glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); + //glMultMatrixd(oglmatrix); + glMultMatrixd(maat); + return true; +} + +void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) +{ + /* FIXME: + blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const + MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. + + Program received signal SIGABRT, Aborted. + [Switching to Thread 16384 (LWP 1519)] + 0x40477571 in kill () from /lib/libc.so.6 + (gdb) bt + #7 0x08334368 in MT_Vector3::normalized() const () + #8 0x0833e6ec in GPC_RenderTools::applyTransform(RAS_IRasterizer*, double*, int) () + */ + + if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || + objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) + { + // rotate the billboard/halo + //page 360/361 3D Game Engine Design, David Eberly for a discussion + // on screen aligned and axis aligned billboards + // assumed is that the preprocessor transformed all billboard polygons + // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) + // when new parenting for objects is done, this rotation + // will be moved into the object + + MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); + MT_Point3 campos = rasty->GetCameraPosition(); + MT_Vector3 dir = (campos - objpos).safe_normalized(); + MT_Vector3 up(0,0,1.0); + + KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; + // get scaling of halo object + MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); + + bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned + if (screenaligned) + { + up = (up - up.dot(dir) * dir).safe_normalized(); + } else + { + dir = (dir - up.dot(dir)*up).safe_normalized(); + } + + MT_Vector3 left = dir.normalized(); + dir = (left.cross(up)).normalized(); + + // we have calculated the row vectors, now we keep + // local scaling into account: + + left *= size[0]; + dir *= size[1]; + up *= size[2]; + double maat[16]={ + left[0], left[1],left[2], 0, + dir[0], dir[1],dir[2],0, + up[0],up[1],up[2],0, + 0,0,0,1}; + glTranslated(objpos[0],objpos[1],objpos[2]); + glMultMatrixd(maat); + + } else + { + if (objectdrawmode & RAS_IPolyMaterial::SHADOW) + { + // shadow must be cast to the ground, physics system needed here! + MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); + KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; + MT_Vector3 direction = MT_Vector3(0,0,-1); + + direction.normalize(); + direction *= 100000; + + MT_Point3 topoint = frompoint + direction; + + KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; + PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); + KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); + + KX_GameObject *parent = gameobj->GetParent(); + if (!physics_controller && parent) + physics_controller = parent->GetPhysicsController(); + if (parent) + parent->Release(); + + KX_RayCast::Callback callback(this, physics_controller, oglmatrix); + if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) + { + // couldn't find something to cast the shadow on... + glMultMatrixd(oglmatrix); + } + } else + { + + // 'normal' object + glMultMatrixd(oglmatrix); + } + } +} + + +void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height) { STR_String tmpstr(text); int lines; @@ -234,21 +349,19 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, glDisable(GL_LIGHTING); } -/** - * Copied from KX_BlenderRenderTools.cpp in KX_blenderhook - * Renders text into a (series of) polygon(s), using a texture font, - * Each character consists of one polygon (one quad or two triangles) - */ +/* Render Text renders text into a (series of) polygon, using a texture font, + * Each character consists of one polygon (one quad or two triangles) */ + void GPC_RenderTools::RenderText( int mode, RAS_IPolyMaterial* polymat, - float v1[3], float v2[3], float v3[3], float v4[3]) + float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); struct MTFace* tface = 0; - unsigned int* col = 0; + unsigned int *col = 0; if(flag & RAS_BLENDERMAT) { KX_BlenderMaterial *bl_mat = static_cast(polymat); @@ -259,110 +372,29 @@ void GPC_RenderTools::RenderText( tface = blenderpoly->GetMTFace(); col = blenderpoly->GetMCol(); } - - BL_RenderText(mode, mytext, mytext.Length(), tface, col, v1, v2, v3, v4); -} - - - -/** - * Copied from KX_BlenderGL.cpp in KX_blenderhook - */ -void GPC_RenderTools::BL_RenderText( - int mode, - const char* textstr, - int textlen, - struct MTFace* tface, - unsigned int* col, - float v1[3],float v2[3],float v3[3],float v4[3]) -{ - struct Image* ima; - - if (mode & TF_BMFONT) { - //char string[MAX_PROPSTRING]; -// float tmat[4][4]; - int characters, index, character; - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - -// bProperty *prop; - - // string = "Frank van Beek"; - - characters = textlen; - - ima = (struct Image*) tface->tpage; - if (ima == NULL) { - characters = 0; - } - - if(!col) glColor3f(1.0f, 1.0f, 1.0f); - - glPushMatrix(); - for (index = 0; index < characters; index++) { - // lets calculate offset stuff - character = textstr[index]; - - // space starts at offset 1 - // character = character - ' ' + 1; - - matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - - glBegin(GL_POLYGON); - // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], ); - // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - - if(col) BL_spack(col[0]); - // glVertex3fv(v1); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); - if(col) BL_spack(col[1]); - // glVertex3fv(v2); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); - if(col) BL_spack(col[2]); - // glVertex3fv(v3); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(v4) { - // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy); - glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); - if(col) BL_spack(col[3]); - // glVertex3fv(v4); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - glEnd(); - - glTranslatef(advance, 0.0, 0.0); - } - glPopMatrix(); - - } + GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); } -RAS_IPolyMaterial* GPC_RenderTools::CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant, bool zsort, - int lightlayer,bool bIsTriangle,void* clientobject,void* tface) +void GPC_RenderTools::PushMatrix() { - assert(!"Deprecated"); -/* return new GPC_PolygonMaterial(texname, ba,matname,tile,tilexrep,tileyrep, - mode,transparant,zsort,lightlayer,bIsTriangle,clientobject,tface); - */ - return NULL; + glPushMatrix(); +} + +void GPC_RenderTools::PopMatrix() +{ + glPopMatrix(); } -int GPC_RenderTools::applyLights(int objectlayer) +int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) { -// taken from blender source, incompatibility between Blender Object / GameObject - - int count; + // taken from blender source, incompatibility between Blender Object / GameObject + float glviewmat[16]; + unsigned int count; float vec[4]; - + vec[3]= 1.0; for(count=0; count m_lights; std::vector::iterator lit = m_lights.begin(); + viewmat.getValue(glviewmat); + glPushMatrix(); + glLoadMatrixf(glviewmat); for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) { RAS_LightObject* lightdata = (*lit); if (lightdata->m_layer & objectlayer) { - - glPushMatrix(); - glLoadMatrixf(m_viewmat); - - vec[0] = (*(lightdata->m_worldmatrix))(0,3); vec[1] = (*(lightdata->m_worldmatrix))(1,3); vec[2] = (*(lightdata->m_worldmatrix))(2,3); vec[3] = 1; - if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) { vec[0] = (*(lightdata->m_worldmatrix))(0,2); @@ -443,142 +472,16 @@ int GPC_RenderTools::applyLights(int objectlayer) } glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec); glEnable((GLenum)(GL_LIGHT0+count)); - - count++; - glPopMatrix(); + count++; } } + glPopMatrix(); return count; } -void GPC_RenderTools::SetClientObject(void* obj) -{ - if (m_clientobject != obj) - { - if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) - { - glFrontFace(GL_CCW); - } else - { - glFrontFace(GL_CW); - } - m_clientobject = obj; - m_modified = true; - } -} - -bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) -{ - double* const oglmatrix = (double* const) data; - MT_Point3 resultpoint(hit_point); - MT_Vector3 resultnormal(hit_normal); - MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); - MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); - left = (dir.cross(resultnormal)).safe_normalized(); - // for the up vector, we take the 'resultnormal' returned by the physics - - double maat[16]={ - left[0], left[1], left[2], 0, - dir[0], dir[1], dir[2], 0, - resultnormal[0],resultnormal[1],resultnormal[2], 0, - 0, 0, 0, 1}; - glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); - //glMultMatrixd(oglmatrix); - glMultMatrixd(maat); - return true; -} - -void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) -{ - if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || - objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) - { - // rotate the billboard/halo - //page 360/361 3D Game Engine Design, David Eberly for a discussion - // on screen aligned and axis aligned billboards - // assumed is that the preprocessor transformed all billboard polygons - // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) - // when new parenting for objects is done, this rotation - // will be moved into the object - - MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); - MT_Point3 campos = rasty->GetCameraPosition(); - MT_Vector3 dir = (campos - objpos).safe_normalized(); - MT_Vector3 up(0,0,1.0); - - KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; - // get scaling of halo object - MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); - - bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned - if (screenaligned) - { - up = (up - up.dot(dir) * dir).safe_normalized(); - } else - { - dir = (dir - up.dot(dir)*up).safe_normalized(); - } - - MT_Vector3 left = dir.normalized(); - dir = (left.cross(up)).normalized(); - - // we have calculated the row vectors, now we keep - // local scaling into account: - - left *= size[0]; - dir *= size[1]; - up *= size[2]; - double maat[16]={ - left[0], left[1],left[2], 0, - dir[0], dir[1],dir[2],0, - up[0],up[1],up[2],0, - 0,0,0,1}; - glTranslated(objpos[0],objpos[1],objpos[2]); - glMultMatrixd(maat); - - } else - { - if (objectdrawmode & RAS_IPolyMaterial::SHADOW) - { - // shadow must be cast to the ground, physics system needed here! - MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; - MT_Vector3 direction = MT_Vector3(0,0,-1); - - direction.normalize(); - direction *= 100000; - - MT_Point3 topoint = frompoint + direction; - - KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; - PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); - KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); - - KX_GameObject *parent = gameobj->GetParent(); - if (!physics_controller && parent) - physics_controller = parent->GetPhysicsController(); - if (parent) - parent->Release(); - - MT_Point3 resultpoint; - MT_Vector3 resultnormal; - if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this, oglmatrix))) - { - // couldn't find something to cast the shadow on... - glMultMatrixd(oglmatrix); - } - } else - { - - // 'normal' object - glMultMatrixd(oglmatrix); - } - } -} - void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) { int state = rasterizer->GetMotionBlurState(); @@ -609,7 +512,6 @@ void GPC_RenderTools::Update2DFilter(vector& propNames, void* gameOb void GPC_RenderTools::Render2DFilters(RAS_ICanvas* canvas) { - m_filtermanager.RenderFilters( canvas); + m_filtermanager.RenderFilters(canvas); } -unsigned int GPC_RenderTools::m_numgllights; diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 8fae3d2b305..382956e73ea 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -31,114 +31,67 @@ #define __GPC_RENDERTOOLS_H #ifdef WIN32 - #include +// don't show stl-warnings +#pragma warning (disable:4786) +#include #endif // WIN32 -#include "GL/glew.h" - #include "RAS_IRenderTools.h" #include "BMF_Api.h" struct KX_ClientObjectInfo; +class KX_RayCast; +/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which + * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon) + * text, lighting. + * + * Most of this code is duplicated in KX_BlenderRenderTools, so this should be + * moved to some common location to avoid duplication. */ class GPC_RenderTools : public RAS_IRenderTools { + int m_lastlightlayer; + bool m_lastlighting; + static unsigned int m_numgllights; + + BMF_Font* m_font; + public: - GPC_RenderTools(); - virtual ~GPC_RenderTools(); + GPC_RenderTools(); + virtual ~GPC_RenderTools(); - virtual void EndFrame(RAS_IRasterizer* rasty); - virtual void BeginFrame(RAS_IRasterizer* rasty); + void EndFrame(RAS_IRasterizer* rasty); + void BeginFrame(RAS_IRasterizer* rasty); - void DisableOpenGLLights() - { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - } + void EnableOpenGLLights(); + void DisableOpenGLLights(); + void ProcessLighting(int layer, const MT_Transform& viewmat); - void EnableOpenGLLights(); + /* @attention mode is ignored here */ + void RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height); + void RenderText(int mode, + class RAS_IPolyMaterial* polymat, + float v1[3], + float v2[3], + float v3[3], + float v4[3], + int glattrib); - int ProcessLighting(int layer); + void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); + int applyLights(int objectlayer, const MT_Transform& viewmat); - void Perspective(int a, int width, int height, float mat[4][4], float viewmat[4][4]) - { - if(a== 0) - { - glMatrixMode(GL_PROJECTION); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - } - else - { - if(a== 1) - { - glMatrixMode(GL_PROJECTION); - glMatrixMode(GL_MODELVIEW); - } - } - } + void PushMatrix(); + void PopMatrix(); - /** - * @attention mode is ignored here - */ - virtual void RenderText2D( - RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height); - - /** - * Renders text into a (series of) polygon(s), using a texture font, - * Each character consists of one polygon (one quad or two triangles) - */ - virtual void RenderText( - int mode, - RAS_IPolyMaterial* polymat, - float v1[3], - float v2[3], - float v3[3], - float v4[3]); - - void Render(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode) - { - glPopMatrix(); - glPushMatrix(); - glMultMatrixd(oglmatrix); - } - - void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); - - virtual void PushMatrix() - { - glPushMatrix(); - } - - virtual void PopMatrix() - { - glPopMatrix(); - } - - virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep,int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - void* tface); - - int applyLights(int objectlayer); - - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } virtual void MotionBlur(RAS_IRasterizer* rasterizer); @@ -146,28 +99,7 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); - virtual void SetClientObject(void* obj); - -protected: - /** - * Copied from KX_BlenderGL.cpp in KX_blenderhook - */ - void BL_RenderText( - int mode, - const char* textstr, - int textlen, - struct MTFace* tface, - unsigned int* col, - float v1[3],float v2[3],float v3[3],float v4[3]); - void BL_spack(unsigned int ucol) - { - char *cp = (char *)&ucol; - glColor3ub(cp[3], cp[2], cp[1]); - } - - - BMF_Font* m_font; - static unsigned int m_numgllights; + virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); }; #endif // __GPC_RENDERTOOLS_H diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile index 19d792ddbdb..6a12e659be6 100644 --- a/source/gameengine/GamePlayer/common/Makefile +++ b/source/gameengine/GamePlayer/common/Makefile @@ -43,6 +43,7 @@ CPPFLAGS += -I../../../blender/blenloader CPPFLAGS += -I../../../blender/blenlib CPPFLAGS += -I../../../blender/imbuf CPPFLAGS += -I../../../blender/makesdna +CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include @@ -72,10 +73,6 @@ CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer CPPFLAGS += -I../../../gameengine/Physics/Sumo CPPFLAGS += -I../../../gameengine/Physics/common -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - ############################### SOURCEDIR = source/gameengine/GamePlayer/common diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index 3b2367d2592..30f20a670d3 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -8,7 +8,6 @@ source_files = ['bmfont.cpp', 'GPC_Engine.cpp', 'GPC_KeyboardDevice.cpp', 'GPC_MouseDevice.cpp', - 'GPC_PolygonMaterial.cpp', 'GPC_RawImage.cpp', 'GPC_RawLoadDotBlendArray.cpp', 'GPC_RawLogoArrays.cpp', @@ -46,6 +45,7 @@ incs = ['.', '#source/gameengine/GamePlayer/ghost', '#source/blender/misc', '#source/blender/blenloader', + '#source/blender/gpu', '#extern/glew/include'] #This is all plugin stuff! diff --git a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h index fee729a84ac..e5ed7f39811 100644 --- a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h +++ b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h @@ -37,9 +37,9 @@ class GPU_PolygonMaterial : public BP_PolygonMaterial public: GPUPolygonMaterial(const STR_String& texname, bool ba,const STR_String& matname, int tile, int tileXrep, int tileYrep, int mode, int transparant, - int lightlayer,bool bIsTriangle,void* clientobject,void* tpage) : + int lightlayer,,void* tpage) : BP_PolygonMaterial(texname, ba,matname, tile, tileXrep, tileYrep, - mode, transparant, lightlayer, bIsTriangle, clientobject), + mode, transparant, lightlayer), m_tface(tpage) { } diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index d9f0675001f..5e0ca93ac06 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -64,6 +64,7 @@ SET(INC ../../../../source/gameengine/GamePlayer/common ../../../../source/blender/misc ../../../../source/blender/blenloader + ../../../../source/blender/gpu ../../../../extern/solid ../../../../extern/glew/include ${PYTHON_INC} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index f859193ef7a..580c80ee0a5 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -38,6 +38,7 @@ #endif #include "GL/glew.h" +#include "GPU_extensions.h" #include "GPG_Application.h" @@ -97,16 +98,16 @@ extern "C" #include "GHOST_IEventConsumer.h" #include "GHOST_IWindow.h" #include "GHOST_Rect.h" -#include "marshal.h" static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time); static GHOST_ISystem* fSystem = 0; static const int kTimerFreq = 10; -GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName) - : m_startSceneName(startSceneName), - m_maggie(maggie), +GPG_Application::GPG_Application(GHOST_ISystem* system) + : m_startSceneName(""), + m_startScene(0), + m_maggie(0), m_exitRequested(0), m_system(system), m_mainWindow(0), @@ -127,7 +128,8 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR m_blendermat(0), m_blenderglslmat(0), m_pyGlobalDictString(0), - m_pyGlobalDictString_Length(0) + m_pyGlobalDictString_Length(0), + m_isEmbedded(false) { fSystem = system; } @@ -142,15 +144,16 @@ GPG_Application::~GPG_Application(void) -bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSceneName) +bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene) { bool result = false; - if (maggie != NULL && startSceneName != "") + if (maggie != NULL && scene != NULL) { - G.scene = (Scene*)maggie->scene.first; + G.scene = scene; m_maggie = maggie; - m_startSceneName = startSceneName; + m_startSceneName = scene->id.name+2; + m_startScene = scene; result = true; } @@ -322,6 +325,26 @@ bool GPG_Application::startWindow(STR_String& title, return success; } +bool GPG_Application::startEmbeddedWindow(STR_String& title, + const GHOST_TEmbedderWindowID parentWindow, + const bool stereoVisual, + const int stereoMode) { + + m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, stereoVisual, parentWindow); + + if (!m_mainWindow) { + printf("error: could not create main window\n"); + exit(-1); + } + m_isEmbedded = true; + + bool success = initEngine(m_mainWindow, stereoMode); + if (success) { + success = startEngine(); + } + return success; +} bool GPG_Application::startFullScreen( @@ -480,7 +503,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) { if (!m_engineInitialized) { - glewInit(); + GPU_extensions_init(); bgl::InitExtensions(true); // get and set the preferences @@ -499,13 +522,16 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); - bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0); + bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DISPLAY_LISTS) != 0); + + if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) + m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); + + if(GPU_extensions_minimum_support()) + m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); + else if(G.fileflags & G_FILE_GAME_MAT_GLSL) + m_blendermat = false; - if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) { - int gameflag =(G.fileflags & G_FILE_GAME_MAT); - m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0); - } - // create the canvas, rasterizer and rendertools m_canvas = new GPG_Canvas(window); if (!m_canvas) @@ -628,41 +654,34 @@ bool GPG_Application::startEngine(void) { STR_String startscenename = m_startSceneName.Ptr(); m_ketsjiengine->SetSceneConverter(m_sceneconverter); - + // if (always_use_expand_framing) // sceneconverter->SetAlwaysUseExpandFraming(true); - if(m_blendermat) + if(m_blendermat && (G.fileflags & G_FILE_GAME_MAT)) m_sceneconverter->SetMaterials(true); - if(m_blenderglslmat) + if(m_blenderglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) m_sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(m_keyboard, m_mouse, m_networkdevice, m_audiodevice, - startscenename); + startscenename, + m_startScene); // some python things PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest); m_ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(m_rasterizer, m_canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyObject *gameLogic = initGameLogic(m_ketsjiengine, startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); initMathutils(); /* Restore the dict */ - if (m_pyGlobalDictString) { - PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length); - if (pyGlobalDict) { - PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. - } else { - PyErr_Clear(); - printf("Error could not marshall string\n"); - } - } + loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); m_sceneconverter->ConvertScene( startscenename, @@ -700,30 +719,12 @@ bool GPG_Application::startEngine(void) void GPG_Application::stopEngine() { // get the python dict and convert to a string for future use - { - SetPyGlobalDictMarshal(NULL, 0); - - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); - if (gameLogic) { - PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module - if (pyGlobalDict) { - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 - if (pyGlobalDictMarshal) { - m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal); - PyObject_Print(pyGlobalDictMarshal, stderr, 0); - m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); - memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length); - } else { - printf("Error, GameLogic.globalDict could not be marshal'd\n"); - } - } else { - printf("Error, GameLogic.globalDict was removed\n"); - } - } else { - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); - } - } - + char *marshal_buffer; + m_pyGlobalDictString_Length = saveGamePythonConfig(&marshal_buffer); + if (m_pyGlobalDictString_Length) { + m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); + memcpy(m_pyGlobalDictString, marshal_buffer, m_pyGlobalDictString_Length); + } // when exiting the mainloop exitGamePythonScripting(); @@ -744,6 +745,8 @@ void GPG_Application::stopEngine() void GPG_Application::exitEngine() { + GPU_extensions_exit(); + if (m_ketsjiengine) { stopEngine(); @@ -870,7 +873,7 @@ bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown) GHOST_TEventKeyData* keyData = static_cast(eventData); //no need for this test //if (fSystem->getFullScreen()) { - if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc) { + if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc && !m_isEmbedded) { m_exitRequested = KX_EXIT_REQUEST_OUTSIDE; } //} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 31f5eb75e52..7fc369fc0fd 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -50,17 +50,19 @@ class GPG_Canvas; class GPG_KeyboardDevice; class GPG_System; struct Main; +struct Scene; class GPG_Application : public GHOST_IEventConsumer { public: - GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName); + GPG_Application(GHOST_ISystem* system); ~GPG_Application(void); - bool SetGameEngineData(struct Main* maggie,STR_String startSceneName); + bool SetGameEngineData(struct Main* maggie, struct Scene* scene); bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight, const bool stereoVisual, const int stereoMode); bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); + bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window, const bool stereoVisual, const int stereoMode); #ifdef WIN32 bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode); @@ -123,6 +125,7 @@ protected: /* The game data */ STR_String m_startSceneName; + struct Scene* m_startScene; struct Main* m_maggie; /* Exit state. */ @@ -141,6 +144,8 @@ protected: bool m_engineInitialized; /** Engine state. */ bool m_engineRunning; + /** Running on embedded window */ + bool m_isEmbedded; /** the gameengine itself */ KX_KetsjiEngine* m_ketsjiengine; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 26a85128025..c4e738c1896 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -54,6 +54,7 @@ extern "C" #endif // __cplusplus #include "BKE_global.h" #include "BKE_icons.h" +#include "BKE_node.h" #include "BLI_blenlib.h" #include "DNA_scene_types.h" #include "BLO_readfile.h" @@ -64,13 +65,15 @@ extern "C" #ifdef __cplusplus } #endif // __cplusplus + +#include "GPU_draw.h" + /********************************** * End Blender include block **********************************/ #include "SYS_System.h" #include "GPG_Application.h" -#include "GPC_PolygonMaterial.h" #include "GHOST_ISystem.h" #include "RAS_IRasterizer.h" @@ -176,6 +179,9 @@ void usage(char* program) printf(" anaglyph (Red-Blue glasses)\n"); printf(" vinterlace (Vertical interlace for autostereo display)\n"); printf(" depending on the type of stereo you want\n"); +#ifndef _WIN32 + printf(" -i: parent windows ID \n"); +#endif #ifdef _WIN32 printf(" -c: keep console window open\n"); #endif @@ -193,7 +199,8 @@ void usage(char* program) printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } -char *get_filename(int argc, char **argv) { +static void get_filename(int argc, char **argv, char *filename) +{ #ifdef __APPLE__ /* On Mac we park the game file (called game.blend) in the application bundle. * The executable is located in the bundle as well. @@ -201,22 +208,18 @@ char *get_filename(int argc, char **argv) { */ int srclen = ::strlen(argv[0]); int len = 0; - char *filename = NULL; + char *gamefile = NULL; + filename[0] = '\0'; + if (argc > 1) { if (BLI_exists(argv[argc-1])) { - len = ::strlen(argv[argc-1]); - filename = new char [len + 1]; - ::strcpy(filename, argv[argc-1]); - return(filename); + BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); } if (::strncmp(argv[argc-1], "-psn_", 5)==0) { static char firstfilebuf[512]; if (GHOST_HACK_getFirstFile(firstfilebuf)) { - len = ::strlen(firstfilebuf); - filename = new char [len + 1]; - ::strcpy(filename, firstfilebuf); - return(filename); + BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE); } } } @@ -224,23 +227,26 @@ char *get_filename(int argc, char **argv) { srclen -= ::strlen("MacOS/blenderplayer"); if (srclen > 0) { len = srclen + ::strlen("Resources/game.blend"); - filename = new char [len + 1]; - ::strcpy(filename, argv[0]); - ::strcpy(filename + srclen, "Resources/game.blend"); + gamefile = new char [len + 1]; + ::strcpy(gamefile, argv[0]); + ::strcpy(gamefile + srclen, "Resources/game.blend"); //::printf("looking for file: %s\n", filename); - if (BLI_exists(filename)) { - return (filename); - } + if (BLI_exists(gamefile)) + BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE); + + delete gamefile; } - return(NULL); #else - return (argc>1)?argv[argc-1]:NULL; + filename[0] = '\0'; + + if(argc > 1) + BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); #endif // !_APPLE } -static BlendFileData *load_game_data(char *progname, char *filename = NULL) { +static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL) { BlendReadError error; BlendFileData *bfd = NULL; @@ -282,7 +288,7 @@ int main(int argc, char** argv) bool fullScreenParFound = false; bool windowParFound = false; bool closeConsole = true; - RAS_IRasterizer::StereoMode stereomode; + RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; bool stereoWindow = false; bool stereoParFound = false; int windowLeft = 100; @@ -295,6 +301,9 @@ int main(int argc, char** argv) int fullScreenFrequency = 60; char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */ int pyGlobalDictString_Length = 0; + GHOST_TEmbedderWindowID parentWindow = 0; + + #ifdef __linux__ #ifdef __alpha__ @@ -323,6 +332,8 @@ int main(int argc, char** argv) ::DisposeNibReference(nibRef); */ #endif // __APPLE__ + + init_nodesystem(); GEN_init_messaging_system(); @@ -455,6 +466,16 @@ int main(int argc, char** argv) usage(argv[0]); return 0; break; +#ifndef _WIN32 + case 'i': + i++; + if ( (i + 1) < argc ) + parentWindow = atoi(argv[i++]); +#ifndef NDEBUG + printf("XWindows ID = %d\n", parentWindow); +#endif //NDEBUG + +#endif // _WIN32 case 'c': i++; closeConsole = false; @@ -525,21 +546,19 @@ int main(int argc, char** argv) return 0; } - if (!stereoParFound) stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; - #ifdef WIN32 if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION) #endif { #ifdef __APPLE__ //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1); - SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); + //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); //fullScreen = false; // Can't use full screen #endif if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) { - GPC_PolygonMaterial::SetMipMappingEnabled(0); + GPU_set_mipmap(0); } // Create the system @@ -561,11 +580,15 @@ int main(int argc, char** argv) { int exitcode = KX_EXIT_REQUEST_NO_REQUEST; STR_String exitstring = ""; - GPG_Application app(system, NULL, exitstring); + GPG_Application app(system); bool firstTimeRunning = true; - char *filename = get_filename(argc, argv); + char filename[FILE_MAXDIR + FILE_MAXFILE]; char *titlename; char pathname[160]; + + get_filename(argc, argv, filename); + if(filename[0]) + BLI_convertstringcwd(filename); do { @@ -597,7 +620,7 @@ int main(int argc, char** argv) } else { - bfd = load_game_data(argv[0], filename); + bfd = load_game_data(bprogname, filename[0]? filename: NULL); } //::printf("game data loaded from %s\n", filename); @@ -619,7 +642,7 @@ int main(int argc, char** argv) #endif // WIN32 Main *maggie = bfd->main; Scene *scene = bfd->curscene; - char *startscenename = scene->id.name + 2; + G.main = maggie; G.fileflags = bfd->fileflags; //Seg Fault; icon.c gIcons == 0 @@ -661,7 +684,7 @@ int main(int argc, char** argv) } // GPG_Application app (system, maggie, startscenename); - app.SetGameEngineData(maggie, startscenename); + app.SetGameEngineData(maggie, scene); if (firstTimeRunning) { @@ -729,7 +752,10 @@ int main(int argc, char** argv) else #endif { - app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, + if (parentWindow != 0) + app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode); + else + app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, stereoWindow, stereomode); } } @@ -763,12 +789,6 @@ int main(int argc, char** argv) pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength(); BLO_blendfiledata_free(bfd); - -#ifdef __APPLE__ - if (filename) { - delete [] filename; - } -#endif // __APPLE__ } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); } @@ -784,6 +804,8 @@ int main(int argc, char** argv) } } + free_nodesystem(); + if (pyGlobalDictString) { free(pyGlobalDictString); pyGlobalDictString = NULL; diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile index 13940ac3fc8..0b187791734 100644 --- a/source/gameengine/GamePlayer/ghost/Makefile +++ b/source/gameengine/GamePlayer/ghost/Makefile @@ -69,6 +69,7 @@ CPPFLAGS += -I../../../blender/blenloader CPPFLAGS += -I../../../blender/imbuf CPPFLAGS += -I../../../blender/makesdna CPPFLAGS += -I../../../blender/readblenfile +CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../../gameengine/BlenderRoutines @@ -80,7 +81,3 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_GHOST)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index f3cce6c7443..33cf07b6211 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -40,6 +40,7 @@ incs = ['.', '#source/gameengine/GamePlayer/common', '#source/blender/misc', '#source/blender/blenloader', + '#source/blender/gpu', '#extern/glew/include'] incs += Split(env['BF_PYTHON_INC']) @@ -48,8 +49,5 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': cflags = ['/GR'] -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index a9a0771936c..8ec463be6ff 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -9,108 +9,64 @@ #include "BL_BlenderShader.h" #include "BL_Material.h" -#ifdef BLENDER_GLSL #include "GPU_extensions.h" #include "GPU_material.h" -#endif #include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" - /* this is evil, but we need the scene to create materials with - * lights from the correct scene .. */ -static struct Scene *GetSceneForName(const STR_String& scenename) -{ - Scene *sce; - - for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next) - if (scenename == (sce->id.name+2)) - return sce; - - return (Scene*)G.main->scene.first; -} - -bool BL_BlenderShader::Ok() -{ -#ifdef BLENDER_GLSL - VerifyShader(); - - return (mMat && mMat->gpumaterial); -#else - return 0; -#endif -} - BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) : -#ifdef BLENDER_GLSL mScene(scene), mMat(ma), - mGPUMat(NULL), -#endif - mBound(false), mLightLayer(lightlayer) { -#ifdef BLENDER_GLSL - mBlenderScene = GetSceneForName(scene->GetName()); + mBlenderScene = scene->GetBlenderScene(); mBlendMode = GPU_BLEND_SOLID; - if(mMat) { + if(mMat) GPU_material_from_blender(mBlenderScene, mMat); - mGPUMat = mMat->gpumaterial; - } -#endif } BL_BlenderShader::~BL_BlenderShader() { -#ifdef BLENDER_GLSL - if(mMat && mMat->gpumaterial) - GPU_material_unbind(mMat->gpumaterial); -#endif + if(mMat && GPU_material_from_blender(mBlenderScene, mMat)) + GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); +} + +bool BL_BlenderShader::Ok() +{ + return VerifyShader(); } bool BL_BlenderShader::VerifyShader() { -#ifdef BLENDER_GLSL - if(mMat && !mMat->gpumaterial) - GPU_material_from_blender(mBlenderScene, mMat); - - mGPUMat = mMat->gpumaterial; - - return (mMat && mGPUMat); -#else - return false; -#endif + if(mMat) + return (GPU_material_from_blender(mBlenderScene, mMat) != 0); + else + return false; } -void BL_BlenderShader::SetProg(bool enable) +void BL_BlenderShader::SetProg(bool enable, double time) { -#ifdef BLENDER_GLSL if(VerifyShader()) { - if(enable) { - GPU_material_bind(mGPUMat, mLightLayer); - mBound = true; - } - else { - GPU_material_unbind(mGPUMat); - mBound = false; - } + if(enable) + GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, ~0, time); + else + GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); } -#endif } int BL_BlenderShader::GetAttribNum() { -#ifdef BLENDER_GLSL GPUVertexAttribs attribs; int i, enabled = 0; if(!VerifyShader()) return enabled; - GPU_material_vertex_attributes(mGPUMat, &attribs); + GPU_material_vertex_attributes(GPU_material_from_blender(mBlenderScene, mMat), &attribs); for(i = 0; i < attribs.totlayer; i++) if(attribs.layer[i].glindex+1 > enabled) @@ -120,24 +76,23 @@ int BL_BlenderShader::GetAttribNum() enabled = BL_MAX_ATTRIB; return enabled; -#else - return 0; -#endif } void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) { -#ifdef BLENDER_GLSL GPUVertexAttribs attribs; + GPUMaterial *gpumat; int i, attrib_num; ras->SetAttribNum(0); if(!VerifyShader()) return; + + gpumat = GPU_material_from_blender(mBlenderScene, mMat); if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { - GPU_material_vertex_attributes(mGPUMat, &attribs); + GPU_material_vertex_attributes(gpumat, &attribs); attrib_num = GetAttribNum(); ras->SetTexCoordNum(0); @@ -168,44 +123,37 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) else ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex); } - - ras->EnableTextures(true); } - else - ras->EnableTextures(false); -#endif } -void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) +void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { -#ifdef BLENDER_GLSL float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; + GPUMaterial *gpumat; - VerifyShader(); + gpumat = GPU_material_from_blender(mBlenderScene, mMat); - if(!mGPUMat) // || !mBound) + if(!gpumat || !GPU_material_bound(gpumat)) return; MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - MT_Matrix4x4 view; - rasty->GetViewMatrix(view); + const MT_Matrix4x4& view = rasty->GetViewMatrix(); + const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); + // note: getValue gives back column major as needed by OpenGL model.getValue((float*)obmat); view.getValue((float*)viewmat); - - view.invert(); - view.getValue((float*)viewinvmat); + viewinv.getValue((float*)viewinvmat); if(ms.m_bObjectColor) ms.m_RGBAcolor.getValue((float*)obcol); else obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; - GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol); + GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol); - mBlendMode = GPU_material_blend_mode(mGPUMat, obcol); -#endif + mBlendMode = GPU_material_blend_mode(gpumat, obcol); } int BL_BlenderShader::GetBlendMode() @@ -215,12 +163,8 @@ int BL_BlenderShader::GetBlendMode() bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) { -#ifdef BLENDER_GLSL /* to avoid unneeded state switches */ - return (blshader && mGPUMat == blshader->mGPUMat && mLightLayer == blshader->mLightLayer); -#else - return true; -#endif + return (blshader && mMat == blshader->mMat && mLightLayer == blshader->mLightLayer); } // eof diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index da9765dafa4..5c1f59f94ad 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -2,9 +2,7 @@ #ifndef __BL_GPUSHADER_H__ #define __BL_GPUSHADER_H__ -#ifdef BLENDER_GLSL #include "GPU_material.h" -#endif #include "MT_Matrix4x4.h" #include "MT_Matrix3x3.h" @@ -29,13 +27,9 @@ class BL_Material; class BL_BlenderShader { private: -#ifdef BLENDER_GLSL KX_Scene *mScene; struct Scene *mBlenderScene; struct Material *mMat; - GPUMaterial *mGPUMat; -#endif - bool mBound; int mLightLayer; int mBlendMode; @@ -46,11 +40,11 @@ public: virtual ~BL_BlenderShader(); bool Ok(); - void SetProg(bool enable); + void SetProg(bool enable, double time=0.0); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); - void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index dcb66ea2579..0eaa234566c 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -18,9 +18,9 @@ struct EnvMap; this will default to users available units to build with more available, just increment this value although the more you add the slower the search time will be. - we will go for three, which should be enough + we will go for eight, which should be enough */ -#define MAXTEX 3 //match in RAS_TexVert & RAS_OpenGLRasterizer +#define MAXTEX 8 //match in RAS_TexVert & RAS_OpenGLRasterizer // different mapping modes class BL_Mapping @@ -139,7 +139,7 @@ enum BL_ras_mode COLLIDER=2, ZSORT=4, ALPHA=8, - TRIANGLE=16, + // TRIANGLE=16, USE_LIGHT=32, WIRE=64 }; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 57d0fe4140f..f28d3fa2912 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -433,7 +433,7 @@ void BL_Shader::SetProg(bool enable) } } -void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) +void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { if(!Ok() || !mPreDef.size()) return; @@ -445,8 +445,7 @@ void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - MT_Matrix4x4 view; - rasty->GetViewMatrix(view); + const MT_Matrix4x4& view = rasty->GetViewMatrix(); if(mAttr==SHD_TANGENT) ms.m_mesh->SetMeshModified(true); @@ -525,13 +524,15 @@ void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) } case VIEWMATRIX_INVERSE: { - view.invert(); + MT_Matrix4x4 viewinv = view; + viewinv.invert(); SetUniform(uni->mLoc, view); break; } case VIEWMATRIX_INVERSETRANSPOSE: { - view.invert(); + MT_Matrix4x4 viewinv = view; + viewinv.invert(); SetUniform(uni->mLoc, view, true); break; } @@ -670,6 +671,7 @@ void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose) ) { float value[16]; + // note: getValue gives back column major as needed by OpenGL vec.getValue(value); glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value); } diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 8f303454087..c7fae31ba03 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -177,7 +177,7 @@ public: void UnloadShader(); // Update predefined uniforms each render call - void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); //// Set sampler units (copied) //void InitializeSampler(int unit, BL_Texture* texture ); diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index be009d94701..58411f6d25e 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -69,6 +69,7 @@ SET(INC ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader + ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ../../../extern/glew/include diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 0c66ac1fde3..a35ab8b15e8 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -196,19 +196,19 @@ PyParentObject KX_NetworkMessageSensor::Parents[] = { PyMethodDef KX_NetworkMessageSensor::Methods[] = { {"setSubjectFilterText", (PyCFunction) - KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS, + KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O, SetSubjectFilterText_doc}, {"getFrameMessageCount", (PyCFunction) - KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_NOARGS, GetFrameMessageCount_doc}, {"getBodies", (PyCFunction) - KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetBodies, METH_NOARGS, GetBodies_doc}, {"getSubject", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetSubject, METH_NOARGS, GetSubject_doc}, {"getSubjects", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubjects, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS, GetSubjects_doc}, {NULL,NULL} //Sentinel }; @@ -222,22 +222,16 @@ char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = "\tsetSubjectFilterText(value)\n" "\tChange the message subject text that this sensor is listening to.\n"; -PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value) { - char* Subject; - - if (PyArg_ParseTuple(args, "s", &Subject)) - { - m_subject = Subject; - } - else { + char* Subject = PyString_AsString(value); + if (Subject==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string message"); return NULL; } - - Py_Return; + + m_subject = Subject; + Py_RETURN_NONE; } // 2. Get the number of messages received since the last frame @@ -245,10 +239,7 @@ char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = "\tgetFrameMessageCount()\n" "\tGet the number of messages received since the last frame.\n"; -PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* ) { return PyInt_FromLong(long(m_frame_message_count)); } @@ -258,16 +249,13 @@ char KX_NetworkMessageSensor::GetBodies_doc[] = "\tgetBodies()\n" "\tGet the list of message bodies.\n"; -PyObject* KX_NetworkMessageSensor::PyGetBodies( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* ) { if (m_BodyList) { return ((PyObject*) m_BodyList->AddRef()); + } else { + return ((PyObject*) new CListValue()); } - - Py_Return; } // 4. Get the message subject: field of the message sensor @@ -275,16 +263,9 @@ char KX_NetworkMessageSensor::GetSubject_doc[] = "\tgetSubject()\n" "\tGet the subject: field of the message sensor.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubject( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* ) { - if (m_subject) { - return PyString_FromString(m_subject); - } - - Py_Return; + return PyString_FromString(m_subject ? m_subject : ""); } // 5. Get the message subjects @@ -292,14 +273,11 @@ char KX_NetworkMessageSensor::GetSubjects_doc[] = "\tgetSubjects()\n" "\tGet list of message subjects.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubjects( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* ) { if (m_SubjectList) { - return ((PyObject*) m_SubjectList->AddRef()); - } - - Py_Return; + return ((PyObject*) m_SubjectList->AddRef()); + } else { + return ((PyObject*) new CListValue()); + } } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 6fd92d17be3..8cdfd6cdb5a 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -74,11 +74,11 @@ public: virtual PyObject* _getattr(const STR_String& attr); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, SetSubjectFilterText); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetFrameMessageCount); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetBodies); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubject); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubjects); + KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetBodies); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubject); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubjects); }; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index a67e5b26667..f92200780d5 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -19,13 +19,12 @@ #include "MT_Vector4.h" #include "MT_Matrix4x4.h" +#include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" -extern "C" { -#include "BDR_drawmesh.h" -} +#include "GPU_draw.h" #include "STR_HashedString.h" @@ -48,7 +47,6 @@ KX_BlenderMaterial::KX_BlenderMaterial( BL_Material *data, bool skin, int lightlayer, - void *clientobject, PyTypeObject *T ) : PyObjectPlus(T), @@ -62,9 +60,7 @@ KX_BlenderMaterial::KX_BlenderMaterial( data->transp, ((data->ras_mode &ALPHA)!=0), ((data->ras_mode &ZSORT)!=0), - lightlayer, - ((data->ras_mode &TRIANGLE)!=0), - clientobject + lightlayer ), mMaterial(data), mShader(0), @@ -78,9 +74,10 @@ KX_BlenderMaterial::KX_BlenderMaterial( { // -------------------------------- // RAS_IPolyMaterial variables... - m_flag |=RAS_BLENDERMAT; - m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; - m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; + m_flag |= RAS_BLENDERMAT; + m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0; + m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0; + m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; // figure max int enabled = mMaterial->num_enabled; @@ -97,7 +94,7 @@ KX_BlenderMaterial::KX_BlenderMaterial( mMaterial->blend_mode[i] ); } - m_multimode += mMaterial->IdMode+mMaterial->ras_mode; + m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT)); } @@ -204,7 +201,7 @@ void KX_BlenderMaterial::OnExit() } if( mMaterial->tface ) - set_tpage(mMaterial->tface); + GPU_set_tpage(mMaterial->tface); } @@ -256,25 +253,28 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras) { if( !enable || !mBlenderShader->Ok() ) { + ras->SetBlendingMode(TF_SOLID); + // frame cleanup. if(mLastBlenderShader) { mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; } + else + BL_Texture::DisableAllTextures(); - ras->SetBlendingMode(TF_SOLID); - BL_Texture::DisableAllTextures(); return; } if(!mBlenderShader->Equals(mLastBlenderShader)) { ras->SetBlendingMode(mMaterial->transp); - BL_Texture::DisableAllTextures(); if(mLastBlenderShader) mLastBlenderShader->SetProg(false); + else + BL_Texture::DisableAllTextures(); - mBlenderShader->SetProg(true); + mBlenderShader->SetProg(true, ras->GetTime()); mLastBlenderShader= mBlenderShader; } } @@ -354,21 +354,22 @@ KX_BlenderMaterial::ActivatShaders( if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - tmp->setShaderData( false, rasty); + tmp->setShaderData(false, rasty); cachingInfo = GetCachingInfo(); if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - tmp->setShaderData( true, rasty); + tmp->setShaderData(true, rasty); else - tmp->setShaderData( false, rasty); + tmp->setShaderData(false, rasty); if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) + if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -394,31 +395,24 @@ KX_BlenderMaterial::ActivateBlenderShaders( mLastShader= NULL; } - // reset... - if(tmp->mMaterial->IsShared()) - cachingInfo =0; - if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) tmp->setBlenderShaderData(false, rasty); cachingInfo = GetCachingInfo(); - if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { + if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) tmp->setBlenderShaderData(true, rasty); - rasty->EnableTextures(true); - } - else { + else tmp->setBlenderShaderData(false, rasty); - rasty->EnableTextures(false); - } if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) + if (((mMaterial->ras_mode & WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -426,10 +420,10 @@ KX_BlenderMaterial::ActivateBlenderShaders( } else rasty->SetLines(false); - } - ActivatGLMaterials(rasty); - mBlenderShader->SetAttribs(rasty, mMaterial); + ActivatGLMaterials(rasty); + mBlenderShader->SetAttribs(rasty, mMaterial); + } } void @@ -466,7 +460,8 @@ KX_BlenderMaterial::ActivateMat( else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) + if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -486,12 +481,10 @@ KX_BlenderMaterial::Activate( TCachingInfo& cachingInfo )const { - bool dopass = false; - if( GLEW_ARB_shader_objects && ( mShader && mShader->Ok() ) ) { - if( (mPass++) < mShader->getNumPass() ) { + if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) { + if((mPass++) < mShader->getNumPass() ) { ActivatShaders(rasty, cachingInfo); - dopass = true; - return dopass; + return true; } else { if(mShader == mLastShader) { @@ -499,36 +492,29 @@ KX_BlenderMaterial::Activate( mLastShader = NULL; } mPass = 0; - dopass = false; - return dopass; + return false; } } - else if( GLEW_ARB_shader_objects && ( mBlenderShader && mBlenderShader->Ok() ) ) { - if( (mPass++) == 0 ) { + else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) { + if(mPass++ == 0) { ActivateBlenderShaders(rasty, cachingInfo); - dopass = true; - return dopass; + return true; } else { mPass = 0; - dopass = false; - return dopass; + return false; } } else { - switch (mPass++) - { - case 0: - ActivateMat(rasty, cachingInfo); - dopass = true; - break; - default: - mPass = 0; - dopass = false; - break; + if(mPass++ == 0) { + ActivateMat(rasty, cachingInfo); + return true; + } + else { + mPass = 0; + return false; } } - return dopass; } bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const @@ -536,14 +522,15 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const if(!RAS_IPolyMaterial::UsesLighting(rasty)) return false; - if(mShader && mShader->Ok()); + if(mShader && mShader->Ok()) + return true; else if(mBlenderShader && mBlenderShader->Ok()) return false; - - return true; + else + return true; } -void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const +void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const { if(mShader && GLEW_ARB_shader_objects) { mShader->Update(ms, rasty); @@ -554,7 +541,7 @@ void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterize mBlenderShader->Update(ms, rasty); /* we do blend modes here, because they can change per object - * with the same material due to obcolor */ + * with the same material due to obcolor/obalpha */ blendmode = mBlenderShader->GetBlendMode(); if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) blendmode = mMaterial->transp; @@ -633,11 +620,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const else ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i); } - - ras->EnableTextures(true); } - else - ras->EnableTextures(false); } void KX_BlenderMaterial::setTexMatrixData(int i) @@ -712,8 +695,7 @@ void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras) glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); - MT_Matrix4x4 mvmat; - ras->GetViewMatrix(mvmat); + const MT_Matrix4x4& mvmat = ras->GetViewMatrix(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); @@ -835,7 +817,9 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") } if(mShader && !mShader->GetError()) { + m_flag &= ~RAS_BLENDERGLSL; mMaterial->SetSharedMaterial(true); + mScene->GetBucketManager()->ReleaseDisplayLists(this); Py_INCREF(mShader); return mShader; }else @@ -870,8 +854,6 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(void) delete mBlenderShader; mBlenderShader = 0; } - else - m_flag |= RAS_BLENDERGLSL; } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 0d7657b8cdb..4ddf5a924df 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -28,7 +28,6 @@ public: BL_Material* mat, bool skin, int lightlayer, - void* clientobject, PyTypeObject* T=&Type ); @@ -47,7 +46,7 @@ public: virtual void ActivateMeshSlot( - const KX_MeshSlot & ms, + const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) const; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 42b909927fd..4948c0ea174 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -35,6 +35,8 @@ #include #include "KX_GameObject.h" +#include "PyObjectPlus.h" + STR_String KX_CameraActuator::X_AXIS_STRING = "x"; STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index e00ec68ad33..4b57b0e8c54 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -109,16 +109,11 @@ KX_ConstraintActuator::~KX_ConstraintActuator() // there's nothing to be done here, really.... } /* end of destructor */ -bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } bool bFound = false; if (m_property[0] == 0) @@ -139,8 +134,26 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_p bFound = hitKXObj->GetProperty(m_property) != NULL; } } + // update the hit status + result->m_hitFound = bFound; + // stop looking + return true; +} - return bFound; +/* this function is used to pre-filter the object before casting the ray on them. + This is useful for "X-Ray" option when we want to see "through" unwanted object. + */ +bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client) +{ + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // Unknown type of object, skip it. + // Should not occur as the sensor objects are filtered in RayTest() + printf("Invalid client type %d found in ray casting\n", client->m_type); + return false; + } + // no X-Ray function yet + return true; } bool KX_ConstraintActuator::Update(double curtime, bool frame) @@ -287,8 +300,6 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) direction.normalize(); { MT_Point3 topoint = position + (m_maximumBound) * direction; - MT_Point3 resultpoint; - MT_Vector3 resultnormal; PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment(); KX_IPhysicsController *spc = obj->GetPhysicsController(); @@ -304,9 +315,10 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) parent->Release(); } } - result = KX_RayCast::RayTest(spc, pe, position, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this)); - + KX_RayCast::Callback callback(this,spc); + result = KX_RayCast::RayTest(pe, position, topoint, callback); if (result) { + MT_Vector3 newnormal = callback.m_hitNormal; // compute new position & orientation if ((m_option & (KX_ACT_CONSTRAINT_NORMAL|KX_ACT_CONSTRAINT_DISTANCE)) == 0) { // if none option is set, the actuator does nothing but detect ray @@ -316,27 +328,27 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) if (m_option & KX_ACT_CONSTRAINT_NORMAL) { // the new orientation must be so that the axis is parallel to normal if (sign) - resultnormal = -resultnormal; + newnormal = -newnormal; // apply damping on the direction if (m_rotDampTime) { MT_Scalar rotFilter = 1.0/(1.0+m_rotDampTime); - resultnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*resultnormal; + newnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*newnormal; } else if (m_posDampTime) { - resultnormal = -filter*direction + (1.0-filter)*resultnormal; + newnormal = -filter*direction + (1.0-filter)*newnormal; } - obj->AlignAxisToVect(resultnormal, axis); - direction = -resultnormal; + obj->AlignAxisToVect(newnormal, axis); + direction = -newnormal; } if (m_option & KX_ACT_CONSTRAINT_DISTANCE) { if (m_posDampTime) { - newdistance = filter*(position-resultpoint).length()+(1.0-filter)*m_minimumBound; + newdistance = filter*(position-callback.m_hitPoint).length()+(1.0-filter)*m_minimumBound; } else { newdistance = m_minimumBound; } } else { - newdistance = (position-resultpoint).length(); + newdistance = (position-callback.m_hitPoint).length(); } - newposition = resultpoint-newdistance*direction; + newposition = callback.m_hitPoint-newdistance*direction; } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) { // no contact but still keep running result = true; diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index d9f39124cac..6ec4de9aad9 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -37,6 +37,8 @@ #include "MT_Vector3.h" #include "KX_ClientObjectInfo.h" +class KX_RayCast; + class KX_ConstraintActuator : public SCA_IActuator { Py_Header; @@ -100,7 +102,8 @@ protected: KX_ACT_CONSTRAINT_DISTANCE = 512 }; bool IsValidMode(KX_CONSTRAINTTYPE m); - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo*); KX_ConstraintActuator(SCA_IObject* gameobj, int posDamptime, diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index b54da6eb753..c9095ff34f6 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -27,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ #include +#include "PyObjectPlus.h" #include "KX_ConstraintWrapper.h" #include "PHY_IPhysicsEnvironment.h" diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 6653026f28a..248d2f49b0b 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -86,6 +86,7 @@ struct KX_ObjectProperties bool m_disableSleeping; bool m_hasCompoundChildren; bool m_isCompoundChild; + double m_margin; KX_BoundBoxClass m_boundclass; union { KX_BoxBounds box; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index d6997ee29a8..b3f24d97281 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -76,16 +76,16 @@ struct KX_PhysicsInstance { DT_VertexBaseHandle m_vertexbase; - int m_vtxarray; + RAS_DisplayArray* m_darray; RAS_IPolyMaterial* m_material; - - KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, int vtxarray, RAS_IPolyMaterial* mat) + + KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat) : m_vertexbase(vertex_base), - m_vtxarray(vtxarray), - m_material(mat) + m_darray(darray), + m_material(mat) { } - + ~KX_PhysicsInstance() { DT_DeleteVertexBase(m_vertexbase); @@ -100,11 +100,11 @@ static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoSce 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) + RAS_MeshObject* meshobj, + KX_Scene* kxscene, + PHY_ShapeProps* kxshapeprops, + PHY_MaterialProps* kxmaterial, + struct KX_ObjectProperties* objprop) { @@ -150,23 +150,23 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, 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]); + 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); + 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); + 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. */ + /* Dynamic mesh objects. WARNING! slow. */ case KX_BOUNDPOLYTOPE: polytope = true; // fall through @@ -186,15 +186,15 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, 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 @@ -320,12 +320,11 @@ static void BL_RegisterSumoObject( physicscontroller->SetObject(gameobj->GetSGNode()); } -static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat) +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 = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]); - //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray]; - DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert)); + 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); @@ -337,15 +336,19 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarr // only add polygons that have the collisionflag set if (poly->IsCollider()) { - DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray); + 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->GetVertexIndexBase().m_indexarray[0]); - DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]); - DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[3]); + DT_VertexIndex(poly->GetVertexOffset(0)); + DT_VertexIndex(poly->GetVertexOffset(2)); + DT_VertexIndex(poly->GetVertexOffset(3)); DT_End(); } } @@ -354,16 +357,15 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarr //DT_VertexIndices(indices.size(), &indices[0]); DT_EndComplexShape(); - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat)); + map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); return shape; } -static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat) +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 = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]); - //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray]; - DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert)); + 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++) @@ -373,12 +375,12 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxar // only add polygons that have the collisionflag set if (poly->IsCollider()) { - indices.push_back(poly->GetVertexIndexBase().m_indexarray[0]); - indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]); - indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]); + 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->GetVertexIndexBase().m_indexarray[3]); + indices.push_back(poly->GetVertexOffset(3)); } } @@ -386,7 +388,7 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxar DT_VertexIndices(indices.size(), &indices[0]); DT_EndPolytope(); - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat)); + map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); return shape; } @@ -398,8 +400,8 @@ bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj) KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)]; if (instance) { - const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(instance->m_material)[instance->m_vtxarray])[0]); - DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getLocalXYZ()); + const RAS_TexVert *vertex_array = &instance->m_darray->m_vertex[0]; + DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getXYZ()); return true; } return false; @@ -425,7 +427,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope // Count the number of collision polygons and check they all come from the same // vertex array int numvalidpolys = 0; - int vtxarray = -1; + RAS_DisplayArray *darray = NULL; RAS_IPolyMaterial *poly_material = NULL; bool reinstance = true; @@ -437,14 +439,14 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->IsCollider()) { // check polygon is from the same vertex array - if (poly->GetVertexIndexBase().m_vtxarray != vtxarray) + if (poly->GetDisplayArray() != darray) { - if (vtxarray < 0) - vtxarray = poly->GetVertexIndexBase().m_vtxarray; + if (darray == NULL) + darray = poly->GetDisplayArray(); else { reinstance = false; - vtxarray = -1; + darray = NULL; } } @@ -478,9 +480,9 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (reinstance) { if (polytope) - shape = InstancePhysicsPolytope(meshobj, vtxarray, poly_material); + shape = InstancePhysicsPolytope(meshobj, darray, poly_material); else - shape = InstancePhysicsComplex(meshobj, vtxarray, poly_material); + shape = InstancePhysicsComplex(meshobj, darray, poly_material); } else { @@ -489,7 +491,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl; if (!poly_material) std::cout << " Check mesh materials." << std::endl; - if (vtxarray < 0) + if (darray == NULL) std::cout << " Check number of vertices." << std::endl; } @@ -505,18 +507,10 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->IsCollider()) { /* We have to tesselate here because SOLID can only raycast triangles */ DT_Begin(); - /* V1 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V2 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[1], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V3 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V1, V2, V3 */ + DT_Vertex(poly->GetVertex(2)->getXYZ()); + DT_Vertex(poly->GetVertex(1)->getXYZ()); + DT_Vertex(poly->GetVertex(0)->getXYZ()); numvalidpolys++; DT_End(); @@ -524,18 +518,10 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->VertexCount() == 4) { DT_Begin(); - /* V1 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[3], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V3 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V4 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V1, V3, V4 */ + DT_Vertex(poly->GetVertex(3)->getXYZ()); + DT_Vertex(poly->GetVertex(2)->getXYZ()); + DT_Vertex(poly->GetVertex(0)->getXYZ()); numvalidpolys++; DT_End(); @@ -713,6 +699,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_gravity = btVector3(0,0,0); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; + ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; @@ -800,7 +787,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, return; } - bm->setMargin(0.06); + bm->setMargin(ci.m_margin); if (objprop->m_isCompoundChild) @@ -815,11 +802,29 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; - MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition(); - MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation(); - MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale(); + // compute the local transform from parent, this may include a parent inverse node + SG_Node* gameNode = gameobj->GetSGNode(); + SG_Node* parentInverseNode = gameNode->GetSGParent(); + if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL) + // this is not a parent inverse node, cancel it + parentInverseNode = NULL; + // now combine the parent inverse node and the game node + MT_Point3 childPos = gameNode->GetLocalPosition(); + MT_Matrix3x3 childRot = gameNode->GetLocalOrientation(); + MT_Vector3 childScale = gameNode->GetLocalScale(); + if (parentInverseNode) + { + const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition(); + const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation(); + const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale(); + childRot = parentInverseRot * childRot; + childScale = parentInverseScale * childScale; + childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos); + } - bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z())); + shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z()); + bm->setLocalScaling(shapeInfo->m_childScale); + shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z())); float rotval[12]; childRot.getValue(rotval); diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index fcd32d5f4fe..91ddbbbfbc9 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -34,6 +34,7 @@ //#include #include "KX_Scene.h" #include "KX_KetsjiEngine.h" +#include "KX_PythonInit.h" /* for config load/saving */ #ifdef HAVE_CONFIG_H #include @@ -125,6 +126,71 @@ bool KX_GameActuator::Update() } break; } + case KX_GAME_SAVECFG: + { + if (m_ketsjiengine) + { + char mashal_path[512]; + char *marshal_buffer = NULL; + int marshal_length; + FILE *fp = NULL; + + pathGamePythonConfig(mashal_path); + marshal_length = saveGamePythonConfig(&marshal_buffer); + + if (marshal_length && marshal_buffer) { + fp = fopen(mashal_path, "wb"); + if (fp) { + if (fwrite(marshal_buffer, 1, marshal_length, fp) != marshal_length) { + printf("Warning: could not write marshal data\n"); + } + fclose(fp); + } else { + printf("Warning: could not open marshal file\n"); + } + } else { + printf("Warning: could not create marshal buffer\n"); + } + } + break; + } + case KX_GAME_LOADCFG: + { + if (m_ketsjiengine) + { + char mashal_path[512]; + char *marshal_buffer; + int marshal_length; + FILE *fp = NULL; + int result; + + pathGamePythonConfig(mashal_path); + + fp = fopen(mashal_path, "rb"); + if (fp) { + // obtain file size: + fseek (fp , 0 , SEEK_END); + marshal_length = ftell(fp); + rewind(fp); + + marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); + + result = fread (marshal_buffer, 1, marshal_length, fp); + + if (result == marshal_length) { + loadGamePythonConfig(marshal_buffer, marshal_length); + } else { + printf("warning: could not read all of '%s'\n", mashal_path); + } + + free(marshal_buffer); + fclose(fp); + } else { + printf("warning: could not open '%s'\n", mashal_path); + } + } + break; + } default: ; /* do nothing? this is an internal error !!! */ } diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index 8565dc46caa..bb3448995dc 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -54,6 +54,8 @@ protected: KX_GAME_START, KX_GAME_RESTART, KX_GAME_QUIT, + KX_GAME_SAVECFG, + KX_GAME_LOADCFG, KX_GAME_MAX }; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 700cc00e996..0e5956d4fdb 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -51,6 +51,7 @@ typedef unsigned long uint_ptr; #include "KX_GameObject.h" #include "RAS_MeshObject.h" #include "KX_MeshProxy.h" +#include "KX_PolyProxy.h" #include // printf #include "SG_Controller.h" #include "KX_IPhysicsController.h" @@ -64,6 +65,8 @@ typedef unsigned long uint_ptr; #include "SCA_IActuator.h" #include "SCA_ISensor.h" +#include "PyObjectPlus.h" /* python stuff */ + // This file defines relationships between parents and children // in the game engine. @@ -78,12 +81,15 @@ KX_GameObject::KX_GameObject( m_bDyna(false), m_layer(0), m_pBlenderObject(NULL), + m_pBlenderGroupObject(NULL), m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_bVisible(true), + m_bCulled(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), + m_xray(false), m_pHitObject(NULL), m_isDeformable(false) { @@ -99,8 +105,11 @@ KX_GameObject::KX_GameObject( }; + KX_GameObject::~KX_GameObject() { + RemoveMeshes(); + // is this delete somewhere ? //if (m_sumoObj) // delete m_sumoObj; @@ -162,7 +171,6 @@ STR_String KX_GameObject::GetName() void KX_GameObject::SetName(STR_String name) { m_name = name; - }; // Set the name of the value @@ -227,11 +235,12 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) m_pPhysicsController1->SuspendDynamics(true); } // Set us to our new scale, position, and orientation - scale1[0] = scale1[0]/scale2[0]; - scale1[1] = scale1[1]/scale2[1]; - scale1[2] = scale1[2]/scale2[2]; + scale2[0] = 1.0/scale2[0]; + scale2[1] = 1.0/scale2[1]; + scale2[2] = 1.0/scale2[2]; + scale1 = scale1 * scale2; MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse(); - MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1; + MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; NodeSetLocalScale(scale1); NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); @@ -283,11 +292,11 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica) CValue* KX_GameObject::GetReplica() { KX_GameObject* replica = new KX_GameObject(*this); - + // this will copy properties and so on... CValue::AddDataToReplica(replica); ProcessReplica(replica); - + return replica; } @@ -353,24 +362,47 @@ double* KX_GameObject::GetOpenGLMatrix() return fl; } +void KX_GameObject::AddMeshUser() +{ + for (size_t i=0;iAddMeshUser(this); + + UpdateBuckets(false); +} +static void UpdateBuckets_recursive(SG_Node* node) +{ + NodeList& children = node->GetSGChildren(); -void KX_GameObject::Bucketize() + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->UpdateBuckets(0); + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + UpdateBuckets_recursive(childnode); + } +} + +void KX_GameObject::UpdateBuckets( bool recursive ) { double* fl = GetOpenGLMatrix(); for (size_t i=0;iBucketize(fl, this, m_bUseObjectColor, m_objectColor); + m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); + + if (recursive) { + UpdateBuckets_recursive(m_pSGNode); + } } - - void KX_GameObject::RemoveMeshes() { - double* fl = GetOpenGLMatrix(); - for (size_t i=0;iRemoveFromBuckets(fl, this); + m_meshes[i]->RemoveFromBuckets(this); //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter @@ -453,13 +485,14 @@ KX_GameObject::UpdateMaterialData( ) { int mesh = 0; - if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { - RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial(); + list::iterator mit = m_meshes[mesh]->GetFirstMaterial(); + for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) { - RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial(); - if(poly->GetFlag() & RAS_BLENDERMAT) + RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial(); + + if(poly->GetFlag() & RAS_BLENDERMAT ) { KX_BlenderMaterial *m = static_cast(poly); @@ -467,8 +500,7 @@ KX_GameObject::UpdateMaterialData( { m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) - if(!(poly->GetFlag() & RAS_BLENDERGLSL)) - SetObjectColor(rgba); + SetObjectColor(rgba); } else { @@ -494,14 +526,52 @@ KX_GameObject::GetVisible( return m_bVisible; } +static void setVisible_recursive(SG_Node* node, bool v) +{ + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->SetVisible(v, 0); + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + setVisible_recursive(childnode, v); + } +} + + void KX_GameObject::SetVisible( - bool v + bool v, + bool recursive ) { m_bVisible = v; + if (recursive) + setVisible_recursive(m_pSGNode, v); } +bool +KX_GameObject::GetCulled( + void + ) +{ + return m_bCulled; +} + +void +KX_GameObject::SetCulled( + bool c + ) +{ + m_bCulled = c; +} + + void KX_GameObject::SetLayer( int l @@ -518,44 +588,6 @@ KX_GameObject::GetLayer( return m_layer; } -// used by Python, and the actuatorshould _not_ be misused by the -// scene! -void -KX_GameObject::MarkVisible( - bool visible - ) -{ - /* If explicit visibility settings are used, this is - * determined on this level. Maybe change this to mesh level - * later on? */ - - double* fl = GetOpenGLMatrixPtr()->getPointer(); - for (size_t i=0;iMarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor); - } -} - - -// Always use the flag? -void -KX_GameObject::MarkVisible( - void - ) -{ - double* fl = GetOpenGLMatrixPtr()->getPointer(); - for (size_t i=0;iMarkVisible(fl, - this, - m_bVisible, - m_bUseObjectColor, - m_objectColor - ); - } -} - - void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local) { if (m_pPhysicsController1) @@ -883,15 +915,18 @@ void KX_GameObject::Suspend() PyMethodDef KX_GameObject::Methods[] = { {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, + {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS}, {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS}, + {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, + {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS}, {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS}, {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS}, {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS}, - {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O}, + {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS}, {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, @@ -1032,18 +1067,23 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr method { - if (attr == "mass") + if (attr == "mass") { + PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only"); return 1; + } - if (attr == "parent") + if (attr == "parent") { + PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); return 1; + } if (PyInt_Check(value)) { int val = PyInt_AsLong(value); if (attr == "visible") { - SetVisible(val != 0); + SetVisible(val != 0, false); + UpdateBuckets(false); return 0; } } @@ -1102,7 +1142,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr } return 1; } - + PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence"); return 1; } @@ -1146,9 +1186,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr } -PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -1162,9 +1200,7 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, } } -PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) { int local = 0; PyObject* pyvect; @@ -1179,17 +1215,43 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, return NULL; } -PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) { - int visible = PyInt_AsLong(value); - - if (visible==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected 0 or 1"); + // only can get the velocity if we have a physics object connected to us... + int local = 0; + if (PyArg_ParseTuple(args,"|i",&local)) + { + return PyObjectFrom(GetAngularVelocity((local!=0))); + } + else + { return NULL; } +} + +PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) +{ + int local = 0; + PyObject* pyvect; - MarkVisible(visible!=0); - m_bVisible = (visible!=0); + if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { + MT_Vector3 velocity; + if (PyVecTo(pyvect, velocity)) { + setAngularVelocity(velocity, (local!=0)); + Py_RETURN_NONE; + } + } + return NULL; +} + +PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) +{ + int visible, recursive = 0; + if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive)) + return NULL; + + SetVisible(visible ? true:false, recursive ? true:false); + UpdateBuckets(recursive ? true:false); Py_RETURN_NONE; } @@ -1228,9 +1290,7 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyGetVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... MT_Vector3 velocity(0.0,0.0,0.0); @@ -1362,9 +1422,7 @@ PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self) return list; } -PyObject* KX_GameObject::PyGetMesh(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) { int mesh = 0; @@ -1404,9 +1462,7 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) { PyObject* pyattach; PyObject* pyimpulse; @@ -1477,9 +1533,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value) return NULL; } -PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) { PyObject* pyvect; int axis = 2; //z axis is the default @@ -1524,6 +1578,19 @@ PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value) return NULL; } +PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value) +{ + MT_Point3 pos; + if (PyVecTo(value, pos)) + { + NodeSetWorldPosition(pos); + NodeUpdateGS(0.f,true); + Py_RETURN_NONE; + } + + return NULL; +} + PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self) { KX_IPhysicsController* ctrl = GetPhysicsController(); @@ -1609,25 +1676,45 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, return returnValue; } -bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { - KX_GameObject* hitKXObj = client->m_gameobject; - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } - - if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) + // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit + // if not, all objects were tested and the front one may not be the correct one. + if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) { m_pHitObject = hitKXObj; return true; } + // return true to stop RayCast::RayTest from looping, the above test was decisive + // We would want to loop only if we want to get more than one hit point + return true; +} - return false; +/* this function is used to pre-filter the object before casting the ray on them. + This is useful for "X-Ray" option when we want to see "through" unwanted object. + */ +bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client) +{ + KX_GameObject* hitKXObj = client->m_gameobject; + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // Unknown type of object, skip it. + // Should not occur as the sensor objects are filtered in RayTest() + printf("Invalid client type %d found in ray casting\n", client->m_type); + return false; + } + + // if X-Ray option is selected, skip object that don't match the criteria as we see through them + // if not, test all objects because we don't know yet which one will be on front + if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) + { + return true; + } + // skip the object + return false; } KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, @@ -1667,8 +1754,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, toPoint = fromPoint + (dist) * toDir; } - MT_Point3 resultPoint; - MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); @@ -1682,7 +1767,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, m_testPropName = propName; else m_testPropName.SetLength(0); - KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback(this)); + KX_RayCast::Callback callback(this,spc); + KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) { @@ -1693,13 +1779,24 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, } KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, - "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n" -" prop = property name that object must have; can be omitted => detect any object\n" -" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" + "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n" + " If no hit, return (None,None,None) or (None,None,None,None).\n" +" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" " Can be None or omitted => start from self object center\n" -" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" -"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n") +" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" +" prop = property name that object must have; can be omitted => detect any object\n" +" face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n" +" xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n" +" poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n" +" which can be None if hit object has no mesh or if there is no hit\n" +" If 0 or omitted, return value is a 3-tuple\n" +"Note: The object on which you call this method matters: the ray will ignore it.\n" +" prop and xray option interact as follow:\n" +" prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n" +" prop off, xray on : idem\n" +" prop on, xray off: return closest hit if it matches prop, no hit otherwise\n" +" prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n") { MT_Point3 toPoint; MT_Point3 fromPoint; @@ -1708,8 +1805,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, float dist = 0.0f; char *propName = NULL; KX_GameObject *other; + int face=0, xray=0, poly=0; - if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) { + if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { return NULL; // Python sets a simple error } @@ -1755,8 +1853,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } - MT_Point3 resultPoint; - MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); @@ -1770,20 +1866,41 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, m_testPropName = propName; else m_testPropName.SetLength(0); - KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback(this)); + m_xray = xray; + // to get the hit results + KX_RayCast::Callback callback(this,spc,NULL,face); + KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); - if (m_pHitObject) + if (m_pHitObject) { - PyObject* returnValue = PyTuple_New(3); + PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3); if (returnValue) { // unlikely this would ever fail, if it does python sets an error PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); - PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); - PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal)); + if (poly) + { + if (callback.m_hitMesh) + { + // if this field is set, then we can trust that m_hitPolygon is a valid polygon + RAS_Polygon* poly = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); + KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, poly); + PyTuple_SET_ITEM(returnValue, 3, polyproxy); + } + else + { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(returnValue, 3, Py_None); + } + } } return returnValue; } - return Py_BuildValue("OOO", Py_None, Py_None, Py_None); - //Py_RETURN_NONE; + // no hit + if (poly) + return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None); + else + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } /* --------------------------------------------------------------------- diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index a7ac2d75a93..2da0be4df25 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -54,6 +54,7 @@ //Forward declarations. struct KX_ClientObjectInfo; +class KX_RayCast; class RAS_MeshObject; class KX_IPhysicsController; class PHY_IPhysicsEnvironment; @@ -74,20 +75,23 @@ protected: int m_layer; std::vector m_meshes; struct Object* m_pBlenderObject; + struct Object* m_pBlenderGroupObject; bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; - // Is this object set to be visible? Only useful for the - // visibility subsystem right now. - bool m_bVisible; + // visible = user setting + // culled = while rendering, depending on camera + bool m_bVisible; + bool m_bCulled; KX_IPhysicsController* m_pPhysicsController1; // used for ray casting PHY_IPhysicsEnvironment* m_pPhysicsEnvironment; STR_String m_testPropName; + bool m_xray; KX_GameObject* m_pHitObject; SG_Node* m_pSGNode; @@ -393,6 +397,16 @@ public: { m_pBlenderObject = obj; } + + struct Object* GetBlenderGroupObject( ) + { + return m_pBlenderGroupObject; + } + + void SetBlenderGroupObject( struct Object* obj) + { + m_pBlenderGroupObject = obj; + } bool IsDupliGroup() { @@ -428,7 +442,8 @@ public: return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent()); } - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client); /** @@ -535,18 +550,23 @@ public: /** * @section Mesh accessor functions. */ - + /** - * Run through the meshes associated with this - * object and bucketize them. See RAS_Mesh for - * more details on this function. Interesting to - * note that polygon bucketizing seems to happen on a per - * object basis. Which may explain why there is such - * a big performance gain when all static objects - * are joined into 1. + * Update buckets to indicate that there is a new + * user of this object's meshes. */ void - Bucketize( + AddMeshUser( + ); + + /** + * Update buckets with data about the mesh after + * creating or duplicating the object, changing + * visibility, object color, .. . + */ + void + UpdateBuckets( + bool recursive ); /** @@ -607,25 +627,8 @@ public: ResetDebugColor( ); - /** - * Set the visibility of the meshes associated with this - * object. - */ - void - MarkVisible( - bool visible - ); - - /** - * Set the visibility according to the visibility flag. - */ - void - MarkVisible( - void - ); - /** - * Was this object marked visible? (only for the ewxplicit + * Was this object marked visible? (only for the explicit * visibility system). */ bool @@ -638,7 +641,24 @@ public: */ void SetVisible( - bool b + bool b, + bool recursive + ); + + /** + * Was this object culled? + */ + bool + GetCulled( + void + ); + + /** + * Set culled flag of this object + */ + void + SetCulled( + bool c ); /** @@ -666,6 +686,14 @@ public: void ) { return m_bIsNegativeScaling; } + /** + * Is this a light? + */ + virtual bool + IsLight( + void + ) { return false; } + /** * @section Logic bubbling methods. */ @@ -726,31 +754,34 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); - KX_PYMETHOD(KX_GameObject,GetLinearVelocity); - KX_PYMETHOD(KX_GameObject,SetLinearVelocity); - KX_PYMETHOD(KX_GameObject,GetVelocity); + KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); + KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity); KX_PYMETHOD_NOARGS(KX_GameObject,GetMass); KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce); KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation); KX_PYMETHOD_O(KX_GameObject,SetOrientation); KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible); - KX_PYMETHOD_O(KX_GameObject,SetVisible); + KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible); KX_PYMETHOD_NOARGS(KX_GameObject,GetState); KX_PYMETHOD_O(KX_GameObject,SetState); - KX_PYMETHOD(KX_GameObject,AlignAxisToVect); + KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); - KX_PYMETHOD(KX_GameObject,ApplyImpulse); + KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse); KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin); KX_PYMETHOD_NOARGS(KX_GameObject,GetParent); KX_PYMETHOD_O(KX_GameObject,SetParent); KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive); - KX_PYMETHOD(KX_GameObject,GetMesh); + KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh); KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId); KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames); KX_PYMETHOD_NOARGS(KX_GameObject,EndObject); diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index d3aa924665e..6223643f75a 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -143,7 +143,7 @@ bool KX_IpoSGController::Update(double currentTime) { if (m_ipo_as_force == true) { - if (m_game_object && ob) + if (m_game_object && ob && m_game_object->GetPhysicsController()) { m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ? ob->GetWorldOrientation() * m_ipo_xform.GetPosition() : diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index f069048cd3d..3709fa8c784 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -32,6 +32,8 @@ #include "STR_String.h" #include "KX_Python.h" +struct Scene; + class KX_ISceneConverter { @@ -77,6 +79,8 @@ public: // use blender glsl materials virtual void SetGLSLMaterials(bool val) =0; virtual bool GetGLSLMaterials()=0; + + virtual struct Scene* GetBlenderSceneForName(const STR_String& name)=0; }; #endif //__KX_ISCENECONVERTER_H diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 1d6cc975ab5..888dcf3d01f 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -96,6 +96,7 @@ double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE; double KX_KetsjiEngine::m_anim_framerate = 25.0; double KX_KetsjiEngine::m_suspendedtime = 0.0; double KX_KetsjiEngine::m_suspendeddelta = 0.0; +double KX_KetsjiEngine::m_average_framerate = 0.0; /** @@ -134,6 +135,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_overrideCam(false), m_overrideCamUseOrtho(false), + m_overrideCamNear(0.0), + m_overrideCamFar(0.0), m_stereo(false), m_curreye(0), @@ -275,30 +278,73 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) } +void KX_KetsjiEngine::ClearFrame() +{ + // clear unless we're drawing overlapping stereo + if(m_rasterizer->InterlacedStereo() && + m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE) + return; + + // clear the viewports with the background color of the first scene + bool doclear = false; + KX_SceneList::iterator sceneit; + RAS_Rect clearvp, area, viewport; + + for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++) + { + KX_Scene* scene = *sceneit; + //const RAS_FrameSettings &framesettings = scene->GetFramingType(); + list* cameras = scene->GetCameras(); + + list::iterator it; + for(it = cameras->begin(); it != cameras->end(); it++) + { + SetupViewport(scene, (*it), area, viewport); + + if(!doclear) { + clearvp = viewport; + doclear = true; + } + else { + if(viewport.GetLeft() < clearvp.GetLeft()) + clearvp.SetLeft(viewport.GetLeft()); + if(viewport.GetBottom() < clearvp.GetBottom()) + clearvp.SetBottom(viewport.GetBottom()); + if(viewport.GetRight() > clearvp.GetRight()) + clearvp.SetRight(viewport.GetRight()); + if(viewport.GetTop() > clearvp.GetTop()) + clearvp.SetTop(viewport.GetTop()); + + } + } + } + + if(doclear) { + KX_Scene* firstscene = *m_scenes.begin(); + SetBackGround(firstscene->GetWorldInfo()); + + m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), + clearvp.GetRight(), clearvp.GetTop()); + m_rasterizer->ClearColorBuffer(); + } +} + bool KX_KetsjiEngine::BeginFrame() { - bool result = false; - - RAS_Rect vp; - KX_Scene* firstscene = *m_scenes.begin(); - const RAS_FrameSettings &framesettings = firstscene->GetFramingType(); - - // set the area used for rendering + // set the area used for rendering (stereo can assign only a subset) m_rasterizer->SetRenderArea(); - RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp); - if (m_canvas->BeginDraw()) { - result = true; + ClearFrame(); - m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop()); - SetBackGround( firstscene->GetWorldInfo() ); - m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds()); - m_rendertools->BeginFrame( m_rasterizer); + m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds()); + m_rendertools->BeginFrame(m_rasterizer); + + return true; } - return result; + return false; } @@ -310,6 +356,12 @@ void KX_KetsjiEngine::EndFrame() { RenderDebugProperties(); } + + m_average_framerate = m_logger->GetAverage(); + if (m_average_framerate < 1e-6) + m_average_framerate = 1e-6; + m_average_framerate = 1.0/m_average_framerate; + // Go to next profiling measurement, time spend after this call is shown in the next frame. m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds()); @@ -321,8 +373,6 @@ void KX_KetsjiEngine::EndFrame() m_canvas->EndDraw(); - - } //#include "PIL_time.h" @@ -601,7 +651,7 @@ void KX_KetsjiEngine::Render() ); } // clear the -whole- viewport - m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); } m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); @@ -630,9 +680,6 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - SetupRenderFrame(scene, cam); - // do the rendering RenderFrame(scene, cam); } @@ -650,9 +697,6 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - SetupRenderFrame(scene, (*it)); - // do the rendering RenderFrame(scene, (*it)); } @@ -685,10 +729,6 @@ void KX_KetsjiEngine::Render() //pass the scene, for picking and raycasting (shadows) m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - //SetupRenderFrame(scene); - SetupRenderFrame(scene, cam); - // do the rendering //RenderFrame(scene); RenderFrame(scene, cam); @@ -848,8 +888,13 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat) m_overrideCamViewMat = mat; } - -void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) +void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far) +{ + m_overrideCamNear = near; + m_overrideCamFar = far; +} + +void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) { // In this function we make sure the rasterizer settings are upto // date. We compute the viewport so that logic @@ -857,17 +902,26 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) // Note we postpone computation of the projection matrix // so that we are using the latest camera position. - - RAS_Rect viewport; - - if (!cam) - return; - if (cam->GetViewport()) { - viewport.SetLeft(cam->GetViewportLeft()); - viewport.SetBottom(cam->GetViewportBottom()); - viewport.SetRight(cam->GetViewportRight()); - viewport.SetTop(cam->GetViewportTop()); + RAS_Rect userviewport; + + userviewport.SetLeft(cam->GetViewportLeft()); + userviewport.SetBottom(cam->GetViewportBottom()); + userviewport.SetRight(cam->GetViewportRight()); + userviewport.SetTop(cam->GetViewportTop()); + + // Don't do bars on user specified viewport + RAS_FrameSettings settings = scene->GetFramingType(); + if(settings.FrameType() == RAS_FrameSettings::e_frame_bars) + settings.SetFrameType(RAS_FrameSettings::e_frame_extend); + + RAS_FramingManager::ComputeViewport( + scene->GetFramingType(), + userviewport, + viewport + ); + + area = userviewport; } else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { RAS_FramingManager::ComputeViewport( @@ -875,33 +929,32 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) m_canvas->GetDisplayArea(), viewport ); + + area = m_canvas->GetDisplayArea(); } else { viewport.SetLeft(0); viewport.SetBottom(0); viewport.SetRight(int(m_canvas->GetWidth())); viewport.SetTop(int(m_canvas->GetHeight())); + + area = m_canvas->GetDisplayArea(); } - // store the computed viewport in the scene - - scene->SetSceneViewport(viewport); - - // set the viewport for this frame and scene - m_canvas->SetViewPort( - viewport.GetLeft(), - viewport.GetBottom(), - viewport.GetRight(), - viewport.GetTop() - ); - } void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) { - CListValue *lightlist = scene->GetLightList(); + CListValue *objectlist = scene->GetObjectList(); int i, drawmode; - for(i=0; iGetCount(); i++) { - KX_LightObject *light = (KX_LightObject*)lightlist->GetValue(i); + m_rendertools->SetAuxilaryClientInfo(scene); + + for(i=0; iGetCount(); i++) { + KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i); + + if(!gameobj->IsLight()) + continue; + + KX_LightObject *light = (KX_LightObject*)gameobj; light->Update(); @@ -939,18 +992,32 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { + bool override_camera; + RAS_Rect viewport, area; float left, right, bottom, top, nearfrust, farfrust, focallength; const float ortho = 100.0; // KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; + + SetupViewport(scene, cam, area, viewport); + + // store the computed viewport in the scene + scene->SetSceneViewport(viewport); + + // set the viewport for this frame and scene + m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(), + viewport.GetRight(), viewport.GetTop()); // see KX_BlenderMaterial::Activate //m_rasterizer->SetAmbient(); m_rasterizer->DisplayFog(); - if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) { + override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName); + override_camera = override_camera && (cam->GetName() == "__default__cam__"); + + if (override_camera && m_overrideCamUseOrtho) { MT_CmMatrix4x4 projmat = m_overrideCamProjMat; m_rasterizer->SetProjectionMatrix(projmat); } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) @@ -960,12 +1027,17 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { RAS_FrameFrustum frustum; float lens = cam->GetLens(); + bool orthographic = !cam->GetCameraData()->m_perspective; nearfrust = cam->GetCameraNear(); farfrust = cam->GetCameraFar(); focallength = cam->GetFocalLength(); - if (!cam->GetCameraData()->m_perspective) - { + if(override_camera) { + nearfrust = m_overrideCamNear; + farfrust = m_overrideCamFar; + } + + if (orthographic) { lens *= ortho; nearfrust = (nearfrust + 1.0)*ortho; farfrust *= ortho; @@ -973,8 +1045,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) RAS_FramingManager::ComputeFrustum( scene->GetFramingType(), - m_canvas->GetDisplayArea(), - scene->GetSceneViewport(), + area, + viewport, lens, nearfrust, farfrust, @@ -990,7 +1062,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( left, right, bottom, top, nearfrust, farfrust, focallength); - + cam->SetProjectionMatrix(projmat); // Otherwise the projection matrix for each eye will be the same... @@ -1281,12 +1353,13 @@ void KX_KetsjiEngine::RemoveScheduledScenes() KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename) { - + Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename); KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice, m_mousedevice, m_networkdevice, m_audiodevice, - scenename); + scenename, + scene); m_sceneconverter->ConvertScene(scenename, tmpscene, @@ -1442,6 +1515,11 @@ void KX_KetsjiEngine::SetAnimFrameRate(double framerate) m_anim_framerate = framerate; } +double KX_KetsjiEngine::GetAverageFrameRate() +{ + return m_average_framerate; +} + void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties) { m_show_framerate = frameRate; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 77b69ec2d9e..8fe8731dc05 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -124,6 +124,8 @@ private: bool m_overrideCamUseOrtho; MT_CmMatrix4x4 m_overrideCamProjMat; MT_CmMatrix4x4 m_overrideCamViewMat; + float m_overrideCamNear; + float m_overrideCamFar; bool m_stereo; int m_curreye; @@ -149,6 +151,8 @@ private: /** Labels for profiling display. */ static const char m_profileLabels[tc_numCategories][15]; + /** Last estimated framerate */ + static double m_average_framerate; /** Show the framerate on the game display? */ bool m_show_framerate; /** Show profiling info on the game display? */ @@ -175,7 +179,7 @@ private: /** Blue component of framing bar color. */ float m_overrideFrameColorB; - void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); + void SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); void RenderFrame(KX_Scene* scene, KX_Camera* cam); void PostRenderFrame(); void RenderDebugProperties(); @@ -234,6 +238,7 @@ public: void SetCameraOverrideUseOrtho(bool useOrtho); void SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat); void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat); + void SetCameraOverrideClipping(float near, float far); /** * Sets display of all frames. @@ -271,6 +276,11 @@ public: */ static void SetAnimFrameRate(double framerate); + /** + * Gets the last estimated average framerate + */ + static double GetAverageFrameRate(); + /** * Activates or deactivates timing information display. * @param frameRate Display for frame rate on or off. @@ -348,6 +358,7 @@ protected: KX_Scene* CreateScene(const STR_String& scenename); bool BeginFrame(); + void ClearFrame(); void EndFrame(); }; diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 4e3d6180d22..e0f171e78e0 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -42,14 +42,13 @@ #include "KX_PyMath.h" -#ifdef BLENDER_GLSL +#include "DNA_object_types.h" #include "GPU_material.h" -#endif KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, const RAS_LightObject& lightobj, - struct GPULamp *gpulamp, + bool glsl, PyTypeObject* T ) : @@ -59,12 +58,20 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, m_lightobj = lightobj; m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr(); m_rendertools->AddLight(&m_lightobj); - m_gpulamp = gpulamp; + m_glsl = glsl; + m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene(); }; KX_LightObject::~KX_LightObject() { + GPULamp *lamp; + + if((lamp = GetGPULamp())) { + float obmat[4][4] = {{0}}; + GPU_lamp_update(lamp, 0, obmat); + } + m_rendertools->RemoveLight(&m_lightobj); } @@ -73,7 +80,7 @@ CValue* KX_LightObject::GetReplica() { KX_LightObject* replica = new KX_LightObject(*this); - + // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -81,13 +88,23 @@ CValue* KX_LightObject::GetReplica() replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr(); m_rendertools->AddLight(&replica->m_lightobj); + return replica; } +GPULamp *KX_LightObject::GetGPULamp() +{ + if(m_glsl) + return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject()); + else + return false; +} + void KX_LightObject::Update() { -#ifdef BLENDER_GLSL - if(m_gpulamp) { + GPULamp *lamp; + + if((lamp = GetGPULamp())) { float obmat[4][4]; double *dobmat = GetOpenGLMatrixPtr()->getPointer(); @@ -95,38 +112,39 @@ void KX_LightObject::Update() for(int j=0; j<4; j++, dobmat++) obmat[i][j] = (float)*dobmat; - GPU_lamp_update(m_gpulamp, obmat); + GPU_lamp_update(lamp, m_lightobj.m_layer, obmat); } -#endif } bool KX_LightObject::HasShadowBuffer() { -#ifdef BLENDER_GLSL - return (m_gpulamp && GPU_lamp_has_shadow_buffer(m_gpulamp)); -#else - return false; -#endif + GPULamp *lamp; + + if((lamp = GetGPULamp())) + return GPU_lamp_has_shadow_buffer(lamp); + else + return false; } int KX_LightObject::GetShadowLayer() { -#ifdef BLENDER_GLSL - if(m_gpulamp) - return GPU_lamp_shadow_layer(m_gpulamp); + GPULamp *lamp; + + if((lamp = GetGPULamp())) + return GPU_lamp_shadow_layer(lamp); else -#endif return 0; } void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans) { -#ifdef BLENDER_GLSL + GPULamp *lamp; float viewmat[4][4], winmat[4][4]; int winsize; /* bind framebuffer */ - GPU_lamp_shadow_buffer_bind(m_gpulamp, viewmat, &winsize, winmat); + lamp = GetGPULamp(); + GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat); /* setup camera transformation */ MT_Matrix4x4 modelviewmat((float*)viewmat); @@ -146,14 +164,12 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T ras->SetProjectionMatrix(projectionmat); ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(), cam->GetCameraLocation(), cam->GetCameraOrientation()); -#endif } void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) { -#ifdef BLENDER_GLSL - GPU_lamp_shadow_buffer_unbind(m_gpulamp); -#endif + GPULamp *lamp = GetGPULamp(); + GPU_lamp_shadow_buffer_unbind(lamp); } PyObject* KX_LightObject::_getattr(const STR_String& attr) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 62eb26c61a8..e5dbf0b7f4a 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -33,6 +33,7 @@ #include "KX_GameObject.h" struct GPULamp; +struct Scene; class KX_Camera; class RAS_IRasterizer; class RAS_IRenderTools; @@ -44,16 +45,18 @@ class KX_LightObject : public KX_GameObject protected: RAS_LightObject m_lightobj; class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj - struct GPULamp *m_gpulamp; - static char doc[]; + bool m_glsl; + Scene* m_blenderscene; + static char doc[]; public: - KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, struct GPULamp *gpulamp, PyTypeObject *T = &Type); + KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} /* GLSL shadow */ + struct GPULamp *GetGPULamp(); bool HasShadowBuffer(); int GetShadowLayer(); void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); @@ -62,6 +65,8 @@ public: virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + + virtual bool IsLight(void) { return true; } }; #endif //__KX_LIGHT diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index a0ac9cfd4ff..5cc102248f2 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -35,6 +35,7 @@ #include "RAS_MeshObject.h" #include "KX_VertexProxy.h" +#include "KX_PolyProxy.h" #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" @@ -42,6 +43,8 @@ #include "KX_PyMath.h" #include "KX_ConvertPhysicsObject.h" +#include "PyObjectPlus.h" + PyTypeObject KX_MeshProxy::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -71,10 +74,12 @@ PyParentObject KX_MeshProxy::Parents[] = { PyMethodDef KX_MeshProxy::Methods[] = { {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS}, +{"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS}, {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, +{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh), //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, @@ -93,10 +98,11 @@ KX_MeshProxy::_getattr(const STR_String& attr) if (attr == "materials") { PyObject *materials = PyList_New(0); - RAS_MaterialBucket::Set::iterator mit = m_meshobj->GetFirstMaterial(); + list::iterator mit = m_meshobj->GetFirstMaterial(); for(; mit != m_meshobj->GetLastMaterial(); ++mit) { - RAS_IPolyMaterial *polymat = (*mit)->GetPolyMaterial(); + RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); + if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *mat = static_cast(polymat); @@ -146,6 +152,12 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self, return PyInt_FromLong(num); } +PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self) +{ + int num = m_meshobj->NumPolygons(); + return PyInt_FromLong(num); +} + PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, PyObject* args, PyObject* kwds) @@ -195,11 +207,11 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self, if (PyArg_ParseTuple(args,"i",&matid)) { - RAS_IPolyMaterial* mat = m_meshobj->GetMaterialBucket(matid)->GetPolyMaterial(); + RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); + RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial(); + if (mat) - { - length = m_meshobj->GetVertexArrayLength(mat); - } + length = m_meshobj->NumVertices(mat); } else { return NULL; @@ -234,6 +246,28 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, } +PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + int polyindex= 1; + PyObject* polyob = NULL; + + if (!PyArg_ParseTuple(args,"i",&polyindex)) + return NULL; + + RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex); + if (polygon) + { + polyob = new KX_PolyProxy(m_meshobj, polygon); + } + else + { + PyErr_SetString(PyExc_AttributeError, "Invalid polygon index"); + } + return polyob; +} + KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh, "Reinstance the physics mesh.") { diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 7c6202c15a4..3335c349673 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -57,10 +57,12 @@ public: KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); KX_PYMETHOD(KX_MeshProxy,GetMaterialName); KX_PYMETHOD(KX_MeshProxy,GetTextureName); + KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons); // both take materialid (int) KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); + KX_PYMETHOD(KX_MeshProxy,GetPolygon); KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh); }; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index db0bef8b7e1..3156f543ed5 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -122,16 +122,10 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event) return result; } -bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* result, void * const data) { KX_GameObject* hitKXObj = client_info->m_gameobject; - if (client_info->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } - /* Is this me? In the ray test, there are a lot of extra checks * for aliasing artefacts from self-hits. That doesn't happen * here, so a simple test suffices. Or does the camera also get @@ -142,8 +136,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hi if ((m_focusmode == 2) || hitKXObj == thisObj) { m_hitObject = hitKXObj; - m_hitPosition = hit_point; - m_hitNormal = hit_normal; + m_hitPosition = result->m_hitPoint; + m_hitNormal = result->m_hitNormal; return true; } @@ -158,8 +152,6 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) m_hitObject = 0; m_hitPosition = MT_Vector3(0,0,0); m_hitNormal = MT_Vector3(1,0,0); - MT_Point3 resultpoint; - MT_Vector3 resultnormal; /* All screen handling in the gameengine is done by GL, * specifically the model/view and projection parts. The viewport @@ -280,7 +272,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) bool result = false; - result = KX_RayCast::RayTest(physics_controller, physics_environment, frompoint3, topoint3, resultpoint, resultnormal, KX_RayCast::Callback(this)); + KX_RayCast::Callback callback(this,physics_controller); + KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback); result = (m_hitObject!=0); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index b011ebe1288..a6cc39d66eb 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -33,6 +33,8 @@ #include "SCA_MouseSensor.h" +class KX_RayCast; + /** * The mouse focus sensor extends the basic SCA_MouseSensor. It has * been placed in KX because it needs access to the rasterizer and @@ -76,7 +78,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor return result; }; - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } + /* --------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 344e0fccc35..3ca121f63f8 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -36,6 +36,8 @@ #include "KX_GameObject.h" #include "KX_PythonInit.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index 9291199d859..da4f05ced7c 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -27,6 +27,8 @@ * ***** END GPL LICENSE BLOCK ***** */ #include +#include "PyObjectPlus.h" + #include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 144f74a1a4c..c9180bf3a80 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -35,10 +35,6 @@ #include "BKE_global.h" #include "BKE_image.h" -extern "C" { -#include "BDR_drawmesh.h" -} - #include "DNA_material_types.h" #include "DNA_texture_types.h" #include "DNA_image_types.h" @@ -46,6 +42,8 @@ extern "C" { #include "IMB_imbuf_types.h" +#include "GPU_draw.h" + #include "MEM_guardedalloc.h" #include "RAS_LightObject.h" @@ -63,8 +61,6 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, bool alpha, bool zsort, int lightlayer, - bool bIsTriangle, - void* clientobject, struct MTFace* tface, unsigned int* mcol, PyTypeObject *T) @@ -78,9 +74,7 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, transp, alpha, zsort, - lightlayer, - bIsTriangle, - clientobject), + lightlayer), m_tface(tface), m_mcol(mcol), m_material(material), @@ -140,38 +134,29 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - { - set_tpage(NULL); - } + GPU_set_tpage(NULL); + cachingInfo = GetCachingInfo(); if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)) { - update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime()); - set_tpage(m_tface); - rasty->EnableTextures(true); + Image *ima = (Image*)m_tface->tpage; + GPU_update_image_time(ima, rasty->GetTime()); + GPU_set_tpage(m_tface); } else - { - set_tpage(NULL); - rasty->EnableTextures(false); - } + GPU_set_tpage(NULL); if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) - { rasty->SetCullFace(false); - } else - { rasty->SetCullFace(true); - } - if (m_drawingmode & RAS_IRasterizer::KX_LINES) { + if ((m_drawingmode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) rasty->SetLines(true); - } - else { + else rasty->SetLines(false); - } } rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity); @@ -253,7 +238,8 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) if (attr == "lightlayer") return PyInt_FromLong(m_lightlayer); if (attr == "triangle") - return PyInt_FromLong(m_bIsTriangle); + // deprecated, triangle/quads shouldn't have been a material property + return 0; if (attr == "diffuse") return PyObjectFrom(m_diffuse); @@ -333,7 +319,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) // This probably won't work... if (attr == "triangle") { - m_bIsTriangle = value; + // deprecated, triangle/quads shouldn't have been a material property return 0; } } @@ -386,7 +372,9 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty); - update_realtime_texture(tface, rasty->GetTime()); + Image *ima = (Image*)tface->tpage; + GPU_update_image_time(ima, rasty->GetTime()); + Py_Return; } @@ -399,7 +387,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") if (PyArg_ParseTuple(args, "O!", &PyCObject_Type, &pytface)) { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); - set_tpage(tface); + GPU_set_tpage(tface); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 11c8baa8b1f..fe116f757db 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -68,8 +68,6 @@ public: bool alpha, bool zsort, int lightlayer, - bool bIsTriangle, - void* clientobject, struct MTFace* tface, unsigned int* mcol, PyTypeObject *T = &Type); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 26243c7dba1..ac63e3fade5 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -34,6 +34,8 @@ #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 5d2126ca37a..5308a0b9536 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -57,21 +57,25 @@ #include "BL_ActionActuator.h" #include "RAS_IRasterizer.h" #include "RAS_ICanvas.h" +#include "RAS_BucketManager.h" #include "MT_Vector3.h" #include "MT_Point3.h" #include "ListValue.h" #include "KX_Scene.h" #include "SND_DeviceManager.h" -#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" #include "BL_Shader.h" #include "KX_PyMath.h" +#include "PyObjectPlus.h" + extern "C" { #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. } +#include "marshal.h" /* python header for loading/saving dicts */ + #include "PHY_IPhysicsEnvironment.h" // FIXME: Enable for access to blender python modules. This is disabled because // python has dependencies on a lot of other modules and is a pain to link. @@ -83,6 +87,7 @@ extern "C" { #include "BKE_utildefines.h" #include "BKE_global.h" #include "BLI_blenlib.h" +#include "GPU_material.h" static void setSandbox(TPythonSecurityLevel level); @@ -90,6 +95,7 @@ static void setSandbox(TPythonSecurityLevel level); // 'local' copy of canvas ptr, for window height/width python scripts static RAS_ICanvas* gp_Canvas = NULL; static KX_Scene* gp_KetsjiScene = NULL; +static KX_KetsjiEngine* gp_KetsjiEngine = NULL; static RAS_IRasterizer* gp_Rasterizer = NULL; void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) @@ -121,15 +127,13 @@ static PyObject* gPyGetRandomFloat(PyObject*) static PyObject* gPySetGravity(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_KetsjiScene) - gp_KetsjiScene->SetGravity(vec); - - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; + + if (gp_KetsjiScene) + gp_KetsjiScene->SetGravity(vec); - return NULL; + Py_RETURN_NONE; } static char gPyExpandPath_doc[] = @@ -147,13 +151,12 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) char expanded[FILE_MAXDIR + FILE_MAXFILE]; char* filename; - if (PyArg_ParseTuple(args,"s",&filename)) - { - BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); - BLI_convertstringcode(expanded, G.sce); - return PyString_FromString(expanded); - } - return NULL; + if (!PyArg_ParseTuple(args,"s",&filename)) + return NULL; + + BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); + BLI_convertstringcode(expanded, G.sce); + return PyString_FromString(expanded); } @@ -181,6 +184,12 @@ static PyObject* gPyGetSpectrum(PyObject*) PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index])); } } + else { + for (int index = 0; index < 512; index++) + { + PyList_SetItem(resultlist, index, PyFloat_FromDouble(0.0)); + } + } return resultlist; } @@ -191,16 +200,17 @@ static PyObject* gPyStartDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); - if (audiodevice) - { - if (!usedsp) - { - audiodevice->StartUsingDSP(); - usedsp = true; - Py_Return; - } + if (!audiodevice) { + PyErr_SetString(PyExc_RuntimeError, "no audio device available"); + return NULL; } - return NULL; + + if (!usedsp) { + audiodevice->StartUsingDSP(); + usedsp = true; + } + + Py_RETURN_NONE; } @@ -209,28 +219,27 @@ static PyObject* gPyStopDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); - if (audiodevice) - { - if (usedsp) - { - audiodevice->StopUsingDSP(); - usedsp = false; - Py_Return; - } + if (!audiodevice) { + PyErr_SetString(PyExc_RuntimeError, "no audio device available"); + return NULL; } - return NULL; + + if (usedsp) { + audiodevice->StopUsingDSP(); + usedsp = true; + } + + Py_RETURN_NONE; } static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) { float ticrate; - if (PyArg_ParseTuple(args, "f", &ticrate)) - { - KX_KetsjiEngine::SetTicRate(ticrate); - Py_Return; - } + if (!PyArg_ParseTuple(args, "f", &ticrate)) + return NULL; - return NULL; + KX_KetsjiEngine::SetTicRate(ticrate); + Py_RETURN_NONE; } static PyObject* gPyGetLogicTicRate(PyObject*) @@ -241,26 +250,21 @@ static PyObject* gPyGetLogicTicRate(PyObject*) static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; - if (PyArg_ParseTuple(args, "f", &ticrate)) - { - - PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); - Py_Return; - } + if (!PyArg_ParseTuple(args, "f", &ticrate)) + return NULL; - return NULL; + PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); + Py_RETURN_NONE; } static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) { int debugMode; - if (PyArg_ParseTuple(args, "i", &debugMode)) - { - PHY_GetActiveEnvironment()->setDebugMode(debugMode); - Py_Return; - } + if (!PyArg_ParseTuple(args, "i", &debugMode)) + return NULL; - return NULL; + PHY_GetActiveEnvironment()->setDebugMode(debugMode); + Py_RETURN_NONE; } @@ -270,11 +274,16 @@ static PyObject* gPyGetPhysicsTicRate(PyObject*) return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep()); } +static PyObject* gPyGetAverageFrameRate(PyObject*) +{ + return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate()); +} + static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) { char cpath[sizeof(G.sce)]; char *searchpath = NULL; - PyObject* list; + PyObject* list, *value; DIR *dp; struct dirent *dirp; @@ -294,13 +303,15 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) if((dp = opendir(cpath)) == NULL) { /* todo, show the errno, this shouldnt happen anyway if the blendfile is readable */ - fprintf(stderr, "Could not read directoty () failed, code %d (%s)\n", cpath, errno, strerror(errno)); + fprintf(stderr, "Could not read directoty (%s) failed, code %d (%s)\n", cpath, errno, strerror(errno)); return list; } while ((dirp = readdir(dp)) != NULL) { if (BLI_testextensie(dirp->d_name, ".blend")) { - PyList_Append(list, PyString_FromString(dirp->d_name)); + value = PyString_FromString(dirp->d_name); + PyList_Append(list, value); + Py_DECREF(value); } } @@ -407,6 +418,7 @@ static struct PyMethodDef game_methods[] = { {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, "Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, "Gets the physics tic rate"}, {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, "Sets the physics tic rate"}, + {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, "Gets the estimated average frame rate"}, {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, "Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, "Prints GL Extension Info"}, {NULL, (PyCFunction) NULL, 0, NULL } @@ -415,22 +427,14 @@ static struct PyMethodDef game_methods[] = { static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { - int height = (gp_Canvas ? gp_Canvas->GetHeight() : 0); - - PyObject* heightval = PyInt_FromLong(height); - return heightval; + return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) { - - - int width = (gp_Canvas ? gp_Canvas->GetWidth() : 0); - - PyObject* widthval = PyInt_FromLong(width); - return widthval; + return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -441,15 +445,11 @@ bool gUseVisibilityTemp = false; static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) { int visible; - if (PyArg_ParseTuple(args,"i",&visible)) - { - gUseVisibilityTemp = (visible != 0); - } - else - { + if (!PyArg_ParseTuple(args,"i",&visible)) return NULL; - } - Py_Return; + + gUseVisibilityTemp = (visible != 0); + Py_RETURN_NONE; } @@ -457,23 +457,20 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) static PyObject* gPyShowMouse(PyObject*, PyObject* args) { int visible; - if (PyArg_ParseTuple(args,"i",&visible)) - { - if (visible) - { - if (gp_Canvas) - gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); - } else - { - if (gp_Canvas) - gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); - } - } - else { + if (!PyArg_ParseTuple(args,"i",&visible)) return NULL; + + if (visible) + { + if (gp_Canvas) + gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); + } else + { + if (gp_Canvas) + gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); } - Py_Return; + Py_RETURN_NONE; } @@ -481,74 +478,81 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args) static PyObject* gPySetMousePosition(PyObject*, PyObject* args) { int x,y; - if (PyArg_ParseTuple(args,"ii",&x,&y)) - { - if (gp_Canvas) - gp_Canvas->SetMousePosition(x,y); - } - else { + if (!PyArg_ParseTuple(args,"ii",&x,&y)) return NULL; - } - Py_Return; + if (gp_Canvas) + gp_Canvas->SetMousePosition(x,y); + + Py_RETURN_NONE; } static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) { float sep; - if (PyArg_ParseTuple(args, "f", &sep)) - { - if (gp_Rasterizer) - gp_Rasterizer->SetEyeSeparation(sep); - - Py_Return; + if (!PyArg_ParseTuple(args, "f", &sep)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; } - return NULL; + gp_Rasterizer->SetEyeSeparation(sep); + + Py_RETURN_NONE; } static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*) { - if (gp_Rasterizer) - return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } - return NULL; + return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); } static PyObject* gPySetFocalLength(PyObject*, PyObject* args) { float focus; - if (PyArg_ParseTuple(args, "f", &focus)) - { - if (gp_Rasterizer) - gp_Rasterizer->SetFocalLength(focus); - Py_Return; - } + if (!PyArg_ParseTuple(args, "f", &focus)) + return NULL; - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + + gp_Rasterizer->SetFocalLength(focus); + + Py_RETURN_NONE; } static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) { - if (gp_Rasterizer) - return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength()); - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + + return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength()); + + Py_RETURN_NONE; } static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) { MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_Canvas) - { - gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]); - } - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; - return NULL; + if (gp_Canvas) + { + gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]); + } + Py_RETURN_NONE; } @@ -557,16 +561,16 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); - } - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); + + Py_RETURN_NONE; } @@ -575,17 +579,17 @@ static PyObject* gPySetMistStart(PyObject*, PyObject* args) { float miststart; - if (PyArg_ParseTuple(args,"f",&miststart)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetFogStart(miststart); - } - } - else { + if (!PyArg_ParseTuple(args,"f",&miststart)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); return NULL; } - Py_Return; + + gp_Rasterizer->SetFogStart(miststart); + + Py_RETURN_NONE; } @@ -594,17 +598,17 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) { float mistend; - if (PyArg_ParseTuple(args,"f",&mistend)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetFogEnd(mistend); - } - } - else { + if (!PyArg_ParseTuple(args,"f",&mistend)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); return NULL; } - Py_Return; + + gp_Rasterizer->SetFogEnd(mistend); + + Py_RETURN_NONE; } @@ -612,16 +616,16 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); - } - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); + + Py_RETURN_NONE; } @@ -630,42 +634,167 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) { char* filename; - if (PyArg_ParseTuple(args,"s",&filename)) - { - if (gp_Canvas) - { - gp_Canvas->MakeScreenShot(filename); - } - } - else { + if (!PyArg_ParseTuple(args,"s",&filename)) return NULL; + + if (gp_Canvas) + { + gp_Canvas->MakeScreenShot(filename); } - Py_Return; + + Py_RETURN_NONE; } static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) { float motionblurvalue; - if (PyArg_ParseTuple(args,"f",&motionblurvalue)) - { - if(gp_Rasterizer) - { - gp_Rasterizer->EnableMotionBlur(motionblurvalue); - } - } - else { + if (!PyArg_ParseTuple(args,"f",&motionblurvalue)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); return NULL; } - Py_Return; + + gp_Rasterizer->EnableMotionBlur(motionblurvalue); + + Py_RETURN_NONE; } static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args) { - if(gp_Rasterizer) - { - gp_Rasterizer->DisableMotionBlur(); + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; } - Py_Return; + + gp_Rasterizer->DisableMotionBlur(); + + Py_RETURN_NONE; +} + +int getGLSLSettingFlag(char *setting) +{ + if(strcmp(setting, "lights") == 0) + return G_FILE_GLSL_NO_LIGHTS; + else if(strcmp(setting, "shaders") == 0) + return G_FILE_GLSL_NO_SHADERS; + else if(strcmp(setting, "shadows") == 0) + return G_FILE_GLSL_NO_SHADOWS; + else if(strcmp(setting, "ramps") == 0) + return G_FILE_GLSL_NO_RAMPS; + else if(strcmp(setting, "nodes") == 0) + return G_FILE_GLSL_NO_NODES; + else if(strcmp(setting, "extra_textures") == 0) + return G_FILE_GLSL_NO_EXTRA_TEX; + else + return -1; +} + +static PyObject* gPySetGLSLMaterialSetting(PyObject*, + PyObject* args, + PyObject*) +{ + char *setting; + int enable, flag, fileflags; + + if (!PyArg_ParseTuple(args,"si",&setting,&enable)) + return NULL; + + flag = getGLSLSettingFlag(setting); + + if (flag==-1) { + PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); + return NULL; + } + + fileflags = G.fileflags; + + if (enable) + G.fileflags &= ~flag; + else + G.fileflags |= flag; + + /* display lists and GLSL materials need to be remade */ + if(G.fileflags != fileflags) { + if(gp_KetsjiEngine) { + KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); + KX_SceneList::iterator it; + + for(it=scenes->begin(); it!=scenes->end(); it++) + if((*it)->GetBucketManager()) + (*it)->GetBucketManager()->ReleaseDisplayLists(); + } + + GPU_materials_free(); + } + + Py_RETURN_NONE; +} + +static PyObject* gPyGetGLSLMaterialSetting(PyObject*, + PyObject* args, + PyObject*) +{ + char *setting; + int enabled = 0, flag; + + if (!PyArg_ParseTuple(args,"s",&setting)) + return NULL; + + flag = getGLSLSettingFlag(setting); + + if (flag==-1) { + PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); + return NULL; + } + + enabled = ((G.fileflags & flag) != 0); + return PyInt_FromLong(enabled); +} + +#define KX_TEXFACE_MATERIAL 0 +#define KX_BLENDER_MULTITEX_MATERIAL 1 +#define KX_BLENDER_GLSL_MATERIAL 2 + +static PyObject* gPySetMaterialType(PyObject*, + PyObject* args, + PyObject*) +{ + int flag, type; + + if (!PyArg_ParseTuple(args,"i",&type)) + return NULL; + + if(type == KX_BLENDER_GLSL_MATERIAL) + flag = G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL; + else if(type == KX_BLENDER_MULTITEX_MATERIAL) + flag = G_FILE_GAME_MAT; + else if(type == KX_TEXFACE_MATERIAL) + flag = 0; + else { + PyErr_SetString(PyExc_ValueError, "material type is not known"); + return NULL; + } + + G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + G.fileflags |= flag; + + Py_RETURN_NONE; +} + +static PyObject* gPyGetMaterialType(PyObject*) +{ + int flag; + + if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL)) + flag = KX_BLENDER_GLSL_MATERIAL; + else if(G.fileflags & G_FILE_GAME_MAT) + flag = KX_BLENDER_MULTITEX_MATERIAL; + else + flag = KX_TEXFACE_MATERIAL; + + return PyInt_FromLong(flag); } STR_String gPyGetWindowHeight__doc__="getWindowHeight doc"; @@ -701,11 +830,17 @@ static struct PyMethodDef rasterizer_methods[] = { {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"}, {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, + {"setMaterialMode",(PyCFunction) gPySetMaterialType, + METH_VARARGS, "set the material mode to use for OpenGL rendering"}, + {"getMaterialMode",(PyCFunction) gPyGetMaterialType, + METH_NOARGS, "get the material mode being used for OpenGL rendering"}, + {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting, + METH_VARARGS, "set the state of a GLSL material setting"}, + {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, + METH_VARARGS, "get the state of a GLSL material setting"}, { NULL, (PyCFunction) NULL, 0, NULL } }; - - // Initialization function for the module (*must* be called initGameLogic) static char GameLogic_module_documentation[] = @@ -718,11 +853,12 @@ static char Rasterizer_module_documentation[] = -PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook +PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook { PyObject* m; PyObject* d; + gp_KetsjiEngine = engine; gp_KetsjiScene = scene; gUseVisibilityTemp=false; @@ -852,13 +988,30 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook // override builtin functions import() and open() -PyObject *KXpy_open(PyObject *self, PyObject *args) -{ +PyObject *KXpy_open(PyObject *self, PyObject *args) { PyErr_SetString(PyExc_RuntimeError, "Sandbox: open() function disabled!\nGame Scripts should not use this function."); return NULL; } +PyObject *KXpy_reload(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function."); + return NULL; +} +PyObject *KXpy_file(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function."); + return NULL; +} + +PyObject *KXpy_execfile(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: execfile() function disabled!\nGame Scripts should not use this function."); + return NULL; +} + +PyObject *KXpy_compile(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: compile() function disabled!\nGame Scripts should not use this function."); + return NULL; +} PyObject *KXpy_import(PyObject *self, PyObject *args) { @@ -895,19 +1048,13 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) } +static PyMethodDef meth_open[] = {{ "open", KXpy_open, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_reload[] = {{ "reload", KXpy_reload, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_file[] = {{ "file", KXpy_file, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_execfile[] = {{ "execfile", KXpy_execfile, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_compile[] = {{ "compile", KXpy_compile, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_open[] = { - { "open", KXpy_open, METH_VARARGS, - "(disabled)"} -}; - - -static PyMethodDef meth_import[] = { - { "import", KXpy_import, METH_VARARGS, - "our own import"} -}; - - +static PyMethodDef meth_import[] = {{ "import", KXpy_import, METH_VARARGS, "our own import"}}; //static PyObject *g_oldopen = 0; //static PyObject *g_oldimport = 0; @@ -918,15 +1065,21 @@ void setSandbox(TPythonSecurityLevel level) { PyObject *m = PyImport_AddModule("__builtin__"); PyObject *d = PyModule_GetDict(m); - PyObject *meth = PyCFunction_New(meth_open, NULL); switch (level) { case psl_Highest: //if (!g_security) { //g_oldopen = PyDict_GetItemString(d, "open"); - PyDict_SetItemString(d, "open", meth); - meth = PyCFunction_New(meth_import, NULL); - PyDict_SetItemString(d, "__import__", meth); + + // functions we cant trust + PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL)); + PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL)); + PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL)); + PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL)); + PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL)); + + // our own import + PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL)); //g_security = level; //} break; @@ -1010,6 +1163,11 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) ErrorObject = PyString_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); + /* needed for get/setMaterialType */ + KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_GLSL_MATERIAL, KX_BLENDER_GLSL_MATERIAL); + // XXXX Add constants here // Check for errors @@ -1031,9 +1189,38 @@ static char GameKeys_module_documentation[] = "This modules provides defines for key-codes" ; +static char gPyEventToString_doc[] = +"Take a valid event from the GameKeys module or Keyboard Sensor and return a name" +; +static PyObject* gPyEventToString(PyObject*, PyObject* value) +{ + PyObject* mod, *dict, *key, *val, *ret = NULL; + Py_ssize_t pos = 0; + + mod = PyImport_ImportModule( "GameKeys" ); + if (!mod) + return NULL; + + dict = PyModule_GetDict(mod); + + while (PyDict_Next(dict, &pos, &key, &val)) { + if (PyObject_Compare(value, val)==0) { + ret = key; + break; + } + } + + PyErr_Clear(); // incase there was an error clearing + Py_DECREF(mod); + if (!ret) PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event"); + else Py_INCREF(ret); + + return ret; +} static struct PyMethodDef gamekeys_methods[] = { + {"EventToString", (PyCFunction)gPyEventToString, METH_O, gPyEventToString_doc}, { NULL, (PyCFunction) NULL, 0, NULL } }; @@ -1191,3 +1378,66 @@ class KX_Scene* PHY_GetActiveScene() { return gp_KetsjiScene; } + +// utility function for loading and saving the globalDict +int saveGamePythonConfig( char **marshal_buffer) +{ + int marshal_length = 0; + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + if (gameLogic) { + PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module + if (pyGlobalDict) { +#ifdef Py_MARSHAL_VERSION + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 +#else + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); +#endif + if (pyGlobalDictMarshal) { + marshal_length= PyString_Size(pyGlobalDictMarshal); + // for testing only + // PyObject_Print(pyGlobalDictMarshal, stderr, 0); + *marshal_buffer = PyString_AsString(pyGlobalDictMarshal); + } else { + printf("Error, GameLogic.globalDict could not be marshal'd\n"); + } + Py_DECREF(gameLogic); + } else { + printf("Error, GameLogic.globalDict was removed\n"); + } + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + return marshal_length; +} + +int loadGamePythonConfig(char *marshal_buffer, int marshal_length) +{ + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + /* Restore the dict */ + if (marshal_buffer) { + PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); + if (pyGlobalDict) { + PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. + return 1; + } else { + PyErr_Clear(); + printf("Error could not marshall string\n"); + } + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + return 0; +} + +void pathGamePythonConfig( char *path ) +{ + int len = strlen(G.sce); + + strncpy(path, G.sce, sizeof(G.sce)); + /* replace extension */ + if (BLI_testextensie(path, ".blend")) { + strcpy(path+(len-6), ".bgeconf"); + } else { + strcpy(path+len, ".bgeconf"); + } +} diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index f094a1ca575..28d9d72a4c3 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -40,7 +40,7 @@ typedef enum { extern bool gUseVisibilityTemp; -PyObject* initGameLogic(class KX_Scene* ketsjiscene); +PyObject* initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene); PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level); @@ -49,6 +49,10 @@ void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); void exitGamePythonScripting(); +void pathGamePythonConfig( char *path ); +int saveGamePythonConfig( char **marshal_buffer); +int loadGamePythonConfig(char *marshal_buffer, int marshal_length); + void PHY_SetActiveScene(class KX_Scene* scene); class KX_Scene* PHY_GetActiveScene(); #include "MT_Vector3.h" diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp index 89e2d645d54..974d4b992a6 100644 --- a/source/gameengine/Ketsji/KX_RayCast.cpp +++ b/source/gameengine/Ketsji/KX_RayCast.cpp @@ -40,7 +40,21 @@ #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" -bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, MT_Point3& result_point, MT_Vector3& result_normal, const KX_RayCast& callback) +KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal) + :PHY_IRayCastFilterCallback(dynamic_cast(ignoreController), faceNormal) +{ +} + +void KX_RayCast::reportHit(PHY_RayCastResult* result) +{ + m_hitFound = true; + m_hitPoint.setValue((const float*)result->m_hitPoint); + m_hitNormal.setValue((const float*)result->m_hitNormal); + m_hitMesh = result->m_meshObject; + m_hitPolygon = result->m_polygon; +} + +bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback) { // Loops over all physics objects between frompoint and topoint, // calling callback.RayHit for each one. @@ -50,58 +64,51 @@ bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsE // returns true if an object was found, false if not. MT_Point3 frompoint(_frompoint); const MT_Vector3 todir( (topoint - frompoint).safe_normalized() ); + MT_Point3 prevpoint(_frompoint+todir*(-1.f)); PHY_IPhysicsController* hit_controller; - PHY__Vector3 phy_pos; - PHY__Vector3 phy_normal; - while((hit_controller = physics_environment->rayTest(dynamic_cast(ignore_controller), + while((hit_controller = physics_environment->rayTest(callback, frompoint.x(),frompoint.y(),frompoint.z(), - topoint.x(),topoint.y(),topoint.z(), - phy_pos[0],phy_pos[1],phy_pos[2], - phy_normal[0],phy_normal[1],phy_normal[2]))) + topoint.x(),topoint.y(),topoint.z())) != NULL) { - result_point = MT_Point3(phy_pos); - result_normal = MT_Vector3(phy_normal); KX_ClientObjectInfo* info = static_cast(hit_controller->getNewClientInfo()); if (!info) { printf("no info!\n"); MT_assert(info && "Physics controller with no client object info"); - return false; + break; } - if (callback.RayHit(info, result_point, result_normal)) - return true; - - // There is a bug in the code below: the delta is computed with the wrong - // sign on the face opposite to the center, resulting in infinite looping. - // In Blender 2.45 this code was never executed because callback.RayHit() always - // returned true, causing the ray sensor to stop on the first object. - // To avoid changing the behaviour will simply return false here. - // It should be discussed if we want the ray sensor to "see" through objects - // that don't have the required property/material (condition to get here) - return false; - - // skip past the object and keep tracing - /* We add 0.01 of fudge, so that if the margin && radius == 0., we don't endless loop. */ - MT_Scalar marg = 0.01 + hit_controller->GetMargin(); - marg += 2.f * hit_controller->GetMargin(); + // The biggest danger to to endless loop, prevent this by checking that the + // hit point always progresses along the ray direction.. + prevpoint -= callback.m_hitPoint; + if (prevpoint.length2() < MT_EPSILON) + break; + + if (callback.RayHit(info)) + // caller may decide to stop the loop and still cancel the hit + return callback.m_hitFound; + + // Skip past the object and keep tracing. + // Note that retrieving in a single shot multiple hit points would be possible + // but it would require some change in Bullet. + prevpoint = callback.m_hitPoint; + /* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */ + MT_Scalar marg = 0.001 + hit_controller->GetMargin(); + marg *= 2.f; /* Calculate the other side of this object */ - PHY__Vector3 hitpos; - hit_controller->getPosition(hitpos); - MT_Point3 hitObjPos(hitpos); - - MT_Vector3 hitvector = hitObjPos - result_point; - if (hitvector.dot(hitvector) > MT_EPSILON) - { - hitvector.normalize(); - marg *= 2.*todir.dot(hitvector); - } - frompoint = result_point + marg * todir; + MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal)); + if (h <= 0.01) + // the normal is almost orthogonal to the ray direction, cannot compute the other side + break; + marg /= h; + frompoint = callback.m_hitPoint + marg * todir; + // verify that we are not passed the to point + if ((topoint - frompoint).dot(todir) < 0.f) + break; } - - return hit_controller; + return false; } diff --git a/source/gameengine/Ketsji/KX_RayCast.h b/source/gameengine/Ketsji/KX_RayCast.h index 607dabd8afc..c3084c997a1 100644 --- a/source/gameengine/Ketsji/KX_RayCast.h +++ b/source/gameengine/Ketsji/KX_RayCast.h @@ -30,12 +30,14 @@ #ifndef __KX_RAYCAST_H__ #define __KX_RAYCAST_H__ -class MT_Point3; -class MT_Vector3; -class KX_IPhysicsController; -class PHY_IPhysicsEnvironment; +#include "PHY_IPhysicsEnvironment.h" +#include "PHY_IPhysicsController.h" +#include "MT_Point3.h" +#include "MT_Vector3.h" +class RAS_MeshObject; struct KX_ClientObjectInfo; +class KX_IPhysicsController; /** * Defines a function for doing a ray cast. @@ -49,17 +51,27 @@ struct KX_ClientObjectInfo; * * Returns true if a client was accepted, false if nothing found. */ -class KX_RayCast +class KX_RayCast : public PHY_IRayCastFilterCallback { -protected: - KX_RayCast() {}; public: + bool m_hitFound; + MT_Point3 m_hitPoint; + MT_Vector3 m_hitNormal; + const RAS_MeshObject* m_hitMesh; + int m_hitPolygon; + + KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal); virtual ~KX_RayCast() {} + /** + * The physic environment returns the ray casting result through this function + */ + virtual void reportHit(PHY_RayCastResult* result); + /** ray test callback. * either override this in your class, or use a callback wrapper. */ - virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const = 0; + virtual bool RayHit(KX_ClientObjectInfo* client) = 0; /** * Callback wrapper. @@ -71,13 +83,11 @@ public: /// Public interface. /// Implement bool RayHit in your class to receive ray callbacks. - static bool RayTest(KX_IPhysicsController* physics_controller, + static bool RayTest( PHY_IPhysicsEnvironment* physics_environment, - const MT_Point3& _frompoint, + const MT_Point3& frompoint, const MT_Point3& topoint, - MT_Point3& result_point, - MT_Vector3& result_normal, - const KX_RayCast& callback); + KX_RayCast& callback); }; @@ -86,18 +96,32 @@ template class KX_RayCast::Callback : public KX_RayCast T *self; void *data; public: - Callback(T *_self, void *_data = NULL) - : self(_self), + Callback(T *_self, KX_IPhysicsController* controller=NULL, void *_data = NULL, bool faceNormal=false) + : KX_RayCast(controller, faceNormal), + self(_self), data(_data) { } ~Callback() {} - - virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const + + virtual bool RayHit(KX_ClientObjectInfo* client) { - return self->RayHit(client, hit_point, hit_normal, data); + return self->RayHit(client, this, data); } + + virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller) + { + KX_ClientObjectInfo* info = static_cast(controller->getNewClientInfo()); + + if (!info) + { + MT_assert(info && "Physics controller with no client object info"); + return false; + } + return self->NeedRayCast(info); + } + }; diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index a416c8c9f89..8dc22fe13c1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -51,6 +51,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, bool bFindMaterial, + bool bXRay, double distance, int axis, KX_Scene* ketsjiScene, @@ -58,6 +59,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, : SCA_ISensor(gameobj,eventmgr, T), m_propertyname(propname), m_bFindMaterial(bFindMaterial), + m_bXRay(bXRay), m_distance(distance), m_scene(ketsjiScene), m_axis(axis) @@ -104,16 +106,10 @@ bool KX_RaySensor::IsPositiveTrigger() return result; } -bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; - - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } bool bFound = false; if (m_propertyname.Length() == 0) @@ -139,16 +135,43 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_ { m_rayHit = true; m_hitObject = hitKXObj; - m_hitPosition = hit_point; - m_hitNormal = hit_normal; + m_hitPosition = result->m_hitPoint; + m_hitNormal = result->m_hitNormal; } - - return bFound; - + // no multi-hit search yet + return true; } - +/* this function is used to pre-filter the object before casting the ray on them. + This is useful for "X-Ray" option when we want to see "through" unwanted object. + */ +bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo* client) +{ + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // Unknown type of object, skip it. + // Should not occur as the sensor objects are filtered in RayTest() + printf("Invalid client type %d found ray casting\n", client->m_type); + return false; + } + if (m_bXRay && m_propertyname.Length() != 0) + { + if (m_bFindMaterial) + { + // not quite correct: an object may have multiple material + // should check all the material and not only the first one + if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info))) + return false; + } + else + { + if (client->m_gameobject->GetProperty(m_propertyname) == NULL) + return false; + } + } + return true; +} bool KX_RaySensor::Evaluate(CValue* event) { @@ -215,8 +238,6 @@ bool KX_RaySensor::Evaluate(CValue* event) m_rayDirection = todir; MT_Point3 topoint = frompoint + (m_distance) * todir; - MT_Point3 resultpoint; - MT_Vector3 resultnormal; PHY_IPhysicsEnvironment* pe = m_scene->GetPhysicsEnvironment(); if (!pe) @@ -238,7 +259,8 @@ bool KX_RaySensor::Evaluate(CValue* event) PHY_IPhysicsEnvironment* physics_environment = this->m_scene->GetPhysicsEnvironment(); - result = KX_RayCast::RayTest(spc, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this)); + KX_RayCast::Callback callback(this, spc); + KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback); /* now pass this result to some controller */ @@ -265,6 +287,10 @@ bool KX_RaySensor::Evaluate(CValue* event) // notify logicsystem that ray JUST left the Object result = true; } + else + { + result = false; + } } if (reset) diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index f4305b053d1..02a755fedc1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -36,12 +36,14 @@ #include "MT_Point3.h" struct KX_ClientObjectInfo; +class KX_RayCast; class KX_RaySensor : public SCA_ISensor { Py_Header; STR_String m_propertyname; bool m_bFindMaterial; + bool m_bXRay; double m_distance; class KX_Scene* m_scene; bool m_bTriggered; @@ -56,7 +58,8 @@ public: KX_RaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, - bool fFindMaterial, + bool bFindMaterial, + bool bXRay, double distance, int axis, class KX_Scene* ketsjiScene, @@ -68,7 +71,8 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client); KX_PYMETHOD_DOC(KX_RaySensor,GetHitObject); KX_PYMETHOD_DOC(KX_RaySensor,GetHitPosition); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index ca0106d64d9..c4c190e9fa1 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -39,6 +39,8 @@ #include "KX_GameObject.h" #include "KX_IPhysicsController.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif @@ -52,14 +54,20 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, int time, SCA_IScene* scene, const MT_Vector3& linvel, - bool local, + bool linv_local, + const MT_Vector3& angvel, + bool angv_local, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_OriginalObject(original), m_scene(scene), + m_linear_velocity(linvel), - m_localFlag(local) + m_localLinvFlag(linv_local), + + m_angular_velocity(angvel), + m_localAngvFlag(angv_local) { if (m_OriginalObject) m_OriginalObject->RegisterActuator(this); @@ -181,13 +189,15 @@ PyParentObject KX_SCA_AddObjectActuator::Parents[] = { }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, SetObject_doc}, - {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc}, + {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, SetTime_doc}, {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc}, - {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc}, - {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc}, + {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, GetTime_doc}, + {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, GetLinearVelocity_doc}, {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc}, - {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, - {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_VARARGS,"instantAddObject() : immediately add object without delay\n"}, + {"getAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetAngularVelocity, METH_NOARGS, GetAngularVelocity_doc}, + {"setAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetAngularVelocity, METH_VARARGS, SetAngularVelocity_doc}, + {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_NOARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, + {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, {NULL,NULL} //Sentinel }; @@ -231,19 +241,18 @@ char KX_SCA_AddObjectActuator::SetTime_doc[] = "\tIf the duration is negative, it is set to 0.\n"; -PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value) { - int deltatime; - - if (!PyArg_ParseTuple(args, "i", &deltatime)) + int deltatime = PyInt_AsLong(value); + if (deltatime==-1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected an int"); return NULL; + } m_timeProp = deltatime; if (m_timeProp < 0) m_timeProp = 0; - Py_Return; + Py_RETURN_NONE; } @@ -254,9 +263,7 @@ char KX_SCA_AddObjectActuator::GetTime_doc[] = "\tReturns the lifetime of the object that will be added.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self) { return PyInt_FromLong(m_timeProp); } @@ -290,17 +297,13 @@ char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = "\tReturns the linear velocity that will be assigned to \n" "\tthe created object.\n"; - - -PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self) { PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); return retVal; } @@ -313,12 +316,10 @@ char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = "\t- vx: float\n" "\t- vy: float\n" "\t- vz: float\n" +"\t- local: bool\n" "\tAssign this velocity to the created object. \n"; - -PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* args) { float vecArg[3]; @@ -326,7 +327,46 @@ PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, return NULL; m_linear_velocity.setValue(vecArg); - Py_Return; + Py_RETURN_NONE; +} + +/* 7. getAngularVelocity */ +char KX_SCA_AddObjectActuator::GetAngularVelocity_doc[] = +"GetAngularVelocity()\n" +"\tReturns the angular velocity that will be assigned to \n" +"\tthe created object.\n"; + +PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity(PyObject* self) +{ + PyObject *retVal = PyList_New(3); + + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2])); + + return retVal; +} + + + +/* 8. setAngularVelocity */ +char KX_SCA_AddObjectActuator::SetAngularVelocity_doc[] = +"setAngularVelocity(vx, vy, vz)\n" +"\t- vx: float\n" +"\t- vy: float\n" +"\t- vz: float\n" +"\t- local: bool\n" +"\tAssign this angular velocity to the created object. \n"; + +PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* args) +{ + + float vecArg[3]; + if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) + return NULL; + + m_angular_velocity.setValue(vecArg); + Py_RETURN_NONE; } void KX_SCA_AddObjectActuator::InstantAddObject() @@ -337,8 +377,9 @@ void KX_SCA_AddObjectActuator::InstantAddObject() // Now it needs to be added to the current scene. SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp ); KX_GameObject * game_obj = static_cast(replica); - game_obj->setLinearVelocity(m_linear_velocity,m_localFlag); - game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false); + game_obj->setLinearVelocity(m_linear_velocity,m_localLinvFlag); + game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag); + game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag); // keep a copy of the last object, to allow python scripters to change it if (m_lastCreatedObject) @@ -355,13 +396,11 @@ void KX_SCA_AddObjectActuator::InstantAddObject() } } -PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self) { InstantAddObject(); - Py_Return; + Py_RETURN_NONE; } @@ -372,16 +411,17 @@ char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = "\tReturn the last created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self) { SCA_IObject* result = this->GetLastCreatedObject(); - if (result) + + // if result->GetSGNode() is NULL + // it means the object has ended, The BGE python api crashes in many places if the object is returned. + if (result && (static_cast(result))->GetSGNode()) { result->AddRef(); return result; } // don't return NULL to python anymore, it gives trouble in the scripts - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index e7fdb2fbfbc..278d4180284 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -60,9 +60,13 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator /// Linear velocity upon creation of the object. MT_Vector3 m_linear_velocity; + + /// Angular velocity upon creation of the object. + MT_Vector3 m_angular_velocity; /// Apply the velocity locally - bool m_localFlag; + bool m_localLinvFlag; + bool m_localAngvFlag; SCA_IObject* m_lastCreatedObject; @@ -79,7 +83,9 @@ public: int time, SCA_IScene* scene, const MT_Vector3& linvel, - bool local, + bool linv_local, + const MT_Vector3& angvel, + bool angv_local, PyTypeObject* T=&Type ); @@ -115,19 +121,23 @@ public: /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetObject); /* 2. setTime */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetTime); + KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetTime); /* 3. getTime */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetTime); + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetTime); /* 4. getObject */ KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,GetObject); /* 5. getLinearVelocity */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLinearVelocity); + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLinearVelocity); /* 6. setLinearVelocity */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetLinearVelocity); - /* 7. getLastCreatedObject */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLastCreatedObject); - /* 8. instantAddObject*/ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,InstantAddObject); + KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetLinearVelocity); + /* 7. getAngularVelocity */ + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetAngularVelocity); + /* 8. setAngularVelocity */ + KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetAngularVelocity); + /* 9. getLastCreatedObject */ + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLastCreatedObject); + /* 10. instantAddObject*/ + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject); }; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 630df2d21d9..e1f11732085 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -37,6 +37,8 @@ #include "KX_SCA_ReplaceMeshActuator.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif @@ -80,7 +82,7 @@ PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { - {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_VARARGS, SetMesh_doc}, + {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_O, SetMesh_doc}, KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh), KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, getMesh), @@ -99,28 +101,29 @@ PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const STR_String& attr) /* 1. setMesh */ char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] = "setMesh(name)\n" - "\t- name: string\n" + "\t- name: string or None\n" "\tSet the mesh that will be substituted for the current one.\n"; -PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, PyObject* value) { - char* meshname; - - if (!PyArg_ParseTuple(args, "s", &meshname)) - { - return NULL; - } - - void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); - - if (mesh) { + if (value == Py_None) { + m_mesh = NULL; + } else { + char* meshname = PyString_AsString(value); + if (!meshname) { + PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None"); + return NULL; + } + void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); + + if (mesh==NULL) { + PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist"); + return NULL; + } m_mesh= (class RAS_MeshObject*)mesh; - Py_Return; } - return NULL; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, @@ -129,7 +132,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, ) { if (!m_mesh) - Py_Return; + Py_RETURN_NONE; return PyString_FromString(const_cast(m_mesh->GetName().ReadPtr())); } @@ -139,7 +142,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh, "instantReplaceMesh() : immediately replace mesh without delay\n") { InstantReplaceMesh(); - Py_Return; + Py_RETURN_NONE; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 5ba0a099b14..1da154cc222 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -76,7 +76,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator void InstantReplaceMesh(); /* 1. setMesh */ - KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,SetMesh); + KX_PYMETHOD_DOC_O(KX_SCA_ReplaceMeshActuator,SetMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,getMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,instantReplaceMesh); diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index f085ff435dc..d651373869a 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -78,7 +78,7 @@ UpdateChildCoordinates( if (parent) { - const BL_ArmatureObject *armature = (const BL_ArmatureObject*)(parent->GetSGClientObject()); + BL_ArmatureObject *armature = (BL_ArmatureObject*)(parent->GetSGClientObject()); if (armature) { MT_Matrix4x4 parent_matrix; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index ab3692d2411..72875bbc039 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -68,6 +68,7 @@ #include "SG_IObject.h" #include "SG_Tree.h" #include "DNA_group_types.h" +#include "DNA_scene_types.h" #include "BKE_anim.h" #include "KX_SG_NodeRelationships.h" @@ -116,7 +117,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface *ndi, class SND_IAudioDevice* adi, - const STR_String& sceneName): + const STR_String& sceneName, + Scene *scene): PyObjectPlus(&KX_Scene::Type), m_keyboardmgr(NULL), m_mousemgr(NULL), @@ -126,7 +128,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0) + m_ueberExecutionPriority(0), + m_blenderScene(scene) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -453,7 +456,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal // this is the list of object that are send to the graphics pipeline m_objectlist->Add(newobj->AddRef()); - newobj->Bucketize(); + newobj->AddMeshUser(); // logic cannot be replicated, until the whole hierarchy is replicated. m_logicHierarchicalGameObjects.push_back(newobj); @@ -623,6 +626,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) if (blgroupobj == blenderobj) // this check is also in group_duplilist() continue; + gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj); if (gameobj == NULL) { @@ -630,6 +634,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // Should not happen as dupli group are created automatically continue; } + + gameobj->SetBlenderGroupObject(blgroupobj); + if ((blenderobj->lay & group->layer)==0) { // object is not visible in the 3D view, will not be instantiated @@ -944,6 +951,8 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) newobj->RemoveMeshes(); ret = 1; + if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell + ret = newobj->Release(); if (m_objectlist->RemoveValue(newobj)) ret = newobj->Release(); if (m_tempObjectList->RemoveValue(newobj)) @@ -997,7 +1006,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) newobj->m_pDeformer = NULL; } - if (mesh->m_class == 1) + if (mesh->IsDeformed()) { // we must create a new deformer but which one? KX_GameObject* parentobj = newobj->GetParent(); @@ -1071,7 +1080,8 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) parentobj->Release(); } } - gameobj->Bucketize(); + + gameobj->AddMeshUser(); } @@ -1223,7 +1233,9 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi for (int m=0;mGetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } - gameobj->MarkVisible(visible); + + gameobj->SetCulled(!visible); + gameobj->UpdateBuckets(false); } } if (node->Left()) @@ -1240,7 +1252,8 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam // Shadow lamp layers if(layer && !(gameobj->GetLayer() & layer)) { - gameobj->MarkVisible(false); + gameobj->SetCulled(true); + gameobj->UpdateBuckets(false); return; } @@ -1286,9 +1299,11 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam } // Visibility/ non-visibility are marked // elsewhere now. - gameobj->MarkVisible(); + gameobj->SetCulled(false); + gameobj->UpdateBuckets(false); } else { - gameobj->MarkVisible(false); + gameobj->SetCulled(true); + gameobj->UpdateBuckets(false); } } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 1c56dd1ee55..5f7e1167e27 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -54,6 +54,7 @@ */ struct SM_MaterialProps; struct SM_ShapeProps; +struct Scene; class GEN_HashedPtr; class CListValue; @@ -277,12 +278,15 @@ protected: */ PyObject* m_attrlist; + struct Scene* m_blenderScene; + public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface* ndi, class SND_IAudioDevice* adi, - const STR_String& scenename ); + const STR_String& scenename, + struct Scene* scene); virtual ~KX_Scene(); @@ -582,6 +586,10 @@ public: * was running and not suspended) and the "curtime" */ double getSuspendedDelta(); + /** + * Returns the Blender scene this was made from + */ + struct Scene *GetBlenderScene() { return m_blenderScene; } }; typedef std::vector KX_SceneList; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 34a3baec093..f75a1ee5c62 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -69,11 +69,11 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SoundActuator::~KX_SoundActuator() { - //m_soundScene->RemoveObject(this->m_soundObject); - //(this->m_soundObject)->DeleteWhenFinished(); - m_soundScene->RemoveActiveObject(m_soundObject); -// m_soundScene->DeleteObjectWhenFinished(m_soundObject); - m_soundScene->DeleteObject(m_soundObject); + if (m_soundObject) + { + m_soundScene->RemoveActiveObject(m_soundObject); + m_soundScene->DeleteObject(m_soundObject); + } } @@ -82,9 +82,12 @@ CValue* KX_SoundActuator::GetReplica() { KX_SoundActuator* replica = new KX_SoundActuator(*this); replica->ProcessReplica(); - SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); - replica->setSoundObject(soundobj); - m_soundScene->AddObject(soundobj); + if (m_soundObject) + { + SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); + replica->setSoundObject(soundobj); + m_soundScene->AddObject(soundobj); + } // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -104,6 +107,9 @@ bool KX_SoundActuator::Update(double curtime, bool frame) RemoveAllEvents(); + if (!m_soundObject) + return false; + if (m_pino) { bNegativeEvent = true; @@ -287,6 +293,10 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObje PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds) { + if (!m_soundObject) + { + return PyString_FromString(""); + } STR_String objectname = m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -301,7 +311,8 @@ PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObje PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds) { - m_soundObject->StartSound(); + if (m_soundObject) + m_soundObject->StartSound(); Py_Return; } @@ -309,7 +320,8 @@ PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds) { - m_soundObject->PauseSound(); + if (m_soundObject) + m_soundObject->PauseSound(); Py_Return; } @@ -317,7 +329,8 @@ PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds) { - m_soundObject->StopSound(); + if (m_soundObject) + m_soundObject->StopSound(); Py_Return; } @@ -329,7 +342,8 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* if (!PyArg_ParseTuple(args, "f", &gain)) return NULL; - m_soundObject->SetGain(gain); + if (m_soundObject) + m_soundObject->SetGain(gain); Py_Return; } @@ -338,7 +352,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds) { - float gain = m_soundObject->GetGain(); + float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f; PyObject* result = PyFloat_FromDouble(gain); return result; @@ -352,7 +366,8 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* if (!PyArg_ParseTuple(args, "f", &pitch)) return NULL; - m_soundObject->SetPitch(pitch); + if (m_soundObject) + m_soundObject->SetPitch(pitch); Py_Return; } @@ -361,7 +376,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds) { - float pitch = m_soundObject->GetPitch(); + float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0; PyObject* result = PyFloat_FromDouble(pitch); return result; @@ -375,7 +390,8 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P if (!PyArg_ParseTuple(args, "f", &rollofffactor)) return NULL; - m_soundObject->SetRollOffFactor(rollofffactor); + if (m_soundObject) + m_soundObject->SetRollOffFactor(rollofffactor); Py_Return; } @@ -384,7 +400,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds) { - float rollofffactor = m_soundObject->GetRollOffFactor(); + float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0; PyObject* result = PyFloat_FromDouble(rollofffactor); return result; @@ -398,7 +414,8 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec if (!PyArg_ParseTuple(args, "i", &looping)) return NULL; - m_soundObject->SetLoopMode(looping); + if (m_soundObject) + m_soundObject->SetLoopMode(looping); Py_Return; } @@ -407,7 +424,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds) { - int looping = m_soundObject->GetLoopMode(); + int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : SND_LOOP_OFF; PyObject* result = PyInt_FromLong(looping); return result; @@ -425,7 +442,8 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2])) return NULL; - m_soundObject->SetPosition(pos); + if (m_soundObject) + m_soundObject->SetPosition(pos); Py_Return; } @@ -442,7 +460,8 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2])) return NULL; - m_soundObject->SetVelocity(vel); + if (m_soundObject) + m_soundObject->SetVelocity(vel); Py_Return; } @@ -465,7 +484,8 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2])) return NULL; - m_soundObject->SetOrientation(ori); + if (m_soundObject) + m_soundObject->SetOrientation(ori); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 67937d5c579..8b09cd4e953 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -42,6 +42,8 @@ #include #include "KX_GameObject.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index f5a2b5e02fe..342e71c5093 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -1,6 +1,8 @@ #include +#include "PyObjectPlus.h" + #include "KX_VehicleWrapper.h" #include "PHY_IPhysicsEnvironment.h" #include "PHY_IVehicle.h" diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 5cec65dff1c..25205714308 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -82,7 +82,7 @@ PyObject* KX_VertexProxy::_getattr(const STR_String& attr) { if (attr == "XYZ") - return PyObjectFrom(MT_Vector3(m_vertex->getLocalXYZ())); + return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); if (attr == "UV") return PyObjectFrom(MT_Point2(m_vertex->getUV1())); @@ -102,11 +102,11 @@ KX_VertexProxy::_getattr(const STR_String& attr) // pos if (attr == "x") - return PyFloat_FromDouble(m_vertex->getLocalXYZ()[0]); + return PyFloat_FromDouble(m_vertex->getXYZ()[0]); if (attr == "y") - return PyFloat_FromDouble(m_vertex->getLocalXYZ()[1]); + return PyFloat_FromDouble(m_vertex->getXYZ()[1]); if (attr == "z") - return PyFloat_FromDouble(m_vertex->getLocalXYZ()[2]); + return PyFloat_FromDouble(m_vertex->getXYZ()[2]); // Col if (attr == "r") @@ -184,7 +184,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) { float val = PyFloat_AsDouble(pyvalue); // pos - MT_Point3 pos(m_vertex->getLocalXYZ()); + MT_Point3 pos(m_vertex->getXYZ()); if (attr == "x") { pos.x() = val; @@ -312,7 +312,7 @@ PyObject* KX_VertexProxy::PyGetXYZ(PyObject*, PyObject*, PyObject*) { - return PyObjectFrom(MT_Point3(m_vertex->getLocalXYZ())); + return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); } PyObject* KX_VertexProxy::PySetXYZ(PyObject*, @@ -426,7 +426,7 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject*, { if (PyVecTo(list, vec)) { - m_vertex->SetFlag((m_vertex->getFlag()|TV_2NDUV)); + m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); m_vertex->SetUnit(unit); m_vertex->SetUV2(vec); m_mesh->SetMeshModified(true); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index b4693a7a7db..e60a8d7c099 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -38,10 +38,12 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool recursive, PyTypeObject* T ) : SCA_IActuator(gameobj,T), - m_visible(visible) + m_visible(visible), + m_recursive(recursive) { // intentionally empty } @@ -75,10 +77,10 @@ KX_VisibilityActuator::Update() KX_GameObject *obj = (KX_GameObject*) GetParent(); - obj->SetVisible(m_visible); - obj->MarkVisible(); + obj->SetVisible(m_visible, m_recursive); + obj->UpdateBuckets(m_recursive); - return true; + return false; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index 9b4753033fb..d1b85ab998c 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -39,12 +39,14 @@ class KX_VisibilityActuator : public SCA_IActuator /** Make visible? */ bool m_visible; + bool m_recursive; public: KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool recursive, PyTypeObject* T=&Type ); diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile index 47a4855b00c..0b48ad8b8c3 100644 --- a/source/gameengine/Ketsji/Makefile +++ b/source/gameengine/Ketsji/Makefile @@ -35,10 +35,13 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) +CPPFLAGS += $(NAN_SDLCFLAGS) CPPFLAGS += $(OGL_CPPFLAGS) CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) -CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -I../../blender/python +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I../../blender/python +CPPFLAGS += -I../../blender/python/api2_2x CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include @@ -61,13 +64,9 @@ CPPFLAGS += -I../../blender/blenlib CPPFLAGS += -I../../blender/include CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I../../blender/imbuf +CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - - ########################### SOURCEDIR = source/gameengine/Ketsji diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index f6f744b199a..02e7aed82a5 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -32,16 +32,13 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #sourc incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy' incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' -incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include' +incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu' cflags = [] if env['OURPLATFORM'] == 'win32-vc': cflags.append('/GR') cflags.append('/Ox') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SDL_INC'] diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp index a04560aaf09..6d9b41e08d2 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp @@ -206,8 +206,7 @@ void ODEPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) +PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { //m_OdeWorld diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index 7c61902f8e2..dcc87d614c0 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -54,8 +54,7 @@ public: float axisX,float axisY,float axisZ); virtual void removeConstraint(void * constraintid); - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index d6a32dfd9c0..8ba138df437 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -15,7 +15,7 @@ subject to the following restrictions: #include "CcdPhysicsController.h" #include "btBulletDynamicsCommon.h" - +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" #include "PHY_IMotionState.h" #include "CcdPhysicsEnvironment.h" #include "RAS_MeshObject.h" @@ -126,13 +126,14 @@ void CcdPhysicsController::CreateRigidbody() m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); - m_body = new btRigidBody(m_cci.m_mass, - m_bulletMotionState, - m_collisionShape, - m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor, - m_cci.m_linearDamping,m_cci.m_angularDamping, - m_cci.m_friction,m_cci.m_restitution); - + btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + rbci.m_linearDamping = m_cci.m_linearDamping; + rbci.m_angularDamping = m_cci.m_angularDamping; + rbci.m_friction = m_cci.m_friction; + rbci.m_restitution = m_cci.m_restitution; + + m_body = new btRigidBody(rbci); + // // init the rigidbody properly // @@ -276,7 +277,9 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta if (m_collisionShape) { // new shape has no scaling, apply initial scaling + m_collisionShape->setMargin(m_cci.m_margin); m_collisionShape->setLocalScaling(m_cci.m_scaling); + if (m_cci.m_mass) m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); } @@ -767,6 +770,8 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) // assume no shape information m_shapeType = PHY_SHAPE_NONE; m_vertexArray.clear(); + m_polygonIndexArray.clear(); + m_meshObject = NULL; if (!meshobj) return false; @@ -813,9 +818,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) { for (int i=0;iVertexCount();i++) { - const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[i], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + const float* vtx = poly->GetVertex(i)->getXYZ(); btPoint3 point(vtx[0],vtx[1],vtx[2]); m_vertexArray.push_back(point); numvalidpolys++; @@ -823,40 +826,36 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) } else { { - const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + const float* vtx = poly->GetVertex(2)->getXYZ(); btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[1], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(1)->getXYZ(); btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(0)->getXYZ(); btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); + m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); m_vertexArray.push_back(vertex2); + m_polygonIndexArray.push_back(p2); numvalidpolys++; } if (poly->VertexCount() == 4) { - const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[3], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + const float* vtx = poly->GetVertex(3)->getXYZ(); btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(2)->getXYZ(); btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(0)->getXYZ(); btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); + m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); m_vertexArray.push_back(vertex2); + m_polygonIndexArray.push_back(p2); numvalidpolys++; } } @@ -869,6 +868,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) m_shapeType = PHY_SHAPE_NONE; return false; } + m_meshObject = meshobj; return true; } @@ -906,15 +906,26 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() break; case PHY_SHAPE_MESH: - collisionMeshData = new btTriangleMesh(); - // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + // Let's use the latest btScaledBvhTriangleMeshShape: it allows true sharing of + // triangle mesh information between duplicates => drastic performance increase when + // duplicating complex mesh objects. + // BUT it causes a small performance decrease when sharing is not required: + // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering + // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 + // and btScaledBvhTriangleMeshShape otherwise. + if (!m_unscaledShape) { - collisionMeshData->addTriangle(*it++,*it++,*it++); + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + { + collisionMeshData->addTriangle(*it++,*it++,*it++); + } + // this shape will be shared and not deleted until shapeInfo is deleted + m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); + m_unscaledShape->recalcLocalAabb(); } - concaveShape = new btBvhTriangleMeshShape( collisionMeshData, true ); - concaveShape->recalcLocalAabb(); - collisionShape = concaveShape; + collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); break; case PHY_SHAPE_COMPOUND: @@ -926,6 +937,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionShape = nextShapeInfo->CreateBulletShape(); if (collisionShape) { + collisionShape->setLocalScaling(nextShapeInfo->m_childScale); compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape); } } @@ -954,7 +966,10 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() childShape->Release(); childShape = nextShape; } - + if (m_unscaledShape) + { + DeleteBulletShape(m_unscaledShape); + } m_vertexArray.clear(); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 1e1a38aa2a6..7d55851ebf6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -47,7 +47,9 @@ public: m_radius(1.0), m_height(1.0), m_halfExtend(0.f,0.f,0.f), + m_childScale(1.0f,1.0f,1.0f), m_nextShape(NULL), + m_unscaledShape(NULL), m_refCount(1) { m_childTrans.setIdentity(); @@ -71,10 +73,24 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); + btTriangleMeshShape* GetMeshShape(void) + { + return m_unscaledShape; + } CcdShapeConstructionInfo* GetNextShape() { return m_nextShape; } + CcdShapeConstructionInfo* GetChildShape(int i) + { + CcdShapeConstructionInfo* shape = m_nextShape; + while (i > 0 && shape != NULL) + { + shape = shape->m_nextShape; + i--; + } + return shape; + } bool SetMesh(RAS_MeshObject* mesh, bool polytope); @@ -86,11 +102,19 @@ public: btScalar m_height; btVector3 m_halfExtend; btTransform m_childTrans; + btVector3 m_childScale; std::vector m_vertexArray; // Contains both vertex array for polytope shape and // triangle array for concave mesh shape. // In this case a triangle is made of 3 consecutive points + std::vector m_polygonIndexArray; // Contains the array of polygon index in the + // original mesh that correspond to shape triangles. + // only set for concave mesh shape. + const RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh + protected: CcdShapeConstructionInfo* m_nextShape; // for compound shape + btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, + // the actual shape is of type btScaledBvhTriangleMeshShape int m_refCount; // this class is shared between replicas // keep track of users so that we can release it }; @@ -113,13 +137,15 @@ struct CcdConstructionInfo CcdConstructionInfo() - : m_gravity(0,0,0), + : m_localInertiaTensor(1.f, 1.f, 1.f), + m_gravity(0,0,0), m_scaling(1.f,1.f,1.f), m_mass(0.f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), m_angularDamping(0.1f), + m_margin(0.06f), m_collisionFlags(0), m_bRigid(false), m_collisionFilterGroup(DefaultFilter), @@ -140,6 +166,7 @@ struct CcdConstructionInfo btScalar m_friction; btScalar m_linearDamping; btScalar m_angularDamping; + btScalar m_margin; int m_collisionFlags; bool m_bRigid; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index d8e05fab839..5042df2162a 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -53,6 +53,7 @@ void DrawRasterizerLine(const float* from,const float* to,int color); #include +#include // for memset #ifdef NEW_BULLET_VEHICLE_SUPPORT class WrapperVehicle : public PHY_IVehicle @@ -329,30 +330,21 @@ m_filterCallback(NULL) { m_triggerCallbacks[i] = 0; } + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + if (!dispatcher) { - dispatcher = new btCollisionDispatcher(); + dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_ownDispatcher = dispatcher; } - if(!pairCache) - { - - //todo: calculate/let user specify this world sizes - btVector3 worldMin(-10000,-10000,-10000); - btVector3 worldMax(10000,10000,10000); - - pairCache = new btAxisSweep3(worldMin,worldMax); - // remember that this was allocated by us so that we can release it - m_ownPairCache = pairCache; - //broadphase = new btSimpleBroadphase(); - } + m_broadphase = new btDbvtBroadphase(); m_filterCallback = new CcdOverlapFilterCallBack(this); - pairCache->setOverlapFilterCallback(m_filterCallback); + m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback); setSolverType(1);//issues with quickstep and memory allocations - m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,m_solver); + m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_debugDrawer = 0; m_gravity = btVector3(0.f,-10.f,0.f); m_dynamicsWorld->setGravity(m_gravity); @@ -451,11 +443,12 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); - btVector3 inertia; + btVector3 inertia(0.0,0.0,0.0); m_dynamicsWorld->removeCollisionObject(body); body->setCollisionFlags(newCollisionFlags); - body->getCollisionShape()->calculateLocalInertia(newMass, inertia); + if (newMass) + body->getCollisionShape()->calculateLocalInertia(newMass, inertia); body->setMassProps(newMass, inertia); m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); // to avoid nasty interaction, we must update the property of the controller as well @@ -518,6 +511,9 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) veh->SyncWheels(); } + m_dynamicsWorld->debugDrawWorld(); + + CallbackTriggers(); return true; @@ -578,7 +574,7 @@ void CcdPhysicsEnvironment::setSolverDamping(float damping) void CcdPhysicsEnvironment::setLinearAirDamping(float damping) { - gLinearAirDamping = damping; + //gLinearAirDamping = damping; } void CcdPhysicsEnvironment::setUseEpa(bool epa) @@ -597,7 +593,7 @@ void CcdPhysicsEnvironment::setSolverType(int solverType) { m_solver = new btSequentialImpulseConstraintSolver(); - ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); +// ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); break; } } @@ -659,9 +655,10 @@ int CcdPhysicsEnvironment::createUniversalD6Constraint( { + bool useReferenceFrameA = true; genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB); + frameInA,frameInB,useReferenceFrameA); genericConstraint->setLinearLowerLimit(linearMinLimits); genericConstraint->setLinearUpperLimit(linearMaxLimits); genericConstraint->setAngularLowerLimit(angularMinLimits); @@ -709,35 +706,54 @@ void CcdPhysicsEnvironment::removeConstraint(int constraintId) struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback { - PHY_IPhysicsController* m_ignoreClient; + PHY_IRayCastFilterCallback& m_phyRayFilter; + const btCollisionShape* m_hitTriangleShape; + int m_hitTriangleIndex; - FilterClosestRayResultCallback (PHY_IPhysicsController* ignoreClient,const btVector3& rayFrom,const btVector3& rayTo) + FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo) : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo), - m_ignoreClient(ignoreClient) + m_phyRayFilter(phyRayFilter), + m_hitTriangleShape(NULL), + m_hitTriangleIndex(0) { - } virtual ~FilterClosestRayResultCallback() { } - virtual float AddSingleResult( btCollisionWorld::LocalRayResult& rayResult) + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask)) + return false; + if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask)) + return false; + btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject; + CcdPhysicsController* phyCtrl = static_cast(object->getUserPointer()); + if (phyCtrl == m_phyRayFilter.m_ignoreController) + return false; + return m_phyRayFilter.needBroadphaseRayCast(phyCtrl); + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) { CcdPhysicsController* curHit = static_cast(rayResult.m_collisionObject->getUserPointer()); - //ignore client... - if (curHit != m_ignoreClient) - { - //if valid - return ClosestRayResultCallback::AddSingleResult(rayResult); + // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it + if (rayResult.m_localShapeInfo) + { + m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape(); + m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex; + } else + { + m_hitTriangleShape = NULL; + m_hitTriangleIndex = 0; } - return m_closestHitFraction; + return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace); } }; -PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) +PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { @@ -751,19 +767,101 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* i //Either Ray Cast with or without filtering //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); - FilterClosestRayResultCallback rayCallback(ignoreClient,rayFrom,rayTo); + FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo); - PHY_IPhysicsController* nearestHit = 0; + PHY_RayCastResult result; + memset(&result, 0, sizeof(result)); + // don't collision with sensor object - m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback, CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter); - if (rayCallback.HasHit()) - { - nearestHit = static_cast(rayCallback.m_collisionObject->getUserPointer()); - hitX = rayCallback.m_hitPointWorld.getX(); - hitY = rayCallback.m_hitPointWorld.getY(); - hitZ = rayCallback.m_hitPointWorld.getZ(); + rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; + //, ,filterCallback.m_faceNormal); + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + CcdPhysicsController* controller = static_cast(rayCallback.m_collisionObject->getUserPointer()); + result.m_controller = controller; + result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX(); + result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY(); + result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ(); + + if (rayCallback.m_hitTriangleShape != NULL) + { + // identify the mesh polygon + CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo; + if (shapeInfo) + { + btCollisionShape* shape = controller->GetRigidBody()->getCollisionShape(); + if (shape->isCompound()) + { + btCompoundShape* compoundShape = (btCompoundShape*)shape; + CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo; + // need to search which sub-shape has been hit + for (int i=0; igetNumChildShapes(); i++) + { + shapeInfo = compoundShapeInfo->GetChildShape(i); + shape=compoundShape->getChildShape(i); + if (shape == rayCallback.m_hitTriangleShape) + break; + } + } + if (shape == rayCallback.m_hitTriangleShape && + rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size()) + { + result.m_meshObject = shapeInfo->m_meshObject; + result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex); + + // Bullet returns the normal from "outside". + // If the user requests the real normal, compute it now + if (filterCallback.m_faceNormal) + { + // mesh shapes are shared and stored in the shapeInfo + btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); + if (triangleShape) + { + // this code is copied from Bullet + btVector3 triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface(); + + meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + 0); + + unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride); + const btVector3& meshScaling = shape->getLocalScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + meshInterface->unLockReadOnlyVertexBase(0); + btVector3 triangleNormal; + triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal; + } + } + } + } + } if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { rayCallback.m_hitNormalWorld.normalize(); @@ -771,14 +869,14 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* i { rayCallback.m_hitNormalWorld.setValue(1,0,0); } - normalX = rayCallback.m_hitNormalWorld.getX(); - normalY = rayCallback.m_hitNormalWorld.getY(); - normalZ = rayCallback.m_hitNormalWorld.getZ(); - + result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX(); + result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY(); + result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ(); + filterCallback.reportHit(&result); } - return nearestHit; + return result.m_controller; } @@ -833,6 +931,12 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() if (NULL != m_filterCallback) delete m_filterCallback; + + if (NULL != m_collisionConfiguration) + delete m_collisionConfiguration; + + if (NULL != m_broadphase) + delete m_broadphase; } @@ -845,7 +949,7 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float { //param = 1..12, min0,max0,min1,max1...min6,max6 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; - genCons->SetLimit(param,value0,value1); + genCons->setLimit(param,value0,value1); break; }; default: @@ -1191,10 +1295,11 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA; frameInB = inv * globalFrameA; - + bool useReferenceFrameA = true; + genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB); + frameInA,frameInB,useReferenceFrameA); } else @@ -1215,9 +1320,10 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl ///frameInB in worldspace frameInB = rb0->getCenterOfMassTransform() * frameInA; + bool useReferenceFrameA = true; genericConstraint = new btGeneric6DofConstraint( *rb0,s_fixedObject2, - frameInA,frameInB); + frameInA,frameInB,useReferenceFrameA); } if (genericConstraint) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 825a5e525f2..3cf5a943e3f 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -56,6 +56,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment protected: btIDebugDraw* m_debugDrawer; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + class btBroadphaseInterface* m_broadphase; + //solver iterations int m_numIterations; @@ -157,8 +161,7 @@ protected: btTypedConstraint* getConstraintById(int constraintId); - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //Methods for gamelogic collision/physics callbacks diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile index 49259d0a67c..d5570e75833 100644 --- a/source/gameengine/Physics/Bullet/Makefile +++ b/source/gameengine/Physics/Bullet/Makefile @@ -37,5 +37,10 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I../../Physics/common CPPFLAGS += -I../../Physics/Dummy +CPPFLAGS += -I../../Rasterizer + diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index f512d44c9f2..d78958b746c 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -109,8 +109,7 @@ void DummyPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) +PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { //collision detection / raytesting return NULL; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index b5a61f72e4a..975be84f2a7 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -69,8 +69,7 @@ public: return 0; } - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 65018d2523e..80e4dc4044e 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -26,6 +26,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#include // memset #include "SumoPhysicsEnvironment.h" #include "PHY_IMotionState.h" #include "SumoPhysicsController.h" @@ -125,37 +126,35 @@ void SumoPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClientCtrl, +PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, - float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ, - float& normalX,float& normalY,float& normalZ) + float toX,float toY,float toZ) { - SumoPhysicsController* ignoreCtr = static_cast (ignoreClientCtrl); + SumoPhysicsController* ignoreCtr = static_cast (filterCallback.m_ignoreController); //collision detection / raytesting MT_Point3 hit, normal; - PHY_IPhysicsController *ret = 0; + 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) { - ret = (PHY_IPhysicsController *) smOb->getPhysicsClientObject(); + 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); } - hitX = hit[0]; - hitY = hit[1]; - hitZ = hit[2]; - - normalX = normal[0]; - normalY = normal[1]; - normalZ = normal[2]; - - return ret; + return result.m_controller; } //gamelogic callbacks void SumoPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index 8b9fb463034..100adf969d5 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -75,8 +75,7 @@ public: return 0; } - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 5b275066665..98496fb7f9e 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -33,6 +33,50 @@ #include #include "PHY_DynamicTypes.h" class PHY_IVehicle; +class RAS_MeshObject; +class PHY_IPhysicsController; + +/** + * pass back information from rayTest + */ +struct PHY_RayCastResult +{ + PHY_IPhysicsController* m_controller; + PHY__Vector3 m_hitPoint; + PHY__Vector3 m_hitNormal; + const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers) + int m_polygon; // index of the polygon hit by the ray, + // only if m_meshObject != NULL +}; + +/** + * This class replaces the ignoreController parameter of rayTest function. + * It allows more sophisticated filtering on the physics controller before computing the ray intersection to save CPU. + * It is only used to its full extend by the Ccd physics environement (Bullet). + */ +class PHY_IRayCastFilterCallback +{ +public: + PHY_IPhysicsController* m_ignoreController; + bool m_faceNormal; + + virtual ~PHY_IRayCastFilterCallback() + { + } + + virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller) + { + return true; + } + + virtual void reportHit(PHY_RayCastResult* result) = 0; + + PHY_IRayCastFilterCallback(PHY_IPhysicsController* ignoreController, bool faceNormal=false) + :m_ignoreController(ignoreController), + m_faceNormal(faceNormal) + { + } +}; /** * Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.) @@ -94,8 +138,7 @@ class PHY_IPhysicsEnvironment //complex constraint for vehicles virtual PHY_IVehicle* getVehicleConstraint(int constraintId) =0; - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)=0; + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0; //Methods for gamelogic collision/physics callbacks diff --git a/source/gameengine/PyDoc/GameKeys.py b/source/gameengine/PyDoc/GameKeys.py index 268fb9cc172..1a0a737718e 100644 --- a/source/gameengine/PyDoc/GameKeys.py +++ b/source/gameengine/PyDoc/GameKeys.py @@ -164,3 +164,12 @@ Example:: # Activate Right! """ + +def EventToString(event): + """ + Return the string name of a key event. Will raise a ValueError error if its invalid. + + @type event: int + @param event: key event from GameKeys or the keyboard sensor. + @rtype: string + """ diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index b65bc0f3ce8..af3d2810553 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -220,6 +220,13 @@ def setPhysicsTicRate(ticrate): @param ticrate: The new update frequency (in Hz). @type ticrate: float """ +def getAverageFrameRate(): + """ + Gets the estimated average framerate + + @return: The estimed average framerate in frames per second + @rtype: float + """ def expandPath(path): """ @@ -245,4 +252,4 @@ def getBlendFileList(path = "//"): @type path: string @return: A list of filenames, with no directory prefix @rtype: list - """ \ No newline at end of file + """ diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index a5ba5b1d634..ff9b4ffc95b 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -30,11 +30,11 @@ class KX_GameObject: Delete this object, can be used inpace of the EndObject Actuator. The actual removal of the object from the scene is delayed. """ - def getVisible(visible): + def getVisible(): """ Gets the game object's visible flag. - @type visible: boolean + @rtype: boolean """ def setVisible(visible): """ @@ -49,16 +49,25 @@ class KX_GameObject: @rtype: int @return: the objects state. """ - def setState(): + def setState(state): """ - Sets the game object's visible flag. + Sets the game object's state flag. The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29) - @type visible: boolean + @type state: integer """ def setPosition(pos): """ - Sets the game object's position. + Sets the game object's position. + Global coordinates for root object, local for child objects. + + + @type pos: [x, y, z] + @param pos: the new position, in local coordinates. + """ + def setWorldPosition(pos): + """ + Sets the game object's position in world coordinates regardless if the object is root or child. @type pos: [x, y, z] @param pos: the new position, in world coordinates. @@ -135,6 +144,26 @@ class KX_GameObject: @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - True: you get the "local" velocity ie: relative to object orientation. """ + def getAngularVelocity(local = 0): + """ + Gets the game object's angular velocity. + + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + @rtype: list [vx, vy, vz] + @return: the object's angular velocity. + """ + def setAngularVelocity(velocity, local = 0): + """ + Sets the game object's angular velocity. + + @type velocity: 3d vector. + @param velocity: angular velocity vector. + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + """ def getVelocity(point): """ Gets the game object's velocity at the specified point. @@ -280,11 +309,13 @@ class KX_GameObject: @rtype: L{KX_GameObject} @return: the first object hit or None if no object or object does not match prop """ - def rayCast(to,from,dist,prop): + def rayCast(objto,objfrom,dist,prop,face,xray,poly): """ Look from a point/object to another point/object and find first object hit within dist that matches prop. - Returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. - Ex: + if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. + if poly is 1, returns a 4-tuple with in addition a L{KX_PolyProxy} as 4th element. + + Ex:: # shoot along the axis gun-gunAim (gunAim should be collision-free) ob,point,normal = gun.rayCast(gunAim,None,50) if ob: @@ -292,21 +323,42 @@ class KX_GameObject: Notes: The ray ignores the object on which the method is called. - If is casted from/to object center or explicit [x,y,z] points. - The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray - If a property was specified and the first object hit does not have that property, there is no hit - The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. + It is casted from/to object center or explicit [x,y,z] points. + + The face paremeter determines the orientation of the normal:: + 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside) + 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect) + + The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray. + The prop and xray parameters interact as follow:: + prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray. + prop off, xray on : idem. + prop on, xray off: return closest hit if it matches prop, no hit otherwise. + prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray. + The L{KX_PolyProxy} 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray. + If there is no hit or the hit object is not a static mesh, None is returned as 4th element. + + The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. - @param to: [x,y,z] or object to which the ray is casted - @type to: L{KX_GameObject} or 3-tuple - @param from: [x,y,z] or object from which the ray is casted; None or omitted => use self object center - @type from: L{KX_GameObject} or 3-tuple or None + @param objto: [x,y,z] or object to which the ray is casted + @type objto: L{KX_GameObject} or 3-tuple + @param objfrom: [x,y,z] or object from which the ray is casted; None or omitted => use self object center + @type objfrom: L{KX_GameObject} or 3-tuple or None @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to @type dist: float @param prop: property name that object must have; can be omitted => detect any object @type prop: string - @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) - @return: (object,hitpoint,hitnormal) or (None,None,None) + @param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin + @type face: int + @param xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object + @type xray: int + @param poly: polygon option: 1=>return value is a 4-tuple and the 4th element is a L{KX_PolyProxy} + @type poly: int + @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) + or 4-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz), L{KX_PolyProxy}) + @return: (object,hitpoint,hitnormal) or (object,hitpoint,hitnormal,polygon) + If no hit, returns (None,None,None) or (None,None,None,None) + If the object hit is not a static mesh, polygon is None """ diff --git a/source/gameengine/PyDoc/KX_MeshProxy.py b/source/gameengine/PyDoc/KX_MeshProxy.py index e43fa3598f0..03bc36b6ac1 100644 --- a/source/gameengine/PyDoc/KX_MeshProxy.py +++ b/source/gameengine/PyDoc/KX_MeshProxy.py @@ -95,6 +95,21 @@ class KX_MeshProxy: @rtype: L{KX_VertexProxy} @return: a vertex object. """ + def getNumPolygons(): + """ + Returns the number of polygon in the mesh. + + @rtype: integer + """ + def getPolygon(index): + """ + Gets the specified polygon from the mesh. + + @type index: integer + @param index: polygon number + @rtype: L{KX_PolyProxy} + @return: a polygon object. + """ def reinstancePhysicsMesh(): """ Updates the physics system with the changed mesh. diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py index db577d21e6f..b7b76473292 100644 --- a/source/gameengine/PyDoc/KX_ObjectActuator.py +++ b/source/gameengine/PyDoc/KX_ObjectActuator.py @@ -111,9 +111,7 @@ class KX_ObjectActuator(SCA_IActuator): For the servo control actuator, this is the target speed. @rtype: list [vx, vy, vz, local] - @return: A four item list, containing the vector velocity, and whether - the velocity is applied in local coordinates (True) or world - coordinates (False) + @return: A four item list, containing the vector velocity, and whether the velocity is applied in local coordinates (True) or world coordinates (False) """ def setLinearVelocity(vx, vy, vz, local): """ diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py index 4f2bf85bff3..c3b2e947ddb 100644 --- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py @@ -64,6 +64,23 @@ class KX_SCA_AddObjectActuator(SCA_IActuator): """ Returns the initial linear velocity of added objects. + @rtype: list [vx, vy, vz] + """ + def setAngularVelocity(vx, vy, vz): + """ + Sets the initial angular velocity of added objects. + + @type vx: float + @param vx: the x component of the initial angular velocity. + @type vy: float + @param vy: the y component of the initial angular velocity. + @type vz: float + @param vz: the z component of the initial angular velocity. + """ + def getAngularVelocity(): + """ + Returns the initial angular velocity of added objects. + @rtype: list [vx, vy, vz] """ def getLastCreatedObject(): diff --git a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py index eb00a91a4ce..498f6072e23 100644 --- a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py @@ -59,8 +59,9 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator): def setMesh(name): """ Sets the name of the mesh that will replace the current one. + When the name is None it will unset the mesh value so no action is taken. - @type name: string + @type name: string or None """ def getMesh(): """ @@ -68,6 +69,6 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator): Returns None if no mesh has been scheduled to be added. - @rtype: string + @rtype: string or None """ diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py index 2ecd94f38ae..948302991b7 100644 --- a/source/gameengine/PyDoc/KX_TrackToActuator.py +++ b/source/gameengine/PyDoc/KX_TrackToActuator.py @@ -21,7 +21,7 @@ class KX_TrackToActuator(SCA_IActuator): @type object: L{KX_GameObject}, string or None @param object: Either a reference to a game object or the name of the object to track. """ - def getObject(): + def getObject(name_only): """ Returns the name of the object to track. diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index f0e48b6ed43..ebb5332d98d 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -37,6 +37,10 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M # Centre the mouse Rasterizer.setMousePosition(Rasterizer.getWindowWidth()/2, Rasterizer.getWindowHeight()/2) +@group Material Types: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL +@var KX_TEXFACE_MATERIAL: Materials as defined by the texture face settings. +@var KX_BLENDER_MULTITEX_MATERIAL: Materials approximating blender materials with multitexturing. +@var KX_BLENDER_BLENDER_MATERIAL: Materials approximating blender materials with GLSL. """ @@ -84,7 +88,8 @@ def setMousePosition(x, y): """ Sets the mouse cursor position. - @type x, y: integer + @type x: integer + @type y: integer """ def setBackgroundColor(rgba): @@ -145,3 +150,35 @@ def getFocalLength(): @rtype: float """ + +def setMaterialMode(mode): + """ + Set the material mode to use for OpenGL rendering. + + @type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL + @note: Changes will only affect newly created scenes. + """ + +def getMaterialMode(mode): + """ + Get the material mode to use for OpenGL rendering. + + @rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL + """ + +def setGLSLMaterialSetting(setting, enable): + """ + Enables or disables a GLSL material setting. + + @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) + @type enable: boolean + """ + +def getGLSLMaterialSetting(setting, enable): + """ + Get the state of a GLSL material setting. + + @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) + @rtype: boolean + """ + diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py index 46b74f461a7..19df589ea7b 100644 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ b/source/gameengine/PyDoc/SCA_DelaySensor.py @@ -1,6 +1,6 @@ # $Id$ # Documentation for SCA_DelaySensor -from SCA_IActuator import * +from SCA_ISensor import * class SCA_DelaySensor(SCA_ISensor): """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py index 33f0e976284..14858505e24 100644 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ b/source/gameengine/PyDoc/SCA_ISensor.py @@ -9,7 +9,12 @@ class SCA_ISensor(SCA_ILogicBrick): def isPositive(): """ - True if this sensor brick has been activated. + True if this sensor brick is in a positive state. + """ + + def isTriggered(): + """ + True if this sensor brick has triggered the current controller. """ def getUsePosPulseMode(): diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile index e3b1f274ee5..917f70c7108 100644 --- a/source/gameengine/Rasterizer/Makefile +++ b/source/gameengine/Rasterizer/Makefile @@ -49,10 +49,6 @@ ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings endif -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - ############### SOURCEDIR = source/gameengine/Rasterizer diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 82bdce44519..f7938bb62e6 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -26,10 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 // don't show these anoying STL warnings #pragma warning (disable:4786) @@ -39,14 +35,54 @@ #include "RAS_MaterialBucket.h" #include "STR_HashedString.h" #include "RAS_MeshObject.h" -#define KX_NUM_MATERIALBUCKETS 100 #include "RAS_IRasterizer.h" #include "RAS_IRenderTools.h" #include "RAS_BucketManager.h" +#include #include +/* sorting */ + +struct RAS_BucketManager::sortedmeshslot +{ +public: + MT_Scalar m_z; /* depth */ + RAS_MeshSlot *m_ms; /* mesh slot */ + RAS_MaterialBucket *m_bucket; /* buck mesh slot came from */ + + sortedmeshslot() {} + + void set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm) + { + // would be good to use the actual bounding box center instead + MT_Point3 pos(ms->m_OpenGLMatrix[12], ms->m_OpenGLMatrix[13], ms->m_OpenGLMatrix[14]); + + m_z = MT_dot(pnorm, pos); + m_ms = ms; + m_bucket = bucket; + } +}; + +struct RAS_BucketManager::backtofront +{ + bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) + { + return (a.m_z < b.m_z) || (a.m_z == b.m_z && a.m_ms < b.m_ms); + } +}; + +struct RAS_BucketManager::fronttoback +{ + bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) + { + return (a.m_z > b.m_z) || (a.m_z == b.m_z && a.m_ms > b.m_ms); + } +}; + +/* bucket manager */ + RAS_BucketManager::RAS_BucketManager() { @@ -54,153 +90,179 @@ RAS_BucketManager::RAS_BucketManager() RAS_BucketManager::~RAS_BucketManager() { - RAS_BucketManagerClearAll(); + BucketList::iterator it; + + for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) + delete (*it); + + for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) + delete(*it); + + m_SolidBuckets.clear(); + m_AlphaBuckets.clear(); } -/** - * struct alphamesh holds a mesh, (m_ms) it's depth, (m_z) and the bucket it came from (m_bucket.) - */ -struct RAS_BucketManager::alphamesh +void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector& slots, bool alpha) { -public: - MT_Scalar m_z; - RAS_MaterialBucket::T_MeshSlotList::iterator m_ms; - RAS_MaterialBucket *m_bucket; - alphamesh(MT_Scalar z, RAS_MaterialBucket::T_MeshSlotList::iterator &ms, RAS_MaterialBucket *bucket) : - m_z(z), - m_ms(ms), - m_bucket(bucket) - {} -}; + BucketList::iterator bit; + list::iterator mit; + size_t size = 0, i = 0; -struct RAS_BucketManager::backtofront -{ - bool operator()(const alphamesh &a, const alphamesh &b) - { - return a.m_z < b.m_z; - } -}; - + /* Camera's near plane equation: pnorm.dot(point) + pval, + * but we leave out pval since it's constant anyway */ + const MT_Vector3 pnorm(cameratrans.getBasis()[2]); + + for (bit = buckets.begin(); bit != buckets.end(); ++bit) + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + if (!mit->IsCulled()) + size++; + + slots.resize(size); + + for (bit = buckets.begin(); bit != buckets.end(); ++bit) + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + if (!mit->IsCulled()) + slots[i++].set(&*mit, *bit, pnorm); + + if(alpha) + sort(slots.begin(), slots.end(), backtofront()); + else + sort(slots.begin(), slots.end(), fronttoback()); +} void RAS_BucketManager::RenderAlphaBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - BucketList::iterator bit; - std::multiset alphameshset; - RAS_MaterialBucket::T_MeshSlotList::iterator mit; + vector slots; + vector::iterator sit; + + // Having depth masks disabled/enabled gives different artifacts in + // case no sorting is done or is done inexact. For compatibility, we + // disable it. + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); + + OrderBuckets(cameratrans, m_AlphaBuckets, slots, true); - /* Camera's near plane equation: cam_norm.dot(point) + cam_origin */ - const MT_Vector3 cam_norm(cameratrans.getBasis()[2]); - const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; - for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) - { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - { - if ((*mit).m_bVisible) - { - MT_Point3 pos((*mit).m_OpenGLMatrix[12], (*mit).m_OpenGLMatrix[13], (*mit).m_OpenGLMatrix[14]); - alphameshset.insert(alphamesh(MT_dot(cam_norm, pos) + cam_origin, mit, *bit)); - } + for(sit=slots.begin(); sit!=slots.end(); ++sit) { + rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); + + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); + } + + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); +} + +void RAS_BucketManager::RenderSolidBuckets( + const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) +{ + BucketList::iterator bit; + list::iterator mit; + + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if (mit->IsCulled()) + continue; + + rendertools->SetClientObject(rasty, mit->m_clientObj); + + while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) + (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit); } } - // It shouldn't be strictly necessary to disable depth writes; but - // it is needed for compatibility. - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); + /* this code draws meshes order front-to-back instead to reduce overdraw. + * it turned out slower due to much material state switching, a more clever + * algorithm might do better. */ +#if 0 + vector slots; + vector::iterator sit; - RAS_IRasterizer::DrawMode drawingmode; - std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin(); - for (; msit != alphameshset.end(); ++msit) - { - rendertools->SetClientObject((*(*msit).m_ms).m_clientObj); - while ((*msit).m_bucket->ActivateMaterial(cameratrans, rasty, rendertools, drawingmode)) - (*msit).m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(*msit).m_ms, drawingmode); + OrderBuckets(cameratrans, m_SolidBuckets, slots, false); + + for(sit=slots.begin(); sit!=slots.end(); ++sit) { + rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); + + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); } - - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); +#endif } void RAS_BucketManager::Renderbuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - BucketList::iterator bucket; - - rasty->EnableTextures(false); - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); - - // beginning each frame, clear (texture/material) caching information + /* beginning each frame, clear (texture/material) caching information */ rasty->ClearCachingInfo(); - RAS_MaterialBucket::StartFrame(); - - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - (*bucket)->Render(cameratrans,rasty,rendertools); - + RenderSolidBuckets(cameratrans, rasty, rendertools); RenderAlphaBuckets(cameratrans, rasty, rendertools); - RAS_MaterialBucket::EndFrame(); + + rendertools->SetClientObject(rasty, NULL); } RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { - bucketCreated = false; BucketList::iterator it; - for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) - { + + bucketCreated = false; + + for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) if (*(*it)->GetPolyMaterial() == *material) return *it; - } for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - { if (*(*it)->GetPolyMaterial() == *material) return *it; - } RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; + if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else - m_MaterialBuckets.push_back(bucket); + m_SolidBuckets.push_back(bucket); return bucket; } -void RAS_BucketManager::RAS_BucketManagerClearAll() -{ - BucketList::iterator it; - for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) - { - delete (*it); - } - for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - { - delete(*it); - } - - m_MaterialBuckets.clear(); - m_AlphaBuckets.clear(); -} - -void RAS_BucketManager::ReleaseDisplayLists() +void RAS_BucketManager::OptimizeBuckets(MT_Scalar distance) { BucketList::iterator bit; - RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + distance = 10.0; - for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if(mit->m_DisplayList) { - mit->m_DisplayList->Release(); - mit->m_DisplayList = NULL; + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) + (*bit)->Optimize(distance); + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) + (*bit)->Optimize(distance); +} + +void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat) +{ + BucketList::iterator bit; + list::iterator mit; + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } } } } for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if(mit->m_DisplayList) { - mit->m_DisplayList->Release(); - mit->m_DisplayList = NULL; + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } } } } diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 08b67ed022f..74526f365a0 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -39,32 +39,33 @@ class RAS_BucketManager { - //GEN_Map m_MaterialBuckets; - typedef std::vector BucketList; - BucketList m_MaterialBuckets; + BucketList m_SolidBuckets; BucketList m_AlphaBuckets; - struct alphamesh; + struct sortedmeshslot; struct backtofront; + struct fronttoback; public: RAS_BucketManager(); virtual ~RAS_BucketManager(); - void RenderAlphaBuckets(const MT_Transform& cameratrans, - RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); void Renderbuckets(const MT_Transform & cameratrans, - RAS_IRasterizer* rasty, - class RAS_IRenderTools* rendertools); + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + void OptimizeBuckets(MT_Scalar distance); - void ReleaseDisplayLists(); + void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL); private: - void RAS_BucketManagerClearAll(); + void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector& slots, bool alpha); + void RenderSolidBuckets(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); + void RenderAlphaBuckets(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); }; #endif //__RAS_BUCKETMANAGER diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index dcb48c1c2a0..9cb59f300f7 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -108,6 +108,13 @@ public : ) const { return m_frame_type; }; + + void + SetFrameType( + RAS_FrameType type + ) { + m_frame_type = type; + }; float BarRed( @@ -140,14 +147,6 @@ public : }; private : - - /** - * private to force use of public constructor - */ - - RAS_FrameSettings( - const RAS_FrameSettings & - ); RAS_FrameType m_frame_type; float m_bar_r; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 4ee06d96603..fb3607f89f4 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -42,11 +42,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int transp, bool alpha, bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject=NULL) : - - m_texturename(texname), + int lightlayer) + : m_texturename(texname), m_materialname(matname), m_tile(tile), m_tilexrep(tilexrep), @@ -56,7 +53,6 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_alpha(alpha), m_zsort(zsort), m_lightlayer(lightlayer), - m_bIsTriangle(bIsTriangle), m_polymatid(m_newpolymatid++), m_flag(0), m_multimode(0) @@ -72,15 +68,16 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const { if(m_flag &RAS_BLENDERMAT) { - return ( + bool test = ( this->m_multimode == lhs.m_multimode && this->m_flag == lhs.m_flag && this->m_drawingmode == lhs.m_drawingmode && this->m_transp == lhs.m_transp && - this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() ); + + return test; } else { @@ -92,8 +89,6 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && this->m_drawingmode == lhs.m_drawingmode && - this->m_bIsTriangle == lhs.m_bIsTriangle && - this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() ); @@ -123,11 +118,6 @@ bool RAS_IPolyMaterial::IsZSort() const return m_zsort; } -bool RAS_IPolyMaterial::UsesTriangles() const -{ - return m_bIsTriangle; -} - unsigned int RAS_IPolyMaterial::hash() const { return m_texturename.hash(); @@ -172,5 +162,10 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const return dolights; } +bool RAS_IPolyMaterial::UsesObjectColor() const +{ + return !(m_flag & RAS_BLENDERGLSL); +} + unsigned int RAS_IPolyMaterial::m_newpolymatid = 0; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 8fc53e6b038..218dd91cb30 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -71,7 +71,6 @@ protected: bool m_alpha; bool m_zsort; int m_lightlayer; - bool m_bIsTriangle; unsigned int m_polymatid; static unsigned int m_newpolymatid; @@ -106,9 +105,7 @@ public: int transp, bool alpha, bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject); + int lightlayer); virtual ~RAS_IPolyMaterial() {}; /** @@ -129,14 +126,13 @@ public: { return false; } - virtual void ActivateMeshSlot(const class KX_MeshSlot & ms, RAS_IRasterizer* rasty) const {} + virtual void ActivateMeshSlot(const class RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const {} virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; int GetLightLayer() const; bool IsAlpha() const; bool IsZSort() const; - bool UsesTriangles() const; unsigned int hash() const; int GetDrawingMode() const; const STR_String& GetMaterialName() const; @@ -145,6 +141,7 @@ public: const unsigned int GetFlag() const; virtual bool UsesLighting(RAS_IRasterizer *rasty) const; + virtual bool UsesObjectColor() const; /* * PreCalculate texture gen diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 9e03212283e..411b28fa3b7 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -168,6 +168,10 @@ public: * BeginFrame is called at the start of each frame. */ virtual bool BeginFrame(int drawingmode, double time)=0; + /** + * ClearColorBuffer clears the color buffer. + */ + virtual void ClearColorBuffer()=0; /** * ClearDepthBuffer clears the depth buffer. */ @@ -181,7 +185,8 @@ public: */ virtual void EndFrame()=0; /** - * SetRenderArea sets the render area from the 2d canvas + * SetRenderArea sets the render area from the 2d canvas. + * Returns true if only of subset of the canvas is used. */ virtual void SetRenderArea()=0; @@ -195,6 +200,7 @@ public: * @return true if stereo mode is enabled. */ virtual bool Stereo()=0; + virtual bool InterlacedStereo()=0; /** * Sets which eye buffer subsequent primitives will be rendered to. */ @@ -217,39 +223,18 @@ public: // Drawing Functions /** - * IndexPrimitives: Renders primitives. - * @param vertexarrays is an array of vertex arrays - * @param indexarrays is an array of index arrays - * @param mode determines the type of primitive stored in the vertex/index arrays - * @param useObjectColor will render the object using @param rgbacolor instead of - * vertex colors. + * IndexPrimitives: Renders primitives from mesh slot. */ - virtual void IndexPrimitives( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot)=0; - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot)=0; + virtual void IndexPrimitives(class RAS_MeshSlot& ms)=0; + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0; /** * IndexPrimitives_3DText will render text into the polygons. * The text to be rendered is from @param rendertools client object's text property. */ - virtual void IndexPrimitives_3DText( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, + virtual void IndexPrimitives_3DText(class RAS_MeshSlot& ms, class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, - bool useObjectColor, - const MT_Vector4& rgbacolor)=0; + class RAS_IRenderTools* rendertools)=0; virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0; /* This one should become our final version, methinks. */ @@ -269,9 +254,6 @@ public: /** */ virtual const MT_Point3& GetCameraPosition()=0; - /** - */ - virtual void LoadViewMatrix()=0; /** */ virtual void SetFog(float start, @@ -308,9 +290,6 @@ public: * @return the current drawing mode: KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED. */ virtual int GetDrawingMode()=0; - /** - */ - virtual void EnableTextures(bool enable)=0; /** * Sets face culling */ @@ -385,7 +364,9 @@ public: virtual void SetAttribNum(int num) = 0; virtual void SetTexCoord(TexCoGen coords, int unit) = 0; virtual void SetAttrib(TexCoGen coords, int unit) = 0; - virtual void GetViewMatrix(MT_Matrix4x4 &mat) const = 0; + + virtual const MT_Matrix4x4& GetViewMatrix() const = 0; + virtual const MT_Matrix4x4& GetViewInvMatrix() const = 0; virtual bool QueryLists(){return false;} virtual bool QueryArrays(){return false;} @@ -398,6 +379,7 @@ public: virtual void SetMotionBlurState(int newstate)=0; virtual void SetBlendingMode(int blendmode)=0; + virtual void SetFrontFace(bool ccw)=0; }; #endif //__RAS_IRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp index 2be9bb75ebf..555a3520bb4 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp @@ -28,42 +28,22 @@ #include "RAS_IRenderTools.h" -#ifdef HAVE_CONFIG_H -#include -#endif - -void RAS_IRenderTools::SetViewMat(const MT_Transform& trans) -{ - trans.getValue(m_viewmat); -} - - - -void RAS_IRenderTools::SetClientObject(void* obj) +void RAS_IRenderTools::SetClientObject(RAS_IRasterizer* rasty, void *obj) { if (m_clientobject != obj) - { m_clientobject = obj; - m_modified = true; - } } - - void RAS_IRenderTools::SetAuxilaryClientInfo(void* inf) { m_auxilaryClientInfo = inf; } - - void RAS_IRenderTools::AddLight(struct RAS_LightObject* lightobject) { m_lights.push_back(lightobject); } - - void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject) { std::vector::iterator lit = @@ -71,5 +51,5 @@ void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject) if (!(lit==m_lights.end())) m_lights.erase(lit); - } + diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 54a663ba111..57f331e64cb 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -44,12 +44,9 @@ class RAS_IRenderTools { protected: - float m_viewmat[16]; void* m_clientobject; void* m_auxilaryClientInfo; - bool m_modified; - std::vector m_lights; RAS_2DFilterManager m_filtermanager; @@ -68,8 +65,7 @@ public: RAS_IRenderTools( ) : - m_clientobject(NULL), - m_modified(true) + m_clientobject(NULL) { }; @@ -131,24 +127,21 @@ public: float v1[3], float v2[3], float v3[3], - float v4[3] + float v4[3], + int glattrib )=0; virtual - void - SetViewMat( - const MT_Transform& trans - ); - - virtual - int + void ProcessLighting( - int layer + int layer, + const MT_Transform& trans )=0; virtual void SetClientObject( + RAS_IRasterizer* rasty, void* obj ); @@ -190,24 +183,6 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas)=0; - - virtual - class RAS_IPolyMaterial* - CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - void* tface - )=0; }; #endif //__RAS_IRENDERTOOLS diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 0015b6a251f..788af29c4bb 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -28,10 +28,6 @@ #include "RAS_MaterialBucket.h" -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 #pragma warning (disable:4786) #include @@ -44,81 +40,420 @@ #include "RAS_MeshObject.h" #include "RAS_Deformer.h" // __NLA +/* mesh slot */ - -KX_VertexIndex::KX_VertexIndex(int size) +RAS_MeshSlot::RAS_MeshSlot() { - m_size = size; + m_clientObj = NULL; + m_pDeformer = NULL; + m_OpenGLMatrix = NULL; + m_mesh = NULL; + m_bucket = NULL; + m_bVisible = false; + m_bCulled = true; + m_bObjectColor = false; + m_RGBAcolor = MT_Vector4(0.0, 0.0, 0.0, 0.0); + m_DisplayList = NULL; + m_bDisplayList = true; + m_joinSlot = NULL; } - - -void KX_VertexIndex::SetIndex(short loc,unsigned int index) +RAS_MeshSlot::~RAS_MeshSlot() { - m_indexarray[loc]=index; -} + vector::iterator it; -bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const -{ - bool result = ((m_mesh < lhs.m_mesh ) || - ((m_mesh == lhs.m_mesh)&&(m_OpenGLMatrix < lhs.m_OpenGLMatrix))); - - return result; -} + Split(true); -KX_MeshSlot::~KX_MeshSlot() -{ - if (m_DisplayList) + while(m_joinedSlots.size()) + m_joinedSlots.front()->Split(true); + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + (*it)->m_users--; + if((*it)->m_users == 0) + delete *it; + } + + if (m_DisplayList) { m_DisplayList->Release(); + m_DisplayList = NULL; + } } +RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) +{ + vector::iterator it; + + m_clientObj = NULL; + m_pDeformer = NULL; + m_OpenGLMatrix = NULL; + m_mesh = slot.m_mesh; + m_bucket = slot.m_bucket; + m_bVisible = slot.m_bVisible; + m_bCulled = slot.m_bCulled; + m_bObjectColor = slot.m_bObjectColor; + m_RGBAcolor = slot.m_RGBAcolor; + m_DisplayList = NULL; + m_bDisplayList = slot.m_bDisplayList; + m_joinSlot = NULL; + m_currentArray = slot.m_currentArray; + m_displayArrays = slot.m_displayArrays; + m_joinedSlots = slot.m_joinedSlots; + + m_startarray = slot.m_startarray; + m_startvertex = slot.m_startvertex; + m_startindex = slot.m_startindex; + m_endarray = slot.m_endarray; + m_endvertex = slot.m_endvertex; + m_endindex = slot.m_endindex; + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + *it = new RAS_DisplayArray(**it); + (*it)->m_users = 1; + } +} + +void RAS_MeshSlot::init(RAS_MaterialBucket *bucket, int numverts) +{ + m_bucket = bucket; + + SetDisplayArray(numverts); + + m_startarray = 0; + m_startvertex = 0; + m_startindex = 0; + m_endarray = 0; + m_endvertex = 0; + m_endindex = 0; +} + +void RAS_MeshSlot::begin(RAS_MeshSlot::iterator& it) +{ + int startvertex, endvertex; + int startindex, endindex; + + it.array = (m_displayArrays.size() > 0)? m_displayArrays[m_startarray]: NULL; + + if(it.array == NULL || it.array->m_index.size() == 0 || it.array->m_vertex.size() == 0) { + it.array = NULL; + it.vertex = NULL; + it.index = NULL; + it.startvertex = 0; + it.endvertex = 0; + it.totindex = 0; + } + else { + startvertex = m_startvertex; + endvertex = (m_startarray == m_endarray)? m_endvertex: it.array->m_vertex.size(); + startindex = m_startindex; + endindex = (m_startarray == m_endarray)? m_endindex: it.array->m_index.size(); + + it.vertex = &it.array->m_vertex[0]; + it.index = &it.array->m_index[startindex]; + it.startvertex = startvertex; + it.endvertex = endvertex; + it.totindex = endindex-startindex; + it.arraynum = m_startarray; + } +} + +void RAS_MeshSlot::next(RAS_MeshSlot::iterator& it) +{ + int startvertex, endvertex; + int startindex, endindex; + + if(it.arraynum == (size_t)m_endarray) { + it.array = NULL; + it.vertex = NULL; + it.index = NULL; + it.startvertex = 0; + it.endvertex = 0; + it.totindex = 0; + } + else { + it.arraynum++; + it.array = m_displayArrays[it.arraynum]; + + startindex = 0; + endindex = (it.arraynum == (size_t)m_endarray)? m_endindex: it.array->m_index.size(); + startvertex = 0; + endvertex = (it.arraynum == (size_t)m_endarray)? m_endvertex: it.array->m_vertex.size(); + + it.vertex = &it.array->m_vertex[0]; + it.index = &it.array->m_index[startindex]; + it.startvertex = startvertex; + it.endvertex = endvertex; + it.totindex = endindex-startindex; + } +} + +bool RAS_MeshSlot::end(RAS_MeshSlot::iterator& it) +{ + return (it.array == NULL); +} + +RAS_DisplayArray *RAS_MeshSlot::CurrentDisplayArray() +{ + return m_currentArray; +} + +void RAS_MeshSlot::SetDisplayArray(int numverts) +{ + vector::iterator it; + RAS_DisplayArray *darray = NULL; + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + darray = *it; + + if(darray->m_type == numverts) { + if(darray->m_index.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_INDEX) + darray = NULL; + else if(darray->m_vertex.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_VERTEX) + darray = NULL; + else + break; + } + else + darray = NULL; + } + + if(!darray) { + darray = new RAS_DisplayArray(); + darray->m_users = 1; + + if(numverts == 2) darray->m_type = RAS_DisplayArray::LINE; + else if(numverts == 3) darray->m_type = RAS_DisplayArray::TRIANGLE; + else darray->m_type = RAS_DisplayArray::QUAD; + + m_displayArrays.push_back(darray); + + if(numverts == 2) + darray->m_type = RAS_DisplayArray::LINE; + else if(numverts == 3) + darray->m_type = RAS_DisplayArray::TRIANGLE; + else if(numverts == 4) + darray->m_type = RAS_DisplayArray::QUAD; + + m_endarray = m_displayArrays.size()-1; + m_endvertex = 0; + m_endindex = 0; + } + + m_currentArray = darray; +} + +void RAS_MeshSlot::AddPolygon(int numverts) +{ + SetDisplayArray(numverts); +} + +int RAS_MeshSlot::AddVertex(const RAS_TexVert& tv) +{ + RAS_DisplayArray *darray; + int offset; + + darray = m_currentArray; + darray->m_vertex.push_back(tv); + offset = darray->m_vertex.size()-1; + + if(darray == m_displayArrays[m_endarray]) + m_endvertex++; + + return offset; +} + +void RAS_MeshSlot::AddPolygonVertex(int offset) +{ + RAS_DisplayArray *darray; + + darray = m_currentArray; + darray->m_index.push_back(offset); + + if(darray == m_displayArrays[m_endarray]) + m_endindex++; +} + +bool RAS_MeshSlot::Equals(RAS_MeshSlot *target) +{ + if(!m_OpenGLMatrix || !target->m_OpenGLMatrix) + return false; + if(m_pDeformer || target->m_pDeformer) + return false; + if(m_bVisible != target->m_bVisible) + return false; + if(m_bObjectColor != target->m_bObjectColor) + return false; + if(m_bObjectColor && !(m_RGBAcolor == target->m_RGBAcolor)) + return false; + + return true; +} + +bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance) +{ + vector::iterator it; + iterator mit; + size_t i; + + // verify if we can join + if(m_joinSlot || m_joinedSlots.size() || target->m_joinSlot) + return false; + + if(!Equals(target)) + return false; + + MT_Vector3 co(&m_OpenGLMatrix[12]); + MT_Vector3 targetco(&target->m_OpenGLMatrix[12]); + + if((co - targetco).length() > distance) + return false; + + MT_Matrix4x4 mat(m_OpenGLMatrix); + MT_Matrix4x4 targetmat(target->m_OpenGLMatrix); + targetmat.invert(); + + MT_Matrix4x4 transform = targetmat*mat; + + // m_mesh, clientobj + m_joinSlot = target; + m_joinInvTransform = transform; + m_joinInvTransform.invert(); + target->m_joinedSlots.push_back(this); + + MT_Matrix4x4 ntransform = m_joinInvTransform.transposed(); + ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; + + for(begin(mit); !end(mit); next(mit)) + for(i=mit.startvertex; im_displayArrays.push_back(*it); + target->m_endarray++; + target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); + target->m_endindex = target->m_displayArrays.back()->m_index.size(); + } + + if (m_DisplayList) { + m_DisplayList->Release(); + m_DisplayList = NULL; + } + if (target->m_DisplayList) { + target->m_DisplayList->Release(); + target->m_DisplayList = NULL; + } + + return true; +#if 0 + return false; +#endif +} + +bool RAS_MeshSlot::Split(bool force) +{ + list::iterator jit; + RAS_MeshSlot *target = m_joinSlot; + vector::iterator it, jt; + iterator mit; + size_t i, found0 = 0, found1 = 0; + + if(target && (force || !Equals(target))) { + m_joinSlot = NULL; + + for(jit=target->m_joinedSlots.begin(); jit!=target->m_joinedSlots.end(); jit++) { + if(*jit == this) { + target->m_joinedSlots.erase(jit); + found0 = 1; + break; + } + } + + if(!found0) + abort(); + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + found1 = 0; + for(jt=target->m_displayArrays.begin(); jt!=target->m_displayArrays.end(); jt++) { + if(*jt == *it) { + target->m_displayArrays.erase(jt); + target->m_endarray--; + found1 = 1; + break; + } + } + + if(!found1) + abort(); + } + + if(target->m_displayArrays.size()) { + target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); + target->m_endindex = target->m_displayArrays.back()->m_index.size(); + } + else { + target->m_endvertex = 0; + target->m_endindex = 0; + } + + MT_Matrix4x4 ntransform = m_joinInvTransform.inverse().transposed(); + ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; + + for(begin(mit); !end(mit); next(mit)) + for(i=mit.startvertex; im_DisplayList) { + target->m_DisplayList->Release(); + target->m_DisplayList = NULL; + } + + return true; + } + + return false; +} + +bool RAS_MeshSlot::IsCulled() +{ + list::iterator it; + + if(m_joinSlot) + return true; + if(!m_bCulled) + return false; + + for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++) + if(!(*it)->m_bCulled) + return false; + + return true; +} + +/* material bucket sorting */ + +struct RAS_MaterialBucket::less +{ + bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const + { + return *x->GetPolyMaterial() < *y->GetPolyMaterial(); + } +}; + +/* material bucket */ RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) - :m_bModified(true) { m_material = mat; } - +RAS_MaterialBucket::~RAS_MaterialBucket() +{ +} RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const { return m_material; } - - -void RAS_MaterialBucket::SetMeshSlot(KX_MeshSlot& ms) -{ - m_meshSlots.insert(ms); -} - - - -void RAS_MaterialBucket::RemoveMeshSlot(KX_MeshSlot& ms) -{ - T_MeshSlotList::iterator it = m_meshSlots.find(ms); - - if (!(it == m_meshSlots.end())) - m_meshSlots.erase(it); - -} - - - -void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms, - bool visible, - bool color, - const MT_Vector4& rgbavec) -{ - T_MeshSlotList::iterator it = m_meshSlots.find(ms); - - assert (!(it == m_meshSlots.end())); - (*it).m_bVisible = visible; - (*it).m_bObjectColor = color; - (*it).m_RGBAcolor= rgbavec; -} - bool RAS_MaterialBucket::IsAlpha() const { return (m_material->IsAlpha()); @@ -129,162 +464,129 @@ bool RAS_MaterialBucket::IsZSort() const return (m_material->IsZSort()); } - - -void RAS_MaterialBucket::StartFrame() +RAS_MeshSlot* RAS_MaterialBucket::AddMesh(int numverts) { + RAS_MeshSlot *ms; + + m_meshSlots.push_back(RAS_MeshSlot()); + + ms = &m_meshSlots.back(); + ms->init(this, numverts); + + return ms; } - - -void RAS_MaterialBucket::EndFrame() +RAS_MeshSlot* RAS_MaterialBucket::CopyMesh(RAS_MeshSlot *ms) { + m_meshSlots.push_back(RAS_MeshSlot(*ms)); + + return &m_meshSlots.back(); } -unsigned int RAS_MaterialBucket::NumMeshSlots() +void RAS_MaterialBucket::RemoveMesh(RAS_MeshSlot* ms) { - return m_meshSlots.size(); + list::iterator it; + + for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) { + if(&*it == ms) { + m_meshSlots.erase(it); + return; + } + } } -RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin() +list::iterator RAS_MaterialBucket::msBegin() { return m_meshSlots.begin(); } -RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd() +list::iterator RAS_MaterialBucket::msEnd() { return m_meshSlots.end(); } bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode &drawmode) + RAS_IRenderTools *rendertools) { - rendertools->SetViewMat(cameratrans); - if (!rasty->SetMaterial(*m_material)) return false; if (m_material->UsesLighting(rasty)) - rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*m_material->GetLightLayer()*/); + rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); else - rendertools->ProcessLighting(-1); - - if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) - drawmode = RAS_IRasterizer::KX_MODE_LINES; - else if(m_material->UsesTriangles()) - drawmode = RAS_IRasterizer::KX_MODE_TRIANGLES; - else - drawmode = RAS_IRasterizer::KX_MODE_QUADS; + rendertools->ProcessLighting(-1, cameratrans); return true; } void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode) + RAS_IRenderTools* rendertools, RAS_MeshSlot &ms) { - if (!ms.m_bVisible) - return; - m_material->ActivateMeshSlot(ms, rasty); - /* __NLA Do the deformation */ if (ms.m_pDeformer) { ms.m_pDeformer->Apply(m_material); // KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_) } - /* End __NLA */ - if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix)); + if(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) + ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix)); rendertools->PushMatrix(); rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); if(rasty->QueryLists()) - { if(ms.m_DisplayList) ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified()); - } // verify if we can use display list, not for deformed object, and // also don't create a new display list when drawing shadow buffers, - // then it won't have texture coordinates for actual drawing - KX_ListSlot **displaylist; + // then it won't have texture coordinates for actual drawing. also + // for zsort we can't make a display list, since the polygon order + // changes all the time. if(ms.m_pDeformer) - displaylist = 0; + ms.m_bDisplayList = false; else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) - displaylist = 0; + ms.m_bDisplayList = false; + else if (IsZSort()) + ms.m_bDisplayList = false; + else if(m_material->UsesObjectColor() && ms.m_bObjectColor) + ms.m_bDisplayList = false; else - displaylist = &ms.m_DisplayList; + ms.m_bDisplayList = true; - // Use the text-specific IndexPrimitives for text faces + // for text drawing using faces if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) - { - rasty->IndexPrimitives_3DText( - ms.m_mesh->GetVertexCache(m_material), - ms.m_mesh->GetIndexCache(m_material), - drawmode, - m_material, - rendertools, // needed for textprinting on polys - ms.m_bObjectColor, - ms.m_RGBAcolor); - } - - // for using glMultiTexCoord - else if((m_material->GetFlag() & RAS_MULTITEX)) - { - rasty->IndexPrimitivesMulti( - ms.m_mesh->GetVertexCache(m_material), - ms.m_mesh->GetIndexCache(m_material), - drawmode, - ms.m_bObjectColor, - ms.m_RGBAcolor, - displaylist); - } - - // Use the normal IndexPrimitives + rasty->IndexPrimitives_3DText(ms, m_material, rendertools); + // for multitexturing + else if((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL))) + rasty->IndexPrimitivesMulti(ms); + // use normal IndexPrimitives else - { - rasty->IndexPrimitives( - ms.m_mesh->GetVertexCache(m_material), - ms.m_mesh->GetIndexCache(m_material), - drawmode, - ms.m_bObjectColor, - ms.m_RGBAcolor, - displaylist); - } + rasty->IndexPrimitives(ms); - if(rasty->QueryLists()) { + if(rasty->QueryLists()) if(ms.m_DisplayList) ms.m_mesh->SetMeshModified(false); - } rendertools->PopMatrix(); } -void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, - RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools) +void RAS_MaterialBucket::Optimize(MT_Scalar distance) { - if (m_meshSlots.begin()== m_meshSlots.end()) - return; - - //rendertools->SetViewMat(cameratrans); - - //rasty->SetMaterial(*m_material); + /* TODO: still have to check before this works correct: + * - lightlayer, frontface, text, billboard + * - make it work with physics */ - RAS_IRasterizer::DrawMode drawmode; - for (T_MeshSlotList::const_iterator it = m_meshSlots.begin(); - ! (it == m_meshSlots.end()); ++it) - { - rendertools->SetClientObject((*it).m_clientObj); - while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode)) { - RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode); - } - } - // to reset the eventual GL_CW mode - rendertools->SetClientObject(NULL); +#if 0 + list::iterator it; + list::iterator jt; + + // greed joining on all following buckets + for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) + for(jt=it, jt++; jt!=m_meshSlots.end(); jt++) + jt->Join(&*it, distance); +#endif } - diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 4eef889c533..475f01d549a 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -36,30 +36,15 @@ #include "MT_Transform.h" #include "RAS_IPolygonMaterial.h" #include "RAS_IRasterizer.h" -#include "RAS_Deformer.h" // __NLA +#include "RAS_Deformer.h" + #include -#include #include +#include using namespace std; -/** - * KX_VertexIndex - */ -struct KX_VertexIndex { -public: - KX_VertexIndex(int size); - void SetIndex(short loc,unsigned int index); - - // The vertex array - short m_vtxarray; - // An index into the vertex array for up to 4 verticies - unsigned short m_indexarray[4]; - short m_size; -}; +/* Display List Slot */ -/** - * KX_ListSlot. - */ class KX_ListSlot { protected: @@ -80,91 +65,149 @@ public: virtual void SetModified(bool mod)=0; }; -/** - * KX_MeshSlot. - */ -class KX_MeshSlot +class RAS_DisplayArray; +class RAS_MeshSlot; +class RAS_MeshMaterial; +class RAS_MaterialBucket; + +/* An array with data used for OpenGL drawing */ + +class RAS_DisplayArray { public: - void* m_clientObj; - RAS_Deformer* m_pDeformer; // __NLA - double* m_OpenGLMatrix; - class RAS_MeshObject* m_mesh; - mutable bool m_bVisible; // for visibility - mutable bool m_bObjectColor; - mutable MT_Vector4 m_RGBAcolor; - mutable KX_ListSlot* m_DisplayList; // for lists - KX_MeshSlot() : - m_pDeformer(NULL), - m_bVisible(true), - m_DisplayList(0) - { - } - ~KX_MeshSlot(); - bool Less(const KX_MeshSlot& lhs) const; + vector m_vertex; + vector m_index; + enum { LINE = 2, TRIANGLE = 3, QUAD = 4 } m_type; + //RAS_MeshSlot *m_origSlot; + int m_users; + + enum { BUCKET_MAX_INDEX = 65535 }; + enum { BUCKET_MAX_VERTEX = 65535 }; }; +/* Entry of a RAS_MeshObject into RAS_MaterialBucket */ -inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs) +class RAS_MeshSlot { - return ( rhs.Less(lhs)); -} +private: + // indices into display arrays + int m_startarray; + int m_endarray; + int m_startindex; + int m_endindex; + int m_startvertex; + int m_endvertex; + vector m_displayArrays; + + // for construction only + RAS_DisplayArray* m_currentArray; + +public: + // for rendering + RAS_MaterialBucket* m_bucket; + RAS_MeshObject* m_mesh; + void* m_clientObj; + RAS_Deformer* m_pDeformer; + double* m_OpenGLMatrix; + // visibility + bool m_bVisible; + bool m_bCulled; + // object color + bool m_bObjectColor; + MT_Vector4 m_RGBAcolor; + // display lists + KX_ListSlot* m_DisplayList; + bool m_bDisplayList; + // joined mesh slots + RAS_MeshSlot* m_joinSlot; + MT_Matrix4x4 m_joinInvTransform; + list m_joinedSlots; + + RAS_MeshSlot(); + RAS_MeshSlot(const RAS_MeshSlot& slot); + virtual ~RAS_MeshSlot(); + + void init(RAS_MaterialBucket *bucket, int numverts); + + struct iterator { + RAS_DisplayArray *array; + RAS_TexVert *vertex; + unsigned short *index; + size_t startvertex; + size_t endvertex; + size_t totindex; + size_t arraynum; + }; + + void begin(iterator& it); + void next(iterator& it); + bool end(iterator& it); + + /* used during construction */ + void SetDisplayArray(int numverts); + RAS_DisplayArray *CurrentDisplayArray(); + + void AddPolygon(int numverts); + int AddVertex(const RAS_TexVert& tv); + void AddPolygonVertex(int offset); + + /* optimization */ + bool Split(bool force=false); + bool Join(RAS_MeshSlot *target, MT_Scalar distance); + bool Equals(RAS_MeshSlot *target); + bool IsCulled(); +}; + +/* Used by RAS_MeshObject, to point to it's slots in a bucket */ + +class RAS_MeshMaterial +{ +public: + RAS_MeshSlot *m_baseslot; + class RAS_MaterialBucket *m_bucket; + + GEN_Map m_slots; +}; + +/* Contains a list of display arrays with the same material, + * and a mesh slot for each mesh that uses display arrays in + * this bucket */ -/** - * Contains a list of meshs with the same material properties. - */ class RAS_MaterialBucket { public: - typedef std::set T_MeshSlotList; - RAS_MaterialBucket(RAS_IPolyMaterial* mat); - virtual ~RAS_MaterialBucket() {} - - void Render(const MT_Transform& cameratrans, - class RAS_IRasterizer* rasty, - class RAS_IRenderTools* rendertools); - - RAS_IPolyMaterial* GetPolyMaterial() const; - bool IsAlpha() const; - bool IsZSort() const; - - static void StartFrame(); - static void EndFrame(); - - void SetMeshSlot(KX_MeshSlot& ms); - void RemoveMeshSlot(KX_MeshSlot& ms); - void MarkVisibleMeshSlot(KX_MeshSlot& ms, - bool visible, - bool color, - const MT_Vector4& rgbavec); - - void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode); - bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode& drawmode); - - unsigned int NumMeshSlots(); - T_MeshSlotList::iterator msBegin(); - T_MeshSlotList::iterator msEnd(); - - struct less - { - bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const - { - return *x->GetPolyMaterial() < *y->GetPolyMaterial(); - } - }; + virtual ~RAS_MaterialBucket(); + /* Bucket Sorting */ + struct less; typedef set Set; -private: + + /* Material Properties */ + RAS_IPolyMaterial* GetPolyMaterial() const; + bool IsAlpha() const; + bool IsZSort() const; + + /* Rendering */ + bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools *rendertools); + void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools* rendertools, RAS_MeshSlot &ms); - T_MeshSlotList m_meshSlots; - bool m_bModified; + /* Mesh Slot Access */ + list::iterator msBegin(); + list::iterator msEnd(); + + class RAS_MeshSlot* AddMesh(int numverts); + class RAS_MeshSlot* CopyMesh(class RAS_MeshSlot *ms); + void RemoveMesh(class RAS_MeshSlot* ms); + void Optimize(MT_Scalar distance); + +private: + list m_meshSlots; RAS_IPolyMaterial* m_material; - double* m_pOGLMatrix; }; -#endif //__KX_BUCKET +#endif //__RAS_MATERIAL_BUCKET diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index af5228e4c35..a907994bf57 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -26,10 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include -#endif - #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "MT_MinMax.h" @@ -37,544 +33,7 @@ #include - -STR_String RAS_MeshObject::s_emptyname = ""; - - - -KX_ArrayOptimizer::~KX_ArrayOptimizer() -{ - for (vector::iterator itv = m_VertexArrayCache1.begin(); - !(itv == m_VertexArrayCache1.end());++itv) - { - delete (*itv); - } - - for (vector::iterator iti = m_IndexArrayCache1.begin(); - !(iti == m_IndexArrayCache1.end());++iti) - { - delete (*iti); - } - - m_TriangleArrayCount.clear(); - m_VertexArrayCache1.clear(); - m_IndexArrayCache1.clear(); - - -} - - - -RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) - : m_bModified(true), - m_lightlayer(lightlayer), - m_zsort(false), - m_MeshMod(true), - m_mesh(mesh), - m_class(0) -{ -} - - -bool RAS_MeshObject::MeshModified() -{ - return m_MeshMod; -} - - -RAS_MeshObject::~RAS_MeshObject() -{ - for (vector::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++) - { - delete (*it); - } - - ClearArrayData(); -} - - - -unsigned int RAS_MeshObject::GetLightLayer() -{ - return m_lightlayer; -} - - - -int RAS_MeshObject::NumMaterials() -{ - return m_materials.size(); -} - -const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) -{ - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); - - return bucket?bucket->GetPolyMaterial()->GetMaterialName():s_emptyname; -} - -RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(unsigned int matid) -{ - if (m_materials.size() > 0 && (matid < m_materials.size())) - { - RAS_MaterialBucket::Set::const_iterator it = m_materials.begin(); - while (matid--) ++it; - return *it; - } - - return NULL; -} - - - -int RAS_MeshObject::NumPolygons() -{ - return m_Polygons.size(); -} - - - -RAS_Polygon* RAS_MeshObject::GetPolygon(int num) -{ - return m_Polygons[num]; -} - - - -RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetFirstMaterial() -{ - return m_materials.begin(); -} - - - -RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetLastMaterial() -{ - return m_materials.end(); -} - - - -void RAS_MeshObject::SetName(STR_String name) -{ - m_name = name; -} - - - -const STR_String& RAS_MeshObject::GetName() -{ - return m_name; -} - - - -const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) -{ - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); - - return bucket?bucket->GetPolyMaterial()->GetTextureName():s_emptyname; -} - - - -void RAS_MeshObject::AddPolygon(RAS_Polygon* poly) -{ - m_Polygons.push_back(poly); -} - - - -void RAS_MeshObject::DebugColor(unsigned int abgr) -{ -/* - int numpolys = NumPolygons(); - for (int i=0;iVertexCount();v++) - { - RAS_TexVert* vtx = poly->GetVertex(v); - vtx->setDebugRGBA(abgr); - } - } - */ - - m_debugcolor = abgr; -} - -void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) -{ - const vecVertexArray & vertexvec = GetVertexCache(mat); - - for (vector::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) - { - KX_VertexArray::iterator vit; - for (vit=(*it)->begin(); vit != (*it)->end(); vit++) - { - vit->SetRGBA(rgba); - } - } -} - -void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); - - if (!mat->UsesTriangles()) - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); -} - - -void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat) -{ - //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; - int edgetrace = 1<<(numverts-1); - bool drawedge = (edgecode & edgetrace)!=0; - edgetrace = 1; - int prevvert = idx.m_indexarray[numverts-1]; - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - for (int v = 0; v < numverts; v++) - { - unsigned int curvert = idx.m_indexarray[v]; - if (drawedge) - { - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(prevvert); - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(curvert); - } - prevvert = curvert; - drawedge = (edgecode & edgetrace)!=0; - edgetrace*=2; - } - //m_IndexArrayCount[idx.m_vtxarray] = indexpos; -} - -int RAS_MeshObject::FindOrAddVertex(int vtxarray, - const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, - const MT_Vector4& tangent, - const unsigned int rgbacolor, - const MT_Vector3& normal, - bool flat, - RAS_IPolyMaterial* mat, - int origindex) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray]; - RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0,origindex); - -#define KX_FIND_SHARED_VERTICES -#ifdef KX_FIND_SHARED_VERTICES - if(!flat) { - for (std::vector::iterator it = m_xyz_index_to_vertex_index_mapping[origindex].begin(); - it != m_xyz_index_to_vertex_index_mapping[origindex].end(); - it++) - { - if ((*it).m_arrayindex1 == ao->m_index1 && - (*it).m_array == vtxarray && - *(*it).m_matid == *mat && - (*ao->m_VertexArrayCache1[vtxarray])[(*it).m_index].closeTo(&newvert) - ) - { - return (*it).m_index; - } - } - } -#endif // KX_FIND_SHARED_VERTICES - - // no vertex found, add one - ao->m_VertexArrayCache1[vtxarray]->push_back(newvert); - // printf("(%f,%f,%f) ",xyz[0],xyz[1],xyz[2]); - RAS_MatArrayIndex idx; - idx.m_arrayindex1 = ao->m_index1; - idx.m_array = vtxarray; - idx.m_index = numverts; - idx.m_matid = mat; - m_xyz_index_to_vertex_index_mapping[origindex].push_back(idx); - - return numverts; -} - -vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - return ao->m_VertexArrayCache1; -} - -int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat) -{ - int len = 0; - - const vecVertexArray & vertexvec = GetVertexCache(mat); - vector::const_iterator it = vertexvec.begin(); - - for (; it != vertexvec.end(); ++it) - { - len += (*it)->size(); - } - - return len; -} - - - -RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, - unsigned int index) -{ - RAS_TexVert* vertex = NULL; - - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); - if (bucket) - { - RAS_IPolyMaterial* mat = bucket->GetPolyMaterial(); - if (mat) - { - const vecVertexArray & vertexvec = GetVertexCache(mat); - vector::const_iterator it = vertexvec.begin(); - - for (unsigned int len = 0; it != vertexvec.end(); ++it) - { - if (index < len + (*it)->size()) - { - vertex = &(*(*it))[index-len]; - break; - } - else - { - len += (*it)->size(); - } - } - } - } - - return vertex; -} - - - -const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - return ao->m_IndexArrayCache1; -} - - - -KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat) -{ - KX_ArrayOptimizer** aop = m_matVertexArrayS[polymat]; - - if(aop) - return *aop; - - // didn't find array, but an array might already exist - // for a material equal to this one - for(int i=0;igetValue()); - if(*mat == *polymat) { - m_matVertexArrayS.insert(polymat, *m_matVertexArrayS.at(i)); - return *m_matVertexArrayS.at(i); - } - } - - // create new array - int numelements = m_matVertexArrayS.size(); - m_sortedMaterials.push_back(polymat); - - KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements); - m_matVertexArrayS.insert(polymat, ao); - - return ao; -} - - - -void RAS_MeshObject::Bucketize(double* oglmatrix, - void* clientobj, - bool useObjectColor, - const MT_Vector4& rgbavec) -{ - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_bObjectColor = useObjectColor; - ms.m_RGBAcolor = rgbavec; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; -// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); - bucket->SetMeshSlot(ms); - } - -} - - - -void RAS_MeshObject::MarkVisible(double* oglmatrix, - void* clientobj, - bool visible, - bool useObjectColor, - const MT_Vector4& rgbavec) -{ - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_RGBAcolor = rgbavec; - ms.m_bObjectColor= useObjectColor; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; -// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); - bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); - } -} - - -void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, - void* clientobj) -{ - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; -// RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); - //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); - bucket->RemoveMeshSlot(ms); - } - -} - - - -/* - * RAS_MeshObject::GetVertex returns the vertex located somewhere in the vertexpool - * it is the clients responsibility to make sure the array and index are valid - */ -RAS_TexVert* RAS_MeshObject::GetVertex(short array, - unsigned int index, - RAS_IPolyMaterial* polymat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat); - return &((*(ao->m_VertexArrayCache1)[array])[index]); -} - - - -void RAS_MeshObject::ClearArrayData() -{ - for (int i=0;im_VertexArrayCache1.size();i++) - { - if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES) - { - if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES)) - { - array = i; - ao->m_TriangleArrayCount[array]+=numverts-2; - break; - } - } - } - - if (array == -1) - { - array = ao->m_VertexArrayCache1.size(); - vector* va = new vector; - ao->m_VertexArrayCache1.push_back(va); - KX_IndexArray *ia = new KX_IndexArray(); - ao->m_IndexArrayCache1.push_back(ia); - ao->m_TriangleArrayCount.push_back(numverts-2); - } - - return array; -} - - - - -//void RAS_MeshObject::Transform(const MT_Transform& trans) -//{ - //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); - -// for (int i=0;iTransform(trans); -// } -//} - - -/* -void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) -{ - for (int i=0;iRelativeTransform(vec); - } -} -*/ - - - -void RAS_MeshObject::UpdateMaterialList() -{ - m_materials.clear(); - unsigned int numpolys = m_Polygons.size(); - // for all polygons, find out which material they use, and add it to the set of materials - for (unsigned int i=0;iGetMaterial()); - } -} +/* polygon sorting */ struct RAS_MeshObject::polygonSlot { @@ -585,7 +44,7 @@ struct RAS_MeshObject::polygonSlot /* pnorm is the normal from the plane equation that the distance from is * used to sort again. */ - void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray, + void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray, int offset, int nvert, const MT_Vector3& pnorm) { MT_Vector3 center(0, 0, 0); @@ -593,7 +52,7 @@ struct RAS_MeshObject::polygonSlot for(i=0; i::iterator it; + + for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++) + delete (*it); +} + +bool RAS_MeshObject::MeshModified() +{ + return m_bMeshModified; +} + +unsigned int RAS_MeshObject::GetLightLayer() +{ + return m_lightlayer; +} + + + +int RAS_MeshObject::NumMaterials() +{ + return m_materials.size(); +} + +const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) +{ + RAS_MeshMaterial* mmat = GetMeshMaterial(matid); + + if(mmat) + return mmat->m_bucket->GetPolyMaterial()->GetMaterialName(); + + return s_emptyname; +} + +RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid) +{ + if (m_materials.size() > 0 && (matid < m_materials.size())) + { + list::iterator it = m_materials.begin(); + while (matid--) ++it; + return &*it; + } + + return NULL; +} + + + +int RAS_MeshObject::NumPolygons() +{ + return m_Polygons.size(); +} + + + +RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const +{ + return m_Polygons[num]; +} + + + + + list::iterator GetFirstMaterial(); + list::iterator GetLastMaterial(); +list::iterator RAS_MeshObject::GetFirstMaterial() +{ + return m_materials.begin(); +} + + + +list::iterator RAS_MeshObject::GetLastMaterial() +{ + return m_materials.end(); +} + + + +void RAS_MeshObject::SetName(STR_String name) +{ + m_name = name; +} + + + +const STR_String& RAS_MeshObject::GetName() +{ + return m_name; +} + + + +const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) +{ + RAS_MeshMaterial* mmat = GetMeshMaterial(matid); + + if(mmat) + return mmat->m_bucket->GetPolyMaterial()->GetTextureName(); + + return s_emptyname; +} + +RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat) +{ + list::iterator mit; + + /* find a mesh material */ + for(mit = m_materials.begin(); mit != m_materials.end(); mit++) + if(mit->m_bucket->GetPolyMaterial() == mat) + return &*mit; + + return NULL; +} + +RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts) +{ + RAS_MeshMaterial *mmat; + RAS_Polygon *poly; + RAS_MeshSlot *slot; + + /* find a mesh material */ + mmat = GetMeshMaterial(bucket->GetPolyMaterial()); + + /* none found, create a new one */ + if(!mmat) { + RAS_MeshMaterial meshmat; + meshmat.m_bucket = bucket; + meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts); + m_materials.push_back(meshmat); + mmat = &m_materials.back(); + } + + /* add it to the bucket, this also adds new display arrays */ + slot = mmat->m_baseslot; + slot->AddPolygon(numverts); + + /* create a new polygon */ + RAS_DisplayArray *darray = slot->CurrentDisplayArray(); + poly = new RAS_Polygon(bucket, darray, numverts); + m_Polygons.push_back(poly); + + return poly; +} + +void RAS_MeshObject::DebugColor(unsigned int abgr) +{ + /*int numpolys = NumPolygons(); + + for (int i=0;iVertexCount();v++) + RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr); + } + */ + + /* m_debugcolor = abgr; */ +} + +void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) +{ + RAS_MeshMaterial *mmat = GetMeshMaterial(mat); + RAS_MeshSlot *slot = mmat->m_baseslot; + RAS_MeshSlot::iterator it; + size_t i; + + for(slot->begin(it); !slot->end(it); slot->next(it)) + for(i=it.startvertex; iGetMaterial()->GetPolyMaterial()); + slot = mmat->m_baseslot; + darray = slot->CurrentDisplayArray(); + + if(!flat) { + /* find vertices shared between faces, with the restriction + * that they exist in the same display array, and have the + * same uv coordinate etc */ + vector& sharedmap = m_sharedvertex_map[origindex]; + vector::iterator it; + + for(it = sharedmap.begin(); it != sharedmap.end(); it++) + { + if(it->m_darray != darray) + continue; + if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert)) + continue; + + /* found one, add it and we're done */ + if(poly->IsVisible()) + slot->AddPolygonVertex(it->m_offset); + poly->SetVertexOffset(i, it->m_offset); + return; + } + } + + /* no shared vertex found, add a new one */ + offset = slot->AddVertex(texvert); + if(poly->IsVisible()) + slot->AddPolygonVertex(offset); + poly->SetVertexOffset(i, offset); + + if(!flat) { + SharedVertex shared; + shared.m_darray = darray; + shared.m_offset = offset; + m_sharedvertex_map[origindex].push_back(shared); + } +} + +int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat) +{ + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + RAS_MeshSlot::iterator it; + size_t len = 0; + + mmat = GetMeshMaterial(mat); + slot = mmat->m_baseslot; + for(slot->begin(it); !slot->end(it); slot->next(it)) + len += it.endvertex - it.startvertex; + + return len; +} + + +RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, + unsigned int index) +{ + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + RAS_MeshSlot::iterator it; + size_t len; + + mmat = GetMeshMaterial(matid); + + if(!mmat) + return NULL; + + slot = mmat->m_baseslot; + len = 0; + for(slot->begin(it); !slot->end(it); slot->next(it)) { + if(index >= len + it.endvertex - it.startvertex) + len += it.endvertex - it.startvertex; + else + return &it.vertex[index - len]; + } + + return NULL; +} + +void RAS_MeshObject::AddMeshUser(void *clientobj) +{ + list::iterator it; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + /* always copy from the base slot, which is never removed + * since new objects can be created with the same mesh data */ + RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot); + ms->m_clientObj = clientobj; + it->m_slots.insert(clientobj, ms); + } +} + +void RAS_MeshObject::UpdateBuckets(void* clientobj, + double* oglmatrix, + bool useObjectColor, + const MT_Vector4& rgbavec, + bool visible, + bool culled) +{ + list::iterator it; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + RAS_MeshSlot **msp = it->m_slots[clientobj]; + + if(!msp) + continue; + + RAS_MeshSlot *ms = *msp; + + ms->m_mesh = this; + ms->m_OpenGLMatrix = oglmatrix; + ms->m_bObjectColor = useObjectColor; + ms->m_RGBAcolor = rgbavec; + ms->m_bVisible = visible; + ms->m_bCulled = culled || !visible; + + /* split if necessary */ + ms->Split(); + } +} + +void RAS_MeshObject::RemoveFromBuckets(void *clientobj) +{ + list::iterator it; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + RAS_MeshSlot **msp = it->m_slots[clientobj]; + + if(!msp) + continue; + + RAS_MeshSlot *ms = *msp; + + it->m_bucket->RemoveMesh(ms); + it->m_slots.remove(clientobj); + } +} + +//void RAS_MeshObject::Transform(const MT_Transform& trans) +//{ + //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); + +// for (int i=0;iTransform(trans); +// } +//} + + +/* +void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) +{ + for (int i=0;iRelativeTransform(vec); + } +} +*/ + +void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform) { // Limitations: sorting is quite simple, and handles many // cases wrong, partially due to polygons being sorted per @@ -645,43 +466,34 @@ void RAS_MeshObject::SortPolygons(const MT_Transform &transform) // to avoid excessive state changes while drawing. e) would // require splitting polygons. - if (!m_zsort) - return; + RAS_MeshSlot::iterator it; + size_t j; - // Extract camera Z plane... - const MT_Vector3 pnorm(transform.getBasis()[2]); - // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + for(ms.begin(it); !ms.end(it); ms.next(it)) { + unsigned int nvert = (int)it.array->m_type; + unsigned int totpoly = it.totindex/nvert; - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - if(!(*it)->IsZSort()) + if(totpoly <= 1) + continue; + if(it.array->m_type == RAS_DisplayArray::LINE) continue; - RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial(); - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + // Extract camera Z plane... + const MT_Vector3 pnorm(transform.getBasis()[2]); + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; - vecIndexArrays& indexarrays = ao->m_IndexArrayCache1; - vecVertexArray& vertexarrays = ao->m_VertexArrayCache1; - unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4; + vector slots(totpoly); - for(i=0; i slots(totpoly); + /* sort (stable_sort might be better, if flickering happens?) */ + std::sort(slots.begin(), slots.end(), backtofront()); - /* get indices and z into temporary array */ - for(j=0; jIsZSort()) - m_zsort = true; - - if (drawingmode == RAS_IRasterizer::KX_WIREFRAME) - { - for (i=0;iIsVisible()) - ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(), - poly->GetMaterial()->GetPolyMaterial()); - - } - m_zsort = false; - } - else - { - for (i=0;iIsVisible()) - SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(), - poly->GetMaterial()->GetPolyMaterial()); - } - } - m_bModified = false; - m_MeshMod = true; + m_bMeshModified = true; } } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 99806666fa6..0d35a2f402b 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -36,6 +36,7 @@ #include #include +#include #include "RAS_Polygon.h" #include "RAS_MaterialBucket.h" @@ -44,194 +45,71 @@ #include "GEN_HashedPtr.h" struct Mesh; -/** - * This class holds an array of vertices and indicies. - */ -class KX_ArrayOptimizer -{ -public: - KX_ArrayOptimizer(int index) - : m_index1(index) - {}; - virtual ~KX_ArrayOptimizer(); - - vector m_VertexArrayCache1; - vector m_TriangleArrayCount; - vector m_IndexArrayCache1; - /** - order in which they are stored into the mesh - */ - int m_index1; -}; +/* RAS_MeshObject is a mesh used for rendering. It stores polygons, + * but the actual vertices and index arrays are stored in material + * buckets, referenced by the list of RAS_MeshMaterials. */ -/** - * This struct holds a triangle. - */ -struct RAS_TriangleIndex -{ -public: - int m_index[3]; - int m_array; - RAS_IPolyMaterial* m_matid; - bool m_collider; -}; - -/** - * This class looks horribly broken. Only m_matid is used, and - * m_matid is a (int) RAS_IPolyMaterial*. - * --> m_matid == lhs.m_matid should be *m_matid == *lhs.m_matid - */ -class RAS_MatArrayIndex -{ -public: - - int m_arrayindex1; - RAS_IPolyMaterial* m_matid; - int m_array; - int m_index; - -/* - inline bool Less(const RAS_MatArrayIndex& lhs) const { - bool result = - ( (m_matid < lhs.m_matid) || - ((m_matid == lhs.m_matid)&&(m_array < lhs.m_array)) || - ((m_matid == lhs.m_matid) && (m_array == lhs.m_array) && - (m_index < lhs.m_index)) - - ); - return result; - - } -*/ - -}; -/* -inline bool operator <( const RAS_MatArrayIndex& rhs,const RAS_MatArrayIndex& lhs) -{ - return ( rhs.Less(lhs)); -}*/ - -/** - * RAS_MeshObject stores mesh data for the renderer. - */ class RAS_MeshObject { - - // GEN_Map m_matVertexArrayS; - //vector m_vertexArrays; - virtual KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat); - //vector m_polygons; - +private: unsigned int m_debugcolor; - bool m_bModified; int m_lightlayer; - - vector m_Polygons; + + bool m_bModified; + bool m_bMeshModified; + STR_String m_name; static STR_String s_emptyname; - bool m_zsort; - bool m_MeshMod; + vector m_Polygons; + + /* polygon sorting */ struct polygonSlot; struct backtofront; struct fronttoback; - void SchedulePoly( - const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat - ); - - void ScheduleWireframePoly( - const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat - ); - protected: - enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192}; - enum { BUCKET_MAX_TRIANGLES = 65535 }; - - GEN_Map m_matVertexArrayS; - - RAS_MaterialBucket::Set m_materials; + list m_materials; Mesh* m_mesh; + bool m_bDeformed; + public: // for now, meshes need to be in a certain layer (to avoid sorting on lights in realtime) RAS_MeshObject(Mesh* mesh, int lightlayer); virtual ~RAS_MeshObject(); - vector m_sortedMaterials; - vector > m_xyz_index_to_vertex_index_mapping; - vector m_triangle_indices; - - int m_class; - unsigned int GetLightLayer(); + bool IsDeformed() { return m_bDeformed; } + + /* materials */ int NumMaterials(); const STR_String& GetMaterialName(unsigned int matid); - RAS_MaterialBucket* GetMaterialBucket(unsigned int matid); const STR_String& GetTextureName(unsigned int matid); - virtual void AddPolygon(RAS_Polygon* poly); - void UpdateMaterialList(); - - int NumPolygons(); - RAS_Polygon* GetPolygon(int num); - - virtual void Bucketize( - double* oglmatrix, - void* clientobj, - bool useObjectColor, - const MT_Vector4& rgbavec - ); - void RemoveFromBuckets( - double* oglmatrix, - void* clientobj - ); + RAS_MeshMaterial* GetMeshMaterial(unsigned int matid); + RAS_MeshMaterial* GetMeshMaterial(RAS_IPolyMaterial *mat); - void MarkVisible( - double* oglmatrix, - void* clientobj, - bool visible, - bool useObjectColor, - const MT_Vector4& rgbavec - ); + list::iterator GetFirstMaterial(); + list::iterator GetLastMaterial(); - void DebugColor(unsigned int abgr); - void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); - - /** - * Sorts the polygons by their transformed z values. - */ - void SortPolygons(const MT_Transform &transform); + unsigned int GetLightLayer(); - void SchedulePolygons(int drawingmode); + /* name */ + void SetName(STR_String name); + const STR_String& GetName(); - void ClearArrayData(); - - RAS_MaterialBucket::Set::iterator GetFirstMaterial(); - RAS_MaterialBucket::Set::iterator GetLastMaterial(); - - virtual RAS_TexVert* GetVertex( - short array, - unsigned int index, - RAS_IPolyMaterial* polymat - ); - - virtual int FindVertexArray( - int numverts, - RAS_IPolyMaterial* polymat - ); + /* modification state */ + bool MeshModified(); + void SetMeshModified(bool v){m_bMeshModified = v;} + /* original blender mesh */ + Mesh* GetMesh() { return m_mesh; } + + /* mesh construction */ - // find (and share) or add vertices - // for some speedup, only the last 20 added vertices are searched for equality - - virtual int FindOrAddVertex( - int vtxarray, + virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts); + virtual void AddVertex(RAS_Polygon *poly, int i, const MT_Point3& xyz, const MT_Point2& uv, const MT_Point2& uv2, @@ -239,27 +117,43 @@ public: const unsigned int rgbacolor, const MT_Vector3& normal, bool flat, - RAS_IPolyMaterial* mat, - int origindex - ); + int origindex); + + void SchedulePolygons(int drawingmode); + + /* vertex and polygon acces */ + int NumVertices(RAS_IPolyMaterial* mat); + RAS_TexVert* GetVertex(unsigned int matid, unsigned int index); + + int NumPolygons(); + RAS_Polygon* GetPolygon(int num) const; - vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat); + /* buckets */ + virtual void AddMeshUser(void *clientobj); + virtual void UpdateBuckets( + void* clientobj, + double* oglmatrix, + bool useObjectColor, + const MT_Vector4& rgbavec, + bool visible, + bool culled); + + void RemoveFromBuckets(void *clientobj); + + /* colors */ + void DebugColor(unsigned int abgr); + void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); - int GetVertexArrayLength(RAS_IPolyMaterial* mat); + /* polygon sorting by Z for alpha */ + void SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform); - RAS_TexVert* GetVertex( - unsigned int matid, - unsigned int index - ); - - const vecIndexArrays& GetIndexCache (RAS_IPolyMaterial* mat); - void SetName(STR_String name); - const STR_String& GetName(); - - bool MeshModified(); - void SetMeshModified(bool v){m_MeshMod = v;} - Mesh* GetMesh() { return m_mesh; } + /* for construction to find shared vertices */ + struct SharedVertex { + RAS_DisplayArray *m_darray; + int m_offset; + }; + vector > m_sharedvertex_map; }; #endif //__RAS_MESHOBJECT diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index 2a6d64ecc73..e4403ace69f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -32,6 +32,7 @@ SET(INC ../../../../intern/moto/include ../../../../source/gameengine/Rasterizer ../../../../extern/glew/include + ../../../../source/blender/gpu ) BLENDERLIB(bf_oglrasterizer "${SRC}" "${INC}") diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile index f01978b8eb1..aee485a22be 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile @@ -41,12 +41,11 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../../kernel/gen_system +CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../BlenderRoutines CPPFLAGS += -I.. + ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings endif -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index c2687319717..2c4b55ff964 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -9,6 +9,7 @@ #include "GL/glew.h" +#include "RAS_MaterialBucket.h" #include "RAS_TexVert.h" #include "MT_assert.h" @@ -125,20 +126,20 @@ void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) } } -RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot) +RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) { /* Keep a copy of constant lists submitted for rendering, this guards against (replicated)new...delete every frame, and we can reuse lists! - :: sorted by vertex array + :: sorted by mesh slot */ - RAS_ListSlot* localSlot = (RAS_ListSlot*)*slot; + RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList; if(!localSlot) { - RAS_Lists::iterator it = mLists.find(vertexarrays); + RAS_Lists::iterator it = mLists.find(&ms); if(it == mLists.end()) { localSlot = new RAS_ListSlot(this); - mLists.insert(std::pair(vertexarrays, localSlot)); + mLists.insert(std::pair(&ms, localSlot)); } else { localSlot = static_cast(it->second->AddRef()); } @@ -157,69 +158,45 @@ void RAS_ListRasterizer::ReleaseAlloc() mLists.clear(); } - -void RAS_ListRasterizer::IndexPrimitives( - const vecVertexArray & vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) +void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) { RAS_ListSlot* localSlot =0; - // useObjectColor(are we updating every frame?) - if(!useObjectColor && slot) { - localSlot = FindOrAdd(vertexarrays, slot); + if(ms.m_bDisplayList) { + localSlot = FindOrAdd(ms); localSlot->DrawList(); if(localSlot->End()) { // save slot here too, needed for replicas and object using same mesh // => they have the same vertexarray but different mesh slot - *slot = localSlot; + ms.m_DisplayList = localSlot; return; } } - if (mUseVertexArrays) { - RAS_VAOpenGLRasterizer::IndexPrimitives( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } else { - RAS_OpenGLRasterizer::IndexPrimitives( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } + if (mUseVertexArrays) + RAS_VAOpenGLRasterizer::IndexPrimitives(ms); + else + RAS_OpenGLRasterizer::IndexPrimitives(ms); - if(!useObjectColor && slot) { + if(ms.m_bDisplayList) { localSlot->EndList(); - *slot = localSlot; + ms.m_DisplayList = localSlot; } } -void RAS_ListRasterizer::IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) +void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) { RAS_ListSlot* localSlot =0; - // useObjectColor(are we updating every frame?) - if(!useObjectColor && slot) { - localSlot = FindOrAdd(vertexarrays, slot); + if(ms.m_bDisplayList) { + localSlot = FindOrAdd(ms); localSlot->DrawList(); if(localSlot->End()) { // save slot here too, needed for replicas and object using same mesh // => they have the same vertexarray but different mesh slot - *slot = localSlot; + ms.m_DisplayList = localSlot; return; } } @@ -227,23 +204,14 @@ void RAS_ListRasterizer::IndexPrimitivesMulti( // workaround: note how we do not use vertex arrays for making display // lists, since glVertexAttribPointerARB doesn't seem to work correct // in display lists on ATI? either a bug in the driver or in Blender .. - if (mUseVertexArrays && !localSlot) { - RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } else { - RAS_OpenGLRasterizer::IndexPrimitivesMulti( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } + if (mUseVertexArrays && !localSlot) + RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms); + else + RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); - if(!useObjectColor && slot) { + if(ms.m_bDisplayList) { localSlot->EndList(); - *slot = localSlot; + ms.m_DisplayList = localSlot; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index b1b19144c12..96d6d2a995d 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -4,6 +4,7 @@ #include "RAS_MaterialBucket.h" #include "RAS_VAOpenGLRasterizer.h" #include +#include class RAS_ListRasterizer; class RAS_ListSlot : public KX_ListSlot @@ -34,14 +35,14 @@ enum RAS_ListSlotFlags { LIST_REGEN =64 }; -typedef std::map RAS_Lists; +typedef std::map RAS_Lists; class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer { bool mUseVertexArrays; RAS_Lists mLists; - RAS_ListSlot* FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot); + RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms); void ReleaseAlloc(); public: @@ -49,23 +50,8 @@ public: RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false); virtual ~RAS_ListRasterizer(); - virtual void IndexPrimitives( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ); - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ); + virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); virtual bool Init(); virtual void Exit(); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 1dcc6e70934..87a0a1d8b9e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -38,6 +38,9 @@ #include "MT_CmMatrix4x4.h" #include "RAS_IRenderTools.h" // rendering text +#include "GPU_draw.h" +#include "GPU_material.h" + /** * 32x32 bit masks for vinterlace stereo mode */ @@ -67,10 +70,12 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), - m_last_blendmode(0), + m_last_blendmode(GPU_BLEND_SOLID), + m_last_frontface(true), m_materialCachingInfo(0) { - m_viewmatrix.Identity(); + m_viewmatrix.setIdentity(); + m_viewinvmatrix.setIdentity(); for (int i = 0; i < 32; i++) { @@ -87,81 +92,9 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() { } - - -static void Myinit_gl_stuff(void) -{ - float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - float mat_shininess[] = { 35.0 }; -/* float one= 1.0; */ - int a, x, y; - GLubyte pat[32*32]; - const GLubyte *patc= pat; - - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - - -#if defined(__FreeBSD) || defined(__linux__) - glDisable(GL_DITHER); /* op sgi/sun hardware && 12 bits */ -#endif - - /* no local viewer, looks ugly in ortho mode */ - /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ - - glDepthFunc(GL_LEQUAL); - /* scaling matrices */ - glEnable(GL_NORMALIZE); - - glShadeModel(GL_FLAT); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - glDisable(GL_LIGHTING); - glDisable(GL_LOGIC_OP); - glDisable(GL_STENCIL_TEST); - glDisable(GL_TEXTURE_1D); - glDisable(GL_TEXTURE_2D); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glPixelTransferi(GL_MAP_COLOR, GL_FALSE); - glPixelTransferi(GL_RED_SCALE, 1); - glPixelTransferi(GL_RED_BIAS, 0); - glPixelTransferi(GL_GREEN_SCALE, 1); - glPixelTransferi(GL_GREEN_BIAS, 0); - glPixelTransferi(GL_BLUE_SCALE, 1); - glPixelTransferi(GL_BLUE_BIAS, 0); - glPixelTransferi(GL_ALPHA_SCALE, 1); - glPixelTransferi(GL_ALPHA_BIAS, 0); - - a = 0; - for(x=0; x<32; x++) - { - for(y=0; y<4; y++) - { - if( (x) & 1) pat[a++]= 0x88; - else pat[a++]= 0x22; - } - } - - glPolygonStipple(patc); - - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); -} - - - bool RAS_OpenGLRasterizer::Init() { - - Myinit_gl_stuff(); + GPU_state_init(); m_redback = 0.4375; m_greenback = 0.4375; @@ -172,7 +105,12 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; - SetBlendingMode(0); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + m_last_blendmode = GPU_BLEND_SOLID; + + glFrontFace(GL_CCW); + m_last_frontface = true; glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -316,21 +254,10 @@ void RAS_OpenGLRasterizer::Exit() EndFrame(); } -bool RAS_OpenGLRasterizer::InterlacedStereo() const -{ - return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; -} - bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) { m_time = time; m_drawingmode = drawingmode; - - if (!InterlacedStereo() || m_curreye == RAS_STEREO_LEFTEYE) - { - m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); - m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); - } // Blender camera routine destroys the settings if (m_drawingmode < KX_SOLID) @@ -344,7 +271,12 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } - SetBlendingMode(0); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + m_last_blendmode = GPU_BLEND_SOLID; + + glFrontFace(GL_CCW); + m_last_frontface = true; glShadeModel(GL_SMOOTH); @@ -359,34 +291,28 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) { m_drawingmode = drawingmode; - switch (m_drawingmode) - { - case KX_WIREFRAME: - { - glDisable (GL_CULL_FACE); - break; - } - default: - { - } - } + if(m_drawingmode == KX_WIREFRAME) + glDisable(GL_CULL_FACE); } - - int RAS_OpenGLRasterizer::GetDrawingMode() { return m_drawingmode; } - void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask) { glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE); } +void RAS_OpenGLRasterizer::ClearColorBuffer() +{ + m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); + m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); +} + void RAS_OpenGLRasterizer::ClearDepthBuffer() { @@ -497,6 +423,10 @@ bool RAS_OpenGLRasterizer::Stereo() return true; } +bool RAS_OpenGLRasterizer::InterlacedStereo() +{ + return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; +} void RAS_OpenGLRasterizer::SetEye(const StereoEye eye) { @@ -573,294 +503,84 @@ void RAS_OpenGLRasterizer::SwapBuffers() -void RAS_OpenGLRasterizer::GetViewMatrix(MT_Matrix4x4 &mat) const +const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const { - float viewmat[16]; - glGetFloatv(GL_MODELVIEW_MATRIX, viewmat); - mat.setValue(viewmat); + return m_viewmatrix; } - - -void RAS_OpenGLRasterizer::IndexPrimitives(const vecVertexArray & vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ) -{ - const RAS_TexVert* vertexarray; - unsigned int numindices, vt; - - for (vt=0;vtm_type; + + if(it.array->m_type == RAS_DisplayArray::LINE) { + // line drawing, no text + glBegin(GL_LINES); + + for(i=0; igetXYZ()); + + vertex = &it.vertex[it.index[i+1]]; + glVertex3fv(vertex->getXYZ()); + } + + glEnd(); + } + else { + // triangle and quad text drawing + for(i=0; igetXYZ()[0]; + v[j][1] = vertex->getXYZ()[1]; + v[j][2] = vertex->getXYZ()[2]; + } + + // find the right opengl attribute + glattrib = -1; + if(GLEW_ARB_vertex_program) + for(unit=0; unitRenderText(polymat->GetDrawingMode(), polymat, + v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib); + + ClearCachingInfo(); + } + } } - - for (vt=0;vtRenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,v4); - ClearCachingInfo(); - } - break; - } - case KX_MODE_TRIANGLES: - { - glBegin(GL_TRIANGLES); - vindex=0; - for (unsigned int i=0;iRenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,NULL); - ClearCachingInfo(); - } - glEnd(); - break; - } - default: - { - } - } //switch - } //for each vertexarray + + glDisableClientState(GL_COLOR_ARRAY); } void RAS_OpenGLRasterizer::SetTexCoordNum(int num) @@ -897,14 +617,14 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) if(GLEW_ARB_multitexture) { for(unit=0; unitm_type; - for (vt=0;vtm_type == RAS_DisplayArray::LINE) { + // line drawing + glBegin(GL_LINES); - if (!numindices) - break; - - int vindex=0; - switch (mode) - { - case KX_MODE_LINES: + for(i=0; igetXYZ()); + + vertex = &it.vertex[it.index[i+1]]; + glVertex3fv(vertex->getXYZ()); } - break; - case KX_MODE_QUADS: - { - glBegin(GL_QUADS); - vindex=0; - if (useObjectColor) - { - for (unsigned int i=0;im_type == RAS_DisplayArray::TRIANGLE) glBegin(GL_TRIANGLES); - vindex=0; - if (useObjectColor) - { - for (unsigned int i=0;igetRGBA())); + + glNormal3fv(vertex->getNormal()); + + if(multi) + TexCoord(*vertex); + else + glTexCoord2fv(vertex->getUV1()); + } + + glVertex3fv(vertex->getXYZ()); + } } - } // switch - } // for each vertexarray + + glEnd(); + } + } } void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) @@ -1232,7 +821,7 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos, const MT_Point3 &, const MT_Quaternion &camOrientQuat) { - MT_Matrix4x4 viewMat = mat; + m_viewmatrix = mat; // correction for stereo if(m_stereomode != RAS_STEREO_NOSTEREO) @@ -1259,7 +848,7 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto MT_Transform transform; transform.setIdentity(); transform.translate(-(eyeline * m_eyeseparation / 2.0)); - viewMat *= transform; + m_viewmatrix *= transform; } break; case RAS_STEREO_RIGHTEYE: @@ -1268,20 +857,21 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto MT_Transform transform; transform.setIdentity(); transform.translate(eyeline * m_eyeseparation / 2.0); - viewMat *= transform; + m_viewmatrix *= transform; } break; } } - // convert row major matrix 'viewMat' to column major for OpenGL - MT_Scalar cammat[16]; - viewMat.getValue(cammat); - MT_CmMatrix4x4 viewCmmat = cammat; + m_viewinvmatrix = m_viewmatrix; + m_viewinvmatrix.invert(); + + // note: getValue gives back column major as needed by OpenGL + MT_Scalar glviewmat[16]; + m_viewmatrix.getValue(glviewmat); glMatrixMode(GL_MODELVIEW); - m_viewmatrix = viewCmmat; - glLoadMatrixd(&m_viewmatrix(0,0)); + glLoadMatrixd(glviewmat); m_campos = campos; } @@ -1292,20 +882,6 @@ const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition() } - -void RAS_OpenGLRasterizer::LoadViewMatrix() -{ - glLoadMatrixd(&m_viewmatrix(0,0)); -} - - - -void RAS_OpenGLRasterizer::EnableTextures(bool enable) -{ -} - - - void RAS_OpenGLRasterizer::SetCullFace(bool enable) { if (enable) @@ -1373,7 +949,10 @@ void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add) void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue) { - m_motionblur = 1; + /* don't just set m_motionblur to 1, but check if it is 0 so + * we don't reset a motion blur that is already enabled */ + if(m_motionblur == 0) + m_motionblur = 1; m_motionblurvalue = motionblurvalue; } @@ -1388,23 +967,23 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) if(blendmode == m_last_blendmode) return; - if(blendmode == 0) { + if(blendmode == GPU_BLEND_SOLID) { glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else if(blendmode == 1) { + else if(blendmode == GPU_BLEND_ADD) { glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); } - else if(blendmode == 2) { + else if(blendmode == GPU_BLEND_ALPHA) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); } - else if(blendmode == 4) { + else if(blendmode == GPU_BLEND_CLIP) { glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); @@ -1413,3 +992,16 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) m_last_blendmode = blendmode; } +void RAS_OpenGLRasterizer::SetFrontFace(bool ccw) +{ + if(m_last_frontface == ccw) + return; + + if(ccw) + glFrontFace(GL_CCW); + else + glFrontFace(GL_CW); + + m_last_frontface = ccw; +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 02056cce446..0717cce0ce8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -41,7 +41,7 @@ using namespace std; #include "RAS_MaterialBucket.h" #include "RAS_ICanvas.h" -#define RAS_MAX_TEXCO 3 // match in BL_Material +#define RAS_MAX_TEXCO 8 // match in BL_Material #define RAS_MAX_ATTRIB 16 // match in BL_BlenderShader struct OglDebugLine @@ -77,7 +77,8 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_ambb; double m_time; - MT_CmMatrix4x4 m_viewmatrix; + MT_Matrix4x4 m_viewmatrix; + MT_Matrix4x4 m_viewinvmatrix; MT_Point3 m_campos; StereoMode m_stereomode; @@ -87,7 +88,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_focallength; bool m_setfocallength; int m_noOfScanlines; - bool InterlacedStereo() const; //motion blur int m_motionblur; @@ -100,6 +100,7 @@ protected: int m_texco_num; int m_attrib_num; int m_last_blendmode; + bool m_last_frontface; /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; @@ -129,6 +130,7 @@ public: virtual bool Init(); virtual void Exit(); virtual bool BeginFrame(int drawingmode, double time); + virtual void ClearColorBuffer(); virtual void ClearDepthBuffer(); virtual void ClearCachingInfo(void); virtual void EndFrame(); @@ -136,6 +138,7 @@ public: virtual void SetStereoMode(const StereoMode stereomode); virtual bool Stereo(); + virtual bool InterlacedStereo(); virtual void SetEye(const StereoEye eye); virtual StereoEye GetEye(); virtual void SetEyeSeparation(const float eyeseparation); @@ -144,33 +147,15 @@ public: virtual float GetFocalLength(); virtual void SwapBuffers(); - virtual void IndexPrimitives( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ); + virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); virtual void IndexPrimitives_3DText( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, + class RAS_MeshSlot& ms, class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, - bool useObjectColor, - const MT_Vector4& rgbacolor - ); - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot); + class RAS_IRenderTools* rendertools); + void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat); virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat); @@ -182,7 +167,6 @@ public: ); virtual const MT_Point3& GetCameraPosition(); - virtual void LoadViewMatrix(); virtual void SetFog( float start, @@ -214,7 +198,6 @@ public: virtual void SetDrawingMode(int drawingmode); virtual int GetDrawingMode(); - virtual void EnableTextures(bool enable); virtual void SetCullFace(bool enable); virtual void SetLines(bool enable); @@ -270,13 +253,10 @@ public: virtual void SetTexCoord(TexCoGen coords, int unit); virtual void SetAttrib(TexCoGen coords, int unit); - void TexCoord(const RAS_TexVert &tv); - virtual void GetViewMatrix(MT_Matrix4x4 &mat) const; + void TexCoord(const RAS_TexVert &tv); - void Tangent(const RAS_TexVert& v1, - const RAS_TexVert& v2, - const RAS_TexVert& v3, - const MT_Vector3 &no); + const MT_Matrix4x4& GetViewMatrix() const; + const MT_Matrix4x4& GetViewInvMatrix() const; virtual void EnableMotionBlur(float motionblurvalue); virtual void DisableMotionBlur(); @@ -293,6 +273,7 @@ public: }; virtual void SetBlendingMode(int blendmode); + virtual void SetFrontFace(bool ccw); }; #endif //__RAS_OPENGLRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp index c78a97ad7be..2cb3b52adfb 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp @@ -33,6 +33,7 @@ #include #include "GL/glew.h" +#include "GPU_extensions.h" #include "STR_String.h" #include "RAS_TexVert.h" @@ -77,16 +78,16 @@ void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode) { case KX_BOUNDINGBOX: case KX_WIREFRAME: - glDisableClientState(GL_COLOR_ARRAY); - glDisable(GL_CULL_FACE); + //glDisableClientState(GL_COLOR_ARRAY); + //glDisable(GL_CULL_FACE); break; case KX_SOLID: - glDisableClientState(GL_COLOR_ARRAY); + //glDisableClientState(GL_COLOR_ARRAY); break; case KX_TEXTURED: case KX_SHADED: case KX_SHADOW: - glEnableClientState(GL_COLOR_ARRAY); + //glEnableClientState(GL_COLOR_ARRAY); default: break; } @@ -98,141 +99,121 @@ void RAS_VAOpenGLRasterizer::Exit() glEnableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - EnableTextures(false); RAS_OpenGLRasterizer::Exit(); } -void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) +void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) { - static const GLsizei vtxstride = sizeof(RAS_TexVert); + static const GLsizei stride = sizeof(RAS_TexVert); + bool wireframe = m_drawingmode <= KX_WIREFRAME; + RAS_MeshSlot::iterator it; GLenum drawmode; - if(mode == KX_MODE_TRIANGLES) - drawmode = GL_TRIANGLES; - else if(mode == KX_MODE_QUADS) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - const RAS_TexVert* vertexarray; - unsigned int numindices, vt; - - if (drawmode != GL_LINES) - { - if (useObjectColor) - { - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); - } else - { - glColor4d(0,0,0,1.0); - glEnableClientState(GL_COLOR_ARRAY); - } - } - else - { - glColor3d(0,0,0); - } - - EnableTextures(false); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + if(!wireframe) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); // use glDrawElements to draw each vertexarray - for (vt=0;vtgetLocalXYZ()); - glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); - glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1()); - if(glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); - //if(m_Lock) - // local->Begin(vertexarrays[vt]->size()); + // drawing mode + if(it.array->m_type == RAS_DisplayArray::TRIANGLE) + drawmode = GL_TRIANGLES; + else if(it.array->m_type == RAS_DisplayArray::QUAD) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; - // here the actual drawing takes places - glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0])); + // colors + if (drawmode != GL_LINES && !wireframe) { + if (ms.m_bObjectColor) { + const MT_Vector4& rgba = ms.m_RGBAcolor; - //if(m_Lock) - // local->End(); - } - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} - -void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) -{ - static const GLsizei vtxstride = sizeof(RAS_TexVert); - - GLenum drawmode; - if(mode == KX_MODE_TRIANGLES) - drawmode = GL_TRIANGLES; - else if(mode == KX_MODE_QUADS) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - - const RAS_TexVert* vertexarray; - unsigned int numindices, vt; - - if (drawmode != GL_LINES) - { - if (useObjectColor) - { - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + } + else { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glEnableClientState(GL_COLOR_ARRAY); + } } else - { - glColor4d(0,0,0,1.0); - glEnableClientState(GL_COLOR_ARRAY); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); + glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); + if(!wireframe) { + glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1()); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); } - } - else - { - glColor3d(0,0,0); - } - - // use glDrawElements to draw each vertexarray - for (vt=0;vtgetLocalXYZ()); - glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); - TexCoordPtr(vertexarray); - if(glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); - - //if(m_Lock) - // local->Begin(vertexarrays[vt]->size()); // here the actual drawing takes places - glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0])); - - //if(m_Lock) - // local->End(); + glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + + if(!wireframe) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } +} + +void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) +{ + static const GLsizei stride = sizeof(RAS_TexVert); + bool wireframe = m_drawingmode <= KX_WIREFRAME; + RAS_MeshSlot::iterator it; + GLenum drawmode; + + if(!wireframe) + EnableTextures(true); + + // use glDrawElements to draw each vertexarray + for(ms.begin(it); !ms.end(it); ms.next(it)) { + if(it.totindex == 0) + continue; + + // drawing mode + if(it.array->m_type == RAS_DisplayArray::TRIANGLE) + drawmode = GL_TRIANGLES; + else if(it.array->m_type == RAS_DisplayArray::QUAD) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; + + // colors + if (drawmode != GL_LINES && !wireframe) { + if (ms.m_bObjectColor) { + const MT_Vector4& rgba = ms.m_RGBAcolor; + + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + } + else { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glEnableClientState(GL_COLOR_ARRAY); + } + } + else + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); + glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); + if(!wireframe) { + TexCoordPtr(it.vertex); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); + } + + // here the actual drawing takes places + glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + + if(!wireframe) { + glDisableClientState(GL_COLOR_ARRAY); + EnableTextures(false); } } @@ -248,7 +229,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) for(unit=0; unitgetFlag() & TV_2NDUV && (int)tv->getUnit() == unit) { + if(tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2()); continue; @@ -257,7 +238,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ()); + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); break; case RAS_TEXCO_UV1: glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1()); @@ -284,7 +265,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) switch(m_attrib[unit]) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ()); + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); break; case RAS_TEXCO_UV1: glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); @@ -313,11 +294,6 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) TexCoGen *texco, *attrib; int unit, texco_num, attrib_num; - /* disable previously enabled texture coordinates and attributes. ideally - * this shouldn't be necessary .. */ - if(enable) - EnableTextures(false); - /* we cache last texcoords and attribs to ensure we disable the ones that * were actually last set */ if(enable) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h index e4cc4ace0e8..766bbfbed0e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h @@ -50,22 +50,10 @@ public: virtual void SetDrawingMode(int drawingmode); - virtual void IndexPrimitives( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot); - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot); - + virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); +private: virtual void EnableTextures(bool enable); //virtual bool QueryArrays(){return true;} //virtual bool QueryLists(){return m_Lock;} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 0cf9c326370..8d46528f7f0 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -1,12 +1,9 @@ #!/usr/bin/python Import ('env') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - sources = env.Glob('*.cpp') incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' -incs += ' #extern/glew/include ' + env['BF_OPENGL_INC'] +incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120] ) diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index b74cb9cfcac..50331d7a664 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -26,99 +26,82 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 - #pragma warning (disable:4786) #endif #include "RAS_Polygon.h" -RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, - bool visible, - int numverts, - int vtxarrayindex) - :m_bucket(bucket), - m_vertexindexbase(numverts), - m_numverts(numverts), - m_edgecode(65535) +RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray *darray, int numvert) { - m_vertexindexbase.m_vtxarray = vtxarrayindex ;//m_bucket->FindVertexArray(numverts); - m_polyFlags.Visible = visible; + m_bucket = bucket; + m_darray = darray; + m_offset[0]= m_offset[1]= m_offset[2]= m_offset[3]= 0; + m_numvert = numvert; + + m_edgecode = 255; + m_polyflags = 0; } - - int RAS_Polygon::VertexCount() { - return m_numverts; + return m_numvert; } - - -void RAS_Polygon::SetVertex(int i, - unsigned int vertexindex ) //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal) +void RAS_Polygon::SetVertexOffset(int i, unsigned short offset) { - m_vertexindexbase.SetIndex(i,vertexindex); //m_bucket->FindOrAddVertex(m_vertexindexbase.m_vtxarray, - //xyz,uv,rgbacolor,normal)); + m_offset[i] = offset; } - - -const KX_VertexIndex& RAS_Polygon::GetIndexBase() +RAS_TexVert *RAS_Polygon::GetVertex(int i) { - return m_vertexindexbase; + return &m_darray->m_vertex[m_offset[i]]; } - - -void RAS_Polygon::SetVisibleWireframeEdges(int edgecode) +int RAS_Polygon::GetVertexOffset(int i) { - m_edgecode = edgecode; + return m_offset[i]; } - - -// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. int RAS_Polygon::GetEdgeCode() { return m_edgecode; } +void RAS_Polygon::SetEdgeCode(int edgecode) +{ + m_edgecode = edgecode; +} bool RAS_Polygon::IsVisible() { - return m_polyFlags.Visible; + return (m_polyflags & VISIBLE) != 0; } - +void RAS_Polygon::SetVisible(bool visible) +{ + if(visible) m_polyflags |= VISIBLE; + else m_polyflags &= ~VISIBLE; +} bool RAS_Polygon::IsCollider() { - return m_polyFlags.Collider; + return (m_polyflags & COLLIDER) != 0; } - - -void RAS_Polygon::SetCollider(bool col) +void RAS_Polygon::SetCollider(bool visible) { - m_polyFlags.Collider = col; + if(visible) m_polyflags |= COLLIDER; + else m_polyflags &= ~COLLIDER; } - - -KX_VertexIndex& RAS_Polygon::GetVertexIndexBase() -{ - return m_vertexindexbase; -} - - - -RAS_MaterialBucket* RAS_Polygon::GetMaterial() +RAS_MaterialBucket* RAS_Polygon::GetMaterial() { return m_bucket; } + +RAS_DisplayArray* RAS_Polygon::GetDisplayArray() +{ + return m_darray; +} diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h index 7ce7926a816..18526ba45f7 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.h +++ b/source/gameengine/Rasterizer/RAS_Polygon.h @@ -35,55 +35,47 @@ #include using namespace std; - -// -// Bitfield that stores the flags for each CValue derived class -// -struct PolygonFlags { - PolygonFlags() : - Visible(true), - Collider(true) - { - } - unsigned char Visible : 1; - unsigned char Collider : 1; - //int Visible : 1; - //int Collider : 1; -}; +/* polygon flags */ class RAS_Polygon { + /* location */ RAS_MaterialBucket* m_bucket; - KX_VertexIndex m_vertexindexbase; - int m_numverts; - int m_edgecode; - PolygonFlags m_polyFlags; - + RAS_DisplayArray* m_darray; + unsigned short m_offset[4]; + unsigned short m_numvert; + + /* flags */ + unsigned char m_edgecode; + unsigned char m_polyflags; public: - RAS_Polygon(RAS_MaterialBucket* bucket, - bool visible, - int numverts, - int vtxarrayindex) ; + enum { + VISIBLE = 1, + COLLIDER = 2 + }; + + RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray* darray, int numvert); virtual ~RAS_Polygon() {}; -// RAS_TexVert* GetVertex(int index); int VertexCount(); - void SetVertex(int i, unsigned int vertexindex); //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal) - - const KX_VertexIndex& GetIndexBase(); + RAS_TexVert* GetVertex(int i); - void SetVisibleWireframeEdges(int edgecode); + void SetVertexOffset(int i, unsigned short offset); + int GetVertexOffset(int i); + // each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. int GetEdgeCode(); + void SetEdgeCode(int edgecode); bool IsVisible(); + void SetVisible(bool visible); + bool IsCollider(); - void SetCollider(bool col); + void SetCollider(bool collider); - KX_VertexIndex& GetVertexIndexBase(); RAS_MaterialBucket* GetMaterial(); - + RAS_DisplayArray* GetDisplayArray(); }; #endif diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 935633dc636..d6f1fe912be 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -27,12 +27,7 @@ */ #include "RAS_TexVert.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define SHORT(x) short(x*32767.0) +#include "MT_Matrix4x4.h" RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Point2& uv, @@ -40,7 +35,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const short flag, + const bool flat, const unsigned int origindex) { xyz.getValue(m_localxyz); @@ -49,7 +44,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, SetRGBA(rgba); SetNormal(normal); tangent.getValue(m_tangent); - m_flag = flag; + m_flag = (flat)? FLAT: 0; m_origindex = origindex; m_unit = 2; } @@ -101,7 +96,7 @@ void RAS_TexVert::SetFlag(const short flag) void RAS_TexVert::SetUnit(const unsigned int u) { - m_unit = u<=TV_MAX?u:TV_MAX; + m_unit = u<=MAX_UNIT?u:MAX_UNIT; } void RAS_TexVert::SetNormal(const MT_Vector3& normal) @@ -109,12 +104,18 @@ void RAS_TexVert::SetNormal(const MT_Vector3& normal) normal.getValue(m_normal); } +void RAS_TexVert::SetTangent(const MT_Vector3& tangent) +{ + tangent.getValue(m_tangent); +} + // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { return (m_flag == other->m_flag && m_rgba == other->m_rgba && MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) && + MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) && MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) && MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) && // p -- MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))) ; @@ -131,11 +132,10 @@ unsigned int RAS_TexVert::getUnit() const return m_unit; } - -void RAS_TexVert::getOffsets(void* &xyz, void* &uv1, void* &rgba, void* &normal) const +void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) { - xyz = (void *) m_localxyz; - uv1 = (void *) m_uv1; - rgba = (void *) &m_rgba; - normal = (void *) m_normal; + SetXYZ((mat*MT_Vector4(m_localxyz[0], m_localxyz[1], m_localxyz[2], 1.0)).getValue()); + SetNormal((nmat*MT_Vector4(m_normal[0], m_normal[1], m_normal[2], 1.0)).getValue()); + SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } + diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index bf092b4b230..4ec4db19e53 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -37,11 +37,6 @@ static MT_Point3 g_pt3; static MT_Point2 g_pt2; -#define TV_CALCFACENORMAL 0x0001 -#define TV_2NDUV 0x0002 - -#define TV_MAX 3//match Def in BL_Material.h - class RAS_TexVert { @@ -59,6 +54,12 @@ class RAS_TexVert // 32 bytes total size, fits nice = 56 = not fit nice. // We'll go for 64 bytes total size - 24 bytes left. public: + enum { + FLAT = 1, + SECOND_UV = 2, + MAX_UNIT = 8 + }; + short getFlag() const; unsigned int getUnit() const; @@ -70,7 +71,7 @@ public: const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const short flag, + const bool flat, const unsigned int origindex); ~RAS_TexVert() {}; @@ -82,7 +83,7 @@ public: return m_uv2; }; - const float* getLocalXYZ() const { + const float* getXYZ() const { return m_localxyz; }; @@ -108,20 +109,19 @@ public: void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); + void SetTangent(const MT_Vector3& tangent); void SetFlag(const short flag); void SetUnit(const unsigned u); void SetRGBA(const MT_Vector4& rgba); const MT_Point3& xyz(); - // compare two vertices, and return TRUE if both are almost identical (they can be shared) - bool closeTo(const RAS_TexVert* other); + void Transform(const class MT_Matrix4x4& mat, + const class MT_Matrix4x4& nmat); - bool closeTo(const MT_Point3& otherxyz, - const MT_Point2& otheruv, - const unsigned int otherrgba, - short othernormal[3]) const; - void getOffsets(void*&xyz, void *&uv1, void *&rgba, void *&normal) const; + // compare two vertices, to test if they can be shared, used for + // splitting up based on uv's, colors, etc + bool closeTo(const RAS_TexVert* other); }; #endif //__RAS_TEXVERT diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index e6bc657ed6d..a024f7e0ee6 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -3,11 +3,8 @@ Import ('env') sources = env.Glob('*.cpp') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - -incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions' +incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna' incs += ' ' + env['BF_PYTHON_INC'] if env['OURPLATFORM']=='win32-vc': diff --git a/source/kernel/gen_system/GEN_Map.h b/source/kernel/gen_system/GEN_Map.h index 37c75d8293a..88c79293223 100644 --- a/source/kernel/gen_system/GEN_Map.h +++ b/source/kernel/gen_system/GEN_Map.h @@ -50,6 +50,19 @@ public: m_buckets[i] = 0; } } + + GEN_Map(const GEN_Map& map) + { + m_num_buckets = map.m_num_buckets; + m_buckets = new Entry *[m_num_buckets]; + + for (int i = 0; i < m_num_buckets; ++i) { + m_buckets[i] = 0; + + for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) + insert(entry->m_key, entry->m_value); + } + } int size() { int count=0; diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 9c1a28de999..424a7c558d7 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -56,9 +56,6 @@ all debug:: # Object Config_Guess DIRectory export OCGDIR = $(NAN_OBJDIR)/$(CONFIG_GUESS) - export WITH_GLEXT?=true - export WITH_BF_GLEXT?=$(WITH_GLEXT) - # Determines what targets are built export WITH_BF_DYNAMICOPENGL ?= true export WITH_BF_STATICOPENGL ?= false @@ -287,7 +284,7 @@ endif export FREEDESKTOP ?= true export NAN_PYTHON ?= /usr/local - export NAN_PYTHON_VERSION ?= 2.3 + export NAN_PYTHON_VERSION ?= 2.5 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 ?= /usr/local @@ -302,9 +299,9 @@ endif export NAN_NSPR ?= /usr/local export NAN_FREETYPE ?= $(LCGDIR)/freetype export NAN_GETTEXT ?= $(LCGDIR)/gettext - export NAN_SDL ?= $(shell sdl11-config --prefix) - export NAN_SDLLIBS ?= $(shell sdl11-config --libs) - export NAN_SDLCFLAGS ?= $(shell sdl11-config --cflags) + 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 diff --git a/tools/Blender.py b/tools/Blender.py index 2c982a0a46f..3f928ff8c97 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -129,6 +129,9 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_STATICOPENGL']: statlibs += Split(lenv['BF_OPENGL_LIB_STATIC']) + if lenv['WITH_BF_STATICPYTHON']: + statlibs += Split(lenv['BF_PYTHON_LIB_STATIC']) + if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'): libincs += Split(lenv['BF_PTHREADS_LIBPATH']) @@ -141,10 +144,12 @@ def setup_syslibs(lenv): lenv['BF_PNG_LIB'], lenv['BF_ZLIB_LIB'] ] - if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): - syslibs.append(lenv['BF_PYTHON_LIB']+'_d') - else: - syslibs.append(lenv['BF_PYTHON_LIB']) + + if not lenv['WITH_BF_STATICPYTHON']: + if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): + syslibs.append(lenv['BF_PYTHON_LIB']+'_d') + else: + syslibs.append(lenv['BF_PYTHON_LIB']) if lenv['WITH_BF_INTERNATIONAL']: syslibs += Split(lenv['BF_FREETYPE_LIB']) syslibs += Split(lenv['BF_GETTEXT_LIB']) diff --git a/tools/btools.py b/tools/btools.py index a25120f6c4b..afcc83d2002 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -27,7 +27,7 @@ def print_arguments(args, bc): def validate_arguments(args, bc): opts_list = [ - 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', + 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', @@ -51,7 +51,6 @@ def validate_arguments(args, bc): 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', 'BF_OPENGL_LINKFLAGS', 'WITH_BF_FTGL', 'BF_FTGL', 'BF_FTGL_INC', 'BF_FTGL_LIB', 'WITH_BF_PLAYER', - 'WITH_BF_GLEXT', 'WITH_BF_BINRELOC', 'CFLAGS', 'CCFLAGS', 'CPPFLAGS', 'REL_CFLAGS', 'REL_CCFLAGS', @@ -145,8 +144,10 @@ def read_opts(cfg, args): ('BF_PYTHON_INC', 'include path for Python headers', ''), ('BF_PYTHON_BINARY', 'Path to the Python interpreter', ''), ('BF_PYTHON_LIB', 'Python library', ''), + ('BF_PYTHON_LIB_STATIC', 'Python static libraries', ''), ('BF_PYTHON_LIBPATH', 'Library path', ''), ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), + (BoolOption('WITH_BF_STATICPYTHON', 'Staticly link to python', 'false')), (BoolOption('BF_NO_ELBEEM', 'Disable Fluid Sim', 'false')), (BoolOption('WITH_BF_YAFRAY', 'Enable Yafray', 'true')), (BoolOption('WITH_BF_OPENAL', 'Use OpenAL if true', '')), @@ -292,7 +293,6 @@ def read_opts(cfg, args): ('BF_FTGL_INC', 'FTGL include path', ''), ('BF_FTGL_LIB', 'FTGL libraries', ''), - (BoolOption('WITH_BF_GLEXT', 'Enable GL Extensions', 'true')), (BoolOption('WITH_BF_PLAYER', 'Build blenderplayer if true', 'false')), ('CFLAGS', 'C-compiler flags', ''), From 27de7cc2e178167ec51d2f3706ad6cadf2c68e65 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 16 Sep 2008 15:41:13 +0000 Subject: [PATCH 03/10] Added SSLevels options to all shrinkwrap modes (before it was only available to projection mode) Added BVHTree cache at derivedMesh level --- source/blender/blenkernel/BKE_DerivedMesh.h | 2 + source/blender/blenkernel/BKE_bvhutils.h | 45 ++- source/blender/blenkernel/BKE_shrinkwrap.h | 6 +- .../blender/blenkernel/intern/DerivedMesh.c | 6 + source/blender/blenkernel/intern/bvhutils.c | 204 ++++++++++--- source/blender/blenkernel/intern/modifier.c | 2 +- source/blender/blenkernel/intern/shrinkwrap.c | 280 +++++++++--------- source/blender/src/buttons_editing.c | 12 +- 8 files changed, 349 insertions(+), 208 deletions(-) diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 171a73f72c4..fe25ada3962 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -44,6 +44,7 @@ #include "DNA_customdata_types.h" #include "BKE_customdata.h" +#include "BKE_bvhutils.h" struct MVert; struct MEdge; @@ -69,6 +70,7 @@ struct DerivedMesh { int numVertData, numEdgeData, numFaceData; int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ + BVHCache bvhCache; /* Misc. Queries */ diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index dd9ea61f24b..66c8d99959a 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -31,6 +31,7 @@ #define BKE_BVHUTILS_H #include "BLI_kdopbvh.h" +#include "BLI_linklist.h" /* * This header encapsulates necessary code to buld a BVH @@ -52,7 +53,7 @@ typedef struct BVHTreeFromMesh BVHTree_RayCastCallback raycast_callback; /* Mesh represented on this BVHTree */ - struct DerivedMesh *mesh; + struct DerivedMesh *mesh; /* Vertex array, so that callbacks have instante access to data */ struct MVert *vert; @@ -61,6 +62,9 @@ typedef struct BVHTreeFromMesh /* radius for raycast */ float sphere_radius; + /* Private data */ + int cached; + } BVHTreeFromMesh; /* @@ -74,7 +78,7 @@ typedef struct BVHTreeFromMesh * * free_bvhtree_from_mesh should be called when the tree is no longer needed. */ -void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); +BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); /* * Builds a bvh tree where nodes are the faces of the given mesh. @@ -84,15 +88,50 @@ void bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMesh *m * so that the coordinates and rays are first translated on the mesh local coordinates. * Reason for this is that later bvh_from_mesh_* might use a cache system and so it becames possible to reuse * a BVHTree. + * + * The returned value is the same as in data->tree, its only returned to make it easier to test + * the success * * free_bvhtree_from_mesh should be called when the tree is no longer needed. */ -void bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); +BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); /* * Frees data allocated by a call to bvhtree_from_mesh_*. */ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data); + +/* + * BVHCache + */ + +//Using local coordinates +#define BVHTREE_FROM_FACES 0 +#define BVHTREE_FROM_VERTICES 1 + +typedef LinkNode* BVHCache; + + +/* + * Queries a bvhcache for the chache bvhtree of the request type + */ +BVHTree *bvhcache_find(BVHCache *cache, int type); + +/* + * Inserts a BVHTree of the given type under the cache + * After that the caller no longer needs to worry when to free the BVHTree + * as that will be done when the cache is freed. + * + * A call to this assumes that there was no previous cached tree of the given type + */ +void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type); + +/* + * inits and frees a bvhcache + */ +void bvhcache_init(BVHCache *cache); +void bvhcache_free(BVHCache *cache); + #endif diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index e8276238ff2..795da6ff884 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -95,6 +95,8 @@ void space_transform_invert_normal(const SpaceTransform *data, float *no); struct Object; struct DerivedMesh; +struct MVert; +struct MDeformVert; struct ShrinkwrapModifierData; struct BVHTree; @@ -104,8 +106,10 @@ typedef struct ShrinkwrapCalcData ShrinkwrapModifierData *smd; //shrinkwrap modifier data struct Object *ob; //object we are applying shrinkwrap to - struct DerivedMesh *original; //mesh before shrinkwrap + MVert *vert; //Array of verts being projected (to fetch normals or other data) + MDeformVert *dvert; //Array to get vertexs weights + int vgroup; float (*vertexCos)[3]; //vertexs being shrinkwraped int numVerts; diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 328dcada01a..a5eb1f258f1 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -78,6 +78,7 @@ #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_particle.h" +#include "BKE_bvhutils.h" #include "BLO_sys_types.h" // for intptr_t support @@ -188,6 +189,8 @@ void DM_init_funcs(DerivedMesh *dm) dm->getVertDataArray = DM_get_vert_data_layer; dm->getEdgeDataArray = DM_get_edge_data_layer; dm->getFaceDataArray = DM_get_face_data_layer; + + bvhcache_init(&dm->bvhCache); } void DM_init(DerivedMesh *dm, @@ -224,6 +227,8 @@ void DM_from_template(DerivedMesh *dm, DerivedMesh *source, int DM_release(DerivedMesh *dm) { if (dm->needsFree) { + bvhcache_free(&dm->bvhCache); + CustomData_free(&dm->vertData, dm->numVertData); CustomData_free(&dm->edgeData, dm->numEdgeData); CustomData_free(&dm->faceData, dm->numFaceData); @@ -2735,6 +2740,7 @@ static void mesh_build_data(Object *ob, CustomDataMask dataMask) Mesh *me = ob->data; float min[3], max[3]; + printf("Building DerivedMesh for %s\n", ob->id.name); clear_mesh_caches(ob); if(ob!=G.obedit) { diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index ae449843d2a..a8aea621502 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "BKE_bvhutils.h" @@ -45,6 +46,8 @@ #include "BKE_global.h" #include "BLI_arithb.h" +#include "BLI_linklist.h" +#include "MEM_guardedalloc.h" /* Math stuff for ray casting on mesh faces and for nearest surface */ @@ -480,30 +483,47 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r * BVH builders */ // Builds a bvh tree.. where nodes are the vertexs of the given mesh -void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) +BVHTree* bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) { - int i; - int numVerts= mesh->getNumVerts(mesh); - MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); - BVHTree *tree = NULL; + BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_VERTICES); - memset(data, 0, sizeof(*data)); - - if(vert == NULL) + //Not in cache + if(tree == NULL) { - printf("bvhtree cant be build: cant get a vertex array"); - return; + int i; + int numVerts= mesh->getNumVerts(mesh); + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + + if(vert != NULL) + { + tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis); + + if(tree != NULL) + { + for(i = 0; i < numVerts; i++) + BLI_bvhtree_insert(tree, i, vert[i].co, 1); + + 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_VERTICES); + } + } + } + else + { + printf("BVHTree is already build, using cached tree\n"); } - tree = BLI_bvhtree_new(numVerts, epsilon, tree_type, axis); - if(tree != NULL) + + //Setup BVHTreeFromMesh + memset(data, 0, sizeof(*data)); + data->tree = tree; + + if(data->tree) { - for(i = 0; i < numVerts; i++) - BLI_bvhtree_insert(tree, i, vert[i].co, 1); - - BLI_bvhtree_balance(tree); - - data->tree = tree; + data->cached = TRUE; //a NULL nearest callback works fine //remeber the min distance to point is the same as the min distance to BV of point @@ -516,43 +536,62 @@ void bvhtree_from_mesh_verts(BVHTreeFromMesh *data, DerivedMesh *mesh, float eps data->sphere_radius = epsilon; } + + return data->tree; } // Builds a bvh tree.. where nodes are the faces of the given mesh. -void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) +BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) { - int i; - int numFaces= mesh->getNumFaces(mesh); - MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); - MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE); - BVHTree *tree = NULL; + BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_FACES); - memset(data, 0, sizeof(*data)); - - if(vert == NULL && face == NULL) + //Not in cache + if(tree == NULL) { - printf("bvhtree cant be build: cant get a vertex/face array"); - return; + int i; + int numFaces= mesh->getNumFaces(mesh); + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + MFace *face = mesh->getFaceDataArray(mesh, CD_MFACE); + + if(vert != NULL && face != NULL) + { + /* Create a bvh-tree of the given target */ + tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); + if(tree != NULL) + { + for(i = 0; i < numFaces; i++) + { + float co[4][3]; + VECCOPY(co[0], vert[ face[i].v1 ].co); + VECCOPY(co[1], vert[ face[i].v2 ].co); + VECCOPY(co[2], vert[ face[i].v3 ].co); + if(face[i].v4) + VECCOPY(co[3], vert[ face[i].v4 ].co); + + BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); + } + 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_FACES); + } + } + } + else + { + printf("BVHTree is already build, using cached tree\n"); } - /* Create a bvh-tree of the given target */ - tree = BLI_bvhtree_new(numFaces, epsilon, tree_type, axis); - if(tree != NULL) - { - for(i = 0; i < numFaces; i++) - { - float co[4][3]; - VECCOPY(co[0], vert[ face[i].v1 ].co); - VECCOPY(co[1], vert[ face[i].v2 ].co); - VECCOPY(co[2], vert[ face[i].v3 ].co); - if(face[i].v4) - VECCOPY(co[3], vert[ face[i].v4 ].co); - - BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3); - } - BLI_bvhtree_balance(tree); - data->tree = tree; + //Setup BVHTreeFromMesh + memset(data, 0, sizeof(*data)); + data->tree = tree; + + if(data->tree) + { + data->cached = TRUE; + data->nearest_callback = mesh_faces_nearest_point; data->raycast_callback = mesh_faces_spherecast; @@ -562,6 +601,8 @@ void bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float eps data->sphere_radius = epsilon; } + return data->tree; + } // Frees data allocated by a call to bvhtree_from_mesh_*. @@ -569,9 +610,78 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) { if(data->tree) { - BLI_bvhtree_free(data->tree); + if(!data->cached) + BLI_bvhtree_free(data->tree); + memset( data, 0, sizeof(data) ); } } +/* BVHCache */ +typedef struct BVHCacheItem +{ + int type; + BVHTree *tree; + +} BVHCacheItem; + +static void bvhcacheitem_set_if_match(void *_cached, void *_search) +{ + BVHCacheItem * cached = (BVHCacheItem *)_cached; + BVHCacheItem * search = (BVHCacheItem *)_search; + + if(search->type == cached->type) + { + search->tree = cached->tree; + } +} + +BVHTree *bvhcache_find(BVHCache *cache, int type) +{ + BVHCacheItem item; + item.type = type; + item.tree = NULL; + + BLI_linklist_apply(*cache, bvhcacheitem_set_if_match, &item); + return item.tree; +} + +void bvhcache_insert(BVHCache *cache, BVHTree *tree, int type) +{ + BVHCacheItem *item = NULL; + + assert( tree != NULL ); + assert( bvhcache_find(cache, type) == NULL ); + + item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem"); + assert( item != NULL ); + + item->type = type; + item->tree = tree; + + BLI_linklist_prepend( cache, item ); +} + + +void bvhcache_init(BVHCache *cache) +{ + *cache = NULL; +} + +static void bvhcacheitem_free(void *_item) +{ + BVHCacheItem *item = (BVHCacheItem *)_item; + + BLI_bvhtree_free(item->tree); + MEM_freeN(item); +} + + +void bvhcache_free(BVHCache *cache) +{ + BLI_linklist_free(*cache, (LinkNodeFreeFP)bvhcacheitem_free); + *cache = NULL; +} + + diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 97e3bc9e9bd..16287d360b5 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7300,7 +7300,7 @@ static void shrinkwrapModifier_deformVerts(ModifierData *md, Object *ob, Derived CustomDataMask dataMask = shrinkwrapModifier_requiredDataMask(md); /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ - if(shrinkwrapModifier_requiredDataMask(md)) + if(dataMask) { if(derivedData) dm = CDDM_copy(derivedData); else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 76af9a763ee..931519a1b4a 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -147,6 +147,7 @@ static float squared_dist(const float *a, const float *b) void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { + DerivedMesh *ss_mesh = NULL; ShrinkwrapCalcData calc = NULL_ShrinkwrapCalcData; //remove loop dependencies on derived meshs (TODO should this be done elsewhere?) @@ -157,23 +158,59 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM //Configure Shrinkwrap calc data calc.smd = smd; calc.ob = ob; - calc.original = dm; calc.numVerts = numVerts; calc.vertexCos = vertexCos; if(smd->target) { - //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array - calc.target = CDDM_copy( object_get_derived_final(smd->target, CD_MASK_BAREMESH) ); + calc.target = object_get_derived_final(smd->target, CD_MASK_BAREMESH); - //TODO there might be several "bugs" on non-uniform scales matrixs.. because it will no longer be nearest surface, not sphere projection + //TODO there might be several "bugs" on non-uniform scales matrixs + //because it will no longer be nearest surface, not sphere projection //because space has been deformed space_transform_setup(&calc.local2target, ob, smd->target); - calc.keepDist = smd->keepDist; //TODO: smd->keepDist is in global units.. must change to local + //TODO: smd->keepDist is in global units.. must change to local + calc.keepDist = smd->keepDist; } + + calc.vgroup = get_named_vertexgroup_num(calc.ob, smd->vgroup_name); + + if(dm != NULL) + { + //Setup arrays to get vertexs positions, normals and deform weights + calc.vert = dm->getVertDataArray(dm, CD_MVERT); + calc.dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + + //Using vertexs positions/normals as if a subsurface was applied + if(smd->subsurfLevels) + { + SubsurfModifierData ssmd; + memset(&ssmd, 0, sizeof(ssmd)); + ssmd.subdivType = ME_CC_SUBSURF; //catmull clark + ssmd.levels = smd->subsurfLevels; //levels + + ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, FALSE, NULL, 0, 0); + + if(ss_mesh) + { + calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT); + if(calc.vert) + { + //TRICKY: this code assumes subsurface will have the transformed original vertices + //in their original order at the end of the vert array. + calc.vert = calc.vert + ss_mesh->getNumVerts(ss_mesh) - dm->getNumVerts(dm); + } + } + + //Just to make sure we are not letting any memory behind + assert(ssmd.emCache == NULL); + assert(ssmd.mCache == NULL); + } + } + //Projecting target defined - lets work! if(calc.target) { @@ -194,8 +231,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM } //free memory - if(calc.target) - calc.target->release( calc.target ); + if(ss_mesh) + ss_mesh->release(ss_mesh); } /* @@ -207,8 +244,6 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) { int i; - const int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name); - MDeformVert *const dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL; BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; BVHTreeNearest nearest = NULL_BVHTreeNearest; @@ -226,11 +261,20 @@ void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) { float *co = calc->vertexCos[i]; float tmp_co[3]; - float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup); + float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup); if(weight == 0.0f) continue; - VECCOPY(tmp_co, co); - space_transform_apply(&calc->local2target, tmp_co); //Convert the coordinates to the tree coordinates + + //Convert the vertex to tree coordinates + if(calc->vert) + { + VECCOPY(tmp_co, calc->vert[i].co); + } + else + { + VECCOPY(tmp_co, co); + } + space_transform_apply(&calc->local2target, tmp_co); //Use local proximity heuristics (to reduce the nearest search) // @@ -333,177 +377,116 @@ void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) int i; //Options about projection direction - const char use_normal = calc->smd->shrinkOpts; - float proj_axis[3] = {0.0f, 0.0f, 0.0f}; - MVert *vert = NULL; //Needed in case of vertex normal - DerivedMesh* ss_mesh = NULL; - - //Vertex group data - const int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name); - const MDeformVert *dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL; - + const char use_normal = calc->smd->shrinkOpts; + float proj_axis[3] = {0.0f, 0.0f, 0.0f}; //Raycast and tree stuff BVHTreeRayHit hit; - BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; //target + BVHTreeFromMesh treeData= NULL_BVHTreeFromMesh; //auxiliar target - DerivedMesh * aux_mesh = NULL; - BVHTreeFromMesh auxData= NULL_BVHTreeFromMesh; + DerivedMesh *auxMesh = NULL; + BVHTreeFromMesh auxData = NULL_BVHTreeFromMesh; SpaceTransform local2aux; -do -{ + //If the user doesn't allows to project in any direction of projection axis + //then theres nothing todo. + if((use_normal & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0) + return; + //Prepare data to retrieve the direction in which we should project each vertex if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) { - //No Mvert information: jump to "free memory and return" part - if(calc->original == NULL) break; - - if(calc->smd->subsurfLevels) - { - SubsurfModifierData smd; - memset(&smd, 0, sizeof(smd)); - smd.subdivType = ME_CC_SUBSURF; //catmull clark - smd.levels = calc->smd->subsurfLevels; //levels - - ss_mesh = subsurf_make_derived_from_derived(calc->original, &smd, FALSE, NULL, 0, 0); - - if(ss_mesh) - { - vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT); - if(vert) - { - //TRICKY: this code assumes subsurface will have the transformed original vertices - //in their original order at the end of the vert array. - vert = vert - + ss_mesh->getNumVerts(ss_mesh) - - calc->original->getNumVerts(calc->original); - } - } - - //To make sure we are not letting any memory behind - assert(smd.emCache == NULL); - assert(smd.mCache == NULL); - } - else - vert = calc->original->getVertDataArray(calc->original, CD_MVERT); - - //Not able to get vert information: jump to "free memory and return" part - if(vert == NULL) break; + if(calc->vert == NULL) return; } else { - //The code supports any axis that is a combination of X,Y,Z.. altought currently UI only allows to set the 3 diferent axis + //The code supports any axis that is a combination of X,Y,Z + //altought currently UI only allows to set the 3 diferent axis if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) proj_axis[0] = 1.0f; if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) proj_axis[1] = 1.0f; if(calc->smd->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) proj_axis[2] = 1.0f; Normalize(proj_axis); - //Invalid projection direction: jump to "free memory and return" part - if(INPR(proj_axis, proj_axis) < FLT_EPSILON) break; + //Invalid projection direction + if(INPR(proj_axis, proj_axis) < FLT_EPSILON) + return; } - //If the user doesn't allows to project in any direction of projection axis... then theres nothing todo. - if((use_normal & (MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR | MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR)) == 0) - break; //jump to "free memory and return" part - - - //Build target tree - BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6)); - if(treeData.tree == NULL) - break; //jump to "free memory and return" part - - - //Build auxiliar target if(calc->smd->auxTarget) { + auxMesh = object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH); space_transform_setup( &local2aux, calc->ob, calc->smd->auxTarget); - - aux_mesh = CDDM_copy( object_get_derived_final(calc->smd->auxTarget, CD_MASK_BAREMESH) ); //TODO currently we need a copy in case object_get_derived_final returns an emDM that does not defines getVertArray or getFace array - if(aux_mesh) - BENCH(bvhtree_from_mesh_faces(&auxData, aux_mesh, 0.0, 4, 6)); - else - printf("Auxiliar target finalDerived mesh is null\n"); } - - //Now, everything is ready to project the vertexs! -#pragma omp parallel for private(i,hit) schedule(static) - for(i = 0; inumVerts; ++i) + //After sucessufuly build the trees, start projection vertexs + if( bvhtree_from_mesh_faces(&treeData, calc->target, calc->keepDist, 4, 6) + && (auxMesh == NULL || bvhtree_from_mesh_faces(&auxData, auxMesh, 0.0, 4, 6))) { - float *co = calc->vertexCos[i]; - float tmp_co[3], tmp_no[3]; - float lim = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that - float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup); - if(weight == 0.0f) continue; - if(ss_mesh) +#pragma omp parallel for private(i,hit) schedule(static) + for(i = 0; inumVerts; ++i) { - VECCOPY(tmp_co, vert[i].co); - } - else - { - VECCOPY(tmp_co, co); - } + float *co = calc->vertexCos[i]; + float tmp_co[3], tmp_no[3]; + float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup); + + if(weight == 0.0f) continue; + + if(calc->vert) + { + VECCOPY(tmp_co, calc->vert[i].co); + if(calc->smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL) + NormalShortToFloat(tmp_no, calc->vert[i].no); + else + VECCOPY(tmp_no, proj_axis); + } + else + { + VECCOPY(tmp_co, co); + VECCOPY(tmp_no, proj_axis); + } - if(vert) - NormalShortToFloat(tmp_no, vert[i].no); - else - VECCOPY( tmp_no, proj_axis ); + hit.index = -1; + hit.dist = 10000.0f; //TODO: we should use FLT_MAX here, but sweepsphere code isnt prepared for that + + //Project over positive direction of axis + if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) + { + + if(auxData.tree) + normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); + + normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); + } + + //Project over negative direction of axis + if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) + { + float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] }; - hit.index = -1; - hit.dist = lim; + if(auxData.tree) + normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); + + normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); + } - //Project over positive direction of axis - if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) - { - - if(auxData.tree) - normal_projection_project_vertex(0, tmp_co, tmp_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); - - normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); - } - - //Project over negative direction of axis - if(use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR) - { - float inv_no[3] = { -tmp_no[0], -tmp_no[1], -tmp_no[2] }; - - - if(auxData.tree) - normal_projection_project_vertex(0, tmp_co, inv_no, &local2aux, auxData.tree, &hit, auxData.raycast_callback, &auxData); - - normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, &calc->local2target, treeData.tree, &hit, treeData.raycast_callback, &treeData); - } - - - if(hit.index != -1) - { - VecLerpf(co, co, hit.co, weight); + if(hit.index != -1) + { + VecLerpf(co, co, hit.co, weight); + } } } - -//Simple do{} while(0) structure to allow to easily jump to the "free memory and return" part -} while(0); - //free data structures - free_bvhtree_from_mesh(&treeData); free_bvhtree_from_mesh(&auxData); - - if(aux_mesh) - aux_mesh->release(aux_mesh); - - if(ss_mesh) - ss_mesh->release(ss_mesh); } /* @@ -516,14 +499,9 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) { int i; - const int vgroup = get_named_vertexgroup_num(calc->ob, calc->smd->vgroup_name); - const MDeformVert *const dvert = calc->original ? calc->original->getVertDataArray(calc->original, CD_MDEFORMVERT) : NULL; - BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; BVHTreeNearest nearest = NULL_BVHTreeNearest; - - //Create a bvh-tree of the given target BENCH(bvhtree_from_mesh_faces( &treeData, calc->target, 0.0, 2, 6)); if(treeData.tree == NULL) return OUT_OF_MEMORY(); @@ -539,11 +517,18 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) { float *co = calc->vertexCos[i]; float tmp_co[3]; - float weight = vertexgroup_get_vertex_weight(dvert, i, vgroup); + float weight = vertexgroup_get_vertex_weight(calc->dvert, i, calc->vgroup); if(weight == 0.0f) continue; //Convert the vertex to tree coordinates - VECCOPY(tmp_co, co); + if(calc->vert) + { + VECCOPY(tmp_co, calc->vert[i].co); + } + else + { + VECCOPY(tmp_co, co); + } space_transform_apply(&calc->local2target, tmp_co); //Use local proximity heuristics (to reduce the nearest search) @@ -582,7 +567,6 @@ void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } } - free_bvhtree_from_mesh(&treeData); } diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index f393139ee3e..5aec47965fc 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1887,12 +1887,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height = 94; } else if (md->type==eModifierType_Shrinkwrap) { ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md; - height = 86 + 3; + height = 105 + 3; + if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT) - { height += 19*5; - if(smd->projAxis == 0) height += 19; - } else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE) height += 19; @@ -2542,16 +2540,14 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco cy -= 3; uiDefButS(block, MENU, B_MODIFIER_RECALC, shrinktypemenu, lx,(cy-=19),buttonWidth,19, &smd->shrinkType, 0, 0, 0, 0, "Selects type of shrinkwrap algorithm for target position."); + uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:", lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals"); + if (smd->shrinkType == MOD_SHRINKWRAP_PROJECT){ /* UI for projection axis */ uiBlockBeginAlign(block); uiDefButC(block, ROW, B_MODIFIER_RECALC, "Normal" , lx,(cy-=19),buttonWidth,19, &smd->projAxis, 18.0, MOD_SHRINKWRAP_PROJECT_OVER_NORMAL, 0, 0, "Projection over X axis"); - if(smd->projAxis == 0) - { - uiDefButC(block, NUM, B_MODIFIER_RECALC, "SS Levels:", lx, (cy-=19), buttonWidth,19, &smd->subsurfLevels, 0, 6, 0, 0, "This indicates the number of CCSubdivisions that must be performed before extracting vertexs positions and normals"); - } uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS, B_MODIFIER_RECALC, "X", lx+buttonWidth/3*0,(cy-=19),buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over X axis"); uiDefButBitC(block, TOG, MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS, B_MODIFIER_RECALC, "Y", lx+buttonWidth/3*1,cy,buttonWidth/3,19, &smd->projAxis, 0, 0, 0, 0, "Projection over Y axis"); From 2f9f0710d140466f3b8030b66f4637b7f12b9d4a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 19 Sep 2008 12:05:45 +0000 Subject: [PATCH 04/10] Revert last merge from trunk svn merge -r 16539:16538 https://svn.blender.org/svnroot/bf-blender/branches/soc-2008-jaguarandi/ --- CMake/macros.cmake | 4 - CMakeLists.txt | 21 +- blenderplayer/CMakeLists.txt | 2 - config/darwin-config.py | 1 + config/linux2-config.py | 2 - .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 126 +- extern/bullet2/readme.txt | 5 - extern/bullet2/src/Bullet-C-Api.h | 140 +- .../BroadphaseCollision/btAxisSweep3.cpp | 636 ++- .../BroadphaseCollision/btAxisSweep3.h | 870 +--- .../btBroadphaseInterface.h | 28 +- .../BroadphaseCollision/btBroadphaseProxy.h | 55 +- .../btCollisionAlgorithm.cpp | 2 +- .../btCollisionAlgorithm.h | 11 +- .../BroadphaseCollision/btDbvt.cpp | 1289 ----- .../BroadphaseCollision/btDbvt.h | 1111 ----- .../BroadphaseCollision/btDbvtBroadphase.cpp | 344 -- .../BroadphaseCollision/btDbvtBroadphase.h | 103 - .../BroadphaseCollision/btDispatcher.h | 22 +- .../btMultiSapBroadphase.cpp | 466 -- .../btMultiSapBroadphase.h | 144 - .../btOverlappingPairCache.cpp | 515 +- .../btOverlappingPairCache.h | 351 +- .../btOverlappingPairCallback.h | 40 - .../BroadphaseCollision/btQuantizedBvh.cpp | 1025 ---- .../BroadphaseCollision/btQuantizedBvh.h | 486 -- .../btSimpleBroadphase.cpp | 232 +- .../BroadphaseCollision/btSimpleBroadphase.h | 94 +- .../src/BulletCollision/CMakeLists.txt | 93 - .../SphereTriangleDetector.cpp | 15 +- .../SphereTriangleDetector.h | 6 +- .../btBoxBoxCollisionAlgorithm.cpp | 85 - .../btBoxBoxCollisionAlgorithm.h | 66 - .../CollisionDispatch/btBoxBoxDetector.cpp | 683 --- .../CollisionDispatch/btBoxBoxDetector.h | 44 - .../btCollisionConfiguration.h | 47 - .../CollisionDispatch/btCollisionCreateFunc.h | 2 +- .../btCollisionDispatcher.cpp | 237 +- .../CollisionDispatch/btCollisionDispatcher.h | 62 +- .../CollisionDispatch/btCollisionObject.cpp | 12 +- .../CollisionDispatch/btCollisionObject.h | 89 +- .../CollisionDispatch/btCollisionWorld.cpp | 626 +-- .../CollisionDispatch/btCollisionWorld.h | 202 +- .../btCompoundCollisionAlgorithm.cpp | 217 +- .../btCompoundCollisionAlgorithm.h | 33 +- .../btConvexConcaveCollisionAlgorithm.cpp | 27 +- .../btConvexConcaveCollisionAlgorithm.h | 24 +- .../btConvexConvexAlgorithm.cpp | 20 +- .../btConvexConvexAlgorithm.h | 25 +- .../btConvexPlaneCollisionAlgorithm.cpp | 108 - .../btConvexPlaneCollisionAlgorithm.h | 71 - .../btDefaultCollisionConfiguration.cpp | 291 -- .../btDefaultCollisionConfiguration.h | 115 - .../btEmptyCollisionAlgorithm.h | 10 +- .../CollisionDispatch/btManifoldResult.cpp | 30 +- .../CollisionDispatch/btManifoldResult.h | 29 +- .../btSimulationIslandManager.cpp | 129 +- .../btSimulationIslandManager.h | 14 +- .../btSphereBoxCollisionAlgorithm.cpp | 19 +- .../btSphereBoxCollisionAlgorithm.h | 23 +- .../btSphereSphereCollisionAlgorithm.cpp | 19 +- .../btSphereSphereCollisionAlgorithm.h | 18 +- .../btSphereTriangleCollisionAlgorithm.cpp | 18 +- .../btSphereTriangleCollisionAlgorithm.h | 18 +- .../CollisionDispatch/btUnionFind.cpp | 4 +- .../CollisionDispatch/btUnionFind.h | 6 +- .../CollisionShapes/btBoxShape.cpp | 23 +- .../CollisionShapes/btBoxShape.h | 104 +- .../btBvhTriangleMeshShape.cpp | 223 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 40 +- .../CollisionShapes/btCapsuleShape.cpp | 36 +- .../CollisionShapes/btCapsuleShape.h | 78 +- .../CollisionShapes/btCollisionShape.cpp | 9 +- .../CollisionShapes/btCollisionShape.h | 45 +- .../CollisionShapes/btCompoundShape.cpp | 169 +- .../CollisionShapes/btCompoundShape.h | 93 +- .../CollisionShapes/btConcaveShape.h | 6 +- .../CollisionShapes/btConeShape.h | 12 +- .../CollisionShapes/btConvexHullShape.h | 20 +- .../CollisionShapes/btConvexInternalShape.cpp | 78 - .../CollisionShapes/btConvexInternalShape.h | 98 - .../CollisionShapes/btConvexShape.cpp | 59 + .../CollisionShapes/btConvexShape.h | 93 +- .../btConvexTriangleMeshShape.cpp | 115 +- .../btConvexTriangleMeshShape.h | 24 +- .../CollisionShapes/btCylinderShape.cpp | 14 +- .../CollisionShapes/btCylinderShape.h | 20 +- .../CollisionShapes/btEmptyShape.cpp | 2 +- .../CollisionShapes/btEmptyShape.h | 14 +- .../btHeightfieldTerrainShape.cpp | 115 +- .../btHeightfieldTerrainShape.h | 17 +- .../CollisionShapes/btMaterial.h | 34 - .../CollisionShapes/btMinkowskiSumShape.cpp | 6 +- .../CollisionShapes/btMinkowskiSumShape.h | 12 +- .../CollisionShapes/btMultiSphereShape.cpp | 4 +- .../CollisionShapes/btMultiSphereShape.h | 13 +- .../btMultimaterialTriangleMeshShape.cpp | 45 - .../btMultimaterialTriangleMeshShape.h | 124 - .../CollisionShapes/btOptimizedBvh.cpp | 661 ++- .../CollisionShapes/btOptimizedBvh.h | 297 +- .../btPolyhedralConvexShape.cpp | 42 +- .../CollisionShapes/btPolyhedralConvexShape.h | 38 +- .../btScaledBvhTriangleMeshShape.cpp | 103 - .../btScaledBvhTriangleMeshShape.h | 57 - .../CollisionShapes/btShapeHull.cpp | 164 - .../CollisionShapes/btShapeHull.h | 56 - .../CollisionShapes/btSphereShape.cpp | 2 +- .../CollisionShapes/btSphereShape.h | 20 +- .../CollisionShapes/btStaticPlaneShape.cpp | 5 +- .../CollisionShapes/btStaticPlaneShape.h | 16 +- .../btStridingMeshInterface.cpp | 6 +- .../CollisionShapes/btStridingMeshInterface.h | 12 +- .../CollisionShapes/btTetrahedronShape.h | 6 +- .../CollisionShapes/btTriangleBuffer.cpp | 9 +- .../CollisionShapes/btTriangleBuffer.h | 10 +- .../CollisionShapes/btTriangleCallback.h | 4 +- .../btTriangleIndexVertexArray.cpp | 45 +- .../btTriangleIndexVertexArray.h | 40 +- .../btTriangleIndexVertexMaterialArray.cpp | 86 - .../btTriangleIndexVertexMaterialArray.h | 84 - .../CollisionShapes/btTriangleMesh.cpp | 117 +- .../CollisionShapes/btTriangleMesh.h | 62 +- .../CollisionShapes/btTriangleMeshShape.cpp | 19 +- .../CollisionShapes/btTriangleMeshShape.h | 27 +- .../CollisionShapes/btTriangleShape.h | 18 +- .../CollisionShapes/btUniformScalingShape.cpp | 114 - .../CollisionShapes/btUniformScalingShape.h | 88 - .../btContinuousConvexCollision.cpp | 41 +- .../btContinuousConvexCollision.h | 6 +- .../NarrowPhaseCollision/btConvexCast.h | 18 +- .../btConvexPenetrationDepthSolver.h | 4 +- .../btDiscreteCollisionDetectorInterface.h | 6 +- .../NarrowPhaseCollision/btGjkConvexCast.cpp | 162 +- .../NarrowPhaseCollision/btGjkConvexCast.h | 10 +- .../NarrowPhaseCollision/btGjkEpa.cpp | 10 +- .../NarrowPhaseCollision/btGjkEpa.h | 8 +- .../NarrowPhaseCollision/btGjkEpa2.cpp | 943 ---- .../NarrowPhaseCollision/btGjkEpa2.h | 71 - .../btGjkEpaPenetrationDepthSolver.cpp | 13 +- .../btGjkEpaPenetrationDepthSolver.h | 2 +- .../btGjkPairDetector.cpp | 11 +- .../NarrowPhaseCollision/btGjkPairDetector.h | 12 +- .../NarrowPhaseCollision/btManifoldPoint.h | 26 +- .../btMinkowskiPenetrationDepthSolver.cpp | 7 +- .../btMinkowskiPenetrationDepthSolver.h | 2 +- .../btPersistentManifold.cpp | 38 +- .../btPersistentManifold.h | 62 +- .../btRaycastCallback.cpp | 66 +- .../NarrowPhaseCollision/btRaycastCallback.h | 24 +- .../btSimplexSolverInterface.h | 4 +- .../btSubSimplexConvexCast.cpp | 80 +- .../btVoronoiSimplexSolver.cpp | 2 +- .../bullet2/src/BulletDynamics/CMakeLists.txt | 18 +- .../btConeTwistConstraint.cpp | 48 +- .../ConstraintSolver/btConeTwistConstraint.h | 3 - .../ConstraintSolver/btConstraintSolver.h | 13 +- .../ConstraintSolver/btContactConstraint.cpp | 32 +- .../ConstraintSolver/btContactConstraint.h | 4 +- .../ConstraintSolver/btContactSolverInfo.h | 56 +- .../btGeneric6DofConstraint.cpp | 821 ++-- .../btGeneric6DofConstraint.h | 463 +- .../ConstraintSolver/btHingeConstraint.cpp | 272 +- .../ConstraintSolver/btHingeConstraint.h | 97 +- .../ConstraintSolver/btJacobianEntry.h | 4 +- .../btPoint2PointConstraint.cpp | 15 +- .../btPoint2PointConstraint.h | 18 +- .../btSequentialImpulseConstraintSolver.cpp | 840 ++-- .../btSequentialImpulseConstraintSolver.h | 48 +- .../ConstraintSolver/btSliderConstraint.cpp | 415 -- .../ConstraintSolver/btSliderConstraint.h | 218 - .../btSolve2LinearConstraint.h | 4 +- .../ConstraintSolver/btSolverBody.h | 64 +- .../ConstraintSolver/btSolverConstraint.h | 21 +- .../ConstraintSolver/btTypedConstraint.cpp | 15 +- .../ConstraintSolver/btTypedConstraint.h | 38 +- .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 294 +- .../Dynamics/btContinuousDynamicsWorld.cpp | 193 - .../Dynamics/btContinuousDynamicsWorld.h | 46 - .../Dynamics/btDiscreteDynamicsWorld.cpp | 537 +- .../Dynamics/btDiscreteDynamicsWorld.h | 44 +- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 84 +- .../BulletDynamics/Dynamics/btRigidBody.cpp | 222 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 189 +- .../Dynamics/btSimpleDynamicsWorld.cpp | 52 +- .../Dynamics/btSimpleDynamicsWorld.h | 32 +- .../Vehicle/btRaycastVehicle.cpp | 72 +- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 14 +- .../Vehicle/btVehicleRaycaster.h | 2 +- .../src/BulletDynamics/Vehicle/btWheelInfo.h | 4 +- .../bullet2/src/BulletSoftBody/CMakeLists.txt | 21 - .../bullet2/src/BulletSoftBody/btSoftBody.cpp | 2590 ---------- .../bullet2/src/BulletSoftBody/btSoftBody.h | 810 ---- .../btSoftBodyConcaveCollisionAlgorithm.cpp | 410 -- .../btSoftBodyConcaveCollisionAlgorithm.h | 118 - .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 653 --- .../src/BulletSoftBody/btSoftBodyHelpers.h | 107 - .../src/BulletSoftBody/btSoftBodyInternals.h | 896 ---- ...oftBodyRigidBodyCollisionConfiguration.cpp | 108 - ...tSoftBodyRigidBodyCollisionConfiguration.h | 48 - .../btSoftRigidCollisionAlgorithm.cpp | 79 - .../btSoftRigidCollisionAlgorithm.h | 75 - .../btSoftRigidDynamicsWorld.cpp | 126 - .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 73 - .../btSoftSoftCollisionAlgorithm.cpp | 46 - .../btSoftSoftCollisionAlgorithm.h | 69 - .../bullet2/src/BulletSoftBody/btSparseSDF.h | 306 -- extern/bullet2/src/LinearMath/CMakeLists.txt | 29 +- extern/bullet2/src/LinearMath/btAabbUtil2.h | 83 +- .../src/LinearMath/btAlignedAllocator.cpp | 185 +- .../src/LinearMath/btAlignedAllocator.h | 28 +- .../src/LinearMath/btAlignedObjectArray.h | 69 +- extern/bullet2/src/LinearMath/btConvexHull.h | 242 - .../src/LinearMath/btDefaultMotionState.h | 2 +- .../bullet2/src/LinearMath/btGeometryUtil.cpp | 9 +- .../bullet2/src/LinearMath/btGeometryUtil.h | 1 - extern/bullet2/src/LinearMath/btIDebugDraw.h | 16 - extern/bullet2/src/LinearMath/btMatrix3x3.h | 96 +- extern/bullet2/src/LinearMath/btMinMax.h | 12 +- extern/bullet2/src/LinearMath/btMotionState.h | 2 +- .../bullet2/src/LinearMath/btPoolAllocator.h | 97 - extern/bullet2/src/LinearMath/btQuadWord.h | 71 +- extern/bullet2/src/LinearMath/btQuaternion.h | 10 +- extern/bullet2/src/LinearMath/btQuickprof.cpp | 302 +- extern/bullet2/src/LinearMath/btQuickprof.h | 864 +++- extern/bullet2/src/LinearMath/btScalar.h | 268 +- extern/bullet2/src/LinearMath/btStackAlloc.h | 19 +- extern/bullet2/src/LinearMath/btTransform.h | 19 +- .../bullet2/src/LinearMath/btTransformUtil.h | 12 +- extern/bullet2/src/LinearMath/btVector3.h | 51 - extern/bullet2/src/SConscript | 73 +- extern/bullet2/src/btBulletCollisionCommon.h | 11 +- extern/bullet2/src/btBulletDynamicsCommon.h | 6 +- extern/glew/SConscript | 2 +- extern/glew/include/GL/glew.h | 7 +- extern/glew/src/glew.c | 2 - intern/SoundSystem/SoundDefines.h | 2 +- .../SoundSystem/openal/SND_OpenALDevice.cpp | 4 - intern/ghost/GHOST_ISystem.h | 4 +- intern/ghost/GHOST_Types.h | 10 - intern/ghost/intern/GHOST_SystemCarbon.cpp | 3 +- intern/ghost/intern/GHOST_SystemCarbon.h | 4 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 8 +- intern/ghost/intern/GHOST_SystemWin32.h | 3 +- intern/ghost/intern/GHOST_SystemX11.cpp | 13 +- intern/ghost/intern/GHOST_SystemX11.h | 6 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 8 +- intern/ghost/intern/GHOST_WindowX11.cpp | 67 +- intern/ghost/intern/GHOST_WindowX11.h | 2 - intern/guardedalloc/MEM_guardedalloc.h | 10 +- intern/guardedalloc/intern/mallocn.c | 21 +- intern/iksolver/CMakeLists.txt | 2 +- intern/iksolver/SConscript | 3 +- intern/memutil/MEM_Allocator.h | 1 - intern/memutil/MEM_CacheLimiter.h | 12 +- .../memutil/intern/MEM_CacheLimiterC-Api.cpp | 8 +- intern/moto/include/GEN_Map.h | 13 - intern/moto/include/MT_Matrix4x4.h | 1 - intern/moto/include/MT_Matrix4x4.inl | 14 +- intern/opennl/superlu/BLO_sys_types.h | 2 - .../blender/BPY_python/BPY_python.vcproj | 8 +- projectfiles_vc7/blender/blender.sln | 22 - projectfiles_vc7/blender/blender.vcproj | 10 +- .../blender/blenkernel/BKE_blenkernel.vcproj | 20 +- projectfiles_vc7/blender/gpu/BL_gpu.vcproj | 372 -- projectfiles_vc7/blender/nodes/nodes.vcproj | 8 +- .../blender/radiosity/BRA_radiosity.vcproj | 4 +- projectfiles_vc7/blender/src/BL_src.vcproj | 10 +- .../blenderhook/KX_blenderhook.vcproj | 4 +- .../gameengine/converter/KX_converter.vcproj | 12 +- .../expression/EXP_expressions.vcproj | 12 +- .../gameengine/gamelogic/SCA_GameLogic.vcproj | 12 +- .../gameplayer/ghost/GP_ghost.vcproj | 4 +- .../gameengine/ketsji/KX_ketsji.vcproj | 18 +- .../PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj | 10 +- .../RAS_openglrasterizer.vcproj | 12 +- release/datafiles/blenderbuttons | Bin 68242 -> 69599 bytes release/scripts/mesh_cleanup.py | 32 +- release/scripts/object_find.py | 26 +- release/scripts/sysinfo.py | 2 - source/Makefile | 9 +- source/blender/CMakeLists.txt | 2 +- source/blender/Makefile | 2 +- source/blender/SConscript | 1 - source/blender/blenkernel/BKE_DerivedMesh.h | 49 +- source/blender/blenkernel/BKE_action.h | 2 +- .../blender/blenkernel/BKE_bad_level_calls.h | 4 + source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_colortools.h | 1 - source/blender/blenkernel/BKE_global.h | 9 +- source/blender/blenkernel/BKE_mesh.h | 1 + source/blender/blenkernel/BKE_node.h | 8 - source/blender/blenkernel/BKE_particle.h | 1 - source/blender/blenkernel/BKE_suggestions.h | 93 - source/blender/blenkernel/BKE_text.h | 29 +- source/blender/blenkernel/BKE_texture.h | 1 - source/blender/blenkernel/BKE_utildefines.h | 2 - source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/SConscript | 1 - .../blenkernel/bad_level_call_stubs/stubs.c | 32 +- .../blender/blenkernel/intern/DerivedMesh.c | 407 +- source/blender/blenkernel/intern/Makefile | 4 - source/blender/blenkernel/intern/action.c | 4 +- source/blender/blenkernel/intern/anim.c | 21 +- source/blender/blenkernel/intern/armature.c | 21 +- source/blender/blenkernel/intern/blender.c | 36 +- .../blender/blenkernel/intern/cdderivedmesh.c | 138 +- source/blender/blenkernel/intern/colortools.c | 21 - source/blender/blenkernel/intern/constraint.c | 108 +- source/blender/blenkernel/intern/depsgraph.c | 15 +- source/blender/blenkernel/intern/effect.c | 15 +- source/blender/blenkernel/intern/exotic.c | 14 +- source/blender/blenkernel/intern/image.c | 11 +- source/blender/blenkernel/intern/ipo.c | 27 +- source/blender/blenkernel/intern/material.c | 7 - source/blender/blenkernel/intern/mesh.c | 39 + source/blender/blenkernel/intern/modifier.c | 14 +- source/blender/blenkernel/intern/node.c | 114 - source/blender/blenkernel/intern/object.c | 15 +- source/blender/blenkernel/intern/particle.c | 33 +- .../blenkernel/intern/particle_system.c | 657 +-- source/blender/blenkernel/intern/shrinkwrap.c | 14 +- source/blender/blenkernel/intern/softbody.c | 76 +- .../blender/blenkernel/intern/subsurf_ccg.c | 179 +- .../blender/blenkernel/intern/suggestions.c | 254 - source/blender/blenkernel/intern/text.c | 564 +-- source/blender/blenkernel/intern/texture.c | 12 - source/blender/blenlib/BLI_arithb.h | 2 - source/blender/blenlib/BLI_blenlib.h | 2 +- source/blender/blenlib/BLI_kdopbvh.h | 3 +- source/blender/blenlib/SConscript | 2 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 36 +- source/blender/blenlib/intern/arithb.c | 30 - source/blender/blenlib/intern/util.c | 43 - source/blender/blenloader/BLO_readfile.h | 2 +- source/blender/blenloader/BLO_sys_types.h | 14 +- source/blender/blenloader/intern/readfile.c | 36 +- source/blender/blenloader/intern/writefile.c | 14 +- source/blender/gpu/CMakeLists.txt | 34 - source/blender/gpu/GPU_draw.h | 116 - source/blender/gpu/GPU_extensions.h | 144 - source/blender/gpu/GPU_material.h | 169 - source/blender/gpu/Makefile | 37 - source/blender/gpu/SConscript | 11 - source/blender/gpu/intern/Makefile | 53 - source/blender/gpu/intern/gpu_codegen.c | 1441 ------ source/blender/gpu/intern/gpu_codegen.h | 87 - source/blender/gpu/intern/gpu_draw.c | 1168 ----- source/blender/gpu/intern/gpu_extensions.c | 987 ---- source/blender/gpu/intern/gpu_material.c | 1496 ------ .../gpu/intern/gpu_shader_material.glsl | 1555 ------ .../gpu/intern/gpu_shader_material.glsl.c | 1032 ---- .../blender/gpu/intern/gpu_shader_vertex.glsl | 12 - .../gpu/intern/gpu_shader_vertex.glsl.c | 13 - source/blender/imbuf/intern/bmp.c | 4 +- .../blender/imbuf/intern/dds/ColorBlock.cpp | 37 +- source/blender/imbuf/intern/dds/ColorBlock.h | 2 - .../imbuf/intern/dds/DirectDrawSurface.cpp | 307 +- .../imbuf/intern/dds/DirectDrawSurface.h | 4 - source/blender/imbuf/intern/dds/dds_api.cpp | 1 - source/blender/include/BDR_drawmesh.h | 43 +- source/blender/include/BDR_drawobject.h | 3 +- source/blender/include/BDR_gpencil.h | 3 - source/blender/include/BDR_imagepaint.h | 4 +- source/blender/include/BIF_drawseq.h | 2 - source/blender/include/BIF_drawtext.h | 6 +- source/blender/include/BIF_editaction.h | 2 +- source/blender/include/BIF_editarmature.h | 4 +- source/blender/include/BIF_editview.h | 1 - source/blender/include/BIF_gl.h | 15 +- source/blender/include/BIF_glutil.h | 1 - source/blender/include/BIF_keyframing.h | 99 - source/blender/include/BIF_keyval.h | 3 - source/blender/include/BIF_meshlaplacian.h | 2 +- source/blender/include/BIF_meshtools.h | 2 - source/blender/include/BIF_resources.h | 10 +- source/blender/include/BIF_space.h | 4 - source/blender/include/BSE_drawipo.h | 3 - source/blender/include/BSE_drawview.h | 6 +- source/blender/include/BSE_editipo.h | 13 +- source/blender/include/blendef.h | 8 - source/blender/include/transform.h | 2 +- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/makesdna/DNA_actuator_types.h | 14 +- source/blender/makesdna/DNA_brush_types.h | 4 +- source/blender/makesdna/DNA_gpencil_types.h | 2 +- source/blender/makesdna/DNA_group_types.h | 2 +- source/blender/makesdna/DNA_image_types.h | 4 +- source/blender/makesdna/DNA_ipo_types.h | 28 +- source/blender/makesdna/DNA_lamp_types.h | 16 +- source/blender/makesdna/DNA_material_types.h | 11 +- source/blender/makesdna/DNA_meshdata_types.h | 1 - source/blender/makesdna/DNA_object_types.h | 8 +- source/blender/makesdna/DNA_particle_types.h | 1 - source/blender/makesdna/DNA_scene_types.h | 3 +- source/blender/makesdna/DNA_sensor_types.h | 9 +- source/blender/makesdna/DNA_space_types.h | 14 +- source/blender/makesdna/DNA_text_types.h | 25 +- source/blender/makesdna/DNA_texture_types.h | 1 - source/blender/makesdna/DNA_userdef_types.h | 2 - source/blender/makesdna/DNA_view3d_types.h | 3 +- source/blender/makesdna/DNA_world_types.h | 4 +- source/blender/nodes/CMakeLists.txt | 2 +- source/blender/nodes/SConscript | 1 - .../nodes/intern/CMP_nodes/CMP_tonemap.c | 9 +- .../blender/nodes/intern/CMP_nodes/Makefile | 1 - source/blender/nodes/intern/Makefile | 2 - .../blender/nodes/intern/SHD_nodes/Makefile | 2 - .../nodes/intern/SHD_nodes/SHD_camera.c | 10 +- .../nodes/intern/SHD_nodes/SHD_curves.c | 24 +- .../blender/nodes/intern/SHD_nodes/SHD_geom.c | 16 +- .../nodes/intern/SHD_nodes/SHD_hueSatVal.c | 9 +- .../nodes/intern/SHD_nodes/SHD_invert.c | 8 +- .../nodes/intern/SHD_nodes/SHD_mapping.c | 17 +- .../nodes/intern/SHD_nodes/SHD_material.c | 79 +- .../blender/nodes/intern/SHD_nodes/SHD_math.c | 43 +- .../nodes/intern/SHD_nodes/SHD_mixRgb.c | 14 +- .../nodes/intern/SHD_nodes/SHD_normal.c | 11 +- .../nodes/intern/SHD_nodes/SHD_output.c | 16 +- .../blender/nodes/intern/SHD_nodes/SHD_rgb.c | 11 +- .../nodes/intern/SHD_nodes/SHD_sepcombRGB.c | 16 +- .../nodes/intern/SHD_nodes/SHD_squeeze.c | 8 +- .../nodes/intern/SHD_nodes/SHD_texture.c | 17 +- .../nodes/intern/SHD_nodes/SHD_valToRgb.c | 20 +- .../nodes/intern/SHD_nodes/SHD_value.c | 9 +- .../nodes/intern/SHD_nodes/SHD_vectMath.c | 31 +- source/blender/nodes/intern/SHD_util.h | 2 - source/blender/python/BPY_extern.h | 5 +- source/blender/python/BPY_interface.c | 138 +- source/blender/python/BPY_menus.c | 40 +- source/blender/python/BPY_menus.h | 2 - source/blender/python/CMakeLists.txt | 6 +- source/blender/python/SConscript | 4 - source/blender/python/api2_2x/BGL.h | 9 +- source/blender/python/api2_2x/Blender.c | 22 +- source/blender/python/api2_2x/Camera.c | 1 - source/blender/python/api2_2x/Constraint.c | 3 +- source/blender/python/api2_2x/Draw.c | 110 +- source/blender/python/api2_2x/Group.c | 31 - source/blender/python/api2_2x/Image.c | 4 +- source/blender/python/api2_2x/Ipo.c | 1 - source/blender/python/api2_2x/Ipocurve.c | 1 - source/blender/python/api2_2x/Lamp.c | 122 +- source/blender/python/api2_2x/MTex.c | 347 +- source/blender/python/api2_2x/MTex.h | 8 +- source/blender/python/api2_2x/Makefile | 6 - source/blender/python/api2_2x/Material.c | 288 +- source/blender/python/api2_2x/Mathutils.c | 2 +- source/blender/python/api2_2x/Mathutils.h | 2 +- source/blender/python/api2_2x/Mesh.c | 5 +- source/blender/python/api2_2x/Object.c | 3 +- source/blender/python/api2_2x/Particle.c | 14 +- source/blender/python/api2_2x/Pose.c | 1 - source/blender/python/api2_2x/Text.c | 405 +- source/blender/python/api2_2x/Text.h | 2 - source/blender/python/api2_2x/Texture.c | 7 - source/blender/python/api2_2x/Window.c | 13 +- source/blender/python/api2_2x/World.c | 103 - source/blender/python/api2_2x/bpy_data.c | 15 +- source/blender/python/api2_2x/doc/Draw.py | 8 +- source/blender/python/api2_2x/doc/Group.py | 2 - source/blender/python/api2_2x/doc/Lamp.py | 2 - source/blender/python/api2_2x/doc/Material.py | 62 +- source/blender/python/api2_2x/doc/Mesh.py | 3 +- source/blender/python/api2_2x/doc/Text.py | 103 +- source/blender/python/api2_2x/doc/Texture.py | 151 +- source/blender/python/api2_2x/doc/World.py | 2 - source/blender/python/api2_2x/gen_utils.h | 1 - source/blender/python/api2_2x/sceneSequence.c | 115 +- source/blender/radiosity/CMakeLists.txt | 2 +- source/blender/radiosity/SConscript | 2 +- .../blender/radiosity/intern/source/Makefile | 1 - .../readblenfile/intern/BLO_readblenfile.c | 2 +- .../render/intern/include/render_types.h | 3 +- .../render/intern/source/convertblender.c | 20 +- .../render/intern/source/imagetexture.c | 8 +- .../blender/render/intern/source/pipeline.c | 27 +- .../blender/render/intern/source/rayshade.c | 5 +- .../blender/render/intern/source/rendercore.c | 30 +- .../render/intern/source/renderdatabase.c | 14 +- source/blender/render/intern/source/shadbuf.c | 4 +- .../render/intern/source/shadeoutput.c | 16 +- source/blender/render/intern/source/zbuf.c | 92 +- source/blender/src/CMakeLists.txt | 2 +- source/blender/src/Makefile | 1 - source/blender/src/SConscript | 3 +- source/blender/src/blenderbuttons.c | 4310 +++++++++-------- source/blender/src/buttons_editing.c | 25 +- source/blender/src/buttons_logic.c | 399 +- source/blender/src/buttons_object.c | 45 +- source/blender/src/buttons_scene.c | 8 +- source/blender/src/buttons_shading.c | 139 +- source/blender/src/drawaction.c | 13 - source/blender/src/drawarmature.c | 3 - source/blender/src/drawgpencil.c | 223 +- source/blender/src/drawimage.c | 56 +- source/blender/src/drawipo.c | 11 +- source/blender/src/drawmesh.c | 773 ++- source/blender/src/drawobject.c | 331 +- source/blender/src/drawseq.c | 17 +- source/blender/src/drawtext.c | 2799 +++-------- source/blender/src/drawview.c | 524 +- source/blender/src/editaction.c | 3 +- source/blender/src/editarmature.c | 103 - source/blender/src/editdeform.c | 2 +- source/blender/src/editface.c | 7 +- source/blender/src/editipo.c | 1475 +++++- source/blender/src/editipo_lib.c | 10 +- source/blender/src/editipo_mods.c | 1 + source/blender/src/editkey.c | 5 +- source/blender/src/editlattice.c | 2 +- source/blender/src/editmesh.c | 4 - source/blender/src/editmesh_add.c | 152 +- source/blender/src/editmesh_loop.c | 6 +- source/blender/src/editmesh_mods.c | 17 +- source/blender/src/editmesh_tools.c | 399 +- source/blender/src/editmode_undo.c | 40 +- source/blender/src/editnode.c | 6 +- source/blender/src/editobject.c | 35 +- source/blender/src/editscreen.c | 7 +- source/blender/src/editsound.c | 15 - source/blender/src/editview.c | 5 +- source/blender/src/filesel.c | 22 +- source/blender/src/glutil.c | 79 +- source/blender/src/gpencil.c | 588 +-- source/blender/src/header_image.c | 11 +- source/blender/src/header_info.c | 115 +- source/blender/src/header_ipo.c | 2 +- source/blender/src/header_node.c | 6 +- source/blender/src/header_text.c | 215 +- source/blender/src/header_view3d.c | 48 +- source/blender/src/headerbuttons.c | 7 +- source/blender/src/imagepaint.c | 309 +- source/blender/src/keyframing.c | 1838 ------- source/blender/src/keyval.c | 195 - source/blender/src/meshlaplacian.c | 10 +- source/blender/src/meshtools.c | 5 +- source/blender/src/mywindow.c | 12 + source/blender/src/playanim.c | 20 +- source/blender/src/poselib.c | 2 +- source/blender/src/poseobject.c | 2 - source/blender/src/previewrender.c | 32 - source/blender/src/renderwin.c | 17 +- source/blender/src/resources.c | 2 - source/blender/src/sculptmode.c | 7 +- source/blender/src/sequence.c | 13 +- source/blender/src/space.c | 86 +- source/blender/src/toets.c | 9 +- source/blender/src/toolbox.c | 14 +- source/blender/src/transform_conversions.c | 138 +- source/blender/src/transform_generics.c | 47 +- source/blender/src/transform_numinput.c | 14 - source/blender/src/transform_orientations.c | 2 +- source/blender/src/usiblender.c | 42 +- source/blender/src/verse_image.c | 4 +- source/blender/src/view.c | 135 +- source/blender/yafray/intern/export_File.cpp | 2 +- .../blender/yafray/intern/export_Plugin.cpp | 2 +- source/creator/CMakeLists.txt | 7 +- source/creator/Makefile | 2 - source/creator/SConscript | 2 +- source/creator/creator.c | 44 +- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 41 +- .../gameengine/BlenderRoutines/CMakeLists.txt | 1 - .../BlenderRoutines/KX_BlenderGL.cpp | 75 + .../gameengine/BlenderRoutines/KX_BlenderGL.h | 3 + .../BlenderRoutines/KX_BlenderRenderTools.cpp | 266 +- .../BlenderRoutines/KX_BlenderRenderTools.h | 69 +- source/gameengine/BlenderRoutines/Makefile | 5 +- source/gameengine/BlenderRoutines/SConscript | 5 +- .../Converter/BL_ActionActuator.cpp | 1 - .../Converter/BL_ArmatureObject.cpp | 80 +- .../gameengine/Converter/BL_ArmatureObject.h | 9 +- .../Converter/BL_BlenderDataConversion.cpp | 199 +- .../Converter/BL_DeformableGameObject.cpp | 8 +- .../gameengine/Converter/BL_MeshDeformer.cpp | 89 +- source/gameengine/Converter/BL_MeshDeformer.h | 3 +- .../Converter/BL_ShapeActionActuator.cpp | 2 +- .../gameengine/Converter/BL_ShapeDeformer.cpp | 3 + .../gameengine/Converter/BL_ShapeDeformer.h | 11 + .../gameengine/Converter/BL_SkinDeformer.cpp | 47 +- source/gameengine/Converter/BL_SkinDeformer.h | 16 +- .../Converter/BL_SkinMeshObject.cpp | 74 +- .../gameengine/Converter/BL_SkinMeshObject.h | 45 +- source/gameengine/Converter/CMakeLists.txt | 1 - .../Converter/KX_BlenderSceneConverter.cpp | 72 +- .../Converter/KX_BlenderSceneConverter.h | 2 - .../Converter/KX_ConvertActuators.cpp | 132 +- .../Converter/KX_ConvertSensors.cpp | 22 +- source/gameengine/Converter/Makefile | 1 - source/gameengine/Converter/SConscript | 2 +- source/gameengine/Expressions/Makefile | 1 - .../gameengine/Expressions/PyObjectPlus.cpp | 4 +- source/gameengine/Expressions/PyObjectPlus.h | 39 - source/gameengine/Expressions/Value.cpp | 30 +- .../GameLogic/Joystick/SCA_Joystick.cpp | 207 +- .../GameLogic/Joystick/SCA_Joystick.h | 206 +- .../GameLogic/Joystick/SCA_JoystickDefines.h | 8 +- .../GameLogic/Joystick/SCA_JoystickEvents.cpp | 56 +- .../GameLogic/Joystick/SCA_JoystickPrivate.h | 4 + source/gameengine/GameLogic/Makefile | 1 - .../GameLogic/SCA_2DFilterActuator.cpp | 8 +- .../gameengine/GameLogic/SCA_IController.cpp | 2 - .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 1 - source/gameengine/GameLogic/SCA_ISensor.cpp | 48 +- source/gameengine/GameLogic/SCA_ISensor.h | 13 +- .../GameLogic/SCA_JoystickManager.cpp | 35 +- .../GameLogic/SCA_JoystickManager.h | 4 +- .../GameLogic/SCA_JoystickSensor.cpp | 162 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 43 +- .../GameLogic/SCA_KeyboardSensor.cpp | 2 +- .../gameengine/GameLogic/SCA_LogicManager.cpp | 31 +- .../gameengine/GameLogic/SCA_LogicManager.h | 2 - .../GameLogic/SCA_PythonController.cpp | 13 +- .../GameLogic/SCA_PythonController.h | 6 - source/gameengine/GamePlayer/CMakeLists.txt | 4 - .../GamePlayer/common/CMakeLists.txt | 2 +- .../GamePlayer/common/GPC_RenderTools.cpp | 546 ++- .../GamePlayer/common/GPC_RenderTools.h | 156 +- source/gameengine/GamePlayer/common/Makefile | 5 +- .../gameengine/GamePlayer/common/SConscript | 2 +- .../common/unix/GPU_PolygonMaterial.h | 4 +- .../GamePlayer/ghost/CMakeLists.txt | 1 - .../GamePlayer/ghost/GPG_Application.cpp | 113 +- .../GamePlayer/ghost/GPG_Application.h | 9 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 96 +- source/gameengine/GamePlayer/ghost/Makefile | 5 +- source/gameengine/GamePlayer/ghost/SConscript | 4 +- source/gameengine/Ketsji/BL_BlenderShader.cpp | 136 +- source/gameengine/Ketsji/BL_BlenderShader.h | 10 +- source/gameengine/Ketsji/BL_Material.h | 6 +- source/gameengine/Ketsji/BL_Shader.cpp | 12 +- source/gameengine/Ketsji/BL_Shader.h | 2 +- source/gameengine/Ketsji/CMakeLists.txt | 1 - .../KXNetwork/KX_NetworkMessageSensor.cpp | 68 +- .../KXNetwork/KX_NetworkMessageSensor.h | 10 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 126 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 3 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 2 - .../Ketsji/KX_ConstraintActuator.cpp | 50 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 5 +- .../Ketsji/KX_ConstraintWrapper.cpp | 1 - .../Ketsji/KX_ConvertPhysicsObject.h | 1 - .../Ketsji/KX_ConvertPhysicsObjects.cpp | 165 +- source/gameengine/Ketsji/KX_GameActuator.cpp | 66 - source/gameengine/Ketsji/KX_GameActuator.h | 2 - source/gameengine/Ketsji/KX_GameObject.cpp | 345 +- source/gameengine/Ketsji/KX_GameObject.h | 107 +- .../gameengine/Ketsji/KX_IPO_SGController.cpp | 2 +- source/gameengine/Ketsji/KX_ISceneConverter.h | 4 - source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 204 +- source/gameengine/Ketsji/KX_KetsjiEngine.h | 13 +- source/gameengine/Ketsji/KX_Light.cpp | 64 +- source/gameengine/Ketsji/KX_Light.h | 11 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 46 +- source/gameengine/Ketsji/KX_MeshProxy.h | 2 - .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 17 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 6 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 2 - .../Ketsji/KX_PhysicsObjectWrapper.cpp | 2 - .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 50 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 2 + .../Ketsji/KX_PyConstraintBinding.cpp | 2 - source/gameengine/Ketsji/KX_PythonInit.cpp | 654 +-- source/gameengine/Ketsji/KX_PythonInit.h | 6 +- source/gameengine/Ketsji/KX_RayCast.cpp | 85 +- source/gameengine/Ketsji/KX_RayCast.h | 62 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 58 +- source/gameengine/Ketsji/KX_RaySensor.h | 8 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 122 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 30 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 41 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 2 +- .../KX_SG_BoneParentNodeRelationship.cpp | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 33 +- source/gameengine/Ketsji/KX_Scene.h | 10 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 64 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 2 - .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 2 - source/gameengine/Ketsji/KX_VertexProxy.cpp | 14 +- .../Ketsji/KX_VisibilityActuator.cpp | 10 +- .../gameengine/Ketsji/KX_VisibilityActuator.h | 2 - source/gameengine/Ketsji/Makefile | 11 +- source/gameengine/Ketsji/SConscript | 5 +- .../Physics/BlOde/OdePhysicsEnvironment.cpp | 3 +- .../Physics/BlOde/OdePhysicsEnvironment.h | 3 +- .../Physics/Bullet/CcdPhysicsController.cpp | 89 +- .../Physics/Bullet/CcdPhysicsController.h | 29 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 206 +- .../Physics/Bullet/CcdPhysicsEnvironment.h | 7 +- source/gameengine/Physics/Bullet/Makefile | 5 - .../Physics/Dummy/DummyPhysicsEnvironment.cpp | 3 +- .../Physics/Dummy/DummyPhysicsEnvironment.h | 3 +- .../Physics/Sumo/SumoPhysicsEnvironment.cpp | 31 +- .../Physics/Sumo/SumoPhysicsEnvironment.h | 3 +- .../Physics/common/PHY_IPhysicsEnvironment.h | 47 +- source/gameengine/PyDoc/GameKeys.py | 9 - source/gameengine/PyDoc/GameLogic.py | 9 +- source/gameengine/PyDoc/KX_GameObject.py | 90 +- source/gameengine/PyDoc/KX_MeshProxy.py | 15 - source/gameengine/PyDoc/KX_ObjectActuator.py | 4 +- .../PyDoc/KX_SCA_AddObjectActuator.py | 17 - .../PyDoc/KX_SCA_ReplaceMeshActuator.py | 5 +- source/gameengine/PyDoc/KX_TrackToActuator.py | 2 +- source/gameengine/PyDoc/Rasterizer.py | 39 +- source/gameengine/PyDoc/SCA_DelaySensor.py | 2 +- source/gameengine/PyDoc/SCA_ISensor.py | 7 +- source/gameengine/Rasterizer/Makefile | 4 + .../Rasterizer/RAS_BucketManager.cpp | 256 +- .../gameengine/Rasterizer/RAS_BucketManager.h | 31 +- .../Rasterizer/RAS_FramingManager.h | 15 +- .../Rasterizer/RAS_IPolygonMaterial.cpp | 25 +- .../Rasterizer/RAS_IPolygonMaterial.h | 9 +- .../gameengine/Rasterizer/RAS_IRasterizer.h | 50 +- .../Rasterizer/RAS_IRenderTools.cpp | 24 +- .../gameengine/Rasterizer/RAS_IRenderTools.h | 39 +- .../Rasterizer/RAS_MaterialBucket.cpp | 606 +-- .../Rasterizer/RAS_MaterialBucket.h | 211 +- .../gameengine/Rasterizer/RAS_MeshObject.cpp | 993 ++-- source/gameengine/Rasterizer/RAS_MeshObject.h | 256 +- .../RAS_OpenGLRasterizer/CMakeLists.txt | 1 - .../Rasterizer/RAS_OpenGLRasterizer/Makefile | 5 +- .../RAS_ListRasterizer.cpp | 84 +- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 24 +- .../RAS_OpenGLRasterizer.cpp | 798 ++- .../RAS_OpenGLRasterizer.h | 49 +- .../RAS_VAOpenGLRasterizer.cpp | 218 +- .../RAS_VAOpenGLRasterizer.h | 18 +- .../RAS_OpenGLRasterizer/SConscript | 5 +- source/gameengine/Rasterizer/RAS_Polygon.cpp | 87 +- source/gameengine/Rasterizer/RAS_Polygon.h | 56 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 32 +- source/gameengine/Rasterizer/RAS_TexVert.h | 28 +- source/gameengine/Rasterizer/SConscript | 5 +- source/kernel/gen_system/GEN_Map.h | 13 - source/nan_definitions.mk | 11 +- tools/Blender.py | 13 +- tools/btools.py | 6 +- 737 files changed, 18165 insertions(+), 56070 deletions(-) delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp delete mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp delete mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp delete mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h delete mode 100644 extern/bullet2/src/BulletSoftBody/CMakeLists.txt delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBody.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBody.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp delete mode 100644 extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h delete mode 100644 extern/bullet2/src/BulletSoftBody/btSparseSDF.h delete mode 100644 extern/bullet2/src/LinearMath/btConvexHull.h delete mode 100644 extern/bullet2/src/LinearMath/btPoolAllocator.h delete mode 100644 projectfiles_vc7/blender/gpu/BL_gpu.vcproj delete mode 100644 source/blender/blenkernel/BKE_suggestions.h delete mode 100644 source/blender/blenkernel/intern/suggestions.c delete mode 100644 source/blender/gpu/CMakeLists.txt delete mode 100644 source/blender/gpu/GPU_draw.h delete mode 100644 source/blender/gpu/GPU_extensions.h delete mode 100644 source/blender/gpu/GPU_material.h delete mode 100644 source/blender/gpu/Makefile delete mode 100644 source/blender/gpu/SConscript delete mode 100644 source/blender/gpu/intern/Makefile delete mode 100644 source/blender/gpu/intern/gpu_codegen.c delete mode 100644 source/blender/gpu/intern/gpu_codegen.h delete mode 100644 source/blender/gpu/intern/gpu_draw.c delete mode 100644 source/blender/gpu/intern/gpu_extensions.c delete mode 100644 source/blender/gpu/intern/gpu_material.c delete mode 100644 source/blender/gpu/intern/gpu_shader_material.glsl delete mode 100644 source/blender/gpu/intern/gpu_shader_material.glsl.c delete mode 100644 source/blender/gpu/intern/gpu_shader_vertex.glsl delete mode 100644 source/blender/gpu/intern/gpu_shader_vertex.glsl.c delete mode 100644 source/blender/include/BIF_keyframing.h delete mode 100644 source/blender/src/keyframing.c diff --git a/CMake/macros.cmake b/CMake/macros.cmake index 95799a2c1fd..6b6837d25f0 100644 --- a/CMake/macros.cmake +++ b/CMake/macros.cmake @@ -38,10 +38,6 @@ MACRO(BLENDERLIB ENDMACRO(BLENDERLIB) MACRO(SETUP_LIBDIRS) - # see "cmake --help-policy CMP0003" - if(COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 NEW) - endif(COMMAND cmake_policy) LINK_DIRECTORIES(${PYTHON_LIBPATH} ${SDL_LIBPATH} ${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${ICONV_LIBPATH} ${OPENEXR_LIBPATH} ${QUICKTIME_LIBPATH} ${FFMPEG_LIBPATH}) IF(WITH_INTERNATIONAL) LINK_DIRECTORIES(${GETTEXT_LIBPATH}) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c1b863178f..5b86ca8f21e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,6 @@ OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) -OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Mozilla-Unix only)" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -249,11 +248,7 @@ IF(WIN32) SET(GETTEXT ${LIBDIR}/gettext) SET(GETTEXT_INC ${GETTEXT}/include) - IF(CMAKE_CL_64) - SET(GETTEXT_LIB gettextlib) - ELSE(CMAKE_CL_64) - SET(GETTEXT_LIB gnu_gettext) - ENDIF(CMAKE_CL_64) + SET(GETTEXT_LIB gnu_gettext) SET(GETTEXT_LIBPATH ${GETTEXT}/lib) SET(FREETYPE ${LIBDIR}/freetype) @@ -284,12 +279,7 @@ IF(WIN32) SET(FFMPEG_LIB avcodec-51 avformat-52 avdevice-52 avutil-49 swscale-0) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) - IF(CMAKE_CL_64) - SET(LLIBS kernel32 user32 vfw32 winmm ws2_32 ) - ELSE(CMAKE_CL_64) SET(LLIBS kernel32 user32 gdi32 comdlg32 advapi32 shell32 ole32 oleaut32 uuid ws2_32 vfw32 winmm) - ENDIF(CMAKE_CL_64) - IF(WITH_OPENAL) SET(LLIBS ${LLIBS} dxguid) ENDIF(WITH_OPENAL) @@ -327,7 +317,7 @@ IF(WIN32) SET(WINTAB_INC ${LIBDIR}/wintab/include) IF(CMAKE_CL_64) - SET(PLATFORM_LINKFLAGS "/MACHINE:X64 /NODEFAULTLIB:libc.lib;MSVCRT.lib ") + SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib;MSVCRT.lib ") ELSE(CMAKE_CL_64) SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib ") ENDIF(CMAKE_CL_64) @@ -457,13 +447,6 @@ SUBDIRS( # Blender Application SUBDIRS(source/creator) -#----------------------------------------------------------------------------- -# Blender WebPlugin -IF(WITH_WEBPLUGIN) - SET(MOZILLA_DIR "${CMAKE_SOURCE_DIR}/../gecko-sdk/" CACHE PATH "Gecko SDK path") - SET(WITH_PLAYER ON) -ENDIF(WITH_WEBPLUGIN) - #----------------------------------------------------------------------------- # Blender Player IF(WITH_PLAYER) diff --git a/blenderplayer/CMakeLists.txt b/blenderplayer/CMakeLists.txt index 9786b7e61b2..d90639562d2 100644 --- a/blenderplayer/CMakeLists.txt +++ b/blenderplayer/CMakeLists.txt @@ -86,12 +86,10 @@ IF(UNIX) bf_oglrasterizer bf_expressions bf_scenegraph - bf_IK bf_moto bf_soundsystem bf_kernel bf_nodes - bf_gpu bf_imbuf bf_avi kx_network diff --git a/config/darwin-config.py b/config/darwin-config.py index 48455d2ce8c..8fd6c3251ba 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -143,6 +143,7 @@ BF_FTGL_LIB = 'extern_ftgl' WITH_BF_GAMEENGINE='true' WITH_BF_PLAYER='true' +WITH_BF_GLEXT= '1' WITH_BF_ODE = 'false' BF_ODE = LIBDIR + '/ode' diff --git a/config/linux2-config.py b/config/linux2-config.py index 36cbac6df10..fe4325361a8 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -6,12 +6,10 @@ BF_VERSE_INCLUDE = "#extern/verse/dist" BF_PYTHON = '/usr' BF_PYTHON_VERSION = '2.5' -WITH_BF_STATICPYTHON = 'false' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] -BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a' WITH_BF_OPENAL = 'true' BF_OPENAL = '/usr' diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 7a6b58b2ed7..6de2fd3a2bd 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -394,24 +394,12 @@ ECHO Done - - - - - - - - @@ -422,12 +410,6 @@ ECHO Done - - - - @@ -500,45 +482,18 @@ ECHO Done - - - - - - - - - - - - - - - - - - @@ -579,12 +534,6 @@ ECHO Done - - - - @@ -640,21 +589,6 @@ ECHO Done - - - - - - - - - - @@ -694,18 +628,6 @@ ECHO Done - - - - - - - - @@ -809,12 +731,6 @@ ECHO Done - - - - @@ -845,21 +761,12 @@ ECHO Done - - - - - - @@ -878,18 +785,6 @@ ECHO Done - - - - - - - - @@ -932,12 +827,6 @@ ECHO Done - - - - @@ -953,12 +842,6 @@ ECHO Done - - - - - - @@ -1006,9 +886,6 @@ ECHO Done - - @@ -1027,6 +904,9 @@ ECHO Done + + diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt index 02430cb5c0e..4d1a4c11706 100644 --- a/extern/bullet2/readme.txt +++ b/extern/bullet2/readme.txt @@ -1,8 +1,3 @@ -*** -Apply bullet_compound_raycast.patch if not already applied in Bullet source -This patch is needed to return correct raycast results on compound shape. -/ben - *** These files in extern/bullet2 are NOT part of the Blender build yet *** diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index 8074aed3038..078dcae63bb 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -23,153 +23,15 @@ subject to the following restrictions: #ifndef BULLET_C_API_H #define BULLET_C_API_H -#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name - -#ifdef BT_USE_DOUBLE_PRECISION -typedef double plReal; -#else -typedef float plReal; -#endif - -typedef plReal plVector3[3]; -typedef plReal plQuaternion[4]; - #ifdef __cplusplus extern "C" { #endif -/* Particular physics SDK */ - PL_DECLARE_HANDLE(plPhysicsSdkHandle); - -/* Dynamics world, belonging to some physics SDK */ - PL_DECLARE_HANDLE(plDynamicsWorldHandle); - -/* Rigid Body that can be part of a Dynamics World */ - PL_DECLARE_HANDLE(plRigidBodyHandle); - -/* Collision Shape/Geometry, property of a Rigid Body */ - PL_DECLARE_HANDLE(plCollisionShapeHandle); - -/* Constraint for Rigid Bodies */ - PL_DECLARE_HANDLE(plConstraintHandle); - -/* Triangle Mesh interface */ - PL_DECLARE_HANDLE(plMeshInterfaceHandle); - -/* Broadphase Scene/Proxy Handles */ - PL_DECLARE_HANDLE(plCollisionBroadphaseHandle); - PL_DECLARE_HANDLE(plBroadphaseProxyHandle); - PL_DECLARE_HANDLE(plCollisionWorldHandle); - -/* - Create and Delete a Physics SDK -*/ - - extern plPhysicsSdkHandle plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc. - extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk); - -/* Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */ - - typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2); - - extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback); - - extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp); - - extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); - - extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle); - - extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); - -/* todo: add pair cache support with queries like add/remove/find pair */ - - extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk); - -/* todo: add/remove objects */ - - -/* Dynamics World */ - - extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk); - - extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world); - - extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep); - - extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); - - extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); - - -/* Rigid Body */ - - extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ); - - extern void plDeleteRigidBody(plRigidBodyHandle body); - - -/* Collision Shape definition */ - - extern plCollisionShapeHandle plNewSphereShape(plReal radius); - extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z); - extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height); - extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height); - extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height); - extern plCollisionShapeHandle plNewCompoundShape(); - extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn); - - extern void plDeleteShape(plCollisionShapeHandle shape); - - /* Convex Meshes */ - extern plCollisionShapeHandle plNewConvexHullShape(); - extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z); -/* Concave static triangle meshes */ - extern plMeshInterfaceHandle plNewMeshInterface(); - extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); - extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); - - extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling); - -/* SOLID has Response Callback/Table/Management */ -/* PhysX has Triggers, User Callbacks and filtering */ -/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */ - -/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */ -/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */ - - /* get world transform */ - extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); - extern void plGetPosition(plRigidBodyHandle object,plVector3 position); - extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation); - - /* set world transform (position/orientation) */ - extern void plSetPosition(plRigidBodyHandle object, const plVector3 position); - extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation); - extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient); - - typedef struct plRayCastResult { - plRigidBodyHandle m_body; - plCollisionShapeHandle m_shape; - plVector3 m_positionWorld; - plVector3 m_normalWorld; - } plRayCastResult; - - extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res); - - /* Sweep API */ - - /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */ - - /* Continuous Collision Detection API */ - - // needed for source/blender/blenkernel/intern/collision.c - double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); +double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); #ifdef __cplusplus } #endif - #endif //BULLET_C_API_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp index d7eea33ea41..be4a11506df 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -21,18 +21,640 @@ #include -btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache) -:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache) +#ifdef DEBUG_BROADPHASE +#include +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) { - // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < 32767); + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + assert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + + +btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask); + + Handle* handle = getHandle(handleId); + + return handle; +} + +void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy) +{ + Handle* handle = static_cast(proxy); + removeHandle(handle->m_handleId); +} + +void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax) +{ + Handle* handle = static_cast(proxy); + updateHandle(handle->m_handleId,aabbMin,aabbMax); } -bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache ) -:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache) + + + + +btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles) +:btOverlappingPairCache() { + m_invalidPair = 0; + //assert(bounds.HasVolume()); + // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < 2147483647); + btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer and put all handles on free list + m_pHandles = new Handle[maxHandles]; + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(i + 1); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + m_pEdges[i] = new Edge[maxHandles * 2]; + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = BP_HANDLE_SENTINEL; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +btAxisSweep3::~btAxisSweep3() +{ + + for (int i = 2; i >= 0; i--) + delete[] m_pEdges[i]; + delete[] m_pHandles; +} + +void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const +{ + btPoint3 clampedPoint(point); + + + + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & BP_HANDLE_MASK) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax); + +} + + + +BP_FP_INT_TYPE btAxisSweep3::allocHandle() +{ + assert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle) +{ + assert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + + +BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + assert(handle!= 0xcdcd); + + Handle* pHandle = getHandle(handle); + + pHandle->m_handleId = handle; + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = m_numHandles * 2; + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = limit - 1; + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], false); + sortMaxDown(0, pHandle->m_maxEdges[0], false); + sortMinDown(1, pHandle->m_minEdges[1], false); + sortMaxDown(1, pHandle->m_maxEdges[1], false); + sortMinDown(2, pHandle->m_minEdges[2], true); + sortMaxDown(2, pHandle->m_maxEdges[2], true); + + + return handle; +} + + +void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + //todo: compare performance + removeOverlappingPairsContainingProxy(pHandle); + + + // compute current limit of edge arrays + int limit = m_numHandles * 2; + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = BP_HANDLE_SENTINEL; + + sortMaxUp(axis,max,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = BP_HANDLE_SENTINEL; + + + sortMinUp(axis,i,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +extern int gOverlappingPairs; + + +void btAxisSweep3::refreshOverlappingPairs() +{ + +} +void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback) +{ + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); + + //remove the 'invalid' ones +#ifdef USE_POPBACK_REMOVAL + while (m_invalidPair>0) + { + m_invalidPair--; + m_overlappingPairArray.pop_back(); + } +#else + m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + cleanOverlappingPair(pair); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } +} + + +bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (axis != ignoreAxis) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + } + + //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) + + /*for (int axis = 0; axis < 3; axis++) + { + if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || + m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) + { + return false; + } + } + */ + + return true; +} + +void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax) +{ +// assert(bounds.IsFinite()); + //assert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin); + + if (dmax > 0) + sortMaxUp(axis, emax); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin); + + if (dmax < 0) + sortMaxDown(axis, emax); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) + { + addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps) + { + /* + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + btBroadphasePair tmpPair(*handle0,*handle1); + removeOverlappingPair(tmpPair); + */ + + } + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + if (updateOverlaps) + { + //this is done during the overlappingpairarray iteration/narrowphase collision + /* + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + btBroadphasePair* pair = findPair(handle0,handle1); + //assert(pair); + + if (pair) + { + removeOverlappingPair(*pair); + } + */ + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index d0ad09a385a..57bbb368672 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -19,26 +19,34 @@ #ifndef AXIS_SWEEP_3_H #define AXIS_SWEEP_3_H -#include "LinearMath/btPoint3.h" -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btVector3.h" #include "btOverlappingPairCache.h" -#include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" -#include "btOverlappingPairCallback.h" + + +//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects +//#define BP_USE_FIXEDPOINT_INT_32 1 + +#ifdef BP_USE_FIXEDPOINT_INT_32 + #define BP_FP_INT_TYPE unsigned int + #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles + #define BP_HANDLE_SENTINEL 0x7fffffff + #define BP_HANDLE_MASK 0xfffffffe +#else + #define BP_FP_INT_TYPE unsigned short int + #define BP_MAX_HANDLES 32767 + #define BP_HANDLE_SENTINEL 0xffff + #define BP_HANDLE_MASK 0xfffe +#endif //BP_USE_FIXEDPOINT_INT_32 //#define DEBUG_BROADPHASE 1 -#define USE_OVERLAP_TEST_ON_REMOVES 1 -/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. -/// It uses quantized integers to represent the begin and end points for each of the 3 axis. -/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. -template -class btAxisSweep3Internal : public btBroadphaseInterface +/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats. +/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos +class btAxisSweep3 : public btOverlappingPairCache { -protected: - - BP_FP_INT_TYPE m_bpHandleMask; - BP_FP_INT_TYPE m_handleSentinel; public: @@ -49,57 +57,47 @@ public: BP_FP_INT_TYPE m_pos; // low bit is min/max BP_FP_INT_TYPE m_handle; - BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);} + BP_FP_INT_TYPE IsMax() const {return m_pos & 1;} }; public: - class Handle : public btBroadphaseProxy + class Handle : public btBroadphaseProxy { public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - + // indexes into the edge arrays BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 -// BP_FP_INT_TYPE m_uniqueId; + BP_FP_INT_TYPE m_handleId; BP_FP_INT_TYPE m_pad; //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject - SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} - SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry -protected: +private: btPoint3 m_worldAabbMin; // overall system bounds btPoint3 m_worldAabbMax; // overall system bounds btVector3 m_quantize; // scaling factor for quantization BP_FP_INT_TYPE m_numHandles; // number of active handles - BP_FP_INT_TYPE m_maxHandles; // max number of handles + int m_maxHandles; // max number of handles Handle* m_pHandles; // handles pool - BP_FP_INT_TYPE m_firstFreeHandle; // free handles list Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) - void* m_pEdgesRawPtr[3]; - btOverlappingPairCache* m_pairCache; - - ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. - btOverlappingPairCallback* m_userPairCallback; - - bool m_ownsPairCache; - - int m_invalidPair; + int m_invalidPair; // allocation/deallocation BP_FP_INT_TYPE allocHandle(); void freeHandle(BP_FP_INT_TYPE handle); - bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1); + bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); #ifdef DEBUG_BROADPHASE void debugPrintAxis(int axis,bool checkCardinality=true); @@ -110,803 +108,29 @@ protected: void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const; - void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); - void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); public: + btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384); + virtual ~btAxisSweep3(); - btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0); - - virtual ~btAxisSweep3Internal(); - - BP_FP_INT_TYPE getNumHandles() const - { - return m_numHandles; - } - - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + virtual void refreshOverlappingPairs(); - BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); - void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); - void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher); - SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); + void removeHandle(BP_FP_INT_TYPE handle); + void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax); + inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} void processAllOverlappingPairs(btOverlapCallback* callback); //Broadphase Interface - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - btOverlappingPairCache* getOverlappingPairCache() - { - return m_pairCache; - } - const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_pairCache; - } - - void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) - { - m_userPairCallback = pairCallback; - } - const btOverlappingPairCallback* getOverlappingPairUserCallback() const - { - return m_userPairCallback; - } - - ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame - ///will add some transform later - virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const - { - aabbMin = m_worldAabbMin; - aabbMax = m_worldAabbMax; - } - - virtual void printStats() - { -/* printf("btAxisSweep3.h\n"); - printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); - printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(), - m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ()); - */ - - } - -}; - -//////////////////////////////////////////////////////////////////// - - - - -#ifdef DEBUG_BROADPHASE -#include - -template -void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) -{ - int numEdges = m_pHandles[0].m_maxEdges[axis]; - printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); - - int i; - for (i=0;im_handle); - int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; - char beginOrEnd; - beginOrEnd=pEdge->IsMax()?'E':'B'; - printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); - } - - if (checkCardinality) - assert(numEdges == m_numHandles*2+1); -} -#endif //DEBUG_BROADPHASE - -template -btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) -{ - (void)shapeType; - BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); - - Handle* handle = getHandle(handleId); - - return handle; -} - - - -template -void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - Handle* handle = static_cast(proxy); - removeHandle(static_cast(handle->m_uniqueId), dispatcher); -} - -template -void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) -{ - Handle* handle = static_cast(proxy); - updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher); - -} - - - - - -template -btAxisSweep3Internal::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache ) -:m_bpHandleMask(handleMask), -m_handleSentinel(handleSentinel), -m_pairCache(pairCache), -m_userPairCallback(0), -m_ownsPairCache(false), -m_invalidPair(0) -{ - BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle - - if (!m_pairCache) - { - void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16); - m_pairCache = new(ptr) btHashedOverlappingPairCache(); - m_ownsPairCache = true; - } - - //assert(bounds.HasVolume()); - - // init bounds - m_worldAabbMin = worldAabbMin; - m_worldAabbMax = worldAabbMax; - - btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; - - BP_FP_INT_TYPE maxInt = m_handleSentinel; - - m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; - - // allocate handles buffer, using btAlignedAlloc, and put all handles on free list - m_pHandles = new Handle[maxHandles]; - - m_maxHandles = maxHandles; - m_numHandles = 0; - - // handle 0 is reserved as the null index, and is also used as the sentinel - m_firstFreeHandle = 1; - { - for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) - m_pHandles[i].SetNextFree(static_cast(i + 1)); - m_pHandles[maxHandles - 1].SetNextFree(0); - } - - { - // allocate edge buffers - for (int i = 0; i < 3; i++) - { - m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); - m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2]; - } - } - //removed overlap management - - // make boundary sentinels - - m_pHandles[0].m_clientObject = 0; - - for (int axis = 0; axis < 3; axis++) - { - m_pHandles[0].m_minEdges[axis] = 0; - m_pHandles[0].m_maxEdges[axis] = 1; - - m_pEdges[axis][0].m_pos = 0; - m_pEdges[axis][0].m_handle = 0; - m_pEdges[axis][1].m_pos = m_handleSentinel; - m_pEdges[axis][1].m_handle = 0; -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - - } - -} - -template -btAxisSweep3Internal::~btAxisSweep3Internal() -{ - - for (int i = 2; i >= 0; i--) - { - btAlignedFree(m_pEdgesRawPtr[i]); - } - delete [] m_pHandles; - - if (m_ownsPairCache) - { - m_pairCache->~btOverlappingPairCache(); - btAlignedFree(m_pairCache); - } -} - -template -void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const -{ - btPoint3 clampedPoint(point); - - - - clampedPoint.setMax(m_worldAabbMin); - clampedPoint.setMin(m_worldAabbMax); - - btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; - out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); - out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); - out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); - -} - - -template -BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() -{ - assert(m_firstFreeHandle); - - BP_FP_INT_TYPE handle = m_firstFreeHandle; - m_firstFreeHandle = getHandle(handle)->GetNextFree(); - m_numHandles++; - - return handle; -} - -template -void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) -{ - assert(handle > 0 && handle < m_maxHandles); - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numHandles--; -} - - -template -BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) -{ - // quantize the bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // allocate a handle - BP_FP_INT_TYPE handle = allocHandle(); - - - Handle* pHandle = getHandle(handle); - - pHandle->m_uniqueId = static_cast(handle); - //pHandle->m_pOverlaps = 0; - pHandle->m_clientObject = pOwner; - pHandle->m_collisionFilterGroup = collisionFilterGroup; - pHandle->m_collisionFilterMask = collisionFilterMask; - pHandle->m_multiSapParentProxy = multiSapProxy; - - // compute current limit of edge arrays - BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2); - - - // insert new edges just inside the max boundary edge - for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) - { - - m_pHandles[0].m_maxEdges[axis] += 2; - - m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; - - m_pEdges[axis][limit - 1].m_pos = min[axis]; - m_pEdges[axis][limit - 1].m_handle = handle; - - m_pEdges[axis][limit].m_pos = max[axis]; - m_pEdges[axis][limit].m_handle = handle; - - pHandle->m_minEdges[axis] = static_cast(limit - 1); - pHandle->m_maxEdges[axis] = limit; - } - - // now sort the new edges to their correct position - sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); - sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); - sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); - sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); - sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); - sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); - - - return handle; -} - - -template -void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) -{ - - Handle* pHandle = getHandle(handle); - - //explicitly remove the pairs containing the proxy - //we could do it also in the sortMinUp (passing true) - //todo: compare performance - if (!m_pairCache->hasDeferredRemoval()) - { - m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); - } - - // compute current limit of edge arrays - int limit = static_cast(m_numHandles * 2); - - int axis; - - for (axis = 0;axis<3;axis++) - { - m_pHandles[0].m_maxEdges[axis] -= 2; - } - - // remove the edges by sorting them up to the end of the list - for ( axis = 0; axis < 3; axis++) - { - Edge* pEdges = m_pEdges[axis]; - BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; - pEdges[max].m_pos = m_handleSentinel; - - sortMaxUp(axis,max,dispatcher,false); - - - BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; - pEdges[i].m_pos = m_handleSentinel; - - - sortMinUp(axis,i,dispatcher,false); - - pEdges[limit-1].m_handle = 0; - pEdges[limit-1].m_pos = m_handleSentinel; - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis,false); -#endif //DEBUG_BROADPHASE - - - } - - - // free the handle - freeHandle(handle); - - -} - -extern int gOverlappingPairs; -//#include - -template -void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) -{ - - if (m_pairCache->hasDeferredRemoval()) - { - - btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - m_pairCache->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - - ///if you don't like to skip the invalid pairs in the array, execute following code: - #define CLEAN_INVALID_PAIRS 1 - #ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - #endif//CLEAN_INVALID_PAIRS - - //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); - } - - - - - -} - - -template -bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - const Handle* pHandleA = static_cast(proxy0); - const Handle* pHandleB = static_cast(proxy1); - - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - return true; -} - -template -bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1) -{ - //optimization 1: check the array index (memory address), instead of the m_pos - - if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || - pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] || - pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] || - pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) - { - return false; - } - return true; -} - -template -void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher) -{ -// assert(bounds.IsFinite()); - //assert(bounds.HasVolume()); - - Handle* pHandle = getHandle(handle); - - // quantize the new bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // update changed edges - for (int axis = 0; axis < 3; axis++) - { - BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; - BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; - - int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; - int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; - - m_pEdges[axis][emin].m_pos = min[axis]; - m_pEdges[axis][emax].m_pos = max[axis]; - - // expand (only adds overlaps) - if (dmin < 0) - sortMinDown(axis, emin,dispatcher,true); - - if (dmax > 0) - sortMaxUp(axis, emax,dispatcher,true); - - // shrink (only removes overlaps) - if (dmin > 0) - sortMinUp(axis, emin,dispatcher,true); - - if (dmax < 0) - sortMaxDown(axis, emax,dispatcher,true); - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - } - - -} - - - - -// sorting a min edge downwards can only ever *add* overlaps -template -void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (pPrev->IsMax()) - { - // if previous edge is a maximum check the bounds and add an overlap if necessary - const int axis1 = (1 << axis) & 3; - const int axis2 = (1 << axis1) & 3; - if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2)) - { - m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); - if (m_userPairCallback) - m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); - - //AddOverlap(pEdge->m_handle, pPrev->m_handle); - - } - - // update edge reference in other handle - pHandlePrev->m_maxEdges[axis]++; - } - else - pHandlePrev->m_minEdges[axis]++; - - pHandleEdge->m_minEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a min edge upwards can only ever *remove* overlaps -template -void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (pNext->IsMax()) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - const int axis1 = (1 << axis) & 3; - const int axis2 = (1 << axis1) & 3; - - // if next edge is maximum remove any overlap between the two handles - if (updateOverlaps -#ifdef USE_OVERLAP_TEST_ON_REMOVES - && testOverlap2D(handle0,handle1,axis1,axis2) -#endif //USE_OVERLAP_TEST_ON_REMOVES - ) - { - - - m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); - if (m_userPairCallback) - m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); - - } - - - // update edge reference in other handle - pHandleNext->m_maxEdges[axis]--; - } - else - pHandleNext->m_minEdges[axis]--; - - pHandleEdge->m_minEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - - -} - -// sorting a max edge downwards can only ever *remove* overlaps -template -void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (!pPrev->IsMax()) - { - // if previous edge was a minimum remove any overlap between the two handles - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pPrev->m_handle); - const int axis1 = (1 << axis) & 3; - const int axis2 = (1 << axis1) & 3; - - if (updateOverlaps -#ifdef USE_OVERLAP_TEST_ON_REMOVES - && testOverlap2D(handle0,handle1,axis1,axis2) -#endif //USE_OVERLAP_TEST_ON_REMOVES - ) - { - //this is done during the overlappingpairarray iteration/narrowphase collision - - - m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); - if (m_userPairCallback) - m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); - - - - } - - // update edge reference in other handle - pHandlePrev->m_minEdges[axis]++;; - } - else - pHandlePrev->m_maxEdges[axis]++; - - pHandleEdge->m_maxEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a max edge upwards can only ever *add* overlaps -template -void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - const int axis1 = (1 << axis) & 3; - const int axis2 = (1 << axis1) & 3; - - if (!pNext->IsMax()) - { - // if next edge is a minimum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2)) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - m_pairCache->addOverlappingPair(handle0,handle1); - if (m_userPairCallback) - m_userPairCallback->addOverlappingPair(handle0,handle1); - } - - // update edge reference in other handle - pHandleNext->m_minEdges[axis]--; - } - else - pHandleNext->m_maxEdges[axis]--; - - pHandleEdge->m_maxEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - -} - - - -//////////////////////////////////////////////////////////////////// - - -/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. -/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. -/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. -class btAxisSweep3 : public btAxisSweep3Internal -{ -public: - - btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0); - -}; - -/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. -/// This comes at the cost of more memory per handle, and a bit slower performance. -/// It uses arrays rather then lists for storage of the 3 axis. -class bt32BitAxisSweep3 : public btAxisSweep3Internal -{ -public: - - bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0); + virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); + virtual void destroyProxy(btBroadphaseProxy* proxy); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); + bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index 200ac365329..b6ace03c07a 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -20,34 +20,20 @@ subject to the following restrictions: struct btDispatcherInfo; class btDispatcher; -#include "btBroadphaseProxy.h" -class btOverlappingPairCache; +struct btBroadphaseProxy; +#include "../../LinearMath/btVector3.h" -#include "LinearMath/btVector3.h" - -///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. -///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase. -///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class. +///BroadphaseInterface for aabb-overlapping object pairs class btBroadphaseInterface { public: virtual ~btBroadphaseInterface() {} - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; + virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; + virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0; - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb - virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; - - virtual btOverlappingPairCache* getOverlappingPairCache()=0; - virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; - - ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame - ///will add some transform later - virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; - - virtual void printStats() = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index e0bb67f8521..40d9748ffa9 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -16,8 +16,7 @@ subject to the following restrictions: #ifndef BROADPHASE_PROXY_H #define BROADPHASE_PROXY_H -#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE -#include "LinearMath/btAlignedAllocator.h" +#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE /// btDispatcher uses these types @@ -39,7 +38,6 @@ IMPLICIT_CONVEX_SHAPES_START_HERE, CONE_SHAPE_PROXYTYPE, CONVEX_SHAPE_PROXYTYPE, CYLINDER_SHAPE_PROXYTYPE, - UNIFORM_SCALING_SHAPE_PROXYTYPE, MINKOWSKI_SUM_SHAPE_PROXYTYPE, MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, //concave shapes @@ -52,8 +50,6 @@ CONCAVE_SHAPES_START_HERE, TERRAIN_SHAPE_PROXYTYPE, ///Used for GIMPACT Trimesh integration GIMPACT_SHAPE_PROXYTYPE, -///Multimaterial mesh - MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, EMPTY_SHAPE_PROXYTYPE, STATIC_PLANE_PROXYTYPE, @@ -61,18 +57,13 @@ CONCAVE_SHAPES_END_HERE, COMPOUND_SHAPE_PROXYTYPE, - SOFTBODY_SHAPE_PROXYTYPE, - MAX_BROADPHASE_COLLISION_TYPES }; -///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. -///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody. -ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy +///btBroadphaseProxy +struct btBroadphaseProxy { - -BT_DECLARE_ALIGNED_ALLOCATOR(); ///optional filtering to cull potential collisions enum CollisionFilterGroups @@ -82,60 +73,44 @@ BT_DECLARE_ALIGNED_ALLOCATOR(); KinematicFilter = 4, DebrisFilter = 8, SensorTrigger = 16, - AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger + AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger }; //Usually the client btCollisionObject or Rigidbody class void* m_clientObject; - short int m_collisionFilterGroup; short int m_collisionFilterMask; - void* m_multiSapParentProxy; - - - int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. - - SIMD_FORCE_INLINE int getUid() const - { - return m_uniqueId; - } - //used for memory pools - btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) - { - } + btBroadphaseProxy() :m_clientObject(0){} - btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) + btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :m_clientObject(userPtr), m_collisionFilterGroup(collisionFilterGroup), m_collisionFilterMask(collisionFilterMask) { - m_multiSapParentProxy = multiSapParentProxy; } - - - static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) + static inline bool isPolyhedral(int proxyType) { return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); } - static SIMD_FORCE_INLINE bool isConvex(int proxyType) + static inline bool isConvex(int proxyType) { return (proxyType < CONCAVE_SHAPES_START_HERE); } - static SIMD_FORCE_INLINE bool isConcave(int proxyType) + static inline bool isConcave(int proxyType) { return ((proxyType > CONCAVE_SHAPES_START_HERE) && (proxyType < CONCAVE_SHAPES_END_HERE)); } - static SIMD_FORCE_INLINE bool isCompound(int proxyType) + static inline bool isCompound(int proxyType) { return (proxyType == COMPOUND_SHAPE_PROXYTYPE); } - static SIMD_FORCE_INLINE bool isInfinite(int proxyType) + static inline bool isInfinite(int proxyType) { return (proxyType == STATIC_PLANE_PROXYTYPE); } @@ -149,9 +124,8 @@ struct btBroadphaseProxy; -///The btBroadphasePair class contains a pair of aabb-overlapping objects. -///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes. -ATTRIBUTE_ALIGNED16(struct) btBroadphasePair +/// contains a pair of aabb-overlapping objects +struct btBroadphasePair { btBroadphasePair () : @@ -162,8 +136,6 @@ ATTRIBUTE_ALIGNED16(struct) btBroadphasePair { } -BT_DECLARE_ALIGNED_ALLOCATOR(); - btBroadphasePair(const btBroadphasePair& other) : m_pProxy0(other.m_pProxy0), m_pProxy1(other.m_pProxy1), @@ -209,7 +181,6 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa */ - class btBroadphasePairSortPredicate { public: diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp index c95d1be0f2c..2ad0c86d8a2 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -18,6 +18,6 @@ subject to the following restrictions: btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) { - m_dispatcher = ci.m_dispatcher1; + m_dispatcher = ci.m_dispatcher; } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h index 1618ad9fdd3..55cec386a7b 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -16,8 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_ALGORITHM_H #define COLLISION_ALGORITHM_H -#include "LinearMath/btScalar.h" -#include "LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btScalar.h" struct btBroadphaseProxy; class btDispatcher; @@ -26,22 +25,21 @@ class btCollisionObject; struct btDispatcherInfo; class btPersistentManifold; -typedef btAlignedObjectArray btManifoldArray; struct btCollisionAlgorithmConstructionInfo { btCollisionAlgorithmConstructionInfo() - :m_dispatcher1(0), + :m_dispatcher(0), m_manifold(0) { } btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) - :m_dispatcher1(dispatcher) + :m_dispatcher(dispatcher) { (void)temp; } - btDispatcher* m_dispatcher1; + btDispatcher* m_dispatcher; btPersistentManifold* m_manifold; int getDispatcherId(); @@ -73,7 +71,6 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp deleted file mode 100644 index 7c41c8d8f71..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp +++ /dev/null @@ -1,1289 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btDbvt implementation by Nathanael Presson - -#include "btDbvt.h" - -// -typedef btAlignedObjectArray tNodeArray; -typedef btAlignedObjectArray tConstNodeArray; - -// -struct btDbvtNodeEnumerator : btDbvt::ICollide -{ -tConstNodeArray nodes; -void Process(const btDbvtNode* n) { nodes.push_back(n); } -}; - -// -static DBVT_INLINE int indexof(const btDbvtNode* node) -{ -return(node->parent->childs[1]==node); -} - -// -static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a, - const btDbvtVolume& b) -{ -#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE -DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)]; -btDbvtVolume& res=*(btDbvtVolume*)locals; -#else -btDbvtVolume res; -#endif -Merge(a,b,res); -return(res); -} - -// volume+edge lengths -static DBVT_INLINE btScalar size(const btDbvtVolume& a) -{ -const btVector3 edges=a.Lengths(); -return( edges.x()*edges.y()*edges.z()+ - edges.x()+edges.y()+edges.z()); -} - -// -static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth) -{ -if(node->isinternal()) - { - getmaxdepth(node->childs[0],depth+1,maxdepth); - getmaxdepth(node->childs[0],depth+1,maxdepth); - } else maxdepth=btMax(maxdepth,depth); -} - -// -static DBVT_INLINE void deletenode( btDbvt* pdbvt, - btDbvtNode* node) -{ -btAlignedFree(pdbvt->m_free); -pdbvt->m_free=node; -} - -// -static void recursedeletenode( btDbvt* pdbvt, - btDbvtNode* node) -{ -if(!node->isleaf()) - { - recursedeletenode(pdbvt,node->childs[0]); - recursedeletenode(pdbvt,node->childs[1]); - } -if(node==pdbvt->m_root) pdbvt->m_root=0; -deletenode(pdbvt,node); -} - -// -static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, - btDbvtNode* parent, - void* data) -{ -btDbvtNode* node; -if(pdbvt->m_free) - { node=pdbvt->m_free;pdbvt->m_free=0; } - else - { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); } -node->parent = parent; -node->data = data; -node->childs[1] = 0; -return(node); -} - -// -static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, - btDbvtNode* parent, - const btDbvtVolume& volume, - void* data) -{ -btDbvtNode* node=createnode(pdbvt,parent,data); -node->volume=volume; -return(node); -} - -// -static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, - btDbvtNode* parent, - const btDbvtVolume& volume0, - const btDbvtVolume& volume1, - void* data) -{ -btDbvtNode* node=createnode(pdbvt,parent,data); -Merge(volume0,volume1,node->volume); -return(node); -} - -// -static void insertleaf( btDbvt* pdbvt, - btDbvtNode* root, - btDbvtNode* leaf) -{ -if(!pdbvt->m_root) - { - pdbvt->m_root = leaf; - leaf->parent = 0; - } - else - { - if(!root->isleaf()) - { - do { - root=root->childs[Select( leaf->volume, - root->childs[0]->volume, - root->childs[1]->volume)]; - } while(!root->isleaf()); - } - btDbvtNode* prev=root->parent; - btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0); - if(prev) - { - prev->childs[indexof(root)] = node; - node->childs[0] = root;root->parent=node; - node->childs[1] = leaf;leaf->parent=node; - do { - if(!prev->volume.Contain(node->volume)) - Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); - else - break; - node=prev; - } while(0!=(prev=node->parent)); - } - else - { - node->childs[0] = root;root->parent=node; - node->childs[1] = leaf;leaf->parent=node; - pdbvt->m_root = node; - } - } -} - -// -static btDbvtNode* removeleaf( btDbvt* pdbvt, - btDbvtNode* leaf) -{ -if(leaf==pdbvt->m_root) - { - pdbvt->m_root=0; - return(0); - } - else - { - btDbvtNode* parent=leaf->parent; - btDbvtNode* prev=parent->parent; - btDbvtNode* sibling=parent->childs[1-indexof(leaf)]; - if(prev) - { - prev->childs[indexof(parent)]=sibling; - sibling->parent=prev; - deletenode(pdbvt,parent); - while(prev) - { - const btDbvtVolume pb=prev->volume; - Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); - if(NotEqual(pb,prev->volume)) - { - prev=prev->parent; - } else break; - } - return(prev?prev:pdbvt->m_root); - } - else - { - pdbvt->m_root=sibling; - sibling->parent=0; - deletenode(pdbvt,parent); - return(pdbvt->m_root); - } - } -} - -// -static void fetchleaves(btDbvt* pdbvt, - btDbvtNode* root, - tNodeArray& leaves, - int depth=-1) -{ -if(root->isinternal()&&depth) - { - fetchleaves(pdbvt,root->childs[0],leaves,depth-1); - fetchleaves(pdbvt,root->childs[1],leaves,depth-1); - deletenode(pdbvt,root); - } - else - { - leaves.push_back(root); - } -} - -// -static void split( const tNodeArray& leaves, - tNodeArray& left, - tNodeArray& right, - const btVector3& org, - const btVector3& axis) -{ -left.resize(0); -right.resize(0); -for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) - left.push_back(leaves[i]); - else - right.push_back(leaves[i]); - } -} - -// -static btDbvtVolume bounds( const tNodeArray& leaves) -{ -#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE -DBVT_ALIGN char locals[sizeof(btDbvtVolume)]; -btDbvtVolume& volume=*(btDbvtVolume*)locals; -volume=leaves[0]->volume; -#else -btDbvtVolume volume=leaves[0]->volume; -#endif -for(int i=1,ni=leaves.size();ivolume,volume); - } -return(volume); -} - -// -static void bottomup( btDbvt* pdbvt, - tNodeArray& leaves) -{ -while(leaves.size()>1) - { - btScalar minsize=SIMD_INFINITY; - int minidx[2]={-1,-1}; - for(int i=0;ivolume,leaves[j]->volume)); - if(szvolume,n[1]->volume,0); - p->childs[0] = n[0]; - p->childs[1] = n[1]; - n[0]->parent = p; - n[1]->parent = p; - leaves[minidx[0]] = p; - leaves.swap(minidx[1],leaves.size()-1); - leaves.pop_back(); - } -} - -// -static btDbvtNode* topdown(btDbvt* pdbvt, - tNodeArray& leaves, - int bu_treshold) -{ -static const btVector3 axis[]={btVector3(1,0,0), - btVector3(0,1,0), - btVector3(0,0,1)}; -if(leaves.size()>1) - { - if(leaves.size()>bu_treshold) - { - const btDbvtVolume vol=bounds(leaves); - const btVector3 org=vol.Center(); - tNodeArray sets[2]; - int bestaxis=-1; - int bestmidp=leaves.size(); - int splitcount[3][2]={{0,0},{0,0},{0,0}}; - int i; - for( i=0;ivolume.Center()-org; - for(int j=0;j<3;++j) - { - ++splitcount[j][dot(x,axis[j])>0?1:0]; - } - } - for( i=0;i<3;++i) - { - if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) - { - const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1])); - if(midp=0) - { - sets[0].reserve(splitcount[bestaxis][0]); - sets[1].reserve(splitcount[bestaxis][1]); - split(leaves,sets[0],sets[1],org,axis[bestaxis]); - } - else - { - sets[0].reserve(leaves.size()/2+1); - sets[1].reserve(leaves.size()/2); - for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold); - node->childs[1]=topdown(pdbvt,sets[1],bu_treshold); - node->childs[0]->parent=node; - node->childs[1]->parent=node; - return(node); - } - else - { - bottomup(pdbvt,leaves); - return(leaves[0]); - } - } -return(leaves[0]); -} - -// -static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r) -{ -btDbvtNode* p=n->parent; -btAssert(n->isinternal()); -if(p>n) - { - const int i=indexof(n); - const int j=1-i; - btDbvtNode* s=p->childs[j]; - btDbvtNode* q=p->parent; - btAssert(n==p->childs[i]); - if(q) q->childs[indexof(p)]=n; else r=n; - s->parent=n; - p->parent=n; - n->parent=q; - p->childs[0]=n->childs[0]; - p->childs[1]=n->childs[1]; - n->childs[0]->parent=p; - n->childs[1]->parent=p; - n->childs[i]=p; - n->childs[j]=s; - btSwap(p->volume,n->volume); - return(p); - } -return(n); -} - -// -static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) -{ -while(n&&(count--)) n=n->parent; -return(n); -} - -// -// Api -// - -// - btDbvt::btDbvt() -{ -m_root = 0; -m_free = 0; -m_lkhd = -1; -m_leaves = 0; -m_opath = 0; -} - -// - btDbvt::~btDbvt() -{ -clear(); -} - -// -void btDbvt::clear() -{ -if(m_root) recursedeletenode(this,m_root); -btAlignedFree(m_free); -m_free=0; -} - -// -void btDbvt::optimizeBottomUp() -{ -if(m_root) - { - tNodeArray leaves; - leaves.reserve(m_leaves); - fetchleaves(this,m_root,leaves); - bottomup(this,leaves); - m_root=leaves[0]; - } -} - -// -void btDbvt::optimizeTopDown(int bu_treshold) -{ -if(m_root) - { - tNodeArray leaves; - leaves.reserve(m_leaves); - fetchleaves(this,m_root,leaves); - m_root=topdown(this,leaves,bu_treshold); - } -} - -// -void btDbvt::optimizeIncremental(int passes) -{ -if(passes<0) passes=m_leaves; -if(m_root&&(passes>0)) - { - do { - btDbvtNode* node=m_root; - unsigned bit=0; - while(node->isinternal()) - { - node=sort(node,m_root)->childs[(m_opath>>bit)&1]; - bit=(bit+1)&(sizeof(unsigned)*8-1); - } - update(node); - ++m_opath; - } while(--passes); - } -} - -// -btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data) -{ -btDbvtNode* leaf=createnode(this,0,volume,data); -insertleaf(this,m_root,leaf); -++m_leaves; -return(leaf); -} - -// -void btDbvt::update(btDbvtNode* leaf,int lookahead) -{ -btDbvtNode* root=removeleaf(this,leaf); -if(root) - { - if(lookahead>=0) - { - for(int i=0;(iparent;++i) - { - root=root->parent; - } - } else root=m_root; - } -insertleaf(this,root,leaf); -} - -// -void btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume) -{ -btDbvtNode* root=removeleaf(this,leaf); -if(root) - { - if(m_lkhd>=0) - { - for(int i=0;(iparent;++i) - { - root=root->parent; - } - } else root=m_root; - } -leaf->volume=volume; -insertleaf(this,root,leaf); -} - -// -bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin) -{ -if(leaf->volume.Contain(volume)) return(false); -volume.Expand(btVector3(margin,margin,margin)); -volume.SignedExpand(velocity); -update(leaf,volume); -return(true); -} - -// -bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity) -{ -if(leaf->volume.Contain(volume)) return(false); -volume.SignedExpand(velocity); -update(leaf,volume); -return(true); -} - -// -bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin) -{ -if(leaf->volume.Contain(volume)) return(false); -volume.Expand(btVector3(margin,margin,margin)); -update(leaf,volume); -return(true); -} - -// -void btDbvt::remove(btDbvtNode* leaf) -{ -removeleaf(this,leaf); -deletenode(this,leaf); ---m_leaves; -} - -// -void btDbvt::write(IWriter* iwriter) const -{ -btDbvtNodeEnumerator nodes; -nodes.nodes.reserve(m_leaves*2); -enumNodes(m_root,nodes); -iwriter->Prepare(m_root,nodes.nodes.size()); -for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent); - if(n->isinternal()) - { - const int c0=nodes.nodes.findLinearSearch(n->childs[0]); - const int c1=nodes.nodes.findLinearSearch(n->childs[1]); - iwriter->WriteNode(n,i,p,c0,c1); - } - else - { - iwriter->WriteLeaf(n,i,p); - } - } -} - -// -void btDbvt::clone(btDbvt& dest,IClone* iclone) const -{ -dest.clear(); -if(m_root!=0) - { - btAlignedObjectArray stack; - stack.reserve(m_leaves); - stack.push_back(sStkCLN(m_root,0)); - do { - const int i=stack.size()-1; - const sStkCLN e=stack[i]; - btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data); - stack.pop_back(); - if(e.parent!=0) - e.parent->childs[i&1]=n; - else - dest.m_root=n; - if(e.node->isinternal()) - { - stack.push_back(sStkCLN(e.node->childs[0],n)); - stack.push_back(sStkCLN(e.node->childs[1],n)); - } - else - { - iclone->CloneLeaf(n); - } - } while(stack.size()>0); - } -} - -// -int btDbvt::maxdepth(const btDbvtNode* node) -{ -int depth=0; -if(node) getmaxdepth(node,1,depth); -return(depth); -} - -// -int btDbvt::countLeaves(const btDbvtNode* node) -{ -if(node->isinternal()) - return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); - else - return(1); -} - -// -void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves) -{ -if(node->isinternal()) - { - extractLeaves(node->childs[0],leaves); - extractLeaves(node->childs[1],leaves); - } - else - { - leaves.push_back(node); - } -} - -// -#if DBVT_ENABLE_BENCHMARK - -#include -#include -#include "LinearMath/btQuickProf.h" - -/* -q6600,2.4ghz - -/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32" -/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch" -/Fo"..\..\out\release8\build\libbulletcollision\\" -/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb" -/W3 /nologo /c /Wp64 /Zi /errorReport:prompt - -Benchmarking dbvt... - World scale: 100.000000 - Extents base: 1.000000 - Extents range: 4.000000 - Leaves: 8192 - sizeof(btDbvtVolume): 32 bytes - sizeof(btDbvtNode): 44 bytes -[1] btDbvtVolume intersections: 3499 ms (-1%) -[2] btDbvtVolume merges: 1934 ms (0%) -[3] btDbvt::collideTT: 5485 ms (-21%) -[4] btDbvt::collideTT self: 2814 ms (-20%) -[5] btDbvt::collideTT xform: 7379 ms (-1%) -[6] btDbvt::collideTT xform,self: 7270 ms (-2%) -[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s) -[8] insert/remove: 2093 ms (0%),(1001983 ir/s) -[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) -[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) -[11] optimize (incremental): 2514 ms (0%),(1668000 o/s) -[12] btDbvtVolume notequal: 3659 ms (0%) -[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) -[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) -[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) -[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) -[17] btDbvtVolume select: 3419 ms (0%) -*/ - -struct btDbvtBenchmark -{ -struct NilPolicy : btDbvt::ICollide - { - NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} - void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; } - void Process(const btDbvtNode*) { ++m_pcount; } - void Process(const btDbvtNode*,btScalar depth) - { - ++m_pcount; - if(m_checksort) - { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); } - } - int m_pcount; - btScalar m_depth; - bool m_checksort; - }; -struct P14 : btDbvt::ICollide - { - struct Node - { - const btDbvtNode* leaf; - btScalar depth; - }; - void Process(const btDbvtNode* leaf,btScalar depth) - { - Node n; - n.leaf = leaf; - n.depth = depth; - } - static int sortfnc(const Node& a,const Node& b) - { - if(a.depthb.depth) return(-1); - return(0); - } - btAlignedObjectArray m_nodes; - }; -struct P15 : btDbvt::ICollide - { - struct Node - { - const btDbvtNode* leaf; - btScalar depth; - }; - void Process(const btDbvtNode* leaf) - { - Node n; - n.leaf = leaf; - n.depth = dot(leaf->volume.Center(),m_axis); - } - static int sortfnc(const Node& a,const Node& b) - { - if(a.depthb.depth) return(-1); - return(0); - } - btAlignedObjectArray m_nodes; - btVector3 m_axis; - }; -static btScalar RandUnit() - { - return(rand()/(btScalar)RAND_MAX); - } -static btVector3 RandVector3() - { - return(btVector3(RandUnit(),RandUnit(),RandUnit())); - } -static btVector3 RandVector3(btScalar cs) - { - return(RandVector3()*cs-btVector3(cs,cs,cs)/2); - } -static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) - { - return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); - } -static btTransform RandTransform(btScalar cs) - { - btTransform t; - t.setOrigin(RandVector3(cs)); - t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized()); - return(t); - } -static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt) - { - dbvt.clear(); - for(int i=0;i volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i transforms; - btDbvtBenchmark::NilPolicy policy; - transforms.resize(cfgBenchmark5_Iterations); - for(int i=0;i transforms; - btDbvtBenchmark::NilPolicy policy; - transforms.resize(cfgBenchmark6_Iterations); - for(int i=0;i rayorg; - btAlignedObjectArray raydir; - btDbvtBenchmark::NilPolicy policy; - rayorg.resize(cfgBenchmark7_Iterations); - raydir.resize(cfgBenchmark7_Iterations); - for(int i=0;i leaves; - btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); - dbvt.optimizeTopDown(); - dbvt.extractLeaves(dbvt.m_root,leaves); - printf("[9] updates (teleport): "); - wallclock.reset(); - for(int i=0;i(leaves[rand()%cfgLeaves]), - btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale)); - } - } - const int time=(int)wallclock.getTimeMilliseconds(); - const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations; - printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time); - } -if(cfgBenchmark10_Enable) - {// Benchmark 10 - srand(380843); - btDbvt dbvt; - btAlignedObjectArray leaves; - btAlignedObjectArray vectors; - vectors.resize(cfgBenchmark10_Iterations); - for(int i=0;i(leaves[rand()%cfgLeaves]); - btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d); - dbvt.update(l,v); - } - } - const int time=(int)wallclock.getTimeMilliseconds(); - const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations; - printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time); - } -if(cfgBenchmark11_Enable) - {// Benchmark 11 - srand(380843); - btDbvt dbvt; - btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); - dbvt.optimizeTopDown(); - printf("[11] optimize (incremental): "); - wallclock.reset(); - for(int i=0;i volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i vectors; - btDbvtBenchmark::NilPolicy policy; - vectors.resize(cfgBenchmark13_Iterations); - for(int i=0;i vectors; - btDbvtBenchmark::P14 policy; - vectors.resize(cfgBenchmark14_Iterations); - for(int i=0;i vectors; - btDbvtBenchmark::P15 policy; - vectors.resize(cfgBenchmark15_Iterations); - for(int i=0;i batch; - btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); - dbvt.optimizeTopDown(); - batch.reserve(cfgBenchmark16_BatchCount); - printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount); - wallclock.reset(); - for(int i=0;i volumes; - btAlignedObjectArray results; - btAlignedObjectArray indices; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - indices.resize(cfgLeaves); - for(int i=0;i= 1400) - #define DBVT_USE_TEMPLATE 1 - #else - #define DBVT_USE_TEMPLATE 0 -#endif -#else -#define DBVT_USE_TEMPLATE 0 -#endif - -// Use only intrinsics instead of inline asm -#define DBVT_USE_INTRINSIC_SSE 1 - -// Using memmov for collideOCL -#define DBVT_USE_MEMMOVE 1 - -// Enable benchmarking code -#define DBVT_ENABLE_BENCHMARK 0 - -// Inlining -#define DBVT_INLINE SIMD_FORCE_INLINE -// Align -#ifdef WIN32 -#define DBVT_ALIGN __declspec(align(16)) -#else -#define DBVT_ALIGN -#endif - -// Specific methods implementation - -#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds -#define DBVT_SELECT_IMPL DBVT_IMPL_SSE -#define DBVT_MERGE_IMPL DBVT_IMPL_SSE -#define DBVT_INT0_IMPL DBVT_IMPL_SSE -#else -#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC -#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC -#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC -#endif - -#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ - (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ - (DBVT_INT0_IMPL==DBVT_IMPL_SSE) -#include -#endif - -// -// Auto config and checks -// - -#if DBVT_USE_TEMPLATE -#define DBVT_VIRTUAL -#define DBVT_VIRTUAL_DTOR(a) -#define DBVT_PREFIX template -#define DBVT_IPOLICY T& policy -#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0; -#else -#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} -#define DBVT_VIRTUAL virtual -#define DBVT_PREFIX -#define DBVT_IPOLICY ICollide& policy -#define DBVT_CHECKTYPE -#endif - -#if DBVT_USE_MEMMOVE -#ifndef __CELLOS_LV2__ -#include -#endif -#include -#endif - -#ifndef DBVT_USE_TEMPLATE -#error "DBVT_USE_TEMPLATE undefined" -#endif - -#ifndef DBVT_USE_MEMMOVE -#error "DBVT_USE_MEMMOVE undefined" -#endif - -#ifndef DBVT_ENABLE_BENCHMARK -#error "DBVT_ENABLE_BENCHMARK undefined" -#endif - -#ifndef DBVT_SELECT_IMPL -#error "DBVT_SELECT_IMPL undefined" -#endif - -#ifndef DBVT_MERGE_IMPL -#error "DBVT_MERGE_IMPL undefined" -#endif - -#ifndef DBVT_INT0_IMPL -#error "DBVT_INT0_IMPL undefined" -#endif - -// -// Defaults volumes -// - -/* btDbvtAabbMm */ -struct btDbvtAabbMm -{ -DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); } -DBVT_INLINE btVector3 Lengths() const { return(mx-mi); } -DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); } -DBVT_INLINE const btVector3& Mins() const { return(mi); } -DBVT_INLINE const btVector3& Maxs() const { return(mx); } -static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e); -static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); -static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); -static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); -static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); -DBVT_INLINE void Expand(const btVector3& e); -DBVT_INLINE void SignedExpand(const btVector3& e); -DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; -DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; -DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; -DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, - const btDbvtAabbMm& b); -DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, - const btDbvtAabbMm& b, - const btTransform& xform); -DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, - const btVector3& b); -DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, - const btVector3& org, - const btVector3& invdir, - const unsigned* signs); -DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, - const btDbvtAabbMm& b); -DBVT_INLINE friend int Select( const btDbvtAabbMm& o, - const btDbvtAabbMm& a, - const btDbvtAabbMm& b); -DBVT_INLINE friend void Merge( const btDbvtAabbMm& a, - const btDbvtAabbMm& b, - btDbvtAabbMm& r); -DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a, - const btDbvtAabbMm& b); -private: -DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; -private: -btVector3 mi,mx; -}; - -// Types -typedef btDbvtAabbMm btDbvtVolume; - -/* btDbvtNode */ -struct btDbvtNode -{ - btDbvtVolume volume; - btDbvtNode* parent; - DBVT_INLINE bool isleaf() const { return(childs[1]==0); } - DBVT_INLINE bool isinternal() const { return(!isleaf()); } - union { - btDbvtNode* childs[2]; - void* data; - }; -}; - -///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). -///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. -///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. -struct btDbvt - { - /* Stack element */ - struct sStkNN - { - const btDbvtNode* a; - const btDbvtNode* b; - sStkNN() {} - sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {} - }; - struct sStkNP - { - const btDbvtNode* node; - int mask; - sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {} - }; - struct sStkNPS - { - const btDbvtNode* node; - int mask; - btScalar value; - sStkNPS() {} - sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} - }; - struct sStkCLN - { - const btDbvtNode* node; - btDbvtNode* parent; - sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {} - }; - // Policies/Interfaces - - /* ICollide */ - struct ICollide - { - DBVT_VIRTUAL_DTOR(ICollide) - DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {} - DBVT_VIRTUAL void Process(const btDbvtNode*) {} - DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); } - DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); } - DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); } - }; - /* IWriter */ - struct IWriter - { - virtual ~IWriter() {} - virtual void Prepare(const btDbvtNode* root,int numnodes)=0; - virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0; - virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0; - }; - /* IClone */ - struct IClone - { - virtual ~IClone() {} - virtual void CloneLeaf(btDbvtNode*) {} - }; - - // Constants - enum { - SIMPLE_STACKSIZE = 64, - DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 - }; - - // Fields - btDbvtNode* m_root; - btDbvtNode* m_free; - int m_lkhd; - int m_leaves; - unsigned m_opath; - // Methods - btDbvt(); - ~btDbvt(); - void clear(); - bool empty() const { return(0==m_root); } - void optimizeBottomUp(); - void optimizeTopDown(int bu_treshold=128); - void optimizeIncremental(int passes); - btDbvtNode* insert(const btDbvtVolume& box,void* data); - void update(btDbvtNode* leaf,int lookahead=-1); - void update(btDbvtNode* leaf,const btDbvtVolume& volume); - bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin); - bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity); - bool update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin); - void remove(btDbvtNode* leaf); - void write(IWriter* iwriter) const; - void clone(btDbvt& dest,IClone* iclone=0) const; - static int maxdepth(const btDbvtNode* node); - static int countLeaves(const btDbvtNode* node); - static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves); - #if DBVT_ENABLE_BENCHMARK - static void benchmark(); - #else - static void benchmark(){} - #endif - // DBVT_IPOLICY must support ICollide policy/interface - DBVT_PREFIX - static void enumNodes( const btDbvtNode* root, - DBVT_IPOLICY); - DBVT_PREFIX - static void enumLeaves( const btDbvtNode* root, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideTT( const btDbvtNode* root0, - const btDbvtNode* root1, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideTT( const btDbvtNode* root0, - const btDbvtNode* root1, - const btTransform& xform, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideTT( const btDbvtNode* root0, - const btTransform& xform0, - const btDbvtNode* root1, - const btTransform& xform1, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideTV( const btDbvtNode* root, - const btDbvtVolume& volume, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideRAY( const btDbvtNode* root, - const btVector3& origin, - const btVector3& direction, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideKDOP(const btDbvtNode* root, - const btVector3* normals, - const btScalar* offsets, - int count, - DBVT_IPOLICY); - DBVT_PREFIX - static void collideOCL( const btDbvtNode* root, - const btVector3* normals, - const btScalar* offsets, - const btVector3& sortaxis, - int count, - DBVT_IPOLICY, - bool fullsort=true); - DBVT_PREFIX - static void collideTU( const btDbvtNode* root, - DBVT_IPOLICY); - // Helpers - static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) - { - int m=0; - while(l>1; - if(a[i[m]].value>=v) l=m+1; else h=m; - } - return(h); - } - static DBVT_INLINE int allocate( btAlignedObjectArray& ifree, - btAlignedObjectArray& stock, - const sStkNPS& value) - { - int i; - if(ifree.size()>0) - { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; } - else - { i=stock.size();stock.push_back(value); } - return(i); - } - // - private: - btDbvt(const btDbvt&) {} - }; - -// -// Inline's -// - -// -inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) -{ -btDbvtAabbMm box; -box.mi=c-e;box.mx=c+e; -return(box); -} - -// -inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r) -{ -return(FromCE(c,btVector3(r,r,r))); -} - -// -inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx) -{ -btDbvtAabbMm box; -box.mi=mi;box.mx=mx; -return(box); -} - -// -inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n) -{ -btDbvtAabbMm box; -box.mi=box.mx=pts[0]; -for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); -if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); -if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); -} - -// -DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const -{ -return( (mi.x()<=a.mi.x())&& - (mi.y()<=a.mi.y())&& - (mi.z()<=a.mi.z())&& - (mx.x()>=a.mx.x())&& - (mx.y()>=a.mx.y())&& - (mx.z()>=a.mx.z())); -} - -// -DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const -{ -btVector3 pi,px; -switch(s) - { - case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z()); - pi=btVector3(mx.x(),mx.y(),mx.z());break; - case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z()); - pi=btVector3(mi.x(),mx.y(),mx.z());break; - case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z()); - pi=btVector3(mx.x(),mi.y(),mx.z());break; - case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z()); - pi=btVector3(mi.x(),mi.y(),mx.z());break; - case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z()); - pi=btVector3(mx.x(),mx.y(),mi.z());break; - case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z()); - pi=btVector3(mi.x(),mx.y(),mi.z());break; - case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z()); - pi=btVector3(mx.x(),mi.y(),mi.z());break; - case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z()); - pi=btVector3(mi.x(),mi.y(),mi.z());break; - } -if((dot(n,px)+o)<0) return(-1); -if((dot(n,pi)+o)>=0) return(+1); -return(0); -} - -// -DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const -{ -const btVector3* b[]={&mx,&mi}; -const btVector3 p( b[(signs>>0)&1]->x(), - b[(signs>>1)&1]->y(), - b[(signs>>2)&1]->z()); -return(dot(p,v)); -} - -// -DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const -{ -for(int i=0;i<3;++i) - { - if(d[i]<0) - { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; } - else - { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; } - } -} - -// -DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, - const btDbvtAabbMm& b) -{ -#if DBVT_INT0_IMPL == DBVT_IMPL_SSE -const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), - _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); -const __int32* pu((const __int32*)&rt); -return((pu[0]|pu[1]|pu[2])==0); -#else -return( (a.mi.x()<=b.mx.x())&& - (a.mx.x()>=b.mi.x())&& - (a.mi.y()<=b.mx.y())&& - (a.mx.y()>=b.mi.y())&& - (a.mi.z()<=b.mx.z())&& - (a.mx.z()>=b.mi.z())); -#endif -} - -// -DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, - const btDbvtAabbMm& b, - const btTransform& xform) -{ -const btVector3 d0=xform*b.Center()-a.Center(); -const btVector3 d1=d0*xform.getBasis(); -btScalar s0[2]={0,0}; -btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]}; -a.AddSpan(d0,s0[0],s0[1]); -b.AddSpan(d1,s1[0],s1[1]); -if(s0[0]>(s1[1])) return(false); -if(s0[1]<(s1[0])) return(false); -return(true); -} - -// -DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, - const btVector3& b) -{ -return( (b.x()>=a.mi.x())&& - (b.y()>=a.mi.y())&& - (b.z()>=a.mi.z())&& - (b.x()<=a.mx.x())&& - (b.y()<=a.mx.y())&& - (b.z()<=a.mx.z())); -} - -// -DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, - const btVector3& org, - const btVector3& invdir, - const unsigned* signs) -{ -#if 0 -const btVector3 b0((a.mi-org)*invdir); -const btVector3 b1((a.mx-org)*invdir); -const btVector3 tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2])); -const btVector3 tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2])); -const btScalar tin=btMax(tmin[0],btMax(tmin[1],tmin[2])); -const btScalar tout=btMin(tmax[0],btMin(tmax[1],tmax[2])); -return(tinx()-org[0])*invdir[0]; -btScalar txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0]; -const btScalar tymin=(bounds[ signs[1]]->y()-org[1])*invdir[1]; -const btScalar tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1]; -if((txmin>tymax)||(tymin>txmax)) return(false); -if(tymin>txmin) txmin=tymin; -if(tymaxz()-org[2])*invdir[2]; -const btScalar tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2]; -if((txmin>tzmax)||(tzmin>txmax)) return(false); -if(tzmin>txmin) txmin=tzmin; -if(tzmax0); -#endif -} - -// -DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, - const btDbvtAabbMm& b) -{ -const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); -return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); -} - -// -DBVT_INLINE int Select( const btDbvtAabbMm& o, - const btDbvtAabbMm& a, - const btDbvtAabbMm& b) -{ -#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE -static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; - // TODO: the intrinsic version is 11% slower - #if DBVT_USE_INTRINSIC_SSE - __m128 omi(_mm_load_ps(o.mi)); - omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); - __m128 ami(_mm_load_ps(a.mi)); - ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); - ami=_mm_sub_ps(ami,omi); - ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); - __m128 bmi(_mm_load_ps(b.mi)); - bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); - bmi=_mm_sub_ps(bmi,omi); - bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); - __m128 t0(_mm_movehl_ps(ami,ami)); - ami=_mm_add_ps(ami,t0); - ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); - __m128 t1(_mm_movehl_ps(bmi,bmi)); - bmi=_mm_add_ps(bmi,t1); - bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); - return(_mm_cmple_ss(bmi,ami).m128_u32[0]&1); - #else - DBVT_ALIGN __int32 r[1]; - __asm - { - mov eax,o - mov ecx,a - mov edx,b - movaps xmm0,[eax] - movaps xmm5,mask - addps xmm0,[eax+16] - movaps xmm1,[ecx] - movaps xmm2,[edx] - addps xmm1,[ecx+16] - addps xmm2,[edx+16] - subps xmm1,xmm0 - subps xmm2,xmm0 - andps xmm1,xmm5 - andps xmm2,xmm5 - movhlps xmm3,xmm1 - movhlps xmm4,xmm2 - addps xmm1,xmm3 - addps xmm2,xmm4 - pshufd xmm3,xmm1,1 - pshufd xmm4,xmm2,1 - addss xmm1,xmm3 - addss xmm2,xmm4 - cmpless xmm2,xmm1 - movss r,xmm2 - } - return(r[0]&1); - #endif -#else -return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; - } -#endif -} - -// -DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a, - const btDbvtAabbMm& b) -{ -return( (a.mi.x()!=b.mi.x())|| - (a.mi.y()!=b.mi.y())|| - (a.mi.z()!=b.mi.z())|| - (a.mx.x()!=b.mx.x())|| - (a.mx.y()!=b.mx.y())|| - (a.mx.z()!=b.mx.z())); -} - -// -// Inline's -// - -// -DBVT_PREFIX -inline void btDbvt::enumNodes( const btDbvtNode* root, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -policy.Process(root); -if(root->isinternal()) - { - enumNodes(root->childs[0],policy); - enumNodes(root->childs[1],policy); - } -} - -// -DBVT_PREFIX -inline void btDbvt::enumLeaves( const btDbvtNode* root, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root->isinternal()) - { - enumLeaves(root->childs[0],policy); - enumLeaves(root->childs[1],policy); - } - else - { - policy.Process(root); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideTT( const btDbvtNode* root0, - const btDbvtNode* root1, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root0&&root1) - { - btAlignedObjectArray stack; - int depth=1; - int treshold=DOUBLE_STACKSIZE-4; - stack.resize(DOUBLE_STACKSIZE); - stack[0]=sStkNN(root0,root1); - do { - sStkNN p=stack[--depth]; - if(depth>treshold) - { - stack.resize(stack.size()*2); - treshold=stack.size()-4; - } - if(p.a==p.b) - { - if(p.a->isinternal()) - { - stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); - stack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); - stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); - } - } - else if(Intersect(p.a->volume,p.b->volume)) - { - if(p.a->isinternal()) - { - if(p.b->isinternal()) - { - stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); - stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); - stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); - stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); - } - else - { - stack[depth++]=sStkNN(p.a->childs[0],p.b); - stack[depth++]=sStkNN(p.a->childs[1],p.b); - } - } - else - { - if(p.b->isinternal()) - { - stack[depth++]=sStkNN(p.a,p.b->childs[0]); - stack[depth++]=sStkNN(p.a,p.b->childs[1]); - } - else - { - policy.Process(p.a,p.b); - } - } - } - } while(depth); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideTT( const btDbvtNode* root0, - const btDbvtNode* root1, - const btTransform& xform, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root0&&root1) - { - btAlignedObjectArray stack; - int depth=1; - int treshold=DOUBLE_STACKSIZE-4; - stack.resize(DOUBLE_STACKSIZE); - stack[0]=sStkNN(root0,root1); - do { - sStkNN p=stack[--depth]; - if(Intersect(p.a->volume,p.b->volume,xform)) - { - if(depth>treshold) - { - stack.resize(stack.size()*2); - treshold=stack.size()-4; - } - if(p.a->isinternal()) - { - if(p.b->isinternal()) - { - stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); - stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); - stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); - stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); - } - else - { - stack[depth++]=sStkNN(p.a->childs[0],p.b); - stack[depth++]=sStkNN(p.a->childs[1],p.b); - } - } - else - { - if(p.b->isinternal()) - { - stack[depth++]=sStkNN(p.a,p.b->childs[0]); - stack[depth++]=sStkNN(p.a,p.b->childs[1]); - } - else - { - policy.Process(p.a,p.b); - } - } - } - } while(depth); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideTT( const btDbvtNode* root0, - const btTransform& xform0, - const btDbvtNode* root1, - const btTransform& xform1, - DBVT_IPOLICY) -{ -const btTransform xform=xform0.inverse()*xform1; -collideTT(root0,root1,xform,policy); -} - -// -DBVT_PREFIX -inline void btDbvt::collideTV( const btDbvtNode* root, - const btDbvtVolume& vol, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root) - { - ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); - btAlignedObjectArray stack; - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(root); - do { - const btDbvtNode* n=stack[stack.size()-1]; - stack.pop_back(); - if(Intersect(n->volume,volume)) - { - if(n->isinternal()) - { - stack.push_back(n->childs[0]); - stack.push_back(n->childs[1]); - } - else - { - policy.Process(n); - } - } - } while(stack.size()>0); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideRAY( const btDbvtNode* root, - const btVector3& origin, - const btVector3& direction, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root) - { - const btVector3 normal=direction.normalized(); - const btVector3 invdir( 1/normal.x(), - 1/normal.y(), - 1/normal.z()); - const unsigned signs[]={ direction.x()<0, - direction.y()<0, - direction.z()<0}; - btAlignedObjectArray stack; - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(root); - do { - const btDbvtNode* node=stack[stack.size()-1]; - stack.pop_back(); - if(Intersect(node->volume,origin,invdir,signs)) - { - if(node->isinternal()) - { - stack.push_back(node->childs[0]); - stack.push_back(node->childs[1]); - } - else - { - policy.Process(node); - } - } - } while(stack.size()); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideKDOP(const btDbvtNode* root, - const btVector3* normals, - const btScalar* offsets, - int count, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root) - { - const int inside=(1< stack; - int signs[sizeof(unsigned)*8]; - btAssert(count=0)?1:0)+ - ((normals[i].y()>=0)?2:0)+ - ((normals[i].z()>=0)?4:0); - } - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(sStkNP(root,0)); - do { - sStkNP se=stack[stack.size()-1]; - bool out=false; - stack.pop_back(); - for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); - switch(side) - { - case -1: out=true;break; - case +1: se.mask|=j;break; - } - } - } - if(!out) - { - if((se.mask!=inside)&&(se.node->isinternal())) - { - stack.push_back(sStkNP(se.node->childs[0],se.mask)); - stack.push_back(sStkNP(se.node->childs[1],se.mask)); - } - else - { - if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); - } - } - } while(stack.size()); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideOCL( const btDbvtNode* root, - const btVector3* normals, - const btScalar* offsets, - const btVector3& sortaxis, - int count, - DBVT_IPOLICY, - bool fsort) -{ -DBVT_CHECKTYPE -if(root) - { - const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ - (sortaxis[1]>=0?2:0)+ - (sortaxis[2]>=0?4:0); - const int inside=(1< stock; - btAlignedObjectArray ifree; - btAlignedObjectArray stack; - int signs[sizeof(unsigned)*8]; - btAssert(count=0)?1:0)+ - ((normals[i].y()>=0)?2:0)+ - ((normals[i].z()>=0)?4:0); - } - stock.reserve(SIMPLE_STACKSIZE); - stack.reserve(SIMPLE_STACKSIZE); - ifree.reserve(SIMPLE_STACKSIZE); - stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); - do { - const int id=stack[stack.size()-1]; - sStkNPS se=stock[id]; - stack.pop_back();ifree.push_back(id); - if(se.mask!=inside) - { - bool out=false; - for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); - switch(side) - { - case -1: out=true;break; - case +1: se.mask|=j;break; - } - } - } - if(out) continue; - } - if(policy.Descent(se.node)) - { - if(se.node->isinternal()) - { - const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]}; - sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), - sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; - const int q=nes[0].value0)) - { - /* Insert 0 */ - j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); - stack.push_back(0); - #if DBVT_USE_MEMMOVE - memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); - #else - for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; - #endif - stack[j]=allocate(ifree,stock,nes[q]); - /* Insert 1 */ - j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); - stack.push_back(0); - #if DBVT_USE_MEMMOVE - memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); - #else - for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; - #endif - stack[j]=allocate(ifree,stock,nes[1-q]); - } - else - { - stack.push_back(allocate(ifree,stock,nes[q])); - stack.push_back(allocate(ifree,stock,nes[1-q])); - } - } - else - { - policy.Process(se.node,se.value); - } - } - } while(stack.size()); - } -} - -// -DBVT_PREFIX -inline void btDbvt::collideTU( const btDbvtNode* root, - DBVT_IPOLICY) -{ -DBVT_CHECKTYPE -if(root) - { - btAlignedObjectArray stack; - stack.reserve(SIMPLE_STACKSIZE); - stack.push_back(root); - do { - const btDbvtNode* n=stack[stack.size()-1]; - stack.pop_back(); - if(policy.Descent(n)) - { - if(n->isinternal()) - { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } - else - { policy.Process(n); } - } - } while(stack.size()>0); - } -} - -// -// PP Cleanup -// - -#undef DBVT_USE_MEMMOVE -#undef DBVT_USE_TEMPLATE -#undef DBVT_VIRTUAL_DTOR -#undef DBVT_VIRTUAL -#undef DBVT_PREFIX -#undef DBVT_IPOLICY -#undef DBVT_CHECKTYPE -#undef DBVT_IMPL_GENERIC -#undef DBVT_IMPL_SSE -#undef DBVT_USE_INTRINSIC_SSE -#undef DBVT_SELECT_IMPL -#undef DBVT_MERGE_IMPL -#undef DBVT_INT0_IMPL - -#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp deleted file mode 100644 index c6086f28f19..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btDbvtBroadphase implementation by Nathanael Presson - -#include "btDbvtBroadphase.h" - -// -// Profiling -// - -#if DBVT_BP_PROFILE -#include -struct ProfileScope - { - ProfileScope(btClock& clock,unsigned long& value) - { - m_clock=&clock; - m_value=&value; - m_base=clock.getTimeMicroseconds(); - } - ~ProfileScope() - { - (*m_value)+=m_clock->getTimeMicroseconds()-m_base; - } - btClock* m_clock; - unsigned long* m_value; - unsigned long m_base; - }; -#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_) -#else -#define SPC(_value_) -#endif - -// -// Helpers -// - -// -template -static inline void listappend(T* item,T*& list) -{ -item->links[0]=0; -item->links[1]=list; -if(list) list->links[0]=item; -list=item; -} - -// -template -static inline void listremove(T* item,T*& list) -{ -if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1]; -if(item->links[1]) item->links[1]->links[0]=item->links[0]; -} - -// -template -static inline int listcount(T* root) -{ -int n=0; -while(root) { ++n;root=root->links[1]; } -return(n); -} - -// -template -static inline void clear(T& value) -{ -static const struct ZeroDummy : T {} zerodummy; -value=zerodummy; -} - -// -// Colliders -// - -/* Tree collider */ -struct btDbvtTreeCollider : btDbvt::ICollide -{ -btDbvtBroadphase* pbp; - btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} -void Process(const btDbvtNode* na,const btDbvtNode* nb) - { - btDbvtProxy* pa=(btDbvtProxy*)na->data; - btDbvtProxy* pb=(btDbvtProxy*)nb->data; - #if DBVT_BP_DISCRETPAIRS - if(Intersect(pa->aabb,pb->aabb)) - #endif - { - if(pa>pb) btSwap(pa,pb); - pbp->m_paircache->addOverlappingPair(pa,pb); - } - } -}; - -// -// btDbvtBroadphase -// - -// -btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) -{ -m_releasepaircache = (paircache!=0)?false:true; -m_predictedframes = 2; -m_stageCurrent = 0; -m_fupdates = 1; -m_dupdates = 1; -m_paircache = paircache? - paircache : - new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); -m_gid = 0; -m_pid = 0; -for(int i=0;i<=STAGECOUNT;++i) - { - m_stageRoots[i]=0; - } -#if DBVT_BP_PROFILE -clear(m_profiling); -#endif -} - -// -btDbvtBroadphase::~btDbvtBroadphase() -{ -if(m_releasepaircache) -{ - m_paircache->~btOverlappingPairCache(); - btAlignedFree(m_paircache); -} -} - -// -btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, - const btVector3& aabbMax, - int /*shapeType*/, - void* userPtr, - short int collisionFilterGroup, - short int collisionFilterMask, - btDispatcher* /*dispatcher*/, - void* /*multiSapProxy*/) -{ -btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr, - collisionFilterGroup, - collisionFilterMask); -proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); -proxy->leaf = m_sets[0].insert(proxy->aabb,proxy); -proxy->stage = m_stageCurrent; -proxy->m_uniqueId = ++m_gid; -listappend(proxy,m_stageRoots[m_stageCurrent]); -return(proxy); -} - -// -void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy, - btDispatcher* dispatcher) -{ -btDbvtProxy* proxy=(btDbvtProxy*)absproxy; -if(proxy->stage==STAGECOUNT) - m_sets[1].remove(proxy->leaf); - else - m_sets[0].remove(proxy->leaf); -listremove(proxy,m_stageRoots[proxy->stage]); -m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); -btAlignedFree(proxy); -} - -// -void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, - const btVector3& aabbMin, - const btVector3& aabbMax, - btDispatcher* /*dispatcher*/) -{ -btDbvtProxy* proxy=(btDbvtProxy*)absproxy; -btDbvtVolume aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); -if(NotEqual(aabb,proxy->leaf->volume)) - { - if(proxy->stage==STAGECOUNT) - {/* fixed -> dynamic set */ - m_sets[1].remove(proxy->leaf); - proxy->leaf=m_sets[0].insert(aabb,proxy); - } - else - {/* dynamic set */ - if(Intersect(proxy->leaf->volume,aabb)) - {/* Moving */ - const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center(); - #ifdef DBVT_BP_MARGIN - m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes,DBVT_BP_MARGIN); - #else - m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes); - #endif - } - else - {/* Teleporting */ - m_sets[0].update(proxy->leaf,aabb); - } - } - listremove(proxy,m_stageRoots[proxy->stage]); - proxy->aabb = aabb; - proxy->stage = m_stageCurrent; - listappend(proxy,m_stageRoots[m_stageCurrent]); - } -} - -// -void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) -{ -collide(dispatcher); -#if DBVT_BP_PROFILE -if(0==(m_pid%DBVT_BP_PROFILING_RATE)) - { - printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs()); - unsigned int total=m_profiling.m_total; - if(total<=0) total=1; - printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE); - printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE); - printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE); - printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE); - const unsigned long sum=m_profiling.m_ddcollide+ - m_profiling.m_fdcollide+ - m_profiling.m_cleanup; - printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE); - printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE)); - clear(m_profiling); - m_clock.reset(); - } -#endif -} - -// -void btDbvtBroadphase::collide(btDispatcher* dispatcher) -{ -SPC(m_profiling.m_total); -/* optimize */ -m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); -m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); -/* dynamic -> fixed set */ -m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; -btDbvtProxy* current=m_stageRoots[m_stageCurrent]; -if(current) - { - btDbvtTreeCollider collider(this); - do { - btDbvtProxy* next=current->links[1]; - listremove(current,m_stageRoots[current->stage]); - listappend(current,m_stageRoots[STAGECOUNT]); - btDbvt::collideTT(m_sets[1].m_root,current->leaf,collider); - m_sets[0].remove(current->leaf); - current->leaf = m_sets[1].insert(current->aabb,current); - current->stage = STAGECOUNT; - current = next; - } while(current); - } -/* collide dynamics */ - { - btDbvtTreeCollider collider(this); - { - SPC(m_profiling.m_fdcollide); - btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider); - } - { - SPC(m_profiling.m_ddcollide); - btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider); - } - } -/* clean up */ - { - SPC(m_profiling.m_cleanup); - btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); - if(pairs.size()>0) - { - for(int i=0,ni=pairs.size();iaabb,pb->aabb)) - { - if(pa>pb) btSwap(pa,pb); - m_paircache->removeOverlappingPair(pa,pb,dispatcher); - --ni;--i; - } - } - } - } -++m_pid; -} - -// -void btDbvtBroadphase::optimize() -{ -m_sets[0].optimizeTopDown(); -m_sets[1].optimizeTopDown(); -} - -// -btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() -{ -return(m_paircache); -} - -// -const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const -{ -return(m_paircache); -} - -// -void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const -{ - - ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds; - -if(!m_sets[0].empty()) - if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume, - m_sets[1].m_root->volume,bounds); - else - bounds=m_sets[0].m_root->volume; -else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume; - else - bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0); -aabbMin=bounds.Mins(); -aabbMax=bounds.Maxs(); -} - -// -void btDbvtBroadphase::printStats() -{} - -#if DBVT_BP_PROFILE -#undef SPC -#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h deleted file mode 100644 index 3f19075552b..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btDbvtBroadphase implementation by Nathanael Presson -#ifndef BT_DBVT_BROADPHASE_H -#define BT_DBVT_BROADPHASE_H - -#include "BulletCollision/BroadphaseCollision/btDbvt.h" -#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" - -// -// Compile time config -// - -#define DBVT_BP_PROFILE 0 -#define DBVT_BP_DISCRETPAIRS 1 -#define DBVT_BP_MARGIN (btScalar)0.05 - -#if DBVT_BP_PROFILE - #define DBVT_BP_PROFILING_RATE 256 - #include "LinearMath/btQuickprof.h" -#endif - -// -// btDbvtProxy -// -struct btDbvtProxy : btBroadphaseProxy -{ -/* Fields */ -btDbvtAabbMm aabb; -btDbvtNode* leaf; -btDbvtProxy* links[2]; -int stage; -/* ctor */ -btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : - btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask) - { - links[0]=links[1]=0; - } -}; - -typedef btAlignedObjectArray btDbvtProxyArray; - -///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt). -///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other. -///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3. -struct btDbvtBroadphase : btBroadphaseInterface -{ -/* Config */ -enum { - DYNAMIC_SET = 0, /* Dynamic set index */ - FIXED_SET = 1, /* Fixed set index */ - STAGECOUNT = 2 /* Number of stages */ - }; -/* Fields */ -btDbvt m_sets[2]; // Dbvt sets -btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list -btOverlappingPairCache* m_paircache; // Pair cache -btScalar m_predictedframes; // Frames predicted -int m_stageCurrent; // Current stage -int m_fupdates; // % of fixed updates per frame -int m_dupdates; // % of dynamic updates per frame -int m_pid; // Parse id -int m_gid; // Gen id -bool m_releasepaircache; // Release pair cache on delete -#if DBVT_BP_PROFILE -btClock m_clock; -struct { - unsigned long m_total; - unsigned long m_ddcollide; - unsigned long m_fdcollide; - unsigned long m_cleanup; - unsigned long m_jobcount; - } m_profiling; -#endif -/* Methods */ -btDbvtBroadphase(btOverlappingPairCache* paircache=0); -~btDbvtBroadphase(); -void collide(btDispatcher* dispatcher); -void optimize(); -/* btBroadphaseInterface Implementation */ -btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); -void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); -void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); -void calculateOverlappingPairs(btDispatcher* dispatcher); -btOverlappingPairCache* getOverlappingPairCache(); -const btOverlappingPairCache* getOverlappingPairCache() const; -void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; -void printStats(); -}; - -#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 6db71a0170e..3d958cc8fef 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef _DISPATCHER_H #define _DISPATCHER_H -#include "LinearMath/btScalar.h" +#include "../../LinearMath/btScalar.h" class btCollisionAlgorithm; struct btBroadphaseProxy; @@ -43,9 +43,7 @@ struct btDispatcherInfo m_useContinuous(false), m_debugDraw(0), m_enableSatConvex(false), - m_enableSPU(true), - m_useEpa(true), - m_allowedCcdPenetration(btScalar(0.04)), + m_enableSPU(false), m_stackAllocator(0) { @@ -53,19 +51,17 @@ struct btDispatcherInfo btScalar m_timeStep; int m_stepCount; int m_dispatchFunc; - mutable btScalar m_timeOfImpact; + btScalar m_timeOfImpact; bool m_useContinuous; class btIDebugDraw* m_debugDraw; bool m_enableSatConvex; bool m_enableSPU; - bool m_useEpa; - btScalar m_allowedCcdPenetration; btStackAlloc* m_stackAllocator; }; -///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. -///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). +/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs. +/// For example for pairwise collision detection or user callbacks (game logic). class btDispatcher { @@ -85,18 +81,12 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0; + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0; virtual int getNumManifolds() const = 0; virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; - virtual btPersistentManifold** getInternalManifoldPointer() = 0; - - virtual void* allocateCollisionAlgorithm(int size) = 0; - - virtual void freeCollisionAlgorithm(void* ptr) = 0; - }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp deleted file mode 100644 index 3f866ab7c5f..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btMultiSapBroadphase.h" - -#include "btSimpleBroadphase.h" -#include "LinearMath/btAabbUtil2.h" -#include "btQuantizedBvh.h" - -/// btSapBroadphaseArray m_sapBroadphases; - -/// btOverlappingPairCache* m_overlappingPairs; -extern int gOverlappingPairs; - -/* -class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache -{ -public: - - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) - { - return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); - } -}; - -*/ - -btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) -:m_overlappingPairs(pairCache), -m_optimizedAabbTree(0), -m_ownsPairCache(false), -m_invalidPair(0) -{ - if (!m_overlappingPairs) - { - m_ownsPairCache = true; - void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); - m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); - } - - struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback - { - virtual ~btMultiSapOverlapFilterCallback() - {} - // return true when pairs need collision - virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const - { - btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; - btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; - - bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; - collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); - - return collides; - } - }; - - void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); - m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); - - m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); -// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); -// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); -} - -btMultiSapBroadphase::~btMultiSapBroadphase() -{ - if (m_ownsPairCache) - { - m_overlappingPairs->~btOverlappingPairCache(); - btAlignedFree(m_overlappingPairs); - } -} - - -void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) -{ - m_optimizedAabbTree = new btQuantizedBvh(); - m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); - QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray(); - for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax); - m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); - m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); - int partId = 0; - node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; - nodes.push_back(node); - } - m_optimizedAabbTree->buildInternal(); -} - -btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) -{ - //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested - - void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); - btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); - m_multiSapProxies.push_back(proxy); - - ///this should deal with inserting/removal into child broadphases - setAabb(proxy,aabbMin,aabbMax,dispatcher); - return proxy; -} - -void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) -{ - ///not yet - btAssert(0); - -} - - -void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase) -{ - void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); - btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; - bridgeProxyRef->m_childProxy = childProxy; - bridgeProxyRef->m_childBroadphase = childBroadphase; - parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); -} - - -bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); -bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) -{ -return -amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && -amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && -amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); -} - - - - - - -//#include - -void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) -{ - btMultiSapProxy* multiProxy = static_cast(proxy); - multiProxy->m_aabbMin = aabbMin; - multiProxy->m_aabbMax = aabbMax; - - -// bool fullyContained = false; -// bool alreadyInSimple = false; - - - - - struct MyNodeOverlapCallback : public btNodeOverlapCallback - { - btMultiSapBroadphase* m_multiSap; - btMultiSapProxy* m_multiProxy; - btDispatcher* m_dispatcher; - - MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) - :m_multiSap(multiSap), - m_multiProxy(multiProxy), - m_dispatcher(dispatcher) - { - - } - - virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) - { - btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; - - int containingBroadphaseIndex = -1; - //already found? - for (int i=0;im_bridgeProxies.size();i++) - { - - if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) - { - containingBroadphaseIndex = i; - break; - } - } - if (containingBroadphaseIndex<0) - { - //add it - btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); - m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); - - } - } - }; - - MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); - - - - - m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); - int i; - - for ( i=0;im_bridgeProxies.size();i++) - { - btVector3 worldAabbMin,worldAabbMax; - multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); - bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); - if (!overlapsBroadphase) - { - //remove it now - btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; - - btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; - bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); - - multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); - multiProxy->m_bridgeProxies.pop_back(); - - } - } - - - /* - - if (1) - { - - //find broadphase that contain this multiProxy - int numChildBroadphases = getBroadphaseArray().size(); - for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax); - bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); - - // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); - int containingBroadphaseIndex = -1; - - //if already contains this - - for (int i=0;im_bridgeProxies.size();i++) - { - if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) - { - containingBroadphaseIndex = i; - } - alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); - } - - if (overlapsBroadphase) - { - if (containingBroadphaseIndex<0) - { - btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); - childProxy->m_multiSapParentProxy = multiProxy; - addToChildBroadphase(multiProxy,childProxy,childBroadphase); - } - } else - { - if (containingBroadphaseIndex>=0) - { - //remove - btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; - - btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; - bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); - - multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); - multiProxy->m_bridgeProxies.pop_back(); - } - } - } - - - ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) - ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) - if (0)//!multiProxy->m_bridgeProxies.size()) - { - ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision - ///this is needed to be able to calculate the aabb overlap - btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); - childProxy->m_multiSapParentProxy = multiProxy; - addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); - } - } - - if (!multiProxy->m_bridgeProxies.size()) - { - ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision - ///this is needed to be able to calculate the aabb overlap - btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); - childProxy->m_multiSapParentProxy = multiProxy; - addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); - } -*/ - - - //update - for ( i=0;im_bridgeProxies.size();i++) - { - btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; - bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); - } - -} -bool stopUpdating=false; - - - -class btMultiSapBroadphasePairSortPredicate -{ - public: - - bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) - { - btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; - btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; - btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; - btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; - - return aProxy0 > bProxy0 || - (aProxy0 == bProxy0 && aProxy1 > bProxy1) || - (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); - } -}; - - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb -void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) -{ - -// m_simpleBroadphase->calculateOverlappingPairs(dispatcher); - - if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) - { - - btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); - - // quicksort(overlappingPairArray,0,overlappingPairArray.size()); - - overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;im_multiSapParentProxy : 0; - btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; - btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; - btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; - - bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); - - previousPair = pair; - - bool needsRemoval = false; - - if (!isDuplicate) - { - bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); - - if (hasOverlap) - { - needsRemoval = false;//callback->processOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - - ///if you don't like to skip the invalid pairs in the array, execute following code: - #define CLEAN_INVALID_PAIRS 1 - #ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); - overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - #endif//CLEAN_INVALID_PAIRS - - //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); - } - - -} - - -bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) -{ - btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; - btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; - - return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, - multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); - -} - - -void btMultiSapBroadphase::printStats() -{ -/* printf("---------------------------------\n"); - - printf("btMultiSapBroadphase.h\n"); - printf("numHandles = %d\n",m_multiSapProxies.size()); - //find broadphase that contain this multiProxy - int numChildBroadphases = getBroadphaseArray().size(); - for (int i=0;iprintStats(); - - } - */ - -} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h deleted file mode 100644 index a0c002de856..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h +++ /dev/null @@ -1,144 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -#ifndef BT_MULTI_SAP_BROADPHASE -#define BT_MULTI_SAP_BROADPHASE - -#include "btBroadphaseInterface.h" -#include "LinearMath/btAlignedObjectArray.h" -#include "btOverlappingPairCache.h" - - -class btBroadphaseInterface; -class btSimpleBroadphase; - - -typedef btAlignedObjectArray btSapBroadphaseArray; - -///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. -///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. -///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. -///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 -///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 -class btMultiSapBroadphase :public btBroadphaseInterface -{ - btSapBroadphaseArray m_sapBroadphases; - - btSimpleBroadphase* m_simpleBroadphase; - - btOverlappingPairCache* m_overlappingPairs; - - class btQuantizedBvh* m_optimizedAabbTree; - - - bool m_ownsPairCache; - - btOverlapFilterCallback* m_filterCallback; - - int m_invalidPair; - - struct btBridgeProxy - { - btBroadphaseProxy* m_childProxy; - btBroadphaseInterface* m_childBroadphase; - }; - - -public: - - struct btMultiSapProxy : public btBroadphaseProxy - { - - ///array with all the entries that this proxy belongs to - btAlignedObjectArray m_bridgeProxies; - btVector3 m_aabbMin; - btVector3 m_aabbMax; - - int m_shapeType; - -/* void* m_userPtr; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; -*/ - btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) - :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), - m_aabbMin(aabbMin), - m_aabbMax(aabbMax), - m_shapeType(shapeType) - { - m_multiSapParentProxy =this; - } - - - }; - -protected: - - - btAlignedObjectArray m_multiSapProxies; - -public: - - btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); - - - btSapBroadphaseArray& getBroadphaseArray() - { - return m_sapBroadphases; - } - - const btSapBroadphaseArray& getBroadphaseArray() const - { - return m_sapBroadphases; - } - - virtual ~btMultiSapBroadphase(); - - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - - void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); - - ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - virtual btOverlappingPairCache* getOverlappingPairCache() - { - return m_overlappingPairs; - } - virtual const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_overlappingPairs; - } - - ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame - ///will add some transform later - virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const - { - aabbMin.setValue(-1e30f,-1e30f,-1e30f); - aabbMax.setValue(1e30f,1e30f,1e30f); - } - - void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); - - virtual void printStats(); - - void quicksort (btBroadphasePairArray& a, int lo, int hi); - -}; - -#endif //BT_MULTI_SAP_BROADPHASE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp index ff65cdde79f..60f0a41a9d7 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -1,3 +1,4 @@ + /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -20,43 +21,44 @@ subject to the following restrictions: #include "btDispatcher.h" #include "btCollisionAlgorithm.h" -#include - int gOverlappingPairs = 0; -int gRemovePairs =0; -int gAddedPairs =0; -int gFindPairs =0; - - - - -btHashedOverlappingPairCache::btHashedOverlappingPairCache(): - m_overlapFilterCallback(0), - m_blockedForChanges(false) +btOverlappingPairCache::btOverlappingPairCache(): +m_blockedForChanges(false), +m_overlapFilterCallback(0) +//m_NumOverlapBroadphasePair(0) { - int initialAllocatedSize= 2; - m_overlappingPairArray.reserve(initialAllocatedSize); - growTables(); } - - -btHashedOverlappingPairCache::~btHashedOverlappingPairCache() +btOverlappingPairCache::~btOverlappingPairCache() { //todo/test: show we erase/delete data, or is it automatic } +void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair) +{ + + int findIndex = m_overlappingPairArray.findLinearSearch(findPair); + if (findIndex < m_overlappingPairArray.size()) + { + gOverlappingPairs--; + btBroadphasePair& pair = m_overlappingPairArray[findIndex]; + cleanOverlappingPair(pair); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1); + m_overlappingPairArray.pop_back(); + } +} -void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) + +void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) { if (pair.m_algorithm) { { - pair.m_algorithm->~btCollisionAlgorithm(); - dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + delete pair.m_algorithm;; pair.m_algorithm=0; } } @@ -65,370 +67,20 @@ void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,b -void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - class CleanPairCallback : public btOverlapCallback - { - btBroadphaseProxy* m_cleanProxy; - btOverlappingPairCache* m_pairCache; - btDispatcher* m_dispatcher; - - public: - CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) - :m_cleanProxy(cleanProxy), - m_pairCache(pairCache), - m_dispatcher(dispatcher) - { - } - virtual bool processOverlap(btBroadphasePair& pair) - { - if ((pair.m_pProxy0 == m_cleanProxy) || - (pair.m_pProxy1 == m_cleanProxy)) - { - m_pairCache->cleanOverlappingPair(pair,m_dispatcher); - } - return false; - } - - }; - - CleanPairCallback cleanPairs(proxy,this,dispatcher); - - processAllOverlappingPairs(&cleanPairs,dispatcher); - -} - - - - -void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) -{ - - class RemovePairCallback : public btOverlapCallback - { - btBroadphaseProxy* m_obsoleteProxy; - - public: - RemovePairCallback(btBroadphaseProxy* obsoleteProxy) - :m_obsoleteProxy(obsoleteProxy) - { - } - virtual bool processOverlap(btBroadphasePair& pair) - { - return ((pair.m_pProxy0 == m_obsoleteProxy) || - (pair.m_pProxy1 == m_obsoleteProxy)); - } - - }; - - - RemovePairCallback removeCallback(proxy); - - processAllOverlappingPairs(&removeCallback,dispatcher); -} - - - - - -btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) -{ - gFindPairs++; - if(proxy0>proxy1) btSwap(proxy0,proxy1); - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - - /*if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2);*/ - - int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); - - if (hash >= m_hashTable.size()) - { - return NULL; - } - - int index = m_hashTable[hash]; - while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) - { - index = m_next[index]; - } - - if (index == BT_NULL_PAIR) - { - return NULL; - } - - btAssert(index < m_overlappingPairArray.size()); - - return &m_overlappingPairArray[index]; -} - -//#include - -void btHashedOverlappingPairCache::growTables() -{ - - int newCapacity = m_overlappingPairArray.capacity(); - - if (m_hashTable.size() < newCapacity) - { - //grow hashtable and next table - int curHashtableSize = m_hashTable.size(); - - m_hashTable.resize(newCapacity); - m_next.resize(newCapacity); - - - int i; - - for (i= 0; i < newCapacity; ++i) - { - m_hashTable[i] = BT_NULL_PAIR; - } - for (i = 0; i < newCapacity; ++i) - { - m_next[i] = BT_NULL_PAIR; - } - - for(i=0;igetUid(); - int proxyId2 = pair.m_pProxy1->getUid(); - /*if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2);*/ - int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask - m_next[i] = m_hashTable[hashValue]; - m_hashTable[hashValue] = i; - } - - - } -} - -btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) -{ - if(proxy0>proxy1) btSwap(proxy0,proxy1); - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - - /*if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2);*/ - - int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask - - - btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); - if (pair != NULL) - { - return pair; - } - /*for(int i=0;i%u\r\n",proxyId1,proxyId2); - internalFindPair(proxy0, proxy1, hash); - } - }*/ - int count = m_overlappingPairArray.size(); - int oldCapacity = m_overlappingPairArray.capacity(); - void* mem = &m_overlappingPairArray.expand(); - int newCapacity = m_overlappingPairArray.capacity(); - - if (oldCapacity < newCapacity) - { - growTables(); - //hash with new capacity - hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); - } - - pair = new (mem) btBroadphasePair(*proxy0,*proxy1); -// pair->m_pProxy0 = proxy0; -// pair->m_pProxy1 = proxy1; - pair->m_algorithm = 0; - pair->m_userInfo = 0; - - - m_next[count] = m_hashTable[hash]; - m_hashTable[hash] = count; - - return pair; -} - - - -void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) -{ - gRemovePairs++; - if(proxy0>proxy1) btSwap(proxy0,proxy1); - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - - /*if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2);*/ - - int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); - - btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); - if (pair == NULL) - { - return 0; - } - - cleanOverlappingPair(*pair,dispatcher); - - void* userData = pair->m_userInfo; - - btAssert(pair->m_pProxy0->getUid() == proxyId1); - btAssert(pair->m_pProxy1->getUid() == proxyId2); - - int pairIndex = int(pair - &m_overlappingPairArray[0]); - btAssert(pairIndex < m_overlappingPairArray.size()); - - // Remove the pair from the hash table. - int index = m_hashTable[hash]; - btAssert(index != BT_NULL_PAIR); - - int previous = BT_NULL_PAIR; - while (index != pairIndex) - { - previous = index; - index = m_next[index]; - } - - if (previous != BT_NULL_PAIR) - { - btAssert(m_next[previous] == pairIndex); - m_next[previous] = m_next[pairIndex]; - } - else - { - m_hashTable[hash] = m_next[pairIndex]; - } - - // We now move the last pair into spot of the - // pair being removed. We need to fix the hash - // table indices to support the move. - - int lastPairIndex = m_overlappingPairArray.size() - 1; - - // If the removed pair is the last pair, we are done. - if (lastPairIndex == pairIndex) - { - m_overlappingPairArray.pop_back(); - return userData; - } - - // Remove the last pair from the hash table. - const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; - /* missing swap here too, Nat. */ - int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1)); - - index = m_hashTable[lastHash]; - btAssert(index != BT_NULL_PAIR); - - previous = BT_NULL_PAIR; - while (index != lastPairIndex) - { - previous = index; - index = m_next[index]; - } - - if (previous != BT_NULL_PAIR) - { - btAssert(m_next[previous] == lastPairIndex); - m_next[previous] = m_next[lastPairIndex]; - } - else - { - m_hashTable[lastHash] = m_next[lastPairIndex]; - } - - // Copy the last pair into the remove pair's spot. - m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; - - // Insert the last pair into the hash table - m_next[pairIndex] = m_hashTable[lastHash]; - m_hashTable[lastHash] = pairIndex; - - m_overlappingPairArray.pop_back(); - - return userData; -} -//#include - -void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) -{ - - int i; - -// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); - for (i=0;iprocessOverlap(*pair)) - { - removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); - - gOverlappingPairs--; - } else - { - i++; - } - } -} - - - -void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher ) -{ - if (!hasDeferredRemoval()) - { - btBroadphasePair findPair(*proxy0,*proxy1); - - int findIndex = m_overlappingPairArray.findLinearSearch(findPair); - if (findIndex < m_overlappingPairArray.size()) - { - gOverlappingPairs--; - btBroadphasePair& pair = m_overlappingPairArray[findIndex]; - void* userData = pair.m_userInfo; - cleanOverlappingPair(pair,dispatcher); - - m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); - m_overlappingPairArray.pop_back(); - return userData; - } - } - - return 0; -} - - - - - - - - -btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) { //don't add overlap with own assert(proxy0 != proxy1); if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; + return; + + + btBroadphasePair pair(*proxy0,*proxy1); - void* mem = &m_overlappingPairArray.expand(); - btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + m_overlappingPairArray.push_back(pair); gOverlappingPairs++; - gAddedPairs++; - return pair; } @@ -436,7 +88,7 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP ///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. ///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) ///Also we can use a 2D bitmap, which can be useful for a future GPU implementation - btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) { if (!needsBroadphaseCollision(proxy0,proxy1)) return 0; @@ -457,81 +109,18 @@ btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseP - - - - - -//#include - -void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) -{ - - int i; - - for (i=0;iprocessOverlap(*pair)) - { - cleanOverlappingPair(*pair,dispatcher); - - m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); - m_overlappingPairArray.pop_back(); - gOverlappingPairs--; - } else - { - i++; - } - } -} - - - - -btSortedOverlappingPairCache::btSortedOverlappingPairCache(): - m_blockedForChanges(false), - m_hasDeferredRemoval(true), - m_overlapFilterCallback(0) -{ - int initialAllocatedSize= 2; - m_overlappingPairArray.reserve(initialAllocatedSize); -} - -btSortedOverlappingPairCache::~btSortedOverlappingPairCache() -{ - //todo/test: show we erase/delete data, or is it automatic -} - -void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) -{ - if (pair.m_algorithm) - { - { - pair.m_algorithm->~btCollisionAlgorithm(); - dispatcher->freeCollisionAlgorithm(pair.m_algorithm); - pair.m_algorithm=0; - gRemovePairs--; - } - } -} - - -void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) { class CleanPairCallback : public btOverlapCallback { btBroadphaseProxy* m_cleanProxy; btOverlappingPairCache* m_pairCache; - btDispatcher* m_dispatcher; public: - CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache) :m_cleanProxy(cleanProxy), - m_pairCache(pairCache), - m_dispatcher(dispatcher) + m_pairCache(pairCache) { } virtual bool processOverlap(btBroadphasePair& pair) @@ -539,21 +128,22 @@ void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { - m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + m_pairCache->cleanOverlappingPair(pair); } return false; } }; - CleanPairCallback cleanPairs(proxy,this,dispatcher); + CleanPairCallback cleanPairs(proxy,this); - processAllOverlappingPairs(&cleanPairs,dispatcher); + processAllOverlappingPairs(&cleanPairs); } -void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) + +void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy) { class RemovePairCallback : public btOverlapCallback @@ -573,7 +163,34 @@ void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroad }; + RemovePairCallback removeCallback(proxy); - processAllOverlappingPairs(&removeCallback,dispatcher); + processAllOverlappingPairs(&removeCallback); } + + + +void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback) +{ + + int i; + + for (i=0;iprocessOverlap(*pair)) + { + cleanOverlappingPair(*pair); + + m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.pop_back(); + gOverlappingPairs--; + } else + { + i++; + } + } +} + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index 66679bd218a..a81fe3264df 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -1,3 +1,4 @@ + /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -19,13 +20,9 @@ subject to the following restrictions: #include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" -#include "btOverlappingPairCallback.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btAlignedObjectArray.h" -class btDispatcher; - -typedef btAlignedObjectArray btBroadphasePairArray; struct btOverlapCallback { @@ -33,7 +30,6 @@ struct btOverlapCallback {} //return true for deletion of the pair virtual bool processOverlap(btBroadphasePair& pair) = 0; - }; struct btOverlapFilterCallback @@ -44,261 +40,38 @@ struct btOverlapFilterCallback virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; }; - - - - - - -extern int gRemovePairs; -extern int gAddedPairs; -extern int gFindPairs; - -const int BT_NULL_PAIR=0xffffffff; - -///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. -///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. -class btOverlappingPairCache : public btOverlappingPairCallback -{ -public: - virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor - - virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0; - - virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0; - - virtual btBroadphasePairArray& getOverlappingPairArray() = 0; - - virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; - - virtual int getNumOverlappingPairs() const = 0; - - virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; - - virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; - - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; - - virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; - - virtual bool hasDeferredRemoval() = 0; - -}; - -/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com -class btHashedOverlappingPairCache : public btOverlappingPairCache -{ - btBroadphasePairArray m_overlappingPairArray; - btOverlapFilterCallback* m_overlapFilterCallback; - bool m_blockedForChanges; - - -public: - btHashedOverlappingPairCache(); - virtual ~btHashedOverlappingPairCache(); - - - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - - virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); - - SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const - { - if (m_overlapFilterCallback) - return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); - - bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; - collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); - - return collides; - } - - // Add a pair and return the new pair. If the pair already exists, - // no new pair is created and the old one is returned. - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) - { - gAddedPairs++; - - if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; - - return internalAddPair(proxy0,proxy1); - } - - - - void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - - - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); - - virtual btBroadphasePair* getOverlappingPairArrayPtr() - { - return &m_overlappingPairArray[0]; - } - - const btBroadphasePair* getOverlappingPairArrayPtr() const - { - return &m_overlappingPairArray[0]; - } - - btBroadphasePairArray& getOverlappingPairArray() - { - return m_overlappingPairArray; - } - - const btBroadphasePairArray& getOverlappingPairArray() const - { - return m_overlappingPairArray; - } - - void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); - - - - btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); - - int GetCount() const { return m_overlappingPairArray.size(); } -// btBroadphasePair* GetPairs() { return m_pairs; } - - btOverlapFilterCallback* getOverlapFilterCallback() - { - return m_overlapFilterCallback; - } - - void setOverlapFilterCallback(btOverlapFilterCallback* callback) - { - m_overlapFilterCallback = callback; - } - - int getNumOverlappingPairs() const - { - return m_overlappingPairArray.size(); - } -private: - - btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - - void growTables(); - - SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) - { - return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; - } - - /* - // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm - // This assumes proxyId1 and proxyId2 are 16-bit. - SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) - { - int key = (proxyId2 << 16) | proxyId1; - key = ~key + (key << 15); - key = key ^ (key >> 12); - key = key + (key << 2); - key = key ^ (key >> 4); - key = key * 2057; - key = key ^ (key >> 16); - return key; - } - */ - - - - SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) - { - int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); - // Thomas Wang's hash - - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return static_cast(key); - } - - - - - - SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) - { - int proxyId1 = proxy0->getUid(); - int proxyId2 = proxy1->getUid(); - #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. - if (proxyId1 > proxyId2) - btSwap(proxyId1, proxyId2); - #endif - - int index = m_hashTable[hash]; - - while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) - { - index = m_next[index]; - } - - if ( index == BT_NULL_PAIR ) - { - return NULL; - } - - btAssert(index < m_overlappingPairArray.size()); - - return &m_overlappingPairArray[index]; - } - - virtual bool hasDeferredRemoval() - { - return false; - } - -public: - - btAlignedObjectArray m_hashTable; - btAlignedObjectArray m_next; - -}; - - - - -///btSortedOverlappingPairCache maintains the objects with overlapping AABB +///btOverlappingPairCache maintains the objects with overlapping AABB ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase -class btSortedOverlappingPairCache : public btOverlappingPairCache +class btOverlappingPairCache : public btBroadphaseInterface { protected: //avoid brute-force finding all the time - btBroadphasePairArray m_overlappingPairArray; - + btAlignedObjectArray m_overlappingPairArray; + //during the dispatch, check that user doesn't destroy/create proxy bool m_blockedForChanges; - - ///by default, do the removal during the pair traversal - bool m_hasDeferredRemoval; //if set, use the callback instead of the built in filter in needBroadphaseCollision btOverlapFilterCallback* m_overlapFilterCallback; - public: - btSortedOverlappingPairCache(); - virtual ~btSortedOverlappingPairCache(); + btOverlappingPairCache(); + virtual ~btOverlappingPairCache(); - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + virtual void processAllOverlappingPairs(btOverlapCallback*); - void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + void removeOverlappingPair(btBroadphasePair& pair); - void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + void cleanOverlappingPair(btBroadphasePair& pair); - btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + void cleanProxyFromPairs(btBroadphaseProxy* proxy); - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy); inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const @@ -311,19 +84,10 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache return collides; } - - btBroadphasePairArray& getOverlappingPairArray() - { - return m_overlappingPairArray; - } - - const btBroadphasePairArray& getOverlappingPairArray() const - { - return m_overlappingPairArray; - } - + + virtual void refreshOverlappingPairs() =0; btBroadphasePair* getOverlappingPairArrayPtr() { @@ -350,88 +114,7 @@ class btSortedOverlappingPairCache : public btOverlappingPairCache m_overlapFilterCallback = callback; } - virtual bool hasDeferredRemoval() - { - return m_hasDeferredRemoval; - } - - }; - - - -///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing. -class btNullPairCache : public btOverlappingPairCache -{ - - btBroadphasePairArray m_overlappingPairArray; - -public: - - virtual btBroadphasePair* getOverlappingPairArrayPtr() - { - return &m_overlappingPairArray[0]; - } - const btBroadphasePair* getOverlappingPairArrayPtr() const - { - return &m_overlappingPairArray[0]; - } - btBroadphasePairArray& getOverlappingPairArray() - { - return m_overlappingPairArray; - } - - virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) - { - - } - - virtual int getNumOverlappingPairs() const - { - return 0; - } - - virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) - { - - } - - virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) - { - } - - virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) - { - } - - virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) - { - return 0; - } - - virtual bool hasDeferredRemoval() - { - return true; - } - - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) - { - return 0; - } - - virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) - { - return 0; - } - - virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) - { - } - - -}; - - #endif //OVERLAPPING_PAIR_CACHE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h deleted file mode 100644 index 9c7b6f81367..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h +++ /dev/null @@ -1,40 +0,0 @@ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef OVERLAPPING_PAIR_CALLBACK_H -#define OVERLAPPING_PAIR_CALLBACK_H - -class btDispatcher; -struct btBroadphasePair; - -///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. -class btOverlappingPairCallback -{ -public: - virtual ~btOverlappingPairCallback() - { - - } - - virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; - - virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0; - - virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0; - -}; - -#endif //OVERLAPPING_PAIR_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp deleted file mode 100644 index a30bd1fd9e1..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp +++ /dev/null @@ -1,1025 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btQuantizedBvh.h" - -#include "LinearMath/btAabbUtil2.h" -#include "LinearMath/btIDebugDraw.h" - - -btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false), - //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) - m_traversalMode(TRAVERSAL_STACKLESS) - //m_traversalMode(TRAVERSAL_RECURSIVE) - ,m_subtreeHeaderCount(0) //PCK: add this line -{ - -} - - - - - -void btQuantizedBvh::buildInternal() -{ - ///assumes that caller filled in the m_quantizedLeafNodes - m_useQuantization = true; - int numLeafNodes = 0; - - if (m_useQuantization) - { - //now we have an array of leafnodes in m_leafNodes - numLeafNodes = m_quantizedLeafNodes.size(); - - m_quantizedContiguousNodes.resize(2*numLeafNodes); - - } - - m_curNodeIndex = 0; - - buildTree(0,numLeafNodes); - - ///if the entire tree is small then subtree size, we need to create a header info for the tree - if(m_useQuantization && !m_SubtreeHeaders.size()) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); - subtree.m_rootNodeIndex = 0; - subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); - } - - //PCK: update the copy of the size - m_subtreeHeaderCount = m_SubtreeHeaders.size(); - - //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary - m_quantizedLeafNodes.clear(); - m_leafNodes.clear(); -} - - - -///just for debugging, to visualize the individual patches/subtrees -#ifdef DEBUG_PATCH_COLORS -btVector3 color[4]= -{ - btVector3(255,0,0), - btVector3(0,255,0), - btVector3(0,0,255), - btVector3(0,255,255) -}; -#endif //DEBUG_PATCH_COLORS - - - -void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) -{ - //enlarge the AABB to avoid division by zero when initializing the quantization values - btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); - m_bvhAabbMin = bvhAabbMin - clampValue; - m_bvhAabbMax = bvhAabbMax + clampValue; - btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; - m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; - m_useQuantization = true; -} - - - - -btQuantizedBvh::~btQuantizedBvh() -{ -} - -#ifdef DEBUG_TREE_BUILDING -int gStackDepth = 0; -int gMaxStackDepth = 0; -#endif //DEBUG_TREE_BUILDING - -void btQuantizedBvh::buildTree (int startIndex,int endIndex) -{ -#ifdef DEBUG_TREE_BUILDING - gStackDepth++; - if (gStackDepth > gMaxStackDepth) - gMaxStackDepth = gStackDepth; -#endif //DEBUG_TREE_BUILDING - - - int splitAxis, splitIndex, i; - int numIndices =endIndex-startIndex; - int curIndex = m_curNodeIndex; - - assert(numIndices>0); - - if (numIndices==1) - { -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); - - m_curNodeIndex++; - return; - } - //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. - - splitAxis = calcSplittingAxis(startIndex,endIndex); - - splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); - - int internalNodeIndex = m_curNodeIndex; - - setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin); - setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax); - - for (i=startIndex;im_escapeIndex; - - int leftChildNodexIndex = m_curNodeIndex; - - //build left child tree - buildTree(startIndex,splitIndex); - - int rightChildNodexIndex = m_curNodeIndex; - //build right child tree - buildTree(splitIndex,endIndex); - -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - int escapeIndex = m_curNodeIndex - curIndex; - - if (m_useQuantization) - { - //escapeIndex is the number of nodes of this subtree - const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); - const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; - if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) - { - updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); - } - } - - setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); - -} - -void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) -{ - btAssert(m_useQuantization); - - btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; - int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); - int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); - - btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; - int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); - int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); - - if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(leftChildNode); - subtree.m_rootNodeIndex = leftChildNodexIndex; - subtree.m_subtreeSize = leftSubTreeSize; - } - - if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(rightChildNode); - subtree.m_rootNodeIndex = rightChildNodexIndex; - subtree.m_subtreeSize = rightSubTreeSize; - } - - //PCK: update the copy of the size - m_subtreeHeaderCount = m_SubtreeHeaders.size(); -} - - -int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) -{ - int i; - int splitIndex =startIndex; - int numIndices = endIndex - startIndex; - btScalar splitValue; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - for (i=startIndex;i splitValue) - { - //swap - swapLeafNodes(i,splitIndex); - splitIndex++; - } - } - - //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex - //otherwise the tree-building might fail due to stack-overflows in certain cases. - //unbalanced1 is unsafe: it can cause stack overflows - //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); - - //unbalanced2 should work too: always use center (perfect balanced trees) - //bool unbalanced2 = true; - - //this should be safe too: - int rangeBalancedIndices = numIndices/3; - bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); - - if (unbalanced) - { - splitIndex = startIndex+ (numIndices>>1); - } - - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - (void)unbal; - btAssert(!unbal); - - return splitIndex; -} - - -int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex) -{ - int i; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); - int numIndices = endIndex-startIndex; - - for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); - isLeafNode = rootNode->m_escapeIndex == -1; - - //PCK: unsigned instead of bool - if (isLeafNode && (aabbOverlap != 0)) - { - nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); - } - - //PCK: unsigned instead of bool - if ((aabbOverlap != 0) || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->m_escapeIndex; - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -/* -///this was the original recursive traversal, before we optimized towards stackless traversal -void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); - if (aabbOverlap) - { - isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); - if (isLeafNode) - { - nodeCallback->processNode(rootNode); - } else - { - walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); - walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); - } - } - -} -*/ - -void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - bool isLeafNode; - //PCK: unsigned instead of bool - unsigned aabbOverlap; - - //PCK: unsigned instead of bool - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); - isLeafNode = currentNode->isLeafNode(); - - //PCK: unsigned instead of bool - if (aabbOverlap != 0) - { - if (isLeafNode) - { - nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex()); - } else - { - //process left and right children - const btQuantizedBvhNode* leftChildNode = currentNode+1; - walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - - const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); - walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - } - } -} - - - - - -void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const -{ - btAssert(m_useQuantization); - - int curIndex = startNodeIndex; - int walkIterations = 0; - int subTreeSize = endNodeIndex - startNodeIndex; - (void)subTreeSize; - - const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; - int escapeIndex; - - bool isLeafNode; - //PCK: unsigned instead of bool - unsigned boxBoxOverlap = 0; - unsigned rayBoxOverlap = 0; - - btScalar lambda_max = 1.0; -#define RAYAABB2 -#ifdef RAYAABB2 - btVector3 rayFrom = raySource; - btVector3 rayDirection = (rayTarget-raySource); - rayDirection.normalize (); - lambda_max = rayDirection.dot(rayTarget-raySource); - ///what about division by zero? --> just set rayDirection[i] to 1.0 - rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0]; - rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1]; - rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2]; - unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0}; -#endif - - /* Quick pruning by quantized box */ - btVector3 rayAabbMin = raySource; - btVector3 rayAabbMax = raySource; - rayAabbMin.setMin(rayTarget); - rayAabbMax.setMax(rayTarget); - - /* Add box cast extents to bounding box */ - rayAabbMin += aabbMin; - rayAabbMax += aabbMax; - - unsigned short int quantizedQueryAabbMin[3]; - unsigned short int quantizedQueryAabbMax[3]; - quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0); - quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1); - - while (curIndex < endNodeIndex) - { - -//#define VISUALLY_ANALYZE_BVH 1 -#ifdef VISUALLY_ANALYZE_BVH - //some code snippet to debugDraw aabb, to visually analyze bvh structure - static int drawPatch = 0; - //need some global access to a debugDrawer - extern btIDebugDraw* debugDrawerPtr; - if (curIndex==drawPatch) - { - btVector3 aabbMin,aabbMax; - aabbMin = unQuantize(rootNode->m_quantizedAabbMin); - aabbMax = unQuantize(rootNode->m_quantizedAabbMax); - btVector3 color(1,0,0); - debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); - } -#endif//VISUALLY_ANALYZE_BVH - - //catch bugs in tree data - assert (walkIterations < subTreeSize); - - walkIterations++; - //PCK: unsigned instead of bool - // only interested if this is closer than any previous hit - btScalar param = 1.0; - rayBoxOverlap = 0; - boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); - isLeafNode = rootNode->isLeafNode(); - if (boxBoxOverlap) - { - btVector3 bounds[2]; - bounds[0] = unQuantize(rootNode->m_quantizedAabbMin); - bounds[1] = unQuantize(rootNode->m_quantizedAabbMax); - /* Add box cast extents */ - bounds[0] += aabbMin; - bounds[1] += aabbMax; - btVector3 normal; -#if 0 - bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max); - bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal); - if (ra2 != ra) - { - printf("functions don't match\n"); - } -#endif -#ifdef RAYAABB2 - ///careful with this check: need to check division by zero (above) and fix the unQuantize method - ///thanks Joerg/hiker for the reproduction case! - ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 - - rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max); -#else - rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal); -#endif - } - - if (isLeafNode && rayBoxOverlap) - { - nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); - } - - //PCK: unsigned instead of bool - if ((rayBoxOverlap != 0) || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->getEscapeIndex(); - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const -{ - btAssert(m_useQuantization); - - int curIndex = startNodeIndex; - int walkIterations = 0; - int subTreeSize = endNodeIndex - startNodeIndex; - (void)subTreeSize; - - const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; - int escapeIndex; - - bool isLeafNode; - //PCK: unsigned instead of bool - unsigned aabbOverlap; - - while (curIndex < endNodeIndex) - { - -//#define VISUALLY_ANALYZE_BVH 1 -#ifdef VISUALLY_ANALYZE_BVH - //some code snippet to debugDraw aabb, to visually analyze bvh structure - static int drawPatch = 0; - //need some global access to a debugDrawer - extern btIDebugDraw* debugDrawerPtr; - if (curIndex==drawPatch) - { - btVector3 aabbMin,aabbMax; - aabbMin = unQuantize(rootNode->m_quantizedAabbMin); - aabbMax = unQuantize(rootNode->m_quantizedAabbMax); - btVector3 color(1,0,0); - debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); - } -#endif//VISUALLY_ANALYZE_BVH - - //catch bugs in tree data - assert (walkIterations < subTreeSize); - - walkIterations++; - //PCK: unsigned instead of bool - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); - isLeafNode = rootNode->isLeafNode(); - - if (isLeafNode && aabbOverlap) - { - nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); - } - - //PCK: unsigned instead of bool - if ((aabbOverlap != 0) || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->getEscapeIndex(); - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -//This traversal can be called from Playstation 3 SPU -void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - int i; - - - for (i=0;im_SubtreeHeaders.size();i++) - { - const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - - //PCK: unsigned instead of bool - unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap != 0) - { - walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, - subtree.m_rootNodeIndex, - subtree.m_rootNodeIndex+subtree.m_subtreeSize); - } - } -} - - -void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const -{ - bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS; - if (fast_path) - { - walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex); - } else { - /* Otherwise fallback to AABB overlap test */ - btVector3 aabbMin = raySource; - btVector3 aabbMax = raySource; - aabbMin.setMin(rayTarget); - aabbMax.setMax(rayTarget); - reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax); - } -} - - -void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const -{ - bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS; - if (fast_path) - { - walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); - } else { - /* Slow path: - Construct the bounding box for the entire box cast and send that down the tree */ - btVector3 qaabbMin = raySource; - btVector3 qaabbMax = raySource; - qaabbMin.setMin(rayTarget); - qaabbMax.setMax(rayTarget); - qaabbMin += aabbMin; - qaabbMax += aabbMax; - reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax); - } -} - - -void btQuantizedBvh::swapLeafNodes(int i,int splitIndex) -{ - if (m_useQuantization) - { - btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; - m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; - m_quantizedLeafNodes[splitIndex] = tmp; - } else - { - btOptimizedBvhNode tmp = m_leafNodes[i]; - m_leafNodes[i] = m_leafNodes[splitIndex]; - m_leafNodes[splitIndex] = tmp; - } -} - -void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) -{ - if (m_useQuantization) - { - m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; - } else - { - m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; - } -} - -//PCK: include -#include - -//PCK: consts -static const unsigned BVH_ALIGNMENT = 16; -static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; - -static const unsigned BVH_ALIGNMENT_BLOCKS = 2; - - - -unsigned int btQuantizedBvh::getAlignmentSerializationPadding() -{ - return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; -} - -unsigned btQuantizedBvh::calculateSerializeBufferSize() -{ - unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding(); - baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; - if (m_useQuantization) - { - return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); - } - return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); -} - -bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) -{ - assert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); - m_subtreeHeaderCount = m_SubtreeHeaders.size(); - -/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) - { - ///check alignedment for buffer? - btAssert(0); - return false; - } -*/ - - btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer; - - // construct the class so the virtual function table, etc will be set up - // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor - new (targetBvh) btQuantizedBvh; - - if (i_swapEndian) - { - targetBvh->m_curNodeIndex = static_cast(btSwapEndian(m_curNodeIndex)); - - - btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); - btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); - btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); - - targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); - targetBvh->m_subtreeHeaderCount = static_cast(btSwapEndian(m_subtreeHeaderCount)); - } - else - { - targetBvh->m_curNodeIndex = m_curNodeIndex; - targetBvh->m_bvhAabbMin = m_bvhAabbMin; - targetBvh->m_bvhAabbMax = m_bvhAabbMax; - targetBvh->m_bvhQuantization = m_bvhQuantization; - targetBvh->m_traversalMode = m_traversalMode; - targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; - } - - targetBvh->m_useQuantization = m_useQuantization; - - unsigned char *nodeData = (unsigned char *)targetBvh; - nodeData += sizeof(btQuantizedBvh); - - unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - int nodeCount = m_curNodeIndex; - - if (m_useQuantization) - { - targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); - } - } - else - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; - - targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; - - - } - } - nodeData += sizeof(btQuantizedBvhNode) * nodeCount; - } - else - { - targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); - btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); - - targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex)); - targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart)); - targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex)); - } - } - else - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; - targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; - - targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; - targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; - targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; - } - } - nodeData += sizeof(btOptimizedBvhNode) * nodeCount; - } - - sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - // Now serialize the subtree headers - targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); - if (i_swapEndian) - { - for (int i = 0; i < m_subtreeHeaderCount; i++) - { - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); - - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); - - targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex)); - targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize)); - } - } - else - { - for (int i = 0; i < m_subtreeHeaderCount; i++) - { - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); - - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); - targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); - - targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); - targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); - targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i]; - } - } - - nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; - - return true; -} - -btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) -{ - - if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) - { - return NULL; - } - btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer; - - if (i_swapEndian) - { - bvh->m_curNodeIndex = static_cast(btSwapEndian(bvh->m_curNodeIndex)); - - btUnSwapVector3Endian(bvh->m_bvhAabbMin); - btUnSwapVector3Endian(bvh->m_bvhAabbMax); - btUnSwapVector3Endian(bvh->m_bvhQuantization); - - bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); - bvh->m_subtreeHeaderCount = static_cast(btSwapEndian(bvh->m_subtreeHeaderCount)); - } - - unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize(); - btAssert(calculatedBufSize <= i_dataBufferSize); - - if (calculatedBufSize > i_dataBufferSize) - { - return NULL; - } - - unsigned char *nodeData = (unsigned char *)bvh; - nodeData += sizeof(btQuantizedBvh); - - unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - int nodeCount = bvh->m_curNodeIndex; - - // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor - // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor - new (bvh) btQuantizedBvh(*bvh, false); - - if (bvh->m_useQuantization) - { - bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); - - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); - bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); - - bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); - } - } - nodeData += sizeof(btQuantizedBvhNode) * nodeCount; - } - else - { - bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); - - if (i_swapEndian) - { - for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) - { - btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); - btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); - - bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex)); - bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart)); - bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex)); - } - } - nodeData += sizeof(btOptimizedBvhNode) * nodeCount; - } - - sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; - nodeData += sizeToAdd; - - // Now serialize the subtree headers - bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); - if (i_swapEndian) - { - for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) - { - bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); - - bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); - bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); - - bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex)); - bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize)); - } - } - - return bvh; -} - -// Constructor that prevents btVector3's default constructor from being called -btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) : -m_bvhAabbMin(self.m_bvhAabbMin), -m_bvhAabbMax(self.m_bvhAabbMax), -m_bvhQuantization(self.m_bvhQuantization) -{ - - -} - - - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h deleted file mode 100644 index 8a149b533fa..00000000000 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h +++ /dev/null @@ -1,486 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef QUANTIZED_BVH_H -#define QUANTIZED_BVH_H - -//#define DEBUG_CHECK_DEQUANTIZATION 1 -#ifdef DEBUG_CHECK_DEQUANTIZATION -#ifdef __SPU__ -#define printf spu_printf -#endif //__SPU__ - -#include -#include -#endif //DEBUG_CHECK_DEQUANTIZATION - -#include "LinearMath/btVector3.h" -#include "LinearMath/btAlignedAllocator.h" - - -//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp - - -//Note: currently we have 16 bytes per quantized node -#define MAX_SUBTREE_SIZE_IN_BYTES 2048 - -// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one -// actually) triangles each (since the sign bit is reserved -#define MAX_NUM_PARTS_IN_BITS 10 - -///btQuantizedBvhNode is a compressed aabb node, 16 bytes. -///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). -ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes - int m_escapeIndexOrTriangleIndex; - - bool isLeafNode() const - { - //skipindex is negative (internal node), triangleindex >=0 (leafnode) - return (m_escapeIndexOrTriangleIndex >= 0); - } - int getEscapeIndex() const - { - btAssert(!isLeafNode()); - return -m_escapeIndexOrTriangleIndex; - } - int getTriangleIndex() const - { - btAssert(isLeafNode()); - // Get only the lower bits where the triangle index is stored - return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); - } - int getPartId() const - { - btAssert(isLeafNode()); - // Get only the highest bits where the part index is stored - return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); - } -} -; - -/// btOptimizedBvhNode contains both internal and leaf node information. -/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. -ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - //32 bytes - btVector3 m_aabbMinOrg; - btVector3 m_aabbMaxOrg; - - //4 - int m_escapeIndex; - - //8 - //for child nodes - int m_subPart; - int m_triangleIndex; - int m_padding[5];//bad, due to alignment - - -}; - - -///btBvhSubtreeInfo provides info to gather a subtree of limited size -ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo -{ -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes, points to the root of the subtree - int m_rootNodeIndex; - //4 bytes - int m_subtreeSize; - int m_padding[3]; - - btBvhSubtreeInfo() - { - //memset(&m_padding[0], 0, sizeof(m_padding)); - } - - - void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) - { - m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; - m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; - m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; - m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; - m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; - m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; - } -} -; - - -class btNodeOverlapCallback -{ -public: - virtual ~btNodeOverlapCallback() {}; - - virtual void processNode(int subPart, int triangleIndex) = 0; -}; - -#include "LinearMath/btAlignedAllocator.h" -#include "LinearMath/btAlignedObjectArray.h" - - - -///for code readability: -typedef btAlignedObjectArray NodeArray; -typedef btAlignedObjectArray QuantizedNodeArray; -typedef btAlignedObjectArray BvhSubtreeInfoArray; - - -///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. -///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. -///It is recommended to use quantization for better performance and lower memory requirements. -ATTRIBUTE_ALIGNED16(class) btQuantizedBvh -{ -protected: - - NodeArray m_leafNodes; - NodeArray m_contiguousNodes; - - QuantizedNodeArray m_quantizedLeafNodes; - - QuantizedNodeArray m_quantizedContiguousNodes; - - int m_curNodeIndex; - - - //quantization data - bool m_useQuantization; - btVector3 m_bvhAabbMin; - btVector3 m_bvhAabbMax; - btVector3 m_bvhQuantization; -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - enum btTraversalMode - { - TRAVERSAL_STACKLESS = 0, - TRAVERSAL_STACKLESS_CACHE_FRIENDLY, - TRAVERSAL_RECURSIVE - }; -protected: - - btTraversalMode m_traversalMode; - - BvhSubtreeInfoArray m_SubtreeHeaders; - - //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray - int m_subtreeHeaderCount; - - - ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) - ///this might be refactored into a virtual, it is usually not calculated at run-time - void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) - { - if (m_useQuantization) - { - quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; - - } - } - void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) - { - if (m_useQuantization) - { - quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; - } - } - - btVector3 getAabbMin(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMinOrg; - - } - btVector3 getAabbMax(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMaxOrg; - - } - - - void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) - { - if (m_useQuantization) - { - m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; - } - else - { - m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; - } - - } - - void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) - { - if (m_useQuantization) - { - unsigned short int quantizedAabbMin[3]; - unsigned short int quantizedAabbMax[3]; - quantize(quantizedAabbMin,newAabbMin,0); - quantize(quantizedAabbMax,newAabbMax,1); - for (int i=0;i<3;i++) - { - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; - - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; - - } - } else - { - //non-quantized - m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); - m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); - } - } - - void swapLeafNodes(int firstIndex,int secondIndex); - - void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); - -protected: - - - - void buildTree (int startIndex,int endIndex); - - int calcSplittingAxis(int startIndex,int endIndex); - - int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); - - void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; - void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; - - ///tree traversal designed for small-memory processors like PS3 SPU - void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; - - -#define USE_BANCHLESS 1 -#ifdef USE_BANCHLESS - //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) - SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const - { - return static_cast(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) - & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) - & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), - 1, 0)); - } -#else - SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const - { - bool overlap = true; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; - return overlap; - } -#endif //USE_BANCHLESS - - void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); - -public: - btQuantizedBvh(); - - virtual ~btQuantizedBvh(); - - - ///***************************************** expert/internal use only ************************* - void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); - QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; } - ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized - void buildInternal(); - ///***************************************** expert/internal use only ************************* - - void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const; - void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const; - - SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const - { - - btAssert(m_useQuantization); - - btAssert(point.getX() <= m_bvhAabbMax.getX()); - btAssert(point.getY() <= m_bvhAabbMax.getY()); - btAssert(point.getZ() <= m_bvhAabbMax.getZ()); - - btAssert(point.getX() >= m_bvhAabbMin.getX()); - btAssert(point.getY() >= m_bvhAabbMin.getY()); - btAssert(point.getZ() >= m_bvhAabbMin.getZ()); - - btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization; - ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative - ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly) - ///todo: double-check this - if (isMax) - { - out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); - out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1)); - out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1)); - } else - { - out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe)); - out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe)); - out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe)); - } - - -#ifdef DEBUG_CHECK_DEQUANTIZATION - btVector3 newPoint = unQuantize(out); - if (isMax) - { - if (newPoint.getX() < point.getX()) - { - printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); - } - if (newPoint.getY() < point.getY()) - { - printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); - } - if (newPoint.getZ() < point.getZ()) - { - - printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); - } - } else - { - if (newPoint.getX() > point.getX()) - { - printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); - } - if (newPoint.getY() > point.getY()) - { - printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); - } - if (newPoint.getZ() > point.getZ()) - { - printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); - } - } -#endif //DEBUG_CHECK_DEQUANTIZATION - - } - - - SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const - { - - btAssert(m_useQuantization); - - btVector3 clampedPoint(point2); - clampedPoint.setMax(m_bvhAabbMin); - clampedPoint.setMin(m_bvhAabbMax); - - quantize(out,clampedPoint,isMax); - - } - - SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const - { - btVector3 vecOut; - vecOut.setValue( - (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), - (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), - (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); - vecOut += m_bvhAabbMin; - return vecOut; - } - - ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. - void setTraversalMode(btTraversalMode traversalMode) - { - m_traversalMode = traversalMode; - } - - - SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() - { - return m_quantizedContiguousNodes; - } - - - SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() - { - return m_SubtreeHeaders; - } - - - /////Calculate space needed to store BVH for serialization - unsigned calculateSerializeBufferSize(); - - /// Data buffer MUST be 16 byte aligned - virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); - - ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' - static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); - - static unsigned int getAlignmentSerializationPadding(); - - SIMD_FORCE_INLINE bool isQuantized() - { - return m_useQuantization; - } - -private: - // Special "copy" constructor that allows for in-place deserialization - // Prevents btVector3's default constructor from being called, but doesn't inialize much else - // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) - btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory); - -} -; - - -#endif //QUANTIZED_BVH_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index a57952ffa06..30bcbe0c5f1 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -14,84 +14,83 @@ subject to the following restrictions: */ #include "btSimpleBroadphase.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include +#include #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" #include "LinearMath/btMatrix3x3.h" #include -extern int gOverlappingPairs; void btSimpleBroadphase::validate() { - for (int i=0;i=0;i--) { - m_pairCache->~btOverlappingPairCache(); - btAlignedFree(m_pairCache); + BP_Proxy* proxy = m_pProxies[i]; + destroyProxy(proxy); } + */ } -btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask) { - if (m_numHandles >= m_maxHandles) + if (m_numProxies >= m_maxProxies) { - btAssert(0); + assert(0); return 0; //should never happen, but don't let the game crash ;-) } - assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); + assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]); - int newHandleIndex = allocHandle(); - btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); + int freeIndex= m_freeProxies[m_firstFreeProxy]; + btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); + m_firstFreeProxy++; + + btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; + + int index = int(proxy - proxy1); + btAssert(index == freeIndex); + + m_pProxies[m_numProxies] = proxy; + m_numProxies++; + //validate(); return proxy; } @@ -125,19 +124,34 @@ protected: }; }; -void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg) { + int i; + btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); - freeHandle(proxy0); - - m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); + btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; + + int index = int(proxy0 - proxy1); + btAssert (index < m_maxProxies); + m_freeProxies[--m_firstFreeProxy] = index; + removeOverlappingPairsContainingProxy(proxyOrg); + + for (i=0;im_min = aabbMin; @@ -172,129 +186,37 @@ public: } }; -void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +void btSimpleBroadphase::refreshOverlappingPairs() { //first check for new overlapping pairs int i,j; - if (m_numHandles >= 0) + for (i=0;ifindPair(proxy0,proxy1)) - { - m_pairCache->addOverlappingPair(proxy0,proxy1); - } - } else - { - if (!m_pairCache->hasDeferredRemoval()) - { - if ( m_pairCache->findPair(proxy0,proxy1)) - { - m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); - } - } + addOverlappingPair(proxy0,proxy1); } } - } - - if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) - { - - btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; - - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - m_pairCache->cleanOverlappingPair(pair,dispatcher); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } - - ///if you don't like to skip the invalid pairs in the array, execute following code: -#define CLEAN_INVALID_PAIRS 1 -#ifdef CLEAN_INVALID_PAIRS - - //perform a sort, to sort 'invalid' pairs to the end - overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); - - overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; -#endif//CLEAN_INVALID_PAIRS } } + + + CheckOverlapCallback checkOverlap; + + processAllOverlappingPairs(&checkOverlap); + + } -bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); - btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); - return aabbOverlap(p0,p1); -} - - - diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index e2ebb825725..fb155e7047c 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -24,69 +24,35 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy { btVector3 m_min; btVector3 m_max; - int m_nextFree; - -// int m_handleId; - btSimpleBroadphaseProxy() {}; - btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) - :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy), + btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) + :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), m_min(minpt),m_max(maxpt) { (void)shapeType; } - - SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} - SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} - - - }; -///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead. -///It is a brute force aabb culling broadphase based on O(n^2) aabb checks -class btSimpleBroadphase : public btBroadphaseInterface +///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks +class btSimpleBroadphase : public btOverlappingPairCache { protected: - int m_numHandles; // number of active handles - int m_maxHandles; // max number of handles + btSimpleBroadphaseProxy* m_proxies; + int* m_freeProxies; + int m_firstFreeProxy; + + btSimpleBroadphaseProxy** m_pProxies; + int m_numProxies; + - btSimpleBroadphaseProxy* m_pHandles; // handles pool - - void* m_pHandlesRawPtr; - int m_firstFreeHandle; // free handles list - - int allocHandle() - { - btAssert(m_numHandles < m_maxHandles); - int freeHandle = m_firstFreeHandle; - m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); - m_numHandles++; - return freeHandle; - } - - void freeHandle(btSimpleBroadphaseProxy* proxy) - { - int handle = int(proxy-m_pHandles); - btAssert(handle >= 0 && handle < m_maxHandles); - - proxy->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numHandles--; - } - - btOverlappingPairCache* m_pairCache; - bool m_ownsPairCache; - - int m_invalidPair; + int m_maxProxies; inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) @@ -101,48 +67,26 @@ protected: protected: - - + virtual void refreshOverlappingPairs(); public: - btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); + btSimpleBroadphase(int maxProxies=16384); virtual ~btSimpleBroadphase(); static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); - virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); - virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + virtual void destroyProxy(btBroadphaseProxy* proxy); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); - btOverlappingPairCache* getOverlappingPairCache() - { - return m_pairCache; - } - const btOverlappingPairCache* getOverlappingPairCache() const - { - return m_pairCache; - } - - bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + - ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame - ///will add some transform later - virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const - { - aabbMin.setValue(-1e30f,-1e30f,-1e30f); - aabbMax.setValue(1e30f,1e30f,1e30f); - } - virtual void printStats() - { -// printf("btSimpleBroadphase.h\n"); -// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); - } }; diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt index d77ca6444c7..e565bf7edea 100644 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -5,149 +5,56 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletCollision BroadphaseCollision/btAxisSweep3.cpp - BroadphaseCollision/btAxisSweep3.h BroadphaseCollision/btBroadphaseProxy.cpp - BroadphaseCollision/btBroadphaseProxy.h BroadphaseCollision/btCollisionAlgorithm.cpp - BroadphaseCollision/btCollisionAlgorithm.h BroadphaseCollision/btDispatcher.cpp - BroadphaseCollision/btDispatcher.h - BroadphaseCollision/btDbvtBroadphase.cpp - BroadphaseCollision/btDbvtBroadphase.h - BroadphaseCollision/btDbvt.cpp - BroadphaseCollision/btDbvt.h - BroadphaseCollision/btMultiSapBroadphase.cpp - BroadphaseCollision/btMultiSapBroadphase.h BroadphaseCollision/btOverlappingPairCache.cpp - BroadphaseCollision/btOverlappingPairCache.h - BroadphaseCollision/btOverlappingPairCallback.h - BroadphaseCollision/btQuantizedBvh.cpp - BroadphaseCollision/btQuantizedBvh.h BroadphaseCollision/btSimpleBroadphase.cpp - BroadphaseCollision/btSimpleBroadphase.h CollisionDispatch/btCollisionDispatcher.cpp - CollisionDispatch/btCollisionDispatcher.h CollisionDispatch/btCollisionObject.cpp - CollisionDispatch/btCollisionObject.h CollisionDispatch/btCollisionWorld.cpp - CollisionDispatch/btCollisionWorld.h CollisionDispatch/btCompoundCollisionAlgorithm.cpp - CollisionDispatch/btCompoundCollisionAlgorithm.h CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp - CollisionDispatch/btConvexConcaveCollisionAlgorithm.h - CollisionDispatch/btDefaultCollisionConfiguration.cpp - CollisionDispatch/btDefaultCollisionConfiguration.h CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp - CollisionDispatch/btSphereSphereCollisionAlgorithm.h - CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp - CollisionDispatch/btBoxBoxCollisionAlgorithm.h - CollisionDispatch/btBoxBoxDetector.cpp - CollisionDispatch/btBoxBoxDetector.h CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp - CollisionDispatch/btSphereBoxCollisionAlgorithm.h - CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp - CollisionDispatch/btConvexPlaneCollisionAlgorithm.h - CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp - CollisionDispatch/btSphereTriangleCollisionAlgorithm.h CollisionDispatch/btConvexConvexAlgorithm.cpp - CollisionDispatch/btConvexConvexAlgorithm.h CollisionDispatch/btEmptyCollisionAlgorithm.cpp - CollisionDispatch/btEmptyCollisionAlgorithm.h CollisionDispatch/btManifoldResult.cpp - CollisionDispatch/btManifoldResult.h CollisionDispatch/btSimulationIslandManager.cpp - CollisionDispatch/btSimulationIslandManager.h CollisionDispatch/btUnionFind.cpp - CollisionDispatch/btUnionFind.h - CollisionDispatch/SphereTriangleDetector.cpp - CollisionDispatch/SphereTriangleDetector.h CollisionShapes/btBoxShape.cpp - CollisionShapes/btBoxShape.h CollisionShapes/btBvhTriangleMeshShape.cpp - CollisionShapes/btBvhTriangleMeshShape.h - CollisionShapes/btCapsuleShape.cpp - CollisionShapes/btCapsuleShape.h CollisionShapes/btCollisionShape.cpp - CollisionShapes/btCollisionShape.h CollisionShapes/btCompoundShape.cpp - CollisionShapes/btCompoundShape.h CollisionShapes/btConcaveShape.cpp - CollisionShapes/btConcaveShape.h CollisionShapes/btConeShape.cpp - CollisionShapes/btConeShape.h CollisionShapes/btConvexHullShape.cpp - CollisionShapes/btConvexHullShape.h CollisionShapes/btConvexShape.cpp - CollisionShapes/btConvexShape.h - CollisionShapes/btConvexInternalShape.cpp - CollisionShapes/btConvexInternalShape.h CollisionShapes/btConvexTriangleMeshShape.cpp - CollisionShapes/btConvexTriangleMeshShape.h CollisionShapes/btCylinderShape.cpp - CollisionShapes/btCylinderShape.h CollisionShapes/btEmptyShape.cpp - CollisionShapes/btEmptyShape.h - CollisionShapes/btHeightfieldTerrainShape.cpp - CollisionShapes/btHeightfieldTerrainShape.h CollisionShapes/btMinkowskiSumShape.cpp - CollisionShapes/btMinkowskiSumShape.h - CollisionShapes/btMaterial.h - CollisionShapes/btMultimaterialTriangleMeshShape.cpp - CollisionShapes/btMultimaterialTriangleMeshShape.h CollisionShapes/btMultiSphereShape.cpp - CollisionShapes/btMultiSphereShape.h CollisionShapes/btOptimizedBvh.cpp - CollisionShapes/btOptimizedBvh.h CollisionShapes/btPolyhedralConvexShape.cpp - CollisionShapes/btPolyhedralConvexShape.h - CollisionShapes/btScaledBvhTriangleMeshShape.cpp - CollisionShapes/btScaledBvhTriangleMeshShape.h CollisionShapes/btTetrahedronShape.cpp - CollisionShapes/btTetrahedronShape.h CollisionShapes/btSphereShape.cpp - CollisionShapes/btSphereShape.h - CollisionShapes/btShapeHull.h - CollisionShapes/btShapeHull.cpp CollisionShapes/btStaticPlaneShape.cpp - CollisionShapes/btStaticPlaneShape.h CollisionShapes/btStridingMeshInterface.cpp - CollisionShapes/btStridingMeshInterface.h CollisionShapes/btTriangleCallback.cpp - CollisionShapes/btTriangleCallback.h CollisionShapes/btTriangleBuffer.cpp - CollisionShapes/btTriangleBuffer.h CollisionShapes/btTriangleIndexVertexArray.cpp - CollisionShapes/btTriangleIndexVertexArray.h - CollisionShapes/btTriangleIndexVertexMaterialArray.h - CollisionShapes/btTriangleIndexVertexMaterialArray.cpp CollisionShapes/btTriangleMesh.cpp - CollisionShapes/btTriangleMesh.h CollisionShapes/btTriangleMeshShape.cpp - CollisionShapes/btTriangleMeshShape.h - CollisionShapes/btUniformScalingShape.cpp - CollisionShapes/btUniformScalingShape.h NarrowPhaseCollision/btContinuousConvexCollision.cpp - NarrowPhaseCollision/btContinuousConvexCollision.h NarrowPhaseCollision/btGjkEpa.cpp - NarrowPhaseCollision/btGjkEpa.h - NarrowPhaseCollision/btGjkEpa2.cpp - NarrowPhaseCollision/btGjkEpa2.h NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp - NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h NarrowPhaseCollision/btConvexCast.cpp - NarrowPhaseCollision/btConvexCast.h NarrowPhaseCollision/btGjkConvexCast.cpp - NarrowPhaseCollision/btGjkConvexCast.h NarrowPhaseCollision/btGjkPairDetector.cpp - NarrowPhaseCollision/btGjkPairDetector.h NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp - NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h NarrowPhaseCollision/btPersistentManifold.cpp - NarrowPhaseCollision/btPersistentManifold.h NarrowPhaseCollision/btRaycastCallback.cpp - NarrowPhaseCollision/btRaycastCallback.h NarrowPhaseCollision/btSubSimplexConvexCast.cpp - NarrowPhaseCollision/btSubSimplexConvexCast.h NarrowPhaseCollision/btVoronoiSimplexSolver.cpp - NarrowPhaseCollision/btVoronoiSimplexSolver.h ) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index f6c1e32ac7c..81133670f0c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -26,7 +26,7 @@ m_triangle(triangle) } -void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) +void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) { (void)debugDraw; @@ -42,16 +42,7 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) { - if (swapResults) - { - btVector3 normalOnB = transformB.getBasis()*normal; - btVector3 normalOnA = -normalOnB; - btVector3 pointOnA = transformB*point+normalOnB*depth; - output.addContactPoint(normalOnA,pointOnA,depth); - } else - { - output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); - } + output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); } } @@ -62,8 +53,6 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res // See also geometrictools.com // Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv -btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest); - btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { btVector3 diff = p - from; btVector3 v = to - from; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h index 26dabaa480e..b32806a6846 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_DETECTOR_H #define SPHERE_TRIANGLE_DETECTOR_H -#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "LinearMath/btPoint3.h" +#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "../../LinearMath/btPoint3.h" class btSphereShape; @@ -28,7 +28,7 @@ class btTriangleShape; /// sphere-triangle to match the btDiscreteCollisionDetectorInterface struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface { - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp deleted file mode 100644 index cd0c028012c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btBoxBoxCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "btBoxBoxDetector.h" - -#define USE_PERSISTENT_CONTACTS 1 - -btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) -: btCollisionAlgorithm(ci), -m_ownManifold(false), -m_manifoldPtr(mf) -{ - if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) - { - m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); - m_ownManifold = true; - } -} - -btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm() -{ - if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } -} - -void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - if (!m_manifoldPtr) - return; - - btCollisionObject* col0 = body0; - btCollisionObject* col1 = body1; - btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape(); - btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape(); - - - - /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); -#ifndef USE_PERSISTENT_CONTACTS - m_manifoldPtr->clearManifold(); -#endif //USE_PERSISTENT_CONTACTS - - btDiscreteCollisionDetectorInterface::ClosestPointInput input; - input.m_maximumDistanceSquared = 1e30f; - input.m_transformA = body0->getWorldTransform(); - input.m_transformB = body1->getWorldTransform(); - - btBoxBoxDetector detector(box0,box1); - detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); - -#ifdef USE_PERSISTENT_CONTACTS - // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added - if (m_ownManifold) - { - resultOut->refreshContactPoints(); - } -#endif //USE_PERSISTENT_CONTACTS - -} - -btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) -{ - //not yet - return 1.f; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h deleted file mode 100644 index 35afaf175a1..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BOX_BOX__COLLISION_ALGORITHM_H -#define BOX_BOX__COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" - -class btPersistentManifold; - -///box-box collision detection -class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - -public: - btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); - - virtual ~btBoxBoxCollisionAlgorithm(); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - { - manifoldArray.push_back(m_manifoldPtr); - } - } - - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - int bbsize = sizeof(btBoxBoxCollisionAlgorithm); - void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); - return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1); - } - }; - -}; - -#endif //BOX_BOX__COLLISION_ALGORITHM_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp deleted file mode 100644 index 45ebff5dc45..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp +++ /dev/null @@ -1,683 +0,0 @@ - -/* - * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith - * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. - * All rights reserved. Email: russ@q12.org Web: www.q12.org - Bullet Continuous Collision Detection and Physics Library - Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -///ODE box-box collision detection is adapted to work with Bullet - -#include "btBoxBoxDetector.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" - -#include -#include - -btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2) -: m_box1(box1), -m_box2(box2) -{ - -} - - -// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and -// generate contact points. this returns 0 if there is no contact otherwise -// it returns the number of contacts generated. -// `normal' returns the contact normal. -// `depth' returns the maximum penetration depth along that normal. -// `return_code' returns a number indicating the type of contact that was -// detected: -// 1,2,3 = box 2 intersects with a face of box 1 -// 4,5,6 = box 1 intersects with a face of box 2 -// 7..15 = edge-edge contact -// `maxc' is the maximum number of contacts allowed to be generated, i.e. -// the size of the `contact' array. -// `contact' and `skip' are the contact array information provided to the -// collision functions. this function only fills in the position and depth -// fields. -struct dContactGeom; -#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) -#define dInfinity FLT_MAX - - -/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } -PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); } -PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); } -PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); } -*/ -static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } -static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); } -static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); } -static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); } -#define dMULTIPLYOP1_331(A,op,B,C) \ -{\ - (A)[0] op dDOT41((B),(C)); \ - (A)[1] op dDOT41((B+1),(C)); \ - (A)[2] op dDOT41((B+2),(C)); \ -} - -#define dMULTIPLYOP0_331(A,op,B,C) \ -{ \ - (A)[0] op dDOT((B),(C)); \ - (A)[1] op dDOT((B+4),(C)); \ - (A)[2] op dDOT((B+8),(C)); \ -} - -#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) -#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) - -typedef btScalar dMatrix3[4*3]; - -void dLineClosestApproach (const btVector3& pa, const btVector3& ua, - const btVector3& pb, const btVector3& ub, - btScalar *alpha, btScalar *beta); -void dLineClosestApproach (const btVector3& pa, const btVector3& ua, - const btVector3& pb, const btVector3& ub, - btScalar *alpha, btScalar *beta) -{ - btVector3 p; - p[0] = pb[0] - pa[0]; - p[1] = pb[1] - pa[1]; - p[2] = pb[2] - pa[2]; - btScalar uaub = dDOT(ua,ub); - btScalar q1 = dDOT(ua,p); - btScalar q2 = -dDOT(ub,p); - btScalar d = 1-uaub*uaub; - if (d <= btScalar(0.0001f)) { - // @@@ this needs to be made more robust - *alpha = 0; - *beta = 0; - } - else { - d = 1.f/d; - *alpha = (q1 + uaub*q2)*d; - *beta = (uaub*q1 + q2)*d; - } -} - - - -// find all the intersection points between the 2D rectangle with vertices -// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), -// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). -// -// the intersection points are returned as x,y pairs in the 'ret' array. -// the number of intersection points is returned by the function (this will -// be in the range 0 to 8). - -static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16]) -{ - // q (and r) contain nq (and nr) coordinate points for the current (and - // chopped) polygons - int nq=4,nr=0; - btScalar buffer[16]; - btScalar *q = p; - btScalar *r = ret; - for (int dir=0; dir <= 1; dir++) { - // direction notation: xy[0] = x axis, xy[1] = y axis - for (int sign=-1; sign <= 1; sign += 2) { - // chop q along the line xy[dir] = sign*h[dir] - btScalar *pq = q; - btScalar *pr = r; - nr = 0; - for (int i=nq; i > 0; i--) { - // go through all points in q and all lines between adjacent points - if (sign*pq[dir] < h[dir]) { - // this point is inside the chopping line - pr[0] = pq[0]; - pr[1] = pq[1]; - pr += 2; - nr++; - if (nr & 8) { - q = r; - goto done; - } - } - btScalar *nextq = (i > 1) ? pq+2 : q; - if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { - // this line crosses the chopping line - pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / - (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); - pr[dir] = sign*h[dir]; - pr += 2; - nr++; - if (nr & 8) { - q = r; - goto done; - } - } - pq += 2; - } - q = r; - r = (q==ret) ? buffer : ret; - nq = nr; - } - } - done: - if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar)); - return nr; -} - - -#define M__PI 3.14159265f - -// given n points in the plane (array p, of size 2*n), generate m points that -// best represent the whole set. the definition of 'best' here is not -// predetermined - the idea is to select points that give good box-box -// collision detection behavior. the chosen point indexes are returned in the -// array iret (of size m). 'i0' is always the first entry in the array. -// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be -// in the range [0..n-1]. - -void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]); -void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) -{ - // compute the centroid of the polygon in cx,cy - int i,j; - btScalar a,cx,cy,q; - if (n==1) { - cx = p[0]; - cy = p[1]; - } - else if (n==2) { - cx = btScalar(0.5)*(p[0] + p[2]); - cy = btScalar(0.5)*(p[1] + p[3]); - } - else { - a = 0; - cx = 0; - cy = 0; - for (i=0; i<(n-1); i++) { - q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; - a += q; - cx += q*(p[i*2]+p[i*2+2]); - cy += q*(p[i*2+1]+p[i*2+3]); - } - q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; - a = 1.f/(btScalar(3.0)*(a+q)); - cx = a*(cx + q*(p[n*2-2]+p[0])); - cy = a*(cy + q*(p[n*2-1]+p[1])); - } - - // compute the angle of each point w.r.t. the centroid - btScalar A[8]; - for (i=0; i M__PI) a -= 2*M__PI; - btScalar maxdiff=1e9,diff; -#if defined(DEBUG) || defined (_DEBUG) - *iret = i0; // iret is not allowed to keep this value -#endif - for (i=0; i M__PI) diff = 2*M__PI - diff; - if (diff < maxdiff) { - maxdiff = diff; - *iret = i; - } - } - } -#if defined(DEBUG) || defined (_DEBUG) - btAssert (*iret != i0); // ensure iret got set -#endif - avail[*iret] = 0; - iret++; - } -} - - - -int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, - const btVector3& side1, const btVector3& p2, - const dMatrix3 R2, const btVector3& side2, - btVector3& normal, btScalar *depth, int *return_code, - int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output); -int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, - const btVector3& side1, const btVector3& p2, - const dMatrix3 R2, const btVector3& side2, - btVector3& normal, btScalar *depth, int *return_code, - int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output) -{ - const btScalar fudge_factor = btScalar(1.05); - btVector3 p,pp,normalC; - const btScalar *normalR = 0; - btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, - Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l; - int i,j,invert_normal,code; - - // get vector from centers of box 1 to box 2, relative to box 1 - p = p2 - p1; - dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1 - - // get side lengths / 2 - A[0] = side1[0]*btScalar(0.5); - A[1] = side1[1]*btScalar(0.5); - A[2] = side1[2]*btScalar(0.5); - B[0] = side2[0]*btScalar(0.5); - B[1] = side2[1]*btScalar(0.5); - B[2] = side2[2]*btScalar(0.5); - - // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 - R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); - R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); - R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); - - Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13); - Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23); - Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33); - - // for all 15 possible separating axes: - // * see if the axis separates the boxes. if so, return 0. - // * find the depth of the penetration along the separating axis (s2) - // * if this is the largest depth so far, record it. - // the normal vector will be set to the separating axis with the smallest - // depth. note: normalR is set to point to a column of R1 or R2 if that is - // the smallest depth normal so far. otherwise normalR is 0 and normalC is - // set to a vector relative to body 1. invert_normal is 1 if the sign of - // the normal should be flipped. - -#define TST(expr1,expr2,norm,cc) \ - s2 = btFabs(expr1) - (expr2); \ - if (s2 > 0) return 0; \ - if (s2 > s) { \ - s = s2; \ - normalR = norm; \ - invert_normal = ((expr1) < 0); \ - code = (cc); \ - } - - s = -dInfinity; - invert_normal = 0; - code = 0; - - // separating axis = u1,u2,u3 - TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); - TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); - TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); - - // separating axis = v1,v2,v3 - TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); - TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); - TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); - - // note: cross product axes need to be scaled when s is computed. - // normal (n1,n2,n3) is relative to box 1. -#undef TST -#define TST(expr1,expr2,n1,n2,n3,cc) \ - s2 = btFabs(expr1) - (expr2); \ - if (s2 > 0) return 0; \ - l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ - if (l > 0) { \ - s2 /= l; \ - if (s2*fudge_factor > s) { \ - s = s2; \ - normalR = 0; \ - normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ - invert_normal = ((expr1) < 0); \ - code = (cc); \ - } \ - } - - // separating axis = u1 x (v1,v2,v3) - TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); - TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); - TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); - - // separating axis = u2 x (v1,v2,v3) - TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); - TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); - TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); - - // separating axis = u3 x (v1,v2,v3) - TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); - TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); - TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); - -#undef TST - - if (!code) return 0; - - // if we get to this point, the boxes interpenetrate. compute the normal - // in global coordinates. - if (normalR) { - normal[0] = normalR[0]; - normal[1] = normalR[4]; - normal[2] = normalR[8]; - } - else { - dMULTIPLY0_331 (normal,R1,normalC); - } - if (invert_normal) { - normal[0] = -normal[0]; - normal[1] = -normal[1]; - normal[2] = -normal[2]; - } - *depth = -s; - - // compute contact point(s) - - if (code > 6) { - // an edge from box 1 touches an edge from box 2. - // find a point pa on the intersecting edge of box 1 - btVector3 pa; - btScalar sign; - for (i=0; i<3; i++) pa[i] = p1[i]; - for (j=0; j<3; j++) { - sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0); - for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; - } - - // find a point pb on the intersecting edge of box 2 - btVector3 pb; - for (i=0; i<3; i++) pb[i] = p2[i]; - for (j=0; j<3; j++) { - sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0); - for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; - } - - btScalar alpha,beta; - btVector3 ua,ub; - for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; - for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; - - dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); - for (i=0; i<3; i++) pa[i] += ua[i]*alpha; - for (i=0; i<3; i++) pb[i] += ub[i]*beta; - - { - - //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]); - //contact[0].depth = *depth; - btVector3 pointInWorld; - -#ifdef USE_CENTER_POINT - for (i=0; i<3; i++) - pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5); - output.addContactPoint(-normal,pointInWorld,-*depth); -#else - output.addContactPoint(-normal,pb,-*depth); -#endif // - *return_code = code; - } - return 1; - } - - // okay, we have a face-something intersection (because the separating - // axis is perpendicular to a face). define face 'a' to be the reference - // face (i.e. the normal vector is perpendicular to this) and face 'b' to be - // the incident face (the closest face of the other box). - - const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb; - if (code <= 3) { - Ra = R1; - Rb = R2; - pa = p1; - pb = p2; - Sa = A; - Sb = B; - } - else { - Ra = R2; - Rb = R1; - pa = p2; - pb = p1; - Sa = B; - Sb = A; - } - - // nr = normal vector of reference face dotted with axes of incident box. - // anr = absolute values of nr. - btVector3 normal2,nr,anr; - if (code <= 3) { - normal2[0] = normal[0]; - normal2[1] = normal[1]; - normal2[2] = normal[2]; - } - else { - normal2[0] = -normal[0]; - normal2[1] = -normal[1]; - normal2[2] = -normal[2]; - } - dMULTIPLY1_331 (nr,Rb,normal2); - anr[0] = btFabs (nr[0]); - anr[1] = btFabs (nr[1]); - anr[2] = btFabs (nr[2]); - - // find the largest compontent of anr: this corresponds to the normal - // for the indident face. the other axis numbers of the indicent face - // are stored in a1,a2. - int lanr,a1,a2; - if (anr[1] > anr[0]) { - if (anr[1] > anr[2]) { - a1 = 0; - lanr = 1; - a2 = 2; - } - else { - a1 = 0; - a2 = 1; - lanr = 2; - } - } - else { - if (anr[0] > anr[2]) { - lanr = 0; - a1 = 1; - a2 = 2; - } - else { - a1 = 0; - a2 = 1; - lanr = 2; - } - } - - // compute center point of incident face, in reference-face coordinates - btVector3 center; - if (nr[lanr] < 0) { - for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; - } - else { - for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; - } - - // find the normal and non-normal axis numbers of the reference box - int codeN,code1,code2; - if (code <= 3) codeN = code-1; else codeN = code-4; - if (codeN==0) { - code1 = 1; - code2 = 2; - } - else if (codeN==1) { - code1 = 0; - code2 = 2; - } - else { - code1 = 0; - code2 = 1; - } - - // find the four corners of the incident face, in reference-face coordinates - btScalar quad[8]; // 2D coordinate of incident face (x,y pairs) - btScalar c1,c2,m11,m12,m21,m22; - c1 = dDOT14 (center,Ra+code1); - c2 = dDOT14 (center,Ra+code2); - // optimize this? - we have already computed this data above, but it is not - // stored in an easy-to-index format. for now it's quicker just to recompute - // the four dot products. - m11 = dDOT44 (Ra+code1,Rb+a1); - m12 = dDOT44 (Ra+code1,Rb+a2); - m21 = dDOT44 (Ra+code2,Rb+a1); - m22 = dDOT44 (Ra+code2,Rb+a2); - { - btScalar k1 = m11*Sb[a1]; - btScalar k2 = m21*Sb[a1]; - btScalar k3 = m12*Sb[a2]; - btScalar k4 = m22*Sb[a2]; - quad[0] = c1 - k1 - k3; - quad[1] = c2 - k2 - k4; - quad[2] = c1 - k1 + k3; - quad[3] = c2 - k2 + k4; - quad[4] = c1 + k1 + k3; - quad[5] = c2 + k2 + k4; - quad[6] = c1 + k1 - k3; - quad[7] = c2 + k2 - k4; - } - - // find the size of the reference face - btScalar rect[2]; - rect[0] = Sa[code1]; - rect[1] = Sa[code2]; - - // intersect the incident and reference faces - btScalar ret[16]; - int n = intersectRectQuad2 (rect,quad,ret); - if (n < 1) return 0; // this should never happen - - // convert the intersection points into reference-face coordinates, - // and compute the contact position and depth for each point. only keep - // those points that have a positive (penetrating) depth. delete points in - // the 'ret' array as necessary so that 'point' and 'ret' correspond. - btScalar point[3*8]; // penetrating contact points - btScalar dep[8]; // depths for those points - btScalar det1 = 1.f/(m11*m22 - m12*m21); - m11 *= det1; - m12 *= det1; - m21 *= det1; - m22 *= det1; - int cnum = 0; // number of penetrating contact points found - for (j=0; j < n; j++) { - btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); - btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); - for (i=0; i<3; i++) point[cnum*3+i] = - center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; - dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3); - if (dep[cnum] >= 0) { - ret[cnum*2] = ret[j*2]; - ret[cnum*2+1] = ret[j*2+1]; - cnum++; - } - } - if (cnum < 1) return 0; // this should never happen - - // we can't generate more contacts than we actually have - if (maxc > cnum) maxc = cnum; - if (maxc < 1) maxc = 1; - - if (cnum <= maxc) { - // we have less contacts than we need, so we use them all - for (j=0; j < cnum; j++) { - - //AddContactPoint... - - //dContactGeom *con = CONTACT(contact,skip*j); - //for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i]; - //con->depth = dep[j]; - - btVector3 pointInWorld; - for (i=0; i<3; i++) - pointInWorld[i] = point[j*3+i] + pa[i]; - output.addContactPoint(-normal,pointInWorld,-dep[j]); - - } - } - else { - // we have more contacts than are wanted, some of them must be culled. - // find the deepest point, it is always the first contact. - int i1 = 0; - btScalar maxdepth = dep[0]; - for (i=1; i maxdepth) { - maxdepth = dep[i]; - i1 = i; - } - } - - int iret[8]; - cullPoints2 (cnum,ret,maxc,i1,iret); - - for (j=0; j < maxc; j++) { -// dContactGeom *con = CONTACT(contact,skip*j); - // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; - // con->depth = dep[iret[j]]; - - btVector3 posInWorld; - for (i=0; i<3; i++) - posInWorld[i] = point[iret[j]*3+i] + pa[i]; - output.addContactPoint(-normal,posInWorld,-dep[iret[j]]); - } - cnum = maxc; - } - - *return_code = code; - return cnum; -} - -void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/) -{ - - const btTransform& transformA = input.m_transformA; - const btTransform& transformB = input.m_transformB; - - int skip = 0; - dContactGeom *contact = 0; - - dMatrix3 R1; - dMatrix3 R2; - - for (int j=0;j<3;j++) - { - R1[0+4*j] = transformA.getBasis()[j].x(); - R2[0+4*j] = transformB.getBasis()[j].x(); - - R1[1+4*j] = transformA.getBasis()[j].y(); - R2[1+4*j] = transformB.getBasis()[j].y(); - - - R1[2+4*j] = transformA.getBasis()[j].z(); - R2[2+4*j] = transformB.getBasis()[j].z(); - - } - - - - btVector3 normal; - btScalar depth; - int return_code; - int maxc = 4; - - - dBoxBox2 (transformA.getOrigin(), - R1, - 2.f*m_box1->getHalfExtentsWithMargin(), - transformB.getOrigin(), - R2, - 2.f*m_box2->getHalfExtentsWithMargin(), - normal, &depth, &return_code, - maxc, contact, skip, - output - ); - -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h deleted file mode 100644 index 605294d47bd..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith - * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. - * All rights reserved. Email: russ@q12.org Web: www.q12.org - -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -#ifndef BOX_BOX_DETECTOR_H -#define BOX_BOX_DETECTOR_H - - -class btBoxShape; -#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" - - -/// btBoxBoxDetector wraps the ODE box-box collision detector -/// re-distributed under the Zlib license with permission from Russell L. Smith -struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface -{ - btBoxShape* m_box1; - btBoxShape* m_box2; - -public: - - btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2); - - virtual ~btBoxBoxDetector() {}; - - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); - -}; - -#endif //BT_BOX_BOX_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h deleted file mode 100644 index fad770ac26d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_COLLISION_CONFIGURATION -#define BT_COLLISION_CONFIGURATION -struct btCollisionAlgorithmCreateFunc; - -class btStackAlloc; -class btPoolAllocator; - -///btCollisionConfiguration allows to configure Bullet collision detection -///stack allocator size, default collision algorithms and persistent manifold pool size -///todo: describe the meaning -class btCollisionConfiguration -{ - -public: - - virtual ~btCollisionConfiguration() - { - } - - ///memory pools - virtual btPoolAllocator* getPersistentManifoldPool() = 0; - - virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; - - virtual btStackAlloc* getStackAllocator() = 0; - - virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; - -}; - -#endif //BT_COLLISION_CONFIGURATION - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h index c6728918d16..d51a59af7f0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_CREATE_FUNC #define COLLISION_CREATE_FUNC -#include "LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btAlignedObjectArray.h" typedef btAlignedObjectArray btCollisionObjectArray; class btCollisionAlgorithm; class btCollisionObject; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index a031a9f9784..b535fac6563 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -19,39 +19,69 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" - +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" -#include "LinearMath/btPoolAllocator.h" -#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" int gNumManifold = 0; -#ifdef BT_DEBUG #include -#endif + +btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms): +m_count(0), +m_useIslands(true), +m_convexConvexCreateFunc(0), +m_convexConcaveCreateFunc(0), +m_swappedConvexConcaveCreateFunc(0), +m_compoundCreateFunc(0), +m_swappedCompoundCreateFunc(0), +m_emptyCreateFunc(0) +{ + (void)noDefaultAlgorithms; + int i; -btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): + setNearCallback(defaultNearCallback); + + m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc; + for (i=0;igetCollisionAlgorithmPool(); - - m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); + //default CreationFunctions, filling the m_doubleDispatch table + m_convexConvexCreateFunc = new btConvexConvexAlgorithm::CreateFunc; + m_convexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::CreateFunc; + m_swappedConvexConcaveCreateFunc = new btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; + m_compoundCreateFunc = new btCompoundCollisionAlgorithm::CreateFunc; + m_swappedCompoundCreateFunc = new btCompoundCollisionAlgorithm::SwappedCreateFunc; + m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc; for (i=0;igetCollisionAlgorithmCreateFunc(i,j); + m_doubleDispatch[i][j] = internalFindCreateFunc(i,j); assert(m_doubleDispatch[i][j]); } } @@ -59,6 +89,8 @@ btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisio }; +#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION + void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) { @@ -67,6 +99,12 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox btCollisionDispatcher::~btCollisionDispatcher() { + delete m_convexConvexCreateFunc; + delete m_convexConcaveCreateFunc; + delete m_swappedConvexConcaveCreateFunc; + delete m_compoundCreateFunc; + delete m_swappedCompoundCreateFunc; + delete m_emptyCreateFunc; } btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) @@ -79,18 +117,7 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) btCollisionObject* body0 = (btCollisionObject*)b0; btCollisionObject* body1 = (btCollisionObject*)b1; - void* mem = 0; - - if (m_persistentManifoldPoolAllocator->getFreeCount()) - { - mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); - } else - { - mem = btAlignedAlloc(sizeof(btPersistentManifold),16); - - } - btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); - manifold->m_index1a = m_manifoldsPtr.size(); + btPersistentManifold* manifold = new btPersistentManifold (body0,body1); m_manifoldsPtr.push_back(manifold); return manifold; @@ -110,19 +137,13 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) //printf("releaseManifold: gNumManifold %d\n",gNumManifold); clearManifold(manifold); - int findIndex = manifold->m_index1a; - btAssert(findIndex < m_manifoldsPtr.size()); - m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); - m_manifoldsPtr[findIndex]->m_index1a = findIndex; - m_manifoldsPtr.pop_back(); - - manifold->~btPersistentManifold(); - if (m_persistentManifoldPoolAllocator->validPtr(manifold)) + ///todo: this can be improved a lot, linear search might be slow part! + int findIndex = m_manifoldsPtr.findLinearSearch(manifold); + if (findIndex < m_manifoldsPtr.size()) { - m_persistentManifoldPoolAllocator->freeMemory(manifold); - } else - { - btAlignedFree(manifold); + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr.pop_back(); + delete manifold; } } @@ -131,19 +152,99 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) { + +#ifdef USE_DISPATCH_REGISTRY_ARRAY btCollisionAlgorithmConstructionInfo ci; - - ci.m_dispatcher1 = this; + ci.m_dispatcher = this; ci.m_manifold = sharedManifold; - btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); - + btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()] + ->CreateCollisionAlgorithm(ci,body0,body1); +#else + btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1); +#endif //USE_DISPATCH_REGISTRY_ARRAY return algo; } +#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION + +btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1) +{ + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} + +#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION +#ifndef USE_DISPATCH_REGISTRY_ARRAY + +btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) +{ + m_count++; + + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher = this; + + if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() ) + { + return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1); + } + + if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave()) + { + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + } + + if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave()) + { + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + } + + if (body0->getCollisionShape()->isCompound()) + { + return new btCompoundCollisionAlgorithm(ci,body0,body1,false); + } else + { + if (body1->getCollisionShape()->isCompound()) + { + return new btCompoundCollisionAlgorithm(ci,body0,body1,true); + } + } + + //failed to find an algorithm + return new btEmptyAlgorithm(ci); + +} +#endif //USE_DISPATCH_REGISTRY_ARRAY bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) { @@ -163,19 +264,13 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO bool needsCollision = true; -#ifdef BT_DEBUG - if (!m_staticWarningReported) + //broadphase filtering already deals with this + if ((body0->isStaticObject() || body0->isKinematicObject()) && + (body1->isStaticObject() || body1->isKinematicObject())) { - //broadphase filtering already deals with this - if ((body0->isStaticObject() || body0->isKinematicObject()) && - (body1->isStaticObject() || body1->isKinematicObject())) - { - m_staticWarningReported = true; - printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); - } + printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); } -#endif //BT_DEBUG - + if ((!body0->isActive()) && (!body1->isActive())) needsCollision = false; else if (!body0->checkCollideWith(body1)) @@ -191,25 +286,23 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO ///this is useful for the collision dispatcher. class btCollisionPairCallback : public btOverlapCallback { - const btDispatcherInfo& m_dispatchInfo; + btDispatcherInfo& m_dispatchInfo; btCollisionDispatcher* m_dispatcher; public: - btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) :m_dispatchInfo(dispatchInfo), m_dispatcher(dispatcher) { } - /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) + btCollisionPairCallback& operator=(btCollisionPairCallback& other) { m_dispatchInfo = other.m_dispatchInfo; m_dispatcher = other.m_dispatcher; return *this; } - */ - virtual ~btCollisionPairCallback() {} @@ -223,14 +316,13 @@ public: }; - -void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo) { //m_blockedForChanges = true; btCollisionPairCallback collisionCallback(dispatchInfo,this); - pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); + pairCache->processAllOverlappingPairs(&collisionCallback); //m_blockedForChanges = false; @@ -240,7 +332,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa //by default, Bullet will use this near callback -void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; @@ -273,26 +365,3 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, } } - - -void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) -{ - if (m_collisionAlgorithmPoolAllocator->getFreeCount()) - { - return m_collisionAlgorithmPoolAllocator->allocate(size); - } - - //warn user for overflow? - return btAlignedAlloc(static_cast(size), 16); -} - -void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) -{ - if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) - { - m_collisionAlgorithmPoolAllocator->freeMemory(ptr); - } else - { - btAlignedFree(ptr); - } -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index a9c9cd414c1..ca5aba8f01c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -16,18 +16,17 @@ subject to the following restrictions: #ifndef COLLISION__DISPATCHER_H #define COLLISION__DISPATCHER_H -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "../BroadphaseCollision/btDispatcher.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "../CollisionDispatch/btManifoldResult.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "LinearMath/btAlignedObjectArray.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../../LinearMath/btAlignedObjectArray.h" class btIDebugDraw; class btOverlappingPairCache; -class btPoolAllocator; -class btCollisionConfiguration; + #include "btCollisionCreateFunc.h" @@ -35,7 +34,7 @@ class btCollisionConfiguration; class btCollisionDispatcher; ///user can override this nearcallback for collision filtering and more finegrained control over collision detection -typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. @@ -47,22 +46,26 @@ class btCollisionDispatcher : public btDispatcher btAlignedObjectArray m_manifoldsPtr; bool m_useIslands; - - bool m_staticWarningReported; btManifoldResult m_defaultManifoldResult; btNearCallback m_nearCallback; - btPoolAllocator* m_collisionAlgorithmPoolAllocator; - - btPoolAllocator* m_persistentManifoldPoolAllocator; - btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; + btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1); - btCollisionConfiguration* m_collisionConfiguration; + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; +#ifndef USE_DISPATCH_REGISTRY_ARRAY + btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); +#endif //USE_DISPATCH_REGISTRY_ARRAY public: @@ -89,7 +92,11 @@ public: return m_manifoldsPtr[index]; } - btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); + ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support + btCollisionDispatcher (); + + ///a special constructor that doesn't create/register the default collision algorithms + btCollisionDispatcher(bool noDefaultAlgorithms); virtual ~btCollisionDispatcher(); @@ -107,7 +114,7 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo); void setNearCallback(btNearCallback nearCallback) { @@ -120,26 +127,7 @@ public: } //by default, Bullet will use this near callback - static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); - - virtual void* allocateCollisionAlgorithm(int size); - - virtual void freeCollisionAlgorithm(void* ptr); - - btCollisionConfiguration* getCollisionConfiguration() - { - return m_collisionConfiguration; - } - - const btCollisionConfiguration* getCollisionConfiguration() const - { - return m_collisionConfiguration; - } - - void setCollisionConfiguration(btCollisionConfiguration* config) - { - m_collisionConfiguration = config; - } + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp index eebd0c99fcb..d4c0a4e8cb3 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -13,25 +13,18 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ - #include "btCollisionObject.h" btCollisionObject::btCollisionObject() : m_broadphaseHandle(0), m_collisionShape(0), - m_rootCollisionShape(0), - m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), - m_islandTag1(-1), - m_companionId(-1), + m_collisionFlags(0), m_activationState1(1), m_deactivationTime(btScalar(0.)), - m_friction(btScalar(0.5)), - m_restitution(btScalar(0.)), m_userObjectPointer(0), - m_internalType(CO_COLLISION_OBJECT), m_hitFraction(btScalar(1.)), m_ccdSweptSphereRadius(btScalar(0.)), - m_ccdMotionThreshold(btScalar(0.)), + m_ccdSquareMotionThreshold(btScalar(0.)), m_checkCollideWith(false) { @@ -62,4 +55,3 @@ void btCollisionObject::activate(bool forceActivation) } - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index eb297ef4a3b..9fb6a67c4a3 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_OBJECT_H #define COLLISION_OBJECT_H -#include "LinearMath/btTransform.h" +#include "../../LinearMath/btTransform.h" //island management, m_activationState1 #define ACTIVE_TAG 1 @@ -27,8 +27,7 @@ subject to the following restrictions: struct btBroadphaseProxy; class btCollisionShape; -#include "LinearMath/btMotionState.h" -#include "LinearMath/btAlignedAllocator.h" +#include "../../LinearMath/btMotionState.h" @@ -51,11 +50,6 @@ protected: btVector3 m_interpolationAngularVelocity; btBroadphaseProxy* m_broadphaseHandle; btCollisionShape* m_collisionShape; - - ///m_rootCollisionShape is temporarily used to store the original collision shape - ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes - ///If it is NULL, the m_collisionShape is not temporarily replaced. - btCollisionShape* m_rootCollisionShape; int m_collisionFlags; @@ -71,9 +65,8 @@ protected: ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer void* m_userObjectPointer; - ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc. - ///do not assign your own m_internalType unless you write a new dynamics object class. - int m_internalType; + ///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead. + void* m_internalOwner; ///time of impact calculation btScalar m_hitFraction; @@ -81,23 +74,21 @@ protected: ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: btScalar m_ccdSweptSphereRadius; - /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold - btScalar m_ccdMotionThreshold; + /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold + btScalar m_ccdSquareMotionThreshold; /// If some object should have elaborate collision filtering by sub-classes bool m_checkCollideWith; char m_pad[7]; - virtual bool checkCollideWithOverride(btCollisionObject* /* co */) + virtual bool checkCollideWithOverride(btCollisionObject* co) { return true; } public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - enum CollisionFlags { CF_STATIC_OBJECT= 1, @@ -106,35 +97,29 @@ public: CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) }; - enum CollisionObjectTypes - { - CO_COLLISION_OBJECT =1, - CO_RIGID_BODY, - CO_SOFT_BODY - }; - SIMD_FORCE_INLINE bool mergesSimulationIslands() const + inline bool mergesSimulationIslands() const { ///static objects, kinematic and object without contact response don't merge islands return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); } - SIMD_FORCE_INLINE bool isStaticObject() const { + inline bool isStaticObject() const { return (m_collisionFlags & CF_STATIC_OBJECT) != 0; } - SIMD_FORCE_INLINE bool isKinematicObject() const + inline bool isKinematicObject() const { return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; } - SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const + inline bool isStaticOrKinematicObject() const { return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; } - SIMD_FORCE_INLINE bool hasContactResponse() const { + inline bool hasContactResponse() const { return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; } @@ -146,35 +131,20 @@ public: void setCollisionShape(btCollisionShape* collisionShape) { m_collisionShape = collisionShape; - m_rootCollisionShape = collisionShape; } - SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const + const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() + btCollisionShape* getCollisionShape() { return m_collisionShape; } - SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const - { - return m_rootCollisionShape; - } + - SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape() - { - return m_rootCollisionShape; - } - - ///Avoid using this internal API call - ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape. - void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape) - { - m_collisionShape = collisionShape; - } int getActivationState() const { return m_activationState1;} @@ -216,9 +186,14 @@ public: } ///reserved for Bullet internal usage - int getInternalType() const + void* getInternalOwner() { - return m_internalType; + return m_internalOwner; + } + + const void* getInternalOwner() const + { + return m_internalOwner; } btTransform& getWorldTransform() @@ -332,22 +307,16 @@ public: m_ccdSweptSphereRadius = radius; } - btScalar getCcdMotionThreshold() const - { - return m_ccdMotionThreshold; - } - btScalar getCcdSquareMotionThreshold() const { - return m_ccdMotionThreshold*m_ccdMotionThreshold; + return m_ccdSquareMotionThreshold; } - - /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold - void setCcdMotionThreshold(btScalar ccdMotionThreshold) + /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold + void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold) { - m_ccdMotionThreshold = ccdMotionThreshold*ccdMotionThreshold; + m_ccdSquareMotionThreshold = ccdSquareMotionThreshold; } ///users can point to their objects, userPointer is not used by Bullet @@ -362,7 +331,6 @@ public: m_userObjectPointer = userPointer; } - inline bool checkCollideWith(btCollisionObject* co) { if (m_checkCollideWith) @@ -370,6 +338,9 @@ public: return true; } -}; + + +} +; #endif //COLLISION_OBJECT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index d8674a320a7..b49036a5b50 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -4,8 +4,8 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. @@ -18,57 +18,59 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" + #include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting +#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" - #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "LinearMath/btAabbUtil2.h" #include "LinearMath/btQuickprof.h" #include "LinearMath/btStackAlloc.h" - //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" -btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize) :m_dispatcher1(dispatcher), m_broadphasePairCache(pairCache), -m_debugDrawer(0) +m_ownsDispatcher(false), +m_ownsBroadphasePairCache(false) { - m_stackAlloc = collisionConfiguration->getStackAllocator(); + m_stackAlloc = new btStackAlloc(stackSize); m_dispatchInfo.m_stackAllocator = m_stackAlloc; } btCollisionWorld::~btCollisionWorld() { + m_stackAlloc->destroy(); + delete m_stackAlloc; //clean up remaining objects int i; for (i=0;igetBroadphaseHandle(); if (bp) { // // only clear the cached algorithms // - getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); - getBroadphase()->destroyProxy(bp,m_dispatcher1); + getBroadphase()->cleanProxyFromPairs(bp); + getBroadphase()->destroyProxy(bp); } } + if (m_ownsDispatcher) + delete m_dispatcher1; + if (m_ownsBroadphasePairCache) + delete m_broadphasePairCache; } @@ -103,105 +105,66 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho type, collisionObject, collisionFilterGroup, - collisionFilterMask, - m_dispatcher1,0 + collisionFilterMask )) ; - + } -void btCollisionWorld::updateAabbs() -{ - BT_PROFILE("updateAabbs"); - - btTransform predictedTrans; - for ( int i=0;iisActive()) - { - btPoint3 minAabb,maxAabb; - colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); - //need to increase the aabb for contact thresholds - btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); - minAabb -= contactThreshold; - maxAabb += contactThreshold; - - btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; - - //moving objects should be moderately sized, probably something wrong if not - if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) - { - bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); - } else - { - //something went wrong, investigate - //this assert is unwanted in 3D modelers (danger of loosing work) - colObj->setActivationState(DISABLE_SIMULATION); - - static bool reportMe = true; - if (reportMe && m_debugDrawer) - { - reportMe = false; - m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); - m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); - m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); - m_debugDrawer->reportErrorWarning("Thanks.\n"); - } - } - } - } - -} void btCollisionWorld::performDiscreteCollisionDetection() { - BT_PROFILE("performDiscreteCollisionDetection"); - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - updateAabbs(); + BEGIN_PROFILE("perform Broadphase Collision Detection"); + + //update aabb (of all moved objects) + + btVector3 aabbMin,aabbMax; + for (int i=0;icalculateOverlappingPairs(m_dispatcher1); + m_collisionObjects[i]->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); + m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); } + m_broadphasePairCache->refreshOverlappingPairs(); + + + END_PROFILE("perform Broadphase Collision Detection"); + + BEGIN_PROFILE("performDiscreteCollisionDetection"); btDispatcher* dispatcher = getDispatcher(); - { - BT_PROFILE("dispatchAllCollisionPairs"); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - } + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); + + END_PROFILE("performDiscreteCollisionDetection"); } - void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) { - - + + //bool removeFromBroadphase = false; - + { - + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); if (bp) { // // only clear the cached algorithms // - getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); - getBroadphase()->destroyProxy(bp,m_dispatcher1); + getBroadphase()->cleanProxyFromPairs(bp); + getBroadphase()->destroyProxy(bp); collisionObject->setBroadphaseHandle(0); } } @@ -218,412 +181,172 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback) + RayResultCallback& resultCallback,short int collisionFilterMask) { + btSphereShape pointShape(btScalar(0.0)); pointShape.setMargin(0.f); - const btConvexShape* castShape = &pointShape; - if (collisionShape->isConvex()) - { - btConvexCast::CastResult castResult; - castResult.m_fraction = resultCallback.m_closestHitFraction; - - btConvexShape* convexShape = (btConvexShape*) collisionShape; - btVoronoiSimplexSolver simplexSolver; -#define USE_SUBSIMPLEX_CONVEX_CAST 1 -#ifdef USE_SUBSIMPLEX_CONVEX_CAST - btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); -#else - //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); -#endif //#USE_SUBSIMPLEX_CONVEX_CAST - - if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) - { - //add hit - if (castResult.m_normal.length2() > btScalar(0.0001)) - { - if (castResult.m_fraction < resultCallback.m_closestHitFraction) - { -#ifdef USE_SUBSIMPLEX_CONVEX_CAST - //rotate normal into worldspace - castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; -#endif //USE_SUBSIMPLEX_CONVEX_CAST - - castResult.m_normal.normalize(); - btCollisionWorld::LocalRayResult localRayResult - ( - collisionObject, - 0, - castResult.m_normal, - castResult.m_fraction - ); - - bool normalInWorldSpace = true; - resultCallback.addSingleResult(localRayResult, normalInWorldSpace); - - } - } - } - } else { - if (collisionShape->isConcave()) - { - if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) - { - ///optimized version for btBvhTriangleMeshShape - btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); - btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); - btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); - - //ConvexCast::CastResult - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback - { - btCollisionWorld::RayResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, - btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } - - - virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - - btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitFraction); - - bool normalInWorldSpace = false; - return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); - } - - }; - - BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); - rcb.m_hitFraction = resultCallback.m_closestHitFraction; - triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); - } else - { - btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; - - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); - - btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); - btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); - - //ConvexCast::CastResult - - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback - { - btCollisionWorld::RayResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, - btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } - - - virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - - btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitFraction); - - bool normalInWorldSpace = false; - return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); - - - } - - }; - - - BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); - rcb.m_hitFraction = resultCallback.m_closestHitFraction; - - btVector3 rayAabbMinLocal = rayFromLocal; - rayAabbMinLocal.setMin(rayToLocal); - btVector3 rayAabbMaxLocal = rayFromLocal; - rayAabbMaxLocal.setMax(rayToLocal); - - triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); - } - } else { - //todo: use AABB tree or other BVH acceleration structure! - if (collisionShape->isCompound()) - { - const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - // replace collision shape so that callback can determine the triangle - btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); - collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); - rayTestSingle(rayFromTrans,rayToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback); - // restore - collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); - } - } - } - } + objectQuerySingle(&pointShape,rayFromTrans,rayToTrans, + collisionObject, + collisionShape, + colObjWorldTransform, + resultCallback,collisionFilterMask); } -void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, +void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - ConvexResultCallback& resultCallback, btScalar allowedPenetration) + RayResultCallback& resultCallback,short int collisionFilterMask) { + + if (collisionShape->isConvex()) - { - btConvexCast::CastResult castResult; - castResult.m_allowedPenetration = allowedPenetration; - castResult.m_fraction = btScalar(1.);//?? - - btConvexShape* convexShape = (btConvexShape*) collisionShape; - btVoronoiSimplexSolver simplexSolver; - btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; - - btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); - //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); - //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); - - btConvexCast* castPtr = &convexCaster1; - - - - if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) - { - //add hit - if (castResult.m_normal.length2() > btScalar(0.0001)) { - if (castResult.m_fraction < resultCallback.m_closestHitFraction) + btConvexCast::CastResult castResult; + castResult.m_fraction = btScalar(1.);//?? + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) { - castResult.m_normal.normalize(); - btCollisionWorld::LocalConvexResult localConvexResult + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + castResult.m_normal.normalize(); + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { + + btCollisionWorld::LocalRayResult localRayResult ( - collisionObject, + collisionObject, 0, castResult.m_normal, - castResult.m_hitPoint, castResult.m_fraction ); - bool normalInWorldSpace = true; - resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); + resultCallback.AddSingleResult(localRayResult); + } + } } } - } - } else { - if (collisionShape->isConcave()) - { - if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + else { - btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); - btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); - btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); - // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation - btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); - - //ConvexCast::CastResult - struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback - { - btCollisionWorld::ConvexResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, - btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): - btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } - - - virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + + if (collisionShape->isConcave()) { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - if (hitFraction <= m_resultCallback->m_closestHitFraction) + + btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; - btCollisionWorld::LocalConvexResult convexResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitPointLocal, - hitFraction); - - bool normalInWorldSpace = true; + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): + btTriangleRaycastCallback(from,to), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } - return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); - } - return hitFraction; - } - - }; - - BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); - tccb.m_hitFraction = resultCallback.m_closestHitFraction; - btVector3 boxMinLocal, boxMaxLocal; - castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); - triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); - } else - { - btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); - btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); - btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); - // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation - btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); - - //ConvexCast::CastResult - struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback - { - btCollisionWorld::ConvexResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, - btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): - btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitFraction); + + return m_resultCallback->AddSingleResult(rayResult); + + + } + + }; - virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + + btVector3 rayAabbMinLocal = rayFromLocal; + rayAabbMinLocal.setMin(rayToLocal); + btVector3 rayAabbMaxLocal = rayFromLocal; + rayAabbMaxLocal.setMax(rayToLocal); + + triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + + } else { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - if (hitFraction <= m_resultCallback->m_closestHitFraction) + //todo: use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) { + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + objectQuerySingle(castShape, rayFromTrans,rayToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback, collisionFilterMask); - btCollisionWorld::LocalConvexResult convexResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitPointLocal, - hitFraction); + } - bool normalInWorldSpace = false; - return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); } - return hitFraction; } - - }; - - BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); - tccb.m_hitFraction = resultCallback.m_closestHitFraction; - btVector3 boxMinLocal, boxMaxLocal; - castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); - - btVector3 rayAabbMinLocal = convexFromLocal; - rayAabbMinLocal.setMin(convexToLocal); - btVector3 rayAabbMaxLocal = convexFromLocal; - rayAabbMaxLocal.setMax(convexToLocal); - rayAabbMinLocal += boxMinLocal; - rayAabbMaxLocal += boxMaxLocal; - triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); } - } else { - //todo: use AABB tree or other BVH acceleration structure! - if (collisionShape->isCompound()) - { - const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - // replace collision shape so that callback can determine the triangle - btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); - collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); - objectQuerySingle(castShape, convexFromTrans,convexToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback, allowedPenetration); - // restore - collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); - } - } - } - } } -void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) { - + btTransform rayFromTrans,rayToTrans; rayFromTrans.setIdentity(); rayFromTrans.setOrigin(rayFromWorld); rayToTrans.setIdentity(); - + rayToTrans.setOrigin(rayToWorld); /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) - + int i; for (i=0;igetBroadphaseHandle())) { + if(collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); btVector3 collisionObjectAabbMin,collisionObjectAabbMax; collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); - btScalar hitLambda = resultCallback.m_closestHitFraction; + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing btVector3 hitNormal; if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) { @@ -632,52 +355,7 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r collisionObject->getCollisionShape(), collisionObject->getWorldTransform(), resultCallback); - } - } - - } - -} - -void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const -{ - btTransform convexFromTrans,convexToTrans; - convexFromTrans = convexFromWorld; - convexToTrans = convexToWorld; - btVector3 castShapeAabbMin, castShapeAabbMax; - /* Compute AABB that encompasses angular movement */ - { - btVector3 linVel, angVel; - btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); - btTransform R; - R.setIdentity (); - R.setRotation (convexFromTrans.getRotation()); - castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); - } - - /// go over all objects, and if the ray intersects their aabb + cast shape aabb, - // do a ray-shape query using convexCaster (CCD) - int i; - for (i=0;igetBroadphaseHandle())) { - //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); - btVector3 collisionObjectAabbMin,collisionObjectAabbMax; - collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); - AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); - btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing - btVector3 hitNormal; - if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) - { - objectQuerySingle(castShape, convexFromTrans,convexToTrans, - collisionObject, - collisionObject->getCollisionShape(), - collisionObject->getWorldTransform(), - resultCallback, - getDispatchInfo().m_allowedCcdPenetration); - } + } } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index 7557691a9a9..b6d80233ab7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -68,12 +68,12 @@ class btStackAlloc; class btCollisionShape; class btConvexShape; class btBroadphaseInterface; -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" #include "btCollisionObject.h" #include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray -#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" -#include "LinearMath/btAlignedObjectArray.h" +#include "../BroadphaseCollision/btOverlappingPairCache.h" +#include "../../LinearMath/btAlignedObjectArray.h" ///CollisionWorld is interface and container for the collision detection class btCollisionWorld @@ -90,22 +90,18 @@ protected: btStackAlloc* m_stackAlloc; - btBroadphaseInterface* m_broadphasePairCache; - - btIDebugDraw* m_debugDrawer; - + btOverlappingPairCache* m_broadphasePairCache; + bool m_ownsDispatcher; + bool m_ownsBroadphasePairCache; + public: //this constructor doesn't own the dispatcher and paircache/broadphase - btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); + btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); virtual ~btCollisionWorld(); - void setBroadphase(btBroadphaseInterface* pairCache) - { - m_broadphasePairCache = pairCache; - } btBroadphaseInterface* getBroadphase() { @@ -114,7 +110,7 @@ public: btOverlappingPairCache* getPairCache() { - return m_broadphasePairCache->getOverlappingPairCache(); + return m_broadphasePairCache; } @@ -123,24 +119,6 @@ public: return m_dispatcher1; } - const btDispatcher* getDispatcher() const - { - return m_dispatcher1; - } - - virtual void updateAabbs(); - - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - } - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } - - ///LocalShapeInfo gives extra information for complex shapes ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart struct LocalShapeInfo @@ -175,43 +153,28 @@ public: ///RayResultCallback is used to report new raycast results struct RayResultCallback { - btScalar m_closestHitFraction; - btCollisionObject* m_collisionObject; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; - virtual ~RayResultCallback() { } - bool hasHit() const + btScalar m_closestHitFraction; + bool HasHit() { - return (m_collisionObject != 0); + return (m_closestHitFraction < btScalar(1.)); } RayResultCallback() - :m_closestHitFraction(btScalar(1.)), - m_collisionObject(0), - m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), - m_collisionFilterMask(btBroadphaseProxy::AllFilter) + :m_closestHitFraction(btScalar(1.)) { } - - virtual bool needsCollision(btBroadphaseProxy* proxy0) const - { - bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; - collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); - return collides; - } - - - virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; + virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0; }; struct ClosestRayResultCallback : public RayResultCallback { ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) :m_rayFromWorld(rayFromWorld), - m_rayToWorld(rayToWorld) + m_rayToWorld(rayToWorld), + m_collisionObject(0) { } @@ -220,121 +183,24 @@ public: btVector3 m_hitNormalWorld; btVector3 m_hitPointWorld; - - virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) + btCollisionObject* m_collisionObject; + + virtual btScalar AddSingleResult(LocalRayResult& rayResult) { - //caller already does the filter on the m_closestHitFraction - btAssert(rayResult.m_hitFraction <= m_closestHitFraction); + +//caller already does the filter on the m_closestHitFraction + assert(rayResult.m_hitFraction <= m_closestHitFraction); m_closestHitFraction = rayResult.m_hitFraction; m_collisionObject = rayResult.m_collisionObject; - if (normalInWorldSpace) - { - m_hitNormalWorld = rayResult.m_hitNormalLocal; - } else - { - ///need to transform normal into worldspace - m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; - } + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); return rayResult.m_hitFraction; } }; - struct LocalConvexResult - { - LocalConvexResult(btCollisionObject* hitCollisionObject, - LocalShapeInfo* localShapeInfo, - const btVector3& hitNormalLocal, - const btVector3& hitPointLocal, - btScalar hitFraction - ) - :m_hitCollisionObject(hitCollisionObject), - m_localShapeInfo(localShapeInfo), - m_hitNormalLocal(hitNormalLocal), - m_hitPointLocal(hitPointLocal), - m_hitFraction(hitFraction) - { - } - - btCollisionObject* m_hitCollisionObject; - LocalShapeInfo* m_localShapeInfo; - btVector3 m_hitNormalLocal; - btVector3 m_hitPointLocal; - btScalar m_hitFraction; - }; - - ///RayResultCallback is used to report new raycast results - struct ConvexResultCallback - { - btScalar m_closestHitFraction; - short int m_collisionFilterGroup; - short int m_collisionFilterMask; - - ConvexResultCallback() - :m_closestHitFraction(btScalar(1.)), - m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), - m_collisionFilterMask(btBroadphaseProxy::AllFilter) - { - } - - virtual ~ConvexResultCallback() - { - } - - bool hasHit() const - { - return (m_closestHitFraction < btScalar(1.)); - } - - - - virtual bool needsCollision(btBroadphaseProxy* proxy0) const - { - bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; - collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); - return collides; - } - - virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0; - }; - - struct ClosestConvexResultCallback : public ConvexResultCallback - { - ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld) - :m_convexFromWorld(convexFromWorld), - m_convexToWorld(convexToWorld), - m_hitCollisionObject(0) - { - } - - btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction - btVector3 m_convexToWorld; - - btVector3 m_hitNormalWorld; - btVector3 m_hitPointWorld; - btCollisionObject* m_hitCollisionObject; - - virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) - { -//caller already does the filter on the m_closestHitFraction - btAssert(convexResult.m_hitFraction <= m_closestHitFraction); - - m_closestHitFraction = convexResult.m_hitFraction; - m_hitCollisionObject = convexResult.m_hitCollisionObject; - if (normalInWorldSpace) - { - m_hitNormalWorld = convexResult.m_hitNormalLocal; - } else - { - ///need to transform normal into worldspace - m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; - } - m_hitPointWorld = convexResult.m_hitPointLocal; - return convexResult.m_hitFraction; - } - }; + int getNumCollisionObjects() const { @@ -343,12 +209,7 @@ public: /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. - void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; - - // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback - // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. - void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback) const; - + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. @@ -357,16 +218,16 @@ public: btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback); + RayResultCallback& resultCallback, short int collisionFilterMask=-1); /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - ConvexResultCallback& resultCallback, btScalar allowedPenetration); + RayResultCallback& resultCallback, short int collisionFilterMask=-1); - void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); + void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); btCollisionObjectArray& getCollisionObjectArray() { @@ -388,11 +249,6 @@ public: return m_dispatchInfo; } - const btDispatcherInfo& getDispatchInfo() const - { - return m_dispatchInfo; - } - }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 57812818007..92f4c8b28a6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -16,17 +16,11 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" -#include "BulletCollision/BroadphaseCollision/btDbvt.h" -#include "LinearMath/btIDebugDraw.h" -#include "LinearMath/btAabbUtil2.h" + btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -:btCollisionAlgorithm(ci), -m_isSwapped(isSwapped), -m_sharedManifold(ci.m_manifold) +:m_isSwapped(isSwapped) { - m_ownsManifold = false; - btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; assert (colObj->getCollisionShape()->isCompound()); @@ -38,17 +32,11 @@ m_sharedManifold(ci.m_manifold) m_childCollisionAlgorithms.resize(numChildren); for (i=0;igetDynamicAabbTree()) - { - m_childCollisionAlgorithms[i] = 0; - } else - { - btCollisionShape* tmpShape = colObj->getCollisionShape(); - btCollisionShape* childShape = compoundShape->getChildShape(i); - colObj->internalSetTemporaryCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold); - colObj->internalSetTemporaryCollisionShape( tmpShape ); - } + btCollisionShape* childShape = compoundShape->getChildShape(i); + btCollisionShape* orgShape = colObj->getCollisionShape(); + colObj->setCollisionShape( childShape ); + m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj); + colObj->setCollisionShape( orgShape ); } } @@ -59,109 +47,10 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() int i; for (i=0;i~btCollisionAlgorithm(); - m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); - } + delete m_childCollisionAlgorithms[i]; } } - - - -struct btCompoundLeafCallback : btDbvt::ICollide -{ - -public: - - btCollisionObject* m_compoundColObj; - btCollisionObject* m_otherObj; - btDispatcher* m_dispatcher; - const btDispatcherInfo& m_dispatchInfo; - btManifoldResult* m_resultOut; - btCollisionAlgorithm** m_childCollisionAlgorithms; - btPersistentManifold* m_sharedManifold; - - - - - btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold) - :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), - m_childCollisionAlgorithms(childCollisionAlgorithms), - m_sharedManifold(sharedManifold) - { - - } - - - void ProcessChildShape(btCollisionShape* childShape,int index) - { - - btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); - - - //backup - btTransform orgTrans = m_compoundColObj->getWorldTransform(); - btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform(); - const btTransform& childTrans = compoundShape->getChildTransform(index); - btTransform newChildWorldTrans = orgTrans*childTrans ; - - //perform an AABB check first - btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; - childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); - m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1); - - if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) - { - - m_compoundColObj->setWorldTransform( newChildWorldTrans); - m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans); - - //the contactpoint is still projected back using the original inverted worldtrans - btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape(); - m_compoundColObj->internalSetTemporaryCollisionShape( childShape ); - - if (!m_childCollisionAlgorithms[index]) - m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold); - - m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut); - if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - btVector3 worldAabbMin,worldAabbMax; - m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); - m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); - } - - //revert back transform - m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape); - m_compoundColObj->setWorldTransform( orgTrans ); - m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans); - } - } - void Process(const btDbvtNode* leaf) - { - int index = int(long(leaf->data)); - - btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); - btCollisionShape* childShape = compoundShape->getChildShape(index); - if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - btVector3 worldAabbMin,worldAabbMax; - btTransform orgTrans = m_compoundColObj->getWorldTransform(); - btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); - m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); - } - ProcessChildShape(childShape,index); - - } -}; - - - - - - void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) { btCollisionObject* colObj = m_isSwapped? body1 : body0; @@ -170,69 +59,33 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt assert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - btDbvt* tree = compoundShape->getDynamicAabbTree(); - //use a dynamic aabb tree to cull potential child-overlaps - btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); + //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps + //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals + //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: + //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 + //then use each overlapping node AABB against Tree0 + //and vise versa. - - if (tree) + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i); - btVector3 localAabbMin,localAabbMax; - btTransform otherInCompoundSpace; - otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform(); - otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); - - const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); - //process all children, that overlap with the given AABB bounds - tree->collideTV(tree->m_root,bounds,callback); - - } else - { - //iterate over all children, perform an AABB check inside ProcessChildShape - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;igetChildShape(i),i); - } - } - - { - //iterate over all children, perform an AABB check inside ProcessChildShape - int numChildren = m_childCollisionAlgorithms.size(); - int i; - btManifoldArray manifoldArray; - - for (i=0;igetChildShape(i); - //if not longer overlapping, remove the algorithm - btTransform orgTrans = colObj->getWorldTransform(); - btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform(); - const btTransform& childTrans = compoundShape->getChildTransform(i); - btTransform newChildWorldTrans = orgTrans*childTrans ; - - //perform an AABB check first - btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; - childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); - otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1); - - if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) - { - m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); - m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); - m_childCollisionAlgorithms[i] = 0; - } - - } - - } - - + //backup + btTransform orgTrans = colObj->getWorldTransform(); + btCollisionShape* orgShape = colObj->getCollisionShape(); + const btTransform& childTrans = compoundShape->getChildTransform(i); + //btTransform newChildWorldTrans = orgTrans*childTrans ; + colObj->setWorldTransform( orgTrans*childTrans ); + //the contactpoint is still projected back using the original inverted worldtrans + colObj->setCollisionShape( childShape ); + m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); + //revert back + colObj->setCollisionShape( orgShape); + colObj->setWorldTransform( orgTrans ); } } @@ -264,20 +117,20 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* //backup btTransform orgTrans = colObj->getWorldTransform(); - + btCollisionShape* orgShape = colObj->getCollisionShape(); + const btTransform& childTrans = compoundShape->getChildTransform(i); //btTransform newChildWorldTrans = orgTrans*childTrans ; colObj->setWorldTransform( orgTrans*childTrans ); - btCollisionShape* tmpShape = colObj->getCollisionShape(); - colObj->internalSetTemporaryCollisionShape( childShape ); + colObj->setCollisionShape( childShape ); btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); if (fracinternalSetTemporaryCollisionShape( tmpShape); + colObj->setCollisionShape( orgShape); colObj->setWorldTransform( orgTrans); } return hitFraction; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 624a3cf10f5..7091b233b46 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -16,25 +16,22 @@ subject to the following restrictions: #ifndef COMPOUND_COLLISION_ALGORITHM_H #define COMPOUND_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btDispatcher.h" +#include "../BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" -#include "LinearMath/btAlignedObjectArray.h" -class btDispatcher; +#include "../../LinearMath/btAlignedObjectArray.h" /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes +/// Place holder, not fully implemented yet class btCompoundCollisionAlgorithm : public btCollisionAlgorithm { btAlignedObjectArray m_childCollisionAlgorithms; bool m_isSwapped; - - class btPersistentManifold* m_sharedManifold; - bool m_ownsManifold; public: @@ -46,22 +43,11 @@ public: btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - int i; - for (i=0;igetAllContactManifolds(manifoldArray); - } - } - struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); - return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); + return new btCompoundCollisionAlgorithm(ci,body0,body1,false); } }; @@ -69,8 +55,7 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); - return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); + return new btCompoundCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 6d28904cb03..24ceacfd40d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -29,7 +29,7 @@ subject to the following restrictions: btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) : btCollisionAlgorithm(ci), m_isSwapped(isSwapped), -m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) +m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped) { } @@ -37,13 +37,6 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() { } -void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) -{ - if (m_btConvexTriangleCallback.m_manifoldPtr) - { - manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); - } -} btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): @@ -86,7 +79,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i //aabb filter is already applied! btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher1 = m_dispatcher; + ci.m_dispatcher = m_dispatcher; btCollisionObject* ob = static_cast(m_triBody); @@ -116,11 +109,13 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i { btTriangleShape tm(triangle[0],triangle[1],triangle[2]); tm.setMargin(m_collisionMarginTriangle); + btCollisionShape* tmpShape = ob->getCollisionShape(); - ob->internalSetTemporaryCollisionShape( &tm ); + ob->setCollisionShape( &tm ); - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); ///this should use the btDispatcher, so the actual registered algorithm is used // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); @@ -128,11 +123,12 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->~btCollisionAlgorithm(); - ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); - ob->internalSetTemporaryCollisionShape( tmpShape); + delete colAlgo; + ob->setCollisionShape( tmpShape ); + } + } @@ -192,10 +188,9 @@ void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* bod concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); - resultOut->refreshContactPoints(); } - + } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index 34b9a107be9..4915b6c20c8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -16,13 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btDispatcher.h" +#include "../BroadphaseCollision/btBroadphaseInterface.h" +#include "../CollisionShapes/btTriangleCallback.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. @@ -55,11 +55,11 @@ int m_triangleCount; void clearCache(); - SIMD_FORCE_INLINE const btVector3& getAabbMin() const + inline const btVector3& getAabbMin() const { return m_aabbMin; } - SIMD_FORCE_INLINE const btVector3& getAabbMax() const + inline const btVector3& getAabbMax() const { return m_aabbMax; } @@ -88,16 +88,13 @@ public: btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray); - void clearCache(); struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); - return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); } }; @@ -105,8 +102,7 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); - return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index cb830f889be..9105fe20b49 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -15,7 +15,7 @@ subject to the following restrictions: #include "btConvexConvexAlgorithm.h" -//#include +#include #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" @@ -33,6 +33,7 @@ subject to the following restrictions: +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -47,16 +48,26 @@ subject to the following restrictions: - +btConvexConvexAlgorithm::CreateFunc::CreateFunc() +{ + m_ownsSolvers = true; + m_simplexSolver = new btVoronoiSimplexSolver(); + m_pdSolver = new btGjkEpaPenetrationDepthSolver; +} btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) { + m_ownsSolvers = false; m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } btConvexConvexAlgorithm::CreateFunc::~CreateFunc() { + if (m_ownsSolvers){ + delete m_simplexSolver; + delete m_pdSolver; + } } btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) @@ -141,11 +152,6 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); #endif - if (m_ownManifold) - { - resultOut->refreshContactPoints(); - } - } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index a0030e6793d..cbea9a92b75 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -16,13 +16,12 @@ subject to the following restrictions: #ifndef CONVEX_CONVEX_ALGORITHM_H #define CONVEX_CONVEX_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../NarrowPhaseCollision/btGjkPairDetector.h" +#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "btCollisionCreateFunc.h" -#include "btCollisionDispatcher.h" class btConvexPenetrationDepthSolver; @@ -47,14 +46,6 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - ///should we use m_ownManifold to avoid adding duplicates? - if (m_manifoldPtr && m_ownManifold) - manifoldArray.push_back(m_manifoldPtr); - } - - void setLowLevelOfDetail(bool useLowLevel); @@ -67,15 +58,15 @@ public: { btConvexPenetrationDepthSolver* m_pdSolver; btSimplexSolverInterface* m_simplexSolver; + bool m_ownsSolvers; CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); - + CreateFunc(); virtual ~CreateFunc(); virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); - return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); + return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp deleted file mode 100644 index 391cf6c7bc4..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btConvexPlaneCollisionAlgorithm.h" - -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" - -//#include - -btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) -: btCollisionAlgorithm(ci), -m_ownManifold(false), -m_manifoldPtr(mf), -m_isSwapped(isSwapped) -{ - btCollisionObject* convexObj = m_isSwapped? col1 : col0; - btCollisionObject* planeObj = m_isSwapped? col0 : col1; - - if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) - { - m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj); - m_ownManifold = true; - } -} - - -btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() -{ - if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } -} - - - -void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)dispatchInfo; - (void)resultOut; - if (!m_manifoldPtr) - return; - - btCollisionObject* convexObj = m_isSwapped? body1 : body0; - btCollisionObject* planeObj = m_isSwapped? body0: body1; - - btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); - btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); - - bool hasCollision = false; - const btVector3& planeNormal = planeShape->getPlaneNormal(); - const btScalar& planeConstant = planeShape->getPlaneConstant(); - btTransform planeInConvex; - planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); - btTransform convexInPlaneTrans; - convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); - - btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); - btVector3 vtxInPlane = convexInPlaneTrans(vtx); - btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); - - btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; - btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; - - hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); - resultOut->setPersistentManifold(m_manifoldPtr); - if (hasCollision) - { - /// report a contact. internally this will be kept persistent, and contact reduction is done - btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; - btVector3 pOnB = vtxInPlaneWorld; - resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); - } - if (m_ownManifold) - { - if (m_manifoldPtr->getNumContacts()) - { - resultOut->refreshContactPoints(); - } - } -} - -btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - (void)col0; - (void)col1; - - //not yet - return btScalar(1.); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h deleted file mode 100644 index 7b258554171..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H -#define CONVEX_PLANE_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btPersistentManifold; -#include "btCollisionDispatcher.h" - -#include "LinearMath/btVector3.h" - -/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. -/// Other features are frame-coherency (persistent data) and collision response. -class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - bool m_isSwapped; - -public: - - btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); - - virtual ~btConvexPlaneCollisionAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - { - manifoldArray.push_back(m_manifoldPtr); - } - } - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm)); - if (!m_swapped) - { - return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false); - } else - { - return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true); - } - } - }; - -}; - -#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp deleted file mode 100644 index 1c317080544..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btDefaultCollisionConfiguration.h" - -#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM -#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" -#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM -#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" - - - -#include "LinearMath/btStackAlloc.h" -#include "LinearMath/btPoolAllocator.h" - - - - - -btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) -//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) -{ - - void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); - m_simplexSolver = new (mem)btVoronoiSimplexSolver(); - -#define USE_EPA 1 -#ifdef USE_EPA - mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); - m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; -#else - mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); - m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; -#endif//USE_EPA - - - //default CreationFunctions, filling the m_doubleDispatch table - mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); - m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); - mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); - m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); - m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; - mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); - m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); - m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; - mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); - m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); - m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; -#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM - mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); - m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); - m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; - m_boxSphereCF->m_swapped = true; -#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM - - mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); - m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); - m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; - m_triangleSphereCF->m_swapped = true; - - mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); - m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; - - //convex versus plane - mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); - m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; - mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); - m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; - m_planeConvexCF->m_swapped = true; - - ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool - int maxSize = sizeof(btConvexConvexAlgorithm); - int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); - int maxSize3 = sizeof(btCompoundCollisionAlgorithm); - int maxSize4 = sizeof(btEmptyAlgorithm); - - int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); - collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); - collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4); - - if (constructionInfo.m_stackAlloc) - { - m_ownsStackAllocator = false; - this->m_stackAlloc = constructionInfo.m_stackAlloc; - } else - { - m_ownsStackAllocator = true; - void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); - m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize); - } - - if (constructionInfo.m_persistentManifoldPool) - { - m_ownsPersistentManifoldPool = false; - m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; - } else - { - m_ownsPersistentManifoldPool = true; - void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); - m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); - } - - if (constructionInfo.m_collisionAlgorithmPool) - { - m_ownsCollisionAlgorithmPool = false; - m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; - } else - { - m_ownsCollisionAlgorithmPool = true; - void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); - m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); - } - - -} - -btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() -{ - if (m_ownsStackAllocator) - { - m_stackAlloc->destroy(); - m_stackAlloc->~btStackAlloc(); - btAlignedFree(m_stackAlloc); - } - if (m_ownsCollisionAlgorithmPool) - { - m_collisionAlgorithmPool->~btPoolAllocator(); - btAlignedFree(m_collisionAlgorithmPool); - } - if (m_ownsPersistentManifoldPool) - { - m_persistentManifoldPool->~btPoolAllocator(); - btAlignedFree(m_persistentManifoldPool); - } - - m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_convexConvexCreateFunc); - - m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_convexConcaveCreateFunc); - m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedConvexConcaveCreateFunc); - - m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_compoundCreateFunc); - - m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedCompoundCreateFunc); - - m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_emptyCreateFunc); - - m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_sphereSphereCF); - -#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM - m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_sphereBoxCF); - m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_boxSphereCF); -#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM - - m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_sphereTriangleCF); - m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_triangleSphereCF); - m_boxBoxCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_boxBoxCF); - - m_convexPlaneCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_convexPlaneCF); - m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_planeConvexCF); - - m_simplexSolver->~btVoronoiSimplexSolver(); - btAlignedFree(m_simplexSolver); - - m_pdSolver->~btConvexPenetrationDepthSolver(); - - btAlignedFree(m_pdSolver); - - -} - - -btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) -{ - - - - if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) - { - return m_sphereSphereCF; - } -#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM - if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) - { - return m_sphereBoxCF; - } - - if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) - { - return m_boxSphereCF; - } -#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM - - - if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) - { - return m_sphereTriangleCF; - } - - if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) - { - return m_triangleSphereCF; - } - - if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) - { - return m_boxBoxCF; - } - - if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) - { - return m_convexPlaneCF; - } - - if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) - { - return m_planeConvexCF; - } - - - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_convexConvexCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_convexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) - { - return m_swappedConvexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isCompound(proxyType0)) - { - return m_compoundCreateFunc; - } else - { - if (btBroadphaseProxy::isCompound(proxyType1)) - { - return m_swappedCompoundCreateFunc; - } - } - - //failed to find an algorithm - return m_emptyCreateFunc; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h deleted file mode 100644 index 4f5af5f048c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_DEFAULT_COLLISION_CONFIGURATION -#define BT_DEFAULT_COLLISION_CONFIGURATION - -#include "btCollisionConfiguration.h" -class btVoronoiSimplexSolver; -class btConvexPenetrationDepthSolver; - -struct btDefaultCollisionConstructionInfo -{ - btStackAlloc* m_stackAlloc; - btPoolAllocator* m_persistentManifoldPool; - btPoolAllocator* m_collisionAlgorithmPool; - int m_defaultMaxPersistentManifoldPoolSize; - int m_defaultMaxCollisionAlgorithmPoolSize; - int m_defaultStackAllocatorSize; - - btDefaultCollisionConstructionInfo() - :m_stackAlloc(0), - m_persistentManifoldPool(0), - m_collisionAlgorithmPool(0), - m_defaultMaxPersistentManifoldPoolSize(65535), - m_defaultMaxCollisionAlgorithmPoolSize(65535), - m_defaultStackAllocatorSize(5*1024*1024) - { - } -}; - - - -///btCollisionConfiguration allows to configure Bullet collision detection -///stack allocator, pool memory allocators -///todo: describe the meaning -class btDefaultCollisionConfiguration : public btCollisionConfiguration -{ - - int m_persistentManifoldPoolSize; - - btStackAlloc* m_stackAlloc; - bool m_ownsStackAllocator; - - btPoolAllocator* m_persistentManifoldPool; - bool m_ownsPersistentManifoldPool; - - btPoolAllocator* m_collisionAlgorithmPool; - bool m_ownsCollisionAlgorithmPool; - - //default simplex/penetration depth solvers - btVoronoiSimplexSolver* m_simplexSolver; - btConvexPenetrationDepthSolver* m_pdSolver; - - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; - btCollisionAlgorithmCreateFunc* m_sphereSphereCF; -#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM - btCollisionAlgorithmCreateFunc* m_sphereBoxCF; - btCollisionAlgorithmCreateFunc* m_boxSphereCF; -#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM - - btCollisionAlgorithmCreateFunc* m_boxBoxCF; - btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; - btCollisionAlgorithmCreateFunc* m_triangleSphereCF; - btCollisionAlgorithmCreateFunc* m_planeConvexCF; - btCollisionAlgorithmCreateFunc* m_convexPlaneCF; - -public: - - - btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); - - virtual ~btDefaultCollisionConfiguration(); - - ///memory pools - virtual btPoolAllocator* getPersistentManifoldPool() - { - return m_persistentManifoldPool; - } - - virtual btPoolAllocator* getCollisionAlgorithmPool() - { - return m_collisionAlgorithmPool; - } - - virtual btStackAlloc* getStackAllocator() - { - return m_stackAlloc; - } - - - virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); - - -}; - -#endif //BT_DEFAULT_COLLISION_CONFIGURATION - diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h index e54721dec21..b1a193d2cfd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -15,9 +15,8 @@ subject to the following restrictions: #ifndef EMPTY_ALGORITH #define EMPTY_ALGORITH -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btCollisionAlgorithm.h" #include "btCollisionCreateFunc.h" -#include "btCollisionDispatcher.h" #define ATTRIBUTE_ALIGNED(a) @@ -34,18 +33,13 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - } - struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { (void)body0; (void)body1; - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); - return new(mem) btEmptyAlgorithm(ci); + return new btEmptyAlgorithm(ci); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index d5b12598be2..490acc0b611 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -79,30 +79,12 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b } btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); - newPt.m_positionWorldOnA = pointA; - newPt.m_positionWorldOnB = pointInWorld; - + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); - //BP mod, store contact triangles. - newPt.m_partId0 = m_partId0; - newPt.m_partId1 = m_partId1; - newPt.m_index0 = m_index0; - newPt.m_index1 = m_index1; - - ///todo, check this for any side effects - if (insertIndex >= 0) - { - //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); - m_manifoldPtr->replaceContactPoint(newPt,insertIndex); - } else - { - insertIndex = m_manifoldPtr->addManifoldPoint(newPt); - } - //User can override friction and/or restitution if (gContactAddedCallback && //and if either of the two bodies requires custom material @@ -112,8 +94,16 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b //experimental feature info, for per-triangle material etc. btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; - (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); + (*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); } + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + m_manifoldPtr->AddManifoldPoint(newPt); + } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 5aac9a46f6a..77192625513 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -18,12 +18,12 @@ subject to the following restrictions: #define MANIFOLD_RESULT_H class btCollisionObject; -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btPersistentManifold; class btManifoldPoint; #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "LinearMath/btTransform.h" +#include "../../LinearMath/btTransform.h" typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); extern ContactAddedCallback gContactAddedCallback; @@ -60,15 +60,6 @@ public: m_manifoldPtr = manifoldPtr; } - const btPersistentManifold* getPersistentManifold() const - { - return m_manifoldPtr; - } - btPersistentManifold* getPersistentManifold() - { - return m_manifoldPtr; - } - virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) { m_partId0=partId0; @@ -79,22 +70,6 @@ public: virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); - SIMD_FORCE_INLINE void refreshContactPoints() - { - btAssert(m_manifoldPtr); - if (!m_manifoldPtr->getNumContacts()) - return; - - bool isSwapped = m_manifoldPtr->getBody0() != m_body0; - - if (isSwapped) - { - m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); - } else - { - m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); - } - } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index 1cc78f76acd..ac2e8554c3a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -1,17 +1,3 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ #include "LinearMath/btScalar.h" @@ -21,7 +7,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" -//#include +#include #include "LinearMath/btQuickprof.h" btSimulationIslandManager::btSimulationIslandManager() @@ -39,17 +25,17 @@ void btSimulationIslandManager::initUnionFind(int n) } -void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) +void btSimulationIslandManager::findUnions(btDispatcher* dispatcher) { { - btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); - - for (int i=0;igetPairCache()->getNumOverlappingPairs();i++) + for (int i=0;igetNumManifolds();i++) { - const btBroadphasePair& collisionPair = pairPtr[i]; - btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; - btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; + const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); + //static objects (invmass btScalar(0.)) don't merge ! + + const btCollisionObject* colObj0 = static_cast(manifold->getBody0()); + const btCollisionObject* colObj1 = static_cast(manifold->getBody1()); if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && ((colObj1) && ((colObj1)->mergesSimulationIslands()))) @@ -85,7 +71,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld } // do the union find - findUnions(dispatcher,colWorld); + findUnions(dispatcher); @@ -143,13 +129,30 @@ class btPersistentManifoldSortPredicate }; -void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects) + + + +// +// todo: this is random access, it can be walked 'cache friendly'! +// +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) { - BT_PROFILE("islandUnionFindAndQuickSort"); - m_islandmanifold.resize(0); + + /*if (0) + { + int maxNumManifolds = dispatcher->getNumManifolds(); + btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher; + btPersistentManifold** manifold = colDis->getInternalManifoldPointer(); + callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0); + return; + } + */ + + BEGIN_PROFILE("islandUnionFindAndHeapSort"); + //we are going to sort the unionfind array, and store the element id in the size //afterwards, we clean unionfind, to make sure no-one uses it anymore @@ -180,7 +183,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { -// printf("error in island management\n"); + printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -207,7 +210,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { -// printf("error in island management\n"); + printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -228,7 +231,7 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { -// printf("error in island management\n"); + printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -244,17 +247,11 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio } } - + btAlignedObjectArray islandmanifold; int i; int maxNumManifolds = dispatcher->getNumManifolds(); + islandmanifold.reserve(maxNumManifolds); -#define SPLIT_ISLANDS 1 -#ifdef SPLIT_ISLANDS - - -#endif //SPLIT_ISLANDS - - for (i=0;igetManifoldByIndexInternal(i); @@ -268,52 +265,29 @@ void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisio { //kinematic objects don't merge islands, but wake up all connected objects - if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) { colObj1->activate(); } - if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) { colObj0->activate(); } -#ifdef SPLIT_ISLANDS - // //filtering for response + + //filtering for response if (dispatcher->needsResponse(colObj0,colObj1)) - m_islandmanifold.push_back(manifold); -#endif //SPLIT_ISLANDS + islandmanifold.push_back(manifold); } } -} + int numManifolds = int (islandmanifold.size()); - -// -// todo: this is random access, it can be walked 'cache friendly'! -// -void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) -{ - - buildIslands(dispatcher,collisionObjects); - - int endIslandIndex=1; - int startIslandIndex; - int numElem = getUnionFind().getNumElements(); - - BT_PROFILE("processIslands"); - -#ifndef SPLIT_ISLANDS - btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); - - callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); -#else // Sort manifolds, based on islands // Sort the vector using predicate and std::sort //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); - int numManifolds = int (m_islandmanifold.size()); - //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) - m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); + islandmanifold.heapSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) @@ -322,9 +296,10 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, //int islandId; - + END_PROFILE("islandUnionFindAndHeapSort"); + + btAlignedObjectArray islandBodies; -// printf("Start Islands\n"); //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated for ( startIslandIndex=0;startIslandIndexisActive()) islandSleeping = true; } @@ -350,12 +325,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, if (startManifoldIndexProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); -// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); + callback->ProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); } if (numIslandManifolds) @@ -376,9 +350,8 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, startManifoldIndex = endManifoldIndex; } - m_islandBodies.resize(0); + islandBodies.resize(0); } -#endif //SPLIT_ISLANDS - + } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index 5f4d54cd803..d91ed1c20eb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -16,26 +16,18 @@ subject to the following restrictions: #ifndef SIMULATION_ISLAND_MANAGER_H #define SIMULATION_ISLAND_MANAGER_H -#include "BulletCollision/CollisionDispatch/btUnionFind.h" +#include "../CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" -#include "LinearMath/btAlignedObjectArray.h" - class btCollisionObject; class btCollisionWorld; class btDispatcher; -class btPersistentManifold; - ///SimulationIslandManager creates and handles simulation islands, using btUnionFind class btSimulationIslandManager { btUnionFind m_unionFind; - btAlignedObjectArray m_islandmanifold; - btAlignedObjectArray m_islandBodies; - - public: btSimulationIslandManager(); virtual ~btSimulationIslandManager(); @@ -50,7 +42,7 @@ public: virtual void storeIslandActivationState(btCollisionWorld* world); - void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); + void findUnions(btDispatcher* dispatcher); @@ -63,8 +55,6 @@ public: void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); - void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects); - }; #endif //SIMULATION_ISLAND_MANAGER_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp index 1e4bbce451d..05556bd34e2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -68,25 +68,18 @@ void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,b btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); - resultOut->setPersistentManifold(m_manifoldPtr); - if (dist < SIMD_EPSILON) { btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); } - if (m_ownManifold) - { - if (m_manifoldPtr->getNumContacts()) - { - resultOut->refreshContactPoints(); - } - } + } @@ -109,8 +102,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* box btVector3 bounds[2]; btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); - bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); - bounds[1] = boxShape->getHalfExtentsWithoutMargin(); + bounds[0] = -boxShape->getHalfExtents(); + bounds[1] = boxShape->getHalfExtents(); margins = boxShape->getMargin();//also add sphereShape margin? @@ -216,10 +209,6 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* btVector3 p0, tmp, prel, n[6], normal; btScalar fSep = btScalar(-10000000.0), fSepThis; - // set p0 and normal to a default value to shup up GCC - p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); - normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); - n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h index 158f0ffcc74..07592909200 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -16,13 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H #define SPHERE_BOX_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; -#include "btCollisionDispatcher.h" - -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btVector3.h" /// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -42,14 +40,6 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - { - manifoldArray.push_back(m_manifoldPtr); - } - } - btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); @@ -58,13 +48,12 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); if (!m_swapped) { - return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); + return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); } else { - return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); + return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); } } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp index c9256473c00..424ff432f84 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -46,8 +46,6 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 if (!m_manifoldPtr) return; - resultOut->setPersistentManifold(m_manifoldPtr); - btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); @@ -56,34 +54,23 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 btScalar radius0 = sphere0->getRadius(); btScalar radius1 = sphere1->getRadius(); - //m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting - ///iff distance positive, don't generate a new contact if ( len > (radius0+radius1)) - { return; - } + ///distance (negative means penetration) btScalar dist = len - (radius0+radius1); - btVector3 normalOnSurfaceB(1,0,0); - if (len > SIMD_EPSILON) - { - normalOnSurfaceB = diff / len; - } - + btVector3 normalOnSurfaceB = diff / len; ///point on A (worldspace) btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; ///point on B (worldspace) btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; /// report a contact. internally this will be kept persistent, and contact reduction is done - - + resultOut->setPersistentManifold(m_manifoldPtr); resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); - //no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new) - } btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h index afdc2ee7fa0..7a19ff31edf 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -16,11 +16,9 @@ subject to the following restrictions: #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H #define SPHERE_SPHERE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -#include "btCollisionDispatcher.h" - +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. @@ -41,13 +39,6 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - { - manifoldArray.push_back(m_manifoldPtr); - } - } virtual ~btSphereSphereCollisionAlgorithm(); @@ -55,8 +46,7 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); - return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); + return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index fdbd4abef27..b011b707e3f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -48,11 +48,8 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co if (!m_manifoldPtr) return; - btCollisionObject* sphereObj = m_swapped? col1 : col0; - btCollisionObject* triObj = m_swapped? col0 : col1; - - btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); - btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); + btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape(); /// report a contact. internally this will be kept persistent, and contact reduction is done resultOut->setPersistentManifold(m_manifoldPtr); @@ -60,16 +57,11 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co btDiscreteCollisionDetectorInterface::ClosestPointInput input; input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds - input.m_transformA = sphereObj->getWorldTransform(); - input.m_transformB = triObj->getWorldTransform(); + input.m_transformA = col0->getWorldTransform(); + input.m_transformB = col1->getWorldTransform(); - bool swapResults = m_swapped; + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); - detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); - - if (m_ownManifold) - resultOut->refreshContactPoints(); - } btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h index bbaf228c44c..57c6e6af619 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -16,11 +16,10 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; -#include "btCollisionDispatcher.h" /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -41,13 +40,6 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - { - manifoldArray.push_back(m_manifoldPtr); - } - } virtual ~btSphereTriangleCollisionAlgorithm(); @@ -57,9 +49,7 @@ public: virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); - - return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); + return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp index bb01b60fa85..62254335796 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -18,7 +18,6 @@ subject to the following restrictions: - btUnionFind::~btUnionFind() { Free(); @@ -77,7 +76,8 @@ void btUnionFind::sortIslands() // Sort the vector using predicate and std::sort //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate); - m_elements.quickSort(btUnionFindElementSortPredicate()); + //perhaps use radix sort? + m_elements.heapSort(btUnionFindElementSortPredicate()); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h index 820c8bc858e..236cc33b94f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef UNION_FIND_H #define UNION_FIND_H -#include "LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btAlignedObjectArray.h" #define USE_PATH_COMPRESSION 1 @@ -46,11 +46,11 @@ class btUnionFind void reset(int N); - SIMD_FORCE_INLINE int getNumElements() const + inline int getNumElements() const { return int(m_elements.size()); } - SIMD_FORCE_INLINE bool isRoot(int x) const + inline bool isRoot(int x) const { return (x == m_elements[x].m_id); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp index 8bc2cfa6ffa..636b0046c13 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -15,20 +15,35 @@ subject to the following restrictions: #include "btBoxShape.h" - +btVector3 btBoxShape::getHalfExtents() const +{ + return m_implicitShapeDimensions * m_localScaling; +} //{ void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { - btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); + btVector3 halfExtents = getHalfExtents(); + + btMatrix3x3 abs_b = t.getBasis().absolute(); + btPoint3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents), + abs_b[1].dot(halfExtents), + abs_b[2].dot(halfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + + aabbMin = center - extent; + aabbMax = center + extent; + + } -void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { //btScalar margin = btScalar(0.); - btVector3 halfExtents = getHalfExtentsWithMargin(); + btVector3 halfExtents = getHalfExtents(); btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h index 4d4fbefea37..bc42f146c7c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -18,11 +18,11 @@ subject to the following restrictions: #include "btPolyhedralConvexShape.h" #include "btCollisionMargin.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btMinMax.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btSimdMinMax.h" -///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. +///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box class btBoxShape: public btPolyhedralConvexShape { @@ -31,52 +31,47 @@ class btBoxShape: public btPolyhedralConvexShape public: - btVector3 getHalfExtentsWithMargin() const - { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents += margin; - return halfExtents; - } - - const btVector3& getHalfExtentsWithoutMargin() const - { - return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included - } - - + btVector3 getHalfExtents() const; + virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} virtual btVector3 localGetSupportingVertex(const btVector3& vec) const { - btVector3 halfExtents = getHalfExtentsWithoutMargin(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents += margin; - return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), - btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), - btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + btVector3 halfExtents = getHalfExtents(); + + btVector3 supVertex; + supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); + + return supVertex; } - SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - const btVector3& halfExtents = getHalfExtentsWithoutMargin(); - - return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), - btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), - btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); + btVector3 halfExtents = getHalfExtents(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents -= margin; + + return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), + vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), + vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); } virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { - const btVector3& halfExtents = getHalfExtentsWithoutMargin(); - + btVector3 halfExtents = getHalfExtents(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents -= margin; + + for (int i=0;ihasPremadeAabb()) - { - meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax); - } - else - { - meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); - } - - if (buildBvh) - { - void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); - m_bvh = new (mem) btOptimizedBvh(); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); - m_ownsBvh = true; - } + meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); #endif //DISABLE_BVH } -btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) -:btTriangleMeshShape(meshInterface), -m_bvh(0), -m_useQuantizedAabbCompression(useQuantizedAabbCompression), -m_ownsBvh(false) +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) +:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) { //construct bvh from meshInterface #ifndef DISABLE_BVH - if (buildBvh) - { - void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); - m_bvh = new (mem) btOptimizedBvh(); - - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); - m_ownsBvh = true; - } + m_bvh = new btOptimizedBvh(); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); #endif //DISABLE_BVH @@ -82,140 +58,16 @@ void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btV } -void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax) +void btBvhTriangleMeshShape::refitTree() { - m_bvh->refit( m_meshInterface, aabbMin,aabbMax ); + m_bvh->refit( m_meshInterface ); recalcLocalAabb(); } btBvhTriangleMeshShape::~btBvhTriangleMeshShape() { - if (m_ownsBvh) - { - m_bvh->~btOptimizedBvh(); - btAlignedFree(m_bvh); - } -} - -void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) -{ - struct MyNodeOverlapCallback : public btNodeOverlapCallback - { - btStridingMeshInterface* m_meshInterface; - btTriangleCallback* m_callback; - - MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) - :m_meshInterface(meshInterface), - m_callback(callback) - { - } - - virtual void processNode(int nodeSubPart, int nodeTriangleIndex) - { - btVector3 m_triangle[3]; - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - - m_meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - nodeSubPart); - - unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); - btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); - - const btVector3& meshScaling = m_meshInterface->getScaling(); - for (int j=2;j>=0;j--) - { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; - - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); - - m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); - } - - /* Perform ray vs. triangle collision here */ - m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); - m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); - } - }; - - MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); - - m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget); -} - -void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) -{ - struct MyNodeOverlapCallback : public btNodeOverlapCallback - { - btStridingMeshInterface* m_meshInterface; - btTriangleCallback* m_callback; - - MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) - :m_meshInterface(meshInterface), - m_callback(callback) - { - } - - virtual void processNode(int nodeSubPart, int nodeTriangleIndex) - { - btVector3 m_triangle[3]; - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - - m_meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - nodeSubPart); - - unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); - btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); - - const btVector3& meshScaling = m_meshInterface->getScaling(); - for (int j=2;j>=0;j--) - { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; - - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); - - m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); - } - - /* Perform ray vs. triangle collision here */ - m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); - m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); - } - }; - - MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); - - m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); + delete m_bvh; } //perform bvh tree traversal and report overlapping triangles to 'callback' @@ -266,14 +118,13 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co indicestype, nodeSubPart); - unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); - btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); const btVector3& meshScaling = m_meshInterface->getScaling(); for (int j=2;j>=0;j--) { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + int graphicsindex = gfxbase[j]; #ifdef DEBUG_TRIANGLE_MESH @@ -306,37 +157,17 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co } -void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) + +void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) { - if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) - { - btTriangleMeshShape::setLocalScaling(scaling); - if (m_ownsBvh) - { - m_bvh->~btOptimizedBvh(); - btAlignedFree(m_bvh); - } - ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work - void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); - m_bvh = new(mem) btOptimizedBvh(); - //rebuild the bvh... - m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); - m_ownsBvh = true; - } + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + delete m_bvh; + ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work + m_bvh = new btOptimizedBvh(); + //rebuild the bvh... + m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); + + } } - -void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling) -{ - btAssert(!m_bvh); - btAssert(!m_ownsBvh); - - m_bvh = bvh; - m_ownsBvh = false; - // update the scaling without rebuilding the bvh - if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) - { - btTriangleMeshShape::setLocalScaling(scaling); - } -} - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index 6e587340dc1..4914d9f959c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -18,55 +18,45 @@ subject to the following restrictions: #include "btTriangleMeshShape.h" #include "btOptimizedBvh.h" -#include "LinearMath/btAlignedAllocator.h" - -///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage. -///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method. -///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk. -///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example. +///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. +///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape { btOptimizedBvh* m_bvh; bool m_useQuantizedAabbCompression; - bool m_ownsBvh; - bool m_pad[11];////need padding due to alignment + bool m_pad[12];////need padding due to alignment public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {}; - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); + btBvhTriangleMeshShape() :btTriangleMeshShape(0) {}; + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression); ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); virtual ~btBvhTriangleMeshShape(); - bool getOwnsBvh () const - { - return m_ownsBvh; - } - + + /* virtual int getShapeType() const { return TRIANGLE_MESH_SHAPE_PROXYTYPE; } - - void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget); - void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax); + */ + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - void refitTree(const btVector3& aabbMin,const btVector3& aabbMax); + void refitTree(); ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); //debugging - virtual const char* getName()const {return "BVHTRIANGLEMESH";} + virtual char* getName()const {return "BVHTRIANGLEMESH";} virtual void setLocalScaling(const btVector3& scaling); @@ -75,10 +65,6 @@ public: { return m_bvh; } - - - void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1)); - bool usesQuantizedAabbCompression() const { return m_useQuantizedAabbCompression; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index 26ba276b900..b7e15172da2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -21,7 +21,6 @@ subject to the following restrictions: btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) { - m_upAxis = 1; m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); } @@ -51,9 +50,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) { - btVector3 pos(0,0,0); - pos[getUpAxis()] = getHalfHeight(); - + btVector3 pos(0,getHalfHeight(),0); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -63,9 +60,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } } { - btVector3 pos(0,0,0); - pos[getUpAxis()] = -getHalfHeight(); - + btVector3 pos(0,-getHalfHeight(),0); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -93,8 +88,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) btVector3 vtx; btScalar newDot; { - btVector3 pos(0,0,0); - pos[getUpAxis()] = getHalfHeight(); + btVector3 pos(0,getHalfHeight(),0); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -104,8 +98,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } } { - btVector3 pos(0,0,0); - pos[getUpAxis()] = -getHalfHeight(); + btVector3 pos(0,-getHalfHeight(),0); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -119,7 +112,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } -void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { //as an approximation, take the inertia of the box that bounds the spheres @@ -129,8 +122,7 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con btScalar radius = getRadius(); - btVector3 halfExtents(radius,radius,radius); - halfExtents[getUpAxis()]+=getHalfHeight(); + btVector3 halfExtents(radius,radius+getHalfHeight(),radius); btScalar margin = CONVEX_DISTANCE_MARGIN; @@ -148,22 +140,6 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) con } -btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) -{ - m_upAxis = 0; - m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); -} - - - - - - -btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) -{ - m_upAxis = 2; - m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h index d4b046d40c9..27da8adefa5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -16,27 +16,20 @@ subject to the following restrictions: #ifndef BT_CAPSULE_SHAPE_H #define BT_CAPSULE_SHAPE_H -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis. -///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. -///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres. -class btCapsuleShape : public btConvexInternalShape +///btCapsuleShape represents a capsule around the Y axis +///A more general solution that can represent capsules is the btMultiSphereShape +class btCapsuleShape : public btConvexShape { -protected: - int m_upAxis; - -protected: - ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. - btCapsuleShape() {}; public: btCapsuleShape(btScalar radius,btScalar height); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -45,76 +38,23 @@ public: virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } - virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const - { - btVector3 halfExtents(getRadius(),getRadius(),getRadius()); - halfExtents[m_upAxis] = getRadius() + getHalfHeight(); - halfExtents += btVector3(getMargin(),getMargin(),getMargin()); - btMatrix3x3 abs_b = t.getBasis().absolute(); - btPoint3 center = t.getOrigin(); - btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); - - aabbMin = center - extent; - aabbMax = center + extent; - } - - virtual const char* getName()const + virtual char* getName()const { return "CapsuleShape"; } - int getUpAxis() const - { - return m_upAxis; - } - btScalar getRadius() const { - int radiusAxis = (m_upAxis+2)%3; - return m_implicitShapeDimensions[radiusAxis]; + return m_implicitShapeDimensions.getX(); } btScalar getHalfHeight() const { - return m_implicitShapeDimensions[m_upAxis]; + return m_implicitShapeDimensions.getY(); } }; -///btCapsuleShapeX represents a capsule around the Z axis -///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. -class btCapsuleShapeX : public btCapsuleShape -{ -public: - - btCapsuleShapeX(btScalar radius,btScalar height); - - //debugging - virtual const char* getName()const - { - return "CapsuleX"; - } - - - -}; - -///btCapsuleShapeZ represents a capsule around the Z axis -///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. -class btCapsuleShapeZ : public btCapsuleShape -{ -public: - btCapsuleShapeZ(btScalar radius,btScalar height); - - //debugging - virtual const char* getName()const - { - return "CapsuleZ"; - } - - -}; - #endif //BT_CAPSULE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp index 39e621aa946..81d82428f4c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -21,12 +21,7 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" -{ -void btBulletCollisionProbe (); - -void btBulletCollisionProbe () {} -} +extern "C" void btBulletCollisionProbe () {} @@ -51,7 +46,7 @@ btScalar btCollisionShape::getAngularMotionDisc() const return disc; } -void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const +void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) { //start with static aabb getAabb(curTrans,temporalAabbMin,temporalAabbMax); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h index 3a352b90777..96268734a83 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -16,21 +16,18 @@ subject to the following restrictions: #ifndef COLLISION_SHAPE_H #define COLLISION_SHAPE_H -#include "LinearMath/btTransform.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btMatrix3x3.h" -#include "LinearMath/btPoint3.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "../../LinearMath/btPoint3.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types -///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. +///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. class btCollisionShape { - - void* m_userPointer; - public: - btCollisionShape() : m_userPointer(0) + btCollisionShape() { } virtual ~btCollisionShape() @@ -48,30 +45,30 @@ public: ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) ///result is conservative - void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const; + void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax); #ifndef __SPU__ - SIMD_FORCE_INLINE bool isPolyhedral() const + inline bool isPolyhedral() const { return btBroadphaseProxy::isPolyhedral(getShapeType()); } - SIMD_FORCE_INLINE bool isConvex() const + inline bool isConvex() const { return btBroadphaseProxy::isConvex(getShapeType()); } - SIMD_FORCE_INLINE bool isConcave() const + inline bool isConcave() const { return btBroadphaseProxy::isConcave(getShapeType()); } - SIMD_FORCE_INLINE bool isCompound() const + inline bool isCompound() const { return btBroadphaseProxy::isCompound(getShapeType()); } ///isInfinite is used to catch simulation error (aabb check) - SIMD_FORCE_INLINE bool isInfinite() const + inline bool isInfinite() const { return btBroadphaseProxy::isInfinite(getShapeType()); } @@ -79,11 +76,11 @@ public: virtual int getShapeType() const=0; virtual void setLocalScaling(const btVector3& scaling) =0; virtual const btVector3& getLocalScaling() const =0; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0; //debugging support - virtual const char* getName()const =0 ; + virtual char* getName()const =0 ; #endif //__SPU__ @@ -91,18 +88,6 @@ public: virtual void setMargin(btScalar margin) = 0; virtual btScalar getMargin() const = 0; - - ///optional user data pointer - void setUserPointer(void* userPtr) - { - m_userPointer = userPtr; - } - - void* getUserPointer() const - { - return m_userPointer; - } - }; #endif //COLLISION_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index f08b810eadb..a4712b3e925 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -14,42 +14,29 @@ subject to the following restrictions: */ #include "btCompoundShape.h" + + #include "btCollisionShape.h" -#include "BulletCollision/BroadphaseCollision/btDbvt.h" + btCompoundShape::btCompoundShape() :m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), +m_aabbTree(0), m_collisionMargin(btScalar(0.)), -m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_dynamicAabbTree(0) +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) { - void* mem = btAlignedAlloc(sizeof(btDbvt),16); - m_dynamicAabbTree = new(mem) btDbvt(); - btAssert(mem==m_dynamicAabbTree); } btCompoundShape::~btCompoundShape() { - if (m_dynamicAabbTree) - { - m_dynamicAabbTree->~btDbvt(); - btAlignedFree(m_dynamicAabbTree); - } } void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) { - //m_childTransforms.push_back(localTransform); - //m_childShapes.push_back(shape); - btCompoundShapeChild child; - child.m_transform = localTransform; - child.m_childShape = shape; - child.m_childShapeType = shape->getShapeType(); - child.m_childMargin = shape->getMargin(); - - m_children.push_back(child); + m_childTransforms.push_back(localTransform); + m_childShapes.push_back(shape); //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; @@ -66,100 +53,39 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio } } - if (m_dynamicAabbTree) - { - const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); - int index = m_children.size()-1; - child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); - } - } -void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) -{ - btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); - if (m_dynamicAabbTree) - { - m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); - } - m_children.swap(childShapeIndex,m_children.size()-1); - m_children.pop_back(); - -} - -void btCompoundShape::removeChildShape(btCollisionShape* shape) -{ - // Find the children containing the shape specified, and remove those children. - //note: there might be multiple children using the same shape! - for(int i = m_children.size()-1; i >= 0 ; i--) - { - if(m_children[i].m_childShape == shape) - { - m_children.swap(i,m_children.size()-1); - m_children.pop_back(); - //remove it from the m_dynamicAabbTree too - //m_dynamicAabbTree->remove(m_aabbProxies[i]); - //m_aabbProxies.swap(i,m_children.size()-1); - //m_aabbProxies.pop_back(); - } - } - - recalculateLocalAabb(); -} - -void btCompoundShape::recalculateLocalAabb() -{ - // Recalculate the local aabb - // Brute force, it iterates over all the shapes left. - m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - - //extend the local aabbMin/aabbMax - for (int j = 0; j < m_children.size(); j++) - { - btVector3 localAabbMin,localAabbMax; - m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); - for (int i=0;i<3;i++) - { - if (m_localAabbMin[i] > localAabbMin[i]) - m_localAabbMin[i] = localAabbMin[i]; - if (m_localAabbMax[i] < localAabbMax[i]) - m_localAabbMax[i] = localAabbMax[i]; - } - } -} - -///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - + btMatrix3x3 abs_b = trans.getBasis().absolute(); btPoint3 center = trans(localCenter); btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - aabbMin = center-extent; - aabbMax = center+extent; + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + aabbMin = center - extent; + aabbMax = center + extent; } -void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { //approximation: take the inertia from the aabb for now btTransform ident; ident.setIdentity(); btVector3 aabbMin,aabbMax; getAabb(ident,aabbMin,aabbMax); - + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); - + btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); btScalar lz=btScalar(2.)*(halfExtents.z()); @@ -170,62 +96,5 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) co } - - - -void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const -{ - int n = m_children.size(); - - btScalar totalMass = 0; - btVector3 center(0, 0, 0); - for (int k = 0; k < n; k++) - { - center += m_children[k].m_transform.getOrigin() * masses[k]; - totalMass += masses[k]; - } - center /= totalMass; - principal.setOrigin(center); - - btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); - for (int k = 0; k < n; k++) - { - btVector3 i; - m_children[k].m_childShape->calculateLocalInertia(masses[k], i); - - const btTransform& t = m_children[k].m_transform; - btVector3 o = t.getOrigin() - center; - - //compute inertia tensor in coordinate system of compound shape - btMatrix3x3 j = t.getBasis().transpose(); - j[0] *= i[0]; - j[1] *= i[1]; - j[2] *= i[2]; - j = t.getBasis() * j; - - //add inertia tensor - tensor[0] += j[0]; - tensor[1] += j[1]; - tensor[2] += j[2]; - - //compute inertia tensor of pointmass at o - btScalar o2 = o.length2(); - j[0].setValue(o2, 0, 0); - j[1].setValue(0, o2, 0); - j[2].setValue(0, 0, o2); - j[0] += o * -o.x(); - j[1] += o * -o.y(); - j[2] += o * -o.z(); - - //add inertia tensor of pointmass - tensor[0] += masses[k] * j[0]; - tensor[1] += masses[k] * j[1]; - tensor[2] += masses[k] * j[2]; - } - - tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); - inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); -} - - - + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index 3624749f768..86dc1f80947 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -18,97 +18,58 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btMatrix3x3.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" -#include "LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btAlignedObjectArray.h" -//class btOptimizedBvh; -struct btDbvt; - -ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild -{ - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btTransform m_transform; - btCollisionShape* m_childShape; - int m_childShapeType; - btScalar m_childMargin; - struct btDbvtNode* m_node; -}; - -SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) -{ - return ( c1.m_transform == c2.m_transform && - c1.m_childShape == c2.m_childShape && - c1.m_childShapeType == c2.m_childShapeType && - c1.m_childMargin == c2.m_childMargin ); -} +class btOptimizedBvh; /// btCompoundShape allows to store multiple other btCollisionShapes -/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. -ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape +/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. +class btCompoundShape : public btCollisionShape { - //btAlignedObjectArray m_childTransforms; - //btAlignedObjectArray m_childShapes; - btAlignedObjectArray m_children; + btAlignedObjectArray m_childTransforms; + btAlignedObjectArray m_childShapes; btVector3 m_localAabbMin; btVector3 m_localAabbMax; - //btOptimizedBvh* m_aabbTree; - btDbvt* m_dynamicAabbTree; + btOptimizedBvh* m_aabbTree; public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - btCompoundShape(); virtual ~btCompoundShape(); void addChildShape(const btTransform& localTransform,btCollisionShape* shape); - /// Remove all children shapes that contain the specified shape - virtual void removeChildShape(btCollisionShape* shape); - - void removeChildShapeByIndex(int childShapeindex); - - int getNumChildShapes() const { - return int (m_children.size()); + return int (m_childShapes.size()); } btCollisionShape* getChildShape(int index) { - return m_children[index].m_childShape; + return m_childShapes[index]; } const btCollisionShape* getChildShape(int index) const { - return m_children[index].m_childShape; + return m_childShapes[index]; } - btTransform getChildTransform(int index) + btTransform& getChildTransform(int index) { - return m_children[index].m_transform; + return m_childTransforms[index]; } - const btTransform getChildTransform(int index) const + const btTransform& getChildTransform(int index) const { - return m_children[index].m_transform; - } - - - btCompoundShapeChild* getChildList() - { - return &m_children[0]; + return m_childTransforms[index]; } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. - Use this yourself if you modify the children or their transforms. */ - virtual void recalculateLocalAabb(); virtual void setLocalScaling(const btVector3& scaling) { @@ -119,8 +80,8 @@ public: return m_localScaling; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} virtual void setMargin(btScalar margin) @@ -131,7 +92,7 @@ public: { return m_collisionMargin; } - virtual const char* getName()const + virtual char* getName()const { return "Compound"; } @@ -139,19 +100,11 @@ public: //this is optional, but should make collision queries faster, by culling non-overlapping nodes void createAabbTreeFromChildren(); - btDbvt* getDynamicAabbTree() + const btOptimizedBvh* getAabbTree() const { - return m_dynamicAabbTree; + return m_aabbTree; } - ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia - ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform - ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound - ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform - ///of the collision object by the principal transform. - void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; - - private: btScalar m_collisionMargin; protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h index f3f57206ab7..73f974e4ee9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -17,12 +17,12 @@ subject to the following restrictions: #define CONCAVE_SHAPE_H #include "btCollisionShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "btTriangleCallback.h" -///The btConcaveShape class provides an interface for non-moving (static) concave shapes. -///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. +///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB. +///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface. class btConcaveShape : public btCollisionShape { protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h index 685369742e4..3ccda5b12c6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef CONE_MINKOWSKI_H #define CONE_MINKOWSKI_H -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis. -class btConeShape : public btConvexInternalShape +///btConeShape implements a Cone shape, around the Y axis +class btConeShape : public btConvexShape { @@ -42,7 +42,7 @@ public: btScalar getHeight() const { return m_height;} - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) { btTransform identity; identity.setIdentity(); @@ -72,7 +72,7 @@ public: virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; } - virtual const char* getName()const + virtual char* getName()const { return "Cone"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h index c029ca19403..3fd5e382525 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -17,17 +17,18 @@ subject to the following restrictions: #define CONVEX_HULL_SHAPE_H #include "btPolyhedralConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -#include "LinearMath/btAlignedObjectArray.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "../../LinearMath/btAlignedObjectArray.h" -///The btConvexHullShape implements an implicit convex hull of an array of vertices. -///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex. +///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) +///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. +///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash. +///(memory is much slower then the cpu) ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape { btAlignedObjectArray m_points; public: - BT_DECLARE_ALIGNED_ALLOCATOR(); ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. @@ -42,12 +43,7 @@ public: return &m_points[0]; } - const btPoint3* getPoints() const - { - return &m_points[0]; - } - - int getNumPoints() const + int getNumPoints() { return m_points.size(); } @@ -60,7 +56,7 @@ public: virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } //debugging - virtual const char* getName()const {return "Convex";} + virtual char* getName()const {return "Convex";} virtual int getNumVertices() const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp deleted file mode 100644 index f828d28e18c..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btConvexInternalShape.h" - - -btConvexInternalShape::btConvexInternalShape() -: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_collisionMargin(CONVEX_DISTANCE_MARGIN) -{ -} - - -void btConvexInternalShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} - - - -void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const -{ - - btScalar margin = getMargin(); - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - - btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); - - btVector3 tmp = trans(sv); - maxAabb[i] = tmp[i]+margin; - vec[i] = btScalar(-1.); - tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); - minAabb[i] = tmp[i]-margin; - } -}; - - -btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const -{ -#ifndef __SPU__ - - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; - -#else - return btVector3(0,0,0); -#endif //__SPU__ - - } - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h deleted file mode 100644 index 9388ccf31f2..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h +++ /dev/null @@ -1,98 +0,0 @@ - -#ifndef BT_CONVEX_INTERNAL_SHAPE_H -#define BT_CONVEX_INTERNAL_SHAPE_H - -#include "btConvexShape.h" - -///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. -class btConvexInternalShape : public btConvexShape -{ - - protected: - - //local scaling. collisionMargin is not scaled ! - btVector3 m_localScaling; - - btVector3 m_implicitShapeDimensions; - - btScalar m_collisionMargin; - - btScalar m_padding; - -public: - - btConvexInternalShape(); - - virtual ~btConvexInternalShape() - { - - } - - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; -#ifndef __SPU__ - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; - - //notice that the vectors should be unit length - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; -#endif //#ifndef __SPU__ - - const btVector3& getImplicitShapeDimensions() const - { - return m_implicitShapeDimensions; - } - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - getAabbSlow(t,aabbMin,aabbMax); - } - - - - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const - { - return m_localScaling; - } - - const btVector3& getLocalScalingNV() const - { - return m_localScaling; - } - - virtual void setMargin(btScalar margin) - { - m_collisionMargin = margin; - } - virtual btScalar getMargin() const - { - return m_collisionMargin; - } - - btScalar getMarginNV() const - { - return m_collisionMargin; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 0; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - (void)penetrationVector; - (void)index; - btAssert(0); - } - - - -}; - - -#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp index 7afcccf8b03..7edf1ea6db8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -16,3 +16,62 @@ subject to the following restrictions: #include "btConvexShape.h" +btConvexShape::btConvexShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + + + +void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +}; + + +btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + return btVector3(0,0,0); +#endif //__SPU__ + + } + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h index e4eb7f6dbf6..746f383dfc7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -18,25 +18,37 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btMatrix3x3.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" -#include "LinearMath/btAlignedAllocator.h" //todo: get rid of this btConvexCastResult thing! struct btConvexCastResult; #define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 -/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc. -/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector. +/// btConvexShape is an abstract shape interface. +/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface. +/// used in combination with GJK or btConvexCast ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape { +protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding[2]; + + + public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); + btConvexShape(); virtual ~btConvexShape() { @@ -44,7 +56,7 @@ public: } - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0; + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; #ifndef __SPU__ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; @@ -52,24 +64,63 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; #endif //#ifndef __SPU__ + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; - virtual void setLocalScaling(const btVector3& scaling) =0; - virtual const btVector3& getLocalScaling() const =0; - - virtual void setMargin(btScalar margin)=0; - - virtual btScalar getMargin() const=0; - - virtual int getNumPreferredPenetrationDirections() const=0; - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; -}; + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + + + +} +; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp index 02a293e82ba..6941030b15f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -19,11 +19,10 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" -btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) +btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface) :m_stridingMesh(meshInterface) { - if ( calcAabb ) - recalcLocalAabb(); + recalcLocalAabb(); } @@ -204,113 +203,3 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const { return m_stridingMesh->getScaling(); } - -void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const -{ - class CenterCallback: public btInternalTriangleIndexCallback - { - bool first; - btVector3 ref; - btVector3 sum; - btScalar volume; - - public: - - CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) - { - (void) triangleIndex; - (void) partId; - if (first) - { - ref = triangle[0]; - first = false; - } - else - { - btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); - sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); - volume += vol; - } - } - - btVector3 getCenter() - { - return (volume > 0) ? sum / volume : ref; - } - - btScalar getVolume() - { - return volume * btScalar(1. / 6); - } - - }; - - class InertiaCallback: public btInternalTriangleIndexCallback - { - btMatrix3x3 sum; - btVector3 center; - - public: - - InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) - { - } - - virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) - { - (void) triangleIndex; - (void) partId; - btMatrix3x3 i; - btVector3 a = triangle[0] - center; - btVector3 b = triangle[1] - center; - btVector3 c = triangle[2] - center; - btVector3 abc = a + b + c; - btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); - for (int j = 0; j < 3; j++) - { - for (int k = 0; k <= j; k++) - { - i[j][k] = i[k][j] = volNeg * (center[j] * center[k] - + btScalar(0.25) * (center[j] * abc[k] + center[k] * abc[j]) - + btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) - + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); - } - } - btScalar i00 = -i[0][0]; - btScalar i11 = -i[1][1]; - btScalar i22 = -i[2][2]; - i[0][0] = i11 + i22; - i[1][1] = i22 + i00; - i[2][2] = i00 + i11; - sum[0] += i[0]; - sum[1] += i[1]; - sum[2] += i[2]; - } - - btMatrix3x3& getInertia() - { - return sum; - } - - }; - - CenterCallback centerCallback; - btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); - btVector3 center = centerCallback.getCenter(); - principal.setOrigin(center); - volume = centerCallback.getVolume(); - - InertiaCallback inertiaCallback(center); - m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); - - btMatrix3x3& i = inertiaCallback.getInertia(); - i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); - inertia.setValue(i[0][0], i[1][1], i[2][2]); - inertia /= volume; -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h index 6ff0bf5d43b..34ee7af744c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -3,24 +3,20 @@ #include "btPolyhedralConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape. -/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead. +/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. +/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data. class btConvexTriangleMeshShape : public btPolyhedralConvexShape { class btStridingMeshInterface* m_stridingMesh; public: - btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true); + btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); - class btStridingMeshInterface* getMeshInterface() - { - return m_stridingMesh; - } - const class btStridingMeshInterface* getMeshInterface() const + class btStridingMeshInterface* getStridingMesh() { return m_stridingMesh; } @@ -32,7 +28,7 @@ public: virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } //debugging - virtual const char* getName()const {return "ConvexTrimesh";} + virtual char* getName()const {return "ConvexTrimesh";} virtual int getNumVertices() const; virtual int getNumEdges() const; @@ -46,13 +42,6 @@ public: virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; - ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia - ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" - ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the - ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform - ///of the collision object by the principal transform. This method also computes the volume of the convex mesh. - void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; - }; @@ -60,4 +49,3 @@ public: #endif //CONVEX_TRIANGLEMESH_SHAPE_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp index 3afef1c7550..1666afb3b88 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -45,7 +45,7 @@ void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& } -SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) { const int cylinderUpAxis = 0; const int XX = 1; @@ -163,24 +163,24 @@ const int ZZ = 1; btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); + return CylinderLocalSupportX(getHalfExtents(),vec); } btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); + return CylinderLocalSupportZ(getHalfExtents(),vec); } btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); + return CylinderLocalSupportY(getHalfExtents(),vec); } void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { for (int i=0;i=0); btAssert(y>=0); - btAssert(xstartX) startX = quantizedAabbMin[1]; @@ -240,10 +243,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback } case 1: { - quantizedAabbMin[0]+=m_heightStickWidth/2-1; - quantizedAabbMax[0]+=m_heightStickWidth/2+1; - quantizedAabbMin[2]+=m_heightStickLength/2-1; - quantizedAabbMax[2]+=m_heightStickLength/2+1; + quantizedAabbMin[0]+=m_width/2-1; + quantizedAabbMax[0]+=m_width/2+1; + quantizedAabbMin[2]+=m_length/2-1; + quantizedAabbMax[2]+=m_length/2+1; if (quantizedAabbMin[0]>startX) startX = quantizedAabbMin[0]; @@ -257,10 +260,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback }; case 2: { - quantizedAabbMin[0]+=m_heightStickWidth/2-1; - quantizedAabbMax[0]+=m_heightStickWidth/2+1; - quantizedAabbMin[1]+=m_heightStickLength/2-1; - quantizedAabbMax[1]+=m_heightStickLength/2+1; + quantizedAabbMin[0]+=m_width/2-1; + quantizedAabbMax[0]+=m_width/2+1; + quantizedAabbMin[1]+=m_length/2-1; + quantizedAabbMax[1]+=m_length/2+1; if (quantizedAabbMin[0]>startX) startX = quantizedAabbMin[0]; @@ -287,7 +290,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback for(int x=startX; xlocalGetSupportingVertexWithoutMargin(-vec*m_transA.getBasis())); + btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis())); - return supVertexA - supVertexB; + return supVertexA + supVertexB; } void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const @@ -49,7 +49,7 @@ btScalar btMinkowskiSumShape::getMargin() const } -void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { (void)mass; btAssert(0); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h index f9c8427c2f3..198faaff9f9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef MINKOWSKI_SUM_SHAPE_H #define MINKOWSKI_SUM_SHAPE_H -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes. -class btMinkowskiSumShape : public btConvexInternalShape +/// btMinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes. +class btMinkowskiSumShape : public btConvexShape { btTransform m_transA; @@ -37,7 +37,7 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); void setTransformA(const btTransform& transA) { m_transA = transA;} void setTransformB(const btTransform& transB) { m_transB = transB;} @@ -53,7 +53,7 @@ public: const btConvexShape* getShapeA() const { return m_shapeA;} const btConvexShape* getShapeB() const { return m_shapeB;} - virtual const char* getName()const + virtual char* getName()const { return "MinkowskiSum"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp index c709205efc2..6015a618082 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -47,7 +47,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons btVector3 vec = vec0; btScalar lenSqr = vec.length2(); - if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON)) + if (lenSqr < btScalar(0.0001)) { vec.setValue(1,0,0); } else @@ -116,7 +116,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons -void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { //as an approximation, take the inertia of the box that bounds the spheres diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h index 45968f3947f..1897b474057 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -16,14 +16,13 @@ subject to the following restrictions: #ifndef MULTI_SPHERE_MINKOWSKI_H #define MULTI_SPHERE_MINKOWSKI_H -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types #define MAX_NUM_SPHERES 5 -///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes. -///It is possible to animate the spheres for deformation. -class btMultiSphereShape : public btConvexInternalShape +///btMultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex) +class btMultiSphereShape : public btConvexShape { @@ -40,7 +39,7 @@ public: btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -64,7 +63,7 @@ public: virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; } - virtual const char* getName()const + virtual char* getName()const { return "MultiSphere"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp deleted file mode 100644 index fc47e86411d..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/// This file was created by Alex Silverman - -#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h" -//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" - - -///Obtains the material for a specific triangle -const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex) -{ - const unsigned char * materialBase = 0; - int numMaterials; - PHY_ScalarType materialType; - int materialStride; - const unsigned char * triangleMaterialBase = 0; - int numTriangles; - int triangleMaterialStride; - PHY_ScalarType triangleType; - - ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, - &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID); - - // return the pointer to the place with the friction for the triangle - // TODO: This depends on whether it's a moving mesh or not - // BUG IN GIMPACT - //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]); - int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)])); - btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride])); - return (matVal); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h deleted file mode 100644 index 2f108020cdf..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/// This file was created by Alex Silverman - -#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H -#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H - -#include "btBvhTriangleMeshShape.h" -#include "btMaterial.h" - -///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution. -ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape -{ - btAlignedObjectArray m_materialList; - int ** m_triangleMaterials; - -public: - - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {} - btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true): - btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh) - { - btVector3 m_triangle[3]; - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - - //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); - - for(int i = 0; i < meshInterface->getNumSubParts(); i++) - { - m_meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - i); - //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16)); - } - } - - ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb - btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true): - btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh) - { - btVector3 m_triangle[3]; - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - - //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); - - for(int i = 0; i < meshInterface->getNumSubParts(); i++) - { - m_meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - i); - //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16)); - } - } - - virtual ~btMultimaterialTriangleMeshShape() - { -/* - for(int i = 0; i < m_meshInterface->getNumSubParts(); i++) - { - btAlignedFree(m_materialValues[i]); - m_materialLookup[i] = NULL; - } - btAlignedFree(m_materialValues); - m_materialLookup = NULL; -*/ - } - virtual int getShapeType() const - { - return MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; - } - - //debugging - virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";} - - ///Obtains the material for a specific triangle - const btMaterial * getMaterialProperties(int partID, int triIndex); - -} -; - -#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp index a248c55b571..44438a24455 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -19,12 +19,13 @@ subject to the following restrictions: #include "LinearMath/btIDebugDraw.h" -btOptimizedBvh::btOptimizedBvh() -{ -} -btOptimizedBvh::~btOptimizedBvh() -{ +btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false), + m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) + //m_traversalMode(TRAVERSAL_STACKLESS) + //m_traversalMode(TRAVERSAL_RECURSIVE) +{ + } @@ -79,7 +80,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback { QuantizedNodeArray& m_triangleNodes; - const btQuantizedBvh* m_optimizedTree; // for quantization + const btOptimizedBvh* m_optimizedTree; // for quantization QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) { @@ -88,16 +89,14 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized return *this; } - QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree) + QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree) :m_triangleNodes(triangleNodes),m_optimizedTree(tree) { } virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) { - // The partId and triangle index must fit in the same (positive) integer - btAssert(partId < (1<=0); @@ -112,29 +111,10 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized aabbMin.setMin(triangle[2]); aabbMax.setMax(triangle[2]); - //PCK: add these checks for zero dimensions of aabb - const btScalar MIN_AABB_DIMENSION = btScalar(0.002); - const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); - if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) - { - aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); - aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); - } - if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) - { - aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); - aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); - } - if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) - { - aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); - aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); - } + m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); + m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); - m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); - m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); - - node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; + node.m_escapeIndexOrTriangleIndex = triangleIndex; m_triangleNodes.push_back(node); } @@ -190,45 +170,10 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized subtree.m_rootNodeIndex = 0; subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); } - - //PCK: update the copy of the size - m_subtreeHeaderCount = m_SubtreeHeaders.size(); - - //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary - m_quantizedLeafNodes.clear(); - m_leafNodes.clear(); } - -void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) -{ - if (m_useQuantization) - { - - setQuantizationValues(aabbMin,aabbMax); - - updateBvhNodes(meshInterface,0,m_curNodeIndex,0); - - ///now update all subtree headers - - int i; - for (i=0;im_SubtreeHeaders.size();i++) { btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - //PCK: unsigned instead of bool - unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap != 0) + bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap) { updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); @@ -268,23 +212,36 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b } +///just for debugging, to visualize the individual patches/subtrees +#ifdef DEBUG_PATCH_COLORS +btVector3 color[4]= +{ + btVector3(255,0,0), + btVector3(0,255,0), + btVector3(0,0,255), + btVector3(0,255,255) +}; +#endif //DEBUG_PATCH_COLORS + + void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) { (void)index; btAssert(m_useQuantization); - int curNodeSubPart=-1; + int nodeSubPart=0; //get access info to trianglemesh data - const unsigned char *vertexbase = 0; - int numverts = 0; - PHY_ScalarType type = PHY_INTEGER; - int stride = 0; - const unsigned char *indexbase = 0; - int indexstride = 0; - int numfaces = 0; - PHY_ScalarType indicestype = PHY_INTEGER; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); btVector3 triangleVerts[3]; btVector3 aabbMin,aabbMax; @@ -299,26 +256,16 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f if (curNode.isLeafNode()) { //recalc aabb from triangle data - int nodeSubPart = curNode.getPartId(); int nodeTriangleIndex = curNode.getTriangleIndex(); - if (nodeSubPart != curNodeSubPart) - { - if (curNodeSubPart >= 0) - meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); - meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); - - curNodeSubPart = nodeSubPart; - btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); - } //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, - unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); for (int j=2;j>=0;j--) { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + int graphicsindex = gfxbase[j]; btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); #ifdef DEBUG_PATCH_COLORS btVector3 mycolor = color[index&3]; @@ -345,8 +292,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f aabbMin.setMin(triangleVerts[2]); aabbMax.setMax(triangleVerts[2]); - quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0); - quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1); + quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin); + quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax); } else { @@ -374,17 +321,525 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f } - if (curNodeSubPart >= 0) - meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + meshInterface->unLockReadOnlyVertexBase(nodeSubPart); } -///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' -btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) { - btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian); - - //we don't add additional data so just do a static upcast - return static_cast(bvh); + //enlarge the AABB to avoid division by zero when initializing the quantization values + btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); + m_bvhAabbMin = bvhAabbMin - clampValue; + m_bvhAabbMax = bvhAabbMax + clampValue; + btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize; +} + + +void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface) +{ + if (m_useQuantization) + { + //calculate new aabb + btVector3 aabbMin,aabbMax; + meshInterface->calculateAabbBruteForce(aabbMin,aabbMax); + + setQuantizationValues(aabbMin,aabbMax); + + updateBvhNodes(meshInterface,0,m_curNodeIndex,0); + + ///now update all subtree headers + + int i; + for (i=0;i gMaxStackDepth) + gMaxStackDepth = gStackDepth; +#endif //DEBUG_TREE_BUILDING + + + int splitAxis, splitIndex, i; + int numIndices =endIndex-startIndex; + int curIndex = m_curNodeIndex; + + assert(numIndices>0); + + if (numIndices==1) + { +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); + + m_curNodeIndex++; + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + splitAxis = calcSplittingAxis(startIndex,endIndex); + + splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); + + int internalNodeIndex = m_curNodeIndex; + + setInternalNodeAabbMax(m_curNodeIndex,btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30))); + setInternalNodeAabbMin(m_curNodeIndex,btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30))); + + for (i=startIndex;im_escapeIndex; + + int leftChildNodexIndex = m_curNodeIndex; + + //build left child tree + buildTree(startIndex,splitIndex); + + int rightChildNodexIndex = m_curNodeIndex; + //build right child tree + buildTree(splitIndex,endIndex); + +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + int escapeIndex = m_curNodeIndex - curIndex; + + if (m_useQuantization) + { + //escapeIndex is the number of nodes of this subtree + const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); + const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; + if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) + { + updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); + } + } + + setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); + +} + +void btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) +{ + btAssert(m_useQuantization); + + btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; + int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); + int leftSubTreeSizeInBytes = leftSubTreeSize * sizeof(btQuantizedBvhNode); + + btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; + int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); + int rightSubTreeSizeInBytes = rightSubTreeSize * sizeof(btQuantizedBvhNode); + + if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(leftChildNode); + subtree.m_rootNodeIndex = leftChildNodexIndex; + subtree.m_subtreeSize = leftSubTreeSize; + } + + if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(rightChildNode); + subtree.m_rootNodeIndex = rightChildNodexIndex; + subtree.m_subtreeSize = rightSubTreeSize; + } +} + + +int btOptimizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) +{ + int i; + int splitIndex =startIndex; + int numIndices = endIndex - startIndex; + btScalar splitValue; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + for (i=startIndex;i splitValue) + { + //swap + swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + btAssert(!unbal); + + return splitIndex; +} + + +int btOptimizedBvh::calcSplittingAxis(int startIndex,int endIndex) +{ + int i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + int numIndices = endIndex-startIndex; + + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); + isLeafNode = rootNode->m_escapeIndex == -1; + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + if (aabbOverlap || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +/* +///this was the original recursive traversal, before we optimized towards stackless traversal +void btOptimizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); + if (aabbOverlap) + { + isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); + if (isLeafNode) + { + nodeCallback->processNode(rootNode); + } else + { + walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); + walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); + } + } + +} +*/ + +void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + bool aabbOverlap, isLeafNode; + + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); + isLeafNode = currentNode->isLeafNode(); + + if (aabbOverlap) + { + if (isLeafNode) + { + nodeCallback->processNode(0,currentNode->getTriangleIndex()); + } else + { + //process left and right children + const btQuantizedBvhNode* leftChildNode = currentNode+1; + walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + + const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); + walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + } + } +} + + + + + + + +void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool aabbOverlap, isLeafNode; + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + assert (walkIterations < subTreeSize); + + walkIterations++; + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(0,rootNode->getTriangleIndex()); + } + + if (aabbOverlap || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +//This traversal can be called from Playstation 3 SPU +void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + int i; + + + for (i=0;im_SubtreeHeaders.size();i++) + { + const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap) + { + walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + subtree.m_rootNodeIndex, + subtree.m_rootNodeIndex+subtree.m_subtreeSize); + } + } +} + + + + +void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + (void)nodeCallback; + (void)aabbMin; + (void)aabbMax; + //not yet, please use aabb + btAssert(0); +} + + +void btOptimizedBvh::quantizeWithClamp(unsigned short* out, const btVector3& point) const +{ + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; + out[0] = (unsigned short)(v.getX()+0.5f); + out[1] = (unsigned short)(v.getY()+0.5f); + out[2] = (unsigned short)(v.getZ()+0.5f); +} + +btVector3 btOptimizedBvh::unQuantize(const unsigned short* vecIn) const +{ + btVector3 vecOut; + vecOut.setValue( + (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), + (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), + (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); + vecOut += m_bvhAabbMin; + return vecOut; +} + + +void btOptimizedBvh::swapLeafNodes(int i,int splitIndex) +{ + if (m_useQuantization) + { + btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; + m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; + m_quantizedLeafNodes[splitIndex] = tmp; + } else + { + btOptimizedBvhNode tmp = m_leafNodes[i]; + m_leafNodes[i] = m_leafNodes[splitIndex]; + m_leafNodes[splitIndex] = tmp; + } +} + +void btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) +{ + if (m_useQuantization) + { + m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; + } else + { + m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; + } } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h index d7536417d7e..d5159586344 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -16,48 +16,315 @@ subject to the following restrictions: #ifndef OPTIMIZED_BVH_H #define OPTIMIZED_BVH_H -#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" + +#include "../../LinearMath/btVector3.h" + + +//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp + + class btStridingMeshInterface; +//Note: currently we have 16 bytes per quantized node +#define MAX_SUBTREE_SIZE_IN_BYTES 2048 -///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface. -ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode { + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrTriangleIndex; + + bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrTriangleIndex >= 0); + } + int getEscapeIndex() const + { + btAssert(!isLeafNode()); + return -m_escapeIndexOrTriangleIndex; + } + int getTriangleIndex() const + { + btAssert(isLeafNode()); + return m_escapeIndexOrTriangleIndex; + } +} +; + +/// btOptimizedBvhNode contains both internal and leaf node information. +/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. +ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode +{ + //32 bytes + btVector3 m_aabbMinOrg; + btVector3 m_aabbMaxOrg; + + //4 + int m_escapeIndex; + + //8 + //for child nodes + int m_subPart; + int m_triangleIndex; + int m_padding[5];//bad, due to alignment + + +}; + + +///btBvhSubtreeInfo provides info to gather a subtree of limited size +ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo +{ public: - BT_DECLARE_ALIGNED_ALLOCATOR(); + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes, points to the root of the subtree + int m_rootNodeIndex; + //4 bytes + int m_subtreeSize; + int m_padding[3]; + + + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) + { + m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; + m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; + m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; + m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; + m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; + m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; + } +} +; + + +class btNodeOverlapCallback +{ +public: + virtual ~btNodeOverlapCallback() {}; + + virtual void processNode(int subPart, int triangleIndex) = 0; +}; + +#include "../../LinearMath/btAlignedAllocator.h" +#include "../../LinearMath/btAlignedObjectArray.h" + + + +///for code readability: +typedef btAlignedObjectArray NodeArray; +typedef btAlignedObjectArray QuantizedNodeArray; +typedef btAlignedObjectArray BvhSubtreeInfoArray; + + +///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future) +ATTRIBUTE_ALIGNED16(class) btOptimizedBvh +{ + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + + QuantizedNodeArray m_quantizedLeafNodes; + + QuantizedNodeArray m_quantizedContiguousNodes; + + int m_curNodeIndex; + + + //quantization data + bool m_useQuantization; + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; + + enum btTraversalMode + { + TRAVERSAL_STACKLESS = 0, + TRAVERSAL_STACKLESS_CACHE_FRIENDLY, + TRAVERSAL_RECURSIVE + }; + + btTraversalMode m_traversalMode; + + + + + BvhSubtreeInfoArray m_SubtreeHeaders; + + + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) + ///this might be refactored into a virtual, it is usually not calculated at run-time + void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) + { + if (m_useQuantization) + { + quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; + + } + } + void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) + { + if (m_useQuantization) + { + quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; + } + } + + btVector3 getAabbMin(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMinOrg; + + } + btVector3 getAabbMax(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMaxOrg; + + } + + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); + + void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) + { + if (m_useQuantization) + { + m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; + } + else + { + m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; + } + + } + + void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) + { + if (m_useQuantization) + { + unsigned short int quantizedAabbMin[3]; + unsigned short int quantizedAabbMax[3]; + quantizeWithClamp(quantizedAabbMin,newAabbMin); + quantizeWithClamp(quantizedAabbMax,newAabbMax); + for (int i=0;i<3;i++) + { + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; + + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; + + } + } else + { + //non-quantized + m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); + m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); + } + } + + void swapLeafNodes(int firstIndex,int secondIndex); + + void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); protected: -public: + + void buildTree (int startIndex,int endIndex); + + int calcSplittingAxis(int startIndex,int endIndex); + + int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); + + void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; + + ///tree traversal designed for small-memory processors like PS3 SPU + void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; + + + inline bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } + + void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); + +public: btOptimizedBvh(); virtual ~btOptimizedBvh(); void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); - void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax); + void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void quantizeWithClamp(unsigned short* out, const btVector3& point) const; + + btVector3 unQuantize(const unsigned short* vecIn) const; + + ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. + void setTraversalMode(btTraversalMode traversalMode) + { + m_traversalMode = traversalMode; + } + + void refit(btStridingMeshInterface* triangles); void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); - /// Data buffer MUST be 16 byte aligned - virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) - { - return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + QuantizedNodeArray& getQuantizedNodeArray() + { + return m_quantizedContiguousNodes; } - ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' - static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + BvhSubtreeInfoArray& getSubtreeInfoArray() + { + return m_SubtreeHeaders; + } - -}; +} +; #endif //OPTIMIZED_BVH_H - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp index 71c3af38a02..bbc4ba62af6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -13,7 +13,7 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" +#include btPolyhedralConvexShape::btPolyhedralConvexShape() :m_localAabbMin(1,1,1), @@ -95,7 +95,7 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin( -void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { //not yet, return box inertia @@ -128,46 +128,10 @@ void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMi -void btPolyhedralConvexShape::setLocalScaling(const btVector3& scaling) -{ - btConvexInternalShape::setLocalScaling(scaling); - recalcLocalAabb(); -} void btPolyhedralConvexShape::recalcLocalAabb() { m_isLocalAabbValid = true; - - #if 1 - static const btVector3 _directions[] = - { - btVector3( 1., 0., 0.), - btVector3( 0., 1., 0.), - btVector3( 0., 0., 1.), - btVector3( -1., 0., 0.), - btVector3( 0., -1., 0.), - btVector3( 0., 0., -1.) - }; - - btVector3 _supporting[] = - { - btVector3( 0., 0., 0.), - btVector3( 0., 0., 0.), - btVector3( 0., 0., 0.), - btVector3( 0., 0., 0.), - btVector3( 0., 0., 0.), - btVector3( 0., 0., 0.) - }; - - batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); - - for ( int i = 0; i < 3; ++i ) - { - m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; - m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; - } - - #else for (int i=0;i<3;i++) { @@ -179,8 +143,6 @@ void btPolyhedralConvexShape::recalcLocalAabb() tmp = localGetSupportingVertex(vec); m_localAabbMin[i] = tmp[i]-m_collisionMargin; } - #endif } - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h index 4c4ce7feaa7..c35f7512663 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -16,14 +16,13 @@ subject to the following restrictions: #ifndef BU_SHAPE #define BU_SHAPE -#include "LinearMath/btPoint3.h" -#include "LinearMath/btMatrix3x3.h" -#include "LinearMath/btAabbUtil2.h" -#include "btConvexInternalShape.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "btConvexShape.h" -///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes. -class btPolyhedralConvexShape : public btConvexInternalShape +///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. +class btPolyhedralConvexShape : public btConvexShape { protected: @@ -39,7 +38,7 @@ public: virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const @@ -47,14 +46,33 @@ public: //lazy evaluation of local aabb btAssert(m_isLocalAabbValid); - btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); + + btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX()); + btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY()); + btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ()); + + + btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + extent += btVector3(margin,margin,margin); + + aabbMin = center - extent; + aabbMax = center + extent; + + } virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - virtual void setLocalScaling(const btVector3& scaling); - void recalcLocalAabb(); virtual int getNumVertices() const = 0 ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp deleted file mode 100644 index 5a17b4e2df0..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btScaledBvhTriangleMeshShape.h" - -btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling) -:m_bvhTriMeshShape(childShape), -m_localScaling(localScaling) -{ - -} - -btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape() -{ -} - - -class btScaledTriangleCallback : public btTriangleCallback -{ - btTriangleCallback* m_originalCallback; - - btVector3 m_localScaling; - -public: - - btScaledTriangleCallback(btTriangleCallback* originalCallback,btVector3 localScaling) - :m_originalCallback(originalCallback), - m_localScaling(localScaling) - { - } - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) - { - btVector3 newTriangle[3]; - newTriangle[0] = triangle[0]*m_localScaling; - newTriangle[1] = triangle[1]*m_localScaling; - newTriangle[2] = triangle[2]*m_localScaling; - m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex); - } -}; - -void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - btScaledTriangleCallback scaledCallback(callback,m_localScaling); - - btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ()); - btVector3 scaledAabbMin = aabbMin * invLocalScaling; - btVector3 scaledAabbMax = aabbMax * invLocalScaling; - m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax); -} - - -void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const -{ - btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin(); - btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax(); - localAabbMin *= m_localScaling; - localAabbMax *= m_localScaling; - - btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); - btScalar margin = m_bvhTriMeshShape->getMargin(); - localHalfExtents += btVector3(margin,margin,margin); - btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - aabbMin = center - extent; - aabbMax = center + extent; - -} - -void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} - -const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const -{ - return m_localScaling; -} - -void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - ///don't make this a movable object! - btAssert(0); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h deleted file mode 100644 index 8e1d29fc005..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H -#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H - -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" - - -///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape. -///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling' -ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape -{ - - - btVector3 m_localScaling; - - btBvhTriangleMeshShape* m_bvhTriMeshShape; - -public: - - - btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling); - - virtual ~btScaledBvhTriangleMeshShape(); - - virtual int getShapeType() const - { - //use un-used 'FAST_CONCAVE_MESH_PROXYTYPE' for now, later add SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE to btBroadphaseProxy.h - return FAST_CONCAVE_MESH_PROXYTYPE; - } - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - //debugging - virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} - -}; - -#endif //BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp deleted file mode 100644 index a87b87f1a6f..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* -btbtShapeHull implemented by John McCutchan. - -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btShapeHull.h" -#include "LinearMath/btConvexHull.h" - -#define NUM_UNITSPHERE_POINTS 42 - -static btVector3 btUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = -{ - btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), - btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), - btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), - btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), - btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), - btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), - btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), - btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), - btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), - btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), - btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), - btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), - btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), - btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), - btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), - btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), - btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), - btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), - btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), - btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), - btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), - btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), - btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), - btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), - btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), - btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), - btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), - btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), - btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), - btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), - btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), - btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), - btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), - btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), - btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), - btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), - btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), - btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), - btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), - btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), - btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), - btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) -}; - -btShapeHull::btShapeHull (const btConvexShape* shape) -{ - m_shape = shape; - m_vertices.clear (); - m_indices.clear(); - m_numIndices = 0; -} - -btShapeHull::~btShapeHull () -{ - m_indices.clear(); - m_vertices.clear (); -} - -bool -btShapeHull::buildHull (btScalar /*margin*/) -{ - int numSampleDirections = NUM_UNITSPHERE_POINTS; - { - int numPDA = m_shape->getNumPreferredPenetrationDirections(); - if (numPDA) - { - for (int i=0;igetPreferredPenetrationDirection(i,norm); - btUnitSpherePoints[numSampleDirections] = norm; - numSampleDirections++; - } - } - } - - btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; - int i; - for (i = 0; i < numSampleDirections; i++) - { - supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]); - } - - HullDesc hd; - hd.mFlags = QF_TRIANGLES; - hd.mVcount = static_cast(numSampleDirections); - -#ifdef BT_USE_DOUBLE_PRECISION - hd.mVertices = &supportPoints[0]; - hd.mVertexStride = sizeof(btVector3); -#else - hd.mVertices = &supportPoints[0]; - hd.mVertexStride = sizeof (btVector3); -#endif - - HullLibrary hl; - HullResult hr; - if (hl.CreateConvexHull (hd, hr) == QE_FAIL) - { - return false; - } - - m_vertices.resize (static_cast(hr.mNumOutputVertices)); - - - for (i = 0; i < static_cast(hr.mNumOutputVertices); i++) - { - m_vertices[i] = hr.m_OutputVertices[i]; - } - m_numIndices = hr.mNumIndices; - m_indices.resize(static_cast(m_numIndices)); - for (i = 0; i < static_cast(m_numIndices); i++) - { - m_indices[i] = hr.m_Indices[i]; - } - - // free temporary hull result that we just copied - hl.ReleaseResult (hr); - - return true; -} - -int -btShapeHull::numTriangles () const -{ - return static_cast(m_numIndices / 3); -} - -int -btShapeHull::numVertices () const -{ - return m_vertices.size (); -} - -int -btShapeHull::numIndices () const -{ - return static_cast(m_numIndices); -} - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h deleted file mode 100644 index 583c6b99eb6..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -btShapeHull implemented by John McCutchan. - -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef _SHAPE_HULL_H -#define _SHAPE_HULL_H - -#include "LinearMath/btAlignedObjectArray.h" -#include "BulletCollision/CollisionShapes/btConvexShape.h" - - -///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices. -///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object. -///It approximates the convex hull using the supporting vertex of 42 directions. -class btShapeHull -{ -public: - btShapeHull (const btConvexShape* shape); - ~btShapeHull (); - - bool buildHull (btScalar margin); - - int numTriangles () const; - int numVertices () const; - int numIndices () const; - - const btVector3* getVertexPointer() const - { - return &m_vertices[0]; - } - const unsigned int* getIndexPointer() const - { - return &m_indices[0]; - } - -protected: - btAlignedObjectArray m_vertices; - btAlignedObjectArray m_indices; - unsigned int m_numIndices; - const btConvexShape* m_shape; -}; - -#endif //_SHAPE_HULL_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp index 15cfe432e27..ca65dd03f3e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -68,7 +68,7 @@ void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& a -void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin(); inertia.setValue(elem,elem,elem); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h index 83421d69e0d..66521664087 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h @@ -16,17 +16,15 @@ subject to the following restrictions: #ifndef SPHERE_MINKOWSKI_H #define SPHERE_MINKOWSKI_H -#include "btConvexInternalShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexShape.h" +#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -///The btSphereShape implements an implicit sphere, centered around a local origin with radius. -ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape +///btSphereShape implements an implicit (getSupportingVertex) Sphere +ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexShape { public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - btSphereShape (btScalar radius); @@ -36,26 +34,26 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual int getShapeType() const { return SPHERE_SHAPE_PROXYTYPE; } - btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();} + btScalar getRadius() const { return m_implicitShapeDimensions.getX();} //debugging - virtual const char* getName()const {return "SPHERE";} + virtual char* getName()const {return "SPHERE";} virtual void setMargin(btScalar margin) { - btConvexInternalShape::setMargin(margin); + btConvexShape::setMargin(margin); } virtual btScalar getMargin() const { //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case //this means, non-uniform scaling is not supported anymore - return getRadius(); + return m_localScaling.getX() * getRadius() + btConvexShape::getMargin(); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp index 3c98ca08ddc..4fbaafa1b93 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp @@ -19,11 +19,10 @@ subject to the following restrictions: btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant) -:m_planeNormal(planeNormal.normalized()), +:m_planeNormal(planeNormal), m_planeConstant(planeConstant), m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.)) { - // btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) ); } @@ -87,7 +86,7 @@ void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const } -void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { (void)mass; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h index ddebca73dea..f59cc0c3347 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -19,7 +19,8 @@ subject to the following restrictions: #include "btConcaveShape.h" -///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane. +///StaticPlaneShape simulates an 'infinite' plane by dynamically reporting triangles approximated by intersection of the plane with the AABB. +///Assumed is that the other objects is not also infinite, so a reasonable sized AABB. class btStaticPlaneShape : public btConcaveShape { protected: @@ -45,23 +46,14 @@ public: virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; - const btVector3& getPlaneNormal() const - { - return m_planeNormal; - } - - const btScalar& getPlaneConstant() const - { - return m_planeConstant; - } //debugging - virtual const char* getName()const {return "STATICPLANE";} + virtual char* getName()const {return "STATICPLANE";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp index 752a5fc1dfa..03ca1ae7736 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -51,7 +51,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde { for (gfxindex=0;gfxindexprocessAllTriangles(&triBuf,aabbMin, aabbMax); +// for (int i=0;iprocessAllTriangles(&triBuf,aabbMin, aabbMax); -/// for (int i=0;i IndexedMeshArray; -///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays. +///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. ///Additional meshes can be added using addIndexedMesh ///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. ///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface { -protected: IndexedMeshArray m_indexedMeshes; - int m_pad[2]; - int m_hasAabb; // using int instead of bool to maintain alignment - btVector3 m_aabbMin; - btVector3 m_aabbMax; + int m_pad[3]; + public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btTriangleIndexVertexArray() : m_hasAabb(0) + btTriangleIndexVertexArray() { } - virtual ~btTriangleIndexVertexArray(); - //just to be backwards compatible - btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); + btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); - void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER) + void addIndexedMesh(const btIndexedMesh& mesh) { m_indexedMeshes.push_back(mesh); - m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType; } @@ -105,10 +91,6 @@ public: virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateIndices(int numindices){(void) numindices;} - virtual bool hasPremadeAabb() const; - virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ); - virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const; - } ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp deleted file mode 100644 index 492854ff646..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -///This file was created by Alex Silverman - -#include "btTriangleIndexVertexMaterialArray.h" - -btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, - int numVertices,btScalar* vertexBase,int vertexStride, - int numMaterials, unsigned char* materialBase, int materialStride, - int* triangleMaterialsBase, int materialIndexStride) : -btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride) -{ - btMaterialProperties mat; - - mat.m_numMaterials = numMaterials; - mat.m_materialBase = materialBase; - mat.m_materialStride = materialStride; -#ifdef BT_USE_DOUBLE_PRECISION - mat.m_materialType = PHY_DOUBLE; -#else - mat.m_materialType = PHY_FLOAT; -#endif - - mat.m_numTriangles = numTriangles; - mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase; - mat.m_triangleMaterialStride = materialIndexStride; - mat.m_triangleType = PHY_INTEGER; - - addMaterialProperties(mat); -} - - -void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, - unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) -{ - btAssert(subpart< getNumSubParts() ); - - btMaterialProperties& mats = m_materials[subpart]; - - numMaterials = mats.m_numMaterials; - (*materialBase) = (unsigned char *) mats.m_materialBase; -#ifdef BT_USE_DOUBLE_PRECISION - materialType = PHY_DOUBLE; -#else - materialType = PHY_FLOAT; -#endif - materialStride = mats.m_materialStride; - - numTriangles = mats.m_numTriangles; - (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase; - triangleMaterialStride = mats.m_triangleMaterialStride; - triangleType = mats.m_triangleType; -} - -void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, - const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) -{ - btMaterialProperties& mats = m_materials[subpart]; - - numMaterials = mats.m_numMaterials; - (*materialBase) = (const unsigned char *) mats.m_materialBase; -#ifdef BT_USE_DOUBLE_PRECISION - materialType = PHY_DOUBLE; -#else - materialType = PHY_FLOAT; -#endif - materialStride = mats.m_materialStride; - - numTriangles = mats.m_numTriangles; - (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase; - triangleMaterialStride = mats.m_triangleMaterialStride; - triangleType = mats.m_triangleType; -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h deleted file mode 100644 index 69a2e631458..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h +++ /dev/null @@ -1,84 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -///This file was created by Alex Silverman - -#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H -#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H - -#include "btTriangleIndexVertexArray.h" - - -ATTRIBUTE_ALIGNED16( struct) btMaterialProperties -{ - ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution - int m_numMaterials; - const unsigned char * m_materialBase; - int m_materialStride; - PHY_ScalarType m_materialType; - ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're - /// padding the structure, it can be reproduced at no real cost - ///m_triangleMaterials =====> 1 integer value makes up one entry - /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5 - int m_numTriangles; - const unsigned char * m_triangleMaterialsBase; - int m_triangleMaterialStride; - ///m_triangleType <========== Automatically set in addMaterialProperties - PHY_ScalarType m_triangleType; -}; - -typedef btAlignedObjectArray MaterialArray; - -///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray -///The addition of a material array allows for the utilization of the partID and -///triangleIndex that are returned in the ContactAddedCallback. As with -///TriangleIndexVertexArray, no duplicate is made of the material data, so it -///is the users responsibility to maintain the array during the lifetime of the -///TriangleIndexVertexMaterialArray. -ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray -{ -protected: - MaterialArray m_materials; - -public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - btTriangleIndexVertexMaterialArray() - { - } - - btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, - int numVertices,btScalar* vertexBase,int vertexStride, - int numMaterials, unsigned char* materialBase, int materialStride, - int* triangleMaterialsBase, int materialIndexStride); - - virtual ~btTriangleIndexVertexMaterialArray() {} - - void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER) - { - m_materials.push_back(mat); - m_materials[m_materials.size()-1].m_triangleType = triangleType; - } - - virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, - unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0); - - virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, - const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0); - -} -; - -#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp index bcea97052d6..98c54ef45f8 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp @@ -14,102 +14,47 @@ subject to the following restrictions: */ #include "btTriangleMesh.h" +#include - -btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices) -:m_use32bitIndices(use32bitIndices), -m_use4componentVertices(use4componentVertices) +btTriangleMesh::btTriangleMesh () { - btIndexedMesh meshIndex; - meshIndex.m_numTriangles = 0; - meshIndex.m_numVertices = 0; - meshIndex.m_indexType = PHY_INTEGER; - meshIndex.m_triangleIndexBase = 0; - meshIndex.m_triangleIndexStride = 3*sizeof(int); - meshIndex.m_vertexBase = 0; - meshIndex.m_vertexStride = sizeof(btVector3); - m_indexedMeshes.push_back(meshIndex); - - if (m_use32bitIndices) - { - m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3; - m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; - m_indexedMeshes[0].m_indexType = PHY_INTEGER; - m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int); - } else - { - m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3; - m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; - m_indexedMeshes[0].m_indexType = PHY_SHORT; - m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int); - } - - if (m_use4componentVertices) - { - m_indexedMeshes[0].m_numVertices = m_4componentVertices.size(); - m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; - m_indexedMeshes[0].m_vertexStride = sizeof(btVector3); - } else - { - m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3; - m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; - m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar); - } - } - -void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) +void btTriangleMesh::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) { - m_indexedMeshes[0].m_numTriangles++; - m_indexedMeshes[0].m_numVertices+=3; + (void)subpart; + numverts = m_vertices.size(); + *vertexbase = (unsigned char*)&m_vertices[0]; + type = PHY_FLOAT; + stride = sizeof(btVector3); - if (m_use4componentVertices) - { - m_4componentVertices.push_back(vertex0); - m_4componentVertices.push_back(vertex1); - m_4componentVertices.push_back(vertex2); - m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; - } else - { - m_3componentVertices.push_back(vertex0.getX()); - m_3componentVertices.push_back(vertex0.getY()); - m_3componentVertices.push_back(vertex0.getZ()); + numfaces = m_indices.size()/3; + *indexbase = (unsigned char*) &m_indices[0]; + indicestype = PHY_INTEGER; + indexstride = 3*sizeof(int); - m_3componentVertices.push_back(vertex1.getX()); - m_3componentVertices.push_back(vertex1.getY()); - m_3componentVertices.push_back(vertex1.getZ()); - - m_3componentVertices.push_back(vertex2.getX()); - m_3componentVertices.push_back(vertex2.getY()); - m_3componentVertices.push_back(vertex2.getZ()); - m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; - } - - if (m_use32bitIndices) - { - int curIndex = m_32bitIndices.size(); - m_32bitIndices.push_back(curIndex++); - m_32bitIndices.push_back(curIndex++); - m_32bitIndices.push_back(curIndex++); - m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; - } else - { - short curIndex = static_cast(m_16bitIndices.size()); - m_16bitIndices.push_back(curIndex++); - m_16bitIndices.push_back(curIndex++); - m_16bitIndices.push_back(curIndex++); - m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; - } } -int btTriangleMesh::getNumTriangles() const +void btTriangleMesh::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const { - if (m_use32bitIndices) - { - return m_32bitIndices.size() / 3; - } - return m_16bitIndices.size() / 3; + (void)subpart; + numverts = m_vertices.size(); + *vertexbase = (unsigned char*)&m_vertices[0]; + type = PHY_FLOAT; + stride = sizeof(btVector3); + + numfaces = m_indices.size()/3; + *indexbase = (unsigned char*) &m_indices[0]; + indicestype = PHY_INTEGER; + indexstride = 3*sizeof(int); + +} + + + +int btTriangleMesh::getNumSubParts() const +{ + return 1; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index e4d41d5ede0..525f5336b48 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -17,42 +17,54 @@ subject to the following restrictions: #ifndef TRIANGLE_MESH_H #define TRIANGLE_MESH_H -#include "btTriangleIndexVertexArray.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btAlignedObjectArray.h" +#include "btStridingMeshInterface.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btAlignedObjectArray.h" -///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape. -///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices. -///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface. -///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same. -class btTriangleMesh : public btTriangleIndexVertexArray +///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the btTriangleMeshShape. +class btTriangleMesh : public btStridingMeshInterface { - btAlignedObjectArray m_4componentVertices; - btAlignedObjectArray m_3componentVertices; - - btAlignedObjectArray m_32bitIndices; - btAlignedObjectArray m_16bitIndices; - bool m_use32bitIndices; - bool m_use4componentVertices; - + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_indices; public: - btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); + btTriangleMesh (); - bool getUse32bitIndices() const + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) { - return m_use32bitIndices; + int curIndex = m_indices.size(); + m_vertices.push_back(vertex0); + m_vertices.push_back(vertex1); + m_vertices.push_back(vertex2); + + m_indices.push_back(curIndex++); + m_indices.push_back(curIndex++); + m_indices.push_back(curIndex++); } - bool getUse4componentVertices() const + int getNumTriangles() const { - return m_use4componentVertices; + return m_indices.size() / 3; } - - void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2); - - int getNumTriangles() const; + + +//StridingMeshInterface interface implementation + + virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); + + virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; + + /// unLockVertexBase finishes the access to a subpart of the triangle mesh + /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished + virtual void unLockVertexBase(int subpart) {(void) subpart;} + + virtual void unLockReadOnlyVertexBase(int subpart) const { (void) subpart;} + + /// getNumSubParts returns the number of seperate subparts + /// each subpart has a continuous array of vertices and indices + virtual int getNumSubParts() const; + virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateIndices(int numindices){(void) numindices;} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp index 0a2c77096d1..ed81897b515 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -20,18 +20,12 @@ subject to the following restrictions: #include "LinearMath/btAabbUtil2.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "stdio.h" btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) : m_meshInterface(meshInterface) { - if(meshInterface->hasPremadeAabb()) - { - meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax); - } - else - { - recalcLocalAabb(); - } + recalcLocalAabb(); } @@ -47,7 +41,6 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); btMatrix3x3 abs_b = trans.getBasis().absolute(); @@ -57,10 +50,12 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), abs_b[1].dot(localHalfExtents), abs_b[2].dot(localHalfExtents)); + extent += btVector3(getMargin(),getMargin(),getMargin()); + aabbMin = center - extent; aabbMax = center + extent; - + } void btTriangleMeshShape::recalcLocalAabb() @@ -143,7 +138,6 @@ const btVector3& btTriangleMeshShape::getLocalScaling() const //#define DEBUG_TRIANGLE_MESH - void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const { struct FilteredCallback : public btInternalTriangleIndexCallback @@ -180,7 +174,8 @@ void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const -void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const + +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) { (void)mass; //moving concave objects not supported diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index c9eabafe290..e6173e47640 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -20,19 +20,17 @@ subject to the following restrictions: #include "btStridingMeshInterface.h" -///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. +///Concave triangle mesh. Uses an interface to access the triangles to allow for sharing graphics/physics triangles. class btTriangleMeshShape : public btConcaveShape { protected: btVector3 m_localAabbMin; btVector3 m_localAabbMax; btStridingMeshInterface* m_meshInterface; - - ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. - ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! - btTriangleMeshShape(btStridingMeshInterface* meshInterface); + public: + btTriangleMeshShape(btStridingMeshInterface* meshInterface); virtual ~btTriangleMeshShape(); @@ -46,11 +44,16 @@ public: void recalcLocalAabb(); + virtual int getShapeType() const + { + return TRIANGLE_MESH_SHAPE_PROXYTYPE; + } + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; @@ -65,19 +68,9 @@ public: return m_meshInterface; } - const btVector3& getLocalAabbMin() const - { - return m_localAabbMin; - } - const btVector3& getLocalAabbMax() const - { - return m_localAabbMax; - } - - //debugging - virtual const char* getName()const {return "TRIANGLEMESH";} + virtual char* getName()const {return "TRIANGLEMESH";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h index ba7aa0c32a0..c2e240c051c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -27,6 +27,7 @@ public: btVector3 m_vertices1[3]; + virtual int getNumVertices() const { return 3; @@ -83,13 +84,14 @@ public: - btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) - { - m_vertices1[0] = p0; - m_vertices1[1] = p1; - m_vertices1[2] = p2; - } + btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) + { + m_vertices1[0] = p0; + m_vertices1[1] = p1; + m_vertices1[2] = p2; + } + virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const { @@ -114,7 +116,7 @@ public: planeSupport = m_vertices1[0]; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) { (void)mass; btAssert(0); @@ -153,7 +155,7 @@ public: return false; } //debugging - virtual const char* getName()const + virtual char* getName()const { return "Triangle"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp deleted file mode 100644 index ef340286cb0..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btUniformScalingShape.h" - -btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): -m_childConvexShape(convexChildShape), -m_uniformScalingFactor(uniformScalingFactor) -{ -} - -btUniformScalingShape::~btUniformScalingShape() -{ -} - - -btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const -{ - btVector3 tmpVertex; - tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); - return tmpVertex*m_uniformScalingFactor; -} - -void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const -{ - m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); - int i; - for (i=0;ilocalGetSupportingVertex(vec); - return tmpVertex*m_uniformScalingFactor; -} - - -void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const -{ - - ///this linear upscaling is not realistic, but we don't deal with large mass ratios... - btVector3 tmpInertia; - m_childConvexShape->calculateLocalInertia(mass,tmpInertia); - inertia = tmpInertia * m_uniformScalingFactor; -} - - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version -void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const -{ - m_childConvexShape->getAabb(t,aabbMin,aabbMax); - btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); - btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; - - aabbMin = aabbCenter - scaledAabbHalfExtends; - aabbMax = aabbCenter + scaledAabbHalfExtends; - -} - -void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const -{ - m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); - btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); - btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; - - aabbMin = aabbCenter - scaledAabbHalfExtends; - aabbMax = aabbCenter + scaledAabbHalfExtends; -} - -void btUniformScalingShape::setLocalScaling(const btVector3& scaling) -{ - m_childConvexShape->setLocalScaling(scaling); -} - -const btVector3& btUniformScalingShape::getLocalScaling() const -{ - return m_childConvexShape->getLocalScaling(); -} - -void btUniformScalingShape::setMargin(btScalar margin) -{ - m_childConvexShape->setMargin(margin); -} -btScalar btUniformScalingShape::getMargin() const -{ - return m_childConvexShape->getMargin() * m_uniformScalingFactor; -} - -int btUniformScalingShape::getNumPreferredPenetrationDirections() const -{ - return m_childConvexShape->getNumPreferredPenetrationDirections(); -} - -void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const -{ - m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); -} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h deleted file mode 100644 index 1e17fc8e198..00000000000 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_UNIFORM_SCALING_SHAPE_H -#define BT_UNIFORM_SCALING_SHAPE_H - -#include "btConvexShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types - -///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way. -///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it. -class btUniformScalingShape : public btConvexShape -{ - btConvexShape* m_childConvexShape; - - btScalar m_uniformScalingFactor; - - public: - - btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); - - virtual ~btUniformScalingShape(); - - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; - - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; - - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - - btScalar getUniformScalingFactor() const - { - return m_uniformScalingFactor; - } - - btConvexShape* getChildShape() - { - return m_childConvexShape; - } - - const btConvexShape* getChildShape() const - { - return m_childConvexShape; - } - - virtual const char* getName()const - { - return "UniformScalingShape"; - } - - virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; } - - - /////////////////////////// - - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - virtual void setLocalScaling(const btVector3& scaling) ; - virtual const btVector3& getLocalScaling() const ; - - virtual void setMargin(btScalar margin); - virtual btScalar getMargin() const; - - virtual int getNumPreferredPenetrationDirections() const; - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; - - -}; - -#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp index 6551cfb92fe..2c565734e97 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -16,6 +16,7 @@ subject to the following restrictions: #include "btContinuousConvexCollision.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "LinearMath/btTransformUtil.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -25,7 +26,7 @@ subject to the following restrictions: -btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +btContinuousConvexCollision::btContinuousConvexCollision ( btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_simplexSolver(simplexSolver), m_penetrationDepthSolver(penetrationDepthSolver), m_convexA(convexA),m_convexB(convexB) @@ -34,7 +35,7 @@ m_convexA(convexA),m_convexB(convexB) /// This maximum should not be necessary. It allows for untested/degenerate cases in production code. /// You don't want your game ever to lock-up. -#define MAX_ITERATIONS 64 +#define MAX_ITERATIONS 1000 bool btContinuousConvexCollision::calcTimeOfImpact( const btTransform& fromA, @@ -51,18 +52,10 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); - btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; - btVector3 relLinVel = (linVelB-linVelA); - - btScalar relLinVelocLength = (linVelB-linVelA).length(); - - if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) - return false; - btScalar radius = btScalar(0.001); @@ -100,7 +93,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btGjkPairDetector::ClosestPointInput input; //we don't use margins during CCD - // gjk.setIgnoreMargin(true); + gjk.setIgnoreMargin(true); input.m_transformA = fromA; input.m_transformB = fromB; @@ -115,31 +108,25 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btScalar dist; dist = pointCollector1.m_distance; n = pointCollector1.m_normalOnBInWorld; - - btScalar projectedLinearVelocity = relLinVel.dot(n); //not close enough while (dist > radius) { numIter++; if (numIter > maxIter) - { return false; //todo: report a failure - } - btScalar dLambda = btScalar(0.); - projectedLinearVelocity = relLinVel.dot(n); + btScalar dLambda = btScalar(0.); //calculate safe moving fraction from distance / (linear+rotational velocity) //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); //btScalar clippedDist = dist; + btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); - - lambda = lambda + dLambda; if (lambda > btScalar(1.)) @@ -148,14 +135,9 @@ bool btContinuousConvexCollision::calcTimeOfImpact( if (lambda < btScalar(0.)) return false; - //todo: next check with relative epsilon if (lambda <= lastLambda) - { - return false; - //n.setValue(0,0,0); break; - } lastLambda = lambda; @@ -181,13 +163,11 @@ bool btContinuousConvexCollision::calcTimeOfImpact( { //degenerate ?! result.m_fraction = lastLambda; - n = pointCollector.m_normalOnBInWorld; - result.m_normal=n;//.setValue(1,1,1);// = n; - result.m_hitPoint = pointCollector.m_pointInWorld; + result.m_normal = n; return true; } c = pointCollector.m_pointInWorld; - n = pointCollector.m_normalOnBInWorld; + dist = pointCollector.m_distance; } else { @@ -197,13 +177,8 @@ bool btContinuousConvexCollision::calcTimeOfImpact( } - //don't report time of impact for motion away from the contact normal (or causes minor penetration) - if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) - return false; - result.m_fraction = lambda; result.m_normal = n; - result.m_hitPoint = c; return true; } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h index 28c2b4d6156..9901bab4b45 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -30,13 +30,13 @@ class btContinuousConvexCollision : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; btConvexPenetrationDepthSolver* m_penetrationDepthSolver; - const btConvexShape* m_convexA; - const btConvexShape* m_convexB; + btConvexShape* m_convexA; + btConvexShape* m_convexB; public: - btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btContinuousConvexCollision (btConvexShape* shapeA,btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); virtual bool calcTimeOfImpact( const btTransform& fromA, diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h index 0edf4dcd496..3101b59993d 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -17,11 +17,11 @@ subject to the following restrictions: #ifndef CONVEX_CAST_H #define CONVEX_CAST_H -#include "LinearMath/btTransform.h" -#include "LinearMath/btVector3.h" -#include "LinearMath/btScalar.h" +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btScalar.h" class btMinkowskiSumShape; -#include "LinearMath/btIDebugDraw.h" +#include "../../LinearMath/btIDebugDraw.h" /// btConvexCast is an interface for Casting class btConvexCast @@ -42,21 +42,19 @@ public: CastResult() :m_fraction(btScalar(1e30)), - m_debugDrawer(0), - m_allowedPenetration(btScalar(0)) + m_debugDrawer(0) { } virtual ~CastResult() {}; + btVector3 m_normal; + btScalar m_fraction; btTransform m_hitTransformA; btTransform m_hitTransformB; - btVector3 m_normal; - btVector3 m_hitPoint; - btScalar m_fraction; //input and output + btIDebugDraw* m_debugDrawer; - btScalar m_allowedPenetration; }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h index 99690921317..7caeba4be45 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -21,7 +21,7 @@ class btStackAlloc; class btVector3; #include "btSimplexSolverInterface.h" class btConvexShape; -#include "LinearMath/btPoint3.h" +#include "../../LinearMath/btPoint3.h" class btTransform; ///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. @@ -31,7 +31,7 @@ public: virtual ~btConvexPenetrationDepthSolver() {}; virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* convexA,const btConvexShape* convexB, + btConvexShape* convexA,btConvexShape* convexB, const btTransform& transA,const btTransform& transB, btVector3& v, btPoint3& pa, btPoint3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h index db797d5141f..15000c1ab61 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H #define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#include "LinearMath/btTransform.h" -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" class btStackAlloc; /// This interface is made to be used by an iterative approach to do TimeOfImpact calculations @@ -58,7 +58,7 @@ struct btDiscreteCollisionDetectorInterface // give either closest points (distance > 0) or penetration (distance) // the normal always points from B towards A // - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0; + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) = 0; }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp index bef697a0a11..93edffeafd6 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -17,17 +17,12 @@ subject to the following restrictions: #include "btGjkConvexCast.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "btGjkPairDetector.h" #include "btPointCollector.h" -#include "LinearMath/btTransformUtil.h" -#ifdef BT_USE_DOUBLE_PRECISION -#define MAX_ITERATIONS 64 -#else -#define MAX_ITERATIONS 32 -#endif -btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +btGjkConvexCast::btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), m_convexA(convexA), m_convexB(convexB) @@ -43,113 +38,120 @@ bool btGjkConvexCast::calcTimeOfImpact( { - m_simplexSolver->reset(); + btMinkowskiSumShape combi(m_convexA,m_convexB); + btMinkowskiSumShape* convex = &combi; - /// compute linear velocity for this interval, to interpolate - //assume no rotation/angular velocity, assert here? - btVector3 linVelA,linVelB; - linVelA = toA.getOrigin()-fromA.getOrigin(); - linVelB = toB.getOrigin()-fromB.getOrigin(); + btTransform rayFromLocalA; + btTransform rayToLocalA; + + rayFromLocalA = fromA.inverse()* fromB; + rayToLocalA = toA.inverse()* toB; + + + btTransform trA,trB; + trA = btTransform(fromA); + trB = btTransform(fromB); + trA.setOrigin(btPoint3(0,0,0)); + trB.setOrigin(btPoint3(0,0,0)); + + convex->setTransformA(trA); + convex->setTransformB(trB); + + + + + btScalar radius = btScalar(0.01); - btScalar radius = btScalar(0.001); btScalar lambda = btScalar(0.); - btVector3 v(1,0,0); - - int maxIter = MAX_ITERATIONS; - + btVector3 s = rayFromLocalA.getOrigin(); + btVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin(); + btVector3 x = s; btVector3 n; - n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + n.setValue(0,0,0); bool hasResult = false; btVector3 c; - btVector3 r = (linVelA-linVelB); btScalar lastLambda = lambda; - //btScalar epsilon = btScalar(0.001); - int numIter = 0; //first solution, using GJK + //no penetration support for now, perhaps pass a pointer when we really want it + btConvexPenetrationDepthSolver* penSolverPtr = 0; btTransform identityTrans; identityTrans.setIdentity(); + btSphereShape raySphere(btScalar(0.0)); + raySphere.setMargin(btScalar(0.)); -// result.drawCoordSystem(sphereTr); + btTransform sphereTr; + sphereTr.setIdentity(); + sphereTr.setOrigin( rayFromLocalA.getOrigin()); - btPointCollector pointCollector; + result.drawCoordSystem(sphereTr); + { + btPointCollector pointCollector1; + btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); - - btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver); - btGjkPairDetector::ClosestPointInput input; + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = sphereTr; + input.m_transformB = identityTrans; + gjk.getClosestPoints(input,pointCollector1,0); - //we don't use margins during CCD - // gjk.setIgnoreMargin(true); + hasResult = pointCollector1.m_hasResult; + c = pointCollector1.m_pointInWorld; + n = pointCollector1.m_normalOnBInWorld; + } - input.m_transformA = fromA; - input.m_transformB = fromB; - gjk.getClosestPoints(input,pointCollector,0); - - hasResult = pointCollector.m_hasResult; - c = pointCollector.m_pointInWorld; + if (hasResult) { btScalar dist; - dist = pointCollector.m_distance; - n = pointCollector.m_normalOnBInWorld; - - + dist = (c-x).length(); + if (dist < radius) + { + //penetration + lastLambda = btScalar(1.); + } //not close enough while (dist > radius) { - numIter++; - if (numIter > maxIter) - { - return false; //todo: report a failure - } - btScalar dLambda = btScalar(0.); - - btScalar projectedLinearVelocity = r.dot(n); - dLambda = dist / (projectedLinearVelocity); + n = x - c; + btScalar nDotr = n.dot(r); - lambda = lambda - dLambda; - - if (lambda > btScalar(1.)) + if (nDotr >= -(SIMD_EPSILON*SIMD_EPSILON)) return false; - - if (lambda < btScalar(0.)) - return false; - - //todo: next check with relative epsilon + + lambda = lambda - n.dot(n) / nDotr; if (lambda <= lastLambda) - { - return false; - //n.setValue(0,0,0); break; - } + lastLambda = lambda; - //interpolate to next lambda - result.DebugDraw( lambda ); - input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); - input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); - + x = s + lambda * r; + + sphereTr.setOrigin( x ); + result.drawCoordSystem(sphereTr); + btPointCollector pointCollector; + btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); + btGjkPairDetector::ClosestPointInput input; + input.m_transformA = sphereTr; + input.m_transformB = identityTrans; gjk.getClosestPoints(input,pointCollector,0); if (pointCollector.m_hasResult) { if (pointCollector.m_distance < btScalar(0.)) { + //degeneracy, report a hit result.m_fraction = lastLambda; - n = pointCollector.m_normalOnBInWorld; - result.m_normal=n; - result.m_hitPoint = pointCollector.m_pointInWorld; + result.m_normal = n; return true; } - c = pointCollector.m_pointInWorld; - n = pointCollector.m_normalOnBInWorld; - dist = pointCollector.m_distance; + c = pointCollector.m_pointInWorld; + dist = (c-x).length(); } else { //?? @@ -158,19 +160,15 @@ bool btGjkConvexCast::calcTimeOfImpact( } - //is n normalized? - //don't report time of impact for motion away from the contact normal (or causes minor penetration) - if (n.dot(r)>=-result.m_allowedPenetration) - return false; - - result.m_fraction = lambda; - result.m_normal = n; - result.m_hitPoint = c; - return true; + if (lastLambda < btScalar(1.)) + { + + result.m_fraction = lastLambda; + result.m_normal = n; + return true; + } } return false; - - } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h index a977c9e83f7..3905c45e6d6 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -18,9 +18,9 @@ subject to the following restrictions: #ifndef GJK_CONVEX_CAST_H #define GJK_CONVEX_CAST_H -#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "../CollisionShapes/btCollisionMargin.h" -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btVector3.h" #include "btConvexCast.h" class btConvexShape; class btMinkowskiSumShape; @@ -30,12 +30,12 @@ class btMinkowskiSumShape; class btGjkConvexCast : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; - const btConvexShape* m_convexA; - const btConvexShape* m_convexB; + btConvexShape* m_convexA; + btConvexShape* m_convexB; public: - btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); /// cast a convex against another convex object virtual bool calcTimeOfImpact( diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp index 36cdeeaefdb..8abdfdbb7e5 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp @@ -26,7 +26,7 @@ Nov.2006 #include "btGjkEpa.h" #include //for memset -#include "LinearMath/btStackAlloc.h" +#include #if defined(DEBUG) || defined (_DEBUG) #include //for debug printf @@ -580,8 +580,8 @@ using namespace gjkepa_impl; // -bool btGjkEpaSolver::Collide(const btConvexShape *shape0,const btTransform &wtrs0, - const btConvexShape *shape1,const btTransform &wtrs1, +bool btGjkEpaSolver::Collide(btConvexShape *shape0,const btTransform &wtrs0, + btConvexShape *shape1,const btTransform &wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results) @@ -602,13 +602,13 @@ GJK gjk(stackAlloc, wtrs1.getBasis(),wtrs1.getOrigin(),shape1, radialmargin+EPA_accuracy); const Z collide(gjk.SearchOrigin()); -results.gjk_iterations = static_cast(gjk.iterations+1); +results.gjk_iterations = gjk.iterations+1; if(collide) { /* Then EPA for penetration depth */ EPA epa(&gjk); const F pd(epa.EvaluatePD()); - results.epa_iterations = static_cast(epa.iterations+1); + results.epa_iterations = epa.iterations+1; if(pd>0) { results.status = sResults::Penetrating; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h index 1c256f41939..759b30bb17f 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h @@ -21,7 +21,7 @@ Nov.2006 #ifndef _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ #define _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ -#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "../CollisionShapes/btConvexShape.h" class btStackAlloc; @@ -35,7 +35,7 @@ struct sResults Separated, /* Shapes doesnt penetrate */ Penetrating, /* Shapes are penetrating */ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ - EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ + EPA_Failed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ } status; btVector3 witnesses[2]; btVector3 normal; @@ -43,8 +43,8 @@ struct sResults int epa_iterations; int gjk_iterations; }; -static bool Collide(const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, +static bool Collide(btConvexShape* shape0,const btTransform& wtrs0, + btConvexShape* shape1,const btTransform& wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp deleted file mode 100644 index ccfc22ee673..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp +++ /dev/null @@ -1,943 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the -use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software in a -product, an acknowledgment in the product documentation would be appreciated -but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -GJK-EPA collision solver by Nathanael Presson, 2008 -*/ -#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "btGjkEpa2.h" - -#if defined(DEBUG) || defined (_DEBUG) -#include //for debug printf -#ifdef __SPU__ -#include -#define printf spu_printf -#endif //__SPU__ -#endif - -namespace gjkepa2_impl -{ - -// Config - - /* GJK */ -#define GJK_MAX_ITERATIONS 128 -#define GJK_ACCURARY ((btScalar)0.0001) -#define GJK_MIN_DISTANCE ((btScalar)0.0001) -#define GJK_DUPLICATED_EPS ((btScalar)0.0001) -#define GJK_SIMPLEX2_EPS ((btScalar)0.0) -#define GJK_SIMPLEX3_EPS ((btScalar)0.0) -#define GJK_SIMPLEX4_EPS ((btScalar)0.0) - - /* EPA */ -#define EPA_MAX_VERTICES 64 -#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) -#define EPA_MAX_ITERATIONS 255 -#define EPA_ACCURACY ((btScalar)0.0001) -#define EPA_FALLBACK (10*EPA_ACCURACY) -#define EPA_PLANE_EPS ((btScalar)0.00001) -#define EPA_INSIDE_EPS ((btScalar)0.01) - - -// Shorthands -typedef unsigned int U; -typedef unsigned char U1; - -// MinkowskiDiff -struct MinkowskiDiff - { - const btConvexShape* m_shapes[2]; - btMatrix3x3 m_toshape1; - btTransform m_toshape0; - btVector3 (btConvexShape::*Ls)(const btVector3&) const; - void EnableMargin(bool enable) - { - if(enable) - Ls=&btConvexShape::localGetSupportingVertex; - else - Ls=&btConvexShape::localGetSupportingVertexWithoutMargin; - } - inline btVector3 Support0(const btVector3& d) const - { - return(((m_shapes[0])->*(Ls))(d)); - } - inline btVector3 Support1(const btVector3& d) const - { - return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); - } - inline btVector3 Support(const btVector3& d) const - { - return(Support0(d)-Support1(-d)); - } - btVector3 Support(const btVector3& d,U index) const - { - if(index) - return(Support1(d)); - else - return(Support0(d)); - } - }; - -typedef MinkowskiDiff tShape; - - -// GJK -struct GJK -{ -/* Types */ -struct sSV - { - btVector3 d,w; - }; -struct sSimplex - { - sSV* c[4]; - btScalar p[4]; - U rank; - }; -struct eStatus { enum _ { - Valid, - Inside, - Failed };}; -/* Fields */ -tShape m_shape; -btVector3 m_ray; -btScalar m_distance; -sSimplex m_simplices[2]; -sSV m_store[4]; -sSV* m_free[4]; -U m_nfree; -U m_current; -sSimplex* m_simplex; -eStatus::_ m_status; -/* Methods */ - GJK() - { - Initialize(); - } -void Initialize() - { - m_ray = btVector3(0,0,0); - m_nfree = 0; - m_status = eStatus::Failed; - m_current = 0; - m_distance = 0; - } -eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess) - { - U iterations=0; - btScalar sqdist=0; - btScalar alpha=0; - btVector3 lastw[4]; - U clastw=0; - /* Initialize solver */ - m_free[0] = &m_store[0]; - m_free[1] = &m_store[1]; - m_free[2] = &m_store[2]; - m_free[3] = &m_store[3]; - m_nfree = 4; - m_current = 0; - m_status = eStatus::Valid; - m_shape = shapearg; - m_distance = 0; - /* Initialize simplex */ - m_simplices[0].rank = 0; - m_ray = guess; - const btScalar sqrl= m_ray.length2(); - appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0)); - m_simplices[0].p[0] = 1; - m_ray = m_simplices[0].c[0]->w; - sqdist = sqrl; - lastw[0] = - lastw[1] = - lastw[2] = - lastw[3] = m_ray; - /* Loop */ - do { - const U next=1-m_current; - sSimplex& cs=m_simplices[m_current]; - sSimplex& ns=m_simplices[next]; - /* Check zero */ - const btScalar rl=m_ray.length(); - if(rlw; - bool found=false; - for(U i=0;i<4;++i) - { - if((w-lastw[i]).length2()w, - cs.c[1]->w, - weights,mask);break; - case 3: sqdist=projectorigin( cs.c[0]->w, - cs.c[1]->w, - cs.c[2]->w, - weights,mask);break; - case 4: sqdist=projectorigin( cs.c[0]->w, - cs.c[1]->w, - cs.c[2]->w, - cs.c[3]->w, - weights,mask);break; - } - if(sqdist>=0) - {/* Valid */ - ns.rank = 0; - m_ray = btVector3(0,0,0); - m_current = next; - for(U i=0,ni=cs.rank;iw*weights[i]; - } - else - { - m_free[m_nfree++] = cs.c[i]; - } - } - if(mask==15) m_status=eStatus::Inside; - } - else - {/* Return old simplex */ - removevertice(m_simplices[m_current]); - break; - } - m_status=((++iterations)rank) - { - case 1: - { - for(U i=0;i<3;++i) - { - btVector3 axis=btVector3(0,0,0); - axis[i]=1; - appendvertice(*m_simplex, axis); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-axis); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - } - } - break; - case 2: - { - const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; - for(U i=0;i<3;++i) - { - btVector3 axis=btVector3(0,0,0); - axis[i]=1; - const btVector3 p=cross(d,axis); - if(p.length2()>0) - { - appendvertice(*m_simplex, p); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-p); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - } - } - } - break; - case 3: - { - const btVector3 n=cross(m_simplex->c[1]->w-m_simplex->c[0]->w, - m_simplex->c[2]->w-m_simplex->c[0]->w); - if(n.length2()>0) - { - appendvertice(*m_simplex,n); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-n); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - } - } - break; - case 4: - { - if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, - m_simplex->c[1]->w-m_simplex->c[3]->w, - m_simplex->c[2]->w-m_simplex->c[3]->w))>0) - return(true); - } - break; - } - return(false); - } -/* Internals */ -void getsupport(const btVector3& d,sSV& sv) const - { - sv.d = d/d.length(); - sv.w = m_shape.Support(sv.d); - } -void removevertice(sSimplex& simplex) - { - m_free[m_nfree++]=simplex.c[--simplex.rank]; - } -void appendvertice(sSimplex& simplex,const btVector3& v) - { - simplex.p[simplex.rank]=0; - simplex.c[simplex.rank]=m_free[--m_nfree]; - getsupport(v,*simplex.c[simplex.rank++]); - } -static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c) - { - return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()- - a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+ - a.x()*b.y()*c.z()-a.z()*b.y()*c.x()); - } -static btScalar projectorigin( const btVector3& a, - const btVector3& b, - btScalar* w,U& m) - { - const btVector3 d=b-a; - const btScalar l=d.length2(); - if(l>GJK_SIMPLEX2_EPS) - { - const btScalar t(l>0?-dot(a,d)/l:0); - if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); } - else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); } - else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); } - } - return(-1); - } -static btScalar projectorigin( const btVector3& a, - const btVector3& b, - const btVector3& c, - btScalar* w,U& m) - { - static const U imd3[]={1,2,0}; - const btVector3* vt[]={&a,&b,&c}; - const btVector3 dl[]={a-b,b-c,c-a}; - const btVector3 n=cross(dl[0],dl[1]); - const btScalar l=n.length2(); - if(l>GJK_SIMPLEX3_EPS) - { - btScalar mindist=-1; - btScalar subw[2]; - U subm; - for(U i=0;i<3;++i) - { - if(dot(*vt[i],cross(dl[i],n))>0) - { - const U j=imd3[i]; - const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm)); - if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) - { - btScalar mindist=-1; - btScalar subw[3]; - U subm; - for(U i=0;i<3;++i) - { - const U j=imd3[i]; - const btScalar s=vl*dot(d,cross(dl[i],dl[j])); - if(s>0) - { - const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm); - if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; - fb->e[eb]=(U1)ea;fb->f[eb]=fa; - } -static inline void append(sList& list,sFace* face) - { - face->l[0] = 0; - face->l[1] = list.root; - if(list.root) list.root->l[0]=face; - list.root = face; - ++list.count; - } -static inline void remove(sList& list,sFace* face) - { - if(face->l[1]) face->l[1]->l[0]=face->l[0]; - if(face->l[0]) face->l[0]->l[1]=face->l[1]; - if(face==list.root) list.root=face->l[1]; - --list.count; - } - - -void Initialize() - { - m_status = eStatus::Failed; - m_normal = btVector3(0,0,0); - m_depth = 0; - m_nextsv = 0; - for(U i=0;i1)&&gjk.EncloseOrigin()) - { - - /* Clean up */ - while(m_hull.root) - { - sFace* f = m_hull.root; - remove(m_hull,f); - append(m_stock,f); - } - m_status = eStatus::Valid; - m_nextsv = 0; - /* Orient simplex */ - if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, - simplex.c[1]->w-simplex.c[3]->w, - simplex.c[2]->w-simplex.c[3]->w)<0) - { - btSwap(simplex.c[0],simplex.c[1]); - btSwap(simplex.p[0],simplex.p[1]); - } - /* Build initial hull */ - sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), - newface(simplex.c[1],simplex.c[0],simplex.c[3],true), - newface(simplex.c[2],simplex.c[1],simplex.c[3],true), - newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; - if(m_hull.count==4) - { - sFace* best=findbest(); - sFace outer=*best; - U pass=0; - U iterations=0; - bind(tetra[0],0,tetra[1],0); - bind(tetra[0],1,tetra[2],0); - bind(tetra[0],2,tetra[3],0); - bind(tetra[1],1,tetra[3],2); - bind(tetra[1],2,tetra[2],1); - bind(tetra[2],2,tetra[3],1); - m_status=eStatus::Valid; - for(;iterationspass = (U1)(++pass); - gjk.getsupport(best->n,*w); - const btScalar wdist=dot(best->n,w->w)-best->d; - if(wdist>EPA_ACCURACY) - { - for(U j=0;(j<3)&&valid;++j) - { - valid&=expand( pass,w, - best->f[j],best->e[j], - horizon); - } - if(valid&&(horizon.nf>=3)) - { - bind(horizon.cf,1,horizon.ff,2); - remove(m_hull,best); - append(m_stock,best); - best=findbest(); - if(best->p>=outer.p) outer=*best; - } else { m_status=eStatus::InvalidHull;break; } - } else { m_status=eStatus::AccuraryReached;break; } - } else { m_status=eStatus::OutOfVertices;break; } - } - const btVector3 projection=outer.n*outer.d; - m_normal = outer.n; - m_depth = outer.d; - m_result.rank = 3; - m_result.c[0] = outer.c[0]; - m_result.c[1] = outer.c[1]; - m_result.c[2] = outer.c[2]; - m_result.p[0] = cross( outer.c[1]->w-projection, - outer.c[2]->w-projection).length(); - m_result.p[1] = cross( outer.c[2]->w-projection, - outer.c[0]->w-projection).length(); - m_result.p[2] = cross( outer.c[0]->w-projection, - outer.c[1]->w-projection).length(); - const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; - m_result.p[0] /= sum; - m_result.p[1] /= sum; - m_result.p[2] /= sum; - return(m_status); - } - } - /* Fallback */ - m_status = eStatus::FallBack; - m_normal = -guess; - const btScalar nl=m_normal.length(); - if(nl>0) - m_normal = m_normal/nl; - else - m_normal = btVector3(1,0,0); - m_depth = 0; - m_result.rank=1; - m_result.c[0]=simplex.c[0]; - m_result.p[0]=1; - return(m_status); - } -sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) - { - if(m_stock.root) - { - sFace* face=m_stock.root; - remove(m_stock,face); - append(m_hull,face); - face->pass = 0; - face->c[0] = a; - face->c[1] = b; - face->c[2] = c; - face->n = cross(b->w-a->w,c->w-a->w); - const btScalar l=face->n.length(); - const bool v=l>EPA_ACCURACY; - face->p = btMin(btMin( - dot(a->w,cross(face->n,a->w-b->w)), - dot(b->w,cross(face->n,b->w-c->w))), - dot(c->w,cross(face->n,c->w-a->w))) / - (v?l:1); - face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; - if(v) - { - face->d = dot(a->w,face->n)/l; - face->n /= l; - if(forced||(face->d>=-EPA_PLANE_EPS)) - { - return(face); - } else m_status=eStatus::NonConvex; - } else m_status=eStatus::Degenerated; - remove(m_hull,face); - append(m_stock,face); - return(0); - } - m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; - return(0); - } -sFace* findbest() - { - sFace* minf=m_hull.root; - btScalar mind=minf->d*minf->d; - btScalar maxp=minf->p; - for(sFace* f=minf->l[1];f;f=f->l[1]) - { - const btScalar sqd=f->d*f->d; - if((f->p>=maxp)&&(sqdp; - } - } - return(minf); - } -bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon) - { - static const U i1m3[]={1,2,0}; - static const U i2m3[]={2,0,1}; - if(f->pass!=pass) - { - const U e1=i1m3[e]; - if((dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) - { - sFace* nf=newface(f->c[e1],f->c[e],w,false); - if(nf) - { - bind(nf,0,f,e); - if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; - horizon.cf=nf; - ++horizon.nf; - return(true); - } - } - else - { - const U e2=i2m3[e]; - f->pass = (U1)pass; - if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& - expand(pass,w,f->f[e2],f->e[e2],horizon)) - { - remove(m_hull,f); - append(m_stock,f); - return(true); - } - } - } - return(false); - } - -}; - -// -static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, - btGjkEpaSolver2::sResults& results, - tShape& shape, - bool withmargins) -{ -/* Results */ -results.witnesses[0] = -results.witnesses[1] = btVector3(0,0,0); -results.status = btGjkEpaSolver2::sResults::Separated; -/* Shape */ -shape.m_shapes[0] = shape0; -shape.m_shapes[1] = shape1; -shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis()); -shape.m_toshape0 = wtrs0.inverseTimes(wtrs1); -shape.EnableMargin(withmargins); -} - -} - -// -// Api -// - -using namespace gjkepa2_impl; - -// -int btGjkEpaSolver2::StackSizeRequirement() -{ -return(sizeof(GJK)+sizeof(EPA)); -} - -// -bool btGjkEpaSolver2::Distance( const btConvexShape* shape0, - const btTransform& wtrs0, - const btConvexShape* shape1, - const btTransform& wtrs1, - const btVector3& guess, - sResults& results) -{ -tShape shape; -Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); -GJK gjk; -GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); -if(gjk_status==GJK::eStatus::Valid) - { - btVector3 w0=btVector3(0,0,0); - btVector3 w1=btVector3(0,0,0); - for(U i=0;irank;++i) - { - const btScalar p=gjk.m_simplex->p[i]; - w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; - w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; - } - results.witnesses[0] = wtrs0*w0; - results.witnesses[1] = wtrs0*w1; - results.normal = w0-w1; - results.distance = results.normal.length(); - results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; - return(true); - } - else - { - results.status = gjk_status==GJK::eStatus::Inside? - sResults::Penetrating : - sResults::GJK_Failed ; - return(false); - } -} - -// -bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, - const btTransform& wtrs0, - const btConvexShape* shape1, - const btTransform& wtrs1, - const btVector3& guess, - sResults& results, - bool usemargins) -{ -tShape shape; -Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins); -GJK gjk; -GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); -switch(gjk_status) - { - case GJK::eStatus::Inside: - { - EPA epa; - EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); - if(epa_status!=EPA::eStatus::Failed) - { - btVector3 w0=btVector3(0,0,0); - for(U i=0;id,0)*epa.m_result.p[i]; - } - results.status = sResults::Penetrating; - results.witnesses[0] = wtrs0*w0; - results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); - results.normal = -epa.m_normal; - results.distance = -epa.m_depth; - return(true); - } else results.status=sResults::EPA_Failed; - } - break; - case GJK::eStatus::Failed: - results.status=sResults::GJK_Failed; - break; - } -return(false); -} - -// -btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, - btScalar margin, - const btConvexShape* shape0, - const btTransform& wtrs0, - sResults& results) -{ -tShape shape; -btSphereShape shape1(margin); -btTransform wtrs1(btQuaternion(0,0,0,1),position); -Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false); -GJK gjk; -GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1)); -if(gjk_status==GJK::eStatus::Valid) - { - btVector3 w0=btVector3(0,0,0); - btVector3 w1=btVector3(0,0,0); - for(U i=0;irank;++i) - { - const btScalar p=gjk.m_simplex->p[i]; - w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; - w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; - } - results.witnesses[0] = wtrs0*w0; - results.witnesses[1] = wtrs0*w1; - const btVector3 delta= results.witnesses[1]- - results.witnesses[0]; - const btScalar margin= shape0->getMargin()+ - shape1.getMargin(); - const btScalar length= delta.length(); - results.normal = delta/length; - results.witnesses[0] += results.normal*margin; - return(length-margin); - } - else - { - if(gjk_status==GJK::eStatus::Inside) - { - if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results)) - { - const btVector3 delta= results.witnesses[0]- - results.witnesses[1]; - const btScalar length= delta.length(); - if (length >= SIMD_EPSILON) - results.normal = delta/length; - return(-length); - } - } - } -return(SIMD_INFINITY); -} - -// -bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, - const btTransform& wtrs0, - const btConvexShape* shape1, - const btTransform& wtrs1, - const btVector3& guess, - sResults& results) -{ -if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) - return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); - else - return(true); -} - -/* Symbols cleanup */ - -#undef GJK_MAX_ITERATIONS -#undef GJK_ACCURARY -#undef GJK_MIN_DISTANCE -#undef GJK_DUPLICATED_EPS -#undef GJK_SIMPLEX2_EPS -#undef GJK_SIMPLEX3_EPS -#undef GJK_SIMPLEX4_EPS - -#undef EPA_MAX_VERTICES -#undef EPA_MAX_FACES -#undef EPA_MAX_ITERATIONS -#undef EPA_ACCURACY -#undef EPA_FALLBACK -#undef EPA_PLANE_EPS -#undef EPA_INSIDE_EPS diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h deleted file mode 100644 index a55214203d3..00000000000 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the -use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software in a -product, an acknowledgment in the product documentation would be appreciated -but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -GJK-EPA collision solver by Nathanael Presson, 2008 -*/ -#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ -#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ -#include "BulletCollision/CollisionShapes/btConvexShape.h" - -///btGjkEpaSolver contributed under zlib by Nathanael Presson -struct btGjkEpaSolver2 -{ -struct sResults - { - enum eStatus - { - Separated, /* Shapes doesnt penetrate */ - Penetrating, /* Shapes are penetrating */ - GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ - EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ - } status; - btVector3 witnesses[2]; - btVector3 normal; - btScalar distance; - }; - -static int StackSizeRequirement(); - -static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, - const btVector3& guess, - sResults& results); - -static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, - const btVector3& guess, - sResults& results, - bool usemargins=true); - -static btScalar SignedDistance( const btVector3& position, - btScalar margin, - const btConvexShape* shape, - const btTransform& wtrs, - sResults& results); - -static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0, - const btConvexShape* shape1,const btTransform& wtrs1, - const btVector3& guess, - sResults& results); -}; - -#endif diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp index c4f84ed4d75..87330493b60 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -18,10 +18,9 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexShape.h" #include "btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* pConvexA, const btConvexShape* pConvexB, + btConvexShape* pConvexA, btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) @@ -33,20 +32,10 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim const btScalar radialmargin(btScalar(0.)); -//#define USE_ORIGINAL_GJK 1 -#ifdef USE_ORIGINAL_GJK btGjkEpaSolver::sResults results; if(btGjkEpaSolver::Collide( pConvexA,transformA, pConvexB,transformB, radialmargin,stackAlloc,results)) -#else - btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin()); - btGjkEpaSolver2::sResults results; - if(btGjkEpaSolver2::Penetration(pConvexA,transformA, - pConvexB,transformB, - guessVector,results)) - -#endif { // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h index 2dc069ce5cf..3916ba0776c 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -26,7 +26,7 @@ class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver public : bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - const btConvexShape* pConvexA, const btConvexShape* pConvexB, + btConvexShape* pConvexA, btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index 01fb1a4b068..f1f3f7f7f6c 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -35,7 +35,7 @@ int gNumGjkChecks = 0; -btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +btGjkPairDetector::btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_cachedSeparatingAxis(btScalar(0.),btScalar(0.),btScalar(1.)), m_penetrationDepthSolver(penetrationDepthSolver), m_simplexSolver(simplexSolver), @@ -47,7 +47,7 @@ m_catchDegeneracies(1) { } -void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) +void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) { btScalar distance=btScalar(0.); btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); @@ -144,13 +144,6 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& break; } - if(m_cachedSeparatingAxis.length2() @@ -162,7 +169,7 @@ int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const return nearestPoint; } -int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) +void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) { assert(validContactDistance(newPoint)); @@ -175,7 +182,7 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) #else insertIndex = 0; #endif - clearUserCache(m_pointCache[insertIndex]); + } else { @@ -183,9 +190,7 @@ int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) } - btAssert(m_pointCache[insertIndex].m_userPersistentData==0); - m_pointCache[insertIndex] = newPoint; - return insertIndex; + replaceContactPoint(newPoint,insertIndex); } btScalar btPersistentManifold::getContactBreakingThreshold() const @@ -193,20 +198,10 @@ btScalar btPersistentManifold::getContactBreakingThreshold() const return gContactBreakingThreshold; } - - void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) { int i; -#ifdef DEBUG_PERSISTENCY - printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", - trA.getOrigin().getX(), - trA.getOrigin().getY(), - trA.getOrigin().getZ(), - trB.getOrigin().getX(), - trB.getOrigin().getY(), - trB.getOrigin().getZ()); -#endif //DEBUG_PERSISTENCY + /// first refresh worldspace positions and distance for (i=getNumContacts()-1;i>=0;i--) { @@ -237,11 +232,6 @@ void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btT if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) { removeContactPoint(i); - } else - { - //contact point processed callback - if (gContactProcessedCallback) - (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1); } } } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index c122eb865e8..a5918b84db3 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -17,10 +17,9 @@ subject to the following restrictions: #define PERSISTENT_MANIFOLD_H -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" #include "btManifoldPoint.h" -#include "LinearMath/btAlignedAllocator.h" struct btCollisionResult; @@ -28,7 +27,6 @@ struct btCollisionResult; extern btScalar gContactBreakingThreshold; typedef bool (*ContactDestroyedCallback)(void* userPersistentData); -typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1); extern ContactDestroyedCallback gContactDestroyedCallback; @@ -36,13 +34,8 @@ extern ContactDestroyedCallback gContactDestroyedCallback; #define MANIFOLD_CACHE_SIZE 4 -///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. -///Those contact points are created by the collision narrow phase. -///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. -///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) -///reduces the cache to 4 points, when more then 4 points are added, using following rules: -///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points -///note that some pairs of objects might have more then one contact manifold. +///btPersistentManifold maintains contact points, and reduces them to 4. +///It does contact filtering/contact reduction. ATTRIBUTE_ALIGNED16( class) btPersistentManifold { @@ -62,23 +55,20 @@ ATTRIBUTE_ALIGNED16( class) btPersistentManifold public: - BT_DECLARE_ALIGNED_ALLOCATOR(); - - int m_index1a; + int m_index1; btPersistentManifold(); - btPersistentManifold(void* body0,void* body1,int bla) + btPersistentManifold(void* body0,void* body1) : m_body0(body0),m_body1(body1),m_cachedPoints(0) { - (void)bla; } - SIMD_FORCE_INLINE void* getBody0() { return m_body0;} - SIMD_FORCE_INLINE void* getBody1() { return m_body1;} + inline void* getBody0() { return m_body0;} + inline void* getBody1() { return m_body1;} - SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;} - SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;} + inline const void* getBody0() const { return m_body0;} + inline const void* getBody1() const { return m_body1;} void setBodies(void* body0,void* body1) { @@ -92,15 +82,15 @@ public: void DebugPersistency(); #endif // - SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} + inline int getNumContacts() const { return m_cachedPoints;} - SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const + inline const btManifoldPoint& getContactPoint(int index) const { btAssert(index < m_cachedPoints); return m_pointCache[index]; } - SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) + inline btManifoldPoint& getContactPoint(int index) { btAssert(index < m_cachedPoints); return m_pointCache[index]; @@ -111,7 +101,7 @@ public: int getCacheEntry(const btManifoldPoint& newPoint) const; - int addManifoldPoint( const btManifoldPoint& newPoint); + void AddManifoldPoint( const btManifoldPoint& newPoint); void removeContactPoint (int index) { @@ -124,11 +114,6 @@ public: m_pointCache[index] = m_pointCache[lastUsedIndex]; //get rid of duplicated userPersistentData pointer m_pointCache[lastUsedIndex].m_userPersistentData = 0; - m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f; - m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false; - m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f; - m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f; - m_pointCache[lastUsedIndex].m_lifeTime = 0; } btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); @@ -141,20 +126,12 @@ public: #define MAINTAIN_PERSISTENCY 1 #ifdef MAINTAIN_PERSISTENCY int lifeTime = m_pointCache[insertIndex].getLifeTime(); - btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse; - btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1; - btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2; - btAssert(lifeTime>=0); void* cache = m_pointCache[insertIndex].m_userPersistentData; m_pointCache[insertIndex] = newPoint; m_pointCache[insertIndex].m_userPersistentData = cache; - m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; - m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; - m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; - m_pointCache[insertIndex].m_lifeTime = lifeTime; #else clearUserCache(m_pointCache[insertIndex]); @@ -170,16 +147,7 @@ public: /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin void refreshContactPoints( const btTransform& trA,const btTransform& trB); - - SIMD_FORCE_INLINE void clearManifold() - { - int i; - for (i=0;i -#include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "btRaycastCallback.h" btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to) @@ -36,6 +29,8 @@ btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) { + + const btVector3 &vert0=triangle[0]; const btVector3 &vert1=triangle[1]; const btVector3 &vert2=triangle[2]; @@ -104,60 +99,3 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, } } } - - -btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin) -{ - m_convexShape = convexShape; - m_convexShapeFrom = convexShapeFrom; - m_convexShapeTo = convexShapeTo; - m_triangleToWorld = triangleToWorld; - m_hitFraction = 1.0; - m_triangleCollisionMargin = triangleCollisionMargin; -} - -void -btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex) -{ - btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]); - triangleShape.setMargin(m_triangleCollisionMargin); - - btVoronoiSimplexSolver simplexSolver; - btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; - -//#define USE_SUBSIMPLEX_CONVEX_CAST 1 -//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below -#ifdef USE_SUBSIMPLEX_CONVEX_CAST - btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver); -#else - //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver); - btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver); -#endif //#USE_SUBSIMPLEX_CONVEX_CAST - - btConvexCast::CastResult castResult; - castResult.m_fraction = btScalar(1.); - if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult)) - { - //add hit - if (castResult.m_normal.length2() > btScalar(0.0001)) - { - if (castResult.m_fraction < m_hitFraction) - { -/* btContinuousConvexCast's normal is already in world space */ -/* -#ifdef USE_SUBSIMPLEX_CONVEX_CAST - //rotate normal into worldspace - castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal; -#endif //USE_SUBSIMPLEX_CONVEX_CAST -*/ - castResult.m_normal.normalize(); - - reportHit (castResult.m_normal, - castResult.m_hitPoint, - castResult.m_fraction, - partId, - triangleIndex); - } - } - } -} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h index d2b4b80f8ba..a0bbc9f8fe9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -16,16 +16,15 @@ subject to the following restrictions: #ifndef RAYCAST_TRI_CALLBACK_H #define RAYCAST_TRI_CALLBACK_H -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -#include "LinearMath/btTransform.h" +#include "../CollisionShapes/btTriangleCallback.h" struct btBroadphaseProxy; -class btConvexShape; + class btTriangleRaycastCallback: public btTriangleCallback { public: - //input + //input btVector3 m_from; btVector3 m_to; @@ -39,22 +38,5 @@ public: }; -class btTriangleConvexcastCallback : public btTriangleCallback -{ -public: - const btConvexShape* m_convexShape; - btTransform m_convexShapeFrom; - btTransform m_convexShapeTo; - btTransform m_triangleToWorld; - btScalar m_hitFraction; - btScalar m_triangleCollisionMargin; - - btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin); - - virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex); - - virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0; -}; - #endif //RAYCAST_TRI_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h index cf65f46505b..58393b2eab9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -18,8 +18,8 @@ subject to the following restrictions: #ifndef SIMPLEX_SOLVER_INTERFACE_H #define SIMPLEX_SOLVER_INTERFACE_H -#include "LinearMath/btVector3.h" -#include "LinearMath/btPoint3.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btPoint3.h" #define NO_VIRTUAL_INTERFACE 1 #ifdef NO_VIRTUAL_INTERFACE diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp index 4c709a8c3a9..687738b7fa9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -16,11 +16,9 @@ subject to the following restrictions: #include "btSubSimplexConvexCast.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" - #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" -#include "btPointCollector.h" -#include "LinearMath/btTransformUtil.h" + btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), @@ -43,24 +41,34 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( CastResult& result) { + btMinkowskiSumShape combi(m_convexA,m_convexB); + btMinkowskiSumShape* convex = &combi; + + btTransform rayFromLocalA; + btTransform rayToLocalA; + + rayFromLocalA = fromA.inverse()* fromB; + rayToLocalA = toA.inverse()* toB; + + m_simplexSolver->reset(); - btVector3 linVelA,linVelB; - linVelA = toA.getOrigin()-fromA.getOrigin(); - linVelB = toB.getOrigin()-fromB.getOrigin(); + convex->setTransformB(btTransform(rayFromLocalA.getBasis())); + + //btScalar radius = btScalar(0.01); btScalar lambda = btScalar(0.); - - btTransform interpolatedTransA = fromA; - btTransform interpolatedTransB = fromB; - - ///take relative motion - btVector3 r = (linVelA-linVelB); - btVector3 v; + //todo: need to verify this: + //because of minkowski difference, we need the inverse direction - btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis())); - btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis())); - v = supVertexA-supVertexB; + btVector3 s = -rayFromLocalA.getOrigin(); + btVector3 r = -(rayToLocalA.getOrigin()-rayFromLocalA.getOrigin()); + btVector3 x = s; + btVector3 v; + btVector3 arbitraryPoint = convex->localGetSupportingVertex(r); + + v = x - arbitraryPoint; + int maxIter = MAX_ITERATIONS; btVector3 n; @@ -82,17 +90,11 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( while ( (dist2 > epsilon) && maxIter--) { - supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis())); - supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis())); - w = supVertexA-supVertexB; + p = convex->localGetSupportingVertex( v); + w = x - p; btScalar VdotW = v.dot(w); - if (lambda > btScalar(1.0)) - { - return false; - } - if ( VdotW > btScalar(0.)) { VdotR = v.dot(r); @@ -102,25 +104,20 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( else { lambda = lambda - VdotW / VdotR; - //interpolate to next lambda - // x = s + lambda * r; - interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); - interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); - //m_simplexSolver->reset(); + x = s + lambda * r; + m_simplexSolver->reset(); //check next line - w = supVertexA-supVertexB; + w = x-p; lastLambda = lambda; n = v; hasResult = true; } } - m_simplexSolver->addVertex( w, supVertexA , supVertexB); + m_simplexSolver->addVertex( w, x , p); if (m_simplexSolver->closest(v)) { dist2 = v.length2(); hasResult = true; - //todo: check this normal for validity - //n=v; //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); //printf("DIST2=%f\n",dist2); //printf("numverts = %i\n",m_simplexSolver->numVertices()); @@ -132,26 +129,11 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( //int numiter = MAX_ITERATIONS - maxIter; // printf("number of iterations: %d", numiter); - - //don't report a time of impact when moving 'away' from the hitnormal - - result.m_fraction = lambda; - if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON)) - result.m_normal = n.normalized(); - else - result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + result.m_normal = n; - //don't report time of impact for motion away from the contact normal (or causes minor penetration) - if (result.m_normal.dot(r)>=-result.m_allowedPenetration) - return false; - - btVector3 hitA,hitB; - m_simplexSolver->compute_points(hitA,hitB); - result.m_hitPoint=hitB; return true; } - diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp index cf8a3ab5eb1..105b7eccefa 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -26,7 +26,7 @@ subject to the following restrictions: #include "btVoronoiSimplexSolver.h" #include -//#include +#include #define VERTA 0 #define VERTB 1 diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt index 58b023e9775..8598575799a 100644 --- a/extern/bullet2/src/BulletDynamics/CMakeLists.txt +++ b/extern/bullet2/src/BulletDynamics/CMakeLists.txt @@ -5,32 +5,16 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletDynamics ConstraintSolver/btContactConstraint.cpp - ConstraintSolver/btContactConstraint.h - ConstraintSolver/btConeTwistConstraint.cpp - ConstraintSolver/btConeTwistConstraint.h ConstraintSolver/btGeneric6DofConstraint.cpp - ConstraintSolver/btGeneric6DofConstraint.h ConstraintSolver/btHingeConstraint.cpp - ConstraintSolver/btHingeConstraint.h ConstraintSolver/btPoint2PointConstraint.cpp - ConstraintSolver/btPoint2PointConstraint.h ConstraintSolver/btSequentialImpulseConstraintSolver.cpp - ConstraintSolver/btSequentialImpulseConstraintSolver.h - ConstraintSolver/btSliderConstraint.cpp - ConstraintSolver/btSliderConstraint.h ConstraintSolver/btSolve2LinearConstraint.cpp - ConstraintSolver/btSolve2LinearConstraint.h ConstraintSolver/btTypedConstraint.cpp - ConstraintSolver/btTypedConstraint.h - Dynamics/Bullet-C-API.cpp Dynamics/btDiscreteDynamicsWorld.cpp - Dynamics/btDiscreteDynamicsWorld.h Dynamics/btSimpleDynamicsWorld.cpp - Dynamics/btSimpleDynamicsWorld.h + Dynamics/Bullet-C-API.cpp Dynamics/btRigidBody.cpp - Dynamics/btRigidBody.h Vehicle/btRaycastVehicle.cpp - Vehicle/btRaycastVehicle.h Vehicle/btWheelInfo.cpp - Vehicle/btWheelInfo.h ) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index 61dad522a5b..2289621e8e3 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -19,20 +19,24 @@ Written by: Marcus Hennix #include "btConeTwistConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" -#include "LinearMath/btMinMax.h" +#include "LinearMath/btSimdMinMax.h" #include btConeTwistConstraint::btConeTwistConstraint() -:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) { } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame,const btTransform& rbBFrame) - :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + :btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false) { + // flip axis for correct angles + m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_swingSpan1 = btScalar(1e30); m_swingSpan2 = btScalar(1e30); m_twistSpan = btScalar(1e30); @@ -45,11 +49,20 @@ btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) - :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), + :btTypedConstraint(rbA),m_rbAFrame(rbAFrame), m_angularOnly(false) { m_rbBFrame = m_rbAFrame; + // flip axis for correct angles + m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + + m_rbBFrame.getBasis()[2][0] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][1] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + m_swingSpan1 = btScalar(1e30); m_swingSpan2 = btScalar(1e30); m_twistSpan = btScalar(1e30); @@ -114,39 +127,22 @@ void btConeTwistConstraint::buildJacobian() btScalar swing1=btScalar(0.),swing2 = btScalar(0.); - btScalar swx=btScalar(0.),swy = btScalar(0.); - btScalar thresh = btScalar(10.); - btScalar fact; - // Get Frame into world space if (m_swingSpan1 >= btScalar(0.05f)) { b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); -// swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); - swx = b2Axis1.dot(b1Axis1); - swy = b2Axis1.dot(b1Axis2); - swing1 = btAtan2Fast(swy, swx); - fact = (swy*swy + swx*swx) * thresh * thresh; - fact = fact / (fact + btScalar(1.0)); - swing1 *= fact; - + swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); } if (m_swingSpan2 >= btScalar(0.05f)) { b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); -// swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); - swx = b2Axis1.dot(b1Axis1); - swy = b2Axis1.dot(b1Axis3); - swing2 = btAtan2Fast(swy, swx); - fact = (swy*swy + swx*swx) * thresh * thresh; - fact = fact / (fact + btScalar(1.0)); - swing2 *= fact; + swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); } btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); - btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq; + btScalar EllipseAngle = btFabs(swing1)* RMaxAngle1Sq + btFabs(swing2) * RMaxAngle2Sq; if (EllipseAngle > 1.0f) { @@ -250,7 +246,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, 0.0f ); impulseMag = m_accSwingLimitImpulse - temp; btVector3 impulse = m_swingAxis * impulseMag; @@ -268,7 +264,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, 0.0f ); impulseMag = m_accTwistLimitImpulse - temp; btVector3 impulse = m_twistAxis * impulseMag; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index f121919c8f9..874669c80b3 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -30,9 +30,6 @@ class btRigidBody; ///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) class btConeTwistConstraint : public btTypedConstraint { -#ifdef IN_PARALLELL_SOLVER -public: -#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btTransform m_rbAFrame; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h index 7a8e9c1953d..7e8458c2c7b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef CONSTRAINT_SOLVER_H #define CONSTRAINT_SOLVER_H -#include "LinearMath/btScalar.h" +#include "../../LinearMath/btScalar.h" class btPersistentManifold; class btRigidBody; @@ -26,7 +26,7 @@ struct btContactSolverInfo; struct btBroadphaseProxy; class btIDebugDraw; class btStackAlloc; -class btDispatcher; + /// btConstraintSolver provides solver interface class btConstraintSolver { @@ -35,15 +35,8 @@ public: virtual ~btConstraintSolver() {} - virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;} + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0; - ///solve a group of constraints - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0; - - virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */, btStackAlloc* /* stackAlloc */) {;} - - ///clear internal cached data and reset random seed - virtual void reset() = 0; }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index 4d7cd05feb7..bb3fe832592 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -192,8 +192,8 @@ btScalar resolveSingleFriction( j1 = -vrel * cpd->m_jacDiagABInvTangent0; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; - btSetMin(cpd->m_accumulatedTangentImpulse0, limit); - btSetMax(cpd->m_accumulatedTangentImpulse0, -limit); + GEN_set_min(cpd->m_accumulatedTangentImpulse0, limit); + GEN_set_max(cpd->m_accumulatedTangentImpulse0, -limit); j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; } @@ -206,8 +206,8 @@ btScalar resolveSingleFriction( j2 = -vrel * cpd->m_jacDiagABInvTangent1; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; - btSetMin(cpd->m_accumulatedTangentImpulse1, limit); - btSetMax(cpd->m_accumulatedTangentImpulse1, -limit); + GEN_set_min(cpd->m_accumulatedTangentImpulse1, limit); + GEN_set_max(cpd->m_accumulatedTangentImpulse1, -limit); j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; } @@ -233,12 +233,6 @@ btScalar resolveSingleFriction( } -btScalar resolveSingleFrictionOriginal( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo); - btScalar resolveSingleFrictionOriginal( btRigidBody& body1, btRigidBody& body2, @@ -276,8 +270,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; btScalar total = cpd->m_accumulatedTangentImpulse0 + j; - btSetMin(total, limit); - btSetMax(total, -limit); + GEN_set_min(total, limit); + GEN_set_max(total, -limit); j = total - cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); @@ -296,8 +290,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; btScalar total = cpd->m_accumulatedTangentImpulse1 + j; - btSetMin(total, limit); - btSetMax(total, -limit); + GEN_set_min(total, limit); + GEN_set_max(total, -limit); j = total - cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); @@ -394,8 +388,8 @@ btScalar resolveSingleCollisionCombined( (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; - btSetMin(friction_impulse, normal_impulse); - btSetMax(friction_impulse, -normal_impulse); + GEN_set_min(friction_impulse, normal_impulse); + GEN_set_max(friction_impulse, -normal_impulse); body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); } @@ -406,12 +400,6 @@ btScalar resolveSingleCollisionCombined( return normalImpulse; } -btScalar resolveSingleFrictionEmpty( - btRigidBody& body1, - btRigidBody& body2, - btManifoldPoint& contactPoint, - const btContactSolverInfo& solverInfo); - btScalar resolveSingleFrictionEmpty( btRigidBody& body1, btRigidBody& body2, diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index 826e79f78bd..0834deddeac 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -19,8 +19,8 @@ subject to the following restrictions: //todo: make into a proper class working with the iterative constraint solver class btRigidBody; -#include "LinearMath/btVector3.h" -#include "LinearMath/btScalar.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btScalar.h" struct btContactSolverInfo; class btManifoldPoint; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index 916d4581f79..c3c73e300f4 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -16,42 +16,9 @@ subject to the following restrictions: #ifndef CONTACT_SOLVER_INFO #define CONTACT_SOLVER_INFO -enum btSolverMode + +struct btContactSolverInfo { - SOLVER_RANDMIZE_ORDER = 1, - SOLVER_FRICTION_SEPARATE = 2, - SOLVER_USE_WARMSTARTING = 4, - SOLVER_CACHE_FRIENDLY = 8 -}; - -struct btContactSolverInfoData -{ - - - btScalar m_tau; - btScalar m_damping; - btScalar m_friction; - btScalar m_timeStep; - btScalar m_restitution; - int m_numIterations; - btScalar m_maxErrorReduction; - btScalar m_sor; - btScalar m_erp;//used as Baumgarte factor - btScalar m_erp2;//used in Split Impulse - int m_splitImpulse; - btScalar m_splitImpulsePenetrationThreshold; - btScalar m_linearSlop; - btScalar m_warmstartingFactor; - - int m_solverMode; - - -}; - -struct btContactSolverInfo : public btContactSolverInfoData -{ - - inline btContactSolverInfo() { @@ -61,15 +28,20 @@ struct btContactSolverInfo : public btContactSolverInfoData m_restitution = btScalar(0.); m_maxErrorReduction = btScalar(20.); m_numIterations = 10; - m_erp = btScalar(0.2); - m_erp2 = btScalar(0.1); + m_erp = btScalar(0.4); m_sor = btScalar(1.3); - m_splitImpulse = false; - m_splitImpulsePenetrationThreshold = -0.02f; - m_linearSlop = btScalar(0.0); - m_warmstartingFactor=btScalar(0.85); - m_solverMode = SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY | SOLVER_USE_WARMSTARTING; } + + btScalar m_tau; + btScalar m_damping; + btScalar m_friction; + btScalar m_timeStep; + btScalar m_restitution; + int m_numIterations; + btScalar m_maxErrorReduction; + btScalar m_sor; + btScalar m_erp; + }; #endif //CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index 077b326d13a..747d10d1f8b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -4,20 +4,14 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -/* -2007-09-09 -Refactored by Francisco Le?n -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ #include "btGeneric6DofConstraint.h" @@ -25,504 +19,371 @@ http://gimpact.sf.net #include "LinearMath/btTransformUtil.h" #include - static const btScalar kSign[] = { btScalar(1.0), btScalar(-1.0), btScalar(1.0) }; static const int kAxisA[] = { 1, 0, 0 }; static const int kAxisB[] = { 2, 2, 1 }; #define GENERIC_D6_DISABLE_WARMSTARTING 1 -btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); -btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) +btGeneric6DofConstraint::btGeneric6DofConstraint() { - int i = index%3; - int j = index/3; - return mat[i][j]; +} + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) +: btTypedConstraint(rbA, rbB) +, m_frameInA(frameInA) +, m_frameInB(frameInB) +{ + //free means upper < lower, + //locked means upper == lower + //limited means upper > lower + //so start all locked + for (int i=0; i<6;++i) + { + m_lowerLimit[i] = btScalar(0.0); + m_upperLimit[i] = btScalar(0.0); + m_accumulatedImpulse[i] = btScalar(0.0); + } + +} + + +void btGeneric6DofConstraint::buildJacobian() +{ + btVector3 localNormalInA(0,0,0); + + const btVector3& pivotInA = m_frameInA.getOrigin(); + const btVector3& pivotInB = m_frameInB.getOrigin(); + + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); + + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + int i; + //linear part + for (i=0;i<3;i++) + { + if (isLimited(i)) + { + localNormalInA[i] = 1; + btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; + + + // Create linear atom + new (&m_jacLinear[i]) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getCenterOfMassTransform()*pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*pivotInB - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + + //optionally disable warmstarting +#ifdef GENERIC_D6_DISABLE_WARMSTARTING + m_accumulatedImpulse[i] = btScalar(0.); +#endif //GENERIC_D6_DISABLE_WARMSTARTING + + // Apply accumulated impulse + btVector3 impulse_vector = m_accumulatedImpulse[i] * normalWorld; + + m_rbA.applyImpulse( impulse_vector, rel_pos1); + m_rbB.applyImpulse(-impulse_vector, rel_pos2); + + localNormalInA[i] = 0; + } + } + + // angular part + for (i=0;i<3;i++) + { + if (isLimited(i+3)) + { + btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); + btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); + + // Dirk: This is IMO mathematically the correct way, but we should consider axisA and axisB being near parallel maybe + btVector3 axis = kSign[i] * axisA.cross(axisB); + + // Create angular atom + new (&m_jacAng[i]) btJacobianEntry(axis, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +#ifdef GENERIC_D6_DISABLE_WARMSTARTING + m_accumulatedImpulse[i + 3] = btScalar(0.); +#endif //GENERIC_D6_DISABLE_WARMSTARTING + + // Apply accumulated impulse + btVector3 impulse_vector = m_accumulatedImpulse[i + 3] * axis; + + m_rbA.applyTorqueImpulse( impulse_vector); + m_rbB.applyTorqueImpulse(-impulse_vector); + } + } +} + +btScalar getMatrixElem(const btMatrix3x3& mat,int index) +{ + int row = index%3; + int col = index / 3; + return mat[row][col]; } ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); -bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +bool MatrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) { -// // rot = cy*cz -cy*sz sy -// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx -// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy -// - - if (btGetMatrixElem(mat,2) < btScalar(1.0)) - { - if (btGetMatrixElem(mat,2) > btScalar(-1.0)) - { - xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); - xyz[1] = btAsin(btGetMatrixElem(mat,2)); - xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); - return true; - } - else - { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = -SIMD_HALF_PI; - xyz[2] = btScalar(0.0); - return false; - } - } - else - { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); - xyz[1] = SIMD_HALF_PI; - xyz[2] = 0.0; - - } + // rot = cy*cz -cy*sz sy + // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx + // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +/// 0..8 + if (getMatrixElem(mat,2) < btScalar(1.0)) + { + if (getMatrixElem(mat,2) > btScalar(-1.0)) + { + xyz[0] = btAtan2(-getMatrixElem(mat,5),getMatrixElem(mat,8)); + xyz[1] = btAsin(getMatrixElem(mat,2)); + xyz[2] = btAtan2(-getMatrixElem(mat,1),getMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + + } + return false; } - -//////////////////////////// btRotationalLimitMotor //////////////////////////////////// - - -int btRotationalLimitMotor::testLimitValue(btScalar test_value) +void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) { - if(m_loLimit>m_hiLimit) - { - m_currentLimit = 0;//Free from violation - return 0; - } + btScalar tau = btScalar(0.1); + btScalar damping = btScalar(1.0); - if (test_value < m_loLimit) - { - m_currentLimit = 1;//low limit violation - m_currentLimitError = test_value - m_loLimit; - return 1; - } - else if (test_value> m_hiLimit) - { - m_currentLimit = 2;//High limit violation - m_currentLimitError = test_value - m_hiLimit; - return 2; - }; + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - m_currentLimit = 0;//Free from violation - return 0; + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); -} - - -btScalar btRotationalLimitMotor::solveAngularLimits( - btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, - btRigidBody * body0, btRigidBody * body1) -{ - if (needApplyTorques()==false) return 0.0f; - - btScalar target_velocity = m_targetVelocity; - btScalar maxMotorForce = m_maxMotorForce; - - //current error correction - if (m_currentLimit!=0) - { - target_velocity = -m_ERP*m_currentLimitError/(timeStep); - maxMotorForce = m_maxLimitForce; - } - - maxMotorForce *= timeStep; - - // current velocity difference - btVector3 vel_diff = body0->getAngularVelocity(); - if (body1) - { - vel_diff -= body1->getAngularVelocity(); - } - - - - btScalar rel_vel = axis.dot(vel_diff); - - // correction velocity - btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); - - - if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) - { - return 0.0f;//no need for applying force - } - - - // correction impulse - btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; - - // clip correction impulse - btScalar clippedMotorImpulse; - - //todo: should clip against accumulated impulse - if (unclippedMotorImpulse>0.0f) - { - clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; - } - else - { - clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; - } - - - // sort with accumulated impulses - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - btScalar oldaccumImpulse = m_accumulatedImpulse; - btScalar sum = oldaccumImpulse + clippedMotorImpulse; - m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - - clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; - - - - btVector3 motorImp = clippedMotorImpulse * axis; - - - body0->applyTorqueImpulse(motorImp); - if (body1) body1->applyTorqueImpulse(-motorImp); - - return clippedMotorImpulse; - - -} - -//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// - -//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// -btScalar btTranslationalLimitMotor::solveLinearAxis( - btScalar timeStep, - btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, - int limit_index, - const btVector3 & axis_normal_on_a, - const btVector3 & anchorPos) -{ - -///find relative velocity -// btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); -// btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); - btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); - btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); - - btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - - btScalar rel_vel = axis_normal_on_a.dot(vel); - - - -/// apply displacement correction - -//positional error (zeroth order error) - btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - btScalar minLimit = m_lowerLimit[limit_index]; - btScalar maxLimit = m_upperLimit[limit_index]; - - //handle the limits - if (minLimit < maxLimit) - { - { - if (depth > maxLimit) - { - depth -= maxLimit; - lo = btScalar(0.); - - } - else - { - if (depth < minLimit) - { - depth -= minLimit; - hi = btScalar(0.); - } - else - { - return 0.0f; - } - } - } - } - - btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; - - - - - btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; - - btVector3 impulse_vector = axis_normal_on_a * normalImpulse; - body1.applyImpulse( impulse_vector, rel_pos1); - body2.applyImpulse(-impulse_vector, rel_pos2); - return normalImpulse; -} - -//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// - - -btGeneric6DofConstraint::btGeneric6DofConstraint() - :btTypedConstraint(D6_CONSTRAINT_TYPE), - m_useLinearReferenceFrameA(true) -{ -} - -btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) - : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) - , m_frameInA(frameInA) - , m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) -{ - -} - - - - - -void btGeneric6DofConstraint::calculateAngleInfo() -{ - btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); - - matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); - - - - // in euler angle mode we do not actually constrain the angular velocity - // along the axes axis[0] and axis[2] (although we do use axis[1]) : - // - // to get constrain w2-w1 along ...not - // ------ --------------------- ------ - // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] - // d(angle[1])/dt = 0 ax[1] - // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] - // - // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. - // to prove the result for angle[0], write the expression for angle[0] from - // GetInfo1 then take the derivative. to prove this for angle[2] it is - // easier to take the euler rate expression for d(angle[2])/dt with respect - // to the components of w and set that to 0. - - btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); - btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); - - m_calculatedAxis[1] = axis2.cross(axis0); - m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); - m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); - - -// if(m_debugDrawer) -// { -// -// char buff[300]; -// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", -// m_calculatedAxisAngleDiff[0], -// m_calculatedAxisAngleDiff[1], -// m_calculatedAxisAngleDiff[2]); -// m_debugDrawer->reportErrorWarning(buff); -// } - -} - -void btGeneric6DofConstraint::calculateTransforms() -{ - m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; - m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; - - calculateAngleInfo(); -} - - -void btGeneric6DofConstraint::buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW) -{ - new (&jacLinear) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normalWorld, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - -} - -void btGeneric6DofConstraint::buildAngularJacobian( - btJacobianEntry & jacAngular,const btVector3 & jointAxisW) -{ - new (&jacAngular) btJacobianEntry(jointAxisW, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - -} - -bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) -{ - btScalar angle = m_calculatedAxisAngleDiff[axis_index]; - - //test limits - m_angularLimits[axis_index].testLimitValue(angle); - return m_angularLimits[axis_index].needApplyTorques(); -} - -void btGeneric6DofConstraint::buildJacobian() -{ - - // Clear accumulated impulses for the next simulation step - m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); - int i; - for(i = 0; i < 3; i++) - { - m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); - } - //calculates transform - calculateTransforms(); - -// const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); -// const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); - calcAnchorPos(); - btVector3 pivotAInW = m_AnchorPos; - btVector3 pivotBInW = m_AnchorPos; - -// not used here -// btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); -// btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 normalWorld; - //linear part - for (i=0;i<3;i++) - { - if (m_linearLimits.isLimited(i)) - { - if (m_useLinearReferenceFrameA) - normalWorld = m_calculatedTransformA.getBasis().getColumn(i); - else - normalWorld = m_calculatedTransformB.getBasis().getColumn(i); - - buildLinearJacobian( - m_jacLinear[i],normalWorld , - pivotAInW,pivotBInW); - - } - } - - // angular part - for (i=0;i<3;i++) - { - //calculates error angle - if (testAngularLimitMotor(i)) - { - normalWorld = this->getAxis(i); - // Create angular atom - buildAngularJacobian(m_jacAng[i],normalWorld); - } - } - - -} - - -void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) -{ - m_timeStep = timeStep; - - //calculateTransforms(); - - int i; - - // linear - - btVector3 pointInA = m_calculatedTransformA.getOrigin(); - btVector3 pointInB = m_calculatedTransformB.getOrigin(); - - btScalar jacDiagABInv; - btVector3 linear_axis; - for (i=0;i<3;i++) - { - if (m_linearLimits.isLimited(i)) - { - jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); - - if (m_useLinearReferenceFrameA) - linear_axis = m_calculatedTransformA.getBasis().getColumn(i); - else - linear_axis = m_calculatedTransformB.getBasis().getColumn(i); - - m_linearLimits.solveLinearAxis( - m_timeStep, - jacDiagABInv, - m_rbA,pointInA, - m_rbB,pointInB, - i,linear_axis, m_AnchorPos); - - } - } - - // angular - btVector3 angular_axis; - btScalar angularJacDiagABInv; - for (i=0;i<3;i++) - { - if (m_angularLimits[i].needApplyTorques()) - { - - // get axis - angular_axis = getAxis(i); - - angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); - - m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); - } - } + btVector3 localNormalInA(0,0,0); + int i; + + // linear + for (i=0;i<3;i++) + { + if (isLimited(i)) + { + btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); + btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + + localNormalInA.setValue(0,0,0); + localNormalInA[i] = 1; + btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; + + btScalar jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); + + //velocity error (first order error) + btScalar rel_vel = m_jacLinear[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, + m_rbB.getLinearVelocity(),angvelB); + + //positional error (zeroth order error) + btScalar depth = -(pivotAInW - pivotBInW).dot(normalWorld); + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + //handle the limits + if (m_lowerLimit[i] < m_upperLimit[i]) + { + { + if (depth > m_upperLimit[i]) + { + depth -= m_upperLimit[i]; + lo = btScalar(0.); + + } else + { + if (depth < m_lowerLimit[i]) + { + depth -= m_lowerLimit[i]; + hi = btScalar(0.); + } else + { + continue; + } + } + } + } + + btScalar normalImpulse= (tau*depth/timeStep - damping*rel_vel) * jacDiagABInv; + btScalar oldNormalImpulse = m_accumulatedImpulse[i]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[i] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[i] - oldNormalImpulse; + + btVector3 impulse_vector = normalWorld * normalImpulse; + m_rbA.applyImpulse( impulse_vector, rel_pos1); + m_rbB.applyImpulse(-impulse_vector, rel_pos2); + + localNormalInA[i] = 0; + } + } + + btVector3 axis; + btScalar angle; + btTransform frameAWorld = m_rbA.getCenterOfMassTransform() * m_frameInA; + btTransform frameBWorld = m_rbB.getCenterOfMassTransform() * m_frameInB; + + btTransformUtil::calculateDiffAxisAngle(frameAWorld,frameBWorld,axis,angle); + btQuaternion diff(axis,angle); + btMatrix3x3 diffMat (diff); + btVector3 xyz; + ///this is not perfect, we can first check which axis are limited, and choose a more appropriate order + MatrixToEulerXYZ(diffMat,xyz); + + // angular + for (i=0;i<3;i++) + { + if (isLimited(i+3)) + { + btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); + btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); + + btScalar jacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); + + //velocity error (first order error) + btScalar rel_vel = m_jacAng[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, + m_rbB.getLinearVelocity(),angvelB); + + //positional error (zeroth order error) + btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); + btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); + + btScalar rel_pos = kSign[i] * axisA.dot(axisB); + + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + //handle the twist limit + if (m_lowerLimit[i+3] < m_upperLimit[i+3]) + { + //clamp the values + btScalar loLimit = m_lowerLimit[i+3] > -3.1415 ? m_lowerLimit[i+3] : btScalar(-1e30); + btScalar hiLimit = m_upperLimit[i+3] < 3.1415 ? m_upperLimit[i+3] : btScalar(1e30); + + btScalar projAngle = btScalar(-1.)*xyz[i]; + + if (projAngle < loLimit) + { + hi = btScalar(0.); + rel_pos = (loLimit - projAngle); + } else + { + if (projAngle > hiLimit) + { + lo = btScalar(0.); + rel_pos = (hiLimit - projAngle); + } else + { + continue; + } + } + } + + //impulse + + btScalar normalImpulse= -(tau*rel_pos/timeStep + damping*rel_vel) * jacDiagABInv; + btScalar oldNormalImpulse = m_accumulatedImpulse[i+3]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[i+3] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[i+3] - oldNormalImpulse; + + // Dirk: Not needed - we could actually project onto Jacobian entry here (same as above) + btVector3 axis = kSign[i] * axisA.cross(axisB); + btVector3 impulse_vector = axis * normalImpulse; + + m_rbA.applyTorqueImpulse( impulse_vector); + m_rbB.applyTorqueImpulse(-impulse_vector); + } + } } void btGeneric6DofConstraint::updateRHS(btScalar timeStep) { - (void)timeStep; + (void)timeStep; } -btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const -{ - return m_calculatedAxis[axis_index]; -} - -btScalar btGeneric6DofConstraint::getAngle(int axis_index) const -{ - return m_calculatedAxisAngleDiff[axis_index]; -} - -void btGeneric6DofConstraint::calcAnchorPos(void) -{ - btScalar imA = m_rbA.getInvMass(); - btScalar imB = m_rbB.getInvMass(); - btScalar weight; - if(imB == btScalar(0.0)) +btScalar btGeneric6DofConstraint::computeAngle(int axis) const { - weight = btScalar(1.0); - } - else - { - weight = imA / (imA + imB); - } - const btVector3& pA = m_calculatedTransformA.getOrigin(); - const btVector3& pB = m_calculatedTransformB.getOrigin(); - m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight); - return; -} // btGeneric6DofConstraint::calcAnchorPos() + btScalar angle = btScalar(0.f); + + switch (axis) + { + case 0: + { + btVector3 v1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(1); + btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); + btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); + + btScalar s = v1.dot(w2); + btScalar c = v1.dot(v2); + + angle = btAtan2( s, c ); + } + break; + + case 1: + { + btVector3 w1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(2); + btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); + btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); + + btScalar s = w1.dot(u2); + btScalar c = w1.dot(w2); + + angle = btAtan2( s, c ); + } + break; + + case 2: + { + btVector3 u1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(0); + btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); + btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); + + btScalar s = u1.dot(v2); + btScalar c = u1.dot(u2); + + angle = btAtan2( s, c ); + } + break; + default: + btAssert ( 0 ) ; + + break ; + } + + return angle; + } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index f0718d2d4a0..b114e54fa69 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -4,433 +4,116 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -/* -2007-09-09 -btGeneric6DofConstraint Refactored by Francisco Le?n -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ - #ifndef GENERIC_6DOF_CONSTRAINT_H #define GENERIC_6DOF_CONSTRAINT_H -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; -//! Rotation Limit structure for generic joints -class btRotationalLimitMotor -{ -public: - //! limit_parameters - //!@{ - btScalar m_loLimit;//!< joint limit - btScalar m_hiLimit;//!< joint limit - btScalar m_targetVelocity;//!< target motor velocity - btScalar m_maxMotorForce;//!< max force on motor - btScalar m_maxLimitForce;//!< max force on limit - btScalar m_damping;//!< Damping. - btScalar m_limitSoftness;//! Relaxation factor - btScalar m_ERP;//!< Error tolerance factor when joint is at limit - btScalar m_bounce;//!< restitution factor - bool m_enableMotor; - - //!@} - - //! temp_variables - //!@{ - btScalar m_currentLimitError;//! How much is violated this limit - int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit - btScalar m_accumulatedImpulse; - //!@} - - btRotationalLimitMotor() - { - m_accumulatedImpulse = 0.f; - m_targetVelocity = 0; - m_maxMotorForce = 0.1f; - m_maxLimitForce = 300.0f; - m_loLimit = -SIMD_INFINITY; - m_hiLimit = SIMD_INFINITY; - m_ERP = 0.5f; - m_bounce = 0.0f; - m_damping = 1.0f; - m_limitSoftness = 0.5f; - m_currentLimit = 0; - m_currentLimitError = 0; - m_enableMotor = false; - } - - btRotationalLimitMotor(const btRotationalLimitMotor & limot) - { - m_targetVelocity = limot.m_targetVelocity; - m_maxMotorForce = limot.m_maxMotorForce; - m_limitSoftness = limot.m_limitSoftness; - m_loLimit = limot.m_loLimit; - m_hiLimit = limot.m_hiLimit; - m_ERP = limot.m_ERP; - m_bounce = limot.m_bounce; - m_currentLimit = limot.m_currentLimit; - m_currentLimitError = limot.m_currentLimitError; - m_enableMotor = limot.m_enableMotor; - } - - - - //! Is limited - bool isLimited() - { - if(m_loLimit>=m_hiLimit) return false; - return true; - } - - //! Need apply correction - bool needApplyTorques() - { - if(m_currentLimit == 0 && m_enableMotor == false) return false; - return true; - } - - //! calculates error - /*! - calculates m_currentLimit and m_currentLimitError. - */ - int testLimitValue(btScalar test_value); - - //! apply the correction impulses for two bodies - btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); - - -}; - - - -class btTranslationalLimitMotor -{ -public: - btVector3 m_lowerLimit;//!< the constraint lower limits - btVector3 m_upperLimit;//!< the constraint upper limits - btVector3 m_accumulatedImpulse; - //! Linear_Limit_parameters - //!@{ - btScalar m_limitSoftness;//!< Softness for linear limit - btScalar m_damping;//!< Damping for linear limit - btScalar m_restitution;//! Bounce parameter for linear limit - //!@} - - btTranslationalLimitMotor() - { - m_lowerLimit.setValue(0.f,0.f,0.f); - m_upperLimit.setValue(0.f,0.f,0.f); - m_accumulatedImpulse.setValue(0.f,0.f,0.f); - - m_limitSoftness = 0.7f; - m_damping = btScalar(1.0f); - m_restitution = btScalar(0.5f); - } - - btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) - { - m_lowerLimit = other.m_lowerLimit; - m_upperLimit = other.m_upperLimit; - m_accumulatedImpulse = other.m_accumulatedImpulse; - - m_limitSoftness = other.m_limitSoftness ; - m_damping = other.m_damping; - m_restitution = other.m_restitution; - } - - //! Test limit - /*! - - free means upper < lower, - - locked means upper == lower - - limited means upper > lower - - limitIndex: first 3 are linear, next 3 are angular - */ - inline bool isLimited(int limitIndex) - { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } - - - btScalar solveLinearAxis( - btScalar timeStep, - btScalar jacDiagABInv, - btRigidBody& body1,const btVector3 &pointInA, - btRigidBody& body2,const btVector3 &pointInB, - int limit_index, - const btVector3 & axis_normal_on_a, - const btVector3 & anchorPos); - - -}; /// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space -/*! -btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. -currently this limit supports rotational motors
-
    -
  • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. -At this moment translational motors are not supported. May be in the future.
  • - -
  • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. -This is accessible through btGeneric6DofConstraint.getLimitMotor method, -This brings support for limit parameters and motors.
  • - -
  • Angulars limits have these possible ranges: - -AXIS - - - - - - - - - - - - -
    MIN ANGLEMAX ANGLEX-PIPIY-PI/2PI/2Z-PI/2PI/2
    -
  • -
- -*/ +/// btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked' +/// Work in progress (is still a Hinge actually) class btGeneric6DofConstraint : public btTypedConstraint { -protected: + btJacobianEntry m_jacLinear[3]; // 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3]; // 3 orthogonal angular constraints - //! relative_frames - //!@{ - btTransform m_frameInA;//!< the constraint space w.r.t body A - btTransform m_frameInB;//!< the constraint space w.r.t body B - //!@} - - //! Jacobians - //!@{ - btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints - btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints - //!@} - - //! Linear_Limit_parameters - //!@{ - btTranslationalLimitMotor m_linearLimits; - //!@} - - - //! hinge_parameters - //!@{ - btRotationalLimitMotor m_angularLimits[3]; - //!@} - - -protected: - //! temporal variables - //!@{ - btScalar m_timeStep; - btTransform m_calculatedTransformA; - btTransform m_calculatedTransformB; - btVector3 m_calculatedAxisAngleDiff; - btVector3 m_calculatedAxis[3]; - - btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes - - bool m_useLinearReferenceFrameA; - - //!@} - - btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } - - - - void buildLinearJacobian( - btJacobianEntry & jacLinear,const btVector3 & normalWorld, - const btVector3 & pivotAInW,const btVector3 & pivotBInW); - - void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); - - - //! calcs the euler angles between the two bodies. - void calculateAngleInfo(); + btTransform m_frameInA; // the constraint space w.r.t body A + btTransform m_frameInB; // the constraint space w.r.t body B + btScalar m_lowerLimit[6]; // the constraint lower limits + btScalar m_upperLimit[6]; // the constraint upper limits + btScalar m_accumulatedImpulse[6]; + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + public: - btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ); - btGeneric6DofConstraint(); + btGeneric6DofConstraint(); - //! Calcs global transform of the offsets - /*! - Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. - \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo - */ - void calculateTransforms(); + + virtual void buildJacobian(); - //! Gets the global transform of the offset for body A - /*! - \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. - */ - const btTransform & getCalculatedTransformA() const - { - return m_calculatedTransformA; - } + virtual void solveConstraint(btScalar timeStep); - //! Gets the global transform of the offset for body B - /*! - \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. - */ - const btTransform & getCalculatedTransformB() const - { - return m_calculatedTransformB; - } + void updateRHS(btScalar timeStep); - const btTransform & getFrameOffsetA() const - { - return m_frameInA; - } + btScalar computeAngle(int axis) const; - const btTransform & getFrameOffsetB() const - { - return m_frameInB; - } + void setLinearLowerLimit(const btVector3& linearLower) + { + m_lowerLimit[0] = linearLower.getX(); + m_lowerLimit[1] = linearLower.getY(); + m_lowerLimit[2] = linearLower.getZ(); + } + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_upperLimit[0] = linearUpper.getX(); + m_upperLimit[1] = linearUpper.getY(); + m_upperLimit[2] = linearUpper.getZ(); + } - btTransform & getFrameOffsetA() - { - return m_frameInA; - } + void setAngularLowerLimit(const btVector3& angularLower) + { + m_lowerLimit[3] = angularLower.getX(); + m_lowerLimit[4] = angularLower.getY(); + m_lowerLimit[5] = angularLower.getZ(); + } - btTransform & getFrameOffsetB() - { - return m_frameInB; - } + void setAngularUpperLimit(const btVector3& angularUpper) + { + m_upperLimit[3] = angularUpper.getX(); + m_upperLimit[4] = angularUpper.getY(); + m_upperLimit[5] = angularUpper.getZ(); + } + //first 3 are linear, next 3 are angular + void SetLimit(int axis, btScalar lo, btScalar hi) + { + m_lowerLimit[axis] = lo; + m_upperLimit[axis] = hi; + } - //! performs Jacobian calculation, and also calculates angle differences and axis - virtual void buildJacobian(); + //free means upper < lower, + //locked means upper == lower + //limited means upper > lower + //limitIndex: first 3 are linear, next 3 are angular + bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } - virtual void solveConstraint(btScalar timeStep); - - void updateRHS(btScalar timeStep); - - //! Get the rotation axis in global coordinates - /*! - \pre btGeneric6DofConstraint.buildJacobian must be called previously. - */ - btVector3 getAxis(int axis_index) const; - - //! Get the relative Euler angle - /*! - \pre btGeneric6DofConstraint.buildJacobian must be called previously. - */ - btScalar getAngle(int axis_index) const; - - //! Test angular limit. - /*! - Calculates angular correction and returns true if limit needs to be corrected. - \pre btGeneric6DofConstraint.buildJacobian must be called previously. - */ - bool testAngularLimitMotor(int axis_index); - - void setLinearLowerLimit(const btVector3& linearLower) - { - m_linearLimits.m_lowerLimit = linearLower; - } - - void setLinearUpperLimit(const btVector3& linearUpper) - { - m_linearLimits.m_upperLimit = linearUpper; - } - - void setAngularLowerLimit(const btVector3& angularLower) - { - m_angularLimits[0].m_loLimit = angularLower.getX(); - m_angularLimits[1].m_loLimit = angularLower.getY(); - m_angularLimits[2].m_loLimit = angularLower.getZ(); - } - - void setAngularUpperLimit(const btVector3& angularUpper) - { - m_angularLimits[0].m_hiLimit = angularUpper.getX(); - m_angularLimits[1].m_hiLimit = angularUpper.getY(); - m_angularLimits[2].m_hiLimit = angularUpper.getZ(); - } - - //! Retrieves the angular limit informacion - btRotationalLimitMotor * getRotationalLimitMotor(int index) - { - return &m_angularLimits[index]; - } - - //! Retrieves the limit informacion - btTranslationalLimitMotor * getTranslationalLimitMotor() - { - return &m_linearLimits; - } - - //first 3 are linear, next 3 are angular - void setLimit(int axis, btScalar lo, btScalar hi) - { - if(axis<3) - { - m_linearLimits.m_lowerLimit[axis] = lo; - m_linearLimits.m_upperLimit[axis] = hi; - } - else - { - m_angularLimits[axis-3].m_loLimit = lo; - m_angularLimits[axis-3].m_hiLimit = hi; - } - } - - //! Test limit - /*! - - free means upper < lower, - - locked means upper == lower - - limited means upper > lower - - limitIndex: first 3 are linear, next 3 are angular - */ - bool isLimited(int limitIndex) - { - if(limitIndex<3) - { - return m_linearLimits.isLimited(limitIndex); - - } - return m_angularLimits[limitIndex-3].isLimited(); - } - - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - - virtual void calcAnchorPos(void); // overridable + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index a0523a8c76b..27e30987549 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -17,185 +17,58 @@ subject to the following restrictions: #include "btHingeConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" -#include "LinearMath/btMinMax.h" #include - -btHingeConstraint::btHingeConstraint() -: btTypedConstraint (HINGE_CONSTRAINT_TYPE), +btHingeConstraint::btHingeConstraint(): m_enableAngularMotor(false) { } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - btVector3& axisInA,btVector3& axisInB) - :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), - m_angularOnly(false), - m_enableAngularMotor(false) + btVector3& axisInA,btVector3& axisInB) +:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), +m_axisInA(axisInA), +m_axisInB(-axisInB), +m_angularOnly(false), +m_enableAngularMotor(false) { - m_rbAFrame.getOrigin() = pivotInA; - - // since no frame is given, assume this to be zero angle and just pick rb transform axis - btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); - - btVector3 rbAxisA2; - btScalar projection = axisInA.dot(rbAxisA1); - if (projection >= 1.0f - SIMD_EPSILON) { - rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2); - rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - } else if (projection <= -1.0f + SIMD_EPSILON) { - rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2); - rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - } else { - rbAxisA2 = axisInA.cross(rbAxisA1); - rbAxisA1 = rbAxisA2.cross(axisInA); - } - - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); - - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); - btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); - - m_rbBFrame.getOrigin() = pivotInB; - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),-axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),-axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),-axisInB.getZ() ); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) +:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), +m_axisInA(axisInA), +//fixed axis in worldspace +m_axisInB(rbA.getCenterOfMassTransform().getBasis() * -axisInA), +m_angularOnly(false), +m_enableAngularMotor(false) { - - // since no frame is given, assume this to be zero angle and just pick rb transform axis - // fixed axis in worldspace - btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); - btScalar projection = rbAxisA1.dot(axisInA); - if (projection > SIMD_EPSILON) - rbAxisA1 = rbAxisA1*projection - axisInA; - else - rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); - - btVector3 rbAxisA2 = axisInA.cross(rbAxisA1); - - m_rbAFrame.getOrigin() = pivotInA; - m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), - rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), - rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); - - - btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA; - - btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); - btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); - btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); - - - m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); - m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), - rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), - rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; -} - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, - const btTransform& rbAFrame, const btTransform& rbBFrame) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), -m_angularOnly(false), -m_enableAngularMotor(false) -{ - // flip axis - m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; -} - - - -btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame) -:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), -m_angularOnly(false), -m_enableAngularMotor(false) -{ - ///not providing rigidbody B means implicitly using worldspace for body B - - // flip axis - m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - - m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); - - //start with free - m_lowerLimit = btScalar(1e30); - m_upperLimit = btScalar(-1e30); - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; } void btHingeConstraint::buildJacobian() { m_appliedImpulse = btScalar(0.); + btVector3 normal(0,0,0); + if (!m_angularOnly) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 relPos = pivotBInW - pivotAInW; - - btVector3 normal[3]; - if (relPos.length2() > SIMD_EPSILON) - { - normal[0] = relPos.normalized(); - } - else - { - normal[0].setValue(btScalar(1.0),0,0); - } - - btPlaneSpace1(normal[0], normal[1], normal[2]); - for (int i=0;i<3;i++) { + normal[i] = 1; new (&m_jac[i]) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), - pivotAInW - m_rbA.getCenterOfMassPosition(), - pivotBInW - m_rbB.getCenterOfMassPosition(), - normal[i], + m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), + m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), + normal, m_rbA.getInvInertiaDiagLocal(), m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); + normal[i] = 0; } } @@ -206,12 +79,12 @@ void btHingeConstraint::buildJacobian() btVector3 jointAxis0local; btVector3 jointAxis1local; - btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); + btPlaneSpace1(m_axisInA,jointAxis0local,jointAxis1local); - getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; - btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; new (&m_jacAng[0]) btJacobianEntry(jointAxis0, m_rbA.getCenterOfMassTransform().getBasis().transpose(), @@ -232,73 +105,44 @@ void btHingeConstraint::buildJacobian() m_rbB.getInvInertiaDiagLocal()); - // Compute limit information - btScalar hingeAngle = getHingeAngle(); - - //set bias, sign, clear accumulator - m_correction = btScalar(0.); - m_limitSign = btScalar(0.); - m_solveLimit = false; - m_accLimitImpulse = btScalar(0.); - -// if (m_lowerLimit < m_upperLimit) - if (m_lowerLimit <= m_upperLimit) - { -// if (hingeAngle <= m_lowerLimit*m_limitSoftness) - if (hingeAngle <= m_lowerLimit) - { - m_correction = (m_lowerLimit - hingeAngle); - m_limitSign = 1.0f; - m_solveLimit = true; - } -// else if (hingeAngle >= m_upperLimit*m_limitSoftness) - else if (hingeAngle >= m_upperLimit) - { - m_correction = m_upperLimit - hingeAngle; - m_limitSign = -1.0f; - m_solveLimit = true; - } - } - - //Compute K = J*W*J' for hinge axis - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + - getRigidBodyB().computeAngularImpulseDenominator(axisA)); } void btHingeConstraint::solveConstraint(btScalar timeStep) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + btVector3 normal(0,0,0); btScalar tau = btScalar(0.3); + btScalar damping = btScalar(1.); - //linear part +//linear part if (!m_angularOnly) { - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; - for (int i=0;i<3;i++) { - const btVector3& normal = m_jac[i].m_linearJointAxis; + normal[i] = 1; btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; btScalar rel_vel; rel_vel = normal.dot(vel); //positional error (zeroth order error) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; + btScalar impulse = depth*tau/timeStep * jacDiagABInv - damping * rel_vel * jacDiagABInv * damping; m_appliedImpulse += impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); + + normal[i] = 0; } } @@ -307,8 +151,8 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) ///solve angular part // get axes in world space - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); - btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_axisInB; const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); @@ -330,7 +174,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) getRigidBodyB().computeAngularImpulseDenominator(normal); // scale for mass and relaxation //todo: expose this 0.9 factor to developer - velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; + velrelOrthog *= (btScalar(1.)/denom) * btScalar(0.9); } //solve angular positional correction @@ -346,28 +190,10 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); m_rbB.applyTorqueImpulse(velrelOrthog-angularError); - - // solve limit - if (m_solveLimit) - { - btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; - - btScalar impulseMag = amplitude * m_kHinge; - - // Clamp the accumulated impulse - btScalar temp = m_accLimitImpulse; - m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); - impulseMag = m_accLimitImpulse - temp; - - - btVector3 impulse = axisA * impulseMag * m_limitSign; - m_rbA.applyTorqueImpulse(impulse); - m_rbB.applyTorqueImpulse(-impulse); - } } //apply motor - if (m_enableAngularMotor) + if (m_enableAngularMotor) { //todo: add limits too btVector3 angularLimit(0,0,0); @@ -378,7 +204,10 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) btScalar desiredMotorVel = m_motorTargetVelocity; btScalar motor_relvel = desiredMotorVel - projRelVel; - btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; + btScalar denom3 = getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA); + + btScalar unclippedMotorImpulse = (btScalar(1.)/denom3) * motor_relvel;; //todo: should clip against accumulated impulse btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; @@ -398,12 +227,3 @@ void btHingeConstraint::updateRHS(btScalar timeStep) } -btScalar btHingeConstraint::getHingeAngle() -{ - const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); - const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); - const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); - - return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1) ); -} - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 4fa9972f6d8..5c1ceafbc5b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -13,61 +13,39 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ - #ifndef HINGECONSTRAINT_H #define HINGECONSTRAINT_H -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; + /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /// axis defines the orientation of the hinge axis class btHingeConstraint : public btTypedConstraint { -#ifdef IN_PARALLELL_SOLVER -public: -#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. - btTransform m_rbBFrame; - - btScalar m_motorTargetVelocity; - btScalar m_maxMotorImpulse; - - btScalar m_limitSoftness; - btScalar m_biasFactor; - btScalar m_relaxationFactor; - - btScalar m_lowerLimit; - btScalar m_upperLimit; - - btScalar m_kHinge; - - btScalar m_limitSign; - btScalar m_correction; - - btScalar m_accLimitImpulse; + btVector3 m_pivotInA; + btVector3 m_pivotInB; + btVector3 m_axisInA; + btVector3 m_axisInB; bool m_angularOnly; - bool m_enableAngularMotor; - bool m_solveLimit; + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + bool m_enableAngularMotor; public: - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB); + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,btVector3& axisInA,btVector3& axisInB); btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); - - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); - - btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame); btHingeConstraint(); @@ -98,61 +76,6 @@ public: m_maxMotorImpulse = maxMotorImpulse; } - void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) - { - m_lowerLimit = low; - m_upperLimit = high; - - m_limitSoftness = _softness; - m_biasFactor = _biasFactor; - m_relaxationFactor = _relaxationFactor; - - } - - btScalar getLowerLimit() const - { - return m_lowerLimit; - } - - btScalar getUpperLimit() const - { - return m_upperLimit; - } - - - btScalar getHingeAngle(); - - - const btTransform& getAFrame() { return m_rbAFrame; }; - const btTransform& getBFrame() { return m_rbBFrame; }; - - inline int getSolveLimit() - { - return m_solveLimit; - } - - inline btScalar getLimitSign() - { - return m_limitSign; - } - - inline bool getAngularOnly() - { - return m_angularOnly; - } - inline bool getEnableAngularMotor() - { - return m_enableAngularMotor; - } - inline btScalar getMotorTargetVelosity() - { - return m_motorTargetVelocity; - } - inline btScalar getMaxMotorImpulse() - { - return m_maxMotorImpulse; - } - }; #endif //HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h index bfeb24c2dfb..aae3ed0373f 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef JACOBIAN_ENTRY_H #define JACOBIAN_ENTRY_H -#include "LinearMath/btVector3.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "../../LinearMath/btVector3.h" +#include "../Dynamics/btRigidBody.h" //notes: diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index 2b69ad90438..aacb0a3ea66 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -21,19 +21,18 @@ subject to the following restrictions: btPoint2PointConstraint::btPoint2PointConstraint() -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) +:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) +:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) { } @@ -100,16 +99,6 @@ void btPoint2PointConstraint::solveConstraint(btScalar timeStep) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal btScalar impulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; - - btScalar impulseClamp = m_setting.m_impulseClamp; - if (impulseClamp > 0) - { - if (impulse < -impulseClamp) - impulse = -impulseClamp; - if (impulse > impulseClamp) - impulse = impulseClamp; - } - m_appliedImpulse+=impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index c9d5968530c..71da8ac0347 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef POINT2POINTCONSTRAINT_H #define POINT2POINTCONSTRAINT_H -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" @@ -26,21 +26,16 @@ struct btConstraintSetting { btConstraintSetting() : m_tau(btScalar(0.3)), - m_damping(btScalar(1.)), - m_impulseClamp(btScalar(0.)) + m_damping(btScalar(1.)) { } btScalar m_tau; btScalar m_damping; - btScalar m_impulseClamp; }; /// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space class btPoint2PointConstraint : public btTypedConstraint { -#ifdef IN_PARALLELL_SOLVER -public: -#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btVector3 m_pivotInA; @@ -75,15 +70,6 @@ public: m_pivotInB = pivotB; } - const btVector3& getPivotInA() const - { - return m_pivotInA; - } - - const btVector3& getPivotInB() const - { - return m_pivotInB; - } }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index b8afbd6aac5..14b36ad44fd 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -13,9 +13,6 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -//#define COMPUTE_IMPULSE_DENOM 1 -//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. -//#define FORCE_REFESH_CONTACT_MANIFOLDS 1 #include "btSequentialImpulseConstraintSolver.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -33,9 +30,11 @@ subject to the following restrictions: #include "btSolverBody.h" #include "btSolverConstraint.h" - #include "LinearMath/btAlignedObjectArray.h" +#ifdef USE_PROFILE +#include "LinearMath/btQuickprof.h" +#endif //USE_PROFILE int totalCpd = 0; @@ -65,7 +64,7 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2() int btSequentialImpulseConstraintSolver::btRandInt2 (int n) { // seems good; xor-fold and modulus - const unsigned long un = static_cast(n); + const unsigned long un = n; unsigned long r = btRand2(); // note: probably more aggressive than it needs to be -- might be @@ -92,12 +91,12 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n) -bool MyContactDestroyedCallback(void* userPersistentData); + bool MyContactDestroyedCallback(void* userPersistentData) { assert (userPersistentData); btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; - btAlignedFree(cpd); + delete cpd; totalCpd--; //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); return true; @@ -106,7 +105,8 @@ bool MyContactDestroyedCallback(void* userPersistentData) btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() -:m_btSeed2(0) +:m_solverMode(SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY), //not using SOLVER_USE_WARMSTARTING, +m_btSeed2(0) { gContactDestroyedCallback = &MyContactDestroyedCallback; @@ -121,42 +121,27 @@ btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() } } -btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() -{ +void initSolverBody(btSolverBody* solverBody, btRigidBody* rigidbody) +{ +/* int size = sizeof(btSolverBody); + int sizeofrb = sizeof(btRigidBody); + int sizemanifold = sizeof(btPersistentManifold); + int sizeofmp = sizeof(btManifoldPoint); + int sizeofPersistData = sizeof (btConstraintPersistentData); +*/ + + solverBody->m_angularVelocity = rigidbody->getAngularVelocity(); + solverBody->m_centerOfMassPosition = rigidbody->getCenterOfMassPosition(); + solverBody->m_friction = rigidbody->getFriction(); +// solverBody->m_invInertiaWorld = rigidbody->getInvInertiaTensorWorld(); + solverBody->m_invMass = rigidbody->getInvMass(); + solverBody->m_linearVelocity = rigidbody->getLinearVelocity(); + solverBody->m_originalBody = rigidbody; + solverBody->m_angularFactor = rigidbody->getAngularFactor(); } -void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); -void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) -{ - btRigidBody* rb = btRigidBody::upcast(collisionObject); - if (rb) - { - solverBody->m_angularVelocity = rb->getAngularVelocity() ; - solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin(); - solverBody->m_friction = collisionObject->getFriction(); - solverBody->m_invMass = rb->getInvMass(); - solverBody->m_linearVelocity = rb->getLinearVelocity(); - solverBody->m_originalBody = rb; - solverBody->m_angularFactor = rb->getAngularFactor(); - } else - { - solverBody->m_angularVelocity.setValue(0,0,0); - solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin(); - solverBody->m_friction = collisionObject->getFriction(); - solverBody->m_invMass = 0.f; - solverBody->m_linearVelocity.setValue(0,0,0); - solverBody->m_originalBody = 0; - solverBody->m_angularFactor = 1.f; - } - solverBody->m_pushVelocity.setValue(0.f,0.f,0.f); - solverBody->m_turnVelocity.setValue(0.f,0.f,0.f); -} - - -int gNumSplitImpulseRecoveries = 0; - -btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); +btScalar penetrationResolveFactor = btScalar(0.9); btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) { btScalar rest = restitution * -rel_vel; @@ -164,95 +149,30 @@ btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) } -void resolveSplitPenetrationImpulseCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - const btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo); - -//SIMD_FORCE_INLINE -void resolveSplitPenetrationImpulseCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - const btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo) -{ - (void)solverInfo; - - if (contactConstraint.m_penetration < solverInfo.m_splitImpulsePenetrationThreshold) - { - - gNumSplitImpulseRecoveries++; - btScalar normalImpulse; - - // Optimized version of projected relative velocity, use precomputed cross products with normal - // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); - // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - // btVector3 vel = vel1 - vel2; - // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); - - btScalar rel_vel; - btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_pushVelocity) - + contactConstraint.m_relpos1CrossNormal.dot(body1.m_turnVelocity); - btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_pushVelocity) - + contactConstraint.m_relpos2CrossNormal.dot(body2.m_turnVelocity); - - rel_vel = vel1Dotn-vel2Dotn; - btScalar positionalError = -contactConstraint.m_penetration * solverInfo.m_erp2/solverInfo.m_timeStep; - // btScalar positionalError = contactConstraint.m_penetration; - - btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; - - btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; - btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; - normalImpulse = penetrationImpulse+velocityImpulse; - - // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse - btScalar oldNormalImpulse = contactConstraint.m_appliedPushImpulse; - btScalar sum = oldNormalImpulse + normalImpulse; - contactConstraint.m_appliedPushImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - - normalImpulse = contactConstraint.m_appliedPushImpulse - oldNormalImpulse; - - body1.internalApplyPushImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); - - body2.internalApplyPushImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); - - } - -} //velocity + friction //response between two dynamic objects with friction - -btScalar resolveSingleCollisionCombinedCacheFriendly( +SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( btSolverBody& body1, btSolverBody& body2, - const btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo); - -//SIMD_FORCE_INLINE -btScalar resolveSingleCollisionCombinedCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - const btSolverConstraint& contactConstraint, + btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo) { (void)solverInfo; - btScalar normalImpulse; - + btScalar normalImpulse(0.f); { + if (contactConstraint.m_penetration < 0.f) + return 0.f; - - // Optimized version of projected relative velocity, use precomputed cross products with normal - // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); - // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - // btVector3 vel = vel1 - vel2; - // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); + // Optimized version of projected relative velocity, use precomputed cross products with normal + // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + // btVector3 vel = vel1 - vel2; + // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); btScalar rel_vel; btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) @@ -262,51 +182,50 @@ btScalar resolveSingleCollisionCombinedCacheFriendly( rel_vel = vel1Dotn-vel2Dotn; - btScalar positionalError = 0.f; - if (!solverInfo.m_splitImpulse || (contactConstraint.m_penetration > solverInfo.m_splitImpulsePenetrationThreshold)) - { - positionalError = -contactConstraint.m_penetration * solverInfo.m_erp/solverInfo.m_timeStep; - } + btScalar positionalError = contactConstraint.m_penetration; btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; - normalImpulse = penetrationImpulse+velocityImpulse; - + btScalar normalImpulse = penetrationImpulse+velocityImpulse; // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; btScalar sum = oldNormalImpulse + normalImpulse; contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; + btScalar velocitySum = oldVelocityImpulse + velocityImpulse; + contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; + normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, + if (body1.m_invMass) + { + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); - - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, + } + if (body2.m_invMass) + { + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); + } + } + + return normalImpulse; } #ifndef NO_FRICTION_TANGENTIALS -btScalar resolveSingleFrictionCacheFriendly( +SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( btSolverBody& body1, btSolverBody& body2, - const btSolverConstraint& contactConstraint, - const btContactSolverInfo& solverInfo, - btScalar appliedNormalImpulse); - -//SIMD_FORCE_INLINE -btScalar resolveSingleFrictionCacheFriendly( - btSolverBody& body1, - btSolverBody& body2, - const btSolverConstraint& contactConstraint, + btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo, btScalar appliedNormalImpulse) { @@ -333,42 +252,22 @@ btScalar resolveSingleFrictionCacheFriendly( // calculate j that moves us to zero relative velocity j1 = -rel_vel * contactConstraint.m_jacDiagABInv; -#define CLAMP_ACCUMULATED_FRICTION_IMPULSE 1 -#ifdef CLAMP_ACCUMULATED_FRICTION_IMPULSE btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; - - if (limit < contactConstraint.m_appliedImpulse) - { - contactConstraint.m_appliedImpulse = limit; - } else - { - if (contactConstraint.m_appliedImpulse < -limit) - contactConstraint.m_appliedImpulse = -limit; - } + GEN_set_min(contactConstraint.m_appliedImpulse, limit); + GEN_set_max(contactConstraint.m_appliedImpulse, -limit); j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; -#else - if (limit < j1) - { - j1 = limit; - } else - { - if (j1 < -limit) - j1 = -limit; - } - -#endif //CLAMP_ACCUMULATED_FRICTION_IMPULSE - - //GEN_set_min(contactConstraint.m_appliedImpulse, limit); - //GEN_set_max(contactConstraint.m_appliedImpulse, -limit); - - } - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); - - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); + if (body1.m_invMass) + { + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); + } + if (body2.m_invMass) + { + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); + } } return 0.f; @@ -410,6 +309,7 @@ btScalar resolveSingleFrictionCacheFriendly( const btVector3& rel_pos2 = contactConstraint.m_rel_posB; + //if (contactConstraint.m_appliedVelocityImpulse > 0.f) if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) { lat_rel_vel = btSqrt(lat_rel_vel); @@ -419,7 +319,7 @@ btScalar resolveSingleFrictionCacheFriendly( btVector3 temp2 = body2.m_invInertiaWorld * rel_pos2.cross(lat_vel); btScalar friction_impulse = lat_rel_vel / (body1.m_invMass + body2.m_invMass + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); - btScalar normal_impulse = contactConstraint.m_appliedImpulse * combinedFriction; + btScalar normal_impulse = contactConstraint.m_appliedVelocityImpulse * combinedFriction; GEN_set_min(friction_impulse, normal_impulse); GEN_set_max(friction_impulse, -normal_impulse); @@ -433,111 +333,39 @@ btScalar resolveSingleFrictionCacheFriendly( #endif //NO_FRICTION_TANGENTIALS +btAlignedObjectArray tmpSolverBodyPool; +btAlignedObjectArray tmpSolverConstraintPool; +btAlignedObjectArray tmpSolverFrictionConstraintPool; - - -void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation) +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) { - - btRigidBody* body0=btRigidBody::upcast(colObj0); - btRigidBody* body1=btRigidBody::upcast(colObj1); - - btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = normalAxis; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - solverConstraint.m_originalContactPoint = 0; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedPushImpulse = 0.f; - solverConstraint.m_penetration = 0.f; - { - btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0); - } - { - btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0); - } - -#ifdef COMPUTE_IMPULSE_DENOM - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); -#else - btVector3 vec; - btScalar denom0 = 0.f; - btScalar denom1 = 0.f; - if (body0) - { - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); - denom0 = body0->getInvMass() + normalAxis.dot(vec); - } - if (body1) - { - vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); - denom1 = body1->getInvMass() + normalAxis.dot(vec); - } - - -#endif //COMPUTE_IMPULSE_DENOM - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; - - -} - - - -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** /*bodies */,int /*numBodies */,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) -{ - BT_PROFILE("solveGroupCacheFriendlySetup"); (void)stackAlloc; (void)debugDrawer; - if (!(numConstraints + numManifolds)) { // printf("empty\n"); return 0.f; } - btPersistentManifold* manifold = 0; - btCollisionObject* colObj0=0,*colObj1=0; - - //btRigidBody* rb0=0,*rb1=0; - - -#ifdef FORCE_REFESH_CONTACT_MANIFOLDS BEGIN_PROFILE("refreshManifolds"); int i; - - - for (i=0;igetBody1(); - rb0 = (btRigidBody*)manifold->getBody0(); - + btPersistentManifold* manifold = manifoldPtr[i]; + btRigidBody* rb0 = (btRigidBody*)manifold->getBody0(); + btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); + manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); } - - END_PROFILE("refreshManifolds"); -#endif //FORCE_REFESH_CONTACT_MANIFOLDS - + END_PROFILE("refreshManifolds"); + BEGIN_PROFILE("gatherSolverData"); //int sizeofSB = sizeof(btSolverBody); //int sizeofSC = sizeof(btSolverConstraint); @@ -554,12 +382,10 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol //todo: use stack allocator for this temp memory -// int minReservation = numManifolds*2; + int minReservation = numManifolds*2; - //m_tmpSolverBodyPool.reserve(minReservation); + tmpSolverBodyPool.reserve(minReservation); - //don't convert all bodies, only the one we need so solver the constraints -/* { for (int i=0;igetIslandTag() >= 0)) { btAssert(rb->getCompanionId() < 0); - int solverBodyId = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + int solverBodyId = tmpSolverBodyPool.size(); + btSolverBody& solverBody = tmpSolverBodyPool.expand(); initSolverBody(&solverBody,rb); rb->setCompanionId(solverBodyId); } } } -*/ - - //m_tmpSolverConstraintPool.reserve(minReservation); - //m_tmpSolverFrictionConstraintPool.reserve(minReservation); + + tmpSolverConstraintPool.reserve(minReservation); + tmpSolverFrictionConstraintPool.reserve(minReservation); { int i; for (i=0;igetBody0(); - colObj1 = (btCollisionObject*)manifold->getBody1(); + btPersistentManifold* manifold = manifoldPtr[i]; + btRigidBody* rb0 = (btRigidBody*)manifold->getBody0(); + btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); + int solverBodyIdA=-1; int solverBodyIdB=-1; @@ -596,108 +422,61 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol - if (colObj0->getIslandTag() >= 0) + if (rb0->getIslandTag() >= 0) { - if (colObj0->getCompanionId() >= 0) - { - //body has already been converted - solverBodyIdA = colObj0->getCompanionId(); - } else - { - solverBodyIdA = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,colObj0); - colObj0->setCompanionId(solverBodyIdA); - } + solverBodyIdA = rb0->getCompanionId(); } else { //create a static body - solverBodyIdA = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,colObj0); + solverBodyIdA = tmpSolverBodyPool.size(); + btSolverBody& solverBody = tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb0); } - if (colObj1->getIslandTag() >= 0) + if (rb1->getIslandTag() >= 0) { - if (colObj1->getCompanionId() >= 0) - { - solverBodyIdB = colObj1->getCompanionId(); - } else - { - solverBodyIdB = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,colObj1); - colObj1->setCompanionId(solverBodyIdB); - } + solverBodyIdB = rb1->getCompanionId(); } else { //create a static body - solverBodyIdB = m_tmpSolverBodyPool.size(); - btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,colObj1); + solverBodyIdB = tmpSolverBodyPool.size(); + btSolverBody& solverBody = tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,rb1); } } - btVector3 rel_pos1; - btVector3 rel_pos2; - btScalar relaxation; - for (int j=0;jgetNumContacts();j++) { btManifoldPoint& cp = manifold->getContactPoint(j); - + + int frictionIndex = tmpSolverConstraintPool.size(); + if (cp.getDistance() <= btScalar(0.)) { const btVector3& pos1 = cp.getPositionWorldOnA(); const btVector3& pos2 = cp.getPositionWorldOnB(); - rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); - rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); + btVector3 rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); + btVector3 rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); - relaxation = 1.f; - btScalar rel_vel; - btVector3 vel; - - int frictionIndex = m_tmpSolverConstraintPool.size(); + btScalar relaxation = 1.f; { - btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand(); - btRigidBody* rb0 = btRigidBody::upcast(colObj0); - btRigidBody* rb1 = btRigidBody::upcast(colObj1); + btSolverConstraint& solverConstraint = tmpSolverConstraintPool.expand(); solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; - solverConstraint.m_originalContactPoint = &cp; + - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0 : btVector3(0,0,0); - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1 : btVector3(0,0,0); { -#ifdef COMPUTE_IMPULSE_DENOM + //can be optimized, the cross products are already calculated btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); -#else - btVector3 vec; - btScalar denom0 = 0.f; - btScalar denom1 = 0.f; - if (rb0) - { - vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); - denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); - } - if (rb1) - { - vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); - denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); - } -#endif //COMPUTE_IMPULSE_DENOM - btScalar denom = relaxation/(denom0+denom1); solverConstraint.m_jacDiagABInv = denom; } @@ -707,115 +486,121 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB); - btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); - btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); + btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2); - vel = vel1 - vel2; - + btVector3 vel = vel1 - vel2; + btScalar rel_vel; rel_vel = cp.m_normalWorldOnB.dot(vel); - solverConstraint.m_penetration = btMin(cp.getDistance()+infoGlobal.m_linearSlop,btScalar(0.)); - //solverConstraint.m_penetration = cp.getDistance(); + solverConstraint.m_penetration = cp.getDistance();///btScalar(infoGlobal.m_numIterations); solverConstraint.m_friction = cp.m_combinedFriction; - solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); - if (solverConstraint.m_restitution <= btScalar(0.)) + btScalar rest = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (rest <= btScalar(0.)) { - solverConstraint.m_restitution = 0.f; + rest = 0.f; }; - btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; + if (rest > penVel) + { + rest = btScalar(0.); + } + solverConstraint.m_restitution = rest; - + solverConstraint.m_penetration *= -(infoGlobal.m_erp/infoGlobal.m_timeStep); - if (solverConstraint.m_restitution > penVel) - { - solverConstraint.m_penetration = btScalar(0.); - } - + solverConstraint.m_appliedImpulse = 0.f; + solverConstraint.m_appliedVelocityImpulse = 0.f; - - ///warm starting (or zero if disabled) - if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; - if (rb0) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); - if (rb1) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); - } else - { - solverConstraint.m_appliedImpulse = 0.f; - } - - solverConstraint.m_appliedPushImpulse = 0.f; - - solverConstraint.m_frictionIndex = m_tmpSolverFrictionConstraintPool.size(); - if (!cp.m_lateralFrictionInitialized) - { - cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; - btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); - if (lat_rel_vel > SIMD_EPSILON)//0.0f) - { - cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); - cp.m_lateralFrictionDir2.normalize();//?? - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - } else - { - //re-calculate friction direction every frame, todo: check if this is really needed - - btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - } - cp.m_lateralFrictionInitialized = true; - - } else - { - addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); - } - - { - btSolverConstraint& frictionConstraint1 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex]; - if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; - if (rb0) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); - if (rb1) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); - } else - { - frictionConstraint1.m_appliedImpulse = 0.f; - } - } - { - btSolverConstraint& frictionConstraint2 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; - if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) - { - frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; - if (rb0) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); - if (rb1) - m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse); - } else - { - frictionConstraint2.m_appliedImpulse = 0.f; - } - } + + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; } + //create 2 '1d axis' constraints for 2 tangential friction directions + + //re-calculate friction direction every frame, todo: check if this is really needed + btVector3 frictionTangential0a, frictionTangential1b; + + btPlaneSpace1(cp.m_normalWorldOnB,frictionTangential0a,frictionTangential1b); + + { + btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = frictionTangential0a; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedVelocityImpulse = 0.f; + + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + + { + btVector3 ftorqueAxis0 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis0; + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis0; + } + { + btVector3 ftorqueAxis0 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis0; + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis0; + } + + } + + + { + + btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = frictionTangential1b; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedVelocityImpulse = 0.f; + + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; + } + } } } } } } - + END_PROFILE("gatherSolverData"); + + BEGIN_PROFILE("prepareConstraints"); + btContactSolverInfo info = infoGlobal; { @@ -827,60 +612,57 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCol } } - + btAlignedObjectArray gOrderTmpConstraintPool; + btAlignedObjectArray gOrderFrictionConstraintPool; - int numConstraintPool = m_tmpSolverConstraintPool.size(); - int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); + int numConstraintPool = tmpSolverConstraintPool.size(); + int numFrictionPool = tmpSolverFrictionConstraintPool.size(); ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints - m_orderTmpConstraintPool.resize(numConstraintPool); - m_orderFrictionConstraintPool.resize(numFrictionPool); + gOrderTmpConstraintPool.resize(numConstraintPool); + gOrderFrictionConstraintPool.resize(numFrictionPool); { int i; for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); + tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); + tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); } - constraint->solveConstraint(infoGlobal.m_timeStep); + constraint->solveConstraint(info.m_timeStep); if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); + tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); + tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); } } { - int numPoolConstraints = m_tmpSolverConstraintPool.size(); + int numPoolConstraints = tmpSolverConstraintPool.size(); for (j=0;jm_appliedImpulse = solveManifold.m_appliedImpulse; - pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; - pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; - - //do a callback here? - - } - - if (infoGlobal.m_splitImpulse) - { - for ( i=0;igetBody0(), (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); } - } } + END_PROFILE("solveConstraints"); + + +#ifdef USE_PROFILE + btProfiler::endBlock("solve"); +#endif //USE_PROFILE + @@ -1140,14 +878,13 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop { -#ifdef FORCE_REFESH_CONTACT_MANIFOLDS manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); -#endif //FORCE_REFESH_CONTACT_MANIFOLDS + int numpoints = manifoldPtr->getNumContacts(); gTotalContactPoints += numpoints; - + btVector3 color(0,1,0); for (int i=0;igetContactPoint(i); @@ -1188,9 +925,7 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol } else { - //todo: should this be in a pool? - void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); - cpd = new (mem)btConstraintPersistentData; + cpd = new btConstraintPersistentData; assert(cpd); totalCpd ++; @@ -1237,9 +972,10 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol cpd->m_penetration = btScalar(0.); } + btScalar relaxation = info.m_damping; - if (info.m_solverMode & SOLVER_USE_WARMSTARTING) + if (m_solverMode & SOLVER_USE_WARMSTARTING) { cpd->m_appliedImpulse *= relaxation; } else @@ -1324,12 +1060,16 @@ btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRig { - + btVector3 color(0,1,0); { if (cp.getDistance() <= btScalar(0.)) { - + if (iter == 0) + { + if (debugDrawer) + debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } { @@ -1358,12 +1098,16 @@ btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBo { - + btVector3 color(0,1,0); { if (cp.getDistance() <= btScalar(0.)) { - + if (iter == 0) + { + if (debugDrawer) + debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } { @@ -1392,7 +1136,7 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b { - + btVector3 color(0,1,0); { if (cp.getDistance() <= btScalar(0.)) @@ -1412,11 +1156,3 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b } return btScalar(0.); } - - -void btSequentialImpulseConstraintSolver::reset() -{ - m_btSeed2 = 0; -} - - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 7143bc41991..13e70c41be4 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -19,8 +19,7 @@ subject to the following restrictions: #include "btConstraintSolver.h" class btIDebugDraw; #include "btContactConstraint.h" -#include "btSolverBody.h" -#include "btSolverConstraint.h" + /// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses @@ -30,29 +29,29 @@ class btIDebugDraw; class btSequentialImpulseConstraintSolver : public btConstraintSolver { - btAlignedObjectArray m_tmpSolverBodyPool; - btAlignedObjectArray m_tmpSolverConstraintPool; - btAlignedObjectArray m_tmpSolverFrictionConstraintPool; - btAlignedObjectArray m_orderTmpConstraintPool; - btAlignedObjectArray m_orderFrictionConstraintPool; - - protected: btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer); - void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation); ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; - + //choose between several modes, different friction model etc. + int m_solverMode; ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction unsigned long m_btSeed2; public: - + enum eSolverMode + { + SOLVER_RANDMIZE_ORDER = 1, + SOLVER_FRICTION_SEPARATE = 2, + SOLVER_USE_WARMSTARTING = 4, + SOLVER_CACHE_FRIENDLY = 8 + }; + btSequentialImpulseConstraintSolver(); ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody @@ -69,22 +68,25 @@ public: m_frictionDispatch[type0][type1] = func; } - virtual ~btSequentialImpulseConstraintSolver(); + virtual ~btSequentialImpulseConstraintSolver() {} - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc); virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); - btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); - btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); - - - ///clear internal cached data and reset random seed - virtual void reset(); btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); - + void setSolverMode(int mode) + { + m_solverMode = mode; + } + + int getSolverMode() const + { + return m_solverMode; + } + unsigned long btRand2(); int btRandInt2 (int n); @@ -100,9 +102,7 @@ public: }; -#ifndef BT_PREFER_SIMD -typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered; -#endif + #endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp deleted file mode 100644 index 4128f504bf1..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -Added by Roman Ponomarev (rponom@gmail.com) -April 04, 2008 -*/ - -//----------------------------------------------------------------------------- - -#include "btSliderConstraint.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btTransformUtil.h" -#include - -//----------------------------------------------------------------------------- - -void btSliderConstraint::initParams() -{ - m_lowerLinLimit = btScalar(1.0); - m_upperLinLimit = btScalar(-1.0); - m_lowerAngLimit = btScalar(0.); - m_upperAngLimit = btScalar(0.); - m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingDirLin = btScalar(0.); - m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingDirAng = btScalar(0.); - m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; - m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; - m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; - m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; - - m_poweredLinMotor = false; - m_targetLinMotorVelocity = btScalar(0.); - m_maxLinMotorForce = btScalar(0.); - m_accumulatedLinMotorImpulse = btScalar(0.0); - - m_poweredAngMotor = false; - m_targetAngMotorVelocity = btScalar(0.); - m_maxAngMotorForce = btScalar(0.); - m_accumulatedAngMotorImpulse = btScalar(0.0); - -} // btSliderConstraint::initParams() - -//----------------------------------------------------------------------------- - -btSliderConstraint::btSliderConstraint() - :btTypedConstraint(SLIDER_CONSTRAINT_TYPE), - m_useLinearReferenceFrameA(true) -{ - initParams(); -} // btSliderConstraint::btSliderConstraint() - -//----------------------------------------------------------------------------- - -btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) - : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB) - , m_frameInA(frameInA) - , m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) -{ - initParams(); -} // btSliderConstraint::btSliderConstraint() - -//----------------------------------------------------------------------------- - -void btSliderConstraint::buildJacobian() -{ - if(m_useLinearReferenceFrameA) - { - buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB); - } - else - { - buildJacobianInt(m_rbB, m_rbA, m_frameInB, m_frameInA); - } -} // btSliderConstraint::buildJacobian() - -//----------------------------------------------------------------------------- - -void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) -{ - //calculate transforms - m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA; - m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB; - m_realPivotAInW = m_calculatedTransformA.getOrigin(); - m_realPivotBInW = m_calculatedTransformB.getOrigin(); - m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X - m_delta = m_realPivotBInW - m_realPivotAInW; - m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; - m_relPosA = m_projPivotInW - rbA.getCenterOfMassPosition(); - m_relPosB = m_realPivotBInW - rbB.getCenterOfMassPosition(); - btVector3 normalWorld; - int i; - //linear part - for(i = 0; i < 3; i++) - { - normalWorld = m_calculatedTransformA.getBasis().getColumn(i); - new (&m_jacLin[i]) btJacobianEntry( - rbA.getCenterOfMassTransform().getBasis().transpose(), - rbB.getCenterOfMassTransform().getBasis().transpose(), - m_relPosA, - m_relPosB, - normalWorld, - rbA.getInvInertiaDiagLocal(), - rbA.getInvMass(), - rbB.getInvInertiaDiagLocal(), - rbB.getInvMass() - ); - m_jacLinDiagABInv[i] = btScalar(1.) / m_jacLin[i].getDiagonal(); - m_depth[i] = m_delta.dot(normalWorld); - } - testLinLimits(); - // angular part - for(i = 0; i < 3; i++) - { - normalWorld = m_calculatedTransformA.getBasis().getColumn(i); - new (&m_jacAng[i]) btJacobianEntry( - normalWorld, - rbA.getCenterOfMassTransform().getBasis().transpose(), - rbB.getCenterOfMassTransform().getBasis().transpose(), - rbA.getInvInertiaDiagLocal(), - rbB.getInvInertiaDiagLocal() - ); - } - testAngLimits(); - btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0); - m_kAngle = btScalar(1.0 )/ (rbA.computeAngularImpulseDenominator(axisA) + rbB.computeAngularImpulseDenominator(axisA)); - // clear accumulator for motors - m_accumulatedLinMotorImpulse = btScalar(0.0); - m_accumulatedAngMotorImpulse = btScalar(0.0); -} // btSliderConstraint::buildJacobianInt() - -//----------------------------------------------------------------------------- - -void btSliderConstraint::solveConstraint(btScalar timeStep) -{ - m_timeStep = timeStep; - if(m_useLinearReferenceFrameA) - { - solveConstraintInt(m_rbA, m_rbB); - } - else - { - solveConstraintInt(m_rbB, m_rbA); - } -} // btSliderConstraint::solveConstraint() - -//----------------------------------------------------------------------------- - -void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) -{ - int i; - // linear - btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA); - btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB); - btVector3 vel = velA - velB; - for(i = 0; i < 3; i++) - { - const btVector3& normal = m_jacLin[i].m_linearJointAxis; - btScalar rel_vel = normal.dot(vel); - // calculate positional error - btScalar depth = m_depth[i]; - // get parameters - btScalar softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin); - btScalar restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin); - btScalar damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin); - // calcutate and apply impulse - btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i]; - btVector3 impulse_vector = normal * normalImpulse; - rbA.applyImpulse( impulse_vector, m_relPosA); - rbB.applyImpulse(-impulse_vector, m_relPosB); - if(m_poweredLinMotor && (!i)) - { // apply linear motor - if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce) - { - btScalar desiredMotorVel = m_targetLinMotorVelocity; - btScalar motor_relvel = desiredMotorVel + rel_vel; - normalImpulse = -motor_relvel * m_jacLinDiagABInv[i]; - // clamp accumulated impulse - btScalar new_acc = m_accumulatedLinMotorImpulse + btFabs(normalImpulse); - if(new_acc > m_maxLinMotorForce) - { - new_acc = m_maxLinMotorForce; - } - btScalar del = new_acc - m_accumulatedLinMotorImpulse; - if(normalImpulse < btScalar(0.0)) - { - normalImpulse = -del; - } - else - { - normalImpulse = del; - } - m_accumulatedLinMotorImpulse = new_acc; - // apply clamped impulse - impulse_vector = normal * normalImpulse; - rbA.applyImpulse( impulse_vector, m_relPosA); - rbB.applyImpulse(-impulse_vector, m_relPosB); - } - } - } - // angular - // get axes in world space - btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0); - btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0); - - const btVector3& angVelA = rbA.getAngularVelocity(); - const btVector3& angVelB = rbB.getAngularVelocity(); - - btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); - btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB); - - btVector3 angAorthog = angVelA - angVelAroundAxisA; - btVector3 angBorthog = angVelB - angVelAroundAxisB; - btVector3 velrelOrthog = angAorthog-angBorthog; - //solve orthogonal angular velocity correction - btScalar len = velrelOrthog.length(); - if (len > btScalar(0.00001)) - { - btVector3 normal = velrelOrthog.normalized(); - btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal); - velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; - } - //solve angular positional correction - btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep); - btScalar len2 = angularError.length(); - if (len2>btScalar(0.00001)) - { - btVector3 normal2 = angularError.normalized(); - btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2); - angularError *= (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; - } - // apply impulse - rbA.applyTorqueImpulse(-velrelOrthog+angularError); - rbB.applyTorqueImpulse(velrelOrthog-angularError); - btScalar impulseMag; - //solve angular limits - if(m_solveAngLim) - { - impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / m_timeStep; - impulseMag *= m_kAngle * m_softnessLimAng; - } - else - { - impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / m_timeStep; - impulseMag *= m_kAngle * m_softnessDirAng; - } - btVector3 impulse = axisA * impulseMag; - rbA.applyTorqueImpulse(impulse); - rbB.applyTorqueImpulse(-impulse); - //apply angular motor - if(m_poweredAngMotor) - { - if(m_accumulatedAngMotorImpulse < m_maxAngMotorForce) - { - btVector3 velrel = angVelAroundAxisA - angVelAroundAxisB; - btScalar projRelVel = velrel.dot(axisA); - - btScalar desiredMotorVel = m_targetAngMotorVelocity; - btScalar motor_relvel = desiredMotorVel - projRelVel; - - btScalar angImpulse = m_kAngle * motor_relvel; - // clamp accumulated impulse - btScalar new_acc = m_accumulatedAngMotorImpulse + btFabs(angImpulse); - if(new_acc > m_maxAngMotorForce) - { - new_acc = m_maxAngMotorForce; - } - btScalar del = new_acc - m_accumulatedAngMotorImpulse; - if(angImpulse < btScalar(0.0)) - { - angImpulse = -del; - } - else - { - angImpulse = del; - } - m_accumulatedAngMotorImpulse = new_acc; - // apply clamped impulse - btVector3 motorImp = angImpulse * axisA; - m_rbA.applyTorqueImpulse(motorImp); - m_rbB.applyTorqueImpulse(-motorImp); - } - } -} // btSliderConstraint::solveConstraint() - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- - -void btSliderConstraint::calculateTransforms(void){ - if(m_useLinearReferenceFrameA) - { - m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; - m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; - } - else - { - m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB; - m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA; - } - m_realPivotAInW = m_calculatedTransformA.getOrigin(); - m_realPivotBInW = m_calculatedTransformB.getOrigin(); - m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X - m_delta = m_realPivotBInW - m_realPivotAInW; - m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; - btVector3 normalWorld; - int i; - //linear part - for(i = 0; i < 3; i++) - { - normalWorld = m_calculatedTransformA.getBasis().getColumn(i); - m_depth[i] = m_delta.dot(normalWorld); - } -} // btSliderConstraint::calculateTransforms() - -//----------------------------------------------------------------------------- - -void btSliderConstraint::testLinLimits(void) -{ - m_solveLinLim = false; - m_linPos = m_depth[0]; - if(m_lowerLinLimit <= m_upperLinLimit) - { - if(m_depth[0] > m_upperLinLimit) - { - m_depth[0] -= m_upperLinLimit; - m_solveLinLim = true; - } - else if(m_depth[0] < m_lowerLinLimit) - { - m_depth[0] -= m_lowerLinLimit; - m_solveLinLim = true; - } - else - { - m_depth[0] = btScalar(0.); - } - } - else - { - m_depth[0] = btScalar(0.); - } -} // btSliderConstraint::testLinLimits() - -//----------------------------------------------------------------------------- - - -void btSliderConstraint::testAngLimits(void) -{ - m_angDepth = btScalar(0.); - m_solveAngLim = false; - if(m_lowerAngLimit <= m_upperAngLimit) - { - const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); - const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); - const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); - btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); - if(rot < m_lowerAngLimit) - { - m_angDepth = rot - m_lowerAngLimit; - m_solveAngLim = true; - } - else if(rot > m_upperAngLimit) - { - m_angDepth = rot - m_upperAngLimit; - m_solveAngLim = true; - } - } -} // btSliderConstraint::testAngLimits() - - -//----------------------------------------------------------------------------- - - - -btVector3 btSliderConstraint::getAncorInA(void) -{ - btVector3 ancorInA; - ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis; - ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA; - return ancorInA; -} // btSliderConstraint::getAncorInA() - -//----------------------------------------------------------------------------- - -btVector3 btSliderConstraint::getAncorInB(void) -{ - btVector3 ancorInB; - ancorInB = m_frameInB.getOrigin(); - return ancorInB; -} // btSliderConstraint::getAncorInB(); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h deleted file mode 100644 index 580dfa1178d..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ /dev/null @@ -1,218 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -Added by Roman Ponomarev (rponom@gmail.com) -April 04, 2008 - -TODO: - - add clamping od accumulated impulse to improve stability - - add conversion for ODE constraint solver -*/ - -#ifndef SLIDER_CONSTRAINT_H -#define SLIDER_CONSTRAINT_H - -//----------------------------------------------------------------------------- - -#include "LinearMath/btVector3.h" -#include "btJacobianEntry.h" -#include "btTypedConstraint.h" - -//----------------------------------------------------------------------------- - -class btRigidBody; - -//----------------------------------------------------------------------------- - -#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) -#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) -#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) - -//----------------------------------------------------------------------------- - -class btSliderConstraint : public btTypedConstraint -{ -protected: - btTransform m_frameInA; - btTransform m_frameInB; - // use frameA fo define limits, if true - bool m_useLinearReferenceFrameA; - // linear limits - btScalar m_lowerLinLimit; - btScalar m_upperLinLimit; - // angular limits - btScalar m_lowerAngLimit; - btScalar m_upperAngLimit; - // softness, restitution and damping for different cases - // DirLin - moving inside linear limits - // LimLin - hitting linear limit - // DirAng - moving inside angular limits - // LimAng - hitting angular limit - // OrthoLin, OrthoAng - against constraint axis - btScalar m_softnessDirLin; - btScalar m_restitutionDirLin; - btScalar m_dampingDirLin; - btScalar m_softnessDirAng; - btScalar m_restitutionDirAng; - btScalar m_dampingDirAng; - btScalar m_softnessLimLin; - btScalar m_restitutionLimLin; - btScalar m_dampingLimLin; - btScalar m_softnessLimAng; - btScalar m_restitutionLimAng; - btScalar m_dampingLimAng; - btScalar m_softnessOrthoLin; - btScalar m_restitutionOrthoLin; - btScalar m_dampingOrthoLin; - btScalar m_softnessOrthoAng; - btScalar m_restitutionOrthoAng; - btScalar m_dampingOrthoAng; - - // for interlal use - bool m_solveLinLim; - bool m_solveAngLim; - - btJacobianEntry m_jacLin[3]; - btScalar m_jacLinDiagABInv[3]; - - btJacobianEntry m_jacAng[3]; - - btScalar m_timeStep; - btTransform m_calculatedTransformA; - btTransform m_calculatedTransformB; - - btVector3 m_sliderAxis; - btVector3 m_realPivotAInW; - btVector3 m_realPivotBInW; - btVector3 m_projPivotInW; - btVector3 m_delta; - btVector3 m_depth; - btVector3 m_relPosA; - btVector3 m_relPosB; - - btScalar m_linPos; - - btScalar m_angDepth; - btScalar m_kAngle; - - bool m_poweredLinMotor; - btScalar m_targetLinMotorVelocity; - btScalar m_maxLinMotorForce; - btScalar m_accumulatedLinMotorImpulse; - - bool m_poweredAngMotor; - btScalar m_targetAngMotorVelocity; - btScalar m_maxAngMotorForce; - btScalar m_accumulatedAngMotorImpulse; - - //------------------------ - void initParams(); -public: - // constructors - btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btSliderConstraint(); - // overrides - virtual void buildJacobian(); - virtual void solveConstraint(btScalar timeStep); - // access - const btRigidBody& getRigidBodyA() const { return m_rbA; } - const btRigidBody& getRigidBodyB() const { return m_rbB; } - const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } - const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } - const btTransform & getFrameOffsetA() const { return m_frameInA; } - const btTransform & getFrameOffsetB() const { return m_frameInB; } - btTransform & getFrameOffsetA() { return m_frameInA; } - btTransform & getFrameOffsetB() { return m_frameInB; } - btScalar getLowerLinLimit() { return m_lowerLinLimit; } - void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } - btScalar getUpperLinLimit() { return m_upperLinLimit; } - void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } - btScalar getLowerAngLimit() { return m_lowerAngLimit; } - void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; } - btScalar getUpperAngLimit() { return m_upperAngLimit; } - void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; } - bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; } - btScalar getSoftnessDirLin() { return m_softnessDirLin; } - btScalar getRestitutionDirLin() { return m_restitutionDirLin; } - btScalar getDampingDirLin() { return m_dampingDirLin ; } - btScalar getSoftnessDirAng() { return m_softnessDirAng; } - btScalar getRestitutionDirAng() { return m_restitutionDirAng; } - btScalar getDampingDirAng() { return m_dampingDirAng; } - btScalar getSoftnessLimLin() { return m_softnessLimLin; } - btScalar getRestitutionLimLin() { return m_restitutionLimLin; } - btScalar getDampingLimLin() { return m_dampingLimLin; } - btScalar getSoftnessLimAng() { return m_softnessLimAng; } - btScalar getRestitutionLimAng() { return m_restitutionLimAng; } - btScalar getDampingLimAng() { return m_dampingLimAng; } - btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; } - btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; } - btScalar getDampingOrthoLin() { return m_dampingOrthoLin; } - btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; } - btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; } - btScalar getDampingOrthoAng() { return m_dampingOrthoAng; } - void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; } - void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } - void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; } - void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; } - void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } - void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; } - void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; } - void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } - void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; } - void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; } - void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } - void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; } - void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } - void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } - void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } - void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } - void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } - void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } - void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } - bool getPoweredLinMotor() { return m_poweredLinMotor; } - void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } - btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } - void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } - btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; } - void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } - bool getPoweredAngMotor() { return m_poweredAngMotor; } - void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } - btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } - void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } - btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } - btScalar getLinearPos() { return m_linPos; } - - // access for ODE solver - bool getSolveLinLimit() { return m_solveLinLim; } - btScalar getLinDepth() { return m_depth[0]; } - bool getSolveAngLimit() { return m_solveAngLim; } - btScalar getAngDepth() { return m_angDepth; } - // internal - void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB); - void solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB); - // shared code used by ODE solver - void calculateTransforms(void); - void testLinLimits(void); - void testAngLimits(void); - // access for PE Solver - btVector3 getAncorInA(void); - btVector3 getAncorInB(void); -}; - -//----------------------------------------------------------------------------- - -#endif //SLIDER_CONSTRAINT_H - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h index 057d3fac827..e7d26645c6a 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SOLVE_2LINEAR_CONSTRAINT_H #define SOLVE_2LINEAR_CONSTRAINT_H -#include "LinearMath/btMatrix3x3.h" -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btMatrix3x3.h" +#include "../../LinearMath/btVector3.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h index b3f0c9d7444..0ab536f42b3 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -19,78 +19,38 @@ subject to the following restrictions: class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "LinearMath/btAlignedAllocator.h" -#include "LinearMath/btTransformUtil.h" -///btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. + + ATTRIBUTE_ALIGNED16 (struct) btSolverBody { - BT_DECLARE_ALIGNED_ALLOCATOR(); - + btVector3 m_centerOfMassPosition; + btVector3 m_linearVelocity; btVector3 m_angularVelocity; - float m_angularFactor; + btRigidBody* m_originalBody; float m_invMass; float m_friction; - btRigidBody* m_originalBody; - btVector3 m_linearVelocity; - btVector3 m_centerOfMassPosition; - - btVector3 m_pushVelocity; - btVector3 m_turnVelocity; - - - SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const + float m_angularFactor; + + inline void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const { velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { - if (m_invMass) - { - m_linearVelocity += linearComponent*impulseMagnitude; - m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); - } - } - - SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) - { - if (m_invMass) - { - m_pushVelocity += linearComponent*impulseMagnitude; - m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); - } + m_linearVelocity += linearComponent*impulseMagnitude; + m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; } - void writebackVelocity() { if (m_invMass) { m_originalBody->setLinearVelocity(m_linearVelocity); m_originalBody->setAngularVelocity(m_angularVelocity); - - //m_originalBody->setCompanionId(-1); - } - } - - - void writebackVelocity(btScalar timeStep) - { - if (m_invMass) - { - m_originalBody->setLinearVelocity(m_linearVelocity); - m_originalBody->setAngularVelocity(m_angularVelocity); - - //correct the position/orientation based on push/turn recovery - btTransform newTransform; - btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform); - m_originalBody->setWorldTransform(newTransform); - - //m_originalBody->setCompanionId(-1); } } @@ -109,5 +69,3 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody }; #endif //BT_SOLVER_BODY_H - - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h index 2c71360c5b9..f1f40ffdf19 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -1,3 +1,5 @@ + + /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -25,34 +27,24 @@ class btRigidBody; ///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint { - BT_DECLARE_ALIGNED_ALLOCATOR(); - btVector3 m_relpos1CrossNormal; - btVector3 m_contactNormal; - btVector3 m_relpos2CrossNormal; + btVector3 m_contactNormal; btVector3 m_angularComponentA; - btVector3 m_angularComponentB; - mutable btScalar m_appliedPushImpulse; - - mutable btScalar m_appliedImpulse; + btScalar m_appliedVelocityImpulse; int m_solverBodyIdA; int m_solverBodyIdB; - btScalar m_friction; btScalar m_restitution; btScalar m_jacDiagABInv; btScalar m_penetration; - + btScalar m_appliedImpulse; - int m_constraintType; int m_frictionIndex; - void* m_originalContactPoint; - int m_unusedPadding[1]; - + int m_unusedPadding[2]; enum btSolverConstraintType { @@ -69,4 +61,3 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint #endif //BT_SOLVER_CONSTRAINT_H - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp index 6e8b552dbbc..a15b3e026cd 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -19,20 +19,18 @@ subject to the following restrictions: static btRigidBody s_fixed(0, 0,0); -btTypedConstraint::btTypedConstraint(btTypedConstraintType type) -:m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint() +: m_userConstraintType(-1), m_userConstraintId(-1), -m_constraintType (type), m_rbA(s_fixed), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); } -btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) -:m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btRigidBody& rbA) +: m_userConstraintType(-1), m_userConstraintId(-1), -m_constraintType (type), m_rbA(rbA), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) @@ -42,10 +40,9 @@ m_appliedImpulse(btScalar(0.)) } -btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) -:m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB) +: m_userConstraintType(-1), m_userConstraintId(-1), -m_constraintType (type), m_rbA(rbA), m_rbB(rbB), m_appliedImpulse(btScalar(0.)) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index c50ec6ec579..dfee6e80d0e 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -17,17 +17,7 @@ subject to the following restrictions: #define TYPED_CONSTRAINT_H class btRigidBody; -#include "LinearMath/btScalar.h" - -enum btTypedConstraintType -{ - POINT2POINT_CONSTRAINT_TYPE, - HINGE_CONSTRAINT_TYPE, - CONETWIST_CONSTRAINT_TYPE, - D6_CONSTRAINT_TYPE, - VEHICLE_CONSTRAINT_TYPE, - SLIDER_CONSTRAINT_TYPE -}; +#include "../../LinearMath/btScalar.h" ///TypedConstraint is the baseclass for Bullet constraints and vehicles class btTypedConstraint @@ -35,8 +25,6 @@ class btTypedConstraint int m_userConstraintType; int m_userConstraintId; - btTypedConstraintType m_constraintType; - btTypedConstraint& operator=(btTypedConstraint& other) { btAssert(0); @@ -52,11 +40,11 @@ protected: public: - btTypedConstraint(btTypedConstraintType type); + btTypedConstraint(); virtual ~btTypedConstraint() {}; - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); + btTypedConstraint(btRigidBody& rbA); - btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); + btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB); virtual void buildJacobian() = 0; @@ -71,7 +59,7 @@ public: return m_rbB; } - btRigidBody& getRigidBodyA() + btRigidBody& getRigidBodyA() { return m_rbA; } @@ -95,26 +83,14 @@ public: m_userConstraintId = uid; } - int getUserConstraintId() const + int getUserConstraintId() { return m_userConstraintId; } - - int getUid() const - { - return m_userConstraintId; - } - - btScalar getAppliedImpulse() const + btScalar getAppliedImpulse() { return m_appliedImpulse; } - - btTypedConstraintType getConstraintType () const - { - return m_constraintType; - } - }; #endif //TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp index c2fd71d67fe..248c582dcd8 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -25,7 +25,6 @@ subject to the following restrictions: #include "LinearMath/btAlignedAllocator.h" - #include "LinearMath/btVector3.h" #include "LinearMath/btScalar.h" #include "LinearMath/btMatrix3x3.h" @@ -40,296 +39,18 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" + #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "LinearMath/btStackAlloc.h" -/* - Create and Delete a Physics SDK -*/ - -struct btPhysicsSdk -{ - -// btDispatcher* m_dispatcher; -// btOverlappingPairCache* m_pairCache; -// btConstraintSolver* m_constraintSolver - - btVector3 m_worldAabbMin; - btVector3 m_worldAabbMax; - - - //todo: version, hardware/optimization settings etc? - btPhysicsSdk() - :m_worldAabbMin(-1000,-1000,-1000), - m_worldAabbMax(1000,1000,1000) - { - - } - - -}; - -plPhysicsSdkHandle plNewBulletSdk() -{ - void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); - return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; -} - -void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) -{ - btPhysicsSdk* phys = reinterpret_cast(physicsSdk); - btAlignedFree(phys); -} - - -/* Dynamics World */ -plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle) -{ - btPhysicsSdk* physicsSdk = reinterpret_cast(physicsSdkHandle); - void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16); - btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration(); - mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16); - btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration); - mem = btAlignedAlloc(sizeof(btAxisSweep3),16); - btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); - mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); - btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver(); - - mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16); - return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration); -} -void plDeleteDynamicsWorld(plDynamicsWorldHandle world) -{ - //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration - btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - btAlignedFree(dynamicsWorld); -} - -void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) -{ - btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - assert(dynamicsWorld); - dynamicsWorld->stepSimulation(timeStep); -} - -void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) -{ - btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - assert(dynamicsWorld); - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - assert(body); - - dynamicsWorld->addRigidBody(body); -} - -void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) -{ - btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); - assert(dynamicsWorld); - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - assert(body); - - dynamicsWorld->removeRigidBody(body); -} - -/* Rigid Body */ - -plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) -{ - btTransform trans; - trans.setIdentity(); - btVector3 localInertia(0,0,0); - btCollisionShape* shape = reinterpret_cast( cshape); - assert(shape); - if (mass) - { - shape->calculateLocalInertia(mass,localInertia); - } - void* mem = btAlignedAlloc(sizeof(btRigidBody),16); - btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia); - btRigidBody* body = new (mem)btRigidBody(rbci); - body->setWorldTransform(trans); - body->setUserPointer(user_data); - return (plRigidBodyHandle) body; -} - -void plDeleteRigidBody(plRigidBodyHandle cbody) -{ - btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); - assert(body); - btAlignedFree( body); -} - - -/* Collision Shape definition */ - -plCollisionShapeHandle plNewSphereShape(plReal radius) -{ - void* mem = btAlignedAlloc(sizeof(btSphereShape),16); - return (plCollisionShapeHandle) new (mem)btSphereShape(radius); - -} - -plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) -{ - void* mem = btAlignedAlloc(sizeof(btBoxShape),16); - return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); -} - -plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) -{ - //capsule is convex hull of 2 spheres, so use btMultiSphereShape - btVector3 inertiaHalfExtents(radius,height,radius); - const int numSpheres = 2; - btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; - btScalar radi[numSpheres] = {radius,radius}; - void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16); - return (plCollisionShapeHandle) new (mem)btMultiSphereShape(inertiaHalfExtents,positions,radi,numSpheres); -} -plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) -{ - void* mem = btAlignedAlloc(sizeof(btConeShape),16); - return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); -} - -plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) -{ - void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); - return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); -} - -/* Convex Meshes */ -plCollisionShapeHandle plNewConvexHullShape() -{ - void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); - return (plCollisionShapeHandle) new (mem)btConvexHullShape(); -} - - -/* Concave static triangle meshes */ -plMeshInterfaceHandle plNewMeshInterface() -{ - return 0; -} - -plCollisionShapeHandle plNewCompoundShape() -{ - void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); - return (plCollisionShapeHandle) new (mem)btCompoundShape(); -} - -void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn) -{ - btCollisionShape* colShape = reinterpret_cast(compoundShapeHandle); - btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE); - btCompoundShape* compoundShape = reinterpret_cast(colShape); - btCollisionShape* childShape = reinterpret_cast(childShapeHandle); - btTransform localTrans; - localTrans.setIdentity(); - localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2])); - localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3])); - compoundShape->addChildShape(localTrans,childShape); -} - -void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient) -{ - btQuaternion orn; - orn.setEuler(yaw,pitch,roll); - orient[0] = orn.getX(); - orient[1] = orn.getY(); - orient[2] = orn.getZ(); - orient[3] = orn.getW(); - -} - - -// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); -// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); - - -void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) -{ - btCollisionShape* colShape = reinterpret_cast( cshape); - (void)colShape; - btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); - btConvexHullShape* convexHullShape = reinterpret_cast( cshape); - convexHullShape->addPoint(btPoint3(x,y,z)); - -} - -void plDeleteShape(plCollisionShapeHandle cshape) -{ - btCollisionShape* shape = reinterpret_cast( cshape); - assert(shape); - btAlignedFree(shape); -} -void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) -{ - btCollisionShape* shape = reinterpret_cast( cshape); - assert(shape); - btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); - shape->setLocalScaling(scaling); -} - - - -void plSetPosition(plRigidBodyHandle object, const plVector3 position) -{ - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - btAssert(body); - btVector3 pos(position[0],position[1],position[2]); - btTransform worldTrans = body->getWorldTransform(); - worldTrans.setOrigin(pos); - body->setWorldTransform(worldTrans); -} - -void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) -{ - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - btAssert(body); - btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]); - btTransform worldTrans = body->getWorldTransform(); - worldTrans.setRotation(orn); - body->setWorldTransform(worldTrans); -} - -void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) -{ - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - btAssert(body); - body->getWorldTransform().getOpenGLMatrix(matrix); - -} - -void plGetPosition(plRigidBodyHandle object,plVector3 position) -{ - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - btAssert(body); - const btVector3& pos = body->getWorldTransform().getOrigin(); - position[0] = pos.getX(); - position[1] = pos.getY(); - position[2] = pos.getZ(); -} - -void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation) -{ - btRigidBody* body = reinterpret_cast< btRigidBody* >(object); - btAssert(body); - const btQuaternion& orn = body->getWorldTransform().getRotation(); - orientation[0] = orn.getX(); - orientation[1] = orn.getY(); - orientation[2] = orn.getZ(); - orientation[3] = orn.getW(); -} - - - -//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); - -// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); - +extern "C" double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]) { btVector3 vp(p1[0], p1[1], p1[2]); @@ -397,4 +118,3 @@ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float } return -1.0f; } - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp deleted file mode 100644 index 19443adc723..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btContinuousDynamicsWorld.h" -#include "LinearMath/btQuickprof.h" - -//collision detection -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" -#include "BulletCollision/CollisionShapes/btCollisionShape.h" -#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" - -//rigidbody & constraints -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" - - - -#include - -btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) -:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) -{ -} - -btContinuousDynamicsWorld::~btContinuousDynamicsWorld() -{ -} - - -void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) -{ - - startProfiling(timeStep); - - - ///update aabbs information - updateAabbs(); - //static int frame=0; -// printf("frame %d\n",frame++); - - ///apply gravity, predict motion - predictUnconstraintMotion(timeStep); - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_debugDraw = getDebugDrawer(); - - ///perform collision detection - performDiscreteCollisionDetection(); - - calculateSimulationIslands(); - - - getSolverInfo().m_timeStep = timeStep; - - - - ///solve contact and other joint constraints - solveConstraints(getSolverInfo()); - - ///CallbackTriggers(); - calculateTimeOfImpacts(timeStep); - - btScalar toi = dispatchInfo.m_timeOfImpact; -// if (toi < 1.f) -// printf("toi = %f\n",toi); - if (toi < 0.f) - printf("toi = %f\n",toi); - - - ///integrate transforms - integrateTransforms(timeStep * toi); - - ///update vehicle simulation - updateVehicles(timeStep); - - - updateActivationState( timeStep ); - - if(0 != m_internalTickCallback) { - (*m_internalTickCallback)(this, timeStep); - } -} - -void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) -{ - ///these should be 'temporal' aabbs! - updateTemporalAabbs(timeStep); - - ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually. - ///so we handle the case moving versus static properly, and we cheat for moving versus moving - btScalar toi = 1.f; - - - btDispatcherInfo& dispatchInfo = getDispatchInfo(); - dispatchInfo.m_timeStep = timeStep; - dispatchInfo.m_timeOfImpact = 1.f; - dispatchInfo.m_stepCount = 0; - dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS; - - ///calculate time of impact for overlapping pairs - - - btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); - - toi = dispatchInfo.m_timeOfImpact; - - dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; - -} - -void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) -{ - - btVector3 temporalAabbMin,temporalAabbMax; - - for ( int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax); - const btVector3& linvel = body->getLinearVelocity(); - - //make the AABB temporal - btScalar temporalAabbMaxx = temporalAabbMax.getX(); - btScalar temporalAabbMaxy = temporalAabbMax.getY(); - btScalar temporalAabbMaxz = temporalAabbMax.getZ(); - btScalar temporalAabbMinx = temporalAabbMin.getX(); - btScalar temporalAabbMiny = temporalAabbMin.getY(); - btScalar temporalAabbMinz = temporalAabbMin.getZ(); - - // add linear motion - btVector3 linMotion = linvel*timeStep; - - if (linMotion.x() > 0.f) - temporalAabbMaxx += linMotion.x(); - else - temporalAabbMinx += linMotion.x(); - if (linMotion.y() > 0.f) - temporalAabbMaxy += linMotion.y(); - else - temporalAabbMiny += linMotion.y(); - if (linMotion.z() > 0.f) - temporalAabbMaxz += linMotion.z(); - else - temporalAabbMinz += linMotion.z(); - - //add conservative angular motion - btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep; - btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); - temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); - temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); - - temporalAabbMin -= angularMotion3d; - temporalAabbMax += angularMotion3d; - - m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1); - } - } - - //update aabb (of all moved objects) - - m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); - - - -} - - - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h deleted file mode 100644 index 61c8dea03eb..00000000000 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H -#define BT_CONTINUOUS_DYNAMICS_WORLD_H - -#include "btDiscreteDynamicsWorld.h" - -///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld. -///This copes with fast moving objects that otherwise would tunnel/miss collisions. -///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead. -class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld -{ - - void updateTemporalAabbs(btScalar timeStep); - - public: - - btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); - virtual ~btContinuousDynamicsWorld(); - - ///time stepping with calculation of time of impact for selected fast moving objects - virtual void internalSingleStepSimulation( btScalar timeStep); - - virtual void calculateTimeOfImpacts(btScalar timeStep); - - virtual btDynamicsWorldType getWorldType() const - { - return BT_CONTINUOUS_DYNAMICS_WORLD; - } - -}; - -#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index e46c4e6136b..1017c8af6ea 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -21,8 +21,7 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" -#include "LinearMath/btTransformUtil.h" -#include "LinearMath/btQuickprof.h" +#include //rigidbody & constraints #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -42,7 +41,6 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btSphereShape.h" #include "BulletCollision/CollisionShapes/btTriangleCallback.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" #include "LinearMath/btIDebugDraw.h" @@ -59,29 +57,17 @@ subject to the following restrictions: -btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) -:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), -m_constraintSolver(constraintSolver), +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) +:btDynamicsWorld(dispatcher,pairCache), +m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver), +m_debugDrawer(0), m_gravity(0,-10,0), m_localTime(btScalar(1.)/btScalar(60.)), m_profileTimings(0) { - if (!m_constraintSolver) - { - void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); - m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; - m_ownsConstraintSolver = true; - } else - { - m_ownsConstraintSolver = false; - } - - { - void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); - m_islandManager = new (mem) btSimulationIslandManager(); - } - + m_islandManager = new btSimulationIslandManager(); m_ownsIslandManager = true; + m_ownsConstraintSolver = (constraintSolver==0); } @@ -89,16 +75,9 @@ btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() { //only delete it when we created it if (m_ownsIslandManager) - { - m_islandManager->~btSimulationIslandManager(); - btAlignedFree( m_islandManager); - } + delete m_islandManager; if (m_ownsConstraintSolver) - { - - m_constraintSolver->~btConstraintSolver(); - btAlignedFree(m_constraintSolver); - } + delete m_constraintSolver; } void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) @@ -123,35 +102,14 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) } } -void btDiscreteDynamicsWorld::debugDrawWorld() +void btDiscreteDynamicsWorld::synchronizeMotionStates() { - - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) + //debug vehicle wheels + + { - int numManifolds = getDispatcher()->getNumManifolds(); - btVector3 color(0,0,0); - for (int i=0;igetManifoldByIndexInternal(i); - //btCollisionObject* obA = static_cast(contactManifold->getBody0()); - //btCollisionObject* obB = static_cast(contactManifold->getBody1()); - - int numContacts = contactManifold->getNumContacts(); - for (int j=0;jgetContactPoint(j); - getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } - } - } - - - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)) - { - int i; - //todo: iterate over awake simulation islands! - for ( i=0;igetDebugMode() & btIDebugDraw::DBG_DrawWireframe) @@ -177,17 +135,26 @@ void btDiscreteDynamicsWorld::debugDrawWorld() debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); } - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + btRigidBody* body = btRigidBody::upcast(colObj); + if (body && body->getMotionState() && !body->isStaticOrKinematicObject()) { - btPoint3 minAabb,maxAabb; - btVector3 colorvec(1,0,0); - colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); - m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + //so todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime,interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } } - } - - for ( i=0;im_vehicles.size();i++) + } + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) + { + for ( int i=0;im_vehicles.size();i++) { for (int v=0;vgetNumWheels();v++) { @@ -199,7 +166,10 @@ void btDiscreteDynamicsWorld::debugDrawWorld() { wheelColor.setValue(255,0,255); } - + + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicles[i]->updateWheelTransform(v,true); + btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); btVector3 axle = btVector3( @@ -216,87 +186,12 @@ void btDiscreteDynamicsWorld::debugDrawWorld() } } } -} - -void btDiscreteDynamicsWorld::clearForces() -{ - //todo: iterate over awake simulation islands! - for ( int i=0;iclearForces(); - } - } -} - -///apply gravity, call this once per timestep -void btDiscreteDynamicsWorld::applyGravity() -{ - //todo: iterate over awake simulation islands! - for ( int i=0;iisActive()) - { - body->applyGravity(); - } - } -} - - - -void btDiscreteDynamicsWorld::synchronizeMotionStates() -{ - { - //todo: iterate over awake simulation islands! - for ( int i=0;igetMotionState() && !body->isStaticOrKinematicObject()) - { - //we need to call the update at least once, even for sleeping objects - //otherwise the 'graphics' transform never updates properly - //so todo: add 'dirty' flag - //if (body->getActivationState() != ISLAND_SLEEPING) - { - btTransform interpolatedTransform; - btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform); - body->getMotionState()->setWorldTransform(interpolatedTransform); - } - } - } - } - - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) - { - for ( int i=0;im_vehicles.size();i++) - { - for (int v=0;vgetNumWheels();v++) - { - //synchronize the wheels with the (interpolated) chassis worldtransform - m_vehicles[i]->updateWheelTransform(v,true); - } - } - } } int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) { - startProfiling(timeStep); - - BT_PROFILE("stepSimulation"); - int numSimulationSubSteps = 0; if (maxSubSteps) @@ -334,8 +229,6 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, saveKinematicState(fixedTimeStep); - applyGravity(); - //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; @@ -349,19 +242,16 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, synchronizeMotionStates(); - clearForces(); - -#ifndef BT_NO_PROFILE - CProfileManager::Increment_Frame_Counter(); -#endif //BT_NO_PROFILE - return numSimulationSubSteps; } void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) { - BT_PROFILE("internalSingleStepSimulation"); + startProfiling(timeStep); + + ///update aabbs information + updateAabbs(); ///apply gravity, predict motion predictUnconstraintMotion(timeStep); @@ -396,9 +286,8 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) updateActivationState( timeStep ); - if(0 != m_internalTickCallback) { - (*m_internalTickCallback)(this, timeStep); - } + + } void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) @@ -415,11 +304,6 @@ void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) } } -btVector3 btDiscreteDynamicsWorld::getGravity () const -{ - return m_gravity; -} - void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) { @@ -459,18 +343,19 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) { - BT_PROFILE("updateVehicles"); - + BEGIN_PROFILE("updateVehicles"); + for ( int i=0;iupdateVehicle( timeStep); } + END_PROFILE("updateVehicles"); } void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) { - BT_PROFILE("updateActivationState"); + BEGIN_PROFILE("updateActivationState"); for ( int i=0;igetActivationState() == ACTIVE_TAG) body->setActivationState( WANTS_DEACTIVATION ); - if (body->getActivationState() == ISLAND_SLEEPING) - { - body->setAngularVelocity(btVector3(0,0,0)); - body->setLinearVelocity(btVector3(0,0,0)); - } - } } else { @@ -503,6 +382,7 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) } } } + END_PROFILE("updateActivationState"); } void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) @@ -532,7 +412,7 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) m_vehicles.remove(vehicle); } -SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) +inline int btGetConstraintIslandId(const btTypedConstraint* lhs) { int islandId; @@ -562,7 +442,6 @@ class btSortConstraintOnIslandPredicate void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { - BT_PROFILE("solveConstraints"); struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback { @@ -573,7 +452,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) int m_numConstraints; btIDebugDraw* m_debugDrawer; btStackAlloc* m_stackAlloc; - btDispatcher* m_dispatcher; + InplaceSolverIslandCallback( btContactSolverInfo& solverInfo, @@ -581,15 +460,13 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer, - btStackAlloc* stackAlloc, - btDispatcher* dispatcher) + btStackAlloc* stackAlloc) :m_solverInfo(solverInfo), m_solver(solver), m_sortedConstraints(sortedConstraints), m_numConstraints(numConstraints), m_debugDrawer(debugDrawer), - m_stackAlloc(stackAlloc), - m_dispatcher(dispatcher) + m_stackAlloc(stackAlloc) { } @@ -602,42 +479,30 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) } virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) { - if (islandId<0) + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - } else - { - //also add all non-contact constraints/joints for this island - btTypedConstraint** startConstraint = 0; - int numCurConstraints = 0; - int i; - - //find the first constraint for this island - for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); - } - } + //count the number of constraints in this island + for (;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc); } }; @@ -655,18 +520,18 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) - sortedConstraints.quickSort(btSortConstraintOnIslandPredicate()); + sortedConstraints.heapSort(btSortConstraintOnIslandPredicate()); btTypedConstraint** constraintsPtr = getNumConstraints() ? &sortedConstraints[0] : 0; - InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc,m_dispatcher1); + InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc); + - m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); - m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); + } @@ -674,7 +539,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) void btDiscreteDynamicsWorld::calculateSimulationIslands() { - BT_PROFILE("calculateSimulationIslands"); + BEGIN_PROFILE("calculateSimulationIslands"); getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); @@ -704,85 +569,66 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() //Store the island id in each body getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); - + END_PROFILE("calculateSimulationIslands"); + } -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" - -class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +void btDiscreteDynamicsWorld::updateAabbs() { - btCollisionObject* m_me; - btScalar m_allowedPenetration; - btOverlappingPairCache* m_pairCache; - - -public: - btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache) : - btCollisionWorld::ClosestConvexResultCallback(fromA,toA), - m_allowedPenetration(0.0f), - m_me(me), - m_pairCache(pairCache) + BEGIN_PROFILE("updateAabbs"); + + btVector3 colorvec(1,0,0); + btTransform predictedTrans; + for ( int i=0;i=-m_allowedPenetration) - return 1.f; - - return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); - } - - virtual bool needsCollision(btBroadphaseProxy* proxy0) const - { - //don't collide with itself - if (proxy0->m_clientObject == m_me) - return false; - - ///don't do CCD when the collision filters are not matching - if (!btCollisionWorld::ClosestConvexResultCallback::needsCollision(proxy0)) - return false; - - ///don't do CCD when there are already contact points (touching contact/penetration) - btAlignedObjectArray manifoldArray; - btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); - if (collisionPair) + btCollisionObject* colObj = m_collisionObjects[i]; + + btRigidBody* body = btRigidBody::upcast(colObj); + if (body) { - if (collisionPair->m_algorithm) + // if (body->IsActive() && (!body->IsStatic())) { - manifoldArray.resize(0); - collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); - for (int j=0;jgetCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; + + //moving objects should be moderately sized, probably something wrong if not + if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) { - btPersistentManifold* manifold = manifoldArray[j]; - if (manifold->getNumContacts()>0) - return false; + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + } else + { + //something went wrong, investigate + //this assert is unwanted in 3D modelers (danger of loosing work) + body->setActivationState(DISABLE_SIMULATION); + + static bool reportMe = true; + if (reportMe && m_debugDrawer) + { + reportMe = false; + m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); + m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); + m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); + m_debugDrawer->reportErrorWarning("Thanks.\n"); + } + + + } + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); } } } - return true; } + + END_PROFILE("updateAabbs"); +} - -}; - -///internal debugging variable. this value shouldn't be too high -int gNumClampedCcdMotions=0; - -//#include "stdio.h" void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { - BT_PROFILE("integrateTransforms"); + BEGIN_PROFILE("integrateTransforms"); btTransform predictedTrans; for ( int i=0;isetHitFraction(1.f); - if (body->isActive() && (!body->isStaticOrKinematicObject())) { body->predictIntegratedTransform(timeStep, predictedTrans); - btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); - - if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) - { - BT_PROFILE("CCD motion clamping"); - if (body->getCollisionShape()->isConvex()) - { - gNumClampedCcdMotions++; - - btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache()); - btConvexShape* convexShape = static_cast(body->getCollisionShape()); - btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); - convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults); - if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) - { - body->setHitFraction(sweepResults.m_closestHitFraction); - body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); - body->setHitFraction(0.f); -// printf("clamped integration to hit fraction = %f\n",fraction); - } - } - } - body->proceedToTransform( predictedTrans); } } } + END_PROFILE("integrateTransforms"); } void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { - BT_PROFILE("predictUnconstraintMotion"); + BEGIN_PROFILE("predictUnconstraintMotion"); for ( int i=0;iisActive()) { + body->applyForces( timeStep); body->integrateVelocities( timeStep); - //damping - body->applyDamping(timeStep); - body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } } } + END_PROFILE("predictUnconstraintMotion"); } void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) { (void)timeStep; + #ifdef USE_QUICKPROF -#ifndef BT_NO_PROFILE - CProfileManager::Reset(); -#endif //BT_NO_PROFILE + //toggle btProfiler + if ( m_debugDrawer && m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_ProfileTimings) + { + if (!m_profileTimings) + { + m_profileTimings = 1; + // To disable profiling, simply comment out the following line. + static int counter = 0; + + char filename[128]; + sprintf(filename,"quickprof_bullet_timings%i.csv",counter++); + btProfiler::init(filename, btProfiler::BLOCK_CYCLE_SECONDS);//BLOCK_TOTAL_MICROSECONDS + } else + { + btProfiler::endProfilingCycle(); + } + + } else + { + if (m_profileTimings) + { + btProfiler::endProfilingCycle(); + + m_profileTimings = 0; + btProfiler::destroy(); + } + } +#endif //USE_QUICKPROF } @@ -980,52 +827,27 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = capsuleShape->getRadius(); btScalar halfHeight = capsuleShape->getHalfHeight(); - - int upAxis = capsuleShape->getUpAxis(); - - - btVector3 capStart(0.f,0.f,0.f); - capStart[upAxis] = -halfHeight; - - btVector3 capEnd(0.f,0.f,0.f); - capEnd[upAxis] = halfHeight; // Draw the ends { - btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * capStart; + childTransform.getOrigin() = worldTransform * btVector3(0,halfHeight,0); debugDrawSphere(radius, childTransform, color); } { btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * capEnd; + childTransform.getOrigin() = worldTransform * btVector3(0,-halfHeight,0); debugDrawSphere(radius, childTransform, color); } // Draw some additional lines btVector3 start = worldTransform.getOrigin(); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(-radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(-radius,-halfHeight,0), color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(radius,-halfHeight,0), color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,-radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,-radius), color); + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,radius), color); - - capStart[(upAxis+1)%3] = radius; - capEnd[(upAxis+1)%3] = radius; - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); - capStart[(upAxis+1)%3] = -radius; - capEnd[(upAxis+1)%3] = -radius; - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); - - capStart[(upAxis+1)%3] = 0.f; - capEnd[(upAxis+1)%3] = 0.f; - - capStart[(upAxis+2)%3] = radius; - capEnd[(upAxis+2)%3] = radius; - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); - capStart[(upAxis+2)%3] = -radius; - capEnd[(upAxis+2)%3] = -radius; - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); - - break; } case CONE_SHAPE_PROXYTYPE: @@ -1034,10 +856,9 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); btScalar height = coneShape->getHeight();//+coneShape->getMargin(); btVector3 start = worldTransform.getOrigin(); - + // insert here Bullet 2.69 that fixes representation of cone int upAxis= coneShape->getConeUpIndex(); - btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = height * btScalar(0.5); btVector3 offsetRadius(0,0,0); @@ -1050,8 +871,11 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color); getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color); - - + // buggy code that does not take into account the direction of the cone + //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color); + //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color); + //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color); + //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color); break; } @@ -1060,7 +884,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, const btCylinderShape* cylinder = static_cast(shape); int upAxis = cylinder->getUpAxis(); btScalar radius = cylinder->getRadius(); - btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; + btScalar halfHeight = cylinder->getHalfExtents()[upAxis]; btVector3 start = worldTransform.getOrigin(); btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = halfHeight; @@ -1070,25 +894,6 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); break; } - - case STATIC_PLANE_PROXYTYPE: - { - const btStaticPlaneShape* staticPlaneShape = static_cast(shape); - btScalar planeConst = staticPlaneShape->getPlaneConstant(); - const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); - btVector3 planeOrigin = planeNormal * planeConst; - btVector3 vec0,vec1; - btPlaneSpace1(planeNormal,vec0,vec1); - btScalar vecLen = 100.f; - btVector3 pt0 = planeOrigin + vec0*vecLen; - btVector3 pt1 = planeOrigin - vec0*vecLen; - btVector3 pt2 = planeOrigin + vec1*vecLen; - btVector3 pt3 = planeOrigin - vec1*vecLen; - getDebugDrawer()->drawLine(worldTransform*pt0,worldTransform*pt1,color); - getDebugDrawer()->drawLine(worldTransform*pt2,worldTransform*pt3,color); - break; - - } default: { @@ -1113,7 +918,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); //DebugDrawcallback drawCallback; DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + convexMesh->getStridingMesh()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); } @@ -1145,18 +950,12 @@ void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - btAlignedFree( m_constraintSolver); + delete m_constraintSolver; } m_ownsConstraintSolver = false; m_constraintSolver = solver; } -btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() -{ - return m_constraintSolver; -} - - int btDiscreteDynamicsWorld::getNumConstraints() const { return int(m_constraints.size()); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index d9e2652aaf6..83b90bfeebc 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -23,11 +23,11 @@ class btOverlappingPairCache; class btConstraintSolver; class btSimulationIslandManager; class btTypedConstraint; - +#include "../ConstraintSolver/btContactSolverInfo.h" class btRaycastVehicle; class btIDebugDraw; -#include "LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btAlignedObjectArray.h" ///btDiscreteDynamicsWorld provides discrete rigid body simulation @@ -42,6 +42,7 @@ protected: btAlignedObjectArray m_constraints; + btIDebugDraw* m_debugDrawer; btVector3 m_gravity; @@ -52,14 +53,16 @@ protected: bool m_ownsIslandManager; bool m_ownsConstraintSolver; - + btContactSolverInfo m_solverInfo; + + btAlignedObjectArray m_vehicles; int m_profileTimings; - virtual void predictUnconstraintMotion(btScalar timeStep); + void predictUnconstraintMotion(btScalar timeStep); - virtual void integrateTransforms(btScalar timeStep); + void integrateTransforms(btScalar timeStep); void calculateSimulationIslands(); @@ -83,13 +86,14 @@ public: ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those - btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); virtual ~btDiscreteDynamicsWorld(); ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); + virtual void updateAabbs(); void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); @@ -114,9 +118,17 @@ public: return this; } + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + } + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } virtual void setGravity(const btVector3& gravity); - virtual btVector3 getGravity () const; virtual void addRigidBody(btRigidBody* body); @@ -126,11 +138,7 @@ public: void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); - virtual void debugDrawWorld(); - virtual void setConstraintSolver(btConstraintSolver* solver); - - virtual btConstraintSolver* getConstraintSolver(); virtual int getNumConstraints() const; @@ -138,21 +146,11 @@ public: virtual const btTypedConstraint* getConstraint(int index) const; - - virtual btDynamicsWorldType getWorldType() const + btContactSolverInfo& getSolverInfo() { - return BT_DISCRETE_DYNAMICS_WORLD; + return m_solverInfo; } - - ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep. - virtual void clearForces(); - ///apply gravity, call this once per timestep - virtual void applyGravity(); - - virtual void setNumTasks(int numTasks) - { - } }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 929e24d337c..65b63fad4b5 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -16,39 +16,20 @@ subject to the following restrictions: #ifndef BT_DYNAMICS_WORLD_H #define BT_DYNAMICS_WORLD_H -#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" - +#include "../../BulletCollision/CollisionDispatch/btCollisionWorld.h" class btTypedConstraint; class btRaycastVehicle; class btConstraintSolver; -class btDynamicsWorld; -/// Type for the callback for each tick -typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); -enum btDynamicsWorldType -{ - BT_SIMPLE_DYNAMICS_WORLD=1, - BT_DISCRETE_DYNAMICS_WORLD=2, - BT_CONTINUOUS_DYNAMICS_WORLD=3 -}; - -///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. +///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous class btDynamicsWorld : public btCollisionWorld { - -protected: - btInternalTickCallback m_internalTickCallback; - void* m_worldUserInfo; - - btContactSolverInfo m_solverInfo; - -public: + public: - btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) - :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0) + btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) + :btCollisionWorld(dispatcher,pairCache) { } @@ -56,37 +37,34 @@ public: { } - ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds. - ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'. - ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'. - ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant. + ///stepSimulation proceeds the simulation over timeStep units + ///if maxSubSteps > 0, it will interpolate time steps virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; - virtual void debugDrawWorld() = 0; + virtual void updateAabbs() = 0; - virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) - { - (void)constraint; (void)disableCollisionsBetweenLinkedBodies; - } + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;}; - virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} + virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}; - virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} + virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; - virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} + virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; + + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0; + + virtual btIDebugDraw* getDebugDrawer() = 0; //once a rigidbody is added to the dynamics world, it will get this gravity assigned //existing rigidbodies in the world get gravity assigned too, during this method virtual void setGravity(const btVector3& gravity) = 0; - virtual btVector3 getGravity () const = 0; virtual void addRigidBody(btRigidBody* body) = 0; virtual void removeRigidBody(btRigidBody* body) = 0; virtual void setConstraintSolver(btConstraintSolver* solver) = 0; - - virtual btConstraintSolver* getConstraintSolver() = 0; virtual int getNumConstraints() const { return 0; } @@ -94,35 +72,7 @@ public: virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } - virtual btDynamicsWorldType getWorldType() const=0; - - virtual void clearForces() = 0; - - /// Set the callback for when an internal tick (simulation substep) happens, optional user info - void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0) - { - m_internalTickCallback = cb; - m_worldUserInfo = worldUserInfo; - } - - void setWorldUserInfo(void* worldUserInfo) - { - m_worldUserInfo = worldUserInfo; - } - - void* getWorldUserInfo() const - { - return m_worldUserInfo; - } - - btContactSolverInfo& getSolverInfo() - { - return m_solverInfo; - } - - }; #endif //BT_DYNAMICS_WORLD_H - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index e2afb687ac6..9ed3579d89c 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -20,53 +20,36 @@ subject to the following restrictions: #include "LinearMath/btMotionState.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +btScalar gLinearAirDamping = btScalar(1.); //'temporarily' global variables btScalar gDeactivationTime = btScalar(2.); bool gDisableDeactivation = false; + +btScalar gLinearSleepingThreshold = btScalar(0.8); +btScalar gAngularSleepingThreshold = btScalar(1.0); static int uniqueId = 0; - -btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) -{ - setupRigidBody(constructionInfo); -} - -btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) -{ - btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); - setupRigidBody(cinfo); -} - -void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) +: + m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), + m_angularFactor(btScalar(1.)), + m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.5)), + m_optionalMotionState(motionState), + m_contactSolverType(0), + m_frictionSolverType(0) { - m_internalType=CO_RIGID_BODY; - - m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); - m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - m_angularFactor = btScalar(1.); - m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); - m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); - m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearDamping = btScalar(0.); - m_angularDamping = btScalar(0.5); - m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; - m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; - m_optionalMotionState = constructionInfo.m_motionState; - m_contactSolverType = 0; - m_frictionSolverType = 0; - m_additionalDamping = constructionInfo.m_additionalDamping; - m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor; - m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; - m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; - m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; - - if (m_optionalMotionState) + if (motionState) { - m_optionalMotionState->getWorldTransform(m_worldTransform); + motionState->getWorldTransform(m_worldTransform); } else { - m_worldTransform = constructionInfo.m_startWorldTransform; + m_worldTransform = btTransform::getIdentity(); } m_interpolationWorldTransform = m_worldTransform; @@ -74,21 +57,90 @@ void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& m_interpolationAngularVelocity.setValue(0,0,0); //moved to btCollisionObject - m_friction = constructionInfo.m_friction; - m_restitution = constructionInfo.m_restitution; + m_friction = friction; + m_restitution = restitution; - setCollisionShape( constructionInfo.m_collisionShape ); + m_collisionShape = collisionShape; m_debugBodyId = uniqueId++; - setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); - setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); + //m_internalOwner is to allow upcasting from collision object to rigid body + m_internalOwner = this; + + setMassProps(mass, localInertia); + setDamping(linearDamping, angularDamping); updateInertiaTensor(); } +#ifdef OBSOLETE_MOTIONSTATE_LESS +btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) +: + m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.5)), + m_optionalMotionState(0), + m_contactSolverType(0), + m_frictionSolverType(0) +{ + + m_worldTransform = worldTransform; + m_interpolationWorldTransform = m_worldTransform; + m_interpolationLinearVelocity.setValue(0,0,0); + m_interpolationAngularVelocity.setValue(0,0,0); + + //moved to btCollisionObject + m_friction = friction; + m_restitution = restitution; + + m_collisionShape = collisionShape; + m_debugBodyId = uniqueId++; + + //m_internalOwner is to allow upcasting from collision object to rigid body + m_internalOwner = this; + + setMassProps(mass, localInertia); + setDamping(linearDamping, angularDamping); + updateInertiaTensor(); + +} + +#endif //OBSOLETE_MOTIONSTATE_LESS + + + + +//#define EXPERIMENTAL_JITTER_REMOVAL 1 +#ifdef EXPERIMENTAL_JITTER_REMOVAL +//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate +//doesn't work very well yet (value 0 disabled this damping) +//note there this influences deactivation thresholds! +btScalar gClippedAngvelThresholdSqr = btScalar(0.01); +btScalar gClippedLinearThresholdSqr = btScalar(0.01); +#endif //EXPERIMENTAL_JITTER_REMOVAL + +btScalar gJitterVelocityDampingFactor = btScalar(0.7); void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) { + +#ifdef EXPERIMENTAL_JITTER_REMOVAL + //if (wantsSleeping()) + { + //clip to avoid jitter + if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) && + (m_linearVelocity.length2() < gClippedLinearThresholdSqr)) + { + m_angularVelocity *= gJitterVelocityDampingFactor; + m_linearVelocity *= gJitterVelocityDampingFactor; + } + } + +#endif //EXPERIMENTAL_JITTER_REMOVAL + btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); } @@ -139,63 +191,50 @@ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) - -///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping -void btRigidBody::applyDamping(btScalar timeStep) -{ - m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - - if (m_additionalDamping) - { - //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. - //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete - if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && - (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) - { - m_angularVelocity *= m_additionalDampingFactor; - m_linearVelocity *= m_additionalDampingFactor; - } - - - btScalar speed = m_linearVelocity.length(); - if (speed < m_linearDamping) - { - btScalar dampVel = btScalar(0.005); - if (speed > dampVel) - { - btVector3 dir = m_linearVelocity.normalized(); - m_linearVelocity -= dir * dampVel; - } else - { - m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } - - btScalar angSpeed = m_angularVelocity.length(); - if (angSpeed < m_angularDamping) - { - btScalar angDampVel = btScalar(0.005); - if (angSpeed > angDampVel) - { - btVector3 dir = m_angularVelocity.normalized(); - m_angularVelocity -= dir * angDampVel; - } else - { - m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } - } -} +#include -void btRigidBody::applyGravity() +void btRigidBody::applyForces(btScalar step) { if (isStaticOrKinematicObject()) return; applyCentralForce(m_gravity); + + m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); +#define FORCE_VELOCITY_DAMPING 1 +#ifdef FORCE_VELOCITY_DAMPING + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } +#endif //FORCE_VELOCITY_DAMPING + } void btRigidBody::proceedToTransform(const btTransform& newTrans) @@ -246,6 +285,7 @@ void btRigidBody::integrateVelocities(btScalar step) m_angularVelocity *= (MAX_ANGVEL/step) /angvel; } + clearForces(); } btQuaternion btRigidBody::getOrientation() const diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index 4596f90a00f..0707595d48e 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -16,29 +16,27 @@ subject to the following restrictions: #ifndef RIGIDBODY_H #define RIGIDBODY_H -#include "LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btTransform.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "../../LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btPoint3.h" +#include "../../LinearMath/btTransform.h" +#include "../../BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "../../BulletCollision/CollisionDispatch/btCollisionObject.h" class btCollisionShape; class btMotionState; class btTypedConstraint; +extern btScalar gLinearAirDamping; + extern btScalar gDeactivationTime; extern bool gDisableDeactivation; +extern btScalar gLinearSleepingThreshold; +extern btScalar gAngularSleepingThreshold; -///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. -///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. -///There are 3 types of rigid bodies: -///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. -///- B) Fixed objects with zero mass. They are not moving (basically collision objects) -///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. -///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. -///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) +/// btRigidBody class for btRigidBody Dynamics +/// class btRigidBody : public btCollisionObject { @@ -55,16 +53,7 @@ class btRigidBody : public btCollisionObject btScalar m_linearDamping; btScalar m_angularDamping; - - bool m_additionalDamping; - btScalar m_additionalDampingFactor; - btScalar m_additionalLinearDampingThresholdSqr; - btScalar m_additionalAngularDampingThresholdSqr; - btScalar m_additionalAngularDampingFactor; - - - btScalar m_linearSleepingThreshold; - btScalar m_angularSleepingThreshold; + //m_optionalMotionState allows to automatic synchronize the world transform for active objects btMotionState* m_optionalMotionState; @@ -74,85 +63,12 @@ class btRigidBody : public btCollisionObject public: +#ifdef OBSOLETE_MOTIONSTATE_LESS + //not supported, please use btMotionState + btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); +#endif //OBSOLETE_MOTIONSTATE_LESS - ///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. - ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) - ///You can use the motion state to synchronize the world transform between physics and graphics objects. - ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, - ///m_startWorldTransform is only used when you don't provide a motion state. - struct btRigidBodyConstructionInfo - { - btScalar m_mass; - - ///When a motionState is provided, the rigid body will initialize its world transform from the motion state - ///In this case, m_startWorldTransform is ignored. - btMotionState* m_motionState; - btTransform m_startWorldTransform; - - btCollisionShape* m_collisionShape; - btVector3 m_localInertia; - btScalar m_linearDamping; - btScalar m_angularDamping; - - ///best simulation results when friction is non-zero - btScalar m_friction; - ///best simulation results using zero restitution. - btScalar m_restitution; - - btScalar m_linearSleepingThreshold; - btScalar m_angularSleepingThreshold; - - //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. - //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete - bool m_additionalDamping; - btScalar m_additionalDampingFactor; - btScalar m_additionalLinearDampingThresholdSqr; - btScalar m_additionalAngularDampingThresholdSqr; - btScalar m_additionalAngularDampingFactor; - - - btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): - m_mass(mass), - m_motionState(motionState), - m_collisionShape(collisionShape), - m_localInertia(localInertia), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.)), - m_friction(btScalar(0.5)), - m_restitution(btScalar(0.)), - m_linearSleepingThreshold(btScalar(0.8)), - m_angularSleepingThreshold(btScalar(1.f)), - m_additionalDamping(false), - m_additionalDampingFactor(btScalar(0.005)), - m_additionalLinearDampingThresholdSqr(btScalar(0.01)), - m_additionalAngularDampingThresholdSqr(btScalar(0.01)), - m_additionalAngularDampingFactor(btScalar(0.01)) - { - m_startWorldTransform.setIdentity(); - } - }; - - ///btRigidBody constructor using construction info - btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); - - ///btRigidBody constructor for backwards compatibility. - ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) - btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); - - - virtual ~btRigidBody() - { - //No constraints should point to this rigidbody - //Remove constraints from the dynamics world before you delete the related rigidbodies. - btAssert(m_constraintRefs.size()==0); - } - -protected: - - ///setupRigidBody is only used internally by the constructor - void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); - -public: + btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); void proceedToTransform(const btTransform& newTrans); @@ -160,15 +76,11 @@ public: ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast static const btRigidBody* upcast(const btCollisionObject* colObj) { - if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY) - return (const btRigidBody*)colObj; - return 0; + return (const btRigidBody*)colObj->getInternalOwner(); } static btRigidBody* upcast(btCollisionObject* colObj) { - if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY) - return (btRigidBody*)colObj; - return 0; + return (btRigidBody*)colObj->getInternalOwner(); } /// continuous collision detection needs prediction @@ -176,7 +88,8 @@ public: void saveKinematicState(btScalar step); - void applyGravity(); + + void applyForces(btScalar step); void setGravity(const btVector3& acceleration); @@ -186,34 +99,12 @@ public: } void setDamping(btScalar lin_damping, btScalar ang_damping); - - btScalar getLinearDamping() const - { - return m_linearDamping; - } - - btScalar getAngularDamping() const - { - return m_angularDamping; - } - - btScalar getLinearSleepingThreshold() const - { - return m_linearSleepingThreshold; - } - - btScalar getAngularSleepingThreshold() const - { - return m_angularSleepingThreshold; - } - - void applyDamping(btScalar timeStep); - - SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { + + inline const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { + inline btCollisionShape* getCollisionShape() { return m_collisionShape; } @@ -243,12 +134,6 @@ public: m_invInertiaLocal = diagInvInertia; } - void setSleepingThresholds(btScalar linear,btScalar angular) - { - m_linearSleepingThreshold = linear; - m_angularSleepingThreshold = angular; - } - void applyTorque(const btVector3& torque) { m_totalTorque += torque; @@ -257,7 +142,7 @@ public: void applyForce(const btVector3& force, const btVector3& rel_pos) { applyCentralForce(force); - applyTorque(rel_pos.cross(force)*m_angularFactor); + applyTorque(rel_pos.cross(force)); } void applyCentralImpulse(const btVector3& impulse) @@ -283,7 +168,7 @@ public: } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { if (m_inverseMass != btScalar(0.)) { @@ -353,7 +238,7 @@ public: - SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const + inline btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const { btVector3 r0 = pos - getCenterOfMassPosition(); @@ -365,19 +250,19 @@ public: } - SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const + inline btScalar computeAngularImpulseDenominator(const btVector3& axis) const { btVector3 vec = axis * getInvInertiaTensorWorld(); return axis.dot(vec); } - SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) + inline void updateDeactivation(btScalar timeStep) { if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) return; - if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && - (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) + if ((getLinearVelocity().length2() < gLinearSleepingThreshold*gLinearSleepingThreshold) && + (getAngularVelocity().length2() < gAngularSleepingThreshold*gAngularSleepingThreshold)) { m_deactivationTime += timeStep; } else @@ -388,7 +273,7 @@ public: } - SIMD_FORCE_INLINE bool wantsSleeping() + inline bool wantsSleeping() { if (getActivationState() == DISABLE_DEACTIVATION) @@ -463,16 +348,6 @@ public: void addConstraintRef(btTypedConstraint* c); void removeConstraintRef(btTypedConstraint* c); - btTypedConstraint* getConstraintRef(int index) - { - return m_constraintRefs[index]; - } - - int getNumConstraintRefs() - { - return m_constraintRefs.size(); - } - int m_debugBodyId; }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 3be04d1a4ad..4ebcb8e7517 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -27,19 +27,16 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" -{ - void btBulletDynamicsProbe (); - void btBulletDynamicsProbe () {} -} +extern "C" void btBulletDynamicsProbe () {} -btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) -:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) +:btDynamicsWorld(dispatcher,pairCache), m_constraintSolver(constraintSolver), m_ownsConstraintSolver(false), +m_debugDrawer(0), m_gravity(0,0,-10) { @@ -49,7 +46,7 @@ m_gravity(0,0,-10) btSimpleDynamicsWorld::~btSimpleDynamicsWorld() { if (m_ownsConstraintSolver) - btAlignedFree( m_constraintSolver); + delete m_constraintSolver; } int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) @@ -77,9 +74,8 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b btContactSolverInfo infoGlobal; infoGlobal.m_timeStep = timeStep; - m_constraintSolver->prepareSolve(0,numManifolds); - m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1); - m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc); + + m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc); } ///integrate transforms @@ -89,27 +85,10 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b synchronizeMotionStates(); - clearForces(); - return 1; } -void btSimpleDynamicsWorld::clearForces() -{ - //todo: iterate over awake simulation islands! - for ( int i=0;iclearForces(); - } - } -} - void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) { @@ -125,11 +104,6 @@ void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) } } -btVector3 btSimpleDynamicsWorld::getGravity () const -{ - return m_gravity; -} - void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) { removeCollisionObject(body); @@ -159,7 +133,7 @@ void btSimpleDynamicsWorld::updateAabbs() btPoint3 minAabb,maxAabb; colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); btBroadphaseInterface* bp = getBroadphase(); - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); } } } @@ -197,9 +171,8 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { if (body->isActive()) { - body->applyGravity(); + body->applyForces( timeStep); body->integrateVelocities( timeStep); - body->applyDamping(timeStep); body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } @@ -231,13 +204,8 @@ void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - btAlignedFree(m_constraintSolver); + delete m_constraintSolver; } m_ownsConstraintSolver = false; m_constraintSolver = solver; } - -btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() -{ - return m_constraintSolver; -} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h index 5c56fdf1327..25f4ccd8e68 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -22,8 +22,11 @@ class btDispatcher; class btOverlappingPairCache; class btConstraintSolver; -///btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. -///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished). +///btSimpleDynamicsWorld demonstrates very basic usage of Bullet rigid body dynamics +///It can be used for basic simulations, and as a starting point for porting Bullet +///btSimpleDynamicsWorld lacks object deactivation, island management and other concepts. +///For more complicated simulations, btDiscreteDynamicsWorld and btContinuousDynamicsWorld are recommended +///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController class btSimpleDynamicsWorld : public btDynamicsWorld { protected: @@ -32,6 +35,8 @@ protected: bool m_ownsConstraintSolver; + btIDebugDraw* m_debugDrawer; + void predictUnconstraintMotion(btScalar timeStep); void integrateTransforms(btScalar timeStep); @@ -43,16 +48,24 @@ public: ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver - btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); virtual ~btSimpleDynamicsWorld(); ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - virtual void setGravity(const btVector3& gravity); + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + }; - virtual btVector3 getGravity () const; + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + virtual void setGravity(const btVector3& gravity); virtual void addRigidBody(btRigidBody* body); @@ -64,15 +77,6 @@ public: virtual void setConstraintSolver(btConstraintSolver* solver); - virtual btConstraintSolver* getConstraintSolver(); - - virtual btDynamicsWorldType getWorldType() const - { - return BT_SIMPLE_DYNAMICS_WORLD; - } - - virtual void clearForces(); - }; #endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp index fe65245c2a1..d53de7f3687 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -23,11 +23,12 @@ #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" + + static btRigidBody s_fixedObject( 0,0,0); btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) -: btTypedConstraint(VEHICLE_CONSTRAINT_TYPE), -m_vehicleRaycaster(raycaster), +:m_vehicleRaycaster(raycaster), m_pitchControl(btScalar(0.)) { m_chassisBody = chassis; @@ -486,7 +487,6 @@ struct btWheelContactPoint }; -btScalar calcRollingFriction(btWheelContactPoint& contactPoint); btScalar calcRollingFriction(btWheelContactPoint& contactPoint) { @@ -507,8 +507,8 @@ btScalar calcRollingFriction(btWheelContactPoint& contactPoint) // calculate j that moves us to zero relative velocity j1 = -vrel * contactPoint.m_jacDiagABInv; - btSetMin(j1, maxImpulse); - btSetMax(j1, -maxImpulse); + GEN_set_min(j1, maxImpulse); + GEN_set_max(j1, -maxImpulse); return j1; } @@ -525,10 +525,11 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) if (!numWheel) return; - m_forwardWS.resize(numWheel); - m_axle.resize(numWheel); - m_forwardImpulse.resize(numWheel); - m_sideImpulse.resize(numWheel); + + btVector3* forwardWS = new btVector3[numWheel]; + btVector3* axle = new btVector3[numWheel]; + btScalar* forwardImpulse = new btScalar[numWheel]; + btScalar* sideImpulse = new btScalar[numWheel]; int numWheelsOnGround = 0; @@ -540,8 +541,8 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; if (groundObject) numWheelsOnGround++; - m_sideImpulse[i] = btScalar(0.); - m_forwardImpulse[i] = btScalar(0.); + sideImpulse[i] = btScalar(0.); + forwardImpulse[i] = btScalar(0.); } @@ -560,25 +561,25 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) const btTransform& wheelTrans = getWheelTransformWS( i ); btMatrix3x3 wheelBasis0 = wheelTrans.getBasis(); - m_axle[i] = btVector3( + axle[i] = btVector3( wheelBasis0[0][m_indexRightAxis], wheelBasis0[1][m_indexRightAxis], wheelBasis0[2][m_indexRightAxis]); const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS; - btScalar proj = m_axle[i].dot(surfNormalWS); - m_axle[i] -= surfNormalWS * proj; - m_axle[i] = m_axle[i].normalize(); + btScalar proj = axle[i].dot(surfNormalWS); + axle[i] -= surfNormalWS * proj; + axle[i] = axle[i].normalize(); - m_forwardWS[i] = surfNormalWS.cross(m_axle[i]); - m_forwardWS[i].normalize(); + forwardWS[i] = surfNormalWS.cross(axle[i]); + forwardWS[i].normalize(); resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS, *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, - btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep); + btScalar(0.), axle[i],sideImpulse[i],timeStep); - m_sideImpulse[i] *= sideFrictionStiffness2; + sideImpulse[i] *= sideFrictionStiffness2; } @@ -607,7 +608,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) { btScalar defaultRollingFrictionImpulse = 0.f; btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; - btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse); + btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,forwardWS[wheel],maxImpulse); rollingFriction = calcRollingFriction(contactPt); } } @@ -617,7 +618,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) - m_forwardImpulse[wheel] = btScalar(0.); + forwardImpulse[wheel] = btScalar(0.); m_wheelInfo[wheel].m_skidInfo= btScalar(1.); if (groundObject) @@ -630,10 +631,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btScalar maximpSquared = maximp * maximpSide; - m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; + forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; - btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor; - btScalar y = (m_sideImpulse[wheel] ) * sideFactor; + btScalar x = (forwardImpulse[wheel] ) * fwdFactor; + btScalar y = (sideImpulse[wheel] ) * sideFactor; btScalar impulseSquared = (x*x + y*y); @@ -657,12 +658,12 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) { for (int wheel = 0;wheel < getNumWheels(); wheel++) { - if (m_sideImpulse[wheel] != btScalar(0.)) + if (sideImpulse[wheel] != btScalar(0.)) { if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) { - m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; - m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; } } } @@ -677,11 +678,11 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS - m_chassisBody->getCenterOfMassPosition(); - if (m_forwardImpulse[wheel] != btScalar(0.)) + if (forwardImpulse[wheel] != btScalar(0.)) { - m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); + m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos); } - if (m_sideImpulse[wheel] != btScalar(0.)) + if (sideImpulse[wheel] != btScalar(0.)) { class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; @@ -689,7 +690,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) groundObject->getCenterOfMassPosition(); - btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; + btVector3 sideImp = axle[wheel] * sideImpulse[wheel]; rel_pos[2] *= wheelInfo.m_rollInfluence; m_chassisBody->applyImpulse(sideImp,rel_pos); @@ -700,7 +701,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) } } - + delete []forwardWS; + delete [] axle; + delete[]forwardImpulse; + delete[] sideImpulse; } @@ -712,11 +716,11 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& m_dynamicsWorld->rayTest(from, to, rayCallback); - if (rayCallback.hasHit()) + if (rayCallback.HasHit()) { btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); - if (body && body->hasContactResponse()) + if (body) { result.m_hitPointInWorld = rayCallback.m_hitPointWorld; result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index 8361dcabe4b..f4249599615 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -11,11 +11,11 @@ #ifndef RAYCASTVEHICLE_H #define RAYCASTVEHICLE_H -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" +#include "../Dynamics/btRigidBody.h" +#include "../ConstraintSolver/btTypedConstraint.h" #include "btVehicleRaycaster.h" class btDynamicsWorld; -#include "LinearMath/btAlignedObjectArray.h" +#include "../../LinearMath/btAlignedObjectArray.h" #include "btWheelInfo.h" class btVehicleTuning; @@ -23,12 +23,6 @@ class btVehicleTuning; ///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. class btRaycastVehicle : public btTypedConstraint { - - btAlignedObjectArray m_forwardWS; - btAlignedObjectArray m_axle; - btAlignedObjectArray m_forwardImpulse; - btAlignedObjectArray m_sideImpulse; - public: class btVehicleTuning { @@ -120,7 +114,7 @@ public: void updateSuspension(btScalar deltaTime); - virtual void updateFriction(btScalar timeStep); + void updateFriction(btScalar timeStep); diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h index 5112ce6d420..64a47fcaada 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -11,7 +11,7 @@ #ifndef VEHICLE_RAYCASTER_H #define VEHICLE_RAYCASTER_H -#include "LinearMath/btVector3.h" +#include "../../LinearMath/btVector3.h" /// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting struct btVehicleRaycaster diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h index ac2729f4fd7..2e349b3fde4 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -11,8 +11,8 @@ #ifndef WHEEL_INFO_H #define WHEEL_INFO_H -#include "LinearMath/btVector3.h" -#include "LinearMath/btTransform.h" +#include "../../LinearMath/btVector3.h" +#include "../../LinearMath/btTransform.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletSoftBody/CMakeLists.txt b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt deleted file mode 100644 index a725e10ff77..00000000000 --- a/extern/bullet2/src/BulletSoftBody/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -INCLUDE_DIRECTORIES( -${BULLET_PHYSICS_SOURCE_DIR}/src } -) - -ADD_LIBRARY(LibBulletSoftBody - btSoftBody.cpp - btSoftBody.h - btSoftBodyHelpers.cpp - btSparseSDF.h - btSoftBodyHelpers.h - btSoftBodyRigidBodyCollisionConfiguration.cpp - btSoftRigidCollisionAlgorithm.cpp - btSoftRigidCollisionAlgorithm.h - btSoftSoftCollisionAlgorithm.cpp - btSoftSoftCollisionAlgorithm.h - btSoftBodyConcaveCollisionAlgorithm.cpp - btSoftBodyConcaveCollisionAlgorithm.h - btSoftRigidDynamicsWorld.h - btSoftRigidDynamicsWorld.cpp -) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp deleted file mode 100644 index 2553009fec2..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +++ /dev/null @@ -1,2590 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBody implementation by Nathanael Presson - -#include "btSoftBodyInternals.h" - -// -btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) -:m_worldInfo(worldInfo) -{ - /* Init */ - m_internalType = CO_SOFT_BODY; - m_cfg.aeromodel = eAeroModel::V_Point; - m_cfg.kVCF = 1; - m_cfg.kDG = 0; - m_cfg.kLF = 0; - m_cfg.kDP = 0; - m_cfg.kPR = 0; - m_cfg.kVC = 0; - m_cfg.kDF = (btScalar)0.2; - m_cfg.kMT = 0; - m_cfg.kCHR = (btScalar)1.0; - m_cfg.kKHR = (btScalar)0.1; - m_cfg.kSHR = (btScalar)1.0; - m_cfg.kAHR = (btScalar)0.7; - m_cfg.kSRHR_CL = (btScalar)0.1; - m_cfg.kSKHR_CL = (btScalar)1; - m_cfg.kSSHR_CL = (btScalar)0.5; - m_cfg.kSR_SPLT_CL = (btScalar)0.5; - m_cfg.kSK_SPLT_CL = (btScalar)0.5; - m_cfg.kSS_SPLT_CL = (btScalar)0.5; - m_cfg.maxvolume = (btScalar)1; - m_cfg.timescale = 1; - m_cfg.viterations = 0; - m_cfg.piterations = 1; - m_cfg.diterations = 0; - m_cfg.citerations = 4; - m_cfg.collisions = fCollision::Default; - m_pose.m_bvolume = false; - m_pose.m_bframe = false; - m_pose.m_volume = 0; - m_pose.m_com = btVector3(0,0,0); - m_pose.m_rot.setIdentity(); - m_pose.m_scl.setIdentity(); - m_tag = 0; - m_timeacc = 0; - m_bUpdateRtCst = true; - m_bounds[0] = btVector3(0,0,0); - m_bounds[1] = btVector3(0,0,0); - m_worldTransform.setIdentity(); - setSolver(eSolverPresets::Positions); - /* Default material */ - Material* pm=appendMaterial(); - pm->m_kLST = 1; - pm->m_kAST = 1; - pm->m_kVST = 1; - pm->m_flags = fMaterial::Default; - /* Collision shape */ - ///for now, create a collision shape internally - setCollisionShape(new btSoftBodyCollisionShape(this)); - m_collisionShape->setMargin(0.25); - /* Nodes */ - const btScalar margin=getCollisionShape()->getMargin(); - m_nodes.resize(node_count); - for(int i=0,ni=node_count;i0?1/n.m_im:0; - n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); - n.m_material= pm; - } - updateBounds(); - - -} - -// -btSoftBody::~btSoftBody() -{ - //for now, delete the internal shape - delete m_collisionShape; - int i; - - for(i=0;i0) - *pm=*m_materials[0]; - else - ZeroInitialize(*pm); -m_materials.push_back(pm); -return(pm); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - const btVector4& c, - Node* n0, - Node* n1, - Node* n2, - Node* n3) -{ -Note n; -ZeroInitialize(n); -n.m_rank = 0; -n.m_text = text; -n.m_offset = o; -n.m_coords[0] = c.x(); -n.m_coords[1] = c.y(); -n.m_coords[2] = c.z(); -n.m_coords[3] = c.w(); -n.m_nodes[0] = n0;n.m_rank+=n0?1:0; -n.m_nodes[1] = n1;n.m_rank+=n1?1:0; -n.m_nodes[2] = n2;n.m_rank+=n2?1:0; -n.m_nodes[3] = n3;n.m_rank+=n3?1:0; -m_notes.push_back(n); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - Node* feature) -{ -appendNote(text,o,btVector4(1,0,0,0),feature); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - Link* feature) -{ -static const btScalar w=1/(btScalar)2; -appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0], - feature->m_n[1]); -} - -// -void btSoftBody::appendNote( const char* text, - const btVector3& o, - Face* feature) -{ -static const btScalar w=1/(btScalar)3; -appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0], - feature->m_n[1], - feature->m_n[2]); -} - -// -void btSoftBody::appendNode( const btVector3& x,btScalar m) -{ -if(m_nodes.capacity()==m_nodes.size()) - { - pointersToIndices(); - m_nodes.reserve(m_nodes.size()*2+1); - indicesToPointers(); - } -const btScalar margin=getCollisionShape()->getMargin(); -m_nodes.push_back(Node()); -Node& n=m_nodes[m_nodes.size()-1]; -ZeroInitialize(n); -n.m_x = x; -n.m_q = n.m_x; -n.m_im = m>0?1/m:0; -n.m_material = m_materials[0]; -n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); -} - -// -void btSoftBody::appendLink(int model,Material* mat) -{ -Link l; -if(model>=0) - l=m_links[model]; - else - { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; } -m_links.push_back(l); -} - -// -void btSoftBody::appendLink( int node0, - int node1, - Material* mat, - bool bcheckexist) -{ - appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist); -} - -// -void btSoftBody::appendLink( Node* node0, - Node* node1, - Material* mat, - bool bcheckexist) -{ - if((!bcheckexist)||(!checkLink(node0,node1))) - { - appendLink(-1,mat); - Link& l=m_links[m_links.size()-1]; - l.m_n[0] = node0; - l.m_n[1] = node1; - l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); - m_bUpdateRtCst=true; - } -} - -// -void btSoftBody::appendFace(int model,Material* mat) -{ -Face f; -if(model>=0) - { f=m_faces[model]; } - else - { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; } -m_faces.push_back(f); -} - -// -void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) -{ - appendFace(-1,mat); - Face& f=m_faces[m_faces.size()-1]; - btAssert(node0!=node1); - btAssert(node1!=node2); - btAssert(node2!=node0); - f.m_n[0] = &m_nodes[node0]; - f.m_n[1] = &m_nodes[node1]; - f.m_n[2] = &m_nodes[node2]; - f.m_ra = AreaOf( f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x); - m_bUpdateRtCst=true; -} - -// -void btSoftBody::appendAnchor(int node,btRigidBody* body) -{ - Anchor a; - a.m_node = &m_nodes[node]; - a.m_body = body; - a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x; - a.m_node->m_battach = 1; - m_anchors.push_back(a); -} - -// -void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1) -{ -LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint(); -pj->m_bodies[0] = body0; -pj->m_bodies[1] = body1; -pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position; -pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position; -pj->m_cfm = specs.cfm; -pj->m_erp = specs.erp; -pj->m_split = specs.split; -m_joints.push_back(pj); -} - -// -void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body) -{ -appendLinearJoint(specs,m_clusters[0],body); -} - -// -void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) -{ -appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); -} - -// -void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1) -{ -AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint(); -pj->m_bodies[0] = body0; -pj->m_bodies[1] = body1; -pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis; -pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis; -pj->m_cfm = specs.cfm; -pj->m_erp = specs.erp; -pj->m_split = specs.split; -pj->m_icontrol = specs.icontrol; -m_joints.push_back(pj); -} - -// -void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body) -{ -appendAngularJoint(specs,m_clusters[0],body); -} - -// -void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) -{ -appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); -} - -// -void btSoftBody::addForce(const btVector3& force) -{ - for(int i=0,ni=m_nodes.size();i0) - { - n.m_f += force; - } -} - -// -void btSoftBody::addVelocity(const btVector3& velocity) -{ - for(int i=0,ni=m_nodes.size();i0) - { - n.m_v += velocity; - } -} - -// -void btSoftBody::setMass(int node,btScalar mass) -{ - m_nodes[node].m_im=mass>0?1/mass:0; - m_bUpdateRtCst=true; -} - -// -btScalar btSoftBody::getMass(int node) const -{ - return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); -} - -// -btScalar btSoftBody::getTotalMass() const -{ - btScalar mass=0; - for(int i=0;im_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x); - for(int j=0;j<3;++j) - { - f.m_n[j]->m_im+=twicearea; - } - } - for( i=0;igetMargin(); - for(int i=0,ni=m_nodes.size();igetMargin(); - for(int i=0,ni=m_nodes.size();i0 ? - 1/(m_nodes[i].m_im*tmass) : - kmass/tmass; - } - /* Pos */ - const btVector3 com=evaluateCom(); - m_pose.m_pos.resize(m_nodes.size()); - for( i=0,ni=m_nodes.size();i0) - { - int i,ni; - - const btVector3 org=m_nodes[0].m_x; - for(i=0,ni=m_faces.size();im_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); - } - vol/=(btScalar)6; - } - return(vol); -} - -// -int btSoftBody::clusterCount() const -{ -return(m_clusters.size()); -} - -// -btVector3 btSoftBody::clusterCom(const Cluster* cluster) -{ -btVector3 com(0,0,0); -for(int i=0,ni=cluster->m_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; - } -return(com*cluster->m_imass); -} - -// -btVector3 btSoftBody::clusterCom(int cluster) const -{ -return(clusterCom(m_clusters[cluster])); -} - -// -btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) -{ -return(cluster->m_lv+cross(cluster->m_av,rpos)); -} - -// -void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) -{ -const btVector3 li=cluster->m_imass*impulse; -const btVector3 ai=cluster->m_invwi*cross(rpos,impulse); -cluster->m_vimpulses[0]+=li;cluster->m_lv+=li; -cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; -cluster->m_nvimpulses++; -} - -// -void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) -{ -const btVector3 li=cluster->m_imass*impulse; -const btVector3 ai=cluster->m_invwi*cross(rpos,impulse); -cluster->m_dimpulses[0]+=li; -cluster->m_dimpulses[1]+=ai; -cluster->m_ndimpulses++; -} - -// -void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse) -{ -if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity); -if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift); -} - -// -void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse) -{ -const btVector3 ai=cluster->m_invwi*impulse; -cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; -cluster->m_nvimpulses++; -} - -// -void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse) -{ -const btVector3 ai=cluster->m_invwi*impulse; -cluster->m_dimpulses[1]+=ai; -cluster->m_ndimpulses++; -} - -// -void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse) -{ -if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity); -if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift); -} - -// -void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse) -{ -cluster->m_dimpulses[0]+=impulse*cluster->m_imass; -cluster->m_ndimpulses++; -} - -// -int btSoftBody::generateBendingConstraints(int distance,Material* mat) -{ - int i,j; - - if(distance>1) - { - /* Build graph */ - const int n=m_nodes.size(); - const unsigned inf=(~(unsigned)0)>>1; - unsigned* adj=new unsigned[n*n]; -#define IDX(_x_,_y_) ((_y_)*n+(_x_)) - for(j=0;jsum) - { - adj[IDX(i,j)]=adj[IDX(j,i)]=sum; - } - } - } - } - /* Build links */ - int nlinks=0; - for(j=0;jm_leaf) m_cdbvt.remove(m_clusters[i]->m_leaf); - btAlignedFree(m_clusters[i]); - } -m_clusters.resize(btMin(k,m_nodes.size())); - - - -for(i=0;im_collide= true; - } -k=m_clusters.size(); -if(k>0) - { - /* Initialize */ - btAlignedObjectArray centers; - btVector3 cog(0,0,0); - int i; - for(i=0;im_nodes.push_back(&m_nodes[i]); - } - cog/=(btScalar)m_nodes.size(); - centers.resize(k,cog); - /* Iterate */ - const btScalar slope=16; - bool changed; - int iterations=0; - do { - const btScalar w=2-btMin(1,iterations/slope); - changed=false; - iterations++; - int i; - - for(i=0;im_nodes.size();++j) - { - c+=m_clusters[i]->m_nodes[j]->m_x; - } - if(m_clusters[i]->m_nodes.size()) - { - c /= (btScalar)m_clusters[i]->m_nodes.size(); - c = centers[i]+(c-centers[i])*w; - changed |= ((c-centers[i]).length2()>SIMD_EPSILON); - centers[i] = c; - m_clusters[i]->m_nodes.resize(0); - } - } - for(i=0;im_nodes.push_back(&m_nodes[i]); - } - } while(changed&&(iterations cids; - cids.resize(m_nodes.size(),-1); - for(i=0;im_nodes.size();++j) - { - cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; - } - } - for(i=0;im_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) - { - m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); - } - } - } - } - } - /* Master */ - if(m_clusters.size()>1) - { - Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); - pmaster->m_collide = false; - pmaster->m_nodes.reserve(m_nodes.size()); - for(int i=0;im_nodes.push_back(&m_nodes[i]); - m_clusters.push_back(pmaster); - btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]); - } - /* Terminate */ - for(i=0;im_nodes.size()==0) - { - btAlignedFree(m_clusters[i]); - btSwap(m_clusters[i],m_clusters[m_clusters.size()-1]); - m_clusters.pop_back(); - --i; - } - } - - initializeClusters(); - updateClusters(); - return(m_clusters.size()); - } -return(0); -} - -// -void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut) -{ -const Node* nbase = &m_nodes[0]; -int ncount = m_nodes.size(); -btSymMatrix edges(ncount,-2); -int newnodes=0; -int i,j,k,ni; - -/* Filter out */ -for(i=0;iEval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x))) - { - btSwap(m_links[i],m_links[m_links.size()-1]); - m_links.pop_back();--i; - } - } - } -/* Fill edges */ -for(i=0;i0) - { - const btVector3 x=Lerp(a.m_x,b.m_x,t); - const btVector3 v=Lerp(a.m_v,b.m_v,t); - btScalar m=0; - if(a.m_im>0) - { - if(b.m_im>0) - { - const btScalar ma=1/a.m_im; - const btScalar mb=1/b.m_im; - const btScalar mc=Lerp(ma,mb,t); - const btScalar f=(ma+mb)/(ma+mb+mc); - a.m_im=1/(ma*f); - b.m_im=1/(mb*f); - m=mc*f; - } - else - { a.m_im/=0.5;m=1/a.m_im; } - } - else - { - if(b.m_im>0) - { b.m_im/=0.5;m=1/b.m_im; } - else - m=0; - } - appendNode(x,m); - edges(i,j)=m_nodes.size()-1; - m_nodes[edges(i,j)].m_v=v; - ++newnodes; - } - } - } - } -nbase=&m_nodes[0]; -/* Refine links */ -for(i=0,ni=m_links.size();i0) - { - appendLink(i); - Link* pft[]={ &m_links[i], - &m_links[m_links.size()-1]}; - pft[0]->m_n[0]=&m_nodes[idx[0]]; - pft[0]->m_n[1]=&m_nodes[ni]; - pft[1]->m_n[0]=&m_nodes[ni]; - pft[1]->m_n[1]=&m_nodes[idx[1]]; - } - } - } -/* Refine faces */ -for(i=0;i0) - { - appendFace(i); - const int l=(k+1)%3; - Face* pft[]={ &m_faces[i], - &m_faces[m_faces.size()-1]}; - pft[0]->m_n[0]=&m_nodes[idx[l]]; - pft[0]->m_n[1]=&m_nodes[idx[j]]; - pft[0]->m_n[2]=&m_nodes[ni]; - pft[1]->m_n[0]=&m_nodes[ni]; - pft[1]->m_n[1]=&m_nodes[idx[k]]; - pft[1]->m_n[2]=&m_nodes[idx[l]]; - appendLink(ni,idx[l],pft[0]->m_material); - --i;break; - } - } - } - } -/* Cut */ -if(cut) - { - btAlignedObjectArray cnodes; - const int pcount=ncount; - int i; - ncount=m_nodes.size(); - cnodes.resize(ncount,0); - /* Nodes */ - for(i=0;i=pcount)||(btFabs(ifn->Eval(x))0) { m*=0.5;m_nodes[i].m_im/=0.5; } - appendNode(x,m); - cnodes[i]=m_nodes.size()-1; - m_nodes[cnodes[i]].m_v=v; - } - } - nbase=&m_nodes[0]; - /* Links */ - for(i=0,ni=m_links.size();iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)Eval(n[0]->m_x)Eval(n[1]->m_x)Eval(n[2]->m_x) ranks; - btAlignedObjectArray todelete; - ranks.resize(nnodes,0); - for(i=0,ni=m_links.size();i=0;--i) - { - if(!ranks[i]) todelete.push_back(i); - } - if(todelete.size()) - { - btAlignedObjectArray& map=ranks; - for(int i=0;im_v=v; -pn[1]->m_v=v; -for(i=0,ni=m_links.size();im_n[1]=pn[mtch]; - pft[1]->m_n[0]=pn[1-mtch]; - done=true; - } - } -for(i=0,ni=m_faces.size();im_n[l]=pn[mtch]; - pft[1]->m_n[k]=pn[1-mtch]; - appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); - appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); - } - } - } -if(!done) - { - m_ndbvt.remove(pn[0]->m_leaf); - m_ndbvt.remove(pn[1]->m_leaf); - m_nodes.pop_back(); - m_nodes.pop_back(); - } -return(done); -} - -// -bool btSoftBody::rayCast(const btVector3& org, - const btVector3& dir, - sRayCast& results, - btScalar maxtime) -{ -if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree(); -results.body = this; -results.time = maxtime; -results.feature = eFeature::None; -results.index = -1; -return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0); -} - -// -void btSoftBody::setSolver(eSolverPresets::_ preset) -{ -m_cfg.m_vsequence.clear(); -m_cfg.m_psequence.clear(); -m_cfg.m_dsequence.clear(); -switch(preset) - { - case eSolverPresets::Positions: - m_cfg.m_psequence.push_back(ePSolver::Anchors); - m_cfg.m_psequence.push_back(ePSolver::RContacts); - m_cfg.m_psequence.push_back(ePSolver::SContacts); - m_cfg.m_psequence.push_back(ePSolver::Linear); - break; - case eSolverPresets::Velocities: - m_cfg.m_vsequence.push_back(eVSolver::Linear); - - m_cfg.m_psequence.push_back(ePSolver::Anchors); - m_cfg.m_psequence.push_back(ePSolver::RContacts); - m_cfg.m_psequence.push_back(ePSolver::SContacts); - - m_cfg.m_dsequence.push_back(ePSolver::Linear); - break; - } -} - -// -void btSoftBody::predictMotion(btScalar dt) -{ - int i,ni; - - /* Update */ - if(m_bUpdateRtCst) - { - m_bUpdateRtCst=false; - updateConstants(); - m_fdbvt.clear(); - if(m_cfg.collisions&fCollision::VF_SS) - { - initializeFaceTree(); - } - } - - /* Prepare */ - m_sst.sdt = dt*m_cfg.timescale; - m_sst.isdt = 1/m_sst.sdt; - m_sst.velmrg = m_sst.sdt*3; - m_sst.radmrg = getCollisionShape()->getMargin(); - m_sst.updmrg = m_sst.radmrg*(btScalar)0.25; - /* Forces */ - addVelocity(m_worldInfo->m_gravity*m_sst.sdt); - applyForces(); - /* Integrate */ - for(i=0,ni=m_nodes.size();im_v+ - f.m_n[1]->m_v+ - f.m_n[2]->m_v)/3; - m_fdbvt.update( f.m_leaf, - VolumeOf(f,m_sst.radmrg), - v*m_sst.velmrg, - m_sst.updmrg); - } - } - /* Pose */ - updatePose(); - /* Match */ - if(m_pose.m_bframe&&(m_cfg.kMT>0)) - { - const btMatrix3x3 posetrs=m_pose.m_rot; - for(int i=0,ni=m_nodes.size();i0) - { - const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com; - n.m_x=Lerp(n.m_x,x,m_cfg.kMT); - } - } - } - /* Clear contacts */ - m_rcontacts.resize(0); - m_scontacts.resize(0); - /* Optimize dbvt's */ - m_ndbvt.optimizeIncremental(1); - m_fdbvt.optimizeIncremental(1); - m_cdbvt.optimizeIncremental(1); -} - -// -void btSoftBody::solveConstraints() -{ -/* Apply clusters */ -applyClusters(false); -/* Prepare links */ - -int i,ni; - -for(i=0,ni=m_links.size();im_q-l.m_n[0]->m_q; - l.m_c2 = 1/(l.m_c3.length2()*l.m_c0); - } -/* Prepare anchors */ -for(i=0,ni=m_anchors.size();igetWorldTransform().getBasis()*a.m_local; - a.m_c0 = ImpulseMatrix( m_sst.sdt, - a.m_node->m_im, - a.m_body->getInvMass(), - a.m_body->getInvInertiaTensorWorld(), - ra); - a.m_c1 = ra; - a.m_c2 = m_sst.sdt*a.m_node->m_im; - a.m_body->activate(); - } -/* Solve velocities */ -if(m_cfg.viterations>0) - { - /* Solve */ - for(int isolve=0;isolve0) - { - for(int isolve=0;isolve0) - { - const btScalar vcf=m_cfg.kVCF*m_sst.isdt; - for(i=0,ni=m_nodes.size();i& bodies) -{ -const int nb=bodies.size(); -int iterations=0; -int i; - -for(i=0;im_cfg.citerations); - } -for(i=0;iprepareClusters(iterations); - } -for(i=0;isolveClusters(sor); - } - } -for(i=0;icleanupClusters(); - } -} - -// -void btSoftBody::integrateMotion() -{ - /* Update */ - updateNormals(); -} - -// - btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt) -{ -o = org; -d = dir; -mint = mxt; -face = 0; -tests = 0; -} - -// -void btSoftBody::RayCaster::Process(const btDbvtNode* leaf) -{ -btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; -const btScalar t=rayTriangle( o,d, - f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x, - mint); -if((t>0)&&(tteps)&&(tceps) && - (dot(n,cross(b-hit,c-hit))>ceps) && - (dot(n,cross(c-hit,a-hit))>ceps)) - { - return(t); - } - } - } - return(-1); -} - -// -void btSoftBody::pointersToIndices() -{ -#define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) - btSoftBody::Node* base=&m_nodes[0]; - int i,ni; - - for(i=0,ni=m_nodes.size();idata=*(void**)&i; - } - } - for(i=0,ni=m_links.size();idata=*(void**)&i; - } - } - for(i=0,ni=m_anchors.size();idata=&m_nodes[i]; - } - } - for(i=0,ni=m_links.size();idata=&m_faces[i]; - } - } - for(i=0,ni=m_anchors.size();im_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x, - mint); - if(t>0) - { - ++cnt; - if(!bcountonly) - { - feature=btSoftBody::eFeature::Face; - index=i; - mint=t; - } - } - } - } - else - {/* Use dbvt */ - RayCaster collider(org,dir,mint); - btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider); - if(collider.face) - { - mint=collider.mint; - feature=btSoftBody::eFeature::Face; - index=(int)(collider.face-&m_faces[0]); - cnt=1; - } - } - return(cnt); -} - -// -void btSoftBody::initializeFaceTree() -{ -m_fdbvt.clear(); -for(int i=0;igetCollisionShape(); - const btTransform& wtr=prb->getInterpolationWorldTransform(); - btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x), - shp, - nrm, - margin); - if(dst<0) - { - cti.m_body = prb; - cti.m_normal = wtr.getBasis()*nrm; - cti.m_offset = -dot( cti.m_normal, - x-cti.m_normal*dst); - return(true); - } - return(false); -} - -// -void btSoftBody::updateNormals() -{ - const btVector3 zv(0,0,0); - int i,ni; - - for(i=0,ni=m_nodes.size();im_x-f.m_n[0]->m_x, - f.m_n[2]->m_x-f.m_n[0]->m_x); - f.m_normal=n.normalized(); - f.m_n[0]->m_n+=n; - f.m_n[1]->m_n+=n; - f.m_n[2]->m_n+=n; - } - for(i=0,ni=m_nodes.size();iSIMD_EPSILON) - m_nodes[i].m_n /= len; - } -} - -// -void btSoftBody::updateBounds() -{ - if(m_ndbvt.m_root) - { - const btVector3& mins=m_ndbvt.m_root->volume.Mins(); - const btVector3& maxs=m_ndbvt.m_root->volume.Maxs(); - const btScalar csm=getCollisionShape()->getMargin(); - const btVector3 mrg=btVector3( csm, - csm, - csm)*1; // ??? to investigate... - m_bounds[0]=mins-mrg; - m_bounds[1]=maxs+mrg; - if(0!=getBroadphaseHandle()) - { - m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), - m_bounds[0], - m_bounds[1], - m_worldInfo->m_dispatcher); - } - } - else - { - m_bounds[0]= - m_bounds[1]=btVector3(0,0,0); - } -} - - -// -void btSoftBody::updatePose() -{ - if(m_pose.m_bframe) - { - btSoftBody::Pose& pose=m_pose; - const btVector3 com=evaluateCom(); - /* Com */ - pose.m_com = com; - /* Rotation */ - btMatrix3x3 Apq; - const btScalar eps=SIMD_EPSILON; - Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); - Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); - for(int i=0,ni=m_nodes.size();i1) - { - const btScalar idet=Clamp( 1/pose.m_scl.determinant(), - 1,m_cfg.maxvolume); - pose.m_scl=Mul(pose.m_scl,idet); - } - - } -} - -// -void btSoftBody::updateConstants() -{ - int i,ni; - - /* Links */ - for(i=0,ni=m_links.size();im_x-l.m_n[1]->m_x).length(); - l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST; - l.m_c1 = l.m_rl*l.m_rl; - } - /* Faces */ - for(i=0,ni=m_faces.size();im_x,f.m_n[1]->m_x,f.m_n[2]->m_x); - } - /* Area's */ - btAlignedObjectArray counts; - counts.resize(m_nodes.size(),0); - for(i=0,ni=m_nodes.size();im_area+=btFabs(f.m_ra); - } - } - for(i=0,ni=m_nodes.size();i0) - m_nodes[i].m_area/=(btScalar)counts[i]; - else - m_nodes[i].m_area=0; - } -} - -// -void btSoftBody::initializeClusters() -{ - int i; - -for( i=0;im_im>0?1/c.m_nodes[j]->m_im:0; - c.m_imass += c.m_masses[j]; - } - c.m_imass = 1/c.m_imass; - c.m_com = btSoftBody::clusterCom(&c); - c.m_lv = btVector3(0,0,0); - c.m_av = btVector3(0,0,0); - c.m_leaf = 0; - /* Inertia */ - btMatrix3x3& ii=c.m_locii; - ii[0]=ii[1]=ii[2]=btVector3(0,0,0); - { - int i,ni; - - for(i=0,ni=c.m_nodes.size();im_x-c.m_com; - const btVector3 q=k*k; - const btScalar m=c.m_masses[i]; - ii[0][0] += m*(q[1]+q[2]); - ii[1][1] += m*(q[0]+q[2]); - ii[2][2] += m*(q[0]+q[1]); - ii[0][1] -= m*k[0]*k[1]; - ii[0][2] -= m*k[0]*k[2]; - ii[1][2] -= m*k[1]*k[2]; - } - } - ii[1][0]=ii[0][1]; - ii[2][0]=ii[0][2]; - ii[2][1]=ii[1][2]; - ii=ii.inverse(); - /* Frame */ - c.m_framexform.setIdentity(); - c.m_framexform.setOrigin(c.m_com); - c.m_framerefs.resize(c.m_nodes.size()); - { - int i; - for(i=0;im_x-c.m_com; - } - } - } -} - -// -void btSoftBody::updateClusters() -{ -BT_PROFILE("UpdateClusters"); -int i; - -for(i=0;im_x-c.m_com; - const btVector3& b=c.m_framerefs[i]; - m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b; - } - PolarDecompose(m,r,s); - c.m_framexform.setOrigin(c.m_com); - c.m_framexform.setBasis(r); - /* Inertia */ - #if 1/* Constant */ - c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose(); - #else - #if 0/* Sphere */ - const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass); - const btVector3 inertia(rk,rk,rk); - const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0, - btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0, - btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0); - - c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose(); - #else/* Actual */ - c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0); - for(int i=0;im_x-c.m_com; - const btVector3 q=k*k; - const btScalar m=1/c.m_nodes[i]->m_im; - c.m_invwi[0][0] += m*(q[1]+q[2]); - c.m_invwi[1][1] += m*(q[0]+q[2]); - c.m_invwi[2][2] += m*(q[0]+q[1]); - c.m_invwi[0][1] -= m*k[0]*k[1]; - c.m_invwi[0][2] -= m*k[0]*k[2]; - c.m_invwi[1][2] -= m*k[1]*k[2]; - } - c.m_invwi[1][0]=c.m_invwi[0][1]; - c.m_invwi[2][0]=c.m_invwi[0][2]; - c.m_invwi[2][1]=c.m_invwi[1][2]; - c.m_invwi=c.m_invwi.inverse(); - #endif - #endif - /* Velocities */ - c.m_lv=btVector3(0,0,0); - c.m_av=btVector3(0,0,0); - { - int i; - - for(i=0;im_v*c.m_masses[i]; - c.m_lv += v; - c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v); - } - } - c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping); - c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping); - c.m_vimpulses[0] = - c.m_vimpulses[1] = btVector3(0,0,0); - c.m_dimpulses[0] = - c.m_dimpulses[1] = btVector3(0,0,0); - c.m_nvimpulses = 0; - c.m_ndimpulses = 0; - /* Matching */ - if(c.m_matching>0) - { - for(int j=0;jm_x; - btVector3 mx=mi; - for(int j=1;jm_x); - mx.setMax(c.m_nodes[j]->m_x); - } - const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); - if(c.m_leaf) - m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); - else - c.m_leaf=m_cdbvt.insert(bounds,&c); - } - } - } -} - -// -void btSoftBody::cleanupClusters() -{ -for(int i=0;iTerminate(m_sst.sdt); - if(m_joints[i]->m_delete) - { - btAlignedFree(m_joints[i]); - m_joints.remove(m_joints[i--]); - } - } -} - -// -void btSoftBody::prepareClusters(int iterations) -{ -for(int i=0;iPrepare(m_sst.sdt,iterations); - } -} - - -// -void btSoftBody::solveClusters(btScalar sor) -{ -for(int i=0,ni=m_joints.size();iSolve(m_sst.sdt,sor); - } -} - -// -void btSoftBody::applyClusters(bool drift) -{ -BT_PROFILE("ApplyClusters"); -const btScalar f0=m_sst.sdt; -const btScalar f1=f0/2; -btAlignedObjectArray deltas; -btAlignedObjectArray weights; -deltas.resize(m_nodes.size(),btVector3(0,0,0)); -weights.resize(m_nodes.size(),0); -int i; - -if(drift) - { - for(i=0;im_x; - const btScalar q=c.m_masses[j]; - deltas[idx] += (v+cross(w,x-c.m_com))*q; - weights[idx] += q; - } - } - } - for(i=0;i0) m_nodes[i].m_x+=deltas[i]/weights[i]; - } -} - -// -void btSoftBody::dampClusters() -{ - int i; - -for(i=0;i0) - { - for(int j=0;j0) - { - const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com); - n.m_v += c.m_ndamping*(vx-n.m_v); - } - } - } - } -} - -// -void btSoftBody::Joint::Prepare(btScalar dt,int) -{ -m_bodies[0].activate(); -m_bodies[1].activate(); -} - -// -void btSoftBody::LJoint::Prepare(btScalar dt,int iterations) -{ -static const btScalar maxdrift=4; -Joint::Prepare(dt,iterations); -m_rpos[0] = m_bodies[0].xform()*m_refs[0]; -m_rpos[1] = m_bodies[1].xform()*m_refs[1]; -m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt; -m_rpos[0] -= m_bodies[0].xform().getOrigin(); -m_rpos[1] -= m_bodies[1].xform().getOrigin(); -m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0], - m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]); -if(m_split>0) - { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; - } -m_drift /=(btScalar)iterations; -} - -// -void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor) -{ -const btVector3 va=m_bodies[0].velocity(m_rpos[0]); -const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); -const btVector3 vr=va-vb; -btSoftBody::Impulse impulse; -impulse.m_asVelocity = 1; -impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor; -m_bodies[0].applyImpulse(-impulse,m_rpos[0]); -m_bodies[1].applyImpulse( impulse,m_rpos[1]); -} - -// -void btSoftBody::LJoint::Terminate(btScalar dt) -{ -if(m_split>0) - { - m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); - m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); - } -} - -// -void btSoftBody::AJoint::Prepare(btScalar dt,int iterations) -{ -static const btScalar maxdrift=SIMD_PI/16; -m_icontrol->Prepare(this); -Joint::Prepare(dt,iterations); -m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0]; -m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1]; -m_drift = NormalizeAny(cross(m_axis[1],m_axis[0])); -m_drift *= btMin(maxdrift,btAcos(Clamp(dot(m_axis[0],m_axis[1]),-1,+1))); -m_drift *= m_erp/dt; -m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia()); -if(m_split>0) - { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; - } -m_drift /=(btScalar)iterations; -} - -// -void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor) -{ -const btVector3 va=m_bodies[0].angularVelocity(); -const btVector3 vb=m_bodies[1].angularVelocity(); -const btVector3 vr=va-vb; -const btScalar sp=dot(vr,m_axis[0]); -const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp); -btSoftBody::Impulse impulse; -impulse.m_asVelocity = 1; -impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor; -m_bodies[0].applyAImpulse(-impulse); -m_bodies[1].applyAImpulse( impulse); -} - -// -void btSoftBody::AJoint::Terminate(btScalar dt) -{ -if(m_split>0) - { - m_bodies[0].applyDAImpulse(-m_sdrift); - m_bodies[1].applyDAImpulse( m_sdrift); - } -} - -// -void btSoftBody::CJoint::Prepare(btScalar dt,int iterations) -{ -Joint::Prepare(dt,iterations); -const bool dodrift=(m_life==0); -m_delete=(++m_life)>m_maxlife; -if(dodrift) - { - m_drift=m_drift*m_erp/dt; - if(m_split>0) - { - m_sdrift = m_massmatrix*(m_drift*m_split); - m_drift *= 1-m_split; - } - m_drift/=(btScalar)iterations; - } - else - { - m_drift=m_sdrift=btVector3(0,0,0); - } -} - -// -void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor) -{ -const btVector3 va=m_bodies[0].velocity(m_rpos[0]); -const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); -const btVector3 vrel=va-vb; -const btScalar rvac=dot(vrel,m_normal); -btSoftBody::Impulse impulse; -impulse.m_asVelocity = 1; -impulse.m_velocity = m_drift; -if(rvac<0) - { - const btVector3 iv=m_normal*rvac; - const btVector3 fv=vrel-iv; - impulse.m_velocity += iv+fv*m_friction; - } -impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor; -m_bodies[0].applyImpulse(-impulse,m_rpos[0]); -m_bodies[1].applyImpulse( impulse,m_rpos[1]); -} - -// -void btSoftBody::CJoint::Terminate(btScalar dt) -{ -if(m_split>0) - { - m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); - m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); - } -} - -// -void btSoftBody::applyForces() -{ - BT_PROFILE("SoftBody applyForces"); - const btScalar dt=m_sst.sdt; - const btScalar kLF=m_cfg.kLF; - const btScalar kDG=m_cfg.kDG; - const btScalar kPR=m_cfg.kPR; - const btScalar kVC=m_cfg.kVC; - const bool as_lift=kLF>0; - const bool as_drag=kDG>0; - const bool as_pressure=kPR!=0; - const bool as_volume=kVC>0; - const bool as_aero= as_lift || - as_drag ; - const bool as_vaero= as_aero && - (m_cfg.aeromodel=btSoftBody::eAeroModel::F_TwoSided); - const bool use_medium= as_aero; - const bool use_volume= as_pressure || - as_volume ; - btScalar volume=0; - btScalar ivolumetp=0; - btScalar dvolumetv=0; - btSoftBody::sMedium medium; - if(use_volume) - { - volume = getVolume(); - ivolumetp = 1/btFabs(volume)*kPR; - dvolumetv = (m_pose.m_volume-volume)*kVC; - } - /* Per vertex forces */ - int i,ni; - - for(i=0,ni=m_nodes.size();i0) - { - if(use_medium) - { - EvaluateMedium(m_worldInfo,n.m_x,medium); - /* Aerodynamics */ - if(as_vaero) - { - const btVector3 rel_v=n.m_v-medium.m_velocity; - const btScalar rel_v2=rel_v.length2(); - if(rel_v2>SIMD_EPSILON) - { - btVector3 nrm=n.m_n; - /* Setup normal */ - switch(m_cfg.aeromodel) - { - case btSoftBody::eAeroModel::V_Point: - nrm=NormalizeAny(rel_v);break; - case btSoftBody::eAeroModel::V_TwoSided: - nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break; - } - const btScalar dvn=dot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) - { - btVector3 force(0,0,0); - const btScalar c0 = n.m_area*dvn*rel_v2/2; - const btScalar c1 = c0*medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized()*(-c1*kDG); - ApplyClampedForce(n,force,dt); - } - } - } - } - /* Pressure */ - if(as_pressure) - { - n.m_f += n.m_n*(n.m_area*ivolumetp); - } - /* Volume */ - if(as_volume) - { - n.m_f += n.m_n*(n.m_area*dvolumetv); - } - } - } - /* Per face forces */ - for(i=0,ni=m_faces.size();im_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; - const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; - EvaluateMedium(m_worldInfo,x,medium); - const btVector3 rel_v=v-medium.m_velocity; - const btScalar rel_v2=rel_v.length2(); - if(rel_v2>SIMD_EPSILON) - { - btVector3 nrm=f.m_normal; - /* Setup normal */ - switch(m_cfg.aeromodel) - { - case btSoftBody::eAeroModel::F_TwoSided: - nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break; - } - const btScalar dvn=dot(rel_v,nrm); - /* Compute forces */ - if(dvn>0) - { - btVector3 force(0,0,0); - const btScalar c0 = f.m_ra*dvn*rel_v2; - const btScalar c1 = c0*medium.m_density; - force += nrm*(-c1*kLF); - force += rel_v.normalized()*(-c1*kDG); - force /= 3; - for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); - } - } - } - } -} - -// -void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti) -{ - const btScalar kAHR=psb->m_cfg.kAHR*kst; - const btScalar dt=psb->m_sst.sdt; - for(int i=0,ni=psb->m_anchors.size();im_anchors[i]; - const btTransform& t=a.m_body->getInterpolationWorldTransform(); - Node& n=*a.m_node; - const btVector3 wa=t*a.m_local; - const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; - const btVector3 vb=n.m_x-n.m_q; - const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; - const btVector3 impulse=a.m_c0*vr; - n.m_x+=impulse*a.m_c2; - a.m_body->applyImpulse(-impulse,a.m_c1); - } -} - -// -void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti) -{ - const btScalar dt=psb->m_sst.sdt; - const btScalar mrg=psb->getCollisionShape()->getMargin(); - for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; - const sCti& cti=c.m_cti; - const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt; - const btVector3 vb=c.m_node->m_x-c.m_node->m_q; - const btVector3 vr=vb-va; - const btScalar dn=dot(vr,cti.m_normal); - if(dn<=SIMD_EPSILON) - { - const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg); - const btVector3 fv=vr-cti.m_normal*dn; - const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst); - c.m_node->m_x-=impulse*c.m_c2; - c.m_cti.m_body->applyImpulse(impulse,c.m_c1); - } - } -} - -// -void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) -{ -for(int i=0,ni=psb->m_scontacts.size();im_scontacts[i]; - const btVector3& nr=c.m_normal; - Node& n=*c.m_node; - Face& f=*c.m_face; - const btVector3 p=BaryEval( f.m_n[0]->m_x, - f.m_n[1]->m_x, - f.m_n[2]->m_x, - c.m_weights); - const btVector3 q=BaryEval( f.m_n[0]->m_q, - f.m_n[1]->m_q, - f.m_n[2]->m_q, - c.m_weights); - const btVector3 vr=(n.m_x-n.m_q)-(p-q); - btVector3 corr(0,0,0); - if(dot(vr,nr)<0) - { - const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p)); - corr+=c.m_normal*j; - } - corr -= ProjectOnPlane(vr,nr)*c.m_friction; - n.m_x += corr*c.m_cfm[0]; - f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x()); - f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y()); - f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z()); - } -} - -// -void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) -{ - for(int i=0,ni=psb->m_links.size();im_links[i]; - if(l.m_c0>0) - { - Node& a=*l.m_n[0]; - Node& b=*l.m_n[1]; - const btVector3 del=b.m_x-a.m_x; - const btScalar len=del.length2(); - const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst; - const btScalar t=k*a.m_im; - a.m_x-=del*(k*a.m_im); - b.m_x+=del*(k*b.m_im); - } - } -} - -// -void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) -{ -for(int i=0,ni=psb->m_links.size();im_links[i]; - Node** n=l.m_n; - const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst; - n[0]->m_v+= l.m_c3*(j*n[0]->m_im); - n[1]->m_v-= l.m_c3*(j*n[1]->m_im); - } -} - -// -btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver) -{ -switch(solver) - { - case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors); - case ePSolver::Linear: return(&btSoftBody::PSolve_Links); - case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts); - case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts); - } -return(0); -} - -// -btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) -{ -switch(solver) - { - case eVSolver::Linear: return(&btSoftBody::VSolve_Links); - } -return(0); -} - -// -void btSoftBody::defaultCollisionHandler(btCollisionObject* pco) -{ -switch(m_cfg.collisions&fCollision::RVSmask) - { - case fCollision::SDF_RS: - { - btSoftColliders::CollideSDF_RS docollide; - btRigidBody* prb=btRigidBody::upcast(pco); - const btTransform wtr=prb->getInterpolationWorldTransform(); - const btTransform ctr=prb->getWorldTransform(); - const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length(); - const btScalar basemargin=getCollisionShape()->getMargin(); - btVector3 mins; - btVector3 maxs; - ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; - pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(), - mins, - maxs); - volume=btDbvtVolume::FromMM(mins,maxs); - volume.Expand(btVector3(basemargin,basemargin,basemargin)); - docollide.psb = this; - docollide.prb = prb; - docollide.dynmargin = basemargin+timemargin; - docollide.stamargin = basemargin; - btDbvt::collideTV(m_ndbvt.m_root,volume,docollide); - } - break; - case fCollision::CL_RS: - { - btSoftColliders::CollideCL_RS collider; - collider.Process(this,btRigidBody::upcast(pco)); - } - break; - } -} - -// -void btSoftBody::defaultCollisionHandler(btSoftBody* psb) -{ -const int cf=m_cfg.collisions&psb->m_cfg.collisions; -switch(cf&fCollision::SVSmask) - { - case fCollision::CL_SS: - { - btSoftColliders::CollideCL_SS docollide; - docollide.Process(this,psb); - } - break; - case fCollision::VF_SS: - { - btSoftColliders::CollideVF_SS docollide; - /* common */ - docollide.mrg= getCollisionShape()->getMargin()+ - psb->getCollisionShape()->getMargin(); - /* psb0 nodes vs psb1 faces */ - docollide.psb[0]=this; - docollide.psb[1]=psb; - btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root, - docollide.psb[1]->m_fdbvt.m_root, - docollide); - /* psb1 nodes vs psb0 faces */ - docollide.psb[0]=psb; - docollide.psb[1]=this; - btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root, - docollide.psb[1]->m_fdbvt.m_root, - docollide); - } - break; - } -} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h deleted file mode 100644 index 834199c668a..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h +++ /dev/null @@ -1,810 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBody implementation by Nathanael Presson - -#ifndef _BT_SOFT_BODY_H -#define _BT_SOFT_BODY_H - -#include "LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btPoint3.h" -#include "LinearMath/btTransform.h" -#include "LinearMath/btIDebugDraw.h" -#include "BulletDynamics/Dynamics/btRigidBody.h" - -#include "BulletCollision/CollisionShapes/btConcaveShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -#include "btSparseSDF.h" -#include "BulletCollision/BroadphaseCollision/btDbvt.h" - -class btBroadphaseInterface; -class btCollisionDispatcher; - -/* btSoftBodyWorldInfo */ -struct btSoftBodyWorldInfo -{ - btScalar air_density; - btScalar water_density; - btScalar water_offset; - btVector3 water_normal; - btBroadphaseInterface* m_broadphase; - btCollisionDispatcher* m_dispatcher; - btVector3 m_gravity; - btSparseSdf<3> m_sparsesdf; -}; - - -/// btSoftBody is work-in-progress -class btSoftBody : public btCollisionObject -{ -public: - // - // Enumerations - // - - ///eAeroModel - struct eAeroModel { enum _ { - V_Point, ///Vertex normals are oriented toward velocity - V_TwoSided, ///Vertex normals are fliped to match velocity - V_OneSided, ///Vertex normals are taken as it is - F_TwoSided, ///Face normals are fliped to match velocity - F_OneSided, ///Face normals are taken as it is - END - };}; - - ///eVSolver : velocities solvers - struct eVSolver { enum _ { - Linear, ///Linear solver - END - };}; - - ///ePSolver : positions solvers - struct ePSolver { enum _ { - Linear, ///Linear solver - Anchors, ///Anchor solver - RContacts, ///Rigid contacts solver - SContacts, ///Soft contacts solver - END - };}; - - ///eSolverPresets - struct eSolverPresets { enum _ { - Positions, - Velocities, - Default = Positions, - END - };}; - - ///eFeature - struct eFeature { enum _ { - None, - Node, - Link, - Face, - END - };}; - - typedef btAlignedObjectArray tVSolverArray; - typedef btAlignedObjectArray tPSolverArray; - - // - // Flags - // - - ///fCollision - struct fCollision { enum _ { - RVSmask = 0x000f, ///Rigid versus soft mask - SDF_RS = 0x0001, ///SDF based rigid vs soft - CL_RS = 0x0002, ///Cluster vs convex rigid vs soft - - SVSmask = 0x00f0, ///Rigid versus soft mask - VF_SS = 0x0010, ///Vertex vs face soft vs soft handling - CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling - /* presets */ - Default = SDF_RS, - END - };}; - - ///fMaterial - struct fMaterial { enum _ { - DebugDraw = 0x0001, /// Enable debug draw - /* presets */ - Default = DebugDraw, - END - };}; - - // - // API Types - // - - /* sRayCast */ - struct sRayCast - { - btSoftBody* body; /// soft body - eFeature::_ feature; /// feature type - int index; /// feature index - btScalar time; /// time of impact (rayorg+raydir*time) - }; - - /* ImplicitFn */ - struct ImplicitFn - { - virtual btScalar Eval(const btVector3& x)=0; - }; - - // - // Internal types - // - - typedef btAlignedObjectArray tScalarArray; - typedef btAlignedObjectArray tVector3Array; - - /* sCti is Softbody contact info */ - struct sCti - { - btRigidBody* m_body; /* Rigid body */ - btVector3 m_normal; /* Outward normal */ - btScalar m_offset; /* Offset from origin */ - }; - - /* sMedium */ - struct sMedium - { - btVector3 m_velocity; /* Velocity */ - btScalar m_pressure; /* Pressure */ - btScalar m_density; /* Density */ - }; - - /* Base type */ - struct Element - { - void* m_tag; // User data - Element() : m_tag(0) {} - }; - /* Material */ - struct Material : Element - { - btScalar m_kLST; // Linear stiffness coefficient [0,1] - btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] - btScalar m_kVST; // Volume stiffness coefficient [0,1] - int m_flags; // Flags - }; - - /* Feature */ - struct Feature : Element - { - Material* m_material; // Material - }; - /* Node */ - struct Node : Feature - { - btVector3 m_x; // Position - btVector3 m_q; // Previous step position - btVector3 m_v; // Velocity - btVector3 m_f; // Force accumulator - btVector3 m_n; // Normal - btScalar m_im; // 1/mass - btScalar m_area; // Area - btDbvtNode* m_leaf; // Leaf data - int m_battach:1; // Attached - }; - /* Link */ - struct Link : Feature - { - Node* m_n[2]; // Node pointers - btScalar m_rl; // Rest length - int m_bbending:1; // Bending link - btScalar m_c0; // (ima+imb)*kLST - btScalar m_c1; // rl^2 - btScalar m_c2; // |gradient|^2/c0 - btVector3 m_c3; // gradient - }; - /* Face */ - struct Face : Feature - { - Node* m_n[3]; // Node pointers - btVector3 m_normal; // Normal - btScalar m_ra; // Rest area - btDbvtNode* m_leaf; // Leaf data - }; - /* RContact */ - struct RContact - { - sCti m_cti; // Contact infos - Node* m_node; // Owner node - btMatrix3x3 m_c0; // Impulse matrix - btVector3 m_c1; // Relative anchor - btScalar m_c2; // ima*dt - btScalar m_c3; // Friction - btScalar m_c4; // Hardness - }; - /* SContact */ - struct SContact - { - Node* m_node; // Node - Face* m_face; // Face - btVector3 m_weights; // Weigths - btVector3 m_normal; // Normal - btScalar m_margin; // Margin - btScalar m_friction; // Friction - btScalar m_cfm[2]; // Constraint force mixing - }; - /* Anchor */ - struct Anchor - { - Node* m_node; // Node pointer - btVector3 m_local; // Anchor position in body space - btRigidBody* m_body; // Body - btMatrix3x3 m_c0; // Impulse matrix - btVector3 m_c1; // Relative anchor - btScalar m_c2; // ima*dt - }; - /* Note */ - struct Note : Element - { - const char* m_text; // Text - btVector3 m_offset; // Offset - int m_rank; // Rank - Node* m_nodes[4]; // Nodes - btScalar m_coords[4]; // Coordinates - }; - /* Pose */ - struct Pose - { - bool m_bvolume; // Is valid - bool m_bframe; // Is frame - btScalar m_volume; // Rest volume - tVector3Array m_pos; // Reference positions - tScalarArray m_wgh; // Weights - btVector3 m_com; // COM - btMatrix3x3 m_rot; // Rotation - btMatrix3x3 m_scl; // Scale - btMatrix3x3 m_aqq; // Base scaling - }; - /* Cluster */ - struct Cluster - { - btAlignedObjectArray m_nodes; - tScalarArray m_masses; - tVector3Array m_framerefs; - btTransform m_framexform; - btScalar m_idmass; - btScalar m_imass; - btMatrix3x3 m_locii; - btMatrix3x3 m_invwi; - btVector3 m_com; - btVector3 m_vimpulses[2]; - btVector3 m_dimpulses[2]; - int m_nvimpulses; - int m_ndimpulses; - btVector3 m_lv; - btVector3 m_av; - btDbvtNode* m_leaf; - btScalar m_ndamping; - btScalar m_ldamping; - btScalar m_adamping; - btScalar m_matching; - bool m_collide; - Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {} - }; - /* Impulse */ - struct Impulse - { - btVector3 m_velocity; - btVector3 m_drift; - int m_asVelocity:1; - int m_asDrift:1; - Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} - Impulse operator -() const - { - Impulse i=*this; - i.m_velocity=-i.m_velocity; - i.m_drift=-i.m_drift; - return(i); - } - Impulse operator*(btScalar x) const - { - Impulse i=*this; - i.m_velocity*=x; - i.m_drift*=x; - return(i); - } - }; - /* Body */ - struct Body - { - Cluster* m_soft; - btRigidBody* m_rigid; - Body() : m_soft(0),m_rigid(0) {} - Body(Cluster* p) : m_soft(p),m_rigid(0) {} - Body(btRigidBody* p) : m_soft(0),m_rigid(p) {} - void activate() const - { - if(m_rigid) m_rigid->activate(); - } - const btMatrix3x3& invWorldInertia() const - { - static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); - if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); - if(m_soft) return(m_soft->m_invwi); - return(iwi); - } - btScalar invMass() const - { - if(m_rigid) return(m_rigid->getInvMass()); - if(m_soft) return(m_soft->m_imass); - return(0); - } - const btTransform& xform() const - { - static const btTransform identity=btTransform::getIdentity(); - if(m_rigid) return(m_rigid->getInterpolationWorldTransform()); - if(m_soft) return(m_soft->m_framexform); - return(identity); - } - btVector3 linearVelocity() const - { - if(m_rigid) return(m_rigid->getLinearVelocity()); - if(m_soft) return(m_soft->m_lv); - return(btVector3(0,0,0)); - } - btVector3 angularVelocity(const btVector3& rpos) const - { - if(m_rigid) return(cross(m_rigid->getAngularVelocity(),rpos)); - if(m_soft) return(cross(m_soft->m_av,rpos)); - return(btVector3(0,0,0)); - } - btVector3 angularVelocity() const - { - if(m_rigid) return(m_rigid->getAngularVelocity()); - if(m_soft) return(m_soft->m_av); - return(btVector3(0,0,0)); - } - btVector3 velocity(const btVector3& rpos) const - { - return(linearVelocity()+angularVelocity(rpos)); - } - void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const - { - if(m_rigid) m_rigid->applyImpulse(impulse,rpos); - if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); - } - void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const - { - if(m_rigid) m_rigid->applyImpulse(impulse,rpos); - if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); - } - void applyImpulse(const Impulse& impulse,const btVector3& rpos) const - { - if(impulse.m_asVelocity) applyVImpulse(impulse.m_velocity,rpos); - if(impulse.m_asDrift) applyDImpulse(impulse.m_drift,rpos); - } - void applyVAImpulse(const btVector3& impulse) const - { - if(m_rigid) m_rigid->applyTorqueImpulse(impulse); - if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); - } - void applyDAImpulse(const btVector3& impulse) const - { - if(m_rigid) m_rigid->applyTorqueImpulse(impulse); - if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); - } - void applyAImpulse(const Impulse& impulse) const - { - if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); - if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); - } - void applyDCImpulse(const btVector3& impulse) const - { - if(m_rigid) m_rigid->applyCentralImpulse(impulse); - if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); - } - }; - /* Joint */ - struct Joint - { - struct eType { enum _ { - Linear, - Angular, - Contact, - };}; - struct Specs - { - Specs() : erp(1),cfm(1),split(1) {} - btScalar erp; - btScalar cfm; - btScalar split; - }; - Body m_bodies[2]; - btVector3 m_refs[2]; - btScalar m_cfm; - btScalar m_erp; - btScalar m_split; - btVector3 m_drift; - btVector3 m_sdrift; - btMatrix3x3 m_massmatrix; - bool m_delete; - virtual ~Joint() {} - Joint() : m_delete(false) {} - virtual void Prepare(btScalar dt,int iterations); - virtual void Solve(btScalar dt,btScalar sor)=0; - virtual void Terminate(btScalar dt)=0; - virtual eType::_ Type() const=0; - }; - /* LJoint */ - struct LJoint : Joint - { - struct Specs : Joint::Specs - { - btVector3 position; - }; - btVector3 m_rpos[2]; - void Prepare(btScalar dt,int iterations); - void Solve(btScalar dt,btScalar sor); - void Terminate(btScalar dt); - eType::_ Type() const { return(eType::Linear); } - }; - /* AJoint */ - struct AJoint : Joint - { - struct IControl - { - virtual void Prepare(AJoint*) {} - virtual btScalar Speed(AJoint*,btScalar current) { return(current); } - static IControl* Default() { static IControl def;return(&def); } - }; - struct Specs : Joint::Specs - { - Specs() : icontrol(IControl::Default()) {} - btVector3 axis; - IControl* icontrol; - }; - btVector3 m_axis[2]; - IControl* m_icontrol; - void Prepare(btScalar dt,int iterations); - void Solve(btScalar dt,btScalar sor); - void Terminate(btScalar dt); - eType::_ Type() const { return(eType::Angular); } - }; - /* CJoint */ - struct CJoint : Joint - { - int m_life; - int m_maxlife; - btVector3 m_rpos[2]; - btVector3 m_normal; - btScalar m_friction; - void Prepare(btScalar dt,int iterations); - void Solve(btScalar dt,btScalar sor); - void Terminate(btScalar dt); - eType::_ Type() const { return(eType::Contact); } - }; - /* Config */ - struct Config - { - eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) - btScalar kVCF; // Velocities correction factor (Baumgarte) - btScalar kDP; // Damping coefficient [0,1] - btScalar kDG; // Drag coefficient [0,+inf] - btScalar kLF; // Lift coefficient [0,+inf] - btScalar kPR; // Pressure coefficient [-inf,+inf] - btScalar kVC; // Volume conversation coefficient [0,+inf] - btScalar kDF; // Dynamic friction coefficient [0,1] - btScalar kMT; // Pose matching coefficient [0,1] - btScalar kCHR; // Rigid contacts hardness [0,1] - btScalar kKHR; // Kinetic contacts hardness [0,1] - btScalar kSHR; // Soft contacts hardness [0,1] - btScalar kAHR; // Anchors hardness [0,1] - btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) - btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only) - btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) - btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) - btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) - btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) - btScalar maxvolume; // Maximum volume ratio for pose - btScalar timescale; // Time scale - int viterations; // Velocities solver iterations - int piterations; // Positions solver iterations - int diterations; // Drift solver iterations - int citerations; // Cluster solver iterations - int collisions; // Collisions flags - tVSolverArray m_vsequence; // Velocity solvers sequence - tPSolverArray m_psequence; // Position solvers sequence - tPSolverArray m_dsequence; // Drift solvers sequence - }; - /* SolverState */ - struct SolverState - { - btScalar sdt; // dt*timescale - btScalar isdt; // 1/sdt - btScalar velmrg; // velocity margin - btScalar radmrg; // radial margin - btScalar updmrg; // Update margin - }; - /* RayCaster */ - struct RayCaster : btDbvt::ICollide - { - btVector3 o; - btVector3 d; - btScalar mint; - Face* face; - int tests; - RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt); - void Process(const btDbvtNode* leaf); - static inline btScalar rayTriangle(const btVector3& org, - const btVector3& dir, - const btVector3& a, - const btVector3& b, - const btVector3& c, - btScalar maxt=SIMD_INFINITY); - }; - - // - // Typedef's - // - - typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); - typedef void (*vsolver_t)(btSoftBody*,btScalar); - typedef btAlignedObjectArray tClusterArray; - typedef btAlignedObjectArray tNoteArray; - typedef btAlignedObjectArray tNodeArray; - typedef btAlignedObjectArray tLeafArray; - typedef btAlignedObjectArray tLinkArray; - typedef btAlignedObjectArray tFaceArray; - typedef btAlignedObjectArray tAnchorArray; - typedef btAlignedObjectArray tRContactArray; - typedef btAlignedObjectArray tSContactArray; - typedef btAlignedObjectArray tMaterialArray; - typedef btAlignedObjectArray tJointArray; - typedef btAlignedObjectArray tSoftBodyArray; - - // - // Fields - // - - Config m_cfg; // Configuration - SolverState m_sst; // Solver state - Pose m_pose; // Pose - void* m_tag; // User data - btSoftBodyWorldInfo* m_worldInfo; // World info - tNoteArray m_notes; // Notes - tNodeArray m_nodes; // Nodes - tLinkArray m_links; // Links - tFaceArray m_faces; // Faces - tAnchorArray m_anchors; // Anchors - tRContactArray m_rcontacts; // Rigid contacts - tSContactArray m_scontacts; // Soft contacts - tJointArray m_joints; // Joints - tMaterialArray m_materials; // Materials - btScalar m_timeacc; // Time accumulator - btVector3 m_bounds[2]; // Spatial bounds - bool m_bUpdateRtCst; // Update runtime constants - btDbvt m_ndbvt; // Nodes tree - btDbvt m_fdbvt; // Faces tree - btDbvt m_cdbvt; // Clusters tree - tClusterArray m_clusters; // Clusters - - // - // Api - // - - /* ctor */ - btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, - const btVector3* x, - const btScalar* m); - /* dtor */ - virtual ~btSoftBody(); - /* Check for existing link */ - bool checkLink( int node0, - int node1) const; - bool checkLink( const Node* node0, - const Node* node1) const; - /* Check for existring face */ - bool checkFace( int node0, - int node1, - int node2) const; - /* Append material */ - Material* appendMaterial(); - /* Append note */ - void appendNote( const char* text, - const btVector3& o, - const btVector4& c=btVector4(1,0,0,0), - Node* n0=0, - Node* n1=0, - Node* n2=0, - Node* n3=0); - void appendNote( const char* text, - const btVector3& o, - Node* feature); - void appendNote( const char* text, - const btVector3& o, - Link* feature); - void appendNote( const char* text, - const btVector3& o, - Face* feature); - /* Append node */ - void appendNode( const btVector3& x,btScalar m); - /* Append link */ - void appendLink(int model=-1,Material* mat=0); - void appendLink( int node0, - int node1, - Material* mat=0, - bool bcheckexist=false); - void appendLink( Node* node0, - Node* node1, - Material* mat=0, - bool bcheckexist=false); - /* Append face */ - void appendFace(int model=-1,Material* mat=0); - void appendFace( int node0, - int node1, - int node2, - Material* mat=0); - /* Append anchor */ - void appendAnchor( int node, - btRigidBody* body); - /* Append linear joint */ - void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); - void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); - void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); - /* Append linear joint */ - void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); - void appendAngularJoint(const AJoint::Specs& specs,Body body=Body()); - void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); - /* Add force (or gravity) to the entire body */ - void addForce( const btVector3& force); - /* Add force (or gravity) to a node of the body */ - void addForce( const btVector3& force, - int node); - /* Add velocity to the entire body */ - void addVelocity( const btVector3& velocity); - /* Add velocity to a node of the body */ - void addVelocity( const btVector3& velocity, - int node); - /* Set mass */ - void setMass( int node, - btScalar mass); - /* Get mass */ - btScalar getMass( int node) const; - /* Get total mass */ - btScalar getTotalMass() const; - /* Set total mass (weighted by previous masses) */ - void setTotalMass( btScalar mass, - bool fromfaces=false); - /* Set total density */ - void setTotalDensity(btScalar density); - /* Transform */ - void transform( const btTransform& trs); - /* Translate */ - void translate( const btVector3& trs); - /* Rotate */ - void rotate( const btQuaternion& rot); - /* Scale */ - void scale( const btVector3& scl); - /* Set current state as pose */ - void setPose( bool bvolume, - bool bframe); - /* Return the volume */ - btScalar getVolume() const; - /* Cluster count */ - int clusterCount() const; - /* Cluster center of mass */ - static btVector3 clusterCom(const Cluster* cluster); - btVector3 clusterCom(int cluster) const; - /* Cluster velocity at rpos */ - static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); - /* Cluster impulse */ - static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); - static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); - static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); - static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); - static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); - static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); - static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); - /* Generate bending constraints based on distance in the adjency graph */ - int generateBendingConstraints( int distance, - Material* mat=0); - /* Randomize constraints to reduce solver bias */ - void randomizeConstraints(); - /* Generate clusters (K-mean) */ - int generateClusters(int k,int maxiterations=8192); - /* Refine */ - void refine(ImplicitFn* ifn,btScalar accurary,bool cut); - /* CutLink */ - bool cutLink(int node0,int node1,btScalar position); - bool cutLink(const Node* node0,const Node* node1,btScalar position); - /* Ray casting */ - bool rayCast(const btVector3& org, - const btVector3& dir, - sRayCast& results, - btScalar maxtime=SIMD_INFINITY); - /* Solver presets */ - void setSolver(eSolverPresets::_ preset); - /* predictMotion */ - void predictMotion(btScalar dt); - /* solveConstraints */ - void solveConstraints(); - /* staticSolve */ - void staticSolve(int iterations); - /* solveCommonConstraints */ - static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); - /* solveClusters */ - static void solveClusters(const btAlignedObjectArray& bodies); - /* integrateMotion */ - void integrateMotion(); - /* defaultCollisionHandlers */ - void defaultCollisionHandler(btCollisionObject* pco); - void defaultCollisionHandler(btSoftBody* psb); - - // - // Cast - // - - static const btSoftBody* upcast(const btCollisionObject* colObj) - { - if (colObj->getInternalType()==CO_SOFT_BODY) - return (const btSoftBody*)colObj; - return 0; - } - static btSoftBody* upcast(btCollisionObject* colObj) - { - if (colObj->getInternalType()==CO_SOFT_BODY) - return (btSoftBody*)colObj; - return 0; - } - - // - // ::btCollisionObject - // - - virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const - { - aabbMin = m_bounds[0]; - aabbMax = m_bounds[1]; - } - // - // Private - // - void pointersToIndices(); - void indicesToPointers(const int* map=0); - int rayCast(const btVector3& org,const btVector3& dir, - btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; - void initializeFaceTree(); - btVector3 evaluateCom() const; - bool checkContact(btRigidBody* prb,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; - void updateNormals(); - void updateBounds(); - void updatePose(); - void updateConstants(); - void initializeClusters(); - void updateClusters(); - void cleanupClusters(); - void prepareClusters(int iterations); - void solveClusters(btScalar sor); - void applyClusters(bool drift); - void dampClusters(); - void applyForces(); - static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); - static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti); - static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti); - static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); - static void VSolve_Links(btSoftBody* psb,btScalar kst); - static psolver_t getSolver(ePSolver::_ solver); - static vsolver_t getSolver(eVSolver::_ solver); - -}; - - - -#endif //_BT_SOFT_BODY_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp deleted file mode 100644 index 5e3211ed73b..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btSoftBodyConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionShapes/btConcaveShape.h" -#include "BulletCollision/CollisionDispatch/btManifoldResult.h" -#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" -#include "BulletCollision/CollisionShapes/btTriangleShape.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" -#include "BulletCollision/CollisionShapes/btConvexHullShape.h" - - - -#include "LinearMath/btIDebugDraw.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletSoftBody/btSoftBody.h" - -#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.3) - -btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -: btCollisionAlgorithm(ci), -m_isSwapped(isSwapped), -m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) -{ -} - - - -btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() -{ -} - - - -btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): - m_dispatcher(dispatcher), - m_dispatchInfoPtr(0) -{ - m_softBody = (btSoftBody*) (isSwapped? body1:body0); - m_triBody = isSwapped? body0:body1; - - // - // create the manifold from the dispatcher 'manifold pool' - // -// m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); - - clearCache(); -} - -btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() -{ - clearCache(); -// m_dispatcher->releaseManifold( m_manifoldPtr ); - -} - - -void btSoftBodyTriangleCallback::clearCache() -{ - //m_dispatcher->clearManifold(m_manifoldPtr); -}; - - -static const int maxParts = 1; -static const int maxTriangleIndex = 100*100; - -btCollisionShape* shapeCache[maxParts][maxTriangleIndex]; - - -void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) -{ - static bool hackedFirst = true; - if (hackedFirst) - { - hackedFirst = false; - int i,j; - for (i=0;i(m_triBody); - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher1 = m_dispatcher; - - ///debug drawing of the overlapping triangles - if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) - { - btVector3 color(255,255,0); - btTransform& tr = ob->getWorldTransform(); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); - m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); - - //btVector3 center = triangle[0] + triangle[1]+triangle[2]; - //center *= btScalar(0.333333); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); - //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); - - } - - if (shapeCache[partId][triangleIndex]) - { - btCollisionShape* tm = shapeCache[partId][triangleIndex]; - - //copy over user pointers to temporary shape - tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); - - btCollisionShape* tmpShape = ob->getCollisionShape(); - ob->internalSetTemporaryCollisionShape( tm ); - - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); - - colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->~btCollisionAlgorithm(); - ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); - ob->internalSetTemporaryCollisionShape( tmpShape); - return; - } - - //aabb filter is already applied! - - - - - - - - - //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); - -// if (m_softBody->getCollisionShape()->getShapeType()== - { -// btVector3 other; - btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); - normal.normalize(); - normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; -// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; -// other+=normal*22.f; - btVector3 pts[6] = {triangle[0]+normal, - triangle[1]+normal, - triangle[2]+normal, - triangle[0]-normal, - triangle[1]-normal, - triangle[2]-normal}; - - btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6); - - -// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); - - //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); - // tm.setMargin(m_collisionMarginTriangle); - - //copy over user pointers to temporary shape - tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); - - btCollisionShape* tmpShape = ob->getCollisionShape(); - ob->internalSetTemporaryCollisionShape( tm ); - - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); - ///this should use the btDispatcher, so the actual registered algorithm is used - // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); - - //m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex); - // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); -// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - colAlgo->~btCollisionAlgorithm(); - ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); - ob->internalSetTemporaryCollisionShape( tmpShape ); -// delete tm; - - shapeCache[partId][triangleIndex] = tm; - - } - - - -} - - - -void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - m_dispatchInfoPtr = &dispatchInfo; - m_collisionMarginTriangle = collisionMarginTriangle; - m_resultOut = resultOut; - - //recalc aabbs -// btTransform softbodyInTriangleSpace; -// softbodyInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_softBody->getWorldTransform(); -// btCollisionShape* convexShape = static_cast(m_convexBody->getCollisionShape()); - //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); - btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; - m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); - - btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); - btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5); - - btTransform triInverse = m_triBody->getWorldTransform().inverse(); - - btMatrix3x3 abs_b = triInverse.getBasis().absolute(); - btPoint3 center = softBodyCenter + triInverse.getOrigin(); - - btVector3 extent = btVector3(abs_b[0].dot(halfExtents), - abs_b[1].dot(halfExtents), - abs_b[2].dot(halfExtents)); -// extent += btVector3(getMargin(),getMargin(),getMargin()); - - m_aabbMin = center - extent; - m_aabbMax = center + extent; - - btScalar extraMargin = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); - btVector3 extra(extraMargin,extraMargin,extraMargin); - - m_aabbMax += extra; - m_aabbMin -= extra; - -/* btVector3 extra(2,2,2); - m_aabbMin = aabbWorldSpaceMin-extra; - m_aabbMax = aabbWorldSpaceMax+extra; -*/ - -} - -void btSoftBodyConcaveCollisionAlgorithm::clearCache() -{ - m_btSoftBodyTriangleCallback.clearCache(); - -} - -void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - - - btCollisionObject* convexBody = m_isSwapped ? body1 : body0; - btCollisionObject* triBody = m_isSwapped ? body0 : body1; - - if (triBody->getCollisionShape()->isConcave()) - { - - - btCollisionObject* triOb = triBody; - btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); - - // if (convexBody->getCollisionShape()->isConvex()) - { - btScalar collisionMarginTriangle = concaveShape->getMargin(); - -// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); - m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); - - //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. - //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); - -// m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); - - - concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); - - // resultOut->refreshContactPoints(); - - } - - } - -} - - -btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - btCollisionObject* convexbody = m_isSwapped ? body1 : body0; - btCollisionObject* triBody = m_isSwapped ? body0 : body1; - - - //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) - - //only perform CCD above a certain threshold, this prevents blocking on the long run - //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... - btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); - if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) - { - return btScalar(1.); - } - - //const btVector3& from = convexbody->m_worldTransform.getOrigin(); - //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); - //todo: only do if the motion exceeds the 'radius' - - btTransform triInv = triBody->getWorldTransform().inverse(); - btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); - btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); - - struct LocalTriangleSphereCastCallback : public btTriangleCallback - { - btTransform m_ccdSphereFromTrans; - btTransform m_ccdSphereToTrans; - btTransform m_meshTransform; - - btScalar m_ccdSphereRadius; - btScalar m_hitFraction; - - - LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) - :m_ccdSphereFromTrans(from), - m_ccdSphereToTrans(to), - m_ccdSphereRadius(ccdSphereRadius), - m_hitFraction(hitFraction) - { - } - - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) - { - (void)partId; - (void)triangleIndex; - //do a swept sphere for now - btTransform ident; - ident.setIdentity(); - btConvexCast::CastResult castResult; - castResult.m_fraction = m_hitFraction; - btSphereShape pointShape(m_ccdSphereRadius); - btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); - btVoronoiSimplexSolver simplexSolver; - btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); - //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); - //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); - //local space? - - if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, - ident,ident,castResult)) - { - if (m_hitFraction > castResult.m_fraction) - m_hitFraction = castResult.m_fraction; - } - - } - - }; - - - - - - if (triBody->getCollisionShape()->isConcave()) - { - btVector3 rayAabbMin = convexFromLocal.getOrigin(); - rayAabbMin.setMin(convexToLocal.getOrigin()); - btVector3 rayAabbMax = convexFromLocal.getOrigin(); - rayAabbMax.setMax(convexToLocal.getOrigin()); - btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); - rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); - rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); - - btScalar curHitFraction = btScalar(1.); //is this available? - LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, - convexbody->getCcdSweptSphereRadius(),curHitFraction); - - raycastCallback.m_hitFraction = convexbody->getHitFraction(); - - btCollisionObject* concavebody = triBody; - - btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); - - if (triangleMesh) - { - triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); - } - - - - if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) - { - convexbody->setHitFraction( raycastCallback.m_hitFraction); - return raycastCallback.m_hitFraction; - } - } - - return btScalar(1.); - -} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h deleted file mode 100644 index adb91329a4c..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H -#define SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionShapes/btTriangleCallback.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -class btDispatcher; -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btSoftBody; - -///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called. -class btSoftBodyTriangleCallback : public btTriangleCallback -{ - btSoftBody* m_softBody; - btCollisionObject* m_triBody; - - btVector3 m_aabbMin; - btVector3 m_aabbMax ; - - btManifoldResult* m_resultOut; - - btDispatcher* m_dispatcher; - const btDispatcherInfo* m_dispatchInfoPtr; - btScalar m_collisionMarginTriangle; - -public: -int m_triangleCount; - -// btPersistentManifold* m_manifoldPtr; - - btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); - - void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual ~btSoftBodyTriangleCallback(); - - virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); - - void clearCache(); - - SIMD_FORCE_INLINE const btVector3& getAabbMin() const - { - return m_aabbMin; - } - SIMD_FORCE_INLINE const btVector3& getAabbMax() const - { - return m_aabbMax; - } - -}; - - - - -/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes. -class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm -{ - - bool m_isSwapped; - - btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback; - -public: - - btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); - - virtual ~btSoftBodyConcaveCollisionAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - //we don't add any manifolds - } - - void clearCache(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); - return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false); - } - }; - - struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); - return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true); - } - }; - -}; - -#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp deleted file mode 100644 index d9919967233..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ /dev/null @@ -1,653 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBodyHelpers.cpp by Nathanael Presson - -#include "btSoftBodyInternals.h" -#include -#include -#include "btSoftBodyHelpers.h" -#include "LinearMath/btConvexHull.h" - -// -static void drawVertex( btIDebugDraw* idraw, - const btVector3& x,btScalar s,const btVector3& c) - { - idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); - idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); - idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); - } - -// -static void drawBox( btIDebugDraw* idraw, - const btVector3& mins, - const btVector3& maxs, - const btVector3& color) -{ -const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), - btVector3(maxs.x(),mins.y(),mins.z()), - btVector3(maxs.x(),maxs.y(),mins.z()), - btVector3(mins.x(),maxs.y(),mins.z()), - btVector3(mins.x(),mins.y(),maxs.z()), - btVector3(maxs.x(),mins.y(),maxs.z()), - btVector3(maxs.x(),maxs.y(),maxs.z()), - btVector3(mins.x(),maxs.y(),maxs.z())}; -idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); -idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); -idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); -idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); -idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); -idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); -} - -// -static void drawTree( btIDebugDraw* idraw, - const btDbvtNode* node, - int depth, - const btVector3& ncolor, - const btVector3& lcolor, - int mindepth, - int maxdepth) -{ -if(node) - { - if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); - drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); - } - if(depth>=mindepth) - { - const btScalar scl=(btScalar)(node->isinternal()?1:1); - const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; - const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; - drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); - } - } -} - -// -template -static inline T sum(const btAlignedObjectArray& items) -{ -T v; -if(items.size()) - { - v=items[0]; - for(int i=1,ni=items.size();i -static inline void add(btAlignedObjectArray& items,const Q& value) -{ -for(int i=0,ni=items.size();i -static inline void mul(btAlignedObjectArray& items,const Q& value) -{ -for(int i=0,ni=items.size();i -static inline T average(const btAlignedObjectArray& items) -{ -const btScalar n=(btScalar)(items.size()>0?items.size():1); -return(sum(items)/n); -} - -// -static inline btScalar tetravolume(const btVector3& x0, - const btVector3& x1, - const btVector3& x2, - const btVector3& x3) -{ - const btVector3 a=x1-x0; - const btVector3 b=x2-x0; - const btVector3 c=x3-x0; - return(dot(a,cross(b,c))); -} - -// -#if 0 -static btVector3 stresscolor(btScalar stress) - { - static const btVector3 spectrum[]= { btVector3(1,0,1), - btVector3(0,0,1), - btVector3(0,1,1), - btVector3(0,1,0), - btVector3(1,1,0), - btVector3(1,0,0), - btVector3(1,0,0)}; - static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; - static const btScalar one=1; - stress=btMax(0,btMin(1,stress))*ncolors; - const int sel=(int)stress; - const btScalar frc=stress-sel; - return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); - } -#endif - -// -void btSoftBodyHelpers::Draw( btSoftBody* psb, - btIDebugDraw* idraw, - int drawflags) -{ - const btScalar scl=(btScalar)0.1; - const btScalar nscl=scl*5; - const btVector3 lcolor=btVector3(0,0,0); - const btVector3 ncolor=btVector3(1,1,1); - const btVector3 ccolor=btVector3(1,0,0); - int i,j,nj; - - /* Nodes */ - if(0!=(drawflags&fDrawFlags::Nodes)) - { - for(i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); - idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); - idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); - } - } - /* Links */ - if(0!=(drawflags&fDrawFlags::Links)) - { - for(i=0;im_links.size();++i) - { - const btSoftBody::Link& l=psb->m_links[i]; - if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); - } - } - /* Normals */ - if(0!=(drawflags&fDrawFlags::Normals)) - { - for(i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 d=n.m_n*nscl; - idraw->drawLine(n.m_x,n.m_x+d,ncolor); - idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); - } - } - /* Contacts */ - if(0!=(drawflags&fDrawFlags::Contacts)) - { - static const btVector3 axis[]={btVector3(1,0,0), - btVector3(0,1,0), - btVector3(0,0,1)}; - for(i=0;im_rcontacts.size();++i) - { - const btSoftBody::RContact& c=psb->m_rcontacts[i]; - const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* - (dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); - const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); - const btVector3 y=cross(x,c.m_cti.m_normal).normalized(); - idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); - idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); - idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); - } - } - /* Anchors */ - if(0!=(drawflags&fDrawFlags::Anchors)) - { - for(i=0;im_anchors.size();++i) - { - const btSoftBody::Anchor& a=psb->m_anchors[i]; - const btVector3 q=a.m_body->getWorldTransform()*a.m_local; - drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); - drawVertex(idraw,q,0.25,btVector3(0,1,0)); - idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); - } - for(i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - if(n.m_im<=0) - { - drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); - } - } - } - /* Faces */ - if(0!=(drawflags&fDrawFlags::Faces)) - { - const btScalar scl=(btScalar)0.8; - const btScalar alp=(btScalar)1; - const btVector3 col(0,(btScalar)0.7,0); - for(i=0;im_faces.size();++i) - { - const btSoftBody::Face& f=psb->m_faces[i]; - if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; - const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; - const btVector3 c=(x[0]+x[1]+x[2])/3; - idraw->drawTriangle((x[0]-c)*scl+c, - (x[1]-c)*scl+c, - (x[2]-c)*scl+c, - col,alp); - } - } - /* Clusters */ - if(0!=(drawflags&fDrawFlags::Clusters)) - { - srand(1806); - for(i=0;im_clusters.size();++i) - { - if(psb->m_clusters[i]->m_collide) - { - btVector3 color( rand()/(btScalar)RAND_MAX, - rand()/(btScalar)RAND_MAX, - rand()/(btScalar)RAND_MAX); - color=color.normalized()*0.75; - btAlignedObjectArray vertices; - vertices.resize(psb->m_clusters[i]->m_nodes.size()); - for(j=0,nj=vertices.size();jm_clusters[i]->m_nodes[j]->m_x; - } - HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); - HullResult hres; - HullLibrary hlib; - hdsc.mMaxVertices=vertices.size(); - hlib.CreateConvexHull(hdsc,hres); - const btVector3 center=average(hres.m_OutputVertices); - add(hres.m_OutputVertices,-center); - mul(hres.m_OutputVertices,(btScalar)1); - add(hres.m_OutputVertices,center); - for(j=0;j<(int)hres.mNumFaces;++j) - { - const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]}; - idraw->drawTriangle(hres.m_OutputVertices[idx[0]], - hres.m_OutputVertices[idx[1]], - hres.m_OutputVertices[idx[2]], - color,1); - } - hlib.ReleaseResult(hres); - } - /* Velocities */ - #if 0 - for(int j=0;jm_clusters[i].m_nodes.size();++j) - { - const btSoftBody::Cluster& c=psb->m_clusters[i]; - const btVector3 r=c.m_nodes[j]->m_x-c.m_com; - const btVector3 v=c.m_lv+cross(c.m_av,r); - idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0)); - } - #endif - /* Frame */ - btSoftBody::Cluster& c=*psb->m_clusters[i]; - idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0)); - idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0)); - idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1)); - } - } - /* Notes */ - if(0!=(drawflags&fDrawFlags::Notes)) - { - for(i=0;im_notes.size();++i) - { - const btSoftBody::Note& n=psb->m_notes[i]; - btVector3 p=n.m_offset; - for(int j=0;jm_x*n.m_coords[j]; - } - idraw->draw3dText(p,n.m_text); - } - } - /* Node tree */ - if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw); - /* Face tree */ - if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw); - /* Cluster tree */ - if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw); - /* Joints */ - if(0!=(drawflags&fDrawFlags::Joints)) - { - for(i=0;im_joints.size();++i) - { - const btSoftBody::Joint* pj=psb->m_joints[i]; - switch(pj->Type()) - { - case btSoftBody::Joint::eType::Linear: - { - const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj; - const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0]; - const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1]; - idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0)); - idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1)); - drawVertex(idraw,a0,0.25,btVector3(1,1,0)); - drawVertex(idraw,a1,0.25,btVector3(0,1,1)); - } - break; - case btSoftBody::Joint::eType::Angular: - { - const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj; - const btVector3 o0=pj->m_bodies[0].xform().getOrigin(); - const btVector3 o1=pj->m_bodies[1].xform().getOrigin(); - const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0]; - const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1]; - idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0)); - idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0)); - idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1)); - idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1)); - } - } - } - } -} - -// -void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool /*stress*/) -{ - for(int i=0;im_nodes.size();++i) - { - const btSoftBody::Node& n=psb->m_nodes[i]; - char text[2048]={0}; - char buff[1024]; - if(masses) - { - sprintf(buff," M(%.2f)",1/n.m_im); - strcat(text,buff); - } - if(areas) - { - sprintf(buff," A(%.2f)",n.m_area); - strcat(text,buff); - } - if(text[0]) idraw->draw3dText(n.m_x,text); - } -} - -// -void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ -drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ -drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth, - int maxdepth) -{ -drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth); -} - -// -void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, - btIDebugDraw* idraw) -{ - if(psb->m_pose.m_bframe) - { - static const btScalar ascl=10; - static const btScalar nscl=(btScalar)0.1; - const btVector3 com=psb->m_pose.m_com; - const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; - const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); - const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); - const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); - idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); - idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); - idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); - for(int i=0;im_pose.m_pos.size();++i) - { - const btVector3 x=com+trs*psb->m_pose.m_pos[i]; - drawVertex(idraw,x,nscl,btVector3(1,0,1)); - } - } -} - -// -btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, - const btVector3& to, - int res, - int fixeds) -{ - /* Create nodes */ - const int r=res+2; - btVector3* x=new btVector3[r]; - btScalar* m=new btScalar[r]; - int i; - - for(i=0;isetMass(0,0); - if(fixeds&2) psb->setMass(r-1,0); - delete[] x; - delete[] m; - /* Create links */ - for(i=1;iappendLink(i-1,i); - } - /* Finished */ - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags) -{ -#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) - /* Create nodes */ - if((resx<2)||(resy<2)) return(0); - const int rx=resx; - const int ry=resy; - const int tot=rx*ry; - btVector3* x=new btVector3[tot]; - btScalar* m=new btScalar[tot]; - int iy; - - for(iy=0;iysetMass(IDX(0,0),0); - if(fixeds&2) psb->setMass(IDX(rx-1,0),0); - if(fixeds&4) psb->setMass(IDX(0,ry-1),0); - if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); - delete[] x; - delete[] m; - /* Create links and faces */ - for(iy=0;iyappendLink(idx,IDX(ix+1,iy)); - if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); - if(mdx&&mdy) - { - if((ix+iy)&1) - { - psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); - psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); - if(gendiags) - { - psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); - } - } - else - { - psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); - psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); - if(gendiags) - { - psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); - } - } - } - } - } - /* Finished */ -#undef IDX - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, - const btVector3& radius, - int res) -{ - struct Hammersley - { - static void Generate(btVector3* x,int n) - { - for(int i=0;i>=1) if(j&1) t+=p; - btScalar w=2*t-1; - btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; - btScalar s=btSqrt(1-w*w); - *x++=btVector3(s*btCos(a),s*btSin(a),w); - } - } - }; - btAlignedObjectArray vtx; - vtx.resize(3+res); - Hammersley::Generate(&vtx[0],vtx.size()); - for(int i=0;i chks; - btAlignedObjectArray vtx; - chks.resize(maxidx*maxidx,false); - vtx.resize(maxidx); - for(i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); - } - } -#undef IDX - psb->appendFace(idx[0],idx[1],idx[2]); - } - psb->randomizeConstraints(); - return(psb); -} - -// -btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, - int nvertices) -{ - HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); - HullResult hres; - HullLibrary hlib;/*??*/ - hdsc.mMaxVertices=nvertices; - hlib.CreateConvexHull(hdsc,hres); - btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, - &hres.m_OutputVertices[0],0); - for(int i=0;i<(int)hres.mNumFaces;++i) - { - const int idx[]={ hres.m_Indices[i*3+0], - hres.m_Indices[i*3+1], - hres.m_Indices[i*3+2]}; - if(idx[0]appendLink( idx[0],idx[1]); - if(idx[1]appendLink( idx[1],idx[2]); - if(idx[2]appendLink( idx[2],idx[0]); - psb->appendFace(idx[0],idx[1],idx[2]); - } - hlib.ReleaseResult(hres); - psb->randomizeConstraints(); - return(psb); -} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h deleted file mode 100644 index e9c6cb20657..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SOFT_BODY_HELPERS_H -#define SOFT_BODY_HELPERS_H - -#include "btSoftBody.h" - -// -// Helpers -// - -/* fDrawFlags */ -struct fDrawFlags { enum _ { - Nodes = 0x0001, - Links = 0x0002, - Faces = 0x0004, - Tetras = 0x0008, - Normals = 0x0010, - Contacts = 0x0020, - Anchors = 0x0040, - Notes = 0x0080, - Clusters = 0x0100, - NodeTree = 0x0200, - FaceTree = 0x0400, - ClusterTree = 0x0800, - Joints = 0x1000, - /* presets */ - Std = Links+Faces+Tetras+Anchors+Notes+Joints, - StdTetra = Std-Faces+Tetras, -};}; - -struct btSoftBodyHelpers -{ - /* Draw body */ - static void Draw( btSoftBody* psb, - btIDebugDraw* idraw, - int drawflags=fDrawFlags::Std); - /* Draw body infos */ - static void DrawInfos( btSoftBody* psb, - btIDebugDraw* idraw, - bool masses, - bool areas, - bool stress); - /* Draw node tree */ - static void DrawNodeTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); - /* Draw face tree */ - static void DrawFaceTree( btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); - /* Draw cluster tree */ - static void DrawClusterTree(btSoftBody* psb, - btIDebugDraw* idraw, - int mindepth=0, - int maxdepth=-1); - /* Draw rigid frame */ - static void DrawFrame( btSoftBody* psb, - btIDebugDraw* idraw); - /* Create a rope */ - static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, - const btVector3& from, - const btVector3& to, - int res, - int fixeds); - /* Create a patch */ - static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo, - const btVector3& corner00, - const btVector3& corner10, - const btVector3& corner01, - const btVector3& corner11, - int resx, - int resy, - int fixeds, - bool gendiags); - /* Create an ellipsoid */ - static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, - const btVector3& center, - const btVector3& radius, - int res); - /* Create from trimesh */ - static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, - const btScalar* vertices, - const int* triangles, - int ntriangles); - /* Create from convex-hull */ - static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, - const btVector3* vertices, - int nvertices); -}; - -#endif //SOFT_BODY_HELPERS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h deleted file mode 100644 index 1a7be2cb840..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h +++ /dev/null @@ -1,896 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSoftBody implementation by Nathanael Presson - -#ifndef _BT_SOFT_BODY_INTERNALS_H -#define _BT_SOFT_BODY_INTERNALS_H - -#include "btSoftBody.h" - -#include "LinearMath/btQuickprof.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" - -// -// btSymMatrix -// -template -struct btSymMatrix -{ - btSymMatrix() : dim(0) {} - btSymMatrix(int n,const T& init=T()) { resize(n,init); } -void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); } -int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r store; -int dim; -}; - -// -// btSoftBodyCollisionShape -// -class btSoftBodyCollisionShape : public btConcaveShape -{ -public: - btSoftBody* m_body; - - btSoftBodyCollisionShape(btSoftBody* backptr) - { - m_body=backptr; - } - - virtual ~btSoftBodyCollisionShape() - { - - } - - void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const - { - //not yet - btAssert(0); - } - - ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - /* t should be identity, but better be safe than...fast? */ - const btVector3 mins=m_body->m_bounds[0]; - const btVector3 maxs=m_body->m_bounds[1]; - const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), - t*btVector3(maxs.x(),mins.y(),mins.z()), - t*btVector3(maxs.x(),maxs.y(),mins.z()), - t*btVector3(mins.x(),maxs.y(),mins.z()), - t*btVector3(mins.x(),mins.y(),maxs.z()), - t*btVector3(maxs.x(),mins.y(),maxs.z()), - t*btVector3(maxs.x(),maxs.y(),maxs.z()), - t*btVector3(mins.x(),maxs.y(),maxs.z())}; - aabbMin=aabbMax=crns[0]; - for(int i=1;i<8;++i) - { - aabbMin.setMin(crns[i]); - aabbMax.setMax(crns[i]); - } - } - - virtual int getShapeType() const - { - return SOFTBODY_SHAPE_PROXYTYPE; - } - virtual void setLocalScaling(const btVector3& /*scaling*/) - { - ///na - btAssert(0); - } - virtual const btVector3& getLocalScaling() const - { - static const btVector3 dummy(1,1,1); - return dummy; - } - virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const - { - ///not yet - btAssert(0); - } - virtual const char* getName()const - { - return "SoftBody"; - } - -}; - -// -// btSoftClusterCollisionShape -// -class btSoftClusterCollisionShape : public btConvexInternalShape -{ -public: - const btSoftBody::Cluster* m_cluster; - - btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); } - - - virtual btVector3 localGetSupportingVertex(const btVector3& vec) const - { - btSoftBody::Node* const * n=&m_cluster->m_nodes[0]; - btScalar d=dot(vec,n[0]->m_x); - int j=0; - for(int i=1,ni=m_cluster->m_nodes.size();im_x); - if(k>d) { d=k;j=i; } - } - return(n[j]->m_x); - } - virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const - { - return(localGetSupportingVertex(vec)); - } - //notice that the vectors should be unit length - virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const - {} - - - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const - {} - - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - {} - - virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } - - //debugging - virtual const char* getName()const {return "SOFTCLUSTER";} - - virtual void setMargin(btScalar margin) - { - btConvexInternalShape::setMargin(margin); - } - virtual btScalar getMargin() const - { - return getMargin(); - } -}; - -// -// Inline's -// - -// -template -static inline void ZeroInitialize(T& value) -{ -static const T zerodummy; -value=zerodummy; -} -// -template -static inline bool CompLess(const T& a,const T& b) -{ return(a -static inline bool CompGreater(const T& a,const T& b) -{ return(a>b); } -// -template -static inline T Lerp(const T& a,const T& b,btScalar t) -{ return(a+(b-a)*t); } -// -template -static inline T InvLerp(const T& a,const T& b,btScalar t) -{ return((b+a*t-b*t)/(a*b)); } -// -static inline btMatrix3x3 Lerp( const btMatrix3x3& a, - const btMatrix3x3& b, - btScalar t) -{ -btMatrix3x3 r; -r[0]=Lerp(a[0],b[0],t); -r[1]=Lerp(a[1],b[1],t); -r[2]=Lerp(a[2],b[2],t); -return(r); -} -// -static inline btVector3 Clamp(const btVector3& v,btScalar maxlength) -{ -const btScalar sql=v.length2(); -if(sql>(maxlength*maxlength)) - return((v*maxlength)/btSqrt(sql)); - else - return(v); -} -// -template -static inline T Clamp(const T& x,const T& l,const T& h) -{ return(xh?h:x); } -// -template -static inline T Sq(const T& x) -{ return(x*x); } -// -template -static inline T Cube(const T& x) -{ return(x*x*x); } -// -template -static inline T Sign(const T& x) -{ return((T)(x<0?-1:+1)); } -// -template -static inline bool SameSign(const T& x,const T& y) -{ return((x*y)>0); } -// -static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y) -{ -const btVector3 d=x-y; -return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); -} -// -static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) -{ - const btScalar xx=a.x()*a.x(); - const btScalar yy=a.y()*a.y(); - const btScalar zz=a.z()*a.z(); - const btScalar xy=a.x()*a.y(); - const btScalar yz=a.y()*a.z(); - const btScalar zx=a.z()*a.x(); - btMatrix3x3 m; - m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx); - m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz); - m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s); - return(m); -} -// -static inline btMatrix3x3 Cross(const btVector3& v) -{ - btMatrix3x3 m; - m[0]=btVector3(0,-v.z(),+v.y()); - m[1]=btVector3(+v.z(),0,-v.x()); - m[2]=btVector3(-v.y(),+v.x(),0); - return(m); -} -// -static inline btMatrix3x3 Diagonal(btScalar x) -{ - btMatrix3x3 m; - m[0]=btVector3(x,0,0); - m[1]=btVector3(0,x,0); - m[2]=btVector3(0,0,x); - return(m); -} -// -static inline btMatrix3x3 Add(const btMatrix3x3& a, - const btMatrix3x3& b) -{ - btMatrix3x3 r; - for(int i=0;i<3;++i) r[i]=a[i]+b[i]; - return(r); -} -// -static inline btMatrix3x3 Sub(const btMatrix3x3& a, - const btMatrix3x3& b) -{ - btMatrix3x3 r; - for(int i=0;i<3;++i) r[i]=a[i]-b[i]; - return(r); -} -// -static inline btMatrix3x3 Mul(const btMatrix3x3& a, - btScalar b) -{ - btMatrix3x3 r; - for(int i=0;i<3;++i) r[i]=a[i]*b; - return(r); -} -// -static inline void Orthogonalize(btMatrix3x3& m) -{ -m[2]=cross(m[0],m[1]).normalized(); -m[1]=cross(m[2],m[0]).normalized(); -m[0]=cross(m[1],m[2]).normalized(); -} -// -static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r) -{ - const btMatrix3x3 cr=Cross(r); - return(Sub(Diagonal(im),cr*iwi*cr)); -} - -// -static inline btMatrix3x3 ImpulseMatrix( btScalar dt, - btScalar ima, - btScalar imb, - const btMatrix3x3& iwi, - const btVector3& r) -{ - return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse()); -} - -// -static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra, - btScalar imb,const btMatrix3x3& iib,const btVector3& rb) -{ -return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); -} - -// -static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, - const btMatrix3x3& iib) -{ -return(Add(iia,iib).inverse()); -} - -// -static inline btVector3 ProjectOnAxis( const btVector3& v, - const btVector3& a) -{ - return(a*dot(v,a)); -} -// -static inline btVector3 ProjectOnPlane( const btVector3& v, - const btVector3& a) -{ - return(v-ProjectOnAxis(v,a)); -} - -// -static inline void ProjectOrigin( const btVector3& a, - const btVector3& b, - btVector3& prj, - btScalar& sqd) -{ -const btVector3 d=b-a; -const btScalar m2=d.length2(); -if(m2>SIMD_EPSILON) - { - const btScalar t=Clamp(-dot(a,d)/m2,0,1); - const btVector3 p=a+d*t; - const btScalar l2=p.length2(); - if(l2SIMD_EPSILON) - { - const btVector3 n=q/btSqrt(m2); - const btScalar k=dot(a,n); - const btScalar k2=k*k; - if(k20)&& - (dot(cross(b-p,c-p),q)>0)&& - (dot(cross(c-p,a-p),q)>0)) - { - prj=p; - sqd=k2; - } - else - { - ProjectOrigin(a,b,prj,sqd); - ProjectOrigin(b,c,prj,sqd); - ProjectOrigin(c,a,prj,sqd); - } - } - } -} - -// -template -static inline T BaryEval( const T& a, - const T& b, - const T& c, - const btVector3& coord) -{ - return(a*coord.x()+b*coord.y()+c*coord.z()); -} -// -static inline btVector3 BaryCoord( const btVector3& a, - const btVector3& b, - const btVector3& c, - const btVector3& p) -{ -const btScalar w[]={ cross(a-p,b-p).length(), - cross(b-p,c-p).length(), - cross(c-p,a-p).length()}; -const btScalar isum=1/(w[0]+w[1]+w[2]); -return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum)); -} - -// -static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, - const btVector3& a, - const btVector3& b, - const btScalar accuracy, - const int maxiterations=256) -{ -btScalar span[2]={0,1}; -btScalar values[2]={fn->Eval(a),fn->Eval(b)}; -if(values[0]>values[1]) - { - btSwap(span[0],span[1]); - btSwap(values[0],values[1]); - } -if(values[0]>-accuracy) return(-1); -if(values[1]<+accuracy) return(-1); -for(int i=0;iEval(Lerp(a,b,t)); - if((t<=0)||(t>=1)) break; - if(btFabs(v)SIMD_EPSILON) - return(v/l); - else - return(btVector3(0,0,0)); -} - -// -static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f, - btScalar margin) -{ -const btVector3* pts[]={ &f.m_n[0]->m_x, - &f.m_n[1]->m_x, - &f.m_n[2]->m_x}; -btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3); -vol.Expand(btVector3(margin,margin,margin)); -return(vol); -} - -// -static inline btVector3 CenterOf( const btSoftBody::Face& f) -{ -return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3); -} - -// -static inline btScalar AreaOf( const btVector3& x0, - const btVector3& x1, - const btVector3& x2) -{ - const btVector3 a=x1-x0; - const btVector3 b=x2-x0; - const btVector3 cr=cross(a,b); - const btScalar area=cr.length(); - return(area); -} - -// -static inline btScalar VolumeOf( const btVector3& x0, - const btVector3& x1, - const btVector3& x2, - const btVector3& x3) -{ - const btVector3 a=x1-x0; - const btVector3 b=x2-x0; - const btVector3 c=x3-x0; - return(dot(a,cross(b,c))); -} - -// -static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, - const btVector3& x, - btSoftBody::sMedium& medium) -{ - medium.m_velocity = btVector3(0,0,0); - medium.m_pressure = 0; - medium.m_density = wfi->air_density; - if(wfi->water_density>0) - { - const btScalar depth=-(dot(x,wfi->water_normal)+wfi->water_offset); - if(depth>0) - { - medium.m_density = wfi->water_density; - medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); - } - } -} - -// -static inline void ApplyClampedForce( btSoftBody::Node& n, - const btVector3& f, - btScalar dt) -{ - const btScalar dtim=dt*n.m_im; - if((f*dtim).length2()>n.m_v.length2()) - {/* Clamp */ - n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim; - } - else - {/* Apply */ - n.m_f+=f; - } -} - -// -static inline int MatchEdge( const btSoftBody::Node* a, - const btSoftBody::Node* b, - const btSoftBody::Node* ma, - const btSoftBody::Node* mb) -{ -if((a==ma)&&(b==mb)) return(0); -if((a==mb)&&(b==ma)) return(1); -return(-1); -} - -// -// btEigen : Extract eigen system, -// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html -// outputs are NOT sorted. -// -struct btEigen -{ -static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) - { - static const int maxiterations=16; - static const btScalar accuracy=(btScalar)0.0001; - btMatrix3x3& v=*vectors; - int iterations=0; - vectors->setIdentity(); - do { - int p=0,q=1; - if(btFabs(a[p][q])accuracy) - { - const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]); - const btScalar z=btFabs(w); - const btScalar t=w/(z*(btSqrt(1+w*w)+z)); - if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ - { - const btScalar c=1/btSqrt(t*t+1); - const btScalar s=c*t; - mulPQ(a,c,s,p,q); - mulTPQ(a,c,s,p,q); - mulPQ(v,c,s,p,q); - } else break; - } else break; - } while((++iterations)accuracy) det=ndet; else break; - } - /* Final orthogonalization */ - Orthogonalize(q); - /* Compute 'S' */ - s=q.transpose()*m; - } - else - { - q.setIdentity(); - s.setIdentity(); - } -return(i); -} - -// -// btSoftColliders -// -struct btSoftColliders -{ - // - // ClusterBase - // - struct ClusterBase : btDbvt::ICollide - { - btScalar erp; - btScalar idt; - btScalar margin; - btScalar friction; - btScalar threshold; - ClusterBase() - { - erp =(btScalar)1; - idt =0; - margin =0; - friction =0; - threshold =(btScalar)0; - } - bool SolveContact( const btGjkEpaSolver2::sResults& res, - btSoftBody::Body ba,btSoftBody::Body bb, - btSoftBody::CJoint& joint) - { - if(res.distancedata; - btSoftClusterCollisionShape cshape(cluster); - const btConvexShape* rshape=(const btConvexShape*)prb->getCollisionShape(); - btGjkEpaSolver2::sResults res; - if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), - rshape,prb->getInterpolationWorldTransform(), - btVector3(1,0,0),res)) - { - btSoftBody::CJoint joint; - if(SolveContact(res,cluster,prb,joint)) - { - btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); - *pj=joint;psb->m_joints.push_back(pj); - if(prb->isStaticOrKinematicObject()) - { - pj->m_erp *= psb->m_cfg.kSKHR_CL; - pj->m_split *= psb->m_cfg.kSK_SPLT_CL; - } - else - { - pj->m_erp *= psb->m_cfg.kSRHR_CL; - pj->m_split *= psb->m_cfg.kSR_SPLT_CL; - } - } - } - } - void Process(btSoftBody* ps,btRigidBody* pr) - { - psb = ps; - prb = pr; - idt = ps->m_sst.isdt; - margin = ps->getCollisionShape()->getMargin()+ - pr->getCollisionShape()->getMargin(); - friction = btMin(psb->m_cfg.kDF,prb->getFriction()); - btVector3 mins; - btVector3 maxs; - - ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; - pr->getCollisionShape()->getAabb(pr->getInterpolationWorldTransform(),mins,maxs); - volume=btDbvtVolume::FromMM(mins,maxs); - volume.Expand(btVector3(1,1,1)*margin); - btDbvt::collideTV(ps->m_cdbvt.m_root,volume,*this); - } - }; - // - // CollideCL_SS - // - struct CollideCL_SS : ClusterBase - { - btSoftBody* bodies[2]; - void Process(const btDbvtNode* la,const btDbvtNode* lb) - { - btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data; - btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; - btSoftClusterCollisionShape csa(cla); - btSoftClusterCollisionShape csb(clb); - btGjkEpaSolver2::sResults res; - if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(), - &csb,btTransform::getIdentity(), - cla->m_com-clb->m_com,res)) - { - btSoftBody::CJoint joint; - if(SolveContact(res,cla,clb,joint)) - { - btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); - *pj=joint;bodies[0]->m_joints.push_back(pj); - pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL); - pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2; - } - } - } - void Process(btSoftBody* psa,btSoftBody* psb) - { - idt = psa->m_sst.isdt; - margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2; - friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF); - bodies[0] = psa; - bodies[1] = psb; - btDbvt::collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); - } - }; - // - // CollideSDF_RS - // - struct CollideSDF_RS : btDbvt::ICollide - { - void Process(const btDbvtNode* leaf) - { - btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; - DoNode(*node); - } - void DoNode(btSoftBody::Node& n) const - { - const btScalar m=n.m_im>0?dynmargin:stamargin; - btSoftBody::RContact c; - if( (!n.m_battach)&& - psb->checkContact(prb,n.m_x,m,c.m_cti)) - { - const btScalar ima=n.m_im; - const btScalar imb=prb->getInvMass(); - const btScalar ms=ima+imb; - if(ms>0) - { - const btTransform& wtr=prb->getInterpolationWorldTransform(); - const btMatrix3x3& iwi=prb->getInvInertiaTensorWorld(); - const btVector3 ra=n.m_x-wtr.getOrigin(); - const btVector3 va=prb->getVelocityInLocalPoint(ra)*psb->m_sst.sdt; - const btVector3 vb=n.m_x-n.m_q; - const btVector3 vr=vb-va; - const btScalar dn=dot(vr,c.m_cti.m_normal); - const btVector3 fv=vr-c.m_cti.m_normal*dn; - const btScalar fc=psb->m_cfg.kDF*prb->getFriction(); - c.m_node = &n; - c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra); - c.m_c1 = ra; - c.m_c2 = ima*psb->m_sst.sdt; - c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc; - c.m_c4 = prb->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; - psb->m_rcontacts.push_back(c); - prb->activate(); - } - } - } - btSoftBody* psb; - btRigidBody* prb; - btScalar dynmargin; - btScalar stamargin; - }; - // - // CollideVF_SS - // - struct CollideVF_SS : btDbvt::ICollide - { - void Process(const btDbvtNode* lnode, - const btDbvtNode* lface) - { - btSoftBody::Node* node=(btSoftBody::Node*)lnode->data; - btSoftBody::Face* face=(btSoftBody::Face*)lface->data; - btVector3 o=node->m_x; - btVector3 p; - btScalar d=SIMD_INFINITY; - ProjectOrigin( face->m_n[0]->m_x-o, - face->m_n[1]->m_x-o, - face->m_n[2]->m_x-o, - p,d); - const btScalar m=mrg+(o-node->m_q).length()*2; - if(d<(m*m)) - { - const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]}; - const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o); - const btScalar ma=node->m_im; - btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w); - if( (n[0]->m_im<=0)|| - (n[1]->m_im<=0)|| - (n[2]->m_im<=0)) - { - mb=0; - } - const btScalar ms=ma+mb; - if(ms>0) - { - btSoftBody::SContact c; - c.m_normal = p/-btSqrt(d); - c.m_margin = m; - c.m_node = node; - c.m_face = face; - c.m_weights = w; - c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF); - c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR; - c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR; - psb[0]->m_scontacts.push_back(c); - } - } - } - btSoftBody* psb[2]; - btScalar mrg; - }; -}; - -#endif //_BT_SOFT_BODY_INTERNALS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp deleted file mode 100644 index e62f35567b0..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btSoftBodyRigidBodyCollisionConfiguration.h" -#include "btSoftRigidCollisionAlgorithm.h" -#include "btSoftBodyConcaveCollisionAlgorithm.h" -#include "btSoftSoftCollisionAlgorithm.h" - -#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1 - -btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) -:btDefaultCollisionConfiguration(constructionInfo) -{ - void* mem; - - mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16); - m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); - m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); - m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; - m_swappedSoftRigidConvexCreateFunc->m_swapped=true; - -#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS - mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); - m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc; - - mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); - m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc; - m_swappedSoftRigidConcaveCreateFunc->m_swapped=true; -#endif - -} - -btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() -{ - m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_softSoftCreateFunc); - - m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_softRigidConvexCreateFunc); - - m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedSoftRigidConvexCreateFunc); - -#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS - m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_softRigidConcaveCreateFunc); - - m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); - btAlignedFree( m_swappedSoftRigidConcaveCreateFunc); -#endif -} - -///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation -btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) -{ - - ///try to handle the softbody interactions first - - if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE)) - { - return m_softSoftCreateFunc; - } - - ///softbody versus convex - if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_softRigidConvexCreateFunc; - } - - ///convex versus soft body - if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) - { - return m_swappedSoftRigidConvexCreateFunc; - } - -#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS - ///softbody versus convex - if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_softRigidConcaveCreateFunc; - } - - ///convex versus soft body - if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) - { - return m_swappedSoftRigidConcaveCreateFunc; - } -#endif - - ///fallback to the regular rigid collision shape - return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); -} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h deleted file mode 100644 index 41c3af96939..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION -#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION - -#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" - -class btVoronoiSimplexSolver; -class btGjkEpaPenetrationDepthSolver; - - -///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration -class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration -{ - - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc; - btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; - -public: - - btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); - - virtual ~btSoftBodyRigidBodyCollisionConfiguration(); - - ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation - virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); - -}; - -#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION - diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp deleted file mode 100644 index 835a03b8e3c..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btSoftRigidCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "btSoftBody.h" -///TODO: include all the shapes that the softbody can collide with -///alternatively, implement special case collision algorithms (just like for rigid collision shapes) - -//#include - -btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*col0*/,btCollisionObject* /*col1*/, bool isSwapped) -: btCollisionAlgorithm(ci), -//m_ownManifold(false), -//m_manifoldPtr(mf), -m_isSwapped(isSwapped) -{ -} - - -btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() -{ - - //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); - - /*if (m_ownManifold) - { - if (m_manifoldPtr) - m_dispatcher->releaseManifold(m_manifoldPtr); - } - */ - -} - - -#include - -void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)dispatchInfo; - (void)resultOut; - //printf("btSoftRigidCollisionAlgorithm\n"); - - btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0; - btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1; - - softBody->defaultCollisionHandler(rigidCollisionObject); - - -} - -btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) -{ - (void)resultOut; - (void)dispatchInfo; - (void)col0; - (void)col1; - - //not yet - return btScalar(1.); -} - - - diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h deleted file mode 100644 index 74327e6c635..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SOFT_RIGID_COLLISION_ALGORITHM_H -#define SOFT_RIGID_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" -class btPersistentManifold; -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" - -#include "LinearMath/btVector3.h" -class btSoftBody; - -/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody -class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm -{ -// bool m_ownManifold; -// btPersistentManifold* m_manifoldPtr; - - btSoftBody* m_softBody; - btCollisionObject* m_rigidCollisionObject; - - ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean - bool m_isSwapped; - -public: - - btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); - - virtual ~btSoftRigidCollisionAlgorithm(); - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - //we don't add any manifolds - } - - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm)); - if (!m_swapped) - { - return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false); - } else - { - return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true); - } - } - }; - -}; - -#endif //SOFT_RIGID_COLLISION_ALGORITHM_H - - diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp deleted file mode 100644 index 01b9fc0fd35..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#include "btSoftRigidDynamicsWorld.h" -#include "LinearMath/btQuickprof.h" - -//softbody & helpers -#include "btSoftBody.h" -#include "btSoftBodyHelpers.h" - -btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) -:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) -{ -m_drawFlags = fDrawFlags::Std; -m_drawNodeTree = true; -m_drawFaceTree = false; -m_drawClusterTree = false; -} - -btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() -{ - -} - -void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) -{ - btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep); - - for ( int i=0;ipredictMotion(timeStep); - } -} - -void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) -{ - btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); - - ///solve soft bodies constraints - solveSoftBodiesConstraints(); - - ///update soft bodies - updateSoftBodies(); - -} - -void btSoftRigidDynamicsWorld::updateSoftBodies() -{ - BT_PROFILE("updateSoftBodies"); - - for ( int i=0;iintegrateMotion(); - } -} - -void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints() -{ - BT_PROFILE("solveSoftConstraints"); - - if(m_softBodies.size()) - { - btSoftBody::solveClusters(m_softBodies); - } - - for(int i=0;isolveConstraints(); - } -} - -void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body) -{ - m_softBodies.push_back(body); - - btCollisionWorld::addCollisionObject(body, - btBroadphaseProxy::DefaultFilter, - btBroadphaseProxy::AllFilter); - -} - -void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body) -{ - m_softBodies.remove(body); - - btCollisionWorld::removeCollisionObject(body); -} - -void btSoftRigidDynamicsWorld::debugDrawWorld() -{ - btDiscreteDynamicsWorld::debugDrawWorld(); - - if (getDebugDrawer()) - { - int i; - for ( i=0;im_softBodies.size();i++) - { - btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; - btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); - btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); - if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); - if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); - } - } - } -} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h deleted file mode 100644 index d0010b65aad..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" - -#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H -#define BT_SOFT_RIGID_DYNAMICS_WORLD_H - -class btSoftBody; -typedef btAlignedObjectArray btSoftBodyArray; - -class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld -{ - - btSoftBodyArray m_softBodies; - int m_drawFlags; - bool m_drawNodeTree; - bool m_drawFaceTree; - bool m_drawClusterTree; - -protected: - - virtual void predictUnconstraintMotion(btScalar timeStep); - - virtual void internalSingleStepSimulation( btScalar timeStep); - - void updateSoftBodies(); - - void solveSoftBodiesConstraints(); - - - -public: - - btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); - - virtual ~btSoftRigidDynamicsWorld(); - - virtual void debugDrawWorld(); - - void addSoftBody(btSoftBody* body); - - void removeSoftBody(btSoftBody* body); - - int getDrawFlags() const { return(m_drawFlags); } - void setDrawFlags(int f) { m_drawFlags=f; } - - - btSoftBodyArray& getSoftBodyArray() - { - return m_softBodies; - } - - const btSoftBodyArray& getSoftBodyArray() const - { - return m_softBodies; - } - -}; - -#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp deleted file mode 100644 index 85a727944e0..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "btSoftSoftCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" -#include "BulletCollision/CollisionShapes/btBoxShape.h" -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "btSoftBody.h" - -#define USE_PERSISTENT_CONTACTS 1 - -btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*obj0*/,btCollisionObject* /*obj1*/) -: btCollisionAlgorithm(ci) -//m_ownManifold(false), -//m_manifoldPtr(mf) -{ -} - -btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm() -{ -} - -void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) -{ - btSoftBody* soft0 = (btSoftBody*)body0; - btSoftBody* soft1 = (btSoftBody*)body1; - soft0->defaultCollisionHandler(soft1); -} - -btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) -{ - //not yet - return 1.f; -} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h deleted file mode 100644 index 7ca9c3415c9..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SOFT_SOFT_COLLISION_ALGORITHM_H -#define SOFT_SOFT_COLLISION_ALGORITHM_H - -#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "BulletCollision/BroadphaseCollision/btDispatcher.h" -#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" - -class btPersistentManifold; -class btSoftBody; - -///collision detection between two btSoftBody shapes -class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm -{ - bool m_ownManifold; - btPersistentManifold* m_manifoldPtr; - - btSoftBody* m_softBody0; - btSoftBody* m_softBody1; - - -public: - btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) - : btCollisionAlgorithm(ci) {} - - virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); - - virtual void getAllContactManifolds(btManifoldArray& manifoldArray) - { - if (m_manifoldPtr && m_ownManifold) - manifoldArray.push_back(m_manifoldPtr); - } - - btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); - - virtual ~btSoftSoftCollisionAlgorithm(); - - struct CreateFunc :public btCollisionAlgorithmCreateFunc - { - virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) - { - int bbsize = sizeof(btSoftSoftCollisionAlgorithm); - void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); - return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1); - } - }; - -}; - -#endif //SOFT_SOFT_COLLISION_ALGORITHM_H - - diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h deleted file mode 100644 index eafe74be1ae..00000000000 --- a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h +++ /dev/null @@ -1,306 +0,0 @@ -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ -///btSparseSdf implementation by Nathanael Presson - -#ifndef _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ -#define _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ - -#include "BulletCollision/CollisionDispatch/btCollisionObject.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" - -// Modified Paul Hsieh hash -template -unsigned int HsiehHash(const void* pdata) - { - const unsigned short* data=(const unsigned short*)pdata; - unsigned hash=DWORDLEN<<2,tmp; - for(int i=0;i>11; - } - hash^=hash<<3;hash+=hash>>5; - hash^=hash<<4;hash+=hash>>17; - hash^=hash<<25;hash+=hash>>6; - return(hash); - } - -template -struct btSparseSdf - { - // - // Inner types - // - struct IntFrac - { - int b; - int i; - btScalar f; - }; - struct Cell - { - btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]; - int c[3]; - int puid; - unsigned hash; - btCollisionShape* pclient; - Cell* next; - }; - // - // Fields - // - - btAlignedObjectArray cells; - btScalar voxelsz; - int puid; - int ncells; - int nprobes; - int nqueries; - - // - // Methods - // - - // - void Initialize(int hashsize=2383) - { - cells.resize(hashsize,0); - Reset(); - } - // - void Reset() - { - for(int i=0,ni=cells.size();inext; - delete pc; - pc=pn; - } - } - voxelsz =0.25; - puid =0; - ncells =0; - nprobes =1; - nqueries =1; - } - // - void GarbageCollect(int lifetime=256) - { - const int life=puid-lifetime; - for(int i=0;inext; - if(pc->puidnext=pn; else root=pn; - delete pc;pc=pp;--ncells; - } - pp=pc;pc=pn; - } - } - //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries); - nqueries=1; - nprobes=1; - ++puid; /* TODO: Reset puid's when int range limit is reached */ - /* else setup a priority list... */ - } - // - int RemoveReferences(btCollisionShape* pcs) - { - int refcount=0; - for(int i=0;inext; - if(pc->pclient==pcs) - { - if(pp) pp->next=pn; else root=pn; - delete pc;pc=pp;++refcount; - } - pp=pc;pc=pn; - } - } - return(refcount); - } - // - btScalar Evaluate( const btVector3& x, - btCollisionShape* shape, - btVector3& normal, - btScalar margin) - { - /* Lookup cell */ - const btVector3 scx=x/voxelsz; - const IntFrac ix=Decompose(scx.x()); - const IntFrac iy=Decompose(scx.y()); - const IntFrac iz=Decompose(scx.z()); - const unsigned h=Hash(ix.b,iy.b,iz.b,shape); - Cell*& root=cells[static_cast(h%cells.size())]; - Cell* c=root; - ++nqueries; - while(c) - { - ++nprobes; - if( (c->hash==h) && - (c->c[0]==ix.b) && - (c->c[1]==iy.b) && - (c->c[2]==iz.b) && - (c->pclient==shape)) - { break; } - else - { c=c->next; } - } - if(!c) - { - ++nprobes; - ++ncells; - c=new Cell(); - c->next=root;root=c; - c->pclient=shape; - c->hash=h; - c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b; - BuildCell(*c); - } - c->puid=puid; - /* Extract infos */ - const int o[]={ ix.i,iy.i,iz.i}; - const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0], - c->d[o[0]+1][o[1]+0][o[2]+0], - c->d[o[0]+1][o[1]+1][o[2]+0], - c->d[o[0]+0][o[1]+1][o[2]+0], - c->d[o[0]+0][o[1]+0][o[2]+1], - c->d[o[0]+1][o[1]+0][o[2]+1], - c->d[o[0]+1][o[1]+1][o[2]+1], - c->d[o[0]+0][o[1]+1][o[2]+1]}; - /* Normal */ - #if 1 - const btScalar gx[]={ d[1]-d[0],d[2]-d[3], - d[5]-d[4],d[6]-d[7]}; - const btScalar gy[]={ d[3]-d[0],d[2]-d[1], - d[7]-d[4],d[6]-d[5]}; - const btScalar gz[]={ d[4]-d[0],d[5]-d[1], - d[7]-d[3],d[6]-d[2]}; - normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f), - Lerp(gx[2],gx[3],iy.f),iz.f)); - normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f), - Lerp(gy[2],gy[3],ix.f),iz.f)); - normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f), - Lerp(gz[2],gz[3],ix.f),iy.f)); - normal = normal.normalized(); - #else - normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); - #endif - /* Distance */ - const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), - Lerp(d[3],d[2],ix.f),iy.f); - const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f), - Lerp(d[7],d[6],ix.f),iy.f); - return(Lerp(d0,d1,iz.f)-margin); - } - // - void BuildCell(Cell& c) - { - const btVector3 org=btVector3( (btScalar)c.c[0], - (btScalar)c.c[1], - (btScalar)c.c[2]) * - CELLSIZE*voxelsz; - for(int k=0;k<=CELLSIZE;++k) - { - const btScalar z=voxelsz*k+org.z(); - for(int j=0;j<=CELLSIZE;++j) - { - const btScalar y=voxelsz*j+org.y(); - for(int i=0;i<=CELLSIZE;++i) - { - const btScalar x=voxelsz*i+org.x(); - c.d[i][j][k]=DistanceToShape( btVector3(x,y,z), - c.pclient); - } - } - } - } - // - static inline btScalar DistanceToShape(const btVector3& x, - btCollisionShape* shape) - { - btTransform unit; - unit.setIdentity(); - if(shape->isConvex()) - { - btGjkEpaSolver2::sResults res; - btConvexShape* csh=static_cast(shape); - return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res)); - } - return(0); - } - // - static inline IntFrac Decompose(btScalar x) - { - /* That one need a lot of improvements... */ - /* Remove test, faster floor... */ - IntFrac r; - x/=CELLSIZE; - const int o=x<0?(int)(-x+1):0; - x+=o;r.b=(int)x; - const btScalar k=(x-r.b)*CELLSIZE; - r.i=(int)k;r.f=k-r.i;r.b-=o; - return(r); - } - // - static inline btScalar Lerp(btScalar a,btScalar b,btScalar t) - { - return(a+(b-a)*t); - } - - - - // - static inline unsigned int Hash(int x,int y,int z,btCollisionShape* shape) - { - struct btS - { - int x,y,z; - void* p; - }; - - btS myset; - - myset.x=x;myset.y=y;myset.z=z;myset.p=shape; - const void* ptr = &myset; - - unsigned int result = HsiehHash (ptr); - - - return result; - } -}; - - -#endif diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt index 02ffaad7228..207eed94a3e 100644 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -4,32 +4,7 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ) ADD_LIBRARY(LibLinearMath - btAlignedObjectArray.h - btList.h - btPoolAllocator.h - btRandom.h - btVector3.h - btDefaultMotionState.h - btMatrix3x3.h - btQuadWord.h - btHashMap.h - btScalar.h - btAabbUtil2.h - btConvexHull.h - btConvexHull.cpp - btMinMax.h - btQuaternion.h - btStackAlloc.h - btGeometryUtil.h - btMotionState.h - btTransform.h - btAlignedAllocator.h - btIDebugDraw.h - btPoint3.h - btQuickprof.h - btTransformUtil.h - btQuickprof.cpp - btGeometryUtil.cpp - btAlignedAllocator.cpp +btQuickprof.cpp +btGeometryUtil.cpp ) diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 275c4914628..429163c8138 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -17,18 +17,12 @@ subject to the following restrictions: #ifndef AABB_UTIL2 #define AABB_UTIL2 -#include "btTransform.h" #include "btVector3.h" -#include "btMinMax.h" +#include "btSimdMinMax.h" -SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, - btVector3& aabbMax, - const btVector3& expansionMin, - const btVector3& expansionMax) -{ - aabbMin = aabbMin + expansionMin; - aabbMax = aabbMax + expansionMax; -} + +#define btMin(a,b) ((a < b ? a : b)) +#define btMax(a,b) ((a > b ? a : b)) /// conservative test for overlap between two aabbs @@ -73,41 +67,6 @@ SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) } -SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, - const btVector3& rayInvDirection, - const unsigned int raySign[3], - const btVector3 bounds[2], - btScalar& tmin, - btScalar lambda_min, - btScalar lambda_max) -{ - btScalar tmax, tymin, tymax, tzmin, tzmax; - tmin = (bounds[raySign[0]][0] - rayFrom[0]) * rayInvDirection[0]; - tmax = (bounds[1-raySign[0]][0] - rayFrom[0]) * rayInvDirection[0]; - tymin = (bounds[raySign[1]][1] - rayFrom[1]) * rayInvDirection[1]; - tymax = (bounds[1-raySign[1]][1] - rayFrom[1]) * rayInvDirection[1]; - - if ( (tmin > tymax) || (tymin > tmax) ) - return false; - - if (tymin > tmin) - tmin = tymin; - - if (tymax < tmax) - tmax = tymax; - - tzmin = (bounds[raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; - tzmax = (bounds[1-raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; - - if ( (tmin > tzmax) || (tzmin > tmax) ) - return false; - if (tzmin > tmin) - tmin = tzmin; - if (tzmax < tmax) - tmax = tzmax; - return ( (tmin < lambda_max) && (tmax > lambda_min) ); -} - SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, const btVector3& rayTo, const btVector3& aabbMin, @@ -164,39 +123,5 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, } - -SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut) -{ - btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin); - btMatrix3x3 abs_b = t.getBasis().absolute(); - btVector3 center = t.getOrigin(); - btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin), - abs_b[1].dot(halfExtentsWithMargin), - abs_b[2].dot(halfExtentsWithMargin)); - aabbMinOut = center - extent; - aabbMaxOut = center + extent; -} - - -SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut) -{ - btAssert(localAabbMin.getX() <= localAabbMax.getX()); - btAssert(localAabbMin.getY() <= localAabbMax.getY()); - btAssert(localAabbMin.getZ() <= localAabbMax.getZ()); - btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); - localHalfExtents+=btVector3(margin,margin,margin); - - btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); - btMatrix3x3 abs_b = trans.getBasis().absolute(); - btVector3 center = trans(localCenter); - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - aabbMinOut = center-extent; - aabbMaxOut = center+extent; -} - - #endif - diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp index e120289e061..1f5877fa37e 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -15,187 +15,56 @@ subject to the following restrictions: #include "btAlignedAllocator.h" -int gNumAlignedAllocs = 0; -int gNumAlignedFree = 0; -int gTotalBytesAlignedAllocs = 0;//detect memory leaks -#if defined (BT_HAS_ALIGNED_ALLOCATOR) +#if defined (BT_HAS_ALIGNED_ALOCATOR) + #include -static void *btAlignedAllocDefault(size_t size, int alignment) +void* btAlignedAlloc (int size, int alignment) { - return _aligned_malloc(size, (size_t)alignment); + return _aligned_malloc(size,alignment); } -static void btAlignedFreeDefault(void *ptr) +void btAlignedFree (void* ptr) { _aligned_free(ptr); } -#elif defined(__CELLOS_LV2__) + +#else + +#ifdef __CELLOS_LV2__ + #include -static inline void *btAlignedAllocDefault(size_t size, int alignment) +int numAllocs = 0; +int numFree = 0; + +void* btAlignedAlloc (int size, int alignment) { + numAllocs++; return memalign(alignment, size); } -static inline void btAlignedFreeDefault(void *ptr) +void btAlignedFree (void* ptr) { + numFree++; free(ptr); } + #else -static inline void *btAlignedAllocDefault(size_t size, int alignment) -{ - void *ret; - char *real; - unsigned long offset; +///todo +///will add some multi-platform version that works without _aligned_malloc/_aligned_free - real = (char *)malloc(size + sizeof(void *) + (alignment-1)); - if (real) { - offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); - ret = (void *)((real + sizeof(void *)) + offset); - *((void **)(ret)-1) = (void *)(real); - } else { - ret = (void *)(real); - } - return (ret); +void* btAlignedAlloc (int size, int alignment) +{ + return new char[size]; } -static inline void btAlignedFreeDefault(void *ptr) +void btAlignedFree (void* ptr) { - void* real; - - if (ptr) { - real = *((void **)(ptr)-1); - free(real); - } + delete [] (char*) ptr; } +#endif // + #endif -static void *btAllocDefault(size_t size) -{ - return malloc(size); -} - -static void btFreeDefault(void *ptr) -{ - free(ptr); -} - -static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; -static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; -static btAllocFunc *sAllocFunc = btAllocDefault; -static btFreeFunc *sFreeFunc = btFreeDefault; - -void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) -{ - sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault; - sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault; -} - -void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) -{ - sAllocFunc = allocFunc ? allocFunc : btAllocDefault; - sFreeFunc = freeFunc ? freeFunc : btFreeDefault; -} - -#ifdef BT_DEBUG_MEMORY_ALLOCATIONS -//this generic allocator provides the total allocated number of bytes -#include - -void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) -{ - void *ret; - char *real; - unsigned long offset; - - gTotalBytesAlignedAllocs += size; - gNumAlignedAllocs++; - - - real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); - if (real) { - offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & -(alignment-1); - ret = (void *)((real + 2*sizeof(void *)) + offset); - *((void **)(ret)-1) = (void *)(real); - *((int*)(ret)-2) = size; - - } else { - ret = (void *)(real);//?? - } - - printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); - - int* ptr = (int*)ret; - *ptr = 12; - return (ret); -} - -void btAlignedFreeInternal (void* ptr,int line,char* filename) -{ - - void* real; - gNumAlignedFree++; - - if (ptr) { - real = *((void **)(ptr)-1); - int size = *((int*)(ptr)-2); - gTotalBytesAlignedAllocs -= size; - - printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); - - sFreeFunc(real); - } else - { - printf("NULL ptr\n"); - } -} - -#else //BT_DEBUG_MEMORY_ALLOCATIONS - -void* btAlignedAllocInternal (size_t size, int alignment) -{ - gNumAlignedAllocs++; - void* ptr; -#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) - ptr = sAlignedAllocFunc(size, alignment); -#else - char *real; - unsigned long offset; - - real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); - if (real) { - offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); - ptr = (void *)((real + sizeof(void *)) + offset); - *((void **)(ptr)-1) = (void *)(real); - } else { - ptr = (void *)(real); - } -#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) -// printf("btAlignedAllocInternal %d, %x\n",size,ptr); - return ptr; -} - -void btAlignedFreeInternal (void* ptr) -{ - if (!ptr) - { - return; - } - - gNumAlignedFree++; -// printf("btAlignedFreeInternal %x\n",ptr); -#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) - sAlignedFreeFunc(ptr); -#else - void* real; - - if (ptr) { - real = *((void **)(ptr)-1); - sFreeFunc(real); - } -#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) -} - -#endif //BT_DEBUG_MEMORY_ALLOCATIONS diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h index a252f324d77..07585717f45 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h @@ -21,39 +21,15 @@ subject to the following restrictions: ///that is better portable and more predictable #include "btScalar.h" -//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 -#ifdef BT_DEBUG_MEMORY_ALLOCATIONS -#define btAlignedAlloc(a,b) \ - btAlignedAllocInternal(a,b,__LINE__,__FILE__) +void* btAlignedAlloc (int size, int alignment); -#define btAlignedFree(ptr) \ - btAlignedFreeInternal(ptr,__LINE__,__FILE__) +void btAlignedFree (void* ptr); -void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); -void btAlignedFreeInternal (void* ptr,int line,char* filename); - -#else - void* btAlignedAllocInternal (size_t size, int alignment); - void btAlignedFreeInternal (void* ptr); - - #define btAlignedAlloc(a,b) btAlignedAllocInternal(a,b) - #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) - -#endif typedef int size_type; -typedef void *(btAlignedAllocFunc)(size_t size, int alignment); -typedef void (btAlignedFreeFunc)(void *memblock); -typedef void *(btAllocFunc)(size_t size); -typedef void (btFreeFunc)(void *memblock); -void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); -void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); - -///The btAlignedAllocator is a portable class for aligned memory allocations. -///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. template < typename T , unsigned Alignment > class btAlignedAllocator { diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h index 5598f0d7236..8bef5eb5d06 100644 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -39,8 +39,8 @@ subject to the following restrictions: #endif //BT_USE_PLACEMENT_NEW -///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods -///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data +///btAlignedObjectArray uses a subset of the stl::vector interface for its methods +///It is developed to replace stl::vector to avoid STL alignment issues to add SIMD/SSE data template //template class btAlignedObjectArray @@ -50,8 +50,6 @@ class btAlignedObjectArray int m_size; int m_capacity; T* m_data; - //PCK: added this line - bool m_ownsMemory; protected: SIMD_FORCE_INLINE int allocSize(int size) @@ -71,8 +69,6 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void init() { - //PCK: added this line - m_ownsMemory = true; m_data = 0; m_size = 0; m_capacity = 0; @@ -96,11 +92,7 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void deallocate() { if(m_data) { - //PCK: enclosed the deallocation in this block - if (m_ownsMemory) - { - m_allocator.deallocate(m_data); - } + m_allocator.deallocate(m_data); m_data = 0; } } @@ -231,9 +223,6 @@ class btAlignedObjectArray destroy(0,size()); deallocate(); - - //PCK: added this line - m_ownsMemory = true; m_data = s; @@ -253,46 +242,6 @@ class btAlignedObjectArray } }; - template - void quickSortInternal(L CompareFunc,int lo, int hi) - { - // lo is the lower index, hi is the upper index - // of the region of array a that is to be sorted - int i=lo, j=hi; - T x=m_data[(lo+hi)/2]; - - // partition - do - { - while (CompareFunc(m_data[i],x)) - i++; - while (CompareFunc(x,m_data[j])) - j--; - if (i<=j) - { - swap(i,j); - i++; j--; - } - } while (i<=j); - - // recursion - if (lo - void quickSort(L CompareFunc) - { - //don't sort 0 or 1 elements - if (size()>1) - { - quickSortInternal(CompareFunc,0,size()-1); - } - } - ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ template @@ -411,16 +360,8 @@ class btAlignedObjectArray } } - //PCK: whole function - void initializeFromBuffer(void *buffer, int size, int capacity) - { - clear(); - m_ownsMemory = false; - m_data = (T*)buffer; - m_size = size; - m_capacity = capacity; - } - }; #endif //BT_OBJECT_ARRAY__ + + diff --git a/extern/bullet2/src/LinearMath/btConvexHull.h b/extern/bullet2/src/LinearMath/btConvexHull.h deleted file mode 100644 index 8bb80de0225..00000000000 --- a/extern/bullet2/src/LinearMath/btConvexHull.h +++ /dev/null @@ -1,242 +0,0 @@ - -/* -Stan Melax Convex Hull Computation -Copyright (c) 2008 Stan Melax http://www.melax.com/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -///includes modifications/improvements by John Ratcliff, see BringOutYourDead below. - -#ifndef CD_HULL_H -#define CD_HULL_H - -#include "LinearMath/btVector3.h" -#include "LinearMath/btAlignedObjectArray.h" - -typedef btAlignedObjectArray TUIntArray; - -class HullResult -{ -public: - HullResult(void) - { - mPolygons = true; - mNumOutputVertices = 0; - mNumFaces = 0; - mNumIndices = 0; - } - bool mPolygons; // true if indices represents polygons, false indices are triangles - unsigned int mNumOutputVertices; // number of vertices in the output hull - btAlignedObjectArray m_OutputVertices; // array of vertices - unsigned int mNumFaces; // the number of faces produced - unsigned int mNumIndices; // the total number of indices - btAlignedObjectArray m_Indices; // pointer to indices. - -// If triangles, then indices are array indexes into the vertex list. -// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc.. -}; - -enum HullFlag -{ - QF_TRIANGLES = (1<<0), // report results as triangles, not polygons. - QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices. - QF_DEFAULT = QF_TRIANGLES -}; - - -class HullDesc -{ -public: - HullDesc(void) - { - mFlags = QF_DEFAULT; - mVcount = 0; - mVertices = 0; - mVertexStride = sizeof(btVector3); - mNormalEpsilon = 0.001f; - mMaxVertices = 4096; // maximum number of points to be considered for a convex hull. - mMaxFaces = 4096; - }; - - HullDesc(HullFlag flag, - unsigned int vcount, - const btVector3 *vertices, - unsigned int stride = sizeof(btVector3)) - { - mFlags = flag; - mVcount = vcount; - mVertices = vertices; - mVertexStride = stride; - mNormalEpsilon = btScalar(0.001); - mMaxVertices = 4096; - } - - bool HasHullFlag(HullFlag flag) const - { - if ( mFlags & flag ) return true; - return false; - } - - void SetHullFlag(HullFlag flag) - { - mFlags|=flag; - } - - void ClearHullFlag(HullFlag flag) - { - mFlags&=~flag; - } - - unsigned int mFlags; // flags to use when generating the convex hull. - unsigned int mVcount; // number of vertices in the input point cloud - const btVector3 *mVertices; // the array of vertices. - unsigned int mVertexStride; // the stride of each vertex, in bytes. - btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on. - unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull! - unsigned int mMaxFaces; -}; - -enum HullError -{ - QE_OK, // success! - QE_FAIL // failed. -}; - -class btPlane -{ - public: - btVector3 normal; - btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0 - btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){} - btPlane():normal(),dist(0){} - -}; - - - -class ConvexH -{ - public: - class HalfEdge - { - public: - short ea; // the other half of the edge (index into edges list) - unsigned char v; // the vertex at the start of this edge (index into vertices list) - unsigned char p; // the facet on which this edge lies (index into facets list) - HalfEdge(){} - HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){} - }; - ConvexH() - { - int i; - i=0; - } - ~ConvexH() - { - int i; - i=0; - } - btAlignedObjectArray vertices; - btAlignedObjectArray edges; - btAlignedObjectArray facets; - ConvexH(int vertices_size,int edges_size,int facets_size); -}; - - -class int4 -{ -public: - int x,y,z,w; - int4(){}; - int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;} - const int& operator[](int i) const {return (&x)[i];} - int& operator[](int i) {return (&x)[i];} -}; - -class PHullResult -{ -public: - - PHullResult(void) - { - mVcount = 0; - mIndexCount = 0; - mFaceCount = 0; - mVertices = 0; - } - - unsigned int mVcount; - unsigned int mIndexCount; - unsigned int mFaceCount; - btVector3* mVertices; - TUIntArray m_Indices; -}; - - - -///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method. -///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape. -class HullLibrary -{ - - btAlignedObjectArray m_tris; - -public: - - HullError CreateConvexHull(const HullDesc& desc, // describes the input request - HullResult& result); // contains the resulst - HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. - -private: - - bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit); - - class Tri* allocateTriangle(int a,int b,int c); - void deAllocateTriangle(Tri*); - void b2bfix(Tri* s,Tri*t); - - void removeb2b(Tri* s,Tri*t); - - void checkit(Tri *t); - - Tri* extrudable(btScalar epsilon); - - int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit); - - int calchullgen(btVector3 *verts,int verts_count, int vlimit); - - int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow); - - class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice); - - void extrude(class Tri* t0,int v); - - ConvexH* test_cube(); - - //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. - //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud. - //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull. - //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation. - void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount); - - bool CleanupVertices(unsigned int svcount, - const btVector3* svertices, - unsigned int stride, - unsigned int &vcount, // output number of vertices - btVector3* vertices, // location to store the results. - btScalar normalepsilon, - btVector3& scale); -}; - - -#endif - diff --git a/extern/bullet2/src/LinearMath/btDefaultMotionState.h b/extern/bullet2/src/LinearMath/btDefaultMotionState.h index d758f77ed81..d4ec8e8879c 100644 --- a/extern/bullet2/src/LinearMath/btDefaultMotionState.h +++ b/extern/bullet2/src/LinearMath/btDefaultMotionState.h @@ -1,7 +1,7 @@ #ifndef DEFAULT_MOTION_STATE_H #define DEFAULT_MOTION_STATE_H -///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets. +///btDefaultMotionState provides a common implementation to synchronize world transforms with offsets struct btDefaultMotionState : public btMotionState { btTransform m_graphicsWorldTrans; diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp index 5ac230f712f..3d0fb122a6b 100644 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp @@ -22,12 +22,7 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" -{ - void btBulletMathProbe (); - - void btBulletMathProbe () {} -} +extern "C" void btBulletMathProbe () {} bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin) @@ -62,8 +57,6 @@ bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const return true; } -bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations); - bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) { int numbrushes = planeEquations.size(); diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.h b/extern/bullet2/src/LinearMath/btGeometryUtil.h index a4b13b45609..766cd75c383 100644 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.h +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.h @@ -19,7 +19,6 @@ subject to the following restrictions: #include "btVector3.h" #include "btAlignedObjectArray.h" -///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices. class btGeometryUtil { public: diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h index 563615a9a32..5f40ca39157 100644 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -31,9 +31,6 @@ DEALINGS IN THE SOFTWARE. #include "btVector3.h" -///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations. -///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld. -///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum. class btIDebugDraw { public: @@ -58,24 +55,11 @@ class btIDebugDraw virtual ~btIDebugDraw() {}; virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; - - virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha) - { - drawTriangle(v0,v1,v2,color,alpha); - } - virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/) - { - drawLine(v0,v1,color); - drawLine(v1,v2,color); - drawLine(v2,v0,color); - } virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; virtual void reportErrorWarning(const char* warningString) = 0; - virtual void draw3dText(const btVector3& location,const char* textString) = 0; - virtual void setDebugMode(int debugMode) =0; virtual int getDebugMode() const = 0; diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h index 14aa4ae2348..94f53c3c0a5 100644 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -22,9 +22,6 @@ subject to the following restrictions: #include "btQuaternion.h" - -///The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3. -///Make sure to only include a pure orthogonal matrix without scaling. class btMatrix3x3 { public: btMatrix3x3 () {} @@ -284,91 +281,6 @@ class btMatrix3x3 { } - ///diagonalizes this matrix by the Jacobi method. rot stores the rotation - ///from the coordinate system in which the matrix is diagonal to the original - ///coordinate system, i.e., old_this = rot * new_this * rot^T. The iteration - ///stops when all off-diagonal elements are less than the threshold multiplied - ///by the sum of the absolute values of the diagonal, or when maxSteps have - ///been executed. Note that this matrix is assumed to be symmetric. - void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps) - { - rot.setIdentity(); - for (int step = maxSteps; step > 0; step--) - { - // find off-diagonal element [p][q] with largest magnitude - int p = 0; - int q = 1; - int r = 2; - btScalar max = btFabs(m_el[0][1]); - btScalar v = btFabs(m_el[0][2]); - if (v > max) - { - q = 2; - r = 1; - max = v; - } - v = btFabs(m_el[1][2]); - if (v > max) - { - p = 1; - q = 2; - r = 0; - max = v; - } - - btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2])); - if (max <= t) - { - if (max <= SIMD_EPSILON * t) - { - return; - } - step = 1; - } - - // compute Jacobi rotation J which leads to a zero for element [p][q] - btScalar mpq = m_el[p][q]; - btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq); - btScalar theta2 = theta * theta; - btScalar cos; - btScalar sin; - if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON)) - { - t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2)) - : 1 / (theta - btSqrt(1 + theta2)); - cos = 1 / btSqrt(1 + t * t); - sin = cos * t; - } - else - { - // approximation for large theta-value, i.e., a nearly diagonal matrix - t = 1 / (theta * (2 + btScalar(0.5) / theta2)); - cos = 1 - btScalar(0.5) * t * t; - sin = cos * t; - } - - // apply rotation to matrix (this = J^T * this * J) - m_el[p][q] = m_el[q][p] = 0; - m_el[p][p] -= t * mpq; - m_el[q][q] += t * mpq; - btScalar mrp = m_el[r][p]; - btScalar mrq = m_el[r][q]; - m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq; - m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp; - - // apply rotation to rot (rot = rot * J) - for (int i = 0; i < 3; i++) - { - btVector3& row = rot[i]; - mrp = row[p]; - mrq = row[q]; - row[p] = cos * mrp - sin * mrq; - row[q] = cos * mrq + sin * mrp; - } - } - } - - protected: btScalar cofac(int r1, int c1, int r2, int c2) const @@ -444,7 +356,7 @@ class btMatrix3x3 { m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), - m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].x()); } SIMD_FORCE_INLINE btMatrix3x3 @@ -494,11 +406,5 @@ class btMatrix3x3 { } */ -SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2) -{ - return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] && - m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] && - m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] ); -} #endif diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h index 5e27d62a4a4..1b8a3633f38 100644 --- a/extern/bullet2/src/LinearMath/btMinMax.h +++ b/extern/bullet2/src/LinearMath/btMinMax.h @@ -18,15 +18,15 @@ subject to the following restrictions: #define GEN_MINMAX_H template -SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) +SIMD_FORCE_INLINE const T& GEN_min(const T& a, const T& b) { - return a < b ? a : b ; + return b < a ? b : a; } template -SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) +SIMD_FORCE_INLINE const T& GEN_max(const T& a, const T& b) { - return a > b ? a : b; + return a < b ? b : a; } template @@ -36,7 +36,7 @@ SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub) } template -SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) +SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) { if (b < a) { @@ -45,7 +45,7 @@ SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) } template -SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) +SIMD_FORCE_INLINE void GEN_set_max(T& a, const T& b) { if (a < b) { diff --git a/extern/bullet2/src/LinearMath/btMotionState.h b/extern/bullet2/src/LinearMath/btMotionState.h index 94318140902..1975e5ff900 100644 --- a/extern/bullet2/src/LinearMath/btMotionState.h +++ b/extern/bullet2/src/LinearMath/btMotionState.h @@ -18,7 +18,7 @@ subject to the following restrictions: #include "btTransform.h" -///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics +///btMotionState allows the dynamics world to synchronize the updated world transforms with graphics ///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) class btMotionState { diff --git a/extern/bullet2/src/LinearMath/btPoolAllocator.h b/extern/bullet2/src/LinearMath/btPoolAllocator.h deleted file mode 100644 index e9620ac5faa..00000000000 --- a/extern/bullet2/src/LinearMath/btPoolAllocator.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - - -#ifndef _BT_POOL_ALLOCATOR_H -#define _BT_POOL_ALLOCATOR_H - -#include "btScalar.h" -#include "btAlignedAllocator.h" - -///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. -class btPoolAllocator -{ - int m_elemSize; - int m_maxElements; - int m_freeCount; - void* m_firstFree; - unsigned char* m_pool; - -public: - - btPoolAllocator(int elemSize, int maxElements) - :m_elemSize(elemSize), - m_maxElements(maxElements) - { - m_pool = (unsigned char*) btAlignedAlloc( static_cast(m_elemSize*m_maxElements),16); - - unsigned char* p = m_pool; - m_firstFree = p; - m_freeCount = m_maxElements; - int count = m_maxElements; - while (--count) { - *(void**)p = (p + m_elemSize); - p += m_elemSize; - } - *(void**)p = 0; - } - - ~btPoolAllocator() - { - btAlignedFree( m_pool); - } - - int getFreeCount() const - { - return m_freeCount; - } - - void* allocate(int size) - { - // release mode fix - (void)size; - btAssert(!size || size<=m_elemSize); - btAssert(m_freeCount>0); - void* result = m_firstFree; - m_firstFree = *(void**)m_firstFree; - --m_freeCount; - return result; - } - - bool validPtr(void* ptr) - { - if (ptr) { - if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) - { - return true; - } - } - return false; - } - - void freeMemory(void* ptr) - { - if (ptr) { - btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); - - *(void**)ptr = m_firstFree; - m_firstFree = ptr; - ++m_freeCount; - } - } - - -}; - -#endif //_BT_POOL_ALLOCATOR_H diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h index 2e80fc2ca47..961ac484d20 100644 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -17,31 +17,19 @@ subject to the following restrictions: #define SIMD_QUADWORD_H #include "btScalar.h" -#include "btMinMax.h" -#include -///The btQuadWordStorage class is base class for btVector3 and btQuaternion. -///Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. todo: look into this -///ATTRIBUTE_ALIGNED16(class) btQuadWordStorage -class btQuadWordStorage -{ -protected: - - btScalar m_x; - btScalar m_y; - btScalar m_z; - btScalar m_unusedW; - -public: - -}; - ///btQuadWord is base-class for vectors, points -class btQuadWord : public btQuadWordStorage +class btQuadWord { + protected: + btScalar m_x; + btScalar m_y; + btScalar m_z; + btScalar m_unusedW; + public: // SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } @@ -73,8 +61,6 @@ class btQuadWord : public btQuadWordStorage SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } - - SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) { m_x=x; @@ -103,36 +89,47 @@ class btQuadWord : public btQuadWordStorage { } - SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) + :m_x(x),m_y(y),m_z(z) + //todo, remove this in release/simd ? + ,m_unusedW(btScalar(0.)) { - *((btQuadWordStorage*)this) = q; - } - - SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) - { - m_x = x, m_y = y, m_z = z, m_unusedW = 0.0f; } SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) + :m_x(x),m_y(y),m_z(z),m_unusedW(w) { - m_x = x, m_y = y, m_z = z, m_unusedW = w; } SIMD_FORCE_INLINE void setMax(const btQuadWord& other) { - btSetMax(m_x, other.m_x); - btSetMax(m_y, other.m_y); - btSetMax(m_z, other.m_z); - btSetMax(m_unusedW, other.m_unusedW); + if (other.m_x > m_x) + m_x = other.m_x; + + if (other.m_y > m_y) + m_y = other.m_y; + + if (other.m_z > m_z) + m_z = other.m_z; + + if (other.m_unusedW > m_unusedW) + m_unusedW = other.m_unusedW; } SIMD_FORCE_INLINE void setMin(const btQuadWord& other) { - btSetMin(m_x, other.m_x); - btSetMin(m_y, other.m_y); - btSetMin(m_z, other.m_z); - btSetMin(m_unusedW, other.m_unusedW); + if (other.m_x < m_x) + m_x = other.m_x; + + if (other.m_y < m_y) + m_y = other.m_y; + + if (other.m_z < m_z) + m_z = other.m_z; + + if (other.m_unusedW < m_unusedW) + m_unusedW = other.m_unusedW; } diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h index 264751b33e7..50334970ba6 100644 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -19,7 +19,6 @@ subject to the following restrictions: #include "btVector3.h" -///The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. class btQuaternion : public btQuadWord { public: btQuaternion() {} @@ -159,7 +158,7 @@ public: btQuaternion inverse() const { - return btQuaternion(-m_x, -m_y, -m_z, m_unusedW); + return btQuaternion(m_x, m_y, m_z, -m_unusedW); } SIMD_FORCE_INLINE btQuaternion @@ -286,7 +285,7 @@ slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) } SIMD_FORCE_INLINE btVector3 -quatRotate(const btQuaternion& rotation, const btVector3& v) +quatRotate(btQuaternion& rotation, btVector3& v) { btQuaternion q = rotation * v; q *= rotation.inverse(); @@ -294,7 +293,7 @@ quatRotate(const btQuaternion& rotation, const btVector3& v) } SIMD_FORCE_INLINE btQuaternion -shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized { btVector3 c = v0.cross(v1); btScalar d = v0.dot(v1); @@ -309,7 +308,7 @@ shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Ge } SIMD_FORCE_INLINE btQuaternion -shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) +shortestArcQuatNormalize(btVector3& v0,btVector3& v1) { v0.normalize(); v1.normalize(); @@ -320,4 +319,3 @@ shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) - diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp index e5b1196149b..37a0c8c3be5 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.cpp +++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp @@ -1,282 +1,38 @@ /* +Copyright (c) 2006 Tyler Streeter -/*************************************************************************************************** -** -** profile.cpp -** -** Real-Time Hierarchical Profiling for Game Programming Gems 3 -** -** by Greg Hjelstrom & Byon Garrabrant -** -***************************************************************************************************/ +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + + +// Please visit the project website (http://quickprof.sourceforge.net) +// for usage instructions. // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). #include "LinearMath/btQuickprof.h" +#ifdef USE_QUICKPROF -#ifdef USE_BT_CLOCK - -static btClock gProfileClock; - -inline void Profile_Get_Ticks(unsigned long int * ticks) -{ - *ticks = gProfileClock.getTimeMicroseconds(); -} - -inline float Profile_Get_Tick_Rate(void) -{ -// return 1000000.f; - return 1000.f; - -} - - - -/*************************************************************************************************** -** -** CProfileNode -** -***************************************************************************************************/ - -/*********************************************************************************************** - * INPUT: * - * name - pointer to a static string which is the name of this profile node * - * parent - parent pointer * - * * - * WARNINGS: * - * The name is assumed to be a static pointer, only the pointer is stored and compared for * - * efficiency reasons. * - *=============================================================================================*/ -CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : - Name( name ), - TotalCalls( 0 ), - TotalTime( 0 ), - StartTime( 0 ), - RecursionCounter( 0 ), - Parent( parent ), - Child( NULL ), - Sibling( NULL ) -{ - Reset(); -} - - -void CProfileNode::CleanupMemory() -{ - delete ( Child); - Child = NULL; - delete ( Sibling); - Sibling = NULL; -} - -CProfileNode::~CProfileNode( void ) -{ - delete ( Child); - delete ( Sibling); -} - - -/*********************************************************************************************** - * INPUT: * - * name - static string pointer to the name of the node we are searching for * - * * - * WARNINGS: * - * All profile names are assumed to be static strings so this function uses pointer compares * - * to find the named node. * - *=============================================================================================*/ -CProfileNode * CProfileNode::Get_Sub_Node( const char * name ) -{ - // Try to find this sub node - CProfileNode * child = Child; - while ( child ) { - if ( child->Name == name ) { - return child; - } - child = child->Sibling; - } - - // We didn't find it, so add it - - CProfileNode * node = new CProfileNode( name, this ); - node->Sibling = Child; - Child = node; - return node; -} - - -void CProfileNode::Reset( void ) -{ - TotalCalls = 0; - TotalTime = 0.0f; - gProfileClock.reset(); - - if ( Child ) { - Child->Reset(); - } - if ( Sibling ) { - Sibling->Reset(); - } -} - - -void CProfileNode::Call( void ) -{ - TotalCalls++; - if (RecursionCounter++ == 0) { - Profile_Get_Ticks(&StartTime); - } -} - - -bool CProfileNode::Return( void ) -{ - if ( --RecursionCounter == 0 && TotalCalls != 0 ) { - unsigned long int time; - Profile_Get_Ticks(&time); - time-=StartTime; - TotalTime += (float)time / Profile_Get_Tick_Rate(); - } - return ( RecursionCounter == 0 ); -} - - -/*************************************************************************************************** -** -** CProfileIterator -** -***************************************************************************************************/ -CProfileIterator::CProfileIterator( CProfileNode * start ) -{ - CurrentParent = start; - CurrentChild = CurrentParent->Get_Child(); -} - - -void CProfileIterator::First(void) -{ - CurrentChild = CurrentParent->Get_Child(); -} - - -void CProfileIterator::Next(void) -{ - CurrentChild = CurrentChild->Get_Sibling(); -} - - -bool CProfileIterator::Is_Done(void) -{ - return CurrentChild == NULL; -} - - -void CProfileIterator::Enter_Child( int index ) -{ - CurrentChild = CurrentParent->Get_Child(); - while ( (CurrentChild != NULL) && (index != 0) ) { - index--; - CurrentChild = CurrentChild->Get_Sibling(); - } - - if ( CurrentChild != NULL ) { - CurrentParent = CurrentChild; - CurrentChild = CurrentParent->Get_Child(); - } -} - - -void CProfileIterator::Enter_Parent( void ) -{ - if ( CurrentParent->Get_Parent() != NULL ) { - CurrentParent = CurrentParent->Get_Parent(); - } - CurrentChild = CurrentParent->Get_Child(); -} - - -/*************************************************************************************************** -** -** CProfileManager -** -***************************************************************************************************/ - -CProfileNode CProfileManager::Root( "Root", NULL ); -CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; -int CProfileManager::FrameCounter = 0; -unsigned long int CProfileManager::ResetTime = 0; - - -/*********************************************************************************************** - * CProfileManager::Start_Profile -- Begin a named profile * - * * - * Steps one level deeper into the tree, if a child already exists with the specified name * - * then it accumulates the profiling; otherwise a new child node is added to the profile tree. * - * * - * INPUT: * - * name - name of this profiling record * - * * - * WARNINGS: * - * The string used is assumed to be a static string; pointer compares are used throughout * - * the profiling code for efficiency. * - *=============================================================================================*/ -void CProfileManager::Start_Profile( const char * name ) -{ - if (name != CurrentNode->Get_Name()) { - CurrentNode = CurrentNode->Get_Sub_Node( name ); - } - - CurrentNode->Call(); -} - - -/*********************************************************************************************** - * CProfileManager::Stop_Profile -- Stop timing and record the results. * - *=============================================================================================*/ -void CProfileManager::Stop_Profile( void ) -{ - // Return will indicate whether we should back up to our parent (we may - // be profiling a recursive function) - if (CurrentNode->Return()) { - CurrentNode = CurrentNode->Get_Parent(); - } -} - - -/*********************************************************************************************** - * CProfileManager::Reset -- Reset the contents of the profiling system * - * * - * This resets everything except for the tree structure. All of the timing data is reset. * - *=============================================================================================*/ -void CProfileManager::Reset( void ) -{ - Root.Reset(); - Root.Call(); - FrameCounter = 0; - Profile_Get_Ticks(&ResetTime); -} - - -/*********************************************************************************************** - * CProfileManager::Increment_Frame_Counter -- Increment the frame counter * - *=============================================================================================*/ -void CProfileManager::Increment_Frame_Counter( void ) -{ - FrameCounter++; -} - - -/*********************************************************************************************** - * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset * - *=============================================================================================*/ -float CProfileManager::Get_Time_Since_Reset( void ) -{ - unsigned long int time; - Profile_Get_Ticks(&time); - time -= ResetTime; - return (float)time / Profile_Get_Tick_Rate(); -} - -#endif //USE_BT_CLOCK - +// Note: We must declare these private static variables again here to +// avoid link errors. +bool btProfiler::mEnabled = false; +btClock btProfiler::mClock; +unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0; +unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0; +std::map btProfiler::mProfileBlocks; +std::ofstream btProfiler::mOutputFile; +bool btProfiler::mFirstFileOutput = true; +btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; +unsigned long int btProfiler::mCycleNumber = 0; +#endif //USE_QUICKPROF diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h index b033940ca5c..a885967c5fa 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.h +++ b/extern/bullet2/src/LinearMath/btQuickprof.h @@ -1,11 +1,20 @@ +/* +Copyright (c) 2006 Tyler Streeter -/*************************************************************************************************** -** -** Real-Time Hierarchical Profiling for Game Programming Gems 3 -** -** by Greg Hjelstrom & Byon Garrabrant -** -***************************************************************************************************/ +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +*/ + +// Please visit the project website (http://quickprof.sourceforge.net) +// for usage instructions. // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). @@ -14,10 +23,9 @@ #define QUICK_PROF_H #include "btScalar.h" -#include "LinearMath/btAlignedAllocator.h" -#include -//To disable built-in profiling, please comment out next line -//#define BT_NO_PROFILE 1 + +//#define USE_QUICKPROF 1 +//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes. //if you don't need btClock, you can comment next line @@ -26,332 +34,678 @@ #ifdef USE_BT_CLOCK #ifdef __CELLOS_LV2__ #include -#include #include +typedef uint64_t __int64; #endif #if defined (SUNOS) || defined (__SUNOS__) -#include + #include #endif #if defined(WIN32) || defined(_WIN32) -#define USE_WINDOWS_TIMERS -#define WIN32_LEAN_AND_MEAN -#define NOWINRES -#define NOMCX -#define NOIME + #define USE_WINDOWS_TIMERS + #define WIN32_LEAN_AND_MEAN + #define NOWINRES + #define NOMCX + #define NOIME #ifdef _XBOX -#include + #include #else -#include + #include #endif -#include + #include #else -#include + #include #endif #define mymin(a,b) (a > b ? a : b) -///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. +/// basic clock class btClock -{ -public: - btClock() { -#ifdef USE_WINDOWS_TIMERS - QueryPerformanceFrequency(&mClockFrequency); -#endif - reset(); - } - - ~btClock() - { - } - - /// Resets the initial reference time. - void reset() - { -#ifdef USE_WINDOWS_TIMERS - QueryPerformanceCounter(&mStartTime); - mStartTick = GetTickCount(); - mPrevElapsedTime = 0; -#else -#ifdef __CELLOS_LV2__ - - typedef uint64_t ClockSize; - ClockSize newTime; - //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - SYS_TIMEBASE_GET( newTime ); - mStartTime = newTime; -#else - gettimeofday(&mStartTime, 0); -#endif - -#endif - } - - /// Returns the time in ms since the last call to reset or since - /// the btClock was created. - unsigned long int getTimeMilliseconds() - { -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; - - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) + public: + btClock() { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - - // Recompute the number of millisecond ticks elapsed. - msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); +#ifdef USE_WINDOWS_TIMERS + QueryPerformanceFrequency(&mClockFrequency); +#endif + reset(); } - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; + ~btClock() + { + } - return msecTicks; + /// Resets the initial reference time. + void reset() + { +#ifdef USE_WINDOWS_TIMERS + QueryPerformanceCounter(&mStartTime); + mStartTick = GetTickCount(); + mPrevElapsedTime = 0; #else - #ifdef __CELLOS_LV2__ - uint64_t freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq) / 1000.0; - typedef uint64_t ClockSize; - ClockSize newTime; - SYS_TIMEBASE_GET( newTime ); - //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - return (unsigned long int)((double(newTime-mStartTime)) / dFreq); + typedef uint64_t __int64; + typedef __int64 ClockSize; + ClockSize newTime; + __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + mStartTime = newTime; +#else + gettimeofday(&mStartTime, 0); +#endif + +#endif + } + + /// Returns the time in ms since the last call to reset or since + /// the btClock was created. + unsigned long int getTimeMilliseconds() + { +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + + // Recompute the number of millisecond ticks elapsed. + msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + } + + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; + + return msecTicks; +#else + +#ifdef __CELLOS_LV2__ + __int64 freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq) / 1000.0; + typedef uint64_t __int64; + typedef __int64 ClockSize; + ClockSize newTime; + __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (newTime-mStartTime) / dFreq; #else - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + - (currentTime.tv_usec - mStartTime.tv_usec) / 1000; + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + + (currentTime.tv_usec - mStartTime.tv_usec) / 1000; #endif //__CELLOS_LV2__ #endif - } - - /// Returns the time in us since the last call to reset or since - /// the Clock was created. - unsigned long int getTimeMicroseconds() - { -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; - - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; } - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds() + { +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; - // Convert to microseconds. - unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / - mClockFrequency.QuadPart); + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); - return usecTicks; + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + } + + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; + + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + mClockFrequency.QuadPart); + + return usecTicks; #else #ifdef __CELLOS_LV2__ - uint64_t freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq)/ 1000000.0; - typedef uint64_t ClockSize; - ClockSize newTime; - //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - SYS_TIMEBASE_GET( newTime ); - - return (unsigned long int)((double(newTime-mStartTime)) / dFreq); + __int64 freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t __int64; + typedef __int64 ClockSize; + ClockSize newTime; + __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (newTime-mStartTime) / dFreq; #else - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + - (currentTime.tv_usec - mStartTime.tv_usec); + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + + (currentTime.tv_usec - mStartTime.tv_usec); #endif//__CELLOS_LV2__ #endif - } + } -private: + private: #ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER mClockFrequency; - DWORD mStartTick; - LONGLONG mPrevElapsedTime; - LARGE_INTEGER mStartTime; + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; #else #ifdef __CELLOS_LV2__ - uint64_t mStartTime; + uint64_t mStartTime; #else - struct timeval mStartTime; + struct timeval mStartTime; #endif #endif //__CELLOS_LV2__ -}; + }; #endif //USE_BT_CLOCK +#ifdef USE_QUICKPROF -///A node in the Profile Hierarchy Tree -class CProfileNode { +#include +#include +#include +#include -public: - CProfileNode( const char * name, CProfileNode * parent ); - ~CProfileNode( void ); - CProfileNode * Get_Sub_Node( const char * name ); - CProfileNode * Get_Parent( void ) { return Parent; } - CProfileNode * Get_Sibling( void ) { return Sibling; } - CProfileNode * Get_Child( void ) { return Child; } - void CleanupMemory(); - void Reset( void ); - void Call( void ); - bool Return( void ); +namespace hidden +{ + /// A simple data structure representing a single timed block + /// of code. + struct ProfileBlock + { + ProfileBlock() + { + currentBlockStartMicroseconds = 0; + currentCycleTotalMicroseconds = 0; + lastCycleTotalMicroseconds = 0; + totalMicroseconds = 0; + } - const char * Get_Name( void ) { return Name; } - int Get_Total_Calls( void ) { return TotalCalls; } - float Get_Total_Time( void ) { return TotalTime; } + /// The starting time (in us) of the current block update. + unsigned long int currentBlockStartMicroseconds; -protected: + /// The accumulated time (in us) spent in this block during the + /// current profiling cycle. + unsigned long int currentCycleTotalMicroseconds; - const char * Name; - int TotalCalls; - float TotalTime; - unsigned long int StartTime; - int RecursionCounter; + /// The accumulated time (in us) spent in this block during the + /// past profiling cycle. + unsigned long int lastCycleTotalMicroseconds; + + /// The total accumulated time (in us) spent in this block. + unsigned long int totalMicroseconds; + }; - CProfileNode * Parent; - CProfileNode * Child; - CProfileNode * Sibling; }; -///An iterator to navigate through the tree -class CProfileIterator +/// A static class that manages timing for a set of profiling blocks. +class btProfiler { public: - // Access all the children of the current parent - void First(void); - void Next(void); - bool Is_Done(void); - bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } - - void Enter_Child( int index ); // Make the given child the new parent - void Enter_Largest_Child( void ); // Make the largest child the new parent - void Enter_Parent( void ); // Make the current parent's parent the new parent - - // Access the current child - const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } - int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } - float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } - - // Access the current parent - const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } - int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } - float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } - -protected: - - CProfileNode * CurrentParent; - CProfileNode * CurrentChild; - - CProfileIterator( CProfileNode * start ); - friend class CProfileManager; -}; - - -///The Manager for the Profile system -class CProfileManager { -public: - static void Start_Profile( const char * name ); - static void Stop_Profile( void ); - - static void CleanupMemory(void) + /// A set of ways to retrieve block timing data. + enum BlockTimingMethod { - Root.CleanupMemory(); + /// The total time spent in the block (in seconds) since the + /// profiler was initialized. + BLOCK_TOTAL_SECONDS, + + /// The total time spent in the block (in ms) since the + /// profiler was initialized. + BLOCK_TOTAL_MILLISECONDS, + + /// The total time spent in the block (in us) since the + /// profiler was initialized. + BLOCK_TOTAL_MICROSECONDS, + + /// The total time spent in the block, as a % of the total + /// elapsed time since the profiler was initialized. + BLOCK_TOTAL_PERCENT, + + /// The time spent in the block (in seconds) in the most recent + /// profiling cycle. + BLOCK_CYCLE_SECONDS, + + /// The time spent in the block (in ms) in the most recent + /// profiling cycle. + BLOCK_CYCLE_MILLISECONDS, + + /// The time spent in the block (in us) in the most recent + /// profiling cycle. + BLOCK_CYCLE_MICROSECONDS, + + /// The time spent in the block (in seconds) in the most recent + /// profiling cycle, as a % of the total cycle time. + BLOCK_CYCLE_PERCENT + }; + + /// Initializes the profiler. This must be called first. If this is + /// never called, the profiler is effectively disabled; all other + /// functions will return immediately. The first parameter + /// is the name of an output data file; if this string is not empty, + /// data will be saved on every profiling cycle; if this string is + /// empty, no data will be saved to a file. The second parameter + /// determines which timing method is used when printing data to the + /// output file. + inline static void init(const std::string outputFilename="", + BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS); + + /// Cleans up allocated memory. + inline static void destroy(); + + /// Begins timing the named block of code. + inline static void beginBlock(const std::string& name); + + /// Updates the accumulated time spent in the named block by adding + /// the elapsed time since the last call to startBlock for this block + /// name. + inline static void endBlock(const std::string& name); + + /// Returns the time spent in the named block according to the + /// given timing method. See comments on BlockTimingMethod for details. + inline static double getBlockTime(const std::string& name, + BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS); + + /// Defines the end of a profiling cycle. Use this regularly if you + /// want to generate detailed timing information. This must not be + /// called within a timing block. + inline static void endProfilingCycle(); + + /// A helper function that creates a string of statistics for + /// each timing block. This is mainly for printing an overall + /// summary to the command line. + inline static std::string createStatsString( + BlockTimingMethod method=BLOCK_TOTAL_PERCENT); + +//private: + inline btProfiler(); + + inline ~btProfiler(); + + /// Prints an error message to standard output. + inline static void printError(const std::string& msg) + { + //btAssert(0); + std::cout << "[QuickProf error] " << msg << std::endl; } - static void Reset( void ); - static void Increment_Frame_Counter( void ); - static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } - static float Get_Time_Since_Reset( void ); + /// Determines whether the profiler is enabled. + static bool mEnabled; - static CProfileIterator * Get_Iterator( void ) - { - - return new CProfileIterator( &Root ); - } - static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } + /// The clock used to time profile blocks. + static btClock mClock; -private: - static CProfileNode Root; - static CProfileNode * CurrentNode; - static int FrameCounter; - static unsigned long int ResetTime; + /// The starting time (in us) of the current profiling cycle. + static unsigned long int mCurrentCycleStartMicroseconds; + + /// The duration (in us) of the most recent profiling cycle. + static unsigned long int mLastCycleDurationMicroseconds; + + /// Internal map of named profile blocks. + static std::map mProfileBlocks; + + /// The data file used if this feature is enabled in 'init.' + static std::ofstream mOutputFile; + + /// Tracks whether we have begun print data to the output file. + static bool mFirstFileOutput; + + /// The method used when printing timing data to an output file. + static BlockTimingMethod mFileOutputMethod; + + /// The number of the current profiling cycle. + static unsigned long int mCycleNumber; }; -///ProfileSampleClass is a simple way to profile a function's scope -///Use the BT_PROFILE macro at the start of scope to time -class CProfileSample { -public: - CProfileSample( const char * name ) - { - CProfileManager::Start_Profile( name ); +btProfiler::btProfiler() +{ + // This never gets called because a btProfiler instance is never + // created. +} + +btProfiler::~btProfiler() +{ + // This never gets called because a btProfiler instance is never + // created. +} + +void btProfiler::init(const std::string outputFilename, + BlockTimingMethod outputMethod) +{ + mEnabled = true; + + if (!outputFilename.empty()) + { + mOutputFile.open(outputFilename.c_str()); } - ~CProfileSample( void ) - { - CProfileManager::Stop_Profile(); + mFileOutputMethod = outputMethod; + + mClock.reset(); + + // Set the start time for the first cycle. + mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); +} + +void btProfiler::destroy() +{ + if (!mEnabled) + { + return; } -}; -#if !defined(BT_NO_PROFILE) -#define BT_PROFILE( name ) CProfileSample __profile( name ) -#else -#define BT_PROFILE( name ) -#endif + if (mOutputFile.is_open()) + { + mOutputFile.close(); + } + + // Destroy all ProfileBlocks. + while (!mProfileBlocks.empty()) + { + delete (*mProfileBlocks.begin()).second; + mProfileBlocks.erase(mProfileBlocks.begin()); + } +} + +void btProfiler::beginBlock(const std::string& name) +{ + if (!mEnabled) + { + return; + } + + if (name.empty()) + { + printError("Cannot allow unnamed profile blocks."); + return; + } + + hidden::ProfileBlock* block = mProfileBlocks[name]; + + if (!block) + { + // Create a new ProfileBlock. + mProfileBlocks[name] = new hidden::ProfileBlock(); + block = mProfileBlocks[name]; + } + + // We do this at the end to get more accurate results. + block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds(); +} + +void btProfiler::endBlock(const std::string& name) +{ + if (!mEnabled) + { + return; + } + + // We do this at the beginning to get more accurate results. + unsigned long int endTick = mClock.getTimeMicroseconds(); + + hidden::ProfileBlock* block = mProfileBlocks[name]; + + if (!block) + { + // The named block does not exist. Print an error. + printError("The profile block named '" + name + + "' does not exist."); + return; + } + + unsigned long int blockDuration = endTick - + block->currentBlockStartMicroseconds; + block->currentCycleTotalMicroseconds += blockDuration; + block->totalMicroseconds += blockDuration; +} + +double btProfiler::getBlockTime(const std::string& name, + BlockTimingMethod method) +{ + if (!mEnabled) + { + return 0; + } + + hidden::ProfileBlock* block = mProfileBlocks[name]; + + if (!block) + { + // The named block does not exist. Print an error. + printError("The profile block named '" + name + + "' does not exist."); + return 0; + } + + double result = 0; + + switch(method) + { + case BLOCK_TOTAL_SECONDS: + result = (double)block->totalMicroseconds * (double)0.000001; + break; + case BLOCK_TOTAL_MILLISECONDS: + result = (double)block->totalMicroseconds * (double)0.001; + break; + case BLOCK_TOTAL_MICROSECONDS: + result = (double)block->totalMicroseconds; + break; + case BLOCK_TOTAL_PERCENT: + { + double timeSinceInit = (double)mClock.getTimeMicroseconds(); + if (timeSinceInit <= 0) + { + result = 0; + } + else + { + result = 100.0 * (double)block->totalMicroseconds / + timeSinceInit; + } + break; + } + case BLOCK_CYCLE_SECONDS: + result = (double)block->lastCycleTotalMicroseconds * + (double)0.000001; + break; + case BLOCK_CYCLE_MILLISECONDS: + result = (double)block->lastCycleTotalMicroseconds * + (double)0.001; + break; + case BLOCK_CYCLE_MICROSECONDS: + result = (double)block->lastCycleTotalMicroseconds; + break; + case BLOCK_CYCLE_PERCENT: + { + if (0 == mLastCycleDurationMicroseconds) + { + // We have not yet finished a cycle, so just return zero + // percent to avoid a divide by zero error. + result = 0; + } + else + { + result = 100.0 * (double)block->lastCycleTotalMicroseconds / + mLastCycleDurationMicroseconds; + } + break; + } + default: + break; + } + + return result; +} + +void btProfiler::endProfilingCycle() +{ + if (!mEnabled) + { + return; + } + + // Store the duration of the cycle that just finished. + mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() - + mCurrentCycleStartMicroseconds; + + // For each block, update data for the cycle that just finished. + std::map::iterator iter; + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) + { + hidden::ProfileBlock* block = (*iter).second; + block->lastCycleTotalMicroseconds = + block->currentCycleTotalMicroseconds; + block->currentCycleTotalMicroseconds = 0; + } + + if (mOutputFile.is_open()) + { + // Print data to the output file. + if (mFirstFileOutput) + { + // On the first iteration, print a header line that shows the + // names of each profiling block. + mOutputFile << "#cycle, "; + + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); + ++iter) + { + mOutputFile << (*iter).first << ", "; + } + + mOutputFile << std::endl; + mFirstFileOutput = false; + } + + mOutputFile << mCycleNumber << ", "; + + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); + ++iter) + { + mOutputFile << getBlockTime((*iter).first, mFileOutputMethod) + << ", "; + } + + mOutputFile << std::endl; + } + + ++mCycleNumber; + mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); +} + +std::string btProfiler::createStatsString(BlockTimingMethod method) +{ + if (!mEnabled) + { + return ""; + } + + std::string s; + std::string suffix; + + switch(method) + { + case BLOCK_TOTAL_SECONDS: + suffix = "s"; + break; + case BLOCK_TOTAL_MILLISECONDS: + suffix = "ms"; + break; + case BLOCK_TOTAL_MICROSECONDS: + suffix = "us"; + break; + case BLOCK_TOTAL_PERCENT: + { + suffix = "%"; + break; + } + case BLOCK_CYCLE_SECONDS: + suffix = "s"; + break; + case BLOCK_CYCLE_MILLISECONDS: + suffix = "ms"; + break; + case BLOCK_CYCLE_MICROSECONDS: + suffix = "us"; + break; + case BLOCK_CYCLE_PERCENT: + { + suffix = "%"; + break; + } + default: + break; + } + + std::map::iterator iter; + for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) + { + if (iter != mProfileBlocks.begin()) + { + s += "\n"; + } + + char blockTime[64]; + sprintf(blockTime, "%lf", getBlockTime((*iter).first, method)); + + s += (*iter).first; + s += ": "; + s += blockTime; + s += " "; + s += suffix; + } + + return s; +} +#define BEGIN_PROFILE(a) btProfiler::beginBlock(a) +#define END_PROFILE(a) btProfiler::endBlock(a) +#else //USE_QUICKPROF +#define BEGIN_PROFILE(a) +#define END_PROFILE(a) + +#endif //USE_QUICKPROF #endif //QUICK_PROF_H diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 3c96857d4eb..01ad93e786a 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -18,123 +18,57 @@ subject to the following restrictions: #define SIMD___SCALAR_H #include -#include //size_t for MSVC 6.0 #include #include #include -#define BT_BULLET_VERSION 272 - -inline int btGetVersion() -{ - return BT_BULLET_VERSION; -} - -#if defined(DEBUG) || defined (_DEBUG) -#define BT_DEBUG -#endif - - #ifdef WIN32 #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) - #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a - #define ATTRIBUTE_ALIGNED128(a) a #else - #define BT_HAS_ALIGNED_ALLOCATOR - #pragma warning(disable : 4324) // disable padding warning -// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. -// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines -// #pragma warning(disable:4786) // Disable the "debug name too long" warning - + #define BT_HAS_ALIGNED_ALOCATOR + #pragma warning(disable:4530) + #pragma warning(disable:4996) + #pragma warning(disable:4786) #define SIMD_FORCE_INLINE __forceinline #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a - #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a #ifdef _XBOX #define BT_USE_VMX128 - - #include - #define BT_HAVE_NATIVE_FSEL - #define btFsel(a,b,c) __fsel((a),(b),(c)) #else #define BT_USE_SSE #endif #endif //__MINGW32__ #include -#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert -#else - #define btAssert(x) -#endif //btFullAssert is optional, slows down a lot #define btFullAssert(x) - - #define btLikely(_c) _c - #define btUnlikely(_c) _c - #else #if defined (__CELLOS_LV2__) #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) - #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) #ifndef assert #include #endif #define btAssert assert //btFullAssert is optional, slows down a lot #define btFullAssert(x) - - #define btLikely(_c) _c - #define btUnlikely(_c) _c - #else -#ifdef USE_LIBSPE2 - - #define SIMD_FORCE_INLINE __inline - #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) - #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) - #ifndef assert - #include - #endif - #define btAssert assert - //btFullAssert is optional, slows down a lot - #define btFullAssert(x) - - - #define btLikely(_c) __builtin_expect((_c), 1) - #define btUnlikely(_c) __builtin_expect((_c), 0) - - -#else //non-windows systems #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a - #define ATTRIBUTE_ALIGNED128(a) a #ifndef assert #include #endif - -#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert -#else - #define btAssert(x) -#endif - //btFullAssert is optional, slows down a lot #define btFullAssert(x) - #define btLikely(_c) _c - #define btUnlikely(_c) _c - - -#endif // LIBSPE2 - #endif //__CELLOS_LV2__ #endif @@ -147,7 +81,6 @@ inline int btGetVersion() #endif #endif -///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. #if defined(BT_USE_DOUBLE_PRECISION) typedef double btScalar; #else @@ -155,19 +88,6 @@ typedef float btScalar; #endif - -#define BT_DECLARE_ALIGNED_ALLOCATOR() \ - SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ - SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ - SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ - SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ - SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ - SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ - SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ - SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ - - - #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } @@ -185,34 +105,12 @@ SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } #else -SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) -{ -#ifdef USE_APPROXIMATION - double x, z, tempf; - unsigned long *tfptr = ((unsigned long *)&tempf) + 1; - - tempf = y; - *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ - x = tempf; - z = y*btScalar(0.5); /* hoist out the “/2” */ - x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ - x = (btScalar(1.5)*x)-(x*x)*(x*z); - x = (btScalar(1.5)*x)-(x*x)*(x*z); - x = (btScalar(1.5)*x)-(x*x)*(x*z); - x = (btScalar(1.5)*x)-(x*x)*(x*z); - return x*y; -#else - return sqrtf(y); -#endif -} +SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrtf(x); } SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { - btAssert(x <= btScalar(1.)); - return acosf(x); -} +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } @@ -261,6 +159,14 @@ SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { return (!((a) <= eps)); } +/*SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } +SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } +SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } +SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } +SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } +SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } +*/ SIMD_FORCE_INLINE int btIsNegative(btScalar x) { return x < btScalar(0.0) ? 1 : 0; @@ -271,151 +177,5 @@ SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name -#ifndef btFsel -SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) -{ - return a >= 0 ? b : c; -} -#endif -#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) - - -SIMD_FORCE_INLINE bool btMachineIsLittleEndian() -{ - long int i = 1; - const char *p = (const char *) &i; - if (p[0] == 1) // Lowest address contains the least significant byte - return true; - else - return false; -} - - - -///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 -///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html -SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) -{ - // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero - // Rely on positive value or'ed with its negative having sign bit on - // and zero value or'ed with its negative (which is still zero) having sign bit off - // Use arithmetic shift right, shifting the sign bit through all 32 bits - unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); - unsigned testEqz = ~testNz; - return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); -} -SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) -{ - unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); - unsigned testEqz = ~testNz; - return static_cast((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); -} -SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) -{ -#ifdef BT_HAVE_NATIVE_FSEL - return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); -#else - return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; -#endif -} - -template SIMD_FORCE_INLINE void btSwap(T& a, T& b) -{ - T tmp = a; - a = b; - b = tmp; -} - - -//PCK: endian swapping functions -SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) -{ - return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); -} - -SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) -{ - return static_cast(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); -} - -SIMD_FORCE_INLINE unsigned btSwapEndian(int val) -{ - return btSwapEndian((unsigned)val); -} - -SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) -{ - return btSwapEndian((unsigned short) val); -} - -///btSwapFloat uses using char pointers to swap the endianness -////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values -///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. -///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. -///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. -///so instead of returning a float/double, we return integer/long long integer -SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) -{ - unsigned int a = 0; - unsigned char *dst = (unsigned char *)&a; - unsigned char *src = (unsigned char *)&d; - - dst[0] = src[3]; - dst[1] = src[2]; - dst[2] = src[1]; - dst[3] = src[0]; - return a; -} - -// unswap using char pointers -SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) -{ - float d = 0.0f; - unsigned char *src = (unsigned char *)&a; - unsigned char *dst = (unsigned char *)&d; - - dst[0] = src[3]; - dst[1] = src[2]; - dst[2] = src[1]; - dst[3] = src[0]; - - return d; -} - - -// swap using char pointers -SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) -{ - unsigned char *src = (unsigned char *)&d; - - dst[0] = src[7]; - dst[1] = src[6]; - dst[2] = src[5]; - dst[3] = src[4]; - dst[4] = src[3]; - dst[5] = src[2]; - dst[6] = src[1]; - dst[7] = src[0]; - -} - -// unswap using char pointers -SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) -{ - double d = 0.0; - unsigned char *dst = (unsigned char *)&d; - - dst[0] = src[7]; - dst[1] = src[6]; - dst[2] = src[5]; - dst[3] = src[4]; - dst[4] = src[3]; - dst[5] = src[2]; - dst[6] = src[1]; - dst[7] = src[0]; - - return d; -} - #endif //SIMD___SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h index 050d44bdfe9..d219b453537 100644 --- a/extern/bullet2/src/LinearMath/btStackAlloc.h +++ b/extern/bullet2/src/LinearMath/btStackAlloc.h @@ -21,7 +21,6 @@ Nov.2006 #define BT_STACK_ALLOC #include "btScalar.h" //for btAssert -#include "btAlignedAllocator.h" struct btBlock { @@ -29,7 +28,7 @@ struct btBlock unsigned char* address; }; -///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out) +///StackAlloc provides some fast stack-based memory allocator (LIFO last-in first-out) class btStackAlloc { public: @@ -40,7 +39,7 @@ public: inline void create(unsigned int size) { destroy(); - data = (unsigned char*) btAlignedAlloc(size,16); + data = new unsigned char[size]; totalsize = size; } inline void destroy() @@ -50,20 +49,12 @@ public: if(usedsize==0) { - if(!ischild && data) - btAlignedFree(data); - + if(!ischild) delete[] data; data = 0; usedsize = 0; } } - - int getAvailableMemory() const - { - return static_cast(totalsize - usedsize); - } - unsigned char* allocate(unsigned int size) { const unsigned int nus(usedsize+size); @@ -77,7 +68,7 @@ public: return(0); } - SIMD_FORCE_INLINE btBlock* beginBlock() + inline btBlock* beginBlock() { btBlock* pb = (btBlock*)allocate(sizeof(btBlock)); pb->previous = current; @@ -85,7 +76,7 @@ public: current = pb; return(pb); } - SIMD_FORCE_INLINE void endBlock(btBlock* block) + inline void endBlock(btBlock* block) { btAssert(block==current); //Raise(L"Unmatched blocks"); diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h index a8cdb428100..2d55fec83a4 100644 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -21,8 +21,7 @@ subject to the following restrictions: #include "btMatrix3x3.h" -///The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear. -///It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. +///btTransform supports rigid transforms (only translation and rotation, no scaling/shear) class btTransform { @@ -93,7 +92,13 @@ public: m_basis.getRotation(q); return q; } - + template + void setValue(const Scalar2 *m) + { + m_basis.setValue(m); + m_origin.setValue(&m[12]); + } + void setFromOpenGLMatrix(const btScalar *m) { @@ -189,13 +194,8 @@ btTransform::operator*(const btTransform& t) const { return btTransform(m_basis * t.m_basis, (*this)(t.m_origin)); -} +} -SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) -{ - return ( t1.getBasis() == t2.getBasis() && - t1.getOrigin() == t2.getOrigin() ); -} #endif @@ -204,4 +204,3 @@ SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) - diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h index 86ee1da5edf..bc42fd166b6 100644 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -25,7 +25,7 @@ subject to the following restrictions: #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ -SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) { return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), @@ -33,7 +33,7 @@ SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btV } -SIMD_FORCE_INLINE void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) +inline void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) { if (btFabs(n.z()) > SIMDSQRT12) { // choose p in y-z plane @@ -70,9 +70,7 @@ public: predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); predictedOrn.normalize(); #else - //Exponential map - //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia - + //exponential map btVector3 axis; btScalar fAngle = angvel.length(); //limit the angular motion @@ -123,10 +121,6 @@ public: dmat.getRotation(dorn); #endif//USE_QUATERNION_DIFF - ///floating point inaccuracy can lead to w component > 1..., which breaks - - dorn.normalize(); - angle = dorn.getAngle(); axis = btVector3(dorn.x(),dorn.y(),dorn.z()); axis[3] = btScalar(0.); diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h index 96548c6ba60..74d41ad2a19 100644 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -27,10 +27,6 @@ class btVector3 : public btQuadWord { public: SIMD_FORCE_INLINE btVector3() {} - SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q) - : btQuadWord(q) - { - } SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) @@ -47,7 +43,6 @@ public: SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) { - m_x += v.x(); m_y += v.y(); m_z += v.z(); return *this; } @@ -404,50 +399,4 @@ public: }; - -///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization -SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) -{ - #ifdef BT_USE_DOUBLE_PRECISION - unsigned char* dest = (unsigned char*) &destVal; - unsigned char* src = (unsigned char*) &sourceVal; - dest[0] = src[7]; - dest[1] = src[6]; - dest[2] = src[5]; - dest[3] = src[4]; - dest[4] = src[3]; - dest[5] = src[2]; - dest[6] = src[1]; - dest[7] = src[0]; -#else - unsigned char* dest = (unsigned char*) &destVal; - unsigned char* src = (unsigned char*) &sourceVal; - dest[0] = src[3]; - dest[1] = src[2]; - dest[2] = src[1]; - dest[3] = src[0]; -#endif //BT_USE_DOUBLE_PRECISION -} -///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization -SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) -{ - for (int i=0;i<4;i++) - { - btSwapScalarEndian(sourceVec[i],destVec[i]); - } - -} - -///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization -SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) -{ - - btVector3 swappedVec; - for (int i=0;i<4;i++) - { - btSwapScalarEndian(vector[i],swappedVec[i]); - } - vector = swappedVec; -} - #endif //SIMD__VECTOR3_H diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 59b823982f5..19702782b0d 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -22,11 +22,74 @@ elif sys.platform=='darwin': cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] linearmath_src = env.Glob("LinearMath/*.cpp") - -bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") - -collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") -collision_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") +bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", + "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", + "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", + "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", + "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", + "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", + "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", + "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", + "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp", + "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp", + "BulletDynamics/Dynamics/btRigidBody.cpp", + "BulletDynamics/Vehicle/btRaycastVehicle.cpp", + "BulletDynamics/Dynamics/Bullet-C-API.cpp", + "BulletDynamics/Vehicle/btWheelInfo.cpp"] +collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp", + "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", + "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", + "BulletCollision/BroadphaseCollision/btDispatcher.cpp", + "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", + "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", + "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", + "BulletCollision/CollisionDispatch/btCollisionObject.cpp", + "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", + "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", + "BulletCollision/CollisionDispatch/btManifoldResult.cpp", + "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", + "BulletCollision/CollisionDispatch/btUnionFind.cpp", + "BulletCollision/CollisionShapes/btBoxShape.cpp", + "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btCollisionShape.cpp", + "BulletCollision/CollisionShapes/btCompoundShape.cpp", + "BulletCollision/CollisionShapes/btConcaveShape.cpp", + "BulletCollision/CollisionShapes/btConeShape.cpp", + "BulletCollision/CollisionShapes/btConvexHullShape.cpp", + "BulletCollision/CollisionShapes/btConvexShape.cpp", + "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btCylinderShape.cpp", + "BulletCollision/CollisionShapes/btEmptyShape.cpp", + "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", + "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", + "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", + "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", + "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", + "BulletCollision/CollisionShapes/btSphereShape.cpp", + "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", + "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", + "BulletCollision/CollisionShapes/btTriangleCallback.cpp", + "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", + "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", + "BulletCollision/CollisionShapes/btTriangleMesh.cpp", + "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", + "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", + "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", + "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", + "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", + "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", + "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", + "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"] incs = '. BulletCollision BulletDynamics LinearMath' diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h index 4b14f6d00f3..8417ccc671f 100644 --- a/extern/bullet2/src/btBulletCollisionCommon.h +++ b/extern/bullet2/src/btBulletCollisionCommon.h @@ -32,28 +32,23 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexHullShape.h" #include "BulletCollision/CollisionShapes/btTriangleMesh.h" #include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btTetrahedronShape.h" #include "BulletCollision/CollisionShapes/btEmptyShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" -#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" ///Narrowphase Collision Detector #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" - -//btSphereBoxCollisionAlgorithm is broken, use gjk for now -//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" ///Dispatching and generation of collision pairs (broadphase) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" -#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" -#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" + ///Math library & Utils #include "LinearMath/btQuaternion.h" diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h index b95972cd15d..25f016cba8a 100644 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -20,8 +20,6 @@ subject to the following restrictions: #include "btBulletCollisionCommon.h" #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" -#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h" - #include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -29,11 +27,9 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" -#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" + #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" - - ///Vehicle simulation, with wheel contact simulated by raycasts #include "BulletDynamics/Vehicle/btRaycastVehicle.h" diff --git a/extern/glew/SConscript b/extern/glew/SConscript index 3badbeb040e..32b3b478113 100644 --- a/extern/glew/SConscript +++ b/extern/glew/SConscript @@ -9,4 +9,4 @@ sources = ['src/glew.c'] defs = '' incs = 'include' -env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['blender', 'player'], priority=[50, 50]) +env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['intern', 'player'], priority=[25, 50]) diff --git a/extern/glew/include/GL/glew.h b/extern/glew/include/GL/glew.h index 6b88e6eb4c9..fd3fe10b938 100644 --- a/extern/glew/include/GL/glew.h +++ b/extern/glew/include/GL/glew.h @@ -58,11 +58,8 @@ ** version 1.2.1 Specification. */ -#define BLENDER_CHANGES - -#ifdef BLENDER_CHANGES +/* added this here for blender, should be moved elsewhere */ #define GLEW_STATIC -#endif #ifndef __glew_h__ #define __glew_h__ @@ -1808,7 +1805,6 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuin typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); -#ifndef BLENDER_CHANGES #define glAttachShader GLEW_GET_FUN(__glewAttachShader) #define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) #define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) @@ -1902,7 +1898,6 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint si #define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) #define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) #define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) -#endif #define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) diff --git a/extern/glew/src/glew.c b/extern/glew/src/glew.c index f20463630dc..593f0e58f7c 100644 --- a/extern/glew/src/glew.c +++ b/extern/glew/src/glew.c @@ -1836,7 +1836,6 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; -#ifndef BLENDER_CHANGES r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r; r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r; r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r; @@ -1930,7 +1929,6 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r; r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r; r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r; -#endif return r; } diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h index 450fde187b5..5d425a8dc94 100644 --- a/intern/SoundSystem/SoundDefines.h +++ b/intern/SoundSystem/SoundDefines.h @@ -44,7 +44,7 @@ enum /* general stuff */ #define NUM_BUFFERS 128 -#define NUM_SOURCES 24 /* 24 is the limit for openal on windows, was 16 in 2.47 and previous */ +#define NUM_SOURCES 16 /* openal related stuff */ #define AL_LOOPING 0x1007 diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp index c660e9aecba..82ed1c8a808 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.cpp +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -294,10 +294,6 @@ SND_OpenALDevice::SND_OpenALDevice() // let openal generate its sources if (alc_error == ALC_NO_ERROR) { - int i; - - for (i=0;i" because it conflits with Window defined in winlay.h -typedef int GHOST_TEmbedderWindowID; -#endif // _WIN32 - /** * A timer task callback routine. * @param task The timer task object. diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index 067c8deee32..78c25997806 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -402,8 +402,7 @@ GHOST_IWindow* GHOST_SystemCarbon::createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual, - const GHOST_TEmbedderWindowID parentWindow + bool stereoVisual ) { GHOST_IWindow* window = 0; diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h index 2a1d6325784..2afc8e0885a 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -103,7 +103,6 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. - * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( @@ -114,8 +113,7 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, - const GHOST_TEmbedderWindowID parentWindow = 0 + const bool stereoVisual ); /*************************************************************************************** diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index feb0fe39040..f5c7c08ebfe 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -169,7 +169,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow ) + bool stereoVisual) { GHOST_Window* window = 0; window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual); @@ -917,12 +917,8 @@ GHOST_TUns8* GHOST_SystemWin32::getClipboard(int flag) const char *buffer; char *temp_buff; - if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) { + if ( OpenClipboard(NULL) ) { HANDLE hData = GetClipboardData( CF_TEXT ); - if (hData == NULL) { - CloseClipboard(); - return NULL; - } buffer = (char*)GlobalLock( hData ); temp_buff = (char*) malloc(strlen(buffer)+1); diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 00f7af00162..c26ef25e366 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -109,14 +109,13 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. - * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow = 0 ); + const bool stereoVisual); /*************************************************************************************** ** Event management functionality diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 1b90831986d..3003e0b8b14 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -191,7 +191,6 @@ getMainDisplayDimensions( * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. - * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -204,18 +203,14 @@ createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual, - const GHOST_TEmbedderWindowID parentWindow + bool stereoVisual ){ GHOST_WindowX11 * window = 0; if (!m_display) return 0; - - - window = new GHOST_WindowX11 ( - this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual + this,m_display,title, left, top, width, height, state, type, stereoVisual ); if (window) { @@ -516,9 +511,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) } break; } - - case DestroyNotify: - ::exit(-1); + // We're not interested in the following things.(yet...) case NoExpose : case GraphicsExpose : diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index c67f7d81e60..726cdfb2fff 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -108,7 +108,6 @@ public: * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. * @param stereoVisual Create a stereo visual for quad buffered stereo. - * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -120,10 +119,9 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual, - const GHOST_TEmbedderWindowID parentWindow = 0 + const bool stereoVisual ); - + /** * @section Interface Inherited from GHOST_ISystem */ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index c30b915c019..fef58d071a4 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -437,13 +437,7 @@ GHOST_TSuccess GHOST_WindowWin32::swapBuffers() // adding a glFinish() here is to prevent Geforce in 'full scene antialias' mode // from antialising the Blender window. Officially a swapbuffers does a glFinish // itself, so this feels really like a hack... but it won't harm. (ton) - // - // disabled this because it is a performance killer for the game engine, glFinish - // forces synchronization with the graphics card and calling it is strongly - // discouraged for good performance. (brecht) - // - // glFinish(); - + glFinish(); return ::SwapBuffers(m_hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 7b0606c40b7..a98a59377c7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -138,7 +138,6 @@ GHOST_WindowX11( GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, - const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type, const bool stereoVisual ) : @@ -206,57 +205,21 @@ GHOST_WindowX11( // create the window! - ; - if (parentWindow == 0) { - m_window = - XCreateWindow( - m_display, - RootWindow(m_display, m_visual->screen), - left, - top, - width, - height, - 0, // no border. - m_visual->depth, - InputOutput, - m_visual->visual, - CWBorderPixel|CWColormap|CWEventMask, - &xattributes - ); - } else { - - Window root_return; - int x_return,y_return; - unsigned int w_return,h_return,border_w_return,depth_return; - GHOST_TInt32 screen_x, screen_y; - - XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return, - &w_return, &h_return, &border_w_return, &depth_return ); - - left = 0; - top = 0; - width = w_return; - height = h_return; - - - m_window = XCreateWindow( - m_display, - parentWindow, // reparent against embedder - left, - top, - width, - height, - 0, // no border. - m_visual->depth, - InputOutput, - m_visual->visual, - CWBorderPixel|CWColormap|CWEventMask, - &xattributes - ); - - XSelectInput(m_display , parentWindow, SubstructureNotifyMask); - - } + m_window = + XCreateWindow( + m_display, + RootWindow(m_display, m_visual->screen), + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); // Are we in fullscreen mode - then include diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index abb5c131cb7..1203dbde80d 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -64,7 +64,6 @@ public: * @param width The width the window. * @param height The height the window. * @param state The state the window is initially opened with. - * @param parentWindow Parent (embedder) window * @param type The type of drawing context installed in this window. * @param stereoVisual Stereo visual for quad buffered stereo. */ @@ -77,7 +76,6 @@ public: GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, - const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false ); diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index 1d4c753802b..d004e7952cc 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -58,8 +58,8 @@ #ifndef MEM_MALLOCN_H #define MEM_MALLOCN_H -#include "stdio.h" /* needed for FILE* */ -#include "BLO_sys_types.h" /* needed for uintptr_t */ +/* Needed for FILE* */ +#include "stdio.h" #ifdef __cplusplus extern "C" { @@ -123,12 +123,6 @@ extern "C" { /** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */ void MEM_set_memory_debug(void); - /* Memory usage stats - * - MEM_get_memory_in_use is all memory - * - MEM_get_mapped_memory_in_use is a subset of all memory */ - uintptr_t MEM_get_memory_in_use(void); - uintptr_t MEM_get_mapped_memory_in_use(void); - int MEM_get_memory_blocks_in_use(void); #ifdef __cplusplus } diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index 7bdca7339fc..a36549d0cc7 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -49,6 +49,8 @@ #include "MEM_guardedalloc.h" +#include "BLO_sys_types.h" // needed for intptr_t + /* --------------------------------------------------------------------- */ /* Data definition */ /* --------------------------------------------------------------------- */ @@ -111,8 +113,8 @@ static const char *check_memlist(MemHead *memh); /* --------------------------------------------------------------------- */ -static volatile int totblock= 0; -static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0; +volatile int totblock= 0; +volatile uintptr_t mem_in_use= 0, mmap_in_use= 0; static volatile struct localListBase _membase; static volatile struct localListBase *membase = &_membase; @@ -696,19 +698,4 @@ static const char *check_memlist(MemHead *memh) return(name); } -uintptr_t MEM_get_memory_in_use(void) -{ - return mem_in_use; -} - -uintptr_t MEM_get_mapped_memory_in_use(void) -{ - return mmap_in_use; -} - -int MEM_get_memory_blocks_in_use(void) -{ - return totblock; -} - /* eof */ diff --git a/intern/iksolver/CMakeLists.txt b/intern/iksolver/CMakeLists.txt index 736a2a78bb2..da69f2a3332 100644 --- a/intern/iksolver/CMakeLists.txt +++ b/intern/iksolver/CMakeLists.txt @@ -28,5 +28,5 @@ SET(INC intern ../moto/include ../memutil) FILE(GLOB SRC intern/*.cpp) -BLENDERLIB(bf_IK "${SRC}" "${INC}") +BLENDERLIB_NOLIST(blender_IK "${SRC}" "${INC}") #, libtype=['blender'], priority = [10] ) diff --git a/intern/iksolver/SConscript b/intern/iksolver/SConscript index 543ee46487c..81bf61dfcd8 100644 --- a/intern/iksolver/SConscript +++ b/intern/iksolver/SConscript @@ -5,5 +5,4 @@ sources = env.Glob('intern/*.cpp') incs = 'intern ../moto/include ../memutil' -env.BlenderLib ('bf_IK', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] ) - +env.BlenderLib ('blender_IK', sources, Split(incs), [], libtype='blender', priority=10 ) diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h index b2c3c5e82e2..d5ae94cc6b8 100644 --- a/intern/memutil/MEM_Allocator.h +++ b/intern/memutil/MEM_Allocator.h @@ -25,7 +25,6 @@ #define __MEM_Allocator_h_included__ 1 #include "guardedalloc/MEM_guardedalloc.h" -#include "guardedalloc/BLO_sys_types.h" #ifdef _MSC_VER #if _MSC_VER < 1300 // 1200 == VC++ 6.0 according to boost diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h index 43149efc977..cada06ae523 100644 --- a/intern/memutil/MEM_CacheLimiter.h +++ b/intern/memutil/MEM_CacheLimiter.h @@ -61,8 +61,11 @@ class MEM_CacheLimiter; #ifndef __MEM_cache_limiter_c_api_h_included__ extern "C" { - extern void MEM_CacheLimiter_set_maximum(intptr_t m); - extern intptr_t MEM_CacheLimiter_get_maximum(); + extern void MEM_CacheLimiter_set_maximum(int m); + extern int MEM_CacheLimiter_get_maximum(); + // this is rather _ugly_! + extern int mem_in_use; + extern int mmap_in_use; }; #endif @@ -138,10 +141,7 @@ public: delete handle; } void enforce_limits() { - intptr_t max = MEM_CacheLimiter_get_maximum(); - intptr_t mem_in_use= MEM_get_memory_in_use(); - intptr_t mmap_in_use= MEM_get_mapped_memory_in_use(); - + int max = MEM_CacheLimiter_get_maximum(); if (max == 0) { return; } diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp index d998c9a3e80..4cf0ef305d4 100644 --- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp +++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp @@ -27,18 +27,18 @@ #include "MEM_CacheLimiter.h" #include "MEM_CacheLimiterC-Api.h" -static intptr_t & get_max() +static int & get_max() { - static intptr_t m = 32*1024*1024; + static int m = 32*1024*1024; return m; } -void MEM_CacheLimiter_set_maximum(intptr_t m) +void MEM_CacheLimiter_set_maximum(int m) { get_max() = m; } -intptr_t MEM_CacheLimiter_get_maximum() +int MEM_CacheLimiter_get_maximum() { return get_max(); } diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h index d85e9af175b..9f56924419e 100644 --- a/intern/moto/include/GEN_Map.h +++ b/intern/moto/include/GEN_Map.h @@ -50,19 +50,6 @@ public: m_buckets[i] = 0; } } - - GEN_Map(const GEN_Map& map) - { - m_num_buckets = map.m_num_buckets; - m_buckets = new Entry *[m_num_buckets]; - - for (int i = 0; i < m_num_buckets; ++i) { - m_buckets[i] = 0; - - for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) - insert(entry->m_key, entry->m_value); - } - } int size() { int count=0; diff --git a/intern/moto/include/MT_Matrix4x4.h b/intern/moto/include/MT_Matrix4x4.h index b4ee84a718b..823541347b7 100644 --- a/intern/moto/include/MT_Matrix4x4.h +++ b/intern/moto/include/MT_Matrix4x4.h @@ -212,7 +212,6 @@ public: MT_Matrix4x4 transposed() const; void transpose(); - MT_Matrix4x4 inverse() const; void invert(); protected: diff --git a/intern/moto/include/MT_Matrix4x4.inl b/intern/moto/include/MT_Matrix4x4.inl index 074bd6e4b05..a2aa893a6b3 100644 --- a/intern/moto/include/MT_Matrix4x4.inl +++ b/intern/moto/include/MT_Matrix4x4.inl @@ -52,14 +52,14 @@ GEN_INLINE void MT_Matrix4x4::invert() { } } -GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::inverse() const -{ - MT_Matrix4x4 invmat = *this; +/* We do things slightly different here, because the invert() modifies + * the buffer itself. This makes it impossible to make this op right + * away. Like other, still missing facilities, I will repair this + * later. */ +/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */ +/* { */ +/* } */ - invmat.invert(); - - return invmat; -} GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m) { diff --git a/intern/opennl/superlu/BLO_sys_types.h b/intern/opennl/superlu/BLO_sys_types.h index 411a8582f96..5ed3117c890 100644 --- a/intern/opennl/superlu/BLO_sys_types.h +++ b/intern/opennl/superlu/BLO_sys_types.h @@ -54,7 +54,6 @@ extern "C" { /* The __intXX are built-in types of the visual complier! So we don't * need to include anything else here. */ - typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; @@ -103,7 +102,6 @@ typedef unsigned long uintptr_t; #endif /* ifdef platform for types */ - #ifdef _WIN32 #ifndef htonl #define htonl(x) correctByteOrder(x) diff --git a/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj index 01a29d2d24e..97f70a26db4 100644 --- a/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj +++ b/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj @@ -21,7 +21,7 @@ - - @@ -726,9 +723,6 @@ - - diff --git a/projectfiles_vc7/blender/gpu/BL_gpu.vcproj b/projectfiles_vc7/blender/gpu/BL_gpu.vcproj deleted file mode 100644 index a780bfc9e0c..00000000000 --- a/projectfiles_vc7/blender/gpu/BL_gpu.vcproj +++ /dev/null @@ -1,372 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/projectfiles_vc7/blender/nodes/nodes.vcproj b/projectfiles_vc7/blender/nodes/nodes.vcproj index e08a2e04f98..3e19417de9f 100644 --- a/projectfiles_vc7/blender/nodes/nodes.vcproj +++ b/projectfiles_vc7/blender/nodes/nodes.vcproj @@ -19,7 +19,7 @@ - - @@ -749,9 +746,6 @@ - - diff --git a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj index faa7f184197..edf0faf4ab7 100644 --- a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj +++ b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj @@ -21,7 +21,7 @@ - - @@ -624,9 +621,6 @@ - - diff --git a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj index 19394024d5f..76fde7612e3 100644 --- a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj +++ b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj @@ -19,7 +19,7 @@ %P~oR=Apq90n>WDgXc&@8zX6000jB6#}3jfj@fUMlJt4a?y~J1jXX6-Sj5BERZ<(Z!hyMW1YFfev#l!0Wyzo2pjShz zHuJ@Me}C%Qyt46dL8O?DTO?4#L&TAYvo{I(HFX0>tM@PA9?6$Np;yC_Re(4 z+sW5}e-EhA1=0`!>SGkx|9RD+ffo3mxBd69062DI z@Gbt&1JeKdhO-o4<=SMq#q-a{pS8Ag%e=`QBRku+h^|NTwf;KyzpJaQ4GhSgcKWhX zP8J(oIEdN`3z-@&x<_ubw_WCeTOlcyBwjDr+wW1Xo37>h^_W4}>!Sj5=N{LG|KwFw zq5LWe3ipb_Ln7W|HS^eXDlyNBDJ0=9Dq(J|I1u>#Dx$mjdOc6#av+hawL#9Z{FYoDp{h+^BYZ3R2F5# zz;E6iV;yNepo2XFvs4Qzs#}5p&@nR7($M7eT$ZWosL~F-&bWWNHQu1;Cwldm)e0E) zsxaYCb8HD!FOIh0_G9?Di2K+S8Jf2vU-h8R|t+($mSa;^N|#;`g<@Ya#w2 z53P6}JJCd8DIF=hJ(9&0GjFf-=x;h1OI`@8Hx5aG|1P-t8Cs&IPxj5do;^UD&v<&J zuzP_SI>7z*?P^`fkrYEhJb1-=nwmjBf4)9ksITbu!kukN9|&TwVGKDVGwd6@nCa*Ylf=ki%eCQ_rraT|g<7YYmGBj{J?EnVH$4 zGdLy;@3`mZ9Fc&U4v+V5G4HcNs9?l0QQceh%#)Loo7UFW6hB*k=U0i$!^FCu z>iBrebQLKvB3IkvF8Mis`4e|D(nx>M?hD7UF>7+=*>f=B7Pvih5S$2ccY;9!@O(;+ z3n6jw@iZ&fCwy_|%Nm|$X0NRkA=Rj2fTneEfVjz7r+YS=rucnD47~;W$1pL$=sMXB zcr0NU_#p*_hPpRcGNzoO#Sq(WLKb-@ofgSKkN2rh9bn|>Hf-|quO-AIlIv) zR>NAlWX=%Va&4)zKF(`xgm=r*JIuk`xkip|Rb>V0O~c682j3wAwAiW4!SzQ*N0&Jz z$_-hQNF^C@dG5Pb!O2#MckHmbnaMIuI}1~(&QiZ2z1!luGRu@N;NDZ#C`x?C_xTTD zZEfvKZQIz`SjG9}rNy)jkEQoWe>|<2>$~Vgjpi;D6y5Pz%fb4cr<=VgwzXvS@3R*ae?b=;AiyqIVYxT6E4A9x#};8@vnX7o zx~2N{$1$FeQD`A#_3OX7yyPVl;zd$T8_Fs>9m^CU>kh$i2`^}Ef>%I|%vrvp@({Ut)AhQE=AGKt zu8iQ%XEzsb+#x6)m`=5!r|{xgk=jlhNA%{iEq+}zyEGzhO=z52y|W7{*O zDyH22cs|6t<*A|)!wK6%#-e=0>T~iU!`Zy>5LN|VqN1ah%wrkbxw1HMB6{Eg`V-dh zs0Q&o9fc{gXwmt*_|z#?$2P)LM!2nogW!*VPZY(!1-2P0hmu=kOO4X{9cf+B+{#2J|N4{d;1HLmPR$gY zJZjJ%T4a2+XxelRV}h<~1$R;r9gqKqe}R4;Z?fx=;NvXRbbcF;`q z@r9|z0s(-HW{0X2xO`t=nV%IsUtKlPhZ4r{GAN6zB}<0Kyz@fJT|T@!zyNzzWc!3w zkX~7cLeag{#UDGaynjfWrT%~G*hfCmf>m7BHO7Vh$Lx)8tMGi{Hn{GNCmUV2HAByY zP^8)Z2JJuqqeg9~w(NPkN_t_ejbQhHVw-|VZuesYn|T3uz+m2SjxhZ61>)j6 zu)qPZ8eBcr=h?$EseQsBwc(JaPW%xKt9kc}j!|fdVqEhP5e_2#8V4NUKW0^mH%o;^ z_2cv=6^gdKO-I=uXdP{p-ofFZ4GgPxCVzzU6J6DY_QXh> zfBycBYdcroGoB-Lw(NaEBPd9!S5{XP`kANbr1(^bWxV_ga*c(2Lsvq2`XcpX`E>O5 zpLPkmTc1j{13Pz^yOGf{!C7V&!bD$7gn{n&psf-OuIv#j<3AEx`u|xmW`IxiZsvc znN`c&Uj2P==zMUYNxfqRN7V1QfXl(3^7Nv!+%mz@caBH6!3?jXeP}3Rw_FOBApmR$ zDg}YyRB~|ONM_fcJ=~(CoJAS@SkSZZv10!Ej@NgYoua;{->O`{gCsL32;p0LdepC9 zbRZh+-0J_6V(j-`r_L#D_%~ZR1sXOPnK!+FfaflFrd}!$uW2C~nzf*hkL)ol;M{BV zdulQ{S#I@xdU{gr?d>Ie*Y{CdzfVT?QazedL~w7t$N1z!@y84%TZ_(){(X{Gql!5e z_43V2!H?EX0uLLM|Dh1Wn(#J-mS)RSZ*WLZU8$8Zlk7f!4=17G|7EDQ$%t#c>tS>;@0&g`@o57n zDJf6S&%f5E5Vf=jtK}AkBggp`NIkKy`AG0Y5iQH`IE&+IfBo}}jCeBEGfiMD#byFP zRvw)p-6V%ky0BSHC_}v#nAqB!4snmwG`$-Mq15SxJxlgu~jxA+{ z^O)bN+v@#3x6TrrEKVFlEQaD=s@ap(nDlS{?=+d+wkRaM=Xo$yV6YApO!{rPD23! ztJ63+)lB|3=5xm{>>_UK(gl%s?co)PgyT@LXQOXT`%e(vX7`HyrIMRiqnu1RGjnrg zN3Japbn$zhTTC~(9W2l6xqiI?8&RNP^Oq40cJ|ihu8CO=Sck1lVO7wx{Toq!V%D>? z4Wm%{KQ9Y=k*5b_L9bSXgQEKU;`Fi@#>RH$${4jO^>*#DhH@BvRnT zfv6uH!N=t<@7uSya}g10dU_FM`t99^|FAYzI|HYAamV%G=@JHl0G%SuL7p9m0Qbj< z{kxs*ZArrlYp#w&7W%|NL8hcDj?k{M<@QhX;wk6>AhF;Rj6uPYYk%IBaB4Sf3bIWO zlbbpq?@aaX6{o|OcpWd!Mkqyxo72*=XnIypwD0Z~4I>%iH9>|UYrJ5+JNg)x_>tdO z4Fh*IwuD}x`sT!fNPMasC@4U-sRb&s-+QdEU4qTZ*yjwfH}=KX;BO~mHw+cy{#c!w zr9n;+!{bXr8&qI?{BbDF=pe$ReinLCymL}a<5X}mXNFMYNht2&aXSk(Z=|fDA;k%s zTB*%*DcpFSKb9zgQlXfhSj1c=ADo@f{aIL9kGu}5Ek`!}79Td&a->4p-&Nitmv0;E z4iXSl0)@m;PL3yS)-*Jo-X1<{^)J4*jcW_hWNf}Z?B<*O@l*_SbN~RJB|a%>>taUR zm>m(8z^EES&hNO|CKe1axf(rr`J#AW6oU5wu51>1*)@SezE~u2X)pC+sr7i6xHWI& zqETjju+lEZVbCxxuVZ6tiw0cU91E3~w=T}Q@`}71@vZz<=g{$P6D|{QR4W;uwH(u5 znS~S8=uvPOwxG0$1G$|5mMWIrQWJqN<(Qy*+l;p%2xUc!G;QJrENH;f=puI%jcIt?55I`pzGmRf%Hlh5IU-0zWMnft zXX#IWPz6DPE>C#Jgoo$M%J{Viw@@dCyiHU{Vc`_ zXLG>VsFnVw>Z@DGg*d-$_p+;6diB)0UEfK~%muVu*)jM)Wx1jZXPj~iy4n$tRhU@Z zN^2GptI3=MDGi?q4GGZ-2@XzTO&YvNN=m}yL;b*@x(3*Zcx_5M9R95mlc&Qqh8x6@ z>~N}4DbecZ+#x7wTWaXc`LcXJ3|xrs=fhut3&nL7IC63S$u-G{{^ZQ1T2dV>k4MbA z_U{+KnsGYce6Oj+8-(Hw5qGN<_<8x)JoYK)`^+VYy24&=tVqO6$(+vpuhz~cfubWLhWA~*1<{)8~-p-YLw7i8*-{gePg4e?Qbmkd~Q$k zy&>;>jt^1)6Qe9FEvL%#>v{DG`v#8`JYymwX=P_oatHsG-z@9xuKa6-d}dn!{<1x~ zoRGE0Dr(e!@FJ4|km?+Kl6#YX;)`ECJnJ|&VSR;Y5*AK0yF-BvM#aZB*3w+B8McHj z7emMH;9`bTNkP#8dt*@`or*nAQKGY-6PtsRf zO}xe@B&^fdBiCJ?(@pnO4&dg(LZ`@L>wMnu#ok{FHdbAdG)C@OF}gb_99paE(}VNR ze>j4TwJQo;lr`yFw;wb^mWxoNyh$No*IXCVh0yt*LiM!^P0NsA&1bv(R<%Jk+jx#$ASkTWY_8aphmdwhyH)1$Fm!_4L^kc)ggI-|06+yI%GZM zf0avz1`Oc;N|TNooB^`c!1hSm&Uydz_I7ylogn23C_RFoC$HUKdmqcOOg91Fk+Ub= z^X`9^4SrAe&EMLtM`N46w_oRn3qCx~r;RPOHQfDJJ3tkOh@)iJ<>rl9!*@iti_TUU zpZKBpbKlaagu^w0l% zp|aeU-f0%tjl%)>p1raYdFS{4&Y*P6*V-N#af1Y@VR(30mNim2m5b)NBLJS`BdBa# ze!lzm?VBKiu^bXj&?O3njJl^lSy@@_@!0A#ZeU&SdJ#p5B1)&r?^aKe$pNXh9Q?tn zhx1JRcjj~usXNr97|g7@mMMMb&!0Z^=%%FCKDt{s{sSp5`;GmQRYBuP)8Ic!AN!@Z zf0L{RGO%Anys!HUR5I=@`9@10Dpw}TFWr|t0?u%6-+EQWP0iWdfr{e;s5mZs3hi7# zhh5{NXg8*B(FSo5vMMPuZwcz%&nucNbOV*V`*qgzLA%U(KkKAXQE2c1tunnCtG-G^ zG{XK@G}(!`mSpt6YTFIeHS>ECGpJd(HbLxE+r*^sgEbU3yk*93jc@>%GrUkiLR|a5 z`#b2Mm-=^jvI3xE;3#X`g}m#S1aI@AQ_&m?on+npsd0<;1r4a*fA_+;n(zYITn7gl zS@6N`2Zzi;^44ejo_3KaSaRD&u}&Sbv9t4AkmZv%FM*6o~1*zdES$ zy!b3=IZD26L5cS1t!{H^N~_1&dSg*hQMr~CRpd@Z8=jlT)Q{TXTvMENqHmN$A(vPi z7w=JWi%QIUPLO30N7*xzKB zKi0vYxF=4A8WQ}CfeSI!J0YWcQzNyd!7SgJ~yU;}wRnsAJNVJ!8Dz5E#4V21onI zpz@M$_NH*o_FIXf zZShtM4u>1X>ZV)oL7l)Q5mYLO*mPhY3REVt{O(_Y7Kc;vATcdq&y#x1P_cc35~ z1wStT-&Ii8Mtctj?u`&8u$b=XP+IGiK#rvh%{UjMY#e@TrtDv8{N)H@*5&j^n-%12QP!92V zegJ@E!0#+_ynW5=yeeH1?dVg1GH=M#$vQSV5$g3S_#=^X7-M%I+Q#dN9@Vc0jdJ0$ z;sakBV@cM*s`R5=X3G6&@wd`+MA$yt^8C(hptOL94e-lR`o5u}S+_9wWz zXql+RH3!u5p8N0!_B}VAQ{fih9YXc_GI-!h=l;gfR=Q`j9@Q@-fbwtL06u^pr|>k9 zZY30v9EGYVov*BprGK{4>Rq31O3Z~G2*Q-L-HF`j^C9(ArF>z^Sj$9(JfH7Mv$JPx z-}d+SPvGI!fEJ*G`wPEH2a9FSLnUI0)tRhK)&K#HFhtl?K&%oYB)DR$ zj1kD=ru>42gHHqF1K5%VERbB;qJTK~Y&;r^5_;7(Yn$;Ji)@R}p9k%`pV0`}toZAE z+ihlwJt9rVZKA=}n79zK_gxp&;Gg+&aQyqne2JRIlc&z%!Ni4y@d5!+Tl3!GZyJ_& zOnFWqiR(@ma5)7@*6Q$gZl{TfiGRu!IFUW)pzI-pTM~QVb4X;6iHBUl$pK5WUbnKu zLZhlO_{twp-YlH$a-jdO_a-9S2EHz^Bvqnn$X9^M;}9~X~lq;R9ekl8UkJoAN%>!2!T zs- z(9w~)b#v7E>!j$ikwDF)q#hXwskb0Me=y^gg9^y>Ie)JX>V%)Qw6qH76_YEWtyfyK zhMl3|2F1)EHdMFAIT zKcaTGx^2G4vy?BP!x((KO@StLg|e?NqBNU9nk*Q(iOGT+ow$;e)nQl203pO<8dvf? zlA02VXR^k9G~Vkc5bZGM*`mZwPkD&LkiAGvG=A48fAws1>47D%VNG(@y{CJ}c+u{r)9G zulDPo@70&qXmR4c?R$B=_4$Q4G|TK$lxucE;4?`nJoeK~q;J`?_kHq*-#S(A|cDYFy*RMRB=C zq(XxwNkdyIpW>CWh<~*QytVZapM0f=u)hMc&b50qrO+3)7)p`-Z@2m;_$UYrF&i;& z(9P{~aj?yNKNuRaW1*ubf*nGz$wfk z#pcdVE+{QCadP%GpS0O}Jsj010K#NsWDmNLQRD}*bdv6GXae>XTkulYYy#Acf5@w6MuV>c&sUC?cx&XO1@l8BQbxtGoX^dp^Hjbd?VWo!P9M>l@? zU?f^BCN6(nk&}NLumiU#h zz8~o2)J^U~QZKzk^!4<9kPs4nt|8L3Lu6S9+~2p+H8EKY1i@ZR%|n}DM)?@X*9%6| z_+l|Bg;N15Z2$kSF8wxE_#99`oa+0qW6uyG;u zuPrvDHs>J<10AkKlqhyBw6&JhX-mGhd$+y|mIDE;BfMX<9Tq*ZMHMb3B_(s4EGhAs&UB%Yl-kx=6V`I zQd{Wtk)fE$YW59=pt5f>@qhM`e4d8wx{$6>DErhQ>CbF{5L>dTL%0hE_)$B~{_`Ae z82+-HXU#goHu=DaI>=`ll?uWI-{CCeV+^k&jdC}ra&L#G%s;$AVP@f$n1#AHMyvbUi%{qLns}UE3LB>Ec zn>Ajyu<9cbkc&cd0eM6)aaY`fAHLYt-#w6>7ne7mKu}bEb9x#V*|Sb~*ENVy#Hm-Yo}dw8SBOdThD>_ZxA4@k>zP! z#Y0eWCj20D^edlVTAv;XJ21R6Sz!(NQ!jd_;v0s#c-f85FYWO2f*;53pK5B}&1 z>+?<>9@@pZR-5{)vO|>&es7VYh$zT zfZRR=SJ)5Q7h;#=Qr#fC2~AaEcpWd#W!i;sxYABV-beH1O?=z!dL$hSi-MSWZxkgD z4^O?TprK;K@Uz$6V7^3P=xwI3)B01j&vSOBh?n0U9+mHrsBR}M1=OG z0@bW;P-(Y)aF2ci)_biY0u1@WwOt1|fp{#x7S61@dbKTKrVV*qn51_sM)X74miUYe zc<{$%nga|!w}J_Xflj~+;I|LGsM%`5u36+8=xB+`ZO>a+rHORh(Qmk5@6!h!fr}`3 zL?Do&O*gq;N-Q$oB5m|7paHb&mOm|Ht|)SiIXM1e?S}6V1=5Z-`;>r}+D9?l1knI` z&MCkL)g*lD;&-y&DJYrz3&O?+S#lXSf`TZ306Leb9wE<>hM2F^`yyO|YTm&052Pu+gbRTV!&7LLE5T z(9pwgss!fzpQQ^|+98WnaDxy}MZ}uS3(4qNWYo9lQhi4e(6Yb!pB?RxD_h-TE8760 z*);xNI|QZ%g^kS#YQ-8=hu-xLOHEti-@T|{md{Y0*xAfwLQQq8zzBVo)4Q3>E7Sqe zA`A@q-Ndgk0x8PYv-->e7Y+L6S)ONqpB+|@Azj=(Mws`-_R=m+g6V>b-HH&dCW0DPHjA*Z&+gwUbH%Z(Ew@>lT4@e3gm@i<5H2v^fK9?>0%HJ; zJk3v^@|Fboyl0iJ`&z~P1YLJ4Gm*5!?rffu3L1ZYEda#PLokn*ZY<>G9eHCpeU93p z>=iFxat}lXM@Rrp{n8v}fCF-Bv+eE8M(K?Uizhs@;~jiOjoYDxi~+M5x@yt7T?Y)D z;!YyA?kUPnM-WfxU}#)pY7MhN`VME$S=AohWC4V72B&P44;#QwHua$G$)Xycwox+# zJGxGUy?Qc9h5k-s&4{>YG*lo%qLu&>-tW zIkx}Xx^t$wwxUq52M(ty#59^5zZNN3KJ1rD&o!p?KN>47wjXUTv?(X8Q`Nxy;M}*q z|7Ig5?epTzGk=^VWkS8WLx+1GdUj%+Vw;|T62k``Kw3_&-dcjXH61EyFrHt#BiLq+bA+9cDgNo8j9|-brQO>Qh%Y!eI$b&e zvUuhzC(i8-M{DyEzlGy5_Ua<8@FJWHYIJ~0@vnk{zBkqLmV3+B+Yj8?*_-*IzxC^* zFP4pOeqE(YblA;WH~4P#^st1YPTgPC>|Y}Neta+{JT~%O8QowU%zSmdmH!qZ>X!%? zq}H0bH7Jlhn7#9;FjNyF&p4S1hAE*76rhGgzM`IKENAfQbnNSUMNRih%1>`e7?Tu) zz!l^7?(XixLLfH}&y@)X1rxyPAj{wabQCx70WPoM-7O%QueEZIm`3i6!()Gz$#I1J zSFX!r?!u9q#dJuvOF(EH?(2!>yXW6N(IzUQZce4 z+b8Gd#uMC_R-)XnC6EEvF)>1w5L94vcY4<7nI$Ur@D~XDA&r1?D?u&2LBFPrxxbTe z!sae12?xq?E}pG-LiCyb$tdD|+?2yrIqecxsMY+#%eM)~Nb)~_{(PpCvRDEY`%_O? zXc%l`*xt2u*6?Y`aRa(Q*+3OQ=J4p-@dL=~Wx01abMKCB=O(_P{ol0l|BuRF5he>F zjQ>&jN495Y9b!)WSNtjYtmL7dJLRTlEM0=)~A){g`o?&xuK!+VVnJKf_H*M_;-~k`5o5Nvu>O~k397%(Bj@~Zn4Nx*ei0wp=c_p?T3#B$QaxI# zai}mq=D9I#TMQMi9ZI=TYfO_K4^r&+geBaSd+3%EK7xqXO`@W)?$>?Qx{b6kF?j0U z%nN!G;(jr|9rn!~V_6RmtS~yCMYaK`lT&;bMV5Mw8cMkI*RNmUTwk3@V6UJVHa&D2 zucN7&!F6+Gr@tb_p>nI=S9`PgY;fN6m1kOCBlHceSLaXyR!$Hk3zIzXol@fJx&Hk-JvB3y~c0Umi3?8r8`1#5O zi{wBzt}+2x*KZz=^))p$S>kMPJ8Mzk_zL_n7gv|(=U$HcnpmmYl?R2iLS+-5%gdxSil+PK=G-Mfpl%r^{j;1Nyn&3G z5mcHqzAI_1!ewQ(x4(P?V`$Lx>M>EWXHb1xY;s)ddXu4YQ?A6&yo%EI{Pb|P(N95K zeX~peM!zaNy}Zo8s8E6BXu80oDjvj2;?Xnn^>bKX@3r25da;n#-7I5DodQ;vw@Zl*p8`KX{zaMz4uicNU{j_9+>5_LI0A5kfJydQ+_Q2MhD? zC5^GMsL~sCqArMD0xH@TR!#-_AXrf(@Y5;qr?Q>Fir5HuG+!>MJh-_z-6xAeE}#8@o@@C_VVYpiGyK`t zsOfnWHg)WzUMCihUzoa!gqyycRkqw@H{6~+WAQ`r8Rz)jJQWmB>*y_Oy_9{lHp=9Y zZofloCHo|Xeq4OCzvCp^3Kd=cs&%JTZt(r7SFs{QDecXYV!_n<29}r!7!WB-6Z7{Y zhNT@D-drCoq*S`>j4E|B@*q3AxLB*J>L}=$N#H@#vMWyYBGgXxsGW$~Ge2v^NSpa^|n4j9Q@LJMMya z3Qhg>3iWUeY?cjHq}Umu72;$jsnB8N*O z1cnDIn8)3aEHwvrIZdM&tm-jidR%)%M~13 z&)C%@o4vBSe0u#YySxo|D``t@dg-gW-0Ip|!0M{baJpZB!^*$a%UXg$z+eQR6h zSFXlnm9UWtgTZ_x!(ucB!5s1p6B84PlA_{JrjWY>kv7_Iu6M3qx}kv6vv{+N&}>28 z#7?F+$Fh$48vahKfWRb}D&n9ZBS6fR4+3pJC+?GGC|usVA!h9u>{6edjF1gPXnXX> zleUHZDv@_QaLJsixnQuWe~{(Zt5+h(a7+em!paA~Zg(&#`N#Y8EQNb;6F+K+7Zu7} z_N!Bh`PI_c4t{tcM!DEVEDP{8-LrYl<)+${3kh}68aqAun8n+)yM#EFhS8p~-6tmM z_I2tG)KvL&`XMR?>8tp)j9IIX&8mU72%VZ9l=of6@y5Bmr>z8-zWy0XUoHvuTtp~e zc0Tx7r?qc%b$5TKAJXo4$e_Pn3#C$^^4g_IL7yND^6vue2rQjgkX|0gITvXbH-P&g z`lDrOy{`6yL9eHCZjJ~{KQ?$?Fq9iMhotdAC;tPB-rn9q>8ju?zxTaax;Yz6Vy(v{ z<2^JlsRD%&qTzIb1UhPq)-L63pY7v)D{XiHg2 z8yagzh=Ioq#RUw3OPC5&d=egy=Gwf{dPtNDJ??o)Hj(g|^hM3U;(Duk#Kj4Jl^>J5 zuhZhK1ZOrEE-g9|{5wiP7+zowLuwHI6%xhtV3XDq;b9(f7N>-X3ANYFarC%KE^bY99>HV>UX}G8KcjOKRK6MpZ|=2mOSs|IIDwxq=ouVe9!I>lnz$ zxr5?Nz@9@foF?R1lf#BKTdG^V1@my_1Hr&BO?~uJuh4mwukTf zji%4QDenTLvdYLPedvVhi5NECI6U?CS?0B>Fe>>9W=6a=e2ZY`ew4fLc$8UhD{*(` z)VdthjrWztLmg==9p&^%DjoMF5E&~u)cx4`B5O=^>gXzk$m}Y_jYv*b?#AF|PcSxx zuq|T5T-Fp!u*ZsksphnKrbj0bx!5_TvYB2HnJlv`abS}3Q)6Lb_Ews9>x7uzZtt=o z2Z)2+1aRG-el=Ha*c||myvc1j>RMP1N@|;S zPZ;Cpgi~o7vInP()L1N{^iE)$|P_;gww+@6&o(oPh?W-5O z4Vc*L_(?9@Dd4(S{->b6%P^?S^jZ=O&*#03v6y-Y< zkdzaYXjhEFVT;+FuJX!39s}&G6;N@4g8q~lwd!%8yb5<=z%{`Sryf73@_qOc6cl9A z`zL(X3UKR1Y4}hX(Wb;uZGY={d%9LRk()pzJ+vUZU>20s?k`5!y-M}|ePP*$pTF}- z;UH8#ZFlt8DAeCPvb8;KL$y^iL|42$q82Ill77DSX@2sr_k5g{?cByy$ybEq zOS8}Mn&o{|a>q+a$uK7r#!(w8#b&|JAG+DxW%pA!>SNt9@?(Xiu z*t4XP68hlKP<&dN;*lFNSP1_>jgOVeV-->X`oQ--k7s?7sqX9}2-p}GNS0KcEg26I zsqVt|NzfhE3Oma2b}`+ILdJ4s`&W@xsMArPNNhr11N;eQ^ zT>daE6MHQA2JJ`$ADn1H+xl^uQrU26(tQ)9j>U+a|ChZ@H?x)B*+A)lub=tjykQ(HJwFFZT2poo#YmCcu`re7faJY$y5pAnj+y16z9MPzDJ5B92s z6nlvbDjYbj&Dr*kh(vz-eNHG~ABn18AUn{gc>C#u#=_wiJG9P0{C(#~$7z(9IHWcA z{Otv_iv{?sF=UuN;BfcwkmBL(eL%#n=Zd=xF-IS^{j}3O*#3Fs$27Qi01%gUbPUT= zO`pq5>Snp0m50Hvy&wQOwKfFhiAkp5oUfFHKR-VQ0HICieNZX$c(8A|9~Ht_^F8oB zsJd#UUGr!C{TtQ#!&$w^=pf7EEDoiZ=u5j`Af+%RRyzS^~Uu*tAv%@I-L5dyr z<1I?_jYN;j4fV-EYzNl<;;H(72lB%mp(|cadu0FWBSS+A`WTH%Cwf-AD;%d&C(v;inYn^(B3<#i-&Tks0kQd88 zS*xb0i7+(#M+xKuZ@IbSQ&Ny?^)P}Z1HhP5PD2ARpTnYfETsteu4$H)7S9Vxe-L1; z#70J5fEDyBRyOypK>GCn(rJ+rgFairz&`MZ)qx@z7N=ojH?o&1=Ks7Q#->v#z)KfY ziAH1=)d@>z{xShB*ae^7{#yX!YPcP}pey{FZ3x^;f@W%JY9yOmrF)k3&KeiY6o5OU z!JWc#;I`Zqux7-|wD5u@C$h$NR4WPm8x3NRseG_05J%h~L2$b~z8*K0&4^y30qSU% z88Gh7DW{dkitMst#IZiI^H{3B28b9fHK&U(?3n#Y9GX>rOAif=Zq2E4#Uq8}Qu@Ro z_iCKDKbssoL}a8-I!m;QpLK98*kgxp@gl&)(UVgLpe2_C7B8bv;)sut znr0(`bBubk0~;2`KW(kdR52}HW|@Z3%k^j41i(IT&Lnozo1U45(FmX3;b;4th8_;FNXn4;Z*%T__MC5U}a7=Z-3xe%n*<#^$3fGgPn7|mZjVB0yn zE>;Z&ut_M5oQ~Ex?FZ+AHa~6FbMHBMyZbRiW94DorZ2Ll|Ln79_rp_YB8bf#Sc?ba zjLny&Ro;C@jZkJ2)}n$YNfl|{htru|#)M%Tvo=mNHvJ~8rp%ySapA(F;?z%Sa~UiD z)gLA=EPC-~GjpJG^k`wv6~0+MV#TR9R9u5P3*xcFr0M zqPO3J$Thlb>1D3Mr3|W+pY$MC%oa=xFD|xtXJ>^sQz*pDl1=wK_ z)0_8P_*C|e)kF&!L-|~`kRGUHi>WZ}iwSig#X>k8zWCGvN^P9+G5%#67x zDT&M2;qQ0N_6o5e{{06T4qE-_bS?|=?adxs+E9O%^RT$KOPk=|iQ9fVI;#>Z3pM7^ z{)89*kcDvGK+RpNU}tA1EnS9X$4P%NG6WUPA#|m2L5F|smzQFPA-LzbDT!9o%7)|jt{#j>4*W0_j zN89s_G|Bwl{#?sF49?hl4_bmD^hoN?_|n$)&onirXS=hBCOI*(G zMEPSbZtjYCfFW%WV|6uhC)$O*yv&^kO?{~y5NJ{&u%KSZ2aU6eyroh-pJ#M$B%hz! zLdOfk!EkI`d@NuugVexnv7_E;eF+GJCz?I^wc|xm78b{LrwLJwuHBk!IQ)?|D=n=# zd-6+Q1&!>t;29GDdg4ktxTiiOnv1vB(kV|*rjtLiBkq#zDCkDNaQJG5My34x0-fMF zCl!YRqp1xCvcn>jC-LL^XuDAL&r)_YLlhCt6LY%@Gja$y{clGWs!vp!^qAsN_>Yp= z$8GyNVOmRSu*?S&)t)p#s$O&3H_}ilib7&cc;~?|1U((cZrj8uetR72_te67obtE- z-LVim4+ZY#)>el4m}IuPWPU+#NeeZwp|1WgR81dEy#E>_%P1I^&KSznw3bNu6*8rJ zbeCj9!iz=1>&#YQgH!ir)RBT*$rvW_0wrKk0uz-9HCyCs-F#(aWfk?G?(VC|jmU4J zf)j8nxc@7Mi%aw1mcHeKHvV-jGK2xEW|07%(aBb6>#aJlGUzx(wSD7c>`KFsmUe|n zSXuphMfC_Kl{plG57+>>5$P zwcSNyocH9(u^Ah#?l4;G-*p#U5t_YufiIZ9C{POu3e@xq5xSYa;H#j8dQ<4BM)h4< zGi#*%_o>@?VV$HJ2~w9|x>?&5L>Z{QDC&9iEJ{d=pS)3%m(b|NG&E+^+{Ll$hDI3u z_IxG6u#?$*vnr}a{IJ6$G6tn|uwFJiwXUge6_3HRR{WxzZLW(^l*KZzH6y`nkx^0zA3K=)+~tA~bdB0fY#>@dXtI1;dkn zsP7g}8}5+wQm2UZTdv8ore`@<%`(r^{P9_yOe73ajQz4DtH{JLuz)y$m+x?8Mo_?M zlgN?x3V%!lC-S8?&LaEc4^LX5{!YSxprG&G;}6a~ZpPiL|FY)g@3$)L+$()=Re+WF zm5z>JxG|X%a4~Rx{HJ!jGfi5oTkR)9FA1h+E~7RGK&rq!+n@~IyBMf_$HB;Gd8TFP z{d8#KW9iuAtt?eAGNvqVfD>Gb#BEv zbiCEwWe(d9G-Zpx0Db?5Y@w##N2iJSUlgU_caKsuSP0+fvOp3E>~DjBjp#Pxrnp7E zln&4EMv_*cEo$xQ>SeVdK>schOy0HpmHV@BDX7rmjDZ2#|3xe^EC@63CbstNT=B9_U@@-a)Bc9%E|DlDP3S#{f8?@ zhU;}7?VVo#cR736h<2=$u^`7{)KwwuUw!O#KC|J4 zDE%Sj&4aXlZg63sU;o3KaZ&V`Ne0R_t3eJg2%~aWJ z?}~x(=q7f^2iWyeC&9fLgUI5|{n<#A14eD$Ey^JoiPqhc!hv4zOf^-6d{(!1jn{dU zEM%%G8rBwN&}=sMXXkH83Y)0tqn@y^!j{QuZ15lYsCxq(ECI`3FOu~e)%5hjU!$VR z*>l^=;y{p)$ML^hJ;k&uaX!BI1YuGLOEs0fOt+Xb`Q@Midq;Jjmcz}jH+rp(#8VZv zc}yI^ilwzZ0~#7eQF^<@xW!?^;v~;h?zAz|u^?f){aOB$6++TBO2*G-%E|*IdFVLJ zA8^zY}n8!GBJj{GeRMZ?AP4N865bG^wm~fi}FGB8!1>ors7? z4KF}};bqbj(0o&2(1E&r_VU>cso@F@<4A?MvR=bSOeg>Z64bfuP+XqvMS?vADCn=R zy*P1@r7)fWyD0G3dBo*wu*~x&_h-f`t)h`u_}Bp&a{~wtKHsZ~@TJJ0d6;&(21}_& z^jWDiNnh0EVGjGX#d79w8pGK@FJf&F6VUaQZ{ECNR?0pUiDZ_6jP`8iM4E=_dUxffHFwku zbj;6)zZTc&Wyss(@sE}}i9Cy65t@5JM~FUQ3b{~K8?BGo={5UcvUlvTV*co&pAqdm z@=$vofM2OOK?^BkkWpf57nOYqfQ;Lkzpw?0Y9Y`?M0TDY&caCt@wo!kR+fy*AWf{1 zB&6hCG%1XbuWdHS#|%cAhpnF)H9qr^;zpQj;|E{Omk{AkXrqOHzULn_=w25QAl*Ew&(id=mYR^90Y5f2=w8DqWJ1++#@w6B9k7Tb_b~5>kH)kXmFi)d6jipyRbN+rGhYSywn#T zEw&=BxEM8?C|3QO@PRO!#lu|+!mVOl{hn_Q(C?dyzuVxqv)?V%Ym}xBhY9vs34ciP zkkV}vo}IU(lBPSaw{y?P;ap_kpq?Qio31i>dI(H;yWr%Ui2EVKfGrrW8xFnx zD6K|xI$;Ga9e9Gxt+C7?yB%?Ve}5WIiU=AYoY`~#b=CD|4tb!&&}nZ% zab=zb@zD)`uf#3T23s`;yn)TWLa)g#Ysw@aA00I#P&?cxxj(CR(yrG3`r`X%7_IvY zcfG6XrK%OKr~KJEj@!0fc%#*tH)V~wvoz%Nb@E09xYg=84NX(u5dYx1z_cJGoB%VU|4h-r3AN<+SVXSaqHCe+3c{`pLpc<(?S~OL{vJeD{_c1oY zMr@prhDH?>WSK}RL3(NtH_q?f zg%c*el59bPsVBiVnVydl(A!22U26x5Sw{n}>v!hES~X*d3`=`a2j>nBlb~1_Q;bN? z@#Yeh$bw}5!Mu_g-_(npOUIFag|zrVNG~vMPmu12zI=Lk8ST0zLW^pu*2rgHX<=NZ z^AQ@&JU3!U6lDKf$cBvqWxIS2f=o8mP^eby2aqrj>r?$JBU*}UJ@#save+4>#vIv1 ze5|s?sCfl7KVVp_=CnivZ0=iM(Dpn}?L4E#l143=$|s89SO|5PT5y*HDlLqJjkOaS zyZgYVW72*gK1JMf?jcf`kzv8&rxa}nAOnLN9~-~}-r3!K3)G2&=^&kE5hP2Ut{Stk z&Q@7}naV)Pb7w+|&+6>VD!I9u-rX2g-usuyFrrWJDNE+6a_84$=D{$I7A9l_ov7#B zM>dx>gdBm)-CVP{DOtD6VQ!if$h`7wp5I@zeV;407c_EGUS3}EckGXIkr)#aBU;3x z=XOW%mI|8NjVeis#PO)#IgKBb08ySlj+wEKx?-i9|I zP`h_|+fBHj6n3}O(WB54RjSm|U_TSkxuYs3W_ve_d^z8EamD`gW|dR@_3PSVyEciV z?-;)?Pp9qgj&^G2yPq;J9JbT}!Zl*@KC=;YVe}xt2Y4tju(5^pb#%y`uFpS!>d6J> zQ1GTNR~~7f+uE|<*4SBdat_M7i?b4ip0)J(>=T=g;E=&R;+m`MdzV{&IWZwscbS`i zCsj#nv3gGS)sS3nM1{8QyBgE`J|aY;9bzsAnvpvEs*bn7-;-wOc70&UV{OgR%N=W9 znAva)8Tm0O_=P1Da(XPiSZZuS=XE^^ZQpz|57}`+bVb#2GSzrroZlO--W^VBV*n2a zeL#q=Jrk@9HiFjTYh0q>eToZ%!VFWTWu+Rc?agwI4_&k099pvDD?PsmSKG z93hm7WVm)a8&y9yYy;5@A*FdaoEG^&D2z^yY}IIwwUcq1O-;>rOfS>75MtMJf=W5N z*T%_CPHt&d>+31vc8%84udS{(`UnE72_nmvKW%sRR@UixY2ZQtjw^jX4J_w(W$^PN zloyHIs4Y2X)dU0XwaN_D9e4>g_7@0ou$j_8oT#X%+o?@dRd%C<5%~krU%#HqnwTtU z?WfMwKS<)YFY!74E3XJbe?SAxc6f9IvW6ZF6IDZ0W>;{mK&jZ|4Hl_laI{~xq&W2M;G~D~37L&U2u) zjpqlT>A#5-$(XD;!f|(#!g%*^6m!akRZi7yX74jTT$O_mKESHRWRTnTMuvy7mtBU&7v}b2q{I4x0ZPAJ@2NZv)BN_N?WK1V6 zzS!RE=1Y9RncS~Jzl_1A_H-}|dnow0!{vC=aPEcE0-oz zlyZjthY!8^uGLzJ93EXY%6`k)8x%Nx6e?GnUHe1q#My`y(=YmuJg5p zlU;byd)A7+2Yr~U&BagXRtA__(E*x>j7uN^A))LuB0aS7gOXrKhj_FI2!_D~Uc|ru z3BH5`62^aCy8j2(e_sNxJ50Y~jB+FJt`Dm~9{zJ+;LO9oz<^rRWt$9e6N;@qHx%rV9bf=nR5XC# zCU_9K;n0^u#n@#P1L;-c8^xw0EtWMl7jA6iC zQ6hfeF%O=LgZVp;KWetziU0N&JMJSriu4<6fYs9Zy_LQj(2iLA{@T7}P-@T|3hbo| zDu3S5wBe4ZqJ3n2h=f`+@it`dc~dTrkK3OIX=VkZ{5V;|xvGzOct!*<>Z{OcY{SOp zOT-aiHcJA5HnpgLW*6E3h7iiwc{1QX`U^~ay*WTM^H9fbs!DM*=Orajy*w03`TSB< zb-rkLBS%(7<~&w59N!O26YcdWU%!St5_WN$ISsm0LP%w#gPrQ<@84N^CJctXtrZpA zwVr3Y?2rU~G_8ODnYp=nUS6Jrwl>*)%Ha;c7sa`_${7)?sR1Wj<9LA24*A>?ePR#X zNX~zB>Ky1SdkgLrJV!^T!PkOC+U4Ifr2pum-qQ2%5HYHJLnu7)o3sNhjj$R>z5}^n zlZ=8|Tg1H{0Ln#$R>W`5mp}i_lsEJS)YUY|zy!weJbfxVtSty9(Q+Aya(%D8gIap|R62JUtXBc{sNcU|Xeo!3Ryz;Z=soM% zoo!^MTgh3zUFe~KYqSC%%+Ei6x>tI?Bxl{Y?9M2H&=hIr?4P~8uhv&q&a=|L0kQ;$ zD$I~LP0GK5uo6koY_M&lUN!ATb-kNs!Bzq$i6ZXY zgoK0`5Qx9w@8tz?%qp8@{}gm|5_wozmGw0>8BRt`T!TTtQw;cR0@Cn?K<|A50=T?l z3Wqm}2nYz4UMBOkFXHBb`||?aOuiHq{%7>`CTBZdEmRwgr{;lDl7deo7-BDn_%lFevvaJp3etiI5?ISE zdYQsohVgN6+3&;Gdr`;Gx|QbU5Mc2#S ze2yy$Y`Rq#%JFR0X)!U}C*?iV(m=rufsC);c9RvWB-!fL2O2n5;KG`kAW)~i^1Y)F zM}EqJ1snmJAQU)HgQesq8~lrnitmGkF~7&~-RHR|*NfDMptbTFO#G%%r8Y3&%v-4< zIL=o4>_skrtJqzdd3~uOK7;XTyai#OizJ z#^msk8ixrqx64G(vLQV8N87au75T=g4pu!@R$Yk>i)1Lz+Nw!Sbj zFpPcrRKM49wdsa-UUxIgG&`byx0D*T^%21cW@J-EAe?~iqX9r%D#&H~(|{+HfggZB zVaEr!7cXFS24SuSh0p3^;9!})UF~uXZKHWA@hkyQypoh#xK^PbhD^$h_7~cLu#}A3 z4CC0N*~vye^RE%`%9J@i{pnqKU2fJJ^8ozskb=h!d%YYiGb11xx?5GAc!|>wT-OAY zlwtq=S>XUrEpRZ(bVtL%6b=CVG_tr1C>3d672NzIhdC7J71Z*EC2kxxa)<6>CwBhW zA4-}(tDMwoQ8sJJ)YVX?p z(f@+DV1`$h6sF!E#_m8ROL1PyR?jbDZicAjBB|Ly8ptb8VSA8)Mn)#DIm+%)#Tm)NL88!ga7|m^=GCIK&CFID zfFrhWG!zKIq-gQm?D#qW?_{pC?rB%94H)P;*D2etZqm>00gW6L7k@NdM-Pd*<4N$%4{#NOpx~#O?M~O?0d9C3? zfyUi>Hx>$%I>13hK1vQF!jk349`gKj*~(pKgGf|1Y_P^!;GjfyU}QmhZt*)kjD)?R zm-rvvh4|%*;XlJ0Czr{7*8+uxz@vIE!;HJuFNSONfkkRf5g|9cVgMP6FoJ^017Tp| z;&$1VHlsx=tcaw3`-TIBgoLz#{F!q2-EA|N=dYzphO3+P*Y9TO`1op6vb%%E2$K6P ztg3ZK#>VK`*l@sy08m;$1m z;j+;@AJcs&pwjy+(R&UV1ke-H(a`~21<1a^z{L$z$?e!2Eo|p(=^_O&ixs9yO1~}u zGGq++fO}Uwls*f1;*!f@l?Q>anXg?DZ(3qn3mJ_-rgR1P2nvw?^WCpsN)dQBlSOJw z7LfLqB&LGH#SFOwd?FzWZ9(c9cab9z(*baB6*(9f$Ky(_kD?OTbcU=B*E!t=CAKFE zyBnJ6RI+LJ^wQ*JP3`R1LPJBNQc@zohh*HJ#OtH2ukp(pV5hc(hwDXmV4v2xG0l`? z)eblPpB5k@#@y0Uc)%J9l!&|wkF<|MvwLL&*p(pKstsHn60|j53SxklRVo2of&~V< z7WO@aZB?uAYPfyk8gSzHgMmgUUHBWw5Y#;D8&A!Ajh53dQ8_-;fW-CHV3Ac&zyP`xqzF0x!9leq5Ir;jR2Qz0!|0c%1M-;K6=sUBqr@Qv!9#S!{e1#$V_y|_ed$GIkjEPkBPQwt`%<}e%9Y{&rg0JhTpp!G+9JqsKD`nXH zFIOCPHnvW1i;O^q2MrDQ;|LHj_98`y80eydBxo0kA;1}bT=^+3E>2_LbbtnZOa)!Q zDkzIF-dCr*HaM#yND*{*6BF9MPAWm+0MMpHd{R=u?qnq+NMUux#5taR2(0UCu&M!?Z1LB*MGo*ow5u9 zlMfZ=Kzo&fCE?=22N1rkBCP$@+wmfuOf&@OK|4ARENbV6nyX zzI-DuFAvVOP#5z>oWvrmp)uiDgg-vE3=^@(8=`V>~$@k zQoaws7{kCGdYdz916r%V=io?_d&PZdD3+R%VBu_Tugm+}*4v8K%MUQG-uV;3d23~N z!KVw^2?qD_oBKxtOp16QvYxjL99Kz16A@$><9H5QhKL;6 zJK+z5Uxi&uw!s2>$uew=o1d)CAn!Ia2K(8~e96r_SppXR?^I0ZqK%c#m!HxKNXZ zbuDP3ma&Ba&J1k$&p?a_L}}>X#(Ta8hCR?wICnp^UsePC3Ofr+%&6-Dzhf^A0&VtY z42ZInp|8e~X-l_W>M*^BcOoYvum22yVbs8|vaU{GsMg-_66BMLHi7(?J;4fnU|REv zxLkMG74>eH;aq==B|@Uce}ibb>JxsNgHQDPVUSaCy9u2_7ibFTXzGe6GDV(4W0KG29G_PZ2DM9H=Is**%M&vjy$QpKh5;esdf| zqu6%u^s;oCIJo2C7NB+VsLje+5d>E!{;`->!=PiMStUjWvSi^3yw`<@tFLc2s@9W---1n<+jeKfW9;1>4=;E!uRc70B; z(H~IJf@^AhidEd2h`z}vmaT2v;pmy$16e3;)!)$`P?3>^ApaK)S+GZA z7)1FWNTLQHlm82nAYlK+P1@4%H6gona@anKaXRLIe{AXr!H-n9LC#<6<7cz7&Ym&r z?{3OV50fr0{{xon9{TuXPwe@c4>syM6s|ta03@w0#Y`VP)&Z7w%e<6Ml7Lv#*!i8_z2m{gUX8C&`n9 z75i+MXxxoH_3iWkhivwAt-V%mtI7QB`*{VhbNY`vO(uA%{lfn)=6v`BsHPe|ZunXB zCqL#grrKL?0MLLC$9oqS5bTKsxJsWh$`ZBLa&mIZm-;bd2fi>`3C*m#3X=rnzp4}B zq{V0t2JEk;Q@omYPt0qVPI#p-Mz>BXKn!y}$eW6KV)Mx*MK@E^UZ$))lmI)mGw;*u z@{=$eyU9v<(f2a~laB@iRj2K0PC*sgMj#<~0-935apfl~umL>;#62BjfE9E0Tn?;2 zpT9_x^~kn;Kvd`tMF1RkXIjX99G#N?QQYlN=KR+)s>5eOL}+{q*5}FfpS=3#_mru< z414Em-Y4_4ILq^X3Y9Z{i8|%_ub`%k@7uK*?yrWbc-#~>aSqvqGF?ee=k*$ta~IMu zZ}C@ID##wr=xZF-R3DsBl_-)^ey4E%)o`Tr9~sdI?Lt{84jRaag@s|}T&I5QDXMOf zyd9Ce%`Ai8`P{c9TdsT5Wnrfq&rx)A5oZ~%$b%5dOM~*nu36Algb+C2CTX1H zL^=?bt1bTz=2T*?>`g!Rtz&4ze`(Z&5}T6Ak5$THb&6LnzeJ`s-GYZLSk zFLe~JS4&jP2BP8#U8fzOox)wWH{6~VZaJy!8)9#5S=4Z2I5uSS+)sQELG8eAKgR}6 zcS=q&CTrS%_HA_Fe55@j~!+M`xaO7!!ITy(y6+dQckn64?lf7oh=A4*_hVJ!)RRIX?L zmA9&-ihKeI`<*>KwT9I;qtmZ*UbqjTqe_&)2gVJ>xCaMM9jc*W((#2kNt&fZ_t$|m zY(@WS_Wi4eGtpmaefQ=0SrV`-l#`pC{mS(!xq(&>s%=AFxQrUx(SG~)ret?9v^Ldj zJ>0E3!A9lD^XFe2trhFo6J;fQ?H`jaW;pd5DYTC@OOI zcwd?qJFN^5h(kzxxLYn3?91&mILSnwITWdY=!J@SO0Wb^#L|9i>1; zvtg*j%W}WZHV!V2t68jV)IE9knGt&q|L{5OCL)&YTfLW$ zjt0yNpWhC@?k-CaF<_Lx1)V7xXd+g=s3vWr0<=%%u(Xhf$x1G0-SukjB611d$OO&+`y#AQ55H-lw`Ke9VpT(&z^^a7~Pzi$lwSOZJ?L>QBfCYYXfQX zS^gEZ8k5h=l$o*@Q%Gf}u+K__vLtp*!w(9ZrhvQW?Gxs5$)F=!=>}wODQZJR`0%?q~sCpVHK^ zCRsD16EksC17WRR&O~I3Ud3*{kG=hk*&)BFsW&0v8g#6z*ezKHR1_mpvpHjEy-T@9 zjU|C6L(Ujo^a1!tQlFp<7#+PV;lBb_2lqWm=ZUNgDcy{`9l(OKS z^SSm%S!{g(d$%+ zBWk47DE$Vl6WS^OI$!~!4>{&V>P1*;FVvUb)L)Q0d#x0nuQcjdb$>*IL{98famXkl zs?*ktR`2FCSmiI*g`S|OiNJpg{+k6V*@;^FG%e8YkPpk)7;zv>^XjH>M1_#k;0DOm z6hM3%^0_7qy!QK+`}9u#X1X*bgz<15q;YA-JI5Rc;Zjn(q%D~~>7{|1qQxOIrnmr@ zI?M_Xt(4p6MSba|Ah(kMR&;H*`jU%-^?7W`EirSp#trbn3b}d#$XmPI1eKecds8#| zaa6;X1Y=cW*34KNkWbl*Rywe`B-?v^?LJi>RlM{n2aJywpCF)8Mr&Y25V7`}{+O{W~qv}51Ujtq#c@h&5dF@Zx zmY&=IBU-0LB{?88`;+;D4NBz!WAQyRv%Uc}wdhVw3PYJWqNvVoA(y|E?bEf10lL+R zNk|}$keq_UY6E#F{4JM}f}NEmM`{3wulmIdEAcMR7(klwa9A-k6f|nWrPpiT6MFxr zlU&SD!oq@~`pcaV%0gQ6_M0~uQ}4blZm`SSk5c9HDh`ssr9(G7z5DvIM5X{sd^U=i}u4170A;{ z8+X-NgS{JG<7d3kN|;vW#3M6egqPr_-)M6d^!XEzJ5FZ)?)}0Dj@L5=d;eD@#*!A%g$IoOiaI3C9c@gmeA2ltbcMnf|2lp)=@XpcDv5sa2)$b zvtbbpP6}@Ok{}M~N(8kGm}m0=*HfrjTreDbba*(Dnv(%yMx}m6-Ot+qFtP%&@4z}$ zu?rcnT9?^|^#E-FoLIyvps`;MA$Tn0`RWOoltMygeey4ry>D=z+rEvRTDD!pymDY( z5dq?e~3$>0$S}dP)Z1sM(?wkNImC<0F;5BB|zMEhx4?oQMVg zLcL&rJF?Gdg-2+2jR5oz=K9dOY4N<-4f6SA;;C~@aFYfKLGuG_>p&2g*X-2{#Zd6l z&tKA%G)Dz(O&NVGqYCcVM1h!YvuEFJl~KBS6{U)*=m4UsQ?@B|(VOwH*r5R5uA985 z3*nul8Q}Jh@8Ng%3+*bqdh~wX6Xa|noQ{1g85U-w(9q8x9%3T0&~!yPKjwL>8q@7> z(>*dw- z+lr@vQf-^f-QE2LzzToAzpZ^g(c;~hQBk1|+Q6N;2R+w4U?efcplgp+&!prE4-?7x zH^RX>cdn&W882F~?=<%Cd_5kP zy^gqNtNwvHr!Iy`M2kY)wZA$E7|6jAyvEjhVx&2N zx>u8c;=hS6E`KX&$K^L+(!^yD0?@kWhKb34%B@mT7iYwBYZsR$)xQZjP-*?qnmPU4 zxcj^jru#;Yz+@YFgN=?_ht2Ue+y2`F*bh$$kAHJiB3y=_Lz+Zs0~W53PvzSZK*2cP z)KM*m#4b<-oVs^0-Hu*ver$cM1W3+BZxol~SIPZo07bcf@PW;#3&1h}p0NgqByd3*0a^wR^S28=si?si{tlq&@n2{{HyU5(P624GqU~ z2q6Rx@Gvu&djC7`RiUkJrk0t;FHF#+ys7 z`%Eq`K+-A%w_TE9=4_CN1X0scviY)pWjAu*qXblo7oHmoE+u&&MVJ&+GF0ej+ST&-|Y2Cp5(oMkj_DNfXEKChU0@HuQ8bwv*q3PJj*uS}EcI^=8 z+@-n@-XI7jKp$NHUEt=h-?Dxm#U%4dQ1n?i>;!qA!5tc)+wIFRp zhq7^`L}Rjby*n_C6FhwQdVLR^PWa=keRH64!nvpUO#gTzJ$t_^Hrw;(uWP(69BTvm z$1hz!h|Uw`w!N!lYb83hkZPlNfnU7^>k{6h7385>OwwCF(799Srlh$>5A18{-n!{A zQj+1{o@*ipu*m!Q*5F~Hf77LD;n+4SMBL*WnKD2S0B`p{YfyW0Z0=_6EdB*#(<+t-p#G9w%c^8w-N}$$f;jmDb!r% z(h0ybu-2qyqBbVq+9LPn$dnO4p(tfyj$3k|h2AN?SE*pEDT*j}D=ShT~b{W5Qe(qYWRH>6s4la;;Nh#3{N>}FH& zUoi=^z{N@M+fcnWayl2LJz?}?&$6K0MmkRQY)k1Fl>687*b4>BzR7r zLw}h#S_!@}T5xpyuId@SQC&VXzmh1@U^&~5PCk8U@u-Ux%qBBgotK&D-nwyrN8A?j zPm|cOLXiuWA;hBhPU68WuRYfT>b)>LK9yj{t=BfIGCnA`onC_UkKdF8u~q2`GW9#w zu`pLu#JKe)UH{B9JNu(gRMvQF&h58F`XhZ@(Wr>f^oGK(-ibN1uYik9?7?uZ%Cb4} zv>o5NSF4hFtEScu4pvrhkXquvt~cP!$%E=YX*}nS?TmaPL7`*~B&wv5kiAx2p>3R1HF9&0FC`~`urzv^J_)OVl*r&h4zY&2=s6)PW{W~~$ zpaL9nvBB_^_GJbnF#_#t=q5RBq*qf4HQ`$+?zGLSv{o(5~HnA_pHbXCvWB*Ei+1 zkMq6radtDfx?XVzmSPnP%;-E;auO{YTPO^bPe~HGHhAr;E=|motw%^njr>q{lgID( z3IF9vZ>2=(t|mshJ<&y@iwj)e0BlGVMMb$I5=d3L#r0WPGIcyizkkeTa+c0Z<`Q>n zc>ik>5C{pbgV%Fs6y*6ZI+QOAFMq73Y56`6-MM=$PiZ+y9wqXk-Q<`ok zsAUL~l*O-2$l~qv*7Q=>h|Tt&txs!@JP#Y>KA&?KG+{t>j;o==&mB%S->kQ7;>9XG zT_i*rP3!1aW5G=Gf=bS>j|R3nVQhviGnRm1G(N`$>3FPN>wk+q@yawGhK!;aACXvz zxnU&XHlP>HVI{Yt*i<9&kzi~2Ao7QEL3&qRoTWZZ`q#Y~JIL zahU{6*DOii(gu`4F2~!GPJ^I_wQB*&h<8#_KcvBfT?)4RLvZvC^F3p5lCdKT3H9Jo zjtRZfr1+yRlI!iIIrUSzaXibgWb6SAw~+6*SEoirPTp(K;zfRRsb3;}+j1S$czQ^oMXs z$G?g>Cs|yMSZC>-m5*rZ7c;=x)F^S(-vvey{Ag1!Th93%6h&A%o){G+vD>iq%%gBl zys5=0*4*~&B)GPcQop!jp>`ihCC)^wlZxdl$@+}BUF1+1J7$IV7laucP!Qakyc zbT9%8$xfJ8YB>&j_X9~_+_@VZY5wMX-+58<*?qMG2Hs2bd-0a*vk6obN=r=GvYq2F*k|Lj*683==WO-~q{ zo8B9f@Zv(W_wQ%i`FWzaUmP#*+AW2wsAZPZB2#8CQ@@ILC+2>m?9t5KleAjL0k^%E zF>#SSb(D$;%{UQTJ+s{aomPW>JV3TRmpJp;jq1vvK(d!X+-q2pRQzKSiGJ_*MIvym zc;~&jM?0yWDm5nK&z%2G&(kT65H5aR5|#5Ob|P)UkyLn6Q~GLYToYxPBD!|oqVmT$ zS^A|CM8i6-EF2BUA;ZkroU_f*t-ixU$7Vn|j@o3izpeS`p#cK@!8x|WVJnhzd7$c* zY5FZbMr-t(7{G&5Fa8@8)w1NbNq?#H&M`q+}!cBO|9x?8M>Kanr z8ztZQ&abrNw30sZvR{N^AxG@BzwaFDukThIFYb7|PIwn@VsZr5HGjMxMgB~5b@KTs zuM%H}%TR!l5O0^c?t61e9^=2n5gbk@2Cbc;HE9WU$VCIGOg5`hmzCUk%&A%Z|!69(OH8m=1j1@ZH&7&M3* zL;)ihNbcpr`|G~M66}!TL&^_xSZD_&Ok{0o$iBhk|NWUCzQl9t6?=qeNMrsvLe^+< z-mv5`>VGJ-{c&jp1P2Vm?f)m&Bp|r!$cGIeC+pe6P;u?@-2LeO*WVwX>LV)s2UP8` z7Pc3(Ms4`MH}D_?aE@W@*cusk#lNFhQzGcC3WyvhMM)>#MiLn<<2b8m(l`(aCn9It~fYrl`RAVy-LV04IU@)6XV038>LI(TYr4C0ApI~2jS$pND?8Q z%gl$^0WK8lNGI(#M3BsgpYh`!qO{u`#@9M;-i7z8Vb|+XKS<|J55BFBzUhZ&i#E8v zHf+?K&I?e5(<^`wb^RlVXEPOibEASz1?~$^G&-UqskCLG_@xM!Q~Y>Bb^a>v(?e_- zg%@Ru5PnJNu^v*O4Z*IV3z`|z*zIHZTSE%ax zF$AlpYw3&rk11#A!UufU`!{C*sUoiR^lnnhZV(4LFv{AL*w|x)-m`fUH{Pb@TEjOZ zx}JJ`JMFtR@$B;E=$V%*&Y)jd%Y(QqBYdwsz@$Q*!gVD5Q=P$n5hSzSZ6%7U#C z#L@#mo6>7e&yQx@&Q}i?DM1(ZXMJ0joC}eInt&VS-#7!g#-bzIX{PaZX)KWfAt_%B zpvVM{b$;^L|;K~M=uKU@%cfr?nS7)WjA1>HQ* zGMrtn8ic03;Zev7jN;0y84FVK=G=Y6+m(Ad|Me!WO16yT?yC@)expd<`@i%!B!$Gl zyDdK*gUuxJHozaf>f?Dx@U=$?n5Rd~9a@Ib_k9`vU5IiuNf!`jb zfx}VZ%^uj?#?gnX5=)uzz3roumedBC#!V=9I^+dYNst-!g z@aii@_x0BC-^Ju(&%Q}&JUPns_JM2F#WV|Nw-ur^^}_SEsGkSLclc1asfcPJj+^<8ZZa6l}cC$GAXn6->Qk z{|+33xa0g3&Tkc$nrd+H1Dj*JW%e}@ZuA{c_lyA1YEvmYgOK{8(Hg8`-JtKL8o~hq zLFsjMM0}KCc@O$OT%YL`iM?TZ>EjjO(+;#VH^-wdN_cnSrMIrSLPs>$#Bst@>TL#Ip&ek={d{+|f(p>z?2>23TG&IQ zPiKjSvF%%L_`tdEuQQzv`c@sKFz)3($6rm;q;+*EoY(2Jn?0&ySs$#Ze0sw~RF$Do zQgTAY1e_*ABM}EuBMJP+s}$GA29-jcG;L|am!Fy9jdT|EN^SC+)hPbn zV~7fyQa?#WVLTfwkQ480&Z_3W?D8%wE#>rg2FP3psvz|mgk1qOtB6}Eyl+mCta5Uu zJwj^9b_N$0JF1`JqP?;p8r1P*elPt)iP3i4VFo*02Y1`{AL#TA|9L+Fy&u=#yfgnA zTxMK|<+VI<63Bys+}b{U`vx*Chy+pOBvasIrxn8zT2YsD*CBqVfs?KtT4_#c@s0os ziLHT^Pja{#O2*%fRXLnC!6BClyrvd9$!XKt4|uru%tUpX+YLOYmqAWRuOmf_XQHGv zy}$k7#ze`J@b#md@mXA_+bBtJJG(gj=DzyQ+`18Pa~y^?zDK5I3ASEU=9FlUVcd=JNKJK6S?l z3;L;Rcg|}W6r;J8bm9)lxqPRuaX&~nnlL#ko>}@(A-uDn_I`?Ng^|;9*ZTf=hZ7Ra40~hK?;=jqF--1p zewKOXUetVGp@O_+qNz+STr9S^;1V(+#nZ>EP1%ZsToL%pm82g&sQj$YrzLkLgY6mT zegN68TLk3AION64?>`h?_lo8B-M&8XQ+}Y%kR~uFM6o&Hk!8{8Y_i2U=FI!w_Oxlp zj`2Ant+tjC1k1JdI(~kB^}m17&;3I-0;kibWZ}8Eykn7kp+rVbS75HLE98bt<>ab= z%`Q&+(oS4A70^Yr%_pMH#b;}0U!?cLX38ky!K3SB{qyF|!c)@1R- zTx9i}9Q)pdb{pWe%-@p?={pCd*<83UI}}3~$p>?^d@G*5yrzw6Xg`W$Xkb9o3g)Lq zuibz=BPuOD9(&3b-~AnwauyY@1cf8+9YByHCx^>xlBY znUt2FGdxhJpJ@t`9y@8{mTYWnwfOhJ6f!Kl!+P`PSXBdLl^?+*feu_q6^ou=_Ob!9 z6#yP{t@U-0pdFKvZfu{7B1s)j>% zItxsm7}q^;UR-niyEVx~CB>wqh^PIFCcV(Ce_25Gcez94+qYymxVZDXv9@FiIHmzt z1r|m*a}fz%xC*z2r8KTlqXk6~Lhf4=iM2!mgT(Zx0++5B9#{TR(A{41ls#U_P*G7~ z^`XeBEIv*Cy8Y~H6iDdERkH`X`d|`6p_r8E9~~Vn22XrvPmlKhG~#bY6+#bQ0X|q| z8_ZTxD{~?(3<@*|ChHS<(|j?en>gEh#0Ajsu!m2se5h_lG~QyGd7aHi-1|@MT^QDn zlu9_T^`yDOPU~&--xPNNeu|(UC3+=v-Ts?1XRpO>3D%3*e8xS^2(7<$A+3G6+?5!NZV^C_~#APDNj+8MyzulUD(G#7~T@F-2 z)6fXA-y(Tl0y3Mgf<~22gJ%yw$~R*65qioRCMNZX9G-{|V0H(T`KC-3h{oZTjaIwz zK?}Bh;!Q6^Nne9x9qr}i<=iT>Vh}$zEIB>Ja4epWo$T&>$vHhcnAk9WcAw||SY`ku zud&);;Zhc{f9vEjwX&wC)itA3US9t3m0JMK!SOBP^(CrjRQ!54M1)*5}_t)xHL){2p~jp?JAnV1U%-(=8bC;6-%D3oa88 zi}6HhsuHp(<-d7xqW)LPqPN#Am;ieFo>k`z!IW;ES5fuA z^7}tNSHx)y&u2rh=@khG*i_Uua#hvThN^i8_D8Vl+b>;<`j~@#P0;>v79OeX+G`2{ zPaoC=#Kg^=Y{bMHYPk?V^NOvX5Vy#4zNq)&6j~V>M}B;~^%%iPPE3c>X@yqeyxkr5 zB2>xMNm8#U@7%%L@|RfWe9gQMh9;EihR5mRRlkSaVDqi9`cAIx5{Klvc5ONLm+gg$ zwZJkdvv6eHT$ElI*k6c7s9Zw9$N2R2)aWtdv91m3wb zXVHI^GXC*=2+Ko7U52o`EVP~-$7;)cTG(hj)(?d`H3UiftiHi)5A4%Z;tA39CUcQ{ zL$*Xj6>3xg5S5K*f_|FnOC3n|BQa~(X@eB&?`GmkWUbMbhbd=A{HZK>J70r?E;nH? z>JdvWi>S?8TQCCtZttyW`^SJAFWtyv+ADf4?x!zKaKud$;p-5}0jl5}FF1ND2O z2sEW0!|;B<$pHgK%nkqzT8#pv%^d;Tj>#8zMlMoIGevr|X$Ux@0ot4j`Q%rTAlR$_ZXY<2a+UsB~z|G!pZeUS!J{c#! zvanc(kd?k~t2Wx!n-P9IhzghHyJ>Bx3Fj3Wx&=)hX6A>DWC8y7+!#;Pk-?Idm|wq$ zf0tAHvuQHkW^%-)Y136KXe{;9y%C2U%YkXGD^bJ!R2u0(xZ zJOQjLCOYS?6dN0I&ya8TO|5=XG@J*DJDb1lzA8kU$6cR;f2E=$^<2cTGj8scDK*kK zRsPjtP|&5s+rvGWdwWaDH9X`^Y@(*0H%OmJRHXPd$P^AMvu?BL zQVC6=^s*L`z)cpDXgob#*h`9){D$?jn1Y(9f+mV#LGy~0CWFPN#r5MX zI$W7+AEBZ3dvA(>-|L^L(7pLT>VCr2T$0xhic%{q`ln4kZP$6P$DkJ$tlp=l78;d5 z|JXh$O-8)9=61)oIMsT3{)fJ8$$2BQfr&oJpcu!(E^Vv(7R6gl=d31u5^0qR{cj`% zR7mC2sa@~A*a`Ov^NrSy(~=3_BjzAR^!R;3n}}0iF9e20e)h-OHDX*`<(HRU%bv8o zy?^!Xy*3rPhYCF5UumT`NU-8uhaURX_h&^TDZYGeV%-YXF;D;S$40b7oXLd;Dc&Jb zaf-RAEKe)q?@hHe?A<+7r#z5hQkz0ol7Sr?^7kuEq1>a&B7L0(^b*_tcWs6B7WbMz zPFXz2TbF0x3bNU7$fFTRES%FQ1@6E6|NS)q(SJTfK*lPsfxx-=3I06*#L55taHaH5 zGpa^lA7S^-{M9j(9^JL>O9a(3t!uC+BJbr87R)Eg^;OP-mo`^7aYK;0 zSg-19xr!A$=43#e^hJjzFSG&@xA z^;q8sRl!muV02^nOfGCC^0B-sA!O1)7YnV&?+}+)onuE3>9EO;8Qzpef~BLL>}_o_ zUrO@_++3s9{nQC8L}N4$wzI_C+a+nvY_1vj3DFoh^bvu+MC0Ila#r*0u_ygcPDIWi z+J$t#O%Q>=6YxHXD^JwP&4l3tz!fgPf%B=lk`fL8#O$jWUz3S!0Fv!iCP~PjznOM| zk5ns&+%zauv)V+~z&mjT2I2W&r#2*}6-twokvZLyUxczD^1`W<0srpZeeH3pF6K_n(xZfileqY}nLyoNYh~LO`Z1Ac?z4RTkQ&xI6-qMCkne)r-fnyYr*75ZIlTisW^?!mWh>&foPw&*2A(Jc z%YE0GA2h`-ZCVBXL!++h`Ne-vQ#G?G(WPo!-BKMDEwfH%es?%$?Uk|R6LoqulXZN> z_}$jAS$_x!+|R=*ClCREvh!0I5{|Malp)NzH^$Sk(d<+VJDv0 zMihkQRcEr=L*WD#?k!B~)Ob0niYu?+kTW>5r;k1G$Cns~`bn-Y7YjquF{O_){Wo2BjP(?y4rVnHUgP&y9CshzSa{CVvq{Ivo_uj?EQb}xvdCnpj z5tVPe9nV}j4yRZoriN_A?4Q>&{@;fU#-@=ZZ}lUT&Mn$F@%3|+#%eD*8sG_RiMOX|t%6c)n z7K7nM>f~yVWh{HDPj4-=SuoOXrn~WGE6v46z~ic+)Xplx&WJEV)ftae`(8_(LSH`nCjf-M&p1h@4X$E&RhnB|xn)vCSfY~l z7i*_9opy1gcW#eL@aW0@0h0**ANyps_a1@^)9?oCN`lYHsER!1-@KO5e)fQ-lz=E@ zq3k{ntBa4AH_V+;ue0rQL9e9*U?lpJKv=lw6lFh4*w}Q zo0v>lLvIO2>K~VXeB{63-a@y)p)RK7kJ;f~}us9rUo?qaK^^!%wwDCg72hNCedKr(RLciN3B_+35#2p5P217_g=f}&-A9`Duyz+EE zaGy?d-=3NTga`8)cnt&)AZTp3r@46J;%4Krp`&Ed-dte_~cv@XSUM7@2c z(f3h+?4NPO`g;UWt7BW*Z{@5`vEhjjVuR{<^S2nI^b1-Y=}U2$fYWUn4dJp?qpq1g z*Wlv0Jwh^qxYFc1DR7%hV1Inq{o46Dzl`s7ScKpWRLd~&|I*n_k?Oa9IYo^w)c=O* z^P!x5yzIwB?^FUqLkR#kq>wdulPVkWy+J)!GB8ZpBFuDw6oE3`XF2u#g)&-bs4F1pi%MRRq2pV0 zolZ6JxqlR|Olp&|a;U5FK`4+NhgivmMuPHTUAczVkQ=U`m}2g)--sDVNf*O<>oU$= zXjt(Emu#*+zeEQP1OiV*>0>dB%jQR*{cOG4HHBFGs_dvSikyB6{hH`x3F!9KXkN*-1j_VGX#Rp&{OVpxTpc*_IV-k^<*QJ@#9W3yKIuB@ix_SV{)Y}5#)=bBxvpI# zX=`q+ZkB0oBOyb0vq4~AtpD9*263?M-_F+wfz+}_IxMt7{++XBuS;DK@R>td8wkJ7 zg#AB#3GfbCfn=8v8{-vGz?+Gwho~E*eGj964;RR%ya2xOeLL>6YGak8&R@<^UXsXpD zt_dPy{@5Gd2dgIn5fl_OdNwJs%Xf7|@1jw8{d$ks6r7;SKi!<)+`LKgXS}N0W-{}# z#?uAg?I%>RMPnQLE@e#OiA?c=CT}H{KYDqQ;y5;M2H_QOhqndzP1e{cQj!<(2ff1e z8?9hD_t|tUqLg&`$Nz@;hzjcGAQdGi$9NCQGmDUbZEXPgz zet*$hWFa?33uOKMCdWD0)q)?o?7sV)faWvNK_1#ROi)l(5`B)~(yJ*W5Pp;_?8!a* z%P*-0UlzEu6*>d=uy!W32WFiPGlecfdw>IB zo7d2ZoWPftv29)e6v-#*AZx|}`~TGf1O;7yZqT3DzZ4abA;6e|kdYK2ykahrcWk9K z7D0C-4%{MM{tfe+YfBYmQ(A9|9Qw@X4N-TdP4b<$TSq_!q>#`>Uf4eZI0YoM4}>G` zxM-y2%O6+Z`8ndXmhdZDY3glK5+iA`YL5#?X3hMorLe&={JIia*D*npB%N0+LOD;3 ziri|9JxxdW65<|tp~G zW<;fV=Q8I^yV;1H4Xm*i4>wIED|_-ZeD3#J?2&;WMO_@`=b6c?rk{yP)LJLhir9X_TU%q?#^yw>(bMR`kmOY!lHC5hxU8(VDZKj+I7XJM%vMCA1 zw(&mX3%V~dvJCxyC_H<6NGMIOm)+;I5MD+i(A_kGqU%-S)KX-W0ft#*9=ym135pO+ zqBtxPa9faJ`RuupFefLyjw{YLqF~*(EPQ@ND>&uA$jx_akgs)-a~)-RMM>@Bw8X;d z)`8m;%lh=-URUdjXT;}2?=3!XOoJ_Nr1hdVS2~%&F$8tf$FDttZWR+zF?%o_zK~An zF>ks(R~PGfh%()1uYGi{@}E7k?Mtszt3-Ie2Q--jd#vT2myT_25g{O7b3YSJXvlhO zc*(IC^{`ML8y9U(J472nCXC}&gUz2=RNBiqz|p|m{ zl8_RYn%soZ75ex%VJou_E~8{v@S^Wa<`zpcs@6+%=pU$G#m2L$6MttkPYTNwG>}O? zss#ga90;A&@3G(<3xStsnuvkvQ8Y?WhpmJn?d-CL^+!CY=DFlfxC)9!iu{f)kqMtJ z0=@^0Bn;ggAk4QgRO})fB~5O+GE5ZCzWY>3sg;$p{Q7fkDaNVet2wy> zxIp;d{V!VPuOKKzWYz*>6;AO1r14ZcxfpF?nSCp-wisk4oT-$%?*o` z&3h(SNg$?noqq^to`!$HeAb5_bwHS6h|79;xbX~gvW-Ll+vYK7nT$_XGNP*a@7!8o zVPL4S2Ny{?lz5*2+dNaXoRR^Kc3L%_Nr!L!%rOJ0rxi<|=v`0n6Ub=Qb`Ll`+=HF~ z?B#P>8am$Y9Nf70l?O12EQntgCIK=K;^!!*2d=yrVoCM8*eSI93O>MB4}W%V1?#P(%iPx-t#O-3MfTv9rU1Bs=$HG^u$X7mGo$;T zw|^g0eyi#$UA$S&`?qGh_Jsd+gMegIVZ+MOKytKKa!V73EGu=}@sl%e4nHmRs|Xyc zGj9eP*#5B)Q^RsIM$6OHu6BC-)G={!&9hEvPrBp2=H)3t2;Ta5tekngsdTum$w=A~ z)=uxIS)oxTy-I$DZNUdEpB4?-xN!V->?`Cj5!m3Oz%lBkCqP z`r1szzTA^7MU_v;J2-jW(ouzSKFluDU5(8lCv)HXna*q*pdj=Re8Q`79X}MuW83&M zrj}ItP9MJK-m|x_1b0d>$eEE`VOpyke+9OHM*??8c*ym>5{gCOxN)MTB8s$)+DKW3 z%$6bwDy)7|Q&SIkS+HI#?NYv$4~SWAC0%?cJtDOqFW)=>SBCWpXgFBkselB)AKX^I zxic4gj(pYgzmv8~lfhm8hDmPqI@?vaRfT~3q^I@AYq@N0(hXD(0KVWrk!6QW!WWwP zJB#fUb#(5!_1I@R^HQZ#W4VB_A}kqy!sO;Rix(6^tuo94aZC$6=vf@jsQTn2iCyBJ zvbnA<`{~bYwFTBPQ4DWSC)>;*$-LE8*0<3hLQv6l|cJgOplz#jFx@-#W@rP1msTB}*^4I}(o4JMYaVGDW?cNt&l65&|2Ph0}C2JwB-*T4H_L zmrCB|rCmekbmIPYing?M6K_Lj_f4KPpwqzDZ8R*`T~g41;YFktdJr~HZY${7JsmKu z)C=6TdwPW}I<0z*NQv10!z_*8Qr`K${#nUKFPYtPsYHq?@m|qQ+mf)}6KfLOUH-lO zF3Y6l7}Y?^ap~JOebn?DmR7i>ctd`Oq9Qx;@}#lLL!(H~`y2d{$layEi(>BZy&U4l zO1a)iOD|TV!6oeMpf|#4cb>oMNe}t)Jg{~_Mx6iVs|R6(HtfhEB&Ea0LJ+OLsG3;6 zS+7^)c73?Ocs#F(k(n9u0|foIIoR2Oh(pH26bV8@GR26dBvHw50PLh<^#;nL-ebK| z$6TDt-yfT-_u45#$cIg}9{;UnPamN9UFJt2R)C)PK012js039IV`TSs^So=CMxHB< zT|j_jVhw$~mkx`y9N)=ImHYHv`)70(90s$8VfR0j%3Oj4gp;gfseT#b>wYuf+DvaF zxN3e|!Pg>-*pCh^*Qn7~e)jr{);MioNT-u&q0+=isbDLynb1wARa+{eZ`0Y$ino0* zucR`r5Hb}uKY#b?#huHzlrL^@LvY9w1hV<|=1Q^?@`PmnHV6nE*QY1vbd}oW746Yy zQAfRO|IQdD^HJ{MsnTx$4$Vi(d~!Cb_>hR7)n!_A**Q6iN=kv-PBT$TDMkJB~G zzyj+RbB%}@?AFtskdUqgcbP9LA|mikMiVT!`#QP%O=cLD-nr$t?xRGq4@pUCFRO(` zX`zR}SiHx^%}j-t4|*%+T0kUcKoE~T$oxgL9_}^(U{AhR^xg!6Jz72N)vTi~U`FpCL^h)vYyr z4}tyrZpgepK67K?)7SkaE`50On{d4&5VvMP>4eGKcqM!!XTFr1YTg=p1;{LWIX1Yt z3X)eFQ_CIH*eGH`4euV;sv@!F;h`SZbk#o!|M!i^$$CIjl`Z-^8C_Eio;W9Yn7Af8 z;c<_1f#17Hg3-tVVvje6XU5@eRmXkIauKB+q#WYn)QgLY$SWwT=Z1QooOgHIevI7e z@b~?l_PxewHo&ezF0svr>FDJ4DWmlP>1BfxBtrjBK=|R!T{%vA}6N9&>5Z`M9Btn(6cE(wd`Lj|E;_nYqj01! zEruHB1chTsXeRW16|aesnYkW>r2@~tB%Ohxk%1`9rMp))Qat?TXTRE2j7iM##eDwttbh*6+9IuVs`vnU>pm&RDX3g2{Tjj|?}qe(2_0j5j| zACT1Sx$rXRrZ#{3oQC;mr ze7SVpdHn)AM2tu^&Jm@zr!MuD5&3jmO@;Dw;w*|o+g;+E>GNa4$}m-g;B7u(;YTVP z|DEDsVLBQK)c<#q^Z%Li@crL85Bq-kz+Vkqs=)7tRxY?9nj$oBG#f?wL} zm0GKdCVA6KI$g>!tcLR&z#Rs__CpA#ybH_6Pv-zo=nTGtVc+xK1IRhbflRy%>$Rcm ztq?IF)m_#joT0oR$QC@#GA+3{Po|z1e&27DcK4erl!<*n68jP2jL`s96IU%i>s&JatF ztd;hwzLXBi+dhstt@hV8-oQ<^0J8FkEMyNH2JAkUcmn7pyu$Zh0qQk=bAGX+ zUW!cWxW5Evj-Nn8P5b5zK!@m*l->(Y{NJopKgHG62lC1>jcb1I8?Jr$!nF%eoRzh; zrXz(7tMqNL5ygY6eLYksi9Y7I)EzP& z1Qq4y8Vla)IAcSp@>EWa`D_j>S7D+#^10hDUDY!if#0di=$M-b9Hg*oQ*H#;AteMlU{hdU`qu7{#jq)J~7% zIA1c;`o|8eYb@Z-^?y>H;TTLlMVi6<&T!3m_7Pm;3UK_8!|ZI)?wiM({#ZWUxnlgJ za`WL*A~go~woCIV%f1i6a|bUn4!oN8KnOWP<9^xniJ+`(GH%j%9&AP`L5*uYoabCr zh&Oq#0UAHKHkp476*l}t0moBw_Y?8gfH4mk5e?xe1m90r0U?O9y@x~-{5?RaJnFgy zl}#;GJFG?$;9=ztHvd3(!#WLswlIQytHMbZ-Ui>`7m)P>oKKVcpS(WK#6Sx95Sijz z5Xit5^Y%hY0F45WEmdJMu6%j@<$FW@b?phxEzAb=p&!GgHDE1z{|$b&f)gw!Oetap z(zq=J>;94h`_Xg%is|7}qGLOw)JyILSdhS9C@Lx%bHS}e^L-a#-8HTExkNc6bStF`0?0qNJ6lop$#fm#TPFI&7**K_6)%)CbnPg zXL$bcg;G^smj>z^?mc}JcdDGaOY2l&jj)-QObG-yj}swYeRk{wp7OJ0`2?qQ#dY>IqE$JI;P zx$F46Br+&1{5kyH%efLyV zKPB{8m=|KG0`u`0dy{qO-Z35f5_4(_^S_~%^hg&p(JyELonL6hlV4b;j}bDmNQ?mn z%6ZWbTMnkXYc1pod!n##z6S*xx_;wO!=|N3<4KHPNS zQoMcp3N>{w;3<{v+$jP4u^I$1Fr!YLM_l1F3(|=ogZwX%8#+{$Wd@Ice+t=tot-M3 zRwARDZW^kyPLgJ22Ii$>Ffl*v65OFGQB_xO+ayc)6HB%tD0!822D4w-KJKvg{o8SE zVxyI}!THu}E7tGmlwp+CYaY{GnlL3%c6KZ$uAwW4A&5qSMFqseL@V_-EmircEt>*x zC10+PVM0&#wg;zCP~*3Rkm94ABwMQPAb^H^I~TG=lr&V0yTnsn=lG^g!=Ak=tiU|Q zjE7#vf1VceX*$C1gTxDF!k3etX{u;jH?A|kCwD_Hdo^yIj_@P0X}Rl%v1$Y_J6ZYZ z3jj%x46gnAc@(2h9twT;Y9l-Y@$1vFaJB)Ep(3d00;r>x*#u_}kD*q}Ugm?-`=SnR zWj+DHH;RzS9wvbsHz=U5>iDxza`)lAdjJU~LYRS!T0JZb_-i84j3i)~fBg8dJY)<& z6byVb6Ou0+$$+mK(%h)S+hQq)IK!?409Lz!vRs-D7;g4EFFJtK8?%*q)S4t~iAjm` zb}9K+=j(p4Oo9;jYt;oUrFL21%_&`Q`u;_*{`Y5>fy4Cga|45)s(VR5mI1M+g2 zi%iQ9nUp{eagxob!}nO;WP_)Y9HEwatFF=nS>$uHc&r1Yd&e^Py)t0ewmjAU;$eTH zO-7dIUW$2I>lkQbaJgQ_tj(oQHsr~4gD>9_)s-w9nZqQeAxgp(87{_8fNIG9s`GZ=%-?8<)IZ>k8*c|7EN2!UEFcO$a+iN9=?xS_x{4pGTPnWtYPW`3#J>2#tF4+d4Jye3qpJ zTAbdV*V5F~EI+)FjOZOb|Hk${m|BjTTBZWwY-u=M5}*(G=gXo#2A4YX5cdf;NQmfg z=O`mi_T31ab`MHu7_`YGN%KBLEy|fSqStqkr_TMJ@7>5c$Fx$G@LtxM9334gM7vjT zVVr}WNJ=;ZF*(I!ju7$o#YkmpZt6GsmOntPmn-;XTgpU&560H#;)#4)j^c^N_lc`o z8=+pe_54foJ~>%^y$*5t*d7pG?u@V(*VbxFNaHu&;GbFd6m>Pp*BPYZ)3IUp-VpYI zR0*W4OW$I}#BwBqgzZ51uMcZ21I!R0DT~6$)SqKc?u?&+O71@%o|9AAXV1n&uiJ~Z zNAM^d|6E=_ixwdd8`5%`O;lL2vJ|uI?*MB2@EzsEZ$MPE=_{1BV^n=ry`MmK)X)rfp~k95wuu z-Nc=`D?VDP@^|jweUxxyz8rYUz=^1qb+7m=kE%mN@@~-x7&-CS_*}kxps~1r(BoK; zlbxLo$Ahhf^PDydg?sl1r65Xx>z-KTjl=AZ-(S?5BW?_(Ud)?Vy<`f&_pSvpo&n}UN>DICi;oF0~&CVfYahQjX z{bjV|QwEtaa;Db!KVC2BZvC9>@qf*nYZ*eVK|=Kcc|eQT(m&Dx@~8 z;QW9ae?tP+$wm(IcM|k22l(`OHa{j=RA?LPYV)ogiMkdP8(s~}O8|_10=(7ZpEY^- zsV{A~NrU$o0s%nG@pfr>pcHVZ_O`aXV^uEKdcJ>GfXBJA8sxo;Rc04)*Dsp`3Bes; zSNeTAdSN%2=;K4j38=SG$g<`fZfpu-hnn zj+YWOV#na)KyrivW?s`;>GQ1$!|EzsEMn>e&CcO`!{zw>!UvlMyMLa2>*>6S@4iL% zCsnQ5d#X-SE2j|-3~8F#tgHmg2!u_u!eUED=}zP~7a_6;6zyIMqHfoEpIw z)^HDMH~bX4d^07`E){m#v0}@R-GR*e^q}GjY4JbVs(Ba-r`4T3W`F}gK}{^tf=`)H z)qfLFe`~K;a=o;Lf&5LXvUR0+b8g@g$EK9G5ES%ZXmSHlg0;)7Fey4*3_ zGvhJiRxqrn_C_4x}%c9AhyzaO;DHQ+BVKU)VSSRUwdCyhU@{MPGN7ETl;B|EP7zC@ZshVED-MEcuG8+dVlpkz3l<ZDDm?W;u4*T6*9&IK_ zAW8c0;R9(@jyJMP3j#@SApXa|ymr#_qSb?;`Lo-NdzpSKQUdS&xT;B0Hzi_<_7Kk* z#qw3AKr;!%LGX{(h?wV;G4n*+s`Iq-dA&itTk<^L0qROb*#mvdI5HxXcjQ~CY5TL^ zbRlb>w674pV!eEM-jkd}})1Nj|rX1#1x z!hfk|k_5g1bqj=-@YxnKp$Y2a$G&owJ9pU<&^NulzrUK-F#)(z1IP=&`G)X?4_x-^ zThv7Lk*a6niBjV{iMlzt?P*&xDJ9M%8mG;UnfNTajh2BEP&< z3fC~?3Hme~$b47l84<-&b_5$!S)}269LT{Ae9YSh6fmRD*Wal$3K4T>LYzm@_$JWa zDt(SbMCsKt40&%5V*|Dfx^8BNJG0OXxKQ4BCSk$h3r2ZP8>7M>daN6WZagb9$W-AR z0NE+@UOwgJZDa%Ja-?fj!{wG7aQCk;BFZ${3cuM+?gmPo3qf0pn|E(1Lf@7>xDmV z`5vd`Z^*HmW6UJ+izOS9GvEE>eik-tlirR zvFVW9nXT#GyQ`kaRM$Z53A6c`1klvppbkfC2SVhhd#39mBWsX1U zD*9OrKA*BO-u`{fgzNdib`2%YEjGj!${Vx)7csFaq^rw)SC7Q5ONnHHg7D>rJlh&a zQ009ZmFw1eewD=cBWc-nuv{?9^wy`PygD1QjEz;xaDE8?`js1)X|M{ZWNL=CS;YT> z+U=31W&l)|psau}?k@{B8A%xB{1_or<~B&^7hc?iLojTtP#8nK=Z86Z3e_oQCih131cX|0?4Unp^EiDq;h9mg~8)5I2z^pp=f z2G*MCokh+@-<9Kd_&h-!3dm$a{mx5nwHbQC~N>=#;@pE=Yy*MccnR ze`&zY!m8v1NWZ|qzzgw$&959P3row3b2zm7!0=wBh!e>}nG%P3_AGk|^jRwtRX5rr z8A8Al2Zu%rsDUm>_IIsIKe}&P5vzL4qIvluQeWb&&w?{P zoc!tNl=h+Z3?a?fAAE?7cwSyD>mM->R_lbs#Bd(1FGj?qq)$PEMs$gY=mJp>=UP@a zwkAQ(ZI)ZF+(|LPW!v>HAM=a&I}gom# z>0}X${zs*6(c+|v@=Ta|Y4%C3a3NZ-u-SECSc7h7L`#8QdTW(x<`t~Jiy#aX1qxLp zvy0pa&6J zcL;oZq;Ge7+va0%6c%gr_lwAdBnUGCZ49sr6oF?5CrL18lZGi_Wk3GCU_zASj@H8B z&g2Go`pcK1bMx~TQDYFu0;*?dfv98-;PH{xs`E`GLfzj3o!Os|k|%RG^9szYpKRw^ z!*U?W3pUw{%s{0_kNV9JwR40pkg2(!YfCm+CP@B%Ic+)cXhqnZS?bmfci!XH@ALaU z>n<#!ApV=(($;=>`UCD$(aTj$2z2=y^VCG%k}Pbo>+1@0!tiGBvriUYXdw%qzhQVT zav0i+@Au;clp)FQuxqdAbT#g}p^#N48AN6`a3GH0%Hdu3j5?xNLcUu;4NY<9Pi*}D z$&=cHJ)S(z`Jl$9E%Mp z6bj&^j`fk7{!Z{E6Sg2^lgqh;ZBTXF(AiZK&}bc!@v-aQlb-p5J0mV8#-_5zm|mKi zpchs$P_n8+3sGA&Q*(T@_)b{voCt}Ln7N_~!9Qc`{_+OmwGCUg6L`U zDBH?NxLb)g#74-*0tdDVa9|ZQs`a=6Qz}JR8q)_?opxpvbor-sYg5SPcCnmxxic@e zBoMVnLjR_SA0Ry>VM=obR~tL9FTzn^69UT+;?JKyy#MtF5YvmQxWfOV=VB-^vJOYV zZVc4vW^_EiuX1H5`(V+&!+9O5_mWl=Nkh8y$z%%G^aXcj7le4KJ39+Q*9d*#xrIb+ zH|R*g>vZ)cR2Tn_J#Vmyh>-6Sz0TnI_`;Le!s4XaHd{e?(Oi$ex?eoeoE0qrmR({5 zcb(hi{asF{@xNbqz`HG&4HL!=03clyatJeUc(C<$celVQ(D83|@M)Hu@6orZ&^B+s zHbaz_iqvgfalcZ0Iu_qZ`%BAd_s6LC2TgCkd>Qc;$0MY1a&!B-X=XnoqHnam z5IVyFbvS|=wSMR8yo#OnV^hrc&*&GB9=zC1MwkxWn-})-xVShVYT8A2Bw$0e0j-os zlR{lj>A3gr2Ubd@HJ>O(#6#U?LvG;i zSlioQf8pX{+_eBjtmXdI!g^FDcv-9-eh_L>#sI1kyVP^fnme{D4Dl*9+A0DBE{n41*wl31row3oA{>+WnjbGgTMP{;bCSsspSe8)T@zU3q+G(=Y@Ah}O zpC6>|o~DdpmN%KbC98Ybuy#%O+XoMr|Jjm_Yf%K+$t3O-LKcl~^qkkoDE zClcDWFps!k2)55UL3c442EF$zg=is87axKKWjfv8to=;KrX7Ag*K+i={snzr3tn_R zW4zxn$*>gDwL%J(#o*g&Y7xOt^y9N!V1T#)Oy{rH?5X9GDgy4N6pgDFjT37GmIoVM zxs2vUjzS_P{X7>bq@phpaeLM+!yA4)_B6F0hGWNtsI&EPIOM7&Nxs{|Td8Awi!L`YHR2`gPn5I`N(Tqc8f$k*#a8`M&kTD9c?U6TgqtwWlG{(|e_Y50#1* zs$RJqp>|iEa*`dOV942B;>bVM$K>8HOyjdidPu>n!5jM<+~<0WCQ0q%#qv&Y3Yr0) zzQfGgfm>exwtEf!q@psxHFTtA(vW^JCJ)z?nY*cPIY+|+i?@d)>4t_;nFej1xVF|p z+x4DOgM1i&UECBeFjEz-C|g1*vq1BbN{w*y62T;d4ce9kkOjax{0Zi~@q(szw6&=q z{sRY$EYL(R)-#&^69k!R+F(U{!y@-)yWyM}5Zk|=!=rTo34(B<-f6@pO@lR_Ylq*8 zf`K8CoQ5f^>yzo9lir6;r!~JMkBspIFqL#7!HWx2C+|6^!^@nVopZngb%ExDz>0q8 zie}cZYitvm4Hue5rO0|8pW5r(zigY+r^rsI9KN!Z@UzJ6t%_o7pwO!-yXM@z^rH>B zh*gJ~n5FfdN%v`mbd5A%60ZzpQ>?Y%yCpw(3X!+ZAo}}*i0#nV>pmwACR6V4=e2~s zdleCOb~4l7&>Qq_^pS~9kmtjO;3xME(ongLu?vtDFjz6|XQ+YYK%v~o;E-5{aM;fY zkS7>5CH85_man7`bKkK3?o!d5Ix5Nl#oXjf-HC8LbxqB+ro_AHRi4PL6hvQx&lP6o z0!ZKcW($}4KQ)0>O^vaf*IyfLk3*L3-C8EQ0jZdv9IuLJVd=sm6D(Ji4R2!8Wxh4s zSRvyIexrG6T{QnPnQ7CYEp70OgCVv}|7=3D0TM>j9H;AluD<+QP;kf9Rjj$CMc8A< zOfO$YR~_9>kf_D=T$}-*3Mwk-?^cSi;exFmbjWXDvE=0BgcEknf|!nOqZUtic(|4; z=yObJE3*4*x@%K)yLTHbvU^mFKw*D=vP-DO3G7&r?d|el|Ec;| zQli!XJQnU4Ki~&8H=xiw;!JRGo1~sGH8ecq|G6~uc;*AD$`z89%A*K)AaM!&KY zc;<>Fa%nARr*<2oH}u6p9S}=mTL5eeTp4tYjU&Lx>NTJv2mY>kG7L~_wxF9UA#tC` zA2m-n87rGF?{c}g=;)e;96CMfa7l>oS|fPc$8-ZKpnSk+00j^sf_0wl@0eAvTMYrq z8)tW0e($=B3s_UJek(z&;by<~3(Z3yUR|QSA2TU_q}?-}^QMJPEwq$F$7`p@@`-2N zF`6lC-hE~UfDs?6?6Oy>74*jr-hW$wEpxafrM5pxjKCF^rA*4TqkLtH8KTP8H7kJG zdyj~lG|%NX*3Tx^CmDJW7$a~90w8HDz(o`)$2wd^nnqX6%Z)&+fgRYZ$AQ}sH_JRe zK}5&>$jbaKyQ`!2fuwVXE9y`v`D> ze0!Gn)1cn#nq|No8Fi^O3k3Cu*UXY308L)Lx8S{bS9v$wrUvu_3;{$=03Ly{+iDZ6 zm-4_V`6B>4DFNzt8*9hJ$r*LxQ9Ttm={&Q`Ro#HYlTRXKv#?D}Hw5#p?KGb?J0||9 zt=^R~5bo#3P5?;RDxgaTGmG8Ocehk=M1Zs`))Z*})EH6QVP`=Nl^ zhRtgSpIK37W`!3SsPOn`p6ysBj%$jUsV7;vM7$&Vu7hKkK_2N$TN+LO;n3!ZxD=En z?%j?GL9-D^127H4do|0jKGSs&wnPa!{a-!iWj<|I8;yCh>`tZd<|!H2gfWAyLyIs02E-%t*DNbOXrpAc$3eugJ8J zEaMCTP6H)C#fg&dTkWK1M0Dhr3zBh{k5a#v50)bx%IB7EpJZYw68K` zG}C*vCt$JeN}%_Mi;7D6axVrf!Y~+%y7V53i0N(j( zoYiXf1V#5fW}DLh1V_nZRwD}_d*G!HuwMHI*}0TfNh z)C)s7{V>wVqq$T`ZS^d#nG2?E>mIKY1j4_Svl58rWUhZ*SfO?BO@1F*R5i?cNcE)d zu_8r`XTmmDyWL;D55B(NYg~$>HSVr^z0^?yR&q{YYWLnr0IgPl)>Qm%*|7-)OOf5$ zVBVl}ONU1g_^^D9hq?s;0)0@xqmD1e4LkpKR;_3)a$8{zCWYBpYm@xI%DAnhIw$&>nUoA0N#SH2~tg6u+^ zm8}&rFLql_OaS@~fpv4Q^zw_u`3b$O;>q02;B;_v%IZ6nw6L&%B)%uV?^T&JOB1C5 zLO&_Sky}1ONa@_hr|8nOxcw01s(#YbX!Ge z4)~ZT7#O_c?#KZJ3~tT=1Pp7ZoB(e(hm{n|22^yV&H)O3rjW11zVrAqjx{jpf;o9sJZd>_w3nC5X3$RbJ?Yjj9XU*T==`z?>|Rt z;kiu|8*n`Ov99D)$8Gz@WA|4_dj05$#6v8Y962%ZdoG6PdWIdd_a=#S38_5;_(vnYp&?eJvjb-Zi zhGD$_LQ)c&{q23h)!xjLt5&amUuR}Q5D^bjlIS68a5|=x@VU2X(7ruHp#Q0xh=L{$ z-JU5;L-}TeMD*Y1_`}2JZxV_A{0(+tLaIopK$MA^<)X-3$B9;t#$tl@?3tUpZUcXg zCcXM-ul%Y0-WT_>w$vS3SGn{@c$Zd;qB=UTMLpgP+Sn-UgyYl6kf0oRF|_Yq$G%Ip zQ0%^Qry_;)a6^l+s15;S8j+L-Cj|fYGDt{zAE9l_*@F_tFf3xXYqA#q=K$vH%L8_c zwjj%e)m2QOAOz{j>ma&!0ZR^e;llJREqUVNCTeY@Ku}UDQ`fYxJ#PO|sCwah>8ZM)!pIlTkDb|{ei9zt%93chzrWwPjl<~7 z7l6a(PDyk~r1SFi{QOf^A1*DsA1j?7v{jp*qZl@+wkNqJZFr*@QhJJyNnk*|->H6I zIM>CPffL)LDxcsM;590Jt;iHoSy^d&0Ys)#b(PNnihFif0{IhE8qYUJHHm3yH3LDQ zJCqB+x(-rp$q-;4_^icFyH5inveRJ<_9#cA;o}aqAhG$M8pENk9~FCNte=Sl0NtGQvSri?|-r{ zODIzpalGX2&%?Wrb`KKep=y5lw8{4JGxg;Gl`O{}T#h*MwI!S|477rdknL#dyAN6{ z`K<>PGw5Eb;KNccq?zG6zIJ{A0d^NY6o(syib2vkrkwJgo_wLNUftF>!0K*kbrrBL zl!q#+eT}u}e6I#r5h)xzJgf;a*J3H>A7BjZ<^-~AgKd-X zfEyz`CR!c!rdUAaFTnfG~6Ob|-0s472>7`DG`VA+zV1xQ;2l z!3cCSgLBV>;GQ{pY#fC6fWb}>+!YXmK?yvn0I!j(wG~CG9XY=$3I{m)J2n;;9RP^@ zPEDl*BaP3lm5Dl;3$8p}|CGZ-Lqo&NGjVx5<-rWTyrZS1MILMpx;-ExH_27i2N)V6 zkY>CoF}qR70Q*J&1hyN>-j?KN1A1vZ`SEUPtowwQ+oGL^`k%;Jc*zwk^k3~z1S>2h zbwpQu(&m;`{lK#wc(|quu+vyFa&qNK{{cRc@po0VP8x@{4to0o?P(IqqZ8H51gF4$oo6H4t2qB-Iwq2GQEXr)xzVNI z!5xurGc!_c6%7B^wqAdP1TJ)nE;?$9c= z65OvwMgs@(dOPRJc-JND=g908T|uowSAF5b*I&m4k7#Mwd802cUtyeHG=vb%qZT$F z>umU1#!>!_sIau~yi(?|eA%GKK!QCeI*5CH{VjXYW5}6=)!2Yi6z}mLsOcCM-GR8C z;Xq(O36gk+g!v348+GLLv;>#x6}Ey5pqUTWWN~8<(%loj z*5DxH!oVv+eR1%AaXuSB@pM@&)zqBp{jZW$k4RwqWg_JWz{fuTe@yQVTI`DZZo;6E z%9m%kQNhy;WKIDW@$%(EvJ6B>tk=0usHxL2%7^7X6%183Tj&ZtFX|hc9vppj*?cU4=3TEP#JRY*ChtZ6R^0ES3l4bO2Eai9RX}oZ*j(-Mm^iCs!0+tum&Zbf6Uh_FJiyY=e zKe*wie`F3gTnhmyN}%^(#UFI(SDcYSgMiCPLx2vq-r&_5T{qhZi_X{4B@RtYoUQl! zm;WGutw+>t@{f45A{KD@?psgCSCUm>3Ra0kC`@lpp#7cWMT)^})7RL)Zq(?I(o)x$ zalE>aSega`S*+-MSEgWy^1(9}>{_oAaB1UBu1545cQVWFJ7S`*H+@*OpSRQ9{&61(}|fw z-w{^TLd0KB!@*wiLP>Ub^k02Y0XZl&EHJD`%kegNzTHPxJ0yg^42P+&qT#N>>2}UP z-Jro-WSB0{{&E<$~4(%4^Ww;pN?|^1!7ND}B0iv${;pUjO_>z7`tlaTv%B=i2B-jVPJ136Fnj5axc&?T;kf}Qu zmitx~k(U^nyf&CSlxtM3oYvO%=STd3kGD6vlJ0L}X62HsU1`F%>>B zVkR6yrH;x&b=X*Isnt1!uvQz{UdPzc(#?V~k|4{iAM0_YlRHo7 z;GgDF89Cy{KFo>28kY$BQ6N075xaseOXI&n zdnmf|T~hp_;I<^aZfO?bs868ys6h~#@(BT!jZDb^+|Cqk(1U)-u`)Cv1Fv`Qv(8EM zTMr2Z_TA{hsRG!ie***AP;W|6DH(^^Z3J0E>@1I*H)|&a5vb(LDLVq$7cUzA^z^7a zy*#CdkTDbzcHbjmYrhL|SxB$}m$MMmBbjEMP9FSkNk{28C28{x~PCh?8Gc93P$;y!;rO5i8we&A)AjtUn3d+g+ z*)jV05f-)EX9`r(=g*8Pi=;W07`fSTEwEQ?D}XElFc$z%A(JJwaM(=%urmv}1v_Ykdz`FQnm9o^Dq zE$N8Os~<8{B7Tx@`MdCugve)*nowcja%d!f@F&-Y`@^G0gGu{plpP}@!oeU&^iL{( zd}TdgvAh)HXkZoG@zB^OWz)z7Q%Y65{Ut<4tBo*`h9uAGVB?N31jGf_fBJw0fU^+N zNnYE|pTOt;|7$-O>ObEDl2vpFTmzrKy`q5r|1)NS45nEbJQc8y`>F*rS)a{s*TzYS zWQ^B*YH4n6R)wO0?Qz8T6u@LyG=~YQf6N7MJ9>y9HQinYX+bQ5?B%+0ZRxL398vgl zbj>X?O;SLAP5mGhEv3*P{;RJ{Ql^0>139x-0dDC*Pft%wFUb5A+wjNVE`QWw2Eq&S zKRX22=pWQn2aTDP0`$G@Yq6CGG2uyAq~ z7fjPzuC~0{@0%nvl0ly*#2m*>z4_f^_42wqLOZ=`6(Nh;Lp70^J1{-&z0jW0c6Pc* zm=hW#$WBf0bII}Yu2-`tL7kz34%r=cA}kCnM5tVaeL|SJ{wQ1FJ0t(J3zai@$jHs`s z8)IoAcYQY9I<=n5n|Klf2^Tixc?Ui+xyw{qF&*+Iy{O1zD{MTK>u|5Y^YWBYPrso3 z!^5|ehFHB;^?R&?hf8O;6s?D6Kj_=s>sruptr&!8rGme;r$}4b{mu@5O@$9Re+zwm zf2hWNKNMUxvzttYM3($NlR9@??1Hw64tU@c#9!<$y$p!OdEIW3q$(uGLL$XWhSP$8 zhnRzgj5TQK4QxCYe|+R;@oAV9IxT#ND9Si*6QReLsj|bgnVJJ_uBVNkfOGc4tutxD z9~}y0Lyfk+2q7k^#L^GBPsH{ZpPKNt%Fcsu=|<) z!tx)1S>nx`G?KFEGFwAqx?f}he2S6&tlzk`A9{XJ#dVO9dqtfXPLa2kAFnTzdw3r4 zVZ)KV-j}?ivWceA2e)g4MA)Bj5cN8pjnDydE__9vQcRZ%+k;MHB2grAVb|upJ+4w(hZa!kkYN`Mkca`4oL!*~SFk zdt^XE1oULpw);!n<&%6&Orgz3qvilw`#j#tl=S$G$vrv_@)!zmmK_5fHIJ|LH=e=oE zErQpB%?RYqiw1ds^XC)T#`6@2Lw|zh?4=5z;%<`XJ)tHtkeewA9XEv!W)oo{ZsiBU z<6_UAFjDn*5XxwXc+BE?9Xs}CMuBxh?`t+a^lnaE8*gAB+og^*-I^Dlj~fQ|g$X8M z;gJn~*T|l`XO%z`2Vhn=UH4KfRl4MdgJ1|{l=Q;sfμ9qM%fZ^TAnH2G&6r-1c{ zi&OhyI9=<%!BC##doNDa9ly+R_N$!XtY0J&@%EF^?Nj{qVa1O#ij*)!jCdnD+lGiO*1{yS9`FECo$ z)FdRKfLS2VLbC8yTRKDwn1{)|+FMMJx%F`q^IE|RlV5NW&vGwe%>b-px1H6pqgSq2 z#=I%&SC^MS6B$D=2%!E4yYIh^e?7Xu)6J0yp0#Zwrl#gvR$Bqx2xGuh2j>X|=L90L zr~5=NHnYyw{&W|PI2|3SEnWIiJ1sqPRy)~Q^0&=DYrR4_2inn@#O=KO%NRvTV5w@- zvp3;OGkTmzTf>oo+wK3QAgtW zHAeIpIP%|k`HKx&bU+L+X?$L+32!Gk%nlN`m7TnK|A2&u8#|*aSl`}F<5zMxdha(K z9nic~hX0xMHRVo>|e+SxUTo$C!c0 zcyYRc%g@jB>zI+}@o~`NzqYHsGhymIv-B08&BNj`Hx^SkL_)YLdcE7-_Moz{OkrT6 z*quUcAoYurw~7cbA?l~g_UL`F&$%i%#+7uc_+_eX?qSu@bg%M$?|XCNS@9LBsDuO+ zz?2FyG9rJc=HNvmkR1%#y`>`FK0b8jR#tN|LPBJ~mjEpEemf1Thgl8EuK-cLAU7BK zFDOG;s7IwS{Jabd`bUkYYgaXPKM0HzyvUR|>%;f(-KO@hJ`Q>Yfu1F3NooY`?Cuhp zV>bi#Bk;!c!447pbpLM#{uDTbnS|kQ3|TySevAQ{iDC4jHyU3a1>PAWC0!73zx%H3 z()PF3$|)HR#Or3FfMLAVr5{kIKtY1BoWBe~DTX}@fb0>Y-nn*h7#eV761@AM_IZ%* z(4twE)oiwv=gOgyA|9>F!IfQ4VyI31oSu;E_Ypf^p`pnbu=O{!=45g*uMya@tw~h$ zhAxrY1hxFI(u`$>xpp@KMnq_k+R4b>HVzb!M=Wh#YTqyoaq^-L%GAvdu!GO8;SD-OEziv zJ;y2Qy^r}EN-a@-H)KjSfbPU1Elme3yCPy@)a^kKM=0(YnrB5xiN9IF5SE3dCBIEO z0_1Gt0BjBXEub@r2CO|jmwpmof~dz^k?2eCQDe5P@L2%y23U%e;lpk@oMrvhJQ2`W z_nD1EMu?D*@CgVBZJ%~J{@TPNFKebJzf)!rMF`FB*-U3qMT{uOrz;%Wpn*f`7U!Df z3mP!gLk`^}9HF5_-@tJHdqAvCudM3ILVo`R#f?0%Q9^cD2(vQdsXOOr0D)5R4<5WX zs*!4iwj-^-A1dtq8U81BzG=GEe}(M1+Qekb8kiLU0^wvwIiPB1U3j zKWoT*_PxwIe7ZXM5k{CTi}nt_-?6gea473nyPNp%g2-P*IQ?wAwv!i`6s^)vB=nk%)?CW(`&@`^JXD8hEZaQBs4L>$f zf?3Q=TLrJbS99J^jFFGPx|U^aC|@vMNg`aQ~bKJekgm-8Mpbte~qS<6EsQApXgL$$Ngh9RsB3 z#v!uvE`6t<2j3fQ@A&vu%9h!FNb8M-(j!CB?an=7)G;+2xttYsqr>>v_rtHij#uXV zuK$iq{2QhF^Txr!^^h2IiauY}J*{GcH`!7WiyOiW_n62`&Zr+2F{Hz6U~BMJ>|UHGp3g0L<8%_}DEz?0Qrd>G(Ys_N;zc}FEEL=Fq5B@v|a*nA0v z9|Fs6&MQ77Wg5-y?vX(CbwPf95g?V?@=)8lP2{o4uZrK@J1jlg+hs$MV%ru`!w7wG z;3eIgm?0&wB4g4&+}In22q74Pe8obh@e`#XdDgDZ)K+E+SvQE>ZdKFcak_yb6(zA^>RTI z%8@v@6zG8PZoAda*GW+gkVXL}npiDh0#-34{oLNHZ0iCg(q6CNfHlZF%H_ZTM4S-4 zVnqP{)tK=BX8{#`GKV9W=aTDryfng^6K5W4ch1Ol{4*?AJ^S@Wi84bV&j#ULl~4aV zGGr=Mtzwv*oOEvd=+K;GqB}NyZT9Ag9k(qT4I=p$ZFNnSUf1S0*j%1g`K=B+_;EWE zw4x8*6gyQNSKo{5e3UBgCf2%Qy}L*#VxxG;&@A!z4$i0gZ`=z%$bX#It9c4pg&^Dd zmMsV|38OzhD~!1VJE4e%C=-}7m`^`0nlM+($|zWBU#27;bvvvX!)nOTUBh8_X-5Zo zdYHp!Wk`wnEQtuswIIY(1P*U=lbyOI{z@*J5LamtsZW|2yW;AuF)HR8`7 zA|h%(KN9pPL}Xl6G%#rT()e-fNI<}?V!Kok;htp`XrmOaPe5E_ZAJ4UglN)aD!$J<&+=|EV2H%+1JCkWvvtsqdKwN z>Hv0);J;L#GH-%9*QY1BoSjPUfg(Fo>?s_q=q^WDVPS~3ny_3VRPjiuG2uVZue58Q zw+cMElO1?$T4r8XF%e@0>~=~@N_0R1iHN;B)vo^%m$4} zgs=YWQjeliPA4((DDdFtjTDJD!RqmR@SM)*N9g7CgGn}G9Ti16xsZ{GC19tLRF*;} z?kjJ!dxiXp%++RR`E(-Z7$k{q|0W=mVRFR=S}a7aBx9s+-g6Kz6+ENShV11xG|~#O zka@U%l(=xTMnzCZsAB3*Q9T0c)tF|G$5|d zm#e+~@!j!HXspn6{X@CG@U1EQqW5GRaJ+a=`3Yfa(5RBLu(;dFMrw5IPi1<>^m$2t zN(svI=5OSc4z)a#BHzG3CBWZxgh%nZc=Km&5sQOe0N$x-S=~}Wf>M$H<~_)#JLLO3 z_QCzhcja0;*`cL%CFzmqp1x1Rn@TB(7ZjAtTUq(HFW1t`yc|bCVfOMs>X+g!IJG?K zMk`12JOh#xZ@|9U#d#%s1xDIXu-jRP8i3dqjnA|B<{%Eh-CKw581T#9HRt(mCnR$ts z@H#>8bp;8|uY)%0O&70CpGJ?3mx-3U7)LRO`=brzyTa z!ueqQOXpiBuZE95gMo2gdHW@x|Gr{kWP~}sLGUY9VtAGSVhbzR`;rJ9j(7Eq8!5JK zv&~e%d^1e1I83cj-p-C09F7gdvv?zjp1tks7Izj#y%IoJQ=(hX)?xk=TpRvDSox9F z?xeyhsbv|F*_rh(V4{V%Ec+VVxeB@OpRZ5%3hbM6t{<=mw6@Z5h#UX8d@+vX12wptPc*Ydk{1bV5+sz>(}oFvwkBy4Dn`K|iam zq5@+IYWE~I4+?;0eD^fXuNw1EW2lMm&_kL)^;j@b;z5&`vXd+*rGVwEN*Wm>D$usD zb7Y>rJ&-6oCA`(OBEfuRc3t`PYh;hqg1%JbRm2}O)C%{qULwI0l%H#a%r;E|q%4 zm+2qZ{Xh3YKUvUi<+m*4ZwM!ekTzr};%yi89Z26#$cKzBj&|fQ=ZgAkVat=_D2W03 zLBB=9w@fo|Q6saM^p%D70#w9U$XDp+RY8vJIYHCG80-Ncim7m=&*Rra z#=$AEM*5=40=dTw{7-RgZEefGs(`iaVIaxgbF^RXXuSQ9CQ^%p!4l&`w;Krz6RfhX za<CWs1UIiIU+mV2y=}`Y2apc`PF!&7XD>Omk|`&8 zN4}-t$?w&b%eGUKgT!O2ePm}K=r;jiF2JrpnIrlO3u5|@vv-y(!_R}0lU-AD^NYX# z7JoDWy3V^%=UV)ck&!x({t;LR)Sj%s2Ab25>wQM8**1?nmJ1BUf-Vq=Gyc2vx5ySQ zt^1Vj;`Q;QF6V0ksoA095-#+ggTILU#tExsYI!xlOFs_OKL5$v%RU?s198}^#+)S&JxFY_+M`ER4lE|Z0pNV0xY`cvZ-!dRcT~(RBBe&yu1cmG+~gEt|DltpV`Te1JD2%9^QML zj-ffs5N2{ArB*u9NFx7SNK@2VDE&%4FOdWb(GO)lNe|chL<;6sl~L(-#qfGR&C9wz zQP|%FN@CAK10|o`=}?zD!g~kKkFU2J3%TJhB?^LXu8q1I%eU~U1i~6kM^#5()}VE^ z&AB_=um3~{M?*7B3O4_y7f*KERG6cC3t9?9ho ze;Nt@Ai3Wx@W*I>DduO1BCupnKAs3!S%MY=90`6lm;ei^r@9;&UZ}Q_E=A>~ant9+Mu>29E?L;BcJ|wNZ2FkNpuEhTHej?=+qeVTntGrc zqmqFQ@lT-v&0pU{eQ}>HWh#^IVw}i0NjVSA;%8#A*co86U~g~F(Ywvlf7j_r`Nw|` zj@O29Ay4(fP@{>W`(-7t+_?*+x;sK)AM>!Gv!SdOKp={;>(!e;pBHKTCmVtYZf>~% z%O^RNEjOXP^-`37>uRO$a&l4aC&a|*zyuy@eVtyJvqpqHficu=N{(z8EUmBsc?&5v zHdP-n%sdSBE&tV0US7*y-pf197A>+a-a1LjojX>+(GyL(P68sHnFdTrCU@Y#*NaIr z>9r9Z@qM`8<@;OsnfxYWV|a@g%3L8#o$Txu^1!05^Q#o_io=EaD%rYo@*&)lR~l^036fuM1x(8nlw>Vj6%~Nz8h2t; zrmOpR_qBy7_5BsVWC892pBi z94S4)i^XliXMzr0Ou4V2TUHx@U?C(5B}?fpf|lEP^HEwfB03sJ34oKEs>pwjPLfqq zoz-4H(a5(@*a8MBMhV?LJ$6dhpo(;S7!0IAKY#v2=E+*Wq6_q2P<9Xw$`mEFEPBdu zW=jnJglVfS@m2=u*p7(=y49~7PE2Uw%kjrsJjDFNbStXCSLa9I$7Q$b^Tv;Q9->-E zb@YAbHa%A>NGoL7e0IbahysS4lTBZWR7LRB#=3gLlo{MXk(I<4)deEit%S8#W+&kMvX^@dw(dLMT=Y&Yle!f!A-QWiVHY?5u(r`Dg*!%kM#`OZ( zX$qKbWdXqr+I7JR`NL5ru`4(H8nd0KejxchFm-Km238+;_D0QejkV`TefULQ7I#hW z_NI6>9z@v*8q#PTa}PX%o$z5#pI?(^7)d5DqFoK%zqT~m{zq5Px+rHlSI5htEUsUTASmYJtZJDl%ico|Z z!QZ_GdbbzuJq<^SF|skS?S|UMX+E-Za44J^15Sj{7C8)@an3IkUk+>cU zYUsO1`-Ri&)U$H5^vJ=ed=6vC2I_~c0go(a$e?@qnRL07%5WYQh=$% z-_;dzJ8pjwk8J2hCQGV#!3%j%ekUvKSFSC=(D>EHGnVEXSdH!?1AN}6o-#mf2ZCyJ zadRJRqLpmUJ$Oqt#Sz0gopvm9&u>MXx8FSUJZA*Nz+3D@Vj+3{T7wzyFPzB-Q~AX; zFa4cX^qD#oCFsa|O4A(BRX6qOvHNISLB3hC5tfNLZDK}dOlmJ>?=&9E>c-qE+v>A; z_@83ug~i|KW`<~yNbB!ElWz4p8wG^YiGyL*{cpYIXF6%{y}buFYCL^6@Zx0chL4O4 z4QowkQQq>_-1|<}1z5m*h7I_x0&19j%syC^n53j=!5+WO2A_;RjRWryO!;bIoIUQt z#Vg^#h--GVdW1C}@-DPFSfl@`a0ek0{`-amj!Gp;m0F#6>HcI?2+h$iB#r22FTQm? z8kq1nj`g`M;*V6?CrxA)ud1tr?Y12gzf0E(v%xL-2zUj@WX-QJ=O?K0C2l&76L6rs z#Dm(YFF5U#pRCSg@CY&C6l6@j+f){Q9N4EPB-P8?cVJ+ZM4b{}5ef4muwNxxAF1Rl zT71Lr%@DdP>gAK)_@#^S4xEr10)jC$Pza^XVAo}>Aa|8#{o0&06)8O2hu`IfQHvE8G{qvUz`*IV(|Sp2a!qMwQVQuhQi^ZBSTjm+`5U7xqt+8|^5p=fw18elz{TCD=G zzv$f!vMi_-D=*OO=K8G1`NJhUo@=-NWX%%;aLcIxu@UeA%>o|*8Zj^yQwm55ek-a~ zyFA{;xD^TKOU1id+EvbOr{#bqabi~qAz%=d?C9XYnL5};^^~Cnz-^)2*i(}a#r>&r z^G-aXPpR@cmS1Y8Ooyy&nb*Izny0A40a(Vv6(&UA4Uy;=4?I&5nHwk|VO5GLANZ-7 z*CPQ7*p?~JY!&G))72PPVu(Ey0j-7{H<{O+3DU6*^p_L~Ehm~y8gveb$NF^8uSZXv zwTtHT$QT;Bt3}y@6?W&SF9WZtE@XMTj;V3SwA^!_z+pq7A32ERbD5FJY=h3VI!0r5 zKdNYnHos@G7gAT^sG9Q;=wGTQy@+kW_hLeFpV3UJtE)2uLa`#?i0xuuydeR_Y%a6k zbv!xzV{>poKBPII$byW3nvW?`FEJr`s1ef)q8vEaR#S7P^A#n-4By@UH}AIoleQLb zF!RKN`=4NHl`U-$VsGt2U-k=mNO~a*TSlvoCxf7QNzQefFkp4f4OI9sQo&g2o4HR z^L$7kt&9e0`$*%!fh2=igNfNK$CA5t)#)HF;t+sYtH-^T2Q8Y=QYi(dH7rga{FdOw zmw6a=%C4w`m#O9)`0Ri}GlpCWgfGj+oAVlR9> zWCADZt15;)LDz=?MMN+D3rVTX_429fCj7>UNkP&8&AZc`Ew~2Mcd!_VV!jvYiOm1p zm9e|3qhX+B@K*i%`L?96>A<*W_FW1SB}EK1{hS+|1vI2oNoeh--F3J;DtUJ@LjtwO zj|^&Q!$EOF@nF-V^-C=cxK&}^Rt?LrHN<@-=-G*&9JKe%DX`Q^zl0b51h6z2Q) z6L@)egjoch0ACQNT}Nz$S5ywc8boIhI>++FUx38KG|70NP0z6 za1gXDx!PCBn9|b;@bj4=fvj51?V-^m$mI-x-#p=n-lR5AON~3u@V_Oc5?n2 zs!4m(KD7GSJ$7QKVdp_R6;hQqrOllP9`Nf?#!zLTE?AY>mzI}rZNJfFe;+!D{u9)N z%r|?fyS1~}T%O)F{_FESQT9LF^GvNvic|HWsY8B;?gpH%2QcOExDV9S)J$V7Z3M7y zgq+a4{DQ~t(=|j`c*Nv19iZ$N0vgb?vmsKsplTE2nULwtgyV%Tw5NWlp$LoZF~Nmg zvc=4`XGXP>+?dD%qJ9l2{ul=gKW1<%nL5sK@bGHZ>(a4)Ezl~fP+o|@d?D}iuuC#@ z6#D4c$(JVy+~EK9HhxJ*p->fIFYc$!;M1& literal 68242 zcmX`S1z6l%v^AW;-Ai#TQmnYUmlk(-cPMT{DNx*@xE6VFD^P5J;$GZcic4|()BAt- zGMSKM=HVeZ`>eh9TI)opD9K@>k)QzpfcaitS`7f;z(WXtf&~8RjUTiAcjm4pCka%I zk^KQrkjy^FNdqtcUU}^$N#GS!7kOQG06@q8_l5u&Sw!GPDTXux(4Sv;Xlf` z7|BD^Uvd=cf8(V!7~p+UQCFKZ7($eRNF-QlS+%`4HU2A^-c<|9{2^ zP6+71PZbMuWZZA6QY@4*vP5tlWRJP#;k;zx-~ixw$#xvZA6QNZLrr zpQ&Xs)?_Y@_+?*^7Ihi5HXpx0ypZG}zS?*>@vxxe$#=p{7zmQF%;tAB8>upEweZ}l zZS_1Jvc+XhtpA(+rD5K4@D(8;98je8XRQq1RZl2e(Br?Uai@j4-d8d)OFupAM+e8U zg>YZL);@d=QG>gUc*o-bEXa-G=Ug~~M|1Irvlu>F|SC}=8{UUhjq#`bi3)6?lyVDJXT{|XMH)l)M68v-H}l9-~yA`o+Jme;KU?Y);y3*@7w zrl#lOQrFtkbFi|qQbM=aA60XHp+8+ZvcYGe5rqpfBS04@R8!VGoT-?#xzGJZzNZ4I z!TWJsU-l|^snPy*s*@pB?)7tNM_KnnM3g1#@}|>!Dz&m?W)>D{Q&Z~e)3vyTdg~?) zI@l~!URE}YNOJ8-2krM{?x+%=-TP48&1 zQ&cAfaw6diXP_EL@hy~cJ^XU6GaTXAq>m#x$Q5Z1?LYRr9!#ZxcJQ8+@O~nWKi)_8 z2q#4AN9RSnEBJc_ff}j0KSe(~W#!{pD-g0`ZXtPU+K347FJ3OF({rzMZY~Z|Wi2p0gs}x< zcobmswdSfiIw)lti<=ip^!0y9Yin!C047>mT44c!7H%G%tA=_>qA-YJrrp=IoX5+H z3mkItW3>W2eEj15k5|y$Qf9U^sZXD{(*-@4_^d|0`JIsSyTEq;)cA;GrLJZ5 zKsHp5RsT~l?LR8P{TPIecJ8JGyR%zUGVZv%oHyUXJH}8PSzD z^|~YE)$3JzJ0D);KfEOv-1QX?=N+S;i;CX71F+%GYFjH1Tmq+x72T|N{Og|aBdfU4 zYzieRpzm35&hG3&zTu%=v5b#r=F`#RcOIplAHL%y$?>x-UP!;uVoG_beag+vHU4va ztZ3V)H~X9}5rP!3Jo2j}ugqu2%i_uS=O@(cfXAbD$cZ<^ZlF_5JM>i?TUpEbW0iKW ziiw&XjVIgkfdZXkZl2zq(uMTBX_iPvj%Cm!}roILXR8|lQHm0qKur>@_R9THw( zpVebPP`t-%Yeu>IW_LDumi>bS{-%?X-r&f;VJE_1WMmX?*+BbA)z)QQ>2%h2AX?jq ze^@Wz)bP%1u1bJ!iP-i_b9Pn8RlBplzpxxiE#?mQPJp9h`qt&0BGV=K_=A8XEDGUU z=TyrWPmhT4t@E~|#6+XT2HPp4@aPsBNauxCs16m5kGlV6|GBggOI*J-Dq`x{C|R8K zcI~gcopg^?Nyy#iyiw0`aym;Sd5LPiN~wn+IXs|OnHq4j;$@HW5`r!2U08M%@OOW* z-tooS+PZ{KjDz63 zZ~c6uX60UXSGUKVPBR;&yOv?M`|vYt`$cH!Z){c3ueZJH)igne-^Avi3;=yb-?~Id zhScEt52uyLO8q8D`lJ~$HYVY$kMvRw4i1=iOKTsMl(Yn=I5?sg%U6+ z;`_=tfB*UP(XhPpdx%|hbL*!+pT|T4CsJ1Www{oiKThz{nf;mF0aT=(dEa$|ImpdH zK|JD~5Q&9sGchrL27HW}uB}5~f1|-Wt#UNW`2XnJ{Q5{qK%xp~k{1JptRn9CpatiA z-++{)DpAHc6AT>MwtfnsckcIXAJf-}><4jQW`aV`P6007P5nT&nVheh>V^g)LGF}<=7hF!x zDV>Jz!^N~PNB>tJVP{dPhZX+IRvXy?2CS)U5YWnI>=y2qA3-Q;mz?@kuUXU)@W7kN z5@`PGX-)UtD&10IrgynDUqu~G!w0?c(fg)^!0fd$0qm2N#qYng4@W2ViAozWG-fc8 zN&2p|bd|R|+f$rhUak)3@->)V>L_SMM99_32!7;s3YtF|`1%TB_y(vG08Tw&n2c{( zL!tdrI)}53122r5o*`LU$B?P4flwcYOl0!yU(5TBci4G?i!pm-k52XFL* z`zdGgR#GuAFg)Dt<>p>LoOZ4y)k}0q99@43cz5AXwuV(aeturXdP#H+e$%z#WxQCfc%zgUw=g%LumczM# zA6WEBsK?zsrkt6iG(p;ecxrKnomK~C<~h-R1i+$()N_ea&S$0SaM{9Oh3}u$$|@`u zTF{o*#qs-|R5f)&|NBotLu*h~R}(y9($Lgn`R%mQD&_RFrg=yS+~1rA%^loahsDLc z^AGUPpR_T{lz(=@Mkc7pLhPEd$B8yw->V9?eXtjYQhIih#1*XYu~U2C!(O7&UU3je z;IRd3m4|kjK$S|QoSfK1AJ2MxDQ_<7d{nAhq*hP#X0Go(WC=S*CT`eeR?;zWaV5QZ z^Jacv&2bzdcboyEXIc|&-HruTte9Cv|K`o#l{TNtfkL^s`&bH*`=Xe~N~AZ^G`QLt z8gJ&CoQ>yTFqk?R>CC0dvs~&qrb2QalNiLDZ=N@M#VA$nc`60^enCG+aHz=^PL^sH zejFvi%=o>@xw|Lgr>=(>o;=ksmValIdsVH%cnhrW?ai5mBbJ6$yi~sU&K2;atyFo8 z&*(t^<*+J0A0FTXZ0%pc&ilKm5*6oWR2_hFm31y`!ap-jYxE^1CX(2%$=-X0qQ}U> zhjf|DMLc@gW{E7}J(!vifgpq1nJW;|5pdsa!Y*FT2g{q=T5|3PJ{GVh@zv8K@%?lP zNgDi8u3i0^W0H~et>dh4W48VrOHHNW`aHY|=VuQ6C)2n8xnNi?zdVS38Msabz~pQ zx{jZkqP+aq+Sb?Vdqx#e$Di%Lz%tEcgNIXt0!}m2)8GGaT$0VW?PyE}yav|7ZdUzH zAJvsbcpQ5pUm1>P3-NuVNjS^#zj#lB7XhndA?9;hzPr2JyZJLyK6jF4+GYAhaOY>UElA$Hh99nOIXw}xP8u2y z&okSJNh>8;gO--vBv`@rJY4dQCeNPvSHLBK=jg4f)zqrPwsZZnVY+3FxlHG-sg9(} zpWk%zO!kI1b>dV|aVl{c8N|LA(i^Iw2>I`7Y#?@rAYp#)viY)_7v4p(T*Rjn2AQog zjB0V;6Fm6XJUy-PZPY4DGyn;%qt|h%#oc5$mE)0G^B!LqEyjn|K{&U=Wy4h&fTmG`k-$YT@(6LVpB3%&Dce3Rfl$&ylt<@>)z zLl_JJ;NRfX)z?3D+#i%<1MAae>LI?@M=dYT`M^Bkv(Mk9(O4Eg?P7$)Z1g5KctR`* zm(y9EBI7Nkc9k#?2wDz)*i{LXApmpjeqIL6F8PGDj44BK0J-7x?r90bdd}M8b*8f^ zJCR9IOr9-CSy@>OYhus$;^Nt?nhIjG2<*SU@N9-{C>`PezGBbt61x5m2S{AMl$jX~ zMZjOxs{j7m0IH{_r=P&K<&&(eY$>brK?VGJqP_b@cPPK-5z&9;<*Jo4l7(9OgT|OK zdLed-JPn@Y9b7)I$;n4|c6MfTUal13KY8L(9U469S(?%YEX@}(mlG^%-NFNu?=qyddl5PhX@7gaVL*FxZz%`NE@NmHkRQH>E4|zew0cY2#K7m6fIDq|XUITgU zXUOV9yUKMER^*OXb;d{fXd(_c0EdFHtD5+@_M#{A_9%KaLB>Ih6$|sp`NkoZG(gLJ zw9+}2Lj0G0+_^dhUZj6>)25pLgGUY9duTU2S(gn0~9FG2M(J1P6_I z1l#5Fyy0>!iti;Q?&D+Lg!Xe)^|9$(I?XPog;Qw;1`^|D0_4K`HuVuF;3#S*B_$1W zadLWtqsWe!UM3iU2fO4yXE6_?L&ncJA9O zhY2_T>xU6@@7{Z9>VA9NK!Q1Kp(dzeg&jmM*ybklt8%)shQM%Km z(+(DCF6mHSYm=N;=+BXlkL7&uH24fk(F-YyG&gWmKyx^SFN)vI36IYET*P&cTw!d* zFjje&lVyRdnTsGQTYd1>Edre0x7vQG(h=GgO>obELDEdqOch|d+m(HZ7FXu zSs>FK_~cvvy*GU)z_2&H=@mcx2b28)1k^x*Nkmg4(Oa%lte=AKpOvONQ-6}NwJ5KF zl)wquB5!?LLnqTl(47<1Lj=Rg8}FnQkKJjR|9q_i?x*Df-<-3xg~hy9scB+TQl?
za#;S4BZT|k%M{)O!2hy^utMN}*+S$Ol<5pam+K?lCR+7Fbo##om;du}S2HS{lGcX` zE8qEU&vY|axBbR~!a*l~&iF(rlOHC1$}&C%sHmt~&!0TuSBqk5M(D^980fS> zo?4ksib8Lh1`|F|FVt-mSm8BTQQOV{2Ltz=K6kaNhk(gOQTRZ2Ng?99xIa6y88p`) zCPBJxcG17&?Y6V_X{LMSQ}K`kmd|p4io>&-%%2E`oUaS5Ue!mG6MYypEQDUhJ`IXB zUk{cAlPRekqdc~JOr@h=4x+@f5|@Hwe)B#t*A@%l%4os z?z@vYYH-^lrGMvfEO-Q!mwq++p7?L>OCox6;cpS@^`u}ZUEwpm6IIo9w zP+-$!e^AlTGU(EV#k?*L1A%0l4$T^SQ=Qzv>G};-GfQb^Q=1zX(cCX;f+>->w9z1s zSD2g09_Do5%wPWg3*fzczwmnD)AxULw(H(lgW@NE_NMn=|pk-=;Phx zDRmGa|KUSawpdWdu+~`LT-zzNJzx@q@(VnqENuf(n<%oN**d4CwdfcO89aDs)Yq@; zi;edEV5{#A;$MS0Ctpz@fqNE7H)~96b#34rtKn-d?D7@?T+(LZ;~#EYAvf+Jf-LSs zf+rJf6&@dv-`*@{5%=vlw-2!To090E->tO^J?K{WZ&^AmEWe(23KW$EY*qxnIkUd_ zx?1f`W%u;7!{wyorSrO~`9X$jf5&UloW>c8CGeh>1+Ixc>tqgmMLFFJdUtYs!kd0g zD$~+nn+!ipIl7K&<4OS?8TptPAFp!R{^bioRYyKPv#n6226r-+kbvUJ{?TAi*Jnf` z0k=0dht-`wX(OFvw;EX(8Eq0X*D#w%veW>11%=3u3JQx!$;rv~UPs`en=R>%@@!DI zvSI4x&23Ur_bYfm&-EtE(^B5ALRy(u#}T<+`hp__eaS0mxA##olCOQ1SrPL@pw7TA zeX*q`sz7w4n%@7i$dK7*eJPeP>Plb{=f6{{0RCWVpbGfv*8j7%WrCK5#_YH$7wMTKQH2U z&7Trpscew!Y6iL2K(W{D`LbD4b?bAX_?{*qwjF19ndEfBkz`6@NCt(jY0cl`XKi+z zO6gDUXz!HV{x;m~NnY{K7hH0K*;Dt3#g_t9<&6K73mAXW zys%3KTKu^=ISFjg?)Zu|rW2;#V8i}FOTG0t1u-=OfeiJ#ci3`q6doT^7aT;LuK;d2 z;V5agv{MW;G~dOT(?#L243G#h0ui><4H9q7WAx znDF5qgW|xEIPd{Ds@3`{GJ7e`w?hu8c`eQfy#iKihJ=6rQrK{Q`s;**PO61&|K2=x z7XFtM5DT$!)Xd58*ck?yY)-%7e}Prk(9kdszIFWQs90H9d6}6%>_!XweaOxzfX%dX zxplKYY;;}~DqKRRqI>UyXl$7y8T_9=#2j!^Usy_GR;lmCeQnX6s_(e?O(%&>*R#>LyB&GD zrP|J2;@BHBjk-KyDEw2UfDP2=)80SJ_SJ1Jbj2YJ62Da$dBAe=uIP&5qIr<7v~Yld zDmmrWn-pXYNF}?ME?>FD$XA->sSq2wn)mZdWhwQ+FPq=Zl_a<3A;kNN9#UM1>?I33 z*{_R)M_rH%P0=TK8h)ptl?vXa2?7BGWRV7SQhUKUh9!vtcEo7Iv#l(yQWQ2B&*Z=q zMh+kVfDFR1goH#bTVNVCz-2u~02vq>8#}3USl}$K!XqIgiU~2;ConzaExj(s zWuRX;Io&%_*FM4`1p6re?#%lbmD*9<+mt07CDv-G?5a3kMNC#6^Y=0zBGt0pdG!~| zEc5SI!pkvh8IZhry>vndN?jn{p@;U(;u9a#9+-vTz&OK3f!h(^_O}o3;t*6ICK_A` zN9e$6Q{WHozX)fvP`S#SH9+jB0;!X?D%|ip;2hBr2MU?&nW5{6P^oP04y1rGMp*D7#d@ zxO6@>Q2s~D(99(i#Af%=;N;YC@5`5a4+m1*Uhntwv9y%RfB&$v`}iNSDfb~Z#+)!$ zJCQpVC>9?g>Xn48Rv_$XWDkstBnx~aRyh@6Ff)3_t%pxcf=|fu*KTRV^>UB*6hVt# zN)_vOWlulBTEM0hU7j^sPI1ITL7-2yjMEo^D5}EQg^BLCwSc(ExDa|uNKa3HPcG{3 zE#v9w36A)4hGCmGN6_W&=>G5T=l~TbCmu)wd`M&Cp%nbYDEjv8pBY)Yy6Db@5$OzK zcjcso>0G%4M(SL=2t;9?wGZA)OKD!=47<^06z{%{PdGYd-K}_mETvO_yMP)%QLh(% z&2QCyf>sRiCQq$Ryn#GIh93vTD)!V4pKO(eF5%eG#S^cVZMe~3vOogi(puncLX^|?OE66+bM715Nai@qY} zAUsCU(Y_U4P$O2B?a(6e<5p*i3h=fJ*-@9|Di?k6cb~Yv{LaUh`&P?|KhV&xa0I4G zh8Qvy9f?Nb(~EXl)vY#~qi;DxE<=|Vmy#0KV#^&c9sjWtcIJ6+C$mH`8K=S>L8j|_ zCl_E6-&7=Z6Zncu-8JXzQBo&$XQidkt1n7>j>j;Uv`s6y6@P2IsOr13&yy6St#y1ld0HR>AVM+6~?ku9ukXy8UyL`RvPc0(T6AqHnC ze%2KMDMr{c`fE1-ixh364d0s+MZjb*k#1nT=}1<&Zi_N&B?F3{m zgI0&j1MSRo$Ku`3)_-(&AC6}#?y~2Io2}#4M&hArCeN2=5qfKW##^!KwF;5doKg7k zaOAhE-q}iivnvlFf?rq3whynE%SOb8wE}n$4W6@)DOb;}E=~s4Bv5!j19Mqh_f*-P zR+%E0E^J-uaF158)ZkpJdJxCnH%w=I%P<)qg$fqYGn1d34`kyooc*sCKxxwn!6jj4 zYD+6i&M>O8N)D!3BZg3L+3ajLCKUHjyeclLy*)#XKlaK8?5B1>)!OC$uWf_PT43hGO`A=Ql}U8F{rJ`22Ny7KC6;V1~f=hu}{rC52&RQ8vj%` zdepDgGeT1#NU*ng(T#W_pCMHX*En!5pF=}v5Pi{>*?KuPalV?nLTNtKL_r&Jsv`sb z6+&LOXQtr&L$~<-AJ6+iZtkn1s(UL20a|DR4(BGwErgw&oi)?@dcXn04#43a2H>Eg z63-QuVRv(~^8MlF^u-RG>f8I1g%+UXmK6g|N6#COi;UuV#M=r_AnJ=!y=Nizk-WJ#z zHn#cV4pw0y?y1i#d9EIU|>)oG6^OF4|Dj< z%}ulVx;m18V9;8jV>h(o>USM3uA)VkccRm=bWzO6@3oyR;zx*!i`(pf=cbrV%ZV7+QlOzWb0>U&6u*n`a;djeKf4JA;of|2B-%3jMCR=m8}YAYc@3ZR!9=aK=tvEn zek{C1?=?+&_1$vQ(~_>_7Y>346ANd!cFM{Z6-Ja};$0ENGL8WB^3Bi0F&BxeJpb(+XD$Mu8V6T zH8C?{AcOJKN@bq_M2xB9X!Sw^wzaKoFJfQ^^o%5mTurM_GHX@roAYKyNYh9d7?1_t z?YstY!*#3A^>S~V;pzU03lzu%IH{>OlsW^S4zyvrZ@4((q8Fyiy(nMQ8I-FYv&T0x{+wi)JB2yut_fL(d_`i%fN=uV zy38S7lU}g1Dy8F(HVL+*5hzN?MiT`Or@dRFb1mccJe;kp1F6Jcbu7$L z(b3yFsi8*I{o`UU(fj-R^I*X>!(46e#MXh0Rhgo_vKJfdxudu~sp7)I&Tzq8m2nkp zaEj~`h;tu1Pwr$t`(p5;|UeQKjXg^53X|%~y8lxLM+=&2!+wAvW^kVbYcY zvUJjxbcv!tgheNEVP#I*k+gQF?PZuiR_qpBtSc(C92+xPnMj@P$6XTTzy3NK0=7cCr%oJPd=?*!eOHyHnD*B;(9_kDnC zqYTyl{`z<=*eW{C7^Gck^mWeQfUgp+Anhvhii9MwXA6Dpd3-bZKshzw$WwN<1ZXpz z3G0JzMu3&%oE|so9i7*V&??)3!YFa-zMC}xlVps(SqGXV?HGu=sMv0I?hPy9+@ibbFl0DE>+9D`c=A zI%+_D3sjTvY&%8}M zsIam?J0GbfcZZnLQX6|w%TT`quQmh*g}`StP{o5%S!qL{U@I(k!tPr(1PXEt+>dwZ z8(P`O>B?;XgoUS=!KDT_V-0=$nG{=CDYI!dV4@M`+s7S6RRcjOBS56PU-rJBhM zzA+Zc5C5S5K=w(0WMW;Mt2vydIKOH^S zZJNcXr^}+;0fez*}oG}}Vc}~L8q8JD9KaTAm z%9C_g9_s}6Sn1I9mldEvuZ4dYxOc84AWnc?;u;0J39Qh1EX%e|yu~1p9i%aeLDb#< z3`n+w0bML7|q6*ByDHh_Ln8**SS?Vv&pI+6%ibg`%P{o+f7N z4{0}EP=gXb$QdUD#k4Dh1mo{+U0tO6Z0zvcwwpWWEg$%a#M1xU-9!o%X9WO!g-x`1~!A2 z@|_jF-jcTpL_9JONtB!{{_<5(3($o)dR1i!$h*gPX5-aNhW5i(9?L&?9aG+3Y5dxa z{&qg_U_E@9_njGV6JSUiw&u|sQ+Gbu1J)N3L&ab@6U|B3tEEAS?C)sDC#;t2PW*T^}>tmCCg0s>2&6_IF?j+h*6CR}S!bHe^NqX5Cd#Rl}a znf=DPp1S4v3aLG}<&-(Uvv1!51CWMKl2g0&H)AsC5NmxHu79#tx2$=ca5GsAtYdLT z@L~H?Akxr#yB)}ER<&)vq>)}utcP1XiwZ-r-(XY)#ZHCz8ppK}GFMNQS+PC^2w`|< zT$-bw*xv^RH4PlcHoPDw+!#DGYnClttd_QU^=K*wJb&0eR~;wN)!y#y>ystMK$3BC zs=AQqs2)ZWm(n2*83P1ibxPu0k7Ua(*T{Vsr#MnDnm1G^E#cz>tLZ}UJ+j#Fg)@V` zpGZ+tLmgJ5u=_#RB=TIV#O$rz0`Q>7RQ51*6sG*YbZ}12R2=W|DDfP|+CU|Lp zV7wr2d@jaFxc-cM{PX;uh22FjRst-g)1d+U#t~?N5XoEbOX_5m^-DluKyGY&GAm+> z+Nm401ikG>z1+OJr)RRtTqu3j1c5FQpf^!kEF)@HimHBom2?Tb8cgMly9*+&N)4SF zXK1S*AcaX)(iy$HWo134$BBaZ`UIeu1nh>tonfVeFYt|yY;iqz3Gl;wq&=_!dHy@A zsp4Upe3kCHiq59ExbZIxxqsorL1%|MEB7b?@P>h*ew1o#d~GdA0(1v4L`fHT(t$tU zzkg@2&3FdHgGn#o;NaoY#4ZMC85vnp17<2hMl&!4YUy3y{-X$Zqma--~KwQ4V zuF2fRr+&M&`AYa^`7z^x0P!)k6}OV6+tQ(tg!_ZbzKYY)VvHO~Jkembs4MQTVQgzQ z!mZ`rz4Muy&go@KU6Z4Ud~pwAz?i_G89|~Pz##qop?I37pdJT}is1f=7&^Nu+2BYQ zX6%9kC)0sKa7nd(Zo-+FZ=sX*->0_a-QU_v?sz$Hfks9swy!Y6#NN3i6JzLOa*cq3 zzhwFBv5HFz`dsZ2UyP^1)7G5JbI0l#Hj1=-xd~`KL6I>-!AR}BD=13fY>|wRGg>Cn zH*iCbtfSG$9(F0h;9q$kog*N~>u2s6i(hwAj;ErdGXQ~VFwwEf759y1JGLkQ0ejjT6~WBVK9t)|oBS z{&>_V=4PNBiNDPzlJo7`*Gkld7*YI8LqFz33P`FpD__k7SE}2Lo){Mra$Zz*o~lo| zR^^b-%~g{mgHq16Is1O?{Z?FQqx~Go?pQV{*1DE^Q#5+7+EuSf?aRByM%ovn&veH3X*?}{iDnWkz_;^LOd`48nb@LbM-gs^<`g-RW8Yl?Z zwAxJ4fV_b#Neq47m?K4&zGkB?C_yd!G=keBfX;B(U=L$?3jHkHRdoj;b6h-hC^MFq#faHX=c^_9=ba*O(LAZ_2u%;tgR2gzmu z_uXIMu+7q?gCg@F=)$-+@$L*{kB|m+9CK^sbiB0Z9_$6SXHhLyT{ZWP^{1PJAD?Us z_r|_fN}XhR)Dt=V-NzDv7%0CVoNkqWZfW|Be`#5|O*#mHeYVN#vjxfq{) zHdc_6PFc*amzkY@)1~)ZudKZ8m8zgyjt9M&nw{1vc-@8sc;8&LI5{#L6W%Sw6K{9- z6dK|kk23H#{guJ#)M7UlL*BX)OL#X&<7?cazIG~R0-MyGN~B3L@};J_Y(3R2(@zjfLh%SQG*S+*6TG=EqN{*33o4uj~bs^SWI9(~27 zl?Am*N`>!uO-?J_pr?}EYJ|vXA2L|czdiBNG^0N?6LJQ!*MhT#`!5BGRkD3pSFqy)WH^AqldN^Bg$HD)S9KVvK0> z*H5y^MlW2RYpI$7n2u=!ZoqJzi7ug4J+UkV8J{D#*ml1S17Jq#O*bWUD=o&H_)jyY znDtjbim37D^>vd^2h*sgmB{eIXjYfDDp`0)tnggrG7GE%lAoDz$=ER{tL_DMADmB9 z=s4Kdqf?*~2pOCb%-e-}G=MP`f{rr|g+!wkvWzY+ni6G5TQd>M@aIi$C(VrN*)`29 zWA7cr{wIs$nSKngwToKyzZ_iv+gt+bH(;@~<)_2zb>Y@TGp-dzRBiGPJSC06zh-uZ_p-sOV~jwNCetHvRt5DfekycSREd}8C*sJ0Tf$Qo^k8vlULIA0(+UabDuV^XBU`XFw0r^Sqo4*b z+Ic{$h@moyDa0RXodb|Vq5fdHV7$W$e8^5{vO8I(3}bi`ztZXzGQKB8pR}>u;=Vs! zh7Yb73Nvc=H3jkd5%jV-r_h@I3w!`JJbdUWE)M)Ml#ixY#W6alXjgS71oX&L}_eY}KALK5k9}KsbkT< zpl}CZAgSI1`RJlHA_WN!UhyUf-P_vA*Cqn<3+E%l(0LT2k3%v|yUH=Jl!Dj{|VIyhzBJB)mw=53TV0^n9qS@_YeA z5B(<|2Z(wHN|+Grd|lPXa_$JF^v2q?SZVgGJh+U0@qD`PG~SweC&qm5Fe7)`dAHbx zIxMDx6;aJ6i$NR)GIIe>4!`T2I_qN|9rr*xVxJVY$TTkOll96o=>LUB!Y~=N;xhiO z)@8%pZNt5Ju`?V$Xz|Yn2CAH(rT9xam$hKhY*|D^MDE8N;RR=q3Jm;$Lk;Z#Gyo*v zc2MbD7$q-_)<v5sXb-Xx@^MPAtO#)Fu2M_#>QAR(`9NeWS}Zvu zW?coXXdrRmC2>edP_ntrxVSLQ6LCkU|3r|3*q^_na%|74xo5oD_$d7;F8H~bafsCc zNa9$-b%V0fp5#F7SM2s#lnFw_uDQ9_I~Pbd!(m2Vp};!Z^EDl#og*u4@XQNp$Rt8U z91)Hl0YZ#kOukh3=791Vk3(z?w@xZ{n5hXjiR$QHu(CSLk%#CVk`*<&5-cRPAGvTw z!q$O*c5qG(J&cpS=H*cl|>BsEH`b^zlKp_yT{++O}Keyr( zSc&vZDT~Dnn)fXq?~ms;d4HCaCA&p^1aaQ(SE{VO^lG)u-m}GN5LpxEcbBW(7)GGLq z_Y1C}il`jMB(1vX*b;XABA&B~=$@&x)pqv?uaV|Y&y&U3;o+sjsdux)W^yrjSQLWW zt?+(9K93iT{?HvN!U%SUb@ro$c4YJZ*d4H=J^iGuGIt>6vJO-kcPhc-fZSqY4(P#X zh>ni7CLeqYE*R{OC5J$nSXh36{#YDh;)v2xMn(cOuwn*>918^#Q^vyL4X729Rx=W$ zB!ByM`_Bs$0Gj)E`q@W5;6+#z7*!i14$tn@Fah=^3)yk9v{Orna1v^}Z9b%wSg6#m z&|jM|4x5dhtQeFj-O!vk4R?TYbJQVm*v7-{EtRnFa=!(q1QiayZ$S0$-@mK)oL9eS zmD8bx76|2z$C(oq_nz=;t>K6hL1U8&XpI~xk3`7nMJ9N#tR?9;5?YKUjLQ(l$6wdY zyeFF6;zP(DCqbnu$fw-jp2G^tS~J~qnSf*0#Y)2UPemS5*c1x-)D|`Hj84{feX7}y zvICC;z;O_nh0S2~CI7hu#8WR$mXSz5r|-aO2pGd4GNk#1EFN;>TV0uxQk8q+2nb;P zBFLpu<>=j{9%f~Va|SygVy{5Uu*3J3258OUMkh@^a#LAI;6lIZl>W6!*4)qI;k+Ul zB;c6CAi;I>lAp7fkfKWqp%Fg2BZHlH(Vk=qYDZR07}B<)WxGD`6=ilgVIPA|5mdm5 zO|PM}v$Hb@s_>mj;k|1>_y{;e9W_oXf?$qae9mwi&EQ$U_BiCdpWYcp&Mc=M0sY;x zPK`uMNov%c-Cpq2{toiftr z)#8T!ob7}^h4wHN#t*mN-QE|d0D#f|6ptX1(?ufV(nDzblgZx`_Hg{|671i=cnG4Wf!E@_3P@L)RlYVzkVl} zUkmPa?jwhm2GaBif+i=<8F{(R^ph&tIaNhsgCwN8Iq3Twzs44TRSXjvL$BhZ0 zR?xQ}j(e*s=h=mVw4j}2K*Sxxygz#5nv#G0Ec>|f8LY0T*x1I3SLAl$Mw*_MpMD{)e#f>m(E;4lAv$y^%l^o1WH6ZgJx>xG({+ZK(L+2tGuSx}O`V zmrv5cu%mICQ!iNsdxf>kVd*yb2ze@wHAgB!yjH-Qt__{W^AaR{;U9cmtL|h7X5vKW zMEjeCJVrpU3IaaHS%Qw|o0WDi^k@F`snQRLmbxgmA|G)+7ZAZr{>*=*$B#yWc>6<4 z0RCA{X`Ht)aBhdWs(D;B>*pvRqfwD)(Hr~JuoYR57YE?{p$zN6?~uN(Vx+R0v*O*kXZo)=q?C(jD%m#U~UKmmONQHXe=_pHDkmBo)UrG^s}_i0Cf~0E0gm3_YsI^ z(*-h7eV|>+2BOijQwNsYRr*aQ!(cBYuiyAz3!CE%6YKyH#Rms7tk^c)@hEr7=BzsC z3BB(>rg@q*LEV&B!INK6@#&M(Qqz>(`+ht1QK#!sKxKsy_yg{_%anaezfY6cGTI7Y zAi={uK2Z}!ns9Qh^J9TQ!L8V1!5M5hGS;Xb>$5rdf2Xjltx)&8#+fThK3Z^>l`#qGJ~tLII8}&kYETKRjM$i!p%EWcSe)&9E@U;@;V@@U{OI} z&cOXF?deS;=Rzd3t<5Xfl*k{W##l>xyp;B|3|trxAZ$O&0(ybq{jQH7J?!Ct@Yb(G zb%?N03bvxu!^5co%CKD(B%||Z+`(Kml?Lk8Y24 zGHBj3>qDx-Ogm>m)rv4!j@rnFKr&^|qF{7n80s4g63kgu8e?6I4iut?ZPNM2KjDPt zs@7k0u^$r1bMPts4Fdl9!a1o z=)qWNmK}FB`5L+&(?EASZZjcOGL`@HCkaU-8c7Ti=-S7anVC4e!qk4YgKO`?0Jq99 z1jR;Nv>03k9?X)VL-p3qV#^IC4;%H^HYo* zt!$cCwuhH@oS#UwZq2Wn-|kGj<5B2JDPXReZE*p})z#IMWm4j`S4v_h**4M>!z}@ z^lqvQTJT8l@Cv+fB8T=T$sI1M>s9<1(1@oH={%Po3IMDA|>AQ^h@5$;lrb2l0&_A40g)BSQf| zf(l`}H8Ocb$Ci|e%AZn_gcvGY8t{g6olep^a(knpYC=-ZQ!%V7rPKm%Ik<>FcDG2GgUX zqvskL8jKKYvdz;+32d+LZY~4x8iIGicsX}(!7vyT6&I(d{VZJTiQbF1$X-b1ZM`!- z%GBd}XWES9-s2g}- zB-wZ}@Khqce!*5KpCFbl(Ec95AhUj3D|7?)@*%7kRuzKruW^I1xdAE~{bu!6<)v(P z*+Fje%grfdAEiyVyMfj=#&hjIUvK7R+l-@@Q|REHD-v=@U-X3?wUskcHuQZS45IK3 z7AWUU86vy=bsCmCs5BQx<4`CAn|w7XxOu&T;Yadw|s*LgWC`X=Eh!KhQ?NU@*{n z0Qeg9sRl#nUoi4v;^TWL>|zMMh(kRLnXfBhR)~J)yH%J1|NZ-ScPJrthpN6UY|fRz zWeF>Rt*N5Lj(l(G>R+vx^&H36Pcc`bmoHzI8I}jYlBdyBz3U%eUZL0WaQt|kh3|w4 zcX6RR2;!<=tTby+|53sSL1;#?i>VxwRB9+cF-9JpJ9KX_H;1+Mw!1Q6QrkjIE*-^a zqWF)pFNQ{?T>>K%bj@aN=IyF~e`e`}WCqe-zc9eIZy^q2m#zROVTTeXWfU22ngtOS>^s7rrJVGeG3@lO-YMDfzwmWI85KrSF>gv0 zL>gR2p+nON#)vAfV*U-fa$sOCPsF7hNo#VytdWeW4xXAv3Tw)kSM!^ro+ZJdVgx)f zgQCOWvRPbpK5HiCm0||i5jmi@5rWWxGI;N~lG0;|mt&tqnn1;83a!0bO;9`IGHvmi z=}+R&+GfltJLU1)DX&j%J)JO`s<9*ZSMSh1Fh5h)J;K4#WQi~#v{s6m!prh!Kv~>8F($Rt^7@UT+n7~q1 z3OGb9O)V{g)r}2b2G6<^NRRXfs8aq6J!UjAJ*uxI)m|y)m>R0Y?e3jru(ZAsmPMaehdA+L{j0*-p-Q z^3q&J9yf9w{|OK`GbxuUR;A|Zmxja>#?e8&&1va|D?|J9&A*RGvU`U1#H)eH%kOaE zda6ha^tFf))x6Qd!c!iTg>Oz7J*udm!0=m6gi{rW3@~omTbd@P#lt{P2eSnaYRKD_vDyuKP1_UDmbqm&N(jo?gU5og~5AUt|Pq z`lAM7ddIja_PIu=G}m9fuHpX3x5uL_^gi};A5>fp_ecjGQ5%t?dJ)_2=EVvIgufC`G-$*jY?_W{GXgbH`A1@ao6&XWWx}avl4_X%w6`8Nh7F zW8CUf*9$;gen=uEG4WsK$smVb#UD=77X5E;)|Aw+ziTkMy1KeA{97)qobf{}JVeju zb`FF(;ul(N9?&GVTR~F(GeqT&%gm%-$;o}+07YF8q}Dw5+M5x23&sN{z{F(2Ne?vW zAiK2y4uA!T^{hl|N&5Z=`;t`p@3{Mj$5i4qZ@G=Rc@)11)-PLu;#IY)6i97JY@*ba4;C+p>aQ}aUaP*r;~M+Aesmcl4hgI0{sfco?&h$`CZOJL~+ z^x1cyRL#>ZJp#OXF6d=}?J+meP%T@cFI=9mm4^)Zu#T6A59K7)y z=9PVLG!5dBYE$d#X>V5cp>)^;9x2#M~v7*IQTi_PN3beEB)Q(0Bsz z)seuOkL%YU)Q%573$q$jnXWu?Z4=1ln$O>BVn?Or_oF5zWmv$&()bA@G56>A#|?&7 zdi97P0MZLTe3Wsj22)pp9O@~HA$jw#advs#GhNl;n;B`-1e3u=!yGty=Qr&FslC94A8_<^3sl*058~W2dH6)B_UFZ+OzImKqk8XX??@xpY`b? zM)}Gd!M`(vw1-3P_rmhVc*F_VbsuKi?`&V`*H^^p=;?J@^8awC%lCfGt5j#Gd+Elg z@h~v(q|ymSSyO3BR&#>fVhQZ^GN^So_->c|5k-vG&Qzk+Yb*bk!6iyZaZz>x?c8l zy1P|yMA~4Csb+P6zy*)-4fKlln7?K~M!+QK{ivG&sWlWv4H%VTAj+f#oD0kM@89qF zN)SX~lLR`u9C1(l#>U3zXa9W%`_c+f02_M+**siaCUxMDy@I2(cDkSyeJi^V+nV;| zcv6&ie4)7$^Mn4yxrXU@T|U!jhJnE)c}S4hAaDK|T-L&ZL<}}(gYr)h?JxO>&Cp?OSsgEJyVPFT@O z{cN1JG7PofE!TzL(7d>&fFXV|MzKz19^#rm6!t_G?$Vl)9q*jCPYB8(m#r(R`WO31 z{0<2q8Vou07s`#Ad38#3O}J+LStD{3n+Y~0TG zbM-TWf}_~jKC?f0SVoTHqbUFLaj5jWmG=F=y1j`i)7LxPy-QWS-)R=l@0v;{T>bNo z%mN&ke-`BUn0nk<;yas)7oa0Td;>M=eLq$1>Mj^m&iWs(_8khhR)$@S`$`^!on4$N zj7!oVf>AS2hdoKf*7oyhM>T1!!+gJc;d?!h&onEdRCp{NCTDTH?s-o-Q$cBbR_KF$ zeX>CA1H`gF0JRsZTW%?q67kIj_#3Xu|1s_l8K>I`2@{k06uu|dc`6l;l6CK|;hsW-;FPzsv z8=jYy$0cI*`;1x2a|F+ru!Hj zUmcRZ$bJrYSY!8KrdP~Z&pdU`x@#fJxs>lQu7`W{1hq=PGQOTEmsmW;@S2(GO+v|t zpl46J()+ZYm_f8)>}6(3c5Qg8;JeYHb0^eew>}YNX@>PI~;z_mbGye*CF91Nrpxs@^HYTsbznv?LupfG`xE`qT#v8m0VSyy> ze>((&ARGGMpXnsL;2q#K`1#QO%^%DclJ47y!x|a;!C2njEfS^+D9n`$o3GpMyu4dl zq?08ou@JvymbfJFBx2a&dPA`K>t~-#<7Xb|u_pyV*}wqtQxP6yo|=#;pSqJ;@EEq}89k+nBVVxx;?q5ql$e>3y& zkCs~B+5UX#61#w)VC_U$a4>wblaxIv@-^p*Bs0u??Zk!M8>FbvwSrl2wXBR2k^w5$ z8jzhM?&oB-5unEA-a^0YeP&Xf!$S8{VAA7I;ZoWIaJJ>Z)7;twlCpq?C-=)2Z0McS ze3K3>C8d`}iMA9-h}oW3ItG!CrVmg-hsqx&mv^)-!k(nWl`>${_8%hO^pQm>P(zCx zU_iOb6tnmZAaS9%;#;BY%n;zmMi4@tDX6_&8jQv2nwr6YD<>r* zJDsVqQ+uabvRk6gioKIC39u0GJ%xtNgV-v-np2&3_4cAbv9#i!&k7d>|GQoR2Irlo z)v3}BJydk`Wq|n+M#%G0#oUh!AZVl7y6+?U=?V}~z!0f`z}bt4jcq#x!$Q5Xs_Hu# z2K(P%ZIoeNHzi5ZzC%fKiBY`-3KrcrHFGT z**!N;LPr-H8X8JJTl?|}_-}fBEnF8$x#gIcm{_lkfpyLN9L0P#tY+4%=(iJDR5ur7 z4kSgX!cJ7+@7~EN zvo~FXaWB*XVObiQnwBj&RtX?UbA4k&t5B28-IGgPJi`<)=xQGjv6?fbY)OHRH%eVS zm1PN(a};oyx!kssHU>#alX=Sj%mGJCfQMzzii`e)t8_7C-6pB;)AIxx-2hEZVyZ6} zS>=IAN>4%39h+8(wvYrIuM;%Jm=G~7EtlJ=;A@(zOj030jY*gOR8Tr+gS z-RJgTsL^ImT3Ok}(ywzM1HbJb;GCpXSgi&trrt8C;BXb$I6B!LF9m^`6v;ehvD_w2 zx!^Mn9%U!U{34{J#DoYjsjQ1VQvqO^7aE95-@h>{O(C^!Q-@LrM z@R%5#jn!3kyES@h>e7IJql!m}gO9V#LG9-#Bktf&4u2{tQbgHYBqdlXyU1!63By1% zUHwDG#oD2HmE)bQ)mp|7079+W`Bldy~ zKBw%!qq*DgdDI@rB$gTAQn@SOq&jK8T&M2pniA&Uo~mXB*6H)Awa@L~6eOie_Ino= zwglE8QRj~Ha%Z}RCFRHh6LDZZdr~H)0ukcmzF=lUz9UB918hI3^<+pqAC&oin7m}M z%0^okG&js3BaRghOxmyfl1A%Z>8WH0;{l&jNF^T(6}nw|Pd{fm*Xk>>JJ|w^BK=mB zGkX%){3*i4*_j(RAZvw)gd}8YO8@;a$Y67`if=y07W2fnK8N&R3W zJ%0SyaC@(%^*!?8iW~%TB%7kLuEAM+zqx?kiGer*1b)2-Th{#Ycx`0s?XzdkF1*+J zlM2XrOv}!4tzX5%)c9aD+cb0@&|4J@FQ0|@_;`!)@p0aaK~bN7tf+7pSaNm_4vRWN z+JovoYdLp!p=;Ii)BozZMFRc&TA1k=I5}~FUk~q5zG^AF;p{0Fg3yyRf?} z+ymICs^1||{<4_m_=8RD zzv#V@r3vxeJDx^V)rk-E=4+Z^6=ro)7MGRaN7ubJ62x^3Mi?r1ATez~!c=D*)W(YJ zsl9_W)ZH1Bn*B$d2SDxTN$oYK2Q(vvx}{mI(7B|!00##S2;hr^$;g8^|p7O>Wk>&urfgruaX($dl( z>`Gn9qFNsaHZ1tl%&YY?v2L@ju+uU!jF_SLEd1AJn4)GbtbUl7iGSQX#U6D~^H%}? zpGqn(44myxfyfG|bHTp|YG&T=ttyKj=)BRB_|vNQ%h_b!33psxF}QFj6esve52BhvlBA<#Q84~?$O;M5;=Ya# zw$h_}H6oxOFV6rl9grxwIoBv~FCwlRFVuddlqDe=lYcXPd6A#bl(tiMU(D~r}wF$3BHPpi)9Q99w;d*gVGYQz3t%PEK)9&R?$Ci!cemF1*)iOzADLZ zTVTkop0!%(iHTP##Kgqx0C8&|0T7(6;qAA3F82v@$(#nuTrhiSxAk8;T1Beez*p48 zj*KOUJg$$yQDQ5-ftiCTe>;kT$49)b|06W@9I^AZ!=~uK8yXUnxkSeK&mB)+v4k1} zRfh@=4vsQYC@PU$`t-p3f3NZ2j>PcS(!mh5(d8_er#ypj9`#N?s0}4HEOz_{^wbT zpnD0Aj{e7bV%h~&CD-C$<#KMVL;}B*O3gGbNF1H5cPXf{dYK2X7!eGExp` z6RTZU6k34Uj4-O35EGRUTTI+qd@xh&WF5GLK`dzyfz$<}F2H3OX3&!fQg5ckkU(5( z2?PTC&?Y#AGf_~epTXCEtefVbn&Ts$U98`=L*}Kofhw;sVO1-F2zMwOb|`@uJg?cG zeirB{i>N4t_9sc9)8iZZr?a?nZE?}d>jIOBwbo__-SGy>EL*&-n?PlzPjEReX>1(lNrDf{8_hD z@+|A$zkj#Dr%IUxlD&b9h6XfVU~7H{t>3RqF%rY_GeZXlhm^y^*PlLr{@BnUsv?&%XyuDb`}m(pjDo@8SbNmKE4C9|3i4e0Sb;3 zAb2&^WF@ure6F}H2Ne6@wFBy{w>aA0vdum2!0kEd-BLJ}ukngRz*ps4AgFy|FG%&% znjbun0)racp92FSG7NvWVGQ@j21wt0OC#k+8F)Rr2r-a$;LQypM^=-i#oIt&3^>Sw z_w2rcYUHl3PYD_lc`L~XYA4@PbAM>0s{|PlCy)mT7bVGniC`f3wR$}Hvw3PO1>lP(6!<{SdqA2Jp)}b zf5M(kDLhPzPB`|Y`bB$k1-3=tb5OVfmb)VE%g4Q<-3GLgU%}r{J>J)#Lr|R>zh7QS zb<0^o{?rGy|5DIyF~v}D+9$~`J;ImMCmL_|yB=61tw4`I$_ zH-^8}&t)!s@sd#i4ob@kf&*5-|bPbVnx1V-}Vgx2haewY0FeG{~q_4f{9WuyTtX3&jg1I7GsrR`BalT zhu!}a(wen0GL#Np+%jE`1@8@7A-y$&oEESrW88G*>96Jk!T0PcE+phmpjV2N@|q1V ztuMm=-W!41)!pr1tj(SfaIy5>4Wu3Jet}BIBSEt(SM*z!JB1m9aDa$QFXO+1u{=Ya zfnW}hQBhHeIqLc?N=i?!=H}*RQ^6fz_8Sua@dA|GE3KI0#SQh6XSbkW8{5>91^SvG8H$3JTAFwl$jun%ayNw{<;weKXBev!vDV)|35?`?meNcSG5UW zoHR?QAKCwa6w=>LE)qOHf;x0bOzC3aja%?)dlWXbJG+^8YCF^OlKrP+R~H^eEAdP1>CJ^>kyE=$WR@w>~z z1ktyfghd{g1JQbgxQyG%6g*(t<^f^9{X~n{w}(z^a}^1XUVJ%Pe)RC+cymgyWOKgS z?YsHn2+f(Q0G7!KKOG&$wt+}}l+ad(>+EKjXm#;Y%;PQ9!Q+Q@>;D7_HJ_jQv^s)8 zVta1R_~+B|kv2DK?JbTa7hbCiqe`pQF1D%57fc>BqPcY99%Z|*&F==}QHA#dZygB6 zUk2xSriAzLJZSL1K+La@r*6Npyj*t5g#~i%I6S59mZNx5C6N&aqc109S_D3+WmsL` zwc6}F*eap(S1e};wI{=VdI$Dvna5a%FV&s3Gm}didXb|Q=t_ACa*`D4wmv<|{aL{( z`##oW{81^I@)h0_jTGUpE*^K^BQU#E(e}o(B#F&ur8w~Ei^8+8|83)QUKLwJX3Xb) z%A4++`w-Fdah6bBi7lBZo?xdHLtlaSGWaIQ;FZ7LrB?GXeFVsndwu0JQ%zAa{RfAA z{KcoDY2pcMlNOLBQWrI%oWjyaKDaT#ZPgQ9y}#I=1Blb_07HBA-w)TYI5utC!PU>q zTH7dj=D)*4MD1j!N@HU@K>z<+6t$xyd$*b7jhw0~zM#>!V(I9#XxQ&{nK^Ds!kL6y z12%KAPQw>`cjNl2{!PSS_}Ae`>ZjUr&Vb0@SNct3MIZCm`~5~^SoMKD285%gmhuQJ$dymcb9rQZCHY3jj2@6^RFd-2u=#hYvCfa zYGSJ?oSZ6IX=xE4S?=amy69;0!b=F+UP~@Y+)?CC@ePPd zncijv(A1kokPr*N9F<*U(4R&Lk}IwRVFh2%^UF2?`;ZVLs!M>%;mOhmQNIh`qDALv z{uhr0`SF<*=DNUvXt**nz=N{Vi-NQ9utYELd-)6fwaQU@P$@pEq``w^MhI=p297;N z7)X{gj$H)h%g~`Rlji%x&$=w?#1ZRmF|R|0HZMleG7Ll^M=4Nl zF1bMQX!xXAR>)VBw4Z%_8XQSVZ0Y#_2?z*$0kf|qs3f2S-47jrx&=+%b`=n;1x_8T zkP?ELgQkdobB?6L`sq@{L-BXbhV0^IF$WsF#zxXEelr^Cqc`;!qgA2piWg;bw-kRt zvzRr!SkTJrCHNJiV^k^Q>_&a;c66VMjK0nJR8#z8csOSN=ZEe}YD%pyW=s5*bhfmz z=yjq>e;p#vXL+fk<6AC?g1d;dBiQpQzl2I-eyOA=L0%3A_Jeu}JSYd`SWFxuJR z%l~)ntjK`IQ0^;6OOZE-Z0jhukbb+G!Qx(+_0VI?a~ZYXLs#Ou@$Kzd`xnp5JBWk) zCi>Y+QDJ{?O0$C+Cqlt%9{QgXw;L!q&vd>w=XP)xw}}JVGriuQ<~;%ZJO9OCpMm-- zl16QAmqPS5=ulwnchJwD&6CKZxaLKQA!W^L49=v%0Dte+HS456aPtZ11f-BRCkpN( z5Mtb+y!__n?E#N~f!@lR-TT+2bA$f)(m8v|$h*3YsWi4GD#1mEtROTTa?uJN{VE7N zf3)9L6Z1%i_QfoTCDQXXxA{Ip(J-S+aF&g8EBIyH;mQ%~vd^H5_Xx!uMh!RJU_$w*gM7a#bLI>F@v=5>ayV2%VrF<7hb zxq`j@CI@8dsWIX1gTh)^-pso-h94JAlJY52wq%H4@j%e(yc%hqJ!i%$sL#C1hvtk0 zRgPrPxxYAXIKkzmdCVm4g1PnagMLoFW15>7Mp2tMN}=Xf(rE`fM#vHdC2mIUcu&kfX_12gwa4!_^`HwNeBcB4zo6n<4V%Kd{^1_ z)!=R*8D?Q2O!TlmJ#ST40C&?L>C_;T+*)H~wTNSCEwe0Ux-3sGa=6O{*d~${{rLV$LVdCe6lsd zw=%G3Ukl+4Z=|~!SE1AF9sXZVC1;^0-qlVx>vy+7bdm@?)5g-9fv8&z)7`juM8;`9 zxLu0an*V`943*B0(}SBM8>NnU-yNLg%=LOK##l9zjb&2o7^aDnOfN^rvYD*47Jwpk z_4G`D`*HfN4NAIzhM$((YvZxil8>{8apoh{rGQdfzCv^OjX8S@`r26GR4z{tw@>lP zl?ZYgL9pP1w-jai{kF8H^A8hJ=YMi%RoUJ6d3GJ~33(4e1#>GXn`E*$j<=GL1>POmg3 z7M|)+a6R9wvNBLKW+lw8m4i57ksQ&vJ!xG4p$tA|@j{UpJrS0>>EJYGl zWYcGeRZlNgF7NOyiF@6hQ^hxzonw5jn<9V1daYL_Sj(1N|4GxM67kC<5!D(KSPDNu z?T{-k{+g=cEDYBj)+ME0t-or0EXL(18yq92AECvN(@T+?d`bYWmU>(4D&ghIE&mT+ z<&%&$`?zccPx2?Zn0NwY$gE4xQtSjh?TZcb>Qy*Yk>#*xP3tj`J^ZIKMrT6(j`JNl zPj{760wLKOe4{f?Jzs(FXd1DPpFe%dZSWE_tb2^GEx!)d#C~TXipI3I25W4z+fyV% ze1aQF@>+-QsdxwOk&BfitMkP0MA^Dg zR4ykSUeAflywG^K$FK8s?|CoGi;`drRQIn9z`J9Z^AS#~g#FgEPUyPvRrd^)>6;t& zn;~+U)JiK!NNB%O`S0b81Wmge%0|WN@{g5HrkOp;kJBH>k^Sx)Q?uMXD~j++!arg+!3!G>$X^y<$oFLU^!Uazx%-zl z_TLFt{eOcHgd|7LyP6QPzNQD<5S;|5i zfS?~%S6)t+?Yzf?wKJ5c^x_DigXw4c!0jd0cn34@mQGICpNDM>cSi}IOGE!QWve~7 zMhflF=%{_DpC~N$obaTHri@N6+r|C(@q-8uf1ocD@*wl|o6M{R`Q>TiVS9)9<)$%! zXmk4-Y8H6wE<}BKfDcC5vNg2V@1Ja(@VZSHXHL~(DJOH5BxF{ti38i(HqI3FUi z;+`P=IWz>`?I~}XSmFK~j<*K6*}wUX`+{m@3AhJ$$E~8!iJ8mS|&_Xh#AHQCzCAw=%ExD{1*V zulD_Oa6cC+5HWm~1R$V=BXW`~X}MIXXJJ3f8*lVg0@BMrY$M`z>#hih{a zu}CQ{Yw;Jvgf?E*IBLPT+u=@vTEm0G%w@P~#uzTCrFvyOtev{`V4cQpb^gouAd<(p zrkO@H+?%u)29=$|K6vyJ59LiwvpB!G>7vJ9iAt6&b=`E z3_<;otZ;VvkhjT%$QqT^i~k(GAA~j^spU|A2-c&RPLyUuZT~crj@U^LBwuRvnc&=b z^!H>KB)U0eBifN!kLL~&HBrG0T695s{)t)V$cvS@4+#k&Knq|EV#~$E9sr#QImn+( zFO$@Nx-s-ITRKn*lQA=ikrDOuL&Q~u*h-Zd7UpkUv-WGE^gR^?M@LRm+i6PZX zJs&PWMehS1?|BZ8H&d!troVJ{d;OUKN90=K-N=Y~8t67t)c<(KguHp{m6@NPZ><_h z4Cw77@5Ah9DzP`#Q7tVJ_mE%}T%J`Vv!Gz&&fC!OyTIq?rYI|u2d^R)J$Zg4 zXtWZsS`bp22eq3CWd}HaB|}VHz6XBZ?Dc$_Qb-g$Wv>wl2nyFMag++Y^ZS(}O%FvQ z!>=(^p4whqEB{qq>0A4DxP&O;4#B2uK_+xgUu}dUz<1ba0KNSaeBwhpluW*2JWZR) z@q4+&G-?2yHnOx--9mWfo$SFy&goKEHEQW1iTSB7Tpd#eD`ct!wNj1DY9dj1bD@>C zjL`e`XIbf@w`p7UCmHv?c$RGN($|;3uW|&q#pNEnebWb?C#OP{zApaY!cWt0wu4ml*cqj# z2dh36WJMixM&)ywQ`A^Nnndb@Q^6~%q+5-%PPeIOzr1T!hZC#>XX|cB`I(M2)x}? ze^5xetBrW?qf8VbA9p{ch=GJ60EpjH;(*T?0lJ4;$LTSxH3O6ItnT6A;X}*0qOW+p z7%SVS{Ixj53}09}SLRvaMzyRk^AbfDfE`MFnvni$@gP?&uNc&;00>To9TtM-5xKuf za$=Km)wlMBJ$o(uhDG%RNr$oO>FG4;M{`1hyY7&yytv-aPIo^mCOiuas@kW+$5(yYX6Q1&wQZ*~-4ClhHy- zx*tBoTNcM9upo|;ytLUUb#b1Yk~b&z{^SN(8f8gH{LxW*Y^qNam$lBo3VQnN89$4` z_4&TrYOU9$jm#tF1~*AepDffQ8_S!959W7%k*}Vvg-26GCWbhu>Q;AKy8b$6VVUjU zE<20@LKbc9E(4@E8*V?Z3Rj^LTX_9*1ju7u2baKA65(|CptiV%k+A4mx*O=qV4jPK z%VGXnTO+K)4`RrDaMdD;MITEW;yG>Oi-OUqX@I6t>ai)J9a)jpwDcS2<>qXCz>JE%E1uDFmqMoOslQj>8H~;VQ|EPNwL0O&}6xhBBb6Nm1Avf-Qa#yR9N`3ffd=+ zB`=3*F!R-BKY}DDe_n8 z*3ol?Q%cV2tQ=>_L~p)qf_J#n4QQHWh}vZ`g^JQQt@|&Hb`ieu+KPdqRYR}`)sB1u z8s5FBd~)PEM5+IIyiWy2?9OKO)ItZ%oWIl3Z1QbhJ}TNfe!#&F^W-jRwtx@(PGHL{ z3(q>#+LXbFXp`+>1pLcGe zpN;V0@a`@i>j?4nH|%EMabq&x3yu%R^=!;_qW5@guwdmcrx#1KO#iW_ajxYWN;;65 zbM8j(JPfFsu`?3ioL$hUoth)}CP{w0m>cGbSWAEm!^w*Z{!X;~0J7T*!j zb1Q@ECf##b)?6w%I1rLR<3@8aZI|-^+;?Xp1TLG|;1>`;+VWCH0+mwv#lPQbb;dht zpk_l7{DS;nU(A(>8uzv5XGwAF_x-!2CUH)F^&T&l&dO<$?IzH;{N_p%XZD)XbvdUi z2LJW#(2DFs=+uCsjWtkr`p*a6cO+Q)-pBFiP}*bG$nR!wTA?5I!atPC?a4?({ruTl zo^!7{doRvYLI)F;&2C2`f+m%caUER%#XJa)i=%iS8mjNI&=P^>@6yB`ID{;y2$huT z%w8LQ@v+G8{Pol2STQQdTCUw@%*5`lLUk5SNO+IaIreT52pT6z&!$91DQe|L*99!8 z9ymS|?Ks2GTwJH}D9t9_xl-aDN~NaWsFnl__%onI zYJGn|&srEtD3`@NlO+jT_z8%;bilW9>Q{BhvZk|>?H6kl@OlpT`01Ml!$z4qYH_|L z^~pPx_%gzYFlD>oen|~fTnYpVK-AV6JL7_xS?23*ZT*Q;NT^QMJt-l9#0@AfUIAs| zb%L7IWgL(W&6(Can_!z~yg8I3MPazl#eC8>TlIkm=cYo<=cOhR@BrIwz)6J#1@A_- zXU;Q(M=1vNhQPS@1I@5xLa;(G)_!=)Tpd|ceNg+TT%PiE{K|p(7dcK7!GqA(ZlCJ0 z>qmn%rannSf69cM<529?@%@sN>VVD)8;D!LwGegNIjXCci6_YAZ4GF|zEAm)nfVIm zc0gMn#i|tF?fp7i%)Sq{1WWA4Uhtxkq@~IJk4a6+TOJ0xm`i)N<(YTt-|giMnYN!GAT=;UGkpXo zE|DDE+!NQi7g;<0)iW>lz}=BSMf0)Hq4#sEIX4~)twYi%DJAE( z)7hH0KBH})eGM>T>b4@~@Dqf6^WZ4q!?`{4($C=*_UPx9gR{I}p<`r15 zw7TC(cLKk!BYs7Bs_6bBU>*@v@RvO5A{n=>5ko`V0r{0nJaJ4^6!SqlQc8#_2CAy8 zxYn&Oeh%b7yBB6>+8w8{dlj8o68k(2J`LfO*O({wa@n{?K@Viepy$lguGt>At1Sf# zaqm(5td9SO%|c^D*aBk+>>IS-GlrpiIB<9Onl|EpB(*n3gdICLbS)T&|5e!j?IeNz zm-t#4j-}$x`X5T`!wz@qp==6;@K1uf03exDHm{pW4#PslrDUqQwZX)+kcl7+CFJF` z>g6V4EyT1i?94cx7GVGOjtfyl^9>c{kw@R;5B)$O)}`Z#OX(f(_s3aR z+i!jT(=oBJe74U*bj3f<Yo#MpU)G-ywgEXdSYOBtzMc{YGVkE_6B-XgVQbAOS zg%)?kOW8i_3dn^X*P>+8x^xHa%_Sn&a16ZuRqt<7&JbTta(iGoEaH`m8y@cPw1aEI z8&O}hFee*x(^qPic!<$TulW5caQ>CWT(thh?JFZur$cESWg#ucc-Bmu!c%t)zq&i= zz^SYuODn5!aETGbi27=xOhZIL6%wX}Dv<}$Elehf!MrN|doQwP6P$iG_tiUmt2r48 zm!P6>6qaG(fr-FJw9WTxxM`#(P_bd5aH4lliEEvH$go=fWg*Vh6AgJaIY>#|nX40y z+D_*Pg9t~I)E&Z#NISL6vQz_yf5}hAW*z#@@O`3wF)}|YyE{qKih-|)T(Zhr$P3Q2 za=!7+y-+OC{(=JBN#Jq`YjG7Ugg1MVLlNkufhHN_&Yq`xS5)kj#DUQ|y7(4n&7w4ZbZ^eA8MsH0%kriT0Sd1z^AU)RNdQ&jyoqWd0*Qc#ZYn zt&kn9%kamosq_AzN#awwh&gaW#kMG&h%*h)QfnRX#ral(U~w^$px1vc3;$0G;DaTz z{oySxJ(2e!w$mxM_@|RWsn*bFbtp?W{LJa8{h}_ou7T)3CPq#890X3jDk${@d)9@+(keb_PV}$>{fV&EK-zEt}38albm{%m$>7t_h?>=fUcmM zcvHyk=L!{Lbi7Bn4^1amMuEKNdo6DetIA>0_@?j*sH298#=%W2z5DZX7^q7Hm%B{m(^o`3FG&QbX%b(6ctNd5jYM0MKp=<&dxhtN_O7Y=JWuw z%KzKtLV0KXN$`}{Gyj+&r0#BSRyE`l6)<-buXrHw`Ga(pgc>94M-ZdXUE6%UE z1Aw6Uky^G&z2h|8!>aI#G~1tJ&TuU*GV+tDi4Gfa%@mgdfxXVQ3e;`dR4W z(6=BNR(ZD%3*;Ch(cq7`Ni6hY%VDk#r^}Y(%G}7vSm3OB5y;EkKxyhrNTnC8ZBE^tx!JK&;=3yA*= z&rFoId!~q&pcE>ybg)QFEX~*Cz7siQ(wtwWf>QnsZdna6b`oRW8u`$ugw;ZW8Fj&V zW6?EsHLe9!q#`&R>IPh$%z3uYZcu*?^>-J{H?Q;z@@uCXy{5{|n!j_;I`?>-%bnKt z)3O{1$gw|<+g~rq<+MQi9xQLO#GN@Suvv zKK^_0oDnd7h*|f3$x9=AcJ}R|j_GoL-!CF0+PcZ#Err|yhJadb;>BZJbk)e7@zaCY z2m4diKQ8Z9KOe#y+>XRK0RBUm6*>e0M z@9!gFCf{N_ItX1})=W&I&K=jue_DD+d3Le#^Vxhztb%~jfYNAu5JTm{J+4;9#+YC#(ky8IiY^C$vEk-7{cCT4@Qb`x zc*VUNwSiqvPfZ7`a5|n}LE;#|4aXY-Kxj%GOA&@Ll|J!b$L>j+O!z*bf$f7GCbYxYtv`IiC8cX zHg%CVFc5N{A6x2)5ohJ8RCpSOMMkEudHN_ZIngIk$HYlNCkgFQ0?}Yb)Tmf38XS%S zgDmEo^R;@(F&!9Th2*KfbhY(%z_LCEbc_$6S5Mhbz%(#KUgEF3^tiIppa$K{|1@dR z2v6KeeCMJHyDm2uF)#U>V^0`J>e3SvQSFYwY5Nm+9ky@hftyDb6E+)n?<#?K?{S&Z zp9ZBlt*UJ9#v6yVLS)Dp&;-oCRO`i8KXJM&;yy;Gn0Q@@Nhf`(2)XK>zjq zgJ#E!m*H@TfwZK!Db%As#;&#$9)R2&*MFND^^?F}CQ6X}ILlcOx+jSRY=6DZ6y6smJsVfV$#MFGs|wPxb4x37t|o) zq+@uPUIb@A7PT|8e{=VvOPLN7(;A%1{ff4M8m9xGOL8RC)KT}W$uWD?Z``&DPGEm} zgNKvs-wuZMqi%{1iHY(JA0fSg#mn^4qE0ffip&sjm;mZyW}#9D7)Y-5@DRXhAzm?A zpY;lCb02VL&esA(r-Lr=WWb%QF8sP-_k`G>6mlf*iRAy|>${_|j^DpOZd+z%GRxk{ z&dlB;*%_&j%(7=jLPoZ1vXY3bvdK({D0|D^dp(!$@B2H?AI~|@InF8FPPjksab2(L zH9RjZ2Sa!tH6@h|nR|T-eku4#)6mv&a8WH8XOc!Bpj}paWLAHOX}pMH7AUi0`e(4~gClpB5zZ7}Dbm-`(j;(4 zzEU)r+StG@iboC3#BMtbeY$ObU+W*QEdvwEr2efU&vV`L{g+^Jf9$dcBZ6^>l2?|Z zZDf>`8&>h+h+3)$3D_4oj@{GKdj*v4)v=n`2R!bRcS?MwbRfpG;IH|u6Va0RyUWur zBGjnSjI^+1b8*EQIJEw0-G8hAJ0xtK%5nAyW_p|pTC`EgM-@xkIn$bmQv0Y(<0=h6 z*#f5$D0csm1XbEKGi)6wDl21Zq}IMZ4dDN>F}RpTD}6OyMFr>4M;;fw4|~OdT(_=Sn)6(4DIEcb>ZHIN&&ejh-{ihj&RpwL|`#qCcX5}DBYOP7POoS|$2 zT3Pq;rOiaU=+G}-PEH72Z-h=04KedQVnzy5vh4FJ0596z2qiAWKz?Bs1&y~!&n6-U=C62cmCpa>j$bACOG zDgSm7DzYHk8V|N=?SR2ASNh_yEqY(66BYNqa7}HVIL9a_$7?ThEDHZ+MTOD|>B@x9 zcik+TuA=Z*jp!&TvGsWyVZbAUBV&?!*KT+*i8fyv*eCPgbMJThVX_c7y`&A|GGKlp~mtcqCbT+4M2V+x^iT9uLUy%$_R zo)ZVu<*(46jLoA>St4{gD86Th(O&$E0|p5V&lR^Zjc8>;T=Ai4q{2EO{IhUycFMF# zdSWp%fB{v*DKo~%Lo|L3fspS{WfnCidRE|o^1OM0_agaQe@;1$)fMjyN^oPW#3I1& zf`X(B5^_v>z8(RQFJDeUK@TYSe#6guC4?)htCQ3+Bz;OG%%o#oe(vtRP={aR&DjL8 z;iSWuTwcR5f6rHUI$`IMmlil&6nLS2IL%%M-_y-vMTeInM)i^_4_|%#(DlaGr-gXr zvmhL30qbgnJdfw68=EGbiv4HY7Ys8-mSmLAEyrnAcYM&L7T9Ny!v>c>SMKO< zSwnT}b55AKaRTq@+rNJoEZ7ib_lV#f9`_(m^;^+M*I)CtE`@4+Iu#db8o3(D+XIbW{7>unqt;f>lZm$02z9}Q`j4M#)A z5<#60l^B_b$&btZGIY0}20Xn3o zRvQTND=y)p?v=z}&A^qjzUkOU$3?sYqu;Bv4XypMjTP3wA7;>kLe zh#tnA{j+VW9kQ_l#g;!-c>*8if3_py227be^Beu>n^s6L_lFEV2(n=0X4i?tVI&Ek zVx^e*yG0gfL^9TeUmo1}wBir8RIhujEhbAXn__S&_K47x)^6S)^MT6SgjdbWPJ?b! zrnshwsA8l>9#yqtmo(FpJSvOq<8G=D4CH8K^;mJ?B)MK&y&p^({%&mf;NG1LQ6TxR_mvGU4)YKUN59SltPLD3A zhn6bl(zR%<<<=Aw!R;{eLnNwU!1fC5B)aU#o%)MSyNAVIqaCI@Yz`OizFpgC<2oJN zI;%XkJ=CfHI%Rvb9Pn*hLh8ZvmRs`jgMT9xoS#hV!kWr(BX^|yN@^GP77H7gf?lai za=hbbwd?+w@dFL19Ueu)!AZ198Swfx;5DZ-iqS_|-knG)Ki zM3x{XcbMV^-}^e*t*VVNazxAh?1Sd^eu)RVC57+0mWkQ3-b26rPvW(qAG{i3-y41{ ziSyyq)ng|kF(myPgzD1yqANv`g+}uD-usLOA}LA?`LHr9xv9W1aydgNLR9{K(aBtm z(@_!5^cs1h`NY>xfOH^QC|2O(&lB+-rt-N*3qR`)Bo@b>_hKSHsK!@n29e%QqU?Mo z)Z!ert&*L$0K&k!*qLa?#_$tkF3X>ZG`g3YO?u>16Ah_L@IH|1=H}oC8~JRBEkLba zJbO1wi;kQ;7})Gm#RKRkb$xk%pLAL4K3a^#pCTd?W9r^r0o z9ZVV4$0YCjGM5*({=J@$Yc@xUJpSu*duw=+#Qb65e%Lv_;;f{A@cXZyiX0+y_x!ex zPT%QCYcq7d+Xp6m&q43>*ISj@Xqn16?{w3?cHvnQU?I{KSqi2pSsOVI7T4drrboW+ zT?=}?9r$FXWaVqSq3?_Qx47m>A=oi-Dx&JA;D_DOe=Jt)xivoI(7MFzm&G8AzGl4F z))rND$0P)Z#HN$r-l2Yug-|2wh*E??3u&m_>({S|N4GJ=Eif9$hW506?N_9C1+4s| z6!jS$cRp)CPWQjKsDa!iuKdcT0ZGn11Hd3eV4Pa-u`?MO3KEuRpb~?0?p%|LLUo}h zrTyPo*CYO)z?C__G8OOJGC^zyviQT|gFFv3K9u#tudA3yDhSC45jxZ5S{|J>^0RBd zW+?BuR0v~_V8?q35t#50DdeDqeR!%yb07xBO24(5^GuFR4gQ1_KlbAm$J{6Pf84GA z`uokcZexM%m*1kXW0)+M(C8BV8#J+B*iY)Dr@qiC^W1y-IY*^2jGVKTR#v0?n@cr1 zPdl60XXo5U3nBDkOtOZq^fxk)Lw7GU|D%B+mk8r8l`8}y)CY{7@_w(}CTXr93!28m z#UqIe(XKu7&i%C>&mC(_K-L zn1qIBfnR@J^{h$QzX+cAxGcq<}wk?xP;;9#=UzSLwq9KP}0f$wP7{9JY z(=jCGB;)7gQS#`>ihJ@^0u4TzvPH*=!n0G~#JPVQd}}{EAd&P$y;#o@{(J`|3oe>F zib2?JaF@GFCUsFMaA}q%KYeY|0EPpC!8k46+TUOv>WM__q-7 z-S3|C+K}i3`PseILCS})lZ=lEye#i71mCV*P``eC!qWj9<_-><%s^c{ObD-EpMbyk zAdbs}g`T6>vHN-hk~obTH`3wkyB87@Inx|(yI@HjK`~iupfBO0L#Fzt_ZA%<%H->d z!s^MsTib-(=nRgt{!Gea4Sw{Aw|S(k7-V9|P~Ky=UK}db7}+`=5@FiQOSIpoGF`Al1Wb3%KK${czKW}I8`%0`1>^}sV9jJVB!=2|Sfd#EizJ9+zS|{$_%SJMJ?Z=M;3!##z7I>S4 zdDJo~^_Tq`*daJ07&64}NAroaJmqt9b0HlUAlwEaS+<8+$uMY5uWti+$+IpA9@I(c zWT~)%FX^3>#OP@M41KQoWO0Qj+nP#BjXrbkzk-P zG1InP2st$8zQOnAx1y*vAym4F>)?iF)bK|WTojz!2%do)eCFrcMpvE0{lmx4NklM$ zO&>UP>3=d=(z;n8e=e|9M4nqgh9Unr{((m&HR*UXoFKzDs(bGEJ$?}dV|$R$N`uA0 zp|_+64dLKZLGZI_njaEyR-`Z<*%>wcVdRV9rSBbi`MB4oqr@%IDqCT6Q#dfiA7>SQ zYBQrxHlYx*5TTX(OL~e2d86=c3)$~-XgWr(_B`kM`eh9xxWE3FQtU;~O~oyE_{mYM z?D0xE9B;YLcq2`|1^uiWLFMizKA{sSDRw_r44jjpqs_|ufY^~7j__MY-0zEi8tttq zurf(1n^%>+YWRG&xIP;*c9wim8Qik{DYy0yV=?t>o@CnC`;O;#av))y%{#ahc-pKkMa zcZZ0pbkm=ocfO8{baj8-7qiJ8cH`gt`{Wr=;gUzPg8I`tE6bJCID%}(ajAzq~#^J-2m?;uIt@n|GggF zdNz^vCOrmcZZrwgyySHML5{yy<3AaUA^Hvlf3xdv)>Qd8q(;Uw-k*9cJz5SI$xKGI z4hCnQpO80d2PzrMxpBBqJn0b8^x&Ly)TJ)U;)V-i%uYn`D@|IS65oqFRyki@>5d(A zhcBpm`1cAjhA*C#$Hu7Sk`;e(5~0x|%e~FsPfZw-lg$Q_!B8x<5}1{$LhNqR`!8Q~ z)8pcFa}Jr9vjC#}*OwI-B)Nd|;me$2?8Qd@*`%Vtf)+JqUYpf2f#;b@F-bTgQbG0o zy2C#@(IZIx$QQ9ZGbT(X#&`+oDWS=qIBW!{X?3WebVN^9QvjB8+mH>TzXsx7qVT2| z@XLL5O-;qScTvsd<)UEggZP8YtX8O$wN?VtpvK9eAIdAs;g5#5NBj3(H>$pGE^`H0 zof!V9aL4=VV)KSl!Pli4_;OGrmX;U3W-20ktZ>hSO|>A|ZPQyEcF zL=ZuPANaCn`^&8(3~wX!nZ9>tYO)b0^aY~(N5js#|7fnqbn<@0)qD20gWgnk}A!=J1cB5W3j(mvq_RgxJyS52=n(c@Fy#yz91W2td&MbHa_QZ#U7 zv9Eq7O2UkI7bn~Uh^YwD#Xf+iop*-C2uk2wc-B|l+}yyprg?mv7Ce#Uz=9}@bcQ+# z+#b$8xHLFYwP3sG{7mS@Z)*VY4L+|_&SU_3GO+E?(vNRO0WtXIX#2xV1WPu zsq8)5$r(=>+L?DKYdamhakJ|Om2JOBrH#)^cGqnGP7o^P>O|aJ<9;%T)KX2LnU2>& z4lgA!9-sX}L*GhT29-p4let_|9X8g;cK%y8;ry(Ugb$XMTV!k)rH>1>@_t6VM{XMC zU=U+$uB4As-F6j61yU#9k?wlw);Uj>_57Ro&UyHQv7WCMQ5t`zoM{eF2H#HX(%f2) zt6UF8#T-Nv>m)Bdtic`1sF;FDIlH?0&+0kIL&49`)f&fqBdqtWGp5!Y;wiW};2rw+ z%_gTSoNl>$?u82SVwn>A;sx!H|8T_sYFo2t=uv^buc4uQ<(McouPH%!yV(h7g9J%U9r; z5TXS(;lyN{GuQ?w-R3cEEDC(}ySkGNUZA|sL5nX|?6cyx_tYun$-$h=IbL}}e|};< zyFwxY8+YQCYW>r_r){Rl$k!5Hsy_CWiu5UJ#Y>YIh@{2AKtT*3BO6->4Ov0IwU)N_ zbTo>1r-$%Vzzmf!B;7?mmBZ}pzFkdqvQ^c=x^dI@Z~l~XQg=@A#pb3KMulC3g3QaQ z=Qvb2c;8h7yNU#0*Aj*MwOpqiZ5+LWtjnlp@p85YqmOE9C#>i)pFiFTXDqT?I~JLZe}%F{5?&gVm)HIR8|^{a!IDXUi{6?p!DSr?Oqe;;tGToXyruMrGabU~VxZtHEKk zvZvONK4*GkgQ!r~NS`%{C=-RS!X*tp`?hpDL_|c`TIHwvKYc>kN`4g}T&YAVwExQm zfV)LOab$GEtD&*<==QCLtqd4=)de@$m>w@oug0T7UV9$DFGwsaFLU>BdoJz3vW;z9 zA(hhV;PZn5LSNx|jD2-g{`Ix6!DOy2uwN;F0f!ia_+}bf*bNJTd2}rsf$H>R0?A2x zU19uV{udiB+RNG-vCB8idx!QHKKw54wmW^>-*2%pNpV@kAyaXC4n?#*0gZKc^qs1dUPd$co%){Re=-Yf8M>(Md_J{6LQ7(zs(wyF>F;O0#oezKua+ zKT3g%i+gFll~rjs4webkTW}}8868atGI~({v?7xx3QhG@Cop zXsR_k_{uY8R5n)}GL-H2Q>z<&vk9A?nEas3@lFYuxG)dC!d1^elEvQqS-*=>oV2$A z6G{QSvzZ08)R@D)Do=Xe-FFBy0vF$E%Z~AeV!wNJBjti$@+6(u{AFLZF!p~Nbvb&9 zWr`RNHOzA%L>Fy@ZyUH*Ciy?OcC5w|zSURHH;9CrzPhF+x!5m;sV5_n12LYVnDTDI zbr<@Cd%QE_r0p$rWdbFv8#f==&Dc20cilIy_=4ixv^v2D8!L?vMMwYpH}xrxR3KDp zaNYAX3`?EjZAqQskmG*Av5Dl=zi5P~oXR1EB$56iJ#nDLCc~1ZdYxl4EbVmsS=4zk zpJ+xgdZpko^_8jVX_A)NEqh~nv&v_N+}-quQN`0>04yEKtS;s#CrZfIE{-mGUir5x zIy&?-O?u-%PzyJ=FF5DrgMbWHLiPDbf*T`tWK=_dXZ1SsvX zpnn)ZN06O`9@QgXcE+rN{_P=k^r?9s>3klGe}gsG-Dxt7?Bv$#_}}N!#JPJ`kDj6D zss#7x9c1?7sT&$U{qR<)08Jk4F*(W~sTIfnNBu4^c5&6}bNQEZZf@VVn#dTNg!$pO zhTGe#lR3G24mMi@?PZ@#`OLbRy3=#7B1pvbVYZuK@wmCaFZAt#RvWQqMh+T+lCVyY!Rv6_q?FSPy!WvfmzKl%DS8u$1tyA>7v{an^trA8I zQz&b{q2B%bK2l&X(7!TVLV0|6D9w{-33y?=SlYUv{yCA|*1*6#4FQIlk`jZOvM;sT zIbtre>e@YK`U<#^A7VQn)w!*WxF{Fu3iYqp<|P}&`sHh+!Q6M_txn1H;JQb~p%kE)_U3o6?>d-_jk(ifCOx`OJ3m2pBbqF8XgNA9En;Rh{3@>| z5sZe$?OVukga5d=X9h+3mkiT3O*gg#*6hh?qU~-v;QuNpVe}*24N4g&`!C9hazMY&JwN>|3@O=_G-C74Mn zlqN~G^S6#e%q%pCh`dGe0#&;lG?X-dj8|Q06~5xccKDd9q+Vy`)PUZMOHWrsj)pbi zN&ey1D~5(sp)l2rX_-9MY6XW~pU+aRsS{grcLXUPpWLZ}D}fP1hUN_Xw}KsNw-j^Vm`2`PFeL4zo8OuS^P7 zICYG%oxYQ0!TmAFFj`R6=0P)ONo_!Q6&~@QyywOH`yU}R8IUnM^-O0)hNhMb^G&|!E!M9(? z z?o&M4z$vA?*XK{K{7ilE;MT(2T$29DfUO|W+lHI1nzLpS;wE~&h;*yZQx@NMryFeX zF`p&tl~6hqoE)j1`;!#(7604^5r10!WY*OzwlEMeKjB5rXc3sKTdbT|wiUvB_VFdj zX%VXFHZ-N@d-T;0movgUJLkc7>?!hG%{XwP9jql!P}Zb>^2$|8epjcA7&9Z7{wv(* zW0Sy7B)tERF{8xKq;(@Mdwy<@%f!F5luu#KVHmOdr{WWZ+WjM`ernCIHDEaqmhH_J zwoO7tHpmc8kKil(ve=M?2JoJU5ARTB`~Cy@)2Pf-9E56NTE@`mY}~`1;KsQh)%k~y zAKyF-2N(|SF8*Y-{f04}c=$mKA{9NW@Es4HKirc-6kr zL{SBBOO0;R=ppH(0&JafFn6W$f83>|eE05MydqA?Yu*RrZX1^|1EU~YUc|#d73hA@ ze9Zq>2kY7&gVXWPTF9Gc%HrdfP&`QJ`M!5fs$3-{jrzuxMFvh+6JUHa_8I1^e#m{~ zjpo;${yBPDT6J*AB?n2vBTjYnEfWH?q>gVg4U-kNi7xey9bA<3SfpqLVrmQ#rbp2OZ*~KQcCs5xcX=5cg^XRwWCM zno6#*zQ*F7tpq=kBe3W}2AO`B7Nj~`)#81*E3XVdVAq1tVnG28NWCGoT}E5Ge+z1MC2&1XnVGti z_3uR~hKxBxUQvm=mp%d`*EjR4qX#KRC;$2#{)|^)?DJs zXeX<+Iki4C^L$ZwbaM9Iivb5UD(Q+XJ#|vm;3dJwM~syE>8x_RUcu9Y~!cZo63coMG!-)*X<3BkX114|kl)2{E{$zsEU zgs~aUM z$Y|*l(xXt3HD72z3?#`WDtaU$uPq0=DeUH)8Rb694|x+48l{+4fI+UYlO@a%At8jc zBarcpAeXW=etZZV0=p`K?>&55{6ixUk}Eplo!cffw*MK&VQ+eNz#@asmj#+Fd@4Q! z-o=IULC>5Liw~<{u^KDg!@q(|t(i8Ld7^hVm}2^~6akp}d_-AwrBge*;-8$!IJ+Sy zI*$v%DAiR*ssy~?&SO8im1~dxCc`j2NfQ!SZtGEjl~@%={IVTkNJ}y}z>(o$Ld@p$ z!U7gu6gGSa3k$=WSMd8OpA#cU)bzZ8!X_$1OeN(j&K8y(FaGfKa0~IDn|mZWdVf&! zJnw+>vu@0io5Rv?=e7U<_ZieSFu`)gC6vDs{1ryntV^vPf>pLGxL_oXLGAU$b~thw z6n1}~KQub)XWxb*^%_n964KHHVw}d->z4Cx-P0IwY9WpWYk={AuC8vb0aqJ5s}ArP z|KsD@eP4NlbsQas;XJ3IoWkMc53RNjX41t-{+o^P(D~lEcd!6BAla}GB5rPk2A z5@b=mX;{+Q5SY;jy8oW`j|Xc87h^3UL{ShIj&N8`jkU0 z!J>t1Dj4H6uPvE~>U?}Qn>pi4Sbb@Pam+XY{B@MKuO&}V_7i)+8Rz$UEHzk~A@h3F3;KXc5 zp7@M~*o+X9lix>c6uxx}bi5=FRfB6K2MsQWN-TA5(;&|#U7Hv^2)={ivLj%(M(uCN z-OT%95pB%L;aw4{ia&zaX*%AVuIwR6AN`vDgX+OrC1CXPLQ~P`EZK*}IJG34zj{1x+|K{^vl4{*;B}c_L-OlnXm|+C%+K$F2e3FO z>_wh0;6o;>mWc^|g%N@0o49PY%Yd>9BL!Lf7vlxtW29HF!l~alc)Q$T(qSQ@vtFX0 z*V`cc-%^kBA*F4WewAj++-Tldg$Xd z2(ibteLQTqJ(w@1y{76+p*~r zc0I@ZH82ng465wq5y!X;n}D!;H?-!-r3D+cuW5P2pzmdP>!#WSwT!;Xgh>nG)_@eP zI7>wAK8DECquvau45P9~q22aF>EicT=gYb}U*H!@{`wq!pF3VfVnu9&i>v+oK^BHV z%6X42dyZka*jeha9sgE<%&Fhq`vkC(~m zZ)|VJM!iI^0?{sM1p=4ehb6-;)&gQ=X6ATCMLV^*i^&h>e9h&!) zNNdE{N4t)zL?R(K{SFPjwcVL<*K-Q^-f{iba!|9lfRyzH7uTC#D|=uZO~6?3?q_0q z%O$sSeN6OJV!gLkgC5LF9N|VnYwVUg=0G60Loo-~!|o{~*cQiMINgt;y0`Q;LW(c` zW$6BKQXmS;?(=!*X7b1NrF&}IeNRs@#v^?Z7k3ZN%@3StvOQ+8$f0=VR6TFx;;ZY! zcDxHyVJwgZu4oDLJVA<|p`?4ETfIMj4*kyvKIi>= z4DkEcD%6D!K!X)v>Ia7;jQqfjI7#3|07I$Qfqe*BrPVb6z$=7Qe?SoBvzp#VKmN8Q z`EhsGF>0Sw`l@P^eTFYfY(uS1)QwIHjpZm3by*9%BmEK-9IVZxJOd3mh`Ti;b{ZCm zpe$vTUf;!(*M1!ye!C%O@HSIYq_>=$TrC;`EI~{bOzCevUfwxN1Np*YPBR#ncTelv zROBFb{U!3!{mP2pOcaOXq>lN?HClj9f|)}ayjERA#l=%qInhdb`2BTGka&ax&7NHA z2oZUah0E2Ek(i$T$)a;o@@RAqF^D=bZbRpDDQ9A0dY^;}n$t^XvbysoWUjvjmFJ|C zSnUVC;@-@l%jzCD46rGhyl?L}vh3ElW_AU9@fS8O&Nlom9dD67w5fqsA_R)CihQI% zR#rAkr!aG1>2f2#lt$>Hto9M0I)Gss>}5!Mesf(|qwF%gU?ZxMe@)HyJE*SLIPe7V zdUC?i92aT@x$;gVg24au2o@SMuv^(RzYq>voEbO2HSquX(a#DVBGEE1F=2)Np?vWh zT$Zj#h>JtY!Hh2b&XE;5WDuhsx*^C^$D%3Ku?smCK9#>iLMkG!{icrm@@59F4{3yL z;mbtaWe+4wms@G>7@h0|#Kev%lK~N*b3%HX{B(97(XeNSJew z;A))m8N}w`;n6q;*P(}yTJ_VjyEP%5)H8#SD%DXU26lvAT0=hRIha^fYebF1rAg)W zq^k?-9>VuXNeGf1>=Y6c69`dSgpIxpzYFiNUcTKyh2^IxM1w151j^z&LB*q0-2m6+Yc$tIOY z8>=FNP{Q)X9}2Ts>eNa46;F(KA8b&^DD%PM9oaLy=bkXpwAQs?eUlAKJfP{Gq<>Wz zne@%__C_Nc^XVY$M(3{?zXgOi7#W)^5(_bHzRk69&-d?KWDG31^kRJMsvjczEcR1k z@EVMp0@YYXZ#zykCWGw;Cq(mtbNr862m*`q4MZerkzpz>4@5J{GJ!>7JSzmbmq{*7 z5?$kO&3Ysqg<8H%FD83PL{gi^lfr-#;QZ=TJsrkvb|eT_0P30rl;#WDz3u6z4}cjZYM(#eRK`Tl{r&vHPc?yfi;rwIK8J3G7QElCfzHQX~y%FV;WlyGD^3Z%@yj=ZOJdn026T>sU={5_sd z!M|LPq_w0t)GI?12Bf*h{$sAndlQ2}D{rr|OjLtZdya9onHsou?B4}C?s4pub82$z zSu&|HUF}a}lGi4Ku{)HgX>>bPt)(SJPuGNlP9qe6g{on2I>c~rR^L$fm_=GYOEUP! zT{QDYXR7TXWalxVd1d2Ow(>_r2ILyF8T%-E3F0it64EQ!5=b7UqKNY;u5l*2=HD}7 zLW3W!WN({zzLh|vvr?+khH**olNMBQuh?TU0hV|b0^~J-MWJ91JpZ(U8ulXS&|-F1 z{|+o2fZd;cH@lUFM+BVs`ygr=%m1K#yiI|3(UxDwy>Wh=2_9n z=nJWK*O5|aEt~J#MJx#-S|BSBvK!HY?QQ-0134JOnfw}dn&85QqV3ERf9+M%FXn+C zle9faOB}F*o!3Guc;ZEEelf)k%P-(Invbv*>Z%x-%=V#oyH46a?UeXZBqbq{7ER|B z{;>0cgbnE>rXEwu7&@K(R9~Vv73}eT{t5N0@I^al1~N9UGlu3Ho2na%zSI7s!S%5s z67%s&YUj3w2c1~V$-zd-q$2o5c29(=RVKu!}zJo*C(7Gtib63&s!Y40;nd3xRj z`vAY*X~)KSXZjdL-XC%?g5|Z#MqD924KA`Q#;gn57@11wc^W=a->-QMXcIbWS+S=dP#ZuI!rkwfINd?}g_m9xGbUVGIqEY@a1k6G62UxG4 znLGC?@@&wD?{OxChL@x^Aq@{bZp+f~7Yd2w?m@ z)QMYVgVbZ*dwlac_@wT!*qfmUK#$xF5@;2wP3*ao1(vQyDD33@e)<+tT3y#hB-}O> zK`{mWq0u+j;zOWt!8j*j3^o_IN!V$fnN``>88GaIluTZ6e(dt{(fHSl??w7|5>70@ zsd@&)nzP_JC<5+PcV%U7fmZ+1{FoQ(TxYq1Rn`L~<4sHyj0I1ACnZsdj_PFGBWf%U zVw8RL=eK(#oy5~Bi(eRa>SI5fe{a*F;b1F|+CMd1NE!Tv|9s?CtF<9>p->1~wt^QD;h2VH5$ZTVNC% z+c4Nh7TP-^RMascrts!~UbHnfAI{asf_wSR#r>R}i)WpQ*^% zUSp{-mgq6=^}@!9w*g1->b*!X_po%-9W-t?SoS`a$v>~yCgamVKHjSu8TDJ8yMV#g zpqILbhbW?@7Kgn1c>QUy6rM*yLc^7heu~N|?1tZr(&sA@G7$f=vUfjT17)gLUbg4x z_O-R`xovUs(9dht?u;GCuZ(~cDa!k~-mgCl{!99-Q_sw!xBYWf-h~4VLuLx5LQ^|O z?t8!Wd)}`>vkpV@uxtpcvEZZ1gawqCh+Si1x){?%Lx}BJM|bVowSSWhQn1!AP%jPX ziV>){Aj)7Ch*m%rSg=5`fQ9YV=QSoC@a6%f4Mb>?GwVpSq_2l`AMJ`oiu(7hh10KSWT42G_vRs(4Xtuou z%Qhs!>Ss`g1l8~OngZRigw|FyH5tg8l#KRe3zj!c+89XoXj&-A@9o0B)WIdX&) z8|h5dcVL&;8E;llTWc=L6ivNU{VEe%D_`&XTc>mIT4e~j^?^6^_>k|#@Ky;JMgaLY z&2IhBYf#9Mv9Ms&NEJbYhd>w-cszG4LIDy-$zdr4R#gcH-DUhwH;(>7j21Fwwua68 zWQu+Vw9h76qOE3KnrUAbw(o$%o4~Fv6~L+l?8n^a!Tqs6Uz0u^YLtJkul67l+9*dT@+ zH|$9{kogJunHF0f=zo-+6@E8+vf&q}mVR1!?`#Ry{G8wU5v%0MYPkwe;tDqz-sLw2 zwJ)@l*^rq)_(dFLT)uA6TZ~#g@wr`Xf_na>Ue?u?ro&L!mT~9~N7Q#xMn7BTUkN%> zyIlUPb+vZBHH)tQ%LM@DC-Z(~yWQm;;Q4Z#98-Dw5rOJTYGt3gGaKvt@4wn7C#-iK zpOqL@sE9*c%ZE>vLyOA+^Lv-m4&#h+Nj(RT2NJxzTm^DBdFe(xwWly+rs}q-#lPCU zENCYpK78F+q9>cnpUtcvJb3u^UZ=AN&8E9JOnRq5Qh2$VU|dQCaQYj(=SUAJBQo9BhUT8QRXz&}-MO`OouuXz8BX?n_|Sj_fJ?D?RA{IBXqf zD=PBN8y|L|r66^WZr+?31hv3CzEd+zEEr;xFHfISCmx0U(%?@n%RnqWfN z0uS{v+6^4*+T(s*sVd!#;xuS@(Zo!rPZ0STZ<6~Wxcs&tZ7>a;srxi$!s86m%~a+? z)(ZFUH_J;e{)RQ)yr%DvS(IM-e2g*oGP-OA_Izh~S=q8UxLUR;QTRMCGNSJ4>Y9UJ zBK}8;zGeKVm>zwtV6M`S-df-c3IZZ>optjEhy)V+0*)!?|at$wJ(ba+6|Fw^p{36cztt!m6O z82?a9e(2`ZO8lVlhF)soR{#sdjIE6NJ<--Fds#Y`F67a8)9GT^szUf*dRoO#+ATyR z3=FIwlJ&&)Z9}o;PX59Z~Zj$r>0 zzm0_*$>vxS*Zln<`lkeHEhF~^(~{KOt8f%L9jrfqp#{3My2%env(~odYN+4x3}EGRyLVFV0uj*tW@mjzx+YGGmd>D zuj5gfE;0#>1`Eg}dGh@;Y*jH97q6|E?>PUea)-T9py?hm*AKvI-wBNVejrnSH>#H7stS50zZNluK&9%B-BVvUSOS|aFAR52 z&+Pj}dY4ekY~@vyVRz2r!F7Brn1*PP1ygVvWoBj~>hA>5AQV-vC|D!^_62Y3^ktqR z^dgWzMSFB~3eM=m&do9 zFT`=u%2E@C--SBM-eh2qt_KIpa>{(joVtwjQ+uzD!l{hk?4ZU9q{i|Ql%tDaBs;on zZW2^-U&)74U>bC^Kxvqz#rBW=4Uq-ZWxDV<3h5*~wO}wmzmcOD)drO=8Uo!%3Gkk! zU>+fL3}+E`a@^l+`S1c@8fiQDY%-dT`=EBt1u5u##AvA>2(FL)3{;>yU&V}eucWy=kPLSV}@`Zg%EwWF^n#R_ z?gDVv53@7R!$vJrQ`1Y>VG`2&`r%R->;1CM!a^5RRmF;h?`=pvG%Nq+$edp{2<^N4 z<0PRSPOhcDgc8)EB}{-Bryj3=+c03BV%NraHeG0VWlFi1!||0r?e|wP)R@gN1xuEi zfwlR+bIj*)GikPvK2SQEc4f*0GC}3@VJB(6=Gffh3_gE~dGc3Guf&CIGx~+y)z|fC zsM@)9#e0m{sIUMnTWM8Ix-ND+{SO2ky3~CiwGpERfl>{_FTXW4_iX=`F$3oKYJ1xm zCVQFL*(msZAec<}g;<&>t28__PEzP!Fl4}qhYa8rP}H+=aNKorx&@Y*(AHj7;M>bx zoaV)GnAq5=z=pUCiezGDX5{83SYKbiY>@h4>Ku4C%aL%v#tT;4B>foMzqM$V`hxm1 zR{mI_OolbLL)osnY>5B`;UkG7!stM|~ z^P>i4rV}4z2_1-0~r@oC7XoMyF`V_pcE>lv?zlV{3yt+wcA-e8B6va)N$!SHN z6mwF|M4BmKz&hg;e055t%(X&XzxHW0gG6aON@j5Svm?&ss{DMOHvbv)J;`s?j>U|J zZ^z3(N_HCi&SWwoYjnez%%64om0mgx85OQ0ruch`Ygvph8PF&hC9tPvb64&y--8-d z0{R+2Is@T&$t)|o3Vd^MDag=mnw+GE-lqj>j2>B3B_uxf7-B%WJ5Fp09emALx{c;t zAfs!;&Rbqy78@-SOwJJZ;AaMBpWiSRrms@M(Cvqg2L!o%Mqr9Y!`=-$uMH}c`>yL_ z9vQ*4G4NlPoPzoDHLI0m@aF1zCkVkjuLxQIubzWGNg8U4+S=MVDEFxNAL00(A6WrH z7rRwgcX57)UFxD%IlDiuX_!}ced#yKbb>qUBgdZx_f9OiIzg&YDOcgdSnhDU*4HFT zYHD)6zLNQnMn@fi1x@P!)<6WDO5m~uboYnDf^zr1m9lW(6QC6p_2c1^ohnA*m zfxaUujXk2CV5}js2V&`@0U7Yxocgv=kB%(E$o1LCChL1Lab-+@n4;I_UWq7mJ|Kp5s72#CVB>1-uXCJ*CE0e%HW-CA9Ws1!S-*T%>p2HqEl$7fLNdtGB7uz3F zyz%KJX`m>3uCx%x9;@@H%;jO41|!M+g^oHO*{SuvWb5hbPIG_Ii369bszFSxrj{la z51n$$Ym%EUz>?cLhUsle%1WssJ_6vVno{nqxPyupKa#d2--T2z`U$W2I1eoMq{f>> z+;i~&#C#A&64NUy;ZV5)bs?Gw7x)w2J3Yde8-34&&q)ASwHHD<*yCha|s+aKfwcUd$a^g3V5AHBz8fMN7 z2#)HwzE`hWk+&VlBY->CiY{u=xdwRU3xjnDEg0NJU!*VJag< zK(e2es7s$SBLg4>K$E)(Jg;efJ`d~b{lw4+7?=lwHp&nj1M7G|U&9WZ5gaKJinsZp`tYgMA4T)K@=9&Y6_oJvjV= z?N4}|qYvsQTr?SCs3zKFw=ZLygMu)2Dim`1*PR;y)dMCOM(n>sD+4h0d5};3l3Hid z|D7Y3&QG~?Wy2eYIe?afP+W&vwx?#ilX~1WD9ciU8^WY~Go*z?RP6L_V8wa{4|Aiv z;@YZM^M4WKa4SlhN}T@>1ux(}^50h}dNH5&psL-svIj^~D+6#1JwA%-O+06h@;oD8 z_q|ZZ0%p_a_~IyTDLqqItUbdJ0(n(4rFQYmN8}^Y7x69q|FreiK~a8j-|)3dm!yC+ zNVkL{5)0BHr2^8Rf`sq`X@R8#q(SKp0ZD13mXJn3QaYu(Yk3a${XFkqud_1_><%+~ z#ks!clbfk^EtdLe!b0gMtHoI0<2ds~sF~-CN)X#`Rt@*|48!9-=P&EziA|Ls*0uLR zBj7Sn$V1Sr$Oiy6W+^IX$_+u|b5Z8)dkol!o>-M!)`@rNyhXR6;MODgB!_79b;ee7 zwWK=%<~0IK8aQM<-bR2RA@89*kPaYkznob9>oJQhb*OXQAhK`L_`z|h zWSa*^^gSh6k>=XM(h}I))O7z&t^W#=2aL4~jw0?0<;MQh`dcIX-xEdu22YAtBFrRz zUIkY(XGYoexV@q&hCU>Vh-q+5A9T793SOnHzke|9dXIt3ejsa$TU1>~^ zW8R$8Wf6}qujeYN$;5oB%4W`Nixy)jEAi1sFHFwT!Hjuhg5Skk2Plk7@90v)A6r4h zmcRAQG-f*)pHa+pOE3v=_o0$W5pxbqId`MJK3y1jEK0U=k6Lmh*_vEj`(UZZ?l)N? z51&u#r!9^wOdyz8$c}uDiw|eH@B1sX@IQb^gU(lg$cR{vD0$DLU|?Z-Q4U%pf_mPA z#cmNaOf!jz={14*%N!^WAtntFfPcB$90~04Vi!dpAti|qX&6QKZKN1~?+^G@f&Pl= zT1h39@8@A5bwrc*=kp&S;{Y~bu(w$%nr_jNg1Jp<+6X%)Z(jM&h7CysuUx=#OY1ga zkKK=8-@Y&u%1{jYL7KTXR!0iIl4C-krgV^lB%mm6f(GN#+1^>?-T10dV$l!DL{}l= zuFD`@^KlhZN7liX;N!k^wo7B)64Amup#^2N`IJ@mj6dIpAKN2zoHU`E*P27-2=<-!1) z?(7w1IBK`KJIZZMV)b3lByQdZ@Y3*LQ=>zVD_IB3Mi<}46&y|YzKYAWe@~%Z< z5nNdGC79TF{n0DSkhXBYVFl~z=%g(dP7!=hqzq-zKB~$=RRajMO5I5IDjs+cls*us z)a9Q{i^FVpMMCzcWC(nM7;IL>CFTDp&v5c{KkyXF7=pVVAc4J43(s~6r|$|LY=nQb z4s*y?QQ~m6p#6^Z(`B3c{Q5M)Y6LeyEIOzo+@uwxxv>GUDU(739T)J*QiC?^{{TDy z62Ww&-cO6|gYx9(0lMIg9HVOt`8&b1oDg;IE)dr$1NfZlEhgo%288(V zp|TAh^o1n37w#s+_QzQ%9U6nfRl5xg^q|4G$Kdr_UlaWh_QXd_=%peF&ihaKowV_k z0Mhq`OD7*JG~&f_gF*>(7Tg0#Yl(CfI7vtA8Z-GWMAkea>%-}fJh6VzD@nEwU=DnT zBmPbpvY(O8GOjF6<NN%*Ay^(kit=U{O(}QAlG*0&ZCxFs5Khx*|>-{fGnXW|sJ37ywzaHlyr>74G zVrM7=$hDj)cl|O#r2iL;(I}U8I7v{qDm9czmc9|;^ULw~WtG_oXFA5lOjVO-Ydap> zWSMS8U#OyccuFN4*--a(WuJDNJo=v6&&S2yUEuliFHhIMlg$JZ{c3wATW+X5;2`Ls zC0-DWS)4mE-_n!&3z2nvdVevjr}ydj)H!i-RQKzK4)v$vqIO$&pW)gA%L{uyZ0V%p z!n4Tka(;t$=QGp zr-)rrNJ>hI_#5Dwu8(VG+lZCFFC~@6?peWtu%~R-NGS0nd-i1WWZ+0I)yhPhdwl(P z5WMcG^KiznDrJ)@+zF>G0o2L+y>)&uACY!8lEC|`qs**nnVrA;9y>anLn3t?cSN|0Y;RYH8RPM{y z$>KoH_`mBFnR8zB-!wmja5v=;C>%m;Q!5|TI6>EMtWQMHE78(AG+s78+k74MH5WIx zV?O=M7Y|Il9)a%;!UevmsUUM*=R@L+0JTuCwPoA-_i)UiJ{7Cj7{{;IKROEm2~sPs z5wUV+leQNp^VjX(F4Ka7nrIM2pe%KLG)!Un71}hTPz;%Ru?#xZZ~Hi6Xlho?0!=4= zn$7PHw4$$T`lByTI(FW<@7lWSF;myO@)|4gbkxkHz2@CbS3--V<>^Dm(fMtdQz)(o z=U%V&3cO&vl?XJ>?Zfu~p9p?ELwbI*?d5LxeDw0>@{S;(AZINL4c^Wo4S&9VSY0@7 zZM0X5W(=2|{diu_q?S0)BI6FH_NI8*kpX0!8 zWMXK%S)8XO_7ADkYmfa~iM{1-$<^6I@3d8k)yMmiW+Fp-$H#v0N|>^^>=E036Az3K zT8MLczE{;pFyzz;rqrOX?7|DbG$W)|TVLw60c^08gJc>W1(I2bKuS$~Nx~+T(S5_t zxB(ki#;dn~v1`rRJ|%$e@7pqT>8m~ei^kL0SmoS57Z#T4?6F&|fi4?0vp?^A&eD82 zMi1g!I&xL3LI>&i5nH$-AdC32R6N8R_Ef0@<(prjsX%_P0ih0zUcstV>SJ#FwqCng^RF1&Ju z;dMRUOwu$iOm28rL_fP*x8>j5d(WS*J5Epv6dEsG)_GeZ&;O0vWg&G|eRF(ZMvNl$*K_A2B$p5i>7GSXT@x+l_Bu8G z=6=)aSQ|)zW{OU@d<}L0XQ0|`)ZP6pzh0w7=N2mm7_V+tc1v>uoE2BDNKtz=& z=??ZeDLzwHBIs>K!-waJa&jb|J|DjZwpMSyc0F>=|FfAnN~>up(uz>a7p2xL9?xbK zdH(NN{q^-VAh(#N8r+3{xq9Y_4n5&n%EkoMvF-2fQ3)U=4=fFCJ}&>g?^As&fMh%; zz(+|UbnLlUO|blt6LzhGr|cr?F4j91~Y}@ zcdxF59kvqiQpHnm8J!WJ)_c7>+qjXELO0#uPEIU&MDk4|oxiuQug~dAdk_gr#VS@A zcDCCdRs|-?7~hJ&jPC*@Z1&8i7hgn>NH{R{C`$QFy`tZt-pCN9(XtTC)Gk##&hH## z=kAd&WeNm?Xa*qW%K=lhQg`29{iwQUS_?kmKN&aeYX97uNIv(@ja7ggCzZan) zrKawh`dlS<4Uz+dca5q{6Qvd3eEb4wj9@_Wj*e;GYnp$5{jhkQ3$T}wPMlmx&&5Br z{|OD3StYiX%e7Gfu>aGOm(m8GDuhbBta>+q>!)m3NEfw?TboRgKgdUr)=i31!Dn^D z6pN8&dJVVL?!EH9A_|n%LNEM09d^32qj$C%zQJ$Q=1=;hn!wMWwN@vyt-!=SYrcn` zf|8Ps{*m_uKQx}wO}Hzim!OLG%}hU)^)zKxSUCbvoyx zJ5@0Ov?5>t`^;xhy~o15S>-e4xv0X6d*5YTc6Hd^ z(5H9!fG%2^_M)}~>OA)GTpsvTb|2Nmfl4!cXgqqHNw&xpM#p~+OCS6(_D&*i&*+g z{)HQ_*Q>nHc=z1>JF%DHSFrgIjx-b)$o94>I3UO$o2Ydu@-)8jVx#bQ`D!Ur`XHtb zEU6OEb6ZavA33I?ejyd+w3h33JhL(_07!AXN21Hz?HBW!~)V0bU9ovby?xb|S z-kquu7|v)WfBB0K+9QRiFGt5Gr}1Mny%X^XrDYiv$!)4vFLh24!qsYv6lNJX7m!dY<)eWlY!iMDJ!J} zVg_bnf{!0Rx`4Xck3aOTXrbKr`1sFR`N!bTs*@l2La=bndMncXJ^!)SPH7ct$N-Yd z=6>NvB0q4CzDO8T7I8cPe@0tVbN-9r3jno&JsGI3tVncpMqiz$3{Y4u7wcCjJoG_- zJO)~X(U+f*st0QXz04ce52dc35knaQyv>F5C*H}r%^%N=p-jB8>kR$4D=kJj7fE7N z5hm~f9nvIMM!tS<*XK*N0%OtG2o^%B1Wx~yGazVy^~DSEt%)Dm`W#2g?uW+M>XGVc zk9OZcz0+}zTxSmhzICz=RPhaHsl0We2d(n`sZVy_Bs~lVNbGE{N8|fMB6*o*l@gps znU-@tfS`D;ktie|2ZU*>5re=i)7#kC$hZ#(vDV&R9z9kvWgQ(Id7$-5u@g!(6Sz0=s`0*1~_lN_UZVeFXucbxG%Wob@zp0{VYU>$~S<6nJZ_AQD8wuy>A?KYgo0;#&4cl|{ zc^!mn3vm*Gvdnkz)&+N?E(AsMeR9%AV~1Sd~6$`1M7H0_(H?C{X7!)C*0lMEo=G?CR-p+`Lr(&cwmdsaLN3 zGyE148WbT4=FTV`mf7NgtuX=k71)ka#NYlB?!NOnRoW-*R%Vmd00sgUA)y$@DlfgX zh`aX9vJ=}*tCQEmf82cLjA=|u@F9+a)!TygJm*@Hc*z5kD(kzTtjD(aL+!}=vK)oX z=1xXybIt_i4d4s7AXD^|fzuCm8^vY&eL}ISNpO=)PPSV1OnCL_rrjs-8G63M@$1bu zoT&H2pXXOq7g{t0rhh(dGd+@Z$C7zNB-4^E!UUf@OMi3GxsX$KbjASG9 zQe|B5oE_xIw?w}%k{)nxwJ3Pb{RRZoS<42u?E++4@AwINVUN9#B7`;~Del~i+v}F$N!vOpl zW%XprXU~&AK~oIuUyknP`J09o6)XQ8Do09|-Te$io`u=j*|fFj^PWrd%#oetlM!no z%f}#@J$V246>c={-YEw6cdHRnKS&y1oMv#0^n*1I+zyl9L>QQFm9~{0C!Zc9B<$f_ zkD5PdIjs29`kIB4Z#etR18d%i$h*b4R_g>uZc)XsR?|1GC1OQ1^?c6yoP0oH=@Od= zQ^4EEA?1q&pML_wW7g9zpxU(f1uI^)K4GE%7UcwUN=L0XJEMMFRe=1n z@Pg9PU59Xm;R@YSV}L~@fGSh4}`K?6Nv*xfy zP*|t*-w1>@Q1@jEmZ(Lgc-ne6PB>tKbSt{yOKI+VUKf z%juH?Y`4Rz2}$+Joz}$@SFe|$a2Xurq>Z;jzRdYZ<-3Jr|3;_PXZXpVNNhA9-Ey$f z+aP|IM2YH_eYumz+Vab&%kgHar~%lE4#v-QhcfG_L?-KBRINgLe1!7 zTPa{~x8OHvvORo+fx$CMQ;ci(3M+Hb1tk9RI9$nbmCUh{;EZHhjMG@z*k>9@V~C%A zZ;OaLeBgetoB$Am>DbGD^B<9EV$QEFW8zvkMd04qow5|uKZ%T9h*F}MKNZ2wfMuz% z!krP7P}{9Db;D*IQYeazDJeoT>)T?dR^_?^gQyO01mFKz=GqR47vL6kULzMJ{6on% zWo08u^jegPdNVzX6GUZ2LnvSojRs2W*qE5Ce^1dWxqoW1vdq7=n39}dUM@u|GPD5L z6<`Y(fwI0~VT9m`y#%~bXCTgNA7}uxfaSw3Okv5tYzb{yk4WW%fraZCj-hODY_V4B`lm%>*ylrs9DQe=MO0eDTPiNkCzTuWX5DxU0wcjk3w9i|%8 zQZh!4g;HjEzIv6t0@(z=AqukrHy`ch@lWpRYPeJ^!3ozMu25AYO&=d3D*TeAlWiI~g~W`Zdzpp8G6t&ImDGdQNC09Kp3@;0?to=;`z}T0 z)n7JM)+c%tWDU#C>)XEw;u5*J@BHX`HSi{^F;}K{wc)3pdoK_;p4Fz6>d1BZ|rp~_08rJ#WQb|5VrNCf;y{D36}Z_ejN65y(#KvQ)4 z3g5T=Cjuj_lN{t{YdoX_MD1VmvYJRyOo%CE&fN7hk;pdx2Z=E0eqn)wz z+;qZjJ~mPC%*`Mxni*t(JJWsT?xnFwb;HZz>j&PgnqeTJ-F|3&aGVdw=mEBYT4*ER zU-+r&wipu1%DW|#lY4%+m^U3XhhiymaBHI%7rF9LfH48@mC#sHW)&IYM=?>T>MUD- zDDyR#9ksu!KZSl!kNi$OJu*+s_W=!0Z0zi0ma`=&dBEZ?3(m=|G^ZFZq2lg=XpY8j)b^KiEyx3-7WFi9 zP1LPD+y7P2r-k-`;|GpbJeO1@-VL?U5*)_JS&U0!Y6_Z3JgR52$H8H4yp$%~x`*!# zbhs<~4sGb0NvWvDIniATypZsk5iG^H(rU;7h)mW&L(=ElTm(=X`s@3PLWCB@E$%~u#B}AaJ7IeUGA{AtIe_6~`ikf!3P|$JN;c7KI*Ujcg=Zp|B zkY{PJvH$f#B8s<$t`c!IwkZgi`aWz|DSeOY-f)(!pkh*?(YQM zS8Rxm`?p#aQFt;i_Xoq&f{u)tEA-HpBfo)jc!h zDz;@RlsARgrO%5r#;DSHN3BGJlg{^ZL6*l<{#O5^Iabfp9eEd*hpU;8!yVK*@D?2b z^Ct)JSd`GWONjEJTQ7aP`m!u zv1sP_w2chOCxFZ=_EBITXG0RSee(727Wadqw6yXi-R~s1KAPRG$>|*0Uhia%PAI*( za_=;#NE}!p?^BUOhg6(x-Bh>vtdWe+gbhB8RAiu^$d{sWA6N5`_=}bwu4?k)A{b}p+n!6=P4@flH$>&IkbFjID1lwV2EQ=ihQRpoEW4R6-HCjS z7J9MDh>UE-YsEnFJ7;*j);VMP?!7&i`Ucu8MxIn-i#ybh#Wp)bOiS99Jt=Mwr;Tdg zO!w7-;*v$loLI)UsXrv{7*cWWLkM!}aD=m{?<_=3^fs5tEatDLMduq0dE(H>g8C{G z`g_Vtd#CK0Ec2z>_+--am;Oj&RbLiFbI?akZMCH#MT_XKUw^IZ*_;bTRZ{hj?|vsk zSPhHmY(C7wI5MKNCT0qNS88d^>V|#$uVIT9f${^jsJOA_f$%iW1dMtd8> z%T}=Va*hXr&hCA{C29rQv!JtDGb_fscyjW79^M{LbE#1M+I%Ok8J`9XGVL75UXh6A z(`I2i+dPjfZBYDn)Vdkz4PB%pUaj(`tj9>$@ZuRB^!IFhwMaVf{h$gf+xpv_M>-Mq zwNSf&IyAmqD@bs8p!~DDZzBPcYsu!^00(-dX>to4RK0oZA1m?jeCjjaJkP+rKSIt9 z?4Wmtr_`AwurtdGfg!l|?(B2_%=2RAd|?u5bp-k`xtfS?1)rxr5NdBvX}gJZ5X7b* z$f}FVIJ0FGd?T3+N4?IN=Znc$d>9@heO!A*TZ4Q6&diZJ;#AOd#s)QgYNP{KDt_Ce zs)cbH^m;oUJJOAM8&;VI4G-P#N`0K&p;?&Nr^rxTn0j@!CIgI2$5oX^%?nmbs+q+B zekY5O6Neo|H2&3b6%FF4E(Zaf3JeK1J09(>gsO>GbXzRB8`5NQLs}lWe2!YGoR&cuC1)F?Vmof|JBpi*A5bLGDodJ zoQI~aE)ED>6HZjq4~Wu^7^_nJSKZu822By58s6Vov?O6*@MA0GSeW-s-#gxk-Md?Z zN@sJ`EfWtsQAlmVCzd~MpFCnM`sj)w;0}g2uMNbsWfubO zLL%I`IKROOVpW(q>HI2|Qlsxr>-?7&(7F@u)hn2Hv0Lf&6tm9+lg%^YPon1rotS%H zJN>Ux0ZYm>(jGr{Xx(GGz{vmZ3B?nPxkvtUm?(bRyFw8tp zRNE9J2-}A4PuzW!sbFHnhvN`nsmu7_UEvDVT*?Qgqek9$oh|n>>f9*Oo4;u4==K`S zlBQO_Z2EWX!w4AA8l~(YBE^<-Q0@6nLETP0oX5^aTTJQXDJXWW+rr+%$Hx~h9<`PR z`u~k-AQ;5W9$MR8TJkR{;sw$sZ1L1PU_k{IAjcOD4tuVzicfTszKPB!z@q4*P~*op zt_E;ZPnZOA=htaiwV<&S#nQ@CfC-M9(e@-Sr#Vtpk~>>k3p#o6q7P@ZYo_8#G&ov1 zO#6<~-8Bep;wg~-%C7A67~8)~rj=`Nd0^IhKoaWcuyTu)S&l8Crh}AU@V&2jL!>I% z7^ES{`{)0vyxHdm8g`@u;~O@tWwqkoxTw62+dm{me*1)->3epjw>4SSyYAK%a6{S5A1Niz^0h9oKN#&f7s8BjYNjBlE^ii z!j+)0=C7HB#c8?VD*h>+NE_bKreG2N(aYnNg1UOY8l+hCrVfElL-^ktO}a{~rFV%k z1;V`h?!P=5XX8n<)rTv!OUG{jIWqPwE6eW{h}(Pt(ra#mmkVvItwlTAwOODo++2Aq zlAuAcP`EuOcuc=&9Mdd`g&HQZDkmt9;(XKl>K_KN;;~aV<=PnW-s7WA@>z(gqkYHI zbp?ntBgggX$oB^VE1gGQ7)fwx80gIWdKxz!owTvRfBLsV4Tk!ro*b;i3P0?0G3#A% z1PETzx7&ih$A9l4fRoWjHaO(ly10MKo_~Bi6&qQ|N7&gP5u(`cI|i2`Ony$W=0agkz3oN!oqhTSnm&X00Fatb&l%{^dCl#AkMghAP+u z3E?pO4~cMAk1*GQTT$+ZI)KDydx)O5^j&5>AQ%3JW4ID#f-}8ovS^gjJqiu6E#qT{|rD@|FEx(pqWZ zcA;MeeOleFjFtm|$~LJm{hz}Bo7UMyW2MQ~B+SN^#VAn%El ze`lwpb<38-QUxhoWLzQsb|6zSI5KyTN_L_MXXBZGN zS)4v>QryW*{_a!9=|7C)8q0r)9P#xWLl4E5jN}q4HXq!;@=B8}9N!Bv5boDMU`T7g zjuBM$#XAW4fRr_7_K5fP&qcV=d3fPFI>rdTpJs3WmCN#EYFf916Ry#GB~oDJOl$MC zkaUZYaMH>zVx)i={lRMb!|>8;w|3mWphhi)8!l}5n-!#`JiL6a3CEl!Xz%PCAGqiA zukY4*L*p<2!eMCXo~`iKeGzsyjQlR;bx~OrkIKe}O3z>hc@yq%+OItcRMTontsFrQ z6?;>`7c~XtWsv60+=&Lc_bf7lQp})|-g^y`+*|JNzgRIHy$G(t>W5Pp4kzPIYvVP< zR`8T3mfl3uUj6)ec&iVX={o%v#ThEz_QR1EHxENnv!G6Cbq3EZsOkFUjuxA#-&N*h zP7bS&DS3I5OZddhkG)j=8%WUEn%&W{?VbesT*G7dEVDz=gV~>F25ZgggvP`>R>vYnlbOyM;&7h9fkGPfs zP@b6-=uMEq*_&$IVLZ_%1_xBe#l;2VS)!!p!?V}?&g`XV_kkW3kjh6vbzs?3^c9JX zj{r;w(CEM+kWPg3ng|0KpL??xPKuOZEKGcrtNq^zre3=9Zg7A}Sx#%^KUfq02>`1e z7sn#A9*FGun3N}J6 z1p$&UPv-H`J=1v4$#PfOcGd?EhWOV(Ryh&S=0`r47 zZhT`IqFoOg$L>@moDlRrmSnOW_tDnAv$*(k(>U^u9v*3^0-$C7du&kGEyw0+G+( z`xDo@!U}9B(2flo=&XPIt-L&DKdx@{H-Kv1K66!$kj>%-z=rI*)#FE7R6;w098xBbZ0?(j-vj*$8aP*9^Mbtt1%^&2Tpz8Mt(h% zw$Ffo^+cQy{<^saJ*`Co&wk#QE^U$u(v3F#9gBzuK!tq7A1ZCSo}}YUKs}dkku}Q? zedo9VCPb&0b4#rUBK7f4#V?!JsL{}5&B@cD9TwqpoGL*9*qPh@dmHdj3u`1abstd0 zR!5dW^KJJ~PE*KgH0l@r)XM7ao=v)>d_?5Y)wG7`;S9RPY_nMvq}o zgaOetLMe@yZwXAyhX1UVqwNXanYcad=6HJ1=i_Cl8(cvk=F|MrAe3}Cs4)8pp?sPfC+My3@qYuhHH}pS(#*`hVosoFyScd~W*>yPjo22Z7s~cUNgsOX zY%D4mBRykqkX0w2fhYxJ7M4W&p@3fa>wo=DyS&sPkRRvyO+^9V>vw@vG z#P?ZC*qu{p9&UOhG%~MhdZ--wwi=QeDDofbk{;3r_ZCBa`dN%L^u-I_P(|vNLGIvG zN`24ZD4}Y``?0`bnp<4^M2q*MCgVVq5?;=Xaf@zY+S3~;=Cud=^v{-Ba@Qr|@HwIO z&sSWZ&W!ZOSFIPEe5FbX`w!@NG?2p6ob|pxLM%upSg6^1g4^b9kQ+%f?Y}ygO3Q_| z`lbUP5B%O(?+4tdKIyUoIK6Ar zC17dn-n3)Vhm&7zw(Z>6y`VFUU`z)XLJ{P~a!c&>{lwf{N?QeOA0{2Odx>>np_Y@g zjvF8j%Mih$ z-keRVPcH9*(V!G$lj7}0h3*~g;@2Q(ThEQT2{DjTbu+fvb2IbE|@xSxgx9uwTKmXX8s43y#ky7Ex-yiRiuK@A#JV#-;j-st;7T7?dRUujQ@80Mh}XI9brUanesqEk3zKz zD1g`~GSB~Q{g%G3$8mZ^Jf@1OsznO@kvwiDwV!4E1xP=%jq}uoF}=)Da`WB+qZH|J z4#@B2voOb?-bKjC1tjV7Ta|>2$2wGx4V0r(&3ii3qRt$q=}t&qSzum$EAij&FhOV% zxW)T~G_Ic`z4MI%jJCEg5(tqs|v%?wr%ME4?8IU6*&%@}ZF|rju zC>qYm>%}&~s18b(0=4`#ld2fMx_*~%mY#UU?VvJf+j`1+J{8@K2b_D)L2h7T(qBzx z2nmj{Oo|b5YpeAl71}a{Rlk3f^vx^_CQG}p$&cIS!u|Qx&`M&Oo`s%v^z4J zj48esge3bFX{1YS0K2C`dQe~>U`J&>T}rT{j5g=g1t0^nHE5m?*$s&?zL}(0CKdy* zj9K6ElAcvb5=``iIJiy9y7gQGlQ=VbJt?iv@31dvpNn5sN~g+e!VWL(86A6i2m1{y{xGG z-eIl{wbzb#-oKBR#nb$MF_0@x$;Y)Z&8eOveCB)YcYJeFfEY3(dSw8U@U11)Rdp9)D(-i!qCF-tZ?9p;ME1?`$fe7H9ex|FEbs6;UAQZ zL;n;LK#cZ?5sAdqP*FswOYGzLM?pAXbgg=Ov6lJh)t?sPkygc+Iv4)2UCHpkCB}}T z(`HoV&8d(229e{35PcIKGiA73U17@4r483*ETx`q=IX9=yXz-Ut?D)DBvSkrhzWyy zkQ5^7Oe_k66j-vjYM6q5Fo9-kQibT`x}4ZNHsN&4Y|{u@%PcbM=)`>lFe zxI55hsBg}_ShN&;Gx~B1F6jM+H`p4M-#I?7X7)J$Weew7MUU4^xv^?~@uIQ(qWOYNRp*19K_!p0PiF0P5rK))P+z?QU6inA$fwl^_&^)w zxp15`ln3(#vZm}$(hnt!C0PV`e(Z`oU;mB>ft*xGY1qkOb|NgOMCS z=&eQ<*WBn|#Ltwb(Dre{Vs*XYF?f}UxpK2S!+Q=JtH?-VIP2ouI^z=tAA?e(J`7V# zrgG3g*1uo-*z0I8M)%>HAc0ijYI!TAFb33LphJrjWMtd?<0e=$T{G8{80@3_ z)vm}V~X}xavH}Db@ ztX+l|CE4N3W37x}FfxH;`&8b_6FZS(0_;pM88 zC0Sh6Fp!QYTkxC)#PBupsp1fxM>;ypJT!Z(raXiB^eNpJo&FDpm#=nu-^8)R%4WJv zs{d%Rm^~9SDR?dwlbjqnJ#9!2RD%QL?HYBlG!yr_In=a8s0EtZw?o)`|Nn%S`;dXu zglw@<{lmALJ;k`27a25=xAbYU?P7vhj=j>rRKzxamGJ%h{xl#qE87T$?cY+oc`BlR zGn{q3i}5E1u*v5fhM^pB6x0Gp=X;h|s6@8kZQ8EK3LNUZb2@W1Tmpa}1C~RNip$V# zvxS0;Wl>V*xyV>eCM1oMtoLX5JPyaD=i`V@#=5$?zK0p#K}<+B*!47>J~ermJ2e|y z4*J>)76X4VY+}4jySdn= len_materials: - f_mat = f.mat = 0 - material_users[f_mat] += 1 + if f.mat >= len_materials: + f.mat=0 + material_users[f.mat] += 1 - # mat_idx_subtract= 0 - # reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) - - reindex_mapping_ls = range(len_materials) - for i in range(len_materials-1, -1, -1): + mat_idx_subtract= 0 + reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) + i= len_materials + while i: + i-=1 + if material_users[i] == 0: - del reindex_mapping_ls[i] - del materials[i] + mat_idx_subtract+=1 + reindex_mapping[i]= mat_idx_subtract + materials.pop(i) rem_materials+=1 - reindex_mapping= {} - - for i, mat in enumerate(reindex_mapping_ls): - reindex_mapping[mat] = i - for f in me.faces: - f.mat= reindex_mapping[f.mat] + f.mat= f.mat - reindex_mapping[f.mat] me.materials= materials return rem_materials @@ -453,4 +449,4 @@ def main(): if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/release/scripts/object_find.py b/release/scripts/object_find.py index f12af07e3e4..0cfd6ad1d92 100644 --- a/release/scripts/object_find.py +++ b/release/scripts/object_find.py @@ -61,20 +61,8 @@ def get_object_images(ob): me.activeUVLayer = orig_uvlayer - - # Now get material images - for mat in me.materials: - if mat: - for mtex in mat.getTextures(): - if mtex: - tex = mtex.tex - i = tex.getImage() - if i: unique_images[i.name] = i - return unique_images.values() - - # Todo, support other object types, materials return [] @@ -130,7 +118,7 @@ def main(): def activate(ob, scn): bpy.data.scenes.active = scn scn.objects.selected = [] - scn.Layers = ob.Layers & (1<<20)-1 + scn.Layers = ob.Layers ob.sel = 1 def name_cmp(name_search, name_found): @@ -207,13 +195,11 @@ def main(): activate(ob, scn) return if NAME_TEXTURE: - for mtex in mat.getTextures(): - if mtex: - tex = mtex.tex - if tex: - if name_cmp(NAME_TEXTURE, tex.name): - activate(ob, scn) - return + for tex in mat.getTextures(): + if tex: + if name_cmp(NAME_MATERIAL, tex.name): + activate(ob, scn) + return Draw.PupMenu('No Objects Found') diff --git a/release/scripts/sysinfo.py b/release/scripts/sysinfo.py index 3a671e7221e..9f24885829c 100644 --- a/release/scripts/sysinfo.py +++ b/release/scripts/sysinfo.py @@ -94,8 +94,6 @@ output = Blender.Text.New(output_filename) output.write(header + "\n\n") -output.write("%s\n\n" % Blender.Get('buildinfo')) - output.write("Platform: %s\n========\n\n" % sys.platform) output.write("Python:\n======\n\n") diff --git a/source/Makefile b/source/Makefile index 99155206987..d06962cbe3f 100644 --- a/source/Makefile +++ b/source/Makefile @@ -100,13 +100,10 @@ COMLIB += $(OCGDIR)/blender/nodes_cmp/$(DEBUG_DIR)libnodes_cmp.a COMLIB += $(OCGDIR)/blender/nodes/$(DEBUG_DIR)libnodes.a COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a -COMLIB += $(NAN_IKSOLVER)/lib/libiksolver.a COMLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a COMLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a COMLIB += $(NAN_JPEG)/lib/libjpeg.a -COMLIB += $(OCGDIR)/blender/gpu/$(DEBUG_DIR)libgpu.a -COMLIB += $(NAN_GLEW)/lib/libglew.a ifneq ($(NAN_NO_KETSJI),true) COMLIB += $(OCGDIR)/gameengine/bloutines/$(DEBUG_DIR)libbloutines.a @@ -160,6 +157,7 @@ COMLIB += $(NAN_BMFONT)/lib/$(DEBUG_DIR)libbmfont.a COMLIB += $(NAN_PNG)/lib/libpng.a COMLIB += $(OCGDIR)/blender/yafray/$(DEBUG_DIR)libyafrayexport.a COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a +COMLIB += $(NAN_GLEW)/lib/libglew.a ifeq ($(WITH_QUICKTIME), true) COMLIB += $(OCGDIR)/blender/blenderqt/$(DEBUG_DIR)libblenderqt.a @@ -228,7 +226,8 @@ ifeq ($(WITH_OPENEXR), true) COMLIB += $(NAN_OPENEXR_LIBS) endif -PULIB = $(NAN_MOTO)/lib/libmoto.a +PULIB = $(NAN_IKSOLVER)/lib/libiksolver.a +PULIB += $(NAN_MOTO)/lib/libmoto.a PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a @@ -242,7 +241,6 @@ endif SPLIB1 = $(OCGDIR)/gameengine/GamePlayer/ghost/$(DEBUG_DIR)libghost.a SPLIB1 += $(OCGDIR)/gameengine/GamePlayer/common/$(DEBUG_DIR)libcommon.a -SPLIB1 += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a SPLIB1 += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a SPLIB1 += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a @@ -252,7 +250,6 @@ SPLIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a # but somehow it consistently fails to resolve these symbols... or # can I just not check them? nm claims they aren't... SPLIB += $(OCGDIR)/blender/blenkernel/blenkernel_blc/$(DEBUG_DIR)libblenkernel_blc.a -SPLIB += $(OCGDIR)/blender/python/$(DEBUG_DIR)libpython.a # These three need to be explicitly mentioned on the cl, because # if they are offered as a lib, they are optimized away. (nzc) diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index a21eadf15fa..966bf5f7be4 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -24,7 +24,7 @@ # # ***** END GPL LICENSE BLOCK ***** -SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon gpu makesdna python radiosity readblenfile render src yafray) +SUBDIRS(avi nodes blenkernel blenlib blenloader blenpluginapi imbuf imbuf/intern/cineon makesdna python radiosity readblenfile render src yafray) IF(WITH_INTERNATIONAL) SUBDIRS(ftfont) diff --git a/source/blender/Makefile b/source/blender/Makefile index 52abd2cdddb..937512f34bd 100644 --- a/source/blender/Makefile +++ b/source/blender/Makefile @@ -33,7 +33,7 @@ include nan_definitions.mk DIRS = blenloader readblenfile DIRS += avi imbuf render radiosity blenlib blenkernel blenpluginapi DIRS += makesdna src yafray -DIRS += python nodes gpu +DIRS += python nodes ifeq ($(WITH_FREETYPE2), true) DIRS += ftfont diff --git a/source/blender/SConscript b/source/blender/SConscript index 25745c0e51a..56a661238f8 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -7,7 +7,6 @@ SConscript(['avi/SConscript', 'blenlib/SConscript', 'blenloader/SConscript', 'blenpluginapi/SConscript', - 'gpu/SConscript', 'imbuf/SConscript', 'imbuf/intern/cineon/SConscript', 'makesdna/SConscript', diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index fe25ada3962..4da7da46cc8 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -56,7 +56,6 @@ struct EditMesh; struct ModifierData; struct MCol; struct ColorBand; -struct GPUVertexAttribs; /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 @@ -201,8 +200,7 @@ struct DerivedMesh { * * Also called for *final* editmode DerivedMeshes */ - void (*drawFacesSolid)(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs)); + void (*drawFacesSolid)(DerivedMesh *dm, int (*setMaterial)(int)); /* Draw all faces * o If useTwoSided, draw front and back using col arrays @@ -219,13 +217,6 @@ struct DerivedMesh { int (*setDrawOptions)(struct MTFace *tface, struct MCol *mcol, int matnr)); - /* Draw all faces with GLSL materials - * o setMaterial is called for every different material nr - * o Only if setMaterial returns true - */ - void (*drawFacesGLSL)(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs)); - /* Draw mapped faces (no color, or texture) * o Only if !setDrawOptions or * setDrawOptions(userData, mapped-face-index, drawSmooth_r) @@ -252,15 +243,6 @@ struct DerivedMesh { int index), void *userData); - /* Draw mapped faces with GLSL materials - * o setMaterial is called for every different material nr - * o setDrawOptions is called for every face - * o Only if setMaterial and setDrawOptions return true - */ - void (*drawMappedFacesGLSL)(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs), - int (*setDrawOptions)(void *userData, int index), void *userData); - /* Draw mapped edges as lines * o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge) * returns true @@ -457,35 +439,6 @@ void weight_to_rgb(float input, float *fr, float *fg, float *fb); /* determines required DerivedMesh data according to view and edit modes */ CustomDataMask get_viewedit_datamask(); -/* convert layers requested by a GLSL material to actually available layers in - * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */ -typedef struct DMVertexAttribs { - struct { - struct MTFace *array; - int emOffset, glIndex; - } tface[MAX_MTFACE]; - - struct { - struct MCol *array; - int emOffset, glIndex; - } mcol[MAX_MCOL]; - - struct { - float (*array)[3]; - int emOffset, glIndex; - } tang; - - struct { - float (*array)[3]; - int emOffset, glIndex; - } orco; - - int tottface, totmcol, tottang, totorco; -} DMVertexAttribs; - -void DM_vertex_attributes_from_gpu(DerivedMesh *dm, - struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs); - void DM_add_tangent_layer(DerivedMesh *dm); #endif diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 4a13fa31f6c..716eac81b55 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -159,7 +159,7 @@ float get_action_frame(struct Object *ob, float cframe); /* map strip time to global time (frame nr) */ float get_action_frame_inv(struct Object *ob, float cframe); /* builds a list of NlaIpoChannel with ipo values to write in datablock */ -void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, const char *name, float ctime); +void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, char *name, float ctime); /* write values returned by extract_ipochannels_from_action, returns the number of value written */ int execute_ipochannels(ListBase *lb); diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 8dee9a27f49..3e45749c26a 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -115,6 +115,10 @@ void free_editArmature(void); void docenter_new(void); int saveover(char *str); +/* image.c */ +#include "DNA_image_types.h" +void free_realtime_image(Image *ima); // has to become a callback, opengl stuff + /* ipo.c */ void copy_view3d_lock(short val); // was a hack, to make scene layer ipo's possible diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 0591937ea4c..e403fc33e06 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 247 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 1 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 555b467b1d6..e78882220a9 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -57,7 +57,6 @@ void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf); void curvemapping_premultiply(struct CurveMapping *cumap, int restore); int curvemapping_RGBA_does_something(struct CurveMapping *cumap); void curvemapping_initialize(struct CurveMapping *cumap); -void curvemapping_table_RGBA(struct CurveMapping *cumap, float **array, int *size); #endif diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 1cc336db69e..8c9634cba06 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -218,15 +218,8 @@ typedef struct Global { #define G_FILE_NO_UI (1 << 10) #define G_FILE_GAME_TO_IPO (1 << 11) #define G_FILE_GAME_MAT (1 << 12) -#define G_FILE_DISPLAY_LISTS (1 << 13) +#define G_FILE_DIAPLAY_LISTS (1 << 13) #define G_FILE_SHOW_PHYSICS (1 << 14) -#define G_FILE_GAME_MAT_GLSL (1 << 15) -#define G_FILE_GLSL_NO_LIGHTS (1 << 16) -#define G_FILE_GLSL_NO_SHADERS (1 << 17) -#define G_FILE_GLSL_NO_SHADOWS (1 << 18) -#define G_FILE_GLSL_NO_RAMPS (1 << 19) -#define G_FILE_GLSL_NO_NODES (1 << 20) -#define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 2ca4b3aa39a..d4ae76e8984 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -68,6 +68,7 @@ void mball_to_mesh(struct ListBase *lb, struct Mesh *me); void nurbs_to_mesh(struct Object *ob); void free_dverts(struct MDeformVert *dvert, int totvert); void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */ +int update_realtime_texture(struct MTFace *tface, double time); void mesh_delete_material_index(struct Mesh *me, int index); void mesh_set_smooth_flag(struct Object *meshOb, int enableSmooth); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 01c54663c6d..b3b68a9b3ff 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -47,9 +47,6 @@ struct rctf; struct ListBase; struct RenderData; struct Scene; -struct GPUMaterial; -struct GPUNode; -struct GPUNodeStack; #define SOCK_IN 1 #define SOCK_OUT 2 @@ -94,9 +91,6 @@ typedef struct bNodeType { void *pynode; /* holds pointer to python script */ void *pydict; /* holds pointer to python script dictionary (scope)*/ - /* gpu */ - int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out); - } bNodeType; /* node->exec, now in use for composites (#define for break is same as ready yes) */ @@ -258,8 +252,6 @@ void nodeShaderSynchronizeID(struct bNode *node, int copyto); extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *)); -void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); - /* ************** COMPOSITE NODES *************** */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index ea1dc7407db..944a9081679 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -302,7 +302,6 @@ int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int #define PSYS_RESET_ALL 1 #define PSYS_RESET_DEPSGRAPH 2 #define PSYS_RESET_CHILDREN 3 -#define PSYS_RESET_CACHE_MISS 4 /* ParticleEffectorCache->type */ #define PSYS_EC_EFFECTOR 1 diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h deleted file mode 100644 index d58b8f58bf5..00000000000 --- a/source/blender/blenkernel/BKE_suggestions.h +++ /dev/null @@ -1,93 +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) 2008, Blender Foundation - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef BKE_SUGGESTIONS_H -#define BKE_SUGGESTIONS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* **************************************************************************** -Suggestions should be added in sorted order although a linear sorting method is -implemented. The list is then divided up based on the prefix provided by -update_suggestions: - -Example: - Prefix: ab - aaa <-- first - aab - aba <-- firstmatch - abb <-- lastmatch - baa - bab <-- last -**************************************************************************** */ - -struct Text; - -typedef struct SuggItem { - struct SuggItem *prev, *next; - char *name; - char type; -} SuggItem; - -typedef struct SuggList { - SuggItem *first, *last; - SuggItem *firstmatch, *lastmatch; - SuggItem *selected; - int top; -} SuggList; - -/* Free all text tool memory */ -void free_texttools(); - -/* Used to identify which Text object the current tools should appear against */ -void texttool_text_set_active(Text *text); -void texttool_text_clear(); -short texttool_text_is_active(Text *text); - -/* Suggestions */ -void texttool_suggest_add(const char *name, char type); -void texttool_suggest_prefix(const char *prefix); -void texttool_suggest_clear(); -SuggItem *texttool_suggest_first(); -SuggItem *texttool_suggest_last(); -void texttool_suggest_select(SuggItem *sel); -SuggItem *texttool_suggest_selected(); -int *texttool_suggest_top(); - -/* Documentation */ -void texttool_docs_show(const char *docs); -char *texttool_docs_get(); -void texttool_docs_clear(); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 002c804f17f..6f891ab4887 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -52,24 +52,20 @@ void txt_free_cut_buffer (void); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); void txt_order_cursors (struct Text *text); -int txt_find_string (struct Text *text, char *findstr, int wrap); +int txt_find_string (struct Text *text, char *findstr); int txt_has_sel (struct Text *text); int txt_get_span (struct TextLine *from, struct TextLine *to); void txt_move_up (struct Text *text, short sel); void txt_move_down (struct Text *text, short sel); void txt_move_left (struct Text *text, short sel); void txt_move_right (struct Text *text, short sel); -void txt_jump_left (struct Text *text, short sel); -void txt_jump_right (struct Text *text, short sel); void txt_move_bof (struct Text *text, short sel); void txt_move_eof (struct Text *text, short sel); void txt_move_bol (struct Text *text, short sel); void txt_move_eol (struct Text *text, short sel); void txt_move_toline (struct Text *text, unsigned int line, short sel); -void txt_move_to (struct Text *text, unsigned int line, unsigned int ch, short sel); void txt_pop_sel (struct Text *text); void txt_delete_char (struct Text *text); -void txt_delete_word (struct Text *text); void txt_copy_sel (struct Text *text); void txt_sel_all (struct Text *text); void txt_sel_line (struct Text *text); @@ -84,10 +80,8 @@ void txt_do_undo (struct Text *text); void txt_do_redo (struct Text *text); void txt_split_curline (struct Text *text); void txt_backspace_char (struct Text *text); -void txt_backspace_word (struct Text *text); int txt_add_char (struct Text *text, char add); -int txt_replace_char (struct Text *text, char add); -void find_and_replace (struct SpaceText *st, short mode); +void txt_find_panel (struct SpaceText *st, int again); void run_python_script (struct SpaceText *st); int jumptoline_interactive (struct SpaceText *st); void txt_export_to_object (struct Text *text); @@ -100,17 +94,6 @@ int setcurr_tab (struct Text *text); void convert_tabs (struct SpaceText *st, int tab); void txt_copy_clipboard (struct Text *text); void txt_paste_clipboard (struct Text *text); - -void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, char color[4], int group, int flags); -short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -short txt_clear_markers (struct Text *text, int group, int flags); -struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); -struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); -struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker); -struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker); -struct TextMarker *txt_prev_marker_color (struct Text *text, struct TextMarker *marker); -struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker *marker); - /* Undo opcodes */ /* Simple main cursor movement */ @@ -152,14 +135,6 @@ struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker * #define UNDO_COMMENT 034 #define UNDO_UNCOMMENT 035 -/* Find and replace flags */ -#define TXT_FIND_WRAP 0x01 -#define TXT_FIND_ALLTEXTS 0x02 - -/* Marker flags */ -#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */ -#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */ - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index cfcae3c44bc..c162a04e055 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -53,7 +53,6 @@ void free_plugin_tex(struct PluginTex *pit); void init_colorband(struct ColorBand *coba, int rangetype); struct ColorBand *add_colorband(int rangetype); int do_colorband(struct ColorBand *coba, float in, float out[4]); -void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size); void default_tex(struct Tex *tex); struct Tex *add_texture(char *name); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index d647a74c6e2..f389521ffa0 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -55,8 +55,6 @@ #define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) #define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) #define ELEM9(a, b, c, d, e, f, g, h, i, j) ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) ) -#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) ) -#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) ) /* shift around elements */ #define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0345711c9c3..9088b410e27 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -32,7 +32,7 @@ SET(INC ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern ../../../intern/iksolver/extern ../blenloader ../quicktime ../../../intern/bmfont ../../../extern/bullet2/src - ../nodes ../../../extern/glew/include ../gpu + ../nodes ${SDL_INC} ${ZLIB_INC} ${PYTHON_INC} diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index db67251f44e..1bb98239a68 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -10,7 +10,6 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime' incs += ' #/extern/bullet2/src' incs += ' #/intern/bmfont' incs += ' #/intern/opennl/extern' -incs += ' ../gpu #/extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index f4beca262d7..561d8d7c2a6 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -60,7 +60,7 @@ struct EditFace; char *getIpoCurveName( struct IpoCurve * icu ); void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f); +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e); void elbeemDebugOut(char *msg); void fluidsimSettingsFree(struct FluidsimSettings* sb); void fluidsimSettingsCopy(struct FluidsimSettings* sb); @@ -88,7 +88,7 @@ void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast) } -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f) +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e) { return 0; } @@ -176,6 +176,10 @@ void free_editMesh(struct EditMesh *em){} void docenter_new(void){} int saveover(char *str){ return 0;} +/* image.c */ +#include "DNA_image_types.h" +void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff + /* ipo.c */ void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible @@ -216,6 +220,30 @@ struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2) { retur void countall(void) {} + +/* IKsolver stubs */ +#include "IK_solver.h" + +IK_Segment *IK_CreateSegment(int flag) { return 0; } +void IK_FreeSegment(IK_Segment *seg) {} + +void IK_SetParent(IK_Segment *seg, IK_Segment *parent) {} +void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length) {} +void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) {} +void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) {}; +void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lower, float upper) {}; +void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) {}; + +IK_Solver *IK_CreateSolver(IK_Segment *root) { return 0; } +void IK_FreeSolver(IK_Solver *solver) {}; + +void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) {} +void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) {} +void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle) {} +float IK_SolverGetPoleAngle(IK_Solver *solver) { return 0.0f; } + +int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) { return 0; } + /* exotic.c */ int BPY_call_importloader(char *name) { diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index a5eb1f258f1..8bbda2da976 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -89,10 +89,6 @@ #include "BIF_gl.h" #include "BIF_glutil.h" -#include "GPU_draw.h" -#include "GPU_extensions.h" -#include "GPU_material.h" - // headers for fluidsim bobj meshes #include #include "LBM_fluidsim.h" @@ -420,8 +416,6 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices) CustomData_swap(&dm->faceData, index, corner_indices); } -/// - static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -905,162 +899,6 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } -static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs), - int (*setDrawOptions)(void *userData, int index), void *userData) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - float (*vertexCos)[3]= emdm->vertexCos; - float (*vertexNos)[3]= emdm->vertexNos; - EditVert *eve; - EditFace *efa; - DMVertexAttribs attribs; - GPUVertexAttribs gattribs; - MTFace *tf; - int transp, new_transp, orig_transp, tfoffset; - int i, b, matnr, new_matnr, dodraw, layer; - - dodraw = 0; - matnr = -1; - - transp = GPU_get_material_blend_mode(); - orig_transp = transp; - layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); - tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; - - memset(&attribs, 0, sizeof(attribs)); - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - glShadeModel(GL_SMOOTH); - - for (i=0,eve=em->verts.first; eve; eve= eve->next) - eve->tmp.l = (long) i++; - -#define PASSATTRIB(efa, eve, vert) { \ - if(attribs.totorco) { \ - float *orco = attribs.orco.array[eve->tmp.l]; \ - glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ - } \ - for(b = 0; b < attribs.tottface; b++) { \ - MTFace *tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[i*4 + vert]; \ - glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ - } \ -} - - for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { - int drawSmooth= (efa->flag & ME_SMOOTH); - - if(setDrawOptions && !setDrawOptions(userData, i)) - continue; - - new_matnr = efa->mat_nr + 1; - if(new_matnr != matnr) { - dodraw = setMaterial(matnr = new_matnr, &gattribs); - if(dodraw) - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - if(tfoffset != -1) { - tf = (MTFace*)((char*)efa->data)+tfoffset; - new_transp = tf->transp; - - if(new_transp != transp) { - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - } - } - - if(dodraw) { - glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); - if (!drawSmooth) { - if(vertexCos) glNormal3fv(emdm->faceNos[i]); - else glNormal3fv(efa->n); - - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - else glVertex3fv(efa->v1->co); - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - else glVertex3fv(efa->v2->co); - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - else glVertex3fv(efa->v3->co); - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - else glVertex3fv(efa->v4->co); - } - } else { - PASSATTRIB(efa, efa->v1, 0); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); - } - else { - glNormal3fv(efa->v1->no); - glVertex3fv(efa->v1->co); - } - - PASSATTRIB(efa, efa->v2, 1); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); - } - else { - glNormal3fv(efa->v2->no); - glVertex3fv(efa->v2->co); - } - - PASSATTRIB(efa, efa->v3, 2); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); - } - else { - glNormal3fv(efa->v3->no); - glVertex3fv(efa->v3->co); - } - - if(efa->v4) { - PASSATTRIB(efa, efa->v4, 3); - if(vertexCos) { - glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); - glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); - } - else { - glNormal3fv(efa->v4->no); - glVertex3fv(efa->v4->co); - } - } - } - glEnd(); - } - } -} - -static void emDM_drawFacesGLSL(DerivedMesh *dm, - int (*setMaterial)(int, void *attribs)) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1266,43 +1104,6 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) } } -static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) -{ - EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; - EditMesh *em= emdm->em; - EditFace *efa; - char *data, *emdata; - void *datalayer; - int index, offset, size; - - datalayer = DM_get_face_data_layer(dm, type); - if(datalayer) - return datalayer; - - /* layers are store per face for editmesh, we convert to a temporary - * data layer array in the derivedmesh when these are requested */ - if(type == CD_MTFACE || type == CD_MCOL) { - index = CustomData_get_layer_index(&em->fdata, type); - - if(index != -1) { - offset = em->fdata.layers[index].offset; - size = CustomData_sizeof(type); - - DM_add_face_layer(dm, type, CD_CALLOC, NULL); - index = CustomData_get_layer_index(&dm->faceData, type); - dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; - - data = datalayer = DM_get_face_data_layer(dm, type); - for(efa=em->faces.first; efa; efa=efa->next, data+=size) { - emdata = CustomData_em_get(&em->fdata, efa->data, type); - memcpy(data, emdata, size); - } - } - } - - return datalayer; -} - static void emDM_release(DerivedMesh *dm) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1338,7 +1139,6 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, emdm->dm.copyVertArray = emDM_copyVertArray; emdm->dm.copyEdgeArray = emDM_copyEdgeArray; emdm->dm.copyFaceArray = emDM_copyFaceArray; - emdm->dm.getFaceDataArray = emDM_getFaceDataArray; emdm->dm.foreachMappedVert = emDM_foreachMappedVert; emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; @@ -1349,9 +1149,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; emdm->dm.drawMappedFaces = emDM_drawMappedFaces; emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; - emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; emdm->dm.drawFacesTex = emDM_drawFacesTex; - emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; emdm->dm.drawUVEdges = emDM_drawUVEdges; emdm->dm.release = emDM_release; @@ -1781,7 +1579,7 @@ static void vDM_drawUVEdges(DerivedMesh *dm) } /* draw all VerseFaces */ -static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) +static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { VDerivedMesh *vdm = (VDerivedMesh*)dm; struct VerseFace *vface; @@ -1881,8 +1679,6 @@ static void vDM_drawMappedFacesTex( int (*setDrawParams)(void *userData, int index), void *userData) { - /* not supported yet */ - vDM_drawFacesTex(dm, NULL); } /**/ @@ -2024,23 +1820,19 @@ CustomDataMask get_viewedit_datamask() ScrArea *sa; /* check if we need tfaces & mcols due to face select or texture paint */ - if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) + if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) { mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - - /* check if we need tfaces & mcols due to view mode */ - for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { - if(sa->spacetype == SPACE_VIEW3D) { - View3D *view = sa->spacedata.first; - if(view->drawtype == OB_SHADED) { - /* this includes normals for mesh_create_shadedColors */ - mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; - } - if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { - mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - - if((G.fileflags & G_FILE_GAME_MAT) && - (G.fileflags & G_FILE_GAME_MAT_GLSL)) { - mask |= CD_MASK_ORCO; + } else { + /* check if we need tfaces & mcols due to view mode */ + for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { + if(sa->spacetype == SPACE_VIEW3D) { + View3D *view = sa->spacedata.first; + if(view->drawtype == OB_SHADED) { + /* this includes normals for mesh_create_shadedColors */ + mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; + } + if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { + mask |= CD_MASK_MTFACE | CD_MASK_MCOL; } } } @@ -2053,41 +1845,13 @@ CustomDataMask get_viewedit_datamask() return mask; } -static float *get_editmesh_orco_verts(EditMesh *em) -{ - EditVert *eve; - float *orco; - int a, totvert; - - /* these may not really be the orco's, but it's only for preview. - * could be solver better once, but isn't simple */ - - totvert= 0; - for(eve=em->verts.first; eve; eve=eve->next) - totvert++; - - orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco"); - - for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3) - VECCOPY(orco+a, eve->co); - - return orco; -} - -static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em) +static DerivedMesh *create_orco_dm(Object *ob, Mesh *me) { DerivedMesh *dm; float (*orco)[3]; - if(em) { - dm= CDDM_from_editmesh(em, me); - orco= (float(*)[3])get_editmesh_orco_verts(em); - } - else { - dm= CDDM_from_mesh(me, ob); - orco= (float(*)[3])get_mesh_orco_verts(ob); - } - + dm= CDDM_from_mesh(me, ob); + orco= (float(*)[3])get_mesh_orco_verts(ob); CDDM_apply_vert_coords(dm, orco); CDDM_calc_normals(dm); MEM_freeN(orco); @@ -2095,7 +1859,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em) return dm; } -static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm) +static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) { float (*orco)[3], (*layerorco)[3]; int totvert; @@ -2110,10 +1874,8 @@ static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh * else dm->getVertCos(dm, orco); } - else { - if(em) orco= (float(*)[3])get_editmesh_orco_verts(em); - else orco= (float(*)[3])get_mesh_orco_verts(ob); - } + else + orco= (float(*)[3])get_mesh_orco_verts(ob); transform_mesh_orco_verts(ob->data, orco, totvert, 0); @@ -2259,7 +2021,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if(dm && mti->requiredDataMask) { mask = mti->requiredDataMask(md); if(mask & CD_MASK_ORCO) - add_orco_dm(ob, NULL, dm, orcodm); + add_orco_dm(ob, dm, orcodm); } /* How to apply modifier depends on (a) what we already have as @@ -2312,7 +2074,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], mask= (CustomDataMask)curr->link; if(mask & CD_MASK_ORCO) { if(!orcodm) - orcodm= create_orco_dm(ob, me, NULL); + orcodm= create_orco_dm(ob, me); mask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, mask); @@ -2389,10 +2151,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], /* add an orco layer if needed */ if(dataMask & CD_MASK_ORCO) { - add_orco_dm(ob, NULL, finaldm, orcodm); + add_orco_dm(ob, finaldm, orcodm); if(deform_r && *deform_r) - add_orco_dm(ob, NULL, *deform_r, NULL); + add_orco_dm(ob, *deform_r, NULL); } *final_r = finaldm; @@ -2448,8 +2210,7 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, EditMesh *em = G.editMesh; ModifierData *md; float (*deformedVerts)[3] = NULL; - CustomDataMask mask; - DerivedMesh *dm, *orcodm = NULL; + DerivedMesh *dm; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL); LinkNode *datamasks, *curr; @@ -2474,13 +2235,6 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, if(!editmesh_modifier_is_enabled(md, dm)) continue; - /* add an orco layer if needed by this modifier */ - if(dm && mti->requiredDataMask) { - mask = mti->requiredDataMask(md); - if(mask & CD_MASK_ORCO) - add_orco_dm(ob, em, dm, orcodm); - } - /* How to apply modifier depends on (a) what we already have as * a result of previous modifiers (could be a DerivedMesh or just * deformed vertices) and (b) what type the modifier is. @@ -2531,23 +2285,6 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, } } - /* create an orco derivedmesh in parallel */ - mask= (CustomDataMask)curr->link; - if(mask & CD_MASK_ORCO) { - if(!orcodm) - orcodm= create_orco_dm(ob, ob->data, em); - - mask &= ~CD_MASK_ORCO; - DM_set_only_copy(orcodm, mask); - ndm = mti->applyModifierEM(md, ob, em, orcodm); - - if(ndm) { - /* if the modifier returned a new dm, release the old one */ - if(orcodm && orcodm != ndm) orcodm->release(orcodm); - orcodm = ndm; - } - } - /* set the DerivedMesh to only copy needed data */ DM_set_only_copy(dm, (CustomDataMask)curr->link); @@ -2606,13 +2343,6 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, deformedVerts = NULL; } - /* add an orco layer if needed */ - if(dataMask & CD_MASK_ORCO) - add_orco_dm(ob, em, *final_r, orcodm); - - if(orcodm) - orcodm->release(orcodm); - if(deformedVerts) MEM_freeN(deformedVerts); } @@ -2908,7 +2638,7 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c old->release(old); if(dataMask & CD_MASK_ORCO) - add_orco_dm(ob, NULL, *dm, NULL); + add_orco_dm(ob, *dm, NULL); /* Restore the original verts */ me->mr->newlvl= BLI_countlist(&me->mr->levels); @@ -3123,8 +2853,6 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo return numleft; } -/* ******************* GLSL ******************** */ - void DM_add_tangent_layer(DerivedMesh *dm) { /* mesh vars */ @@ -3245,91 +2973,6 @@ void DM_add_tangent_layer(DerivedMesh *dm) MEM_freeN(vtangents); } -void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs) -{ - CustomData *vdata, *fdata, *tfdata = NULL; - int a, b, layer; - - /* From the layers requested by the GLSL shader, figure out which ones are - * actually available for this derivedmesh, and retrieve the pointers */ - - memset(attribs, 0, sizeof(DMVertexAttribs)); - - vdata = &dm->vertData; - fdata = &dm->faceData; - - /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we - * can use offsets instead */ - if(dm->release == emDM_release) - tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata; - else - tfdata = fdata; - - /* add a tangent layer if necessary */ - for(b = 0; b < gattribs->totlayer; b++) - if(gattribs->layer[b].type == CD_TANGENT) - if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1) - DM_add_tangent_layer(dm); - - for(b = 0; b < gattribs->totlayer; b++) { - if(gattribs->layer[b].type == CD_MTFACE) { - /* uv coordinates */ - if(gattribs->layer[b].name[0]) - layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE, - gattribs->layer[b].name); - else - layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE); - - if(layer != -1) { - a = attribs->tottface++; - - attribs->tface[a].array = tfdata->layers[layer].data; - attribs->tface[a].emOffset = tfdata->layers[layer].offset; - attribs->tface[a].glIndex = gattribs->layer[b].glindex; - } - } - else if(gattribs->layer[b].type == CD_MCOL) { - /* vertex colors */ - if(gattribs->layer[b].name[0]) - layer = CustomData_get_named_layer_index(tfdata, CD_MCOL, - gattribs->layer[b].name); - else - layer = CustomData_get_active_layer_index(tfdata, CD_MCOL); - - if(layer != -1) { - a = attribs->totmcol++; - - attribs->mcol[a].array = tfdata->layers[layer].data; - attribs->mcol[a].emOffset = tfdata->layers[layer].offset; - attribs->mcol[a].glIndex = gattribs->layer[b].glindex; - } - } - else if(gattribs->layer[b].type == CD_TANGENT) { - /* tangents */ - layer = CustomData_get_layer_index(fdata, CD_TANGENT); - - if(layer != -1) { - attribs->tottang = 1; - - attribs->tang.array = fdata->layers[layer].data; - attribs->tang.emOffset = fdata->layers[layer].offset; - attribs->tang.glIndex = gattribs->layer[b].glindex; - } - } - else if(gattribs->layer[b].type == CD_ORCO) { - /* original coordinates */ - layer = CustomData_get_layer_index(vdata, CD_ORCO); - - if(layer != -1) { - attribs->totorco = 1; - - attribs->orco.array = vdata->layers[layer].data; - attribs->orco.emOffset = vdata->layers[layer].offset; - attribs->orco.glIndex = gattribs->layer[b].glindex; - } - } - } -} /* ************************* fluidsim bobj file handling **************************** */ diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 8921ea5d3b7..74c6c551a83 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -36,7 +36,6 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) # OpenGL and Python -CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) @@ -75,9 +74,6 @@ CPPFLAGS += -I$(NAN_ZLIB)/include #path to nodes CPPFLAGS += -I../../nodes -#path to gpu -CPPFLAGS += -I../../gpu - # path to our own external headerfiles CPPFLAGS += -I.. diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 043ede5987a..5b96bf11056 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -347,8 +347,6 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); QUATCOPY(pchan->quat, chan->quat); - Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat); - Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat); pchan->flag= chan->flag; con= chan->constraints.first; @@ -862,7 +860,7 @@ typedef struct NlaIpoChannel { int type; } NlaIpoChannel; -void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) +void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime) { bActionChannel *achan= get_action_channel(act, name); IpoCurve *icu; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index ceb0e132ff9..1592c3e5504 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -303,7 +303,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4], tmat[4][4]; + float mat[4][4]; if(ob->dup_group==NULL) return; group= ob->dup_group; @@ -320,15 +320,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if(go->ob!=ob) { - /* Group Dupli Offset, should apply after everything else */ - if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) { - Mat4CpyMat4(tmat, go->ob->obmat); - VecSubf(tmat[3], tmat[3], group->dupli_ofs); - Mat4MulMat4(mat, tmat, ob->obmat); - } else { - Mat4MulMat4(mat, go->ob->obmat, ob->obmat); - } - + Mat4MulMat4(mat, go->ob->obmat, ob->obmat); dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); dob->no_draw= (dob->origlay & group->layer)==0; @@ -783,10 +775,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ hair= (totchild == 0 || psys->childcache) && psys->pathcache; if(!hair) return; - - /* we use cache, update totchild according to cached data */ - totchild = psys->totchildcache; - totpart = psys->totcached; } psys->lattice = psys_get_lattice(par, psys); @@ -869,8 +857,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ } VECCOPY(pamat[3], cache->co); - pamat[3][3]= 1.0f; - } else if(step_nbr) { /* other keys */ @@ -1073,8 +1059,7 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, } } -/* Returns a list of DupliObject - * note; group dupli's already set transform matrix. see note in group_duplilist() */ +/* note; group dupli's already set transform matrix. see note in group_duplilist() */ ListBase *object_duplilist(Scene *sce, Object *ob) { ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 720ed0513ed..fb7d59c137a 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1690,7 +1690,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) were executed & assigned. Now as last we do an IK pass */ static void execute_posetree(Object *ob, PoseTree *tree) { - float R_parmat[3][3], identity[3][3]; + float R_parmat[3][3]; float iR_parmat[3][3]; float R_bonemat[3][3]; float goalrot[3][3], goalpos[3]; @@ -1699,8 +1699,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) float irest_basis[3][3], full_basis[3][3]; float end_pose[4][4], world_pose[4][4]; float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - float resultinf=0.0f; - int a, flag, hasstretch=0, resultblend=0; + int a, flag, hasstretch=0; bPoseChannel *pchan; IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; @@ -1845,12 +1844,6 @@ static void execute_posetree(Object *ob, PoseTree *tree) Mat4MulMat4(goal, rootmat, goalinv); VECCOPY(polepos, goal[3]); poleconstrain= 1; - - /* for pole targets, we blend the result of the ik solver - * instead of the target position, otherwise we can't get - * a smooth transition */ - resultblend= 1; - resultinf= target->con->enforce; if(data->flag & CONSTRAINT_IK_GETANGLE) { poleangledata= data; @@ -1860,7 +1853,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) } /* do we need blending? */ - if (!resultblend && target->con->enforce!=1.0) { + if (target->con->enforce!=1.0) { float q1[4], q2[4], q[4]; float fac= target->con->enforce; float mfac= 1.0-fac; @@ -1910,7 +1903,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); if(hasstretch) ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - + for(a=0; atotchannel; a++) { IK_GetBasisChange(iktree[a], tree->basis_change[a]); @@ -1938,12 +1931,6 @@ static void execute_posetree(Object *ob, PoseTree *tree) VecMulf(tree->basis_change[a][1], stretch); VecMulf(tree->basis_change[a][2], stretch); } - - if(resultblend && resultinf!=1.0f) { - Mat3One(identity); - Mat3BlendMat3(tree->basis_change[a], identity, - tree->basis_change[a], resultinf); - } IK_FreeSegment(iktree[a]); } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 1fe6447752e..aca51e56c6e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -525,7 +525,6 @@ typedef struct UndoElem { char str[FILE_MAXDIR+FILE_MAXFILE]; char name[MAXUNDONAME]; MemFile memfile; - uintptr_t undosize; } UndoElem; static ListBase undobase={NULL, NULL}; @@ -556,7 +555,6 @@ static int read_undosave(UndoElem *uel) /* name can be a dynamic string */ void BKE_write_undo(char *name) { - uintptr_t maxmem, totmem, memused; int nr, success; UndoElem *uel; @@ -618,36 +616,8 @@ void BKE_write_undo(char *name) if(curundo->prev) prevfile= &(curundo->prev->memfile); - memused= MEM_get_memory_in_use(); success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err); - curundo->undosize= MEM_get_memory_in_use() - memused; - } - - if(U.undomemory != 0) { - /* limit to maximum memory (afterwards, we can't know in advance) */ - totmem= 0; - maxmem= ((uintptr_t)U.undomemory)*1024*1024; - - /* keep at least two (original + other) */ - uel= undobase.last; - while(uel && uel->prev) { - totmem+= uel->undosize; - if(totmem>maxmem) break; - uel= uel->prev; - } - - if(uel) { - if(uel->prev && uel->prev->prev) - uel= uel->prev; - - while(undobase.first!=uel) { - UndoElem *first= undobase.first; - BLI_remlink(&undobase, first); - /* the merge is because of compression */ - BLO_merge_memfile(&first->memfile, &first->next->memfile); - MEM_freeN(first); - } - } + } } @@ -713,14 +683,14 @@ char *BKE_undo_menu_string(void) UndoElem *uel; DynStr *ds= BLI_dynstr_new(); char *menu; - + BLI_dynstr_append(ds, "Global Undo History %t"); for(uel= undobase.first; uel; uel= uel->next) { BLI_dynstr_append(ds, "|"); BLI_dynstr_append(ds, uel->name); } - + menu= BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 9d5dcb8109b..472df3d0f26 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -58,10 +58,6 @@ #include "MEM_guardedalloc.h" -#include "GPU_draw.h" -#include "GPU_extensions.h" -#include "GPU_material.h" - #include #include @@ -247,7 +243,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) glEnd(); } -static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) +static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; @@ -275,7 +271,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *a || new_shademodel != shademodel) { glEnd(); - drawCurrentMat = setMaterial(matnr = new_matnr, NULL); + drawCurrentMat = setMaterial(matnr = new_matnr); glShadeModel(shademodel = new_shademodel); glBegin(glmode = new_glmode); @@ -560,134 +556,6 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } -static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) -{ - CDDerivedMesh *cddm = (CDDerivedMesh*) dm; - GPUVertexAttribs gattribs; - DMVertexAttribs attribs; - MVert *mvert = cddm->mvert; - MFace *mface = cddm->mface; - MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); - float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); - int a, b, dodraw, smoothnormal, matnr, new_matnr; - int transp, new_transp, orig_transp; - int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); - - matnr = -1; - smoothnormal = 0; - dodraw = 0; - transp = GPU_get_material_blend_mode(); - orig_transp = transp; - - memset(&attribs, 0, sizeof(attribs)); - - glShadeModel(GL_SMOOTH); - glBegin(GL_QUADS); - - for(a = 0; a < dm->numFaceData; a++, mface++) { - new_matnr = mface->mat_nr + 1; - - if(new_matnr != matnr) { - glEnd(); - - dodraw = setMaterial(matnr = new_matnr, &gattribs); - if(dodraw) - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - - glBegin(GL_QUADS); - } - - if(!dodraw) { - continue; - } - else if(setDrawOptions) { - orig = index[a]; - - if(orig == ORIGINDEX_NONE) - continue; - else if(!setDrawOptions(userData, orig)) - continue; - } - - if(tf) { - new_transp = tf[a].transp; - - if(new_transp != transp) { - glEnd(); - - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - - glBegin(GL_QUADS); - } - } - - smoothnormal = (mface->flag & ME_SMOOTH); - - if(!smoothnormal) { - if(nors) { - glNormal3fv(nors[a]); - } - else { - /* TODO ideally a normal layer should always be available */ - float nor[3]; - if(mface->v4) { - CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co, - mvert[mface->v3].co, mvert[mface->v4].co, - nor); - } else { - CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co, - mvert[mface->v3].co, nor); - } - glNormal3fv(nor); - } - } - -#define PASSVERT(index, vert) { \ - if(attribs.totorco) \ - glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ - for(b = 0; b < attribs.tottface; b++) { \ - MTFace *tf = &attribs.tface[b].array[a]; \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[a*4 + vert]; \ - glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ - } \ - if(smoothnormal) \ - glNormal3sv(mvert[index].no); \ - glVertex3fv(mvert[index].co); \ -} - - PASSVERT(mface->v1, 0); - PASSVERT(mface->v2, 1); - PASSVERT(mface->v3, 2); - if(mface->v4) - PASSVERT(mface->v4, 3) - else - PASSVERT(mface->v3, 2) - -#undef PASSVERT - } - glEnd(); - - glShadeModel(GL_FLAT); -} - -static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -845,10 +713,8 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->drawFacesSolid = cdDM_drawFacesSolid; dm->drawFacesColored = cdDM_drawFacesColored; dm->drawFacesTex = cdDM_drawFacesTex; - dm->drawFacesGLSL = cdDM_drawFacesGLSL; dm->drawMappedFaces = cdDM_drawMappedFaces; dm->drawMappedFacesTex = cdDM_drawMappedFacesTex; - dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL; dm->foreachMappedVert = cdDM_foreachMappedVert; dm->foreachMappedEdge = cdDM_foreachMappedEdge; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 45b8bb7935c..295b8fe3552 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -730,24 +730,3 @@ void curvemapping_initialize(CurveMapping *cumap) curvemap_make_table(cumap->cm+a, &cumap->clipr); } } - -void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size) -{ - int a; - - *size = CM_TABLE+1; - *array = MEM_callocN(sizeof(float)*(*size)*4, "CurveMapping"); - curvemapping_initialize(cumap); - - for(a=0; a<*size; a++) { - if(cumap->cm[0].table) - (*array)[a*4+0]= cumap->cm[0].table[a].y; - if(cumap->cm[1].table) - (*array)[a*4+1]= cumap->cm[1].table[a].y; - if(cumap->cm[2].table) - (*array)[a*4+2]= cumap->cm[2].table[a].y; - if(cumap->cm[3].table) - (*array)[a*4+3]= cumap->cm[3].table[a].y; - } -} - diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 5f72bf316ab..1d7d4d1fda0 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -369,12 +369,19 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */ { /* world to pose */ - Mat4Invert(imat, ob->obmat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, imat); + if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_LOCAL || to==CONSTRAINT_SPACE_PARLOCAL) { + Mat4Invert(imat, ob->obmat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, imat); + } - /* use pose-space as stepping stone for other spaces... */ - if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { + /* pose to local */ + if (to == CONSTRAINT_SPACE_LOCAL) { + /* call self with slightly different values */ + constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + } + /* pose to local + parent */ + else if (to == CONSTRAINT_SPACE_PARLOCAL) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } @@ -440,65 +447,68 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 break; case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ { - /* local to pose - do inverse procedure that was done for pose to local */ - if (pchan->bone) { - /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ - if (pchan->parent) { - float offs_bone[4][4]; - - /* construct offs_bone the same way it is done in armature.c */ - Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); - VECCOPY(offs_bone[3], pchan->bone->head); - offs_bone[3][1]+= pchan->bone->parent->length; - - if (pchan->bone->flag & BONE_HINGE) { - /* pose_mat = par_pose-space_location * chan_mat */ - float tmat[4][4]; + /* local to pose */ + if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) { + /* do inverse procedure that was done for pose to local */ + if (pchan->bone) { + /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ + if (pchan->parent) { + float offs_bone[4][4]; - /* the rotation of the parent restposition */ - Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat); - /* the location of actual parent transform */ - VECCOPY(tmat[3], offs_bone[3]); - offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; - Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]); - - Mat4MulMat4(diff_mat, offs_bone, tmat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, diff_mat); + /* construct offs_bone the same way it is done in armature.c */ + Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); + VECCOPY(offs_bone[3], pchan->bone->head); + offs_bone[3][1]+= pchan->bone->parent->length; + if (pchan->bone->flag & BONE_HINGE) { + /* pose_mat = par_pose-space_location * chan_mat */ + float tmat[4][4]; + + /* the rotation of the parent restposition */ + Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat); + + /* the location of actual parent transform */ + VECCOPY(tmat[3], offs_bone[3]); + offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; + Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]); + + Mat4MulMat4(diff_mat, offs_bone, tmat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, diff_mat); + } + else { + /* pose_mat = par_pose_mat * bone_mat * chan_mat */ + Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, diff_mat); + } } else { - /* pose_mat = par_pose_mat * bone_mat * chan_mat */ - Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat); + Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); + Mat4CpyMat4(tempmat, mat); Mat4MulMat4(mat, tempmat, diff_mat); } } - else { - Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); - - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, diff_mat); - } } - - /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { + /* local to world */ + if (to == CONSTRAINT_SPACE_WORLD) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); - } + } } break; case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */ { - /* local + parent to pose */ - if (pchan->bone) { - Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, diff_mat, tempmat); + /* local to pose */ + if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) { + if (pchan->bone) { + Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, diff_mat, tempmat); + } } - - /* use pose-space as stepping stone for other spaces */ - if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { + /* local to world */ + if (to == CONSTRAINT_SPACE_WORLD) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 1be0a2aafdb..80f450000bb 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1924,10 +1924,8 @@ static void dag_object_time_update_flags(Object *ob) } } } - - if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; - - if(ob->parent) { + else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; + else if(ob->parent) { /* motion path or bone child */ if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB; } @@ -1948,11 +1946,10 @@ static void dag_object_time_update_flags(Object *ob) } } } - - if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; - if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; - - { + else if(modifiers_isSoftbodyEnabled(ob)) ob->recalc |= OB_RECALC_DATA; + else if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; + else if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; + else { Mesh *me; Curve *cu; Lattice *lt; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 327008c60de..0842e55a0ea 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -267,7 +267,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) hit.dist = len + FLT_EPSILON; // check if the way is blocked - if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) + if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0) { // visibility is only between 0 and 1, calculated from 1-absorption visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01))); @@ -406,15 +406,12 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); - Normalize(mag_vec); - VecMulf(mag_vec,force_val*falloff); VecAddf(field,field,mag_vec); break; case PFIELD_VORTEX: Crossf(mag_vec,eff_vel,vec_to_part); - Normalize(mag_vec); VecMulf(mag_vec,force_val*distance*falloff); @@ -428,8 +425,6 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, /* magnetic field of a moving charge */ Crossf(temp,eff_vel,vec_to_part); - Normalize(temp); - Crossf(temp2,velocity,temp); VecAddf(mag_vec,mag_vec,temp2); @@ -442,8 +437,6 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); - Normalize(mag_vec); - VecMulf(mag_vec,force_val*falloff); VecSubf(field,field,mag_vec); @@ -458,8 +451,6 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); - Normalize(mag_vec); - VecMulf(mag_vec,charge*force_val*falloff); VecAddf(field,field,mag_vec); break; @@ -544,6 +535,10 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float where_is_object_time(ob,cur_time); /* use center of object for distance calculus */ + obloc= ob->obmat[3]; + VECSUB(vect_to_vert, obloc, opco); + distance = VecLength(vect_to_vert); + VecSubf(vec_to_part, opco, ob->obmat[3]); distance = VecLength(vec_to_part); diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index 479be2ee644..fb48c875995 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -2632,17 +2632,17 @@ static void write_videoscape_mesh(Object *ob, char *str) if(evl->v4==0) { fprintf(fp, "3 %ld %ld %ld 0x%x\n", - (long int) evl->v1->tmp.l, - (long int) evl->v2->tmp.l, - (long int) evl->v3->tmp.l, + evl->v1->tmp.l, + evl->v2->tmp.l, + evl->v3->tmp.l, kleur[evl->mat_nr]); } else { fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - (long int) evl->v1->tmp.l, - (long int) evl->v2->tmp.l, - (long int) evl->v3->tmp.l, - (long int) evl->v4->tmp.l, + evl->v1->tmp.l, + evl->v2->tmp.l, + evl->v3->tmp.l, + evl->v4->tmp.l, kleur[evl->mat_nr]); } evl= evl->next; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 27fa00ac239..07537e3a81c 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -53,7 +53,6 @@ #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_camera_types.h" -#include "DNA_sequence_types.h" #include "DNA_texture_types.h" #include "DNA_userdef_types.h" @@ -78,15 +77,15 @@ #include "RE_pipeline.h" +/* bad level; call to free_realtime_image */ +#include "BKE_bad_level_calls.h" + /* for stamp drawing to an image */ #include "BMF_Api.h" #include "blendef.h" #include "BSE_time.h" -#include "GPU_extensions.h" -#include "GPU_draw.h" - #include "BLO_sys_types.h" // for intptr_t support /* max int, to indicate we don't store sequences in ibuf */ @@ -241,7 +240,7 @@ static void image_free_buffers(Image *ima) ima->rr= NULL; } - GPU_free_image(ima); + free_realtime_image(ima); ima->ok= IMA_OK; } @@ -621,7 +620,7 @@ void free_old_images() This gives textures a "second chance" to be used before dying. */ if(ima->bindcode || ima->repbind) { - GPU_free_image(ima); + free_realtime_image(ima); ima->lastused = ctime; } /* Otherwise, just kill the buffers */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index e8a25aaaf80..4af25ee99e7 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1390,14 +1390,6 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= ma->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= ma->mtex[9]; - else if(icu->adrcode & MA_MAP12) mtex= ma->mtex[11]; - else if(icu->adrcode & MA_MAP11) mtex= ma->mtex[10]; - else if(icu->adrcode & MA_MAP13) mtex= ma->mtex[12]; - else if(icu->adrcode & MA_MAP14) mtex= ma->mtex[13]; - else if(icu->adrcode & MA_MAP15) mtex= ma->mtex[14]; - else if(icu->adrcode & MA_MAP16) mtex= ma->mtex[15]; - else if(icu->adrcode & MA_MAP17) mtex= ma->mtex[16]; - else if(icu->adrcode & MA_MAP18) mtex= ma->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); @@ -1487,14 +1479,7 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= wo->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= wo->mtex[9]; - else if(icu->adrcode & MA_MAP11) mtex= wo->mtex[10]; - else if(icu->adrcode & MA_MAP12) mtex= wo->mtex[11]; - else if(icu->adrcode & MA_MAP13) mtex= wo->mtex[12]; - else if(icu->adrcode & MA_MAP14) mtex= wo->mtex[13]; - else if(icu->adrcode & MA_MAP15) mtex= wo->mtex[14]; - else if(icu->adrcode & MA_MAP16) mtex= wo->mtex[15]; - else if(icu->adrcode & MA_MAP17) mtex= wo->mtex[16]; - else if(icu->adrcode & MA_MAP18) mtex= wo->mtex[17]; + if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); } @@ -1539,14 +1524,6 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= la->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= la->mtex[9]; - else if(icu->adrcode & MA_MAP11) mtex= la->mtex[10]; - else if(icu->adrcode & MA_MAP12) mtex= la->mtex[11]; - else if(icu->adrcode & MA_MAP13) mtex= la->mtex[12]; - else if(icu->adrcode & MA_MAP14) mtex= la->mtex[13]; - else if(icu->adrcode & MA_MAP15) mtex= la->mtex[14]; - else if(icu->adrcode & MA_MAP16) mtex= la->mtex[15]; - else if(icu->adrcode & MA_MAP17) mtex= la->mtex[16]; - else if(icu->adrcode & MA_MAP18) mtex= la->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); @@ -1695,8 +1672,6 @@ void set_icu_vars(IpoCurve *icu) icu->ymax= 5.0; break; case MA_ADD: icu->ymax= 1.0; break; - case MA_EMIT: - icu->ymax= 2.0; break; default: icu->ymax= 1.0; break; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index f05b84f6e90..3983eecdaba 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -61,8 +61,6 @@ #include "BPY_extern.h" -#include "GPU_material.h" - /* used in UI and render */ Material defmaterial; @@ -98,9 +96,6 @@ void free_material(Material *ma) ntreeFreeTree(ma->nodetree); MEM_freeN(ma->nodetree); } - - if(ma->gpumaterial.first) - GPU_material_free(ma); } void init_material(Material *ma) @@ -212,8 +207,6 @@ Material *copy_material(Material *ma) if(ma->nodetree) { man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */ } - - man->gpumaterial.first= man->gpumaterial.last= NULL; return man; } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 77b9ea4fa2d..43e48c3bacd 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -79,6 +79,45 @@ #include "BLI_editVert.h" #include "BLI_arithb.h" +int update_realtime_texture(MTFace *tface, double time) +{ + Image *ima; + int inc = 0; + float diff; + int newframe; + + ima = tface->tpage; + + if (!ima) + return 0; + + if (ima->lastupdate<0) + ima->lastupdate = 0; + + if (ima->lastupdate>time) + ima->lastupdate=(float)time; + + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; + + /* check: is the bindcode not in the array? Then free. (still to do) */ + + diff = (float)(time-ima->lastupdate); + + inc = (int)(diff*(float)ima->animspeed); + + ima->lastupdate+=((float)inc/(float)ima->animspeed); + + newframe = ima->lastframe+inc; + + if (newframe > (int)ima->twend) + newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); + + ima->lastframe = newframe; + } + return inc; +} + void mesh_update_customdata_pointers(Mesh *me) { me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 16287d360b5..3b8bb25d601 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -794,18 +794,12 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { Curve *cu = amd->curve_ob->data; if(cu) { - float tmp_mat[3][3]; - float scale; - - object_to_mat3(amd->curve_ob, tmp_mat); - scale = Mat3ToScalef(tmp_mat); - if(!cu->path) { cu->flag |= CU_PATH; // needed for path & bevlist makeDispListCurveTypes(amd->curve_ob, 0); } if(cu->path) - length = scale*cu->path->totdist; + length = cu->path->totdist; } } @@ -5294,11 +5288,6 @@ static void softbodyModifier_deformVerts( sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); } -static int softbodyModifier_dependsOnTime(ModifierData *md) -{ - return 1; -} - /* Cloth */ @@ -7648,7 +7637,6 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_RequiresOriginalData; mti->deformVerts = softbodyModifier_deformVerts; - mti->dependsOnTime = softbodyModifier_dependsOnTime; mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_Nonconstructive; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 94a21cdd5df..4e36df35a14 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -68,9 +68,6 @@ #include "SHD_node.h" -#include "GPU_extensions.h" -#include "GPU_material.h" - static ListBase empty_list = {NULL, NULL}; ListBase node_all_composit = {NULL, NULL}; ListBase node_all_shaders = {NULL, NULL}; @@ -2355,117 +2352,6 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeEndExecTree(ntree); } -/* GPU material from shader nodes */ - -static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) -{ - bNodeSocket *sock; - int i; - - for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { - memset(&gs[i], 0, sizeof(gs[i])); - - QUATCOPY(gs[i].vec, ns[i]->vec); - gs[i].link= ns[i]->data; - - if (sock->type == SOCK_VALUE) - gs[i].type= GPU_FLOAT; - else if (sock->type == SOCK_VECTOR) - gs[i].type= GPU_VEC3; - else if (sock->type == SOCK_RGBA) - gs[i].type= GPU_VEC4; - else - gs[i].type= GPU_NONE; - - gs[i].name = ""; - gs[i].hasinput= ns[i]->hasinput && ns[i]->data; - gs[i].hasoutput= ns[i]->hasinput && ns[i]->data; - gs[i].sockettype= ns[i]->sockettype; - } - - gs[i].type= GPU_NONE; -} - -static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) -{ - bNodeSocket *sock; - int i; - - for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { - ns[i]->data= gs[i].link; - ns[i]->hasinput= gs[i].hasinput && gs[i].link; - ns[i]->hasoutput= gs[i].hasoutput; - ns[i]->sockettype= gs[i].sockettype; - } -} - -static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out) -{ - bNode *node; - bNodeTree *ntree= (bNodeTree *)gnode->id; - bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ - GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; - int doit = 0; - - if(ntree==NULL) return; - - stack+= gnode->stack_index; - - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->gpufunc) { - group_node_get_stack(node, stack, nsin, nsout, in, out); - - doit = 0; - - /* for groups, only execute outputs for edited group */ - if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { - if(gnode->flag & NODE_GROUP_EDIT) - if(node->flag & NODE_DO_OUTPUT) - doit = 1; - } - else - doit = 1; - - if(doit) { - gpu_from_node_stack(&node->inputs, nsin, gpuin); - gpu_from_node_stack(&node->outputs, nsout, gpuout); - if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) - data_from_gpu_stack(&node->outputs, nsout, gpuout); - } - } - } -} - -void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) -{ - bNode *node; - bNodeStack *stack; - bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ - bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ - GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; - - if((ntree->init & NTREE_EXEC_INIT)==0) - ntreeBeginExecTree(ntree); - - stack= ntree->stack; - - for(node= ntree->nodes.first; node; node= node->next) { - if(node->typeinfo->gpufunc) { - node_get_stack(node, stack, nsin, nsout); - gpu_from_node_stack(&node->inputs, nsin, gpuin); - gpu_from_node_stack(&node->outputs, nsout, gpuout); - if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) - data_from_gpu_stack(&node->outputs, nsout, gpuout); - } - else if(node->type==NODE_GROUP && node->id) { - node_get_stack(node, stack, nsin, nsout); - gpu_node_group_execute(stack, mat, node, nsin, nsout); - } - } - - ntreeEndExecTree(ntree); -} /* **************** call to switch lamploop for material node ************ */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index e63d6047cc6..7b36e46d45e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -112,8 +112,6 @@ #include "BPY_extern.h" -#include "GPU_material.h" - #include "blendef.h" /* Local function protos */ @@ -270,7 +268,6 @@ void free_object(Object *ob) } if(ob->soft) sbFree(ob->soft); if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings); - if(ob->gpulamp.first) GPU_lamp_free(ob); } static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin) @@ -697,11 +694,9 @@ float dof_camera(Object *ob) if (cam->dof_ob) { /* too simple, better to return the distance on the view axis only * return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */ - float mat[4][4], obmat[4][4]; - Mat4CpyMat4(obmat, ob->obmat); - Mat4Ortho(obmat); - Mat4Invert(ob->imat, obmat); + float mat[4][4]; + Mat4Invert(ob->imat, ob->obmat); Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat); return fabs(mat[3][2]); } @@ -923,7 +918,7 @@ Object *add_only_object(int type, char *name) QuatOne(ob->dquat); #endif - ob->col[0]= ob->col[1]= ob->col[2]= 1.0; + ob->col[0]= ob->col[1]= ob->col[2]= 0.0; ob->col[3]= 1.0; ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0; @@ -960,8 +955,7 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[0] = 1.0f; ob->anisotropicFriction[1] = 1.0f; ob->anisotropicFriction[2] = 1.0f; - ob->gameflag= OB_PROP|OB_PHYSICS; - ob->margin = 0.0; + ob->gameflag= OB_PROP; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; @@ -1232,7 +1226,6 @@ Object *copy_object(Object *ob) obn->vnode = NULL; #endif - obn->gpulamp.first = obn->gpulamp.last = NULL; return obn; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index db3576f0c50..2f4696fc442 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -379,11 +379,8 @@ void psys_free_children(ParticleSystem *psys) } /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) -{ +{ if(psys){ - int nr = 0; - ParticleSystem * tpsys; - if(ob->particlesystem.first == NULL && G.f & G_PARTICLEEDIT) G.f &= ~G_PARTICLEEDIT; @@ -409,21 +406,6 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->effectors.first) psys_end_effectors(psys); - - // check if we are last non-visible particle system - for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){ - if(tpsys->part) - { - if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) - { - nr++; - break; - } - } - } - // clear do-not-draw-flag - if(!nr) - ob->transflag &= ~OB_DUPLIPARTS; if(psys->part){ psys->part->id.us--; @@ -435,7 +417,7 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->pointcache) BKE_ptcache_free(psys->pointcache); - + MEM_freeN(psys); } } @@ -3841,7 +3823,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { - float loc[3], nor[3], vec[3], len, obrotmat[4][4], qmat[4][4]; + float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; VecSubf(vec, (cache+cache->steps-1)->co, cache->co); @@ -3866,9 +3848,14 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys Mat4MulMat4(mat, obrotmat, qmat); } else { - Normalize(nor); + Crossf(side, nor, vec); + Normalize(side); + Crossf(nor, vec, side); + Mat4One(mat); - VECCOPY(mat[2], nor); // mat[2] is normal/direction + VECCOPY(mat[0], vec); + VECCOPY(mat[1], side); + VECCOPY(mat[2], nor); } *scale= len; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index df193bc3802..ef8373ee977 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -53,14 +53,12 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_kdtree.h" -#include "BLI_kdopbvh.h" #include "BLI_linklist.h" #include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" -#include "BKE_collision.h" #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_particle.h" @@ -78,8 +76,6 @@ #include "BKE_modifier.h" #include "BKE_scene.h" -#include "PIL_time.h" - #include "BSE_headerbuttons.h" #include "blendef.h" @@ -150,14 +146,6 @@ void psys_reset(ParticleSystem *psys, int mode) BLI_freelistN(&psys->reactevents); } } - else if(mode == PSYS_RESET_CACHE_MISS) { - /* set all particles to be skipped */ - ParticleData *pa = psys->particles; - int p=0; - - for(; ptotpart; p++, pa++) - pa->flag = PARS_NO_DISP; - } /* reset children */ if(psys->child) { @@ -2313,15 +2301,7 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy } } else if(pd->forcefield) - { type |= PSYS_EC_EFFECTOR; - - if(pd->forcefield == PFIELD_WIND) - { - pd->rng = rng_new(1); - rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed - } - } } if(pd && pd->deflect) @@ -2433,16 +2413,13 @@ void psys_end_effectors(ParticleSystem *psys) if(ec->tree) BLI_kdtree_free(ec->tree); - - if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND)) - rng_free(ec->ob->pd->rng); } BLI_freelistN(lb); } } -static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) { ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -2482,20 +2459,96 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } - else if(ec->type==PSYS_EC_PARTICLE){ - Object *eob = ec->ob; - ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); - ParticleSettings *epart = epsys->part; - ParticleData *epa = epsys->particles; - int totepart = epsys->totpart; + else if(ec->type==PSYS_EC_DEFLECT){ + DerivedMesh *dm; + MFace *mface=0; + MVert *mvert=0; + int i, totface; + float v1[3],v2[3],v3[3],v4[4], *min, *max; + if(ob==ec->ob) + dm=psmd->dm; + else{ + psys_disable_all(ec->ob); + + dm=mesh_get_derived_final(ec->ob,0); + + psys_enable_all(ec->ob); + } + + if(dm){ + totvert=dm->getNumVerts(dm); + totface=dm->getNumFaces(dm); + mface=dm->getFaceDataArray(dm,CD_MFACE); + mvert=dm->getVertDataArray(dm,CD_MVERT); + + /* Decide which is faster to calculate by the amount of*/ + /* matrice multiplications needed to convert spaces. */ + /* With size deflect we have to convert allways because */ + /* the object can be scaled nonuniformly (sphere->ellipsoid). */ + if(totvert<2*psys->totpart || part->flag & PART_SIZE_DEFL){ + co=ec->vert_cos=MEM_callocN(sizeof(float)*3*totvert,"Particle deflection vert cos"); + /* convert vert coordinates to global (particle) coordinates */ + for(i=0; iob->obmat,co); + } + co=ec->vert_cos; + } + else + ec->vert_cos=0; + + INIT_MINMAX(ec->ob_minmax,ec->ob_minmax+3); + + min=ec->face_minmax=MEM_callocN(sizeof(float)*6*totface,"Particle deflection face minmax"); + max=min+3; + + for(i=0; iv1); + VECCOPY(v2,co+3*mface->v2); + VECCOPY(v3,co+3*mface->v3); + } + else{ + VECCOPY(v1,mvert[mface->v1].co); + VECCOPY(v2,mvert[mface->v2].co); + VECCOPY(v3,mvert[mface->v3].co); + } + INIT_MINMAX(min,max); + DO_MINMAX(v1,min,max); + DO_MINMAX(v2,min,max); + DO_MINMAX(v3,min,max); + + if(mface->v4){ + if(co){ + VECCOPY(v4,co+3*mface->v4); + } + else{ + VECCOPY(v4,mvert[mface->v4].co); + } + DO_MINMAX(v4,min,max); + } + + DO_MINMAX(min,ec->ob_minmax,ec->ob_minmax+3); + DO_MINMAX(max,ec->ob_minmax,ec->ob_minmax+3); + } + } + else + ec->face_minmax=0; + } + else if(ec->type==PSYS_EC_PARTICLE){ if(psys->part->phystype==PART_PHYS_BOIDS){ + Object *eob = ec->ob; + ParticleSystem *epsys; + ParticleSettings *epart; ParticleData *epa; ParticleKey state; PartDeflect *pd; - int p; - + int totepart, p; + epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); + epart= epsys->part; pd= epart->pd; + totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && totepart){ KDTree *tree; @@ -2510,11 +2563,6 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } - else if(ec->type==PSYS_EC_DEFLECT) { - CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); - if(collmd) - collision_move_object(collmd, 1.0, 0.0); - } } } @@ -2617,7 +2665,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size); } } - else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ + else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ psys_get_particle_state(eob,epsys,p,&estate,1); VECADD(vel,vel,estate.vel); @@ -2963,124 +3011,37 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, } return intersect; } - -/* container for moving data between deflet_particle and particle_intersect_face */ -typedef struct ParticleCollision -{ - struct Object *ob, *ob_t; // collided and current objects - struct CollisionModifierData *md; // collision modifier for ob_t; - float nor[3]; // normal at collision point - float vel[3]; // velocity of collision point - float co1[3], co2[3]; // ray start and end points - float ray_len; // original length of co2-co1, needed for collision time evaluation - float t; // time of previous collision, needed for substracting face velocity -} -ParticleCollision; - -static void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) -{ - ParticleCollision *col = (ParticleCollision *) userdata; - MFace *face = col->md->mfaces + index; - MVert *x = col->md->x; - MVert *v = col->md->current_v; - float dir[3], vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], dist, t, threshold; - int ret=0; - - float *t0, *t1, *t2, *t3; - t0 = x[ face->v1 ].co; - t1 = x[ face->v2 ].co; - t2 = x[ face->v3 ].co; - t3 = face->v4 ? x[ face->v4].co : NULL; - - /* calculate average velocity of face */ - VECCOPY(vel, v[ face->v1 ].co); - VECADD(vel, vel, v[ face->v2 ].co); - VECADD(vel, vel, v[ face->v3 ].co); - VecMulf(vel, 0.33334f); - - /* substract face velocity, in other words convert to - a coordinate system where only the particle moves */ - VECADDFAC(co1, col->co1, vel, -col->t); - VECSUB(co2, col->co2, vel); - - do - { - if(ray->radius == 0.0f) { - if(LineIntersectsTriangle(co1, co2, t0, t1, t2, &t, uv)) { - if(t >= 0.0f && t < hit->dist/col->ray_len) { - hit->dist = col->ray_len * t; - hit->index = index; - - /* calculate normal that's facing the particle */ - CalcNormFloat(t0, t1, t2, col->nor); - VECSUB(temp, co2, co1); - if(Inpf(col->nor, temp) > 0.0f) - VecMulf(col->nor, -1.0f); - - VECCOPY(col->vel,vel); - - col->ob = col->ob_t; - } - } - } - else { - if(SweepingSphereIntersectsTriangleUV(co1, co2, ray->radius, t0, t1, t2, &t, ipoint)) { - if(t >=0.0f && t < hit->dist/col->ray_len) { - hit->dist = col->ray_len * t; - hit->index = index; - - VecLerpf(temp, co1, co2, t); - - VECSUB(col->nor, temp, ipoint); - Normalize(col->nor); - - VECCOPY(col->vel,vel); - - col->ob = col->ob_t; - } - } - } - - t1 = t2; - t2 = t3; - t3 = NULL; - - } while(t2); -} /* particle - mesh collision code */ /* in addition to basic point to surface collisions handles friction & damping,*/ /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){ - Object *ob; +static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float dfra, float cfra, ParticleKey *state, int *pa_die){ + Object *ob, *min_ob; + MFace *mface; + MVert *mvert; + DerivedMesh *dm; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; - ParticleKey reaction_state; - ParticleCollision col; - CollisionModifierData *collmd; - BVHTreeRayHit hit; - float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; - float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f); - int deflections=0, max_deflections=10; + ParticleKey cstate; + float imat[4][4]; + float co1[3],co2[3],def_loc[3],def_nor[3],unit_nor[3],def_tan[3],dvec[3],def_vel[3],dave[3],dvel[3]; + float pa_minmax[6]; + float min_w[4], zerovec[3]={0.0,0.0,0.0}, ipoint[3]; + float min_d,dotprod,damp,frict,o_len,d_len,radius=-1.0f; + int min_face=0, intersect=1, through=0; + short deflections=0, global=0; - VECCOPY(col.co1, pa->state.co); - VECCOPY(col.co2, state->co); - col.t = 0.0f; + VECCOPY(def_loc,pa->state.co); + VECCOPY(def_vel,pa->state.vel); /* 10 iterations to catch multiple deflections */ - if(lb->first) while(deflections < max_deflections){ + if(lb->first) while(deflections<10){ + intersect=0; + global=0; + min_d=20000.0; + min_ob=NULL; /* 1. */ - - VECSUB(ray_dir, col.co2, col.co1); - hit.index = -1; - hit.dist = col.ray_len = VecLength(ray_dir); - - /* even if particle is stationary we want to check for moving colliders */ - /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */ - if(hit.dist == 0.0f) - hit.dist = col.ray_len = 0.000001f; - for(ec=lb->first; ec; ec=ec->next){ if(ec->type & PSYS_EC_DEFLECT){ ob= ec->ob; @@ -3088,165 +3049,263 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part if(part->type!=PART_HAIR) where_is_object_time(ob,cfra); - /* particles should not collide with emitter at birth */ - if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) - continue; + if(ob==pob){ + dm=psmd->dm; + /* particles should not collide with emitter at birth */ + if(pa->time < cfra && pa->time >= psys->cfra) + continue; + } + else + dm=0; + + VECCOPY(co1,def_loc); + VECCOPY(co2,state->co); - col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); - col.ob_t = ob; + if(ec->vert_cos==0){ + /* convert particle coordinates to object coordinates */ + Mat4Invert(imat,ob->obmat); + Mat4MulVecfl(imat,co1); + Mat4MulVecfl(imat,co2); + } - if(col.md->bvhtree) - BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); + INIT_MINMAX(pa_minmax,pa_minmax+3); + DO_MINMAX(co1,pa_minmax,pa_minmax+3); + DO_MINMAX(co2,pa_minmax,pa_minmax+3); + if(part->flag&PART_SIZE_DEFL){ + pa_minmax[0]-=pa->size; + pa_minmax[1]-=pa->size; + pa_minmax[2]-=pa->size; + pa_minmax[3]+=pa->size; + pa_minmax[4]+=pa->size; + pa_minmax[5]+=pa->size; + + radius=pa->size; + } + + if(ec->face_minmax==0 || AabbIntersectAabb(pa_minmax,pa_minmax+3,ec->ob_minmax,ec->ob_minmax+3)) { + if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w, + ec->face_minmax,pa_minmax,radius,ipoint)){ + + min_ob=ob; + + if(ec->vert_cos) + global=1; + else + global=0; + } + } } } /* 2. */ - if(hit.index>=0) { - PartDeflect *pd = col.ob->pd; - int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; - float co[3]; /* point of collision */ - float vec[3]; /* movement through collision */ - float vel[3]; /* velocity after collision */ - float t = hit.dist/col.ray_len; /* time of collision between this iteration */ - float dt = col.t + t * (1.0f - col.t); /* time of collision between frame change*/ + if(min_ob){ + BLI_srandom((int)cfra+p); + ob=min_ob; - VecLerpf(co, col.co1, col.co2, t); - VECSUB(vec, col.co2, col.co1); + if(ob==pob){ + dm=psmd->dm; + } + else{ + psys_disable_all(ob); - VecMulf(col.vel, 1.0f-col.t); + dm=mesh_get_derived_final(ob,0); - /* particle dies in collision */ - if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) { - pa->alive = PARS_DYING; - pa->dietime = pa->state.time + (cfra - pa->state.time) * dt; - VECCOPY(state->co, co); - VecLerpf(state->vel, pa->state.vel, state->vel, dt); - QuatInterpol(state->rot, pa->state.rot, state->rot, dt); - VecLerpf(state->ave, pa->state.ave, state->ave, dt); + psys_enable_all(ob); + } + + mface=dm->getFaceDataArray(dm,CD_MFACE); + mface+=min_face; + mvert=dm->getVertDataArray(dm,CD_MVERT); + + /* permeability check */ + if(BLI_frand()pd->pdef_perm) + through=1; + else + through=0; + + if(through==0 && (part->flag & PART_DIE_ON_COL || ob->pd->flag & PDEFLE_KILL_PART)){ + pa->dietime = cfra-(1.0f-min_d)*dfra; + VecLerpf(def_loc,def_loc,state->co,min_d); + + VECCOPY(state->co,def_loc); + VecLerpf(state->vel,pa->state.vel,state->vel,min_d); + QuatInterpol(state->rot,pa->state.rot,state->rot,min_d); + VecLerpf(state->ave,pa->state.ave,state->ave,min_d); + + *pa_die=1; /* particle is dead so we don't need to calculate further */ - deflections=max_deflections; + deflections=10; /* store for reactors */ - copy_particle_key(&reaction_state,state,0); + copy_particle_key(&cstate,state,0); if(part->flag & PART_STICKY){ pa->stick_ob=ob; pa->flag |= PARS_STICKY; } } - else { - float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; - float damp, frict; - float inp, inp_v; - - /* get damping & friction factors */ - damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); - CLAMP(damp,0.0,1.0); + else{ + VECCOPY(co1,def_loc); + VECCOPY(co2,state->co); - frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f); - CLAMP(frict,0.0,1.0); - - /* treat normal & tangent components separately */ - inp = Inpf(col.nor, vec); - inp_v = Inpf(col.nor, col.vel); - - VECADDFAC(tan_vec, vec, col.nor, -inp); - VECADDFAC(tan_vel, col.vel, col.nor, -inp_v); - if((part->flag & PART_ROT_DYN)==0) - VecLerpf(tan_vec, tan_vec, tan_vel, frict); - - VECCOPY(nor_vec, col.nor); - inp *= 1.0f - damp; - - if(through) - inp_v *= damp; - - /* special case for object hitting the particle from behind */ - if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v linear velocity - slightly more physical and looks even nicer than before */ - if(part->flag & PART_ROT_DYN) { - float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3]; - - /* apparent velocity along collision surface */ - VECSUB(surface_vel, tan_vec, tan_vel); - - /* direction of rolling friction */ - Crossf(rot_vel, state->ave, col.nor); - /* convert to current dt */ - VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t)); - VecMulf(rot_vel, pa->size); - - /* apply sliding friction */ - VECSUB(surface_vel, surface_vel, rot_vel); - VECCOPY(friction, surface_vel); - - VecMulf(surface_vel, 1.0 - frict); - VecMulf(friction, frict); - - /* sliding changes angular velocity */ - Crossf(dave, col.nor, friction); - VecMulf(dave, 1.0f/MAX2(pa->size, 0.001)); - - /* we assume rolling friction is around 0.01 of sliding friction */ - VecMulf(rot_vel, 1.0 - frict*0.01); - - /* change in angular velocity has to be added to the linear velocity too */ - Crossf(dvel, dave, col.nor); - VecMulf(dvel, pa->size); - VECADD(rot_vel, rot_vel, dvel); - - VECADD(surface_vel, surface_vel, rot_vel); - VECADD(tan_vec, surface_vel, tan_vel); - - /* convert back to normal time */ - VecMulf(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - - VecMulf(state->ave, 1.0 - frict*0.01); - VECADD(state->ave, state->ave, dave); + if(global==0){ + /* convert particle coordinates to object coordinates */ + Mat4Invert(imat,ob->obmat); + Mat4MulVecfl(imat,co1); + Mat4MulVecfl(imat,co2); } - /* combine components together again */ - VECADD(vec, nor_vec, tan_vec); + VecLerpf(def_loc,co1,co2,min_d); - /* calculate velocity from collision vector */ - VECCOPY(vel, vec); - VecMulf(vel, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - - /* make sure we don't hit the current face again */ - VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - - /* store state for reactors */ - VECCOPY(reaction_state.co, co); - VecLerpf(reaction_state.vel, pa->state.vel, state->vel, dt); - QuatInterpol(reaction_state.rot, pa->state.rot, state->rot, dt); - - /* set coordinates for next iteration */ - VECCOPY(col.co1, co); - VECADDFAC(col.co2, co, vec, 1.0f - t); - col.t = dt; - - if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) { - /* kill speed to stop slipping */ - VECCOPY(state->vel,zerovec); - VECCOPY(state->co, co); - if(part->flag & PART_ROT_DYN) { - VECCOPY(state->ave,zerovec); + if(radius>0.0f){ + VECSUB(unit_nor,def_loc,ipoint); + } + else{ + /* get deflection point & normal */ + psys_interpolate_face(mvert,mface,0,0,min_w,ipoint,unit_nor,0,0,0,0); + if(global){ + Mat4Mul3Vecfl(ob->obmat,unit_nor); + Mat4MulVecfl(ob->obmat,ipoint); } } - else { - VECCOPY(state->co, col.co2); - VECCOPY(state->vel, vel); + + Normalize(unit_nor); + + VECSUB(dvec,co1,co2); + /* scale to remaining length after deflection */ + VecMulf(dvec,1.0f-min_d); + + /* flip normal to face particle */ + if(Inpf(unit_nor,dvec)<0.0f) + VecMulf(unit_nor,-1.0f); + + /* store for easy velocity calculation */ + o_len=VecLength(dvec); + + /* project particle movement to normal & create tangent */ + dotprod=Inpf(dvec,unit_nor); + VECCOPY(def_nor,unit_nor); + VecMulf(def_nor,dotprod); + VECSUB(def_tan,def_nor,dvec); + + damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); + + /* create location after deflection */ + VECCOPY(dvec,def_nor); + damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); + CLAMP(damp,0.0,1.0); + VecMulf(dvec,1.0f-damp); + if(through) + VecMulf(dvec,-1.0); + + frict=ob->pd->pdef_frict+ob->pd->pdef_rfrict*2.0f*(BLI_frand()-0.5f); + CLAMP(frict,0.0,1.0); + VECADDFAC(dvec,dvec,def_tan,1.0f-frict); + + /* store for easy velocity calculation */ + d_len=VecLength(dvec); + + /* just to be sure we don't hit the current face again */ + if(through){ + VECADDFAC(ipoint,ipoint,unit_nor,-0.0001f); + VECADDFAC(def_loc,def_loc,unit_nor,-0.0001f); + + if(part->flag & PART_ROT_DYN){ + VECADDFAC(def_tan,def_tan,unit_nor,-0.0001f); + VECADDFAC(def_nor,def_nor,unit_nor,-0.0001f); + } + } + else{ + VECADDFAC(ipoint,ipoint,unit_nor,0.0001f); + VECADDFAC(def_loc,def_loc,unit_nor,0.0001f); + + if(part->flag & PART_ROT_DYN){ + VECADDFAC(def_tan,def_tan,unit_nor,0.0001f); + VECADDFAC(def_nor,def_nor,unit_nor,0.0001f); + } + } + + /* lets get back to global space */ + if(global==0){ + Mat4Mul3Vecfl(ob->obmat,dvec); + Mat4MulVecfl(ob->obmat,ipoint); + Mat4MulVecfl(ob->obmat,def_loc);/* def_loc remains as intersection point for next iteration */ + } + + /* store for reactors */ + VECCOPY(cstate.co,ipoint); + VecLerpf(cstate.vel,pa->state.vel,state->vel,min_d); + QuatInterpol(cstate.rot,pa->state.rot,state->rot,min_d); + + /* slightly unphysical but looks nice enough */ + if(part->flag & PART_ROT_DYN){ + if(global==0){ + Mat4Mul3Vecfl(ob->obmat,def_nor); + Mat4Mul3Vecfl(ob->obmat,def_tan); + } + + Normalize(def_tan); + Normalize(def_nor); + VECCOPY(unit_nor,def_nor); + + /* create normal velocity */ + VecMulf(def_nor,Inpf(pa->state.vel,def_nor)); + + /* create tangential velocity */ + VecMulf(def_tan,Inpf(pa->state.vel,def_tan)); + + /* angular velocity change due to tangential velocity */ + Crossf(dave,unit_nor,def_tan); + VecMulf(dave,1.0f/pa->size); + + /* linear velocity change due to angular velocity */ + VecMulf(unit_nor,pa->size); /* point of impact from particle center */ + Crossf(dvel,pa->state.ave,unit_nor); + + if(through) + VecMulf(def_nor,-1.0); + + VecMulf(def_nor,1.0f-damp); + VECSUB(dvel,dvel,def_nor); + + VecMulf(dvel,1.0f-frict); + VecMulf(dave,1.0f-frict); + } + + if(d_len<0.001 && VecLength(pa->state.vel)<0.001){ + /* kill speed to stop slipping */ + VECCOPY(state->vel,zerovec); + VECCOPY(state->co,def_loc); + if(part->flag & PART_ROT_DYN) + VECCOPY(state->ave,zerovec); + deflections=10; + } + else{ + + /* apply new coordinates */ + VECADD(state->co,def_loc,dvec); + + Normalize(dvec); + + /* we have to use original velocity because otherwise we get slipping */ + /* when forces like gravity balance out damping & friction */ + VecMulf(dvec,VecLength(pa->state.vel)*(d_len/o_len)); + VECCOPY(state->vel,dvec); + + if(part->flag & PART_ROT_DYN){ + VECADD(state->vel,state->vel,dvel); + VecMulf(state->vel,0.5); + VECADD(state->ave,state->ave,dave); + VecMulf(state->ave,0.5); + } } } deflections++; - reaction_state.time = cfra - (1.0f - dt) * dfra; - push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); + cstate.time=cfra-(1.0f-min_d)*dfra; + //particle_react_to_collision(min_ob,pob,psys,pa,p,&cstate); + push_reaction(pob,psys,p,PART_EVENT_COLLIDE,&cstate); } else return; @@ -3410,7 +3469,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l } } /* determines the acceleration that the boid tries to acchieve */ -static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc) +static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc, int *pa_die) { ParticleData *pars=psys->particles; KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1]; @@ -3477,7 +3536,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS distance=Normalize(dvec); if(part->flag & PART_DIE_ON_COL && distance < pd->mindist){ - pa->alive = PARS_DYING; + *pa_die=1; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3506,7 +3565,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0 && ec->tree){ + if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){ count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); for(p=0; pflag & PART_DIE_ON_COL && distance < (epsys->particles+ptn2[p].index)->size){ - pa->alive = PARS_DYING; + *pa_die=1; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3653,7 +3712,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0 && ec->tree){ + if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){ count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); for(p=0; pvel[2]=0.0; state->co[2]=part->groundz; - if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ + if(psys->keyed_ob){ Object *zob=psys->keyed_ob; int min_face; float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; @@ -3925,7 +3984,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); Material *ma=give_current_material(ob,part->omat); float timestep; - int p, totpart; + int p, totpart, pa_die; /* current time */ float ctime, ipotime; /* frame & time changes */ @@ -4005,7 +4064,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd,cfra); + precalc_effectors(ob,psys,psmd); if(part->phystype==PART_PHYS_BOIDS){ /* create particle tree for fast inter-particle comparisons */ @@ -4034,13 +4093,15 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + pa_die=0; + birthtime = pa->time + pa->loop * pa->lifetime; - /* allways reset particles to emitter before birth */ if(pa->alive==PARS_UNBORN || pa->alive==PARS_KILLED || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ + /* allways reset particles to emitter before birth */ reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); copy_particle_key(key,&pa->state,1); } @@ -4065,31 +4126,32 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi /* particle dies some time between this and last step */ pa_dfra = dietime - psys->cfra; pa_dtime = pa_dfra * timestep; - pa->alive = PARS_DYING; + pa_die = 1; } else if(dietime < cfra){ - /* nothing to be done when particle is dead */ + /* TODO: figure out if there's something to be done when particle is dead */ } copy_particle_key(key,&pa->state,1); - if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ + if(dfra>0.0 && pa->alive==PARS_ALIVE){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra,key); - + /* deflection */ - deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key); + deflect_particle(ob,psmd,psys,part,pa,p,pa_dfra,cfra,key,&pa_die); /* rotations */ rotate_particle(part,pa,pa_dfra,timestep,key); + break; case PART_PHYS_BOIDS: { float acc[3]; - boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); - if(pa->alive != PARS_DYING) + boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc,&pa_die); + if(pa_die==0) boid_body(&bvf,pa,psys,part,timestep,acc,key); break; } @@ -4097,7 +4159,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi push_reaction(ob,psys,p,PART_EVENT_NEAR,key); - if(pa->alive == PARS_DYING){ + if(pa_die){ push_reaction(ob,psys,p,PART_EVENT_DEATH,key); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ @@ -4119,7 +4181,6 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } } } - /* apply outstates to particles */ for(p=0, pa=psys->particles, key=outstate; pstate,key,1); @@ -4199,7 +4260,7 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd,cfra); + precalc_effectors(ob,psys,psmd); if(psys_in_edit_mode(psys)) PE_recalc_world_cos(ob, psys); @@ -4227,7 +4288,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd,cfra); + precalc_effectors(ob,psys,psmd); //} disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; @@ -4481,7 +4542,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(usecache) { /* frame clamping */ if(framenr < startframe) { - psys_reset(psys, PSYS_RESET_CACHE_MISS); + psys_reset(psys, PSYS_RESET_DEPSGRAPH); psys->cfra = cfra; psys->recalc = 0; return; @@ -4561,14 +4622,14 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier return; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { - psys_reset(psys, PSYS_RESET_CACHE_MISS); + psys_reset(psys, PSYS_RESET_DEPSGRAPH); psys->cfra=cfra; psys->recalc = 0; return; } if(framenr != startframe && framedelta != 1) { - psys_reset(psys, PSYS_RESET_CACHE_MISS); + psys_reset(psys, PSYS_RESET_DEPSGRAPH); psys->cfra = cfra; psys->recalc = 0; return; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 931519a1b4a..050cca15721 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -113,23 +113,23 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float void space_transform_apply(const SpaceTransform *data, float *co) { - VecMat4MulVecfl(co, ((SpaceTransform*)data)->local2target, co); + VecMat4MulVecfl(co, data->local2target, co); } void space_transform_invert(const SpaceTransform *data, float *co) { - VecMat4MulVecfl(co, ((SpaceTransform*)data)->target2local, co); + VecMat4MulVecfl(co, data->target2local, co); } void space_transform_apply_normal(const SpaceTransform *data, float *no) { - Mat4Mul3Vecfl( ((SpaceTransform*)data)->local2target, no); + Mat4Mul3Vecfl(data->local2target, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } void space_transform_invert_normal(const SpaceTransform *data, float *no) { - Mat4Mul3Vecfl(((SpaceTransform*)data)->target2local, no); + Mat4Mul3Vecfl(data->target2local, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } @@ -335,7 +335,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa space_transform_apply_normal( transf, tmp_no ); no = tmp_no; - hit_tmp.dist *= Mat4ToScalef( ((SpaceTransform*)transf)->local2target ); + hit_tmp.dist *= Mat4ToScalef( transf->local2target ); } else { @@ -345,7 +345,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa hit_tmp.index = -1; - BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); + BLI_bvhtree_ray_cast(tree, co, no, &hit_tmp, callback, userdata); if(hit_tmp.index != -1) { @@ -362,7 +362,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa space_transform_invert( transf, hit_tmp.co ); space_transform_invert_normal( transf, hit_tmp.no ); - hit_tmp.dist = VecLenf( (float*)vert, hit_tmp.co ); + hit_tmp.dist = VecLenf( vert, hit_tmp.co ); } memcpy(hit, &hit_tmp, sizeof(hit_tmp) ); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 508b2233536..d465c058d30 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1622,23 +1622,23 @@ void *exec_scan_for_ext_spring_forces(void *data) void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func()) { - ListBase *do_effector = NULL; + ListBase *do_effector = NULL; ListBase threads; SB_thread_context *sb_threads; int i, totthread,left,dec; - int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ + int lowsprings =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ do_effector= pdInitEffectors(ob,NULL); /* figure the number of threads while preventing pretty pointless threading overhead */ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; - else - totthread= BLI_system_thread_count(); - /* what if we got zillions of CPUs running but less to spread*/ - while ((totsprings/totthread < lowsprings) && (totthread > 1)) { - totthread--; + if(totsprings < lowsprings) {totthread=1;} + else{ + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); } + /*left to do--> what if we got zillions of CPUs running but 'totsprings' tasks to spread*/ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread"); memset(sb_threads, 0, sizeof(SB_thread_context)*totthread); @@ -2279,11 +2279,6 @@ int _softbody_calc_forces_slice_in_a_thread(Object *ob, float forcetime, float t float kd = 1.0f; if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ - if (intrusion < 0.0f){ - sb->scratch->flag |= SBF_DOFUZZY; - bp->flag |= SBF_DOFUZZY; - bp->choke = sb->choke*0.01f; - } VECSUB(cfforce,bp->vec,vel); Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); @@ -2331,19 +2326,17 @@ void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow,int tot ListBase threads; SB_thread_context *sb_threads; int i, totthread,left,dec; - int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ + int lowpoints =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ /* figure the number of threads while preventing pretty pointless threading overhead */ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; - else - totthread= BLI_system_thread_count(); - /* what if we got zillions of CPUs running but less to spread*/ - while ((totpoint/totthread < lowpoints) && (totthread > 1)) { - totthread--; + if(totpoint < lowpoints) {totthread=1;} + else{ + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); } - - /* printf("sb_cf_threads_run spawning %d threads \n",totthread); */ + /*left to do--> what if we got zillions of CPUs running but 'totpoint' tasks to spread*/ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread"); memset(sb_threads, 0, sizeof(SB_thread_context)*totthread); @@ -2432,7 +2425,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags) { /* redirection to the new threaded Version */ - if (!(G.rt & 0x10)){ // 16 + if (G.rt !=16){ softbody_calc_forcesEx(ob, forcetime, timenow, nl_flags); return; } @@ -2440,10 +2433,6 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int /* so the following will die */ /* |||||||||||||||||||||||||| */ /* VVVVVVVVVVVVVVVVVVVVVVVVVV */ - /*backward compatibility note: - fixing bug [17428] which forces adaptive step size to tiny steps - in some situations - .. keeping G.rt==17 0x11 option for old files 'needing' the bug*/ /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2692,25 +2681,14 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ if ((!nl_flags)&&(intrusion < 0.0f)){ - if(G.rt & 0x01){ // 17 we did check for bit 0x10 before - /*fixing bug [17428] this forces adaptive step size to tiny steps - in some situations .. keeping G.rt==17 option for old files 'needing' the bug - */ - /*bjornmose: uugh.. what an evil hack - violation of the 'don't touch bp->pos in here' rule - but works nice, like this--> - we predict the solution beeing out of the collider - in heun step No1 and leave the heun step No2 adapt to it - so we kind of introduced a implicit solver for this case - */ - Vec3PlusStVec(bp->pos,-intrusion,facenormal); - } - else{ - - VECSUB(cfforce,bp->vec,vel); - Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); - } - + /*bjornmose: uugh.. what an evil hack + violation of the 'don't touch bp->pos in here' rule + but works nice, like this--> + we predict the solution beeing out of the collider + in heun step No1 and leave the heun step No2 adapt to it + so we kind of introduced a implicit solver for this case + */ + Vec3PlusStVec(bp->pos,-intrusion,facenormal); sb->scratch->flag |= SBF_DOFUZZY; bp->flag |= SBF_DOFUZZY; @@ -4062,7 +4040,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime) if(sb->solverflags & SBSO_MONITOR ){ sct=PIL_check_seconds_timer(); - if ((sct-sst > 0.5f) || (G.f & G_DEBUG)) printf(" solver time %f sec %s \n",sct-sst,ob->id.name); + if (sct-sst > 0.5f) printf(" solver time %f sec %s \n",sct-sst,ob->id.name); } } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index e6797186b53..bba79bd6d28 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -61,10 +61,6 @@ #include "BIF_gl.h" -#include "GPU_draw.h" -#include "GPU_extensions.h" -#include "GPU_material.h" - #include "CCGSubSurf.h" typedef struct _VertData { @@ -700,7 +696,6 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, for(index = 0; index < totedge; index++) { CCGEdge *e = edgeMap2[index]; unsigned int flags = 0; - char bweight = 0; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ss, e)); if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE; @@ -711,14 +706,12 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, dm->getEdge(dm, edgeIdx, &origMed); flags |= origMed.flag; - bweight = origMed.bweight; } for(x = 0; x < edgeSize - 1; x++) { med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); med->flag = flags; - med->bweight = bweight; *origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e); ++med; ++origIndex; @@ -980,7 +973,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) memset(mv, 0, sizeof(*mv)); - if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { + if(vertNum < ccgdm->edgeMap[0].startVert) { /* this vert comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -1021,7 +1014,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) x = offset % gridSideVerts + 1; VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y)); } - } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) { + } else if(vertNum < ccgdm->vertMap[0].startVert) { /* this vert comes from edge data */ CCGEdge *e; int lastedge = ccgSubSurf_getNumEdges(ss) - 1; @@ -1606,7 +1599,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { +static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); @@ -1628,7 +1621,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void * mat_nr= 0; } - if (!setMaterial(mat_nr+1, NULL)) + if (!setMaterial(mat_nr+1)) continue; glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); @@ -1673,168 +1666,6 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void * ccgFaceIterator_free(fi); } - - /* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { - CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); - GPUVertexAttribs gattribs; - DMVertexAttribs attribs; - MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - int transp, orig_transp, new_transp; - char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS); - int a, b, i, doDraw, numVerts, matnr, new_matnr, totface; - - doDraw = 0; - numVerts = 0; - matnr = -1; - transp = GPU_get_material_blend_mode(); - orig_transp = transp; - - memset(&attribs, 0, sizeof(attribs)); - -#define PASSATTRIB(dx, dy, vert) { \ - if(attribs.totorco) { \ - index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \ - glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ - } \ - for(b = 0; b < attribs.tottface; b++) { \ - MTFace *tf = &attribs.tface[b].array[a]; \ - glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ - } \ - for(b = 0; b < attribs.totmcol; b++) { \ - MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ - GLubyte col[4]; \ - col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ - glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ - } \ - if(attribs.tottang) { \ - float *tang = attribs.tang.array[a*4 + vert]; \ - glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ - } \ -} - - totface = ccgSubSurf_getNumFaces(ss); - for(a = 0, i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, drawSmooth; - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); - int origIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f); - - numVerts = ccgSubSurf_getFaceNumVerts(ss, f); - - if(faceFlags) { - drawSmooth = (faceFlags[index*4] & ME_SMOOTH); - new_matnr= faceFlags[index*4 + 1] + 1; - } - else { - drawSmooth = 1; - new_matnr= 1; - } - - if(new_matnr != matnr) { - doDraw = setMaterial(matnr = new_matnr, &gattribs); - if(doDraw) - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) { - a += gridFaces*gridFaces*numVerts; - continue; - } - - if(tf) { - new_transp = tf[i].transp; - - if(new_transp != transp) { - if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) - GPU_set_material_blend_mode(orig_transp); - else - GPU_set_material_blend_mode(new_transp); - transp = new_transp; - } - } - - glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); - for (S=0; Sno); - glVertex3fv(vda->co); - - PASSATTRIB(0, 1, 1); - glNormal3fv(vdb->no); - glVertex3fv(vdb->co); - - if(x != gridFaces-1) - a++; - } - - vda = &faceGridData[(y+0)*gridSize + x]; - vdb = &faceGridData[(y+1)*gridSize + x]; - - PASSATTRIB(0, 0, 3); - glNormal3fv(vda->no); - glVertex3fv(vda->co); - - PASSATTRIB(0, 1, 2); - glNormal3fv(vdb->no); - glVertex3fv(vdb->co); - - glEnd(); - - a++; - } - } else { - glBegin(GL_QUADS); - for (y=0; ydrawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; @@ -2312,10 +2143,8 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid; ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored; ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex; - ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL; ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; - ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL; ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c deleted file mode 100644 index 6530909336c..00000000000 --- a/source/blender/blenkernel/intern/suggestions.c +++ /dev/null @@ -1,254 +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) 2008, Blender Foundation - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Ian Thompson. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include -#include - -#include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" -#include "DNA_text_types.h" -#include "BKE_text.h" -#include "BKE_suggestions.h" - -/**********************/ -/* Static definitions */ -/**********************/ - -static Text *activeToolText = NULL; -static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; -static char *documentation = NULL; -//static int doc_lines = 0; - -static int txttl_cmp(const char *first, const char *second, int len) { - int cmp, i; - for (cmp=0, i=0; iprev; - MEM_freeN(item); - } - suggestions.first = suggestions.last = NULL; - suggestions.firstmatch = suggestions.lastmatch = NULL; - suggestions.selected = NULL; - suggestions.top = 0; -} - -static void txttl_free_docs() { - if (documentation) { - MEM_freeN(documentation); - documentation = NULL; - } -} - -/**************************/ -/* General tool functions */ -/**************************/ - -void free_texttools() { - txttl_free_suggest(); - txttl_free_docs(); -} - -void texttool_text_set_active(Text *text) { - if (activeToolText == text) return; - texttool_text_clear(); - activeToolText = text; -} - -void texttool_text_clear() { - free_texttools(); - activeToolText = NULL; -} - -short texttool_text_is_active(Text *text) { - return activeToolText==text ? 1 : 0; -} - -/***************************/ -/* Suggestion list methods */ -/***************************/ - -void texttool_suggest_add(const char *name, char type) { - SuggItem *newitem, *item; - int len, cmp; - - newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); - if (!newitem) { - printf("Failed to allocate memory for suggestion.\n"); - return; - } - - newitem->name = (char *) (newitem + 1); - len = strlen(name); - strncpy(newitem->name, name, len); - newitem->name[len] = '\0'; - newitem->type = type; - newitem->prev = newitem->next = NULL; - - /* Perform simple linear search for ordered storage */ - if (!suggestions.first || !suggestions.last) { - suggestions.first = suggestions.last = newitem; - } else { - cmp = -1; - for (item=suggestions.last; item; item=item->prev) { - cmp = txttl_cmp(name, item->name, len); - - /* Newitem comes after this item, insert here */ - if (cmp >= 0) { - newitem->prev = item; - if (item->next) - item->next->prev = newitem; - newitem->next = item->next; - item->next = newitem; - - /* At last item, set last pointer here */ - if (item == suggestions.last) - suggestions.last = newitem; - break; - } - } - /* Reached beginning of list, insert before first */ - if (cmp < 0) { - newitem->next = suggestions.first; - suggestions.first->prev = newitem; - suggestions.first = newitem; - } - } - suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL; - suggestions.top= 0; -} - -void texttool_suggest_prefix(const char *prefix) { - SuggItem *match, *first, *last; - int cmp, len = strlen(prefix), top = 0; - - if (!suggestions.first) return; - if (len==0) { - suggestions.selected = suggestions.firstmatch = suggestions.first; - suggestions.lastmatch = suggestions.last; - return; - } - - first = last = NULL; - for (match=suggestions.first; match; match=match->next) { - cmp = txttl_cmp(prefix, match->name, len); - if (cmp==0) { - if (!first) { - first = match; - suggestions.top = top; - } - } else if (cmp<0) { - if (!last) { - last = match->prev; - break; - } - } - top++; - } - if (first) { - if (!last) last = suggestions.last; - suggestions.firstmatch = first; - suggestions.lastmatch = last; - suggestions.selected = first; - } else { - suggestions.firstmatch = NULL; - suggestions.lastmatch = NULL; - suggestions.selected = NULL; - suggestions.top = 0; - } -} - -void texttool_suggest_clear() { - txttl_free_suggest(); -} - -SuggItem *texttool_suggest_first() { - return suggestions.firstmatch; -} - -SuggItem *texttool_suggest_last() { - return suggestions.lastmatch; -} - -void texttool_suggest_select(SuggItem *sel) { - suggestions.selected = sel; -} - -SuggItem *texttool_suggest_selected() { - return suggestions.selected; -} - -int *texttool_suggest_top() { - return &suggestions.top; -} - -/*************************/ -/* Documentation methods */ -/*************************/ - -void texttool_docs_show(const char *docs) { - int len; - - if (!docs) return; - - len = strlen(docs); - - if (documentation) { - MEM_freeN(documentation); - documentation = NULL; - } - - /* Ensure documentation ends with a '\n' */ - if (docs[len-1] != '\n') { - documentation = MEM_mallocN(len+2, "Documentation"); - strncpy(documentation, docs, len); - documentation[len++] = '\n'; - } else { - documentation = MEM_mallocN(len+1, "Documentation"); - strncpy(documentation, docs, len); - } - documentation[len] = '\0'; -} - -char *texttool_docs_get() { - return documentation; -} - -void texttool_docs_clear() { - txttl_free_docs(); -} diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 5f1a1e63da4..53b7bb975a3 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -30,8 +30,6 @@ */ #include /* strstr */ -#include -#include #include "MEM_guardedalloc.h" @@ -83,19 +81,12 @@ The st->top determines at what line the top of the text is displayed. If the user moves the cursor the st containing that cursor should be popped ... other st's retain their own top location. -Markers --- -The mrk->flags define the behaviour and relationships between markers. The -upper two bytes are used to hold a group ID, the lower two are normal flags. If -TMARK_EDITALL is set the group ID defines which other markers should be edited. +*/ /***************/ -The mrk->clr field is used to visually group markers where the flags may not -match. A template system, for example, may allow editing of repeating tokens -(in one group) but include other marked positions (in another group) all in the -same template with the same colour. -Undo --- +/****************/ /* + Undo + Undo/Redo works by storing events in a queue, and a pointer to the current position in the @@ -154,7 +145,6 @@ void free_text(Text *text) } BLI_freelistN(&text->lines); - BLI_freelistN(&text->markers); if(text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -179,11 +169,10 @@ Text *add_empty_text(char *name) ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM; ta->lines.first= ta->lines.last= NULL; - ta->markers.first= ta->markers.last= NULL; tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(1, "textline_string"); - tmp->format= NULL; + tmp->format= (char*) MEM_mallocN(2, "Syntax_format"); tmp->line[0]=0; tmp->len= 0; @@ -220,12 +209,11 @@ static void cleanup_textline(TextLine * tl) int reopen_text(Text *text) { FILE *fp; - int i, llen, len, res; + int i, llen, len; unsigned char *buffer; TextLine *tmp; char sfile[FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE]; - struct stat st; if (!text || !text->name) return 0; @@ -254,7 +242,7 @@ int reopen_text(Text *text) text->undo_len= TXT_INIT_UNDO; text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); - text->flags= TXT_ISTMP; + text->flags= TXT_ISDIRTY | TXT_ISTMP; fseek(fp, 0L, SEEK_END); len= ftell(fp); @@ -268,9 +256,6 @@ int reopen_text(Text *text) len = fread(buffer, 1, len, fp); fclose(fp); - - res= stat(str, &st); - text->mtime= st.st_mtime; text->nlines=0; i=0; @@ -279,7 +264,7 @@ int reopen_text(Text *text) if (buffer[i]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= NULL; + tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); if(llen) memcpy(tmp->line, &buffer[i-llen], llen); tmp->line[llen]=0; @@ -299,7 +284,7 @@ int reopen_text(Text *text) if (llen!=0 || text->nlines==0) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= NULL; + tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); if(llen) memcpy(tmp->line, &buffer[i-llen], llen); @@ -322,13 +307,12 @@ int reopen_text(Text *text) Text *add_text(char *file) { FILE *fp; - int i, llen, len, res; + int i, llen, len; unsigned char *buffer; TextLine *tmp; Text *ta; char sfile[FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE]; - struct stat st; BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE); if (G.scene) /* can be NULL (bg mode) */ @@ -342,7 +326,6 @@ Text *add_text(char *file) ta->id.us= 1; ta->lines.first= ta->lines.last= NULL; - ta->markers.first= ta->markers.last= NULL; ta->curl= ta->sell= NULL; /* ta->flags= TXT_ISTMP | TXT_ISEXT; */ @@ -365,9 +348,6 @@ Text *add_text(char *file) len = fread(buffer, 1, len, fp); fclose(fp); - - res= stat(str, &st); - ta->mtime= st.st_mtime; ta->nlines=0; i=0; @@ -376,7 +356,7 @@ Text *add_text(char *file) if (buffer[i]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= NULL; + tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); if(llen) memcpy(tmp->line, &buffer[i-llen], llen); tmp->line[llen]=0; @@ -396,7 +376,7 @@ Text *add_text(char *file) if (llen!=0 || ta->nlines==0) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= NULL; + tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); if(llen) memcpy(tmp->line, &buffer[i-llen], llen); @@ -430,7 +410,6 @@ Text *copy_text(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP; tan->lines.first= tan->lines.last= NULL; - tan->markers.first= tan->markers.last= NULL; tan->curl= tan->sell= NULL; tan->nlines= ta->nlines; @@ -440,7 +419,7 @@ Text *copy_text(Text *ta) while (line) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(line->len+1, "textline_string"); - tmp->format= NULL; + tmp->format= MEM_mallocN(line->len+2, "Syntax_format"); strcpy(tmp->line, line->line); @@ -461,14 +440,14 @@ Text *copy_text(Text *ta) /* Editing utility functions */ /*****************************/ -static void make_new_line (TextLine *line, char *newline) +static void make_new_line (TextLine *line, char *newline, char *newformat) { if (line->line) MEM_freeN(line->line); if (line->format) MEM_freeN(line->format); line->line= newline; line->len= strlen(newline); - line->format= NULL; + line->format= newformat; } static TextLine *txt_new_line(char *str) @@ -479,7 +458,7 @@ static TextLine *txt_new_line(char *str) tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(strlen(str)+1, "textline_string"); - tmp->format= NULL; + tmp->format= MEM_mallocN(strlen(str)+2, "Syntax_format"); strcpy(tmp->line, str); @@ -497,7 +476,7 @@ static TextLine *txt_new_linen(char *str, int n) tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(n+1, "textline_string"); - tmp->format= NULL; + tmp->format= MEM_mallocN(n+2, "Syntax_format"); BLI_strncpy(tmp->line, str, n+1); @@ -574,19 +553,6 @@ static void txt_make_dirty (Text *text) if (text->compiled) BPY_free_compiled_text(text); } -/* 0:whitespace, 1:punct, 2:alphanumeric */ -static short txt_char_type (char ch) -{ - if (ch <= ' ') return 0; - if (ch <= '/') return 1; - if (ch <= '9') return 2; - if (ch <= '@') return 1; - if (ch <= 'Z') return 2; - if (ch <= '`') return 1; - if (ch <= 'z') return 2; - return 1; -} - /****************************/ /* Cursor utility functions */ /****************************/ @@ -640,7 +606,8 @@ void txt_move_up(Text *text, short sel) if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); } } else { - txt_move_bol(text, sel); + *charp= 0; + if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); } if(!sel) txt_pop_sel(text); @@ -665,7 +632,8 @@ void txt_move_down(Text *text, short sel) } else if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); } else { - txt_move_eol(text, sel); + *charp= (*linep)->len; + if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); } if(!sel) txt_pop_sel(text); @@ -721,68 +689,6 @@ void txt_move_right(Text *text, short sel) if(!sel) txt_pop_sel(text); } -void txt_jump_left(Text *text, short sel) -{ - TextLine **linep, *oldl; - int *charp, oldc, count, i; - unsigned char oldu; - - if (!text) return; - if(sel) txt_curs_sel(text, &linep, &charp); - else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } - if (!*linep) return; - - oldl= *linep; - oldc= *charp; - oldu= undoing; - undoing= 1; /* Don't push individual moves to undo stack */ - - count= 0; - for (i=0; i<3; i++) { - if (count < 2) { - while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) { - txt_move_left(text, sel); - count++; - } - } - } - if (count==0) txt_move_left(text, sel); - - undoing= oldu; - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); -} - -void txt_jump_right(Text *text, short sel) -{ - TextLine **linep, *oldl; - int *charp, oldc, count, i; - unsigned char oldu; - - if (!text) return; - if(sel) txt_curs_sel(text, &linep, &charp); - else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } - if (!*linep) return; - - oldl= *linep; - oldc= *charp; - oldu= undoing; - undoing= 1; /* Don't push individual moves to undo stack */ - - count= 0; - for (i=0; i<3; i++) { - if (count < 2) { - while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) { - txt_move_right(text, sel); - count++; - } - } - } - if (count==0) txt_move_right(text, sel); - - undoing= oldu; - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); -} - void txt_move_bol (Text *text, short sel) { TextLine **linep; @@ -854,11 +760,6 @@ void txt_move_eof (Text *text, short sel) } void txt_move_toline (Text *text, unsigned int line, short sel) -{ - txt_move_to(text, line, 0, sel); -} - -void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel) { TextLine **linep, *oldl; int *charp, oldc; @@ -876,12 +777,10 @@ void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel) if ((*linep)->next) *linep= (*linep)->next; else break; } - if (ch>(*linep)->len) - ch= (*linep)->len; - *charp= ch; + *charp= 0; if(!sel) txt_pop_sel(text); - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -966,9 +865,7 @@ int txt_has_sel(Text *text) static void txt_delete_sel (Text *text) { TextLine *tmpl; - TextMarker *mrk; - char *buf; - int move, lineno; + char *buf, *format; if (!text) return; if (!text->curl) return; @@ -985,33 +882,13 @@ static void txt_delete_sel (Text *text) } buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string"); + format= MEM_mallocN(text->curc+(text->sell->len - text->selc)+2, "Syntax_format"); - if (text->curl != text->sell) { - txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); - move= txt_get_span(text->curl, text->sell); - } else { - mrk= txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) - txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); - move= 0; - } - - mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0, 0); - if (mrk) { - lineno= mrk->lineno; - do { - mrk->lineno -= move; - if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; - mrk->end -= text->selc - text->curc; - mrk= mrk->next; - } while (mrk && mrk->lineno==lineno); - } - strncpy(buf, text->curl->line, text->curc); strcpy(buf+text->curc, text->sell->line + text->selc); buf[text->curc+(text->sell->len - text->selc)]=0; - make_new_line(text->curl, buf); + make_new_line(text->curl, buf, format); tmpl= text->sell; while (tmpl != text->curl) { @@ -1118,31 +995,22 @@ char *txt_to_buf (Text *text) return buf; } -int txt_find_string(Text *text, char *findstr, int wrap) +int txt_find_string(Text *text, char *findstr) { TextLine *tl, *startl; char *s= NULL; - int oldcl, oldsl, oldcc, oldsc; if (!text || !text->curl || !text->sell) return 0; txt_order_cursors(text); - oldcl= txt_get_span(text->lines.first, text->curl); - oldsl= txt_get_span(text->lines.first, text->sell); tl= startl= text->sell; - oldcc= text->curc; - oldsc= text->selc; s= strstr(&tl->line[text->selc], findstr); while (!s) { tl= tl->next; - if (!tl) { - if (wrap) - tl= text->lines.first; - else - break; - } + if (!tl) + tl= text->lines.first; s= strstr(tl->line, findstr); if (tl==startl) @@ -1150,10 +1018,10 @@ int txt_find_string(Text *text, char *findstr, int wrap) } if (s) { - int newl= txt_get_span(text->lines.first, tl); - int newc= (int)(s-tl->line); - txt_move_to(text, newl, newc, 0); - txt_move_to(text, newl, newc + strlen(findstr), 1); + text->curl= text->sell= tl; + text->curc= (int) (s-tl->line); + text->selc= text->curc + strlen(findstr); + return 1; } else return 0; @@ -1753,6 +1621,7 @@ void txt_do_undo(Text *text) case UNDO_SWAP: txt_curs_swap(text); + txt_do_undo(text); /* swaps should appear transparent */ break; case UNDO_DBLOCK: @@ -1867,19 +1736,6 @@ void txt_do_undo(Text *text) break; } - - /* next undo step may need evaluating */ - if (text->undo_pos>=0) { - switch (text->undo_buf[text->undo_pos]) { - case UNDO_STO: - txt_do_undo(text); - txt_do_redo(text); /* selections need restoring */ - break; - case UNDO_SWAP: - txt_do_undo(text); /* swaps should appear transparent */ - break; - } - } undoing= 0; } @@ -1954,7 +1810,7 @@ void txt_do_redo(Text *text) case UNDO_SWAP: txt_curs_swap(text); - txt_do_redo(text); /* swaps should appear transparent a*/ + txt_do_undo(text); /* swaps should appear transparent a*/ break; case UNDO_CTO: @@ -2091,37 +1947,22 @@ void txt_do_redo(Text *text) void txt_split_curline (Text *text) { TextLine *ins; - TextMarker *mrk; - char *left, *right; - int lineno= -1; + char *left, *right, *fleft, *fright; if (!text) return; if (!text->curl) return; - txt_delete_sel(text); - - /* Move markers */ - - lineno= txt_get_span(text->lines.first, text->curl); - mrk= text->markers.first; - while (mrk) { - if (mrk->lineno==lineno && mrk->start>text->curc) { - mrk->lineno++; - mrk->start -= text->curc; - mrk->end -= text->curc; - } else if (mrk->lineno > lineno) { - mrk->lineno++; - } - mrk= mrk->next; - } + txt_delete_sel(text); /* Make the two half strings */ left= MEM_mallocN(text->curc+1, "textline_string"); + fleft= MEM_mallocN(text->curc+2, "Syntax_format"); if (text->curc) memcpy(left, text->curl->line, text->curc); left[text->curc]=0; right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string"); + fright= MEM_mallocN(text->curl->len - text->curc+2, "Syntax_format"); if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc); right[text->curl->len - text->curc]=0; @@ -2132,11 +1973,11 @@ void txt_split_curline (Text *text) ins= MEM_mallocN(sizeof(TextLine), "textline"); ins->line= left; - ins->format= NULL; + ins->format= fleft; ins->len= text->curc; text->curl->line= right; - text->curl->format= NULL; + text->curl->format= fright; text->curl->len= text->curl->len - text->curc; BLI_insertlinkbefore(&text->lines, text->curl, ins); @@ -2152,23 +1993,9 @@ void txt_split_curline (Text *text) static void txt_delete_line (Text *text, TextLine *line) { - TextMarker *mrk=NULL, *nxt; - int lineno= -1; - if (!text) return; if (!text->curl) return; - lineno= txt_get_span(text->lines.first, line); - mrk= text->markers.first; - while (mrk) { - nxt= mrk->next; - if (mrk->lineno==lineno) - BLI_freelinkN(&text->markers, mrk); - else if (mrk->lineno > lineno) - mrk->lineno--; - mrk= nxt; - } - BLI_remlink (&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2182,35 +2009,21 @@ static void txt_delete_line (Text *text, TextLine *line) static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb) { - char *tmp; - TextMarker *mrk= NULL; - int lineno=-1; + char *tmp, *format; if (!text) return; if(!linea || !lineb) return; - - mrk= txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); - if (mrk) { - lineno= mrk->lineno; - do { - mrk->lineno--; - mrk->start += linea->len; - mrk->end += linea->len; - mrk= mrk->next; - } while (mrk && mrk->lineno==lineno); - } - if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb); - if (!mrk) mrk= text->markers.first; tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string"); + format= MEM_mallocN(linea->len+lineb->len+1, "Syntax_format"); strcpy(tmp, linea->line); strcat(tmp, lineb->line); - make_new_line(linea, tmp); + make_new_line(linea, tmp, format); - txt_delete_line(text, lineb); + txt_delete_line(text, lineb); txt_make_dirty(text); txt_clean_text(text); @@ -2224,9 +2037,8 @@ void txt_delete_char (Text *text) if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ - txt_delete_sel(text); - txt_make_dirty(text); - return; + txt_delete_sel(text); + return; } else if (text->curc== text->curl->len) { /* Appending two lines */ if (text->curl->next) { @@ -2235,25 +2047,6 @@ void txt_delete_char (Text *text) } } else { /* Just deleting a char */ int i= text->curc; - - TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0, 0); - if (mrk) { - int lineno= mrk->lineno; - if (mrk->end==i) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } else { - //TextMarker *nxt= mrk->next; - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start>i) mrk->start--; - mrk->end--; - mrk= mrk->next; - } while (mrk && mrk->lineno==lineno); - } c= text->curl->line[i]; while(i< text->curl->len) { @@ -2271,12 +2064,6 @@ void txt_delete_char (Text *text) if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c); } -void txt_delete_word (Text *text) -{ - txt_jump_right(text, 1); - txt_delete_sel(text); -} - void txt_backspace_char (Text *text) { char c='\n'; @@ -2285,9 +2072,8 @@ void txt_backspace_char (Text *text) if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ - txt_delete_sel(text); - txt_make_dirty(text); - return; + txt_delete_sel(text); + return; } else if (text->curc==0) { /* Appending two lines */ if (!text->curl->prev) return; @@ -2297,38 +2083,19 @@ void txt_backspace_char (Text *text) txt_combine_lines(text, text->curl, text->curl->next); txt_pop_sel(text); - } + } else { /* Just backspacing a char */ - int i= text->curc-1; - - TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0, 0); - if (mrk) { - int lineno= mrk->lineno; - if (mrk->start==i+1) { - if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { - txt_clear_markers(text, mrk->group, TMARK_TEMP); - } else { - //TextMarker *nxt= mrk->next; - BLI_freelinkN(&text->markers, mrk); - } - return; - } - do { - if (mrk->start>i) mrk->start--; - mrk->end--; - mrk= mrk->next; - } while (mrk && mrk->lineno==lineno); - } + int i= text->curc-1; - c= text->curl->line[i]; - while(i< text->curl->len) { - text->curl->line[i]= text->curl->line[i+1]; - i++; - } - text->curl->len--; - text->curc--; - - txt_pop_sel(text); + c= text->curl->line[i]; + while(i< text->curl->len) { + text->curl->line[i]= text->curl->line[i+1]; + i++; + } + text->curl->len--; + text->curc--; + + txt_pop_sel(text); } txt_make_dirty(text); @@ -2337,17 +2104,10 @@ void txt_backspace_char (Text *text) if(!undoing) txt_undo_add_charop(text, UNDO_BS, c); } -void txt_backspace_word (Text *text) -{ - txt_jump_left(text, 1); - txt_delete_sel(text); -} - int txt_add_char (Text *text, char add) { - int len, lineno; - char *tmp; - TextMarker *mrk; + int len; + char *tmp, *format; if (!text) return 0; if (!text->curl) return 0; @@ -2359,17 +2119,8 @@ int txt_add_char (Text *text, char add) txt_delete_sel(text); - mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0, 0); - if (mrk) { - lineno= mrk->lineno; - do { - if (mrk->start>text->curc) mrk->start++; - mrk->end++; - mrk= mrk->next; - } while (mrk && mrk->lineno==lineno); - } - tmp= MEM_mallocN(text->curl->len+2, "textline_string"); + format= MEM_mallocN(text->curl->len+4, "Syntax_format"); if(text->curc) memcpy(tmp, text->curl->line, text->curc); tmp[text->curc]= add; @@ -2377,7 +2128,7 @@ int txt_add_char (Text *text, char add) len= text->curl->len - text->curc; if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp); + make_new_line(text->curl, tmp, format); text->curc++; @@ -2390,42 +2141,10 @@ int txt_add_char (Text *text, char add) return 1; } -int txt_replace_char (Text *text, char add) -{ - char del; - - if (!text) return 0; - if (!text->curl) return 0; - - /* If text is selected or we're at the end of the line just use txt_add_char */ - if (text->curc==text->curl->len || txt_has_sel(text) || add=='\n') { - TextMarker *mrk; - int i= txt_add_char(text, add); - mrk= txt_find_marker(text, text->curl, text->curc, 0, 0); - if (mrk && mrk->end==text->curc) mrk->end--; - return i; - } - - del= text->curl->line[text->curc]; - text->curl->line[text->curc]= (unsigned char) add; - text->curc++; - txt_pop_sel(text); - - txt_make_dirty(text); - txt_clean_text(text); - - /* Should probably create a new op for this */ - if(!undoing) { - txt_undo_add_charop(text, UNDO_DEL, del); - txt_undo_add_charop(text, UNDO_INSERT, add); - } - return 1; -} - void indent(Text *text) { int len, num; - char *tmp; + char *tmp, *format; char add = '\t'; if (!text) return; @@ -2436,6 +2155,7 @@ void indent(Text *text) while (TRUE) { tmp= MEM_mallocN(text->curl->len+2, "textline_string"); + format= MEM_mallocN(text->curl->len+3, "Syntax_format"); text->curc = 0; if(text->curc) memcpy(tmp, text->curl->line, text->curc); @@ -2445,7 +2165,7 @@ void indent(Text *text) if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp); + make_new_line(text->curl, tmp, format); text->curc++; @@ -2526,7 +2246,7 @@ void unindent(Text *text) void comment(Text *text) { int len, num; - char *tmp; + char *tmp, *format; char add = '#'; if (!text) return; @@ -2537,6 +2257,7 @@ void comment(Text *text) while (TRUE) { tmp= MEM_mallocN(text->curl->len+2, "textline_string"); + format = MEM_mallocN(text->curl->len+3, "Syntax_format"); text->curc = 0; if(text->curc) memcpy(tmp, text->curl->line, text->curc); @@ -2546,7 +2267,7 @@ void comment(Text *text) if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp); + make_new_line(text->curl, tmp, format); text->curc++; @@ -2677,148 +2398,3 @@ int setcurr_tab (Text *text) return i; } -/*********************************/ -/* Text marker utility functions */ -/*********************************/ - -static int color_match(TextMarker *a, TextMarker *b) { - return (a->color[0]==b->color[0] && - a->color[1]==b->color[1] && - a->color[2]==b->color[2] && - a->color[3]==b->color[3]); -} - -/* Creates and adds a marker to the list maintaining sorted order */ -void txt_add_marker(Text *text, TextLine *line, int start, int end, char color[4], int group, int flags) { - TextMarker *tmp, *marker; - - marker= MEM_mallocN(sizeof(TextMarker), "text_marker"); - - marker->lineno= txt_get_span(text->lines.first, line); - marker->start= MIN2(start, end); - marker->end= MAX2(start, end); - marker->group= group; - marker->flags= flags; - - marker->color[0]= color[0]; - marker->color[1]= color[1]; - marker->color[2]= color[2]; - marker->color[3]= color[3]; - - for (tmp=text->markers.last; tmp; tmp=tmp->prev) - if (tmp->lineno < marker->lineno || (tmp->lineno==marker->lineno && tmp->start < marker->start)) - break; - - if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); - else BLI_addhead(&text->markers, marker); -} - -/* Returns the first matching marker on the specified line between two points. - If the group or flags fields are non-zero the returned flag must be in the - specified group and have at least the specified flags set. */ -TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) { - TextMarker *marker, *next; - int lineno= txt_get_span(text->lines.first, line); - - for (marker=text->markers.first; marker; marker=next) { - next= marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start==marker->end && start<=marker->start && marker->start<=end) || - (marker->startend>start)) - return marker; - } - return NULL; -} - -/* Clears all markers on the specified line between two points. If the group or - flags fields are non-zero the returned flag must be in the specified group - and have at least the specified flags set. */ -short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) { - TextMarker *marker, *next; - int lineno= txt_get_span(text->lines.first, line); - short cleared= 0; - - for (marker=text->markers.first; marker; marker=next) { - next= marker->next; - - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if ((marker->start==marker->end && start<=marker->start && marker->start<=end) || - (marker->startend>start)) { - BLI_freelinkN(&text->markers, marker); - cleared= 1; - } - } - return cleared; -} - -/* Clears all markers in the specified group (if given) with at least the - specified flags set. Useful for clearing temporary markers (group=0, - flags=TMARK_TEMP) */ -short txt_clear_markers(Text *text, int group, int flags) { - TextMarker *marker, *next; - short cleared= 0; - - for (marker=text->markers.first; marker; marker=next) { - next= marker->next; - - if ((!group || marker->group==group) && - (marker->flags & flags) == flags) { - BLI_freelinkN(&text->markers, marker); - cleared= 1; - } - } - return cleared; -} - -/* Finds the marker at the specified line and cursor position with at least the - specified flags set in the given group (if non-zero). */ -TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) { - TextMarker *marker; - int lineno= txt_get_span(text->lines.first, line); - - for (marker=text->markers.first; marker; marker=marker->next) { - if (group && marker->group != group) continue; - else if ((marker->flags & flags) != flags) continue; - else if (marker->lineno < lineno) continue; - else if (marker->lineno > lineno) break; - - if (marker->start <= curs && curs <= marker->end) - return marker; - } - return NULL; -} - -/* Finds the previous marker in the same group. If no other is found, the same - marker will be returned */ -TextMarker *txt_prev_marker(Text *text, TextMarker *marker) { - TextMarker *tmp= marker; - while (tmp) { - if (tmp->prev) tmp= tmp->prev; - else tmp= text->markers.last; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if marker==NULL */ -} - -/* Finds the next marker in the same group. If no other is found, the same - marker will be returned */ -TextMarker *txt_next_marker(Text *text, TextMarker *marker) { - TextMarker *tmp= marker; - while (tmp) { - if (tmp->next) tmp= tmp->next; - else tmp= text->markers.first; - if (tmp->group == marker->group) - return tmp; - } - return NULL; /* Only if marker==NULL */ -} diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index bb726887d32..936381c85cc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -53,7 +53,6 @@ #include "DNA_world_types.h" #include "DNA_brush_types.h" #include "DNA_node_types.h" -#include "DNA_color_types.h" #include "DNA_scene_types.h" #include "IMB_imbuf_types.h" @@ -391,17 +390,6 @@ int do_colorband(ColorBand *coba, float in, float out[4]) return 1; /* OK */ } -void colorband_table_RGBA(ColorBand *coba, float **array, int *size) -{ - int a; - - *size = CM_TABLE+1; - *array = MEM_callocN(sizeof(float)*(*size)*4, "ColorBand"); - - for(a=0; a<*size; a++) - do_colorband(coba, (float)a/(float)CM_TABLE, &(*array)[a*4]); -} - /* ******************* TEX ************************ */ void free_texture(Tex *tex) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 6e54fae58d0..c22b6f79e08 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -164,7 +164,6 @@ void Mat3Inv(float m1[][3], float m2[][3]); void Mat3CpyMat4(float m1[][3],float m2[][4]); void Mat4CpyMat3(float m1[][4], float m2[][3]); -void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight); void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight); float Det2x2(float a,float b,float c, float d); @@ -261,7 +260,6 @@ void Vec2Mulf(float *v1, float f); void Vec2Addf(float *v, float *v1, float *v2); void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); -void Vec2Lerpf(float *target, float *a, float *b, float t); void AxisAngleToQuat(float *q, float *axis, float angle); void vectoquat(float *vec, short axis, short upflag, float *q); diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index a1db7adf33d..e24ccad12fb 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -73,6 +73,7 @@ extern ListBase fillvertbase; * @attention Defined in scanfill.c */ extern ListBase filledgebase; +extern int totblock; extern char btempdir[]; /* creator.c temp dir used instead of U.tempdir, set with BLI_where_is_temp( btempdir, 1 ); */ @@ -151,7 +152,6 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds */ int BLI_convertstringcode(char *path, const char *basepath); int BLI_convertstringframe(char *path, int frame); -int BLI_convertstringcwd(char *path); void BLI_makestringcode(const char *relfile, char *file); diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index e3591a84e98..6d9a17efebf 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -54,7 +54,6 @@ typedef struct BVHTreeRay { float origin[3]; /* ray origin */ float direction[3]; /* ray direction */ - float radius; /* radius around ray */ } BVHTreeRay; typedef struct BVHTreeRayHit @@ -91,7 +90,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index 65cebf02f62..649d3cb5659 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -24,4 +24,4 @@ if env['OURPLATFORM'] == 'linux2': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core', 'intern', 'player'], priority = [85,150,195], compileflags =cflags ) +env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [85,195], compileflags =cflags ) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 30472beb3e6..c41c3d8c3ab 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -51,7 +51,6 @@ typedef struct BVHNode { struct BVHNode **children; - struct BVHNode *parent; // some user defined traversed need that 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 @@ -83,7 +82,7 @@ typedef struct BVHOverlapData typedef struct BVHNearestData { BVHTree *tree; - const float *co; + float *co; BVHTree_NearestPointCallback callback; void *userdata; float proj[13]; //coordinates projection over axis @@ -482,7 +481,7 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; for(i=0; iindex, node - tree->nodearray); + printf(" - %d (%d): ", node->index, node - tree->nodearray); for(i=2*tree->start_axis; i<2*tree->stop_axis; i++) printf("%.3f ", node->bv[i]); printf("\n"); @@ -497,10 +496,10 @@ static void bvhtree_info(BVHTree *tree) printf("BVHTree info\n"); printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); + printf("Memory per node = %dbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv)); - printf("Total memory = %ldbytes\n", sizeof(BVHTree) + printf("Total memory = %dbytes\n", sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + MEM_allocN_len(tree->nodechild) @@ -701,10 +700,6 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHBuildHelper data; int depth; - - // set parent from root node to NULL - BVHNode *tmp = branches_array+0; - tmp->parent = NULL; //Most of bvhtree code relies on 1-leaf trees having at least one branch //We handle that special case here @@ -714,8 +709,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, refit_kdop_hull(tree, root, 0, num_leafs); root->main_axis = get_largest_axis(root->bv) / 2; root->totnode = 1; - root->children[0] = leafs_array[0]; - root->children[0]->parent = root; + root->children[0] = leafs_array[0]; return; } @@ -778,15 +772,9 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); if(child_leafs_end - child_leafs_begin > 1) - { parent->children[k] = branches_array + child_index; - parent->children[k]->parent = parent; - } else if(child_leafs_end - child_leafs_begin == 1) - { parent->children[k] = leafs_array[ child_leafs_begin ]; - parent->children[k]->parent = parent; - } else break; @@ -1108,7 +1096,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) BVHOverlapData **data; // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) - if((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18)) + if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) return 0; // fast check root nodes for collision before doing big splitting + traversal @@ -1260,6 +1248,7 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) { + int i; float nearest[3], sdist; sdist = calc_nearest_point(data, node, nearest); if(sdist >= data->nearest.dist) return; @@ -1414,14 +1403,14 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) if(data->ray_dot_axis[i] == 0.0f) { //axis aligned ray - if(data->ray.origin[i] < bv[0] - data->ray.radius - || data->ray.origin[i] > bv[1] + data->ray.radius) + if(data->ray.origin[i] < bv[0] + || data->ray.origin[i] > bv[1]) return FLT_MAX; } else { - float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; if(data->ray_dot_axis[i] > 0.0f) { @@ -1480,7 +1469,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; @@ -1493,7 +1482,6 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float VECCOPY(data.ray.origin, co); VECCOPY(data.ray.direction, dir); - data.ray.radius = radius; Normalize(data.ray.direction); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 844c0cc909a..c1edb7d3ac1 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -758,28 +758,6 @@ void Mat4MulSerie(float answ[][4], float m1[][4], } } -void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight) -{ - float squat[4], dquat[4], fquat[4]; - float ssize[3], dsize[3], fsize[4]; - float rmat[3][3], smat[3][3]; - - Mat3ToQuat(dst, dquat); - Mat3ToSize(dst, dsize); - - Mat3ToQuat(src, squat); - Mat3ToSize(src, ssize); - - /* do blending */ - QuatInterpol(fquat, dquat, squat, srcweight); - VecLerpf(fsize, dsize, ssize, srcweight); - - /* compose new matrix */ - QuatToMat3(fquat, rmat); - SizeToMat3(fsize, smat); - Mat3MulMat3(out, rmat, smat); -} - void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight) { float squat[4], dquat[4], fquat[4]; @@ -2134,14 +2112,6 @@ void VecLerpf(float *target, float *a, float *b, float t) target[2]= s*a[2] + t*b[2]; } -void Vec2Lerpf(float *target, float *a, float *b, float t) -{ - float s = 1.0f-t; - - target[0]= s*a[0] + t*b[0]; - target[1]= s*a[1] + t*b[1]; -} - void VecMidf(float *v, float *v1, float *v2) { v[0]= 0.5f*(v1[0]+ v2[0]); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index c27efcb7934..a31121148e3 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1211,49 +1211,6 @@ int BLI_convertstringcode(char *path, const char *basepath) return wasrelative; } - -/* - * Should only be done with command line paths. - * this is NOT somthing blenders internal paths support like the // prefix - */ -int BLI_convertstringcwd(char *path) -{ - int wasrelative = 1; - int filelen = strlen(path); - -#ifdef WIN32 - if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) - wasrelative = 0; -#else - if (filelen >= 2 && path[0] == '/') - wasrelative = 0; -#endif - - if (wasrelative==1) { - char cwd[FILE_MAXDIR + FILE_MAXFILE]; - BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ - - if (cwd[0] == '\0') { - printf( "Could not get the current working directory - $PWD for an unknown reason."); - } else { - /* uses the blend path relative to cwd important for loading relative linked files. - * - * cwd should contain c:\ etc on win32 so the relbase can be NULL - * relbase being NULL also prevents // being misunderstood as relative to the current - * blend file which isnt a feature we want to use in this case since were dealing - * with a path from the command line, rather then from inside Blender */ - - char origpath[FILE_MAXDIR + FILE_MAXFILE]; - BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE); - - BLI_make_file_string(NULL, path, cwd, origpath); - } - } - - return wasrelative; -} - - /* copy di to fi, filename only */ void BLI_splitdirstring(char *di, char *fi) { diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 4aa2a229dcc..ff2a256f606 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -237,7 +237,7 @@ void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode); void BLO_library_append_(BlendHandle **libfiledata, struct direntry* filelist, int totfile, char *dir, char* file, short flag, int idcode); void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Scene *scene); -BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r); +BlendFileData* blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r); #ifdef __cplusplus } diff --git a/source/blender/blenloader/BLO_sys_types.h b/source/blender/blenloader/BLO_sys_types.h index 49155260b31..a9d29375eac 100644 --- a/source/blender/blenloader/BLO_sys_types.h +++ b/source/blender/blenloader/BLO_sys_types.h @@ -49,7 +49,6 @@ extern "C" { /* The __intXX are built-in types of the visual complier! So we don't * need to include anything else here. */ - typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; @@ -60,23 +59,13 @@ typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; -#ifndef _INTPTR_T_DEFINED #ifdef _WIN64 typedef __int64 intptr_t; -#else -typedef long intptr_t; -#endif -#define _INTPTR_T_DEFINED -#endif - -#ifndef _UINTPTR_T_DEFINED -#ifdef _WIN64 typedef unsigned __int64 uintptr_t; #else +typedef long intptr_t; typedef unsigned long uintptr_t; #endif -#define _UINTPTR_T_DEFINED -#endif #elif defined(__linux__) @@ -98,7 +87,6 @@ typedef unsigned long uintptr_t; #endif /* ifdef platform for types */ - #ifdef _WIN32 #define htonl(x) correctByteOrder(x) #define ntohl(x) correctByteOrder(x) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8e792426998..35ca42a4949 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -970,11 +970,9 @@ FileData *blo_openblenderfile(char *name, BlendReadError *error_r) } else { FileData *fd = filedata_new(); fd->gzfiledes = gzfile; + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); // now only in use by library append fd->read = fd_read_gzip_from_file; - /* needed for library_append and read_libraries */ - BLI_strncpy(fd->filename, name, sizeof(fd->filename)); - return blo_decode_and_check(fd, error_r); } } @@ -1140,8 +1138,6 @@ void blo_make_image_pointer_map(FileData *fd) Link *ibuf= ima->ibufs.first; for(; ibuf; ibuf= ibuf->next) oldnewmap_insert(fd->imamap, ibuf, ibuf, 0); - if(ima->gputexture) - oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -1176,11 +1172,8 @@ void blo_end_image_pointer_map(FileData *fd) if(NULL==newimaadr(fd, ibuf)) { /* so was restored */ BLI_remlink(&ima->ibufs, ibuf); ima->bindcode= 0; - ima->gputexture= NULL; } } - - ima->gputexture= newimaadr(fd, ima->gputexture); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -2287,7 +2280,6 @@ static void direct_link_text(FileData *fd, Text *text) */ link_list(fd, &text->lines); - link_list(fd, &text->markers); text->curl= newdataadr(fd, text->curl); text->sell= newdataadr(fd, text->sell); @@ -2354,10 +2346,8 @@ static void direct_link_image(FileData *fd, Image *ima) ima->ibufs.first= ima->ibufs.last= NULL; /* if not restored, we keep the binded opengl index */ - if(ima->ibufs.first==NULL) { + if(ima->ibufs.first==NULL) ima->bindcode= 0; - ima->gputexture= NULL; - } ima->anim= NULL; ima->rr= NULL; @@ -2568,7 +2558,6 @@ static void direct_link_material(FileData *fd, Material *ma) direct_link_nodetree(fd, ma->nodetree); ma->preview = direct_link_preview_image(fd, ma->preview); - ma->gpumaterial.first = ma->gpumaterial.last = NULL; } /* ************ READ PARTICLE SETTINGS ***************** */ @@ -3407,7 +3396,6 @@ static void direct_link_object(FileData *fd, Object *ob) ob->bb= NULL; ob->derivedDeform= NULL; ob->derivedFinal= NULL; - ob->gpulamp.first= ob->gpulamp.last= NULL; } /* ************ READ SCENE ***************** */ @@ -4182,9 +4170,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sima->cumap= newdataadr(fd, sima->cumap); if(sima->cumap) direct_link_curvemapping(fd, sima->cumap); - sima->gpd= newdataadr(fd, sima->gpd); - if (sima->gpd) - link_gpencil(fd, sima->gpd); sima->iuser.ok= 1; } else if(sl->spacetype==SPACE_NODE) { @@ -7769,14 +7754,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) { + if(main->versionfile <= 246 && main->subversionfile < 1){ Mesh *me; for(me=main->mesh.first; me; me= me->id.next) alphasort_version_246(fd, lib, me); } - if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)){ + if(main->versionfile <= 246 && main->subversionfile < 1){ Object *ob; for(ob = main->object.first; ob; ob= ob->id.next) { if(ob->pd && (ob->pd->forcefield == PFIELD_WIND)) @@ -7784,14 +7769,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 2)){ - Object *ob; - for(ob = main->object.first; ob; ob= ob->id.next) { - ob->gameflag |= OB_PHYSICS; - ob->margin = 0.06; - } - } - /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ @@ -9147,7 +9124,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) /* reading runtime */ -BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r) +BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r) { BlendFileData *bfd = NULL; FileData *fd = filedata_new(); @@ -9155,9 +9132,6 @@ BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize, fd->buffersize = actualsize; fd->read = fd_read_from_file; - /* needed for library_append and read_libraries */ - BLI_strncpy(fd->filename, name, sizeof(fd->filename)); - fd = blo_decode_and_check(fd, error_r); if (!fd) return NULL; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 44634a7468c..d596f57990f 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1698,9 +1698,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceImage", 1, sl); if(sima->cumap) - write_curvemapping(wd, sima->cumap); - if(sima->gpd) - write_gpencil(wd, sima->gpd); + write_curvemapping(wd, sima->cumap); } else if(sl->spacetype==SPACE_IMASEL) { writestruct(wd, DATA, "SpaceImaSel", 1, sl); @@ -1851,7 +1849,6 @@ static void write_texts(WriteData *wd, ListBase *idbase) { Text *text; TextLine *tmp; - TextMarker *mrk; text= idbase->first; while(text) { @@ -1875,16 +1872,7 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } - - /* write markers */ - mrk= text->markers.first; - while (mrk) { - writestruct(wd, DATA, "TextMarker", 1, mrk); - mrk= mrk->next; - } } - - text= text->id.next; } diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt deleted file mode 100644 index 4d376f47d91..00000000000 --- a/source/blender/gpu/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ -# ***** 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/*.c) - -SET(INC - . ../blenlib ../blenkernel ../makesdna ../include - ../../../extern/glew/include ../../../intern/guardedalloc ../imbuf) - -BLENDERLIB(bf_gpu "${SRC}" "${INC}") - diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h deleted file mode 100644 index 2399e7b6a8c..00000000000 --- a/source/blender/gpu/GPU_draw.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef GPU_GAME_H -#define GPU_GAME_H - -#ifdef __cplusplus -extern "C" { -#endif - -struct MTFace; -struct Image; -struct Scene; -struct Object; - -/* OpenGL drawing functions related to shading. These are also - * shared with the game engine, where there were previously - * duplicates of some of these functions. */ - -/* Initialize - * - sets the default Blender opengl state, if in doubt, check - * the contents of this function - * - this is called when starting Blender, for opengl rendering, - * and for switching back from the game engine for example. */ - -void GPU_state_init(void); - -/* Material drawing - * - first the state is initialized by a particular object and - * it's materials - * - after this, materials can be quickly enabled by their number, - * GPU_enable_material returns 0 if drawing should be skipped - * - after drawing, the material must be disabled again */ - -void GPU_set_object_materials(struct Scene *scene, struct Object *ob, - int glsl, int *do_alpha_pass); -int GPU_enable_material(int nr, void *attribs); -void GPU_disable_material(void); - -void GPU_set_material_blend_mode(int blendmode); -int GPU_get_material_blend_mode(void); - -/* TexFace drawing - * - this is mutually exclusive with material drawing, a mesh should - * be drawn using one or the other - * - passing NULL clears the state again */ - -int GPU_set_tpage(struct MTFace *tface); - -/* Lights - * - returns how many lights were enabled - * - this affects fixed functions materials and texface, not glsl */ - -int GPU_default_lights(void); -int GPU_scene_object_lights(struct Scene *scene, struct Object *ob, - int lay, float viewmat[][4]); - -/* Text render - * - based on moving uv coordinates */ - -void GPU_render_text(struct MTFace *tface, int mode, - const char *textstr, int textlen, unsigned int *col, - float *v1, float *v2, float *v3, float *v4, int glattrib); - -/* Mipmap settings - * - these will free textures on changes */ - -void GPU_set_mipmap(int mipmap); -void GPU_set_linear_mipmap(int linear); -void GPU_paint_set_mipmap(int mipmap); - -/* Image updates and free - * - these deal with images bound as opengl textures */ - -void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h); -void GPU_update_images_framechange(void); -int GPU_update_image_time(struct Image *ima, double time); -int GPU_verify_image(struct Image *ima, int tftile, int tfmode, int compare); -void GPU_free_image(struct Image *ima); -void GPU_free_images(void); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h deleted file mode 100644 index d3faa81ebb1..00000000000 --- a/source/blender/gpu/GPU_extensions.h +++ /dev/null @@ -1,144 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef GPU_EXTENSIONS_H -#define GPU_EXTENSIONS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* GPU extensions support */ - -struct Image; -struct ImageUser; - -struct GPUTexture; -typedef struct GPUTexture GPUTexture; - -struct GPUFrameBuffer; -typedef struct GPUFrameBuffer GPUFrameBuffer; - -struct GPUShader; -typedef struct GPUShader GPUShader; - -void GPU_extensions_init(void); /* call this before running any of the functions below */ -void GPU_extensions_exit(void); -int GPU_extensions_minimum_support(void); -int GPU_print_error(char *str); - -/* GPU Texture - - always returns unsigned char RGBA textures - - if texture with non square dimensions is created, depending on the - graphics card capabilities the texture may actually be stored in a - larger texture with power of two dimensions. the actual dimensions - may be querd with GPU_texture_opengl_width/height. GPU_texture_coord_2f - calls glTexCoord2f with the coordinates adjust for this. - - can use reference counting: - - reference counter after GPU_texture_create is 1 - - GPU_texture_ref increases by one - - GPU_texture_free decreases by one, and frees if 0 - - if created with from_blender, will not free the texture -*/ - -GPUTexture *GPU_texture_create_1D(int w, float *pixels); -GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels); -GPUTexture *GPU_texture_create_depth(int w, int h); -GPUTexture *GPU_texture_from_blender(struct Image *ima, - struct ImageUser *iuser, double time); -void GPU_texture_free(GPUTexture *tex); - -void GPU_texture_ref(GPUTexture *tex); - -void GPU_texture_bind(GPUTexture *tex, int number); -void GPU_texture_unbind(GPUTexture *tex); - -GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); - -int GPU_texture_target(GPUTexture *tex); -int GPU_texture_opengl_width(GPUTexture *tex); -int GPU_texture_opengl_height(GPUTexture *tex); - -/* GPU Framebuffer - - this is a wrapper for an OpenGL framebuffer object (FBO). in practice - multiple FBO's may be created, to get around limitations on the number - of attached textures and the dimension requirements. - - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must - be called before rendering to the window framebuffer again */ - -GPUFrameBuffer *GPU_framebuffer_create(); -int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex); -void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex); -void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex); -void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex); -void GPU_framebuffer_free(GPUFrameBuffer *fb); - -void GPU_framebuffer_restore(); - -/* GPU Shader - - only for fragment shaders now - - must call texture bind before setting a texture as uniform! */ - -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib); -GPUShader *GPU_shader_create_lib(const char *code); -void GPU_shader_free(GPUShader *shader); - -void GPU_shader_bind(GPUShader *shader); -void GPU_shader_unbind(); - -int GPU_shader_get_uniform(GPUShader *shader, char *name); -void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, - int arraysize, float *value); -void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex); - -int GPU_shader_get_attribute(GPUShader *shader, char *name); - -/* Vertex attributes for shaders */ - -#define GPU_MAX_ATTRIB 32 - -typedef struct GPUVertexAttribs { - struct { - int type; - int glindex; - char name[32]; - } layer[GPU_MAX_ATTRIB]; - - int totlayer; -} GPUVertexAttribs; - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h deleted file mode 100644 index ccc687858f4..00000000000 --- a/source/blender/gpu/GPU_material.h +++ /dev/null @@ -1,169 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __GPU_MATERIAL__ -#define __GPU_MATERIAL__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct Image; -struct ImageUser; -struct Material; -struct Object; -struct Lamp; -struct bNode; -struct LinkNode; -struct Scene; -struct GPUVertexAttribs; -struct GPUNode; -struct GPUNodeLink; -struct GPUNodeStack; -struct GPUMaterial; -struct GPUTexture; -struct GPULamp; - -typedef struct GPUNode GPUNode; -typedef struct GPUNodeLink GPUNodeLink; -typedef struct GPUMaterial GPUMaterial; -typedef struct GPULamp GPULamp; - -/* Functions to create GPU Materials nodes */ - -typedef enum GPUType { - GPU_NONE = 0, - GPU_FLOAT = 1, - GPU_VEC2 = 2, - GPU_VEC3 = 3, - GPU_VEC4 = 4, - GPU_MAT3 = 9, - GPU_MAT4 = 16, - GPU_TEX1D = 1001, - GPU_TEX2D = 1002, - GPU_SHADOW2D = 1003, - GPU_ATTRIB = 3001 -} GPUType; - -typedef enum GPUBuiltin { - GPU_VIEW_MATRIX = 1, - GPU_OBJECT_MATRIX = 2, - GPU_INVERSE_VIEW_MATRIX = 4, - GPU_INVERSE_OBJECT_MATRIX = 8, - GPU_VIEW_POSITION = 16, - GPU_VIEW_NORMAL = 32, - GPU_OBCOLOR = 64 -} GPUBuiltin; - -typedef enum GPUBlendMode { - GPU_BLEND_SOLID = 0, - GPU_BLEND_ADD = 1, - GPU_BLEND_ALPHA = 2, - GPU_BLEND_CLIP = 4 -} GPUBlendMode; - -typedef struct GPUNodeStack { - GPUType type; - char *name; - float vec[4]; - struct GPUNodeLink *link; - short hasinput; - short hasoutput; - short sockettype; -} GPUNodeStack; - -GPUNodeLink *GPU_attribute(int type, char *name); -GPUNodeLink *GPU_uniform(float *num); -GPUNodeLink *GPU_dynamic_uniform(float *num); -GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser); -GPUNodeLink *GPU_texture(int size, float *pixels); -GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex); -GPUNodeLink *GPU_socket(GPUNodeStack *sock); -GPUNodeLink *GPU_builtin(GPUBuiltin builtin); - -int GPU_link(GPUMaterial *mat, char *name, ...); -int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...); - -void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); -void GPU_material_enable_alpha(GPUMaterial *material); -GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[4]); - -/* High level functions to create and use GPU materials */ - -GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma); -void GPU_material_free(struct Material *ma); - -void GPU_materials_free(); - -void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time); -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]); -void GPU_material_unbind(GPUMaterial *material); -int GPU_material_bound(GPUMaterial *material); - -void GPU_material_vertex_attributes(GPUMaterial *material, - struct GPUVertexAttribs *attrib); - -/* Exported shading */ - -typedef struct GPUShadeInput { - GPUMaterial *gpumat; - struct Material *mat; - - GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref; - GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb; -} GPUShadeInput; - -typedef struct GPUShadeResult { - GPUNodeLink *diff, *spec, *combined, *alpha; -} GPUShadeResult; - -void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi); -void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr); - -/* Lamps */ - -GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par); -void GPU_lamp_free(struct Object *ob); - -int GPU_lamp_has_shadow_buffer(GPULamp *lamp); -void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]); -void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); - -void GPU_lamp_update(GPULamp *lamp, int lay, float obmat[][4]); -int GPU_lamp_shadow_layer(GPULamp *lamp); - -#ifdef __cplusplus -} -#endif - -#endif /*__GPU_MATERIAL__*/ - diff --git a/source/blender/gpu/Makefile b/source/blender/gpu/Makefile deleted file mode 100644 index b9bde147115..00000000000 --- a/source/blender/gpu/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -# -# $Id$ -# -# ***** 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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL/BL DUAL LICENSE BLOCK ***** -# -# Makes module object directory and bounces make to subdirectories. - -SOURCEDIR = source/blender/gpu -DIRS = intern - -include nan_subdirs.mk diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript deleted file mode 100644 index 8ccd4b7b24c..00000000000 --- a/source/blender/gpu/SConscript +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/python -Import ('env') - -sources = env.Glob('intern/*.c') - -incs = '../blenlib ../blenkernel ../makesdna ../include' -incs += ' #/extern/glew/include #intern/guardedalloc ../imbuf .' - -incs += ' ' + env['BF_OPENGL_INC'] - -env.BlenderLib ( 'bf_gpu', sources, Split(incs), [], libtype=['core', 'player'], priority=[65, 20] ) diff --git a/source/blender/gpu/intern/Makefile b/source/blender/gpu/intern/Makefile deleted file mode 100644 index 733ee3f764c..00000000000 --- a/source/blender/gpu/intern/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# -# $Id$ -# -# ***** 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. -# -# The Original Code is: all of this file. -# -# Contributor(s): none yet. -# -# ***** END GPL/BL DUAL LICENSE BLOCK ***** -# - -LIBNAME = gpu -DIR = $(OCGDIR)/blender/$(LIBNAME) - -include nan_compile.mk - -ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) - CFLAGS += -funsigned-char -endif - -CFLAGS += $(LEVEL_1_C_WARNINGS) - -CPPFLAGS += -I$(OPENGL_HEADERS) - -CPPFLAGS += -I../../blenlib -CPPFLAGS += -I../../makesdna -CPPFLAGS += -I../../imbuf -CPPFLAGS += -I../../blenkernel -CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -CPPFLAGS += -I$(NAN_GLEW)/include -CPPFLAGS += -I../ - diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c deleted file mode 100644 index 00efe6e1572..00000000000 --- a/source/blender/gpu/intern/gpu_codegen.c +++ /dev/null @@ -1,1441 +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. 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "GL/glew.h" - -#include "MEM_guardedalloc.h" - -#include "DNA_customdata_types.h" -#include "DNA_image_types.h" -#include "DNA_listBase.h" -#include "DNA_material_types.h" - -#include "BLI_dynstr.h" -#include "BLI_blenlib.h" -#include "BLI_ghash.h" -#include "BLI_heap.h" - -#include "BKE_global.h" -#include "BKE_utildefines.h" - -#include "GPU_material.h" -#include "GPU_extensions.h" - -#include "BLO_sys_types.h" // for intptr_t support - -#include "gpu_codegen.h" - -#include -#include - -#ifdef _WIN32 -#ifndef vsnprintf -#define vsnprintf _vsnprintf -#endif -#ifndef snprintf -#define snprintf _snprintf -#endif -#endif - -extern char datatoc_gpu_shader_material_glsl[]; -extern char datatoc_gpu_shader_vertex_glsl[]; - -/* structs and defines */ - -typedef enum GPUDataSource { - GPU_SOURCE_VEC_UNIFORM, - GPU_SOURCE_BUILTIN, - GPU_SOURCE_TEX_PIXEL, - GPU_SOURCE_TEX, - GPU_SOURCE_ATTRIB -} GPUDataSource; - -static char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", - 0, 0, 0, 0, "mat3", 0, 0, 0, 0, 0, 0, "mat4"}; - -struct GPUNode { - struct GPUNode *next, *prev; - - char *name; - int tag; - - ListBase inputs; - ListBase outputs; -}; - -struct GPUNodeLink { - GPUNodeStack *socket; - - int attribtype; - char *attribname; - - int image; - - int texture; - int texturesize; - - void *ptr1, *ptr2; - - int dynamic; - - int type; - int users; - - GPUTexture *dynamictex; - - GPUBuiltin builtin; - - struct GPUOutput *output; -}; - -typedef struct GPUOutput { - struct GPUOutput *next, *prev; - - GPUNode *node; - int type; /* data type = length of vector/matrix */ - GPUNodeLink *link; /* output link */ - int id; /* unique id as created by code generator */ -} GPUOutput; - -typedef struct GPUInput { - struct GPUInput *next, *prev; - - GPUNode *node; - - int type; /* datatype */ - int source; /* data source */ - - int id; /* unique id as created by code generator */ - int texid; /* number for multitexture */ - int attribid; /* id for vertex attributes */ - int bindtex; /* input is responsible for binding the texture? */ - int definetex; /* input is responsible for defining the pixel? */ - int textarget; /* GL_TEXTURE_* */ - int textype; /* datatype */ - - struct Image *ima; /* image */ - struct ImageUser *iuser;/* image user */ - float *dynamicvec; /* vector data in case it is dynamic */ - GPUTexture *tex; /* input texture, only set at runtime */ - int shaderloc; /* id from opengl */ - char shadername[32]; /* name in shader */ - - float vec[16]; /* vector data */ - GPUNodeLink *link; - int dynamictex; /* dynamic? */ - int attribtype; /* attribute type */ - char attribname[32]; /* attribute name */ - int attribfirst; /* this is the first one that is bound */ - GPUBuiltin builtin; /* builtin uniform */ -} GPUInput; - -struct GPUPass { - struct GPUPass *next, *prev; - - ListBase inputs; - struct GPUOutput *output; - struct GPUShader *shader; -}; - -/* Strings utility */ - -static void BLI_dynstr_printf(DynStr *dynstr, const char *format, ...) -{ - va_list args; - int retval; - char str[2048]; - - va_start(args, format); - retval = vsnprintf(str, sizeof(str), format, args); - va_end(args); - - if (retval >= sizeof(str)) - fprintf(stderr, "BLI_dynstr_printf: limit exceeded\n"); - else - BLI_dynstr_append(dynstr, str); -} - -/* GLSL code parsing for finding function definitions. - * These are stored in a hash for lookup when creating a material. */ - -static GHash *FUNCTION_HASH= NULL; -static char *FUNCTION_PROTOTYPES= NULL; -static GPUShader *FUNCTION_LIB= NULL; - -static int gpu_str_prefix(char *str, char *prefix) -{ - while(*str && *prefix) { - if(*str != *prefix) - return 0; - - str++; - prefix++; - } - - return (*prefix == '\0'); -} - -static char *gpu_str_skip_token(char *str, char *token, int max) -{ - int len = 0; - - /* skip a variable/function name */ - while(*str) { - if(ELEM6(*str, ' ', '(', ')', ',', '\t', '\n')) - break; - else { - if(token && len < max-1) { - *token= *str; - token++; - len++; - } - str++; - } - } - - if(token) - *token= '\0'; - - /* skip the next special characters: - * note the missing ')' */ - while(*str) { - if(ELEM5(*str, ' ', '(', ',', '\t', '\n')) - str++; - else - break; - } - - return str; -} - -static void gpu_parse_functions_string(GHash *hash, char *code) -{ - GPUFunction *function; - int i, type, qual; - - while((code = strstr(code, "void "))) { - function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); - - code = gpu_str_skip_token(code, NULL, 0); - code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME); - - /* get parameters */ - while(*code && *code != ')') { - /* test if it's an input or output */ - qual = FUNCTION_QUAL_IN; - if(gpu_str_prefix(code, "out ")) - qual = FUNCTION_QUAL_OUT; - if(gpu_str_prefix(code, "inout ")) - qual = FUNCTION_QUAL_INOUT; - if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in ")) - code = gpu_str_skip_token(code, NULL, 0); - - /* test for type */ - type= 0; - for(i=1; i<=16; i++) { - if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) { - type= i; - break; - } - } - - if(!type && gpu_str_prefix(code, "sampler2DShadow")) - type= GPU_SHADOW2D; - if(!type && gpu_str_prefix(code, "sampler1D")) - type= GPU_TEX1D; - if(!type && gpu_str_prefix(code, "sampler2D")) - type= GPU_TEX2D; - - if(type) { - /* add paramater */ - code = gpu_str_skip_token(code, NULL, 0); - code = gpu_str_skip_token(code, NULL, 0); - function->paramqual[function->totparam]= qual; - function->paramtype[function->totparam]= type; - function->totparam++; - } - else { - fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name); - break; - } - } - - if(strlen(function->name) == 0 || function->totparam == 0) { - fprintf(stderr, "GPU functions parse error.\n"); - MEM_freeN(function); - break; - } - - BLI_ghash_insert(hash, function->name, function); - } -} - -static char *gpu_generate_function_prototyps(GHash *hash) -{ - DynStr *ds = BLI_dynstr_new(); - GHashIterator *ghi; - GPUFunction *function; - char *name, *prototypes; - int a; - - /* automatically generate function prototypes to add to the top of the - * generated code, to avoid have to add the actual code & recompile all */ - ghi = BLI_ghashIterator_new(hash); - - for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) { - name = BLI_ghashIterator_getValue(ghi); - function = BLI_ghashIterator_getValue(ghi); - - BLI_dynstr_printf(ds, "void %s(", name); - for(a=0; atotparam; a++) { - if(function->paramqual[a] == FUNCTION_QUAL_OUT) - BLI_dynstr_append(ds, "out "); - else if(function->paramqual[a] == FUNCTION_QUAL_INOUT) - BLI_dynstr_append(ds, "inout "); - - if(function->paramtype[a] == GPU_TEX1D) - BLI_dynstr_append(ds, "sampler1D"); - else if(function->paramtype[a] == GPU_TEX2D) - BLI_dynstr_append(ds, "sampler2D"); - else if(function->paramtype[a] == GPU_SHADOW2D) - BLI_dynstr_append(ds, "sampler2DShadow"); - else - BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); - - BLI_dynstr_printf(ds, " param%d", a); - - if(a != function->totparam-1) - BLI_dynstr_append(ds, ", "); - } - BLI_dynstr_append(ds, ");\n"); - } - - BLI_dynstr_append(ds, "\n"); - - prototypes = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - return prototypes; -} - -GPUFunction *GPU_lookup_function(char *name) -{ - if(!FUNCTION_HASH) { - FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); - gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl); - FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH); - FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl); - } - - return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, name); -} - -void GPU_extensions_exit(void) -{ - extern Material defmaterial; // render module abuse... - - if(defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial); - - if(FUNCTION_HASH) { - BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN); - FUNCTION_HASH = NULL; - } - if(FUNCTION_PROTOTYPES) { - MEM_freeN(FUNCTION_PROTOTYPES); - FUNCTION_PROTOTYPES = NULL; - } - if(FUNCTION_LIB) { - GPU_shader_free(FUNCTION_LIB); - FUNCTION_LIB = NULL; - } -} - -/* GLSL code generation */ - -static void codegen_convert_datatype(DynStr *ds, int from, int to, char *tmp, int id) -{ - char name[1024]; - - snprintf(name, sizeof(name), "%s%d", tmp, id); - - if (from == to) { - BLI_dynstr_append(ds, name); - } - else if (to == GPU_FLOAT) { - if (from == GPU_VEC4) - BLI_dynstr_printf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name); - else if (from == GPU_VEC3) - BLI_dynstr_printf(ds, "dot(%s, vec3(0.33))", name); - else if (from == GPU_VEC2) - BLI_dynstr_printf(ds, "%s.r", name); - } - else if (to == GPU_VEC2) { - if (from == GPU_VEC4) - BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name); - else if (from == GPU_VEC3) - BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name); - else if (from == GPU_FLOAT) - BLI_dynstr_printf(ds, "vec2(%s, 1.0)", name); - } - else if (to == GPU_VEC3) { - if (from == GPU_VEC4) - BLI_dynstr_printf(ds, "%s.rgb", name); - else if (from == GPU_VEC2) - BLI_dynstr_printf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name); - else if (from == GPU_FLOAT) - BLI_dynstr_printf(ds, "vec3(%s, %s, %s)", name, name, name); - } - else { - if (from == GPU_VEC3) - BLI_dynstr_printf(ds, "vec4(%s, 1.0)", name); - else if (from == GPU_VEC2) - BLI_dynstr_printf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); - else if (from == GPU_FLOAT) - BLI_dynstr_printf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); - } -} - -static void codegen_print_datatype(DynStr *ds, int type, float *data) -{ - int i; - - BLI_dynstr_printf(ds, "%s(", GPU_DATATYPE_STR[type]); - - for(i=0; ilink) - return 0; - else if(input->ima) - return 1; - else - return input->tex != 0; -} - -char *GPU_builtin_name(GPUBuiltin builtin) -{ - if(builtin == GPU_VIEW_MATRIX) - return "unfviewmat"; - else if(builtin == GPU_OBJECT_MATRIX) - return "unfobmat"; - else if(builtin == GPU_INVERSE_VIEW_MATRIX) - return "unfinvviewmat"; - else if(builtin == GPU_INVERSE_OBJECT_MATRIX) - return "unfinvobmat"; - else if(builtin == GPU_VIEW_POSITION) - return "varposition"; - else if(builtin == GPU_VIEW_NORMAL) - return "varnormal"; - else if(builtin == GPU_OBCOLOR) - return "unfobcolor"; - else - return ""; -} - -static void codegen_set_unique_ids(ListBase *nodes) -{ - GHash *bindhash, *definehash; - GPUNode *node; - GPUInput *input; - GPUOutput *output; - int id = 1, texid = 0; - - bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { - /* set id for unique names of uniform variables */ - input->id = id++; - input->bindtex = 0; - input->definetex = 0; - - /* set texid used for settings texture slot with multitexture */ - if (codegen_input_has_texture(input) && - ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) { - if (input->link) { - /* input is texture from buffer, assign only one texid per - buffer to avoid sampling the same texture twice */ - if (!BLI_ghash_haskey(bindhash, input->link)) { - input->texid = texid++; - input->bindtex = 1; - BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid)); - } - else - input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link)); - } - else if(input->ima) { - /* input is texture from image, assign only one texid per - buffer to avoid sampling the same texture twice */ - if (!BLI_ghash_haskey(bindhash, input->ima)) { - input->texid = texid++; - input->bindtex = 1; - BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid)); - } - else - input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima)); - } - else { - /* input is user created texture, we know there there is - only one, so assign new texid */ - input->bindtex = 1; - input->texid = texid++; - } - - /* make sure this pixel is defined exactly once */ - if (input->source == GPU_SOURCE_TEX_PIXEL) { - if(input->ima) { - if (!BLI_ghash_haskey(definehash, input->ima)) { - input->definetex = 1; - BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid)); - } - } - else { - if (!BLI_ghash_haskey(definehash, input->link)) { - input->definetex = 1; - BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid)); - } - } - } - } - } - - for (output=node->outputs.first; output; output=output->next) - /* set id for unique names of tmp variables storing output */ - output->id = id++; - } - - BLI_ghash_free(bindhash, NULL, NULL); - BLI_ghash_free(definehash, NULL, NULL); -} - -static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) -{ - GPUNode *node; - GPUInput *input; - char *name; - int builtins = 0; - - /* print uniforms */ - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { - if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) { - /* create exactly one sampler for each texture */ - if (codegen_input_has_texture(input) && input->bindtex) - BLI_dynstr_printf(ds, "uniform %s samp%d;\n", - (input->textype == GPU_TEX1D)? "sampler1D": - (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow", - input->texid); - } - else if(input->source == GPU_SOURCE_BUILTIN) { - /* only define each builting uniform/varying once */ - if(!(builtins & input->builtin)) { - builtins |= input->builtin; - name = GPU_builtin_name(input->builtin); - - if(gpu_str_prefix(name, "unf")) { - BLI_dynstr_printf(ds, "uniform %s %s;\n", - GPU_DATATYPE_STR[input->type], name); - } - else { - BLI_dynstr_printf(ds, "varying %s %s;\n", - GPU_DATATYPE_STR[input->type], name); - } - } - } - else if (input->source == GPU_SOURCE_VEC_UNIFORM) { - if(input->dynamicvec) { - /* only create uniforms for dynamic vectors */ - BLI_dynstr_printf(ds, "uniform %s unf%d;\n", - GPU_DATATYPE_STR[input->type], input->id); - } - else { - /* for others use const so the compiler can do folding */ - BLI_dynstr_printf(ds, "const %s cons%d = ", - GPU_DATATYPE_STR[input->type], input->id); - codegen_print_datatype(ds, input->type, input->vec); - BLI_dynstr_append(ds, ";\n"); - } - } - else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { - BLI_dynstr_printf(ds, "varying %s var%d;\n", - GPU_DATATYPE_STR[input->type], input->attribid); - } - } - } - - BLI_dynstr_append(ds, "\n"); -} - -static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) -{ - GPUNode *node; - GPUInput *input; - GPUOutput *output; - - for (node=nodes->first; node; node=node->next) { - /* load pixels from textures */ - for (input=node->inputs.first; input; input=input->next) { - if (input->source == GPU_SOURCE_TEX_PIXEL) { - if (codegen_input_has_texture(input) && input->definetex) { - BLI_dynstr_printf(ds, "\tvec4 tex%d = texture2D(", input->texid); - BLI_dynstr_printf(ds, "samp%d, gl_TexCoord[%d].st);\n", - input->texid, input->texid); - } - } - } - - /* declare temporary variables for node output storage */ - for (output=node->outputs.first; output; output=output->next) - BLI_dynstr_printf(ds, "\t%s tmp%d;\n", - GPU_DATATYPE_STR[output->type], output->id); - } - - BLI_dynstr_append(ds, "\n"); -} - -static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput) -{ - GPUNode *node; - GPUInput *input; - GPUOutput *output; - - for (node=nodes->first; node; node=node->next) { - BLI_dynstr_printf(ds, "\t%s(", node->name); - - for (input=node->inputs.first; input; input=input->next) { - if (input->source == GPU_SOURCE_TEX) { - BLI_dynstr_printf(ds, "samp%d", input->texid); - if (input->link) - BLI_dynstr_printf(ds, ", gl_TexCoord[%d].st", input->texid); - } - else if (input->source == GPU_SOURCE_TEX_PIXEL) { - if (input->link && input->link->output) - codegen_convert_datatype(ds, input->link->output->type, input->type, - "tmp", input->link->output->id); - else - codegen_convert_datatype(ds, input->link->output->type, input->type, - "tex", input->texid); - } - else if(input->source == GPU_SOURCE_BUILTIN) - BLI_dynstr_printf(ds, "%s", GPU_builtin_name(input->builtin)); - else if(input->source == GPU_SOURCE_VEC_UNIFORM) { - if(input->dynamicvec) - BLI_dynstr_printf(ds, "unf%d", input->id); - else - BLI_dynstr_printf(ds, "cons%d", input->id); - } - else if (input->source == GPU_SOURCE_ATTRIB) - BLI_dynstr_printf(ds, "var%d", input->attribid); - - BLI_dynstr_append(ds, ", "); - } - - for (output=node->outputs.first; output; output=output->next) { - BLI_dynstr_printf(ds, "tmp%d", output->id); - if (output->next) - BLI_dynstr_append(ds, ", "); - } - - BLI_dynstr_append(ds, ");\n"); - } - - BLI_dynstr_append(ds, "\n\tgl_FragColor = "); - codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); - BLI_dynstr_append(ds, ";\n"); -} - -static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *name) -{ - DynStr *ds = BLI_dynstr_new(); - char *code; - - BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); - - codegen_set_unique_ids(nodes); - codegen_print_uniforms_functions(ds, nodes); - - //if(G.f & G_DEBUG) - // BLI_dynstr_printf(ds, "/* %s */\n", name); - - BLI_dynstr_append(ds, "void main(void)\n"); - BLI_dynstr_append(ds, "{\n"); - - codegen_declare_tmps(ds, nodes); - codegen_call_functions(ds, nodes, output); - - BLI_dynstr_append(ds, "}\n"); - - /* create shader */ - code = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - //if(G.f & G_DEBUG) printf("%s\n", code); - - return code; -} - -static char *code_generate_vertex(ListBase *nodes) -{ - DynStr *ds = BLI_dynstr_new(); - GPUNode *node; - GPUInput *input; - char *code; - - for (node=nodes->first; node; node=node->next) { - for (input=node->inputs.first; input; input=input->next) { - if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { - BLI_dynstr_printf(ds, "attribute %s att%d;\n", - GPU_DATATYPE_STR[input->type], input->attribid); - BLI_dynstr_printf(ds, "varying %s var%d;\n", - GPU_DATATYPE_STR[input->type], input->attribid); - } - } - } - - BLI_dynstr_append(ds, "\n"); - BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl); - - for (node=nodes->first; node; node=node->next) - for (input=node->inputs.first; input; input=input->next) - if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { - if(input->attribtype == CD_TANGENT) /* silly exception */ - BLI_dynstr_printf(ds, "\tvar%d = gl_NormalMatrix * ", input->attribid); - else - BLI_dynstr_printf(ds, "\tvar%d = ", input->attribid); - - BLI_dynstr_printf(ds, "att%d;\n", input->attribid); - } - - BLI_dynstr_append(ds, "}\n\n"); - - code = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); - - //if(G.f & G_DEBUG) printf("%s\n", code); - - return code; -} - -/* GPU pass binding/unbinding */ - -GPUShader *GPU_pass_shader(GPUPass *pass) -{ - return pass->shader; -} - -void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) -{ - GPUShader *shader = pass->shader; - GPUNode *node; - GPUInput *next, *input; - ListBase *inputs = &pass->inputs; - int extract, z; - - memset(inputs, 0, sizeof(*inputs)); - - if(!shader) - return; - - GPU_shader_bind(shader); - - for (node=nodes->first; node; node=node->next) { - z = 0; - for (input=node->inputs.first; input; input=next, z++) { - next = input->next; - - /* attributes don't need to be bound, they already have - * an id that the drawing functions will use */ - if(input->source == GPU_SOURCE_ATTRIB || - input->source == GPU_SOURCE_BUILTIN) - continue; - - if (input->ima || input->tex) - snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); - else - snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); - - /* pass non-dynamic uniforms to opengl */ - extract = 0; - - if(input->ima || input->tex) { - if (input->bindtex) - extract = 1; - } - else if(input->dynamicvec) - extract = 1; - - if(extract) - input->shaderloc = GPU_shader_get_uniform(shader, input->shadername); - - /* extract nodes */ - if(extract) { - BLI_remlink(&node->inputs, input); - BLI_addtail(inputs, input); - } - } - } - - GPU_shader_unbind(shader); -} - -void GPU_pass_bind(GPUPass *pass, double time) -{ - GPUInput *input; - GPUShader *shader = pass->shader; - ListBase *inputs = &pass->inputs; - - if (!shader) - return; - - GPU_shader_bind(shader); - - /* now bind the textures */ - for (input=inputs->first; input; input=input->next) { - if (input->ima) - input->tex = GPU_texture_from_blender(input->ima, input->iuser, time); - - if(input->ima || input->tex) { - if(input->tex) { - GPU_texture_bind(input->tex, input->texid); - GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); - } - } - } -} - -void GPU_pass_update_uniforms(GPUPass *pass) -{ - GPUInput *input; - GPUShader *shader = pass->shader; - ListBase *inputs = &pass->inputs; - - if (!shader) - return; - - /* pass dynamic inputs to opengl, others were removed */ - for (input=inputs->first; input; input=input->next) - if(!(input->ima || input->tex)) - GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, - input->dynamicvec); -} - -void GPU_pass_unbind(GPUPass *pass) -{ - GPUInput *input; - GPUShader *shader = pass->shader; - ListBase *inputs = &pass->inputs; - - if (!shader) - return; - - for (input=inputs->first; input; input=input->next) { - if (input->tex) - if(input->bindtex) - GPU_texture_unbind(input->tex); - if (input->ima) - input->tex = 0; - } - - GPU_shader_unbind(shader); -} - -/* Node Link Functions */ - -GPUNodeLink *GPU_node_link_create(int type) -{ - GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink"); - link->type = type; - link->users++; - - return link; -} - -void GPU_node_link_free(GPUNodeLink *link) -{ - link->users--; - - if (link->users < 0) - fprintf(stderr, "GPU_node_link_free: negative refcount\n"); - - if (link->users == 0) { - if (link->output) - link->output->link = NULL; - MEM_freeN(link); - } -} - -/* Node Functions */ - -GPUNode *GPU_node_begin(char *name) -{ - GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode"); - - node->name = name; - - return node; -} - -void GPU_node_end(GPUNode *node) -{ - /* empty */ -} - -static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) -{ - GPUInput *input; - GPUNode *outnode; - char *name; - - if(link->output) { - outnode = link->output->node; - name = outnode->name; - - if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { - input = MEM_dupallocN(outnode->inputs.first); - input->type = type; - if(input->link) - input->link->users++; - BLI_addtail(&node->inputs, input); - return; - } - } - - input = MEM_callocN(sizeof(GPUInput), "GPUInput"); - input->node = node; - - if(link->builtin) { - /* builtin uniform */ - input->type = type; - input->source = GPU_SOURCE_BUILTIN; - input->builtin = link->builtin; - - MEM_freeN(link); - } - else if(link->output) { - /* link to a node output */ - input->type = type; - input->source = GPU_SOURCE_TEX_PIXEL; - input->link = link; - link->users++; - } - else if(link->dynamictex) { - /* dynamic texture, GPUTexture is updated/deleted externally */ - input->type = type; - input->source = GPU_SOURCE_TEX; - - input->tex = link->dynamictex; - input->textarget = GL_TEXTURE_2D; - input->textype = type; - input->dynamictex = 1; - MEM_freeN(link); - } - else if(link->texture) { - /* small texture created on the fly, like for colorbands */ - input->type = GPU_VEC4; - input->source = GPU_SOURCE_TEX; - input->textype = type; - - if (type == GPU_TEX1D) { - input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1); - input->textarget = GL_TEXTURE_1D; - } - else { - input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2); - input->textarget = GL_TEXTURE_2D; - } - - MEM_freeN(link->ptr1); - MEM_freeN(link); - } - else if(link->image) { - /* blender image */ - input->type = GPU_VEC4; - input->source = GPU_SOURCE_TEX; - - input->ima = link->ptr1; - input->textarget = GL_TEXTURE_2D; - input->textype = GPU_TEX2D; - MEM_freeN(link); - } - else if(link->attribtype) { - /* vertex attribute */ - input->type = type; - input->source = GPU_SOURCE_ATTRIB; - - input->attribtype = link->attribtype; - BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname)); - MEM_freeN(link); - } - else { - /* uniform vector */ - input->type = type; - input->source = GPU_SOURCE_VEC_UNIFORM; - - memcpy(input->vec, link->ptr1, type*sizeof(float)); - if(link->dynamic) - input->dynamicvec= link->ptr1; - MEM_freeN(link); - } - - BLI_addtail(&node->inputs, input); -} - -static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock) -{ - GPUNodeLink *link; - - if(sock->link) { - gpu_node_input_link(node, sock->link, sock->type); - } - else { - link = GPU_node_link_create(0); - link->ptr1 = sock->vec; - gpu_node_input_link(node, link, sock->type); - } -} - -void GPU_node_output(GPUNode *node, int type, char *name, GPUNodeLink **link) -{ - GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput"); - - output->type = type; - output->node = node; - - if (link) { - *link = output->link = GPU_node_link_create(type); - output->link->output = output; - - /* note: the caller owns the reference to the linkfer, GPUOutput - merely points to it, and if the node is destroyed it will - set that pointer to NULL */ - } - - BLI_addtail(&node->outputs, output); -} - -void GPU_inputs_free(ListBase *inputs) -{ - GPUInput *input; - - for(input=inputs->first; input; input=input->next) { - if(input->link) - GPU_node_link_free(input->link); - else if(input->tex && !input->dynamictex) - GPU_texture_free(input->tex); - } - - BLI_freelistN(inputs); -} - -void GPU_node_free(GPUNode *node) -{ - GPUOutput *output; - - GPU_inputs_free(&node->inputs); - - for (output=node->outputs.first; output; output=output->next) - if (output->link) { - output->link->output = NULL; - GPU_node_link_free(output->link); - } - - BLI_freelistN(&node->outputs); - MEM_freeN(node); -} - -void GPU_nodes_free(ListBase *nodes) -{ - GPUNode *node; - - while (nodes->first) { - node = nodes->first; - BLI_remlink(nodes, node); - GPU_node_free(node); - } -} - -/* vertex attributes */ - -void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs) -{ - GPUNode *node; - GPUInput *input; - int a; - - /* convert attributes requested by node inputs to an array of layers, - * checking for duplicates and assigning id's starting from zero. */ - - memset(attribs, 0, sizeof(*attribs)); - - for(node=nodes->first; node; node=node->next) { - for(input=node->inputs.first; input; input=input->next) { - if(input->source == GPU_SOURCE_ATTRIB) { - for(a=0; atotlayer; a++) { - if(attribs->layer[a].type == input->attribtype && - strcmp(attribs->layer[a].name, input->attribname) == 0) - break; - } - - if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) { - input->attribid = attribs->totlayer++; - input->attribfirst = 1; - - attribs->layer[a].type = input->attribtype; - attribs->layer[a].glindex = input->attribid; - BLI_strncpy(attribs->layer[a].name, input->attribname, - sizeof(attribs->layer[a].name)); - } - else - input->attribid = attribs->layer[a].glindex; - } - } - } -} - -void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin) -{ - GPUNode *node; - GPUInput *input; - - *builtin= 0; - - for(node=nodes->first; node; node=node->next) - for(input=node->inputs.first; input; input=input->next) - if(input->source == GPU_SOURCE_BUILTIN) - *builtin |= input->builtin; -} - -/* varargs linking */ - -GPUNodeLink *GPU_attribute(int type, char *name) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->attribtype= type; - link->attribname= name; - - return link; -} - -GPUNodeLink *GPU_uniform(float *num) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->ptr1= num; - link->ptr2= NULL; - - return link; -} - -GPUNodeLink *GPU_dynamic_uniform(float *num) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->ptr1= num; - link->ptr2= NULL; - link->dynamic= 1; - - return link; -} - -GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->image= 1; - link->ptr1= ima; - link->ptr2= iuser; - - return link; -} - -GPUNodeLink *GPU_texture(int size, float *pixels) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->texture = 1; - link->texturesize = size; - link->ptr1= pixels; - - return link; -} - -GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->dynamic = 1; - link->dynamictex = tex; - - return link; -} - -GPUNodeLink *GPU_socket(GPUNodeStack *sock) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->socket= sock; - - return link; -} - -GPUNodeLink *GPU_builtin(GPUBuiltin builtin) -{ - GPUNodeLink *link = GPU_node_link_create(0); - - link->builtin= builtin; - - return link; -} - -int GPU_link(GPUMaterial *mat, char *name, ...) -{ - GPUNode *node; - GPUFunction *function; - GPUNodeLink *link, **linkptr; - va_list params; - int i; - - function = GPU_lookup_function(name); - if(!function) { - fprintf(stderr, "GPU failed to find function %s\n", name); - return 0; - } - - node = GPU_node_begin(name); - - va_start(params, name); - for(i=0; itotparam; i++) { - if(function->paramqual[i] != FUNCTION_QUAL_IN) { - linkptr= va_arg(params, GPUNodeLink**); - GPU_node_output(node, function->paramtype[i], "", linkptr); - } - else { - link= va_arg(params, GPUNodeLink*); - gpu_node_input_link(node, link, function->paramtype[i]); - } - } - va_end(params); - - GPU_node_end(node); - - gpu_material_add_node(mat, node); - - return 1; -} - -int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...) -{ - GPUNode *node; - GPUFunction *function; - GPUNodeLink *link, **linkptr; - va_list params; - int i, totin, totout; - - function = GPU_lookup_function(name); - if(!function) { - fprintf(stderr, "GPU failed to find function %s\n", name); - return 0; - } - - node = GPU_node_begin(name); - totin = 0; - totout = 0; - - if(in) { - for(i = 0; in[i].type != GPU_NONE; i++) { - gpu_node_input_socket(node, &in[i]); - totin++; - } - } - - if(out) { - for(i = 0; out[i].type != GPU_NONE; i++) { - GPU_node_output(node, out[i].type, out[i].name, &out[i].link); - totout++; - } - } - - va_start(params, out); - for(i=0; itotparam; i++) { - if(function->paramqual[i] != FUNCTION_QUAL_IN) { - if(totout == 0) { - linkptr= va_arg(params, GPUNodeLink**); - GPU_node_output(node, function->paramtype[i], "", linkptr); - } - else - totout--; - } - else { - if(totin == 0) { - link= va_arg(params, GPUNodeLink*); - if(link->socket) - gpu_node_input_socket(node, link->socket); - else - gpu_node_input_link(node, link, function->paramtype[i]); - } - else - totin--; - } - } - va_end(params); - - GPU_node_end(node); - - gpu_material_add_node(mat, node); - - return 1; -} - -int GPU_link_changed(GPUNodeLink *link) -{ - GPUNode *node; - GPUInput *input; - char *name; - - if(link->output) { - node = link->output->node; - name = node->name; - - if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { - input = node->inputs.first; - return (input->link != NULL); - } - - return 1; - } - else - return 0; -} - -/* Pass create/free */ - -void gpu_nodes_tag(GPUNodeLink *link) -{ - GPUNode *node; - GPUInput *input; - - if(!link->output) - return; - - node = link->output->node; - if(node->tag) - return; - - node->tag= 1; - for(input=node->inputs.first; input; input=input->next) - if(input->link) - gpu_nodes_tag(input->link); -} - -void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) -{ - GPUNode *node, *next; - - for(node=nodes->first; node; node=node->next) - node->tag= 0; - - gpu_nodes_tag(outlink); - - for(node=nodes->first; node; node=next) { - next = node->next; - - if(!node->tag) { - BLI_remlink(nodes, node); - GPU_node_free(node); - } - } -} - -GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name) -{ - GPUShader *shader; - GPUPass *pass; - char *vertexcode, *fragmentcode; - - if(!FUNCTION_LIB) { - GPU_nodes_free(nodes); - return NULL; - } - - /* prune unused nodes */ - gpu_nodes_prune(nodes, outlink); - - gpu_nodes_get_vertex_attributes(nodes, attribs); - gpu_nodes_get_builtin_flag(nodes, builtins); - - /* generate code and compile with opengl */ - fragmentcode = code_generate_fragment(nodes, outlink->output, name); - vertexcode = code_generate_vertex(nodes); - shader = GPU_shader_create(vertexcode, fragmentcode, FUNCTION_LIB); - MEM_freeN(fragmentcode); - MEM_freeN(vertexcode); - - /* failed? */ - if (!shader) { - memset(attribs, 0, sizeof(*attribs)); - memset(builtins, 0, sizeof(*builtins)); - GPU_nodes_free(nodes); - return NULL; - } - - /* create pass */ - pass = MEM_callocN(sizeof(GPUPass), "GPUPass"); - - pass->output = outlink->output; - pass->shader = shader; - - /* extract dynamic inputs and throw away nodes */ - GPU_nodes_extract_dynamic_inputs(pass, nodes); - GPU_nodes_free(nodes); - - return pass; -} - -void GPU_pass_free(GPUPass *pass) -{ - GPU_shader_free(pass->shader); - GPU_inputs_free(&pass->inputs); - MEM_freeN(pass); -} - diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h deleted file mode 100644 index 53b52f24f16..00000000000 --- a/source/blender/gpu/intern/gpu_codegen.h +++ /dev/null @@ -1,87 +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. 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __GPU_CODEGEN_H__ -#define __GPU_CODEGEN_H__ - -#include "DNA_listBase.h" - -struct ListBase; -struct GPUShader; -struct GPUOutput; -struct GPUNode; -struct GPUVertexAttribs; - -#define MAX_FUNCTION_NAME 64 -#define MAX_PARAMETER 32 - -#define FUNCTION_QUAL_IN 0 -#define FUNCTION_QUAL_OUT 1 -#define FUNCTION_QUAL_INOUT 2 - -typedef struct GPUFunction { - char name[MAX_FUNCTION_NAME]; - int paramtype[MAX_PARAMETER]; - int paramqual[MAX_PARAMETER]; - int totparam; -} GPUFunction; - -GPUFunction *GPU_lookup_function(char *name); - -/* Pass Generation - - Takes a list of nodes and a desired output, and makes a pass. This - will take ownership of the nodes and free them early if unused or - at the end if used. -*/ - -struct GPUPass; -typedef struct GPUPass GPUPass; - -GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, - struct GPUVertexAttribs *attribs, int *builtin, const char *name); - -struct GPUShader *GPU_pass_shader(GPUPass *pass); - -void GPU_pass_bind(GPUPass *pass, double time); -void GPU_pass_update_uniforms(GPUPass *pass); -void GPU_pass_unbind(GPUPass *pass); - -void GPU_pass_free(GPUPass *pass); - -/* Material calls */ - -char *GPU_builtin_name(GPUBuiltin builtin); -void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node); -int GPU_link_changed(struct GPUNodeLink *link); - -#endif - diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c deleted file mode 100644 index fe47fa3c60e..00000000000 --- a/source/blender/gpu/intern/gpu_draw.c +++ /dev/null @@ -1,1168 +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. 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include - -#include "GL/glew.h" - -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_material_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_userdef_types.h" -#include "DNA_view3d_types.h" - -#include "MEM_guardedalloc.h" - -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" - -#include "BKE_bmfont.h" -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_main.h" -#include "BKE_material.h" -#include "BKE_node.h" -#include "BKE_object.h" -#include "BKE_utildefines.h" - -#include "GPU_extensions.h" -#include "GPU_material.h" -#include "GPU_draw.h" - -/* These are some obscure rendering functions shared between the - * game engine and the blender, in this module to avoid duplicaten - * and abstract them away from the rest a bit */ - -/* Text Rendering */ - -static void gpu_mcol(unsigned int ucol) -{ - /* mcol order is swapped */ - char *cp= (char *)&ucol; - glColor3ub(cp[3], cp[2], cp[1]); -} - -void GPU_render_text(MTFace *tface, int mode, - const char *textstr, int textlen, unsigned int *col, - float *v1, float *v2, float *v3, float *v4, int glattrib) -{ - if (mode & TF_BMFONT) { - Image* ima; - int characters, index, character; - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - - characters = textlen; - - ima = (Image*)tface->tpage; - if (ima == NULL) - characters = 0; - - // color has been set - if (tface->mode & TF_OBCOL) - col= NULL; - else if (!col) - glColor3f(1.0f, 1.0f, 1.0f); - - glPushMatrix(); - for (index = 0; index < characters; index++) { - float uv[4][2]; - - // lets calculate offset stuff - character = textstr[index]; - - // space starts at offset 1 - // character = character - ' ' + 1; - matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, - &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - - uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx; - uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy; - uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx; - uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy; - uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx; - uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy; - - glBegin(GL_POLYGON); - if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]); - else glTexCoord2fv(uv[0]); - if(col) gpu_mcol(col[0]); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[1]); - else glTexCoord2fv(uv[1]); - if(col) gpu_mcol(col[1]); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - - if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[2]); - else glTexCoord2fv(uv[2]); - if(col) gpu_mcol(col[2]); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(v4) { - uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx; - uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy; - - if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]); - else glTexCoord2fv(uv[3]); - if(col) gpu_mcol(col[3]); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - glEnd(); - - glTranslatef(advance, 0.0, 0.0); - } - glPopMatrix(); - } -} - -/* Checking powers of two for images since opengl 1.x requires it */ - -static int is_pow2(int num) -{ - /* (n&(n-1)) zeros the least significant bit of n */ - return ((num)&(num-1))==0; -} - -static int smaller_pow2(int num) -{ - while (!is_pow2(num)) - num= num&(num-1); - - return num; -} - -static int is_pow2_limit(int num) -{ - /* take texture clamping into account */ - if (U.glreslimit != 0 && num > U.glreslimit) - return 0; - - return ((num)&(num-1))==0; -} - -static int smaller_pow2_limit(int num) -{ - /* take texture clamping into account */ - if (U.glreslimit != 0 && num > U.glreslimit) - return U.glreslimit; - - return smaller_pow2(num); -} - -/* Current OpenGL state caching for GPU_set_tpage */ - -static struct GPUTextureState { - int curtile, tile; - int curtilemode, tilemode; - int curtileXRep, tileXRep; - int curtileYRep, tileYRep; - Image *ima, *curima; - - int domipmap, linearmipmap; - - int alphamode; - MTFace *lasttface; -} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, NULL}; - -/* Mipmap settings */ - -void GPU_set_mipmap(int mipmap) -{ - if (GTS.domipmap != (mipmap != 0)) { - GPU_free_images(); - GTS.domipmap = mipmap != 0; - } -} - -void GPU_set_linear_mipmap(int linear) -{ - if (GTS.linearmipmap != (linear != 0)) { - GPU_free_images(); - GTS.linearmipmap = linear != 0; - } -} - -static int gpu_get_mipmap(void) -{ - return GTS.domipmap && (!(G.f & G_TEXTUREPAINT)); -} - -static GLenum gpu_get_mipmap_filter() -{ - return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST; -} - -/* Set OpenGL state for an MTFace */ - -static void gpu_make_repbind(Image *ima) -{ - ImBuf *ibuf; - - ibuf = BKE_image_get_ibuf(ima, NULL); - if(ibuf==NULL) - return; - - if(ima->repbind) { - glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - MEM_freeN(ima->repbind); - ima->repbind= 0; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } - - ima->totbind= ima->xrep*ima->yrep; - - if(ima->totbind>1) - ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); -} - -static void gpu_clear_tpage() -{ - if(GTS.lasttface==0) - return; - - GTS.lasttface= 0; - GTS.curtile= 0; - GTS.curima= 0; - if(GTS.curtilemode!=0) { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - } - GTS.curtilemode= 0; - GTS.curtileXRep=0; - GTS.curtileYRep=0; - GTS.alphamode= -1; - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glDisable(GL_ALPHA_TEST); -} - -static void gpu_set_blend_mode(GPUBlendMode blendmode) -{ - if(blendmode == GPU_BLEND_SOLID) { - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else if(blendmode==GPU_BLEND_ADD) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable(GL_ALPHA_TEST); - } - else if(blendmode==GPU_BLEND_ALPHA) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* if U.glalphaclip == 1.0, some cards go bonkers... - * turn off alpha test in this case */ - - /* added after 2.45 to clip alpha */ - if(U.glalphaclip == 1.0) { - glDisable(GL_ALPHA_TEST); - } - else { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, U.glalphaclip); - } - } - else if(blendmode==GPU_BLEND_CLIP) { - glDisable(GL_BLEND); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.5f); - } -} - -static void gpu_verify_alpha_mode(MTFace *tface) -{ - /* verify alpha blending modes */ - if(GTS.alphamode == tface->transp) - return; - - gpu_set_blend_mode(tface->transp); - GTS.alphamode= tface->transp; -} - -static void gpu_verify_reflection(Image *ima) -{ - if (ima && (ima->flag & IMA_REFLECT)) { - /* enable reflection mapping */ - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - } - else { - /* disable reflection mapping */ - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - } -} - -int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare) -{ - ImBuf *ibuf = NULL; - unsigned int *bind = NULL; - int rectw, recth, tpx=0, tpy=0, y; - unsigned int *rectrow, *tilerectrow; - unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL; - short texwindx, texwindy, texwinsx, texwinsy; - - /* initialize tile mode and number of repeats */ - GTS.ima = ima; - GTS.tilemode= (tfmode & TF_TILES) || (ima && (ima->tpageflag & IMA_TWINANIM)); - GTS.tileXRep = 0; - GTS.tileYRep = 0; - - /* setting current tile according to frame */ - if(ima && (ima->tpageflag & IMA_TWINANIM)) - GTS.tile= ima->lastframe; - else - GTS.tile= tftile; - - if(ima) { - GTS.tileXRep = ima->xrep; - GTS.tileYRep = ima->yrep; - } - - /* if same image & tile, we're done */ - if(compare && ima == GTS.curima && GTS.curtile == GTS.tile && - GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep && - GTS.curtileYRep == GTS.tileYRep) - return (ima!=0); - - /* if tiling mode or repeat changed, change texture matrix to fit */ - if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep || - GTS.curtileYRep != GTS.tileYRep) { - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - if((tfmode & TF_TILES) && ima!=NULL) - glScalef(ima->xrep, ima->yrep, 1.0); - - glMatrixMode(GL_MODELVIEW); - } - - /* check if we have a valid image */ - if(ima==NULL || ima->ok==0) - return 0; - - /* check if we have a valid image buffer */ - ibuf= BKE_image_get_ibuf(ima, NULL); - - if(ibuf==NULL) - return 0; - - /* ensure we have a char buffer and not only float */ - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - - if(GTS.tilemode) { - /* tiled mode */ - if(ima->repbind==0) gpu_make_repbind(ima); - if(GTS.tile>=ima->totbind) GTS.tile= 0; - - /* this happens when you change repeat buttons */ - if(ima->repbind) bind= &ima->repbind[GTS.tile]; - else bind= &ima->bindcode; - - if(*bind==0) { - - texwindx= ibuf->x/ima->xrep; - texwindy= ibuf->y/ima->yrep; - - if(GTS.tile>=ima->xrep*ima->yrep) - GTS.tile= ima->xrep*ima->yrep-1; - - texwinsy= GTS.tile / ima->xrep; - texwinsx= GTS.tile - texwinsy*ima->xrep; - - texwinsx*= texwindx; - texwinsy*= texwindy; - - tpx= texwindx; - tpy= texwindy; - - rect= ibuf->rect + texwinsy*ibuf->x + texwinsx; - } - } - else { - /* regular image mode */ - bind= &ima->bindcode; - - if(*bind==0) { - tpx= ibuf->x; - tpy= ibuf->y; - rect= ibuf->rect; - } - } - - if(*bind != 0) { - /* enable opengl drawing with textures */ - glBindTexture(GL_TEXTURE_2D, *bind); - return *bind; - } - - rectw = tpx; - recth = tpy; - - /* for tiles, copy only part of image into buffer */ - if (GTS.tilemode) { - tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); - - for (y=0; yx]; - tilerectrow= &tilerect[y*rectw]; - - memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); - } - - rect= tilerect; - } - - /* scale if not a power of two */ - if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { - rectw= smaller_pow2_limit(rectw); - recth= smaller_pow2_limit(recth); - - scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); - rect= scalerect; - } - - /* create image */ - glGenTextures(1, (GLuint *)bind); - glBindTexture( GL_TEXTURE_2D, *bind); - - if (!gpu_get_mipmap()) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else { - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - ima->tpageflag |= IMA_MIPMAP_COMPLETE; - } - - /* set to modulate with vertex color */ - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - /* clean up */ - if (tilerect) - MEM_freeN(tilerect); - if (scalerect) - MEM_freeN(scalerect); - - return *bind; -} - -static void gpu_verify_repeat(Image *ima) -{ - /* set either clamp or repeat in X/Y */ - if (ima->tpageflag & IMA_CLAMP_U) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - - if (ima->tpageflag & IMA_CLAMP_V) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -} - -int GPU_set_tpage(MTFace *tface) -{ - Image *ima; - - /* check if we need to clear the state */ - if(tface==0) { - gpu_clear_tpage(); - return 0; - } - - ima= tface->tpage; - GTS.lasttface= tface; - - gpu_verify_alpha_mode(tface); - gpu_verify_reflection(ima); - - if(GPU_verify_image(ima, tface->tile, tface->mode, 1)) { - GTS.curtile= GTS.tile; - GTS.curima= GTS.ima; - GTS.curtilemode= GTS.tilemode; - GTS.curtileXRep = GTS.tileXRep; - GTS.curtileYRep = GTS.tileYRep; - - glEnable(GL_TEXTURE_2D); - } - else { - glDisable(GL_TEXTURE_2D); - - GTS.curtile= 0; - GTS.curima= 0; - GTS.curtilemode= 0; - GTS.curtileXRep = 0; - GTS.curtileYRep = 0; - - return 0; - } - - gpu_verify_repeat(ima); - - /* Did this get lost in the image recode? */ - /* tag_image_time(ima);*/ - - return 1; -} - -/* these two functions are called on entering and exiting texture paint mode, - temporary disabling/enabling mipmapping on all images for quick texture - updates with glTexSubImage2D. images that didn't change don't have to be - re-uploaded to OpenGL */ -void GPU_paint_set_mipmap(int mipmap) -{ - Image* ima; - - if(!GTS.domipmap) - return; - - if(mipmap) { - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->bindcode) { - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - GPU_free_image(ima); - } - } - - } - else { - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->bindcode) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - } - } -} - -void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) -{ - ImBuf *ibuf; - - ibuf = BKE_image_get_ibuf(ima, NULL); - - if (ima->repbind || gpu_get_mipmap() || !ima->bindcode || !ibuf || - (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || - (w == 0) || (h == 0)) { - /* these cases require full reload still */ - GPU_free_image(ima); - } - else { - /* for the special case, we can do a partial update - * which is much quicker for painting */ - GLint row_length, skip_pixels, skip_rows; - - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); - glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); - glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); - - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); - glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); - - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } -} - -void GPU_update_images_framechange(void) -{ - Image *ima; - - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->tpageflag & IMA_TWINANIM) { - if(ima->twend >= ima->xrep*ima->yrep) - ima->twend= ima->xrep*ima->yrep-1; - - /* check: is bindcode not in the array? free. (to do) */ - - ima->lastframe++; - if(ima->lastframe > ima->twend) - ima->lastframe= ima->twsta; - } - } -} - -int GPU_update_image_time(Image *ima, double time) -{ - int inc = 0; - float diff; - int newframe; - - if (!ima) - return 0; - - if (ima->lastupdate<0) - ima->lastupdate = 0; - - if (ima->lastupdate>time) - ima->lastupdate=(float)time; - - if(ima->tpageflag & IMA_TWINANIM) { - if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; - - /* check: is the bindcode not in the array? Then free. (still to do) */ - - diff = (float)(time-ima->lastupdate); - inc = (int)(diff*(float)ima->animspeed); - - ima->lastupdate+=((float)inc/(float)ima->animspeed); - - newframe = ima->lastframe+inc; - - if(newframe > (int)ima->twend) { - if(ima->twend-ima->twsta != 0) - newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); - else - newframe = ima->twsta; - } - - ima->lastframe = newframe; - } - - return inc; -} - -void GPU_free_image(Image *ima) -{ - /* free regular image binding */ - if(ima->bindcode) { - glDeleteTextures(1, (GLuint *)&ima->bindcode); - ima->bindcode= 0; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } - - /* free glsl image binding */ - if(ima->gputexture) { - GPU_texture_free(ima->gputexture); - ima->gputexture= NULL; - } - - /* free repeated image binding */ - if(ima->repbind) { - glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - - MEM_freeN(ima->repbind); - ima->repbind= NULL; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } -} - -void GPU_free_images(void) -{ - Image* ima; - - if(G.main) - for(ima=G.main->image.first; ima; ima=ima->id.next) - GPU_free_image(ima); -} - -/* OpenGL Materials */ - -/* materials start counting at # one.... */ -#define MAXMATBUF (MAXMAT+1) - -/* OpenGL state caching for materials */ - -static struct GPUMaterialState { - float matbuf[MAXMATBUF][2][4]; - int totmat; - - Material *gmatbuf[MAXMATBUF]; - Material *gboundmat; - Object *gob; - Scene *gscene; - - GPUBlendMode blendmode[MAXMATBUF]; - int alphapass; - - int lastmatnr, lastretval; - GPUBlendMode lastblendmode; -} GMS; - -Material *gpu_active_node_material(Material *ma) -{ - if(ma && ma->use_nodes && ma->nodetree) { - bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); - - if(node) - return (Material *)node->id; - else - return NULL; - } - - return ma; -} - -void GPU_set_object_materials(Scene *scene, Object *ob, int glsl, int *do_alpha_pass) -{ - extern Material defmaterial; /* from material.c */ - Material *ma; - GPUMaterial *gpumat; - GPUBlendMode blendmode; - int a; - - /* initialize state */ - memset(&GMS, 0, sizeof(GMS)); - GMS.lastmatnr = -1; - GMS.lastretval = -1; - GMS.lastblendmode = GPU_BLEND_SOLID; - - GMS.gob = ob; - GMS.gscene = scene; - GMS.totmat= ob->totcol; - - GMS.alphapass = (G.vd && G.vd->transp); - if(do_alpha_pass) - *do_alpha_pass = 0; - - /* no materials assigned? */ - if(ob->totcol==0) { - GMS.matbuf[0][0][0]= defmaterial.r; - GMS.matbuf[0][0][1]= defmaterial.g; - GMS.matbuf[0][0][2]= defmaterial.b; - GMS.matbuf[0][0][3]= 1.0; - - GMS.matbuf[0][1][0]= defmaterial.specr; - GMS.matbuf[0][1][1]= defmaterial.specg; - GMS.matbuf[0][1][2]= defmaterial.specb; - GMS.matbuf[0][1][3]= 1.0; - - /* do material 1 too, for displists! */ - QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]); - QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]); - - if(glsl) { - GMS.gmatbuf[0]= &defmaterial; - GPU_material_from_blender(GMS.gscene, &defmaterial); - } - - GMS.blendmode[0]= GPU_BLEND_SOLID; - } - - /* setup materials */ - for(a=1; a<=ob->totcol; a++) { - /* find a suitable material */ - ma= give_current_material(ob, a); - if(!glsl) ma= gpu_active_node_material(ma); - if(ma==NULL) ma= &defmaterial; - - /* this shouldn't happen .. */ - if(a>=MAXMATBUF) - continue; - - /* create glsl material if requested */ - gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; - - if(gpumat) { - /* do glsl only if creating it succeed, else fallback */ - GMS.gmatbuf[a]= ma; - blendmode = GPU_material_blend_mode(gpumat, ob->col); - } - else { - /* fixed function opengl materials */ - if (ma->mode & MA_SHLESS) { - GMS.matbuf[a][0][0]= ma->r; - GMS.matbuf[a][0][1]= ma->g; - GMS.matbuf[a][0][2]= ma->b; - } else { - GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r; - GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; - GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; - - GMS.matbuf[a][1][0]= ma->spec*ma->specr; - GMS.matbuf[a][1][1]= ma->spec*ma->specg; - GMS.matbuf[a][1][2]= ma->spec*ma->specb; - GMS.matbuf[a][1][3]= 1.0; - } - - blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; - if(do_alpha_pass && GMS.alphapass) - GMS.matbuf[a][0][3]= ma->alpha; - else - GMS.matbuf[a][0][3]= 1.0f; - } - - /* setting do_alpha_pass = 1 indicates this object needs to be - * drawn in a second alpha pass for improved blending */ - if(do_alpha_pass) { - GMS.blendmode[a]= blendmode; - if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass) - *do_alpha_pass= 1; - } - } - - /* let's start with a clean state */ - GPU_disable_material(); -} - -int GPU_enable_material(int nr, void *attribs) -{ - GPUVertexAttribs *gattribs = attribs; - GPUMaterial *gpumat; - GPUBlendMode blendmode; - - /* prevent index to use un-initialized array items */ - if(nr>GMS.totmat) - nr= GMS.totmat; - - if(gattribs) - memset(gattribs, 0, sizeof(*gattribs)); - - /* keep current material */ - if(nr>=MAXMATBUF || nr==GMS.lastmatnr) - return GMS.lastretval; - - /* unbind glsl material */ - if(GMS.gboundmat) { - if(GMS.alphapass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); - GMS.gboundmat= NULL; - } - - /* draw materials with alpha in alpha pass */ - GMS.lastmatnr = nr; - GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); - if(GMS.alphapass) - GMS.lastretval = !GMS.lastretval; - - if(GMS.lastretval) { - if(gattribs && GMS.gmatbuf[nr]) { - /* bind glsl material and get attributes */ - Material *mat = GMS.gmatbuf[nr]; - - gpumat = GPU_material_from_blender(GMS.gscene, mat); - GPU_material_vertex_attributes(gpumat, gattribs); - GPU_material_bind(gpumat, GMS.gob->lay, G.vd->lay, 1.0); - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, G.vd->viewmat, G.vd->viewinv, GMS.gob->col); - GMS.gboundmat= mat; - - if(GMS.alphapass) glDepthMask(1); - } - else { - /* or do fixed function opengl material */ - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]); - } - - /* set (alpha) blending mode */ - blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID; - GPU_set_material_blend_mode(blendmode); - } - - return GMS.lastretval; -} - -void GPU_set_material_blend_mode(int blendmode) -{ - if(GMS.lastblendmode == blendmode) - return; - - gpu_set_blend_mode(blendmode); - GMS.lastblendmode = blendmode; -} - -int GPU_get_material_blend_mode(void) -{ - return GMS.lastblendmode; -} - -void GPU_disable_material(void) -{ - GMS.lastmatnr= -1; - GMS.lastretval= 1; - - if(GMS.gboundmat) { - if(GMS.alphapass) glDepthMask(0); - GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); - GMS.gboundmat= NULL; - } - - GPU_set_material_blend_mode(GPU_BLEND_SOLID); -} - -/* Lights */ - -int GPU_default_lights(void) -{ - int a, count = 0; - - /* initialize */ - if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { - U.light[0].flag= 1; - U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; - U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; - U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; - U.light[0].spec[3]= 1.0; - - U.light[1].flag= 0; - U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; - U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; - U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; - U.light[1].spec[3]= 1.0; - - U.light[2].flag= 0; - U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; - U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; - U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; - U.light[2].spec[3]= 1.0; - } - - glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); - glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); - glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); - - glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); - glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); - glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); - - glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); - glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); - glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); - - for(a=0; a<8; a++) { - if(a<3) { - if(U.light[a].flag) { - glEnable(GL_LIGHT0+a); - count++; - } - else - glDisable(GL_LIGHT0+a); - - // clear stuff from other opengl lamp usage - glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); - glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); - } - else - glDisable(GL_LIGHT0+a); - } - - glDisable(GL_LIGHTING); - - glDisable(GL_COLOR_MATERIAL); - - return count; -} - -int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4]) -{ - Base *base; - Lamp *la; - int count; - float position[4], direction[4], energy[4]; - - /* disable all lights */ - for(count=0; count<8; count++) - glDisable(GL_LIGHT0+count); - - count= 0; - - for(base=scene->base.first; base; base=base->next) { - if(base->object->type!=OB_LAMP) - continue; - - if(!(base->lay & lay) || !(base->lay & ob->lay)) - continue; - - la= base->object->data; - - /* setup lamp transform */ - glPushMatrix(); - glLoadMatrixf((float *)viewmat); - - where_is_object_simul(base->object); - - if(la->type==LA_SUN) { - /* sun lamp */ - VECCOPY(position, base->object->obmat[2]); - direction[3]= 0.0; - - glLightfv(GL_LIGHT0+count, GL_POSITION, direction); - } - else { - /* other lamps with attenuation */ - VECCOPY(position, base->object->obmat[3]); - position[3]= 1.0f; - - glLightfv(GL_LIGHT0+count, GL_POSITION, position); - glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); - glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); - - if(la->type==LA_SPOT) { - /* spot lamp */ - direction[0]= -base->object->obmat[2][0]; - direction[1]= -base->object->obmat[2][1]; - direction[2]= -base->object->obmat[2][2]; - glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction); - glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0); - glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend); - } - else - glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); - } - - /* setup energy */ - energy[0]= la->energy*la->r; - energy[1]= la->energy*la->g; - energy[2]= la->energy*la->b; - energy[3]= 1.0; - - glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); - glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy); - glEnable(GL_LIGHT0+count); - - glPopMatrix(); - - count++; - if(count==8) - break; - } - - return count; -} - -/* Default OpenGL State */ - -void GPU_state_init(void) -{ - /* also called when doing opengl rendering and in the game engine */ - float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; - float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - float mat_shininess[] = { 35.0 }; - int a, x, y; - GLubyte pat[32*32]; - const GLubyte *patc= pat; - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - - GPU_default_lights(); - - /* no local viewer, looks ugly in ortho mode */ - /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ - - glDepthFunc(GL_LEQUAL); - /* scaling matrices */ - glEnable(GL_NORMALIZE); - - glShadeModel(GL_FLAT); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - glDisable(GL_LIGHTING); - glDisable(GL_LOGIC_OP); - glDisable(GL_STENCIL_TEST); - glDisable(GL_TEXTURE_1D); - glDisable(GL_TEXTURE_2D); - - /* default on, disable/enable should be local per function */ - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glPixelTransferi(GL_MAP_COLOR, GL_FALSE); - glPixelTransferi(GL_RED_SCALE, 1); - glPixelTransferi(GL_RED_BIAS, 0); - glPixelTransferi(GL_GREEN_SCALE, 1); - glPixelTransferi(GL_GREEN_BIAS, 0); - glPixelTransferi(GL_BLUE_SCALE, 1); - glPixelTransferi(GL_BLUE_BIAS, 0); - glPixelTransferi(GL_ALPHA_SCALE, 1); - glPixelTransferi(GL_ALPHA_BIAS, 0); - - glPixelTransferi(GL_DEPTH_BIAS, 0); - glPixelTransferi(GL_DEPTH_SCALE, 1); - glDepthRange(0.0, 1.0); - - a= 0; - for(x=0; x<32; x++) { - for(y=0; y<4; y++) { - if( (x) & 1) pat[a++]= 0x88; - else pat[a++]= 0x22; - } - } - - glPolygonStipple(patc); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glDisable(GL_CULL_FACE); -} - diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c deleted file mode 100644 index d900f9c63f2..00000000000 --- a/source/blender/gpu/intern/gpu_extensions.c +++ /dev/null @@ -1,987 +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. 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) 2005 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "GL/glew.h" - -#include "DNA_listBase.h" -#include "DNA_image_types.h" -#include "DNA_userdef_types.h" - -#include "MEM_guardedalloc.h" - -#include "BKE_image.h" -#include "BKE_global.h" - -#include "IMB_imbuf.h" -#include "IMB_imbuf_types.h" - -#include "BLI_blenlib.h" - -#include "GPU_draw.h" -#include "GPU_extensions.h" - -#include -#include -#include - -/* Extensions support */ - -/* extensions used: - - texture border clamp: 1.3 core - - fragement shader: 2.0 core - - framebuffer object: ext specification - - multitexture 1.3 core - - arb non power of two: 2.0 core - - pixel buffer objects? 2.1 core - - arb draw buffers? 2.0 core -*/ - -struct GPUGlobal { - GLint maxtextures; - GLuint currentfb; - int minimumsupport; -} GG = {1, 0, 0}; - -void GPU_extensions_init() -{ - glewInit(); - - /* glewIsSupported("GL_VERSION_2_0") */ - - if (GLEW_ARB_multitexture) - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures); - - GG.minimumsupport = 1; - if (!GLEW_ARB_multitexture) GG.minimumsupport = 0; - if (!GLEW_ARB_vertex_shader) GG.minimumsupport = 0; - if (!GLEW_ARB_fragment_shader) GG.minimumsupport = 0; -} - -int GPU_extensions_minimum_support() -{ - return GG.minimumsupport; -} - -int GPU_print_error(char *str) -{ - GLenum errCode; - - if (G.f & G_DEBUG) { - if ((errCode = glGetError()) != GL_NO_ERROR) { - fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode)); - return 1; - } - } - - return 0; -} - -static void GPU_print_framebuffer_error(GLenum status) -{ - fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d\n", - (int)status); - - switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - fprintf(stderr, "Incomplete attachment.\n"); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - fprintf(stderr, "Unsupported framebuffer format.\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - fprintf(stderr, "Missing attachment.\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: - fprintf(stderr, "Attached images must have same dimensions.\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: - fprintf(stderr, "Attached images must have same format.\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - fprintf(stderr, "Missing draw buffer.\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - fprintf(stderr, "Missing read buffer.\n"); - break; - default: - fprintf(stderr, "Unknown.\n"); - break; - } -} - -/* GPUTexture */ - -struct GPUTexture { - int w, h; /* width/height */ - int number; /* number for multitexture binding */ - int refcount; /* reference count */ - GLenum target; /* GL_TEXTURE_* */ - GLuint bindcode; /* opengl identifier for texture */ - int fromblender; /* we got the texture from Blender */ - - GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ - int depth; /* is a depth texture? */ -}; - -#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) -static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels) -{ - unsigned char *pixels, *p; - float *fp; - int a, len; - - len = 4*length; - fp = fpixels; - p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels"); - - for (a=0; aw = w; - tex->h = h; - tex->number = -1; - tex->refcount = 1; - tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; - tex->depth = depth; - - glGenTextures(1, &tex->bindcode); - - if (!tex->bindcode) { - fprintf(stderr, "GPUTexture: texture create failed: %d\n", - (int)glGetError()); - GPU_texture_free(tex); - return NULL; - } - - if (!GLEW_ARB_texture_non_power_of_two) { - tex->w = larger_pow2(tex->w); - tex->h = larger_pow2(tex->h); - } - - tex->number = 0; - glBindTexture(tex->target, tex->bindcode); - - if(depth) { - type = GL_UNSIGNED_BYTE; - format = GL_DEPTH_COMPONENT; - internalformat = GL_DEPTH_COMPONENT; - } - else { - type = GL_UNSIGNED_BYTE; - format = GL_RGBA; - internalformat = GL_RGBA8; - - if (fpixels) - pixels = GPU_texture_convert_pixels(w*h, fpixels); - } - - if (tex->target == GL_TEXTURE_1D) { - glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, 0); - - if (fpixels) { - glTexSubImage1D(tex->target, 0, 0, w, format, type, - pixels? pixels: fpixels); - - if (tex->w > w) - GPU_glTexSubImageEmpty(tex->target, format, w, 0, - tex->w-w, 1); - } - } - else { - glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, - format, type, 0); - - if (fpixels) { - glTexSubImage2D(tex->target, 0, 0, 0, w, h, - format, type, pixels? pixels: fpixels); - - if (tex->w > w) - GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); - if (tex->h > h) - GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); - } - } - - if (pixels) - MEM_freeN(pixels); - - if(depth) { - glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); - glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); - glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); - } - else { - glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (tex->target != GL_TEXTURE_1D) { - /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */ - GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER; - glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode); - glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode); - -#if 0 - float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); -#endif - } - else - glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - - return tex; -} - -GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time) -{ - GPUTexture *tex; - GLint w, h, border, lastbindcode, bindcode; - - glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); - - GPU_update_image_time(ima, time); - bindcode = GPU_verify_image(ima, 0, 0, 0); - - if(ima->gputexture) { - ima->gputexture->bindcode = bindcode; - glBindTexture(GL_TEXTURE_2D, lastbindcode); - return ima->gputexture; - } - - if(!bindcode) { - glBindTexture(GL_TEXTURE_2D, lastbindcode); - return NULL; - } - - tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->bindcode = bindcode; - tex->number = -1; - tex->refcount = 1; - tex->target = GL_TEXTURE_2D; - tex->fromblender = 1; - - ima->gputexture= tex; - - if (!glIsTexture(tex->bindcode)) { - GPU_print_error("Blender Texture"); - } - else { - glBindTexture(GL_TEXTURE_2D, tex->bindcode); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border); - - tex->w = w - border; - tex->h = h - border; - } - - glBindTexture(GL_TEXTURE_2D, lastbindcode); - - return tex; -} - -GPUTexture *GPU_texture_create_1D(int w, float *fpixels) -{ - GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0); - - if (tex) - GPU_texture_unbind(tex); - - return tex; -} - -GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels) -{ - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0); - - if (tex) - GPU_texture_unbind(tex); - - return tex; -} - -GPUTexture *GPU_texture_create_depth(int w, int h) -{ - GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1); - - if (tex) - GPU_texture_unbind(tex); - - return tex; -} - -void GPU_texture_bind(GPUTexture *tex, int number) -{ - GLenum arbnumber; - - if (number >= GG.maxtextures) { - GPU_print_error("Not enough texture slots."); - return; - } - - if(number == -1) - return; - - GPU_print_error("Pre Texture Bind"); - - arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number); - if (number != 0) glActiveTextureARB(arbnumber); - glBindTexture(tex->target, tex->bindcode); - glEnable(tex->target); - if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); - - tex->number = number; - - GPU_print_error("Post Texture Bind"); -} - -void GPU_texture_unbind(GPUTexture *tex) -{ - GLenum arbnumber; - - if (tex->number >= GG.maxtextures) { - GPU_print_error("Not enough texture slots."); - return; - } - - if(tex->number == -1) - return; - - GPU_print_error("Pre Texture Unbind"); - - arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); - if (tex->number != 0) glActiveTextureARB(arbnumber); - glBindTexture(tex->target, 0); - glDisable(tex->target); - if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); - - tex->number = -1; - - GPU_print_error("Post Texture Unbind"); -} - -void GPU_texture_free(GPUTexture *tex) -{ - tex->refcount--; - - if (tex->refcount < 0) - fprintf(stderr, "GPUTexture: negative refcount\n"); - - if (tex->refcount == 0) { - if (tex->fb) - GPU_framebuffer_texture_detach(tex->fb, tex); - if (tex->bindcode && !tex->fromblender) - glDeleteTextures(1, &tex->bindcode); - - MEM_freeN(tex); - } -} - -void GPU_texture_ref(GPUTexture *tex) -{ - tex->refcount++; -} - -int GPU_texture_target(GPUTexture *tex) -{ - return tex->target; -} - -int GPU_texture_opengl_width(GPUTexture *tex) -{ - return tex->w; -} - -int GPU_texture_opengl_height(GPUTexture *tex) -{ - return tex->h; -} - -GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex) -{ - return tex->fb; -} - -/* GPUFrameBuffer */ - -struct GPUFrameBuffer { - GLuint object; - GPUTexture *colortex; - GPUTexture *depthtex; -}; - -GPUFrameBuffer *GPU_framebuffer_create() -{ - GPUFrameBuffer *fb; - - if (!GLEW_EXT_framebuffer_object) - return NULL; - - fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); - glGenFramebuffersEXT(1, &fb->object); - - if (!fb->object) { - fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n", - (int)glGetError()); - GPU_framebuffer_free(fb); - return NULL; - } - - return fb; -} - -int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex) -{ - GLenum status; - GLenum attachment; - - if(tex->depth) - attachment = GL_DEPTH_ATTACHMENT_EXT; - else - attachment = GL_COLOR_ATTACHMENT0_EXT; - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object); - GG.currentfb = fb->object; - - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, - tex->target, tex->bindcode, 0); - - if(tex->depth) { - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } - else { - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glReadBuffer(GL_NONE); - } - - status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { - GPU_framebuffer_restore(); - GPU_print_framebuffer_error(status); - return 0; - } - - if(tex->depth) - fb->depthtex = tex; - else - fb->colortex = tex; - - tex->fb= fb; - - return 1; -} - -void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) -{ - GLenum attachment; - - if(!tex->fb) - return; - - if(GG.currentfb != tex->fb->object) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); - GG.currentfb = tex->fb->object; - } - - if(tex->depth) { - fb->depthtex = NULL; - attachment = GL_DEPTH_ATTACHMENT_EXT; - } - else { - fb->colortex = NULL; - attachment = GL_COLOR_ATTACHMENT0_EXT; - } - - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, - tex->target, 0, 0); - - tex->fb = NULL; -} - -void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex) -{ - /* push attributes */ - glPushAttrib(GL_ENABLE_BIT); - glPushAttrib(GL_VIEWPORT_BIT); - glDisable(GL_SCISSOR_TEST); - - /* bind framebuffer */ - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); - - /* push matrices and set default viewport and matrix */ - glViewport(0, 0, tex->w, tex->h); - GG.currentfb = tex->fb->object; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); -} - -void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex) -{ - /* restore matrix */ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - /* restore attributes */ - glPopAttrib(); - glPopAttrib(); - glEnable(GL_SCISSOR_TEST); -} - -void GPU_framebuffer_free(GPUFrameBuffer *fb) -{ - if(fb->depthtex) - GPU_framebuffer_texture_detach(fb, fb->depthtex); - if(fb->colortex) - GPU_framebuffer_texture_detach(fb, fb->colortex); - - if(fb->object) { - glDeleteFramebuffersEXT(1, &fb->object); - - if (GG.currentfb == fb->object) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - GG.currentfb = 0; - } - } - - MEM_freeN(fb); -} - -void GPU_framebuffer_restore() -{ - if (GG.currentfb != 0) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - GG.currentfb = 0; - } -} - -/* GPUShader */ - -struct GPUShader { - GLhandleARB object; /* handle for full shader */ - GLhandleARB vertex; /* handle for vertex shader */ - GLhandleARB fragment; /* handle for fragment shader */ - GLhandleARB lib; /* handle for libment shader */ - int totattrib; /* total number of attributes */ -}; - -static void shader_print_errors(char *task, char *log, const char *code) -{ - const char *c, *pos, *end = code + strlen(code); - int line = 1; - - fprintf(stderr, "GPUShader: %s error:\n", task); - - if(G.f & G_DEBUG) { - c = code; - while ((c < end) && (pos = strchr(c, '\n'))) { - fprintf(stderr, "%2d ", line); - fwrite(c, (pos+1)-c, 1, stderr); - c = pos+1; - line++; - } - - fprintf(stderr, "%s", c); - } - - fprintf(stderr, "%s\n", log); -} - -GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib) -{ - GLint status; - GLcharARB log[5000]; - GLsizei length = 0; - GPUShader *shader; - - if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) - return NULL; - - shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); - - if(vertexcode) - shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); - if(fragcode) - shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); - shader->object = glCreateProgramObjectARB(); - - if (!shader->object || - (vertexcode && !shader->vertex) || - (fragcode && !shader->fragment)) { - fprintf(stderr, "GPUShader, object creation failed.\n"); - GPU_shader_free(shader); - return NULL; - } - - if(lib && lib->lib) - glAttachObjectARB(shader->object, lib->lib); - - if(vertexcode) { - glAttachObjectARB(shader->object, shader->vertex); - glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL); - - glCompileShaderARB(shader->vertex); - glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status); - - if (!status) { - glValidateProgramARB(shader->vertex); - glGetInfoLogARB(shader->vertex, sizeof(log), &length, log); - shader_print_errors("compile", log, vertexcode); - - GPU_shader_free(shader); - return NULL; - } - } - - if(fragcode) { - glAttachObjectARB(shader->object, shader->fragment); - glShaderSourceARB(shader->fragment, 1, (const char**)&fragcode, NULL); - - glCompileShaderARB(shader->fragment); - glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status); - - if (!status) { - glValidateProgramARB(shader->fragment); - glGetInfoLogARB(shader->fragment, sizeof(log), &length, log); - shader_print_errors("compile", log, fragcode); - - GPU_shader_free(shader); - return NULL; - } - } - - glLinkProgramARB(shader->object); - glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status); - if (!status) { - glGetInfoLogARB(shader->object, sizeof(log), &length, log); - shader_print_errors("linking", log, fragcode); - - GPU_shader_free(shader); - return NULL; - } - - return shader; -} - -GPUShader *GPU_shader_create_lib(const char *code) -{ - GLint status; - GLcharARB log[5000]; - GLsizei length = 0; - GPUShader *shader; - - if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) - return NULL; - - shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); - - shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); - - if (!shader->lib) { - fprintf(stderr, "GPUShader, object creation failed.\n"); - GPU_shader_free(shader); - return NULL; - } - - glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL); - - glCompileShaderARB(shader->lib); - glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status); - - if (!status) { - glValidateProgramARB(shader->lib); - glGetInfoLogARB(shader->lib, sizeof(log), &length, log); - shader_print_errors("compile", log, code); - - GPU_shader_free(shader); - return NULL; - } - - return shader; -} - -void GPU_shader_bind(GPUShader *shader) -{ - GPU_print_error("Pre Shader Bind"); - glUseProgramObjectARB(shader->object); - GPU_print_error("Post Shader Bind"); -} - -void GPU_shader_unbind() -{ - GPU_print_error("Pre Shader Unbind"); - glUseProgramObjectARB(0); - GPU_print_error("Post Shader Unbind"); -} - -void GPU_shader_free(GPUShader *shader) -{ - if (shader->lib) - glDeleteObjectARB(shader->lib); - if (shader->vertex) - glDeleteObjectARB(shader->vertex); - if (shader->fragment) - glDeleteObjectARB(shader->fragment); - if (shader->object) - glDeleteObjectARB(shader->object); - MEM_freeN(shader); -} - -int GPU_shader_get_uniform(GPUShader *shader, char *name) -{ - return glGetUniformLocationARB(shader->object, name); -} - -void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, float *value) -{ - if(location == -1) - return; - - GPU_print_error("Pre Uniform Vector"); - - if (length == 1) glUniform1fvARB(location, arraysize, value); - else if (length == 2) glUniform2fvARB(location, arraysize, value); - else if (length == 3) glUniform3fvARB(location, arraysize, value); - else if (length == 4) glUniform4fvARB(location, arraysize, value); - else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value); - else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value); - - GPU_print_error("Post Uniform Vector"); -} - -void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex) -{ - GLenum arbnumber; - - if (tex->number >= GG.maxtextures) { - GPU_print_error("Not enough texture slots."); - return; - } - - if(tex->number == -1) - return; - - if(location == -1) - return; - - GPU_print_error("Pre Uniform Texture"); - - arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); - - if (tex->number != 0) glActiveTextureARB(arbnumber); - glBindTexture(tex->target, tex->bindcode); - glUniform1iARB(location, tex->number); - glEnable(tex->target); - if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); - - GPU_print_error("Post Uniform Texture"); -} - -int GPU_shader_get_attribute(GPUShader *shader, char *name) -{ - int index; - - GPU_print_error("Pre Get Attribute"); - - index = glGetAttribLocationARB(shader->object, name); - - GPU_print_error("Post Get Attribute"); - - return index; -} - -#if 0 -/* GPUPixelBuffer */ - -typedef struct GPUPixelBuffer { - GLuint bindcode[2]; - GLuint current; - int datasize; - int numbuffers; - int halffloat; -} GPUPixelBuffer; - -void GPU_pixelbuffer_free(GPUPixelBuffer *pb) -{ - if (pb->bindcode[0]) - glDeleteBuffersARB(pb->numbuffers, pb->bindcode); - MEM_freeN(pb); -} - -GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers) -{ - GPUPixelBuffer *pb; - - if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object) - return NULL; - - pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO"); - pb->datasize = x*y*4*((halffloat)? 16: 8); - pb->numbuffers = numbuffers; - pb->halffloat = halffloat; - - glGenBuffersARB(pb->numbuffers, pb->bindcode); - - if (!pb->bindcode[0]) { - fprintf(stderr, "GPUPixelBuffer allocation failed\n"); - GPU_pixelbuffer_free(pb); - return NULL; - } - - return pb; -} - -void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb) -{ - void *pixels; - int i; - - glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); - - for (i = 0; i < pb->numbuffers; i++) { - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]); - glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL, - GL_STREAM_DRAW_ARB); - - pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); - /*memcpy(pixels, _oImage.data(), pb->datasize);*/ - - if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { - fprintf(stderr, "Could not unmap opengl PBO\n"); - break; - } - } - - glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); -} - -static int pixelbuffer_map_into_gpu(GLuint bindcode) -{ - void *pixels; - - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); - pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); - - /* do stuff in pixels */ - - if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { - fprintf(stderr, "Could not unmap opengl PBO\n"); - return 0; - } - - return 1; -} - -static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode) -{ - GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE; - glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); - - glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, - GL_RGBA, type, NULL); - - glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); - glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); -} - -void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb) -{ - int newbuffer; - - if (pb->numbuffers == 1) { - pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]); - pixelbuffer_map_into_gpu(pb->bindcode[0]); - } - else { - pb->current = (pb->current+1)%pb->numbuffers; - newbuffer = (pb->current+1)%pb->numbuffers; - - pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]); - pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]); - } -} -#endif - diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c deleted file mode 100644 index d4da2866d96..00000000000 --- a/source/blender/gpu/intern/gpu_material.c +++ /dev/null @@ -1,1496 +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): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include - -#include "GL/glew.h" - -#include "MEM_guardedalloc.h" - -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_listBase.h" -#include "DNA_material_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_texture_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" - -#include "BKE_anim.h" -#include "BKE_colortools.h" -#include "BKE_DerivedMesh.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_node.h" -#include "BKE_scene.h" -#include "BKE_texture.h" -#include "BKE_utildefines.h" - -#include "BLI_arithb.h" -#include "BLI_blenlib.h" - -#include "GPU_extensions.h" -#include "GPU_material.h" - -#include "gpu_codegen.h" - -#include - -/* Structs */ - -typedef enum DynMatProperty { - DYN_LAMP_CO = 1, - DYN_LAMP_VEC = 2, - DYN_LAMP_IMAT = 4, - DYN_LAMP_PERSMAT = 8, -} DynMatProperty; - -struct GPUMaterial { - Scene *scene; - Material *ma; - - /* for creating the material */ - ListBase nodes; - GPUNodeLink *outlink; - - /* for binding the material */ - GPUPass *pass; - GPUVertexAttribs attribs; - int bound; - int builtins; - int alpha, obcolalpha; - int dynproperty; - - /* for passing uniforms */ - int viewmatloc, invviewmatloc; - int obmatloc, invobmatloc; - int obcolloc; - - ListBase lamps; -}; - -struct GPULamp { - Scene *scene; - Object *ob; - Object *par; - Lamp *la; - - int type, mode, lay; - - float dynenergy, dyncol[3]; - float energy, col[3]; - - float co[3], vec[3]; - float dynco[3], dynvec[3]; - float obmat[4][4]; - float imat[4][4]; - float dynimat[4][4]; - - float spotsi, spotbl, k; - float dist, att1, att2; - - float bias, d, clipend; - int size; - - int falloff_type; - struct CurveMapping *curfalloff; - - float winmat[4][4]; - float viewmat[4][4]; - float persmat[4][4]; - float dynpersmat[4][4]; - - GPUFrameBuffer *fb; - GPUTexture *tex; - - ListBase materials; -}; - -/* Functions */ - -static GPUMaterial *GPU_material_construct_begin(Material *ma) -{ - GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); - - material->ma= ma; - - return material; -} - -static void gpu_material_set_attrib_id(GPUMaterial *material) -{ - GPUVertexAttribs *attribs; - GPUShader *shader; - GPUPass *pass; - char name[32]; - int a, b; - - attribs= &material->attribs; - pass= material->pass; - if(!pass) { - attribs->totlayer = 0; - return; - } - - shader= GPU_pass_shader(pass); - if(!shader) { - attribs->totlayer = 0; - return; - } - - /* convert from attribute number to the actual id assigned by opengl, - * in case the attrib does not get a valid index back, it was probably - * removed by the glsl compiler by dead code elimination */ - - for(a=0, b=0; atotlayer; a++) { - sprintf(name, "att%d", attribs->layer[a].glindex); - attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name); - - if(attribs->layer[a].glindex >= 0) { - attribs->layer[b] = attribs->layer[a]; - b++; - } - } - - attribs->totlayer = b; -} - -static int GPU_material_construct_end(GPUMaterial *material) -{ - if (material->outlink) { - GPUNodeLink *outlink; - GPUShader *shader; - - outlink = material->outlink; - material->pass = GPU_generate_pass(&material->nodes, outlink, - &material->attribs, &material->builtins, material->ma->id.name); - - if(!material->pass) - return 0; - - gpu_material_set_attrib_id(material); - - shader = GPU_pass_shader(material->pass); - - if(material->builtins & GPU_VIEW_MATRIX) - material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX)); - if(material->builtins & GPU_INVERSE_VIEW_MATRIX) - material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX)); - if(material->builtins & GPU_OBJECT_MATRIX) - material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX)); - if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) - material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX)); - if(material->builtins & GPU_OBCOLOR) - material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR)); - - return 1; - } - - return 0; -} - -void GPU_material_free(Material *ma) -{ - LinkData *link; - LinkData *nlink, *mlink, *next; - - for(link=ma->gpumaterial.first; link; link=link->next) { - GPUMaterial *material = link->data; - - if(material->pass) - GPU_pass_free(material->pass); - - for(nlink=material->lamps.first; nlink; nlink=nlink->next) { - GPULamp *lamp = nlink->data; - - for(mlink=lamp->materials.first; mlink; mlink=next) { - next = mlink->next; - if(mlink->data == ma) - BLI_freelinkN(&lamp->materials, mlink); - } - } - - BLI_freelistN(&material->lamps); - - MEM_freeN(material); - } - - BLI_freelistN(&ma->gpumaterial); -} - -void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time) -{ - if(material->pass) { - LinkData *nlink; - GPULamp *lamp; - - /* handle layer lamps */ - for(nlink=material->lamps.first; nlink; nlink=nlink->next) { - lamp= nlink->data; - - if((lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))) { - lamp->dynenergy = lamp->energy; - VECCOPY(lamp->dyncol, lamp->col); - } - else { - lamp->dynenergy = 0.0f; - lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; - } - } - - GPU_pass_bind(material->pass, time); - material->bound = 1; - } -} - -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]) -{ - if(material->pass) { - GPUShader *shader = GPU_pass_shader(material->pass); - LinkData *nlink; - GPULamp *lamp; - float invmat[4][4], col[4]; - - /* handle builtins */ - if(material->builtins & GPU_VIEW_MATRIX) { - GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); - } - if(material->builtins & GPU_INVERSE_VIEW_MATRIX) { - GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); - } - if(material->builtins & GPU_OBJECT_MATRIX) { - GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); - } - if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) { - Mat4Invert(invmat, obmat); - GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat); - } - if(material->builtins & GPU_OBCOLOR) { - QUATCOPY(col, obcol); - CLAMP(col[3], 0.0f, 1.0f); - GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); - } - - /* update lamps */ - for(nlink=material->lamps.first; nlink; nlink=nlink->next) { - lamp= nlink->data; - - if(material->dynproperty & DYN_LAMP_VEC) { - VECCOPY(lamp->dynvec, lamp->vec); - Normalize(lamp->dynvec); - VecMulf(lamp->dynvec, -1.0f); - Mat4Mul3Vecfl(viewmat, lamp->dynvec); - } - - if(material->dynproperty & DYN_LAMP_CO) { - VECCOPY(lamp->dynco, lamp->co); - Mat4MulVecfl(viewmat, lamp->dynco); - } - - if(material->dynproperty & DYN_LAMP_IMAT) - Mat4MulMat4(lamp->dynimat, viewinv, lamp->imat); - if(material->dynproperty & DYN_LAMP_PERSMAT) - Mat4MulMat4(lamp->dynpersmat, viewinv, lamp->persmat); - } - - GPU_pass_update_uniforms(material->pass); - } -} - -void GPU_material_unbind(GPUMaterial *material) -{ - if (material->pass) { - material->bound = 0; - GPU_pass_unbind(material->pass); - } -} - -int GPU_material_bound(GPUMaterial *material) -{ - return material->bound; -} - -void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs) -{ - *attribs = material->attribs; -} - -void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) -{ - if(!material->outlink) - material->outlink= link; -} - -void GPU_material_enable_alpha(GPUMaterial *material) -{ - material->alpha= 1; -} - -GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[3]) -{ - if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f)) - return GPU_BLEND_ALPHA; - else - return GPU_BLEND_SOLID; -} - -void gpu_material_add_node(GPUMaterial *material, GPUNode *node) -{ - BLI_addtail(&material->nodes, node); -} - -/* Code generation */ - -static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) -{ - GPUNodeLink *visifac, *inpr; - - /* from get_lamp_visibility */ - if(lamp->type==LA_SUN || lamp->type==LA_HEMI) { - mat->dynproperty |= DYN_LAMP_VEC; - GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec), lv, dist, &visifac); - return visifac; - } - else { - mat->dynproperty |= DYN_LAMP_CO; - GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), lv, dist, &visifac); - - if(lamp->type==LA_AREA) - return visifac; - - switch(lamp->falloff_type) - { - case LA_FALLOFF_CONSTANT: - break; - case LA_FALLOFF_INVLINEAR: - GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac); - break; - case LA_FALLOFF_INVSQUARE: - GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac); - break; - case LA_FALLOFF_SLIDERS: - GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac); - break; - case LA_FALLOFF_CURVE: - { - float *array; - int size; - - curvemapping_table_RGBA(lamp->curfalloff, &array, &size); - GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac); - } - break; - } - - if(lamp->mode & LA_SPHERE) - GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac); - - if(lamp->type == LA_SPOT) { - if(lamp->mode & LA_SQUARE) { - mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT; - GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec), GPU_dynamic_uniform((float*)lamp->dynimat), *lv, &inpr); - } - else { - mat->dynproperty |= DYN_LAMP_VEC; - GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec), *lv, &inpr); - } - - GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac); - } - - GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); - - return visifac; - } -} - -#if 0 -static void area_lamp_vectors(LampRen *lar) -{ - float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; - - /* make it smaller, so area light can be multisampled */ - multifac= 1.0f/sqrt((float)lar->ray_totsamp); - xsize *= multifac; - ysize *= multifac; - - /* corner vectors */ - lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; - lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; - - /* corner vectors */ - lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; - lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; - - /* corner vectors */ - lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; - lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; - lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; - - /* corner vectors */ - lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; - lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; - lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; - /* only for correction button size, matrix size works on energy */ - lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize); -} -#endif - -static void ramp_blend(GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type, GPUNodeLink **outcol) -{ - static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", - "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", - "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", - "mix_val", "mix_color"}; - - GPU_link(mat, names[type], fac, col1, col2, outcol); -} - -static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type, GPUNodeLink *incol, GPUNodeLink **outcol) -{ - GPUNodeLink *tmp, *alpha, *col; - float *array; - int size; - - /* do colorband */ - colorband_table_RGBA(coba, &array, &size); - GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp); - - /* use alpha in fac */ - GPU_link(mat, "mtex_alpha_from_col", col, &alpha); - GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac); - - /* blending method */ - ramp_blend(mat, fac, incol, col, type, outcol); -} - -static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff) -{ - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; - GPUNodeLink *fac; - - if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS)) { - if(ma->ramp_col) { - if(ma->rampin_col==MA_RAMP_IN_RESULT) { - GPU_link(mat, "ramp_rgbtobw", *diff, &fac); - - /* colorband + blend */ - do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff); - } - } - } -} - -static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb, GPUNodeLink **diff) -{ - GPUNodeLink *fac, *tmp, *addcol; - - if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS) && - ma->ramp_col && (ma->mode & MA_RAMP_COL)) { - /* MA_RAMP_IN_RESULT is exceptional */ - if(ma->rampin_col==MA_RAMP_IN_RESULT) { - addcol = shi->rgb; - } - else { - /* input */ - switch(ma->rampin_col) { - case MA_RAMP_IN_ENERGY: - GPU_link(mat, "ramp_rgbtobw", rgb, &fac); - break; - case MA_RAMP_IN_SHADER: - fac= is; - break; - case MA_RAMP_IN_NOR: - GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); - break; - default: - GPU_link(mat, "set_value_zero", &fac); - break; - } - - /* colorband + blend */ - do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol); - } - } - else - addcol = shi->rgb; - - /* output to */ - GPU_link(mat, "shade_madd", *diff, rgb, addcol, diff); -} - -static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec) -{ - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; - GPUNodeLink *fac; - - if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS) && - ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) { - GPU_link(mat, "ramp_rgbtobw", *spec, &fac); - - /* colorband + blend */ - do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); - } -} - -static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec) -{ - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; - GPUNodeLink *fac, *tmp; - - *spec = shi->specrgb; - - /* MA_RAMP_IN_RESULT is exception */ - if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { - - /* input */ - switch(ma->rampin_spec) { - case MA_RAMP_IN_ENERGY: - fac = t; - break; - case MA_RAMP_IN_SHADER: - fac = is; - break; - case MA_RAMP_IN_NOR: - GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); - break; - default: - GPU_link(mat, "set_value_zero", &fac); - break; - } - - /* colorband + blend */ - do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); - } -} - -void add_user_list(ListBase *list, void *data) -{ - LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData"); - link->data = data; - BLI_addtail(list, link); -} - -static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp) -{ - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; - GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view; - GPUNodeLink *outcol, *specfac, *t, *shadfac; - float one = 1.0f; - - if((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW)) - return; - - vn= shi->vn; - view= shi->view; - - visifac= lamp_get_visibility(mat, lamp, &lv, &dist); - - /*if(ma->mode & MA_TANGENT_V) - GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/ - - GPU_link(mat, "shade_inp", vn, lv, &inp); - - if(lamp->mode & LA_NO_DIFF) { - GPU_link(mat, "shade_is_no_diffuse", &is); - } - else if(lamp->type == LA_HEMI) { - GPU_link(mat, "shade_is_hemi", inp, &is); - } - else { - if(lamp->type == LA_AREA) { - float area[4][4], areasize; - - memset(&area, 0, sizeof(area)); - memset(&areasize, 0, sizeof(areasize)); - mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO; - GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), GPU_dynamic_uniform(lamp->dynvec), vn, GPU_uniform((float*)area), - GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp); - } - - is= inp; /* Lambert */ - - if(!(G.fileflags & G_FILE_GLSL_NO_SHADERS)) { - if(ma->diff_shader==MA_DIFF_ORENNAYAR) - GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is); - else if(ma->diff_shader==MA_DIFF_TOON) - GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); - else if(ma->diff_shader==MA_DIFF_MINNAERT) - GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is); - else if(ma->diff_shader==MA_DIFF_FRESNEL) - GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); - } - } - - if(!(G.fileflags & G_FILE_GLSL_NO_SHADERS)) - if(ma->shade_flag & MA_CUBIC) - GPU_link(mat, "shade_cubic", is, &is); - - i = is; - GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i); - - vn = shi->vn; - /*if(ma->mode & MA_TANGENT_VN) - GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/ - - /* this replaces if(i > 0.0) conditional until that is supported */ - // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); - - if((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) { - if(!(G.fileflags & G_FILE_GLSL_NO_SHADOWS)) { - mat->dynproperty |= DYN_LAMP_PERSMAT; - - GPU_link(mat, "test_shadowbuf", - GPU_builtin(GPU_VIEW_POSITION), - GPU_dynamic_texture(lamp->tex), - GPU_dynamic_uniform((float*)lamp->dynpersmat), - GPU_uniform(&lamp->bias), inp, &shadfac); - - if(lamp->mode & LA_ONLYSHADOW) { - GPU_link(mat, "shade_only_shadow", i, shadfac, - GPU_dynamic_uniform(&lamp->dynenergy), &shadfac); - - if(!(lamp->mode & LA_NO_DIFF)) - GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb, - shr->diff, &shr->diff); - - if(!(lamp->mode & LA_NO_SPEC)) - GPU_link(mat, "shade_only_shadow_specular", shadfac, shi->specrgb, - shr->spec, &shr->spec); - - add_user_list(&mat->lamps, lamp); - add_user_list(&lamp->materials, ma); - return; - } - - GPU_link(mat, "math_multiply", i, shadfac, &i); - } - } - else if((G.fileflags & G_FILE_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) { - add_user_list(&mat->lamps, lamp); - add_user_list(&lamp->materials, ma); - return; - } - else - GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac); - - if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) { - if(!(lamp->mode & LA_NO_DIFF)) { - GPUNodeLink *rgb; - GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol), &rgb); - add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff); - } - } - - if(G.fileflags & G_FILE_GLSL_NO_SHADERS); - else if(!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) && - (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) { - if(lamp->type == LA_HEMI) { - GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t); - GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol); - GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); - } - else { - if(ma->spec_shader==MA_SPEC_PHONG) - GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac); - else if(ma->spec_shader==MA_SPEC_COOKTORR) - GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac); - else if(ma->spec_shader==MA_SPEC_BLINN) - GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac); - else if(ma->spec_shader==MA_SPEC_WARDISO) - GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac); - else - GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac); - - if(lamp->type==LA_AREA) - GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac); - - GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t); - - if(ma->mode & MA_RAMP_SPEC) { - GPUNodeLink *spec; - do_specular_ramp(shi, specfac, t, &spec); - GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), spec, &outcol); - GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); - } - else { - GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol); - GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); - } - } - } - - add_user_list(&mat->lamps, lamp); - add_user_list(&lamp->materials, ma); -} - -static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) -{ - Base *base; - Object *ob; - Scene *sce; - GPULamp *lamp; - - for(SETLOOPER(shi->gpumat->scene, base)) { - ob= base->object; - - if(ob->type==OB_LAMP) { - lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL); - if(lamp) - shade_one_light(shi, shr, lamp); - } - - if (ob->transflag & OB_DUPLI) { - DupliObject *dob; - ListBase *lb = object_duplilist(shi->gpumat->scene, ob); - - for(dob=lb->first; dob; dob=dob->next) { - Object *ob = dob->ob; - - if(ob->type==OB_LAMP) { - Mat4CpyMat4(ob->obmat, dob->mat); - - lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, base->object); - if(lamp) - shade_one_light(shi, shr, lamp); - } - } - - free_object_duplilist(lb); - } - } -} - -static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in) -{ - switch(blendtype) { - case MTEX_BLEND: - GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in); - break; - case MTEX_MUL: - GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in); - break; - case MTEX_SCREEN: - GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in); - break; - case MTEX_OVERLAY: - GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in); - break; - case MTEX_SUB: - GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in); - break; - case MTEX_ADD: - GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in); - break; - case MTEX_DIV: - GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in); - break; - case MTEX_DIFF: - GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in); - break; - case MTEX_DARK: - GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in); - break; - case MTEX_LIGHT: - GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in); - break; - case MTEX_BLEND_HUE: - GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in); - break; - case MTEX_BLEND_SAT: - GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in); - break; - case MTEX_BLEND_VAL: - GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in); - break; - case MTEX_BLEND_COLOR: - GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in); - break; - default: - GPU_link(mat, "set_rgb_zero", &in); - break; - } -} - -static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, int flip, GPUNodeLink **in) -{ - float flipf = (flip)? 1.0f: 0.0; - - switch(blendtype) { - case MTEX_BLEND: - GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_MUL: - GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_SCREEN: - GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_SUB: - GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_ADD: - GPU_link(mat, "mtex_value_add", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_DIV: - GPU_link(mat, "mtex_value_div", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_DIFF: - GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_DARK: - GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - case MTEX_LIGHT: - GPU_link(mat, "mtex_value_light", out, tex, fact, facg, GPU_uniform(&flipf), in); - break; - default: - GPU_link(mat, "set_value_zero", &in); - break; - } -} - -static void do_material_tex(GPUShadeInput *shi) -{ - Material *ma= shi->mat; - GPUMaterial *mat= shi->gpumat; - MTex *mtex; - Tex *tex; - GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac; - GPUNodeLink *texco_norm, *texco_orco, *texco_object, *texco_tangent; - GPUNodeLink *texco_global, *texco_uv = NULL; - GPUNodeLink *colfac, *newnor, *varfac, *orn; - char *lastuvname = NULL; - float one = 1.0f, norfac, ofs[3]; - int tex_nr, rgbnor, talpha; - - GPU_link(mat, "set_value", GPU_uniform(&one), &stencil); - - GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm); - GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco); - GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), - GPU_builtin(GPU_VIEW_POSITION), &texco_object); - GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); - GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), - GPU_builtin(GPU_VIEW_POSITION), &texco_global); - - orn= texco_norm; - - /* go over texture slots */ - for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { - mtex= ma->mtex[tex_nr]; - - tex= mtex->tex; - if(tex==0) continue; - - /* which coords */ - if(mtex->texco==TEXCO_ORCO) - texco= texco_orco; - else if(mtex->texco==TEXCO_OBJECT) - texco= texco_object; - else if(mtex->texco==TEXCO_NORM) - texco= texco_norm; - else if(mtex->texco==TEXCO_TANGENT) - texco= texco_object; - else if(mtex->texco==TEXCO_GLOB) - texco= texco_global; - else if(mtex->texco==TEXCO_REFL) - texco= shi->ref; - else if(mtex->texco==TEXCO_UV) { - if(1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) { - GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv); - lastuvname = mtex->uvname; - } - texco= texco_uv; - } - else - continue; - - /* in case of uv, this would just undo a multiplication in texco_uv */ - if(mtex->texco != TEXCO_UV) - GPU_link(mat, "mtex_2d_mapping", texco, &texco); - - if(mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) - GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco); - - ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0]; - ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1]; - ofs[2] = 0.0f; - if(ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) - GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); - - talpha = 0; - rgbnor = 0; - - if(tex && tex->type == TEX_IMAGE && tex->ima) { - GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, NULL), &tin, &trgb, &tnor); - rgbnor= TEX_RGB; - - if(tex->imaflag & TEX_USEALPHA) - talpha= 1; - } - else continue; - - /* texture output */ - if((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { - GPU_link(mat, "mtex_rgbtoint", trgb, &tin); - rgbnor -= TEX_RGB; - } - - if(mtex->texflag & MTEX_NEGATIVE) { - if(rgbnor & TEX_RGB) - GPU_link(mat, "mtex_rgb_invert", trgb, &trgb); - else - GPU_link(mat, "mtex_value_invert", tin, &tin); - } - - if(mtex->texflag & MTEX_STENCIL) { - if(rgbnor & TEX_RGB) - GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb); - else - GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin); - } - - /* mapping */ - if(mtex->mapto & (MAP_COL+MAP_COLSPEC)) { - /* stencil maps on the texture control slider, not texture intensity value */ - if(mtex->colfac == 1.0f) - colfac = stencil; - else - GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac); - - if((rgbnor & TEX_RGB)==0) { - GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol); - } - else { - GPU_link(mat, "set_rgba", trgb, &tcol); - - if(mtex->mapto & MAP_ALPHA) - GPU_link(mat, "set_value", stencil, &tin); - else if(talpha) - GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); - else - GPU_link(mat, "set_value_one", &tin); - } - - if(mtex->mapto & MAP_COL) - texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb); - - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) - texture_rgb_blend(mat, tcol, shi->specrgb, tin, colfac, mtex->blendtype, &shi->specrgb); - } - - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) { - if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; - else tex->norfac= mtex->norfac; - - if((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) { - tex->norfac = mtex->norfac; - - if(mtex->maptoneg & MAP_NORM) - GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor); - - if(mtex->normapspace == MTEX_NSPACE_TANGENT) - GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor); - else - newnor = tnor; - - norfac = MIN2(mtex->norfac, 1.0); - if(norfac == 1.0f && !GPU_link_changed(stencil)) { - shi->vn = newnor; - } - else { - tnorfac = GPU_uniform(&norfac); - - if(GPU_link_changed(stencil)) - GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); - - GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn); - } - } - - GPU_link(mat, "vec_math_negate", shi->vn, &orn); - GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); - } - - if((mtex->mapto & MAP_VARS)) { - if(mtex->varfac == 1.0f) - varfac = stencil; - else - GPU_link(mat, "math_multiply", GPU_uniform(&mtex->varfac), stencil, &varfac); - - if(rgbnor & TEX_RGB) { - if(talpha) - GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); - else - GPU_link(mat, "mtex_rgbtoint", trgb, &tin); - } - - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) { - int flip= mtex->maptoneg & MAP_REF; - texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->refl, tin, varfac, mtex->blendtype, flip, &shi->refl); - GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl); - } - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) { - int flip= mtex->maptoneg & MAP_SPEC; - texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->spec, tin, varfac, mtex->blendtype, flip, &shi->spec); - GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec); - } - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) { - int flip= mtex->maptoneg & MAP_EMIT; - texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->emit, tin, varfac, mtex->blendtype, flip, &shi->emit); - GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit); - } - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) { - int flip= mtex->maptoneg & MAP_HAR; - GPU_link(mat, "mtex_har_divide", shi->har, &shi->har); - texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->har, tin, varfac, mtex->blendtype, flip, &shi->har); - GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har); - } - if(mtex->mapto & MAP_ALPHA) { - int flip= mtex->maptoneg & MAP_ALPHA; - texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, varfac, mtex->blendtype, flip, &shi->alpha); - GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha); - } - if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) { - int flip= mtex->maptoneg & MAP_AMB; - texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->amb, tin, varfac, mtex->blendtype, flip, &shi->amb); - GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb); - } - } - } - } -} - -void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) -{ - float hard = ma->har; - - memset(shi, 0, sizeof(*shi)); - - shi->gpumat = mat; - shi->mat = ma; - - GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb); - GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb); - GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn); - GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha); - GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl); - GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec); - GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit); - GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har); - GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb); - GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view); - GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol); - GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); -} - -void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) -{ - GPUMaterial *mat= shi->gpumat; - GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac; - Material *ma= shi->mat; - World *world= mat->scene->world; - float linfac, logfac, misttype; - - memset(shr, 0, sizeof(*shr)); - - if(ma->mode & MA_VERTEXCOLP) - shi->rgb = shi->vcol; - - do_material_tex(shi); - - if(ma->mode & MA_ZTRA) - GPU_material_enable_alpha(mat); - - if((G.fileflags & G_FILE_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) { - shr->combined = shi->rgb; - shr->alpha = shi->alpha; - } - else { - if(GPU_link_changed(shi->emit) || ma->emit != 0.0f) { - if((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) { - GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit); - GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff); - } - else - GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff); - } - else - GPU_link(mat, "set_rgb_zero", &shr->diff); - - GPU_link(mat, "set_rgb_zero", &shr->spec); - - material_lights(shi, shr); - - shr->combined = shr->diff; - shr->alpha = shi->alpha; - - if(world) { - /* exposure correction */ - if(world->exp!=0.0f || world->range!=1.0f) { - linfac= 1.0 + pow((2.0*world->exp + 0.5), -10); - logfac= log((linfac-1.0)/linfac)/world->range; - - GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac); - GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac); - - GPU_link(mat, "shade_exposure_correct", shr->combined, - ulinfac, ulogfac, &shr->combined); - GPU_link(mat, "shade_exposure_correct", shr->spec, - ulinfac, ulogfac, &shr->spec); - } - - /* ambient color */ - if(world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) { - if(GPU_link_changed(shi->amb) || ma->amb != 0.0f) - GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), - GPU_uniform(&world->ambr), &shr->combined); - } - } - - if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined); - if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec); - - if(GPU_link_changed(shi->spec) || ma->spec != 0.0f) - GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined); - } - - GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined); - - if(ma->shade_flag & MA_OBCOLOR) - GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); - - if(world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) { - misttype = world->mistype; - - GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION), - GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist), - GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac); - - GPU_link(mat, "mix_blend", mistfac, shr->combined, - GPU_uniform(&world->horr), &shr->combined); - } - - if(!(ma->mode & MA_ZTRA)) { - if(world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f)) - GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr), - shr->combined, &shr->combined); - - GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined); - } - - if(ma->shade_flag & MA_OBCOLOR) { - mat->obcolalpha = 1; - GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); - } -} - -GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) -{ - GPUShadeInput shi; - GPUShadeResult shr; - - GPU_shadeinput_set(mat, ma, &shi); - GPU_shaderesult_set(&shi, &shr); - - return shr.combined; -} - -GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) -{ - GPUMaterial *mat; - GPUNodeLink *outlink; - LinkData *link; - - for(link=ma->gpumaterial.first; link; link=link->next) - if(((GPUMaterial*)link->data)->scene == scene) - return link->data; - - mat = GPU_material_construct_begin(ma); - mat->scene = scene; - - if(!(G.fileflags & G_FILE_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) { - ntreeGPUMaterialNodes(ma->nodetree, mat); - } - else { - outlink = GPU_blender_material(mat, ma); - GPU_material_output_link(mat, outlink); - } - - /*if(!GPU_material_construct_end(mat)) { - GPU_material_free(mat); - mat= NULL; - return 0; - }*/ - - GPU_material_construct_end(mat); - - link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); - link->data = mat; - BLI_addtail(&ma->gpumaterial, link); - - return mat; -} - -void GPU_materials_free() -{ - Object *ob; - Material *ma; - extern Material defmaterial; - - for(ma=G.main->mat.first; ma; ma=ma->id.next) - GPU_material_free(ma); - - GPU_material_free(&defmaterial); - - for(ob=G.main->object.first; ma; ma=ma->id.next) - GPU_lamp_free(ob); -} - -/* Lamps and shadow buffers */ - -void GPU_lamp_update(GPULamp *lamp, int lay, float obmat[][4]) -{ - float mat[4][4]; - - lamp->lay = lay; - - Mat4CpyMat4(mat, obmat); - Mat4Ortho(mat); - - VECCOPY(lamp->vec, mat[2]); - VECCOPY(lamp->co, mat[3]); - Mat4CpyMat4(lamp->obmat, mat); - Mat4Invert(lamp->imat, mat); -} - -static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) -{ - float temp, angle, pixsize, wsize; - - lamp->scene = scene; - lamp->ob = ob; - lamp->par = par; - lamp->la = la; - - /* add_render_lamp */ - lamp->mode = la->mode; - lamp->type = la->type; - - lamp->energy = la->energy; - if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy; - - lamp->col[0]= la->r*lamp->energy; - lamp->col[1]= la->g*lamp->energy; - lamp->col[2]= la->b*lamp->energy; - - GPU_lamp_update(lamp, ob->lay, ob->obmat); - - lamp->spotsi= la->spotsize; - if(lamp->mode & LA_HALO) - if(lamp->spotsi > 170.0) - lamp->spotsi = 170.0; - lamp->spotsi= cos(M_PI*lamp->spotsi/360.0); - lamp->spotbl= (1.0 - lamp->spotsi)*la->spotblend; - lamp->k= la->k; - - lamp->dist= la->dist; - lamp->falloff_type= la->falloff_type; - lamp->att1= la->att1; - lamp->att2= la->att2; - lamp->curfalloff= la->curfalloff; - - /* initshadowbuf */ - lamp->bias = 0.02f*la->bias; - lamp->size = la->bufsize; - lamp->d= la->clipsta; - lamp->clipend= la->clipend; - - /* arbitrary correction for the fact we do no soft transition */ - lamp->bias *= 0.25f; - - /* makeshadowbuf */ - angle= saacos(lamp->spotsi); - temp= 0.5f*lamp->size*cos(angle)/sin(angle); - pixsize= (lamp->d)/temp; - wsize= pixsize*0.5f*lamp->size; - - i_window(-wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend, lamp->winmat); -} - -static void gpu_lamp_shadow_free(GPULamp *lamp) -{ - if(lamp->tex) - GPU_texture_free(lamp->tex); - if(lamp->fb) - GPU_framebuffer_free(lamp->fb); -} - -GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) -{ - Lamp *la; - GPULamp *lamp; - LinkData *link; - - for(link=ob->gpulamp.first; link; link=link->next) { - lamp = (GPULamp*)link->data; - - if(lamp->par == par && lamp->scene == scene) - return link->data; - } - - lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); - - link = MEM_callocN(sizeof(LinkData), "GPULampLink"); - link->data = lamp; - BLI_addtail(&ob->gpulamp, link); - - la = ob->data; - gpu_lamp_from_blender(scene, ob, par, la, lamp); - - if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF)) { - /* opengl */ - lamp->fb = GPU_framebuffer_create(); - if(!lamp->fb) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size); - if(!lamp->tex) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if(!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - GPU_framebuffer_restore(); - } - - return lamp; -} - -void GPU_lamp_free(Object *ob) -{ - GPULamp *lamp; - LinkData *link; - LinkData *nlink; - Material *ma; - - for(link=ob->gpulamp.first; link; link=link->next) { - lamp = link->data; - - while(lamp->materials.first) { - nlink = lamp->materials.first; - ma = nlink->data; - BLI_freelinkN(&lamp->materials, nlink); - - if(ma->gpumaterial.first) - GPU_material_free(ma); - } - - gpu_lamp_shadow_free(lamp); - - MEM_freeN(lamp); - } - - BLI_freelistN(&ob->gpulamp); -} - -int GPU_lamp_has_shadow_buffer(GPULamp *lamp) -{ - return (!(G.fileflags & G_FILE_GLSL_NO_SHADOWS) && - !(G.fileflags & G_FILE_GLSL_NO_LIGHTS) && - lamp->tex && lamp->fb); -} - -void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]) -{ - float rangemat[4][4], persmat[4][4]; - - /* initshadowbuf */ - Mat4Invert(lamp->viewmat, lamp->obmat); - Normalize(lamp->viewmat[0]); - Normalize(lamp->viewmat[1]); - Normalize(lamp->viewmat[2]); - - /* makeshadowbuf */ - Mat4MulMat4(persmat, lamp->viewmat, lamp->winmat); - - /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ - Mat4One(rangemat); - rangemat[0][0] = 0.5f; - rangemat[1][1] = 0.5f; - rangemat[2][2] = 0.5f; - rangemat[3][0] = 0.5f; - rangemat[3][1] = 0.5f; - rangemat[3][2] = 0.5f; - - Mat4MulMat4(lamp->persmat, persmat, rangemat); - - /* opengl */ - GPU_framebuffer_texture_bind(lamp->fb, lamp->tex); - - /* set matrices */ - Mat4CpyMat4(viewmat, lamp->viewmat); - Mat4CpyMat4(winmat, lamp->winmat); - *winsize = lamp->size; -} - -void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) -{ - GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); - GPU_framebuffer_restore(); -} - -int GPU_lamp_shadow_layer(GPULamp *lamp) -{ - if(lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW))) - return lamp->lay; - else - return -1; -} - diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl b/source/blender/gpu/intern/gpu_shader_material.glsl deleted file mode 100644 index 16ed38cb47d..00000000000 --- a/source/blender/gpu/intern/gpu_shader_material.glsl +++ /dev/null @@ -1,1555 +0,0 @@ - -float exp_blender(float f) -{ - return pow(2.71828182846, f); -} - -void rgb_to_hsv(vec4 rgb, out vec4 outcol) -{ - float cmax, cmin, h, s, v, cdelta; - vec3 c; - - cmax = max(rgb[0], max(rgb[1], rgb[2])); - cmin = min(rgb[0], min(rgb[1], rgb[2])); - cdelta = cmax-cmin; - - v = cmax; - if (cmax!=0.0) - s = cdelta/cmax; - else { - s = 0.0; - h = 0.0; - } - - if (s == 0.0) { - h = 0.0; - } - else { - c = (vec3(cmax, cmax, cmax) - rgb.xyz)/cdelta; - - if (rgb.x==cmax) h = c[2] - c[1]; - else if (rgb.y==cmax) h = 2.0 + c[0] - c[2]; - else h = 4.0 + c[1] - c[0]; - - h /= 6.0; - - if (h<0.0) - h += 1.0; - } - - outcol = vec4(h, s, v, rgb.w); -} - -void hsv_to_rgb(vec4 hsv, out vec4 outcol) -{ - float i, f, p, q, t, h, s, v; - vec3 rgb; - - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; - - if(s==0.0) { - rgb = vec3(v, v, v); - } - else { - if(h==1.0) - h = 0.0; - - h *= 6.0; - i = floor(h); - f = h - i; - rgb = vec3(f, f, f); - p = v*(1.0-s); - q = v*(1.0-(s*f)); - t = v*(1.0-(s*(1.0-f))); - - if (i == 0.0) rgb = vec3(v, t, p); - else if (i == 1.0) rgb = vec3(q, v, p); - else if (i == 2.0) rgb = vec3(p, v, t); - else if (i == 3.0) rgb = vec3(p, q, v); - else if (i == 4.0) rgb = vec3(t, p, v); - else rgb = vec3(v, p, q); - } - - outcol = vec4(rgb, hsv.w); -} - -#define M_PI 3.14159265358979323846 - -/*********** SHADER NODES ***************/ - -void vcol_attribute(vec4 attvcol, out vec4 vcol) -{ - vcol = vec4(attvcol.x/255.0, attvcol.y/255.0, attvcol.z/255.0, 1.0); -} - -void uv_attribute(vec2 attuv, out vec3 uv) -{ - uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); -} - -void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol, out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv, out vec3 normal, out vec4 vcol, out float frontback) -{ - local = co; - view = normalize(local); - global = (viewinvmat*vec4(local, 1.0)).xyz; - orco = attorco; - uv_attribute(attuv, uv); - normal = -normalize(nor); /* blender render normal is negated */ - vcol_attribute(attvcol, vcol); - frontback = 1.0; -} - -void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec) -{ - outvec = (mat * vec4(vec, 1.0)).xyz; - if(domin == 1.0) - outvec = max(outvec, minvec); - if(domax == 1.0) - outvec = min(outvec, maxvec); -} - -void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) -{ - outdepth = abs(co.z); - outdist = length(co); - outview = normalize(co); -} - -void math_add(float val1, float val2, out float outval) -{ - outval = val1 + val2; -} - -void math_subtract(float val1, float val2, out float outval) -{ - outval = val1 - val2; -} - -void math_multiply(float val1, float val2, out float outval) -{ - outval = val1 * val2; -} - -void math_divide(float val1, float val2, out float outval) -{ - if (val2 == 0.0) - outval = 0.0; - else - outval = val1 / val2; -} - -void math_sine(float val, out float outval) -{ - outval = sin(val); -} - -void math_cosine(float val, out float outval) -{ - outval = cos(val); -} - -void math_tangent(float val, out float outval) -{ - outval = tan(val); -} - -void math_asin(float val, out float outval) -{ - if (val <= 1.0 && val >= -1.0) - outval = asin(val); - else - outval = 0.0; -} - -void math_acos(float val, out float outval) -{ - if (val <= 1.0 && val >= -1.0) - outval = acos(val); - else - outval = 0.0; -} - -void math_atan(float val, out float outval) -{ - outval = atan(val); -} - -void math_pow(float val1, float val2, out float outval) -{ - if (val1 >= 0.0) - outval = pow(val1, val2); - else - outval = 0.0; -} - -void math_log(float val1, float val2, out float outval) -{ - if(val1 > 0.0 && val2 > 0.0) - outval= log2(val1) / log2(val2); - else - outval= 0.0; -} - -void math_max(float val1, float val2, out float outval) -{ - outval = max(val1, val2); -} - -void math_min(float val1, float val2, out float outval) -{ - outval = min(val1, val2); -} - -void math_round(float val, out float outval) -{ - outval= floor(val + 0.5); -} - -void math_less_than(float val1, float val2, out float outval) -{ - if(val1 < val2) - outval = 1.0; - else - outval = 0.0; -} - -void math_greater_than(float val1, float val2, out float outval) -{ - if(val1 > val2) - outval = 1.0; - else - outval = 0.0; -} - -void squeeze(float val, float width, float center, out float outval) -{ - outval = 1.0/(1.0 + pow(2.71828183, -((val-center)*width))); -} - -void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = v1 + v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0; -} - -void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = v1 - v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0; -} - -void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = v1 + v2; - outval = length(outvec); - outvec = normalize(outvec); -} - -void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = vec3(0, 0, 0); - outval = dot(v1, v2); -} - -void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval) -{ - outvec = cross(v1, v2); - outval = length(outvec); -} - -void vec_math_normalize(vec3 v, out vec3 outvec, out float outval) -{ - outval = length(v); - outvec = normalize(v); -} - -void vec_math_negate(vec3 v, out vec3 outv) -{ - outv = -v; -} - -void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot) -{ - outnor = dir; - outdot = -dot(dir, nor); -} - -void curves_vec(vec3 vec, sampler1D curvemap, out vec3 outvec) -{ - outvec.x = texture1D(curvemap, (vec.x + 1.0)*0.5).x; - outvec.y = texture1D(curvemap, (vec.y + 1.0)*0.5).y; - outvec.z = texture1D(curvemap, (vec.z + 1.0)*0.5).z; -} - -void curves_rgb(vec4 col, sampler1D curvemap, out vec4 outcol) -{ - outcol.r = texture1D(curvemap, texture1D(curvemap, col.r).a).r; - outcol.g = texture1D(curvemap, texture1D(curvemap, col.g).a).g; - outcol.b = texture1D(curvemap, texture1D(curvemap, col.b).a).b; - outcol.a = col.a; -} - -void set_value(float val, out float outval) -{ - outval = val; -} - -void set_rgb(vec3 col, out vec3 outcol) -{ - outcol = col; -} - -void set_rgba(vec4 col, out vec4 outcol) -{ - outcol = col; -} - -void set_value_zero(out float outval) -{ - outval = 0.0; -} - -void set_value_one(out float outval) -{ - outval = 1.0; -} - -void set_rgb_zero(out vec3 outval) -{ - outval = vec3(0.0); -} - -void set_rgba_zero(out vec4 outval) -{ - outval = vec4(0.0); -} - -void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col2, fac); - outcol.a = col1.a; -} - -void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 + col2, fac); - outcol.a = col1.a; -} - -void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 * col2, fac); - outcol.a = col1.a; -} - -void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = vec4(1.0) - (vec4(facm) + fac*(vec4(1.0) - col2))*(vec4(1.0) - col1); - outcol.a = col1.a; -} - -void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - if(outcol.r < 0.5) - outcol.r *= facm + 2.0*fac*col2.r; - else - outcol.r = 1.0 - (facm + 2.0*fac*(1.0 - col2.r))*(1.0 - outcol.r); - - if(outcol.g < 0.5) - outcol.g *= facm + 2.0*fac*col2.g; - else - outcol.g = 1.0 - (facm + 2.0*fac*(1.0 - col2.g))*(1.0 - outcol.g); - - if(outcol.b < 0.5) - outcol.b *= facm + 2.0*fac*col2.b; - else - outcol.b = 1.0 - (facm + 2.0*fac*(1.0 - col2.b))*(1.0 - outcol.b); -} - -void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 - col2, fac); - outcol.a = col1.a; -} - -void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - if(col2.r != 0.0) outcol.r = facm*outcol.r + fac*outcol.r/col2.r; - if(col2.g != 0.0) outcol.g = facm*outcol.g + fac*outcol.g/col2.g; - if(col2.b != 0.0) outcol.b = facm*outcol.b + fac*outcol.b/col2.b; -} - -void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, abs(col1 - col2), fac); - outcol.a = col1.a; -} - -void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = min(col1.rgb, col2.rgb*fac); - outcol.a = col1.a; -} - -void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = max(col1.rgb, col2.rgb*fac); - outcol.a = col1.a; -} - -void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - outcol = col1; - - if(outcol.r != 0.0) { - float tmp = 1.0 - fac*col2.r; - if(tmp <= 0.0) - outcol.r = 1.0; - else if((tmp = outcol.r/tmp) > 1.0) - outcol.r = 1.0; - else - outcol.r = tmp; - } - if(outcol.g != 0.0) { - float tmp = 1.0 - fac*col2.g; - if(tmp <= 0.0) - outcol.g = 1.0; - else if((tmp = outcol.g/tmp) > 1.0) - outcol.g = 1.0; - else - outcol.g = tmp; - } - if(outcol.b != 0.0) { - float tmp = 1.0 - fac*col2.b; - if(tmp <= 0.0) - outcol.b = 1.0; - else if((tmp = outcol.b/tmp) > 1.0) - outcol.b = 1.0; - else - outcol.b = tmp; - } -} - -void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float tmp, facm = 1.0 - fac; - - outcol = col1; - - tmp = facm + fac*col2.r; - if(tmp <= 0.0) - outcol.r = 0.0; - else if((tmp = (1.0 - (1.0 - outcol.r)/tmp)) < 0.0) - outcol.r = 0.0; - else if(tmp > 1.0) - outcol.r = 1.0; - else - outcol.r = tmp; - - tmp = facm + fac*col2.g; - if(tmp <= 0.0) - outcol.g = 0.0; - else if((tmp = (1.0 - (1.0 - outcol.g)/tmp)) < 0.0) - outcol.g = 0.0; - else if(tmp > 1.0) - outcol.g = 1.0; - else - outcol.g = tmp; - - tmp = facm + fac*col2.b; - if(tmp <= 0.0) - outcol.b = 0.0; - else if((tmp = (1.0 - (1.0 - outcol.b)/tmp)) < 0.0) - outcol.b = 0.0; - else if(tmp > 1.0) - outcol.b = 1.0; - else - outcol.b = tmp; -} - -void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); - - if(hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv_to_rgb(hsv, tmp); - - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } -} - -void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2; - rgb_to_hsv(outcol, hsv); - - if(hsv.y != 0.0) { - rgb_to_hsv(col2, hsv2); - - hsv.y = facm*hsv.y + fac*hsv2.y; - hsv_to_rgb(hsv, outcol); - } -} - -void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - vec4 hsv, hsv2; - rgb_to_hsv(col1, hsv); - rgb_to_hsv(col2, hsv2); - - hsv.z = facm*hsv.z + fac*hsv2.z; - hsv_to_rgb(hsv, outcol); -} - -void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) -{ - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; - - outcol = col1; - - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); - - if(hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv.y = hsv2.y; - hsv_to_rgb(hsv, tmp); - - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } -} - -void valtorgb(float fac, sampler1D colormap, out vec4 outcol, out float outalpha) -{ - outcol = texture1D(colormap, fac); - outalpha = outcol.a; -} - -void rgbtobw(vec4 color, out float outval) -{ - outval = color.r*0.35 + color.g*0.45 + color.b*0.2; -} - -void invert(float fac, vec4 col, out vec4 outcol) -{ - outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac); - outcol.w = col.w; -} - -void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) -{ - vec4 hsv; - - rgb_to_hsv(col, hsv); - - hsv[0] += (hue - 0.5); - if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0; - hsv[1] *= sat; - if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0; - hsv[2] *= value; - if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0; - - hsv_to_rgb(hsv, outcol); - - outcol = mix(col, outcol, fac); -} - -void separate_rgb(vec4 col, out float r, out float g, out float b) -{ - r = col.r; - g = col.g; - b = col.b; -} - -void combine_rgb(float r, float g, float b, out vec4 col) -{ - col = vec4(r, g, b, 1.0); -} - -void output_node(vec4 rgb, float alpha, out vec4 outrgb) -{ - outrgb = vec4(rgb.rgb, alpha); -} - -/*********** TEXTURES ***************/ - -void texture_flip_blend(vec3 vec, out vec3 outvec) -{ - outvec = vec.yxz; -} - -void texture_blend_lin(vec3 vec, out float outval) -{ - outval = (1.0+vec.x)/2.0; -} - -void texture_blend_quad(vec3 vec, out float outval) -{ - outval = max((1.0+vec.x)/2.0, 0.0); - outval *= outval; -} - -void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal) -{ - float a = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)*20.0; - float wi = 0.5 + 0.5*sin(a); - - value = wi; - color = vec4(wi, wi, wi, 1.0); - normal = vec3(0.0, 0.0, 0.0); -} - -void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) -{ - color = texture2D(ima, (vec.xy + vec2(1.0, 1.0))*0.5); - value = 1.0; - - normal.x = 2.0*(color.r - 0.5); - normal.y = 2.0*(0.5 - color.g); - normal.z = 2.0*(color.b - 0.5); -} - -/************* MTEX *****************/ - -void texco_orco(vec3 attorco, out vec3 orco) -{ - orco = attorco; -} - -void texco_uv(vec2 attuv, out vec3 uv) -{ - /* disabled for now, works together with leaving out mtex_2d_mapping - uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */ - uv = vec3(attuv, 0.0); -} - -void texco_norm(vec3 normal, out vec3 outnormal) -{ - /* corresponds to shi->orn, which is negated so cancels - out blender normal negation */ - outnormal = normalize(normal); -} - -void texco_tangent(vec3 tangent, out vec3 outtangent) -{ - outtangent = normalize(tangent); -} - -void texco_global(mat4 viewinvmat, vec3 co, out vec3 global) -{ - global = (viewinvmat*vec4(co, 1.0)).xyz; -} - -void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object) -{ - object = (obinvmat*(viewinvmat*vec4(co, 1.0))).xyz; -} - -void texco_refl(vec3 vn, vec3 view, out vec3 ref) -{ - ref = view - 2.0*dot(vn, view)*vn; -} - -void shade_norm(vec3 normal, out vec3 outnormal) -{ - /* blender render normal is negated */ - outnormal = -normalize(normal); -} - -void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0-fact; - - incol = fact*texcol + facm*outcol; -} - -void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0-facg; - - incol = (facm + fact*texcol)*outcol; -} - -void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0-facg; - - incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol); -} - -void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0-facg; - - if(outcol.r < 0.5) - incol.r = outcol.r*(facm + 2.0*fact*texcol.r); - else - incol.r = 1.0 - (facm + 2.0*fact*(1.0 - texcol.r))*(1.0 - outcol.r); - - if(outcol.g < 0.5) - incol.g = outcol.g*(facm + 2.0*fact*texcol.g); - else - incol.g = 1.0 - (facm + 2.0*fact*(1.0 - texcol.g))*(1.0 - outcol.g); - - if(outcol.b < 0.5) - incol.b = outcol.b*(facm + 2.0*fact*texcol.b); - else - incol.b = 1.0 - (facm + 2.0*fact*(1.0 - texcol.b))*(1.0 - outcol.b); -} - -void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - incol = -fact*facg*texcol + outcol; -} - -void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - incol = fact*facg*texcol + outcol; -} - -void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0-fact; - - if(texcol.r != 0.0) incol.r = facm*outcol.r + fact*outcol.r/texcol.r; - if(texcol.g != 0.0) incol.g = facm*outcol.g + fact*outcol.g/texcol.g; - if(texcol.b != 0.0) incol.b = facm*outcol.b + fact*outcol.b/texcol.b; -} - -void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm; - - fact *= facg; - facm = 1.0-fact; - - incol = facm*outcol + fact*abs(texcol - outcol); -} - -void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm, col; - - fact *= facg; - facm = 1.0-fact; - - col = fact*texcol.r; - if(col < outcol.r) incol.r = col; else incol.r = outcol.r; - col = fact*texcol.g; - if(col < outcol.g) incol.g = col; else incol.g = outcol.g; - col = fact*texcol.b; - if(col < outcol.b) incol.b = col; else incol.b = outcol.b; -} - -void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - float facm, col; - - fact *= facg; - facm = 1.0-fact; - - col = fact*texcol.r; - if(col > outcol.r) incol.r = col; else incol.r = outcol.r; - col = fact*texcol.g; - if(col > outcol.g) incol.g = col; else incol.g = outcol.g; - col = fact*texcol.b; - if(col > outcol.b) incol.b = col; else incol.b = outcol.b; -} - -void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_hue(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_sat(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_val(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) -{ - vec4 col; - - mix_color(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); - incol.rgb = col.rgb; -} - -void mtex_value_vars(inout float fact, float facg, out float facm, float flip) -{ - fact *= facg; - facm = 1.0-fact; - - if(flip != 0.0) { - float tmp = fact; - fact = facm; - facm = tmp; - } -} - -void mtex_value_blend(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - incol = fact*texcol + facm*outcol; -} - -void mtex_value_mul(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - facm = 1.0 - facg; - incol = (facm + fact*texcol)*outcol; -} - -void mtex_value_screen(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - facm = 1.0 - facg; - incol = 1.0 - (facm + fact*(1.0 - texcol))*(1.0 - outcol); -} - -void mtex_value_sub(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - fact = -fact; - incol = fact*texcol + outcol; -} - -void mtex_value_add(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - fact = fact; - incol = fact*texcol + outcol; -} - -void mtex_value_div(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - if(texcol != 0.0) - incol = facm*outcol + fact*outcol/texcol; - else - incol = 0.0; -} - -void mtex_value_diff(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - incol = facm*outcol + fact*abs(texcol - outcol); -} - -void mtex_value_dark(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - float col = fact*texcol; - if(col < outcol) incol = col; else incol = outcol; -} - -void mtex_value_light(float outcol, float texcol, float fact, float facg, float flip, out float incol) -{ - float facm; - mtex_value_vars(fact, facg, facm, flip); - - float col = fact*texcol; - if(col > outcol) incol = col; else incol = outcol; -} - -void mtex_value_clamp_positive(float fac, out float outfac) -{ - outfac = max(fac, 0.0); -} - -void mtex_value_clamp(float fac, out float outfac) -{ - outfac = clamp(fac, 0.0, 1.0); -} - -void mtex_har_divide(float har, out float outhar) -{ - outhar = har/128.0; -} - -void mtex_har_multiply_clamp(float har, out float outhar) -{ - har *= 128.0; - - if(har < 1.0) outhar = 1.0; - else if(har > 511.0) outhar = 511.0; - else outhar = har; -} - -void mtex_alpha_from_col(vec4 col, out float alpha) -{ - alpha = col.a; -} - -void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol) -{ - outcol = vec4(col.rgb, alpha); -} - -void mtex_rgbtoint(vec4 rgb, out float intensity) -{ - intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb); -} - -void mtex_value_invert(float invalue, out float outvalue) -{ - outvalue = 1.0 - invalue; -} - -void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb) -{ - outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a); -} - -void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity) -{ - float fact = intensity; - outintensity = intensity*stencil; - outstencil = stencil*fact; -} - -void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb) -{ - float fact = rgb.a; - outrgb = vec4(rgb.rgb, rgb.a*stencil); - outstencil = stencil*fact; -} - -void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco) -{ - outtexco = texco + ofs; -} - -void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco) -{ - outtexco = size*texco; -} - -void mtex_2d_mapping(vec3 vec, out vec3 outvec) -{ - outvec = vec3(vec.xy*0.5 + vec2(0.5, 0.5), vec.z); -} - -void mtex_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) -{ - color = texture2D(ima, vec.xy); - value = 1.0; - - normal = 2.0*(vec3(color.r, -color.g, color.b) - vec3(0.5, -0.5, 0.5)); -} - -void mtex_negate_texnormal(vec3 normal, out vec3 outnormal) -{ - outnormal = vec3(-normal.x, -normal.y, normal.z); -} - -void mtex_nspace_tangent(vec3 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) -{ - tangent = normalize(tangent); - vec3 B = cross(normal, tangent); - - outnormal = texnormal.x*tangent + texnormal.y*B + texnormal.z*normal; - outnormal = normalize(outnormal); -} - -void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) -{ - outnormal = (1.0 - norfac)*normal + norfac*newnormal; - outnormal = normalize(outnormal); -} - -/******* MATERIAL *********/ - -void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac) -{ - lv = lampvec; - dist = 1.0; - visifac = 1.0; -} - -void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac) -{ - lv = co - lampco; - dist = length(lv); - lv = normalize(lv); - visifac = 1.0; -} - -void lamp_falloff_invlinear(float lampdist, float dist, out float visifac) -{ - visifac = lampdist/(lampdist + dist); -} - -void lamp_falloff_invsquare(float lampdist, float dist, out float visifac) -{ - visifac = lampdist/(lampdist + dist*dist); -} - -void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac) -{ - float lampdistkw = lampdist*lampdist; - - visifac = lampdist/(lampdist + ld1*dist); - visifac *= lampdistkw/(lampdistkw + ld2*dist*dist); -} - -void lamp_falloff_curve(float lampdist, sampler1D curvemap, float dist, out float visifac) -{ - visifac = texture1D(curvemap, dist/lampdist).x; -} - -void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac) -{ - float t= lampdist - dist; - - outvisifac= visifac*max(t, 0.0)/lampdist; -} - -void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr) -{ - if(dot(lv, lampvec) > 0.0) { - vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz; - float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z)); - - inpr = 1.0/sqrt(1.0 + x*x); - } - else - inpr = 0.0; -} - -void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr) -{ - inpr = dot(lv, lampvec); -} - -void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac) -{ - float t = spotsi; - - if(inpr <= t) { - outvisifac = 0.0; - } - else { - t = inpr - t; - - /* soft area */ - if(spotbl != 0.0) - inpr *= smoothstep(0.0, 1.0, t/spotbl); - - outvisifac = visifac*inpr; - } -} - -void lamp_visibility_clamp(float visifac, out float outvisifac) -{ - outvisifac = (visifac < 0.001)? 0.0: visifac; -} - -void shade_view(vec3 co, out vec3 view) -{ - /* handle perspective/orthographic */ - view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(co): vec3(0.0, 0.0, -1.0); -} - -void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn) -{ - vec3 c = cross(lv, tang); - vec3 vnor = cross(c, tang); - - vn = -normalize(vnor); -} - -void shade_inp(vec3 vn, vec3 lv, out float inp) -{ - inp = dot(vn, lv); -} - -void shade_is_no_diffuse(out float is) -{ - is = 0.0; -} - -void shade_is_hemi(float inp, out float is) -{ - is = 0.5*inp + 0.5; -} - -float area_lamp_energy(mat4 area, vec3 co, vec3 vn) -{ - vec3 vec[4], c[4]; - float rad[4], fac; - - vec[0] = normalize(co - area[0].xyz); - vec[1] = normalize(co - area[1].xyz); - vec[2] = normalize(co - area[2].xyz); - vec[3] = normalize(co - area[3].xyz); - - c[0] = normalize(cross(vec[0], vec[1])); - c[1] = normalize(cross(vec[1], vec[2])); - c[2] = normalize(cross(vec[2], vec[3])); - c[3] = normalize(cross(vec[3], vec[0])); - - rad[0] = acos(dot(vec[0], vec[1])); - rad[1] = acos(dot(vec[1], vec[2])); - rad[2] = acos(dot(vec[2], vec[3])); - rad[3] = acos(dot(vec[3], vec[0])); - - fac= rad[0]*dot(vn, c[0]); - fac+= rad[1]*dot(vn, c[1]); - fac+= rad[2]*dot(vn, c[2]); - fac+= rad[3]*dot(vn, c[3]); - - return max(fac, 0.0); -} - -void shade_inp_area(vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k, out float inp) -{ - vec3 co = position; - vec3 vec = co - lampco; - - if(dot(vec, lampvec) < 0.0) { - inp = 0.0; - } - else { - float intens = area_lamp_energy(area, co, vn); - - inp = pow(intens*areasize, k); - } -} - -void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is) -{ - vec3 h = normalize(v + l); - float nh = max(dot(n, h), 0.0); - float nv = max(dot(n, v), 0.0); - float realnl = dot(n, l); - - if(realnl < 0.0) { - is = 0.0; - } - else if(nl < 0.0) { - is = 0.0; - } - else { - float vh = max(dot(v, h), 0.0); - float Lit_A = acos(realnl); - float View_A = acos(nv); - - vec3 Lit_B = normalize(l - realnl*n); - vec3 View_B = normalize(v - nv*n); - - float t = max(dot(Lit_B, View_B), 0.0); - - float a, b; - - if(Lit_A > View_A) { - a = Lit_A; - b = View_A; - } - else { - a = View_A; - b = Lit_A; - } - - float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33))); - float B = 0.45*((rough*rough)/((rough*rough) + 0.09)); - - b *= 0.95; - is = nl*(A + (B * t * sin(a) * tan(b))); - } -} - -void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is) -{ - float rslt = dot(n, l); - float ang = acos(rslt); - - if(ang < size) is = 1.0; - else if(ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0; - else is = 1.0 - ((ang - size)/tsmooth); -} - -void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is) -{ - if(nl <= 0.0) { - is = 0.0; - } - else { - float nv = max(dot(n, v), 0.0); - - if(darkness <= 1.0) - is = nl*pow(max(nv*nl, 0.1), darkness - 1.0); - else - is = nl*pow(1.0001 - nv, darkness - 1.0); - } -} - -float fresnel_fac(vec3 view, vec3 vn, float grad, float fac) -{ - float t1, t2; - float ffac; - - if(fac==0.0) { - ffac = 1.0; - } - else { - t1= dot(view, vn); - if(t1>0.0) t2= 1.0+t1; - else t2= 1.0-t1; - - t2= grad + (1.0-grad)*pow(t2, fac); - - if(t2<0.0) ffac = 0.0; - else if(t2>1.0) ffac = 1.0; - else ffac = t2; - } - - return ffac; -} - -void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is) -{ - is = fresnel_fac(lv, vn, fac_i, fac); -} - -void shade_cubic(float is, out float outis) -{ - if(is>0.0 && is<1.0) - outis= smoothstep(0.0, 1.0, is); - else - outis= is; -} - -void shade_visifac(float i, float visifac, float refl, out float outi) -{ - /*if(i > 0.0)*/ - outi = max(i*visifac*refl, 0.0); - /*else - outi = i;*/ -} - -void shade_tangent_v_spec(vec3 tang, out vec3 vn) -{ - vn = tang; -} - -void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol) -{ - if(i > 0.0) - outcol = i*lampcol*col; - else - outcol = vec3(0.0, 0.0, 0.0); -} - -void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t) -{ - lv += view; - lv = normalize(lv); - - t = dot(vn, lv); - t = 0.5*t + 0.5; - - t = visifac*spec*pow(t, hard); -} - -void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) -{ - vec3 h = normalize(l + v); - float rslt = max(dot(h, n), 0.0); - - specfac = pow(rslt, hard); -} - -void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) -{ - vec3 h = normalize(v + l); - float nh = dot(n, h); - - if(nh < 0.0) { - specfac = 0.0; - } - else { - float nv = max(dot(n, v), 0.0); - float i = pow(nh, hard); - - i = i/(0.1+nv); - specfac = i; - } -} - -void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac) -{ - if(refrac < 1.0) { - specfac = 0.0; - } - else if(spec_power == 0.0) { - specfac = 0.0; - } - else { - if(spec_power<100.0) - spec_power= sqrt(1.0/spec_power); - else - spec_power= 10.0/spec_power; - - vec3 h = normalize(v + l); - float nh = dot(n, h); - if(nh < 0.0) { - specfac = 0.0; - } - else { - float nv = max(dot(n, v), 0.01); - float nl = dot(n, l); - if(nl <= 0.01) { - specfac = 0.0; - } - else { - float vh = max(dot(v, h), 0.01); - - float a = 1.0; - float b = (2.0*nh*nv)/vh; - float c = (2.0*nh*nl)/vh; - - float g = 0.0; - - if(a < b && a < c) g = a; - else if(b < a && b < c) g = b; - else if(c < a && c < b) g = c; - - float p = sqrt(((refrac * refrac)+(vh*vh)-1.0)); - float f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1.0+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0)))); - float ang = acos(nh); - - specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0); - } - } - } -} - -void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac) -{ - vec3 h = normalize(l + v); - float nh = max(dot(n, h), 0.001); - float nv = max(dot(n, v), 0.001); - float nl = max(dot(n, l), 0.001); - float angle = tan(acos(nh)); - float alpha = max(rms, 0.001); - - specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp_blender(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl))); -} - -void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac) -{ - vec3 h = normalize(l + v); - float rslt = dot(h, n); - float ang = acos(rslt); - - if(ang < size) rslt = 1.0; - else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0; - else rslt = 1.0 - ((ang - size)/tsmooth); - - specfac = rslt; -} - -void shade_spec_area_inp(float specfac, float inp, out float outspecfac) -{ - outspecfac = specfac*inp; -} - -void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t) -{ - t = shadfac*spec*visifac*specfac; -} - -void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol) -{ - outcol = t*lampcol*speccol; -} - -void shade_add(vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col1 + col2; -} - -void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col + col1*col2; -} - -void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol) -{ - outcol = col + f*col1; -} - -void shade_mul(vec4 col1, vec4 col2, out vec4 outcol) -{ - outcol = col1*col2; -} - -void shade_mul_value(float fac, vec4 col, out vec4 outcol) -{ - outcol = col*fac; -} - -void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) -{ - outcol = vec4(col.rgb*obcol.rgb, col.a); -} - -void ramp_rgbtobw(vec3 color, out float outval) -{ - outval = color.r*0.3 + color.g*0.58 + color.b*0.12; -} - -void shade_only_shadow(float i, float shadfac, float energy, out float outshadfac) -{ - outshadfac = i*energy*(1.0 - shadfac); -} - -void shade_only_shadow_diffuse(float shadfac, vec3 rgb, vec4 diff, out vec4 outdiff) -{ - outdiff = diff - vec4(rgb*shadfac, 0.0); -} - -void shade_only_shadow_specular(float shadfac, vec3 specrgb, vec4 spec, out vec4 outspec) -{ - outspec = spec - vec4(specrgb*shadfac, 0.0); -} - -void test_shadowbuf(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp, out float result) -{ - if(inp <= 0.0) { - result = 0.0; - } - else { - vec4 co = shadowpersmat*vec4(rco, 1.0); - - //float bias = (1.5 - inp*inp)*shadowbias; - co.z -= shadowbias*co.w; - - result = shadow2DProj(shadowmap, co).x; - } -} - -void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol) -{ - outcol = linfac*(1.0 - exp(col*logfac)); -} - -void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac) -{ - float fac, zcor; - - zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; - - fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0); - if(misttype == 0.0) fac *= fac; - else if(misttype == 1.0); - else fac = sqrt(fac); - - outfac = 1.0 - (1.0-fac)*(1.0-misi); -} - -void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol) -{ - float fac = clamp(col.a, 0.0, 1.0); - outcol = vec4(mix(hor, col.rgb, fac), col.a); -} - -void shade_alpha_opaque(vec4 col, out vec4 outcol) -{ - outcol = vec4(col.rgb, 1.0); -} - -void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) -{ - outcol = vec4(col.rgb, col.a*obcol.a); -} - diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl.c b/source/blender/gpu/intern/gpu_shader_material.glsl.c deleted file mode 100644 index 8287efe84ea..00000000000 --- a/source/blender/gpu/intern/gpu_shader_material.glsl.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* DataToC output of file */ - -int datatoc_gpu_shader_material_glsl_size= 32828; -char datatoc_gpu_shader_material_glsl[]= { - 10,102,108,111, 97,116, 32,101,120,112, 95, 98,108,101,110,100,101,114, 40,102,108,111, 97,116, 32,102, 41, 10, -123, 10, 9,114,101,116,117,114,110, 32,112,111,119, 40, 50, 46, 55, 49, 56, 50, 56, 49, 56, 50, 56, 52, 54, 44, 32,102, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,114,103, 98, 95,116,111, 95,104,115,118, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117, -116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, 99,109, 97,120, 44, 32, 99,109, -105,110, 44, 32,104, 44, 32,115, 44, 32,118, 44, 32, 99,100,101,108,116, 97, 59, 10, 9,118,101, 99, 51, 32, 99, 59, 10, 10, 9, - 99,109, 97,120, 32, 61, 32,109, 97,120, 40,114,103, 98, 91, 48, 93, 44, 32,109, 97,120, 40,114,103, 98, 91, 49, 93, 44, 32,114, -103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,109,105,110, 32, 61, 32,109,105,110, 40,114,103, 98, 91, 48, 93, 44, 32,109,105,110, - 40,114,103, 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,100,101,108,116, 97, 32, 61, 32, 99,109, 97, -120, 45, 99,109,105,110, 59, 10, 10, 9,118, 32, 61, 32, 99,109, 97,120, 59, 10, 9,105,102, 32, 40, 99,109, 97,120, 33, 61, 48, - 46, 48, 41, 10, 9, 9,115, 32, 61, 32, 99,100,101,108,116, 97, 47, 99,109, 97,120, 59, 10, 9,101,108,115,101, 32,123, 10, 9, - 9,115, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 10, 9,105,102, 32, 40,115, 32, - 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, - 9, 9, 99, 32, 61, 32, 40,118,101, 99, 51, 40, 99,109, 97,120, 44, 32, 99,109, 97,120, 44, 32, 99,109, 97,120, 41, 32, 45, 32, -114,103, 98, 46,120,121,122, 41, 47, 99,100,101,108,116, 97, 59, 10, 10, 9, 9,105,102, 32, 40,114,103, 98, 46,120, 61, 61, 99, -109, 97,120, 41, 32,104, 32, 61, 32, 99, 91, 50, 93, 32, 45, 32, 99, 91, 49, 93, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, - 40,114,103, 98, 46,121, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 50, 46, 48, 32, 43, 32, 99, 91, 48, 93, 32, 45, 32, 32, - 99, 91, 50, 93, 59, 10, 9, 9,101,108,115,101, 32,104, 32, 61, 32, 52, 46, 48, 32, 43, 32, 99, 91, 49, 93, 32, 45, 32, 99, 91, - 48, 93, 59, 10, 10, 9, 9,104, 32, 47, 61, 32, 54, 46, 48, 59, 10, 10, 9, 9,105,102, 32, 40,104, 60, 48, 46, 48, 41, 10, 9, - 9, 9,104, 32, 43, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,104, - 44, 32,115, 44, 32,118, 44, 32,114,103, 98, 46,119, 41, 59, 10,125, 10, 10,118,111,105,100, 32,104,115,118, 95,116,111, 95,114, -103, 98, 40,118,101, 99, 52, 32,104,115,118, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, - 9,102,108,111, 97,116, 32,105, 44, 32,102, 44, 32,112, 44, 32,113, 44, 32,116, 44, 32,104, 44, 32,115, 44, 32,118, 59, 10, 9, -118,101, 99, 51, 32,114,103, 98, 59, 10, 10, 9,104, 32, 61, 32,104,115,118, 91, 48, 93, 59, 10, 9,115, 32, 61, 32,104,115,118, - 91, 49, 93, 59, 10, 9,118, 32, 61, 32,104,115,118, 91, 50, 93, 59, 10, 10, 9,105,102, 40,115, 61, 61, 48, 46, 48, 41, 32,123, - 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,118, 44, 32,118, 41, 59, 10, 9,125, 10, 9,101,108,115,101, - 32,123, 10, 9, 9,105,102, 40,104, 61, 61, 49, 46, 48, 41, 10, 9, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9, 10, 9, - 9,104, 32, 42, 61, 32, 54, 46, 48, 59, 10, 9, 9,105, 32, 61, 32,102,108,111,111,114, 40,104, 41, 59, 10, 9, 9,102, 32, 61, - 32,104, 32, 45, 32,105, 59, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,102, 44, 32,102, 44, 32,102, 41, 59, 10, 9, - 9,112, 32, 61, 32,118, 42, 40, 49, 46, 48, 45,115, 41, 59, 10, 9, 9,113, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, -102, 41, 41, 59, 10, 9, 9,116, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, 40, 49, 46, 48, 45,102, 41, 41, 41, 59, 10, - 9, 9, 10, 9, 9,105,102, 32, 40,105, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, - 32,116, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 49, 46, 48, 41, 32,114,103, 98, - 32, 61, 32,118,101, 99, 51, 40,113, 44, 32,118, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, - 61, 32, 50, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,118, 44, 32,116, 41, 59, 10, 9, 9,101,108, -115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 51, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,113, - 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 52, 46, 48, 41, 32,114,103, 98, 32, 61, - 32,118,101, 99, 51, 40,116, 44, 32,112, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,114,103, 98, 32, 61, 32,118,101, 99, - 51, 40,118, 44, 32,112, 44, 32,113, 41, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,114, -103, 98, 44, 32,104,115,118, 46,119, 41, 59, 10,125, 10, 10, 35,100,101,102,105,110,101, 32, 77, 95, 80, 73, 32, 51, 46, 49, 52, - 49, 53, 57, 50, 54, 53, 51, 53, 56, 57, 55, 57, 51, 50, 51, 56, 52, 54, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, 68, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10, -118,111,105,100, 32,118, 99,111,108, 95, 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 41, 10,123, 10, 9,118, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, - 97,116,116,118, 99,111,108, 46,120, 47, 50, 53, 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46,121, 47, 50, 53, 53, 46, 48, - 44, 32, 97,116,116,118, 99,111,108, 46,122, 47, 50, 53, 53, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, - 32,117,118, 95, 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, - 99, 51, 32,117,118, 41, 10,123, 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32, -118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,103,101, -111,109, 40,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,109, 97,116, 52, 32,118,105,101,119,105, -110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 97,116,116,111,114, 99,111, 44, 32,118,101, 99, 50, 32, 97,116,116,117,118, 44, - 32,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 44, 32, -111,117,116, 32,118,101, 99, 51, 32,108,111, 99, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,111, -117,116, 32,118,101, 99, 51, 32,111,114, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32,111,117,116, 32,118, -101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 44, 32,111,117,116, 32,102, -108,111, 97,116, 32,102,114,111,110,116, 98, 97, 99,107, 41, 10,123, 10, 9,108,111, 99, 97,108, 32, 61, 32, 99,111, 59, 10, 9, -118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,111, 99, 97,108, 41, 59, 10, 9,103,108,111, 98, 97,108, - 32, 61, 32, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40,108,111, 99, 97,108, 44, 32, 49, 46, 48, 41, 41, - 46,120,121,122, 59, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99,111, 59, 10, 9,117,118, 95, 97,116,116,114,105, - 98,117,116,101, 40, 97,116,116,117,118, 44, 32,117,118, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32, 45,110,111,114,109, - 97,108,105,122,101, 40,110,111,114, 41, 59, 9, 47, 42, 32, 98,108,101,110,100,101,114, 32,114,101,110,100,101,114, 32,110,111, -114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,118, 99,111,108, 95, 97,116,116,114,105, 98,117, -116,101, 40, 97,116,116,118, 99,111,108, 44, 32,118, 99,111,108, 41, 59, 10, 9,102,114,111,110,116, 98, 97, 99,107, 32, 61, 32, - 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,109, - 97,116, 52, 32,109, 97,116, 44, 32,118,101, 99, 51, 32,109,105,110,118,101, 99, 44, 32,118,101, 99, 51, 32,109, 97,120,118,101, - 99, 44, 32,102,108,111, 97,116, 32,100,111,109,105,110, 44, 32,102,108,111, 97,116, 32,100,111,109, 97,120, 44, 32,111,117,116, - 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 40,109, 97,116, 32, 42, - 32,118,101, 99, 52, 40,118,101, 99, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,105,102, 40,100,111,109,105,110, 32, - 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32,109, 97,120, 40,111,117,116,118,101, 99, 44, 32,109, -105,110,118,101, 99, 41, 59, 10, 9,105,102, 40,100,111,109, 97,120, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118, -101, 99, 32, 61, 32,109,105,110, 40,111,117,116,118,101, 99, 44, 32,109, 97,120,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105, -100, 32, 99, 97,109,101,114, 97, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,105, -101,119, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,101,112,116,104, 44, 32,111,117,116, 32,102,108,111, 97, -116, 32,111,117,116,100,105,115,116, 41, 10,123, 10, 9,111,117,116,100,101,112,116,104, 32, 61, 32, 97, 98,115, 40, 99,111, 46, -122, 41, 59, 10, 9,111,117,116,100,105,115,116, 32, 61, 32,108,101,110,103,116,104, 40, 99,111, 41, 59, 10, 9,111,117,116,118, -105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116, -104, 95, 97,100,100, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, - 32, 43, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,115,117, 98,116,114, 97, 99,116, 40,102, -108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 45, 32,118, 97,108, 50, - 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,117,108,116,105,112,108,121, 40,102,108,111, 97,116, 32,118, 97, -108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, - 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 42, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111, -105,100, 32,109, 97,116,104, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, - 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40, -118, 97,108, 50, 32, 61, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, -115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 47, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111, -105,100, 32,109, 97,116,104, 95,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97, -116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,115,105,110, 40,118, 97,108, 41, 59, 10, -125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 99,111,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111, -117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,115, - 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,116, 97,110,103,101,110,116, 40,102,108,111, 97, -116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, - 97,108, 32, 61, 32,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,115,105,110, - 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, - 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, - 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97,115,105,110, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117, -116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97, 99,111,115, 40,102,108, -111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, - 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, 9, 9,111, -117,116,118, 97,108, 32, 61, 32, 97, 99,111,115, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97, -108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,116, 97,110, 40,102,108,111, 97,116, - 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97, -108, 32, 61, 32, 97,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,112,111,119, 40, -102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97, -116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40,118, 97,108, 49, 32, 62, 61, 32, 48, 46, 48, 41, 10, 9, 9, -111,117,116,118, 97,108, 32, 61, 32,112,111,119, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, - 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,111,103, - 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, - 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32, 48, 46, 48, 32, 32, 38, 38, 32, -118, 97,108, 50, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 61, 32,108,111,103, 50, 40,118, 97,108, 49, 41, - 32, 47, 32,108,111,103, 50, 40,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 61, 32, 48, - 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109, 97,120, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, - 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, - 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118, -111,105,100, 32,109, 97,116,104, 95,109,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, - 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, - 32, 61, 32,109,105,110, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, - 95,114,111,117,110,100, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, - 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 61, 32,102,108,111,111,114, 40,118, 97,108, 32, 43, 32, 48, 46, 53, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,101,115,115, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97, -108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, - 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 60, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, - 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111, -105,100, 32,109, 97,116,104, 95,103,114,101, 97,116,101,114, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, - 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, - 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, - 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32, -115,113,117,101,101,122,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,102,108,111, 97,116, 32,119,105,100,116,104, 44, 32, -102,108,111, 97,116, 32, 99,101,110,116,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, -123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, 47, 40, 49, 46, 48, 32, 43, 32,112,111,119, 40, 50, 46, 55, 49, 56, - 50, 56, 49, 56, 51, 44, 32, 45, 40, 40,118, 97,108, 45, 99,101,110,116,101,114, 41, 42,119,105,100,116,104, 41, 41, 41, 59, 10, -125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,100,100, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, - 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97, -116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, 32,118, 50, 59, 10, 9, -111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98,115, 40,111, -117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, 46, 48, 59, - 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,115,117, 98, 40,118,101, 99, 51, 32,118, 49, 44, 32,118, -101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, - 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 45, 32,118, 50, 59, 10, - 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98,115, 40, -111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, 46, 48, - 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,118,101,114, 97,103,101, 40,118,101, 99, 51, 32, -118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, - 32,118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10, 9, -111,117,116,118,101, 99, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118, -111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,100,111,116, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, - 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117, -116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 44, 32, 48, 44, 32, 48, 41, 59, - 10, 9,111,117,116,118, 97,108, 32, 61, 32,100,111,116, 40,118, 49, 44, 32,118, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32, -118,101, 99, 95,109, 97,116,104, 95, 99,114,111,115,115, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, - 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, - 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 99,114,111,115,115, 40,118, 49, 44, 32,118, 50, 41, 59, 10, 9, -111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105,100, - 32,118,101, 99, 95,109, 97,116,104, 95,110,111,114,109, 97,108,105,122,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32, -118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, - 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,118, 41, 59, 10, 9,111,117,116,118,101, 99, 32, 61, 32, -110,111,114,109, 97,108,105,122,101, 40,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,110, -101,103, 97,116,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118, 41, 10,123, 10, 9, -111,117,116,118, 32, 61, 32, 45,118, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,100, -105,114, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114, 44, 32,111, -117,116, 32,102,108,111, 97,116, 32,111,117,116,100,111,116, 41, 10,123, 10, 9,111,117,116,110,111,114, 32, 61, 32,100,105,114, - 59, 10, 9,111,117,116,100,111,116, 32, 61, 32, 45,100,111,116, 40,100,105,114, 44, 32,110,111,114, 41, 59, 10,125, 10, 10,118, -111,105,100, 32, 99,117,114,118,101,115, 95,118,101, 99, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, - 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, - 9,111,117,116,118,101, 99, 46,120, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, - 40,118,101, 99, 46,120, 32, 43, 32, 49, 46, 48, 41, 42, 48, 46, 53, 41, 46,120, 59, 10, 9,111,117,116,118,101, 99, 46,121, 32, - 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 40,118,101, 99, 46,121, 32, 43, 32, 49, - 46, 48, 41, 42, 48, 46, 53, 41, 46,121, 59, 10, 9,111,117,116,118,101, 99, 46,122, 32, 61, 32,116,101,120,116,117,114,101, 49, - 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 40,118,101, 99, 46,122, 32, 43, 32, 49, 46, 48, 41, 42, 48, 46, 53, 41, 46,122, - 59, 10,125, 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,115, - 97,109,112,108,101,114, 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, -111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118, -101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46,114, 41, - 46, 97, 41, 46,114, 59, 10, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114, -118,101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46,103, - 41, 46, 97, 41, 46,103, 59, 10, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117, -114,118,101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46, - 98, 41, 46, 97, 41, 46, 98, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118, -111,105,100, 32,115,101,116, 95,118, 97,108,117,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, - 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 59, 10,125, 10, 10,118, -111,105,100, 32,115,101,116, 95,114,103, 98, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111, -117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32, -115,101,116, 95,114,103, 98, 97, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, -111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, - 95,118, 97,108,117,101, 95,122,101,114,111, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, - 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, - 95,111,110,101, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, - 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 95,122,101,114,111, 40,111,117,116, - 32,118,101, 99, 51, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, - 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 97, 95,122,101,114,111, 40,111,117,116, 32,118, -101, 99, 52, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 52, 40, 48, 46, 48, - 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, -118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, -117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, - 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 50, 44, 32, -102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105, -100, 32,109,105,120, 95, 97,100,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32, -118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, - 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99, -111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, - 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105, -120, 95,109,117,108,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, - 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, - 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, - 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 42, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9, -111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, - 99,114,101,101,110, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, - 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, - 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, - 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, - 49, 46, 48, 41, 32, 45, 32, 40,118,101, 99, 52, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99, 42, 40,118,101, 99, 52, 40, 49, - 46, 48, 41, 32, 45, 32, 99,111,108, 50, 41, 41, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 49, 41, 59, - 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, - 95,111,118,101,114,108, 97,121, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, -101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, - 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, - 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, -108, 49, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111, -108, 46,114, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,101, -108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, - 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117, -116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9, -111,117,116, 99,111,108, 46,103, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46, -103, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99, -109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,103, 41, 41, 42, 40, 49, 46, 48, - 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, - 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, - 99,111,108, 50, 46, 98, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, - 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46, 98, 41, 41, - 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, -117, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111, -108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, - 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105, -120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 45, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99, -111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,118, 40,102, -108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32, -111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, -102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, - 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99, -111,108, 50, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,114, 32, 61, 32,102, 97, 99,109, 42,111,117, -116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,114, 47, 99,111,108, 50, 46,114, 59, 10, 9,105, -102, 40, 99,111,108, 50, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, - 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,103, 47, 99,111,108, 50, 46,103, 59, - 10, 9,105,102, 40, 99,111,108, 50, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46, 98, 32, 61, 32,102, - 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46, 98, 47, 99,111,108, 50, - 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,102,102, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, -118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, -117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, - 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 97, 98,115, 40, 99,111, -108, 49, 32, 45, 32, 99,111,108, 50, 41, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111, -108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,102, 97, 99, - 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, - 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, - 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109,105,110, 40, 99,111,108, 49, 46,114, -103, 98, 44, 32, 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99, -111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,108,105,103,104,116, 40,102,108,111, 97,116, 32,102, - 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, - 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, - 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109, 97,120, 40, 99,111,108, 49, - 46,114,103, 98, 44, 32, 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, - 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,111,100,103,101, 40,102,108,111, 97,116, - 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32, -118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, - 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, - 40,111,117,116, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, - 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, - 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105, -102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46,114, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, - 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111, -108, 46,114, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, - 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, - 50, 46,103, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, -103, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, - 46,103, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, - 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9, -105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109, -112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, - 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, - 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, - 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, - 99,111,108, 46, 98, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,117,114,110, - 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109, -112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,116,109,112, 44, 32,102, 97, - 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, - 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40, -116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9,101, -108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99, -111,108, 46,114, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, - 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111, -108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,109, -112, 59, 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,105, -102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, 10, - 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117, -116, 99,111,108, 46,103, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, - 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, - 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, -116,109,112, 59, 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, - 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, 48, - 59, 10, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32, -111,117,116, 99,111,108, 46, 98, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, - 98, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111, -117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, - 61, 32,116,109,112, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,104,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, - 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, - 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, - 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, - 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115, -118, 50, 44, 32,116,109,112, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, - 59, 10, 10, 9,105,102, 40,104,115,118, 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, - 95,104,115,118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, - 50, 46,120, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, 10, 9, - 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, 41, 59, - 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, - 32,109,105,120, 95,115, 97,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, -101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, - 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, - 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, -108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115, -118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 46,121, 32, 33, 61, 32, 48, 46, - 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, - 9, 9,104,115,118, 46,121, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,121, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46, -121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 9,125, - 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,118, 97,108, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, - 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, -108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, - 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, - 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 49, 44, 32,104, -115,118, 41, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9, -104,115,118, 46,122, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,122, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,122, 59, - 10, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111, -105,100, 32,109,105,120, 95, 99,111,108,111,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, - 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, - 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102, -108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, - 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109,112, 59, 10, 9, -114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, 40,104,115,118, - 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99,111, -108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, 9,104,115,118, - 46,121, 32, 61, 32,104,115,118, 50, 46,121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116, -109,112, 41, 59, 32, 10, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109, -112, 44, 32,102, 97, 99, 41, 59, 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, - 10,125, 10, 10,118,111,105,100, 32,118, 97,108,116,111,114,103, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,115, 97,109, -112,108,101,114, 49, 68, 32, 99,111,108,111,114,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, - 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, 97,108,112,104, 97, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, - 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,111,108,111,114,109, 97,112, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, - 97,108,112,104, 97, 32, 61, 32,111,117,116, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98,116,111, 98, -119, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, -123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 53, 32, 43, 32, 99,111,108,111,114, - 46,103, 42, 48, 46, 52, 53, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 50, 59, 10,125, 10, 10,118,111,105,100, 32,105, -110,118,101,114,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118, -101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,120,121,122, 32, 61, 32,109,105,120, 40, - 99,111,108, 46,120,121,122, 44, 32,118,101, 99, 51, 40, 49, 46, 48, 44, 32, 49, 46, 48, 44, 32, 49, 46, 48, 41, 32, 45, 32, 99, -111,108, 46,120,121,122, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46,119, 32, 61, 32, 99,111,108, 46,119, 59, - 10,125, 10, 10,118,111,105,100, 32,104,117,101, 95,115, 97,116, 40,102,108,111, 97,116, 32,104,117,101, 44, 32,102,108,111, 97, -116, 32,115, 97,116, 44, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118, -101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,118,101, 99, - 52, 32,104,115,118, 59, 10, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, - 9,104,115,118, 91, 48, 93, 32, 43, 61, 32, 40,104,117,101, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,105,102, 40,104,115,118, 91, - 48, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 48, 93, 45, 61, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, - 91, 48, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 48, 93, 43, 61, 32, 49, 46, 48, 59, 10, 9,104,115,118, 91, 49, 93, 32, 42, - 61, 32,115, 97,116, 59, 10, 9,105,102, 40,104,115,118, 91, 49, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 49, - 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 49, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, - 48, 46, 48, 59, 10, 9,104,115,118, 91, 50, 93, 32, 42, 61, 32,118, 97,108,117,101, 59, 10, 9,105,102, 40,104,115,118, 91, 50, - 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 50, 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, - 50, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 50, 93, 61, 32, 48, 46, 48, 59, 10, 10, 9,104,115,118, 95,116,111, 95,114,103, - 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99, -111,108, 44, 32,111,117,116, 99,111,108, 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,112, 97,114, 97, -116,101, 95,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, 98, 41, 10,123, 10, 9,114, 32, 61, 32, 99, -111,108, 46,114, 59, 10, 9,103, 32, 61, 32, 99,111,108, 46,103, 59, 10, 9, 98, 32, 61, 32, 99,111,108, 46, 98, 59, 10,125, 10, - 10,118,111,105,100, 32, 99,111,109, 98,105,110,101, 95,114,103, 98, 40,102,108,111, 97,116, 32,114, 44, 32,102,108,111, 97,116, - 32,103, 44, 32,102,108,111, 97,116, 32, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 41, 10,123, 10, 9, 99,111, -108, 32, 61, 32,118,101, 99, 52, 40,114, 44, 32,103, 44, 32, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32, -111,117,116,112,117,116, 95,110,111,100,101, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, - 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32, -118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 42, 42, 32, 84, 69, 88, 84, 85, 82, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, - 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,102,108,105,112, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,118,101, - 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, -118,101, 99, 46,121,120,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,108, -105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, - 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 59, 10,125, 10, 10,118, -111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,113,117, 97,100, 40,118,101, 99, 51, 32,118,101, 99, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, - 97,120, 40, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10, 9,111,117,116,118, 97, -108, 32, 42, 61, 32,111,117,116,118, 97,108, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,119,111,111, -100, 95,115,105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, - 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, - 41, 10,123, 10, 9,102,108,111, 97,116, 32, 97, 32, 61, 32,115,113,114,116, 40,118,101, 99, 46,120, 42,118,101, 99, 46,120, 32, - 43, 32,118,101, 99, 46,121, 42,118,101, 99, 46,121, 32, 43, 32,118,101, 99, 46,122, 42,118,101, 99, 46,122, 41, 42, 50, 48, 46, - 48, 59, 10, 9,102,108,111, 97,116, 32,119,105, 32, 61, 32, 48, 46, 53, 32, 43, 32, 48, 46, 53, 42,115,105,110, 40, 97, 41, 59, - 10, 10, 9,118, 97,108,117,101, 32, 61, 32,119,105, 59, 10, 9, 99,111,108,111,114, 32, 61, 32,118,101, 99, 52, 40,119,105, 44, - 32,119,105, 44, 32,119,105, 44, 32, 49, 46, 48, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, - 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,105,109, - 97,103,101, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117, -116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114, -101, 50, 68, 40,105,109, 97, 44, 32, 40,118,101, 99, 46,120,121, 32, 43, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, - 41, 41, 42, 48, 46, 53, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 10, 9,110,111,114,109, 97,108, 46, -120, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108,111,114, 46,114, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,110,111,114,109, 97,108, - 46,121, 32, 61, 32, 50, 46, 48, 42, 40, 48, 46, 53, 32, 45, 32, 99,111,108,111,114, 46,103, 41, 59, 10, 9,110,111,114,109, 97, -108, 46,122, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108,111,114, 46, 98, 32, 45, 32, 48, 46, 53, 41, 59, 10,125, 10, 10, 47, 42, - 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 77, 84, 69, 88, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, - 42, 42, 42, 47, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,111,114, 99,111, 40,118,101, 99, 51, 32, 97,116,116,111,114, - 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,114, 99,111, 41, 10,123, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116, -111,114, 99,111, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,117,118, 40,118,101, 99, 50, 32, 97,116,116,117, -118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 41, 10,123, 10, 9, 47, 42, 32,100,105,115, 97, 98,108,101,100, 32,102, -111,114, 32,110,111,119, 44, 32,119,111,114,107,115, 32,116,111,103,101,116,104,101,114, 32,119,105,116,104, 32,108,101, 97,118, -105,110,103, 32,111,117,116, 32,109,116,101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 10, 9, 32, 32, 32,117,118, 32, 61, - 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, - 44, 32, 48, 46, 48, 41, 59, 32, 42, 47, 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 44, 32, 48, 46, 48, - 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97, -108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 99,111,114, -114,101,115,112,111,110,100,115, 32,116,111, 32,115,104,105, 45, 62,111,114,110, 44, 32,119,104,105, 99,104, 32,105,115, 32,110, -101,103, 97,116,101,100, 32,115,111, 32, 99, 97,110, 99,101,108,115, 10, 9, 32, 32, 32,111,117,116, 32, 98,108,101,110,100,101, -114, 32,110,111,114,109, 97,108, 32,110,101,103, 97,116,105,111,110, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97,108, 32, - 61, 32,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, - 99,111, 95,116, 97,110,103,101,110,116, 40,118,101, 99, 51, 32,116, 97,110,103,101,110,116, 44, 32,111,117,116, 32,118,101, 99, - 51, 32,111,117,116,116, 97,110,103,101,110,116, 41, 10,123, 10, 9,111,117,116,116, 97,110,103,101,110,116, 32, 61, 32,110,111, -114,109, 97,108,105,122,101, 40,116, 97,110,103,101,110,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95, -103,108,111, 98, 97,108, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, - 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 41, 10,123, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118, -105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10,125, 10, - 10,118,111,105,100, 32,116,101,120, 99,111, 95,111, 98,106,101, 99,116, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, - 97,116, 44, 32,109, 97,116, 52, 32,111, 98,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32, -118,101, 99, 51, 32,111, 98,106,101, 99,116, 41, 10,123, 10, 9,111, 98,106,101, 99,116, 32, 61, 32, 40,111, 98,105,110,118,109, - 97,116, 42, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 41, 46,120, -121,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,114,101,102,108, 40,118,101, 99, 51, 32,118,110, 44, 32, -118,101, 99, 51, 32,118,105,101,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102, 41, 10,123, 10, 9,114,101,102, 32, - 61, 32,118,105,101,119, 32, 45, 32, 50, 46, 48, 42,100,111,116, 40,118,110, 44, 32,118,105,101,119, 41, 42,118,110, 59, 10,125, - 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111, -117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 98,108,101,110,100,101,114, - 32,114,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,111,117, -116,110,111,114,109, 97,108, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, - 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, - 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, - 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, -102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, - 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32, -102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,109,117, -108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97, -116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99, -111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99, -103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32, 40, -102, 97, 99,109, 32, 43, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115, 99,114,101,101,110, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, - 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32, -102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, - 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, - 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32, 40,118,101, - 99, 51, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99,116, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,116,101,120, - 99,111,108, 41, 41, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,111,118,101,114,108, 97,121, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, - 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, - 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, -102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, - 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105, -110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, - 99,116, 42,116,101,120, 99,111,108, 46,114, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,114, 32, 61, 32, - 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101, -120, 99,111,108, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40, -111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99, -111,108, 46,103, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 41, 59, - 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, - 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,103, 41, 41, 42, 40, 49, 46, 48, - 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, - 53, 41, 10, 9, 9,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 42, 40,102, 97, 99,109, 32, 43, 32, - 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111, -108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, - 48, 32, 45, 32,116,101,120, 99,111,108, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115,117, 98, 40,118,101, 99, 51, 32,111,117,116, 99,111, -108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, -116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, - 32, 61, 32, 45,102, 97, 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, - 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 97,100,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, - 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32, -102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, - 32,102, 97, 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,100,105,118, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, - 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99, -103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, - 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, - 99,116, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46, -114, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46, -114, 47,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, - 32,105,110, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99,116, 42, -111,117,116, 99,111,108, 46,103, 47,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46, 98, 32, - 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, - 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46, 98, 47,116,101,120, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105, -100, 32,109,116,101,120, 95,114,103, 98, 95,100,105,102,102, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, - 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, - 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, - 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99, -116, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, - 97, 98,115, 40,116,101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,114,103, 98, 95,100, 97,114,107, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, -120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, -116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, - 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, - 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99, -111,108, 32, 60, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108, -115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, - 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46,103, 41, - 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111, -117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9, -105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, - 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111, -105,100, 32,109,116,101,120, 95,114,103, 98, 95,108,105,103,104,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118, -101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, - 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, -109, 44, 32, 99,111,108, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, - 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, - 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99, -111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111, -108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, - 99,111,108, 46,103, 41, 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, - 46,103, 32, 61, 32,111,117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111, -108, 46, 98, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, - 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, - 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,104,117,101, 40,118,101, 99, 51, 32,111,117,116, 99,111, -108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, -116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, - 99,111,108, 59, 10, 10, 9,109,105,120, 95,104,117,101, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111, -117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, - 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115, 97,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, - 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99, -103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, - 10, 9,109,105,120, 95,115, 97,116, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, - 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, - 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109, -116,101,120, 95,114,103, 98, 95,118, 97,108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, -120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, -116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, - 95,118, 97,108, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, - 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99, -111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, -103, 98, 95, 99,111,108,111,114, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111, -108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118, -101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95, 99,111, -108,111,114, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, - 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111, -108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97, -108,117,101, 95,118, 97,114,115, 40,105,110,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, - 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32,102,108,111, 97,116, 32,102,108,105, -112, 41, 10,123, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45, -102, 97, 99,116, 59, 10, 10, 9,105,102, 40,102,108,105,112, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97, -116, 32,116,109,112, 32, 61, 32,102, 97, 99,116, 59, 10, 9, 9,102, 97, 99,116, 32, 61, 32,102, 97, 99,109, 59, 10, 9, 9,102, - 97, 99,109, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, - 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111, -108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, - 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, - 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, - 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42, -116,101,120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, -101,120, 95,118, 97,108,117,101, 95,109,117,108, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, - 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, - 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, - 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, - 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, - 49, 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, 99, -116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, - 97,108,117,101, 95,115, 99,114,101,101,110, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32, -116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, -102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9, -102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99, -116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, - 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, - 43, 32,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117, -116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,117, 98, 40,102,108, -111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32, -102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109, -116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, - 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32, 45,102, 97, 99,116, 59, 10, 9,105,110, 99,111,108, 32, 61, - 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109, -116,101,120, 95,118, 97,108,117,101, 95, 97,100,100, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97, -116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, - 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, - 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, - 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, - 32,102, 97, 99,116, 59, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117, -116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,118, 40,102,108,111, - 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, - 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116, -101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32, -102,108,105,112, 41, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, 9,105,110, 99, -111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 47,116, -101,120, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118, -111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,102,102, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, - 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, -116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, - 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95, -118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9, -105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116, -101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97, -108,117,101, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, - 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, - 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, - 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32, -102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, - 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 41, 32, -105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, - 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,108,105,103,104,116, 40,102,108,111, 97,116, - 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99, -116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102, -108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, - 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108, -105,112, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, - 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 41, 32,105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101, -108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, - 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 95,112,111,115,105,116,105,118,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32,109, - 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, - 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, - 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, - 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, 97,114, 95,100,105,118,105,100,101, 40,102,108, -111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,111,117, -116,104, 97,114, 32, 61, 32,104, 97,114, 47, 49, 50, 56, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, - 97,114, 95,109,117,108,116,105,112,108,121, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,104, 97,114, 32, 42, 61, 32, 49, 50, 56, 46, 48, 59, 10, - 10, 9,105,102, 40,104, 97,114, 32, 60, 32, 49, 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101, -108,115,101, 32,105,102, 40,104, 97,114, 32, 62, 32, 53, 49, 49, 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 53, 49, 49, - 46, 48, 59, 10, 9,101,108,115,101, 32,111,117,116,104, 97,114, 32, 61, 32,104, 97,114, 59, 10,125, 10, 10,118,111,105,100, 32, -109,116,101,120, 95, 97,108,112,104, 97, 95,102,114,111,109, 95, 99,111,108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117, -116, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 41, 10,123, 10, 9, 97,108,112,104, 97, 32, 61, 32, 99,111,108, 46, 97, 59, - 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108,112,104, 97, 95,116,111, 95, 99,111,108, 40,118,101, 99, 52, 32, - 99,111,108, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, -108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 97,108,112, -104, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98,116,111,105,110,116, 40,118,101, 99, 52, 32, -114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,105,110,116, -101,110,115,105,116,121, 32, 61, 32,100,111,116, 40,118,101, 99, 51, 40, 48, 46, 51, 53, 44, 32, 48, 46, 52, 53, 44, 32, 48, 46, - 50, 41, 44, 32,114,103, 98, 46,114,103, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, - 95,105,110,118,101,114,116, 40,102,108,111, 97,116, 32,105,110,118, 97,108,117,101, 44, 32,111,117,116, 32,102,108,111, 97,116, - 32,111,117,116,118, 97,108,117,101, 41, 10,123, 10, 9,111,117,116,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 32, 45, 32,105, -110,118, 97,108,117,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,105,110,118,101,114,116, 40, -118,101, 99, 52, 32,105,110,114,103, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9, -111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,105,110,114,103, 98, 46, -114,103, 98, 44, 32,105,110,114,103, 98, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117, -101, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116,101,110, 99,105,108, 44, 32,102,108,111, 97,116, 32,105, -110,116,101,110,115,105,116,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32, -111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,102,108,111, 97,116, - 32,102, 97, 99,116, 32, 61, 32,105,110,116,101,110,115,105,116,121, 59, 10, 9,111,117,116,105,110,116,101,110,115,105,116,121, - 32, 61, 32,105,110,116,101,110,115,105,116,121, 42,115,116,101,110, 99,105,108, 59, 10, 9,111,117,116,115,116,101,110, 99,105, -108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, -103, 98, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116,101,110, 99,105,108, 44, 32,118,101, 99, 52, 32,114, -103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32,111,117,116, 32,118,101, - 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,116, 32, 61, 32,114,103, 98, 46, 97, - 59, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, 44, 32,114,103, 98, 46, 97, 42, -115,116,101,110, 99,105,108, 41, 59, 10, 9,111,117,116,115,116,101,110, 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42, -102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97,112,112,105,110,103, 95,111,102,115, 40,118, -101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,111,102,115, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117, -116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, 32, 61, 32,116,101,120, 99,111, 32, 43, 32,111,102, -115, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97,112,112,105,110,103, 95,115,105,122,101, 40,118,101, 99, - 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,115,105,122,101, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, -116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, 32, 61, 32,115,105,122,101, 42,116,101,120, 99,111, 59, - 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, - 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, -118,101, 99, 51, 40,118,101, 99, 46,120,121, 42, 48, 46, 53, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, - 44, 32,118,101, 99, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,105,109, 97,103,101, 40,118,101, 99, - 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, -118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32, -110,111,114,109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, - 44, 32,118,101, 99, 46,120,121, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 9, 10, 9,110,111,114,109, - 97,108, 32, 61, 32, 50, 46, 48, 42, 40,118,101, 99, 51, 40, 99,111,108,111,114, 46,114, 44, 32, 45, 99,111,108,111,114, 46,103, - 44, 32, 99,111,108,111,114, 46, 98, 41, 32, 45, 32,118,101, 99, 51, 40, 48, 46, 53, 44, 32, 45, 48, 46, 53, 44, 32, 48, 46, 53, - 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,110,101,103, 97,116,101, 95,116,101,120,110,111,114,109, 97, -108, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97, -108, 41, 10,123, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 45,110,111,114,109, 97,108, 46,120, - 44, 32, 45,110,111,114,109, 97,108, 46,121, 44, 32,110,111,114,109, 97,108, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32, -109,116,101,120, 95,110,115,112, 97, 99,101, 95,116, 97,110,103,101,110,116, 40,118,101, 99, 51, 32,116, 97,110,103,101,110,116, - 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,116,101,120,110,111,114,109, 97,108, 44, 32,111, -117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,116, 97,110,103,101,110,116, 32, 61, 32, -110,111,114,109, 97,108,105,122,101, 40,116, 97,110,103,101,110,116, 41, 59, 10, 9,118,101, 99, 51, 32, 66, 32, 61, 32, 99,114, -111,115,115, 40,110,111,114,109, 97,108, 44, 32,116, 97,110,103,101,110,116, 41, 59, 10, 10, 9,111,117,116,110,111,114,109, 97, -108, 32, 61, 32,116,101,120,110,111,114,109, 97,108, 46,120, 42,116, 97,110,103,101,110,116, 32, 43, 32,116,101,120,110,111,114, -109, 97,108, 46,121, 42, 66, 32, 43, 32,116,101,120,110,111,114,109, 97,108, 46,122, 42,110,111,114,109, 97,108, 59, 10, 9,111, -117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, - 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,108,101,110,100, 95,110,111,114,109, 97,108, 40,102,108,111, 97,116, - 32,110,111,114,102, 97, 99, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,110,101,119,110,111, -114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,111,117,116, -110,111,114,109, 97,108, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32,110,111,114,102, 97, 99, 41, 42,110,111,114,109, 97,108, 32, 43, - 32,110,111,114,102, 97, 99, 42,110,101,119,110,111,114,109, 97,108, 59, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32, -110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, - 42, 32, 77, 65, 84, 69, 82, 73, 65, 76, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,108, 97,109,112, - 95,118,105,115,105, 98,105,108,105,116,121, 95,115,117,110, 95,104,101,109,105, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, - 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32, -111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32,108, 97,109,112,118, -101, 99, 59, 10, 9,100,105,115,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, - 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,111,116,104,101,114, 40,118, -101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, - 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105, -102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 9,100,105,115,116, 32, - 61, 32,108,101,110,103,116,104, 40,108,118, 41, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,118, - 41, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95, -102, 97,108,108,111,102,102, 95,105,110,118,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, - 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, - 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, - 32, 43, 32,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,105, -110,118,115,113,117, 97,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100, -105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, - 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,100,105,115,116, 42,100, -105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,115,108,105,100,101, -114,115, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,108,100, 49, 44, 32,102,108, -111, 97,116, 32,108,100, 50, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, -105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116,107,119, 32, 61, 32,108, 97, -109,112,100,105,115,116, 42,108, 97,109,112,100,105,115,116, 59, 10, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109, -112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,108,100, 49, 42,100,105,115,116, 41, 59, 10, 9,118,105, -115,105,102, 97, 99, 32, 42, 61, 32,108, 97,109,112,100,105,115,116,107,119, 47, 40,108, 97,109,112,100,105,115,116,107,119, 32, - 43, 32,108,100, 50, 42,100,105,115,116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, - 97,108,108,111,102,102, 95, 99,117,114,118,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,115, 97,109, -112,108,101,114, 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,116,101,120, -116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,100,105,115,116, 47,108, 97,109,112,100,105,115,116, 41, 46, -120, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,104,101,114, -101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,102,108, -111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, - 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 61, 32,108, 97,109,112,100,105,115,116, 32, 45, 32,100,105,115,116, 59, 10, - 10, 9,111,117,116,118,105,115,105,102, 97, 99, 61, 32,118,105,115,105,102, 97, 99, 42,109, 97,120, 40,116, 44, 32, 48, 46, 48, - 41, 47,108, 97,109,112,100,105,115,116, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108, -105,116,121, 95,115,112,111,116, 95,115,113,117, 97,114,101, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,109, 97, -116, 52, 32,108, 97,109,112,105,109, 97,116, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, -105,110,112,114, 41, 10,123, 10, 9,105,102, 40,100,111,116, 40,108,118, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 62, 32, 48, - 46, 48, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,118,114,111,116, 32, 61, 32, 40,108, 97,109,112,105,109, 97,116, 42,118, -101, 99, 52, 40,108,118, 44, 32, 48, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,109, - 97,120, 40, 97, 98,115, 40,108,118,114,111,116, 46,120, 47,108,118,114,111,116, 46,122, 41, 44, 32, 97, 98,115, 40,108,118,114, -111,116, 46,121, 47,108,118,114,111,116, 46,122, 41, 41, 59, 10, 10, 9, 9,105,110,112,114, 32, 61, 32, 49, 46, 48, 47,115,113, -114,116, 40, 49, 46, 48, 32, 43, 32,120, 42,120, 41, 59, 10, 9,125, 10, 9,101,108,115,101, 10, 9, 9,105,110,112,114, 32, 61, - 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112, -111,116, 95, 99,105,114, 99,108,101, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,108,118, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, 10,123, 10, 9,105,110,112,114, 32, 61, 32,100,111,116, 40,108, -118, 44, 32,108, 97,109,112,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105, -108,105,116,121, 95,115,112,111,116, 40,102,108,111, 97,116, 32,115,112,111,116,115,105, 44, 32,102,108,111, 97,116, 32,115,112, -111,116, 98,108, 44, 32,102,108,111, 97,116, 32,105,110,112,114, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, - 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32, -116, 32, 61, 32,115,112,111,116,115,105, 59, 10, 10, 9,105,102, 40,105,110,112,114, 32, 60, 61, 32,116, 41, 32,123, 10, 9, 9, -111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, - 32, 61, 32,105,110,112,114, 32, 45, 32,116, 59, 10, 10, 9, 9, 47, 42, 32,115,111,102,116, 32, 97,114,101, 97, 32, 42, 47, 10, - 9, 9,105,102, 40,115,112,111,116, 98,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,105,110,112,114, 32, 42, 61, 32,115, -109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, 46, 48, 44, 32,116, 47,115,112,111,116, 98,108, 41, 59, 10, 10, - 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32,118,105,115,105,102, 97, 99, 42,105,110,112,114, 59, 10, 9,125, 10, -125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95, 99,108, 97,109,112, 40,102,108, -111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, - 99, 41, 10,123, 10, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 40,118,105,115,105,102, 97, 99, 32, 60, 32, 48, 46, - 48, 48, 49, 41, 63, 32, 48, 46, 48, 58, 32,118,105,115,105,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, -101, 95,118,105,101,119, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 41, 10,123, - 10, 9, 47, 42, 32,104, 97,110,100,108,101, 32,112,101,114,115,112,101, 99,116,105,118,101, 47,111,114,116,104,111,103,114, 97, -112,104,105, 99, 32, 42, 47, 10, 9,118,105,101,119, 32, 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97, -116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, 48, 41, 63, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, - 41, 58, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 45, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, - 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, 40,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,116, - 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,101, 99, 51, 32, 99, 32, 61, 32, 99,114, -111,115,115, 40,108,118, 44, 32,116, 97,110,103, 41, 59, 10, 9,118,101, 99, 51, 32,118,110,111,114, 32, 61, 32, 99,114,111,115, -115, 40, 99, 44, 32,116, 97,110,103, 41, 59, 10, 10, 9,118,110, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,118,110, -111,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,110,112, 40,118,101, 99, 51, 32,118,110, 44, 32, -118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10,123, 10, 9,105,110,112, 32, 61, - 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,110, -111, 95,100,105,102,102,117,115,101, 40,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, - 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,104,101,109,105, 40,102,108,111, 97,116, - 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 53, 42, -105,110,112, 32, 43, 32, 48, 46, 53, 59, 10,125, 10, 10,102,108,111, 97,116, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110, -101,114,103,121, 40,109, 97,116, 52, 32, 97,114,101, 97, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,118,110, - 41, 10,123, 10, 9,118,101, 99, 51, 32,118,101, 99, 91, 52, 93, 44, 32, 99, 91, 52, 93, 59, 10, 9,102,108,111, 97,116, 32,114, - 97,100, 91, 52, 93, 44, 32,102, 97, 99, 59, 10, 9, 10, 9,118,101, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122, -101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 48, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 49, 93, 32, 61, 32,110, -111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 49, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, - 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 50, 93, 46,120,121,122, - 41, 59, 10, 9,118,101, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, - 91, 51, 93, 46,120,121,122, 41, 59, 10, 10, 9, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111, -115,115, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, 41, 59, 10, 9, 99, 91, 49, 93, 32, 61, 32,110,111,114, -109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9, - 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 50, 93, 44, 32,118, -101, 99, 91, 51, 93, 41, 41, 59, 10, 9, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, - 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,114, 97,100, 91, 48, 93, 32, 61, 32, 97, 99, -111,115, 40,100,111,116, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 49, 93, - 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9,114, - 97,100, 91, 50, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, - 41, 59, 10, 9,114, 97,100, 91, 51, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, - 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,102, 97, 99, 61, 32, 32,114, 97,100, 91, 48, 93, 42,100,111,116, 40,118,110, 44, 32, 99, - 91, 48, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 49, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 49, 93, - 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 50, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 50, 93, 41, 59, 10, - 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 51, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 51, 93, 41, 59, 10, 10, 9,114, -101,116,117,114,110, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95,105,110,112, 95, 97,114,101, 97, 40,118,101, 99, 51, 32,112,111,115,105,116,105,111,110, 44, 32,118,101, 99, 51, 32, -108, 97,109,112, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,109, - 97,116, 52, 32, 97,114,101, 97, 44, 32,102,108,111, 97,116, 32, 97,114,101, 97,115,105,122,101, 44, 32,102,108,111, 97,116, 32, -107, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10,123, 10, 9,118,101, 99, 51, 32, 99,111, 32, 61, 32,112, -111,115,105,116,105,111,110, 59, 10, 9,118,101, 99, 51, 32,118,101, 99, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, - 59, 10, 10, 9,105,102, 40,100,111,116, 40,118,101, 99, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 60, 32, 48, 46, 48, 41, 32, -123, 10, 9, 9,105,110,112, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97, -116, 32,105,110,116,101,110,115, 32, 61, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110,101,114,103,121, 40, 97,114,101, 97, - 44, 32, 99,111, 44, 32,118,110, 41, 59, 10, 10, 9, 9,105,110,112, 32, 61, 32,112,111,119, 40,105,110,116,101,110,115, 42, 97, -114,101, 97,115,105,122,101, 44, 32,107, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105, -102,102,117,115,101, 95,111,114,101,110, 95,110, 97,121,101,114, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32, -110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104, 44, 32, -111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108, -105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40, -110, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, - 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,114,101, 97,108,110,108, 32, 61, 32,100,111, -116, 40,110, 44, 32,108, 41, 59, 10, 10, 9,105,102, 40,114,101, 97,108,110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, -105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105,102, 40,110,108, 32, 60, 32, 48, 46, 48, 41, 32, -123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, - 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, - 97,116, 32, 76,105,116, 95, 65, 32, 61, 32, 97, 99,111,115, 40,114,101, 97,108,110,108, 41, 59, 10, 9, 9,102,108,111, 97,116, - 32, 86,105,101,119, 95, 65, 32, 61, 32, 97, 99,111,115, 40,110,118, 41, 59, 10, 10, 9, 9,118,101, 99, 51, 32, 76,105,116, 95, - 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 45, 32,114,101, 97,108,110,108, 42,110, 41, 59, 10, 9, 9,118, -101, 99, 51, 32, 86,105,101,119, 95, 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 45, 32,110,118, 42,110, 41, - 59, 10, 10, 9, 9,102,108,111, 97,116, 32,116, 32, 61, 32,109, 97,120, 40,100,111,116, 40, 76,105,116, 95, 66, 44, 32, 86,105, -101,119, 95, 66, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,102,108,111, 97,116, 32, 97, 44, 32, 98, 59, 10, 10, 9, 9,105, -102, 40, 76,105,116, 95, 65, 32, 62, 32, 86,105,101,119, 95, 65, 41, 32,123, 10, 9, 9, 9, 97, 32, 61, 32, 76,105,116, 95, 65, - 59, 10, 9, 9, 9, 98, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, - 9, 97, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9, 9, 98, 32, 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9,125, 10, 10, - 9, 9,102,108,111, 97,116, 32, 65, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 48, 46, 53, 42, 40, 40,114,111,117,103,104, 42,114, -111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, 46, 51, 51, 41, 41, 41, 59, 10, - 9, 9,102,108,111, 97,116, 32, 66, 32, 61, 32, 48, 46, 52, 53, 42, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, - 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, 46, 48, 57, 41, 41, 59, 10, 10, 9, 9, 98, 32, 42, 61, - 32, 48, 46, 57, 53, 59, 10, 9, 9,105,115, 32, 61, 32,110,108, 42, 40, 65, 32, 43, 32, 40, 66, 32, 42, 32,116, 32, 42, 32,115, -105,110, 40, 97, 41, 32, 42, 32,116, 97,110, 40, 98, 41, 41, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95,100,105,102,102,117,115,101, 95,116,111,111,110, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32, -118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116, -104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, - 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115, -108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,105,115, 32, 61, 32, 49, 46, 48, 59, 10, - 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 32, 40,115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32, -124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, -115,101, 32,105,115, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111, -111,116,104, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,109,105,110,110, - 97,101,114,116, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,118, 44, 32,102, -108,111, 97,116, 32,100, 97,114,107,110,101,115,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9, -105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9, -101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, - 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,105,102, 40,100, 97,114,107,110,101,115,115, 32, 60, 61, 32, 49, 46, 48, 41, 10, - 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40,109, 97,120, 40,110,118, 42,110,108, 44, 32, 48, 46, 49, 41, 44, 32, -100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,105,115, 32, 61, 32, -110,108, 42,112,111,119, 40, 49, 46, 48, 48, 48, 49, 32, 45, 32,110,118, 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, - 46, 48, 41, 59, 10, 9,125, 10,125, 10, 10,102,108,111, 97,116, 32,102,114,101,115,110,101,108, 95,102, 97, 99, 40,118,101, 99, - 51, 32,118,105,101,119, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,102,108,111, 97,116, 32,103,114, 97,100, 44, 32,102,108,111, - 97,116, 32,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 49, 44, 32,116, 50, 59, 10, 9,102,108,111, 97,116, 32, -102,102, 97, 99, 59, 10, 10, 9,105,102, 40,102, 97, 99, 61, 61, 48, 46, 48, 41, 32,123, 10, 9, 9,102,102, 97, 99, 32, 61, 32, - 49, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, 49, 61, 32,100,111,116, 40,118,105,101,119, 44, 32, -118,110, 41, 59, 10, 9, 9,105,102, 40,116, 49, 62, 48, 46, 48, 41, 32, 32,116, 50, 61, 32, 49, 46, 48, 43,116, 49, 59, 10, 9, - 9,101,108,115,101, 32,116, 50, 61, 32, 49, 46, 48, 45,116, 49, 59, 10, 10, 9, 9,116, 50, 61, 32,103,114, 97,100, 32, 43, 32, - 40, 49, 46, 48, 45,103,114, 97,100, 41, 42,112,111,119, 40,116, 50, 44, 32,102, 97, 99, 41, 59, 10, 10, 9, 9,105,102, 40,116, - 50, 60, 48, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40,116, 50, 62, - 49, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,102,102, 97, 99, 32, 61, 32,116, - 50, 59, 10, 9,125, 10, 10, 9,114,101,116,117,114,110, 32,102,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95,100,105,102,102,117,115,101, 95,102,114,101,115,110,101,108, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, - 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 95,105, 44, 32,102,108,111, - 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32,102,114, -101,115,110,101,108, 95,102, 97, 99, 40,108,118, 44, 32,118,110, 44, 32,102, 97, 99, 95,105, 44, 32,102, 97, 99, 41, 59, 10,125, - 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,117, 98,105, 99, 40,102,108,111, 97,116, 32,105,115, 44, 32,111,117,116, - 32,102,108,111, 97,116, 32,111,117,116,105,115, 41, 10,123, 10, 9,105,102, 40,105,115, 62, 48, 46, 48, 32, 38, 38, 32,105,115, - 60, 49, 46, 48, 41, 10, 9, 9,111,117,116,105,115, 61, 32,115,109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, - 46, 48, 44, 32,105,115, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,105,115, 61, 32,105,115, 59, 10,125, 10, 10,118, -111,105,100, 32,115,104, 97,100,101, 95,118,105,115,105,102, 97, 99, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, - 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32,114,101,102,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, -111,117,116,105, 41, 10,123, 10, 9, 47, 42,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, 42, 47, 10, 9, 9,111,117,116,105, 32, - 61, 32,109, 97,120, 40,105, 42,118,105,115,105,102, 97, 99, 42,114,101,102,108, 44, 32, 48, 46, 48, 41, 59, 10, 9, 47, 42,101, -108,115,101, 10, 9, 9,111,117,116,105, 32, 61, 32,105, 59, 42, 47, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, -116, 97,110,103,101,110,116, 95,118, 95,115,112,101, 99, 40,118,101, 99, 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, - 99, 51, 32,118,110, 41, 10,123, 10, 9,118,110, 32, 61, 32,116, 97,110,103, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95, 97,100,100, 95,116,111, 95,100,105,102,102,117,115,101, 40,102,108,111, 97,116, 32,105, 44, 32,118,101, 99, 51, 32, -108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99, -111,108, 41, 10,123, 10, 9,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,105, 42, -108, 97,109,112, 99,111,108, 42, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, - 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, - 95,104,101,109,105, 95,115,112,101, 99, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, - 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32, -102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,108, -118, 32, 43, 61, 32,118,105,101,119, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,118, 41, 59, 10, - 10, 9,116, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10, 9,116, 32, 61, 32, 48, 46, 53, 42,116, 32, 43, 32, - 48, 46, 53, 59, 10, 10, 9,116, 32, 61, 32,118,105,115,105,102, 97, 99, 42,115,112,101, 99, 42,112,111,119, 40,116, 44, 32,104, - 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,112,104,111,110,103, 95,115,112,101, 99, 40,118, -101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114, -100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, - 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, - 61, 32,109, 97,120, 40,100,111,116, 40,104, 44, 32,110, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, - 32, 61, 32,112,111,119, 40,114,115,108,116, 44, 32,104, 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, -101, 95, 99,111,111,107,116,111,114,114, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32, -118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112, -101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, - 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 10, 9,105,102, - 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, - 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, - 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,105, 32, 61, 32,112,111,119, 40,110,104, 44, 32,104, - 97,114,100, 41, 59, 10, 10, 9, 9,105, 32, 61, 32,105, 47, 40, 48, 46, 49, 43,110,118, 41, 59, 10, 9, 9,115,112,101, 99,102, - 97, 99, 32, 61, 32,105, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 98,108,105,110,110, 95,115, -112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97, -116, 32,114,101,102,114, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 95,112,111,119,101,114, 44, 32,111,117,116, 32, -102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,105,102, 40,114,101,102,114, 97, 99, 32, 60, 32, 49, 46, - 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105, -102, 40,115,112,101, 99, 95,112,111,119,101,114, 32, 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, - 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,105,102, 40,115,112,101, 99, 95,112,111,119, -101,114, 60, 49, 48, 48, 46, 48, 41, 10, 9, 9, 9,115,112,101, 99, 95,112,111,119,101,114, 61, 32,115,113,114,116, 40, 49, 46, - 48, 47,115,112,101, 99, 95,112,111,119,101,114, 41, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,115,112,101, 99, 95,112,111, -119,101,114, 61, 32, 49, 48, 46, 48, 47,115,112,101, 99, 95,112,111,119,101,114, 59, 10, 10, 9, 9,118,101, 99, 51, 32,104, 32, - 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,110,104, 32, 61, - 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 9, 9,105,102, 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, 9, -115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9,102, -108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, - 9, 9, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9, 9, 9,105,102, 40,110, -108, 32, 60, 61, 32, 48, 46, 48, 49, 41, 32,123, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, - 9, 9, 9,125, 10, 9, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97, -120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97, - 32, 61, 32, 49, 46, 48, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 98, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,118, - 41, 47,118,104, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 99, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,108, 41, 47, -118,104, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,103, 32, 61, 32, 48, 46, 48, 59, 10, 10, 9, 9, 9, 9,105,102, 40, - 97, 32, 60, 32, 98, 32, 38, 38, 32, 97, 32, 60, 32, 99, 41, 32,103, 32, 61, 32, 97, 59, 10, 9, 9, 9, 9,101,108,115,101, 32, -105,102, 40, 98, 32, 60, 32, 97, 32, 38, 38, 32, 98, 32, 60, 32, 99, 41, 32,103, 32, 61, 32, 98, 59, 10, 9, 9, 9, 9,101,108, -115,101, 32,105,102, 40, 99, 32, 60, 32, 97, 32, 38, 38, 32, 99, 32, 60, 32, 98, 41, 32,103, 32, 61, 32, 99, 59, 10, 10, 9, 9, - 9, 9,102,108,111, 97,116, 32,112, 32, 61, 32,115,113,114,116, 40, 40, 40,114,101,102,114, 97, 99, 32, 42, 32,114,101,102,114, - 97, 99, 41, 43, 40,118,104, 42,118,104, 41, 45, 49, 46, 48, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,102, 32, 61, - 32, 40, 40, 40,112, 45,118,104, 41, 42, 40,112, 45,118,104, 41, 41, 47, 40, 40,112, 43,118,104, 41, 42, 40,112, 43,118,104, 41, - 41, 41, 42, 40, 49, 46, 48, 43, 40, 40, 40, 40,118,104, 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 42, 40, 40,118,104, - 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 41, 47, 40, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, - 41, 42, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, 41, 41, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97, -116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,110,104, 41, 59, 10, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, - 32,109, 97,120, 40,102, 42,103, 42,101,120,112, 95, 98,108,101,110,100,101,114, 40, 40, 45, 40, 97,110,103, 42, 97,110,103, 41, - 47, 40, 50, 46, 48, 42,115,112,101, 99, 95,112,111,119,101,114, 42,115,112,101, 99, 95,112,111,119,101,114, 41, 41, 41, 44, 32, - 48, 46, 48, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, -119, 97,114,100,105,115,111, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, - 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,109,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, - 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, - 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 48, - 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, - 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,108, 41, - 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103,108,101, 32, 61, 32,116, 97,110, 40, 97, 99,111, -115, 40,110,104, 41, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,108,112,104, 97, 32, 61, 32,109, 97,120, 40,114,109,115, 44, 32, - 48, 46, 48, 48, 49, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 61, 32,110,108, 32, 42, 32, 40, 49, 46, 48, 47, 40, 52, 46, - 48, 42, 77, 95, 80, 73, 42, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 42, 40,101,120,112, 95, 98,108,101,110,100,101, -114, 40, 45, 40, 97,110,103,108,101, 42, 97,110,103,108,101, 41, 47, 40, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 47, - 40,115,113,114,116, 40,110,118, 42,110,108, 41, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116,111, -111,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32, -102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102, -108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108, -105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,100,111,116, 40,104, 44, - 32,110, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9, -105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, - 32,105,102, 40, 97,110,103, 32, 62, 61, 32, 40,115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116, -115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,115,108,116, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, - 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111, -111,116,104, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,114,115,108,116, 59, 10,125, 10, 10,118,111,105,100, 32, -115,104, 97,100,101, 95,115,112,101, 99, 95, 97,114,101, 97, 95,105,110,112, 40,102,108,111, 97,116, 32,115,112,101, 99,102, 97, - 99, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,112,101, 99,102, - 97, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99,102, 97, 99, 32, 61, 32,115,112,101, 99,102, 97, 99, 42,105,110,112, 59, - 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115,112,101, 99, 95,116, 40,102,108,111, 97,116, 32,115,104, 97,100, -102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32, -102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,116, - 32, 61, 32,115,104, 97,100,102, 97, 99, 42,115,112,101, 99, 42,118,105,115,105,102, 97, 99, 42,115,112,101, 99,102, 97, 99, 59, - 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 95,115,112,101, 99, 40,102,108,111, 97,116, 32,116, 44, - 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32,115,112,101, 99, 99,111,108, 44, 32,111,117,116, - 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,116, 42,108, 97,109,112, - 99,111,108, 42,115,112,101, 99, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 40,118, -101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117, -116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 59, 10,125, - 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, - 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, -108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 32, 43, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10, -125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100,102, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108, -111, 97,116, 32,102, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, -108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 32, 43, 32,102, 42, 99,111,108, 49, 59, 10,125, 10, 10, -118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99, -111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, - 61, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 95,118, - 97,108,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, - 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 42,102, 97, 99, 59, 10, -125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32, -118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9, -111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 42,111, 98, 99,111,108, 46,114,103, 98, 44, - 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,114, 97,109,112, 95,114,103, 98,116,111, 98,119, 40,118,101, - 99, 51, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111, -117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 32, 43, 32, 99,111,108,111,114, 46,103, 42, 48, 46, - 53, 56, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 49, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, - 95,111,110,108,121, 95,115,104, 97,100,111,119, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, 32,115,104, 97,100, -102, 97, 99, 44, 32,102,108,111, 97,116, 32,101,110,101,114,103,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, -115,104, 97,100,102, 97, 99, 41, 10,123, 10, 9,111,117,116,115,104, 97,100,102, 97, 99, 32, 61, 32,105, 42,101,110,101,114,103, -121, 42, 40, 49, 46, 48, 32, 45, 32,115,104, 97,100,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, - 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,100,105,102,102,117,115,101, 40,102,108,111, 97,116, 32,115,104, 97,100,102, - 97, 99, 44, 32,118,101, 99, 51, 32,114,103, 98, 44, 32,118,101, 99, 52, 32,100,105,102,102, 44, 32,111,117,116, 32,118,101, 99, - 52, 32,111,117,116,100,105,102,102, 41, 10,123, 10, 9,111,117,116,100,105,102,102, 32, 61, 32,100,105,102,102, 32, 45, 32,118, -101, 99, 52, 40,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115, -104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,115,112,101, 99,117,108, 97,114, 40,102,108,111, 97,116, 32, -115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,115,112,101, 99,114,103, 98, 44, 32,118,101, 99, 52, 32,115,112,101, 99, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,115,112,101, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99, 32, 61, - 32,115,112,101, 99, 32, 45, 32,118,101, 99, 52, 40,115,112,101, 99,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, - 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,115,116, 95,115,104, 97,100,111,119, 98,117,102, 40,118,101, 99, 51, 32, -114, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 83,104, 97,100,111,119, 32,115,104, 97,100,111,119,109, 97,112, 44, 32, -109, 97,116, 52, 32,115,104, 97,100,111,119,112,101,114,115,109, 97,116, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,111,119, - 98,105, 97,115, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108, -116, 41, 10,123, 10, 9,105,102, 40,105,110,112, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,101,115,117,108,116, 32, - 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,115,104, - 97,100,111,119,112,101,114,115,109, 97,116, 42,118,101, 99, 52, 40,114, 99,111, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9, 9, 47, - 47,102,108,111, 97,116, 32, 98,105, 97,115, 32, 61, 32, 40, 49, 46, 53, 32, 45, 32,105,110,112, 42,105,110,112, 41, 42,115,104, - 97,100,111,119, 98,105, 97,115, 59, 10, 9, 9, 99,111, 46,122, 32, 45, 61, 32,115,104, 97,100,111,119, 98,105, 97,115, 42, 99, -111, 46,119, 59, 10, 10, 9, 9,114,101,115,117,108,116, 32, 61, 32,115,104, 97,100,111,119, 50, 68, 80,114,111,106, 40,115,104, - 97,100,111,119,109, 97,112, 44, 32, 99,111, 41, 46,120, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, - 95,101,120,112,111,115,117,114,101, 95, 99,111,114,114,101, 99,116, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,102,108,111, 97, -116, 32,108,105,110,102, 97, 99, 44, 32,102,108,111, 97,116, 32,108,111,103,102, 97, 99, 44, 32,111,117,116, 32,118,101, 99, 51, - 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,108,105,110,102, 97, 99, 42, 40, 49, 46, 48, - 32, 45, 32,101,120,112, 40, 99,111,108, 42,108,111,103,102, 97, 99, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, -100,101, 95,109,105,115,116, 95,102, 97, 99,116,111,114, 40,118,101, 99, 51, 32, 99,111, 44, 32,102,108,111, 97,116, 32,109,105, -115,116,115,116, 97, 44, 32,102,108,111, 97,116, 32,109,105,115,116,100,105,115,116, 44, 32,102,108,111, 97,116, 32,109,105,115, -116,116,121,112,101, 44, 32,102,108,111, 97,116, 32,109,105,115,105, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, -102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 44, 32,122, 99,111,114, 59, 10, 10, 9,122, 99,111,114, 32, - 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, - 48, 46, 48, 41, 63, 32,108,101,110,103,116,104, 40, 99,111, 41, 58, 32, 45, 99,111, 91, 50, 93, 59, 10, 9, 10, 9,102, 97, 99, - 32, 61, 32, 99,108, 97,109,112, 40, 40,122, 99,111,114, 45,109,105,115,116,115,116, 97, 41, 47,109,105,115,116,100,105,115,116, - 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105,102, 40,109,105,115,116,116,121,112,101, 32, 61, 61, 32, 48, 46, 48, - 41, 32,102, 97, 99, 32, 42, 61, 32,102, 97, 99, 59, 10, 9,101,108,115,101, 32,105,102, 40,109,105,115,116,116,121,112,101, 32, - 61, 61, 32, 49, 46, 48, 41, 59, 10, 9,101,108,115,101, 32,102, 97, 99, 32, 61, 32,115,113,114,116, 40,102, 97, 99, 41, 59, 10, - 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 45,102, 97, 99, 41, 42, 40, 49, 46, 48, 45, -109,105,115,105, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,119,111,114,108,100, 95,109,105,120, 40,118, -101, 99, 51, 32,104,111,114, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, -111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, 99,111,108, 46, 97, 44, 32, - 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,109,105,120, 40,104,111, -114, 44, 32, 99,111,108, 46,114,103, 98, 44, 32,102, 97, 99, 41, 44, 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105, -100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111,112, 97,113,117,101, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111, -117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, - 40, 99,111,108, 46,114,103, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108, -112,104, 97, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, - 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118, -101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 99,111,108, 46, 97, 42,111, 98, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10, - 0}; - diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl b/source/blender/gpu/intern/gpu_shader_vertex.glsl deleted file mode 100644 index ba9ef7dead6..00000000000 --- a/source/blender/gpu/intern/gpu_shader_vertex.glsl +++ /dev/null @@ -1,12 +0,0 @@ - -varying vec3 varposition; -varying vec3 varnormal; - -void main() -{ - vec4 co = gl_ModelViewMatrix * gl_Vertex; - - varposition = co.xyz; - varnormal = gl_NormalMatrix * gl_Normal; - gl_Position = gl_ProjectionMatrix * co; - diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl.c b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c deleted file mode 100644 index a89de776864..00000000000 --- a/source/blender/gpu/intern/gpu_shader_vertex.glsl.c +++ /dev/null @@ -1,13 +0,0 @@ -/* DataToC output of file */ - -int datatoc_gpu_shader_vertex_glsl_size= 217; -char datatoc_gpu_shader_vertex_glsl[]= { - 10,118, 97,114,121,105,110,103, 32,118,101, 99, 51, 32,118, 97,114,112,111,115,105,116,105,111,110, - 59, 10,118, 97,114,121,105,110,103, 32,118,101, 99, 51, 32,118, 97,114,110,111,114,109, 97,108, 59, 10, 10,118,111,105,100, 32, -109, 97,105,110, 40, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,103,108, 95, 77,111,100,101,108, 86,105,101,119, - 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 86,101,114,116,101,120, 59, 10, 10, 9,118, 97,114,112,111,115,105,116,105,111, -110, 32, 61, 32, 99,111, 46,120,121,122, 59, 10, 9,118, 97,114,110,111,114,109, 97,108, 32, 61, 32,103,108, 95, 78,111,114,109, - 97,108, 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 78,111,114,109, 97,108, 59, 10, 9,103,108, 95, 80,111,115,105,116,105, -111,110, 32, 61, 32,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 32, 42, 32, 99,111, 59, 10, 10, -}; - diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 141b8a985cf..2aa276a5f53 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -164,9 +164,9 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags) } } else if (depth == 32) { for (i = x * y; i > 0; i--) { - rect[0] = bmp[2]; + rect[0] = bmp[0]; rect[1] = bmp[1]; - rect[2] = bmp[0]; + rect[2] = bmp[2]; rect[3] = bmp[3]; rect += 4; bmp += 4; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 043fba9d675..d298e8b5ea8 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -53,14 +53,6 @@ ColorBlock::ColorBlock() { } -/// Init the color block from an array of colors. -ColorBlock::ColorBlock(const uint * linearImage) -{ - for(uint i = 0; i < 16; i++) { - color(i) = Color32(linearImage[i]); - } -} - /// Init the color block with the contents of the given block. ColorBlock::ColorBlock(const ColorBlock & block) { @@ -133,36 +125,9 @@ void ColorBlock::splatY() /// Returns true if the block has a single color. bool ColorBlock::isSingleColor() const { - Color32 mask(0xFF, 0xFF, 0xFF, 0x00); - uint u = m_color[0].u & mask.u; - for(int i = 1; i < 16; i++) { - if (u != (m_color[i].u & mask.u)) - { - return false; - } - } - - return true; -} - -/// Returns true if the block has a single color, ignoring transparent pixels. -bool ColorBlock::isSingleColorNoAlpha() const -{ - Color32 c; - int i; - for(i = 0; i < 16; i++) - { - if (m_color[i].a != 0) c = m_color[i]; - } - - Color32 mask(0xFF, 0xFF, 0xFF, 0x00); - uint u = c.u & mask.u; - - for(; i < 16; i++) - { - if (u != (m_color[i].u & mask.u)) + if (m_color[0] != m_color[i]) { return false; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 537c17346a1..141411f37af 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -41,7 +41,6 @@ struct ColorBlock { ColorBlock(); - ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); ColorBlock(const Image * img, uint x, uint y); @@ -52,7 +51,6 @@ struct ColorBlock void splatY(); bool isSingleColor() const; - bool isSingleColorNoAlpha() const; uint countUniqueColors() const; Color32 averageColor() const; bool hasAlpha() const; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 0981ae88db6..01838281dee 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -80,10 +80,6 @@ static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); -static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y'); - -static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0'); - // 32 bit RGB formats. static const uint D3DFMT_R8G8B8 = 20; static const uint D3DFMT_A8R8G8B8 = 21; @@ -283,144 +279,6 @@ static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, }; - - const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) - { -#define CASE(format) case DXGI_FORMAT_##format: return #format - switch(dxgiFormat) - { - CASE(UNKNOWN); - - CASE(R32G32B32A32_TYPELESS); - CASE(R32G32B32A32_FLOAT); - CASE(R32G32B32A32_UINT); - CASE(R32G32B32A32_SINT); - - CASE(R32G32B32_TYPELESS); - CASE(R32G32B32_FLOAT); - CASE(R32G32B32_UINT); - CASE(R32G32B32_SINT); - - CASE(R16G16B16A16_TYPELESS); - CASE(R16G16B16A16_FLOAT); - CASE(R16G16B16A16_UNORM); - CASE(R16G16B16A16_UINT); - CASE(R16G16B16A16_SNORM); - CASE(R16G16B16A16_SINT); - - CASE(R32G32_TYPELESS); - CASE(R32G32_FLOAT); - CASE(R32G32_UINT); - CASE(R32G32_SINT); - - CASE(R32G8X24_TYPELESS); - CASE(D32_FLOAT_S8X24_UINT); - CASE(R32_FLOAT_X8X24_TYPELESS); - CASE(X32_TYPELESS_G8X24_UINT); - - CASE(R10G10B10A2_TYPELESS); - CASE(R10G10B10A2_UNORM); - CASE(R10G10B10A2_UINT); - - CASE(R11G11B10_FLOAT); - - CASE(R8G8B8A8_TYPELESS); - CASE(R8G8B8A8_UNORM); - CASE(R8G8B8A8_UNORM_SRGB); - CASE(R8G8B8A8_UINT); - CASE(R8G8B8A8_SNORM); - CASE(R8G8B8A8_SINT); - - CASE(R16G16_TYPELESS); - CASE(R16G16_FLOAT); - CASE(R16G16_UNORM); - CASE(R16G16_UINT); - CASE(R16G16_SNORM); - CASE(R16G16_SINT); - - CASE(R32_TYPELESS); - CASE(D32_FLOAT); - CASE(R32_FLOAT); - CASE(R32_UINT); - CASE(R32_SINT); - - CASE(R24G8_TYPELESS); - CASE(D24_UNORM_S8_UINT); - CASE(R24_UNORM_X8_TYPELESS); - CASE(X24_TYPELESS_G8_UINT); - - CASE(R8G8_TYPELESS); - CASE(R8G8_UNORM); - CASE(R8G8_UINT); - CASE(R8G8_SNORM); - CASE(R8G8_SINT); - - CASE(R16_TYPELESS); - CASE(R16_FLOAT); - CASE(D16_UNORM); - CASE(R16_UNORM); - CASE(R16_UINT); - CASE(R16_SNORM); - CASE(R16_SINT); - - CASE(R8_TYPELESS); - CASE(R8_UNORM); - CASE(R8_UINT); - CASE(R8_SNORM); - CASE(R8_SINT); - CASE(A8_UNORM); - - CASE(R1_UNORM); - - CASE(R9G9B9E5_SHAREDEXP); - - CASE(R8G8_B8G8_UNORM); - CASE(G8R8_G8B8_UNORM); - - CASE(BC1_TYPELESS); - CASE(BC1_UNORM); - CASE(BC1_UNORM_SRGB); - - CASE(BC2_TYPELESS); - CASE(BC2_UNORM); - CASE(BC2_UNORM_SRGB); - - CASE(BC3_TYPELESS); - CASE(BC3_UNORM); - CASE(BC3_UNORM_SRGB); - - CASE(BC4_TYPELESS); - CASE(BC4_UNORM); - CASE(BC4_SNORM); - - CASE(BC5_TYPELESS); - CASE(BC5_UNORM); - CASE(BC5_SNORM); - - CASE(B5G6R5_UNORM); - CASE(B5G5R5A1_UNORM); - CASE(B8G8R8A8_UNORM); - CASE(B8G8R8X8_UNORM); - - default: - return "UNKNOWN"; - } -#undef CASE - } - - const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) - { - switch(resourceDimension) - { - default: - case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; - case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; - case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; - case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; - case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; - } - } - /*** implementation ***/ void mem_read(Stream & mem, DDSPixelFormat & pf) @@ -593,16 +451,7 @@ void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3) // set fourcc pixel format. this->pf.flags = DDPF_FOURCC; this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3); - - if (this->pf.fourcc == FOURCC_ATI2) - { - this->pf.bitcount = FOURCC_A2XY; - } - else - { - this->pf.bitcount = 0; - } - + this->pf.bitcount = 0; this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; @@ -659,8 +508,7 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask void DDSHeader::setDX10Format(uint format) { - //this->pf.flags = 0; - this->pf.fourcc = FOURCC_DX10; + this->pf.flags = 0; this->header10.dxgiFormat = format; } @@ -672,18 +520,12 @@ void DDSHeader::setNormalFlag(bool b) bool DDSHeader::hasDX10Header() const { - return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD - //return this->pf.flags == 0; // @@ This is according to MS + return this->pf.flags == 0; } DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() { mem_read(stream, header); - - // some ATI2 compressed normal maps do not have their - // normal flag set, so force it here (the original nvtt don't do - // this, but the decompressor has a -forcenormal flag) - if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true); } DirectDrawSurface::~DirectDrawSurface() @@ -697,7 +539,7 @@ bool DirectDrawSurface::isValid() const return false; } - const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); + const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); if( (header.flags & required) != required ) { return false; } @@ -718,46 +560,40 @@ bool DirectDrawSurface::isValid() const bool DirectDrawSurface::isSupported() const { - if (header.hasDX10Header()) + if (header.pf.flags & DDPF_FOURCC) { + if (header.pf.fourcc != FOURCC_DXT1 && + header.pf.fourcc != FOURCC_DXT2 && + header.pf.fourcc != FOURCC_DXT3 && + header.pf.fourcc != FOURCC_DXT4 && + header.pf.fourcc != FOURCC_DXT5 && + header.pf.fourcc != FOURCC_RXGB && + header.pf.fourcc != FOURCC_ATI1 && + header.pf.fourcc != FOURCC_ATI2) + { + // Unknown fourcc code. + return false; + } + } + else if (header.pf.flags & DDPF_RGB) + { + // All RGB formats are supported now. } else { - if (header.pf.flags & DDPF_FOURCC) - { - if (header.pf.fourcc != FOURCC_DXT1 && - header.pf.fourcc != FOURCC_DXT2 && - header.pf.fourcc != FOURCC_DXT3 && - header.pf.fourcc != FOURCC_DXT4 && - header.pf.fourcc != FOURCC_DXT5 && - header.pf.fourcc != FOURCC_RXGB && - header.pf.fourcc != FOURCC_ATI1 && - header.pf.fourcc != FOURCC_ATI2) - { - // Unknown fourcc code. - return false; - } - } - else if (header.pf.flags & DDPF_RGB) - { - // All RGB formats are supported now. - } - else - { - return false; - } - - if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) - { - // Cubemaps must contain all faces. - return false; - } + return false; + } - if (isTexture3D()) - { - // @@ 3D textures not supported yet. - return false; - } + if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) + { + // Cubemaps must contain all faces. + return false; + } + + if (isTexture3D()) + { + // @@ 3D textures not supported yet. + return false; } return true; @@ -805,37 +641,14 @@ bool DirectDrawSurface::hasAlpha() const } } -bool DirectDrawSurface::isTexture1D() const -{ - if (header.hasDX10Header()) - { - return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; - } - return false; -} - bool DirectDrawSurface::isTexture2D() const { - if (header.hasDX10Header()) - { - return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; - } - else - { - return !isTexture3D() && !isTextureCube(); - } + return !isTexture3D() && !isTextureCube(); } bool DirectDrawSurface::isTexture3D() const { - if (header.hasDX10Header()) - { - return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; - } - else - { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; - } } bool DirectDrawSurface::isTextureCube() const @@ -843,11 +656,6 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } -void DirectDrawSurface::setNormalFlag(bool b) -{ - header.setNormalFlag(b); -} - void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { stream.seek(offset(face, mipmap)); @@ -901,13 +709,7 @@ void DirectDrawSurface::readLinearImage(Image * img) return; } - // set image format: RGB or ARGB - // alpha channel exists if and only if the alpha mask is non-zero - if (header.pf.amask == 0) - { - img->setFormat(Image::Format_RGB); - } - else + if (header.pf.amask != 0) { img->setFormat(Image::Format_ARGB); } @@ -933,20 +735,6 @@ void DirectDrawSurface::readLinearImage(Image * img) void DirectDrawSurface::readBlockImage(Image * img) { - - // set image format: RGB or ARGB - if (header.pf.fourcc == FOURCC_RXGB || - header.pf.fourcc == FOURCC_ATI1 || - header.pf.fourcc == FOURCC_ATI2 || - header.pf.flags & DDPF_NORMAL) - { - img->setFormat(Image::Format_RGB); - } - else - { - img->setFormat(Image::Format_ARGB); - } - const uint w = img->width(); const uint h = img->height(); @@ -1183,23 +971,8 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - printf("\tFourCC: '%c%c%c%c'\n", - ((header.pf.fourcc >> 0) & 0xFF), - ((header.pf.fourcc >> 8) & 0xFF), - ((header.pf.fourcc >> 16) & 0xFF), - ((header.pf.fourcc >> 24) & 0xFF)); - if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) - { - printf("\tSwizzle: '%c%c%c%c'\n", - (header.pf.bitcount >> 0) & 0xFF, - (header.pf.bitcount >> 8) & 0xFF, - (header.pf.bitcount >> 16) & 0xFF, - (header.pf.bitcount >> 24) & 0xFF); - } - else - { - printf("\tBit count: %d\n", header.pf.bitcount); - } + printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); + printf("\tBit count: %d\n", header.pf.bitcount); printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); @@ -1230,11 +1003,11 @@ void DirectDrawSurface::printInfo() const printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); - if (header.hasDX10Header()) + if (header.pf.flags == 0) { printf("DX10 Header:\n"); - printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); - printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); + printf("\tDXGI Format: %u\n", header.header10.dxgiFormat); + printf("\tResource dimension: %u\n", header.header10.resourceDimension); printf("\tMisc flag: %u\n", header.header10.miscFlag); printf("\tArray size: %u\n", header.header10.arraySize); } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index 28fcc95fe83..d8abfc69167 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -142,13 +142,9 @@ public: uint width() const; uint height() const; uint depth() const; - bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; - - void setNormalFlag(bool b); - bool hasAlpha() const; /* false for DXT1, true for all other DXTs */ void mipmap(Image * img, uint f, uint m); diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index cf2f6c16d08..b41b940dca7 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -94,7 +94,6 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) } /* convert DDS into ImBuf */ - // TODO use the image RGB or RGBA tag to determine the bits per pixel if (dds.hasAlpha()) bits_per_pixel = 32; else bits_per_pixel = 24; ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0); diff --git a/source/blender/include/BDR_drawmesh.h b/source/blender/include/BDR_drawmesh.h index 34351549345..93e08ab452d 100644 --- a/source/blender/include/BDR_drawmesh.h +++ b/source/blender/include/BDR_drawmesh.h @@ -30,11 +30,52 @@ #ifndef BDR_DRAWMESH_H #define BDR_DRAWMESH_H +struct Image; +struct MTFace; struct Object; struct DerivedMesh; +struct Mesh; +struct EdgeHash; + +/** + * Enables or disable mipmapping for realtime images (textures). + * Note that this will will destroy all texture bindings in OpenGL. + * @see free_realtime_image() + * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0). + */ +void set_mipmap(int mipmap); + +/** + * Enables or disable linear mipmap setting for realtime images (textures). + * Note that this will will destroy all texture bindings in OpenGL. + * @see free_realtime_image() + * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0). + */ +void set_linear_mipmap(int linear); + +/** + * Returns the current setting for linear mipmapping. + */ +int get_linear_mipmap(void); + +/** + * Resets the realtime image cache variables. + */ +void clear_realtime_image_cache(void); + + +void update_realtime_image(struct Image *ima, int x, int y, int w, int h); +void free_realtime_image(struct Image *ima); +void free_all_realtime_images(void); +void make_repbind(struct Image *ima); +int set_tpage(struct MTFace *tface); + +void texpaint_enable_mipmap(void); +void texpaint_disable_mipmap(void); void draw_mesh_textured(struct Object *ob, struct DerivedMesh *dm, int facesel); -void draw_mesh_text(struct Object *ob, int glsl); +struct EdgeHash *get_tface_mesh_marked_edge_info(struct Mesh *me); +void init_realtime_GL(void); #endif /* BDR_DRAWMESH_H */ diff --git a/source/blender/include/BDR_drawobject.h b/source/blender/include/BDR_drawobject.h index 635b73af80c..de28db64c3b 100644 --- a/source/blender/include/BDR_drawobject.h +++ b/source/blender/include/BDR_drawobject.h @@ -47,7 +47,8 @@ struct EditVert; struct EditFace; struct EditEdge; -int draw_glsl_material(struct Object *ob, int dt); +int set_gl_material(int nr); +int init_gl_materials(struct Object *ob, int check_alpha); void mesh_foreachScreenVert(void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts); void mesh_foreachScreenEdge(void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts); diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index 9b9294b0343..7340a2e44e0 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -76,9 +76,6 @@ void gpencil_delete_laststroke(struct bGPdata *gpd); void gpencil_delete_operation(short mode); void gpencil_delete_menu(void); -void gpencil_convert_operation(short mode); -void gpencil_convert_menu(void); - //short gpencil_paint(short mousebutton); short gpencil_do_paint(struct ScrArea *sa, short mousebutton); diff --git a/source/blender/include/BDR_imagepaint.h b/source/blender/include/BDR_imagepaint.h index bd1ac301416..26f2375e60a 100644 --- a/source/blender/include/BDR_imagepaint.h +++ b/source/blender/include/BDR_imagepaint.h @@ -34,8 +34,8 @@ void imagepaint_redraw_tool(void); void imagepaint_pick(short mousebutton); void imagepaint_paint(short mousebutton, short texturepaint); -void undo_imagepaint_step(int step); -void undo_imagepaint_clear(void); +void imagepaint_undo(); +void free_imagepaint(); #endif /* BDR_IMAGEPAINT_H */ diff --git a/source/blender/include/BIF_drawseq.h b/source/blender/include/BIF_drawseq.h index 85a6c7a9e2d..462075cdf3d 100644 --- a/source/blender/include/BIF_drawseq.h +++ b/source/blender/include/BIF_drawseq.h @@ -33,8 +33,6 @@ struct ScrArea; struct Sequence; -#define SEQ_ZOOM_FAC(szoom) (szoom > 0)? (szoom) : (szoom == 0)? (1.0) : (-1.0/szoom) - void drawprefetchseqspace(struct ScrArea *sa, void *spacedata); void drawseqspace(struct ScrArea *sa, void *spacedata); void set_special_seq_update(int val); diff --git a/source/blender/include/BIF_drawtext.h b/source/blender/include/BIF_drawtext.h index 51000f8c81a..a75e0f1bd86 100644 --- a/source/blender/include/BIF_drawtext.h +++ b/source/blender/include/BIF_drawtext.h @@ -33,21 +33,19 @@ struct ScrArea; struct SpaceText; struct Text; -struct TextLine; void unlink_text(struct Text *text); void free_textspace(struct SpaceText *st); -int txt_file_modified(struct Text *text); void txt_write_file(struct Text *text); void add_text_fs(char *file); void free_txt_data(void); void pop_space_text(struct SpaceText *st); -void txt_format_text(struct SpaceText *st); -void txt_format_line(struct SpaceText *st, struct TextLine *line, int do_next); +void get_format_string(struct SpaceText *st); +void do_brackets(void); #endif diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 1425cf6a67c..77c2f19bb9b 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -78,7 +78,7 @@ enum { #define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT)) #define NLA_ACTION_SCALED (G.saction->mode==SACTCONT_ACTION && G.saction->pin==0 && OBACT && OBACT->action) -#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo && G.sipo->pin==0 && G.sipo->actname) +#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) /* constants for setting ipo-interpolation type */ enum { diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index fdd00a67465..07fc8f08b4a 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -91,7 +91,6 @@ void free_editArmature(void); int join_armature(void); void separate_armature(void); -void apply_armature_pose2bones(void); void load_editArmature(void); void make_bone_parent(void); @@ -100,14 +99,13 @@ struct Bone *get_indexed_bone (struct Object *ob, int index); void make_editArmature(void); void make_trans_bones (char mode); -void remake_editArmature(void); -void editbones_to_armature(struct ListBase *list, struct Object *ob); int do_pose_selectbuffer(struct Base *base, unsigned int *buffer, short hits); void generateSkeleton(void); void mouse_armature(void); +void remake_editArmature(void); void selectconnected_armature(void); void selectconnected_posearmature(void); void armature_select_hierarchy(short direction, short add_to_sel); diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h index 204733a19d6..d2c6c56d01a 100644 --- a/source/blender/include/BIF_editview.h +++ b/source/blender/include/BIF_editview.h @@ -40,7 +40,6 @@ void arrows_move_cursor(unsigned short event); void lasso_select_boundbox(struct rcti *rect, short mcords[][2], short moves); int lasso_inside(short mcords[][2], short moves, short sx, short sy); int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1); -int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2); void borderselect(void); void circle_select(void); void deselectall(void); diff --git a/source/blender/include/BIF_gl.h b/source/blender/include/BIF_gl.h index c1b3b056d62..2468abdff60 100644 --- a/source/blender/include/BIF_gl.h +++ b/source/blender/include/BIF_gl.h @@ -49,7 +49,20 @@ #endif #endif -#include "GL/glew.h" +#ifdef __APPLE__ + #include + #include +#else +/* #if defined (__sun) || defined (__sun__) + #include + #include + #else +*/ + #include + #include +/* #endif */ +#endif + /* * these should be phased out. cpack should be replaced in diff --git a/source/blender/include/BIF_glutil.h b/source/blender/include/BIF_glutil.h index ed9096549ca..f530e7ba8d0 100644 --- a/source/blender/include/BIF_glutil.h +++ b/source/blender/include/BIF_glutil.h @@ -204,7 +204,6 @@ void bglVertex2fv(float *vec); /* intel gfx cards frontbuffer problem */ void bglFlush(void); int is_a_really_crappy_intel_card(void); -int is_a_really_crappy_nvidia_card(void); void set_inverted_drawing(int enable); diff --git a/source/blender/include/BIF_keyframing.h b/source/blender/include/BIF_keyframing.h deleted file mode 100644 index eeaef957b90..00000000000 --- a/source/blender/include/BIF_keyframing.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $Id: BIF_keyframing.h 14444 2008-04-16 22:40:48Z aligorith $ - * - * ***** 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 - * This is a new part of Blender (with some old code) - * - * Contributor(s): Joshua Leung - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef BIF_KEYFRAMING_H -#define BIF_KEYFRAMING_H - -struct ListBase; -struct ID; - -struct IpoCurve; -struct BezTriple; - -/* ************ Keyframing Management **************** */ - -/* Lesser Keyframing API call: - * Use this when validation of necessary animation data isn't necessary as it already - * exists, and there is a beztriple that can be directly copied into the array. - */ -int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); - -/* Main Keyframing API call: - * Use this when validation of necessary animation data isn't necessary as it - * already exists. It will insert a keyframe using the current value being keyframed. - */ -void insert_vert_icu(struct IpoCurve *icu, float x, float y, short flag); - - -/* flags for use in insert_key(), and insert_vert_icu() */ -enum { - INSERTKEY_NEEDED = (1<<0), /* only insert keyframes where they're needed */ - INSERTKEY_MATRIX = (1<<1), /* insert 'visual' keyframes where possible/needed */ - INSERTKEY_FAST = (1<<2), /* don't recalculate handles,etc. after adding key */ - INSERTKEY_FASTR = (1<<3), /* don't realloc mem (or increase count, as array has already been set out) */ - INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */ -} eInsertKeyFlags; - -/* -------- */ - -/* Main Keyframing API calls: - * Use this to create any necessary animation data,, and then insert a keyframe - * using the current value being keyframed, in the relevant place. Returns success. - */ - // TODO: adapt this for new data-api -> this blocktype, etc. stuff is evil! -short insertkey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); - -/* Main Keyframing API call: - * Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case. - */ -short deletekey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); - - -/* Main Keyframe Management calls: - * These handle keyframes management from various spaces. They will handle the menus - * required for each space. - */ -void common_insertkey(void); -void common_deletekey(void); - -/* ************ Keyframe Checking ******************** */ - -/* Checks whether a keyframe exists for the given ID-block one the given frame */ -short id_cfra_has_keyframe(struct ID *id, short filter); - -/* filter flags fr id_cfra_has_keyframe */ -enum { - /* general */ - ANIMFILTER_ALL = 0, /* include all available animation data */ - ANIMFILTER_LOCAL = (1<<0), /* only include locally available anim data */ - - /* object specific */ - ANIMFILTER_MAT = (1<<1), /* include material keyframes too */ - ANIMFILTER_SKEY = (1<<2), /* shape keys (for geometry) */ -} eAnimFilterFlags; - -#endif /* BIF_KEYFRAMING_H */ diff --git a/source/blender/include/BIF_keyval.h b/source/blender/include/BIF_keyval.h index 9693684e425..70d248ded91 100644 --- a/source/blender/include/BIF_keyval.h +++ b/source/blender/include/BIF_keyval.h @@ -31,9 +31,6 @@ #define BIF_KEYVAL_H char *key_event_to_string(unsigned short event); -int decode_key_string(char *str, unsigned short *key, unsigned short *qual); #endif - - diff --git a/source/blender/include/BIF_meshlaplacian.h b/source/blender/include/BIF_meshlaplacian.h index 71db8d0bba2..9fb8aad0eb6 100644 --- a/source/blender/include/BIF_meshlaplacian.h +++ b/source/blender/include/BIF_meshlaplacian.h @@ -47,7 +47,7 @@ struct EditMesh; struct LaplacianSystem; typedef struct LaplacianSystem LaplacianSystem; -LaplacianSystem *laplacian_construct_begin(int totvert, int totface, int lsq); +LaplacianSystem *laplacian_construct_begin(int totvert, int totface); void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned); void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3); diff --git a/source/blender/include/BIF_meshtools.h b/source/blender/include/BIF_meshtools.h index a894d66cb10..d809d1f21f9 100644 --- a/source/blender/include/BIF_meshtools.h +++ b/source/blender/include/BIF_meshtools.h @@ -30,8 +30,6 @@ #ifndef BIF_MESHTOOLS_H #define BIF_MESHTOOLS_H -#include "BLO_sys_types.h" - struct Object; struct EditVert; diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index b6a9882309d..0d27804dd1a 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -57,8 +57,8 @@ typedef enum { ICON_TRIA_UP, ICON_FONTPREVIEW, ICON_BLANK4, - ICON_WORDWRAP, - ICON_WORDWRAP_OFF, + ICON_BLANK5, + ICON_BLANK6, ICON_ORTHO, ICON_PERSP, @@ -108,7 +108,7 @@ typedef enum { ICON_FF, ICON_REW, ICON_PYTHON, - ICON_PYTHON_ON, + ICON_BLANK11, ICON_BLANK12, ICON_BLANK13, ICON_BLANK14, @@ -266,8 +266,8 @@ typedef enum { ICON_WINDOW_WINDOW, ICON_PANEL_CLOSE, ICON_PHYSICS, - ICON_LAYER_USED, - ICON_LAYER_ACTIVE, + ICON_BLANK36, + ICON_BLANK37, ICON_BLANK38, ICON_BLENDER, diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index c7d0f4a1ada..4b2b8e14bb6 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -65,7 +65,6 @@ struct SpaceOops; #define IMAGE_HANDLER_PREVIEW 33 #define IMAGE_HANDLER_GAME_PROPERTIES 34 #define IMAGE_HANDLER_VIEW_PROPERTIES 35 -#define IMAGE_HANDLER_GREASEPENCIL 36 /*#define IMAGE_HANDLER_TRANSFORM_PROPERTIES 36*/ /* action handler codes */ @@ -84,9 +83,6 @@ struct SpaceOops; /* nodes handler codes */ #define NODES_HANDLER_GREASEPENCIL 80 -/* text handler codes */ -#define TEXT_HANDLER_FIND 90 - /* theme codes */ #define B_ADD_THEME 3301 #define B_DEL_THEME 3302 diff --git a/source/blender/include/BSE_drawipo.h b/source/blender/include/BSE_drawipo.h index b8388b2172a..932f103a579 100644 --- a/source/blender/include/BSE_drawipo.h +++ b/source/blender/include/BSE_drawipo.h @@ -42,7 +42,6 @@ struct ScrArea; struct EditIpo; struct View2D; struct rctf; -struct SpaceLink; void calc_ipogrid(void); void draw_ipogrid(void); @@ -51,8 +50,6 @@ void areamouseco_to_ipoco (struct View2D *v2d, short *mval, float *x, float *y); void ipoco_to_areaco (struct View2D *v2d, float *vec, short *mval); void ipoco_to_areaco_noclip (struct View2D *v2d, float *vec, short *mval); -struct View2D *spacelink_get_view2d(struct SpaceLink *sl); - void view2d_do_locks (struct ScrArea *cursa, int flag); void view2d_zoom (struct View2D *v2d, float factor, int winx, int winy); void view2d_getscale (struct View2D *v2d, float *x, float *y); diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index 1b2834b2e3b..e6f22a4fb67 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -36,6 +36,8 @@ struct rctf; struct ScrArea; struct ImBuf; +void default_gl_light(void); +void init_gl_stuff(void); void circf(float x, float y, float rad); void circ(float x, float y, float rad); @@ -53,8 +55,8 @@ struct ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax); unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict, unsigned int (*indextest)(unsigned int index)); void drawview3dspace(struct ScrArea *sa, void *spacedata); -void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int winy, float winmat[][4], int shadow); -void draw_depth(struct ScrArea *sa, void *spacedata, int (*func)(void *) ); +void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]); +void draw_depth(struct ScrArea *sa, void *spacedata); void view3d_update_depths(struct View3D *v3d); int update_time(int cfra); diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index 807e338f514..e7445efc63e 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -86,10 +86,13 @@ void do_ipo_selectbuttons(void); /* gets ipo curve, creates if needed */ -struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); -struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *, short); +struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); +struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *); int texchannel_to_adrcode(int channel); +int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); +void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); +void add_vert_ipo(void); void add_duplicate_editipo(void); void remove_doubles_ipo(void); @@ -118,8 +121,10 @@ void paste_editipo(void); void set_exprap_ipo(int mode); void set_speed_editipo(float speed); +void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast); +void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode); void insertkey_editipo(void); -void add_vert_ipo(void); +void common_insertkey(void); void free_ipokey(struct ListBase *lb); void add_to_ipokey(struct ListBase *lb, struct BezTriple *bezt, int nr, int len); void make_ipokey(void); @@ -158,6 +163,8 @@ void duplicate_ipo_keys(struct Ipo *ipo); void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val); void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, int (*select_function)(struct BezTriple *)); +int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode); +void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey); void select_ipo_key(struct Ipo *ipo, float selx, int sel); void select_icu_key(struct IpoCurve *icu, float selx, int selectmode); void setexprap_ipoloop(struct Ipo *ipo, int code); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index a7f7bc2e4b8..6f8b94d7cd1 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -241,7 +241,6 @@ #define B_SEL_END 168 #define B_MAN_MODE 169 #define B_NDOF 170 -#define B_VIEW_BUTSEDIT 171 /* IPO: 200 */ #define B_IPOHOME 201 @@ -378,13 +377,6 @@ #define B_TEXTLINENUM 507 #define B_TAB_NUMBERS 508 #define B_SYNTAX 509 -#define B_WORDWRAP 510 -#define B_TEXTPLUGINS 511 -#define B_PASTEFIND 512 -#define B_PASTEREPLACE 513 -#define B_TEXTREPLACE 514 -#define B_TEXTFIND 515 -#define B_TEXTMARKALL 516 /* SCRIPT: 525 */ #define B_SCRIPTBROWSE 526 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 51fa39ff9d6..720b856a149 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -466,6 +466,7 @@ int validSnappingNormal(TransInfo *t); /*********************** Generics ********************************/ void initTrans(TransInfo *t); +void initTransModeFlags(TransInfo *t, int mode); void postTrans (TransInfo *t); void drawLine(float *center, float *dir, char axis, short options); @@ -497,7 +498,6 @@ TransInfo * BIF_GetTransInfo(void); /*********************** NumInput ********************************/ -void initNumInput(NumInput *n); void outputNumInput(NumInput *n, char *str); short hasNumInput(NumInput *n); void applyNumInput(NumInput *n, float *vec); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 4a10ecf2368..2e8d95335cc 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -277,9 +277,7 @@ typedef enum POSE_FLAG { /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ POSE_DO_UNLOCK = (1<<2), /* pose has constraints which depend on time (used when depsgraph updates for a new frame) */ - POSE_CONSTRAINTS_TIMEDEPEND = (1<<3), - /* recalculate bone paths */ - POSE_RECALCPATHS = (1<<4), + POSE_CONSTRAINTS_TIMEDEPEND = (1<<3) } POSE_FLAG; /* PoseChannel (transform) flags */ diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 750bdf2cfff..7444ce95f56 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -81,9 +81,7 @@ typedef struct bEditObjectActuator { struct Mesh *me; char name[32]; float linVelocity[3]; /* initial lin. velocity on creation */ - float angVelocity[3]; /* initial ang. velocity on creation */ - float pad; - short localflag; /* flag for the lin & ang. vel: apply locally */ + short localflag; /* flag for the lin. vel: apply locally */ short dyn_operation; } bEditObjectActuator; @@ -193,8 +191,7 @@ typedef struct bGameActuator { } bGameActuator; typedef struct bVisibilityActuator { - /** bit 0: Is this object visible? - ** bit 1: Apply recursively */ + /** bit 0: Is this object visible? */ int flag; } bVisibilityActuator; @@ -301,7 +298,6 @@ typedef struct FreeCamera { #define ACT_NEW 4 #define ACT_LINKED 8 #define ACT_VISIBLE 16 -#define ACT_PIN 32 /* link codes */ #define LINK_SENSOR 0 @@ -388,9 +384,6 @@ typedef struct FreeCamera { #define ACT_EDOB_TRACK_TO 3 #define ACT_EDOB_DYNAMICS 4 -/* editObjectActuator->localflag */ -#define ACT_EDOB_LOCAL_LINV 2 -#define ACT_EDOB_LOCAL_ANGV 4 /* editObjectActuator->flag */ @@ -445,13 +438,10 @@ typedef struct FreeCamera { #define ACT_GAME_START 1 #define ACT_GAME_RESTART 2 #define ACT_GAME_QUIT 3 -#define ACT_GAME_SAVECFG 4 -#define ACT_GAME_LOADCFG 5 /* visibilityact->flag */ /* Set means the object will become invisible */ #define ACT_VISIBILITY_INVISIBLE (1 << 0) -#define ACT_VISIBILITY_RECURSIVE (1 << 1) /* twodfilter->type */ #define ACT_2DFILTER_ENABLED -2 diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index c7196763358..1c272105067 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -33,7 +33,7 @@ #include "DNA_ID.h" #ifndef MAX_MTEX -#define MAX_MTEX 18 +#define MAX_MTEX 10 #endif struct MTex; @@ -58,7 +58,7 @@ typedef struct Brush { float alpha; /* opacity */ short texact, pad; - struct MTex *mtex[18]; /* MAX_MTEX */ + struct MTex *mtex[10]; struct BrushClone clone; } Brush; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index cc0c9912057..13d412c2c42 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -61,7 +61,7 @@ typedef struct bGPDstroke { #define GP_STROKE_2DSPACE (1<<1) /* stroke is in 2d-space (but with special 'image' scaling) */ #define GP_STROKE_2DIMAGE (1<<2) - /* only for use with stroke-buffer (while drawing eraser) */ + /* stroke is an "eraser" stroke */ #define GP_STROKE_ERASER (1<<15) diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h index 0987050261d..1bb18ca2ca2 100644 --- a/source/blender/makesdna/DNA_group_types.h +++ b/source/blender/makesdna/DNA_group_types.h @@ -54,7 +54,7 @@ typedef struct Group { * the objects that show in the group can change depending * on the last used scene */ unsigned int layer; - float dupli_ofs[3]; + int pad; } Group; diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index e1d79f0f875..42b651a7555 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -37,7 +37,6 @@ struct PackedFile; struct anim; struct ImBuf; struct RenderResult; -struct GPUTexture; /* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ @@ -63,8 +62,7 @@ typedef struct Image { char name[240]; /* file path */ - ListBase ibufs; /* not written in file */ - struct GPUTexture *gputexture; /* not written in file */ + ListBase ibufs; /* not written in file */ /* sources from: */ struct anim *anim; diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index 2659de2f067..1e30f3f7640 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -142,24 +142,16 @@ typedef short IPO_Channel; #define MA_FRESTRAI 25 #define MA_ADD 26 -#define MA_MAP1 (1<<5) -#define MA_MAP2 (1<<6) -#define MA_MAP3 (1<<7) -#define MA_MAP4 (1<<8) -#define MA_MAP5 (1<<9) -#define MA_MAP6 (1<<10) -#define MA_MAP7 (1<<11) -#define MA_MAP8 (1<<12) -#define MA_MAP9 (1<<13) -#define MA_MAP10 (1<<14) -#define MA_MAP11 (1<<15) -#define MA_MAP12 (1<<16) -#define MA_MAP13 (1<<17) -#define MA_MAP14 (1<<18) -#define MA_MAP15 (1<<19) -#define MA_MAP16 (1<<20) -#define MA_MAP17 (1<<21) -#define MA_MAP18 (1<<22) +#define MA_MAP1 0x20 +#define MA_MAP2 0x40 +#define MA_MAP3 0x80 +#define MA_MAP4 0x100 +#define MA_MAP5 0x200 +#define MA_MAP6 0x400 +#define MA_MAP7 0x800 +#define MA_MAP8 0x1000 +#define MA_MAP9 0x2000 +#define MA_MAP10 0x4000 #define TEX_TOTNAM 14 diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index 2a39580bb5c..c00dae08eb4 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -35,7 +35,7 @@ #include "DNA_scriptlink_types.h" #ifndef MAX_MTEX -#define MAX_MTEX 18 +#define MAX_MTEX 10 #endif struct MTex; @@ -45,8 +45,7 @@ struct CurveMapping; typedef struct Lamp { ID id; - short type, pad3; - int mode; + short type, mode; short colormodel, totex; float r, g, b, k; @@ -56,9 +55,10 @@ typedef struct Lamp { float att1, att2; /* Quad1 and Quad2 attenuation */ + int pad2; struct CurveMapping *curfalloff; short falloff_type; - short pad2; + short pad3; float clipsta, clipend, shadspotsize; float bias, soft; @@ -99,7 +99,7 @@ typedef struct Lamp { float YF_glowint, YF_glowofs; short YF_glowtype, YF_pad2; - struct MTex *mtex[18]; /* MAX_MTEX */ + struct MTex *mtex[10]; struct Ipo *ipo; /* preview */ @@ -137,12 +137,6 @@ typedef struct Lamp { /* yafray: lamp shadowbuffer flag, softlight */ /* Since it is used with LOCAL lamp, can't use LA_SHAD */ #define LA_YF_SOFT 16384 -#define LA_LAYER_SHADOW 32768 - -/* layer_shadow */ -#define LA_LAYER_SHADOW_BOTH 0 -#define LA_LAYER_SHADOW_CAST 1 -#define LA_LAYER_SHADOW_RECEIVE 2 /* sun effect type*/ #define LA_SUN_EFFECT_SKY 1 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index c92a33bbcbb..9412a09d0f4 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -36,7 +36,7 @@ #include "DNA_listBase.h" #ifndef MAX_MTEX -#define MAX_MTEX 18 +#define MAX_MTEX 10 #endif struct MTex; @@ -88,11 +88,11 @@ typedef struct Material { float sbias; /* shadow bias to prevent terminator prob */ float lbias; /* factor to multiply lampbias with (0.0 = no mult) */ float shad_alpha; /* in use for irregular shadowbuffer */ - int septex; + float padf; /* free padding, take me! */ /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; - short pr_back, pr_lamp, pad4, ml_flag; /* ml_flag is for disable base material */ + short pr_back, pr_lamp, septex, ml_flag; /* ml_flag is for disable base material */ /* shaders */ short diff_shader, spec_shader; @@ -110,7 +110,7 @@ typedef struct Material { short ramp_show, pad3; float rampfac_col, rampfac_spec; - struct MTex *mtex[18]; /* MAX_MTEX */ + struct MTex *mtex[10]; struct bNodeTree *nodetree; struct Ipo *ipo; struct Group *group; /* light group */ @@ -133,8 +133,6 @@ typedef struct Material { int YF_dsmp, YF_preset, YF_djit; ScriptLink scriptlink; - - ListBase gpumaterial; /* runtime */ } Material; /* **************** MATERIAL ********************* */ @@ -205,7 +203,6 @@ typedef struct Material { /* shade_flag */ #define MA_CUBIC 1 -#define MA_OBCOLOR 2 /* diff_shader */ #define MA_DIFF_LAMBERT 0 diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index fc686a4cc10..4e427ed733c 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -82,7 +82,6 @@ typedef struct MLoopUV{ typedef struct MLoopCol{ char a, r, g, b; - int pad; /*waste!*/ }MLoopCol; typedef struct MSticky { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 3708db3fd38..85c49a03569 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -156,9 +156,7 @@ typedef struct Object { float formfactor; float rdamping, sizefac; - float margin, pad3; - - + char dt, dtx; char totcol; /* copy of mesh or curve or meta */ char actcol; /* currently selected material in the user interface */ @@ -225,8 +223,6 @@ typedef struct Object { /*#ifdef WITH_VERSE*/ void *vnode; /* pointer at object VerseNode */ /*#endif*/ - - ListBase gpulamp; /* runtime, for lamps only */ } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -429,8 +425,6 @@ extern Object workob; #define OB_PROP 16384 #define OB_MAINACTOR 32768 -#define OB_PHYSICS 65536 - /* ob->gameflag2 */ #define OB_NEVER_DO_ACTIVITY_CULLING 1 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 8618bee3638..363f0075e23 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -416,7 +416,6 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PARS_DEAD 1 #define PARS_UNBORN 2 #define PARS_ALIVE 3 -#define PARS_DYING 4 /* psys->vg */ #define PSYS_TOT_VG 12 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 32522d1e866..75affbfa7f5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -464,7 +464,7 @@ typedef struct SculptData struct SculptSession *session; /* Pointers to all of sculptmodes's textures */ - struct MTex *mtex[18]; + struct MTex *mtex[10]; /* Editable brush shape */ struct CurveMapping *cumap; @@ -790,7 +790,6 @@ typedef struct Scene { /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 #define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */ -#define UVCALC_TRANSFORM_CORRECT 4 /* adjust UV's while transforming to avoid distortion */ /* toolsettings->edge_mode */ #define EDGE_MODE_SELECT 0 diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index 1fd97fe0158..b5d8511c698 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -164,7 +164,7 @@ typedef struct bSensor { typedef struct bJoystickSensor { char name[32]; short type; - short joyindex; + short pad; int axis; int axisf; int button; @@ -218,7 +218,6 @@ typedef struct bJoystickSensor { #define SENS_NEW 4 #define SENS_NOT 8 #define SENS_VISIBLE 16 -#define SENS_PIN 32 /* sensor->pulse */ #define SENS_PULSE_CONT 0 @@ -238,9 +237,6 @@ typedef struct bJoystickSensor { * */ /* #define SENS_COLLISION_PROPERTY 0 */ #define SENS_COLLISION_MATERIAL 1 -/* ray specific mode */ -/* X-Ray means that the ray will traverse objects that don't have the property/material */ -#define SENS_RAY_XRAY 2 /* Some stuff for the mouse sensor Type: */ #define BL_SENS_MOUSE_LEFT_BUTTON 1 @@ -267,7 +263,6 @@ typedef struct bJoystickSensor { #define SENS_JOY_HAT_DIR 0 #define SENS_DELAY_REPEAT 1 -// should match JOYINDEX_MAX in SCA_JoystickDefines.h */ -#define SENS_JOY_MAXINDEX 8 + #endif diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index c59cafc1ef0..39d457058c1 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -276,23 +276,22 @@ typedef struct SpaceText { struct Text *text; int top, viewlines; - short flags, menunr; - int font_id; - + short flags, menunr; + + int font_id; int lheight; int left; int showlinenrs; + int tabnumber; - int currtab_set; int showsyntax; - int overwrite; + int unused_padd; + float pix_per_line; struct rcti txtscroll, txtbar; - int wordwrap, doplugins; - } SpaceText; typedef struct Script { @@ -538,7 +537,6 @@ typedef struct SpaceImaSel { #define SI_DRAW_TILE 1<<19 #define SI_SMOOTH_UV 1<<20 #define SI_DRAW_STRETCH 1<<21 -#define SI_DISPGP 1<<22 /* SpaceIpo->flag */ #define SIPO_LOCK_VIEW 1<<0 diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index 48ecccd517a..d1859d22115 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -38,36 +38,25 @@ typedef struct TextLine { struct TextLine *next, *prev; char *line; - char *format; /* may be NULL if syntax is off or not yet formatted */ - int len, blen; /* blen unused */ + char *format; + int len, blen; } TextLine; -typedef struct TextMarker { - struct TextMarker *next, *prev; - - int lineno, start, end, pad1; /* line number and start/end character indices */ - - int group, flags; /* see BKE_text.h for flag defines */ - char color[4], pad[4]; /* draw color of the marker */ -} TextMarker; - typedef struct Text { ID id; char *name; - + int flags, nlines; ListBase lines; TextLine *curl, *sell; int curc, selc; - ListBase markers; char *undo_buf; int undo_pos, undo_len; void *compiled; - double mtime; } Text; @@ -85,12 +74,4 @@ typedef struct Text { #define TXT_READONLY 0x0100 #define TXT_FOLLOW 0x0200 /* always follow cursor (console) */ -/* format continuation flags */ -#define TXT_NOCONT 0x00 /* no continuation */ -#define TXT_SNGQUOTSTR 0x01 /* single quotes */ -#define TXT_DBLQUOTSTR 0x02 /* double quotes */ -#define TXT_TRISTR 0x04 /* triplets of quotes: """ or ''' */ -#define TXT_SNGTRISTR 0x05 /*(TXT_TRISTR | TXT_SNGQUOTSTR)*/ -#define TXT_DBLTRISTR 0x06 /*(TXT_TRISTR | TXT_DBLQUOTSTR)*/ - #endif diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 111dc08ee02..8a79ce845d7 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -367,7 +367,6 @@ typedef struct TexMapping { #define MTEX_BLEND_SAT 11 #define MTEX_BLEND_VAL 12 #define MTEX_BLEND_COLOR 13 -#define MTEX_NUM_BLENDTYPES 14 /* **************** EnvMap ********************* */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 981591dc810..856324695a9 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -188,7 +188,6 @@ typedef struct UserDef { char fontname[256]; // FILE_MAXDIR+FILE length struct ListBase themes; short undosteps; - short undomemory, pad[3]; short curssize; short tb_leftmouse, tb_rightmouse; struct SolidLight light[3]; @@ -268,7 +267,6 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_GLOBALUNDO (1 << 13) #define USER_ORBIT_SELECTION (1 << 14) // old flag for #define USER_KEYINSERTAVAI (1 << 15) -#define USER_ORBIT_ZBUF (1 << 15) #define USER_HIDE_DOT (1 << 16) #define USER_SHOW_ROTVIEWICON (1 << 17) #define USER_SHOW_VIEWPORTNAME (1 << 18) diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index b30a7162b93..135272b9ac2 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -86,8 +86,7 @@ typedef struct View3D { float winmat1[4][4]; // persp(1) storage, for swap matrices float viewmat1[4][4]; - float viewquat[4], dist, zfac; /* zfac is initgrabz() result */ - int lay_used; /* used while drawing */ + float viewquat[4], dist, zfac, pad0; /* zfac is initgrabz() result */ short persp; short view; diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index ab7e25190ad..26b3f051944 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -38,7 +38,7 @@ struct Ipo; struct MTex; #ifndef MAX_MTEX -#define MAX_MTEX 18 +#define MAX_MTEX 10 #endif @@ -108,7 +108,7 @@ typedef struct World { struct Ipo *ipo; - struct MTex *mtex[18]; /* MAX_MTEX */ + struct MTex *mtex[10]; /* previews */ struct PreviewImage *preview; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index cf83804b999..2cb855ed440 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -30,7 +30,7 @@ SET(INC ../python ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/iksolver/extern ../blenloader ../quicktime - ../blenkernel ../../../extern/glew/include ../gpu + ../blenkernel ${SDL_INC} ${ZLIB_INC} ${PYTHON_INC} diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 8af7b67520e..8682f626b80 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -11,7 +11,6 @@ incs += ' ../python ../render/extern/include ' incs += ' ../imbuf ../avi ' incs += ' ../blenloader ../quicktime' incs += ' ../blenkernel ../renderconverter ' -incs += ' ../gpu #/extern/glew/include ' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c index 950ad97a397..5e1803a6774 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c @@ -130,16 +130,13 @@ static void node_composit_exec_tonemap(void *data, bNode *node, bNodeStack **in, if ((img==NULL) || (out[0]->hasoutput==0)) return; if (img->type != CB_RGBA) - img = typecheck_compbuf(img, CB_RGBA); - - new = dupalloc_compbuf(img); + new = typecheck_compbuf(img, CB_RGBA); + else + new = dupalloc_compbuf(img); tonemap(node->storage, new, img); out[0]->data = new; - - if(img!=in[0]->data) - free_compbuf(img); } static void node_composit_init_tonemap(bNode* node) diff --git a/source/blender/nodes/intern/CMP_nodes/Makefile b/source/blender/nodes/intern/CMP_nodes/Makefile index 8a8d323ac5b..61b03f237db 100644 --- a/source/blender/nodes/intern/CMP_nodes/Makefile +++ b/source/blender/nodes/intern/CMP_nodes/Makefile @@ -42,5 +42,4 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include -CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/Makefile b/source/blender/nodes/intern/Makefile index 6167cf6bc72..7cf2411ed84 100644 --- a/source/blender/nodes/intern/Makefile +++ b/source/blender/nodes/intern/Makefile @@ -42,6 +42,4 @@ CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../include CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../render/extern/include -CPPFLAGS += -I../../gpu -CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index ae3cae029d2..1917e9ba15c 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -44,6 +44,4 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include -CPPFLAGS += -I../../../gpu -CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c index 20136d75540..63260ff91ed 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c @@ -46,13 +46,8 @@ static void node_shader_exec_camera(void *data, bNode *node, bNodeStack **in, bN VECCOPY(out[0]->vec, shi->co); /* get view vector */ out[1]->vec[0]= fabs(shi->co[2]); /* get view z-depth */ out[2]->vec[0]= Normalize(out[0]->vec); /* get view distance */ + } } -} - -static int gpu_shader_camera(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION)); -} bNodeType sh_node_camera= { /* *next,*prev */ NULL, NULL, @@ -68,7 +63,6 @@ bNodeType sh_node_camera= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_camera + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c index d277547b636..b6f1f8d52cd 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c @@ -56,15 +56,6 @@ static void node_shader_init_curve_vec(bNode* node) node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); } -static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - float *array; - int size; - - curvemapping_table_RGBA(node->storage, &array, &size); - return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array)); -} - bNodeType sh_node_curve_vec= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_VEC, @@ -79,8 +70,7 @@ bNodeType sh_node_curve_vec= { /* initfunc */ node_shader_init_curve_vec, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_curve_vec + /* id */ NULL }; @@ -110,15 +100,6 @@ static void node_shader_init_curve_rgb(bNode *node) node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } -static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - float *array; - int size; - - curvemapping_table_RGBA(node->storage, &array, &size); - return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array)); -} - bNodeType sh_node_curve_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_RGB, @@ -133,7 +114,6 @@ bNodeType sh_node_curve_rgb= { /* initfunc */ node_shader_init_curve_rgb, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_curve_rgb + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c index bc345759b98..24395059c60 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c @@ -29,7 +29,6 @@ #include "../SHD_util.h" -#include "DNA_customdata_types.h" /* **************** GEOMETRY ******************** */ @@ -125,18 +124,6 @@ static void node_shader_init_geometry(bNode *node) node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); } -static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - NodeGeometry *ngeo= (NodeGeometry*)node->storage; - GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); - GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname); - GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname); - - return GPU_stack_link(mat, "geom", in, out, - GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), - GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol); -} - /* node type definition */ bNodeType sh_node_geom= { /* *next,*prev */ NULL, NULL, @@ -152,7 +139,6 @@ bNodeType sh_node_geom= { /* initfunc */ node_shader_init_geometry, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_geom + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c index 1b7b2dfb8e7..67dfc619080 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c @@ -71,12 +71,6 @@ static void node_shader_exec_hue_sat(void *data, bNode *node, bNodeStack **in, b do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec); } - -static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "hue_sat", in, out); -} - bNodeType sh_node_hue_sat= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_HUE_SAT, @@ -91,8 +85,7 @@ bNodeType sh_node_hue_sat= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_hue_sat + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c index 72ee1483ecf..4d1ce282fce 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c @@ -64,11 +64,6 @@ bNodeStack **out) VECCOPY(out[0]->vec, col); } -static int gpu_shader_invert(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "invert", in, out); -} - bNodeType sh_node_invert= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_INVERT, @@ -83,7 +78,6 @@ bNodeType sh_node_invert= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_invert + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c index c081929a2fc..589954c8f7b 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c @@ -69,20 +69,6 @@ static void node_shader_init_mapping(bNode *node) node->storage= add_mapping(); } -static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - TexMapping *texmap= node->storage; - float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; - float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0; - GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat); - GPUNodeLink *tmin = GPU_uniform(texmap->min); - GPUNodeLink *tmax = GPU_uniform(texmap->max); - GPUNodeLink *tdomin = GPU_uniform(&domin); - GPUNodeLink *tdomax = GPU_uniform(&domax); - - return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax); -} - bNodeType sh_node_mapping= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MAPPING, @@ -97,8 +83,7 @@ bNodeType sh_node_mapping= { /* initfunc */ node_shader_init_mapping, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_mapping + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index c0a2534ac4a..9396410f850 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -182,77 +182,6 @@ static void node_shader_init_material(bNode* node) node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; } -static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - if(node->id) { - GPUShadeInput shi; - GPUShadeResult shr; - - GPU_shadeinput_set(mat, (Material*)node->id, &shi); - - /* write values */ - if(in[MAT_IN_COLOR].hasinput) - shi.rgb = in[MAT_IN_COLOR].link; - - if(in[MAT_IN_SPEC].hasinput) - shi.specrgb = in[MAT_IN_SPEC].link; - - if(in[MAT_IN_REFL].hasinput) - shi.refl = in[MAT_IN_REFL].link; - - /* retrieve normal */ - if(in[MAT_IN_NORMAL].hasinput) { - GPUNodeLink *tmp; - shi.vn = in[MAT_IN_NORMAL].link; - GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); - } - - /* custom option to flip normal */ - if(node->custom1 & SH_NODE_MAT_NEG) - GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); - - if (node->type == SH_NODE_MATERIAL_EXT) { - if(in[MAT_IN_AMB].hasinput) - shi.amb= in[MAT_IN_AMB].link; - if(in[MAT_IN_EMIT].hasinput) - shi.emit= in[MAT_IN_EMIT].link; - if(in[MAT_IN_ALPHA].hasinput) - shi.alpha= in[MAT_IN_ALPHA].link; - } - - GPU_shaderesult_set(&shi, &shr); /* clears shr */ - - /* write to outputs */ - if(node->custom1 & SH_NODE_MAT_DIFF) { - if(node->custom1 & SH_NODE_MAT_SPEC) - out[MAT_OUT_COLOR].link= shr.combined; - else - out[MAT_OUT_COLOR].link= shr.diff; - } - else if(node->custom1 & SH_NODE_MAT_SPEC) { - out[MAT_OUT_COLOR].link= shr.spec; - } - else - GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); - - GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); - - out[MAT_OUT_ALPHA].link = shr.alpha; // - - if(node->custom1 & SH_NODE_MAT_NEG) - GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); - out[MAT_OUT_NORMAL].link = shi.vn; - - if (node->type == SH_NODE_MATERIAL_EXT) { - out[MAT_OUT_DIFFUSE].link = shr.diff; - out[MAT_OUT_SPEC].link = shr.spec; - } - - return 1; - } - - return 0; -} bNodeType sh_node_material= { /* *next,*prev */ NULL, NULL, @@ -268,8 +197,8 @@ bNodeType sh_node_material= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_material + /* id */ NULL + }; bNodeType sh_node_material_ext= { @@ -286,7 +215,7 @@ bNodeType sh_node_material_ext= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_material + /* id */ NULL + }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c index 050c2cdcc95..2e156cf12bf 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c @@ -194,46 +194,6 @@ bNodeStack **out) } } -static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - static char *names[] = {"math_add", "math_subtract", "math_multiply", - "math_divide", "math_sine", "math_cosine", "math_tangnet", "math_asin", - "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", - "math_round", "math_less_than", "math_greater_than"}; - - switch (node->custom1) { - case 0: - case 1: - case 2: - case 3: - case 10: - case 11: - case 12: - case 13: - case 15: - case 16: - GPU_stack_link(mat, names[node->custom1], NULL, out, - GPU_socket(&in[0]), GPU_socket(&in[1])); - break; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 14: - if(in[0].hasinput || !in[1].hasinput) - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); - else - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); - break; - default: - return 0; - } - - return 1; -} - bNodeType sh_node_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MATH, @@ -248,7 +208,6 @@ bNodeType sh_node_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_math + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c index 2da1dee5623..dba70253fda 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c @@ -60,17 +60,6 @@ static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, b VECCOPY(out[0]->vec, col); } -static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", - "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", - "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", - "mix_val", "mix_color"}; - - return GPU_stack_link(mat, names[node->custom1], in, out); -} - - bNodeType sh_node_mix_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MIX_RGB, @@ -85,7 +74,6 @@ bNodeType sh_node_mix_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_mix_rgb + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c index 9d4ea1ccf67..f1ffd3446af 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c @@ -57,14 +57,6 @@ static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bN out[1]->vec[0]= -INPR(out[0]->vec, vec); } -static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - bNodeSocket *sock= node->outputs.first; - GPUNodeLink *vec = GPU_uniform(sock->ns.vec); - - return GPU_stack_link(mat, "normal", in, out, vec); -} - bNodeType sh_node_normal= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_NORMAL, @@ -79,7 +71,6 @@ bNodeType sh_node_normal= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_normal + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_output.c b/source/blender/nodes/intern/SHD_nodes/SHD_output.c index 76856cfd2e8..0a9a30c452b 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_output.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_output.c @@ -62,19 +62,6 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN } } -static int gpu_shader_output(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - GPUNodeLink *outlink; - - /*if(in[1].hasinput) - GPU_material_enable_alpha(mat);*/ - - GPU_stack_link(mat, "output_node", in, out, &outlink); - GPU_material_output_link(mat, outlink); - - return 1; -} - bNodeType sh_node_output= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_OUTPUT, @@ -89,8 +76,7 @@ bNodeType sh_node_output= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_output + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c index 1aa1a2ffc33..4e56e26d3ad 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c @@ -42,14 +42,6 @@ static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNode VECCOPY(out[0]->vec, sock->ns.vec); } -static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - bNodeSocket *sock= node->outputs.first; - GPUNodeLink *vec = GPU_uniform(sock->ns.vec); - - return GPU_stack_link(mat, "set_rgba", in, out, vec); -} - bNodeType sh_node_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGB, @@ -64,7 +56,6 @@ bNodeType sh_node_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_rgb + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c index 6d5df2a1321..2b52a8e2229 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c @@ -48,11 +48,6 @@ static void node_shader_exec_seprgb(void *data, bNode *node, bNodeStack **in, bN out[2]->vec[0] = in[0]->vec[2]; } -static int gpu_shader_seprgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "separate_rgb", in, out); -} - bNodeType sh_node_seprgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SEPRGB, @@ -67,8 +62,7 @@ bNodeType sh_node_seprgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_seprgb + /* id */ NULL }; @@ -92,11 +86,6 @@ static void node_shader_exec_combrgb(void *data, bNode *node, bNodeStack **in, b out[0]->vec[2] = in[2]->vec[0]; } -static int gpu_shader_combrgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "combine_rgb", in, out); -} - bNodeType sh_node_combrgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_COMBRGB, @@ -111,7 +100,6 @@ bNodeType sh_node_combrgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_combrgb + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c index d3480a6ae9d..30abad666c4 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c @@ -54,11 +54,6 @@ bNodeStack **out) out[0]->vec[0] = 1.0f / (1.0f + pow(2.71828183,-((vec[0]-vec[2])*vec[1]))) ; } -static int gpu_shader_squeeze(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "squeeze", in, out); -} - bNodeType sh_node_squeeze= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SQUEEZE, @@ -73,7 +68,6 @@ bNodeType sh_node_squeeze= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_squeeze + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c index 31dbde940fd..ace11a20d42 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c @@ -27,8 +27,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "DNA_texture_types.h" - #include "../SHD_util.h" /* **************** TEXTURE ******************** */ @@ -112,18 +110,6 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b } } -static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - Tex *tex = (Tex*)node->id; - - if(tex && tex->type == TEX_IMAGE && tex->ima) { - GPUNodeLink *texlink = GPU_image(tex->ima, NULL); - return GPU_stack_link(mat, "texture_image", in, out, texlink); - } - else - return 0; -} - bNodeType sh_node_texture= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_TEXTURE, @@ -138,8 +124,7 @@ bNodeType sh_node_texture= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_texture + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c index 301c0cb7031..cf7e33d9dca 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c @@ -59,15 +59,6 @@ static void node_shader_init_valtorgb(bNode *node) node->storage= add_colorband(1); } -static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - float *array; - int size; - - colorband_table_RGBA(node->storage, &array, &size); - return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array)); -} - bNodeType sh_node_valtorgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VALTORGB, @@ -82,8 +73,7 @@ bNodeType sh_node_valtorgb= { /* initfunc */ node_shader_init_valtorgb, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_valtorgb + /* id */ NULL }; @@ -106,11 +96,6 @@ static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, b out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f; } -static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - return GPU_stack_link(mat, "rgbtobw", in, out); -} - bNodeType sh_node_rgbtobw= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGBTOBW, @@ -125,8 +110,7 @@ bNodeType sh_node_rgbtobw= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_rgbtobw + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_value.c b/source/blender/nodes/intern/SHD_nodes/SHD_value.c index 768ef3cda3d..57ef7226066 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_value.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_value.c @@ -42,13 +42,7 @@ static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNo out[0]->vec[0]= sock->ns.vec[0]; } -static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - bNodeSocket *sock= node->outputs.first; - GPUNodeLink *vec = GPU_uniform(sock->ns.vec); - return GPU_stack_link(mat, "set_value", in, out, vec); -} bNodeType sh_node_value= { /* *next,*prev */ NULL, NULL, @@ -64,8 +58,7 @@ bNodeType sh_node_value= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_value + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c index 96db8db18a6..8d0a4b3abe3 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c @@ -99,34 +99,6 @@ static void node_shader_exec_vect_math(void *data, bNode *node, bNodeStack **in, } -static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) -{ - static char *names[] = {"vec_math_add", "vec_math_subtract", - "vec_math_average", "vec_math_dot", "vec_math_cross", - "vec_math_normalize"}; - - switch (node->custom1) { - case 0: - case 1: - case 2: - case 3: - case 4: - GPU_stack_link(mat, names[node->custom1], NULL, out, - GPU_socket(&in[0]), GPU_socket(&in[1])); - break; - case 5: - if(in[0].hasinput || !in[1].hasinput) - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); - else - GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); - break; - default: - return 0; - } - - return 1; -} - bNodeType sh_node_vect_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VECT_MATH, @@ -141,7 +113,6 @@ bNodeType sh_node_vect_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL, NULL, NULL, - /* gpufunc */ gpu_shader_vect_math + /* id */ NULL }; diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h index eda985529c1..bdb2bb3707d 100644 --- a/source/blender/nodes/intern/SHD_util.h +++ b/source/blender/nodes/intern/SHD_util.h @@ -88,8 +88,6 @@ #include "RE_pipeline.h" #include "RE_shader_ext.h" -#include "GPU_material.h" - #include "butspace.h" #include "blendef.h" #include "mydevice.h" diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 4b96ef3fdf0..f6a27b80733 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -48,7 +48,6 @@ struct bPythonConstraint; /* DNA_constraint_types.h */ struct bConstraintOb; /* DNA_constraint_types.h */ struct bConstraintTarget; /* DNA_constraint_types.h*/ struct Script; /* DNA_screen_types.h */ -struct BPyMenu; #ifdef __cplusplus extern "C" { #endif @@ -92,9 +91,7 @@ extern "C" { int BPY_txt_do_python_Text( struct Text *text ); int BPY_menu_do_python( short menutype, int event ); - int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers ); - int BPY_menu_invoke( struct BPyMenu *pym, short menutype ); - void BPY_run_python_script( const char *filename ); + void BPY_run_python_script( char *filename ); int BPY_run_script(struct Script *script); void BPY_free_compiled_text( struct Text *text ); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 041ba069928..69bff059356 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -292,7 +292,7 @@ void syspath_append( char *dirname ) short ok=1; PyErr_Clear( ); - dir = PyString_FromString( dirname ); + dir = Py_BuildValue( "s", dirname ); mod_sys = PyImport_ImportModule( "sys" ); /* new ref */ @@ -308,29 +308,32 @@ void syspath_append( char *dirname ) } if (PySequence_Contains(path, dir)==0) { /* Only add if we need to */ - if (ok && PyList_Append( path, dir ) != 0) /* decref below */ + if (ok && PyList_Append( path, dir ) != 0) ok = 0; /* append failed */ if( (ok==0) || PyErr_Occurred( ) ) Py_FatalError( "could import or build sys.path, can't continue" ); } - Py_DECREF( dir ); Py_XDECREF( mod_sys ); } void init_syspath( int first_time ) { + PyObject *path; PyObject *mod, *d; char *progname; char execdir[FILE_MAXDIR]; /*defines from DNA_space_types.h */ int n; + + + path = Py_BuildValue( "s", bprogname ); mod = PyImport_ImportModule( "Blender.sys" ); if( mod ) { d = PyModule_GetDict( mod ); - EXPP_dict_set_item_str( d, "progname", PyString_FromString( bprogname ) ); + EXPP_dict_set_item_str( d, "progname", path ); Py_DECREF( mod ); } else printf( "Warning: could not set Blender.sys.progname\n" ); @@ -553,7 +556,6 @@ void BPY_Err_Handle( char *script_name ) if( exception && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) { /* no traceback available when SyntaxError */ - PyErr_NormalizeException( &exception, &err, &tb ); PyErr_Restore( exception, err, tb ); /* takes away reference! */ PyErr_Print( ); v = PyObject_GetAttrString( err, "lineno" ); @@ -720,23 +722,13 @@ int BPY_txt_do_python_Text( struct Text *text ) * automatically. The script can be a file or a Blender Text in the current * .blend. ****************************************************************************/ -void BPY_run_python_script( const char *fn ) +void BPY_run_python_script( char *fn ) { - char filename[FILE_MAXDIR + FILE_MAXFILE]; Text *text = NULL; int is_blender_text = 0; - - BLI_strncpy(filename, fn, FILE_MAXDIR + FILE_MAXFILE); - - if (!BLI_exists(filename)) - BLI_convertstringcwd(filename); - - if (!BLI_exists(filename)) { /* if there's no such filename ... */ - /* try an already existing Blender Text. - * use 'fn' rather then filename for this since were looking for - * internal text - */ - text = G.main->text.first; + + if (!BLI_exists(fn)) { /* if there's no such filename ... */ + text = G.main->text.first; /* try an already existing Blender Text */ while (text) { if (!strcmp(fn, text->id.name + 2)) break; @@ -751,14 +743,11 @@ void BPY_run_python_script( const char *fn ) } else { - /* use filename here since we know it exists, - * 'fn' may have been a relative path - */ - text = add_text(filename); + text = add_text(fn); if (text == NULL) { printf("\nError in BPY_run_python_script:\n" - "couldn't create Blender text from \"%s\"\n", filename); + "couldn't create Blender text from %s\n", fn); /* Chris: On Windows if I continue I just get a segmentation * violation. To get a baseline file I exit here. */ exit(2); @@ -775,8 +764,13 @@ void BPY_run_python_script( const char *fn ) /* We can't simply free the text, since the script might have called * Blender.Load() to load a new .blend, freeing previous data. * So we check if the pointer is still valid. */ - if (BLI_findindex(&G.main->text, text) != -1) { - free_libblock(&G.main->text, text); + Text *txtptr = G.main->text.first; + while (txtptr) { + if (txtptr == text) { + free_libblock(&G.main->text, text); + break; + } + txtptr = txtptr->id.next; } } } @@ -786,6 +780,9 @@ int BPY_run_script(Script *script) PyObject *py_dict, *py_res, *pyarg; Text *text = NULL; BPy_constant *info; + int len; + + FILE *fp = NULL; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -830,8 +827,12 @@ int BPY_run_script(Script *script) Py_INCREF( Py_None ); pyarg = Py_None; } else { - if (!BLI_exists(script->scriptname)) { - printf( "Script does not exit %s\n", script->scriptname ); + if (BLI_exists(script->scriptname)) { + fp = fopen( script->scriptname, "rb" ); + } + + if( !fp ) { + printf( "Error loading script: couldn't open file %s\n", script->scriptname ); free_libblock( &G.main->script, script ); PyGILState_Release(gilstate); return 0; @@ -876,17 +877,51 @@ int BPY_run_script(Script *script) if (text) { py_res = RunPython( text, py_dict ); } else { - char pystring[sizeof(script->scriptname) + 15]; - sprintf(pystring, "execfile(r'%s')", script->scriptname); - py_res = PyRun_String( pystring, Py_file_input, py_dict, py_dict ); - } - - if( !py_res ) { /* Failed execution of the script */ /* Previously we used PyRun_File to run directly the code on a FILE * object, but as written in the Python/C API Ref Manual, chapter 2, * 'FILE structs for different C libraries can be different and * incompatible'. * So now we load the script file data to a buffer */ + char *buffer=NULL, *buffer_ofs=NULL, *b_to, *b_from; + + fseek( fp, 0L, SEEK_END ); + len = ftell( fp ); + fseek( fp, 0L, SEEK_SET ); + + buffer = buffer_ofs = MEM_mallocN( len + 2, "pyfilebuf" ); /* len+2 to add '\n\0' */ + len = fread( buffer, 1, len, fp ); + + buffer[len] = '\n'; /* fix syntax error in files w/o eol */ + buffer[len + 1] = '\0'; + + + /* fast clean-up of dos cr/lf line endings, remove convert '\r\n's to '\n' */ + if (*buffer_ofs == '\r' && *(buffer_ofs+1) == '\n') { + buffer_ofs++; + } + b_from = b_to = buffer_ofs; + + while(*b_from != '\0') { + if (*b_from == '\r' && *( b_from+1 ) == '\n') { + b_from++; + } + if (b_from != b_to) { + *b_to = *b_from; + } + b_to++; + b_from++; + } + *b_to = '\0'; + /* done cleaning the string */ + + fclose( fp ); + + py_res = PyRun_String( buffer_ofs, Py_file_input, py_dict, py_dict ); + MEM_freeN( buffer ); + } + + if( !py_res ) { /* Failed execution of the script */ + BPY_Err_Handle( script->id.name + 2 ); ReleaseGlobalDictionary( py_dict ); script->py_globaldict = NULL; @@ -929,39 +964,9 @@ int BPY_run_script(Script *script) * menutype and event values to know which one was chosen. *****************************************************************************/ int BPY_menu_do_python( short menutype, int event ) -{ - BPyMenu *pym; - pym = BPyMenu_GetEntry( menutype, ( short ) event ); - return BPY_menu_invoke( pym, menutype ); -} - -/**************************************************************************** -* Description: This function executes the script by its shortcut. -* Notes: It is called by the ui code in src/???.c when a user presses an -* unassigned key combination. Scripts are searched in the BPyMenuTable, -* using the given menutype and event values to know which one to invoke. -*****************************************************************************/ -int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short qual ) -{ - BPyMenu *pym; - pym = BPyMenu_GetEntry( menutype, 0 ); - - while ( pym ) { - if ( pym->key && pym->key == key && pym->qual == qual ) { - return BPY_menu_invoke( pym, menutype ); - } - pym = pym->next; - } - - return 0; -} - -/**************************************************************************** -* Description: This function executes the script described by a menu item. -*****************************************************************************/ -int BPY_menu_invoke( BPyMenu *pym, short menutype ) { char *argstr = NULL; + BPyMenu *pym; BPySubMenu *pysm; char scriptname[21]; Script *script = NULL; @@ -969,6 +974,8 @@ int BPY_menu_invoke( BPyMenu *pym, short menutype ) PyGILState_STATE gilstate; char filestr[FILE_MAX]; + pym = BPyMenu_GetEntry( menutype, ( short ) event ); + if( !pym ) return 0; @@ -1052,7 +1059,6 @@ int BPY_menu_invoke( BPyMenu *pym, short menutype ) case PYMENU_RENDER: case PYMENU_WIZARDS: case PYMENU_SCRIPTTEMPLATE: - case PYMENU_TEXTPLUGIN: case PYMENU_MESHFACEKEY: break; diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c index 69b50e5c47a..82da9edbee6 100644 --- a/source/blender/python/BPY_menus.c +++ b/source/blender/python/BPY_menus.c @@ -42,7 +42,6 @@ #endif #include "BKE_global.h" #include "BKE_utildefines.h" -#include "BIF_keyval.h" #include "BLI_blenlib.h" #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" /* for U.pythondir */ @@ -107,8 +106,6 @@ static int bpymenu_group_atoi( char *str ) return PYMENU_ARMATURE; else if( !strcmp( str, "ScriptTemplate" ) ) return PYMENU_SCRIPTTEMPLATE; - else if( !strcmp( str, "TextPlugin" ) ) - return PYMENU_TEXTPLUGIN; else if( !strcmp( str, "MeshFaceKey" ) ) return PYMENU_MESHFACEKEY; else if( !strcmp( str, "AddMesh" ) ) @@ -187,9 +184,6 @@ char *BPyMenu_group_itoa( short menugroup ) case PYMENU_SCRIPTTEMPLATE: return "ScriptTemplate"; break; - case PYMENU_TEXTPLUGIN: - return "TextPlugin"; - break; case PYMENU_MESHFACEKEY: return "MeshFaceKey"; break; @@ -334,23 +328,6 @@ static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip ) return; } -static void bpymenu_set_shortcut( BPyMenu * pymenu, char *combi ) -{ - unsigned short key, qual; - - if( !pymenu ) - return; - - if (!decode_key_string(combi, &key, &qual)) { - return; /* TODO: Print some error */ - } - - pymenu->key = key; - pymenu->qual = qual; - - 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. @@ -711,7 +688,6 @@ void BPyMenu_PrintAllEntries( void ) * # Blender: short int (minimal Blender version) * # Group: 'group name' (defines menu) * # Submenu: 'submenu name' related_1word_arg - * # Shortcut: Modifier+Key (optional shortcut combination for supported groups) * # Tooltip: 'tooltip for the menu' * # \"\"\" * @@ -820,19 +796,13 @@ static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir) if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) { bpymenu_AddSubEntry(scriptMenu, middle, tail); } else { - /* Shortcut: 'key+combination' */ + /* Tooltip: 'tooltip for the menu */ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); - if ((matches == 3) && (strstr(head, "Shortcut:") != NULL)) { - bpymenu_set_shortcut(scriptMenu, middle); - } 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; + if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) || + (strstr(head, "Tip:") != NULL))) { + bpymenu_set_tooltip(scriptMenu, middle); } + parser_state = 0; } break; diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h index 576d7b8dcd6..1b557f79286 100644 --- a/source/blender/python/BPY_menus.h +++ b/source/blender/python/BPY_menus.h @@ -59,7 +59,6 @@ typedef struct BPyMenu { char *name; char *filename; char *tooltip; - unsigned short key, qual; /* Registered shortcut key */ short version; /* Blender version */ int dir; /* 0: default, 1: U.pythondir */ struct BPySubMenu *submenus; @@ -100,7 +99,6 @@ typedef enum { PYMENU_UVCALCULATION, PYMENU_ARMATURE, PYMENU_SCRIPTTEMPLATE, - PYMENU_TEXTPLUGIN, PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/ PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */ PYMENU_HELPWEBSITES,/* Help -> Websites submenu */ diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 63a1e67236e..0106ab77843 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -34,7 +34,7 @@ SET(INC api2_2x ../blenkernel ../blenlib ../blenloader ../render/extern/include ../radiosity/extern/include ../makesdna ../../../intern/guardedalloc ../../../intern/bmfont ../imbuf ../include - ${PYTHON_INC} ../../../extern/glew/include ../gpu + ${PYTHON_INC} ) IF(WITH_QUICKTIME) @@ -50,9 +50,5 @@ IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) -IF(BF_BUILDINFO) - ADD_DEFINITIONS(-DNAN_BUILDINFO) -ENDIF(BF_BUILDINFO) - BLENDERLIB_NOLIST(blender_python "${SRC}" "${INC}") #env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] ) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 27dd510f944..481fdcbe13e 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -6,7 +6,6 @@ sources = Split('BPY_interface.c BPY_menus.c') + env.Glob('api2_2x/*.c') incs = 'api2_2x ../blenkernel ../nodes ../blenlib ../blenloader' incs += ' ../render/extern/include ../radiosity/extern/include' incs += ' ../makesdna #intern/guardedalloc #intern/bmfont ../imbuf ../include' -incs += ' #extern/glew/include ../gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] @@ -24,7 +23,4 @@ if env['WITH_BF_OPENEXR'] == 1: if env['WITH_BF_FFMPEG'] == 1: defs.append('WITH_FFMPEG') -if env['BF_BUILDINFO'] == 1: - defs.append('NAN_BUILDINFO') - env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] ) diff --git a/source/blender/python/api2_2x/BGL.h b/source/blender/python/api2_2x/BGL.h index 461f5bc9372..ce972795322 100644 --- a/source/blender/python/api2_2x/BGL.h +++ b/source/blender/python/api2_2x/BGL.h @@ -323,13 +323,8 @@ typedef struct _Buffer { #define ret_def_GLstring const unsigned char *ret_str; #define ret_set_GLstring ret_str= +#define ret_ret_GLstring return PyString_FromString(ret_str); + -#define ret_ret_GLstring \ - if (ret_str) {\ - return PyString_FromString(ret_str);\ - } else {\ - PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\ - return NULL;\ - } #endif /* EXPP_BGL_H */ diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 47e7bcb2007..2b190a6c828 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -34,7 +34,7 @@ struct ID; /*keep me up here */ /* for open, close in Blender_Load */ #include #include "BDR_editobject.h" /* exit_editmode() */ -#include "GPU_draw.h" /* GPU_set_mipmap() */ +#include "BDR_drawmesh.h" /* set_mipmap() */ #include "BIF_usiblender.h" #include "BLI_blenlib.h" #include "BLI_bpath.h" @@ -314,8 +314,8 @@ static PyObject *Blender_Set( PyObject * self, PyObject * args ) else U.gameflags |= USER_DISABLE_MIPMAP; - GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); - } else + set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + }else return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "value given is not a blender setting" ) ); Py_RETURN_NONE; @@ -543,21 +543,7 @@ static PyObject *Blender_Get( PyObject * self, PyObject * value ) } /* End 'quick hack' part. */ else if(StringEqual( str, "version" )) ret = PyInt_FromLong( G.version ); - else if(StringEqual( str, "buildinfo" )) { -#ifdef NAN_BUILDINFO - char buffer[1024]; - extern char * build_date; - extern char * build_time; - extern char * build_rev; - extern char * build_platform; - extern char * build_type; - - sprintf(buffer, "Built on %s %s, Rev-%s Version %s %s", build_date, build_time, build_rev, build_platform, build_type); - ret = PyString_FromString( buffer ); -#else - ret = PyString_FromString( "No Build Info" ); -#endif - } + else if(StringEqual( str, "compressfile" )) ret = PyInt_FromLong( (U.flag & USER_FILECOMPRESS) >> 15 ); else if(StringEqual( str, "mipmap" )) diff --git a/source/blender/python/api2_2x/Camera.c b/source/blender/python/api2_2x/Camera.c index 87c605ef612..b35fcf410a4 100644 --- a/source/blender/python/api2_2x/Camera.c +++ b/source/blender/python/api2_2x/Camera.c @@ -37,7 +37,6 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" /* for M_PI */ #include "BSE_editipo.h" -#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "gen_utils.h" diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index b0b9aa04a08..a62a5ee7ed8 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -44,7 +44,6 @@ #include "BKE_constraint.h" #include "BLI_blenlib.h" #include "BIF_editconstraint.h" -#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" @@ -442,7 +441,7 @@ static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * value ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "constraint doesn't belong to anything" ); } - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index b04366d5579..bd19a6a6a3e 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -928,11 +928,6 @@ static PyObject *Method_Register( PyObject * self, PyObject * args ) Script *script; int startspace = 0; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Register() in background mode." ); - } - if( !PyArg_ParseTuple ( args, "O|OO", &newdrawc, &neweventc, &newbuttonc ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1013,10 +1008,6 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) { int after = 0; - if (G.background) { - Py_RETURN_NONE; - } - if( !PyArg_ParseTuple( args, "|i", &after ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected int argument (or nothing)" ); @@ -1031,10 +1022,6 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) static PyObject *Method_Draw( PyObject * self ) { - if (G.background) { - Py_RETURN_NONE; - } - /*@ If forced drawing is disable queue a redraw event instead */ if( EXPP_disable_force_draw ) { scrarea_queue_winredraw( curarea ); @@ -1102,11 +1089,6 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args ) PyObject *result = NULL; ListBase listb= {NULL, NULL}; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.UIBlock() in background mode." ); - } - if ( !PyArg_ParseTuple( args, "O", &val ) || !PyCallable_Check( val ) ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected 1 python function and 2 ints" ); @@ -1219,11 +1201,6 @@ static PyObject *Method_Button( PyObject * self, PyObject * args ) int x, y, w, h; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Button() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiiii|sO", &name, &event, &x, &y, &w, &h, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1248,11 +1225,6 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Menu() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1283,11 +1255,6 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Toggle() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1355,11 +1322,6 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args ) PyObject *mino, *maxo, *inio; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Sider() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiiiiOOO|isO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip, &callback ) ) @@ -1433,11 +1395,6 @@ static PyObject *Method_Scrollbar( PyObject * self, PyObject * args ) float ini, min, max; uiBut *ubut; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Scrollbar() in background mode." ); - } - if( !PyArg_ParseTuple( args, "iiiiiOOO|isO", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1497,11 +1454,6 @@ static PyObject *Method_ColorPicker( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.ColorPicker() in background mode." ); - } - if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1552,11 +1504,6 @@ static PyObject *Method_Normal( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Normal() in background mode." ); - } - if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1599,11 +1546,6 @@ static PyObject *Method_Number( PyObject * self, PyObject * args ) PyObject *callback=NULL; uiBut *ubut= NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Number() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiiiiOOO|sO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1675,11 +1617,6 @@ static PyObject *Method_String( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.String() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiiiisi|sO", &info_arg, &event, &x, &y, &w, &h, &newstr, &len, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1756,11 +1693,6 @@ static PyObject *Method_Text( PyObject * self, PyObject * args ) char *font_str = NULL; struct BMF_Font *font; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Text() in background mode." ); - } - if( !PyArg_ParseTuple( args, "s|s", &text, &font_str ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected one or two string arguments" ); @@ -1792,11 +1724,6 @@ static PyObject *Method_Label( PyObject * self, PyObject * args ) char *text; int x, y, w, h; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Label() in background mode." ); - } - if( !PyArg_ParseTuple( args, "siiii", &text, &x, &y, &w, &h ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and four ints" ); @@ -1813,12 +1740,7 @@ static PyObject *Method_PupMenu( PyObject * self, PyObject * args ) char *text; int maxrow = -1; PyObject *ret; - - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.PupMenu() in background mode." ); - } - + if( !PyArg_ParseTuple( args, "s|i", &text, &maxrow ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and optionally an int as arguments" ); @@ -1905,11 +1827,6 @@ static PyObject *Method_PupTreeMenu( PyObject * self, PyObject * args ) ListBase storage = {NULL, NULL}; TBitem *tb; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.PupMenuTree() in background mode." ); - } - if( !PyArg_ParseTuple( args, "O!", &PyList_Type, ¤t_menu ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "Expected a list" ); @@ -1940,11 +1857,6 @@ static PyObject *Method_PupIntInput( PyObject * self, PyObject * args ) short var = 0; PyObject *ret = NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.PupIntInput() in background mode." ); - } - if( !PyArg_ParseTuple( args, "s|hii", &text, &var, &min, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 1 string and 3 int arguments" ); @@ -1967,11 +1879,6 @@ static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args ) float min = 0, max = 1, var = 0, a1 = 10, a2 = 2; PyObject *ret = NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.PupFloatInput() in background mode." ); - } - if( !PyArg_ParseTuple ( args, "s|fffff", &text, &var, &min, &max, &a1, &a2 ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1996,11 +1903,6 @@ static PyObject *Method_PupStrInput( PyObject * self, PyObject * args ) char max = 20; PyObject *ret = NULL; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.PupStrInput() in background mode." ); - } - if( !PyArg_ParseTuple( args, "ss|b", &textMsg, &text, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 strings and 1 int" ); @@ -2035,11 +1937,6 @@ static PyObject *Method_PupBlock( PyObject * self, PyObject * args ) int len, i; char *title; - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.PupBlock() in background mode." ); - } - if (!PyArg_ParseTuple( args, "sO", &title, &pyList ) || !PySequence_Check( pyList )) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and a sequence" ); @@ -2173,11 +2070,6 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) int clipX = 0, clipY = 0, clipW = -1, clipH = -1; /*GLfloat scissorBox[4];*/ - if (G.background) { - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Can't run Draw.Image() in background mode." ); - } - /* parse the arguments passed-in from Python */ if( !PyArg_ParseTuple( args, "O!ff|ffiiii", &Image_Type, &pyObjImage, &originX, &originY, &zoomX, &zoomY, diff --git a/source/blender/python/api2_2x/Group.c b/source/blender/python/api2_2x/Group.c index 3152d3a973f..3e7f02c3797 100644 --- a/source/blender/python/api2_2x/Group.c +++ b/source/blender/python/api2_2x/Group.c @@ -46,8 +46,6 @@ #include "gen_utils.h" #include "gen_library.h" -#include "vector.h" - /* checks for the group being removed */ #define GROUP_DEL_CHECK_PY(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Group has been removed" ) ) #define GROUP_DEL_CHECK_INT(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Group has been removed" ) ) @@ -202,31 +200,6 @@ static int Group_setObjects( BPy_Group * self, PyObject * args ) return 0; } -static PyObject *Group_getDupliOfs( BPy_Group * self ) -{ - GROUP_DEL_CHECK_PY(self); - return newVectorObject( self->group->dupli_ofs, 3, Py_WRAP ); -} - -static int Group_setDupliOfs( BPy_Group * self, PyObject * value ) -{ - VectorObject *bpy_vec; - GROUP_DEL_CHECK_INT(self); - if (!VectorObject_Check(value)) - return ( EXPP_ReturnIntError( PyExc_TypeError, - "expected a vector" ) ); - - bpy_vec = (VectorObject *)value; - - if (bpy_vec->size != 3) - return ( EXPP_ReturnIntError( PyExc_ValueError, - "can only assign a 3D vector" ) ); - - self->group->dupli_ofs[0] = bpy_vec->vec[0]; - self->group->dupli_ofs[1] = bpy_vec->vec[1]; - self->group->dupli_ofs[2] = bpy_vec->vec[2]; - return 0; -} /*****************************************************************************/ @@ -278,10 +251,6 @@ static PyGetSetDef BPy_Group_getseters[] = { (getter)Group_getObjects, (setter)Group_setObjects, "objects in this group", NULL}, - {"dupliOffset", - (getter)Group_getDupliOfs, (setter)Group_setDupliOfs, - "offset to use when instancing this group as a DupliGroup", - NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; diff --git a/source/blender/python/api2_2x/Image.c b/source/blender/python/api2_2x/Image.c index 5ef2cbadbdc..94da5a77170 100644 --- a/source/blender/python/api2_2x/Image.c +++ b/source/blender/python/api2_2x/Image.c @@ -29,6 +29,7 @@ */ #include "Image.h" /*This must come first */ +#include "BDR_drawmesh.h" /* free_realtime_image */ #include "BKE_main.h" #include "BKE_global.h" #include "BKE_library.h" @@ -47,7 +48,6 @@ #include "BKE_icons.h" #include "IMB_imbuf.h" #include "IDProp.h" -#include "GPU_draw.h" /* used so we can get G.scene->r.cfra for getting the current image frame, some images change frame if they are a sequence */ @@ -1003,7 +1003,7 @@ static PyObject *Image_glFree( BPy_Image * self ) { Image *image = self->image; - GPU_free_image( image ); + free_realtime_image( image ); /* remove the nocollect flag, image is available for garbage collection again */ image->flag &= ~IMA_NOCOLLECT; Py_RETURN_NONE; diff --git a/source/blender/python/api2_2x/Ipo.c b/source/blender/python/api2_2x/Ipo.c index 7c2e18bcdf6..68768fc9346 100644 --- a/source/blender/python/api2_2x/Ipo.c +++ b/source/blender/python/api2_2x/Ipo.c @@ -36,7 +36,6 @@ #include "BKE_object.h" #include "BKE_ipo.h" #include "BLI_blenlib.h" -#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Ipocurve.c b/source/blender/python/api2_2x/Ipocurve.c index 4a8cba30e8e..b9bfb77d19e 100644 --- a/source/blender/python/api2_2x/Ipocurve.c +++ b/source/blender/python/api2_2x/Ipocurve.c @@ -35,7 +35,6 @@ #include "BKE_depsgraph.h" #include "BKE_ipo.h" #include "BKE_utildefines.h" -#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 38968b64cf5..53d25a6429d 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -34,19 +34,15 @@ #include "BKE_global.h" #include "BKE_object.h" #include "BKE_library.h" -#include "BKE_texture.h" #include "BLI_blenlib.h" -#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "mydevice.h" #include "Ipo.h" -#include "MTex.h" #include "constant.h" #include "gen_utils.h" #include "gen_library.h" #include "BKE_utildefines.h" -#include "MEM_guardedalloc.h" /*****************************************************************************/ /* Python BPy_Lamp defaults: */ @@ -88,8 +84,6 @@ #define EXPP_LAMP_MODE_NODIFFUSE 2048 #define EXPP_LAMP_MODE_NOSPECULAR 4096 #define EXPP_LAMP_MODE_SHAD_RAY 8192 -#define EXPP_LAMP_MODE_LAYER_SHADOW 32768 - /* Lamp MIN, MAX values */ #define EXPP_LAMP_SAMPLES_MIN 1 @@ -210,7 +204,6 @@ static PyObject *Lamp_getQuad2( BPy_Lamp * self ); static PyObject *Lamp_getCol( BPy_Lamp * self ); static PyObject *Lamp_getIpo( BPy_Lamp * self ); static PyObject *Lamp_getComponent( BPy_Lamp * self, void * closure ); -static PyObject *Lamp_getTextures( BPy_Lamp * self ); static PyObject *Lamp_clearIpo( BPy_Lamp * self ); static PyObject *Lamp_insertIpoKey( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_oldsetIpo( BPy_Lamp * self, PyObject * args ); @@ -258,7 +251,6 @@ static int Lamp_setHaloInt( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad1( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad2( BPy_Lamp * self, PyObject * args ); static int Lamp_setCol( BPy_Lamp * self, PyObject * args ); -static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_getScriptLinks( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_addScriptLink( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ); @@ -506,10 +498,6 @@ static PyGetSetDef BPy_Lamp_getseters[] = { (getter)Lamp_getComponent, (setter)Lamp_setComponent, "Lamp color blue component", (void *)EXPP_LAMP_COMP_B}, - {"textures", - (getter)Lamp_getTextures, (setter)Lamp_setTextures, - "The Lamp's texture list as a tuple", - NULL}, {"Modes", (getter)Lamp_getModesConst, (setter)NULL, "Dictionary of values for 'mode' attribute", @@ -792,8 +780,6 @@ static PyObject *Lamp_ModesDict( void ) PyInt_FromLong( EXPP_LAMP_MODE_NOSPECULAR ) ); PyConstant_Insert( c, "RayShadow", PyInt_FromLong( EXPP_LAMP_MODE_SHAD_RAY ) ); - PyConstant_Insert( c, "LayerShadow", - PyInt_FromLong( EXPP_LAMP_MODE_LAYER_SHADOW ) ); } return Modes; @@ -1025,8 +1011,8 @@ static int Lamp_setType( BPy_Lamp * self, PyObject * value ) static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) { - int param; - static int bitmask = EXPP_LAMP_MODE_SHADOWS + short param; + static short bitmask = EXPP_LAMP_MODE_SHADOWS | EXPP_LAMP_MODE_HALO | EXPP_LAMP_MODE_LAYER | EXPP_LAMP_MODE_QUAD @@ -1036,15 +1022,14 @@ static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) | EXPP_LAMP_MODE_SQUARE | EXPP_LAMP_MODE_NODIFFUSE | EXPP_LAMP_MODE_NOSPECULAR - | EXPP_LAMP_MODE_SHAD_RAY - | EXPP_LAMP_MODE_LAYER_SHADOW; + | EXPP_LAMP_MODE_SHAD_RAY; if( !PyInt_Check ( value ) ) { char errstr[128]; sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask ); return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - param = PyInt_AS_LONG ( value ); + param = (short)PyInt_AS_LONG ( value ); if ( ( param & bitmask ) != param ) return EXPP_ReturnIntError( PyExc_ValueError, @@ -1388,8 +1373,7 @@ static PyObject *Lamp_getModesConst( void ) EXPP_LAMP_MODE_SQUARE, "NoDiffuse", EXPP_LAMP_MODE_NODIFFUSE, "NoSpecular", EXPP_LAMP_MODE_NOSPECULAR, "RayShadow", - EXPP_LAMP_MODE_SHAD_RAY, "LayerShadow", - EXPP_LAMP_MODE_LAYER_SHADOW); + EXPP_LAMP_MODE_SHAD_RAY); } static PyObject *Lamp_getTypesConst( void ) @@ -1403,100 +1387,6 @@ static PyObject *Lamp_getTypesConst( void ) "Photon", EXPP_LAMP_TYPE_YF_PHOTON ); } -static PyObject *Lamp_getTextures( BPy_Lamp * self ) -{ - int i; - PyObject *tuple; - - /* build a texture list */ - tuple = PyTuple_New( MAX_MTEX ); - if( !tuple ) - return EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create PyTuple" ); - - for( i = 0; i < MAX_MTEX; ++i ) { - struct MTex *mtex = self->lamp->mtex[i]; - if( mtex ) { - PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_LA ) ); - } else { - Py_INCREF( Py_None ); - PyTuple_SET_ITEM( tuple, i, Py_None ); - } - } - - return tuple; -} - -static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ) -{ - int i; - - if( !PyList_Check( value ) && !PyTuple_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list of integers" ); - - /* don't allow more than MAX_MTEX items */ - if( PySequence_Size(value) > MAX_MTEX ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "size of sequence greater than number of allowed textures" ); - - /* get a fast sequence; in Python 2.5, this just return the original - * list or tuple and INCREFs it, so we must DECREF */ - value = PySequence_Fast( value, "" ); - - /* check the list for valid entries */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - if( item == Py_None || ( BPy_MTex_Check( item ) && - ((BPy_MTex *)item)->type == ID_LA ) ) { - continue; - } else { - Py_DECREF(value); - return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list containing lamp MTex objects and NONE" ); - } - } - - /* for each MTex object, copy to this structure */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - struct MTex *mtex = self->lamp->mtex[i]; - if( item != Py_None ) { - BPy_MTex *obj = (BPy_MTex *)item; - - /* if MTex is already at this location, just skip it */ - if( obj->mtex == mtex ) continue; - - /* create a new entry if needed, otherwise update reference count - * for texture that is being replaced */ - if( !mtex ) - mtex = self->lamp->mtex[i] = add_mtex( ); - else - mtex->tex->id.us--; - - /* copy the data */ - mtex->tex = obj->mtex->tex; - id_us_plus( &mtex->tex->id ); - mtex->texco = obj->mtex->texco; - mtex->mapto = obj->mtex->mapto; - } - } - - /* now go back and free any entries now marked as None */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - struct MTex *mtex = self->lamp->mtex[i]; - if( item == Py_None && mtex ) { - mtex->tex->id.us--; - MEM_freeN( mtex ); - self->lamp->mtex[i] = NULL; - } - } - - Py_DECREF(value); - return 0; -} - /* #####DEPRECATED###### */ static PyObject *Lamp_oldsetSamples( BPy_Lamp * self, PyObject * args ) @@ -1707,8 +1597,6 @@ static PyObject *Lamp_oldsetMode( BPy_Lamp * self, PyObject * args ) flag |= ( short ) EXPP_LAMP_MODE_NOSPECULAR; else if( !strcmp( name, "RayShadow" ) ) flag |= ( short ) EXPP_LAMP_MODE_SHAD_RAY; - else if( !strcmp( name, "LayerShadow" ) ) - flag |= ( short ) EXPP_LAMP_MODE_LAYER_SHADOW; else return EXPP_ReturnPyObjError( PyExc_AttributeError, "unknown lamp flag argument" ); diff --git a/source/blender/python/api2_2x/MTex.c b/source/blender/python/api2_2x/MTex.c index 4db9715a465..b9a8f7fff65 100644 --- a/source/blender/python/api2_2x/MTex.c +++ b/source/blender/python/api2_2x/MTex.c @@ -22,11 +22,10 @@ * * This is a new part of Blender. * - * Contributor(s): Alex Mole, Yehoshua Sapir, Ken Hughes + * Contributor(s): Alex Mole, Yehoshua Sapir * * ***** END GPL LICENSE BLOCK ***** */ - #include "MTex.h" /*This must come first*/ #include "BKE_utildefines.h" @@ -36,8 +35,7 @@ #include "gen_utils.h" #include "gen_library.h" -#include "DNA_material_types.h" -#include "DNA_world_types.h" +#include /*****************************************************************************/ /* Python BPy_MTex methods declarations: */ @@ -96,7 +94,6 @@ MTEXGETSET(ProjX) MTEXGETSET(ProjY) MTEXGETSET(ProjZ) MTEXGETSET(MapToFlag) -MTEXGETSET(WorldMapToFlag) /*****************************************************************************/ /* Python get/set methods table */ @@ -157,14 +154,8 @@ static PyGetSetDef MTex_getseters[] = { "Projection of Y axis to Texture space", NULL }, { "zproj", (getter) MTex_getProjZ, (setter) MTex_setProjZ, "Projection of Z axis to Texture space", NULL }, - - /* MapTo for Material and Lamp MTex */ - { "mtCol", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to color", (void*) MAP_COL }, - - /* MapTo for Material MTex */ - { "mtNor", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to normals", (void*) MAP_NORM }, { "mtCsp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, @@ -191,18 +182,6 @@ static PyGetSetDef MTex_getseters[] = { "How texture maps to displacement", (void*) MAP_DISPLACE }, { "mtWarp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to warp", (void*) MAP_WARP }, - - /* MapTo for World MTex */ - - { "mtBlend", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, - "Texture affects color progression of background", (void*) WOMAP_BLEND }, - { "mtHoriz", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, - "Texture affects color of the horizon", (void*) WOMAP_HORIZ }, - { "mtZenUp", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, - "Texture affects color of the zenith above", (void*) WOMAP_ZENUP }, - { "mtZenDown", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, - "Texture affects color of the zenith below", (void*) WOMAP_ZENDOWN }, - { NULL, NULL, NULL, NULL, NULL } }; @@ -273,7 +252,7 @@ PyObject *MTex_Init( void ) return submodule; } -PyObject *MTex_CreatePyObject( MTex * mtex, unsigned short type ) +PyObject *MTex_CreatePyObject( MTex * mtex ) { BPy_MTex *pymtex; @@ -283,7 +262,6 @@ PyObject *MTex_CreatePyObject( MTex * mtex, unsigned short type ) "couldn't create BPy_MTex PyObject" ); pymtex->mtex = mtex; - pymtex->type = type; return ( PyObject * ) pymtex; } @@ -308,12 +286,7 @@ static int MTex_compare( BPy_MTex * a, BPy_MTex * b ) static PyObject *MTex_repr( BPy_MTex * self ) { - if( self->type == ID_MA ) - return PyString_FromFormat( "[MTex (Material)]" ); - else if( self->type == ID_LA ) - return PyString_FromFormat( "[MTex (Lamp)]" ); - else - return PyString_FromFormat( "[MTex (World)]" ); + return PyString_FromFormat( "[MTex]" ); } @@ -343,37 +316,19 @@ static int MTex_setTexCo( BPy_MTex *self, PyObject *value, void *closure) { int texco; - if( !PyInt_Check( value ) ) + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.TexCo dictionary" ); + } texco = PyInt_AsLong( value ) ; - switch ( self->type ) { - case ID_MA : - if( texco != TEXCO_ORCO && texco != TEXCO_REFL && - texco != TEXCO_NORM && texco != TEXCO_GLOB && - texco != TEXCO_UV && texco != TEXCO_OBJECT && - texco != TEXCO_STRESS && texco != TEXCO_TANGENT && - texco != TEXCO_WINDOW && texco != TEXCO_VIEW && - texco != TEXCO_STICKY ) - return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be a member of Texture.TexCo dictionary" ); - break; - case ID_LA : - if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && - texco != TEXCO_OBJECT ) - return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be a member of Texture.TexCo dictionary" ); - break; - default: /* ID_WO */ - if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && - texco != TEXCO_ANGMAP && texco != TEXCO_OBJECT && - texco != TEXCO_H_SPHEREMAP && texco != TEXCO_H_TUBEMAP ) - return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be a member of Texture.TexCo dictionary" ); - break; - } + if (texco != TEXCO_ORCO && texco != TEXCO_REFL && texco != TEXCO_NORM && + texco != TEXCO_GLOB && texco != TEXCO_UV && texco != TEXCO_OBJECT && + texco != TEXCO_STRESS && texco != TEXCO_TANGENT && texco != TEXCO_WINDOW && + texco != TEXCO_VIEW && texco != TEXCO_STICKY ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); self->mtex->texco = (short)texco; @@ -395,10 +350,6 @@ static int MTex_setObject( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getUVLayer( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a Material MTex object" ); - return PyString_FromString(self->mtex->uvname); } @@ -413,10 +364,6 @@ static int MTex_setUVLayer( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapTo( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a Material MTex object" ); - return PyInt_FromLong( self->mtex->mapto ); } @@ -424,20 +371,18 @@ static int MTex_setMapTo( BPy_MTex *self, PyObject *value, void *closure) { int mapto; - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); - - if( !PyInt_Check( value ) ) + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, - "expected an int" ); + "expected an int" ); + } mapto = PyInt_AsLong( value ); /* This method is deprecated anyway. */ - if ( mapto < 0 || mapto > 16383 ) + if ( mapto < 0 || mapto > 16383 ) { return EXPP_ReturnIntError( PyExc_ValueError, "Value must be a sum of values from Texture.MapTo dictionary" ); + } self->mtex->mapto = (short)mapto; @@ -455,9 +400,11 @@ static int MTex_setCol( BPy_MTex *self, PyObject *value, void *closure) float rgb[3]; int i; - if( !PyArg_ParseTuple( value, "fff", &rgb[0], &rgb[1], &rgb[2] ) ) + if( !PyArg_ParseTuple( value, "fff", + &rgb[0], &rgb[1], &rgb[2] ) ) + return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple of 3 floats" ); + "expected tuple of 3 floats" ); for( i = 0; i < 3; ++i ) if( rgb[i] < 0 || rgb[i] > 1 ) @@ -506,13 +453,18 @@ static int MTex_setBlendMode( BPy_MTex *self, PyObject *value, void *closure) if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "Value must be member of Texture.BlendModes dictionary" ); + "Value must be member of Texture.BlendModes dictionary" ); n = PyInt_AsLong(value); +/* if (n != MTEX_BLEND && n != MTEX_MUL && n != MTEX_ADD && + n != MTEX_SUB && n != MTEX_DIV && n != MTEX_DARK && + n != MTEX_DIFF && n != MTEX_LIGHT && n != MTEX_SCREEN)*/ if (n < 0 || n > 8) + { return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be member of Texture.BlendModes dictionary" ); + "Value must be member of Texture.BlendModes dictionary" ); + } self->mtex->blendtype = (short)n; @@ -526,84 +478,117 @@ static PyObject *MTex_getColFac( BPy_MTex *self, void *closure ) static int MTex_setColFac( BPy_MTex *self, PyObject *value, void *closure) { - return EXPP_setFloatRange( value, &self->mtex->colfac, 0.0f, 1.0f ); + float f; + + if ( !PyFloat_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float" ); + + f = (float)PyFloat_AsDouble(value); + + if (f < 0 || f > 1) + return EXPP_ReturnIntError( PyExc_ValueError, + "values must be in range [0,1]" ); + + self->mtex->colfac = f; + + return 0; } static PyObject *MTex_getNorFac( BPy_MTex *self, void *closure ) { - if( self->type == ID_LA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material or world MTex object" ); - return PyFloat_FromDouble(self->mtex->norfac); } static int MTex_setNorFac( BPy_MTex *self, PyObject *value, void *closure) { - switch( self->type ) - { - case ID_WO: - return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 1.0f ); - case ID_MA: - return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 25.0f ); - default: - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material or world MTex object" ); - } + float f; + + if ( !PyFloat_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float" ); + + f = (float)PyFloat_AsDouble(value); + + if (f < 0 || f > 25) + return EXPP_ReturnIntError( PyExc_ValueError, + "values must be in range [0,25]" ); + + self->mtex->norfac = f; + + return 0; } static PyObject *MTex_getVarFac( BPy_MTex *self, void *closure ) { - if( self->type == ID_LA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material or world MTex object" ); - return PyFloat_FromDouble(self->mtex->varfac); } static int MTex_setVarFac( BPy_MTex *self, PyObject *value, void *closure) { - if( self->type == ID_LA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material or world MTex object" ); + float f; - return EXPP_setFloatRange( value, &self->mtex->varfac, 0.0f, 1.0f ); + if ( !PyFloat_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float" ); + + f = (float)PyFloat_AsDouble(value); + + if (f < 0 || f > 1) + return EXPP_ReturnIntError( PyExc_ValueError, + "values must be in range [0,1]" ); + + self->mtex->varfac = f; + + return 0; } static PyObject *MTex_getDispFac( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); - return PyFloat_FromDouble(self->mtex->dispfac); } static int MTex_setDispFac( BPy_MTex *self, PyObject *value, void *closure) { - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); + float f; - return EXPP_setFloatRange( value, &self->mtex->dispfac, 0.0f, 1.0f ); + if ( !PyFloat_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float" ); + + f = (float)PyFloat_AsDouble(value); + + if (f < 0 || f > 1) + return EXPP_ReturnIntError( PyExc_ValueError, + "values must be in range [0,1]" ); + + self->mtex->dispfac = f; + + return 0; } static PyObject *MTex_getWarpFac( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); - return PyFloat_FromDouble(self->mtex->warpfac); } static int MTex_setWarpFac( BPy_MTex *self, PyObject *value, void *closure) { - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); + float f; - return EXPP_setFloatRange( value, &self->mtex->warpfac, 0.0f, 1.0f ); + if ( !PyFloat_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected a float" ); + + f = (float)PyFloat_AsDouble(value); + + if (f < 0 || f > 1) + return EXPP_ReturnIntError( PyExc_ValueError, + "values must be in range [0,1]" ); + + self->mtex->warpfac = f; + + return 0; } static PyObject *MTex_getOfs( BPy_MTex *self, void *closure ) @@ -616,24 +601,16 @@ static int MTex_setOfs( BPy_MTex *self, PyObject *value, void *closure) { float f[3]; int i; - float max; if( !PyArg_ParseTuple( value, "fff", &f[0], &f[1], &f[2] ) ) + return EXPP_ReturnIntError( PyExc_TypeError, "expected tuple of 3 floats" ); - if( self->type == ID_MA ) - max = 10.0f; - else - max = 20.0f; - for( i = 0; i < 3; ++i ) - if( f[i] < -max || f[i] > max ) { - char errstr[64]; - sprintf( errstr, "values must be in range [-%6.0f,%6.0f]", - max, max ); - return EXPP_ReturnIntError( PyExc_ValueError, errstr ); - } + if( f[i] < -10 || f[i] > 10 ) + return EXPP_ReturnIntError( PyExc_ValueError, + "values must be in range [-10,10]" ); self->mtex->ofs[0] = f[0]; self->mtex->ofs[1] = f[1]; @@ -672,10 +649,6 @@ static int MTex_setSize( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapping( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); - return PyInt_FromLong( self->mtex->mapping ); } @@ -683,11 +656,6 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) { int n; - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); - - if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be member of Texture.Mappings dictionary" ); @@ -696,7 +664,8 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) /* if (n != MTEX_FLAT && n != MTEX_TUBE && n != MTEX_CUBE && n != MTEX_SPHERE) */ - if (n < 0 || n > 3) { + if (n < 0 || n > 3) + { return EXPP_ReturnIntError( PyExc_ValueError, "Value must be member of Texture.Mappings dictionary" ); } @@ -708,43 +677,25 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getFlag( BPy_MTex *self, void *closure ) { - int flag = GET_INT_FROM_POINTER(closure); - - if( self->type != ID_MA && - flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "attribute only vaild for material MTex object" ); - - return PyBool_FromLong( self->mtex->texflag & flag ); + return PyBool_FromLong( self->mtex->texflag & ((int) closure) ); } static int MTex_setFlag( BPy_MTex *self, PyObject *value, void *closure) { - int flag = GET_INT_FROM_POINTER(closure); - - if( self->type != ID_MA && - flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "attribute only vaild for material MTex object" ); - if ( !PyBool_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected a bool"); if ( value == Py_True ) - self->mtex->texflag |= flag; + self->mtex->texflag |= (int)closure; else - self->mtex->texflag &= ~flag; + self->mtex->texflag &= ~((int) closure); return 0; } static PyObject *MTex_getProjX( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); - return PyInt_FromLong( self->mtex->projx ); } @@ -752,10 +703,6 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) { int proj; - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); - if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -775,10 +722,6 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getProjY( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); - return PyInt_FromLong( self->mtex->projy ); } @@ -786,10 +729,6 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) { int proj; - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); - if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -809,10 +748,6 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) static PyObject *MTex_getProjZ( BPy_MTex *self, void *closure ) { - if( self->type != ID_MA ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); - return PyInt_FromLong( self->mtex->projz ); } @@ -820,10 +755,6 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) { int proj; - if( self->type != ID_MA ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); - if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -843,45 +774,29 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapToFlag( BPy_MTex *self, void *closure ) { - int flag = GET_INT_FROM_POINTER(closure); - - if( self->type == ID_LA && flag != MAP_COL ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "attribute not available for a lamp MTex" ); + int flag = (int) closure; if ( self->mtex->mapto & flag ) + { return PyInt_FromLong( ( self->mtex->maptoneg & flag ) ? -1 : 1 ); - else + } else { return PyInt_FromLong( 0 ); -} - -static PyObject *MTex_getWorldMapToFlag( BPy_MTex *self, void *closure ) -{ - int flag = GET_INT_FROM_POINTER(closure); - - if( self->type != ID_WO ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a world MTex object" ); - - return PyInt_FromLong( (long)( (self->mtex->mapto & flag) != 0 ) ); + } } static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) { - int flag = GET_INT_FROM_POINTER(closure); + int flag = (int) closure; int intVal; - if( self->type == ID_LA && flag != MAP_COL ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "attribute not available for a lamp MTex" ); - if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected an int"); - intVal = PyInt_AsLong( value ) ; + intVal = PyInt_AsLong( value ); - if( flag & ( MAP_COL | MAP_COLSPEC | MAP_COLMIR | MAP_WARP ) ) { + if (flag == MAP_COL || flag == MAP_COLSPEC || flag == MAP_COLMIR || + flag == MAP_WARP) { if (intVal < 0 || intVal > 1) { return EXPP_ReturnIntError( PyExc_ValueError, "value for that mapping must be 0 or 1" ); @@ -913,31 +828,3 @@ static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) return 0; } - -static int MTex_setWorldMapToFlag( BPy_MTex *self, PyObject *value, void *closure) -{ - int flag = GET_INT_FROM_POINTER(closure); - - if( self->type != ID_WO ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "attribute only available for a world MTex" ); - - if ( !PyInt_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected an int"); - - switch( PyInt_AsLong( value ) ) { - case 0: - self->mtex->mapto &= ~flag; - break; - case 1: - self->mtex->mapto |= flag; - break; - default: - return EXPP_ReturnIntError( PyExc_ValueError, - "value for mapping must be 0 or 1" ); - } - - return 0; -} - diff --git a/source/blender/python/api2_2x/MTex.h b/source/blender/python/api2_2x/MTex.h index b6c98a40d2e..5e67ebc47ca 100644 --- a/source/blender/python/api2_2x/MTex.h +++ b/source/blender/python/api2_2x/MTex.h @@ -38,26 +38,22 @@ /* Python BPy_MTex structure definition */ /*****************************************************************************/ -#define MATERIAL_MTEX_TYPE 1 -#define WORLD_MTEX_TYPE 2 -#define LAMP_MTEX_TYPE 3 - typedef struct { PyObject_HEAD MTex * mtex; - unsigned short type; } BPy_MTex; extern PyTypeObject MTex_Type; #define BPy_MTex_Check(v) ((v)->ob_type == &MTex_Type) + /*****************************************************************************/ /* Module Blender.Texture.MTex - public functions */ /*****************************************************************************/ PyObject *MTex_Init( void ); -PyObject *MTex_CreatePyObject( struct MTex *obj, unsigned short type ); +PyObject *MTex_CreatePyObject( struct MTex *obj ); MTex *MTex_FromPyObject( PyObject * py_obj ); diff --git a/source/blender/python/api2_2x/Makefile b/source/blender/python/api2_2x/Makefile index a2b77bf8c98..7c831952042 100644 --- a/source/blender/python/api2_2x/Makefile +++ b/source/blender/python/api2_2x/Makefile @@ -37,10 +37,6 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) -ifdef NAN_BUILDINFO - CPPFLAGS += -DNAN_BUILDINFO -endif - ifeq ($(WITH_FFMPEG), true) CPPFLAGS += -DWITH_FFMPEG endif @@ -49,7 +45,6 @@ ifeq ($(WITH_OPENEXR),true) CPPFLAGS += -DWITH_OPENEXR endif -CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../makesdna @@ -57,7 +52,6 @@ CPPFLAGS += -I../../blenkernel CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader CPPFLAGS += -I../../include -CPPFLAGS += -I../../gpu CPPFLAGS += -I../../render/extern/include CPPFLAGS += -I../../radiosity/extern/include CPPFLAGS += -I$(NAN_BMFONT)/include diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index b118bdb30e7..20747a167e6 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -37,13 +37,11 @@ #include "BKE_library.h" #include "BKE_material.h" #include "BKE_texture.h" -#include "BKE_node.h" #include "BKE_idprop.h" #include "BKE_utildefines.h" /* for CLAMP */ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" -#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "constant.h" @@ -156,8 +154,6 @@ #define EXPP_MAT_SPECTRANS_MAX 1.0 #define EXPP_MAT_MIRRTRANSADD_MIN 0.0 #define EXPP_MAT_MIRRTRANSADD_MAX 1.0 -#define EXPP_MAT_COLORBAND_FACTOR_MIN 0.0 -#define EXPP_MAT_COLORBAND_FACTOR_MAX 1.0 /* closure values for getColorComponent()/setColorComponent() */ @@ -406,62 +402,19 @@ static PyObject *Material_ShadersDict( void ) return Shaders; } -static PyObject *Material_ColorRampMethodsDict( void ) -{ - PyObject *Methods = PyConstant_New( ); - if( Methods ) { - BPy_constant *c = (BPy_constant * ) Methods; - - PyConstant_Insert(c, "BLEND", PyInt_FromLong(MA_RAMP_BLEND)); - PyConstant_Insert(c, "MIX", PyInt_FromLong(MA_RAMP_BLEND)); /* This one is added to solve confusion between Blend-Mix name. */ - PyConstant_Insert(c, "ADD", PyInt_FromLong(MA_RAMP_ADD)); - PyConstant_Insert(c, "MULT", PyInt_FromLong(MA_RAMP_MULT)); - PyConstant_Insert(c, "SUB", PyInt_FromLong(MA_RAMP_SUB)); - PyConstant_Insert(c, "SCREEN", PyInt_FromLong(MA_RAMP_SCREEN)); - PyConstant_Insert(c, "DIV", PyInt_FromLong(MA_RAMP_DIV)); - PyConstant_Insert(c, "DIFF", PyInt_FromLong(MA_RAMP_DIFF)); - PyConstant_Insert(c, "DARK", PyInt_FromLong(MA_RAMP_DARK)); - PyConstant_Insert(c, "LIGHT", PyInt_FromLong(MA_RAMP_LIGHT)); - PyConstant_Insert(c, "OVERLAY", PyInt_FromLong(MA_RAMP_OVERLAY)); - PyConstant_Insert(c, "DODGE", PyInt_FromLong(MA_RAMP_DODGE)); - PyConstant_Insert(c, "BURN", PyInt_FromLong(MA_RAMP_BURN)); - PyConstant_Insert(c, "HUE", PyInt_FromLong(MA_RAMP_HUE)); - PyConstant_Insert(c, "SAT", PyInt_FromLong(MA_RAMP_SAT)); - PyConstant_Insert(c, "VAL", PyInt_FromLong(MA_RAMP_VAL)); - PyConstant_Insert(c, "COLOR", PyInt_FromLong(MA_RAMP_COLOR)); - - } - return Methods; -} - -static PyObject *Material_ColorRampInputDict( void ) -{ - PyObject *Inputs = PyConstant_New( ); - if( Inputs ) { - BPy_constant *c = (BPy_constant * ) Inputs; - - PyConstant_Insert(c, "SHADER", PyInt_FromLong(MA_RAMP_IN_SHADER)); - PyConstant_Insert(c, "ENERGY", PyInt_FromLong(MA_RAMP_IN_ENERGY)); - PyConstant_Insert(c, "NORMAL", PyInt_FromLong(MA_RAMP_IN_NOR)); - PyConstant_Insert(c, "RESULT", PyInt_FromLong(MA_RAMP_IN_RESULT)); - } - return Inputs; -} /*****************************************************************************/ /* Function: Material_Init */ /*****************************************************************************/ PyObject *Material_Init( void ) { - PyObject *submodule, *Modes, *Shaders, *ColorbandInput, *ColorbandMethod; + PyObject *submodule, *Modes, *Shaders; if( PyType_Ready( &Material_Type ) < 0) return NULL; Modes = Material_ModesDict( ); Shaders = Material_ShadersDict( ); - ColorbandMethod = Material_ColorRampMethodsDict( ); - ColorbandInput = Material_ColorRampInputDict( ); submodule = Py_InitModule3( "Blender.Material", M_Material_methods, M_Material_doc ); @@ -470,10 +423,6 @@ PyObject *Material_Init( void ) PyModule_AddObject( submodule, "Modes", Modes ); if( Shaders ) PyModule_AddObject( submodule, "Shaders", Shaders ); - if( ColorbandMethod ) - PyModule_AddObject( submodule, "ColorbandMethod", ColorbandMethod ); - if( ColorbandInput ) - PyModule_AddObject( submodule, "ColorbandInput", ColorbandInput ); PyModule_AddIntConstant( submodule, "RGB", IPOKEY_RGB ); PyModule_AddIntConstant( submodule, "ALPHA", IPOKEY_ALPHA ); @@ -606,7 +555,6 @@ static int Material_setSssFront( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setTexChannel( BPy_Material * self, PyObject * value ); -static int Material_setTextures( BPy_Material * self, PyObject * value ); static PyObject *Material_getColorComponent( BPy_Material * self, void * closure ); @@ -700,21 +648,6 @@ static PyObject *Material_insertIpoKey( BPy_Material * self, PyObject * args ); static PyObject *Material_getColorband( BPy_Material * self, void * type); int Material_setColorband( BPy_Material * self, PyObject * value, void * type); static PyObject *Material_copy( BPy_Material * self ); -static PyObject *Material_freeNodes( BPy_Material * self ); - -static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ); -static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ); -static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ); -static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ); -static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ); -static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ); -static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value); -static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value); -static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ); -static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ); -static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value); -static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value); - /*****************************************************************************/ @@ -953,8 +886,6 @@ static PyMethodDef BPy_Material_methods[] = { "() - Return a copy of the material."}, {"copy", ( PyCFunction ) Material_copy, METH_NOARGS, "() - Return a copy of the material."}, - {"freeNodes", ( PyCFunction ) Material_freeNodes, METH_NOARGS, - "() - Free this materials nodes."}, {NULL, NULL, 0, NULL} }; @@ -1237,35 +1168,7 @@ static PyGetSetDef BPy_Material_getseters[] = { (getter)Material_getColorband, (setter)Material_setColorband, "The specular colorband for this material", (void *) 1}, - {"textures", - (getter)Material_getTextures, (setter)Material_setTextures, - "The Material's texture list as a tuple", - NULL}, - {"colorbandSpecularFactor", - (getter)Material_getColorbandSpecularFactor, (setter)Material_setColorbandSpecularFactor, - "The specular colorband factor for this material", - NULL}, - {"colorbandSpecularMethod", - (getter)Material_getColorbandSpecularMethod, (setter)Material_setColorbandSpecularMethod, - "The specular colorband method for this material", - NULL}, - {"colorbandSpecularInput", - (getter)Material_getColorbandSpecularInput, (setter)Material_setColorbandSpecularInput, - "The specular colorband input for this material", - NULL}, - {"colorbandDiffuseFactor", - (getter)Material_getColorbandDiffuseFactor, (setter)Material_setColorbandDiffuseFactor, - "The diffuse colorband factor for this material", - NULL}, - {"colorbandDiffuseMethod", - (getter)Material_getColorbandDiffuseMethod, (setter)Material_setColorbandDiffuseMethod, - "The diffuse colorband method for this material", - NULL}, - {"colorbandDiffuseInput", - (getter)Material_getColorbandDiffuseInput, (setter)Material_setColorbandDiffuseInput, - "The diffuse colorband input for this material", - NULL}, - + /* SSS settings */ {"enableSSS", (getter)Material_getSssEnable, (setter)Material_setSssEnable, @@ -1834,24 +1737,29 @@ static PyObject* Material_getSssBack( BPy_Material * self ) static PyObject *Material_getTextures( BPy_Material * self ) { int i; + struct MTex *mtex; + PyObject *t[MAX_MTEX]; PyObject *tuple; /* build a texture list */ - tuple = PyTuple_New( MAX_MTEX ); - if( !tuple ) - return EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create PyTuple" ); - for( i = 0; i < MAX_MTEX; ++i ) { - struct MTex *mtex = self->material->mtex[i]; + mtex = self->material->mtex[i]; + if( mtex ) { - PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_MA ) ); + t[i] = MTex_CreatePyObject( mtex ); } else { Py_INCREF( Py_None ); - PyTuple_SET_ITEM( tuple, i, Py_None ); + t[i] = Py_None; } } + /* turn the array into a tuple */ + tuple = Py_BuildValue( "NNNNNNNNNN", t[0], t[1], t[2], t[3], + t[4], t[5], t[6], t[7], t[8], t[9] ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "Material_getTextures: couldn't create PyTuple" ); + return tuple; } @@ -2525,86 +2433,14 @@ static PyObject *Material_setTexture( BPy_Material * self, PyObject * args ) Py_RETURN_NONE; } -static int Material_setTextures( BPy_Material * self, PyObject * value ) -{ - int i; - - if( !PyList_Check( value ) && !PyTuple_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list of integers" ); - - /* don't allow more than MAX_MTEX items */ - if( PySequence_Size(value) > MAX_MTEX ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "size of sequence greater than number of allowed textures" ); - - /* get a fast sequence; in Python 2.5, this just return the original - * list or tuple and INCREFs it, so we must DECREF */ - value = PySequence_Fast( value, "" ); - - /* check the list for valid entries */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - if( item == Py_None || ( BPy_MTex_Check( item ) && - ((BPy_MTex *)item)->type == ID_MA ) ) { - continue; - } else { - Py_DECREF(value); - return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list containing material MTex objects and NONE" ); - } - } - - /* for each MTex object, copy to this structure */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - struct MTex *mtex = self->material->mtex[i]; - if( item != Py_None ) { - BPy_MTex *obj = (BPy_MTex *)item; - - /* if MTex is already at this location, just skip it */ - if( obj->mtex == mtex ) continue; - - /* create a new entry if needed, otherwise update reference count - * for texture that is being replaced */ - if( !mtex ) - mtex = self->material->mtex[i] = add_mtex( ); - else - mtex->tex->id.us--; - - /* copy the data */ - mtex->tex = obj->mtex->tex; - id_us_plus( &mtex->tex->id ); - mtex->texco = obj->mtex->texco; - mtex->mapto = obj->mtex->mapto; - } - } - - /* now go back and free any entries now marked as None */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - struct MTex *mtex = self->material->mtex[i]; - if( item == Py_None && mtex ) { - mtex->tex->id.us--; - MEM_freeN( mtex ); - self->material->mtex[i] = NULL; - } - } - - Py_DECREF(value); - return 0; -} - static PyObject *Material_clearTexture( BPy_Material * self, PyObject * value ) { int texnum = (int)PyInt_AsLong(value); struct MTex *mtex; /* non ints will be -1 */ - if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) { - char errstr[64]; - sprintf( errstr, "expected int in [0,%d]", MAX_MTEX ); - return EXPP_ReturnPyObjError( PyExc_TypeError, errstr ); - } + if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int in [0,9]" ); mtex = self->material->mtex[texnum]; if( mtex ) { @@ -2683,22 +2519,6 @@ static PyObject *Material_copy( BPy_Material * self ) return ( PyObject * ) pymat; } -/* mat.freeNodes() */ -static PyObject *Material_freeNodes( BPy_Material * self ) -{ - if (self->material->nodetree) { - if(self->material->nodetree) { - ntreeFreeTree(self->material->nodetree); - MEM_freeN(self->material->nodetree); - } - self->material->nodetree = NULL; - self->material->use_nodes = 0; - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - /* mat_a==mat_b or mat_a!=mat_b*/ static int Material_compare( BPy_Material * a, BPy_Material * b ) { @@ -3401,75 +3221,3 @@ static PyObject *Material_clearIpo( BPy_Material * self ) return EXPP_incr_ret_False(); /* no ipo found */ } -/* RampCol Factor */ - -static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ) -{ - return PyFloat_FromDouble( (double) self->material->rampfac_col); -} - -static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ) -{ - return PyFloat_FromDouble( (double) self->material->rampfac_spec); -} - -static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ) -{ - return EXPP_setFloatClamped(value, &self->material->rampfac_col, - EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); -} - -static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ) -{ - return EXPP_setFloatClamped(value, &self->material->rampfac_spec, - EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); -} - -/* RampCol Method */ - -static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ) -{ - return PyInt_FromLong( (long) self->material->rampblend_col); -} - -static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ) -{ - return PyInt_FromLong( (long) self->material->rampblend_spec); -} - -static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value) -{ - return EXPP_setIValueClamped(value, &self->material->rampblend_col, - MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); -} - -static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value) -{ - return EXPP_setIValueClamped(value, &self->material->rampblend_spec, - MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); -} - -/* RampCol Input */ - -static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ) -{ - return PyInt_FromLong( (long) self->material->rampin_col); -} - -static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ) -{ - return PyInt_FromLong( (long) self->material->rampin_spec); -} - -static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value) -{ - return EXPP_setIValueClamped(value, &self->material->rampin_col, - MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); -} - -static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value) -{ - return EXPP_setIValueClamped(value, &self->material->rampin_spec, - MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); -} - diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index f0b51285376..217e096060f 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -108,7 +108,7 @@ struct PyMethodDef M_Mathutils_methods[] = { }; /*----------------------------MODULE INIT-------------------------*/ /* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */ -PyObject *Mathutils_Init(const char *from) +PyObject *Mathutils_Init(char *from) { PyObject *submodule; diff --git a/source/blender/python/api2_2x/Mathutils.h b/source/blender/python/api2_2x/Mathutils.h index 0db83216178..76d53cb6c4c 100644 --- a/source/blender/python/api2_2x/Mathutils.h +++ b/source/blender/python/api2_2x/Mathutils.h @@ -38,7 +38,7 @@ #include "euler.h" #include "point.h" -PyObject *Mathutils_Init( const char * from ); +PyObject *Mathutils_Init( char * from ); PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat); diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index 6471fb16e92..b3e8fefdb7b 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -4163,7 +4163,6 @@ static int MFace_setMode( BPy_MFace *self, PyObject *value ) { int param; static short bitmask = TF_DYNAMIC - | TF_ALPHASORT | TF_TEX | TF_SHAREDVERT | TF_LIGHT @@ -8697,11 +8696,11 @@ static PyObject *M_Mesh_FaceModesDict( void ) if( FM ) { BPy_constant *d = ( BPy_constant * ) FM; - PyConstant_Insert( d, "BILLBOARD", PyInt_FromLong( TF_BILLBOARD2 ) ); + PyConstant_Insert( d, "BILLBOARD", + PyInt_FromLong( TF_BILLBOARD2 ) ); PyConstant_Insert( d, "ALL", PyInt_FromLong( 0xffff ) ); PyConstant_Insert( d, "HALO", PyInt_FromLong( TF_BILLBOARD ) ); PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( TF_DYNAMIC ) ); - PyConstant_Insert( d, "ALPHASORT", PyInt_FromLong( TF_ALPHASORT ) ); PyConstant_Insert( d, "INVISIBLE", PyInt_FromLong( TF_INVISIBLE ) ); PyConstant_Insert( d, "LIGHT", PyInt_FromLong( TF_LIGHT ) ); PyConstant_Insert( d, "OBCOL", PyInt_FromLong( TF_OBCOL ) ); diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 45d6bfa3c01..dc70921492c 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -81,7 +81,6 @@ struct rctf; #include "BIF_editarmature.h" #include "BIF_editaction.h" #include "BIF_editnla.h" -#include "BIF_keyframing.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -2735,7 +2734,7 @@ static PyObject *Object_setConstraintInfluenceForBone( BPy_Object * self, "expects bonename, constraintname, influenceval" ); icu = verify_ipocurve((ID *)self->object, ID_CO, boneName, constName, NULL, - CO_ENFORCE, 1); + CO_ENFORCE); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index 893ee077d67..bc65426e16c 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -526,18 +526,15 @@ throws NameError if name not found PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) { -#if 1 - return EXPP_ReturnPyObjError( PyExc_NotImplementedError, - "Particle.Get() not implemented" ); -#else ParticleSettings *psys_iter; char *name = NULL; +#if 0 ParticleSystem *blparticlesys = 0; Object *ob; PyObject *partsyslist,*current; - +#endif if( !PyArg_ParseTuple( args, "|s", &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected string argument" ); @@ -580,6 +577,7 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } while( psys_iter ){ +#if 0 pyobj = ParticleSystem_CreatePyObject( psys_iter); if( !pyobj){ Py_DECREF( pylist ); @@ -588,6 +586,7 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) "could not create ParticleSystem PyObject"); } PyList_SET_ITEM( pylist, index, pyobj); +#endif printf("name is %s\n", psys_iter->id.name+2); psys_iter = psys_iter->id.next; index++; @@ -597,6 +596,10 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } + + +#if 0 + for( ob = G.main->particlesystem.first; ob; ob = ob->id.next ) if( !strcmp( name, ob->id.name + 2 ) ) break; @@ -623,6 +626,7 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } return partsyslist; + #endif } diff --git a/source/blender/python/api2_2x/Pose.c b/source/blender/python/api2_2x/Pose.c index 52ede1cb3ee..1021eac5fc4 100644 --- a/source/blender/python/api2_2x/Pose.c +++ b/source/blender/python/api2_2x/Pose.c @@ -43,7 +43,6 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" //1 - this order #include "BSE_editipo.h" //2 -#include "BIF_keyframing.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "Mathutils.h" diff --git a/source/blender/python/api2_2x/Text.c b/source/blender/python/api2_2x/Text.c index 9719daaa3d4..308ad094c7b 100644 --- a/source/blender/python/api2_2x/Text.c +++ b/source/blender/python/api2_2x/Text.c @@ -34,13 +34,9 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BIF_drawtext.h" -#include "BIF_screen.h" #include "BKE_text.h" -#include "BKE_suggestions.h" #include "BLI_blenlib.h" -#include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "MEM_guardedalloc.h" #include "gen_utils.h" #include "gen_library.h" #include "../BPY_extern.h" @@ -94,20 +90,9 @@ struct PyMethodDef M_Text_methods[] = { static PyObject *Text_getFilename( BPy_Text * self ); static PyObject *Text_getNLines( BPy_Text * self ); static PyObject *Text_clear( BPy_Text * self ); -static PyObject *Text_reset( BPy_Text * self ); -static PyObject *Text_readline( BPy_Text * self ); static PyObject *Text_write( BPy_Text * self, PyObject * value ); -static PyObject *Text_insert( BPy_Text * self, PyObject * value ); -static PyObject *Text_delete( BPy_Text * self, PyObject * value ); static PyObject *Text_set( BPy_Text * self, PyObject * args ); -static PyObject *Text_asLines( BPy_Text * self, PyObject * args ); -static PyObject *Text_getCursorPos( BPy_Text * self ); -static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ); -static PyObject *Text_getSelectPos( BPy_Text * self ); -static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args ); -static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ); -static PyObject *Text_suggest( BPy_Text * self, PyObject * args ); -static PyObject *Text_showDocs( BPy_Text * self, PyObject * args ); +static PyObject *Text_asLines( BPy_Text * self ); /*****************************************************************************/ /* Python BPy_Text methods table: */ @@ -124,34 +109,12 @@ static PyMethodDef BPy_Text_methods[] = { "(str) - Change Text Object name"}, {"clear", ( PyCFunction ) Text_clear, METH_NOARGS, "() - Clear Text buffer"}, - {"reset", ( PyCFunction ) Text_reset, METH_NOARGS, - "() - Moves the IO pointer back to the start of the Text buffer for reading"}, - {"readline", ( PyCFunction ) Text_readline, METH_NOARGS, - "() - Reads a line of text from the buffer and returns it incrementing the internal IO pointer."}, {"write", ( PyCFunction ) Text_write, METH_O, "(line) - Append string 'str' to Text buffer"}, - {"insert", ( PyCFunction ) Text_insert, METH_O, - "(line) - Insert string 'str' to Text buffer at cursor location"}, - {"delete", ( PyCFunction ) Text_delete, METH_O, - "(chars) - Deletes a number of characters to the left (chars<0) or right (chars>0)"}, {"set", ( PyCFunction ) Text_set, METH_VARARGS, "(name, val) - Set attribute 'name' to value 'val'"}, - {"asLines", ( PyCFunction ) Text_asLines, METH_VARARGS, - "(start=0, end=nlines) - Return text buffer as a list of lines between start and end"}, - {"getCursorPos", ( PyCFunction ) Text_getCursorPos, METH_NOARGS, - "() - Return cursor position as (row, col) tuple"}, - {"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS, - "(row, col) - Set the cursor position to (row, col)"}, - {"getSelectPos", ( PyCFunction ) Text_getSelectPos, METH_NOARGS, - "() - Return the selection cursor position as (row, col) tuple"}, - {"setSelectPos", ( PyCFunction ) Text_setSelectPos, METH_VARARGS, - "(row, col) - Set the selection cursor position to (row, col)"}, - {"markSelection", ( PyCFunction ) Text_markSelection, METH_VARARGS, - "(group, (r, g, b), flags) - Places a marker over the current selection. Group: number > 0, flags: TMARK_TEMP, TMARK_EDITALL, etc."}, - {"suggest", ( PyCFunction ) Text_suggest, METH_VARARGS, - "(list, prefix='') - Presents a list of suggestions. List is of strings, or tuples. Tuples must be of the form (name, type) where type is one of 'm', 'v', 'f', 'k' for module, variable, function and keyword respectively or '?' for other types"}, - {"showDocs", ( PyCFunction ) Text_showDocs, METH_VARARGS, - "(docs) - Documentation string"}, + {"asLines", ( PyCFunction ) Text_asLines, METH_NOARGS, + "() - Return text buffer as a list of lines"}, {NULL, NULL, 0, NULL} }; @@ -339,7 +302,7 @@ static PyObject *M_Text_unlink( PyObject * self, PyObject * args ) /*****************************************************************************/ PyObject *Text_Init( void ) { - PyObject *submodule, *dict; + PyObject *submodule; if( PyType_Ready( &Text_Type ) < 0 ) return NULL; @@ -347,19 +310,6 @@ PyObject *Text_Init( void ) submodule = Py_InitModule3( "Blender.Text", M_Text_methods, M_Text_doc ); - dict = PyModule_GetDict( submodule ); - -#define EXPP_ADDCONST(x) \ - EXPP_dict_set_item_str(dict, #x, PyInt_FromLong(x)) - - /* So, for example: - * EXPP_ADDCONST(LEFTMOUSE) becomes - * EXPP_dict_set_item_str(dict, "LEFTMOUSE", PyInt_FromLong(LEFTMOUSE)) - */ - - EXPP_ADDCONST( TMARK_TEMP ); - EXPP_ADDCONST( TMARK_EDITALL ); - return ( submodule ); } @@ -377,8 +327,6 @@ PyObject *Text_CreatePyObject( Text * txt ) "couldn't create BPy_Text PyObject" ); pytxt->text = txt; - pytxt->iol = NULL; - pytxt->ioc = -1; return ( PyObject * ) pytxt; } @@ -428,49 +376,25 @@ static PyObject *Text_clear( BPy_Text * self) Py_RETURN_NONE; } -static PyObject *Text_reset( BPy_Text * self ) +static PyObject *Text_set( BPy_Text * self, PyObject * args ) { - self->iol = NULL; - self->ioc = -1; + int ival; + char *attr; + + if( !PyArg_ParseTuple( args, "si", &attr, &ival ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a string and an int as arguments" ); + + if( strcmp( "follow_cursor", attr ) == 0 ) { + if( ival ) + self->text->flags |= EXPP_TEXT_MODE_FOLLOW; + else + self->text->flags &= EXPP_TEXT_MODE_FOLLOW; + } Py_RETURN_NONE; } -static PyObject *Text_readline( BPy_Text * self ) -{ - PyObject *tmpstr; - - if( !self->text ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object" ); - - /* Reset */ - if (!self->iol && self->ioc == -1) { - self->iol = self->text->lines.first; - self->ioc = 0; - } - - if (!self->iol) { - PyErr_SetString( PyExc_StopIteration, "End of buffer reached" ); - return PyString_FromString( "" ); - } - - if (self->ioc > self->iol->len) { - self->iol = NULL; - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "Line length exceeded, text may have changed while reading" ); - } - - tmpstr = PyString_FromString( self->iol->line + self->ioc ); - if (self->iol->next) - PyString_ConcatAndDel( &tmpstr, PyString_FromString("\n") ); - - self->iol = self->iol->next; - self->ioc = 0; - - return tmpstr; -} - static PyObject *Text_write( BPy_Text * self, PyObject * value ) { char *str = PyString_AsString(value); @@ -489,324 +413,35 @@ static PyObject *Text_write( BPy_Text * self, PyObject * value ) txt_move_eof( self->text, 0 ); txt_set_undostate( oldstate ); - Text_reset( self ); - Py_RETURN_NONE; } -static PyObject *Text_insert( BPy_Text * self, PyObject * value ) -{ - char *str = PyString_AsString(value); - int oldstate; - - if( !self->text ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object" ); - - if( !str ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected string argument" ); - - oldstate = txt_get_undostate( ); - txt_insert_buf( self->text, str ); - txt_set_undostate( oldstate ); - - Text_reset( self ); - - Py_RETURN_NONE; -} - -static PyObject *Text_delete( BPy_Text * self, PyObject * value ) -{ - int num = PyInt_AsLong(value); - int oldstate; - - if( !self->text ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object" ); - - if( !num ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected non-zero int argument" ); - - oldstate = txt_get_undostate( ); - while (num<0) { - txt_backspace_char(self->text); - num++; - } - while (num>0) { - txt_delete_char(self->text); - num--; - } - txt_set_undostate( oldstate ); - - Text_reset( self ); - - Py_RETURN_NONE; -} - -static PyObject *Text_set( BPy_Text * self, PyObject * args ) -{ - int ival; - char *attr; - - if( !PyArg_ParseTuple( args, "si", &attr, &ival ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a string and an int as arguments" ); - - if( strcmp( "follow_cursor", attr ) == 0 ) { - if( ival ) - self->text->flags |= EXPP_TEXT_MODE_FOLLOW; - else - self->text->flags &= EXPP_TEXT_MODE_FOLLOW; - } - - Py_RETURN_NONE; -} - -static PyObject *Text_asLines( BPy_Text * self, PyObject * args ) +static PyObject *Text_asLines( BPy_Text * self ) { TextLine *line; PyObject *list, *tmpstr; - int start=0, end=-1, i; if( !self->text ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); - if( !PyArg_ParseTuple( args, "|ii", &start, &end ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected upto two optional ints as arguments" ); - - if (start<0) - start=0; - line = self->text->lines.first; - for (i = 0; i < start && line->next; i++) - line= line->next; - list = PyList_New( 0 ); if( !list ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyList" ); - while( line && (i < end || end == -1) ) { + while( line ) { tmpstr = PyString_FromString( line->line ); PyList_Append( list, tmpstr ); Py_DECREF(tmpstr); line = line->next; - i++; } return list; } -static PyObject *Text_getCursorPos( BPy_Text * self ) -{ - Text *text; - TextLine *linep; - int row, col; - - text = self->text; - if( !text ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object" ); - - for (row=0,linep=text->lines.first; linep!=text->curl; linep=linep->next) - row++; - col= text->curc; - - return Py_BuildValue( "ii", row, col ); -} - -static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ) -{ - int row, col; - SpaceText *st; - - if (!self->text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object"); - - if (!PyArg_ParseTuple(args, "ii", &row, &col)) - return EXPP_ReturnPyObjError(PyExc_TypeError, - "expected two ints as arguments."); - if (row<0) row=0; - if (col<0) col=0; - - txt_move_to(self->text, row, col, 0); - - if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) - pop_space_text(st); - - Py_RETURN_NONE; -} - -static PyObject *Text_getSelectPos( BPy_Text * self ) -{ - Text *text; - TextLine *linep; - int row, col; - - text = self->text; - if( !text ) - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object" ); - - for (row=0,linep=text->lines.first; linep!=text->sell; linep=linep->next) - row++; - col= text->selc; - - return Py_BuildValue( "ii", row, col ); -} - -static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args ) -{ - int row, col; - SpaceText *st; - - if (!self->text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object"); - - if (!PyArg_ParseTuple(args, "ii", &row, &col)) - return EXPP_ReturnPyObjError(PyExc_TypeError, - "expected two ints as arguments."); - if (row<0) row=0; - if (col<0) col=0; - - txt_move_to(self->text, row, col, 1); - - if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) - pop_space_text(st); - - Py_RETURN_NONE; -} - -static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ) -{ - int group = 0, flags = 0,r, g, b; - Text *text; - char color[4]; - - text = self->text; - if (!text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object"); - - if (!PyArg_ParseTuple(args, "i(iii)i", &group, &r, &g, &b, &flags)) - return EXPP_ReturnPyObjError(PyExc_TypeError, - "expected int, 3-tuple of ints and int as arguments."); - - if (text->curl != text->sell) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "Cannot mark multi-line selection."); - - color[0] = (char) (r&0xFF); - color[1] = (char) (g&0xFF); - color[2] = (char) (b&0xFF); - color[3] = 255; - - group &= 0xFFFF; - - txt_add_marker(text, text->curl, text->curc, text->selc, color, group, flags); - - Py_RETURN_NONE; -} - -static PyObject *Text_suggest( BPy_Text * self, PyObject * args ) -{ - PyObject *item = NULL, *tup1 = NULL, *tup2 = NULL; - PyObject *list = NULL; - int list_len, i; - char *prefix = NULL, *name, type; - SpaceText *st; - - if (!self->text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object"); - - /* Parse args for a list of strings/tuples */ - if (!PyArg_ParseTuple(args, "O!|s", &PyList_Type, &list, &prefix)) - return EXPP_ReturnPyObjError(PyExc_TypeError, - "expected list of strings or tuples followed by an optional string"); - - if (curarea->spacetype != SPACE_TEXT) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "Active space type is not text"); - - st = curarea->spacedata.first; - if (!st || !st->text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "Active text area has no Text object"); - - texttool_suggest_clear(); - texttool_text_set_active(st->text); - list_len = PyList_Size(list); - - for (i = 0; i < list_len; i++) { - item = PyList_GetItem(list, i); - - if (PyString_Check(item)) { - name = PyString_AsString(item); - type = '?'; - } else if (PyTuple_Check(item) && PyTuple_GET_SIZE(item) == 2) { - tup1 = PyTuple_GetItem(item, 0); - tup2 = PyTuple_GetItem(item, 1); - if (PyString_Check(tup1) && PyString_Check(tup2)) { - name = PyString_AsString(tup1); - type = PyString_AsString(tup2)[0]; - } else - return EXPP_ReturnPyObjError(PyExc_AttributeError, - "list must contain tuples of two strings only: (name, type)" ); - } else - return EXPP_ReturnPyObjError(PyExc_AttributeError, - "list must contain only individual strings or tuples of size 2" ); - - if (!strlen(name) || (type!='m' && type!='v' && type!='f' && type!='k' && type!='?')) - return EXPP_ReturnPyObjError(PyExc_AttributeError, - "names must be non-empty and types in ['m', 'v', 'f', 'k', '?']" ); - - texttool_suggest_add(name, type); - } - if (!prefix) - prefix = ""; - texttool_suggest_prefix(prefix); - scrarea_queue_redraw(curarea); - - Py_RETURN_NONE; -} - -static PyObject *Text_showDocs( BPy_Text * self, PyObject * args ) -{ - char *docs; - SpaceText *st; - - if (!self->text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "This object isn't linked to a Blender Text Object"); - - if (!PyArg_ParseTuple(args, "s", &docs)) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a string as argument" ); - - if (curarea->spacetype != SPACE_TEXT) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "Active space type is not text"); - - st = curarea->spacedata.first; - if (!st || !st->text) - return EXPP_ReturnPyObjError(PyExc_RuntimeError, - "Active text area has no Text object"); - - texttool_text_set_active(st->text); - texttool_docs_show(docs); - scrarea_queue_redraw(curarea); - - Py_RETURN_NONE; -} - /*****************************************************************************/ /* Function: Text_compare */ /* Description: This is a callback function for the BPy_Text type. It */ diff --git a/source/blender/python/api2_2x/Text.h b/source/blender/python/api2_2x/Text.h index 73943ddb9cd..0c5e2607f03 100644 --- a/source/blender/python/api2_2x/Text.h +++ b/source/blender/python/api2_2x/Text.h @@ -41,8 +41,6 @@ extern PyTypeObject Text_Type; typedef struct { PyObject_HEAD Text * text; /* libdata must be second */ - TextLine * iol; /* current line being read or NULL if reset */ - int ioc; /* character offset in line being read */ } BPy_Text; PyObject *Text_Init( void ); diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 141b36a05d6..7ba8ad88ea6 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -42,7 +42,6 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" -#include "DNA_world_types.h" #include "MTex.h" #include "Image.h" @@ -1143,11 +1142,6 @@ static PyObject *M_Texture_TexCoDict( void ) PyConstant_Insert(d, "STICK", PyInt_FromLong(TEXCO_STICKY)); PyConstant_Insert(d, "STRESS", PyInt_FromLong(TEXCO_STRESS)); PyConstant_Insert(d, "TANGENT", PyInt_FromLong(TEXCO_TANGENT)); - - /* World TexCo Settings */ - PyConstant_Insert(d, "ANGMAP", PyInt_FromLong(TEXCO_ANGMAP)); - PyConstant_Insert(d, "HSPHERE", PyInt_FromLong(TEXCO_H_SPHEREMAP)); - PyConstant_Insert(d, "HTUBE", PyInt_FromLong(TEXCO_H_TUBEMAP)); } return TexCo; } @@ -1201,7 +1195,6 @@ static PyObject *M_Texture_ExtendModesDict( void ) PyConstant_Insert(d, "CLIP", PyInt_FromLong(TEX_CLIP)); PyConstant_Insert(d, "CLIPCUBE", PyInt_FromLong(TEX_CLIPCUBE)); PyConstant_Insert(d, "REPEAT", PyInt_FromLong(TEX_REPEAT)); - PyConstant_Insert(d, "CHECKER", PyInt_FromLong(TEX_CHECKER)); } return ExtendModes; } diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index 41a4e4e215f..fe789fb4811 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -1249,10 +1249,9 @@ static PyObject *M_Window_TestBreak( PyObject * self ) static PyObject *M_Window_GetMouseCoords( PyObject * self ) { - short mval[2] = {0, 0}; + short mval[2]; - if (!G.background) - getmouse( mval ); + getmouse( mval ); return Py_BuildValue( "hh", mval[0], mval[1] ); } @@ -1284,12 +1283,16 @@ static PyObject *M_Window_SetMouseCoords( PyObject * self, PyObject * args ) static PyObject *M_Window_GetMouseButtons( PyObject * self ) { - return PyInt_FromLong(G.background ? 0 : (int)get_mbut() ); + short mbut = get_mbut( ); + + return Py_BuildValue( "h", mbut ); } static PyObject *M_Window_GetKeyQualifiers( PyObject * self ) { - return PyInt_FromLong( (int)get_qual() ); + short qual = get_qual( ); + + return Py_BuildValue( "h", qual ); } static PyObject *M_Window_SetKeyQualifiers( PyObject * self, PyObject * args ) diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 0c57488a266..6021f8552ad 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -47,17 +47,13 @@ #include "BKE_world.h" #include "BKE_main.h" #include "BKE_library.h" -#include "BKE_texture.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" -#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "Ipo.h" -#include "MTex.h" #include "gen_utils.h" #include "gen_library.h" -#include "MEM_guardedalloc.h" #define IPOKEY_ZENITH 0 #define IPOKEY_HORIZON 1 @@ -103,8 +99,6 @@ static PyObject *World_getScriptLinks( BPy_World * self, PyObject * value ); static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ); static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_setCurrent( BPy_World * self ); -static PyObject *World_getTextures( BPy_World * self ); -static int World_setTextures( BPy_World * self, PyObject * value ); static PyObject *World_copy( BPy_World * self ); @@ -256,9 +250,6 @@ static PyGetSetDef BPy_World_getseters[] = { "world mist settings", NULL}, {"ipo", (getter)World_getIpo, (setter)World_setIpo, "world ipo", NULL}, - {"textures", (getter)World_getTextures, (setter)World_setTextures, - "The World's texture list as a tuple", - NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -1038,97 +1029,3 @@ static PyObject *World_insertIpoKey( BPy_World * self, PyObject * args ) Py_RETURN_NONE; } - -static PyObject *World_getTextures( BPy_World * self ) -{ - int i; - PyObject *tuple; - - /* build a texture list */ - tuple = PyTuple_New( MAX_MTEX ); - if( !tuple ) - return EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create PyTuple" ); - - for( i = 0; i < MAX_MTEX; ++i ) { - struct MTex *mtex = self->world->mtex[i]; - if( mtex ) { - PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_WO ) ); - } else { - Py_INCREF( Py_None ); - PyTuple_SET_ITEM( tuple, i, Py_None ); - } - } - - return tuple; -} - -static int World_setTextures( BPy_World * self, PyObject * value ) -{ - int i; - - if( !PyList_Check( value ) && !PyTuple_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list of integers" ); - - /* don't allow more than MAX_MTEX items */ - if( PySequence_Size(value) > MAX_MTEX ) - return EXPP_ReturnIntError( PyExc_AttributeError, - "size of sequence greater than number of allowed textures" ); - - /* get a fast sequence; in Python 2.5, this just return the original - * list or tuple and INCREFs it, so we must DECREF */ - value = PySequence_Fast( value, "" ); - - /* check the list for valid entries */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - if( item == Py_None || ( BPy_MTex_Check( item ) && - ((BPy_MTex *)item)->type == ID_WO ) ) { - continue; - } else { - Py_DECREF(value); - return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list containing world MTex objects and NONE" ); - } - } - - /* for each MTex object, copy to this structure */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - struct MTex *mtex = self->world->mtex[i]; - if( item != Py_None ) { - BPy_MTex *obj = (BPy_MTex *)item; - - /* if MTex is already at this location, just skip it */ - if( obj->mtex == mtex ) continue; - - /* create a new entry if needed, otherwise update reference count - * for texture that is being replaced */ - if( !mtex ) - mtex = self->world->mtex[i] = add_mtex( ); - else - mtex->tex->id.us--; - - /* copy the data */ - mtex->tex = obj->mtex->tex; - id_us_plus( &mtex->tex->id ); - mtex->texco = obj->mtex->texco; - mtex->mapto = obj->mtex->mapto; - } - } - - /* now go back and free any entries now marked as None */ - for( i= 0; i < PySequence_Size(value) ; ++i ) { - PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - struct MTex *mtex = self->world->mtex[i]; - if( item == Py_None && mtex ) { - mtex->tex->id.us--; - MEM_freeN( mtex ); - self->world->mtex[i] = NULL; - } - } - - Py_DECREF(value); - return 0; -} diff --git a/source/blender/python/api2_2x/bpy_data.c b/source/blender/python/api2_2x/bpy_data.c index 47232c6707a..4705c1bdd03 100644 --- a/source/blender/python/api2_2x/bpy_data.c +++ b/source/blender/python/api2_2x/bpy_data.c @@ -263,12 +263,9 @@ PyObject *LibBlockSeq_getActive(BPy_LibBlockSeq *self) } break; case ID_TXT: { - SpaceText *st = NULL; + SpaceText *st= curarea->spacedata.first; - if (curarea) - st = curarea->spacedata.first; - - if (st==NULL || st->spacetype!=SPACE_TEXT || st->text==NULL) { + if (st->spacetype!=SPACE_TEXT || st->text==NULL) { Py_RETURN_NONE; } else { return Text_CreatePyObject( st->text ); @@ -333,15 +330,9 @@ static int LibBlockSeq_setActive(BPy_LibBlockSeq *self, PyObject *value) return EXPP_ReturnIntError(PyExc_TypeError, "Must be a text" ); } else { - SpaceText *st= NULL; + SpaceText *st= curarea->spacedata.first; Text *data = ((BPy_Text *)value)->text; - if (curarea==NULL) { - return 0; - } else { - st= curarea->spacedata.first; - } - if( !data ) return EXPP_ReturnIntError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); diff --git a/source/blender/python/api2_2x/doc/Draw.py b/source/blender/python/api2_2x/doc/Draw.py index 97e22797902..18234754315 100644 --- a/source/blender/python/api2_2x/doc/Draw.py +++ b/source/blender/python/api2_2x/doc/Draw.py @@ -357,14 +357,12 @@ def PupTreeMenu( menu ): """ Create a popup menu tree. - Each item in the list is: a menu item - (str, event); a separator - None; - or submenu - (str, [...]). + Each item in the list is a menu item - (str, event), separator - None or submenu - (str, [...]). - Submenus list uses the same syntax as the menu list. To add a title to the - main menu, end the first entry str with '%t' - the event is ignored. + Submenus list uses the same syntax as the menu list. Example:: - result = Draw.PupTreeMenu( [ ("Title%t", 0), ("Menu Item 1", 10), ("Menu Item 2", 12), ("SubMenu", [("Menu Item 3", 100), ("MenuItem4", 101) ] ) ] ) + result = Draw.PupTreeMenu( [ ("Menu Item 1", 10), ("Menu Item 2", 12), ("SubMenu", [("Menu Item 3", 100), ("MenuItem4", 101) ] ) ] ) @type menu: string @param menu: A menu list diff --git a/source/blender/python/api2_2x/doc/Group.py b/source/blender/python/api2_2x/doc/Group.py index 1266d2efb6e..6bd6e105ec3 100644 --- a/source/blender/python/api2_2x/doc/Group.py +++ b/source/blender/python/api2_2x/doc/Group.py @@ -105,8 +105,6 @@ class Group: This object gives access to Groups in Blender. @ivar layers: Layer bitmask for this group. @type layers: int - @ivar dupliOffset: Object offset when instanced as a dupligroup - @type dupliOffset: vector @ivar objects: Objects that this group uses. This is a sequence with-list like access so use list(grp.objects) if you need to use a list (where grp is a group). The groups objects can be set by assigning a list or iterator of objects to the groups objects. diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index 162d94ccff3..a7a1fb94620 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -161,8 +161,6 @@ class Lamp: @type type: int @ivar falloffType: Lamp falloff type. See L{Falloffs} for values. @type falloffType: int - @type textures: a tuple of Blender MTex objects. - @ivar textures: The Lamp's texture list. Empty texture channels contains None. @warning: Most member variables assume values in some [Min, Max] interval. When trying to set them, the given parameter will be clamped to lie in diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index fa6a9f7047a..02f7edd77f5 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -80,35 +80,6 @@ Example:: - SPEC_BLINN - Make Material use the Blinn specular shader. - SPEC_TOON - Make Material use the toon specular shader. - SPEC_WARDISO - Make Material use the Ward-iso specular shader. - -@type ColorbandMethod: readonly dictionary -@var ColorbandMethod: The available Colorband mixing methods. - - ADD - Make Material use the Add method. - - BLEND - Make Material use the Blend/Mix method. - - BURN - Make Material use the Burn method. - - COLOR - Make Material use the Color method. - - DARK - Make Material use the Darken method. - - DIFF - Make Material use the Difference method. - - DIV - Make Material use the Divide method. - - DODGE - Make Material use the Dodge method. - - HUE - Make Material use the Hue method. - - LIGHT - Make Material use the Lighten method. - - MIX - Make Material use the Blend/Mix method. - - MULT - Make Material use the Multiply method. - - OVERLAY - Make Material use the Overlay method. - - SAT - Make Material use the Saturation method. - - SCREEN - Make Material use the Screen method. - - SUB - Make Material use the Substract method. - - VAL - Make Material use the Value method. - -@type ColorbandInput: readonly dictionary -@var ColorbandInput: The available Colorband Input sources. - - ENERGY - Make Material use the Energy input. - - NORMAL - Make Material use the Normal input. - - RESULT - Make Material use the Result input. - - SHADER - Make Material use the Shader input. - - """ def New (name = 'Mat'): @@ -352,28 +323,6 @@ class Material: each color a list of 5 floats [0 - 1], [r,g,b,a,pos]. The colorband can have between 1 and 31 colors. @type colorbandSpecular: list - @ivar colorbandDiffuseInput: Material Diffuse colorband input. - The integer result must be compared with L{ColorbandInput} - dictionary. - @type colorbandDiffuseInput: int - @ivar colorbandDiffuseMethod: Material Diffuse colorband method. - The integer result must be compared with L{ColorbandMethod} - dictionary. - @type colorbandDiffuseMethod: int - @ivar colorbandDiffuseFactor: Material Diffuse colorband factor. - Value is clamped to the range [0.0,1.0]. - @type colorbandDiffuseFactor: float - @ivar colorbandSpecularInput: Material Specular colorband input. - The integer result must be compared with L{ColorbandInput} - dictionary. - @type colorbandSpecularInput: int - @ivar colorbandSpecularMethod: Material Specular colorband method. - The integer result must be compared with L{ColorbandMethod} - dictionary. - @type colorbandSpecularMethod: int - @ivar colorbandSpecularFactor: Material Specular colorband factor. - Value is clamped to the range [0.0,1.0]. - @type colorbandSpecularFactor: float @type enabledTextures: list of integers @ivar enabledTextures: The texture channels enabled in this material. The attribute returns is list of integers in the range [0, 9], each @@ -389,9 +338,7 @@ class Material: ch.append(4) mat.enabledTextures = ch print mat.enabledTextures # will print: [0, 4, 6] - - @type textures: a tuple of Blender MTex objects. - @ivar textures: the Material's Texture list. Empty texture channels contains None. + @ivar enableSSS: If True, subsurface scattering will be rendered on this material. @type enableSSS: bool @ivar sssScale: If True, subsurface scattering will be rendered on this material. @@ -1138,12 +1085,5 @@ class Material: @return: a copy of this material """ - def freeNodes (): - """ - Removes the node tree from this material. - @rtype: bool - @return: true if nodes were freed from this material. - """ - import id_generics Material.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index e48f41e8f9c..4a53f869283 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -69,7 +69,6 @@ done once. - BILLBOARD - always orient after camera. - HALO - halo face, always point to camera. - DYNAMIC - respond to collisions. - - ALPHASORT - game engine sorts these faces only. - INVISIBLE - invisible face. - LIGHT - dynamic lighting. - OBCOL - use object color instead of vertex colors. @@ -636,7 +635,7 @@ class MFaceSeq: This object provides sequence and iterator access to the mesh's faces. """ - def extend(vertseq,ignoreDups=True,indexList=True,smooth=False): + def extend(vertseq,ignoreDups=True,indexList=True): """ Add zero or more faces and edges to the mesh. Faces which already exist in the mesh, or faces which contain the same vertex multiple times are diff --git a/source/blender/python/api2_2x/doc/Text.py b/source/blender/python/api2_2x/doc/Text.py index 022205573aa..98ecb664b71 100644 --- a/source/blender/python/api2_2x/doc/Text.py +++ b/source/blender/python/api2_2x/doc/Text.py @@ -100,19 +100,6 @@ class Text: Clear this Text object: its buffer becomes empty. """ - def reset(): - """ - Reset the read IO pointer to the start of the buffer. - """ - - def readline(): - """ - Reads a line of text from the buffer from the current IO pointer - position to the end of the line. If the text has changed since the last - read, reset() *must* be called. - @rtype: string - """ - def set(attribute, value): """ Set this Text's attributes. @@ -131,94 +118,12 @@ class Text: @param data: The string to append to the text buffer. """ - def insert(data): + def asLines(): """ - Inserts a string into this Text buffer at the cursor. - @type data: string - @param data: The string to insert into the text buffer. - """ - - def asLines(start=0, end=-1): - """ - Retrieve the contents of this Text buffer as a list of strings between - the start and end lines specified. If end < 0 all lines from start will - be included. - @type start int - @param start: Optional index of first line of the span to return - @type end int - @param end: Optional index of the line to which the span is taken or - -1 to include all lines from start + Retrieve the contents of this Text buffer as a list of strings. @rtype: list of strings - @return: A list of strings, one for each line in the buffer between - start and end. - """ - - def getCursorPos(): - """ - Retrieve the position of the cursor in this Text buffer. - @rtype: (int, int) - @return: A pair (row, col) indexing the line and character of the - cursor. - """ - - def setCursorPos(row, col): - """ - Set the position of the cursor in this Text buffer. Any selection will - be cleared. Use setSelectPos to extend a selection from the point - specified here. - @type row: int - @param row: The index of the line in which to position the cursor. - @type col: int - @param col: The index of the character within the line to position the - cursor. - """ - - def getSelectPos(): - """ - Retrieve the position of the selection cursor in this Text buffer. - @rtype: (int, int) - @return: A pair (row, col) indexing the line and character of the - selection cursor. - """ - - def setSelectPos(row, col): - """ - Set the position of the selection cursor in this Text buffer. This - method should be called after setCursorPos to extend the selection to - the specified point. - @type row: int - @param row: The index of the line in which to position the cursor. - @type col: int - @param col: The index of the character within the line to position the - cursor. - """ - - def suggest(list, prefix=''): - """ - Suggest a list of names. If list is a list of tuples (name, type) the - list will be formatted to syntax-highlight each entry type. Types must - be strings in the list ['m', 'f', 'v', 'k', '?']. It is recommended that - the list be sorted, case-insensitively by name. - - @type list: list of tuples or strings - @param list: List of pair-tuples of the form (name, type) where name is - the suggested name and type is one of 'm' (module or class), 'f' - (function or method), 'v' (variable), 'k' (keyword), '?' (other). - Lists of plain strings are also accepted where the type is always - '?'. - @type prefix: string - @param prefix: The optional prefix used to limit what is suggested from - the list. This is usually whatever precedes the cursor so that - backspace will update it. - """ - - def showDocs(docs): - """ - Displays a word-wrapped message box containing the specified - documentation when this Text object is visible. - @type docs: string - @param docs: The documentation string to display. + @return: A list of strings, one for each line in the buffer """ import id_generics -Text.__doc__ += id_generics.attributes +Text.__doc__ += id_generics.attributes \ No newline at end of file diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index b5b82b1a519..cebb7de7011 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -195,23 +195,20 @@ Example:: - DN_CELLNOISE - Steven Worley's cellular basis algorithm (1996) @var TexCo: Flags for MTex.texco. - - ORCO - Use the original coordinates of the mesh (material texture only) - - REFL - Use reflection vector as texture coordinates (material texture only) - - NOR - Use normal vector as texture coordinates (material texture only) + - ORCO - Use the original coordinates of the mesh + - REFL - Use reflection vector as texture coordinates + - NOR - Use normal vector as texture coordinates - GLOB - Use global coordinates for the texture coordinates - - UV - Use UV coordinates for texture coordinates (material texture only) + - UV - Use UV coordinates for texture coordinates - OBJECT - Use linked object's coordinates for texture coordinates - - WIN - Use screen coordinates as texture coordinates (material texture only) - - VIEW - Use view coordinates for the texture (world and lamp texture only) - - STICK - Use mesh sticky coordinates for the texture coordinates (material texture only) - - STRESS - Use mesh stress coordinates for the texture coordinates (material texture only) - - TANGENT - Use mesh tangent coordinates for the texture coordinates (material texture only) - - ANGMAP - Uses 360 degree angular coordinates, e.g. for spherical light probes (world texture only) - - HSPHERE - For 360 degree panorama sky, spherical mapped, only top half (world texture only) - - HTUBE - For 360 degree panorama sky, cylindrical mapped, only top half (world texture only) + - WIN - Use screen coordinates as texture coordinates + - VIEW - Pass camera view vector on to the texture (World texture only!) + - STICK - Use mesh sticky coordinates for the texture coordinates + - STRESS - Use mesh stress coordinates for the texture coordinates + - TANGENT - Use mesh tangent coordinates for the texture coordinates @type TexCo: readonly dictionary -@var MapTo: Flags for MTex.mapto +@var MapTo: Flags for MTex.mapto. - COL - Make the texture affect the basic color of the material - NOR - Make the texture affect the rendered normal - CSP - Make the texture affect the specularity color @@ -503,92 +500,48 @@ class MTex: This object links a material to a texture. It allows the same texture to be used in several different ways. - @ivar blendmode: Texture blending mode. See L{BlendModes} - @type blendmode: int - @ivar col: Color that the texture blends with. - @type col: tuple - @ivar colfac: Factor by which texture affects color. - @type colfac: float - @ivar correctNor: Correct normal mapping for Texture space and Object space (material only). - @type correctNor: boolean - @ivar dispfac: Factor by which texture affects displacement (material only). - @type dispfac: float - @ivar dvar: Value that the texture blends with when not blending colors. - @type dvar: float - @ivar fromDupli: Duplis instanced from verts, faces or particles, inherit texture coordinate from their parent (material only). - @type fromDupli: boolean - @ivar fromOrig: Duplis derive their object coordinates from the original objects transformation (material only). - @type fromOrig: boolean - @ivar mapping: Mapping of texture coordinates (flat, cube, etc.) (material only). See L{Mappings}. - @type mapping: int - @ivar mapto: "Map to" field of texture (material only). OR'd values of L{MapTo}. - @type mapto: int - @ivar mtCol: How texture maps to color (material and lamp only). - @type mtCol: int - @ivar mtAlpha: How texture maps to alpha value (material only). - @type mtAlpha: int - @ivar mtAmb: How texture maps to ambient value (material only). - @type mtAmb: int - @ivar mtCmir: How texture maps to mirror color (material only). - @type mtCmir: int - @ivar mtCsp: How texture maps to specularity color (material only). - @type mtCsp: int - @ivar mtDisp: How texture maps to displacement (material only). - @type mtDisp: int - @ivar mtEmit: How texture maps to emit value (material only). - @type mtEmit: int - @ivar mtHard: How texture maps to hardness (material only). - @type mtHard: int - @ivar mtNor: How texture maps to normals (material only). - @type mtNor: int - @ivar mtRayMir: How texture maps to RayMir value (material only). - @type mtRayMir: int - @ivar mtRef: How texture maps to reflectivity (material only). - @type mtRef: int - @ivar mtSpec: How texture maps to specularity (material only). - @type mtSpec: int - @ivar mtTranslu: How texture maps to translucency (material only). - @type mtTranslu: int - @ivar mtWarp: How texture maps to warp (material only). - @type mtWarp: int - @ivar mtBlend: Texture affects color progression of background (world only). - @type mtBlend: int - @ivar mtHoriz: Texture affects color of the horizon (world only). - @type mtHoriz: int - @ivar mtZenUp: Texture affects color of the zenith above (world only). - @type mtZenUp: int - @ivar mtZenDown: Texture affects color of the zenith below (world only). - @type mtZenDown: int - @ivar neg: Negate texture values mode. - @type neg: boolean - @ivar norfac: Factor by which texture affects normal (material and world only). - @type norfac: float - @ivar noRGB: Convert texture RGB values to intensity values. - @type noRGB: boolean - @ivar object: Object whose space to use when texco is Object. - @type object: Blender Object or None - @ivar ofs: Offset to adjust texture space. - @type ofs: tuple - @ivar size: Size to scale texture space. - @type size: tuple - @ivar stencil: Stencil mode. - @type stencil: boolean - @ivar tex: The Texture this is linked to. - @type tex: Blender Texture - @ivar texco: Texture coordinates ("Map input"). See L{TexCo}. - @type texco: int - @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) (material only). - @type uvlayer: string - @ivar varfac: Factor by which texture affects most variables (material and world only). - @type varfac: float - @ivar warpfac: Factor by which texture affects warp (material only). - @type warpfac: float - @ivar xproj: Projection of X axis to Texture space (material only). See L{Proj} - @type xproj: int - @ivar yproj: Projection of Y axis to Texture space (material only). See L{Proj} - @type yproj: int - @ivar zproj: Projection of Z axis to Texture space (material only). See L{Proj} - @type zproj: int + @ivar tex: The Texture this is linked to. + @type tex: Blender Texture + @ivar texco: Texture coordinates ("Map input"). See L{TexCo} + @ivar mapto: "Map to" field of texture. OR'd values of L{MapTo} + @ivar object: Object whose space to use when texco is Object + @type object: Blender Object + @ivar col: Color that the texture blends with + @ivar dvar: Value that the texture blends with when not blending colors + @ivar blendmode: Texture blending mode. L{BlendModes} + @ivar colfac: Factor by which texture affects color + @ivar norfac: Factor by which texture affects normal + @ivar varfac: Factor by which texture affects most variables + @ivar dispfac: Factor by which texture affects displacement + @ivar warpfac: Factor by which texture affects warp + @ivar ofs: Offset to adjust texture space + @ivar size: Size to scale texture space + @ivar mapping: Mapping of texture coordinates (flat, cube, etc.). L{Mappings} + @ivar stencil: Stencil mode + @ivar neg: Negate texture values mode + @ivar noRGB: Convert texture RGB values to intensity values + @ivar correctNor: Correct normal mapping for Texture space and Object space + @ivar fromDupli: Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent + @ivar fromOrig: Dupli's derive their object coordinates from the original objects transformation + @ivar xproj: Projection of X axis to Texture space. L{Proj} + @ivar yproj: Projection of Y axis to Texture space. L{Proj} + @ivar zproj: Projection of Z axis to Texture space. L{Proj} + @ivar mtCol: How texture maps to color + @ivar mtNor: How texture maps to normals + @ivar mtCsp: How texture maps to specularity color + @ivar mtCmir: How texture maps to mirror color + @ivar mtRef: How texture maps to reflectivity + @ivar mtSpec: How texture maps to specularity + @ivar mtEmit: How texture maps to emit value + @ivar mtAlpha: How texture maps to alpha value + @ivar mtHard: How texture maps to hardness + @ivar mtRayMir: How texture maps to RayMir value + @ivar mtTranslu: How texture maps to translucency + @ivar mtAmb: How texture maps to ambient value + @ivar mtDisp: How texture maps to displacement + @ivar mtWarp: How texture maps to warp + @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) + @type uvlayer: string """ def getIpo(): diff --git a/source/blender/python/api2_2x/doc/World.py b/source/blender/python/api2_2x/doc/World.py index d8052c609cd..d9e9bae750d 100644 --- a/source/blender/python/api2_2x/doc/World.py +++ b/source/blender/python/api2_2x/doc/World.py @@ -82,8 +82,6 @@ class World: @ivar mist: the mist parameters of a world object. See getMist for the semantics of these parameters. @type ipo: Blender Ipo @ivar ipo: The world type ipo linked to this world object. - @type textures: a tuple of Blender MTex objects. - @ivar textures: The World's texture list. Empty texture channels contains None. """ def getRange(): diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h index f33dc69d703..1f2fd55cf1b 100644 --- a/source/blender/python/api2_2x/gen_utils.h +++ b/source/blender/python/api2_2x/gen_utils.h @@ -45,7 +45,6 @@ Py_RETURN_NONE Python 2.4 macro. defined here until we switch to 2.4 - also in PyObjectPlus.h for gameengine */ #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_BuildValue("O", Py_None) diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index ddc4eb6aea8..0d3ad3fcb44 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -33,14 +33,12 @@ #include "DNA_scene_types.h" /* for Base */ #include "BKE_mesh.h" -#include "BKE_image.h" // RFS: openanim #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_scene.h" #include "BIF_editseq.h" /* get_last_seq */ -#include "BIF_editsound.h" // RFS: sound_open_hdaudio #include "BLI_blenlib.h" #include "BSE_sequence.h" #include "Ipo.h" @@ -50,9 +48,6 @@ #include "Sound.h" #include "gen_utils.h" -#include "IMB_imbuf_types.h" // RFS: IB_rect -#include "IMB_imbuf.h" // RFS: IMB_anim_get_duration - enum seq_consts { EXPP_SEQ_ATTR_TYPE = 0, EXPP_SEQ_ATTR_CHAN, @@ -150,6 +145,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) seq->len = PyList_Size( list ); + /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= seq->len; @@ -189,103 +185,12 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->us= 1; strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); - } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 4) { - // MOVIE or AUDIO_HD - char *filename; - char *dir; - char *fullpath; - char *type; - int totframe; - - if (!PyArg_ParseTuple( py_data, "ssss", &filename, &dir, &fullpath, &type )) { - BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "movie/audio hd data needs to be a tuple of a string and a list of images - (filename, dir, fullpath, type)" ); - } - - // RFS - Attempting to support Movie and Audio (HD) strips -#define RFS -#ifdef RFS - // Movie strips - if( strcmp( type, "movie" ) == 0 ) - { - /* open it as an animation */ - struct anim * an = openanim(fullpath, IB_rect); - if(an==0) { - BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - "invalid movie strip" ); - } - - /* get the length in frames */ - totframe = IMB_anim_get_duration( an ); - - /* set up sequence */ - seq->type= SEQ_MOVIE; - seq->len= totframe; - seq->anim= an; - seq->anim_preseek = IMB_anim_get_preseek(an); - - calc_sequence(seq); - - /* strip and stripdata */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= totframe; - strip->us= 1; - strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? - strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); - - /* name movie in first strip */ - strncpy(se->name, filename, FILE_MAXFILE-1); // ???? - } - - // Audio (HD) strips - if( strcmp( type, "audio_hd" ) == 0 ) - { - struct hdaudio *hdaudio; - - totframe= 0; - - /* is it a sound file? */ - hdaudio = sound_open_hdaudio( fullpath ); - if(hdaudio==0) { - BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_ValueError, - fullpath ); - } - - totframe= sound_hdaudio_get_duration(hdaudio, FPS); - - /* set up sequence */ - seq->type= SEQ_HD_SOUND; - seq->len= totframe; - seq->hdaudio= hdaudio; - - calc_sequence(seq); - - /* strip and stripdata - same as for MOVIE */ - seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); - strip->len= totframe; - strip->us= 1; - strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? - strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); - - /* name movie in first strip */ - strncpy(se->name, filename, FILE_MAXFILE-1); // ???? - } -#endif - } else if (BPy_Sound_Check(py_data)) { - /* RAM sound */ + /* sound */ int totframe; bSound *sound = (( BPy_Sound * )py_data)->sound; + seq->type= SEQ_RAM_SOUND; seq->sound = sound; @@ -293,6 +198,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) sound->flags |= SOUND_FLAGS_SEQUENCE; + /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= totframe; @@ -319,7 +225,18 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->len= seq->len; strip->us= 1; } else { - // RFS: REMOVED MOVIE FROM HERE + /* movie, pydata is a path to a movie file */ + char *name = PyString_AsString ( py_data ); + if (!name) { + /* only free these 2 because other stuff isnt set */ + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expects a string for chan/bone name and an int for the frame where to put the new key" ); + } + + seq->type= SEQ_MOVIE; } strncpy(seq->name+2, "Untitled", 21); intern_pos_update(seq); diff --git a/source/blender/radiosity/CMakeLists.txt b/source/blender/radiosity/CMakeLists.txt index 502acf1e211..941da41a5b2 100644 --- a/source/blender/radiosity/CMakeLists.txt +++ b/source/blender/radiosity/CMakeLists.txt @@ -29,7 +29,7 @@ FILE(GLOB SRC intern/source/*.c) SET(INC extern/include ../blenlib ../blenkernel ../makesdna ../include ../../../intern/guardedalloc ../render/extern/include - ../render/intern/include ../blenloader ../../../extern/glew/include + ../render/intern/include ../blenloader ) BLENDERLIB_NOLIST(blender_radiosity "${SRC}" "${INC}") diff --git a/source/blender/radiosity/SConscript b/source/blender/radiosity/SConscript index 82d84f5ef16..a86b76bb4b1 100644 --- a/source/blender/radiosity/SConscript +++ b/source/blender/radiosity/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('intern/source/*.c') incs = 'extern/include ../blenlib ../blenkernel ../makesdna ../include' incs += ' #/intern/guardedalloc ../render/extern/include' -incs += ' ../render/intern/include ../blenloader #/extern/glew/include' +incs += ' ../render/intern/include ../blenloader' incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile index 5912cdba590..e5ff8c40d08 100644 --- a/source/blender/radiosity/intern/source/Makefile +++ b/source/blender/radiosity/intern/source/Makefile @@ -36,7 +36,6 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) -CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) # not very neat.... diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c index ec71611b31d..6e5bf149c7a 100644 --- a/source/blender/readblenfile/intern/BLO_readblenfile.c +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -159,7 +159,7 @@ blo_read_runtime( } else { //printf("starting to read runtime from %s at datastart %d\n", path, datastart); lseek(fd, datastart, SEEK_SET); - bfd = blo_read_blendafterruntime(fd, path, actualsize-datastart, error_r); + bfd = blo_read_blendafterruntime(fd, actualsize-datastart, error_r); fd= -1; // file was closed in blo_read_blendafterruntime() } diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 7e2194549cc..f83bbd7e8b2 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -418,8 +418,7 @@ typedef struct LampRen { float xs, ys, dist; float co[3]; - short type; - int mode; + short type, mode; float r, g, b, k; float energy, haint; int lay; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 322d2066a6c..e4a5ad67631 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1565,7 +1565,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; int i, a, k, max_k=0, totpart, totuv=0, totcol=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0; - int path_possible=0, keys_possible=0, baked_keys=0, totchild=0; + int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num; int totface, *origindex = 0; char **uv_name=0; @@ -1573,8 +1573,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem /* 1. check that everything is ok & updated */ if(psys==NULL) return 0; - - totchild=psys->totchild; part=psys->part; pars=psys->particles; @@ -1766,7 +1764,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem psys->lattice=psys_get_lattice(ob,psys); /* 3. start creating renderable things */ - for(a=0,pa=pars; amode & MA_HALO)) + if(totmaterial && material) { + for(a= 0; a<*totmaterial; a++) + if((*material)[a] && (*material)[a]->mode & MA_HALO) return 0; - } } for(psys=obd->particlesystem.first; psys; psys=psys->next) diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index b9a2acb8b1c..c2d27f8f3a7 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -577,10 +577,10 @@ static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float max if(texres->talpha==0) texres->ta= 1.0; if(alphaclip!=1.0) { - /* premul it all */ - texres->tr*= alphaclip; - texres->tg*= alphaclip; - texres->tb*= alphaclip; + /* this is for later investigation, premul or not? */ + /* texres->tr*= alphaclip; */ + /* texres->tg*= alphaclip; */ + /* texres->tb*= alphaclip; */ texres->ta*= alphaclip; } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index bf2a72b4f9b..3cd7bdc6772 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -138,7 +138,7 @@ static void print_error(char *str) {printf("ERROR: %s\n", str);} static void stats_background(RenderStats *rs) { - uintptr_t mem_in_use= MEM_get_memory_in_use(); + extern uintptr_t mem_in_use; float megs_used_memory= mem_in_use/(1024.0*1024.0); char str[400], *spos= str; @@ -1889,7 +1889,6 @@ static void do_render_fields_blur_3d(Render *re) re->result->tilerect= re->disprect; /* this copying sequence could become function? */ - /* weak is: it chances disprect from border */ re->disprect.xmin= re->disprect.ymin= 0; re->disprect.xmax= re->winx; re->disprect.ymax= re->winy; @@ -2347,12 +2346,6 @@ static int is_rendering_allowed(Render *re) if(re->osa==0) re->r.scemode &= ~R_FULL_SAMPLE; - /* no fullsample and edge */ - if((re->r.scemode & R_FULL_SAMPLE) && (re->r.mode & R_EDGE)) { - re->error("Full Sample doesn't support Edge Enhance"); - return 0; - } - } else re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ @@ -2414,7 +2407,7 @@ static int is_rendering_allowed(Render *re) } /* evaluating scene options for general Blender render */ -static int render_initialize_from_scene(Render *re, Scene *scene, int anim) +static int render_initialize_from_scene(Render *re, Scene *scene) { int winx, winy; rcti disprect; @@ -2442,12 +2435,6 @@ static int render_initialize_from_scene(Render *re, Scene *scene, int anim) re->scene= scene; - /* not too nice, but it survives anim-border render */ - if(anim) { - re->disprect= disprect; - return 1; - } - /* check all scenes involved */ tag_scenes_for_render(re); @@ -2479,7 +2466,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) scene->r.cfra= frame; - if(render_initialize_from_scene(re, scene, 0)) { + if(render_initialize_from_scene(re, scene)) { do_render_all_options(re); } @@ -2564,8 +2551,8 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype); int cfrao= scene->r.cfra; - /* do not fully call for each frame, it initializes & pops output window */ - if(!render_initialize_from_scene(re, scene, 0)) + /* do not call for each frame, it initializes & pops output window */ + if(!render_initialize_from_scene(re, scene)) return; /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ @@ -2593,10 +2580,6 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) } else { for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) { char name[FILE_MAX]; - - /* only border now, todo: camera lens. (ton) */ - render_initialize_from_scene(re, scene, 1); - if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 0fd9365477c..c352a83d0f4 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -2056,10 +2056,7 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; - if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) - isec.lay= lar->lay; - else - isec.lay= -1; + if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; /* only when not mir tracing, first hit optimm */ if(shi->depth==0) { diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index bda02bea8d7..4a2ad995b39 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -158,7 +158,7 @@ static int calchalo_z(HaloRen *har, int zz) { if(har->type & HA_ONLYSKY) { - if(zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */ + if(zz!=0x7FFFFFFF) zz= - 0x7FFFFF; } else { zz= (zz>>8); @@ -931,23 +931,17 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) } } -static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl) + +static void convert_to_key_alpha(RenderPart *pa, float *rectf) { - RenderLayer *rlpp[RE_MAX_OSA]; - int y, sample, totsample; + int y; - totsample= get_sample_layers(pa, rl, rlpp); - - for(sample= 0; samplerectf; - - for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { - if(rectf[3] >= 1.0f); - else if(rectf[3] > 0.0f) { - rectf[0] /= rectf[3]; - rectf[1] /= rectf[3]; - rectf[2] /= rectf[3]; - } + for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { + if(rectf[3] >= 1.0f); + else if(rectf[3] > 0.0f) { + rectf[0] /= rectf[3]; + rectf[1] /= rectf[3]; + rectf[2] /= rectf[3]; } } } @@ -1235,7 +1229,7 @@ void zbufshadeDA_tile(RenderPart *pa) /* de-premul alpha */ if(R.r.alphamode & R_ALPHAKEY) - convert_to_key_alpha(pa, rl); + convert_to_key_alpha(pa, rl->rectf); /* free stuff within loop! */ MEM_freeN(pa->rectdaps); pa->rectdaps= NULL; @@ -1399,7 +1393,7 @@ void zbufshade_tile(RenderPart *pa) /* de-premul alpha */ if(R.r.alphamode & R_ALPHAKEY) - convert_to_key_alpha(pa, rl); + convert_to_key_alpha(pa, rl->rectf); if(edgerect) MEM_freeN(edgerect); edgerect= NULL; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index d44b49cc706..98b1426e8ff 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -483,16 +483,16 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) DerivedMesh which stores the layers is freed */ CustomDataLayer *layer; - int numtf = 0, numcol = 0, i, mtfn, mcn; + int numlayers, i, mtfn, mcn; if (CustomData_has_layer(data, CD_MTFACE)) { - numtf= CustomData_number_of_layers(data, CD_MTFACE); - obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames"); + numlayers= CustomData_number_of_layers(data, CD_MTFACE); + obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numlayers, "mtfacenames"); } if (CustomData_has_layer(data, CD_MCOL)) { - numcol= CustomData_number_of_layers(data, CD_MCOL); - obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames"); + numlayers= CustomData_number_of_layers(data, CD_MCOL); + obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numlayers, "mcolnames"); } for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { @@ -500,12 +500,12 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) if (layer->type == CD_MTFACE) { strcpy(obr->mtface[mtfn++], layer->name); - obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf); + obr->actmtface= layer->active_rnd; obr->bakemtface= layer->active; } else if (layer->type == CD_MCOL) { strcpy(obr->mcol[mcn++], layer->name); - obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol); + obr->actmcol= layer->active_rnd; } } } diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index c53a2b68c9c..f477df3ed8c 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -296,7 +296,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) minz= 1.0e30f; maxz= -1.0e30f; Mat4CpyMat4(viewmat, lar->shb->viewmat); - if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; + if(lar->mode & LA_LAYER) lay= lar->lay; maxtotvert= 0; for(obr=re->objecttable.first; obr; obr=obr->next) @@ -1520,7 +1520,7 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) minmaxf[2]= (2.0f*root->box.ymin - size-2.0f)/size; minmaxf[3]= (2.0f*root->box.ymax - size+2.0f)/size; - if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; + if(lar->mode & LA_LAYER) lay= lar->lay; /* (ab)use zspan, since we use zbuffer clipping code */ zbuf_alloc_span(&zspan, size, size, re->clipcrop); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 5a80173d1f1..5b69323667e 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1761,21 +1761,7 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) if(shi->combinedflag & SCE_PASS_SPEC) VECADD(shr->combined, shr->combined, shr->spec); - /* modulate by the object color */ - if((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { - if(!(ma->sss_flag & MA_DIFF_SSS) || !has_sss_tree(&R, ma)) { - float obcol[4]; - - QUATCOPY(obcol, shi->obr->ob->col); - CLAMP(obcol[3], 0.0f, 1.0f); - - shr->combined[0] *= obcol[0]; - shr->combined[1] *= obcol[1]; - shr->combined[2] *= obcol[2]; - shr->alpha *= obcol[3]; - } - } - shr->combined[3]= shr->alpha; } + diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 76a47a11338..29aa6e3be29 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2410,7 +2410,7 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4]; int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1; - if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; + if(lar->mode & LA_LAYER) lay= lar->lay; /* 1.0f for clipping in clippyra()... bad stuff actually */ zbuf_alloc_span(&zspan, size, size, 1.0f); @@ -2981,11 +2981,10 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * { ZSpan zspan; DrawBufPixel *rectdraw, *dr; - static float jit[256][2]; + static float jit[16][2]; float v1[3], v2[3], v3[3], v4[3], fx, fy; - float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz; - float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro; - float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed, totfac; + float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz, *minvecbufrect= NULL; + float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed; int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples; int tsktsk= 0; static int firsttime= 1; @@ -3004,9 +3003,6 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * rectmove= MEM_mapallocN(xsize*ysize, "rectmove"); rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw"); zspan.rectp= (int *)rectdraw; - - rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight"); - rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max"); /* debug... check if PASS_VECTOR_MAX still is in buffers */ dvec1= vecbufrect; @@ -3146,7 +3142,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dm= rectmove; dvec1= vecbufrect; for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) { - if((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f)) + if(dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f) *dm= 255; } @@ -3155,12 +3151,9 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ if(firsttime) { firsttime= 0; - BLI_initjit(jit[0], 256); + BLI_initjit(jit[0], 16); } - memset(newrect, 0, sizeof(float)*xsize*ysize*4); - totfac= 0.0f; - /* accumulate */ samples/= 2; for(step= 1; step<=samples; step++) { @@ -3168,7 +3161,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * int side; for(side=0; side<2; side++) { - float blendfac, ipodata[4]; + float blendfac= 1.0f/((ABS(step)*2+side)+1), ipodata[4]; /* clear zbuf, if we draw future we fill in not moving pixels */ if(0) @@ -3200,32 +3193,30 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata); - for(fy= -0.5f+jit[step & 255][0], y=0; y1) { - float jfx = fx + 0.5f; - float jfy = fy + 0.5f; DrawBufPixel col; /* make vertices */ if(nbd->curved) { /* curved */ quad_bezier_2d(v1, dz1, dz1+2, ipodata); - v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz; + v1[0]+= fx; v1[1]+= fy; v1[2]= *dz; quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata); - v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz; + v2[0]+= fx+1.0f; v2[1]+= fy; v2[2]= *dz; quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata); - v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz; + v3[0]+= fx+1.0f; v3[1]+= fy+1.0f; v3[2]= *dz; quad_bezier_2d(v4, dz2, dz2+2, ipodata); - v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz; + v4[0]+= fx; v4[1]+= fy+1.0f; v4[2]= *dz; } else { - v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz; - v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz; - v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz; - v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz; + v1[0]= speedfac*dz1[0]+fx; v1[1]= speedfac*dz1[1]+fy; v1[2]= *dz; + v2[0]= speedfac*dz1[4]+fx+1.0f; v2[1]= speedfac*dz1[5]+fy; v2[2]= *dz; + v3[0]= speedfac*dz2[4]+fx+1.0f; v3[1]= speedfac*dz2[5]+fy+1.0f; v3[2]= *dz; + v4[0]= speedfac*dz2[0]+fx; v4[1]= speedfac*dz2[1]+fy+1.0f; v4[2]= *dz; } if(*dm==255) col.alpha= 1.0f; else if(*dm<2) col.alpha= 0.0f; @@ -3238,59 +3229,26 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dz1+=4; dz2+=4; } - - /* blend with a falloff. this fixes the ugly effect you get with - * a fast moving object. then it looks like a solid object overlayed - * over a very transparent moving version of itself. in reality, the - * whole object should become transparent if it is moving fast, be - * we don't know what is behind it so we don't do that. this hack - * overestimates the contribution of foreground pixels but looks a - * bit better without a sudden cutoff. */ - blendfac= ((samples - step)/(float)samples); - /* smoothstep to make it look a bit nicer as well */ - blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f); - + /* accum */ - rw= rectweight; - rm= rectmax; - for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) { + for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4) { if(dr->colpoin) { - float bfac= dr->alpha*blendfac; + float bfac= dr->alpha*blendfac*dr->colpoin[3]; + float mf= 1.0f - bfac; - dz2[0] += bfac*dr->colpoin[0]; - dz2[1] += bfac*dr->colpoin[1]; - dz2[2] += bfac*dr->colpoin[2]; - dz2[3] += bfac*dr->colpoin[3]; - - *rw += bfac; - *rm= MAX2(*rm, bfac); + dz2[0]= mf*dz2[0] + bfac*dr->colpoin[0]; + dz2[1]= mf*dz2[1] + bfac*dr->colpoin[1]; + dz2[2]= mf*dz2[2] + bfac*dr->colpoin[2]; + dz2[3]= mf*dz2[3] + bfac*dr->colpoin[3]; } } } } - /* blend between original images and accumulated image */ - rw= rectweight; - rm= rectmax; - ro= imgrect; - dm= rectmove; - for(dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) { - float mfac = *rm; - float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw); - float nfac = 1.0f - mfac; - - dz2[0]= fac*dz2[0] + nfac*ro[0]; - dz2[1]= fac*dz2[1] + nfac*ro[1]; - dz2[2]= fac*dz2[2] + nfac*ro[2]; - dz2[3]= fac*dz2[3] + nfac*ro[3]; - } - MEM_freeN(rectz); MEM_freeN(rectmove); MEM_freeN(rectdraw); MEM_freeN(rectvz); - MEM_freeN(rectweight); - MEM_freeN(rectmax); if(minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */ zbuf_free_span(&zspan); } diff --git a/source/blender/src/CMakeLists.txt b/source/blender/src/CMakeLists.txt index d95551940f8..342579fb3b0 100644 --- a/source/blender/src/CMakeLists.txt +++ b/source/blender/src/CMakeLists.txt @@ -35,7 +35,7 @@ SET(INC ../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue ../quicktime ../../../intern/elbeem/extern ../../../intern/ghost ../../../intern/opennl/extern - ../nodes ../../../extern/glew/include ../gpu + ../nodes ../../../extern/glew/include ${PYTHON_INC} ${SDL_INC} ) diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile index 46e916b0437..001efc58b5d 100644 --- a/source/blender/src/Makefile +++ b/source/blender/src/Makefile @@ -68,7 +68,6 @@ CPPFLAGS += -I.. CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../../gameengine/SoundSystem CPPFLAGS += -I../ftfont -CPPFLAGS += -I../gpu # Only used by py_demo.c !!! CPPFLAGS += -I../radiosity/extern/include diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index c8c517e15ff..229cc87ef37 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -26,8 +26,7 @@ incs += ' #/intern/bsp/extern ../radiosity/extern/include' incs += ' #/intern/decimation/extern ../blenloader ../python' incs += ' ../../kernel/gen_system #/intern/SoundSystem ../readstreamglue ../nodes' incs += ' ../quicktime #/intern/elbeem/extern' -incs += ' #/intern/ghost #/intern/opennl/extern' -incs += ' ../gpu #extern/glew/include' +incs += ' #/intern/ghost #/intern/opennl/extern #/extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/blender/src/blenderbuttons.c b/source/blender/src/blenderbuttons.c index f29397b2156..e15ef3fd898 100644 --- a/source/blender/src/blenderbuttons.c +++ b/source/blender/src/blenderbuttons.c @@ -1,2139 +1,2181 @@ /* DataToC output of file */ -int datatoc_blenderbuttons_size= 68242; +int datatoc_blenderbuttons_size= 69599; char datatoc_blenderbuttons[]= { -137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, - 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144,206,103, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, - 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167,147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0, -154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,216, 9, 7, 16, 32, 48, 13, 5,217, 84, 0, 0, 32, 0, 73, 68, 65, 84,120,218, -236,125,121, 92, 84, 85,255,255,251,220,217,217, 23, 1, 21,133,193,125, 95,201, 37, 55, 40, 49, 51,205, 52,192,212, 36,219,196, -210,180,178,180,111,249, 60,233, 79,159, 12,148,202,212,132,158, 74,179,210, 18,151,180, 92, 18,116, 80, 83, 82,209, 92,202, 5, - 69, 1, 65,145,101, 86,102,187,115,231,222,223, 31, 51,131, 3, 2,179,128, 73, 61,243,126,113, 95,195, 93,230, 51,231,158,237, -253,249,124,206,231,156, 67,250,245,235,199,193, 3, 15, 60,240,192, 3, 15, 60,248,159, 2,229,201, 2, 15, 60,240,192, 3, 15, - 60,248,223,193,153,223,179, 1, 0,196,227, 1,240,192, 3, 15, 60,240,192, 3,143, 7,192, 3, 15, 60,240,192, 3, 15, 60,240, - 40, 0, 30,120,224,129, 7, 30,120,224,129, 71, 1,240,192, 3, 15, 60,240,192, 3, 15,254, 17,224,219,159,156, 61,123,150,184, - 43,168,190, 88, 2,143, 60,143,188,134,144,145,145,193,173, 95,191,254,129,165,111,234,212,169,220,150, 45, 91,136,167, 60,254, -214,242,208, 4,121,240,228,159, 71,222, 63, 89,158,203, 10,192,255, 56,234,102, 32,105,201,233, 76, 79, 79,199,236,217,179,137, -167,216,220, 47,227,184,184,184,154,243,172,172,172,127, 68, 94, 78,124, 42,185,209,142, 96,215,143, 25,255,232, 58, 35, 9,220, - 9,177,161, 19,162, 64,163, 26,251,144,175, 95,220,146,235,162,167,253,122,208,114, 60, 0,127, 69,101,157, 56,113, 98,204,174, - 93,187,100,118,231,177,187,118,237,202,105, 17, 45,146,179,244,157,132,180,216,118,201, 21, 22, 22, 2, 0,164, 82,233,223,169, - 19,113, 90, 59,157, 58,117,170,211,207,110,217,178,197, 21, 69,141,219,186,117,107,205,201,206,157, 59, 17, 23, 23, 87,235,254, -131, 82, 2,242,242,242, 56, 0,136,142,142, 38,205,241,220,174, 31, 51,238,107,249,133, 71,181, 7, 0,220, 49, 24,192,232,141, -150,139, 74, 53, 0, 32, 33, 33, 1,153,153,153, 13,166,111, 96,193, 64,174,243,237,206, 46,253,248,247,195,191,119,162, 92, 36, - 8,124,245, 2, 12,187,118, 66,161,152, 4, 5,128, 1,146,149, 88, 44, 57,141,246, 98,160,194, 80,128,197,250, 68,151,126, 55, - 33, 33, 33, 38, 51, 51, 83, 86,231, 90,108,102,102,102, 78, 11,107, 91,205, 82,111,255, 38,239,219,236,104, 19, 44, 34, 62, 2, -127, 98, 20, 11, 57,163, 82, 79, 85,235,213,172,214,104,250,159,152, 29,231, 80, 1,176, 18,182,237,179,169, 21,129,219,181,107, - 23,150,110, 93, 14,159,246,254,168,190,169,194,251,137,139,101, 45,220,226,110, 73, 32, 82,169,148, 43, 44, 44, 68, 97, 97, 33, -246,239,223,143,217,179,103,183, 84, 37,192,214,128, 72, 70, 70,134, 32, 57, 57,217,148,154,154,122, 10, 0, 22, 46, 92,248, 80, - 99, 95,156, 52,105, 82,205,255, 12, 99, 6,109, 50,130, 54,210,160,105,203,193, 48, 12, 22, 46, 92,232, 82, 90,236,201,191, 62, - 88,149, 1,238, 65,122, 2, 92, 81,126, 30,152,133, 31,224,135,243,215,191,135, 4,237, 96,198, 49,148,127,113, 6,231, 10,170, - 48,249,195, 13, 78,125,189,243,237,206, 78, 18,186, 5,207,252,250,140,195, 60,145,140, 91,140,160,137, 47,162,244,245, 1,128, - 94, 81,115,253,140,254,109,156, 1, 0, 61, 48, 82,146,128,131,129,167, 17, 0, 96,160, 98,160, 83,117, 38, 51, 51,243,158,139, -118, 4, 73, 90, 80, 27,107,142, 62,224,239,240,190,205,138, 97,125,250,145,103,195,163,248,202,136, 86,188,208,238,225, 20,159, -132, 18,157, 74,197,138, 17,102,166,250,183, 51, 63, 55, 97,140,217, 73, 81,183, 92,248,217,182, 78, 60,179,192, 5,121,105,247, - 85, 1,216,181,107,151,108,235,191,222, 69,226,178, 15,100, 77,172, 4,156,141,248, 1,160, 82, 87, 5, 4, 3,255,119,112, 9, -212,215, 21, 88,247,242,234,150, 70,100, 13,117, 60, 15, 58,141, 53, 74,192,216,177, 99, 81, 88, 88, 8,169, 84,218,226,242, 78, - 38,179,244, 27,177,177,177, 28, 0, 42, 35, 35, 35, 60, 57, 57,185, 52, 53, 53,245,180,179, 66, 24,134, 1, 77,155,106,136,223, -158,252,243,242,242, 16, 29, 29,237, 82,162, 18, 19, 19,237,201, 22, 89, 89, 89,117, 21,128,230,168, 43, 46,151, 67,116,116, 52, -153, 58,117, 42, 55,102,204,152,123,238, 29, 56,112,192,230,233,176,121, 61,156,150,223,156,195, 1,225, 81,237, 81,170, 80, 97, -199,236,167, 17, 76,134,161,224,191,111,161,195,164, 14,200,114,129,252,107, 50,203,234,106, 35,205,224,106, 11,223,122, 12,186, -162,106,148, 38, 71, 53,250,220, 5,113, 54,150,246,190,131, 21, 23,222,107,106,121, 54, 7,233, 54,167, 12, 52,179,172,251,241, -190,205,130,164,164, 36, 47, 0, 15, 3,240,177,187,172, 4,112,126,211,166, 77,114,103,229,124,178,254, 19,138,174, 52, 10,104, -163, 65,172,128, 73, 44, 16,240,249,106,131,152, 18, 10,245, 44,207,207,155,161, 37, 38, 19,191,236,150,241,235, 47, 54, 26,158, -123,105,166,217,153,247, 86, 42,149,255,177,253,159,159,159, 95,233,237,237, 77,105,181, 90,214,254,153, 65,131, 6,125,220,204, -196,190,160,169,121,202,119,100,253, 95,186,116, 9,157,125,252,236,189, 1,238,120, 1,106,200,191, 82, 87,133, 21,143, 46,169, -185,241,252,174, 87,129, 80, 96, 82,106, 34,118, 46,220,234, 74, 37,107,172,115,107,114, 69,189,121,243, 38, 0,160,125,251,246, -181,254,135, 11,238,236,102, 84, 68, 72, 67, 74,128,201,196,216,226, 1,154,197, 10,104,134,188,180, 39,127, 0, 32,201,201,201, - 0,112, 43, 35, 35, 35, 48, 57, 57, 89,225, 52,249,155, 76,160,105, 35,140, 52, 13, 83, 29,242,231, 88,215,138, 33, 49, 49, 17, -121,121,121,119, 91, 87, 90, 26,226,227,227,107,206,183,109,219,214,100,101,199, 78,225,105,114,253,179, 39,254,169, 83,167,162, -127,255,254, 54, 5,192, 85,143, 64,179, 84,194,146,235,197,208,238,252, 55,124, 94, 88,141,240,168,246, 8, 11,150,224,250,206, -235, 22,242, 15,240,179, 12, 1, 8,120,206,105,176,205, 52,198,214,229,226, 53,220,124,127, 57,244,153, 27, 27,247, 16, 72, 36, - 48, 24, 12, 40, 40, 40, 64,185,225, 10,186, 32,188,193,103,173,110,240,198,234, 62,177,181, 19,235,179, 57,110,180, 47, 98,215, -174, 57, 55,219, 25,105,132,184,157,174,131,245,189,111,124,124, 60, 71, 8,177, 13,229, 52,229,125,109,109,153,227,243,249, 77, - 42,243,164,164, 36,127, 0,147, 14, 30, 60,248,111,150,101,141,118,117,137,207,227,241,188,147,146,146, 94,218,180,105,211, 94, -135,140,185,104, 1,191,242, 86,133, 88, 32, 16,121, 83,124,226,199,241, 68, 94, 44,143,199,103, 9, 5,150,240,205, 28,143,103, -228,177,196,160,229,153,117,222, 66, 1,249,226,216, 94,195,220,148,153, 44,138, 29,167, 81,161, 80,168,117, 58, 29, 3, 0, 90, -173,150,125,247,221,119,107, 8,255,131, 15, 62,120,163,169,245,125,244,232,209,179,109,255,103,103,103,167, 55, 71, 27,162, 28, - 89,255,203,167,196,195, 80, 81,129,183,122,118,131,253,216,189,211, 86,200,196,137, 49, 0,106,145,255,196,137, 19, 99, 1,144, -137, 19, 39,198,110,152,248,153,197,179,216,181, 85,173,231,157,193,194,117,249, 88,184, 46, 31,115, 86, 93,194,115,203,254,192, -228,255, 59,219,244,142,174,164,196, 41,197,224,175, 34,127,235,152, 63,215,128, 39, 0, 38,154,198,224, 65,131,154, 67,201,224, -182,110,221,138,173, 91,183, 66, 38,147,213, 28, 46, 42, 60,156, 76, 38, 67,108,108,108, 13,249,219,223, 76, 78, 78, 86, 58,211, - 49, 49,140,217, 98,249, 27, 45,174,255,186,228,111, 54,155,161,213,107, 93,122, 65,155,199,160,174,215, 96,219,182,109,216,182, -109, 91, 45,101,192,165,247,205,169,221, 31, 90,207,155,164, 36,218,200,127,234,212,169, 72, 77, 77,173, 33,127, 1, 95,224, 42, -249,219, 58,240,134, 14,167,161, 71, 49,170, 39, 13, 6,151,249, 22, 74,174, 23,131,155,212,253,110, 38,100,190, 5,126,155, 16, - 32, 32,224, 47,213,140,181,149, 5,208,103,110, 4,199,113,184,112,225, 2, 70,142, 28, 9,137, 68, 82,139,248, 3, 3, 3,161, -215,235,161,215,235, 81, 90, 90,138,105,250,121,248, 34,240,245, 6,101, 58,233,242, 38,117,158,117,149,184,155,203, 88, 33, 13, -144,191,211,117,176,238,251,198,199,199,115,219,182,109, 67,102,102, 38, 18, 18, 18,184,166,190,175,149,252,193, 48,140,219,109, - 34, 41, 41, 73, 12,224,229,236,236,236,119,151, 45, 91,118,130, 16, 34,181, 29, 0,218, 5, 7, 7,123, 29, 58,116,104,125, 82, - 82,210,200,198,228,124,150,190,158,199, 35, 2, 17,205,112,126, 70,163, 41,212,204,178,237,204, 44, 27,101, 38, 36, 2, 60, 94, - 48, 33, 36, 0,132,231,199,114, 8,226,104, 54, 64,173, 55,121,135,250, 49, 60,106,144,198,169, 50,210,233,116, 76, 93,171,191, -165,131,106,140,184,187,116,233,130,206, 62,126,208,149,221,198,227,253, 7,184, 76,208, 54, 37, 98,233,214,229, 0, 80, 67,254, - 54, 47,194,174, 93,187,114,108, 74, 64,137,250, 22, 6, 44, 28,226,146,146,161,213,155,161,213,155,113,187,202,136,210, 10, 3, -110,222, 49,184, 69,124,182,198,226,136,252, 31, 20, 26, 81, 2, 96,160,141, 48, 24, 12, 77, 17,207,201,100, 50,216,198,200, 67, - 66, 66,236,173, 89,184,208,153,212,178,132, 27,113, 37, 58,236,244,104,147,209, 98,249, 27,105,208,166,218,228,111, 50,153,160, -213,106,161, 81,107, 30,116,177,112, 91,183,102,214,126, 37,203, 31,172,215,221,234,240,236,201,223, 70,252, 20, 69, 65, 44, 22, -195,219,199,171, 73, 9,158,248, 84, 50,215,208,225,232,187,251,255,111, 9,130, 49, 12,204,232,215, 0, 0, 62,185,215,112,174, -160,202,210,201,143,126, 13,166, 11, 75,129,202, 42,215, 50,208, 10,119,223,199, 27,149, 0,128,141, 27, 55, 98,215,174, 93, 88, -185,114, 37, 78,158, 60, 9,163,209,136,242,242,114,155, 85, 86,243,124,120,120, 56,244, 0,120,184,241, 64,234, 75, 35,245,158, - 52, 65,105, 36,141,120,240, 92,150,105,239, 9,171, 47, 38,192, 29,242, 7, 0,119,149,128,164,164,164,214, 86,242,159,245,245, -215, 95, 95, 92,188,120,241, 83,155, 55,111, 70,151, 46, 93, 0, 0,145,145,145, 80,169, 84,162,165, 75,151,158, 62,116,232,208, -183, 73, 73, 73,210, 6,115,137,229, 8, 88, 70,108, 54, 51, 65,102,198,220,206,100, 54,117,226, 81,164,173,144, 79, 9,196, 2, -158,158,239, 37, 84,122,251,242,212, 60, 49,199,136,121, 60,111, 62, 67,251,221, 56,243,187,104, 70,200, 39, 14,211,157,159,159, - 95,169,213,106,217,250,220,252,125,251,246,189, 66,211,116,179, 85,164,190,125,251, 54,155, 44,126, 99,196,253,223, 89, 47,222, - 37,219,146,155,120,171,103, 55,172,178, 16,180, 75, 90,171,205,250,183,145,126,157,223,169, 57, 15,238,221,218,165,196, 87,235, -205,208,232, 24,168,181, 12, 84,213, 12,148, 26,198,245, 86, 89, 79,228,191,189,149,111,255,255,245,235,215,161, 84, 42,255,178, - 30, 35, 61, 61, 29, 82,169, 20,182,160,191, 58, 99,253, 92,122,122, 58, 12,122,125, 83, 20, 0,110,195,134, 13, 40, 41, 45,133, -128,199, 67, 88,235,214,181,200,255,209, 71, 31,197,193,131, 7,157,237,156, 72,108,108,108, 93, 37,160,150, 39,195,217, 88, 5, -218, 72,131, 54, 26, 97, 50,209, 96, 24,115, 13,249, 27,141, 70,232,116, 58, 84, 87, 87, 67,163,113, 93, 1,176, 31, 2,176,193, - 93,203,127,107,230, 86,128, 3, 42,173, 68, 99, 29,212, 6,225, 56,139, 18,144,153,137, 68,139, 5,229, 82, 91,169, 75,254, 2, -129, 0, 34,145, 8, 98,177, 24, 98,177,184,201,117,170,161, 33,129,250,230,197,219, 99,114,250,118,112, 79, 70,225,206,208, 1, - 8,198, 48, 72,158, 94, 3,230,118, 5, 16,224, 7,126,213, 22,252,252,201,105,128,199,115, 41, 45, 77, 29, 10,208,242, 44,125, -202,138, 21, 43, 80, 81, 81,129,245,235,215,163,111,223,190, 88,182,108, 25, 6, 12, 24, 0,189, 94, 95,215, 66,179,169,212,127, - 53,241, 59, 75,208,238, 14, 7, 52,164, 72,184, 44,199, 58,139,163,166,109,184, 59, 52,102, 79,254, 53,100, 99, 85, 2, 92, 28, - 14,240, 61,127,254,252,167,175,188,242,202,145,222,189,123,251, 1,192,146, 37, 75,144,159,159, 15, 0, 24, 50,100, 8,118,236, -216,129,225,195,135,123, 79,155, 54,173, 32, 39, 39, 39,251,249,231,159,159,246,251,239,191,223,147,179, 65,193, 65,236,245,235, - 5, 76,142,236,224,190, 78,157, 58,231, 68, 69, 74, 47,242,124, 37,229, 60, 34,212, 82, 34,129,142, 18,123,105,104, 62,143, 6, -103,226,177, 98,147,175,166,180,202,231,228,161,179,131, 90, 5,134,237,112,168,140,218,141,249,239,220,185,243,185, 73,147, 38, -125,109,115,251,171,213,106, 74, 40, 20, 54,185, 34,217,220,254,217,217,217,247,215, 3, 96,179,242,163, 59,118,134,161,162, 2, -218, 18, 11, 9,142,180, 90,135,174,122, 1,174,255,113,237, 30,217,245,157, 87, 93, 40,115, 41,241, 77, 37,127,123,226,231, 56, -206, 54,198, 95, 3,147,201, 84,115, 40,149, 74,104,181, 90,200,229,242,191,172,231,176,205,243,223,191,127,127, 93, 79, 0,151, -158,158,142, 62,125,250,192, 96,208,215,116,116,233,233,233, 46,185,235,215,125,182, 14, 38,147, 9,237,194,195, 97, 50,155, 27, - 34,127, 87, 58, 18, 82,143,235,191,102,234, 98, 99,158,140,123, 20, 0,218, 84, 67,254,167, 78,158,130, 78,175,135, 70,163,129, - 74,165,130, 82,169,172,101,217,185, 10,219, 48, 64, 19,198,253, 81, 85, 89,133,170,170, 74, 84, 86,201, 81, 89, 85,133,170,170, - 42, 84, 85, 90, 44,210,110,221,187, 67,110,253,223, 85,235, 31, 0,250,247,239,127,215,234,247,246,134,143,143, 47,124,125,124, -161,209,104, 98,155, 72,254,110, 15, 7, 20,172,156, 5,193,211,107, 16,140, 97,224,231,174,129,105,251,107, 64,128, 31,118,191, - 26,143,162,221, 55, 48, 33,117, 19,192,255,139,151, 21, 49, 20, 65, 18, 46,129, 86,171,133,193, 96,128, 78,167, 67,110,110, 46, - 62,252,240,195,122, 31,247,242,178,121, 80,174,185, 67,222,238, 90,213,246,249, 75,156, 60,111,138,146,225,106,155,173, 37, 39, - 51, 51,147, 36, 36, 36,216,200,223,109,207, 4,159,207, 39, 12,195,212, 85, 10,224,106, 44,192,166, 77,155,174, 38, 36, 36,244, -221,188,121,243,200,163, 71,143,250,142, 30, 61,250,164,141,252,173, 6, 36, 68, 34, 17, 87, 84, 84, 36,216,183,111, 95,215,192, -192,192, 83,195,134, 13, 43,168, 79,214, 51, 83,158, 97, 59, 71,117,209, 12, 25, 50, 36,254,226,197, 63, 31, 81,107, 53,173, 57, -198,196,128,130,137, 49, 82, 70,163,209,168, 87,163, 76,205, 26, 13,154,210,226, 50,230,231, 61,123, 83, 90, 5,135,148,211,180, -206,161,249, 94,159,245,175, 80, 40,248, 0,224,231,231,215, 98,135, 5,168,134,172,255,173,255,122,215,162, 53,151,221,174,117, -207,213, 88,128,137, 19, 39,198,174,123,121, 53, 0, 75,192,223,174, 93,187,100, 54,210,183,173, 9, 16,247,205, 83, 0,128, 51, -169,191,217,226, 3,254, 42,212, 84,198,146,146,146, 26,107,223, 70,250,118,133, 11,141, 70, 3,131,193, 96,215,137,252,117,105, -156, 61,219, 18,251, 97, 98, 24, 92,188,120, 17,191,159, 57,131,190,125,250,194, 96, 48, 64,175, 55,192,160,215,227,219,111,190, -129,237, 57,103, 26,122, 90, 90, 26,122,116,239, 1,147,201,132,171, 87,175,130, 49,209, 40, 45, 41,109,214, 60,181,157, 91,215, - 44,176,173, 93,224,216, 3, 96, 50,130, 49, 91,220,254, 39, 78,252, 6,173, 94,139,106,141, 26, 42,149, 10, 10,165, 18, 10,133, -188, 73,138,152,205, 19,224,166,245, 15, 0, 56,114,228, 8, 52, 26, 13, 52, 26,181,245, 83,131, 86,193,193,232,214,189, 59, 46, - 95,186,132,195, 71,142,184, 44,211,102,253,243,249, 2,120,121,121,193,199,199, 7,190, 62, 62,240,241,241,130, 92, 33,143, 77, - 78, 78,206,113,170,205, 53,193,213,223, 16,206, 21, 84,193,116, 97, 41,170,112, 12,100,220, 42,144, 97,255, 70,193,202, 89,120, - 50,245,107,136, 5, 20, 32,224, 91, 14,119, 88,199,205,161,128,210,241,159, 33,104,203,120,232,116, 58, 4, 5, 5, 65,161, 80, - 64,161, 80,224,248,241,227,184,125,251,118,141,155,184,230,249,210, 82,188, 26, 40, 65, 43,175,138,198, 44,224, 88,123, 82, 77, - 72, 72,136,177,187, 23, 83,231, 94,172,139,237,130,107,132,192,155, 99, 70,129,203,150,127,125,239,155,153,153, 73,182,109,219, - 70,154,248,190,181,148, 0,119,200,223,134,247,222,123,239,252, 83, 79, 61, 53,109,197,138, 21, 93,207,157, 59, 55, 76, 34,145, -240,158,124,242, 73, 34, 18,137,192,178, 44, 25, 55,110,220,249,249,243,231,247,233,213,171,215,238,151, 94,122,233,185,151, 94, -122,169,193,177,168,228, 57,201,236,159,151,174,158,234,213,187,207,179,167, 78,158,156,188,123,207, 79, 31,228,157, 60,217,250, - 98,254,101,241,213,210, 2,238,219,213, 63, 72, 86,164,173,236,145,189,103, 79, 90,167,142,157,126,246, 9,243, 62,178,105,211, - 38,179,179, 57, 58,122,244,104,156, 58,117,170, 95,122,122,250, 82,131,193, 32, 88,182,108,217, 71,187,119,239,158, 90, 90, 90, -250,151, 19,135, 83,101,212,208,141,224, 27,133,144, 3, 53,214,191, 13, 35, 67, 66,176, 10,151,157,183, 58,172, 46,254,203,167, - 47, 34,160,107, 43,196,125,243, 20,118,205,248, 81,102,211,222,108,228,111,179,254, 93,153,101,176, 99, 69,191,230, 97, 88, 66, -112,233,210, 37,216, 42,107, 93,247,178, 64, 32,128, 64, 32, 64, 69, 69, 5,198,141, 27,247, 32,202,137, 72,165, 82, 46, 61, 61, - 29,131, 6, 13,130,193,104,132,222,160,135,193, 26,220,164, 55, 88,134, 1,214,174, 93,139,185,115,231, 58,234, 76,184,212,212, - 84,152,205,102,156, 62,125, 6, 2,190,197,109,219,185,115,103,220, 40, 44, 68,105,105, 41,182,108,249, 30, 83,167, 62, 3, 0, - 92, 29, 79, 64,131, 29, 80, 70, 70,134, 16, 0,147,156,156,204,214,103, 1,185, 50, 85,209,102,249,231,230,230, 66, 91,173,171, - 81,192,212, 26, 53,212,106, 21,212,106,247,134, 0,236,173,255,169, 83,167,214,120, 0, 92, 85, 4,166, 78,157, 90,235, 60, 74, - 42, 69,183,238,150,160,184,203,151, 46,225,134,213,227, 49,117,234, 84,151,163,246,135, 62, 60, 20, 34,161, 8, 18,137, 4, 98, -177, 24, 34,145, 8,101,101,101, 78,147,191,157,181,223,172, 21,112,242,135, 27,176, 3,192,216, 21, 79,128,203,124, 11, 36, 49, - 13,231, 10,170, 64,130, 2,113,173, 68,109,177,254, 93, 28, 2,176,107,127,196,166, 8,216,159, 59,132, 94, 15,240, 44,198,222, - 93,247,190,133,232, 77, 38, 19,190,248,226, 11,140, 28,121, 55, 46,236,224,204,112,160, 92,135,174,123, 21,232, 23, 18, 89,175, -200,122,162,220,237,135, 60,101, 14,158,117,150,176, 73, 19, 60, 10,141,121, 35, 92, 86, 36,238,247,251, 90,149,128, 38,207, 2, - 88,177, 98,197,150,121,243,230,133,156, 61,127, 62, 81,175,215,247,145,201, 14, 73, 68, 98, 17,159, 34, 20, 14, 29, 58,228,219, -163, 71,143, 77, 9, 9, 9,255,158, 60,121,178, 67,107, 61,231,208, 1,118,194, 83, 19, 14,247,237,219,127, 33,205, 24,199, 94, -203,191,250, 1, 91, 88,192, 0,224,196,160, 76,189, 59,117,205, 12, 13, 13,217,203,227, 11,191,253,207,226, 20,250,147,101, 31, - 59, 44,165, 65,131, 6,125, 60,122,244,104, 0, 64, 69, 69, 5,178,179,179,253,190,250,234,171, 15, 0,224,212,169, 83,131,122, -246,236,185,255,111,161, 0,216, 22,254,121,244,219,205,142, 44,123, 87,166, 4,146,157, 11,183,114, 3, 22, 14, 65,112,239,214, - 53,164, 95,227, 78,189, 80,134, 51,169,191,185,234,182,106,174, 57,169, 4, 0,215,189,123,119, 92,184,112,161, 22,177, 40,149, -202, 2, 0, 29, 93,212,230,239,167, 39,224,158,223,252,246,155,111, 97, 48, 24, 96,164,141,160,105, 26,169,169,169,141, 45,146, -195,165,166,166,214,156,176,172, 25, 98,137, 15,244,122, 3, 46, 93,188, 8,190, 64, 0, 19, 77,195,203,219, 11, 91,182,108, 1, -143,199, 67, 98, 98, 34, 30,125,244, 81,174,170,170,225, 0,175,212,212,212,253,201,201,201,116, 70, 70, 70,168, 45,111,234,172, - 3,224,146,107,115,225,194,133, 56,118,236, 24,170,171,171, 81,173,213, 66,163, 86, 91,201, 95, 13,141, 90,131,106, 77, 53,180, -118, 29,190, 51,121, 23, 29, 29,205,229,229,229,213, 88,255,245, 77, 3,116,118, 17, 32,235, 92,252, 90,101, 97, 35,125,219,216, -163, 43,171, 20,218, 86,248, 3, 0, 31, 47, 31,136, 37, 98,104, 52,154, 88,219,208,142, 27,228,127, 95,230,107,219,148,128, 73, - 43,190, 2,183, 29,104, 53, 51, 3, 57,175,199, 99,120,202,119,128, 64, 0,111,113,211,198, 57,235, 42, 2, 0, 48,245,216, 84, - 7,223,186,131,222,251,189, 80,246,147, 14,138,229,119,175,154, 76, 38,140, 24, 49, 2, 0, 16, 30, 40,193,175, 25,237,177,242, -195,155,248,236,140,222,145, 69,108, 63, 45, 14, 13,253,111,247,108,142, 27,125, 86,115,205,173,111,142, 49,255,251,249,190, 53, - 74, 64,115,212,191, 79, 63,253,244,211,231,103, 62,191,239,161,129,209,131, 52,106,117, 16, 99,102,140, 97, 97, 97, 21,225,225, -225,101,106,181,250,220,228,201,147,157,238, 20,126,250,241, 39, 22,192,150,103,167,191,152, 59,108,248,240, 31, 37, 18,137, 63, - 1,199, 18, 66,192,178,156, 74,175, 85,200,174,156, 47,214,120,139,132, 78,245,243, 54,242, 7, 44,129,212,117, 3,245, 62,252, -240,195,127,255, 45, 20, 0, 43,169, 59, 44,176, 93,187,118,185, 92, 89,207,164,254,198, 1,128, 77, 17,176, 35,254,230, 36,116, -183, 27, 82,239,222,189,113,234,212, 41, 84, 84,212,184, 8, 59, 2,128,141,252,102,204,152,241,160,203,171, 86, 30,165,167,167, -115,207,206,120, 22,107,215,174,179,142,153, 51, 88,184,112, 97,163,211,151, 92, 92, 65,207, 98, 57, 29, 60,232,104,179,137,238, -169,169,169, 87,147,147,147,203, 51, 50, 50,120,201,201,201, 53, 1,129,214,105,129, 78,119,116, 54,139,121,216,176, 97,205,158, -119,209,209,209,156,189, 21,111, 31, 3,224,198, 10,128, 4, 0,183,101,203,150,123,172,124,171,135,192,229,250,188,101,203, 22, -226,170,199,192, 25, 52,230,250,119, 85, 89,152,252,225, 6,192,110,225,159, 81,239,222,157,142,172,109,174,130,178,243, 0, 56, - 90, 9,176,116, 88, 41, 74, 1, 12, 88, 25,136,229,167,187, 32, 4, 64, 69,129, 22,157, 58,117,178,144,198,242, 64, 60,246, 80, - 8,162, 30,203,119,214, 34,118,122,120,211,250, 44,113,183,191,105,166, 62,175, 73,178,254,162,247,109, 54,108,216,184,225, 42, -128,171,205, 37,239,219,239,190, 44, 68, 51, 68,133, 54,103, 96,158, 21, 11,254,138,252,252,171, 55, 3, 34, 19, 39, 78,140,217, -149,218, 34,247, 2, 32, 0,184,135, 30,122, 8,123,247,238, 53, 88, 73,159, 5,224,117,159, 60, 15, 77,134, 45, 72,112,238,220, - 57,156,213,242,127, 32,105, 91,184,112, 97,100,125,110, 73,187,105,132,174, 88, 59,228, 62,151,113, 77,122,154,186,236,111, 67, -171,242,185, 74,226,142,214,246,111, 14, 52,101, 72, 96,209,162, 69,184,126,253,122,179,165,197,153,229,125, 93,197,153,183, 21, - 56, 3, 75, 96,232,200, 4, 9,126, 57,209, 5, 97, 94, 62,248, 51,239, 14,186, 58, 73,254, 78,212,191,150,186, 28, 46,185, 79, -223,245, 44,207,238, 28,218, 54,179,188,180,191, 42,225,127,249,110,128,117, 61, 12,110,120, 18,238,187, 18, 48,110,220, 56,241, -223,172, 2,186,101,217, 55,215,111,103,100,100,216, 86,168, 97,146,147,147,155, 58,149,201,131,230, 39,255, 38,149, 69, 74, 74, - 74,179,148,101, 70, 70, 6, 63,121,120,242,125,175, 23, 71, 50,245, 56,146,153,223,226,219,172,167,102,122,240,192, 43,161,187, -251, 8,123,224,129, 7, 30,120,224,129, 7,127, 95, 80,158, 44,240,192, 3, 15, 60,240,192, 3,143, 2,224,129, 7, 30,120,224, -129, 7, 30,120, 20, 0, 15, 60,240,192, 3, 15, 60,240,192,163, 0,120,224,129, 7, 30,120,224,129, 7,255, 8,212,154, 5,112, -246,236, 89,183, 35, 83,235, 11, 38,244,200,243,200,243,200,243,200,115, 82, 94,163,211, 68, 91,128, 60, 79,249,122,228,213,194, - 43,175,188,210, 14,128, 2,128,208,186,213,121,139, 74,159,199, 3,224,129, 7, 30,192,223,223,159,242,247,247, 39,254,254,254, - 2, 0,188,150,150, 62,219,190,243,118,251,207, 55, 21,245,173,143,239, 65, 11,194, 19, 79, 60, 17,243, 15,120, 13,219,218, 87, -146,191,235, 11,120, 20,128,127, 56,154,176,221,186,203,136,139,139,139,177,118,186, 53,135,245,218, 63, 82, 94, 11, 7,137, 12, - 11, 35, 0,160, 82,169, 88,149, 74,197,169, 84, 42, 19, 0,179, 59,194, 94,126,172,119,201,172,177,189, 39, 2,192,172,177,189, -191,121,249,177,222,235, 0, 96,225,164,135,200,194,167,163, 5, 47,143,233,229,214,154, 34,246, 75,209,102,102,102,214,218,124, -167, 41,228,111, 87,239,155,115,173,253,166,202,108, 14,121,220,125, 80,108,254, 82, 69,233,137, 39,158,136,217,187,119,175,236, - 31,208,198, 12,176, 44, 22,119, 95,121,180, 77,176,136,234,220, 58,148, 31, 33,109, 71,133, 5, 4, 11,189, 69,130,102,251, 61, - 62,254, 25,160,172, 90,152,222, 90, 32, 30,216, 41, 0, 78,236,173, 98, 4, 32,106,234, 79,101,101,101, 33, 45, 45,173,214,242, -127, 11, 22, 44,176, 53,116,226,142, 60,246,135,192,218, 5, 61, 37,171,165,200,107,241, 69, 31,229, 45,225,162, 58, 72, 1, 0, -101, 52, 51,189,181,144,255,157,237,230,101,117,181,168,172,178,146,118, 70,208, 75, 99,122,229,155,205, 92,248,195, 67, 91,249, -117,237, 58,236,128, 72, 68, 21,205, 73, 25,244,159,255,146, 11,184,163,210, 61, 33,224,147,159, 0,114, 17, 64, 79, 87, 19, 89, -119, 41,218, 38, 46, 55, 91,139,252,237,234,190,187, 75,229, 18, 23,175,223,119,121, 9, 9, 9,182, 53,250, 29,190, 83, 66, 66, - 2,151,153,153, 73, 92,200, 59,210, 12,114,156, 34,127,150,101, 65, 8,193,200,145, 35,185, 35, 71,142, 16, 23,203, 88, 8,192, -212, 28,233, 9, 10, 10,154, 37,151,203, 63,119,243,235,126, 0,148,104,190, 85,176,107, 97, 88,159,126,212,179,225, 81, 98,101, - 68, 43, 97,104,247,112, 62,159,132, 82, 58,149,138, 17, 35,140,166,250,183,163,159,155, 48,134,110,234,111, 56,171, 73,132, 0, -120,220,250,217,210,224, 7,224, 41, 0,233,214, 79,191,102,146,251,125, 75,179,176,221, 42, 96,202, 97, 17, 15,178, 54,168,208, -166,144,205,252,249,243,239, 33,127, 0, 72, 75, 75,139,157, 63,127,190,203, 86,206,198,215,188,239, 33,107, 0, 96,127, 8,196, -198,215,188, 31,168,188,212,212,212, 24,138,162,184,103,158,185,187,164,237, 43,175,188, 18, 3,128,139,136,136,224,218,181,107, -199, 5, 7, 7,115, 79, 63,253,180, 83, 50, 55,164,126, 20,115,156, 26,194, 45,141,142,175,177,126,215, 45, 93, 23, 51, 15,171, -185, 57, 17, 27,184, 25,237,182,114,227,131,247,115,131, 58, 44,115,202, 58,238,208, 46,172,117, 76, 7, 41,247,218,156, 25,198, -229,111,189,200, 45,124, 97, 26, 90, 11,249,223,189, 59,251, 89,172,124,227,101,110,217,220, 23,216,110,126, 62, 70, 0,104,221, - 58,152,111, 45,255,122,113,102,231,211,157,195,195,189, 2,158,153, 18,153, 54,113, 82,123, 1,203,177,210,144, 86, 34,239,143, - 95, 63,145, 54,239,169,126,223, 62,254, 88,155,200,136, 8,239,226,127, 47,238,237,238, 54,153,246, 27, 69,185,180,105,148, 3, -203, 31,205,224, 9,104,113, 30,128,204,204, 76,146,144,144, 80,243,189,132,132, 4,174,190,161, 19, 43,105, 59,173, 84, 52,148, - 14, 59, 57, 77,238,232,236,201,127,193,130, 5, 24, 57,114, 36,247,235,175,191,186, 35,138,110, 70,227,181, 44, 40, 40,104,146, -155,223, 13,183, 26,156, 82, 0, 72, 74, 74,138, 76, 74, 74,218,147,148,148,148,107,119,236, 76, 74, 74,114,105, 27,229, 79,214, -127,194, 79, 93,150,226,247,248,147,147,194, 21, 3,123,118,224,183, 13,239,168, 54,136, 59, 86,155,245,237,137,159,119, 91, 58, -204, 20,198,148,221, 10,248,250,139,141, 66, 23,121,220, 45, 5,160, 61,128,111, 0,196, 91, 63,219,183, 32,126, 11, 6,176,197, -170,156, 28, 7, 48,214,122, 30,220, 12,178,167,192,137,241,210,150,174, 0, 56,129, 33, 0,174, 0,136,114,199,186,177,185,208, - 35, 34, 34, 98,237,173,126, 59,203,191,230,158, 51,238,118,219, 51, 73,195,133,118, 86,186, 2,212, 20, 69,205,185,237,222,131, -144, 7, 0, 39, 78,156,144,137,197, 98,228,230,230,222,163,108, 21, 23, 23,147,146,146, 18, 50,100,200,144,216, 61,123,246, 56, -149,135,173, 79, 92,148,113, 98, 1,250, 84, 8,107, 89,195,132,226,176,174,248,121,242, 77, 73, 34,145,142,189, 16,203,220, 26, -239,208,109, 26,211, 65,202, 69, 8, 37,183,223,124,117,186,177,157,143, 80,168,186,120,140,120,149,159,199,188, 17,157,209, 54, - 64,130,242, 51, 71,201,157,211,199,168, 5,179,102,208, 49, 29,164, 92, 55, 47, 95,147,181, 67,173, 23,173, 90, 9, 71, 9,133, -148,248,248,241,219,243, 79,157,188,213, 61,172, 93, 7, 83, 64,171,118,196,215, 23, 94, 29,162,188,162,130,130, 68,157, 88,142, - 51,254,124,178, 92,251, 0,235, 48,103,111,241,219, 14, 55,149, 0,174,158,207,186, 71,125,207,253, 85,242,106,148, 0,185,124, - 52, 50, 50, 20,104, 10,249, 55,166, 84,212,145,211, 36, 15,192, 19, 79, 60, 17,179,103,207, 30, 25, 33, 4, 20, 69, 33, 47, 47, - 15, 71,143, 30,117, 75,150,217,108, 62,111,245, 0, 52, 71, 60,139, 68, 46,151,239, 12, 10, 10,122,218,141,239,218, 60,206,154, -164,164,164, 94, 0, 14, 28, 60,120,112, 92, 86, 86,214, 16,219,145,157,157,253,148, 76, 38, 59,148,148,148,228,212,144,199,130, - 69, 11,196,149,183, 42,130,245,156, 49,130,227,147,110,156, 72,212,157, 21, 8,187,179,132,234,204, 18,126, 39,134,199,139,100, - 89, 18,174, 37,230, 80, 70, 72, 5,126,113,108,175, 88,252,100,232,125, 85, 0, 62, 1,112, 16,192, 60,235,231, 39, 77,200,236, - 64, 0, 75, 0,236,177, 86,244, 61,214,243, 64, 55,229, 29, 1,176, 23, 64, 50,128,245, 0,222,176,202, 60,210,196, 74,225,111, -253,244,110, 6, 11, 27, 86, 11,107, 73, 99,150,214, 3,196, 67, 0,142, 1,104,109, 85,158,158,117,229,203, 89, 89, 89, 50,123, -203,127,193,130, 5,178,180,180,180,216,180,180,180, 88,123, 37, 32, 45, 45, 45, 54, 43, 43, 75,230,140, 60,123, 75,157,154,162, -192,213,189, 51,112,117,239,140, 90,164,205,254, 16, 8,119,229,217, 44, 77,119,228,165,167,167,199, 28, 63,126, 28,211,167, 79, - 71,113,113, 49,146,147,147, 99,234,123, 70, 44, 22,203,218,180,105,227, 48,255, 50,210,211, 99,218, 28,255, 3, 37,211,135, 65, - 88,172,194,231, 75, 62,142,169,109, 28, 3,233,233, 25, 49, 2, 67,132, 44,168,141,222, 33,249,207,122,105, 10,253,175,249, 51, - 56, 97,209, 25, 97,224,157, 11,228,194,109, 53,194, 67,188,241,112,143, 48,180, 85, 94,193,117,141, 30,124,150, 67, 0,225, 9, -254,239,197,233,220,107,175,188,112, 37,166,131,180, 65,210, 81, 40, 53, 65,131, 6,249,164,245, 30,242,184,201, 55,168,163,200, - 39, 32,148,149,248,120, 27,131, 90, 5, 27, 66,194,219,243, 21,114,141, 72,173, 98,160, 80, 25, 93,113, 99,199, 56, 67,156, 78, -198, 3,220, 99,249,215,167,148,187,160, 4,144,122, 62,235, 30,245, 61,231,148, 60,110,107,224, 61,135,139,242, 26,202,211, 38, -145,118, 93,165, 34, 35, 67,129,230, 34,127,138,162,184,125,251,246,201, 88,150,197,235,175,191, 14, 66, 8,142, 30, 61, 10,203, -214,187, 44,113, 67, 30,104,154,254, 29, 0,211, 12,158, 0, 57, 0,200,229,242,237, 65, 65, 65,177, 46,126,151, 15, 0, 51,103, -206, 20, 1,200,202,206,206,238,178,108,217, 50,166,174, 18, 26, 28, 28,140, 67,135, 14,197, 36, 37, 37, 57,212,202,120, 68,224, - 71, 51, 92, 91,163,209,212,197,204,178,189,204, 44, 59,192, 76, 72, 47,240,120,237, 9, 33,109, 64,120, 97, 44,135, 8,142,102, -219,169,245,166,144, 80, 63, 70, 72, 13,210,220, 55, 5, 32,220,106,241,175,132,101,156, 99,165,245, 60,220,141,223,154, 1,160, -216, 90,153, 22, 1, 8,178,126, 18,235,117, 87,247,218,253, 55,128,107, 0,214, 1, 16,192, 50,134,205, 0,248,204,122,189, 41, -251, 47,143, 4, 80, 1, 96, 84, 51,145,236, 11, 0,222,183,126,182, 52,244, 4,240, 35,128, 71,173,158,148,158,238, 10,178,145, -191, 61,233,219, 43, 1, 46, 87, 78, 43,249,219, 80, 87, 9,112, 71, 94,157,206,140,184, 42,239,240,225,195,160,105, 26, 3, 7, - 14,140,237,214,173, 27, 10, 11, 11,107,222,143,101, 89, 72,165, 82,110,241,226,197,178,227,199,143, 99,220,184,113, 14, 59, 20, - 67,238, 41, 80, 52, 3,229, 64,105,172,177, 91, 48,174,109, 56,124,151,180, 88, 14,115,164, 27,184,195,139,131,101, 55,142,251, - 35,238,249,171,142, 59, 40,138, 87, 93,113, 33,151, 45, 83, 26, 80, 85, 77,115,241,253, 34, 56,127,137, 16,183,148, 90, 84,168, -244, 72,236, 31,193, 81,132,112,191,253,180, 31,170, 35, 39,184, 51, 59,127, 46,106, 76, 92,238,239,109,231,132,132,250,117,108, - 27, 17,197,120, 73,216,142, 35, 31, 79,244,233, 48, 48,121,124,235, 46, 79,198, 5,181,141,238, 43,175,110, 29,111,162, 77,166, -235, 5, 90,167,134,222,172, 4,229, 84,157,200,204,204,148, 57,152, 25, 80,239, 61, 39, 98, 94,254, 17,179, 3,146,147, 3,145, -156,124, 87,185,181, 17,119,115,144,118, 61, 10,140,219,150, 63,199,113, 48,153,238, 14,217, 15, 31, 62,220,214, 94,220,149,109, - 18, 8, 4, 38,150,101,143, 91, 61, 1, 77, 81, 2,106,134, 62,229,114,185, 44, 40, 40, 40,217,133,239, 22, 38, 38, 38,250, 29, - 62,124,120, 69,118,118,118,235,175,191,254,154, 93,188,120, 49,127,243,230,205,232,210,165, 11, 0, 32, 50, 50, 18, 42,149, 10, - 75,151, 46, 53, 31, 58,116, 40, 62, 41, 41,233,213, 70, 37,178,140,191,217,204, 68,154, 25,115, 79,147,217,212,159, 71,145, 40, - 33,159, 18,137, 5, 60, 53,223, 75,120,219,219,151,119,135, 39,230,140, 98, 30, 47,136,207,208,109,110,156,249,221,119, 70,200, - 39,110,199,189, 57, 82, 0, 30,179, 90,135,246, 56,102,189,238, 10,166, 1,120, 29,150,177,146,247, 1,252, 1,203,252,201, 63, -172,231, 82,235,253,105, 78,202,243, 2, 48, 11, 64,146,245,220,104,119,192,122,125, 22,238,221,202,215, 89, 76, 1,240,149,245, -179,169,120, 30,192, 28,107,158,205,177,158,183, 20,116,178,186,176,126, 6, 48, 23,192,108, 0, 49,240,160, 65,148,150,150,202, - 6, 15, 30,140,217,179,103,231, 12, 30, 60, 24, 39, 78,156,192,250,245,235, 99, 90,183,110, 45,163, 40, 10,133,133,133,164,178, -178,146,188,246,218,107,177, 71,142, 28,145,189,244,210, 75,141,146,205,208, 27,183,100,101,131,187, 35,121,246,236,156, 63,195, -204,177, 61, 85, 65,178,140,245, 25, 49, 22,237, 4, 88, 87,248, 60,217, 82, 25, 79, 70,190, 86, 26,123, 52, 83, 42,139,125,120, -101,131,229, 83, 66, 51,171, 62,255,124,115,208,246,243,165, 55, 55,159, 41, 86,110, 56,126, 93,123,163,204,192, 81, 28, 5,131, -206,140,138, 10, 26,121,197, 10,243,174,194, 82,205,158, 91,101,202, 29, 69, 37,151,143,149,149,143,185,105, 52,125,212,144, 76, -191,192,240,118,250,106, 69,219, 30,209,143, 80, 52,137, 28, 89,122,249, 71,125, 96,144,183,164, 67,247,126, 21, 28, 83,113,158, -240,252, 66, 88,150,229,221,185,163,119,198,139, 87,215, 53, 93,159, 27,188, 86,148,187, 19,227,207,164,174,165,111, 59,238, 7, -161,181, 20, 52, 22,148,103,231,206,111, 18,154, 67, 78,117,117,181, 12, 0,248,124, 62,222,122,235, 45,228,229,229,193,205,113, -127,123, 24, 1, 24,141, 70,163,177,180,180, 52, 11, 77, 11, 8,212,212,114, 7,200,229, 25, 65, 65, 65, 19,156,245, 20, 27, 12, -134,254, 11, 23, 46,124,242,149, 87, 94,225,122,247,238, 77, 0, 96,201,146, 37,200,207,183,236, 70, 57,100,200, 16,176, 44,139, -225,195,135, 83,211,166, 77,227, 46, 95,190,188,238,249,231,159,127,222,203,171,126,106, 98, 89,206,144,115,240,224,182,194,194, -235,207,155, 77,230, 48,158, 64, 98,224, 17,177,138, 18, 9, 85,148,216,171,156, 22,120, 85,130, 18,221,102,197,102,131, 70, 85, -213, 74,182,251,236,123,230, 83,191,187, 29,247,230, 72, 1, 24, 3,224, 80,157,107,135,172,215,157, 5, 15,192,187, 0, 18, 1, - 84, 53,240, 76,149,245,254,187,112,110, 92,103, 26,128, 3, 0, 84, 13,220, 87, 89,239, 79,115, 35, 79, 30,129, 37,134,224, 67, -235,231, 35, 77,168, 92,241, 86,175,201, 16,107,122,134, 88,207,227, 93,148, 19, 8, 32,192,137,195,213,161,148,161, 0,157, 16, - 39,240, 0, 0, 32, 0, 73, 68, 65, 84, 78,226,110, 4,112,145,213,211,227, 86,156, 71, 93,139,191,174, 71,192, 85,176, 63, 4, -162,243,184,111,106,206, 59,143,251,166,222, 64, 62, 87,228,213, 33, 19,206, 21,121,107,215,174,229,242,242,242,112,250,244,105, -180,107,215,142,251,229,151, 95,160, 86,171,113,233,210,165,123, 44,218,119,223,125, 55,167, 71,143, 30,177, 91,183,110,109, 80, -222, 23,107,215,114,237,243, 46, 32,244,116, 62,100,237,198,113,189,175, 48, 50, 74,109,130,249, 82,245, 61,207,190,249,238,139, - 57, 17,209,167, 99,139,254,152,210,160,245,124,173,164,228,237, 18,154, 89, 85, 81,169,151,210,122,115, 96,254, 45,181,207,158, -203,165, 85,198,200,190,232, 17, 26, 4, 0,216,115,246, 14,191,160,172,218, 15, 64, 96, 25,109,232,113,211,104, 74, 40, 40, 45, -125,187, 33,153,163,198, 39, 82,221, 70,126,208,155,209,254, 81, 28,209,125,180, 68, 32, 48,211,215,254,200, 82,150, 22, 95,186, - 83, 94,252, 91,177, 90, 94, 10, 80, 20,145,107,104,255, 89,137,253, 29,213, 27, 82,135, 84,234,115,171,215, 10, 4,180, 62,255, - 87, 69,227,255,237, 96,111,245,215,245, 8,184,235, 85, 8, 10,202,110,178, 28, 0, 24, 57,114, 36,119,248,240, 97,176, 63, 4, -128,227, 56,124,252,241,199, 56,114,228,136, 77, 81,115,187, 12, 20, 10,133,145, 16, 50,226,212,169, 83,134,240,240,240,184, 38, -122,117, 2, 0,203,108, 0,235,231, 12, 0,108, 80, 80,144, 51,134,154,106,247,238,221,165,251,247,239,255,106,243,230,205,228, -232,209,163,100,244,232,209,156,141,252, 1,203,118,247, 34,145, 8, 69, 69, 69,216,183,111, 31, 9, 12, 12,100,134, 13, 27,246, - 43,203,214,111,180,119,142,234,114,123,200,144, 33,179, 46, 94,252, 51, 66,173,213,132,113,140,201, 4, 10, 70,198, 72, 85, 27, -141, 70,165, 26,101,183, 88,163,225, 78,105,113,153,241,231, 61,123,215,180, 10, 14, 41,162,105, 93,181,187,121,201,175,167, 97, -216, 10,166,181,245, 56, 92, 71, 81, 56, 12, 96, 1,128,182, 0,202, 28,100, 62,129, 37,118,224, 56,128, 27, 14, 20,142, 27,214, -231,230,161,225, 56, 3, 91,250, 38, 3, 72,113, 32,239,107, 88,134, 24,190,114,144, 62,251,138, 40,133, 37,206, 97, 32, 0, 53, -128,247, 0,156, 6,208, 17, 64,161, 19, 46, 68,123,121,207, 0,120,209, 74,178,122,107, 90,245,214,243,116, 88,226, 1,190,119, - 66,222, 12, 0,175, 56, 89,193, 9, 44,177, 16,223, 56, 72,223, 42, 0,190,176,196, 58,236,182,166, 77,108,213,164,255, 0, 48, -216,234, 17,248, 21,119,227, 53,234, 69, 92, 92, 92,172, 61,209,219, 43, 1,117, 99, 3,226,226,226, 98,179,178,178, 26,125,129, -184,184,184, 88,106,202,221,113,123,246,135, 64, 80, 86, 37,160,238, 88,190,219,242,166, 40, 56,119,228,157, 61,123, 22, 17, 17, - 17,184,124,249,114, 77,157, 25, 54,108, 24,151,155,155,139,241,227,199,223,235,166,242,242,146,137,197, 98,168,213,234,122,229, - 73,207,158,133, 50,162, 13,250, 93, 62, 81, 35,239, 77,191,199, 98,162,114, 85, 50,106,188,248, 30,197,169, 56,159,134, 72,108, -178,212,204,134,149,128,133,104,215,238, 55, 0, 67, 56,112, 60,220,168,120, 67,199, 48, 96, 12, 22,231,216,197,138, 10,220, 48, -208,155,248,132,104, 64,136,169,160,180,116, 91, 99,249,215, 86,218,109, 33,128,212,252,163,243, 11,197, 97,147, 21,165,101,226, -118,101, 37,167,196, 16, 4,117, 42, 44, 50,135, 87,149,221,132, 80, 40, 8,237, 25,230, 61, 77,169, 49,125, 11,224,166, 35,203, -213, 58,247,223,225, 48, 64, 66, 66, 66,108,102,102,102,142,203,236, 94,103, 8,224, 31, 16,168,219,100,175,128,139,223,231,154, - 42,111,212,168,145,156, 76,150, 3,178,205, 18,143,125, 96,177, 47,198, 44,215, 96,228,200,145,112,113,218,223, 61,176,141,213, - 63,252,240,195,186,102, 80,232, 20, 65, 65, 65,211,237,140, 83,163, 92, 46,223,227,228,119, 25, 0,229,187,118,237,146, 61,245, -212, 83,209, 43, 86,172,232, 99, 54,155,137, 68, 34, 65, 92, 92, 28,126,249,229, 23,176, 44,139,113,227,198,113,243,231,207, 39, -253,250,245, 51, 78,158, 60, 57, 50, 33, 33,225, 78,191,126,253,234, 87,192,230, 36, 51, 49,143,140,217,212,171,119, 31,255, 83, - 39, 79,174,252,157,207,239,213, 33,178,195,151,126,193, 33, 37,130, 16, 49,119,120,223,161, 64,185,162,106, 68,120, 80,200,251, - 93,186,116, 57,236, 19,230,189,254,147,101,159,211, 13,201,115, 85, 1,224, 1,136, 6, 48, 12,192, 50, 0,175, 89, 43,131,119, - 29,242,251, 6,150,113,246,127,193, 50, 36,144,215,136,135,225, 33,171,245,235,140, 59,254,184,213,187, 64, 53, 34, 47, 4, 64, -164,149,152, 27,147,121,218,250, 92, 40, 44,227,249, 13,201, 19, 90, 45,231, 36, 88,166, 17, 62, 3, 32,223, 42, 59,223,122,190, - 25,150,113,242, 77,176, 12, 93,208, 14,228, 77, 1,240, 5,128,110, 86, 37,201, 62,157,183, 97, 9, 90,188,108,125,246, 7, 7, -242, 94,135,101,118,131,206,137,252,243, 2,176, 31,192,119, 14,202,227,105, 0,255,177,126,254,110,151, 62,129,181, 44, 51, 1, -172, 1,176,220,122,255,118, 67, 63,152,149,149,149, 3, 0,197,197,197, 50, 91,180,127, 93,171,191,184,184, 88,102,255,108, 99, -176, 61,179,233, 87,186, 38, 58,191,174,149,190,233, 87, 26, 15, 66, 94,110,110, 46, 70,140, 24,129,203,151, 47,223, 37,113,169, - 52,118,235,214,173,178, 14, 29, 58,196,178, 44, 43,139,140,140,228, 88,150,133, 94,175,199,207, 63,255,140,232,232,232,216,125, -251,246,213, 43,175,107,110, 46,190, 15, 14,173,149, 87,221,231,142,129,118,229, 77,224,209, 80,112, 44, 48, 39,242, 43,174,154, -245,129, 92,239, 7,121,126, 16,250,142,216, 29,123,105, 71,227,110,246,107, 37, 37,219, 1,108,239, 24,209,182, 43,128, 55,140, -102, 22,219,206, 23, 98, 68,152,101,184,147,112,156, 70,195, 48,203,202,203,203,239, 56, 65,166, 43, 57,142,243,206,191, 44,127, - 86,121,122,107,171,242,219,114,148,223,209,128,207,175,242,174, 86,112, 80,170,205, 92,104,136, 48,128,207, 98,146,222,104,254, -126,217,235, 15, 7,252,235,147,227, 74, 7, 68,147,227, 68,167, 77, 92,137,100,191, 7,163,173,158,151,236, 68, 87,191,105,243, -134, 57,138,202,183,127,142, 56, 43,143, 36, 42,208, 68,121,247, 88,236,153,153,153, 24, 56,112, 96, 75,210, 69,184,156, 57, 23, - 0, 27,249,159,103,176, 65,102,105, 99, 77, 37,127, 91,221,224,241,120, 33,124, 62,191,252,248,241,227, 95, 62,252,240,195,238, -174,243, 0, 0, 17,114,185,124,157, 85,177,152, 34,151,203,127,176,125, 58,227, 84, 4, 80, 13,160,114,197,138, 21,125,231,205, -155, 87,122,246,252,249, 54,122,189,158,200,100,135, 32, 18,139, 64, 17, 10,135, 14, 29, 34, 61,122,244,208, 37, 36, 36, 12,158, - 60,121,178,195, 54,151,115,232, 0, 51,225,169, 9,107,250,246,237,223,129,102,140,143, 95,203,191,250, 34, 91, 88,240, 2, 0, -136, 65,113,189, 59,117, 61, 21, 26, 26,146,195,227, 11,223,254,207,226,148,234, 79,150,125,236,118, 70,214,167, 0,188, 97,213, -134,198, 3,184, 4,192,167,158,239,237,181, 90,236,241,176,204, 35, 79,106,196,253,223, 25,150,232,114,103, 20,128, 42,235,243, -188, 70,228,197, 0,184,234,164,188,171,214,231,119, 52, 34,111, 22,128,153, 0, 46, 0,152,111,125, 47,123,217, 50,171,245, 63, -199,106, 13,111,180, 90,217, 13,201,155, 97,205,143,126, 86, 47, 66,125,233, 84, 91,239,219, 60, 1, 27, 27,145,247,181,181, 83, -240,114,178,243,250,218, 65,254,125,100,245,108, 28,176, 42, 53,168, 35,251, 23, 0, 61,172,101,145,111, 85,164, 28,186,118, 87, -175, 94,205, 1,144, 53,211, 66, 64,100,230, 26, 45, 55,115,141,182,158,133,123,220, 10,114,106, 22,121,127,254,249, 39,249,243, -207, 63,107, 93,251,238,187,239,114, 0,144, 31,126,248, 1, 0, 72, 81, 81,237,152,186,134,200, 31, 0,218,255,249, 39, 1,106, -203,123,249,131, 5, 22,114,252,208,154,166,186, 33,122, 59, 92,232,133,205, 92, 33,248, 0,175, 26, 53,228,111,101,245, 59, 98, -177,216,169, 69, 68, 56,142, 35,132,144, 37, 11, 19,123,122,133,181,139,156,192,194,171,115, 73,113, 25,207,100, 80,114,173, 67, -125,136,143,183,128, 48, 38, 22, 10, 37,205, 16, 9,145,168, 52, 76,167, 70, 12,130,134,234,108,221,255, 31,164,139,222,126, 56, -162, 33, 98,225,224,222, 44,128,230,144, 87,175,197,222,161, 67, 7,156, 62,125,186, 69,144, 63,251, 67, 32, 14,156,103, 0, 0, - 27,101, 52,190, 63, 78,219,188, 48,164,185,202,199,108, 54, 87, 1,192,128, 1, 3,154,180, 32,144,141,252,173,168,180,126, 58, -187,192,142,208,106,152,157, 1,128, 79, 63,253, 52,252,249,153,207, 47,122,104, 96,244, 12,141, 90,237,207,152, 25, 83, 88, 88, -216,157,240,240,240,171,106,181,122,249,228,201,147,243,157, 77,215, 79, 63,254,196, 0,120,237,217,233, 47, 14, 31, 54,124,248, -120,137, 68,210,138,128, 51, 91,102, 78,112, 85,122,173, 98,221,149,243,197,183,189, 69,194, 38, 45,124, 87, 87, 1, 48,195, 18, -164,230,204, 56,252, 41,235, 97, 70,195,203,139,154, 97,137,168,119,118,190,166, 12, 64,182, 3,121,187, 96, 9, 90,115, 6,207, - 58,145,190,207, 1,124,233,168,239, 7,240,170,221,119, 26,147,247,141,213, 99,224, 8,133, 86,203,222,153,244,185, 50,223,245, -115, 7,242, 30,117, 66,158,205,219,176,209,154, 55,206, 44, 31, 75,226,226,226, 98,234, 70,253, 91,221,234, 57,238, 52,244,184, -184,184, 24,187,149,250, 90,154,188, 22,143,235,165,183,141, 84,187,118, 27, 95, 89,153, 62,211,118,141, 22, 80,223, 25,116,236, -254,178,226, 98,141, 83,153, 70, 8,247,159, 89, 67,200,123,159,255,182,240,231, 53,161, 59, 79,156,188, 61, 59,196,159,125,146, - 10,242, 11,224, 56,128, 16,206,104,100,216, 50, 22,168,164,141,108, 64,233,109,189, 75,171,147, 89,221,252,178, 58,231, 45, 37, - 11, 91,220, 74,128,127, 23, 60,182, 92,115,191,223,145, 5,208, 70, 44, 22,223, 30, 48, 96,192,163,103,206,156,105,178, 64,185, - 92,126, 48, 40, 40,104,166, 92, 46,223,232,130, 2,192, 88, 61,167, 0,128, 13, 27, 55,164,192, 50, 60,221, 44,248,246,187, 47, -127,133,101, 40,246,190,160, 62, 5,192,224,142,214,215, 72, 33, 25, 61,242,254,177,242,106,193, 74,164,164,206, 53,183, 43,103, - 75,151,247,119,128, 92,167,123, 1,240, 50, 1, 8, 97,193,149, 26, 12,244,230,178,178,138,115,214,142,203, 41,188,247,249,111, -220,143, 31,141, 37,227, 95,219,159, 11, 32, 55, 97,112,215, 55,130,130, 68,139,248, 60,194,221,174, 50, 92,185, 77, 51,155, 36, - 2, 74, 44,225,243,120, 38,134, 21,187,146,190,204,204,204, 28,219,242,182,214, 79,183,148,177,123,166,254,217,185,254,157,152, - 22,216, 88,189, 39, 46, 92,255,171,229,221, 55,197,167, 41, 74, 24, 53, 69, 1, 66, 8,158,156, 56,171,222, 62,100,215,143, 25, -205,245,174,101, 0, 72,115,144,191,157, 18,176,209,133,199, 3,173,237, 72,251,119,237, 31,248,245, 84,196,230,140,152,241,200, -251,103,203,243,160,165, 43, 0,114, 57, 39,151,203,103, 53, 85,206, 83,111,238,231, 0,224,217,145, 61,200,183, 71, 46,126,172, -231,230,172,121,109,234,241, 30,180,150, 68, 5, 9,248,173, 64,136,206, 71,194,175,232,213,205, 47,127,219, 1,215,100, 91, 93, -217, 77, 89,111,254,126,145,231,223,197, 3, 64, 90,146,215, 36, 35, 35,157, 75, 78,158, 77,118,253,152,241, 79,111, 94,225, 86, -131,217, 23,150, 61, 1,254,118, 32,238,238, 35,236,129, 7, 30,252, 13, 53,126, 30,224, 37, 34, 96, 89, 14, 32, 4,213,122, 79, -243,247,192,131,255,217,254,192,147, 5, 30,120,240,191, 3,198, 12,168,117, 78, 47, 59,239,129, 7, 30,252,131, 65,121,178,192, - 3, 15, 60,240,192, 3, 15, 60, 10,128, 7, 30,120,224,129, 7, 30,120,224, 81, 0, 60,240,192, 3, 15, 60,240,192,131,127, 34, -106,197, 0,156, 61,123,214,237,104,212,250,130, 9,235,147, 55,254,145,232,152, 94,125, 58,201,218,180, 11,143,213,232,181,178, -195,178,220,216,172, 67,231,114,220,149,215,123,240,152,152,126,125, 6,203,238,148,150,194, 91,226,141,155, 37, 5,177,121, 39, -246,186, 45,175,185,223,119,238, 52, 42,102,200,224, 14, 50,137, 55, 15,124, 30, 5, 34, 38,120,114,234, 69,226,174,188,228,255, -151, 27,243,208,224,135,100,254, 62, 60,128, 15, 36, 12,174,127,142,211,131,122, 95,143,188, 22, 43,175,209,169,102, 45,253,125, - 59, 12,120,154,243, 99, 11,238,107,250,126,127,183,200,237,142,180,255, 7,145,247, 92,251,184, 85,169,219,242,222,168,188,119, -195, 85, 79,125,254, 75,228,241, 81,207, 20, 89, 87,228,197,198,198, 70, 25, 12, 6, 69,110,110,174,242, 65,190,175,203, 10, 64, - 67, 88, 29,131,206, 0, 58,192,178, 78, 64,193,252, 28,220,112,246, 7,198, 12,239, 16, 67,192, 34, 36, 32, 8,185,135,207,200, -222,153, 59, 3,195, 70, 15, 3,163,213,201,122,116, 27, 9,150,133,108,222,139, 15,199,246,239,223, 7,215,174, 21, 65,165,212, - 98,237,198, 35, 57, 13,201, 27, 56,226,153, 24, 14, 4,145,157, 58,200,146,223, 92,142, 23,158,121, 12,223,252,247, 51, 0, 98, -236, 61, 87, 2,138,130,108,245,146,197,200,207,191, 2,169, 52, 18, 34, 9, 31,183, 74,242, 99,161,171, 63,201,139, 30,235,203, - 9,133, 66, 72, 36, 18, 20, 20, 20,160,109,168, 31, 90,241,125,208, 54, 34, 0,129, 18,127,120, 19, 51, 40,138, 2,199,154,161, - 19,241,161,186,163,194,164,255,102, 57, 44,168,212,133,125, 56, 95,137, 10,126, 1, 66,248,120,243, 33,148, 80,224,243, 0, 74, -200, 71,206,207,209,156,137,227, 33,110,194, 9,167, 11,188,247, 83,171, 99,194,195,195,209,174, 99, 59,153,222, 96, 4, 37,146, - 0, 38, 96, 78,218,169, 24,189, 78,139,175,254, 21,147,243, 0, 21,201,150, 54,143,249,127, 25,174,150,133,211,207, 39,188,179, -200, 27,192, 67,173, 37, 94,255, 41, 45, 45,237, 38, 16,139,192,122,121,125, 8, 96,125,230,135, 41,213, 45, 37, 3,162,122,140, -138,185,113,241,112,125,123, 13,252, 35,234,104, 70, 70, 6,249,102,211,166,203, 34,161, 80,194,178,172,191,183,143,143,207,132, - 39,159,244, 2, 64, 39, 39, 39,115, 45, 52,205, 20, 0, 36, 39, 39,179,205, 32,206,207,223,223,127, 65,215,174, 93, 39,139, 68, -162,118, 37, 37, 37, 37,165,165,165, 39,105,154,254, 0, 64,129, 27,242, 2, 2, 3, 3,151, 63,242,200, 35,143,135,133,133, 73, - 79,157, 58,117,231,194,133, 11,199, 13, 6,195, 82, 88, 86,136,117, 26,163, 70,141, 74,141,136,136,120,219,219,219, 27,190,190, -190,167, 15, 28, 56, 16,253,183,241, 0, 52, 64,254, 60,111, 17,255,161, 25,195, 59,174, 98, 57,206,112,244,202,157, 79, 87,199, -168, 14,204,207,193, 69, 71,223,149,223, 62,200, 25,171,229, 48, 85, 43,193, 55, 83,248,227,226, 21, 60,247,220,252,154,251, 20, - 5,252,150,187, 17,173, 34,194,101,108,181, 26, 52, 75,112,232, 80,110,236,218,141, 71, 26,144, 24,201,157, 62,113, 17,196,203, - 15,103, 46, 22,227,220,197,231,241,213,247,191,212,220,101, 89, 96,236,208,161, 64,117, 25, 0, 95, 20, 92,184, 4, 65,171, 0, - 12, 27,210, 75,166,212, 53,162,179, 16, 10, 32, 20,250,245, 25,128,214,222, 66,180,109, 37,134, 95,112, 16, 2, 69,190, 8, 20, -243, 32,224,241, 96, 50,155,161,100, 88,156,170,116,188,220,230,210, 87,219,115, 18,158, 2,126, 94, 94, 8,105, 21, 12, 63, 63, - 47,112,148, 25, 12, 91, 13, 51,204,240,241,241, 66,171,214,237, 80,112,185, 11,215,177,219, 55,141,118, 74,253,227,215,112,254, -190,222,240, 15, 8, 68, 72,171, 96,104,181, 90, 8, 69, 98, 8, 12,150,197,249,162,164,145, 50,185, 66,137, 71, 94,220, 24, 91, - 92,114, 11,138,178, 34, 84,157,203,112,164, 12, 56,221, 73,140,158, 57, 58, 54,123, 99,118,142, 19,178,238,171, 18, 80, 88, 88, -200, 1,128, 84, 42, 37, 45, 69, 94,120,120,248,115, 52, 77,111, 4,128,201,177,177, 84,198,214,173,238,116,190,150, 53, 82,237, - 28, 57, 28,199,129, 16, 82,243,105,187,102,123,206,193, 78,106,174,172, 39,239, 10,249,247,240, 54, 49,219,125, 3,252,187, 1, -128, 80, 34, 6,173, 55,128,213,234, 82,143, 31, 57,188, 36,225,157, 69,221, 51, 63, 76, 41,118, 36,231,211,119,231,114, 86, 11, -139,129,101, 8,146,181,246, 67,245,246, 69,125, 71, 61,142, 81,143, 61,225, 82, 25,221,184,120, 88,214,169, 87, 76,236,181, 63, -114, 92, 87,138, 19,228, 46, 61,158,152,152,136,173, 9,217,141, 62, 19,155, 93,123, 43,146, 30, 1,150, 87, 45, 55,176,208, 51, -150,114,213, 90, 63, 51, 6, 7,160,139,175,160, 81,121,171, 86,173,202,121,247,245,183, 66, 39, 78,158,228, 99, 48,232,177,250, -227,143,168,181,107,215, 26,230,206,157, 27, 14,224, 86,115,183,189, 73,147, 38,141,222,185,115,103,150,171, 74,212,204,153, 51, -185,194,194, 66, 84, 85, 85, 97,197,138, 21,240,245,245, 69, 76, 76, 12,164, 82, 41, 54,110,220,232,110,187, 27, 57, 96,192,128, - 77,111,190,249,230,181,174, 93,187,110,236,223,191,255,165, 59,119,238,180,203,205,205, 29,240,194, 11, 47,236, 81,171,213,169, -176,108, 0,231, 44, 98, 39, 79,158,156,153,146,146, 18,108, 50,153, 32,145, 72,224,237,237,221, 70,171,213, 62, 61,113,226,196, - 9,231,207,159,159, 11,224,191,206, 10,139,136,136,104,187,104,209, 34,228,229,229,113, 26,141, 38,160,206,109, 30,156, 91, 85, -181, 89,112,246,236,217,186, 94, 2,231, 20,128,213, 49,104, 15,203, 14,120, 60, 0,102,173,145,185,153,123,181,252,147,161,157, - 67,231, 63,210,163,205,146,214,254,146,182,171, 81,182, 5,192,149,249, 57, 13,111, 82, 99,172,150,163,117,167, 71,177,252,237, -201,216,104,199, 73,135,143,167, 67,171, 51, 98,220,232,249,120,120,216, 76, 60,147,248, 8, 36, 18, 17,104, 51, 3,141,142,150, - 53, 92,201,138, 0, 26,152, 60,125, 61, 94,126,115,118,205,213,177, 15,199, 64, 44, 22,225,199, 67,191, 96,239,177, 92,108,218, -240, 25, 12,122, 35,132, 60, 62,124,188,132,208, 86,149,196, 42, 75, 80,239,238, 99, 28,199, 1, 28,107, 57, 40, 22, 28,199,193, - 72,139, 44,221,147, 8,224,104, 51,204, 60,192, 12, 51,204, 52, 11,198,220,184, 2,187,240, 69, 41, 23,232,199,192,207,215, 27, -225,237,162,208,173,119, 39,248,250, 72,160,170,174, 64, 89, 69, 25, 20,170, 59, 48, 25, 8,188,188,188, 16, 18, 50, 12,149,229, - 33, 92,171,208,143,234,119,227,143, 92,204, 49,122, 29,244,124, 64, 40, 22, 66,175, 19,130,214, 9, 97, 16,139,192, 39, 12, 56, -240, 96,208, 87, 67,175,211,160, 93,187,182, 50, 33,143, 15, 57,212, 8,165,167,163,238, 26,243,117,177,114,211, 74,135, 21,232, -237,164,183, 27,239, 43, 19, 18,106,237,239,158,144,144, 48, 48, 40, 40, 40,159, 16, 98,224, 56,142, 31, 24, 24,232, 85, 80, 80, - 16,108, 93,221,173,173,187, 21,121,238,220,185, 83,237,126, 35,198,221,213,226,234,101, 75, 66,184, 57,115,230,196,174, 93,187, -214, 37,153,225,225,225,201,131, 6, 13,250, 96,120,191,126, 48,137, 68, 72, 75, 75, 99,103, 79,153, 18,151,254,195, 15,217, 46, -254, 62, 86, 45, 89, 82,115,190,224,253,247,145,182,116,105,163,231,206,136,173, 67,238,156,117,179, 24,110,244,232, 14, 61, 1, - 92, 79, 73,201,212,187, 72,254,185,189,123,246,244,179,181, 25,111,177, 4,183, 43,202,161, 86, 40, 49, 96,208, 96,175,159,191, -218,144,157,240,206,162,158,153, 31,166, 56, 90,155,157,153,247,193, 90,254,179, 79, 79,224,119,150, 74, 89,171, 18,128,247,211, -214,212, 86,162, 23,188, 6, 0,120,247,245,185,110,109, 39,237, 22,249,219,144, 25,228,194,195,163, 93, 18,237,205, 39, 56,183, -244, 69, 16,191, 86, 48, 95, 63, 7,227,245, 63,145, 47,215, 34,122, 95,185, 83,223,239, 63, 96,192,209, 89,211,146, 34,147, 94, -122, 33, 32,243,187,239, 89,169, 84, 74, 45, 79, 73,133,239,146,229,248,241,199, 31, 75, 51, 50, 50,168,230,242, 2, 76,154, 52, - 41,110,231,206,157, 7,118,238,220,105, 59, 31, 99,251,223,129,130, 18,115,224,192, 1, 89, 81, 81, 17, 58,118,236,136, 17, 35, - 70,192,223,223, 31, 74,165, 18,183,110,221,194,141, 27, 55, 48,102,204, 24,110,204,152, 49,177,111,189,245,150, 43,229, 52,233, -145, 71, 30, 89,189,106,213,170, 45,253,251,247, 95, 77, 8,185,101,215,143,147,248,248,120, 31, 0,185,214,195, 41,121,115,231, -206,221, 54,103,206, 28,234,244,233,211, 32,132, 32, 56, 56,184,230,216,183,111,159,112,200,144, 33,159,221,188,121,243,132, 35, - 65,147, 39, 79, 38, 59,118,236,224,138,138,138, 34,242,243,243,113,253,250,117,162, 82,169, 58, 2,224, 79,156, 56,209,188,107, -215, 46,238, 65,146,191,237, 90, 93, 37,128, 95, 15,249, 7, 71, 71, 5, 39,245,139, 12,154, 78, 8, 17,112, 28,103, 98, 45, 7, -109, 54, 25,244, 66,138,109,219,187,181,248,237, 86,126, 29, 59,237, 60,117,227,251,213, 49,236,209,249, 57, 13,239, 22, 7, 8, -209,163,123, 87, 80, 84, 14,242,149, 85, 0, 46, 65, 85,122, 21, 2,177, 8,187,246,124, 10, 93,165, 25,211,159,127, 3, 44, 11, - 60, 57, 97, 40,204,124, 31,135, 47,151,159,127, 9, 44, 11,140,235, 75,172,188, 18, 9,131,145, 70,252,216, 49, 16, 7, 80,216, -180,121, 63, 40, 10,216,246,253, 70,148, 94,255, 51,118,223,150, 85, 57, 13,109,151,200,114, 0,203,178, 96, 89, 22,102,179, 25, - 70, 1, 7, 19, 49,129,166,105,232,188, 12, 0, 43, 6,197,153, 97, 22,114,168,166, 13,208,170, 85,141,166, 45,196,199, 8, 62, - 95,130,224,224, 96,116,234,212, 9, 97,173, 7, 3, 60, 10,102,243,105, 80,156, 18, 6, 45, 3, 51,171, 69,217, 45, 57, 66,130, - 43, 17, 28, 48, 12, 31,174,250, 57,230,251,111,239,149, 37, 49, 48,224,140,149,128, 65, 4,154, 50, 65, 43,228,163, 90, 34, 0, - 95, 32, 4, 88,111, 16, 30, 65,181, 86, 7, 69, 89, 17, 10, 78, 31,131,188,184, 24, 44,203,130,226,120,110, 85,154,175,214,223, - 85,156, 95,120,229, 5,199,253,100,237,213,199, 12,153,153,153,139,222,124,243,205,217,197,197,197, 20, 33, 36, 36, 35, 35,227, -123, 88, 54,119,242,114,183, 34,207, 74, 72, 16,172, 91,183,110,243,157, 59,119,176,109,219, 54, 68,119,237,202,107,142, 6, 34, -149, 74, 73, 98, 98, 98, 12,199,113,178,181,107,215,186,188, 97, 17, 77,211,233,195,173,117, 74, 40, 20,162, 75,151, 46,216,126, -232, 80, 86, 72, 72, 8, 42, 42, 42,156,150,115, 31,183,170, 37, 3, 7, 14,228,108, 27,196,216,125,254, 57,106,212,168,210, 69, -139, 18,252, 83, 82, 28,175, 30,151,240,206, 34,111,111, 19,179,189,119,207,158,126, 60,138,194,171,207, 78,135,222, 96, 68,218, -151, 95,194, 75, 34,129,193, 96,128, 65,175, 71,223,254,253, 58,255,242,221,119,115,208,240, 86,222, 53,125,206,210, 5,175,177, - 0,168,171,133,133, 84, 93,194,175,219, 60,221,121,241,246,221, 70,198,222,188,124,132,139,123,242,197,216,172,221, 95,186,165, - 8,216,239,218,199,109, 13,116,120,221, 17,122, 4,240, 81, 84,109,198,225,184, 16, 8,230,103, 64, 61, 61, 10,252,192, 80,151, -200, 63, 49, 49,177,204,164,213,221,122,233,213,217,237,223,121, 99, 33,214,110, 72,191, 56,104,192,128, 14,233,107,210,189, 94, - 95,248, 22,190, 27, 58, 24,155, 55,111,158, 1,203,174,165, 77, 33,254,152,157, 59,119,202,108,100,159,145,145, 81, 0,203, 54, -237, 7,157, 81, 0, 14, 28, 56, 32, 11, 9, 9, 65,255,254,253, 25,138,162,248, 22,239, 44, 11,129, 64,128,160,160, 32,180,110, -221, 26, 55,110,220,192,129, 3, 7,100, 46,180,185,132,241,227,199,127,180,106,213,170, 53, 93,187,118, 93, 79, 8, 97, 1,124, - 6,224, 49, 0, 71, 8, 33, 75, 97,217, 95,229, 45, 0, 75,157,145,183,106,238,220, 31,134, 39, 36,144,221,187,119,131,207,231, - 67, 38,147,225,220,185,115,232,212,169, 19,150, 45, 91,134, 94,189,122, 97,246,236,217,252,247,222,123,111,149, 35, 97, 59,118, -236,224, 0,192,203,203,235,118, 64, 64, 0,196, 98, 49,132, 66, 97, 53, 0,198,129,199,238,190,145,255,172, 69, 31,214, 92,251, - 60,229,157,122,149,128,250,102, 1, 80,124, 30,197,103, 88, 78,163, 55, 49,183, 8, 33, 34, 31, 17,175,143,159, 16,209,146,158, -163, 58, 34,246,101,160,219, 8,180,241,230, 38,205, 24, 22,245, 78,144,159, 87,220,234, 24,248, 55,156, 28, 22, 60,158,173,207, -246, 3,208, 14,254,225,227,161, 55, 27,176, 62, 99, 3,190,217,188, 13, 99, 98,135, 1, 0,116, 58,128,199,111, 88,148,196,171, - 43, 0,192,108,182, 87,164,202, 0,228,130,226,137,144,244,220,139,136, 79, 76,196,207,123, 44, 68,230,229, 13,104,171,111, 55, -154, 89, 38,240,106,200,223,196,152, 97, 84,155,160, 83,234,160, 52,209,144,235,104, 40,140, 26, 40, 53,213, 80,148,107, 32, 87, - 26, 32,175,110,120, 9,245, 87,159,233,192, 17, 66,192,227, 17, 16, 74, 4,179,153, 3,163, 43,134, 86,121, 21,165,101, 42,200, - 21,213, 80,105,204,144, 43, 12, 40, 41, 41,195,197,203,103,161, 84,157,197,224, 1, 3, 27,220, 27,157, 7,128,210, 24,160,191, -118, 11, 85,127, 92, 66, 85,113, 17,212, 42, 57,212, 42, 57,138, 46,158,198,241,204,175,144,187,117, 19, 42,174, 93,131,153,102, - 45,173,137,247,151, 13, 3, 18,235, 65,199,199,199,119, 95,190,124,249,155,109,218,180,209,110,219,182,173, 79,102,102,230, 79, - 0,250, 91, 11,221,237, 5,167,132, 97, 97, 11, 0, 96, 72,175, 94,152, 51,103, 78,249,169,203,151,179, 31,234,214, 45,166, 57, - 18,191,117,235,214, 28, 0,100,238, 92,139,149, 57,119,238, 92,151,228,154, 68, 34, 0,192,246,237,219, 17, 26, 26,138,119,230, -206,197,130, 5, 11, 16, 18, 18,210, 34,198, 97,109,164,159,145,145, 81,115, 0,192,225,195,135,195, 1, 76,112, 82,204, 67, 1, -129,129,221,120, 20,133,231,227,227,161, 84,169, 81,114,251, 22, 4, 2, 62,248,124,203, 33, 16, 8, 32,146,120,161,163, 84,250, -113,255,209,163,157,178,216,175, 22, 22,226,219,237, 63,213, 28, 54,188,159,182, 6,239,167,173,193, 94,217, 97,151,223,119,116, -194,123, 49, 0,112,243,242,145,156,209, 22,242,151,161,133,172,118,116,254,235, 79, 80,254,242, 0,140,202,170, 64,143, 0, 62, -120,126, 65, 96, 20,229,136,222, 87, 14,111,190,133, 31,120, 14,230,100,221,184,118,173,234,243,140,255,118,253,250,191, 95,227, -211, 47, 63, 43,250,108,213, 71,239,191,249,218,188, 9,203, 63, 88, 14,137,175, 55, 70, 12, 25,134, 83, 39, 79,125,253,108,210, -179,110,191,179,141,252,109,231,187,119,239,198, 67, 15, 61,212, 17,192,116,103,221,254, 38,147, 9, 3, 6, 12, 96,205,102, 51, - 95,165, 82,193,104, 52,194,104, 52,226,242,229,203,144,201,100, 56,118,236, 24,218,180,105, 3,147,201,132,153, 51,103, 58,147, -214,169,137,137,137,159, 76,158, 60,217,111,253,250,245,126,132, 16, 33,128,195, 0, 84, 0, 6, 0,248,201, 78,241, 60, 8,160, -151, 35,121, 59,223,124,243,135, 9,125,251,146,239,226,227, 81,250,251,239,248,232,163,143,216,159,127,254,249,255,221,188,121, - 51, 84, 38,147,189,188,104,209, 34,152, 76, 38, 12, 27, 54, 12,222,222,222, 67,157,205,191,128,128,128,202,214,173, 91,195,199, -199,135,243,246,246,190,105,205,195, 7, 94, 7,237,149,129, 70, 61, 0,243,115, 80,177, 26, 21,233,191, 93,171,200,138,142, 10, -142, 29, 40, 13,178,172, 35, 62,126, 25,126,243, 25,131,131,127,148, 99,104,207, 64, 60, 34,253, 25,190,191,124,208,127,108, 63, -233,244,205, 71, 46,254, 81,159,240, 54,157, 19, 8,199,149,112, 19,159,155,143, 5,175,125, 6, 64, 14,203,178,201, 70, 68,118, - 29, 0,177,136, 15,189,214, 8,208, 22, 5,193,215,215, 23,229,242, 6,247,203,134, 94,119,133, 0,224, 46,254,246, 37, 40,106, -109, 45, 35,129,213,255, 9,131,209, 4,137,143, 24, 16, 90, 20, 4,141, 90,141,161, 67,135,226,200, 79,223, 53,108,142,176, 52, - 88,150, 15,134, 97, 96, 52, 26, 81,205,231,129, 79, 83,192,109, 53, 24, 47, 6,102, 33, 11, 78,192,131,142,199, 7,163,213, 65, -105,108, 56,214,201,215, 71, 11,134, 33, 48,210,102, 40, 85,106,228, 95, 43, 70,201,237, 74,232,105, 19,212,213,114, 84,107,148, - 48,152,105, 16, 62,129, 86,167,130, 90,119, 3, 69,165, 42, 84,105, 26,222, 75,194,108,167,165, 49, 42, 45, 74,206, 94,194,157, - 75, 55,160,214, 92,131, 70,169, 4, 7, 62, 4, 60, 2,142, 8, 64, 81, 22,175,175, 43,234,230,219, 73,111, 59, 53, 28,224, 0, -119, 0,220, 89,188,120,177, 30, 0, 22, 45, 90,116, 42, 37, 37,197,219,154,116, 3,128, 98,119, 5,175, 91,183,110, 69,124,124, - 60, 0, 32, 42, 36, 36,212, 58, 38,206,107,206,198, 97,115,255, 91, 61, 1, 14,179, 47, 60, 60,124, 52, 77,211, 72, 75, 75,195, -211, 79, 63,141,201, 99,198,220,237,232,207,159,183,120,130, 66, 66, 56,103,227, 2, 22,188,255,126,205,152, 63, 0,188,181,100, - 73, 45,207,128,147,110,255, 90,176, 89,255, 54,210,183, 33, 35, 35, 3,201,201,201,200,206,190,254, 45,128,239, 28,118,104,124, -254,127, 12,180, 17, 60, 30, 15,151,175, 23,128,227, 56, 92,204,191, 10,154, 54,129, 2, 1,159,207, 7, 33, 4,172,217, 12,189, - 86,135,171,191,253,118,200,137, 60,164,236, 73,255,217,167, 39,216, 91,252, 20, 0,156, 56,115, 30,157,163, 34, 93,154,166,156, -157,249,159, 26,107, 63,219, 98,249,219,134, 66,184,199, 39,189, 24,187,111,167,123,222,128,102,129,252, 54,132, 17, 93, 80, 62, - 71, 12,209, 35, 83, 97,206,219, 15,179,218, 18,111, 80, 62,231, 97, 68,102,228,194,204, 54, 94, 85,186,118,238,218,214,203,203, -219,235,211, 47,214, 25, 98, 71,141, 18, 14, 30, 58,228,187, 3,123,127,121,252,242,181,124,128,229, 32, 22,137, 48,108,224, 48, -236,217,189, 7, 99,199,142,229,246,239,223,239,116, 87, 80,215,234, 63,112,224, 0,174, 95,191, 78, 3, 16,158, 60,121,146,158, - 61,123,246,180,140,140,140,103, 29,201, 41, 44, 44, 68,199,142, 29, 1,128, 42, 44, 44,196,185,115,231, 16, 25, 25,137,168,168, - 40, 40, 20, 10,228,229,229,161, 67,135, 14, 8, 13, 13, 69,100,100, 36, 10, 11, 11, 27,175, 40, 20,149,148,152,152,248,193,200, -145, 35,125, 78,157, 58,229,199, 48,204, 75, 18,137,100,162, 94,175, 95, 5,203,214,231,176, 42, 0,107, 96,217,157,143, 70, 35, -211,219, 5, 2, 65, 82,230,188,121, 27, 31, 14, 9, 33, 21, 11, 23, 98, 40,203, 98,205,238,221, 92,169, 78,247, 34,238,110,203, -190,241,226,197,139,235, 25,134,225,251,248,248, 32, 60, 60,220,199,100, 50, 65, 32, 16, 56,122,125,175,210,210,210,174, 55,111, -222,132, 86,171, 37, 10,133,162, 59,159,207,143, 99, 24,166,197,238, 56, 86,223, 16, 64, 24,128,142,147,162, 35, 94,109, 31,236, - 61, 29, 38, 61,208, 53, 14,103, 66, 38,225,145,185, 95, 65, 95,169, 4,207,207, 23,178,213, 73, 24,209,227, 55, 4,157,207, 26, - 9, 32,162,161, 31,232,228,215, 14,127,156,223, 97,231,112,208, 2, 48, 89, 14,147, 17,124,150, 7,202, 74,226, 59,127,116,188, -139,200,254, 11, 28,198,246,239, 85,199, 8,229, 3, 16, 0, 2, 49, 24, 98,134,213, 14,198,148,233,243, 0, 64,150,242,238,220, - 6, 27,130,153,229,192,176, 20, 40,134, 1, 69, 27,161,163, 44,117, 71,207,227,193,155,209, 67,173,231, 64, 4, 4,102,179, 25, - 58, 51, 80,174,109,120,183, 83,134,102, 97, 16,240,192,234, 24, 48,172, 10,154,106, 19,120, 68, 0, 35, 99, 2,205,209, 96, 76, - 52, 32,100, 65, 17,128,136, 88,168,244,102,148, 85,232,160, 53, 50,245, 26,201, 20, 49,215, 12, 26, 17,114,119, 72,215,100,208, - 67, 37,151,131, 34, 60,240,249, 28,192,241,193, 35,238,155, 58, 87,138,174,208, 93, 35,187, 10,157,113,251, 55,164,155,193,110, - 15,237,148,148,148, 9, 0,110, 46, 90,180,168,191,191,191,127,128, 74,165, 42, 74, 73,113,125,135,204,185,115,231,190,176,110, -221, 58,180,110,221,218,254,154,114,205,154, 53,217, 15,117,235, 54,250,212,229,203, 7,155,171, 33,204,157, 59, 55,214,110, 40, -160, 49,242,143, 25, 52,104, 80,248,240,126,253, 64,124,125,145,146,146,130,133, 11, 23, 66, 32, 16,192,164, 80,192,223,223, 31, -239,204,157, 91, 19, 23,144,156,152,232, 80, 9,168, 59,198,239, 40, 38,160,177, 17,133,186,214,191, 3,239,128,195, 42,163,144, -203,187,249,248,250,162, 82,161,128,236,196, 9,240, 41, 30,140, 38, 19,116,122, 61, 88,150,173, 81, 92, 24, 19, 13,218,104,116, -102, 72,131, 5, 64, 89,135, 1, 88,187,138,111,176, 94,199,251,105,107,132, 0,208, 89, 42, 45,191, 81,191,109,225,146,151,170, - 93,199,232,152,125, 59,191,116,197,221,220,112, 6,187,224,246,175,229,150,221,250, 95,244,123,238, 13,136,162,250, 88,250,138, -202,219,200,151, 91, 20,127,209,208,241, 40, 54, 51,240, 90,219,248, 80,179, 90,173, 14, 16, 73,196,232, 20, 21, 37,190, 81,114, -179, 77, 85, 69, 21,166, 60, 59, 93,182,247, 96, 22, 86,127,152,182,109,231,222,221,241,157,163, 58, 35,233,233, 25,200, 61,115, - 12, 99,199,140,225,246, 31, 56,224,240,157,237,173,254, 3, 7, 14, 32, 46, 46,206,166, 44, 10,111,221,186,133,217,179,103, 11, - 1,192,153,216,130,170,170, 42,140, 24, 49, 2,102,179, 25,133,133,133, 56,118,236, 24,122,244,232, 1,127,127,127,180,111,223, - 30,253,250,245, 3, 69, 81,160, 40, 10,109,218,180,113, 84, 79,123,244,234,213,235,147,161, 67,135,242,206,159, 63,239,103, 54, -155,203,182,111,223,174,214,235,245, 41, 0,236, 7, 77, 95,125,252,241,199,139,247,238,221, 27, 69, 8,185,141,134,119,180,237, -159, 60,124,248,198,193,124, 62,169,248,224, 3,112, 38, 19,100, 60, 30,155,171,211,205,132,101, 27,119, 27, 94, 89,188,120, 49, -159,162, 40,200,229,114, 92,191,126,189,188, 87,175, 94,161,206,148,115,120,120,120,144,153,227,160,215,233,112,241,226, 69, 48, - 12,211,162,103,158,240,235,144,127,231, 48,127,201,240,199,251,134,207,246,147, 8, 6, 49,102, 86,193,231,204,126, 8,104,195, -187,173, 52, 64, 95,169, 2,132,124,152,149, 26,148, 40,104, 32, 56, 2, 20, 75,139, 27,115,241, 94, 83,171,209, 37,192, 15,140, - 17,184,150,243, 45, 58,197, 60, 86, 99,192,153,104, 19, 4,160, 80,109,176,236, 80, 59, 54,102, 0, 36,193,225, 88,181,241,167, - 6, 19, 60,182, 55,193,222,115, 28, 4, 98, 64, 24,241, 24,232,226,163, 53, 94, 0,129, 80, 4, 19, 12,240,145, 88,118, 36,221, -189,119, 11,254, 56,153,211,168, 75,146,101, 89, 8,105, 61, 76, 16,130,162, 24,192, 96,233,216, 76, 38, 19,140, 6, 1,120,124, - 1, 96, 0, 56,214, 50, 68, 16, 41,141, 2,114,235,159, 81,160, 51,176,224,241, 8, 76,140, 9, 6, 35, 11,181,198, 82, 15, 77, - 44, 7,218,200, 2,124,128, 39,224,129, 47, 6,136,222, 12,150, 48, 96,161,135, 70, 15, 88,118,150,108, 28,102, 0, 20, 11,112, - 4,160, 40, 22,132,240,192,114, 4, 20,101, 53,156, 88, 10, 44, 69,129,176,206, 25,200,118, 65,126,194, 38,214, 35,111, 0, 33, -139, 22, 45, 42, 79, 73, 73,137, 5,240,212,162, 69,139,198,164,164,164,104, 1, 84,185,229,178, 74, 72, 16,174, 91,183,238,203, -248,248,120, 72, 91,181,170,185, 46,109,213, 42,192,234, 5, 8,121, 16, 13,134,166,105,153,109,236,159,211,104,240,175,127,253, - 11,198,170, 42,216, 34,223, 58, 89,149, 21,129,209,136, 9, 19, 38,148,151,150,151, 79,115,198,210,110,198, 33,153, 90, 30,128, - 70, 60, 4, 56,125,250, 52,169, 79,121,168,165,212, 26,105, 40,105, 57, 12, 6, 3, 2,252,253, 33, 22,138, 96, 50, 51,224, 56, - 14,102,179, 25, 52, 77,195,100, 50,129,101,204,206,198, 51,176, 87, 11, 11,169,206, 82,169,205, 34, 96,175, 22, 22, 82,223,110, -255, 73,108,239, 17,232, 44,149, 42,155,203,125, 95, 82,144,215,108,150,191,187, 49, 0,163,178, 42, 80, 46,221, 6, 97, 68, 23, -144,168, 62,136,220,240, 59, 42, 13, 44,188,249, 4,244,175, 63,226,202,245, 27,112,180,107,177,158,161,113, 58,247, 36, 62, 89, -245, 49, 30,142, 25,142,197,255,111, 9,126,217,247, 11,190,219,244, 13,134,142, 28, 30,223, 94, 26, 1,190,151, 0, 7,143, 30, -196,230,175,191,193,142, 31,183, 67, 40, 22,115,187,119,239,110,116,125,136,157, 59,119,214, 34,126, 27,148, 74,215, 55,184,211, -104, 52,240,247,247, 63, 1, 96,176, 84,103, 60,227,177, 0, 0, 32, 0, 73, 68, 65, 84, 42,197,192,129, 3,193,227, 89,134, 89, - 35, 35, 35, 33, 18,137,160, 82,169, 32,149, 74,225,235,235, 91,164,209,104, 34, 27, 17,119,241,252,249,243, 43,118,236,216, 49, -174,115,231,206,221,182,111,223, 94,173, 80, 40,150, 2,216,108,175,191,140, 26, 53,234,205, 13, 27, 54,108, 5, 80, 14, 32, 1, -192,111, 0,250,214, 35,239,247,181, 50,217,138,128,188,188,119,159, 97, 24,124, 12,176, 95, 86, 87,207,168, 35,239,169,121,243, -230,125, 60,107,214, 44,220,184,113, 3,123,246,236, 1,195, 48,135, 0, 60,227,196,235, 83, 1, 60, 94,149, 15, 77, 67,251,251, -239, 92, 8,203,106,174, 1,154,191,186,143,234,215,175, 31,206,158, 61, 91, 51,238,223,104,130,235,156,119,152, 20, 29,177,220, - 79, 34, 24, 84,161, 54,252,114,252,106, 69, 10,120, 34,224,202, 81, 60, 42,229,240,127,175, 77,192,192,158, 82,204, 75,126, 28, - 79,118,164,129, 11, 7,192, 9, 36, 12, 26, 13,214, 81, 34, 95, 89, 12,190, 8, 24,251,228, 27,216,252,233,135, 22, 99, 81,103, -132, 89, 15,252, 40, 59,139,236, 83,150, 25,133,237, 34,162, 64,241, 29,147,215,184,190, 4, 38, 3,176,123,207,126, 68,143,121, -205, 98,253, 67, 0,158, 4, 72, 28,159,128,113, 35, 39, 90, 26,126, 81, 1, 24, 3,221,184, 70,207,113, 96,136,133,224,141,180, - 37,248,207,104,208, 67,167,211,161,186,186, 26, 26,181, 10, 26,141, 6,106, 77, 53, 12,213,213,208,235,245, 13, 87,254,106, 2, -189,193, 12,189,193, 12,173,206, 4, 77,181, 17, 10,141, 17, 74, 53, 13,149,198, 4,165,210,242, 41,175, 98, 32, 87, 48,144,171, - 24, 84,202,105,220,169,108, 56,141, 20,199,193, 12,128,152, 9, 8,197,130, 35, 28,192,113,224, 56, 30,204,236,221,226, 99,173, -189,135,171,190,241,238, 67,187,227,216,222, 99,248,229,208, 47, 53, 74,193,149,162, 43,174,214,185,112, 0, 29, 83, 83, 83,207, - 1, 88,251,206, 59,239,188,222,161, 67, 7, 38, 35, 35,131,164,165,165,185,172, 1,207, 74, 72, 32,194,176,176,157, 0, 16, 22, - 22,118,207,253, 57,115,230, 48,121, 87,174,108,105,174, 88, 0,155,251,223,217,125,227,109, 99,255, 0,240,195, 15, 63,224, 90, - 89, 25, 0,224,231,156,156, 90,247,174, 92,185, 18, 26, 18, 18,162,120, 16,138,202,232,209, 29,108,243,174,107, 93,183,157,219, -238, 59,244,105,250,249, 94,102,205,102,168,229, 10, 84, 86, 86,162, 74,169,128, 86,167,131, 86,167,131,166,186, 26, 90,149, 26, - 26,165, 18, 6,189, 14,180,193, 0,150,113, 24,232, 76,117,150, 74,109,125, 6, 11,128,182, 31, 14, 0,128,111,183,255,132,247, -211,214, 4, 0, 8,115,185, 34,118,140,142,169,171, 56, 68,245, 24, 21,131, 7,140,219, 83,164,136,220,240, 59, 72, 84, 31, 24, - 15,111, 67,209,243,253,225,205, 39, 56, 26, 23, 2, 70, 85,129,232,253,229,224, 59,168,126, 89, 89, 89,228,229,249,175,224,218, -149, 43,200,205, 57, 10,127, 95,127, 76,157, 50, 21, 1,193, 65, 56,115, 50, 15, 62, 66, 49,188,189,189,209, 70,218, 22, 91,190, -223,130,119,222,123, 23,213, 74,247,119,169, 29, 48, 96,128,203,223,241,245,245,133, 74,165, 26, 76, 81, 20,221,190,125,123, 12, - 26, 52, 8, 61,123,246, 68,171, 86,173, 32, 22,139, 33,149, 74,209,183,111, 95, 4, 4, 4, 64,163,209, 68,250,250,250, 58, 18, -185,242,240,225,195, 89,155, 54,109, 18, 40, 20,138,197,117,200, 58, 97,196,136, 17,159,108,216,176,225,171,176,176,176, 15, 8, - 33, 62, 0,222, 1,208,152,155,236,189,229, 26,205,202, 23, 25,198,252,165, 94, 63,173,142,188,248,103,146,255,189,227,181,215, - 23,240,174, 92,185,130, 19, 39, 78, 96,195,134, 13,213, 0,254,207,201,215,167,188,140, 70, 49,119,233, 18,218,103,103,147,240, -210, 82, 30, 30, 80, 12, 74,221,160,247,134,130,224,235,118, 2, 34, 30, 69,124,139,171,180,223,109,201,189,241,127,103,139,228, - 39,245,102,114, 13,149, 55, 32,222,241, 42, 62, 24,166, 65,222,210, 65, 88, 29, 91, 13,239, 31,231, 0,242, 18, 84,115,226, 11, - 86,205,171, 1,220,141,234, 63,119,254, 39,252,251,223,155,208,201,175, 55,254, 60,126, 14, 7,100,151, 16, 59,180, 39,226, 70, - 88, 42, 26,199,227,131,118, 97,162,196,216,254,221,176,124,229,135,216,127, 65, 13, 31,105, 15,140, 31, 63, 1,191, 28,218,137, - 61,191,108,177,188,156,217, 4,145,160,241,126,142, 99,205, 48,179, 22,107, 6, 86,107,134,166,105, 24, 12, 6,232,245,122,104, -117,122,232,117, 90,232,117, 90,232,140, 6,208, 70, 67,195,238, 47,189, 47, 84,213,102,168,245, 44,212,122,214,242,191,134, 69, -181,150, 65,181,142,129, 66,110, 70,149,220,132, 42,133, 9, 85, 85, 38, 84, 86,210,184, 83,105,106, 84, 1,184,235,254,191,215, - 84,227,243, 56,240, 8, 1, 87, 39,234,159, 35,142,235,220,219, 73,111,163,251,208,238, 53,231,217, 27,179,107, 60, 2,199,246, - 30,195,149,162, 43, 55, 92,169,112,219,182,109,251,149,227,184, 94,241,241,241, 73, 81, 81, 81, 33, 0, 40,150,101, 69, 38,147, - 41,112,254,252,249,126, 13,184,130,235,133, 48, 44,236,253,117,235,214,141,139,143,143, 71, 84, 72,136, 83, 67, 87, 77,116,255, -199, 0, 64,116,183,110, 14, 3,216, 58,183,110, 29,155,150,150,134, 63,139,138,212, 59, 14, 28,192,229,203,151,107,172,254,174, - 93,187,194,122,143,222,113,224, 0,138,138,138,112, 37, 47, 79,239, 72,230,130,247,223,199, 91, 75,150,212,184,247,109,255,219, -206,109,255,187, 18, 11,144,146,146,201,141, 26, 53,234, 85,123,210,183,125, 14, 28, 56, 16, 41, 41,153, 78,117, 76, 87, 47, 23, -228, 49, 12, 3,154, 54, 66,126,167, 28, 21,183,203, 80, 89,118, 7,149,101,119, 32, 47,175,128,178,170, 10, 70,173,214, 18, 63, -163, 84,194,137, 32, 64,230,253,180, 53,252,247,211,214,240, 1,168, 1,176,131, 7,244,185,231, 33,187,184, 0,167,209,182, 99, -116, 76,105, 65,158,172,239,160,187,105,232,216,255,201, 24,101,197,117, 89, 83,234, 7, 73, 84,212,178,252,221, 65,190, 92,139, -226,151, 30, 2,119,227, 60, 66,255,123, 6,222,235, 79,227,246, 20, 41, 6,238, 47, 7, 17,136,192, 39, 0,159,114,172,128,158, -191,112,129,252,235,195,229,152,247,214,155, 48,177,102, 92, 46,188,138,233, 83,167, 65, 40, 22, 99,215,143,187, 1,147, 25, 70, -131, 17, 71,243,142, 67,175,175,198,172,153, 51, 15,191,252,242,203,141,149, 53,153, 52,105, 82,236,152, 49, 99, 64, 8, 65, 86, - 86,214, 61, 46,253,183,223,126,219,233,247, 12, 14, 14,198,173, 91,183, 0,128,159,158,158,142,138,138, 10,244,238,221, 27, 1, - 1, 1,160, 40, 10, 39, 79,158, 4, 69, 81, 32,132,224,214,173, 91, 8, 14, 14,118, 70,236, 7, 52, 77,143, 4,240,131,221,181, -169, 35, 70,140, 72,123,233,165,151, 2,211,211,211,197,132, 16, 10,192, 78, 88,102, 1,220,113, 32,111,225, 9,147, 41,186,174, -188,103, 22,237,216,250,244,180, 57,100,220, 43,233,200, 57,113, 17,105,105,105,172, 90,173,126, 1,150,217, 5, 78,121,183, 58, -249,250, 6,180, 47, 43,195,112,157, 14,109, 4, 2,111,111, 30,239,129, 45,183,223,175, 95,191,154,195,169, 33, 0, 0, 5, 91, -142,223,152, 43,215, 26, 79, 3,200, 7,208, 38,247,106,197,231, 35,187,133,189,199,191,113, 34, 8, 27,102, 0, 34,111,192,168, - 5, 56, 14, 38,158,248,206,209, 63,111,127,137, 70, 86, 95,218,252,221,103,177,211,166, 39,201, 0, 64,203,154,112, 77, 89, 12, -192,140, 78,126, 81,136,141,237,131,176, 86,255,159,189, 43, 13,107,234,218,218,239, 62, 25, 8,160, 34, 56,139, 86,197,138, 90, -181, 14, 88, 17,181,146, 40, 90,171,181,195, 87,163,182, 94, 91, 63,109, 9,106,175, 83, 7,180,181,215,222, 94, 91,245,222,139, -218, 81, 98,135, 79,219, 91,111, 53, 88, 91,167, 58,160, 9, 42, 34,136, 86,235, 12,130,138,160,136,146, 48, 37, 64,166,253,253, - 72, 78, 12, 33,144,147,128,162,237,121,159, 39, 15, 57, 67, 22,251,236,189,207, 94,239, 90,123,237,181,219,163,184,180,204,230, - 43, 48,154,113,179, 68, 95,239, 67,117,122, 36, 10,249,121,246,101,158, 68,136,113,253,109, 49, 0,123,206,152,176,119,103, 18, -110,221,185,129, 86, 45,109, 43, 9, 90,138, 69,120,124,240, 0,168,127,174,199,165, 11, 33,196, 86, 51, 44, 16,192, 74, 8, 24, -139, 21, 48,153, 97, 17, 9, 1,194,128,125, 39,173, 20,182, 92, 1,245,224, 87,245, 21,242,244,136,230, 52, 64, 76, 33, 20, 57, -121, 24, 76,128,153, 2, 85, 70,192, 82,109, 1, 33, 4, 68, 76, 96,182, 0,250,106, 32, 35,173,148, 12, 24,208,153,186,117,249, -179, 61,139,177,130,216,221,255, 54, 82, 64, 96,177, 50, 96, 4,246,149, 2, 0,168,128, 2,148,155, 23,192, 89,249,187, 59, 78, -221,157,218,141,107, 71,155, 52,105, 82,159,164,164,164, 53, 0, 6, 36, 37, 37,237, 73, 74, 74, 58, 60,105,210,164, 55,186,119, -239,110, 34,132,180,250,228,147, 79,246, 45, 94,188,120,218,202,149, 43, 83,234, 33,159,172,245, 47,124,235,173,183,150,189,245, -214, 91,216,179,103, 15,244,183,106,191,203,221,218,180,193,149, 43, 87, 0, 64,205, 37,145, 79, 93, 73,127,222,120,227, 13,233, - 23, 95,124,161,254,252,243,207, 49,184,103, 79,217,241, 11, 23, 60,186,138,143,158, 57,163, 25,222,191,255, 83, 23,143, 31,239, - 10,192, 15,192,167, 38, 63, 63,136,170,171,209,163, 67, 7, 44, 90,180, 8,169,169,169,171,194,195,195, 83, 82, 83, 83, 15,228, -231,231,123, 32,119,181,243, 0, 52, 32, 6,160, 6, 15, 76, 73, 73, 33,241,241,242,227,199,142, 21,165, 42, 20, 10, 49, 0,196, -199,203,135,173, 90,165, 74, 3,199, 36, 64, 93,251, 63,246,110,229,205,194,177, 86,179,165,151,190,180, 20,165,119,110,131, 16, - 6,148, 90, 81, 85, 85, 5, 74, 41, 40,165,184,114,254, 2, 76,198,106,252,150,156,236,169, 14,157,199,156,150, 0,152,241,178, -104,235,120, 89, 52,156,151, 5,218,167, 8, 56,163, 83,143, 33,210,252,236, 12, 53, 0,116,237,210, 5,167, 51,108, 60, 57,231, -183,237, 0,128, 54,143, 12,146,221,206, 59,217,100, 30,128,193,191, 22, 33,243,105, 96, 64, 68, 12,138,230, 14, 67,251, 47,143, - 34, 75,171, 71,176,152,160, 88,171,131,144, 16,143, 30, 0,199,187,153,154, 90,227,206,238,221,187,211,241, 19,158,198,206,237, - 59,177,101,203, 22,124,240,222,251,216,167, 57, 0,129, 80,128,208, 78,161,209,165,165,245, 47, 93,222,182,109,155,198, 78, 4, -164, 99,199,142,173, 17, 11,176,127,255,126, 92,190,124,185, 74,169, 84,118,112,245, 38,185,237, 47, 93,187, 34, 55, 55, 23,143, - 61,246,152,121,193,130, 5,226, 31,127,252, 17, 65, 65, 65,184,120,241, 98, 45,207,107,110,110, 46,186,114,111,103,231,196,115, -211,159,120,226,137, 15, 95,122,233,165,160,204,204,204,230, 85, 85, 85,255,235,239,239,255,140, 61, 48,240, 23,142,242,156, 23, -202, 79,127,230,175, 63,110, 28, 49,250, 5,242,207,100,128,116,124, 22, 31,175,125,151,106,179, 47,206, 4,160,242,162,153, 73, -185,201, 84, 34,246,243, 67, 11,177, 24,254, 22, 75,181,190,230,146,181, 7, 14, 53, 8,192,124, 13,206,125, 34,173,206,154,175, -113, 76,105,230,125, 34, 45,249,181,188,202,172,143,124,180,245,248,144, 0,193, 19,130,234,170, 64, 51,101,202,139,203,141,199, -210, 46, 23,238, 45,208, 26, 82,230,107,112,179, 46,146, 49,237, 47, 75, 53,135,142,166,201, 0,168,173, 2,118,154, 79,128,203, -101, 55,241,183, 55,102,194, 96,168, 70, 89,165, 45, 6,192,200,248, 97,243,182,250,211,236,230,231,165,145, 23,158,253,171, 77, - 89, 90, 88,203,217,140,113,253, 8,166,206, 89,141,128, 0, 63,180,240,151,200, 0,168,179,207,158,148,109,248,108, 91,189, 3, -146,144,154, 97, 36, 54, 18, 0, 66, 96,161,212, 70, 4,204,246,229,126,132,129,208,106,133,217, 30, 28,232,137, 4,148, 84,182, - 68,101,117, 49,196, 66,198,145,230,204,108, 5, 76, 38, 10,147,153,162,162,210, 10, 34, 32,176,128,192,100,189,235,186,119, 7, -139,149, 1, 67, 44, 32, 22, 2,202, 80,135,251,159,212, 97, 60,179,146,206, 93,252,145,120,202, 13,125, 33,237, 66, 67,251,142, -195,109,209,175, 95,191,155, 97, 97, 97, 47, 92,189,122,181,199,150, 45, 91, 50, 0, 60,151,148,148,244,156,243,205, 43, 87,174, -212, 44, 94,188, 88,182,114,229, 74, 79, 10,194, 81, 33,113,113,113,117,222,244,226,171,175,218,124,128,222, 37, 6,162, 46,110, -127, 0,192,144,222,189,101, 25, 28,148,191, 99, 0, 62,125,218, 17,173, 58,172, 95, 63,107, 66, 66,194,231, 19, 39, 78, 52, 95, -186,116, 73,120,237,218, 53,116,109,213, 42,109,231,206,157,156, 2, 20,239, 81, 30, 0,103,229,126, 43, 37, 37,197, 57,198,227, -140, 83, 61,123, 36, 1,170,149,171,244,242,197,241, 47, 94, 60,112, 48,173,101, 96, 96,139, 50, 93, 9,204,102, 51,168,253, 61, -208,221, 42, 66,153, 78, 7, 74, 41, 6,198,196,200,126, 75,246,152, 7,201,140,187, 49, 39,140,125, 57, 32, 19, 57,232,113,140, -151, 69, 59, 86, 1,100, 95,189,202,153, 4,196, 76,120, 73,154,188,235,191, 14, 43,255, 23,213, 55,106, 0,104, 19, 54, 92,118, - 59, 55, 85, 3, 0, 77,163,252,105,109, 18,128,175, 48, 32,238,111, 40,180, 90,209,127, 67, 6, 50,198,181, 67,159,157,183, 32, - 36, 64,115,145,111,198,226,206,157, 59,201,148,151,166,208, 81, 99, 70, 99,251,214,159,241,143, 85, 43, 17, 95, 90, 10,106,181, - 98,243,230,173, 40, 40, 40,120, 6,192, 78, 79,114,220, 17, 1, 0,120,225,133, 23, 78,129,227, 92,246,134, 13, 27,200,216,177, - 99,233,201,147, 39,197,131, 6, 13,194,232,209,163,161, 86,171,241,200, 35,143,160,186,186, 26,209,209,209,160,148, 90, 79,158, - 60,201,136, 68, 34, 95, 50, 2, 62, 22, 20, 20,180,102,202,148, 41,162,243,231,207,183,168,174,174,174, 43, 48,144, 43, 6,134, - 14,152,188,113,192,200, 41,228,155, 20,160,172, 18, 48, 94,217, 99,213,102,171,103,160,102, 96, 32, 39,125,170, 45, 45, 53,139, - 77, 38, 24,196, 98, 8,205,102, 15,211,227,247, 6,108, 30, 0,103,203,223,221, 57,183,174, 84, 39,229,207, 30, 95,248, 68, 90, -145,119,237, 78, 69, 26,128, 14,246,151,183, 26, 64, 1,128,220,249, 26,120,116,113, 42,191,220,165, 25, 49,162,159,204, 66,155, -169,157, 95,142, 10,125,153,109,221, 63, 19,128,156,114,144,181, 95,110,226,244,128,219,182,127, 70,110,107,115,165, 96, 12,106, -231,234,109,214, 44, 8, 22,147, 14,160,122,140,235,199,109, 66,215, 4, 1, 64,169, 77, 81, 67, 0, 49,181, 19, 1,187,242,183, -229, 0, 4,192,145,200,165,157,184, 78, 34,250,118,160,102,147, 22, 66,187,247,135, 82, 10,139,153,162,202, 4,148,149,155, 97, - 2,133,153, 50, 16,138, 8,238,220, 50,213, 89,206,227,199, 87, 17, 0, 24, 22,245, 54, 37, 38,155,245, 79, 1, 80, 74, 0,106, -183, 24,168, 0, 68, 96,133,213, 42, 68, 86,246, 86, 78,207,252,218, 63, 94,147, 93,205,185, 90,159, 2, 22,193,182, 84,163, 62, -237,228,168,249,101,203,150,177,254,209,211,118,171,248,174,162,126,241, 69,233,214,173, 91,213,118, 18,160,246, 68, 2,214,171, - 84,166,223,206,156,145,119,237,215,207,242, 68,175, 94,122,123, 31,173,134, 75, 22, 45,249,184,113, 54,139,163, 95, 63,207,211, - 29,111,191, 45, 3,128,193, 61,123,214,186,150,121,233,146, 38,227,130,239,100,168, 95,239,222, 95, 50, 12, 99,185,120,252,120, - 96,187,118,237,238,164,230,231,111,244,100,245,223, 7,173,227,220, 15,244,246,128, 63,118,106,160,194,165,173,185,144,128,243, -242,197,241,145,219,191,254,102,107, 88,183,174,143, 85, 87, 87,193, 98, 50,195,106,181,162,121,112, 48, 74,181, 90, 86,249,115, - 33, 81, 37,127,127,243,175,109, 1, 24,179,175, 94, 21,179,243,255,233, 39,127,199,120, 89,180,117, 89,194,103,158,146, 3, 57, - 48,103, 94, 60,189,120,233,162,204, 89,249, 3,192,168,167,158,147, 29,220,251,139,230,118,110,170,239,149, 88, 71,128,159,251, -243,220,117,216,224, 95,139,128, 95,223,112, 28, 63,250, 75,161,227,123,169,201,119, 99,113,243,127, 55,147,225,195,135, 63, 61, -118,194,184,221,175, 79,159,117,228,241,254,253, 70,108,255,101, 7,210, 78,157,192,137, 19, 39,118,213,231, 6,174,135, 8,204, -218,182,109,219,215,219,182,109, 27,186,109,219, 54,206,133, 27, 59,118,236,168,125,251,246, 29,220,185,115, 39,194,194,194, 48, -102,204, 24, 4, 5, 5,101,149,150,150,134,159, 59,119, 14,185,185,185,140, 72, 36,194,216,177, 99, 99,246,237,219,231,237,163, -158, 47, 45, 45, 93,181, 99,199,142,250, 2, 3,189,193,111, 5,167,182,172,248, 57,233,217,119, 43, 67,167,161,242,248, 82,235, -141,195, 31, 77,247, 81, 94,213,181,162, 34,209,155, 89, 89,249, 22,131,129, 57,205, 48,162,246, 2, 65, 97, 97, 19, 57, 1,220, -101, 3,244, 52, 5,224, 22,243, 53,208, 3,248,221,254,241, 9, 71,142,156,209,196,197, 45,150, 37, 42,255,161, 14,237,210, 3, - 64, 53, 68,126, 18,228,223, 44,195,166,157,169,196,123,121,187, 52, 51, 94, 91,136, 13,223,254, 4, 88,175, 1, 16,194, 92, 85, -137,208, 14, 65,178,143,222,158,197,217,154,131,197, 10, 33, 99,133,137, 8, 33,162,230,187, 68, 0,102,128, 90,192, 53, 48,204, - 25, 39,206,222, 36, 0,208, 62,132,161, 34,161,205,218, 55, 91,109, 9,140, 74,202, 41, 44,102, 64, 32,180,194, 98,230, 54,114, - 28, 77,251, 23, 1,128,200, 33,139, 40,216,156,240, 12, 96, 37, 54,119,255,165,236, 29, 94, 21,242,235,247,191,214, 52, 66,255, -226,100,174,176,202,223,201, 19,224,113, 57,214,241,139, 23,147,142,187,184, 12,235,185,215,227, 61,141,153, 58,184, 22,185,181, - 45,241, 75,180,217,214,103,124,146,209,200,121, 0, 92,235, 86,239, 97,169, 21,167,190,163, 90,185,234,162,124,113,124, 95, 0, -130,139, 41, 41,166, 42, 67, 37,172, 22, 11,122, 71, 68,200, 58,132, 63,134,227,191,238,224, 86,199,148, 76,217,251,235, 46,199, -225,176,199,194, 28,223,247,254,186,171,214,113,125,161,241, 95,126,106, 35,200,163,159,122, 94,118,254, 98, 14,110, 94, 59,163, - 6,128,131,123,127, 81,183,123,164,175,236, 86,222, 89,175,219,125,242,228,201,240, 54,189,175,133,248,213,123, 61,239,133,246, -248,245, 70,213, 61, 31,240, 83, 83, 83,127, 85, 42,149, 76,102,102,166,245,192,177, 20,180,106,221,202,117,165,135, 87,216,182, -109,219, 55, 74,165,242, 59,133, 66, 97,242,230,119,111,189,245,150, 26, 0,153, 49, 99, 6,205,201,201, 65, 70, 70, 6,202,203, -203,195,155, 55,111,142, 86,173, 90, 57,246, 2,240, 65,249,179,248, 87, 74, 74,138, 40, 45, 45,173,159,209,104, 92,138,154,115, -249,190,224,189,179,155,255, 34, 10,234,254,221,162,210,156,125,211, 26, 32,207,252, 99,122,250, 51, 0,198, 0,248, 13, 86,107, - 57, 60,199, 35, 52, 58,216, 85, 0,238,206,251, 68, 0, 60, 14,130, 74,165,112,221,186,117,158, 93, 85,123,143,106, 58,117, 29, - 77,110,229,167,209,182,161,157,161, 45, 55, 99,211,246, 35, 62,119,208, 13, 95,175,177,255,182, 29, 5,110, 33,184,185, 16, 31, - 45,121,221,171,151,254,171, 99,217,247,108,157,102,161,214, 74, 0, 64,226, 47,162,198, 74, 19,172, 0, 2, 2, 2, 96, 48, 27, -136,197,236,189,188,244, 12,219,158, 1,145, 79, 44,164, 86, 42,192,213, 43,187,155,114,141, 41,215,165,131,252, 46,129, 28,234, -199, 89,225, 55,242,180,128, 49, 62, 94,238, 7,192,178,106,149,170, 65,166,136,106,229, 42,118, 35, 31, 71,155,230,156,245,110, -157,254,188, 21,159,249, 68,198, 92,183, 2,118,198,129,189, 63,107, 92,251,218,173, 60,223,242, 7,120,218,216,199,149, 3,155, -137, 31, 42,153,250, 87,164,230,148,155, 17,222, 92,120, 95, 94, 21,251, 90,253, 70,123,231,188, 85,254, 53,198,103,223, 55,252, -225,130,143,141, 70,227,207,128,231, 77,233, 56,226,157,210,156,125,155, 80, 51, 54,192, 91,152, 0,148,192,187,184,129,123, 70, - 2, 56, 13, 62,190,238, 35,204,131,135, 51,122,244,232,129,236,236,108,190, 34,120,240,224,193,227, 33, 1,195, 87, 1,143,198, - 0,175,252,121,240,224,193,131, 39, 0, 60,120,240,224,193,131, 7, 15,158, 0,240,224,193,131, 7, 15, 30, 60,120, 2,192,131, - 7, 15, 30, 60,120,240,104,114,212, 8, 77, 61,117,234,148,207, 81,155,238,130, 9,121,121,188, 60, 94,222, 3, 35,175,222,232, -112,190,254,120,121,188,188, 63,150, 60,175, 9,128,211, 64,225, 45, 60, 13, 60,141, 41,143,199,131, 9,202,183,219, 67,217, 14, -156,239, 87, 42,149,129, 0,158, 56,114,228,200, 71, 2,129, 96,152,159,159, 31, 12, 6,195,209, 17, 35, 70,188, 7, 32, 67,161, - 80, 24, 30,132, 10,176,103,135, 84,255,153,199, 21, 74, 41, 61,123,246, 44,250,245,235,199,191,147, 60,188, 34, 0, 94,173, 67, -230,146, 40,199,157, 60,231,196, 39,222,202,251, 19, 14,232,156,240,212, 83, 79,201,246,238,221,171,225, 42, 51, 52, 52,180,214, -133,130,130, 2,215,193, 20, 42,149,138,112, 44,227, 61, 35, 1,117,229,243,111, 42,121,171, 87,175, 30,189,117,235,214,228,172, -172, 44, 0, 64, 88, 88,216,179,233,233,233, 59,124,109, 95,231,126, 79, 41,117,188, 31,236,121,246, 93,177,159, 39, 30,200, 51, -215,118,240, 70,249, 63,118,246,236,217,173,101,101,101,189,186,116,233,130, 59,119,238,160,170,170, 10, 0,134,109,221,186, 85, - 29, 24, 24,120, 81,169, 84, 62,175, 80, 40,234,221, 74,242,236,217,179, 94, 25, 4,169,169,169, 50,133, 66,161,241,230, 55, 42, -149, 74, 45,151,203,101,190, 36,128,162, 94, 38, 97,152, 60,121,178, 55,239, 7, 0,160, 75, 23,219, 14,184,229,229,229,168,174, -182,165, 65,215,235,245,222,188,111,245,226,204,153, 51,116,216,176, 97,232,221,187, 55,252,252,252,138,170,171,171, 31,225,135, -209, 63, 31, 92,147, 1,221,179, 68, 64,188, 21,123,111,241, 75,226, 56,143,247, 60, 63,123,143, 87, 50,213,234,187, 6, 82, 86, - 86, 22, 2, 3, 3, 29,131, 16, 11, 46,155,127,200,229,114,170, 82,169, 92,143, 73, 29,247,248, 84,183,209,209,119,183,115,117, - 39,191, 33, 32,132,208,145, 35, 71,202, 82, 82, 82,188, 82, 22, 91,183,110, 77,110,219,182, 45, 94,121,229, 21,232,116, 58,107, - 66, 66,194,246,149, 43, 87, 78, 93,188,120,241,102, 47,255, 63,126,253,245, 87,199,241,184,113,227,176,103,207,158,122,143,185, -136,117,233,203, 52, 34, 34, 2, 0,168, 83,102, 56,175,148,127,105,105,105, 90,247,238,221, 91, 0,128, 68, 34,129,191,191, 63, -138,138,138, 80, 82, 82,130,160,160, 32, 20, 21, 21,245,218,179,103, 79,134, 82,169,236,169, 80, 40, 10,235,147,215,183,111, 95, -200,229,114,132,133,221,205,250,183,106,213,170, 26,247,196,199,199, 3, 0,142, 29, 59,166,246,165,223, 52, 36,251,227,218,181, -107,235,186,228,216,171,192, 87, 4, 6, 6,226,252,249,243, 16,137, 68, 48, 26,141,216,179,103, 15,178,179,179,177,100,201,146, - 6,245,227,224,224, 96, 1,128,152, 67,135, 14,237,137,142,142,190,245,252,243,207,183, 75, 78, 78,134, 64, 32,104,211,178,101, - 75, 1,120,252,169,149, 63,123,206,149, 4,252, 97,130, 0, 35, 35, 35,165,247,219,226,110, 74,132, 14, 94,238,248,248, 10,157, - 78,231,176,248,245,122, 61,214,175, 95,239,248,120, 49,208,186, 61,158, 52,105, 18,149,203,229, 20, 0,117,189,199, 91, 28, 58, -116, 72,253,246,219,111,163, 91,183,110,141, 86,127, 93,187,118, 37,239,188,243, 14, 40,165, 72, 73, 73, 81,123,219,238, 89, 89, - 89, 24, 55,110,156, 21, 0,196, 98, 49, 19, 30, 30,142,132,132,132, 31,219,180,105, 67, 35, 35, 35,199,123, 97,113,222,171, 46, - 66, 34, 34, 34, 40,251, 92, 39, 78,156, 96,247, 3, 96,219,133,179,219, 95,167,211,109, 21,139,197, 45, 0, 96,238,220,185,152, - 54,109, 26,196, 98, 49,252,253,253, 33,145, 72, 64, 8,129, 64, 32, 64,105,105,105, 11, 0, 9, 74,165,178, 94,217,241,241,241, - 8, 11, 11, 67,110,110,174,227, 19, 31, 31, 95,227,211, 16,200,229,114,153,253, 57,125, 30, 19, 22, 46, 92,232,248, 56,143,151, - 46,231, 57,111,244,210,165, 75, 23, 4, 6, 6, 98,233,210,165, 8, 12, 12,196,246,237,219, 81, 89, 89,217, 40,202,223,254, 46, - 83,157, 78,247,191,211,167, 79, 71,143, 30, 61,218,237,217,179, 7,183,110,221,194,245,235,215, 81, 82, 82, 98,188,159, 99,147, - 82,169,148,230,231,231, 83,165, 82, 41,117,119, 45, 59, 59,155, 94,190,124,249, 79,145,128,142, 82,218,171, 41,149,127,108,252, - 74,196,198,175,172,147, 24,220, 23, 2, 64,220,160,190,243,190, 32, 61, 61, 93,221, 24, 36, 96,218,180,105, 15, 13, 9,104, 40, - 12, 6, 67, 45,171,223,151,230,101,149,201,164, 73,147, 28, 86,126, 82, 82, 18, 26,170,248,157,173,127,149, 74, 69, 70,142, 28, - 41, 83,169, 84, 53, 60, 2, 13,193,150, 45, 91, 8, 0, 18, 29, 29, 45,115,245, 52,112, 28,116,205,118,111, 0,218,182,109,139, -229,203,151, 87,189,249,230,155,198,220,220,220, 93, 43, 87,174, 28,211,212,237,235,180, 7, 0,113,110, 39, 47,219,229,137,236, -236,236, 94, 0, 48,107,214, 44,148,150,150,226,198,141, 27, 16,137, 68, 16, 10,133, 16, 10,133, 16,137, 68,240,247,247, 71,101, -101, 37,146,147,147, 95, 6, 16,236, 73,104,110,110, 46, 84, 42,149,227,227,236, 9, 88,181,106, 21,146,147,147,125,126,110,149, - 74,165,177, 79, 1,168, 27,233, 93,174, 43,113, 55,231,241,243,234,213,171,216,181,107, 23,150, 47, 95,142, 46, 93,186,160,117, -235,214, 72, 73, 73,193,146, 37, 75, 16, 24, 24, 8, 0, 16, 8, 26,100,168,119,152, 57,115,230,148,127,253,235, 95, 72, 79, 79, -199,141, 27, 55, 96, 54,155, 95,105,213,170, 85, 48, 0,211,253,238,123,161,161,161,136,141,141, 85,231,228,228, 80,103,229, 31, - 27, 27,171,126,244,209, 71,241,128,239,146,219,187,129,191,247, 3,208,117,213,170, 85,207,164,167,167, 71, 3,232,223, 20, 15, -225,172,248,157,191, 55,133, 7,128,186,249,212,119,190,201, 72,192,248,241,227, 27,131, 4, 80, 47, 62,156,241,226, 27,123, 27, -173, 65,178,178,178,160,215,235,235,116,243, 31, 61,122,180, 49,136, 65,131,113,232,208, 33,181,157, 88, 32, 37, 37, 69, 67, 8, - 65,219,182,109,213,141,217, 57, 89,247,191,221, 19, 80, 47, 86,175, 94, 61,126,248,240,225, 20, 0, 18, 18, 18,196,223,126,251, - 45, 94,121,229, 21,214, 53, 47,249,253,247,223,197,246,107,251, 34, 35, 35,159,227,242,255,199,141, 27,135,167,159,126,218,225, -222,103,191,179,199,236,119,142,238,127, 0,128,221,250,119,215, 14,196,229,122,189,216,179,103,207, 71,173, 91,183, 6, 0, 92, -190,124, 25,121,121,121, 56,121,242, 36,140, 70, 35, 8, 33, 16, 10,133, 32,132,192, 98,177,192, 96, 48, 96,219,182,109,224, 50, -224,185, 76, 27,185, 37, 47,185,185,185, 13, 34, 1, 78,207,222, 32,111, 0, 26, 97,170,212,100, 50, 97,208,160, 65,208,104, 52, -184,122,245, 42, 6, 15, 30,236,184,166,209,104, 16, 18, 18,226, 32, 2, 62,160,227,204,153, 51,243,191,249,230, 27,196,196,216, - 54, 50,234,216,177, 35, 44, 22,203,247,176,229,166,191,175, 80, 40, 20, 26,150,124,134,133,133,225,248,241,227,148, 85,254, 44, -249,235,217,179, 39,151,241, 97, 8,128,239, 96,219,243,172, 62, 76, 0, 16, 11,160, 77, 35, 41,255,134, 18,128, 14,115,231,206, -149,189,243,206, 59,162,182,109,219,202, 1, 68, 61,168, 76,231,190,196, 0,220,207, 32, 64, 59, 9,144,165,167,167,107,124,149, -209,181,107, 87, 76,155, 54, 13, 63,252,240,131,175, 49, 1, 4, 0,253,225,135, 31,220, 94,220,189,123, 55,236,215,188,150,125, -236,202, 99, 24,218,237, 60, 10, 50,151, 54,168,158,156,231,252,147,147,147, 17, 19, 19,131,216,216, 88,135,242,239,220,185,115, - 99,144,190, 6, 17,129,232,232,104,233,161, 67,135,112,231,206, 29, 25,123, 78, 42,149,202, 84, 42,149, 58, 58, 58, 90,234,237, -188,189,135,255, 37,227, 66, 0,182,110,221,186,139,157,251,215,235,245, 88,181,106, 21, 42, 42, 42, 32, 18,137,224,231,231,135, - 43, 87,174, 96,249,242,229,208,233,116, 72, 72, 72,248,121,229,202,149,163, 22, 47, 94,172,246,160,100,107,144, 1, 79, 49, 1, - 28,234, 28, 30,118, 0,116, 76, 7,120,122,222,144,144,144, 97,213,213,213, 48,155,205, 56,122,244, 40, 4, 2, 1,140, 70, 35, - 42, 43, 43, 97,181, 90, 29,239,177,201,100, 66,117,117, 53,251, 78,247,245, 36,183, 46, 55,127,124,124,188, 35, 30, 32, 44, 44, - 12, 69, 69, 69, 13, 38,162, 78,171, 2,184,246, 69, 45,128, 16,119, 23,214,172, 89,227, 83, 33, 18, 18, 18,240,246,219,111, 99, -224,192,129, 14, 15, 8,155, 62,123,224,192,129,184,116,233, 18,218,182,109,235,139,232, 46, 51,103,206,188,250,205, 55,223, 56, -143,159,161, 55,110,220,184,209,148,138,101,240,224,193,132, 85,250,131, 7, 15,198,224,193,131,213, 0,112,233,210, 37,244,234, -213,139,107, 59,156, 2,224, 15,224, 71, 0, 83,225,178, 37,184, 29,111, 0,248,204,254,253, 61, 0,189, 0,207, 91,212,123, 80, -254,255, 3,224, 39, 95,159,125,213,170, 85,125,223,121,231,157, 82, 0, 47,118,235,214,173,208, 78, 80, 18,239, 87,221,179,187, - 1,174, 95,181,216, 97,249,175, 95,181,216,113,237,190, 19,128,251,141, 7,133, 4, 76,155, 54,141,190,247,222,123,181, 92,129, -190, 40,255,198,180,254, 1,184,181,254, 89,171, 95, 36, 18,161,176,176,176, 73,149,191,179,245,239, 28,208,165, 86,171,157,189, - 0,247, 61, 96, 51, 43, 43, 11,175,188,242,138, 1, 64, 64, 96, 96, 32,222,127,255,125,136, 68, 34,199,245, 25, 51,102, 0, 0, -130,131,131, 49,113,226, 68, 28, 57,114,228,224,125, 44, 39,113,246, 0,212, 71, 2, 34, 34, 34, 92,183,138,117, 75, 6,140, 70, - 35,180, 90, 45,170,170,170, 16, 20, 20, 4, 63, 63, 63,152,205,102, 80, 74, 97,177, 88, 96, 52, 26, 97, 50,153, 96,177, 88,156, - 9,253,157,250, 10,153,155,155, 91, 35, 0,144,157, 14,112,246, 8, 56, 95,111, 40,124, 8, 8,148,212,117,193, 57, 38,192, 27, - 50,176,124,249,114, 76,152, 48, 1, 93,187,118, 69, 64, 64, 0,164, 82, 41,180, 90, 45, 2, 3, 3,161,211,233,176, 97,195, 6, - 48,140,215, 14,217, 78, 51,103,206,188,186, 96,193, 2,108,223,190, 29,207, 61,247, 28, 0,180, 71, 19,108, 65, 91,151, 39, 32, - 40, 40, 72, 54,101,202, 20, 53, 0,108,222,188, 89, 54,117,234, 84,111,218,194, 8, 96, 26,128, 31,234, 33, 1,206, 83,109,143, - 0,232, 7, 32,195, 71,229,255, 24,128, 23, 26,104,236,246,202,200,200,232,116,229,202, 21,185, 93,249,179, 59,104, 54, 9, 88, -197, 95, 23,254,144,153, 0, 27,170,252, 89,248,106,165, 59, 15,200, 31,125,244, 81,131,149, 63,139, 65, 3, 7,224,192, 65, 53, - 54, 29, 12,112,144,130, 99, 87, 30,107,208, 51, 70, 68, 68, 32, 55, 55, 23, 73, 73, 73,232,220,185, 51, 54,110,220,232,181,213, -165, 84, 38, 74,157, 60, 56,141,162,252,217,249,248,162,162, 34,153,235,181,145, 35, 71,202,146,146,146, 26, 45, 22, 0,176,185, -255,185,122,159,116, 58,221, 5,251, 75,109,221,188,121, 51, 54,108,216, 0, 0,248,241,199, 31,161,211,233,216,219,204,151, 46, - 93, 66,155, 54,109,154,228, 29,112,137,246,175, 69,206,184,238, 19,159,155,155,123,212, 98,177, 64,167,211,225,206,157, 59,208, -233,116, 48, 24, 12, 48, 24, 12,168,168,168, 64, 89, 89, 25, 74, 75, 75, 81, 89, 89,137,234,234,106,118,110, 55,173, 62,153,174, -202,221, 93, 32,169,235,170, 0,174,176,187,250,169,155,115,222, 32,160,177,219, 99,227,198,141,144, 74,165, 8, 8, 8,192,249, -243,231,161,209,104, 16, 24, 24,136,191,253,237,111, 56,114,228, 8,150, 44, 89,226, 45, 1,104, 63,115,230,204,235, 83,167, 78, -197, 79, 63,253,196, 42,255,142, 15,138,242,183,141, 11, 74, 41,171,252, 1, 96,202,148, 41,234,139, 23, 47,122, 59,181,202,146, - 0,216, 73,128,235,116,192,101,167,239,121, 0,206, 52, 64,249,255,143,125,220,242,217,250, 39,132, 92,140,140,140, 76, 11, 11, - 11, 75, 34,132, 4, 17, 66,154,217,203,221, 36,112, 13, 2,108, 18, 2,112, 63,130, 0, 27, 91,249,219, 21,119, 99, 88,110,228, -163,143, 62,106,144,242,127,241,141,189, 24, 52,240,174,235,102,235, 79,219, 28, 30,129, 3, 7,213, 62,145, 0,133, 66, 1,251, -210, 48, 24, 12, 6,236,223,191, 31,203,151,219, 86, 20,156, 57,115, 6,102,179,217, 11, 89,113, 26,192, 22,248, 71, 41,101,131, - 1, 27,164,252, 89,235,191, 62, 55,127, 99,197, 2,176, 68, 66, 42,149,202, 60,221, 27, 22, 22, 54, 54, 33, 33, 33, 34, 61, 61, - 93,248,221,119,223, 49, 23, 47, 94,196,140, 25, 51,204,108, 61, 38, 36, 36, 32, 61, 61, 29,223,125,247,157,240,218,181,107,136, -140,140,244, 40,243, 94,196, 0,176,150,180, 11, 9,160, 44,233,227,138,240,240,240, 76,179,217, 12,163,209,136,219,183,111,163, -176,176, 16,183,110,221,194,173, 91,183,112,251,246,109,104,181, 90, 24, 12, 6, 84, 87, 87,163,180,180,148,253,159,249,245,201, -100, 3,253,156, 73,104, 61,101,247, 74,249,179, 57, 0, 92,207, 53,164,127,184, 89, 13,224, 32,121, 92,101,100,103,103,227,210, -165, 75, 48, 24, 12,136,138,138, 66,255,254,253,177,113,227, 70,188,251,238,187, 16,139,197, 16, 8, 4, 16, 10, 57, 59,100, 59, -205,156, 57,243,230,212,169, 83,145,145,145,129, 15, 62,248,128,181,126,111,226, 1, 89,198,156,153,153, 73,217, 57,255,147, 39, - 79, 98,253,250,245, 50, 0,232,217,179, 39,156, 3, 3, 27, 72, 2,230,195,230, 94,159, 4, 96, 14,128, 72,248,230,254,191, 0, - 96,171,253,127, 76,107, 8, 1,176,227, 52,128,117, 0,158, 1,240, 60,128,205,247,179,238,217, 72,127,119, 65,128,174,171, 0, -238,215, 20, 0,245,242,252, 31, 69,249, 59, 72, 64, 3,166, 18,106, 40,127,119,199, 7, 14,122, 63,190, 57, 15,186, 1, 1, 1, -232,221,187,102,220, 75,122,122,186, 87,242, 38, 77,154,132,164,164, 36,176, 68, 0, 0,181,159,243,122,221,249,198,141, 27,213, - 0,176,103,207, 30,153,187,136,245,148,148, 20,205,213,171, 87,221, 90,143,238, 80, 87,210, 31,150,104,164,164,164, 32, 58, 58, - 90,166, 86,171, 61,246,157,244,244,244,253, 43, 86,172, 24,157,154,154,122, 32, 60, 60, 28, 89, 89, 89,208,233,116,194,224,224, - 96,204,156, 57, 19, 90,173,246, 90,106,106,106,151,240,240,112,164,166,166,146,184,184, 56, 79,228,184,214,156,127, 3, 98, 0, -106,188, 91,108,190, 4,123,238, 4,135,103,198,105,254,223, 99,123, 12, 29, 58,244, 93,141, 70, 51,207, 98,177,160,172,172, 12, - 38,147,201, 49,239, 95, 85, 85, 5, 74, 41, 40,165,184,116,233, 18,140, 70, 35, 98, 98, 98, 94, 82, 40, 20,102,119, 73, 71,234, - 66, 76, 76, 12, 98, 98, 98,106, 4,253,121, 59, 5,224,172,232,237, 46,127,234,220, 63,236,171, 2, 26,123, 92,227, 60,126,178, - 75,253,222,124,243, 77,104, 52, 26,200,100, 50,100,103,103,163, 89,179,102,200,203,203,131, 64, 32,224,234, 1, 32, 51,103,206, -188, 62,125,250,116, 28, 62,124, 24,127,251,219,223, 0, 32, 20,192, 13,220,205,255,208,228,150, 63, 59,190,228,230,230, 34, 34, - 34,130,237,103,178,216,216, 88,117, 88, 88, 24, 46, 93,186, 68, 57, 6, 2, 58,147,128,169,118, 2,240, 35,128,163, 0, 20, 0, -164, 0, 10,193,163,241, 58,112, 99,103,227,115, 23,240,179,106,213,170, 58,207, 55,165,242,183,175, 0,184, 23, 44,218,103,153, -215,243, 61,247,111,127,127,239,188,150,158,130,196,188, 69, 76, 76,140, 44, 41, 41, 73, 51,121,242,100,186,101,203,150, 26, 68, -192,133,240,113,174,135,184,184, 56,143,204,198,203,196, 64,212,133, 72,216, 70, 37,153,140,147,242,119, 26,204, 29,243,250,145, -145,145,127, 73, 72, 72,248,126,226,196,137,184,116,233, 18,174, 93,187,214,101,233,210,165,178,184,184, 56, 78,242,238, 81, 30, -128, 26,245, 92,135,226,227,148, 49, 80,161, 80,232, 19, 19, 19,151,237,222,189,251,239,102,179, 25, 37, 37, 37,142, 24, 0, 0, -184,125,251, 54, 74, 74, 74, 64, 41,101,173,118,175,180, 44, 59,255, 31, 17, 17,225,136, 96,103,207,115, 37, 1,110,172,252, 90, -211, 80,247, 64,249,123, 13,150, 4, 44, 94,188, 24, 41, 41, 41,152, 56,113, 34, 86,172, 88,129,183,222,122, 11, 66,161, 16, 18, -137,196,227, 24, 66, 41,181,206,154, 53, 11,223,127,255, 61,190,253,246, 91, 0,232,108,202,132,133,197, 0, 0, 32, 0, 73, 68, - 65, 84, 87,254,141,110, 80, 53, 4, 5, 5, 5,216,181,107, 87,141, 44,142,246,239,178, 81,163, 70,169,125, 92,242,104,177,147, -128,157,118,235,127, 40,175,252,235,134,187, 32, 64, 78, 4,192,155, 68, 28,190, 42,236,198, 70, 99, 40,255,134, 42,234,123,129, -249,243,231,203, 46, 94,188,216,168, 50,237, 46,210, 70, 93, 74,199, 42, 60,251,218,122,214, 43, 64, 9, 33,176, 90,173,216,186, -117, 43,103, 18,240,246,219,111,179,229,172, 21, 3,192, 48, 12,172, 86, 43,222,121,231, 29, 53, 87,229, 89,159,188,148,148, 20, -141,115, 86, 68, 31,250,221,127, 86,172, 88,113, 59, 53, 53,117, 15, 87,171,255, 62,120,219,136,171,183,167, 14,194,199,137, 4, -196,197,197,125,168, 84, 42,147,126,248,225,135,115, 98,177, 24,236,170, 0,171,213,138,150, 45, 91, 66,167,211, 65, 46,151, 35, - 38, 38, 38, 64,161, 80,120, 92,224,205,142, 47,206,193,127, 39, 78,156, 64, 76, 76, 76,141,241,196,211, 56, 20, 31, 31, 79,115, -115,115,101,174, 46,126, 95,211, 0, 59,195, 77,128,159, 25,128,121,205,154, 53, 18,187, 53,202, 56,125,188, 34, 1,206,137,127, -230,204,153,227,248, 94, 86, 86,230,113,108, 34,132,144,153, 51,103,210,239,190,251,238,121, 0,191, 60,136,138,199,174,232,137, -183,215,184,144,118, 23,220,124, 24,198,240,251, 13,118, 21,128, 59,197,207,105, 21, 64, 99, 43,245,186,228, 61, 40,228,225, 65, -238, 56,159,124,242,137,166,177,101,186,172,145,190,103,112,113,255,115,125,169,185,230, 66, 39, 94, 60,239, 61,125,214, 37, 75, -150,236,109, 72,125,142, 27, 55,174,198,178,216,167,159,126,186,134,103,192,203,185,127,226,165,183,135, 83,185, 21, 10,197,121, -165, 82,217,108,223,190,125, 31,231,229,229,205,171,172,172,132,197, 98,193,128, 1, 3, 48,120,240,224,132,152,152,152,120, 46, -202, 31, 0,142, 29, 59,230,248, 30, 29, 29, 93,227,188,235,177,135,113,133, 56, 19, 90,150, 76,216,227, 0,124,106,247,201,147, - 39,215,117, 73,232, 52, 94,138,239,213,184,226,193, 83, 97, 5,128,111,191,253,150,223, 48,133, 7,103, 18, 80,151,242,175,139, - 0, 52,118,231,226, 59, 43, 15,226, 37,179,255,211,213,141,179,194,191, 7,211, 2,141,242, 14, 42, 20, 10, 61,108,174,215,249, -236,185, 11, 23, 46,112, 81, 92, 14,244,237,219,183,209,199, 3,119,132,214, 87,151,255,189, 38,139, 60,120,253,113, 63, 73,128, -199,202,245,117, 31, 97, 30, 60,120,240,224,193,131,199,195, 11,134,175, 2, 30, 60,120,240,224,193,131, 39, 0, 60,120,240,224, -193,131, 7, 15,158, 0,240,224,193,131, 7,143,135, 16,102,120,177, 93, 49,143, 63, 39,132,124, 21,240,224,193,131, 7, 63,182, -243,248,147,119,146, 83,167, 78,249, 28,113,233, 46,152,208,131,188,122,215, 31,251, 32,175,177,203,199,203,227,229,253,169,229, -253,246,238, 53,159, 7,150,129, 31,119,193,189,150,119, 98,137,239,242, 34, 86,212,150,199,214,159, 82,169,148,154, 76, 38, 92, -185,114, 69,109, 52, 26, 33, 20, 10,145,159,159,143,151,130,186, 98,111,102, 38, 42, 31,239,140,161, 67,135,202, 4, 2, 1,187, -174,189,201,218, 87,169, 84, 62, 6,160,237,185,115,231,118,117,236,216,145,209,106,181,146,142, 29, 59, 46,247,247,247, 95,167, - 80, 40,110, 0, 64, 98, 98, 34,147,152,152,104,169, 75, 94, 98, 98, 98,115,187,183,192, 16, 23, 23, 71, 1, 96,233, 95,159,252, - 74,241,100,222,204, 77,153,225, 87,132,109,199, 14,109,214,188, 69, 5, 0, 74, 41, 21, 2, 8, 78, 76, 76,188,206,191,111, 15, -182,188,123,205, 18,185,110,250,226,109, 10, 92,175, 83,230,174,138,122, 74, 42, 12, 9, 82,231,100, 93,150, 61,234,215, 12,139, -206, 30,210, 60, 72, 44,171,158,124,228,252, 18,151, 38,198,132, 9, 19,164,187,119,239, 86, 39,188,107, 59,254,249,240,147, 56, -116,232, 16,167,118,249,203,140, 87,165, 12, 33,234, 75, 23, 47, 66,167,211,161, 75,151, 46,104,214,188, 57,182, 37,109,229,220, -174,147, 38, 77,170,241,226, 38, 37, 37,213,187,151,130, 61,187,162, 79,253,134,221,168,137, 82,218,176,126, 39,215,214,124, 85, - 85, 33,190,203,138, 88, 3,132,189,106,251,158,187, 1, 56,177,168,225,141, 58,233, 78,205,242, 37,181,230,244, 51,165, 82, 73, -245,122,189,108,219,182,109,234,220,220, 92,200, 69,173,208,190,115, 27, 84,233, 43,225,111, 48, 99,248, 91,175, 99,228,196, 41, -216,249, 77, 34,118, 28, 56,160, 30, 59,118,172,236, 1,232,194, 89, 22,139,165, 67,110,110,174,181,127,255,254,226,240,240,112, -156, 60,121,242,221,170,170,170, 9, 74,165, 50, 70,161, 80,104,227,226,226,172,245, 45, 9,139,139,139, 43,119, 62,254,226,139, - 47,152, 61,255,137,239,209,105,214, 64,188, 51,164, 79,155, 99,251,254,189,101,235, 25,233,169, 30,125, 71,173, 32,132,104, 21, - 10, 69,254,128, 1, 3,172,118,210,192,123, 26,254,100,110, 34,111,153, 6,167,108, 99,190, 40,255, 47,163,159,149, 70,181,233, -164, 38,160,200,174, 40, 65,135,142, 93,213, 38,171, 5, 75,250, 13, 67, 81,151, 54,178,111,118,254,194,137, 8,196, 78, 5,237, -213,157, 61, 18, 96,219, 62, 43, 14, 31,167,136,157, 10,244,234, 14, 44,250,168, 97,138,155,221,160,164,161,217,201,220,145,137, -198,146,219, 16, 80, 74, 41,150, 17,144, 15,235,189, 7, 88, 70, 48,249,130,252,129, 89,107,125, 87,249, 83,187,242, 31,137, 35, - 71,142,112,250,109,218,177, 23,169,217,212, 11, 42,213, 77,164,167,217, 18,214,100, 93,188, 4, 0,216,181,139,208, 75,151, 39, -201, 22,205,231,214, 46, 99,198,140,177,238,223,191,159, 73, 74, 74,194,193,131, 7,107, 36,195,113,133,143, 41, 84, 29,205,228, -166, 35, 83,234, 3,161, 96,211,133, 55, 56,103, 65,216,171,142,141,118,214,172, 89,211, 56, 4,192,169,158,236,187, 19,114, 66, - 78, 78, 14, 52, 91,182,168, 63,140,153,140, 1,211,230, 64,220, 46, 24, 16,218,147,253, 89, 41, 96, 21,193, 90, 77, 49,254,213, - 88,228,125,186, 18, 71,143, 30, 85, 43,149,202, 26,233,110,155, 0, 22,134, 97,218,182,110,221, 26, 26,141, 70,216,191,127,127, - 12, 25, 50,132, 41, 44, 44, 28,120,250,244,233,179, 74,165,114,144, 66,161, 40,180, 43,107,134, 99,221, 53, 27, 61,106, 76,216, -138,213,219,153,248, 25,103, 90, 12, 29, 55, 91, 54, 52, 50,249,201,183, 62,203,127, 38,252,137, 87, 34, 0,148,195, 22, 99,192, -212,165, 31,156, 19, 91,121,234, 71, 13, 38,164, 60, 92, 61, 9,158,188, 5,142,239,222, 4, 1, 82,182,113, 7,188,210, 15, 74, -165,146,241, 66, 17,186,110, 82, 65, 35, 34, 34, 16, 17, 17,225,115,158,120,229,203,177,210,151, 7, 70,169,123,118, 8, 69,247, - 14,161,120,188, 77, 71,132,250, 55,131,196, 10,116,243,107,134,160,236, 27,234,153,207, 60, 39,229, 34,171, 87,119,224, 98, 14, -131, 11,151, 3,112, 54,167, 5,158, 31, 19,136,213,239, 9,208,171, 59,105, 52, 35,189,161, 74,154,221,230, 52, 44, 44, 76,157, -153,153,137,204,204, 76,252,253, 63,167,241,232,248,120, 53, 0,234,229,150,167,148,235, 71, 46,151,123,126,139,151,217,234, 40, - 34, 34, 2,114,185,220,237,135,189,199, 91, 76,236,255,129,212,185, 60, 19,250, 45,147, 54, 70,123, 76,152, 48, 65,186,107,215, - 46, 53, 33, 4,111,126, 76,240,243,225,145, 56,124,248, 48,167,223,110,217, 50, 77, 58, 52, 50, 14, 35, 70,220,196,167,159,126, - 90,227,218,203, 47, 3,227,199, 3, 11,231, 37,169, 87,127,194,173, 77, 88,229,175,209,104,192, 48, 12,166, 76,153, 2,129, 64, -208, 16,101, 95,203,242,119, 55, 32, 19,226,155,242,111, 52, 68,172, 6, 0,172, 93,187, 22,107,215,174,181,157, 27,148,208,100, -197, 57,120,240, 32,190,120, 33, 22,131,159,147, 67,216, 42, 4, 68, 36, 0, 35, 18, 64, 32, 17,131,241,151, 0,160,160, 22, 51, -168,209,136,215, 95,157,131,178, 3,153,200,201,201, 81, 43,149, 74, 41,154, 14, 36, 51, 51, 51,170,115,231,206, 98,171,213,138, -148,148, 20,108,223,190, 29, 65, 65, 65,136,138,138,234,176,121,243,230,127,216,239,227, 20, 16,168, 84, 42, 5, 71, 14,252,247, -255, 30, 9,200,111,167, 47, 23,224,229,101, 21,248,252,223,159, 0,205,251, 10,255, 29,223,182, 91,206,201, 31, 94,118,210, 29, - 76, 29,196,144, 56, 41,117, 98, 59, 77, 28,223,157,207,223,163,189, 48,120, 52,178, 7,192,209, 74,155,246,252, 80,210,253,209, -238, 45, 21, 31,190,110,245, 82, 59,146,136,136, 8,202,166, 37,117, 74, 79, 74,189, 77,219,169,124,225, 85,233, 83,157, 31, 85, -139,171,204,240,255,247,219, 48, 27,140,144,188,249, 17,130,196, 18, 84,137, 42,161,175,170,132, 63, 8,170,175, 23,169,255,249, -207,127,202,222,121,231,157,122,149,239,197, 28, 96,253,143, 86, 0, 6,251, 7,120,242, 9, 6, 47,140, 37, 53,222,155,216,169, -192,122, 31,118,118,182, 91,233,212, 87,107,157,181,250, 51, 51, 51,239,214,193, 17, 19, 42,141,122, 0,192,232,248,253, 80,173, - 26,227,149,151, 33,103,101, 14, 68, 36,251,110, 71, 32, 5, 32,173,123, 57, 29, 23,161,205,255,190,192,173, 97, 63,116,228,155, - 39,117,165,157, 37,118,210,119,226, 4,183,118, 86, 60,251,185,116,253,246,191,170,119,156,254, 0, 43, 22,252,140, 72,105, 56, - 54,125,121, 24, 95,239,179,109, 16, 52,251, 47, 31,200,214,253,231, 3,159, 72, 85,194,187,160,192, 46,168,190, 59, 7, 74, 41, -154,183,125, 28,135, 15, 31,134,125,223,130,122,203,183,250, 19,185, 84, 46,111,165, 6,190, 0,240, 51,210,211,129,200,200,187, -215,255,241,143,187,223, 23,206, 75, 82,251, 7, 44,149,205,126,125,121,189,229,100,149,127,116,116, 52,172, 86, 43, 62,255,252, -243, 70,117,208, 0,128,213,106,173,173,252,105,253,239, 47, 51, 89, 87,227,229,103,135,112,171,220,205,125, 14, 63,159,237, 75, -255,254,181,231,216,153, 41,186, 26, 52,223,106,157,129, 5, 11, 22, 56,174, 47, 88,176, 0,107,215,174, 5,211, 99,214,221,255, -106,191,223,157, 60,225, 20,247,229,115,221,201, 90, 56,133, 91,249,170,170,170,208,190, 75, 87,192,106, 4,227, 7, 16,161, 0, -230,242, 82, 84,229, 94,193,237,252, 2,116, 26, 38, 5, 17,183, 4, 49, 25, 1, 1,131, 85,179,223,194,152,245, 31, 96,209,162, - 69,141, 61, 46,115,210,138, 74,165,146, 80, 74, 91, 86, 86, 86, 14, 11, 9, 9,193,165, 75,151, 96,181, 90,113,229,202, 21,108, -216,176, 1,189,123,247, 70,104,104,232, 43, 0, 94,119, 81,214,117,122, 3, 40,165,173,187, 48,233,210, 14,143,140, 19,151,164, -156, 65,169,206, 15,223,239, 52, 99,247,177,255, 96,158,220, 95, 40, 52, 88, 35,236, 49, 5,110, 9, 0,175,208,155, 30,117, 77, -247,184,243, 12, 48, 28, 58, 34, 59,111, 8,233,146,145, 88,159,162,108,153,115, 57, 7,167,190, 59, 3,165, 82,233,149,245,192, - 42, 7,131,225, 7, 24, 12,155,160,213,198,176,214,177, 87, 15, 56,196,175,133,186,109,149, 5,146,101,115, 96,185,163,133,249, -242, 85, 8,197, 34, 4, 16, 1, 2,137, 0,129, 2, 33, 66, 68, 18,208,114, 61,110, 30, 60,234,113,167, 23,119, 74,253,240,113, -171,227, 61, 92,253, 30, 65,194, 82, 98,247, 8,248,102,253,219,149,179, 26, 62,164,192,117, 85,254, 16, 10,144,123,179, 2, 55, -139,141, 72, 63,111,219, 64,164,199,140, 29,240,102,223,115, 17,201,134,144, 20,192,143, 57,109,251,219,150, 32,248,229, 27, 8, -154,122, 22,126,207, 47, 3, 66, 3,189,243,228,114,216,185,205,155, 45, 94,149,219,223, 80, 15, 13,121, 15, 39, 14, 93,193,255, - 76,154,136,208,214, 61, 49,231,175,175,225,179,165,251, 48, 52,120, 41,214,253,231,239, 62,239,224, 67, 8, 16,183,232,172,195, - 98, 25, 49, 98,132, 93, 33, 89, 61, 54,240,180,169, 34, 53,112, 16,192,207, 40,185,213, 12, 61, 30,105,134,175,190,178, 89,254, -203,150, 1, 97, 97, 54, 17, 37,183,154,161,228, 86, 51, 12,232,119, 65,237, 73,249, 31, 60,120, 16, 86,171,213,161,164, 55,111, -222, 12,139,197,226,149,251,186, 30, 15, 79, 45,229,111,123,159, 61,147,119, 10,144,117, 74,165,140,181,212,172,148,194,106,173, -221,125,217,243, 86, 74,177, 46, 49, 81,150,104,251,141,219,255, 73, 1, 66, 41, 72, 98,162, 82, 70, 41,197, 39,159,124,226,184, -206,126, 79, 76, 76,148, 81,106,187,143, 2,164, 46,121,137, 74, 37,236,215,136,197, 98,129,217, 98,129,217, 92,187,206,216,243, -102,139, 5, 95,174, 91, 39, 91,151,152, 88, 71,249, 40,132,205,155, 3, 34, 1, 44,134, 10,156,219,154,132,191,189,166, 64,167, - 55, 20, 24,184,242, 67, 92,249,237, 36, 4,254, 18,152,138,111,225,204, 49, 13,118, 28,222,139,210,194, 66,156, 61,123,182,209, - 54,214,138,138,138,226,228, 77, 80, 42,149, 65,148,210, 33,153,153,153,191,188,255,254,251,125,206,157, 59, 39, 54, 26,141, 16, - 8, 4,104,222,188, 57,204,102, 51, 50, 50, 50, 64, 8, 17,123, 26,235, 19, 19, 19, 3,149, 74,165,127, 98, 98, 98,104, 73,126, -234,111,127,255,191,188,144,223, 15,239,132, 86,207, 64, 44,100,208, 41, 88,130,210, 59, 98, 40,254,105,198,153, 59, 3, 3, 61, -233, 13,123,172, 9,117,238,139,118, 98, 80,235, 60,175,174,239, 15, 88,229,239, 74, 14, 24, 79, 44,148,221,239,187,134,155,115, -220, 52,239,189,125,118,119,191,193,176, 9, 0, 65, 85,213,183,144, 28,191, 10,195,222, 71,107, 92,247,132,119, 6, 69, 75,131, -180,229,176,138,133, 48,158, 56,135,234, 11,185,168,218,119, 24,168,172,134,152, 82, 4, 64, 0, 33, 8,170,173,102,104,171,171, -240,229,254,157, 30,101,174,126,207,102,221, 59,195,118,204,154, 43, 20,151, 46, 83, 44,250,200,247,254,234,146,175,156,179,203, - 94, 46,151, 59,246,214,102,241,210,218,124, 28, 56,161, 67,222,173, 42, 0, 64,222,173, 42,100,231, 87, 2, 49, 91,216,141, 81, - 60,187,126, 72,129,141, 8,148,159, 65, 96,224,101,248, 73,202, 97,181,106, 97, 50,157,128, 64, 16, 6,163,190,184,201, 58,235, -228,113,127,149, 2, 4,159,255, 60, 11,205,152, 71, 0, 0, 55, 47, 81, 12,154, 40,192, 95,151,143,193,136, 49,125, 0, 80,251, -125,222, 33, 58, 58,154,190,249, 49, 65,179, 54,253, 64, 1,140,123, 97, 54,231,121,255,117, 95, 45,165,109,219,254, 14,224, 44, - 74,110, 53, 67,121,177,109, 11,230,254,253,129, 30, 61,128, 87, 94,185,171,252,203,139,253, 81, 94,236,143,144,128,155,245,202, -156, 52,105, 18,100, 50, 25, 70,141, 26, 85,195,245,239,252,241,101, 74,192,221,123,235, 11,226,156,230,183, 9, 33,142, 79, 93, -231,226, 20, 10,141, 34,214,243,156,120,108,108,172,218,157,229,188, 96,193, 2,196,198,198,214, 80,168,117,201,251, 89,169,196, -217,179,103, 29, 46,120,231, 58, 99,225,122,110,118, 92,156, 38, 78,225,126,171,102, 49,165, 96, 2,252, 96, 42,188, 6,229,210, -165,216,160, 47,129, 46,122,168,227,250, 55,255,217,128, 15,222,122, 13,225,139, 94,194,135,103, 14, 98,139,238, 10,198, 60,251, - 44,194,194,194,188, 14, 6,180, 43,122, 26, 25, 25, 89,163, 15, 31, 59,118, 76, 93,223,118,236, 74,165, 82,164, 84, 42, 7,159, - 57,115, 38, 47, 37, 37, 69,243,230,155,111, 14,253,252,243,207, 37, 21, 21, 21,142,109,154,171,170,170,208,172, 89,179,236,201, -147, 39,247, 28, 62,124,248, 35, 30,136, 4, 67, 8,233,114, 38,109,107, 81,214,222, 69, 87, 23, 45, 73,232,176, 99, 89, 71, 92, - 40, 16,162,180, 66, 0, 43, 1,138, 43,140,160,173,186, 87, 45,124,247,163, 62,207, 60,255,151,215,225, 33,158,192,238,254,175, -225,234,247,240,157, 71, 19, 40,255,186,166, 0, 40, 87, 87,142, 66,161,240,116, 19,117,181,254,109,174,182,111,235,242, 14,120, -252,167,125, 90,183, 83,107,169, 9,226, 98, 45, 36, 63, 31, 4, 17, 50, 64,149, 17,180, 92, 15, 98, 54, 67, 4,192, 66,173,168, -178,152, 81,110, 54, 2, 86,207, 86, 20, 27,228,183,250,189, 58, 57, 45,108, 65,130,141, 66, 88,137, 83, 32,159,199, 23,160,150, -245, 15,224,191,111,116,168,113, 60,120,113, 46, 68,244, 14, 76,164, 53, 84, 42,213, 65,174, 47,150,164, 66,141,144, 15,255,131, -219,111,198,225,142,214, 31, 29, 77,231, 96,177,228, 2, 0,174,157,106,223,100, 29,118,203,158,207,212,175,141, 85,214, 80,254, - 44,134, 6, 47,197,176, 62,147, 16, 21,114, 14, 91,246, 44, 87,123, 51,136,140, 28, 57,146,166,164,164,160,184,120, 52, 90,181, - 58,128,102,173,251,130, 82, 10,134, 97, 56, 5, 34,229,229, 1,185,185,103,237, 71, 21,128,164, 2, 90, 61, 48,100,136,237, 76, -118, 54,240,197, 23, 64,121, 25,160,175, 0, 42,244, 64, 96,112, 25,167,178,213,101,237,231,228,228, 0, 0, 62,254,248, 99, 0, - 64,120,120,248,189,112, 51,115,170,195,249,243,231,215,176,216, 93, 21, 55,103,239,142, 93, 97, 59,230,253,157,240,201, 39,159, - 96,237,218,181, 80, 42,149, 82, 79,193,117,179, 66,195,145,117,238, 60, 10,130,131,213, 12,195, 96,222,188,121,181, 98, 50,188, - 41,223,147,213, 45, 65,173, 21,120,237,227,247,208,111,210, 36, 40, 63,254, 24, 12,115, 87,207, 41,179,207,222,245, 16, 30, 62, -140,253,251,247,227,202,149, 43, 50,133, 66,161,225,178,241,138,179,242, 79, 75, 75, 83, 3, 64, 70, 70,134, 58, 42, 42, 74,150, -150,150,166,137,140,140,148,166,167,167, 35, 42, 42, 74, 86, 89, 89,169,174, 99,204, 53,205,152, 49,163,223,180,105,211, 90,116, -235,214, 13,187,119,239, 54,148,150,150, 10, 43, 43, 43,109,222, 14,251,252,199,182,109,219,194,199,141, 27,231,175, 80, 40, 42, -221,136, 97,156,148, 53,147,123,233,212,218, 15,222,153,217,172, 85, 15, 21,126, 83,189,138,223,175, 19,228,221, 18, 2,148, 65, -181,209, 4, 45,109, 85, 48,119,214,156,161,132,144, 2,118,204,247,230,121,221,120, 8,248,169,130, 7, 4,117,178,184,148,148, -148, 90,159,146, 2, 29, 74, 10,116, 94,181, 53,251,185,107,197,218, 26, 94,114,252, 42,252,206, 22, 64,152,175, 99, 61, 0, 53, -238,175, 75,224,249,252, 60, 28,191,115, 3,231,174,228,226,214,149,171, 40,187,154,143,242,235, 5, 48, 27, 42, 97, 50,153, 81, -110, 49,194, 96, 49,163,154, 90, 96, 1, 5, 37,220, 73,166,115,180,255,197, 28,219,241,162,143, 88,203,159, 65,194,123,141,179, -226,197,219, 56,128,120,149, 14,241, 42, 93, 13,133,207,126,162,226, 51, 32,162,119, 32,164, 58,252,119,150,197,204,121, 10,224, -214,113, 88,244,205, 0, 0,255, 22, 6,161,250,214, 53,100,254,179, 3,178,126,152,128,227,255, 28,128,236, 75, 55,154,180, 99, -246, 31, 18, 6,189, 14,208,235, 0,131,255,121, 0,192, 79,127, 55,225,157, 5,203, 0, 0,195, 99,250,120,109,249,191, 48,242, - 16,180,218, 24, 4, 31, 59,128, 53,239,217, 72,238,200,145, 35, 57,185,254, 1, 96,197, 63,150,147,238,221, 1,231,207,197,139, - 54,247, 63, 0,244,232, 65,177,118, 45,208,165,103, 5, 30, 27,122, 27, 67, 70,223,198,243, 47,153, 56,151,209,217,226,103,143, -195,195,195, 17, 30, 30,142,121,243,230, 53,118, 21,123,124,215,156,177,126,253,122,153, 59,133,237,240,162,173, 94,141,245,235, -215,115,178,132, 95,127,253,117, 53, 27,249,239, 14, 11, 23, 46,172,229, 5,112,135, 67,231,243, 48,115,214, 92,156,216,180, 9, - 75,150, 44,169,147,156,176,229, 59,112,224, 0,234, 11,216, 27,249,216, 35,248,246,155, 47, 16,241,242,203, 88,177, 98, 5,234, - 43,227,130, 5, 11, 48,122,244,104,248,178, 2, 32, 45, 45, 77,237, 20, 44,135, 99,199,142,169, 1, 32, 61, 61, 93, 77, 8, 65, - 90, 90, 90,189, 50, 13, 6, 67,203,157, 59,119,226,252,249,243,200,206,206, 14,208,235,245, 48,153,108,253,204,104, 52, 98,207, -158, 61,196, 78, 22, 42, 57, 20,199, 90, 93, 93, 45, 62,177,245,101, 84,101,125,134,189, 41, 57,184,114, 83,128, 50, 61, 3, 11, - 5, 10,244,254,152,187,232,189,168,184,184,184,124, 14, 6,159,131, 87,176, 75, 78, 57, 78, 7,240,104, 2,235,191, 46, 2, 64, - 0, 16,169, 84, 10,169, 84,138,211,167, 79, 59, 62,185,199,175,161,180,178, 20,173,134,120,191,238,247,196,137, 19, 4, 0, 2, - 2,166, 65,114,252, 42, 68,215,138, 65, 9,129,120, 86,113,141,235, 30, 21,151, 88, 0, 11, 5,242,245, 37,200, 43,213,226,118, -153, 14,165, 85, 85,208, 25, 43,113,187,186, 18, 55,171, 12, 40,168,170,128,214, 84, 13,157,213, 4,163,213,115,240,235,147, 79, -184, 25,240,156,226, 2, 94,155,210, 12, 20, 98, 80,175,183, 1,191, 27,189,239,230, 28,103,228,221,170,194,129, 19, 58, 12, 94, -156, 91,179, 46,232, 29,248, 89,175,193,207,122, 13, 31, 60, 37, 68, 94, 94,158,145,171,204,173, 87,172,104,147,144,232, 56,190, -162,183, 32, 63,167, 0,151, 82,207,161,240,106, 73,147,119,220, 77, 95,166, 0, 0,202,138, 40, 2, 42, 31,131,116,150, 16,255, -179, 76,228,248, 36,108,121, 25,132,187,241, 79,159, 27,145,130, 87, 23,217,148, 63, 33, 4,191,164,218,154,128,235,154,127, 22, -225,189,122,214, 44,231, 38,224,243,207,129,203,151,109,158,128,191,255,157, 58,220,239,148, 82, 4, 7, 7,123, 30,129,237,125, -148,157,247,255,248,227,143,145,147,147,131,172,172, 44,100,101,101, 33, 57, 57, 25,111,189,245, 22,242,242,242,154,172, 61, 88, - 69,231,206,146,158, 63,127, 62, 8, 33,156,149, 33, 33, 4,245,145,137,250,174, 57,227,176, 95, 9, 8,211, 12, 95,191,251, 17, -154,237, 76, 70,108,108, 44, 94,102,217, 24, 0, 69,143,190,152, 31, 49, 12, 1, 1, 1, 24, 57,114, 36,222,127,255,125, 36, 39, - 39,171, 87,172, 88,225,246,253,251,166, 32, 11, 55,251, 60,134,208,208, 80,153,213,106,173,151, 80,212,119,141,131,114,116,120, -156,162,162,162,100, 78,138, 18, 67,135, 14,149,121,240,158,140, 26, 57,114,100,139,188,188, 60, 28, 62,124, 24,143, 62,250, 40, -132, 66,161, 99,138, 35, 52, 52,148,235,116,132,213,254,127, 73,247, 94, 3,227,215,239,107,137,223,119, 47,195,147, 81,189, 17, - 40, 97, 16, 24, 96,129,191, 95, 53,158,126,110,178, 21,128,214,249,135,137,137,137,158,230,162, 28,171, 0, 56, 78, 7,240,120, -208, 60, 0, 0,136, 82,169,108, 62,127,254,124,204,159, 63, 31, 0,140,255,136,251, 7, 76, 69,102,248,251, 75,224, 75,227,201, -229,182,240,225,128,167, 46,131, 10, 24,188,255,147,193,217,250,231,132,128,208, 80,153,185, 89, 0,116,212,130,243,122, 29,206, -150, 22,227, 92,217, 29,156, 43,211,226,188, 94,139,203, 6, 29,138,171,171, 80, 97, 54,227,134, 65,239,248,159,245,225,133,177, - 4,171,223, 19, 96,245,123, 2, 80, 8, 64, 9,131,216,169, 4,175, 79, 21, 99,214,148, 54,232,222,189, 29,172, 16,121,253,200, -172,171,223,121, 94,190,158,164, 64,117,201,144,101,231,219,136,124,230, 74, 91, 16,221,222,183,131, 0, 0, 66,170,131,128,234, - 81,205,216, 34,154,181, 90,109,128, 92, 46,143,241,166,140, 17, 17, 17, 72, 78, 78,198,166, 10, 61, 42,141, 12, 94,253,241,107, - 20, 73,252, 81,105,108,186,109, 34, 38,246,255, 64,150,166,253, 8,155,190,223,226, 56,247,211,223, 77, 24, 26,188,212,113, 28, -251,204, 23, 50, 10, 78,235,135,233,154,165,192,140, 69,163,209,242, 88, 50,100,255,140, 6, 51, 1,208,104, 52, 62,245,225, 46, - 93,106, 70,143,143, 26, 5,180,108, 9,132,133, 1,145,253,155, 67, 34, 22, 64,192,220, 21, 43,241,247,247, 56, 32, 51, 12,227, -176,252,115,114,114, 28, 86, 63,251,249,240,195, 15,241,225,135, 31,226,198, 13,238, 94, 25,119,243,245, 53,175,123,111,125,173, - 95,191, 94,182,102,205, 26,183, 10,155,171,245,239,228,122,174, 21,167,192, 30, 91,173,220, 82,216, 27, 9,129,213, 80, 13, 81, -251, 46, 80, 44, 95,142, 25,129, 45,209, 82,147,230,184, 62,235, 47, 51,240,193,191,191, 70,246,234,255,226,111,253, 70, 97,114, -112, 55,236,223,190, 29,185,185,185,110,223,191,231,227, 20,232,211,183,175,204,106, 47, 19, 75,200,156,167,103,220,157,171, 11, -179,103,207,166,132, 16,202, 6,246,177,243,253,206, 74, 62, 45, 45, 77, 51,116,232, 80, 25,165, 20,236, 84,128,135,122, 75, 17, -137, 68,143, 62,255,252,243, 57,165,165,165,208,233,116,240,247,247, 71,155, 54,109,208,178,101, 75,180,108,217,210, 83,229, 89, - 93,136,157,197,207,207,207,240, 98,220,167,178, 13,199, 7,227,234,245, 50,180, 11, 18, 32,170, 39,193,227,221, 40, 2, 91,180, - 40, 1, 96,169, 71,111,240,251, 13, 60,164,214, 63,224, 97, 25,160, 66,161,168, 80, 42,149,126, 0, 2, 21, 10,133,131, 5,118, -138,238,232, 19,243,101,151,250,201,229,114, 42,158,229,136,252, 39, 78,243,255, 30, 7,228,119,119,109,209,124, 28,243, 28, 12, -230,106,148,233, 13,200, 49,153, 32,178,218,126, 92,106,170,130,149, 82, 80, 0,187,111, 93,129,222,108, 2, 0, 14, 3, 19,193, -162,143,106,246,113, 91, 60,128, 21, 22, 84,227,194,229,114,124,187,185,204,171,135,117, 86,244,118,151, 63,181,127,119, 40,118, - 46,171, 31,108,191, 85, 65, 52,250, 75, 0, 97, 40, 46,190, 27,156, 39,182,222,132,145,233,128,185,253,178,112,243,166,195,114, - 58,192,165,124,113, 63,173,175, 65,188, 84, 42, 21,216,210,252,120,230, 40, 98, 98, 98,154,172,227,238, 56,109, 91,222,151,154, -124, 14, 0, 48,172,143, 45, 51,222, 59, 11,150,225,232,185, 62,248,247,150,151,161,220, 57,135,243,252,255,171,139, 98, 16, 18, -146,108, 63,210,216,201, 82, 12, 40,181, 89, 99, 0, 69, 72, 72, 50, 39, 89,251,247,238,115,228,180,120,249,101, 64, 38, 35,184, -115, 61, 8,122,157, 4,149,101, 98,252,184,145, 96,254,124,138,107, 69,229,136,140, 26,138,148,131,106, 78, 86,177,197, 98,113, -204,247, 39, 39,219,202,234,172,240,139,138,138, 80, 84, 84,196, 89,255, 59, 41, 12,202, 48, 76, 45,165, 74, 41,136,183, 73,128, - 20, 10,133,230,245,215, 95,175, 17, 11,192,122, 4,188,113,133, 19, 39, 86, 98,117, 89, 86, 64, 8,247, 57, 59, 66, 8,204,229, -229, 16,181, 14,129, 32,160, 25,250,188, 56, 9, 31,142, 29,131,119,217,101,123, 3, 7,193, 82, 89, 5, 81,171,118,232, 55, 84, -138,174,157,186,225,211, 11,105,232,219,183,175,236,248,241,227,181, 72, 64,156, 66, 1,128,168, 1, 96, 78, 92,156, 99,233,160, -217, 69,217, 11,133, 2,128,222, 93,168, 88, 87,129,215,173, 91, 71, 0, 80,187,139,159,100,100,100,184,117,241,167,165,165,105, -184, 40,255,196,196, 68, 66, 8, 89,218,178,101,203, 62, 67,135, 14,237,126,241,226, 69,156, 60,121, 18, 22,139, 5,129,129,129, - 48, 24, 12, 69, 33, 33, 33, 87,189, 49,250,148, 74, 37,211,174, 93,187,253,207, 61,247, 92,187, 99, 71, 50,176, 86,181, 31, 45, -136, 24, 61,219, 85,227,242,157, 64,140,232,105,186, 2,192,117, 30,203, 82, 95,155, 56,103,156, 34,132, 56, 31,186,230,125,225, -209,196, 16,114,120,233,141, 0,140, 78,131, 10,205, 79,241,122,126,184,134,114,175, 67,241,113,206, 24, 88,166,213,201, 76, 1, - 18,117, 41, 99, 69, 97, 85, 5, 96, 50,193, 98, 95,215,116,161,162, 4, 5,134, 50, 80, 74, 97,207, 47,160,225, 82,188,216,169, - 4,235,127,188,219, 39, 47,230, 0,189,186,155, 33,128,190, 65,202,223,165,179,123,170,131, 58,189, 0, 42,213, 28, 53,144, 9, -173, 86,107,204,203,203, 19,174, 26, 3, 38,126,255, 72, 44,232,123,212, 97,133,113, 37, 21,238,188, 46,174,199,172, 18,226,106, -205, 97, 25,193, 96,251, 74, 14,119,203,253,182,108,217, 98,203, 4, 40,151, 83, 46, 57, 31,226, 38,126, 41, 83,238,152,171, 78, -219, 66, 17, 21,114, 14,195, 99,250,224,200,254,115, 56,166, 91, 14, 2, 2,197,196, 47,100,137, 59,230,114, 42, 95, 72, 72, 50, - 8, 33,120,225,133, 23,240,213, 87,101, 96, 85,140,237, 47,101, 9, 1,173,105,217,223,169, 83, 94,244, 40,153, 44,229,160, 90, - 61,106, 20, 96, 44,236,140,235, 37,126,176,218,103, 91, 59,232,219,225,237,216,114,236, 63,214, 19,205, 59,245,148,177, 89, 2, -235, 3,171,248,243,243,243, 1, 0,133,133,133, 14,207,192,173, 91,183, 28, 3,171,143, 32, 78,110,103,215,151,146,112,201, 7, -224,140,175,190,250, 74,182,118,237, 90, 53, 75, 0,214,172, 89,227,181,245,239,170, 48,124,133, 68, 34, 65,225,181,171,232,214, -189, 7,172,230,106, 16,179, 5,194,230, 45,208,124,208, 96, 52, 27,248, 4,172,122, 51, 44,134,106, 80,179, 5,176, 88, 17,191, -238,223,152,242,242, 20, 72, 36, 18,183,242,204, 63, 6,115,250,191,238,238,139, 88,225,254,222,168,168, 40,153,157, 0, 80, 74, - 41,134, 15, 31, 46, 75, 77, 77,173,117,159, 39,229,111,175, 43, 43,128, 61, 61,123,246, 28,248,217,103,159, 25,111,223,190, 93, - 53,102,204,152,231, 50, 51, 51,255,102, 48, 24,138, 91,183,110,173,248,244,211, 79,181, 92,235, 79,169, 84,138, 0, 60, 50, 52, - 50,178, 77,220,172, 56, 92,201,191,162,157, 62, 43,238,201,244,253, 27, 19,110,150,107,135, 13,142, 30, 99,109,215, 41,252,127, - 92,173,252,250, 82, 11,219,251, 24,113,226,159,196,141, 14,112,253,206,227, 65, 37, 0,245, 89, 23,190, 40,127, 86,217,212,145, - 48,134, 19, 9, 88,121,242,144, 6, 0,153, 58, 40,138,194, 95, 2, 29, 53,195,104, 54,195, 74,173,104, 21, 20,132,124,125, 41, -188, 73, 46,228,110,121,223,221, 24, 0,239,214, 98,187,115,241, 55, 52, 93,175, 61,143,192,196,193,131, 7,239,136,143,143, 23, -135,132,132, 88,111,222,188,137, 5,125,111,186, 42,127,206,255,163,174,132, 61, 62,193,158,229,207, 77,146,167, 90,247,112, 69, -226,142, 57, 26, 0,100, 66,191,101,210, 93,103,254,174, 78,219, 2, 16, 16, 76,236,255,129,108,199,233, 15, 52, 92,149, 63,219, -151,138,139, 71, 83,160,140,181,126,225, 78,239,108, 72, 56,192,246, 7, 82,223,230, 26,118,171,158, 20,235,250, 74, 45,229,229, -106, 34, 0, 12, 85,254, 32,229,102, 8, 25, 33, 12,140, 68, 54,118,242,107,152, 27, 27,231,177, 61,146,146,146, 72, 82, 82, 18, -189,135,239, 31, 40,165,132, 16, 66,157, 35,218,157, 61, 1,222,200, 82, 40, 20,154,216,216, 88, 44, 88,176,192, 65, 40,154, 42, - 21,238,168, 81,163, 48,119,203,122,124, 88, 94,130, 1,209, 35,192,180, 11,182,149,201, 68,109,169,123, 33, 2, 17, 8, 65,196, - 2,124,149,184, 26, 45, 70, 15, 70,247,238,221,189,142,218,111, 8,156,172,123,117,100,100,164, 44, 53, 53,181, 65,117,149,147, -147, 19,115,224,192,129,107, 2,129, 96,251,147, 79, 62,249,143, 57,115,230,220, 94,183,110, 93, 10, 96,155,114,240, 66, 20, 3, - 32,249,228,201,147, 67,190,219,176,145, 17, 11,252,174, 79,122,105, 82,255,185,115,231,234,190,252,242,203, 9, 0,130,236,138, -191,156,221, 32,136,139, 71,129,199,131, 1, 46,238,127, 95, 9, 64,131, 9,131, 7,229,195,121, 64,250,241,100, 26,145, 79,146, - 75,173,151,178,213,250,106, 35,204, 22, 11,186, 15, 25,132,112,115,164,183, 10,183,209,130, 81,216,164, 63, 0,212,172, 53,110, -143, 3,104, 80, 14,124,149, 74,181, 83,169, 84, 10,147,147,147, 23,173, 90,181,234,159, 78,228, 98,148,243,255,226,234, 81, 0, -208,104,201, 75, 38, 95, 96,227, 44,234,126,190,201, 23,228, 62, 49,253, 93,103,254,174, 97,219,135,130, 98,199,233, 15,124, 42, -163, 77,185, 19,188,186,104,212, 93,179,151,220,189,182,232, 35,239,243,145,199,191,125, 86, 19, 15,144,117, 95, 45,149, 86, 26, -108,251, 0,220,205,255, 31,231,245, 59, 98,183,200, 44, 10,133,162,209,231, 85, 89, 18,208, 24,178,236,177, 0,106,246,123, 35, -148,205,167,223,117,239,222, 29,237,231,205,147,173,221,183, 79,157,251,143,159, 33, 23,181, 66, 75,251,230, 61,149, 6, 51,230, -191,181, 4,130,128, 16,236,222,168,196,233,214, 4, 99,135, 13,243, 57,111,191,197, 98,246,121,152,224,234,226,231, 64,190,200, -243,207, 63,127,155, 82,154,208,171, 87,175,255, 43, 46, 46,214,251,160,248,157,235,125,100, 70, 70, 6,172,102,130, 97,195,251, -127, 48,119,238, 92, 29, 0,204,153, 51,199, 10, 64,215,144, 38,117,242, 56,213,248,238,198, 43,202,227, 33,243, 0,220, 19, 82, -224,179, 98, 76,170,145, 96, 7, 25, 57,151,154,188, 82, 93,146,254,176,231, 26, 44, 87,161, 80, 88, 0,252,203,254,241, 89,174, -187,242, 53,240,121, 73, 99,220,115, 47, 97, 83,240, 20,139, 62, 74,110,116,217,158, 82,253,122,209,190,166,123, 89, 7,141,181, -233,138, 66,161,208, 40, 20,138, 70,145, 69, 26, 48, 7,192,150, 65,169, 84,194,190,125, 47,242,156,182,239, 77, 61,176,223,177, -125,239,232,161,163, 97, 39,189,117,254, 63,193, 20, 29,177,108, 14,174,173,152, 56,238, 38,232,137, 4, 52, 70,125, 61,241,196, - 19,213,102,179, 57, 5,128,254,253,247,223,111,144, 18,141,139,139, 35,239,191,255, 62, 53, 26,141, 0,176,175,174,251, 86,174, - 92, 73, 22, 47, 94,236,248, 95,246, 84,192,245,142,237,174,193,157, 60,238, 47,184,122,184,136,175,251, 8,243,224,193,131, 7, -143, 38,129, 25, 64, 21, 0, 73, 35, 27,113,158,118, 12,228,188,163, 32,143,135, 3,124, 99,242,224,193,131,199,195, 5, 33,128, -102, 28,148,191, 1,182, 0,238,198,210, 7, 86,240,203,254,254,112, 29,137, 7, 15, 30, 60,120,252,241, 16,192,235, 11, 30,188, - 7,128, 7, 15, 30, 60,120,240,224,193, 19, 0, 30, 60,120,240,224,193,227,207,142, 26, 46,157, 83,167, 78,249, 28,145,235, 46, -152,240, 65,151, 23, 54,200, 15,254,126,133, 16,137, 75, 96,181,218,150,133, 9, 4, 12, 24, 34,176,253,101, 8, 8, 97, 64,137, - 16,132, 16, 48, 48, 99,199, 46, 17, 40,165, 8, 97, 90,193,155,242,217, 51, 42,182,134, 45,128,167, 28,182, 4, 3, 38,118,201, -215,195, 88,127,188, 60, 94, 30, 47,143,151,199,203,123, 48,229,241, 30, 0, 15, 56,116,228, 50,116,165, 58,152, 76, 20,183,239, - 16,236, 77,246,199,190,253,129, 96,136, 8,251,213,237,177,239, 96, 7,236, 83,119,192,225,227,109, 32,132, 16, 12, 36, 24, 17, -197,192, 79,236,199,249,127, 76,125,117, 58,157,250,234,116,122, 36, 85, 93,101, 98, 72,234,185,179,153,135,212, 71,143,232,147, -147,147,171, 0, 52,231, 57,232,195,143, 49, 79,141,144,206,153, 51,157,122,187,201,211,195, 10,165, 82, 41,165,118,212,183,187, - 30, 87, 80, 23,240, 61,138, 7,143, 38,240, 0,176, 24, 54,124, 8,231,151,240,104,106,134, 71,214,210,216,242, 26, 19, 25,153, - 34,140, 27, 99,193,233,223,253, 33, 22, 9, 33, 20, 8, 33, 18, 81,248, 9, 76,128,176, 57,132,168,196,144, 62,102, 72,196,126, -160, 0, 58,180, 3,158, 29,111,197,129,237,220,148,255,229, 11, 89,120,244,177,238,232, 24,218, 18,249,215, 46,118, 9,106,223, - 13,173, 59, 90,240,235, 47,191, 32, 57, 57,185, 4, 77,188, 35,150, 92, 46, 31,175, 82,169,118, 57, 29, 63,227,124,204,163,110, -204,157, 35,167,230,170,115,178, 33, 17,193,106,171,181, 24,165, 29, 43,213,157,218,143, 70, 69,117, 7,124,181,254, 63,127,216, -157,206, 98, 99, 99,213, 11, 22, 44, 0, 33, 4,107,214,172, 81, 55, 70, 78, 0, 54, 29, 0,175,255,239, 63,188, 34, 93,148,130, - 48, 76,125,237, 77,157,219,147,109,211,187,201,183,106,182,179,243,206,136, 60, 26, 23,108, 54, 64, 39, 47, 1, 55, 2,208, 84, - 96,238,179, 46, 28, 63,214, 4, 10, 1,132, 2, 17,134, 69, 18,180,109,195, 64, 40,100,224, 39, 18,160, 87, 56,131,107,215,205, - 24, 18,193,160, 85,136, 4,191, 30,108, 1, 0, 16,208, 74, 80,106,133,167, 20,193, 83, 95,157, 78,127,207,204, 68,215,142,157, -240,123,218, 49,164, 27, 77,208,221,209, 65,236,215, 28,189, 7, 14, 71,255,225, 99,161,222,161,130,156, 99,110,252,123,160,248, - 71,169, 84,170, 3, 97, 97, 97,200,204,204,100, 59, 76, 9,128,121, 42,149,106,167, 92, 46,143, 81,169, 84, 7,254,104, 47,197, -236, 56, 57,245, 19,106, 33,100,140,168,170,178,160, 84,239,143,239,127, 56,224, 85,253,143, 30, 51, 92,218,194, 95,139, 81,195, -197,232,218,229, 89,117,139, 22, 65, 48,153,205,184,125,251, 14,218,229, 93, 71,118, 78, 46, 94,125,101, 60,221,248,221,110,159, -218, 53,194,190,167, 2,192,125,155,236,251,105,253, 3,119,183,195, 93,179,102, 13,148, 74,165,180,169,210, 1,223,199,247,133, -110,221,186,181,246,126, 10, 77,164,188,148,202, 68, 41, 1, 65,108, 35,212, 59,205,251, 9, 36,253, 53,103, 29,111,207,146,233, -216,247,202,129,215, 18,245, 30,137,220,175,191,254,234, 56, 30, 55,110, 28,246,236,217, 83,239, 49,143,123,175,252,157,207, 57, - 19,129,112,212,249,165, 0, 0, 32, 0, 73, 68, 65, 84,122, 9, 64,234,145,116, 12, 31, 17,121,223, 10,109,245, 46, 59,164,243, -205, 62,189,132,140, 80, 0,157, 86,136,246,109, 69,104,223, 86,140,138, 10, 17, 36, 34, 33, 44, 66, 63, 12,234, 71, 48,224,113, - 1, 24, 34, 2, 33, 4,126, 34, 49, 68, 76, 53,136, 68, 12,179, 1, 48, 67, 95,175,242, 63,114,240, 0,186,117,104,131,179,167, -207, 34,175,232,230,221,242,149, 87, 64,114,238, 56,101, 4, 4,131, 34, 6,225,215, 61,222,233,216,117,235,214, 73, 51, 51, 51, -213,151, 47, 95,134,191,191, 63,252,253,253,101,219,182,109,211,120, 57,152,201, 84, 42,213, 1, 86,241, 59,117,142,150, 0,198, -126,253,245,215,119, 94,123,237,181,100,185, 92, 62, 70,165, 82, 37, 63,136, 29, 60, 50, 50, 82,154,158,158,206,249,185,165,163, -134, 73,251,134, 55, 87,119,234, 80,132,160, 22,126, 96,152, 0, 84, 86,154, 81,172,173,196,203,242,222, 84,210, 98, 16,190,253, -230, 7, 78,253, 72,132, 66,188,240,204,227,234, 62,125,122,227,102,161, 14, 39,126, 59,137,138, 10, 61,130,130,154, 35, 44,172, - 11, 24,129, 8, 22, 75, 30,226,102, 79,167,137,235,190,255, 67, 89, 55,177,177,177,234,133, 11, 23, 58,142, 23, 44, 88,208,104, - 94,128, 7,217, 3,160, 82,169,136, 92, 46,167, 73, 73, 73,112,183,177,210,253, 54,218, 21,138, 56, 16, 66,176,126,189, 82, 22, - 27,219, 48, 18,192,116,121,209,161,188, 51, 86, 52,115, 59,152,182,111,201, 32, 52,132,121,104,219,239,207, 10,103,101,239,142, - 20,120,244, 0,164, 30, 73, 7,128, 6, 19,129, 35,243,178,235,189, 62,226,211, 30, 62, 15, 22, 78, 57,206,189, 26,132,146, 53, -109, 33, 18,138,208,185, 99, 5,202,203, 69, 56,113,182, 51, 4, 2, 1, 4, 68, 0,177,200,140, 62, 61, 12,232,217, 67, 0, 2, - 6, 98,145, 31,196, 2,130,136,199,141, 8, 9,182, 98,211,255,213, 47,187,119,183,118,184,150, 83, 84, 83,249,219,145,119,227, - 26, 33,140,144,118,136,122, 28,193, 45,155,163, 68,119,135, 83,121,215,174, 93, 43, 93,185,114,165,250,218,181,107,206,167,213, -227,199,143,199,238,221,220,173, 77,149, 74,117,208, 89,249,187, 65,235,132,132,132,146, 55,223,124,115, 63,154,120,138,162, 30, -229,175,246,166,108,225, 97, 33,234,208,118,101,104,221, 42, 16,157, 66,219, 35, 32, 48, 0,215,174, 21,192, 98,177, 34,180, 99, -115,156,187,144,134,168, 17, 67,164,105, 71, 50,234, 29, 76,223,120, 99, 58,125, 60, 92,135, 71, 30,233,132,243, 23,174,225,196, -137, 11,184,125,167, 28,148, 2,193,193,254, 48, 24, 42, 48,112, 96, 31,148,148,148,162,224,196,111, 24,254,100,164, 52,245, 48, -119,162,242, 32,131,181,254,237,219, 78,131,245, 4,172, 93,187,214,107, 47, 0, 59,221,239,154, 9,216,205,118,178, 13,238,127, -157, 58,117,162,157, 59,119,110,112, 46,126,149, 74, 69, 38, 79,158, 76,183,108,217, 2,118, 99,165,250, 20,158,125, 43,220, 90, -229,143,138,138,146,178,155, 3,213, 65, 98,169, 7,153,142,255,173, 80,196,169, 27,242,142,186,202, 27,178,164, 2,199, 87, 52, -171,161,248,121, 60,156,214,191,171,203,191, 65, 83, 0, 13, 37, 2, 35, 62,237, 81, 39, 9,240, 69,249,179, 72, 73, 73, 65, 65, - 65, 1, 0, 32, 52, 52,148,122,243, 50, 8,104, 37,132,196, 2,177, 72,132,223,206,182,129, 64, 40, 68,115,145,222, 22, 7,208, -140, 65, 65, 65,115, 60,222,199, 10, 66, 8,228,207,154, 65,173, 12, 64,252, 64, 64, 97, 11,228,119, 15, 67,201,117, 20,106, 43, -144, 85, 80, 80,103, 89, 74, 74,181,208,221, 46,180,203,226, 60, 0,185, 42,127, 0,192,238,221,187,241,212, 83, 79, 73,247,238, -221,235,113,128,147,203,229,163,114,115,115,221,118,152,210,210, 82,231,211, 45,151, 45, 91,134,243,231,207,143,126,144,166, 2, -156,148, 63,103, 72, 71, 13,147, 74,132, 55,225,239,223, 18, 18, 63, 49,186,117,235,138,206, 93,187,162,172, 76, 3,173,182, 2, - 98,177, 0, 33,193, 18, 8,253, 91,122, 28, 76,133,180, 0,205,155,181,130,161,210,140,179,103,179,113,163,176, 20, 55, 11, 43, - 80, 89, 45,193, 35,161,102, 72,252, 4,200,206,202,197,163,221,187,227,198,205, 50, 84,154, 91,112, 26,160,157,221,254,117,157, -247,118, 58,160, 46,153,190,200, 98,173,255, 5, 11, 22,212, 58,191,112,225, 66,159,188, 0,238,118, 39,116,157, 59,110, 44,175, - 66, 90, 90,154,186,161, 27,242, 76,158, 60,153,170, 84, 42,200,229,114,184,155, 14,224,226,169, 98,149, 63, 0,100,100,100,212, - 42,147,253,186, 71,163,135,221, 97,176,177, 60, 46, 91, 22, 6, 98,242, 26,189, 91,197, 31, 26,194,216, 71, 41,110,205, 59,110, -220,184, 26, 94,146,167,159,126,186, 70, 93,241,110,255, 7, 7, 94,199, 0, 52,150, 71,160, 49,145,157,109, 35, 22, 5, 5, 5, - 94,145, 0,161, 80, 8,145, 64, 4,145,136, 96,228,112,192,160,175,198,149, 28, 49, 68, 66, 17,132, 22, 33,134, 70, 82,136, 69, - 34, 8, 4, 12, 64, 9,180, 58,224,248, 73, 33,172, 86, 43,128,219,117,202, 61,249, 91, 14, 42, 42,234,206,192,217,173,125,123, -170, 55, 19, 84, 86,150,194, 98, 53,115,126,206,147, 39, 79,214, 77, 58, 12, 6, 78,138,198,213,245,239,142, 25,238,216,177,195, -249,254,228,166,240, 2,184,115,241, 59, 43,127,251, 0,200,205, 2, 12,109,167,102,152,235, 48, 91,172, 48,154,204,184,125, 71, - 11,145, 88,130,234,106, 19, 76,102, 11,204,102, 43,204, 22,202,201, 19, 35, 22,233, 33,241,239,132,226,226, 82,148,149, 27,160, -213, 85,162, 69,171,254, 24,246,248,227,200, 72,221,131,142, 70, 51, 74,203, 74,209,179,103,119,248,137,133,208,151,107,255, 16, - 3,133, 61,242,223, 49,247,239,226,153,242, 41, 22, 96,193,130, 5, 53,188, 9,174,215,184, 18, 0,173, 54,198,113, 99, 92, 92, - 8,182,108,217, 82,163,191,178, 6, 66, 94, 94,158,207,187,114,202,229,114,186,101,203, 22,199, 54,227,117,197, 4,184, 42, 87, - 87, 79, 85, 90, 90,154,154, 13,124,163,148,210, 99,199,142,213,184,126,236,216, 49,181, 39,167, 7, 75, 26, 88, 18,224,108,197, -215,101,232,123,120, 54, 76,138, 74,198,102, 0, 83,214,232,241,196,146,138, 6,145, 47,215, 57,126, 79, 49, 1, 60,238,189, 55, -160, 46, 15,192,125,245,239,184,179,244, 27, 98,253,187, 88,172,200,206,206,102, 7, 20, 78,189, 87, 32, 16, 98,232, 16, 43, 4, -140, 16,199, 51, 37,184,148, 45,193,132,167,128,103,158, 6, 38,142, 35,232,208, 78, 12,137,216, 15, 18,177, 31,252, 37,126, 8, -237,224, 7,137, 88, 2,137,135,101,128,249,121,215, 73,137,246, 22,169,107, 32,233,222,173, 11,130, 90, 6, 66, 98, 53,162,194, - 96,186,239,157,226,200,145, 35, 7,142, 28, 57, 82, 67,225, 59,127, 0,160,184,184, 24, 19, 39, 78,108, 50, 43,223,110, 29, 73, - 93,207,217,191,123,101,201, 89, 44,128,222, 96,130, 94,111, 68, 89, 89, 53,110,221,210,225,198,141, 59, 40, 47,175, 70, 69,133, - 9, 21, 21, 70,232,245, 38,148,150,148,122,148, 85, 93,109, 70, 85,149, 5, 38,147, 17,205,155,139,209, 57,180, 5, 2, 2, 3, - 1, 0, 97,221,187,162, 83,199, 22, 8,106, 33, 1,165, 22,152,204, 86, 84, 87,235,255, 16, 3, 73,108,108,172,122,209,162, 69, -245, 42,243,216,216, 88,206, 22,169,125, 75,225, 58,175,175, 89,179, 6, 95,125,245,149,215, 91, 13, 59,109, 59,235,248,176, 10, -181,160,160,128,221, 61,211, 43,237, 54,121,242,100,154,148,148, 4,103,242,160, 82,169,200,164, 73,147,234,253,221,236,217,179, - 65, 8, 1,219,143, 35, 35, 35,165, 0, 48,116,232, 80, 25,171,200, 89,171,159,189, 78, 41,117, 92,231,240,180, 53,172,120,119, -196,129,203, 12, 74,235,214,173, 65,156, 88, 66, 67,229,241,120,240,148,191,187, 99,159, 60, 0, 15,146,229,127,119,128,183, 64, - 32, 16,120,253,187,225, 67,172,104,219,198, 15,101,101, 66,248, 9,205,240, 19, 11,160, 73, 23, 99,130, 76, 4,177, 72,132,178, - 50, 17, 82, 51, 3,209, 66, 66,192, 48, 12,198,197, 24,241,220, 4, 10,134,161, 88,126,202,251,114,202,229,114, 42, 8,144, 64, - 43,106,141, 0, 83, 62, 46, 23, 80,140,146,142,228,188,165,239,192,129, 3,113,244,232, 81,183,215, 2, 2, 2, 56, 15,150, 58, -157,110, 52, 0,108,216,176, 1, 51,102,204,112,156, 47, 46, 46,118,124,159, 49, 99, 6,138,138,138,154,164, 61,211,211,211, 53, -132, 16,176,243,164, 12,195,128,117,119,214, 51,111, 90, 39,242,174,223,144,181,105, 97, 80,251,137, 5, 48,154,172,168,170,206, -199,245,252, 98,104,117,101,208,106, 13, 40,214, 86,162, 88, 91,137,150, 33, 93, 1,228,212, 43,235,214, 29,138,194, 91,119,208, -187,119,119,148,232,116, 16, 9, 25,148,149,231, 67, 95, 98,197, 99,143,234,209,174, 77, 27, 4, 4, 4,192,207,207, 31, 55, 11, -203, 65, 4,193,156,202,232,236,146,111,172, 85, 0,141,189,130,160, 46,107, 29,184, 27, 11,192, 21, 10,133, 66, 19, 27, 27,139, -249,243,231,215,242, 42,176,211, 12,190,174, 44,152, 60,121,114, 13, 11,150,125,191, 8, 33,120,241,197, 23,145,148,148, 68,184, -146, 0, 87,203,223,249,154,171,167,193, 21,235,214,173, 35, 0, 28, 86,126, 70, 70,134,218,222,175, 53,118,111, 0,251, 87, 13, -128,164,167,167, 59,174,215,183,157,107, 90, 90,154,122,248,240, 97,178,163, 71,109,239,196,236,217,179,113,234,212,111, 50, 86, -133, 31, 59,118, 76,205, 62,255,208,161, 67, 61,122,202,214,173, 91,135, 47,100,193,152,178,214, 96,123,174,133,129, 53,174, 79, - 89,107,112,212,231, 76,153, 8,223, 28, 52,130,199, 67, 64,218,227, 87,214, 36,221,171, 22,227,212,169, 83,220, 87, 1,220, 11, -197,239, 28, 11,208, 16,235,191,166, 37, 95, 83,249,219,221, 76, 30,167, 2, 90,183, 22,128, 33, 2,180,105, 45, 64,143,238, 20, - 55,110, 8,193, 8, 8, 68, 66, 33, 68, 66, 17,126, 63, 19,136,144, 64, 17, 4, 2, 1,134, 71, 90,224,239,239, 7,171,149, 2, -212,226,147,242,111,214,174, 51,110, 85, 80,232, 47,107, 32, 36, 2, 92,190,145, 71, 46,115, 84,254,246,129, 77,118,253,250,117, -245,245,235,215,221, 61,175,134, 99, 57,198, 20, 23, 23,239,103,149, 60, 0, 76,156, 56, 17, 27, 54,108,112,220, 83, 86, 86,134, -162,162, 34,236,220,185,147, 93, 46,120,223, 59,175,125,224, 82,103,100,100,168,217, 96, 49,251, 57,175,149, 66,234,225,116,141, - 76, 26, 1, 90, 80, 6, 67,165, 9, 58,191, 42, 80,232, 80, 85,101, 70, 89, 89, 53,138,238, 24,112,227,102, 5,158,148,117, 1, -144, 90,175,172, 74, 99,107,228, 94,185,141,176,110,143,160, 91,183, 78, 40, 46,190,131,224,150, 22,244,232, 17,132,182,109,194, - 32,241,247, 71, 73, 73, 5, 78,156,188,136,252,130, 50,180,239,212,231,161, 29, 64, 18,149, 74, 74, 8,100,172, 46,117, 86,170, -245,173,219, 79, 84, 42,165,137,235,214,113,242, 2,172, 93,187, 86,237, 74, 0, 86,175, 94,141,245,235,215,203, 60,201, 75, 76, - 76,164,113,113,113, 68,161, 8,118, 42, 19,117,167,152, 41, 0, 76,154, 52,137,147,251,223,121, 74,161, 85,171, 36,248, 58,109, -192, 90,249,118, 2, 64, 41,165, 24, 62,124,184, 44, 53, 53,181,206,235,158, 20, 54, 59,183,158,154,122, 84, 77, 8, 1, 33, 4, - 3, 6,244,151,173, 91,183, 78, 83,251,222,187, 36,195,147, 60,102,178, 14,172, 60,249,168,174, 53,248,209,228, 53,231, 29,242, -184,128,143, 1,120,120,224,145, 0, 60,136, 22, 63,139,169, 83,167, 54,232,247, 12,195, 64, 32,176,125,122,135, 51, 24,216,207, - 2, 63,177,196, 70, 0, 68, 34, 12,139, 4,252,252, 0,145,192, 15,173, 91, 75, 32, 16,232, 97,177, 88, 97,181,122,239,182, 55, -104, 11, 33,233,212, 11, 87,146,255,131, 54, 66, 6, 71,242,174,121, 61,160, 44, 88,176, 64,179,110,221, 58, 89, 67,150, 1,178, -203,250,222,120,227, 13,199, 57,214,210, 47, 43, 43,131,193, 96,192,204,153, 51, 1, 0, 95,126,249, 37, 0,168,155,162,109,211, -210,210, 52,118,107, 95, 13, 0, 67,134, 12,105, 80, 0, 87,167, 46, 61,145,121,108, 47,218,182, 14, 64, 64,128,173,219, 87, 87, - 91, 80, 86,110,132, 86, 87,137,206,221,250,224,251,141,155, 60,182,201, 47,191,236, 35, 47, 62, 63,148, 30,203, 56,135, 39,135, -247, 71,151, 46, 93, 96, 50, 86, 97,224,128,199, 17, 24, 20,132,107,185,121, 40,184, 81,130,212,180, 11,208,149, 7, 97,207,134, - 77, 15,173,207,116,118,156,194,222,254, 4,179, 21, 10,199,178,112,171,139,210,103, 24, 2, 80,135,202,160,179, 21, 10,244,119, - 99,193, 18, 2, 10, 39, 90, 30, 23, 23, 7, 87, 47,192,252,249,243, 65, 8, 65, 92,156, 66,109,215,231,152, 29,167, 64,255,254, -181,229,197,197,197, 57,220,241,158,148, 28, 87,229,239,138, 73,147, 38, 97,244,232,209, 50, 95, 73,176,243, 92,125,100,100,164, - 44, 53, 53, 85, 83,215,117, 46, 65,138,246, 85, 5,148, 37, 95, 81, 81, 81, 50,133, 34, 78,227, 74, 58,156,228,195, 27,121, 91, - 22, 54,179, 29, 74,218,221,245,116, 44,204,115, 16,130,189,167,235, 31,251,220,229, 1,224, 99, 0, 30, 82, 2, 48,108,248,144, -123, 50,231,211, 88,150,191,115, 71,242, 5, 90, 29, 65,135,118, 12, 8, 97, 64, 24, 6,251, 14,216,230,247,253,252, 36,240, 19, -251, 97,226,211, 4, 18, 63, 49,252, 37, 4,218, 98, 1, 50, 78, 52,135,197,106, 65,231, 78,222,205,235,202,229,114,122, 35,255, - 10,116,153,187,209,163,179, 8,103, 11,124,159, 23,158, 61,123,182, 6, 13, 12,202,147,203,229,178,207, 63,255, 92,205,186,249, -139,139,139,167, 68, 70, 70, 86,236,223,191,127,215,115,207, 61, 55,182,184,184,152, 76,159, 62,125,175, 61, 95, 64,147,117,206, -244,244,116, 77,100,100,164,140,253,222, 16, 89,223,111,220, 68,166,191,250, 50,205,186,120, 30, 55,114,175,129, 97, 8, 44, 22, - 10,137,127, 8,194,123,247,197,158, 95,147, 57,215,233,141,219, 86,153,182,248,134,186,170,202,140,126,125,195, 16,218,177, 53, -242,174,223,130,238, 76, 14, 46,101,229,225,192,193,223,113,173,128,226,120,230, 89,159,218,233, 65, 73,254, 99,221, 28,236,243, -125, 3, 63,230, 40, 47,231,255,176,118,237, 90, 7, 1, 88,187,118, 45,144,187,161,214,189,238,228,113, 5,165,148, 52,164, 31, -199,197,197, 53,168,239, 57, 41,121,141, 47,215,221,121, 21,156,127,235, 78,158, 87,237,124,109, 43,146,214,190, 98, 27, 27, 70, - 61, 82, 67,249, 3,128,124,252, 19,182, 47,186, 83, 30, 9, 0,159, 7,224,193,193,250, 85,139,107, 77, 3,120, 69, 0, 30,240, -128,143, 6, 23, 46,243,164, 31, 36, 98, 49, 38,142, 39, 96, 8,193,144,193,102,156, 57,235, 15,134,216,230,252, 75, 74, 24,116, -108, 47, 0, 67,196, 56,125, 70, 12,137, 31, 96, 52, 25,113, 45,207,223, 43,229,159,147,245, 27, 34, 71, 63, 3, 97,235, 72,228, -100,101, 64, 88,152,132,160, 22, 33,180,180, 76,219, 36, 21,172, 82,169, 52,114,185, 92, 54,120,240, 96,117,124,124, 60,250,246, -237, 91,164,211,233, 48,120,240, 96,153, 78,167,195,188,121,243,212,118,229,175,105,234, 70,110,168,226,119, 37, 1, 0, 16, 53, - 98,136,180, 67,251, 14,234,192,192, 64,124,191,113, 19, 57,123, 46,199,187, 1, 61, 53, 67, 3,128, 88,208,154,158,191,148,142, - 14,237,154, 65, 34, 17,161,162,194,136,130,155,101, 32,194,206, 56,158,153,202, 71, 75,113,193,201, 55,129,238,255,139, 26,203, - 11, 79, 44,106,210, 34,197,197,133, 56,165,173,109, 28,133,230, 73, 41,123,163,180, 27,154,207,192,221, 56, 47,143,242,179, 61, -107,229, 77,219,135,199, 67,139, 1, 3, 6, 56, 2,254,214,175, 90, 92,235,154, 71, 2,208,216,249,248,239,119,126,127,239, 88, - 4,129, 78, 71, 16,208,158,160, 85, 8,193,224, 65, 38, 72,196, 2,248,137, 77,104, 21, 34,177, 15, 2, 4, 67, 7, 91,144,113, - 82,100,243, 22,112, 36, 70,114,185,156,246,233,217, 2,111,206,255, 16,149,226, 78,248, 41,185, 0,221,195,135, 0, 0,154, 29, -223,137,172, 60,208,138,242,166, 35, 1, 0, 72,110,110,174,116,213,170, 85,106,103,239, 0, 0,210,148,150,255,189,134, 61,217, - 79,131,235,253,208,225,147,100,250,171, 47,211,219,197,183, 81, 89,104,128, 68,210, 10,157,186, 61,206,105, 42,225, 97,135, 45, - 29,118, 35, 61,102,238, 6, 56, 86, 4,228,110,108,242,103,243, 20,220,247, 71,195,216,103,166, 52,170,229,206,199, 0, 60, 88, - 36,160, 46,229,239,209, 3,240,103, 0,133, 45,170,159, 48, 20, 20, 20, 33, 45, 41, 82,142, 8, 33, 17,139,224, 39, 22,226,217, -241, 20,148, 90, 17,220,202, 12,179,133,192,106,181,216, 7, 63,207,120,188,107, 5, 38,188, 40, 71,133,176, 7,218, 54, 11,196, -203, 47,132, 96,211,182, 51, 14, 18, 96,178,252,132, 51, 23,155,118,157, 56, 75, 4,156,142,249,183,199, 7,175,194, 31, 17,100, -178,142,208, 45,193,181, 53,131, 42,196, 39,121,235,117, 43, 17, 27,188,184,246,133, 19,139,154,220,234,255, 51, 99,255,239,166, -198,236,195,196, 70, 16,169, 19, 89,228,167, 5,154,138, 4,120,108, 44, 95,247, 17,230,193,131, 7, 15, 30, 60,120, 60,188,224, - 19, 61,243,224,193,131, 7, 15, 30, 60, 1,224,193,131, 7, 15, 30, 60,120,240, 4,128, 7, 15, 30, 60,120,240,224,193, 19, 0, - 30, 60,120,240,224,193,131,199, 31, 3, 53, 86, 1,156, 58,117,202,231,104, 80,119,193,132,141, 45,111,218,204, 56,143,191,211, -107, 11, 29,223, 3, 67,218, 59,190,255,240,109, 98,173,123,219,200, 94,243, 40,111,255,154,187, 25,243,198, 44,252,220,241,253, -182,250,107,248, 82,190,186,224,107,249,234,130,187,242, 61, 63, 93,225,241,119,153,234, 93,232,218,181, 43,174, 94,189,138,193, -178, 9,142,243, 63,127,175,188,231,245,231,169,191, 36,132,134, 74,223, 44, 40,112,206, 76, 72,238,103,255,115,149, 55, 97,194, - 4,233,238,221,187,107,100, 74, 28, 63,126,188,108,215,174, 93,154,166,120, 63, 30,100,121, 13,145,245, 71,174,191,232,232,232, -151,250,245,235,183,233,204,153, 51, 47,166,164,164,252,212, 8,229,163, 15,202,251,193,203,107, 90,121, 94, 19, 0, 87,124,241, -197, 23,210,170,170, 42, 16,129, 8,132, 16, 88,204, 38,136, 69, 66,204,155, 55, 79,211, 80,230,241,197, 23, 95, 72, 1, 96,238, -220,185, 13,146,165,215, 22, 34, 48,164,189, 67,241,183,239,220, 21, 0, 80,120,253,170, 79,242,246,175,121, 3, 99, 22,126,238, - 80, 92, 95,108,207,248,127,246,174, 60,188,137,170,123,191,147,164, 89,186,175,148,125, 43, 84, 86, 41, 20, 17, 89, 19,217,132, - 2,202, 82,180, 84, 63, 17,161, 1, 17,101, 83,164,159,191, 15, 63, 23, 4, 69,138,178, 6, 68,224,131,178, 21, 68, 89, 10,133, - 66, 74,217,180, 82,160,236,148, 82, 74, 55,160,123,218,102, 79,102,126,127, 52, 19,211,144, 54,147, 52,172,206,251, 60,243, 36, -179,228,100,230,206,189,247, 61,231,220,115,207, 5, 0,204, 24,221,235,185,212, 0,207,201, 15,162,167, 36, 2,231,228, 7,107, - 72,109,124, 52, 0, 32, 39,231,201,151, 95, 40, 32,206, 4,228,161,128, 36, 19,144,207, 45, 40, 64,218,252, 79, 1, 0,189,150, -124,247, 68,203, 45, 42, 42,138,218,177, 99, 7, 52, 26, 77,173,227, 66,161, 80, 30, 21, 21,133,237,219,183, 63,173,211, 3,251, -189,208,166,217,102,202,104, 84,101,230,222, 95, 0,224, 0,107, 7,213,141,159,126,250,233,213, 11, 23, 46,120, 23, 22, 22, 54, -246,247,247,247, 13, 15, 15, 47,152, 55,111,222, 22,103,229, 13, 28, 56,112,208,196,137, 19, 79,108,219,182,109, 10, 0,159,183, -222,155, 54, 25, 0,121,249,242,229,127,201,100,178,223,164, 82, 41,233,160, 72, 58,185, 50,229,130,254,202,154, 68, 92, 85,135, -169, 71, 32,147,133,171, 61, 0,150,248,126,233, 15, 98,159, 22, 93,229, 3,187,118,128,187,192, 13, 20, 69,193,104,164,112,229, -214, 93,252, 16,247,163, 68, 36,112,195, 7, 31,124,224, 20,121,199,111, 94, 32,238,220, 62, 85,126, 37,179,173,196,217, 27,167, - 9, 95,228, 19, 0,101,217,125, 51,241,215,231, 17, 96, 98,169,246,138,254, 12, 71,227, 62, 52, 55,164,186,174,171,111,142,165, -245,127,242,249,252,154, 86, 64, 81, 32,201,154,246,109, 52, 26,205,247,207,225,186, 49,182,162, 1,160, 73,163,154, 84,157,186, -202, 10,104, 13, 6, 0, 64,181,161, 70, 94,155,161,239,163, 93,231,238,140,136, 31, 0,186,245, 25,132,115,242,131,102,226,175, -235,186,199, 89,126,116,167,145, 9, 96,152,135, 7,146,148, 74, 57, 77,252, 0,112,243,200,209,250, 58,173,122,241,221,214,111, -196,233, 37,127,161, 32, 55, 3,237, 91,245,198,198,143,183, 59, 92,135, 35, 34, 34, 94,223,185,115, 39, 77,254, 6, 0, 26, 0, -238, 0, 72,141, 70,195, 19,137, 68,136,136,136, 16,219,242, 4, 60, 97, 4,191, 20,214,245, 80,210,246,181,158,202,130,235,232, - 23, 57,125,219,221,114,253,191, 0,252,246,180,117, 76,145,145,145,148,179, 11,240, 88, 17,163, 83, 88,185,114,165, 56, 45, 45, - 77,190,121,243,223,137,137, 74, 74, 74,144,153,153,137,145, 35, 71,254, 79, 44, 22, 75,230,205,155,199,232,253,202,100, 50,206, -182,109,219,254, 11,224,149,126,195,222, 16,109,219,182, 45,248,173,247,166,121, 1, 48, 2,104, 98,186,236, 5, 0,156,129, 3, - 7, 14, 0, 30, 94,234,188, 46, 82,237, 21,253, 25,210,226, 23, 83,117,181, 55, 7,218, 7,149,122, 54, 13, 92, 46, 15, 70,163, - 1,138,170,106, 76, 28,247, 58, 85, 85, 85,213, 80,194,166, 92,249, 94, 88,216,135,173,101,127, 45, 60, 5,246, 21,128,101,203, - 87,136,197, 35,198,203, 91, 52,242,129,187,144, 7,146, 36, 97, 36, 1, 30,151,128,191, 79, 7,116,110,223, 82,158,156,116, 80, -178,122,245,106,177,163, 74,192,138, 21, 43,196, 29, 67, 78,203,187,117,184, 3, 46,199, 40, 95,177,114,165,100,230,135, 31, 58, - 36, 67, 89,118, 31, 34,159, 0,248,120,123, 1,128,249,211,214,117,141, 91,180,182,235, 13, 56, 26,247, 33,122, 69,127,134,119, -223, 28, 11, 0,230, 79, 91,215,173,218,151,230,144,118,205,229,114,209,188,121,115,112,185, 92,232,116, 58, 40,149, 74, 24,141, - 70,148,151,151, 59,245,114, 61,121, 92,252,178,124, 47, 4, 62,192,131, 28,224,175,234, 2, 20,223,207,194,150,184, 5, 14, 89, -253,221,250, 12, 66,243,166, 53, 67, 36,205,109,144,127,235,214,173,205,195, 1, 0,144,159,159,239,146,242, 99,152, 92,149, 26, -230,225,129,175, 62,156, 1, 0,248,202,130,248,183,102,102,214,238, 76, 28,200,214, 58,113, 65,127,113,121,175,100,249,103, 45, -223,134,150, 28, 12, 1, 73, 97,200,235, 70,108,252,126,151,228,232, 42, 48,237,204,121,211,166, 77,251, 77,173, 86, 99,211,166, - 77,154, 73,147, 38, 9, 1,120, 2, 32, 55,109,218,164,155, 52,105, 18, 79,173, 86, 67, 40, 20,202, 27,218,209, 13, 27, 54, 76, -124,228,200, 17,185,105,193,150, 6,195,147,207,249,207,138,175, 62, 21,249, 94,219, 14,209,205,227,248,226, 85, 63,175,143,246, - 23,127, 89,165,163,158, 42, 5,128, 94,130,183,188,124, 8,229,239,159,236,240,179,191,252,242,203,226, 63,255,252,211,105,178, - 89,182,108,153,120,247,238,221,242,170,170, 42,155,231,239,221,187,135,221,187,119,203,223,123,239, 61,201,198,141, 27, 83,236, -212, 23, 98,219,182,109, 91,250, 13,123, 99, 66,230,133, 51,188,230, 77, 27, 27,222,122,111, 90,173,126,247,248,193, 95,209,181, -107,215, 14,219,182,109, 27,222,181,107,215,125, 0,112,234,212,169,122,219, 7,147,246, 86,211, 62, 8,192, 78, 34,158,238,221, -187, 83,135,146,142,226,194,149,107,230, 99, 26,141, 22,223,173, 88, 87, 61,125, 82, 20, 75,216,207, 49, 30, 10, 2, 92,186,116, -169,184,223,208, 49,242, 14, 45, 3, 32,112,227,128, 36, 73,220,191,127, 31,151, 51, 46, 64,103, 32, 65,146, 20, 2,124,220, 49, -116,248, 72,185, 90,107,112,248, 15, 5,110, 69, 8,105,121, 31,224, 18,232,212, 62, 15, 2,222, 3,135, 45,127, 75,242,183,134, -162,178, 10,247,243,114, 32,242, 9,168,211, 43, 80, 31,121, 89, 99,243,206, 95, 49, 99,116, 47,244,138,254, 12,245,104,217, 15, -129,207,231,131,203,229,194,219,219, 27,217,217,217, 40, 47, 47,175, 81,164,156, 36,255, 38,141,130,225,201,227, 98,204,204,175, - 49,124, 98, 31, 28,184, 82,128,251,106, 52,152,252,173,145, 95,120, 31, 87,207,157, 70,144,159,119, 13,249,243,184, 46, 41,191, -215,198,189, 11, 0,240,227,185, 57, 68,254, 0,240,127, 43, 87,225,255, 86,174, 50,147,127,146, 82,137, 79,134,142,172, 57, 25, -196,103,244,220,125, 98,219,136,167,206,125, 69,254, 94,171, 15,224,198,241,132, 7,220,193, 1, 23,205,130,251,226,195,175,230, -200,231,239,239,192, 72,141, 72, 73, 73,209, 3,192,230,205,155, 85, 0,132,244, 50,202,155, 54,109, 34, 1,184, 91, 46,171, 28, - 21, 21,229,212,184, 92, 92, 92,156,216,145,227, 12,208,175,103,247,110,170,132, 95,247, 74,187,119, 9,229, 42,175, 29, 67, 78, - 81, 21,238, 85,168, 64, 82,148, 83,129,192, 20, 69, 81,101,101,131,169, 1, 3, 6,184, 52,145,152, 5,249,195,223, 63,217, 41, - 25,105,105,105,114, 0, 4, 65, 16,120,249,229,151, 29, 46,179,228,228,228,135,200,255,220,185,115,152, 56,113,162,121, 95,175, -215,227,198,141, 27,242,184,184,184,122,189,152,219,182,109,251,176,223,176, 55, 70,126, 19, 59,155,151,144,144,128,159, 87, 44, -229,153, 60, 70,102,242, 79, 72, 72,192,202,149, 43,209,181,107,215,125,246,218,155, 53,249,215,213,222,134,247, 53,121, 1,189, - 60,236,202,251, 97,197, 26, 51,249, 23,149,148,162,168,164, 20,138,170,106,184,185,241, 60,215,108,218,174,129,171, 22, 68, 96, -241, 88, 17, 22, 22,246,208, 86,175, 2,176,122,245,106, 42,160,245,139,104,221,216, 23, 26,189, 17, 4, 1, 36, 37, 29,198,255, - 54,111,194,165,140, 12,124, 50,103, 22,184, 92, 14, 72, 35, 9,111,119, 1, 90,191,216, 79,190,124,249,114,198, 13,108,229,202, -149,226,206,237,239,202,189, 61, 85,248,101,115, 17, 56, 4,133, 94, 93,111,202, 87,174, 92,233, 80, 35,181, 69,254, 52,241,171, - 21,165,181, 20, 4, 69,101,149, 93,121,182, 26, 19,221,144,210,226, 23,215, 34,184,205, 59,127,101,116,143, 33, 33, 33, 8, 8, - 8, 64,101,101, 37,248,124, 62, 56, 28, 14,212,106, 53,202,203,203,193,229,214, 52,114, 71, 22, 91,218,243,219, 94,204, 90,126, - 4,123, 87,124,142, 38,141,130,225,238,225,143, 60, 99, 1,182,196, 45,128,167,169,211,224, 50,148,103,139,252,105,226, 87, 20, -222, 70,135,230,141, 80,165,210, 64,224, 46, 0,140, 70,187,241, 0,246,202,111,193,250, 3,184,122,254, 44,186,180,237, 4,133, -209,190,210, 72,147,255,205, 35, 71,241,127, 43, 87,153,143, 39, 41,149, 72, 82, 42,145, 45,253, 47,142, 92,187,132,206,189,218, - 2,165,246,151,102, 30, 56,175,173,120,250, 71,131,228, 65, 30, 29,161,166,170, 0,109, 17,248,218, 50,104,141, 85,208,144,106, -144,124, 79, 52,235,223, 19, 67,166,183,162,236, 89,115,244,184,191, 84, 42,117,151, 74,165, 64,205, 16, 0,164, 82, 41, 76,251, - 38, 11, 74,131, 29, 59,118, 56,220,104,103,207,158, 45,158, 51,103,142,188, 83,167, 78, 20, 65, 16,114, 0,120,251,237,183,169, - 86,173, 90, 81,159,127,254,185, 83, 75, 51,123, 9, 56,155, 86,125,246,158,104, 88, 51, 45,247,204,141,251, 56,144,195,193,103, -135, 30,104,255,155, 82,173, 80,234,241,174, 51, 50,203,203,135, 60, 74,203, 31,254,254,201,136,142,142,118,120,136,208,146,240, - 41,138, 34,232,229,164,153,226,221,119,223, 21, 63,120,192,204, 40,209,233,116,184,124,249,242,241,250,234, 11, 0,113,243,166, -141,249,145,145,145, 0,128,244,244,116, 28, 63,248,171, 48,191,240, 62, 73,147,191,233,217,205,237,237,242,229,203,113, 13,105, -111,223, 77, 26,137, 43,183,243,208,184,109, 19, 64,169, 98,252,236, 69, 37,165,208,235, 13, 38, 5,199, 0,189,222,128,188,187, - 57,194, 6,190, 86,194,206, 62,139, 39,136, 90,174, 40,173, 86,139,238, 29, 58,200,221, 69,110, 32, 73, 10, 70, 18, 56,125,242, - 20,254,251,213,215, 32, 41,224, 86, 86, 22, 46,101, 92, 68,151, 46,221,192,229, 18,120,161,109,115,100,159,103,238, 5,224,243, -138, 16,218,186, 16,224, 17,200,187,167, 7,120, 4, 94,236,112, 23,105,151,139,156,126, 0, 75,247,190, 45,207,128, 90, 81, 90, -107, 54,128, 61, 88,186,247,109,105,218,105,241,139, 49,100,246, 74,155, 81,236,150, 48, 24, 12,112,119,119, 7,135,195,129,159, -159, 31, 84, 42, 21,148,202,154,101,128,131,130,130, 80, 90, 90,234, 80,142,108, 77, 57,208, 75, 36,194, 39, 43, 78, 98, 72, 55, -224,238, 5,224, 47,211,185, 79, 86,156,196, 79,179, 37, 48,146, 70,135,203,239,234,185,211,230,239,131,194, 59,128,231,197, 65, - 82,202, 53,116,239,208, 2,222,158, 2,108,222,157,140,158,146, 8,228,219,152, 5, 96,175,252,246, 93,163,128,123,192,232, 65, - 4,214, 31,200, 70,128, 95, 27,140,237, 75, 48, 42, 63,218,221,159,164,252,123,233,100,234,139, 56,160,153, 2,196,212,133,160, -254,251, 21,192, 81,131, 72, 91, 68,119, 42,117, 22,102,200, 56, 79,121, 43,223,112, 84, 26,171,161, 45,207,194,150,220,109, 56, - 53,186, 28,157,166, 72, 48,116,166, 39, 68,126, 47, 64,200,243, 3,111,180, 2, 83, 12, 83,168,159,215,255,108,179,147,146, 74, -165, 20,173,180,113, 56, 28, 80, 20,165, 51, 41,209, 26, 14,135,163,162, 40,202, 31, 0,137, 6, 76,175,141,139,139, 75, 25, 54, -108,152,164,180,180, 84,158,148,148, 84,163,248, 36, 37,161, 99,199,142,232,208,161,131,132, 62,230, 8,170,180,228, 71,147,255, -239,167,253,223, 71, 52,230, 80, 26, 5,166,198,103,234, 13,122,253, 74,173, 17,139, 0, 56,181, 24,197, 27,111,232, 30, 57,249, -199,199,199,167, 56, 99,253, 91, 14,153, 16, 4,129, 94,189,122,137,153,174, 42,105, 52, 26, 29, 82, 24,238,220,185, 3,153, 76, - 70,172, 89,179,198,214,105, 33,128, 78, 0,120,175, 70,140,173,200,206,206,246, 77, 79, 79, 71, 66, 66, 2,194,179,179, 57,233, -233,233, 0,128,240,240,112,188, 54,176, 39,188, 61, 5, 88,185,113,111,209,196,137, 19, 99,215,172, 89, 51,219,209,246,118,239, -183,197,240,234, 44,132,103,251, 89,216,181,120, 10,186,117,105,140, 23, 70,126,109,183,125, 40, 42,171, 32, 20, 10, 0, 0,110, -110, 60,168, 84, 26, 87,243, 12, 75,250, 79, 0, 76, 22, 3,170,213, 81,145, 36, 9,119, 1, 31, 58, 3, 5,146, 2, 56, 4,176, -240,203,175, 97, 36,129,234,234,106,220,191,127, 15,193,193,141, 65, 81, 36, 12, 6, 35,132,110, 60,112,221,152,185, 96, 87,173, - 90, 37,110,223, 58, 95, 30,232, 87, 89, 83, 29, 76, 27, 65, 80,232,209,249,150,156,158, 21,224, 8,104,235,158,118,247, 91,147, - 63, 19,235,223, 90,139,166,137,127,213,190,180,135,200,159,169,245, 15,212, 4, 12, 9, 4, 2,248,248,248,152, 93,134,116,224, -159,143,143, 15, 26, 55,110, 12,131,129,185,242,180, 49,249, 4,124, 90, 3,226,208,154,253, 76, 67,141,251, 31,168, 57,246,249, -215,114, 84,232, 28, 27,146,201, 47,172, 9, 86,108,217,200, 31, 94, 62, 30,224,121,115,161, 41, 81, 3, 28, 14,154,180,106,142, -211, 25, 57, 78,149,223,187,115,191,193,128,222,175,130,119, 31,168, 14, 6,220, 57, 28,244,110,221, 6,210,209,193,140,228, 88, -143,245,111,125,115, 10,198,188,209, 31,104,167, 1, 46,241, 0, 79, 30, 48, 42, 28,205,215,174,103,230,141,105,230, 15,157,174, - 12,132,182, 20, 91,114,183,225,236, 36, 31, 12, 24, 51, 9,253, 26,189, 38,185,114,196, 0, 3,169,132,155, 78, 9, 67, 7, 18, -197, 15,152, 5,141,154,148, 55,205,164, 73,147, 56, 0,202, 41,211, 10, 81,166,253, 6, 33, 41, 41, 41,165, 99,199,142, 18,119, -119,119, 4, 6, 6,194,221,221, 29,169,169,169, 68, 82, 82, 82,138, 19,226, 26,143, 28, 57,114,253,170,117,191,112, 22,166, 84, -147,187,207,100, 65,171,211, 43, 53, 70,204,115,132,252,173, 93,254,169,169,169, 4,189, 61, 45,228,111,203,221,239,168, 23,160, -186,186,218,252,253,220,185,115,230, 13, 0,230,204,153, 83,107,223,226,122, 65, 29,226,154, 2,104,109, 82, 10,221, 95, 27,247, -182,198,210, 19, 64, 91,254,175,244,237,107,217,222, 14, 72,165, 82,141, 35,237, 45,102,212, 0,188, 24,222, 1, 94,221,188, 80, -112, 44, 23, 16, 10, 48,110,230,191,208,235,157,159, 24, 61,179,193, 96, 68,193,189, 7, 6,218,242,167,145,119, 55,167,161,175, -150,170, 99, 99,241, 20, 40, 4,176,101,169, 80,166,206,141,164, 0, 35, 89,163, 4, 16, 4,240,235,158,221, 24, 51,118, 60, 2, -131, 26,153, 59, 64,202,129,119,201,229, 20,161,115,187, 60,243,254,139, 93,220,205,186, 97,143, 78,217,224,114, 28,247, 2, 88, -187,251,109,157,119,196,250,183,118,247,219, 58,111, 57,151,189, 62, 84, 86, 86,162,170,170, 10, 90,173, 22, 36, 73,162,184,184, -216,236,254, 87,169, 84,168,174,174,118,104, 8, 96,239,138,207,145,114, 5, 80,228, 0,122, 53,240,211,124,137,217,253,127,254, - 2,112,241,222,105,112, 29, 44, 63, 69,225,109,248,251,120, 32,192,223, 3, 47,132,118, 68,246,157, 98,100, 22,148,162,101,128, - 15,180, 15,138,144,117, 43,171, 86, 46, 0, 38,229,215, 71,252, 58,250, 73,162,176,119,255, 46,200, 83,119, 97,219,178,185, 24, - 55,119, 17, 46,233,129,226,210, 34, 70,229,103, 57,214,255, 94,159,151, 17,221,169, 21,118,237, 61,142, 75,151,114,176,236,114, - 58,118, 12,249, 23,176,225, 12, 10, 10,138, 25, 89, 23,205, 53, 2, 24,117, 37,208,233,106, 34,171,131,155,181, 64,135,142, 29, - 37,149,162,154, 88, 12, 53,169, 2, 71,171,132, 72,201,197,131,123,245, 43, 0,244, 59,211,104, 52,208,104, 52, 66, 0, 58, 0, - 94, 26,141,198,219,122, 74, 96, 3,188, 0,226,212,212, 84,121,199,142, 29,241,246,219,111, 75, 74, 74, 74, 48,118,236, 88, 71, - 58,206,126,124, 62,191,218,211,211,211, 48,100,200,144,123,243,231,207,111, 26, 27, 27,155,253,215,133, 75, 35,118, 92,213,222, -208,147,112,120, 61,214, 71,225,242,119, 37,249, 91, 91,255,180,194, 66,191, 51,166,177, 0,110,110,127,199,168, 44, 91,182,204, -188,217,218, 7,204, 51,124,234,122, 55,124,211,198, 1,192, 83, 20,222,182,233, 78,167,219,219,133,243, 23,238, 76,156, 56, 49, -198,145,246,214,255,165, 23, 48,184,111, 40,190,249,114, 41,126, 88,158,136,255,108, 61,142,105,175,246,196,253,223, 19,161, 40, -175,100,210, 62,136,200,209,175, 65,175, 55, 92,208,235, 13, 6, 75, 5, 0, 0, 22, 45, 92,208, 16, 11,158,181,252,159, 32,108, -141,253, 91, 43, 1,181, 20, 0, 14,135, 3, 69,181, 10, 92, 14, 1,131,193, 8,146,162, 96, 32,107,130, 72, 51, 46, 94,192,171, -131,134,213,184,201, 40, 10, 92, 14, 23, 85, 42, 29, 12, 58,173,125,235,127,245,106,113,155,102,247,228, 65,254, 10,179,150,209, -167,151,167, 41, 70,151, 0, 65, 80,232,222, 49, 75,190,106,245,106,198, 94, 0,218,186,175, 47, 24,208, 41,235,181,158,224, 26, - 71,224,231,231,135,226,226, 98, 8, 4, 2, 84, 85, 85, 33, 40, 40,200, 28, 20,168,209,104, 80, 81, 81,225,144, 2, 16,243,205, - 14,252, 52, 95, 2,159,214, 64,202, 21,224,163, 37,114,120,242,184, 24,251,241,183,200, 39,239, 35,126,217,167,224,114,152,203, -163,173,255,240,240, 80, 4,181,109,141, 70, 65,129,224,115, 8, 24, 8, 10,197, 74, 53,202,171, 52, 78,149,223, 15,139,127,195, - 27, 29,219,192,219, 59, 0,238, 65, 77,161, 47, 43,199,133, 3,219, 81, 81,150,235, 84, 37,254,101,241,135,192,236,193,224, 25, -116,104,173, 4,138,184,149,248,233,222, 95, 0,223,155,177,140,243,251,255,144,148,112,212,200,229,171,208,179,157, 4,157,254, -229,137,108,191, 20,121, 80,208, 5,121,139,222,217, 80,112,170,160,165,212, 80,109, 37, 33,244,244, 98, 98,249, 91,118,240,244, - 44, 0,190,171, 26,238,225,195,135, 1, 0,209,209,209,146,184,184,184,148, 49, 99,198,152, 45, 70, 38,228, 31, 20, 20,116,104, -253,250,245, 30, 50,153,140, 59,123,246,108,204,154, 53,139, 58,115,230, 76,111, 0, 73,106, 3, 58, 2,248,211,209,123,146, 74, -253,234,116,251, 59, 27, 16,232, 74,242,183, 38,120, 75,133,133,162, 40,194, 20, 24,104,191, 93,228,231,159,161,191,111,219,182, -205,188, 89, 31,163,225,239,239, 15,169, 84, 90, 87, 39,152, 15,160, 2, 0, 39,191,240, 62,206,158, 61,107, 30,243, 15, 15, 15, - 7, 80,179,252,246,206,125,137, 40,175,210,168, 0, 44,156, 15, 74, 29, 0, 0, 32, 0, 73, 68, 65, 84,146, 74,165, 70, 71,218, -219,239,123,191,192,176,249, 51, 49, 98,196, 32, 4, 10,184,168, 34, 40, 36,101,230,225,236,149, 2,135,136,122,250,164,168,151, -178,179,178,120,121,119,115, 64,111, 38,242, 7,107,181, 63,155,196,111,125,204, 22,106,197, 0, 8, 4, 2,220,186,118, 73,210, -186,169,191, 92,228,198,131,209, 72,130, 32, 8, 16, 4, 16, 35,157, 1,138, 34, 97, 52,229, 3, 80,105, 52,184,158,153, 13, 62, -223,110, 84, 55, 12,250, 50,116,239,116,199,178,199,192, 7,179,239, 96,207,214,246,230,170,213,179,203,109,252,145,209,209, 97, -235,223, 22,241,171, 21,165, 0,224,148,245,111,171,161,165,197, 47, 6, 0,198,214, 63, 80, 51,207,191,113,227,198,208,106,181, -120,240,224, 1,140, 70, 35, 2, 3, 3, 81, 90, 90,138,192,192, 64, 83,185, 50, 39,236,226,251, 89,248,252,107, 57, 20, 57,192, -247,115,251,163,218, 96,196,156, 37, 9,248,113,126, 36,230, 46, 59, 0, 30, 65,192, 1,254,135,162,240, 54,154, 4,250,194, 13, -110, 48,130,192,189, 59, 87,113,183, 72,129,144, 32,127,252,126,254, 12,174, 95,131,195,214,255,184,201,115,224,230, 15,112,184, -192,166,196, 59,216,179,250, 19, 76, 94, 44,195,156, 81,221, 48, 99, 80, 43,135,202, 47, 73,169,196, 15,163, 39, 0, 21, 66,128, -112, 3,126, 88,138,241,127,157,196,145, 65,211, 65,124, 59, 19,196, 31,159, 50,182, 48, 46,222, 11,192,203,106, 5,170, 69, 92, -168,132, 66,132,140,115,131,150, 82, 67,193,113,131, 1,161,160,140, 42,232, 75,238,225,244, 10, 5,162, 39,134, 32, 69, 46,127, -236,141, 54, 38, 38,134, 2,128,117,235,214,209,174,126, 98,246,236,154, 97,224,173, 91,183, 50,125,179,125,155, 54,109,122,248, -219,111,191,245,184,117,235, 22,220,220,220,224,237,237,141, 75,151, 46,233, 1, 20, 55,228,254,234,155,147,239,140,119,192,149, -228,111,109,253,215, 16,243,195,211, 7, 77,211, 3, 83,236,220,215,173,157, 59,119,246, 97, 58, 60, 39, 20, 10, 39,215,173, 52, - 73,171, 6, 14, 28,120, 7, 64,120,230,133, 51,176, 28,243,255, 96,242, 4, 28,110,219, 22, 9, 9, 9, 72, 79, 79,199,161,182, -109,221, 39, 78,156,184,241,196,137, 19,140,219,219,155,131, 95,134, 15,233, 7, 21,220,176, 39,110, 38, 86, 31,184,136, 79, 94, -235,135, 73,203,182, 97,252,162, 45,142, 90,224,196,162,133, 11,108, 37, 2,162, 44,148, 0,214,162,127,206, 80,203, 3,240,193, - 7, 31, 16, 21,247,178,112, 59,175, 20, 60, 55, 46, 12, 70, 18,122,131, 17,231,207,167,227,127,255,219, 8,157,145,130,222, 72, -130,207,227,160,168,188, 26, 5,215,207, 74,102,205,154, 85,111,131, 90,189,122,181,184, 99,200,221,191,173,127, 83,189,218,179, - 53,180,166, 62,113, 40,128, 67,129,195, 33,209,187,219,117,249,106, 6, 94, 0, 91,214,191,229, 44, 0, 15,255,198, 14,145,191, - 45,235,223, 50,170,118,200,236,149, 14,145, 87, 77,167, 88,142,234,234,106,184,185,185,153,173,127,146, 36,205,159,142, 42, 0, - 91,226, 22,224,124,193, 9,120, 54,174, 9,250,243,226,113, 81,124, 63, 11,222, 2, 55, 84,148,229,131,203, 33,192,227, 48, 27, -126,166,173,255, 22,254, 94,184,150,125, 7, 6,157, 14, 2, 30, 31,213,213, 26,252, 46, 63,131,158,146, 8,135,200,159, 46,191, -215, 63,252, 10,241, 63,253, 8, 21, 9,180, 8,105,142, 43, 87,255,192,156, 81,221,156, 42, 63, 0,152, 19,210, 19,251,111, 29, - 7, 20, 6, 64, 24,136,163,105,215, 64,124, 59,147,238,152, 24, 23,222,137,165,217, 41,167,143,166, 1,186, 42, 84, 19, 85, 40, -231, 84, 67,193,211, 67,111,172,132, 64,163,130,176,240, 14,118,196,222, 66,235,176, 80,212, 21, 0,104, 13,145, 72,100, 73, 2, - 16, 10,133, 54,207, 49,197,250,245,235,177,126,253,250, 6, 53,102, 47, 47,175,143,178,178,178, 60,188,189,189, 33, 18,137,224, -239,239,143,226,226, 98, 16, 4,161,114,101,167, 65, 91,252,145,145,145, 20, 80, 19, 16,232, 72, 80,160,171,201,255,229,151, 95, - 22,219, 11,168,101, 26, 11,224,225,225, 17,195,227,241,110, 91, 31, 95,182,108, 89, 45,203, 31, 0, 90,181,106,133,193,131, 7, -111,178,103,255,228, 23,222,175, 21,237,255,249,255,205,134,128,199, 71,112,112, 48,232,152, 0,211,121, 15, 71,218,219, 20,241, -139,152,181,244, 71, 84, 61, 40, 66,144,119, 35, 92,189,150,139, 73,203,182, 57,220, 62,172, 8,159,176,250,189,165, 28,214, 19, -240, 12,224,226,197,139,245, 38, 3,170,211, 3, 0, 0,243,230,205, 75,249,126, 41, 33,161,168,209,242,214, 77, 3,224,229, 46, - 64,167, 46, 97,232,212,185, 27,120, 28,160, 90,109, 68,238,189, 50,164,165, 28,148,120,122,184,219,253, 3,165, 74,133,208, 86, -247,160,209, 10, 77, 89, 91,106,170,145, 72,168, 1, 69, 1,101, 21, 2,128, 0,188, 60, 12,232, 26,154,131,147,231,236,103,177, -179,180,254, 45, 45,126,145, 79, 0,220, 40, 61, 96,248,187,191, 51,242,236,223,163,165,245,111,105,241,211,199,178,174, 94, 48, - 95,203, 36,203,158,165, 18, 0, 0,141, 27,215, 40, 35,101,101,101,240,246,246, 54,187,255, 29, 81, 0,104, 37, 0,248, 22,211, - 35, 7, 2, 63,157,196,234,127, 71, 96,252,220, 31,177,109,241, 12,240, 8, 2,124, 1,179, 25, 59,180,245,127, 45,183, 8,237, - 90, 4, 98,195,207, 59,208,186,117,107,248, 52, 13, 65,183,166, 33,208,107,255,118,255,187, 49,144, 73, 91,255, 95, 79, 30,132, -143, 22,110, 66,139,182, 68,131,202,143,182,254,135,238,253, 5, 71,162,163, 64, 52,239, 13,160, 38, 43, 32, 0,220, 81, 42,205, - 74, 98, 38,152, 37,240, 89, 53,233, 54, 49,112, 30, 37, 14, 25, 91, 37,111,221,190, 11, 42, 69,192, 29,220, 69, 85, 78, 49,138, - 23, 25, 81, 93,222, 28, 55, 78,103, 50,126, 33, 36, 73, 18, 34,145,136, 82,171,213,176,176, 60, 41,145, 72, 4,146, 36,137, 39, -209, 89, 86, 85, 85,125, 63, 99,198,140,209,235,215,175, 23,250,248,248, 64, 46,151, 99,249,242,229,149, 58,157,238, 53, 87,254, - 15,109,241,211,211,229, 28, 13, 4, 76, 72, 72, 32, 76, 73,126, 26, 76,254, 0, 96, 65,236,118,203,220, 94,134, 65,169, 84,170, -147,201,100,189,119,237,218,117, 73,169, 84, 54,209,235,107,166,153, 90,147,127,167, 78,157,208,187,119,239,145, 82,169,212,222, -127,242, 20,133,183,241,205, 23,159,227,215,253,135, 48,172, 95, 15, 28, 75,254,163,198,128,105, 26, 2,159,166, 33, 8,207,206, -198,107,227,222, 46,201, 45, 85, 13, 5,176,155,169,245, 63,107,221,126,196,190, 63, 20, 77, 27,139,205,202,133,117, 57, 52, 48, -155, 34,235, 9,120,142,148, 2, 70, 10, 0, 0,124, 50,111,110,202,247,223,147,146, 59,205, 95, 64,219,246, 29,229,222, 30, 34, -144, 20,160,214,234,144,157,157,141,226,236,139, 18, 47, 79, 15, 76,159, 62,221,110,195, 21, 9,133,216,117,120,160,132,142,128, -175,215, 29,193,225,192,195,131,185,245, 68, 79, 1,244,240,111, 12,210,168,175, 33,127, 19,244,132,155,221, 20,187,214,160,167, -212, 12,153,189,178, 22,105, 57, 67,254,150, 74,128,101,226,159,178,178, 50,251, 47,192,142, 18,176,197, 98,150,240,250, 69, 31, -252,189,163,175,134, 39, 67, 57, 45,252,189,176,235,220, 69, 92,185,113, 19, 61, 37, 17,181, 72,223, 17,242,167,241,250,135, 95, - 97, 79, 15, 15,124, 56,166,131, 75,202,111, 78, 72, 79,204,221,183, 11,196, 55, 11,113, 40,248,101, 44,175,190, 82,235,252, 88, - 31, 95, 44, 86, 84, 56, 68, 28, 39,150,102,167,248,241,134, 32,191,252, 54,138, 75,239,225, 65,166, 39,184, 70,111,244,125,177, - 63,118,156,222,241, 68, 59, 53, 23,101,251, 59,183,113,227,198, 33, 4, 65, 28,253,241,199, 31,133,111,188,241, 70,165, 74,165, - 26, 10, 39,198,252,235,131, 43,166, 0, 74,165,126, 46, 33,127, 27, 86,170, 61,229,131,193,189, 73, 75,100, 50, 89, 72, 85, 85, -213, 55,233,233,233,179, 11, 10, 10,160, 84, 42,193,231,243,209,164, 73, 19, 4, 5, 5,189, 33,147,201,126,223,178,133,209,146, - 0,215, 1,132,183,240,247,194, 43,175,188,130,139,183, 10, 16,216,166,115,173,246,246,218,184,183, 85, 0, 86,124, 19, 59,123, - 55,211,231,152, 34,126, 17, 67,146,255, 68,244,194,255, 97,192,128, 1, 8, 14, 14,182,169,104,185,240,181, 19, 78,144, 63, 85, -207,113, 86,137,120, 2,164,207, 40, 21, 48, 0,124,242,201, 39, 41,171, 86,173, 18,159, 79,201,148, 0, 53,145,180, 20, 69, 65, - 32, 16,224,211, 79,230, 49,110,180, 31, 58,152,230,151, 41,104, 87, 63,215,160, 2, 12, 42,115, 4, 60, 77,252,142,206,197,162, - 93,253, 89, 87, 47, 32,235,234, 5, 4, 5, 5,161,184,184,216, 41,226,247, 9,106, 10, 29,131,224, 72,166,136,254,106, 11,206, -156,116, 93, 49,230,228,228,152, 87,251,211,107, 53, 15,145,191, 35,196, 79,227, 95, 61, 60, 92, 86,126, 0, 64,196,125,106, 38, -126,154,252,239, 40,149,146,177, 62,190, 72, 2, 82, 22, 43, 42,156,122,246,223, 22, 31,181,232,120,212, 0,128, 29, 87,153, 39, -236,161, 40,138, 16, 8, 4,102, 47, 0,253, 29, 0, 4, 2, 1, 97,235,251, 99,198,169, 95,126,249,101,192,238,221,187,231, 84, - 86, 86,198, 1, 72,115,245, 31,184, 98,234,159,139,201,201,229,144, 74,165,106, 0,115, 76, 91,131,222,199,229,203,151,251, 2, -104, 19,216,166,179, 74,175,213,184,155,218, 91, 37, 0, 5,128,235, 45, 3,220,223,148, 74,165, 14, 85,232, 33,159,175,127, 92, -196,239,148,162,229,228,245, 44, 92,128,176,176, 48, 70,228,111,215, 0,109,232, 74,125,143, 2,244,216, 62, 77,252,104, 32,241, -211, 99,211,138,162,124, 40,138,242, 17, 20, 20,212, 32,139, 31, 0, 12, 70,210, 97,239, 67,125, 40, 42, 83, 56,125, 47,214,160, -199,246, 93, 69,252,143,160,252, 8, 0, 24,230,225, 65, 89, 90,253,221,121,110, 13, 34,254,127, 24,254,170,172,172,140, 98,139, -225,201,227,196,137, 19, 50,153, 76,246,191,220, 82,149, 74,175,213, 88,142, 71,122,183, 12,112,247,115, 98,245, 63, 2,168, 25, -202,120,214,148, 42, 22,143, 87, 9, 96, 84,153,156, 93, 71,152, 5, 11, 22, 44, 88,176, 96,241,236,130,195, 22, 1, 11, 22, 44, - 88,176, 96,193, 42, 0, 44, 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88,176, 10, 0, 11, 22, 44, 88,176, - 96,193,226,185, 64,173, 89, 0, 23, 47, 94,116, 58,138,212, 86, 48, 33, 43,143,149,231, 42,121,166,181,213, 57, 0, 72, 91,201, - 87,216,242,171, 91, 94, 88, 88, 24, 93,118,244, 92,110,234,226,197,139, 36, 91,126,172,188,103, 73, 94,120,120, 56, 47, 61, 61, -221, 0, 0,189,122,245,162,218,183,111,143,248,248,120,130, 45, 63,219,242, 28, 86, 0,158, 19, 52, 40,201, 68,100,100,164, 24, -128,101,202, 80, 73, 66, 66, 66, 10,171, 43, 62, 25,124,247,221,119,239, 92,190,124,185,219,217,179,103,231, 10, 4, 2,168, 84, -170, 79,101, 50,217, 82, 6, 25,216, 88,252,221,177, 80, 0,140,108, 73, 60,221,136,136,136, 16, 31, 60,120, 48,197,201,223, 74, - 18, 19, 19,143,187, 40,161, 20, 34, 34, 34,222, 76, 76, 76,220,177,118,237, 90,127, 0, 85, 0,140, 79,186,205,209,228, 31, 29, - 29, 77,109,221,186, 21, 61,123,246,100, 43, 77, 3,241, 92, 13, 1,152,200,187, 65,191,223,181,107,151,117,190,112,121, 67,228, - 70, 70, 70,138, 77,115,118,169,200,200, 72,202, 81, 89,148,131,176, 53, 63,184,129,242,196, 79,226, 93,202,100, 50, 98,230,204, -153, 75,175, 94,189,250, 83,171, 86,173,230, 10,133, 66,104,181, 90, 0,248,110,207,158, 61,228,152, 49, 99, 36, 79,168,201, 80, -142,111,143, 83, 94,157,107,176, 91,174,197,238,212,250,236,145,145,145, 98,138,162, 40,234, 63,182,101,211,231,236,213, 65, 91, -200,201,201,161,114,114,114, 92, 70, 48,101,101,131,107,173, 87,224,106,162, 38, 8,194, 33,185, 36, 73, 81, 70, 35, 69,145,164, -237, 45, 34, 34, 66,156,152,152,232,212, 42, 84,235,214,173,123,245,208,161, 67,199, 7, 14, 28, 8,130, 32,168,237,219,183, 15, -118,244,222,172,183, 67,135, 14,237,120,171, 15, 31,210,105,210,178,219,158,217,187,167, 78,141, 33,233,115,246,228, 41,149, 74, - 74,169, 84,214, 91, 15,233,107,156,125, 63, 55,206, 73,144,188, 46, 3,225,225,225,172, 33,192,220, 16,120, 40, 65, 16,207, 78, -131,183,153, 55,219, 94, 62,237, 39,136, 6, 45,227,182,107,215, 46,249,132, 9, 19, 0,212, 36,213,176,168,156,114,103,188, 10, -180, 66, 65,231,252, 55,165, 33,149, 71, 70, 70, 58,230, 85, 72,240,119,224, 95,237,183,125,229,168, 15,152,139,115,124, 93,155, -186, 26, 36,227,242,147,201,100,132, 66,161,216,217,165, 75,151,113, 0, 56, 20, 69, 65, 36, 18,161,168,168, 8, 21, 21, 21,240, -241,241, 65, 81, 81,209,241, 49, 99,198, 72,246,238,221,155,226,224, 59,161,232,116,176, 4, 65, 96,220,184,113, 24, 60,120,176, -100,218,180,105,140,229,236,219,247,155,249,251,232,209,111,216,221,183, 7,245,153, 15,255, 46,238, 62, 43,107,237, 91, 31, 19, -245,177,191,168, 18,189,156,176, 37, 82, 83, 83,177,104,209,162,135,222, 69,255,254,253,169,147, 39, 79, 50,170,203, 9, 9, 9, -114, 44, 36,232,253,135, 19,207, 44, 36, 26,220, 25, 63,197,125, 75, 45, 75, 91, 38,147, 73, 98, 98, 98, 48, 96,192, 0,234,212, -169, 83,140,126,123,166,142,156,140,123, 19,230, 34, 49, 49, 81, 78, 47, 18, 54, 96,192, 0,170,178,178,178, 62,194, 23,199,196, -196,152,235,235,239,191,255,238, 78, 16, 4,162,162,162, 30, 0, 8,158, 56,113,226, 81,153, 76,198,113,196, 98, 95,122,116,169, -249,251,253,164,123, 32, 8, 2,219, 62,118, 7, 64,224,251,183,191,123, 61, 48, 48, 16, 0,176,125,243, 54,198,101, 21, 30, 30, -142,182,109,219,186,164,220,195,195,195, 57,233,233,233,100,175, 94,189,168,173, 91,183,226, 65,102,107,160,196,143,101,117, 7, -200,223, 81, 15, 0,149,144,144,240,144,134,101,209,129, 82, 78, 52,110,151, 90,147,214,242, 18, 18, 18, 44, 23,196,112, 24, 4, - 65, 16, 9, 9, 9, 4,221, 1,153, 62,157,182, 52,105,242, 55,221, 19, 97,113,111, 14, 43, 42,196,132,114,243,198,228,184, 61, -120, 30, 88, 99,222,152, 28,119,132,252, 41,138, 2,189, 58, 27, 69, 57, 86, 77,100, 50, 25,167,188,188,252,127, 62, 62, 62,227, - 0,112, 38, 79,158,140,232,232,104,240,249,124,136, 68, 34, 8,133, 66, 16, 4, 1, 46,151, 11,133, 66,193,184, 28,135, 12, 25, - 34, 6, 64,237,222,189, 27,244, 59,161, 40, 10,123,246,236,193,180,105,211,228,166,243, 79, 29,108, 41, 4, 79,194,179,150,144, -144, 32, 7, 64,188,121, 99, 2, 38, 92,183,217,198,168, 9,215, 35, 37,196,151, 78,181, 59,234,147, 79, 62, 65,155, 54,109, 92, -114,191, 4, 65, 80, 82,169, 31, 2, 2,142,185,180, 28,134, 15, 31, 62, 40, 57, 57,249, 56, 69, 81, 68, 76, 76, 76,138, 35,228, - 95, 23,246, 38,204, 69, 92, 92, 28, 72,146,196,220,185,115, 25, 41, 20,150,228, 15, 0,135, 14, 29,218, 63, 96,192, 0, 0,240, -139,138,138, 50, 12, 28, 56, 16, 82,169,148, 52,197,205, 48,241, 50,214,218, 95,190,124, 57,222,124,165,198, 54,220,246,177, 8, -111,245,225,227,211, 97,159, 48,126, 38, 15, 15, 15, 12, 24, 48, 0,233,233,233,230,254,212,122,163,175, 97,170,236,165,167,167, -147, 64,205, 50,235, 0,224,237, 94,194,178,122, 3,201,191, 94, 5,128, 38,171,244,244,116,115,218, 73, 75,235,201, 81,162,181, -232, 68, 92,221, 41, 89, 43, 3, 46,117, 13,219, 24, 18,112, 24,150, 10,133,201,250,127, 30,235, 25,101,217,153, 20, 20, 20,152, - 79,228,231,231, 51, 86, 24, 21, 10,197,183, 42,149,234,109, 14,135,195,153, 56,113, 34, 20, 10, 5, 10, 11, 11,225,230,230, 6, - 30,143, 7, 30,143, 7, 55, 55, 55,136, 68, 34,168,213,106, 48,113, 33,174, 93,187, 86,124,244,232, 81, 57, 65, 16, 24, 63,126, - 60, 40,138,162,149, 60, 98,252,248,241, 0,128,228,228,100, 57,219, 85,212, 79,254,166,247, 43,177, 84,146,233,119,111,233,213, -114,198,130, 79, 72, 72, 32, 76,239, 5,107,215,174,117,137, 50,182, 96,193, 2,218, 40,104,176,103, 98,216,176, 97, 67,206,157, - 59,151,220,186,117,107,180,107,215,142,234,219,183,175,217,115, 98, 90,253,209, 41,242, 95,182,108, 25, 8,130, 0,135,195,193, -185,115,231,192,196, 27, 99,229,145,120,157, 32, 8,188,245,214, 91, 6,211, 33, 93, 84, 84, 84,165, 88, 44,198,180,105,211,200, - 17, 35, 70,216,125,118,203, 85, 73,239, 39,221, 3, 8, 32,254,163,191,179, 22,111,251,216, 29, 81,125, 5,152,255,218,167,140, -239,139,137,229,207,228,154,232,232,104, 42, 60, 60,220,188,157, 59,119, 14,213,185,225,128, 78, 13,194,211,128,228,175,175,195, -242, 60,189,177, 45,183, 54,249,199,204, 95,108,243, 60,175,190, 6, 25, 30, 30, 78,165,167,167,131,246, 4,208,196, 21, 30, 30, -238, 80, 35,127,212,228,111,105, 85, 63,237, 1,123,150, 67, 2,207,157, 6, 64, 81, 40, 40, 40,192,253,251,247,205,199,172,247, -237, 88,255,220,195,135, 15,143, 8, 13, 13, 5,151,203, 69, 86, 86, 22, 40,138,194,205,155, 55,161,211,233, 64, 16, 4,120, 60, - 30, 8,130,128,209,104,132, 74,165,194,222,189,123,237,202, 61,118,236,152, 28, 0,198,143, 31,255, 80,189,165,135,122,104,162, - 96, 82,175,173,221,250,246,246,153, 88,249, 52,234, 26, 14, 96,226,250,183, 70,106,106, 42, 76,150, 97,195, 20,224,133, 4,136, - 47,107, 20, 56, 75,229,149,162, 40, 96, 33,129, 9,215, 35,157, 14,148, 37, 8,130, 50,189, 23, 51, 25,153,222, 23,209, 16,121, -237,219,183,127,136,220,156,133, 64, 32,160,174, 94,189,138,226,226, 98,162,184,184, 24, 97, 97, 97, 84, 78, 78, 14,184, 92, 46, - 12, 6,131, 83,127, 48,176, 47,151, 86, 30, 48,111,222, 60, 44, 95,190, 28, 39, 79,158, 4, 65, 16, 24, 53,122, 42,238,230, 48, - 91,192,241,208,161, 67,191,153,222,177, 6, 0,105,218, 16, 21, 21, 85, 1,192, 55, 49, 49, 17, 17, 17, 17, 98, 75,133,188, 62, -212, 88,255, 15,175, 99, 82, 51, 28, 0,108,223,118,193, 33,121, 13,197,141, 27, 55,112,238,220,185, 90,199,140, 21,119, 96,208, -147, 0, 81, 5,223,215,244, 56,103,181,216, 53, 27, 28,200,140,252,235,245, 0,152,172,127,194,210, 19, 64, 91,254,233,233,233, - 13, 33,127,123, 1, 74, 78,201,179,240, 76,136,225, 68,128,211, 35,176,156, 40,139,206,199,124, 63,244, 49, 87, 5, 39, 81,187, -252,204,155, 43, 80, 61,114,186,121,115,192,242,167,232,206,182,121,243,230,232,217,179,167,185, 17,210,251,214,215,214, 1, 95, -127,127,255, 46, 90,173, 22,101,101,101, 56,115,230, 12,210,210,210, 80, 92, 92, 12,181, 90, 13,122,140,148,162, 40,232,245,122, -104,181, 90, 70, 67, 12,116,221,168,139,220, 19, 18, 18, 8,130, 32,192,212, 51,179,111,223,111,230,141,201,190, 61,168,207,124, - 88,139,232,233,205,114,223,242, 26,166, 24, 48, 96, 0, 82, 83, 83, 27, 86, 33, 44,198,252, 81, 51,140, 37, 49,145, 51, 65,159, - 67, 3, 99,111, 44,223, 11,237, 5,112, 21, 92,225, 5,104,214,172, 25,242,243,243, 9,107,101,215, 89,242,223,155, 48,215, 92, -135,105,244,235,215, 15, 0,112,226, 52,243,201, 26, 17, 17, 17,195, 76, 99,255,215, 0,168, 76,253, 57,189,153,181,110,166,193, -133,181,199,254,109, 40, 87, 14,202,115, 5,210,211,211,137,158, 61,123,162,234,218,112,148,159,105,130,138, 83, 34, 80,229, 21, - 64, 53,192, 81, 25, 80,121,146, 3,245,159,124, 84,156,105,132,195,219,134,160,103,207,158, 14,241,211, 63, 29, 60, 38,141,147, -246, 4, 56,106,249,207,159, 63,159, 90,178,100,137,203,110,214,158, 60, 83, 39,229,178,202,201,116, 12,173, 62,210,177,144, 85, - 45,149, 74, 61,235, 58,239, 44, 44,199,254, 93,161, 4, 88,142,253, 51, 85, 2,162,163,163,225,225,225, 1, 79, 79, 79,120,121, -121,193,199,199,135,244,243,243,227, 36, 38, 38,226,157,119,222, 49, 95, 39, 20, 10, 49,116,232, 80,212,163, 4, 4,232,116, 58, -148,149,149, 65,163,209,192,199,199, 7, 2,129, 0, 6,131, 1, 20, 69,193,104, 52, 66,167,211, 65,175,215,195,104, 52, 58, 20, - 95, 96, 10, 90,171,243,188,165, 21,250, 36, 97, 47, 32,208, 81, 52, 84, 9, 32,190,172,123,184,111,194,245, 72, 19,185, 58, 41, -219,202,250,183, 56,142,241,227,199, 59, 28, 12,104,109,253, 91,202,115, 22,225,225,225,148,209,104, 68, 88, 88, 24,117,241,226, - 69, 34, 44, 44,140,210,235,245, 80, 40, 20, 13, 33,181,154,206,151,199,195,236,217,179,113,238,220, 57,252, 61,238,207,188, 78, - 31, 62,124,248,112,255,254,253, 1,192,203, 68,250, 42, 0,216,177, 99, 71,163, 19, 39, 78,120,155,218, 7, 97,250,180, 43,120, -249,143,203,241, 86,239,135,173,255,232,159, 84,216,113, 70, 15,138,162,208,125, 98,119, 92,216,118,129,120,156,198, 85,122,122, - 58, 33,249, 87, 56,117,120,121, 43,240,170, 43, 1, 67,205, 95,147, 0,248, 60,160,224,190, 47,142,231,134, 27,215,109, 47,230, -166,167,167, 19,225,225,225, 66, 58, 86,128,181,254, 23,215,123,157,221,105,128,145,145,145, 20, 93, 97, 45,227, 1,152, 96,201, -146, 37,180,197,224, 18, 48,144,231,244,248,186,105,138, 94,173, 45, 57, 57,153,164,103, 5, 52,212, 98,143,137,137,241,124,158, - 43,220,186,117,235,176,108,217,178, 90,245,138, 38,255,209,163, 71, 99,244,232,209, 53, 22,206,137, 19,245,137,241,207,206,206, -214, 24,141, 70,148,151,151,163,164,164, 4,229,229,229, 80,169, 84, 80,169, 84,168,174,174, 70,101,101, 37, 20, 10, 5,212,106, - 53,180, 90, 45,152, 52,116,130, 32,176,123,247,110,135, 20,182,103, 25,169,169,169,181, 54, 75,204,158, 61, 91,108,185,207,100, -204,217,198,152,127, 45,203,189, 33, 81,251,182,126, 75, 81, 20,177,123,247,110,151,198, 2,236,222,189,219,225, 54,220,163, 71, - 15,202,104, 52,154, 19,180,132,133,133, 81, 36, 73,226,193,131, 7, 80, 42,149, 78, 61,243,191,231, 15,196,137, 19, 39, 64,238, -244, 5, 69, 81,136,139,139, 51,191,163,212, 51, 36,152,142,124, 68, 68, 68,188, 1, 0, 81, 81, 81, 5, 38, 5, 64,187,125,123, -124,163,233,211,167, 55, 58,113,226, 4,134, 15, 31, 62,196,145,156, 0,247,147,238,129, 0,129,120, 11,235,127,226,143, 42,112, -223, 82, 96,251, 25, 29,102,205,154,133, 37,135,191,123,236,117, 57, 60, 60,156, 75, 43, 1,175,205, 50,128, 82,251, 0,149, 0, - 42, 1,110, 21, 80,249, 0, 56,116,161, 9, 44,200,159,151,158,158,174, 97,201,223, 62,249,219,245, 0, 88,143,251, 91,198, 3, - 48,117,179, 36, 36, 36,164,152, 2,132,228, 86,158, 36,103, 59,140,135,228,209,195, 2,166,113, 72,151,184,127, 6, 15, 30,124, - 37, 57, 57,185,203,211,248,130,105,171,223, 85,110,127,218,234,119,192,237, 95, 11,241,241,241,230,239,255,253,239,127,177,113, -227, 70, 0,208, 1,224,211,196, 15, 0, 67,135, 14,181,167, 0,168, 67, 67, 67,161, 82,169,160,211,233, 80, 92, 92, 12,129, 64, - 0, 30,143,103,246, 0, 40,149, 74,168, 84, 42,104,181, 90, 40, 20, 10,140, 27, 55, 78,178,103,207,158,122,239,143,182, 50,237, - 76,107,197,248,241,227,237, 42, 10, 53, 10,205,163,139, 1,112,230,188, 53, 44,166,251, 61,132,184,184, 56,249,236,217,179, 37, -113,113,113, 41, 79,180, 14,215, 97,253, 91,194,145, 88,128,186,172,127,103,209,163, 71, 15,234,252,249,243, 68, 88, 88,216, 23, -116,213, 54, 26,141, 11, 61, 60, 60, 80, 82, 82,226, 84, 31,243,249,103, 3,145,146,146, 2, 98,119, 0, 0,224,200,231, 94, 24, -250,117, 21, 6, 12, 24,128,111,150,156, 0, 69, 81,140,189, 21,135, 14, 29,218, 59,112,224, 64, 0, 40,222,177, 99, 91,179, 19, - 39, 78,250, 82, 4,133, 17,195, 71,140, 62,120,240,224,254,131, 7, 15, 58,228,229, 92,190,124, 57,222,234,227, 86,219,226, 7, -133,217,179,102, 35,120,104, 99, 60,169,184,165,244,244,244, 90, 26, 62, 85, 5, 8,116, 0, 73, 17, 48, 24, 41, 8, 40, 32, 88, -196,177,188,222, 0, 22, 53, 70,217,146,207,234, 84, 16,194,194,194,234, 87, 0, 44, 35,254, 77,228,111, 14,150,162, 61, 1, 76, - 53,127, 27,164,221, 32,216,144,231,242, 49,169,152,152,152, 46,201,201,201,174,236,240,158,215,122, 70,160, 38, 10,220,108, 73, -191,247,222,123, 0,192,183,168, 75,230,115,166, 78,171, 46, 92,237,221,187,247, 59, 41, 41, 41, 9, 70,163, 17,149,149,149,208, -235,245,230,113,127,141, 70, 99,158, 98, 72, 7, 6,238,217,179, 39,133, 65,125, 33, 96,154, 2,104, 93,111, 35, 35, 35, 41,154, -244, 7, 15, 30, 44, 97,162, 0, 60,170, 60, 0,150, 99,255,150,228,111, 61, 44,192,224,125,212, 7, 42, 46, 46, 78,254,230,155, -111, 98,231,206,157,206,122,203,196,150,158, 19,122,159, 14, 24,156,112, 61,146,186,117,235, 86,157,191,167, 19,254, 28, 62,124, -184, 78,143,221,157, 59,119, 24,123,102,202,202, 6, 83, 0, 48,100, 72, 54,178,179,179,109, 70,151,151,150, 14, 2, 80, 14,192, -126,191,213,169, 83, 39,234,252,249,243,132,169,179,252, 2, 0, 56, 28,206,194,187,119,239,162,188,188,220,169,134,204,225, 16, - 53, 10, 59, 77,254,151, 12,216, 40,215, 1, 0,190, 89,114,194,225, 62,130,110, 19,211,167, 79, 15,163, 40, 10, 17, 35, 35,198, - 29,216,127,224, 87,166,196,111, 41,234,141, 49,175, 95, 35, 8,162, 19, 69, 1,220,183, 20,160, 40, 10,179,231,204, 70,227,161, - 77, 26,152, 87,181,102, 90, 47, 93,239, 26,146, 73, 48, 60, 60,156,218,245, 89, 83,120,150,222,193,237,202,230,104, 35, 40, 6, - 60,130,193, 83, 62,128,183,178, 20, 64, 35,179,199,192, 90,105, 96,225,132, 7,192,114,186,159,213, 52, 54, 42, 33, 33,193, 97, -151,169, 5,105,187,228,198, 45,229,209,243,255,159,211,233,117,207, 4,172,202,190,214, 20,177, 58,206, 61,212, 25, 72,165, 82, -131, 76, 38,219, 51,112,224,192,153,137,137,137, 43, 12, 6, 3, 42, 42, 42,204, 49, 0, 0, 80, 92, 92,140,138,138, 10, 80, 20, - 5, 71,234,211,144, 33, 67, 36, 71,143, 30,149, 39, 36, 36,212,178, 62,233,223, 15, 25, 50,196,161,100, 64,143, 2,234, 51, 31, - 58, 67,248, 15, 17,188,157, 46,155, 32, 8,130,114,134,252, 77,158,182, 20, 91,109, 17, 0, 44,130, 2, 25, 97,218,180,105,114, - 6,255, 73, 57, 48, 87,188,214,103,109, 34, 98,150, 28,175, 77,155, 54,212,181,107,215,104,151,255, 23, 0, 22,106,181, 90,220, -190,125, 27, 10,133,194, 89, 42,164,200,157,126, 56,114,169,198, 56,221, 36,215, 97,199, 25, 29, 40,138,194,201,179,206,143, 44, -166,166,166, 98,248,240,225,146,131, 7, 15,166, 28,216,127,192, 89, 49, 28,146, 36,221, 0, 96,231, 89, 61,102,205,154,133,198, -195,154, 48, 87, 39,109, 64,169, 84, 2, 0,178,179,179,169,117,235,214,153, 21, 50,203, 88,146, 77,155, 54, 89,246, 15,140,254, -165, 21, 71, 9, 4,133,225,157,245, 10, 0,193, 53,101, 48, 35, 16, 45,121,121,248,122,112, 17, 54,183,127,139,218,177, 99,199, - 63, 62, 0,144,182,238,109, 89,254,214,231,235, 27, 2, 32, 76, 67, 0, 15, 77,155,114,100, 8,192,102, 71,225, 58,210,177,148, -231,210,249,255,244,216,191,179,176,167,144, 56,170,176,212,229,238,119,118, 24,160, 46,119,191,147,195, 0,150, 65, 65,132, 3, -231, 96, 67, 9,160, 0,172,148,201,100,107,227,227,227,245,124, 62, 31, 90,173, 22, 6,131, 1, 36, 73,194,215,215, 23,229,229, -229,112, 52,155,226,209,163, 71, 83, 80, 51,239,159,218,189,123, 55, 76,138,128,121,106,224,209,163, 71,255, 17,157,195,155,111, -190, 73, 41,149, 74, 28, 56,112,192,209,250, 44,182, 83,222,212,132,235,145, 18, 38,222,184, 79, 62,249,228, 33,227,194, 26,159, -126,250, 41,197, 52,200, 83, 42,245,179, 43, 79, 42,245, 99, 36, 76, 36, 18,209,157, 36, 69, 81, 20, 84, 42, 21, 10, 11, 11,157, - 30,243,183,196,176,175,171,106,237, 55,132,252,141, 70, 35, 1, 0, 78, 88,252,214, 32,247,253,190,191,189,101, 38, 64, 87,161, - 62,133,204, 66, 1, 96,100,253, 75,199,135, 20,254,146,137,166,178,221,183,107, 69,249, 15, 88, 21, 78, 29,159,246, 2,110, 61, - 16,161, 62,175, 19, 11, 7, 61, 0,166, 23, 71, 56,114,252, 9, 91,160, 41, 79,217,253, 16, 14, 88,204,118, 20,145,193, 46,187, -175, 9, 19, 38, 72,156, 72,239, 91,175,133,102,195, 2,173,207, 58,101, 20, 52, 38,149, 74, 13, 0,136,113,227,198,137,115,115, -115,229,106,181, 26, 70,163, 17,157, 58,117,146,244,236,217,211,233,247,189,123,247,110,203, 41,103, 78,121,141, 30,117, 12,128, -189,125, 38,250,162, 41, 58,188, 54,225,156, 60,233,176,219,223, 52,215,159,154,112,253, 97, 5,142,162, 40,138,206, 17, 96,161, -144,153, 3,230,156,109, 27, 0,176,107,215, 46,194, 85,109,141,233, 53, 0, 80, 86, 86,134, 54,109,218, 80,149,149,149,104,213, -170, 21, 50, 50, 50, 92,210,215,113,222, 44, 7, 65, 16, 24,253,122, 12,237,134,193,210, 37,211,204,223, 29,205,152,233, 42, 72, -165, 82,114,237,137,181, 46,149, 57,105,210, 36,147,215, 69,230, 9,192, 96,218, 40,169, 84, 74, 90, 92,227,208, 3,203,118,223, -110,106,201, 61,180,171, 63, 61, 61,157,144, 30,123,139, 98,201,255, 17, 40, 0,207, 16, 26,220, 72,159,214,252,227,174,190,175, - 71,224,133,121,164,229,102, 26,227, 55,255,199,245,235,215,159,240, 27, 33,137,167, 91, 94, 77, 89, 57,154, 81,174, 78, 44,172, -181,142, 5,101,235,156,201,242, 78,121, 30, 58,146,251,247,239,155,223, 71,118,118,182,203,222,137, 76,182,150,146, 74,167, 17, -191,255, 38, 99,244, 3,103,151,119,117, 6,166,105,125, 46,239, 19,234, 83,174, 29,236, 55, 60, 80, 19, 83,164,183, 48, 66,205, -227,252,172,219, 31, 76,235,212,195, 21,243,113, 86, 52, 22, 44, 88,176, 96,193,130,197,211, 1, 14, 91, 4, 44, 88,176, 96,193, -130, 5,171, 0,176, 96,193,130, 5, 11, 22, 44, 88, 5,128, 5, 11, 22, 44, 88,176, 96,193, 42, 0, 44, 88,176, 96,193,130, 5, -139,231, 2,181,102, 1,208, 57,175,157,129,173, 96, 66, 86, 30, 43,143,149,247,248,228,197,198,198,214,214,238, 57, 28,115,118, - 57,203,169,102,116, 54, 69,203,169,103,182,210, 7,123,122,122, 66, 40, 20,154,127,207,225,112,192,229,114, 31,146, 71, 47,204, - 68,146, 53,179,188,234, 90, 44,135,125,191,117, 67, 38, 91, 39,230,242, 4,160, 72, 3,166, 78,125, 63,197, 25,121,107,215,174, -149,100,100,100,240,194,194,194,146,173,179,238, 57, 41, 79,156,145,145,129, 53,107,214,164,176,237,237,217,147,231,176, 2,240, - 79, 68, 96,224,251,181, 10,174,164,100, 3,241, 84,201,123, 63,144, 2,128,146, 13, 37,132,229,247, 6,136,108, 96,114,207, 71, - 46,239, 31,139,245, 43,150,137,139,175,156,193, 0,191, 98,121, 51, 67, 30, 50,169, 54, 56,167,244,151,120,135,190,140,153,115, -230,165,216,251,253,169, 83,167,208,175, 95, 63, 51,241,211,132, 77, 16,196, 67,132, 77,146,164,121,187,123,247,174, 77,121,231, -207,159, 71,120,120, 56, 68, 34, 17,120, 60, 30,184, 92,110, 45,153, 52,233, 27,141, 70,243,166,213,106,145,158,158,142,118,237, -218, 61,119,239, 71, 38,147, 17, 82,169,148, 90,187,118,173,248,230,205,155,184,117,235,150,220,215,215, 23, 91,183,110,109, 80, -253, 95,183,110,189, 88, 32,244,135,175,223, 11,114,101,117,129,100,221,186,159,197,171, 87, 59,150,251, 97,205,154, 53,226,132, -132,132,227,153,153,153, 56,112,224, 0, 66, 67, 67, 49,119,238, 92,174,229,220,123, 39,228,201,179,111,103,161, 93, 72, 91,240, - 5, 2,204,154, 53,251,213,152,152, 24, 57,219, 82,159, 83, 15,192,179,132, 33, 67,134,216,213,120,142, 30, 61,106,183, 97,210, - 4,109, 77,220,206,194,213,242, 30, 1, 8, 7, 73,219,110,106, 89, 23,203, 99,242,123,235,255,127,182,137,101,237, 90,241,181, - 83, 71,144,187,227,123,185, 74,165,133,254,101, 14, 68,205, 9,180,207,189,132,151,188, 40,121,121,241, 95,104,186,246, 63,146, -113,211,190,172, 87, 9,184,118,237, 26,184, 92, 46,250,247,239, 15, 30,143,103,222,104,133,128,182,250, 13, 6, 3,140, 70, 35, -244,122, 61,238,222,189,139,227,199,143,219,148,167, 82,169,112,225,194, 5,244,238,221, 27,124, 62, 31,110,110,110,181,100,146, - 36, 9,131,193, 0,131,193, 0,189, 94, 15,181, 90,141, 11, 23, 46,160,186,186,250,105, 32,107,142,169,110,112, 0, 24, 26,146, -135, 94, 38,147, 17,177,177,177,100,108,108, 44, 2, 2, 2,240,239,127,255, 27,227,199,143, 71, 85, 85, 21, 2, 2, 2,156,202, - 64, 26, 16, 16, 96,190,159, 5, 11, 62,195,150,109,233, 16,137, 26,129,203,229,203,171,171,242, 28,150,153,150,150,134,234,234, -106,244,238,221,251,238,224,193,131,155,148,150,150,226,200,145, 35,198,169, 83,167, 98,253,250,245,245,182, 17,109, 78,214, 67, -101,115,249,198, 13,164,120,185, 99, 78,220,151,121,221,123,116,105,113, 47,191, 8, 71, 18, 83,142,111,223,190, 99,112, 84,212, - 91,199, 88,234,124,250, 65,167,254,181,242, 20, 48, 82, 0,172, 83,183,218,219,127,236,228,255,193, 7, 31,212,123, 77,121,121, - 57, 0, 80, 76,148, 0,154,172, 27,106,173, 63, 10,121,150,150,191, 11,172,127, 71, 73,155, 41, 89,187, 90,158,229,181,150,159, - 0,128,178,178,154,204,136,254,254,201,207, 69, 67,205,249, 51, 25,237,242,228,242, 60, 21,137,177,237,184,120, 33,200, 0,210, -159,130,155, 63, 23, 85,165,124,136,170,212,232,152,177, 82,190, 37, 46, 86,242,206,236, 69,117, 42, 1, 4, 65,224,250,245,235, -224,243,249,120,245,213, 87,205,164,237,230,230, 6, 14,135, 3,138,162,160,215,235, 97, 48, 24,160,213,106,145,151,151, 7,185, - 92, 94,231,146,202, 28, 14, 7,122,189, 30, 25, 25, 25,232,223,191, 63, 68, 34, 17, 4, 2,129, 89, 30,173, 0,104,181, 90, 84, - 87, 87,227,242,229,203,208,104, 52,230, 97, 2, 38,136,138,138, 18,115,185, 92,121, 85, 85, 21,248,124, 62,138,138,138, 62, 28, - 59,118,108,149, 80, 40,220,226, 12,105, 71, 69, 69, 77,224,114,185, 59, 19, 19, 19,105,121,153, 99,199,142,189, 41,147,201,198, - 75,165, 82,157, 51,150,112,108,108,172,124,209,162, 69, 69, 48,173, 56, 19, 27, 27,139,107,215,174,161, 81,163, 70, 8, 11, 11, -195,230,205,155, 29, 38,255, 95, 38, 79,198,136,238,221, 1, 0,141,103,206,132,200, 61, 24,213,149,185,168, 84,220,150,196,196, - 76, 73,169, 43,159,123, 93,120,241,197, 23, 81, 84, 84,132, 83,167, 78,181,226,112, 56,184,124,249, 50,252,253,253,145,154,154, -138,119,223,125,151,202,200,200,168,247,247,165,223,206,169,181,239,169,211,163,169, 65,131, 89,159, 44,108, 17,183,244,191,248, -126,233,106, 52,227, 24,177,122,233,178,228,119,223,125, 23,246,228,177,120,250,200,159, 62,206,116, 45,128,135,242,127,219,219, -127,156,112,229, 74,125,207, 2, 44,149,128,199,228, 9,112,212, 82, 39,236, 88,231,206,200,179,245,249, 92, 37,174,250,113,201, - 55,226,208,140, 95,228, 69, 92, 35,218,249, 0,173, 90, 82,224,190,200, 7,175,109, 91,240,181, 26,104, 79,231, 65,171,224,129, - 75,186, 65,147,188, 69,190,126,213, 82,201,212, 25,182,135, 3,104,247,124, 86, 86, 22,252,252,252, 32,145, 72, 32, 20, 10,193, -231,243,193,227,241,204, 86,191, 70,163, 65, 97, 97, 33, 78,156, 56, 1, 14,135, 3, 14,135,131,250,228, 25,141, 70, 92,189,122, - 21,253,250,245,131,183,183, 55,132, 66, 33,184, 92, 46, 12, 6, 3,116, 58, 29, 42, 43, 43,241,215, 95,127, 65,171,213,130,199, -227,153, 99, 1,236,161,127,255,254,226, 27, 55,110,200,239,220,185,131,202,202, 74,240,249,124, 52,110,220,120,229,201,147, 39, -209,167, 79, 31,158, 76, 38,219,232,136, 18,208,191,127,255, 49, 55,110,220,216,105, 37, 47,244,228,201,147,161,125,250,244,217, -110, 82, 2, 24,201, 91,179,102,141, 88,167,211,225,254,253,251,180,203,219, 92, 72,139, 22, 45, 42,136,141,141,109, 54,126,252, -248, 87, 63,254,248, 99,135,250,191,245, 63,111, 20,127, 54,127, 94,173, 99,247, 87,172, 64,227, 55,154,227,251,239,127,148, 76, -158,252,182, 83,253,233,169, 83,167,228,127,254,249, 39, 62,251,236,179, 74, 46,151,235, 45, 20, 10,209,167, 79, 31,200,229,114, - 36, 38, 38,162, 89,179,102, 14,180, 60, 2, 91,179,238, 97,207,173, 2,236,251,125, 51,184, 92, 2,115,102,190, 67,118,107, 28, -200, 89, 55,107, 33,214, 59, 42,143,197, 19, 33,127,107, 37,210,150, 82,224,244, 44,128, 39,189,188,109,126,185,231,118, 0, 0, - 32, 0, 73, 68, 65, 84,219,182,109, 37,246,182,199,109,173, 63, 10,121, 46,180,250,153,146,182, 51,100, 13, 75,235,156,182,208, - 77,114, 40, 39,229,213,217, 81,251,251, 39, 59,101,253,175, 90,181, 74, 60,101,202, 20,170,174, 99,214,231,234,130,229,245,171, - 86,173, 18, 91,159,179, 62, 86,111,121, 93, 61, 47, 47, 44,168, 68, 35, 47, 30,218,122, 81,224, 5,146,224,189,242, 26, 60,186, -109,129,168,199, 15, 16,248,136,192,175, 86, 67,165, 50,162, 37, 87,133,212,248,186, 83,201,114, 56, 28,240,120, 60,184,185,185, -225,214,173, 91,184,124,249, 50,188,189,189, 17, 16, 16,128,128,128, 0, 4, 6, 6,194,215,215, 23, 10,133, 2,169,169,169,224, -114,185,230,177,125, 91,160,207,243,249,124, 24,141, 70,100,102,102,194,221,221, 29,129,129,129,104,212,168, 17,130,130,130,224, -233,233,137,204,204, 76,232,245,122,243, 16, 65, 93, 10,133,181,229,255,224,193, 3,249,237,219,183,209,166, 77, 27, 12, 27, 54, - 12,189,122,245,130, 74,165,194,241,227,199,145,145,145,177, 65,163,209,188,237,128,229, 47,121, 80, 84,252,107,246, 61, 5,188, -218,245, 70,232,176,247,209,172,215,104,148,107, 57, 56,154,124, 12, 25, 25, 25, 99, 53, 26,205, 84,166,228, 95, 89, 89,137, 75, -151, 46,201, 79,157, 58,133, 23, 95,124, 17,177,177,177,129, 0, 72,147, 7,160, 25, 0, 8,133, 66,198,100,189,254,231,141,226, -173,241,251,197,254, 1, 93,228,241, 59, 46, 97,242, 47,191, 32,241,194, 5, 36, 94,184,128,198, 51,103, 2, 0,244,122,229, 9, -103,218,220,235,175,191, 78,237,219,183, 15,227,198,141,187,235,229,229,197,113,119,119, 79, 79, 75, 75,195,169, 83,167, 80, 82, - 82,130,208,208, 80,199,148,210, 11,183,176,244,143, 43, 88,191,116,193, 37, 30, 87, 13,142,177, 10,223, 45,255,133,179, 51, 53, - 29,133, 28, 30, 94,120,225, 5,150,101,159, 19,240,156, 37,248, 39,181,120,197, 35,179,176,255,217,138,192, 35, 25, 87,111,160, -171,158,176,115,220, 33,165, 98,233,210,165,226, 99,199,142,201,179,178,178,234, 60,150,150,150,198, 72, 22,125, 93, 90, 90, 26, -202,202,202,228, 75,151, 46,149,204,155, 87, 99,149,219, 58, 86, 31,188, 53,165, 72,204,213,160, 89, 57, 23,221,189, 9, 4, 21, - 3,237,120, 62,224, 16, 1,160, 52, 15,160,124, 64,224,106, 46,137,251, 74, 13,120, 28, 14,186,250, 11,228,117, 61,183,165, 2, - 32, 16, 8,112,251,246,109, 52,107,214, 12, 67,134, 12, 1,151,203, 5, 73,146, 40, 45, 45,197,169, 83,167,224,230,230, 6, 62, -159, 15,157, 78, 87,167, 2, 64,123, 7,104, 37,128,162, 40,100,103,103,163, 93,187,118,240,241,241, 65,117,117, 53, 46, 92,184, - 0,163,209, 8,129, 64, 0,173, 86, 11,173, 86, 91,103,223, 65, 7,209, 1, 64,113,113,177, 60, 63, 63, 31,221,186,117,131, 88, - 44, 70,243,230,205, 37, 74,165, 18, 65, 65, 65,242,228,228,100,156, 61,123, 22,190,190,190,189,101, 50,217, 54,169, 84,106,119, -125,247,226,226,226,227, 15,202, 20,240, 15,237,141,182,253,223,132,111,243, 80,104,149, 21,200,253,243, 32,110, 29,219, 76,203, - 99,244,126, 77,177, 15,242,194,194, 66, 4, 7, 7, 67, 40, 20, 74, 46, 93,186, 36,143,141,141,229,152, 60, 0, 0,112, 35, 54, - 54,150,100, 82, 7,127,222,176, 89,236,235,247,130,220,215,255, 5,112, 56,110,208,235,149,216,176, 81,142,201,239, 73,104,143, - 2,166, 78,157,138,160,160, 32,210,209,182,247,206, 59,239, 80,241,241,241,232,223,191, 63,122,244,232,209, 10,128,225,216,177, - 99,225, 57, 57, 57, 16,137, 68, 16,137, 68,136,136,136,120,117,215,174, 93,199,153,200,219,118, 51, 15, 63,252,117, 3, 63, 47, -158, 95,214,252,133, 86, 47, 42,171,203,241,251,161,191,112,233,242, 77,248, 82, 36,248,247, 31, 32,226,195,232,193, 59,119,238, -250,103,185, 96,159, 33,216, 26, 62,170,203, 43, 80,151,170, 78,140, 31, 63,222,210,130, 38, 34, 35, 35,235,219,127,102, 81, 82, -178,129,176,220,158, 54,121,192, 35,113,255,215,103,181, 55,232,158,157,181,206, 29,241, 0, 56,138,168,168, 40,241,254,253,251, -107,145,191,173, 99,206, 32, 43, 43, 11,251,247,239,151, 71, 69, 69,137,235, 59, 86, 39,113,149,228,225,204, 61, 53, 84, 70, 18, - 39,243, 72,220, 55,240, 96,212,166,163,252,218, 7,216, 60, 51, 6, 7,142, 40,112,185,148,194,197, 98, 3,174,150, 26, 80, 90, -120,191, 94,175,156,165, 18, 32, 20, 10,113,247,238, 93,220,184,113, 3, 64, 77, 92,204, 31,127,252, 81,107, 44,191,190,241,122, -130, 32,204, 94, 0, 90, 30, 69, 81,200,203,203, 67,203,150, 45, 81, 88, 88, 8,146, 36, 33, 20, 10,205,178,234, 27, 82,176, 68, -110,110, 46, 52, 26, 13,194,195,195,209,188,121,115, 9,151,203,133,183,183, 55, 94,126,249,101,137,167,167, 39,114,115,115, 81, - 89, 89,121,153,105, 61,200,205,205, 5,201,225,163, 89,216, 96,248, 54, 15, 5,135,235, 6,145,119, 16, 90,190, 28, 1,190,135, - 31, 45, 47,199,158,156,181,107,215,138, 43, 42, 42,228, 5, 5, 5,104,209,162, 5, 36, 18,137,100,203,150, 45, 41,165,165,165, - 4, 0,244,238,221,219, 96,186, 52,212,199,199, 7, 50,153,204,110,192,131, 80, 24,128,128,160,110, 48, 26,180, 40,186,151,134, -251, 5,167, 6,149, 20, 95, 88, 96,146, 7, 0,120,112,255, 62, 76,242,220,152,214, 61,169, 84, 58, 62, 62, 62, 30,209,209,209, -152, 56,113, 34, 0,144, 71,142, 28,225,237,223,191, 31,147, 39, 79, 30,122,254,252,121,226,244,233,211, 68,108,108, 44,163,200, -253,204, 74, 21,230,159,184,136,111,231,198,160,255,200,193,254, 70,202,128, 93,191,158,192, 79, 43,183,224,208,236,119,177,190, - 91, 75,180,244,225, 97,193,130, 88, 54, 8,240, 25,193,197,139, 23,235, 36,255,122, 61, 0,214, 99,251,246,246,159, 71, 60,130, - 41,120, 78,225,235,151,190,150, 76,155, 54,237, 89, 40,239, 90, 67, 10,143, 56, 72,143,209,123,136,136,136, 16,223,186,117, 75, -174,211,233,234, 61,214, 16,148,151,151, 67,169, 84,202, 35, 34, 34, 36,121,121,121, 15, 29, 59,120,240, 96,157,239, 46,163, 76, - 13,133,142, 68, 70,177, 1,133, 21, 6, 4,255,193,195,139,187,178,112, 55,231, 42,110,254,169,131,129,199,133,142, 4, 52, 58, - 10,229, 20,137,160,122,150,181,167,167,251,209, 99,247,116,196,254,131, 7, 15,208,170, 85, 43,228,228,228,152, 93,254, 60, 30, -207,124,189,163,195,121,150, 57, 4,232,207, 71, 52, 36, 88, 1,215,198,124,216, 37,107,146, 36,161, 84, 42,107, 58, 71, 30, 79, -242,193, 7, 31,212,122,119, 85, 85, 85,188,125,251,246, 97,244,232,209,156,249,243,231, 63, 88,178,100,137,193, 94, 93, 36,136, - 26,133, 72,173,122,128,234,170, 60,201,148, 41,239,166,200,100,178, 84, 0,223, 86, 85, 85, 97,223,190,125,102,197,177, 93,187, -118, 58, 38,117,123,241,226,197,163,191,255,254,251,132,136,136, 8,244,235,215, 15, 0,200,211,167, 79,115,126,251,237, 55,136, -197,226,145,171, 86,173, 58,234, 72,193,220, 83,105,241, 78,226, 31,152, 53, 33, 2,227,223, 25, 7,149,166, 18,123,247,165, 96, -249,234,109,248,223,208,151,208,182, 40,159,101,211,231, 64, 25, 96,234, 1,112, 53, 40,171,134,108,111,159,133, 5, 30, 53,249, -187,208,106,175,203,163,224,236,248,127,125,245,130, 81,125, 57,120,240, 96, 74,251,246,237, 37,126,126,126,245, 30,107, 8,252, -252,252,208,190,125,251, 90, 68,111,235,152, 45,168,141,222,208, 19,192,185, 18, 45,138,140, 70, 28,203,214, 96, 87,130, 6,199, -243,131,144,197,247, 65,190, 66,143,188, 42, 18, 74, 3,160, 50, 80, 16, 4, 52,182, 75,204,244,252,126,163,209, 8,131,193,128, -128,128, 0,120,122,122,162, 85,171, 86,208,235,245,230,227,182, 18, 2, 89,203,163,231,247, 27, 12, 6,168,213,106, 80, 20,133, - 22, 45, 90,160,160,160, 0, 77,154, 52, 1,143,199,131, 86,171,133, 78,167, 51,255, 47,147,225,193,150, 45, 91, 66, 40, 20, 34, - 61, 61, 29,249,249,249,114,163,209,136,202,202, 74,226,207, 63,255,148, 87, 87, 87,163,101,203,150,240,246,246,126,141,105, 31, -213,178,101, 75,112, 72, 29, 10, 46, 36,163, 34, 63, 19,164, 81, 15,117,101, 49,114,255, 60, 8,157,178,156,150,215,154,137,114, - 67, 35, 32, 32, 64,190,102,205, 26,179, 23,167,180,180,148,184,122,245, 42, 76,164, 77, 2, 8,182,149,240,200, 26, 6,131, 26, - 6,125, 53, 68, 30,141, 33, 20,249, 67, 38, 91, 39,150, 74,165,134, 69,139, 22, 5, 88,200,195,250,245,235,161, 80, 40,232, 41, -140, 15, 97,209,162, 69, 84,223,190,125,169, 30, 61,122, 80, 95,126,249,229,239,163, 71,143,198,200,145, 35, 1, 0,231,207,159, -175,220,191,127, 63,198,143, 31, 63,250,216,177, 99, 7,153,148,217,162, 69,139,168,126,253,250, 81,111,125,240, 33, 94,221,125, - 2,243,254, 53, 22, 31,125, 58, 29, 26, 93, 53,238,220,206,131, 76,182, 11,191,141,234, 3,113,139, 70, 78,183,141,225,195,135, -179,253,250, 19, 68, 88, 88, 88, 45,210,183, 14, 4,124,172,169,128, 35, 35, 35,197,142,236, 63, 54, 75,191,142, 57,251,214,214, - 62, 83,235,191, 46,121,239, 7, 6, 82,239, 7,254,237,206,183,222,183,231,137,112,149,188, 58, 44,105,103,136,250,145,193, 74, -137,112,218, 3, 0, 0,219,183,111, 79, 25, 53,106,148,196, 50, 57,141,173, 99,206,160, 93,187,118, 24, 53,106,148,100,251,246, -237, 41,245, 29,171,243,247,237,219,161,189, 7, 23, 94, 4,160,167, 40, 92, 47,215, 33, 62, 75,139,237,103, 10,241,215,237, 50, - 20,170,129, 82,141, 17,183,171, 41,220,211, 82,168,214,233, 37,245,145, 23, 61, 53, 79,167,211, 65,173, 86,163, 73,147, 38,232, -210,165,139, 73,209,243, 71,175, 94,189,204,132, 77,147,118, 93,132, 77, 19,186, 94,175,135, 78,167, 3, 65, 16, 8, 9, 9, 65, - 69, 69, 5,242,242,242, 80, 86, 86,134,214,173, 91,131,195,225, 64,167,211, 65,171,213,154,127, 99, 15, 65, 65, 65,146,230,205, -155,227,234,213,171, 56,124,248, 48, 14, 28, 56, 32, 63,112,224,192,241,147, 39, 79,130,203,229,226,149, 87, 94, 65,219,182,109, -213, 48, 5,222, 49,144, 55, 58,216,223, 7,165,217, 23,113,243,232, 70, 92, 61,184, 6,215, 15,202,112,247,236,111, 16,112, 72, - 90, 94,129, 61, 57, 51,102,204, 72, 9, 14, 14,150,120,123,123, 35, 35, 35, 3,249,249,249,242,184,184, 56,177,165, 34, 96,242, - 4,112,226,227,227,209,185,115,103,187,247,166,211, 42,160,168,200,130,155,155, 7,124,253, 59,200, 61, 60,155,225,151, 95,182, -138, 9,130,211,155,190,198,171, 34, 25,242,255,125,132, 33, 29,170,235,172,219, 7, 15, 30,132, 72, 36, 66,231,206,157,209,186, -117,107,122,248,192, 80, 94, 94, 94,189,123,247,110,223,176,176,176,209, 59,119,238,220,207,180,238, 38, 38, 30,132,183,183, 39, - 6, 12,124, 89, 21,214,227, 69,140,249, 96, 50, 84,132, 1,197, 69,101,152, 54,243, 43, 44,233,217, 14, 61, 26, 57,175, 36, 15, - 31, 62,156,250,238,187,239, 88, 37,224, 41, 81, 4,108,225,169, 89, 11,224, 73,207, 42,112,134,128, 29,197,134,146, 26, 5,194, -146,168,233, 99, 79,131,188,167,213,163, 96,229, 9,160, 28,241, 0,208,152, 55,111, 94,202,160, 65,131, 36,189,122,245,170,243, -152,229,185,250, 96,121,253,160, 65,131,106, 5,251,217, 58, 86,175,117, 40,240,144,116,109, 18,136,190, 1, 2,188,228,199, 71, - 83, 33, 7, 2,138,130, 80,107, 64, 75, 79, 30,202, 41, 10, 87,170, 13,200, 84, 26,208,172, 81, 0, 90,191, 52,176, 78, 89,180, -213, 79, 79,245,107,217,178, 37,186,117,235,134,242,242,114, 84, 84, 84,160,162,162, 2, 94, 94, 94,232,221,187, 55,116, 58,157, - 57, 39, 64, 93,132, 77, 43, 19,122,189, 30, 4, 65, 32, 52, 52, 20,106,181, 26,197,197,197, 40, 42, 42, 66,113,113, 49,148, 74, - 37, 66, 67, 67,193,227,241,204,242,234,202, 43, 96,173,148, 5, 7, 7, 75, 66, 66, 66,112,231,206, 29, 36, 37, 37, 33, 45, 45, - 13,238,238,238,120,245,213, 87,209,173, 91,183,131, 66,161,112, 14,211,105,123,219,183,111,223, 31,220, 40,232,237,144, 38,190, -168,190,253, 39, 50,147, 54,160, 32,237,119,248, 9,140, 24, 60,232, 85,116,235,214,109,210,199, 31,127,188,143,137, 44,111,111, -111,244,232,209, 3, 20, 69,225,204,153, 51, 72, 79, 79,151, 23, 20, 20,200,191,253,246, 91,113,108,108,172,132,206,156,216,179, -103, 79,164,166,166,218,149, 55,117,234,228, 20, 69,121,150,164,172,248, 50, 4, 66,127, 52,110,250,138, 60,168,113, 47,185,151, -119,235,131,223, 47,253,105, 20, 45,111,251,199,238,216,113, 90,139,186,148,158,204,204, 76, 4, 6, 6,162, 95,191,126,228, 75, - 47,189, 4,149, 74, 5,165, 82,137,149, 43, 87,122,118,232,208,225, 13,185, 92,190,223,145, 54,113,243,102, 38, 90,181,108,142, -183,222, 26,237,254,249,191,103,161,180, 74,129,146,210, 18,196,124,244, 21,190, 26, 51, 8,131, 90, 6, 55,136,252,151, 47, 95, -142, 46, 93,186, 96,197,138, 21,172, 18,240, 24, 97, 57,238,111, 15,143, 45, 19,160, 43,103, 21,152,146,251,184, 36, 19,160, 61, - 88, 39,226,113,133, 18,224, 74,178,118,181, 60, 87,188,106,184, 32, 61,176,149, 2, 65,212,225,177,112, 8, 51,102,204, 72,177, -254,157,229,177,159,127,254,153,145, 76,250, 58, 91,215, 51,149, 65, 99,211,246,157, 41,243,223,153, 0, 67, 90, 34,114, 20,128, - 39,225,134, 86,158, 28, 20, 24, 9,112, 5, 60,164, 22, 25,161, 33,129, 32, 1, 23, 33, 61, 7,224,227,165,235, 83,234, 83, 0, -244,122, 61,184, 92, 46,218,180,105,131, 30, 61,122,160,178,178, 18, 26,141,198, 60, 63, 95,167,211,193,223,223, 31,253,250,245, -195,254,253,251,205, 67, 2,182, 96, 52, 26,205, 89, 4, 59,118,236, 8,147,155, 30, 26,141,198,220,158,105, 79, 66,199,142, 29, - 81, 86, 86,134,234,234,234, 58,219,178, 53,153,159, 60,121, 50, 37, 42, 42,234,213,206,157, 59, 31,183, 72, 4, 84,209,191,127, -255,227, 66,161, 48, 90, 42,149,106, 28, 41,203,147, 39, 79,198, 71, 69, 69, 85,118,238,220,121,159,133,188,146,254,253,251,175, -252,248,227,143, 25,103,235,153, 62,125,122,202,154, 53,107, 36,195,134, 13,195,157, 59,119,228, 55,110,220, 64,110,110, 46,188, -188,188,228,190,190,190, 24, 50,100, 8,126,254,249,103,244,236,217,147,241,189,189,255,254, 59, 41, 63,255,188, 73,162,209,148, -193,215, 47, 84,238,233,213, 2, 94,222, 45,161,172, 42,216,191,120,201, 6, 68,189, 53, 24,219, 63,118, 55,151,147, 45,139,109, -196,136, 17, 72, 76, 76, 68,126,126, 62,167,172,172, 12, 26,141, 6,169,169,169, 60,147,210, 89,121,250,244,105,135,218, 67, 68, -196, 8,236,221,187, 31,149, 21,165,200, 47,188,135,143,103,252, 75,247,201,103,139,248, 99, 94,237,131,126,218, 74,192,205, 57, -122, 24, 62,124, 56,245,197, 23, 95,152,211, 65,135,132,132,224,187,239,190, 3, 0,234,208,161, 67,108,218,240, 39,164, 20, 60, - 73, 5,128, 24, 63,126,188,165, 11,141,176,114,247, 19,142,186,255, 93, 65,238,102,146, 47,217, 0,123,217,246, 28, 9,254, 43, - 41,217, 0, 75, 87,188, 37, 49, 91,187,236,153,144,118,201,134, 18,151,202,123, 6,240,143,234, 36, 90,247,145, 72, 46,105, 13, -242,226,227,199,224,102, 80,227, 82, 21,133,228, 42, 3,248, 4,129, 0,138,130,164,137, 47,252, 26, 7, 73,154,191, 44, 6, 54, -237,180,235, 1,104,221,186, 53,122,245,234, 5,181, 90, 13,189, 94, 15, 62,159,111, 38,108,218, 74, 15, 10, 10, 66,223,190,125, -145,148,148, 84,175, 7,128,199,227,161, 91,183,110, 32, 8, 2, 42,149,202,236, 93,160,149,118, 58,187, 32, 73,146,232,218,181, - 43,254,248,227, 15, 56, 18, 92,185,125,251,118, 57, 0, 66, 38,147, 17, 0, 60, 81,147,109, 47, 87, 42,149,234,157, 41,203,237, -219,183,239, 55,201,243, 4,224, 15,160, 76, 42,149, 58,156,155,120,250,244,233, 41, 0,176,106,213, 42,137,155,155, 27,178,179, -179,225,239,239, 47, 7,128,130,130, 2, 12, 31, 62, 28,203,150, 45,115, 72,230,148, 41,147, 82,100,178,117, 98,157, 78, 33, 17, - 85,230,200,189,125, 67,224,238,217, 20,238,158, 77,113,228,216, 3, 16,131,234,183,184, 55,111,222, 76, 76,157, 58,149, 42, 43, - 43,195,136, 17, 35,116, 1, 1, 1,124,146, 36,145,155,155,235,176, 71, 12, 0, 54,109,218, 76, 72,165, 49,148,247,181,116,204, -152,241, 62,154,135,182,231,127, 55,235,125,114,211,234,205,156,149, 92,141, 83,117,121,248,240,225,212,252,249,243,225,235,235, -139,194,194, 66,136, 68, 34,144, 36, 9, 15, 15, 15,124,243,205, 55,172, 18,240, 24, 16, 22, 22, 86,167, 23,128,105, 42, 96,151, -227, 41,159, 85, 64,148,108, 40,177,121,194, 73,235,159,216, 80,242,176, 60,107, 75,157,118,221, 51, 32,109, 87,203, 99,241, 20, -193, 68, 54,196,155, 17,195,197, 62, 6,173,156,123, 55, 27,237,244,247,224, 21, 16,140, 62, 93, 59, 32,160, 89,160,228,211, 53, -219, 82,118,164, 77,183,235, 69,107,211,166, 13,250,245,235,103, 30,143,231,114,185,208,106,181,230,212,189,150,195, 4, 45, 90, -180, 64,223,190,125,145,146, 98,187,233,137, 68, 34,132,133,133,129,199,227, 65,167,211,153,127,103, 57,117,208,114, 33, 32, 14, -135,131,238,221,187, 35, 61, 61,221,225, 50, 48,121, 7,170, 76, 91,131, 97, 34,253, 6, 47, 74, 96,242, 16,153,219,225,154, 53, -107,196, 42,149, 10, 90,173, 22, 29, 58,116, 64, 92, 92,156,220,177,251,138, 73, 1, 0,153,108,157, 68,173, 46,134, 64,224, 7, - 55,190,151,156,195,225, 97,107,252, 65,201,219,209, 17,245,202, 91,191,126, 61, 33,147,201,136, 31,126,248,129, 84,171,213, 0, -128,208,208, 80,135,210, 47, 91, 66, 38, 91, 71,252,252,243,250,225,147,191,248, 33,177, 70, 30,197, 9, 13,125, 1,161,111,188, -241,246,140, 25, 51,226,157,145,185,100,201, 18,182, 81, 63, 37, 74, 64,125,228,255, 88, 21,128,103, 21,174,156,246,103, 77,204, - 13, 37,106, 23,202,115,181,194,192, 42, 32, 78, 96,231,193, 67, 41,181,202,174, 50, 23, 39,239,228, 50,254,125,100,100, 36,252, -252,252,204, 17,254, 36, 73,154, 93,248,180, 7,128, 14,250,163, 87, 4, 12, 9, 9, 1, 65, 16,216,177, 99,199, 67,242,150, 47, - 95,142,132,132, 4,243,181, 70,163,209,238,114,192,124, 62, 31, 61,123,246, 4,147,232,248,103, 88, 89,107,112, 93,167, 21,129, - 26, 82,223,128,154,112, 44, 82,206, 68,158, 73, 89, 34, 0, 96,205,154, 53,212,244,233,211,137, 99,199,156,159,154, 63,101,202, -212, 67, 38,175, 9,135, 36, 73, 35,135,195, 17, 57, 58,252, 66,131,181,238,159, 46, 37,192,110, 71,237,236, 58,194, 44, 88,176, - 96,193,130, 5,139,103, 23, 28,182, 8, 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88,176, 10, 0, 11, 22, - 44, 88,176, 96,193,130, 85, 0, 88,176, 96,193,130, 5, 11, 22,207, 5,106,205, 2,184,120,241,162,211, 17,156,182,130, 9, 89, -121,172, 60, 86,222,115, 41,143,122,253, 13, 41,126,255, 77, 6,153, 76,198,177,149,173,143, 45, 63, 86, 94,203,150, 45,205,215, -228,230,230, 18, 79,155,188,231,253,125, 56,172, 0,208,141,187,158,235,157,185,193,103, 89,158, 51, 50,159,246,231,173, 5,153, - 76,198, 7,224, 13,192,221, 84, 31, 72, 0, 37,206, 36, 79,121,196,160, 92,245,204,117,148,233, 19,153,190,180,116,233, 82,241, -153, 51,103,228, 39, 78,156, 0, 0, 12, 28, 56, 16,125,250,244, 97,156, 74,248, 73,188,135,215,223,144, 98,196,240, 30, 6, 64, -202,147, 74,165, 36,216,105,159, 44,172,208,178,101, 75,106,212,168, 16,243,254,254,253,160,236,145,182, 61,121, 11, 22,244, 55, -239,127,251,237,201, 6,201, 99, 81,183, 2, 0,106,215,195, 11, 64, 16, 19,202, 27,242, 63,132, 19,196,251,216,228,217,122,222, - 6, 62,243, 83,253,188, 52,241, 95,189,116,114,227,174,237, 43, 7, 53,110, 22, 18,172, 80,232,225,227,227,134,251, 5,183,201, -206,157,187,149,201,100,178, 94, 82,169,244,142, 35, 50,165,147,186, 81,217,183, 51,113, 59, 71,131,188,123, 20, 90, 52, 33, 16, -210, 90,136,182, 33,161,144,109,202,120, 90, 26,171, 45, 69,130, 94,107,224,177,223,227,229,203,151,229, 97, 97,135,177,118,173, - 10, 41, 41,192,194,133, 71,144,151,151, 39, 31, 53,106, 20,132, 66, 33, 10, 11, 11, 37, 99,198,140,129, 43, 20,130,183,223,126, -155, 82, 40, 20,146, 33, 67,134,224,163,143, 62, 74,113,162,206,112,164, 82, 41, 70, 12,239, 65,198,196,196,240,128,117,248,253, - 55, 64, 38,147, 17, 76,115,246,179,248,231, 64,167,155,143,164,164, 24, 12, 27,182, 14,163, 70, 45,193,254,253, 53,109,207, 89, -226,190,121,115, 14,126,253,117, 12,198,142,221,139, 5, 11,106,148,128,134,200,123,222,193, 38, 2,114,132, 97, 45,200,158, 32, - 0,114,167,223,115,251,172, 43, 87, 44,123,231,192,190, 95, 98,219,181,107,223, 97,236, 27, 3,209,162,153, 55,124,125, 4, 40, -175,208,160,224, 94, 11,206,173,236,242,192, 3,251,126,145,175, 92,177,236,135, 15,103,206, 89, 97, 79,222,199, 31, 78, 20,223, -201, 60, 32, 47, 42,204,192,155, 17, 64,223,112, 32,164, 21,144,149, 67,225,212, 57, 53, 18,229, 25, 24, 61,212,155,106, 19, 58, - 82,242,227,202,109,206, 18,153, 43, 45,127,194,134,236, 39,162, 4,148,149,149,225,163,143, 84, 8, 10, 2, 34, 35,129,197,139, -171,113,225,194, 5, 24, 12, 6, 8,133, 66, 52,106,212, 72,126,224,192, 1, 76,157, 58, 85,178,126,253,122,135,202,110,250,244, -233,226, 43, 87,174, 32, 56, 56, 88,190,123,247,110, 98,235,214,173, 0, 32, 79, 78, 78,198,251,239,191,143, 13, 27, 54, 56,250, -172,124, 0, 72, 60,116,158, 3,172, 35,107, 62, 31,206,241,207,130,181,254, 1, 96,220,184, 61, 72, 74,170,249,140,137,185, 13, -218, 35,224,168, 55,128,150,247,206, 59, 91,240,235,175, 53,159, 99,198,156, 4,237, 17, 96,189, 1,245, 19,191,229,113,107, 37, -128, 13, 2,180,225, 5,120,158,201, 95, 38,147,241,142, 38,237,250, 92, 50,160, 71,135,177, 17,161,232,214,185, 17, 2,252, 68, - 32, 64,192,219, 83,128,208, 16,127, 12, 25,216, 26, 3,251,117,111,117, 52,105,215,231, 50,153,172,177, 61,153,119, 50, 15,200, -251,135, 87, 98,215, 74, 96,114, 36,208,193,228,249,243,112, 7, 58,182, 3,190,156, 13,244,238, 86,137, 59,153, 7,228, 13,121, - 69, 13,245,122,216, 81, 36,158, 72, 7,226,239,239,143, 3, 7, 68, 40, 46, 6, 18, 18,128,242,114, 30,218,181,107,135,145, 35, - 71,210,203,189, 34, 37, 37, 5,233,233,233,242,165, 75,151,138,153,202, 29, 54,108,152,248,234,213,171,114, 62,159, 47, 47, 47, -175,237,201, 82,171,213,216,176, 97, 3, 36, 18,137,163,229, 73, 2,192,239,191,201,144,120,232, 60,231,247,223,100, 13,122,246, - 41, 83,166, 80,244, 86,223, 49,134,245,130,114,226, 88,189, 88,183,118,173,120,221,236,217,226,139, 83,167, 82,121, 35, 70, 80, -103, 39, 77,162, 86,125,244,145,120,221,218,181,226,134, 60,115, 67,235,140, 45, 25, 76,143, 61,106,121,180,235,127,212,168, 16, -196,196, 36,213,250,164, 49,106, 84, 72,173,241,124,123,242, 22, 44,232,143, 5, 11,250, 99,204,152, 95,107,125,210, 88,176,160, - 63, 99,121,255, 36,132,133,133,213,218,108, 41, 7,172, 2,240, 52,176,192, 99,196,213, 75, 39, 23,183,107,215, 46,180, 87,143, - 38,181, 43, 2,135, 0,159,207,133, 72,200,131,155, 27, 7, 33,109,252, 16, 18,210,174,209,213, 75, 39, 15,200,100,178, 58, 61, - 69,210, 73,221, 40, 46, 42, 49,123, 50,160,209, 2,119,242,128,114, 5, 80, 81, 9,108,219, 7,204,252, 2,136, 93, 10,244,233, - 1,112,168, 74, 72, 39,117, 99, 27,170, 5,186,118,237, 42,249,253,247,142,104,212, 8,152, 56,145,135,198,141, 95,194,192,129, - 3, 37, 7, 14, 28, 32, 70,142, 28, 41, 25, 54,108, 24,130,131,131,113,254,252,121,236,220,185, 83, 62,110,220, 56,241, 79, 63, -253, 84, 47, 1,245,239,223, 95,172,213,106,229,110,110,110,245,254,183, 92, 46,199,160, 65,131,152,144, 25, 21, 29, 29, 77, 73, -165, 82,157, 41,102, 4, 22,228, 79, 0, 64,116,116,180,195, 10, 90, 90, 90,154,121,171,239,152,147,205,150,104, 72,243, 94,183, -118,173,184,237,141, 27,242, 49, 23, 47,202, 91,100,102,129, 95, 89,137, 38,153, 55, 32,254,227,172, 60, 40, 35, 67, 46,115, 82, - 9, 72, 75, 75,195,148, 41, 83,168,153, 51,103, 58,173, 68,208, 50,152, 28, 99, 42,207,154,232,153, 28,179, 7,154,244,233, 79, -221,168,118, 13,106, 43, 52,233,211,159, 55,123, 5,177, 29, 72, 61,196,207, 4,207,170, 2, 64,217,216, 92, 38,248, 17,222, 31, -229,226,219,164, 28, 45,139,171,215, 50,134,135,134,248,155, 73,223,214, 50,205, 66, 1, 15, 6, 3,137,208, 16,127, 92,189,150, - 17, 2,192,167, 46,121,217,183, 51, 17,241,106,205,247,195,169,192,251,159, 1,107,183, 1,133, 15,128, 27, 89,192,133,171, 20, -146, 79, 3,199,206, 0,195, 6,214, 92,223, 0,221,140,120,132,175,248,137, 40, 38,243,230,205, 75,169,174,174,137,183,156, 56, -113, 34,206,158, 61, 75,200,100,178, 20,250, 92, 89, 89,153,164, 99, 71, 30,166, 78, 5,186,119, 63, 7,163,241,134, 60, 63, 63, -191, 78, 79,202,244,233,211,197, 4, 65,200,153, 46, 14, 83, 84, 84,100,215, 43, 19, 29, 29,141,248,248,120, 0,160, 82, 83, 83, -117, 22,239,130,160,137, 63, 62, 62, 30,209,209,209, 79,178, 63,112,246,152, 77,104,175, 92, 65,155, 63,255, 52, 45,130,164,131, -129, 36, 65,234,141, 32,245, 6, 4,157, 76, 69, 37,195,245,214,235, 34,220,191,254,250, 75,254,202, 43,175, 60,114, 37,192, 25, -239, 66, 67,201, 95, 55,170,157,205, 45, 41, 38,201,169,123,186,217, 43,200,230,246,235,152, 95, 89,182,111, 32,108, 42, 0,196, -132,242,135, 54,103, 9,135, 1, 33, 58, 42,143,168,103,123, 42,148, 13,106,151,159,205,173, 1,202,203, 67,215,219,249, 15,155, -144,201,100,188,198, 77, 67, 58, 53,109,236, 9,138, 2, 82,207,228,225,240,177,108, 28, 62,150,141,162, 18, 21, 40,138, 66,110, -126, 37,153,114, 58, 23, 89,119,202, 17, 24, 32, 66,211,166,237,124, 81,179, 68,171, 77,220,206,209,160,111, 56,160,213, 3,135, - 78, 0,242,179, 20, 86,108, 6,110,100, 3,131,250, 1, 29, 66, 8,240,184, 53, 75,139,247, 14,171,185,158,225,179, 58,243,157, -169,165,104,203, 61,252,196, 28, 64,166,229, 92,241,226,139, 47, 74,172,207,113,185, 92,121,167, 78, 69, 88,184, 16,248,207,127, - 40, 52,109,154,137,156,156,156, 58,101,105, 52, 26,187,150,191, 37,234,147, 69, 35, 62, 62,158, 38,123,179, 34, 64,111, 22,196, - 79,152,174,123, 18, 78, 59,235,246,207,244, 88,157,104, 95, 82, 42,215,233,245,208,233,245,208, 25, 77, 43, 40,146, 36, 72,163, - 17, 70, 35,137,230,247,238, 53,100, 56, 11, 42,149, 10, 74,165, 82, 62,101,202, 20,106,234,212,169, 13,242, 38,184, 74, 9,112, -149,229, 79, 19,253,184, 61,127,127,167, 63,157,241, 2,208, 68,255,206,150,191,191,211,159,172, 23,192, 62, 44,151, 6,102,180, - 28,112, 93,179, 0, 26, 48, 59,160,174, 40,118,103,162,219,169,122,254,131,114,224,255, 25, 61,183,141,223, 50,106, 92,245, 4, - 21, 58, 35,175,206,223,208,255, 67, 0, 32,119,217,141, 93, 32,107,162,253, 5, 0,128,188,194, 74,168,213, 6, 0, 64,187,182, -126, 8, 10, 16, 33,227,106, 17,231,230,173, 50, 8,133, 92,132,180,241, 69,185, 66, 7, 0,117, 10,206,187, 71, 33,164, 85,205, -255,191, 54, 0, 8,235, 68, 64,192, 7, 12, 6, 96,104,127,192,215, 11,200,206, 5,134, 13, 0, 90, 53,175,185,254, 9,163, 46, - 37,224,185, 24,253, 41, 42, 42,114,168, 29, 86, 85, 49, 95,125, 55, 62, 62,158,136,142,142,166, 76, 74,128,165,119,224,137,151, - 93,219,182,109,169,236,236,108,194,217,243,214,112,187,157, 5,173, 94, 7,130,203,131,145,162, 64, 0, 48, 24, 73,232, 13, 36, - 40,163, 17,196,173,155, 46,185,239, 43, 87,174, 32, 48, 48, 80,254,221,119,223, 73, 62,253,244,211, 20,103,149, 0,235, 97, 20, - 71,137,219, 85,228,159,155,155, 75,180,108,217,146, 26,183,231, 97,133, 96,216,186, 97,224,239,207,194,254,253,183,205,145,251, -246,198,238,105,121,239,108,121, 88, 33, 24,187,119, 44, 94, 72, 43,198,183,223,158,100, 44,239,159, 72,254, 52,158,167, 89, 0, -245,145,168,195, 4,219,192, 41,142,117,203,125,196,179, 9,136, 9,229,142,254, 7,225,227,227,134,242, 10, 13, 2,253,221, 17, -249,255,237,125,121, 92, 84,213,251,255,251, 14, 48, 12, 48, 40,184, 34, 26, 9,238,226, 26, 46,168, 89,140,185,141, 8,184,145, -125,202,210,180,152,248,148, 89,185,160,150,102,125,234,167,144, 38,159, 44,117, 76, 83,250,182,104, 35, 26,226,134, 81, 67,105, -106, 37,110,185,148, 2, 38, 38, 34,137,178, 13, 51,204,114,207,239,143,153,139,151, 97,150,123,103, 6,177, 62,247,253,122,241, - 98,230,204,153,103,206, 61,231,222,243,126,158,231, 60,231, 57,241, 61, 97, 52,209,240,245,245,130,151, 72, 4, 66, 8, 38,142, -237,130,216, 49, 93, 64, 81, 64,249, 29, 45, 90,182,244, 1,128,219,246, 4, 62,208,129, 66,225, 85,130,158, 93,128, 81,195,204, -157,253, 91, 1,208,175, 39, 16,220, 2,144,199, 0, 52, 13,120,123, 1,151,174,152,235, 23, 93, 35, 92,199,150,207,107,119, 31, -252,102,217, 6,184, 97,195,134,152,213,171, 87,163,176,176, 16, 63,252,240,131,250,189,247,222,147, 73,165,210,250, 99,103, 77, - 38,147,236,194,133,118,234,183,222,186, 14,138,162, 80, 86,214, 29,221,187,119,198,165, 75,182,151, 82,104,154,182, 89,254,216, - 99,143, 53,234, 31, 66, 8,190,251,238, 59, 94,215,204, 86, 2,238, 39,242,247,132,146,192,198,237, 78, 29, 33,254,237,119, 16, - 31, 64, 76, 19, 80, 20, 96, 48, 25,161, 39, 38,212, 26,141,208,118,237, 9, 92,248,205,237,182,247,233,211, 7, 20, 69,185, 68, -254, 0, 48,100,200, 16,108,222,188,153,234,215,175, 31,113, 84,230, 12,155, 55,111,166,172, 9,223, 86, 25, 31, 36,229,220, 37, -126, 0, 16,103, 23, 52,248,156, 9, 24,204,206, 46,228, 36,111,242,174,187,196, 15, 0, 61,126,254,171,145,188, 37, 75, 70, 98, -229,202,195, 2,243,115, 32,127, 64, 8, 2,180,229, 30,100,187, 9,221,154,220, 8, 1, 68,211,239, 52, 89,163,201, 87,193,230, -223,224,174,192,120,151, 94, 47,188,117,237,186,217,234,123,127,195, 47, 56,125,174, 12, 6, 3, 13,154, 38, 22,165,133,170,143, - 13,184,118,189, 26,165,215, 11,175, 0,176,107, 86,118,233, 44,193,143,249,230,215,109,162,128, 83,231,129,164,127, 1, 93, 31, - 52,187,253,223,249, 16, 16,251, 0, 34, 17,240, 99,190,185,190, 27, 4,237,233, 24, 10,235,241,190,231,214,195,133, 11, 23, 32, -145,152,251,100,223,190,125,248,252,243,207,213,121,121,102, 46, 88,189,122,117, 76,171, 86,173,212, 23, 47, 26,241,241,199,192, -169, 83,131,224,229,213, 83,214,169, 83, 39,153, 61,121, 1, 1, 1,156,127,219,104, 52,254,237, 31, 92, 54,249, 71, 68, 68, 16, -123,127,124,149,133,194,182,237,100,119,244,117,168,210,235,161,213, 27, 80,103, 52,194, 64, 76,168, 53, 24, 80,173,215,163, 36, - 52, 84,230, 78,187,253,253,253, 17, 16, 16, 32,219,188,121, 51,197,119,123,167, 53,209, 59, 43,227,163, 4, 12, 25, 50,196,105, - 25, 23, 47,128, 61,242,103, 91,255,124,228,217, 35,127,182,245, 47,128, 31,249, 11, 10,192, 61, 64, 83,111, 41, 36, 95, 5,131, -128,179,162, 97,140,140,236, 95, 82,112,229, 14,104,154, 96,241,188,104, 92, 42,184,141,139,151,202, 65, 81,104, 16, 16, 72,211, - 4, 5, 87,238, 32, 50,178,255, 57, 0,118,253,196, 17, 93,186, 99,223,119,128,201, 4,144, 34, 64,125, 12,200,254, 22,144, 63, - 11,200,158, 4,242,142,155,235,153, 76,192,190,239,204,245,155, 17, 4,142,115, 1,220,115,220,190,125, 91,221,171,215, 21,252, -252, 51,112,236,152, 9,157, 58,157,197,169, 83,167,212,113,113,113,100,239,222,189,234,156,156, 28,220,188,121, 19, 15, 61,244, - 16,166, 79,159, 46,203,204,204,204,115,148,196,135, 16, 34,179,231, 5,176, 6,163,120,240, 5,179, 4,192, 94, 10,104, 46,176, - 45,250,162,162, 34,202,222,159,173,250,142, 16, 60,112, 32,202, 71, 62,130,219, 90, 29,238, 24,234,160, 51, 26, 81, 99, 48,161, - 82,175, 71,245,168,199,208, 38, 42,202, 69,175, 32,133, 33, 67,134,160,111,223,190,178, 99,199,142,229,185, 35,131, 77,244,182, -202,220, 81, 2,216,115,129,173, 50, 46,176, 69,254,140,165,110,157, 41,144, 11,108,145, 63, 91, 30,123,107,160, 64,254,206,201, - 95, 80, 0,254,238,110, 11, 38, 72,147,227, 50,128, 66,161, 48, 69,246, 27, 57,170,176,176,224,183,159,242, 75, 64,211, 4,242, -209, 17, 56,123,190, 12,239,190,127, 12,239,172, 57, 90, 79,254, 63,229,151,160,176,176,224,106,100,191,145, 47, 41, 20, 10,131, - 61,153,202,109,103, 40, 19, 90, 96,237, 39,102,146,223,248, 14,240,233, 46, 64, 22, 13, 12,236, 13,228,125,105, 46, 95,251, 9, - 96, 66, 11,119, 50, 2,186, 27,232, 73,156,200,105,150,181, 67,141, 70,131,190,125,117, 24, 60, 24, 24, 60, 24, 24, 52,136,160, -168,168, 8,217,217,217, 56,126,220,172, 61,197,196,196, 32, 42, 42,138, 83,122,224,204,204,204, 60, 46,196,110, 52, 26, 17, 24, - 24,200,219,138,181, 68,253,215, 71,252, 51,239, 93,181, 96,153, 63, 71,101,124,148, 0, 79,212, 3, 0, 69,114,114,158,126,232, - 80,217,197,177, 99,100,165, 61,122,160,212,199, 7,165, 61,123,226,210,184,113, 50,211,176,104,153,194,178, 68,195, 23,131, 7, - 15,134, 59, 86, 63, 91,134,179, 50,174,125,104,203,234, 31, 60,120,176,211, 50, 87,192,228, 8,184,155, 20,168,208, 45, 11,158, -201, 17,192, 74, 10, 36,120, 4, 56,146, 63, 32,100, 2,108, 82,203,252,126,252, 13,133, 66, 81,254,225,186,247,211,115, 14,238, - 88,248,231,141,234, 46, 93,195,131, 17, 59,182, 11,130,131, 36,184, 83,161,195,169, 95,111,162,224,202, 29, 20, 22, 22, 28, 29, - 55,126,250, 46, 0,215,156,201, 12,239, 62, 81,118, 56,127,175,250,104,126, 21, 98, 71, 1, 31,175, 52,103, 2, 44,188, 10,108, -249,202,108,249,155,208, 2,225,221, 39,202,112,232, 11, 79, 16,184,167,191,219,108,187, 0,110,220,184, 33, 11, 14,110,163, 62, -113,194,108,213, 92,186,212, 2,131, 7,247, 70,235,214,173, 33,145, 72,112,227,198, 13,217,196,137, 19,121,165, 2,238,220,185, -179,236,247,223,127, 87,219,179,216,140, 70, 35,186,118,237,138, 45, 91,182,240, 34, 33,235,181,127,214,123,226, 74, 44,128, 45, -107,213, 85, 11,214, 25,185,243, 33,127,182, 18,208,224,190, 56,123,214,237,241,118,215, 66,231,211,111, 92,127,203,211,242, 28, -145, 63, 27,250,184,174, 0,199,245,127,123,228,207,134,176, 35,192,190, 39,192,158, 98,224,109,207,178,228, 83,206, 99, 2,246, -148,213, 69, 92,252,236,158,180,207, 73, 63,121,164,125,238, 4, 46,190, 52,247, 53,165, 82,169,220,126,254,236,225,245,187,179, -190,143, 8,233,216, 37,154,117, 22,192,241,200,200,254, 63, 79,140,159,189, 84,161, 80,104,184,200,179,164,247,165, 20,179,250, -147, 29,251, 46,225,255,125,100,231, 44, 0,215,201,223, 35, 14,147,251,141,252, 1,224,137, 39,158,192,153, 51,103,240,236,179, - 39, 0, 0,131, 6, 13,194,227,143,247,151,189,250,234,171,245,228,252,227,143, 63,242,146,185, 97,195,134, 60, 0, 84,108,108, -108, 76,117,117,181,218,203,203, 11, 34,145, 8, 70,163, 17, 98,177, 24, 82,169, 84,230, 46,249, 3,240,136, 18, 32,224,159,137, -226,226, 98, 42, 39, 41,135,132,206, 13,149,161,179,237, 58, 37, 73, 57,106,174,214,122,113,113, 49,181,107,242, 46,210, 45,181, -155,236,215, 32,219,117, 46, 79, 62,172, 22,172,127,126,240,230, 49, 81,122,122,226,109, 10,121,212,125,222,190,251, 65, 30,227, - 9,168, 84, 42,149, 51, 34,251,141,100, 50,198, 72, 1,180, 1,112, 3,128,214,114,202, 27, 47, 88,187,247,139,174, 17, 20, 93, -211, 2,135,207, 52,119, 63, 80,247,186,127,185,194, 66,244,245,109, 56,119,238,156,199,100,239,219,183, 47,207, 83,215,199, 90, -247,167,172,202, 41, 88,242, 1, 8, 16, 96, 77,218,197, 11,139, 61,246, 76, 23, 23, 23, 83,197,255, 42,198,253,250, 44,223, 47, -224,154, 5, 16, 0, 40, 87,207, 17, 22, 32, 64,128, 0, 1, 2, 4,252,125, 33, 4, 1, 10, 16, 32, 64,128, 0, 1,130, 2, 32, - 64,128, 0, 1, 2, 4,131, 1, 0,215, 0, 0, 32, 0, 73, 68, 65, 84, 8, 16, 20, 0, 1, 2, 4, 8, 16, 32, 64,128,160, 0, - 8, 16, 32, 64,128, 0, 1, 2,254, 25,104,176, 11,224,244,233,211, 46, 71, 81,218, 10, 38, 20,228, 53,153, 60,167,135,216, 52, -167,188,196,196,196, 24, 0,106,149, 74,229, 17,121,211,167, 79,143,161,105,218, 99,242,132,251,175,121,228, 37, 39, 39, 79, 87, - 40, 20, 95, 53,101,251,148, 74,165, 15, 0,137,229,158,214, 1,160, 1, 16,133, 66, 65,132,241, 16,228,253, 47,201,243,148, 7, -128,112,248,227, 3, 79,203,187,103, 32,183,211, 8,169, 73,231,220, 62, 11, 17,122,236,122, 89,242,176,102,205, 26,153,131,254, -228, 45,239,220, 71, 45,224,174, 60, 6,147, 6,239, 87,135,183,200, 6, 0, 68, 69, 69,185, 61,158,221,219,239,192,131,109,191, -133,159,159, 31, 70,143, 30,125,223,220, 31, 74,165,178, 45, 21, 32, 61,168, 84, 42,219,122, 72, 94,152,200,215, 63,199,158, 60, -165, 82,233,163, 84, 42, 41, 39, 50,124,152,182, 73, 36,254, 7,149, 74,101, 91,165, 82,233,229,236,123,174, 60, 14, 46,220, 27, -199,154,106, 44, 54,109,218, 52, 97,243,230,205, 11,124,124,124,118,139,197,226,124,177, 88,252, 27, 0,165,151,151,151,138,162, -168,245, 74,165,178, 77, 19,244,129, 0, 1,141, 80,187,104, 17,241,240,131,214,100,115,158,179, 76,128,132, 16,251,191,205, 51, - 55, 52,177, 8,244,148, 60, 94, 22,172, 39, 49,109,218, 52, 82, 80, 80,224,148, 92, 85, 42,149, 58, 37, 37, 5,237,218,181,179, -153,114,117,254,252,249,156,207, 20,103,228,173, 89,179, 70, 54,127,254,124,245,241,227,199,213, 86,138,128, 75,242,232, 11,203, - 33,234,253, 54, 62,253, 78, 15, 0,160, 47, 44,191,171, 29,246,126,155, 87,191,124,249, 94, 0,161, 9,176,253,160, 89,150,252, - 81, 31, 68,118, 61, 15,192,172, 4,228,231,231,243, 26,155,180,143,100, 49, 21,127,148,163, 70, 31,172,214,212, 5, 64, 62,174, - 2, 29, 67, 40,132,135,207, 36, 85, 85, 58,236,216,177,163, 89, 39,244,228,121,243, 94, 6, 77,143, 77,158, 55,239,101, 0,203, -220,150, 55,119,222,243,132,166,199, 36,207,181, 45,207, 81, 74,102,118, 29,165, 82, 73,205,157, 59,239,101,154, 54,141,157, 59, -119,222,203,122,189,110,153, 13, 69, 65,228, 74,174, 7, 55,161,103,223,127, 59,119,238, 84, 79,153, 50, 69,150,153,153,153,231, -142,208,205,155, 55,203,189,189,189, 31,241,246,246,126,194,203,203, 43, 88, 36, 18, 73, 83, 83, 83, 69, 11, 23, 46,156,109, 50, -153, 96, 52,227, 9,147,201, 20,167, 84, 42,127,180,120, 3,244,150,249,175,201,151, 65,227,227,227, 9,215,249, 46, 43, 43,139, -215, 61,157,144,144, 64,220,249,190, 0,207,195, 47, 45,205,163,242,180,139, 22, 1,110,200,100, 50, 2,242, 61, 14,216, 41,249, - 71, 69, 69, 33, 63, 63,159, 15, 57, 59, 36,121,142,242, 26,201, 79, 73, 73, 65, 81, 81, 17, 44, 46, 98,143, 29,235, 74, 74,162, - 8,252,186,131, 10,254,146, 2, 0,170,213, 34,106,218,180,105, 78,181, 49, 54, 89,151,149,149,169,237,145,127, 74, 74, 10, 82, - 83, 83,121,145,191,229, 61,162,163,163,101,209,209,209,110,201, 99,200,158,249,191,234, 63,104, 64,254,139,166, 74,144,150,169, -227,212, 87,219,211,165,164, 79,184, 8, 26, 45,193,107, 79, 75,112,252,188, 17, 90, 13, 65,173, 30,144, 13, 56,143,243,151, 76, -136,138,138, 34, 92,149,128,148, 55,122,146,194, 83, 85, 8,108, 33, 70, 72, 7, 41,218,182,239,138,171,133,122,116,238,109,128, -143,164, 12,185,187,111, 97,252,248,241,228,224,193,131,205, 53,225,249,182,106,221,122,222,103,199,127,166,228, 61,186,189, 12, -224, 29, 0,117,238,200,107,221,170,245,188,237,223, 29,167,198, 12,232,225,150, 60,133, 66, 33, 14, 9,233, 48,239,144,250, 48, - 53,168,127,164, 77, 89,205, 64,254, 0, 80,127,252,160, 74,165, 82,199,197,197, 33, 51, 51, 83,109,235,121,253,229,151, 95,200, - 91,111,189,133,189,123,247, 58, 28,223, 45, 91,182,140, 18,139,197,125,196, 98,241, 92,177, 88,236,127,237,218, 53,116,235,214, - 13, 94, 94, 94, 8, 12, 12, 68, 65, 65, 1,164, 82,169,247, 47,191,252, 18,116,236,216,177,195, 47,190,248, 98,103, 0, 87, 1, -136, 97, 94, 30,176, 59,241,177,231, 63,246,188,197,148, 83, 20, 5,138,131,213,178,103,207, 30,187, 50,216,229,142,230, 91,123, -200,202,202,114,235,251, 77,170, 32, 39, 39,199, 88,178, 82,186,141,183,223,126,155,208, 52, 13,136, 42,160,175,211, 65,236, 43, - 1,232, 32,136, 68, 34, 44, 95,190,156, 58,102,197, 51,201, 14,100,157, 63,127,158,100,102,102,194,158,188,169, 83,167, 34, 50, - 50,146,114,181,125, 88,158,142, 21,111,191, 66,216,237,115,231,218,253,211,210,120,127,223, 94, 26, 96,174, 10, 0, 39,242,231, -138,148,148, 20,167,117,184, 16,151, 61,242, 95,181,106, 21, 22, 47, 94,108,173,116,184,212,233,228, 68, 20, 65,235,238,160,194, -191,164,216, 22,255,206,157, 59, 41, 0, 96,254,219, 91,115,177, 38,107, 71,228,111,241, 12, 56,181,218, 85, 42,149,218,218,194, -103,202,216,125,204, 87,158, 35, 11,127,209, 84,238, 39,197,101,166, 7,144,110, 15,138,224,231, 75,225,193, 80, 47,220,186, 67, -195, 96,244, 66,121, 5, 65,101, 13, 65,193,159, 52, 32, 2,218,248,159,101,250,199,225,164,176,244,245, 30, 49,221,187, 68,224, - 88,233, 77,132,135,181, 69,159,126, 17,240,242,109,133, 7,195,239,224,142, 86,135,178, 82, 19,254,188,169,131,191,119, 17, 39, -121, 77,132,167,158, 94,184, 80, 92,212, 33, 20,190, 81,131, 68,186,195, 63, 60, 5,224, 19,190, 66, 88,150,248, 83, 51, 95, 94, - 32,254, 83, 28, 2,105,247,135, 68, 85,231,142,184, 36,143,105,219,139,243, 94, 21,195, 55, 16,225, 61, 34, 69,191,255,122,210, - 29, 89,158, 4,205,178,254, 33,145, 72,100, 0,212,214, 99,120,226,196, 9, 78,228, 15, 0, 62, 62, 62, 65, 18,137,100,214,173, - 91,183,252,187,119,239,142,129, 3, 7,194,219,219, 27, 31,124,240, 1, 76, 38, 19,250,246,237,139, 93,187,118,225,151, 95,126, -193,217,179,103,225,229,229,181, 94,169, 84, 38,108,216,176,193,145, 85, 93, 63,207,121,194, 99,169, 84, 42,101, 33, 33, 33,106, - 66,136,195,239,148,150,150,202, 20, 10, 5,223,251, 71, 22, 18, 18,162,118,245,251, 12, 81, 95,188,120,209,225,188,209,171, 87, - 47, 25, 95, 50,191,120,241,162,250,201, 39,159, 68,203,150, 45,101,238, 40, 2,138, 23,102,146,164,228,177, 8, 8,240,107,244, -153, 70,163,197,242,229,203, 49, 12,160,254,220,179,135, 92,139,143,183, 63,183,207,232,110, 30,204,149,147,209, 97,212, 68, 72, - 30, 26, 4, 83,247,200, 6,117, 12,219, 51, 16,188,114,242,221,186, 0,180,227,159,195,240,213, 95, 56,108,223,204,103,199,160, - 85,107,127,115,193,242,116,204, 95,240, 44, 0,224,118,121, 45,174,151, 20, 18,229,198, 12,151,149,128,218, 69,139,136, 43, 74, -128,171, 10, 0,225, 98,169,223, 47, 40, 42, 42,194,226,197,139, 93, 85, 32,236, 98,218,180,105,132, 10,221, 73, 77,155, 22, 78, - 84,155,134, 0,219, 30, 38,148,244, 21,167,131, 96,139,172,173, 73,217,209,178,128, 61,176, 21,138,227,199,143,171,163,163,163, - 27,184,254,249,202,251, 98,161,212,238,228,246,212,106, 13,103, 57, 27, 54,108,136,241,245, 90, 8,145, 8,240,247, 3, 42,170, -104,212, 17,130, 0, 63, 10, 58, 26,208,214, 17,116,106, 43, 2,109, 4, 46, 95, 51,161,168,168, 72,237, 72, 57,155,247,242,152, -152,240, 7,253,213, 98, 49,193,243,179,134,194,100, 34, 40, 45,211,163,248,122, 5,224,115, 13,126,193,117,184, 81,246, 7, 68, -226, 74, 92,184, 80,129,150,193,142,229, 53,157,249,223,106,249, 19,207, 60,227,251, 6, 13, 4, 47,126, 93,122,243,204,233,101, -116, 85,149, 43, 36, 75, 0, 64,210,178,213,242,127,205,120,198,119,245, 21, 19, 58, 77, 79,145,254, 94,116,118,153,169,182,161, - 60,165, 82, 73, 89, 7,179,217, 66,139,150, 65,203,159,154,241,180,239,217,226, 59,136,127, 50, 73,250,225,127,230, 47,211,214, -106,220, 85, 0,184,158,151,225,104, 44, 76,204, 51, 50,113,226, 68, 48,164,175,213,106,235,199,144,177,252,179,179,179, 57,141, -169,175,175,239,112,141, 70,211,179, 87,175, 94,144,201,100,152, 63,127, 62,230,204,153, 99,158,204, 13, 6,108,219,182, 13,249, -249,249, 56,121,242, 36,118,236,216, 1,173, 86,219,149,166,105,185, 19,139,221,163,247,211,190,125,251, 56, 45,205, 81, 20,197, -251, 94,102,203,118,229,251,150,103, 56,239,201, 39,159, 68, 73, 73,137,205,207, 67, 67, 67,225, 42,129,151,148,148,160,164,164, -196, 45, 69,224,236,153, 75,248,191,140,189, 24, 57,114, 56, 34,251,118,188,107,201,255,122, 29,135, 15, 31,197,176, 97,195,136, -106,201, 18, 92,139,143,135,223,136, 17,208,218, 57, 59,131,250,236, 18, 5, 0, 11,134,247, 33,253,202, 14,226,233,239,246,194, -212, 61, 18,218, 5, 43, 0, 0,126,171, 87, 64,122,233, 60, 22, 22,137,177,250,232,185,187,253,248,217, 34,135, 65,118, 76,251, - 70,143, 25,209,168,125,185,223,252,136,179,103, 46,185,117,255,184,178,164,192,118,247, 59,242, 6,120,243,181,216, 61, 77,180, -238,194,226,246,119,125, 86,139, 2, 65, 7,128,218,107,126,112,168, 65,249,212,180,105,225,245,131,189,115,231, 78, 10,155,134, - 16,107, 79, 0, 87,178, 46, 43, 43,107, 64,206,174,144, 53, 87,176,148, 14,167, 36,193,197, 93,200,114,255,219,172,188,113,227, - 70,242,215,249, 87,209,161,187, 23, 52,218,187, 85,180, 38, 2,157, 30, 48, 88,202, 12, 70, 2, 34, 50,191,254,245,108, 62, 18, - 19, 19, 99, 46, 95,190,108,243, 55, 3, 3, 43,213, 26,173, 8,109, 90, 5,161,226,118, 45, 42, 42, 43,112,252, 68, 41,174,223, - 36, 16, 7,212,162, 99,215, 26,104,107,111,161, 91, 63, 3, 58,247,170,195,142,143,243, 49,121,242,228,152, 43, 87,174,220,147, -251,205, 98,177,143,158, 56,117, 90,251,146,150,193, 40, 52, 2,126,163,199, 66, 20,220,186, 13, 93, 85, 53, 22,192, 33,134,172, - 1,248, 40, 20, 10,189,179,121, 31,192,152,184,201, 83,219,255, 37,106,137,171, 53, 6, 4, 61, 52, 26,222,129,193,109, 76,181, -119,229, 1, 0, 23,242, 7, 48,110,210,228, 41,237,137,151, 47, 42, 53,117,232, 19, 53, 12,210, 22, 45,219,104,107, 53, 13,100, - 53, 23, 24,235,159,162, 40, 76,156, 56,145, 0,192,222,189,123,145,152,152, 24,147,146,146,162,230, 67,254, 74,165,210,183,162, -162, 98,166,193, 96, 16,249,251,251,227,145, 71, 30,193,234,213,171,225,227,227, 3,133, 66,129,140,140, 12,228,231,231,227,248, -241,227,248,246,219,111,241,235,175,191,162, 77,155, 54,109,140, 70,227,131,176,227,254,103,187, 64,157, 45, 1,136, 68, 34, 78, -237,108,202, 37,128, 61,123,246,120,100, 9,160,101,203,150,178,146,146, 18,181,189,207,220, 29,119, 87, 20,129, 75,139, 22,145, -242,180, 52,224,216, 49,224,216, 49,220,158, 58, 1,107,250,119,175,119,217, 71,246,238,141,199,167,199,162,243,157, 91,184, 22, - 31,143,214,139, 22,161,123, 90, 90,163,229, 0,107,136,101, 15,163,187, 60, 6, 11, 23,189,131,247,112, 30,107,162, 71,161,207, -224,161,232,122,187, 8,219,130, 6,162,168,229, 77,100,100,100,144,153, 51,103,114, 26, 95,217,168,254,120,122,230, 68,252,252, -211,175, 56,152,115, 8,111, 2, 88,179,122, 43, 34,123,247,198,211, 51, 39,162, 86, 91,142, 23, 94,120,129,179, 60,107,184, 27, - 3,192,215, 3,240,119, 2,101,135,156,120,119,244,180,105,211,136,106,241, 21,192, 75, 12, 4,249, 0, 65,157, 65,237,180, 8, -227,184,246,223, 4, 32,108,171, 31, 0,216,150,191,141,201, 21,209,209,209, 50, 7,193,128,188,175,225,243, 5, 1,118, 61, 2, -129, 85,243,241,135,158,160,244, 22, 13, 64, 4,169,191,217,197,105, 48, 18,232,234, 0,157, 30,208,213, 1,122, 3,160,211, 2, -250,186,187, 94, 18, 91, 1, 41,159,127, 20, 64,114,143, 87,227,129,112, 41,136,143, 55,110,105,181, 80,127,127, 13, 23, 10,174, -227,246,237, 26, 68, 70,153,160,209, 25,161,171, 51, 65, 91, 75,163,180, 24,208,106,128,221,187,119,171,249, 28,128,225, 14, 20, - 10, 5,237, 21, 20,180,252,217, 37, 75, 36, 59, 88, 20, 18,188,228,117,233,237,197, 11,150,153, 42, 42, 14,177,200, 90,207,101, -140,189,165, 65,203,231,188,186, 88,114,224,186,169,190,176,211, 19,139,165, 87,183, 44, 89,102,172,169, 56,196,199, 11,224, 47, - 13, 92,246,242,107, 11, 36,133, 37,119, 79,139,140,123, 50, 73,186,125,211,154,101,181, 53,213,135,220,124,214,108,221, 75,124, -158, 53,194, 88,255, 18,137, 68,166, 82,169,242,152, 45,163, 90,173, 86, 61,104,208, 32, 62,178,140, 0,186, 2,160, 7, 12, 24, - 64, 75, 36, 18, 81, 70, 70, 6,102,207,158,141,149, 43, 87,130, 16,130,159,126,250, 9,223,127,255, 61,206,158, 61,139,202,202, - 74,116,235,214, 13, 85, 85, 85,254, 34,145,168,157, 51,225,147, 38, 77,178, 75,168,206,150, 6,236,185,233,239,215, 37, 0, 71, - 94, 0,119,172,127,119, 21,129, 59, 21, 21,245,175,219,189,254, 2,250,188,158,140,145, 86,117,174,140,159,131, 78, 63,156, 64, -225,130,231,241, 83,104, 40, 0, 96, 24, 64, 13,176, 49,215,165,167,167,147, 78,157, 90,224,228,169,159, 17,249, 80, 47, 32,237, - 13,188,186,101, 55,102,117, 57,131,254,117, 5, 88,120, 83,140,255,124,190, 20, 43,223,221,128,179,191, 30, 65,122,122, 58,121, -229, 21,251, 94, 95,182,188, 86,173,253, 49,126,194, 80,140,159, 48, 20,111,209,233,208,215, 45,198,169, 83,192,169, 83,192,225, -195, 19,241,225,186, 75,120,226,137,139, 36, 44,236, 65,164,165,249,243,226,167,220,135,223,192, 34,172,112,120,195, 29, 58, 52, -252,127, 70, 1, 32,137,137,137, 50,214,154,161,181, 18, 64,177,173, 13,139, 75,222, 37,205,139, 33,253,157, 59,119, 82,170, 77, - 67, 0,177, 24,212,206,157,247,244, 98,153,168,127,149, 74, 69, 37, 38, 38, 18,103,222, 16,235,216, 0, 62,132,110, 11,142,234, -206, 92,162, 65,104,123, 17,158,140, 19, 67, 87, 7,180, 12,164, 32,162, 44, 86, 63, 8,116,181,128, 70, 79,160,209, 18,104,116, - 4, 52, 1, 68, 14, 98,174,103,206,211,160,111,255, 34,132,244,188,141,111, 14,148,225,246,109, 29, 6, 12,171, 66,191, 86, 53, -128, 79, 29,116,181, 52,202,174, 19,104, 52, 20,140, 70, 10,173,218, 80, 0,117,207, 99,217, 34, 7,246,239, 63, 40, 56, 44, 12, - 71,239,242, 53,164, 79,206,192,237,148,249, 81, 0,122, 3,184,192, 67,161,232, 53,120,196,163,131, 90,135,134,225,196,207,245, - 49,114,104, 43,251, 23,174,126,188,184,145, 60, 39, 94,128,222, 3,251, 15, 24, 20, 26,218, 9, 23, 78,222,245,136,140,120, 44, - 22, 95, 42, 87,243,110, 91, 83, 42,180,204,243,107, 29,191, 17, 23, 23,215, 40,254,200, 70, 44, 0, 51,232, 93, 1,156, 94,180, -104,209,112,111,111,111,233,167,159,126,138,173, 91,183,226,217,103,159,197,170, 85,171, 64, 81, 20,254,248,227, 15,104,181, 90, -164,164,164,192,104, 52,226,133, 23, 94,160, 41,138,114,250, 0,120, 50,154,254,126, 95, 2,112,228, 5,240,132,245,239, 42, 50, - 50, 50,240, 76,210,227,168,172,168, 3,222,221, 8,205,225, 19, 8, 24, 57,168,254,243,178,119, 55,226,188,175, 47,168,151,158, - 67,159,233,227,113,108,219, 1,135,242, 46, 95, 62,135, 97, 35,228, 56,119, 62, 24, 27,215,171, 48,114,228,112,252,231,163,165, -120,107,244, 83,248, 12, 64,207,167,103, 99,227,122, 21,196,226, 96, 36, 76, 26,132, 79,121,200,251,239,251, 95, 97,240,196,190, -120,167,239,106,156,139,149, 34, 56,110, 87,131,186,109,252, 37,248, 57, 79,141,176,103,102,241,238,135, 35, 71,188,145,150,230, -231,176,142,171,246,207,223,210, 3, 96, 99, 29,153,114, 80,143,187,137, 51,200, 28,161, 62,109, 90, 71, 2, 92,134,234,131, 43, -128, 95,247,122, 79, 0,163, 20,112, 89, 6,240, 20, 24,107, 62, 49, 49,145,176,173,127,198, 35,192,126,159,152,152, 8, 86,178, - 28,194,151,208,173,193,218, 5, 96, 83,158,209, 4,104,106, 9,234,244,230, 96,191, 58, 61,129,183,239,221,207,116,181,128,214, - 64, 80,126,155,224,175, 59, 4, 39, 47, 24, 65,211, 64, 98, 98,162,236,242,229,203,141,198,198,104, 4, 74,174,233,113,173,240, - 14,142, 28,187, 3, 66, 40, 92,248,141,198,196, 39,141, 16,123, 19,252,117, 19, 56,114, 8,168,170, 34, 32, 52,240,240, 40, 10, - 18, 9, 32,151, 39,224,234,213,171,156,174, 73, 62, 12,228,192, 49,215, 39, 73,145,180,197,146,231, 87,165,250,100, 17, 81,131, - 14,105,227,235, 11,159,151,230,249,252,177, 46,125,169,190,170,106, 6, 87,121, 94,126,210,165,201,203, 86,249, 28, 42, 33, 13, -228,181, 14,240, 69,159,233, 47,250, 92,248,234,131,165,122, 77,205, 12, 46, 30, 0,137, 95,192,210,197,203, 87,248, 92, 41,173, -108, 32,171, 69, 96, 0, 38, 63,249,172, 79,214, 23,159, 44,213,104, 52, 51,154,249,241,165,246,238,221,219,168,236,205, 55,223, - 36,123,247,238, 69,118,118, 54,231,161, 0,112, 14,192,233, 53,107,214,244, 15, 10, 10,146, 50,110,240, 79, 62,249, 4,179,103, -207,198,214,173, 91,235, 45,245, 53,107,214,160,162,162, 2, 85, 85, 85, 53,181,181,181, 69, 22, 15,130,216,209, 15,208, 52, 77, -172, 93,244,140,245,207,213,253,207,184,233,217,114,172,221,245,247,195, 18,128, 45, 47,128,167,173,127, 70, 38,215, 37,128, 11, -195,134,129,122,126, 58,130, 0,144, 81, 81,168, 61,121, 14,154,119, 55,222,237,183,164,199,209,237,233,199, 33,145,152,175,255, -252,121,199, 91,179,153,207,229, 19,204, 74, 68,254,137,179,248,236,255,182,195,127,232, 16,212, 26,140,208, 67,143, 71, 30, 29, -216,168, 62, 23,121,215, 76,122, 60,217,254, 69,208, 39,235,144,248,222, 40,136,167, 29, 71,239,200,222,136,236,211,181,190,125, - 41, 11,215, 33, 45,237,223,156,239,155,130,170,130,209, 23,112,225,155,248, 22, 92, 60, 6,174, 37, 2,250, 91, 42, 0,249,249, -249, 78,163,191, 45,159,115, 19,232, 27, 0, 85,231, 31,128,143,194, 9,194, 3,128, 46,117,160,122,100, 83,248, 32,170,126,237, -223,157,101, 0,235,173,128,246,182, 6, 58,112,187,214,147,191,117, 0, 32,227, 82,103,202,156,120, 0, 40,107, 75,204,221,201, -252,225, 71,227, 99,174,223, 56,160,166,219,210, 16,121, 3, 62,150,121,209, 64, 19, 24,141, 64,117, 53,129,222, 0, 24, 13,102, -165, 32, 97,146,217,123, 99,199,101, 79, 69, 15,139,143,169,187,181, 95, 29, 25, 73,227,240,247, 38, 80, 34,224,175, 82, 10, 18, - 63,224,251,131,128, 94, 75,129, 34, 64,191,135,124, 80, 82, 76,227,209, 71, 99,145,149,149,197,233, 88,107,249, 48,144,180, 23, -205,215,239,170, 18, 64,104,211, 56, 83,235, 54,162, 3,244, 93, 22,106, 15, 32,132, 2,180, 81, 81,222, 87,140,166,113,188,228, - 17,122, 28, 2, 91,137,212,165,166,122,121,109, 37, 64, 27, 9, 5,255,190, 81,222,231,183,211,227,172, 60, 6,196,145,172,128, -192, 32,209,213,155, 21, 22, 98, 1, 2,253,124, 17,232, 47,198, 67, 3, 6,122,239,254,140,140,107,230, 71,215,102,159, 51, 81, -255,236, 58,140,247,110,234,212,169,178,204,204, 76,123,242,106, 0, 92, 57,117,234, 84,205,200,145, 35,219,130,181,167,255,147, - 79, 62,169, 39, 68,131,193, 0,147,201,132,203,151, 47,163,109,219,182,183,104,154,230,164, 45, 78,154, 52,201,158,165,238,146, -155,254,126, 94, 2,176,229, 5,240,164,245,207,135,248, 25,116, 8, 13,194,199, 31,127,135,248,184, 97,104, 31, 21, 9, 68, 69, -130,122,126,122, 67,165, 23,192,205, 82, 45,246,100, 31, 67,135,208, 32,238,242, 66,252, 16, 53,168, 27,162, 6,117,107, 84,143, -175,188, 71,166,244,194,235,143,126, 0,250,156,153,252,231, 44,156,233,146, 60,107, 44, 9, 92,242,205,202,234,149, 99,154,242, -129,116, 75, 1,176,236,217,191,167, 17,216,140,149,171, 82,169, 24,139,151,178, 81,135, 48,228,207,178,138,121,129,189, 11,128, - 41,227,107,249, 91, 7, 0, 90, 80, 95, 54,127,254,124,181,101, 57,131,147, 60, 54,249,219,138, 9,224, 43,207, 25,210, 50,117, -112, 38, 47, 43, 43, 43,175,117, 16,133,199,162,125, 64, 3, 48,232,105,248,138,205,221, 84,173, 33,168, 51, 16, 24, 77, 64,254, - 57, 19, 76, 52,129,179, 45,123, 89, 89, 89,121,237,219, 82,120, 52,198, 11,147,159,242, 66, 77, 53, 65,117, 37,160,169,166, 16, -222,141,192,100,160,224, 45,146,160,226, 54,141,146, 63,245,184,252, 27,183,128, 49,249, 48,144,244,121, 64,247, 48, 96,221,107, -192,220,247, 93, 83, 2, 72,173,102,202, 75, 81, 3,247,135,100,237,151, 6,143,120, 24,237, 1,180,167, 0,211,209, 35,200,157, - 57,163,198, 80,171,153,204, 71, 30,173,171,157,252,252,232, 65, 7,122,189,245,181,180, 93,191,225,104,227, 75,161,173,132,130, -246,226,143,216,243,198,172, 26,131,182,150,179,188, 58,157,118,242,132,199, 70, 30,152,255,238,122,105,239,254, 81, 8,244, 23, - 35,208,207, 23,133, 23, 78, 99,121,202,203, 53, 90, 30,178, 92, 37,115,103,151,107,139,252, 87,172, 88,209,200,205,191,115,231, - 78, 38, 79, 64,158, 29,235, 31, 48,199, 88,156,238,209,163, 71,161, 78,167,235,232,229,229, 37,241,247, 55,111,197,202,204,204, -196,212,169, 83,161,213,106,161,211,233, 80, 87, 87, 7,169, 84,170, 51,153, 76, 89,132,144, 82,142,214,181, 71,230,182,191,203, - 18, 0,219, 11,192,188,110, 14,226,103, 16, 30, 30,130, 37,175, 39,225,224,129,159,240,245,238,147,240, 21,183,192,159, 37,119, - 87,176, 58,133,246, 70,157,190, 10, 15, 69,245,196,218,244, 36,172,124,119, 3, 47,121,237,218,181,196,249, 11,231,235, 63,143, -236, 29,137,178,178, 74, 94,242, 98,231, 77,198, 84,209, 12,212,157,171, 65,244,220, 62,160,251, 73,240,241,199, 59,234,219, 87, - 89, 89,137,225, 15,247,226, 36,207, 26, 42, 74, 69,169,160, 66, 83,194,101, 5,160, 41,200,159,139, 76, 11,225, 19,203,107, 0, - 32,236,109,137,249,249,249, 13, 8,223,150,130,208,216, 15, 75, 1, 98, 17,224,231, 5, 72,189,129,186,106,168, 86,250, 0,233, -115, 8,252, 90, 1,126,173,120,175,253,219, 33,127,216, 32,107, 78, 15,134, 53,249, 91,199, 4,240,149,199,131,252,157,202, 43, -175, 32,212,190, 60, 3,145, 72, 0,154, 6,250,246,240,186, 59, 30,191,154, 96, 48, 17,152,104, 47, 76,153, 50,133,147,114,114, -243, 47, 66, 29, 56,104, 34, 70, 35,160, 55, 16,152,140,128,136, 2, 98, 98,129,234, 10, 10,191,157,209, 66,171, 19, 33, 62,110, - 10,118,237,218,197,137,252, 87,204, 1,186,118, 50,191,239,210, 17,112,213, 19,160, 84, 42,143, 43, 20, 10,121,105,194,132, 3, - 97,123,246, 75,195, 70, 60, 12,195,209, 35,216, 21, 55,161, 70, 95, 93, 45, 7,112,132,103, 87, 31, 49,105,171,229, 23,223,156, -116, 32,244,189, 44,105,199,193, 35,160,185,120, 20,159,191,148, 80, 83, 87,203, 91,222, 17,157,182, 86,190,230,245,127, 31,248, -207,127,183, 72,163,135, 13, 71,193,249,211,120, 57,105, 70, 77,109, 77,141, 43,109,107, 82, 56, 72,246, 67, 98, 99, 99,185,236, - 6,240, 10, 10, 10, 58,173,213,106, 63, 43, 42, 42,234,220,191,127,255, 8,163,209,232,237,227,227,131,172,172, 44,140, 25, 51, - 6, 58,157, 14,181,181,181,184,124,249,114, 85,112,112,240,119, 90,173,246, 83,154,166, 53,224,152, 1,144, 29,144,192,215,245, -255,119, 91, 2, 96,123, 1, 60, 33,199,149,220, 1,182, 48, 94, 62, 20,227,229, 67, 45,239,220,215, 97, 27,202,155,228,158,114, - 23,180, 19,117,103,106, 48,115,125, 44,254,243,221, 82,183,219,150,174, 79, 39,193,198, 96,204,244,159,121, 79, 12,107,151, 20, -128,230,176,252,109, 88, 31,196,170, 61,158,178, 82,236,122, 4,184,122, 0, 60, 77,254,140,178, 99,229,222, 39,236, 50,190,242, -156,197, 2,240,149,167,209, 17, 74,163, 3, 17,137,128, 35,249,230,181,126, 38,224,207,188,238, 63,133,151,188,234,106, 66, 81, -150,101,118, 74,100,150,241,243, 15,128,166,134, 6,161,129,248,248, 88,236,218,181,203,233,120,200,135,129,164,204, 0,130,164, - 64,201, 45,192,207, 23,160, 9, 16, 32, 1,222, 85,184,166, 4, 0, 56, 66, 87, 87,203,243,227, 39, 28,104,185,226,109,105,222, -138,229, 53,117,174,145,127, 3, 37, 32,111, 81,194, 1,191,151,222,148,230,124,248,150, 43,228, 95, 47,203,104,208, 79, 88,254, -202,243,251,231,206, 79,145,174, 95,155, 90, 83, 91, 83, 35, 87, 42,149,103,216,238, 97,165, 82,233,173, 80, 40,140,124, 29, 32, -158,244, 10,216, 34,127,138,162, 72,108,108, 44, 0, 96,226,196,137,132,162, 40, 71,138,128, 84,175,215,215,136, 68,162,220,208, -208,208, 78,213,213,213, 47,158, 56,113,162,195,192,129, 3,105,163,209, 88, 91, 89, 89,121,243,204,153, 51,127,132,135,135, 23, -182,110,221,186, 72,171,213,102, 26,141,198,155, 73, 73, 73,154, 1, 3, 6,112, 82, 0,152,164, 64,238, 64,169, 84,114, 38, 84, - 87,150, 0,220,249,190, 61, 47,128, 39,230, 76,119,229,232,180, 94, 30,173,239,105,121, 21,119, 68, 72, 53, 42, 16,113, 44, 4, -211, 63,114,174,152, 84,220,113,126,203,221, 75,242,183,171, 0,112,216,235,207,171,129, 60,114, 7,240,145, 75,177,162,252, 93, - 38, 47, 42, 31,212,180,240,241, 4,151, 0, 52,202,215, 80,105,249,227,183,199,220,114,189,106, 79,145,171, 85,191, 16, 38,207, -128, 37, 64,144, 98,121, 67, 92,146,247,249,130, 0,182, 82,224,138,188,122,185, 83,167,222, 29, 19, 38,224, 79,165, 82,229,185, - 34,143,208, 13,199,184,166, 10,136,141,141,197,190,125,251, 40,198,170,226, 52, 30,159,121,238,129, 97,229,227, 63, 98,168,174, -150,127,191,226,205,140,186,234,234,153, 30,176,174,143,232,107,171,229,135,214,191,149,161,171,173,158,165, 84, 42,143,186, 58, -153, 27,141,198,195, 70, 99,141,124,125,122, 90, 70, 77, 77,205, 76, 0, 71,172,101,185, 64,254,158, 64,131, 25,213,154,252,153, -184, 29,118,144, 96, 92, 92,156, 35,121,197,122,189,222,151, 16, 82, 77,211,180, 82,175,215,255, 20, 22, 22,214,166,162,162,130, - 90,182,108, 89, 85,101,101,101,121,199,142, 29,171,107,106,106, 52,122,189,190,202, 96, 48,212, 61,247,220,115, 90,158, 22, 54, -229,129,123, 38,175,169, 58,180, 41,101, 55, 55,222,127,255, 35, 10, 0,121,252,137, 49,136,236, 19,110,183,222,249,115, 87,240, -213,246,111,152,250,247, 76,222,250,245,235,235,229, 57, 52,152, 79, 20,225,171,237,223, 48,245, 29,226, 94,146,191, 61, 5,192, -211, 13,104,178, 11,178,144, 40,101,203, 90,230, 3, 15, 71,245,115,201, 22,232,214, 15,240, 57,244,199, 19,222, 0, 23,198,196, -238,123,119,229,237,219,183,143,215, 88,185, 19,241,207,133,180,117,213, 85, 93, 60, 41, 79, 91, 83,221,197, 67,150,220,145,154, -234,234, 46,247,217,179, 76, 1,192,166, 77,155,136, 72, 36, 2,243,199,118, 97,203,229,114,208, 52, 13,154,166,145,148,148, 68, - 57,217, 21, 64, 25,141, 70,127, 66,136,137,166,233, 58,131,193,240,131,151,151, 23, 37, 18,137,124, 1,248,210, 52, 13,147,201, -228,101, 52, 26,197, 70,163,177,195,115,207, 61,119,145,245,221, 38, 63, 4, 72,128,103,148,128, 33, 67, 70,146,131,251,119,163, -184,172, 10, 33,193,181,245,159,149,222,241, 71, 88,187, 22,232,217,179,167, 83,178,110, 42,121,235,215,175,167, 30,121,228, 17, -178, 46,125, 31, 10,254,188,213, 72, 94,215, 78,109, 16, 17, 17,193,137,252,155, 10,142,114,164, 80,174,158, 35, 44, 64,128, 0, - 1,247, 1,106, 89,132, 78,179, 12, 27,111, 86,249, 13, 0, 45, 97, 14, 26, 23,136, 95,128, 0, 7, 30, 0, 1, 2, 4, 8,248, -187, 64, 98, 81, 2,104, 22,241,139,112,247,228, 65,111, 0, 29, 44,175,105,161,187, 4, 8, 16, 20, 0, 1, 2, 4,252, 51, 32, - 2, 32,101,189,103,136, 95,204, 34,125,218, 82, 79,176,254, 5, 8, 16, 20, 0, 1, 2, 4,252,143,204,105, 2,233, 11, 16,224, - 64,123, 22, 32, 64,128, 0, 1, 2, 4,252, 47,107,203,167, 79,159,102, 31,164, 67,172,146,232, 16, 52, 60,104,167, 88,165, 82, -133, 49,239,109, 5, 19,178,229,241,197, 63, 81,158,141,109,139,148,208,127,194,120,252, 93,228,133,133,133,213,215, 41, 46, 46, -166,248,202, 75, 78, 78,134, 66,161,160,132,251,207, 53,153,194,243, 43,200,227, 35,143,183, 2,192, 19,109, 57,214, 35,137,137, -137,188, 51, 75,217, 59, 47, 30,141,147,145,216, 58, 13,208, 86,157,123, 14,134, 96, 44,123,225,213, 42,149,170, 62, 91, 23,223, -124,226, 77,133,184,184,184,152,236,236,236,122, 18,140,141,141,149,237,219,183, 47,239,159,168,237,218, 26,143,139, 23,205, 59, -195,122,245,234,213,220,205, 35, 9,147, 20,200,250, 90,105,243,158, 77,152,164, 32,150,207,236,222, 56, 9,147, 28,158, 20,136, -172,175,149, 46,223,116, 97, 97, 97, 36, 46,238,238,174,194,236,108, 16,103, 74,128, 51,172, 94,179, 58,102,207,161, 61,136,136, -140, 80,131, 2, 46,158,186, 32, 27, 54, 96, 56,210,223, 79,231,117,255,205,156, 57,179,209,117,103,100,100, 80, 16, 32, 64, 64, -147, 41, 0, 98,174, 21,163,163,163,121, 11,119,160, 0,216, 36, 81,235,131, 54,120, 16,173, 43,154, 19,151,201,133,168, 84, 42, -164,164,164, 32, 53, 53, 85,237, 32, 77, 39,151,223,111, 80,167, 99,248, 3, 0,128,155, 58, 29,140,218, 58,115, 97, 69, 21, 67, -114,220,210, 31,215, 79,228,217, 13,114, 10, 88,114,139,243, 58,227, 93, 68,153,179,235, 49,255, 1,167,175,155, 99,114,110, 48, - 30, 12,241,187, 49, 30,158,188, 6,146, 48, 73,129, 9,242,135,116,128, 66, 98, 33,122,151,126,131,165, 64,120, 28,122,125, 10, -114,114,146, 48,110,220, 38,196,197,165, 34, 59,219,220, 87,174, 40, 2, 79,191,252, 52,169,104,117, 27,107,149,171, 17,236, 31, - 12,218,104,130,142,212,169, 15,254,116,104,220,116,211,227,100,120,196, 8,217,188,121,243,156, 42, 2, 51,103,206, 36,201,201, -201, 54,251, 84, 80, 2, 4,220, 11,196,199,199,215,207, 25,115,230,204,193,150, 45, 91, 26,112,207,236,217,179, 27, 28, 78,229, - 44,185,148, 51,121, 92,143,170, 62,125,250,180,181,151,192,163, 10, 0,175,248, 1, 91,167,216,121, 2, 27,149,202,152, 23,220, - 76,154,194, 39,135, 54, 71,203,157,164,164,164, 96,213,170, 85, 0, 80,255,223,246, 79, 19,126,222,128,160, 22, 56, 91,180, 29, -126,232, 4, 19,126, 68,217,230,147, 56, 83, 88,142, 41,171,182, 54,219, 3,112,246,215,115,232,215,183, 15,104, 2,156, 59,103, -126, 13,220,125,205, 46,167, 9,231, 49, 33, 28,199,131,226, 58, 30,179,102,205, 2,128,250,255, 54,137,157,162, 0,199, 63, 77, - 30,123,236, 0,190,253, 86,238, 81, 37, 96,130,252,161,218,164,164, 36,127, 96, 19,178,190,118,141,216,221,177,240,157, 89,255, - 0, 48,117,106, 38,114,114,204,255,147,146, 10,193,120, 4,248,120, 3, 54,110,220, 24,163,254,253, 59,245,243,201,179, 49,168, -237, 64,248,181,108, 9,162, 55,130, 38, 38,120,121,139,209,117,116,215,156,223,162,126,199,170, 77,169,234,181,107,215,202, 94, -125,245, 85,167, 74,192,173, 91,183, 26,188,143, 29, 25,128,161,243,126,132, 78, 55,189,193, 64,238,216,177,195,229,254,145,203, -229,228,192,129, 3, 30,235, 95, 79,203,107, 74, 36, 39, 39,199,184,155,214, 55, 57, 57, 57, 6,112, 61, 61,176, 82,169,236,247, -218,107,175,221,208,104, 52, 97, 0,198,194,124, 8,103, 47, 0,167, 97, 62, 20, 10, 0, 62, 7,240,219,189,238, 31,246, 89, 15, -115,230,204, 65,118,118,118, 3, 78,153, 61,123, 54,248,100, 46,117, 38,175,254,121,207,202, 34, 9, 9, 9, 20, 23,242,103,202, -172,149,128, 6, 10, 64, 74, 74, 10, 41, 42, 42, 2, 0, 68, 68, 68,128,125,216,140, 74,165,106,240,222,250,115, 71, 22,123, 89, - 89,153, 90,165, 82,113,246, 4, 88,159,117,239,136,132, 95,176,164,194,180,230, 1,190, 46,246, 77,155, 54, 57,173,147,155,155, -203,137,187, 18, 19, 19,237,146,254,226,197,139,145,154,154, 10,182,130,192, 5, 29,195, 31,192,245, 59,149,216,245,194, 84,180, -166, 70,160,240,227, 5,136,152, 28,129,111,154,153,252, 1,212, 19, 62, 0,244,233,211,167, 65, 57,227, 25, 96,151,123,218,178, -119, 66,196, 36, 49, 49,209, 46,233,111,219,182, 13,169,169,169,144,143, 24,136, 3, 63,158, 2, 2, 3,128,170,154,123,222,135, -251, 15,156,244, 7, 54, 97,255,129,147, 30,145,119,243,189,214, 14,181,152,246, 11,203, 57, 61, 32,108,215,127, 82, 82, 14,226, -226,186,212,255,103, 16, 23,215,133,179, 18,240,241,151, 31, 99,229, 71,239, 96,100,183, 24,152,234,234, 96, 52, 25, 65,121, 83, - 0,188, 64, 64,227,230, 95, 37,232,213,182, 39,150,190,176, 20,239,164,189,195,201, 27,101, 61,217,197,134,110,179, 73,248,211, -167, 79, 39,174, 40, 1,114,185,156,236, 95,118, 0, 19,224, 25,210,150,203,229, 36, 45, 45, 13, 0,238,107, 37, 32, 57, 57, 57, -166,178,178,146,241,150,185,213,206,202,202, 74,102, 78,119, 73,142, 66,161, 40, 2, 48, 11,192, 41, 0,159, 2, 24, 3, 96, 60, -128,127,179, 20,128, 91,205,209, 79,236,227,158, 1,224,235,175, 27,107,240, 95,127,253, 53, 8, 33,152, 52,105, 18,197, 87,222, -198,141, 27, 71, 89,230, 57, 2,128, 10, 9, 9,177, 75,252,214, 72, 74, 49,115,204,166,212,197, 54, 63,111,160, 0,164,166,166, - 58, 12, 2,100,191,183,254,220, 81, 16, 2,163, 84,204,159, 63, 95,157,146,146, 2,235,131,114,172, 15,207, 81,169, 84,142,210, - 23, 82, 28,202,154,245,161,250,234,171,175,236, 18,191, 69,209,170, 39,255,197,139, 23,115,146,249,103, 81, 49, 52,187,151, 67, - 58,251,191,232, 24,254, 0,218,183,246, 67,209,238, 34, 51,249, 7,181, 48, 47, 1,248,120,241,110,107, 92, 92,156,140,189, 12, - 96,121,207, 75, 6, 77,128,176, 0,224,195, 25,192,115,219,128,182,254,192,197, 10,219,229,231,239,240,107,159, 61, 69,142,143, -215,230,237,183,223,182, 75,252, 0,144, 54,107, 34,214, 29, 60,142,144,136, 14, 40,189,122,211,169,245, 15, 0, 28,189, 0,156, -189, 4,102, 11, 95, 97,211,210,231,178,254,111, 11,105, 95,120, 54,201, 39, 67,250,204,127,125, 92, 87,136,179, 11, 56,127,191, - 86, 91,139, 17,211,135,171,163, 59, 12, 69,157, 70, 3,111, 95, 95,120,123,223,157,130,138, 10, 10,176, 39, 43,235,250,236,103, -103,117,236,236, 27,134,129,143, 14, 24, 45,213, 5,198,124,242,241, 39,188,172,198,119,247,207,194,247,223,127, 15,160, 97,219, -118,236,216, 65,241, 85, 2, 24,242, 71,231,181,216,191,236, 85,183,149, 0,185, 92, 78,210,211,211,209,189,123,119,172, 91,183, - 14,115,231,206,189,239,148, 0, 43,226,247,136, 60, 70,150, 27,222, 4, 25,128, 71, 1,108, 3, 80, 3, 32, 4,192,239, 0,174, -226,110,238,135,102,129,245,113,207,108,183,189,181, 11, 63, 33, 33,129, 56,115,225,239,223,191,191,193,146,241,158, 61,123,212, -108,171,159,171, 66,204,144, 63,243,122, 83,234,226, 70, 94,128,123,146, 7,128,181,246,138,162,162, 34,180,107,215,174,145,130, -192,148,149,149,149,113,205,115,239, 44, 24,144,243,132,249,248,227,143, 55,217,181,179, 9,204,150,213,111, 33, 33, 91,109,111, - 0, 45,138, 81, 51,121, 40, 72,224, 2, 96,244, 50,212,224, 75, 96,243, 73,139,102,182, 0, 62,207,172,131,209,200, 63,209, 89, -118,118,118, 30,187,159,248,146, 63, 0,148,125, 2,188,181, 17,120,160, 19,112,115,175, 24, 25, 91,244,152,181,221,126, 57, 47, -243,158,120,150,196,216,193,126, 55,190, 94,133,192, 72, 9,164,221, 94,193, 87,171,158, 67,255, 62, 33,232, 49,241, 29, 78,227, -193,165,233, 60,150, 10, 40, 0,196,138,252, 41,134,248, 93, 89,215,231,106,225,115,129, 62,174,171,205,242, 28, 43, 79,128, 51, -220, 40,187,129,177,137, 99, 17,216, 34, 24, 38,202,136,195,223,255,128,234,154, 26,196,197,199,227,175,178, 50,236,204,220,133, - 57,207,206,234,232, 43,241,133,136,248, 96,220, 67,227,114,127, 87,175,115, 73,161,191,115,231,142,219,215,205, 38,127, 0,110, - 43, 1,114,185,156,172, 88,177, 2, 93,187,154,251,179, 75,151, 46,184,159, 60, 1,158, 38,126, 27,214, 63,243,218,149,107,237, -109,121, 38,125, 0,248, 3,136, 4,112, 1, 64, 71, 0, 85, 0, 42, 60,240,204,186, 4,235,227,158,231,204,153, 83, 95,198,184, -240,153,185,140,139,103,218,222,114, 1,155,252,185, 40, 2, 92,112,207, 87,242, 20, 7, 0, 0, 9,178, 73, 68, 65, 84, 18, 1, -181,107,215, 78,150,152,152,216,104, 41,192,114,182, 61, 0,240,142, 17,176, 23, 12,232,200,114,180,167,160, 52, 5, 24,235,222, -158,187,159,171,245, 15, 0, 7,151,172, 64,220,202,247, 97, 28, 61, 2,222, 0,164,199, 10,240, 77, 97, 57, 0,192, 56,122, 46, - 12,191,182, 1,213,246,223,188, 73,138,135,151,197, 46,202, 39,125,137,185,207, 94,195,165, 23, 22, 65,243,173, 30, 33,109, 28, -151,123,194, 3,224,138,114,176,109,219, 54,179, 54, 28,247, 8,142,151,148, 33,176,127, 32,174,231, 20, 2, 18, 95, 76,157,251, - 12, 90,117,154,216,156,243,175,189,168,127,143,120,181, 28,237, 16,112, 22, 59,144,147,148,131,113,155,198, 97,106, 38,144,148, - 99,126,157,147,148,195,219, 11, 80,163,171, 70, 27,191,214, 48,234,106, 65, 68, 4,131,135, 12,193,238,221,187,117,233,239,191, - 47,161, 9,193, 83, 51,158, 66,171,214,173, 80, 91, 83, 3,163,201,136, 64,159, 22, 48,136, 12, 46, 93,111, 69, 69, 69,131,221, - 1,124, 3, 2, 27,145, 63, 3, 23,149, 0,185, 92, 78, 82, 82, 82, 48,100,200,144, 6,229,125,250,244,193,187,239,190,219,172, - 74, 64, 83, 17,191,181,245, 15, 0, 37, 37, 37,174,122, 1,126,130,121,189,191, 10,102,215,255, 88, 0,151, 1,244, 3,144, 5, - 96, 43, 0,135, 55,139, 82,169, 20, 41, 20, 10,143,167,131,102,187,236, 89,129,122,245,159,179,151, 4, 74, 75, 75, 99,156, 29, -244, 69, 8,161, 24,130,103,187,250, 19, 18, 18,108,150,123, 82, 1, 32, 86,164, 72,120,126,238, 16, 17, 17, 17,245,164, 31, 29, - 29, 45, 99, 98, 3, 24,239, 64, 68, 68,132,154, 89, 46,104,174,137,215,147,112,182,214,207,178,254,157, 98,202,198, 76,144,248, -112,220, 28,246, 16, 90, 99, 4,252,166,174,131,241,198, 95, 64, 80, 11,120,151,127,137,189,233,249,128,151,151, 43,215,238,182, - 38,121,230,181,127, 97,208, 0, 32, 98,238, 57, 68, 74,159,197,239, 15, 38, 2, 31, 46,178, 91,222, 92, 30,128,212,212, 84,140, - 28,220, 3,163, 71,116, 71, 92,223, 69, 88,147,190, 1, 23,242,175,227,133, 81,131, 80,154,181, 31,149,119,170, 60,117, 63,216, - 90, 42,112, 74,208,108,194,247, 36,249,219,145,201, 9,197,197,197, 84, 88, 88, 24,153,154,217, 80, 33, 0,128,113,155,198, 65, -156, 93,128,236,236,194,250,157, 0,236, 92, 1,182,110, 55,154,166, 97,162, 1, 66, 27,225,235, 39,193,140,167,159,150,188,245, -230,155,104,223,190, 61,221, 49, 36, 68,164,211,212,192, 68, 0, 66,155, 64,211,206,231,234,140,140, 12,106,204,152, 49,164,188, -188, 28, 85, 85, 85, 13, 20, 71,171,221, 1,156,119, 5,200,229,114,178,230,185,243,128,164, 43, 80,250, 81,227, 10,146,174, 88, -243,220,121,128,163, 18, 32,151,203, 73, 66, 66,130,172, 79,159, 62,234,242,242,242, 70,159,135,133,133, 33, 33, 33, 65,134,251, - 60, 38,192, 93,235,223, 77, 47, 0, 91, 97,232, 0,224, 12,128,201, 0, 56, 31,101,218, 20,228, 15, 56, 94, 2,176, 97,204,228, - 57,187,246,248,248,120,194,124, 63, 62, 62,158, 88,203,219,178,101, 11,226,227,227, 9,223, 93, 1, 92, 20, 0, 62,137,128,108, -125,110, 19,137,137,137, 54,189, 0, 12,217,183,107,215, 78,150,146,146,162,102,214,100, 19, 19, 19, 29, 6, 21, 58,178, 14, 93, -216, 95,223, 36,219, 0, 25,235,222, 81, 48, 32, 31, 20,190,151, 4,159,169,235,160, 45,185, 4,239, 99,235, 96,200,156, 11,106, -194,106,236,249,247, 52, 92,221,115, 5,113,105,159, 2,222,205,147,217,121,145, 10,200, 73,219,141,200,171,227,128, 91, 26, 44, - 28,179,200, 97,185, 39, 60, 0,174, 90,255, 89,187, 87,192,171, 99,111, 72,209, 29,197,223,111, 66, 53, 69,240,243,165,107, 24, -125,238, 58,167,230,124,251,173,220, 46,217, 3,128,229,115,155,245,184,146,191,157,123,212, 45, 98,240,196, 14,129,164,156,187, -196, 15,160,145,229,207, 4, 12,102,103, 23,218,252,126,160, 95, 32, 74, 42, 75, 48,164,243, 80,104,235,116,128, 86, 7,163,222, -128,165, 41, 41,160, 68, 16,213,106,106, 64,211, 38, 24, 77, 4,190,222, 62,248,171,230, 47,248,152,156,239, 54,254,230,155,111, -234,175,109,230,204,153,132,153,111,216,187, 3,110,220,184,193,249, 58,205, 36,108, 86, 2,122,133, 55,254,253,139, 87,244,152, -191, 57, 18, 92,201,218, 82,143, 12, 25, 50, 4, 97, 97, 97,141, 62, 63,119,238, 28,178,178,178,212,205, 69,254, 22,107,156, 98, - 60, 1, 37, 37, 37, 77, 98,253,123,192, 11,192, 96,172,133, 72,235,238, 7, 37,199,209, 18, 0,187,156,239, 18,128,167,150, 20, -248, 40, 0, 77, 2,198,242, 7,128,232,232,104,153, 74,165, 82, 51,174,127, 59,202,129,236,242,229,203,206, 98, 1, 40,142,101, - 30,181, 50,185,118, 56, 99,253,219, 34,126, 70,209,225,211,222, 51,133,229, 48,252,250, 22,110,226, 71,132, 76, 88, 13, 84, 86, -161,112,211, 2,116, 73, 94,139,210,173, 11, 0, 31,111, 64,212, 60,153,157,139, 53, 64,175,118,147, 57,151, 55,135, 7, 32, 53, - 53,181,102,250,232,161, 55, 90,210,193, 15,212,194, 71,146,185,118, 46,214,239, 61,141,133,227, 31,198,172,247,191,192,180,255, -247,127, 77,234, 13,114,116,137, 89, 95, 43, 97, 73, 2, 68,185,171,156,186,227,234,119,228, 5, 72,202,201, 33,182,200,159,109, -253, 59, 67,104,187, 80, 28, 60,156,131,225, 15, 12,135,127,128, 20, 52, 77, 32, 34, 70,208, 20, 5, 66, 8, 76, 4, 48,210, 4, - 70,163, 17,218, 74, 13,246,253,178, 15, 98,147,152,247,214, 97,235, 93, 1,175,207, 29,129,216,208, 34, 80,135,184,203,176,167, - 4,240, 37,127,107, 37, 32, 45, 45, 13, 29, 58,116,184,171,216, 23, 22, 34, 53, 53, 21,247,131,229,239,105, 69,192,150,245,239, -166, 23, 0, 0, 98, 0, 60, 8,224, 13, 52,115,240, 31, 3,165, 82,217,224, 30, 45, 45, 45,133, 82,169,116,228,137,112, 42,143, -189,164, 80, 90, 90, 26,163, 84, 42, 41, 0,164,180,180,148,218,184,113, 35, 97,121,111, 41,133, 27,219,224,239,137, 2, 96, 29, -245,111, 73, 86,211, 72, 57, 96,191,118,211,130,231,125, 99,121,112, 27,160, 77,235,223, 85,226,103, 48,101,213, 86,236, 2, 48, -126,101, 44,136,106, 1,168,199,215,224, 76, 97, 57,168, 86,193, 40,248,179,202,108,253,243, 95, 2,240, 8,236,237,247,119, 39, - 15, 0, 23,133,139,171,114,176,109,219, 54, 61,128,234,231, 98,250, 85,189,178,250,191,250, 37, 75, 83,116,109, 91,180, 43, 63, -127,161,184,253,172, 11, 95, 72,209,204,187, 70, 28,144, 51,123,137,134,231,142, 2,207,195, 22,249, 51,150, 63, 0,167, 1,129, -243,230,205,163,134, 63, 54, 60, 94, 61, 34, 47, 43,177,239, 52, 84,233,170, 64,137, 0,115, 74, 17, 26, 38, 19, 1,109, 52, 34, -192, 55, 16, 71, 43, 79,225,242,177, 2,236, 84,238,204,115,187,225,133,207, 3,224,191, 13,176,129, 18,208,161, 24, 23,111,132, -185, 68,254,214, 74,192,186,117,235, 16, 20, 20,132,242,242,114,172, 88,177, 2,247,155,219,223, 19,138,128, 61,235,223, 69, 47, - 64,123,152,163,254, 69, 0, 6, 2,152, 15,160,240,126,233, 47,133,101, 43,186,167, 96,189,164,176,103,207,158,239,155,170,237, -247, 36, 15,128, 61,143,192,154, 53,107,100,214,138, 66, 98, 98,162,154,239, 69,176,137,224,126, 72,177,203,182,254,173,183,255, - 89,250,151,221,175,156, 27,204, 40, 1,147, 87,126, 2,146, 9,180,153,165, 68,222, 43,211,240,112,234,231,128,143, 15, 2, 36, -226,102,185, 94,246, 30,127, 91,175, 93,204, 3, 96, 4, 32,178,140,173,200,205,241,184, 57,125,244,208,146, 87, 54,101,135, 47, -157, 51,182, 69,104, 72,140, 30,192,217,196,196,196,150, 48, 31, 37,235,210,120, 48,183,220,183,223,202,153,136,127, 87,148, 59, -202,153, 5,207,135,208,155, 42, 25,144, 61, 88,147, 62,227, 17,104,213,170,149, 77,237,236,232,183, 71,247,132,245,124, 0,166, -233,198,179,143, 62,240,104,191,214,129,173,161, 51,232, 64, 8,129,216, 91,140, 10,109, 45,142,255,249, 45,182,125,150, 1, 89, -111,153,108, 39,118,186,221,198,119,247,207, 66, 70, 70, 6, 46, 95,230,159, 3,224,174, 18, 0,183,200,159, 45,111,238,220,185, - 36, 45, 45, 13,139, 22, 45,194,253,188,230,207, 86, 4,242,242,242, 92,250,174,163, 58, 60,100, 38,192,188,223, 95, 7,224, 53, - 0,191, 0, 48,225, 31, 10,235, 37, 0,190, 24, 48, 96, 0, 78,159, 62,141, 77,169,139, 27,229, 1,112,152, 8,168,169,242, 0, -216,242, 8,216, 35,122, 23,189, 0,110,161,169,182, 1, 50, 3,168, 84, 42,145,155,155, 75, 23, 21, 21,177,137, 76,166, 82,169, -120,107,142, 83, 86,109, 5, 88,137,127, 30, 93,186,177,254,181,166,121,238, 87,167,119, 41, 77, 92,234,187,116, 0,183, 97,222, -254, 51,195,205, 54,150, 62, 23,211,175,110, 76,238, 79, 45,158,122,243, 83, 40,149, 74,113,110,110,110, 7, 52, 76,103,237,210, -120, 52,181, 39,192, 89,126,127,167, 51,103, 19, 44, 9,216, 35,127,125, 92, 87, 32,219,185, 97,182,253,163, 29, 84,128,151,148, - 28, 11, 59,142, 17, 67, 71,160, 99, 96, 71,128, 38,248, 75, 87,142,163, 39,143,162,244,124, 41, 70,245, 26, 37,123,249,229,151, -155,125, 60,216, 74,128,167,200,154,241, 4,252, 93, 2,254,220,205, 2,232, 1,108,178,252,253, 79,192,122, 73,193, 29, 23,191, -189, 4, 64, 54, 21,128,166,194,252,249,243,109,146,189,213, 73,108,108,168, 29, 36, 2,178, 75,180,174,162, 41,182, 1,166,166, -166, 66,169, 84, 26,115,115,115,189, 45, 75, 7, 12,249,143,114,112,221, 54, 97, 57, 76, 73,221, 4, 67, 67, 28,148, 83,205,116, -243,251, 90,238,203,101,150, 34,147, 66,161,120,218, 77,177,190, 99,222,248, 56, 95,169, 84, 62,146,155,155,139,220,220, 92, 29, - 0,137,229,207, 19,196, 79,185,147, 26,216, 25,201, 39, 76, 82, 52, 24, 47,190,196,237,137, 37,129,226,226, 98, 42, 39, 41,135, -132,206, 13,149,161,179,237, 58, 37, 73, 57,106,174,241, 0, 91, 62,216, 66,173, 93,187, 54,102,235,202,173, 8,235,250,160, 26, - 0,126, 63,247,155,108,226,152, 56,164,111, 72,207,219,142,237, 46,181, 51, 35, 35,131, 26, 59,118,108,163, 93, 1, 6,131,193, -173,235,247, 52, 89,255,211,162,253,239, 3,210,164, 20, 10, 5,249, 39, 92,139, 39,150, 20, 24, 47,128,117, 25,103, 5,192,153, - 37,206,195, 82,119,245, 70, 39, 77, 44,223, 83,223,183, 41, 47, 49, 49,145,228,230,230,122,179,251,139,237, 97,225,169,160,228, - 53, 17, 33,223,143,147, 80, 32,128, 26,115, 66,126,138, 2,224, 7, 39,251,123, 57,142,199, 31,185,185,185,204, 54,160,170,136, -136,136,182,169,169,169,190,247, 67, 95, 54,165,219,222,147,178,139,139,139,169,226,133,197, 30,235, 3, 86,158,255,250,239, 29, -253,238,152,219,237, 60,116,232,144, 64,174,255,112,178,103,115,152, 66,161, 48,120,146,252,149, 74,101,144, 66,161,168,248,187, -247, 19, 23, 35,154,114,245, 28, 97, 1, 2, 4, 8, 16, 32, 64,192,223, 23, 34,161, 11, 4, 8, 16, 32, 64,128, 0, 65, 1, 16, - 32, 64,128, 0, 1, 2, 4,252, 15,224,255, 3, 40, 50, 24,122,163,191,209,130, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, +137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144, +206,103, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167, +147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0,154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,216, + 5, 19, 11, 8, 1, 11,126, 22,156, 0, 0, 32, 0, 73, 68, 65, 84,120,218,236,125,121, 92, 84,229,254,255,251, 57,179,179,239, +168,184,128,138,251,130,224, 26,106, 80,168,201,215, 52, 21, 48,179,237,214,189, 78,150,173,150,102,117,111,245,203, 43,106,218, +170,233,216,162, 89,106, 9,106,120,115, 5, 29,212,144,220, 21, 75, 19, 5, 17, 65,144,109, 96,134,217,207,156,231,247,199,204, +208,128,192, 44,160, 81,205,251,197,188,152,115,230,204,123,158,115,158,229,253,249,124,158,141, 68, 69, 69, 81,184,225,134, 27, +110,184,225,134, 27,127, 43, 48,238, 71,224,134, 27,110,184,225,134, 27,127, 31,156, 57,155, 5, 0, 32,238, 8,128, 27,110,184, +225,134, 27,110,184, 35, 0,110,184,225,134, 27,110,184,225,134,219, 0,112,195, 13, 55,220,112,195, 13, 55,220, 6,128, 27,110, +184,225,134, 27,110,184,241,151, 0,223,246, 96,222,188,121,196, 85,162,181,107,215,222, 54,150,192,205,231,230,107, 5,116,237, +218,181,127, 88,250,178,179,179,105, 92, 92, 28,113,231,199,159,151,239,220,185,115, 46, 23,190,168,168, 40,184,243,195,205,247, + 87,230,115,218, 0,248, 59, 67, 42,149, 54,122,128, 50,153,140,116,228,116,174, 91,183, 14,132, 16,226,206, 57,215,242,120,246, +236,217, 72, 79, 79,111, 56, 78, 74, 74,250, 75, 60,203, 61,123,207,180,218, 16, 36, 78,142,254, 75,151, 25,137,255, 78,136,117, +189, 17, 1, 3,234,177, 23,249,218,183, 58,108, 89,236,168,109,140, 27,127,211, 8,192,221, 40,172,123,246,236,137,203,200,200, +144, 91,143,167, 77,155, 22,159,152,152,152,221, 17, 30, 6,165,230,182,179,163,234,170, 84, 42,165, 69, 69, 69, 0,128,240,240, +112, 0,248, 83, 52, 34, 77,141, 43,139,129,213,162,103,238, 40,239,214,173, 91, 29, 54,212,164, 82, 41,221,182,109, 91,195,241, +206,157, 59, 49, 97,194,132,134,227,244,244,116,250, 71, 25, 1, 49, 49, 49, 20, 0, 78,159, 62, 77,218,227,186,140, 31,100,173, + 24, 0,178, 54,231, 95, 88, 68, 55, 0,192, 45,157, 14,172, 86,111, 62, 89,171, 4, 0, 36, 39, 39, 35, 33, 33,161,197,244,173, + 79, 88, 79, 35,203, 34,157,250,253,248, 95,227, 29,200, 23, 9,252,159,189, 0, 93,198, 78, 40, 20,211,161, 0, 16, 45,121, 31, +111, 73, 78,163,155, 24,168,212, 21,224, 45,109,138, 83,191,155,149,149, 21,151,150,150, 38,183, 61,151,156,156, 28,159,144,144, +144,221,145,234, 86,123,181, 1,127,134,251,189, 19,120,231,141, 23,136,151,192,151,232,197, 66,170,175,213, 50,245, 90, 37,247, +193, 39,171,255, 22,179,227,236, 26, 0,123,246,236,137,179,254,111,171, 80, 91, 27,146,119,183, 45,129, 87, 55, 95,212,223,168, +195,219, 41,111,201, 51, 50, 50,224,182,134,237, 67, 38,147,145,240,240,112, 90, 84, 84,132,162,162, 34,236,219,183,175,195,122, + 18,214,188,150,201,100, 68, 38,147, 9,164, 82,169,113,197,138, 21, 39, 1, 96,225,194,133, 35, 90,251,238,244,233,211, 27,222, +179,172, 9, 6,163, 30, 6,189, 1, 6,131,249,197,178, 44, 22, 46, 92,232, 84, 90,108,197,191, 57, 76,152, 48,225, 15, 53, 2, + 28, 49,126, 98, 98, 98,236,114, 36, 78,142, 38,174,136,188,195,240,243, 65, 94,225,119,144,160, 43, 76,200, 65,197, 23,103,112, +190,160, 26, 51,150,109,112,232,235,145,101,145, 14, 10,186, 25,242,129,114,187, 13,177, 36,241, 45, 4, 76,123, 26,165, 47, 69, + 3, 90, 69,195,249, 51,218,215,112, 6, 0,180,192,120, 73, 50, 14,250,159,134, 31,128, 24, 69,140,195,229,183, 41,210,210,210, +228,105,105,105, 29,162,189,178,166,177, 61,218,128, 63,195,253,182, 55, 54,173, 89, 75, 30, 13,139,224,191,144,244, 56, 47,164, +127, 24,195, 39, 33, 68, 83, 87,199,137, 17,106, 98,186,116, 53,233,110, 94, 51, 57,248,236,110, 58,209,134,119,113,128,111,129, + 19,124,171,238,168, 1,144,145,145, 33,223,246,239, 55,144,242,222, 82,121, 98, 98, 34,105, 75, 1,179, 10, 63, 0, 84,105,170, +129, 64, 96,241,193,119,160, 44, 84, 64,250,175,142, 37,100, 45, 85,136, 63, 58,141,182, 70,192, 3, 15, 60,128,162,162, 34,132, +135,135,119,184,103, 39,151,155, 29,137,248,248,120, 42,147,201, 24,153, 76, 22, 38,149, 74, 75, 87,172, 88,113,218, 81, 30,150, +101, 97, 48, 24, 27,132,223, 86,252, 79,157, 58,133,225,195,135, 59,149,174,148,148,223, 61,192,217,179,103, 35, 51, 51,179,145, + 1,208, 30,101,197,149,124, 56,125,250, 52,201,206,206,166, 19, 39, 78,188,237,179, 3, 7, 14, 96,235,214,173, 13,199,173,141, + 91,184,205,120,111,199,238,128,176,136,110, 40, 85,212, 97,199, 51, 51, 17, 72, 98, 81,240,249,171,232, 57,189, 39, 50,157, 16, +127, 43,230,206,157, 75, 1, 96,253,250,245,109, 46,179, 97,219,114,160,185, 94,143, 82,105, 68,171,215, 93, 16,103,225,221,193, +183,144,122,225,205, 54,229,103,123,136,110,123,114,180, 71, 36,224, 78,223,111,123, 33, 39, 39,199, 3,192, 61, 0,188,108, 78, +215, 2,200,139,141,141,173,113,148, 71,203,105, 25, 67,149, 94, 48,121,234,116,177, 2, 70,177, 64,192,231, 43,117, 98, 70, 40, +212,114, 60, 31, 79,214, 32, 49, 26,249,229, 55,245, 98,158, 72,167, 51,233, 77, 82,169,148, 52, 55,102,196, 22,181,181,181,255, +181,190,207,207,207,175,242,244,244,100,212,106, 53,103,123,205,200,145, 35, 63,116, 52,141,148, 82,187,194, 78, 8, 89,208,214, +103,202,183,231,253,247,233,211, 7,145, 94, 62,104, 75, 20,192, 86,252,171, 52,213, 72,189,255,157,134,207,254,145,241, 44, 16, + 2, 76, 95,145,226, 84, 33,107, 73,160,219, 75,164,111,220,184, 1, 0,232,214,173, 91,163,247,214,223,181, 87, 32,238,100,136, +207,214, 8, 48, 26, 89,172, 91,183,238,142,121, 1,206,114, 54, 17,127,219,239,223,148,201,100,254, 82,169, 84,225,176,248, 27, +141, 48, 24,244,208, 27, 12, 48, 54, 17,127,202, 57, 23,161, 75, 73, 73,193,169, 83,167, 26,142, 87,173, 90,133,164,164,164,134, +227,244,244,244, 54, 27, 59, 54, 6, 79,155,203,159,173,240,207,158, 61, 27,195,134, 13,115,137,167,189,186, 3, 74, 10,139,161, +222,249, 31,120, 61,245, 49,194, 34,186, 33, 52, 80,130,194,157,133,102,241,247,243, 49,119, 1, 8,120, 14,113,181,135,240, 3, + 64,159,139, 87,113,227,237, 37,208,166,109,108, 61, 66, 32,145, 64,167,211,161,160,160, 0, 21,186,203,232,131,176, 22,175,205, +202,202,138,107,173,236,203,100, 50, 98,173, 39, 89, 89, 89,113,206,132,199,109,163, 98,214,250,106,123,206, 89, 71,160, 37,225, +118,166, 45,104,238,126, 51, 51, 51, 41, 33, 4, 9, 9, 9,164, 45,247,107,197,211, 79, 63, 77,191,252,242,203, 54,229,121, 78, + 78,142, 47,128,233, 7, 15, 30,252, 15,199,113,122, 27, 17,228,243,120, 60, 79, 0,255,140,141,141,221, 99,143, 39,191, 48,159, + 47, 17,138,197, 2,129,200,147,225, 19, 31,202, 19,121,112, 60, 30,159, 35, 12, 56,194, 55, 81, 30, 79,207,227,136, 78,205, 51, +105, 60,133, 2,194,235,213, 77, 39,158, 26,194,161,216,126, 26, 21, 10,133, 82,163,209,176, 0,160, 86,171,185, 55,222,120,163, + 65,240,151, 46, 93,250,114, 91,203,251,132, 9, 19,158,177,190,207,204,204, 92,215, 30,117,136,177,231,253, 47,153,149, 4, 93, +101, 37, 94, 29,216, 15,182,125,247, 14,123, 33,150, 46, 4, 91,241,159, 54,109, 90,188, 76, 38, 35,211,166, 77,139,223, 48,237, + 51,115,100,177,111, 80,163,235, 29,193,194, 53,249, 88,184, 38, 31,207,173,188,132, 39,222,251, 5, 51, 22,159,107,243, 3, 41, + 41, 41,113,200, 48,184, 91,226, 95, 84, 84,212,162, 48,135,135,135,195,104, 48, 96,212,200,145,109,254, 29,107,152,124,219,182, +109,144,203,229, 13,175,214, 12,173,150,196, 48, 62, 62,190,169,248, 55, 24,202,142, 52, 76, 44,107, 50,123,254,122,115,232,191, +169,248,155, 76, 38,168,181,106,167,238,209, 26, 49,104, 26, 53, 72, 79, 79, 71,122,122,122, 35, 99,192,169,251,205,110,220, 30, +202,179,179,157,122,102,173,137,255,236,217,179,177, 98,197,138, 6,241, 23,240, 5, 78,241, 36, 78,142, 38,150, 46,152,102, 95, +206,112,105, 81,140,250,233,163, 64,211, 94, 69, 73, 97, 49,232,244,254,191,123, 43,105,175,130,223, 57, 24,240,243,187,171, 30, +161,186,170, 0,218,180,141,160,148,226,194,133, 11, 24, 63,126, 60, 36, 18, 73, 35,225,247,247,247,135, 86,171,133, 86,171, 69, +105,105, 41, 30,209,190,128, 47,252, 95,106,145,211,218, 7,222,218,243,177,126,214,180,191,220, 81,225,110, 47,103,197,250,221, +166,226,111,207, 65,106,237,126, 51, 51, 51,105,122,122, 58,210,210,210,144,149,149, 69,219,122,191, 79, 63,253, 52,229,243,249, +120,250,233,167, 93,174, 19, 57, 57, 57, 98, 0,255,202,202,202,122,227,189,247,222, 59, 78, 8, 9,183,190, 0,116, 13, 12, 12, +244, 56,116,232,208,218,156,156,156,241,173,241,152, 40,199,227, 17,129,200,192, 82, 31,189,222, 24, 98,226,184,174, 38,142,139, + 48, 17,210, 29, 60, 94, 32, 33,196, 15,132,231,195, 81, 4, 80, 3,231,167,212, 26, 61, 67,124, 88, 30, 51, 82,229, 80, 30,105, + 52, 26,182,169,215,223,209,193, 56,226,253,107,202,203, 48,121, 88,180,211, 2,109, 53, 34,222,221,182, 4, 0, 26,196,223, 26, + 69, 72, 76, 76,204,182, 26, 1, 37,202,155,136, 94, 56,218, 41, 35, 67,173, 53, 65,173, 53,161,172, 90,143,210, 74, 29,110,220, +210,185, 36,124,214,202, 98, 79,252,255, 40,180,100, 4, 0,128,206,160,135, 78,167,115,153,219, 42,218,214, 62,242,224,224, 96, + 91,111, 22,142, 54, 38, 77, 61,225,150, 66,137,142, 52,122, 6,163,222,236,249,235, 13, 48, 24, 27,139,191,209,104,132, 90,173, +134, 74,169,250, 67,243,196,108, 48,165,217, 6,228,172,127,216,182, 45,205,101, 35,192, 86,252,173,194,207, 48, 12,196, 98, 49, + 60,189, 60,218,148,230, 61,123,207,208,150, 94,246,190,187,111,241, 59, 8, 68, 44,216,132,231, 1, 0, 94,185, 87,113,190,160, +218,108,176, 37, 60, 15,227,133,119,129,170,106,167,210, 51,119,238, 92,106,237, 14,112, 5,158,168, 2, 0,108,220,184, 17, 25, + 25, 25,120,255,253,247,113,226,196, 9,232,245,122, 84, 84, 84, 88,189,178,134,235,195,194,194,160, 5,192,195,181, 63,164,188, +180, 84,238,155,122,243,174, 26, 20,205,117, 11, 56,203,103, 27, 9, 75, 75, 75,107,211, 61, 91,197, 31, 0, 92, 53, 2,114,114, +114, 58, 89,196,127,238,215, 95,127,125,241,173,183,222,122,104,203,150, 45,232,211,167, 15, 0,160, 71,143, 30,168,171,171, 19, +189,251,238,187,167, 15, 29, 58,244,109, 78, 78, 78,120,179, 68, 4, 0, 71, 9, 56, 86,108, 50,177, 1, 38,214,212,213,104, 50, +246,230, 49,164,139,144,207, 8,196, 2,158,150,239, 33,172,245,244,230, 41,121, 98,202,138,121, 60, 79, 62,107,240,185,118,230, +172,232,177,224,143,236,166, 59, 63, 63,191, 74,173, 86,115,205,133,249,135, 14, 29,122,217, 96, 48,180, 91, 89, 26, 58,116,104, +187,113,241, 91, 19,238,207,231, 62,253,187,216,150,220,192,171, 3,251, 97,101, 70,134,211, 99, 1,172,222,191, 85,244, 27,121, + 41,137,137,217, 25, 25, 25, 0,128,192,193,157,156, 74,124,189,214, 4,149,134,133, 82,205,162,174,158, 69,173,138,117,250, 1, + 52, 55,242,223,214,203,183,125, 95, 88, 88,136,218,218,218,187,214,104,172, 91,183, 14,225,225,225,176, 14,250,179,237,235,151, + 74,165,116,221,186,117,208,105,181, 46, 27, 0, 82,169,148,110,216,176, 1, 37,165,165, 16,240,120, 8,237,212,169,145,248,223, +127,255,253, 72, 73, 73,113,168,113,146,201,100, 36, 62, 62,190,145, 17,208, 52,146,225,232, 88, 5,131,222, 0,131, 94, 15,163, +209, 0,150, 53, 53,136,191, 94,175,135, 70,163, 65,125,125, 61, 84, 42,231, 13, 0,219, 46, 0, 43, 92,245,252,183,165,109, 3, + 40, 80,101, 17, 26,106, 46, 68, 32,148,154,141,128,180, 52,164, 36, 39, 59,221, 29,208, 84,252, 5, 2, 1, 68, 34, 17,196, 98, + 49,196, 98,177, 75,247,221,168, 94,183,208, 37, 96,175, 75,107,198,186,237,160, 83, 35,112,107, 76, 52, 2, 17, 11,201,204, 79, +193,150, 85, 2,126, 62,224, 87,111,197,143, 31,157, 6,120, 60,167,210,210,214,174, 0, 53,207,220,166,164,166,166,162,178,178, + 18,107,215,174,197,208,161, 67,241,222,123,239, 33, 58, 58, 26, 90,173,182,169,135,102, 53,169,239,170,240, 59, 42,208,174,118, + 7,180,100, 72,184,194,147,156,156,220, 32,252,174,212,141,230,196,191, 65,108,248,124,176, 44,235,108,119,128,119, 94, 94,222, + 39,243,230,205, 59, 50,120,240, 96, 31, 0,120,231,157,119,144,159,159, 15, 0, 24, 61,122, 52,118,236,216,129,177, 99,199,122, + 62,242,200, 35, 5,217,217,217, 89, 60, 30,239,145,219, 27,122, 32, 32, 48,128, 43, 44, 44, 96,179,229, 7,247,246,238, 29,153, + 29,209, 35,252, 34,207, 91, 82,193, 35, 66, 53, 35, 18,104, 24,177,135,202,192,231, 25, 64,141, 60, 78,108,244, 86,149, 86,123, +157, 56,116,110,100,144,127,232, 14,187,198,168, 77,159,255,206,157, 59,159,152, 62,125,250,215,214,176,191, 82,169,100,132, 66, + 97,155,203, 82,123,133,253,237, 70, 0,172, 94,254,240, 94,145,208, 85, 86, 66, 93, 98, 22,193,241, 22,239,208,217, 40, 64,225, + 47, 87,111,227,110,238,184,250, 66,185, 83,137,111,171,248,219, 10, 63,165, 20,221,186,117,107,244,153,209,104,108,120,213,214, +214, 66,173, 86,163,166,166,230,174, 53, 30,214,121,254,251,246,237,107, 20, 9,176,138,255,144, 33, 67,160,211,105, 27, 26, 58, +106,181,102, 28,108,152,214,124,182, 6, 70,163, 17, 93,195,194, 96, 52,153,154, 21,127,103, 26, 18,139, 17,112,155, 87, 98,157, +186,216, 90, 36,227, 54, 3,192, 96,108, 16,255,147, 39, 78, 66,163,213, 66,165, 82,161,174,174, 14,181,181,181,141, 60, 59,103, + 97,237, 6,112,181,223, 31, 0,170,171,170, 81, 93, 93,133,170,234, 26, 84, 85, 87,163,186,186, 26,213, 85,102,143,180, 95,255, +254,168,177,188,119,214,251, 7,128, 97,195,134,253,238,245,123,122,194,203,203, 27,222, 94,222, 80,169, 84,241,109, 41, 79,173, +117, 9,216,251,110,193,251,115, 33,152,249, 41, 2, 17, 11,126,238,167, 48,110,127, 30,240,243,193,174,103,147,112,125,215, 53, + 60,184, 98, 19,192,191,203,203,138,232,174, 67, 18, 38,129, 90,173,134, 78,167,131, 70,163, 65,110,110, 46,150, 45, 91,214,236, +229, 30, 30,214, 8,202, 85,167,197,219, 85,175,218,246,249, 54,125,222, 45, 29,183,197,200,104,174, 91,192, 25,158,132,132, 4, +146,156,156,140,164,164, 36, 76,152, 48,193,229,200,196,151, 95,126, 73, 88,182,113,155,204,178, 44,156, 29, 11, 16, 27, 27,123, + 37, 57, 57,121,232,150, 45, 91,198, 31, 61,122,212, 59, 33, 33,225,132, 85,252, 45,142, 42, 68, 34, 17,189,126,253,186, 96,239, +222,189,125,253,253,253, 79,198,198,198, 22, 52,199, 85, 87, 91,199, 69, 70,244, 81,141, 30, 61, 58,233,226,197, 95,239, 83,170, + 85,157, 40,107,100,193,192,200,234, 25,189, 94,175,215, 42, 81,174,228,244, 58, 85,105,113, 57,251,227,238, 61,203,131, 2,131, + 43, 12, 6,141, 93,247,189, 57,239, 95,161, 80,240, 1,192,199,199,167,195,118, 11, 48, 45,121,255,219,254,253,134,217,106, 46, + 47,107,244,153,179, 99, 1,166, 77,155, 22,191,230, 95, 31, 3, 48, 15,248,203,200,200,144,219, 78, 45,204,200,200,144, 79,248, +230, 33, 0,192,153, 21, 63, 99,218,180,105,241,119,235,230,109, 43, 73, 73, 73, 73,131,183,111, 21,125,155,204,133, 74,165,130, + 78,167,179,105, 68,238, 94, 26,159,121,198, 60,246,195,200,178,184,120,241, 34,206,158, 57,131,161, 67,134, 66,167,211, 65,171, +213, 65,167,213,226,219,111,190,129,245, 58, 71, 42,250,170, 85,171, 48,160,255, 0, 24,141, 70, 92,185,114, 5,172,209,128,210, +146,210,118,125,166,214, 99,203,154, 5, 8, 15, 15,119,168, 97, 50, 24,245, 96, 77,230,176,255,241,227, 63, 67,173, 85,163, 94, +165, 68, 93, 93, 29, 20,181,181, 80, 40,106,218,100,136, 89, 35, 1,109,241,112,142, 28, 57, 2,149, 74, 5,149, 74,105,249,175, + 66, 80, 96, 32,250,245,239,143,223, 46, 93,194,225, 35, 71,156,230,180,122,255,124,190, 0, 30, 30, 30,240,242,242,130,183,151, + 23,188,188, 60, 80,163,168,137, 7,144,125,167, 67,253, 45,225,124, 65, 53,140, 23,222, 69, 53,114, 64, 18, 87,130,196,254, 7, + 5,239,207,197,212, 21, 95, 67, 44, 96, 0, 1,223,252,114, 1,174,118, 5,148, 78,249, 12, 1, 91,167, 64,163,209, 32, 32, 32, + 0, 10,133, 2, 10,133, 2,199,142, 29, 67, 89, 89, 89, 67,152,184,225,250,210, 82, 60,235, 47, 65,144, 71,101,107, 30,112,188, +173,168,218, 14,146,179,190,183,126,102,189,214, 21,239,220,209,238, 1, 71,197,223, 85,207,191,185,251, 77, 72, 72, 32, 19, 38, + 76, 32,109,185,223,166, 70,128, 43,226,111, 69, 80, 80, 80,222, 67, 15, 61,244, 72,106,106,106,223,243,231,207,199, 74, 36, 18, +222,212,169, 83,137, 72, 36, 2,199,113, 36, 49, 49, 49,239,197, 23, 95, 28, 50,104,208,160, 93,255,252,231, 63,159, 48,153, 76, +213,173,196,188,185, 95, 47, 93, 57, 57,104,240,144, 71, 79,158, 56, 49, 99,215,238,255, 45, 61,117,226, 68,167,139,249,191,137, +175,148, 22,208,111, 63,254, 94,146,186,234,253, 1, 89,187,119,175,234,221,171,247,143, 94,161,158, 71, 98, 99, 99, 77,112, 48, +229, 9, 9, 9, 56,121,242,100,212,186,117,235,222,213,233,116,130,247,222,123,239,131, 93,187,118,205, 46, 45, 45,189,187,194, +209,214, 46,128,192,107, 69,168,177,132,254,109, 49, 62, 56, 24, 43,241,155,227, 94,135, 37,196,255,219,233,139,240,235, 27,132, + 9,223, 60,132,140,199,126,144, 91,195,254, 86,241,183,122,255,206,204, 50,216,145,218, 62, 35,241, 9, 33,184,116,233, 18,172, +133,181,105,152, 85, 32, 16, 64, 32, 16,160,178,178, 18,137,137,137,119, 61,147,172,163,254,215,173, 91,135,145, 35, 71, 66,167, +215, 67,171,211, 66,103, 25,220,164,213,153,187, 1, 86,175, 94,109,183, 49,145, 74,165,116,197,138, 21, 48,153, 76, 56,125,250, + 12, 4,124,115,216, 54, 50, 50, 18,215,138,138, 80, 90, 90,138,173, 91,191,195,236,217, 15,227,224,193,131,212, 54, 18,208, 90, + 3, 36,147,201,132, 0, 88,169, 84,202, 53,231, 1, 57, 51, 85,209,234,249,231,230,230, 66, 93,175,105, 48,192,148, 42, 37,148, +202, 58, 40,149,245, 46,135,194,173,222,191,101, 37, 64,151, 12,129,217,179,103, 55, 58,142, 8, 15, 71,191,254,230, 65,113,191, + 93,186,132,107,150,136, 71,211,235, 28,193,152,123,198, 64, 36, 20, 65, 34,145, 64, 44, 22, 67, 36, 18,161,188,188,220, 97,241, +183, 23,234,119,117,141,128, 25,203, 54, 96, 7,128, 7, 82,255, 15, 52,237, 85,144,148, 85, 56, 95, 80, 13, 18,224,143,171, 37, + 74,179,247,239,100, 23, 64,211,174, 0,167,167, 7,106,181, 0,175,160, 73,120,223, 44,244, 70,163, 17, 95,124,241, 5,198,143, +255,125, 92,216,193, 39,195,128, 10, 13,250,238, 81, 32, 42,184, 71, 75, 13,120,118,147,190,111, 57,208,208,252,203,155, 94,235, +138, 96,183,214,111,239,170,231,239,170, 33,113,167,239,215, 98, 4,180,121, 22, 64,120,120,248,214,177, 99,199, 6,159,203,203, + 75,209,106,181, 67,228,242, 67, 18,145, 88,196,103, 8,131, 67,135, 14,121, 15, 24, 48, 96, 83,114,114,242,127, 42, 43, 43,237, +122,235,179,103,205,228,126,220,251,227,225,161, 67,135, 45, 52,176,250, 7,174,230, 95, 89,202, 21, 21,176, 0,168, 24,140,113, +112,239,190,105, 33, 33,193,123,120,124,225,183,255,125,107,185,225,219,141, 27, 44,125,124, 45, 99,228,200,145, 31, 38, 36, 36, + 0, 0, 42, 43, 43,145,149,149,229,243,213, 87, 95, 45, 5,128,147, 39, 79,142, 28, 56,112,224,190, 63,133, 1, 96,245,206,239, +255,118, 75,235, 94,134, 19, 83, 2,173,214,111,244,194,209, 8, 28,220,169, 65,244,109, 67,255,103, 86,252,236,148,229,218, 94, +115, 82,173,105,235,223,191, 63, 46, 92,184,208, 72, 88,106,107,107, 11, 0,244,106,238, 59,174,174,189,220,214,116, 54, 61,255, +237, 55,223, 66,167,211, 65,111,208,195, 96, 48, 96,197,138, 21,176, 39,254, 86,112,156, 9, 98,137, 23,180, 90, 29, 46, 93,188, + 8,190, 64, 0,163,193, 0, 15, 79, 15,108,221,186, 21, 60, 30,207, 58,119,190,213,123, 93,177, 98,197, 62,169, 84,106,144,201, +100, 33,214,116, 54, 89, 7,192,169,208,230,194,133, 11,145,147,147,131,250,250,122,212,171,213, 80, 41,149, 22,241, 87, 66,165, + 84,161, 94, 85, 15,181, 77,131,239,200,179, 27, 62,124, 56, 61,117,234, 84,131,247,223,220, 52, 64, 71, 23, 1,138,139,139,187, + 45, 47,172,162,127,246,236,217, 6,111,222,209,123,142,137,137,161,214, 69,126,188, 60,188, 32,150,136,161, 82,169,226,109,250, +176,157,106,120,239,212, 98, 64, 86, 35, 96,122,234, 87,160,219,129,160, 39,101,200,126, 41, 9, 99,151,111, 6, 4, 2,120,138, +219,214,207,217,212, 16, 0, 0,121,142,189, 96,227, 45, 12,222,231,129,242,255,105,160, 88,242,251, 89,163,209,136,113,227,198, + 1, 0,194,252, 37,248, 73,214, 13,239, 47,187,129,207,206,104, 91,101,179,245,248, 1,243, 64, 56,107,195,222,116, 80,156,179, +211,226,108,199,239,180,213,243,111,174, 77,112,133,235, 78,222,175,173, 17,208, 30,229,111,224,192,129,159,168,148,170,189, 35, + 98,134,143, 84, 41,149, 1,172,137,213,135,134,134, 86,134,133,133,149, 43,149,202,243,149,149,149, 14, 55, 10, 83, 38, 79,225, + 0,108, 61,122,228, 68,110,236,216,177, 63, 72, 36, 18, 95, 2,202, 17, 66,192,113,180, 78,171, 86,200, 47,231, 21,171,190,221, +184,193,161,118,222,250,204, 0,243, 64,234,166, 3,245,150, 45, 91,246,159, 63,133, 1,144,152,152,152,221,150, 5,127, 28, 41, +172, 86, 67,192, 42,252,237, 41,232,109, 73,219,224,193,131,113,242,228, 73, 84, 86, 54,132, 8,123, 1, 64,117,181, 57,162,244, +216, 99,143,253,161,153,213,244, 25, 81, 74,233,163,143, 61,138,213,171,215, 88,250,204, 89,248,250,250, 18, 71,191,111,133, 68, + 34,182,242,153,189, 41,181,198,246, 59, 0,236,110, 54,209,127,197,138, 21, 87,164, 82,105,133, 76, 38,227,217, 14, 8,180, 76, + 11,116,184,161,179,206,125,143,141,141,109,247,103, 55,124,248,240,166,123, 1, 52,124,238,236, 10,128, 50,153,140,100,103,103, +211,173, 91,183, 54, 90,168,199,202,237, 74,121,142,139,139, 35, 70,214, 8,163,202,216,174,247,222, 90,232,223,217,189, 1,102, + 44,219, 0,216, 44,252,115,239, 27,191,143, 75, 82,183, 83,122, 27, 69, 0, 6,182,110,124,150,198,150,162, 20, 64,244,251,254, + 88,114,186, 15,130, 1, 84, 22,168,209,187,119,111, 0,192, 39, 75,252, 49,105, 68, 48, 34, 38,229, 59,244,219,206, 76,117, 75, + 75, 75,147,183,182,236,177,189,246,166, 61,218,188,182,114,221,141,251,109, 79,140, 30, 51,250, 10,128, 43,183, 69,172, 3, 3, + 93,226, 27, 55,126,100, 17,154, 29, 21, 26,134,222,125, 6, 57, 99, 72,181,235,125,182,199, 34, 63, 46, 25, 0,119, 90,192,246, +236,217, 19,151,177,162,227,237, 5, 96,173, 72, 35, 70,140,192,158, 61,123,116, 22,209,231, 0,120,220,137,200, 67, 59, 21, 18, + 34,147,201, 26, 60,251,214,196,255, 78, 98,225,194,133,182,241,212,134, 6,219, 58,141,208, 25,111,231, 78, 62, 95, 91,238,236, +236,236, 54, 47,251, 27, 23, 23, 71,226,226,226,218,156, 46,123,107,251,183, 7,218,210, 37,176,104,209, 34, 20, 22, 22,182, 91, + 90, 28, 89,222,215, 89,156,121, 77,129, 51, 48, 15, 12, 29,159, 44,193,254,227,125, 16,234,225,133, 95, 79,221, 66, 95, 7,197, +223, 94,249,235,168,203,225,182,199, 90, 2,127,166,251,237,128,207,191, 75, 59,243,173,186, 91,105,191,235,187, 1,222,169, 8, + 67,123, 26, 1,137,137,137,226, 63, 89, 1, 36,127,240,111, 91, 87,168, 97,173, 6,128,187,241,232, 56,104,107,151, 64,207,158, + 61, 73,207,158, 61,219,165,189,113,102, 31, 0, 87,113, 36, 77,139, 35,105,249,238, 58,235,134, 27,246,156,200,168,168, 40,234, +126, 12,110,184,225,134, 27,110,184,241,247, 2,227,126, 4,110,184,225,134, 27,110,184,225, 54, 0,220,112,195, 13, 55,220,112, +195, 13,183, 1,224,134, 27,110,184,225,134, 27,110,184, 13, 0, 55,220,112,195, 13, 55,220,112,227, 47,129, 70,179, 0,230,205, +155,231,242,200,212,230,230,137,187,249, 58, 30,223,220,185,115, 93,226, 27, 54,108,216,109,124,103,207,158,117, 57,125,205,241, +253, 89,242,195,217,103,184,126,253,250,187,146,190,246,206,143,187,153,191,246,166,137, 58,251,252,218,155,207,221,190,184,249, +154,225,235, 10, 64, 1, 64, 8,160,182,163,165,207,105, 3,192,141,191, 62,214,175, 95,239,126, 8,127, 51,248,249,249, 49, 48, + 79,207,228,215,213,213,113,148, 82, 83, 71, 74,159,117,223,249,172,172, 44,218, 30, 11,205,180,215, 74,123,110,220, 57,236,218, +181, 43,110,234,212,169,217,127,242,219,176,174,125, 37,113,214, 0,232,144, 17, 0, 55,254,122,160,148, 54,218,234,216,213, 8, +192,218,181,107,237, 94, 51,113,226,196,184,204,204,204, 70, 43,139, 77,152, 48, 33,254,192,129, 3, 46, 85,244,244,244,244,102, +249,146,146,146, 58, 4, 95, 71, 6, 33,132,244, 8, 13, 69, 81,121, 57,173,173,173,181,238,207,224,212, 18,131,182,198,226,169, + 29,171, 75, 8,193,115,178,189,121, 25,210,201, 67,190,161, 20,202,245,251,242,158, 91, 52, 99, 36, 1, 67,249, 10,149,142, 14, +159,249,188,211, 91,114,102,101,101,197, 89,151,156,181,252,119,105,185,217,166,226,111, 45,247,109,221,104,167,185,239,186,202, +217, 30,124,109,221, 50,216,149,104,201,157, 16,255, 61,123,246,200,167, 78,157,250,103, 55,206,172,251,176,223,209,174,244,119, +222,120,129,241, 18,248, 50,122,177,144,211,215,106,249,245, 90, 37,251,193, 39,171,219,101,135,193,219, 12,128,246, 20, 8, 87, +185,156,229, 35,132, 48, 22, 43, 76, 75, 41,229, 58, 90,250,218, 75, 96,219,195, 0,176, 54,234,182,105, 37,132,232, 41,165,162, +182, 68, 10, 8, 33, 20, 0, 86,173, 90,213,104,199,176, 5, 11, 22,200, 9, 33,160,148, 18,103, 27, 37, 0,224,190,247,111,116, +158,153,149, 41,207,204,204,116,186, 1,108, 79,190, 63, 67, 20,133, 82, 74,227,123, 69,208,248, 94, 17, 0,128,114, 3, 59,167, +147,144,191,217,250,249,111,202,122, 81,153, 3, 27,167, 0,192,201,237,159,230,115, 28,194,238, 25, 19,228,243,193, 75, 99, 15, + 12, 25,226,119,253,185,229, 35,255, 11, 0,183,234, 52,255, 39,224,147,255, 1,228,226,220,185,115, 7, 58,251,108,154, 46, 69, +219,150,229,102,109,197,191, 61,140,128,150,190,227,170, 88,182, 7, 95,114,114, 50,210,210,210, 28,186, 39,103, 34, 42,173,241, +181, 87,100,198, 86,252, 57,142,195,250,245,235,177,121,243,102, 58,103,206, 28,226,100, 30, 11,101, 50, 89,187,172,151,189,120, +241,226,185,169,169,169,174, 86,104, 31,139,231,175,190, 19,117,120,211,154,181,204,163, 97, 17,226, 23,146, 30, 23,134,244, 15, +227,243, 73, 8,163,169,171, 99,197, 8, 53, 48, 93,186, 26,116, 55,175, 25,218,250, 27,124, 71, 26, 55,169, 84, 26, 12, 96, 56, +128, 83, 50,153,172,178,131,121, 58, 62, 0, 18, 0, 76, 7,176,147, 16,146, 69, 41, 85,182, 3,239,119,148,210,135, 93, 21,216, +142, 2,134, 97, 90, 53, 82, 8, 33, 35, 1, 8, 9, 33, 33,148,210,138,150,174,107,205, 64, 33,132,208, 23, 95,124, 17,221,187, +119,191,109,187,208, 85,171, 86,197, 23, 23, 23,203, 9, 33,212, 81, 35, 64, 42,149,210,141,207,123,226,241,177,183,111, 46,195, +125,239,143, 77, 63, 25,240,164,147, 94, 83,123,242,213,213,213,197,189,254,250,235,242,148,148, 20,196,199,155, 87,182, 59,119, +238, 92,220,218,181,107,229,221,187,119, 7,199,113,208,106,181,136,139,139,195,196,137, 19,237,114, 10,235,212,113,125, 95,223, + 38,207,140,238, 26,223,233, 95, 19,178, 1,128, 45,103,227, 46,191,205,202, 77,221,125,160,228, 60,161,208,250,160,194,247,100, +252,211,139, 66,236,122,199,189,186,117,234,212, 93, 40, 41,123,254,185,199,244,161, 18,161, 80, 89,163, 37, 43,190,218,178,249, +141,103, 30,133,191, 68, 66,117, 70, 19,253,247,234,175,244, 0, 72,231,206, 65,252,242,242,106, 38, 42,170,249,157, 53, 71,132, + 28,136,188, 25,230,225, 23,123, 79,240,170, 97, 49, 1,130,141, 27,175,134, 7, 7, 73,170, 62,124,233,248,170,162,235,195, 76, +147, 39,117,206,205,191,162, 42,126,242,241, 94,137,214,114,227, 76, 29,176,221, 32,167, 45, 94,104, 83,241,111, 90, 63, 93,225, +239,136, 17, 0,139, 16, 83,171, 17,144,156,156,108,123,190,145,104,219,110,236,227,170, 81, 97,229, 73, 75, 75,107,115,148,192, + 86,252, 23, 44, 88,128, 83,167, 78,209,159,126,250, 9,115,230,204,113,150,202, 32,149, 74, 5, 50,153,140,109,135, 38,178,124, +241,226,197,211, 83, 83, 83,119,186,240,221, 48, 0, 53, 0,194, 1,156,203,201,201,233, 1,224, 51, 0, 1,182,252, 0, 62,137, +141,141,117,120,207, 5, 45,167,229, 27,170,244, 30,147,167, 78,247, 85,192,232, 43, 16,240, 69, 74,157,152, 47, 20,106, 89,158, +143,167,222, 32, 49,106,249,229, 55, 85, 98,158,168, 86,103,210, 27,164, 82,105,139,245,183,205, 17, 0, 66, 72, 55, 0,159, 3, + 40, 5,240,162, 84, 42,253, 23,165,244,198,221,242, 96,237,136,116, 32,128, 77, 0,110, 2, 56, 6,224, 1, 0, 79, 19, 66, 30, +167,148, 86,183,145,126, 22, 33,100,142,189,254,210,187, 25, 98,191, 67, 24, 13,224, 50,128, 8, 0, 21,196,162,212,142, 26, 52, + 19, 39, 78,140, 3,208, 72,252, 23, 44, 88, 32,183,141, 6, 88, 62,147, 79,156, 56, 49,206, 94,119, 64,122,122,122, 28,128, 70, + 98,205,204, 82,192,214,123,127,124,172, 16, 79,126,170, 70,122,122,122,156,189,240,125,123,243, 1,192,241,227,199,229, 98,177, + 24,185,185,185,141,246, 59, 96, 24, 6,111,190,249, 38,177, 54,118,187,119,239,150, 79,156, 56,209,110, 6,116, 58,126, 81, 78, +197, 2, 12,169, 20,202, 43,126,223,138, 21,132,161, 24,242,166,129, 0, 6, 92, 56,114, 61,238,230,246, 41,114,224, 68,171,141, +112,124,175, 8,218, 93, 40,193, 43,207,206,209,135,122, 9,133, 85, 23,114,136, 39,195,199, 11,227, 34,209,197, 79,130,235,185, + 71,137,214, 64,201,130,185,143, 25,226,123, 69,208,126, 30,222, 40,163, 85,100,216,176, 97,205,242, 5, 5, 9,239, 21, 10, 25, +241,177, 99,101, 47,178, 38,221, 71,161, 93,123, 26,253,130, 4, 68,169,188,234,209, 51,194, 35, 40, 32, 64, 84,201, 81,165,254, +199, 19, 21,234,121,227,254,152, 2,220, 52,236,111, 91, 55,157, 53, 2,172,215,216,142, 35,176,119,157,189,237,183,219,147,207, +214, 8,144,201, 20, 0, 20,144, 74,253,209,156,104, 59,138,150,140, 10, 75, 68,166, 77, 81, 15, 91,241,223,189,123,183,156, 97, + 24, 48, 12,131,113,227,198,225,232,209,163,141,242,203, 81,152, 76,166, 60, 30,143,103,148, 74,165,124,153, 76,214,214,241, 44, +146,234,234,234,239, 3, 3, 3,103,166,166,166,110,119,242,187, 90,152,247,139, 81,229,228,228, 12, 2,176,253,224,193,131,125, + 56,142,179,213, 40,240,120,188,135, 0,100,199,198,198,198,219, 35,204, 47,204, 23, 75,132, 98, 95,129, 64, 20,204,240, 73,103, +202, 19,249,113, 60,158,136, 35, 12, 56,194, 55, 82, 30,175,158,199, 17,149,154,103,170,241, 20, 10, 8,175, 87,183, 58,241,212, + 16, 22,197,119, 46, 2,240, 17,128,131, 22,203,230, 89, 0, 31,173, 95,191,126,166,139,130,237, 15,224, 69, 0, 35, 0, 36, 2, +216, 3,224, 36,128,143, 41,165, 10, 23, 40,143, 88,210,181,150, 82,202, 17, 66, 60, 1, 60, 97, 57, 63,176, 13,134,133,175,229, +173, 39, 0,165, 51, 30,118, 11, 17, 20, 33,128, 55, 0, 44,149,201,100, 6,116, 44,140, 0,144, 3,160, 19, 33,100,171, 37, 79, +190,105,106,208,180,100,160,100,102,102,202,109,195,254, 11, 22, 44,104, 56,182,125,191,106,213,170,120,139, 97,208,106,141,207, +204,204,148,219,134,233,153, 89, 10, 92,217, 99,222,133,145, 73,252,166, 65,180,185,239,253,193,204,202,148,219,219,208,167, 57, + 62,107, 99,198,204,146, 82,103,249, 40,165,113,199,142, 29,195,156, 57,115,240,197, 23, 95,224,204,153, 51,113,209,209,209,217, + 77,175, 17,139,197,242,206,157, 59, 59, 18,171,143,235,124,236, 23, 92,158, 19, 7,175, 47, 46,128,148,105,226,104,103, 15, 11, + 31,177, 92,130, 56,129,174,187, 60,160,115,235, 91,217,198,247,138,160,115,255, 57,203, 16,234, 41, 20, 24,175,158, 18,250, 7, +123, 19,121,153, 18, 51,163,186,161, 95,152, 31,132,181,151, 33, 87,105,209, 77, 32,130, 31,225, 9, 22, 63, 61,135,214, 11, 69, +249,241,189, 34, 40,124,252,154,229, 84,212,170, 2, 70,142,244, 90,165,100, 71, 45,242,246,175, 20,233, 24, 79, 78,226,101,208, + 7, 4, 5, 50, 30,126, 98,190,162,166, 76,164,172, 99, 33,168,211, 19,219, 50,211,154, 65,107,233,247,151,219, 19,206,228,228, +228,120,123,227, 1,154,243,252,155, 26, 2,206, 24, 1,214,207, 90, 19, 99,219,243,246,132,177, 41, 31,221,230,127,123,123,147, +162,128,163,124,173,133,251,219, 34,218, 77,141, 10, 0, 8, 8,200,106, 23,241,159, 55,111,158,185,251,141,227,240,234,171,175, +226,163,143, 62,106, 16,255,181,107,215, 58,205,205, 48, 12, 12, 6,195, 89,161, 80,200,182, 67, 36,160, 6, 0,170,171,171,183, + 7, 6, 6,198,167,166,166,202,157,248, 46, 31, 0,158,124,242, 73, 81, 78, 78, 78,102, 86, 86, 86,167, 37, 75,150,176,111,189, +245, 86, 35, 93, 13, 12, 12,196,161, 67,135,226, 0,164,197,198,198, 38,183, 70,200, 35, 2, 31, 3, 75,187,112,156, 49, 66,200, +227,245,160,132,132, 16, 62,159,240,121,188, 58, 66,136, 22,132,167,228, 40,252,169,129,243, 80,154,140,232,229,195,106,153,145, + 42,174,221, 12,128, 38,125,195, 97, 0,186, 81, 74,173,130,255, 62, 33,228,132, 84, 42, 13,163,148,150, 58,227,193, 18, 66, 30, +179,136,245, 7, 0, 22, 1,120,212, 18, 66, 73, 6, 80, 76, 8,121,150, 82,250,141, 19, 34,253, 31, 0, 87, 41,165,107, 8, 33, + 34, 75,133,103, 41,165,159, 17, 66, 38, 17, 66,254, 67, 41,253,127, 46, 22,138,241, 0, 42, 1,220, 11,224,127,206,124,177,185, + 8,128, 84, 42,125, 10,192,219, 0,202,231,206,157,187,174,131, 69, 0, 6, 90,210, 54, 1,192,100, 0,215,237, 25, 52, 45,193, + 86,240,109, 69,191,233,184, 0,135, 43,186,141,248, 3,192,149, 61,143, 53, 50, 2, 92,225,179,109,204,100, 50, 25,177, 53, 2, + 28,193,225,195,135, 97, 48, 24, 16, 19, 19, 19,255,211, 79, 63,201,139,138,138,228,209,209,230, 45,117, 57,142, 67,106,106, 42, +173,175,175,135, 64, 32,192,140, 25, 51,236,222,183, 46,247, 36, 24, 3,139,218,152,240,120,193, 79, 55,229, 87, 55, 28, 70,175, + 55, 38,155, 69,139,163,200, 75, 21,210,154,122,111,104, 5, 94,152, 48,239,138,253,231,200,240,234, 43, 47,228,250,234,244, 38, +198, 87, 34,162, 73, 81,221,225, 35, 17,144,146,234,122,120, 50,124,164, 12,235, 78,143,255, 90,129,159,255,183, 15, 61, 60,189, +232,121,149,242, 58,128,190, 45,209,229,158,237,242,220,232, 97, 85,135,189,248, 17,172,144,189,213,107,252,152, 20, 47,157,193, +115, 10,207,235, 36,163,172,173,241, 40,186,116, 50,194,104,184, 84, 89, 88,160,246,177,212, 25,187, 66,229,168,119,106, 29, 31, +208, 82,255,115, 75,222,180, 61,175, 82, 42,149, 82, 87, 67,166, 29, 9, 77, 61,127,179,120, 3,105,105,237, 55, 72,176, 61, 60, +127, 74, 41, 88,246,119,141, 30, 59,118, 44,142, 30, 61,234,146,248, 91, 96, 20, 8, 4, 38,142,227,142, 49, 12, 99,108,163, 17, + 16, 98,125, 83, 93, 93, 45, 15, 12, 12,148,166,166,166, 58,186,115, 86, 81, 74, 74,138,207,225,195,135, 83,179,178,178, 58,125, +253,245,215,220, 19, 79, 60,193,223,178,101, 11,222,121,231, 29,228,231,231,163, 71,143, 30, 40, 47, 47,199,187,239,190,107,122, +251,237,183,147, 0, 60, 27, 27, 27,251, 89,139,140, 28,235,107, 2,211,131,112, 24,104, 4, 23,233, 33, 16, 9,133,124,166, 76, + 44,224, 41,121, 18, 97,149, 72,196,171,215,155, 56, 15,190,145, 31, 96, 96,245,166,107,103,206, 42, 30, 11,254, 72,115, 28,174, +233,135,189, 8,192, 36, 0, 57, 77, 6,142,229, 0,152,180,126,253,250,175,156, 16,235, 71, 0,188, 4, 32,188, 73,104, 94, 1, +224, 23, 66,200, 39, 0, 14, 16, 66, 76,148,210, 45, 14,240,121, 0, 19, 92,166, 19, 0, 0, 32, 0, 73, 68, 65, 84,152,107,245, +242, 41,165,250, 38,151, 60, 14,224, 87, 66,200, 74, 74,169,198,149,240, 63,128,175, 44,255,157, 50, 0,154, 10,166, 84, 42,253, + 7,128,231, 44,207,114, 21, 33, 68, 47,147,201, 54,116,132, 6,132, 16,210,219, 18,194,250, 17, 64, 6, 0,107, 62,193,209, 8, +192,223, 13,165,165,165,242, 81,163, 70,129, 16,146, 61,106,212, 40,252,240,195, 15,120,232,161,135,226, 58,117,234, 36,103, 24, + 6,139, 23, 47, 38,150,198, 36,110,235,214,173,114,189, 94,143, 17, 35, 70,180,216,208,141,185,118, 83, 94, 62,170, 63, 64, 72, +246,175,161,166,248,129,231, 2,228, 58, 14,241,230, 46, 0, 96,200, 98, 3, 1,170,161,174,174,139, 59,180,181,183, 92,237,125, + 34,254,225, 39,124,154,245,138, 75, 12,236,202,245,235,183,188, 26, 28, 36, 41,170, 83, 27,124,195,253, 61, 5,201, 67,123,122, + 12, 11, 23, 17,157,198, 4,141,150,195, 85,162, 53,101, 20,149,106, 10,202,235, 77,157,132,226,178,114,131,110,226, 13,189,241, + 3,111,224,149,230, 56,125,252,195,186,106,235,175,116, 25,144,112, 31,115,241,120,217,248,210,223,126,184,209,123,248,220, 16, + 94,255,168,146,179, 71,191,175, 35, 60,159, 17, 28,199,213,220,186,165,181,107, 69, 53, 21,108,123,199, 86,111, 54, 45, 45,173, + 69,193,182, 13,175, 55,141, 4, 56,114,253,159, 21, 9, 9, 9,196,214,235,183,133,109, 8,191, 45,104, 15,158,250,250,122, 57, + 0,240,249,124,188,252,242,203, 56,117,234, 20,126,250,233,167,182,210,234, 1,152,244,122, 61, 91, 90, 90,154, 25, 22, 22,102, +180, 23, 89,108, 5, 42,219,131,234,234,106, 89, 96, 96,224,131,169,169,169,142,180,251,190, 58,157,174,207,194,133, 11,167,206, +155, 55,143, 14, 30, 60,152, 0,104, 16,127, 0, 24, 61,122, 52,118,236,216,129,177, 99,199, 50,143, 60,242, 8,205,206,206, 94, +195,227,241,180, 30, 30, 30,208,104,110,151, 38,142,163,186,108,249,193,244,222,189, 35,139, 35,122,132, 95,225,121, 75,202,120, + 68, 88,199,136, 4,117,140,216,163,194,192,231,105, 64,141, 2, 78,108, 12, 81,149, 86, 7,157, 56,116,238,205, 32,255,208,183, + 92,125,144,173, 70, 0,164, 82,233, 68, 0,155,155,120,181,135, 0,204,153, 59,119,238, 87,142,120,176,132, 16,158, 37,252, 61, +173,165,126,121, 74,105, 53, 33, 36, 5, 64, 6, 33,228,123, 7,230, 41, 63, 2,224, 0,165,180,174, 5,190, 58, 66,200, 1,203, +117, 95, 56, 41,138,247, 1, 8, 4, 48, 31,192, 86, 66,200,125,148,210, 67,174, 68, 0, 8, 33, 73, 0,222, 7,208,131, 82,170, + 38,132,140, 6,112, 93, 42,149,170, 40,165,233,142, 70, 0,164,102, 83,223,145, 70,139,200,172,110,128, 99, 24, 3,224, 4,165, +148, 18,179,219,116, 29,128,154, 16,210,205, 58,206,195,153, 8, 64, 83,143,191, 45,222,127, 67, 88, 62,241,155,134, 40, 64,100, + 27,188,255,223,195,252,191,135,111,165, 82,231,188,127,163,209, 72, 79,157, 58, 5,111,111,111,228,229,229, 81,147,201, 4,165, + 82,137, 75,151, 46,201, 3, 3, 3,209, 36,236,151, 61, 96,192,128,248,109,219,182,201, 71,140, 24,209,124,184,207,104,164,221, + 78, 93,128,208, 59, 12,130,188,106, 26,106,242,134, 74,201,192,116,169, 30, 8,108,188, 35,181,103, 32,155,221,125,248,233,248, +125,219,103,201,129,189,205, 54,118, 87,110,220,120, 45,178, 91, 55,160, 74,251, 42, 0,228,107,149,216, 45, 42,173, 28,112,239, +248,224, 1,134, 60,252,114, 93,129,221,231,110,241, 11, 42,235,125, 0,160,220,160,243,191,161, 55, 38, 23,148,150,238,136, 10, + 14,110,214, 0,184,119, 74, 10,227, 33,156, 56,152, 85,255, 82,220,189,127, 66,159,186, 27,219, 13, 87,127,201,172, 53,114, 94, +183, 42,138,127,174, 80,214,120,142, 0,195,144, 26,149,206, 87, 58, 43,186,155,236,251, 51, 55, 90, 42, 51, 50,153,140,216, 70, + 0,108,189,203,166,225,118,171, 72, 39, 39, 39, 35, 33, 33,129, 52,183,208, 73, 91, 70,227,187,186,112, 74, 71,131,181,186, 75, +165,254,183, 69, 4, 92,141, 42,164,165,165,181,139,248,111,222,188,153, 30, 57,114, 4,116,155, 63, 72,138, 2, 31,126,248, 33, + 40,165, 96, 24, 6,235,214,173,115, 57,178,160, 80, 40,244, 1, 1, 1,241, 71,142, 28,217, 59,126,252,248,201,205,149, 31, 39, +224,103,169,175,115,171,171,171,215, 7, 6, 6, 62, 6,160,102,241,226,197,255, 72, 77, 77,181,231,168,213,237,218,181,171,116, +223,190,125, 95,197,199,199, 63,213,175, 95, 63, 36, 36, 36,208,172,172,172,134,116,100,100,100, 64, 36, 18,225,250,245,235,216, +187,119, 47,233,210,165, 11, 27, 27, 27,251,211,165, 75,151,154, 37,140,140,232, 83,166,213,234,230, 30, 57,114,100,125, 96, 80, +160,210,215,199,167, 24, 66,161,158,213, 51,245, 44, 79, 95,171,227, 43,171, 60,245,158,226,155, 21,149,190,135,246,237, 93, 63, + 96,224,160,247, 13, 58, 77,125,187, 24, 0, 82,169,148, 72,165, 82,107,226, 59, 89, 94,135, 45,211,236, 26,162,160, 0, 22, 16, + 66,186,192, 60,194, 17, 0,154,181,208, 45,162,242, 2,204, 3,244,174, 53,225,105,138,107,150,235, 94, 32,132,124,212, 10, 31, + 1, 48, 3,192,114, 59,124, 95, 3, 88, 68, 8,249,202, 78,250,108, 11, 77, 56,204,227, 29, 98, 96,238,251,127, 19,192,105, 66, + 72, 47, 0, 69,182, 54,134, 3,124, 15, 3,120,218, 34,178, 90, 75, 90,181,150,227,117,132, 16, 33,128,239, 90,227,179,228,197, + 99, 0,230, 57,106, 0, 72,165,210,181, 0,190,105,137,207,194,185, 18,128, 55, 0, 95, 0,187, 44,105, 19,195, 60, 79,252, 23, + 0,163, 8, 33,243, 1,252, 4, 96,119, 75,233, 3,204,243,232, 91,232,235, 71,211,177, 1, 19, 38, 76,176,107, 12, 76,152, 48, + 33,158,153,245,123,191,189,213, 8,176,190,183, 13,231,187,204, 55,235,246, 41,129,142,240,157, 59,119, 14,221,187,119,199,203, + 47,191,220, 80,102, 54,109,218, 68,115,115,115, 49,101,202,148,219,174,247,240,240,144,139,197,226, 22,249,194,207,157, 67,109, +247,206, 56,254,242, 83, 13,124,151, 95,219, 17, 23,145, 91, 39,103,166,136,111, 75, 75,113,190, 1, 34,113,235,179,159,174,150, +148, 44, 68,215,174, 63, 3, 24, 77, 65,121,184, 86,249,178,134,101,193,234,204, 65,178,139,149,149,184,166, 51,108,226, 19,162, + 2, 33,198,171, 37, 37,233, 0,208,210, 32,192, 46,225,253, 22, 2, 88,145,127,244,197, 34,113,232, 12, 69,105,185,184,107,121, +201, 73, 49, 4, 1,189,139,174,155,194,170,203,111, 64, 40, 20,132, 12, 12,245,124,164, 86,101,252, 22,192, 13,123,158, 43,128, +184,166,211,255, 90,240, 64,227, 93, 89, 19,160,185,254,255,191, 3,218, 58, 85,207,250,253,180,180, 52,218, 86,190, 45, 91, 54, +211,236,236,108,144,116,179, 97,124,224, 45,111, 76, 92,162,194,248,241,227,225,204,180,191,230, 16, 16, 16, 16, 15, 0,247,220, +115,143,166, 29,186, 41, 20,129,129,129,115, 0, 88,157, 83,125,106,106,234,110, 7,191,203, 2,168,200,200,200,144, 63,244,208, + 67,195, 83, 83, 83,135,152, 76, 38, 34,145, 72, 48, 97,194, 4,236,223,191, 31, 28,199, 33, 49, 49,145,190,248,226,139, 36, 42, + 42, 74, 63, 99,198,140, 30, 53, 53, 53,183,116, 58, 93, 75,138,204,254,122,233,202,166, 65,131,135,248,158, 60,113,226,253,179, +124,254,160,158, 61,122,126,233, 19, 24, 92, 34, 8, 22,211,195,123, 15,249,215, 40,170,199,133, 5, 4,191,221,167, 79,159,195, + 94,161,158,107,251,119,141, 49,228,229,229,181, 75, 4,128, 7,243,116,191, 88, 0,239, 1,120,222, 34, 60,158,182,245, 9,230, + 65, 98, 87, 1,252,219,210, 37,112,170, 5,126, 6,230, 65,102, 7, 0,120, 56,144,158, 99, 0, 38,162,229,133, 21, 24, 0,193, + 0,122, 0, 56,109,135,243,180,229,186, 16,180,220, 55,201,192,188,140,163,191,165,219,224, 33,139,112,231, 91,184,243, 45,199, + 91, 0,252, 0,243,140, 3, 5, 0,131, 29,190, 89,150,200, 67, 63,139,145,100,155,206, 50, 0, 82, 0,191, 89,174,253,222, 14, +223, 75, 48,207,110,112,164, 43,195, 3,192, 62, 0,155,237,228,199, 76, 0,255,181,252, 63,107,147, 62,129, 37, 47,211, 0,124, + 10, 96,137,229,243,178,150,126,240,192,129, 3,217,132, 16, 20, 23, 23,203,173, 51, 1,154,122,253,197,197,197,114,235,181,246, +110, 32, 41, 41, 41, 59, 51, 51, 19,155,126, 50, 52,140,220,111,234,165,111,250,201,208,112,237,221,228,203,205,205,197,184,113, +141,135,186,135,135,135,199,111,219,182, 77,222,179,103,207,120,142,227,228, 75,151, 46,165,214,105,128,132, 16, 12, 31, 62,188, + 69,163,162,111,110, 46,190, 11, 12,137,247,177, 57,215,127,254, 68,168,223,191, 1,220, 31, 2,202, 1,121, 75, 5,180,158,243, + 66,141,214, 7, 10, 50, 12, 67,199,237,138,111,173,216, 91,102,112,108, 7,176,189,119,143,176,190, 0, 94,214,155, 56,164,231, + 21, 97, 92,168,185,187,147, 80,170, 82,177,236,123,183,110,221,186,229, 64,153,122, 31,128,103,254,111, 53,143,214,158,222, 22, + 84, 81, 86,131,138, 91, 42,240,249,213,158,245, 10,138, 90,165,137,134, 4, 11,253,248, 28,166,107,245,166,239,150,188, 28,235, + 23,210,255,137, 90, 59, 66,147,109, 79, 92,218,220,135,157,176,205,252, 63, 43,197, 73, 15,248,206,206, 2, 32, 41, 10,180,133, +175, 37,143, 61, 38, 38,166,195, 24, 34, 13,131, 29,173,226,159,199, 98,131,220, 92,199,218, 42,254,214,178,241,236,179,207, 6, +243,249,252,138, 99,199,142,125,121,207, 61,247,180,101,138, 98,247,212,212,212, 53,150, 40,192, 44,203,140,128, 89,169,169,169, +223, 59, 18, 84, 4, 80, 15,160, 42, 60, 60,124,232,216,177, 99, 75,207,229,229,117,214,106,181, 68, 46, 63, 4,145, 88, 4,134, + 48, 56,116,232, 16, 25, 48, 96,128, 38, 57, 57,121, 84,101,101,165,221, 58, 55,123,214, 76,246,199,189, 63,126, 58,116,232,176, +158, 6, 86, 63,249,106,254,149,167,185,162,130,167, 0, 64, 12,134, 14,238,221,247,100, 72, 72,112, 54,143, 47,124,237,191,111, + 45,175,255,118,163,235, 61,202,205, 25, 0, 47, 91,172,161, 41, 0, 46, 1,240,106,230,123,123, 44, 30,123, 18,128,145, 22,241, +108, 54,202, 9, 32, 18,192, 86, 7, 13,128,106,203,245,188, 86,248,226, 0, 92,113,144,239,138,229,250, 29,173,240,205, 5,240, + 36,128, 11, 48,207, 80,184,214,132, 91,110,241,254,159,179,120,195, 27,129, 22, 71, 92,240, 44, 30,251,227, 0,162, 44, 81,132, +230,210,169,180,124,190,206, 98, 4,108,108,133,239,107,139,209,229,200,253, 82,203,245,173, 61,191, 15, 44,145,141, 3, 22,163, + 6, 77,184,247, 3, 24, 96,201,139,124,139, 33,213,173,213, 31, 53,247, 32, 80, 0,242,230, 22, 2,178, 94,227, 76, 5,127, 82, + 42,165, 79,126,170,110,102,225, 30,133,211, 2,209, 94,124, 47,188,240,194,109,215,140, 31, 63, 62,123,252,248,241, 4, 0,238, +187,239, 62,167, 26,161, 61, 47,188, 64,124,154,182, 40, 61,188,178, 37,171,251, 19, 0, 24, 40, 19, 16,115, 80,198, 58, 50,251, +186,131,197,192,146, 47, 38, 90, 4, 62,192,171, 71,131,248, 91, 92,228, 91, 98,177,216,209,217, 40, 4,192, 59, 71,179,206,122, +132,118,237,241, 32, 7,143,200,146,226,114,158, 81, 87, 75, 59,133,120, 17, 47, 79, 1, 97,141, 28, 20,181, 6,150, 72,136,164, + 78,197,246, 14,105,217, 33,104, 86, 44,154,190,255, 35,151,239,189,211,179, 0,218,202,215,146,199,222,179,103,207, 14, 35,254, +220,247,254, 56,144,103, 30,147,183, 81,110,192,119,199, 12,160,148,182, 75,190, 90, 57, 76, 38, 83, 53, 0, 68, 71, 71,183,105, + 65, 32,171,248, 91, 80,101,249,239,104,221, 16, 90, 28,179, 51, 0, 48,112,224,192, 48,149, 82,181,104, 68,204,240,199, 84, 74, +165, 47,107, 98,141,161,161,161,183,194,194,194,174, 40,149,202, 37,149,149,149,249,142,166,107,202,228, 41, 44,128,231,143, 30, + 57, 49, 54,118,236,216, 41, 18,137, 36,136,128,154, 8, 33,224, 56, 90,173, 85, 43,214, 92,206, 43, 46,251,118,227,134, 54,173, + 8,216,212, 0, 48, 1,248, 71, 43, 2, 98,139,147,150,151,201,242,106, 14, 38,152, 71,212,243, 28, 76,143, 28, 64,150, 29,190, + 12,152, 7,173, 57,130, 71, 29, 72,223,122, 0, 95,218,225,249, 21,230, 41,144,112,128,239, 27, 75,196,192, 30,138, 44,158,189, + 35,233,227, 57,145,167,235,237,240,221,239, 0,159, 53,218,176,209,242,108,236,206,181,165,148,146,137, 19, 39,198, 89, 5,223, + 54, 4,239,202, 82,192, 50,153,140,164,167,167,199, 49,179,218,103,233,222,246,230,251, 51,160,160,228,166, 62,178, 91,183,141, +243,222, 95,247,164,245,156, 65,192,108,214,105,184,125,229,197,197, 42,135, 10,211,250,245,180,234,244, 6,178,252,251, 95, 22, +238, 94,125,223,206,227, 39,202,158, 9,246,229,166, 50, 1, 62,126,148, 2,132, 80,189,158,229,202, 57,160,202,160,231,252, 74, +203,180,134, 72, 39,210,152,156,156, 28,111,219, 29,144,156,156, 28,223, 81,158, 95, 71, 92, 9,240,207,130, 73, 75, 84,119,244, + 30,101, 50, 25, 39,149, 74, 59,139,197,226,178,232,232,232,251,219,131, 51, 53, 53,245, 96, 96, 96,224,147,169,169,169, 27,157, + 48, 0, 88, 75,228, 20, 0, 48,122,204,232,229, 0,150, 55,189,176,233, 24, 33, 71, 49,110,252,200,159, 96,238,138,109,130, 48, +244,238, 51,168,205,247,220,156, 1,160,115,129,135,182, 18, 34,209,187,249,254,178,124,141, 96, 17,250,118,171,232, 73, 73, 73, +217,246,230,229,255,145,124,127, 6,212,104, 52, 79, 1, 30, 70, 0,193, 28,104,169, 78,103,216, 82, 94, 94,121,158, 82,234,240, +180,169,160,152,127,208,140, 15, 39,147, 91,158, 15,231,118, 29,139,220,172,175, 62,120, 57, 32, 64,180,136,207, 35,180,172, 90, +119,185,204,192,110,146, 8, 24,177,132,207,227, 25, 89, 78,236, 76,250,172,125,252,214,129,103,174,238, 3,112,219,212, 63,155, +208,191, 43,139,205, 52,245,204, 29, 57,127,183,249,238,182,225,227, 40,152, 89, 10, 16, 66, 48,117,218,239, 3,162,247,236, 61, +211,208,134, 36, 78,142,110,175, 41,138,229,237,217,222, 88,140,128,141, 78, 92,238,111, 49, 0,212,127,214,246,129,223,228,129, + 82, 71, 27,251,166,104,110, 20,187,155,239,175,205,231, 70,199, 71,117,117, 53,133,185,155,171, 77,184,229, 57,157, 2,192,209, +205, 31,147,132,167, 94,249,240,241,185,121,159, 62, 63,251,216, 0,131,154, 68, 4, 8,248, 65, 32, 68,227, 37,225, 87, 14,234, +231,147,239, 44,119, 66, 66, 2, 73, 75, 75,115,121,189,249, 59, 37,158,127,150, 8, 64,199, 51, 30,204,177,161,191, 65,245, 10, +179, 56,204,222,248,147,238, 6, 72,162,162,162,254, 30, 67,100,221,112,195, 13,240,121,128,135,136,128,227,204,109,116,189,214, + 93,253,221,112,227,111,219, 30,184, 31,129, 27,110,252,125,192,154, 0,165,198, 42,250,110,241,119,195,141,191, 51, 24,247, 35, +112,195, 13, 55,220,112,195, 13,183, 1,224,134, 27,110,184,225,134, 27,110,184, 13, 0, 55,220,112,195, 13, 55,220,112,227,175, +136, 70, 99, 0,230,205,155,231,242,200,205,230,214,214,110,142,239,127,223,127, 30, 55,104, 72,111,121,231,174, 97,241, 42,173, + 90,126, 88,158, 27,159, 52,235,217,108, 87,249, 86,127,181, 61, 46,106,200, 40,249,173,210, 82,120, 74, 60,113,163,164, 32,254, + 95, 79, 77,115,153,175,189,239,247,194,225,121,113,163, 71,245,148, 75, 60,121,224,243, 24, 16, 49, 65,153,242, 69,226, 42,223, +153, 91, 67,226, 70,140, 26, 33,247,245,226, 1,124,160,230,220,122,226,104,250, 34, 39, 69,186,124,191, 87,246, 95,185,141,111, +228,200,145, 46,243,157, 56,113,226,118,190, 72,215,211,119,226,202,237,233, 27,213,167,143,203,124,199,243,243,255,116,124,147, + 90,201,223,229,203,211,232,162, 69,201, 45,126,190,191,153,252,141,124, 96,146,235,229,101,223,254,219,203,243, 36,215,203,203, +242,204,106,234,195, 21, 52, 58, 23, 20,249,176,203,124, 85, 87,190,187, 45,125,103,223,184,238,114, 67, 58,108,105,143,219,206, +125, 24, 84,234, 50,223,203, 85, 97,248, 35,218,171,191, 59,159, 84, 42,229, 55,183,179,160, 35,124,251,247,239, 7, 0, 40, 20, +138, 8,157, 78,167,120,242,201, 39,107,255,200,251,117,218, 0,104, 9,186,173,210, 72, 0, 61, 97, 94, 39,160, 64, 60, 91,118, +205,209, 31,216,254,205,242, 56, 2, 14,193,126, 1,200, 61,124, 70,254,245,215, 31, 35, 54, 33, 22,172, 90, 35, 31,208,111, 60, + 56, 14,242, 95, 35,190,142, 31, 54,108, 8,174, 94,189,142,186, 90, 53, 6,143,153,147,221, 18,223,250,111,229,113, 20, 4, 61, +122,247,148, 75, 95, 89,130,234, 79,182,227,155,207, 63, 3, 32,198,158,243, 37, 96, 24,200, 63,126,231, 45,228,231, 95, 70,120, +120, 15,136, 36,124,220, 44,201,111,113,113,145,194, 29,159, 81,161, 80, 8,137, 68,130,130,130, 2,116, 9,241, 65, 16,223, 11, + 93,186,251,193, 95,226, 11, 79, 98, 2,195, 48,160,156, 9, 26, 17, 31,117,183,234, 80, 49,220,254, 92,242,186,130, 53,212, 91, + 82,135, 49, 35,122,193,203,147, 15,161,132, 1,159, 7, 48, 66, 62,250,134,125, 78,141,148,135,194,155, 79, 57,156,225,171,247, +234,226,194,194,194, 16,123, 79, 87,185, 86,167, 7, 35,146, 0, 70, 32,175, 62, 58, 78,171, 81, 99, 84,200,229,236, 63,202,138, + 92,191,126, 61,157, 59,119,238,223,106,126,125, 71,133, 61,161,111,227,245,158, 0, 70,116,146,120,252,183,180,180,180,159, 64, + 44, 2,231,225,177, 12,230,149, 49,235, 59,202, 51, 40,248,117,111,220,181,139,135,111,219,107, 32, 33,121,217, 95,165,140,146, +111, 54,109,250, 77, 36, 20, 74, 56,142,243,245,244,242,242,122,112,234, 84, 15,152, 87,176,235,168, 35, 59,173,209,102,174,173, + 68, 82,169,212,199,215,215,119, 65,223,190,125,103,136, 68,162,174, 37, 37, 37, 37,165,165,165, 39, 12, 6,195, 82,153, 76, 86, +224, 2,159,159,191,191,255,146,251,238,187,111,242,179,207, 62, 27,254,197, 23, 95,220,186,112,225,194, 49,157, 78,247,174, 76, + 38,187,224, 8,199,254,253,251,241,227,200, 29, 24,179,247,222, 21,225,225,225,175,121,122,122, 98,251,246,237,167,103,206,156, + 57,252, 79, 19, 1,104, 65,252,121,158, 34,254,136,199,198,246, 90,201, 81,170, 59,122,249,214, 39,151,182, 74, 15,136,103,203, + 46,218,251,110,242,212,222,116,234,125,203, 97,172,175, 5,223,196,224,151,139,151,241,196, 19, 47,254, 94, 34, 24,224,231,220, +141, 8,234, 30, 38,231,234,149, 48,112, 4,135, 14,229,198,151,104, 91,202,168,165, 20, 66, 95, 16, 15, 31,156,185, 88,140,243, + 23,255,129,175,190,219,223,240, 57,199, 1, 15,140, 25, 3,212,151, 3,240, 70,193,133, 75, 16, 4,249, 33,118,244, 32,121,173, +166, 21,155,133, 48, 0, 97, 16, 53, 36, 26,157, 60,133,232, 18, 36,134, 79, 96, 0,252, 69,222,240, 23,243, 32,224,241, 96, 52, +153, 80,203,114, 56, 89,117,218,238, 67, 45, 63,191,132, 6,248, 2, 62, 30, 30, 8, 14, 10,132,143,143, 7, 40, 99, 2,203,213, +195, 4, 19,188,188, 60, 16,212,169, 43,122, 70,254, 68,179, 14,143,109,181, 81, 90,151,105,160,190,222,158,232, 25, 17,130,224, +160, 64,168,213,106, 8, 69, 98, 8,116,230,197,249, 34,194,123,200,107, 20,181,248, 62,183, 40,190,184,228, 38, 20,229,215,177, +244,217,232, 86,141,129,180,229,105, 14, 55, 18, 9, 79, 38,196,251,135,250,103,183, 38,254,119,195, 8,120,227,253,247, 41, 0, + 44,125,237,181,118,249,141,197, 43, 86, 80, 0, 72, 93,184,208,101,190, 31,115,114,158, 48, 24, 12, 27, 1, 96, 70,124, 60,227, + 74,227, 43,219,182,205,188, 70,188,205,180,105, 74, 41, 8, 33, 13,255,173,231,172,215,205, 77,110, 89,176, 23, 45, 74, 38,142, +138,186,147,226, 63,192,211,200,110,247,246,243,237, 7, 0, 66,137, 24, 6,173, 14,156, 90,179,226,216,145,195,239,220, 59,115, +102,127, 0,197,246, 72,244, 60, 33,133,121,241, 20,214, 34, 10,156,165, 29,106,182, 45, 26,122,239,100,252,118, 40,195,169, 60, +186,118,241,176,188,247,160,184,248,240,254, 15, 56,111, 20, 39,215, 56,117,121, 74, 74, 10,182, 37,103,181,122, 77,124, 86,227, +173, 72, 6,248,153,111,181, 66,199, 65,203,154,243, 85,109,249, 47, 27,229,135, 62,222,130, 86,249, 86,174, 92,153,253,198, 75, +175,134, 76,155, 49,221, 75,167,211,226,227, 15, 63, 96, 86,175, 94,173,155, 63,127,126, 24,128,155,237, 93,247,246,237,219,151, +176,115,231,206, 76,192,185, 53, 7,114,115,115,105, 81, 81, 17,170,171,171,161, 82,169,224,237,237,141,192,192, 64,132,135,135, + 99,204,152, 49, 46,213, 59,169, 84, 58, 62, 58, 58,122,211, 43,175,188,114,181,111,223,190, 27,135, 13, 27,118,233,214,173, 91, + 93,115,115,115,163,159,122,234,169,221, 82,169,116,133, 76, 38,251,202, 9,190,248, 25, 51,102,164, 45, 95,190, 60,208,104, 52, + 66, 34,145,192,211,211,179,179, 90,173,158, 57,109,218,180, 7,165, 82,233,124,153, 76,246,121,107, 28,207, 43,164,192, 72, 96, +202,137, 25,240,236,238,217,101,209,162, 69, 56,117,234, 20, 85,169, 84,126, 54,191, 3, 0,188,153, 51,103,154, 38, 78,156,120, + 87,196,253,220,185,115,141,142,155,219,208,141,223,130,232,119, 3,208, 11,230, 37, 99, 77,106, 61,123, 35,247, 74,197, 71, 99, + 34, 67, 94,188,111, 64,231,119, 58,249, 74,186,200,183, 74,183, 2,184, 44,158, 45,107,113,147, 26,125,125, 13, 58,245,190, 31, + 75, 94,155,129,141,178,223,235,226,225, 99,235,160,214,232,145,152,240, 34,238,137,125, 18, 15,167,220, 7,137, 68, 4,131,137, +133, 74, 99,144,247, 25,221,187,133,194,113, 29, 48, 0, 51,230,172,197,191, 94,121,166,225,236, 3,247,196, 65, 44, 22,225,135, + 67,251,177, 39, 39, 23,155, 54,124, 6,157, 86, 15, 33,143, 15, 47, 15, 33,212,213, 37,241,181, 37,104,118,247, 49, 74, 41, 64, + 57,243,139,225, 64, 41,133,222, 32, 50, 55, 79, 34,128, 26, 76, 48,241, 0, 19, 76, 48, 25, 56,176,166,214, 13,216,130, 19,169, +180,107, 48,133,143,183, 39,194,186, 70,160,223,224,222,240,246,146,160,174,190, 18,229,149,229, 80,212,221,130, 81, 71,224,225, +225,129,224,224, 88,204,156,126,129,110,223,217,183,249, 48,254,230, 27,212,228,237, 13, 45, 31, 16,138,133,208,106,132, 48,104, +132,208,137, 69,224, 19, 22, 20, 60,232,180,245,208,106, 84,232,218,181,139, 92,200,227,163, 6, 74,124,244,209, 17,136, 68,173, + 23,142,247, 55,189,111,183, 0,189,246,248,107,173,126,174, 80, 40,104,147,227,152,128,128,128,124, 66,136,142, 82,202,247,247, +247,247, 40, 40, 40, 8, 76, 75, 75,203,158, 59,119,110, 23, 87, 11,178, 48, 52,116,118,195,111, 0,113,254, 64,187, 69, 59,214, +167,165,209,231,158,123, 46,222, 88, 81,225, 20,231,143, 57, 57,210,145, 35, 71, 46, 29, 27, 21, 5,163, 72,132, 85,171, 86,113, + 51,239,187,111, 2,165, 52,203, 41, 87,142, 16,172,124,231,157,134,227, 5,111,191,141, 85,239,190,219,234,177, 61, 52, 53, 2, +150, 47, 79,163, 49, 49, 49,200,202, 42,164, 9, 9, 61, 7, 2, 40, 92,190, 60, 77,235,164,248,231, 14, 30, 56,208,199, 90,103, + 60,197, 18,148, 85, 86, 64,169,168, 69,244,200, 81, 30, 63,126,181, 33,107,202, 83,255, 24, 8,243,230, 5,173,129,125, 97,233, +106,254,163, 51, 31,228, 71,134,135,115, 86,207,240,237, 85,159, 54,186,232,221, 5,207,155, 13,191,151,230,199, 63, 62,117,130, +211,249,234,146,248, 55, 88,200, 1, 78, 92,156,224, 20,181, 39,159,224,252,187, 79,131,248, 4,193, 84,120, 30,250,194, 95,145, + 95,163,198,240,189, 21, 14,125,127,157, 76,118,244, 21,233,115, 61, 30,255,231, 83,126,105,155,191,227,194,195,195,153, 37,203, + 87,192,251,157, 37,248,225,135, 31, 74, 31,122,232, 33,151, 12,209, 22,132,127,194,206,157, 59, 15, 88,143,167, 79,159,238,144, +114,169, 84,170,184, 3, 7, 14,200,141, 70, 35,122,245,234,133,113,227,198,193,215,215, 23,181,181,181,184,121,243, 38,174, 93, +187,134,155, 55,111,210,137, 19, 39,198,123,123,123, 59,156, 79, 82,169,116,250,125,247,221,247,241,202,149, 43,183, 14, 27, 54, +236, 99,171,177,211,165, 75, 23,204,156, 57,147, 36, 37, 37,121, 1,200,149, 74,165,185, 45,237, 94,218,148,111,254,252,249,233, +207, 61,247, 28,115,250,244,105, 16, 66, 16, 24, 24,216,240,218,187,119,175,112,244,232,209,159, 73,165,210,227, 45,241, 61,175, +144, 98,202,137, 25, 0, 64,182,167,236,160,247,126, 54,190,123,126,126, 62, 10, 11, 11, 73, 93, 93, 93, 47,169, 84,202,159, 54, +109,154, 9, 0,157, 54,109,154,137,101, 89,220, 13, 52, 21,127,235,185,166,247,193,111, 70,252, 3,135, 71, 4, 62, 30,213, 35, + 96, 14, 33, 68, 64, 41, 53,114,230,151,193,100,212,105,133, 12,215,101,112, 39,241,107, 65, 62,189,122,239, 60,121,237, 59,221, + 86,233, 81,241,108, 89, 89, 43,205, 55, 6,244,239, 11,134,201, 70,126,109, 53,128, 75,168, 43,189, 2,129, 88,132,140,221,159, + 64, 83,101,194,156,127,188, 12,142, 3,166, 62, 56, 6, 38,190,151,221,155,203,207,191, 4,142, 3, 18,135, 18, 0, 93, 0,244, +128, 78,111, 64,210, 3, 19, 33,246, 99,176,105,203, 62, 48, 12,144,254,221, 70,148, 22,254, 26,255, 80, 92,100,246,229,179,205, +115,113, 20,224, 56, 14, 28,199,193,100, 50, 65, 47,160, 48, 18, 35, 12, 6, 3, 52, 30, 58,128, 19,131,161, 38,152,132, 20,245, + 6, 29,212,202,186, 86,211, 22,236,165, 7,159, 47, 65, 96, 96, 32,122,247,238,141,208, 78,163, 0, 30, 3,147,233, 52, 24, 90, + 11,157,154,133,137, 83,163,252,102, 13,130, 3,171, 16,232, 23, 11,133,106,113, 92,115,155,188, 72,116, 44,168,190, 10,208,137, + 96, 96,140, 80, 11,249,168,151, 8,192, 23, 8, 1,206, 19,132, 71, 80,175,214, 64, 81,126, 29, 5,167,115, 80, 83, 92, 12,142, +227,192, 80,158, 75,133,230,171,181,191, 27,206, 79,205,123,202,126, 59,105,217,215,221, 90,116,210,210,210, 22,189,242,202, 43, +207, 20, 23, 23, 51,132,144, 96,153, 76,246, 29,204,155, 59,121,180,161, 44, 11,214,172, 89,179,229,214,173, 91, 72, 79, 79,199, +240,190,125,121,254,131, 7,183,185,130,164, 46, 92, 72, 20, 64, 28,165, 84,190,122,245,106, 57, 0, 72, 83, 82, 28,246, 74, 12, + 6,195,186,177,150,202, 36, 20, 10,209,167, 79, 31,108, 63,116, 40,211, 18, 13,112,152,231, 78,109, 85,187,104, 81, 50,201,202, + 42,164,167, 79,155, 35, 86, 54,255,127,189,247,222,123, 75, 23, 45, 74,246,117, 84,179, 60,141,236,246,193, 3, 7,250,240, 24, + 6,207, 62, 58, 7, 90,157, 30,171,190,252, 18, 30, 18, 9,116, 58, 29,116, 90, 45,134, 14,139,138,220,191,121,243,115,147,230, +204,249,200, 94,212,241,221, 5,207,115, 0,152, 43, 69, 69, 76, 83,193,111, 90, 61, 93,185,247,110,253,198,199,103,165,189, 78, + 39, 76,125, 58,158,138, 34, 93, 50, 4,108,119,237,163,219,252,237,158,183,107, 65,249,241,113,189,222,132,195, 19,130, 33,120, + 81, 6,229,156, 8,240,253, 67,156, 18,255,131, 7, 15,150,135,119,238,114,243,159,207, 62,211,237,245,151, 23, 98,245,134,117, + 23, 71, 70, 71,247, 92,247,233, 58,143,151, 22,190,138,205, 99, 70, 97,203,150, 45,143, 61,242,200, 35,155,218, 40,252,113, 59, +119,238,108,112,152, 44, 97,245, 23, 96,222, 42,221, 46, 14, 28, 56, 32, 15, 14, 14,198,176, 97,195, 88,134, 97,248,230,232, 44, + 7,129, 64,128,128,128, 0,116,234,212, 9,215,174, 93,195,129, 3, 7,228, 51,103,206,116,168,174, 72,165,210,228, 41, 83,166, +124,176,114,229,202, 79,251,246,237,187,150, 16,194, 1,248, 12,192, 36, 0, 71, 0,188, 75, 41, 45, 34,132,188, 10,224, 93, 71, +248, 86,206,159,255,253,216,228,100,178,107,215, 46,240,249,124,200,229,114,156, 63,127, 30,189,123,247,198,123,239,189,135, 65, +131, 6,225,153,103,158,225,191,249,230,155, 43, 91,244,252, 45,216,158,178,131, 2,128,135,135, 71,153,159,159, 31,196, 98, 49, +132, 66, 97,189,112, 25, 88,122,140,146,105,211,166, 97,217,178,101, 56,127,254, 60,182,110,221,122, 87,196,127,238,162,101,191, + 59, 58,203, 95,111,214, 8,104, 46, 2,192,240,121, 12,159,229,168,138,229, 76, 58,137,128,223,213, 75,200,244, 7,199, 2,145, +247, 2,157,122, 3,183,174,160,243,229,156,233,143,197, 70,132,103,156, 43, 19,215,108,149,102,152, 55,183,107,190, 14,243,120, + 86, 65,242, 1,208, 21,190, 97,125,113,253,114, 58,214,202, 54,128,209,123, 96, 98,124, 44,246, 29,204,129, 70, 3,120, 4,180, +220, 46, 73, 60,250, 66,171,185, 12,147,201,118,111,154,114, 0, 55,193,240,226,240,248, 19, 79,131, 19,169,241,227,238,175, 48, +245,193,167,224,225, 9,168,235,203, 44, 26,212, 60,140,224, 65, 96, 17,127, 35,107,130, 94,105,132,198,168, 65,173,132, 15,163, + 70, 0, 61,223, 8,158,145,128, 53,113, 80,106, 89,212,212,179, 45,170,217,121,249,114,218,179, 19, 1,143, 71, 64, 24, 17, 76, + 38, 10, 86, 83, 12,189,201,136,210,242, 58,212, 40,234, 81,167, 50,129,209,233,192,162, 28, 60,193, 57,116,233,174,196,168,232, + 24,249,119,223, 94,106,150,147, 7,128,170,116,208,170,110,194,116,171, 14,188, 94, 93,193, 48, 12, 76,172, 30,181,229, 69,184, +124, 34, 23,149,215,139, 45, 66,194, 7,195, 7,192,187, 59,221,128,214,144,255,250,245,235,245, 73, 73, 73,253,163,162,162, 88, +145, 72,164,254,224,131, 15, 70,194,188, 41, 81, 31,180,113,166,137, 48, 52,116, 1, 0,140, 30, 52, 8,161,161,161, 21,171, 87, +175,206, 2, 16, 63,108,240,224, 54, 71, 1,252,129,108,105, 74, 10, 17,132,132,196,173, 94,189, 90, 46, 8, 9,137,115, 38, 18, + 96, 20,137, 32,208,235,177,125,251,118,132,132,132, 96,198,196,137,214,104, 0,117,198, 8,184, 83,176,138,190, 76, 38,179,109, +248,112,248,240,225,176,209,163,147, 31, 68,203,219, 70,219, 98,132,159,191,127, 63, 30,195,224, 31, 73, 73,168,173, 83,162,178, +166, 26, 2, 1, 31,124,190,249, 37, 16, 8, 32,146,120,160, 87,120,248,135, 87, 79,157, 62,223,123,120,140,220, 30,233,149,162, + 34,124,187,253,127,183,121,252,214, 72,192,168,232, 33, 72,140,191,215,201, 59, 86,197, 1,222,217,125, 7, 39,102,247,237, 19, + 25,159,185,235, 75, 57,208, 49,250,254,243,190,254, 8,250,125, 27, 16,242,249, 25, 12,240,227,131,231, 19, 0, 86, 81,129,225, +123, 43,224,201, 39, 80,179, 20, 60, 59, 53,229,218,213,171,213,123,118,237,238,251,245,231, 95,227,147, 47, 63,187,190,238,131, +143,222, 14, 8, 12,168, 93,178,116,201,193, 77, 91, 54, 99,220,232, 88,124,155,182,245,235,110, 61,186,125, 61, 46,118,156, 75, +247,220, 84,252,119,237,218,133,174, 93,187,246, 58,121,242,228, 28,152,183, 26,183, 27,246, 55, 26,141,136,142,142,230, 88,150, +229,171, 84, 42,136,197, 98,112, 28,135,223,126,251, 13,249,249,249,240,242,242, 66, 76, 76, 12,202,203,203,145,155,155, 75,237, +117, 7, 72,165,210,217, 41, 41, 41, 43, 31,120,224, 1,175,181,107,215,250,124,252,241,199, 66,152,119, 45,205, 4, 16, 13,243, + 6,103, 31,193,188,157,251, 65,152,119, 60,109,149,111,231, 43,175,108, 30,208,191, 63, 89,157,148, 4,114,255,253,216,126,244, + 40, 87, 90, 90,186, 4,192,234, 27, 55,110, 76, 91,180,104,209,231, 63,252,240, 3, 98, 99, 99,225,233,233, 57,166, 37,174, 41, + 39,102, 96,199,142, 29, 88, 63,201, 92,199,252,252,228, 85,157, 58,117,130,151,151, 23,245,244,244,188, 97,120, 29, 32,211, 8, + 93,182,108, 25,172,134, 70, 99,253,186, 59,152,187,104, 89,131, 17,208, 72,236,155,158, 16,207,150, 85,254,124,181,114,221,198, + 35, 87, 95,254,173,180,238, 0, 3,202, 7, 40, 48,229, 61,252, 28,243, 1,254,171, 72,194,161,129, 43,128, 73,139,225, 45,224, +134, 61, 16, 21, 62,199,210, 93,112, 27,118, 29,170, 33,128, 18,211,158,120, 17, 28, 7, 0, 53, 48, 47,155,108, 68,143,190,209, + 16,139,248, 48,177,122, 80,131, 57, 44,226,237,237,141,234, 26, 69,139, 55,241,209,135,175, 16, 0,184,248,243,151, 96,152,198, + 78, 2,167,253, 21, 58,189, 17, 60,129, 24, 68,104,238, 67, 83, 41,149, 24, 51,102, 76,235,238, 8,103, 0,199,113, 96, 89, 22, +122,189, 30,245, 28,139, 58,131, 17,202, 50, 37,234,110,214, 65, 89, 94,131, 26,101, 45,202,117, 26, 40,213,181,168,213,183, 60, +214,201,219, 75, 13,150,229,160, 55,152, 80, 91,167, 68,254,213, 98,156, 56,157,135,159, 79,228,225,210,111, 5, 40,185, 81,133, +122,181, 1,170,122, 61,202, 74,235,112,225,215,107,200,205, 61,139,146,178,242, 22, 57,109,139, 10, 91,167, 70,201,185, 75,248, +101,239, 33,100,110,248, 16,135,182,110, 64, 73,193, 85,112,212, 8,142,144, 6,225,119,166,230,219, 11,243,219, 3,159,207, 7, +128, 91, 0,110,249,251,251,151,120,123,123,235, 23, 45, 90,116, 18,230, 1, 99, 12,204,107,101,231,187,202,191,102,205,154,212, +164,164, 36, 0, 64, 68,112,112,136,165, 79,156,215,158,149,195, 42,250,214, 72,128, 3,225,255, 4, 0, 88,181,106, 21,174,148, +149, 97,198,196,137,176, 70, 3,242,242,242, 0, 0, 59,228,114,234,104, 86, 44,120,251,109,188,250,206, 59, 13,225,125,235,123, +235,177,245,189, 35,225,127, 43,178,178, 10,105, 83,241,183, 61,206,202, 42,252,214, 17, 30, 63, 62,255,191, 58,131, 30, 60, 30, + 15,191, 21, 22,160,176,228, 6,142,159, 59, 15,131,193, 8, 6, 4,124, 62, 31,132, 16,112, 38, 19,180,106, 13,242, 14,103, 31, +114,128,150,177, 21,255, 71,103, 62,120,155,199,127,252, 76, 30,108, 35, 4,142,193, 38,156, 44,138,204,182, 10,127, 86,218,235, + 84,192, 94,137,251, 67, 45,128,154, 50, 8,187,247, 65,197,115,247, 32,239,235,143,192, 15,234,220,240, 81,197,115,247, 32, 72, +204,192,135,223,122,113,233, 27,217,183,139,135,135,167,199, 39, 95,172,209,197,223,123,175,112,212,152,209,155,175, 93,189,198, +253,118, 53, 31,224, 40,196, 34, 17, 98, 99, 98,177,123,215,110,236,220,185,211, 41, 47, 96,223,190,125,113, 82,169,148, 90,197, +255,192,129, 3, 88,183,110,157, 1, 0, 78,156, 56, 97,144, 74,165,143, 56,210,181, 80, 84, 84, 4,203,214,196, 76, 81, 81, 17, + 50, 51, 51,145,151,151, 7,181, 90, 13,133, 66,129, 83,167, 78,161,184,184, 24, 55,110,220, 64,143, 30, 61, 80, 84, 84,212, 42, +223,188,121,243, 30,127,248,225,135,223,143,139,139,243, 58,121,242,164,143, 70,163,249,167, 68, 34,201, 6,240,169, 76, 38, 91, + 44,147,201,234, 0,252, 15,192, 8, 66,136,144, 82,106,108,205,233,152, 63,127,254,227, 63, 44, 88,176, 57, 54, 36,132,176, 11, + 23, 98,140,193,128,147,187,118,209,210,210,210,167,101, 50,217,219, 50,153,172, 18,192,198,139, 23, 47,178, 44,203,194,203,203, + 11, 97, 97, 97, 94, 70,163,177, 89,241,159, 52,105, 18,100, 50, 25,164, 82, 41,164, 82,169, 71,105,105,105,223, 27, 55,110, 64, +173, 86, 19,133, 66,209,159,207,231, 79,176, 21,127,185, 92,142, 7, 31,124, 16, 29, 5,205,117, 1,132, 2,232, 53,125,120,247, +103,187, 5,122,206,129, 81, 11,244,157,128, 51,193,211,113,223,252,175,160,173,170, 5,207,199, 27,242,143, 31,199,184, 1, 63, + 35, 32, 47,115, 60,128,238, 45,253, 64,111,159,174,248, 37,111,135,141,189,161,182,116, 19, 26, 1,163, 30,124,142, 7,198, 82, +239,119,254, 96,238,110,138,157,156,210,114, 65,189, 64,241,192, 48,219,109, 16,137,229, 54, 4,128, 64, 12,150,152,192, 89,218, +221, 89,115, 94, 0, 0,249,245, 99,235, 91,172, 89, 38,142,130,229, 24, 48, 44, 11,198,160,135,198, 98, 89,104,121, 60,120,178, + 90, 40,181, 20, 68, 64, 96, 50,153,160, 49, 1, 21,106, 3, 90,234,204,102, 13, 28,116, 2, 30, 56, 13, 11,150,171,131,170,222, + 8, 30, 17, 64,207, 26, 97,160, 6,176, 70, 3, 32,228,192, 16,128,136, 56,212,105, 77, 40,175,212, 64,173,103,155, 13,198, 48, +196,212, 96, 0, 16,242,187,158, 24,117, 90,212,213,212,128, 33, 60,240,249, 20,160,124,240,136,235, 29,127,151,175, 95, 54,244, +237,209, 87,232, 72,216,191, 81,152,148, 16, 72, 36, 18, 0,208, 2, 48,240,249,124, 20, 22, 22, 98,249,242,229, 15, 2,184,177, +104,209,162, 97,190,190,190,126,117,117,117,215,107,107,107,157, 14,119, 11, 67, 67,159, 2,128, 78,157, 58,217, 86,224,218, 79, + 63,253, 52, 11, 64,194,176,193,131, 15,182, 87, 69,152, 63,127,126,188, 35, 6,192,143, 57, 57,113, 35, 71,142, 12,150, 42,201, +129, 0, 0, 32, 0, 73, 68, 65, 84, 27, 27, 21, 5,226,237,141,229,203,151, 99,225,194,133, 16, 8, 4, 48, 42, 20,240,245,245, +197,235,243,231, 55,140, 11,112,100,112, 96,211, 62,126,123, 99, 2, 90,194,114, 39, 6,119,158, 62,125, 26,167, 79,159,110,184, +190,165, 62, 78, 69, 77, 77, 63, 47,111,111, 84, 41, 20,144, 31, 63, 14, 62,195,131,222,104,132, 70,171, 5,199,113, 13,131, 21, + 89,163, 1, 6,189,222,145, 60,230, 0, 48,150,110, 0,206,166,224,235, 44,231,241,246,170, 79,133, 0, 16, 25, 30, 94,113,237, +226, 47,109,202,215,132,228,101,228,183, 51,233,113,123,119,126, 41,111,143, 72,128, 51, 97,255, 70, 97,217,109,159, 35,234,137, +151, 33,138, 24, 98,110, 43,170,202,144, 95, 99,222, 68, 78, 52,102, 10,138, 77, 44, 60, 86, 31,111,149, 67,169, 84,250,137, 36, + 98,244,142,136, 16, 95, 43,185,209,185,186,178, 26,179, 30,157, 35,223,115, 48, 19, 31, 47, 91,149,190,115,207,174,164,200,136, + 72, 60, 62,243, 49,228,158,201,193,206,237,219,233,116, 7, 66,236,182, 94,255,129, 3, 7, 48, 97,194, 4,171,177, 40,188,121, +243, 38,158,121,230, 25,161,245,246,237,113, 85, 87, 87, 99,220,184,113, 48,153, 76, 40, 42, 42, 66, 78, 78, 14, 6, 12, 24, 0, + 95, 95, 95,116,235,214, 13, 81, 81, 81, 96, 24, 6, 12,195,160,115,231,206, 13, 81,170, 22, 60,245, 1, 67,134, 12,249,104,204, +152, 49,188,188,188, 60, 31,147,201, 84,190,125,251,118,165, 86,171, 93, 46,147,201,108, 13,216,103, 39, 79,158, 92,188,103,207, +158, 8, 66, 72, 25, 90,216,209, 86, 42,149, 14,155, 31, 31,191,113, 20,159, 79, 42,151, 46, 5, 53, 26, 33,231,241,184, 92,141, +230, 73,153, 76,246,141,173,221,241,214, 91,111,241, 25,134, 65, 77, 77, 13, 10, 11, 11, 43, 6, 13, 26, 20,210,148,111,210,164, + 73,183,253, 70, 88, 88, 88,128,137, 82,104, 53, 26, 92,188,120, 17, 44,203,146,142, 42,254,183, 25, 0,186,173,210,200, 80, 95, +201,216,201, 67,195,158,241,145, 8, 70,178, 38, 78,193,167, 38, 31,248,117,230,149,213,234,160,173,170, 3,132,124,152,106, 85, + 40, 81, 24,128,192,238, 96, 56,131, 24,173,204, 38,184,170, 84,162,143,159, 15, 88, 61,112, 53,251, 91,244,142,155,212,224,192, + 25, 13, 70, 8,192,160, 94,103,222,161,246,129,184,104, 72, 2,195, 90, 77,240, 3,131, 9,246,156,167, 16,136, 1, 97,247, 73, + 48, 20, 31,109,112, 28, 4, 66, 17,140,208,193, 75, 98,222,145,116,215,158,173,248,229, 68,118,252,156,137, 49, 45,183, 70, 28, + 7,161, 65, 11, 35,132, 96, 24, 22,208,153, 27, 54,163,209, 8,189, 78, 0, 30, 95, 0,232, 0,202,153,187, 8,122,132, 71,180, +200,165,209,113,224,241, 8,140,172, 17, 58, 61, 7,165,202, 92, 14,141, 28,133, 65,207, 1,124,128, 39,224,129, 47, 6,136,214, + 4,142,176,224,160,133, 74,107, 9, 72,219,129, 9, 0,195, 1,148, 0, 12,195,129, 16, 30, 56, 74,192, 48,150,177, 84, 28, 3, +142, 97, 64, 56,199, 28,100, 27,239, 95,232,106, 1,242,240,240,128,197,219, 15, 46, 44, 44,172, 88,190,124,121, 60,128,135, 22, + 45, 90, 52,177,103,207,158,106,149, 74, 85,205,178,108,131, 80, 56,163,255,107,214,172,249, 50, 41, 41, 9,225, 65, 65, 13, 39, +195,131,130,252, 44, 81,128,224, 63,162,194, 24, 12, 6,185,213,219,167, 42, 21,254,253,239,127, 67, 95, 93,221, 48,242,173,183, +197, 88, 17,232,245,120,240,193, 7, 43, 74, 43, 42, 30, 9,243,240,216,124, 55,210,102, 59,168,207,182,255,191, 57,196,196,196, + 32, 33,161,103,195,245,205,173, 3, 0, 0,172,222,128, 90, 67, 13,116, 58, 29,252,124,125, 33, 22,138, 96, 52,177,160,148,194, +100, 50,193, 96, 48,192,104, 52,130, 99, 77,142,230, 47,119,165,168,136,137, 12, 15,183,122, 4,220,149,162, 34,230,219,237,255, + 19,219, 70, 4, 34,195,195,107,209, 78,131,217,250, 69, 39,101,151, 20,156,106,151,103,236,234, 24,128,123, 51, 43, 81, 17,158, + 14, 97,247, 62, 32, 17, 67,208, 99,195, 89, 84,233, 56,120,242, 9, 12, 63,253,128,203,133,215,236,238,159,167,101, 13, 56,157, +123, 2, 31,173,252, 16,247,196,141,197, 91,255,239, 29,236,223,187, 31,155, 55,125,131, 49,227,199, 38,117, 11,239, 14,190,135, + 0, 7,143, 30,196,150,175,191,193,142, 31,182, 99,247,238,221,244,255,254,239,255, 72, 43, 34, 75,155, 10,191, 21,181,181,206, +111,112,167, 82,169,224,235,235,123, 28,192,168,240,240,112,196,196,196,128,199,227,129,227, 56,244,232,209, 3, 34,145, 8,117, +117,117, 8, 15, 15,135,183,183,247,117,149, 74,213,163, 37, 46,153, 76,118, 81, 42,149,166,238,216,177, 35, 49, 50, 50,178,223, +246,237,219,235, 21, 10,197,187, 50,153,108,139, 77,250,167,223,123,239,189,175,108,216,176, 97, 27,128, 10, 0,201, 0,126, 6, + 48,180, 25,190,179, 82,169, 52,213,239,212,169, 55, 30,102, 89,124, 8,112, 95,214,215, 63,214,132,239,161, 23, 94,120,225,195, +185,115,231,226,218,181,107,216,189,123, 55, 88,150, 61, 4,224,225,214,238,219, 18, 5, 96,252,120,188,106, 47,131, 1,234,179, +103,105, 48,199,169,174, 2,170,187, 45,254, 81, 81, 81, 56,119,238, 92,179, 33,127,123, 93, 0, 61,167, 15,239,190,196, 71, 34, + 24, 89,169,212,237, 63,118,165,114, 57,120, 34,224,242, 81,220, 31, 78,177,248,249, 7, 17, 51, 48, 28, 47, 72, 39, 99,106, 47, + 3,112,225, 0,168, 64,194,162,213,193, 58,181,200,175, 45, 6, 95, 4, 60, 48,245,101,108,249,100, 25, 0, 3,160,209,195,164, + 5,126,144,159, 67,214, 73,243,140,194,174,221, 35,192,240,237,139, 87,226, 80, 2,163, 14,216,181,123, 31,134, 79,124,222,236, +253, 67, 0,158, 4, 72,153,146,140,196,241,211, 0, 0, 37,215, 11,192,234, 12,173, 91,244,148,130, 37,102,129,215, 27,204,131, +255,244, 58, 45, 52, 26, 13,234,235,235,161, 82,214, 65,165, 82, 65,169,170,135,174,190, 30, 90,173,182,229,194, 95, 79,160,213, +153,160,213,153,160,214, 24,161,170,215, 67,161,210,163, 86,105, 64,157,202,136,218, 90,243,255,154,106, 22, 53, 10, 22, 53,117, + 44,170,106, 12,184, 85,213,114, 26, 25, 74, 97, 2, 64, 76, 4,132,225, 64, 9, 5, 40, 5,165, 60,152,184,223,179,143,179,180, + 30,206,198,198,251,143,233,143,156, 61, 57,216,127,104,127,131, 81,112,249,250,101,135,190,203,227,241,192, 55,231, 87, 24,128, + 94, 43, 86,172, 56, 15, 96,245,235,175,191,254, 82,207,158, 61, 89,115,144,192,156, 48, 39,197,159, 8, 67, 67,119, 2, 64,104, +104,232,109, 31, 62,247,220,115,236,169,203,151,183,158,189,112,161,221,194,186,171, 87,175,150, 59,186,111,188,209,102,138,197, +247,223,127,143,171,229,230, 46,156, 31,179,179, 27,125,118,249,242,229,144,224,224, 96,197, 31, 97,168, 36, 36,244,100, 44, 13, + 90,211, 6,191,209,231,118, 13, 60, 31,239,223, 56,147, 9,202, 26, 5,170,170,170, 80, 93,171,128, 90,163,129, 90,163,129,170, +190, 30,234, 58, 37, 84,181,255,159,189, 43,143,111,162,218,254,223, 59, 89,154,182, 64, 23,118,202, 90,164,236,178, 20,161, 5, +129, 4, 82,168, 34, 42, 74, 1,225,137,125, 5,155,226, 6, 34, 62, 84, 84,220, 80,121, 63, 11,184,210,212, 39,130,239,129, 64, +139, 11,155, 44,129,164,178,180,212,130, 11,139, 64,161,208, 66, 89, 10, 77,186, 37,105,182,185,191, 63,146, 9,105, 73,147, 73, + 90, 4, 53,223,207,167,144, 89,114, 50,115,231,206,253,158,115,238,185,231, 84,160,214,104,128,185,182, 22,172,213,235,252, 38, +211,163,107, 87,110,204, 96, 1,152, 93,167, 3, 0,224,127,155,182, 96,113,250,199,225, 0,218,250,122,223,191, 31,201,150,170, +178, 94,170,211,217,206, 30,255,225,246,186,255, 1, 92,158,218, 21, 93,190,252, 25,164,219,221, 48,229,100,163,248,159,131, 16, + 42, 36,216,151,208, 26,214,202,107, 24,178,163, 12, 94,102, 0, 48,121,242,100,242,228,220, 57, 56,115,234, 20,114, 53,251, 16, +214, 60, 12,143, 77,125, 12,225, 45, 35,113, 36,191, 0,205,196, 18,132,134,134,162,125,215, 14,248,122,253,215,120,105,209, 43, +168,169,240,191, 74,237,224,193,131,125,254, 78,243,230,205, 81, 89, 89, 57,140, 97, 24,115,167, 78,157, 48,116,232, 80,244,237, +219, 23,173, 90,181,130, 68, 34, 65,215,174, 93, 49, 96,192, 0,132,135,135,163,186,186,186, 75,243,230,205,225,133, 88,255, 47, + 39, 39,103,247, 87, 95,125, 37,210,233,116,175,214, 35,235,164,145, 35, 71,174,248,242,203, 47, 87,181,109,219,246, 93, 66, 72, + 51, 0, 47, 1, 88,236, 65,222,162,119,170,171,255,111,150,213,106,251,194,104,156, 94, 79,222,228,105,138,215,191,121,118,222, + 11,130, 83,167, 78,225,208,161, 67,248,242,203, 47,107, 0,188,204,243,246,153, 16,147, 73, 66,127,255, 29,157, 84, 42, 18, 85, + 90, 42, 0, 64,151, 45, 91,134,173, 91,183,254,161,253,173,190, 71,175, 33, 15, 95,253, 65, 32, 72,192,144,230, 37,229,250,181, + 95,231,158,123,249,151, 98,109,190,209, 70,206,224,250, 57, 72,190,121, 10,239,142,168, 70,193,155, 67,241,161,172, 6,161,223, + 61, 13,104, 47,162,134, 74,142, 58, 52,175, 6,112, 35,170,255,215,223,182,224,245,215,191,194, 93, 45,250,227,248,193, 95,177, + 75,253, 59,100,241,125,145, 48,210,222,209,168, 64, 8,179, 15,241, 17,137,131,122,225,157,255,123, 31, 59,142, 86,161, 89,215, + 62,120,224,129,137,216,185,247, 91,108,219,105,143,178,100,108, 22, 4,137, 60,143,115,148,181,193,198,218,173, 25, 56,172, 25, +179,217,140,218,218, 90, 24,141, 70,232, 13, 70, 24, 13,122, 24, 13,122, 24, 76,181, 48,155,106, 27,118,127, 25,155,163,178,198, +134, 42, 35,139, 42, 35,107,255, 92,205,162, 70,111, 69,141,193, 10,157,214,134,114,173, 5,229, 58, 11,202,203, 45,184,126,221, +140,171,215, 45, 30, 21,128, 27,238,127,151,107,230,220, 55, 2, 10, 1, 33,160,245,162,254, 41,241, 78,182, 47,206,124, 17,189, +227,123, 59,183, 85,171, 85, 78,143,192,129,237, 7,112,170,248, 20,175,100, 79, 44,107,255,173,236,236,236,253,148,210,126,147, + 39, 79,158,217,173, 91,183,214, 0, 24,150,101,131, 44, 22, 75,132,213,106,109,225, 70, 1, 96, 61,184,254, 23,127,250,233,167, +247, 79,158, 60, 25,221, 90,183,230, 53,117,213, 24,136,218,180,145, 2,192,144, 94,189,100,222,206,237,209,174,157, 44, 61, 61, + 29,199,139,139,171,190,217,181, 11, 39, 79,158,116, 90,253, 61,123,246,132,227,152,249,155, 93,187, 80, 92, 92,140, 83, 5, 5, + 70,111, 50,111, 69, 12, 0, 0, 58,122,244,232,167, 92, 73,159,251, 63, 54, 54,150,151, 59, 23, 0, 10, 79,158, 45,176, 90,173, + 48,155, 77,208, 94, 45,195,181,203, 87,112,253,202, 85, 92,191,114, 21,218,178,107,168, 40, 47,135, 73,175,183,199,207, 84, 84, + 96,144, 92,238,173, 13,173,139,211, 63, 22, 46, 78,255, 88, 8,160, 10, 0, 59,108,240,221, 55,157,228, 18, 23,192, 27, 39,142, +100, 75, 75,207, 22,168, 7, 12,189,113, 13,231,206, 28,148, 86, 92, 43, 82, 55,166,127,144, 41,186, 58,150,191, 63, 56,173,213, +163,100,246, 61,160,231,126, 67,155,207,143, 32,116,229, 97, 92,158,218, 21,177, 59,202, 64, 68, 65, 16, 18, 64,200,120, 87, 64, +159,126,230, 25,242,218,251,239,224,185, 5,243, 97, 97,109, 56,121,190, 16, 51, 30,155, 14,177, 68,130,239,191,219, 12, 88,108, + 48,213,154,176,175,224, 32,140,198, 26,164, 38, 39,231, 20, 20, 20, 80, 15,132, 72, 38, 77,154, 36, 27, 55,110, 28, 8, 33,216, +189,123,247, 77, 46,253, 23, 95,228, 31, 39,212,178,101, 75, 92,186,116, 9, 0,132, 25, 25, 25,184,118,237, 26,250,247,239,143, +240,240,112, 48, 12,131,252,252,124, 48, 12, 3, 66, 8, 46, 93,186,132,150, 45, 91,122,149,169, 84, 42,223, 53,155,205,163,148, + 74,229, 6, 23,178,126,108,228,200,145,233,179,103,207,142,200,200,200,144, 16, 66, 24, 0,223, 2, 88,160, 84, 42,175,122,145, +247,175, 67, 22,203,144,250,242,166, 45,252,102,227,163,211,159, 38,247,207,201,128,230,208, 9,164,167,167,179, 85, 85, 85, 41, + 74,165,242, 60,143, 41, 68, 0, 96,239,106,222, 60,188,211,149, 43,184,215, 96, 64,123,145, 40, 52, 84, 32, 96, 74, 75, 75,111, +138,197,249,163,148, 0,238,143,215, 20, 0,128,179, 95, 31, 60,247,140, 86,111, 58, 12,123,224, 86,251,220,194,107,153,163,122, +181, 93, 36, 60,119, 40, 18, 95, 62, 14, 4,133, 2, 38, 61, 64, 41, 44, 2,201,213,125,199, 47,127, 1,160,193,236, 75,235,214, +126, 38,155, 62, 99,166, 26, 0,244,172, 5,103, 42, 74, 0,216,112, 87,139,110,144,201,238, 70,219, 86,237, 80, 94, 89,101,247, + 21,152,173,184, 92,161, 71,111, 15, 55,213,177,115, 60, 46,150,228, 58,222, 76, 33, 18, 7,216, 99, 0,118, 28,181, 96,231,214, +108, 92,189,126, 9, 45,195,237, 43, 9,194,197, 34,220, 61,196,243,122, 80, 51,132, 16,179, 86,216, 32, 0, 75, 8, 24, 27, 11, + 88,172,176,137,132, 0, 97,192,189,147, 44,133, 61, 87,128, 7, 60, 60,237, 37,242,221,127, 23,208, 16, 49,133, 80,228,226, 97, +176, 0, 86, 10,212,154, 1,155,201, 6, 66, 8,136,152,192,106, 3,244, 38, 96, 86,242,191,137,187, 84,142, 54, 23, 13,141,101, + 88, 16,135,251,223,174, 20, 16,216, 88, 6,140,192,110,245, 51, 0,168,128, 2,148,159, 23,192,149,252,221,109, 31,216,126,160, +155,215, 41, 9,155, 13, 38,147, 9,147, 39, 79,238,155,157,157,189, 28,192,192,236,236,236, 29,217,217,217,251, 38, 79,158,252, + 76,247,238,221, 45,132,144,150, 31,126,248,225,174,151, 94,122,105,134, 86,171,205,241,160,124, 58,251,228,130, 5, 11, 22, 47, + 88,176, 0, 59,118,236,128,254,234,205,239,114,183,214,173,113,238,220, 57, 0, 80,243, 73, 12,212, 80,210, 31, 81,155, 54,210, + 79, 63,253, 84, 77, 41,197,144,158, 61,101,131,121,172, 44,232,223,187,183,134, 48,204,248,147, 63,253,212, 21, 64, 16,128,143, +184,213, 0, 61,218,183,199,252,249,243,113,224,192,129,165, 49, 49, 49, 57,253,162,162,188,198, 40,184,203, 3,224,111, 12,128, + 43,184, 60, 0,113,113, 73, 63,229,229,149, 29, 80, 40, 20, 98,199, 52,193,112, 0,185,124,147, 0,117, 29,208,231, 21,227,229, + 43,227, 88,171,173,151,190,178, 18,149,215,175,129, 16, 6,148,178,168,173,173, 5,165, 20,148, 82,156, 59,241, 59, 44,102, 19, +238, 26, 18,235,173, 13, 93,199,156,112, 0,204,253,178,209,236,253,178,209,117,130,254, 28, 83, 4,188,113,242,151,111,164,151, +206, 22,168, 1,160,107,151, 46,248,190,158, 23,160,117,231,193, 50,220, 70, 12,249,161, 12, 5,247, 1, 3, 99,229, 40,123,122, + 56,218,125,118, 16,167,181,122, 68,136, 9,202,181, 58, 8, 9,241,234, 1,224, 48,115,230,204, 58,103,110,217,178,133,222, 63, +225, 62,108,221,188, 21, 27, 55,110,196, 27,139, 94,195, 46,205, 30, 8,132, 2, 68,117,140, 26, 93, 89,233,121,233,114, 98, 98, +162, 38, 49, 49,145,236,216,177, 67, 58,110,220,184, 58,177, 0,187,119,239,198,153, 51,103,106,149, 74,101,123, 62,215,214,181, +107, 87, 20, 21, 21,161, 79,159, 62,214,121,243,230,137,215,175, 95,143,176,176, 48,156, 60,121,242, 38,207,107, 81, 81, 17,186, +242,124,206, 74,229,141,196,115, 10,133,226,241,123,238,185,231,173,199, 30,123, 44,172,160,160,160,121,109,109,237, 63,131,131, +131, 31, 48, 26,141, 31, 40,149,202,239,121,202,251,197, 85,222, 3,207,174, 95,115,239,216, 73,228,223, 42,128,116,120, 16,239, +174,120,133,106, 11, 79,166, 40,149,202, 44,111,178, 92,188,108,164,218, 98,169, 16, 7, 5,161,133, 88,140, 96,155,205,164,183, +217,108,183,131,252,249,162,142, 2, 32,121, 76,121, 92,251,181,226,180,228, 49, 37, 55,165, 89,114,236,107,197, 15,213,181, 86, +253,176,187, 90,221, 31, 25, 34,184, 71, 96,170, 13,181, 82,166,186,188,218,156,151,123,230,202,206, 82,173, 33, 71,242,152,242, + 50, 86,174,116,251, 3, 53,250,214,154,180,167,231,200, 0,168, 89, 1, 55,205, 39,192,153,170,203,120,253,153, 20, 24, 12, 38, + 84, 25,237, 49, 0,102, 38, 8, 99, 18, 61,167,217,125,109, 81, 50,217,177,109,136,253,229,182,113,150,179, 21,137,253, 9,166, + 61,181, 12, 33, 33, 65,104, 17, 44,145, 1, 80, 23, 30, 59, 34,139,239,231, 57, 33,136,144, 90, 97, 38,118, 37, 0,132,192, 70, +169, 93, 17,224, 18, 54, 16, 6, 66,150,133,149, 91,118,224, 69, 9,168, 48,134,195,104, 42,135, 88,200, 56,211,156, 89, 89,192, + 98,161,176, 88, 41,106,140, 44,136,128,192, 6, 2, 11,123,195,117,239,150, 96, 89, 6, 12,177,129,216, 8, 40, 67,157,238,127, +210,128,241,204, 73,122,238,121, 25, 89,185,242,164, 71, 11,239,247,220,223, 27,219,119,204,148, 82, 24,141, 70,244,239,223,255, +114,116,116,244,164,243,231,207,247,216,184,113, 99, 62,128,135,178,179,179, 31,114, 61,249,253,247,223,215,188,244,210, 75, 50, +173, 86,235,141, 32,156, 13,146,150,150,214,224, 73,143, 62,241, 4, 0,223, 18, 3,113, 89,247,234, 99,104,239,222, 62, 45, 43, +236,215,179,231, 46, 87, 79, 70,122,122,250, 39, 19, 39, 78,180,158, 58,117, 74, 88, 92, 92,140,174, 45, 91,230, 70,133,132,240, + 10, 80,188, 21,121, 0,234,145,251,213,156,156, 28,215, 24,143,163, 14, 69,128,111,198, 64,125,112,251,118,143,158,220,179, 55, + 55, 60, 52,180, 69,149,174, 2, 86,171, 21,212,241, 30,232,174,150,161, 74,167, 3,165,148,143,245,111,127, 89,111,196,156, 48, +142,229,128,140, 99,217,159, 51, 49, 80,225,249,243,252,149, 0,195,175,210,139,133,249, 78, 43,255,251, 44,251,242,191,214,209, + 35,100, 3, 98, 39,106,110,223,240, 74,111, 86, 2,240, 57, 6,166,189,142, 43, 44,139, 1,171,243,145,159,216, 22,125,183, 94, +133,144, 0,205, 69,254,173,152,157, 56,113, 34,217,171,217, 75,199, 36,140,197,230, 77,223,225,237,165,239, 99, 97,101, 37, 40, +203, 98,195,134, 77, 40, 45, 45,125, 0,128, 87, 31,180, 59, 69, 0, 0, 38, 77,154,244, 11,128,106, 62,215, 18, 31, 31, 79, 46, + 93,186, 68,143, 28, 57, 34, 30, 60,120, 48,198,142, 29, 11,181, 90,141,206,157, 59,195,100, 50, 97,244,232,209,160,148,178, 71, +142, 28, 97, 68, 34,145,207, 25, 1, 21, 10, 69,159,176,176,176,229, 83,167, 78, 21,157, 56,113,162,133,201,100,106, 40, 48,144, +175,188, 65, 81, 3,167,172, 25, 56,106, 42,249, 34, 7,168, 50, 2,230,115, 59, 88,109,161,186,126, 96,160, 39,101,130, 83, 2, +132,218,202, 74,171,216, 98,129, 65, 44,134,208,158,245,135,253,163,123, 29,151, 7,192,213,242,119,183,207,173, 43,213,133,252, +185,237,223,139,191, 86,148, 20, 95,175,201, 5,208,222,241,242,154, 0,148, 2, 40,146, 60,166,244,234,226, 28, 60,224, 65,205, +241,223, 74,100, 54,218, 76,237,250,114,212,232,171, 32, 16,134, 1, 76, 8,254,245, 1,255, 20,147,137, 19,250,145,119,230, 60, + 32, 5, 99, 80,187, 54,111,179,102, 97,176, 89,116, 0,213,163,248, 96, 38,153, 57, 45,209,171, 44, 11, 4, 0,165,118,162,134, + 0, 98,234, 80, 4, 28,228,111,207, 1, 8,128,231,218,205,228,212, 87, 73,230,199,111, 80,171, 69, 11,161, 99, 97, 47,165, 20, + 54, 43, 69,173, 5,168,170,182,194, 2, 10, 43,101, 32, 20, 17, 44,121,235,147, 6,239,123,246,108,123,144,214,154,213,103, 40, +177,216,173,127, 10,128, 82, 2, 80,135,197, 64, 5, 32, 2, 22, 44, 43,196, 11, 11,198,241,106,195,217,111,207,150,157, 63,123, +222, 19, 1,139, 96, 95,170,225,137,157, 88, 0, 48,153, 76,208,233,116,186,176,176, 48,196,198,198,254, 58,116,232,208,160,107, +215,174,225,236,217,179,246,229, 97, 44, 43,221,180,105,147,218,161, 4,168,121, 40, 1,150,164,196,196,164,174,253,251,219,238, +233,213, 75,239,232,163, 38,212, 93, 17,137,164, 68,251,179,237,202, 35, 41,208,139, 47,190, 40, 3,128, 33, 61,123,222,116, 44, +118,192,128, 70, 17, 68,255,222,189, 63, 99, 24,198,118,242,167,159, 66,219,182,109,123,189,223,240,225,107,110,167, 70,239,134, +212,245,177,177,177,174,209,214,206,117,172, 62, 40, 1, 39, 6,141, 29, 51,108,243,127,190,216, 20,221,173,107, 31,147,169, 22, + 54,139, 21, 44,203,162,121, 68, 4, 42,181, 90, 12,146,203,101, 60,172,127, 0,168,120,243,133,103,219, 0, 48, 23,158, 63, 47, +230,230,255, 15, 29,249, 13,247,203, 70,179,139,211, 63,246,150, 28,200,137,152,246, 58,122,242,212, 73,217,222,157,223,215,113, +241,143, 25,255,144,140,105, 17,223,168,231,218, 80,128,159,251,253,252, 57,108,200, 15,101,192, 15,207, 56,183,239,250,254,198, + 18,224, 74,139,255,235,195,199, 72,199,144,175, 74,190,186,111,220,132,196,237, 79, 62, 62,107,255,221, 3,250,223,187,249,251, + 45,200,253,229, 48, 82, 83, 83,183,173,108,192, 64,243,162, 8,204,250,246,219,111,255,243,237,183,223,198, 37, 38, 38,242,190, +184,113,227,198,141,217,181,107,215,222,173, 91,183, 34, 58, 58, 26, 9, 9, 9, 8, 11, 11, 59, 93, 89, 89, 25,115,252,248,113, + 20, 21, 21, 49, 34,145, 8,227,198,141,147,251,122,159,142,192,192,165, 91,182,108,105, 48, 48,208, 71,121, 63, 43, 20,138,247, +190,203,126,240, 21, 99,212, 12, 24,127,122,149,189,180,111,201,227,190,202,115, 40, 1,181,197,101,101,162, 23, 78,159,190,104, + 51, 24,152, 95, 25, 70,212, 78, 32,184,162, 80, 40,110,203, 20,128,187,108,128,222,166, 0,220, 66,242,152, 82, 15,224, 55,199, +159, 95,120,252,241,103, 52,105,105, 47,201, 50,148,111,171,163,186,244, 0, 96,130, 40, 72,130,139,151,171, 48,122,226, 76,226, +187,188, 7, 53,119,245,138,193,234, 85,223, 0,108, 49, 0, 33,172,181, 70, 68,181, 15,147,117,110, 97,229,255,242,219, 88, 8, + 25, 22, 22, 34,132,136, 90,111, 40, 2,176, 2,212, 6,190,129, 97,174, 72,125,246, 13, 2, 0,139, 95,158, 67, 69, 66,187,181, +111,101,237, 46,243,138,106, 10,155, 21, 16, 8, 89,124,246, 41, 63,165,231,137,100,123,106,228, 85, 95,156,162,224,114,194, 51, + 0, 75,236,238,254,249, 11, 30,240,233, 34, 43,107, 42, 53, 17,109, 35, 26,219,191, 24,192,190,138,194,104, 52,194,102,179,161, +170,170, 10, 2,129, 0, 54,155, 13,237,218,181,131,197, 98,129, 82,169, 84,215,243, 4,168,189,213, 12, 24,212,191,127, 54, 0, + 52, 69,198, 63, 0,136, 36, 68, 3, 0,145, 3, 6,220, 18, 51,175,111,207,158, 25,141, 17,240,194,226,197,117, 86, 73, 44,120, +227,141, 58,158, 1, 95,230,254,221,144,185,222,211,106, 0, 31,210, 1,159,124,112,246,172,126, 0, 4, 39,115,114, 44,181, 6, + 35, 88,155, 13,189, 99, 99,101,237, 99,250,160,235,128, 62,252,222, 57, 74,166,238,252, 97,155,115,115,120,159,104,231,231,157, + 63,108,187,105,219, 83,104,252,233,203, 17,132,105, 17,143,177,227,137,236,196,201,179,184, 92,124, 84, 13, 0,123,119,126,175, +110,219,249,172,172,255,176,127,248,172, 4, 76,153, 50, 5,190,166,247,181, 17,207,121,183, 75, 38,181,195, 15,151,106,111,249, +128, 63,115,230,204, 31, 0, 48, 5, 5, 5,236,158,188, 28,180,108,213, 18,141,169,207,145,152,152,248, 69, 98, 98,226, 87,240, +158,222,185, 14,154, 55,111,174,126,244,209, 71, 73,110,110, 46, 61,123,246, 44,242,243,243, 81, 93, 93, 29,211, 20,181, 0, 28, +100,251,127, 10,133, 66,148,155,155,219,223,108, 54,191,234, 58,151,239,167,188, 69, 10,197, 63, 68, 97,221,191,154, 95,121,118, +215,140, 70,200,179,174, 63,116,232, 1, 0, 9, 0,126, 6,203, 86, 3,184, 58,109,225, 55, 72, 13,123, 4,153,149,127,140, 18, +192,173, 2,112,183,223, 47, 5,192,215,169,132, 6, 93, 85,143, 60,161,217,182,243, 12,121,120, 66, 8,109, 19,213, 9,218,106, + 43, 70, 79,120,220,239,142, 16,127, 79, 47, 18,127,207, 43, 80, 40, 94,167,192, 85, 68, 52, 23,162,115, 36,235,211, 75, 63,228, +159, 11,110, 89,150,176, 55,223, 91, 73, 0, 96,238,188,103,168,217,104, 1, 11,251,178,185,229,159, 46,247,235, 55, 83,102,217, +107, 6,172,250,207, 73,202, 82, 1, 94,126,233,161,219,153,225, 76,236,234,198, 54,153, 76, 48,155,205, 78, 34,227, 8, 44, 80, + 37,208,139, 11,210,135,244,195,126,194,188,112, 97, 82,144,195,131,210,216, 20,100, 20,128,181,215,232,209,117,174,185,107,251, +118,188, 5, 4,177, 38,205, 19, 19,125, 54,252, 80,191, 20,112, 29,251,187, 69,156,166,239,208, 56,244, 29,138, 70,183,165,183, +194, 62,245,117, 96, 43, 9,130,145,241,188, 34,245,108,181, 21, 49,205,249, 12,145, 77,210, 21,232,144, 33, 67,154,178, 79, 89, +252,253, 98,124,124, 60,241,150,136,173, 17,164,253,174, 66,161,248,206, 53, 54,160,145,242,254,165, 80, 40,214,185,198, 6,248, + 33,195, 2,160, 2, 64,189,184,129,107,127, 24,249,123, 34,123,183, 61,110,224,192,129,119,106,249,200, 0,254, 68,232,209,163, + 7, 10, 11, 11, 3, 13, 17, 64, 0, 1, 4,240, 39, 1, 19,104,130, 0,154, 2, 1,242, 15, 32,128, 0, 2, 8, 40, 0, 1, 4, + 16, 64, 0, 1, 4, 16, 64, 64, 1, 8, 32,128, 0, 2, 8, 32,128, 0, 2, 10, 64, 0, 1, 4, 16, 64, 0, 1, 4,112,219, 81, + 39, 52,117,206,156, 57,126, 71,143,186,203,100, 23,144, 23,144, 23,144,119,103,200, 83, 40, 20, 84,169,108,120,217,105,160,253, + 2,242, 2,242,254, 90,242,124, 86, 0,184,129,194, 87, 33,158, 6,150,166,150, 23,192,157, 9,111, 4, 19,192,157,249, 28,124, + 60, 63, 20,192, 61,251,247,239, 95, 34, 16, 8,134, 7, 5, 5,193, 96, 48, 28,188,247,222,123, 23, 1,200, 7, 96,184, 19,218, + 64,165, 82, 73,179,178,178,212,127,197,113,229,216,177, 99,200,207,207,247,122, 94, 94, 94, 30, 61,118,236, 24, 50, 51, 51, 73, +191,126,253, 26, 45,143,195,208,161, 67,225, 73, 94, 0,127, 98, 15, 0, 7, 95,210,147,242, 73,148,227, 78, 94, 67,229, 97,253, + 73,188,243, 87, 31,208,249,158, 59,126,252,120,217, 35,143, 60,162,225, 43, 51, 42,234,230,210,203,165,165,165,117,182,147,146, +146, 32,151,203, 9, 31,121,183, 82, 9, 24, 63,126, 60, 5,128,157, 59,119,146, 59, 65,158, 94,175, 31,187,105,211, 38,213,233, +211,167, 1, 0,209,209,209, 15,166,164,164,108,241,247,249,186,246,123, 74,169,243,253,224,246,115,239, 10, 33, 4, 25, 25, 25, +196,147,242,204,247, 57,248,248,188,250, 28, 59,118,108, 83, 85, 85, 85,175, 46, 93,186,224,250,245,235,168,173,173, 5,128,225, +155, 54,109, 82,135,134,134,158, 76, 76, 76,124, 24,128,199, 82,146, 35, 70,140,240,201, 32, 56,112,224,128, 12, 60, 83, 61,115, +200,202,202, 82, 39, 37, 37,201,228,114,185,198,215,231,145,154,154,234,211,245, 77,153, 50,133,247,251,193,161, 75, 23,123, 5, +220,234,234,106,152, 76, 38,174, 63,241,122,223,242,243,243,241,223,255,122,206, 80,107, 50,153,232,240,225,195,209,187,119,111, +172, 93,187,182,204,100, 50,117,110,104, 93,120,126,126, 62,102,204,152,193,235, 94,175, 94,189,138, 37, 75,150,224, 78,206,109, + 31,192, 13,212, 79, 6,116, 43, 19, 1, 5,172,216, 91,136,239, 51,188,167, 52,126,120,206, 14,159,100,170,213, 55, 12,164,211, +167, 79, 35, 52, 52,212, 57, 8,185,180, 7, 31,107,139,214,223,174, 63,128,169, 84, 42,154,149,149,229,183, 5,182,110,221, 58, +233,248,241,227, 27,148,223, 24,164,165,165,209, 81,163, 70,201,166, 79,159,238, 19, 89,108,218,180, 73,213,166, 77, 27,204,156, + 57, 19, 58,157,142, 77, 79, 79,223,172,211,233,166, 69, 68, 68,248,148, 69,140, 16,130, 31,126,248,193,185,157,152,152,136, 29, + 59,118,120,220,246,134,250, 74,128, 66,161,160,177,177,177,200,204,204,164, 92, 98, 38, 95,201,191,178,178, 50,183,123,247,238, + 45, 0, 64, 34,145, 32, 56, 56, 24,101,101,101,168,168,168, 64, 88, 88, 24,202,202,202,122,237,216,177, 35, 63, 49, 49,177, 39, +128, 43,158,132,245,235,215, 15, 73, 73, 73,136,142,190,145,245,111,233,210,165,117,206, 89,184,112, 33,103,201,170,167, 79,159, +238,243,243,246,135,252, 57,172, 88,177,162,161, 67,206, 90, 5,254, 34, 52, 52, 20, 39, 78,156,128, 72, 36,130,217,108,198,142, + 29, 59, 80, 88, 88,136,151, 95,126,217, 39, 57, 87,235, 21,201,122,240,193, 7, 5, 0,228, 63,254,248,227,142,209,163, 71, 95, +125,248,225,135,219,170, 84, 42, 8, 4,130,214,225,225,225, 2, 95,100, 53,132,243,231,207, 7, 72,226, 79, 74,254,220, 62,175, +181, 0,254,172, 88,181,106,149, 52, 37, 37, 69,211, 88, 57,127, 22, 87,118,212,144,119,110, 88,237, 5,175,250, 37, 67,167,211, +193, 96, 48, 56, 45,144,204,204, 76, 87, 75,136,175,181,117,211,182, 92, 46,199,238,221,187, 41, 33,228,166,227,254,224,199, 31, +127, 84,191,248,226,139,200,206,206,198,228,201,147,155,164,253,118,238,220, 73,246,236,217, 67, 41,165,200,201,201, 81,231,228, +228,248,164,160,156, 62,125, 26, 51,103,206,100, 1, 48, 98,177,152,137,137,137, 65,122,122,250,122, 0,235,163,163,163, 39,164, +164,164,108,231, 35,231, 86, 20, 3,226,148,128,204,204, 76,202,165, 1,230,254, 87, 40, 20, 52, 41, 41,201,151,123, 13,213,233, +116,155, 36, 18, 73, 11, 0,120,250,233,167, 81, 91, 91,139,140,140, 12, 4, 7, 7, 59,203,102, 11, 4, 2, 84, 86, 86,182, 0, +144, 14,224, 31,158, 4,114,228, 94, 84, 84,116,211,190,166, 64, 82, 82,146,204,113,159, 50,127, 21,129,231,159,127,222,249,121, +249,242,229,220, 71,166,222,126,222, 10, 1,231, 53,121,245,213, 87, 17, 26, 26,138,236,236,108,140, 30, 61,218, 47,242,175,143, +145, 35, 71, 2,246, 44,141,255,124,252,241,199,209,163, 71,143,182, 59,118,236, 64,121,121, 57, 87,114,215,236,229, 93,104,234, +238, 39,157, 48, 97,130,122,219,182,109,238,188, 55,210, 49, 99,198,168, 9, 33,216,179,103, 79,192,221,123,139,201, 63,117,225, +251, 0,128,204,165, 47,185, 85, 2,254, 16, 5, 32, 51, 51,211,221,131,166, 13,237,247,231, 55, 14, 29, 58,164, 6, 32,107,172, + 18, 48, 99,198,140,191,205,124,182,193, 96,184,201,234,247,135,104, 56, 98,153, 60,121, 50, 18, 18, 18, 8, 0,100,103,103, 55, +201, 53,174, 91,183, 78,234,176,232, 72, 89, 89,153, 52, 43, 43, 75, 93, 86, 86, 38,245,213, 98,119,135,177, 99,199,146,177, 99, +199, 98,221,186,117,210,156,156, 28,245,186,117,235,124,146,171,211,233,172, 17, 17, 17,226, 77,155, 54,193,225, 13,168,213,233, +116, 76,122,122,250, 54,157, 78, 55, 46, 34, 34, 98,247,237,124,190, 28,233,187,246,101,133, 66, 65, 57, 37,141, 39,238, 41, 44, + 44,236,213,191,127,127,204,154, 53, 11,149,149,149, 40, 47, 47,135, 72, 36,130, 80, 40,132, 80, 40,132, 72, 36, 66,112,112, 48, +180, 90, 45, 84, 42,213,116,185, 92,254,172, 55,161, 69, 69, 69,117,148, 67, 78, 1,224, 60, 1,177,177,177,190, 92,163, 59,235, + 95,150,149,149,165,110,140,231,201, 5,214, 6,198, 74,222,222,128,243,231,207, 35, 39, 39, 7, 19, 38, 76, 64,151, 46, 93,208, +170, 85, 43,228,228,228,224,229,151, 95,118,122,223, 4, 2,129,207, 23, 54,114,228, 72, 44, 90,180, 8, 75,150, 44,105,159,146, +146, 50,245,177,199, 30, 67, 66, 66, 2, 0, 64, 32, 16,204,108,217,178,229, 22,165, 82,105,241, 84, 12,104,221,186,117,188,188, + 0,165,165,165,152, 54,109, 26, 63, 3, 37, 42, 10,169,169,169,234,162,162, 34,168, 84, 42,174,253,165,169,169,169,106, 78,129, + 14,224,214,130, 35,127,238, 51,167, 4,252,225, 30,128,134,230,177,253, 9, 16,188,213, 74,192,253,247,223,223,104, 79,128, 47, +247,229,203,111, 60,250,204, 78,108,250,100,124,147,180, 21,247, 2, 54, 84,169,234,224,193,131,141, 86, 12,154,226,249,254,248, +227,143,106,206,234,159, 62,125,186,230,199, 31,127, 68,155, 54,109,212,104,162,196,233,156,220,156,156, 28,228,228,228,120,117, + 55,235,245,250,251, 55,109,218,180, 13, 0,210,211,211,197,209,209,209, 72, 73, 73,225, 14, 75,126,251,205, 94, 47, 43, 61, 61, +125, 87,116,116,244,195, 41, 41, 41, 94,235,147, 39, 38, 38,214,137,137,185,239,190,251,234,120, 6,248,184,253,221, 40,221,212, + 93,255,226,158,139,235,116,128, 39,236,216,177, 99, 73, 76, 76, 12, 0,224,204,153, 51,160,148,226,212,169, 83,206,186, 15, 66, +161, 16,132, 16,216,108, 54, 24, 12, 6,124,251,237,183,144,203,229, 94,171, 46,185,146,127, 82, 82,146, 91,229,197,117,138,192, + 31, 37, 64, 46,151, 19,133, 66, 65, 27,235, 13,104,138,113,210, 98,177, 96,240,224,193,208,104, 52, 24, 50,100, 8,244,122,189, +115,106, 71,163,209, 96,252,248,241,176,114, 37,200,125,179,252,177,100,201,146, 14, 41, 41, 41, 23,191,248,226, 11,231,177, 14, + 29, 58, 96,217,178,101,255,229, 75,216, 77, 12,205,225,195,135, 17, 27, 27,139,232,232,104, 12, 30, 60,152, 30, 57,114, 68,198, +145,127, 81, 81, 17, 52, 26, 13,159, 24,149,161, 0,158, 1,240, 79,165, 82,105,243,112,222, 4, 0, 81, 0,190, 85, 42,149,215, + 2,212,255, 7,118,108, 62,248, 35,131, 0,155, 66, 9,232,218,181,107,163, 60, 1,220, 32,187,118,237, 90,183,199,183,111,223, +142,181,107,215,250,101,153,228,157,235,131,184,110, 39,252,118,251,115,112,157,243, 87,169, 84,144,203,229, 78,183,255,193,131, + 7,209,169, 83,167, 38, 81,250, 26, 99,125,113,214,255,245,235,215,157,117,230,165, 82,169,172, 41,189, 0, 28, 70,143, 30, 45, +203,201,201, 81,123, 59,111,211,166, 77,219,184,185,127,189, 94,143,165, 75,151,162,166,166, 6, 34,145, 8, 65, 65, 65, 56,119, +238, 28,222,121,231, 29,232,116, 58,164,167,167,127,167,211,233,198, 68, 68, 68,168,189,144,108, 29,178,247, 22, 19,208, 20,138, +231,225,195,135,235,156,223, 80,144, 88,100,100,228,112,147,201, 4,171,213,138,131, 7, 15, 66, 32, 16,192,108, 54,195,104, 52, +130,101, 89,231,123,108,177, 88, 96, 50,153,184,119,218,107,152,120, 67, 46,255,133, 11, 23, 58,189, 0,209,209,209, 40, 43, 43, +107,180, 34,202,173, 10,240, 33,118, 68, 11, 32,210,221, 1,151,233, 0,159,144,158,158,142, 23, 95,124, 17,131, 6, 13,114,122, + 64,184,244,217,131, 6, 13,194,169, 83,167,208,166, 77, 27,159,100,238,219,183, 15, 35, 71,142,236,146,146,146,114,158, 35,127, +199,248, 25,181, 97,195,134, 75,245, 3,122,249, 42, 20, 13,253,150,143,222, 39,114,248,240, 97,105,106,106,170,122,200,144, 33, + 24, 50,100,136, 26, 0, 78,157, 58,133,156,156, 28,190,207,225, 23, 0,193, 0,214, 43, 20,138,105,238,148, 0,133, 66,241, 12, +128,143, 29,155,139, 20, 10, 69, 47,165,210,123,137,250,191, 50,184,106,128,153, 75, 95,186,105, 10,224, 47, 27, 3,112, 39, 42, + 1, 51,102,204,160,139, 22, 45,186,201, 21,232, 15,249, 63,250, 76,211,206,211,233,245,250,155,130,252, 56,171, 95, 36, 18,225, +202,149, 43,183,149,252, 93,173,127, 87,203,109,218,180,105, 26,141, 70,211,228, 94, 0, 95, 60, 39, 51,103,206, 52, 0, 8, 9, + 13, 13,197,107,175,189, 6,145, 72,228, 60,158,156,156, 12, 0,136,136,136,192,196,137, 19,177,127,255,254,189, 19, 39, 78,252, + 67,174,211,181,189, 93,231,255,221, 33, 54, 54,182, 78,165,198,134,214, 17,155,205,102,104,181, 90,212,214,214, 34, 44, 44, 12, + 65, 65, 65,176, 90,173,160,148,194,102,179,193,108, 54,195, 98,177,192,102,179,185, 42,244,215, 61, 93,103, 81, 81, 81, 29,235, +190,254,116, 64,253, 0,193,198, 66, 46,151,107,124,140, 69,145, 52,116,160,129,216, 0,175,120,231,157,119, 48, 97,194, 4,116, +237,218, 21, 33, 33, 33,144, 74,165,208,106,181, 8, 13, 13,133, 78,167,195,234,213,171,193, 48,190,197, 23,142, 28, 57,178, 99, + 74, 74,202,249,121,243,230, 97,243,230,205,120,232,161,135, 0,160,221,190,125,251,174,250,211, 78, 14,133, 2,220,152,197,141, + 85,190,146,191,171, 39, 96,195,134, 13,178,169, 83,167,170, 1, 96,195,134, 13,178,202,202, 74,141, 15,253,217,172, 80, 40,102, + 0, 88,235, 65, 9, 72,112,249,220, 25, 64,127,216,151,164, 6,224, 66,252, 13,225, 47,153, 9,112,216,176, 97,178,166, 8, 8, +244,215, 74,119, 29,144,151, 44, 89,210,104,242,231, 48,120,208, 64,236,217,171,198,186,189, 33, 78,165, 32,239, 92,159, 70,221, + 99,108,108, 44,138,138,138,144,157,157,141, 78,157, 58, 97,205,154, 53,126, 88, 93, 84,202,125, 74, 75, 75,107, 18,242,231,172, +255,178,178, 50, 89,253, 99,163, 70, 43, 88,140, 99, 0, 0, 32, 0, 73, 68, 65, 84,141,146,101,103,103, 59,207,105, 10,228,228, +228,168,249,122,159,116, 58,221,239,176,207, 11,179, 27, 54,108,192,234,213,171, 1, 0,235,215,175,135, 78,167,227, 78,179,158, + 58,117, 10,173, 91,183,190, 45,239,128,107,180,191, 59,229,140,111,153,230,162,162,162,131, 54,155, 13, 58,157, 14,215,175, 95, +119, 6,142, 26, 12, 6,212,212,212,160,170,170, 10,149,149,149, 48, 26,141, 48,153, 76,176,217,108, 0,144,235, 73,102,125,114, +119, 23, 72, 90,127, 85, 0, 95,168, 84, 42,105,253,123, 86,169, 84,190,246,147,144,166,126, 30,107,214,172,129, 84, 42, 69, 72, + 72, 8, 78,156, 56, 1,141, 70,131,208,208, 80,188,254,250,235,216,191,127, 63, 94,126,249,101,159, 20,128,145, 35, 71,182, 75, + 73, 73,185, 48,109,218, 52,124,243,205, 55, 28,249,119, 0,112,213,147, 37,207, 71, 9, 88,178,100, 73, 83,144, 63, 0, 72, 57, +242, 7,128,169, 83,167,170, 71,143, 30, 77,125, 28, 67,205, 0,184,117,138,235, 21, 10, 69,253, 64,137, 51, 46,159, 75, 0, 28, + 13,208,190,203, 56,176,240,253, 58,177, 0,245,241,151, 9, 2,108,106,242,119,172,119,109,180,229,198, 77, 7,204,152, 49,195, +111,242,127,244,153,157, 24, 60,232,134,235,102,211, 55,223, 98,211, 55,246,207,123,246,170,129, 49, 50, 0,190, 45, 3, 84, 40, + 20,136,141,141, 5, 96, 15, 6, 60,124,248, 48,118,239,182,199,172, 29, 61,122, 20,163, 71,143,246, 65, 26,209, 0, 55, 2,255, + 26, 27,169,191,110,221, 58,169, 59,235,191, 62,154,202, 11,192, 41, 18, 82,169, 84,230,237,220,232,232,232,113,233,233,233,187, + 38, 78,156,136, 83,167, 78,225,244,233,211,120,231,157,119,172, 0,132, 6,131, 1,233,233,233,112, 28, 19, 22, 23, 23,227,241, +199, 31,247, 42,243, 86,196, 0,112,150,116, 86, 86,150,211,139,197, 17, 35,247,220,249, 32, 38, 38,166,192, 96, 48, 12, 55,155, +205,184,118,237, 26,130,130,130, 32, 20, 10,157, 30, 0,189, 94, 15,131,193, 0,147,201,132,202,202, 74,110, 62,255,162, 39,153, + 28,185,115,211, 0,177,177,177,168,239,173,112, 23, 23,192,135,252,185, 28, 0,245,247, 53,166,127,112, 86,191, 27,139,223,202, +119, 12, 45, 44, 44,196,169, 83,167, 96, 48, 24, 16, 31, 31, 15,131,193,128,172,172, 44, 76,157, 58, 21,155, 55,111,134, 64, 32, +224,173, 0,196,196,196,116,228,200, 63, 63, 63, 31,111,188,241, 6, 0,116,158, 49, 99,198,229,181,107,215,146,125,251,246, 53, +106, 12,229, 60, 1,141, 33,255,216,216, 88,202,245,179, 35, 71,142,160,160,160, 64,150,154,154,170,238,217,179, 39, 68, 34, 17, +117, 9, 12,244,219, 19,160, 80, 40,230, 2,152, 0, 96, 50,128, 54,176,199, 0,252,173,221,255,192,141, 85, 0,238,130, 0,111, +203, 42,128, 63, 42, 8,240, 78, 35,255,250, 74, 64, 99, 44,127, 79,219,123,246,170,253,121, 65,111,152, 59, 33, 33,232,221,187, +119,157,227,135, 14, 29,242, 73,222,228,201,147,157, 10, 64,118,118, 54,178,179,179,235,172, 10,240,229,254,215,172, 89,163, 6, +128, 29, 59,118,184, 37,207,233,211,167,107,214,172, 89, 3,128,223, 18,166,134,146,254,112,138, 6,165, 20,163, 71,143,150, 77, +155, 54,205,107,223, 73, 73, 73,217,173,213,106,199, 30, 56,112, 96, 79, 76, 76, 12, 78,159, 62, 13,157, 78, 39,140,136,136, 64, + 74, 74, 10,180, 90,109,241,129, 3, 7,186,196,196,196, 96,230,204,153, 94,239,215, 93, 30, 0,127, 99, 0,234,191, 91, 74,165, +146,200,229,114,168, 84, 42, 90,127, 90,134,239,243,136,139,139,123, 69,163,209, 60,103,179,217, 80, 85, 85, 5,139,197,226, 84, + 86,106,107,107, 65, 41,173, 19, 24, 40,151,203, 31,115, 16, 35,111,200,229,114,200,229,242, 58,203, 2,125,157, 2,112, 37,122, +185, 92,174,169, 63,182,184, 42, 5, 77, 8,222,227, 39,183,212,239,133, 23, 94,128, 70,163,129, 76, 38, 67, 97, 97, 33,154, 53, +107,134,146,146, 18,222, 10,192,161, 67,135, 72, 74, 74,202,133,199, 31,127, 28,251,246,237,195,235,175,191, 14, 0, 81, 51,102, +204,184,212, 20,228,239,170, 4, 52,198,242,231,198,151,162,162, 34, 20, 20, 20, 16,135, 33, 40, 75, 77, 77, 85, 71, 71, 71, 67, + 42,149, 82, 62,129,128,245,148,128,105, 0,214, 59,148,128,131, 0, 20, 0,164, 74,165,242, 10, 2,104,186, 14,220,212,217,248, +220, 5,252, 44, 93,186,180,193,253,183,147,252,103,204,152,113, 75, 82,134, 54, 70,230,133,139,222,251,119,112,176,111, 94, 75, + 79,243,195,254, 64, 46,151,203, 18, 18, 18, 52,123,246,236,161, 27, 55,110,172,163, 8,212, 39, 37,190, 50,211,210,210, 26,212, +108,184,164, 36,190, 36, 6,106, 72,225,148,201,100,188,200,159, 67,100,100,164,115, 94,255,196,137, 19,255, 72, 79, 79,255, 47, +231, 17, 40, 46, 46,238,242,234,171,175,202, 8, 33,188,228,221,138, 60, 0,245,219,217,221,252,183, 15, 74,169,126,244,232,209, +139,183,111,223,254,166,213,106, 69, 69, 69,133, 51, 6, 0, 0,174, 93,187,134,138,138, 10, 80, 74, 57,171,221,167,201,118,110, +254,191,254,178,191,250,113, 2,124,201,223,245, 57,223,105, 75,121, 57, 37,224,165,151, 94, 66, 78, 78, 14, 38, 78,156,136,247, +222,123, 15, 11, 22, 44,128, 80, 40,132, 68, 34,241,246, 92, 9,165,148,157, 53,107, 22,254,251,223,255, 98,213,170, 85, 0,208, +105,223,190,125,151, 28, 22,187, 95,157,201,101,218,170,201, 80, 90, 90, 10, 55,121, 0, 52,153,153,153,178, 49, 99,198,168,253, + 89,242,232,176,250,167, 1,216, 10, 96, 46,128,184, 0,249, 55, 12,119, 65,128,188, 20, 0, 95,146,114,248, 75,216, 77,141,166, + 32,255, 59,113,208,152, 59,119,174,236,228,201,147, 77, 42,211, 97, 13,169,155, 82, 38, 71,120,220,218,122, 0,206,100, 64, 44, +203, 98,211,166, 77,188,149,128, 23, 95,124,145,187,206,155, 98, 0, 24,134, 1,203,178,248,215,191,254,165,230, 75,158,158,228, + 53,118, 37, 65, 74, 74,202,255,180, 90,237,181, 3, 7, 14,236,224,107,245,223,106,111, 91,253,246,117,231, 98,247, 69, 9, 32, +132,188, 53, 97,194,132,236,181,107,215, 30, 23,139,197,224, 86, 5,176, 44,139,240,240,112,232,116, 58, 46,133,109, 8, 0, 27, + 95,131,192, 53,248,239,240,225,195,144,203,229,117,198, 19,111,227, 80, 81, 81, 17, 45, 42, 42,146,213,119,241, 55,114,201, 31, +128, 6,221,253,214,229,203,151, 75, 0,152, 97,143,159,226,254,124, 82, 2, 92, 19,255, 60,245,212, 83,206,207, 85, 85, 85, 94, + 95,179,184,184, 56,210,183,111, 95,250,213, 87, 95, 61,188,126,253,250,239, 57,178, 93,191,126, 61,124,141,250,231,112,233,210, + 37,103, 74,226, 38,130,102,219,182,109, 13,245, 41,205,222,189,123,125,170, 85,225,225,240,101,119,217, 74,255,238, 53, 73,184, + 85, 0,238,136,159,215, 42,128,166, 38,245,134,228,221, 41,202,195,157,220,113,250,244,233,163,233,211,167, 79,147,202,116, 12, +142,183,252, 94, 93,221,255,245, 95,234,134,150,157, 57,174,143,207,181, 17, 31,238,247,150,222,107,100,100,228,206,198, 68,250, + 55,101, 12,128,187, 62,236,201,219,227, 67,159, 63, 49, 99,198,140,102,187,118,237,122,183,164,164,228, 57,163,209, 8,155,205, +134,129, 3, 7, 98,200,144, 33,233,114,185,124, 33, 31,242, 7,128,188,188, 60,231,103,215, 88,147,188,188,188,155,182, 61, 33, + 58, 58,154, 56,188, 4, 50, 0,106, 78,153,112,153, 10,240,249,153, 76,153, 50,165,161, 67, 66,151,241, 82,124, 59,198, 21,165, + 82,201, 30, 59,118, 12, 31,127,252, 49, 1,192, 43, 41,207,179,207,122,206,201, 52,116,232, 80, 76,154, 52,137,247, 53,120,147, + 23,192,157,167, 4, 52, 68,254,110, 21,128,166, 38,193, 64,133,184, 0,220,245, 1,127,203, 87,254, 29,218,230, 14,254, 13,253, +184,113,227,230,194,238,126,245, 11, 7, 14, 28, 32,211,167, 79,191, 37, 10,173,191,153, 3,255, 72,101,177,177,232,215,175, 95, +147, 22,227,105,106,121,127, 7,163,236,207,164, 4,120,181,162, 6, 14, 28, 24, 24,136, 3, 8, 32,128, 0, 2, 8,224,111, 6, + 38,208, 4, 1, 4, 16, 64, 0, 1, 4, 16, 80, 0, 2, 8, 32,128, 0, 2, 8, 32,128,128, 2, 16, 64, 0, 1, 4, 16,192,159, + 16, 86, 0,108,160, 25, 2,240, 4, 97,160, 9, 2, 8, 32,128, 0, 2, 99,123, 0,127,243, 78, 50,103,206, 28,191, 35, 46,221, + 69,117,123,146,231,109,253,177,175,242,154,250,250, 2,242, 2,242,254,238,242,126,126,165,216,239,129,101,208,187, 93,112,171, +229, 29,126,217,127,121,177,239,221, 44, 47, 45, 45,141, 0, 0, 33, 68,106,177, 88,112,238,220, 57,181,217,108,134, 80, 40,196, +197,139, 23,241, 88, 88, 87,236, 44, 40,128,241,238, 78,136,139,139,147, 9, 4, 2, 80, 74, 53, 0,144,145,145,113,203,159, 7, +119,125,174, 32,132,244, 1,208,230,248,241,227,219, 58,116,232,192,104,181, 90, 73,135, 14, 29,222, 9, 14, 14, 94, 9,224,146, + 99, 57, 41,147,145,145, 97,243, 32,175,185,195, 91, 96, 32,132, 80, 0,184,112,236,127,159, 43, 70,150,164,172, 43,136, 57, 39, +108, 51, 46,174, 89,243, 22, 53, 0, 40,165, 84, 8, 32, 34, 35, 35,227, 66,224,125,187,179,229,221, 82, 45,145,111,182, 45, 95, +179,191,249,147, 50,183, 98,245, 55, 82, 97,100,152,250,236,233, 51,178,187,130,154, 33,244,217, 25,154, 59, 73,203,106, 40, 31, +121, 96,137,203,237,199,230,205,155,165,219,183,111, 87,167,191, 98,223,254,110,223, 72,204,152, 49,131,215,115,217,151,123, 80, +202, 16,162, 62,117,242, 36,116, 58, 29,186,116,233,130,102,205,155, 35, 49, 97, 28,239,231,186,123,247,238, 58, 47,110,118,118, +182,199, 90, 10,217,217,217,126,247, 27,174, 80, 83, 70, 70, 70,227,250, 93,146,214,241,129, 2, 32, 64, 86,164,255,178, 98,151, + 3,209, 79,216, 63, 23,173, 6, 14,207,111,252, 67,157,124,189,238,245,101,183,226,245, 53, 66, 8,213,235,245,178, 93,187,118, +169,139,138,138,144, 36,106,137,118,157, 90,163, 86,111, 68,176,193,138, 17, 11,158,196,168,137, 83,177,245,139, 12,108,217,179, + 71, 61,110,220, 56,217, 29,208,133, 79,219,108,182,246, 69, 69, 69,236,128, 1, 3,196, 49, 49, 49, 56,114,228,200, 43,181,181, +181, 19,122,244,232, 33, 39,132,104, 41,165,222,166, 2,170, 93, 55,172, 86, 43,243,107,193,207, 61, 58,206, 26,132,127, 13,237, +219, 58,111,215, 7, 27, 55, 29,149,254,210,163,223,152,247, 28,242, 46, 58, 20, 6, 54,224,105,248,155,185,137,124,205,223,239, + 75, 30,124, 95,201,223,182,110,155, 52,190,117, 71, 53,137,138, 70, 97, 77, 5,218,119,232,170,182,176, 54,156,252,100, 13,202, +186,180,150, 13,157,120, 63, 47, 69,224,176, 90, 65,123,117,231,182, 4,248,118, 23,139,125, 63, 81,164, 78, 3,122,117, 7,230, + 47,105, 28,113,115, 5, 74, 26,155,157,204,157, 50,209, 84,114, 27,131,212,212, 84,138,197, 4,228,173,134,207,161,148, 2,139, + 9,166,252,158,116,199,172,181,190, 65,254,212, 65,254,163,176,127,255,126,204,152, 49,195,235,119,239, 30,176,139,246,233, 51, + 4, 89, 89,151,113, 40,215,158,176,230,244,201, 83, 0,128,217,255,252,134,158, 58, 51, 89, 22, 42,225,247, 92, 18, 18, 18,216, +221,187,119, 51,217,217,217,216,187,119,175,199, 66, 76,254,164, 80,245,244,222,166, 41, 20, 52,195, 15,133,130, 75, 23,222,232, + 84,198,209, 79,212, 45,182,211, 20, 10,128, 75, 59, 57,170, 19,242,194,217,179,103,161,217,184, 81,253,150,124, 10, 6,206,120, + 10,226,182, 17,128,208,145,236,143,165, 0, 43, 2,107,162,184,255,137, 84,148,124,244, 62, 14, 30, 60,168, 30, 62,124,184,140, +243, 2,220, 38,216, 24,134,105,211,170, 85, 43,104, 52, 26,225,128, 1, 3, 48,116,232, 80,230,202,149, 43,131,126,253,245,215, + 99,119,223,125,247, 96, 66,200, 21, 7, 89, 51, 60,219,174,217,216, 49, 9,209,239, 45,219,204, 44, 76, 62,218, 34, 46,113,142, + 44,110,152,106,228,130,143, 47, 62, 16,115,207,204, 88, 66, 72, 53,236, 49, 6, 76, 67,253,204, 53,177,149,183,126,212,104,133, + 52,128, 58,168,159, 0,168, 62,252, 42, 6,228, 58,128, 12,156,217, 31,115, 70, 60,195,128,103,229,190,250, 74,128, 66,161,160, +177,177,177,200,204,204,164,174,101, 75,125, 34,214,156,195,210,233,131,226,213, 98, 27, 11, 27, 40,130, 43, 66,112,229,218, 53, + 92,169,174, 68,183,160,102, 48, 21, 94, 82, 31,218,178, 93, 54,140,135, 18,208,171, 59,112,242, 44, 3, 74, 37,176,145, 32, 60, +156, 96,193,164,113, 70,220,136,161,105,124,170,132,198,146, 52, 71,252, 11, 23, 46, 68, 65, 65, 1, 0, 96,219, 73, 17,106, 45, + 22,181,226,159, 67,124, 82, 4,124, 81,226, 28, 41, 94, 61, 63,151,197,246,195,177,177,177, 13,231,111, 95,236,223, 59,190,245, +179,203,210, 45,191,190,225, 84,120, 38,244, 95, 44,123,240,153, 14,141, 30,112, 55,111,222, 44,221,182,109,155,154, 97, 24,188, +240, 46,156,213,207,248,212,193,136,136,248, 81, 26, 55, 44, 13,192, 22,140, 28,249, 81,157, 99,211,167, 3,247,223, 15,220,143, +108,245,242,143,192, 75, 9,224,200, 95,163,177,159, 58,117,234, 84,103, 97, 37, 95, 8,204,147,229,207,165,100,118,189,191,180, + 52,255,200,191,201, 16,187, 12, 0,176, 98,197,138, 27, 10,192,224,116,224,200, 11,183,229,114,246,238,221,139,149,147, 82,209, +109, 76, 2, 32, 48,129,136, 24, 16, 33, 3, 34, 16,129, 82, 2, 86,111, 5,181,217, 64,205, 54, 60,249,196, 83,120,234,245,185, + 56,219,182,173,186,123,247,238,183,211, 19, 64, 10, 10, 10,226, 59,117,234, 36, 46, 42, 42, 66, 78, 78, 14, 78,158, 60,137,132, +132, 4,196,199,199,183, 95,181,106,213,219, 83,166, 76,121,210, 7, 5, 64,176,127,207,215, 95, 62, 50,208,208,246,112,181, 0, +211, 23,215,224,222, 65, 31,226,153,121, 83,133, 31, 44,172,232,182,240,131,181,211,163, 7, 77, 87,162,129, 52,200,174,132,238, + 58,166,167,165,165, 81,119,251,155,186, 32, 92, 0,183,192, 3,224,250,144,214,237, 88, 91,209,253,174,238,225,138,183,158,100, +231,140,120,198,151,106, 78, 36, 51, 51,147,114,105, 73,185,255, 21, 10, 5, 77, 74, 74,242,205,170,222,113, 80, 58, 62,166,175, + 90, 92,107, 69,240, 7, 47,194,106, 48, 67,242,194, 18,132,137, 37,168, 21, 25,161,175, 53, 34, 24, 4,166, 11,101,234,202,202, + 74, 89, 88, 88,152,199, 65,248,228, 89, 32,115, 61, 11,192,224,248, 3, 70,222,195, 96,210, 56, 2,215, 64,218,212,105, 64,230, +122, 63, 60,166, 73, 73, 50,199,125,250,101,173,115,228,207, 17, 63, 0, 40,247, 91, 96, 52,235, 1, 0, 99, 23,238, 70,214,210, + 4, 53, 0,222,242,207,190,127, 22, 34, 82,120,163, 35,144, 82,144, 86,189, 92,182,203,208,250,159,252, 82,132,146,183,236,228, +239,169,198, 60, 81,100, 81,251, 57,252,172,255, 35,219, 44,210,204,205,207,170, 41, 40,222,155,247, 29,134, 73, 99,176,238,179, +125,248,207,174, 52,245, 54, 5,197,156,127,188, 33, 27, 56,178,189, 95,138, 64, 77,177,130,142, 25, 0,100,125,117, 28,148, 82, + 52,111,115,183,147,252, 87,174, 92,233,241,250,244,181, 42,105,106, 82,123, 53,240, 41,128,239,112,232, 16, 48,108,216,141,227, +111,191,125,227,243,243,207,101,171, 51,254,211, 83,198,176,157, 60, 94, 39, 71,254,163, 71,143, 6,203,178,248,228,147, 79,154, +236, 5, 87, 40, 20, 78,242,175,171, 20, 40,104, 70,134,231,119,142,153,162,171,163,254, 18,199, 63,108,146,155,243,136,227, 68, + 98,255, 48, 96,192,205,115,236,204, 84,157,211, 43, 15, 0, 44,155,140,121,243,230, 57,143,207,155, 55, 15, 43, 86,172, 0,211, + 99,214,141, 95,117,156,239, 78,158,112,170,251,235,179, 90,221,156,199,227,250,106,107,107,209,174, 75, 87,128, 53,131, 9, 2, +136, 80, 0,107,117, 37,106,139,206,225,218,197, 82,116, 28, 46, 5, 17,135,131, 88,204,128,128,193,210, 57, 11,144,144,249, 6, +230,207,159,223,164,131,178,183, 84,217, 46,100, 75, 40,165,225, 70,163,113,120,100,100, 36, 78,157, 58, 5,150,101,113,238,220, + 57,172, 94,189, 26,189,123,247, 70, 84, 84,212, 76, 0, 79,214, 35,107,182, 33,242,166,148,182,234,194, 28,146,182,239,156, 40, +174,200, 57,138, 74, 93, 16,254,187,213,138,237,121,255,195,115, 73,193, 66,161,129,141, 5,166, 55, 88, 7,225, 86, 20,183, 10, +192, 55, 52,212,119,220,121, 6,132,124,137,159, 82, 10,217, 43,163,145,153,163, 12, 79,133, 2,191,124,117, 20, 24,225,124,173, +120,129, 35,125,131, 97, 45, 0,130,218,218, 85,136,140, 84, 33, 43, 43, 11,190,164,241, 28, 26,212, 66,221,166,214, 6,201,226, +167, 96,187,174,133,245,210,117, 8,197, 34,132, 16, 1, 66,137, 0,161, 2, 33, 34, 69, 18,232,170, 43,112,121,239, 65,117,216, +164,251, 60, 14,116,238, 72,125,223, 79,172, 67, 1, 0,150, 45, 34,160, 4,176,135,199,248,222,193, 29,164, 44,203,202,202, 82, +103,101,101,249, 53,133,224, 74,254, 16, 10, 80,116,217, 62,248,149, 92,173, 69,231,182, 18,244, 72,222,130,172,213, 19,213,124, +221,235, 34, 82, 8, 33, 41,133,128, 92,135,141,182, 66, 80, 27,130,208,105,151,192,178, 90,212,214,102,193, 86,240, 47,223, 60, +185, 60, 42,183,249, 82,226, 85,185,249, 25,117,124,228,171,248,228,187, 89,104,198,116, 6, 0, 60,245,108, 79, 12, 24, 26,141, +181,159,230, 96,229,255,222, 84, 43, 71,250,231, 58, 36, 4, 80, 60,127,204, 57,232,221,123,239,189,216,183,111,159, 87,242, 7, +128, 25,211, 68,106, 96, 47,128, 99,168,184,218, 12, 61, 58, 3,159,127, 94, 3,181, 26,232,209, 3,136,142,182,139,168,184,218, +204,254, 50,246,255, 93,253,219,175,157,136, 39,242,223,187,119, 47, 88,150,117,146,244,134, 13, 27, 26, 77, 32,174,219,245,201, + 31, 0,188,145, 63, 0,100, 40,149,132, 2, 82, 2,104, 82, 83, 83, 27,236,248,172,203,160,175,204,204,148, 17, 2,172,252,108, +229, 77, 49, 47, 43, 51,148,174,254, 21, 41,165, 84,253,225,135, 31, 58,119,124,248,225,135, 88,177, 98, 5, 50, 50, 50,234, 86, +145, 35,144,186,147,151, 97, 79, 97, 43,163,148,106,158,124,242,201, 6,175,207,234,226, 69,201,252,252,115, 25, 33, 64,198,202, + 12,181, 59,242, 18, 54,111, 14,136, 4,176, 25, 42,240,251,246, 61, 88,187, 49, 27,159, 93, 58, 7, 0,200,127,179, 5,122,140, +186, 31,166,146, 11, 56,254,235, 97, 28, 61,119, 26,149, 87,174,224,216,177, 99, 77, 86, 88,107,245,234,213, 82,126,125,152,132, + 81, 74,123, 21, 20, 20,124,240,218,107,175,245,253,224,131, 15,196,102,179, 25, 2,129, 0,205,155, 55,135, 94,175, 71,126,126, + 62,162,163,163,185,186, 5,158,172,255, 80, 66, 8, 75, 41,141,172,184,120,224,167, 55,191, 44,137,252, 98, 94, 7,104,245, 98, +136,133, 12, 58, 70, 72,112,229,186, 25,138,127, 91, 49, 96, 72,108,104,103, 47,158,132,180,180, 52,202, 41, 2,174,125,177,161, +207, 1,220,122,112,228, 95, 95, 57, 96,188, 13, 34, 92,189,239, 58,110,206,196, 25, 62, 95, 64,102,102, 38,181,147,255, 58, 39, +249, 75,126, 58, 15,195,206,187,234, 28,247,106,185, 42,215, 73,195,180,213, 96,197, 66,152, 15, 31,135,233,247, 34,212,238,218, + 7, 24, 77, 16, 83,138, 16, 8, 32, 4,129,137,181, 66,107,170,197,103,187,183,122,149,185,108,145,221,186,119,133,125,155, 51, + 87, 40, 78,157,161,152,191,196,255, 62, 43,151,203, 53,174,110, 47,149, 74,197,235, 69, 87,169, 84,206,218,218, 28, 30, 91,113, + 17,123, 14,235, 80,114,181,214,169, 4, 20, 94, 52, 2,242,141, 80,169, 84,188,220,145, 66, 98,175, 28, 38,170, 62,138,208,208, + 51, 8,146, 84,131,101,181,176, 88, 14, 67, 32,136,134, 89, 95,126,219, 58,235,158,111,143, 73, 1, 82,135,252, 47,159,162, 24, + 60, 81,128,103,223, 73,192,189, 9,125, 1, 80,199,121,190, 97,221,186,117,244,133,119, 9,154,181,238, 15, 10, 32,113,210, 28, +236,223,191,159,215,119, 89,230, 2,109,211,230, 55, 39,249, 87,151,219, 75, 48, 15, 24, 96, 39,127,174, 16,160,253, 88, 48,170, +203,131, 17, 25,114,217,163,204,201,147, 39, 67, 38,147, 97,204,152, 49,152, 58,117, 42, 4, 2,193, 77,127,174,251,249,194,221, +123,235,151,178,228, 66,196,132, 16,231, 95, 67,251, 8,160, 1,133,166, 1, 89, 55,222,175,212, 84,181, 59,203,121,222,188,121, + 72, 77, 77,173, 75,168, 13,200,251, 78,169,196,177, 99,199,212,132, 16, 41,128, 58,109,230,244,103,215,219,231,233,250,196,148, +130, 9, 9,130,229, 74, 49,148,175,190,138,213,250, 10,232, 70,199, 57,143,127,241,191,213,120, 99,193,108,196,204,127, 12,111, + 29,221,139,141,186,115, 72,120,240, 65, 68, 71, 71,251, 60, 5,176,122,245,106,169, 66,161,160,171, 86,173,170,211,135,243,242, +242,212,158,166,161, 8, 33, 34, 66,200,144,163, 71,143,150,228,228,228,104, 94,120,225,133,184, 79, 62,249, 68, 82, 83, 83,227, + 44,211, 92, 91, 91,139,102,205,154, 21, 78,153, 50,165,231,136, 17, 35, 58,123, 81, 36, 24, 66, 72,151,163,185,155,202, 78,239, +156,127,126,254,203,233,237,183, 44,238,128,223, 75,133,168,172, 17,128, 37, 64,121,141, 25,180,101,247,218,231, 95, 89,210,247, +129,135,255,225,117, 58, 33, 35, 35,131,112, 99,157, 82,169,244,250, 57,128,219, 67,254,110, 61, 0,174,196,207,103,156,241,197, + 18,185,225,106, 91,229,214, 59, 80, 39,206,160, 1, 55, 70,223, 86,109,213, 90,106,129,184, 92, 11,201,119,123, 65,132, 12, 80, +107, 6,173,214,131, 88,173, 16, 1,176, 81, 22,181, 54, 43,170,173,102,128,245, 62,135,202, 5,249, 45, 91,212,240, 48,104, 15, + 18,108,252,128,170, 84, 42, 9,231,210,231, 99,173,223,100,253, 3,248,250,153,246,117,182,135,188, 84, 4, 17,189, 14, 11,105, +133,172,172,172,189,124,189, 0,146, 26, 53, 34,223,250, 31,174,189,144,134,235,218, 96,116,176, 28,135,205, 86, 4, 0, 40,254, +165,221,109,235,176, 27,119,124,172,158, 61, 78, 89,135,252, 57,196, 69,188,138,225,125, 39, 35, 62,242, 56, 54,238,120, 71, 61, +118, 18,255, 65,100,237,218,181,244,199, 31,127, 68,121,249, 88,180,108,185, 7,205, 90,245, 3,165, 20, 12,195,240, 10, 68, 42, + 41, 1,138,138,142,113, 19, 9,128,164, 6, 90, 61, 48,116,168,125, 79, 97, 33,240,233,167, 64,117, 21,160,175, 1,106,244, 64, +104, 68, 21,175,107,107,104,174,255,236,217,179, 0,128,119,223,125, 23, 0, 16, 19, 19,211,100,110,102,215, 62,201,231, 59,115, +231,206,133,171,197, 94,159,184,125,128, 20,184, 49,247,239, 10,206, 11,224, 56, 71,227, 73,200,172,168, 24,156, 62,126, 2,165, + 17, 17,106,134, 97,240,220,115,207,225,163,143, 62,242,251,250, 70,154,194, 65,217, 26,204,126,119, 17,250, 79,158, 12,229,187, +239,130, 97,110,240,156,178,240,216, 13, 15,225,190,125,216,189,123, 55,206,157, 59,231,115, 16,224,234,213,171,165,185,185,185, +106, 0,200,207,207, 87, 51, 12, 35, 75, 78, 78,214,172, 90,181, 74, 74, 41, 69,124,124,188,204,104, 52,170, 27, 80,236, 44,121, +121,121,253,103,204,152,209,162, 91,183,110,216,190,125,187,161,178,178, 82,104, 52, 26,237,222, 14,199,252,199,248,241,227, 99, + 8, 33,193,148, 82,163, 27, 49,140,139, 60,166,232,212, 47, 43,222,248, 87, 74,179,150, 61,178,240,115,214, 19,248,237, 2, 65, +201, 85, 33, 64, 25,152,204, 22,104,105,203,210,167,103, 61, 21, 71, 8, 41,165, 77,160, 85,242,137,179, 9,224,143, 65,131, 83, + 0, 57, 57, 57, 55,237,171, 40,213,249, 76,118,174, 30, 0,251, 20,128,189,255, 72,126, 58,143,160, 99,165,176,133,219,173,168, +250,115,200, 13,173,107, 60,113,177, 4,134,160, 96, 68, 91,173,232, 24,220, 12, 33, 34, 49,136,197, 2,176, 20, 86,155, 13,213, + 54, 51, 12, 54, 43, 76,212, 6, 27, 40,168, 15,157,109,254,146, 27, 74,128, 61, 46,224, 6,233, 47, 91, 36, 64,250, 34,130, 23, +150, 88, 27,221,232,114,185, 92,195,149, 46,229,131,133, 89,246,118, 95,154, 20,225, 36,124,167, 43,159, 94,135, 8,128,144,234, +240,213,236, 8,235, 99, 42,126,113, 29,162,171, 63,193, 6,187,155,250, 3, 97, 24, 30,187, 90,140,130,127,119, 68,104,187,222, +168, 44, 45,197,149,243,151,110,107,199, 28, 48, 52, 26,122, 71,119, 51, 4,159, 64,136,177, 15,190,121,211,226, 60, 62, 66,222, + 23,185, 27,125,179,252, 39,141,250, 17,223,125, 39, 71,120,174, 10,203, 23, 1,207, 47,161, 24, 53,106, 20,239,101,127, 93, 59, +118, 34,221,187,215,213, 2,183,110,181, 7,254,173, 91, 7,244,232, 65,177, 98, 5,193, 91,111,213,216, 21, 4, 0, 61,122, 70, +224,133,231,249, 93, 35,103,165, 78,158, 60, 25, 27, 54,108,168, 99,201, 38, 38, 38, 54, 72,110,254, 42,162, 62,122,240,100, 43, + 86,172, 80, 55,164, 0, 44, 91,182, 12,153,153,153,188, 44,225, 39,159,124, 82,205, 69,254,187,195,243,207, 63,143,229,203,151, +171, 51, 51, 51, 61, 94,227,143, 39, 74,240,202, 91, 11, 48,107,241,191,240,178,217,140, 15, 63,252,176,193, 54, 90,182,108, 25, + 84, 42, 21, 8, 33,210,134, 8,123, 84,159,206, 88,245,197,167,136,157, 62, 29,111,190,249,166, 71,165, 97,222,188,121, 88,182, +108, 25, 62,255,252,115,141,175,109,159,155,155,171,230,130,229, 20, 10, 5,205,203,203, 83, 39, 39, 39,147, 67,135, 14,169, 9, + 33, 72, 78, 78,214,172, 92,185,178,193,239, 27, 12,134,240,173, 91,183, 98,236,216,177, 40, 44, 44, 12,209,235,245,176, 88, 44, + 96, 24, 6,102,179, 25, 73, 73, 73,196, 65,238, 70, 62,142, 45,147,201, 36, 62,188,105, 58, 70, 61,242, 22,118,230,156,197,185, +203, 2, 84,233, 25, 8,132, 64,169, 62, 24,207,189,180, 40, 30,192, 69,190,220,207,197,157, 0,252,166, 3, 2,184, 61,214, 63, +220,185,113, 56,215,140, 84, 42,133, 84, 42,197,175,191,254,234,252, 43,250,169, 24,149,198, 74,180, 28,234,251,186, 95,142,220, + 67, 66,102, 64,242,211,121,136,138,203, 65, 9,129,120, 86,121,157,227, 94,137, 75, 44,128,141, 2, 23,245, 21, 40,169,212,226, + 90,149, 14,149,181,181,208,153,141,184,102, 50,226,114,173, 1,165,181, 53,208, 90, 76,208,177, 22,152, 89,239,217, 48, 71,222, +227,102,192,115,137, 11,152, 61,181, 25, 40,196,160,190,149, 1,119,186,240,235,119,118,190,238,127,167,229,121,181, 22,123, 14, +235,234, 16, 63, 71,254, 65,108, 49,130,216, 98,188, 49, 94,136,146,146, 18, 51, 95,153,155,206,177,104,157,158,225,220, 62,167, +183,225,226,217, 82,156, 58,112, 28, 87,206, 87,220,246,142,187,238, 51,187, 2, 90, 85, 70, 17, 98,236, 3,233, 44, 33, 30, 89, + 44,114,254,165,111,156, 14, 2,194,123, 64,122,232,222, 28, 60, 49, 95,142,136,188, 61, 32,132,224,251, 3,246, 71,192,151,252, + 57,196,244,234, 89, 79,177, 0, 62,249, 4, 56,115,198,238, 9,120,243, 77,234,116,191, 83, 74, 17, 17, 17,225,125, 4,118,244, + 81,155,205, 6,155,205,134,119,223,125, 23,103,207,158,197,233,211,167,113,250,244,105,168, 84, 42, 44, 88,176, 0, 37, 37, 37, +183,243,145,104, 26,178,164,231,206,157,203, 89,117,188,200,144, 16,226,214,250,231,224,233,152, 43,246, 5, 85,128, 48,205,240, +159, 87,150,160,217, 86, 21, 82, 83, 83,225, 90,106, 88,209,163, 31,230,198, 14, 71, 72, 72, 8, 70,141, 26,133,215, 94,123, 13, + 42,149, 74,173,211,233,220,190,127, 95,148,158,198,229,190,125, 16, 21, 21, 37, 99, 89,182, 65,111, 7,231,169,240,215,243,226, + 26, 41, 31, 31, 31, 47,227,136, 18, 0,226,226,226,100, 94,218,110,204,168, 81,163, 90,148,148,148, 96,223,190,125,184,235,174, +187, 32, 20, 10,157,202, 98, 84, 84, 20,223,233, 8,214, 33,143,116,239, 53,104, 97,230,174,112,252,182,125, 49, 70,198,247, 70, +168,132, 65,104,136, 13,193, 65, 38,220,247,208, 20, 22,128,182,190,174,234, 77,185,228,238,143,207,116, 64, 0,183, 15,140,167, +135,168, 84, 42,155,207,157, 59, 23,115,231,206, 5, 0,243,219,105,111,195, 82,102, 69,112,176,196,175,100, 36, 73, 73,246,240, +225,144,241,103, 64, 5, 12, 94,251,198,224,180,254,249, 34, 36, 42, 74,102,109, 22, 2, 29,181,225,132, 94,135, 99,149,229, 56, + 94,117, 29,199,171,180, 56,161,215,226,140, 65,135,114, 83, 45,106,172, 86, 92, 50,232,157,191,233, 9,147,198, 17, 44, 91, 36, +192,178, 69, 2, 80, 8, 64, 9,131,212,105, 4, 79, 78, 19, 99,214,212,214,232,222,189, 45, 88,136, 0,248,118,203,156,171, 63, + 41, 41, 73, 86,127,159, 15,109, 38, 43,188,104, 87,228, 11,222,183, 7,209,237,124, 49,204,238,190,161, 58, 8,168, 30, 38,198, + 30,209,172,213,106, 67,146,146,146,124, 42,138, 30, 27, 27, 11,149, 74,133,117, 53,122, 24,205, 12,158, 88,255, 31,148, 73,130, + 97, 52,223,190, 50, 17, 19, 7,188, 33,203,213, 46,193,186,255,222, 48,241,191,121,211,130,184,136, 87,111, 40,148, 15,124, 42, +203, 80,102,240,202, 45,177,252, 85, 32,121,254, 88,132,231,169, 32,251,247,104, 48, 19, 0,141, 70,227, 87, 31,238,210,165,110, +244,248,152, 49, 64,120, 56, 16, 29, 13, 12, 27,208, 28, 18,177, 0, 2,230,134, 88, 73,112,176,215, 1,153, 97, 24,231, 92,255, +217,179,103, 17, 19, 19, 83,231,239,173,183,222,194, 91,111,189,133, 75,151,248,123,101,220,205,215,187, 34, 45,205,119, 11, 44, + 51, 51, 83,182,124,249,114,183,132,205,215,250,119,113, 61,223, 20,167,192,109,179, 44,191, 20,246,102, 66,192, 26, 76, 16,181, +235, 2,197, 59,239, 32, 57, 52, 28,225,154, 92,231,241, 89,255, 72,198, 27, 31,252, 7,133,203,190,198,235,253,199, 96, 74, 68, + 55,236,222,188, 25, 69, 69, 69,110,223,191,135,211, 20,232,219,175,159,140, 11,106,228, 20, 50,215,233, 25,119,251, 60, 88, 95, + 52, 45, 45,141,114,129,125,220,124,191, 43,201, 39, 39, 39,107,226,226,226,100,156,235, 63, 57, 57, 89,227,165,221,114, 68, 34, +209, 93, 15, 63,252,240,217,202,202, 74,232,116, 58, 4, 7, 7,163,117,235,214, 8, 15, 15, 71,120,120,184,183,198, 99,235,201, +179, 5, 5, 5, 25, 30, 77,251, 72,182,250,167, 33, 56,127,161, 10,109,195, 4,136,239, 73,112,119, 55,138,208, 22, 45, 42, 0, +216, 60,240, 70,160,222,192,159,212,250, 7,188, 47, 3,172, 81, 42,149, 65, 0, 66, 21, 10,133, 83, 11,236, 56,186,131, 95,154, +175, 82,169, 36,114,185, 28, 42,149,138,138,103,101,213,113, 69,242,205, 3,208,242,193,177,154,242,172,237, 48, 88, 77,168,210, + 27,112,214, 98,129,136,181, 59,234, 43, 45,181, 96, 41, 5, 5,176,253,234, 57,232,173, 22, 0,224, 49, 48, 17,204, 95, 82,183, +143,219,167, 2, 88,216, 96,194,239,103,170,177,106, 67,149, 79,247,235, 74,244,114,185, 92, 83,223, 11,224,170, 20,120,130, 92, + 46,215,100, 41,166, 64, 52,246, 51, 0,209, 40, 47,191, 17,156, 39,102, 47,195,204,180,199,211,253, 79,227,242,101,251, 64,172, + 84, 42,247,240,145,155,246, 77,102, 29,197, 43, 43, 43, 11,220,164,196,250,163, 7,125, 90,149,209,212,120,224,169,246,154, 45, + 10,138, 3,170,227, 0,128,225,125,237,153,241,254, 53,111, 49, 14, 30,239,139, 15, 54, 78,135,114,235, 83,106,229, 68,126, 4, +254,196,124, 57, 34, 35, 85,174,134, 44,180, 90, 57, 40,205,114,184, 42, 41,178,178,146,120,201,154,252,200,163,100,247,206, 93, + 20,176,187,254,101, 50,130,235, 23,194,160,215, 73, 96,172, 18, 99,253, 26,130,185,115, 41,138,203,170, 49, 44, 62, 14,211,167, + 78,227,101, 21,219,108, 54,231,124,191, 74,101,191, 86, 87,194, 47, 43, 43, 67, 89, 89,153,207,238,125,133, 66, 65, 25,134,185, +137, 84, 51, 50,148,196,143, 36, 64, 26, 74,105,157, 88, 0, 23,143, 0,111, 87,184,171,107,191,126,244,190, 55,183,127,125, 37, +199, 90, 93, 13, 81,171, 72, 8, 66,154,161,239,163,147,241,214,184, 4,188,194, 45,219, 27, 52, 24, 54, 99, 45, 68, 45,219,162, +127,156, 20, 93, 59,118,195, 71,191,231,162, 95,191,126,178,159,126,250,233, 38, 37, 32, 77,161, 0, 64,212, 0,240, 84, 90,154, +115,233,160,181, 30,217, 11,133, 2,128,222, 88,168, 72, 0, 12,112, 51,200, 14, 28, 56,144, 80, 74,157, 46,254,252,252,124,167, +139,223,245, 60,199,182, 87,242,119, 24,236,175,134,135,135,247,141,139,139,235,126,242,228, 73, 28, 57,114, 4, 54,155, 13,161, +161,161, 48, 24, 12,101,145,145,145,231,125, 49,250, 8, 33, 76,219,182,109,119, 63,244,208, 67,109,243,246,231, 99, 69,214,110, +180, 32, 98,244,108,107,194,153,235,161,184,183,167,229, 28, 0, 11,167,160, 57, 20, 74,155,167,103,226, 58,214, 5,166, 0,238, +108,240,153, 47, 54, 3, 48,187, 18,245,197,156, 75,192,116,223,201,223,149,108,220, 13, 90,124,149,128, 42,173, 78,102, 9,145, +168, 43, 25, 22, 87,106,107, 0,139, 5, 54, 74, 65, 0,252, 94, 83,129, 82, 67, 21, 40,165, 92, 18, 27, 30, 3, 19, 69,234, 52, +130,204,245, 55,250,228,201,179, 64,175,238, 86, 8,160,111, 20,249,187,118,118,127, 93, 94, 73, 73, 73,178,172,172,167,212, 64, + 1,180, 90,173,185,164,164, 68,184, 52, 1,204,194,221,163, 48,175,223, 65,167, 21,198, 87,169,112,231,117,169,191,205,145, 16, + 95,107, 14,139, 9,134,100, 22, 81,192,253,114, 63,103, 38, 64, 21, 40,159, 32,197,180,137,159,201,148, 91,158, 86,231,110,164, +136,143, 60,142, 17,242,190,216,191,251, 56,242,116,239,128,128, 64, 49,241, 83,222,247, 26, 25,169, 2, 33, 4,147, 38, 77,194, +231,159, 87,129, 51,138,237,255, 83, 71, 27,103,213, 25,144, 60, 76,193, 98,244, 24,153, 44,103,175, 90, 61,102, 12, 96,190,210, + 9, 23, 42,130,192, 58,102, 91,219,235,219,226,197,212,106,236,206,235,137,230, 29,123,242,186, 70,142,248, 47, 94,188, 8, 0, +184,114,229,138,211, 51,112,245,234, 85,231,192,234, 15,148, 74, 37,225, 18, 1,213,159,195,205, 80, 42, 9,159,124, 0,174,248, +252,243,207,235,196, 2, 44, 95,190,220,103,235,191, 62, 97,248, 11,137, 68,130, 43,197,231,209,173,123, 15,176, 86, 19,136,213, + 6, 97,243, 22,104, 62,120, 8,154, 13,186, 7,172,222, 10,155,193, 4,106,181, 1, 54, 22, 11, 87,126,128,169,211,167, 66, 34, +145,184,149,103, 93, 31,193,235,119,221,157, 23,251,158,251,115,227,227,227,101,121,121,121,106,110, 12, 24, 49, 98,132,219,182, +226, 65,254, 32,132,176, 0,118,244,236,217,115,208,199, 31,127,108,190,118,237, 90,109, 66, 66,194, 67, 5, 5, 5,175, 27, 12, +134,242, 86,173, 90, 41,250,244,233,163,245,161,237, 69, 0, 58,199, 13, 27,214, 58,109, 86, 26,206, 93, 60,167,125,124, 86,218, +200, 67,187,215,164, 95,174,214, 14, 31, 50, 58,129,109,219, 49,230, 17, 55, 94, 3,214,211, 88,224,202, 21, 13, 37,255, 9, 36, + 2,250,243, 40, 0, 13, 90, 23,254,144, 63, 71, 54, 92, 78, 0,127,148,128,110,138, 25, 26, 0,164, 84,185,154, 34, 88, 2, 29, +181,194,108,181,130,165, 44, 90,134,133,225,162,190,146, 95, 6, 59, 7,220, 45,239,187, 17, 3,224, 91, 38, 54,119, 46,254,198, +166,235,117,124,119,226,144, 33, 67,182, 44, 92,184, 80, 28, 25, 25,201, 94,190,124, 25,243,250, 93,174, 67,254,190,252,134,187, +246,247, 27,142, 44,127,245,147, 60,185, 59,135, 47, 6, 61, 32,208,100, 60,144, 65, 54,127,114, 73,186,237,232,155,234,220,141, + 0, 1,193,196, 1,111,200, 30,120,138,127, 2, 32,174, 47,217, 9,190,202, 49, 72, 1,238,120,103,117,186,221,121, 18,218, 57, +131, 0, 13, 23,215,152, 62,117,154,102,250,212,105,164, 92,247,177,212, 86, 93,173, 38, 2,192, 80, 27, 12, 82,109,133,144, 17, +194,192, 72,100,227,166,204,134,144, 18,175,215,153,144,144, 64,238,186,235, 46,122,171,222, 63,187,181,159, 65,210,210,210,168, +107, 68,187,171, 39,192, 71,113, 26,206,242,119, 81, 40, 52,183, 99,240, 26, 51,102, 12,158,222,152,137,183,170, 43, 48,112,244, +189, 96,218, 70,216,175,201, 66,237,169,123, 33, 2, 17, 8, 65,196, 2,124,158,177, 12, 45,198, 14, 65,247,238,221,255,208,212, +189,156,117,159,155,155,171, 30, 54,108,152,108,230,204,153,141,250,237,179,103,207,202,247,236,217, 83, 44, 16, 8, 54,143, 28, + 57,242,109,134, 97,174,197,197,197,229, 56, 45, 25, 23,143, 18, 33, 4,238,158,185,139, 39, 64,117,228,200,145,161, 95,173, 94, +195,136, 5, 65, 23, 38, 63, 54,121, 0,195, 48,186,123,239,159, 61, 1, 64,152,131,248,171, 1, 80,171,213,234,148, 87, 79,105, + 11,148,148,191, 3,193,199,253,239,151, 2,208, 20, 10,131, 39,242,241,101,128,147, 10,122,251,182, 0, 0, 32, 0, 73, 68, 65, + 84, 41,146,137,106,183, 74,202,158, 42, 84,235, 77,102, 88,109, 54,116, 31, 58, 24, 49,214, 97, 62,145, 97, 83, 6,163,112, 73, +127, 0,168, 57, 79,135,203, 84, 0,105,132,220,173,114,185, 92,168, 82,169,230, 47, 93,186,244,223, 46,202,197, 24,165, 82,233, + 83, 34, 18,135,167,160,201,146,151, 76,249, 61,201,209,142, 13,223,223, 20,149,202, 47, 77,255,193,103, 58,104, 30, 68,227,159, +143,157,220, 9,158,152, 63,198,153,167,156, 27,199, 86,167,239, 65,104,231, 12, 18,218, 57,201, 39,153,225, 45,158,213, 28, 40, + 6, 97,153, 11, 82,163,193, 94, 7, 32, 84, 34,215,132, 69,193,167, 21,163, 46,253, 79,228,208, 56,155,124, 94,149, 83, 2,154, + 66,150, 35, 22, 64,205,125,110,172, 60,127, 87,150,117,239,222, 29,237,158,123, 78,182, 98,215, 46,117,209,219,223, 33, 73,212, + 18,225,142,226, 61, 70,131, 21,115, 23,188, 12, 65, 72, 36,182,175, 81,226,215, 86, 4,227, 26,145,183,223,102,179,194,215, 24, +160,250, 74, 0, 31, 43,223, 75, 59,145,211,167, 79, 95,163,148,166,247,234,213,235,203,242,242,114,189, 80, 40,132,213,106,165, + 45, 91,182,116,122, 84,244,122, 61,196, 98,177,211,139,228, 65,222,168,252,252,124,176, 86,130,225, 35, 6,188,113,241,226, 69, +157, 86,171, 69,100,100, 36,219,177, 99, 71, 29,247,108, 42, 43, 43, 33,145, 72, 64, 8, 65, 80, 80, 16, 47,163,143, 83, 18,234, +127,174,239, 21, 13,224, 79,230, 1,184, 85, 74,129,223,196,152, 32,215, 32, 65,126, 71, 69,147, 58,148, 0,114, 11,230,209,109, +114,185,252,255,228,114,249,255, 53,197,245, 53,225,253,146,166, 56,231, 86,194,110,213, 3,142, 20,251,245,142, 37, 53, 74, 54, +195,118,210,132, 74, 58, 53,197,101, 90,110,101, 27, 52, 97,209, 21,141, 47,115,245, 94,148, 9,191,229, 80, 74, 73, 72, 72, 8, + 38, 77,154, 4, 71,249, 94,148,184,148,239, 61,176,103,183,179,124,239,216,184,177,112, 40,189, 13,254,222,231,186,247,200,147, + 17, 47,223, 76, 76, 60,171, 9,242, 80, 2, 26,141,123,238,185,199,100,181, 90,115, 0,232, 89,150,165,102,179,125,225,207,181, +107,215, 0, 0,205,154,217,151,246,114,251, 69, 34,145,199,246,123,224,129, 7, 56, 25,187, 88,150, 69,120,120, 56, 88,150,117, +174, 56,113,172, 98, 33,181,181,181, 20, 0,196, 98, 49, 8, 33,204, 31, 49,182, 7,224, 63,248,164,146, 6, 0, 50,112,224,192, +128, 38, 22, 64, 0, 1, 4,240,231,129, 21, 64, 45, 0, 73, 19, 27,113,222, 10, 6,241,174, 40, 24,192,159, 3,129,135, 25, 64, + 0, 1, 4,240,231,130, 16, 64, 51, 30,228,111,128, 61,136,187,169,248,128, 69, 96,217,223, 95,174, 35, 5, 16, 64, 0, 1, 4, +240,215, 67, 72,128, 47, 2, 8,120, 0, 2, 8, 32,128, 0, 2, 8, 32,128,128, 2, 16, 64, 0, 1, 4, 16, 64, 0,127,119,212, +113,233,204,153, 51,199,239, 8, 78,119,197,123,238,116,121,209,131,131, 16, 28,116, 5, 34,113, 5, 88,214,190, 44, 76, 32, 96, +192, 16,129,253,127,134,128, 16, 6,148, 8,237,107, 96, 97,197,150,109, 34, 80, 74, 17,201,180,132,143,215, 23, 4,160, 21,236, + 1, 60,213,176, 47,247,178,192, 49,167,246,103,108,191,128,188,128,188,128,188,128,188,128,188, 59, 83,158,207, 10,192,223, 13, + 63,238, 63,131,161, 67, 44,136, 8, 7,180, 58,130,159,127,149, 64,200, 8,113,255,120, 27,118,171, 91,131, 16, 6,132, 97, 32, +105, 14,140, 25, 90, 1, 64,136,123,227, 41,242, 11,132,118, 26,231, 1,245,193,253, 20, 0, 68,212,130, 97, 35,199, 20,159,254, +237, 39, 83, 89, 85,109,140,205, 80, 11,185, 92, 30, 14,160, 50,160,135,254,185,145,253,205,127,165, 61,186,119, 83, 95,187, 86, +219,168,132, 79,127, 34, 72, 83, 83, 83, 93,243, 0, 52,234,158, 83, 83, 83,253, 78, 7, 28, 64, 0, 1, 52,145, 7,128,195,154, +175,190,224,173, 77, 60, 49,115,150,215,151,181,169,229, 53, 37,242, 11, 68, 72, 76,176,225,215,223,130, 33, 22, 9, 33, 20, 8, + 33, 18, 81, 4, 9, 44,128,176, 57,132, 48, 98,104, 95, 43, 36,226, 32, 80, 0,237,219, 2, 15,222,207, 98,207,102,126,228,127, +230,247,211,184,171, 79,119,116,136, 10,199,197,226,147, 93,194,218,117, 67,171, 14, 54,252,240,253,247, 80,169, 84, 21,183,123, +125,188, 74,165,186, 63, 43, 43,107, 27,183,157,148,148,244,128, 92, 46,223, 22,120, 53,188,227,183, 95, 85,212, 90,123, 92, 54, +237,193,238,106,150, 45, 71,101, 7,163,250,228,177,141,168, 49,181,199,144,216,145,127, 89, 18, 75, 77, 77, 85,207,155, 55, 15, +132, 16, 94,101,123,249,128, 75, 22,211, 4,229,230, 3,104,164, 2,230, 17,148, 34,243,243,207, 27,124,222, 92,130, 31,215,108, +129, 92, 13, 1,151, 90, 2,206,231,236, 90, 25, 49,128,166, 5,151, 13,144,131,187,220, 0,119,148, 7,128,193, 31,219, 15,238, + 31,103, 1,133, 0, 66,129, 8,195,135, 17,180,105,205, 64, 40,100, 16, 36, 18,160, 87, 12,131,226, 11, 86, 12,141,101,208, 50, + 82,130, 31,246,182, 0, 0, 8,168, 17,246, 84,216, 54,175,228,255, 91, 65, 1,186,118,232,136,223,114,243,112,200,108,129,238, +186, 14,226,160,230,232, 61,104, 4, 6,140, 24, 7,245,150, 44, 0,252,114,227,223, 2,226, 31,147,149,149,181,103,225,194,133, + 40, 40, 40,224, 58, 76, 5,128,231,102,207,158,189, 53, 41, 41, 73, 46,151,203,247,252,229, 94,138,159, 85, 52, 72,168,133,144, + 49,163,182,214,134, 74,125, 48,238, 29, 53,197,167,246,223,152,253,149,180, 69,176, 22,255,152, 58, 24, 93,187, 60,168,110,209, + 34, 12, 22,171, 21,215,174, 93, 71,219,146, 11, 40, 60, 91,132,131, 7,180,116,248,136,135,252,122,174,153,153,153,212,101,112, +190,211, 6, 71, 41,112,163, 28,174,163, 58,160, 20,183, 41, 29,240, 31,248,190,208, 77,155, 54,221, 92, 79,225,182,145, 23,149, + 18, 16,208, 38,104,119, 90,242, 13,200,161,217,174, 28,239,200,146,233,168,134,228,130,217, 25,122, 12,157,250,177, 71, 69,238, +135, 31,126,112,110, 39, 38, 38, 98,199,142, 29, 30,183, 3,184,245,228,239,186,207, 85, 17,240,168, 0, 28,216,127, 8, 35,238, + 29,246,135, 93, 52,235, 67,254, 84,215, 84,146,254,102,159, 98,132, 2,232,180, 66,180,107, 35, 66,187, 54, 98,212,212,136, 32, + 17, 9, 97, 19, 6, 97,112,127,130,129,119, 11,192, 16,145, 61, 5,166, 72, 12, 17, 99, 2,145,136, 97, 53, 0, 86,232, 61,146, +255,254,189,123,208,173,125,107, 28,251,245, 24, 22,189,253, 70,157,235, 91,242,230,187,148, 17, 16, 12,142, 29,140, 31,118,236, +241,169,242, 30,203,178,210,130,130, 2,245,153, 51,103, 16, 28, 28,140,224,224, 96, 89, 98, 98,162,198,199,193, 76,150,149,149, +181,135, 35,126,151,206, 17, 14, 96,220,127,254,243,159,235,179,103,207, 86, 1, 72,144,203,229,170, 59,177,131,175, 90,181, 74, +154,146,146,194,251,190,191,222,176, 70,218, 47,166,185,186, 75,251, 90,132,181, 8, 2,195,132,192,104,180,162, 92,107, 68,142, +106, 5,149,180, 24,140, 97, 67, 71,241,234, 71, 34, 92,193,164, 7,238, 86,247,237,219, 27,151,175,232,112,248,231, 35,168,169, +209, 35, 44,172, 57,162,163,187,128, 17,136, 96,179,149,224,231, 95,246,211, 65, 3,239,253, 75, 89, 55,169,169,169,234,231,159, +127,222,185, 61,111,222, 60, 44, 95,190, 92,253,185, 7,171,208, 39, 50,186, 67, 61, 0, 14, 37,157,102,103,103,195, 93, 97,165, + 63, 18,174, 86,182, 82,153, 33,163,180,113, 74, 0,211,229, 81, 39,121,231,191,215,204,173, 25,214, 46,156, 65, 84, 36,243,167, +125,126,127, 87,184,146,189, 59,165,192,171, 7,224,192,254, 67, 0,208,104, 69, 96,255,115,133, 30,143,223,251, 81, 15,191, 7, + 11, 66,136, 95,213,246, 84,154, 54, 16, 9, 69,232,212,161, 6,213,213, 34, 28, 62,214, 9, 2,129, 0, 2, 34,128, 88,100, 69, +223, 30, 6,244,236, 33, 0, 1, 3,177, 40, 8, 98, 1, 65,236,221,102, 68, 70,176, 88,247,165,103,217,189,187,181, 69,241,217, +178,155,200, 31, 0, 22, 45,126,133,188,251,246,191,105,251,248,187, 17, 17,222,156,247,245, 26,141, 70,233,242,229,203,213,197, +197,197,117,244, 13,147,201,132,135, 30,226,111,109,102,101,101,237,117, 37,127, 55,104,149,158,158, 94,241,194, 11, 47,236,190, +221, 83, 20, 13,145,255,161, 67,135,212, 41, 41, 41,188,175, 45, 38, 58, 82, 29,213,182, 10,173, 90,134,162, 99, 84, 59,132,132, +134,160,184,184, 20, 54, 27,139,168, 14,205,113,252,247, 92,172, 62, 85, 40, 77,126,124,150,199,193,244,232,209,253,244,145,137, +189,209,185,115, 71,156,248,189, 24,135, 15,255,142,107,215,171, 65, 41, 16, 17, 17, 12,131,161, 6,131, 6,245, 69, 69, 69, 37, + 74, 15,255,140,175,254,119, 90, 58,243, 31,252, 21,149, 59, 28, 82,192, 94,124,138,195,135, 31,126,200,109,251,228, 5, 72, 77, + 77,165,174, 46, 97, 87, 11,210,213, 37,221, 20,211, 11,111,191,253, 54,237,212,169, 83,163,115,241,203,229,114, 66, 8,161, 27, + 55,110,244,152, 99,159, 67, 90, 90, 26,117,231, 33, 88,189,122,181,148, 43, 14,228, 78,137, 85, 40, 20,180,161, 84,174,174,245, + 28, 40,165, 80, 40,210,212,141,241, 66,212,151, 55,244,229, 26,252,244, 94,179, 58,196, 31,192,159,211,250,175,223,135, 26, 53, + 5,208, 88, 69,224,222,143,122, 52,168, 4,248, 67,254, 28,114,114,114, 80, 90, 90, 10, 0,136,138,138,162,190, 40, 1, 2,106, +132,144,216, 32, 22,137,240,243,177,214, 16, 8,133,104, 46,210,219,227, 0,154, 49, 40, 45,109,142,187,251,178, 32,132, 32,233, + 65, 43, 40,203, 0, 36,200,238,120, 67,117,131,114, 13, 21, 23,112, 69, 91,131, 23, 94,127,189,193,107,169,168,212, 66,119,237, +138, 67, 22,111,226,174, 79,254, 0,128,237,219,183,195,102,179, 73, 31,121,228, 17,175, 3,156, 74,165, 26, 83,191,244, 47,215, + 97, 42, 43,235,196, 35,134, 47, 94,188, 24, 42,149,106,236,157, 52, 21,192,145,191, 47,223,249,122,195, 26,233,221, 49, 38, 4, + 7,135, 67, 18, 36, 70,183,110, 93,209,169,107, 87, 84, 85,105,160,213,214, 64, 44, 22, 32, 50, 66, 2, 97,112,184,199, 92,241, + 0, 32,164,165,104,222,172, 37, 12, 70, 43,142, 29, 43,196,165, 43,149,184,124,165, 6, 70,147, 4,157,163,172,144, 4, 9, 80, +120,186, 8,119,117,239,142, 75,151,171, 96,180,182,240, 42,211, 65,116,212,219,126, 95,167, 3, 26,146,233,143, 44,206,250,159, + 55,111,222, 77,251,159,127,254,121,191, 98, 1,220,145,104,253,185,227,166,242, 42,228,230,230,170,209,200,130, 60,123,246,236, +161, 89, 89, 89, 72, 74, 74,130,187,233, 0, 62,158, 42,142,252, 1, 32, 63, 63, 95,205, 48, 76,157,107, 90,189,122,181,148,143, +209, 19, 31, 31, 47,227,228, 52,133,199,101,227,243,161,152,178, 92,239,150,248,163, 34, 25,199, 40,197,239,241, 38, 38, 38,214, +241,146,220,119,223,125,117,218, 42,224,246,191,115,224,115, 12, 64, 83,121, 4,154, 18,133,133,118,197,162,180,180,212, 39, 37, + 64, 40, 20, 66, 36, 16, 65, 36, 34, 24, 53, 2, 48,232, 77, 56,119, 86, 12,145, 80, 4,161, 77,136,184, 97, 20, 98,145, 8, 2, + 1, 3, 80, 2,173, 14,248,233,136, 16, 44,203, 2,184,214,160,220, 35, 63,159, 69, 77, 77,195, 25, 56,223, 95,188,152, 6, 5, + 73, 96, 52, 86,194,198, 90,121,223,231,145, 35, 71, 26, 86, 58, 12, 6, 94, 68, 83,223,245,239, 78, 51,220,178,101,139,235,249, +170,219,225, 5,112,231,226,119, 37,255,248,248,120,222, 85,232, 58, 70,181, 85, 51,204, 5, 88,109, 44,204, 22, 43,174, 93,215, + 66, 36,150,192,100,178,192, 98,181,193,106,101, 97,181, 81, 84,232,174,123,149, 37, 22,233, 33, 9,238,136,242,242, 74, 84, 85, + 27,160,213, 25,209,162,229, 0, 12,191,251,110,228, 31,216,129, 14,102, 43, 42,171, 42,209,179,103,119, 4,137,133,208, 87,107, +255, 42, 99,133,148, 82,234,156,251,119,197,138, 21, 43,252,138, 5,152, 55,111, 94, 29,111, 66,253, 99,124, 21, 0,123,169,103, +206,162,141,196,216,177, 99,235,244, 87,206, 64, 40, 41, 41, 81,171, 84, 42,191, 10, 83,169, 84, 42, 39,249,115,211, 1,155, 54, +109,242, 74,174,245, 61, 85,185,185,185,106, 46,240, 77,161, 80,208,188,188, 60,117,114,114,178,243,120, 94, 94,158,154, 16,207, +151, 23, 31, 31, 47,115, 45, 51,156,150,150, 70, 61,181,149,183,241, 48, 41, 41, 9,147,227, 85,216, 0, 96,234,114, 61,238,121, +185,198, 99,219, 15,157,234,185,173,234,207,241,123,139, 9, 8,224,214,123, 3, 26,242, 0,252,161,254, 29,119,150,126, 99,172, +255,122, 22, 43, 10, 11, 11,177, 98,197, 10,222,165, 38, 5, 2, 33,226,134,178, 16, 48, 66,252, 84, 32,193,169, 66, 9, 38,140, + 7, 30,184, 15,152,152, 72,208,190,173, 24, 18,113, 16, 36,226, 32, 4, 75,130, 16,213, 62, 8, 18,177, 4, 18,177,231,146,152, +175, 45,122,149, 44,125,239, 45,210,208, 64,210,189, 91, 23,132,133,135, 66,194,154, 81, 99,176,252,225,157, 98,255,254,253,123, +246,239,223, 95,135,240, 93,255, 0,160,188,188, 28, 19, 39, 78,188,109, 86,126,126,126,190,218,213, 26,226,246, 1,192,176, 97, +195,124,178,228,108, 54, 64,111,176, 64,175, 55,163,170,202,132,171, 87,117,184,116,233, 58,170,171, 77,168,169,177,160,166,198, + 12,189,222,130,202, 10,239, 43, 50, 77, 38, 43,106,107,109,176, 88,204,104,222, 92,140, 78, 81, 45, 16, 18, 26, 10, 0,136,238, +222, 21, 29, 59,180, 64, 88, 11, 9, 40,181,193, 98,101, 97, 50,233,255, 18, 3, 73,106,106,170,122,254,252,249, 30,201,156, 91, + 26,200,211, 59, 33,115, 40, 13,110,177,124,249,114,124,254,249,231, 62,151, 26,182,187,197, 21,212,245,143, 35,212,210,210, 82, +100,101,101,249, 92,138,118,207,158, 61, 52, 59, 59,219,149,252, 33,151,203,201,228,201,147, 61,126,111,206,156, 57, 32,132, 56, +173,250, 85,171, 86, 73, 1, 32, 46, 46, 78,230,170,196,186, 30,167,148, 58,143,243,184,219, 58, 86,188, 59,197,193,155, 50, 1, + 0,173, 90,181, 2,113,177, 30, 26, 43, 47,128, 59,143,252,221,109,251,229, 1,184,147, 44,255, 27, 3,188, 13, 2,129,192,231, +239,141, 24,202,162, 77,235, 32, 84, 85, 9, 17, 36,180, 34, 72, 44,128,230,144, 24, 19,100, 34,136, 69, 34, 84, 85,137,112,160, + 32, 20, 45, 36, 4, 12,195, 32, 81,110,198, 67, 19, 40, 24,134,226,157, 95,124,191, 78,149, 74, 69, 5, 33, 18,104, 69,173, 16, + 98,185,136, 51,165, 20, 99,164,163,120,127,127,208,160, 65, 56,120,240,160,219, 99, 33, 33, 33,188, 7, 75,157, 78, 55,214, 49, +240, 32, 57, 57,217,185,191,188,188,220,249, 57, 57, 57, 25,101,101,101,183,229,121,166,164,164,104,242,243,243,145,155,155,171, +102, 89, 86,198, 48, 12, 56,203,191,161,121, 83, 79, 40,185,112, 73,214,186,133, 65, 29, 36, 22,192,108, 97, 81,107,186,136, 11, + 23,203,161,213, 85, 65,171, 53,160, 92,107, 68,185,214,136,240,200,174, 94,101, 93,189, 78,113,229,234,117,244,238,221, 29, 21, + 58, 29, 68, 66, 6, 85,213, 23,161,175, 96,209,231, 46, 61,218,182,110,141,144,144, 16, 4, 5, 5,227,242,149,106, 16, 65, 4, + 95,130, 37, 46,228,216, 36,171, 0,154,122, 5, 65, 67,214, 58, 80, 39, 22,128, 47, 52, 0, 48,119,238,220,155,188, 10, 46,211, + 12, 26,127,174,115,202,148, 41,117, 44,216,172,172, 44, 39,121, 61,250,232,163, 72, 72, 72, 32,124, 19,167,184,177,252,157,168, +239,105,168,143,129, 3, 7, 18, 74,169,211,202,207,207,207, 87, 19, 66,156,165,129,147,147,147, 53,185,185,185,200,205,205, 85, + 39, 39, 39,147, 67,135, 14, 57,143,175, 92,185,178, 65,185,185,185,185,106,134, 33,178,188, 60,251, 59, 49,103,206, 28,252,242, +203,207, 50,142,194,243,242,242,212,220,253,243, 81, 38, 86,174, 92,137, 79,101, 17,152,186,194, 0,192, 62, 29,224,138,169, 43, + 12,206,246, 76,145,137, 2,204,250,103, 81,218, 23,190, 95, 87,233, 94,250, 18,126,249,229, 23,254,171, 0,110, 5,241,187,198, + 2, 52,198,250,175,107,201,215, 37,255,196,196, 68, 40, 20, 10,175, 83, 1,173, 90, 9,192, 16, 1, 90,183, 18,160, 71,119,138, + 75,151,132, 96, 4, 4, 34,161, 16, 34,161, 8,191, 29, 13, 69,100,168, 8, 2,129, 0, 35,134,217, 16, 28, 28, 4,150,165, 0, +181,249, 69,254,205,218,118,194,213, 26, 10,253, 25, 13,132, 68,128, 23, 23, 47, 34, 62, 14,108,178, 11, 23, 46,168, 47, 92,184, +112,211,253, 78,154, 52,137,215, 96,153,148,148,148, 80, 94, 94,190,155, 35,121, 0,152, 56,113, 34, 86,175, 94,237, 60,167,170, +170, 10,101,101,101,216,186,117, 43,146,146,146,198,220,142,206, 27, 23, 23, 39,203,205,205, 85,231,231,231,171,185, 96,177,184, +184, 56,191,230,112,103,254, 35,229,255,217,251,242,240,166,170,252,253,247,220,236, 93,105, 75, 41, 75,217,165,130,108, 5, 42, + 32,107, 2, 5, 20,176, 34,180,200, 38, 95,100,102, 26, 24, 87, 96, 20, 69,231,231,204,168, 40, 46,128, 35, 35,180,140,138, 11, + 21,105, 21, 44, 88, 4, 10, 9,139,136,149,138,128, 44,178,148,181,133,174,105,211, 52,123,238,249,253,145,222,152,134,180,185, + 73,195, 58,247,125,158, 60, 77,238,189,249, 52,247,220,115,206,251,217,206,231,104, 55,124,153, 9, 90,172,135,209,100,131, 78, +102, 6,133, 14,102,179, 29,122,189, 5,101, 21, 70,148, 92, 53, 96,184,170,163, 79, 89, 38,107, 75, 20,157, 47, 71,151,206, 29, +208,185,115, 60, 42, 43, 43, 16,213,194,129,110,221, 34,209, 42,182, 11,228, 10, 5,170,171, 13, 40,252,229, 20,174, 20,235,209, + 58,190,231, 29, 59,129, 80,128, 18, 2, 21,199,165,238,164,218,212,186,125, 90,159, 44,120,189,249,136, 6,171,202, 50, 51, 51, + 85, 43, 87,174,212,120, 42, 0,203,151, 47,231, 10, 12, 53, 41,143, 82, 74, 9, 33, 68,173,142,114,251, 77,244, 58, 98,206,206, +118,134, 8, 82, 83, 83,121,185,255, 27,134, 20,118,121, 37,127,190,120,224,129, 7, 84, 7, 15, 30,212,112, 94,135,161, 67,135, +170,188,157,231,146,241,124, 17, 54, 23, 91,255,225,135, 3, 26, 66, 8, 8, 33, 72, 76,236,171, 74, 76, 76,212,186, 41, 8,245, +215, 2,190,198, 11, 39,143,153,170, 3, 39, 47,109, 84,167, 6, 15,106,234,138, 19, 46,121,124, 32,228, 0,220, 57,240,169, 0, +220,142, 22, 63,135,105,211,166, 53,235,251, 12,195, 64, 36,114,190,122, 36, 48,232,215,219, 1,153, 84,238, 84, 0, 36, 18, 12, + 25, 4,200,100,128, 68, 36, 67,203,150,114,136, 68,117,112, 56, 88,176,172,255,110,123, 99,213, 53,200,227,187,227,124,254, 23, +136, 21, 51,120,252,229, 37,126, 79, 40, 10,133, 66,187,100,201, 18, 85,115,150, 1, 38, 39, 39,231,171,213,106, 60,245,212, 83, +174, 99,156,165,175,215,235, 97, 52, 26, 49,119,238, 92, 0,192,135, 31,126,136,140,140, 12,205,173,120,182,115,230,204,209,178, + 44,171,226, 44,255,129, 3, 7, 54, 43,129, 43,190,227,189, 56,116,112, 59, 90,181, 12, 65, 72,136,179,219, 91, 44, 14,232,107, +173,168,210,153,208,190,115, 79, 12, 27, 50,210,231, 51, 25, 63,126, 10,217,177,237, 19,122,176,224, 56,134, 15,237,139,142, 29, + 59,194,102, 53,163, 95, 98, 31,132, 70, 70,226, 98,209, 37, 20,151, 84,227,135, 31, 79, 66, 87, 27,137, 71, 31, 24,121,199,250, + 76,231,207, 83, 3,128, 6, 32,152,175, 86,187, 8,156,245, 32,125,134, 33, 78,109,161,158,151, 9,128,190, 94,226,141,243,212, +106, 10, 10,183, 76, 21,130,244,244,244, 6, 94,128,103,159,125, 22,132, 16,204,155,167,214,112,236, 15, 2,244,237,155,232,141, +188, 92,238,120, 95, 36,199,151,252, 61,145,154,154,138,209,163, 71,171,154,211,143, 81, 31,171, 31, 52,104,144,106,246,236,217, +218,198,206,187,197,246, 27, 5,151, 59,192, 41, 95,206, 48, 2,209,122, 42, 21,124,127,159,167,188,141, 11,194,156,141, 46,143, +115, 93,179,113,193, 37,151, 66,176,253, 72,211,115,159,183, 58, 0, 66, 14,192, 29,170, 0, 12, 25, 58,240,134,196,124,130,101, +249,187,119,164, 64, 80,165, 35,104, 19,199,184, 74,254,238,216,229,140,239,203,100,114,200,164, 50, 60,252, 16,129, 92, 38,133, + 66, 78, 80, 85, 41, 66, 65, 97, 56, 28,172, 3,237,227,253,139,235,230,231,231,211,106,163, 9,186, 67,121,232,214, 94,130,223, +138, 3,143, 11, 51, 12,163, 29, 56,112, 32, 25, 56,112, 96,192, 50,210,210,210, 84,171, 86,173,210,112,110,254,202,202,202,199, + 6, 13, 26,100,216,185,115,231,119,143, 60,242,200,216,202,202, 74,242,248,227,143,111, 79, 75, 75, 83,221,202,206, 89,239,234, + 87,185,189, 15,188,207, 57,201,157,158, 62,117, 2, 37, 69, 23,193, 48, 4, 14, 7,133, 92, 17,141,132, 30,189,240,232,164, 52, +222, 29,189,164,156, 85, 85, 85,150,104,204,102, 59,122,247,234,130,118,109, 91,226,210,229, 82,232,142,157,195,239,167, 47, 97, +215,238,163,184, 88, 76,241,231,191, 60, 29,208,224,185, 93,138,255,176, 95, 69, 5,124, 93,191,165, 60,229,157,251, 4, 43, 87, +174,116, 41, 0, 43, 87,174, 4,138,214, 93,119,173, 55,121,141,120, 5,174,155,179,154, 91,172,135, 16,210,172,190,199,145,124, + 99,228,238,235,188, 55,175,130,199,119,189,201,227,255,156, 47,126,141,156,149,179,157,115,195,168, 14, 13,200, 31, 0,210,198, +223,239,124,163,251,213,167, 2, 32,212, 1,184,125,144,185,236,197,235,194, 0,126, 41, 0,183,115,194, 71,160,197,127,220,113, +232, 23, 25,228, 82, 41, 30, 30, 79,192, 16,130,129, 73,118, 28,251, 77, 1,134, 56, 99,254,213,213, 12,218,182, 22,129, 33, 82, + 28, 57, 38,133, 92, 6, 88,109, 86, 92,188,164,240,139,252,207,157, 62,140, 65,163, 39, 66,220,114, 16,206,157, 46,128,248, 90, + 14, 94,120,254, 37,250,246, 59,111,222,146, 6,174,175, 87,175, 74, 74, 74,210, 44, 94,188, 24,189,122,245, 42,211,233,116, 72, + 74, 74, 82,233,116, 58, 60,243,204, 51,154,180,180,180,219,162,174,125,115,137,223, 83, 9, 24, 54,100, 36,214,125,254,145,178, + 77,235, 54,154,208,208, 80, 94, 86,255,117, 19,236,236, 63,105, 1,144,245, 95,100,208, 19,191,255,132, 54,113, 97,144,203, 37, + 48, 24,172, 40,190,170, 7, 17,183,199,159,255, 50, 91,200,150,226,131, 95, 22, 1, 93,159, 64,131,229,133,133, 11,155, 67,214, +205,254, 73,243,230, 69,187, 41, 18,193, 33, 52, 95,164,236, 15,105, 55,183,158,129,183, 54, 75,123, 64,230,188, 87,211, 85,231, + 75,192, 29,139,196,196, 68, 87,194, 95,230,178, 23,175, 59,231, 83, 1, 8,118, 61,254,155, 93,223,223,175,206, 15, 2,157,142, + 32,164, 53, 65, 76, 52, 65, 82,127, 27,228, 82, 17,100, 82, 27, 98,162,229,245,147, 0,193,224, 36, 7, 10,126,145, 56,189, 5, + 60, 39,153,252,252,124,218,243,222, 8, 44,122,246, 95, 48, 73,227,241, 77,126, 49,186, 38, 56, 45,247,176,159,183, 98,209,223, + 94,162,239,189,123,235,148,128,228,228,100,146,159,159,175, 92,182,108,153,198,221, 59, 16, 12,229,234,118, 70,125,177,159,102, +223,227,204, 89,106,178,255,192, 30, 90, 94, 89, 14,211, 53, 35,228,242, 24,196,119,238, 19,144, 82,113,167,193, 89, 14, 59, 72, +183, 89,180, 14,174, 21, 1, 69,159,222,242,123,243,149,220,119,183, 97,236,196,199,252,178,220,125,249, 30,133, 28,128,219, 75, + 9,104,140,252,125,122, 0,254, 23, 64,225,204,234, 39, 12, 5, 5, 69,116, 11,138, 61,251,197,144, 75, 37,144, 73,197, 72, 25, + 79, 65, 41,139,168, 24, 59,236, 14, 2,150,117,212, 79,126,190,209,167,147, 1, 19,166,164,193, 32,238,134, 86, 97,161,152,241, +104, 52,178, 54, 29,115, 41, 1, 54,199, 55,183,252,254, 57, 69, 64, 24, 50,129,123, 21,238,214,123,203,212,189, 69,210,163, 94, +188,158, 25,178,163, 3,149,135,244,168, 23,175, 63, 81,184,176, 89, 86,191,128,230, 33,245,201, 85, 65,235,195,119,187,241,112, +167, 41, 1, 62, 13,224,196,196, 68, 33,104, 35, 64,128, 0, 1, 2, 4,252,143, 65, 40,244, 44, 64,128, 0, 1, 2, 4, 8, 10, +128, 0, 1, 2, 4, 8, 16, 32, 64, 80, 0, 4, 8, 16, 32, 64,128, 0, 1,130, 2, 32, 64,128, 0, 1, 2, 4, 8,184, 59,208, + 96, 21,192,252,249,243, 3,206,224,244, 86, 91, 59,216,242,102,206,157,231,243,123,117, 85,215, 92,239, 67,163, 91,187,222,175, +255,120,205,117,215,198,170,254,236, 83,222,206, 21,127, 84,204, 27,179, 96,149,235,125,185,230,191, 8,228,247, 53,134, 64,127, + 95, 99,240,246,251, 38, 61,174,246,249,189, 67,154,239,208,169, 83, 39, 92,184,112, 1, 73,170, 9,174,227,155, 63,207,184,225, +237,247,231,171, 87,155,236, 47, 22,177, 88,185,168,184,216,181,100,113, 85, 92,156,235,250,255,182,105,115,195,251,159,167,188, +220,220, 92,101, 94, 94, 94,131, 74,137,227,199,143, 87,165,164,164,104,111,197,248, 56,124,248,112,192,242,250,245,235,119,163, +127, 31,153, 63,127, 62,110,231,249,229, 86,200,203,202,202,154,222,187,119,239,172, 99,199,142, 77,153, 49, 99,198, 55,205,149, +231,190,209,145,123, 70,254,221,218,126,130,188,198,229,249,173, 0,120,194,110,183, 43,205,102, 51,136, 72, 2, 66, 8, 28,118, + 27,164, 18, 49,100, 50,153,182,185,154,135,221,110, 87, 2,128, 88, 44,110,150,172,186,170,107, 8,141,110,237, 34,254,214,237, + 59, 1, 0,174, 93,190, 16,144,188,157, 43,158,194,152, 5,171, 92,196,245,159,220, 2, 0,192,147, 41, 3,113, 55,226,144,230, + 59, 36,169, 38,224,144,230, 59, 0,192,132,212,153, 0,128, 11, 23,110,125,251,253,187,180, 84,121, 26,208, 36, 0,170,211,128, +115, 15,245,197, 47, 0, 0, 6, 46,123,251,150,182,155, 86,171,165,121,121,121, 48,155,205, 13,142,203,229,114, 77, 68, 68, 4, +148, 74,229,109,185, 28,138, 16, 50,236,222,206,237, 62,165, 14,135,241,244,165,107, 47, 81, 74,183, 10,118, 80, 19, 74,167,197, + 50,234,240,225,195, 17, 37, 37, 37,173,163,163,163, 91, 12, 24, 48,160, 56, 60, 60,252,243, 64,229,101,101,101,141,158, 49, 99, +198,158,172,172,172, 63, 3,136,156,246,196,188,185, 0,216, 99,199,142,205, 6,176, 25, 0,235,143, 60,110,207, 19,142,248,155, + 51,222, 60,119, 73, 12,214,146,190,198,148, 18, 1,183,153, 7,192, 29,250, 90,131,178, 77,194,253,154,145,189,187, 35, 68, 38, + 1,165, 20, 14, 7,197,111,103, 46,226,252,209,125, 42,133, 76, 2,145, 72, 20, 16,121,135,201, 47, 40,123,118, 43,210,252,118, +186,139,170,206,210, 41, 96,226, 7, 0, 69,100, 12,234,170,174,185,136,191, 41,143, 0, 31, 75,117,224,204, 23,177,115,197, 83, +174,129,212,216,117, 77,173,177,244,252,159, 82,169, 20,128,179, 76, 38,203, 58,199,183,195,225,112,253,126, 70, 36,225,109, 69, + 3, 64,155, 86,206, 82,157, 86,125, 53, 44,118, 59, 0,192, 96,119,202,235, 60,246, 79,184,167,103, 63, 94,196, 15, 0,125,135, +140,198, 33,205,119, 46,226,111,236,186,155,217,126, 0,240, 84,105, 41, 5,128,113,161,161,216, 94, 87,167,225,136, 31, 0,126, +223,177,243,186,235, 18,219,180,225,245, 59,107, 66, 43,148,133, 21, 63,163,248,210, 17,116,235, 56, 24,131,229, 74,191,251,112, +110,110,238, 35,219,182,109,227,200,223, 14,192, 12, 32, 4, 0,107, 54,155,197, 10,133, 2,122,189, 94,233,205, 19,112,139,201, + 63,238,254,196,222,219,182,127,185, 38,172,174,248, 36,134,165,205,207, 34,132,204,166,148,110,190,221, 38,166,252,252,124,218, +156,250, 20,124, 54, 3,107, 10, 54,155, 77, 89, 80, 80,160, 57,126,252,184,235, 88, 69, 69, 5, 78,159, 62,141, 54,109,218,124, +166, 84, 42, 85,225,225,225,124,159, 47,147,149,149,245, 79, 0, 15, 12, 27, 55, 73,145,149,149, 21, 55,237,137,121,225, 0, 28, + 0,184,142,123,111,253,117, 35,248,222, 31, 55,222,212,106, 53,109,108,188,113,215,249, 26,111,106,181,154,238,253,177, 0, 34, +145, 24, 14,135, 29, 53,181, 6,204,152,242, 8,125,247,221,119,155, 69,216,158, 74, 69,115,159,139, 0,223,240,182,237, 47, 7, + 94,149, 0,235, 76, 86,229,232,148, 25,154,246,173, 34, 17, 34, 23,131,101, 89, 56, 88, 64, 44, 34,136,142,236,142,158,221, 58, +104,242,183,127,167,114,216,234,148,254, 42, 1, 86,171, 85,217,163,231,121, 77,223,238,231, 33, 98, 28, 26,237,161,118, 42,169, + 68,226,151,140,186,170,107, 80, 68,198, 32, 50, 34, 28, 0, 92,127,189, 93,215,186,125, 39,159,222,128,157, 43,158,194,192,153, + 47,226,255, 30,155, 12, 0,174,191,222,174,251, 79,110,129, 95,218,181, 72, 36, 66,124,124, 60, 68, 34, 17,172, 86, 43,234,234, +234,224,112, 56,160,211,233, 2,122,184, 97, 98, 17, 62, 94,185, 9,178, 72,160,244, 2,240,179,161, 24,229,215,206,226,243, 21, + 47,249,101,245,247, 29, 50, 26,241,109,157, 33,146,120, 47,228,223,169, 83, 39, 87, 56, 0, 0,174, 92,185, 18,148,246,227, 83, + 92,245,169,210, 82, 58, 46, 52, 20,175, 61,245, 36, 0,224, 53, 55,226,255,226,244,233,134,228,239, 71,181,214, 61, 23,190, 80, +118,124, 66,172,121,177,195, 44, 88,216,100,200, 88,138,147, 21,187,240,201, 59, 27, 85,169,125, 50,248,246, 65,113, 94, 94,222, +102,147,201,132,117,235,214,153,231,204,153, 35, 7, 16, 6,128, 93,183,110,157,117,206,156, 57, 98,147,201, 4,185, 92,174, 73, + 73, 73,105,214, 68,247,205, 55,223, 40,119,236,216,161,105,110, 45,123, 87,223,145, 50,255,239,131,215, 94, 80,180, 56,241, 37, + 20,191,239,198, 63, 70, 69,133, 63,179,165,252, 95,245,150,231,109, 69,254, 27, 55,110,132, 78, 55,134,102,103,167,249,125,239, + 31,127,252,177,178, 57,100, 83, 87, 87,167,204,205,205,213,212,214,214,122, 61,127,245,234, 85,228,228,228,104,122,244,232,161, + 26, 60,120,176,175,126, 67,178,178,178, 62, 31, 54,110,210,212,211,135, 15,136,227,219,182,182, 79,123, 98, 94,131,121,119,247, +119,223,160,119,239,222,221,179,178,178, 30,234,221,187,119, 46, 0,236,223,191,191, 73, 82,229, 51,222,212,106, 53, 5, 33,128, +143, 42,127,107,214,172,161,215,202, 42,112,248,183, 19,174, 99,102,179, 5,111,127,144,105, 80,207,153, 46, 16,246, 93,140,235, +146, 0,107,107,107,149,195,198, 62,170,233,222, 33, 6, 50, 9, 3,150,101,113,237,218, 53, 28, 59,114, 24, 86, 59, 11,150,165, +136,137, 12,193,216,135, 38,106, 76, 22,187,223,255, 80, 38, 41, 67,215, 14,215, 0, 17,193,125,221, 46, 67, 38, 46,245,219,242, +119, 39,255,235, 44, 60,125, 45,174, 93,190, 0, 69,100, 76,163, 94,129,166,200,203, 19,159,126,245, 13,158, 76, 25,136,129, 51, + 95,108,212,170,245, 6,169, 84, 10,145, 72,132,136,136, 8, 20, 21, 21, 65,167,211, 57, 21,169, 0,201,191, 77,171, 56,132,137, + 69,120,244,233,215,241,208,140, 33,216,250, 91, 49,174,153,208,108,242,247,196,149,146,107, 56,126,232, 7,196, 70, 69, 56,201, + 95, 44, 10, 74,251, 61, 56,229,255, 0, 0, 81, 98,137, 95,228, 15, 0,127, 95,245, 31,252,125,213,127, 92,228,191,189,174, 14, +207,143,157,232, 60, 25, 43,229,117,223,159, 94,124, 75,249,151, 69, 15,104,158,232,248, 87, 72,152, 48,132, 34, 4, 12, 68,104, + 23, 55, 20, 79,189,182, 80, 83,212,118, 5, 47, 53, 66,171,213,218, 0,224,211, 79, 63, 53, 2,144,115,219, 40,175, 91,183,142, + 5, 16,226,190,173,178, 86,171, 13, 40, 46,103, 52, 26,149,254, 28,231, 97,249, 15,187,191,127,162, 49,251,155, 77,234,126,189, + 18, 68,117, 39,118,225, 66, 89, 45,174, 86, 27,193, 82, 26, 80, 34,112,122,122, 58, 77, 75,203,166,235,215,175, 15,106, 33, 49, + 55,242, 71,116,116,126, 64, 50, 10, 10, 10, 52, 25, 25, 25,132, 16,226, 82, 6,252,252, 13,215,145,255,161, 67,135, 48, 99,198, + 12,119, 15, 1, 78,157, 58,165, 49, 26,141, 77,110,152,149,149,149,245,212,176,113,147, 38,190,177,100,129, 56, 59, 59, 27,255, +253,224, 93,113,189,199,200, 69,254,217,217,217, 88,181,106, 21,122,247,238,157,235,107,188,121,146,127, 99,227,237,161,161,245, + 94,192,240, 80,159,242,222,251, 96,181,139,252,203, 42, 42, 81, 86, 81,137,154, 90, 3, 36, 18,113,216,234,117, 95,154, 61,173, +120, 1,119, 6, 18, 19, 19,175,123, 53,169, 0, 56, 28, 14, 26,211,169, 15, 58,181,110, 1,179,205, 1, 66,128,237,219,191,199, +103,159,174,195,209, 35, 71,240,252,194,231, 32, 18, 49, 96, 29, 44, 34, 66,100,232,212,103,152,198,100, 50,241, 30, 96, 54,155, + 77,217,179,219, 69, 77, 68,152, 17, 31,127, 90, 6,134, 80, 12,236,253,187,198,102,179,249, 53, 72,189,145, 63, 71,252,166,154, +202, 6, 10, 66,141,190,214,167, 60,111,131,137, 27, 72, 5,235,223,106, 64,112,159,126,197,175,124,111,215,174, 93, 17, 19, 19, + 3,189, 94, 15,169, 84, 10,134, 97, 96, 50,153,160,211,233, 32, 18,137,184,137,153,247, 61,127,189,121, 19,158, 91,185, 3,155, + 62,120, 5,109, 90,197, 33, 36, 52, 26,151, 29,197,248,124,197, 75, 8,171,159, 52, 68, 60,229,121, 35,127,142,248,107, 74,206, +161,123,124, 43,212, 26,205,144,133,200, 0,135,195,103, 62,128,175,246,123,105,237, 86, 28,255,229, 71,244,234,114, 31,106, 28, +190,149, 70,142,252,127,223,177, 19,127, 95,245, 31,215,241,237,117,117,216, 94, 87,135, 34,245, 63,177,227,196, 81,244, 28,216, + 5,168,244,189, 53,115,214,153,101,202,249,207,140,214,196,134,246,128,137,214, 2,150, 50, 72, 45, 85,176, 56,106, 97,102, 77, + 96,165, 97,104, 55, 60, 9, 57,191, 46,245, 53,209,145, 13, 27, 54,192,108, 54, 67,173, 86,135,168,213,106,192, 25, 2,128, 90, +173, 70,253,231,122, 11,202,140, 13, 27, 54,248, 61,104, 79,157, 58,165, 92,184,112,161,230,253,247,223,167,132, 16, 13, 0,236, +219,183,143, 46, 93,186,148,190,242,202, 43, 1,109,205, 28, 46, 99,214,253,231,197, 39, 20,227,218, 89, 68, 7, 78, 93,195,214, + 11, 12, 94,220, 86,106,249,167,214, 80, 83,103,195,255, 5, 34, 83,167, 27,115, 35, 45,127, 68, 71,231, 99,230,204,153,126,239, + 70,233, 78,248,107,214,172, 33,220,118,210,124,113,224,192, 1,101,105, 41, 63,163,196,106,181,226,216,177, 99,187,155,234, 47, + 0,148,241,109, 91, 75,211,210,210, 0, 0,133,133,133,216,253,221, 55,242, 43, 37,215, 88,142,252, 1, 32, 45, 45,205, 53,222, +142, 29, 59,182,162, 57,227,237,237, 57, 19,241,219,185,203,104,221,165, 13, 80,103,228,125,239,101, 21,149,176,217,236,245,115, +181, 29, 54,155, 29,151, 47, 94,144, 55,231,153,122,122, 15, 4,111,194,237,133, 6,174, 40,139,197,130,126,221,187,107, 66, 20, + 18,176, 44,133,131, 5,126,216,183, 31,255,124,237,117,176, 20, 56,115,246, 44,142, 30,249, 21,189,122,245,133, 72, 68,112,111, +151,120, 20,253, 98,135,130,231,230,120, 82,113, 25, 18, 58,149, 0, 98,130,203, 87,109,128,152,160, 79,247,139, 40, 56, 86, 6, +138,118, 1,221,128,187,123,223,155,103,192, 84, 83,217, 96, 53,128, 47,184,187,247,189,105,218, 5,235,223,194,152, 5,171,188, +102,177,187,195,110,183, 35, 36, 36, 4, 12,195, 32, 42, 42, 10, 70,163, 17,117,117,206,109,128, 99, 99, 99, 81, 89, 89,233,215, + 6, 28,102, 29, 48, 80,161,192,243, 31,236,195,152,190,192,197,195,192,207,245,231,158,255, 96, 31,254,189, 64, 5, 7,235,240, +187,253,142, 31,250,193,245,126,244,128,238, 16,135, 51,216,174, 61,129,126,221,219, 35, 34, 76,134, 79,115,242,145,164,154,128, + 43, 94, 86, 1,248,106,191,220, 19, 20,184, 10,164,140, 38, 88,187,181, 8, 49, 81,157, 49,121, 40,225,213,126,156,187,127,123, +221, 31, 91, 39,211,127,172, 0,218,213,128,252,229, 85,208,127,190, 6, 48, 38,144,130,165, 88, 21, 23, 71,254,219, 68, 32,160, +235,148, 48, 77,199, 22, 3,160,119, 24, 96,209,157,197,231,151,178,176, 63, 69,135,251,254,172,194,216,167,195,160,136,186, 23, +114,113, 20,196, 41, 53,248,249,155,159,233,253, 73,247, 55, 54, 73,185,254, 7,195, 48,160,148, 90,235,149,104, 51,195, 48, 70, + 74,105, 52,156, 73, 92, 1, 47,175,237,222,189,187,118,236,216,177,170,202,202, 74,205,246,237,219,157,138,207,246,237,232,209, +163, 7,186,119,239, 30,208,246,204,181, 22,246,153,185,127,255,247,150,119, 38,180,102,168,185, 6,127, 89,127,218,102,183,217, + 86, 89, 28, 88, 74, 41,173, 10, 68,230,164, 73,214, 27, 78,254, 35, 70,140,208,250, 43,167,160,160,160, 65,200,132,243, 2,240, +221, 85,210,225,112,248,165, 48,156, 63,127, 30,131, 6, 13,106,172,191,200, 1,220, 7, 64, 60,106,194,228,234,162,162,162, 22, +133,102, 28,210,109, 0, 0, 32, 0, 73, 68, 65, 84,133,133,200,206,206,198,128,162, 34,166,176,176, 16, 0, 48, 96,192, 0, 60, + 56, 50, 9, 17, 97, 50,172,250,100, 83,217,140, 25, 51,150,172, 94,189,122,129,191,227,237,234,230,183, 16,222, 83,142,176,110, +207, 97,227, 91,127, 70,223, 94,173,113,239,196,215,145,145,145, 65,154,202, 18,175,209,215, 66, 46,151, 1, 0, 36, 18, 49,140, + 70,115, 80,159,173, 64,250,183, 6,126,111, 6,196,178, 44, 66,100, 82, 88,237, 20, 12, 1, 24, 2,188,250,175,215,225, 96,129, +186, 58, 3,174, 93,187,138,184,184,214,160,148,133,221, 14,200, 37, 98,136, 36,252, 92,176,118,187, 93,121, 95,215, 43,154,150, + 81,122,128, 16,167,110, 76, 0, 66, 40,250,247, 60,163,249,233,104,156,202,223, 21, 1,156,117,223, 88, 72,128,143,245,239,169, + 69, 55, 70,252,254, 88,255,128, 51, 97,168, 85,171, 86,144,201,100, 46,151, 33,151,248, 23, 25, 25, 9,137, 68,130,203,151, 47, + 67,194, 83,222, 39,249,123,240,231,137, 35,193,153, 55,167,237, 78,247, 63, 0, 40, 19,128,136,215, 53, 88,240,183, 33,136,242, +227,126,175,148, 56,147, 21, 59,180,138,134,206, 98,129, 56, 66, 4,115,185, 17, 96, 24,180,233, 24,143, 29,187,127, 14,168,253, +254,111,209, 27, 56,255,195, 46,136,175, 1,213,113, 64, 8,195, 96,112,167,206, 24, 53, 50,142,151, 28,207, 88,255, 23,143,253, + 25, 95, 91,126, 7,238, 49, 3, 63,137,129, 48, 49,240,240, 0,196, 63,204,207,120,237,218, 46, 26, 86,107, 21, 36,118, 27, 62, +191,148,133, 31,231, 68, 98,196,163,143,160,123,171, 30,170,223,118,104, 53,253,210,234, 32,177,214,193,222,157, 69,121, 41,191, +164,209,122,229,205, 60,103,206,156, 48, 0, 58, 74,169, 4, 0,230,204,153,211,236,218, 26,147, 39, 79,214,238,223,191, 95,117, +242,228, 73, 77, 72, 72, 8, 66, 66, 66, 48,115,230,204,128, 38, 81, 66, 72,235,137, 19, 39,174,253,219,223,254,198, 60,191,224, + 25,182, 23,123,150,177, 88,109,117, 86, 7,253,155, 63,114,210,211,211,169, 78, 55, 6,147, 38, 89, 49,115,230, 76, 18,232,239, +185,145,228,239,205,221,191,102,205, 26,162, 86,171,233,220,185,115,121,253, 94,131,193,208,192,237,239,142,133, 11, 23, 98,225, + 66,231,166, 69, 73, 73, 73,238,215,203, 26, 17,215, 22, 64,167,122,165, 48,228,193, 41,179,204, 93,186,116,145,103,103,103,131, + 35,255,180,180, 52,196,181,105,227, 62,222,182,194, 45, 68,192,103,188,165, 63, 60, 2, 7, 75,202, 16,222, 55, 28,197,219,207, + 1,114, 25,166, 60, 61, 27,209,241, 19,121,206,205, 14, 20, 95, 45,181, 75, 36, 98, 49,231, 1, 0,128,203, 23, 47, 52,235,185, + 54, 22, 58, 16, 20,130, 91,167, 16,120, 42, 1,140, 55, 19,135, 82, 10,150, 2, 14,214,169, 4, 16, 2,124,243,117, 14, 30,157, +156,138,150,177,173, 92, 19, 32,245, 99,175,108, 17, 83,134,158,247, 92,118,125,238,211, 43,196,229, 36,235,127, 95, 17, 68, 76, +153,223, 55,228,233,238,247,118,222, 31,235,223,211,221,239,237,188,251, 90,246,166,160,215,235, 81, 91, 91, 11,139,197, 2,150, +101, 81, 94, 94,238,114,255, 27,141, 70, 24, 12, 6,191, 66, 0,155, 62,120, 5,218,223,128,154, 11,128,205, 4,252,123,177,202, +229,254,255,229, 48,240,235,213, 31, 32,242,179,253,106, 74,206, 33, 58, 50, 20, 49,209,161,184, 55,161, 7,138,206,151,227,116, +113, 37, 58,196, 68,194, 82, 90,134,179,103,206, 54,168, 5,192,167,253,134, 40, 31,193, 48,213,116,108,218,178, 17,154,189, 27, +145,181,124, 17,166, 44, 90,138,163, 54,160,188,178,140, 87,251,185,199,250,159, 24, 50, 8, 51,239,235,136,141,155,118,227,232, +209, 11, 88,126,172, 16, 27,198,204, 6, 62, 58,128,226,226,242, 6,181, 0, 26, 67,188, 89, 6,135,181, 2, 86,107, 13, 0, 32, +174, 93,123,116,239,209, 67,165, 87, 56,115, 49, 76,172, 17,140,165, 14,138, 58, 17, 74,175, 94,243, 69,168, 78,143,140,217, 12, +179,217, 44, 7, 96, 5, 16,110, 54,155, 35, 60,151, 4, 6, 10,163,209,168,220,187,119,175,166, 71,143, 30,152, 53,107,150,170, +162,162, 2,219,183,111,231, 61,216, 8, 33,195,100, 50,153, 33, 60, 60,220, 62,102,204,152,171,139, 23, 47,110,187,100,201,146, +162,159, 15, 31, 29,191,225,184,229,148,141,133,223,251,177,222, 8,151,127, 48,201,223,211,250,231,114, 20,220,189, 0,124,100, + 72, 36,127,168,228,203,151, 47,119,189,188,125, 6, 92, 43,124, 26,123, 54,210,250, 23, 3, 64, 92, 83,114,206,171, 59,157, 27, +111,135,127, 57,124,126,198,140, 25,233,254,140,183,225,247,223,139,228,161, 9,120,227, 95,239,226,189,149,121,248,127, 95,236, +198,188, 81, 73,184,246,109, 30,106,116,122,159,100,155,145,145, 65,210, 82, 30,132,205,102, 63,108,179,217,237,238, 10, 0, 0, + 44,125,245,165,128, 9, 91, 32,250, 91, 11,111,177,127, 79,175, 64, 3, 5,128, 97, 24,212, 24,140, 16, 49, 4,118,187, 3, 44, +165,176,179,206, 36,210, 35,191, 30,198,168,209,227,156,110, 50, 74, 33, 98, 68,168, 53, 90, 97,183, 90,124,107,152, 14,135,178, +115,187,171,154,216,232, 26,151,150, 49,100, 96,152,115,216, 16, 2, 66, 40,250,245, 56,171,177, 59, 28, 74,190, 55,199, 89,247, + 77, 37, 3, 6,100,189, 54,145, 92,227, 15,162,162,162, 80, 94, 94, 14,153, 76,134,218,218, 90,196,198,198,186,146, 2,205,102, + 51,170,171,171,253, 82, 0,210,223,216,128,127, 47, 86, 33,178, 19,160,253, 13,120,102,153, 6, 97, 98, 17, 38, 63,251, 38,174, +176,215,176,126,249, 11, 16, 49,252,229,113,214,255,128, 1, 9,136,237,210, 9,173, 98, 91, 66,202, 16,216, 9, 69,121,157, 9, +186, 90,115, 64,237,247,222, 91,155, 49,169, 71,103, 68, 68,196, 32, 36,182, 45,108, 85, 58, 28,222,250, 37,170,171, 46, 5,212, +137, 63,126,235, 41, 96, 65, 50,196,118, 43, 58,213, 1,101, 34, 61,254,125,245,103, 64, 26,193, 91,198, 47, 91, 14,170, 42, 24, + 19, 46, 73,141, 72,186, 71,133,251,102,135,161, 40, 74,171,137,141, 61,172,105, 63,184, 8, 53, 76, 45, 44,212, 4,227, 23, 44, +228, 97,225,124, 44,127,247, 9,158, 91, 5, 32, 13,214,192,253,254,251,239, 1, 0, 51,103,206, 84,117,239,222, 93,251,232,163, +143,186, 44, 70, 62,228, 31, 27, 27,187,109,237,218,181,161, 25, 25, 25,162, 5, 11, 22,224,185,231,158,163, 7, 14, 28, 24, 76, + 41,221,110,180,209, 30,148,210,159,252,183,230,162, 26,117,251, 7,154, 16, 24, 76,242,247, 36,120,119,133,101,205,154, 53,164, +160,160,128,151,107,255,202,149, 43, 7,184,247, 89, 89, 89,174,151,231, 49, 14,209,209,209, 0,208,216, 36,120, 5, 64, 53, 0, +230, 74,201, 53,252,248,227,143,174,152,255,128, 1, 3, 0, 0,217,217,217,248, 42, 55, 15,186, 90,179, 17,192, 82, 56,151, 6, +242, 30,111,223,110,250, 7,198, 45,126, 26,227,199,143, 70, 75,153, 8,181,132, 98,251,233,203,248,241,183, 98,191,136,122,254, +156,233,247, 23,157, 61, 43,190,124,241, 2,184,215,210, 87, 95,106,210,146, 23,112,123, 19,191,231, 49,111,104, 16, 2,144,201, +100, 56,115,226,168,170, 83,219,104,141, 66, 34,134,195,193,130, 16, 2, 66,128,116,245,147,160,148,133,163,190, 30,128,209,108, +198,201,211, 69,144, 74,125, 59,177,237,182, 42,244,187,239,188,251, 44,138,191, 46, 56,143,175,191,232,230,210,157,147,122,157, +195,193, 35, 61, 32, 22,197,250,101,253,123, 35,126, 83, 77, 37, 0, 4,100,253,123, 27,104, 5,235,223, 2, 0,222,214, 63,224, + 92,231,223,186,117,107, 88, 44, 22,148,150,150,194,225,112,160,101,203,150,168,172,172, 68,203,150, 45,235,219,149, 63, 97,151, + 95, 59,139, 87, 94,215,160,230, 2,240,206,162,225, 48,216, 29, 88,184, 44, 27,239, 47, 78,195,162,229, 91, 33, 38, 4,126,240, + 63,106, 74,206,161, 77,203, 22,144, 64, 2, 7, 8,174,158, 63,142,139,101, 53,232, 26, 27,141,111,127, 57,128,147, 39,224,183, +245, 63,101,238, 66, 72,162, 1, 70, 4,172,203, 59,143,175, 63,124, 30,115,223,202,192,194,135,251,226,201,209, 29,253,106,191, +237,117,117,120, 47,101, 42, 80, 45, 7,136, 4,120,239, 93,164,254,188, 15, 59, 70,207, 7,121,243,105,144,131, 47,240,178,254, + 1,224,215,171, 49, 24,100,170,129, 65, 33,130, 81, 46, 71,215, 41, 18, 88,168, 9, 53,140, 4,118, 36,128, 58,140,176, 85, 92, +197, 15, 31,212, 96,230,140,174,183,100,208, 22, 22, 22,210,122, 98, 32,147, 39, 79,214, 58,125, 99, 78, 12, 31, 62,156, 12, 31, + 62,156, 15,249, 15,109,219,182,237,247,111,190,249,102,232,153, 51,103, 32,145, 72, 16, 17, 17,129,163, 71,143,218, 40,165,229, +205,249,125, 77,173,201, 15,196, 59, 16, 76,242,247,180,254,157,196,122,253,242, 65, 62,185, 0,105,105,105,103,190,250,234,171, + 33,118, 59,191, 21, 78,114,185,124,110, 19,167,107, 1,156, 7, 48,224,244,225, 3,112,143,249,255,117,238, 84,124,223,165, 11, +184,112,192,182, 46, 93, 66,102,204,152,241,137, 63,227,237,177,228, 65,136,100,163, 96,132, 4, 95,175,120, 26, 31,110,253, 21, +207, 63, 56, 12,115,150,103, 33,117,233,231,126, 89,224,238,197,132,188, 29, 19,214,239,223,157,104,224, 1, 16,137, 68,164,250, +234, 89,156,187, 92, 9,177, 68, 4,187,131,133,205,238,192, 47,191, 20,226,179,207, 62,129,213, 65, 97,115,176,144,138, 25,148, +233, 12, 40, 62,249,163, 74,161, 80,104,125, 16,161,178, 71,215,139,127, 88,255,206,169, 10, 95,127,145,224,156,227, 24, 10, 48, + 20, 12,195, 98,112,223,147, 26, 7, 15, 47,128, 55,235,223,125, 21, 64,104,116,107,191,200,223,155,245,239,158, 85, 59,102,193, + 42,191,200,203, 57, 41,234, 96, 48, 24, 32,145, 72, 92,214, 63,203,178,174,191,254, 42, 0,159,175,120, 9,191, 20,239, 65, 88, +107,103,210, 95,184, 88,132,242,107,103, 17, 33,147,160,186,234, 10, 68, 12,129,152,225, 23,126,230,172,255,246,209,225, 56, 81, +116, 30,118,171, 21, 50,177, 20, 6,131, 25,223,106, 14, 32, 73, 53,193, 47,242,231,218,239,145,167, 94,195,250,127,191, 15, 35, + 11,180,239, 26,143,223,142, 31,196,194,135,251, 6,212,126, 0,176,176,107, 18,182,156,217, 13,212,216, 1,121, 75,236, 44, 56, + 1,242,230,211, 88, 21, 23, 71,248,146, 63, 0,204,232,182, 88,251,195,206, 2,192, 90, 11, 3,169,133,142, 49,160, 70,108,131, +205,161,135,204,108,132,188,228, 60, 54, 44, 57,131, 78,137, 9,104, 34, 1,176, 1, 20,110,153,175,114,185, 28,114,185,220,235, + 57,190, 88,187,118, 45,214,174, 93,219,172,193, 28, 30, 30,254,204,217,179,103, 67, 35, 34, 34,160, 80, 40, 16, 29, 29,141,242, +242,114, 16, 66,140,193,156, 52, 56,139, 63, 63, 63,159, 2,206,132, 64,127,146, 2,131, 77,254, 31,127,252,177,146,250, 94,235, +206,107, 69, 64,104,104,104,186, 88, 44, 62,231,121,124,249,242,229, 13, 44,127, 0,232,216,177, 35,146,147,147,215,249,178,127, +174,148, 92,107,144,237,255,202,223, 23, 64, 38,150, 34, 46, 46, 14,220,234,128,250,243,161,254,140,183, 63, 43,251,224,185,119, +223, 71,109,105, 25, 98, 35, 90,225,248,137, 75,152,179, 60, 11, 25, 25, 25, 36, 16,178,230,190,231,254,125,119, 57,130, 39,224, +206,192,175,191,254,218,100, 49,160, 70, 61, 0,245,147,136,182, 80,187, 89, 69,105,138,166, 83,219, 24,132,135,200,112, 95,175, + 68,220,215,179, 47,196, 12, 96, 48, 57,112,233,106, 21, 10,180,223,169,194, 66, 67,124,254,131, 58,163, 17, 9, 29,175,194,108, +145,131,114, 70, 13, 5, 20,114, 51, 40, 5,170,170,101, 0, 1,194, 67,237,232,157,112, 1,251, 14,245, 67,120,120, 56,111,235, +223,221,226, 87, 68,198, 64, 66,109,128,253,143,249,206, 33,246,253, 27,221,173,127,119,139,159, 59,118,246,248, 97,215,181,124, +170,236,185, 43, 1, 0,208,186,181, 83, 25,169,170,170, 66, 68, 68,132,203,253,239,143, 2,192, 41, 1,192,155,152,159, 54, 18, +248,247, 62,124,248,242, 4,164, 46,122, 31, 89,111, 61, 9, 49, 33,144,202,248,173,216,225,172,255, 19,151,202,112, 79,251,150, +248,232,191, 27,208,169, 83, 39, 68,182,237,138,190,109,187,194,102,249,195,253, 47,225, 33,147,179,254, 95,159, 59, 26,207,188, +186, 14,237,187,144,102,181, 31,103,253,143,221,244, 49,118,204,156, 14, 18, 63, 24,128,179, 42, 32,224, 44, 17,204, 93,251, 76, + 92, 28, 47,226,232, 99,121,129,100,189,187, 76,217,117,114,173,166, 83,183, 94,208, 43,128,243,184,136,218, 11,229, 40, 95,234, +128, 65, 23,143, 5,179, 23,241,126, 32,171, 87,175, 38, 10,133,130,154, 76, 38,184, 89,158, 84,161, 80, 96,245,234,213,126,148, + 39, 10, 30,106,107,107,223,121,242,201, 39, 83,214,174, 93, 43,143,140,140,132, 70,163,193,202,149, 43,245, 86,171,245,193, 96, +254, 31,206,226,231,150,203,249,155, 16,152,156,156, 76,116,186, 49, 52, 24,228, 15, 0, 28,177,243, 33, 40, 30, 21, 6,173,179, +103,207, 30,188,113,227,198,163,117,117,117,109,108, 54,231, 50, 83, 79,242,191,239,190,251, 48,120,240,224,137, 60,158,179,184, +166,228, 28,222,248,199, 43,248,102,203, 54,140, 27,214, 31,187,242, 15, 58, 13,152,182, 93, 17,217,182, 43, 6, 20, 21,225,193, + 41,179, 42, 46, 85, 26,199,118,136, 9,201,225,107,253, 63,151,185, 5, 75,254, 52, 22,109, 91, 43, 93,202, 5,119,143,124, 60, + 55,129,120, 7, 4, 79,192,157,171, 20,240, 82, 0, 0, 32, 34, 60, 76,251,139,118,179,234,124,252,189,232,210,173,135, 38, 34, + 84, 1,150, 2, 38,139, 21, 69, 69, 69, 40, 47,250, 85, 21, 30, 22, 10,134, 97,124, 14, 92,133, 92,142,141,223,143, 84,113, 25, +240, 77,186, 35, 24, 6,161,161,252,173, 39,110, 9, 96,104,116,107,176, 14,155,147,252,235, 97, 35, 18,159, 37,118, 61,193, 45, +169, 25,179, 96, 85, 3,210, 10,132,252,221,149, 0,247,194, 63, 85, 85, 85,190, 31,128, 15, 37,224,115,183, 85,194,107,151,254, +245,143, 15, 54, 3,194,120,202,105, 31, 29,142,141,135,126,197,111,167,126, 71,146,106, 66, 3,210,247,135,252, 57, 60,242,212, +107,248,186,127, 40,158,122,180,123, 80,218,111, 97,215, 36, 44,202,221, 8,242,198,171,216, 22, 55, 8, 43, 13,191, 53, 56, 63, + 57,178, 5,226,229,254,237, 73, 49,163,219, 98,237,182,220, 28, 92,209,157, 67,121,229, 85,148,158, 14,131,200, 17,129,161,125, +134, 67, 53, 91,117, 75, 39,181, 96, 84,251,163,148, 30, 34,132,140, 33,132,236,124,255,253,247,229,147, 38, 77,210, 27,141,198, +177,129,196,252,155, 66, 48,150, 0,170,213, 81, 65, 33,127, 79, 43, 53, 72,168,152, 58,117,106,215,218,218,218, 55, 10, 11, 11, + 23, 20, 23, 23,163,174,174, 14, 82,169, 20,109,218,180, 65,108,108,236,164,254,253,251,127,203, 83,214, 73, 0, 3,218, 71,135, +227,129, 7, 30,192,175,103,138,209,178,115,207, 6,227,237,193, 41,179,140, 0, 62,224, 67,254, 28,254,172,236,131, 49,249, 63, + 97,230,171,159, 97,196,136, 17,136,139,139,243,170,104, 5,171, 65, 56, 37,192,159,182,110, 76, 33, 19,148,136, 91, 71,250,188, + 74, 1, 3, 64, 68, 68,132,214, 82,117, 89,249,139,246,180, 10,112,102,210, 82, 74, 33,147,201, 16, 25,193,187, 6, 54, 36, 18, +137, 54, 82, 34, 9,250,205,113,174,126,145,221, 8,216,141,174, 12,120,142,248,253, 93,139,197,185,250,207, 30, 63,140,179,199, + 15, 35, 54, 54, 22,229,229,229, 1, 17,127,100,108, 91, 88,121, 36, 71,242,197,204,215, 62,199,129,125,218,160,201,187,112,225, +130,107,183, 63,155,197,124, 29,249,251, 67,252, 28,102,247, 15, 13, 90,251, 1, 0, 89,241,130,139,248, 57,242, 63, 95, 87,167, +154, 28,217, 2, 15,243,180,250,189,225,161,206,169, 4,157,235, 63, 4,144,216,190,102,205, 26,194, 85,251, 91,189,122, 53,113, +175,252,183,110,221, 58,178,122,245,106,215,251, 53,107,214,220,244, 65, 79, 41,221, 79, 8, 25,145,147,147,179, 80,175,215,175, +160,148, 22, 4,251,127, 4, 99, 9, 96, 48,201,233, 6,193, 20, 30, 30,190, 80,169, 84, 46,108,166,156,253,199,142, 29, 27, 10, +160,115,203,206, 61,141, 54,139, 57,164,126,188,233, 1,212, 0, 56,217, 33, 38,228, 49, 56,147, 5,121, 99,204, 43,107,111, 10, +241, 55, 71,209, 18, 72,254,214, 32, 49, 49,145, 23,249,251, 52, 64,197, 98,177,214,151, 59,254,102,131,139,237,115,196,143,102, + 18, 63, 23,155,174, 41,187,130,154,178, 43,136,141,141,109,150,197, 15, 0,118, 7,235,183,247,161, 41,148, 85,213, 4,252, 91, + 60,193,197,246,131, 69,252,193,110, 63, 46,182,191,197, 96,160,238, 86,127, 63,177,164, 89,196,255,191, 4, 74,233,207, 0,166, + 11, 45,113,235, 49, 99,198,140, 12, 0,159, 93,170, 52, 26,109, 22,179,123, 60, 50,162, 67, 76, 72, 20,252,220,253,143, 35, 85, +119, 55,255, 29,164, 84, 9,184,137, 74, 0, 47, 67, 43, 49, 49, 81, 72,236, 16, 32, 64,128, 0, 1, 2,254,199,192, 8, 77, 32, + 64,128, 0, 1, 2, 4, 8, 10,128, 0, 1, 2, 4, 8, 16, 32, 64, 80, 0, 4, 8, 16, 32, 64,128, 0, 1,130, 2, 32, 64,128, + 0, 1, 2, 4, 8,184, 43,208, 96, 21,192,252,249,243, 3,206, 34,245,182,221,228,237, 46,239,240,225,195, 1,203,235,215,175, +223, 13,151, 23,236,251,109,217, 50, 49, 96,121, 21, 21,191,222,234,231, 75,234, 21, 86, 22, 94,138,175,220,137,253,239,102,201, +171, 47, 76,196,212,183, 33, 5, 64,231,207,159,207, 10,237, 39,200,187,147,228,101,102,102,138,211,211,211,237, 0,240,209, 71, + 31,209,110,221,186, 97,196,136, 17, 68,104, 63,239,242,252, 86, 0,238, 6, 52,183,200,196,212,169, 83,149, 0,220, 75,134,170, + 54,110,220,168, 21,116,197, 91,131,154,154,154,199,143, 29, 59,214, 87, 36, 18, 45,146,201,100, 48, 26,141, 47, 12, 27, 54,236, + 93, 4,161,210, 30,165,212,239,106,140,119, 34,230,207,159, 79,193,115,147, 25, 1,183, 14,185,185,185,202,148,148, 20,109,128, +223, 85,229,229,229,237, 14, 70, 65,169,122,121,143,229,229,229,109, 88,179,102, 77, 52,156,123, 26, 56,112, 11,170, 91,186,131, + 35,255,189,123,247,210,159,126,250, 9, 73, 73, 73, 24, 49, 98,132,208,113,130,229, 1,184,211,145,159,159,175,108,206,247,167, + 78,157,170,220,184,113,163,102,234,212,169,238,135, 53, 83,167, 78, 13, 88, 9,224, 20,138,236,236,108,174, 84,167, 95,178,210, +211,211,169,159,255,175,201,245,192, 59,119,126,226,175, 60,149, 78, 23,122, 43, 20, 32,242,219,111,191,189,163,215,235,255,212, +177, 99,199, 22, 21, 21, 21,168,223,110,247,237,175,191,254,250,237,208,208,208, 81, 15, 62,248,160,166, 89,255, 32, 0,242, 87, +171,231,251, 61, 9,102,100,172, 38, 55, 79, 94,211,229,112, 27,219,244,133,239,248,218,184,113,163, 6,175, 18,144,127,121, 87, +168,240, 42,193,212,147,105,126,183,235,184,113,227, 40, 0,108,223,190, 61, 40, 4,198,109, 5,172, 86, 71, 5,125,125,124,110, +110,174, 50, 47, 47, 79,227, 15,217,254,229, 47,233,148, 82,231,214,234,222,240,240,195, 19, 85,121,121,121,154,148,148, 20, 18, + 64, 63, 30,181,109,219,182, 93, 35, 71,142,196,188,121,243,104, 86, 86,214, 24,189, 94,159,239,207,111,243,162, 52, 98,218, 16, + 41,212,243,212, 85, 47,124,177,248,219,183,166,191,245, 8,119,110,237,218,204, 38,127,227,172, 89,179, 40, 0,132,134, 54,190, +181, 65, 93, 93, 29, 0, 96,206,156, 57, 1, 61,159, 83,135, 84,200,207, 60,130,228,244, 76,154,158,158, 46,212, 63,224, 1,174, + 56,144,123,141, 0,177,143, 1,239,181,110, 54,143,122,218,183, 10,205, 34, 4,119,242,223,184,113, 35,153, 58,117, 42,117,147, +235,247,253,114, 10, 5, 71, 52,245, 27,126,248,175, 80,100, 71,251,241, 95,147,125, 94, 81,247,240, 95,249,139,243,115, 95,155, +198, 8,200, 79,175, 12,169,169,169,249,170, 87,175, 94, 83, 0, 48,148, 82, 40, 20, 10,148,149,149,161,186,186, 26,145,145,145, + 40, 43, 43,219,253,253,247,223,171, 30,124,240, 65,191,148,147,252,252,124,202,109,204, 66, 8,193,148, 41, 83,144,156,156,172, + 34,132,240,150,147,155,187,217,245, 62, 37,101,146,207,207,190, 96, 58,240,212, 31,205, 61,100, 85,131,207,158,199, 20, 67,124, +111,170,196,109, 39,236,142,189,123,247, 98,233,210,165,215, 61,139, 47,190,248,130,242,108, 55,101,118,118,182, 6,175,146,122, +130, 77,187,126,226,126,149, 52,219, 66,188,141,231,150, 6,150,118, 70, 70,134,138, 82,138,245,235,215,211,253,251,247,163, 79, +159, 62, 62,191,123,160,145,154,140,155,178, 23, 33, 47, 47, 79,195,178, 44, 50, 51, 51,225,107, 91,101, 66,136,146, 82,234,234, +175,223,126,251,109, 8, 33, 4,211,167, 79, 47, 5, 16, 55, 99,198,140,157,107,214,172, 97,252,177,216,223,221,249,174,235,253, +181,237, 87, 65, 8, 65,214,179, 33, 0, 8,222,153,245,246, 35, 45, 91,182, 4, 0,124,249,105, 22,230,141,156,199, 75,230,128, + 1, 3,208,165, 75,151,160,180,123,102,102, 38,147,158,158,206,126,244,209, 71,244,167,159,126, 66,233,233, 78, 64, 69,148,192, +234,126,146,191, 39,152,166, 38,242,236,236,108,100,102,102, 82,111, 19,104, 32, 59, 67, 53,215, 66,247, 37,207,205,202, 14,216, + 40,220,184,113, 35,217,184,113, 35,225,148, 0, 0,170,230, 40, 20,132, 16,164,165,165,129, 82, 74,220,126,155,223,138, 10,153, +170,115,189,248, 28,247,133,176,173,171, 93, 47, 62,199,253, 33,127, 74, 41,184,221,217,124,237,210,230,173, 79,234,116,186,207, + 34, 35, 35,167, 0, 96,230,206,157,139,153, 51,103, 66, 42,149, 66,161, 80, 64, 46,151,131, 16, 2,145, 72,132,154,154, 26,222, +237,152,147,147,163, 84,171,213, 52, 39, 39, 7,110,207, 4, 95,127,253, 53,230,205,155,167,201,201,201, 81,222,142, 3,215,155, + 66,112, 43, 60,107,217,217,217,154,140,140, 12,242,216,169,169, 94, 45,124,181, 90, 77,167,158, 76, 83,121,243, 12,248,194,188, +121,243,232,243,207, 63,143,206,157, 59, 7,229,247,206,155, 55,143,170,213, 81,136,137,217, 21,212,118,216,188,121,243,232,252, +252,252,221,125,251,246, 37, 31,126,248,161,150, 35,255,230, 96, 83,246, 34,172, 88,177, 2, 44,203, 98,209,162, 69,224, 35,211, +157,252, 1, 96,219,182,109, 91,234, 93,225, 81,211,167, 79,183,143, 28, 57, 18,106,181,154,229,107,180,120,142,209,149, 43, 87, +226,177, 7,156,182, 97,214,179, 10, 76, 27, 34,197, 11,227,158,231,125, 79,161,161,161, 24, 49, 98, 4,210,211,211, 73,114,114, +178,215, 23,119, 13, 95,101, 47, 61, 61,157, 5,156,219,172, 3, 64, 68, 72,133,192,234,205, 36,255, 38, 21, 0,142,172, 10, 11, + 11, 93,101, 39,221,173, 39,127,137,214,101, 65, 4,121, 82,242,162, 12,168,130,217,120, 27, 55,110,212, 4, 65,134, 75,161, 72, + 75, 75, 83,113,109,120, 55,193,157,252, 1,160,184,184,216,117,238,202,149, 43,188, 21,198,154,154,154, 55,141, 70,227, 44,134, + 97,152, 25, 51,102,160,166,166, 6, 37, 37, 37,144, 72, 36, 16,139,197, 16,139,197,144, 72, 36, 80, 40, 20, 48,153, 76, 94, 75, +162,122,153,224,148, 59,119,238,212, 16, 66,144,154,154,138, 53,107,214,144,228,228,100,146,145,145, 65, 82, 83, 83,185,254,163, + 17,166,138,166,201,191,190, 45, 85,220, 36,238,254,236,211,210,210, 84,201,201,201, 90, 32,176,146,180,201,201,201,100,205,154, + 53, 36, 59, 59, 27,148,210,160, 40, 99, 47,189,244, 18,178,179,179,121,245, 17, 95,248,230,155,111,198, 28, 58,116, 40,191, 83, +167, 78, 48, 24, 12, 52, 52, 52,148,238,219,183, 15,128, 43,201, 50, 32,242, 95,190,124, 57, 8, 33, 96, 24, 6,135, 14, 29, 2, + 39,211, 15,143,196, 35,132, 16, 76,155, 54,205, 94,127,200, 58,125,250,116,189, 82,169,196,188,121,243,216,111,191,253,214,231, +189,187,135,194,174,109,191, 10, 16, 96,253, 51,127, 84, 45,206,122, 54, 4,211,135,202,176,248,193, 23,120,255, 46, 62,150, 63, +159,107,246,238,221, 75, 51, 51, 51, 93,175, 67,135, 14,193,112,105, 0, 96, 53,129,132,217,145,255,250, 73,184,159,231, 94,194, +200,109, 72,254,233,139,223,242,122, 94,220,212,128, 44, 42, 42,162,133,133,133,200,206,206, 6,247,158,115,237,248, 51,200,111, + 52,249,187, 91,213,220, 36,116,187,194, 61, 36,112,183,129, 82,138,226,226, 98, 92,187,118,205,117,204,243,179, 15,136,126,252, +241,199,241, 9, 9, 9, 16,137, 68, 56,123,246, 44, 40,165,248,253,247,223, 97,181, 90, 65, 8,129, 88, 44, 6, 33, 4, 14,135, + 3, 70,163, 17,155, 54,109, 66,114,114,211, 97,143, 93,187,118,105, 0, 32, 53, 53,245,186,126, 91,255,153,114, 68,193,167, 95, +123,186,245,125,125,230, 99,229,115,104, 44, 28,192,199,245,239,101,242,108,118,146,148, 43,230,239,166,192,113, 10, 44, 23,243, +207,119, 35,255, 64,172,117, 78, 9,227,200,104,215,174, 93,154, 64,195, 0,156,188,110,221,186, 93, 71,110,129, 96,245,234,213, + 56,121,242, 36,141,141,141, 69,187,118,237, 92,219, 62, 95,184,112, 1, 34,145, 8,255,249,207,127, 2,250, 7, 35,135, 58,183, + 47, 99, 89, 22,127,251,219,223,176,114,229, 74,236,219,183, 15,132, 16, 60,156,242, 23, 92,188,192,111, 3,199,109,219,182,109, +174,127,198,102, 56, 87,200,176, 0, 48,125,250,244,106, 0, 45,242,242,242, 64, 8,225,173, 80, 57,173,255,235,247, 49,113,134, + 3,128, 47,179, 14, 35,183, 38,247,166,121,203, 78,157, 58,133, 67,135, 14, 53, 56,230,168, 62, 15,187,141, 5, 72, 45, 90, 60, +104,195, 33,143,205,174,147,146,146, 4,230,231, 65,254, 77, 42, 0,245,110, 23,194, 89,253, 28,249,123,141,253,249, 65,214, 77, + 89,130,124,226,196,190,228,121,158,191, 85, 59, 82, 77,157, 58,213, 61,214, 76,189,157,231, 60, 3,205, 34,221,141,193,141,131, + 25, 38,206, 15,200,242,111,108,178,141,143,143,191,238,218, 38,158, 73,139,232,232,232, 94, 22,139, 5, 85, 85, 85, 56,112,224, + 0, 68, 34, 17,172, 86, 43, 76, 38, 19, 88,150,117,237, 74,105,179,217, 96,177, 88,120,133, 24,184,231,208, 88,191, 77, 78, 78, + 38, 57, 57, 57, 52, 59, 59,219,167, 50,225,180,186,110, 76, 14,128, 98,200,170,235,136,158,251, 28,136, 34, 48, 98,196,136,230, + 43, 1, 30, 49,255,252,252,124,165,139,236,255,136,249, 7,148, 35,227,161,132, 1,112,238,182,168, 86,171, 41,159,231,192,215, + 11, 80,159,251,224,119,110, 1,183,179, 99,187,118,237, 16, 17, 17, 65, 60,149,221, 94,189,122, 5,108,249, 83, 74, 97,183,219, + 93,199,134, 13, 27,134,125,251,246, 97,207, 15, 14,188,187,140, 95,140, 61, 55, 55,119, 92,125,236,255, 4,128,150, 0,220, 55, + 27, 42, 1,208, 2, 0,242,242,242, 52,125,251,246,245, 41,175, 97,236,223,139,167,160,254, 47, 95,121,193, 64,122,122, 58, 73, + 74, 74,162,154,207, 98, 97,175,254, 21,132,173, 6, 28,206,157, 86, 25,145, 29,250,125, 12, 36, 82, 49, 44,142, 22, 56,120,161, + 47, 94, 89,174,195,161, 67,135,136,183,101,213, 2,252, 84, 0, 60, 61, 1,254, 90,254, 69, 69, 69, 52,152,238,110, 95,242,234, +195, 18, 65,243, 52,100,102,102,146,244,244,244,128,190,235,249, 59, 51, 50, 50, 12,106,181, 58,172,177,243,129,194, 61,246, 31, + 12,101,192, 61,246,207, 87, 25,152, 57,115, 38, 66, 67, 67, 17, 22, 22,134,240,240,112, 68, 70, 70,178, 81, 81, 81, 76, 94, 94, + 30, 30,127,252,113,215,117,114,185, 28, 99,199,142,133, 90,173,166,141,236, 86, 21, 99,181, 90, 81, 85, 85, 5,179,217,140,200, +200, 72,200,100, 50,216,237,118, 80, 74,225,112, 56, 96,181, 90, 97,179,217,224,112, 56,252,202, 47,240, 21,178, 74, 77, 77,197, +237, 16,154,241,149, 16,232, 47, 56, 37, 32,224,254,245,175,198,219,110,234,201,180,250,188,155,192,100,123, 90,255,238,138,100, + 32,201,128,158,214,127, 83,138, 41, 95,242, 23,137, 68, 52, 34, 34, 2,112, 38,212, 17, 0,212,102,179,161,166,166, 6,173, 90, +181, 10,232,190, 57, 99, 74, 44, 22, 99,193,130, 5, 56,116,232, 16,254,136,251,243,239,211,223,127,255,253,247,195,135, 15, 7, +128,112, 56,195,185, 70, 0,216,176, 97, 67,171, 61,123,246, 68, 80, 74, 93,202, 54,159,117,226, 43,223, 95,137,105,131,175,183, +254,103,254,219,136, 13, 7,108,160,148,162,223,140,126,152, 55,114, 30, 9,116,221,121,160, 74,128,106,118, 38,253,126,101, 71, +136, 13,122,192,238,252,215, 44, 0,169, 24, 40,190,214, 2,187, 47, 13,112,100,126, 89, 46, 58,116,232, 16, 73, 74, 74,146,227, +127, 28,124,172,127,128, 71, 37,192,252,252,124,151,235,223, 61, 31,128, 15,186,116,233, 66,210,210,210,130, 22,147,231, 33, 47, +224,248,250,212,169, 83,169,231, 43, 63, 63,159,229, 86, 5,184,173, 8, 8,180, 19,135,221,205, 29, 46, 51, 51, 19,203,151, 47, +111,208,175, 56,242, 79, 73, 73, 65, 74, 74, 10, 0, 96,207,158, 61, 77,137,137, 46, 42, 42, 50, 59, 28, 14,232,116, 58, 84, 84, + 84, 64,167,211,193,104, 52,194,104, 52,194, 96, 48, 64,175,215,163,166,166, 6, 38,147, 9, 22,139,197,149, 20,212, 36,137, 17, +130,156,156, 28,191, 20,182, 59, 25,123,247,238,109,240,114,199,169, 83,167,148,238,159,249,196,156, 61, 99,254,158,150,123,115, +178,246,189,125,119,205,154, 53, 36, 39, 39, 39,168,185, 0, 57, 57, 57,188,231, 46,142,252, 25,134,161,245,253,203,229,250,103, + 89, 22,165,165,165,232,214,173, 27,153, 63,127,190,223,191,229,229,197, 35,177,103,207, 30,176, 95,181, 0,165, 20, 43, 86,172, +112, 61,163,189, 7,120,231,237, 33, 55, 55,119, 18, 0, 76,159, 62,189,184, 94, 1,176,124,249,229,250, 86,243,231,207,111,181, +103,207, 30, 60,244,208, 67, 99,252, 89,166,120,109,251, 85, 16, 16,172,119,179,254,103,188,111,132,104, 90, 13,190, 60, 96,197, +115,207, 61,135,101,223,191,125, 43,230, 21, 17,167, 4, 60,248,156, 29,212, 20, 9,232, 1,232, 1, 81, 45,160, 47, 5,182, 29, +110,131,204, 47,203, 69,245,222, 2,113,122,122,186, 89, 32,127,223,228,239,211, 3,144,153,153,217, 32,238,239,158, 15,192,119, +237,101,189,187, 80,197,185,229,155,235,146,247, 38,143,115,251, 39, 39, 39,107,131,181,132, 40, 57, 57,249,183,252,252,252, 94, +183,227, 3,230,172,254, 96,185,255, 57,171,223, 95,247, 63,135,245,235,215,187,222,255,243,159,255,196, 39,159,124, 2, 0, 86, + 0, 82,142,248, 1, 96,236,216,177,190, 20, 0, 83, 66, 66, 2,140, 70, 35,172, 86, 43,202,203,203, 33,147,201, 32, 22,139, 93, + 30,128,186,186, 58, 24,141, 70, 88, 44, 22,212,212,212, 96,202,148, 41, 62, 21, 76,206,186,111,106, 89, 43,119, 29, 31,220,200, + 28,128, 64,206,123,130, 91,238,231, 13, 43, 86,172,208, 44, 88,176, 64,213,189,123,119,237,173,236,195,141, 89,255,238,240, 39, + 23,160, 49,235, 63, 80,203,159, 97, 24,202,178, 44, 1,240, 15,174,107, 59, 28,142, 87, 67, 67, 67, 17, 31, 31, 31,208, 28,243, +202,139, 35,161,213,106, 65,114, 98, 0, 0, 59, 94, 9,199,216,215,107, 49, 98,196, 8,188,177,108,143, 95,133,169,182,109,219, +182,105,228,200,145, 0, 80,190, 97, 67, 86,187, 61,123,246,181,160,132, 98,252, 67,227, 83, 82, 82, 82,182,248, 51,157, 0,206, +216,255,180, 33,146,134, 22, 63, 40, 22, 60,183, 0,113, 99, 91,223,178,130, 89,233,233,233, 13, 52,124, 90, 11,200,172, 0, 75, + 9,236, 14, 10, 25, 5,226, 20,140,251,245,118, 8,112,242,247,178, 23, 27, 85, 16, 56, 15,172,152,143,229, 63, 96,192,128,235, +242, 1,252,113,209,121,146,118, 16,200,217, 83,158,230, 6,116,188, 94,249,249,249, 65,147,119,183, 38,254,113,133,101, 56, 55, +113,118,118, 54,158,120,226, 9, 0,144,114,215,184,159,171,159,180, 26,195,241,193,131, 7, 63,174,213,106,179, 29, 14, 7,244, +122, 61,108, 54,155, 43,238,111, 54,155, 93, 75, 12,185,196,192,177, 99,199,106,121,244, 23,146,157,157, 77,235,189, 0, 13,250, +109,126,126, 62,119, 28,201,201,201,188,188, 85, 55, 59, 7,192, 51, 44,224,235,121, 52,117, 94,173, 86,211, 21, 43, 86,104, 30, +123,236, 49,124,245,213, 87, 1, 61,115,207,229,183,220,231,141, 27, 55,106,210,139,213,152,234,195,210, 30, 55,110, 28, 61,127, +254, 60,190,255,254,251, 70,219,251,252,249,243, 0,128,237,219,183,251,252, 61,105,105,217, 52, 45,109, 52,198,140, 41, 66, 81, + 81,145,215,236,242,202,202,209, 0,116, 80,171, 27,159,183, 56,242,183, 90,173, 84, 42,149,114,215,252,163, 94, 33,120,245,226, +197,139,232,216,177, 99, 64,150, 63,195, 16,167,194,206,145,255, 81, 59, 62,209, 88, 1, 0,111, 44,219,227,247, 28,193,141,137, +249,243,231, 39, 82, 74, 49, 97,226,132, 41, 15, 79,124,248,155, 64,166,166, 73,143, 62,114,130, 16,114, 31,165,128,104, 90, 13, + 40,165, 88,176,112, 1, 90,143,109,243, 71,224, 35,112,112,236, 76,209,140, 74,130,153,153,153,116,227,139,109, 17, 86,121, 30, +231,244,241,232, 44, 43, 7, 66,227, 32,174, 43, 69, 68, 93, 37,128, 86, 46,143,129,167,210, 32, 32, 0, 15,128,251,114, 63, 15, + 87, 31,205,206,206, 6,223,132, 41, 79,210, 14,214, 15,119,151, 23,132,245,255, 2,154, 9,119, 23,186, 59, 9,113,245, 36, 60, +207, 53, 18, 67,180, 3,248,122,228,200,145, 79,231,229,229,125, 96,183,219, 81, 93, 93,237,202, 1, 0,128,242,242,114, 84, 87, + 87,131, 82, 10,127,194, 75, 99,198,140, 81,237,220,185, 83,147,157,157,141,156,156, 28,234, 25,243, 31, 51,102,140, 95,197,128, +110, 4, 76, 7,158,242,155,240,189, 17,124, 83, 74, 64, 70, 70, 6,153, 55,111, 30, 13,132,252, 27, 36, 0,186, 61,119,183,164, + 64,127,189, 0,141, 42,238, 23, 46, 92,112, 41,104,124, 13, 13,247, 80,229,245,247,205,111,174,170,169,169,161,145,145,145,238, +228,255,170,197, 98, 65, 73, 73, 9, 58,119,238, 28, 16,249,171,213,106,202,126, 21,133, 29, 71,157,198,233, 58,141, 21, 27, 14, + 88, 65, 41,197,190, 31, 3,143, 44,238,221,187, 23, 15, 61,244,144, 42,208,242,193, 28, 65,179, 44, 43, 1,128,175,126,180,225, +185,231,158, 67,235,113,109, 60,252, 3,254,129,171,242, 55, 98,196, 8, 10,120, 95,238,231, 86, 9,144,247,243,237,200,212, 1, +177,137,120,124,109, 13,128, 56,103, 27, 60,217, 18, 29,196,151,241,122,114, 25, 62,213,104,132,170,128,104, 88,233,207,211,242, +247, 60, 47,110,106,162,200,204,204,164,222,150, 77,249, 19, 2,240, 66,218, 65,131,135,188,160,174,255,247, 40, 7,236, 55,210, +210,210,192, 35, 97,145, 55, 26,115,247, 7, 26, 6,104,204,221, 31, 72, 24,192,189,188,172, 39,249, 52,117,174,177, 91, 37,132, +172,154, 48, 97,194,154,245,235,215,219,164, 82, 41, 44, 22, 11,236,118, 59, 88,150, 69,139, 22, 45,160,211,233,144,230,231,210, +179,212,212, 84,109,106,106, 42,217,185,115, 39,205,201,201, 65,118,118, 54,184,186, 0,183,115,229,185, 96, 99,247,238,221,116, +194,132, 9,216,186,117,107,179,201,223,147,228,242,157, 10,153, 79,111,220,243,207, 63,127,157,113,225,137, 23, 94,120,129,242, + 77,242, 84,171,163,124,202, 83,171,249,197,255, 21, 10, 87,233, 75, 74, 41,133,209,104, 68, 73, 73, 73,192, 49,255, 6,158,143, +215,107, 27,124,110, 14,249,127,248,225,135,193,234,179,108,238,183, 91,186,185, 87, 2, 12, 22,154, 82,200,214,173, 91,231,151, +245,175, 78,237, 90,242,241,105,180,205,200, 57, 7,119,238, 25,241,159, 76,186,123,222,189, 56, 83,170,192,153, 51,103,160, 82, +169, 32, 32, 8, 30, 0, 0,104,140,228,111, 71, 45,235,118, 91,255, 31,140, 37,126,127, 40, 34,201, 65,251, 93, 83,167, 78, 85, +249, 91,222,215, 7, 49, 80,119,133,198, 91,162,149,231, 57,158,132,107,159, 57,115, 38,217,177, 99,135,242,210,165, 75, 26,147, +201, 4,135,195,129,251,238,187, 79,149,148,148, 20,240,243, 30, 51,102, 12, 25, 51,102, 12, 55,195, 7, 20,154,185,209, 57, 0, +190, 62,243,177, 56,235,179,195, 27, 18,142,159, 69,102,184, 54,194,171,132,230, 35,237, 58,123, 48, 61, 61,157,166, 23,171, 65, + 26, 22, 2, 34, 0,112,230,204, 25,218,196, 88,245,217,232,163, 71,143, 38,126,140,125, 18,140,107, 0,160,170,170, 10, 10,133, +130, 18, 66,208,177, 99, 71, 16, 66, 72,183,110,221,208, 92,242,103, 30,211,129, 16,130,148, 71,156,171,138, 8, 33,174,229,126, +156, 59,255, 22,129, 29, 48,171,127, 80, 5,206,153, 51,135, 83,254,195,234,189,122,118, 56,221,255,172,219, 53,126,221,112, 70, +206,185,182,238,220,195,185,250,211,211,211,137,122,195, 61,135,103, 0, 0, 32, 0, 73, 68, 65, 84,151,134,158, 57,115, 70, 96, +243, 96, 43, 0,119, 10,130,177,214, 63, 88,132,125, 3, 20,155,160,254,174, 96,111,236,115,163,173,231,250, 24,191,215,255, 97, +181, 90, 33, 18,137, 32, 18,137,110, 98, 95, 91, 77,110,111,121,141,143,133, 89,179,102,249, 47,240,213, 63,246,177,200,206,206, +110, 48,105,167, 23,171,221, 45,111,237,221, 48,151,180,110,221,154,252, 49, 86,156,201,182,205, 37,127,231, 51,105,106, 43,160, +235,177,122,245, 79, 55, 77, 35,152, 55,114, 30,185,217,115,130,159,243, 70, 40,156, 57, 69, 54, 55,229,211, 21,231, 87,169, 84, + 68,176,252,125,195, 91,104,128, 36, 38, 38, 10, 5, 19, 4, 8, 16, 32, 64,128,128,255, 49, 48, 66, 19, 8, 16, 32, 64,128, 0, + 1,130, 2, 32, 64,128, 0, 1, 2, 4, 8, 16, 20, 0, 1, 2, 4, 8, 16, 32, 64,128,160, 0, 8, 16, 32, 64,128, 0, 1, 2, +238, 10, 52, 88, 5, 48,127,254,252,128,179, 65,189, 21,118, 17,228, 9,242, 4,121, 55, 79,222,146, 37, 75, 26,106,247, 12,227, + 90,230,232,190,212,140,171,166,232,190,244,204, 91,249,224,176,176, 48,200,229,114,215,247, 25,134,113,173,184,112,151,199,109, +204,196,178,206, 85, 94,220,102, 57,194,243,245, 71, 30, 81,138,196, 50, 80,214, 14,150,181,107, 3,145, 71, 41, 85, 29, 57,114, + 68,156,152,152,152, 15,143,170,123, 1,202, 83, 30, 57,114, 4,137,137,137, 90, 97,188,221,121,242,252, 86, 0,254, 23,241,242, +203, 5, 13, 26,238,141, 55, 6,146,219, 74, 94,193,203, 20, 0,222, 24,248, 6,113,127, 31,168, 60,174, 82,156, 90,173, 70, 70, + 70, 70, 83,215, 53,121,222, 93, 30,220,150,233,113,223,113,255,190, 90,173,118,157,227, 43,247,127, 17,140,181, 78, 89,254,219, + 1,140,136, 42,215,180,179, 95,198,105,218, 25,135,234,162, 85, 17, 9,131, 32, 13, 13,215,250,250,254,254,253,251, 49,108,216, + 48, 23,241,115,132, 77, 8,185,142,176, 89,150,117,189, 46, 94,188,232, 85,222, 47,191,252,130, 1, 3, 6, 64,161, 80, 64, 44, + 22, 67, 36, 18, 53,144,201,145,190,195,225,112,189, 44, 22, 11, 10, 11, 11,113,207, 61,247,220,141,143,136, 56,121,145, 42,127, +255,253,119,156, 57,115, 70,211,162, 69, 11, 12, 31, 62,188, 89, 99,156, 16, 70, 41,147, 71,163, 69,212,189,154, 58, 67,177,202, + 80,123, 89,233,175, 12,150,101,149, 57, 57, 57,187, 79,159, 62,141,173, 91,183, 66,161, 80, 96,209,162, 69, 34,184,173,189, 15, + 64,158,166,232,220, 89,236,220,177, 29, 82,153, 12,207, 61,183, 96, 20,165, 84, 35,140,212,187,212, 3,112, 39, 33, 39, 39,199, +167,198,147,154,154,234,115, 96,114, 4,237, 73,220,129, 34,216,242,130, 13,183,202,124,188, 38, 45, 62,165,101,249,202,171, 87, + 4,154, 85, 93,156,171, 42,232,254,255,239,248, 81, 72,169,242,196,254, 29,136, 56,255,163,198,104,180,192, 54,136,129, 34,158, +160,219,165,163,184, 63,156,106,116,229, 63,227,215,144,217,170, 10,210,174, 73, 37,224,196,137, 19, 16,137, 68, 24, 62,124, 56, +196, 98,177,235,197, 41, 4,156,213,111,183,219,225,112, 56, 96,179,217,112,241,226, 69,236,222,189,219,171, 60,163,209,136,195, +135, 15, 99,240,224,193,144, 74,165,144, 72, 36, 13,100,178, 44, 11,187,221, 14,187,221, 14,155,205, 6,147,201,132,195,135, 15, +195, 96, 48,220, 22,250, 84,125, 63, 99,240, 71, 33,154,128, 57,122,201,146, 37,172,199,220,130,218,218, 90,196,196,196, 4,180, + 0,125,201,146, 37, 13,126,207,231, 89,133, 80, 40, 90, 65, 36,146,106, 12,181,151,253,150, 89, 80, 80, 0,131,193,128,193,131, + 7, 95, 76, 78, 78,110, 83, 89, 89,137, 29, 59,118, 56,162,163,163,145,148,148,212,228, 24,153, 51,110,244,117,109,115,236,212, + 41,104,195, 67,176,112,197,191, 46,247,235,223,171,253,213, 43,101,216,145,167,221,221,169, 87,191,100,189,190,102,151, 64,157, +183, 63,184,210,191,238,240,172, 5, 32,110,106,146,229, 38, 87, 95,159,111, 5,249,255,245,175,127,109,242, 26,157, 78,135, 47, +191,252,146,242, 81, 2, 56,178,110,174,181,126, 35,228,185, 91,254,205,181,254,221, 72,152, 0,160,106,181,218,231,198, 49, 60, +201,154,112,196,206, 89,251,238,150,191, 59,213,241,237, 51,110,158, 10,234, 94, 78, 24, 0,170,170,156,149, 17,163,163,243,239, +138,129,122,225,167,124,220,115, 89,163,185,108,100, 49,249, 30, 17,238,141,181,131,141,166,144, 68,139, 80, 91, 41,133,162,214, +132, 30, 71, 86,105, 10, 19,230,169,140, 33, 29,181,141, 91,146, 4, 39, 79,158,132, 84, 42,197,168, 81,163, 92,164, 45,145, 72, +192, 48, 12, 40,165,176,217,108,176,219,237,176, 88, 44,184,124,249, 50, 52, 26, 77,163, 91, 42, 51, 12, 3,155,205,134, 35, 71, +142, 96,248,240,225, 80, 40, 20,144,201,100, 46,121,156, 2, 96,177, 88, 96, 48, 24,112,236,216, 49,152,205,102,191, 10, 51,105, +181, 90,165, 72, 36,210,212,214,214, 66, 42,149,162,172,172,236,169,201,147, 39,215,202,229,242,207, 3, 33,109,173, 86, 59, 85, + 36, 18,125,229, 38,239,244,228,201,147,127,151,203,229,169,112,238, 80,233,183, 37,252,202, 43,175,104,150, 46, 93, 90,134,250, + 29,103,150, 44, 89,130, 19, 39, 78,160, 85,171, 86,141,214, 93,247, 69,254, 31,207,157,139,241,253,250, 1, 0, 90, 63,253, 52, + 20, 33,113, 48,232, 47, 65, 95,115, 78, 69,169, 67,235,175,204, 62,125,250,160,172,172, 12,251,247,239,239,200, 48, 12,142, 29, + 59,134,232,232,104,236,221,187, 23, 86,171,213,103, 59, 86,190,185,176,193,231, 48,171, 13,109,237,102, 60,247,252,171,237, 87, +188,251, 79,188,243,238,135,104,199, 56,240,225,187,203,243, 71, 77,155, 33,176,235, 29, 72,254,220,113, 94,123, 1, 0,215,215, +255,246,245,249,102, 34,152, 59,245,221, 9,112, 87, 2,154,233, 1,224, 8,150, 0,160,159, 60,250,153, 87, 66,126, 98,211,108, +222,100, 93,239,218, 39, 94, 38,108,247,239,187, 20, 4, 62, 33, 0,238,127,123,254,245,244, 0,220,233, 48, 87, 87, 40, 71, 88, + 14,107,202, 68, 14,220, 19, 9,116,236, 64, 33,234, 35,133,184, 75, 23, 72, 45,102, 88,126,184, 12, 75,141, 24, 34, 86, 2,115, +254,231, 26,102,252,179, 42, 86,236, 61, 28,192,185,231,207,158, 61,139,168,168, 40,168, 84, 42,200,229,114, 72,165, 82,136,197, + 98,151,213,111, 54,155, 81, 82, 82,130, 61,123,246,128, 97, 24, 48, 12,131,166,228, 57, 28, 14, 28, 63,126, 28,195,134, 13, 67, + 68, 68, 4,228,114, 57, 68, 34, 17,236,118, 59,172, 86, 43,244,122, 61,126,254,249,103, 88, 44, 22,136,197, 98, 87, 46,128, 47, +124,241,197, 23, 74,131,193,160, 57,127,254, 60,244,122, 61,164, 82, 41, 90,183,110,189,106,223,190,125, 24, 50,100,136, 56, 52, + 52,244, 19,127,148,128, 47,190,248,226, 81,131,193,240,149,135,188,132,125,251,246, 37, 12, 25, 50,228,203,208,208,208, 84,190, +242, 88,150, 85, 90,173, 86, 84, 85, 85,105,220, 60, 10, 0,128,165, 75,151, 22, 47, 89,178,164, 93,106,106,234, 40,185, 92,238, +215,252,199,136,164, 74,207, 99,215, 62,248, 0,173, 39,197,227,157,119,222, 87,217,108,117, 1,205,167,251,247,239,215,252,244, +211, 79,120,241,197, 23,245, 34,145, 40, 66, 46,151, 99,200,144, 33,208,104, 52,200,203,203, 67,187,118,237,252,240,119, 16,124, +113,246, 42,190, 62, 83,140,220,111, 63,133, 72, 68,176,240,233,199,217,190,173, 91, 50,153,207,189,138,181,254,202, 19,112, 75, +200,223, 83, 57,245,166, 20, 4,188, 10,224, 86,111,111,219,165, 75, 23,149,175,215,205,182,214,111,132,188, 96, 88,253,141,225, +147, 71, 63, 35, 79,108,154, 77,189,145, 63,248,135, 8, 26, 88,250, 85, 85,201, 46, 11, 29,127,108, 1,234,183,219,191, 41,162, +143,142,206, 15,200,250,183,219,237,202,159,127,254,153, 54,118,204,243, 92, 99,112,191,222,110,183, 43, 61,207,121, 30,107, 10, + 85,199,127,209,148, 20,235,209, 42, 92,140, 46,225, 20,226,150, 44,196, 15, 60,136,208,190,159, 67,209,255, 61,200, 34, 21,144, + 26, 76, 48, 26, 29,232, 32, 50, 98,239,250,198,149, 39,134, 97, 32, 22,139, 33,145, 72,112,230,204, 25, 28, 59,118, 12, 17, 17, + 17,136,137,137, 65, 76, 76, 12, 90,182,108,137, 22, 45, 90,160,166,166, 6,123,247,238,133, 72, 36,114,197,246,189,129, 59, 47, +149, 74,225,112, 56,112,250,244,105,132,132,132,160,101,203,150,104,213,170, 21, 98, 99, 99, 17, 22, 22,134,211,167, 79,195,102, +179,185, 66, 4,141, 41, 20,158,150,127,105,105,169,230,220,185,115,232,220,185, 51,198,141, 27,135,129, 3, 7,194,104, 52, 98, +247,238,221, 56,114,228,200, 71,102,179,153,119,237, 98,173, 86,171, 42, 45, 43,255,166,232,106, 13,194,239, 25,140,132,113,127, + 66,187,129, 41,208, 89, 24,236,204,223,133, 35, 71,142, 76, 54,155,205,127,225, 75,254,122,189, 30, 71,143, 30,213,236,223,191, + 31,125,250,244,193,146, 37, 75, 90,162, 62,158,190,100,201,146,118, 0,224, 15,249, 51, 34,169, 50, 52,172,173, 50, 58,166,151, +102,253,134,163,152,251,241,199,200, 59,124, 24,121,135, 15,163,245,211, 79, 3, 0,108,182,186, 61,129,140,227,188,188, 60,154, +155,155,139, 41, 83,166, 92, 12, 15, 15,103, 66, 66, 66, 10, 11, 10, 10,176,127,255,126, 84, 84, 84, 32, 33, 33,193, 47,121,239, + 31, 62,131,119, 15,254,134,181,239,190,116, 84, 44, 50,129,113,212,226,237,149, 31, 51, 95,237, 45, 68, 9, 35,198,189,247,222, + 43,176,236, 93, 2, 38, 80,130,191,133,155, 87,220, 24, 11,251,229, 2, 26,204,184,125,176,229,221, 72, 69,224,137, 77,179,169, +251,171, 49,175,128, 47,175,194,117,228,214, 80, 25,240,215, 83, 65, 26, 59,238,233, 21,224,131,218,218, 90,229,174, 93,187, 52, + 5, 5, 5,141, 30,115, 63,215, 20,220,175,223,181,107,151,166,182,182, 86,233,126,206,243, 88, 83,136, 48, 87, 34,239,146, 25, +219,206,179,184,172, 35, 40, 45, 7, 24,113, 36, 24, 18, 3, 98,150,161,174,148,224,232, 37, 22,199, 46,153, 81, 89,107, 67,239, +104,153,134,143, 2, 32,147,201,112,238,220, 57,156, 58,117, 10,209,209,209,136,138,138, 66, 84, 84, 20,140, 70, 35,246,239,223, + 15,137, 68, 2,169, 84,218,228, 94, 10,156,119,128, 83, 2, 40,165, 40, 42, 42, 66,116,116, 52,226,227,227, 17, 27, 27,139,162, +162, 34, 56, 28, 14,200,100, 50, 72,165,210, 6, 43, 15,188, 77, 43,220,155,242,242,114,205,149, 43, 87,208,179,103, 79, 60,248, +224,131,152, 56,113,162,106,226,196,137,170,225,195,135,195,225,112,224,199, 31,127, 68, 81, 81,209, 96, 0,188,226, 9,229,229, +229,187, 75,171,106, 16,221,181, 47, 18,146,231,160,231,132,249,232, 49, 97, 30, 58, 62,240, 40,172, 84,196,201,227,245,124,235, +115, 31, 52,103,206,156,225,238, 85, 85, 79,252,204,146, 37, 75,176,116,233, 82, 44, 93,186,244,148,103, 94, 64, 99, 16,137,229, +202,168,232, 30,154,214,237,134,105,162, 98,122,128, 48, 98,124,244,137, 6,115, 63,254, 24,115, 63,254, 24, 75,151, 46, 69,121, +121, 57,248,202,243,176,252,233,150, 45, 91, 48,100,200, 16,244,239,223,191, 35, 0,249,174, 93,187, 6, 92,184,112, 1,199,143, + 31,135,201,100,194,132, 9, 19, 70,241,149,151,245,251,101,188,247,243, 41,172,121,227,249,170,248,123, 59,246, 49, 26,116,200, +250,102, 23,142, 30,251, 29,123,191,219,137,154,107,165,152, 48, 97,124, 50, 4,220,182, 72, 76, 76,108,212,250,231,149, 3,144, +145,145, 65,242,243,243,149,124, 63,223,201, 8,166,165,126, 35,228, 1,193,115,255, 55,106,133,186,197,212,253, 37,127,206, 11, +224,110,157, 7, 3,190,146, 15,253,129, 86,171, 85,150,148,148,104,184,205, 93, 26, 59, 22, 8,206,158, 61,139,202,202, 74, 77, +219,182,109, 85, 74,165, 82,219,216,177, 70,137,171,226, 50, 14, 92, 53, 97, 66, 72, 8,246, 93,102,209,182,191, 12,157, 45,133, +208,157,248, 43, 54,189,125, 20,236,133, 26, 24,172, 20,197,181, 14, 40,196, 12,236, 53,215, 16,217,132,210,238,174, 4,200,229, +114, 92,188,120, 17,167, 78,157, 66,207,158, 61,161,211,233,112,240,224, 65, 87, 44,223, 87,188,158, 16,226,242, 2,112,242, 40, +165,184,124,249, 50,122,247,238,141,252,252,124,176, 44, 11,185, 92, 14,137, 68,226, 90, 37,192,199, 3,112,233,210, 37,152,205, +102, 12, 24, 48, 0,241,241,241, 42,145, 72,132,136,136, 8, 12, 26, 52, 72,117,240,224, 65,205,165, 75,151,160,215,235,143,129, +167,203,254,210,165, 75, 96, 25, 41,218, 37, 38,163, 69,124, 2, 24,145, 4,138,136, 88,116, 24, 52, 1, 23, 15,230,162, 94,222, + 5, 95,114, 40,165,202,234,234,106, 77,113,113, 49, 58,116,232,128,161, 67,135,170, 68, 34,145,118,216,176, 97,100,201,146, 37, +116,240,224,193,246,250,121, 51, 33, 50, 50, 18,245, 10,138,163, 41,153,114,121, 12, 98, 98,251,194,106,169, 65, 69,229, 97, 88, + 44,186,209, 54,155, 97, 32,128, 55, 7, 15, 30, 12, 0, 40,189,118, 13,245,242, 36,112,219,244,166, 41,252,242,203, 47,169,235, +215,175,199,204,153, 51, 49,108,216, 48, 0, 96,119,236,216, 33,206,203,203,195,220,185,115,199,246,233,211,103,167, 63,125,249, +180,222,136,197,123,126,197, 91,127, 83, 99,248,196,228,232, 58, 67, 5, 54,126,179, 7, 25, 31,125,141,109, 11,231,160, 75,217, + 21, 44,211, 95, 67,116,116,140,144, 4,120,135,192,221,237,239, 45, 95,165,209, 28, 0,207,216,190,175,207,119, 35,130,189, 4, + 47, 80,188,126,255,235, 42, 66,200,109,217,222, 30, 75,253, 26,228, 1,120, 42, 3,193, 92,254,199, 87, 57,200,205,205, 85,150, +150,150,106,172, 86,107,147,199,154, 3,157, 78,135,186,186, 58,141, 94,175, 87,121, 59,150,146,146,210,232,179, 59, 82,101, 66, +141,149,197,145,114, 59, 74,170,237,136, 59, 40, 70,159,141,103,113,241,194,113,252,254,147, 21,118,177, 8, 86, 22, 48, 91, 41, +116,148, 69,108, 20,109,146,176,221,151,255,113, 25,251,165,165,165,232,216,177, 35, 46, 92,184,224,114,249,139,197, 98,215,245, +254,134,243,220,107, 8,112,127,111, 80, 72,176, 26,205,203,222,191,206, 24,247,117, 1,203,178,168,171,171,115, 78,142, 98,177, + 74, 36, 18,105, 61, 60, 73,226,220,220, 92,164,164,164, 48,139, 23, 47, 46, 93,182,108,153,125,241,226,197, 77,222, 60, 33, 78, +133,200,100, 44,133,161,246,178,202,225, 48,107, 1,236, 5,240,102,109,109, 45,114,115,115, 93,202,228, 61,247,220, 99,245, 37, +175,190,127,165,228,228,228,100, 79,152, 48,193, 69,254, 63,252,240, 3,179,121,243,102, 40,149,202,137,254,146,255, 85,163, 5, +143,231, 29,196,115, 83, 39, 32,245,241, 41, 48,154,245,216,148,171,197,202, 15,179,240,217,216,251,209,165,236,138,192,166,119, +129, 50,224,169, 4,220,148, 74,128,106,181,154,186,199,116,125,125, 22,112,221,196,126, 67,201, 63,208,152, 58, 71,252,158,217, +254, 30,174,127, 82,255,242,122,109, 99,253,197, 87,191,224,219, 95, 82, 82, 82,180,221,186,117, 83, 69, 69, 69, 53,121,172, 57, +136,138,138, 66,183,110,221, 26, 16,189,183, 99,222, 96,114, 68,192, 70,128, 67, 21, 22,148, 57, 28,216, 85,100,198,198,108, 51, +118, 95,137,197, 89,105, 36,174,212,216,112,185,150, 69,157, 29, 48,218, 41,100, 49,173,125, 18, 51,183,190,223,225,112,192,110, +183, 35, 38, 38, 6, 97, 97, 97,232,216,177, 35,108, 54,155,235,184,183,130, 64,158,242,184,245,253,118,187, 29, 38,147, 9,148, + 82,180,111,223, 30,197,197,197,104,211,166, 13,196, 98, 49, 44, 22, 11,172, 86,171,235,255,242, 9, 15,118,232,208, 1,114,185, + 28,133,133,133,184,114,229,138,198,225,112, 64,175,215,147,159,126,250, 73, 99, 48, 24,208,161, 67, 7, 68, 68, 68, 60,200,119, +142,234,208,161, 3, 24,214,138,226,195,249,168,190,114, 26,172,195, 6,147,190, 28,151,126,250, 14,214, 58, 29, 39,175, 19, 31, +229,134, 67, 76, 76,140,134,101, 89,151,167,115,233,210,165,228,248,241,227,168, 39,109, 22, 64,156,183,130, 71,158,176,219, 77, +176,219, 12, 80,132,182,134, 92, 17, 13,128, 40, 1,216,151, 46, 93, 26,227, 38, 15,107,215,174,229, 10, 40,121,189,231,202,202, + 74,250,217,103,159,209,140,140, 12,250,175,127,253,235,219,148,148, 20, 76,156, 56,145,243, 6,232,183,108,217,130,212,212,212, +148,169, 83,167,126,199,167,205, 42, 43, 43,233,231,159,127, 78,167,253,245, 41,140,202,217,131,191,205,158,140,103, 94,152, 15, +179,213,128,243,231, 46, 35, 35, 99, 35, 54, 63, 60, 4,202,246,173, 2, 30, 27,155, 55,111, 22,230,245, 91, 8,207,112,128,103, + 34,224, 77, 45, 5,236, 25, 54,240,245,249,166, 89,250,141,196,234, 61,173,125,190,214,127, 99,242, 10, 94,126,153, 22,188,252, +135, 59,223,243,179, 47, 79, 68,176,228,185,131,115,249,127,242,232,103, 36, 16,247,127, 70, 70,134,203,178,111, 44,222,207, 29, +119,191,214, 23,124,229, 15,248, 19, 30, 80, 42,149,218,135, 31,126, 88,229, 94,156,198,219,177, 64,112,207, 61,247,224,225,135, + 31,110,224,234,247,118,172,209,239,119,187, 7,221, 66, 69, 8, 39,128,141, 82,156,212, 89,177,254,172, 5, 95, 30, 40,193,207, +231,170, 80, 98, 2, 42,205, 14,156, 51, 80, 92,181, 80, 24,172, 54, 85, 83,228,197, 45,205,179, 90,173, 48,153, 76,104,211,166, + 13,122,245,234, 85,175,232, 69, 99,224,192,129, 46,194,230, 72,187, 49,194,230, 8,221,102,179,193,106,181,130, 16,130,174, 93, +187,162,186,186, 26,151, 47, 95, 70, 85, 85, 21, 58,117,234, 4,134, 97, 96,181, 90, 97,177, 88, 92,223,241,133,216,216, 88, 85, +124,124, 60,142, 31, 63,142,239,191,255, 30, 91,183,110,213,108,221,186,117,247,190,125,251, 32, 18,137,240,192, 3, 15,160, 75, +151, 46, 38,240, 44,100, 19, 27, 27,155, 18, 23, 29,137,202,162, 95,241,251,206, 79,112,252,187,213, 56,249, 93, 6, 46,254,184, + 25, 50,134,229,228, 21,251,146, 35, 22,139,181,113,113,113,170,136,136, 8, 28, 57,114, 4, 87,174, 92,209, 24,141, 70,165,187, + 34, 80,239, 9, 96,214,175, 95,143,158, 61,123,250,252,109, 86, 75, 13,106,170,207, 66, 34, 9, 69,139,232,238,154,208,176,118, +144, 72, 66,149,132, 48,131,185,107,194,171,243,161,249,236, 25,140,233,110,224,148,230,235,240,221,119,223, 65,161, 80,160,103, +207,158,232,212,169, 19,234,195, 7,118,157, 78,103,200,201,201,105,145,152,152,152, 50,106,212,168, 45,124,251,110, 94,222,119, +136,136, 8,195,136,145,131,140,137,253,251,224,209,191,206,133,145,216, 81, 94, 86,133,121, 79,191,134,101, 73,247,160,127,171, +192,149,228,205,155, 55,211,183,223,126, 91, 80, 2,110, 19, 69,192, 27,110,155,189, 0,110,245,170,130, 64, 8,216, 95, 12,124, +195,169, 64,184, 19, 53,119,236,102,201,115,183,194,159,216, 52, 27, 79,108,154,221,224,189,251, 49,190, 22,187,187, 39,193,155, + 71,161,185,121, 1,238,158, 0,207,191,124, 17, 30, 30,174, 29, 61,122,180,106,224,192,129,141, 30,115, 63,215,100,187,187, 93, + 63,122,244,104, 85,120,248, 31,203,242,188, 29,107,210, 58,148,133,170,122,183,105,137,161, 49, 50,220, 31, 37, 69, 91, 57, 3, + 25,165,144, 91,236,232, 16, 38,134,142, 82,252,102,176,227,116,157, 29,237, 90,197,160,211,253, 35, 27,149,197, 89,253,220, 82, +191, 14, 29, 58,160,111,223,190,208,233,116,168,174,174, 70,117,117, 53,194,195,195, 49,120,240, 96, 88,173, 86, 87, 77,128,198, + 8,155, 83, 38,108, 54, 27, 8, 33, 72, 72, 72,128,201,100, 66,121,121, 57,202,202,202, 80, 94, 94,142,186,186, 58, 36, 36, 36, + 64, 44, 22,187,228, 53, 86, 87,192, 83, 41,139,139,139, 83,117,237,218, 21,231,207,159,199,246,237,219, 81, 80, 80,128,144,144, + 16,140, 26, 53, 10,125,251,246,253, 78, 46,151, 47, 4,207, 16,128, 82,169,220, 18,215, 42,118, 86,215, 54, 45, 96, 56,247, 19, + 78,111,255, 8,197, 5,223, 34, 74,230, 64,242,232, 81,232,219,183,239, 28,185, 92,158,203, 71, 86, 68, 68, 4,250,247,239, 15, + 74, 41, 14, 28, 56,128,194,194, 66, 77,113,113,177,166,170,170, 74,185,100,201, 18, 21, 87, 57, 49, 41, 41, 9,123,247,238,245, + 41,143,101,109,218, 26,221, 89, 85, 85,249, 49,200,228,209,104,221,246, 1, 77,108,235,129,154,240,136, 78,223,189,243,238,191, + 31,230,228,125,249,108, 8, 54,252, 96, 65, 99, 74,207,233,211,167,209,178,101, 75, 12, 27, 54,140,189,255,254,251, 97, 52, 26, + 81, 87, 87,135, 85,171, 86,133,117,239,222,125,210,180,105,211,182,248, 51, 38,126,255,253, 52, 58,118,136,199,180,105, 41, 33, +175,188,252, 28, 42,107,107, 80, 81, 89,129,244,103, 94,195,107,143,142,198,232, 14,113,205, 34,255,149, 43, 87,162, 87,175, 94, +248,224,131, 15, 4, 37,224, 38,226,215, 95,127,109,180, 14,192,117, 10,239,237, 66,240,254,172, 42, 72, 77, 77, 37,193,170, 4, +232, 11,158,133,120,130,161, 4, 4,131,252, 3,149,215, 88,169, 94, 79,203,220,159,146,189, 30, 74,130,171, 40, 80,115,238,203, + 93,105,112,183,246, 3, 89, 1,224,110,221,221,127,255,253,164,177, 99,158,231, 26, 67, 83,215,243,149,193,225, 1,229, 40,109, +145,152,194, 94,144,135, 11, 53, 64, 24,145,160, 99, 24,131, 98, 7,129, 72, 38,198,222, 50, 7,204, 44, 16, 43, 19,161,107,210, + 8,200,187, 37,105,155, 82, 0,108, 54, 27, 68, 34, 17, 58,119,238,140,254,253,251, 67,175,215,195,108, 54,187,214,231, 91,173, + 86, 68, 71, 71, 99,216,176, 97,216,178,101,139, 43, 36,224, 13, 14,135,195,149,213,223,163, 71, 15,212,187,233, 97, 54,155, 93, +227,153,243, 36,244,232,209, 3, 85, 85, 85, 48, 24, 12, 77,141,229, 6, 39,102,205,154,165,213,106,181,163,122,246,236,185,219, +173,112, 79,245,240,225,195,119,203,229,242,153, 0,204,254,180,229,172, 89,179,214,107,181, 90,125,207,158, 61,115,221,228, 85, + 12, 31, 62,124,149, 92, 46,255,148,175, 28,134, 97,180,109,219,182, 85,141, 27, 55, 14,231,207,159,215,156, 58,117, 10,151, 46, + 93, 66,120,120,184,166, 69,139, 22, 24, 51,102, 12,254,251,223,255, 34, 41, 41,137,247,111,179,219,141,218,106,221,239, 42,179, +185, 10, 45,162, 18, 52, 97,225,237, 17, 30,209, 1,117,181,197, 91,222, 90,246, 17,166, 79, 75,198,151,207,134,120,109, 39, 14, +227,199,143, 71, 94, 94, 30,174, 92,185,194, 84, 85, 85,193,108, 54, 99,239,222,189,226,122,165, 83,239,239,120,152, 48, 97, 60, + 54,109,218, 2,125,117, 37,174,148, 92,197,179, 79,206,182, 62,255,226, 82,233,163,163,134, 96,152, 69, 15, 72, 2,163,135,205, +155, 55,211,127,252,227, 31,174,114,208, 93,187,118,197,219,111,191,141, 23, 94,120,129, 78,154, 52,233,206,175,220,121,135, 42, + 5,183, 76, 1,184, 17,171, 10,130, 65,238, 28, 42, 42, 62,194,203, 5,223, 54, 89,109,207,159,228,191,138,138,143, 80,240,242, + 31,242,220,137,217,211,101,207,135,180, 43, 62,170, 64,193,183, 47, 7, 77, 94, 48,193,199, 67,192,237, 1,224, 79,127,249, 95, + 26,156,157,134,168, 84, 71, 45,118, 77,249,238, 93,144,216, 77, 56, 90, 75,145, 95,107,135,148, 16,196, 80, 10, 85,155, 22,136, +106, 29,171,138, 31,164,244, 97,105, 58, 61, 0,157, 58,117,194,192,129, 3, 97, 50,153, 96,179,217, 32,149, 74, 93,132,205, 89, +233,177,177,177, 24, 58,116, 40,182,111,223,222,164, 7, 64, 44, 22,163,111,223,190, 32,132,192,104, 52,186,188, 11,156,210,206, + 85, 23,100, 89, 22,189,123,247,198,193,131, 7,225, 79,114,165, 82,169,212,224,143, 60,145, 48, 56,171,237, 93, 2,207, 76,120, +111,158, 0, 55, 89,209, 0,170, 0,248, 93,155,152, 97, 24,109,139, 22, 45,208,187,119,111,149, 68, 34,225,150, 63,106, 0,160, +184,184, 24, 15, 61,244, 16,150, 47, 95,238,151, 76,135,195,162,173, 51, 20, 43,173,214, 26,149, 66,127, 65, 19,209,162, 43, 66, +194,218, 34, 36,172, 45,118,236, 42, 5, 25,221,180,197, 61,100,200, 16, 34,149, 74,105, 85, 85, 21,198,143, 31,111,141,137,137, +145,178, 44,139, 75,151, 46, 1, 1, 36, 75, 62,240,192, 16, 34,147,201,104,196,137, 66, 60,249,228,159, 16,159,208, 77,250,246, +115,127, 98,215,125,248, 41,179, 74,100, 14,168, 47,111,222,188,153, 46, 94,188, 24, 45, 90,180, 64, 73, 73, 9, 20, 10, 5, 88, +150, 69,104,104, 40,222,120,227, 13,188,252,242,203,130, 18,112,131,145,152,152,216,168, 23,128,215, 50,192, 27,129,219,121, 85, + 65, 83,132, 19,136,245,223,152, 60, 79, 75,157,115,221,251, 34,237, 96,203,115,247, 4, 4,122,190, 41,175,130,231,230, 63,254, +202,251, 95, 3,195, 48,218,196,209,227, 72, 85,157, 73, 25,105,183,104, 68, 23,139,112,143,237, 42,194, 99,226, 48,164,119,119, +196,180,107,169,138, 76, 28,233,115,124, 80, 74,209,185,115,103, 12, 27, 54,204, 21,143, 23,137, 68,176, 88, 44,174,210,189,238, + 97,130,246,237,219, 99,232,208,161,208,106,189,139, 86, 40, 20, 72, 76, 76,132, 88, 44,134,213,106,117,125,207,125,233,160,251, + 70, 64, 12,195,160, 95,191,126, 40, 44, 44, 12,164, 25, 40,128,218,250, 87, 48, 96, 8,132,248,189,121,141,122,245,234,197,229, + 81, 16,150,101,149, 70,163, 17, 22,139, 5,221,187,119,199,138, 21, 43,252,220, 28,135,106,109,214, 90,216,172, 6,149,201, 84, + 14,153, 44, 10, 18,105,184,134, 97,196,248, 98,253,119,170, 89, 51, 39, 52, 41,175,190,174, 63,121,239,189,247, 88,147,201, 4, + 0, 72, 72, 72,240,171,252,178, 59,250,247, 31, 64, 68,247,223,255,208,220,127,188,151,231,148, 71,153,132,132,123,145, 48,105, +210, 44,177, 88,188, 62, 16,153,203,150, 45, 19, 6,245,109,162, 4, 52, 69,254, 55, 85, 1,184, 83, 17,204,101,127,158,196,220, + 92,107, 61, 88,242,154, 99,113,187, 19, 59,247,222,195,101, 47,116, 34,158, 24,149, 50, 73, 91,111,189, 98, 68, 0,223, 79, 75, + 75, 67, 84, 84,148, 43,195,159,101, 89,151, 11,159,243, 0,112, 73,127,220,142,128, 93,187,118, 5, 33, 4, 27, 54,108,184, 78, +222,202,149, 43,145,157,157,237,186,214,225,112,248,220, 14, 88, 42,149, 34, 41, 41, 9,124,178,227,239, 84,101, 45, 44, 44, 12, + 97, 97, 97,136,137,137,105,198,216,225, 20,129, 90, 48,140, 24,206,116, 44, 86,195, 83, 30, 93,180,104, 17,169,127,158,148, 97, +152,102,205, 35, 14, 7,187,109,193,130, 5, 4, 0,195,178,172,131, 97, 24, 5,252, 12,191,112, 16,172,251,219, 75, 9,240, 5, +146,152,152, 40, 36,103, 8, 16, 32, 64,128, 0, 1,255, 99, 96,132, 38, 16, 32, 64,128, 0, 1, 2, 4, 5, 64,128, 0, 1, 2, + 4, 8, 16, 32, 40, 0, 2, 4, 8, 16, 32, 64,128, 0, 65, 1, 16, 32, 64,128, 0, 1, 2, 4,220, 21,104,176, 10, 96,254,252, +249, 1,103,112,174, 94,189,250,186,100, 66, 65,158, 32, 79,144,119,247,201, 83,171,213,244,145, 73,106,124,187, 57, 3, 25, 25, + 25, 12,188,172, 65, 23,218, 79,144,247,198, 27,111,184,174,121,249,229,151,137,208,126, 55, 87,158,223, 10, 0, 55,184, 27,187, + 56,144, 37, 47,119,178,188, 64,100,222,238,247,235, 5, 82, 0, 17, 0, 66,234,251, 3, 11,160, 2, 65, 88, 67, 29, 76,112,237, + 16,140,123,246,214,166,183,170,248, 80,109,237,255,111,239,202,195,154,184,214,247, 59, 73, 8, 1, 65, 22, 17, 17,149, 42, 32, +138,184, 32,238, 90,149, 88,144,130,128, 91,209,254,106,123,107, 55,162,183,215,122, 91, 84,172,116,177, 11,173,120,181,155,183, +173,161,183, 85,219,122,111, 43,181,130, 59,149, 26, 92,170, 86,197, 21,180, 42,224, 86, 65,169,202, 78, 66,150, 57,191, 63,194, + 96, 8, 89,102,146, 32,216,206,251, 60, 60, 9, 39,147, 47, 51,231,204,156,247,253,190,115,206,119,106, 35, 15, 29, 58,164,216, +183,111, 31, 0, 96,226,196,137, 24, 59,118, 44,235, 84,194,237,209, 14, 83,167,201, 16, 23, 27,161, 5,100, 34,153, 76, 70,255, +213, 18, 55,241,176,142,244,244,116,146,144, 16,212,226,127,107, 34,128, 71, 59, 71, 0, 24,144, 77,173, 55,128,160,102,217,190, +111,186,169, 14,194,158,221,255, 28,109,207,212,245,218,115,205, 29,253,122, 25,226, 47, 58,115, 96, 93, 81,209,233, 71,252,122, + 4,117,171,174,214,192,195,195, 9, 55,111,148,208, 97, 97, 67,238,134, 13, 30, 63, 18,192,101, 46, 6, 79, 28,254,140,148,150, + 92, 68,201, 21, 21,174,151, 19,244,234, 78, 33,168,183, 4,129, 65, 33,136, 24,243,247, 14,241,240,155, 18, 18,204, 94, 3,237, + 65,100,103,207,158, 85,132,135,239,198,218,181, 13,200,207, 7,222,124,243, 39, 92,191,126, 93,225,231,231, 7,137, 68,130,178, +178, 50,233,244,233,211,225, 8, 65,112,224,192, 1, 82, 93, 93, 45,141,142,142,134,179,179,179, 45,246, 4, 0, 16, 23, 27, 65, + 39, 39, 39,139,128, 76,228,100,235, 31, 21, 56,118,219, 94, 30,127, 2,168,213,169,200,205, 77, 70, 76, 76, 38, 18, 18, 50,154, + 35, 2,188, 16,184, 63,224, 19, 1,113,128, 33,217, 83, 20, 64,127,239,245,167,189, 86,141,186,254,169,220,221,223, 47, 11, 14, +238,219,127,198,180,137,232,213,163, 51, 60, 61,156, 81, 89,165,194,141,242, 94,130, 75,165,149, 62,219,183,126,165,136,121,116, +246,106, 39,113,167, 53,214,236,157, 59,187, 47,242,242,197,237, 10, 33,106, 48,123, 10, 48,110, 24, 16,244, 16, 80,124,133,224, +224,113, 37,118, 42, 78, 99,199,230,197,164, 79, 72,188,116,192, 32,235, 25,237,218, 42,218, 97, 46,138, 32,151,203,169,246, 18, + 1,119,239,222,197, 75, 47, 53,160,107, 87, 32, 41, 9, 88,177,162, 14, 39, 79,158,132, 86,171,133, 68, 34,129,175,175,175, 98, +251,246,237,232,219,183,175,116,248,240,225,249, 28, 59,128,200,194,194, 66,116,235,214, 77, 17, 29, 29, 77,125,251,237,183, 0, +160,200,203,203,195, 19, 79, 60,129,145, 35, 71,114,189, 86, 49, 0,236,220,117, 66, 0,100,210,250, 87,189,134,230,123, 16, 30, +134,222, 62, 0,204,156,185, 25,185,185,250,215,228,228, 18, 48, 17, 1, 62, 26,112,127,137,223,176,188,221, 82, 1,119,116,144, + 77, 94,205, 34,224,207, 76,254, 0, 68,123,114, 55,189, 38,157, 16, 17, 50, 98,104,119, 80,148, 62,171, 27, 77, 19,116,118,115, + 70,167, 32, 49,122,247,242, 64, 15, 63,183,135,246,228,110,122, 45, 46,225,153, 44, 0, 55, 45, 25,188,124,113,187, 98,252,176, + 26,252,243, 25, 64, 40,212, 11, 40,141, 22,232,228, 10,132, 6, 3,163,195,129,237,138, 26, 28, 57,189, 93, 49, 96,208, 68,155, + 30,124, 71, 13, 1,152,251, 62, 35, 2,238,119, 99,120,123,123, 99,251,118, 23,244,234,165, 68,126, 62, 80, 89, 41, 66,112,112, + 48,130,131,131, 81, 87, 87,135,210,210, 82,228,231,231,163,166,166, 70,209,175, 95, 63,214, 67, 3, 63,254,248, 99,164, 82,169, + 84,136,197, 98, 84, 86,182,140,100, 41,149, 74,124,249,229,151, 40, 45, 45, 37,143, 63,254, 56,151,250,164, 1, 32, 39, 91, 14, + 64, 38,208,191,218,142, 99,199,142, 53,215, 55,179,137,146,169, 50, 54,247,133, 97,219,178, 45,179,234, 20, 16, 18,137, 11, 23, + 48,178,174, 78,209,229,198, 13,252,238,235,139, 19,157, 59, 75,157, 6, 12, 0,161,168,124, 91,175,153,235,134, 81,108,108,176, + 45,107,107,123,134,161,255,228,228, 92, 36, 36, 4, 53,191, 50, 72, 72, 8,226, 69,192,125,128, 49,217, 51,251, 3, 24,150,243, +171, 0,140, 31,250, 63,249,245, 21,157, 57,176, 34, 56, 56, 56,100,100, 68,247, 22,229, 2, 1, 5,177, 88, 8, 23,137, 8, 78, + 78, 2, 4,245,241, 66, 80, 80,176,111,209,153, 3,219, 45, 9,197, 19,135, 63, 35, 66,212,224,229,103, 1, 85, 35,112,249, 58, + 80, 89, 13, 84,213, 0,255,221, 10, 44, 88, 14, 44, 91, 5,140,141, 0, 4,164, 6, 39, 14,127,198,123,139, 6, 24, 52,104,144, + 52, 39, 39, 20,190,190,192, 19, 79,136,224,231, 55, 2, 19, 39, 78,148, 38, 36, 36, 80,241,241,241,210,152,152, 24,116,235,214, + 13, 39, 78,156,192,247,223,127,175,248,233,167,159, 34, 27, 27, 27, 35, 45,217,252,246,219,111, 35, 27, 27, 27, 21, 78, 78, 78, + 22,127, 91,161, 80, 96,211,166, 77,145,108, 72,118,255,254,253, 4,128, 90, 46,151,139,239,137,128,123,100,186,127,255,126,194, + 85, 64, 29, 61,122,180,249,207, 82,153, 45,162,142,109,153, 37,242, 15,252,237, 55,197,244, 83,167, 20,189, 46, 22, 67, 92, 83, +131,238, 23,127, 67,228,145,195,138,174,167, 79, 43, 64, 72,164, 45,237,125,244,232, 81, 28, 59,118,140, 20, 22, 22, 70,218,122, +207, 48, 54,216,148,177,181,103, 76,244,108,202,172,129, 33,125,230, 85,157, 16,204, 63,240,247,137,248,217,164, 1,126, 96, 35, + 0,109,233,169,145, 54, 60, 63, 71,133,152, 25,251,230,126,199,210,111, 20,157, 59, 29, 59,107,134,180,153,244, 77, 65,226, 44, + 66, 85,117, 35, 66,130,188,145,181, 69, 17, 20, 54,120,188,135, 57,123,165, 37, 23, 49,123,138,254,253,238,253,192,167,223, 0, +147,199, 3,113,145,192,111,197,192,201, 34, 2, 23, 9,133,161, 97, 64,204, 68,224,199,220,139,136, 24,227, 56,207,221,150,186, +107,163, 57, 21, 54,193,221,221, 61,191,174, 78, 63,223,242,137, 39,158,192,184,113,227, 40,195,207,238,222,189, 43, 13, 13, 21, + 41, 18, 19, 1,138, 58,142,138,138, 6,197,239,191, 7, 89, 10,255, 69, 82, 20,165, 96,187, 57, 76, 69, 69,133,194,154,238,157, + 51,103, 14, 54,110,220,136,141, 27, 55,146, 57,115,230,180,104,139,253,251,247,147,141, 27, 55, 54, 31,215, 81,250, 3,182,101, +230,208, 88, 88,136, 62, 5, 5, 80, 11, 4,112,162, 0, 45, 77, 64,107,116,160,181, 90,116, 61,176, 31,197,132,160,243,208,161, + 54, 19,184,171,171,171,226,248,241,227,210,185,115,231,230,219,106, 3, 64, 11,143,220, 84,153, 45,209, 5,123,201,223, 28,209, +231, 26, 69, 2,120,180, 63, 76, 10, 0,115,147,223,108, 33, 28,107,132,200,213,222,253, 30,163,181,101,198,184,165, 73,133,182, +216, 51,245, 29, 27, 39, 46,138,252,252,131, 6,248,251,185,129, 16,224,192,225,235,104, 80,234,119, 93,141, 24,226,135,174, 93, + 92,112,253, 70, 45, 93,124,185, 82, 32, 18, 9,208, 55,208, 11,254,254,193,158,208,111,209,106, 18, 37, 87, 84, 24, 55, 12,104, +212, 0,187,246, 1,138,195, 4,254,221, 40, 4, 6, 0,143, 60, 12,244, 15,162, 32, 18,234,183, 22, 31, 29, 14,252, 75,174, 98, + 85,223,134, 33,121, 54,239,217, 40, 94,195,177,126,195,122,119,228, 10, 3, 91,208,180,157, 43, 6, 15, 30, 44, 53,254, 76, 40, + 20, 42, 6, 12,168,192,178,101,122,121,250,222,123, 23,113,229, 74,152, 89, 91, 42,149,202,170,231,111,136, 43, 87,174, 88, 61, +102,194,132, 9,212,132, 9, 19,154,201,126,227,198,141,196, 88, 32, 76,152, 48,161, 93,234,174, 45,188,127, 0,232,123,251,142, + 66,173,209, 64, 32, 16,128, 8,133,160,105, 26, 26,154, 6,173,211, 65,167,163,209,179,188, 92, 81, 51,116,168,205,215,220,208, +208, 0, 0,138, 99,199,142,129,162, 40,206,243, 59,218, 66, 4, 56,202,243,207, 77,206, 69, 76,102, 12,102,110, 6,146,115,245, +239,115,147,115,155,197,129,120, 91, 49,207,188,247, 17,134,115, 2, 88,205, 1, 48,183, 10,192,214,213, 1,230, 60, 46, 91, 60, + 49, 75,162,193, 86,129, 98,233,186,141,191,203,214,139, 48, 55,169,208, 22,123,150,190,195,252, 14, 5,128,222,100,117,238, 2, +173,159,237,239, 12, 0,184, 94, 86, 3,165, 82, 11, 0, 8, 14,244, 66,215, 46, 46, 56, 93, 84, 33,184,112,233, 46, 36, 18, 33, +130,250,120,162,178, 90, 13, 0,102, 13, 95, 47, 39, 8,122, 72,255,251,143, 78, 0,194, 7, 80,112, 22, 3, 90,173, 62, 18,224, +233, 14,148, 94, 3, 98, 38, 0, 15,245,212, 31,223,158, 48, 36,125, 91,198,133, 59, 58, 42, 42, 42,218, 44,138,210, 68,242,205, + 30,127,123,147,191, 33, 50, 50, 50, 72,106,106, 42,101,235,231,198,112, 42, 41, 70,163, 70, 13, 74, 40,130,142, 16, 80, 0,180, + 58, 26, 26, 45, 13,162,211,129,186,116, 1, 64,156,221,231, 93, 88, 88, 8, 31, 31, 31, 69,117,117,181,212,195,195,195,102, 17, + 96,173,236,126,145,127, 90, 90, 26,149,158,158, 78,102,110,110, 41, 8, 0, 32, 38, 51, 6,226,109,197,216,182,173,164,121, 37, + 0, 51, 97,208,219,219,155,103,234,251, 76,254,102, 5, 64, 71,135, 37, 66,180,133, 96,237, 89,226,104,209,110, 27,175, 38,160, +102, 85,114,253, 13,202,195,195, 9,149, 85, 42,248,120,187, 34, 41,177, 63,180, 58, 26,206,206, 66, 8, 5, 2, 16, 66, 16, 63, + 57, 8, 83,162,131, 64, 81,192,157, 74, 37, 60, 60,156, 0,224,174, 57,131,189,186, 83, 40,185, 74,189,136,105, 47, 0, 0, 32, + 0, 73, 68, 65, 84,208, 63, 8,152, 52, 70,223,235,252, 86, 12, 12,238, 15,120,117, 6, 98, 35, 1,154, 6, 68, 66,224,226,101, +253,241,108,219,150,203,123, 91, 19, 97, 88, 19,164,109, 13,154,166, 35,123,244,232,129,146,146, 18,236,223,191, 95, 49,126,252, +120,169,155,155, 27, 4, 2, 65, 62, 0,232,116, 58,233,185,115,190,138,183,222,186, 1,138,162, 80, 81, 17,130,144,144,222,184, +120,241,162, 57,123, 38,203, 55,109,218,212, 58,138, 68, 8,102,207,158,205,233,154, 13, 69, 64, 71, 34,127, 71,136, 4, 67,220, +237,217, 3,226,223, 46,128, 56, 1, 98,154,232, 39,182,234,180, 80, 19, 29, 26,180, 90, 40,131,251, 59,228,220, 7, 14, 28, 8, +138,162,108, 34,127, 0, 24, 57,114, 36, 70,140, 24, 65, 29, 61,122,148, 88, 42,179,134,166,136, 65, 11,194, 55, 85,198, 5,201, +185,247,136, 31, 64, 43,207,159,153, 48,184,109, 91, 9,207,212,237, 64,254, 15,172, 0,104,107, 65,225, 40, 66, 32, 4, 16,204, +174,108, 51, 17,192,172, 92, 16,204,170,100,227,253, 3,128,232,230,141,146,219,215,111,244,244,241,241,118,197, 7,159, 31,195, +132,177,189, 16, 49,184, 27, 40, 39,170,121, 69, 64,211,214,241,184,126,163, 22, 55,111,148, 92, 6, 96,214,173, 12,234, 45,193, + 47, 5, 74,244, 15, 2,124,134, 1, 75,231, 3, 11,231, 2, 30,238,250,176,255, 91,159, 0,203, 23,234,143,253,165, 64,127,188, +173, 4,237, 40, 79,189, 35,229, 2, 56,119,238, 28, 36, 18,125,157,236,216,177, 3,215,174, 93, 83,244,235,215, 79, 58,105,210, + 36,212,214,214, 70,122,123,123, 43, 14, 30,212, 34, 63, 31, 24, 49, 98, 56, 2, 2, 2,164, 61,123,246, 4, 0,133, 41,123,157, + 58,117,130, 90,173,102,245,219, 90,173,246,129,127,118, 13,201,159,141, 16, 96, 43, 2, 74,186,250, 74,157,207,156, 81,208,132, +160,147, 64, 4,161,144,130,150,232,208,160,209,160, 86,173, 70,153,191,191,212,199,142,243,118,117,117, 5, 69, 81,210, 17, 35, + 70,228,219,106,131, 33,122,107,101,247, 91, 4,164,165,165, 81,201, 77,158,189, 49,249, 27,122,255, 60,218,151,252,121, 1,112, + 63, 60,188, 54, 94, 82,216, 44, 2,216, 9, 13,109, 88,216,144,178,226,203,149, 62, 67,194,124,177,116,225,104,172,255,223, 89, +184, 72, 68, 8, 31,232, 11,138,162, 12, 60, 73,130,226,203,149, 8, 11, 27, 82, 8,160,214,156,193,192,160, 16,236,216,123, 26, +115,103, 2,164, 20, 24, 61, 3, 8,236, 5,108,204, 49, 56,104, 33,160,211, 1, 59,246,234,143,111, 47, 88,138, 20,181,215, 50, +192,187,119,239, 42, 66, 67, 47, 99,221, 58, 0,208,225,237,183,207,224,228,201, 6, 69, 67, 67, 3,106,107,107, 81, 90, 90,138, + 91,183,110, 33, 34, 34, 2,179,103,207,182,186, 12,144, 16, 34,165,105, 90, 33, 16, 88, 95,224,195, 8, 15,174, 96,134, 0, 54, +110,220,136, 9, 19, 38,180,235,243,149,154,154, 74, 49,196,111,109, 8,192,218, 49,134,240, 26, 58, 20,119,212,106,232, 20,249, + 80,139,157,224, 70, 68, 80,209, 52,170,213,106,212, 78,122, 4, 62,195,134,217, 24, 21,164, 48, 98,196, 8,155,199,253, 13,109, + 24, 18,189,169, 50,123, 68,192,177, 99,199, 44,150,177,129, 41,242,103, 60,127, 0,252,132,192,118, 38,127, 94, 0, 60,224,104, + 30,255,103, 63, 12,160, 11, 27, 60,126,210,246,173, 95, 29,252,181,192,189,255,168, 97,254,136,141, 10,196,238,159, 75,177,227, + 39,253,195,249, 90,202, 88,208, 52,193,175, 5,101, 40, 41, 41,190, 26,159,248,236, 63, 0,104,204, 25,140, 24,243,119,106,199, +230,197,228,195,175,244, 75, 1,215,190,171, 95,250, 23, 53, 78,191, 20,240,195,215,245,228,255,225, 87,128, 14,157,109,206, 8, +104,175,103,110, 45,130,208, 94,171, 0,234,235,235, 49,116,168, 10, 35, 70,232,255, 31, 62,156, 96,247,238, 82, 92,188,120,145, + 73, 4,132,200,200, 72,244,237,219,151, 85, 14,128,201,147, 39,231,103,103,103, 91,141, 2,104,181, 90,120,122,122, 74,185,158, +111,211,114,192,230,149, 1,251,247,239, 39,182, 14, 3,140, 28, 57,146, 85, 25, 23, 17, 96,237, 56,214, 70, 5,130,124,245,168, + 81,210,243, 78, 78,232, 85, 94,174,112,187,118, 13,170, 62,125,112,197,215, 87,234, 29, 17, 1, 52, 13,209,216, 64,176,142, 32, +233, 86, 54, 76,149,177,173, 75,227,227, 24,194,183, 86,102, 11,140, 73,159,137, 8,216, 59,132,199,163, 53,216, 76,140,230, 5, + 64, 27,122,230, 29,244, 55,238,196, 60, 58,251,163,220,221,223, 47,254,189,188, 54, 40,184,143, 23,166, 76, 14,130,151,167, 4, +149, 85, 42,156, 60,123, 11,197,151, 43, 81, 82, 82,124, 40,230,209,217, 63, 2,184,110,205, 96,159,144,120,233,129,130,237,138, + 67, 5, 53,152, 50, 9,248,226,125,125, 38,192,146,171,192,151,155,244,158,191, 14,157,209, 39, 36, 94,106,235,181,218, 51, 4, +192,150,252,219, 99, 14, 64,121,121,185,212,203,203, 71,113,252,248, 31, 0,128,139, 23, 59, 99,196,136, 1,232,210,165, 11, 36, + 18, 9,202,203,203,165,241,241,241,156, 82, 1,247,238,221, 91,122,225,194, 5,133, 97, 68,199,152,252,131,131,131, 49,114,228, + 72, 78, 36,198,172, 2, 48, 24,251,103, 38, 4,218, 36, 2, 76, 17,161,173,228,104,141,220, 57,145,191,129, 8,232, 50,124, 56, + 26, 0,170,161,169,200,222,169,106,246,146, 63,151,122, 99,251, 91,142,182,199,150,252,213, 9,193, 0, 63,254,127, 95, 34, 1, +230,132, 1,167,101,128,182, 78,150,227,186, 12,208, 86,123,182,218,116,244,249, 89,170, 39, 71,157,159, 61, 19, 23,157,196,157, +228,241,137,207,126, 87,116,230,192,103, 91,114,246, 5,250,245, 8, 26,109,176, 23,192,145,176,176, 33, 71,227, 19,159, 93, 6, +160,158,141,189, 1,131, 38,230, 15, 24, 52,145, 58,113,248, 51,242,253,142,139,120,239,211,142,183, 23, 64, 71, 36,127, 0,120, +252,241,199,113,250,244,105, 60,243,204,241,166, 8,192,112,204,154, 53, 68,234,234,234,154,111,171,205,240,240,240,252,240,240, +112,106,235,214,173,145,181,181,181, 10,161, 80, 8,129, 64, 0,173, 86, 11,177, 88, 12, 55, 55, 55,169, 3,200,223, 33, 34,128, +199,159, 19,105,105,105, 84,122,114, 58,241, 95,224, 47, 69,111,211,199,148, 37,231, 42,248,249, 0,237, 11, 17,219,142,210,209, + 29,111, 91,216,179,229,183, 30,228,235,181, 19,213, 97,131,199, 63, 25, 54,120, 60,147, 49,198, 13,128, 15,128,114, 0, 74, 52, +165,125,229,130,136, 49,127,167,108, 73,242,211,214,245,208,145,242, 74, 24,195,213,213, 53,127,204,152, 49,212,152, 49,142,175, +184,196,196,196,124, 56, 40,185, 37, 51,238,111, 76,242, 19, 38, 76,160, 54,110,220, 72, 58,194,124, 0, 30, 29, 79, 4, 88, 62, + 0, 60,249,183, 1,216,102, 1, 4, 0, 42, 60, 60,156, 31,123,225,193,131, 7, 15, 30, 60,254, 98,224,247, 2,224,193,131, 7, + 15, 30, 60,120, 1,192,131, 7, 15, 30, 60,120,240,224, 5, 0, 15, 30, 60,120,240,224,193,131, 23, 0, 60,120,240,224,193,131, + 7,143, 63, 7, 90,172, 2,152, 63,127,190,205,179, 50, 77, 37,114,224,237,181,141, 61, 54,155,216,180,167,189,188,188,188, 72, + 0,138,172,172, 44,135,216,219,187,119,111, 36, 77,211, 14,179,199,223,127,237,102,111, 54,128, 77,109,124,126, 78, 0, 36,208, + 39,173, 81, 65,191,154,133,192, 40,137, 13,223, 30,188,189, 63,187, 61,206, 2,192, 26, 57,152, 3,151,165, 84,142,182,119, 63, +145,156, 84, 77, 32, 22, 35,115,163, 11,171,243,203,203,203,139,204,202,202, 82, 56,234,122, 13,237,173, 94,189, 90,154,146,146, +162,176,101,123, 97, 83,246, 10, 63,237,140,129, 47,214,192, 30,123, 12,166,141,216,169, 56,125, 65, 7, 0,200,204,204, 36,201, +201,201,118,181,103, 72,183,239,161,212,122,195,197,197, 5, 89, 89, 89, 36, 41, 41,169,163,220, 31, 93,231,189,146,242,205,218, + 15, 86, 63, 5,224, 15, 7,216, 11,152,255,210,203, 95,124,254,201,135, 79,154,177,231, 4, 64, 11,203, 25,217,156,160,207,220, +216,117,225,194,151,191,249,248,227, 15,159,130,126, 51, 39, 26, 14,200,228,102,252, 28,115,188, 55, 14,183, 85, 67, 80, 20, 21, + 39, 16, 8, 6, 8, 4,130, 72,138,162, 66, 0,184,170,213,234, 92,161, 80,232, 73,211,116, 5, 33,228,117, 0,119, 28, 89, 7, + 60,120,152,194, 83, 37, 37,228,155,160, 32,135,245, 81,201, 50, 25,201,108, 35, 78, 20, 89,123,200, 9, 33,150, 30, 58,206, 29, +134,163,236,113,245, 96, 29,137, 61,123,246, 88,237, 68, 24,114, 77, 77, 77,133,175,175,175,201, 12,120, 41, 41, 41, 10,182,191, +201,216, 99,136,255,200,145, 35,205, 66,192, 30,123,244,185, 55, 32, 24,240, 54,190,222,171, 79, 29, 75,159,123,163,249, 24,193, +128,183, 57,213, 75,231,154, 87, 8, 77,128,239,118,235,109,197, 78,116, 66, 88,112, 17, 50, 51, 51, 9, 0,112, 21, 2,213,218, +239, 34,171,174,220,129,146,154,168,168,111,236,132,216,152, 42,244,240,163,112,252,248, 33, 82, 83,163,194,164, 73,147,218, 85, + 8,204, 95,184,240, 37,208,244,228,249, 11, 23,190,244,249,199, 31,191,110,183,189, 5, 11, 95, 32, 52, 29, 61,127,193,194,151, + 62, 95, 99,210,158,134,133, 25, 13, 0,106,193,130,133, 47,209,180,110,242,130, 5, 11, 95, 90, 99,218,150, 0, 54,228,122,176, + 19,106,195,251,239,135, 31,126, 80,204,152, 49, 67, 58,121,242,228,124,123,140, 10,133,194, 88,145, 72, 52, 65, 36, 18, 61, 46, + 20, 10,189, 4, 2,129, 91, 70, 70,134, 96,241,226,197,207,234,116, 58,104,245,120, 92,167,211, 37, 0,248,165, 73, 4,168,155, +250,191, 54, 31, 6,221,177, 99, 7, 97,219,223,197,197,197,113,186,167,119,238,220, 73,236,249, 62, 15,199,195,101,229, 74, 64, + 46,119,152, 61,229,146, 37,118,125,159,201, 8,200,105, 59, 96, 54,228, 63,108,216, 48, 20, 20, 20,112,242,248, 45,145, 60, 27, +123,166,236,167,166,166,162,180,180, 20, 89, 89, 89, 14,221,214, 53, 57, 33,147,192, 37, 4,153,155, 34, 41, 0,200,204,242,160, +184,144,255,234,213,171,165, 21, 21, 21, 10,115,228,159,154,154,138,140,140, 12, 78,228, 15, 0, 73, 73, 73, 24, 61,122,180,116, +244,232,209,118,217, 99,200,158,121, 93,241, 14, 90,144,255,146,153, 18,172,220,172, 98, 85, 87, 30,202, 20, 50, 48, 68,136,122, + 37,193, 43, 79, 73,112,164, 72, 11,101, 61, 65,131, 26,144,134, 23,161,232,162,142, 83, 52,160,244,250,135,164,234,102, 39,184, +119, 22,195,175,187, 27,186,118, 11,198,213, 18, 53,122, 15,208,192, 73, 82,129,188, 45,183,177,101,203, 22, 50,125,250,244,118, +233,240,100, 50,153,179, 79,143, 30, 11,191, 61,114,148,138,237,215,247, 37,153, 76,246,174, 92, 46,111,180,199, 94, 87,191, 30, + 11,191,219,123,132,138, 14,239,103,151, 61,153, 76, 38,246,243,235,190,240, 39,197, 1,106,248,144, 48,115,182,232,118,168,182, +230,237, 7,179,178,178, 20, 9, 9, 9,216,188,121,179, 98,242,228,201,173,218, 48, 34, 34,130,188,245,214, 91, 72, 72, 72,176, +216,190, 34,145,104,146, 88, 44, 30, 40, 22,139, 23,136,197, 98,215,235,215,175,163,111,223,190, 16, 10,133,112,119,119, 71,113, +113, 49,220,220,220, 68,199,142, 29,243, 60,124,248,240,129, 23, 95,124,177, 55,128,171, 0,196,230,234, 32, 57, 57,185,149,179, + 98,216,111, 49,229, 20, 69, 33, 51, 51,211,234,253,183,117,235, 86,179, 54, 12,203, 9, 33,136,139,139,227, 84,161, 57, 57, 57, +118,125,191, 45,113,234,212,169,200,240,240,240,124, 71,216,186,117,235, 22,161,105, 26, 16, 84, 65,221,168,130,216, 89, 2,208, +158, 16, 8, 4,232,214,173, 27, 53,216, 56,114,105, 33, 25,206,195, 15, 63, 76, 54,111,222, 12,115,246,102,206,156,137,131, 7, + 15, 82,182,158, 31, 0,148,223, 58, 79, 12,207,207,158,107,183, 37,154, 96, 46, 13, 48, 43, 1,192,150,252,217, 34, 53, 53,213, +234, 49,108,136,203, 28,249,175, 88,177, 2, 75,151, 46,109, 81,110,171, 8, 72, 30,150, 73,208, 37, 4,153, 63, 69, 82,134, 30, +127,116,116, 52, 5, 0,204,107,113,113, 49, 97, 67,214,150,200,191, 41, 50, 96,213,107,103,194,244,134, 30,190,241,208,130, 45, +246, 44,121,248, 75,102,178,223, 41,206, 71,249, 10,233,251,144, 16, 46,206, 20, 30,242, 23,226,118, 37, 13,141, 86,136, 59, 85, + 4,213,117, 4,197,191,211,128, 0,240,113, 61,131,188,188,188,200,168,168, 40,139,157,194,213,107, 31, 68,134, 6, 7,225,240, +205, 91,232, 19,208, 21, 3, 7, 7, 66,232,236,141,135,250, 84,162, 82,169, 66,197, 77, 29,126,191,165,130,171,168, 20,121,121, +238, 86,237,181, 17,230, 60,181,120,177,184,180,187, 63,156,135, 13, 23,168, 14,236,159, 3,224, 43, 27,236, 48,158,248,156,167, + 95, 90, 36,254, 93,236, 7,183,144, 8, 65, 77,225, 65, 91,237, 1,192,156, 23, 23,190, 44,134,179, 59,250,244, 11, 19, 92, 56, +123,194, 30, 91,142, 4,205, 60, 35, 20, 69, 65, 34,145, 72, 1, 40,140,239,137, 97,195,134,177, 34,127, 0,112,114,114,242,148, + 72, 36,115,111,223,190,237, 26, 18, 18,130,161, 67,135, 66, 36, 18,225,147, 79, 62,129, 78,167,195,160, 65,131,240,227,143, 63, +226,216,177, 99, 56,115,230, 12,132, 66,225,103, 58,157,110,170, 37,155, 83,167, 78,109,238,231,172,245,131,108, 8, 87, 46,151, + 75,253,252,252, 20,132, 16,139, 14,208,205,155, 55, 57,239,149,193,216,182,245,251, 12, 81,159, 63,127,222, 98,191, 17, 26, 26, + 42,229, 74,230,231,207,159, 87, 84, 87, 87,195,195,195, 67,106,143, 16, 56,113,242, 16,121,235,157,249,232,212,201,165,213,103, +245,245, 74,228,252,120, 26,103,228,114,106, 74,247,238,228,122, 98,162,249,190,253,192,106,125, 99, 30, 88,141,238,147,226, 33, +137, 24, 14, 93, 72, 88,203,240,217,119, 27,224,245,254,116, 12, 48, 24, 42, 82, 62,250, 60, 62,183,114,126,203,210,230,193,187, +139,171,190,224,141,143,144,178,232, 25, 0,192,221, 59, 13,120, 47,125, 45,137, 24, 58,214,102, 17,224,232, 33, 5,139, 2,128, +241,216,173,121,234, 29, 5,165,165,165, 88,186,116,169, 77, 2,194, 18,244,158,126, 50,181,103,207, 30,146,149, 57, 18, 16, 43, + 9,155,177,127, 83,100,109, 76,202,150,134, 5,204,193, 80, 80, 28, 57,114, 68, 49,122,244,232, 22,161,127,174,246,254,187,216, +205,108,231, 54,103, 85, 61,107, 59, 52, 77, 71, 58,187, 82, 16, 8, 0, 87, 23,160,170,134, 70, 35, 33,232,228, 66, 65, 69, 3, +202, 70,130,158, 93, 5,160,181,192,165,235, 58,148,150,150, 42, 96, 33, 61,237,185,162, 31, 34, 7, 14,236,175, 16,139, 9, 94, +152, 59, 10, 58, 29,193,205, 10, 53,174,221,168, 2,156,174,195,197,171, 17,229, 21, 87, 32, 16, 87,227,220,185, 42,120,120, 89, +182,215, 86,112,246,246,126,227,241,191,253,205,249, 53, 26,240, 90,154,230,118,235,244,169,215,109, 36, 89, 2, 0, 18, 15,239, + 55,254,239,201,191, 57,175,186,172, 67,207,217,169,110, 23, 74,207,152,178,103,117, 71, 54,153, 76,134,206, 30,158,111,204,121, +242, 41,231, 51,215, 42,145,248, 68,178,219,191,223, 73,177,245,220,204, 70,242,204,149, 91, 17,222, 58,230, 25,137,143,143, 71, + 84, 84, 84,126, 86, 86, 22,148, 74,101,115, 27, 50,158,127,124,124, 60,171, 54,117,118,118, 30, 91, 95, 95,223, 63, 52, 52, 20, + 82,169, 20, 41, 41, 41,120,238,185,231,244,157,185, 70,131,245,235,215,163,160,160, 0, 39, 78,156,192,247,223,127, 15,165, 82, + 25, 76,211,116,172, 37,155, 83,166, 76,113,232,253,180, 99,199, 14, 86, 67,115, 20, 69, 41,184,134,240, 13,109,219,242,253,166, +208,112,126,117,117, 53,202,202,202, 76,126,238,239,239, 15, 91, 9,188,172,172, 12,101,101,101,118, 9,129, 51,167, 47,226,155, + 13,219, 49,126,252, 88,132, 13,234,209, 92, 94,116,246, 6, 14, 28, 56,132, 31, 55,255, 76,178, 94,125, 21,215, 19, 19,225, 50, +110, 28,148,191,252, 98,210, 78,230,248, 20, 10, 0, 46,109, 88, 67, 6, 87,236,198, 83,123,183, 67, 23, 18, 6,229,162,229, 0, + 0,151, 85,203,225,118,177, 8,139, 75,197,232,251,244,130,123,245, 88,127,239, 57,181,116,126, 81,209,227, 90,157, 95,222,158, + 95,112,230,244, 69, 68, 12, 29,107,243,253, 99,203,144,130, 97,184,223, 82, 52, 64,196,213, 99,119, 52,209,218,139,172,172, 44, +187,190,159,156, 41, 35,232, 14,100, 38,232, 59,174,204,130,228, 22, 97,126,189,199, 95, 77,140, 35, 1,108,201,186,162,162,162, + 5, 57,219, 66,214,108,193,136, 14,153, 76, 70,172,229,131,182,228,217, 48, 96,194,255,230,236, 17, 66,200,237,115,175,160,123, + 83,232,191, 89, 49,235, 8, 84,106, 64,211, 84,166,209, 18, 16,129,254,253,217, 51, 5,204, 42, 1,147,112,119,175, 86,212, 43, + 5,240,241,246, 68,213,221, 6, 84, 85, 87,225,200,241,155,184,113,139, 64,220,169, 1, 61,130,235,160,108,184,141,190,131, 53, +232, 29,218,136,239,191, 40,192,238,221,187, 35,239,227, 45, 39,144,201,100, 81, 51, 95, 72,238, 86,230,225,133, 18, 45,224, 18, + 53, 25, 2,175, 46, 62, 50,153,108,178, 92, 46,255,201,128,172,157, 96, 48,238,109,174,223,151,201,100,209, 73,115, 95,232,246, +135,192, 3, 87,235, 52,240,140,136,130,200,221,203,216, 30,192,110, 2, 91,204,180,233, 51,186, 17,161, 51,170,235, 27, 49,112, +216, 24,184,117,246, 48,101,171, 93,192,120,255, 20, 69, 97,219,182,109, 36, 62, 62, 30,219,183,111,135,139,139, 75,100,106,106, +170,130, 11,249, 3,112,174,170,170,122, 90,163,209, 8, 92, 93, 93, 49, 97,194, 4,172, 90,181, 10, 78, 78, 78,144,201,100,216, +176, 97, 3, 10, 10, 10,112,228,200, 17,252,252,243,207, 56,123,246, 44,124,124,124,124,180, 90,237, 67,176, 50, 4,146,156,156, + 76,172, 13, 1,124,241,197, 23,172,206,179, 45,135, 0,182,110,221,234,144, 33, 0, 15, 15, 15,105, 89, 89,153,194,220,103,246, +182,187, 45, 66, 64, 90, 82, 66,238,172, 92,137, 15, 0,224,240, 97,220,157, 25,135,213, 67, 66,154, 67,246, 97, 3, 6, 96,214, +236, 41,232, 93,121, 27,215, 19, 19,209,101,201, 18, 40,130,130,168,193,191,252, 98,241, 57, 17, 75, 31, 70, 72,108, 36, 22, 47, +121, 23,255, 66, 17, 86,143,158,132,129, 35, 70, 33,248,110, 41,214,123, 14, 69,169,199, 45, 12,146, 72,136, 74,165, 98,213,190, +210, 73, 67,240,212,211,241, 56,250,235, 89,236,206,253, 9,111, 2, 88,189,106, 29,194, 6, 12,192, 83, 79,199,163, 65,121, 7, + 18, 14,246,140, 97,239, 28, 0, 78, 17,128, 7, 9,114,185,156,114,196,172,117,134,220,179,150, 94, 6,132, 98, 36, 79,238, 13, +120,246, 70,102,211,130, 37,182, 99,255,142,134,225,181, 49,147,254, 12, 61,127, 99, 48,115, 3,204, 77, 6,180,101, 39,194,141, +139, 58,153,141, 8,184,215,164,224,138,154,224,230,109, 26,128, 0,110,174,250, 16,167, 70, 75,160,106, 4, 84,106, 64,213, 8, +168, 53,128, 74, 9,168, 27,239, 69, 73, 76, 9, 10, 55,237, 43,228,198,181, 0,244,234,227, 6,226, 36,194,109,165, 18,138,125, +215,113,174,248, 6,238,222,173, 67,216, 48, 29,234, 85, 90,168, 26,117, 80, 54,208,184,121, 13, 80,214, 3, 91,182,108, 81,112, +217, 0,195,206, 54,161,133,158,158,111, 60,243,234,171,146,239, 13, 40,196,235,213, 52,183,187, 75, 23,189, 14,224, 39, 3,178, + 86,179, 48, 73, 68,110,158,111, 60,247,242, 82,201,174, 27,186,230,194,158,143, 47,117,187,250,229,171,134,246, 88, 69, 1, 92, +221,220, 95,127,233,149, 69,146,146,178,123,187, 69, 38, 60,145,236,246, 93,230,106, 83,182, 56, 61,107,166,238, 37,142,207, 26, + 97,188,127,137, 68, 34,141,138,138,202,103,150,140, 42,149, 74, 69, 65, 65, 1, 21, 31, 31,207,214,150, 22, 64, 48, 0, 58, 60, + 60,156,150, 72, 36,130, 13, 27, 54,224,217,103,159,197,251,239,191, 15, 66, 8,126,253,245, 87,236,219,183, 15,103,206,156, 65, +117,117, 53,250,246,237,139,154,154, 26, 87,129, 64,224,107,205,248,180,105,211,204,138,100,102,104, 96,202,148, 41,156,194,244, + 29,117, 8,192, 82, 20,192, 30,239,223, 94, 33, 80, 89, 85,213,252,222, 55,109, 30, 6,166,205,199,120,163, 99, 46, 63,250, 28, +122,238, 63,142,146, 69, 47,224, 87,127,127,184, 0, 56, 35,151, 83, 48,177, 44, 78,169, 84,146,158, 61, 59,227,234, 53, 32, 44, + 34, 20, 88,249, 26, 94,254,114, 11,230, 6,157,198,144,198, 98, 44,190, 37,198, 59, 27,151,225,253,244,207,113,230,236, 65,244, +234, 25, 70, 92, 92,204, 71,125, 13,237,121,119,113,197,163,113,163,240,104,220, 40,188, 69,127, 4,117,227, 82,156, 60, 9,156, + 60, 9, 28, 56, 16,143,127,175,185,136,184,184, 88, 18, 16,240, 16,130,130,190,225,196, 79,121, 15,191,134,146,131, 34, 43,125, +247,231,127, 13, 1, 32,147,201, 72, 82, 82,146,148, 25, 51, 52, 22, 1,134, 29, 18, 51, 30,111,235,124, 0,134,244,163,163,163, + 41,253, 48,128, 24,153, 27,239,239,245, 50,179,254,163,162,162,168,188,188, 60, 98, 45, 26, 98,109,217,161, 37, 66,231, 58, 28, +240,244,171,245,240,239, 38,192, 19, 9, 98,168, 26, 1, 15,119, 10, 2,170,201,235, 7,129,170, 1,168, 87, 19,212, 43, 9,234, + 85, 4, 52, 1, 4, 22,230, 92, 63,189,176, 30,131,134,148,194,175,255, 93,236,217, 85,129,187,119, 85, 8, 31, 83,131,193,222, +117,128, 83, 35, 84, 13, 52, 42,110, 16,212,215, 83,208,106, 41,120,251, 80, 0,117,223,231,178,133, 13, 29, 50,100,184, 87, 64, + 0, 14,233, 12,196,203, 19, 79,226,110,106,202, 48,153, 76, 54, 64, 46,151,159,227,112, 63,135,142, 24, 55,113,120, 23,255, 0, + 28, 63,218, 60, 71, 14, 93,165,255,135,171, 95, 44, 53,101,207,210, 86,216, 3,198,141, 27, 63,220,223,191, 39,206,157,184,220, + 92, 62,238,145, 41,248,159,124, 21,231,115,107, 3, 52,159, 59,243,252, 50,195, 0, 12,182,111,223,222,106,254,145,137,185, 0, + 76,163, 7, 3, 56,181,100,201,146,177, 34,145,200,237,235,175,191,198,186,117,235,240,204, 51,207, 96,197,138, 21,160, 40, 10, + 87,174, 92,129, 82,169, 68,106,106, 42,180, 90, 45,230,205,155, 71, 83, 20,101,245, 1,112,228,108,250,142, 62, 4, 96, 41, 10, +224, 8,239,223, 86,108,216,176, 1,127, 75,158,133,234,170, 70, 32,125, 45,234, 15, 28, 71,167,241,195,155, 63,175, 72, 95,139, + 34,103,103, 80,255,120, 30, 3,103, 63,138,195,235,119, 97,240,224, 17,102,237, 93,186, 84,136, 49,227, 98, 81, 88,228,133,181, +159,101, 97,252,248,177,120,231,211,101,120, 43,106, 14,190, 5,208,255,169,103,177,246,179, 44,136,197, 94,152, 58,109, 56,190, +230, 96,239,227, 15, 54, 97, 68,252, 32,188, 59,104, 21, 10,167,184,193, 43,225,199, 22,199,250,184, 74,112, 52, 95,129,128,191, +205,229, 92, 15, 7, 15,138,176,114,165,139, 21, 1,247, 23,138, 0, 24,143, 35,155, 35,248,166,227, 88, 35,179, 64, 63, 67, 93, + 79,252,151,144,245,201,101,232, 87, 1,180, 20, 5,108,134, 1, 28, 29,214,207,203,203, 35,134,222, 63, 19, 17, 48,252, 63, 41, + 41, 9, 76,178, 28,115,137, 33,184,144, 63,179, 10,192,156, 61,173, 14,168,111, 32,104, 84,235, 39,251, 53,170, 9, 68,206,247, + 62, 83, 53, 0, 74, 13,193,157,187, 4,127, 84, 18,156, 56,167, 5, 77, 3, 73, 73, 73,210, 75,151, 46,181,106, 27,173, 22, 40, +187,174,198,245,146, 74, 28, 60, 92, 9, 66, 40,156,251,141, 70,252, 19, 90,136, 69, 4,127,220, 2, 14,254, 4,212,212, 16, 16, + 26,120,120, 18, 5,137, 4,136,141,157,138,171, 87,175,178,186,166,236,245, 50, 50,109,174,237,171, 68, 4,110,157, 95,125, 97, + 69,134, 83, 14, 17,180, 96, 98, 31,103,103, 56,253, 99,161,211,149, 53, 31, 45, 3,240, 36, 91,123, 66, 23,183,101,243, 95, 95, +225,244, 83, 25,105, 97,175, 75, 39,103, 12,156,253,162,211,185, 77,159, 24,219, 51, 27, 1,144,184,116, 90,182,244,141,229, 78, +151,111, 86,183, 56,160,179,123, 39, 76,127,226, 25,167,156,255,126,197,233,220,218, 42,106,103,170, 44, 34, 34,130,156, 56,113, + 2,219,182,109,107,245,157,132,132, 4,147, 77, 1,160, 16,192,169,213,171, 87, 15,241,244,244,116, 99,194,224, 95,125,245, 21, +158,125,246, 89,172, 91,183,174,217,139, 95,189,122, 53,170,170,170, 80, 83, 83, 83,215,208,208, 80,218, 20, 65, 16, 91, 58,215, + 23, 94,120,129, 24,135,232, 25,239,159,109,248,255, 65, 25, 2, 48, 21, 5,112,180,247,207,216,100, 59, 4,112,110,204, 24, 80, + 47,204,134, 39, 0, 50,105, 24, 26, 78, 20,162, 62,125,237,189,122, 75,158,133,190, 79,205,130, 68,162,191,254,162,162, 98,139, +132, 93, 84, 84, 12, 0,136,141,211,139,136,130,227,103,240,237, 55,223,193,117,212, 72, 52,104,180, 80, 67,141, 9, 19,135,182, + 56,158,173,189,235, 58, 53,158,232,246, 34,232, 19,141, 72,250,215, 36,136, 31, 59,130, 1, 97, 3, 16, 54, 48,184,249,252, 82, + 23,175, 65, 80,144,144,245,125,243,200,255, 61, 18,117, 14,231,246,224,127,223, 80,214,166, 0,124,254, 57,218, 38, 17, 80, 71, + 68, 65, 65,129,213,217,228,121,121,121,145,172,151, 20, 58,119, 66, 86,239,253,128,182,128,160, 79, 39, 36,167,247, 65,102,126, + 60, 5,100,146,123,130, 32,218,230, 97, 0,227,165,128,230,150, 6,154,235, 44,101, 50, 89, 51,249, 27, 79, 0,100, 66,234, 76, +153,165, 8,128,161, 61, 71,117,230, 59,119,238,140,188, 81,190, 75, 65,119,165, 33, 16, 1, 78, 2,253,253,173,161, 9,180, 90, +160,182,150, 64,173, 1,180, 26,189, 40,152, 58, 77, 31,189,185,116,233,146, 89,123,141,183,119, 42,194,194,104, 28,216,167, 3, + 37, 0,254,184, 73, 65,226, 2,236,219, 13,168,149, 20, 40, 2, 12,142,112, 66,217, 53, 26, 19, 39, 78, 65, 92, 92, 28,197, 38, + 19, 86,246,122, 25, 89,249, 34,176,228, 83,219, 69, 0,161,117, 49,186, 46, 62,130, 93,244, 61, 22,234, 6,192,143, 2,148,195, +134,137, 46,107,117, 49,156,236, 17, 58, 6,238,222, 2,197, 77, 93,179,189,174, 18,192, 71, 66,193,117,208, 48, 81,209,119,116, +140, 57, 47,218,148,173, 78,238,158,130,171,183,170,154,136, 5,112,119,113,134,187,171, 24, 17,225, 67, 69, 91,190, 37, 49,237, +252,232,154,172,115,102,214,127,124,124,124,243, 61,202, 68,239,102,206,156,105,201, 3,173, 3,112,249,228,201,147,117,227,199, +143,239, 10,131, 53,253, 95,125,245, 85, 51,201,106, 52, 26,232,116, 58, 92,186,116, 9, 93,187,118,189, 77,211, 52, 43,181, 56, +109,218, 52,179, 67, 0, 92,136,246, 65, 24, 2, 48, 21, 5,112,164,247,207,133,248, 25,116,247,247,196, 23, 95,236, 69, 98,194, + 24,116, 27, 22, 6, 12, 11, 3,245,194,236,150,162, 23,192,173,155, 74,108,221,118, 24,221,253, 61,217,219,243,115,193,176,225, +125, 49,108,120,223, 86,199,113,181, 55, 97, 70, 40,210, 38,126, 2,186, 80, 79,254,207, 45,126,218, 38,123,198,120,213,253,213, + 61,239,215,190, 31, 93,142,242, 54,123, 32,237, 18, 0, 5, 5, 5,247, 61,107, 31,227,229, 50, 68, 23, 21, 21, 69,153, 32,127, +194,132, 21,147,146,146,108,250, 29,195, 85, 0, 76, 25, 87,207,223,120, 2, 96, 19,154,203, 82, 82, 82, 20, 73, 73, 73,172, 31, + 50, 67,242, 55, 53, 39,128,171, 61,107, 88,185, 89, 5,107,246,226,226,226,242,151,165,110,197, 35,163,157, 64, 3,208,168,105, + 56,139,245,213, 84, 91, 79,208,168, 33,208,234,128,130, 66, 29,116, 52,129,181, 37,123,113,113,113,249,111,188,182, 21, 19, 35, +133,152, 62, 71,136,186, 90,130,218,106,160,190,150, 66,159,190, 4, 58, 13, 5,145, 64,130,170,187, 52,202,126, 87, 99,209,203, +236, 38,140,101,175,151,145,143, 22, 2, 33, 1,192,154, 87,128, 5, 31,216, 38, 2, 72, 67,253,140,127, 12, 27,186,211, 47,103, +167,155,215,184,135,209, 13, 64, 55, 10,208, 29, 58,136,188,167,159,172,211, 52,212, 79,231, 98,143, 86, 53, 76,127, 33,106,248, +174,208,183,178,221,124, 7,143,133,143, 51,133,174, 18, 10,202,243,191, 96,235,107,115,235, 52,202, 6,214,246, 26, 85,202,233, +113,143,140,223,149,146,254,153,219,128, 33,195,224,238, 42,134,187,139, 51, 74,206,157,194, 27,169, 47,213, 41, 57,216,178,197, +147,103,115,185,166,200,127,249,242,229,173,194,252, 63,252,240,131, 34, 33, 33, 1,102,146, 4, 49, 68,175, 6,112,170, 95,191, +126, 37, 42,149,170,135, 80, 40,148,184,186,234,151, 98,109,222,188, 25, 51,103,206,132, 82,169,132, 74,165, 66, 99, 99, 35,220, +220,220, 84, 58,157, 46,135, 16,114,147,205,201, 58,106, 53,192,131, 50, 4, 96, 24, 5, 96,222,183, 7,241, 51,232,211,199, 15, +175,166, 37, 99,247,174, 95,145,189,229, 4,156,197,157,241,123,217,189, 17,172,158,254, 3,208,168,174, 65,196,176,254,248,240, +163,100,188,159,254, 57, 39,123,190,190, 30, 40, 58, 87,212,252,121,216,128, 48, 84, 84, 84,115,178, 55,101,225,116,204, 20, 60, +137,198,194, 58,140, 94, 48, 16,244, 96, 9,190,248,226,251,230,243,171,174,174,198,216,135, 67, 89,217, 51, 70, 84,102, 20,245, + 51,126,110, 83, 62,181, 89, 0,180, 5,249,179,177, 25, 21, 21, 69,101,101,101,145, 38,111, 23, 89, 89, 89,196,112, 89,162,177, +215,111, 74, 32,180,142,195, 82,128, 88, 0,184, 8, 1, 55, 17,208, 88,139,172,247,157, 0,151,163, 36,249,177, 62,128,139, 55, + 50,191,225,238,245, 91,154,237,207,144, 53,219, 53,236,198,228,111, 60, 39,128,171, 61,182,228,207,198,222,123, 25,107,169, 87, + 22,206, 35, 18, 9, 64,211,192,160,126,194,123,237,113, 86, 7,141,142, 64, 71, 11, 49, 99,198, 12, 86,226,228,237,119,215, 82, +139, 22,205, 35, 90, 45,160,214, 16,232,180,128,128, 2, 34,167, 0,181, 85, 20,126, 59,173,132, 82, 37, 64, 98,194, 12,214, 97, +255,229,207, 1,193, 61,245,255, 7,245, 0,108,141, 4,200,229,242, 35, 50,153, 44,246,230,212,184, 93, 1, 91,119,186, 5,140, +123, 24,154, 67, 7,241, 99, 66, 92,157,186,182, 54, 86, 46,151, 31,228,104,239,160, 76, 38,139, 61,255,230,180, 93,254,255,202, +113,235, 49, 98, 28,234,207, 31,194,198,127, 76,173,107,108,224,102,143,177,181, 58,237,239,187,222,249,248, 75,183,209, 99,198, +162,184,232, 20, 94, 74,126,178,174,161,174,142,243,185,181, 53,204, 37,251,145,201,100, 36, 62, 62,158,205,106, 0,161,167,167, +231, 41,165, 82,249,109,105,105,105,239, 33, 67,134, 4,106,181, 90,145,147,147, 19,114,114,114, 16, 29, 29, 13,149, 74,133,134, +134, 6, 92,186,116,169,198,203,203,107,175, 82,169,252,154,166,233,122,176,204, 0,200, 36, 5, 98, 66,236, 92, 66,255, 15,218, + 16,128, 97, 20,192, 17,237,107, 75,238, 0, 83,120, 52,118, 20, 30,141, 29,213,244,159,253, 26,182,165,189,105,246,137, 59,207, + 31,208,120,186, 14, 79,127, 54, 5,239,236, 93,102,247,185, 41,159, 81, 18, 47,173, 23, 84,223,168,238,139, 99,109,147, 0,104, + 15,207,223,216,251, 48, 12, 99,155, 11,245, 59,242, 28,185,140,253, 59,154,252, 13,196,142, 97, 34, 32, 70, 4, 41,154, 34, 29, +156,236, 89,155, 11,192,213,222, 7, 31,175,165,100, 50, 25, 17, 8,128,131, 5,250,177,126,102,194,159,126,220,127, 6, 39,123, +171, 86,173,165,230,205,111,202, 73, 33,208,219, 56,186, 31,168,175,163, 65,104, 32, 49,113, 10, 98, 98, 98,172,182, 71,246,122, + 25, 73,125, 18,240,116, 3,202,110, 3, 46,206, 0, 77,128, 78, 18, 32, 93, 6,164,201,109, 18, 1, 7,101, 50, 89,108, 65, 98, +220, 46,143,229,111,187,229, 47,127,163,174,209, 6,242, 55,182,151,191,100,234, 46,151,127,188,233,150,251,239,183, 56,147,191, +161,173, 23, 95,124, 49,238,141,127,190,176,115, 65, 74,170,219,103, 31,102, 48,228,127,218,196,179,175,229, 98,219,218,208, 17, +215,231,205, 20,249,207,155, 55,143, 48, 43, 1,182,109,219, 70, 40,138,178, 36, 4,220,212,106,117,157, 64, 32,200,243,247,247, +239, 89, 91, 91,251,226,241,227,199,187, 15, 29, 58,148,214,106,181, 13,213,213,213,183, 78,159, 62,125,165, 79,159, 62, 37, 93, +186,116, 41, 85, 42,149,155,181, 90,237, 45, 66, 8,107, 1,192, 36, 5, 50,136, 10,216,210,190,210, 54,236, 11, 29,110,219, 81, +227,254,246,218, 81, 41,133, 14, 61,222,209,246,170, 42, 5,200,208,202, 16,120,216, 15,179, 63,181, 46, 76,170, 42, 5,120, 40, +192,242, 49,247,147,252,205, 10, 0,107,107,253,185, 62,232,108,115, 7,112,177, 43,151,203, 41,115,155,237,112, 33,175,204,100, +185, 62,204,127, 17,192, 69,227, 79,171,155,254, 46,195,134,235, 85, 56,138, 92, 13,235, 69, 38,147, 17, 38,207, 64, 74, 74,138, + 77, 43, 28,140,237,109, 92,212,169, 89, 20,216, 35,154,140,219,132,153,240,103,107, 84, 98,237,231, 45,237,213,213,232, 59,224, +196,196, 68,110,247,223,183, 14,125,102, 52,134,164,189,111,249,155, 27, 26,107,107,159,182,215,187,102,236,253,244,217, 91, 27, + 84, 13,181,115,229,114,249, 33, 91,109,125,250,233,167, 7,100, 50, 89,236,103, 31,173,220, 80, 87, 87,103,238,220,180,184,255, +104,209,163, 26,147,127, 94, 94, 94, 36, 33, 4,219,183,111, 55, 60,198,146,189,107,106,181,218,153, 16, 82, 75,211,180, 92,173, + 86,255, 26, 16, 16,224, 83, 85, 85, 69,189,254,250,235, 53,213,213,213,119,122,244,232, 81, 91, 87, 87, 87,175, 86,171,107, 52, + 26, 77,163, 78,167, 83,114, 57, 97, 7, 13, 3,228,183, 97,157,230,227, 79,138,126,253, 6, 83,111,190,150, 73,102, 61, 30,141, +176,129,125,204, 30, 87, 84,120, 25,155,190,219,131,126,253, 6, 83,247,211,222,144, 33, 67,168,212, 69,114, 50,235,241,104,203, + 14,243,241, 82,108,250,110, 15,134, 12, 25, 98,245, 94,186,159,228,111, 82, 0, 56,218,179,111,203, 72, 65, 84, 84, 84, 62,171, + 16,191, 21, 56,114, 86,255,253,136,140,112,217,244,199, 17,209, 0,174,109, 98,184,172,203,222, 33, 9, 99,123, 92,201,223,158, + 25,255,108, 72, 27, 64, 80, 71,180,231,232,115,115,208,189, 77, 1, 0, 69, 81, 68, 32, 16,128,249, 99, 66,216, 83,166, 76, 65, +108,108, 44,104,154, 6, 77,211, 32,132, 88,251, 61, 74,171,213,186, 18, 66,116, 52, 77, 55,106, 52,154,253, 66,161,144, 18, 8, + 4,206, 0,156,105,154,134, 78,167, 19,106,181, 90,177, 86,171,237,174,211,233,206, 27,124,183,205, 55, 1,226,225, 24, 17,112, +165, 84, 69,118,239,220,130,107, 21, 53,240,243,106,104,254,236,102,165, 43, 2,124, 59,163,127,255,254, 86,201,186,173,236, 13, + 25, 50,132,186, 89,214, 72,214,124,180, 3,197,191,223,110,101, 47,184,167, 15, 2, 3, 3, 89,145,127, 91,193, 82,142, 20, 42, + 60, 60,156,223, 30,147, 7, 15, 30, 15, 42, 26, 12, 8,157, 54,112,108, 68, 6,229,229, 0, 60,160,159, 52,206, 19, 63, 15, 30, +230, 34, 0, 60,120,240,224,241, 0, 65,210, 36, 2,104, 3,226, 23,224,222, 16,135, 8, 64,247,166,247, 52, 95, 93, 60,120,240, + 2,128, 7, 15, 30,127, 14, 8, 0,184, 25,252,207, 16,191,216,128,244,233,166,227,120,239,159, 7, 15, 94, 0,240,224,193,227, + 47,210,167,241,164,207,131,135, 5,245,204,131, 7, 15, 30, 60,120,240,248, 43,171,229,249,243,231, 27,110,164, 67, 12,103,216, +203,100, 50, 98,180,209,206,181,168,168,168,230, 85,141,166, 82,177, 26,218,227,138, 63,163, 61,227,101,139,134,245,201,215, 31, +223, 30, 29,221, 94,122,122,122,243, 49,105,105,105,148, 13,246, 0, 51,233,128,249,251,217,186, 77,254,249,229,237,113,177,199, + 89, 0,112, 68, 87, 54, 7, 49,187,247, 57, 74,177, 24, 39, 35, 49,181, 27,160,169, 99,218, 67, 93, 49, 4,147,148,148, 36,101, +136,134,201, 0,102, 41, 39,248,253,196,246,237,219, 35,183,109,219,214, 76,130, 83,166, 76,145, 38, 38, 38,230,255, 25,213,174, +169,246, 56,127, 94,191, 50, 44, 52, 52,180, 93,207, 77, 38,147,145,169,211,100,200,201,150,155,188,103,119,238, 58, 65,114,178, +229, 22,239,229,157,187, 78, 88,236, 4,226, 98, 35,108,190,233,210,211,211, 73, 66, 66, 80,139,255,173,137, 0,107,168,173,171, +141,220,250,211, 86, 4,134, 5, 42, 64, 1,231, 79,158,147,142, 9, 31,139,208,126,161,156,238,191, 67,135, 14,181,186,238,177, + 99,199, 82,224,193,131, 71,155, 9, 0, 49,219, 3, 71,143, 30,205,217,184,169,205, 98, 24,152, 34, 81,227,141, 54,216, 18,173, + 45, 27,227,176, 17, 20,140,221,212,212, 84,100,100,100, 40,204,237, 45,206, 28,103,105,173,166,241, 57,246,232,211, 11, 0,112, + 75,165,130, 86,217,168, 47,172,170, 1,160,223,251,128, 75,110, 4, 67,242, 7,244,185,197,185,172,181,151,201,100, 68, 64,233, +179,235, 49,175,128,136, 87,212,158, 0, 0, 14,255, 73, 68, 65, 84,229,247,159,175,189,255,130,204,184, 61, 24,226,183,181, 61, + 28, 41, 42, 25,242,143,139,141, 80, 1, 50, 73, 78,182,220,230,223, 96, 4,132,105, 1, 32,183,235, 60,213,234, 84,228,230, 38, + 35, 38, 38, 19, 9, 9, 25,205, 17, 1, 91,132,192,193,162,131,228,161,161,189,240,161,124, 21,188, 92,189, 64,107,117, 80,145, + 70,197,238, 95,127,138,217,187,239,103, 50, 54,112,156, 84, 34,145, 88, 21, 2,135, 14, 29, 34, 77,145,133, 86, 30, 17, 47, 2, +120,252,149,113,234,212,169, 22,255,155,234,211,236, 17, 0,156,230, 15,152,218,197,206, 17, 32, 64,164,221, 54, 8,123, 13,192, +198,115,151,201,100, 36, 53, 53, 21, 43, 86,172, 0,128,230, 87, 83,199, 89,219, 33,172, 21, 60, 59,227, 76,233,119,112, 65, 79, +232,240, 11, 42,254,115, 2,167, 75,238, 96,198,138,117,237,118,163,157, 57, 91,136,193,131, 6,130, 38, 64, 97,161,254, 61,112, +239,189, 97, 57,205,178,170, 13,115,176, 91, 66,102,102, 38,197,182, 61,230,206,157, 11, 0,205,175, 38,201,159,162, 0, 11,247, +131, 76, 38, 35,143, 60,178, 11, 50, 89,172, 67, 69, 64, 92,108, 68, 67,114,114,178, 43,144,137,156,108,110,196,110,232,225,219, + 75,242,230,188,127, 0,152, 57,115, 51,114,115,245,175,201,201, 37, 96, 34, 2, 92,162, 1,132,144, 72,197,133,189,138, 23,255, + 49, 31,195,187, 14,133,139,135, 7,136, 90, 11,154,232, 32, 20,137, 17, 28, 21,156,251,219,176, 11, 88,145,153,161, 24,229, 51, + 90,234,234,234,106, 85, 4,220,190,125,187,197,255, 83,198,119,194,168,133,191,224,241, 12, 85,139,134,156, 52,105,146,205,237, +149,157,157, 77,166, 77,155,230,176,246,118,180,189, 54, 38,146, 72,123,211,250,158, 58,117, 42,178,137,132,108,181, 51,248,149, + 87, 94, 41,175,175,175, 15, 0, 48, 25,250, 77, 56, 67, 1,156,130,126, 83, 40, 0,216, 40,151,203,127,227,169,191, 53,249, 51, +101,198, 34,160,133, 0, 40, 45, 45, 37,165,165,165, 0,128,192,192, 64, 24,110, 54, 3,160,197,255,166, 62, 55,135,138,138, 10, + 69, 86, 86, 22,235, 72,128,241, 94,247,150, 72,152,106, 74,133,105, 76,162, 92, 67,236,153,153,153, 86,143,201,203,203, 99, 69, +254, 73, 73, 73,102, 73,127,233,210,165,200,200,200,128,161, 64, 96,131, 30,125,122,225, 70,101, 53,126,156, 55, 19, 93,168,113, + 40,249, 98, 17, 2,167, 7, 98, 79, 59,147, 63,128,102,194, 7,128,129, 3, 7,182, 40,103, 34, 3,134,229,142,246,236, 45, 17, + 49,211, 30,230, 72,127,253,250,245,200,200,200, 64,236,184,161,216,245,203, 73,192,189, 19, 80, 83,119,223,235,112,231,174, 19, +174, 64, 38,118,238, 58,225, 16,123,211,106,150, 89,124, 54,179, 59,191,199,234, 1, 49, 12,253, 39, 39,231, 34, 33, 33,168,249, +149, 65, 66, 66, 16,107, 17,240,197,255,190,192,251,159,190,139,241,125, 35,161,107,108,132, 86,167, 5, 37,162, 0, 8, 65, 64, +227,214, 31,101, 8,237,218, 31,203,230, 45,195,187, 43,223, 85, 60, 50,208,122, 52,203,184,179,155,226,191,222, 36,225,239,221, +187,151,216, 34, 2,178,179,179,201,206,215,119, 33,238, 29, 56,132,180,179,179,179,201,202,149, 43,177,100,201,146, 14, 45, 2, + 78,157, 58, 21, 89, 93, 93,173, 40, 43, 43, 67,120,120,184, 93,231, 89, 93, 93,173,184,215,101,219,244,156,151, 2,152, 11,224, + 36,128,175, 1, 68, 3,120, 20,192,223, 13, 4,192,237, 63, 41,159, 83,176,176, 13,184, 69, 71, 42, 85,207, 49,153, 25, 75, 77, +126,222, 66, 0, 4, 6, 6, 82,129,129,129,205,100,111, 24, 74,206,202,202,106,241,191,241,231,151, 46, 93, 50,123,130,140,168, + 72, 73, 73, 81,164,166,166,194,120,163, 28,227,205,115,178,178,178,204,134, 96, 77,117,246,198,101,237,185, 81, 17, 0,108,218, +180,201, 44,241, 3,104, 65,254, 75,151, 46,101,101,243,247,210,107,168,223,242, 6,220,158,253, 24, 61,250,244, 66,183, 46, 46, + 40,221, 82,170, 39,127,207,206,250, 33, 0, 39, 33,231,115, 77, 72, 72,144, 26, 14, 3, 36, 36, 36,112,142,210,208, 4, 8,232, + 4,252,251, 73,224,249,245, 64, 87, 87,224,124,149,233,242,162, 74,142,119,190, 25, 33,199, 37,106,243,246,219,111,155, 37,126, + 0, 88, 57, 55, 30,107,118, 31,129, 95, 96,119,220,188,122,203,170,247, 15, 0,108,162, 0, 92,194,248,122, 15, 95,102,210,211, +103,198,246,185,222,215, 43,255,107,190,142, 66,230,193,134,123, 37,168,197,171, 58, 33, 24,226,109,197,172,191,223,160,108,192, +184,217, 99, 21,163,187,143, 66, 99,125, 61, 68,206,206, 16,137,238,117, 65,165,197,197,216,154,147,115,227,217,103,230,246,232, +237, 28,128,161, 19,195,163,126,205,253, 53,114,212,240, 81,156,188,198,244,157,115,177,111,223, 62, 60,246, 88,203,242, 73,147, + 38, 81, 92, 69, 0, 67,254,232,253, 33,118,190,254,178,221, 34, 32, 59, 59,155,124,244,209, 71, 8, 9, 9,193,154, 53,107,176, + 96,193,130, 14, 39, 2, 12,137,223, 81,246, 24, 91,118, 68, 19,164, 0, 38, 2, 88, 79, 8,169,163, 40,202, 15,192, 5, 0, 87, +229,114,185, 22,127,110, 16,142,245,221,130,252,153,247,153, 25, 75, 91, 69, 1,238, 75, 30,128,172,172, 44,102,236, 21,165,165, +165,240,245,245,109, 37, 16,152,178,138,138, 10, 86,121,238,173, 77, 6,228,210, 97,206,154, 53,171,237,164,155, 1,129,153,242, +250, 51, 50, 50, 32,151,203, 41,107,179, 56,149,184,134,186,233,163, 64,220, 23, 1, 81,175,163, 14,255, 3,254,163,247, 22, 73, +214, 34, 56,253,109, 13,180, 90,238,137,206,226,227,227,243, 89,108,187,106, 57,194,243, 21,240,214, 90,160, 87, 79,224,214,118, + 49, 54,124,169,198,220,239,204,151,115,186,243,137, 99, 51, 85, 27, 78,246, 43,207, 94, 1,247, 48, 9,220,250,254, 19,155, 86, + 60,143, 33, 3,253,208, 47,254, 93, 86,237,193,230,254,100, 59, 84,192,220,187,134,228, 47,151,203, 41,102,226,159, 77, 68,211, +249, 61,202, 22,146, 55, 5,117, 66,176,201,242, 92,163, 72,128, 53,148, 87,148, 99,114,210,100,184,119,246,130,142,210,226,192, +190,253,168,173,171, 67, 66, 98, 34,254,168,168,192, 15,155,127,196,115,207,204,237,225, 44,113,134,128, 56, 33, 38, 34, 38,239, +130, 98,141, 77, 94, 99,101,101,165,221,215,109, 72,254, 0,236, 22, 1,217,217,217,100,249,242,229, 8, 14,214,215,103, 80, 80, + 16, 58, 82, 36,192,209,196,111,194,251,103,222,219,114,173, 3,154,136,208,137,162, 40, 87, 0, 97, 0,206, 1,232, 33,147,201, +106, 0, 84,201,229,114, 62,173, 61, 71,220,183, 68, 64,190,190,190,210,164,164,164, 86, 67, 1, 71,142, 28, 81, 52,109,246,194, +121,142,128,185,201,128,150, 60, 71,115, 2,165, 45,192,120,247,230,194,253,108,189,127, 0,216,253,234,114, 36,188,255, 1,180, + 81,227, 32, 2,224,118,184, 24,123, 74,238, 0, 0,180, 81, 11,160, 57,235, 3,170,235,223, 57,147, 20,219, 40,139, 37,220,153, +246, 63, 44,120,230, 58, 46,206, 91,130,250,159,213,240,243,177, 92,238,136, 8,128, 45,226, 96,253,250,245,122, 53,156, 48, 1, + 71,202, 42,224, 62,196, 29, 55,114, 75, 0,137, 51,102, 46,248, 27,188,123,198,183,219,131,104,110,214,191,163,162, 90,150, 86, + 8, 88, 91, 29,144,155,156,139,152,204, 24,204,220, 12, 36,231,234,223,231, 38,231,114,142, 2,212,169,106,225,227,210, 5, 90, + 85, 3,136,128, 96,196,200,145,216,178,101,139,234,163, 15, 62,144,208,132, 96,206,147,115,224,221,197, 27, 13,117,117,208,234, +180,112,119,234, 12,141, 64, 99,211,245, 86, 85, 85,181, 88, 29,192,117, 66, 96, 43,242,103, 96,163, 8,200,206,206, 38,169,169, +169, 24, 57,114,100,139,242,129, 3, 7, 34, 61, 61, 29,105,105,105,237, 38, 2,218,138,248,141,189,127, 0, 40, 43, 43,179, 53, + 10,240, 43,244,227,253, 53,208,135,254, 39, 3,184, 4, 96, 48,128, 28, 0,235,208,180, 83,167,165,238, 4, 54,134,210,255, 18, + 2,192,152, 16,152, 61,231,217,124,110,105,214, 52, 3,102,120,129,153, 16,200,204, 13, 96,162, 3,129,129,129, 10,102,184,160, +189, 58, 94, 71,194,218, 88, 63,227,253,179,177, 53, 99,237,102,144,196, 62,184, 53, 38, 2, 93, 48, 14, 46, 51,215, 64, 91,254, + 7,224,217, 25,162, 59,255,195,246,143, 10, 0,161,144,243,181,219,178, 10,194, 24,167, 95,249, 63, 12, 15, 7, 2, 23, 20, 34, +204,237, 25, 92,120, 40, 9,248,247, 18,179,229,237, 21, 1,200,200,200,192,248, 17,253, 16, 53, 46, 4, 9,131,150, 96,245, 71, +159,227, 92,193, 13,204,155, 52, 28, 55,115,118,162,186,178,198, 33,247,131,169,161, 2,107,207,135, 37,111,223, 81,247,168, 57, +251,150, 38, 14,166,165,165, 81,233,233,233,100,230,230,150,130, 0, 0, 98, 50, 99, 32,222, 86,140,109,219, 74,154, 87, 2, 48, + 19, 6,189,189,189, 77,246,191, 52, 77, 67, 71, 3,132,214,194,217, 69,130, 39,159,122, 74,242,214,155,111,162, 91,183,110,116, + 15, 63, 63,129,170,190, 14, 58, 2, 16, 90, 7,154,182, 30,209, 26, 59,118, 44,245,195, 15, 63,144, 59,119,238,160,166,166,166, +133,112, 52, 92, 29,192,101, 85, 64,118,118, 54, 89,253,124, 17, 32, 9, 6,110,126,218,250, 0, 73, 48, 86, 63, 95,132,148,255, +176, 19, 1,217,217,217,100,234,212,169,210,129, 3, 7, 42,238,220,185,211,234,243,128,128, 0, 76,157, 58, 85,250, 32, 77, 12, +180,197,251,183, 39, 10, 32,151,203,243, 13,158,175,238, 0, 78, 3,152, 46,151,203,185,108,101,202,147,191, 37, 1, 96,148,232, +199, 90, 34,160, 22,159, 91, 10,153, 38, 37, 37,153,140, 2, 48,100,239,235,235, 43, 77, 77, 77, 85, 48, 99,178, 73, 73, 73, 22, +151, 1, 90,242, 14,185, 78,254,107,171,101,128,140,119,111,105, 50, 32, 23,148,252, 43, 25, 78, 51,215, 64, 89,118, 17,162,195, +107,160,217,188, 0, 84,220, 42,108,253,251, 99,184,186,245, 50, 18, 86,126, 13,136,218, 39,179,243,146, 44, 32,119,229, 22,132, + 93,141, 1,110,215, 99,113,244, 18,139,229,142,136, 0,216,234,253,231,108, 89, 14, 97,143, 1,112, 67, 8,174,237,203, 68, 45, + 69,112,244,226,117, 68, 21,222, 96,217,238,215,154,255,159, 53, 75,222,130,236, 1,224,231,159, 99, 77, 30,103,233,249,176, 22, +234,119,196,178, 67, 71,172, 16, 72,206,189, 71,252, 0, 90,121,254,204,132,193,109,219, 74, 76,126,223,221,197, 29,101,213,101, + 24,217,123, 20,148,141, 42, 64,169,130, 86,173,193,178,212, 84, 80, 2, 8, 26,234,235, 64,211, 58,104,117, 4,206, 34, 39,252, + 81,247, 7,156,116,214, 87, 27, 63,246,216, 99,205,117,115,232,208, 33,194,244, 55,134,171, 3,202,203,203, 89, 95,231,180,105, +211,168,148,255,128,172,126,190, 8,161,125, 90,255,254,249,203,106,164,252, 39, 12,108,201,122,218,180,105, 84,118,118, 54, 25, + 57,114, 36, 2, 2, 2, 90,125, 94, 88, 88,136,156,156, 28, 69,123,145,127,147, 55, 78,181,229,216,191, 33,236,136, 2, 48,152, + 12,253,228,239, 70,158,194, 29, 40, 0,218, 10,140,231, 15, 0,163, 71,143,150,102,101,101, 41,152,208,191, 25,113, 32,189,116, +233,146,130, 43, 9,219,218, 73, 58,122, 25,160,161,247,111,138,248, 25,161,195,229,124, 79,151,220,129,230,236, 91,184,133, 95, +224, 23,183, 10,168,174, 65, 73,230, 34, 4,205,255, 16, 55,215, 45, 2,156, 68,128,160,125, 50, 59, 95,171, 7, 66,125,167,179, + 46,111,143, 8, 64, 70, 70, 70,221,236,168, 81,229, 30,180, 87,175, 6, 56, 73, 54,127,184, 0,159,109, 63,133,197,143, 62,140, +185, 31,252, 23,143,189,247, 77,187, 76, 30,101, 4,104, 83, 30, 0,202, 94,113,106, 79,168,223, 82, 20, 32,185,201,179, 55, 38, +127, 67,239,223, 26,252,125,253,177,251, 64, 46,198,246, 26, 11,215, 78,110,160,105, 2, 1,209,130,166, 40, 16, 66,160, 35,128, +150, 38,208,106,181, 80, 86,215, 99,199,177, 29, 16,235,196,156, 39,165, 26,175, 10, 72, 91, 48, 14, 83,252, 75,145,121,140,189, + 13,115, 34,128, 43,249, 27,218, 75, 75, 75, 35, 43, 87,174, 68,247,238,221,239, 9,251,146, 18,100,100,100,160, 35,120,254,142, + 22, 2,166,188,127,123,162, 0, 77,207, 68, 36,128,135, 0,188,246, 23,152,252, 7, 0, 66, 0,186, 7, 90, 0, 24,207,250, 79, + 74, 74,106, 30,119, 55, 20, 7,134,239,237,241,224,109,233,200, 29,181, 12,208,156,247,111, 43,241, 51,152,177, 98, 29,126, 4, +240,232,251, 83, 64,178, 22,129,154,181, 26,167, 75,238,128,242,246, 66,241,239, 53,122,239, 95, 40,108,151, 59,212,220,122,127, +123,242, 0,176, 17, 92,108,197,193,250,245,235,213, 0,106,159,143, 28, 92,243,207, 85, 31,171, 95, 93,150,170,234,218,217,247, + 78,209,185,107,221,230,158,251,175, 91,123,175, 26, 49, 71,206,134, 67, 52,220, 87, 20,152,250, 13,251, 34, 0,166,200,159,241, +252, 1, 88,157, 16, 40,145, 72,168,115, 91,207, 39, 42,198,229,231, 36, 13,122, 12, 53,170, 26, 80, 2, 64,159, 82,132,134, 78, + 71, 64,107,181,232,228,236,142, 67,213, 39,113,233,112, 49,162, 35,162,243,237,174,220,146, 23, 0,112, 95, 6,216, 66, 4,116, +191,134,243,229, 1, 54,145,191,161,189, 37, 75,150,144, 53,107,214,192,211,211, 19,119,238,220,193,242,229,203,209,209,194,254, +142, 16, 2,230,188,127, 91,162, 0, 50,153,172, 27, 0,191,166, 27,101, 40,128, 20, 0, 37,127, 17, 39, 93,215,150,198,239, 75, + 30, 0,115, 17,129,213,171, 87, 75,141,133, 66, 82, 82,146,130,171, 61, 67, 34,232, 8, 41,118, 13,189,127,227,229,127,165,165, +165, 45,234,141, 75,214, 62, 70, 4, 76,127,255, 43,144,205,128,207, 92, 57,242,255,249, 24, 30,206,216, 8, 56, 57,161,147, 68, +220, 46,215,107,184,198,223,212,123, 27,243, 0,104, 1, 8,154,218, 86, 96,103,123,220,154, 29, 53,170,236,159,153,219,250, 44, +123,110,114,103,127,191, 72, 53,128, 51, 73, 73, 73, 30, 0,220,108,109,143,123, 36, 29, 75, 30,121,100,151, 65,248,159,219,247, + 45,121,240,134,233,129,217, 10,137,182, 72, 6,100, 14,198,164,207, 68, 4,204, 13,121, 60, 61,235,233,173,219,254,187, 13,186, +217,218, 51, 19,123, 77, 28,220,197,189, 11, 84, 26, 21, 8, 33, 16,139,196,168, 82, 54,224,200,239, 63, 99,253,183, 27, 32, 29, + 32,117, 72,226,176,244,157,115,177, 97,195, 6, 44, 90,196, 61, 7,192, 61, 17, 0,187,200,223,208,222,130, 5, 11,152, 60, 0, +232,200, 99,254,134, 66,192,150,239,218,155, 59,192,240, 49,128,126,189,191, 10,192, 43, 0,142,201,229,114, 29,120,152,171,123, +156, 58,117, 10,153, 25, 75, 91,229, 1,176,152, 8,168,173,242, 0,152,138, 8,152, 35,122, 91,162, 0,246,162,173,150, 1, 50, + 98, 68, 46,151, 35, 47, 47,143, 46, 45, 45, 53, 36, 50,105, 84, 84, 20,103,239,102,198,138,117,128, 65,226,159,137,203,214, 54, +191,175,111,135,155,173,173,188,103,138,162, 62, 2,112, 23,250,229, 63, 79,218,105,238,230,243,145,131, 27,163,243,126,237, 60, +231,205,175, 33,151,203,197,121,121,121,221,209, 50,157,181, 77,237,209,214,145, 0,107,249,253,173,161, 45,134, 4,204,145,191, + 58, 33, 24,216,102,221, 49,147, 14,158, 68,237,251,225, 0, 57, 28,112, 4,227, 70,141, 67, 15,247, 30, 0, 77,240,135,234, 14, + 14,157, 56,132,155, 69, 55, 49, 41,116,146,212,217,217,185,221,219,195, 80, 4, 56,138,172,153, 72,192,131, 50,225,207,222, 44, +128, 14,232, 99, 50, 1,100,130, 7,103,152, 75, 0,100, 82, 0,180, 21, 82, 82, 82, 76,146,189,225, 78,108, 70, 80,176, 89, 85, +224, 40,175,191, 45,150, 1, 54,205,240,215,230,229,229,137,154,134, 14, 24,242,159, 20, 21, 21,197, 41,202,209,180,153,146,194, +209,231,104,110,140,217,209,185,238, 57,194, 25,128, 72, 46,151,191,110, 16, 2,123,202, 94,155,209,175,125, 81, 32,151,203, 39, +228,229,229, 33, 47, 47, 79, 5, 64,210,244,103, 55,241, 51, 81, 0, 91,235,204, 26,201, 79,157, 38,107,113, 28, 87,226,118,196, +144, 64, 90, 90, 26,149,158,156, 78,252, 23,248, 75,209,219,244, 49,101,201,185, 10,182,243, 1, 70,134,141,164, 26, 26, 26, 34, +215,189,191, 14, 1,193, 15, 41, 0,224, 66,225,111,210,248,232, 4,132,134,135,218,220, 30, 99,199,142,165, 54,111,222,220,106, + 85,128, 70,163,177,235, 6,114, 52, 89,255,217,102,251,119, 0,240, 75,252, 76, 68, 1,140,203, 88, 11, 0,107,158, 56, 91, 79, +221,214, 78,145,109, 34, 22,123,137,202,209, 68,199,216,203,203,203, 35,121,121,121, 34,195,250, 10, 12, 12,180,233,183,154, 8, +202,225, 29, 70, 71, 24,251, 54, 1,119, 0,117,250,132,252, 20, 5,192, 5,214,215,247,178,105,143, 43,121,121,121,204,186,178, +154,192,192,192,174,129,129,129,206, 29,161, 46,237,245,196,173,217,118,212,144,128, 85,114, 79,227,118,143,186,186,186,230,207, +154, 58,155,233,188, 49, 58,108,180, 67,206,115,230,204,153, 60,185,254,249,201,222,144,195, 52, 14, 38,127, 9,244,195, 13, 15, +188, 8,176, 90,145,225,225,225,188,106,226,193,131, 7, 15, 30, 60,254, 98, 16,240, 85,192,131, 7, 15, 30, 60,120,240, 2,128, + 7, 15, 30, 60,120,240,224,241, 23,192,255, 3,211,238,250, 72,118, 88, 93,170, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, 0}; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 5aec47965fc..5d2593b46bb 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1619,18 +1619,6 @@ static void build_uvlayer_menu_vars(CustomData *data, char **menu_string, } } -void set_wave_uvlayer(void *arg1, void *arg2) -{ - WaveModifierData *wmd=arg1; - CustomDataLayer *layer = arg2; - - /*check we have UV layers*/ - if (wmd->uvlayer_tmp < 1) return; - layer = layer + (wmd->uvlayer_tmp-1); - - strcpy(wmd->uvlayer_name, layer->name); -} - void set_displace_uvlayer(void *arg1, void *arg2) { DisplaceModifierData *dmd=arg1; @@ -1908,8 +1896,6 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco y -= 18; if (!isVirtual && (md->type!=eModifierType_Collision)) { - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */ - uiBlockBeginAlign(block); if (md->type==eModifierType_ParticleSystem) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object"); @@ -1925,8 +1911,6 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_copyModifier, ob, md); } uiBlockEndAlign(block); - - uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); } lx = x + 10; @@ -2262,7 +2246,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco 0.0, 1.0, 0, 0, "Set the UV layer to use"); MEM_freeN(strtmp); i = CustomData_get_layer_index(fdata, CD_MTFACE); - uiButSetFunc(but, set_wave_uvlayer, wmd, + uiButSetFunc(but, set_displace_uvlayer, wmd, &fdata->layers[i]); } if(wmd->texmapping == MOD_DISP_MAP_OBJECT) { @@ -2629,7 +2613,7 @@ static void editing_panel_modifiers(Object *ob) block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return; - uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE); + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); uiNewPanelHeight(block, 204); uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier"); @@ -6366,11 +6350,6 @@ static void editing_panel_mesh_uvautocalculation(void) row= 180; uiDefButBitS(block, TOGN, UVCALC_NO_ASPECT_CORRECT, B_NOP, "Image Aspect",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Scale the UV Unwrapping to correct for the current images aspect ratio"); - - row-= butHB+butS; - uiDefButBitS(block, TOG, UVCALC_TRANSFORM_CORRECT, B_NOP, "Transform Correction",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Correct for UV distortion while transforming, (only works with edge slide now)"); - - row= 180; uiBlockBeginAlign(block); uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Cube Size:",315,row,200,butH, &G.scene->toolsettings->uvcalc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size for cube mapping"); diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index d75eaeb2fbb..2dd6d705a9e 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1054,10 +1054,10 @@ static void draw_default_sensor_header(bSensor *sens, (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, &sens->invert, 0.0, 0.0, 0, 0, "Invert the level (output) of this sensor"); - uiDefButS(block, TOG, 1, "Level", - (short)(x + 10 + 0.65 * (w-20)), (short)(y - 19), (short)(0.20 * (w-20)), 19, + uiDefButS(block, TOG, 1, "Lvl", + (short)(x + 10 + 0.70 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, &sens->level, 0.0, 0.0, 0, 0, - "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); + "Level detector versus edge detector (only applicable in case of logic state transition)"); } static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) @@ -1270,15 +1270,15 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short if(ps->type == SENS_PROP_INTERVAL) { uiDefBut(block, TEX, 1, "Min: ", xco,yco-92,width/2, 19, - ps->value, 0, 31, 0, 0, "check for min value"); + ps->value, 0, 31, 0, 0, "test for min value"); uiDefBut(block, TEX, 1, "Max: ", xco+width/2,yco-92,width/2, 19, - ps->maxvalue, 0, 31, 0, 0, "check for max value"); + ps->maxvalue, 0, 31, 0, 0, "test for max value"); } else if(ps->type == SENS_PROP_CHANGED); else { uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-92,width-60, 19, - ps->value, 0, 31, 0, 0, "check for value"); + ps->value, 0, 31, 0, 0, "test for value"); } yco-= ysize; @@ -1390,14 +1390,9 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short &raySens->propname, 0, 31, 0, 0, "Only look for Objects with this property"); } - - /* X-Ray option */ - uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X", - xco + 10,yco - 68, 0.10 * (width-20), 19, - &raySens->mode, 0.0, 0.0, 0, 0, - "Toggle X-Ray option (see through objects that don't have the property)"); + /* 2. sensing range */ - uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19, + uiDefButF(block, NUM, 1, "Range", xco+10, yco-68, 0.6 * (width-20), 19, &raySens->range, 0.01, 10000.0, 100, 0, "Sense objects no farther than this distance"); @@ -1444,13 +1439,10 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short draw_default_sensor_header(sens, block, xco, yco, width); joy= sens->data; - - uiDefButS(block, NUM, 1, "Index:", xco+10, yco-44, 0.6 * (width-120), 19, - &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, - "Specify which joystick to use"); + str= "Type %t|Button %x0|Axis %x1|Hat%x2"; - uiDefButS(block, MENU, B_REDR, str, xco+87, yco-44, 0.6 * (width-150), 19, + uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, 0.6 * (width-20), 19, &joy->type, 0, 31, 0, 0, "The type of event this joystick sensor is triggered on."); @@ -1865,7 +1857,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, &ia->flag, 0, 0, 0, 0, - "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); + "Convert Ipo to force. Force is applied in global or local coordinate according to Local flag"); uiButSetFunc(but, change_ipo_actuator, but, ia); but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, @@ -1891,12 +1883,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh else { uiDefButI(block, NUM, 0, "Sta", xco+10, yco-44, (width-80)/2, 19, - &ia->sta, 1.0, MAXFRAMEF, 0, 0, - "Start frame"); + &ia->sta, 0.0, MAXFRAMEF, 0, 0, + "Start frame, (subtract 1 to match blenders frame numbers)"); uiDefButI(block, NUM, 0, "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, - &ia->end, 1.0, MAXFRAMEF, 0, 0, - "End frame"); + &ia->end, 0.0, MAXFRAMEF, 0, 0, + "End frame, (subtract 1 to match blenders frame numbers)"); } uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, "Child", xco+10+(width-80), yco-44, 60, 19, @@ -1925,7 +1917,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property"); } else { - uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value, use \"\" around strings"); + uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value"); } yco-= ysize; @@ -2030,7 +2022,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh if(eoa->type==ACT_EDOB_ADD_OBJECT) { int wval; /* just a temp width */ - ysize = 92; + ysize = 72; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); @@ -2050,27 +2042,9 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, eoa->linVelocity+2, -100.0, 100.0, 10, 0, "Velocity upon creation, z component."); - uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19, + uiDefButBitS(block, TOG, 2, 0, "L", xco+45+3*wval, yco-68, 15, 19, &eoa->localflag, 0.0, 0.0, 0, 0, "Apply the transformation locally"); - - - uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19, - NULL, 0, 0, 0, 0, - "Angular velocity upon creation."); - uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19, - eoa->angVelocity, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, x component."); - uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19, - eoa->angVelocity+1, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, y component."); - uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19, - eoa->angVelocity+2, -10000.0, 10000.0, 10, 0, - "Angular velocity upon creation, z component."); - uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19, - &eoa->localflag, 0.0, 0.0, 0, 0, - "Apply the rotation locally"); - } else if(eoa->type==ACT_EDOB_END_OBJECT) { @@ -2296,7 +2270,13 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file"); uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation"); } -*/ else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) +*/ else if (gma->type == ACT_GAME_RESTART) + { + ysize = 28; + glRects(xco, yco-ysize, xco+width, yco); + uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); + } + else if (gma->type == ACT_GAME_QUIT) { ysize = 28; glRects(xco, yco-ysize, xco+width, yco); @@ -2304,7 +2284,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh } //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3"; - str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save GameLogic.globalDict %x4|Load GameLogic.globalDict %x5"; + str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); yco -= ysize; @@ -2344,7 +2324,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh visAct = act->data; - str= "Visibility %t|Visible %x0|Invisible %x1|Visible Recursive %x2|Invisible Recursive %x3"; + str= "Visibility %t|Visible %x0|Invisible %x1"; uiDefButI(block, MENU, B_REDR, str, xco + 10, yco - 24, width - 20, 19, &visAct->flag, @@ -2836,158 +2816,134 @@ void buttons_enji(uiBlock *block, Object *ob) void buttons_ketsji(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", - 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that have a physics representation"); - if (ob->gameflag & OB_PHYSICS) { + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are evaluated by the engine "); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); + + uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,185,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use Fh settings in Materials"); + uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,185,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use face normal to rotate Object"); + uiDefButF(block, NUM, B_DIFF, "Mass:", 110, 185, 80, 19, + &ob->mass, 0.01, 10000.0, 10, 0, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 190, 185, 80, 19, + &ob->inertia, 0.01, 10.0, 10, 0, + "Bounding sphere radius"); + uiDefButF(block, NUM, B_DIFF, "Form:", 270, 185, 80, 19, + &ob->formfactor, 0.01, 100.0, 10, 0, + "Form factor"); + + uiDefButF(block, NUM, B_DIFF, "Damp:", 10, 165, 100, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUM, B_DIFF, "RotDamp:", 110, 165, 120, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", + 230, 165, 120, 19, + &ob->gameflag, 0.0, 1.0, 10, 0, + "Enable anisotropic friction"); + } + + if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { + uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 145, 114, 19, + &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the x-direction."); + uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 145, 113, 19, + &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the y-direction."); + uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 145, 113, 19, + &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the z-direction."); + } + } + + if (!(ob->gameflag & OB_GHOST)) { uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - - uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, - &ob->mass, 0.01, 10000.0, 10, 2, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, - &ob->inertia, 0.01, 10.0, 10, 2, - "Bounding sphere radius"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); - - uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); - - uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,145,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use Fh settings in Materials"); - uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,145,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use face normal to rotate Object"); - uiDefButF(block, NUM, B_DIFF, "Form:", 110, 145, 120, 19, - &ob->formfactor, 0.01, 100.0, 10, 0, - "Form factor"); - - uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", - 230, 145, 120, 19, - &ob->gameflag, 0.0, 1.0, 10, 0, - "Enable anisotropic friction"); - } - - if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { - uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 125, 114, 19, - &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the x-direction."); - uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 125, 113, 19, - &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the y-direction."); - uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 125, 113, 19, - &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the z-direction."); - } - } - - if (!(ob->gameflag & OB_GHOST)) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 105, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static TriangleMesh %x4", - 85, 105, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,105,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); - } - uiBlockEndAlign(block); + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + if (ob->gameflag & OB_BOUNDS) { + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", + 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); } + uiBlockEndAlign(block); } } void buttons_bullet(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", - 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that have a physics representation"); - if (ob->gameflag & OB_PHYSICS) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are detected by the Near and Radar sensor"); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are evaluated by the engine "); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, - &ob->mass, 0.01, 10000.0, 10, 2, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, - &ob->inertia, 0.01, 10.0, 10, 2, - "Bounding sphere radius, not used for other bounding shapes"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 170, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 180, 185, 170, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius"); - uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); - } + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); } - uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - if ((ob->gameflag & (OB_ACTOR|OB_DYNAMIC)) == (OB_ACTOR|OB_DYNAMIC)) { - if (ob->margin < 0.001f) - ob->margin = 0.06f; - uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, - &ob->margin, 0.001, 1.0, 1, 0, - "Collision margin"); - } else { - uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, - &ob->margin, 0.0, 1.0, 1, 0, - "Collision margin"); - } - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 115, 105, 55, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static Mesh%x4", - //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", - 170, 105, 105, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 275,105,75,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); - } - uiBlockEndAlign(block); } + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + if (ob->gameflag & OB_BOUNDS) { + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", + //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", + 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); + } + uiBlockEndAlign(block); } static void check_object_state(void *arg1_but, void *arg2_mask) @@ -3123,9 +3079,6 @@ void logic_buts(void) int a, iact, stbit, offset; short xco, yco, count, width, ycoo; char *pupstr, name[32]; - /* pin is a bool used for actuator and sensor drawing with states - * pin so changing states dosnt hide the logic brick */ - char pin; wrld= G.scene->world; @@ -3156,7 +3109,7 @@ void logic_buts(void) uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 70, 340, 24, + uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 90, 340, 24, NULL, 0.0, 100.0, 100, 0, ""); @@ -3165,26 +3118,26 @@ void logic_buts(void) a= 0; prop= ob->prop.first; while(prop) { - but= uiDefBut(block, BUT, 1, "Del", 10, (short)(50-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); + but= uiDefBut(block, BUT, 1, "Del", 10, (short)(70-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); uiButSetFunc(but, del_property, prop, NULL); - uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(50-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); - but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(50-20*a), 110, 20, prop->name, 0, 31, 0, 0, "Available as GameObject attributes in the game engines python api"); + uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(70-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); + but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(70-20*a), 110, 20, prop->name, 0, 31, 0, 0, ""); uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1); if(prop->type==PROP_BOOL) { - uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); - uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); } else if(prop->type==PROP_INT) - uiDefButI(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); + uiDefButI(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); else if(prop->type==PROP_FLOAT) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); else if(prop->type==PROP_STRING) - uiDefBut(block, TEX, B_REDR, "", 220, (short)(50-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); + uiDefBut(block, TEX, B_REDR, "", 220, (short)(70-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); else if(prop->type==PROP_TIME) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); - uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(50-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); + uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(70-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); a++; prop= prop->next; @@ -3311,13 +3264,13 @@ void logic_buts(void) uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); uiBlockSetEmboss(block, UI_EMBOSSP); 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, 19, "Set controller state mask"); uiBlockSetEmboss(block, UI_EMBOSSM); 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-136), 19, cont->name, 0, 31, 0, 0, "Controller name"); + uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-166), 19, cont->name, 0, 31, 0, 0, "Controller name"); uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); ycoo= yco; @@ -3327,9 +3280,9 @@ void logic_buts(void) 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, 100, 19, 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-136), 19, cont, 0, 0, 0, 0, "Controller name"); + but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-166), 19, cont, 0, 0, 0, 0, "Controller name"); uiButSetFunc(but, sca_move_controller, cont, NULL); ycoo= yco; } @@ -3386,26 +3339,18 @@ void logic_buts(void) sens= ob->sensors.first; while(sens) { if (!(G.buts->scaflag & BUTS_SENS_STATE) || - (sens->totlinks == 0) || /* always display sensor without links so that is can be edited */ - (sens->flag & SENS_PIN && G.buts->scaflag & BUTS_SENS_STATE) || /* states can hide some sensors, pinned sensors ignore the visible state */ - (is_sensor_linked(block, sens)) - ) { - /* should we draw the pin? - for now always draw when there is a state */ - pin = (G.buts->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1:0 ; - + sens->totlinks == 0 || /* always display sensor without links so that is can be edited */ + is_sensor_linked(block, sens)) { sens->flag |= SENS_VISIBLE; uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); - if (pin) - uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PIN_DEHLT, (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_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &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"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-124), 19, sens->name, 0, 31, 0, 0, "Sensor name"); uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); sens->otype= sens->type; @@ -3417,7 +3362,7 @@ void logic_buts(void) 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, ""); 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-124), 19, sens, 0, 31, 0, 0, ""); uiButSetFunc(but, sca_move_sensor, sens, NULL); } @@ -3466,22 +3411,16 @@ void logic_buts(void) while(act) { if (!(G.buts->scaflag & BUTS_ACT_STATE) || !(act->flag & ACT_LINKED) || /* always display actuators without links so that is can be edited */ - (act->flag & ACT_VISIBLE) || /* this actuator has visible connection, display it */ - (act->flag & ACT_PIN && G.buts->scaflag & BUTS_ACT_STATE)) { - - pin = (G.buts->scaflag & BUTS_ACT_STATE && (act->flag & SENS_SHOW || act->flag & SENS_PIN)) ? 1:0 ; - + (act->flag & ACT_VISIBLE)) { /* this actuator has visible connection, display it */ act->flag |= ACT_VISIBLE; /* mark the actuator as visible to help implementing the up/down action */ uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator"); - if (pin) - uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PIN_DEHLT, (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_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings"); + 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"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-134), 19, act->name, 0, 31, 0, 0, "Actuator name"); uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0); ycoo= yco; @@ -3493,7 +3432,7 @@ void logic_buts(void) 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"); 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-134), 19, act, 0, 0, 0, 0, "Actuator name"); uiButSetFunc(but, sca_move_actuator, act, NULL); ycoo= yco; } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index a18950157b2..78f19ad0608 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -66,7 +66,6 @@ #include "BIF_glutil.h" #include "BIF_graphics.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_keyval.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" @@ -242,9 +241,9 @@ static void enable_constraint_ipo_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname, 1); + verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname); else - verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL, 1); + verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL); /* make sure ipowin shows it */ ob->ipowin= ID_CO; @@ -269,9 +268,9 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE, 1); + icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE); else - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); if (!icu) { error("Cannot get a curve from this IPO, may be dealing with linked data"); @@ -2632,32 +2631,19 @@ static void object_panel_object(Object *ob) /* all groups */ for(group= G.main->group.first; group; group= group->id.next) { if(object_in_group(ob, group)) { - xco= 130; + xco= 160; - if(group->id.lib) { - uiBlockBeginAlign(block); - uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */ - uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 100, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); - uiClearButLock(); - - but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 110, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local"); - uiButSetFunc(but, group_local, group, NULL); - uiBlockEndAlign(block); - } else { - but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 120, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); - uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); - } - - uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); uiBlockBeginAlign(block); - uiDefButF(block, NUM, REDRAWALL, "X:", xco+5, 120-yco, 50, 20, &group->dupli_ofs[0], -100000, 100000, 100, 0, "Offset to use when instacing the group"); - uiDefButF(block, NUM, REDRAWALL, "Y:", xco+55, 120-yco, 50, 20, &group->dupli_ofs[1], -100000, 100000, 100, 0, "Offset to use when instacing the group"); - uiDefButF(block, NUM, REDRAWALL, "Z:", xco+105, 120-yco, 50, 20, &group->dupli_ofs[2], -100000, 100000, 100, 0, "Offset to use when instacing the group"); - uiBlockEndAlign(block); + uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */ + but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 150, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); + uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); uiClearButLock(); - xco = 290; - if(group->id.lib==0) { /* cant remove objects from linked groups */ + if(group->id.lib) { + but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 160, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local"); + uiButSetFunc(but, group_local, group, NULL); + xco= 180; + } else { /* cant remove objects from linked groups */ but = uiDefIconBut(block, BUT, B_NOP, VICON_X, xco, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove Group membership"); uiButSetFunc(but, group_ob_rem, group, ob); } @@ -2985,8 +2971,7 @@ void do_effects_panels(unsigned short event) psmd= (ParticleSystemModifierData*) md; psmd->psys=psys; BLI_addtail(&ob->modifiers, md); - } else - id->us--; + } idtest->us++; psys->part=(ParticleSettings*)idtest; @@ -3044,7 +3029,7 @@ void do_effects_panels(unsigned short event) if(ob && (psys=psys_get_current(ob))){ if(psys->part) { if(psys->part->id.us>1){ - if(okee("Make Single User")){ + if(okee("Make local")){ part=psys_copy_settings(psys->part); part->id.us=1; psys->part->id.us--; diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index f2e20356f21..5205be3e1b0 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -211,15 +211,9 @@ void do_soundbuts(unsigned short event) case B_SOUND_MENU_SAMPLE: if (G.buts->menunr > 0) { sample = BLI_findlink(samples, G.buts->menunr - 1); - if (sample && sound && sound->sample != sample) { - int wasrelative = (strncmp(sound->name, "//", 2)==0); - + if (sample && sound) { BLI_strncpy(sound->name, sample->name, sizeof(sound->name)); sound_set_sample(sound, sample); - - if (wasrelative) - BLI_makestringcode(G.sce, sound->name); - do_soundbuts(B_SOUND_REDRAW); } } diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 6d5e1a62ad4..1b580381ca5 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -113,8 +113,6 @@ #include "RE_pipeline.h" -#include "GPU_material.h" - /* -----includes for this file specific----- */ #include "butspace.h" // own module @@ -211,7 +209,6 @@ static void load_image_cb(char *str, void *ima_pp_v, void *iuser_v) /* called fr if(GS(tex->id.name)==ID_TE) { BIF_preview_changed(ID_TE); allqueue(REDRAWBUTSSHADING, 0); - allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); } } @@ -1545,35 +1542,10 @@ static void texture_panel_colors(Tex *tex) uiDefButF(block, NUMSLI, B_TEXPRV, "Contr", 160,10,150,20, &tex->contrast, 0.01, 5.0, 0, 0, "Changes the contrast of the color or intensity of a texture"); } -static int texture_channels_num_display(MTex **mtex) + +static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) { - int a, num_mtex; - - if(!mtex) - return 0; - - /* compute number of texture channels to draw, 1 more - * than the last, used texture channel, and at least 10 */ - num_mtex = 0; - - for(a=MAX_MTEX-1; a>=0; a--) { - if (mtex[a]) { - num_mtex = a+1; - break; - } - } - - if (num_mtex < 10) - return 10; - else if(num_mtex < MAX_MTEX) - return num_mtex + 1; - else - return MAX_MTEX; -} - -static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) -{ - MTex **mtex, *mt; + MTex *mt=NULL; uiBlock *block; ID *id=NULL, *idfrom; int a, yco, loos; @@ -1584,35 +1556,17 @@ static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp if(uiNewPanel(curarea, block, "Texture", "Texture", 320, 0, 318, 204)==0) return; /* first do the browse but */ - if(actmtex) - id= (ID *)actmtex->tex; + if(mtex) + id= (ID *)mtex->tex; else if(node) id= node->id; - if(ma) { - idfrom= &ma->id; - mtex= ma->mtex; - } - else if(wrld) { - idfrom= &wrld->id; - mtex= wrld->mtex; - } - else if(la) { - idfrom= &la->id; - mtex= la->mtex; - } - else if(br) { - idfrom= &br->id; - mtex= br->mtex; - } - else if(sd) { - idfrom= NULL; /* Not sure what this does */ - mtex= sd->mtex; - } - else { - idfrom= NULL; - mtex= NULL; - } + if(ma) idfrom= &ma->id; + else if(wrld) idfrom= &wrld->id; + else if(la) idfrom= &la->id; + else if(br) idfrom= &br->id; + else if(sd) idfrom= NULL; /* Not sure what this does */ + else idfrom= NULL; uiBlockSetCol(block, TH_BUT_SETTING2); if(ma) { @@ -1641,13 +1595,15 @@ static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp /* CHANNELS */ if(node==NULL) { - int num_mtex; uiBlockBeginAlign(block); yco= 150; - - num_mtex= texture_channels_num_display(mtex); - for(a=0; amtex[a]; + else if(wrld) mt= wrld->mtex[a]; + else if(la) mt= la->mtex[a]; + else if(br) mt= br->mtex[a]; + else if(sd) mt= sd->mtex[a]; if(mt && mt->tex) splitIDname(mt->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2074,7 +2030,7 @@ static void world_panel_texture(World *wrld) uiBlock *block; MTex *mtex; ID *id; - int a, loos, num_mtex; + int a, loos; char str[64], *strp; block= uiNewBlock(&curarea->uiblocks, "world_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -2085,8 +2041,7 @@ static void world_panel_texture(World *wrld) /* TEX CHANNELS */ uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - num_mtex= texture_channels_num_display(wrld->mtex); - for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2551,7 +2506,7 @@ static void lamp_panel_texture(Object *ob, Lamp *la) uiBlock *block; MTex *mtex; ID *id; - int a, loos, num_mtex; + int a, loos; char *strp, str[64]; block= uiNewBlock(&curarea->uiblocks, "lamp_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -2562,8 +2517,7 @@ static void lamp_panel_texture(Object *ob, Lamp *la) /* TEX CHANNELS */ uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - num_mtex= texture_channels_num_display(la->mtex); - for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2649,9 +2603,9 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); if(la->type==LA_SPOT) { - uiDefButBitI(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); + uiDefButBitS(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); if(la->mode & LA_SHAD_BUF) { char *tip= "Regular buffer type"; if(la->buftype==LA_SHADBUF_IRREGULAR) @@ -2664,15 +2618,12 @@ static void lamp_panel_spot(Object *ob, Lamp *la) } uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, LA_ONLYSHADOW, B_LAMPPRV,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); - uiDefButBitI(block, TOG, LA_LAYER_SHADOW, B_LAMPPRV,"Layer", 10,90,80,19,&la->mode, 0, 0, 0, 0, "Causes only objects on the same layer to cast shadows"); - uiBlockEndAlign(block); + uiDefButBitS(block, TOG, LA_ONLYSHADOW, B_LAMPPRV,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); if(la->type==LA_SPOT) { uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); - uiDefButBitI(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,40,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); + uiDefButBitS(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); + uiDefButBitS(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,40,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); uiBlockBeginAlign(block); uiDefButF(block, NUMSLI,B_LAMPREDRAW,"SpotSi ", 100,180,200,19,&la->spotsize, 1.0, 180.0, 0, 0, "Sets the angle of the spotlight beam in degrees"); @@ -2796,12 +2747,12 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) /* in yafray arealights always cast shadows, so ray shadow flag not needed */ /* ray shadow also not used when halo for spot enabled */ if ((la->type!=LA_AREA) && (!((la->type==LA_SPOT) && (la->mode & LA_HALO)))) - uiDefButBitI(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); /* in yafray the regular lamp can use shadowbuffers (softlight), used by spot with halo as well */ /* to prevent clash with blender shadowbuf flag, a special flag is used for yafray */ if (la->type==LA_LOCAL) { - uiDefButBitI(block, TOG, LA_YF_SOFT, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets light produce shadows using shadow buffer"); + uiDefButBitS(block, TOG, LA_YF_SOFT, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets light produce shadows using shadow buffer"); uiDefButF(block, NUM, B_DIFF, "GloInt:", 100,155,200,19, &la->YF_glowint, 0.0, 1.0, 1, 0, "Sets light glow intensity, 0 is off"); uiDefButF(block, NUM, B_DIFF, "GloOfs:", 100,135,100,19, &la->YF_glowofs, 0.0, 2.0, 1, 0, "Sets light glow offset, the higher, the less 'peaked' the glow"); uiDefButS(block, NUM, B_DIFF, "GlowType:", 200,135,100,19, &la->YF_glowtype, 0, 1, 1, 0, "Sets light glow type"); @@ -2829,7 +2780,7 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) if (la->type==LA_SPOT) { - uiDefButBitI(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,50,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); + uiDefButBitS(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,50,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); @@ -2949,15 +2900,15 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButS(block, MENU, B_LAMPREDRAW, "Falloff %t|Constant %x0|Inverse Linear %x1|Inverse Square %x2|Custom Curve %x3|Lin/Quad Weighted %x4|", 10,150,100,19, &la->falloff_type, 0,0,0,0, "Lamp falloff - intensity decay with distance"); - uiDefButBitI(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); + uiDefButBitS(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); } uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButBitI(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); - uiDefButBitI(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); - uiDefButBitI(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); - uiDefButBitI(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); + uiDefButBitS(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); + uiDefButBitS(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); + uiDefButBitS(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); + uiDefButBitS(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_AUTO); @@ -3572,7 +3523,7 @@ static void material_panel_texture(Object *ob, Material *ma) ID *id; ParticleSystem *psys; int loos, psys_mapto=0; - int a, num_mtex; + int a; char str[64], *strp; block= uiNewBlock(&curarea->uiblocks, "material_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -3588,8 +3539,7 @@ static void material_panel_texture(Object *ob, Material *ma) uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - num_mtex= texture_channels_num_display(ma->mtex); - for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -3603,10 +3553,10 @@ static void material_panel_texture(Object *ob, Material *ma) /* SEPTEX */ uiBlockSetCol(block, TH_AUTO); - for(a= 0; amtex[a]; if(mtex && mtex->tex) { - but=uiDefIconButBitI(block, ICONTOGN, 1<septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel"); + but=uiDefIconButBitS(block, ICONTOGN, 1<septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel"); if(psys_mapto && ma->mtex[a]->mapto & MAP_PA_IVEL) uiButSetFunc(but, particle_recalc_material, ma, NULL); @@ -4141,14 +4091,13 @@ static void material_panel_material(Material *ma) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButBitI(block, TOG, MA_VERTEXCOL, B_MAT_VCOL_LIGHT, "VCol Light", 8,166,74,20, &(ma->mode), 0, 0, 0, 0, "Adds vertex colors as extra light"); uiDefButBitI(block, TOG, MA_VERTEXCOLP, B_MAT_VCOL_PAINT, "VCol Paint", 82,166,74,20, &(ma->mode), 0, 0, 0, 0, "Replaces material's colors with vertex colors"); - uiDefButBitI(block, TOG, MA_FACETEXTURE, B_MATPRV, "TexFace", 156,166,60,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); - uiDefButBitI(block, TOG, MA_FACETEXTURE_ALPHA, B_MATPRV, "A", 216,166,20,20, &(ma->mode), 0, 0, 0, 0, "Use alpha channel in 'TexFace' assigned images"); - uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 236,166,67,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); + uiDefButBitI(block, TOG, MA_FACETEXTURE, B_REDR, "TexFace", 156,166,64,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); + if (ma->mode & MA_FACETEXTURE) uiDefButBitI(block, TOG, MA_FACETEXTURE_ALPHA, B_REDR, "A", 220,166,20,20, &(ma->mode), 0, 0, 0, 0, "Use alpha channel in 'TexFace' assigned images"); + uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 240,166,63,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); - uiDefButBitI(block, TOG, MA_NOMIST, B_MATPRV, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); + uiDefButBitI(block, TOG, MA_NOMIST, B_NOP, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); uiDefButBitI(block, TOG, MA_ENV, B_MATPRV, "Env", 82,146,74,20, &(ma->mode), 0, 0, 0, 0, "Causes faces to render with alpha zero: allows sky/backdrop to show through (only for solid faces)"); - uiDefButBitS(block, TOG, MA_OBCOLOR, B_MATPRV, "ObColor", 156,146,60,20, &(ma->shade_flag), 0, 0, 0, 0, "Modulate the result with a per object color"); - uiDefButF(block, NUM, B_NOP, "Shad A ", 216,146,87,20, &ma->shad_alpha, 0.001, 1.0f, 10, 2, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); + uiDefButF(block, NUM, B_NOP, "Shad A ", 156,146,147,19, &ma->shad_alpha, 0.001, 1.0f, 100, 0, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); } uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index f36719a1c9c..0782ccfc7ee 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -78,7 +78,6 @@ #include "BIF_drawgpencil.h" #include "BIF_gl.h" #include "BIF_glutil.h" -#include "BIF_keyframing.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_mywindow.h" @@ -683,18 +682,6 @@ static void draw_channel_names(void) special= ICON_SEQUENCE; } break; - case SPACE_IMAGE: - { - SpaceImage *sima= sa->spacedata.first; - - if (sima->image) - sprintf(name, "Image: %s", sima->image->id.name+2); - else - sprintf(name, "Image: "); - - special= ICON_IMAGE_COL; - } - break; default: { diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index c37eaf7986c..6d78b21dfbb 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -2505,9 +2505,6 @@ int draw_armature(Base *base, int dt, int flag) Object *ob= base->object; bArmature *arm= ob->data; int retval= 0; - - if(G.f & G_SIMULATION) - return 1; if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) { /* we use color for solid lighting */ diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index fb21d94f39a..f60d53a9c5d 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -60,7 +60,6 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" -#include "BIF_drawseq.h" #include "BIF_graphics.h" #include "BIF_interface.h" #include "BIF_mywindow.h" @@ -98,8 +97,6 @@ void gp_ui_activelayer_cb (void *gpd, void *gpl) { gpencil_layer_setactive(gpd, gpl); - - scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -111,8 +108,6 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128); gpencil_layer_setactive(gpd, gpl); - - scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -120,8 +115,6 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) void gp_ui_addlayer_cb (void *gpd, void *dummy) { gpencil_layer_addnew(gpd); - - scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -129,8 +122,6 @@ void gp_ui_addlayer_cb (void *gpd, void *dummy) void gp_ui_dellayer_cb (void *gpd, void *dummy) { gpencil_layer_delactive(gpd); - - scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -141,8 +132,6 @@ void gp_ui_delstroke_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_frame_delete_laststroke(gpf); - - scrarea_queue_winredraw(curarea); } /* delete active frame of active layer */ @@ -153,19 +142,9 @@ void gp_ui_delframe_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_layer_delframe(gpl, gpf); - scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } -/* convert the active layer to geometry */ -void gp_ui_convertlayer_cb (void *gpd, void *gpl) -{ - gpencil_layer_setactive(gpd, gpl); - gpencil_convert_menu(); - - scrarea_queue_winredraw(curarea); -} - /* ------- Drawing Code ------- */ /* draw the controls for a given layer */ @@ -187,7 +166,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short /* rounded header */ if (active) uiBlockSetCol(block, TH_BUT_ACTION); rb_col= (active)?-20:20; - uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); + uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); if (active) uiBlockSetCol(block, TH_AUTO); /* lock toggle */ @@ -198,7 +177,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) { char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */ - height= 0; + height= 26; /* visibility button (only if hidden but not locked!) */ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) @@ -270,14 +249,8 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short /* options */ uiBlockBeginAlign(block); - if (curarea->spacetype == SPACE_VIEW3D) { - but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)"); - uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl); - } - else { - but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); - uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); - } + but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); + uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)"); uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl); @@ -324,7 +297,7 @@ short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa) /* 'view align' button (naming depends on context) */ if (sa->spacetype == SPACE_VIEW3D) uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space"); - else + else if (sa->spacetype != SPACE_SEQ) /* not available for sequencer yet */ uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas"); } @@ -350,9 +323,6 @@ enum { GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */ }; -/* thickness above which we should use special drawing */ -#define GP_DRAWTHICKNESS_SPECIAL 3 - /* ----- Tool Buffer Drawing ------ */ /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ @@ -377,13 +347,23 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick glEnd(); } else if (sflag & GP_STROKE_ERASER) { - /* don't draw stroke at all! */ + /* draw stroke curve - just standard thickness */ + setlinestyle(4); + glLineWidth(1.0f); + + glBegin(GL_LINE_STRIP); + for (i=0, pt=points; i < totpoints && pt; i++, pt++) { + glVertex2f(pt->x, pt->y); + } + glEnd(); + + setlinestyle(0); } else { float oldpressure = 0.0f; /* draw stroke curve */ - if (G.f & G_DEBUG) setlinestyle(2); + setlinestyle(2); glBegin(GL_LINE_STRIP); for (i=0, pt=points; i < totpoints && pt; i++, pt++) { @@ -401,14 +381,14 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick } glEnd(); - if (G.f & G_DEBUG) setlinestyle(0); + setlinestyle(0); } } /* ----- Existing Strokes Drawing (3D and Point) ------ */ /* draw a given stroke - just a single dot (only one point) */ -static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sflag, int offsx, int offsy, int winx, int winy) +static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int winy) { /* draw point */ if (sflag & GP_STROKE_3DSPACE) { @@ -416,42 +396,18 @@ static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sfl glVertex3f(points->x, points->y, points->z); glEnd(); } + else if (sflag & GP_STROKE_2DSPACE) { + glBegin(GL_POINTS); + glVertex2f(points->x, points->y); + glEnd(); + } else { - float co[2]; + const float x= (points->x / 1000 * winx); + const float y= (points->y / 1000 * winy); - /* get coordinates of point */ - if (sflag & GP_STROKE_2DSPACE) { - co[0]= points->x; - co[1]= points->y; - } - else if (sflag & GP_STROKE_2DIMAGE) { - co[0]= (points->x * winx) + offsx; - co[1]= (points->y * winy) + offsy; - } - else { - co[0]= (points->x / 1000 * winx); - co[1]= (points->y / 1000 * winy); - } - - /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple opengl point will do */ - if (thickness < GP_DRAWTHICKNESS_SPECIAL) { - glBegin(GL_POINTS); - glVertex2fv(co); - glEnd(); - } - else { - /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */ - GLUquadricObj *qobj = gluNewQuadric(); - - gluQuadricDrawStyle(qobj, GLU_FILL); - - /* need to translate drawing position, but must reset after too! */ - glTranslatef(co[0], co[1], 0.); - gluDisk( qobj, 0.0, thickness, 32, 1); - glTranslatef(-co[0], -co[1], 0.); - - gluDeleteQuadric(qobj); - } + glBegin(GL_POINTS); + glVertex2f(x, y); + glEnd(); } } @@ -491,15 +447,10 @@ static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thicknes /* ----- Fancy 2D-Stroke Drawing ------ */ /* draw a given stroke in 2d */ -static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, - short debug, int offsx, int offsy, int winx, int winy) +static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) { - /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better - * - but NOT if Image Editor 'image-based' stroke - */ - if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || - ((curarea->spacetype==SPACE_IMAGE) && (dflag & GP_DRAWDATA_ONLYV2D)) ) - { + /* if thickness is less than 3, 'smooth' opengl lines look better */ + if (thickness < 3) { bGPDspoint *pt; int i; @@ -508,12 +459,6 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } - else if (sflag & GP_STROKE_2DIMAGE) { - const float x= (pt->x * winx) + offsx; - const float y= (pt->y * winy) + offsy; - - glVertex2f(x, y); - } else { const float x= (pt->x / 1000 * winx); const float y= (pt->y / 1000 * winy); @@ -523,10 +468,7 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, } glEnd(); } - - /* tesselation code: currently only enabled with rt != 0 */ - else - { + else { /* tesselation code: currently only enabled with rt != 0 */ bGPDspoint *pt1, *pt2; float pm[2]; int i; @@ -546,12 +488,6 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, s0[0]= pt1->x; s0[1]= pt1->y; s1[0]= pt2->x; s1[1]= pt2->y; } - else if (sflag & GP_STROKE_2DIMAGE) { - s0[0]= (pt1->x * winx) + offsx; - s0[1]= (pt1->y * winy) + offsy; - s1[0]= (pt2->x * winx) + offsx; - s1[1]= (pt2->y * winy) + offsy; - } else { s0[0]= (pt1->x / 1000 * winx); s0[1]= (pt1->y / 1000 * winy); @@ -694,12 +630,6 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } - else if (sflag & GP_STROKE_2DIMAGE) { - const float x= (pt->x * winx) + offsx; - const float y= (pt->y * winy) + offsy; - - glVertex2f(x, y); - } else { const float x= (pt->x / 1000 * winx); const float y= (pt->y / 1000 * winy); @@ -714,8 +644,8 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, /* ----- General Drawing ------ */ /* draw a set of strokes */ -static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, - short debug, short lthick, float color[4]) +static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, short debug, + short lthick, float color[4]) { bGPDstroke *gps; @@ -741,16 +671,16 @@ static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int /* check which stroke-drawer to use */ if (gps->totpoints == 1) - gp_draw_stroke_point(gps->points, lthick, gps->flag, offsx, offsy, winx, winy); + gp_draw_stroke_point(gps->points, gps->flag, winx, winy); else if (dflag & GP_DRAWDATA_ONLY3D) gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); else if (gps->totpoints > 1) - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy); + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); } } /* draw grease-pencil datablock */ -static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int dflag) +static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) { bGPDlayer *gpl, *actlay=NULL; @@ -802,7 +732,7 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ tcolor[3] = color[3] - (i/gpl->gstep); - gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -814,7 +744,7 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy if ((gf->framenum - gpf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ tcolor[3] = color[3] - (i/gpl->gstep); - gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -827,12 +757,12 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->prev) { tcolor[3] = (color[3] / 7); - gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->prev, winx, winy, dflag, debug, lthick, tcolor); } if (gpf->next) { tcolor[3] = (color[3] / 4); - gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->next, winx, winy, dflag, debug, lthick, tcolor); } /* restore alpha */ @@ -842,7 +772,7 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy /* draw the strokes already in active frame */ tcolor[3]= color[3]; - gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) @@ -910,69 +840,16 @@ static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy void draw_gpencil_2dimage (ScrArea *sa, ImBuf *ibuf) { bGPdata *gpd; - int offsx, offsy, sizex, sizey; - int dflag = GP_DRAWDATA_NOSTATUS; + int dflag = 0; /* check that we have grease-pencil stuff to draw */ if (ELEM(NULL, sa, ibuf)) return; gpd= gpencil_data_getactive(sa); if (gpd == NULL) return; - /* calculate rect */ - switch (sa->spacetype) { - case SPACE_IMAGE: /* image */ - { - SpaceImage *sima= (SpaceImage *)sa->spacedata.first; - - /* just draw using standard scaling (settings here are currently ignored anyways) */ - // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled - offsx= 0; - offsy= 0; - sizex= sa->winx; - sizey= sa->winy; - - myortho2(sima->v2d.cur.xmin, sima->v2d.cur.xmax, sima->v2d.cur.ymin, sima->v2d.cur.ymax); - - dflag |= GP_DRAWDATA_ONLYV2D; - } - break; - - case SPACE_SEQ: /* sequence */ - { - SpaceSeq *sseq= (SpaceSeq *)sa->spacedata.first; - float zoom, zoomx, zoomy; - - /* calculate accessory values */ - zoom= SEQ_ZOOM_FAC(sseq->zoom); - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); - zoomy = zoom; - } - else - zoomx = zoomy = zoom; - - sizex= zoomx * ibuf->x; - sizey= zoomy * ibuf->y; - offsx= (sa->winx-sizex)/2 + sseq->xof; - offsy= (sa->winy-sizey)/2 + sseq->yof; - - dflag |= GP_DRAWDATA_ONLYI2D; - } - break; - - default: /* for spacetype not yet handled */ - offsx= 0; - offsy= 0; - sizex= sa->winx; - sizey= sa->winy; - - dflag |= GP_DRAWDATA_ONLYI2D; - break; - } - - /* draw it! */ - gp_draw_data(gpd, offsx, offsy, sizex, sizey, dflag); + dflag = (GP_DRAWDATA_ONLYI2D|GP_DRAWDATA_NOSTATUS); + gp_draw_data(gpd, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly @@ -990,7 +867,7 @@ void draw_gpencil_2dview (ScrArea *sa, short onlyv2d) /* draw it! */ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, 0, 0, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly @@ -1007,7 +884,7 @@ void draw_gpencil_3dview (ScrArea *sa, short only3d) /* draw it! */ if (only3d) dflag |= (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, 0, 0, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to opengl render window assuming that matrices are already set correctly */ @@ -1021,7 +898,7 @@ void draw_gpencil_oglrender (View3D *v3d, int winx, int winy) if (gpd == NULL) return; /* pass 1: draw 3d-strokes ------------ > */ - gp_draw_data(gpd, 0, 0, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D)); + gp_draw_data(gpd, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D)); /* pass 2: draw 2d-strokes ------------ > */ /* adjust view matrices */ @@ -1029,7 +906,7 @@ void draw_gpencil_oglrender (View3D *v3d, int winx, int winy) glLoadIdentity(); /* draw it! */ - gp_draw_data(gpd, 0, 0, winx, winy, GP_DRAWDATA_NOSTATUS); + gp_draw_data(gpd, winx, winy, GP_DRAWDATA_NOSTATUS); } /* ************************************************** */ diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 97765690ceb..14849cdd450 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -52,7 +52,6 @@ #include "DNA_camera_types.h" #include "DNA_color_types.h" #include "DNA_image_types.h" -#include "DNA_gpencil_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_node_types.h" @@ -80,7 +79,6 @@ #include "BDR_editface.h" #include "BDR_drawobject.h" #include "BDR_drawmesh.h" -#include "BDR_gpencil.h" #include "BDR_imagepaint.h" #include "BIF_cursors.h" @@ -88,7 +86,6 @@ #include "BIF_graphics.h" #include "BIF_mywindow.h" #include "BIF_drawimage.h" -#include "BIF_drawgpencil.h" #include "BIF_resources.h" #include "BIF_interface.h" #include "BIF_interface_icons.h" @@ -1781,45 +1778,6 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PREVI } -static void image_panel_gpencil(short cntrl) // IMAGE_HANDLER_GREASEPENCIL -{ - uiBlock *block; - SpaceImage *sima; - - sima= curarea->spacedata.first; - - block= uiNewBlock(&curarea->uiblocks, "image_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win); - uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); - uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL); // for close and esc - if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return; - - /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */ - if (sima->flag & SI_DISPGP) { - if (sima->gpd == NULL) - gpencil_data_setactive(curarea, gpencil_data_addnew()); - } - - if (sima->flag & SI_DISPGP) { - bGPdata *gpd= sima->gpd; - short newheight; - - /* this is a variable height panel, newpanel doesnt force new size on existing panels */ - /* so first we make it default height */ - uiNewPanelHeight(block, 204); - - /* draw button for showing gpencil settings and drawings */ - uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)"); - - /* extend the panel if the contents won't fit */ - newheight= draw_gpencil_panel(block, gpd, curarea); - uiNewPanelHeight(block, newheight); - } - else { - uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor"); - uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); - } -} - static void image_blockhandlers(ScrArea *sa) { SpaceImage *sima= sa->spacedata.first; @@ -1830,6 +1788,7 @@ static void image_blockhandlers(ScrArea *sa) for(a=0; ablockhandler[a]) { + case IMAGE_HANDLER_PROPERTIES: image_panel_properties(sima->blockhandler[a+1]); break; @@ -1847,10 +1806,7 @@ static void image_blockhandlers(ScrArea *sa) break; case IMAGE_HANDLER_PREVIEW: image_panel_preview(sa, sima->blockhandler[a+1]); - break; - case IMAGE_HANDLER_GREASEPENCIL: - image_panel_gpencil(sima->blockhandler[a+1]); - break; + break; } /* clear action value for event */ sima->blockhandler[a+1]= 0; @@ -2383,17 +2339,9 @@ void drawimagespace(ScrArea *sa, void *spacedata) } draw_image_transform(ibuf, xuser_asp, yuser_asp); - - /* draw grease-pencil ('image' strokes) */ - if (sima->flag & SI_DISPGP) - draw_gpencil_2dimage(sa, ibuf); mywinset(sa->win); /* restore scissor after gla call... */ myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); - - /* draw grease-pencil (screen strokes) */ - if (sima->flag & SI_DISPGP) - draw_gpencil_2dview(sa, 0); if(G.rendering==0) { draw_image_view_tool(); diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index ec6a0f0d75b..71854570c8c 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -442,7 +442,7 @@ int in_ipo_buttons(void) else return 1; } -View2D *spacelink_get_view2d(SpaceLink *sl) +static View2D *spacelink_get_view2d(SpaceLink *sl) { if(sl->spacetype==SPACE_IPO) return &((SpaceIpo *)sl)->v2d; @@ -921,13 +921,6 @@ void drawscroll(int disptype) BIF_ThemeColor(TH_TEXT); val= ipogrid_startx; - - if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) { /* prevents printing twice same frame */ - while(ipogrid_dx < 0.9999f) { - ipogrid_dx *= 2.0f; - dfac*= 2.0f; - } - } while(fac < hor.xmax) { if(curarea->spacetype==SPACE_OOPS) { @@ -1952,7 +1945,7 @@ void do_ipobuts(unsigned short event) ei= get_active_editipo(); if(ei) { if(ei->icu==NULL) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); if (!ei->icu) { error("Could not add a driver to this curve, may be linked data!"); break; diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index 8f22c704fd0..09f74c01c71 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -76,12 +76,534 @@ #include "BSE_drawview.h" -#include "GPU_extensions.h" -#include "GPU_draw.h" - #include "blendef.h" #include "nla.h" +#ifndef GL_CLAMP_TO_EDGE +#define GL_CLAMP_TO_EDGE 0x812F +#endif + +//#include "glext.h" +/* some local functions */ +#if defined(GL_EXT_texture_object) && (!defined(__sun__) || (!defined(__sun))) && !defined(__APPLE__) && !defined(__linux__) && !defined(WIN32) + #define glBindTexture(A,B) glBindTextureEXT(A,B) + #define glGenTextures(A,B) glGenTexturesEXT(A,B) + #define glDeleteTextures(A,B) glDeleteTexturesEXT(A,B) + #define glPolygonOffset(A,B) glPolygonOffsetEXT(A,B) + +#else + +/* #define GL_FUNC_ADD_EXT GL_FUNC_ADD */ +/* #define GL_FUNC_REVERSE_SUBTRACT_EXT GL_FUNC_REVERSE_SUBTRACT */ +/* #define GL_POLYGON_OFFSET_EXT GL_POLYGON_OFFSET */ + +#endif + + /* (n&(n-1)) zeros the least significant bit of n */ +static int is_pow2(int num) { + return ((num)&(num-1))==0; +} +static int smaller_pow2(int num) { + while (!is_pow2(num)) + num= num&(num-1); + return num; +} + +/* These are used to enable texture clamping */ +static int is_pow2_limit(int num) { + if (U.glreslimit != 0 && num > U.glreslimit) return 0; + return ((num)&(num-1))==0; +} + +static int smaller_pow2_limit(int num) { + if (U.glreslimit != 0 && num > U.glreslimit) + return U.glreslimit; + return smaller_pow2(num); +} + +static int fCurtile=0, fCurmode=0,fCurtileXRep=0,fCurtileYRep=0; +static Image *fCurpage=0; +static short fTexwindx, fTexwindy, fTexwinsx, fTexwinsy; +static int fDoMipMap = 1; +static int fLinearMipMap = 0; + +/* local prototypes --------------- */ +void update_realtime_textures(void); + + +/* static int source, dest; also not used */ + +/** + * Enables or disable mipmapping for realtime images. + * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0). + */ +void set_mipmap(int mipmap) +{ + if (fDoMipMap != (mipmap != 0)) { + free_all_realtime_images(); + fDoMipMap = mipmap != 0; + } +} + +/** + * Returns the current setting for mipmapping. + */ +static int get_mipmap(void) +{ + return fDoMipMap && (!(G.f & G_TEXTUREPAINT)); +} + +/** + * Enables or disable linear mipmap setting for realtime images (textures). + * Note that this will will destroy all texture bindings in OpenGL. + * @see free_realtime_image() + * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0). + */ +void set_linear_mipmap(int linear) +{ + if (fLinearMipMap != (linear != 0)) { + free_all_realtime_images(); + fLinearMipMap = linear != 0; + } +} + +/** + * Returns the current setting for linear mipmapping. + */ +int get_linear_mipmap(void) +{ + return fLinearMipMap; +} + + +/** + * Resets the realtime image cache variables. + */ +void clear_realtime_image_cache() +{ + fCurpage = NULL; + fCurtile = 0; + fCurmode = 0; + fCurtileXRep = 0; + fCurtileYRep = 0; +} + +/* REMEMBER! Changes here must go into my_set_tpage() as well */ +int set_tpage(MTFace *tface) +{ + static int alphamode= -1; + static MTFace *lasttface= 0; + Image *ima; + ImBuf *ibuf; + unsigned int *rect=NULL, *bind; + int tpx=0, tpy=0, tilemode, tileXRep,tileYRep; + + /* disable */ + if(tface==0) { + if(lasttface==0) return 0; + + lasttface= 0; + fCurtile= 0; + fCurpage= 0; + if(fCurmode!=0) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + fCurmode= 0; + fCurtileXRep=0; + fCurtileYRep=0; + alphamode= -1; + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable ( GL_ALPHA_TEST ); + return 0; + } + lasttface= tface; + + if( alphamode != tface->transp) { + alphamode= tface->transp; + + if(alphamode) { + if(alphamode==TF_ADD) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glDisable ( GL_ALPHA_TEST ); + /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ + } + else if(alphamode==TF_ALPHA) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* added after 2.45 to clip alpha */ + + /*if U.glalphaclip == 1.0, some cards go bonkers... turn off alpha test in this case*/ + if(U.glalphaclip == 1.0) glDisable(GL_ALPHA_TEST); + else{ + glEnable ( GL_ALPHA_TEST ); + glAlphaFunc ( GL_GREATER, U.glalphaclip ); + } + } else if (alphamode==TF_CLIP){ + glDisable(GL_BLEND); + glEnable ( GL_ALPHA_TEST ); + glAlphaFunc(GL_GREATER, 0.5f); + } + /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ + /* else { */ + /* glBlendFunc(GL_ONE, GL_ONE); */ + /* glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */ + /* } */ + } else { + glDisable(GL_BLEND); + glDisable ( GL_ALPHA_TEST ); + } + } + + ima= tface->tpage; + + /* Enable or disable reflection mapping */ + if (ima && (ima->flag & IMA_REFLECT)){ + +// glActiveTextureARB(GL_TEXTURE0_ARB); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + + /* Handle multitexturing here */ + } + else{ + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + } + + tilemode= tface->mode & TF_TILES; + tileXRep = 0; + tileYRep = 0; + if (ima) { + tileXRep = ima->xrep; + tileYRep = ima->yrep; + } + + + if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0; + + if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + if(tilemode && ima!=NULL) + glScalef(ima->xrep, ima->yrep, 1.0); + + glMatrixMode(GL_MODELVIEW); + } + + if(ima==NULL || ima->ok==0) { + glDisable(GL_TEXTURE_2D); + + fCurtile= tface->tile; + fCurpage= 0; + fCurmode= tilemode; + fCurtileXRep = tileXRep; + fCurtileYRep = tileYRep; + + return 0; + } + + ibuf= BKE_image_get_ibuf(ima, NULL); + if(ibuf==NULL) { + + fCurtile= tface->tile; + fCurpage= 0; + fCurmode= tilemode; + fCurtileXRep = tileXRep; + fCurtileYRep = tileYRep; + + glDisable(GL_TEXTURE_2D); + return 0; + } + + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); + + if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe; + else fCurtile= tface->tile; + + if(tilemode) { + if(ima->repbind==0) make_repbind(ima); + + if(fCurtile>=ima->totbind) fCurtile= 0; + + /* this happens when you change repeat buttons */ + if(ima->repbind) bind= ima->repbind+fCurtile; + else bind= &ima->bindcode; + + if(*bind==0) { + + fTexwindx= ibuf->x/ima->xrep; + fTexwindy= ibuf->y/ima->yrep; + + if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1; + + fTexwinsy= fCurtile / ima->xrep; + fTexwinsx= fCurtile - fTexwinsy*ima->xrep; + + fTexwinsx*= fTexwindx; + fTexwinsy*= fTexwindy; + + tpx= fTexwindx; + tpy= fTexwindy; + + rect= ibuf->rect + fTexwinsy*ibuf->x + fTexwinsx; + } + } + else { + bind= &ima->bindcode; + + if(*bind==0) { + tpx= ibuf->x; + tpy= ibuf->y; + rect= ibuf->rect; + } + } + + if(*bind==0) { + int rectw= tpx, recth= tpy; + unsigned int *tilerect= NULL, *scalerect= NULL; + + /* + * Maarten: + * According to Ton this code is not needed anymore. It was used only + * in really old Blenders. + * Reevan: + * Actually it is needed for backwards compatibility. Simpledemo 6 does not display correctly without it. + */ +#if 1 + if (tilemode) { + int y; + + tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); + for (y=0; yx]; + unsigned int *tilerectrow= &tilerect[y*rectw]; + + memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); + } + + rect= tilerect; + } +#endif + if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { + rectw= smaller_pow2_limit(rectw); + recth= smaller_pow2_limit(recth); + + scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); + gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); + rect= scalerect; + } + + glGenTextures(1, (GLuint *)bind); + + if((G.f & G_DEBUG) || !*bind) { + GLenum error = glGetError(); + printf("Texture: %s\n", ima->id.name+2); + printf("name: %d, tpx: %d\n", *bind, tpx); + printf("tile: %d, mode: %d\n", fCurtile, tilemode); + if (error) + printf("error: %s\n", gluErrorString(error)); + } + glBindTexture( GL_TEXTURE_2D, *bind); + + if (!get_mipmap()) + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else + { + int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; + + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + ima->tpageflag |= IMA_MIPMAP_COMPLETE; + } + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (tilerect) + MEM_freeN(tilerect); + if (scalerect) + MEM_freeN(scalerect); + } + else glBindTexture( GL_TEXTURE_2D, *bind); + + /* dont tile x/y as set the the game properties */ + if (ima->tpageflag & IMA_CLAMP_U) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + if (ima->tpageflag & IMA_CLAMP_V) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + /* tag_image_time(ima);*/ /* Did this get lost in the image recode? */ + + glEnable(GL_TEXTURE_2D); + + fCurpage= ima; + fCurmode= tilemode; + fCurtileXRep = tileXRep; + fCurtileYRep = tileYRep; + + return 1; +} + +void update_realtime_image(Image *ima, int x, int y, int w, int h) +{ + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if (ima->repbind || get_mipmap() || !ima->bindcode || !ibuf || + (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || + (w == 0) || (h == 0)) { + /* these special cases require full reload still */ + free_realtime_image(ima); + } + else { + int row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); + int skip_pixels = glaGetOneInteger(GL_UNPACK_SKIP_PIXELS); + int skip_rows = glaGetOneInteger(GL_UNPACK_SKIP_ROWS); + + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei(GL_UNPACK_SKIP_ROWS, y); + + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_UNSIGNED_BYTE, ibuf->rect); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } +} + +void free_realtime_image(Image *ima) +{ + if(ima->bindcode) { + glDeleteTextures(1, (GLuint *)&ima->bindcode); + ima->bindcode= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } + if(ima->repbind) { + glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); + + MEM_freeN(ima->repbind); + ima->repbind= NULL; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } +} + +void free_all_realtime_images(void) +{ + Image* ima; + + for(ima=G.main->image.first; ima; ima=ima->id.next) + free_realtime_image(ima); +} + +/* these two functions are called on entering and exiting texture paint mode, + temporary disabling/enabling mipmapping on all images for quick texture + updates with glTexSubImage2D. images that didn't change don't have to be + re-uploaded to OpenGL */ +void texpaint_disable_mipmap(void) +{ + Image* ima; + + if(!fDoMipMap) + return; + + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + } +} + +void texpaint_enable_mipmap(void) +{ + Image* ima; + + if(!fDoMipMap) + return; + + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { + int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + free_realtime_image(ima); + } + } +} + +void make_repbind(Image *ima) +{ + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf==NULL) return; + + if(ima->repbind) { + glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); + MEM_freeN(ima->repbind); + ima->repbind= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } + ima->totbind= ima->xrep*ima->yrep; + if(ima->totbind>1) { + ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); + } +} + +void update_realtime_textures() +{ + Image *ima; + + ima= G.main->image.first; + while(ima) { + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; + + /* check: is bindcode not in the array? Free. (to do) */ + + ima->lastframe++; + if(ima->lastframe > ima->twend) ima->lastframe= ima->twsta; + + } + ima= ima->id.next; + } +} + /***/ /* Flags for marked edges */ @@ -105,7 +627,7 @@ static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flag *flags_p |= flags; } -static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) +EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) { EdgeHash *eh = BLI_edgehash_new(); int i; @@ -253,6 +775,81 @@ static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm) BLI_edgehash_free(data.eh, NULL); } +static int set_gl_light(Object *ob) +{ + Base *base; + Lamp *la; + int count; + /* float zero[4]= {0.0, 0.0, 0.0, 0.0}; */ + float vec[4]; + + vec[3]= 1.0; + + for(count=0; count<8; count++) glDisable(GL_LIGHT0+count); + + count= 0; + + base= FIRSTBASE; + while(base) { + if(base->object->type==OB_LAMP ) { + if(base->lay & G.vd->lay) { + if(base->lay & ob->lay) + { + la= base->object->data; + + glPushMatrix(); + glLoadMatrixf((float *)G.vd->viewmat); + + where_is_object_simul(base->object); + VECCOPY(vec, base->object->obmat[3]); + + if(la->type==LA_SUN) { + vec[0]= base->object->obmat[2][0]; + vec[1]= base->object->obmat[2][1]; + vec[2]= base->object->obmat[2][2]; + vec[3]= 0.0; + glLightfv(GL_LIGHT0+count, GL_POSITION, vec); + } + else { + vec[3]= 1.0; + glLightfv(GL_LIGHT0+count, GL_POSITION, vec); + glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); + /* post 2.25 engine supports quad lights */ + glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); + + if(la->type==LA_SPOT) { + vec[0]= -base->object->obmat[2][0]; + vec[1]= -base->object->obmat[2][1]; + vec[2]= -base->object->obmat[2][2]; + glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, vec); + glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0); + glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend); + } + else glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); + } + + vec[0]= la->energy*la->r; + vec[1]= la->energy*la->g; + vec[2]= la->energy*la->b; + vec[3]= 1.0; + glLightfv(GL_LIGHT0+count, GL_DIFFUSE, vec); + glLightfv(GL_LIGHT0+count, GL_SPECULAR, vec);//zero); + glEnable(GL_LIGHT0+count); + + glPopMatrix(); + + count++; + if(count>7) break; + } + } + } + base= base->next; + } + + return count; +} + static Material *give_current_material_or_def(Object *ob, int matnr) { extern Material defmaterial; // render module abuse... @@ -296,9 +893,9 @@ static int set_draw_settings_cached(int clearcache, int textured, MTFace *texfac if (textured!=c_textured || texface!=c_texface) { if (textured ) { - c_badtex= !GPU_set_tpage(texface); + c_badtex= !set_tpage(texface); } else { - GPU_set_tpage(0); + set_tpage(0); c_badtex= 0; } c_textured= textured; @@ -353,7 +950,7 @@ static void draw_textured_begin(Object *ob) } else /* draw with lights in the scene otherwise */ - Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat); + Gtexdraw.islit= set_gl_light(ob); obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); @@ -374,12 +971,12 @@ static void draw_textured_begin(Object *ob) static void draw_textured_end() { /* switch off textures */ - GPU_set_tpage(0); + set_tpage(0); glShadeModel(GL_FLAT); glDisable(GL_CULL_FACE); - /* XXX, bad patch - GPU_default_lights() calls + /* XXX, bad patch - default_gl_light() calls * glLightfv(GL_LIGHT_POSITION, ...) which * is transformed by the current matrix... we * need to make sure that matrix is identity. @@ -390,7 +987,7 @@ static void draw_textured_end() */ glPushMatrix(); glLoadIdentity(); - GPU_default_lights(); + default_gl_light(); glPopMatrix(); } @@ -460,71 +1057,50 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot return 1; } -void draw_mesh_text(Object *ob, int glsl) +static void draw_game_text_mesh(Object *ob, Mesh *me) { - Mesh *me = ob->data; - DerivedMesh *ddm; - MFace *mf, *mface= me->mface; + DerivedMesh *ddm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); + MFace *mface= me->mface; MTFace *tface= me->mtface; MCol *mcol= me->mcol; /* why does mcol exist? */ bProperty *prop = get_property(ob, "Text"); - GPUVertexAttribs gattribs; - int a, totface= me->totface; + int a, start= 0, totface= me->totface; - /* don't draw without tfaces */ - if(!tface) - return; - - /* don't draw when editing */ - if(ob==G.obedit) - return; - else if(ob==OBACT) - if(FACESEL_PAINT_TEST) - return; - - ddm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); - - for(a=0, mf=mface; amode; int matnr= mf->mat_nr; int mf_smooth= mf->flag & ME_SMOOTH; if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) { + int badtex= set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE); float v1[3], v2[3], v3[3], v4[3]; char string[MAX_PROPSTRING]; - int characters, i, glattrib= -1, badtex= 0; + int characters, index; + ImBuf *ibuf; + float curpos; - if(glsl) { - GPU_enable_material(matnr+1, &gattribs); - - for(i=0; igetVertCo(ddm, mf->v1, v1); ddm->getVertCo(ddm, mf->v2, v2); ddm->getVertCo(ddm, mf->v3, v3); if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4); - // The BM_FONT handling is in the gpu module, shared with the - // game engine, was duplicated previously + // The BM_FONT handling code is duplicated in the gameengine + // Search for 'Frank van Beek' ;-) + // string = "Frank van Beek"; set_property_valstr(prop, string); characters = strlen(string); - if(!BKE_image_get_ibuf(tface->tpage, NULL)) + ibuf= BKE_image_get_ibuf(tface->tpage, NULL); + if (ibuf == NULL) { characters = 0; + } if (!mf_smooth) { float nor[3]; @@ -534,11 +1110,46 @@ void draw_mesh_text(Object *ob, int glsl) glNormal3fv(nor); } - GPU_render_text(tface, tface->mode, string, characters, - (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib); - } - if (mcol) { - mcol+=4; + curpos= 0.0; + glBegin(mf->v4?GL_QUADS:GL_TRIANGLES); + for (index = 0; index < characters; index++) { + float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; + int character = string[index]; + char *cp= NULL; + + // lets calculate offset stuff + // space starts at offset 1 + // character = character - ' ' + 1; + + matrixGlyph(ibuf, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + movex+= curpos; + + if (tface->mode & TF_OBCOL) + glColor3ubv(Gtexdraw.obcol); + else if (me->mcol) cp= (char *)mcol; + else glColor3ub(255, 255, 255); + + glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); + if (cp) glColor3ub(cp[3], cp[2], cp[1]); + glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); + + glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); + if (cp) glColor3ub(cp[7], cp[6], cp[5]); + glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); + + glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); + if (cp) glColor3ub(cp[11], cp[10], cp[9]); + glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); + + if(mf->v4) { + glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); + if (cp) glColor3ub(cp[15], cp[14], cp[13]); + glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); + } + + curpos+= advance; + } + glEnd(); } } @@ -548,6 +1159,7 @@ void draw_mesh_text(Object *ob, int glsl) void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) { Mesh *me= ob->data; + int editing= 0; /* correct for negative scale */ if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); @@ -556,20 +1168,38 @@ void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) /* draw the textured mesh */ draw_textured_begin(ob); - if(ob==G.obedit) { - dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh); - } else if(faceselect) { - if(G.f & G_WEIGHTPAINT) - dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); - else - dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me); +#ifdef WITH_VERSE + if(me->vnode) { + /* verse-blender doesn't support uv mapping of textures yet */ + dm->drawFacesTex(dm, NULL); } - else - dm->drawFacesTex(dm, draw_tface__set_draw); + else { +#endif + if(ob==G.obedit) { + dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh); + } else if(faceselect) { + if(G.f & G_WEIGHTPAINT) + dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); + else + dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me); + } + else + dm->drawFacesTex(dm, draw_tface__set_draw); +#ifdef WITH_VERSE + } +#endif - /* draw game engine text hack */ - if(get_property(ob, "Text")) - draw_mesh_text(ob, 0); + /* draw game engine text hack - but not if we are editing the mesh */ + if (me->mtface && get_property(ob, "Text")) { + if(ob==G.obedit) + editing= 1; + else if(ob==OBACT) + if(FACESEL_PAINT_TEST) + editing= 1; + + if(!editing) + draw_game_text_mesh(ob, me); + } draw_textured_end(); @@ -584,3 +1214,10 @@ void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } +void init_realtime_GL(void) +{ + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); +} + diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 4876e6cae7c..213f49528f0 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -93,7 +93,6 @@ #include "BKE_object.h" #include "BKE_anim.h" //for the where_on_path function #include "BKE_particle.h" -#include "BKE_property.h" #include "BKE_utildefines.h" #ifdef WITH_VERSE #include "BKE_verse.h" @@ -130,10 +129,6 @@ #include "BKE_deform.h" -#include "GPU_draw.h" -#include "GPU_material.h" -#include "GPU_extensions.h" - /* pretty stupid */ /* extern Lattice *editLatt; already in BKE_lattice.h */ /* editcurve.c */ @@ -148,37 +143,114 @@ static void drawcircle_size(float size); static void draw_empty_sphere(float size); static void draw_empty_cone(float size); -/* check for glsl drawing */ +/* ************* Setting OpenGL Material ************ */ -int draw_glsl_material(Object *ob, int dt) +// Materials start counting at # one.... +#define MAXMATBUF (MAXMAT + 1) +static float matbuf[MAXMATBUF][2][4]; +static int totmat_gl= 0; + +int set_gl_material(int nr) { - if(!GPU_extensions_minimum_support()) - return 0; - if(G.f & G_PICKSEL) - return 0; - if(!CHECK_OB_DRAWTEXTURE(G.vd, dt)) - return 0; - if(ob==OBACT && (G.f & G_WEIGHTPAINT)) - return 0; + static int last_gl_matnr= -1; + static int last_ret_val= 1; - return ((G.fileflags & G_FILE_GAME_MAT) && - (G.fileflags & G_FILE_GAME_MAT_GLSL) && (dt >= OB_SHADED)); -} - -static int check_material_alpha(Base *base, Object *ob, int glsl) -{ - if(base->flag & OB_FROMDUPLI) - return 0; - - if(G.f & G_PICKSEL) - return 0; + /* prevent index to use un-initialized array items */ + if(nr>totmat_gl) nr= totmat_gl; + + if(nr<0) { + last_gl_matnr= -1; + last_ret_val= 1; + } + else if(nrdata==ob->data) - return 0; + } - return (glsl || (ob->dtx & OB_DRAWTRANSP)); + return last_ret_val; } +/* returns 1: when there's alpha needed to be drawn in a 2nd pass */ +int init_gl_materials(Object *ob, int check_alpha) +{ + extern Material defmaterial; // render module abuse... + Material *ma; + int a, has_alpha= 0; + + if(ob->totcol==0) { + matbuf[0][0][0]= defmaterial.r; + matbuf[0][0][1]= defmaterial.g; + matbuf[0][0][2]= defmaterial.b; + matbuf[0][0][3]= 1.0; + + matbuf[0][1][0]= defmaterial.specr; + matbuf[0][1][1]= defmaterial.specg; + matbuf[0][1][2]= defmaterial.specb; + matbuf[0][1][3]= 1.0; + + /* do material 1 too, for displists! */ + QUATCOPY(matbuf[1][0], matbuf[0][0]); + QUATCOPY(matbuf[1][1], matbuf[0][1]); + } + + for(a=1; a<=ob->totcol; a++) { + ma= give_current_material(ob, a); + ma= editnode_get_active_material(ma); + if(ma==NULL) ma= &defmaterial; + + if(amode & MA_SHLESS) { + matbuf[a][0][0]= ma->r; + matbuf[a][0][1]= ma->g; + matbuf[a][0][2]= ma->b; + } else { + matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r; + matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; + matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; + } + + /* draw transparent, not in pick-select, nor editmode */ + if(check_alpha && !(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) { + if(G.vd->transp) { // drawing the transparent pass + if(ma->alpha==1.0) matbuf[a][0][3]= 0.0; // means skip solid + else matbuf[a][0][3]= ma->alpha; + } + else { // normal pass + if(ma->alpha==1.0) matbuf[a][0][3]= 1.0; + else { + matbuf[a][0][3]= 0.0; // means skip transparent + has_alpha= 1; // return value, to indicate adding to after-draw queue + } + } + } + else + matbuf[a][0][3]= 1.0; + + if (!(ma->mode & MA_SHLESS)) { + matbuf[a][1][0]= ma->spec*ma->specr; + matbuf[a][1][1]= ma->spec*ma->specg; + matbuf[a][1][2]= ma->spec*ma->specb; + matbuf[a][1][3]= 1.0; + } + } + } + + totmat_gl= ob->totcol; + set_gl_material(-1); // signal for static variable + return has_alpha; +} + + /***/ static unsigned int colortab[24]= {0x0, 0xFF88FF, 0xFFBBFF, @@ -280,9 +352,6 @@ void drawaxes(float size, int flag, char drawtype) float v1[3]= {0.0, 0.0, 0.0}; float v2[3]= {0.0, 0.0, 0.0}; float v3[3]= {0.0, 0.0, 0.0}; - - if(G.f & G_SIMULATION) - return; switch(drawtype) { @@ -665,9 +734,6 @@ static void drawlamp(Object *ob) float pixsize, lampsize; float imat[4][4], curcol[4]; char col[4]; - - if(G.f & G_SIMULATION) - return; la= ob->data; @@ -958,9 +1024,6 @@ static void drawcamera(Object *ob, int flag) float vec[8][4], tmat[4][4], fac, facx, facy, depth; int i; - if(G.f & G_SIMULATION) - return; - cam= ob->data; glDisable(GL_LIGHTING); @@ -1767,9 +1830,6 @@ static void draw_verse_debug(Object *ob, EditMesh *em) struct EditFace *efa=NULL; float v1[3], v2[3], v3[3], v4[3], fvec[3], col[3]; char val[32]; - - if(G.f & G_SIMULATION) - return; if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) glDisable(GL_DEPTH_TEST); @@ -1834,9 +1894,6 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em) char conv_float[5]; /* Use a float conversion matching the grid size */ float area, col[3]; /* area of the face, color of the text to draw */ - if(G.f & G_SIMULATION) - return; - /* make the precission of the pronted value proportionate to the gridsize */ if ((G.vd->grid) < 0.01) strcpy(conv_float, "%.6f"); @@ -1997,20 +2054,12 @@ static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth EditFace *efa = EM_get_face_for_index(index); if (efa->h==0) { - GPU_enable_material(efa->mat_nr+1, NULL); + set_gl_material(efa->mat_nr+1); return 1; - } - else + } else { return 0; + } } - -static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index) -{ - EditFace *efa = EM_get_face_for_index(index); - - return (efa->h==0); -} - static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt) { Mesh *me = ob->data; @@ -2033,21 +2082,9 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived EM_init_index_arrays(1, 1, 1); if(dt>OB_WIRE) { - if(CHECK_OB_DRAWTEXTURE(G.vd, dt)) { - if(draw_glsl_material(ob, dt)) { - glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); - - finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material, - draw_em_fancy__setGLSLFaceOpts, NULL); - GPU_disable_material(); - - glFrontFace(GL_CCW); - } - else { - draw_mesh_textured(ob, finalDM, 0); - } - } - else { + if( CHECK_OB_DRAWTEXTURE(G.vd, dt) ) { + draw_mesh_textured(ob, finalDM, 0); + } else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED); glEnable(GL_LIGHTING); @@ -2171,7 +2208,6 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived if(dt>OB_WIRE) { glDepthMask(1); bglPolygonOffset(0.0); - GPU_disable_material(); } EM_free_index_arrays(); @@ -2190,9 +2226,8 @@ static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) drawFacesSolid() doesn't draw the transparent faces */ if(ob->dtx & OB_DRAWTRANSP) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - dm->drawFacesSolid(dm, GPU_enable_material); + dm->drawFacesSolid(dm, set_gl_material); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - GPU_disable_material(); } else { dm->drawEdges(dm, 0); @@ -2277,19 +2312,7 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) draw_mesh_object_outline(ob, dm); } - if(draw_glsl_material(ob, dt)) { - glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); - - dm->drawFacesGLSL(dm, GPU_enable_material); - if(get_property(ob, "Text")) - draw_mesh_text(ob, 1); - GPU_disable_material(); - - glFrontFace(GL_CCW); - } - else { - draw_mesh_textured(ob, dm, faceselect); - } + draw_mesh_textured(ob, dm, faceselect); if(!faceselect) { if(base->flag & SELECT) @@ -2300,17 +2323,18 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->drawLooseEdges(dm); } } - else if(dt==OB_SOLID) { - if((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) + else if(dt==OB_SOLID ) { + + if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { draw_mesh_object_outline(ob, dm); + } glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED ); glEnable(GL_LIGHTING); glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); - dm->drawFacesSolid(dm, GPU_enable_material); - GPU_disable_material(); + dm->drawFacesSolid(dm, set_gl_material); glFrontFace(GL_CCW); glDisable(GL_LIGHTING); @@ -2328,8 +2352,7 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) if(ob==OBACT) { do_draw= 0; if( (G.f & G_WEIGHTPAINT)) { - /* enforce default material settings */ - GPU_enable_material(0, NULL); + set_gl_material(0); /* enforce defmaterial settings */ /* but set default spec */ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); @@ -2344,8 +2367,6 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1); glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); - - GPU_disable_material(); } else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) { dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1); @@ -2364,7 +2385,7 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->release(dm); shadeDispList(base); dl = find_displist(&ob->disp, DL_VERTCOL); - dm= mesh_get_derived_final(ob, get_viewedit_datamask()); + dm= mesh_get_derived_final(ob, get_viewedit_datamask()); } if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { @@ -2441,7 +2462,7 @@ static int draw_mesh_object(Base *base, int dt, int flag) { Object *ob= base->object; Mesh *me= ob->data; - int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha; + int has_alpha= 0, drawlinked= 0, retval= 0; if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) { if(ob_get_key(ob)); @@ -2457,12 +2478,7 @@ static int draw_mesh_object(Base *base, int dt, int flag) cageDM = editmesh_get_derived_cage_and_final(&finalDM, get_viewedit_datamask()); - if(dt>OB_WIRE) { - // no transp in editmode, the fancy draw over goes bad then - glsl = draw_glsl_material(ob, dt); - GPU_set_object_materials(G.scene, ob, glsl, NULL); - } - + if(dt>OB_WIRE) init_gl_materials(ob, 0); // no transp in editmode, the fancy draw over goes bad then draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt); if (G.obedit!=ob && finalDM) @@ -2475,22 +2491,15 @@ static int draw_mesh_object(Base *base, int dt, int flag) else { /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */ if(me->totface<=4 || boundbox_clip(ob->obmat, (ob->bb)? ob->bb: me->bb)) { - glsl = draw_glsl_material(ob, dt); - check_alpha = check_material_alpha(base, ob, glsl); - - if(dt==OB_SOLID || glsl) { - GPU_set_object_materials(G.scene, ob, glsl, - (check_alpha)? &do_alpha_pass: NULL); - } - + if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0); draw_mesh_fancy(base, dt, flag); if(me->totvert==0) retval= 1; } } - /* GPU_set_object_materials checked if this is needed */ - if(do_alpha_pass) add_view3d_after(G.vd, base, V3D_TRANSP, flag); + /* init_gl_materials did the proper checking if this is needed */ + if(has_alpha) add_view3d_after(G.vd, base, V3D_TRANSP, flag); return retval; } @@ -2592,10 +2601,9 @@ static int drawDispListwire(ListBase *dlbase) return 0; } -static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) +static void drawDispListsolid(ListBase *lb, Object *ob) { DispList *dl; - GPUVertexAttribs gattribs; float *data, curcol[4]; float *ndata; @@ -2659,7 +2667,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) case DL_SURF: if(dl->index) { - GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); + set_gl_material(dl->col+1); if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); @@ -2667,12 +2675,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index); - GPU_disable_material(); } break; case DL_INDEX3: - GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); + + set_gl_material(dl->col+1); glVertexPointer(3, GL_FLOAT, 0, dl->verts); @@ -2685,7 +2693,6 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index); - GPU_disable_material(); if(index3_nors_incr==0) glEnableClientState(GL_NORMAL_ARRAY); @@ -2693,13 +2700,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) break; case DL_INDEX4: - GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); + + set_gl_material(dl->col+1); glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index); - - GPU_disable_material(); break; } @@ -2793,18 +2799,14 @@ static int drawDispList(Base *base, int dt) draw_index_wire= 1; } else { - if(draw_glsl_material(ob, dt)) { - GPU_set_object_materials(G.scene, ob, 1, NULL); - drawDispListsolid(lb, ob, 1); - } - else if(dt == OB_SHADED) { + if(dt==OB_SHADED) { if(ob->disp.first==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - GPU_set_object_materials(G.scene, ob, 0, NULL); + init_gl_materials(ob, 0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob, 0); + drawDispListsolid(lb, ob); } if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) { cpack(0); @@ -2831,19 +2833,15 @@ static int drawDispList(Base *base, int dt) if(dl->nors==NULL) addnormalsDispList(ob, lb); - if(draw_glsl_material(ob, dt)) { - GPU_set_object_materials(G.scene, ob, 1, NULL); - drawDispListsolid(lb, ob, 1); - } - else if(dt==OB_SHADED) { + if(dt==OB_SHADED) { if(ob->disp.first==NULL) shadeDispList(base); drawDispListshaded(lb, ob); } else { - GPU_set_object_materials(G.scene, ob, 0, NULL); + init_gl_materials(ob, 0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob, 0); + drawDispListsolid(lb, ob); } } else { @@ -2859,20 +2857,16 @@ static int drawDispList(Base *base, int dt) if(solid) { - if(draw_glsl_material(ob, dt)) { - GPU_set_object_materials(G.scene, ob, 1, NULL); - drawDispListsolid(lb, ob, 1); - } - else if(dt == OB_SHADED) { + if(dt==OB_SHADED) { dl= lb->first; if(dl && dl->col1==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - GPU_set_object_materials(G.scene, ob, 0, NULL); + init_gl_materials(ob, 0); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob, 0); + drawDispListsolid(lb, ob); } } else{ @@ -4630,8 +4624,9 @@ static void drawSolidSelect(Base *base) drawDispListwire(&ob->disp); } else if(ob->type==OB_ARMATURE) { - if(!(ob->flag & OB_POSEMODE)) + if(!(ob->flag & OB_POSEMODE)) { draw_armature(base, OB_WIRE, 0); + } } glLineWidth(1.0); @@ -5099,9 +5094,8 @@ void draw_object(Base *base, int flag) drawlattice(ob); break; case OB_ARMATURE: - if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material + if(dt>OB_WIRE) set_gl_material(0); // we use defmaterial empty_object= draw_armature(base, dt, flag); - if(dt>OB_WIRE) GPU_disable_material(); break; default: drawaxes(1.0, flag, OB_ARROWS); @@ -5144,8 +5138,9 @@ void draw_object(Base *base, int flag) } /* draw extra: after normal draw because of makeDispList */ - if(dtx && !(G.f & G_SIMULATION)) { - if(dtx & OB_AXIS) { + if(dtx) { + if(G.f & G_SIMULATION); + else if(dtx & OB_AXIS) { drawaxes(1.0f, flag, OB_ARROWS); } if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob); @@ -5416,6 +5411,19 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot } } +static int bbs_mesh_wire__setDrawOpts(void *userData, int index) +{ + struct { Mesh *me; EdgeHash *eh; int offset; } *data = userData; + MEdge *med = data->me->medge + index; + uintptr_t flags = (intptr_t)BLI_edgehash_lookup(data->eh, med->v1, med->v2); + + if (flags & 1) { + set_framebuffer_index_color(data->offset+index); + return 1; + } else + return 0; +} + /* TODO remove this - since face select mode now only works with painting */ static void bbs_mesh_solid(Object *ob) { @@ -5425,6 +5433,22 @@ static void bbs_mesh_solid(Object *ob) glColor3ub(0, 0, 0); dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0); + /* draw edges for seam marking in faceselect mode, but not when painting, + so that painting doesn't get interrupted on an edge */ + if ((G.f & G_FACESELECT) && !(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))) { + struct { Mesh *me; EdgeHash *eh; int offset; } userData; + + userData.me = me; + userData.eh = get_tface_mesh_marked_edge_info(me); + userData.offset = userData.me->totface+1; + + bglPolygonOffset(1.0); + dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOpts, (void*)&userData); + bglPolygonOffset(0.0); + + BLI_edgehash_free(userData.eh, NULL); + } + dm->release(dm); } @@ -5480,7 +5504,6 @@ void draw_object_backbufsel(Object *ob) static void draw_object_mesh_instance(Object *ob, int dt, int outline) { DerivedMesh *dm=NULL, *edm=NULL; - int glsl; if(G.obedit && ob->data==G.obedit->data) edm= editmesh_get_derived_base(); @@ -5497,10 +5520,8 @@ static void draw_object_mesh_instance(Object *ob, int dt, int outline) if(outline) draw_mesh_object_outline(ob, dm?dm:edm); - if(dm) { - glsl = draw_glsl_material(ob, dt); - GPU_set_object_materials(G.scene, ob, glsl, NULL); - } + if(dm) + init_gl_materials(ob, 0); else { glEnable(GL_COLOR_MATERIAL); BIF_ThemeColor(TH_BONE_SOLID); @@ -5511,10 +5532,8 @@ static void draw_object_mesh_instance(Object *ob, int dt, int outline) glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); glEnable(GL_LIGHTING); - if(dm) { - dm->drawFacesSolid(dm, GPU_enable_material); - GPU_disable_material(); - } + if(dm) + dm->drawFacesSolid(dm, set_gl_material); else if(edm) edm->drawMappedFaces(edm, NULL, NULL, 0); diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index d7346a1ed21..71a777c9056 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -922,11 +922,17 @@ static void draw_image_seq(ScrArea *sa) if(ibuf->rect_float && ibuf->rect==NULL) IMB_rect_from_float(ibuf); - + + if (sseq->zoom > 0) { + zoom = sseq->zoom; + } else if (sseq->zoom == 0) { + zoom = 1.0; + } else { + zoom = -1.0/sseq->zoom; + } + /* needed for gla draw */ glaDefine2DArea(&curarea->winrct); - - zoom= SEQ_ZOOM_FAC(sseq->zoom); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); zoomy = zoom; @@ -970,10 +976,7 @@ static void draw_image_seq(ScrArea *sa) setlinestyle(0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } - - /* draw grease-pencil (image aligned) */ - if (sseq->flag & SEQ_DRAW_GPENCIL) - draw_gpencil_2dimage(sa, ibuf); + if (free_ibuf) { IMB_freeImBuf(ibuf); diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 3f21d32c2d4..71f0bbef7ca 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -31,8 +31,6 @@ #include #include #include -#include -#include #ifdef HAVE_CONFIG_H #include @@ -62,7 +60,6 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_node.h" -#include "BKE_suggestions.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -77,84 +74,32 @@ #include "BIF_space.h" #include "BIF_mywindow.h" #include "BIF_resources.h" -#include "BIF_mainqueue.h" #include "BSE_filesel.h" #include "BPY_extern.h" -#include "BPY_menus.h" #include "mydevice.h" #include "blendef.h" #include "winlay.h" -/***********************/ /* - -Notes on word-wrap --- -All word-wrap functions follow the algorithm below to maintain consistency. - line The line to wrap (tabs converted to spaces) - view_width The maximum number of characters displayable in the region - This equals region_width/font_width for the region - wrap_chars Characters that allow wrapping. This equals [' ', '\t', '-'] - -def wrap(line, view_width, wrap_chars): - draw_start = 0 - draw_end = view_width - pos = 0 - for c in line: - if pos-draw_start >= view_width: - print line[draw_start:draw_end] - draw_start = draw_end - draw_end += view_width - elif c in wrap_chars: - draw_end = pos+1 - pos += 1 - print line[draw_start:] - -*/ /***********************/ - -#define TEXTXLOC 38 - -#define SUGG_LIST_SIZE 7 -#define SUGG_LIST_WIDTH 20 -#define DOC_WIDTH 40 -#define DOC_HEIGHT 10 - -#define TOOL_SUGG_LIST 0x01 -#define TOOL_DOCUMENT 0x02 - -#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */ -#define TMARK_GRP_FINDALL 0x00020000 +#define TEXTXLOC 38 /* forward declarations */ void drawtextspace(ScrArea *sa, void *spacedata); void winqreadtextspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); void txt_copy_selectbuffer (Text *text); -void draw_brackets(SpaceText *st); +void do_brackets(); -static void get_selection_buffer(Text *text); -static int check_bracket(char ch); -static int check_delim(char ch); -static int check_digit(char ch); -static int check_identifier(char ch); -static int check_whitespace(char ch); +void get_selection_buffer(Text *text); +int check_bracket(char *string); +static int check_delim(char *string); +static int check_numbers(char *string); +static int check_builtinfuncs(char *string); +static int check_specialvars(char *string); -static int get_wrap_width(SpaceText *st); -static int get_wrap_points(SpaceText *st, char *line); -static void get_suggest_prefix(Text *text, int offset); -static void confirm_suggestion(Text *text, int skipleft); - -#define TXT_MAXFINDSTR 255 -static int g_find_flags= TXT_FIND_WRAP; -static char *g_find_str= NULL; -static char *g_replace_str= NULL; - -static int doc_scroll= 0; -static double last_check_time= 0; -static int jump_to= 0; -static double last_jump= 0; +static void *last_txt_find_string= NULL; static BMF_Font *spacetext_get_font(SpaceText *st) { static BMF_Font *scr12= NULL; @@ -215,8 +160,7 @@ static void temp_char_write(char c, int accum) { void free_txt_data(void) { txt_free_cut_buffer(); - if (g_find_str) MEM_freeN(g_find_str); - if (g_replace_str) MEM_freeN(g_replace_str); + if (last_txt_find_string) MEM_freeN(last_txt_find_string); if (temp_char_buf) MEM_freeN(temp_char_buf); if (temp_char_accum) MEM_freeN(temp_char_accum); } @@ -240,279 +184,352 @@ static int render_string (SpaceText *st, char *in) { return r; } -static int find_builtinfunc(char *string) +void get_format_string(SpaceText *st) { - int a, i; - char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def", - "del", "elif", "else", "except", "exec", "finally", - "for", "from", "global", "if", "import", "in", - "is", "lambda", "not", "or", "pass", "print", - "raise", "return", "try", "while", "yield"}; - for (a=0; a<30; a++) { - i = 0; - while (1) { - if (builtinfuncs[a][i]=='\0') { - if (check_identifier(string[i])) - i = -1; - break; - } else if (string[i]!=builtinfuncs[a][i]) { - i = -1; - break; - } - i++; - } - if (i>0) break; - } - return i; -} - -static int find_specialvar(char *string) -{ - int i = 0; - if (string[0]=='d' && string[1]=='e' && string[2]=='f') - i = 3; - else if (string[0]=='c' && string[1]=='l' && string[2]=='a' && string[3]=='s' && string[4]=='s') - i = 5; - if (i==0 || check_identifier(string[i])) - return -1; - return i; -} - -static void print_format(SpaceText *st, TextLine *line) { - int i, a; - char *s, *f; - s = line->line; - f = line->format; - for (a=0; *s; s++) { - if (*s == '\t') { - for (i=st->tabnumber-(a%st->tabnumber); i>0; i--) - printf(" "), f++, a++; - } else - printf("%c", *s), f++, a++; - } - printf("\n%s [%#x]\n", line->format, (int) (f[strlen(f)+1])); -} - -/* Ensures the format string for the given line is long enough, reallocating as needed */ -static int check_format_len(TextLine *line, unsigned int len) { - if (line->format) { - if (strlen(line->format) < len) { - MEM_freeN(line->format); - line->format = MEM_mallocN(len+2, "SyntaxFormat"); - if (!line->format) return 0; - } - } else { - line->format = MEM_mallocN(len+2, "SyntaxFormat"); - if (!line->format) return 0; - } - return 1; -} - -/* Formats the specified line and if allowed and needed will move on to the - * next line. The format string contains the following characters: - * '_' Whitespace - * '#' Comment text - * '!' Punctuation and other symbols - * 'n' Numerals - * 'l' String letters - * 'v' Special variables (class, def) - * 'b' Built-in names (print, for, etc.) - * 'q' Other text (identifiers, etc.) - * It is terminated with a null-terminator '\0' followed by a continuation - * flag indicating whether the line is part of a multi-line string. - */ -void txt_format_line(SpaceText *st, TextLine *line, int do_next) { - char *str, *fmt, orig, cont, find, prev = ' '; - int len, i; - - /* Get continuation from previous line */ - if (line->prev && line->prev->format != NULL) { - fmt= line->prev->format; - cont = fmt[strlen(fmt)+1]; /* Just after the null-terminator */ - } else cont = 0; - - /* Get original continuation from this line */ - if (line->format != NULL) { - fmt= line->format; - orig = fmt[strlen(fmt)+1]; /* Just after the null-terminator */ - } else orig = 0xFF; - - render_string(st, line->line); - str = temp_char_buf; - len = strlen(str); - if (!check_format_len(line, len)) return; - fmt = line->format; - - while (*str) { - /* Handle escape sequences by skipping both \ and next char */ - if (*str == '\\') { - *fmt = prev; fmt++; str++; - if (*str == '\0') break; - *fmt = prev; fmt++; str++; - continue; - } - /* Handle continuations */ - else if (cont) { - /* Triple strings ("""...""" or '''...''') */ - if (cont & TXT_TRISTR) { - find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; - if (*str==find && *(str+1)==find && *(str+2)==find) { - *fmt = 'l'; fmt++; str++; - *fmt = 'l'; fmt++; str++; - cont = 0; - } - /* Handle other strings */ - } else { - find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; - if (*str == find) cont = 0; - } - *fmt = 'l'; - } - /* Not in a string... */ - else { - /* Deal with comments first */ - if (prev == '#' || *str == '#') - *fmt = '#'; - /* Strings */ - else if (*str == '"' || *str == '\'') { - find = *str; - cont = (*str== '"') ? TXT_DBLQUOTSTR : TXT_SNGQUOTSTR; - if (*(str+1) == find && *(str+2) == find) { - *fmt = 'l'; fmt++; str++; - *fmt = 'l'; fmt++; str++; - cont |= TXT_TRISTR; - } - *fmt = 'l'; - } - /* Whitespace (all ws. has been converted to spaces) */ - else if (*str == ' ') - *fmt = '_'; - /* Numbers (digits not part of an identifier and periods followed by digits) */ - else if ((prev != 'q' && check_digit(*str)) || (*str == '.' && check_digit(*(str+1)))) - *fmt = 'n'; - /* Punctuation */ - else if (check_delim(*str)) - *fmt = '!'; - /* Identifiers and other text (no previous ws. or delims. so text continues) */ - else if (prev == 'q') - *fmt = 'q'; - /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ - else { - /* Special vars(v) or built-in keywords(b) */ - if ((i=find_specialvar(str)) != -1) - prev = 'v'; - else if ((i=find_builtinfunc(str)) != -1) - prev = 'b'; - if (i>0) { - while (i>1) { - *fmt = prev; fmt++; str++; - i--; - } - *fmt = prev; - } else - *fmt = 'q'; - } - } - prev = *fmt; - fmt++; - str++; - } - - /* Terminate and add continuation char */ - *fmt = '\0'; fmt++; - *fmt = cont; - - /* Debugging */ - //print_format(st, line); - - /* If continuation has changed and we're allowed, process the next line */ - if (cont!=orig && do_next && line->next) { - txt_format_line(st, line->next, do_next); - } -} - -void txt_format_text(SpaceText *st) -{ - TextLine *linep; - - if (!st->text) return; - - for (linep=st->text->lines.first; linep; linep=linep->next) - txt_format_line(st, linep, 0); -} - -static void format_draw_color(char formatchar) { - switch (formatchar) { - case '_': /* Whitespace */ - break; - case '!': /* Symbols */ - BIF_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f); - break; - case '#': /* Comments */ - BIF_ThemeColor(TH_SYNTAX_C); - break; - case 'n': /* Numerals */ - BIF_ThemeColor(TH_SYNTAX_N); - break; - case 'l': /* Strings */ - BIF_ThemeColor(TH_SYNTAX_L); - break; - case 'v': /* Specials: class, def */ - BIF_ThemeColor(TH_SYNTAX_V); - break; - case 'b': /* Keywords: for, print, etc. */ - BIF_ThemeColor(TH_SYNTAX_B); - break; - case 'q': /* Other text (identifiers) */ - default: - BIF_ThemeColor(TH_TEXT); - break; - } -} - -static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format) -{ - int basex, i, a, len, start, end, max, lines; + Text *text = st->text; + TextLine *tmp; + char *in_line; + char format[2000], check[200], other[2]; + unsigned char c; + int spot, letter, tabs, mem_amount; + size_t a, b, len; - len= render_string(st, str); - str= temp_char_buf; - max= w/spacetext_get_fontwidth(st); - if (max<8) max= 8; - basex= x; - - lines= 1; - start= 0; - end= max; - for (i=0; i= max) { - /* Draw the visible portion of text on the overshot line */ - for (a=start; ashowsyntax && format) format_draw_color(format[a]); - glRasterPos2i(x, y); - BMF_DrawCharacter(spacetext_get_font(st), str[a]); - x += BMF_GetCharacterWidth(spacetext_get_font(st), str[a]); - } - y -= st->lheight; - x= basex; - lines++; - start= end; - end += max; - } else if (str[i]==' ' || str[i]=='-') { - end = i+1; + if(!text) return; + tmp = text->lines.first; + + while(tmp) { + in_line = tmp->line; + + len = strlen(in_line); + /* weak code... but we dont want crashes (ton) */ + if(len>2000-1) { + if (tmp->format) MEM_freeN(tmp->format); + tmp->format= NULL; } + else { + + spot = 0; + tabs = 0; + //see how many tabs we have + for(a = 0; a tabnumber)-tabs)+2)+len; // +2 for good measure + if (tmp->format) MEM_freeN(tmp->format); + tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); + + for (a = 0; a < len; a++) { + c = (unsigned char) in_line[a]; + + check[0] = c; + check[1] = '\0'; + + if (check_delim(check)) + { + switch (c) { + case '\"': + if(in_line[a] == '\"' && in_line[a+1] == '\"' && in_line[a+2] == '\"') { + format[spot] = format[spot+1] = format[spot+2] = 'l'; + spot +=3; + a += 3; + while(in_line[a] != '\"' || in_line[a-1] != '\"' || in_line[a-2] != '\"') { + c = (unsigned char) in_line[a]; + if(a >= len) { + format[spot] = '\0'; + memcpy(tmp->format, format, strlen(format)); + if(!(tmp= tmp->next)) { + return; + } else { + in_line = tmp->line; + len = strlen(in_line); + tabs = 0; + for(b = 0; b tabnumber)-tabs)+2)+len; + if (tmp->format) MEM_freeN(tmp->format); + tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); + a = 0; spot = 0; + } + } else { + if(c == '\t' || c == ' ') { + if(c == '\t') { + for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { + format[spot] = ' '; + spot++; + } + a++; + } else { + format[spot] = ' '; + a++; spot++; + } + } else { + format[spot] = 'l'; + a++; spot++; + } + } + } + format[spot] = 'l'; + spot++; + } else { + format[spot] = 'l'; + a++; spot++; + while(in_line[a] != '\"') { + c = (unsigned char) in_line[a]; + if(a >= len) { + format[spot] = '\0'; + memcpy(tmp->format, format, strlen(format)); + if(!(tmp= tmp->next)) { + return; + } else { + in_line = tmp->line; + len = strlen(in_line); + for(b = 0; b tabnumber)-tabs)+2)+len; + if (tmp->format) MEM_freeN(tmp->format); + tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); + a = 0; spot = 0; + } + } + if(c == '\t' || c == ' ') { + if(c == '\t') { + for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { + format[spot] = ' '; + spot++; + } + a++; + } else { + format[spot] = ' '; + a++; spot++; + } + } else { + format[spot] = 'l'; + a++; spot++; + } + } + format[spot] = 'l'; + spot++; + } + break; + case '\'': + if(in_line[a] == '\'' && in_line[a+1] == '\'' && in_line[a+2] == '\'') { + format[spot] = format[spot+1] = format[spot+2] = 'l'; + spot +=3; + a += 3; + while(in_line[a] != '\'' || in_line[a-1] != '\'' || in_line[a-2] != '\'') { + c = (unsigned char) in_line[a]; + if(a >= len) { + format[spot] = '\0'; + memcpy(tmp->format, format, strlen(format)); + if(!(tmp= tmp->next)) { + return; + } else { + in_line = tmp->line; + len = strlen(in_line); + tabs = 0; + for(b = 0; b tabnumber)-tabs)+2)+len; + if (tmp->format) MEM_freeN(tmp->format); + tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); + a = 0; spot = 0; + } + } else { + if(c == '\t' || c == ' ') { + if(c == '\t') { + for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { + format[spot] = ' '; + spot++; + } + a++; + } else { + format[spot] = ' '; + a++; spot++; + } + } else { + format[spot] = 'l'; + a++; spot++; + } + } + } + format[spot] = 'l'; + spot++; + } else { + format[spot] = 'l'; + a++; spot++; + while(in_line[a] != '\'') { + c = (unsigned char) in_line[a]; + if(a >= len) { + format[spot] = '\0'; + memcpy(tmp->format, format, strlen(format)); + if(!(tmp= tmp->next)) { + return; + } else { + in_line = tmp->line; + len = strlen(in_line); + for(b = 0; b tabnumber)-tabs)+2)+len; + if (tmp->format) MEM_freeN(tmp->format); + tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); + a = 0; spot = 0; + } + } + if(c == '\t' || c == ' ') { + if(c == '\t') { + for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { + format[spot] = ' '; + spot++; + } + a++; + } else { + format[spot] = ' '; + a++; spot++; + } + } else { + format[spot] = 'l'; + a++; spot++; + } + } + format[spot] = 'l'; + spot++; + } + break; + case '#': + while(atabnumber-(spot%st->tabnumber); b > 0; b--) { + format[spot] = '#'; + spot++; + } + a++; + } else { + format[spot] = '#'; + a++; spot++; + } + } else { + format[spot] = '#'; + a++; spot++; + } + } + break; + case ' ': + format[spot] = ' '; + spot++; + break; + case '\t': + for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { + format[spot] = ' '; + spot++; + } + break; + default: + format[spot] = 'q'; + spot++; + + break; + } + } else if (check_numbers(check)) { + while (a < len) { + c = (unsigned char) in_line[a]; + other[0] = c; + other[1] = '\0'; + if (check_delim(other) && c != '.') { + a--; break; + } else { + format[spot] = 'n'; + a++; spot++; + } + } + } else { + letter = 0; + while (a < len) { + c = (unsigned char) in_line[a]; + other[0] = c; + other[1] = '\0'; + if (check_delim(other)) { + a--; + break; + } else { + check[letter] = (unsigned char) in_line[a]; + letter++; + a++; + } + } + check[letter] = '\0'; + if (check_builtinfuncs(check)) { + for (b = 0; b < strlen(check); b++) { + format[spot] = 'b'; + spot++; + } + } else if (check_specialvars(check)) { /*If TRUE then color and color next word*/ + for (b = 0; b < strlen(check); b++) { + format[spot] = 'b'; + spot++; + } + a++; + format[spot] = 'q'; + spot++; a++; + letter = 0; + while (a < len) { + c = (unsigned char) in_line[a]; + other[0] = c; + other[1] = '\0'; + if (check_delim(other)) { + a--; + break; + } else { + check[letter] = (unsigned char) in_line[a]; + letter++; + a++; + } + } + check[letter] = '\0'; + for (b = 0; b < strlen(check); b++) { + format[spot] = 'v'; + spot++; + } + }else { + for (b = 0; b < strlen(check); b++) { + format[spot] = 'q'; + spot++; + } + } + } + } + format[spot] = '\0'; + memcpy(tmp->format, format, strlen(format)); + } + + tmp = tmp->next; } - /* Draw the remaining text */ - for (a=start; ashowsyntax && format) format_draw_color(format[a]); - glRasterPos2i(x, y); - BMF_DrawCharacter(spacetext_get_font(st), str[a]); - x += BMF_GetCharacterWidth(spacetext_get_font(st), str[a]); - } - return lines; } -static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) -{ +static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) { int r=0, w= 0; char *in; int *acc; @@ -527,15 +544,40 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra if (draw) { if(st->showsyntax && format) { int amount, a; + char out[2]; format = format+cshift; amount = strlen(in); for(a = 0; a < amount; a++) { - format_draw_color(format[a]); + out[0] = (unsigned char) in[a]; + out[1] = '\0'; + switch (format[a]) { + case 'l': + BIF_ThemeColor(TH_SYNTAX_L); + break; + case 'b': + BIF_ThemeColor(TH_SYNTAX_B); + break; + case '#': + BIF_ThemeColor(TH_SYNTAX_C); + break; + case 'v': + BIF_ThemeColor(TH_SYNTAX_V); + break; + case 'n': + BIF_ThemeColor(TH_SYNTAX_N); + break; + case 'q': + BIF_ThemeColor(TH_TEXT); + break; + default: + BIF_ThemeColor(TH_TEXT); + break; + } glRasterPos2i(x, y); - BMF_DrawCharacter(spacetext_get_font(st), in[a]); - x = x+BMF_GetCharacterWidth(spacetext_get_font(st), in[a]); + BMF_DrawString(spacetext_get_font(st), out); + x = x+BMF_GetStringWidth(spacetext_get_font(st), out); } } else { glRasterPos2i(x, y); @@ -567,6 +609,14 @@ static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) else { linep= &text->curl; charp= &text->curc; } y= (curarea->winy - y)/st->lheight; + + y-= txt_get_span(text->lines.first, *linep) - st->top; + + if (y>0) { + while (y-- != 0) if((*linep)->next) *linep= (*linep)->next; + } else if (y<0) { + while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev; + } if(st->showlinenrs) x-= TXT_OFFSET+TEXTXLOC; @@ -576,353 +626,97 @@ static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) if (x<0) x= 0; x = (x/spacetext_get_fontwidth(st)) + st->left; - if (st->wordwrap) { - int i, j, endj, curs, max, chop, start, end, chars, loop; - char ch; - - /* Point to first visible line */ - *linep= text->lines.first; - for (i=0; itop && (*linep)->next; i++) *linep= (*linep)->next; - - max= get_wrap_width(st); - - loop= 1; - while (loop && *linep) { - start= 0; - end= max; - chop= 1; - chars= 0; - curs= 0; - endj= 0; - for (i=0, j=0; loop; j++) { - - /* Mimic replacement of tabs */ - ch= (*linep)->line[j]; - if (ch=='\t') { - chars= st->tabnumber-i%st->tabnumber; - ch= ' '; - } else - chars= 1; - - while (chars--) { - /* Gone too far, go back to last wrap point */ - if (y<0) { - *charp= endj; - loop= 0; - break; - /* Exactly at the cursor, done */ - } else if (y==0 && i-start==x) { - *charp= curs= j; - loop= 0; - break; - /* Prepare curs for next wrap */ - } else if (i-end==x) { - curs= j; - } - if (i-start>=max) { - if (chop) endj= j; - y--; - start= end; - end += max; - chop= 1; - if (y==0 && i-start>=x) { - *charp= curs; - loop= 0; - break; - } - } else if (ch==' ' || ch=='-' || ch=='\0') { - if (y==0 && i-start>=x) { - *charp= curs; - loop= 0; - break; - } - end = i+1; - endj = j; - chop= 0; - } - i++; - } - if (ch=='\0') break; - } - if (!loop || y<0) break; - - if (!(*linep)->next) { - *charp= (*linep)->len; - break; - } - - /* On correct line but didn't meet cursor, must be at end */ - if (y==0) { - *charp= (*linep)->len; - break; - } - *linep= (*linep)->next; - y--; - } - - } else { - y-= txt_get_span(text->lines.first, *linep) - st->top; - - if (y>0) { - while (y-- != 0) if((*linep)->next) *linep= (*linep)->next; - } else if (y<0) { - while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev; - } - - - w= render_string(st, (*linep)->line); - if(xlen; - } + w= render_string(st, (*linep)->line); + if(xlen; + if(!sel) txt_pop_sel(text); } -static int get_wrap_width(SpaceText *st) { - int x, max; - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - max= (curarea->winx-x)/spacetext_get_fontwidth(st); - return max>8 ? max : 8; -} - -/* Returns the number of wrap points (or additional lines) in the given string */ -static int get_wrap_points(SpaceText *st, char *line) { - int start, end, taboffs, i, max, count; - - if (!st->wordwrap) return 0; - - end= max= get_wrap_width(st); - count= taboffs= start= 0; - - for (i=0; line[i]!='\0'; i++) { - if (i-start+taboffs>=max) { - count++; - start= end; - end += max; - taboffs= 0; - } else if (line[i]==' ' || line[i]=='\t' || line[i]=='-') { - end = i+1; - if (line[i]=='\t') - taboffs += st->tabnumber-(i-start)%st->tabnumber; - } - } - return count; -} - -/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */ -static void wrap_offset(SpaceText *st, TextLine *linein, int cursin, int *offl, int *offc) { - Text *text; - TextLine *linep; - int i, j, start, end, chars, max, chop; - char ch; - - *offl= *offc= 0; - - if (!st->text) return; - if (!st->wordwrap) return; - - text= st->text; - - /* Move pointer to first visible line (top) */ - linep= text->lines.first; - i= st->top; - while (i>0 && linep) { - if (linep == linein) return; /* Line before top */ - linep= linep->next; - i--; - } - - max= get_wrap_width(st); - - while (linep) { - start= 0; - end= max; - chop= 1; - chars= 0; - *offc= 0; - for (i=0, j=0; linep->line[j]!='\0'; j++) { - - /* Mimic replacement of tabs */ - ch= linep->line[j]; - if (ch=='\t') { - chars= st->tabnumber-i%st->tabnumber; - if (linep==linein && i=max) { - if (chop && linep==linein && i >= cursin) - return; - (*offl)++; - *offc -= end-start; - start= end; - end += max; - chop= 1; - } else if (ch==' ' || ch=='-') { - end = i+1; - chop= 0; - if (linep==linein && i >= cursin) - return; - } - i++; - } - } - if (linep==linein) break; - linep= linep->next; - } -} - -static int get_char_pos(SpaceText *st, char *line, int cur) { - int a=0, i; - for (i=0; itabnumber-a%st->tabnumber; - else - a++; - } - return a; -} - -static void draw_markers(SpaceText *st) { - Text *text= st->text; - TextMarker *marker, *next; - TextLine *top, *bottom, *line; - int offl, offc, i, cy, x1, x2, y1, y2, x, y; - - for (i=st->top, top= text->lines.first; top->next && i>0; i--) top= top->next; - for (i=st->viewlines-1, bottom=top; bottom->next && i>0; i--) bottom= bottom->next; - - for (marker= text->markers.first; marker; marker= next) { - next= marker->next; - for (cy= 0, line= top; line; cy++, line= line->next) { - if (cy+st->top==marker->lineno) { - /* Remove broken markers */ - if (marker->end>line->len || marker->start>marker->end) { - BLI_freelinkN(&text->markers, marker); - break; - } - - wrap_offset(st, line, marker->start, &offl, &offc); - x1= get_char_pos(st, line->line, marker->start) - st->left + offc; - y1= cy + offl; - wrap_offset(st, line, marker->end, &offl, &offc); - x2= get_char_pos(st, line->line, marker->end) - st->left + offc; - y2= cy + offl; - - glColor3ub(marker->color[0], marker->color[1], marker->color[2]); - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y= curarea->winy-3; - - if (y1==y2) { - y -= y1*st->lheight; - glBegin(GL_LINE_LOOP); - glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); - glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); - glEnd(); - } else { - y -= y1*st->lheight; - glBegin(GL_LINE_STRIP); - glVertex2i(curarea->winx, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); - glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); - glVertex2i(curarea->winx, y-st->lheight); - glEnd(); - y-=st->lheight; - for (i=y1+1; iwinx, y); - glVertex2i(x, y-st->lheight); - glVertex2i(curarea->winx, y-st->lheight); - glEnd(); - y-=st->lheight; - } - glBegin(GL_LINE_STRIP); - glVertex2i(x, y); - glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); - glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); - glVertex2i(x, y-st->lheight); - glEnd(); - } - - break; - } - if (line==bottom) break; - } - } -} - static void draw_cursor(SpaceText *st) { + int h, x, i; Text *text= st->text; - int vcurl, vcurc, vsell, vselc, hidden=0; - int offl, offc, x, y, w, i; + TextLine *linef, *linel; + int charf, charl; - /* Draw the selection */ - if (text->curl!=text->sell || text->curc!=text->selc) { + if (text->curl==text->sell && text->curc==text->selc) { + x= text_draw(st, text->curl->line, st->left, text->curc, 0, 0, 0, NULL); - /* Convert all to view space character coordinates */ - wrap_offset(st, text->curl, text->curc, &offl, &offc); - vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl; - vcurc = get_char_pos(st, text->curl->line, text->curc) - st->left + offc; - wrap_offset(st, text->sell, text->selc, &offl, &offc); - vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; - vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + if (x) { + h= txt_get_span(text->lines.first, text->curl) - st->top; - if (vcurc<0) vcurc=0; - if (vselc<0) vselc=0, hidden=1; - - BIF_ThemeColor(TH_SHADE2); - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y= curarea->winy-2; - - if (vcurl==vsell) { - y -= vcurl*st->lheight; - if (vcurc < vselc) - glRecti(x+vcurc*spacetext_get_fontwidth(st)-1, y, x+vselc*spacetext_get_fontwidth(st), y-st->lheight); - else - glRecti(x+vselc*spacetext_get_fontwidth(st)-1, y, x+vcurc*spacetext_get_fontwidth(st), y-st->lheight); - } else { - int froml, fromc, tol, toc; - if (vcurl < vsell) { - froml= vcurl; tol= vsell; - fromc= vcurc; toc= vselc; - } else { - froml= vsell; tol= vcurl; - fromc= vselc; toc= vcurc; - } - y -= froml*st->lheight; - glRecti(x+fromc*spacetext_get_fontwidth(st)-1, y, curarea->winx, y-st->lheight); y-=st->lheight; - for (i=froml+1; iwinx, y-st->lheight), y-=st->lheight; - glRecti(x-4, y, x+toc*spacetext_get_fontwidth(st), y-st->lheight); y-=st->lheight; + BIF_ThemeColor(TH_HILITE); + + glRecti(x-1, curarea->winy-st->lheight*(h)-2, x+1, curarea->winy-st->lheight*(h+1)-2); } } else { - wrap_offset(st, text->sell, text->selc, &offl, &offc); - vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; - vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; - if (vselc<0) vselc=0, hidden=1; + int span= txt_get_span(text->curl, text->sell); + + if (span<0) { + linef= text->sell; + charf= text->selc; + + linel= text->curl; + charl= text->curc; + } else if (span>0) { + linef= text->curl; + charf= text->curc; + + linel= text->sell; + charl= text->selc; + } else { + linef= linel= text->curl; + + if (text->curcselc) { + charf= text->curc; + charl= text->selc; + } else { + charf= text->selc; + charl= text->curc; + } + } + + /* Walk to the beginning of visible text */ + h= txt_get_span(text->lines.first, linef) - st->top; + while (h++<-1 && linef!=linel) linef= linef->next; + + x= text_draw(st, linef->line, st->left, charf, 0, 0, 0, NULL); + + BIF_ThemeColor(TH_SHADE2); + + if(st->showlinenrs) { + if (!x) x= TXT_OFFSET + TEXTXLOC -4; + } else { + if (!x) x= TXT_OFFSET - 4; + } + + while (linef && linef != linel) { + h= txt_get_span(text->lines.first, linef) - st->top; + if (h>st->viewlines) break; + + glRecti(x, curarea->winy-st->lheight*(h)-2, curarea->winx, curarea->winy-st->lheight*(h+1)-2); + if(st->showlinenrs) + glRecti(TXT_OFFSET+TEXTXLOC-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET+TEXTXLOC, curarea->winy-st->lheight*(h+2)-2); + else + glRecti(TXT_OFFSET-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET, curarea->winy-st->lheight*(h+2)-2); + + if(st->showlinenrs) + x= TXT_OFFSET + TEXTXLOC; + else + x= TXT_OFFSET; + + linef= linef->next; + } + + h= txt_get_span(text->lines.first, linef) - st->top; + + i= text_draw(st, linel->line, st->left, charl, 0, 0, 0, NULL); + if(i) glRecti(x, curarea->winy-st->lheight*(h)-2, i, curarea->winy-st->lheight*(h+1)-2); + } - if (!hidden) { - /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - x += vselc*spacetext_get_fontwidth(st); - y= curarea->winy-2 - vsell*st->lheight; - - if (st->overwrite) { - char ch= text->sell->line[text->selc]; - if (!ch) ch= ' '; - w= BMF_GetCharacterWidth(spacetext_get_font(st), ch); - BIF_ThemeColor(TH_HILITE); - glRecti(x, y-st->lheight-1, x+w, y-st->lheight+1); - } else { - BIF_ThemeColor(TH_HILITE); - glRecti(x-1, y, x+1, y-st->lheight); - } - } + do_brackets(); + BIF_ThemeColor(TH_TEXT); } static void calc_text_rcts(SpaceText *st) @@ -1065,38 +859,6 @@ static void screen_skip(SpaceText *st, int lines) if (st->top<0) st->top= 0; } -static void cursor_skip(SpaceText *st, int lines, int sel) -{ - Text *text; - TextLine **linep; - int oldl, oldc, *charp; - - if (!st) return; - if (st->spacetype != SPACE_TEXT) return; - if (!st->text) return; - - text= st->text; - - if (sel) linep= &text->sell, charp= &text->selc; - else linep= &text->curl, charp= &text->curc; - oldl= txt_get_span(text->lines.first, *linep); - oldc= *charp; - - while (lines>0 && (*linep)->next) { - *linep= (*linep)->next; - lines--; - } - while (lines<0 && (*linep)->prev) { - *linep= (*linep)->prev; - lines++; - } - - if (*charp > (*linep)->len) *charp= (*linep)->len; - - if (!sel) txt_pop_sel(st->text); - txt_undo_add_toop(st->text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp); -} - /* * mode 1 == view scroll * mode 2 == scrollbar @@ -1112,8 +874,10 @@ static void do_textscroll(SpaceText *st, int mode) st->flags|= ST_SCROLL_SELECT; - scrarea_do_windraw(curarea); - screen_swapbuffers(); + glDrawBuffer(GL_FRONT); + uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT); + bglFlush(); + glDrawBuffer(GL_BACK); getmouseco_areawin(mval); old[0]= hold[0]= mval[0]; @@ -1131,12 +895,9 @@ static void do_textscroll(SpaceText *st, int mode) if (delta[0] || delta[1]) { screen_skip(st, delta[1]); - if (st->wordwrap) { - st->left= 0; - } else { - st->left+= delta[0]; - if (st->left<0) st->left= 0; - } + st->left+= delta[0]; + if (st->left<0) st->left= 0; + scrarea_do_windraw(curarea); screen_swapbuffers(); @@ -1151,8 +912,10 @@ static void do_textscroll(SpaceText *st, int mode) } st->flags^= ST_SCROLL_SELECT; - scrarea_do_windraw(curarea); - screen_swapbuffers(); + glDrawBuffer(GL_FRONT); + uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT); + bglFlush(); + glDrawBuffer(GL_BACK); } static void do_selection(SpaceText *st, int selecting) @@ -1194,7 +957,7 @@ static void do_selection(SpaceText *st, int selecting) scrarea_do_windraw(curarea); screen_swapbuffers(); - } else if (!st->wordwrap && (mval[0]<0 || mval[0]>curarea->winx)) { + } else if (mval[0]<0 || mval[0]>curarea->winx) { if (mval[0]>curarea->winx) st->left++; else if (mval[0]<0 && st->left>0) st->left--; @@ -1223,409 +986,19 @@ static void do_selection(SpaceText *st, int selecting) if (sell!=linep2 || selc!=charp2) txt_undo_add_toop(st->text, UNDO_STO, sell, selc, linep2, charp2); - - pop_space_text(st); -} - -static int do_suggest_select(SpaceText *st) -{ - SuggItem *item, *first, *last, *sel; - short mval[2]; - TextLine *tmp; - int l, x, y, w, h, i; - int tgti, *top; - - if (!st || !st->text) return 0; - if (!texttool_text_is_active(st->text)) return 0; - - first = texttool_suggest_first(); - last = texttool_suggest_last(); - sel = texttool_suggest_selected(); - top = texttool_suggest_top(); - - if (!last || !first) - return 0; - - /* Count the visible lines to the cursor */ - for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); - if (l<0) return 0; - - if(st->showlinenrs) { - x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; - } else { - x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; - } - y = curarea->winy - st->lheight*l - 2; - - w = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20; - h = SUGG_LIST_SIZE*st->lheight + 8; - - getmouseco_areawin(mval); - - if (mval[0]next; i++, item=item->next); - - /* Work out the target item index in the visible list */ - tgti = (y-mval[1]-4) / st->lheight; - if (tgti<0 || tgti>SUGG_LIST_SIZE) - return 1; - - for (i=tgti; i>0 && item->next; i--, item=item->next); - if (item) - texttool_suggest_select(item); - return 1; -} - -static void pop_suggest_list() { - SuggItem *item, *sel; - int *top, i; - - item= texttool_suggest_first(); - sel= texttool_suggest_selected(); - top= texttool_suggest_top(); - - i= 0; - while (item && item != sel) { - item= item->next; - i++; - } - if (i > *top+SUGG_LIST_SIZE-1) - *top= i-SUGG_LIST_SIZE+1; - else if (i < *top) - *top= i; -} - -void draw_documentation(SpaceText *st) -{ - TextLine *tmp; - char *docs, buf[DOC_WIDTH+1], *p; - int len, i, br, lines; - int boxw, boxh, l, x, y, top; - - if (!st || !st->text) return; - if (!texttool_text_is_active(st->text)) return; - - docs = texttool_docs_get(); - - if (!docs) return; - - /* Count the visible lines to the cursor */ - for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); - if (l<0) return; - - if(st->showlinenrs) { - x= spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; - } else { - x= spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; - } - if (texttool_suggest_first()) { - x += SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 50; - } - - top= y= curarea->winy - st->lheight*l - 2; - len= strlen(docs); - boxw= DOC_WIDTH*spacetext_get_fontwidth(st) + 20; - boxh= (DOC_HEIGHT+1)*st->lheight; - - /* Draw panel */ - BIF_ThemeColor(TH_BACK); - glRecti(x, y, x+boxw, y-boxh); - BIF_ThemeColor(TH_SHADE1); - glBegin(GL_LINE_LOOP); - glVertex2i(x, y); - glVertex2i(x+boxw, y); - glVertex2i(x+boxw, y-boxh); - glVertex2i(x, y-boxh); - glEnd(); - glBegin(GL_LINE_LOOP); - glVertex2i(x+boxw-10, y-7); - glVertex2i(x+boxw-4, y-7); - glVertex2i(x+boxw-7, y-2); - glEnd(); - glBegin(GL_LINE_LOOP); - glVertex2i(x+boxw-10, y-boxh+7); - glVertex2i(x+boxw-4, y-boxh+7); - glVertex2i(x+boxw-7, y-boxh+2); - glEnd(); - BIF_ThemeColor(TH_TEXT); - - i= 0; br= DOC_WIDTH; lines= -doc_scroll; - for (p=docs; *p; p++) { - if (*p == '\r' && *(++p) != '\n') *(--p)= '\n'; /* Fix line endings */ - if (*p == ' ' || *p == '\t') - br= i; - else if (*p == '\n') { - buf[i]= '\0'; - if (lines>=0) { - y -= st->lheight; - text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL); - } - i= 0; br= DOC_WIDTH; lines++; - } - buf[i++]= *p; - if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */ - buf[br]= '\0'; - if (lines>=0) { - y -= st->lheight; - text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL); - } - p -= i-br-1; /* Rewind pointer to last break */ - i= 0; br= DOC_WIDTH; lines++; - } - if (lines >= DOC_HEIGHT) break; - } - if (doc_scroll > 0 && lines < DOC_HEIGHT) { - doc_scroll--; - draw_documentation(st); - } -} - -void draw_suggestion_list(SpaceText *st) -{ - SuggItem *item, *first, *last, *sel; - TextLine *tmp; - char str[SUGG_LIST_WIDTH+1]; - int w, boxw=0, boxh, i, l, x, y, b, *top; - - if (!st || !st->text) return; - if (!texttool_text_is_active(st->text)) return; - - first = texttool_suggest_first(); - last = texttool_suggest_last(); - - if (!first || !last) return; - - pop_suggest_list(); - sel = texttool_suggest_selected(); - top = texttool_suggest_top(); - - /* Count the visible lines to the cursor */ - for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); - if (l<0) return; - - if(st->showlinenrs) { - x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; - } else { - x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; - } - y = curarea->winy - st->lheight*l - 2; - - boxw = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20; - boxh = SUGG_LIST_SIZE*st->lheight + 8; - - BIF_ThemeColor(TH_SHADE1); - glRecti(x-1, y+1, x+boxw+1, y-boxh-1); - BIF_ThemeColor(TH_BACK); - glRecti(x, y, x+boxw, y-boxh); - - /* Set the top 'item' of the visible list */ - for (i=0, item=first; i<*top && item->next; i++, item=item->next); - - for (i=0; inext) { - - y -= st->lheight; - - strncpy(str, item->name, SUGG_LIST_WIDTH); - str[SUGG_LIST_WIDTH] = '\0'; - - w = BMF_GetStringWidth(spacetext_get_font(st), str); - - if (item == sel) { - BIF_ThemeColor(TH_SHADE2); - glRecti(x+16, y-3, x+16+w, y+st->lheight-3); - } - b=1; /* b=1 colour block, text is default. b=0 no block, colour text */ - switch (item->type) { - case 'k': BIF_ThemeColor(TH_SYNTAX_B); b=0; break; - case 'm': BIF_ThemeColor(TH_TEXT); break; - case 'f': BIF_ThemeColor(TH_SYNTAX_L); break; - case 'v': BIF_ThemeColor(TH_SYNTAX_N); break; - case '?': BIF_ThemeColor(TH_TEXT); b=0; break; - } - if (b) { - glRecti(x+8, y+2, x+11, y+5); - BIF_ThemeColor(TH_TEXT); - } - text_draw(st, str, 0, 0, 1, x+16, y-1, NULL); - - if (item == last) break; - } -} - -static short check_blockhandler(SpaceText *st, short handler) { - short a; - for(a=0; ablockhandler[a]==handler) return 1; - return 0; -} - -static void text_panel_find(short cntrl) // TEXT_HANDLER_FIND -{ - uiBlock *block; - - if (!g_find_str || !g_replace_str) { - g_find_str= MEM_mallocN(TXT_MAXFINDSTR+1, "find_string"); - g_replace_str= MEM_mallocN(TXT_MAXFINDSTR+1, "replace_string"); - g_find_str[0]= g_replace_str[0]= '\0'; - } - - block= uiNewBlock(&curarea->uiblocks, "text_panel_find", UI_EMBOSS, UI_HELV, curarea->win); - uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); - uiSetPanelHandler(TEXT_HANDLER_FIND); // for close and esc - if(uiNewPanel(curarea, block, "Find & Replace", "Text", curarea->winx-230, curarea->winy-130, 260, 120)==0) return; - - uiBlockBeginAlign(block); - uiDefButC(block, TEX, 0, "Find: ", 0,80,220,20, g_find_str, 0,(float)TXT_MAXFINDSTR, 0,0, ""); - uiDefIconBut(block, BUT, B_PASTEFIND, ICON_TEXT, 220,80,20,20, NULL, 0,0,0,0, "Copy from selection"); - uiDefButC(block, TEX, 0, "Replace: ", 0,60,220,20, g_replace_str, 0,(float)TXT_MAXFINDSTR, 0,0, ""); - uiDefIconBut(block, BUT, B_PASTEREPLACE, ICON_TEXT, 220,60,20,20, NULL, 0,0,0,0, "Copy from selection"); - uiBlockEndAlign(block); - uiDefButBitI(block, TOG, TXT_FIND_WRAP, 0,"Wrap Around", 0,30,110,20,&g_find_flags,0,0,0,0,"Wrap search around current text"); - uiDefButBitI(block, TOG, TXT_FIND_ALLTEXTS,0,"Search All Texts", 110,30,130,20,&g_find_flags,0,0,0,0,"Search in each text"); - uiDefBut(block, BUT, B_TEXTFIND, "Find", 0,0,50,20, NULL, 0,0,0,0, "Find next"); - uiDefBut(block, BUT, B_TEXTREPLACE, "Replace/Find", 50,0,110,20, NULL, 0,0,0,0, "Replace then find next"); - uiDefBut(block, BUT, B_TEXTMARKALL, "Mark All", 160,0,80,20, NULL, 0,0,0,0, "Mark each occurrence to edit all from one"); -} - -/* mode: 0 find only, 1 replace/find, 2 mark all occurrences */ -void find_and_replace(SpaceText *st, short mode) { - char *tmp; - Text *start= NULL, *text= st->text; - int flags, first= 1; - - if (!check_blockhandler(st, TEXT_HANDLER_FIND)) { - toggle_blockhandler(st->area, TEXT_HANDLER_FIND, UI_PNL_TO_MOUSE); - return; - } - - if (!g_find_str || !g_replace_str) return; - if (g_find_str[0] == '\0') return; - flags= g_find_flags; - if (flags & TXT_FIND_ALLTEXTS) flags ^= TXT_FIND_WRAP; - - do { - if (first) - txt_clear_markers(text, TMARK_GRP_FINDALL, 0); - first= 0; - - /* Replace current */ - if (mode && txt_has_sel(text)) { - tmp= txt_sel_to_buf(text); - if (strcmp(g_find_str, tmp)==0) { - if (mode==1) { - txt_insert_buf(text, g_replace_str); - if (st->showsyntax) txt_format_line(st, text->curl, 1); - } else if (mode==2) { - char color[4]; - BIF_GetThemeColor4ubv(TH_SHADE2, color); - if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { - if (tmp) MEM_freeN(tmp), tmp=NULL; - break; - } - txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL); - } - } - MEM_freeN(tmp); - tmp= NULL; - } - - /* Find next */ - if (txt_find_string(text, g_find_str, flags & TXT_FIND_WRAP)) { - pop_space_text(st); - } else if (flags & TXT_FIND_ALLTEXTS) { - if (text==start) break; - if (!start) start= text; - if (text->id.next) - text= st->text= text->id.next; - else - text= st->text= G.main->text.first; - txt_move_toline(text, 0, 0); - pop_space_text(st); - first= 1; - } else { - okee("Text not found: %s", g_find_str); - break; - } - } while (mode==2); -} - -static void do_find_buttons(val) { - Text *text; - SpaceText *st; - int do_draw= 0; - char *tmp; - - st= curarea->spacedata.first; - if (!st || st->spacetype != SPACE_TEXT) return; - text= st->text; - if (!text) return; - - switch (val) { - case B_PASTEFIND: - if (!g_find_str) break; - tmp= txt_sel_to_buf(text); - strncpy(g_find_str, tmp, TXT_MAXFINDSTR); - MEM_freeN(tmp); - do_draw= 1; - break; - case B_PASTEREPLACE: - if (!g_replace_str) break; - tmp= txt_sel_to_buf(text); - strncpy(g_replace_str, tmp, TXT_MAXFINDSTR); - MEM_freeN(tmp); - do_draw= 1; - break; - case B_TEXTFIND: - find_and_replace(st, 0); - do_draw= 1; - break; - case B_TEXTREPLACE: - find_and_replace(st, 1); - do_draw= 1; - break; - case B_TEXTMARKALL: - find_and_replace(st, 2); - do_draw= 1; - break; - } -} - -static void text_blockhandlers(ScrArea *sa) -{ - SpaceText *st= sa->spacedata.first; - short a; - - /* warning; blocks need to be freed each time, handlers dont remove */ - uiFreeBlocksWin(&sa->uiblocks, sa->win); - - for(a=0; ablockhandler[a]) { - case TEXT_HANDLER_FIND: - text_panel_find(st->blockhandler[a+1]); - break; - } - } - uiDrawBlocksPanels(sa, 0); } void drawtextspace(ScrArea *sa, void *spacedata) { SpaceText *st= curarea->spacedata.first; Text *text; - int i, x, y; + int i; TextLine *tmp; char linenr[12]; float col[3]; int linecount = 0; if (st==NULL || st->spacetype != SPACE_TEXT) return; - - bwin_clear_viewmat(sa->win); /* clear buttons view */ - glLoadIdentity(); BIF_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); @@ -1649,23 +1022,23 @@ void drawtextspace(ScrArea *sa, void *spacedata) glRecti(23, 0, (st->lheight==15)?63:59, curarea->winy - 2); } + BIF_ThemeColor(TH_TEXT); + draw_cursor(st); tmp= text->lines.first; for (i= 0; itop && tmp; i++) { - if (st->showsyntax && !tmp->format) txt_format_line(st, tmp, 0); tmp= tmp->next; linecount++; } - - y= curarea->winy-st->lheight; - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - - BIF_ThemeColor(TH_TEXT); - for (i=0; y>0 && iviewlines && tmp; i++, tmp= tmp->next) { - if (st->showsyntax && !tmp->format) { - txt_format_line(st, tmp, 0); + + if(st->showsyntax) { + if (tmp && !tmp->format) { + get_format_string(st); } + } + + for (i=0; iviewlines && tmp; i++, tmp= tmp->next) { if(st->showlinenrs) { /*Change the color of the current line the cursor is on*/ if(tmp == text->curl) { @@ -1675,33 +1048,20 @@ void drawtextspace(ScrArea *sa, void *spacedata) } if(((float)(i + linecount + 1)/10000.0) < 1.0) { sprintf(linenr, "%4d", i + linecount + 1); - glRasterPos2i(TXT_OFFSET - 7, y); + glRasterPos2i(TXT_OFFSET - 7, curarea->winy-st->lheight*(i+1)); } else { sprintf(linenr, "%5d", i + linecount + 1); - glRasterPos2i(TXT_OFFSET - 11, y); + glRasterPos2i(TXT_OFFSET - 11, curarea->winy-st->lheight*(i+1)); } BIF_ThemeColor(TH_TEXT); BMF_DrawString(spacetext_get_font(st), linenr); - } - if (st->wordwrap) { - int lines = text_draw_wrapped(st, tmp->line, x, y, curarea->winx-x, tmp->format); - y -= lines*st->lheight; - } else { - text_draw(st, tmp->line, st->left, 0, 1, x, y, tmp->format); - y -= st->lheight; - } + text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET + TEXTXLOC, curarea->winy-st->lheight*(i+1), tmp->format); + } else + text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET, curarea->winy-st->lheight*(i+1), tmp->format); } - - draw_brackets(st); - draw_markers(st); draw_textscroll(st); - draw_documentation(st); - draw_suggestion_list(st); - - bwin_scalematrix(sa->win, st->blockscale, st->blockscale, st->blockscale); - text_blockhandlers(sa); - + curarea->win_swap= WIN_BACK_OK; } @@ -1715,19 +1075,15 @@ void pop_space_text (SpaceText *st) if(!st->text) return; if(!st->text->curl) return; - i= txt_get_span(st->text->lines.first, st->text->sell); + i= txt_get_span(st->text->lines.first, st->text->curl); if (st->top+st->viewlines <= i || st->top > i) { st->top= i - st->viewlines/2; } - if (st->wordwrap) { - st->left= 0; - } else { - x= text_draw(st, st->text->sell->line, st->left, st->text->selc, 0, 0, 0, NULL); + x= text_draw(st, st->text->curl->line, st->left, st->text->curc, 0, 0, 0, NULL); - if (x==0 || x>curarea->winx) { - st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); - } + if (x==0 || x>curarea->winx) { + st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); } if (st->top < 0) st->top= 0; @@ -1747,7 +1103,7 @@ void add_text_fs(char *file) /* bad but cant pass an as arg here */ st->top= 0; - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); } @@ -1759,60 +1115,6 @@ void free_textspace(SpaceText *st) st->text= NULL; } -/* returns 0 if file on disk is the same or Text is in memory only - returns 1 if file has been modified on disk since last local edit - returns 2 if file on disk has been deleted - -1 is returned if an error occurs -*/ -int txt_file_modified(Text *text) -{ - struct stat st; - int result; - char file[FILE_MAXDIR+FILE_MAXFILE]; - - if (!text || !text->name) - return 0; - - BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_convertstringcode(file, G.sce); - - if (!BLI_exists(file)) - return 2; - - result = stat(file, &st); - - if(result == -1) - return -1; - - if((st.st_mode & S_IFMT) != S_IFREG) - return -1; - - if (st.st_mtime > text->mtime) - return 1; - - return 0; -} - -void txt_ignore_modified(Text *text) { - struct stat st; - int result; - char file[FILE_MAXDIR+FILE_MAXFILE]; - - if (!text || !text->name) return; - - BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_convertstringcode(file, G.sce); - - if (!BLI_exists(file)) return; - - result = stat(file, &st); - - if(result == -1 || (st.st_mode & S_IFMT) != S_IFREG) - return; - - text->mtime= st.st_mtime; -} - static void save_mem_text(char *str) { SpaceText *st= curarea->spacedata.first; @@ -1839,9 +1141,6 @@ void txt_write_file(Text *text) { FILE *fp; TextLine *tmp; - int res; - struct stat st; - char file[FILE_MAXDIR+FILE_MAXFILE]; /* Do we need to get a filename? */ if (text->flags & TXT_ISMEM) { @@ -1849,22 +1148,19 @@ void txt_write_file(Text *text) activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->name, save_mem_text); else activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->id.name+2, save_mem_text); - return; + return; } - - BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_convertstringcode(file, G.sce); /* Should we ask to save over? */ if (text->flags & TXT_ISTMP) { - if (BLI_exists(file)) { + if (BLI_exists(text->name)) { if (!okee("Save over")) return; } else if (!okee("Create new file")) return; text->flags ^= TXT_ISTMP; } - fp= fopen(file, "w"); + fp= fopen(text->name, "w"); if (fp==NULL) { error("Unable to save file"); return; @@ -1879,9 +1175,6 @@ void txt_write_file(Text *text) } fclose (fp); - - res= stat(file, &st); - text->mtime= st.st_mtime; if (text->flags & TXT_ISDIRTY) text->flags ^= TXT_ISDIRTY; } @@ -2093,6 +1386,44 @@ void txt_copy_clipboard(Text *text) { } } +/* + * again==0 show find panel or find + * again==1 find text again */ +void txt_find_panel(SpaceText *st, int again) +{ + Text *text=st->text; + char *findstr= last_txt_find_string; + + if (again==0) { + findstr= txt_sel_to_buf(text); + } else if (again==1) { + char buf[256]; + + if (findstr && strlen(findstr)<(sizeof(buf)-1)) + strcpy(buf, findstr); + else + buf[0]= 0; + + if (sbutton(buf, 0, sizeof(buf)-1, "Find: ") && buf[0]) + findstr= BLI_strdup(buf); + else + findstr= NULL; + } + + if (findstr!=last_txt_find_string) { + if (last_txt_find_string) + MEM_freeN(last_txt_find_string); + last_txt_find_string= findstr; + } + + if (findstr) { + if (txt_find_string(text, findstr)) + pop_space_text(st); + else + error("Not found: %s", findstr); + } +} + void run_python_script(SpaceText *st) { char *py_filename; @@ -2127,580 +1458,6 @@ static void set_tabs(Text *text) st->currtab_set = setcurr_tab(text); } -static void wrap_move_bol(SpaceText *st, short sel) { - int offl, offc, lin; - Text *text= st->text; - - lin= txt_get_span(text->lines.first, text->sell); - wrap_offset(st, text->sell, text->selc, &offl, &offc); - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, -offc); - text->selc= -offc; - } else { - txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, -offc); - text->curc= -offc; - txt_pop_sel(text); - } -} - -static void wrap_move_eol(SpaceText *st, short sel) { - int offl, offc, lin, startl, c; - Text *text= st->text; - - lin= txt_get_span(text->lines.first, text->sell); - wrap_offset(st, text->sell, text->selc, &offl, &offc); - startl= offl; - c= text->selc; - while (offl==startl && text->sell->line[c]!='\0') { - c++; - wrap_offset(st, text->sell, c, &offl, &offc); - } if (offl!=startl) c--; - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, c); - text->selc= c; - } else { - txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, c); - text->curc= c; - txt_pop_sel(text); - } -} - -static void wrap_move_up(SpaceText *st, short sel) { - int offl, offl_1, offc, fromline, toline, c, target; - Text *text= st->text; - - wrap_offset(st, text->sell, 0, &offl_1, &offc); - wrap_offset(st, text->sell, text->selc, &offl, &offc); - fromline= toline= txt_get_span(text->lines.first, text->sell); - target= text->selc + offc; - - if (offl==offl_1) { - if (!text->sell->prev) { - txt_move_bol(text, sel); - return; - } - toline--; - c= text->sell->prev->len; /* End of prev. line */ - wrap_offset(st, text->sell->prev, c, &offl, &offc); - c= -offc+target; - } else { - c= -offc-1; /* End of prev. line */ - wrap_offset(st, text->sell, c, &offl, &offc); - c= -offc+target; - } - if (c<0) c=0; - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); - if (tolinesell= text->sell->prev; - if (c>text->sell->len) c= text->sell->len; - text->selc= c; - } else { - txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); - if (tolinecurl= text->curl->prev; - if (c>text->curl->len) c= text->curl->len; - text->curc= c; - txt_pop_sel(text); - } -} - -static void wrap_move_down(SpaceText *st, short sel) { - int offl, startoff, offc, fromline, toline, c, target; - Text *text= st->text; - - wrap_offset(st, text->sell, text->selc, &offl, &offc); - fromline= toline= txt_get_span(text->lines.first, text->sell); - target= text->selc + offc; - startoff= offl; - c= text->selc; - while (offl==startoff && text->sell->line[c]!='\0') { - c++; - wrap_offset(st, text->sell, c, &offl, &offc); - } - - if (text->sell->line[c]=='\0') { - if (!text->sell->next) { - txt_move_eol(text, sel); - return; - } - toline++; - c= target; - } else { - c += target; - if (c > text->sell->len) c= text->sell->len; - } - if (c<0) c=0; - - if (sel) { - txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); - if (toline>fromline) text->sell= text->sell->next; - if (c>text->sell->len) c= text->sell->len; - text->selc= c; - } else { - txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); - if (toline>fromline) text->curl= text->curl->next; - if (c>text->curl->len) c= text->curl->len; - text->curc= c; - txt_pop_sel(text); - } -} - -static void get_suggest_prefix(Text *text, int offset) { - int i, len; - char *line, tmp[256]; - - if (!text) return; - if (!texttool_text_is_active(text)) return; - - line= text->curl->line; - for (i=text->curc-1+offset; i>=0; i--) - if (!check_identifier(line[i])) - break; - i++; - len= text->curc-i+offset; - if (len > 255) { - printf("Suggestion prefix too long\n"); - len = 255; - } - strncpy(tmp, line+i, len); - tmp[len]= '\0'; - texttool_suggest_prefix(tmp); -} - -static void confirm_suggestion(Text *text, int skipleft) { - int i, over=0; - char *line; - SuggItem *sel; - - if (!text) return; - if (!texttool_text_is_active(text)) return; - - sel = texttool_suggest_selected(); - if (!sel) return; - - line= text->curl->line; - i=text->curc-skipleft-1; - while (i>=0) { - if (!check_identifier(line[i])) - break; - over++; - i--; - } - - for (i=0; iname); - - for (i=0; itext)) return 0; - if (!st->text || st->text->id.lib) return 0; - - if (st->doplugins && texttool_text_is_active(st->text)) { - if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST; - if (texttool_docs_get()) tools |= TOOL_DOCUMENT; - } - - if (ascii) { - if (tools & TOOL_SUGG_LIST) { - if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || check_whitespace(ascii)) { - confirm_suggestion(st->text, 0); - if (st->showsyntax) txt_format_line(st, st->text->curl, 1); - } else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) { - get_suggest_prefix(st->text, 0); - pop_suggest_list(); - swallow= 1; - draw= 1; - } - } - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; - - } else if (val==1 && evnt) { - switch (evnt) { - case LEFTMOUSE: - if (do_suggest_select(st)) - swallow= 1; - else { - if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; - } - draw= 1; - break; - case MIDDLEMOUSE: - if (do_suggest_select(st)) { - confirm_suggestion(st->text, 0); - if (st->showsyntax) txt_format_line(st, st->text->curl, 1); - swallow= 1; - } else { - if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; - } - draw= 1; - break; - case ESCKEY: - draw= swallow= 1; - if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); - else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; - else draw= swallow= 0; - break; - case RETKEY: - if (tools & TOOL_SUGG_LIST) { - confirm_suggestion(st->text, 0); - if (st->showsyntax) txt_format_line(st, st->text->curl, 1); - swallow= 1; - draw= 1; - } - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; - break; - case LEFTARROWKEY: - case BACKSPACEKEY: - if (tools & TOOL_SUGG_LIST) { - if (G.qual) - texttool_suggest_clear(); - else { - /* Work out which char we are about to delete/pass */ - if (st->text->curl && st->text->curc > 0) { - char ch= st->text->curl->line[st->text->curc-1]; - if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) { - get_suggest_prefix(st->text, -1); - pop_suggest_list(); - } - else - texttool_suggest_clear(); - } else - texttool_suggest_clear(); - } - } - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; - break; - case RIGHTARROWKEY: - if (tools & TOOL_SUGG_LIST) { - if (G.qual) - texttool_suggest_clear(); - else { - /* Work out which char we are about to pass */ - if (st->text->curl && st->text->curc < st->text->curl->len) { - char ch= st->text->curl->line[st->text->curc+1]; - if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) { - get_suggest_prefix(st->text, 1); - pop_suggest_list(); - } - else - texttool_suggest_clear(); - } else - texttool_suggest_clear(); - } - } - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; - break; - case PAGEDOWNKEY: - scroll= SUGG_LIST_SIZE-1; - case WHEELDOWNMOUSE: - case DOWNARROWKEY: - if (tools & TOOL_DOCUMENT) { - doc_scroll++; - swallow= 1; - draw= 1; - break; - } else if (tools & TOOL_SUGG_LIST) { - SuggItem *sel = texttool_suggest_selected(); - if (!sel) { - texttool_suggest_select(texttool_suggest_first()); - } else while (sel && sel!=texttool_suggest_last() && sel->next && scroll--) { - texttool_suggest_select(sel->next); - sel= sel->next; - } - pop_suggest_list(); - swallow= 1; - draw= 1; - break; - } - case PAGEUPKEY: - scroll= SUGG_LIST_SIZE-1; - case WHEELUPMOUSE: - case UPARROWKEY: - if (tools & TOOL_DOCUMENT) { - if (doc_scroll>0) doc_scroll--; - swallow= 1; - draw= 1; - break; - } else if (tools & TOOL_SUGG_LIST) { - SuggItem *sel = texttool_suggest_selected(); - while (sel && sel!=texttool_suggest_first() && sel->prev && scroll--) { - texttool_suggest_select(sel->prev); - sel= sel->prev; - } - pop_suggest_list(); - swallow= 1; - draw= 1; - break; - } - case RIGHTSHIFTKEY: - case LEFTSHIFTKEY: - break; - default: - if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw= 1; - if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; - } - } - - if (draw) { - ScrArea *sa; - - for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { - SpaceText *st= sa->spacedata.first; - - if (st && st->spacetype==SPACE_TEXT) { - scrarea_queue_redraw(sa); - } - } - } - - return swallow; -} - -static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short val) { - Text *text; - TextMarker *marker, *mrk, *nxt; - int c, s, draw=0, swallow=0; - - text= st->text; - if (!text || text->id.lib || text->curl != text->sell) return 0; - - marker= txt_find_marker(text, text->sell, text->selc, 0, 0); - if (marker && (marker->start > text->curc || marker->end < text->curc)) - marker= NULL; - - if (!marker) { - /* Find the next temporary marker */ - if (evnt==TABKEY) { - int lineno= txt_get_span(text->lines.first, text->curl); - TextMarker *mrk= text->markers.first; - while (mrk) { - if (!marker && (mrk->flags & TMARK_TEMP)) marker= mrk; - if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) { - marker= mrk; - break; - } - mrk= mrk->next; - } - if (marker) { - txt_move_to(text, marker->lineno, marker->start, 0); - txt_move_to(text, marker->lineno, marker->end, 1); - pop_space_text(st); - evnt= ascii= val= 0; - draw= 1; - swallow= 1; - } - } else if (evnt==ESCKEY) { - if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow= 1; - else if (txt_clear_markers(text, 0, 0)) swallow= 1; - else return 0; - evnt= ascii= val= 0; - draw= 1; - } - if (!swallow) return 0; - } - - if (ascii) { - if (marker->flags & TMARK_EDITALL) { - c= text->curc-marker->start; - s= text->selc-marker->start; - if (s<0 || s>marker->end-marker->start) return 0; - - mrk= txt_next_marker(text, marker); - while (mrk) { - nxt=txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start+c, 0); - if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); - if (st->overwrite) { - if (txt_replace_char(text, ascii)) - if (st->showsyntax) txt_format_line(st, text->curl, 1); - } else { - if (txt_add_char(text, ascii)) { - if (st->showsyntax) txt_format_line(st, text->curl, 1); - } - } - - if (mrk==marker || mrk==nxt) break; - mrk=nxt; - } - swallow= 1; - draw= 1; - } - } else if (val) { - switch(evnt) { - case BACKSPACEKEY: - if (marker->flags & TMARK_EDITALL) { - c= text->curc-marker->start; - s= text->selc-marker->start; - if (s<0 || s>marker->end-marker->start) return 0; - - mrk= txt_next_marker(text, marker); - while (mrk) { - nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start+c, 0); - if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); - txt_backspace_char(text); - if (st->showsyntax) txt_format_line(st, text->curl, 1); - if (mrk==marker || mrk==nxt) break; - mrk= nxt; - } - swallow= 1; - draw= 1; - } - break; - case DELKEY: - if (marker->flags & TMARK_EDITALL) { - c= text->curc-marker->start; - s= text->selc-marker->start; - if (s<0 || s>marker->end-marker->start) return 0; - - mrk= txt_next_marker(text, marker); - while (mrk) { - nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ - txt_move_to(text, mrk->lineno, mrk->start+c, 0); - if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); - txt_delete_char(text); - if (st->showsyntax) txt_format_line(st, text->curl, 1); - if (mrk==marker || mrk==nxt) break; - mrk= nxt; - } - swallow= 1; - draw= 1; - } - break; - case TABKEY: - if (G.qual & LR_SHIFTKEY) { - nxt= marker->prev; - if (!nxt) nxt= text->markers.last; - } else { - nxt= marker->next; - if (!nxt) nxt= text->markers.first; - } - if (marker->flags & TMARK_TEMP) { - if (nxt==marker) nxt= NULL; - BLI_freelinkN(&text->markers, marker); - } - mrk= nxt; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - pop_space_text(st); - } - swallow= 1; - draw= 1; - break; - - /* Events that should clear markers */ - case UKEY: if (!(G.qual & LR_ALTKEY)) break; - case ZKEY: if (evnt==ZKEY && !(G.qual & LR_CTRLKEY)) break; - case RETKEY: - case ESCKEY: - if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) - txt_clear_markers(text, marker->group, 0); - else - BLI_freelinkN(&text->markers, marker); - swallow= 1; - draw= 1; - break; - case RIGHTMOUSE: /* Marker context menu? */ - case LEFTMOUSE: - break; - case FKEY: /* Allow find */ - if (G.qual & LR_SHIFTKEY) swallow= 1; - break; - - default: - if (G.qual!=0 && G.qual!=LR_SHIFTKEY) - swallow= 1; /* Swallow all other shortcut events */ - } - } - - if (draw) { - ScrArea *sa; - - for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { - SpaceText *st= sa->spacedata.first; - - if (st && st->spacetype==SPACE_TEXT) { - scrarea_queue_redraw(sa); - } - } - } - return swallow; -} - -static short do_modification_check(SpaceText *st) { - Text *text= st->text; - - if (last_check_time < PIL_check_seconds_timer() - 2.0) { - switch (txt_file_modified(text)) { - case 1: - /* Modified locally and externally, ahhh. Offer more possibilites. */ - if (text->flags & TXT_ISDIRTY) { - switch (pupmenu("File Modified Outside and Inside Blender %t|Load outside changes (ignore local changes) %x0|Save local changes (ignore outside changes) %x1|Make text internal (separate copy) %x2")) { - case 0: - reopen_text(text); - if (st->showsyntax) txt_format_text(st); - return 1; - case 1: - txt_write_file(text); - return 1; - case 2: - text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; - MEM_freeN(text->name); - text->name= NULL; - return 1; - } - } else { - switch (pupmenu("File Modified Outside Blender %t|Reload from disk %x0|Make text internal (separate copy) %x1|Ignore %x2")) { - case 0: - reopen_text(text); - if (st->showsyntax) txt_format_text(st); - return 1; - case 1: - text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; - MEM_freeN(text->name); - text->name= NULL; - return 1; - case 2: - txt_ignore_modified(text); - return 1; - } - } - break; - case 2: - switch (pupmenu("File Deleted Outside Blender %t|Make text internal %x0|Recreate file %x1")) { - case 0: - text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; - MEM_freeN(text->name); - text->name= NULL; - return 1; - case 1: - txt_write_file(text); - return 1; - } - break; - default: - break; - } - last_check_time = PIL_check_seconds_timer(); - } - return 0; -} - void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { unsigned short event= evt->event; @@ -2771,16 +1528,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } return; } - - if (val && uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING) event= 0; - - if (st->doplugins && do_texttools(st, ascii, event, val)) return; - if (do_markers(st, ascii, event, val)) return; - if (event==UI_BUT_EVENT) { - do_find_buttons(val); - do_draw= 1; - } else if (event==LEFTMOUSE) { + if (event==LEFTMOUSE) { if (val) { short mval[2]; char *buffer; @@ -2801,20 +1550,20 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } else if (event==MIDDLEMOUSE) { if (val) { - if (U.uiflag & USER_MMB_PASTE) { + if (U.uiflag & USER_MMB_PASTE) + { do_selection(st, G.qual&LR_SHIFTKEY); get_selection_buffer(text); do_draw= 1; - } else { + } + else + { do_textscroll(st, 1); } } } else if (event==RIGHTMOUSE) { if (val) { - if (txt_has_sel(text)) - p= pupmenu("Text %t|Cut%x10|Copy%x11|Paste%x12|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); - else - p= pupmenu("Text %t|Paste%x12|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); + p= pupmenu("File %t|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); switch(p) { case 0: @@ -2840,48 +1589,13 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) run_python_script(st); do_draw= 1; break; - case 10: - if (text && text->id.lib) { - error_libdata(); - break; - } - txt_copy_clipboard(text); - txt_cut_sel(text); - pop_space_text(st); - do_draw= 1; - break; - case 11: - //txt_copy_sel(text); - txt_copy_clipboard(text); - break; - case 12: - if (text && text->id.lib) { - error_libdata(); - break; - } - txt_paste_clipboard(text); - if (st->showsyntax) txt_format_text(st); - do_draw= 1; + default: break; } } } else if (ascii) { - if (text && text->id.lib) { - error_libdata(); - } else { - short mval[2]; - getmouseco_areawin(mval); - if (st->showlinenrs && mval[0]>2 && mval[0]<60 && mval[1]>2 && mval[1]winy-2) { - if (ascii>='0' && ascii<='9') { - double time = PIL_check_seconds_timer(); - if (last_jump < time-1) jump_to= 0; - jump_to *= 10; jump_to += (int)(ascii-'0'); - txt_move_toline(text, jump_to-1, 0); - last_jump= time; - } - } else if ((st->overwrite && txt_replace_char(text, ascii)) || txt_add_char(text, ascii)) { - if (st->showsyntax) txt_format_line(st, text->curl, 1); - } + if (txt_add_char(text, ascii)) { + if (st->showsyntax) get_format_string(st); pop_space_text(st); do_draw= 1; } @@ -2908,20 +1622,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } break; /* BREAK C */ case DKEY: - if (text && text->id.lib) { - error_libdata(); - break; - } if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { //uncommenting txt_order_cursors(text); uncomment(text); do_draw = 1; - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); break; } else if (G.qual == LR_CTRLKEY) { txt_delete_char(text); - if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (st->showsyntax) get_format_string(st); do_draw= 1; pop_space_text(st); } @@ -2930,10 +1640,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { switch(pupmenu("Edit %t|Cut %x0|Copy %x1|Paste %x2|Print Cut Buffer %x3")) { case 0: - if (text && text->id.lib) { - error_libdata(); - break; - } txt_copy_clipboard(text); //First copy to clipboard txt_cut_sel(text); do_draw= 1; @@ -2944,13 +1650,9 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) do_draw= 1; break; case 2: - if (text && text->id.lib) { - error_libdata(); - break; - } //txt_paste(text); txt_paste_clipboard(text); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); do_draw= 1; break; case 3: @@ -2985,17 +1687,17 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; } } - else if (G.qual & (LR_ALTKEY|LR_CTRLKEY)) { - find_and_replace(st, 0); + else if (G.qual == LR_ALTKEY) { + if (txt_has_sel(text)) { + txt_find_panel(st,0); + do_draw= 1; + } + } + else if (G.qual == (LR_ALTKEY|LR_CTRLKEY)) { /* always search button */ + txt_find_panel(st,1); do_draw= 1; } break; /* BREAK F */ - case HKEY: - if (G.qual & (LR_ALTKEY|LR_CTRLKEY)) { - find_and_replace(st, 1); - do_draw= 1; - } - break; /* BREAK H */ case JKEY: if (G.qual == LR_ALTKEY) { do_draw= jumptoline_interactive(st); @@ -3004,7 +1706,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case MKEY: if (G.qual == LR_ALTKEY) { txt_export_to_object(text); - do_draw= 1; + do_draw= 1; } break; /* BREAK M */ case NKEY: @@ -3014,6 +1716,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); + } break; /* BREAK N */ case OKEY: @@ -3037,7 +1740,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (okee("Reopen text")) { if (!reopen_text(text)) error("Could not reopen file"); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); } do_draw= 1; } @@ -3077,13 +1780,11 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) //txt_print_undo(text); //debug buffer in console if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { txt_do_redo(text); - pop_space_text(st); do_draw= 1; } if (G.qual == LR_ALTKEY) { txt_do_undo(text); - if (st->showsyntax) txt_format_text(st); - pop_space_text(st); + if (st->showsyntax) get_format_string(st); do_draw= 1; } break; /* BREAK U */ @@ -3112,28 +1813,20 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } /* Support for both Alt-V and Ctrl-V for Paste, for backward compatibility reasons */ else if (G.qual & LR_ALTKEY || G.qual & LR_CTRLKEY) { - if (text && text->id.lib) { - error_libdata(); - break; - } /* Throwing in the Shift modifier Paste from the OS clipboard */ if (G.qual & LR_SHIFTKEY) txt_paste_clipboard(text); else txt_paste_clipboard(text); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); do_draw= 1; pop_space_text(st); } break; /* BREAK V */ case XKEY: if (G.qual == LR_ALTKEY || G.qual == LR_CTRLKEY) { - if (text && text->id.lib) { - error_libdata(); - break; - } txt_cut_sel(text); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); do_draw= 1; pop_space_text(st); } @@ -3145,40 +1838,31 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } else { txt_do_undo(text); } - if (st->showsyntax) txt_format_text(st); - pop_space_text(st); + if (st->showsyntax) get_format_string(st); do_draw= 1; } break; case TABKEY: - if (text && text->id.lib) { - error_libdata(); - break; - } else { + if (G.qual & LR_SHIFTKEY) { if (txt_has_sel(text)) { - if (G.qual & LR_SHIFTKEY) { - txt_order_cursors(text); - unindent(text); - if (st->showsyntax) txt_format_text(st); - } else { - txt_order_cursors(text); - indent(text); - if (st->showsyntax) txt_format_text(st); - } + txt_order_cursors(text); + unindent(text); + + } + } else { + if ( txt_has_sel(text)) { + txt_order_cursors(text); + indent(text); } else { txt_add_char(text, '\t'); - if (st->showsyntax) txt_format_line(st, text->curl, 1); } } + if (st->showsyntax) get_format_string(st); pop_space_text(st); do_draw= 1; st->currtab_set = setcurr_tab(text); break; case RETKEY: - if (text && text->id.lib) { - error_libdata(); - break; - } //double check tabs before splitting the line st->currtab_set = setcurr_tab(text); txt_split_curline(text); @@ -3192,52 +1876,33 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } } - if (st->showsyntax) { - if (text->curl->prev) txt_format_line(st, text->curl->prev, 0); - txt_format_line(st, text->curl, 1); - } + if (st->showsyntax) get_format_string(st); do_draw= 1; pop_space_text(st); break; case BACKSPACEKEY: - if (text && text->id.lib) { - error_libdata(); - break; - } - if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { - txt_backspace_word(text); - } else { - txt_backspace_char(text); - } + txt_backspace_char(text); set_tabs(text); - if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (st->showsyntax) get_format_string(st); do_draw= 1; pop_space_text(st); break; case DELKEY: - if (text && text->id.lib) { - error_libdata(); - break; - } - if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { - txt_delete_word(text); - } else { - txt_delete_char(text); - } - if (st->showsyntax) txt_format_line(st, text->curl, 1); + txt_delete_char(text); + if (st->showsyntax) get_format_string(st); do_draw= 1; pop_space_text(st); st->currtab_set = setcurr_tab(text); break; - case INSERTKEY: - st->overwrite= !st->overwrite; + case DOWNARROWKEY: + txt_move_down(text, G.qual & LR_SHIFTKEY); + set_tabs(text); do_draw= 1; + pop_space_text(st); break; case LEFTARROWKEY: if (G.qual & LR_COMMANDKEY) txt_move_bol(text, G.qual & LR_SHIFTKEY); - else if (G.qual & LR_ALTKEY) - txt_jump_left(text, G.qual & LR_SHIFTKEY); else txt_move_left(text, G.qual & LR_SHIFTKEY); set_tabs(text); @@ -3247,8 +1912,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case RIGHTARROWKEY: if (G.qual & LR_COMMANDKEY) txt_move_eol(text, G.qual & LR_SHIFTKEY); - else if (G.qual & LR_ALTKEY) - txt_jump_right(text, G.qual & LR_SHIFTKEY); else txt_move_right(text, G.qual & LR_SHIFTKEY); set_tabs(text); @@ -3256,38 +1919,26 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pop_space_text(st); break; case UPARROWKEY: - if (st->wordwrap) wrap_move_up(st, G.qual & LR_SHIFTKEY); - else txt_move_up(text, G.qual & LR_SHIFTKEY); - set_tabs(text); - do_draw= 1; - pop_space_text(st); - break; - case DOWNARROWKEY: - if (st->wordwrap) wrap_move_down(st, G.qual & LR_SHIFTKEY); - else txt_move_down(text, G.qual & LR_SHIFTKEY); + txt_move_up(text, G.qual & LR_SHIFTKEY); set_tabs(text); do_draw= 1; pop_space_text(st); break; case PAGEDOWNKEY: - cursor_skip(st, st->viewlines, G.qual & LR_SHIFTKEY); - pop_space_text(st); + screen_skip(st, st->viewlines); do_draw= 1; break; case PAGEUPKEY: - cursor_skip(st, -st->viewlines, G.qual & LR_SHIFTKEY); - pop_space_text(st); + screen_skip(st, -st->viewlines); do_draw= 1; break; case HOMEKEY: - if (st->wordwrap) wrap_move_bol(st, G.qual & LR_SHIFTKEY); - else txt_move_bol(text, G.qual & LR_SHIFTKEY); + txt_move_bol(text, G.qual & LR_SHIFTKEY); do_draw= 1; pop_space_text(st); break; case ENDKEY: - if (st->wordwrap) wrap_move_eol(st, G.qual & LR_SHIFTKEY); - else txt_move_eol(text, G.qual & LR_SHIFTKEY); + txt_move_eol(text, G.qual & LR_SHIFTKEY); do_draw= 1; pop_space_text(st); break; @@ -3302,15 +1953,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } - /* Run text plugin scripts if enabled */ - if (st->doplugins && event && val) { - if (BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, G.qual)) { - do_draw= 1; - } - } - - if (do_modification_check(st)) do_draw= 1; - if (do_draw) { ScrArea *sa; @@ -3324,150 +1966,179 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } -void draw_brackets(SpaceText *st) +void do_brackets(void) { - char ch; - int b, c, startc, endc, find, stack; - int viewc, viewl, offl, offc, x, y; - TextLine *startl, *endl, *linep; + SpaceText *st = curarea->spacedata.first; Text *text = st->text; - - if (!text || !text->curl) return; - - startl= text->curl; - startc= text->curc; - b= check_bracket(startl->line[startc]); - if (b==0 && startc>0) b = check_bracket(startl->line[--startc]); - if (b==0) return; + TextLine *tmp, *start; + char test[2]; + int d, pos, open, x, y, x2, y2, h=0; - linep= startl; - c= startc; - endl= NULL; - endc= -1; - find= -b; - stack= 0; + if(!text) return; + + tmp = text->curl; + start = text->curl; - /* Opening bracket, search forward for close */ - if (b>0) { - c++; - while (linep) { - while (clen) { - b= check_bracket(linep->line[c]); - if (b==find) { - if (stack==0) { - endl= linep; - endc= c; - break; - } - stack--; - } else if (b==-find) { - stack++; - } - c++; + test[0] = (unsigned char) tmp->line[text->curc]; + test[1] = '\0'; + + d = check_bracket(test); + if (!d) /* If not pri char */ + { + test[0] = (unsigned char) tmp->line[text->curc-1]; + test[1] = '\0'; + d = check_bracket(test); + if(!d) { + return; /*If the current char or prev is not a bracket then return*/ + } else { /* current char */ + h= txt_get_span(text->lines.first, start) - st->top; + x = text_draw(st, start->line, st->left, text->curc-1, 0, 0, 0, NULL); + y = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL); + if (d < 4) { + pos = text->curc; + } else { + pos = text->curc-2; } - if (endl) break; - linep= linep->next; - c= 0; + } + } else { /* is pri char */ + h= txt_get_span(text->lines.first, start) - st->top; + x = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL); + y = text_draw(st, start->line, st->left, text->curc+1, 0, 0, 0, NULL); + if (d < 4) { + pos = text->curc+1; + } else { + pos = text->curc-1; } } - /* Closing bracket, search backward for open */ - else { - c--; - while (linep) { - while (c>=0) { - b= check_bracket(linep->line[c]); - if (b==find) { - if (stack==0) { - endl= linep; - endc= c; - break; + + if (d < 4) /*reading forward*/ + { + open = 1; + while ( tmp ) { + while (pos <= tmp->len) { + test[0] = (unsigned char) tmp->line[pos]; + test[1] = '\0'; + if(check_bracket(test) == d) { + open++; + } else if (check_bracket(test) == d+3) { + open--; + if (open == 0) { + BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5); + glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2); + + h= txt_get_span(text->lines.first, tmp) - st->top; + x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL); + y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL); + glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2); + BIF_ThemeColor(TH_TEXT); + return; } - stack--; - } else if (b==-find) { - stack++; } - c--; + pos++; + } + tmp = tmp->next; + pos = 0; + } + } else { /* reading back */ + open = 1; + while ( tmp ) { + while (pos >= 0) { + test[0] = (unsigned char) tmp->line[pos]; + test[1] = '\0'; + if(check_bracket(test) == d) { + open++; + } else if (check_bracket(test) == d-3) { + open--; + if (open == 0) { + BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5); + glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2); + + h= txt_get_span(text->lines.first, tmp) - st->top; + x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL); + y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL); + glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2); + BIF_ThemeColor(TH_TEXT); + return; + } + } + pos--; + } + tmp = tmp->prev; + if (tmp) { + pos = tmp->len; } - if (endl) break; - linep= linep->prev; - if (linep) c= linep->len-1; } } - - if (!endl || endc==-1) return; - - BIF_ThemeColor(TH_HILITE); - x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; - y= curarea->winy - st->lheight; - - ch= startl->line[startc]; - wrap_offset(st, startl, startc, &offl, &offc); - viewc= get_char_pos(st, startl->line, startc) - st->left + offc; - if (viewc >= 0){ - viewl= txt_get_span(text->lines.first, startl) - st->top + offl; - glRasterPos2i(x+viewc*spacetext_get_fontwidth(st), y-viewl*st->lheight); - BMF_DrawCharacter(spacetext_get_font(st), ch); - glRasterPos2i(x+viewc*spacetext_get_fontwidth(st)+1, y-viewl*st->lheight); - BMF_DrawCharacter(spacetext_get_font(st), ch); - } - ch= endl->line[endc]; - wrap_offset(st, endl, endc, &offl, &offc); - viewc= get_char_pos(st, endl->line, endc) - st->left + offc; - if (viewc >= 0) { - viewl= txt_get_span(text->lines.first, endl) - st->top + offl; - glRasterPos2i(x+viewc*spacetext_get_fontwidth(st), y-viewl*st->lheight); - BMF_DrawCharacter(spacetext_get_font(st), ch); - glRasterPos2i(x+viewc*spacetext_get_fontwidth(st)+1, y-viewl*st->lheight); - BMF_DrawCharacter(spacetext_get_font(st), ch); - } + } -static int check_bracket(char ch) +int check_bracket(char *string) { - int a; - char opens[] = "([{"; - char close[] = ")]}"; + int number, a = 0; + char other[][3] = {"(", "[", "{", ")", "]", "}"}; - for (a=0; a<3; a++) { - if(ch==opens[a]) + number = 6; + + while(a < number) { + if(strcmp(other[a], string) == 0) + { return a+1; - else if (ch==close[a]) - return -(a+1); + } + a++; } return 0; } -static int check_delim(char ch) +static int check_builtinfuncs(char *string) { - int a; - char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,"; + int number = 30, a = 0; - for (a=0; a<28; a++) { - if (ch==delims[a]) + char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def", + "del", "elif", "else", "except", "exec", "finally", + "for", "from", "global", "if", "import", "in", + "is", "lambda", "not", "or", "pass", "print", + "raise", "return", "try", "while", "yield"}; + + for( a = 0; a < number; a++) { + if(!strcmp(builtinfuncs[a], string)) return 1; } return 0; } -static int check_digit(char ch) { - if (ch < '0') return 0; - if (ch <= '9') return 1; +static int check_specialvars(char *string) +{ + int number = 2, a = 0; + char specialvars[][7] = {"def", "class"}; + + for( a = 0; a < number; a++) { + if(!strcmp(specialvars[a], string)) + return a+1; + } return 0; } -static int check_identifier(char ch) { - if (ch < '0') return 0; - if (ch <= '9') return 1; - if (ch < 'A') return 0; - if (ch <= 'Z' || ch == '_') return 1; - if (ch < 'a') return 0; - if (ch <= 'z') return 1; +static int check_delim(char *string) +{ + int number = 28, a = 0; + char other[][3] = {"(", ")", ":", "\"", "\'", " ", "~", "!", "%", "^", "&", "*", "-", "+", "=", "[", "]", "{", "}", ";", "/", "<", ">", "|", ".", "#", "\t", ","}; + + for( a = 0; a < number; a++) { + if(!strcmp(other[a], string)) + return 1; + } return 0; } -static int check_whitespace(char ch) { - if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') - return 1; +static int check_numbers(char *string) +{ + int number = 10, a = 0; + char other[][2] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + + for( a = 0; a < number; a++) { + if(!strcmp(other[a], string)) + return 1; + } return 0; } @@ -3475,7 +2146,7 @@ void convert_tabs (struct SpaceText *st, int tab) { Text *text = st->text; TextLine *tmp; - char *check_line, *new_line; + char *check_line, *new_line, *format; int extra, number; //unknown for now size_t a, j; @@ -3487,6 +2158,7 @@ void convert_tabs (struct SpaceText *st, int tab) while(tmp) { check_line = tmp->line; new_line = MEM_mallocN(render_string(st, check_line)+1, "Converted_Line"); + format = MEM_mallocN(render_string(st, check_line)+1, "Converted_Syntax_format"); j = 0; for (a=0; a < strlen(check_line); a++) { //foreach char in line if(check_line[a] == '\t') { //checking for tabs @@ -3513,7 +2185,7 @@ void convert_tabs (struct SpaceText *st, int tab) tmp->line = new_line; tmp->len = strlen(new_line); - tmp->format = NULL; + tmp->format = format; tmp = tmp->next; } @@ -3541,6 +2213,7 @@ void convert_tabs (struct SpaceText *st, int tab) if ( extra > 0 ) { //got tabs make malloc and do what you have to do new_line = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Line"); + format = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Syntax_format"); extra = 0; //reuse vars for (a = 0; a < strlen(check_line); a++) { number = 0; @@ -3568,11 +2241,9 @@ void convert_tabs (struct SpaceText *st, int tab) tmp->line = new_line; tmp->len = strlen(new_line); - tmp->format = NULL; + tmp->format = format; } tmp = tmp->next; } } - - if (st->showsyntax) txt_format_text(st); } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 42576c901d7..2030eb658de 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -64,7 +64,6 @@ #include "DNA_gpencil_types.h" #include "DNA_image_types.h" #include "DNA_key_types.h" -#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -135,7 +134,6 @@ #include "BIF_verse.h" #endif -#include "BDR_drawaction.h" #include "BDR_drawmesh.h" #include "BDR_drawobject.h" #include "BDR_editobject.h" @@ -164,9 +162,6 @@ #include "RE_pipeline.h" // make_stars -#include "GPU_draw.h" -#include "GPU_material.h" - #include "multires.h" /* For MULTISAMPLE_ARB #define. @@ -198,6 +193,132 @@ static void star_stuff_term_func(void) glEnd(); } +void default_gl_light(void) +{ + int a; + + /* initialize */ + if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { + U.light[0].flag= 1; + U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; + U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; + U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; + U.light[0].spec[3]= 1.0; + + U.light[1].flag= 0; + U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; + U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; + U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; + U.light[1].spec[3]= 1.0; + + U.light[2].flag= 0; + U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; + U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; + U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; + U.light[2].spec[3]= 1.0; + } + + + glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); + glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); + glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); + + glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); + glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); + glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); + + glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); + glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); + glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); + + for(a=0; a<8; a++) { + if(a<3) { + if(U.light[a].flag) glEnable(GL_LIGHT0+a); + else glDisable(GL_LIGHT0+a); + + // clear stuff from other opengl lamp usage + glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); + glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); + } + else glDisable(GL_LIGHT0+a); + } + + glDisable(GL_LIGHTING); + + glDisable(GL_COLOR_MATERIAL); +} + +/* also called when render 'ogl' + keep synced with Myinit_gl_stuff in the game engine! */ +void init_gl_stuff(void) +{ + float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; + float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + float mat_shininess[] = { 35.0 }; + int a, x, y; + GLubyte pat[32*32]; + const GLubyte *patc= pat; + + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + default_gl_light(); + + /* no local viewer, looks ugly in ortho mode */ + /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ + + glDepthFunc(GL_LEQUAL); + /* scaling matrices */ + glEnable(GL_NORMALIZE); + + glShadeModel(GL_FLAT); + + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_LOGIC_OP); + glDisable(GL_STENCIL_TEST); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + + /* default on, disable/enable should be local per function */ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glPixelTransferi(GL_MAP_COLOR, GL_FALSE); + glPixelTransferi(GL_RED_SCALE, 1); + glPixelTransferi(GL_RED_BIAS, 0); + glPixelTransferi(GL_GREEN_SCALE, 1); + glPixelTransferi(GL_GREEN_BIAS, 0); + glPixelTransferi(GL_BLUE_SCALE, 1); + glPixelTransferi(GL_BLUE_BIAS, 0); + glPixelTransferi(GL_ALPHA_SCALE, 1); + glPixelTransferi(GL_ALPHA_BIAS, 0); + + glPixelTransferi(GL_DEPTH_BIAS, 0); + glPixelTransferi(GL_DEPTH_SCALE, 1); + glDepthRange(0.0, 1.0); + + a= 0; + for(x=0; x<32; x++) { + for(y=0; y<4; y++) { + if( (x) & 1) pat[a++]= 0x88; + else pat[a++]= 0x22; + } + } + + glPolygonStipple(patc); + + + init_realtime_GL(); +} + void circf(float x, float y, float rad) { GLUquadricObj *qobj = gluNewQuadric(); @@ -1208,196 +1329,60 @@ void drawname(Object *ob) BMF_DrawString(G.font, ob->id.name+2); } -static char *get_cfra_marker_name() -{ - ListBase *markers= &G.scene->markers; - TimeMarker *m1, *m2; - - /* search through markers for match */ - for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) { - if (m1->frame==CFRA) - return m1->name; - if (m2->frame==CFRA) - return m2->name; - - if (m1 == m2) - break; - } - - return NULL; -} -// TODO: move this func into some keyframing API -short ob_cfra_has_keyframe (Object *ob) -{ - // fixme... this is slow! - if (ob) { - ListBase keys = {NULL, NULL}; - ActKeyColumn *ak, *akn; - Key *key= ob_get_key(ob); - int cfra, found= 0; - - /* check active action */ - if (ob->action) { - /* get keyframes of action */ - action_to_keylist(ob->action, &keys, NULL, NULL); - - cfra= frame_to_float(CFRA); - cfra= get_action_frame(ob, cfra); - - /* check if a keyframe occurs on current frame */ - for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { - if (cfra == ak->cfra) { - found= 1; - break; - } - else if (cfra == akn->cfra) { - found= 1; - break; - } - - if (ak == akn) - break; - } - - /* free temp list */ - BLI_freelistN(&keys); - keys.first= keys.last= NULL; - - /* return if found */ - if (found) return 1; - } - - /* accumulate keyframes for available ipo's */ - if (ob->ipo) - ipo_to_keylist(ob->ipo, &keys, NULL, NULL); - if (key) - ipo_to_keylist(key->ipo, &keys, NULL, NULL); - - if (keys.first) { - cfra= frame_to_float(CFRA); - found= 0; - - /* check if a keyframe occurs on current frame */ - for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { - if (IS_EQ(cfra, ak->cfra)) { - found= 1; - break; - } - else if (IS_EQ(cfra, akn->cfra)) { - found= 1; - break; - } - - if (ak == akn) - break; - } - - /* free temp list */ - BLI_freelistN(&keys); - keys.first= keys.last= NULL; - - /* return if found */ - if (found) return 1; - } - } - - /* couldn't find a keyframe */ - return 0; -} - -/* draw info beside axes in bottom left-corner: - * framenum, object name, bone name (if available), marker name (if available) - */ static void draw_selected_name(Object *ob) { - char info[256], *markern; + char info[128]; short offset=30; - - /* get name of marker on current frame (if available) */ - markern= get_cfra_marker_name(); - - /* check if there is an object */ - if(ob) { - /* name(s) to display depends on type of object */ - if(ob->type==OB_ARMATURE) { - bArmature *arm= ob->data; - char *name= NULL; - - /* show name of active bone too (if possible) */ - if(ob==G.obedit) { - EditBone *ebo; - for (ebo=G.edbo.first; ebo; ebo=ebo->next){ - if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { - name= ebo->name; - break; - } - } - } - else if(ob->pose && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { - name= pchan->name; - break; - } - } - } - if(name && markern) - sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern); - else if(name) - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); - else - sprintf(info, "(%d) %s", CFRA, ob->id.name+2); - } - else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { - Key *key= NULL; - KeyBlock *kb = NULL; - char shapes[75]; - - /* try to display active shapekey too */ - shapes[0] = 0; - key = ob_get_key(ob); - if(key){ - kb = BLI_findlink(&key->block, ob->shapenr-1); - if(kb){ - sprintf(shapes, ": %s ", kb->name); - if(ob->shapeflag == OB_SHAPE_LOCK){ - sprintf(shapes, "%s (Pinned)",shapes); - } - } - } - - if(markern) - sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern); - else - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); - } - else { - /* standard object */ - if (markern) - sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern); - else - sprintf(info, "(%d) %s", CFRA, ob->id.name+2); - } - - /* colour depends on whether there is a keyframe */ - if (ob_cfra_has_keyframe(ob)) - BIF_ThemeColor(TH_VERTEX_SELECT); - else - BIF_ThemeColor(TH_TEXT_HI); - } - else { - /* no object */ - if (markern) - sprintf(info, "(%d) <%s>", CFRA, markern); - else - sprintf(info, "(%d)", CFRA); + + if(ob->type==OB_ARMATURE) { + bArmature *arm= ob->data; + char *name= NULL; - /* colour is always white */ - BIF_ThemeColor(TH_TEXT_HI); + if(ob==G.obedit) { + EditBone *ebo; + for (ebo=G.edbo.first; ebo; ebo=ebo->next){ + if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { + name= ebo->name; + break; + } + } + } + else if(ob->pose && (ob->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { + name= pchan->name; + break; + } + } + } + if(name) + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); } - + else if(ob->type==OB_MESH) { + Key *key= NULL; + KeyBlock *kb = NULL; + char shapes[75]; + + shapes[0] = 0; + key = ob_get_key(ob); + if(key){ + kb = BLI_findlink(&key->block, ob->shapenr-1); + if(kb){ + sprintf(shapes, ": %s ", kb->name); + if(ob->shapeflag == OB_SHAPE_LOCK){ + sprintf(shapes, "%s (Pinned)",shapes); + } + } + } + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + } + else sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + + BIF_ThemeColor(TH_TEXT_HI); if (U.uiflag & USER_SHOW_ROTVIEWICON) offset = 14 + (U.rvisize * 2); @@ -2752,7 +2737,7 @@ void add_view3d_after(View3D *v3d, Base *base, int type, int flag) } /* clears zbuffer and draws it over */ -static void view3d_draw_xray(View3D *v3d, int clear) +static void view3d_draw_xray(View3D *v3d) { View3DAfter *v3da, *next; int doit= 0; @@ -2761,7 +2746,7 @@ static void view3d_draw_xray(View3D *v3d, int clear) if(v3da->type==V3D_XRAY) doit= 1; if(doit) { - if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); + if(v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); v3d->xray= TRUE; for(v3da= v3d->afterdraw.first; v3da; v3da= next) { @@ -2783,7 +2768,7 @@ static void view3d_draw_transp(View3D *v3d) glDepthMask(0); v3d->transp= TRUE; - + for(v3da= v3d->afterdraw.first; v3da; v3da= next) { next= v3da->next; if(v3da->type==V3D_TRANSP) { @@ -2826,8 +2811,7 @@ static void draw_dupli_objects_color(View3D *v3d, Base *base, int color) tbase.object= dob->ob; /* extra service: draw the duplicator in drawtype of parent */ - /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ - dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt); + dt= tbase.object->dt; tbase.object->dt= base->object->dt; dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx; /* negative scale flag has to propagate */ @@ -2962,7 +2946,7 @@ static void draw_sculpt_depths(View3D *v3d) } } -void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *)) +void draw_depth(ScrArea *sa, void *spacedata) { View3D *v3d= spacedata; Base *base; @@ -3002,11 +2986,9 @@ void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *)) if(G.scene->set) { for(SETLOOPER(G.scene->set, base)) { if(v3d->lay & base->lay) { - if (func == NULL || func(base)) { - draw_object(base, 0); - if(base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(v3d, base, TH_WIRE); - } + draw_object(base, 0); + if(base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(v3d, base, TH_WIRE); } } } @@ -3014,13 +2996,12 @@ void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *)) for(base= G.scene->base.first; base; base= base->next) { if(v3d->lay & base->lay) { - if (func == NULL || func(base)) { - /* dupli drawing */ - if(base->object->transflag & OB_DUPLI) { - draw_dupli_objects(v3d, base); - } - draw_object(base, 0); + + /* dupli drawing */ + if(base->object->transflag & OB_DUPLI) { + draw_dupli_objects(v3d, base); } + draw_object(base, 0); } } @@ -3065,84 +3046,6 @@ void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *)) static void draw_viewport_fps(ScrArea *sa); -typedef struct View3DShadow{ - struct View3DShadow*next, *prev; - GPULamp *lamp; -} View3DShadow; - -static void gpu_render_lamp_update(View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows) -{ - GPULamp *lamp; - View3DShadow *shadow; - - lamp = GPU_lamp_from_blender(G.scene, ob, par); - - if(lamp) { - GPU_lamp_update(lamp, ob->lay, obmat); - - if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) { - shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow"); - shadow->lamp = lamp; - BLI_addtail(shadows, shadow); - } - } -} - -static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) -{ - ListBase shadows; - View3DShadow *shadow; - Scene *sce; - Base *base; - Object *ob; - - shadows.first= shadows.last= NULL; - - /* update lamp transform and gather shadow lamps */ - for(SETLOOPER(G.scene, base)) { - ob= base->object; - - if(ob->type == OB_LAMP) - gpu_render_lamp_update(v3d, ob, NULL, ob->obmat, &shadows); - - if (ob->transflag & OB_DUPLI) { - DupliObject *dob; - ListBase *lb = object_duplilist(G.scene, ob); - - for(dob=lb->first; dob; dob=dob->next) - if(dob->ob->type==OB_LAMP) - gpu_render_lamp_update(v3d, dob->ob, ob, dob->mat, &shadows); - - free_object_duplilist(lb); - } - } - - /* render shadows after updating all lamps, nested object_duplilist - * don't work correct since it's replacing object matrices */ - for(shadow=shadows.first; shadow; shadow=shadow->next) { - /* this needs to be done better .. */ - float viewmat[4][4], winmat[4][4]; - int drawtype, lay, winsize, flag2; - - drawtype= v3d->drawtype; - lay= v3d->lay; - flag2= v3d->flag2 & V3D_SOLID_TEX; - - v3d->drawtype = OB_SOLID; - v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); - v3d->flag2 &= ~V3D_SOLID_TEX; - - GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); - drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1); - GPU_lamp_shadow_buffer_unbind(shadow->lamp); - - v3d->drawtype= drawtype; - v3d->lay= lay; - v3d->flag2 |= flag2; - } - - BLI_freelistN(&shadows); -} void drawview3dspace(ScrArea *sa, void *spacedata) { @@ -3160,16 +3063,9 @@ void drawview3dspace(ScrArea *sa, void *spacedata) for(SETLOOPER(G.scene->set, base)) object_handle_update(base->object); // bke_object.h } - - v3d->lay_used = 0; - for(base= G.scene->base.first; base; base= base->next) { - object_handle_update(base->object); // bke_object.h - v3d->lay_used |= base->lay; - } - /* shadow buffers, before we setup matrices */ - if(draw_glsl_material(NULL, v3d->drawtype)) - gpu_update_lamps_shadows(G.scene, v3d); + for(base= G.scene->base.first; base; base= base->next) + object_handle_update(base->object); // bke_object.h setwinmatrixview3d(sa->winx, sa->winy, NULL); /* 0= no pick rect */ setviewmatrixview3d(); /* note: calls where_is_object for camera... */ @@ -3312,8 +3208,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata) if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID); /* Transp and X-ray afterdraw stuff */ + view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); - view3d_draw_xray(v3d, 1); // clears zbuffer if it is used! if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) { if(G.f & G_SCULPTMODE) @@ -3394,7 +3290,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } ob= OBACT; - if(U.uiflag & USER_DRAWVIEWINFO) + if(ob && (U.uiflag & USER_DRAWVIEWINFO)) draw_selected_name(ob); draw_area_emboss(sa); @@ -3432,29 +3328,18 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } -void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int winy, float winmat[][4], int shadow) + +void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]) { Base *base; Scene *sce; - float v3dviewmat[4][4], v3dwinmat[4][4]; - - /* shadow buffers, before we setup matrices */ - if(!shadow && draw_glsl_material(NULL, v3d->drawtype)) - gpu_update_lamps_shadows(G.scene, v3d); + float v3dwinmat[4][4]; if(!winmat) setwinmatrixview3d(winx, winy, NULL); - if(viewmat) { - Mat4CpyMat4(v3dviewmat, viewmat); - Mat4CpyMat4(v3d->viewmat, viewmat); - } - else { - setviewmatrixview3d(); - Mat4CpyMat4(v3dviewmat, v3d->viewmat); - } - - myloadmatrix(v3dviewmat); + setviewmatrixview3d(); + myloadmatrix(v3d->viewmat); /* when winmat is not NULL, it overrides the regular window matrix */ glMatrixMode(GL_PROJECTION); @@ -3463,14 +3348,12 @@ void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int win mygetmatrix(v3dwinmat); glMatrixMode(GL_MODELVIEW); - Mat4MulMat4(v3d->persmat, v3dviewmat, v3dwinmat); + Mat4MulMat4(v3d->persmat, v3d->viewmat, v3dwinmat); Mat4Invert(v3d->persinv, v3d->persmat); Mat4Invert(v3d->viewinv, v3d->viewmat); - if(!shadow) { - GPU_free_images(); - reshadeall_displist(); - } + free_all_realtime_images(); + reshadeall_displist(); if(v3d->drawtype > OB_WIRE) { v3d->zbuf= TRUE; @@ -3548,8 +3431,8 @@ void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int win if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID); /* Transp and X-ray afterdraw stuff */ + view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); - view3d_draw_xray(v3d, !shadow); // clears zbuffer if it is used! if(v3d->flag & V3D_CLIPPING) view3d_clr_clipping(); @@ -3568,12 +3451,11 @@ void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int win G.f &= ~G_SIMULATION; - if(!shadow) { - glFlush(); - GPU_free_images(); - } + glFlush(); glLoadIdentity(); + + free_all_realtime_images(); } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index fe83976ee57..c454715b1df 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -74,7 +74,6 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -2154,7 +2153,7 @@ void paste_actdata () /* loop over curves, pasting keyframes */ for (ico= ipo_src->curve.first; ico; ico= ico->next) { - icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode, 1); + icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode); if (icu) { /* just start pasting, with the the first keyframe on the current frame, and so on */ diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 5e50c8117cc..35986fcff4a 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -439,109 +439,6 @@ void docenter_armature (Object *ob, int centermode) } } -/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */ -static void applyarmature_fix_boneparents (Object *armob) -{ - Object *ob; - - /* go through all objects in database */ - for (ob= G.main->object.first; ob; ob= ob->id.next) { - /* if parent is bone in this armature, apply corrections */ - if ((ob->parent == armob) && (ob->partype == PARBONE)) { - /* apply current transform from parent (not yet destroyed), - * then calculate new parent inverse matrix - */ - apply_obmat(ob); - - what_does_parent(ob); - Mat4Invert(ob->parentinv, workob.obmat); - } - } -} - -/* set the current pose as the restpose */ -void apply_armature_pose2bones(void) -{ - Object *ob; - bArmature *arm; - bPose *pose; - bPoseChannel *pchan; - EditBone *curbone; - - /* don't check if editmode (should be done by caller) */ - ob= OBACT; - if (ob->type!=OB_ARMATURE) return; - if (object_data_is_libdata(ob)) { - error_libdata(); - return; - } - arm= get_armature(ob); - - /* helpful warnings... */ - // TODO: add warnings to be careful about actions, applying deforms first, etc. - - /* Get editbones of active armature to alter */ - if (G.edbo.first) BLI_freelistN(&G.edbo); - make_boneList(&G.edbo, &arm->bonebase, NULL); - - /* get pose of active object and move it out of posemode */ - pose= ob->pose; - - for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { - curbone= editbone_name_exists(&G.edbo, pchan->name); - - /* simply copy the head/tail values from pchan over to curbone */ - VECCOPY(curbone->head, pchan->pose_head); - VECCOPY(curbone->tail, pchan->pose_tail); - - /* fix roll: - * 1. find auto-calculated roll value for this bone now - * 2. remove this from the 'visual' y-rotation - */ - { - float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3]; - float delta[3], eul[3]; - - /* obtain new auto y-rotation */ - VecSubf(delta, curbone->tail, curbone->head); - vec_roll_to_mat3(delta, 0.0, premat); - Mat3Inv(imat, premat); - - /* get pchan 'visual' matrix */ - Mat3CpyMat4(pmat, pchan->pose_mat); - - /* remove auto from visual and get euler rotation */ - Mat3MulMat3(tmat, imat, pmat); - Mat3ToEul(tmat, eul); - - /* just use this euler-y as new roll value */ - curbone->roll= eul[1]; - } - - /* clear transform values for pchan */ - pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0; - pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0; - pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1; - - /* set anim lock */ - curbone->flag |= BONE_UNKEYED; - } - - /* convert editbones back to bones */ - editbones_to_armature(&G.edbo, ob); - if (G.edbo.first) BLI_freelistN(&G.edbo); - - /* flush positions of posebones */ - where_is_pose(ob); - - /* fix parenting of objects which are bone-parented */ - applyarmature_fix_boneparents(ob); - - BIF_undo_push("Apply new restpose"); - allqueue(REDRAWVIEW3D, 0); -} - - /* Helper function for armature joining - link fixing */ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone) { diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c index 3f178e1ea2b..5de4c6ed23c 100644 --- a/source/blender/src/editdeform.c +++ b/source/blender/src/editdeform.c @@ -270,7 +270,7 @@ static void del_defgroup_update_users(Object *ob, int id) int a; /* these cases don't use names to refer to vertex groups, so when - * they get deleted the numbers get out of sync, this corrects that */ + * they get deleted the numbers get out of synce, this corrects that */ if(ob->soft) { if(ob->soft->vertgroup == id) diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 008ddf3b5f0..781210cd373 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -82,14 +82,13 @@ #include "BIF_space.h" /* for allqueue */ #include "BIF_drawimage.h" /* for allqueue */ +#include "BDR_drawmesh.h" #include "BDR_editface.h" #include "BDR_vpaint.h" #include "BDR_editface.h" #include "BDR_vpaint.h" -#include "GPU_draw.h" - #include "mydevice.h" #include "blendef.h" #include "butspace.h" @@ -1316,7 +1315,7 @@ void set_texturepaint() /* toggle */ if(G.f & G_TEXTUREPAINT) { G.f &= ~G_TEXTUREPAINT; - GPU_paint_set_mipmap(1); + texpaint_enable_mipmap(); } else if (me) { G.f |= G_TEXTUREPAINT; @@ -1325,7 +1324,7 @@ void set_texturepaint() /* toggle */ make_tfaces(me); brush_check_exists(&G.scene->toolsettings->imapaint.brush); - GPU_paint_set_mipmap(0); + texpaint_disable_mipmap(); } allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 09862636085..cd6aefdb87c 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -97,7 +97,6 @@ #include "BIF_editseq.h" #include "BIF_editview.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -1777,129 +1776,113 @@ void do_ipo_selectbuttons(void) - if bonename, the constname is the ipo to the constraint */ -/* note: check header_ipo.c, spaceipo_assign_ipo() too */ -Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename, short add) +/* note; check header_ipo.c, spaceipo_assign_ipo() too */ +Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename) { - /* lib-linked data is not appropriate here */ - if ((from==NULL) || (from->lib)) - return NULL; + + if(from==NULL || from->lib) return NULL; /* first check action ipos */ - if (actname && actname[0]) { + if(actname && actname[0]) { Object *ob= (Object *)from; bActionChannel *achan; - if (GS(from->name)!=ID_OB) { + if(GS(from->name)!=ID_OB) { printf("called ipo system for action with wrong base pointer\n"); return NULL; } - if ((ob->action==NULL) && (add)) + if(ob->action==NULL) ob->action= add_empty_action("Action"); - if (add) - achan= verify_action_channel(ob->action, actname); - else - achan= get_action_channel(ob->action, actname); + achan= verify_action_channel(ob->action, actname); - if (achan) { + if(achan) { /* automatically assign achan to act-group based on pchan's grouping */ - if ((blocktype == ID_PO) && (add)) + if (blocktype == ID_PO) verify_pchan2achan_grouping(ob->action, ob->pose, actname); /* constraint exception */ - if (blocktype==ID_CO) { - bConstraintChannel *conchan; - - if (add) - conchan= verify_constraint_channel(&achan->constraintChannels, constname); - else - conchan= get_constraint_channel(&achan->constraintChannels, constname); - - if (conchan) { - if ((conchan->ipo==NULL) && (add)) - conchan->ipo= add_ipo("CoIpo", ID_CO); - return conchan->ipo; + if(blocktype==ID_CO) { + bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname); + if(conchan->ipo==NULL) { + conchan->ipo= add_ipo("CoIpo", ID_CO); } + return conchan->ipo; } else { - if ((achan->ipo==NULL) && (add)) + if(achan->ipo==NULL) { achan->ipo= add_ipo("ActIpo", blocktype); + } + return achan->ipo; } } } else { - switch (GS(from->name)) { + + switch(GS(from->name)) { case ID_OB: { Object *ob= (Object *)from; /* constraint exception */ - if (blocktype==ID_CO) { + if(blocktype==ID_CO) { /* check the local constraint ipo */ - if (bonename && bonename[0] && ob->pose) { + if(bonename && bonename[0] && ob->pose) { bPoseChannel *pchan= get_pose_channel(ob->pose, bonename); bConstraint *con; - - for (con= pchan->constraints.first; con; con= con->next) { - if (strcmp(con->name, constname)==0) + for(con= pchan->constraints.first; con; con= con->next) + if(strcmp(con->name, constname)==0) break; - } - - if (con) { - if ((con->ipo==NULL) && (add)) + if(con) { + if(con->ipo==NULL) { con->ipo= add_ipo("CoIpo", ID_CO); + } return con->ipo; } } else { /* the actionchannel */ - bConstraintChannel *conchan; - - if (add) - conchan= verify_constraint_channel(&ob->constraintChannels, constname); - else - conchan= get_constraint_channel(&ob->constraintChannels, constname); - - if (conchan) { - if ((conchan->ipo==NULL) && (add)) - conchan->ipo= add_ipo("CoIpo", ID_CO); - return conchan->ipo; + bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname); + if(conchan->ipo==NULL) { + conchan->ipo= add_ipo("CoIpo", ID_CO); } + return conchan->ipo; } } - else if (blocktype==ID_OB) { - if ((ob->ipo==NULL) && (add)) + else if(blocktype==ID_OB) { + if(ob->ipo==NULL) { ob->ipo= add_ipo("ObIpo", ID_OB); + } return ob->ipo; } - else if (blocktype==ID_KE) { + else if(blocktype==ID_KE) { Key *key= ob_get_key((Object *)from); - if (key) { - if ((key->ipo==NULL) && (add)) + if(key) { + if(key->ipo==NULL) { key->ipo= add_ipo("KeyIpo", ID_KE); + } return key->ipo; } return NULL; } - else if (blocktype== ID_FLUIDSIM) { + else if(blocktype== ID_FLUIDSIM) { Object *ob= (Object *)from; - - if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { + if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { FluidsimSettings *fss= ob->fluidsimSettings; - - if ((fss->ipo==NULL) && (add)) + if(fss->ipo==NULL) { fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM); + //fprintf(stderr,"FSIPO NEW!\n"); + } return fss->ipo; } } - else if(blocktype== ID_PA) { + else if(blocktype== ID_PA){ Object *ob= (Object *)from; ParticleSystem *psys= psys_get_current(ob); - - if (psys) { - if ((psys->part->ipo==NULL) && (add)) + if(psys){ + if(psys->part->ipo==0) psys->part->ipo= add_ipo("ParticleIpo", ID_PA); return psys->part->ipo; } @@ -1910,27 +1893,30 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char case ID_MA: { Material *ma= (Material *)from; - - if ((ma->ipo==NULL) && (add)) + + if(ma->ipo==NULL) { ma->ipo= add_ipo("MatIpo", ID_MA); + } return ma->ipo; } break; case ID_TE: { Tex *tex= (Tex *)from; - - if ((tex->ipo==NULL) && (add)) + + if(tex->ipo==NULL) { tex->ipo= add_ipo("TexIpo", ID_TE); + } return tex->ipo; } break; case ID_SEQ: { Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */ - - if ((seq->ipo==NULL) && (add)) + + if(seq->ipo==NULL) { seq->ipo= add_ipo("SeqIpo", ID_SEQ); + } update_seq_ipo_rect(seq); return seq->ipo; } @@ -1939,17 +1925,19 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Curve *cu= (Curve *)from; - if ((cu->ipo==NULL) && (add)) + if(cu->ipo==NULL) { cu->ipo= add_ipo("CuIpo", ID_CU); + } return cu->ipo; } break; case ID_WO: { World *wo= (World *)from; - - if ((wo->ipo==NULL) && (add)) + + if(wo->ipo==NULL) { wo->ipo= add_ipo("WoIpo", ID_WO); + } return wo->ipo; } break; @@ -1957,26 +1945,29 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Lamp *la= (Lamp *)from; - if ((la->ipo==NULL) && (add)) + if(la->ipo==NULL) { la->ipo= add_ipo("LaIpo", ID_LA); + } return la->ipo; } break; case ID_CA: { Camera *ca= (Camera *)from; - - if ((ca->ipo==NULL) && (add)) + + if(ca->ipo==NULL) { ca->ipo= add_ipo("CaIpo", ID_CA); + } return ca->ipo; } break; case ID_SO: { bSound *snd= (bSound *)from; - - if ((snd->ipo==NULL) && (add)) + + if(snd->ipo==NULL) { snd->ipo= add_ipo("SndIpo", ID_SO); + } return snd->ipo; } } @@ -1988,36 +1979,32 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char /* returns and creates * Make sure functions check for NULL or they will crash! * */ -IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode, short add) +IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode) { Ipo *ipo; IpoCurve *icu= NULL; /* return 0 if lib */ - /* creates ipo too (if add) */ - ipo= verify_ipo(from, blocktype, actname, constname, bonename, add); + /* creates ipo too */ + ipo= verify_ipo(from, blocktype, actname, constname, bonename); - if (ipo && ipo->id.lib==NULL && from->lib==NULL) { - /* try to find matching curve */ - for (icu= ipo->curve.first; icu; icu= icu->next) { - if (icu->adrcode==adrcode) - break; - } + if(ipo && ipo->id.lib==NULL && from->lib==NULL) { - /* make a new one if none found (and can add) */ - if ((icu==NULL) && (add)) { + for(icu= ipo->curve.first; icu; icu= icu->next) { + if(icu->adrcode==adrcode) break; + } + if(icu==NULL) { icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); - icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ); - if (ipo->curve.first==NULL) - icu->flag |= IPO_ACTIVE; /* first one added active */ + icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ; + if(ipo->curve.first==NULL) icu->flag |= IPO_ACTIVE; /* first one added active */ icu->blocktype= blocktype; icu->adrcode= adrcode; set_icu_vars(icu); - BLI_addtail(&ipo->curve, icu); + BLI_addtail( &(ipo->curve), icu); switch (GS(from->name)) { case ID_SEQ: { @@ -2029,12 +2016,190 @@ IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constn } } } - - /* return ipo-curve */ + return icu; } +/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ +#define BEZT_INSERT_THRESH 0.00001 + +/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + const float frame= (item)? item->vec[1][0] : 0.0f; + + /* initialise replace-flag first */ + *replace= 0; + + /* sneaky optimisations (don't go through searching process if...): + * - keyframe to be added is to be added out of current bounds + * - keyframe to be added would replace one of the existing ones on bounds + */ + if ((arraylen <= 0) || ELEM(NULL, array, item)) { + printf("Warning: binarysearch_bezt_index encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum= array[0].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Keyframe */ + framenum= array[(arraylen-1)].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace= 1; + return (arraylen - 1); + } + else if (frame > framenum) + return arraylen; + } + + + /* most of the time, this loop is just to find where to put it + * 'loopbreaker' is just here to prevent infinite loops + */ + for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { + /* compute and get midpoint */ + int mid = (start + end) / 2; + float midfra= array[mid].vec[1][0]; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { + *replace = 1; + return mid; + } + + /* repeat in upper/lower half */ + if (frame > midfra) + start= mid + 1; + else if (frame < midfra) + end= mid - 1; + } + + /* print error if loop-limit exceeded */ + if (loopbreaker == (maxloop-1)) { + printf("Error: binarysearch_bezt_index was taking too long \n"); + + // include debug info + printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); + } + + /* not found, so return where to place it */ + return start; +} + +/* This function adds a given BezTriple to an IPO-Curve. It will allocate + * memory for the array if needed, and will insert the BezTriple into a + * suitable place in chronological order. + * + * NOTE: any recalculate of the IPO-Curve that needs to be done will need to + * be done by the caller. + */ +int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) +{ + BezTriple *newb; + int i= 0; + + if (icu->bezt == NULL) { + icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); + *(icu->bezt)= *bezt; + icu->totvert= 1; + } + else { + short replace = -1; + i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); + + if (replace) { + /* sanity check: 'i' may in rare cases exceed arraylen */ + if ((i >= 0) && (i < icu->totvert)) + *(icu->bezt + i) = *bezt; + } + else { + /* add new */ + newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); + + /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ + if (i > 0) + memcpy(newb, icu->bezt, i*sizeof(BezTriple)); + + /* add beztriple to paste at index i */ + *(newb + i)= *bezt; + + /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ + if (i < icu->totvert) + memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); + + /* replace (+ free) old with new */ + MEM_freeN(icu->bezt); + icu->bezt= newb; + + icu->totvert++; + } + } + + /* we need to return the index, so that some tools which do post-processing can + * detect where we added the BezTriple in the array + */ + return i; +} + +/* This function is a wrapper for insert_bezt_icu, and should be used when + * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere + * else yet. + * + * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. + */ +void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) +{ + BezTriple beztr; + int a, h1, h2; + + /* set all three points, for nicer start position */ + memset(&beztr, 0, sizeof(BezTriple)); + beztr.vec[0][0]= x; + beztr.vec[0][1]= y; + beztr.vec[1][0]= x; + beztr.vec[1][1]= y; + beztr.vec[2][0]= x; + beztr.vec[2][1]= y; + beztr.hide= IPO_BEZ; + beztr.f1= beztr.f2= beztr.f3= SELECT; + beztr.h1= beztr.h2= HD_AUTO; + + /* add temp beztriple to keyframes */ + a= insert_bezt_icu(icu, &beztr); + if (!fast) calchandles_ipocurve(icu); + + /* set handletype */ + if (icu->totvert > 2) { + BezTriple *bezt; + + h1= h2= HD_AUTO; + bezt= (icu->bezt + a); + + if (a > 0) h1= (bezt-1)->h2; + if (a < icu->totvert-1) h2= (bezt+1)->h1; + + bezt->h1= h1; + bezt->h2= h2; + + if (!fast) calchandles_ipocurve(icu); + } +} + void add_vert_ipo(void) { EditIpo *ei; @@ -2068,7 +2233,7 @@ void add_vert_ipo(void) if(ei->icu==NULL) { if(G.sipo->from) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); if (ei->icu) ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ; /* new curve could have been added, weak... */ else @@ -2094,6 +2259,525 @@ void add_vert_ipo(void) BIF_undo_push("Add Ipo vertex"); } +static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) +{ + if (blocktype==ID_PO) { + if (GS(id->name)==ID_OB) { + Object *ob= (Object *)id; + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + *vartype= IPO_FLOAT; + return get_pchan_ipo_poin(pchan, icu->adrcode); + } + else + return NULL; + } + return NULL; + } + else if (blocktype==ID_CO) { + if ((GS(id->name)==ID_OB) && (constname && constname[0])) { + Object *ob= (Object *)id; + bConstraint *con; + + /* assume that we only want the influence (as only used for Constraint Channels) */ + if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { + for (con= ob->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + else if (ob->pose) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + } + } + return NULL; + } + else + return get_ipo_poin(id, icu, vartype); + +} + +#define KEYNEEDED_DONTADD 0 +#define KEYNEEDED_JUSTADD 1 +#define KEYNEEDED_DELPREV 2 +#define KEYNEEDED_DELNEXT 3 + +static int new_key_needed(IpoCurve *icu, float cFrame, float nValue) +{ + /* This function determines whether a new keyframe is needed */ + /* Cases where keyframes should not be added: + * 1. Keyframe to be added bewteen two keyframes with similar values + * 2. Keyframe to be added on frame where two keyframes are already situated + * 3. Keyframe lies at point that intersects the linear line between two keyframes + */ + + BezTriple *bezt=NULL, *prev=NULL; + int totCount, i; + float valA = 0.0f, valB = 0.0f; + + /* safety checking */ + if (!icu) return KEYNEEDED_JUSTADD; + totCount= icu->totvert; + if (totCount==0) return KEYNEEDED_JUSTADD; + + /* loop through checking if any are the same */ + bezt= icu->bezt; + for (i=0; ivec[1][0]; + beztVal= bezt->vec[1][1]; + + if (prev) { + /* there is a keyframe before the one currently being examined */ + + /* get previous time+value */ + prevPosi= prev->vec[1][0]; + prevVal= prev->vec[1][1]; + + /* keyframe to be added at point where there are already two similar points? */ + if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { + return KEYNEEDED_DONTADD; + } + + /* keyframe between prev+current points ? */ + if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { + /* is the value of keyframe to be added the same as keyframes on either side ? */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { + return KEYNEEDED_DONTADD; + } + else { + float realVal; + + /* get real value of curve at that point */ + realVal= eval_icu(icu, cFrame); + + /* compare whether it's the same as proposed */ + if (IS_EQ(realVal, nValue)) + return KEYNEEDED_DONTADD; + else + return KEYNEEDED_JUSTADD; + } + } + + /* new keyframe before prev beztriple? */ + if (cFrame < prevPosi) { + /* A new keyframe will be added. However, whether the previous beztriple + * stays around or not depends on whether the values of previous/current + * beztriples and new keyframe are the same. + */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) + return KEYNEEDED_DELNEXT; + else + return KEYNEEDED_JUSTADD; + } + } + else { + /* just add a keyframe if there's only one keyframe + * and the new one occurs before the exisiting one does. + */ + if ((cFrame < beztPosi) && (totCount==1)) + return KEYNEEDED_JUSTADD; + } + + /* continue. frame to do not yet passed (or other conditions not met) */ + if (i < (totCount-1)) { + prev= bezt; + bezt++; + } + else + break; + } + + /* Frame in which to add a new-keyframe occurs after all other keys + * -> If there are at least two existing keyframes, then if the values of the + * last two keyframes and the new-keyframe match, the last existing keyframe + * gets deleted as it is no longer required. + * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last + * keyframe is not equal to last keyframe. + */ + bezt= (icu->bezt + (icu->totvert - 1)); + valA= bezt->vec[1][1]; + + if (prev) + valB= prev->vec[1][1]; + else + valB= bezt->vec[1][1] + 1.0f; + + if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) + return KEYNEEDED_DELPREV; + else + return KEYNEEDED_JUSTADD; +} + +/* a duplicate of insertkey that does not check for routing to insertmatrixkey + to avoid recursion problems */ +static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *constname, int adrcode) +{ + IpoCurve *icu; + Object *ob; + void *poin= NULL; + float curval, cfra; + int vartype; + int matset=0; + + if (matset==0) { + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); + + if(icu) { + + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + + if(poin) { + curval= read_ipo_poin(poin, vartype); + + cfra= frame_to_float(CFRA); + + /* if action is mapped in NLA, it returns a correction */ + if(actname && actname[0] && GS(id->name)==ID_OB) + cfra= get_action_frame((Object *)id, cfra); + + if( GS(id->name)==ID_OB ) { + ob= (Object *)id; + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + insert_vert_icu(icu, cfra, curval, 0); + } + } + } +} + +int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode) +{ + int matindex=0; + /* branch on adrcode and blocktype, generating the proper matrix-based + values to send to insertfloatkey */ + if (GS(id->name)==ID_OB) { + Object *ob= (Object *)id; + + if ( blocktype==ID_OB ){ //working with an object + if ((ob)&&!(ob->parent)) { + if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)) { //get a rotation + float eul[3]; + switch (adrcode) { + case OB_ROT_X: + matindex=0; + break; + case OB_ROT_Y: + matindex=1; + break; + case OB_ROT_Z: + matindex=2; + break; + } + Mat4ToEul(ob->obmat, eul); + insertfloatkey(id, ID_OB, actname, NULL, adrcode, eul[matindex]*(5.72958)); + return 1; + } else if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)) {//get a translation + switch (adrcode) { + case OB_LOC_X: + matindex=0; + break; + case OB_LOC_Y: + matindex=1; + break; + case OB_LOC_Z: + matindex=2; + break; + } + insertfloatkey(id, ID_OB, actname, NULL, adrcode, ob->obmat[3][matindex]); + return 1; + } + } + } else if ( blocktype==ID_PO) { //working with a pose channel + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + if (pchan) { + if ((adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { + switch (adrcode) { + case AC_LOC_X: + matindex=0; + break; + case AC_LOC_Y: + matindex=1; + break; + case AC_LOC_Z: + matindex=2; + break; + } + if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_CONNECTED))) { /* don't use for non-connected child bones */ + float delta_mat[4][4]; + armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat); + insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, delta_mat[3][matindex]); + return 1; + } + } else if ((adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { + float tmat[4][4], trimat[3][3], localQuat[4]; + + switch (adrcode) { + case AC_QUAT_W: + matindex=0; + break; + case AC_QUAT_X: + matindex=1; + break; + case AC_QUAT_Y: + matindex=2; + break; + case AC_QUAT_Z: + matindex=3; + break; + } + + /* it should be reasonable to assume that we are keyframing on the active object, although it is not + * strictly required for this particular space conversion, arg1 must not be null for this to work + */ + Mat4CpyMat4(tmat, pchan->pose_mat); + constraint_mat_convertspace(OBACT, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + + Mat3CpyMat4(trimat, tmat); + Mat3ToQuat_is_ok(trimat, localQuat); + insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, localQuat[matindex]); + + return 1; + } + } + } + } + /* failed to set a matrix key -- use traditional, but the non-recursing version */ + insertkey_nonrecurs(id,blocktype,actname,constname,adrcode); + return 0; +} + +static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrcode) +{ /* This function matches constraint blocks with adrcodes to see if the + visual keying method should be used. For example, an object looking to key + location and having a CopyLoc constraint would return true. */ + + Object *ob=NULL; + int foundmatch=0; + int searchtype=0; + bConstraint *conref=NULL, *con=NULL; + + /*Retrieve constraint list*/ + if( GS(id->name)==ID_OB ) + ob= (Object *)id; + if (ob) { + if (blocktype==ID_PO) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + conref=pchan->constraints.first; + } else if (blocktype==ID_OB) { + conref=ob->constraints.first; + } + + if (conref) { + /*Set search type: 1 is for translation contraints, 2 is for rotation*/ + if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)||(adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { + searchtype=1; + } else if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)||(adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { + searchtype=2; + } + + if (searchtype>0) { + for (con=conref; (con)&&(foundmatch==0); con=con->next) { + switch (con->type) { + /* match constraint types to which kinds of keying they would affect */ + case CONSTRAINT_TYPE_CHILDOF: + foundmatch=1; + break; + case CONSTRAINT_TYPE_TRACKTO: + if (searchtype==2) foundmatch=1; + break; + case CONSTRAINT_TYPE_FOLLOWPATH: + foundmatch=1; + break; + case CONSTRAINT_TYPE_ROTLIMIT: + if (searchtype==2) foundmatch=1; + break; + case CONSTRAINT_TYPE_LOCLIMIT: + if (searchtype==1) foundmatch=1; + break; + case CONSTRAINT_TYPE_ROTLIKE: + if (searchtype==2) foundmatch=1; + break; + case CONSTRAINT_TYPE_LOCLIKE: + if (searchtype==1) foundmatch=1; + break; + case CONSTRAINT_TYPE_LOCKTRACK: + if (searchtype==2) foundmatch=1; + break; + case CONSTRAINT_TYPE_DISTLIMIT: + if (searchtype==1) foundmatch=1; + break; + case CONSTRAINT_TYPE_MINMAX: + if (searchtype==1) foundmatch=1; + break; + case CONSTRAINT_TYPE_TRANSFORM: + foundmatch=1; + break; + default: + break; + } + } + } + } + } + + return foundmatch; + +} + +void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast) +{ + IpoCurve *icu; + Object *ob; + void *poin= NULL; + float curval, cfra; + int vartype; + int matset=0; + + if ((IS_AUTOKEY_FLAG(AUTOMATKEY))&&(match_adr_constraint(id, blocktype, actname, adrcode))) { + matset=insertmatrixkey(id, blocktype, actname, constname, adrcode); + } + if (matset==0) { + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); + + if(icu) { + + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + + if(poin) { + curval= read_ipo_poin(poin, vartype); + + cfra= frame_to_float(CFRA); + + /* if action is mapped in NLA, it returns a correction */ + if(actname && actname[0] && GS(id->name)==ID_OB) + cfra= get_action_frame((Object *)id, cfra); + + if( GS(id->name)==ID_OB ) { + ob= (Object *)id; + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + insert_vert_icu(icu, cfra, curval, fast); + } + } + } +} + + + +/* This function is a 'smarter' version of the insert key code. + * It uses an auxilliary function to check whether a keyframe is really needed */ +void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode) +{ + IpoCurve *icu; + Object *ob; + void *poin= NULL; + float curval, cfra; + int vartype; + int insert_mode; + + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); + + if(icu) { + + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + + if(poin) { + curval= read_ipo_poin(poin, vartype); + + cfra= frame_to_float(CFRA); + + /* if action is mapped in NLA, it returns a correction */ + if(actname && actname[0] && GS(id->name)==ID_OB) + cfra= get_action_frame((Object *)id, cfra); + + if( GS(id->name)==ID_OB ) { + ob= (Object *)id; + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* check whether this curve really needs a new keyframe */ + insert_mode= new_key_needed(icu, cfra, curval); + + /* insert new keyframe at current frame */ + if (insert_mode) + insert_vert_icu(icu, cfra, curval, 0); + + /* delete keyframe immediately before/after newly added */ + switch (insert_mode) { + case KEYNEEDED_DELPREV: + delete_icu_key(icu, icu->totvert-2, 1); + break; + case KEYNEEDED_DELNEXT: + delete_icu_key(icu, 1, 1); + break; + } + } + } +} + +/* For inserting keys based on an arbitrary float value */ +void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey) +{ + IpoCurve *icu; + Object *ob; + void *poin= NULL; + float cfra; + int vartype; + + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); + + if(icu) { + + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + + if(poin) { + + cfra= frame_to_float(CFRA); + + /* if action is mapped in NLA, it returns a correction */ + if(actname && actname[0] && GS(id->name)==ID_OB) + cfra= get_action_frame((Object *)id, cfra); + + if( GS(id->name)==ID_OB ) { + ob= (Object *)id; + if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* insert new keyframe at current frame */ + insert_vert_icu(icu, cfra, floatkey, 0); + } + } +} void insertkey_editipo(void) { @@ -2225,6 +2909,598 @@ void insertkey_editipo(void) } +void common_insertkey(void) +{ + Base *base; + Object *ob; + Material *ma; + ID *id; + IpoCurve *icu; + World *wo; + Lamp *la; + Tex *te; + int tlay, map, event; + char menustr[256]; + + if(curarea->spacetype==SPACE_IPO) { + insertkey_editipo(); + } + else if(curarea->spacetype==SPACE_ACTION) { + insertkey_action(); + } + else if(curarea->spacetype==SPACE_BUTS) { + if(G.buts->mainb==CONTEXT_SHADING) { + int tab= G.buts->tab[CONTEXT_SHADING]; + + if(tab==TAB_SHADING_MAT) { + ma = G.buts->lockpoin; + ma = editnode_get_active_material(ma); + id = (ID *)ma; + + if(id) { + event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|Halo Size%x2|Mode %x3|All Color%x10|All Mirror%x14|Ofs%x12|Size%x13|All Mapping%x11"); + if(event== -1) return; + + map= texchannel_to_adrcode(ma->texact); + + if(event==0 || event==10) { + insertkey(id, ID_MA, NULL, NULL, MA_COL_R, 0); + insertkey(id, ID_MA, NULL, NULL, MA_COL_G, 0); + insertkey(id, ID_MA, NULL, NULL, MA_COL_B, 0); + } + if(event==1 || event==10) { + insertkey(id, ID_MA, NULL, NULL, MA_ALPHA, 0); + } + if(event==2 || event==10) { + insertkey(id, ID_MA, NULL, NULL, MA_HASIZE, 0); + } + if(event==3 || event==10) { + insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); + } + if(event==10) { + insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R, 0); + insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G, 0); + insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B, 0); + insertkey(id, ID_MA, NULL, NULL, MA_REF, 0); + insertkey(id, ID_MA, NULL, NULL, MA_EMIT, 0); + insertkey(id, ID_MA, NULL, NULL, MA_AMB, 0); + insertkey(id, ID_MA, NULL, NULL, MA_SPEC, 0); + insertkey(id, ID_MA, NULL, NULL, MA_HARD, 0); + insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); + insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU, 0); + insertkey(id, ID_MA, NULL, NULL, MA_ADD, 0); + } + if(event==14) { + insertkey(id, ID_MA, NULL, NULL, MA_RAYM, 0); + insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR, 0); + insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI, 0); + insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA, 0); + insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI, 0); + } + if(event==12 || event==11) { + insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z, 0); + } + if(event==13 || event==11) { + insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z, 0); + } + if(event==11) { + insertkey(id, ID_MA, NULL, NULL, map+MAP_R, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_G, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_B, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF, 0); + insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP, 0); + } + } + } + else if(tab==TAB_SHADING_WORLD) { + id= G.buts->lockpoin; + wo= G.buts->lockpoin; + if(id) { + event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13"); + if(event== -1) return; + + map= texchannel_to_adrcode(wo->texact); + + if(event==0) { + insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R, 0); + insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G, 0); + insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B, 0); + } + if(event==1) { + insertkey(id, ID_WO, NULL, NULL, WO_HOR_R, 0); + insertkey(id, ID_WO, NULL, NULL, WO_HOR_G, 0); + insertkey(id, ID_WO, NULL, NULL, WO_HOR_B, 0); + } + if(event==2) { + insertkey(id, ID_WO, NULL, NULL, WO_MISI, 0); + insertkey(id, ID_WO, NULL, NULL, WO_MISTDI, 0); + insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA, 0); + insertkey(id, ID_WO, NULL, NULL, WO_MISTHI, 0); + } + if(event==3) { + insertkey(id, ID_WO, NULL, NULL, WO_STAR_R, 0); + insertkey(id, ID_WO, NULL, NULL, WO_STAR_G, 0); + insertkey(id, ID_WO, NULL, NULL, WO_STAR_B, 0); + insertkey(id, ID_WO, NULL, NULL, WO_STARDIST, 0); + insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE, 0); + } + if(event==12) { + insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X, 0); + insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y, 0); + insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z, 0); + } + if(event==13) { + insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X, 0); + insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y, 0); + insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z, 0); + } + } + } + else if(tab==TAB_SHADING_LAMP) { + id= G.buts->lockpoin; + la= G.buts->lockpoin; + if(id) { + event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13"); + if(event== -1) return; + + map= texchannel_to_adrcode(la->texact); + + if(event==0) { + insertkey(id, ID_LA, NULL, NULL, LA_COL_R, 0); + insertkey(id, ID_LA, NULL, NULL, LA_COL_G, 0); + insertkey(id, ID_LA, NULL, NULL, LA_COL_B, 0); + } + if(event==1) { + insertkey(id, ID_LA, NULL, NULL, LA_ENERGY, 0); + } + if(event==2) { + insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI, 0); + } + if(event==12) { + insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X, 0); + insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y, 0); + insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z, 0); + } + if(event==13) { + insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X, 0); + insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y, 0); + insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z, 0); + } + + } + } + else if(tab==TAB_SHADING_TEX) { + id= G.buts->lockpoin; + te= G.buts->lockpoin; + if(id) { + event= pupmenu("Insert Key %t|Clouds%x0|Marble%x1|Stucci%x2|Wood%x3|Magic%x4|Blend%x5|Musgrave%x6|Voronoi%x7|DistortedNoise%x8|ColorFilter%x9"); + if(event== -1) return; + + if(event==0) { + insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); + insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); + } + if(event==1) { + insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); + insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); + insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); + } + if(event==2) { + insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); + insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); + } + if(event==3) { + insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); + insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); + insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); + insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); + } + if(event==4) { + insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); + insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); + } + if(event==5) { + insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); + } + if(event==6) { + insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MGH, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_LAC, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); + } + if(event==7) { + insertkey(id, ID_TE, NULL, NULL, TE_VNW1, 0); + insertkey(id, ID_TE, NULL, NULL, TE_VNW2, 0); + insertkey(id, ID_TE, NULL, NULL, TE_VNW3, 0); + insertkey(id, ID_TE, NULL, NULL, TE_VNW4, 0); + insertkey(id, ID_TE, NULL, NULL, TE_VNMEXP, 0); + insertkey(id, ID_TE, NULL, NULL, TE_VN_DISTM, 0); + insertkey(id, ID_TE, NULL, NULL, TE_VN_COLT, 0); + insertkey(id, ID_TE, NULL, NULL, TE_ISCA, 0); + insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); + } + if(event==8) { + insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); + insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); + insertkey(id, ID_TE, NULL, NULL, TE_DISTA, 0); + } + if(event==9) { + insertkey(id, ID_TE, NULL, NULL, TE_COL_R, 0); + insertkey(id, ID_TE, NULL, NULL, TE_COL_G, 0); + insertkey(id, ID_TE, NULL, NULL, TE_COL_B, 0); + insertkey(id, ID_TE, NULL, NULL, TE_BRIGHT, 0); + insertkey(id, ID_TE, NULL, NULL, TE_CONTRA, 0); + } + } + } + } + else if(G.buts->mainb==CONTEXT_OBJECT) { + ob= OBACT; + if(ob) { + id= (ID *) (ob); + if(id) { + if(ob->type==OB_MESH) + event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4"); + else + event= pupmenu("Insert Key %t|Force Strength%x3|Force Falloff%x4"); + if(event == -1) return; + + if(event==0) { + insertkey(id, ID_OB, NULL, NULL, OB_PD_SDAMP, 0); + } + if(event==1) { + insertkey(id, ID_OB, NULL, NULL, OB_PD_RDAMP, 0); + } + if(event==2) { + insertkey(id, ID_OB, NULL, NULL, OB_PD_PERM, 0); + } + if(event==3) { + insertkey(id, ID_OB, NULL, NULL, OB_PD_FSTR, 0); + } + if(event==4) { + insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL, 0); + } + if(event==5) { + insertkey(id, ID_OB, NULL, NULL, OB_PD_FMAXD, 0); + } + } + } + } + else if(G.buts->mainb==CONTEXT_EDITING) { + ob= OBACT; + if(ob && ob->type==OB_CAMERA) { + id= G.buts->lockpoin; + if(id) { + /* yafray: insert key extended with aperture and focal distance */ + /* qdn: FocalDistance now enabled for Blender as wel, for use with defocus node */ + if (G.scene->r.renderer==R_INTERN) + event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|FocalDistance%x3|Viewplane Shift%x4"); + else + event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|Aperture%x2|FocalDistance%x3"); + if(event== -1) return; + + if(event==0) { + insertkey(id, ID_CA, NULL, NULL, CAM_LENS, 0); + } + else if(event==1) { + insertkey(id, ID_CA, NULL, NULL, CAM_STA, 0); + insertkey(id, ID_CA, NULL, NULL, CAM_END, 0); + } + else if(event==2) { + insertkey(id, ID_CA, NULL, NULL, CAM_YF_APERT, 0); + } + else if(event==3) { + insertkey(id, ID_CA, NULL, NULL, CAM_YF_FDIST, 0); + } + else if(event==4) { + insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_X, 0); + insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_Y, 0); + } + } + } + } + else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) { + if(G.ssound) { + id= G.buts->lockpoin; + if(id) { + event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3"); + if(event== -1) return; + + if(event==0) { + insertkey(id, ID_SO, NULL, NULL, SND_VOLUME, 0); + } + if(event==1) { + insertkey(id, ID_SO, NULL, NULL, SND_PITCH, 0); + } + if(event==2) { + insertkey(id, ID_SO, NULL, NULL, SND_PANNING, 0); + } + if(event==3) { + insertkey(id, ID_SO, NULL, NULL, SND_ATTEN, 0); + } + } + } + } + + BIF_undo_push("Insert Key Buttons"); + + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + allqueue(REDRAWIPO, 0); + allspace(REMAKEIPO, 0); + + } + else if(curarea->spacetype==SPACE_VIEW3D) { + ob= OBACT; + + if (ob && (ob->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + + set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) + if (pchan->flag & POSE_KEY) + break; + if(pchan==NULL) return; + strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); + } + else { + base= FIRSTBASE; + while(base) { + if (TESTBASELIB(base)) break; + base= base->next; + } + if(base==NULL) return; + strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Layer%x5|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); + } + + if(ob) { + if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7"); + else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7"); + else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7"); + else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7"); + } + + event= pupmenu(menustr); + if(event== -1) return; + + if(event==7) { // ob != NULL + insert_shapekey(ob); + return; + } + + if (ob && (ob->flag & OB_POSEMODE)){ + bPoseChannel *pchan; + short recalc_bonepaths= 0; + + if (ob->action && ob->action->id.lib) { + error ("Can't key libactions"); + return; + } + + id= &ob->id; + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { + if (pchan->flag & POSE_KEY) { + /* insert relevant keyframes */ + if(event==0 || event==3 ||event==4) { + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); + } + if(event==1 || event==3 || event==4) { + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); + } + if(event==2 || event==4) { + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); + } + if (event==9 && ob->action) { + bActionChannel *achan; + + for (achan = ob->action->chanbase.first; achan; achan=achan->next){ + if (achan->ipo && !strcmp (achan->name, pchan->name)){ + for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + insertkey(id, ID_PO, achan->name, NULL, icu->adrcode, 0); + } + break; + } + } + } + if(event==11 || event==13) { + int matok=0; + /* check one to make sure we're not trying to set visual loc keys on + bones inside of a chain, which only leads to tears. */ + matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); + + if (matok == 0) { + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); + } + } + if(event==12 || event==13) { + int matok=0; + /* check one to make sure we're not trying to set visual rot keys on + bones inside of a chain, which only leads to tears. */ + matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); + insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); + + if (matok == 0) { + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + } + } + if (event==15 && ob->action) { + bActionChannel *achan; + + for (achan = ob->action->chanbase.first; achan; achan=achan->next){ + if (achan->ipo && !strcmp (achan->name, pchan->name)){ + for (icu = achan->ipo->curve.first; icu; icu=icu->next){ + insertkey_smarter(id, ID_PO, achan->name, NULL, icu->adrcode); + } + break; + } + } + } + + /* clear unkeyed flag (it doesn't matter if it's set or not) */ + if (pchan->bone) + pchan->bone->flag &= ~BONE_UNKEYED; + + /* check if bone has a path */ + if (pchan->path) + recalc_bonepaths = 1; + } + } + + /* recalculate ipo handles, etc. */ + if(ob->action) + remake_action_ipos(ob->action); + + /* recalculate bone-paths on adding new keyframe? */ + // TODO: currently, there is no setting to turn this on/off globally + if (recalc_bonepaths) + pose_recalculate_paths(ob); + + + allqueue(REDRAWIPO, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + } + else { + base= FIRSTBASE; + while(base) { + if (TESTBASELIB(base)) { + char *actname= NULL; + + id= (ID *)(base->object); + + if(base->object->ipoflag & OB_ACTION_OB) + actname= "Object"; + + /* all curves in ipo deselect */ + if(base->object->ipo || base->object->action) { + if (base->object->ipo) { + icu= base->object->ipo->curve.first; + } + else { + bActionChannel *achan; + achan= get_action_channel(base->object->action, actname); + + if (achan && achan->ipo) + icu= achan->ipo->curve.first; + else + icu= NULL; + } + + while(icu) { + icu->flag &= ~IPO_SELECT; + + switch (event) { + case 9: + insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); + break; + case 15: + insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); + break; + } + icu= icu->next; + } + } + + if(event==0 || event==3 ||event==4) { + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); + } + if(event==1 || event==3 ||event==4) { + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); + } + if(event==2 || event==4) { + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); + } + if(event==5) { + /* remove localview */ + tlay= base->object->lay; + base->object->lay &= 0xFFFFFF; + insertkey(id, ID_OB, actname, NULL, OB_LAY, 0); + base->object->lay= tlay; + } + if(event==11 || event==13) { + insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_X); + insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Y); + insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Z); + } + if(event==12 || event==13) { + insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_X); + insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Y); + insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Z); + } + base->object->recalc |= OB_RECALC_OB; + } + base= base->next; + } + } + + if(event==0) BIF_undo_push("Insert Loc Key"); + else if(event==1) BIF_undo_push("Insert Rot Key"); + else if(event==2) BIF_undo_push("Insert Scale Key"); + else if(event==3) BIF_undo_push("Insert LocRot Key"); + else if(event==4) BIF_undo_push("Insert LocRotScale Key"); + else if(event==5) BIF_undo_push("Insert Layer Key"); + else if(event==7) BIF_undo_push("Insert Vertex Key"); + else if(event==9) BIF_undo_push("Insert Avail Key"); + else if(event==11) BIF_undo_push("Insert VisualLoc Key"); + else if(event==12) BIF_undo_push("Insert VisualRot Key"); + else if(event==13) BIF_undo_push("Insert VisualLocRot Key"); + else if(event==15) BIF_undo_push("Insert Needed Key"); + + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); + + allspace(REMAKEIPO, 0); + allqueue(REDRAWIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWACTION, 0); + allqueue(REDRAWNLA, 0); + } + +} + /* ****************************************************************************** */ void add_duplicate_editipo(void) @@ -2375,7 +3651,6 @@ void remove_doubles_ipo(void) } deselectall_editipo(); - BIF_undo_push("Remove Doubles (IPO)"); } @@ -3198,7 +4473,7 @@ void paste_editipo(void) int i; /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); if (ei->icu == NULL) return; /* Copy selected beztriples from source icu onto this edit-icu, @@ -3239,7 +4514,7 @@ void paste_editipo(void) else { /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); if (ei->icu==NULL) return; /* clear exisiting dynamic memory (keyframes, driver) */ @@ -4354,7 +5629,7 @@ void ipo_record(void) /* make curves ready, start values */ if(ei1->icu==NULL) - ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode, 1); + ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode); if(ei1->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei1->icu, &type); @@ -4364,7 +5639,7 @@ void ipo_record(void) if(ei2) { if(ei2->icu==NULL) - ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode, 1); + ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode); if(ei2->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei2->icu, &type); diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c index 7bfd097b87f..e1e286e10cf 100644 --- a/source/blender/src/editipo_lib.c +++ b/source/blender/src/editipo_lib.c @@ -392,15 +392,7 @@ int texchannel_to_adrcode(int channel) case 6: return MA_MAP7; case 7: return MA_MAP8; case 8: return MA_MAP9; - case 9: return MA_MAP10; - case 10: return MA_MAP11; - case 11: return MA_MAP12; - case 12: return MA_MAP13; - case 13: return MA_MAP14; - case 14: return MA_MAP15; - case 15: return MA_MAP16; - case 16: return MA_MAP17; - case 17: return MA_MAP18; + case 9: return MA_MAP10; default: return 0; } } diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index 24bb111c8d1..f03de1ff383 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -237,6 +237,7 @@ void deselectall_editipo(void) } } + BIF_undo_push("(De)select all Ipo"); scrarea_queue_winredraw(curarea); } diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index dbabf9d19fb..ce798064632 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -70,7 +70,6 @@ #include "BIF_editkey.h" #include "BIF_editview.h" -#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -171,9 +170,9 @@ static void rvk_slider_func(void *voidob, void *voidkeynum) /* ipo on action or ob? */ if(ob->ipoflag & OB_ACTION_KEY) - icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum, 1); + icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum); else - icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum, 1); + icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum); if (icu) { /* if the ipocurve exists, try to get a bezier diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c index 06b092a30ac..0782e012f68 100644 --- a/source/blender/src/editlattice.c +++ b/source/blender/src/editlattice.c @@ -131,7 +131,7 @@ void make_editLatt(void) copy_dverts(editLatt->dvert, lt->dvert, tot); } - BIF_undo_push("Original"); + BIF_undo_push("original"); } diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index b75f7e07143..188f7476728 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -1683,10 +1683,6 @@ void separate_mesh(void) efa= em->faces.first; while(efa) { vl1= efa->next; - if (efa == G.editMesh->act_face && (efa->f & SELECT)) { - EM_set_actFace(NULL); - } - if((efa->f & SELECT)==0) { BLI_remlink(&em->faces, efa); BLI_addtail(&edvl, efa); diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index 71e04541643..9516f39b05c 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -869,152 +869,6 @@ int confirm_objectExists( Mesh **me, float mat[][3] ) return newob; } -// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker -// this hack is only used so that scons+mingw + split-sources hack works - // ------------------------------- start copied code -/* these are not the monkeys you are looking for */ -int monkeyo= 4; -int monkeynv= 271; -int monkeynf= 250; -signed char monkeyv[271][3]= { -{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92}, -{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83}, -{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102}, -{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92}, -{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74}, -{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99}, -{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105}, -{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100}, -{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100}, -{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73}, -{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45}, -{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68}, -{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68}, -{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80}, -{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96}, -{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90}, -{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85}, -{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94}, -{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96}, -{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95}, -{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84}, -{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109}, -{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88}, -{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82}, -{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96}, -{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96}, -{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100}, -{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104}, -{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71}, -{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88}, -{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84}, -{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81}, -{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99}, -{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87}, -{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100}, -{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97}, -{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86}, -{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96}, -{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79}, -{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59}, -{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37}, -{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59}, -{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7}, -{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9}, -{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52}, -{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51}, -{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55}, -{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34}, -{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30}, -{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7}, -{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57}, -{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26}, -{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16}, -{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54}, -{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52}, -{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28}, -{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57}, -{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27}, -{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35}, -{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24}, -{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41}, -{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41}, -{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62}, -{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42}, -{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48}, -{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62}, -{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63}, -{-26,-16,-42},{-17,49,-49}, -}; - -signed char monkeyf[250][4]= { -{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, -{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, -{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, -{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, -{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, -{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, -{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, -{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, -{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, -{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, -{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, -{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, -{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, -{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, -{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, -{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, -{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, -{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, -{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, -{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, -{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, -{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, -{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, -{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, -{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, -{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, -{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, -{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, -{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, -{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, -{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, -{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, -{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, -{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, -{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, -{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, -{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, -{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, -{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, -{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, -{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, -{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, -{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, -{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, -{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, -{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, -{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, -{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, -{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, -{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, -{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, -{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, -{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, -{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, -{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, -{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, -{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, -{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, -{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, -{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, -{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, -{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, -{-68,-67,24,-33}, -}; - // ------------------------------- end copied code - - void make_prim(int type, float imat[3][3], int tot, int seg, int subdiv, float dia, float d, int ext, int fill, float cent[3]) @@ -1168,9 +1022,9 @@ void make_prim(int type, float imat[3][3], int tot, int seg, break; case 13: /* Monkey */ { - //extern int monkeyo, monkeynv, monkeynf; - //extern signed char monkeyf[][4]; - //extern signed char monkeyv[][3]; + extern int monkeyo, monkeynv, monkeynf; + extern signed char monkeyf[][4]; + extern signed char monkeyv[][3]; EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); EditFace *efa; int i; diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c index 2c5386b86b6..4ac5072b212 100644 --- a/source/blender/src/editmesh_loop.c +++ b/source/blender/src/editmesh_loop.c @@ -745,9 +745,9 @@ void KnifeSubdivide(char mode) eed= eed->next; } - if(mode==KNIFE_EXACT) esubdivideflag(SELECT, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MIDPOINT) esubdivideflag(SELECT, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MULTICUT) esubdivideflag(SELECT, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); + if (mode==KNIFE_EXACT) esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); eed=em->edges.first; while(eed){ diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index 81d0ffeeb3b..c162c904776 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -4202,7 +4202,7 @@ void editmesh_align_view_to_selected(View3D *v3d, int axis) void vertexsmooth(void) { EditMesh *em = G.editMesh; - EditVert *eve, *eve_mir = NULL; + EditVert *eve; EditEdge *eed; float *adror, *adr, fac; float fvec[3]; @@ -4285,19 +4285,13 @@ void vertexsmooth(void) while(eve) { if(eve->f & SELECT) { if(eve->f1) { - - if (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) { - eve_mir= editmesh_get_x_mirror_vert(G.obedit, eve->co); - } - adr = eve->tmp.p; fac= 0.5/(float)eve->f1; eve->co[0]= 0.5*eve->co[0]+fac*adr[0]; eve->co[1]= 0.5*eve->co[1]+fac*adr[1]; eve->co[2]= 0.5*eve->co[2]+fac*adr[2]; - - + /* clip if needed by mirror modifier */ if (eve->f2) { if (eve->f2 & 1) { @@ -4310,13 +4304,6 @@ void vertexsmooth(void) eve->co[2]= 0.0f; } } - - if (eve_mir) { - eve_mir->co[0]=-eve->co[0]; - eve_mir->co[1]= eve->co[1]; - eve_mir->co[2]= eve->co[2]; - } - } eve->tmp.p= NULL; } diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 4cf3b410393..3615a4ad851 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -2698,21 +2698,16 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype) free_tagged_edges_faces(em->edges.first, em->faces.first); if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) { - /* bugfix: vertex could get flagged as "not-selected" - // solution: clear flags before, not at the same time as setting SELECT flag -dg - */ - for(eed = em->edges.first;eed;eed = eed->next) { - if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) { - eed->f &= !flag; - EM_select_edge(eed,0); - } - } for(eed = em->edges.first;eed;eed = eed->next) { if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { eed->f |= flag; - EM_select_edge(eed,1); + EM_select_edge(eed,1); + + }else{ + eed->f &= !flag; + EM_select_edge(eed,0); } - } + } } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) { for(eed = em->edges.first;eed;eed = eed->next) { if(eed->f2 & EDGEINNER) { @@ -4653,12 +4648,6 @@ void bevel_menu_old() } /* *********** END BEVEL *********/ -typedef struct SlideUv { - float origuv[2]; - float *uv_up, *uv_down; - //float *fuv[4]; - LinkNode *fuv_list; -} SlideUv; typedef struct SlideVert { EditEdge *up,*down; @@ -4666,19 +4655,9 @@ typedef struct SlideVert { } SlideVert; int EdgeLoopDelete(void) { - - /* temporal flag setting so we keep UVs when deleting edge loops, - * this is a bit of a hack but it works how you would want in almost all cases */ - short uvcalc_flag_orig = G.scene->toolsettings->uvcalc_flag; - G.scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; - if(!EdgeSlide(1, 1)) { return 0; } - - /* restore uvcalc flag */ - G.scene->toolsettings->uvcalc_flag = uvcalc_flag_orig; - EM_select_more(); removedoublesflag(1,0, 0.001); EM_select_flush(); @@ -4688,35 +4667,22 @@ int EdgeLoopDelete(void) { int EdgeSlide(short immediate, float imperc) { - NumInput num; EditMesh *em = G.editMesh; EditFace *efa; EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; EditVert *ev, *nearest; LinkNode *edgelist = NULL, *vertlist=NULL, *look; GHash *vertgh; - SlideVert *tempsv; float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4]; float shiftlabda= 0.0f,len = 0.0f; int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; int wasshift = 0; - - /* UV correction vars */ - GHash **uvarray= NULL; - int uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE); - int uvlay_idx; - SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; - float uv_tmp[2]; - LinkNode *fuv_link; - short event, draw=1; short mval[2], mvalo[2]; char str[128]; float labda = 0.0f; - initNumInput(&num); - view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat); mvalo[0] = -1; mvalo[1] = -1; @@ -5016,99 +4982,6 @@ int EdgeSlide(short immediate, float imperc) look = look->next; } - - - if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { - int maxnum = 0; - uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); - suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */ - suv = NULL; - - for (uvlay_idx=0; uvlay_idxverts.first;ev;ev=ev->next) { - ev->tmp.l = 0; - } - look = vertlist; - while(look) { - float *uv_new; - tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); - - ev = look->link; - suv = NULL; - for(efa = em->faces.first;efa;efa=efa->next) { - if (ev->tmp.l != -1) { /* test for self, in this case its invalid */ - int k=-1; /* face corner */ - - /* Is this vert in the faces corner? */ - if (efa->v1==ev) k=0; - else if (efa->v2==ev) k=1; - else if (efa->v3==ev) k=2; - else if (efa->v4 && efa->v4==ev) k=3; - - if (k != -1) { - MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx); - EditVert *ev_up, *ev_down; - - uv_new = tf->uv[k]; - - if (ev->tmp.l) { - if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) { - ev->tmp.l = -1; /* Tag as invalid */ - BLI_linklist_free(suv->fuv_list,NULL); - suv->fuv_list = NULL; - BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL); - suv = NULL; - break; - } - } else { - ev->tmp.l = 1; - suv = suv_last; - - suv->fuv_list = NULL; - suv->uv_up = suv->uv_down = NULL; - suv->origuv[0] = uv_new[0]; - suv->origuv[1] = uv_new[1]; - - BLI_linklist_prepend(&suv->fuv_list, uv_new); - BLI_ghash_insert(uvarray[uvlay_idx],ev,suv); - - suv_last++; /* advance to next slide UV */ - maxnum++; - } - - /* Now get the uvs along the up or down edge if we can */ - if (suv) { - if (!suv->uv_up) { - ev_up = editedge_getOtherVert(tempsv->up,ev); - if (efa->v1==ev_up) suv->uv_up = tf->uv[0]; - else if (efa->v2==ev_up) suv->uv_up = tf->uv[1]; - else if (efa->v3==ev_up) suv->uv_up = tf->uv[2]; - else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3]; - } - if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */ - ev_down = editedge_getOtherVert(tempsv->down,ev); - if (efa->v1==ev_down) suv->uv_down = tf->uv[0]; - else if (efa->v2==ev_down) suv->uv_down = tf->uv[1]; - else if (efa->v3==ev_down) suv->uv_down = tf->uv[2]; - else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3]; - } - - /* Copy the pointers to the face UV's */ - BLI_linklist_prepend(&suv->fuv_list, uv_new); - } - } - } - } - look = look->next; - } - } /* end uv layer loop */ - } /* end uvlay_tot */ - - - // we should have enough info now to slide len = 0.0f; @@ -5121,22 +4994,88 @@ int EdgeSlide(short immediate, float imperc) float v2[2], v3[2]; EditVert *centerVert, *upVert, *downVert; + + getmouseco_areawin(mval); if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) { PIL_sleep_ms(10); } else { - char *p = str;; mvalo[0] = mval[0]; mvalo[1] = mval[1]; + //Adjust Edgeloop + if(immediate) { + perc = imperc; + } + percp = perc; + if(prop) { + look = vertlist; + while(look) { + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); + VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); + + look = look->next; + } + } + else { + //Non prop code + look = vertlist; + while(look) { + float newlen; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); + if(newlen > 1.0) {newlen = 1.0;} + if(newlen < 0.0) {newlen = 0.0;} + if(flip == 0) { + VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); + } else{ + VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); + } + look = look->next; + } + } + tempsv = BLI_ghash_lookup(vertgh,nearest); centerVert = editedge_getSharedVert(tempsv->up, tempsv->down); upVert = editedge_getOtherVert(tempsv->up, centerVert); downVert = editedge_getOtherVert(tempsv->down, centerVert); + // Highlight the Control Edges + + scrarea_do_windraw(curarea); + persp(PERSP_VIEW); + glPushMatrix(); + mymultmatrix(G.obedit->obmat); + + glColor3ub(0, 255, 0); + glBegin(GL_LINES); + glVertex3fv(upVert->co); + glVertex3fv(downVert->co); + glEnd(); + + if(prop == 0) { + // draw start edge for non-prop + glPointSize(5); + glBegin(GL_POINTS); + glColor3ub(255,0,255); + if(flip) { + glVertex3fv(upVert->co); + } else { + glVertex3fv(downVert->co); + } + glEnd(); + } + + + glPopMatrix(); view3d_project_float(curarea, upVert->co, v2, projectMat); view3d_project_float(curarea, downVert->co, v3, projectMat); @@ -5175,169 +5114,18 @@ int EdgeSlide(short immediate, float imperc) perc = floor(perc); perc /= 10; } - - if(prop == 0) { + if(prop) { + sprintf(str, "(P)ercentage: %f", perc); + } else { len = VecLenf(upVert->co,downVert->co)*((perc+1)/2); if(flip == 1) { len = VecLenf(upVert->co,downVert->co) - len; } - } - - if (hasNumInput(&num)) - { - applyNumInput(&num, &perc); - - if (prop) - { - perc = MIN2(perc, 1); - perc = MAX2(perc, -1); - } - else - { - len = MIN2(perc, VecLenf(upVert->co,downVert->co)); - len = MAX2(len, 0); - } + sprintf(str, "Non (P)rop Length: %f, Press (F) to flip control side", len); } - //Adjust Edgeloop - if(immediate) { - perc = imperc; - } - percp = perc; - if(prop) { - look = vertlist; - while(look) { - EditVert *tempev; - ev = look->link; - tempsv = BLI_ghash_lookup(vertgh,ev); - - tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); - VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); - - if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { - for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { - Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc)); - fuv_link = suv->fuv_list; - while (fuv_link) { - VECCOPY2D(((float *)fuv_link->link), uv_tmp); - fuv_link = fuv_link->next; - } - } - } - } - - look = look->next; - } - } - else { - //Non prop code - look = vertlist; - while(look) { - float newlen; - ev = look->link; - tempsv = BLI_ghash_lookup(vertgh,ev); - newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); - if(newlen > 1.0) {newlen = 1.0;} - if(newlen < 0.0) {newlen = 0.0;} - if(flip == 0) { - VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); - if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { - /* dont do anything if no UVs */ - for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { - Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen)); - fuv_link = suv->fuv_list; - while (fuv_link) { - VECCOPY2D(((float *)fuv_link->link), uv_tmp); - fuv_link = fuv_link->next; - } - } - } - } - } else{ - VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); - - if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { - /* dont do anything if no UVs */ - for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { - Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen)); - fuv_link = suv->fuv_list; - while (fuv_link) { - VECCOPY2D(((float *)fuv_link->link), uv_tmp); - fuv_link = fuv_link->next; - } - } - } - } - } - look = look->next; - } - - } - - // Highlight the Control Edges - scrarea_do_windraw(curarea); - persp(PERSP_VIEW); - glPushMatrix(); - mymultmatrix(G.obedit->obmat); - - glColor3ub(0, 255, 0); - glBegin(GL_LINES); - glVertex3fv(upVert->co); - glVertex3fv(downVert->co); - glEnd(); - - if(prop == 0) { - // draw start edge for non-prop - glPointSize(5); - glBegin(GL_POINTS); - glColor3ub(255,0,255); - if(flip) { - glVertex3fv(upVert->co); - } else { - glVertex3fv(downVert->co); - } - glEnd(); - } - glPopMatrix(); - - if(prop) { - p += sprintf(str, "(P)ercentage: "); - } else { - p += sprintf(str, "Non (P)rop Length: "); - } - - if (hasNumInput(&num)) - { - char num_str[20]; - - outputNumInput(&num, num_str); - p += sprintf(p, "%s", num_str); - } - else - { - if (prop) - { - p += sprintf(p, "%f", perc); - } - else - { - p += sprintf(p, "%f", len); - } - } - - - if (prop == 0) { - p += sprintf(p, ", Press (F) to flip control side"); - } - headerprint(str); screen_swapbuffers(); } @@ -5360,14 +5148,7 @@ int EdgeSlide(short immediate, float imperc) perc = 0; immediate = 1; } else if(event==PKEY) { - initNumInput(&num); /* reset num input */ - if (prop) { - prop = 0; - num.flag |= NUM_NO_NEGATIVE; - } - else { - prop = 1; - } + (prop == 1) ? (prop = 0):(prop = 1); mvalo[0] = -1; } else if(event==FKEY) { (flip == 1) ? (flip = 0):(flip = 1); @@ -5405,13 +5186,7 @@ int EdgeSlide(short immediate, float imperc) look = look->next; } } - - if (handleNumInput(&num, event)) - { - mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */ - } } - } } else { draw = 0; @@ -5443,24 +5218,6 @@ int EdgeSlide(short immediate, float imperc) BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); BLI_linklist_free(vertlist,NULL); BLI_linklist_free(edgelist,NULL); - - if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { - for (uvlay_idx=0; uvlay_idx= slideuvs) { - if (suv->fuv_list) { - BLI_linklist_free(suv->fuv_list,NULL); - } - suv--; - } - - allqueue(REDRAWIMAGE, 0); - } if(cancel == 1) { return -1; diff --git a/source/blender/src/editmode_undo.c b/source/blender/src/editmode_undo.c index 7893dac2408..d0a44360ad5 100644 --- a/source/blender/src/editmode_undo.c +++ b/source/blender/src/editmode_undo.c @@ -107,7 +107,6 @@ typedef struct UndoElem { Object *ob; // pointer to edited object int type; // type of edited object void *undodata; - uintptr_t undosize; char name[MAXUNDONAME]; void (*freedata)(void *); void (*to_editmode)(void *); @@ -139,7 +138,6 @@ void undo_editmode_push(char *name, void (*freedata)(void *), { UndoElem *uel; int nr; - uintptr_t memused, totmem, maxmem; /* at first here was code to prevent an "original" key to be insterted twice this was giving conflicts for example when mesh changed due to keys or apply */ @@ -147,8 +145,9 @@ void undo_editmode_push(char *name, void (*freedata)(void *), /* remove all undos after (also when curundo==NULL) */ while(undobase.last != curundo) { uel= undobase.last; + BLI_remlink(&undobase, uel); uel->freedata(uel->undodata); - BLI_freelinkN(&undobase, uel); + MEM_freeN(uel); } /* make new */ @@ -161,7 +160,7 @@ void undo_editmode_push(char *name, void (*freedata)(void *), uel->from_editmode= from_editmode; uel->validate_undo= validate_undo; - /* limit amount to the maximum amount*/ + /* and limit amount to the maximum */ nr= 0; uel= undobase.last; while(uel) { @@ -172,44 +171,20 @@ void undo_editmode_push(char *name, void (*freedata)(void *), if(uel) { while(undobase.first!=uel) { UndoElem *first= undobase.first; + BLI_remlink(&undobase, first); first->freedata(first->undodata); - BLI_freelinkN(&undobase, first); + MEM_freeN(first); } } /* copy */ - memused= MEM_get_memory_in_use(); curundo->undodata= curundo->from_editmode(); - curundo->undosize= MEM_get_memory_in_use() - memused; curundo->ob= G.obedit; curundo->id= G.obedit->id; curundo->type= G.obedit->type; - - if(U.undomemory != 0) { - /* limit to maximum memory (afterwards, we can't know in advance) */ - totmem= 0; - maxmem= ((uintptr_t)U.undomemory)*1024*1024; - - uel= undobase.last; - while(uel && uel->prev) { - totmem+= uel->undosize; - if(totmem>maxmem) break; - uel= uel->prev; - } - - if(uel) { - if(uel->prev && uel->prev->prev) - uel= uel->prev; - - while(undobase.first!=uel) { - UndoElem *first= undobase.first; - first->freedata(first->undodata); - BLI_freelinkN(&undobase, first); - } - } - } } + /* helper to remove clean other objects from undo stack */ static void undo_clean_stack(void) { @@ -230,8 +205,9 @@ static void undo_clean_stack(void) } else { mixed= 1; + BLI_remlink(&undobase, uel); uel->freedata(uel->undodata); - BLI_freelinkN(&undobase, uel); + MEM_freeN(uel); } uel= next; diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index d3ba153e600..98f4f1bb46f 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -2001,10 +2001,7 @@ void node_hide(SpaceNode *snode) void node_insert_key(SpaceNode *snode) { bNode *node= editnode_get_active(snode->edittree); - - if(node == NULL) - return; - + if(node->type==CMP_NODE_TIME) { if(node->custom1custom2) { @@ -2113,7 +2110,6 @@ static void node_border_link_delete(SpaceNode *snode) mval[1]= rect.ymax; areamouseco_to_ipoco(&snode->v2d, mval, &rectf.xmax, &rectf.ymax); - glLoadIdentity(); myortho2(rectf.xmin, rectf.xmax, rectf.ymin, rectf.ymax); glSelectBuffer(256, buffer); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 2459f7ed23c..fee967bcd9a 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -172,7 +172,6 @@ #include "BDR_drawobject.h" #include "BDR_editcurve.h" #include "BDR_unwrapper.h" -#include "BDR_gpencil.h" #include #include "mydevice.h" @@ -2828,7 +2827,7 @@ void convertmenu(void) if(G.scene->id.lib) return; obact= OBACT; - if (obact == NULL) return; + if(obact==0) return; if(!obact->flag & SELECT) return; if(G.obedit) return; @@ -3023,10 +3022,6 @@ void convertmenu(void) basedel = NULL; } - /* delete object should renew depsgraph */ - if(nr==2) - DAG_scene_sort(G.scene); - /* texspace and normals */ if(!basen) BASACT= base; @@ -3283,9 +3278,6 @@ static void copymenu_logicbricks(Object *ob) base->object->scavisflag= ob->scavisflag; base->object->scaflag= ob->scaflag; - /* set the initial state */ - base->object->state= ob->state; - base->object->init_state= ob->init_state; } } base= base->next; @@ -3522,7 +3514,6 @@ void copy_attr(short event) if (ob->gameflag & OB_BOUNDS) { base->object->boundtype = ob->boundtype; } - base->object->margin= ob->margin; } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); @@ -4139,27 +4130,15 @@ void apply_object( void ) } allqueue(REDRAWVIEW3D, 0); - } - else { - ob= OBACT; - if(ob==0) return; + } else { - if ((ob->pose) && (ob->flag & OB_POSEMODE)) - evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3"); - else - evt = pupmenu("Apply Object%t|Scale and Rotation to ObData%x1|Visual Transform to Objects Loc/Scale/Rot%x2"); + evt = pupmenu("Apply Object%t|Scale and Rotation to ObData|Visual Transform to Objects Loc/Scale/Rot"); if (evt==-1) return; - switch (evt) { - case 1: - apply_objects_locrot(); - break; - case 2: - apply_objects_visual_tx(); - break; - case 3: - apply_armature_pose2bones(); - break; + if (evt==1) { + apply_objects_locrot(); + } else if (evt==2) { + apply_objects_visual_tx(); } } } diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 976e58ed102..1cd8733a7ea 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -1023,11 +1023,8 @@ int blender_test_break(void) return (G.afbreek==1); } -void reset_autosave(void) -{ - if(U.flag & USER_AUTOSAVE) { - window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); - } +void reset_autosave(void) { + window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); } /* ************ handlers ************** */ diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c index 2d70525f971..05eb094a7c2 100644 --- a/source/blender/src/editsound.c +++ b/source/blender/src/editsound.c @@ -275,12 +275,6 @@ void sound_initialize_sounds(void) bSound *sound; if(ghSoundScene) { - for(sound=G.main->sound.first; sound; sound=sound->id.next) { - if(sound->snd_sound) { - SND_RemoveSound(ghSoundScene, sound->snd_sound); - sound->snd_sound = NULL; - } - } /* clear the soundscene */ SND_RemoveAllSounds(ghSoundScene); @@ -914,16 +908,7 @@ void sound_stop_all_sounds(void) void sound_end_all_sounds(void) { #if GAMEBLENDER == 1 - bSound *sound; - if(ghSoundScene) { - for(sound=G.main->sound.first; sound; sound=sound->id.next) { - if(sound->snd_sound) { - SND_RemoveSound(ghSoundScene, sound->snd_sound); - sound->snd_sound = NULL; - } - } - sound_stop_all_sounds(); SND_RemoveAllSounds(ghSoundScene); } diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index f95b56fe5b0..a3fcad7885c 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -89,7 +89,6 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_previewrender.h" /* use only so fly mode can preview when its done */ #include "BIF_space.h" @@ -1632,7 +1631,7 @@ void mouse_select(void) /* ------------------------------------------------------------------------- */ -int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2) +static int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2) { int radsq= rad*rad; float v1[2], v2[2], v3[2]; @@ -2248,7 +2247,7 @@ void view3d_border_zoom(void) /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); - draw_depth(curarea, (void *)v3d, NULL); + draw_depth(curarea, (void *)v3d); /* force updating */ if (v3d->depths) { diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index cdb001d9193..2ba5745b19b 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -2062,20 +2062,18 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case XKEY: - if(sfile->type==FILE_BLENDER) { - test = get_hilited_entry(sfile); + test = get_hilited_entry(sfile); - if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ - BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); + if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ + BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); - if( okee("Remove %s", str) ) { - ret = BLI_delete(str, 0, 0); - if (ret) { - error("Command failed, see console"); - } else { - freefilelist(sfile); - do_draw= 1; - } + if( okee("Remove %s", str) ) { + ret = BLI_delete(str, 0, 0); + if (ret) { + error("Command failed, see console"); + } else { + freefilelist(sfile); + do_draw= 1; } } } diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c index 69e3d4c7aac..c4a7b32bf8c 100644 --- a/source/blender/src/glutil.c +++ b/source/blender/src/glutil.c @@ -290,66 +290,17 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } -#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) { - float *f_rect; - float xzoom, yzoom; - unsigned char *uc_rect; - int ltexid, lrowlength, texid, tex_w, tex_h; - int subpart_x, subpart_y, nsubparts_x, nsubparts_y; - - uc_rect= (unsigned char*) rect; - f_rect= (float *)rect; - -#ifdef __APPLE__ - /* On Nvidia, Mac OS X 10.5 this function doesn't work correct and - * can crash even, use glDrawPixels instead of textures then */ - if(is_a_really_crappy_nvidia_card()) { - float col[4], modcol[4]; - unsigned char *srect = rect; - int a; - - /* modulate with current color */ - glGetFloatv(GL_CURRENT_COLOR, col); - if(col[0]!=1.0f || col[1]!=1.0f ||col[2]!=1.0f ||col[3]!=1.0f) { - srect = MEM_callocN(4*img_w*img_h, "glDrawPixelsTexSafe"); - for(a=0; a=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf) { float *rf; @@ -765,17 +717,6 @@ int is_a_really_crappy_intel_card(void) return well_is_it; } -int is_a_really_crappy_nvidia_card(void) -{ - static int well_is_it= -1; - - /* Do you understand the implication? Do you? */ - if (well_is_it==-1) - well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); - - return well_is_it; -} - void bglFlush(void) { glFlush(); diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index c7540bc4a1f..9b250fc3ec0 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -46,10 +46,7 @@ #include "BLI_blenlib.h" #include "DNA_listBase.h" -#include "DNA_armature_types.h" -#include "DNA_curve_types.h" #include "DNA_gpencil_types.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -60,15 +57,10 @@ #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_blender.h" -#include "BKE_armature.h" -#include "BKE_curve.h" -#include "BKE_image.h" #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" -#include "BIF_drawseq.h" -#include "BIF_editarmature.h" #include "BIF_editview.h" #include "BIF_graphics.h" #include "BIF_interface.h" @@ -82,8 +74,6 @@ #include "BDR_gpencil.h" #include "BIF_drawgpencil.h" -#include "BDR_editobject.h" - #include "BSE_drawipo.h" #include "BSE_headerbuttons.h" #include "BSE_view.h" @@ -224,8 +214,8 @@ bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) BLI_addtail(&gpd->layers, gpl); /* set basic settings */ - gpl->color[3]= 0.9f; - gpl->thickness = 3; + gpl->color[3]= 1.0f; + gpl->thickness = 1; /* auto-name */ sprintf(gpl->info, "GP_Layer"); @@ -247,7 +237,8 @@ bGPdata *gpencil_data_addnew (void) gpd= MEM_callocN(sizeof(bGPdata), "GreasePencilData"); /* initial settings */ - gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); + /* it is quite useful to be able to see this info, so on by default */ + gpd->flag = GP_DATA_DISPINFO; return gpd; } @@ -687,302 +678,6 @@ void gpencil_delete_menu (void) gpencil_delete_operation(mode); } -/* --------- Data Conversion ---------- */ - -/* convert the coordinates from the given stroke point into 3d-coordinates */ -static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3]) -{ - if (gps->flag & GP_STROKE_3DSPACE) { - /* directly use 3d-coordinates */ - VecCopyf(p3d, &pt->x); - } - else { - short mval[2], mx, my; - float *fp= give_cursor(); - float dvec[3]; - - /* get screen coordinate */ - if (gps->flag & GP_STROKE_2DSPACE) { - View2D *v2d= spacelink_get_view2d(curarea->spacedata.first); - ipoco_to_areaco_noclip(v2d, &pt->x, mval); - } - else { - mval[0]= (pt->x / 1000 * curarea->winx); - mval[1]= (pt->y / 1000 * curarea->winy); - } - mx= mval[0]; - my= mval[1]; - - /* convert screen coordinate to 3d coordinates - * - method taken from editview.c - mouse_cursor() - */ - project_short_noclip(fp, mval); - window_to_3d(dvec, mval[0]-mx, mval[1]-my); - VecSubf(p3d, fp, dvec); - } -} - -/* --- */ - -/* convert stroke to 3d path */ -static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu) -{ - bGPDspoint *pt; - Nurb *nu; - BPoint *bp; - int i; - - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); - - nu->pntsu= gps->totpoints; - nu->pntsv= 1; - nu->orderu= gps->totpoints; - nu->flagu= 2; /* endpoint */ - nu->resolu= 32; - - nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints"); - - /* add points */ - for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) { - float p3d[3]; - - /* get coordinates to add at */ - gp_strokepoint_convertcoords(gps, pt, p3d); - VecCopyf(bp->vec, p3d); - - /* set settings */ - bp->f1= SELECT; - bp->radius = bp->weight = pt->pressure * gpl->thickness; - } - - /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); -} - -/* convert stroke to 3d bezier */ -static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu) -{ - bGPDspoint *pt; - Nurb *nu; - BezTriple *bezt; - int i; - - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - - nu->pntsu= gps->totpoints; - nu->resolu= 12; - nu->resolv= 12; - nu->type= CU_BEZIER; - nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts"); - - /* add points */ - for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) { - float p3d[3]; - - /* get coordinates to add at */ - gp_strokepoint_convertcoords(gps, pt, p3d); - - /* TODO: maybe in future the handles shouldn't be in same place */ - VecCopyf(bezt->vec[0], p3d); - VecCopyf(bezt->vec[1], p3d); - VecCopyf(bezt->vec[2], p3d); - - /* set settings */ - bezt->h1= bezt->h2= HD_FREE; - bezt->f1= bezt->f2= bezt->f3= SELECT; - bezt->radius = bezt->weight = pt->pressure * gpl->thickness; - } - - /* must calculate handles or else we crash */ - calchandlesNurb(nu); - - /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); -} - -/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, short mode) -{ - bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps; - Object *ob; - Curve *cu; - - /* error checking */ - if (ELEM3(NULL, gpd, gpl, gpf)) - return; - - /* only convert if there are any strokes on this layer's frame to convert */ - if (gpf->strokes.first == NULL) - return; - - /* initialise the curve */ - cu= add_curve(gpl->info, 1); - cu->flag |= CU_3D; - - /* init the curve object (remove rotation and assign curve data to it) */ - add_object_draw(OB_CURVE); - ob= OBACT; - ob->loc[0]= ob->loc[1]= ob->loc[2]= 0; - ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; - ob->data= cu; - - /* add points to curve */ - for (gps= gpf->strokes.first; gps; gps= gps->next) { - switch (mode) { - case 1: - gp_stroke_to_path(gpl, gps, cu); - break; - case 2: - gp_stroke_to_bezier(gpl, gps, cu); - break; - } - } -} - -/* --- */ - -/* convert a stroke to a bone chain */ -static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones) -{ - EditBone *ebo, *prev=NULL; - bGPDspoint *pt, *ptn; - int i; - - /* add each segment separately */ - for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) { - float p3da[3], p3db[3]; - - /* get coordinates to add at */ - gp_strokepoint_convertcoords(gps, pt, p3da); - gp_strokepoint_convertcoords(gps, ptn, p3db); - - /* allocate new bone */ - ebo= MEM_callocN(sizeof(EditBone), "eBone"); - - VecCopyf(ebo->head, p3da); - VecCopyf(ebo->tail, p3db); - - /* add new bone - note: sync with editarmature.c::add_editbone() */ - BLI_strncpy(ebo->name, "Stroke", 32); - unique_editbone_name(bones, ebo->name); - - BLI_addtail(bones, ebo); - - ebo->flag |= BONE_CONNECTED; - ebo->weight= 1.0F; - ebo->dist= 0.25F; - ebo->xwidth= 0.1; - ebo->zwidth= 0.1; - ebo->ease1= 1.0; - ebo->ease2= 1.0; - ebo->rad_head= pt->pressure * gpl->thickness * 0.1; - ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1; - ebo->segments= 1; - ebo->layer= arm->layer; - - /* set parenting */ - // TODO: also adjust roll.... - ebo->parent= prev; - } -} - -/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, short mode) -{ - bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps; - Object *ob; - bArmature *arm; - ListBase bones = {0,0}; - - /* error checking */ - if (ELEM3(NULL, gpd, gpl, gpf)) - return; - - /* only convert if there are any strokes on this layer's frame to convert */ - if (gpf->strokes.first == NULL) - return; - - /* initialise the armature */ - arm= add_armature(gpl->info); - - /* init the armature object (remove rotation and assign armature data to it) */ - add_object_draw(OB_ARMATURE); - ob= OBACT; - ob->loc[0]= ob->loc[1]= ob->loc[2]= 0; - ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; - ob->data= arm; - - /* convert segments to bones, strokes to bone chains */ - for (gps= gpf->strokes.first; gps; gps= gps->next) { - gp_stroke_to_bonechain(gpl, gps, arm, &bones); - } - - /* flush editbones to armature */ - editbones_to_armature(&bones, ob); - if (bones.first) BLI_freelistN(&bones); -} - -/* --- */ - -/* convert grease-pencil strokes to another representation - * mode: 1 - Active layer to path - * 2 - Active layer to bezier - * 3 - Active layer to armature - */ -void gpencil_convert_operation (short mode) -{ - bGPdata *gpd; - float *fp= give_cursor(); - - /* get datablock to work on */ - gpd= gpencil_data_getactive(NULL); - if (gpd == NULL) return; - - /* initialise 3d-cursor correction globals */ - initgrabz(fp[0], fp[1], fp[2]); - - /* handle selection modes */ - switch (mode) { - case 1: /* active layer only (to path) */ - case 2: /* active layer only (to bezier) */ - { - bGPDlayer *gpl= gpencil_layer_getactive(gpd); - gp_layer_to_curve(gpd, gpl, mode); - } - break; - case 3: /* active layer only (to armature) */ - { - bGPDlayer *gpl= gpencil_layer_getactive(gpd); - gp_layer_to_armature(gpd, gpl, mode); - } - break; - } - - /* redraw and undo-push */ - BIF_undo_push("GPencil Convert"); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWOOPS, 0); -} - -/* display a menu for converting grease-pencil strokes */ -void gpencil_convert_menu (void) -{ - bGPdata *gpd= gpencil_data_getactive(NULL); - short mode; - - /* only show menu if it will be relevant */ - if (gpd == NULL) return; - - mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3"); - if (mode <= 0) return; - - gpencil_convert_operation(mode); -} - /* ************************************************** */ /* GREASE-PENCIL EDITING MODE - Painting */ @@ -1012,10 +707,6 @@ typedef struct tGPsdata { short status; /* current status of painting */ short paintmode; /* mode for painting */ - - short mval[2]; /* current mouse-position */ - short mvalo[2]; /* previous recorded mouse-position */ - short radius; /* radius of influence for eraser */ } tGPsdata; /* values for tGPsdata->status */ @@ -1137,7 +828,7 @@ static void gp_session_initpaint (tGPsdata *p) /* set the current area */ p->sa= curarea; p->v2d= &sima->v2d; - p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + //p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); } break; /* unsupported views */ @@ -1245,45 +936,24 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) out[1]= y; } - /* 2d - on image 'canvas' (assume that p->v2d is set) */ - else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && (p->v2d) ) + /* 2d - on image 'canvas' (asume that p->v2d is set) */ + else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && + (p->v2d) && (p->ibuf) ) { - /* for now - space specific */ - switch (p->sa->spacetype) { - case SPACE_SEQ: /* sequencer */ - { - SpaceSeq *sseq= (SpaceSeq *)p->sa->spacedata.first; - int sizex, sizey, offsx, offsy, rectx, recty; - float zoom, zoomx, zoomy; - - /* calculate zoom factor */ - zoom= SEQ_ZOOM_FAC(sseq->zoom); - if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { - zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); - zoomy = zoom; - } - else - zoomx = zoomy = zoom; - - /* calculate rect size */ - rectx= (G.scene->r.size*G.scene->r.xsch)/100; - recty= (G.scene->r.size*G.scene->r.ysch)/100; - sizex= zoomx * rectx; - sizey= zoomy * recty; - offsx= (p->sa->winx-sizex)/2 + sseq->xof; - offsy= (p->sa->winy-sizey)/2 + sseq->yof; - - /* calculate new points */ - out[0]= (float)(mval[0] - offsx) / (float)sizex; - out[1]= (float)(mval[1] - offsy) / (float)sizey; - } - break; - - default: /* just use raw mouse coordinates - BAD! */ - out[0]= mval[0]; - out[1]= mval[1]; - break; - } + ImBuf *ibuf= p->ibuf; + float x, y; + + /* convert to 'canvas' coordinates, then adjust for view */ + areamouseco_to_ipoco(p->v2d, mval, &x, &y); + + if (ibuf) { + out[0]= x*ibuf->x; + out[1]= y*ibuf->y; + } + else { + out[0]= x; + out[1]= y; + } } /* 2d - relative to screen (viewport area) */ @@ -1329,18 +999,9 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) bGPDspoint *pt; tGPspoint *ptc; int i, totelem; - - /* macro to test if only converting endpoints */ - #define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (G.qual & LR_CTRLKEY)) - /* get total number of points to allocate space for: - * - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints - * - otherwise, do whole stroke - */ - if (GP_BUFFER2STROKE_ENDPOINTS) - totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size; - else - totelem = gpd->sbuffer_size; + /* get total number of points to allocate space for */ + totelem = gpd->sbuffer_size; /* exit with error if no valid points from this stroke */ if (totelem == 0) { @@ -1361,53 +1022,45 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) gps->flag= gpd->sbuffer_sflag; /* copy points from the buffer to the stroke */ - if (GP_BUFFER2STROKE_ENDPOINTS) { - /* 'Draw Mode' + Ctrl-Modifier - only endpoints */ - { - /* first point */ - ptc= gpd->sbuffer; - - /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); - - /* copy pressure */ - pt->pressure= ptc->pressure; - - pt++; - } - - if (totelem == 2) { - /* last point if applicable */ - ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1); - - /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); - - /* copy pressure */ - pt->pressure= ptc->pressure; - } - } - else { - /* convert all points (normal behaviour) */ - for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { - /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); - - /* copy pressure */ - pt->pressure= ptc->pressure; - - pt++; - } + for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + + pt++; } /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); - - /* undefine macro to test if only converting endpoints */ - #undef GP_BUFFER2STROKE_ENDPOINTS } /* --- 'Eraser' for 'Paint' Tool ------ */ +/* User should draw 'circles' around the parts of the sketches they wish to + * delete instead of drawing squiggles over existing lines. This should be + * easier to manage than if it was done otherwise. + */ + +/* convert gp-buffer stroke into mouse-coordinates array */ +static short (*gp_stroke_eraser_2mco (bGPdata *gpd))[2] +{ + tGPspoint *pt; + short (*mcoords)[2]; + int i; + + /* allocate memory for coordinates array */ + mcoords= MEM_mallocN(sizeof(*mcoords)*gpd->sbuffer_size,"gp_buf_mcords"); + + /* copy coordinates */ + for (pt=gpd->sbuffer, i=0; i < gpd->sbuffer_size; i++, pt++) { + mcoords[i][0]= pt->x; + mcoords[i][1]= pt->y; + } + + /* return */ + return mcoords; +} /* eraser tool - remove segment from stroke/split stroke (after lasso inside) */ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) @@ -1477,19 +1130,8 @@ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) } } -/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */ -static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1) -{ - /* simple within-radius check for now */ - if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) - return 1; - - /* not inside */ - return 0; -} - /* eraser tool - evaluation per stroke */ -static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) +static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) { bGPDspoint *pt1, *pt2; short x0=0, y0=0, x1=0, y1=0; @@ -1505,20 +1147,16 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], else if (gps->totpoints == 1) { /* get coordinates */ if (gps->flag & GP_STROKE_3DSPACE) { + // FIXME: this may not be the correct correction project_short(&gps->points->x, xyval); x0= xyval[0]; - y0= xyval[1]; + x1= xyval[1]; } else if (gps->flag & GP_STROKE_2DSPACE) { ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); x0= xyval[0]; y0= xyval[1]; } - else if (gps->flag & GP_STROKE_2DIMAGE) { - ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); - x0= xyval[0]; - y0= xyval[1]; - } else { x0= (gps->points->x / 1000 * p->sa->winx); y0= (gps->points->y / 1000 * p->sa->winy); @@ -1527,7 +1165,7 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], /* do boundbox check first */ if (BLI_in_rcti(rect, x0, y0)) { /* only check if point is inside */ - if ( ((x0-mval[0])*(x0-mval[0]) + (y0-mval[1])*(y0-mval[1])) <= rad*rad ) { + if (lasso_inside(mcoords, moves, x0, y0)) { /* free stroke */ MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); @@ -1545,13 +1183,10 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], /* get coordinates */ if (gps->flag & GP_STROKE_3DSPACE) { - project_short(&pt1->x, xyval); + // FIXME: may not be correct correction + project_short(&gps->points->x, xyval); x0= xyval[0]; - y0= xyval[1]; - - project_short(&pt2->x, xyval); - x1= xyval[0]; - y1= xyval[1]; + x1= xyval[1]; } else if (gps->flag & GP_STROKE_2DSPACE) { ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); @@ -1562,15 +1197,6 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], x1= xyval[0]; y1= xyval[1]; } - else if (gps->flag & GP_STROKE_2DIMAGE) { - ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); - x0= xyval[0]; - y0= xyval[1]; - - ipoco_to_areaco_noclip(p->v2d, &pt2->x, xyval); - x1= xyval[0]; - y1= xyval[1]; - } else { x0= (pt1->x / 1000 * p->sa->winx); y0= (pt1->y / 1000 * p->sa->winy); @@ -1583,8 +1209,9 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant + * - handled using the lasso-select checking code */ - if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) { + if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) { /* if function returns true, break this loop (as no more point to check) */ if (gp_stroke_eraser_splitdel(gpf, gps, i)) break; @@ -1594,24 +1221,29 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], } } +/* -------- */ + /* erase strokes which fall under the eraser strokes */ static void gp_stroke_doeraser (tGPsdata *p) { + bGPdata *gpd= p->gpd; bGPDframe *gpf= p->gpf; bGPDstroke *gps, *gpn; + short (*mcoords)[2]; rcti rect; - /* rect is rectangle of eraser */ - rect.xmin= p->mval[0] - p->radius; - rect.ymin= p->mval[1] - p->radius; - rect.xmax= p->mval[0] + p->radius; - rect.ymax= p->mval[1] + p->radius; + /* get buffer-stroke coordinates as shorts array, and then get bounding box */ + mcoords= gp_stroke_eraser_2mco(gpd); + lasso_select_boundbox(&rect, mcoords, gpd->sbuffer_size); /* loop over strokes, checking segments for intersections */ for (gps= gpf->strokes.first; gps; gps= gpn) { gpn= gps->next; - gp_stroke_eraser_dostroke(p, p->mval, p->mvalo, p->radius, &rect, gpf, gps); + gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, &rect, gpf, gps); } + + /* free mcoords array */ + MEM_freeN(mcoords); } /* ---------- 'Paint' Tool ------------ */ @@ -1665,14 +1297,6 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) case SPACE_SEQ: { /* for now, this is not applicable here... */ - p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE; - } - break; - case SPACE_IMAGE: - { - /* check if any ibuf available */ - if (p->ibuf) - p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE; } break; } @@ -1683,7 +1307,11 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) static void gp_paint_strokeend (tGPsdata *p) { /* check if doing eraser or not */ - if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) { + if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) { + /* get rid of relevant sections of strokes */ + gp_stroke_doeraser(p); + } + else { /* transfer stroke to frame */ gp_stroke_newfrombuffer(p); } @@ -1717,6 +1345,7 @@ static void gp_paint_cleanup (tGPsdata *p) short gpencil_paint (short mousebutton, short paintmode) { tGPsdata p; + short prevmval[2], mval[2]; float opressure, pressure; short ok = GP_STROKEADD_NORMAL; @@ -1736,51 +1365,31 @@ short gpencil_paint (short mousebutton, short paintmode) setcursor_space(p.sa->spacetype, CURSOR_VPAINT); /* init drawing-device settings */ - getmouseco_areawin(p.mval); + getmouseco_areawin(mval); pressure = get_pressure(); - p.mvalo[0]= p.mval[0]; - p.mvalo[1]= p.mval[1]; + prevmval[0]= mval[0]; + prevmval[1]= mval[1]; opressure= pressure; - /* radius for eraser circle is thickness^2 */ - p.radius= p.gpl->thickness * p.gpl->thickness; - - /* start drawing eraser-circle (if applicable) */ - if (paintmode == GP_PAINTMODE_ERASER) - draw_sel_circle(p.mval, NULL, p.radius, p.radius, 0); // draws frontbuffer, but sets backbuf again - /* only allow painting of single 'dots' if: * - pressure is not excessive (as it can be on some windows tablets) * - draw-mode for active datablock is turned on - * - not erasing */ - if (paintmode != GP_PAINTMODE_ERASER) { - if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { - gp_stroke_addpoint(&p, p.mval, pressure); - } + if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { + gp_stroke_addpoint(&p, mval, pressure); } /* paint loop */ do { /* get current user input */ - getmouseco_areawin(p.mval); + getmouseco_areawin(mval); pressure = get_pressure(); /* only add current point to buffer if mouse moved (otherwise wait until it does) */ - if (paintmode == GP_PAINTMODE_ERASER) { - /* do 'live' erasing now */ - gp_stroke_doeraser(&p); - - draw_sel_circle(p.mval, p.mvalo, p.radius, p.radius, 0); - force_draw(0); - - p.mvalo[0]= p.mval[0]; - p.mvalo[1]= p.mval[1]; - } - else if (gp_stroke_filtermval(&p, p.mval, p.mvalo)) { + if (gp_stroke_filtermval(&p, mval, prevmval)) { /* try to add point */ - ok= gp_stroke_addpoint(&p, p.mval, pressure); + ok= gp_stroke_addpoint(&p, mval, pressure); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { @@ -1788,8 +1397,8 @@ short gpencil_paint (short mousebutton, short paintmode) gp_paint_strokeend(&p); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(&p, p.mvalo, opressure); - ok= gp_stroke_addpoint(&p, p.mval, pressure); + gp_stroke_addpoint(&p, prevmval, opressure); + ok= gp_stroke_addpoint(&p, mval, pressure); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1802,8 +1411,8 @@ short gpencil_paint (short mousebutton, short paintmode) } force_draw(0); - p.mvalo[0]= p.mval[0]; - p.mvalo[1]= p.mval[1]; + prevmval[0]= mval[0]; + prevmval[1]= mval[1]; opressure= pressure; } else @@ -1821,10 +1430,8 @@ short gpencil_paint (short mousebutton, short paintmode) setcursor_space(p.sa->spacetype, CURSOR_STD); /* check size of buffer before cleanup, to determine if anything happened here */ - if (paintmode == GP_PAINTMODE_ERASER) { - ok= 1; // fixme - draw_sel_circle(NULL, p.mvalo, 0, p.radius, 0); - } + if (paintmode == GP_PAINTMODE_ERASER) + ok= (p.gpd->sbuffer_size > 1); else ok= p.gpd->sbuffer_size; @@ -1851,8 +1458,7 @@ short gpencil_do_paint (ScrArea *sa, short mbut) /* currently, we will only 'paint' if: * 1. draw-mode on gpd is set (for accessibility reasons) - * a) single dots are only available by this method if a single click is made - * b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!) + * (single 'dots' are only available via this method) * 2. if shift-modifier is held + lmb -> 'quick paint' * * OR diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index 4ca287d81c5..fac9e3af1af 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -239,10 +239,8 @@ void do_image_buttons(unsigned short event) if(ima->twsta>=nr) ima->twsta= 1; if(ima->twend>=nr) ima->twend= nr-1; if(ima->twsta>ima->twend) ima->twsta= 1; + allqueue(REDRAWIMAGE, 0); } - - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWVIEW3D, 0); } break; } @@ -477,9 +475,6 @@ static void do_image_viewmenu(void *arg, int event) G.sima->flag ^= SI_LOCAL_UV; allqueue(REDRAWIMAGE, 0); break; - case 15: /* Grease Pencil... */ - add_blockhandler(curarea, IMAGE_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); - break; } allqueue(REDRAWVIEW3D, 0); } @@ -502,8 +497,6 @@ static uiBlock *image_viewmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Curves Tool...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Composite Preview...|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Grease Pencil...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); - if(G.sima->flag & SI_LOCAL_UV) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "UV Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "UV Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); if(!(G.sima->flag & SI_LOCAL_UV)) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "UV Global View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); @@ -1300,7 +1293,7 @@ void image_buttons(void) uiBlockEndAlign(block); xco+= 166; } - uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enable image painting"); + uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enables painting textures on the image with left mouse button"); xco+= XIC+8; diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 9bacc2b6351..8b8fd9ef266 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -39,6 +39,8 @@ #include #endif +#include "BLO_sys_types.h" // for intptr_t support + #include "DNA_group_types.h" #include "DNA_ID.h" #include "DNA_image_types.h" @@ -118,9 +120,6 @@ #include "BPY_extern.h" #include "BPY_menus.h" -#include "GPU_extensions.h" -#include "GPU_material.h" - #include "blendef.h" #include "interface.h" #include "mydevice.h" @@ -927,7 +926,7 @@ static void do_info_filemenu(void *arg, int event) winqueue_break= 1; /* leave queues everywhere */ BKE_reset_undo(); - BKE_write_undo("Original"); /* save current state */ + BKE_write_undo("original"); /* save current state */ refresh_interface_font(); } break; @@ -1592,83 +1591,20 @@ static uiBlock *info_addmenu(void *arg_unused) /************************** GAME *****************************/ -void do_info_game_glslmenu(void *arg, int event) -{ - switch (event) { - case G_FILE_GLSL_NO_LIGHTS: - case G_FILE_GLSL_NO_SHADERS: - case G_FILE_GLSL_NO_SHADOWS: - case G_FILE_GLSL_NO_RAMPS: - case G_FILE_GLSL_NO_NODES: - case G_FILE_GLSL_NO_EXTRA_TEX: - G.fileflags ^= event; - GPU_materials_free(); - allqueue(REDRAWINFO, 0); - allqueue(REDRAWVIEW3D, 0); - break; - default: - break; - } -} - -static uiBlock *info_game_glslmenu(void *arg_unused) -{ - uiBlock *block; - short yco= 0, menuwidth=160; - int check; - block= uiNewBlock(&curarea->uiblocks, "game_glslmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); - uiBlockSetButmFunc(block, do_info_game_glslmenu, NULL); - - check = (G.fileflags & G_FILE_GLSL_NO_LIGHTS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; - uiDefIconTextBut(block, BUTM, 1, check, "Enable Lights", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_LIGHTS, - "Enable using lights in GLSL materials."); - check = (G.fileflags & G_FILE_GLSL_NO_SHADERS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; - uiDefIconTextBut(block, BUTM, 1, check, "Enable Shaders", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_SHADERS, - "Enable using shaders other than Lambert in GLSL materials"); - check = (G.fileflags & G_FILE_GLSL_NO_SHADOWS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; - uiDefIconTextBut(block, BUTM, 1, check, "Enable Shadows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_SHADOWS, - "Enable using shadows in GLSL materials"); - check = (G.fileflags & G_FILE_GLSL_NO_RAMPS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; - uiDefIconTextBut(block, BUTM, 1, check, "Enable Ramps", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_RAMPS, - "Enable using ramps in GLSL materials"); - check = (G.fileflags & G_FILE_GLSL_NO_NODES)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; - uiDefIconTextBut(block, BUTM, 1, check, "Enable Nodes", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_NODES, - "Enable using nodes in GLSL materials."); - check = (G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; - uiDefIconTextBut(block, BUTM, 1, check, "Enable Extra Textures", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_EXTRA_TEX, - "Enable using texture channels other than Col and Alpha in GLSL materials."); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 50); - - return block; -} - static void do_info_gamemenu(void *arg, int event) { switch (event) { case G_FILE_ENABLE_ALL_FRAMES: - case G_FILE_DISPLAY_LISTS: + case G_FILE_DIAPLAY_LISTS: case G_FILE_SHOW_FRAMERATE: case G_FILE_SHOW_DEBUG_PROPS: case G_FILE_AUTOPLAY: case G_FILE_GAME_TO_IPO: + case G_FILE_GAME_MAT: case G_FILE_SHOW_PHYSICS: G.fileflags ^= event; break; - case G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL: - G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); - break; - case G_FILE_GAME_MAT: - G.fileflags |= G_FILE_GAME_MAT; - G.fileflags &= ~G_FILE_GAME_MAT_GLSL; - break; - case G_FILE_GAME_MAT_GLSL: - if(!GPU_extensions_minimum_support()) - error("GLSL not supported with this graphics card or driver."); - G.fileflags |= (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); - break; default: ; /* ignore the rest */ } @@ -1699,14 +1635,22 @@ static uiBlock *info_gamemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } else { - if(G.fileflags & G_FILE_DISPLAY_LISTS) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, ""); + if(G.fileflags & G_FILE_DIAPLAY_LISTS) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DIAPLAY_LISTS, ""); } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DIAPLAY_LISTS, ""); } uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } + if(G.fileflags & G_FILE_GAME_MAT) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); + } + + + if(G.fileflags & G_FILE_SHOW_FRAMERATE) { uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Framerate and Profile", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_FRAMERATE, ""); } else { @@ -1725,28 +1669,6 @@ static uiBlock *info_gamemenu(void *arg_unused) } else { uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Debug Properties", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_DEBUG_PROPS, ""); } - - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); - - if(!(G.fileflags & G_FILE_GAME_MAT)) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Texture Face Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); - } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Texture Face Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL, ""); - } - - if((G.fileflags & G_FILE_GAME_MAT) && !(G.fileflags & G_FILE_GAME_MAT_GLSL)) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Blender Multitexture Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); - } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Blender Multitexture Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); - } - - if((G.fileflags & G_FILE_GAME_MAT) && (G.fileflags & G_FILE_GAME_MAT_GLSL)) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Blender GLSL Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); - } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Blender GLSL Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT_GLSL, ""); - } - - uiDefIconTextBlockBut(block, info_game_glslmenu, NULL, ICON_RIGHTARROW_THIN, "GLSL Material Settings", 0, yco-=20, menuwidth, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); @@ -2186,16 +2108,13 @@ static void info_text(int x, int y) { Object *ob= OBACT; extern float hashvectf[]; - uintptr_t mem_in_use, mmap_in_use; + extern uintptr_t mem_in_use, mmap_in_use; unsigned int swatch_color; float fac1, fac2, fac3; char infostr[300], memstr[64]; char *headerstr, *s; int hsize; - mem_in_use= MEM_get_memory_in_use(); - mmap_in_use= MEM_get_mapped_memory_in_use(); - s= memstr + sprintf(memstr," | Mem:%.2fM ", ((mem_in_use-mmap_in_use)>>10)/1024.0); if(mmap_in_use) sprintf(s,"(%.2fM) ", ((mmap_in_use)>>10)/1024.0); diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 130ffa1e49f..59d542e72ec 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -1414,7 +1414,7 @@ void ipo_buttons(void) uiClearButLock(); /* ZOOMBORDER */ - uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area (Shift B)"); + uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area"); xco+=XIC/2; diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index d27a41c59f5..4c7b4aa80bc 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -112,7 +112,7 @@ static void do_node_viewmenu(void *arg, int event) break; case 4: /* Grease Pencil */ add_blockhandler(curarea, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); - break; + break; } allqueue(REDRAWNODE, 0); } @@ -602,11 +602,11 @@ static uiBlock *node_nodemenu(void *arg_unused) if(snode->treetype==NTREE_COMPOSIT) { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Execute Composite|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Render Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl RMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl LMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c index eeea43ec57a..cf6d21ff264 100644 --- a/source/blender/src/header_text.c +++ b/source/blender/src/header_text.c @@ -42,7 +42,6 @@ #include "BMF_Api.h" #include "BIF_language.h" -#include "MEM_guardedalloc.h" #include "BSE_headerbuttons.h" @@ -53,7 +52,6 @@ #include "DNA_constraint_types.h" #include "DNA_action_types.h" -#include "BIF_gl.h" /* for glRasterPos2i */ #include "BIF_drawtext.h" #include "BIF_interface.h" #include "BIF_resources.h" @@ -130,7 +128,7 @@ void do_text_buttons(unsigned short event) st->top= 0; pop_space_text(st); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); } @@ -196,20 +194,14 @@ void do_text_buttons(unsigned short event) break; case B_TAB_NUMBERS: - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); break; case B_SYNTAX: - if (st->showsyntax) txt_format_text(st); - allqueue(REDRAWTEXT, 0); - allqueue(REDRAWHEADERS, 0); - break; - case B_TEXTPLUGINS: - allqueue(REDRAWHEADERS, 0); - break; - case B_WORDWRAP: - st->left= 0; + if (st->showsyntax) { + get_format_string(st); + } allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); break; @@ -247,37 +239,6 @@ static uiBlock *text_template_scriptsmenu (void *args_unused) return block; } -static void do_text_plugin_scriptsmenu(void *arg, int event) -{ - BPY_menu_do_python(PYMENU_TEXTPLUGIN, event); - - allqueue(REDRAWIMAGE, 0); -} - -static uiBlock *text_plugin_scriptsmenu (void *args_unused) -{ - uiBlock *block; - BPyMenu *pym; - int i= 0; - short yco = 20, menuwidth = 120; - - block= uiNewBlock(&curarea->uiblocks, "text_plugin_scriptsmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); - uiBlockSetButmFunc(block, do_text_plugin_scriptsmenu, NULL); - - /* note that we acount for the N previous entries with i+20: */ - for (pym = BPyMenuTable[PYMENU_TEXTPLUGIN]; pym; pym = pym->next, i++) { - - uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, - NULL, 0.0, 0.0, 1, i, - pym->tooltip?pym->tooltip:pym->filename); - } - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - - return block; -} - /* action executed after clicking in File menu */ static void do_text_filemenu(void *arg, int event) { @@ -307,7 +268,7 @@ static void do_text_filemenu(void *arg, int event) if (!reopen_text(text)) { error("Could not reopen file"); } - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); } break; case 5: @@ -316,14 +277,9 @@ static void do_text_filemenu(void *arg, int event) txt_write_file(text); break; case 6: - text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; - MEM_freeN(text->name); - text->name= NULL; - break; - case 7: run_python_script(st); break; - case 8: + case 7: { Object *ob; bConstraint *con; @@ -384,17 +340,11 @@ static void do_text_editmenu(void *arg, int event) switch(event) { case 1: txt_do_undo(text); - pop_space_text(st); break; case 2: txt_do_redo(text); - pop_space_text(st); break; case 3: - if (text && text->id.lib) { - error_libdata(); - break; - } txt_copy_clipboard(text); txt_cut_sel(text); pop_space_text(st); @@ -404,12 +354,8 @@ static void do_text_editmenu(void *arg, int event) txt_copy_clipboard(text); break; case 5: - if (text && text->id.lib) { - error_libdata(); - break; - } txt_paste_clipboard(text); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); break; case 6: txt_print_cutbuffer(); @@ -418,11 +364,10 @@ static void do_text_editmenu(void *arg, int event) jumptoline_interactive(st); break; case 8: - case 9: - find_and_replace(st, 0); + txt_find_panel(st,1); break; - case 10: - find_and_replace(st, 1); + case 9: + txt_find_panel(st,0); break; default: break; @@ -498,57 +443,6 @@ static void do_text_editmenu_selectmenu(void *arg, int event) } } -/* action executed after clicking in Markers menu */ -static void do_text_editmenu_markermenu(void *arg, int event) -{ - SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */ - Text *text; - TextMarker *mrk; - ScrArea *sa; - int lineno; - - if (st==NULL || st->spacetype != SPACE_TEXT) return; - - text = st->text; - - switch(event) { - case 1: - txt_clear_markers(text, 0, 0); - break; - case 2: - lineno= txt_get_span(text->lines.first, text->curl); - mrk= text->markers.first; - while (mrk && (mrk->linenolineno==lineno && mrk->start <= text->curc))) - mrk= mrk->next; - if (!mrk) mrk= text->markers.first; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - break; - case 3: - lineno= txt_get_span(text->lines.first, text->curl); - mrk= text->markers.last; - while (mrk && (mrk->lineno>lineno || (mrk->lineno==lineno && mrk->end > text->curc))) - mrk= mrk->prev; - if (!mrk) mrk= text->markers.last; - if (mrk) { - txt_move_to(text, mrk->lineno, mrk->start, 0); - txt_move_to(text, mrk->lineno, mrk->end, 1); - } - break; - default: - break; - } - - for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { - SpaceText *st= sa->spacedata.first; - if (st && st->spacetype==SPACE_TEXT) { - scrarea_queue_redraw(sa); - } - } -} - /* action executed after clicking in Format menu */ static void do_text_formatmenu(void *arg, int event) { @@ -562,10 +456,6 @@ static void do_text_formatmenu(void *arg, int event) switch(event) { case 3: - if (text && text->id.lib) { - error_libdata(); - break; - } if (txt_has_sel(text)) { txt_order_cursors(text); indent(text); @@ -576,10 +466,6 @@ static void do_text_formatmenu(void *arg, int event) break; } case 4: - if (text && text->id.lib) { - error_libdata(); - break; - } if ( txt_has_sel(text)) { txt_order_cursors(text); unindent(text); @@ -587,26 +473,18 @@ static void do_text_formatmenu(void *arg, int event) } break; case 5: - if (text && text->id.lib) { - error_libdata(); - break; - } if ( txt_has_sel(text)) { txt_order_cursors(text); comment(text); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); break; } break; case 6: - if (text && text->id.lib) { - error_libdata(); - break; - } if ( txt_has_sel(text)) { txt_order_cursors(text); uncomment(text); - if (st->showsyntax) txt_format_text(st); + if (st->showsyntax) get_format_string(st); break; } break; @@ -658,25 +536,6 @@ static uiBlock *text_editmenu_selectmenu(void *arg_unused) return block; } -/* Select menu */ -static uiBlock *text_editmenu_markermenu(void *arg_unused) -{ - uiBlock *block; - short yco = 20, menuwidth = 120; - - block= uiNewBlock(&curarea->uiblocks, "text_editmenu_markermenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); - uiBlockSetButmFunc(block, do_text_editmenu_markermenu, NULL); - - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Next Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Previous Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - - return block; -} - void do_text_formatmenu_convert(void *arg, int event) { SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */ @@ -790,12 +649,10 @@ static uiBlock *text_editmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, text_editmenu_viewmenu, NULL, ICON_RIGHTARROW_THIN, "View|Alt Shift V ", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, text_editmenu_selectmenu, NULL, ICON_RIGHTARROW_THIN, "Select|Alt Shift S ", 0, yco-=20, 120, 19, ""); - uiDefIconTextBlockBut(block, text_editmenu_markermenu, NULL, ICON_RIGHTARROW_THIN, "Markers", 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, "Jump...|Alt J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find And Replace...|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Next|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Replace|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find...|Alt Ctrl F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Again|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, text_editmenu_to3dmenu, NULL, ICON_RIGHTARROW_THIN, "Text to 3d Object", 0, yco-=20, 120, 19, ""); @@ -833,21 +690,17 @@ static uiBlock *text_filemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); - if (text->name) - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Internal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); - uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); if (BPY_is_pyconstraint(text)) - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, ""); - uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, ""); if(curarea->headertype==HEADERTOP) { uiBlockSetDirection(block, UI_DOWN); @@ -862,15 +715,13 @@ static uiBlock *text_filemenu(void *arg_unused) } /* header */ -#define HEADER_PATH_MAX 260 void text_buttons(void) { uiBlock *block; SpaceText *st= curarea->spacedata.first; Text *text; short xco, xmax; - char naam[256], fname[HEADER_PATH_MAX], headtxt[HEADER_PATH_MAX+17]; - int len; + char naam[256]; if (st==NULL || st->spacetype != SPACE_TEXT) return; @@ -928,9 +779,8 @@ void text_buttons(void) else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Makes current window full screen (CTRL+Down arrow)"); uiDefIconButI(block, ICONTOG, B_TEXTLINENUM, ICON_LONGDISPLAY, xco+=XIC,0,XIC,YIC, &st->showlinenrs, 0, 0, 0, 0, "Displays line numbers"); - uiDefIconButI(block, ICONTOG, B_WORDWRAP, ICON_WORDWRAP, xco+=XIC,0,XIC,YIC, &st->wordwrap, 0, 0, 0, 0, "Enables word wrap"); - uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables syntax highlighting"); - uiDefIconButI(block, ICONTOG, B_TEXTPLUGINS, ICON_PYTHON, xco+=XIC,0,XIC,YIC, &st->doplugins, 0, 0, 0, 0, "Enables Python text plugins"); + + uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables Syntax Highlighting"); uiBlockEndAlign(block); /* STD TEXT BUTTONS */ @@ -954,30 +804,9 @@ void text_buttons(void) uiDefButI(block, MENU, B_TEXTFONT, "Screen 12 %x0|Screen 15%x1", xco,0,100,YIC, &st->font_id, 0, 0, 0, 0, "Displays available fonts"); xco+=110; - uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab"); + uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab"); xco+= XIC+50; - - /* File info */ - if (text) { - if (text->name) { - len = strlen(text->name); - if (len > HEADER_PATH_MAX-1) - len = HEADER_PATH_MAX-1; - strncpy(fname, text->name, len); - fname[len]='\0'; - if (text->flags & TXT_ISDIRTY) - sprintf(headtxt, "File: *%s (unsaved)", fname); - else - sprintf(headtxt, "File: %s", fname); - } else { - sprintf(headtxt, text->id.lib?"Text: External":"Text: Internal"); - } - BIF_ThemeColor(TH_MENU_TEXT); - glRasterPos2i(xco+=XIC, 5); - BMF_DrawString(G.font, headtxt); - xco += BMF_GetStringWidth(G.font, headtxt); - } - + /* always as last */ curarea->headbutlen= xco+2*XIC; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index acd80f5efdd..fcf4caf4522 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -106,7 +106,6 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_meshtools.h" #include "BIF_poselib.h" @@ -4371,9 +4370,6 @@ static void do_view3d_pose_armaturemenu(void *arg, int event) case 18: pose_autoside_names(event-16); break; - case 19: /* assign pose as restpose */ - apply_armature_pose2bones(); - break; } allqueue(REDRAWVIEW3D, 0); @@ -4399,7 +4395,6 @@ static uiBlock *view3d_pose_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Relax Pose|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Pose as Restpose|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -4513,7 +4508,7 @@ static void do_view3d_tpaintmenu(void *arg, int event) { switch(event) { case 0: /* undo image painting */ - undo_imagepaint_step(1); + imagepaint_undo(); break; } @@ -5388,11 +5383,7 @@ void do_view3d_buttons(short event) case B_MAN_MODE: allqueue(REDRAWVIEW3D, 1); break; - case B_VIEW_BUTSEDIT: - allqueue(REDRAWVIEW3D, 1); - allqueue(REDRAWBUTSEDIT, 1); - break; - + default: if(event>=B_LAY && eventlocalview==0) { - int ob_lay = ob ? ob->lay : 0; uiBlockBeginAlign(block); - for(a=0; a<5; a++) { - uiDefIconButBitI(block, TOG, 1<lay_used), (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - } - for(a=0; a<5; a++) { - uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, G.vd->lay_used), (short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - } + for(a=0; a<5; a++) + uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); + for(a=0; a<5; a++) + uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + xco+= 5; uiBlockBeginAlign(block); - for(a=5; a<10; a++) { - uiDefIconButBitI(block, TOG, 1<lay_used), (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - } - for(a=5; a<10; a++) { - uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, G.vd->lay_used), (short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - } + for(a=5; a<10; a++) + uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); + for(a=5; a<10; a++) + uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + uiBlockEndAlign(block); xco+= (a-2)*(XIC/2)+3; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 44044841a99..1a91ada1562 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -154,6 +154,7 @@ #include "BSE_editipo.h" #include "BSE_drawipo.h" +#include "BDR_drawmesh.h" #include "BDR_vpaint.h" #include "BDR_editface.h" #include "BDR_editobject.h" @@ -164,8 +165,6 @@ #include "BPY_extern.h" #include "BPY_menus.h" -#include "GPU_draw.h" - #include "mydevice.h" #include "blendef.h" #include "interface.h" @@ -1426,11 +1425,11 @@ void do_global_buttons(unsigned short event) show_splash(); break; case B_MIPMAPCHANGED: - GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); allqueue(REDRAWVIEW3D, 0); break; case B_GLRESLIMITCHANGED: - GPU_free_images(); /* force reloading with new res limit */ + free_all_realtime_images(); /* force reloading with new res limit */ allqueue(REDRAWVIEW3D, 0); break; case B_NEWSPACE: diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 164c368b6fa..15c289cc21c 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -44,8 +44,6 @@ #include "BLI_winstuff.h" #endif #include "BLI_arithb.h" -#include "BLI_blenlib.h" -#include "BLI_dynstr.h" #include "PIL_time.h" #include "IMB_imbuf.h" @@ -66,12 +64,10 @@ #include "BKE_brush.h" #include "BKE_global.h" #include "BKE_image.h" -#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_node.h" #include "BKE_utildefines.h" -#include "BIF_interface.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -82,11 +78,10 @@ #include "BSE_trans_types.h" #include "BSE_view.h" +#include "BDR_drawmesh.h" #include "BDR_imagepaint.h" #include "BDR_vpaint.h" -#include "GPU_draw.h" - #include "GHOST_Types.h" #include "blendef.h" @@ -108,8 +103,6 @@ #define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) #define IMAPAINT_TILE_NUMBER(size) (((size)+IMAPAINT_TILE_SIZE-1) >> IMAPAINT_TILE_BITS) -#define MAXUNDONAME 64 - typedef struct ImagePaintState { Brush *brush; short tool, blend; @@ -127,206 +120,48 @@ typedef struct ImagePaintState { float uv[2]; } ImagePaintState; -typedef struct UndoTile { - struct UndoTile *next, *prev; - ID id; - void *rect; - int x, y; -} UndoTile; - -typedef struct UndoElem { - struct UndoElem *next, *prev; - char name[MAXUNDONAME]; - unsigned long undosize; - - ImBuf *ibuf; - ListBase tiles; -} UndoElem; +typedef struct ImagePaintUndo { + Image *image; + ImBuf *tilebuf; + void **tiles; + int xtiles, ytiles; +} ImagePaintUndo; typedef struct ImagePaintPartialRedraw { int x1, y1, x2, y2; int enabled; } ImagePaintPartialRedraw; -static ListBase undobase = {NULL, NULL}; -static UndoElem *curundo = NULL; +static ImagePaintUndo imapaintundo = {NULL, NULL, NULL, 0, 0}; static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0}; -/* UNDO */ - -/* internal functions */ - -static void undo_copy_tile(UndoTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore) +static void init_imagapaint_undo(Image *ima, ImBuf *ibuf) { - /* copy or swap contents of tile->rect and region in ibuf->rect */ - IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE, - tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); + int xt, yt; - if(ibuf->rect_float) SWAP(void*, tmpibuf->rect_float, tile->rect) - else SWAP(void*, tmpibuf->rect, tile->rect) + imapaintundo.image = ima; + imapaintundo.xtiles = xt = IMAPAINT_TILE_NUMBER(ibuf->x); + imapaintundo.ytiles = yt = IMAPAINT_TILE_NUMBER(ibuf->y); + imapaintundo.tiles = MEM_callocN(sizeof(void*)*xt*yt, "ImagePaintUndoTiles"); + imapaintundo.tilebuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, + ibuf->depth, (ibuf->rect_float)? IB_rectfloat: IB_rect, 0); +} + +static void imapaint_copy_tile(ImBuf *ibuf, int tile, int x, int y, int swapundo) +{ + IMB_rectcpy(imapaintundo.tilebuf, ibuf, 0, 0, x*IMAPAINT_TILE_SIZE, + y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); + + if (imapaintundo.tilebuf->rect_float) + SWAP(void*, imapaintundo.tilebuf->rect_float, imapaintundo.tiles[tile]) + else + SWAP(void*, imapaintundo.tilebuf->rect, imapaintundo.tiles[tile]) - if(restore) - IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE, - tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); + if (swapundo) + IMB_rectcpy(ibuf, imapaintundo.tilebuf, x*IMAPAINT_TILE_SIZE, + y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } -static void undo_restore(UndoElem *undo) -{ - Image *ima = NULL; - ImBuf *ibuf, *tmpibuf; - UndoTile *tile; - - if(!undo) - return; - - tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, - IB_rectfloat|IB_rect, 0); - - for(tile=undo->tiles.first; tile; tile=tile->next) { - /* find image based on name, pointer becomes invalid with global undo */ - if(ima && strcmp(tile->id.name, ima->id.name)==0); - else { - for(ima=G.main->image.first; ima; ima=ima->id.next) - if(strcmp(tile->id.name, ima->id.name)==0) - break; - } - - ibuf= BKE_image_get_ibuf(ima, NULL); - - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) - continue; - - undo_copy_tile(tile, tmpibuf, ibuf, 1); - - GPU_free_image(ima); /* force OpenGL reload */ - if(ibuf->rect_float) - imb_freerectImBuf(ibuf); /* force recreate of char rect */ - } - - IMB_freeImBuf(tmpibuf); -} - -static void undo_free(UndoElem *undo) -{ - UndoTile *tile; - - for(tile=undo->tiles.first; tile; tile=tile->next) - MEM_freeN(tile->rect); - BLI_freelistN(&undo->tiles); -} - -static void undo_imagepaint_push_begin(char *name) -{ - UndoElem *uel; - int nr; - - /* Undo push is split up in begin and end, the reason is that as painting - * happens more tiles are added to the list, and at the very end we know - * how much memory the undo used to remove old undo elements */ - - /* remove all undos after (also when curundo==NULL) */ - while(undobase.last != curundo) { - uel= undobase.last; - undo_free(uel); - BLI_freelinkN(&undobase, uel); - } - - /* make new */ - curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file"); - BLI_addtail(&undobase, uel); - - /* name can be a dynamic string */ - strncpy(uel->name, name, MAXUNDONAME-1); - - /* limit amount to the maximum amount*/ - nr= 0; - uel= undobase.last; - while(uel) { - nr++; - if(nr==U.undosteps) break; - uel= uel->prev; - } - if(uel) { - while(undobase.first!=uel) { - UndoElem *first= undobase.first; - undo_free(first); - BLI_freelinkN(&undobase, first); - } - } -} - -static void undo_imagepaint_push_end() -{ - UndoElem *uel; - unsigned long totmem, maxmem; - - if(U.undomemory != 0) { - /* limit to maximum memory (afterwards, we can't know in advance) */ - totmem= 0; - maxmem= ((unsigned long)U.undomemory)*1024*1024; - - uel= undobase.last; - while(uel) { - totmem+= uel->undosize; - if(totmem>maxmem) break; - uel= uel->prev; - } - - if(uel) { - while(undobase.first!=uel) { - UndoElem *first= undobase.first; - undo_free(first); - BLI_freelinkN(&undobase, first); - } - } - } -} - -/* external functions */ - -/* 1= an undo, -1 is a redo. */ -void undo_imagepaint_step(int step) -{ - UndoElem *undo; - - if(step==1) { - if(curundo==NULL) error("No more steps to undo"); - else { - if(G.f & G_DEBUG) printf("undo %s\n", curundo->name); - undo_restore(curundo); - curundo= curundo->prev; - } - } - else if(step==-1) { - if((curundo!=NULL && curundo->next==NULL) || undobase.first==NULL) error("No more steps to redo"); - else { - undo= (curundo && curundo->next)? curundo->next: undobase.first; - undo_restore(undo); - curundo= undo; - if(G.f & G_DEBUG) printf("redo %s\n", undo->name); - } - } - - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWIMAGE, 0); -} - -void undo_imagepaint_clear(void) -{ - UndoElem *uel; - - uel= undobase.first; - while(uel) { - undo_free(uel); - uel= uel->next; - } - - BLI_freelistN(&undobase); - curundo= NULL; -} - -/* Imagepaint Partial Redraw & Dirty Region */ - static void imapaint_clear_partial_redraw() { memset(&imapaintpartial, 0, sizeof(imapaintpartial)); @@ -334,9 +169,7 @@ static void imapaint_clear_partial_redraw() static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) { - ImBuf *tmpibuf; - UndoTile *tile; - int srcx= 0, srcy= 0, origx, allocsize; + int srcx= 0, srcy= 0, origx, tile, allocsize; IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); @@ -362,36 +195,24 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, origx = (x >> IMAPAINT_TILE_BITS); y = (y >> IMAPAINT_TILE_BITS); - tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, - IB_rectfloat|IB_rect, 0); - for (; y <= h; y++) { for (x=origx; x <= w; x++) { - for(tile=curundo->tiles.first; tile; tile=tile->next) - if(tile->x == x && tile->y == y && strcmp(tile->id.name, ima->id.name)==0) - break; + if (ima != imapaintundo.image) { + free_imagepaint(); + init_imagapaint_undo(ima, ibuf); + } - if(!tile) { - tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); - tile->id= ima->id; - tile->x= x; - tile->y= y; - - allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; - allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); - tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); - - undo_copy_tile(tile, tmpibuf, ibuf, 0); - curundo->undosize += allocsize; - - BLI_addtail(&curundo->tiles, tile); + tile = y*imapaintundo.xtiles + x; + if (!imapaintundo.tiles[tile]) { + allocsize= (ibuf->rect_float)? sizeof(float): sizeof(char); + imapaintundo.tiles[tile]= MEM_mapallocN(allocsize*4* + IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE, "ImagePaintUndoTile"); + imapaint_copy_tile(ibuf, tile, x, y, 0); } } } ibuf->userflags |= IB_BITMAPDIRTY; - - IMB_freeImBuf(tmpibuf); } static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) @@ -405,7 +226,7 @@ static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) if(texpaint || G.sima->lock) { int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; - GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); + update_realtime_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); } } @@ -418,7 +239,7 @@ static void imapaint_redraw(int final, int texpaint, Image *image) allqueue(REDRAWIMAGE, 0); else if(!G.sima->lock) { if(image) - GPU_free_image(image); /* force OpenGL reload */ + free_realtime_image(image); /* force OpenGL reload */ allqueue(REDRAWVIEW3D, 0); } allqueue(REDRAWHEADERS, 0); @@ -448,6 +269,46 @@ static void imapaint_redraw(int final, int texpaint, Image *image) force_draw(0); } +void imagepaint_undo() +{ + Image *ima= imapaintundo.image; + ImBuf *ibuf= BKE_image_get_ibuf(ima, G.sima?&G.sima->iuser:NULL); + int x, y, tile; + + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + return; + + for (tile = 0, y = 0; y < imapaintundo.ytiles; y++) + for (x = 0; x < imapaintundo.xtiles; x++, tile++) + if (imapaintundo.tiles[tile]) + imapaint_copy_tile(ibuf, tile, x, y, 1); + + free_realtime_image(ima); /* force OpenGL reload */ + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); /* force recreate of char rect */ + + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWVIEW3D, 0); +} + +void free_imagepaint() +{ + /* todo: does this need to be in the same places as editmode_undo_clear, + vertex paint isn't? */ + int i, size = imapaintundo.xtiles*imapaintundo.ytiles; + + if (imapaintundo.tiles) { + for (i = 0; i < size; i++) + if (imapaintundo.tiles[i]) + MEM_freeN(imapaintundo.tiles[i]); + MEM_freeN(imapaintundo.tiles); + } + if (imapaintundo.tilebuf) + IMB_freeImBuf(imapaintundo.tilebuf); + + memset(&imapaintundo, 0, sizeof(imapaintundo)); +} + /* Image Paint Operations */ static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, short set, float *rgb) @@ -719,6 +580,7 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho int breakstroke = 0, redraw = 0; if (texpaint) { + /* pick new face and image */ if (facesel_face_pick(s->me, mval, &newfaceindex, 0)) { ImBuf *ibuf; @@ -830,7 +692,7 @@ void imagepaint_paint(short mousebutton, short texpaint) } settings->imapaint.flag |= IMAGEPAINT_DRAWING; - undo_imagepaint_push_begin("Image Paint"); + free_imagepaint(); /* create painter and paint once */ painter= brush_painter_new(s.brush); @@ -879,7 +741,6 @@ void imagepaint_paint(short mousebutton, short texpaint) brush_painter_free(painter); imapaint_redraw(1, texpaint, s.image); - undo_imagepaint_push_end(); if (texpaint) { if (s.warnmultifile) diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c deleted file mode 100644 index 8f887cd4756..00000000000 --- a/source/blender/src/keyframing.c +++ /dev/null @@ -1,1838 +0,0 @@ -/** - * $Id: keyframing.c 14881 2008-05-18 10:41:42Z aligorith $ - * - * ***** 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 - * This is a new part of Blender (with some old code) - * - * Contributor(s): Joshua Leung - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include -#include -#include -#include -#include - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "MEM_guardedalloc.h" - -#include "BLI_arithb.h" -#include "BLI_blenlib.h" -#include "BLI_dynstr.h" - -#include "DNA_listBase.h" -#include "DNA_ID.h" -#include "DNA_action_types.h" -#include "DNA_armature_types.h" -#include "DNA_camera_types.h" -#include "DNA_constraint_types.h" -#include "DNA_curve_types.h" -#include "DNA_ipo_types.h" -#include "DNA_lamp_types.h" -#include "DNA_object_types.h" -#include "DNA_material_types.h" -#include "DNA_screen_types.h" -#include "DNA_scene_types.h" -#include "DNA_space_types.h" -#include "DNA_texture_types.h" -#include "DNA_userdef_types.h" -#include "DNA_vec_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" - -#include "BKE_global.h" -#include "BKE_utildefines.h" -#include "BKE_blender.h" -#include "BKE_main.h" -#include "BKE_action.h" -#include "BKE_armature.h" -#include "BKE_constraint.h" -#include "BKE_curve.h" -#include "BKE_depsgraph.h" -#include "BKE_ipo.h" -#include "BKE_object.h" - -#include "BIF_keyframing.h" -#include "BIF_butspace.h" -#include "BIF_editaction.h" -#include "BIF_editkey.h" -#include "BIF_interface.h" -#include "BIF_mywindow.h" -#include "BIF_poseobject.h" -#include "BIF_screen.h" -#include "BIF_space.h" -#include "BIF_toolbox.h" -#include "BIF_toets.h" - -#include "BSE_editipo.h" -#include "BSE_node.h" -#include "BSE_time.h" -#include "BSE_view.h" - -#include "blendef.h" - -#include "PIL_time.h" /* sleep */ -#include "mydevice.h" - -/* ************************************************** */ -/* LOCAL TYPES AND DEFINES */ - -/* -------------- Keying Sets ------------------- */ - -/* keying set - a set of channels that will be keyframed together */ -// TODO: move this to a header to allow custom sets someday? -typedef struct bKeyingSet { - /* callback func to consider if keyingset should be included - * (by default, if this is undefined, item will be shown) - */ - short (*include_cb)(struct bKeyingSet *, const char *); - - char name[48]; /* name of keyingset */ - int blocktype; /* blocktype that all channels belong to */ // in future, this may be eliminated - short flag; /* flags to use when setting keyframes */ - - short chan_num; /* number of channels to insert keyframe in */ - short adrcodes[32]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */ -} bKeyingSet; - -/* keying set context - an array of keying sets and the number of them */ -typedef struct bKeyingContext { - bKeyingSet *keyingsets; /* array containing the keyingsets of interest */ - bKeyingSet *lastused; /* item that was chosen last time*/ - int tot; /* number of keyingsets in */ -} bKeyingContext; - - -/* ----------- Common KeyData Sources ------------ */ - -/* temporary struct to gather data combos to keyframe */ -typedef struct bCommonKeySrc { - struct bCommonKeySrc *next, *prev; - - /* general data/destination-source settings */ - ID *id; /* id-block this comes from */ - char *actname; /* name of action channel */ - char *constname; /* name of constraint channel */ - - /* general destination source settings */ - Ipo *ipo; /* ipo-block that id-block has (optional) */ - bAction *act; /* action-block that id-block has (optional) */ - - /* pose-level settings */ - bPoseChannel *pchan; /* pose channel */ - - /* buttons-window settings */ - int map; /* offset to apply to certain adrcodes */ -} bCommonKeySrc; - -/* ************************************************** */ -/* KEYFRAME INSERTION */ - -/* -------------- BezTriple Insertion -------------------- */ - -/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ -#define BEZT_INSERT_THRESH 0.00001 - -/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) - * Returns the index to insert at (data already at that index will be offset if replace is 0) - */ -static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) -{ - int start=0, end=arraylen; - int loopbreaker= 0, maxloop= arraylen * 2; - const float frame= (item)? item->vec[1][0] : 0.0f; - - /* initialise replace-flag first */ - *replace= 0; - - /* sneaky optimisations (don't go through searching process if...): - * - keyframe to be added is to be added out of current bounds - * - keyframe to be added would replace one of the existing ones on bounds - */ - if ((arraylen <= 0) || ELEM(NULL, array, item)) { - printf("Warning: binarysearch_bezt_index encountered invalid array \n"); - return 0; - } - else { - /* check whether to add before/after/on */ - float framenum; - - /* 'First' Keyframe (when only one keyframe, this case is used) */ - framenum= array[0].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace = 1; - return 0; - } - else if (frame < framenum) - return 0; - - /* 'Last' Keyframe */ - framenum= array[(arraylen-1)].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace= 1; - return (arraylen - 1); - } - else if (frame > framenum) - return arraylen; - } - - - /* most of the time, this loop is just to find where to put it - * 'loopbreaker' is just here to prevent infinite loops - */ - for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { - /* compute and get midpoint */ - int mid = (start + end) / 2; - float midfra= array[mid].vec[1][0]; - - /* check if exactly equal to midpoint */ - if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { - *replace = 1; - return mid; - } - - /* repeat in upper/lower half */ - if (frame > midfra) - start= mid + 1; - else if (frame < midfra) - end= mid - 1; - } - - /* print error if loop-limit exceeded */ - if (loopbreaker == (maxloop-1)) { - printf("Error: binarysearch_bezt_index was taking too long \n"); - - // include debug info - printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); - } - - /* not found, so return where to place it */ - return start; -} - -/* This function adds a given BezTriple to an IPO-Curve. It will allocate - * memory for the array if needed, and will insert the BezTriple into a - * suitable place in chronological order. - * - * NOTE: any recalculate of the IPO-Curve that needs to be done will need to - * be done by the caller. - */ -int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) -{ - BezTriple *newb; - int i= 0; - - if (icu->bezt == NULL) { - icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); - *(icu->bezt)= *bezt; - icu->totvert= 1; - } - else { - short replace = -1; - i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); - - if (replace) { - /* sanity check: 'i' may in rare cases exceed arraylen */ - if ((i >= 0) && (i < icu->totvert)) - *(icu->bezt + i) = *bezt; - } - else { - /* add new */ - newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); - - /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ - if (i > 0) - memcpy(newb, icu->bezt, i*sizeof(BezTriple)); - - /* add beztriple to paste at index i */ - *(newb + i)= *bezt; - - /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ - if (i < icu->totvert) - memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); - - /* replace (+ free) old with new */ - MEM_freeN(icu->bezt); - icu->bezt= newb; - - icu->totvert++; - } - } - - /* we need to return the index, so that some tools which do post-processing can - * detect where we added the BezTriple in the array - */ - return i; -} - -/* This function is a wrapper for insert_bezt_icu, and should be used when - * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere - * else yet. - * - * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. - */ -void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) -{ - BezTriple beztr; - int a, h1, h2; - - /* set all three points, for nicer start position */ - memset(&beztr, 0, sizeof(BezTriple)); - beztr.vec[0][0]= x; - beztr.vec[0][1]= y; - beztr.vec[1][0]= x; - beztr.vec[1][1]= y; - beztr.vec[2][0]= x; - beztr.vec[2][1]= y; - beztr.hide= IPO_BEZ; - beztr.f1= beztr.f2= beztr.f3= SELECT; - beztr.h1= beztr.h2= HD_AUTO; - - /* add temp beztriple to keyframes */ - a= insert_bezt_icu(icu, &beztr); - if (!fast) calchandles_ipocurve(icu); - - /* set handletype */ - if (icu->totvert > 2) { - BezTriple *bezt; - - h1= h2= HD_AUTO; - bezt= (icu->bezt + a); - - if (a > 0) h1= (bezt-1)->h2; - if (a < icu->totvert-1) h2= (bezt+1)->h1; - - bezt->h1= h1; - bezt->h2= h2; - - if (!fast) calchandles_ipocurve(icu); - } -} - -/* ------------------- Get Data ------------------------ */ - -/* Get pointer to use to get values from */ -// FIXME: this should not be possible with Data-API -static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) -{ - switch (blocktype) { - case ID_PO: /* posechannel */ - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - *vartype= IPO_FLOAT; - return get_pchan_ipo_poin(pchan, icu->adrcode); - } - } - break; - - case ID_CO: /* constraint */ - if ((GS(id->name)==ID_OB) && (constname && constname[0])) { - Object *ob= (Object *)id; - bConstraint *con; - - /* assume that we only want the influence (as only used for Constraint Channels) */ - if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { - for (con= ob->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - else if (ob->pose) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - for (con= pchan->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - } - } - break; - - case ID_OB: /* object */ - /* hack: layer channels for object need to be keyed WITHOUT localview flag... - * tsk... tsk... why must we just dump bitflags upon users :/ - */ - if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) { - Object *ob= (Object *)id; - static int layer = 0; - - /* init layer to be the object's layer var, then remove local view from it */ - layer = ob->lay; - layer &= 0xFFFFFF; - - /* return pointer to this static var - * - assumes that this pointer won't be stored for use later, so may not be threadsafe - * if multiple keyframe calls are made, but that is unlikely to happen in the near future - */ - return (void *)(&layer); - } - /* no break here for other ob channel-types - as they can be done normally */ - - default: /* normal data-source */ - return get_ipo_poin(id, icu, vartype); - } - - /* not valid... */ - return NULL; -} - - -/* -------------- 'Smarter' Keyframing Functions -------------------- */ -/* return codes for new_key_needed */ -enum { - KEYNEEDED_DONTADD = 0, - KEYNEEDED_JUSTADD, - KEYNEEDED_DELPREV, - KEYNEEDED_DELNEXT -} eKeyNeededStatus; - -/* This helper function determines whether a new keyframe is needed */ -/* Cases where keyframes should not be added: - * 1. Keyframe to be added bewteen two keyframes with similar values - * 2. Keyframe to be added on frame where two keyframes are already situated - * 3. Keyframe lies at point that intersects the linear line between two keyframes - */ -static short new_key_needed (IpoCurve *icu, float cFrame, float nValue) -{ - BezTriple *bezt=NULL, *prev=NULL; - int totCount, i; - float valA = 0.0f, valB = 0.0f; - - /* safety checking */ - if (icu == NULL) return KEYNEEDED_JUSTADD; - totCount= icu->totvert; - if (totCount == 0) return KEYNEEDED_JUSTADD; - - /* loop through checking if any are the same */ - bezt= icu->bezt; - for (i=0; ivec[1][0]; - beztVal= bezt->vec[1][1]; - - if (prev) { - /* there is a keyframe before the one currently being examined */ - - /* get previous time+value */ - prevPosi= prev->vec[1][0]; - prevVal= prev->vec[1][1]; - - /* keyframe to be added at point where there are already two similar points? */ - if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { - return KEYNEEDED_DONTADD; - } - - /* keyframe between prev+current points ? */ - if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { - /* is the value of keyframe to be added the same as keyframes on either side ? */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { - return KEYNEEDED_DONTADD; - } - else { - float realVal; - - /* get real value of curve at that point */ - realVal= eval_icu(icu, cFrame); - - /* compare whether it's the same as proposed */ - if (IS_EQ(realVal, nValue)) - return KEYNEEDED_DONTADD; - else - return KEYNEEDED_JUSTADD; - } - } - - /* new keyframe before prev beztriple? */ - if (cFrame < prevPosi) { - /* A new keyframe will be added. However, whether the previous beztriple - * stays around or not depends on whether the values of previous/current - * beztriples and new keyframe are the same. - */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) - return KEYNEEDED_DELNEXT; - else - return KEYNEEDED_JUSTADD; - } - } - else { - /* just add a keyframe if there's only one keyframe - * and the new one occurs before the exisiting one does. - */ - if ((cFrame < beztPosi) && (totCount==1)) - return KEYNEEDED_JUSTADD; - } - - /* continue. frame to do not yet passed (or other conditions not met) */ - if (i < (totCount-1)) { - prev= bezt; - bezt++; - } - else - break; - } - - /* Frame in which to add a new-keyframe occurs after all other keys - * -> If there are at least two existing keyframes, then if the values of the - * last two keyframes and the new-keyframe match, the last existing keyframe - * gets deleted as it is no longer required. - * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last - * keyframe is not equal to last keyframe. - */ - bezt= (icu->bezt + (icu->totvert - 1)); - valA= bezt->vec[1][1]; - - if (prev) - valB= prev->vec[1][1]; - else - valB= bezt->vec[1][1] + 1.0f; - - if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) - return KEYNEEDED_DELPREV; - else - return KEYNEEDED_JUSTADD; -} - -/* ------------------ 'Visual' Keyframing Functions ------------------ */ - -/* internal status codes for visualkey_can_use */ -enum { - VISUALKEY_NONE = 0, - VISUALKEY_LOC, - VISUALKEY_ROT -}; - -/* This helper function determines if visual-keyframing should be used when - * inserting keyframes for the given channel. As visual-keyframing only works - * on Object and Pose-Channel blocks, this should only get called for those - * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying - * settings is on. - */ -static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - Object *ob= NULL; - bConstraint *con= NULL; - short searchtype= VISUALKEY_NONE; - - /* validate data */ - if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO))) - return 0; - - /* get first constraint and determine type of keyframe constraints to check for*/ - ob= (Object *)id; - - if (blocktype == ID_OB) { - con= ob->constraints.first; - - if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) - searchtype= VISUALKEY_LOC; - else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) - searchtype= VISUALKEY_ROT; - } - else if (blocktype == ID_PO) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - con= pchan->constraints.first; - - if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) - searchtype= VISUALKEY_LOC; - else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) - searchtype= VISUALKEY_ROT; - } - - /* only search if a searchtype and initial constraint are available */ - if (searchtype && con) { - for (; con; con= con->next) { - /* only consider constraint if it is not disabled, and has influence */ - if (con->flag & CONSTRAINT_DISABLE) continue; - if (con->enforce == 0.0f) continue; - - /* some constraints may alter these transforms */ - switch (con->type) { - /* multi-transform constraints */ - case CONSTRAINT_TYPE_CHILDOF: - return 1; - case CONSTRAINT_TYPE_TRANSFORM: - return 1; - case CONSTRAINT_TYPE_FOLLOWPATH: - return 1; - - /* single-transform constraits */ - case CONSTRAINT_TYPE_TRACKTO: - if (searchtype==VISUALKEY_ROT) return 1; - break; - case CONSTRAINT_TYPE_ROTLIMIT: - if (searchtype==VISUALKEY_ROT) return 1; - break; - case CONSTRAINT_TYPE_LOCLIMIT: - if (searchtype==VISUALKEY_LOC) return 1; - break; - case CONSTRAINT_TYPE_ROTLIKE: - if (searchtype==VISUALKEY_ROT) return 1; - break; - case CONSTRAINT_TYPE_LOCLIKE: - if (searchtype==VISUALKEY_LOC) return 1; - break; - case CONSTRAINT_TYPE_LOCKTRACK: - if (searchtype==VISUALKEY_ROT) return 1; - break; - case CONSTRAINT_TYPE_MINMAX: - if (searchtype==VISUALKEY_LOC) return 1; - break; - - default: - break; - } - } - } - - /* when some condition is met, this function returns, so here it can be 0 */ - return 0; -} - -/* This helper function extracts the value to use for visual-keyframing - * In the event that it is not possible to perform visual keying, try to fall-back - * to using the poin method. Assumes that all data it has been passed is valid. - */ -static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu) -{ - Object *ob; - void *poin = NULL; - int index, vartype; - - /* validate situtation */ - if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0)) - return 0.0f; - - /* get object */ - ob= (Object *)id; - - /* only valid for objects or posechannels */ - if (blocktype == ID_OB) { - /* parented objects are not supported, as the effects of the parent - * are included in the matrix, which kindof beats the point - */ - if ((ob) && (ob->parent==NULL)) { - /* only Location or Rotation keyframes are supported now */ - if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) { - /* assumes that OB_LOC_Z > OB_LOC_Y > OB_LOC_X */ - index= adrcode - OB_LOC_X; - - return ob->obmat[3][index]; - } - else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) { - float eul[3]; - - /* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */ - index= adrcode - OB_ROT_X; - - Mat4ToEul(ob->obmat, eul); - return eul[index]*(5.72958); - } - } - } - else if (blocktype == ID_PO) { - bPoseChannel *pchan; - float tmat[4][4]; - - /* get data to use */ - pchan= get_pose_channel(ob->pose, actname); - - /* Although it is not strictly required for this particular space conversion, - * arg1 must not be null, as there is a null check for the other conversions to - * be safe. Therefore, the active object is passed here, and in many cases, this - * will be what owns the pose-channel that is getting this anyway. - */ - Mat4CpyMat4(tmat, pchan->pose_mat); - constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); - - /* Loc, Rot/Quat keyframes are supported... */ - if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) { - /* assumes that AC_LOC_Z > AC_LOC_Y > AC_LOC_X */ - index= adrcode - AC_LOC_X; - - /* only use for non-connected bones */ - if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED)) - return tmat[3][index]; - else if (pchan->bone->parent == NULL) - return tmat[3][index]; - } - else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) { - float tmat[4][4], trimat[3][3], quat[4]; - - /* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */ - index= adrcode - AC_QUAT_W; - - Mat3CpyMat4(trimat, tmat); - Mat3ToQuat_is_ok(trimat, quat); - - return quat[index]; - } - } - - /* as the function hasn't returned yet, try reading from poin */ - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - if (poin) - return read_ipo_poin(poin, vartype); - else - return 0.0; -} - - -/* ------------------------- Insert Key API ------------------------- */ - -/* Main Keyframing API call: - * Use this when validation of necessary animation data isn't necessary as it - * already exists. It will insert a keyframe using the current value being keyframed. - * - * The flag argument is used for special settings that alter the behaviour of - * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, - * and extra keyframe filtering. - */ -short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) -{ - IpoCurve *icu; - - /* get ipo-curve */ - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1); - - /* only continue if we have an ipo-curve to add keyframe to */ - if (icu) { - float cfra = frame_to_float(CFRA); - float curval= 0.0f; - void *poin = NULL; - int vartype; - - /* apply special time tweaking */ - if (GS(id->name) == ID_OB) { - Object *ob= (Object *)id; - - /* apply NLA-scaling (if applicable) */ - if (actname && actname[0]) - cfra= get_action_frame(ob, cfra); - - /* ancient time-offset cruft */ - if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* get pointer to data to read from */ - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - if (poin == NULL) return 0; - - /* obtain value to give keyframe */ - if ( (flag & INSERTKEY_MATRIX) && - (visualkey_can_use(id, blocktype, actname, constname, adrcode)) ) - { - /* visual-keying is only available for object and pchan datablocks, as - * it works by keyframing using a value extracted from the final matrix - * instead of using the kt system to extract a value. - */ - curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu); - } - else { - /* use kt's read_poin function to extract value (kt->read_poin should - * exist in all cases, but it never hurts to check) - */ - curval= read_ipo_poin(poin, vartype); - } - - /* only insert keyframes where they are needed */ - if (flag & INSERTKEY_NEEDED) { - short insert_mode; - - /* check whether this curve really needs a new keyframe */ - insert_mode= new_key_needed(icu, cfra, curval); - - /* insert new keyframe at current frame */ - if (insert_mode) - insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); - - /* delete keyframe immediately before/after newly added */ - switch (insert_mode) { - case KEYNEEDED_DELPREV: - delete_icu_key(icu, icu->totvert-2, 1); - break; - case KEYNEEDED_DELNEXT: - delete_icu_key(icu, 1, 1); - break; - } - } - else { - /* just insert keyframe */ - insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); - } - - /* return success */ - return 1; - } - - /* return failure */ - return 0; -} - - -/* ************************************************** */ -/* KEYFRAME DELETION */ - -/* Main Keyframing API call: - * Use this when validation of necessary animation data isn't necessary as it - * already exists. It will delete a keyframe at the current frame. - * - * The flag argument is used for special settings that alter the behaviour of - * the keyframe deletion. These include the quick refresh options. - */ -short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) -{ - Ipo *ipo; - IpoCurve *icu; - - /* get ipo-curve - * Note: here is one of the places where we don't want new ipo + ipo-curve added! - * so 'add' var must be 0 - */ - ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0); - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0); - - /* only continue if we have an ipo-curve to remove keyframes from */ - if (icu) { - BezTriple bezt; - float cfra = frame_to_float(CFRA); - short found = -1; - int i; - - /* apply special time tweaking */ - if (GS(id->name) == ID_OB) { - Object *ob= (Object *)id; - - /* apply NLA-scaling (if applicable) */ - if (actname && actname[0]) - cfra= get_action_frame(ob, cfra); - - /* ancient time-offset cruft */ - if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* only need to set bezt->vec[1][0], as that's all binarysearch uses */ - memset(&bezt, 0, sizeof(BezTriple)); - bezt.vec[1][0]= cfra; - - /* try to find index of beztriple to get rid of */ - i = binarysearch_bezt_index(icu->bezt, &bezt, icu->totvert, &found); - if (found) { - /* delete the key at the index (will sanity check + do recalc afterwards ) */ - delete_icu_key(icu, i, 1); - - /* Only delete curve too if there isn't an ipo-driver still hanging around on an empty curve */ - if (icu->totvert==0 && icu->driver==NULL) { - BLI_remlink(&ipo->curve, icu); - free_ipo_curve(icu); - } - - /* return success */ - return 1; - } - } - - /* return failure */ - return 0; -} - -/* ************************************************** */ -/* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */ - - -/* ------------- KeyingSet Defines ------------ */ -/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */ - -/* macro for defining keyingset contexts */ -#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)} - -/* --- */ - -/* check if option not available for deleting keys */ -static short incl_non_del_keys (bKeyingSet *ks, const char mode[]) -{ - /* as optimisation, assume that it is sufficient to check only first letter - * of mode (int comparison should be faster than string!) - */ - //if (strcmp(mode, "Delete")==0) - if (mode && mode[0]=='D') - return 0; - - return 1; -} - -/* Object KeyingSets ------ */ - -/* check if include shapekey entry */ -static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[]) -{ - Object *ob= (G.obedit)? (G.obedit) : (OBACT); - char *newname= NULL; - - /* not available for delete mode */ - if (strcmp(mode, "Delete")==0) - return 0; - - /* check if is geom object that can get shapekeys */ - switch (ob->type) { - /* geometry? */ - case OB_MESH: newname= "Mesh"; break; - case OB_CURVE: newname= "Curve"; break; - case OB_SURF: newname= "Surface"; break; - case OB_LATTICE: newname= "Lattice"; break; - - /* not geometry! */ - default: - return 0; - } - - /* if ks is shapekey entry (this could be callled for separator before too!) */ - if (ks->flag == -3) - sprintf(ks->name, newname); - - /* if it gets here, it's ok */ - return 1; -} - -/* array for object keyingset defines */ -bKeyingSet defks_v3d_object[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, - {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, - {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "LocRot", ID_OB, 0, 6, - {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, - OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, - - {NULL, "LocScale", ID_OB, 0, 6, - {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, - OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - - {NULL, "LocRotScale", ID_OB, 0, 9, - {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, - OB_ROT_X,OB_ROT_Y,OB_ROT_Z, - OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - - {NULL, "RotScale", ID_OB, 0, 6, - {OB_ROT_X,OB_ROT_Y,OB_ROT_Z, - OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - - {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator - - {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, - {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, - - {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, - {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, - OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option... - {NULL, "Available", ID_OB, -2, 0, {0}}, - - {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry) - {incl_v3d_ob_shapekey, "", ID_OB, -3, 0, {0}} -}; - -/* PoseChannel KeyingSets ------ */ - -/* array for posechannel keyingset defines */ -bKeyingSet defks_v3d_pchan[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, - {NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, - {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "LocRot", ID_PO, 0, 7, - {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, - AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, - - {NULL, "LocScale", ID_PO, 0, 6, - {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, - AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - - {NULL, "LocRotScale", ID_PO, 0, 10, - {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,AC_QUAT_X, - AC_QUAT_Y,AC_QUAT_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - - {NULL, "RotScale", ID_PO, 0, 7, - {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z, - AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - - {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator - - {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, - {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, - - {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, - {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, - AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_PO, -2, 0, {0}} -}; - -/* Material KeyingSets ------ */ - -/* array for material keyingset defines */ -bKeyingSet defks_buts_shading_mat[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}}, - {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}}, - {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}}, - {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "All Color", ID_MA, 0, 18, - {MA_COL_R,MA_COL_G,MA_COL_B, - MA_ALPHA,MA_HASIZE, MA_MODE, - MA_SPEC_R,MA_SPEC_G,MA_SPEC_B, - MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD, - MA_MODE,MA_TRANSLU,MA_ADD}}, - - {NULL, "All Mirror", ID_MA, 0, 5, - {MA_RAYM,MA_FRESMIR,MA_FRESMIRI, - MA_FRESTRA,MA_FRESTRAI}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Ofs", ID_MA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, - {NULL, "Size", ID_MA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, - - {NULL, "All Mapping", ID_MA, 0, 14, - {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, - MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, - MAP_R,MAP_G,MAP_B,MAP_DVAR, - MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_MA, -2, 0, {0}} -}; - -/* World KeyingSets ------ */ - -/* array for world keyingset defines */ -bKeyingSet defks_buts_shading_wo[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}}, - {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}}, - {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}}, - - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Ofs", ID_WO, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, - {NULL, "Size", ID_WO, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, - - {NULL, "All Mapping", ID_WO, 0, 14, - {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, - MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, - MAP_R,MAP_G,MAP_B,MAP_DVAR, - MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_WO, -2, 0, {0}} -}; - -/* Lamp KeyingSets ------ */ - -/* array for lamp keyingset defines */ -bKeyingSet defks_buts_shading_la[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}}, - {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}}, - {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Ofs", ID_LA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, - {NULL, "Size", ID_LA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, - - {NULL, "All Mapping", ID_LA, 0, 14, - {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, - MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, - MAP_R,MAP_G,MAP_B,MAP_DVAR, - MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_LA, -2, 0, {0}} -}; - -/* Texture KeyingSets ------ */ - -/* array for texture keyingset defines */ -bKeyingSet defks_buts_shading_tex[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "Clouds", ID_TE, 0, 5, - {TE_NSIZE,TE_NDEPTH,TE_NTYPE, - TE_MG_TYP,TE_N_BAS1}}, - - {NULL, "Marble", ID_TE, 0, 7, - {TE_NSIZE,TE_NDEPTH,TE_NTYPE, - TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, - - {NULL, "Stucci", ID_TE, 0, 5, - {TE_NSIZE,TE_NTYPE,TE_TURB, - TE_MG_TYP,TE_N_BAS1}}, - - {NULL, "Wood", ID_TE, 0, 6, - {TE_NSIZE,TE_NTYPE,TE_TURB, - TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, - - {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}}, - - {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}}, - - {NULL, "Musgrave", ID_TE, 0, 6, - {TE_MG_TYP,TE_MGH,TE_MG_LAC, - TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}}, - - {NULL, "Voronoi", ID_TE, 0, 9, - {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4, - TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT, - TE_ISCA,TE_NSIZE}}, - - {NULL, "Distorted Noise", ID_TE, 0, 4, - {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}}, - - {NULL, "Color Filter", ID_TE, 0, 5, - {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_TE, -2, 0, {0}} -}; - -/* Object Buttons KeyingSets ------ */ - -/* check if include particles entry */ -static short incl_buts_ob (bKeyingSet *ks, const char mode[]) -{ - Object *ob= OBACT; - /* only if object is mesh type */ - return (ob->type == OB_MESH); -} - -/* array for texture keyingset defines */ -bKeyingSet defks_buts_object[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}}, - {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}}, - {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}}, - {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too! -}; - -/* Camera Buttons KeyingSets ------ */ - -/* check if include internal-renderer entry */ -static short incl_buts_cam1 (bKeyingSet *ks, const char mode[]) -{ - /* only if renderer is internal renderer */ - return (G.scene->r.renderer==R_INTERN); -} - -/* check if include external-renderer entry */ -static short incl_buts_cam2 (bKeyingSet *ks, const char mode[]) -{ - /* only if renderer is internal renderer */ - return (G.scene->r.renderer!=R_INTERN); -} - -/* array for camera keyingset defines */ -bKeyingSet defks_buts_cam[] = -{ - /* include_cb, name, blocktype, flag, chan_num, adrcodes */ - {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}}, - {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}}, - {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - - {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}}, - {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}}, - - {NULL, "%l", 0, -1, 0, {0}}, // separator - - {NULL, "Available", ID_CA, -2, 0, {0}} -}; - -/* --- */ - -/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */ -bKeyingContext ks_contexts[] = -{ - KSC_TEMPLATE(v3d_object), - KSC_TEMPLATE(v3d_pchan), - - KSC_TEMPLATE(buts_shading_mat), - KSC_TEMPLATE(buts_shading_wo), - KSC_TEMPLATE(buts_shading_la), - KSC_TEMPLATE(buts_shading_tex), - - KSC_TEMPLATE(buts_object), - KSC_TEMPLATE(buts_cam) -}; - -/* Keying Context Enumeration - Must keep in sync with definitions*/ -typedef enum eKS_Contexts { - KSC_V3D_OBJECT = 0, - KSC_V3D_PCHAN, - - KSC_BUTS_MAT, - KSC_BUTS_WO, - KSC_BUTS_LA, - KSC_BUTS_TEX, - - KSC_BUTS_OB, - KSC_BUTS_CAM, - - /* make sure this last one remains untouched! */ - KSC_TOT_TYPES -} eKS_Contexts; - - -/* ---------------- KeyingSet Tools ------------------- */ - -/* helper for commonkey_context_get() - get keyingsets for 3d-view */ -static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) -{ - Object *ob; - IpoCurve *icu; - - if ((OBACT) && (OBACT->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - - /* pose-level */ - ob= OBACT; - *ksc= &ks_contexts[KSC_V3D_PCHAN]; - set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ - - /* loop through posechannels */ - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { - if (pchan->flag & POSE_KEY) { - bCommonKeySrc *cks; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set id-block to key to, and action */ - cks->id= (ID *)ob; - cks->act= ob->action; - - /* set pchan */ - cks->pchan= pchan; - cks->actname= pchan->name; - } - } - } - else { - Base *base; - - /* object-level */ - *ksc= &ks_contexts[KSC_V3D_OBJECT]; - - /* loop through bases */ - for (base= FIRSTBASE; base; base= base->next) { - if (TESTBASELIB(base)) { - bCommonKeySrc *cks; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set id-block to key to */ - ob= base->object; - cks->id= (ID *)ob; - - /* when ob's keyframes are in an action, default to using 'Object' as achan name */ - if (ob->ipoflag & OB_ACTION_OB) - cks->actname= "Object"; - - /* set ipo-flags */ - // TODO: add checks for lib-linked data - if ((ob->ipo) || (ob->action)) { - if (ob->ipo) { - cks->ipo= ob->ipo; - } - else { - bActionChannel *achan; - - cks->act= ob->action; - achan= get_action_channel(ob->action, cks->actname); - - if (achan && achan->ipo) - cks->ipo= achan->ipo; - } - - /* deselect all ipo-curves */ - for (icu= cks->ipo->curve.first; icu; icu= icu->next) { - icu->flag &= ~IPO_SELECT; - } - } - } - } - } -} - -/* helper for commonkey_context_get() - get keyingsets for buttons window */ -static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) -{ - bCommonKeySrc *cks; - - /* check on tab-type */ - switch (G.buts->mainb) { - case CONTEXT_SHADING: /* ------------- Shading buttons ---------------- */ - /* subtabs include "Material", "Texture", "Lamp", "World"*/ - switch (G.buts->tab[CONTEXT_SHADING]) { - case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */ - { - Material *ma= editnode_get_active_material(G.buts->lockpoin); - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set data */ - cks->id= (ID *)ma; - cks->ipo= ma->ipo; - cks->map= texchannel_to_adrcode(ma->texact); - - /* set keyingsets */ - *ksc= &ks_contexts[KSC_BUTS_MAT]; - return; - } - break; - case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */ - { - World *wo= G.buts->lockpoin; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set data */ - cks->id= (ID *)wo; - cks->ipo= wo->ipo; - cks->map= texchannel_to_adrcode(wo->texact); - - /* set keyingsets */ - *ksc= &ks_contexts[KSC_BUTS_WO]; - return; - } - break; - case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */ - { - Lamp *la= G.buts->lockpoin; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set data */ - cks->id= (ID *)la; - cks->ipo= la->ipo; - cks->map= texchannel_to_adrcode(la->texact); - - /* set keyingsets */ - *ksc= &ks_contexts[KSC_BUTS_LA]; - return; - } - break; - case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */ - { - Tex *tex= G.buts->lockpoin; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set data */ - cks->id= (ID *)tex; - cks->ipo= tex->ipo; - - /* set keyingsets */ - *ksc= &ks_contexts[KSC_BUTS_TEX]; - return; - } - break; - } - break; - - case CONTEXT_OBJECT: /* ------------- Object buttons ---------------- */ - { - Object *ob= OBACT; - - if (ob) { - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set id-block to key to */ - cks->id= (ID *)ob; - cks->ipo= ob->ipo; - - /* set keyingsets */ - *ksc= &ks_contexts[KSC_BUTS_OB]; - return; - } - } - break; - - case CONTEXT_EDITING: /* ------------- Editing buttons ---------------- */ - { - Object *ob= OBACT; - - if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */ - Camera *ca= G.buts->lockpoin; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set id-block to key to */ - cks->id= (ID *)ca; - cks->ipo= ca->ipo; - - /* set keyingsets */ - *ksc= &ks_contexts[KSC_BUTS_CAM]; - return; - } - } - break; - } - - /* if nothing happened... */ - *ksc= NULL; -} - - -/* get keyingsets for appropriate context */ -static void commonkey_context_get (ListBase *sources, bKeyingContext **ksc) -{ - /* check view type */ - switch (curarea->spacetype) { - /* 3d view - first one tested as most often used */ - case SPACE_VIEW3D: - commonkey_context_getv3d(sources, ksc); - break; - - /* buttons view */ - case SPACE_BUTS: - commonkey_context_getsbuts(sources, ksc); - break; - } -} - -/* flush updates after all operations */ -static void commonkey_context_finish (ListBase *sources) -{ - /* check view type */ - switch (curarea->spacetype) { - /* 3d view - first one tested as most often used */ - case SPACE_VIEW3D: - { - /* either pose or object level */ - if (OBACT && (OBACT->pose)) { - Object *ob= OBACT; - - /* recalculate ipo handles, etc. */ - if (ob->action) - remake_action_ipos(ob->action); - - /* recalculate bone-paths on adding new keyframe? */ - // TODO: currently, there is no setting to turn this on/off globally - if (ob->pose->flag & POSE_RECALCPATHS) - pose_recalculate_paths(ob); - } - else { - bCommonKeySrc *cks; - - /* loop over bases (as seen in sources) */ - for (cks= sources->first; cks; cks= cks->next) { - Object *ob= (Object *)cks->id; - - /* simply set recalc flag */ - ob->recalc |= OB_RECALC_OB; - } - } - } - break; - } -} - -/* flush refreshes after undo */ -static void commonkey_context_refresh (void) -{ - /* check view type */ - switch (curarea->spacetype) { - /* 3d view - first one tested as most often used */ - case SPACE_VIEW3D: - { - /* do refreshes */ - DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); - - allspace(REMAKEIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWMARKER, 0); - } - break; - } -} - -/* --- */ - -/* Build menu-string of available keying-sets (allocates memory for string) - * NOTE: mode must not be longer than 64 chars - */ -static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48]) -{ - DynStr *pupds= BLI_dynstr_new(); - bKeyingSet *ks; - char buf[64]; - char *str; - int i, n; - - /* add title first */ - BLI_snprintf(buf, 64, "%s Key %%t|", mode); - BLI_dynstr_append(pupds, buf); - - /* loop through keyingsets, adding them */ - for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) { - /* check if keyingset can be used */ - if (ks->flag == -1) { - /* optional separator? */ - if (ks->include_cb) { - if (ks->include_cb(ks, mode)) { - BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") ); - BLI_dynstr_append(pupds, buf); - } - } - else { - BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") ); - BLI_dynstr_append(pupds, buf); - } - } - else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) { - /* entry can be included */ - BLI_dynstr_append(pupds, ks->name); - - /* check if special "shapekey" entry */ - if (ks->flag == -3) - BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") ); - else - BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") ); - BLI_dynstr_append(pupds, buf); - } - } - - /* convert to normal MEM_malloc'd string */ - str= BLI_dynstr_get_cstring(pupds); - BLI_dynstr_free(pupds); - - return str; -} - -/* Get the keying set that was chosen by the user from the menu */ -static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index) -{ - /* check if index is valid */ - if (ELEM(NULL, ksc, ksc->keyingsets)) - return NULL; - if ((index < 1) || (index > ksc->tot)) - return NULL; - - /* index starts from 1, and should directly correspond to keyingset in array */ - return (bKeyingSet *)(ksc->keyingsets + (index - 1)); -} - -/* ---------------- Keyframe Management API -------------------- */ - -/* mode for common_modifykey */ -enum { - COMMONKEY_MODE_INSERT = 0, - COMMONKEY_MODE_DELETE, -} eCommonModifyKey_Modes; - -/* Display a menu for handling the insertion of keyframes based on the active view */ -// TODO: add back an option for repeating last keytype -void common_modifykey (short mode) -{ - ListBase dsources = {NULL, NULL}; - bKeyingContext *ksc= NULL; - bCommonKeySrc *cks; - bKeyingSet *ks = NULL; - char *menustr, buf[64]; - short menu_nr; - - /* check if mode is valid */ - if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0) - return; - - /* delegate to other functions or get keyingsets to use */ - switch (curarea->spacetype) { - /* spaces with their own methods */ - case SPACE_IPO: - if (mode == COMMONKEY_MODE_INSERT) - insertkey_editipo(); - return; - case SPACE_ACTION: - if (mode == COMMONKEY_MODE_INSERT) - insertkey_action(); - return; - - /* TODO: based on UI elements? will that even be handled here??? */ - - /* default - check per view */ - default: - /* get the keyingsets and the data to add keyframes to */ - commonkey_context_get(&dsources, &ksc); - break; - } - - /* check that there is data to operate on */ - if (ELEM(NULL, dsources.first, ksc)) { - BLI_freelistN(&dsources); - return; - } - - /* get menu and process it */ - if (mode == COMMONKEY_MODE_DELETE) - menustr= build_keyingsets_menu(ksc, "Delete"); - else - menustr= build_keyingsets_menu(ksc, "Insert"); - menu_nr= pupmenu(menustr); - if (menustr) MEM_freeN(menustr); - - /* no item selected or shapekey entry? */ - if (menu_nr < 1) { - /* free temp sources */ - BLI_freelistN(&dsources); - - /* check if insert new shapekey */ - if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT)) - insert_shapekey(OBACT); - else - ksc->lastused= NULL; - - return; - } - else { - /* try to get keyingset */ - ks= get_keyingset_fromcontext(ksc, menu_nr); - - if (ks == NULL) { - BLI_freelistN(&dsources); - return; - } - } - - /* loop over each destination, applying the keying set */ - for (cks= dsources.first; cks; cks= cks->next) { - short success= 0; - - /* special hacks for 'available' option */ - if (ks->flag == -2) { - IpoCurve *icu= NULL, *icn= NULL; - - /* get first IPO-curve */ - if (cks->act && cks->actname) { - bActionChannel *achan= get_action_channel(cks->act, cks->actname); - - // FIXME: what about constraint channels? - if (achan && achan->ipo) - icu= achan->ipo->curve.first; - } - else - icu= cks->ipo->curve.first; - - /* we get adrcodes directly from IPO curves (see method below...) */ - for (; icu; icu= icn) { - short flag; - - /* get next ipo-curve in case current is deleted */ - icn= icu->next; - - /* insert mode or delete mode */ - if (mode == COMMONKEY_MODE_DELETE) { - /* local flags only add on to global flags */ - flag = 0; - - /* delete keyframe */ - success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); - } - else { - /* local flags only add on to global flags */ - flag = ks->flag; - if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; - // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; - - /* insert keyframe */ - success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); - } - } - } - else { - int i; - - /* loop over channels available in keyingset */ - for (i=0; i < ks->chan_num; i++) { - short flag, adrcode; - - /* get adrcode - * - certain adrcodes (for MTEX channels need special offsets) // BAD CRUFT!!! - */ - adrcode= ks->adrcodes[i]; - if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) { - switch (adrcode) { - case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z: - case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z: - case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR: - case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP: - adrcode += cks->map; - break; - } - } - - /* insert mode or delete mode */ - if (mode == COMMONKEY_MODE_DELETE) { - /* local flags only add on to global flags */ - flag = 0; - - /* delete keyframe */ - success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); - } - else { - /* local flags only add on to global flags */ - flag = ks->flag; - if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; - // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; - - /* insert keyframe */ - success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); - } - } - } - - /* special handling for some key-sources */ - if (success) { - /* set pose recalc-paths flag */ - if (cks->pchan) { - Object *ob= (Object *)cks->id; - bPoseChannel *pchan= cks->pchan; - - /* set flag to trigger path recalc */ - if (pchan->path) - ob->pose->flag |= POSE_RECALCPATHS; - - /* clear unkeyed flag (it doesn't matter if it's set or not) */ - if (pchan->bone) - pchan->bone->flag &= ~BONE_UNKEYED; - } - } - } - - /* apply post-keying flushes for this data sources */ - commonkey_context_finish(&dsources); - ksc->lastused= ks; - - /* free temp data */ - BLI_freelistN(&dsources); - - /* undo pushes */ - if (mode == COMMONKEY_MODE_DELETE) - BLI_snprintf(buf, 64, "Delete %s Key", ks->name); - else - BLI_snprintf(buf, 64, "Insert %s Key", ks->name); - BIF_undo_push(buf); - - /* queue updates for contexts */ - commonkey_context_refresh(); -} - -/* ---- */ - -/* used to insert keyframes from any view */ -void common_insertkey (void) -{ - common_modifykey(COMMONKEY_MODE_INSERT); -} - -/* used to insert keyframes from any view */ -void common_deletekey (void) -{ - common_modifykey(COMMONKEY_MODE_DELETE); -} - -/* ************************************************** */ diff --git a/source/blender/src/keyval.c b/source/blender/src/keyval.c index 5a2ba531821..dab4b4ae839 100644 --- a/source/blender/src/keyval.c +++ b/source/blender/src/keyval.c @@ -27,11 +27,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "stdio.h" -#include "ctype.h" -#include "string.h" - -#include "BKE_global.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BIF_keyval.h" @@ -354,193 +349,3 @@ char *key_event_to_string(unsigned short event) return ""; } - -/* - * Decodes key combination strings [qual1+[qual2+[...]]]keyname - * The '+'s may be replaced by '-' or ' ' characters to support different - * formats. No additional whitespace is allowed. The keyname may be an internal - * name, like "RETKEY", or a more common name, like "Return". Decoding is case- - * insensitive. - * - * Example strings: "Ctrl+L", "ALT-ESC", "Shift A" - * - * Returns 1 if successful. - */ -int decode_key_string(char *str, unsigned short *key, unsigned short *qual) -{ - int i, prev, len, invalid=0; - - len= strlen(str); - *key= *qual= 0; - - /* Convert to upper case */ - for (i=0; i='A' && str[prev]<='Z') { - *key= str[prev]-'A'+AKEY; - } else if (str[prev]>='0' && str[prev]<='9') { - *key= str[prev]-'0'+ZEROKEY; - } else { - invalid= 1; - } - - } else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) { - *key= ZEROKEY; - } else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) { - *key= ONEKEY; - } else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) { - *key= TWOKEY; - } else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) { - *key= THREEKEY; - } else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) { - *key= FOURKEY; - } else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) { - *key= FIVEKEY; - } else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) { - *key= SIXKEY; - } else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) { - *key= SEVENKEY; - } else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) { - *key= EIGHTKEY; - } else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) { - *key= NINEKEY; - - } else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) { - *key= ESCKEY; - } else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) { - *key= TABKEY; - } else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) { - *key= RETKEY; - } else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) { - *key= SPACEKEY; - } else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) { - *key= LINEFEEDKEY; - } else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) { - *key= BACKSPACEKEY; - } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { - *key= DELKEY; - - } else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) { - *key= SEMICOLONKEY; - } else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) { - *key= PERIODKEY; - } else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) { - *key= COMMAKEY; - } else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) { - *key= QUOTEKEY; - } else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) { - *key= ACCENTGRAVEKEY; - } else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) { - *key= MINUSKEY; - } else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) { - *key= SLASHKEY; - } else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) { - *key= BACKSLASHKEY; - } else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) { - *key= EQUALKEY; - } else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) { - *key= LEFTBRACKETKEY; - } else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) { - *key= RIGHTBRACKETKEY; - } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { - *key= DELKEY; - - } else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) { - *key= LEFTARROWKEY; - } else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) { - *key= DOWNARROWKEY; - } else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) { - *key= RIGHTARROWKEY; - } else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) { - *key= UPARROWKEY; - - } else if (!strncmp(str+prev, "PAD", 3)) { - - if (len-prev<=4) { - - if (str[prev]>='0' && str[prev]<='9') { - *key= str[prev]-'0'+ZEROKEY; - } else { - invalid= 1; - } - - } else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) { - *key= PADPERIOD; - } else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) { - *key= PADSLASHKEY; - } else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) { - *key= PADASTERKEY; - } else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) { - *key= PADMINUS; - } else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) { - *key= PADENTER; - } else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) { - *key= PADPLUSKEY; - } else { - invalid= 1; - } - - } else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) { - *key= F1KEY; - } else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) { - *key= F2KEY; - } else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) { - *key= F3KEY; - } else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) { - *key= F4KEY; - } else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) { - *key= F5KEY; - } else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) { - *key= F6KEY; - } else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) { - *key= F7KEY; - } else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) { - *key= F8KEY; - } else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) { - *key= F9KEY; - } else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) { - *key= F10KEY; - } else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) { - *key= F11KEY; - } else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) { - *key= F12KEY; - - } else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) { - *key= PAUSEKEY; - } else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) { - *key= INSERTKEY; - } else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) { - *key= HOMEKEY; - } else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) { - *key= PAGEUPKEY; - } else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) { - *key= PAGEDOWNKEY; - } else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) { - *key= ENDKEY; - - } else { - invalid= 1; - } - - if (!invalid && *key) { - return 1; - } - - return 0; -} diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index 96349e8fb98..2de6367c9ad 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -204,7 +204,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int v3= sys->verts[i3]; /* instead of *0.5 we divided by the number of faces of the edge, it still - needs to be verified that this is indeed the correct thing to do! */ + needs to be varified that this is indeed the correct thing to do! */ t1= cotan_weight(v1, v2, v3)/laplacian_edge_count(sys->edgehash, i2, i3); t2= cotan_weight(v2, v3, v1)/laplacian_edge_count(sys->edgehash, i3, i1); t3= cotan_weight(v3, v1, v2)/laplacian_edge_count(sys->edgehash, i1, i2); @@ -229,7 +229,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int } } -LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) +LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) { LaplacianSystem *sys; @@ -248,8 +248,6 @@ LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int /* create opennl context */ nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, totvert); - if(lsq) - nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); sys->context= nlGetCurrent(); @@ -633,7 +631,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, } /* create laplacian */ - sys = laplacian_system_construct_begin(me->totvert, totface, 1); + sys = laplacian_system_construct_begin(me->totvert, totface); sys->heat.mesh= me; sys->heat.verts= verts; @@ -935,7 +933,7 @@ void rigid_deform_begin(EditMesh *em) } /* create laplacian */ - sys = laplacian_system_construct_begin(totvert, totface, 0); + sys = laplacian_system_construct_begin(totvert, totface); sys->rigid.mesh= em; sys->rigid.R = MEM_callocN(sizeof(float)*3*3*totvert, "RigidDeformR"); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index eed7737c26d..99833625baa 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -84,6 +84,7 @@ void sort_faces(void); #include "BIF_toolbox.h" #include "BIF_editconstraint.h" +#include "BDR_drawmesh.h" #include "BDR_editobject.h" #include "BDR_editface.h" #include "BDR_sculptmode.h" @@ -106,8 +107,6 @@ void sort_faces(void); #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "GPU_draw.h" - #include "BLO_sys_types.h" // for intptr_t support /* from rendercode.c */ @@ -1131,7 +1130,7 @@ void objects_bake_render(short event, char **error_msg) if(ima->ok==IMA_OK_LOADED) { ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { - GPU_free_image(ima); + free_realtime_image(ima); imb_freemipmapImBuf(ibuf); } } diff --git a/source/blender/src/mywindow.c b/source/blender/src/mywindow.c index 6166ab18766..cb8d233c341 100644 --- a/source/blender/src/mywindow.c +++ b/source/blender/src/mywindow.c @@ -604,6 +604,18 @@ int framebuffer_to_index(unsigned int col) /* ********** END MY WINDOW ************** */ +#ifdef WIN32 +static int is_a_really_crappy_nvidia_card(void) { + static int well_is_it= -1; + + /* Do you understand the implication? Do you? */ + if (well_is_it==-1) + well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); + + return well_is_it; +} +#endif + void myswapbuffers(void) { ScrArea *sa; diff --git a/source/blender/src/playanim.c b/source/blender/src/playanim.c index 8421101f66c..7a61368b4cd 100644 --- a/source/blender/src/playanim.c +++ b/source/blender/src/playanim.c @@ -45,6 +45,15 @@ #endif #include "MEM_guardedalloc.h" +#ifdef WITH_QUICKTIME +#ifdef _WIN32 +#include +#include +#elif defined(__APPLE__) +#include +#endif /* __APPLE__ */ +#endif /* WITH_QUICKTIME */ + #include "PIL_time.h" #include @@ -68,15 +77,6 @@ #include "BMF_Api.h" -#ifdef WITH_QUICKTIME -#ifdef _WIN32 -#include -#include -#elif defined(__APPLE__) -#include -#endif /* __APPLE__ */ -#endif /* WITH_QUICKTIME */ - #include "playanim_ext.h" #include "mydevice.h" #include "blendef.h" @@ -346,7 +346,6 @@ void playanim(int argc, char **argv) int start_x= 0, start_y= 0; int sfra= -1; int efra= -1; - int totblock; while (argc > 1) { if (argv[1][0] == '-'){ @@ -824,7 +823,6 @@ void playanim(int argc, char **argv) free_blender(); window_destroy(g_window); - totblock= MEM_get_memory_blocks_in_use(); if(totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_printmemlist(); diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index ff54ad31e22..6aeef7c75c2 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -61,7 +61,7 @@ #include "BKE_global.h" #include "BKE_utildefines.h" -#include "BIF_keyframing.h" +//#include "BIF_keyframing.h" #include "BSE_editipo.h" #include "BDR_drawaction.h" diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 19fb8dc2ecd..28b8729a247 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -69,7 +69,6 @@ #include "BIF_gl.h" #include "BIF_graphics.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_space.h" #include "BIF_toolbox.h" @@ -407,7 +406,6 @@ void pose_recalculate_paths(Object *ob) waitcursor(0); CFRA= cfra; - ob->pose->flag &= ~POSE_RECALCPATHS; allqueue(REDRAWVIEW3D, 0); /* recalc tags are still there */ allqueue(REDRAWBUTSEDIT, 0); } diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index 1730bb890bc..0be63197dd1 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -97,8 +97,6 @@ #include "RE_pipeline.h" #include "BLO_readfile.h" -#include "GPU_material.h" - #include "blendef.h" /* CLAMP */ #include "interface.h" /* ui_graphics_to_window(), SOLVE! (ton) */ #include "mydevice.h" @@ -223,36 +221,6 @@ void BIF_preview_changed(short id_code) } } } - - if(ELEM4(id_code, ID_MA, ID_TE, ID_LA, ID_WO)) { - Object *ob; - Material *ma; - - if(id_code == ID_WO) { - for(ma=G.main->mat.first; ma; ma=ma->id.next) { - if(ma->gpumaterial.first) { - GPU_material_free(ma); - allqueue(REDRAWVIEW3D, 0); - } - } - } - else if(id_code == ID_LA) { - for(ob=G.main->object.first; ob; ob=ob->id.next) { - if(ob->gpulamp.first) { - GPU_lamp_free(ob); - allqueue(REDRAWVIEW3D, 0); - } - } - } else if(OBACT) { - Object *ob = OBACT; - - ma= give_current_material(ob, ob->actcol); - if(ma && ma->gpumaterial.first) { - GPU_material_free(ma); - allqueue(REDRAWVIEW3D, 0); - } - } - } } /* *************************** Preview for buttons *********************** */ diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 33484500328..88f5f6efe15 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -50,6 +50,8 @@ #endif +#include "BLO_sys_types.h" // for intptr_t support + #include #include "BLI_blenlib.h" @@ -100,8 +102,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "GPU_draw.h" - #include "blendef.h" #include "mydevice.h" #include "winlay.h" @@ -676,7 +676,7 @@ static void open_renderwin(int winpos[2], int winsize[2], int imagesize[2]) /* mywindow has to know about it too */ mywindow_build_and_set_renderwin(winpos[0], winpos[1], winsize[0], winsize[1]+RW_HEADERY); /* and we should be able to draw 3d in it */ - GPU_state_init(); + init_gl_stuff(); renderwin_draw(render_win, 1); renderwin_draw(render_win, 1); @@ -903,13 +903,10 @@ static void renderwin_progress_display_cb(RenderResult *rr, volatile rcti *rect) void make_renderinfo_string(RenderStats *rs, char *str) { extern char info_time_str[32]; // header_info.c - uintptr_t mem_in_use, mmap_in_use; + extern uintptr_t mem_in_use, mmap_in_use; float megs_used_memory, mmap_used_memory; char *spos= str; - mem_in_use= MEM_get_memory_in_use(); - mmap_in_use= MEM_get_mapped_memory_in_use(); - megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0); mmap_used_memory= (mmap_in_use)/(1024.0*1024.0); @@ -1307,10 +1304,10 @@ void do_ogl_view3d_render(Render *re, View3D *v3d, int winx, int winy) if(v3d->persp==V3D_CAMOB && v3d->camera) { /* in camera view, use actual render winmat */ RE_GetCameraWindow(re, v3d->camera, CFRA, winmat); - drawview3d_render(v3d, NULL, winx, winy, winmat, 0); + drawview3d_render(v3d, winx, winy, winmat); } else - drawview3d_render(v3d, NULL, winx, winy, NULL, 0); + drawview3d_render(v3d, winx, winy, NULL); } /* set up display, render the current area view in an image */ @@ -1339,7 +1336,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) if(render_win) render_win->flags &= ~RW_FLAGS_ESCAPE; - GPU_state_init(); + init_gl_stuff(); waitcursor(1); diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index 1bef10d0415..acd14aae7a5 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -753,8 +753,6 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Transition Strip %%x%d|", TH_SEQ_TRANSITION); str += sprintf(str, "Meta Strip %%x%d|", TH_SEQ_META); str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); - str += sprintf(str, "Keyframe %%x%d|", TH_VERTEX_SELECT); - str += sprintf(str, "Draw Action %%x%d|", TH_BONE_POSE); break; case SPACE_SOUND: str += sprintf(str, "Grid %%x%d|", TH_GRID); diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 31d5ae4610d..24f4100efdb 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -82,6 +82,7 @@ #include "BIF_space.h" #include "BIF_toolbox.h" +#include "BDR_drawobject.h" #include "BDR_sculptmode.h" #include "BSE_drawview.h" @@ -97,8 +98,6 @@ #include "RE_render_ext.h" #include "RE_shader_ext.h" /*for multitex_ext*/ -#include "GPU_draw.h" - #include #include #include @@ -1515,7 +1514,7 @@ void sculptmode_draw_mesh(int only_damaged) mymultmatrix(OBACT->obmat); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); - GPU_set_object_materials(G.scene, OBACT, 0, NULL); + init_gl_materials(OBACT, 0); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); @@ -1533,7 +1532,7 @@ void sculptmode_draw_mesh(int only_damaged) int new_matnr= f->mat_nr + 1; if(new_matnr != matnr) - drawCurrentMat= GPU_enable_material(matnr = new_matnr, NULL); + drawCurrentMat= set_gl_material(matnr = new_matnr); /* If only_damaged!=0, only draw faces that are partially inside the area(s) modified by the brush */ diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 5be11a724f1..7e2ffc3ba63 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2949,16 +2949,13 @@ void do_render_seq(RenderResult *rr, int cfra) (schlaile) */ { - uintptr_t mem_in_use; - uintptr_t mmap_in_use; - uintptr_t max; - - mem_in_use= MEM_get_memory_in_use(); - mmap_in_use= MEM_get_mapped_memory_in_use(); - max = MEM_CacheLimiter_get_maximum(); + extern int mem_in_use; + extern int mmap_in_use; + int max = MEM_CacheLimiter_get_maximum(); if (max != 0 && mem_in_use + mmap_in_use > max) { - fprintf(stderr, "Memory in use > maximum memory\n"); + fprintf(stderr, "mem_in_use = %d, max = %d\n", + mem_in_use + mmap_in_use, max); fprintf(stderr, "Cleaning up, please wait...\n" "If this happens very often,\n" "consider " diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 9120fc3de76..8787cf9efc4 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -182,9 +182,6 @@ #include "SYS_System.h" /* for the user def menu ... should move elsewhere. */ -#include "GPU_extensions.h" -#include "GPU_draw.h" - #include "BLO_sys_types.h" // for intptr_t support /* maybe we need this defined somewhere else */ @@ -389,7 +386,7 @@ void space_set_commmandline_options(void) { SYS_WriteCommandLineInt(syshandle, "noaudio", a); a= (U.gameflags & USER_DISABLE_MIPMAP); - GPU_set_mipmap(!a); + set_mipmap(!a); SYS_WriteCommandLineInt(syshandle, "nomipmap", a); /* File specific settings: */ @@ -418,9 +415,7 @@ void space_set_commmandline_options(void) { a=(G.fileflags & G_FILE_GAME_MAT); SYS_WriteCommandLineInt(syshandle, "blender_material", a); - a=(G.fileflags & G_FILE_GAME_MAT_GLSL); - SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", a); - a=(G.fileflags & G_FILE_DISPLAY_LISTS); + a=(G.fileflags & G_FILE_DIAPLAY_LISTS); SYS_WriteCommandLineInt(syshandle, "displaylists", a); @@ -437,10 +432,11 @@ static void SaveState(void) { glPushAttrib(GL_ALL_ATTRIB_BITS); - GPU_state_init(); + init_realtime_GL(); + init_gl_stuff(); if(G.f & G_TEXTUREPAINT) - GPU_paint_set_mipmap(1); + texpaint_enable_mipmap(); waitcursor(1); } @@ -448,7 +444,7 @@ static void SaveState(void) static void RestoreState(void) { if(G.f & G_TEXTUREPAINT) - GPU_paint_set_mipmap(0); + texpaint_disable_mipmap(); curarea->win_swap = 0; curarea->head_swap=0; @@ -1028,9 +1024,9 @@ void BIF_undo(void) } else { if(G.f & G_TEXTUREPAINT) - undo_imagepaint_step(1); + imagepaint_undo(); else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL)) - undo_imagepaint_step(1); + imagepaint_undo(); else if(G.f & G_PARTICLEEDIT) PE_undo(); else { @@ -1052,9 +1048,9 @@ void BIF_redo(void) } else { if(G.f & G_TEXTUREPAINT) - undo_imagepaint_step(-1); + imagepaint_undo(); else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL)) - undo_imagepaint_step(-1); + imagepaint_undo(); else if(G.f & G_PARTICLEEDIT) PE_redo(); else { @@ -1910,8 +1906,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else copy_attr_menu(); } - else if(G.qual==(LR_ALTKEY|LR_SHIFTKEY)) - gpencil_convert_menu(); /* gpencil.c */ else if(G.qual==LR_ALTKEY) { if(ob && (ob->flag & OB_POSEMODE)) pose_clear_constraints(); /* poseobject.c */ @@ -1970,7 +1964,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.vd->drawtype= pupval; doredraw= 1; } - } + } break; case EKEY: @@ -2062,7 +2056,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT)){ G.f ^= G_FACESELECT; allqueue(REDRAWVIEW3D, 1); - allqueue(REDRAWBUTSEDIT, 1); } else if(G.f & G_PARTICLEEDIT) { PE_radialcontrol_start(RADIALCONTROL_SIZE); @@ -2648,9 +2641,10 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.f & G_VERTEXPAINT) BIF_undo(); else if(G.f & G_TEXTUREPAINT) - undo_imagepaint_step(1); - else + imagepaint_undo(); + else { single_user(); + } } break; @@ -3103,9 +3097,6 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if (G.qual==LR_CTRLKEY) { borderselect_markers(); } - else if (G.qual==LR_SHIFTKEY) { - do_ipo_buttons(B_IPOBORDER); - } break; case CKEY: if (G.qual == LR_SHIFTKEY) @@ -3266,7 +3257,7 @@ void initipo(ScrArea *sa) /* ******************** SPACE: INFO ********************** */ void space_mipmap_button_function(int event) { - GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); allqueue(REDRAWVIEW3D, 0); } @@ -3742,11 +3733,6 @@ void drawinfospace(ScrArea *sa, void *spacedata) "Snap objects and sub-objects to grid units when scaling"); uiBlockEndAlign(block); - uiDefButBitI(block, TOG, USER_ORBIT_ZBUF, B_DRAWINFO, "Auto Depth", - (xpos+edgsp+mpref+spref+(2*midsp)),y2,spref,buth, - &(U.uiflag), 0, 0, 0, 0, - "Use the depth under the mouse to improve view pan/rotate/zoom functionality"); - uiDefButBitI(block, TOG, USER_LOCKAROUND, B_DRAWINFO, "Global Pivot", (xpos+edgsp+mpref+spref+(2*midsp)),y1,spref,buth, &(U.uiflag), 0, 0, 0, 0, @@ -3961,23 +3947,20 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefBut(block, LABEL,0,"Transform:", - (xpos+(2*edgsp)+mpref),y6label, mpref,buth, + (xpos+(2*edgsp)+mpref),y5label, mpref,buth, 0, 0, 0, 0, 0, ""); uiDefButBitI(block, TOG, USER_DRAGIMMEDIATE, B_DRAWINFO, "Drag Immediately", - (xpos+edgsp+mpref+midsp),y5,mpref,buth, + (xpos+edgsp+mpref+midsp),y4,mpref,buth, &(U.flag), 0, 0, 0, 0, "Moving things with a mouse drag doesn't require a click to confirm (Best for tablet users)"); uiBlockEndAlign(block); uiDefBut(block, LABEL,0,"Undo:", - (xpos+(2*edgsp)+mpref),y4label, mpref,buth, + (xpos+(2*edgsp)+mpref),y3label, mpref,buth, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); uiDefButS(block, NUMSLI, B_DRAWINFO, "Steps: ", - (xpos+edgsp+mpref+midsp),y3,mpref,buth, - &(U.undosteps), 0, 64, 0, 0, "Number of undo steps available (smaller values conserve memory)"); - uiDefButS(block, NUM, B_DRAWINFO, "Memory Limit: ", (xpos+edgsp+mpref+midsp),y2,mpref,buth, - &(U.undomemory), 0, 32767, -1, 0, "Maximum memory usage in megabytes (0 means unlimited)"); + &(U.undosteps), 0, 64, 0, 0, "Number of undo steps available (smaller values conserve memory)"); uiDefButBitI(block, TOG, USER_GLOBALUNDO, B_DRAWINFO, "Global Undo", (xpos+edgsp+mpref+midsp),y1,mpref,buth, @@ -4312,7 +4295,6 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefButI(block, NUM, 0, "Collect Rate ", (xpos+edgsp+(5*mpref)+(5*midsp)), y2, mpref, buth, &U.texcollectrate, 1.0, 3600.0, 30, 2, "Number of seconds between each run of the GL texture garbage collector."); - uiBlockEndAlign(block); /* *** */ uiDefBut(block, LABEL,0,"Color range for weight paint", @@ -4549,7 +4531,7 @@ static void winqreadinfospace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) U.light[0].flag= 1; - GPU_default_lights(); + default_gl_light(); addqueue(sa->win, REDRAW, 1); allqueue(REDRAWVIEW3D, 0); } @@ -5189,8 +5171,8 @@ static void init_seqspace(ScrArea *sa) sseq->v2d.max[0]= MAXFRAMEF; sseq->v2d.max[1]= MAXSEQ; - sseq->v2d.minzoom= 0.01f; - sseq->v2d.maxzoom= 100.0; + sseq->v2d.minzoom= 0.1f; + sseq->v2d.maxzoom= 10.0; sseq->v2d.scroll= L_SCROLL+B_SCROLL; sseq->v2d.keepaspect= 0; @@ -5345,15 +5327,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val==0) return; if(uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; - - /* grease-pencil drawing before draw-tool */ - if (event == LEFTMOUSE) { - if (gpencil_do_paint(sa, L_MOUSE)) return; - } - else if (event == RIGHTMOUSE) { - if (gpencil_do_paint(sa, R_MOUSE)) return; - } - + if (sima->image && (sima->flag & SI_DRAWTOOL)) { switch(event) { case CKEY: @@ -5376,7 +5350,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) event = LEFTMOUSE; } } - + /* Draw tool is inactive, editmode is enabled and the image is not a render or composite */ if (EM_texFaceCheck() && (G.sima->image==0 || (G.sima->image->type != IMA_TYPE_R_RESULT && G.sima->image->type != IMA_TYPE_COMPOSITE))) { switch(event) { @@ -6013,7 +5987,7 @@ static void init_oopsspace(ScrArea *sa) soops= MEM_callocN(sizeof(SpaceOops), "initoopsspace"); BLI_addhead(&sa->spacedata, soops); - soops->visiflag= OOPS_OB|OOPS_MA|OOPS_ME|OOPS_TE|OOPS_CU|OOPS_IP; + soops->visiflag= OOPS_OB+OOPS_MA+OOPS_ME+OOPS_TE+OOPS_CU+OOPS_IP; /* new oops is default an outliner */ soops->type= SO_OUTLINER; @@ -6084,10 +6058,6 @@ static void init_textspace(ScrArea *sa) st->lheight= 12; st->showlinenrs= 0; st->tabnumber = 4; - st->showsyntax= 0; - st->doplugins= 0; - st->overwrite= 0; - st->wordwrap= 0; st->currtab_set = 0; st->top= 0; @@ -6357,8 +6327,6 @@ void freespacelist(ScrArea *sa) SpaceImage *sima= (SpaceImage *)sl; if(sima->cumap) curvemapping_free(sima->cumap); - if(sima->gpd) - free_gpencil_data(sima->gpd); } else if(sl->spacetype==SPACE_NODE) { SpaceNode *snode= (SpaceNode *)sl; @@ -6426,10 +6394,6 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) SpaceSeq *sseq= (SpaceSeq *)sl; sseq->gpd= gpencil_data_duplicate(sseq->gpd); } - else if(sl->spacetype==SPACE_IMAGE) { - SpaceImage *sima= (SpaceImage *)sl; - sima->gpd= gpencil_data_duplicate(sima->gpd); - } sl= sl->next; } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 41ee557c9c2..5f80f14d069 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -75,7 +75,6 @@ #include "BIF_imasel.h" #include "BIF_editparticle.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" #include "BIF_renderwin.h" @@ -105,8 +104,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "GPU_draw.h" - #include "mydevice.h" #include "transform.h" @@ -793,10 +790,6 @@ int blenderqread(unsigned short event, short val) ob= OBACT; if(G.f & G_SCULPTMODE) return 1; - else if(G.qual==(LR_CTRLKEY|LR_ALTKEY)) { - common_deletekey(); - return 0; - } else if(G.qual==0) { common_insertkey(); return 0; @@ -971,7 +964,7 @@ int blenderqread(unsigned short event, short val) /* Reset lights * This isn't done when reading userdef, do it now * */ - GPU_default_lights(); + default_gl_light(); } return 0; } diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index f38affde418..c8a20cdc951 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -93,7 +93,6 @@ #include "BIF_graphics.h" #include "BIF_imasel.h" #include "BIF_interface.h" -#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" #include "BIF_renderwin.h" @@ -2283,7 +2282,7 @@ void toolbox_generic( TBitem *generic_menu ) uiBlock *block; uiBut *but; TBitem *menu; - int dx=96, first=1, len; + int dx=96; short event, mval[2]; intptr_t ypos = -5; @@ -2304,17 +2303,11 @@ void toolbox_generic( TBitem *generic_menu ) /* Add the menu */ for (menu = generic_menu; menu->icon != -1; menu++) { - if (first && (len=strlen(menu->name)) > 2 && menu->name[len-2]=='%' && menu->name[len-1]=='t') { - menu->name[len-2] = '\0'; - uiSetCurFont(block, UI_HELVB); - uiDefIconTextBut(block, LABEL, 0, ICON_BLANK1, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, NULL, 0.0, 0.0, 0, 0, ""); - uiSetCurFont(block, UI_HELV); - ypos-=20; - } else if(strcmp(menu->name, "SEPR")==0) { + if(strcmp(menu->name, "SEPR")==0) { uiDefBut(block, SEPR, 0, "", mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 6, NULL, 0.0, 0.0, 0, 0, ""); ypos-=6; } else { - if (menu->poin) { + if (menu->poin) { but=uiDefIconTextBlockBut(block, tb_makemenu, menu->poin, ICON_RIGHTARROW_THIN, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, ""); uiButSetFlag(but, UI_MAKE_RIGHT); @@ -2325,7 +2318,6 @@ void toolbox_generic( TBitem *generic_menu ) } ypos-=20; } - first= 0; } uiBlockSetButmFunc(block, menu->poin, NULL); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 210a81927c8..efb86b59ed1 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -108,7 +108,6 @@ #include "BIF_editsima.h" #include "BIF_editparticle.h" #include "BIF_gl.h" -#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" @@ -3563,25 +3562,22 @@ short autokeyframe_cfra_can_key(Object *ob) */ void autokeyframe_ob_cb_func(Object *ob, int tmode) { - ID *id= (ID *)(ob); IpoCurve *icu; if (autokeyframe_cfra_can_key(ob)) { char *actname = NULL; - short flag = 0; if (ob->ipoflag & OB_ACTION_OB) actname= "Object"; - - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - flag |= INSERTKEY_NEEDED; - if (IS_AUTOKEY_FLAG(AUTOMATKEY)) - flag |= INSERTKEY_MATRIX; if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { - /* only key on available channels */ if ((ob->ipo) || (ob->action)) { - if (ob->action && actname) { + ID *id= (ID *)(ob); + + if (ob->ipo) { + icu= ob->ipo->curve.first; + } + else { bActionChannel *achan; achan= get_action_channel(ob->action, actname); @@ -3590,16 +3586,19 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) else icu= NULL; } - else - icu= ob->ipo->curve.first; - for (; icu; icu= icu->next) { + while (icu) { icu->flag &= ~IPO_SELECT; - insertkey(id, ID_OB, actname, NULL, icu->adrcode, flag); + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); + else + insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); + icu= icu->next; } } } else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) { + ID *id= (ID *)(ob); short doLoc=0, doRot=0, doScale=0; /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ @@ -3630,33 +3629,35 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) } if (doLoc) { - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); + insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_X); + insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Y); + insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Z); } if (doRot) { - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); + insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_X); + insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Y); + insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Z); } if (doScale) { - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); + insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_X); + insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Y); + insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Z); } } else { - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); + ID *id= (ID *)(ob); - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); + + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); } remake_object_ipos(ob); @@ -3682,15 +3683,8 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) act= ob->action; if (autokeyframe_cfra_can_key(ob)) { - short flag= 0; - if (act == NULL) act= ob->action= add_empty_action("Action"); - - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - flag |= INSERTKEY_NEEDED; - if (IS_AUTOKEY_FLAG(AUTOMATKEY)) - flag |= INSERTKEY_MATRIX; for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { if (pchan->bone->flag & BONE_TRANSFORM) { @@ -3701,10 +3695,17 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { bActionChannel *achan; - achan= get_action_channel(act, pchan->name); - if (achan && achan->ipo) { - for (icu= achan->ipo->curve.first; icu; icu= icu->next) - insertkey(id, ID_PO, pchan->name, NULL, icu->adrcode, flag); + for (achan = act->chanbase.first; achan; achan=achan->next) { + if ((achan->ipo) && !strcmp(achan->name, pchan->name)) { + for (icu = achan->ipo->curve.first; icu; icu=icu->next) { + /* only insert keyframe if needed? */ + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); + else + insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0); + } + break; + } } } /* only insert keyframe if needed? */ @@ -3734,36 +3735,36 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } if (doLoc) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_X); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Y); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Z); } if (doRot) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_W); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_X); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); } if (doScale) { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_X); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); + insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); } } /* insert keyframe in any channel that's appropriate */ else { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); } } } @@ -3912,10 +3913,13 @@ void special_aftertrans_update(TransInfo *t) if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 && (cancelled == 0) ) { - /* NOTE: no need to do NLA scaling stuff here, as when there is NLA scaling, - * the transformed handles will get moved wrong (seem to match wrong repeat cycle) - */ - posttrans_ipo_clean(G.sipo->ipo); + if (NLA_IPO_SCALED) { + actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 1); + posttrans_ipo_clean(G.sipo->ipo); + actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 1); + } + else + posttrans_ipo_clean(G.sipo->ipo); } } diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index a1440b8cbce..656fca3cad8 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -583,6 +583,39 @@ void recalcData(TransInfo *t) reshadeall_displist(); } +void initTransModeFlags(TransInfo *t, int mode) +{ + t->mode = mode; + t->num.flag = 0; + + /* REMOVING RESTRICTIONS FLAGS */ + t->flag &= ~T_ALL_RESTRICTIONS; + + switch (mode) { + case TFM_RESIZE: + t->flag |= T_NULL_ONE; + t->num.flag |= NUM_NULL_ONE; + t->num.flag |= NUM_AFFECT_ALL; + if (!G.obedit) { + t->flag |= T_NO_ZERO; + t->num.flag |= NUM_NO_ZERO; + } + break; + case TFM_TOSPHERE: + t->num.flag |= NUM_NULL_ONE; + t->num.flag |= NUM_NO_NEGATIVE; + t->flag |= T_NO_CONSTRAINT; + break; + case TFM_SHEAR: + case TFM_CREASE: + case TFM_BONE_ENVELOPE: + case TFM_CURVE_SHRINKFATTEN: + case TFM_BONE_ROLL: + t->flag |= T_NO_CONSTRAINT; + break; + } +} + void drawLine(float *center, float *dir, char axis, short options) { extern void make_axis_color(char *col, char *col2, char axis); // drawview.c @@ -641,10 +674,19 @@ void initTrans (TransInfo *t) t->transform = NULL; t->handleEvent = NULL; - t->total = 0; + t->total = + t->num.idx = + t->num.idx_max = + t->num.ctrl[0] = + t->num.ctrl[1] = + t->num.ctrl[2] = 0; t->val = 0.0f; + t->num.val[0] = + t->num.val[1] = + t->num.val[2] = 0.0f; + t->vec[0] = t->vec[1] = t->vec[2] = 0.0f; @@ -666,8 +708,7 @@ void initTrans (TransInfo *t) t->around = V3D_CENTER; setTransformViewMatrices(t); - initNumInput(&t->num); - initNDofInput(&t->ndof); + initNDofInput(&(t->ndof)); } /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */ diff --git a/source/blender/src/transform_numinput.c b/source/blender/src/transform_numinput.c index 89a76c097e0..9b811595a9a 100644 --- a/source/blender/src/transform_numinput.c +++ b/source/blender/src/transform_numinput.c @@ -41,20 +41,6 @@ /* ************************** NUMINPUT **************************** */ -void initNumInput(NumInput *n) -{ - n->flag = - n->idx = - n->idx_max = - n->ctrl[0] = - n->ctrl[1] = - n->ctrl[2] = 0; - - n->val[0] = - n->val[1] = - n->val[2] = 0.0f; -} - void outputNumInput(NumInput *n, char *str) { char cur; diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index fc9dfbb902e..9c7a2f67b89 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -352,7 +352,7 @@ char * BIF_menustringTransformOrientation(char *title) { char *str_menu, *p; - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); + str_menu = MEM_callocN(strlen(menu) + strlen(title) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); p = str_menu; p += sprintf(str_menu, "%s", title); diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index aa49065320b..15c2664a9d8 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -34,6 +34,8 @@ #include #include +#include "GL/glew.h" + #ifdef WIN32 #include /* need to include windows.h so _WIN32_IE is defined */ #ifndef _WIN32_IE @@ -67,7 +69,6 @@ #include "DNA_sound_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" -#include "DNA_text_types.h" #include "BKE_blender.h" #include "BKE_curve.h" @@ -80,7 +81,6 @@ #include "BKE_mball.h" #include "BKE_node.h" #include "BKE_packedFile.h" -#include "BKE_suggestions.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_pointcache.h" @@ -147,9 +147,6 @@ #include "PIL_time.h" -#include "GPU_extensions.h" -#include "GPU_draw.h" - /***/ /* define for setting colors in theme below */ @@ -483,21 +480,9 @@ static void init_userdef_file(void) if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile < 1)) { bTheme *btheme; for(btheme= U.themes.first; btheme; btheme= btheme->next) { - char *col; - - /* IPO Editor: Handles/Vertices */ - col = btheme->tipo.vertex; - SETCOL(btheme->tipo.handle_vertex, col[0], col[1], col[2], 255); - col = btheme->tipo.vertex_select; - SETCOL(btheme->tipo.handle_vertex_select, col[0], col[1], col[2], 255); - btheme->tipo.handle_vertex_size= btheme->tipo.vertex_size; - - /* Sequence/Image Editor: colors for GPencil text */ - col = btheme->tv3d.bone_pose; - SETCOL(btheme->tseq.bone_pose, col[0], col[1], col[2], 255); - SETCOL(btheme->tima.bone_pose, col[0], col[1], col[2], 255); - col = btheme->tv3d.vertex_select; - SETCOL(btheme->tseq.vertex_select, col[0], col[1], col[2], 255); + SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255); + SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255); + btheme->tipo.handle_vertex_size= 3; } } @@ -590,9 +575,8 @@ void BIF_read_file(char *name) if (retval!=0) G.relbase_valid = 1; undo_editmode_clear(); - undo_imagepaint_clear(); BKE_reset_undo(); - BKE_write_undo("Original"); /* save current state */ + BKE_write_undo("original"); /* save current state */ refresh_interface_font(); } @@ -664,9 +648,8 @@ int BIF_read_homefile(int from_memory) init_userdef_file(); undo_editmode_clear(); - undo_imagepaint_clear(); BKE_reset_undo(); - BKE_write_undo("Original"); /* save current state */ + BKE_write_undo("original"); /* save current state */ /* if from memory, need to refresh python scripts */ if (from_memory) { @@ -1064,9 +1047,8 @@ void BIF_init(void) BIF_filelist_init_icons(); - GPU_state_init(); - GPU_extensions_init(); - + init_gl_stuff(); /* drawview.c, after homefile */ + glewInit(); readBlog(); BLI_strncpy(G.lib, G.sce, FILE_MAX); } @@ -1079,7 +1061,6 @@ extern ListBase editelems; void exit_usiblender(void) { struct TmpFont *tf; - int totblock; BIF_clear_tempfiles(); @@ -1125,7 +1106,7 @@ void exit_usiblender(void) free_ipocopybuf(); free_actcopybuf(); free_vertexpaint(); - free_texttools(); + free_imagepaint(); /* editnurb can remain to exist outside editmode */ freeNurblist(&editNurb); @@ -1143,7 +1124,6 @@ void exit_usiblender(void) sound_exit_audio(); if(G.listener) MEM_freeN(G.listener); - GPU_extensions_exit(); libtiff_exit(); @@ -1153,7 +1133,6 @@ void exit_usiblender(void) /* undo free stuff */ undo_editmode_clear(); - undo_imagepaint_clear(); BKE_undo_save_quit(); // saves quit.blend if global undo is on BKE_reset_undo(); @@ -1179,7 +1158,6 @@ void exit_usiblender(void) BLI_freelistN(&U.themes); BIF_preview_free_dbase(); - totblock= MEM_get_memory_blocks_in_use(); if(totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_printmemlist(); diff --git a/source/blender/src/verse_image.c b/source/blender/src/verse_image.c index edb3a0a9f2c..fe9e6137091 100644 --- a/source/blender/src/verse_image.c +++ b/source/blender/src/verse_image.c @@ -43,8 +43,6 @@ #include "BIF_verse.h" #include "BIF_space.h" -#include "GPU_draw.h" - /* * unsubscribe from verse bitmap */ @@ -329,7 +327,7 @@ void post_bitmap_tile_set(VBitmapLayer *vblayer, unsigned int xs, unsigned int y rect[channel] = (char)vuint8[i]; } - GPU_free_image(image); + free_realtime_image(image); /* redraw preview of image ... uncommented, because rendering * was computed too often */ diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 4c56e5ce64e..12450bee9de 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -793,82 +793,6 @@ void viewmoveNDOFfly(int mode) BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); } -int view_autodist( float mouse_worldloc[3] ) //, float *autodist ) -{ - View3D *v3d = G.vd; - - /* Zooms in on a border drawn by the user */ - short mval[2]; - rcti rect; - - /* ZBuffer depth vars */ - bglMats mats; - float depth, depth_close= MAXFLOAT; - int had_depth = 0; - double cent[2], p[3]; - int xs, ys; - - getmouseco_areawin(mval); - - persp(PERSP_VIEW); - - rect.xmax = mval[0] + 4; - rect.ymax = mval[1] + 4; - - rect.xmin = mval[0] - 4; - rect.ymin = mval[1] - 4; - - /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - draw_depth(curarea, (void *)v3d, NULL); - - /* force updating */ - if (v3d->depths) { - had_depth = 1; - v3d->depths->damaged = 1; - } - - view3d_update_depths(v3d); - - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1; - if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= v3d->depths->depths[ys*v3d->depths->w+xs]; - if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - if (depth_close==MAXFLOAT) - return 0; - - if (had_depth==0) { - MEM_freeN(v3d->depths->depths); - v3d->depths->depths = NULL; - } - v3d->depths->damaged = 1; - - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; - - if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, mats.viewport, &p[0], &p[1], &p[2])) - return 0; - - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; - return 1; -} - void viewmove(int mode) { static float lastofs[3] = {0,0,0}; @@ -901,11 +825,15 @@ void viewmove(int mode) Mat3MulVecfl(mat, upvec); VecAddf(G.vd->ofs, G.vd->ofs, upvec); } + + /* sometimes this routine is called from headerbuttons */ areawinset(curarea->win); + initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); + QUATCOPY(oldquat, G.vd->viewquat); getmouseco_areawin(mval_area); /* for zoom to mouse loc */ @@ -939,44 +867,9 @@ void viewmove(int mode) VECCOPY(obofs, lastofs); VecMulf(obofs, -1.0f); } - else if (U.uiflag & USER_ORBIT_ZBUF) { - if ((use_sel=view_autodist(obofs))) { - if (G.vd->persp==V3D_PERSP) { - float my_origin[3]; /* original G.vd->ofs */ - float my_pivot[3]; /* view */ - - VECCOPY(my_origin, G.vd->ofs); - VecMulf(my_origin, -1.0f); /* ofs is flipped */ - - /* Set the dist value to be the distance from this 3d point */ - /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */ - - /* remove dist value */ - upvec[0] = upvec[1] = 0; - upvec[2] = G.vd->dist; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecSubf(my_pivot, G.vd->ofs, upvec); - VecMulf(my_pivot, -1.0f); /* ofs is flipped */ - - /* find a new ofs value that is allong the view axis (rather then the mouse location) */ - lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec); - dist0 = G.vd->dist = VecLenf(my_pivot, dvec); - - VecMulf(dvec, -1.0f); - VECCOPY(G.vd->ofs, dvec); - } - VecMulf(obofs, -1.0f); - VECCOPY(ofs, G.vd->ofs); - } else { - ofs[0] = ofs[1] = ofs[2] = 0.0f; - } - } else ofs[0] = ofs[1] = ofs[2] = 0.0f; - - initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); - + reverse= 1.0f; if (G.vd->persmat[2][1] < 0.0f) reverse= -1.0f; @@ -1153,20 +1046,9 @@ void viewmove(int mode) zfac*G.vd->dist < 10.0*G.vd->far) view_zoom_mouseloc(zfac, mval_area); - - if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (G.vd->persp==V3D_PERSP)) { - /* Secret apricot feature, translate the view when in continues mode */ - upvec[0] = upvec[1] = 0; - upvec[2] = (dist0 - G.vd->dist) * G.vd->grid; - G.vd->dist = dist0; - Mat3CpyMat4(mat, G.vd->viewinv); - Mat3MulVecfl(mat, upvec); - VecAddf(G.vd->ofs, G.vd->ofs, upvec); - } else { - /* these limits are in toets.c too */ - if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; - if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; - } + /* these limits are in toets.c too */ + if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; + if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; if(G.vd->persp==V3D_ORTHO || G.vd->persp==V3D_CAMOB) preview3d_event= 0; } @@ -2471,4 +2353,3 @@ void smooth_view_to_camera(View3D *v3d) v3d->persp= V3D_CAMOB; } } - diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp index f42e00daf6d..f8bbdad5f65 100644 --- a/source/blender/yafray/intern/export_File.cpp +++ b/source/blender/yafray/intern/export_File.cpp @@ -881,7 +881,7 @@ void yafrayFileRender_t::writeShader(const string &shader_name, Material* matr, ostr << "\t\t\n"; // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; + const string blendtype[9] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen"}; ostr << "\t\tblendtype] << "\" />\n"; // texture color (for use with MUL and/or no_rgb etc..) diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp index a7d5653892f..77d53c4ed96 100644 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ b/source/blender/yafray/intern/export_Plugin.cpp @@ -782,7 +782,7 @@ void yafrayPluginRender_t::writeShader(const string &shader_name, Material* matr mparams["input"] = yafray::parameter_t(shader_name + temp); // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; + const string blendtype[9] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen"}; mparams["mode"] = yafray::parameter_t(blendtype[(int)mtex->blendtype]); // texture color (for use with MUL and/or no_rgb etc..) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 93cc0e8afb5..d17b94c631d 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -37,10 +37,8 @@ INCLUDE_DIRECTORIES(../../intern/guardedalloc ../blender/render/extern/include ../blender/python ../blender/makesdna - ../blender/gpu ../kernel/gen_messaging ../kernel/gen_system - ../../extern/glew/include ) @@ -191,7 +189,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} src blender_python blender_render blender_radiosity bf_elbeem) +SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} src blender_python blender_render blender_radiosity blender_IK bf_elbeem) IF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(BLENDER_LINK_LIBS ${BLENDER_LINK_LIBS} extern_binreloc) @@ -212,7 +210,6 @@ IF(UNIX) blender_python bf_blenkernel bf_nodes - bf_gpu bf_blenloader bf_blenpluginapi bf_imbuf @@ -226,7 +223,7 @@ IF(UNIX) bf_decimation bf_elbeem bf_yafray - bf_IK + blender_IK bf_memutil bf_guardedalloc blender_CTR diff --git a/source/creator/Makefile b/source/creator/Makefile index 158aee1a647..8a0d20264ea 100644 --- a/source/creator/Makefile +++ b/source/creator/Makefile @@ -49,11 +49,9 @@ CPPFLAGS += -I../blender/renderconverter CPPFLAGS += -I../blender/blenkernel CPPFLAGS += -I../blender/python CPPFLAGS += -I../blender/blenloader -CPPFLAGS += -I../blender/gpu CPPFLAGS += -I../kernel/gen_system CPPFLAGS += -I../kernel/gen_messaging CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -CPPFLAGS += -I$(NAN_GLEW)/include ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -I$(NAN_QUICKTIME)/include -DWITH_QUICKTIME diff --git a/source/creator/SConscript b/source/creator/SConscript index a4c218f89d6..cac9e895a97 100644 --- a/source/creator/SConscript +++ b/source/creator/SConscript @@ -7,7 +7,7 @@ incs = '#/intern/guardedalloc ../blender/blenlib ../blender/blenkernel' incs += ' ../blender/include ../blender/blenloader ../blender/imbuf' incs += ' ../blender/renderconverter ../blender/render/extern/include' incs += ' ../blender/python ../blender/makesdna ../kernel/gen_messaging' -incs += ' ../kernel/gen_system #/extern/glew/include ../blender/gpu' +incs += ' ../kernel/gen_system' incs += ' ' + env['BF_OPENGL_INC'] defs = [] diff --git a/source/creator/creator.c b/source/creator/creator.c index bdd16dc6bed..e17b0f66977 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -70,14 +70,14 @@ #include "BLO_writefile.h" #include "BLO_readfile.h" +#include "BDR_drawmesh.h" + #include "IMB_imbuf.h" // for quicktime_init #include "BPY_extern.h" #include "RE_pipeline.h" -#include "GPU_draw.h" - #include "playanim_ext.h" #include "mydevice.h" #include "nla.h" @@ -600,12 +600,12 @@ int main(int argc, char **argv) /* doMipMap */ if (!strcmp(argv[a],"nomipmap")) { - GPU_set_mipmap(0); //doMipMap = 0; + set_mipmap(0); //doMipMap = 0; } /* linearMipMap */ if (!strcmp(argv[a],"linearmipmap")) { - GPU_set_linear_mipmap(1); //linearMipMap = 1; + set_linear_mipmap(1); //linearMipMap = 1; } @@ -772,10 +772,44 @@ int main(int argc, char **argv) else { /* Make the path absolute because its needed for relative linked blends to be found */ + int abs = 0; + int filelen; + char cwd[FILE_MAXDIR + FILE_MAXFILE]; char filename[FILE_MAXDIR + FILE_MAXFILE]; + cwd[0] = filename[0] = '\0'; BLI_strncpy(filename, argv[a], sizeof(filename)); - BLI_convertstringcwd(filename); + filelen = strlen(filename); + + /* relative path checks, could do more tests here... */ +#ifdef WIN32 + /* Account for X:/ and X:\ - should be enough */ + if (filelen >= 3 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/')) + abs = 1; +#else + if (filelen >= 2 && filename[0] == '/') + abs = 1 ; +#endif + if (!abs) { + BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + + if (cwd[0] == '\0') { + printf( + "Could not get the current working directory - $PWD for an unknown reason.\n\t" + "Relative linked files will not load if the entire blend path is not used.\n\t" + "The 'Play' button may also fail.\n" + ); + } else { + /* uses the blend path relative to cwd important for loading relative linked files. + * + * cwd should contain c:\ etc on win32 so the relbase can be NULL + * relbase being NULL also prevents // being misunderstood as relative to the current + * blend file which isnt a feature we want to use in this case since were dealing + * with a path from the command line, rather then from inside Blender */ + + BLI_make_file_string(NULL, filename, cwd, argv[a]); + } + } if (G.background) { int retval = BKE_read_file(filename, NULL); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 74fe6c68863..16f8ae0095a 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -79,8 +79,6 @@ #include "DNA_scene_types.h" /***/ -#include "GPU_extensions.h" - #ifdef __cplusplus extern "C" { #endif @@ -138,12 +136,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool usemat = false, useglslmat = false; if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) - usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); - - if(GPU_extensions_minimum_support()) - useglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); - else if(G.fileflags & G_FILE_GAME_MAT_GLSL) - usemat = false; + usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0); // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -198,7 +191,6 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, // some blender stuff MT_CmMatrix4x4 projmat; MT_CmMatrix4x4 viewmat; - float camzoom; int i; for (i = 0; i < 16; i++) @@ -212,13 +204,8 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, projmat.setElem(i, projmat_linear[i]); } - if(v3d->persp==V3D_CAMOB) { - camzoom = (1.41421 + (v3d->camzoom / 50.0)); - camzoom *= camzoom; - } - else - camzoom = 2.0; - + float camzoom = (1.41421 + (v3d->camzoom / 50.0)); + camzoom *= camzoom; camzoom = 4.0 / camzoom; ketsjiengine->SetDrawType(v3d->drawtype); @@ -299,7 +286,6 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(projmat); ketsjiengine->SetCameraOverrideViewMatrix(viewmat); - ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } // create a scene converter, create and convert the startingscene @@ -308,24 +294,23 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); - - if(usemat && (G.fileflags & G_FILE_GAME_MAT)) + + if(usemat) sceneconverter->SetMaterials(true); - if(useglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) + if(useglslmat) sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(keyboarddevice, mousedevice, networkdevice, audiodevice, - startscenename, - blscene); + startscenename); // some python things PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest); ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); - PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); + PyObject *gameLogic = initGameLogic(startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module. PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. initGameKeys(); @@ -541,6 +526,8 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, // create the ketsjiengine KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem); + int i; + Scene *blscene = NULL; if (!bfd) { @@ -556,7 +543,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, } else { blscene = bfd->curscene; } - int cframe = 1, startFrame; + int cframe,startFrame; if (blscene) { cframe=blscene->r.cfra; @@ -587,14 +574,12 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, mousedevice, networkdevice, audiodevice, - startscenename, - blscene); - + startscenename); // some python things PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest); ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); - PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); + PyObject *gameLogic = initGameLogic(startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 340a1ae310b..1d72fb9cde1 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -31,7 +31,6 @@ SET(INC ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader - ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ../../../extern/glew/include diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 669e7bd1b3f..da52be56d1b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -26,6 +26,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "GL/glew.h" #include "KX_BlenderGL.h" #ifdef HAVE_CONFIG_H @@ -92,6 +93,80 @@ void BL_SwapBuffers() myswapbuffers(); } +void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface, + unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]) +{ + Image* ima; + + if(mode & TF_BMFONT) { + //char string[MAX_PROPSTRING]; + int characters, index, character; + float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; + +// bProperty *prop; + + // string = "Frank van Beek"; + + characters = textlen; + + ima = (struct Image*) tface->tpage; + if (ima == NULL) { + characters = 0; + } + + /* When OBCOL flag is on the color is set in IndexPrimitives_3DText */ + if (tface->mode & TF_OBCOL) { /* Color has been set */ + col= NULL; + } else { + if(!col) glColor3f(1.0f, 1.0f, 1.0f); + } + + glPushMatrix(); + for (index = 0; index < characters; index++) { + // lets calculate offset stuff + character = textstr[index]; + + // space starts at offset 1 + // character = character - ' ' + 1; + + matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + + glBegin(GL_POLYGON); + // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], ); + // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); + glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); + + if(col) spack(col[0]); + // glVertex3fv(v1); + glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); + + glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); + if(col) spack(col[1]); + // glVertex3fv(v2); + glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); + + glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); + if(col) spack(col[2]); + // glVertex3fv(v3); + glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); + + if(v4) { + // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy); + glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); + if(col) spack(col[3]); + // glVertex3fv(v4); + glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); + } + glEnd(); + + glTranslatef(advance, 0.0, 0.0); + } + glPopMatrix(); + + } +} + + void DisableForText() { if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h index b891a7343c2..c8e0d47afb6 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.h @@ -46,6 +46,9 @@ void BL_HideMouse(); void BL_NormalMouse(); void BL_WaitMouse(); +void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface, + unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]); + void BL_print_gamedebug_line(char* text, int xco, int yco, int width, int height); void BL_print_gamedebug_line_padded(char* text, int xco, int yco, int width, int height); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 1797d6c1a0f..e4eff163d5b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -26,6 +26,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "KX_BlenderRenderTools.h" + #include "GL/glew.h" #include "RAS_IRenderTools.h" @@ -34,22 +36,23 @@ #include "RAS_ICanvas.h" #include "RAS_GLExtensionManager.h" +// next two includes/dependencies come from the shadow feature +// it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" + #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" -#include "KX_RayCast.h" -#include "KX_IPhysicsController.h" -#include "PHY_IPhysicsEnvironment.h" - -#include "STR_String.h" - -#include "GPU_draw.h" +#include "Value.h" #include "KX_BlenderGL.h" // for text printing -#include "KX_BlenderRenderTools.h" +#include "STR_String.h" +#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting) -unsigned int KX_BlenderRenderTools::m_numgllights; +#include "KX_RayCast.h" +#include "KX_IPhysicsController.h" +#include "PHY_IPhysicsEnvironment.h" +#include "KX_Scene.h" KX_BlenderRenderTools::KX_BlenderRenderTools() { @@ -58,98 +61,81 @@ KX_BlenderRenderTools::KX_BlenderRenderTools() m_numgllights = 8; } -KX_BlenderRenderTools::~KX_BlenderRenderTools() +/** +ProcessLighting performs lighting on objects. the layer is a bitfield that contains layer information. +There are 20 'official' layers in blender. +A light is applied on an object only when they are in the same layer. +OpenGL has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in a scene. +*/ + +int KX_BlenderRenderTools::ProcessLighting(int layer) { -} + + int result = false; -void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) -{ - m_clientobject = NULL; - m_lastlightlayer = -1; - m_lastlighting = false; - DisableOpenGLLights(); -} - -void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) -{ -} - -/* ProcessLighting performs lighting on objects. the layer is a bitfield that - * contains layer information. There are 20 'official' layers in blender. A - * light is applied on an object only when they are in the same layer. OpenGL - * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in - * a scene. */ - -void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) -{ - if(m_lastlightlayer == layer) - return; - - m_lastlightlayer = layer; - - bool enable = false; - - if (layer >= 0) + if (layer < 0) + { + DisableOpenGLLights(); + result = false; + } else { if (m_clientobject) { if (layer == RAS_LIGHT_OBJECT_LAYER) + { layer = static_cast(m_clientobject)->GetLayer(); - - enable = applyLights(layer, viewmat); + } + if (applyLights(layer)) + { + EnableOpenGLLights(); + result = true; + } else + { + DisableOpenGLLights(); + result = false; + } } } - - if(enable) - EnableOpenGLLights(); - else - DisableOpenGLLights(); -} - -void KX_BlenderRenderTools::EnableOpenGLLights() -{ - if(m_lastlighting == true) - return; - - glEnable(GL_LIGHTING); - glEnable(GL_COLOR_MATERIAL); - - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); - if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + return result; + - m_lastlighting = true; } -void KX_BlenderRenderTools::DisableOpenGLLights() + +void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) { - if(m_lastlighting == false) - return; - - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - + m_clientobject = NULL; + m_lastblenderobject = NULL; + m_lastblenderlights = false; + m_lastlayer = -1; m_lastlighting = false; + m_modified = true; + DisableOpenGLLights(); + + } - -void KX_BlenderRenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) +void KX_BlenderRenderTools::SetClientObject(void* obj) { if (m_clientobject != obj) { - bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); - rasty->SetFrontFace(ccw); - + if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) + { + glFrontFace(GL_CCW); + } else + { + glFrontFace(GL_CW); + } m_clientobject = obj; + m_modified = true; } } -bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) +bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { double* const oglmatrix = (double* const) data; - MT_Point3 resultpoint(result->m_hitPoint); - MT_Vector3 resultnormal(result->m_hitNormal); + MT_Point3 resultpoint(hit_point); + MT_Vector3 resultnormal(hit_normal); MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); left = (dir.cross(resultnormal)).safe_normalized(); @@ -196,7 +182,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat MT_Vector3 dir = (campos - objpos).safe_normalized(); MT_Vector3 up(0,0,1.0); - KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; + KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; // get scaling of halo object MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); @@ -232,7 +218,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat { // shadow must be cast to the ground, physics system needed here! MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; + KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; MT_Vector3 direction = MT_Vector3(0,0,-1); direction.normalize(); @@ -250,8 +236,9 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat if (parent) parent->Release(); - KX_RayCast::Callback callback(this, physics_controller, oglmatrix); - if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) + MT_Point3 resultpoint; + MT_Vector3 resultnormal; + if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this, oglmatrix))) { // couldn't find something to cast the shadow on... glMultMatrixd(oglmatrix); @@ -266,29 +253,13 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat } -void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height) -{ - STR_String tmpstr(text); - - if(mode == RAS_IRenderTools::RAS_TEXT_PADDED) - BL_print_gamedebug_line_padded(tmpstr.Ptr(), xco, yco, width, height); - else - BL_print_gamedebug_line(tmpstr.Ptr(), xco, yco, width, height); -} - -/* Render Text renders text into a (series of) polygon, using a texture font, - * Each character consists of one polygon (one quad or two triangles) */ - -void KX_BlenderRenderTools::RenderText( - int mode, - RAS_IPolyMaterial* polymat, - float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) +/** +Render Text renders text into a (series of) polygon, using a texture font, +Each character consists of one polygon (one quad or two triangles) +*/ +void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float v1[3],float v2[3],float v3[3],float v4[3]) { + STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); @@ -305,10 +276,68 @@ void KX_BlenderRenderTools::RenderText( col = blenderpoly->GetMCol(); } - GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); + BL_RenderText( mode,mytext,mytext.Length(),tface,col,v1,v2,v3,v4); + } + +KX_BlenderRenderTools::~KX_BlenderRenderTools() +{ +}; + + +void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) +{ +} + + + +void KX_BlenderRenderTools::DisableOpenGLLights() +{ + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); +} + + +void KX_BlenderRenderTools::EnableOpenGLLights() +{ + glEnable(GL_LIGHTING); + + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + +} + + +/** + * Rendering text using 2D bitmap functionality. + */ +void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height) +{ + switch (mode) { + case RAS_IRenderTools::RAS_TEXT_PADDED: { + STR_String tmpstr(text); + BL_print_gamedebug_line_padded(tmpstr.Ptr(),xco,yco,width,height); + break; + } + default: { + STR_String tmpstr(text); + BL_print_gamedebug_line(tmpstr.Ptr(),xco,yco,width,height); + } + } +} + + + void KX_BlenderRenderTools::PushMatrix() { glPushMatrix(); @@ -320,13 +349,14 @@ void KX_BlenderRenderTools::PopMatrix() } -int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) + +int KX_BlenderRenderTools::applyLights(int objectlayer) { - // taken from blender source, incompatibility between Blender Object / GameObject - float glviewmat[16]; +// taken from blender source, incompatibility between Blender Object / GameObject + unsigned int count; float vec[4]; - + vec[3]= 1.0; for(count=0; count m_lights; std::vector::iterator lit = m_lights.begin(); - - viewmat.getValue(glviewmat); glPushMatrix(); - glLoadMatrixf(glviewmat); + glLoadMatrixf(m_viewmat); for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) { RAS_LightObject* lightdata = (*lit); @@ -406,6 +434,7 @@ int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& view glEnable((GLenum)(GL_LIGHT0+count)); count++; + } } glPopMatrix(); @@ -414,6 +443,22 @@ int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& view } + + +RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial( + const STR_String &texname, + bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant,bool zsort, int lightlayer + ,bool bIsTriangle,void* clientobject,void* tface) +{ + assert(!"Deprecated"); +/* return new KX_BlenderPolyMaterial( + + texname, + ba,matname,tile,tilexrep,tileyrep,mode,transparant,zsort, lightlayer + ,bIsTriangle,clientobject,(struct MTFace*)tface);*/ + return NULL; +} + void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) { int state = rasterizer->GetMotionBlurState(); @@ -447,3 +492,4 @@ void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas) m_filtermanager.RenderFilters(canvas); } +unsigned int KX_BlenderRenderTools::m_numgllights; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index a7618462c9b..8abce1b8c3e 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -26,7 +26,6 @@ * * ***** END GPL LICENSE BLOCK ***** */ - #ifndef __KX_BLENDERRENDERTOOLS #define __KX_BLENDERRENDERTOOLS @@ -38,54 +37,67 @@ #include "RAS_IRenderTools.h" struct KX_ClientObjectInfo; -class KX_RayCast; -/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which - * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon) - * text, lighting. - * - * Most of this code is duplicated in GPC_RenderTools, so this should be - * moved to some common location to avoid duplication. */ +/** +BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which are not +part of the (polygon) Rasterizer. +Effects like 2D text, 3D (polygon) text, lighting. +*/ class KX_BlenderRenderTools : public RAS_IRenderTools { - int m_lastlightlayer; + bool m_lastblenderlights; + void* m_lastblenderobject; + int m_lastlayer; bool m_lastlighting; static unsigned int m_numgllights; - + + public: + KX_BlenderRenderTools(); virtual ~KX_BlenderRenderTools(); - void EndFrame(RAS_IRasterizer* rasty); - void BeginFrame(RAS_IRasterizer* rasty); - - void EnableOpenGLLights(); + virtual void EndFrame(class RAS_IRasterizer* rasty); + virtual void BeginFrame(class RAS_IRasterizer* rasty); void DisableOpenGLLights(); - void ProcessLighting(int layer, const MT_Transform& viewmat); + void EnableOpenGLLights(); + int ProcessLighting(int layer); - void RenderText2D(RAS_TEXT_RENDER_MODE mode, + virtual void RenderText2D(RAS_TEXT_RENDER_MODE mode, const char* text, int xco, int yco, int width, int height); - void RenderText(int mode, + virtual void RenderText(int mode, class RAS_IPolyMaterial* polymat, float v1[3], float v2[3], float v3[3], - float v4[3], - int glattrib); + float v4[3]); + void applyTransform(class RAS_IRasterizer* rasty, + double* oglmatrix, + int objectdrawmode ); + int applyLights(int objectlayer); + virtual void PushMatrix(); + virtual void PopMatrix(); - void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); - int applyLights(int objectlayer, const MT_Transform& viewmat); - - void PushMatrix(); - void PopMatrix(); - - bool RayHit(KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data); - bool NeedRayCast(KX_ClientObjectInfo*) { return true; } + virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(const STR_String &texname, + bool ba, + const STR_String& matname, + int tile, + int tilexrep, + int tileyrep, + int mode, + bool transparant, + bool zsort, + int lightlayer, + bool bIsTriangle, + void* clientobject, + void* tface); + + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); virtual void MotionBlur(RAS_IRasterizer* rasterizer); @@ -93,7 +105,8 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); - virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); + virtual void SetClientObject(void* obj); + }; #endif //__KX_BLENDERRENDERTOOLS diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index 4b9a2a3af17..a7394158a20 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -54,7 +54,6 @@ CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/render/extern/include CPPFLAGS += -I../../blender/blenloader CPPFLAGS += -I../../blender/blenkernel -CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I../Converter CPPFLAGS += -I../Expressions CPPFLAGS += -I../GameLogic @@ -73,5 +72,9 @@ ifeq ($(OS),windows) CPPFLAGS += -I../../blender endif +ifeq ($(WITH_BF_GLEXT),true) + CPPFLAGS += -DWITH_GLEXT +endif + CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 78adbc83d9b..327f4798e04 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -15,7 +15,7 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' incs += ' #source/gameengine/Physics/Bullet #source/gameengine/Physics/Sumo' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader' -incs += ' #extern/glew/include #source/blender/gpu' +incs += ' #extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SOLID_INC'] @@ -26,4 +26,7 @@ cxxflags = [] if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') +if env['WITH_BF_GLEXT'] == 1: + env['CPPFLAGS'].append('-DWITH_GLEXT') + env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 119465c8726..d8b2e063a9d 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -50,7 +50,6 @@ #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" #include "FloatValue.h" -#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index bf774bf7568..09f1d9d4d87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -53,21 +53,16 @@ BL_ArmatureObject::BL_ArmatureObject( : KX_GameObject(sgReplicationInfo,callbacks), m_objArma(armature), - m_framePose(NULL), - m_lastframe(0.0), + m_mrdPose(NULL), + m_lastframe(0.), m_activeAct(NULL), - m_activePriority(999), - m_lastapplyframe(0.0) + m_activePriority(999) { m_armature = get_armature(m_objArma); - - /* we make a copy of blender object's pose, and then always swap it with - * the original pose before calling into blender functions, to deal with - * replica's or other objects using the same blender object */ - m_pose = NULL; - copy_pose(&m_pose, m_objArma->pose, 1 /* copy_constraint_channels_hack */); + m_pose = m_objArma->pose; } + CValue* BL_ArmatureObject::GetReplica() { BL_ArmatureObject* replica = new BL_ArmatureObject(*this); @@ -83,39 +78,34 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) { KX_GameObject::ProcessReplica(replica); - replica->m_pose = NULL; - copy_pose(&replica->m_pose, m_pose, 1 /* copy_constraint_channels_hack */); } BL_ArmatureObject::~BL_ArmatureObject() { - if (m_pose) - free_pose(m_pose); -} - -bool BL_ArmatureObject::VerifyPose() -{ - if(m_lastapplyframe != m_lastframe) { - extract_pose_from_pose(m_objArma->pose, m_pose); - where_is_pose(m_objArma); - m_lastapplyframe = m_lastframe; - extract_pose_from_pose(m_pose, m_objArma->pose); - return false; - } - else - return true; + if (m_mrdPose) + free_pose(m_mrdPose); } +/* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */ +/* there is only 1 unique Pose per Armature */ void BL_ArmatureObject::ApplyPose() { - if(VerifyPose()) - extract_pose_from_pose(m_objArma->pose, m_pose); + if (m_pose) { + // copy to armature object + if (m_objArma->pose != m_pose)/* This should never happen but it does - Campbell */ + extract_pose_from_pose(m_objArma->pose, m_pose); + + // is this needed anymore? + //if (!m_mrdPose) + // copy_pose (&m_mrdPose, m_pose, 0); + //else + // extract_pose_from_pose(m_mrdPose, m_pose); + } } void BL_ArmatureObject::SetPose(bPose *pose) { - extract_pose_from_pose(m_pose, pose); - m_lastapplyframe = -1.0; + m_pose = pose; } bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime) @@ -124,15 +114,10 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, m_activePriority = 9999; m_lastframe= curtime; m_activeAct = NULL; - // remember the pose at the start of the frame - m_framePose = m_pose; } if (priority<=m_activePriority) { - if (prioritySetBlendTime(0.0); /* Reset the blend timer */ m_activeAct = act; @@ -171,7 +156,6 @@ void BL_ArmatureObject::GetPose(bPose **pose) if (*pose == m_pose) // no need to copy if the pointers are the same return; - extract_pose_from_pose(*pose, m_pose); } } @@ -181,16 +165,20 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) /* If the caller supplies a null pose, create a new one. */ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */ + // is this needed anymore? + //if (!m_mrdPose){ + // copy_pose (&m_mrdPose, m_pose, 0); + //} + if (!*pose) { // must duplicate the constraints too otherwise we have corruption in free_pose_channels() // because it will free the blender constraints. // Ideally, blender should rememeber that the constraints were not copied so that // free_pose_channels() would not free them. - copy_pose(pose, m_pose, 1); - } - else { - extract_pose_from_pose(*pose, m_pose); + copy_pose(pose, m_objArma->pose, 1); } + else + extract_pose_from_pose(*pose, m_objArma->pose); } @@ -204,18 +192,16 @@ double BL_ArmatureObject::GetLastFrame() return m_lastframe; } -bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) +bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const { - bPoseChannel *pchan; - - ApplyPose(); - pchan = get_pose_channel(m_objArma->pose, bone->name); + Object* par_arma = m_objArma; + where_is_pose(par_arma); + bPoseChannel *pchan= get_pose_channel(par_arma->pose, bone->name); if(pchan) { matrix.setValue(&pchan->pose_mat[0][0]); return true; } - return false; } diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 6f2c0d2f4c9..752bd5eb365 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -59,10 +59,7 @@ public: void GetMRDPose(struct bPose **pose); void GetPose(struct bPose **pose); void SetPose (struct bPose *pose); - void ApplyPose(); - bool VerifyPose(); - bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime); struct bArmature * GetArmature() { return m_armature; } @@ -72,7 +69,7 @@ public: /// Retrieve the pose matrix for the specified bone. /// Returns true on success. - bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix); + bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const; /// Returns the bone length. The end of the bone is in the local y direction. float GetBoneLength(Bone* bone) const; @@ -82,12 +79,10 @@ protected: Object *m_objArma; struct bArmature *m_armature; struct bPose *m_pose; - struct bPose *m_framePose; + struct bPose *m_mrdPose; double m_lastframe; class BL_ActionActuator *m_activeAct; short m_activePriority; - - double m_lastapplyframe; }; #endif diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 8bdec219354..edc14dabc70 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -377,7 +377,6 @@ BL_Material* ConvertMaterial( material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->flag[i] |= MIPMAP; if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; @@ -602,6 +601,7 @@ BL_Material* ConvertMaterial( (tface->mode & TF_INVISIBLE) )?POLY_VIS:0; + material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; material->tile = tface->tile; material->mode = tface->mode; @@ -617,7 +617,7 @@ BL_Material* ConvertMaterial( } else { // nothing at all - material->ras_mode |= (POLY_VIS| (validmat?0:USE_LIGHT)); + material->ras_mode |= (COLLIDER|POLY_VIS| (validmat?0:USE_LIGHT)); material->mode = default_face_mode; material->transp = TF_SOLID; material->tile = 0; @@ -627,19 +627,13 @@ BL_Material* ConvertMaterial( if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID)) material->transp = TF_ALPHA; - // always zsort alpha + add - if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) { + // always zsort alpha + add + if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) + && (material->transp != TF_CLIP)) { material->ras_mode |= ALPHA; material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; } - // collider or not? - material->ras_mode |= (material->mode & TF_DYNAMIC)? COLLIDER: 0; - - // these flags are irrelevant at this point, remove so they - // don't hurt material bucketing - material->mode &= ~(TF_DYNAMIC|TF_ALPHASORT|TF_TEX); - // get uv sets if(validmat) { @@ -650,7 +644,6 @@ BL_Material* ConvertMaterial( for (int vind = 0; vindnum_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; - if (map.uvCoName.IsEmpty()) isFirstSet = false; else @@ -680,7 +673,7 @@ BL_Material* ConvertMaterial( isFirstSet = false; uvName = layer.name; } - else if(strcmp(layer.name, uvName) != 0) + else { uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; @@ -709,6 +702,7 @@ BL_Material* ConvertMaterial( material->SetConversionUV(uvName, uv); material->SetConversionUV2(uv2Name, uv2); + material->ras_mode |= (mface->v4==0)?TRIANGLE:0; if(validmat) material->matname =(mat->id.name); @@ -773,7 +767,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_sharedvertex_map.resize(totvert); + meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); for (int f=0;fv1].co); @@ -807,6 +801,8 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* NormalShortToFloat(n3, mvert[mface->v4].no); no3 = n3; } + else + no3 = MT_Vector3(0.0, 0.0, 0.0); } else { float fno[3]; @@ -834,7 +830,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* ma = give_current_material(blenderobj, mface->mat_nr+1); { - bool visible = true; + bool polyvisible = true; RAS_IPolyMaterial* polymat = NULL; BL_Material *bl_mat = NULL; @@ -849,7 +845,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* bl_mat->material_index = (int)mface->mat_nr; - visible = ((bl_mat->ras_mode & POLY_VIS)!=0); + polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); collider = ((bl_mat->ras_mode & COLLIDER)!=0); /* vertex colors and uv's were stored in bl_mat temporarily */ @@ -866,7 +862,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* uv22 = uv[2]; uv23 = uv[3]; /* then the KX_BlenderMaterial */ - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer); + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); } else { /* do Texture Face materials */ @@ -890,7 +886,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* tile = tface->tile; mode = tface->mode; - visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); uv0 = MT_Point2(tface->uv[0]); uv1 = MT_Point2(tface->uv[1]); @@ -944,13 +940,15 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rgb3 = KX_rgbaint2uint_new(color); } + bool istriangle = (mface->v4==0); + // only zsort alpha + add bool alpha = (transp == TF_ALPHA || transp == TF_ADD); bool zsort = (mode & TF_ALPHASORT)? alpha: 0; polymat = new KX_PolygonMaterial(imastr, ma, tile, tilexrep, tileyrep, - mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol); + mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol); if (ma) { polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; @@ -963,9 +961,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } } - /* mark face as flat, so vertices are split */ - bool flat = (mface->flag & ME_SMOOTH) == 0; - // see if a bucket was reused or a new one was created // this way only one KX_BlenderMaterial object has to exist per bucket bool bucketCreated; @@ -986,19 +981,49 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* polymat = bucket->GetPolyMaterial(); } - int nverts = (mface->v4)? 4: 3; - RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts); + int nverts = mface->v4?4:3; + int vtxarray = meshobj->FindVertexArray(nverts,polymat); + RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); - poly->SetVisible(visible); - poly->SetCollider(collider); - //poly->SetEdgeCode(mface->edcode); + bool flat; - meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1); - meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2); - meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3); + if (skinMesh) { + /* If the face is set to solid, all fnors are the same */ + if (mface->flag & ME_SMOOTH) + flat = false; + else + flat = true; + } + else + flat = false; + poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); + poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); + poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); if (nverts==4) - meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4); + poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); + + meshobj->AddPolygon(poly); + if (poly->IsCollider()) + { + RAS_TriangleIndex idx; + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v2; + idx.m_index[2] = mface->v3; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + if (nverts==4) + { + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v3; + idx.m_index[2] = mface->v4; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + } + } + +// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetCollider(collider); } if (tface) @@ -1014,12 +1039,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* layer.face++; } } - meshobj->m_sharedvertex_map.clear(); + meshobj->m_xyz_index_to_vertex_index_mapping.clear(); + meshobj->UpdateMaterialList(); // pre calculate texture generation - for(list::iterator mit = meshobj->GetFirstMaterial(); + for(RAS_MaterialBucket::Set::iterator mit = meshobj->GetFirstMaterial(); mit != meshobj->GetLastMaterial(); ++ mit) { - mit->m_bucket->GetPolyMaterial()->OnConstruction(); + (*mit)->GetPolyMaterial()->OnConstruction(); } if (layers) @@ -1279,10 +1305,6 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, //int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0); //bool bRigidBody = (userigidbody == 0); - // object has physics representation? - if (!(blenderobject->gameflag & OB_PHYSICS)) - return; - // get Root Parent of blenderobject struct Object* parent= blenderobject->parent; while(parent && parent->parent) { @@ -1314,7 +1336,6 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_isCompoundChild = isCompoundChild; objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; - objprop.m_margin = blenderobject->margin; if ((objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0)) { @@ -1469,9 +1490,14 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l lightobj.m_type = RAS_LightObject::LIGHT_NORMAL; } - gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, - lightobj, converter->GetGLSLMaterials()); - +#ifdef BLENDER_GLSL + if(converter->GetGLSLMaterials()) + GPU_lamp_from_blender(ob, la); + + gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, ob->gpulamp); +#else + gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, NULL); +#endif BL_ConvertLampIpos(la, gamelight, converter); return gamelight; @@ -1508,7 +1534,7 @@ static KX_GameObject *gameobject_from_blenderobject( gamelight->AddRef(); kxscene->GetLightList()->Add(gamelight); - + break; } @@ -1617,6 +1643,20 @@ struct parentChildLink { SG_Node* m_gamechildnode; }; + /** + * Find the specified scene by name, or the first + * scene if nothing matches (shouldn't happen). + */ +static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scenename) { + Scene *sce; + + for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) + if (scenename == (sce->id.name+2)) + return sce; + + return (Scene*) maggie->scene.first; +} + #include "DNA_constraint_types.h" #include "BIF_editconstraint.h" @@ -1715,7 +1755,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, ) { - Scene *blenderscene = converter->GetBlenderSceneForName(scenename); + Scene *blenderscene = GetSceneForName(maggie, scenename); // for SETLOOPER Scene *sce; Base *base; @@ -1950,7 +1990,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //tf.Add(gameobj->GetSGNode()); gameobj->NodeUpdateGS(0,true); - gameobj->AddMeshUser(); + gameobj->Bucketize(); } else @@ -2147,7 +2187,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //tf.Add(gameobj->GetSGNode()); gameobj->NodeUpdateGS(0,true); - gameobj->AddMeshUser(); + gameobj->Bucketize(); + } else { @@ -2189,16 +2230,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for(oit=allblobj.begin(); oit!=allblobj.end(); oit++) { Object* blenderobj = *oit; - if (blenderobj->type==OB_MESH) { + if (blenderobj->type==OB_MESH){ Mesh *me = (Mesh*)blenderobj->data; if (me->dvert){ - BL_DeformableGameObject *obj = (BL_DeformableGameObject*)converter->FindGameObject(blenderobj); + KX_GameObject *obj = converter->FindGameObject(blenderobj); if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ KX_GameObject *par = converter->FindGameObject(blenderobj->parent); - if (par && obj->m_pDeformer) - ((BL_SkinDeformer*)obj->m_pDeformer)->SetArmature((BL_ArmatureObject*) par); + if (par) + ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); } } } @@ -2212,41 +2253,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { struct Object* blenderchild = pcit->m_blenderchild; - struct Object* blenderparent = blenderchild->parent; - KX_GameObject* parentobj = converter->FindGameObject(blenderparent); - KX_GameObject* childobj = converter->FindGameObject(blenderchild); - - assert(childobj); - - if (!parentobj || objectlist->SearchValue(childobj) != objectlist->SearchValue(parentobj)) - { - // special case: the parent and child object are not in the same layer. - // This weird situation is used in Apricot for test purposes. - // Resolve it by not converting the child - childobj->GetSGNode()->DisconnectFromParent(); - delete pcit->m_gamechildnode; - // Now destroy the child object but also all its descendent that may already be linked - // Remove the child reference in the local list! - // Note: there may be descendents already if the children of the child were processed - // by this loop before the child. In that case, we must remove the children also - CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj); - childrenlist->Add(childobj->AddRef()); - for ( i=0;iGetCount();i++) - { - KX_GameObject* obj = static_cast(childrenlist->GetValue(i)); - if (templist->RemoveValue(obj)) - obj->Release(); - if (sumolist->RemoveValue(obj)) - obj->Release(); - if (logicbrick_conversionlist->RemoveValue(obj)) - obj->Release(); - } - childrenlist->Release(); - // now destroy recursively - kxscene->RemoveObject(childobj); - continue; - } - switch (blenderchild->partype) { case PARVERT1: @@ -2267,11 +2273,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { // parent this to a bone Bone *parent_bone = get_named_bone(get_armature(blenderchild->parent), blenderchild->parsubstr); - - if(parent_bone) { - KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); - pcit->m_gamechildnode->SetParentRelation(bone_parent_relation); - } + KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); + pcit->m_gamechildnode->SetParentRelation(bone_parent_relation); break; } @@ -2286,7 +2289,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie, break; } - parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode); + struct Object* blenderparent = blenderchild->parent; + KX_GameObject* parentobj = converter->FindGameObject(blenderparent); + if (parentobj) + { + parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode); + } } vec_parent_child.clear(); @@ -2503,10 +2511,5 @@ void BL_ConvertBlenderObjects(struct Main* maggie, kxscene->DupliGroupRecurse(gameobj, 0); } } - - KX_Camera *activecam = kxscene->GetActiveCamera(); - MT_Scalar distance = (activecam)? activecam->GetCameraFar() - activecam->GetCameraNear(): 100.0f; - RAS_BucketManager *bucketmanager = kxscene->GetBucketManager(); - bucketmanager->OptimizeBuckets(distance); } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index 1d62a41cce9..d23274324ee 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -41,14 +41,12 @@ BL_DeformableGameObject::~BL_DeformableGameObject() delete m_pDeformer; // __NLA : Temporary until we decide where to put this } -void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) +void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) { - BL_MeshDeformer *deformer; KX_GameObject::ProcessReplica(replica); - if (m_pDeformer) { - deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(); - ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer; + if (m_pDeformer){ + ((BL_DeformableGameObject*)replica)->m_pDeformer = m_pDeformer->GetReplica(); } } diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index fa3b8185fe2..39d66a90e92 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -50,26 +50,26 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { - size_t i; + size_t i, j; float *co; // only apply once per frame if the mesh is actually modified if(m_pMeshObject->MeshModified() && m_lastDeformUpdate != m_gameobj->GetLastFrame()) { // For each material - for(list::iterator mit= m_pMeshObject->GetFirstMaterial(); + for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - if(!mit->m_slots[(void*)m_gameobj]) - continue; + RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; - RAS_MeshSlot::iterator it; + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + + // For each array + for (i=0; ibegin(it); !slot->end(it); slot->next(it)) { // For each vertex - for(i=it.startvertex; imvert[v.getOrigIndex()].co; v.SetXYZ(MT_Point3(co)); } @@ -90,17 +90,7 @@ BL_MeshDeformer::~BL_MeshDeformer() delete [] m_transverts; if (m_transnors) delete [] m_transnors; -} - -void BL_MeshDeformer::Relink(GEN_Map*map) -{ - void **h_obj = (*map)[m_gameobj]; - - if (h_obj) - m_gameobj = (BL_DeformableGameObject*)(*h_obj); - else - m_gameobj = NULL; -} +}; /** * @warning This function is expensive! @@ -111,41 +101,41 @@ void BL_MeshDeformer::RecalcNormals() * gives area-weight normals which often look better anyway, and use * GL_NORMALIZE so we don't have to do per vertex normalization either * since the GPU can do it faster */ - list::iterator mit; - RAS_MeshSlot::iterator it; - size_t i; + size_t i, j; /* set vertex normals to zero */ memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert); /* add face normals to vertices. */ - for(mit = m_pMeshObject->GetFirstMaterial(); + for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - if(!mit->m_slots[(void*)m_gameobj]) - continue; + RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; + const vecIndexArrays& indexarrays = m_pMeshObject->GetIndexCache(mat); + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - for(slot->begin(it); !slot->end(it); slot->next(it)) { - int nvert = (int)it.array->m_type; + for (i=0; iUsesTriangles()? 3: 4; - for(i=0; igetXYZ(); + v4 = &vertexarray[indexarray[j+3]]; + co4 = v4->getLocalXYZ(); n1[0]= co1[0]-co3[0]; n1[1]= co1[1]-co3[1]; @@ -184,7 +174,7 @@ void BL_MeshDeformer::RecalcNormals() } /* in case of flat - just assign, the vertices are split */ - if(v1.getFlag() & RAS_TexVert::FLAT) { + if(v1.getFlag() & TV_CALCFACENORMAL) { v1.SetNormal(fnor); v2.SetNormal(fnor); v3.SetNormal(fnor); @@ -196,18 +186,19 @@ void BL_MeshDeformer::RecalcNormals() } /* assign smooth vertex normals */ - for(mit = m_pMeshObject->GetFirstMaterial(); + for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - if(!mit->m_slots[(void*)m_gameobj]) - continue; + RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); - RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - for(slot->begin(it); !slot->end(it); slot->next(it)) { - for(i=it.startvertex; itotvert; } } - + diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 9d3d2e78123..e9f7f0b192f 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -47,7 +47,7 @@ class BL_MeshDeformer : public RAS_Deformer public: void VerifyStorage(); void RecalcNormals(); - virtual void Relink(GEN_Map*map); + virtual void Relink(GEN_Map*map){}; BL_MeshDeformer(BL_DeformableGameObject *gameobj, struct Object* obj, class BL_SkinMeshObject *meshobj ): @@ -67,7 +67,6 @@ public: virtual RAS_Deformer* GetReplica(){return NULL;}; struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; - protected: class BL_SkinMeshObject* m_pMeshObject; struct Mesh* m_bmesh; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 679b0df7ec6..942e3b502e0 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -49,7 +49,6 @@ #include "BLI_arithb.h" #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" -#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include @@ -135,6 +134,7 @@ void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight) { vector::const_iterator it; float dstweight; + int i; KeyBlock *kb; dstweight = 1.0F - srcweight; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index 236cd1a6667..b2e54539b19 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -111,7 +111,10 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) int type; // the shape drivers use the bone matrix as input. Must // update the matrix now + Object* par_arma = m_armobj->GetArmatureObject(); m_armobj->ApplyPose(); + where_is_pose( par_arma ); + PoseApplied(true); for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { // no need to set a specific time: this curve has a driver diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 1465bb01e22..5f0188e3a42 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -43,6 +43,17 @@ struct IpoCurve; class BL_ShapeDeformer : public BL_SkinDeformer { public: + virtual void Relink(GEN_Map*map) + { + void **h_obj = (*map)[m_gameobj]; + if (h_obj){ + m_gameobj = (BL_DeformableGameObject*)(*h_obj); + } + else + m_gameobj=NULL; + // relink the underlying skin deformer + BL_SkinDeformer::Relink(map); + }; BL_ShapeDeformer(BL_DeformableGameObject *gameobj, Object *bmeshobj, BL_SkinMeshObject *mesh) diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index d8e7a9cdadf..f96c40c098f 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -99,26 +99,9 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } -void BL_SkinDeformer::Relink(GEN_Map*map) -{ - if (m_armobj) { - void **h_obj = (*map)[m_armobj]; - - if (h_obj) - SetArmature( (BL_ArmatureObject*)(*h_obj) ); - else - m_armobj=NULL; - } - - BL_MeshDeformer::Relink(map); -} - bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) { - RAS_MeshSlot::iterator it; - RAS_MeshMaterial *mmat; - RAS_MeshSlot *slot; - size_t i; + size_t i, j; // update the vertex in m_transverts Update(); @@ -127,18 +110,16 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) // share the same mesh (=the same cache). As the rendering is done per polymaterial // cycling through the objects, the entire mesh cache cannot be updated in one shot. - mmat = m_pMeshObject->GetMeshMaterial(mat); - if(!mmat->m_slots[(void*)m_gameobj]) - return true; + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - slot = *mmat->m_slots[(void*)m_gameobj]; + // For each array + for (i=0; ibegin(it); !slot->end(it); slot->next(it)) { - // for each vertex + // For each vertex // copy the untransformed data from the original mvert - for(i=it.startvertex; iGetArmatureObject(); + if (!PoseApplied()){ + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + } /* store verts locally */ VerifyStorage(); @@ -178,8 +163,6 @@ bool BL_SkinDeformer::Update(void) for (int v =0; vtotvert; v++) VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); - m_armobj->ApplyPose(); - // save matrix first Mat4CpyMat4(obmat, m_objMesh->obmat); // set reference matrix @@ -196,11 +179,11 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); - + /* reset for next frame */ + PoseApplied(false); /* indicate that the m_transverts and normals are up to date */ return true; } - return false; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index e08de8c478a..d3fc5ae2a81 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -50,7 +50,17 @@ class BL_SkinDeformer : public BL_MeshDeformer { public: // void SetArmatureController (BL_ArmatureController *cont); - virtual void Relink(GEN_Map*map); + virtual void Relink(GEN_Map*map) + { + if (m_armobj){ + void **h_obj = (*map)[m_armobj]; + if (h_obj){ + SetArmature( (BL_ArmatureObject*)(*h_obj) ); + } + else + m_armobj=NULL; + } + } void SetArmature (class BL_ArmatureObject *armobj); BL_SkinDeformer(BL_DeformableGameObject *gameobj, @@ -71,6 +81,10 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + bool PoseApplied() + { return m_poseApplied; } + void PoseApplied(bool applied) + { m_poseApplied = applied; } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp index 4f9f1a434b5..fa215df1e1c 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.cpp +++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp @@ -28,69 +28,42 @@ * Deformer that supports armature skinning */ +#ifdef HAVE_CONFIG_H +#include +#endif + #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 - -#include "MEM_guardedalloc.h" - -#include "DNA_key_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" - -#include "RAS_BucketManager.h" #include "RAS_IPolygonMaterial.h" - -#include "KX_GameObject.h" - #include "BL_SkinMeshObject.h" #include "BL_DeformableGameObject.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "KX_GameObject.h" +#include "RAS_BucketManager.h" -BL_SkinMeshObject::BL_SkinMeshObject(Mesh* mesh, int lightlayer) - : RAS_MeshObject (mesh, lightlayer) -{ - m_bDeformed = true; - - if (m_mesh && m_mesh->key) - { - KeyBlock *kb; - int count=0; - // initialize weight cache for shape objects - // count how many keys in this mesh - for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) - count++; - m_cacheWeightIndex.resize(count,-1); - } -} - -BL_SkinMeshObject::~BL_SkinMeshObject() +//void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,RAS_BucketManager* bucketmgr) +void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec) { - if (m_mesh && m_mesh->key) + + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + ms.m_bObjectColor = useObjectColor; + ms.m_RGBAcolor = rgbavec; + ms.m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; + + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();it++) { - KeyBlock *kb; - // remove the weight cache to avoid memory leak - for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { - if(kb->weights) - MEM_freeN(kb->weights); - kb->weights= NULL; - } - } -} -void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool useObjectColor,const MT_Vector4& rgbavec, bool visible, bool culled) -{ - list::iterator it; - list::iterator sit; + RAS_MaterialBucket* materialbucket = (*it); - for(it = m_materials.begin();it!=m_materials.end();++it) { - if(!it->m_slots[clientobj]) - continue; - - RAS_MeshSlot *slot = *it->m_slots[clientobj]; - slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; +// KX_ArrayOptimizer* oa = GetArrayOptimizer(materialbucket->GetPolyMaterial()); + materialbucket->SetMeshSlot(ms); } - RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled); } static int get_def_index(Object* ob, const char* vgroup) @@ -101,7 +74,6 @@ static int get_def_index(Object* ob, const char* vgroup) for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++) if (!strcmp(curdef->name, vgroup)) return index; - return -1; } diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h index 8544a2b958c..c21fb64204b 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.h +++ b/source/gameengine/Converter/BL_SkinMeshObject.h @@ -33,27 +33,62 @@ #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 - +#include "MEM_guardedalloc.h" #include "RAS_MeshObject.h" #include "RAS_Deformer.h" #include "RAS_IPolygonMaterial.h" #include "BL_MeshDeformer.h" +#include "DNA_mesh_types.h" +#include "DNA_key_types.h" +#include "DNA_meshdata_types.h" + class BL_SkinMeshObject : public RAS_MeshObject { + +// enum { BUCKET_MAX_INDICES = 16384};//2048};//8192}; +// enum { BUCKET_MAX_TRIANGLES = 4096}; + protected: vector m_cacheWeightIndex; public: - BL_SkinMeshObject(Mesh* mesh, int lightlayer); - ~BL_SkinMeshObject(); + void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec); +// void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr); - void UpdateBuckets(void* clientobj, double* oglmatrix, - bool useObjectColor, const MT_Vector4& rgbavec, bool visible, bool culled); + BL_SkinMeshObject(Mesh* mesh, int lightlayer) : RAS_MeshObject (mesh, lightlayer) + { + m_class = 1; + if (m_mesh && m_mesh->key) + { + KeyBlock *kb; + int count=0; + // initialize weight cache for shape objects + // count how many keys in this mesh + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) + count++; + m_cacheWeightIndex.resize(count,-1); + } + }; + + virtual ~BL_SkinMeshObject() + { + if (m_mesh && m_mesh->key) + { + KeyBlock *kb; + // remove the weight cache to avoid memory leak + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { + if(kb->weights) + MEM_freeN(kb->weights); + kb->weights= NULL; + } + } + }; // for shape keys, void CheckWeightCache(struct Object* obj); + }; #endif diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 217bdb30907..adb7304b10e 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -64,7 +64,6 @@ SET(INC ../../../source/gameengine/Network/LoopBackNetwork ../../../source/blender/misc ../../../source/blender/blenloader - ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ${PYTHON_INC} diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 7eec93dc402..de91bce2ab1 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -184,21 +184,20 @@ bool KX_BlenderSceneConverter::TryAndLoadNewFile() return result; } -Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) -{ - Scene *sce; + /** * Find the specified scene by name, or the first * scene if nothing matches (shouldn't happen). */ +static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& scenename) { + Scene *sce; - for (sce= (Scene*) m_maggie->scene.first; sce; sce= (Scene*) sce->id.next) - if (name == (sce->id.name+2)) + for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) + if (scenename == (sce->id.name+2)) return sce; - return (Scene*)m_maggie->scene.first; - + return (Scene*) maggie->scene.first; } #include "KX_PythonInit.h" @@ -246,11 +245,6 @@ struct BlenderDebugDraw : public btIDebugDraw { return m_debugMode; } - ///todo: find out if Blender can do this - virtual void draw3dText(const btVector3& location,const char* textString) - { - - } }; @@ -264,7 +258,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, class RAS_ICanvas* canvas) { //find out which physics engine - Scene *blenderscene = GetBlenderSceneForName(scenename); + Scene *blenderscene = GetSceneForName2(m_maggie, scenename); e_PhysicsEngine physics_engine = UseBullet; // hook for registration function during conversion. @@ -501,17 +495,7 @@ void KX_BlenderSceneConverter::RegisterGameObject( void KX_BlenderSceneConverter::UnregisterGameObject( KX_GameObject *gameobject) { - CHashedPtr gptr(gameobject); - struct Object **bobp= m_map_gameobject_to_blender[gptr]; - if (bobp) { - CHashedPtr bptr(*bobp); - KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; - if (gobp && *gobp == gameobject) - // also maintain m_map_blender_to_gameobject if the gameobject - // being removed is matching the blender object - m_map_blender_to_gameobject.remove(bptr); - m_map_gameobject_to_blender.remove(gptr); - } + m_map_gameobject_to_blender.remove(CHashedPtr(gameobject)); } @@ -660,13 +644,13 @@ extern "C" { Ipo *add_ipo( char *name, int idcode ); char *getIpoCurveName( IpoCurve * icu ); - struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); + struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); void testhandles_ipocurve(struct IpoCurve *icu); - void insert_vert_icu(struct IpoCurve *, float, float, short); void Mat3ToEul(float tmat[][3], float *eul); + } -IpoCurve* findIpoCurve(IpoCurve* first, const char* searchName) +IpoCurve* findIpoCurve(IpoCurve* first,char* searchName) { IpoCurve* icu1; for( icu1 = first; icu1; icu1 = icu1->next ) @@ -834,7 +818,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { - //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); + KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); if (blenderObject) @@ -862,7 +846,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) - //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); + const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Point3& position = gameObj->NodeGetWorldPosition(); Ipo* ipo = blenderObject->ipo; @@ -873,27 +857,27 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); @@ -990,7 +974,7 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { - //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); + KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); if (blenderObject) @@ -1018,8 +1002,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() - //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - //const MT_Point3& position = gameObj->NodeGetWorldPosition(); + const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); + const MT_Point3& position = gameObj->NodeGetWorldPosition(); Ipo* ipo = blenderObject->ipo; if (ipo) @@ -1029,27 +1013,27 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index 2317e952a0a..e5d6ccc5caf 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -45,7 +45,6 @@ class BL_Material; struct IpoCurve; struct Main; struct SpaceIpo; -struct Scene; class KX_BlenderSceneConverter : public KX_ISceneConverter { @@ -152,7 +151,6 @@ public: virtual void SetGLSLMaterials(bool val); virtual bool GetGLSLMaterials(); - struct Scene* GetBlenderSceneForName(const STR_String& name); }; #endif //__KX_BLENDERSCENECONVERTER_H diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index e8be8de95ed..b1f86afa4ee 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -74,8 +74,6 @@ #include "BKE_text.h" #include "BLI_blenlib.h" -#define FILE_MAX 240 // repeated here to avoid dependency from BKE_utildefines.h - #include "KX_NetworkMessageActuator.h" #ifdef WIN32 @@ -357,26 +355,22 @@ void BL_ConvertActuators(char* maggiename, if (soundActuatorType != KX_SoundActuator::KX_SOUNDACT_NODEF) { - SND_Scene* soundscene = scene->GetSoundScene(); - STR_String samplename = ""; - bool sampleisloaded = false; + SND_SoundObject* sndobj = NULL; - if (soundact->sound) { - /* Need to convert the samplename into absolute path - * before checking if its loaded */ - char fullpath[FILE_MAX]; + if (soundact->sound) + { + SND_Scene* soundscene = scene->GetSoundScene(); + STR_String samplename = soundact->sound->name; - /* dont modify soundact->sound->name, only change a copy */ - BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); - BLI_convertstringcode(fullpath, maggiename); - samplename = fullpath; + bool sampleisloaded = false; /* let's see if the sample was already loaded */ if (soundscene->IsSampleLoaded(samplename)) { sampleisloaded = true; } - else { + else + { /* if not, make it so */ PackedFile* pf = soundact->sound->newpackedfile; @@ -389,33 +383,25 @@ void BL_ConvertActuators(char* maggiename, /* or else load it from disk */ else { - if (soundscene->LoadSample(samplename, NULL, 0) > -1) { + /* but we need to convert the samplename into absolute pathname first */ + char fullpath[sizeof(soundact->sound->name)]; + + /* dont modify soundact->sound->name, only change a copy */ + BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); + BLI_convertstringcode(fullpath, maggiename); + samplename = fullpath; + + /* and now we can load it */ + if (soundscene->LoadSample(samplename, NULL, 0) > -1) sampleisloaded = true; - } - else { - std::cout << "WARNING: Sound actuator \"" << bact->name << - "\" from object \"" << blenderobject->id.name+2 << - "\" failed to load sample." << std::endl; - } } } - } else { - std::cout << "WARNING: Sound actuator \"" << bact->name << - "\" from object \"" << blenderobject->id.name+2 << - "\" has no sound datablock." << std::endl; - } - - /* Note, allowing actuators for sounds that are not there was added since 2.47 - * This is because python may expect the actuator and raise an exception if it dosnt find it - * better just to add a dummy sound actuator. */ - SND_SoundObject* sndobj = NULL; - if (sampleisloaded) - { - /* setup the SND_SoundObject */ - sndobj = new SND_SoundObject(); - sndobj->SetSampleName(samplename.Ptr()); - sndobj->SetObjectName(bact->name); - if (soundact->sound) { + + if (sampleisloaded) + { + sndobj = new SND_SoundObject(); + sndobj->SetSampleName(samplename.Ptr()); + sndobj->SetObjectName(bact->name); sndobj->SetRollOffFactor(soundact->sound->attenuation); sndobj->SetGain(soundact->sound->volume); sndobj->SetPitch(exp((soundact->sound->pitch / 12.0) * log(2.0))); @@ -428,9 +414,8 @@ void BL_ConvertActuators(char* maggiename, else sndobj->SetLoopMode(SND_LOOP_NORMAL); } - else { + else sndobj->SetLoopMode(SND_LOOP_OFF); - } if (soundact->sound->flags & SOUND_FLAGS_PRIORITY) sndobj->SetHighPriority(true); @@ -441,30 +426,22 @@ void BL_ConvertActuators(char* maggiename, sndobj->Set3D(true); else sndobj->Set3D(false); - } - else { - /* dummy values for a NULL sound - * see editsound.c - defaults are unlikely to change soon */ - sndobj->SetRollOffFactor(1.0); - sndobj->SetGain(1.0); - sndobj->SetPitch(1.0); - sndobj->SetLoopMode(SND_LOOP_OFF); - sndobj->SetHighPriority(false); - sndobj->Set3D(false); + + KX_SoundActuator* tmpsoundact = + new KX_SoundActuator(gameobj, + sndobj, + scene->GetSoundScene(), // needed for replication! + soundActuatorType, + startFrame, + stopFrame); + + tmpsoundact->SetName(bact->name); + baseact = tmpsoundact; + soundscene->AddObject(sndobj); + } else { + std::cout << "WARNING: Sound actuator " << bact->name << " failed to load sample." << std::endl; } } - KX_SoundActuator* tmpsoundact = - new KX_SoundActuator(gameobj, - sndobj, - scene->GetSoundScene(), // needed for replication! - soundActuatorType, - startFrame, - stopFrame); - - tmpsoundact->SetName(bact->name); - baseact = tmpsoundact; - if (sndobj) - soundscene->AddObject(sndobj); } break; } @@ -577,16 +554,10 @@ void BL_ConvertActuators(char* maggiename, originalval = converter->FindGameObject(editobact->ob); } } - MT_Vector3 linvelvec ( - KX_BLENDERTRUNC(editobact->linVelocity[0]), + MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]), KX_BLENDERTRUNC(editobact->linVelocity[1]), KX_BLENDERTRUNC(editobact->linVelocity[2])); - - MT_Vector3 angvelvec ( - KX_BLENDERTRUNC(editobact->angVelocity[0]), - KX_BLENDERTRUNC(editobact->angVelocity[1]), - KX_BLENDERTRUNC(editobact->angVelocity[2])); - + KX_SCA_AddObjectActuator* tmpaddact = new KX_SCA_AddObjectActuator( gameobj, @@ -594,9 +565,7 @@ void BL_ConvertActuators(char* maggiename, editobact->time, scene, linvelvec.getValue(), - (editobact->localflag & ACT_EDOB_LOCAL_LINV)!=0, - angvelvec.getValue(), - (editobact->localflag & ACT_EDOB_LOCAL_ANGV)!=0 + editobact->localflag!=0 ); //editobact->ob to gameobj @@ -878,16 +847,6 @@ void BL_ConvertActuators(char* maggiename, mode = KX_GameActuator::KX_GAME_QUIT; break; } - case ACT_GAME_SAVECFG: - { - mode = KX_GameActuator::KX_GAME_SAVECFG; - break; - } - case ACT_GAME_LOADCFG: - { - mode = KX_GameActuator::KX_GAME_LOADCFG; - break; - } default: ; /* flag error */ } @@ -974,9 +933,10 @@ void BL_ConvertActuators(char* maggiename, bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data; KX_VisibilityActuator * tmp_vis_act = NULL; bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0); - bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0); - tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive); + tmp_vis_act = + new KX_VisibilityActuator(gameobj, + !v); baseact = tmp_vis_act; } @@ -1075,7 +1035,7 @@ void BL_ConvertActuators(char* maggiename, { bParentActuator *parAct = (bParentActuator *) bact->data; int mode = KX_ParentActuator::KX_PARENT_NODEF; - KX_GameObject *tmpgob = NULL; + KX_GameObject *tmpgob; switch(parAct->type) { diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index f16855955ff..4806df36090 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -633,7 +633,6 @@ void BL_ConvertSensors(struct Object* blenderobject, if (eventmgr) { bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); @@ -646,7 +645,6 @@ void BL_ConvertSensors(struct Object* blenderobject, gameobj, checkname, bFindMaterial, - bXRay, distance, axis, kxscene); @@ -713,7 +711,6 @@ void BL_ConvertSensors(struct Object* blenderobject, gamesensor = new SCA_JoystickSensor( eventmgr, gameobj, - bjoy->joyindex, joysticktype, axis,axisf, prec, @@ -768,26 +765,19 @@ void BL_ConvertSensors(struct Object* blenderobject, logicmgr->RegisterToSensor(gamecont,gamesensor); } else { printf( - "Warning, sensor \"%s\" could not find its controller " - "(link %d of %d) from object \"%s\"\n" + "Warning, sensor \"%s\" could not find its controller" + "(link %d of %d)\n" "\tthere has been an error converting the blender controller for the game engine," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + "logic may be incorrect\n", sens->name, i+1, sens->totlinks); } } else { printf( - "Warning, sensor \"%s\" has lost a link to a controller " - "(link %d of %d) from object \"%s\"\n" + "Warning, sensor \"%s\" has lost a link to a controller" + "(link %d of %d)\n" "\tpossible causes are partially appended objects or an error reading the file," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + "logic may be incorrect\n", sens->name, i+1, sens->totlinks); } } - // special case: Keyboard sensor with no link - // this combination is usually used for key logging. - if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { - // Force the registration so that the sensor runs - gamesensor->IncLink(); - } - // done with gamesensor gamesensor->Release(); diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile index 4dd63e428bd..f312fc13221 100644 --- a/source/gameengine/Converter/Makefile +++ b/source/gameengine/Converter/Makefile @@ -51,7 +51,6 @@ CPPFLAGS += -I../../blender/include CPPFLAGS += -I../../blender/blenlib CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/render/extern/include -CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index 3be352c568b..f5e382b471e 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -16,7 +16,7 @@ incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/game incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet #source/gameengine/Physics/BlOde' incs += ' #source/gameengine/Physics/Dummy #source/gameengine/Physics/Sumo' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' -incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu' +incs += ' #source/blender/misc #source/blender/blenloader' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SOLID_INC'] diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile index 6736149bbcd..e9c02eedcf2 100644 --- a/source/gameengine/Expressions/Makefile +++ b/source/gameengine/Expressions/Makefile @@ -36,7 +36,6 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -CPPFLAGS += -I../../blender/makesdna 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 1eca527151a..8937f481922 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -119,7 +119,6 @@ PyObject *PyObjectPlus::_getattr(const STR_String& attr) int PyObjectPlus::_delattr(const STR_String& attr) { - PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } @@ -127,8 +126,7 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) { //return PyObject::_setattr(attr,value); //cerr << "Unknown attribute" << endl; - PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); - return 1; + return 1; } /*------------------------------ diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index ccc9af2ed79..f433a08faba 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -43,33 +43,6 @@ * Python defines ------------------------------*/ -/* - Py_RETURN_NONE - Python 2.4 macro. - defined here until we switch to 2.4 - also in api2_2x/gen_utils.h -*/ -#ifndef Py_RETURN_NONE -#define Py_RETURN_NONE return Py_BuildValue("O", Py_None) -#endif -#ifndef Py_RETURN_FALSE -#define Py_RETURN_FALSE return PyBool_FromLong(0) -#endif -#ifndef Py_RETURN_TRUE -#define Py_RETURN_TRUE return PyBool_FromLong(1) -#endif - -/* for pre Py 2.5 */ -#if PY_VERSION_HEX < 0x02050000 -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -#else -/* Py 2.5 and later */ -#define intargfunc ssizeargfunc -#define intintargfunc ssizessizeargfunc -#endif - // some basic python macros #define Py_Return { Py_INCREF(Py_None); return Py_None;} @@ -129,12 +102,6 @@ static inline void Py_Fatal(char *M) { return ((class_name*) self)->Py##method_name(self, args, kwds); \ }; \ -#define KX_PYMETHOD_VARARGS(class_name, method_name) \ - PyObject* Py##method_name(PyObject* self, PyObject* args); \ - static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ - return ((class_name*) self)->Py##method_name(self, args); \ - }; \ - #define KX_PYMETHOD_NOARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self); \ static PyObject* sPy##method_name( PyObject* self) { \ @@ -183,9 +150,6 @@ static inline void Py_Fatal(char *M) { #define KX_PYMETHODTABLE(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, class_name::method_name##_doc} -#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \ - {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, class_name::method_name##_doc} - /** * Function implementation macro */ @@ -193,9 +157,6 @@ static inline void Py_Fatal(char *M) { char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*) -#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \ -char class_name::method_name##_doc[] = doc_string; \ -PyObject* class_name::Py##method_name(PyObject*) /*------------------------------ * PyObjectPlus diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 7296dfbec10..7bcb45228db 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -391,23 +391,16 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber) bool CValue::RemoveProperty(const STR_String & inName) { // Check if there are properties at all which can be removed - if (m_pNamedPropertyArray) { - CValue* val = GetProperty(inName); - if (NULL != val) - { - val->Release(); - m_pNamedPropertyArray->erase(inName); - return true; - } - } - - char err[128]; - if (m_pNamedPropertyArray) - sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr()); - else - sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr()); - - PyErr_SetString(PyExc_AttributeError, err); + if (m_pNamedPropertyArray == NULL) + return false; + + CValue* val = GetProperty(inName); + if (NULL != val) + { + val->Release(); + m_pNamedPropertyArray->erase(inName); + return true; + } return false; } @@ -762,8 +755,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) int CValue::_delattr(const STR_String& attr) { - if (!RemoveProperty(attr)) /* sets error */ - return 1; + RemoveProperty(attr); return 0; } diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index 06002060bf1..18d7b6ffcd0 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -29,9 +29,9 @@ #include "SCA_Joystick.h" #include "SCA_JoystickPrivate.h" -SCA_Joystick::SCA_Joystick(short int index) + +SCA_Joystick::SCA_Joystick() : - m_joyindex(index), m_axis10(0), m_axis11(0), m_axis20(0), @@ -52,53 +52,82 @@ SCA_Joystick::~SCA_Joystick() delete m_private; } -SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX]; +SCA_Joystick *SCA_Joystick::m_instance = NULL; int SCA_Joystick::m_refCount = 0; -SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) +SCA_Joystick *SCA_Joystick::GetInstance() { - if (joyindex < 0 || joyindex >= JOYINDEX_MAX) { - echo("Error-invalid joystick index: " << joyindex); - return NULL; - } - - if (m_refCount == 0) + if (m_instance == 0) { - int i; - // do this once only - if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){ - echo("Error-Initializing-SDL: " << SDL_GetError()); - return NULL; - } - for (i=0; iCreateJoystickDevice(); - } + m_instance = new SCA_Joystick(); + m_instance->CreateJoystickDevice(); m_refCount = 1; } else { m_refCount++; } - return m_instance[joyindex]; + return m_instance; } void SCA_Joystick::ReleaseInstance() { if (--m_refCount == 0) { - int i; - for (i=0; iDestroyJoystickDevice(); - delete m_instance[i]; - } - m_instance[i]= NULL; - } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ); + DestroyJoystickDevice(); + delete m_instance; + m_instance = NULL; } } + +bool SCA_Joystick::CreateJoystickDevice() +{ + bool init = false; + init = pCreateJoystickDevice(); + return init; +} + + +void SCA_Joystick::DestroyJoystickDevice() +{ + if(m_isinit) + pDestroyJoystickDevice(); +} + + +void SCA_Joystick::HandleEvents() +{ + if(m_isinit) + { + if(SDL_PollEvent(&m_private->m_event)) + { + switch(m_private->m_event.type) + { + case SDL_JOYAXISMOTION: + HANDLE_AXISMOTION(OnAxisMotion); + break; + case SDL_JOYHATMOTION: + HANDLE_HATMOTION(OnHatMotion); + break; + case SDL_JOYBUTTONUP: + HANDLE_BUTTONUP(OnButtonUp); + break; + case SDL_JOYBUTTONDOWN: + HANDLE_BUTTONDOWN(OnButtonDown); + break; + case SDL_JOYBALLMOTION: + HANDLE_BALLMOTION(OnBallMotion); + break; + default: + HANDLE_NOEVENT(OnNothing); + break; + } + } + } +} + + void SCA_Joystick::cSetPrecision(int val) { m_prec = val; @@ -197,6 +226,76 @@ int SCA_Joystick::pGetHat(int direction) return 0; } + +bool SCA_Joystick::GetJoyAxisMotion() +{ + bool result = false; + if(m_isinit){ + if(SDL_PollEvent(&m_private->m_event)){ + switch(m_private->m_event.type) + { + case SDL_JOYAXISMOTION: + result = true; + break; + } + } + } + return result; +} + + +bool SCA_Joystick::GetJoyButtonPress() +{ + bool result = false; + if(m_isinit){ + if(SDL_PollEvent(&m_private->m_event)){ + switch(m_private->m_event.type) + { + case SDL_JOYBUTTONDOWN: + result = true; + break; + } + } + } + return result; +} + + +bool SCA_Joystick::GetJoyButtonRelease() +{ + bool result = false; + if(m_isinit) + { + if(SDL_PollEvent(&m_private->m_event)){ + switch(m_private->m_event.type) + { + case SDL_JOYBUTTONUP: + result = true; + break; + } + } + } + return result; +} + + +bool SCA_Joystick::GetJoyHatMotion() +{ + bool result = false; + if(m_isinit){ + if(SDL_PollEvent(&m_private->m_event)){ + switch(m_private->m_event.type) + { + case SDL_JOYHATMOTION: + result = true; + break; + } + } + } + return 0; +} + + int SCA_Joystick::GetNumberOfAxes() { int number; @@ -235,46 +334,42 @@ int SCA_Joystick::GetNumberOfHats() return -1; } -bool SCA_Joystick::CreateJoystickDevice(void) +bool SCA_Joystick::pCreateJoystickDevice() { if(m_isinit == false){ - if (m_joyindex>=SDL_NumJoysticks()) { - // don't print a message, because this is done anyway - //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){ + echo("Error-Initializing-SDL: " << SDL_GetError()); + return false; + } + if(SDL_NumJoysticks() > 0){ + for(int i=0; im_joystick = SDL_JoystickOpen(i); + SDL_JoystickEventState(SDL_ENABLE); + m_numjoys = i; + } + echo("Joystick-initialized"); + m_isinit = true; + return true; + }else{ + echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); return false; } - - m_private->m_joystick = SDL_JoystickOpen(m_joyindex); - SDL_JoystickEventState(SDL_ENABLE); - - echo("Joystick " << m_joyindex << " initialized"); - m_isinit = true; } - return true; + return false; } -void SCA_Joystick::DestroyJoystickDevice(void) +void SCA_Joystick::pDestroyJoystickDevice() { - if (m_isinit){ - if(SDL_JoystickOpened(m_joyindex)){ - echo("Closing-joystick " << m_joyindex); + echo("Closing-"); + for(int i=0; im_joystick); } - m_isinit = false; } + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ); } -int SCA_Joystick::Connected(void) -{ - if (m_isinit){ - if(SDL_JoystickOpened(m_joyindex)){ - return 1; - } - } - - return 0; -} void SCA_Joystick::pFillAxes() { diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h index bcbb43241c2..1e853070b09 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h @@ -1,37 +1,72 @@ /** + * ***** 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): snailrose. + * + * ***** END GPL LICENSE BLOCK ***** + */ #ifndef _SCA_JOYSTICK_H_ + #define _SCA_JOYSTICK_H_ + + #include "SCA_JoystickDefines.h" -#include "SDL.h" + + + + /* + * Basic Joystick class * I will make this class a singleton because there should be only one joystick * even if there are more than one scene using it and count how many scene are using it. @@ -41,7 +76,7 @@ class SCA_Joystick { - static SCA_Joystick *m_instance[JOYINDEX_MAX]; + static SCA_Joystick *m_instance; static int m_refCount; class PrivateData; @@ -50,135 +85,226 @@ class SCA_Joystick int m_joyindex; + /*! + + * the number of avail joysticks + + */ + + int m_numjoys; + /* + *support for 2 axes + */ int m_axis10,m_axis11; + int m_axis20,m_axis21; - /* + /* + * Precision or range of the axes + */ + int m_prec; /* + * multiple axis values stored here + */ + int m_axisnum; + int m_axisvalue; /* + * max # of axes avail + */ + /*disabled + int m_axismax; + */ /* + * button values stored here + */ + int m_buttonnum; /* + * max # of buttons avail + */ int m_buttonmax; + /* + * hat values stored here + */ + int m_hatnum; + int m_hatdir; /* * max # of hats avail + disabled + int m_hatmax; + */ + /* is the joystick initialized ?*/ + bool m_isinit; + /* is triggered */ + bool m_istrig; /* - * event callbacks - */ - void OnAxisMotion(SDL_Event *sdl_event); - void OnHatMotion(SDL_Event *sdl_event); - void OnButtonUp(SDL_Event *sdl_event); - void OnButtonDown(SDL_Event *sdl_event); - void OnNothing(SDL_Event *sdl_event); - void OnBallMotion(SDL_Event *sdl_event){} - /* * Open the joystick + */ - bool CreateJoystickDevice(void); + + bool pCreateJoystickDevice(void); /* + * Close the joystick + */ - void DestroyJoystickDevice(void); + + void pDestroyJoystickDevice(void); + + /* - * fills the axis mnember values + + * event callbacks + */ + + void OnAxisMotion(void); + + void OnHatMotion(void); + + void OnButtonUp(void); + + void OnButtonDown(void); + + void OnNothing(void); + + void OnBallMotion(void){} + + /* + + * fills the axis mnember values + + */ + void pFillAxes(void); + + + void pFillButtons(void); /* + * returns m_axis10,m_axis11... + */ + int pGetAxis(int axisnum, int udlr); - + /* + * gets the current button + */ int pGetButtonPress(int button); /* + * returns if no button is pressed + */ + int pGetButtonRelease(int button); /* + * gets the current hat direction + */ + int pGetHat(int direction); - SCA_Joystick(short int index); + SCA_Joystick(); ~SCA_Joystick(); + bool CreateJoystickDevice(void); + + void DestroyJoystickDevice(void); + + public: - static SCA_Joystick *GetInstance( short int joyindex ); - static void HandleEvents( void ); + static SCA_Joystick *GetInstance(); + void ReleaseInstance(); + void HandleEvents(); + /* + */ bool aUpAxisIsPositive(int axis); + bool aDownAxisIsPositive(int axis); + bool aLeftAxisIsPositive(int axis); + bool aRightAxisIsPositive(int axis); + bool aButtonPressIsPositive(int button); + bool aButtonReleaseIsPositive(int button); + bool aHatIsPositive(int dir); /* + * precision is default '3200' which is overridden by input + */ void cSetPrecision(int val); + + int GetAxis10(void){ return m_axis10; @@ -186,48 +312,80 @@ public: } int GetAxis11(void){ + return m_axis11; + } int GetAxis20(void){ + return m_axis20; + } int GetAxis21(void){ + return m_axis21; + } int GetButton(void){ + return m_buttonnum; + } int GetHat(void){ + return m_hatdir; + } int GetThreshold(void){ + return m_prec; + } bool IsTrig(void){ + return m_istrig; + } + + /* + + * returns true if an event is being processed + + */ + + bool GetJoyAxisMotion(void); + + bool GetJoyButtonPress(void); + + bool GetJoyButtonRelease(void); + + bool GetJoyHatMotion(void); + + /* + * returns the # of... + */ int GetNumberOfAxes(void); + int GetNumberOfButtons(void); + int GetNumberOfHats(void); + - /* - * Test if the joystick is connected - */ - int Connected(void); + }; -void Joystick_HandleEvents( void ); + #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h index 73ffe1406d9..15a421188b9 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h @@ -38,6 +38,12 @@ #define echo(x) std::cout << x << std::endl; #endif -#define JOYINDEX_MAX 8 +/* function callbacks */ +#define HANDLE_AXISMOTION(fn) ((fn)(), 0L) +#define HANDLE_HATMOTION(fn) ((fn)(), 0L) +#define HANDLE_BUTTONUP(fn) ((fn)(), 0L) +#define HANDLE_BUTTONDOWN(fn) ((fn)(), 0L) +#define HANDLE_BALLMOTION(fn) ((fn)(), 0L) +#define HANDLE_NOEVENT(fn) ((fn)(), 0L) #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp index 1e064f55397..ab523470e21 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp @@ -30,75 +30,41 @@ -void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event) +void SCA_Joystick::OnAxisMotion(void) { pFillAxes(); - m_axisnum = sdl_event->jaxis.axis; - m_axisvalue = sdl_event->jaxis.value; + m_axisnum = m_private->m_event.jaxis.axis; + m_axisvalue = m_private->m_event.jaxis.value; m_istrig = 1; } -void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event) +void SCA_Joystick::OnHatMotion(void) { - m_hatdir = sdl_event->jhat.value; - m_hatnum = sdl_event->jhat.hat; + m_hatdir = m_private->m_event.jhat.value; + m_hatnum = m_private->m_event.jhat.hat; m_istrig = 1; } -void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event) +void SCA_Joystick::OnButtonUp(void) { m_buttonnum = -2; } -void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event) +void SCA_Joystick::OnButtonDown(void) { m_buttonmax = GetNumberOfButtons(); - if(sdl_event->jbutton.button >= 1 || sdl_event->jbutton.button <= m_buttonmax) + if(m_private->m_event.jbutton.button >= 1 || m_private->m_event.jbutton.button <= m_buttonmax) { m_istrig = 1; - m_buttonnum = sdl_event->jbutton.button; + m_buttonnum = m_private->m_event.jbutton.button; } } -void SCA_Joystick::OnNothing(SDL_Event* sdl_event) +void SCA_Joystick::OnNothing(void) { m_istrig = 0; } - -/* only handle events for 1 joystick */ - -void SCA_Joystick::HandleEvents(void) -{ - SDL_Event sdl_event; - - if(SDL_PollEvent(&sdl_event)) - { - /* Note! m_instance[sdl_event.jaxis.which] - * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */ - switch(sdl_event.type) - { - case SDL_JOYAXISMOTION: - SCA_Joystick::m_instance[sdl_event.jaxis.which]->OnAxisMotion(&sdl_event); - break; - case SDL_JOYHATMOTION: - SCA_Joystick::m_instance[sdl_event.jhat.which]->OnHatMotion(&sdl_event); - break; - case SDL_JOYBUTTONUP: - SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonUp(&sdl_event); - break; - case SDL_JOYBUTTONDOWN: - SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event); - break; - case SDL_JOYBALLMOTION: - SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event); - break; - default: - printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n"); - break; - } - } -} diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h index bb6bfe2d4cc..23fad3cd55d 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h @@ -32,6 +32,10 @@ class SCA_Joystick::PrivateData { public: + /* + * SDL events structure + */ + SDL_Event m_event; /* * The Joystick */ diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile index 355ece6e8bd..b3eae5d67dc 100644 --- a/source/gameengine/GameLogic/Makefile +++ b/source/gameengine/GameLogic/Makefile @@ -42,7 +42,6 @@ CPPFLAGS += -I../Expressions CPPFLAGS += -I../Rasterizer CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include -CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += $(NAN_SDLCFLAGS) diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 9ec4ea00337..96a770a553f 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -23,8 +23,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( : SCA_IActuator(gameobj, T), m_type(type), m_flag(flag), - m_float_arg(float_arg), m_int_arg(int_arg), + m_float_arg(float_arg), m_rasterizer(rasterizer), m_rendertools(rendertools) { @@ -64,11 +64,13 @@ bool SCA_2DFilterActuator::Update() if( m_type == RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR ) { if(!m_flag) + { m_rasterizer->EnableMotionBlur(m_float_arg); + } else + { m_rasterizer->DisableMotionBlur(); - - return false; + } } else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS) { diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 0bd20117f31..8f156cc63e7 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -188,8 +188,6 @@ void SCA_IController::ApplyState(unsigned int state) for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { (*sensit)->IncLink(); - // remember that this controller just activated that sensor - (*sensit)->AddNewController(this); } SetActive(true); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index abd049e9d64..f5512664d8f 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -27,7 +27,6 @@ */ #include "SCA_ILogicBrick.h" -#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 084b1395159..f99b9b789d7 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -32,8 +32,6 @@ #include "SCA_ISensor.h" #include "SCA_EventManager.h" #include "SCA_LogicManager.h" -// needed for IsTriggered() -#include "SCA_PythonController.h" #ifdef HAVE_CONFIG_H #include @@ -134,8 +132,10 @@ void SCA_ISensor::DecLink() { } if (!m_links) { - // sensor is detached from all controllers, remove it from manager + // sensor is detached from all controllers, initialize it so that it + // is fresh as at startup when it is reattached again. UnregisterToManager(); + Init(); } } @@ -168,9 +168,7 @@ PyParentObject SCA_ISensor::Parents[] = { }; PyMethodDef SCA_ISensor::Methods[] = { {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, - METH_NOARGS, IsPositive_doc}, - {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, - METH_VARARGS, IsTriggered_doc}, + METH_VARARGS, IsPositive_doc}, {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, METH_NOARGS, GetUsePosPulseMode_doc}, {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, @@ -206,9 +204,6 @@ SCA_ISensor::_getattr(const STR_String& attr) void SCA_ISensor::RegisterToManager() { - // sensor is just activated, initialize it - Init(); - m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); m_eventmgr->RegisterSensor(this); } @@ -226,9 +221,6 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) bool result = this->Evaluate(event); if (result) { logicmgr->AddActivatedSensor(this); - // reset these counters so that pulse are synchronized with transition - m_pos_ticks = 0; - m_neg_ticks = 0; } else { /* First, the pulsing behaviour, if pulse mode is @@ -257,47 +249,19 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) } } } - if (!m_newControllers.empty()) - { - if (!IsActive() && m_level) - { - // This level sensor is connected to at least one controller that was just made - // active but it did not generate an event yet, do it now to those controllers only - for (std::vector::iterator ci=m_newControllers.begin(); - ci != m_newControllers.end(); ci++) - { - logicmgr->AddTriggeredController(*ci, this); - } - } - // clear the list. Instead of using clear, which also release the memory, - // use erase, which keeps the memory available for next time. - m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); - } } } /* Python functions: */ char SCA_ISensor::IsPositive_doc[] = "isPositive()\n" -"\tReturns whether the sensor is in an active state.\n"; -PyObject* SCA_ISensor::PyIsPositive(PyObject* self) +"\tReturns whether the sensor is registered a positive event.\n"; +PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds) { int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); } -char SCA_ISensor::IsTriggered_doc[] = -"isTriggered()\n" -"\tReturns whether the sensor has triggered the current controller.\n"; -PyObject* SCA_ISensor::PyIsTriggered(PyObject* self) -{ - // check with the current controller - int retval = 0; - if (SCA_PythonController::m_sCurrentController) - retval = SCA_PythonController::m_sCurrentController->IsTriggered(this); - return PyInt_FromLong(retval); -} - /** * getUsePulseMode: getter for the pulse mode (KX_TRUE = on) */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 0d65270dc7b..fc8f0bd0011 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -34,8 +34,6 @@ #include "SCA_ILogicBrick.h" -#include - /** * Interface Class for all logic Sensors. Implements * pulsemode,pulsefrequency */ @@ -75,9 +73,9 @@ class SCA_ISensor : public SCA_ILogicBrick /** number of connections to controller */ int m_links; - /** list of controllers that have just activated this sensor because of a state change */ - std::vector m_newControllers; - + /** Pass the activation on to the logic manager.*/ + void SignalActivation(class SCA_LogicManager* logicmgr); + public: SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, @@ -130,8 +128,6 @@ public: /** Resume sensing. */ void Resume(); - void AddNewController(class SCA_IController* controller) - { m_newControllers.push_back(controller); } void ClrLink() { m_links = 0; } void IncLink() @@ -141,8 +137,7 @@ public: { return !m_links; } /* Python functions: */ - KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); - KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered); + KX_PYMETHOD_DOC(SCA_ISensor,IsPositive); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode); KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency); diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index a86770a6e0a..8ff28ba0b51 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -40,48 +40,35 @@ SCA_JoystickManager::SCA_JoystickManager(class SCA_LogicManager* logicmgr) : SCA_EventManager(JOY_EVENTMGR), m_logicmgr(logicmgr) { - int i; - for (i=0; iReleaseInstance(); - } + m_joystick->ReleaseInstance(); } void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - if (m_sensors.size()==0) { - return; - } - else { - set::iterator it; - - SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */ - - for (it = m_sensors.begin(); it != m_sensors.end(); it++) + set::iterator it; + for (it = m_sensors.begin(); it != m_sensors.end(); it++) + { + SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); + if(!joysensor->IsSuspended()) { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); - if(!joysensor->IsSuspended()) - { - joysensor->Activate(m_logicmgr, NULL); - } + m_joystick->HandleEvents(); + joysensor->Activate(m_logicmgr, NULL); } } } -SCA_Joystick *SCA_JoystickManager::GetJoystickDevice( short int joyindex) +SCA_Joystick *SCA_JoystickManager::GetJoystickDevice() { /* *Return the instance of SCA_Joystick for use */ - return m_joystick[joyindex]; + return m_joystick; } diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.h b/source/gameengine/GameLogic/SCA_JoystickManager.h index d3a7ac95bea..f2bb27965fa 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.h +++ b/source/gameengine/GameLogic/SCA_JoystickManager.h @@ -40,12 +40,12 @@ class SCA_JoystickManager : public SCA_EventManager /** * SDL Joystick Class Instance */ - SCA_Joystick *m_joystick[JOYINDEX_MAX]; + SCA_Joystick *m_joystick; public: SCA_JoystickManager(class SCA_LogicManager* logicmgr); virtual ~SCA_JoystickManager(); virtual void NextFrame(double curtime,double deltatime); - SCA_Joystick* GetJoystickDevice(short int joyindex); + SCA_Joystick* GetJoystickDevice(void); }; diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 3c08710c6ce..3fb439eb25b 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -30,11 +30,8 @@ #include "SCA_EventManager.h" #include "SCA_LogicManager.h" -#include "PyObjectPlus.h" - #include - #ifdef HAVE_CONFIG_H #include #endif @@ -42,7 +39,6 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, SCA_IObject* gameobj, - short int joyindex, short int joymode, int axis, int axisf,int prec, int button, int buttonf, @@ -57,8 +53,7 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, m_hat(hat), m_hatf(hatf), m_precision(prec), - m_joymode(joymode), - m_joyindex(joyindex) + m_joymode(joymode) { /* std::cout << " axis " << m_axis << std::endl; @@ -104,13 +99,10 @@ bool SCA_JoystickSensor::IsPositiveTrigger() bool SCA_JoystickSensor::Evaluate(CValue* event) { - SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(); bool result = false; bool reset = m_reset && m_level; - if(js==NULL) - return false; - m_reset = false; switch(m_joymode) { @@ -126,7 +118,7 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) js->cSetPrecision(m_precision); if(m_axisf == 1){ if(js->aUpAxisIsPositive(m_axis)){ - m_istrig = 1; + m_istrig =1; result = true; }else{ if(m_istrig){ @@ -249,31 +241,11 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) printf("Error invalid switch statement\n"); break; } - - if (js->IsTrig()) { - /* The if below detects changes with the joystick trigger state. - * js->IsTrig() will stay true as long as the key is held. - * even though the event from SDL will only be sent once. - * (js->IsTrig() && m_istrig_lastjs) - when true it means this sensor - * had the same joystick trigger state last time, - * Setting the result false this time means it wont run the sensors - * controller every time (like a pulse sensor) - * - * This is not done with the joystick its self incase other sensors use - * it or become active. - */ - if (m_istrig_lastjs) { - result = false; - } - m_istrig_lastjs = true; - } else { + if(!js->IsTrig()){ m_istrig = 0; - m_istrig_lastjs = false; } - if (reset) result = true; - return result; } @@ -321,8 +293,6 @@ PyParentObject SCA_JoystickSensor::Parents[] = { PyMethodDef SCA_JoystickSensor::Methods[] = { - {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, GetIndex_doc}, - {"setIndex", (PyCFunction) SCA_JoystickSensor::sPySetIndex, METH_O, SetIndex_doc}, {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, GetAxis_doc}, {"setAxis", (PyCFunction) SCA_JoystickSensor::sPySetAxis, METH_VARARGS, SetAxis_doc}, {"getAxisValue", (PyCFunction) SCA_JoystickSensor::sPyGetRealAxis, METH_NOARGS, GetRealAxis_doc}, @@ -335,7 +305,6 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, NumberOfAxes_doc}, {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, NumberOfButtons_doc}, {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, NumberOfHats_doc}, - {"isConnected", (PyCFunction) SCA_JoystickSensor::sPyConnected, METH_NOARGS, Connected_doc}, {NULL,NULL} //Sentinel }; @@ -345,36 +314,14 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { } -/* get index ---------------------------------------------------------- */ -char SCA_JoystickSensor::GetIndex_doc[] = -"getIndex\n" -"\tReturns the joystick index to use.\n"; -PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) { - return PyInt_FromLong(m_joyindex); -} - - -/* set index ---------------------------------------------------------- */ -char SCA_JoystickSensor::SetIndex_doc[] = -"setIndex\n" -"\tSets the joystick index to use.\n"; -PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) { - int index = PyInt_AsLong( 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; - } - - m_joyindex = index; - Py_RETURN_NONE; -} - /* get axis ---------------------------------------------------------- */ char SCA_JoystickSensor::GetAxis_doc[] = "getAxis\n" "\tReturns the current state of the axis.\n"; -PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) { - return PyInt_FromLong(m_joyindex); +PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self, + PyObject* args, + PyObject* kwds) { + return Py_BuildValue("[ii]",m_axis, m_axisf); } @@ -382,7 +329,9 @@ PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) { char SCA_JoystickSensor::SetAxis_doc[] = "setAxis\n" "\tSets the current state of the axis.\n"; -PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { +PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, + PyObject* args, + PyObject* kwds) { int axis,axisflag; if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){ @@ -390,7 +339,7 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { } m_axis = axis; m_axisf = axisflag; - Py_RETURN_NONE; + Py_Return; } @@ -398,12 +347,16 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { char SCA_JoystickSensor::GetRealAxis_doc[] = "getAxisValue\n" "\tReturns a list of the values for each axis .\n"; -PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) { - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - if(joy) - return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); - else - return Py_BuildValue("[iiii]", 0, 0, 0, 0); +PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self, + PyObject* args, + PyObject* kwds) { + int a,b,c,d; + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); + a = joy->GetAxis10(); + b = joy->GetAxis11(); + c = joy->GetAxis20(); + d = joy->GetAxis21(); + return Py_BuildValue("[iiii]",a,b,c,d); } @@ -411,8 +364,10 @@ PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) { char SCA_JoystickSensor::GetThreshold_doc[] = "getThreshold\n" "\tReturns the threshold of the axis.\n"; -PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) { - return PyInt_FromLong(m_precision); +PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self, + PyObject* args, + PyObject* kwds) { + return Py_BuildValue("i", m_precision); } @@ -420,13 +375,15 @@ PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) { char SCA_JoystickSensor::SetThreshold_doc[] = "setThreshold\n" "\tSets the threshold of the axis.\n"; -PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) { +PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, + PyObject* args, + PyObject* kwds) { int thresh; if(!PyArg_ParseTuple(args, "i", &thresh)){ return NULL; } m_precision = thresh; - Py_RETURN_NONE; + Py_Return; } @@ -434,7 +391,9 @@ PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) { char SCA_JoystickSensor::GetButton_doc[] = "getButton\n" "\tReturns the currently pressed button.\n"; -PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) { +PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self, + PyObject* args, + PyObject* kwds) { return Py_BuildValue("[ii]",m_button, m_buttonf); } @@ -443,14 +402,16 @@ PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) { char SCA_JoystickSensor::SetButton_doc[] = "setButton\n" "\tSets the button the sensor reacts to.\n"; -PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* args ) { +PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, + PyObject* args, + PyObject* kwds) { int button,buttonflag; if(!PyArg_ParseTuple(args, "ii", &button, &buttonflag)){ return NULL; } m_button = button; m_buttonf = buttonflag; - Py_RETURN_NONE; + Py_Return; } @@ -458,7 +419,9 @@ PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* args ) { char SCA_JoystickSensor::GetHat_doc[] = "getHat\n" "\tReturns the current direction of the hat.\n"; -PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) { +PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self, + PyObject* args, + PyObject* kwds) { return Py_BuildValue("[ii]",m_hat, m_hatf); } @@ -467,14 +430,16 @@ PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) { char SCA_JoystickSensor::SetHat_doc[] = "setHat\n" "\tSets the hat the sensor reacts to.\n"; -PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) { +PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, + PyObject* args, + PyObject* kwds) { int hat,hatflag; if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){ return NULL; } m_hat = hat; m_hatf = hatflag; - Py_RETURN_NONE; + Py_Return; } @@ -482,34 +447,37 @@ PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) { char SCA_JoystickSensor::NumberOfAxes_doc[] = "getNumAxes\n" "\tReturns the number of axes .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { - 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 ); +PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self, + PyObject* args, + PyObject* kwds) { + int num; + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); + num = joy->GetNumberOfAxes(); + return Py_BuildValue("i",num); } char SCA_JoystickSensor::NumberOfButtons_doc[] = "getNumButtons\n" "\tReturns the number of buttons .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); +PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self, + PyObject* args, + PyObject* kwds) { + int num; + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); + num = joy->GetNumberOfButtons(); + return Py_BuildValue("i",num); } char SCA_JoystickSensor::NumberOfHats_doc[] = "getNumHats\n" "\tReturns the number of hats .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); -} - -char SCA_JoystickSensor::Connected_doc[] = -"getConnected\n" -"\tReturns True if a joystick is connected at this joysticks index.\n"; -PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) { - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyBool_FromLong( joy ? joy->Connected() : 0 ); +PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self, + PyObject* args, + PyObject* kwds) { + int num; + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); + num = joy->GetNumberOfHats(); + return Py_BuildValue("i",num); } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 8b74f6e0296..69068da6494 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -68,20 +68,10 @@ class SCA_JoystickSensor :public SCA_ISensor * Is an event triggered ? */ bool m_istrig; - /** - * Last trigger state for this sensors joystick, - * Otherwise it will trigger all the time - * this is used to see if the trigger state changes. - */ - bool m_istrig_lastjs; /** * The mode to determine axis,button or hat */ short int m_joymode; - /** - * Select which joystick to use - */ - short int m_joyindex; enum KX_JOYSENSORMODE { KX_JOYSENSORMODE_NODEF = 0, @@ -95,7 +85,6 @@ class SCA_JoystickSensor :public SCA_ISensor public: SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, SCA_IObject* gameobj, - short int joyindex, short int joymode, int axis, int axisf,int prec, int button, int buttonf, @@ -108,36 +97,28 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); - short int GetJoyIndex(void){ - return m_joyindex; - } - /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); - /* Joystick Index */ - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); - KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex); /* Axes*/ - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetAxis); - KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetAxis); - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetRealAxis); - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetThreshold); - KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetThreshold); + KX_PYMETHOD_DOC(SCA_JoystickSensor,GetAxis); + KX_PYMETHOD_DOC(SCA_JoystickSensor,SetAxis); + KX_PYMETHOD_DOC(SCA_JoystickSensor,GetRealAxis); + KX_PYMETHOD_DOC(SCA_JoystickSensor,GetThreshold); + KX_PYMETHOD_DOC(SCA_JoystickSensor,SetThreshold); /* Buttons */ - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButton); - KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetButton); + KX_PYMETHOD_DOC(SCA_JoystickSensor,GetButton); + KX_PYMETHOD_DOC(SCA_JoystickSensor,SetButton); /* Hats */ - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetHat); - KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetHat); + KX_PYMETHOD_DOC(SCA_JoystickSensor,GetHat); + KX_PYMETHOD_DOC(SCA_JoystickSensor,SetHat); /* number of */ - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfAxes); - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfButtons); - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats); - KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected); + KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfAxes); + KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfButtons); + KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfHats); }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index fba1162993d..a7a6fa93db4 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -505,7 +505,7 @@ PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, PyObject* kwds) { // printf("sPyIsPositive\n"); - return ((SCA_KeyboardSensor*) self)->PyIsPositive(self); + return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds); } diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index b584b37180f..91e66aea359 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -33,7 +33,6 @@ #include "SCA_IController.h" #include "SCA_IActuator.h" #include "SCA_EventManager.h" -#include "SCA_PythonController.h" #include #ifdef HAVE_CONFIG_H @@ -233,6 +232,8 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) // for this frame, look up for activated sensors, and build the collection of triggered controllers // int numsensors = this->m_activatedsensors.size(); /*unused*/ + set triggeredControllerSet; + for (vector::const_iterator is=m_activatedsensors.begin(); !(is==m_activatedsensors.end());is++) { @@ -243,28 +244,19 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) { SCA_IController* contr = *c;//controllerarray->at(c); if (contr->IsActive()) - { - m_triggeredControllerSet.insert(SmartControllerPtr(contr,0)); - // So that the controller knows which sensor has activited it. - // Only needed for the python controller though. - if (contr->GetType() == &SCA_PythonController::Type) - { - SCA_PythonController* pythonController = (SCA_PythonController*)contr; - pythonController->AddTriggeredSensor(sensor); - } - } + triggeredControllerSet.insert(SmartControllerPtr(contr,0)); } //sensor->SetActive(false); } // int numtriggered = triggeredControllerSet.size(); /*unused*/ - for (set::iterator tit=m_triggeredControllerSet.begin(); - !(tit==m_triggeredControllerSet.end());tit++) + for (set::iterator tit=triggeredControllerSet.begin(); + !(tit==triggeredControllerSet.end());tit++) { (*tit)->Trigger(this); } - m_triggeredControllerSet.clear(); + triggeredControllerSet.clear(); } @@ -390,17 +382,6 @@ void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor) } } -void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor) -{ - m_triggeredControllerSet.insert(SmartControllerPtr(controller,0)); - // so that the controller knows which sensor has activited it - // only needed for python controller - if (controller->GetType() == &SCA_PythonController::Type) - { - SCA_PythonController* pythonController = (SCA_PythonController*)controller; - pythonController->AddTriggeredSensor(sensor); - } -} void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event) diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 50383879d8f..e0d3d506702 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -99,7 +99,6 @@ class SCA_LogicManager vector m_activatedsensors; set m_activeActuators; - set m_triggeredControllerSet; map m_sensorcontrollermapje; @@ -128,7 +127,6 @@ public: void EndFrame(); void AddActivatedSensor(SCA_ISensor* sensor); void AddActiveActuator(SCA_IActuator* sensor,class CValue* event); - void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor); SCA_EventManager* FindEventManager(int eventmgrtype); void RemoveGameObject(const STR_String& gameobjname); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 6e9a0a7c6b6..f9081c90288 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -33,11 +33,8 @@ #include "SCA_LogicManager.h" #include "SCA_ISensor.h" #include "SCA_IActuator.h" -#include "PyObjectPlus.h" #include "compile.h" #include "eval.h" -#include - #ifdef HAVE_CONFIG_H #include @@ -142,14 +139,6 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */ } -int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) -{ - if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != - m_triggeredSensors.end()) - return 1; - return 0; -} - #if 0 static char* sPyGetCurrentController__doc__; #endif @@ -305,7 +294,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) // something in this dictionary and crash? PyDict_Clear(excdict); Py_DECREF(excdict); - m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end()); + m_sCurrentController = NULL; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 1b62e7ecb53..39b6c68c359 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -36,8 +36,6 @@ #include "SCA_LogicManager.h" #include "BoolValue.h" -#include - class SCA_IObject; class SCA_PythonController : public SCA_IController { @@ -49,7 +47,6 @@ class SCA_PythonController : public SCA_IController STR_String m_scriptText; STR_String m_scriptName; PyObject* m_pythondictionary; - std::vector m_triggeredSensors; public: static SCA_PythonController* m_sCurrentController; // protected !!! @@ -67,9 +64,6 @@ class SCA_PythonController : public SCA_IController void SetScriptText(const STR_String& text); void SetScriptName(const STR_String& name); void SetDictionary(PyObject* pythondictionary); - void AddTriggeredSensor(class SCA_ISensor* sensor) - { m_triggeredSensors.push_back(sensor); } - int IsTriggered(class SCA_ISensor* sensor); static char* sPyGetCurrentController__doc__; static PyObject* sPyGetCurrentController(PyObject* self); diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt index fc5912155cf..ff1040bfb40 100644 --- a/source/gameengine/GamePlayer/CMakeLists.txt +++ b/source/gameengine/GamePlayer/CMakeLists.txt @@ -25,7 +25,3 @@ # ***** END GPL LICENSE BLOCK ***** SUBDIRS(common ghost) - -IF(WITH_WEBPLUGIN) - SUBDIRS(xembed) -ENDIF(WITH_WEBPLUGIN) diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt index 0c6c4179e2d..e26f8b9d69a 100644 --- a/source/gameengine/GamePlayer/common/CMakeLists.txt +++ b/source/gameengine/GamePlayer/common/CMakeLists.txt @@ -30,6 +30,7 @@ SET(SRC GPC_Engine.cpp GPC_KeyboardDevice.cpp GPC_MouseDevice.cpp + GPC_PolygonMaterial.cpp GPC_RawImage.cpp GPC_RawLoadDotBlendArray.cpp GPC_RawLogoArrays.cpp @@ -68,7 +69,6 @@ SET(INC ../../../../source/gameengine/GamePlayer/ghost ../../../../source/blender/misc ../../../../source/blender/blenloader - ../../../../source/blender/gpu ../../../../extern/glew/include ${PYTHON_INC} ${SOLID_INC} diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 78d8eaf2aa3..8b828393c67 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -27,256 +27,141 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include + +#ifdef WIN32 +#pragma warning (disable : 4786) +#include +#endif + #include "GL/glew.h" +#include + +#include "GPC_RenderTools.h" + #include "RAS_IRenderTools.h" #include "RAS_IRasterizer.h" #include "RAS_LightObject.h" #include "RAS_ICanvas.h" #include "RAS_GLExtensionManager.h" +// next two includes/dependencies come from the shadow feature +// it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" + +#include "GPC_PolygonMaterial.h" #include "KX_PolygonMaterial.h" -#include "KX_BlenderMaterial.h" +#include "Value.h" + +//#include "KX_BlenderGL.h" // for text printing +//#include "KX_BlenderClientObject.h" +#include "STR_String.h" +#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting) + + +// Blender includes +/* This list includes only data type definitions */ +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" +#include "DNA_group_types.h" +#include "DNA_scene_types.h" +#include "DNA_camera_types.h" +#include "DNA_property_types.h" +#include "DNA_text_types.h" +#include "DNA_sensor_types.h" +#include "DNA_controller_types.h" +#include "DNA_actuator_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_bmfont.h" +#include "BKE_bmfont_types.h" +#include "BKE_main.h" + +#include "IMB_imbuf_types.h" +// End of Blender includes + +#include "KX_Scene.h" #include "KX_RayCast.h" #include "KX_IPhysicsController.h" - #include "PHY_IPhysicsEnvironment.h" - -#include "STR_String.h" - -#include "GPU_draw.h" - -#include "BKE_bmfont.h" // for text printing -#include "BKE_bmfont_types.h" - -#include "GPC_RenderTools.h" - -unsigned int GPC_RenderTools::m_numgllights; +#include "KX_BlenderMaterial.h" GPC_RenderTools::GPC_RenderTools() { m_font = BMF_GetFont(BMF_kHelvetica10); - glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); if (m_numgllights < 8) m_numgllights = 8; } + GPC_RenderTools::~GPC_RenderTools() { } -void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) -{ - m_clientobject = NULL; - m_lastlightlayer = -1; - m_lastlighting = false; - DisableOpenGLLights(); -} void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty) { } -/* ProcessLighting performs lighting on objects. the layer is a bitfield that - * contains layer information. There are 20 'official' layers in blender. A - * light is applied on an object only when they are in the same layer. OpenGL - * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in - * a scene. */ -void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) +void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) { - if(m_lastlightlayer == layer) - return; + m_clientobject=NULL; + m_modified=true; + DisableOpenGLLights(); - m_lastlightlayer = layer; +} - bool enable = false; +int GPC_RenderTools::ProcessLighting(int layer) +{ + int result = false; - if (layer >= 0) + if (layer < 0) + { + DisableOpenGLLights(); + result = false; + } else { if (m_clientobject) - { - if (layer == RAS_LIGHT_OBJECT_LAYER) - layer = static_cast(m_clientobject)->GetLayer(); - - enable = applyLights(layer, viewmat); + { + if (applyLights(layer)) + { + EnableOpenGLLights(); + result = true; + } else + { + DisableOpenGLLights(); + result = false; + } } } - - if(enable) - EnableOpenGLLights(); - else - DisableOpenGLLights(); + return result; } void GPC_RenderTools::EnableOpenGLLights() { - if(m_lastlighting == true) - return; - glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); - - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - - m_lastlighting = true; } -void GPC_RenderTools::DisableOpenGLLights() -{ - if(m_lastlighting == false) - return; - - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - - m_lastlighting = false; -} - - -void GPC_RenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) -{ - if (m_clientobject != obj) - { - bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); - rasty->SetFrontFace(ccw); - - m_clientobject = obj; - } -} - -bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) -{ - double* const oglmatrix = (double* const) data; - MT_Point3 resultpoint(result->m_hitPoint); - MT_Vector3 resultnormal(result->m_hitNormal); - MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); - MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); - left = (dir.cross(resultnormal)).safe_normalized(); - // for the up vector, we take the 'resultnormal' returned by the physics - - double maat[16]={ - left[0], left[1], left[2], 0, - dir[0], dir[1], dir[2], 0, - resultnormal[0],resultnormal[1],resultnormal[2], 0, - 0, 0, 0, 1}; - glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); - //glMultMatrixd(oglmatrix); - glMultMatrixd(maat); - return true; -} - -void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) -{ - /* FIXME: - blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const - MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. - - Program received signal SIGABRT, Aborted. - [Switching to Thread 16384 (LWP 1519)] - 0x40477571 in kill () from /lib/libc.so.6 - (gdb) bt - #7 0x08334368 in MT_Vector3::normalized() const () - #8 0x0833e6ec in GPC_RenderTools::applyTransform(RAS_IRasterizer*, double*, int) () - */ - - if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || - objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) - { - // rotate the billboard/halo - //page 360/361 3D Game Engine Design, David Eberly for a discussion - // on screen aligned and axis aligned billboards - // assumed is that the preprocessor transformed all billboard polygons - // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) - // when new parenting for objects is done, this rotation - // will be moved into the object - - MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); - MT_Point3 campos = rasty->GetCameraPosition(); - MT_Vector3 dir = (campos - objpos).safe_normalized(); - MT_Vector3 up(0,0,1.0); - - KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; - // get scaling of halo object - MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); - - bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned - if (screenaligned) - { - up = (up - up.dot(dir) * dir).safe_normalized(); - } else - { - dir = (dir - up.dot(dir)*up).safe_normalized(); - } - - MT_Vector3 left = dir.normalized(); - dir = (left.cross(up)).normalized(); - - // we have calculated the row vectors, now we keep - // local scaling into account: - - left *= size[0]; - dir *= size[1]; - up *= size[2]; - double maat[16]={ - left[0], left[1],left[2], 0, - dir[0], dir[1],dir[2],0, - up[0],up[1],up[2],0, - 0,0,0,1}; - glTranslated(objpos[0],objpos[1],objpos[2]); - glMultMatrixd(maat); - - } else - { - if (objectdrawmode & RAS_IPolyMaterial::SHADOW) - { - // shadow must be cast to the ground, physics system needed here! - MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; - MT_Vector3 direction = MT_Vector3(0,0,-1); - - direction.normalize(); - direction *= 100000; - - MT_Point3 topoint = frompoint + direction; - - KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; - PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); - KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); - - KX_GameObject *parent = gameobj->GetParent(); - if (!physics_controller && parent) - physics_controller = parent->GetPhysicsController(); - if (parent) - parent->Release(); - - KX_RayCast::Callback callback(this, physics_controller, oglmatrix); - if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) - { - // couldn't find something to cast the shadow on... - glMultMatrixd(oglmatrix); - } - } else - { - - // 'normal' object - glMultMatrixd(oglmatrix); - } - } -} - - -void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height) +void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height) { STR_String tmpstr(text); int lines; @@ -349,19 +234,21 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, glDisable(GL_LIGHTING); } -/* Render Text renders text into a (series of) polygon, using a texture font, - * Each character consists of one polygon (one quad or two triangles) */ - +/** + * Copied from KX_BlenderRenderTools.cpp in KX_blenderhook + * Renders text into a (series of) polygon(s), using a texture font, + * Each character consists of one polygon (one quad or two triangles) + */ void GPC_RenderTools::RenderText( int mode, RAS_IPolyMaterial* polymat, - float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) + float v1[3], float v2[3], float v3[3], float v4[3]) { STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); struct MTFace* tface = 0; - unsigned int *col = 0; + unsigned int* col = 0; if(flag & RAS_BLENDERMAT) { KX_BlenderMaterial *bl_mat = static_cast(polymat); @@ -372,29 +259,110 @@ void GPC_RenderTools::RenderText( tface = blenderpoly->GetMTFace(); col = blenderpoly->GetMCol(); } + + BL_RenderText(mode, mytext, mytext.Length(), tface, col, v1, v2, v3, v4); +} + + + +/** + * Copied from KX_BlenderGL.cpp in KX_blenderhook + */ +void GPC_RenderTools::BL_RenderText( + int mode, + const char* textstr, + int textlen, + struct MTFace* tface, + unsigned int* col, + float v1[3],float v2[3],float v3[3],float v4[3]) +{ + struct Image* ima; + + if (mode & TF_BMFONT) { + //char string[MAX_PROPSTRING]; +// float tmat[4][4]; + int characters, index, character; + float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; + +// bProperty *prop; + + // string = "Frank van Beek"; + + characters = textlen; + + ima = (struct Image*) tface->tpage; + if (ima == NULL) { + characters = 0; + } + + if(!col) glColor3f(1.0f, 1.0f, 1.0f); + + glPushMatrix(); + for (index = 0; index < characters; index++) { + // lets calculate offset stuff + character = textstr[index]; + + // space starts at offset 1 + // character = character - ' ' + 1; + + matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + + glBegin(GL_POLYGON); + // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], ); + // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); + glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); + + if(col) BL_spack(col[0]); + // glVertex3fv(v1); + glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); + + glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); + if(col) BL_spack(col[1]); + // glVertex3fv(v2); + glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); + glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); + if(col) BL_spack(col[2]); + // glVertex3fv(v3); + glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); + + if(v4) { + // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy); + glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); + if(col) BL_spack(col[3]); + // glVertex3fv(v4); + glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); + } + glEnd(); + + glTranslatef(advance, 0.0, 0.0); + } + glPopMatrix(); + + } } -void GPC_RenderTools::PushMatrix() +RAS_IPolyMaterial* GPC_RenderTools::CreateBlenderPolyMaterial( + const STR_String &texname, + bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant, bool zsort, + int lightlayer,bool bIsTriangle,void* clientobject,void* tface) { - glPushMatrix(); -} - -void GPC_RenderTools::PopMatrix() -{ - glPopMatrix(); + assert(!"Deprecated"); +/* return new GPC_PolygonMaterial(texname, ba,matname,tile,tilexrep,tileyrep, + mode,transparant,zsort,lightlayer,bIsTriangle,clientobject,tface); + */ + return NULL; } -int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) +int GPC_RenderTools::applyLights(int objectlayer) { - // taken from blender source, incompatibility between Blender Object / GameObject - float glviewmat[16]; - unsigned int count; +// taken from blender source, incompatibility between Blender Object / GameObject + + int count; float vec[4]; - + vec[3]= 1.0; for(count=0; count m_lights; std::vector::iterator lit = m_lights.begin(); - viewmat.getValue(glviewmat); - glPushMatrix(); - glLoadMatrixf(glviewmat); for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) { RAS_LightObject* lightdata = (*lit); if (lightdata->m_layer & objectlayer) { + + glPushMatrix(); + glLoadMatrixf(m_viewmat); + + vec[0] = (*(lightdata->m_worldmatrix))(0,3); vec[1] = (*(lightdata->m_worldmatrix))(1,3); vec[2] = (*(lightdata->m_worldmatrix))(2,3); vec[3] = 1; + if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) { vec[0] = (*(lightdata->m_worldmatrix))(0,2); @@ -472,16 +443,142 @@ int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) } glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec); glEnable((GLenum)(GL_LIGHT0+count)); - + count++; + + glPopMatrix(); } } - glPopMatrix(); return count; } +void GPC_RenderTools::SetClientObject(void* obj) +{ + if (m_clientobject != obj) + { + if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) + { + glFrontFace(GL_CCW); + } else + { + glFrontFace(GL_CW); + } + m_clientobject = obj; + m_modified = true; + } +} + +bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +{ + double* const oglmatrix = (double* const) data; + MT_Point3 resultpoint(hit_point); + MT_Vector3 resultnormal(hit_normal); + MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); + MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); + left = (dir.cross(resultnormal)).safe_normalized(); + // for the up vector, we take the 'resultnormal' returned by the physics + + double maat[16]={ + left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + resultnormal[0],resultnormal[1],resultnormal[2], 0, + 0, 0, 0, 1}; + glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); + //glMultMatrixd(oglmatrix); + glMultMatrixd(maat); + return true; +} + +void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) +{ + if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || + objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) + { + // rotate the billboard/halo + //page 360/361 3D Game Engine Design, David Eberly for a discussion + // on screen aligned and axis aligned billboards + // assumed is that the preprocessor transformed all billboard polygons + // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) + // when new parenting for objects is done, this rotation + // will be moved into the object + + MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); + MT_Point3 campos = rasty->GetCameraPosition(); + MT_Vector3 dir = (campos - objpos).safe_normalized(); + MT_Vector3 up(0,0,1.0); + + KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; + // get scaling of halo object + MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); + + bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned + if (screenaligned) + { + up = (up - up.dot(dir) * dir).safe_normalized(); + } else + { + dir = (dir - up.dot(dir)*up).safe_normalized(); + } + + MT_Vector3 left = dir.normalized(); + dir = (left.cross(up)).normalized(); + + // we have calculated the row vectors, now we keep + // local scaling into account: + + left *= size[0]; + dir *= size[1]; + up *= size[2]; + double maat[16]={ + left[0], left[1],left[2], 0, + dir[0], dir[1],dir[2],0, + up[0],up[1],up[2],0, + 0,0,0,1}; + glTranslated(objpos[0],objpos[1],objpos[2]); + glMultMatrixd(maat); + + } else + { + if (objectdrawmode & RAS_IPolyMaterial::SHADOW) + { + // shadow must be cast to the ground, physics system needed here! + MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); + KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; + MT_Vector3 direction = MT_Vector3(0,0,-1); + + direction.normalize(); + direction *= 100000; + + MT_Point3 topoint = frompoint + direction; + + KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; + PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); + KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); + + KX_GameObject *parent = gameobj->GetParent(); + if (!physics_controller && parent) + physics_controller = parent->GetPhysicsController(); + if (parent) + parent->Release(); + + MT_Point3 resultpoint; + MT_Vector3 resultnormal; + if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this, oglmatrix))) + { + // couldn't find something to cast the shadow on... + glMultMatrixd(oglmatrix); + } + } else + { + + // 'normal' object + glMultMatrixd(oglmatrix); + } + } +} + void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) { int state = rasterizer->GetMotionBlurState(); @@ -512,6 +609,7 @@ void GPC_RenderTools::Update2DFilter(vector& propNames, void* gameOb void GPC_RenderTools::Render2DFilters(RAS_ICanvas* canvas) { - m_filtermanager.RenderFilters(canvas); + m_filtermanager.RenderFilters( canvas); } +unsigned int GPC_RenderTools::m_numgllights; diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 382956e73ea..8fae3d2b305 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -31,67 +31,114 @@ #define __GPC_RENDERTOOLS_H #ifdef WIN32 -// don't show stl-warnings -#pragma warning (disable:4786) -#include + #include #endif // WIN32 +#include "GL/glew.h" + #include "RAS_IRenderTools.h" #include "BMF_Api.h" struct KX_ClientObjectInfo; -class KX_RayCast; -/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which - * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon) - * text, lighting. - * - * Most of this code is duplicated in KX_BlenderRenderTools, so this should be - * moved to some common location to avoid duplication. */ class GPC_RenderTools : public RAS_IRenderTools { - int m_lastlightlayer; - bool m_lastlighting; - static unsigned int m_numgllights; - - BMF_Font* m_font; - public: - GPC_RenderTools(); - virtual ~GPC_RenderTools(); + GPC_RenderTools(); + virtual ~GPC_RenderTools(); - void EndFrame(RAS_IRasterizer* rasty); - void BeginFrame(RAS_IRasterizer* rasty); + virtual void EndFrame(RAS_IRasterizer* rasty); + virtual void BeginFrame(RAS_IRasterizer* rasty); - void EnableOpenGLLights(); - void DisableOpenGLLights(); - void ProcessLighting(int layer, const MT_Transform& viewmat); + void DisableOpenGLLights() + { + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + } - /* @attention mode is ignored here */ - void RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height); - void RenderText(int mode, - class RAS_IPolyMaterial* polymat, - float v1[3], - float v2[3], - float v3[3], - float v4[3], - int glattrib); + void EnableOpenGLLights(); - void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); - int applyLights(int objectlayer, const MT_Transform& viewmat); + int ProcessLighting(int layer); - void PushMatrix(); - void PopMatrix(); + void Perspective(int a, int width, int height, float mat[4][4], float viewmat[4][4]) + { + if(a== 0) + { + glMatrixMode(GL_PROJECTION); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } + else + { + if(a== 1) + { + glMatrixMode(GL_PROJECTION); + glMatrixMode(GL_MODELVIEW); + } + } + } - bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); - bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } + /** + * @attention mode is ignored here + */ + virtual void RenderText2D( + RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height); + + /** + * Renders text into a (series of) polygon(s), using a texture font, + * Each character consists of one polygon (one quad or two triangles) + */ + virtual void RenderText( + int mode, + RAS_IPolyMaterial* polymat, + float v1[3], + float v2[3], + float v3[3], + float v4[3]); + + void Render(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode) + { + glPopMatrix(); + glPushMatrix(); + glMultMatrixd(oglmatrix); + } + + void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); + + virtual void PushMatrix() + { + glPushMatrix(); + } + + virtual void PopMatrix() + { + glPopMatrix(); + } + + virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial( + const STR_String &texname, + bool ba, + const STR_String& matname, + int tile, + int tilexrep,int tileyrep, + int mode, + bool transparant, + bool zsort, + int lightlayer, + bool bIsTriangle, + void* clientobject, + void* tface); + + int applyLights(int objectlayer); + + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); virtual void MotionBlur(RAS_IRasterizer* rasterizer); @@ -99,7 +146,28 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); - virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); + virtual void SetClientObject(void* obj); + +protected: + /** + * Copied from KX_BlenderGL.cpp in KX_blenderhook + */ + void BL_RenderText( + int mode, + const char* textstr, + int textlen, + struct MTFace* tface, + unsigned int* col, + float v1[3],float v2[3],float v3[3],float v4[3]); + void BL_spack(unsigned int ucol) + { + char *cp = (char *)&ucol; + glColor3ub(cp[3], cp[2], cp[1]); + } + + + BMF_Font* m_font; + static unsigned int m_numgllights; }; #endif // __GPC_RENDERTOOLS_H diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile index 6a12e659be6..19d792ddbdb 100644 --- a/source/gameengine/GamePlayer/common/Makefile +++ b/source/gameengine/GamePlayer/common/Makefile @@ -43,7 +43,6 @@ CPPFLAGS += -I../../../blender/blenloader CPPFLAGS += -I../../../blender/blenlib CPPFLAGS += -I../../../blender/imbuf CPPFLAGS += -I../../../blender/makesdna -CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include @@ -73,6 +72,10 @@ CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer CPPFLAGS += -I../../../gameengine/Physics/Sumo CPPFLAGS += -I../../../gameengine/Physics/common +ifeq ($(WITH_BF_GLEXT),true) + CPPFLAGS += -DWITH_GLEXT +endif + ############################### SOURCEDIR = source/gameengine/GamePlayer/common diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index 30f20a670d3..3b2367d2592 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -8,6 +8,7 @@ source_files = ['bmfont.cpp', 'GPC_Engine.cpp', 'GPC_KeyboardDevice.cpp', 'GPC_MouseDevice.cpp', + 'GPC_PolygonMaterial.cpp', 'GPC_RawImage.cpp', 'GPC_RawLoadDotBlendArray.cpp', 'GPC_RawLogoArrays.cpp', @@ -45,7 +46,6 @@ incs = ['.', '#source/gameengine/GamePlayer/ghost', '#source/blender/misc', '#source/blender/blenloader', - '#source/blender/gpu', '#extern/glew/include'] #This is all plugin stuff! diff --git a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h index e5ed7f39811..fee729a84ac 100644 --- a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h +++ b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h @@ -37,9 +37,9 @@ class GPU_PolygonMaterial : public BP_PolygonMaterial public: GPUPolygonMaterial(const STR_String& texname, bool ba,const STR_String& matname, int tile, int tileXrep, int tileYrep, int mode, int transparant, - int lightlayer,,void* tpage) : + int lightlayer,bool bIsTriangle,void* clientobject,void* tpage) : BP_PolygonMaterial(texname, ba,matname, tile, tileXrep, tileYrep, - mode, transparant, lightlayer), + mode, transparant, lightlayer, bIsTriangle, clientobject), m_tface(tpage) { } diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index 5e0ca93ac06..d9f0675001f 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -64,7 +64,6 @@ SET(INC ../../../../source/gameengine/GamePlayer/common ../../../../source/blender/misc ../../../../source/blender/blenloader - ../../../../source/blender/gpu ../../../../extern/solid ../../../../extern/glew/include ${PYTHON_INC} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 580c80ee0a5..f859193ef7a 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -38,7 +38,6 @@ #endif #include "GL/glew.h" -#include "GPU_extensions.h" #include "GPG_Application.h" @@ -98,16 +97,16 @@ extern "C" #include "GHOST_IEventConsumer.h" #include "GHOST_IWindow.h" #include "GHOST_Rect.h" +#include "marshal.h" static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time); static GHOST_ISystem* fSystem = 0; static const int kTimerFreq = 10; -GPG_Application::GPG_Application(GHOST_ISystem* system) - : m_startSceneName(""), - m_startScene(0), - m_maggie(0), +GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName) + : m_startSceneName(startSceneName), + m_maggie(maggie), m_exitRequested(0), m_system(system), m_mainWindow(0), @@ -128,8 +127,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) m_blendermat(0), m_blenderglslmat(0), m_pyGlobalDictString(0), - m_pyGlobalDictString_Length(0), - m_isEmbedded(false) + m_pyGlobalDictString_Length(0) { fSystem = system; } @@ -144,16 +142,15 @@ GPG_Application::~GPG_Application(void) -bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene) +bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSceneName) { bool result = false; - if (maggie != NULL && scene != NULL) + if (maggie != NULL && startSceneName != "") { - G.scene = scene; + G.scene = (Scene*)maggie->scene.first; m_maggie = maggie; - m_startSceneName = scene->id.name+2; - m_startScene = scene; + m_startSceneName = startSceneName; result = true; } @@ -325,26 +322,6 @@ bool GPG_Application::startWindow(STR_String& title, return success; } -bool GPG_Application::startEmbeddedWindow(STR_String& title, - const GHOST_TEmbedderWindowID parentWindow, - const bool stereoVisual, - const int stereoMode) { - - m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, stereoVisual, parentWindow); - - if (!m_mainWindow) { - printf("error: could not create main window\n"); - exit(-1); - } - m_isEmbedded = true; - - bool success = initEngine(m_mainWindow, stereoMode); - if (success) { - success = startEngine(); - } - return success; -} bool GPG_Application::startFullScreen( @@ -503,7 +480,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) { if (!m_engineInitialized) { - GPU_extensions_init(); + glewInit(); bgl::InitExtensions(true); // get and set the preferences @@ -522,16 +499,13 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); - bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DISPLAY_LISTS) != 0); - - if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) - m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); - - if(GPU_extensions_minimum_support()) - m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); - else if(G.fileflags & G_FILE_GAME_MAT_GLSL) - m_blendermat = false; + bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0); + if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) { + int gameflag =(G.fileflags & G_FILE_GAME_MAT); + m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0); + } + // create the canvas, rasterizer and rendertools m_canvas = new GPG_Canvas(window); if (!m_canvas) @@ -654,34 +628,41 @@ bool GPG_Application::startEngine(void) { STR_String startscenename = m_startSceneName.Ptr(); m_ketsjiengine->SetSceneConverter(m_sceneconverter); - + // if (always_use_expand_framing) // sceneconverter->SetAlwaysUseExpandFraming(true); - if(m_blendermat && (G.fileflags & G_FILE_GAME_MAT)) + if(m_blendermat) m_sceneconverter->SetMaterials(true); - if(m_blenderglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) + if(m_blenderglslmat) m_sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(m_keyboard, m_mouse, m_networkdevice, m_audiodevice, - startscenename, - m_startScene); + startscenename); // some python things PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest); m_ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(m_rasterizer, m_canvas); - PyObject *gameLogic = initGameLogic(m_ketsjiengine, startscene); + PyObject *gameLogic = initGameLogic(startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); initMathutils(); /* Restore the dict */ - loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); + if (m_pyGlobalDictString) { + PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length); + if (pyGlobalDict) { + PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. + } else { + PyErr_Clear(); + printf("Error could not marshall string\n"); + } + } m_sceneconverter->ConvertScene( startscenename, @@ -719,12 +700,30 @@ bool GPG_Application::startEngine(void) void GPG_Application::stopEngine() { // get the python dict and convert to a string for future use - char *marshal_buffer; - m_pyGlobalDictString_Length = saveGamePythonConfig(&marshal_buffer); - if (m_pyGlobalDictString_Length) { - m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); - memcpy(m_pyGlobalDictString, marshal_buffer, m_pyGlobalDictString_Length); - } + { + SetPyGlobalDictMarshal(NULL, 0); + + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + if (gameLogic) { + PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module + if (pyGlobalDict) { + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 + if (pyGlobalDictMarshal) { + m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal); + PyObject_Print(pyGlobalDictMarshal, stderr, 0); + m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); + memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length); + } else { + printf("Error, GameLogic.globalDict could not be marshal'd\n"); + } + } else { + printf("Error, GameLogic.globalDict was removed\n"); + } + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + } + // when exiting the mainloop exitGamePythonScripting(); @@ -745,8 +744,6 @@ void GPG_Application::stopEngine() void GPG_Application::exitEngine() { - GPU_extensions_exit(); - if (m_ketsjiengine) { stopEngine(); @@ -873,7 +870,7 @@ bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown) GHOST_TEventKeyData* keyData = static_cast(eventData); //no need for this test //if (fSystem->getFullScreen()) { - if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc && !m_isEmbedded) { + if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc) { m_exitRequested = KX_EXIT_REQUEST_OUTSIDE; } //} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 7fc369fc0fd..31f5eb75e52 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -50,19 +50,17 @@ class GPG_Canvas; class GPG_KeyboardDevice; class GPG_System; struct Main; -struct Scene; class GPG_Application : public GHOST_IEventConsumer { public: - GPG_Application(GHOST_ISystem* system); + GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName); ~GPG_Application(void); - bool SetGameEngineData(struct Main* maggie, struct Scene* scene); + bool SetGameEngineData(struct Main* maggie,STR_String startSceneName); bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight, const bool stereoVisual, const int stereoMode); bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); - bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window, const bool stereoVisual, const int stereoMode); #ifdef WIN32 bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode); @@ -125,7 +123,6 @@ protected: /* The game data */ STR_String m_startSceneName; - struct Scene* m_startScene; struct Main* m_maggie; /* Exit state. */ @@ -144,8 +141,6 @@ protected: bool m_engineInitialized; /** Engine state. */ bool m_engineRunning; - /** Running on embedded window */ - bool m_isEmbedded; /** the gameengine itself */ KX_KetsjiEngine* m_ketsjiengine; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index c4e738c1896..26a85128025 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -54,7 +54,6 @@ extern "C" #endif // __cplusplus #include "BKE_global.h" #include "BKE_icons.h" -#include "BKE_node.h" #include "BLI_blenlib.h" #include "DNA_scene_types.h" #include "BLO_readfile.h" @@ -65,15 +64,13 @@ extern "C" #ifdef __cplusplus } #endif // __cplusplus - -#include "GPU_draw.h" - /********************************** * End Blender include block **********************************/ #include "SYS_System.h" #include "GPG_Application.h" +#include "GPC_PolygonMaterial.h" #include "GHOST_ISystem.h" #include "RAS_IRasterizer.h" @@ -179,9 +176,6 @@ void usage(char* program) printf(" anaglyph (Red-Blue glasses)\n"); printf(" vinterlace (Vertical interlace for autostereo display)\n"); printf(" depending on the type of stereo you want\n"); -#ifndef _WIN32 - printf(" -i: parent windows ID \n"); -#endif #ifdef _WIN32 printf(" -c: keep console window open\n"); #endif @@ -199,8 +193,7 @@ void usage(char* program) printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } -static void get_filename(int argc, char **argv, char *filename) -{ +char *get_filename(int argc, char **argv) { #ifdef __APPLE__ /* On Mac we park the game file (called game.blend) in the application bundle. * The executable is located in the bundle as well. @@ -208,18 +201,22 @@ static void get_filename(int argc, char **argv, char *filename) */ int srclen = ::strlen(argv[0]); int len = 0; - char *gamefile = NULL; + char *filename = NULL; - filename[0] = '\0'; - if (argc > 1) { if (BLI_exists(argv[argc-1])) { - BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); + len = ::strlen(argv[argc-1]); + filename = new char [len + 1]; + ::strcpy(filename, argv[argc-1]); + return(filename); } if (::strncmp(argv[argc-1], "-psn_", 5)==0) { static char firstfilebuf[512]; if (GHOST_HACK_getFirstFile(firstfilebuf)) { - BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE); + len = ::strlen(firstfilebuf); + filename = new char [len + 1]; + ::strcpy(filename, firstfilebuf); + return(filename); } } } @@ -227,26 +224,23 @@ static void get_filename(int argc, char **argv, char *filename) srclen -= ::strlen("MacOS/blenderplayer"); if (srclen > 0) { len = srclen + ::strlen("Resources/game.blend"); - gamefile = new char [len + 1]; - ::strcpy(gamefile, argv[0]); - ::strcpy(gamefile + srclen, "Resources/game.blend"); + filename = new char [len + 1]; + ::strcpy(filename, argv[0]); + ::strcpy(filename + srclen, "Resources/game.blend"); //::printf("looking for file: %s\n", filename); - if (BLI_exists(gamefile)) - BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE); - - delete gamefile; + if (BLI_exists(filename)) { + return (filename); + } } + return(NULL); #else - filename[0] = '\0'; - - if(argc > 1) - BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); + return (argc>1)?argv[argc-1]:NULL; #endif // !_APPLE } -static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL) { +static BlendFileData *load_game_data(char *progname, char *filename = NULL) { BlendReadError error; BlendFileData *bfd = NULL; @@ -288,7 +282,7 @@ int main(int argc, char** argv) bool fullScreenParFound = false; bool windowParFound = false; bool closeConsole = true; - RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; + RAS_IRasterizer::StereoMode stereomode; bool stereoWindow = false; bool stereoParFound = false; int windowLeft = 100; @@ -301,9 +295,6 @@ int main(int argc, char** argv) int fullScreenFrequency = 60; char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */ int pyGlobalDictString_Length = 0; - GHOST_TEmbedderWindowID parentWindow = 0; - - #ifdef __linux__ #ifdef __alpha__ @@ -332,8 +323,6 @@ int main(int argc, char** argv) ::DisposeNibReference(nibRef); */ #endif // __APPLE__ - - init_nodesystem(); GEN_init_messaging_system(); @@ -466,16 +455,6 @@ int main(int argc, char** argv) usage(argv[0]); return 0; break; -#ifndef _WIN32 - case 'i': - i++; - if ( (i + 1) < argc ) - parentWindow = atoi(argv[i++]); -#ifndef NDEBUG - printf("XWindows ID = %d\n", parentWindow); -#endif //NDEBUG - -#endif // _WIN32 case 'c': i++; closeConsole = false; @@ -546,19 +525,21 @@ int main(int argc, char** argv) return 0; } + if (!stereoParFound) stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; + #ifdef WIN32 if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION) #endif { #ifdef __APPLE__ //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1); - //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); + SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); //fullScreen = false; // Can't use full screen #endif if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) { - GPU_set_mipmap(0); + GPC_PolygonMaterial::SetMipMappingEnabled(0); } // Create the system @@ -580,15 +561,11 @@ int main(int argc, char** argv) { int exitcode = KX_EXIT_REQUEST_NO_REQUEST; STR_String exitstring = ""; - GPG_Application app(system); + GPG_Application app(system, NULL, exitstring); bool firstTimeRunning = true; - char filename[FILE_MAXDIR + FILE_MAXFILE]; + char *filename = get_filename(argc, argv); char *titlename; char pathname[160]; - - get_filename(argc, argv, filename); - if(filename[0]) - BLI_convertstringcwd(filename); do { @@ -620,7 +597,7 @@ int main(int argc, char** argv) } else { - bfd = load_game_data(bprogname, filename[0]? filename: NULL); + bfd = load_game_data(argv[0], filename); } //::printf("game data loaded from %s\n", filename); @@ -642,7 +619,7 @@ int main(int argc, char** argv) #endif // WIN32 Main *maggie = bfd->main; Scene *scene = bfd->curscene; - G.main = maggie; + char *startscenename = scene->id.name + 2; G.fileflags = bfd->fileflags; //Seg Fault; icon.c gIcons == 0 @@ -684,7 +661,7 @@ int main(int argc, char** argv) } // GPG_Application app (system, maggie, startscenename); - app.SetGameEngineData(maggie, scene); + app.SetGameEngineData(maggie, startscenename); if (firstTimeRunning) { @@ -752,10 +729,7 @@ int main(int argc, char** argv) else #endif { - if (parentWindow != 0) - app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode); - else - app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, + app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, stereoWindow, stereomode); } } @@ -789,6 +763,12 @@ int main(int argc, char** argv) pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength(); BLO_blendfiledata_free(bfd); + +#ifdef __APPLE__ + if (filename) { + delete [] filename; + } +#endif // __APPLE__ } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); } @@ -804,8 +784,6 @@ int main(int argc, char** argv) } } - free_nodesystem(); - if (pyGlobalDictString) { free(pyGlobalDictString); pyGlobalDictString = NULL; diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile index 0b187791734..13940ac3fc8 100644 --- a/source/gameengine/GamePlayer/ghost/Makefile +++ b/source/gameengine/GamePlayer/ghost/Makefile @@ -69,7 +69,6 @@ CPPFLAGS += -I../../../blender/blenloader CPPFLAGS += -I../../../blender/imbuf CPPFLAGS += -I../../../blender/makesdna CPPFLAGS += -I../../../blender/readblenfile -CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../../gameengine/BlenderRoutines @@ -81,3 +80,7 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_GHOST)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +ifeq ($(WITH_BF_GLEXT),true) + CPPFLAGS += -DWITH_GLEXT +endif + diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 33cf07b6211..f3cce6c7443 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -40,7 +40,6 @@ incs = ['.', '#source/gameengine/GamePlayer/common', '#source/blender/misc', '#source/blender/blenloader', - '#source/blender/gpu', '#extern/glew/include'] incs += Split(env['BF_PYTHON_INC']) @@ -49,5 +48,8 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': cflags = ['/GR'] +if env['WITH_BF_GLEXT'] == 1: + env['CPPFLAGS'].append('-DWITH_GLEXT') + env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 8ec463be6ff..a9a0771936c 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -9,64 +9,108 @@ #include "BL_BlenderShader.h" #include "BL_Material.h" +#ifdef BLENDER_GLSL #include "GPU_extensions.h" #include "GPU_material.h" +#endif #include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" -BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) -: - mScene(scene), - mMat(ma), - mLightLayer(lightlayer) + /* this is evil, but we need the scene to create materials with + * lights from the correct scene .. */ +static struct Scene *GetSceneForName(const STR_String& scenename) { - mBlenderScene = scene->GetBlenderScene(); - mBlendMode = GPU_BLEND_SOLID; + Scene *sce; - if(mMat) - GPU_material_from_blender(mBlenderScene, mMat); -} + for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next) + if (scenename == (sce->id.name+2)) + return sce; -BL_BlenderShader::~BL_BlenderShader() -{ - if(mMat && GPU_material_from_blender(mBlenderScene, mMat)) - GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); + return (Scene*)G.main->scene.first; } bool BL_BlenderShader::Ok() { - return VerifyShader(); +#ifdef BLENDER_GLSL + VerifyShader(); + + return (mMat && mMat->gpumaterial); +#else + return 0; +#endif +} + +BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) +: +#ifdef BLENDER_GLSL + mScene(scene), + mMat(ma), + mGPUMat(NULL), +#endif + mBound(false), + mLightLayer(lightlayer) +{ +#ifdef BLENDER_GLSL + mBlenderScene = GetSceneForName(scene->GetName()); + mBlendMode = GPU_BLEND_SOLID; + + if(mMat) { + GPU_material_from_blender(mBlenderScene, mMat); + mGPUMat = mMat->gpumaterial; + } +#endif +} + +BL_BlenderShader::~BL_BlenderShader() +{ +#ifdef BLENDER_GLSL + if(mMat && mMat->gpumaterial) + GPU_material_unbind(mMat->gpumaterial); +#endif } bool BL_BlenderShader::VerifyShader() { - if(mMat) - return (GPU_material_from_blender(mBlenderScene, mMat) != 0); - else - return false; +#ifdef BLENDER_GLSL + if(mMat && !mMat->gpumaterial) + GPU_material_from_blender(mBlenderScene, mMat); + + mGPUMat = mMat->gpumaterial; + + return (mMat && mGPUMat); +#else + return false; +#endif } -void BL_BlenderShader::SetProg(bool enable, double time) +void BL_BlenderShader::SetProg(bool enable) { +#ifdef BLENDER_GLSL if(VerifyShader()) { - if(enable) - GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, ~0, time); - else - GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); + if(enable) { + GPU_material_bind(mGPUMat, mLightLayer); + mBound = true; + } + else { + GPU_material_unbind(mGPUMat); + mBound = false; + } } +#endif } int BL_BlenderShader::GetAttribNum() { +#ifdef BLENDER_GLSL GPUVertexAttribs attribs; int i, enabled = 0; if(!VerifyShader()) return enabled; - GPU_material_vertex_attributes(GPU_material_from_blender(mBlenderScene, mMat), &attribs); + GPU_material_vertex_attributes(mGPUMat, &attribs); for(i = 0; i < attribs.totlayer; i++) if(attribs.layer[i].glindex+1 > enabled) @@ -76,23 +120,24 @@ int BL_BlenderShader::GetAttribNum() enabled = BL_MAX_ATTRIB; return enabled; +#else + return 0; +#endif } void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) { +#ifdef BLENDER_GLSL GPUVertexAttribs attribs; - GPUMaterial *gpumat; int i, attrib_num; ras->SetAttribNum(0); if(!VerifyShader()) return; - - gpumat = GPU_material_from_blender(mBlenderScene, mMat); if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { - GPU_material_vertex_attributes(gpumat, &attribs); + GPU_material_vertex_attributes(mGPUMat, &attribs); attrib_num = GetAttribNum(); ras->SetTexCoordNum(0); @@ -123,37 +168,44 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) else ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex); } + + ras->EnableTextures(true); } + else + ras->EnableTextures(false); +#endif } -void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) +void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { +#ifdef BLENDER_GLSL float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; - GPUMaterial *gpumat; - gpumat = GPU_material_from_blender(mBlenderScene, mMat); + VerifyShader(); - if(!gpumat || !GPU_material_bound(gpumat)) + if(!mGPUMat) // || !mBound) return; MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - const MT_Matrix4x4& view = rasty->GetViewMatrix(); - const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); + MT_Matrix4x4 view; + rasty->GetViewMatrix(view); - // note: getValue gives back column major as needed by OpenGL model.getValue((float*)obmat); view.getValue((float*)viewmat); - viewinv.getValue((float*)viewinvmat); + + view.invert(); + view.getValue((float*)viewinvmat); if(ms.m_bObjectColor) ms.m_RGBAcolor.getValue((float*)obcol); else obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol); + GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol); - mBlendMode = GPU_material_blend_mode(gpumat, obcol); + mBlendMode = GPU_material_blend_mode(mGPUMat, obcol); +#endif } int BL_BlenderShader::GetBlendMode() @@ -163,8 +215,12 @@ int BL_BlenderShader::GetBlendMode() bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) { +#ifdef BLENDER_GLSL /* to avoid unneeded state switches */ - return (blshader && mMat == blshader->mMat && mLightLayer == blshader->mLightLayer); + return (blshader && mGPUMat == blshader->mGPUMat && mLightLayer == blshader->mLightLayer); +#else + return true; +#endif } // eof diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index 5c1f59f94ad..da9765dafa4 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -2,7 +2,9 @@ #ifndef __BL_GPUSHADER_H__ #define __BL_GPUSHADER_H__ +#ifdef BLENDER_GLSL #include "GPU_material.h" +#endif #include "MT_Matrix4x4.h" #include "MT_Matrix3x3.h" @@ -27,9 +29,13 @@ class BL_Material; class BL_BlenderShader { private: +#ifdef BLENDER_GLSL KX_Scene *mScene; struct Scene *mBlenderScene; struct Material *mMat; + GPUMaterial *mGPUMat; +#endif + bool mBound; int mLightLayer; int mBlendMode; @@ -40,11 +46,11 @@ public: virtual ~BL_BlenderShader(); bool Ok(); - void SetProg(bool enable, double time=0.0); + void SetProg(bool enable); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); - void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); + void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 0eaa234566c..dcb66ea2579 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -18,9 +18,9 @@ struct EnvMap; this will default to users available units to build with more available, just increment this value although the more you add the slower the search time will be. - we will go for eight, which should be enough + we will go for three, which should be enough */ -#define MAXTEX 8 //match in RAS_TexVert & RAS_OpenGLRasterizer +#define MAXTEX 3 //match in RAS_TexVert & RAS_OpenGLRasterizer // different mapping modes class BL_Mapping @@ -139,7 +139,7 @@ enum BL_ras_mode COLLIDER=2, ZSORT=4, ALPHA=8, - // TRIANGLE=16, + TRIANGLE=16, USE_LIGHT=32, WIRE=64 }; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index f28d3fa2912..57d0fe4140f 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -433,7 +433,7 @@ void BL_Shader::SetProg(bool enable) } } -void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) +void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { if(!Ok() || !mPreDef.size()) return; @@ -445,7 +445,8 @@ void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - const MT_Matrix4x4& view = rasty->GetViewMatrix(); + MT_Matrix4x4 view; + rasty->GetViewMatrix(view); if(mAttr==SHD_TANGENT) ms.m_mesh->SetMeshModified(true); @@ -524,15 +525,13 @@ void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) } case VIEWMATRIX_INVERSE: { - MT_Matrix4x4 viewinv = view; - viewinv.invert(); + view.invert(); SetUniform(uni->mLoc, view); break; } case VIEWMATRIX_INVERSETRANSPOSE: { - MT_Matrix4x4 viewinv = view; - viewinv.invert(); + view.invert(); SetUniform(uni->mLoc, view, true); break; } @@ -671,7 +670,6 @@ void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose) ) { float value[16]; - // note: getValue gives back column major as needed by OpenGL vec.getValue(value); glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value); } diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index c7fae31ba03..8f303454087 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -177,7 +177,7 @@ public: void UnloadShader(); // Update predefined uniforms each render call - void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); + void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); //// Set sampler units (copied) //void InitializeSampler(int unit, BL_Texture* texture ); diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 58411f6d25e..be009d94701 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -69,7 +69,6 @@ SET(INC ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader - ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ../../../extern/glew/include diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index a35ab8b15e8..0c66ac1fde3 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -196,19 +196,19 @@ PyParentObject KX_NetworkMessageSensor::Parents[] = { PyMethodDef KX_NetworkMessageSensor::Methods[] = { {"setSubjectFilterText", (PyCFunction) - KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O, + KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS, SetSubjectFilterText_doc}, {"getFrameMessageCount", (PyCFunction) - KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_NOARGS, + KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS, GetFrameMessageCount_doc}, {"getBodies", (PyCFunction) - KX_NetworkMessageSensor::sPyGetBodies, METH_NOARGS, + KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS, GetBodies_doc}, {"getSubject", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubject, METH_NOARGS, + KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS, GetSubject_doc}, {"getSubjects", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS, + KX_NetworkMessageSensor::sPyGetSubjects, METH_VARARGS, GetSubjects_doc}, {NULL,NULL} //Sentinel }; @@ -222,16 +222,22 @@ char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = "\tsetSubjectFilterText(value)\n" "\tChange the message subject text that this sensor is listening to.\n"; -PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value) +PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( + PyObject* self, + PyObject* args, + PyObject* kwds) { - char* Subject = PyString_AsString(value); - if (Subject==NULL) { - PyErr_SetString(PyExc_TypeError, "expected a string message"); + char* Subject; + + if (PyArg_ParseTuple(args, "s", &Subject)) + { + m_subject = Subject; + } + else { return NULL; } - - m_subject = Subject; - Py_RETURN_NONE; + + Py_Return; } // 2. Get the number of messages received since the last frame @@ -239,7 +245,10 @@ char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = "\tgetFrameMessageCount()\n" "\tGet the number of messages received since the last frame.\n"; -PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( + PyObject* self, + PyObject* args, + PyObject* kwds) { return PyInt_FromLong(long(m_frame_message_count)); } @@ -249,13 +258,16 @@ char KX_NetworkMessageSensor::GetBodies_doc[] = "\tgetBodies()\n" "\tGet the list of message bodies.\n"; -PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetBodies( + PyObject* self, + PyObject* args, + PyObject* kwds) { if (m_BodyList) { return ((PyObject*) m_BodyList->AddRef()); - } else { - return ((PyObject*) new CListValue()); } + + Py_Return; } // 4. Get the message subject: field of the message sensor @@ -263,9 +275,16 @@ char KX_NetworkMessageSensor::GetSubject_doc[] = "\tgetSubject()\n" "\tGet the subject: field of the message sensor.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetSubject( + PyObject* self, + PyObject* args, + PyObject* kwds) { - return PyString_FromString(m_subject ? m_subject : ""); + if (m_subject) { + return PyString_FromString(m_subject); + } + + Py_Return; } // 5. Get the message subjects @@ -273,11 +292,14 @@ char KX_NetworkMessageSensor::GetSubjects_doc[] = "\tgetSubjects()\n" "\tGet list of message subjects.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* ) +PyObject* KX_NetworkMessageSensor::PyGetSubjects( + PyObject* self, + PyObject* args, + PyObject* kwds) { if (m_SubjectList) { - return ((PyObject*) m_SubjectList->AddRef()); - } else { - return ((PyObject*) new CListValue()); - } + return ((PyObject*) m_SubjectList->AddRef()); + } + + Py_Return; } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 8cdfd6cdb5a..6fd92d17be3 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -74,11 +74,11 @@ public: virtual PyObject* _getattr(const STR_String& attr); - KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); - KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); - KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetBodies); - KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubject); - KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubjects); + KX_PYMETHOD_DOC(KX_NetworkMessageSensor, SetSubjectFilterText); + KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetFrameMessageCount); + KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetBodies); + KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubject); + KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubjects); }; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index f92200780d5..a67e5b26667 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -19,12 +19,13 @@ #include "MT_Vector4.h" #include "MT_Matrix4x4.h" -#include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" -#include "GPU_draw.h" +extern "C" { +#include "BDR_drawmesh.h" +} #include "STR_HashedString.h" @@ -47,6 +48,7 @@ KX_BlenderMaterial::KX_BlenderMaterial( BL_Material *data, bool skin, int lightlayer, + void *clientobject, PyTypeObject *T ) : PyObjectPlus(T), @@ -60,7 +62,9 @@ KX_BlenderMaterial::KX_BlenderMaterial( data->transp, ((data->ras_mode &ALPHA)!=0), ((data->ras_mode &ZSORT)!=0), - lightlayer + lightlayer, + ((data->ras_mode &TRIANGLE)!=0), + clientobject ), mMaterial(data), mShader(0), @@ -74,10 +78,9 @@ KX_BlenderMaterial::KX_BlenderMaterial( { // -------------------------------- // RAS_IPolyMaterial variables... - m_flag |= RAS_BLENDERMAT; - m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0; - m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0; - m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; + m_flag |=RAS_BLENDERMAT; + m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; + m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; // figure max int enabled = mMaterial->num_enabled; @@ -94,7 +97,7 @@ KX_BlenderMaterial::KX_BlenderMaterial( mMaterial->blend_mode[i] ); } - m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT)); + m_multimode += mMaterial->IdMode+mMaterial->ras_mode; } @@ -201,7 +204,7 @@ void KX_BlenderMaterial::OnExit() } if( mMaterial->tface ) - GPU_set_tpage(mMaterial->tface); + set_tpage(mMaterial->tface); } @@ -253,28 +256,25 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras) { if( !enable || !mBlenderShader->Ok() ) { - ras->SetBlendingMode(TF_SOLID); - // frame cleanup. if(mLastBlenderShader) { mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; } - else - BL_Texture::DisableAllTextures(); + ras->SetBlendingMode(TF_SOLID); + BL_Texture::DisableAllTextures(); return; } if(!mBlenderShader->Equals(mLastBlenderShader)) { ras->SetBlendingMode(mMaterial->transp); + BL_Texture::DisableAllTextures(); if(mLastBlenderShader) mLastBlenderShader->SetProg(false); - else - BL_Texture::DisableAllTextures(); - mBlenderShader->SetProg(true, ras->GetTime()); + mBlenderShader->SetProg(true); mLastBlenderShader= mBlenderShader; } } @@ -354,22 +354,21 @@ KX_BlenderMaterial::ActivatShaders( if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - tmp->setShaderData(false, rasty); + tmp->setShaderData( false, rasty); cachingInfo = GetCachingInfo(); if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - tmp->setShaderData(true, rasty); + tmp->setShaderData( true, rasty); else - tmp->setShaderData(false, rasty); + tmp->setShaderData( false, rasty); if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || - (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) + if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -395,24 +394,31 @@ KX_BlenderMaterial::ActivateBlenderShaders( mLastShader= NULL; } + // reset... + if(tmp->mMaterial->IsShared()) + cachingInfo =0; + if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) tmp->setBlenderShaderData(false, rasty); cachingInfo = GetCachingInfo(); - if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) + if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { tmp->setBlenderShaderData(true, rasty); - else + rasty->EnableTextures(true); + } + else { tmp->setBlenderShaderData(false, rasty); + rasty->EnableTextures(false); + } if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode & WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || - (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) + if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -420,10 +426,10 @@ KX_BlenderMaterial::ActivateBlenderShaders( } else rasty->SetLines(false); - - ActivatGLMaterials(rasty); - mBlenderShader->SetAttribs(rasty, mMaterial); } + + ActivatGLMaterials(rasty); + mBlenderShader->SetAttribs(rasty, mMaterial); } void @@ -460,8 +466,7 @@ KX_BlenderMaterial::ActivateMat( else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || - (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) + if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -481,10 +486,12 @@ KX_BlenderMaterial::Activate( TCachingInfo& cachingInfo )const { - if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) { - if((mPass++) < mShader->getNumPass() ) { + bool dopass = false; + if( GLEW_ARB_shader_objects && ( mShader && mShader->Ok() ) ) { + if( (mPass++) < mShader->getNumPass() ) { ActivatShaders(rasty, cachingInfo); - return true; + dopass = true; + return dopass; } else { if(mShader == mLastShader) { @@ -492,29 +499,36 @@ KX_BlenderMaterial::Activate( mLastShader = NULL; } mPass = 0; - return false; + dopass = false; + return dopass; } } - else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) { - if(mPass++ == 0) { + else if( GLEW_ARB_shader_objects && ( mBlenderShader && mBlenderShader->Ok() ) ) { + if( (mPass++) == 0 ) { ActivateBlenderShaders(rasty, cachingInfo); - return true; + dopass = true; + return dopass; } else { mPass = 0; - return false; + dopass = false; + return dopass; } } else { - if(mPass++ == 0) { - ActivateMat(rasty, cachingInfo); - return true; - } - else { - mPass = 0; - return false; + switch (mPass++) + { + case 0: + ActivateMat(rasty, cachingInfo); + dopass = true; + break; + default: + mPass = 0; + dopass = false; + break; } } + return dopass; } bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const @@ -522,15 +536,14 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const if(!RAS_IPolyMaterial::UsesLighting(rasty)) return false; - if(mShader && mShader->Ok()) - return true; + if(mShader && mShader->Ok()); else if(mBlenderShader && mBlenderShader->Ok()) return false; - else - return true; + + return true; } -void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const +void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const { if(mShader && GLEW_ARB_shader_objects) { mShader->Update(ms, rasty); @@ -541,7 +554,7 @@ void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasteriz mBlenderShader->Update(ms, rasty); /* we do blend modes here, because they can change per object - * with the same material due to obcolor/obalpha */ + * with the same material due to obcolor */ blendmode = mBlenderShader->GetBlendMode(); if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) blendmode = mMaterial->transp; @@ -620,7 +633,11 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const else ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i); } + + ras->EnableTextures(true); } + else + ras->EnableTextures(false); } void KX_BlenderMaterial::setTexMatrixData(int i) @@ -695,7 +712,8 @@ void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras) glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); - const MT_Matrix4x4& mvmat = ras->GetViewMatrix(); + MT_Matrix4x4 mvmat; + ras->GetViewMatrix(mvmat); glMatrixMode(GL_TEXTURE); glLoadIdentity(); @@ -817,9 +835,7 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") } if(mShader && !mShader->GetError()) { - m_flag &= ~RAS_BLENDERGLSL; mMaterial->SetSharedMaterial(true); - mScene->GetBucketManager()->ReleaseDisplayLists(this); Py_INCREF(mShader); return mShader; }else @@ -854,6 +870,8 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(void) delete mBlenderShader; mBlenderShader = 0; } + else + m_flag |= RAS_BLENDERGLSL; } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 4ddf5a924df..0d7657b8cdb 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -28,6 +28,7 @@ public: BL_Material* mat, bool skin, int lightlayer, + void* clientobject, PyTypeObject* T=&Type ); @@ -46,7 +47,7 @@ public: virtual void ActivateMeshSlot( - const RAS_MeshSlot & ms, + const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) const; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 4948c0ea174..42b909927fd 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -35,8 +35,6 @@ #include #include "KX_GameObject.h" -#include "PyObjectPlus.h" - STR_String KX_CameraActuator::X_AXIS_STRING = "x"; STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 4b57b0e8c54..e00ec68ad33 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -109,11 +109,16 @@ KX_ConstraintActuator::~KX_ConstraintActuator() // there's nothing to be done here, really.... } /* end of destructor */ -bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) +bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // false hit + return false; + } bool bFound = false; if (m_property[0] == 0) @@ -134,26 +139,8 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* resu bFound = hitKXObj->GetProperty(m_property) != NULL; } } - // update the hit status - result->m_hitFound = bFound; - // stop looking - return true; -} -/* this function is used to pre-filter the object before casting the ray on them. - This is useful for "X-Ray" option when we want to see "through" unwanted object. - */ -bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client) -{ - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // Unknown type of object, skip it. - // Should not occur as the sensor objects are filtered in RayTest() - printf("Invalid client type %d found in ray casting\n", client->m_type); - return false; - } - // no X-Ray function yet - return true; + return bFound; } bool KX_ConstraintActuator::Update(double curtime, bool frame) @@ -300,6 +287,8 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) direction.normalize(); { MT_Point3 topoint = position + (m_maximumBound) * direction; + MT_Point3 resultpoint; + MT_Vector3 resultnormal; PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment(); KX_IPhysicsController *spc = obj->GetPhysicsController(); @@ -315,10 +304,9 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) parent->Release(); } } - KX_RayCast::Callback callback(this,spc); - result = KX_RayCast::RayTest(pe, position, topoint, callback); + result = KX_RayCast::RayTest(spc, pe, position, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this)); + if (result) { - MT_Vector3 newnormal = callback.m_hitNormal; // compute new position & orientation if ((m_option & (KX_ACT_CONSTRAINT_NORMAL|KX_ACT_CONSTRAINT_DISTANCE)) == 0) { // if none option is set, the actuator does nothing but detect ray @@ -328,27 +316,27 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) if (m_option & KX_ACT_CONSTRAINT_NORMAL) { // the new orientation must be so that the axis is parallel to normal if (sign) - newnormal = -newnormal; + resultnormal = -resultnormal; // apply damping on the direction if (m_rotDampTime) { MT_Scalar rotFilter = 1.0/(1.0+m_rotDampTime); - newnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*newnormal; + resultnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*resultnormal; } else if (m_posDampTime) { - newnormal = -filter*direction + (1.0-filter)*newnormal; + resultnormal = -filter*direction + (1.0-filter)*resultnormal; } - obj->AlignAxisToVect(newnormal, axis); - direction = -newnormal; + obj->AlignAxisToVect(resultnormal, axis); + direction = -resultnormal; } if (m_option & KX_ACT_CONSTRAINT_DISTANCE) { if (m_posDampTime) { - newdistance = filter*(position-callback.m_hitPoint).length()+(1.0-filter)*m_minimumBound; + newdistance = filter*(position-resultpoint).length()+(1.0-filter)*m_minimumBound; } else { newdistance = m_minimumBound; } } else { - newdistance = (position-callback.m_hitPoint).length(); + newdistance = (position-resultpoint).length(); } - newposition = callback.m_hitPoint-newdistance*direction; + newposition = resultpoint-newdistance*direction; } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) { // no contact but still keep running result = true; diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 6ec4de9aad9..d9f39124cac 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -37,8 +37,6 @@ #include "MT_Vector3.h" #include "KX_ClientObjectInfo.h" -class KX_RayCast; - class KX_ConstraintActuator : public SCA_IActuator { Py_Header; @@ -102,8 +100,7 @@ protected: KX_ACT_CONSTRAINT_DISTANCE = 512 }; bool IsValidMode(KX_CONSTRAINTTYPE m); - bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); - bool NeedRayCast(KX_ClientObjectInfo*); + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); KX_ConstraintActuator(SCA_IObject* gameobj, int posDamptime, diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index c9095ff34f6..b54da6eb753 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -27,7 +27,6 @@ * ***** END GPL LICENSE BLOCK ***** */ #include -#include "PyObjectPlus.h" #include "KX_ConstraintWrapper.h" #include "PHY_IPhysicsEnvironment.h" diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 248d2f49b0b..6653026f28a 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -86,7 +86,6 @@ struct KX_ObjectProperties bool m_disableSleeping; bool m_hasCompoundChildren; bool m_isCompoundChild; - double m_margin; KX_BoundBoxClass m_boundclass; union { KX_BoxBounds box; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index b3f24d97281..d6997ee29a8 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -76,16 +76,16 @@ struct KX_PhysicsInstance { DT_VertexBaseHandle m_vertexbase; - RAS_DisplayArray* m_darray; + int m_vtxarray; RAS_IPolyMaterial* m_material; - - KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat) + + KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, int vtxarray, RAS_IPolyMaterial* mat) : m_vertexbase(vertex_base), - m_darray(darray), - m_material(mat) + m_vtxarray(vtxarray), + m_material(mat) { } - + ~KX_PhysicsInstance() { DT_DeleteVertexBase(m_vertexbase); @@ -100,11 +100,11 @@ static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoSce 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) + RAS_MeshObject* meshobj, + KX_Scene* kxscene, + PHY_ShapeProps* kxshapeprops, + PHY_MaterialProps* kxmaterial, + struct KX_ObjectProperties* objprop) { @@ -150,23 +150,23 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, 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]); + 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); + 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); + 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. */ + /* Dynamic mesh objects. WARNING! slow. */ case KX_BOUNDPOLYTOPE: polytope = true; // fall through @@ -186,15 +186,15 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, 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 @@ -320,11 +320,12 @@ static void BL_RegisterSumoObject( physicscontroller->SetObject(gameobj->GetSGNode()); } -static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat) +static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, 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)); + const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]); + //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray]; + DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert)); DT_ShapeHandle shape = DT_NewComplexShape(vertex_base); @@ -336,19 +337,15 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_Displa // 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(); + DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray); // tesselate if (poly->VertexCount() == 4) { DT_Begin(); - DT_VertexIndex(poly->GetVertexOffset(0)); - DT_VertexIndex(poly->GetVertexOffset(2)); - DT_VertexIndex(poly->GetVertexOffset(3)); + DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[0]); + DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]); + DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[3]); DT_End(); } } @@ -357,15 +354,16 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_Displa //DT_VertexIndices(indices.size(), &indices[0]); DT_EndComplexShape(); - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); + map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat)); return shape; } -static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat) +static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, 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)); + const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]); + //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray]; + DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert)); std::vector indices; for (int p = 0; p < meshobj->NumPolygons(); p++) @@ -375,12 +373,12 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_Displ // 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)); + indices.push_back(poly->GetVertexIndexBase().m_indexarray[0]); + indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]); + indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]); if (poly->VertexCount() == 4) - indices.push_back(poly->GetVertexOffset(3)); + indices.push_back(poly->GetVertexIndexBase().m_indexarray[3]); } } @@ -388,7 +386,7 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_Displ DT_VertexIndices(indices.size(), &indices[0]); DT_EndPolytope(); - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); + map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat)); return shape; } @@ -400,8 +398,8 @@ 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()); + const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(instance->m_material)[instance->m_vtxarray])[0]); + DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getLocalXYZ()); return true; } return false; @@ -427,7 +425,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope // Count the number of collision polygons and check they all come from the same // vertex array int numvalidpolys = 0; - RAS_DisplayArray *darray = NULL; + int vtxarray = -1; RAS_IPolyMaterial *poly_material = NULL; bool reinstance = true; @@ -439,14 +437,14 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->IsCollider()) { // check polygon is from the same vertex array - if (poly->GetDisplayArray() != darray) + if (poly->GetVertexIndexBase().m_vtxarray != vtxarray) { - if (darray == NULL) - darray = poly->GetDisplayArray(); + if (vtxarray < 0) + vtxarray = poly->GetVertexIndexBase().m_vtxarray; else { reinstance = false; - darray = NULL; + vtxarray = -1; } } @@ -480,9 +478,9 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (reinstance) { if (polytope) - shape = InstancePhysicsPolytope(meshobj, darray, poly_material); + shape = InstancePhysicsPolytope(meshobj, vtxarray, poly_material); else - shape = InstancePhysicsComplex(meshobj, darray, poly_material); + shape = InstancePhysicsComplex(meshobj, vtxarray, poly_material); } else { @@ -491,7 +489,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool 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) + if (vtxarray < 0) std::cout << " Check number of vertices." << std::endl; } @@ -507,10 +505,18 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope 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()); + /* V1 */ + DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[2], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V2 */ + DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[1], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V3 */ + DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[0], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); numvalidpolys++; DT_End(); @@ -518,10 +524,18 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope 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()); + /* V1 */ + DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[3], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V3 */ + DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[2], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V4 */ + DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[0], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); numvalidpolys++; DT_End(); @@ -699,7 +713,6 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_gravity = btVector3(0,0,0); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; - ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; @@ -787,7 +800,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, return; } - bm->setMargin(ci.m_margin); + bm->setMargin(0.06); if (objprop->m_isCompoundChild) @@ -802,29 +815,11 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; - // compute the local transform from parent, this may include a parent inverse node - SG_Node* gameNode = gameobj->GetSGNode(); - SG_Node* parentInverseNode = gameNode->GetSGParent(); - if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL) - // this is not a parent inverse node, cancel it - parentInverseNode = NULL; - // now combine the parent inverse node and the game node - MT_Point3 childPos = gameNode->GetLocalPosition(); - MT_Matrix3x3 childRot = gameNode->GetLocalOrientation(); - MT_Vector3 childScale = gameNode->GetLocalScale(); - if (parentInverseNode) - { - const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition(); - const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation(); - const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale(); - childRot = parentInverseRot * childRot; - childScale = parentInverseScale * childScale; - childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos); - } + MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition(); + MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation(); + MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale(); - shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z()); - bm->setLocalScaling(shapeInfo->m_childScale); - + bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z())); shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z())); float rotval[12]; childRot.getValue(rotval); diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 91ddbbbfbc9..fcd32d5f4fe 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -34,7 +34,6 @@ //#include #include "KX_Scene.h" #include "KX_KetsjiEngine.h" -#include "KX_PythonInit.h" /* for config load/saving */ #ifdef HAVE_CONFIG_H #include @@ -126,71 +125,6 @@ bool KX_GameActuator::Update() } break; } - case KX_GAME_SAVECFG: - { - if (m_ketsjiengine) - { - char mashal_path[512]; - char *marshal_buffer = NULL; - int marshal_length; - FILE *fp = NULL; - - pathGamePythonConfig(mashal_path); - marshal_length = saveGamePythonConfig(&marshal_buffer); - - if (marshal_length && marshal_buffer) { - fp = fopen(mashal_path, "wb"); - if (fp) { - if (fwrite(marshal_buffer, 1, marshal_length, fp) != marshal_length) { - printf("Warning: could not write marshal data\n"); - } - fclose(fp); - } else { - printf("Warning: could not open marshal file\n"); - } - } else { - printf("Warning: could not create marshal buffer\n"); - } - } - break; - } - case KX_GAME_LOADCFG: - { - if (m_ketsjiengine) - { - char mashal_path[512]; - char *marshal_buffer; - int marshal_length; - FILE *fp = NULL; - int result; - - pathGamePythonConfig(mashal_path); - - fp = fopen(mashal_path, "rb"); - if (fp) { - // obtain file size: - fseek (fp , 0 , SEEK_END); - marshal_length = ftell(fp); - rewind(fp); - - marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); - - result = fread (marshal_buffer, 1, marshal_length, fp); - - if (result == marshal_length) { - loadGamePythonConfig(marshal_buffer, marshal_length); - } else { - printf("warning: could not read all of '%s'\n", mashal_path); - } - - free(marshal_buffer); - fclose(fp); - } else { - printf("warning: could not open '%s'\n", mashal_path); - } - } - break; - } default: ; /* do nothing? this is an internal error !!! */ } diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index bb3448995dc..8565dc46caa 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -54,8 +54,6 @@ protected: KX_GAME_START, KX_GAME_RESTART, KX_GAME_QUIT, - KX_GAME_SAVECFG, - KX_GAME_LOADCFG, KX_GAME_MAX }; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 0e5956d4fdb..700cc00e996 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -51,7 +51,6 @@ typedef unsigned long uint_ptr; #include "KX_GameObject.h" #include "RAS_MeshObject.h" #include "KX_MeshProxy.h" -#include "KX_PolyProxy.h" #include // printf #include "SG_Controller.h" #include "KX_IPhysicsController.h" @@ -65,8 +64,6 @@ typedef unsigned long uint_ptr; #include "SCA_IActuator.h" #include "SCA_ISensor.h" -#include "PyObjectPlus.h" /* python stuff */ - // This file defines relationships between parents and children // in the game engine. @@ -81,15 +78,12 @@ KX_GameObject::KX_GameObject( m_bDyna(false), m_layer(0), m_pBlenderObject(NULL), - m_pBlenderGroupObject(NULL), m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_bVisible(true), - m_bCulled(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), - m_xray(false), m_pHitObject(NULL), m_isDeformable(false) { @@ -105,11 +99,8 @@ KX_GameObject::KX_GameObject( }; - KX_GameObject::~KX_GameObject() { - RemoveMeshes(); - // is this delete somewhere ? //if (m_sumoObj) // delete m_sumoObj; @@ -171,6 +162,7 @@ STR_String KX_GameObject::GetName() void KX_GameObject::SetName(STR_String name) { m_name = name; + }; // Set the name of the value @@ -235,12 +227,11 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) m_pPhysicsController1->SuspendDynamics(true); } // Set us to our new scale, position, and orientation - scale2[0] = 1.0/scale2[0]; - scale2[1] = 1.0/scale2[1]; - scale2[2] = 1.0/scale2[2]; - scale1 = scale1 * scale2; + scale1[0] = scale1[0]/scale2[0]; + scale1[1] = scale1[1]/scale2[1]; + scale1[2] = scale1[2]/scale2[2]; MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse(); - MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; + MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1; NodeSetLocalScale(scale1); NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); @@ -292,11 +283,11 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica) CValue* KX_GameObject::GetReplica() { KX_GameObject* replica = new KX_GameObject(*this); - + // this will copy properties and so on... CValue::AddDataToReplica(replica); ProcessReplica(replica); - + return replica; } @@ -362,47 +353,24 @@ double* KX_GameObject::GetOpenGLMatrix() return fl; } -void KX_GameObject::AddMeshUser() -{ - for (size_t i=0;iAddMeshUser(this); - - UpdateBuckets(false); -} -static void UpdateBuckets_recursive(SG_Node* node) -{ - NodeList& children = node->GetSGChildren(); - for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) - { - SG_Node* childnode = (*childit); - KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); - if (clientgameobj != NULL) // This is a GameObject - clientgameobj->UpdateBuckets(0); - - // if the childobj is NULL then this may be an inverse parent link - // so a non recursive search should still look down this node. - UpdateBuckets_recursive(childnode); - } -} - -void KX_GameObject::UpdateBuckets( bool recursive ) +void KX_GameObject::Bucketize() { double* fl = GetOpenGLMatrix(); for (size_t i=0;iUpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); - - if (recursive) { - UpdateBuckets_recursive(m_pSGNode); - } + m_meshes[i]->Bucketize(fl, this, m_bUseObjectColor, m_objectColor); } + + void KX_GameObject::RemoveMeshes() { + double* fl = GetOpenGLMatrix(); + for (size_t i=0;iRemoveFromBuckets(this); + m_meshes[i]->RemoveFromBuckets(fl, this); //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter @@ -485,14 +453,13 @@ KX_GameObject::UpdateMaterialData( ) { int mesh = 0; - if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { - list::iterator mit = m_meshes[mesh]->GetFirstMaterial(); + if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { + RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial(); for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) { - RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial(); - - if(poly->GetFlag() & RAS_BLENDERMAT ) + RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial(); + if(poly->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *m = static_cast(poly); @@ -500,7 +467,8 @@ KX_GameObject::UpdateMaterialData( { m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) - SetObjectColor(rgba); + if(!(poly->GetFlag() & RAS_BLENDERGLSL)) + SetObjectColor(rgba); } else { @@ -526,52 +494,14 @@ KX_GameObject::GetVisible( return m_bVisible; } -static void setVisible_recursive(SG_Node* node, bool v) -{ - NodeList& children = node->GetSGChildren(); - - for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) - { - SG_Node* childnode = (*childit); - KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); - if (clientgameobj != NULL) // This is a GameObject - clientgameobj->SetVisible(v, 0); - - // if the childobj is NULL then this may be an inverse parent link - // so a non recursive search should still look down this node. - setVisible_recursive(childnode, v); - } -} - - void KX_GameObject::SetVisible( - bool v, - bool recursive + bool v ) { m_bVisible = v; - if (recursive) - setVisible_recursive(m_pSGNode, v); } -bool -KX_GameObject::GetCulled( - void - ) -{ - return m_bCulled; -} - -void -KX_GameObject::SetCulled( - bool c - ) -{ - m_bCulled = c; -} - - void KX_GameObject::SetLayer( int l @@ -588,6 +518,44 @@ KX_GameObject::GetLayer( return m_layer; } +// used by Python, and the actuatorshould _not_ be misused by the +// scene! +void +KX_GameObject::MarkVisible( + bool visible + ) +{ + /* If explicit visibility settings are used, this is + * determined on this level. Maybe change this to mesh level + * later on? */ + + double* fl = GetOpenGLMatrixPtr()->getPointer(); + for (size_t i=0;iMarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor); + } +} + + +// Always use the flag? +void +KX_GameObject::MarkVisible( + void + ) +{ + double* fl = GetOpenGLMatrixPtr()->getPointer(); + for (size_t i=0;iMarkVisible(fl, + this, + m_bVisible, + m_bUseObjectColor, + m_objectColor + ); + } +} + + void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local) { if (m_pPhysicsController1) @@ -915,18 +883,15 @@ void KX_GameObject::Suspend() PyMethodDef KX_GameObject::Methods[] = { {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, - {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS}, {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS}, - {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, - {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS}, {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS}, {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS}, {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS}, - {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, + {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O}, {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS}, {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, @@ -1067,23 +1032,18 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr method { - if (attr == "mass") { - PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only"); + if (attr == "mass") return 1; - } - if (attr == "parent") { - PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); + if (attr == "parent") return 1; - } if (PyInt_Check(value)) { int val = PyInt_AsLong(value); if (attr == "visible") { - SetVisible(val != 0, false); - UpdateBuckets(false); + SetVisible(val != 0); return 0; } } @@ -1142,7 +1102,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr } return 1; } - PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence"); + return 1; } @@ -1186,7 +1146,9 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr } -PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, + PyObject* args, + PyObject* kwds) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -1200,7 +1162,9 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) } } -PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, + PyObject* args, + PyObject* kwds) { int local = 0; PyObject* pyvect; @@ -1215,43 +1179,17 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) return NULL; } -PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value) { - // only can get the velocity if we have a physics object connected to us... - int local = 0; - if (PyArg_ParseTuple(args,"|i",&local)) - { - return PyObjectFrom(GetAngularVelocity((local!=0))); - } - else - { + int visible = PyInt_AsLong(value); + + if (visible==-1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected 0 or 1"); return NULL; } -} - -PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) -{ - int local = 0; - PyObject* pyvect; - if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { - MT_Vector3 velocity; - if (PyVecTo(pyvect, velocity)) { - setAngularVelocity(velocity, (local!=0)); - Py_RETURN_NONE; - } - } - return NULL; -} - -PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) -{ - int visible, recursive = 0; - if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive)) - return NULL; - - SetVisible(visible ? true:false, recursive ? true:false); - UpdateBuckets(recursive ? true:false); + MarkVisible(visible!=0); + m_bVisible = (visible!=0); Py_RETURN_NONE; } @@ -1290,7 +1228,9 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetVelocity(PyObject* self, + PyObject* args, + PyObject* kwds) { // only can get the velocity if we have a physics object connected to us... MT_Vector3 velocity(0.0,0.0,0.0); @@ -1422,7 +1362,9 @@ PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self) return list; } -PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyGetMesh(PyObject* self, + PyObject* args, + PyObject* kwds) { int mesh = 0; @@ -1462,7 +1404,9 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, + PyObject* args, + PyObject* kwds) { PyObject* pyattach; PyObject* pyimpulse; @@ -1533,7 +1477,9 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value) return NULL; } -PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) +PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, + PyObject* args, + PyObject* kwds) { PyObject* pyvect; int axis = 2; //z axis is the default @@ -1578,19 +1524,6 @@ PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value) return NULL; } -PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value) -{ - MT_Point3 pos; - if (PyVecTo(value, pos)) - { - NodeSetWorldPosition(pos); - NodeUpdateGS(0.f,true); - Py_RETURN_NONE; - } - - return NULL; -} - PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self) { KX_IPhysicsController* ctrl = GetPhysicsController(); @@ -1676,45 +1609,25 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, return returnValue; } -bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) +bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { - KX_GameObject* hitKXObj = client->m_gameobject; - - // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit - // if not, all objects were tested and the front one may not be the correct one. - if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) - { - m_pHitObject = hitKXObj; - return true; - } - // return true to stop RayCast::RayTest from looping, the above test was decisive - // We would want to loop only if we want to get more than one hit point - return true; -} -/* this function is used to pre-filter the object before casting the ray on them. - This is useful for "X-Ray" option when we want to see "through" unwanted object. - */ -bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client) -{ KX_GameObject* hitKXObj = client->m_gameobject; if (client->m_type > KX_ClientObjectInfo::ACTOR) { - // Unknown type of object, skip it. - // Should not occur as the sensor objects are filtered in RayTest() - printf("Invalid client type %d found in ray casting\n", client->m_type); + // false hit return false; } - - // if X-Ray option is selected, skip object that don't match the criteria as we see through them - // if not, test all objects because we don't know yet which one will be on front - if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) + + if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) { + m_pHitObject = hitKXObj; return true; } - // skip the object + return false; + } KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, @@ -1754,6 +1667,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, toPoint = fromPoint + (dist) * toDir; } + MT_Point3 resultPoint; + MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); @@ -1767,8 +1682,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, m_testPropName = propName; else m_testPropName.SetLength(0); - KX_RayCast::Callback callback(this,spc); - KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); + KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback(this)); if (m_pHitObject) { @@ -1779,24 +1693,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, } KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, - "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n" - " If no hit, return (None,None,None) or (None,None,None,None).\n" -" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" + "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n" +" prop = property name that object must have; can be omitted => detect any object\n" +" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" " Can be None or omitted => start from self object center\n" -" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" -" prop = property name that object must have; can be omitted => detect any object\n" -" face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n" -" xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n" -" poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n" -" which can be None if hit object has no mesh or if there is no hit\n" -" If 0 or omitted, return value is a 3-tuple\n" -"Note: The object on which you call this method matters: the ray will ignore it.\n" -" prop and xray option interact as follow:\n" -" prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n" -" prop off, xray on : idem\n" -" prop on, xray off: return closest hit if it matches prop, no hit otherwise\n" -" prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n") +" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" +"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n") { MT_Point3 toPoint; MT_Point3 fromPoint; @@ -1805,9 +1708,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, float dist = 0.0f; char *propName = NULL; KX_GameObject *other; - int face=0, xray=0, poly=0; - if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { + if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) { return NULL; // Python sets a simple error } @@ -1853,6 +1755,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } + MT_Point3 resultPoint; + MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); @@ -1866,41 +1770,20 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, m_testPropName = propName; else m_testPropName.SetLength(0); - m_xray = xray; - // to get the hit results - KX_RayCast::Callback callback(this,spc,NULL,face); - KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); + KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback(this)); - if (m_pHitObject) + if (m_pHitObject) { - PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3); + PyObject* returnValue = PyTuple_New(3); if (returnValue) { // unlikely this would ever fail, if it does python sets an error PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); - PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); - PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal)); - if (poly) - { - if (callback.m_hitMesh) - { - // if this field is set, then we can trust that m_hitPolygon is a valid polygon - RAS_Polygon* poly = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); - KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, poly); - PyTuple_SET_ITEM(returnValue, 3, polyproxy); - } - else - { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(returnValue, 3, Py_None); - } - } + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); } return returnValue; } - // no hit - if (poly) - return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None); - else - return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + //Py_RETURN_NONE; } /* --------------------------------------------------------------------- diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 2da0be4df25..a7ac2d75a93 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -54,7 +54,6 @@ //Forward declarations. struct KX_ClientObjectInfo; -class KX_RayCast; class RAS_MeshObject; class KX_IPhysicsController; class PHY_IPhysicsEnvironment; @@ -75,23 +74,20 @@ protected: int m_layer; std::vector m_meshes; struct Object* m_pBlenderObject; - struct Object* m_pBlenderGroupObject; bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; - // visible = user setting - // culled = while rendering, depending on camera - bool m_bVisible; - bool m_bCulled; + // Is this object set to be visible? Only useful for the + // visibility subsystem right now. + bool m_bVisible; KX_IPhysicsController* m_pPhysicsController1; // used for ray casting PHY_IPhysicsEnvironment* m_pPhysicsEnvironment; STR_String m_testPropName; - bool m_xray; KX_GameObject* m_pHitObject; SG_Node* m_pSGNode; @@ -397,16 +393,6 @@ public: { m_pBlenderObject = obj; } - - struct Object* GetBlenderGroupObject( ) - { - return m_pBlenderGroupObject; - } - - void SetBlenderGroupObject( struct Object* obj) - { - m_pBlenderGroupObject = obj; - } bool IsDupliGroup() { @@ -442,8 +428,7 @@ public: return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent()); } - bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); - bool NeedRayCast(KX_ClientObjectInfo* client); + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); /** @@ -550,23 +535,18 @@ public: /** * @section Mesh accessor functions. */ - - /** - * Update buckets to indicate that there is a new - * user of this object's meshes. - */ - void - AddMeshUser( - ); /** - * Update buckets with data about the mesh after - * creating or duplicating the object, changing - * visibility, object color, .. . + * Run through the meshes associated with this + * object and bucketize them. See RAS_Mesh for + * more details on this function. Interesting to + * note that polygon bucketizing seems to happen on a per + * object basis. Which may explain why there is such + * a big performance gain when all static objects + * are joined into 1. */ void - UpdateBuckets( - bool recursive + Bucketize( ); /** @@ -627,8 +607,25 @@ public: ResetDebugColor( ); + /** + * Set the visibility of the meshes associated with this + * object. + */ + void + MarkVisible( + bool visible + ); + + /** + * Set the visibility according to the visibility flag. + */ + void + MarkVisible( + void + ); + /** - * Was this object marked visible? (only for the explicit + * Was this object marked visible? (only for the ewxplicit * visibility system). */ bool @@ -641,24 +638,7 @@ public: */ void SetVisible( - bool b, - bool recursive - ); - - /** - * Was this object culled? - */ - bool - GetCulled( - void - ); - - /** - * Set culled flag of this object - */ - void - SetCulled( - bool c + bool b ); /** @@ -686,14 +666,6 @@ public: void ) { return m_bIsNegativeScaling; } - /** - * Is this a light? - */ - virtual bool - IsLight( - void - ) { return false; } - /** * @section Logic bubbling methods. */ @@ -754,34 +726,31 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); - KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); - KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity); - KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity); - KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity); - KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity); - KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity); + KX_PYMETHOD(KX_GameObject,GetLinearVelocity); + KX_PYMETHOD(KX_GameObject,SetLinearVelocity); + KX_PYMETHOD(KX_GameObject,GetVelocity); KX_PYMETHOD_NOARGS(KX_GameObject,GetMass); KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce); KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation); KX_PYMETHOD_O(KX_GameObject,SetOrientation); KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible); - KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible); + KX_PYMETHOD_O(KX_GameObject,SetVisible); KX_PYMETHOD_NOARGS(KX_GameObject,GetState); KX_PYMETHOD_O(KX_GameObject,SetState); - KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); + KX_PYMETHOD(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); - KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse); + KX_PYMETHOD(KX_GameObject,ApplyImpulse); KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin); KX_PYMETHOD_NOARGS(KX_GameObject,GetParent); KX_PYMETHOD_O(KX_GameObject,SetParent); KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive); - KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh); + KX_PYMETHOD(KX_GameObject,GetMesh); KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId); KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames); KX_PYMETHOD_NOARGS(KX_GameObject,EndObject); diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 6223643f75a..d3aa924665e 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -143,7 +143,7 @@ bool KX_IpoSGController::Update(double currentTime) { if (m_ipo_as_force == true) { - if (m_game_object && ob && m_game_object->GetPhysicsController()) + if (m_game_object && ob) { m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ? ob->GetWorldOrientation() * m_ipo_xform.GetPosition() : diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index 3709fa8c784..f069048cd3d 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -32,8 +32,6 @@ #include "STR_String.h" #include "KX_Python.h" -struct Scene; - class KX_ISceneConverter { @@ -79,8 +77,6 @@ public: // use blender glsl materials virtual void SetGLSLMaterials(bool val) =0; virtual bool GetGLSLMaterials()=0; - - virtual struct Scene* GetBlenderSceneForName(const STR_String& name)=0; }; #endif //__KX_ISCENECONVERTER_H diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 888dcf3d01f..1d6cc975ab5 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -96,7 +96,6 @@ double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE; double KX_KetsjiEngine::m_anim_framerate = 25.0; double KX_KetsjiEngine::m_suspendedtime = 0.0; double KX_KetsjiEngine::m_suspendeddelta = 0.0; -double KX_KetsjiEngine::m_average_framerate = 0.0; /** @@ -135,8 +134,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_overrideCam(false), m_overrideCamUseOrtho(false), - m_overrideCamNear(0.0), - m_overrideCamFar(0.0), m_stereo(false), m_curreye(0), @@ -278,73 +275,30 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) } -void KX_KetsjiEngine::ClearFrame() -{ - // clear unless we're drawing overlapping stereo - if(m_rasterizer->InterlacedStereo() && - m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE) - return; - - // clear the viewports with the background color of the first scene - bool doclear = false; - KX_SceneList::iterator sceneit; - RAS_Rect clearvp, area, viewport; - - for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++) - { - KX_Scene* scene = *sceneit; - //const RAS_FrameSettings &framesettings = scene->GetFramingType(); - list* cameras = scene->GetCameras(); - - list::iterator it; - for(it = cameras->begin(); it != cameras->end(); it++) - { - SetupViewport(scene, (*it), area, viewport); - - if(!doclear) { - clearvp = viewport; - doclear = true; - } - else { - if(viewport.GetLeft() < clearvp.GetLeft()) - clearvp.SetLeft(viewport.GetLeft()); - if(viewport.GetBottom() < clearvp.GetBottom()) - clearvp.SetBottom(viewport.GetBottom()); - if(viewport.GetRight() > clearvp.GetRight()) - clearvp.SetRight(viewport.GetRight()); - if(viewport.GetTop() > clearvp.GetTop()) - clearvp.SetTop(viewport.GetTop()); - - } - } - } - - if(doclear) { - KX_Scene* firstscene = *m_scenes.begin(); - SetBackGround(firstscene->GetWorldInfo()); - - m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), - clearvp.GetRight(), clearvp.GetTop()); - m_rasterizer->ClearColorBuffer(); - } -} - bool KX_KetsjiEngine::BeginFrame() { - // set the area used for rendering (stereo can assign only a subset) + bool result = false; + + RAS_Rect vp; + KX_Scene* firstscene = *m_scenes.begin(); + const RAS_FrameSettings &framesettings = firstscene->GetFramingType(); + + // set the area used for rendering m_rasterizer->SetRenderArea(); + RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp); + if (m_canvas->BeginDraw()) { - ClearFrame(); + result = true; - m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds()); - m_rendertools->BeginFrame(m_rasterizer); - - return true; + m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop()); + SetBackGround( firstscene->GetWorldInfo() ); + m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds()); + m_rendertools->BeginFrame( m_rasterizer); } - return false; + return result; } @@ -356,12 +310,6 @@ void KX_KetsjiEngine::EndFrame() { RenderDebugProperties(); } - - m_average_framerate = m_logger->GetAverage(); - if (m_average_framerate < 1e-6) - m_average_framerate = 1e-6; - m_average_framerate = 1.0/m_average_framerate; - // Go to next profiling measurement, time spend after this call is shown in the next frame. m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds()); @@ -373,6 +321,8 @@ void KX_KetsjiEngine::EndFrame() m_canvas->EndDraw(); + + } //#include "PIL_time.h" @@ -651,7 +601,7 @@ void KX_KetsjiEngine::Render() ); } // clear the -whole- viewport - m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); } m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); @@ -680,6 +630,9 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); + //Initialize scene viewport. + SetupRenderFrame(scene, cam); + // do the rendering RenderFrame(scene, cam); } @@ -697,6 +650,9 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); + //Initialize scene viewport. + SetupRenderFrame(scene, (*it)); + // do the rendering RenderFrame(scene, (*it)); } @@ -729,6 +685,10 @@ void KX_KetsjiEngine::Render() //pass the scene, for picking and raycasting (shadows) m_rendertools->SetAuxilaryClientInfo(scene); + //Initialize scene viewport. + //SetupRenderFrame(scene); + SetupRenderFrame(scene, cam); + // do the rendering //RenderFrame(scene); RenderFrame(scene, cam); @@ -888,13 +848,8 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat) m_overrideCamViewMat = mat; } -void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far) -{ - m_overrideCamNear = near; - m_overrideCamFar = far; -} - -void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) + +void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) { // In this function we make sure the rasterizer settings are upto // date. We compute the viewport so that logic @@ -902,26 +857,17 @@ void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& a // Note we postpone computation of the projection matrix // so that we are using the latest camera position. + + RAS_Rect viewport; + + if (!cam) + return; + if (cam->GetViewport()) { - RAS_Rect userviewport; - - userviewport.SetLeft(cam->GetViewportLeft()); - userviewport.SetBottom(cam->GetViewportBottom()); - userviewport.SetRight(cam->GetViewportRight()); - userviewport.SetTop(cam->GetViewportTop()); - - // Don't do bars on user specified viewport - RAS_FrameSettings settings = scene->GetFramingType(); - if(settings.FrameType() == RAS_FrameSettings::e_frame_bars) - settings.SetFrameType(RAS_FrameSettings::e_frame_extend); - - RAS_FramingManager::ComputeViewport( - scene->GetFramingType(), - userviewport, - viewport - ); - - area = userviewport; + viewport.SetLeft(cam->GetViewportLeft()); + viewport.SetBottom(cam->GetViewportBottom()); + viewport.SetRight(cam->GetViewportRight()); + viewport.SetTop(cam->GetViewportTop()); } else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { RAS_FramingManager::ComputeViewport( @@ -929,32 +875,33 @@ void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& a m_canvas->GetDisplayArea(), viewport ); - - area = m_canvas->GetDisplayArea(); } else { viewport.SetLeft(0); viewport.SetBottom(0); viewport.SetRight(int(m_canvas->GetWidth())); viewport.SetTop(int(m_canvas->GetHeight())); - - area = m_canvas->GetDisplayArea(); } + // store the computed viewport in the scene + + scene->SetSceneViewport(viewport); + + // set the viewport for this frame and scene + m_canvas->SetViewPort( + viewport.GetLeft(), + viewport.GetBottom(), + viewport.GetRight(), + viewport.GetTop() + ); + } void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) { - CListValue *objectlist = scene->GetObjectList(); + CListValue *lightlist = scene->GetLightList(); int i, drawmode; - m_rendertools->SetAuxilaryClientInfo(scene); - - for(i=0; iGetCount(); i++) { - KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i); - - if(!gameobj->IsLight()) - continue; - - KX_LightObject *light = (KX_LightObject*)gameobj; + for(i=0; iGetCount(); i++) { + KX_LightObject *light = (KX_LightObject*)lightlist->GetValue(i); light->Update(); @@ -992,32 +939,18 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { - bool override_camera; - RAS_Rect viewport, area; float left, right, bottom, top, nearfrust, farfrust, focallength; const float ortho = 100.0; // KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; - - SetupViewport(scene, cam, area, viewport); - - // store the computed viewport in the scene - scene->SetSceneViewport(viewport); - - // set the viewport for this frame and scene - m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(), - viewport.GetRight(), viewport.GetTop()); // see KX_BlenderMaterial::Activate //m_rasterizer->SetAmbient(); m_rasterizer->DisplayFog(); - override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName); - override_camera = override_camera && (cam->GetName() == "__default__cam__"); - - if (override_camera && m_overrideCamUseOrtho) { + if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) { MT_CmMatrix4x4 projmat = m_overrideCamProjMat; m_rasterizer->SetProjectionMatrix(projmat); } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) @@ -1027,17 +960,12 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { RAS_FrameFrustum frustum; float lens = cam->GetLens(); - bool orthographic = !cam->GetCameraData()->m_perspective; nearfrust = cam->GetCameraNear(); farfrust = cam->GetCameraFar(); focallength = cam->GetFocalLength(); - if(override_camera) { - nearfrust = m_overrideCamNear; - farfrust = m_overrideCamFar; - } - - if (orthographic) { + if (!cam->GetCameraData()->m_perspective) + { lens *= ortho; nearfrust = (nearfrust + 1.0)*ortho; farfrust *= ortho; @@ -1045,8 +973,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) RAS_FramingManager::ComputeFrustum( scene->GetFramingType(), - area, - viewport, + m_canvas->GetDisplayArea(), + scene->GetSceneViewport(), lens, nearfrust, farfrust, @@ -1062,7 +990,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( left, right, bottom, top, nearfrust, farfrust, focallength); - + cam->SetProjectionMatrix(projmat); // Otherwise the projection matrix for each eye will be the same... @@ -1353,13 +1281,12 @@ void KX_KetsjiEngine::RemoveScheduledScenes() KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename) { - Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename); + KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice, m_mousedevice, m_networkdevice, m_audiodevice, - scenename, - scene); + scenename); m_sceneconverter->ConvertScene(scenename, tmpscene, @@ -1515,11 +1442,6 @@ void KX_KetsjiEngine::SetAnimFrameRate(double framerate) m_anim_framerate = framerate; } -double KX_KetsjiEngine::GetAverageFrameRate() -{ - return m_average_framerate; -} - void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties) { m_show_framerate = frameRate; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 8fe8731dc05..77b69ec2d9e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -124,8 +124,6 @@ private: bool m_overrideCamUseOrtho; MT_CmMatrix4x4 m_overrideCamProjMat; MT_CmMatrix4x4 m_overrideCamViewMat; - float m_overrideCamNear; - float m_overrideCamFar; bool m_stereo; int m_curreye; @@ -151,8 +149,6 @@ private: /** Labels for profiling display. */ static const char m_profileLabels[tc_numCategories][15]; - /** Last estimated framerate */ - static double m_average_framerate; /** Show the framerate on the game display? */ bool m_show_framerate; /** Show profiling info on the game display? */ @@ -179,7 +175,7 @@ private: /** Blue component of framing bar color. */ float m_overrideFrameColorB; - void SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); + void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); void RenderFrame(KX_Scene* scene, KX_Camera* cam); void PostRenderFrame(); void RenderDebugProperties(); @@ -238,7 +234,6 @@ public: void SetCameraOverrideUseOrtho(bool useOrtho); void SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat); void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat); - void SetCameraOverrideClipping(float near, float far); /** * Sets display of all frames. @@ -276,11 +271,6 @@ public: */ static void SetAnimFrameRate(double framerate); - /** - * Gets the last estimated average framerate - */ - static double GetAverageFrameRate(); - /** * Activates or deactivates timing information display. * @param frameRate Display for frame rate on or off. @@ -358,7 +348,6 @@ protected: KX_Scene* CreateScene(const STR_String& scenename); bool BeginFrame(); - void ClearFrame(); void EndFrame(); }; diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index e0f171e78e0..4e3d6180d22 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -42,13 +42,14 @@ #include "KX_PyMath.h" -#include "DNA_object_types.h" +#ifdef BLENDER_GLSL #include "GPU_material.h" +#endif KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, const RAS_LightObject& lightobj, - bool glsl, + struct GPULamp *gpulamp, PyTypeObject* T ) : @@ -58,20 +59,12 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, m_lightobj = lightobj; m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr(); m_rendertools->AddLight(&m_lightobj); - m_glsl = glsl; - m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene(); + m_gpulamp = gpulamp; }; KX_LightObject::~KX_LightObject() { - GPULamp *lamp; - - if((lamp = GetGPULamp())) { - float obmat[4][4] = {{0}}; - GPU_lamp_update(lamp, 0, obmat); - } - m_rendertools->RemoveLight(&m_lightobj); } @@ -80,7 +73,7 @@ CValue* KX_LightObject::GetReplica() { KX_LightObject* replica = new KX_LightObject(*this); - + // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -88,23 +81,13 @@ CValue* KX_LightObject::GetReplica() replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr(); m_rendertools->AddLight(&replica->m_lightobj); - return replica; } -GPULamp *KX_LightObject::GetGPULamp() -{ - if(m_glsl) - return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject()); - else - return false; -} - void KX_LightObject::Update() { - GPULamp *lamp; - - if((lamp = GetGPULamp())) { +#ifdef BLENDER_GLSL + if(m_gpulamp) { float obmat[4][4]; double *dobmat = GetOpenGLMatrixPtr()->getPointer(); @@ -112,39 +95,38 @@ void KX_LightObject::Update() for(int j=0; j<4; j++, dobmat++) obmat[i][j] = (float)*dobmat; - GPU_lamp_update(lamp, m_lightobj.m_layer, obmat); + GPU_lamp_update(m_gpulamp, obmat); } +#endif } bool KX_LightObject::HasShadowBuffer() { - GPULamp *lamp; - - if((lamp = GetGPULamp())) - return GPU_lamp_has_shadow_buffer(lamp); - else - return false; +#ifdef BLENDER_GLSL + return (m_gpulamp && GPU_lamp_has_shadow_buffer(m_gpulamp)); +#else + return false; +#endif } int KX_LightObject::GetShadowLayer() { - GPULamp *lamp; - - if((lamp = GetGPULamp())) - return GPU_lamp_shadow_layer(lamp); +#ifdef BLENDER_GLSL + if(m_gpulamp) + return GPU_lamp_shadow_layer(m_gpulamp); else +#endif return 0; } void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans) { - GPULamp *lamp; +#ifdef BLENDER_GLSL float viewmat[4][4], winmat[4][4]; int winsize; /* bind framebuffer */ - lamp = GetGPULamp(); - GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat); + GPU_lamp_shadow_buffer_bind(m_gpulamp, viewmat, &winsize, winmat); /* setup camera transformation */ MT_Matrix4x4 modelviewmat((float*)viewmat); @@ -164,12 +146,14 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T ras->SetProjectionMatrix(projectionmat); ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(), cam->GetCameraLocation(), cam->GetCameraOrientation()); +#endif } void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) { - GPULamp *lamp = GetGPULamp(); - GPU_lamp_shadow_buffer_unbind(lamp); +#ifdef BLENDER_GLSL + GPU_lamp_shadow_buffer_unbind(m_gpulamp); +#endif } PyObject* KX_LightObject::_getattr(const STR_String& attr) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index e5dbf0b7f4a..62eb26c61a8 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -33,7 +33,6 @@ #include "KX_GameObject.h" struct GPULamp; -struct Scene; class KX_Camera; class RAS_IRasterizer; class RAS_IRenderTools; @@ -45,18 +44,16 @@ class KX_LightObject : public KX_GameObject protected: RAS_LightObject m_lightobj; class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj - bool m_glsl; - Scene* m_blenderscene; - static char doc[]; + struct GPULamp *m_gpulamp; + static char doc[]; 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, struct GPULamp *gpulamp, PyTypeObject *T = &Type); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} /* GLSL shadow */ - struct GPULamp *GetGPULamp(); bool HasShadowBuffer(); int GetShadowLayer(); void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); @@ -65,8 +62,6 @@ public: virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ virtual int _setattr(const STR_String& attr, PyObject *pyvalue); - - virtual bool IsLight(void) { return true; } }; #endif //__KX_LIGHT diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 5cc102248f2..a0ac9cfd4ff 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -35,7 +35,6 @@ #include "RAS_MeshObject.h" #include "KX_VertexProxy.h" -#include "KX_PolyProxy.h" #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" @@ -43,8 +42,6 @@ #include "KX_PyMath.h" #include "KX_ConvertPhysicsObject.h" -#include "PyObjectPlus.h" - PyTypeObject KX_MeshProxy::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -74,12 +71,10 @@ PyParentObject KX_MeshProxy::Parents[] = { PyMethodDef KX_MeshProxy::Methods[] = { {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS}, -{"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS}, {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, -{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh), //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, @@ -98,11 +93,10 @@ KX_MeshProxy::_getattr(const STR_String& attr) if (attr == "materials") { PyObject *materials = PyList_New(0); - list::iterator mit = m_meshobj->GetFirstMaterial(); + RAS_MaterialBucket::Set::iterator mit = m_meshobj->GetFirstMaterial(); for(; mit != m_meshobj->GetLastMaterial(); ++mit) { - RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); - + RAS_IPolyMaterial *polymat = (*mit)->GetPolyMaterial(); if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *mat = static_cast(polymat); @@ -152,12 +146,6 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self, return PyInt_FromLong(num); } -PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self) -{ - int num = m_meshobj->NumPolygons(); - return PyInt_FromLong(num); -} - PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, PyObject* args, PyObject* kwds) @@ -207,11 +195,11 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self, if (PyArg_ParseTuple(args,"i",&matid)) { - RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); - RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial(); - + RAS_IPolyMaterial* mat = m_meshobj->GetMaterialBucket(matid)->GetPolyMaterial(); if (mat) - length = m_meshobj->NumVertices(mat); + { + length = m_meshobj->GetVertexArrayLength(mat); + } } else { return NULL; @@ -246,28 +234,6 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, } -PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self, - PyObject* args, - PyObject* kwds) -{ - int polyindex= 1; - PyObject* polyob = NULL; - - if (!PyArg_ParseTuple(args,"i",&polyindex)) - return NULL; - - RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex); - if (polygon) - { - polyob = new KX_PolyProxy(m_meshobj, polygon); - } - else - { - PyErr_SetString(PyExc_AttributeError, "Invalid polygon index"); - } - return polyob; -} - KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh, "Reinstance the physics mesh.") { diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 3335c349673..7c6202c15a4 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -57,12 +57,10 @@ public: KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); KX_PYMETHOD(KX_MeshProxy,GetMaterialName); KX_PYMETHOD(KX_MeshProxy,GetTextureName); - KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons); // both take materialid (int) KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); - KX_PYMETHOD(KX_MeshProxy,GetPolygon); KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh); }; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 3156f543ed5..db0bef8b7e1 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -122,10 +122,16 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event) return result; } -bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* result, void * const data) +bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { KX_GameObject* hitKXObj = client_info->m_gameobject; + if (client_info->m_type > KX_ClientObjectInfo::ACTOR) + { + // false hit + return false; + } + /* Is this me? In the ray test, there are a lot of extra checks * for aliasing artefacts from self-hits. That doesn't happen * here, so a simple test suffices. Or does the camera also get @@ -136,8 +142,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* r if ((m_focusmode == 2) || hitKXObj == thisObj) { m_hitObject = hitKXObj; - m_hitPosition = result->m_hitPoint; - m_hitNormal = result->m_hitNormal; + m_hitPosition = hit_point; + m_hitNormal = hit_normal; return true; } @@ -152,6 +158,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) m_hitObject = 0; m_hitPosition = MT_Vector3(0,0,0); m_hitNormal = MT_Vector3(1,0,0); + MT_Point3 resultpoint; + MT_Vector3 resultnormal; /* All screen handling in the gameengine is done by GL, * specifically the model/view and projection parts. The viewport @@ -272,8 +280,7 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) bool result = false; - KX_RayCast::Callback callback(this,physics_controller); - KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback); + result = KX_RayCast::RayTest(physics_controller, physics_environment, frompoint3, topoint3, resultpoint, resultnormal, KX_RayCast::Callback(this)); result = (m_hitObject!=0); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index a6cc39d66eb..b011ebe1288 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -33,8 +33,6 @@ #include "SCA_MouseSensor.h" -class KX_RayCast; - /** * The mouse focus sensor extends the basic SCA_MouseSensor. It has * been placed in KX because it needs access to the rasterizer and @@ -78,9 +76,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor return result; }; - bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); - bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } - + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); /* --------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 3ca121f63f8..344e0fccc35 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -36,8 +36,6 @@ #include "KX_GameObject.h" #include "KX_PythonInit.h" -#include "PyObjectPlus.h" - #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index da4f05ced7c..9291199d859 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -27,8 +27,6 @@ * ***** END GPL LICENSE BLOCK ***** */ #include -#include "PyObjectPlus.h" - #include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index c9180bf3a80..144f74a1a4c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -35,6 +35,10 @@ #include "BKE_global.h" #include "BKE_image.h" +extern "C" { +#include "BDR_drawmesh.h" +} + #include "DNA_material_types.h" #include "DNA_texture_types.h" #include "DNA_image_types.h" @@ -42,8 +46,6 @@ #include "IMB_imbuf_types.h" -#include "GPU_draw.h" - #include "MEM_guardedalloc.h" #include "RAS_LightObject.h" @@ -61,6 +63,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, bool alpha, bool zsort, int lightlayer, + bool bIsTriangle, + void* clientobject, struct MTFace* tface, unsigned int* mcol, PyTypeObject *T) @@ -74,7 +78,9 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, transp, alpha, zsort, - lightlayer), + lightlayer, + bIsTriangle, + clientobject), m_tface(tface), m_mcol(mcol), m_material(material), @@ -134,29 +140,38 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - GPU_set_tpage(NULL); - + { + set_tpage(NULL); + } cachingInfo = GetCachingInfo(); if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)) { - Image *ima = (Image*)m_tface->tpage; - GPU_update_image_time(ima, rasty->GetTime()); - GPU_set_tpage(m_tface); + update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime()); + set_tpage(m_tface); + rasty->EnableTextures(true); } else - GPU_set_tpage(NULL); + { + set_tpage(NULL); + rasty->EnableTextures(false); + } if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) + { rasty->SetCullFace(false); + } else + { rasty->SetCullFace(true); + } - if ((m_drawingmode & RAS_IRasterizer::KX_LINES) || - (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) + if (m_drawingmode & RAS_IRasterizer::KX_LINES) { rasty->SetLines(true); - else + } + else { rasty->SetLines(false); + } } rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity); @@ -238,8 +253,7 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) if (attr == "lightlayer") return PyInt_FromLong(m_lightlayer); if (attr == "triangle") - // deprecated, triangle/quads shouldn't have been a material property - return 0; + return PyInt_FromLong(m_bIsTriangle); if (attr == "diffuse") return PyObjectFrom(m_diffuse); @@ -319,7 +333,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) // This probably won't work... if (attr == "triangle") { - // deprecated, triangle/quads shouldn't have been a material property + m_bIsTriangle = value; return 0; } } @@ -372,9 +386,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty); - Image *ima = (Image*)tface->tpage; - GPU_update_image_time(ima, rasty->GetTime()); - + update_realtime_texture(tface, rasty->GetTime()); Py_Return; } @@ -387,7 +399,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") if (PyArg_ParseTuple(args, "O!", &PyCObject_Type, &pytface)) { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); - GPU_set_tpage(tface); + set_tpage(tface); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index fe116f757db..11c8baa8b1f 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -68,6 +68,8 @@ public: bool alpha, bool zsort, int lightlayer, + bool bIsTriangle, + void* clientobject, struct MTFace* tface, unsigned int* mcol, PyTypeObject *T = &Type); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index ac63e3fade5..26243c7dba1 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -34,8 +34,6 @@ #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" -#include "PyObjectPlus.h" - #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 5308a0b9536..5d2126ca37a 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -57,25 +57,21 @@ #include "BL_ActionActuator.h" #include "RAS_IRasterizer.h" #include "RAS_ICanvas.h" -#include "RAS_BucketManager.h" #include "MT_Vector3.h" #include "MT_Point3.h" #include "ListValue.h" #include "KX_Scene.h" #include "SND_DeviceManager.h" +#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" #include "BL_Shader.h" #include "KX_PyMath.h" -#include "PyObjectPlus.h" - extern "C" { #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. } -#include "marshal.h" /* python header for loading/saving dicts */ - #include "PHY_IPhysicsEnvironment.h" // FIXME: Enable for access to blender python modules. This is disabled because // python has dependencies on a lot of other modules and is a pain to link. @@ -87,7 +83,6 @@ extern "C" { #include "BKE_utildefines.h" #include "BKE_global.h" #include "BLI_blenlib.h" -#include "GPU_material.h" static void setSandbox(TPythonSecurityLevel level); @@ -95,7 +90,6 @@ static void setSandbox(TPythonSecurityLevel level); // 'local' copy of canvas ptr, for window height/width python scripts static RAS_ICanvas* gp_Canvas = NULL; static KX_Scene* gp_KetsjiScene = NULL; -static KX_KetsjiEngine* gp_KetsjiEngine = NULL; static RAS_IRasterizer* gp_Rasterizer = NULL; void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) @@ -127,13 +121,15 @@ static PyObject* gPyGetRandomFloat(PyObject*) static PyObject* gPySetGravity(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) - return NULL; - - if (gp_KetsjiScene) - gp_KetsjiScene->SetGravity(vec); + if (PyVecArgTo(args, vec)) + { + if (gp_KetsjiScene) + gp_KetsjiScene->SetGravity(vec); + + Py_Return; + } - Py_RETURN_NONE; + return NULL; } static char gPyExpandPath_doc[] = @@ -151,12 +147,13 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) char expanded[FILE_MAXDIR + FILE_MAXFILE]; char* filename; - if (!PyArg_ParseTuple(args,"s",&filename)) - return NULL; - - BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); - BLI_convertstringcode(expanded, G.sce); - return PyString_FromString(expanded); + if (PyArg_ParseTuple(args,"s",&filename)) + { + BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); + BLI_convertstringcode(expanded, G.sce); + return PyString_FromString(expanded); + } + return NULL; } @@ -184,12 +181,6 @@ static PyObject* gPyGetSpectrum(PyObject*) PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index])); } } - else { - for (int index = 0; index < 512; index++) - { - PyList_SetItem(resultlist, index, PyFloat_FromDouble(0.0)); - } - } return resultlist; } @@ -200,17 +191,16 @@ static PyObject* gPyStartDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); - if (!audiodevice) { - PyErr_SetString(PyExc_RuntimeError, "no audio device available"); - return NULL; + if (audiodevice) + { + if (!usedsp) + { + audiodevice->StartUsingDSP(); + usedsp = true; + Py_Return; + } } - - if (!usedsp) { - audiodevice->StartUsingDSP(); - usedsp = true; - } - - Py_RETURN_NONE; + return NULL; } @@ -219,27 +209,28 @@ static PyObject* gPyStopDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); - if (!audiodevice) { - PyErr_SetString(PyExc_RuntimeError, "no audio device available"); - return NULL; + if (audiodevice) + { + if (usedsp) + { + audiodevice->StopUsingDSP(); + usedsp = false; + Py_Return; + } } - - if (usedsp) { - audiodevice->StopUsingDSP(); - usedsp = true; - } - - Py_RETURN_NONE; + return NULL; } static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) { float ticrate; - if (!PyArg_ParseTuple(args, "f", &ticrate)) - return NULL; + if (PyArg_ParseTuple(args, "f", &ticrate)) + { + KX_KetsjiEngine::SetTicRate(ticrate); + Py_Return; + } - KX_KetsjiEngine::SetTicRate(ticrate); - Py_RETURN_NONE; + return NULL; } static PyObject* gPyGetLogicTicRate(PyObject*) @@ -250,21 +241,26 @@ static PyObject* gPyGetLogicTicRate(PyObject*) static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; - if (!PyArg_ParseTuple(args, "f", &ticrate)) - return NULL; + if (PyArg_ParseTuple(args, "f", &ticrate)) + { + + PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); + Py_Return; + } - PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); - Py_RETURN_NONE; + return NULL; } static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) { int debugMode; - if (!PyArg_ParseTuple(args, "i", &debugMode)) - return NULL; + if (PyArg_ParseTuple(args, "i", &debugMode)) + { + PHY_GetActiveEnvironment()->setDebugMode(debugMode); + Py_Return; + } - PHY_GetActiveEnvironment()->setDebugMode(debugMode); - Py_RETURN_NONE; + return NULL; } @@ -274,16 +270,11 @@ static PyObject* gPyGetPhysicsTicRate(PyObject*) return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep()); } -static PyObject* gPyGetAverageFrameRate(PyObject*) -{ - return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate()); -} - static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) { char cpath[sizeof(G.sce)]; char *searchpath = NULL; - PyObject* list, *value; + PyObject* list; DIR *dp; struct dirent *dirp; @@ -303,15 +294,13 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) if((dp = opendir(cpath)) == NULL) { /* todo, show the errno, this shouldnt happen anyway if the blendfile is readable */ - fprintf(stderr, "Could not read directoty (%s) failed, code %d (%s)\n", cpath, errno, strerror(errno)); + fprintf(stderr, "Could not read directoty () failed, code %d (%s)\n", cpath, errno, strerror(errno)); return list; } while ((dirp = readdir(dp)) != NULL) { if (BLI_testextensie(dirp->d_name, ".blend")) { - value = PyString_FromString(dirp->d_name); - PyList_Append(list, value); - Py_DECREF(value); + PyList_Append(list, PyString_FromString(dirp->d_name)); } } @@ -418,7 +407,6 @@ static struct PyMethodDef game_methods[] = { {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, "Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, "Gets the physics tic rate"}, {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, "Sets the physics tic rate"}, - {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, "Gets the estimated average frame rate"}, {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, "Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, "Prints GL Extension Info"}, {NULL, (PyCFunction) NULL, 0, NULL } @@ -427,14 +415,22 @@ static struct PyMethodDef game_methods[] = { static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { - return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); + int height = (gp_Canvas ? gp_Canvas->GetHeight() : 0); + + PyObject* heightval = PyInt_FromLong(height); + return heightval; } static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) { - return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); + + + int width = (gp_Canvas ? gp_Canvas->GetWidth() : 0); + + PyObject* widthval = PyInt_FromLong(width); + return widthval; } @@ -445,11 +441,15 @@ bool gUseVisibilityTemp = false; static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) { int visible; - if (!PyArg_ParseTuple(args,"i",&visible)) + if (PyArg_ParseTuple(args,"i",&visible)) + { + gUseVisibilityTemp = (visible != 0); + } + else + { return NULL; - - gUseVisibilityTemp = (visible != 0); - Py_RETURN_NONE; + } + Py_Return; } @@ -457,20 +457,23 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) static PyObject* gPyShowMouse(PyObject*, PyObject* args) { int visible; - if (!PyArg_ParseTuple(args,"i",&visible)) + if (PyArg_ParseTuple(args,"i",&visible)) + { + if (visible) + { + if (gp_Canvas) + gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); + } else + { + if (gp_Canvas) + gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); + } + } + else { return NULL; - - if (visible) - { - if (gp_Canvas) - gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); - } else - { - if (gp_Canvas) - gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); } - Py_RETURN_NONE; + Py_Return; } @@ -478,81 +481,74 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args) static PyObject* gPySetMousePosition(PyObject*, PyObject* args) { int x,y; - if (!PyArg_ParseTuple(args,"ii",&x,&y)) + if (PyArg_ParseTuple(args,"ii",&x,&y)) + { + if (gp_Canvas) + gp_Canvas->SetMousePosition(x,y); + } + else { return NULL; + } - if (gp_Canvas) - gp_Canvas->SetMousePosition(x,y); - - Py_RETURN_NONE; + Py_Return; } static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) { float sep; - if (!PyArg_ParseTuple(args, "f", &sep)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; + if (PyArg_ParseTuple(args, "f", &sep)) + { + if (gp_Rasterizer) + gp_Rasterizer->SetEyeSeparation(sep); + + Py_Return; } - gp_Rasterizer->SetEyeSeparation(sep); - - Py_RETURN_NONE; + return NULL; } static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*) { - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; - } + if (gp_Rasterizer) + return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); - return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); + return NULL; } static PyObject* gPySetFocalLength(PyObject*, PyObject* args) { float focus; - if (!PyArg_ParseTuple(args, "f", &focus)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; + if (PyArg_ParseTuple(args, "f", &focus)) + { + if (gp_Rasterizer) + gp_Rasterizer->SetFocalLength(focus); + Py_Return; } - - gp_Rasterizer->SetFocalLength(focus); - Py_RETURN_NONE; + return NULL; } static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) { - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; - } - - return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength()); - - Py_RETURN_NONE; + if (gp_Rasterizer) + return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength()); + return NULL; } static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) { MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.); - if (!PyVecArgTo(args, vec)) - return NULL; - - if (gp_Canvas) + if (PyVecArgTo(args, vec)) { - gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]); + if (gp_Canvas) + { + gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]); + } + Py_Return; } - Py_RETURN_NONE; + + return NULL; } @@ -561,16 +557,16 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) - return NULL; + if (PyVecArgTo(args, vec)) + { + if (gp_Rasterizer) + { + gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); + } + Py_Return; + } - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; - } - gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); - - Py_RETURN_NONE; + return NULL; } @@ -579,17 +575,17 @@ static PyObject* gPySetMistStart(PyObject*, PyObject* args) { float miststart; - if (!PyArg_ParseTuple(args,"f",&miststart)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + if (PyArg_ParseTuple(args,"f",&miststart)) + { + if (gp_Rasterizer) + { + gp_Rasterizer->SetFogStart(miststart); + } + } + else { return NULL; } - - gp_Rasterizer->SetFogStart(miststart); - - Py_RETURN_NONE; + Py_Return; } @@ -598,17 +594,17 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) { float mistend; - if (!PyArg_ParseTuple(args,"f",&mistend)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + if (PyArg_ParseTuple(args,"f",&mistend)) + { + if (gp_Rasterizer) + { + gp_Rasterizer->SetFogEnd(mistend); + } + } + else { return NULL; } - - gp_Rasterizer->SetFogEnd(mistend); - - Py_RETURN_NONE; + Py_Return; } @@ -616,16 +612,16 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (!PyVecArgTo(args, vec)) - return NULL; + if (PyVecArgTo(args, vec)) + { + if (gp_Rasterizer) + { + gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); + } + Py_Return; + } - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; - } - gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); - - Py_RETURN_NONE; + return NULL; } @@ -634,167 +630,42 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) { char* filename; - if (!PyArg_ParseTuple(args,"s",&filename)) - return NULL; - - if (gp_Canvas) + if (PyArg_ParseTuple(args,"s",&filename)) { - gp_Canvas->MakeScreenShot(filename); + if (gp_Canvas) + { + gp_Canvas->MakeScreenShot(filename); + } } - - Py_RETURN_NONE; + else { + return NULL; + } + Py_Return; } static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) { float motionblurvalue; - if (!PyArg_ParseTuple(args,"f",&motionblurvalue)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + if (PyArg_ParseTuple(args,"f",&motionblurvalue)) + { + if(gp_Rasterizer) + { + gp_Rasterizer->EnableMotionBlur(motionblurvalue); + } + } + else { return NULL; } - - gp_Rasterizer->EnableMotionBlur(motionblurvalue); - - Py_RETURN_NONE; + Py_Return; } static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args) { - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); - return NULL; + if(gp_Rasterizer) + { + gp_Rasterizer->DisableMotionBlur(); } - - gp_Rasterizer->DisableMotionBlur(); - - Py_RETURN_NONE; -} - -int getGLSLSettingFlag(char *setting) -{ - if(strcmp(setting, "lights") == 0) - return G_FILE_GLSL_NO_LIGHTS; - else if(strcmp(setting, "shaders") == 0) - return G_FILE_GLSL_NO_SHADERS; - else if(strcmp(setting, "shadows") == 0) - return G_FILE_GLSL_NO_SHADOWS; - else if(strcmp(setting, "ramps") == 0) - return G_FILE_GLSL_NO_RAMPS; - else if(strcmp(setting, "nodes") == 0) - return G_FILE_GLSL_NO_NODES; - else if(strcmp(setting, "extra_textures") == 0) - return G_FILE_GLSL_NO_EXTRA_TEX; - else - return -1; -} - -static PyObject* gPySetGLSLMaterialSetting(PyObject*, - PyObject* args, - PyObject*) -{ - char *setting; - int enable, flag, fileflags; - - if (!PyArg_ParseTuple(args,"si",&setting,&enable)) - return NULL; - - flag = getGLSLSettingFlag(setting); - - if (flag==-1) { - PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); - return NULL; - } - - fileflags = G.fileflags; - - if (enable) - G.fileflags &= ~flag; - else - G.fileflags |= flag; - - /* display lists and GLSL materials need to be remade */ - if(G.fileflags != fileflags) { - if(gp_KetsjiEngine) { - KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); - KX_SceneList::iterator it; - - for(it=scenes->begin(); it!=scenes->end(); it++) - if((*it)->GetBucketManager()) - (*it)->GetBucketManager()->ReleaseDisplayLists(); - } - - GPU_materials_free(); - } - - Py_RETURN_NONE; -} - -static PyObject* gPyGetGLSLMaterialSetting(PyObject*, - PyObject* args, - PyObject*) -{ - char *setting; - int enabled = 0, flag; - - if (!PyArg_ParseTuple(args,"s",&setting)) - return NULL; - - flag = getGLSLSettingFlag(setting); - - if (flag==-1) { - PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); - return NULL; - } - - enabled = ((G.fileflags & flag) != 0); - return PyInt_FromLong(enabled); -} - -#define KX_TEXFACE_MATERIAL 0 -#define KX_BLENDER_MULTITEX_MATERIAL 1 -#define KX_BLENDER_GLSL_MATERIAL 2 - -static PyObject* gPySetMaterialType(PyObject*, - PyObject* args, - PyObject*) -{ - int flag, type; - - if (!PyArg_ParseTuple(args,"i",&type)) - return NULL; - - if(type == KX_BLENDER_GLSL_MATERIAL) - flag = G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL; - else if(type == KX_BLENDER_MULTITEX_MATERIAL) - flag = G_FILE_GAME_MAT; - else if(type == KX_TEXFACE_MATERIAL) - flag = 0; - else { - PyErr_SetString(PyExc_ValueError, "material type is not known"); - return NULL; - } - - G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); - G.fileflags |= flag; - - Py_RETURN_NONE; -} - -static PyObject* gPyGetMaterialType(PyObject*) -{ - int flag; - - if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL)) - flag = KX_BLENDER_GLSL_MATERIAL; - else if(G.fileflags & G_FILE_GAME_MAT) - flag = KX_BLENDER_MULTITEX_MATERIAL; - else - flag = KX_TEXFACE_MATERIAL; - - return PyInt_FromLong(flag); + Py_Return; } STR_String gPyGetWindowHeight__doc__="getWindowHeight doc"; @@ -830,17 +701,11 @@ static struct PyMethodDef rasterizer_methods[] = { {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"}, {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, - {"setMaterialMode",(PyCFunction) gPySetMaterialType, - METH_VARARGS, "set the material mode to use for OpenGL rendering"}, - {"getMaterialMode",(PyCFunction) gPyGetMaterialType, - METH_NOARGS, "get the material mode being used for OpenGL rendering"}, - {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting, - METH_VARARGS, "set the state of a GLSL material setting"}, - {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, - METH_VARARGS, "get the state of a GLSL material setting"}, { NULL, (PyCFunction) NULL, 0, NULL } }; + + // Initialization function for the module (*must* be called initGameLogic) static char GameLogic_module_documentation[] = @@ -853,12 +718,11 @@ static char Rasterizer_module_documentation[] = -PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook +PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook { PyObject* m; PyObject* d; - gp_KetsjiEngine = engine; gp_KetsjiScene = scene; gUseVisibilityTemp=false; @@ -988,30 +852,13 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack // override builtin functions import() and open() -PyObject *KXpy_open(PyObject *self, PyObject *args) { +PyObject *KXpy_open(PyObject *self, PyObject *args) +{ PyErr_SetString(PyExc_RuntimeError, "Sandbox: open() function disabled!\nGame Scripts should not use this function."); return NULL; } -PyObject *KXpy_reload(PyObject *self, PyObject *args) { - PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function."); - return NULL; -} -PyObject *KXpy_file(PyObject *self, PyObject *args) { - PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function."); - return NULL; -} - -PyObject *KXpy_execfile(PyObject *self, PyObject *args) { - PyErr_SetString(PyExc_RuntimeError, "Sandbox: execfile() function disabled!\nGame Scripts should not use this function."); - return NULL; -} - -PyObject *KXpy_compile(PyObject *self, PyObject *args) { - PyErr_SetString(PyExc_RuntimeError, "Sandbox: compile() function disabled!\nGame Scripts should not use this function."); - return NULL; -} PyObject *KXpy_import(PyObject *self, PyObject *args) { @@ -1048,13 +895,19 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) } -static PyMethodDef meth_open[] = {{ "open", KXpy_open, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_reload[] = {{ "reload", KXpy_reload, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_file[] = {{ "file", KXpy_file, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_execfile[] = {{ "execfile", KXpy_execfile, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_compile[] = {{ "compile", KXpy_compile, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_import[] = {{ "import", KXpy_import, METH_VARARGS, "our own import"}}; +static PyMethodDef meth_open[] = { + { "open", KXpy_open, METH_VARARGS, + "(disabled)"} +}; + + +static PyMethodDef meth_import[] = { + { "import", KXpy_import, METH_VARARGS, + "our own import"} +}; + + //static PyObject *g_oldopen = 0; //static PyObject *g_oldimport = 0; @@ -1065,21 +918,15 @@ void setSandbox(TPythonSecurityLevel level) { PyObject *m = PyImport_AddModule("__builtin__"); PyObject *d = PyModule_GetDict(m); + PyObject *meth = PyCFunction_New(meth_open, NULL); switch (level) { case psl_Highest: //if (!g_security) { //g_oldopen = PyDict_GetItemString(d, "open"); - - // functions we cant trust - PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL)); - PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL)); - PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL)); - PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL)); - PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL)); - - // our own import - PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL)); + PyDict_SetItemString(d, "open", meth); + meth = PyCFunction_New(meth_import, NULL); + PyDict_SetItemString(d, "__import__", meth); //g_security = level; //} break; @@ -1163,11 +1010,6 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) ErrorObject = PyString_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); - /* needed for get/setMaterialType */ - KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); - KX_MACRO_addTypesToDict(d, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL); - KX_MACRO_addTypesToDict(d, KX_BLENDER_GLSL_MATERIAL, KX_BLENDER_GLSL_MATERIAL); - // XXXX Add constants here // Check for errors @@ -1189,38 +1031,9 @@ static char GameKeys_module_documentation[] = "This modules provides defines for key-codes" ; -static char gPyEventToString_doc[] = -"Take a valid event from the GameKeys module or Keyboard Sensor and return a name" -; -static PyObject* gPyEventToString(PyObject*, PyObject* value) -{ - PyObject* mod, *dict, *key, *val, *ret = NULL; - Py_ssize_t pos = 0; - - mod = PyImport_ImportModule( "GameKeys" ); - if (!mod) - return NULL; - - dict = PyModule_GetDict(mod); - - while (PyDict_Next(dict, &pos, &key, &val)) { - if (PyObject_Compare(value, val)==0) { - ret = key; - break; - } - } - - PyErr_Clear(); // incase there was an error clearing - Py_DECREF(mod); - if (!ret) PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event"); - else Py_INCREF(ret); - - return ret; -} static struct PyMethodDef gamekeys_methods[] = { - {"EventToString", (PyCFunction)gPyEventToString, METH_O, gPyEventToString_doc}, { NULL, (PyCFunction) NULL, 0, NULL } }; @@ -1378,66 +1191,3 @@ class KX_Scene* PHY_GetActiveScene() { return gp_KetsjiScene; } - -// utility function for loading and saving the globalDict -int saveGamePythonConfig( char **marshal_buffer) -{ - int marshal_length = 0; - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); - if (gameLogic) { - PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module - if (pyGlobalDict) { -#ifdef Py_MARSHAL_VERSION - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 -#else - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); -#endif - if (pyGlobalDictMarshal) { - marshal_length= PyString_Size(pyGlobalDictMarshal); - // for testing only - // PyObject_Print(pyGlobalDictMarshal, stderr, 0); - *marshal_buffer = PyString_AsString(pyGlobalDictMarshal); - } else { - printf("Error, GameLogic.globalDict could not be marshal'd\n"); - } - Py_DECREF(gameLogic); - } else { - printf("Error, GameLogic.globalDict was removed\n"); - } - } else { - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); - } - return marshal_length; -} - -int loadGamePythonConfig(char *marshal_buffer, int marshal_length) -{ - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); - /* Restore the dict */ - if (marshal_buffer) { - PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); - if (pyGlobalDict) { - PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. - return 1; - } else { - PyErr_Clear(); - printf("Error could not marshall string\n"); - } - } else { - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); - } - return 0; -} - -void pathGamePythonConfig( char *path ) -{ - int len = strlen(G.sce); - - strncpy(path, G.sce, sizeof(G.sce)); - /* replace extension */ - if (BLI_testextensie(path, ".blend")) { - strcpy(path+(len-6), ".bgeconf"); - } else { - strcpy(path+len, ".bgeconf"); - } -} diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 28d9d72a4c3..f094a1ca575 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -40,7 +40,7 @@ typedef enum { extern bool gUseVisibilityTemp; -PyObject* initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene); +PyObject* initGameLogic(class KX_Scene* ketsjiscene); PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level); @@ -49,10 +49,6 @@ void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); void exitGamePythonScripting(); -void pathGamePythonConfig( char *path ); -int saveGamePythonConfig( char **marshal_buffer); -int loadGamePythonConfig(char *marshal_buffer, int marshal_length); - void PHY_SetActiveScene(class KX_Scene* scene); class KX_Scene* PHY_GetActiveScene(); #include "MT_Vector3.h" diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp index 974d4b992a6..89e2d645d54 100644 --- a/source/gameengine/Ketsji/KX_RayCast.cpp +++ b/source/gameengine/Ketsji/KX_RayCast.cpp @@ -40,21 +40,7 @@ #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" -KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal) - :PHY_IRayCastFilterCallback(dynamic_cast(ignoreController), faceNormal) -{ -} - -void KX_RayCast::reportHit(PHY_RayCastResult* result) -{ - m_hitFound = true; - m_hitPoint.setValue((const float*)result->m_hitPoint); - m_hitNormal.setValue((const float*)result->m_hitNormal); - m_hitMesh = result->m_meshObject; - m_hitPolygon = result->m_polygon; -} - -bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback) +bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, MT_Point3& result_point, MT_Vector3& result_normal, const KX_RayCast& callback) { // Loops over all physics objects between frompoint and topoint, // calling callback.RayHit for each one. @@ -64,51 +50,58 @@ bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_ // returns true if an object was found, false if not. MT_Point3 frompoint(_frompoint); const MT_Vector3 todir( (topoint - frompoint).safe_normalized() ); - MT_Point3 prevpoint(_frompoint+todir*(-1.f)); PHY_IPhysicsController* hit_controller; + PHY__Vector3 phy_pos; + PHY__Vector3 phy_normal; - while((hit_controller = physics_environment->rayTest(callback, + while((hit_controller = physics_environment->rayTest(dynamic_cast(ignore_controller), frompoint.x(),frompoint.y(),frompoint.z(), - topoint.x(),topoint.y(),topoint.z())) != NULL) + topoint.x(),topoint.y(),topoint.z(), + phy_pos[0],phy_pos[1],phy_pos[2], + phy_normal[0],phy_normal[1],phy_normal[2]))) { + result_point = MT_Point3(phy_pos); + result_normal = MT_Vector3(phy_normal); KX_ClientObjectInfo* info = static_cast(hit_controller->getNewClientInfo()); if (!info) { printf("no info!\n"); MT_assert(info && "Physics controller with no client object info"); - break; + return false; } - // The biggest danger to to endless loop, prevent this by checking that the - // hit point always progresses along the ray direction.. - prevpoint -= callback.m_hitPoint; - if (prevpoint.length2() < MT_EPSILON) - break; - - if (callback.RayHit(info)) - // caller may decide to stop the loop and still cancel the hit - return callback.m_hitFound; - - // Skip past the object and keep tracing. - // Note that retrieving in a single shot multiple hit points would be possible - // but it would require some change in Bullet. - prevpoint = callback.m_hitPoint; - /* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */ - MT_Scalar marg = 0.001 + hit_controller->GetMargin(); - marg *= 2.f; + if (callback.RayHit(info, result_point, result_normal)) + return true; + + // There is a bug in the code below: the delta is computed with the wrong + // sign on the face opposite to the center, resulting in infinite looping. + // In Blender 2.45 this code was never executed because callback.RayHit() always + // returned true, causing the ray sensor to stop on the first object. + // To avoid changing the behaviour will simply return false here. + // It should be discussed if we want the ray sensor to "see" through objects + // that don't have the required property/material (condition to get here) + return false; + + // skip past the object and keep tracing + /* We add 0.01 of fudge, so that if the margin && radius == 0., we don't endless loop. */ + MT_Scalar marg = 0.01 + hit_controller->GetMargin(); + marg += 2.f * hit_controller->GetMargin(); /* Calculate the other side of this object */ - MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal)); - if (h <= 0.01) - // the normal is almost orthogonal to the ray direction, cannot compute the other side - break; - marg /= h; - frompoint = callback.m_hitPoint + marg * todir; - // verify that we are not passed the to point - if ((topoint - frompoint).dot(todir) < 0.f) - break; + PHY__Vector3 hitpos; + hit_controller->getPosition(hitpos); + MT_Point3 hitObjPos(hitpos); + + MT_Vector3 hitvector = hitObjPos - result_point; + if (hitvector.dot(hitvector) > MT_EPSILON) + { + hitvector.normalize(); + marg *= 2.*todir.dot(hitvector); + } + frompoint = result_point + marg * todir; } - return false; + + return hit_controller; } diff --git a/source/gameengine/Ketsji/KX_RayCast.h b/source/gameengine/Ketsji/KX_RayCast.h index c3084c997a1..607dabd8afc 100644 --- a/source/gameengine/Ketsji/KX_RayCast.h +++ b/source/gameengine/Ketsji/KX_RayCast.h @@ -30,14 +30,12 @@ #ifndef __KX_RAYCAST_H__ #define __KX_RAYCAST_H__ -#include "PHY_IPhysicsEnvironment.h" -#include "PHY_IPhysicsController.h" -#include "MT_Point3.h" -#include "MT_Vector3.h" - -class RAS_MeshObject; -struct KX_ClientObjectInfo; +class MT_Point3; +class MT_Vector3; class KX_IPhysicsController; +class PHY_IPhysicsEnvironment; + +struct KX_ClientObjectInfo; /** * Defines a function for doing a ray cast. @@ -51,27 +49,17 @@ class KX_IPhysicsController; * * Returns true if a client was accepted, false if nothing found. */ -class KX_RayCast : public PHY_IRayCastFilterCallback +class KX_RayCast { +protected: + KX_RayCast() {}; public: - bool m_hitFound; - MT_Point3 m_hitPoint; - MT_Vector3 m_hitNormal; - const RAS_MeshObject* m_hitMesh; - int m_hitPolygon; - - KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal); virtual ~KX_RayCast() {} - /** - * The physic environment returns the ray casting result through this function - */ - virtual void reportHit(PHY_RayCastResult* result); - /** ray test callback. * either override this in your class, or use a callback wrapper. */ - virtual bool RayHit(KX_ClientObjectInfo* client) = 0; + virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const = 0; /** * Callback wrapper. @@ -83,11 +71,13 @@ public: /// Public interface. /// Implement bool RayHit in your class to receive ray callbacks. - static bool RayTest( + static bool RayTest(KX_IPhysicsController* physics_controller, PHY_IPhysicsEnvironment* physics_environment, - const MT_Point3& frompoint, + const MT_Point3& _frompoint, const MT_Point3& topoint, - KX_RayCast& callback); + MT_Point3& result_point, + MT_Vector3& result_normal, + const KX_RayCast& callback); }; @@ -96,32 +86,18 @@ template class KX_RayCast::Callback : public KX_RayCast T *self; void *data; public: - Callback(T *_self, KX_IPhysicsController* controller=NULL, void *_data = NULL, bool faceNormal=false) - : KX_RayCast(controller, faceNormal), - self(_self), + Callback(T *_self, void *_data = NULL) + : self(_self), data(_data) { } ~Callback() {} - - virtual bool RayHit(KX_ClientObjectInfo* client) + + virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const { - return self->RayHit(client, this, data); + return self->RayHit(client, hit_point, hit_normal, data); } - - virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller) - { - KX_ClientObjectInfo* info = static_cast(controller->getNewClientInfo()); - - if (!info) - { - MT_assert(info && "Physics controller with no client object info"); - return false; - } - return self->NeedRayCast(info); - } - }; diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 8dc22fe13c1..a416c8c9f89 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -51,7 +51,6 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, bool bFindMaterial, - bool bXRay, double distance, int axis, KX_Scene* ketsjiScene, @@ -59,7 +58,6 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, : SCA_ISensor(gameobj,eventmgr, T), m_propertyname(propname), m_bFindMaterial(bFindMaterial), - m_bXRay(bXRay), m_distance(distance), m_scene(ketsjiScene), m_axis(axis) @@ -106,10 +104,16 @@ bool KX_RaySensor::IsPositiveTrigger() return result; } -bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) +bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; + + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // false hit + return false; + } bool bFound = false; if (m_propertyname.Length() == 0) @@ -135,43 +139,16 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void { m_rayHit = true; m_hitObject = hitKXObj; - m_hitPosition = result->m_hitPoint; - m_hitNormal = result->m_hitNormal; + m_hitPosition = hit_point; + m_hitNormal = hit_normal; } - // no multi-hit search yet - return true; + + return bFound; + } -/* this function is used to pre-filter the object before casting the ray on them. - This is useful for "X-Ray" option when we want to see "through" unwanted object. - */ -bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo* client) -{ - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // Unknown type of object, skip it. - // Should not occur as the sensor objects are filtered in RayTest() - printf("Invalid client type %d found ray casting\n", client->m_type); - return false; - } - if (m_bXRay && m_propertyname.Length() != 0) - { - if (m_bFindMaterial) - { - // not quite correct: an object may have multiple material - // should check all the material and not only the first one - if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info))) - return false; - } - else - { - if (client->m_gameobject->GetProperty(m_propertyname) == NULL) - return false; - } - } - return true; -} + bool KX_RaySensor::Evaluate(CValue* event) { @@ -238,6 +215,8 @@ bool KX_RaySensor::Evaluate(CValue* event) m_rayDirection = todir; MT_Point3 topoint = frompoint + (m_distance) * todir; + MT_Point3 resultpoint; + MT_Vector3 resultnormal; PHY_IPhysicsEnvironment* pe = m_scene->GetPhysicsEnvironment(); if (!pe) @@ -259,8 +238,7 @@ bool KX_RaySensor::Evaluate(CValue* event) PHY_IPhysicsEnvironment* physics_environment = this->m_scene->GetPhysicsEnvironment(); - KX_RayCast::Callback callback(this, spc); - KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback); + result = KX_RayCast::RayTest(spc, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this)); /* now pass this result to some controller */ @@ -287,10 +265,6 @@ bool KX_RaySensor::Evaluate(CValue* event) // notify logicsystem that ray JUST left the Object result = true; } - else - { - result = false; - } } if (reset) diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index 02a755fedc1..f4305b053d1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -36,14 +36,12 @@ #include "MT_Point3.h" struct KX_ClientObjectInfo; -class KX_RayCast; class KX_RaySensor : public SCA_ISensor { Py_Header; STR_String m_propertyname; bool m_bFindMaterial; - bool m_bXRay; double m_distance; class KX_Scene* m_scene; bool m_bTriggered; @@ -58,8 +56,7 @@ public: KX_RaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, - bool bFindMaterial, - bool bXRay, + bool fFindMaterial, double distance, int axis, class KX_Scene* ketsjiScene, @@ -71,8 +68,7 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); - bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); - bool NeedRayCast(KX_ClientObjectInfo* client); + bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); KX_PYMETHOD_DOC(KX_RaySensor,GetHitObject); KX_PYMETHOD_DOC(KX_RaySensor,GetHitPosition); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index c4c190e9fa1..ca0106d64d9 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -39,8 +39,6 @@ #include "KX_GameObject.h" #include "KX_IPhysicsController.h" -#include "PyObjectPlus.h" - #ifdef HAVE_CONFIG_H #include #endif @@ -54,20 +52,14 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, int time, SCA_IScene* scene, const MT_Vector3& linvel, - bool linv_local, - const MT_Vector3& angvel, - bool angv_local, + bool local, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_OriginalObject(original), m_scene(scene), - m_linear_velocity(linvel), - m_localLinvFlag(linv_local), - - m_angular_velocity(angvel), - m_localAngvFlag(angv_local) + m_localFlag(local) { if (m_OriginalObject) m_OriginalObject->RegisterActuator(this); @@ -189,15 +181,13 @@ PyParentObject KX_SCA_AddObjectActuator::Parents[] = { }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, SetObject_doc}, - {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, SetTime_doc}, + {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc}, {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc}, - {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, GetTime_doc}, - {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, GetLinearVelocity_doc}, + {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc}, + {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc}, {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc}, - {"getAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetAngularVelocity, METH_NOARGS, GetAngularVelocity_doc}, - {"setAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetAngularVelocity, METH_VARARGS, SetAngularVelocity_doc}, - {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_NOARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, - {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, + {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, + {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_VARARGS,"instantAddObject() : immediately add object without delay\n"}, {NULL,NULL} //Sentinel }; @@ -241,18 +231,19 @@ char KX_SCA_AddObjectActuator::SetTime_doc[] = "\tIf the duration is negative, it is set to 0.\n"; -PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value) +PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, + PyObject* args, + PyObject* kwds) { - int deltatime = PyInt_AsLong(value); - if (deltatime==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected an int"); + int deltatime; + + if (!PyArg_ParseTuple(args, "i", &deltatime)) return NULL; - } m_timeProp = deltatime; if (m_timeProp < 0) m_timeProp = 0; - Py_RETURN_NONE; + Py_Return; } @@ -263,7 +254,9 @@ char KX_SCA_AddObjectActuator::GetTime_doc[] = "\tReturns the lifetime of the object that will be added.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self, + PyObject* args, + PyObject* kwds) { return PyInt_FromLong(m_timeProp); } @@ -297,13 +290,17 @@ char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = "\tReturns the linear velocity that will be assigned to \n" "\tthe created object.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self) + + +PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self, + PyObject* args, + PyObject* kwds) { PyObject *retVal = PyList_New(3); - PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); - PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); - PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); + PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); + PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); + PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); return retVal; } @@ -316,10 +313,12 @@ char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = "\t- vx: float\n" "\t- vy: float\n" "\t- vz: float\n" -"\t- local: bool\n" "\tAssign this velocity to the created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* args) + +PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, + PyObject* args, + PyObject* kwds) { float vecArg[3]; @@ -327,46 +326,7 @@ PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject return NULL; m_linear_velocity.setValue(vecArg); - Py_RETURN_NONE; -} - -/* 7. getAngularVelocity */ -char KX_SCA_AddObjectActuator::GetAngularVelocity_doc[] = -"GetAngularVelocity()\n" -"\tReturns the angular velocity that will be assigned to \n" -"\tthe created object.\n"; - -PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity(PyObject* self) -{ - PyObject *retVal = PyList_New(3); - - PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); - PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1])); - PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2])); - - return retVal; -} - - - -/* 8. setAngularVelocity */ -char KX_SCA_AddObjectActuator::SetAngularVelocity_doc[] = -"setAngularVelocity(vx, vy, vz)\n" -"\t- vx: float\n" -"\t- vy: float\n" -"\t- vz: float\n" -"\t- local: bool\n" -"\tAssign this angular velocity to the created object. \n"; - -PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* args) -{ - - float vecArg[3]; - if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) - return NULL; - - m_angular_velocity.setValue(vecArg); - Py_RETURN_NONE; + Py_Return; } void KX_SCA_AddObjectActuator::InstantAddObject() @@ -377,9 +337,8 @@ void KX_SCA_AddObjectActuator::InstantAddObject() // Now it needs to be added to the current scene. SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp ); KX_GameObject * game_obj = static_cast(replica); - game_obj->setLinearVelocity(m_linear_velocity,m_localLinvFlag); - game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag); - game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag); + game_obj->setLinearVelocity(m_linear_velocity,m_localFlag); + game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false); // keep a copy of the last object, to allow python scripters to change it if (m_lastCreatedObject) @@ -396,11 +355,13 @@ void KX_SCA_AddObjectActuator::InstantAddObject() } } -PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self, + PyObject* args, + PyObject* kwds) { InstantAddObject(); - Py_RETURN_NONE; + Py_Return; } @@ -411,17 +372,16 @@ char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = "\tReturn the last created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self) +PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self, + PyObject* args, + PyObject* kwds) { SCA_IObject* result = this->GetLastCreatedObject(); - - // if result->GetSGNode() is NULL - // it means the object has ended, The BGE python api crashes in many places if the object is returned. - if (result && (static_cast(result))->GetSGNode()) + if (result) { result->AddRef(); return result; } // don't return NULL to python anymore, it gives trouble in the scripts - Py_RETURN_NONE; + Py_Return; } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 278d4180284..e7fdb2fbfbc 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -60,13 +60,9 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator /// Linear velocity upon creation of the object. MT_Vector3 m_linear_velocity; - - /// Angular velocity upon creation of the object. - MT_Vector3 m_angular_velocity; /// Apply the velocity locally - bool m_localLinvFlag; - bool m_localAngvFlag; + bool m_localFlag; SCA_IObject* m_lastCreatedObject; @@ -83,9 +79,7 @@ public: int time, SCA_IScene* scene, const MT_Vector3& linvel, - bool linv_local, - const MT_Vector3& angvel, - bool angv_local, + bool local, PyTypeObject* T=&Type ); @@ -121,23 +115,19 @@ public: /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetObject); /* 2. setTime */ - KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetTime); + KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetTime); /* 3. getTime */ - KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetTime); + KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetTime); /* 4. getObject */ KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,GetObject); /* 5. getLinearVelocity */ - KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLinearVelocity); + KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLinearVelocity); /* 6. setLinearVelocity */ - KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetLinearVelocity); - /* 7. getAngularVelocity */ - KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetAngularVelocity); - /* 8. setAngularVelocity */ - KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetAngularVelocity); - /* 9. getLastCreatedObject */ - KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLastCreatedObject); - /* 10. instantAddObject*/ - KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject); + KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetLinearVelocity); + /* 7. getLastCreatedObject */ + KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLastCreatedObject); + /* 8. instantAddObject*/ + KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,InstantAddObject); }; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index e1f11732085..630df2d21d9 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -37,8 +37,6 @@ #include "KX_SCA_ReplaceMeshActuator.h" -#include "PyObjectPlus.h" - #ifdef HAVE_CONFIG_H #include #endif @@ -82,7 +80,7 @@ PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { - {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_O, SetMesh_doc}, + {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_VARARGS, SetMesh_doc}, KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh), KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, getMesh), @@ -101,29 +99,28 @@ PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const STR_String& attr) /* 1. setMesh */ char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] = "setMesh(name)\n" - "\t- name: string or None\n" + "\t- name: string\n" "\tSet the mesh that will be substituted for the current one.\n"; -PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, PyObject* value) +PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, + PyObject* args, + PyObject* kwds) { - if (value == Py_None) { - m_mesh = NULL; - } else { - char* meshname = PyString_AsString(value); - if (!meshname) { - PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None"); - return NULL; - } - void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); - - if (mesh==NULL) { - PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist"); - return NULL; - } + char* meshname; + + if (!PyArg_ParseTuple(args, "s", &meshname)) + { + return NULL; + } + + void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); + + if (mesh) { m_mesh= (class RAS_MeshObject*)mesh; + Py_Return; } - Py_RETURN_NONE; + return NULL; } KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, @@ -132,7 +129,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, ) { if (!m_mesh) - Py_RETURN_NONE; + Py_Return; return PyString_FromString(const_cast(m_mesh->GetName().ReadPtr())); } @@ -142,7 +139,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh, "instantReplaceMesh() : immediately replace mesh without delay\n") { InstantReplaceMesh(); - Py_RETURN_NONE; + Py_Return; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 1da154cc222..5ba0a099b14 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -76,7 +76,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator void InstantReplaceMesh(); /* 1. setMesh */ - KX_PYMETHOD_DOC_O(KX_SCA_ReplaceMeshActuator,SetMesh); + KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,SetMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,getMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,instantReplaceMesh); diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index d651373869a..f085ff435dc 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -78,7 +78,7 @@ UpdateChildCoordinates( if (parent) { - BL_ArmatureObject *armature = (BL_ArmatureObject*)(parent->GetSGClientObject()); + const BL_ArmatureObject *armature = (const BL_ArmatureObject*)(parent->GetSGClientObject()); if (armature) { MT_Matrix4x4 parent_matrix; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 72875bbc039..ab3692d2411 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -68,7 +68,6 @@ #include "SG_IObject.h" #include "SG_Tree.h" #include "DNA_group_types.h" -#include "DNA_scene_types.h" #include "BKE_anim.h" #include "KX_SG_NodeRelationships.h" @@ -117,8 +116,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface *ndi, class SND_IAudioDevice* adi, - const STR_String& sceneName, - Scene *scene): + const STR_String& sceneName): PyObjectPlus(&KX_Scene::Type), m_keyboardmgr(NULL), m_mousemgr(NULL), @@ -128,8 +126,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0), - m_blenderScene(scene) + m_ueberExecutionPriority(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -456,7 +453,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal // this is the list of object that are send to the graphics pipeline m_objectlist->Add(newobj->AddRef()); - newobj->AddMeshUser(); + newobj->Bucketize(); // logic cannot be replicated, until the whole hierarchy is replicated. m_logicHierarchicalGameObjects.push_back(newobj); @@ -626,7 +623,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) if (blgroupobj == blenderobj) // this check is also in group_duplilist() continue; - gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj); if (gameobj == NULL) { @@ -634,9 +630,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // Should not happen as dupli group are created automatically continue; } - - gameobj->SetBlenderGroupObject(blgroupobj); - if ((blenderobj->lay & group->layer)==0) { // object is not visible in the 3D view, will not be instantiated @@ -951,8 +944,6 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) newobj->RemoveMeshes(); ret = 1; - if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell - ret = newobj->Release(); if (m_objectlist->RemoveValue(newobj)) ret = newobj->Release(); if (m_tempObjectList->RemoveValue(newobj)) @@ -1006,7 +997,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) newobj->m_pDeformer = NULL; } - if (mesh->IsDeformed()) + if (mesh->m_class == 1) { // we must create a new deformer but which one? KX_GameObject* parentobj = newobj->GetParent(); @@ -1080,8 +1071,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) parentobj->Release(); } } - - gameobj->AddMeshUser(); + gameobj->Bucketize(); } @@ -1233,9 +1223,7 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi for (int m=0;mGetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } - - gameobj->SetCulled(!visible); - gameobj->UpdateBuckets(false); + gameobj->MarkVisible(visible); } } if (node->Left()) @@ -1252,8 +1240,7 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam // Shadow lamp layers if(layer && !(gameobj->GetLayer() & layer)) { - gameobj->SetCulled(true); - gameobj->UpdateBuckets(false); + gameobj->MarkVisible(false); return; } @@ -1299,11 +1286,9 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam } // Visibility/ non-visibility are marked // elsewhere now. - gameobj->SetCulled(false); - gameobj->UpdateBuckets(false); + gameobj->MarkVisible(); } else { - gameobj->SetCulled(true); - gameobj->UpdateBuckets(false); + gameobj->MarkVisible(false); } } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 5f7e1167e27..1c56dd1ee55 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -54,7 +54,6 @@ */ struct SM_MaterialProps; struct SM_ShapeProps; -struct Scene; class GEN_HashedPtr; class CListValue; @@ -278,15 +277,12 @@ protected: */ PyObject* m_attrlist; - struct Scene* m_blenderScene; - public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface* ndi, class SND_IAudioDevice* adi, - const STR_String& scenename, - struct Scene* scene); + const STR_String& scenename ); virtual ~KX_Scene(); @@ -586,10 +582,6 @@ public: * was running and not suspended) and the "curtime" */ double getSuspendedDelta(); - /** - * Returns the Blender scene this was made from - */ - struct Scene *GetBlenderScene() { return m_blenderScene; } }; typedef std::vector KX_SceneList; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index f75a1ee5c62..34a3baec093 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -69,11 +69,11 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SoundActuator::~KX_SoundActuator() { - if (m_soundObject) - { - m_soundScene->RemoveActiveObject(m_soundObject); - m_soundScene->DeleteObject(m_soundObject); - } + //m_soundScene->RemoveObject(this->m_soundObject); + //(this->m_soundObject)->DeleteWhenFinished(); + m_soundScene->RemoveActiveObject(m_soundObject); +// m_soundScene->DeleteObjectWhenFinished(m_soundObject); + m_soundScene->DeleteObject(m_soundObject); } @@ -82,12 +82,9 @@ CValue* KX_SoundActuator::GetReplica() { KX_SoundActuator* replica = new KX_SoundActuator(*this); replica->ProcessReplica(); - if (m_soundObject) - { - SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); - replica->setSoundObject(soundobj); - m_soundScene->AddObject(soundobj); - } + SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); + replica->setSoundObject(soundobj); + m_soundScene->AddObject(soundobj); // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -107,9 +104,6 @@ bool KX_SoundActuator::Update(double curtime, bool frame) RemoveAllEvents(); - if (!m_soundObject) - return false; - if (m_pino) { bNegativeEvent = true; @@ -293,10 +287,6 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObje PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds) { - if (!m_soundObject) - { - return PyString_FromString(""); - } STR_String objectname = m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -311,8 +301,7 @@ PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObje PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds) { - if (m_soundObject) - m_soundObject->StartSound(); + m_soundObject->StartSound(); Py_Return; } @@ -320,8 +309,7 @@ PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds) { - if (m_soundObject) - m_soundObject->PauseSound(); + m_soundObject->PauseSound(); Py_Return; } @@ -329,8 +317,7 @@ PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds) { - if (m_soundObject) - m_soundObject->StopSound(); + m_soundObject->StopSound(); Py_Return; } @@ -342,8 +329,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* if (!PyArg_ParseTuple(args, "f", &gain)) return NULL; - if (m_soundObject) - m_soundObject->SetGain(gain); + m_soundObject->SetGain(gain); Py_Return; } @@ -352,7 +338,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds) { - float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f; + float gain = m_soundObject->GetGain(); PyObject* result = PyFloat_FromDouble(gain); return result; @@ -366,8 +352,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* if (!PyArg_ParseTuple(args, "f", &pitch)) return NULL; - if (m_soundObject) - m_soundObject->SetPitch(pitch); + m_soundObject->SetPitch(pitch); Py_Return; } @@ -376,7 +361,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds) { - float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0; + float pitch = m_soundObject->GetPitch(); PyObject* result = PyFloat_FromDouble(pitch); return result; @@ -390,8 +375,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P if (!PyArg_ParseTuple(args, "f", &rollofffactor)) return NULL; - if (m_soundObject) - m_soundObject->SetRollOffFactor(rollofffactor); + m_soundObject->SetRollOffFactor(rollofffactor); Py_Return; } @@ -400,7 +384,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds) { - float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0; + float rollofffactor = m_soundObject->GetRollOffFactor(); PyObject* result = PyFloat_FromDouble(rollofffactor); return result; @@ -414,8 +398,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec if (!PyArg_ParseTuple(args, "i", &looping)) return NULL; - if (m_soundObject) - m_soundObject->SetLoopMode(looping); + m_soundObject->SetLoopMode(looping); Py_Return; } @@ -424,7 +407,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds) { - int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : SND_LOOP_OFF; + int looping = m_soundObject->GetLoopMode(); PyObject* result = PyInt_FromLong(looping); return result; @@ -442,8 +425,7 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2])) return NULL; - if (m_soundObject) - m_soundObject->SetPosition(pos); + m_soundObject->SetPosition(pos); Py_Return; } @@ -460,8 +442,7 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2])) return NULL; - if (m_soundObject) - m_soundObject->SetVelocity(vel); + m_soundObject->SetVelocity(vel); Py_Return; } @@ -484,8 +465,7 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2])) return NULL; - if (m_soundObject) - m_soundObject->SetOrientation(ori); + m_soundObject->SetOrientation(ori); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 8b09cd4e953..67937d5c579 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -42,8 +42,6 @@ #include #include "KX_GameObject.h" -#include "PyObjectPlus.h" - #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 342e71c5093..f5a2b5e02fe 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -1,8 +1,6 @@ #include -#include "PyObjectPlus.h" - #include "KX_VehicleWrapper.h" #include "PHY_IPhysicsEnvironment.h" #include "PHY_IVehicle.h" diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 25205714308..5cec65dff1c 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -82,7 +82,7 @@ PyObject* KX_VertexProxy::_getattr(const STR_String& attr) { if (attr == "XYZ") - return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); + return PyObjectFrom(MT_Vector3(m_vertex->getLocalXYZ())); if (attr == "UV") return PyObjectFrom(MT_Point2(m_vertex->getUV1())); @@ -102,11 +102,11 @@ KX_VertexProxy::_getattr(const STR_String& attr) // pos if (attr == "x") - return PyFloat_FromDouble(m_vertex->getXYZ()[0]); + return PyFloat_FromDouble(m_vertex->getLocalXYZ()[0]); if (attr == "y") - return PyFloat_FromDouble(m_vertex->getXYZ()[1]); + return PyFloat_FromDouble(m_vertex->getLocalXYZ()[1]); if (attr == "z") - return PyFloat_FromDouble(m_vertex->getXYZ()[2]); + return PyFloat_FromDouble(m_vertex->getLocalXYZ()[2]); // Col if (attr == "r") @@ -184,7 +184,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) { float val = PyFloat_AsDouble(pyvalue); // pos - MT_Point3 pos(m_vertex->getXYZ()); + MT_Point3 pos(m_vertex->getLocalXYZ()); if (attr == "x") { pos.x() = val; @@ -312,7 +312,7 @@ PyObject* KX_VertexProxy::PyGetXYZ(PyObject*, PyObject*, PyObject*) { - return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); + return PyObjectFrom(MT_Point3(m_vertex->getLocalXYZ())); } PyObject* KX_VertexProxy::PySetXYZ(PyObject*, @@ -426,7 +426,7 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject*, { if (PyVecTo(list, vec)) { - m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); + m_vertex->SetFlag((m_vertex->getFlag()|TV_2NDUV)); m_vertex->SetUnit(unit); m_vertex->SetUV2(vec); m_mesh->SetMeshModified(true); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index e60a8d7c099..b4693a7a7db 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -38,12 +38,10 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, - bool recursive, PyTypeObject* T ) : SCA_IActuator(gameobj,T), - m_visible(visible), - m_recursive(recursive) + m_visible(visible) { // intentionally empty } @@ -77,10 +75,10 @@ KX_VisibilityActuator::Update() KX_GameObject *obj = (KX_GameObject*) GetParent(); - obj->SetVisible(m_visible, m_recursive); - obj->UpdateBuckets(m_recursive); + obj->SetVisible(m_visible); + obj->MarkVisible(); - return false; + return true; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index d1b85ab998c..9b4753033fb 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -39,14 +39,12 @@ class KX_VisibilityActuator : public SCA_IActuator /** Make visible? */ bool m_visible; - bool m_recursive; public: KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, - bool recursive, PyTypeObject* T=&Type ); diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile index 0b48ad8b8c3..47a4855b00c 100644 --- a/source/gameengine/Ketsji/Makefile +++ b/source/gameengine/Ketsji/Makefile @@ -35,13 +35,10 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) -CPPFLAGS += $(NAN_SDLCFLAGS) CPPFLAGS += $(OGL_CPPFLAGS) CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) -CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -CPPFLAGS += -I../../blender/python -CPPFLAGS += -I../../blender/python/api2_2x +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -I../../blender/python CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include @@ -64,9 +61,13 @@ CPPFLAGS += -I../../blender/blenlib CPPFLAGS += -I../../blender/include CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I../../blender/imbuf -CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +ifeq ($(WITH_BF_GLEXT),true) + CPPFLAGS += -DWITH_GLEXT +endif + + ########################### SOURCEDIR = source/gameengine/Ketsji diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 02e7aed82a5..f6f744b199a 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -32,13 +32,16 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #sourc incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy' incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' -incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu' +incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include' cflags = [] if env['OURPLATFORM'] == 'win32-vc': cflags.append('/GR') cflags.append('/Ox') +if env['WITH_BF_GLEXT'] == 1: + env['CPPFLAGS'].append('-DWITH_GLEXT') + incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SDL_INC'] diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp index 6d9b41e08d2..a04560aaf09 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp @@ -206,7 +206,8 @@ void ODEPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) +PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) { //m_OdeWorld diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index dcc87d614c0..7c61902f8e2 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -54,7 +54,8 @@ public: 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 PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 8ba138df437..d6a32dfd9c0 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -15,7 +15,7 @@ subject to the following restrictions: #include "CcdPhysicsController.h" #include "btBulletDynamicsCommon.h" -#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" + #include "PHY_IMotionState.h" #include "CcdPhysicsEnvironment.h" #include "RAS_MeshObject.h" @@ -126,14 +126,13 @@ void CcdPhysicsController::CreateRigidbody() m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); - btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - rbci.m_linearDamping = m_cci.m_linearDamping; - rbci.m_angularDamping = m_cci.m_angularDamping; - rbci.m_friction = m_cci.m_friction; - rbci.m_restitution = m_cci.m_restitution; - - m_body = new btRigidBody(rbci); - + m_body = new btRigidBody(m_cci.m_mass, + m_bulletMotionState, + m_collisionShape, + m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor, + m_cci.m_linearDamping,m_cci.m_angularDamping, + m_cci.m_friction,m_cci.m_restitution); + // // init the rigidbody properly // @@ -277,9 +276,7 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta if (m_collisionShape) { // new shape has no scaling, apply initial scaling - m_collisionShape->setMargin(m_cci.m_margin); m_collisionShape->setLocalScaling(m_cci.m_scaling); - if (m_cci.m_mass) m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); } @@ -770,8 +767,6 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) // assume no shape information m_shapeType = PHY_SHAPE_NONE; m_vertexArray.clear(); - m_polygonIndexArray.clear(); - m_meshObject = NULL; if (!meshobj) return false; @@ -818,7 +813,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) { for (int i=0;iVertexCount();i++) { - const float* vtx = poly->GetVertex(i)->getXYZ(); + const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[i], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 point(vtx[0],vtx[1],vtx[2]); m_vertexArray.push_back(point); numvalidpolys++; @@ -826,36 +823,40 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) } else { { - const float* vtx = poly->GetVertex(2)->getXYZ(); + const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[2], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); - - vtx = poly->GetVertex(1)->getXYZ(); + vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[1], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); - - vtx = poly->GetVertex(0)->getXYZ(); + vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[0], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); - m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); m_vertexArray.push_back(vertex2); - m_polygonIndexArray.push_back(p2); numvalidpolys++; } if (poly->VertexCount() == 4) { - const float* vtx = poly->GetVertex(3)->getXYZ(); + const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[3], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); - - vtx = poly->GetVertex(2)->getXYZ(); + vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[2], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); - - vtx = poly->GetVertex(0)->getXYZ(); + vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, + poly->GetVertexIndexBase().m_indexarray[0], + poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); - m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); m_vertexArray.push_back(vertex2); - m_polygonIndexArray.push_back(p2); numvalidpolys++; } } @@ -868,7 +869,6 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) m_shapeType = PHY_SHAPE_NONE; return false; } - m_meshObject = meshobj; return true; } @@ -906,26 +906,15 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() break; case PHY_SHAPE_MESH: - // Let's use the latest btScaledBvhTriangleMeshShape: it allows true sharing of - // triangle mesh information between duplicates => drastic performance increase when - // duplicating complex mesh objects. - // BUT it causes a small performance decrease when sharing is not required: - // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering - // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 - // and btScaledBvhTriangleMeshShape otherwise. - if (!m_unscaledShape) + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) { - collisionMeshData = new btTriangleMesh(); - // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) - { - collisionMeshData->addTriangle(*it++,*it++,*it++); - } - // this shape will be shared and not deleted until shapeInfo is deleted - m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); - m_unscaledShape->recalcLocalAabb(); + collisionMeshData->addTriangle(*it++,*it++,*it++); } - collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); + concaveShape = new btBvhTriangleMeshShape( collisionMeshData, true ); + concaveShape->recalcLocalAabb(); + collisionShape = concaveShape; break; case PHY_SHAPE_COMPOUND: @@ -937,7 +926,6 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionShape = nextShapeInfo->CreateBulletShape(); if (collisionShape) { - collisionShape->setLocalScaling(nextShapeInfo->m_childScale); compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape); } } @@ -966,10 +954,7 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() childShape->Release(); childShape = nextShape; } - if (m_unscaledShape) - { - DeleteBulletShape(m_unscaledShape); - } + m_vertexArray.clear(); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 7d55851ebf6..1e1a38aa2a6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -47,9 +47,7 @@ public: m_radius(1.0), m_height(1.0), m_halfExtend(0.f,0.f,0.f), - m_childScale(1.0f,1.0f,1.0f), m_nextShape(NULL), - m_unscaledShape(NULL), m_refCount(1) { m_childTrans.setIdentity(); @@ -73,24 +71,10 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); - btTriangleMeshShape* GetMeshShape(void) - { - return m_unscaledShape; - } CcdShapeConstructionInfo* GetNextShape() { return m_nextShape; } - CcdShapeConstructionInfo* GetChildShape(int i) - { - CcdShapeConstructionInfo* shape = m_nextShape; - while (i > 0 && shape != NULL) - { - shape = shape->m_nextShape; - i--; - } - return shape; - } bool SetMesh(RAS_MeshObject* mesh, bool polytope); @@ -102,19 +86,11 @@ public: btScalar m_height; btVector3 m_halfExtend; btTransform m_childTrans; - btVector3 m_childScale; std::vector m_vertexArray; // Contains both vertex array for polytope shape and // triangle array for concave mesh shape. // In this case a triangle is made of 3 consecutive points - std::vector m_polygonIndexArray; // Contains the array of polygon index in the - // original mesh that correspond to shape triangles. - // only set for concave mesh shape. - const RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh - protected: CcdShapeConstructionInfo* m_nextShape; // for compound shape - btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, - // the actual shape is of type btScaledBvhTriangleMeshShape int m_refCount; // this class is shared between replicas // keep track of users so that we can release it }; @@ -137,15 +113,13 @@ struct CcdConstructionInfo CcdConstructionInfo() - : m_localInertiaTensor(1.f, 1.f, 1.f), - m_gravity(0,0,0), + : m_gravity(0,0,0), m_scaling(1.f,1.f,1.f), m_mass(0.f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), m_angularDamping(0.1f), - m_margin(0.06f), m_collisionFlags(0), m_bRigid(false), m_collisionFilterGroup(DefaultFilter), @@ -166,7 +140,6 @@ struct CcdConstructionInfo btScalar m_friction; btScalar m_linearDamping; btScalar m_angularDamping; - btScalar m_margin; int m_collisionFlags; bool m_bRigid; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 5042df2162a..d8e05fab839 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -53,7 +53,6 @@ void DrawRasterizerLine(const float* from,const float* to,int color); #include -#include // for memset #ifdef NEW_BULLET_VEHICLE_SUPPORT class WrapperVehicle : public PHY_IVehicle @@ -330,21 +329,30 @@ m_filterCallback(NULL) { m_triggerCallbacks[i] = 0; } - m_collisionConfiguration = new btDefaultCollisionConfiguration(); - if (!dispatcher) { - dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + dispatcher = new btCollisionDispatcher(); m_ownDispatcher = dispatcher; } - m_broadphase = new btDbvtBroadphase(); + if(!pairCache) + { + + //todo: calculate/let user specify this world sizes + btVector3 worldMin(-10000,-10000,-10000); + btVector3 worldMax(10000,10000,10000); + + pairCache = new btAxisSweep3(worldMin,worldMax); + // remember that this was allocated by us so that we can release it + m_ownPairCache = pairCache; + //broadphase = new btSimpleBroadphase(); + } m_filterCallback = new CcdOverlapFilterCallBack(this); - m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback); + pairCache->setOverlapFilterCallback(m_filterCallback); setSolverType(1);//issues with quickstep and memory allocations - m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,m_solver); m_debugDrawer = 0; m_gravity = btVector3(0.f,-10.f,0.f); m_dynamicsWorld->setGravity(m_gravity); @@ -443,12 +451,11 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); - btVector3 inertia(0.0,0.0,0.0); + btVector3 inertia; m_dynamicsWorld->removeCollisionObject(body); body->setCollisionFlags(newCollisionFlags); - if (newMass) - body->getCollisionShape()->calculateLocalInertia(newMass, inertia); + body->getCollisionShape()->calculateLocalInertia(newMass, inertia); body->setMassProps(newMass, inertia); m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); // to avoid nasty interaction, we must update the property of the controller as well @@ -511,9 +518,6 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) veh->SyncWheels(); } - m_dynamicsWorld->debugDrawWorld(); - - CallbackTriggers(); return true; @@ -574,7 +578,7 @@ void CcdPhysicsEnvironment::setSolverDamping(float damping) void CcdPhysicsEnvironment::setLinearAirDamping(float damping) { - //gLinearAirDamping = damping; + gLinearAirDamping = damping; } void CcdPhysicsEnvironment::setUseEpa(bool epa) @@ -593,7 +597,7 @@ void CcdPhysicsEnvironment::setSolverType(int solverType) { m_solver = new btSequentialImpulseConstraintSolver(); -// ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); + ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); break; } } @@ -655,10 +659,9 @@ int CcdPhysicsEnvironment::createUniversalD6Constraint( { - bool useReferenceFrameA = true; genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB,useReferenceFrameA); + frameInA,frameInB); genericConstraint->setLinearLowerLimit(linearMinLimits); genericConstraint->setLinearUpperLimit(linearMaxLimits); genericConstraint->setAngularLowerLimit(angularMinLimits); @@ -706,54 +709,35 @@ void CcdPhysicsEnvironment::removeConstraint(int constraintId) struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback { - PHY_IRayCastFilterCallback& m_phyRayFilter; - const btCollisionShape* m_hitTriangleShape; - int m_hitTriangleIndex; + PHY_IPhysicsController* m_ignoreClient; - FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo) + FilterClosestRayResultCallback (PHY_IPhysicsController* ignoreClient,const btVector3& rayFrom,const btVector3& rayTo) : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo), - m_phyRayFilter(phyRayFilter), - m_hitTriangleShape(NULL), - m_hitTriangleIndex(0) + m_ignoreClient(ignoreClient) { + } virtual ~FilterClosestRayResultCallback() { } - virtual bool needsCollision(btBroadphaseProxy* proxy0) const - { - if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask)) - return false; - if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask)) - return false; - btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject; - CcdPhysicsController* phyCtrl = static_cast(object->getUserPointer()); - if (phyCtrl == m_phyRayFilter.m_ignoreController) - return false; - return m_phyRayFilter.needBroadphaseRayCast(phyCtrl); - } - - virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) + virtual float AddSingleResult( btCollisionWorld::LocalRayResult& rayResult) { CcdPhysicsController* curHit = static_cast(rayResult.m_collisionObject->getUserPointer()); - // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it - if (rayResult.m_localShapeInfo) - { - m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape(); - m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex; - } else - { - m_hitTriangleShape = NULL; - m_hitTriangleIndex = 0; + //ignore client... + if (curHit != m_ignoreClient) + { + //if valid + return ClosestRayResultCallback::AddSingleResult(rayResult); } - return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace); + return m_closestHitFraction; } }; -PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ) +PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) { @@ -767,101 +751,19 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac //Either Ray Cast with or without filtering //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); - FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo); + FilterClosestRayResultCallback rayCallback(ignoreClient,rayFrom,rayTo); - PHY_RayCastResult result; - memset(&result, 0, sizeof(result)); - + PHY_IPhysicsController* nearestHit = 0; // don't collision with sensor object - rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; - //, ,filterCallback.m_faceNormal); - - m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); - if (rayCallback.hasHit()) + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback, CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter); + if (rayCallback.HasHit()) { - CcdPhysicsController* controller = static_cast(rayCallback.m_collisionObject->getUserPointer()); - result.m_controller = controller; - result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX(); - result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY(); - result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ(); + nearestHit = static_cast(rayCallback.m_collisionObject->getUserPointer()); + hitX = rayCallback.m_hitPointWorld.getX(); + hitY = rayCallback.m_hitPointWorld.getY(); + hitZ = rayCallback.m_hitPointWorld.getZ(); - if (rayCallback.m_hitTriangleShape != NULL) - { - // identify the mesh polygon - CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo; - if (shapeInfo) - { - btCollisionShape* shape = controller->GetRigidBody()->getCollisionShape(); - if (shape->isCompound()) - { - btCompoundShape* compoundShape = (btCompoundShape*)shape; - CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo; - // need to search which sub-shape has been hit - for (int i=0; igetNumChildShapes(); i++) - { - shapeInfo = compoundShapeInfo->GetChildShape(i); - shape=compoundShape->getChildShape(i); - if (shape == rayCallback.m_hitTriangleShape) - break; - } - } - if (shape == rayCallback.m_hitTriangleShape && - rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size()) - { - result.m_meshObject = shapeInfo->m_meshObject; - result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex); - - // Bullet returns the normal from "outside". - // If the user requests the real normal, compute it now - if (filterCallback.m_faceNormal) - { - // mesh shapes are shared and stored in the shapeInfo - btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); - if (triangleShape) - { - // this code is copied from Bullet - btVector3 triangle[3]; - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface(); - - meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - 0); - - unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride); - const btVector3& meshScaling = shape->getLocalScaling(); - for (int j=2;j>=0;j--) - { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; - - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); - - triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); - } - meshInterface->unLockReadOnlyVertexBase(0); - btVector3 triangleNormal; - triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); - rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal; - } - } - } - } - } if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { rayCallback.m_hitNormalWorld.normalize(); @@ -869,14 +771,14 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac { rayCallback.m_hitNormalWorld.setValue(1,0,0); } - result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX(); - result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY(); - result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ(); - filterCallback.reportHit(&result); + normalX = rayCallback.m_hitNormalWorld.getX(); + normalY = rayCallback.m_hitNormalWorld.getY(); + normalZ = rayCallback.m_hitNormalWorld.getZ(); + } - return result.m_controller; + return nearestHit; } @@ -931,12 +833,6 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() if (NULL != m_filterCallback) delete m_filterCallback; - - if (NULL != m_collisionConfiguration) - delete m_collisionConfiguration; - - if (NULL != m_broadphase) - delete m_broadphase; } @@ -949,7 +845,7 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float { //param = 1..12, min0,max0,min1,max1...min6,max6 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; - genCons->setLimit(param,value0,value1); + genCons->SetLimit(param,value0,value1); break; }; default: @@ -1295,11 +1191,10 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA; frameInB = inv * globalFrameA; - bool useReferenceFrameA = true; - + genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB,useReferenceFrameA); + frameInA,frameInB); } else @@ -1320,10 +1215,9 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl ///frameInB in worldspace frameInB = rb0->getCenterOfMassTransform() * frameInA; - bool useReferenceFrameA = true; genericConstraint = new btGeneric6DofConstraint( *rb0,s_fixedObject2, - frameInA,frameInB,useReferenceFrameA); + frameInA,frameInB); } if (genericConstraint) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 3cf5a943e3f..825a5e525f2 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -56,10 +56,6 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment protected: btIDebugDraw* m_debugDrawer; - - class btDefaultCollisionConfiguration* m_collisionConfiguration; - class btBroadphaseInterface* m_broadphase; - //solver iterations int m_numIterations; @@ -161,7 +157,8 @@ protected: btTypedConstraint* getConstraintById(int constraintId); - virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); + virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); //Methods for gamelogic collision/physics callbacks diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile index d5570e75833..49259d0a67c 100644 --- a/source/gameengine/Physics/Bullet/Makefile +++ b/source/gameengine/Physics/Bullet/Makefile @@ -37,10 +37,5 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -CPPFLAGS += -I$(NAN_STRING)/include -CPPFLAGS += -I$(NAN_MOTO)/include -CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I../../Physics/common CPPFLAGS += -I../../Physics/Dummy -CPPFLAGS += -I../../Rasterizer - diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index d78958b746c..f512d44c9f2 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -109,7 +109,8 @@ void DummyPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) +PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) { //collision detection / raytesting return NULL; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 975be84f2a7..b5a61f72e4a 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -69,7 +69,8 @@ public: return 0; } - virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); + virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 80e4dc4044e..65018d2523e 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -26,7 +26,6 @@ * * ***** END GPL LICENSE BLOCK ***** */ -#include // memset #include "SumoPhysicsEnvironment.h" #include "PHY_IMotionState.h" #include "SumoPhysicsController.h" @@ -126,35 +125,37 @@ void SumoPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, +PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClientCtrl, float fromX,float fromY,float fromZ, - float toX,float toY,float toZ) + float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ, + float& normalX,float& normalY,float& normalZ) { - SumoPhysicsController* ignoreCtr = static_cast (filterCallback.m_ignoreController); + SumoPhysicsController* ignoreCtr = static_cast (ignoreClientCtrl); //collision detection / raytesting MT_Point3 hit, normal; - PHY_RayCastResult result; + PHY_IPhysicsController *ret = 0; 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); + ret = (PHY_IPhysicsController *) smOb->getPhysicsClientObject(); } - return result.m_controller; + hitX = hit[0]; + hitY = hit[1]; + hitZ = hit[2]; + + normalX = normal[0]; + normalY = normal[1]; + normalZ = normal[2]; + + return ret; } //gamelogic callbacks void SumoPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index 100adf969d5..8b9fb463034 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -75,7 +75,8 @@ public: return 0; } - virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); + virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 98496fb7f9e..5b275066665 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -33,50 +33,6 @@ #include #include "PHY_DynamicTypes.h" class PHY_IVehicle; -class RAS_MeshObject; -class PHY_IPhysicsController; - -/** - * pass back information from rayTest - */ -struct PHY_RayCastResult -{ - PHY_IPhysicsController* m_controller; - PHY__Vector3 m_hitPoint; - PHY__Vector3 m_hitNormal; - const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers) - int m_polygon; // index of the polygon hit by the ray, - // only if m_meshObject != NULL -}; - -/** - * This class replaces the ignoreController parameter of rayTest function. - * It allows more sophisticated filtering on the physics controller before computing the ray intersection to save CPU. - * It is only used to its full extend by the Ccd physics environement (Bullet). - */ -class PHY_IRayCastFilterCallback -{ -public: - PHY_IPhysicsController* m_ignoreController; - bool m_faceNormal; - - virtual ~PHY_IRayCastFilterCallback() - { - } - - virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller) - { - return true; - } - - virtual void reportHit(PHY_RayCastResult* result) = 0; - - PHY_IRayCastFilterCallback(PHY_IPhysicsController* ignoreController, bool faceNormal=false) - :m_ignoreController(ignoreController), - m_faceNormal(faceNormal) - { - } -}; /** * Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.) @@ -138,7 +94,8 @@ class PHY_IPhysicsEnvironment //complex constraint for vehicles virtual PHY_IVehicle* getVehicleConstraint(int constraintId) =0; - virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0; + virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, + float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)=0; //Methods for gamelogic collision/physics callbacks diff --git a/source/gameengine/PyDoc/GameKeys.py b/source/gameengine/PyDoc/GameKeys.py index 1a0a737718e..268fb9cc172 100644 --- a/source/gameengine/PyDoc/GameKeys.py +++ b/source/gameengine/PyDoc/GameKeys.py @@ -164,12 +164,3 @@ Example:: # Activate Right! """ - -def EventToString(event): - """ - Return the string name of a key event. Will raise a ValueError error if its invalid. - - @type event: int - @param event: key event from GameKeys or the keyboard sensor. - @rtype: string - """ diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index af3d2810553..b65bc0f3ce8 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -220,13 +220,6 @@ def setPhysicsTicRate(ticrate): @param ticrate: The new update frequency (in Hz). @type ticrate: float """ -def getAverageFrameRate(): - """ - Gets the estimated average framerate - - @return: The estimed average framerate in frames per second - @rtype: float - """ def expandPath(path): """ @@ -252,4 +245,4 @@ def getBlendFileList(path = "//"): @type path: string @return: A list of filenames, with no directory prefix @rtype: list - """ + """ \ No newline at end of file diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index ff9b4ffc95b..a5ba5b1d634 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -30,11 +30,11 @@ class KX_GameObject: Delete this object, can be used inpace of the EndObject Actuator. The actual removal of the object from the scene is delayed. """ - def getVisible(): + def getVisible(visible): """ Gets the game object's visible flag. - @rtype: boolean + @type visible: boolean """ def setVisible(visible): """ @@ -49,25 +49,16 @@ class KX_GameObject: @rtype: int @return: the objects state. """ - def setState(state): + def setState(): """ - Sets the game object's state flag. + Sets the game object's visible flag. The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29) - @type state: integer + @type visible: boolean """ def setPosition(pos): """ - Sets the game object's position. - Global coordinates for root object, local for child objects. - - - @type pos: [x, y, z] - @param pos: the new position, in local coordinates. - """ - def setWorldPosition(pos): - """ - Sets the game object's position in world coordinates regardless if the object is root or child. + Sets the game object's position. @type pos: [x, y, z] @param pos: the new position, in world coordinates. @@ -144,26 +135,6 @@ class KX_GameObject: @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - True: you get the "local" velocity ie: relative to object orientation. """ - def getAngularVelocity(local = 0): - """ - Gets the game object's angular velocity. - - @type local: boolean - @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - - True: you get the "local" velocity ie: relative to object orientation. - @rtype: list [vx, vy, vz] - @return: the object's angular velocity. - """ - def setAngularVelocity(velocity, local = 0): - """ - Sets the game object's angular velocity. - - @type velocity: 3d vector. - @param velocity: angular velocity vector. - @type local: boolean - @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - - True: you get the "local" velocity ie: relative to object orientation. - """ def getVelocity(point): """ Gets the game object's velocity at the specified point. @@ -309,13 +280,11 @@ class KX_GameObject: @rtype: L{KX_GameObject} @return: the first object hit or None if no object or object does not match prop """ - def rayCast(objto,objfrom,dist,prop,face,xray,poly): + def rayCast(to,from,dist,prop): """ Look from a point/object to another point/object and find first object hit within dist that matches prop. - if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. - if poly is 1, returns a 4-tuple with in addition a L{KX_PolyProxy} as 4th element. - - Ex:: + Returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. + Ex: # shoot along the axis gun-gunAim (gunAim should be collision-free) ob,point,normal = gun.rayCast(gunAim,None,50) if ob: @@ -323,42 +292,21 @@ class KX_GameObject: Notes: The ray ignores the object on which the method is called. - It is casted from/to object center or explicit [x,y,z] points. - - The face paremeter determines the orientation of the normal:: - 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside) - 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect) - - The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray. - The prop and xray parameters interact as follow:: - prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray. - prop off, xray on : idem. - prop on, xray off: return closest hit if it matches prop, no hit otherwise. - prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray. - The L{KX_PolyProxy} 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray. - If there is no hit or the hit object is not a static mesh, None is returned as 4th element. - - The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. + If is casted from/to object center or explicit [x,y,z] points. + The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray + If a property was specified and the first object hit does not have that property, there is no hit + The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. - @param objto: [x,y,z] or object to which the ray is casted - @type objto: L{KX_GameObject} or 3-tuple - @param objfrom: [x,y,z] or object from which the ray is casted; None or omitted => use self object center - @type objfrom: L{KX_GameObject} or 3-tuple or None + @param to: [x,y,z] or object to which the ray is casted + @type to: L{KX_GameObject} or 3-tuple + @param from: [x,y,z] or object from which the ray is casted; None or omitted => use self object center + @type from: L{KX_GameObject} or 3-tuple or None @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to @type dist: float @param prop: property name that object must have; can be omitted => detect any object @type prop: string - @param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin - @type face: int - @param xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object - @type xray: int - @param poly: polygon option: 1=>return value is a 4-tuple and the 4th element is a L{KX_PolyProxy} - @type poly: int - @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) - or 4-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz), L{KX_PolyProxy}) - @return: (object,hitpoint,hitnormal) or (object,hitpoint,hitnormal,polygon) - If no hit, returns (None,None,None) or (None,None,None,None) - If the object hit is not a static mesh, polygon is None + @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) + @return: (object,hitpoint,hitnormal) or (None,None,None) """ diff --git a/source/gameengine/PyDoc/KX_MeshProxy.py b/source/gameengine/PyDoc/KX_MeshProxy.py index 03bc36b6ac1..e43fa3598f0 100644 --- a/source/gameengine/PyDoc/KX_MeshProxy.py +++ b/source/gameengine/PyDoc/KX_MeshProxy.py @@ -95,21 +95,6 @@ class KX_MeshProxy: @rtype: L{KX_VertexProxy} @return: a vertex object. """ - def getNumPolygons(): - """ - Returns the number of polygon in the mesh. - - @rtype: integer - """ - def getPolygon(index): - """ - Gets the specified polygon from the mesh. - - @type index: integer - @param index: polygon number - @rtype: L{KX_PolyProxy} - @return: a polygon object. - """ def reinstancePhysicsMesh(): """ Updates the physics system with the changed mesh. diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py index b7b76473292..db577d21e6f 100644 --- a/source/gameengine/PyDoc/KX_ObjectActuator.py +++ b/source/gameengine/PyDoc/KX_ObjectActuator.py @@ -111,7 +111,9 @@ class KX_ObjectActuator(SCA_IActuator): For the servo control actuator, this is the target speed. @rtype: list [vx, vy, vz, local] - @return: A four item list, containing the vector velocity, and whether the velocity is applied in local coordinates (True) or world coordinates (False) + @return: A four item list, containing the vector velocity, and whether + the velocity is applied in local coordinates (True) or world + coordinates (False) """ def setLinearVelocity(vx, vy, vz, local): """ diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py index c3b2e947ddb..4f2bf85bff3 100644 --- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py @@ -64,23 +64,6 @@ class KX_SCA_AddObjectActuator(SCA_IActuator): """ Returns the initial linear velocity of added objects. - @rtype: list [vx, vy, vz] - """ - def setAngularVelocity(vx, vy, vz): - """ - Sets the initial angular velocity of added objects. - - @type vx: float - @param vx: the x component of the initial angular velocity. - @type vy: float - @param vy: the y component of the initial angular velocity. - @type vz: float - @param vz: the z component of the initial angular velocity. - """ - def getAngularVelocity(): - """ - Returns the initial angular velocity of added objects. - @rtype: list [vx, vy, vz] """ def getLastCreatedObject(): diff --git a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py index 498f6072e23..eb00a91a4ce 100644 --- a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py @@ -59,9 +59,8 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator): def setMesh(name): """ Sets the name of the mesh that will replace the current one. - When the name is None it will unset the mesh value so no action is taken. - @type name: string or None + @type name: string """ def getMesh(): """ @@ -69,6 +68,6 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator): Returns None if no mesh has been scheduled to be added. - @rtype: string or None + @rtype: string """ diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py index 948302991b7..2ecd94f38ae 100644 --- a/source/gameengine/PyDoc/KX_TrackToActuator.py +++ b/source/gameengine/PyDoc/KX_TrackToActuator.py @@ -21,7 +21,7 @@ class KX_TrackToActuator(SCA_IActuator): @type object: L{KX_GameObject}, string or None @param object: Either a reference to a game object or the name of the object to track. """ - def getObject(name_only): + def getObject(): """ Returns the name of the object to track. diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index ebb5332d98d..f0e48b6ed43 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -37,10 +37,6 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M # Centre the mouse Rasterizer.setMousePosition(Rasterizer.getWindowWidth()/2, Rasterizer.getWindowHeight()/2) -@group Material Types: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL -@var KX_TEXFACE_MATERIAL: Materials as defined by the texture face settings. -@var KX_BLENDER_MULTITEX_MATERIAL: Materials approximating blender materials with multitexturing. -@var KX_BLENDER_BLENDER_MATERIAL: Materials approximating blender materials with GLSL. """ @@ -88,8 +84,7 @@ def setMousePosition(x, y): """ Sets the mouse cursor position. - @type x: integer - @type y: integer + @type x, y: integer """ def setBackgroundColor(rgba): @@ -150,35 +145,3 @@ def getFocalLength(): @rtype: float """ - -def setMaterialMode(mode): - """ - Set the material mode to use for OpenGL rendering. - - @type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL - @note: Changes will only affect newly created scenes. - """ - -def getMaterialMode(mode): - """ - Get the material mode to use for OpenGL rendering. - - @rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL - """ - -def setGLSLMaterialSetting(setting, enable): - """ - Enables or disables a GLSL material setting. - - @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) - @type enable: boolean - """ - -def getGLSLMaterialSetting(setting, enable): - """ - Get the state of a GLSL material setting. - - @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) - @rtype: boolean - """ - diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py index 19df589ea7b..46b74f461a7 100644 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ b/source/gameengine/PyDoc/SCA_DelaySensor.py @@ -1,6 +1,6 @@ # $Id$ # Documentation for SCA_DelaySensor -from SCA_ISensor import * +from SCA_IActuator import * class SCA_DelaySensor(SCA_ISensor): """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py index 14858505e24..33f0e976284 100644 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ b/source/gameengine/PyDoc/SCA_ISensor.py @@ -9,12 +9,7 @@ class SCA_ISensor(SCA_ILogicBrick): def isPositive(): """ - True if this sensor brick is in a positive state. - """ - - def isTriggered(): - """ - True if this sensor brick has triggered the current controller. + True if this sensor brick has been activated. """ def getUsePosPulseMode(): diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile index 917f70c7108..e3b1f274ee5 100644 --- a/source/gameengine/Rasterizer/Makefile +++ b/source/gameengine/Rasterizer/Makefile @@ -49,6 +49,10 @@ ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings endif +ifeq ($(WITH_BF_GLEXT),true) + CPPFLAGS += -DWITH_GLEXT +endif + ############### SOURCEDIR = source/gameengine/Rasterizer diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index f7938bb62e6..82bdce44519 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -26,6 +26,10 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifdef HAVE_CONFIG_H +#include +#endif + #ifdef WIN32 // don't show these anoying STL warnings #pragma warning (disable:4786) @@ -35,54 +39,14 @@ #include "RAS_MaterialBucket.h" #include "STR_HashedString.h" #include "RAS_MeshObject.h" +#define KX_NUM_MATERIALBUCKETS 100 #include "RAS_IRasterizer.h" #include "RAS_IRenderTools.h" #include "RAS_BucketManager.h" -#include #include -/* sorting */ - -struct RAS_BucketManager::sortedmeshslot -{ -public: - MT_Scalar m_z; /* depth */ - RAS_MeshSlot *m_ms; /* mesh slot */ - RAS_MaterialBucket *m_bucket; /* buck mesh slot came from */ - - sortedmeshslot() {} - - void set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm) - { - // would be good to use the actual bounding box center instead - MT_Point3 pos(ms->m_OpenGLMatrix[12], ms->m_OpenGLMatrix[13], ms->m_OpenGLMatrix[14]); - - m_z = MT_dot(pnorm, pos); - m_ms = ms; - m_bucket = bucket; - } -}; - -struct RAS_BucketManager::backtofront -{ - bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) - { - return (a.m_z < b.m_z) || (a.m_z == b.m_z && a.m_ms < b.m_ms); - } -}; - -struct RAS_BucketManager::fronttoback -{ - bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) - { - return (a.m_z > b.m_z) || (a.m_z == b.m_z && a.m_ms > b.m_ms); - } -}; - -/* bucket manager */ - RAS_BucketManager::RAS_BucketManager() { @@ -90,179 +54,153 @@ RAS_BucketManager::RAS_BucketManager() RAS_BucketManager::~RAS_BucketManager() { - BucketList::iterator it; - - for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) - delete (*it); - - for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - delete(*it); - - m_SolidBuckets.clear(); - m_AlphaBuckets.clear(); + RAS_BucketManagerClearAll(); } -void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector& slots, bool alpha) +/** + * struct alphamesh holds a mesh, (m_ms) it's depth, (m_z) and the bucket it came from (m_bucket.) + */ +struct RAS_BucketManager::alphamesh { - BucketList::iterator bit; - list::iterator mit; - size_t size = 0, i = 0; +public: + MT_Scalar m_z; + RAS_MaterialBucket::T_MeshSlotList::iterator m_ms; + RAS_MaterialBucket *m_bucket; + alphamesh(MT_Scalar z, RAS_MaterialBucket::T_MeshSlotList::iterator &ms, RAS_MaterialBucket *bucket) : + m_z(z), + m_ms(ms), + m_bucket(bucket) + {} +}; - /* Camera's near plane equation: pnorm.dot(point) + pval, - * but we leave out pval since it's constant anyway */ - const MT_Vector3 pnorm(cameratrans.getBasis()[2]); - - for (bit = buckets.begin(); bit != buckets.end(); ++bit) - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - if (!mit->IsCulled()) - size++; - - slots.resize(size); - - for (bit = buckets.begin(); bit != buckets.end(); ++bit) - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - if (!mit->IsCulled()) - slots[i++].set(&*mit, *bit, pnorm); - - if(alpha) - sort(slots.begin(), slots.end(), backtofront()); - else - sort(slots.begin(), slots.end(), fronttoback()); -} +struct RAS_BucketManager::backtofront +{ + bool operator()(const alphamesh &a, const alphamesh &b) + { + return a.m_z < b.m_z; + } +}; + void RAS_BucketManager::RenderAlphaBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) -{ - vector slots; - vector::iterator sit; - - // Having depth masks disabled/enabled gives different artifacts in - // case no sorting is done or is done inexact. For compatibility, we - // disable it. - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); - - OrderBuckets(cameratrans, m_AlphaBuckets, slots, true); - - for(sit=slots.begin(); sit!=slots.end(); ++sit) { - rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); - - while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) - sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); - } - - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); -} - -void RAS_BucketManager::RenderSolidBuckets( - const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { BucketList::iterator bit; - list::iterator mit; - - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); - - for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if (mit->IsCulled()) - continue; - - rendertools->SetClientObject(rasty, mit->m_clientObj); - - while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) - (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit); + std::multiset alphameshset; + RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + /* Camera's near plane equation: cam_norm.dot(point) + cam_origin */ + const MT_Vector3 cam_norm(cameratrans.getBasis()[2]); + const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) + { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + { + if ((*mit).m_bVisible) + { + MT_Point3 pos((*mit).m_OpenGLMatrix[12], (*mit).m_OpenGLMatrix[13], (*mit).m_OpenGLMatrix[14]); + alphameshset.insert(alphamesh(MT_dot(cam_norm, pos) + cam_origin, mit, *bit)); + } } } - /* this code draws meshes order front-to-back instead to reduce overdraw. - * it turned out slower due to much material state switching, a more clever - * algorithm might do better. */ -#if 0 - vector slots; - vector::iterator sit; + // It shouldn't be strictly necessary to disable depth writes; but + // it is needed for compatibility. + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); - OrderBuckets(cameratrans, m_SolidBuckets, slots, false); - - for(sit=slots.begin(); sit!=slots.end(); ++sit) { - rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); - - while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) - sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); + RAS_IRasterizer::DrawMode drawingmode; + std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin(); + for (; msit != alphameshset.end(); ++msit) + { + rendertools->SetClientObject((*(*msit).m_ms).m_clientObj); + while ((*msit).m_bucket->ActivateMaterial(cameratrans, rasty, rendertools, drawingmode)) + (*msit).m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(*msit).m_ms, drawingmode); } -#endif + + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); } void RAS_BucketManager::Renderbuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - /* beginning each frame, clear (texture/material) caching information */ + BucketList::iterator bucket; + + rasty->EnableTextures(false); + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); + + // beginning each frame, clear (texture/material) caching information rasty->ClearCachingInfo(); - RenderSolidBuckets(cameratrans, rasty, rendertools); - RenderAlphaBuckets(cameratrans, rasty, rendertools); + RAS_MaterialBucket::StartFrame(); + + for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) + (*bucket)->Render(cameratrans,rasty,rendertools); - rendertools->SetClientObject(rasty, NULL); + RenderAlphaBuckets(cameratrans, rasty, rendertools); + RAS_MaterialBucket::EndFrame(); } RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { - BucketList::iterator it; - bucketCreated = false; - - for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) + BucketList::iterator it; + for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) + { if (*(*it)->GetPolyMaterial() == *material) return *it; + } for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) + { if (*(*it)->GetPolyMaterial() == *material) return *it; + } RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; - if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else - m_SolidBuckets.push_back(bucket); + m_MaterialBuckets.push_back(bucket); return bucket; } -void RAS_BucketManager::OptimizeBuckets(MT_Scalar distance) +void RAS_BucketManager::RAS_BucketManagerClearAll() { - BucketList::iterator bit; + BucketList::iterator it; + for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) + { + delete (*it); + } + for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) + { + delete(*it); + } - distance = 10.0; - - for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) - (*bit)->Optimize(distance); - for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) - (*bit)->Optimize(distance); + m_MaterialBuckets.clear(); + m_AlphaBuckets.clear(); } -void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat) +void RAS_BucketManager::ReleaseDisplayLists() { BucketList::iterator bit; - list::iterator mit; + RAS_MaterialBucket::T_MeshSlotList::iterator mit; - for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { - if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if(mit->m_DisplayList) { - mit->m_DisplayList->Release(); - mit->m_DisplayList = NULL; - } + for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; } } } for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { - if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if(mit->m_DisplayList) { - mit->m_DisplayList->Release(); - mit->m_DisplayList = NULL; - } + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; } } } diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 74526f365a0..08b67ed022f 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -39,33 +39,32 @@ class RAS_BucketManager { + //GEN_Map m_MaterialBuckets; + typedef std::vector BucketList; - BucketList m_SolidBuckets; + BucketList m_MaterialBuckets; BucketList m_AlphaBuckets; - struct sortedmeshslot; + struct alphamesh; struct backtofront; - struct fronttoback; public: RAS_BucketManager(); virtual ~RAS_BucketManager(); - void Renderbuckets(const MT_Transform & cameratrans, - RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); - - RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); - void OptimizeBuckets(MT_Scalar distance); - - void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL); - -private: - void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector& slots, bool alpha); - - void RenderSolidBuckets(const MT_Transform& cameratrans, - RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); void RenderAlphaBuckets(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); + void Renderbuckets(const MT_Transform & cameratrans, + RAS_IRasterizer* rasty, + class RAS_IRenderTools* rendertools); + + RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + + void ReleaseDisplayLists(); + +private: + void RAS_BucketManagerClearAll(); + }; #endif //__RAS_BUCKETMANAGER diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index 9cb59f300f7..dcb48c1c2a0 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -108,13 +108,6 @@ public : ) const { return m_frame_type; }; - - void - SetFrameType( - RAS_FrameType type - ) { - m_frame_type = type; - }; float BarRed( @@ -147,6 +140,14 @@ public : }; private : + + /** + * private to force use of public constructor + */ + + RAS_FrameSettings( + const RAS_FrameSettings & + ); RAS_FrameType m_frame_type; float m_bar_r; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index fb3607f89f4..4ee06d96603 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -42,8 +42,11 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int transp, bool alpha, bool zsort, - int lightlayer) - : m_texturename(texname), + int lightlayer, + bool bIsTriangle, + void* clientobject=NULL) : + + m_texturename(texname), m_materialname(matname), m_tile(tile), m_tilexrep(tilexrep), @@ -53,6 +56,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_alpha(alpha), m_zsort(zsort), m_lightlayer(lightlayer), + m_bIsTriangle(bIsTriangle), m_polymatid(m_newpolymatid++), m_flag(0), m_multimode(0) @@ -68,16 +72,15 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const { if(m_flag &RAS_BLENDERMAT) { - bool test = ( + return ( this->m_multimode == lhs.m_multimode && this->m_flag == lhs.m_flag && this->m_drawingmode == lhs.m_drawingmode && this->m_transp == lhs.m_transp && + this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() ); - - return test; } else { @@ -89,6 +92,8 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && this->m_drawingmode == lhs.m_drawingmode && + this->m_bIsTriangle == lhs.m_bIsTriangle && + this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() ); @@ -118,6 +123,11 @@ bool RAS_IPolyMaterial::IsZSort() const return m_zsort; } +bool RAS_IPolyMaterial::UsesTriangles() const +{ + return m_bIsTriangle; +} + unsigned int RAS_IPolyMaterial::hash() const { return m_texturename.hash(); @@ -162,10 +172,5 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const return dolights; } -bool RAS_IPolyMaterial::UsesObjectColor() const -{ - return !(m_flag & RAS_BLENDERGLSL); -} - unsigned int RAS_IPolyMaterial::m_newpolymatid = 0; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 218dd91cb30..8fc53e6b038 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -71,6 +71,7 @@ protected: bool m_alpha; bool m_zsort; int m_lightlayer; + bool m_bIsTriangle; unsigned int m_polymatid; static unsigned int m_newpolymatid; @@ -105,7 +106,9 @@ public: int transp, bool alpha, bool zsort, - int lightlayer); + int lightlayer, + bool bIsTriangle, + void* clientobject); virtual ~RAS_IPolyMaterial() {}; /** @@ -126,13 +129,14 @@ public: { return false; } - virtual void ActivateMeshSlot(const class RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const {} + virtual void ActivateMeshSlot(const class KX_MeshSlot & ms, RAS_IRasterizer* rasty) const {} virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; int GetLightLayer() const; bool IsAlpha() const; bool IsZSort() const; + bool UsesTriangles() const; unsigned int hash() const; int GetDrawingMode() const; const STR_String& GetMaterialName() const; @@ -141,7 +145,6 @@ public: const unsigned int GetFlag() const; virtual bool UsesLighting(RAS_IRasterizer *rasty) const; - virtual bool UsesObjectColor() const; /* * PreCalculate texture gen diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 411b28fa3b7..9e03212283e 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -168,10 +168,6 @@ public: * BeginFrame is called at the start of each frame. */ virtual bool BeginFrame(int drawingmode, double time)=0; - /** - * ClearColorBuffer clears the color buffer. - */ - virtual void ClearColorBuffer()=0; /** * ClearDepthBuffer clears the depth buffer. */ @@ -185,8 +181,7 @@ public: */ virtual void EndFrame()=0; /** - * SetRenderArea sets the render area from the 2d canvas. - * Returns true if only of subset of the canvas is used. + * SetRenderArea sets the render area from the 2d canvas */ virtual void SetRenderArea()=0; @@ -200,7 +195,6 @@ public: * @return true if stereo mode is enabled. */ virtual bool Stereo()=0; - virtual bool InterlacedStereo()=0; /** * Sets which eye buffer subsequent primitives will be rendered to. */ @@ -223,18 +217,39 @@ public: // Drawing Functions /** - * IndexPrimitives: Renders primitives from mesh slot. + * IndexPrimitives: Renders primitives. + * @param vertexarrays is an array of vertex arrays + * @param indexarrays is an array of index arrays + * @param mode determines the type of primitive stored in the vertex/index arrays + * @param useObjectColor will render the object using @param rgbacolor instead of + * vertex colors. */ - virtual void IndexPrimitives(class RAS_MeshSlot& ms)=0; - virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0; + virtual void IndexPrimitives( const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot)=0; + + virtual void IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot)=0; /** * IndexPrimitives_3DText will render text into the polygons. * The text to be rendered is from @param rendertools client object's text property. */ - virtual void IndexPrimitives_3DText(class RAS_MeshSlot& ms, + virtual void IndexPrimitives_3DText( const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools)=0; + class RAS_IRenderTools* rendertools, + bool useObjectColor, + const MT_Vector4& rgbacolor)=0; virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0; /* This one should become our final version, methinks. */ @@ -254,6 +269,9 @@ public: /** */ virtual const MT_Point3& GetCameraPosition()=0; + /** + */ + virtual void LoadViewMatrix()=0; /** */ virtual void SetFog(float start, @@ -290,6 +308,9 @@ public: * @return the current drawing mode: KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED. */ virtual int GetDrawingMode()=0; + /** + */ + virtual void EnableTextures(bool enable)=0; /** * Sets face culling */ @@ -364,9 +385,7 @@ public: virtual void SetAttribNum(int num) = 0; virtual void SetTexCoord(TexCoGen coords, int unit) = 0; virtual void SetAttrib(TexCoGen coords, int unit) = 0; - - virtual const MT_Matrix4x4& GetViewMatrix() const = 0; - virtual const MT_Matrix4x4& GetViewInvMatrix() const = 0; + virtual void GetViewMatrix(MT_Matrix4x4 &mat) const = 0; virtual bool QueryLists(){return false;} virtual bool QueryArrays(){return false;} @@ -379,7 +398,6 @@ public: virtual void SetMotionBlurState(int newstate)=0; virtual void SetBlendingMode(int blendmode)=0; - virtual void SetFrontFace(bool ccw)=0; }; #endif //__RAS_IRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp index 555a3520bb4..2be9bb75ebf 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp @@ -28,22 +28,42 @@ #include "RAS_IRenderTools.h" -void RAS_IRenderTools::SetClientObject(RAS_IRasterizer* rasty, void *obj) +#ifdef HAVE_CONFIG_H +#include +#endif + +void RAS_IRenderTools::SetViewMat(const MT_Transform& trans) +{ + trans.getValue(m_viewmat); +} + + + +void RAS_IRenderTools::SetClientObject(void* obj) { if (m_clientobject != obj) + { m_clientobject = obj; + m_modified = true; + } } + + void RAS_IRenderTools::SetAuxilaryClientInfo(void* inf) { m_auxilaryClientInfo = inf; } + + void RAS_IRenderTools::AddLight(struct RAS_LightObject* lightobject) { m_lights.push_back(lightobject); } + + void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject) { std::vector::iterator lit = @@ -51,5 +71,5 @@ void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject) if (!(lit==m_lights.end())) m_lights.erase(lit); -} +} diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 57f331e64cb..54a663ba111 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -44,9 +44,12 @@ class RAS_IRenderTools { protected: + float m_viewmat[16]; void* m_clientobject; void* m_auxilaryClientInfo; + bool m_modified; + std::vector m_lights; RAS_2DFilterManager m_filtermanager; @@ -65,7 +68,8 @@ public: RAS_IRenderTools( ) : - m_clientobject(NULL) + m_clientobject(NULL), + m_modified(true) { }; @@ -127,21 +131,24 @@ public: float v1[3], float v2[3], float v3[3], - float v4[3], - int glattrib + float v4[3] )=0; virtual - void - ProcessLighting( - int layer, + void + SetViewMat( const MT_Transform& trans + ); + + virtual + int + ProcessLighting( + int layer )=0; virtual void SetClientObject( - RAS_IRasterizer* rasty, void* obj ); @@ -183,6 +190,24 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas)=0; + + virtual + class RAS_IPolyMaterial* + CreateBlenderPolyMaterial( + const STR_String &texname, + bool ba, + const STR_String& matname, + int tile, + int tilexrep, + int tileyrep, + int mode, + bool transparant, + bool zsort, + int lightlayer, + bool bIsTriangle, + void* clientobject, + void* tface + )=0; }; #endif //__RAS_IRENDERTOOLS diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 788af29c4bb..0015b6a251f 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -28,6 +28,10 @@ #include "RAS_MaterialBucket.h" +#ifdef HAVE_CONFIG_H +#include +#endif + #ifdef WIN32 #pragma warning (disable:4786) #include @@ -40,420 +44,81 @@ #include "RAS_MeshObject.h" #include "RAS_Deformer.h" // __NLA -/* mesh slot */ -RAS_MeshSlot::RAS_MeshSlot() + +KX_VertexIndex::KX_VertexIndex(int size) { - m_clientObj = NULL; - m_pDeformer = NULL; - m_OpenGLMatrix = NULL; - m_mesh = NULL; - m_bucket = NULL; - m_bVisible = false; - m_bCulled = true; - m_bObjectColor = false; - m_RGBAcolor = MT_Vector4(0.0, 0.0, 0.0, 0.0); - m_DisplayList = NULL; - m_bDisplayList = true; - m_joinSlot = NULL; + m_size = size; } -RAS_MeshSlot::~RAS_MeshSlot() + + +void KX_VertexIndex::SetIndex(short loc,unsigned int index) { - vector::iterator it; + m_indexarray[loc]=index; +} - Split(true); +bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const +{ + bool result = ((m_mesh < lhs.m_mesh ) || + ((m_mesh == lhs.m_mesh)&&(m_OpenGLMatrix < lhs.m_OpenGLMatrix))); + + return result; +} - while(m_joinedSlots.size()) - m_joinedSlots.front()->Split(true); - - for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { - (*it)->m_users--; - if((*it)->m_users == 0) - delete *it; - } - - if (m_DisplayList) { +KX_MeshSlot::~KX_MeshSlot() +{ + if (m_DisplayList) m_DisplayList->Release(); - m_DisplayList = NULL; - } } -RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) -{ - vector::iterator it; - - m_clientObj = NULL; - m_pDeformer = NULL; - m_OpenGLMatrix = NULL; - m_mesh = slot.m_mesh; - m_bucket = slot.m_bucket; - m_bVisible = slot.m_bVisible; - m_bCulled = slot.m_bCulled; - m_bObjectColor = slot.m_bObjectColor; - m_RGBAcolor = slot.m_RGBAcolor; - m_DisplayList = NULL; - m_bDisplayList = slot.m_bDisplayList; - m_joinSlot = NULL; - m_currentArray = slot.m_currentArray; - m_displayArrays = slot.m_displayArrays; - m_joinedSlots = slot.m_joinedSlots; - - m_startarray = slot.m_startarray; - m_startvertex = slot.m_startvertex; - m_startindex = slot.m_startindex; - m_endarray = slot.m_endarray; - m_endvertex = slot.m_endvertex; - m_endindex = slot.m_endindex; - - for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { - *it = new RAS_DisplayArray(**it); - (*it)->m_users = 1; - } -} - -void RAS_MeshSlot::init(RAS_MaterialBucket *bucket, int numverts) -{ - m_bucket = bucket; - - SetDisplayArray(numverts); - - m_startarray = 0; - m_startvertex = 0; - m_startindex = 0; - m_endarray = 0; - m_endvertex = 0; - m_endindex = 0; -} - -void RAS_MeshSlot::begin(RAS_MeshSlot::iterator& it) -{ - int startvertex, endvertex; - int startindex, endindex; - - it.array = (m_displayArrays.size() > 0)? m_displayArrays[m_startarray]: NULL; - - if(it.array == NULL || it.array->m_index.size() == 0 || it.array->m_vertex.size() == 0) { - it.array = NULL; - it.vertex = NULL; - it.index = NULL; - it.startvertex = 0; - it.endvertex = 0; - it.totindex = 0; - } - else { - startvertex = m_startvertex; - endvertex = (m_startarray == m_endarray)? m_endvertex: it.array->m_vertex.size(); - startindex = m_startindex; - endindex = (m_startarray == m_endarray)? m_endindex: it.array->m_index.size(); - - it.vertex = &it.array->m_vertex[0]; - it.index = &it.array->m_index[startindex]; - it.startvertex = startvertex; - it.endvertex = endvertex; - it.totindex = endindex-startindex; - it.arraynum = m_startarray; - } -} - -void RAS_MeshSlot::next(RAS_MeshSlot::iterator& it) -{ - int startvertex, endvertex; - int startindex, endindex; - - if(it.arraynum == (size_t)m_endarray) { - it.array = NULL; - it.vertex = NULL; - it.index = NULL; - it.startvertex = 0; - it.endvertex = 0; - it.totindex = 0; - } - else { - it.arraynum++; - it.array = m_displayArrays[it.arraynum]; - - startindex = 0; - endindex = (it.arraynum == (size_t)m_endarray)? m_endindex: it.array->m_index.size(); - startvertex = 0; - endvertex = (it.arraynum == (size_t)m_endarray)? m_endvertex: it.array->m_vertex.size(); - - it.vertex = &it.array->m_vertex[0]; - it.index = &it.array->m_index[startindex]; - it.startvertex = startvertex; - it.endvertex = endvertex; - it.totindex = endindex-startindex; - } -} - -bool RAS_MeshSlot::end(RAS_MeshSlot::iterator& it) -{ - return (it.array == NULL); -} - -RAS_DisplayArray *RAS_MeshSlot::CurrentDisplayArray() -{ - return m_currentArray; -} - -void RAS_MeshSlot::SetDisplayArray(int numverts) -{ - vector::iterator it; - RAS_DisplayArray *darray = NULL; - - for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { - darray = *it; - - if(darray->m_type == numverts) { - if(darray->m_index.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_INDEX) - darray = NULL; - else if(darray->m_vertex.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_VERTEX) - darray = NULL; - else - break; - } - else - darray = NULL; - } - - if(!darray) { - darray = new RAS_DisplayArray(); - darray->m_users = 1; - - if(numverts == 2) darray->m_type = RAS_DisplayArray::LINE; - else if(numverts == 3) darray->m_type = RAS_DisplayArray::TRIANGLE; - else darray->m_type = RAS_DisplayArray::QUAD; - - m_displayArrays.push_back(darray); - - if(numverts == 2) - darray->m_type = RAS_DisplayArray::LINE; - else if(numverts == 3) - darray->m_type = RAS_DisplayArray::TRIANGLE; - else if(numverts == 4) - darray->m_type = RAS_DisplayArray::QUAD; - - m_endarray = m_displayArrays.size()-1; - m_endvertex = 0; - m_endindex = 0; - } - - m_currentArray = darray; -} - -void RAS_MeshSlot::AddPolygon(int numverts) -{ - SetDisplayArray(numverts); -} - -int RAS_MeshSlot::AddVertex(const RAS_TexVert& tv) -{ - RAS_DisplayArray *darray; - int offset; - - darray = m_currentArray; - darray->m_vertex.push_back(tv); - offset = darray->m_vertex.size()-1; - - if(darray == m_displayArrays[m_endarray]) - m_endvertex++; - - return offset; -} - -void RAS_MeshSlot::AddPolygonVertex(int offset) -{ - RAS_DisplayArray *darray; - - darray = m_currentArray; - darray->m_index.push_back(offset); - - if(darray == m_displayArrays[m_endarray]) - m_endindex++; -} - -bool RAS_MeshSlot::Equals(RAS_MeshSlot *target) -{ - if(!m_OpenGLMatrix || !target->m_OpenGLMatrix) - return false; - if(m_pDeformer || target->m_pDeformer) - return false; - if(m_bVisible != target->m_bVisible) - return false; - if(m_bObjectColor != target->m_bObjectColor) - return false; - if(m_bObjectColor && !(m_RGBAcolor == target->m_RGBAcolor)) - return false; - - return true; -} - -bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance) -{ - vector::iterator it; - iterator mit; - size_t i; - - // verify if we can join - if(m_joinSlot || m_joinedSlots.size() || target->m_joinSlot) - return false; - - if(!Equals(target)) - return false; - - MT_Vector3 co(&m_OpenGLMatrix[12]); - MT_Vector3 targetco(&target->m_OpenGLMatrix[12]); - - if((co - targetco).length() > distance) - return false; - - MT_Matrix4x4 mat(m_OpenGLMatrix); - MT_Matrix4x4 targetmat(target->m_OpenGLMatrix); - targetmat.invert(); - - MT_Matrix4x4 transform = targetmat*mat; - - // m_mesh, clientobj - m_joinSlot = target; - m_joinInvTransform = transform; - m_joinInvTransform.invert(); - target->m_joinedSlots.push_back(this); - - MT_Matrix4x4 ntransform = m_joinInvTransform.transposed(); - ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; - - for(begin(mit); !end(mit); next(mit)) - for(i=mit.startvertex; im_displayArrays.push_back(*it); - target->m_endarray++; - target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); - target->m_endindex = target->m_displayArrays.back()->m_index.size(); - } - - if (m_DisplayList) { - m_DisplayList->Release(); - m_DisplayList = NULL; - } - if (target->m_DisplayList) { - target->m_DisplayList->Release(); - target->m_DisplayList = NULL; - } - - return true; -#if 0 - return false; -#endif -} - -bool RAS_MeshSlot::Split(bool force) -{ - list::iterator jit; - RAS_MeshSlot *target = m_joinSlot; - vector::iterator it, jt; - iterator mit; - size_t i, found0 = 0, found1 = 0; - - if(target && (force || !Equals(target))) { - m_joinSlot = NULL; - - for(jit=target->m_joinedSlots.begin(); jit!=target->m_joinedSlots.end(); jit++) { - if(*jit == this) { - target->m_joinedSlots.erase(jit); - found0 = 1; - break; - } - } - - if(!found0) - abort(); - - for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { - found1 = 0; - for(jt=target->m_displayArrays.begin(); jt!=target->m_displayArrays.end(); jt++) { - if(*jt == *it) { - target->m_displayArrays.erase(jt); - target->m_endarray--; - found1 = 1; - break; - } - } - - if(!found1) - abort(); - } - - if(target->m_displayArrays.size()) { - target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); - target->m_endindex = target->m_displayArrays.back()->m_index.size(); - } - else { - target->m_endvertex = 0; - target->m_endindex = 0; - } - - MT_Matrix4x4 ntransform = m_joinInvTransform.inverse().transposed(); - ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; - - for(begin(mit); !end(mit); next(mit)) - for(i=mit.startvertex; im_DisplayList) { - target->m_DisplayList->Release(); - target->m_DisplayList = NULL; - } - - return true; - } - - return false; -} - -bool RAS_MeshSlot::IsCulled() -{ - list::iterator it; - - if(m_joinSlot) - return true; - if(!m_bCulled) - return false; - - for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++) - if(!(*it)->m_bCulled) - return false; - - return true; -} - -/* material bucket sorting */ - -struct RAS_MaterialBucket::less -{ - bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const - { - return *x->GetPolyMaterial() < *y->GetPolyMaterial(); - } -}; - -/* material bucket */ RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) + :m_bModified(true) { m_material = mat; } -RAS_MaterialBucket::~RAS_MaterialBucket() -{ -} + RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const { return m_material; } + + +void RAS_MaterialBucket::SetMeshSlot(KX_MeshSlot& ms) +{ + m_meshSlots.insert(ms); +} + + + +void RAS_MaterialBucket::RemoveMeshSlot(KX_MeshSlot& ms) +{ + T_MeshSlotList::iterator it = m_meshSlots.find(ms); + + if (!(it == m_meshSlots.end())) + m_meshSlots.erase(it); + +} + + + +void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms, + bool visible, + bool color, + const MT_Vector4& rgbavec) +{ + T_MeshSlotList::iterator it = m_meshSlots.find(ms); + + assert (!(it == m_meshSlots.end())); + (*it).m_bVisible = visible; + (*it).m_bObjectColor = color; + (*it).m_RGBAcolor= rgbavec; +} + bool RAS_MaterialBucket::IsAlpha() const { return (m_material->IsAlpha()); @@ -464,129 +129,162 @@ bool RAS_MaterialBucket::IsZSort() const return (m_material->IsZSort()); } -RAS_MeshSlot* RAS_MaterialBucket::AddMesh(int numverts) + + +void RAS_MaterialBucket::StartFrame() { - RAS_MeshSlot *ms; - - m_meshSlots.push_back(RAS_MeshSlot()); - - ms = &m_meshSlots.back(); - ms->init(this, numverts); - - return ms; } -RAS_MeshSlot* RAS_MaterialBucket::CopyMesh(RAS_MeshSlot *ms) + + +void RAS_MaterialBucket::EndFrame() { - m_meshSlots.push_back(RAS_MeshSlot(*ms)); - - return &m_meshSlots.back(); } -void RAS_MaterialBucket::RemoveMesh(RAS_MeshSlot* ms) +unsigned int RAS_MaterialBucket::NumMeshSlots() { - list::iterator it; - - for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) { - if(&*it == ms) { - m_meshSlots.erase(it); - return; - } - } + return m_meshSlots.size(); } -list::iterator RAS_MaterialBucket::msBegin() +RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin() { return m_meshSlots.begin(); } -list::iterator RAS_MaterialBucket::msEnd() +RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd() { return m_meshSlots.end(); } bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools) + RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode &drawmode) { + rendertools->SetViewMat(cameratrans); + if (!rasty->SetMaterial(*m_material)) return false; if (m_material->UsesLighting(rasty)) - rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); + rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*m_material->GetLightLayer()*/); else - rendertools->ProcessLighting(-1, cameratrans); + rendertools->ProcessLighting(-1); + + if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) + drawmode = RAS_IRasterizer::KX_MODE_LINES; + else if(m_material->UsesTriangles()) + drawmode = RAS_IRasterizer::KX_MODE_TRIANGLES; + else + drawmode = RAS_IRasterizer::KX_MODE_QUADS; return true; } void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, RAS_MeshSlot &ms) + RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode) { + if (!ms.m_bVisible) + return; + m_material->ActivateMeshSlot(ms, rasty); + /* __NLA Do the deformation */ if (ms.m_pDeformer) { ms.m_pDeformer->Apply(m_material); // KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_) } + /* End __NLA */ - if(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix)); + if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) + ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix)); rendertools->PushMatrix(); rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); if(rasty->QueryLists()) + { if(ms.m_DisplayList) ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified()); + } // verify if we can use display list, not for deformed object, and // also don't create a new display list when drawing shadow buffers, - // then it won't have texture coordinates for actual drawing. also - // for zsort we can't make a display list, since the polygon order - // changes all the time. + // then it won't have texture coordinates for actual drawing + KX_ListSlot **displaylist; if(ms.m_pDeformer) - ms.m_bDisplayList = false; + displaylist = 0; else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) - ms.m_bDisplayList = false; - else if (IsZSort()) - ms.m_bDisplayList = false; - else if(m_material->UsesObjectColor() && ms.m_bObjectColor) - ms.m_bDisplayList = false; + displaylist = 0; else - ms.m_bDisplayList = true; + displaylist = &ms.m_DisplayList; - // for text drawing using faces + // Use the text-specific IndexPrimitives for text faces if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) - rasty->IndexPrimitives_3DText(ms, m_material, rendertools); - // for multitexturing - else if((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL))) - rasty->IndexPrimitivesMulti(ms); - // use normal IndexPrimitives - else - rasty->IndexPrimitives(ms); + { + rasty->IndexPrimitives_3DText( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + m_material, + rendertools, // needed for textprinting on polys + ms.m_bObjectColor, + ms.m_RGBAcolor); + } - if(rasty->QueryLists()) + // for using glMultiTexCoord + else if((m_material->GetFlag() & RAS_MULTITEX)) + { + rasty->IndexPrimitivesMulti( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + ms.m_bObjectColor, + ms.m_RGBAcolor, + displaylist); + } + + // Use the normal IndexPrimitives + else + { + rasty->IndexPrimitives( + ms.m_mesh->GetVertexCache(m_material), + ms.m_mesh->GetIndexCache(m_material), + drawmode, + ms.m_bObjectColor, + ms.m_RGBAcolor, + displaylist); + } + + if(rasty->QueryLists()) { if(ms.m_DisplayList) ms.m_mesh->SetMeshModified(false); + } rendertools->PopMatrix(); } -void RAS_MaterialBucket::Optimize(MT_Scalar distance) +void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, + RAS_IRenderTools* rendertools) { - /* TODO: still have to check before this works correct: - * - lightlayer, frontface, text, billboard - * - make it work with physics */ - -#if 0 - list::iterator it; - list::iterator jt; + if (m_meshSlots.begin()== m_meshSlots.end()) + return; + + //rendertools->SetViewMat(cameratrans); - // greed joining on all following buckets - for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) - for(jt=it, jt++; jt!=m_meshSlots.end(); jt++) - jt->Join(&*it, distance); -#endif + //rasty->SetMaterial(*m_material); + + RAS_IRasterizer::DrawMode drawmode; + for (T_MeshSlotList::const_iterator it = m_meshSlots.begin(); + ! (it == m_meshSlots.end()); ++it) + { + rendertools->SetClientObject((*it).m_clientObj); + while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode)) { + RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode); + } + } + // to reset the eventual GL_CW mode + rendertools->SetClientObject(NULL); } + diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 475f01d549a..4eef889c533 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -36,15 +36,30 @@ #include "MT_Transform.h" #include "RAS_IPolygonMaterial.h" #include "RAS_IRasterizer.h" -#include "RAS_Deformer.h" - +#include "RAS_Deformer.h" // __NLA #include +#include #include -#include using namespace std; -/* Display List Slot */ +/** + * KX_VertexIndex + */ +struct KX_VertexIndex { +public: + KX_VertexIndex(int size); + void SetIndex(short loc,unsigned int index); + + // The vertex array + short m_vtxarray; + // An index into the vertex array for up to 4 verticies + unsigned short m_indexarray[4]; + short m_size; +}; +/** + * KX_ListSlot. + */ class KX_ListSlot { protected: @@ -65,149 +80,91 @@ public: virtual void SetModified(bool mod)=0; }; -class RAS_DisplayArray; -class RAS_MeshSlot; -class RAS_MeshMaterial; -class RAS_MaterialBucket; - -/* An array with data used for OpenGL drawing */ - -class RAS_DisplayArray +/** + * KX_MeshSlot. + */ +class KX_MeshSlot { public: - vector m_vertex; - vector m_index; - enum { LINE = 2, TRIANGLE = 3, QUAD = 4 } m_type; - //RAS_MeshSlot *m_origSlot; - int m_users; - - enum { BUCKET_MAX_INDEX = 65535 }; - enum { BUCKET_MAX_VERTEX = 65535 }; + void* m_clientObj; + RAS_Deformer* m_pDeformer; // __NLA + double* m_OpenGLMatrix; + class RAS_MeshObject* m_mesh; + mutable bool m_bVisible; // for visibility + mutable bool m_bObjectColor; + mutable MT_Vector4 m_RGBAcolor; + mutable KX_ListSlot* m_DisplayList; // for lists + KX_MeshSlot() : + m_pDeformer(NULL), + m_bVisible(true), + m_DisplayList(0) + { + } + ~KX_MeshSlot(); + bool Less(const KX_MeshSlot& lhs) const; }; -/* Entry of a RAS_MeshObject into RAS_MaterialBucket */ -class RAS_MeshSlot +inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs) { -private: - // indices into display arrays - int m_startarray; - int m_endarray; - int m_startindex; - int m_endindex; - int m_startvertex; - int m_endvertex; - vector m_displayArrays; - - // for construction only - RAS_DisplayArray* m_currentArray; - -public: - // for rendering - RAS_MaterialBucket* m_bucket; - RAS_MeshObject* m_mesh; - void* m_clientObj; - RAS_Deformer* m_pDeformer; - double* m_OpenGLMatrix; - // visibility - bool m_bVisible; - bool m_bCulled; - // object color - bool m_bObjectColor; - MT_Vector4 m_RGBAcolor; - // display lists - KX_ListSlot* m_DisplayList; - bool m_bDisplayList; - // joined mesh slots - RAS_MeshSlot* m_joinSlot; - MT_Matrix4x4 m_joinInvTransform; - list m_joinedSlots; - - RAS_MeshSlot(); - RAS_MeshSlot(const RAS_MeshSlot& slot); - virtual ~RAS_MeshSlot(); - - void init(RAS_MaterialBucket *bucket, int numverts); - - struct iterator { - RAS_DisplayArray *array; - RAS_TexVert *vertex; - unsigned short *index; - size_t startvertex; - size_t endvertex; - size_t totindex; - size_t arraynum; - }; - - void begin(iterator& it); - void next(iterator& it); - bool end(iterator& it); - - /* used during construction */ - void SetDisplayArray(int numverts); - RAS_DisplayArray *CurrentDisplayArray(); - - void AddPolygon(int numverts); - int AddVertex(const RAS_TexVert& tv); - void AddPolygonVertex(int offset); - - /* optimization */ - bool Split(bool force=false); - bool Join(RAS_MeshSlot *target, MT_Scalar distance); - bool Equals(RAS_MeshSlot *target); - bool IsCulled(); -}; - -/* Used by RAS_MeshObject, to point to it's slots in a bucket */ - -class RAS_MeshMaterial -{ -public: - RAS_MeshSlot *m_baseslot; - class RAS_MaterialBucket *m_bucket; - - GEN_Map m_slots; -}; - -/* Contains a list of display arrays with the same material, - * and a mesh slot for each mesh that uses display arrays in - * this bucket */ + return ( rhs.Less(lhs)); +} +/** + * Contains a list of meshs with the same material properties. + */ class RAS_MaterialBucket { public: + typedef std::set T_MeshSlotList; + RAS_MaterialBucket(RAS_IPolyMaterial* mat); - virtual ~RAS_MaterialBucket(); + virtual ~RAS_MaterialBucket() {} + + void Render(const MT_Transform& cameratrans, + class RAS_IRasterizer* rasty, + class RAS_IRenderTools* rendertools); - /* Bucket Sorting */ - struct less; - typedef set Set; - - /* Material Properties */ RAS_IPolyMaterial* GetPolyMaterial() const; - bool IsAlpha() const; - bool IsZSort() const; + bool IsAlpha() const; + bool IsZSort() const; - /* Rendering */ - bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools); + static void StartFrame(); + static void EndFrame(); + + void SetMeshSlot(KX_MeshSlot& ms); + void RemoveMeshSlot(KX_MeshSlot& ms); + void MarkVisibleMeshSlot(KX_MeshSlot& ms, + bool visible, + bool color, + const MT_Vector4& rgbavec); + void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, RAS_MeshSlot &ms); + RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode); + bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode& drawmode); - /* Mesh Slot Access */ - list::iterator msBegin(); - list::iterator msEnd(); - - class RAS_MeshSlot* AddMesh(int numverts); - class RAS_MeshSlot* CopyMesh(class RAS_MeshSlot *ms); - void RemoveMesh(class RAS_MeshSlot* ms); - void Optimize(MT_Scalar distance); + unsigned int NumMeshSlots(); + T_MeshSlotList::iterator msBegin(); + T_MeshSlotList::iterator msEnd(); + struct less + { + bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const + { + return *x->GetPolyMaterial() < *y->GetPolyMaterial(); + } + }; + + typedef set Set; private: - list m_meshSlots; + + T_MeshSlotList m_meshSlots; + bool m_bModified; RAS_IPolyMaterial* m_material; + double* m_pOGLMatrix; }; -#endif //__RAS_MATERIAL_BUCKET +#endif //__KX_BUCKET diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index a907994bf57..af5228e4c35 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -26,6 +26,10 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "MT_MinMax.h" @@ -33,7 +37,544 @@ #include -/* polygon sorting */ + +STR_String RAS_MeshObject::s_emptyname = ""; + + + +KX_ArrayOptimizer::~KX_ArrayOptimizer() +{ + for (vector::iterator itv = m_VertexArrayCache1.begin(); + !(itv == m_VertexArrayCache1.end());++itv) + { + delete (*itv); + } + + for (vector::iterator iti = m_IndexArrayCache1.begin(); + !(iti == m_IndexArrayCache1.end());++iti) + { + delete (*iti); + } + + m_TriangleArrayCount.clear(); + m_VertexArrayCache1.clear(); + m_IndexArrayCache1.clear(); + + +} + + + +RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) + : m_bModified(true), + m_lightlayer(lightlayer), + m_zsort(false), + m_MeshMod(true), + m_mesh(mesh), + m_class(0) +{ +} + + +bool RAS_MeshObject::MeshModified() +{ + return m_MeshMod; +} + + +RAS_MeshObject::~RAS_MeshObject() +{ + for (vector::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++) + { + delete (*it); + } + + ClearArrayData(); +} + + + +unsigned int RAS_MeshObject::GetLightLayer() +{ + return m_lightlayer; +} + + + +int RAS_MeshObject::NumMaterials() +{ + return m_materials.size(); +} + +const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) +{ + RAS_MaterialBucket* bucket = GetMaterialBucket(matid); + + return bucket?bucket->GetPolyMaterial()->GetMaterialName():s_emptyname; +} + +RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(unsigned int matid) +{ + if (m_materials.size() > 0 && (matid < m_materials.size())) + { + RAS_MaterialBucket::Set::const_iterator it = m_materials.begin(); + while (matid--) ++it; + return *it; + } + + return NULL; +} + + + +int RAS_MeshObject::NumPolygons() +{ + return m_Polygons.size(); +} + + + +RAS_Polygon* RAS_MeshObject::GetPolygon(int num) +{ + return m_Polygons[num]; +} + + + +RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetFirstMaterial() +{ + return m_materials.begin(); +} + + + +RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetLastMaterial() +{ + return m_materials.end(); +} + + + +void RAS_MeshObject::SetName(STR_String name) +{ + m_name = name; +} + + + +const STR_String& RAS_MeshObject::GetName() +{ + return m_name; +} + + + +const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) +{ + RAS_MaterialBucket* bucket = GetMaterialBucket(matid); + + return bucket?bucket->GetPolyMaterial()->GetTextureName():s_emptyname; +} + + + +void RAS_MeshObject::AddPolygon(RAS_Polygon* poly) +{ + m_Polygons.push_back(poly); +} + + + +void RAS_MeshObject::DebugColor(unsigned int abgr) +{ +/* + int numpolys = NumPolygons(); + for (int i=0;iVertexCount();v++) + { + RAS_TexVert* vtx = poly->GetVertex(v); + vtx->setDebugRGBA(abgr); + } + } + */ + + m_debugcolor = abgr; +} + +void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) +{ + const vecVertexArray & vertexvec = GetVertexCache(mat); + + for (vector::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) + { + KX_VertexArray::iterator vit; + for (vit=(*it)->begin(); vit != (*it)->end(); vit++) + { + vit->SetRGBA(rgba); + } + } +} + +void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, + int numverts, + RAS_IPolyMaterial* mat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); + + if (!mat->UsesTriangles()) + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); +} + + +void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, + int numverts, + int edgecode, + RAS_IPolyMaterial* mat) +{ + //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; + int edgetrace = 1<<(numverts-1); + bool drawedge = (edgecode & edgetrace)!=0; + edgetrace = 1; + int prevvert = idx.m_indexarray[numverts-1]; + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + for (int v = 0; v < numverts; v++) + { + unsigned int curvert = idx.m_indexarray[v]; + if (drawedge) + { + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(prevvert); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(curvert); + } + prevvert = curvert; + drawedge = (edgecode & edgetrace)!=0; + edgetrace*=2; + } + //m_IndexArrayCount[idx.m_vtxarray] = indexpos; +} + +int RAS_MeshObject::FindOrAddVertex(int vtxarray, + const MT_Point3& xyz, + const MT_Point2& uv, + const MT_Point2& uv2, + const MT_Vector4& tangent, + const unsigned int rgbacolor, + const MT_Vector3& normal, + bool flat, + RAS_IPolyMaterial* mat, + int origindex) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray]; + RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0,origindex); + +#define KX_FIND_SHARED_VERTICES +#ifdef KX_FIND_SHARED_VERTICES + if(!flat) { + for (std::vector::iterator it = m_xyz_index_to_vertex_index_mapping[origindex].begin(); + it != m_xyz_index_to_vertex_index_mapping[origindex].end(); + it++) + { + if ((*it).m_arrayindex1 == ao->m_index1 && + (*it).m_array == vtxarray && + *(*it).m_matid == *mat && + (*ao->m_VertexArrayCache1[vtxarray])[(*it).m_index].closeTo(&newvert) + ) + { + return (*it).m_index; + } + } + } +#endif // KX_FIND_SHARED_VERTICES + + // no vertex found, add one + ao->m_VertexArrayCache1[vtxarray]->push_back(newvert); + // printf("(%f,%f,%f) ",xyz[0],xyz[1],xyz[2]); + RAS_MatArrayIndex idx; + idx.m_arrayindex1 = ao->m_index1; + idx.m_array = vtxarray; + idx.m_index = numverts; + idx.m_matid = mat; + m_xyz_index_to_vertex_index_mapping[origindex].push_back(idx); + + return numverts; +} + +vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + return ao->m_VertexArrayCache1; +} + +int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat) +{ + int len = 0; + + const vecVertexArray & vertexvec = GetVertexCache(mat); + vector::const_iterator it = vertexvec.begin(); + + for (; it != vertexvec.end(); ++it) + { + len += (*it)->size(); + } + + return len; +} + + + +RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, + unsigned int index) +{ + RAS_TexVert* vertex = NULL; + + RAS_MaterialBucket* bucket = GetMaterialBucket(matid); + if (bucket) + { + RAS_IPolyMaterial* mat = bucket->GetPolyMaterial(); + if (mat) + { + const vecVertexArray & vertexvec = GetVertexCache(mat); + vector::const_iterator it = vertexvec.begin(); + + for (unsigned int len = 0; it != vertexvec.end(); ++it) + { + if (index < len + (*it)->size()) + { + vertex = &(*(*it))[index-len]; + break; + } + else + { + len += (*it)->size(); + } + } + } + } + + return vertex; +} + + + +const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + return ao->m_IndexArrayCache1; +} + + + +KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat) +{ + KX_ArrayOptimizer** aop = m_matVertexArrayS[polymat]; + + if(aop) + return *aop; + + // didn't find array, but an array might already exist + // for a material equal to this one + for(int i=0;igetValue()); + if(*mat == *polymat) { + m_matVertexArrayS.insert(polymat, *m_matVertexArrayS.at(i)); + return *m_matVertexArrayS.at(i); + } + } + + // create new array + int numelements = m_matVertexArrayS.size(); + m_sortedMaterials.push_back(polymat); + + KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements); + m_matVertexArrayS.insert(polymat, ao); + + return ao; +} + + + +void RAS_MeshObject::Bucketize(double* oglmatrix, + void* clientobj, + bool useObjectColor, + const MT_Vector4& rgbavec) +{ + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + ms.m_bObjectColor = useObjectColor; + ms.m_RGBAcolor = rgbavec; + + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) + { + RAS_MaterialBucket* bucket = *it; +// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); + bucket->SetMeshSlot(ms); + } + +} + + + +void RAS_MeshObject::MarkVisible(double* oglmatrix, + void* clientobj, + bool visible, + bool useObjectColor, + const MT_Vector4& rgbavec) +{ + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + ms.m_RGBAcolor = rgbavec; + ms.m_bObjectColor= useObjectColor; + + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) + { + RAS_MaterialBucket* bucket = *it; +// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); + bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); + } +} + + +void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, + void* clientobj) +{ + KX_MeshSlot ms; + ms.m_clientObj = clientobj; + ms.m_mesh = this; + ms.m_OpenGLMatrix = oglmatrix; + + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) + { + RAS_MaterialBucket* bucket = *it; +// RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); + //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); + bucket->RemoveMeshSlot(ms); + } + +} + + + +/* + * RAS_MeshObject::GetVertex returns the vertex located somewhere in the vertexpool + * it is the clients responsibility to make sure the array and index are valid + */ +RAS_TexVert* RAS_MeshObject::GetVertex(short array, + unsigned int index, + RAS_IPolyMaterial* polymat) +{ + KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat); + return &((*(ao->m_VertexArrayCache1)[array])[index]); +} + + + +void RAS_MeshObject::ClearArrayData() +{ + for (int i=0;im_VertexArrayCache1.size();i++) + { + if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES) + { + if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES)) + { + array = i; + ao->m_TriangleArrayCount[array]+=numverts-2; + break; + } + } + } + + if (array == -1) + { + array = ao->m_VertexArrayCache1.size(); + vector* va = new vector; + ao->m_VertexArrayCache1.push_back(va); + KX_IndexArray *ia = new KX_IndexArray(); + ao->m_IndexArrayCache1.push_back(ia); + ao->m_TriangleArrayCount.push_back(numverts-2); + } + + return array; +} + + + + +//void RAS_MeshObject::Transform(const MT_Transform& trans) +//{ + //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); + +// for (int i=0;iTransform(trans); +// } +//} + + +/* +void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) +{ + for (int i=0;iRelativeTransform(vec); + } +} +*/ + + + +void RAS_MeshObject::UpdateMaterialList() +{ + m_materials.clear(); + unsigned int numpolys = m_Polygons.size(); + // for all polygons, find out which material they use, and add it to the set of materials + for (unsigned int i=0;iGetMaterial()); + } +} struct RAS_MeshObject::polygonSlot { @@ -44,7 +585,7 @@ struct RAS_MeshObject::polygonSlot /* pnorm is the normal from the plane equation that the distance from is * used to sort again. */ - void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray, + void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray, int offset, int nvert, const MT_Vector3& pnorm) { MT_Vector3 center(0, 0, 0); @@ -52,7 +593,7 @@ struct RAS_MeshObject::polygonSlot for(i=0; i::iterator it; - - for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++) - delete (*it); -} - -bool RAS_MeshObject::MeshModified() -{ - return m_bMeshModified; -} - -unsigned int RAS_MeshObject::GetLightLayer() -{ - return m_lightlayer; -} - - - -int RAS_MeshObject::NumMaterials() -{ - return m_materials.size(); -} - -const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) -{ - RAS_MeshMaterial* mmat = GetMeshMaterial(matid); - - if(mmat) - return mmat->m_bucket->GetPolyMaterial()->GetMaterialName(); - - return s_emptyname; -} - -RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid) -{ - if (m_materials.size() > 0 && (matid < m_materials.size())) - { - list::iterator it = m_materials.begin(); - while (matid--) ++it; - return &*it; - } - - return NULL; -} - - - -int RAS_MeshObject::NumPolygons() -{ - return m_Polygons.size(); -} - - - -RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const -{ - return m_Polygons[num]; -} - - - - - list::iterator GetFirstMaterial(); - list::iterator GetLastMaterial(); -list::iterator RAS_MeshObject::GetFirstMaterial() -{ - return m_materials.begin(); -} - - - -list::iterator RAS_MeshObject::GetLastMaterial() -{ - return m_materials.end(); -} - - - -void RAS_MeshObject::SetName(STR_String name) -{ - m_name = name; -} - - - -const STR_String& RAS_MeshObject::GetName() -{ - return m_name; -} - - - -const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) -{ - RAS_MeshMaterial* mmat = GetMeshMaterial(matid); - - if(mmat) - return mmat->m_bucket->GetPolyMaterial()->GetTextureName(); - - return s_emptyname; -} - -RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat) -{ - list::iterator mit; - - /* find a mesh material */ - for(mit = m_materials.begin(); mit != m_materials.end(); mit++) - if(mit->m_bucket->GetPolyMaterial() == mat) - return &*mit; - - return NULL; -} - -RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts) -{ - RAS_MeshMaterial *mmat; - RAS_Polygon *poly; - RAS_MeshSlot *slot; - - /* find a mesh material */ - mmat = GetMeshMaterial(bucket->GetPolyMaterial()); - - /* none found, create a new one */ - if(!mmat) { - RAS_MeshMaterial meshmat; - meshmat.m_bucket = bucket; - meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts); - m_materials.push_back(meshmat); - mmat = &m_materials.back(); - } - - /* add it to the bucket, this also adds new display arrays */ - slot = mmat->m_baseslot; - slot->AddPolygon(numverts); - - /* create a new polygon */ - RAS_DisplayArray *darray = slot->CurrentDisplayArray(); - poly = new RAS_Polygon(bucket, darray, numverts); - m_Polygons.push_back(poly); - - return poly; -} - -void RAS_MeshObject::DebugColor(unsigned int abgr) -{ - /*int numpolys = NumPolygons(); - - for (int i=0;iVertexCount();v++) - RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr); - } - */ - - /* m_debugcolor = abgr; */ -} - -void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) -{ - RAS_MeshMaterial *mmat = GetMeshMaterial(mat); - RAS_MeshSlot *slot = mmat->m_baseslot; - RAS_MeshSlot::iterator it; - size_t i; - - for(slot->begin(it); !slot->end(it); slot->next(it)) - for(i=it.startvertex; iGetMaterial()->GetPolyMaterial()); - slot = mmat->m_baseslot; - darray = slot->CurrentDisplayArray(); - - if(!flat) { - /* find vertices shared between faces, with the restriction - * that they exist in the same display array, and have the - * same uv coordinate etc */ - vector& sharedmap = m_sharedvertex_map[origindex]; - vector::iterator it; - - for(it = sharedmap.begin(); it != sharedmap.end(); it++) - { - if(it->m_darray != darray) - continue; - if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert)) - continue; - - /* found one, add it and we're done */ - if(poly->IsVisible()) - slot->AddPolygonVertex(it->m_offset); - poly->SetVertexOffset(i, it->m_offset); - return; - } - } - - /* no shared vertex found, add a new one */ - offset = slot->AddVertex(texvert); - if(poly->IsVisible()) - slot->AddPolygonVertex(offset); - poly->SetVertexOffset(i, offset); - - if(!flat) { - SharedVertex shared; - shared.m_darray = darray; - shared.m_offset = offset; - m_sharedvertex_map[origindex].push_back(shared); - } -} - -int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat) -{ - RAS_MeshMaterial *mmat; - RAS_MeshSlot *slot; - RAS_MeshSlot::iterator it; - size_t len = 0; - - mmat = GetMeshMaterial(mat); - slot = mmat->m_baseslot; - for(slot->begin(it); !slot->end(it); slot->next(it)) - len += it.endvertex - it.startvertex; - - return len; -} - - -RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, - unsigned int index) -{ - RAS_MeshMaterial *mmat; - RAS_MeshSlot *slot; - RAS_MeshSlot::iterator it; - size_t len; - - mmat = GetMeshMaterial(matid); - - if(!mmat) - return NULL; - - slot = mmat->m_baseslot; - len = 0; - for(slot->begin(it); !slot->end(it); slot->next(it)) { - if(index >= len + it.endvertex - it.startvertex) - len += it.endvertex - it.startvertex; - else - return &it.vertex[index - len]; - } - - return NULL; -} - -void RAS_MeshObject::AddMeshUser(void *clientobj) -{ - list::iterator it; - - for(it = m_materials.begin();it!=m_materials.end();++it) { - /* always copy from the base slot, which is never removed - * since new objects can be created with the same mesh data */ - RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot); - ms->m_clientObj = clientobj; - it->m_slots.insert(clientobj, ms); - } -} - -void RAS_MeshObject::UpdateBuckets(void* clientobj, - double* oglmatrix, - bool useObjectColor, - const MT_Vector4& rgbavec, - bool visible, - bool culled) -{ - list::iterator it; - - for(it = m_materials.begin();it!=m_materials.end();++it) { - RAS_MeshSlot **msp = it->m_slots[clientobj]; - - if(!msp) - continue; - - RAS_MeshSlot *ms = *msp; - - ms->m_mesh = this; - ms->m_OpenGLMatrix = oglmatrix; - ms->m_bObjectColor = useObjectColor; - ms->m_RGBAcolor = rgbavec; - ms->m_bVisible = visible; - ms->m_bCulled = culled || !visible; - - /* split if necessary */ - ms->Split(); - } -} - -void RAS_MeshObject::RemoveFromBuckets(void *clientobj) -{ - list::iterator it; - - for(it = m_materials.begin();it!=m_materials.end();++it) { - RAS_MeshSlot **msp = it->m_slots[clientobj]; - - if(!msp) - continue; - - RAS_MeshSlot *ms = *msp; - - it->m_bucket->RemoveMesh(ms); - it->m_slots.remove(clientobj); - } -} - -//void RAS_MeshObject::Transform(const MT_Transform& trans) -//{ - //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); - -// for (int i=0;iTransform(trans); -// } -//} - - -/* -void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) -{ - for (int i=0;iRelativeTransform(vec); - } -} -*/ - -void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform) +void RAS_MeshObject::SortPolygons(const MT_Transform &transform) { // Limitations: sorting is quite simple, and handles many // cases wrong, partially due to polygons being sorted per @@ -466,34 +645,43 @@ void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transfor // to avoid excessive state changes while drawing. e) would // require splitting polygons. - RAS_MeshSlot::iterator it; - size_t j; + if (!m_zsort) + return; - for(ms.begin(it); !ms.end(it); ms.next(it)) { - unsigned int nvert = (int)it.array->m_type; - unsigned int totpoly = it.totindex/nvert; + // Extract camera Z plane... + const MT_Vector3 pnorm(transform.getBasis()[2]); + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; - if(totpoly <= 1) - continue; - if(it.array->m_type == RAS_DisplayArray::LINE) + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) + { + if(!(*it)->IsZSort()) continue; - // Extract camera Z plane... - const MT_Vector3 pnorm(transform.getBasis()[2]); - // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial(); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - vector slots(totpoly); + vecIndexArrays& indexarrays = ao->m_IndexArrayCache1; + vecVertexArray& vertexarrays = ao->m_VertexArrayCache1; + unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4; - /* get indices and z into temporary array */ - for(j=0; j slots(totpoly); - /* get indices from temporary array again */ - for(j=0; jIsZSort()) + m_zsort = true; + + if (drawingmode == RAS_IRasterizer::KX_WIREFRAME) + { + for (i=0;iIsVisible()) + ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(), + poly->GetMaterial()->GetPolyMaterial()); + + } + m_zsort = false; + } + else + { + for (i=0;iIsVisible()) + SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(), + poly->GetMaterial()->GetPolyMaterial()); + } + } + m_bModified = false; - m_bMeshModified = true; + m_MeshMod = true; } } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 0d35a2f402b..99806666fa6 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -36,7 +36,6 @@ #include #include -#include #include "RAS_Polygon.h" #include "RAS_MaterialBucket.h" @@ -45,71 +44,194 @@ #include "GEN_HashedPtr.h" struct Mesh; +/** + * This class holds an array of vertices and indicies. + */ +class KX_ArrayOptimizer +{ +public: + KX_ArrayOptimizer(int index) + : m_index1(index) + {}; + virtual ~KX_ArrayOptimizer(); + + vector m_VertexArrayCache1; + vector m_TriangleArrayCount; + vector m_IndexArrayCache1; -/* RAS_MeshObject is a mesh used for rendering. It stores polygons, - * but the actual vertices and index arrays are stored in material - * buckets, referenced by the list of RAS_MeshMaterials. */ + /** + order in which they are stored into the mesh + */ + int m_index1; +}; +/** + * This struct holds a triangle. + */ +struct RAS_TriangleIndex +{ +public: + int m_index[3]; + int m_array; + RAS_IPolyMaterial* m_matid; + bool m_collider; +}; + +/** + * This class looks horribly broken. Only m_matid is used, and + * m_matid is a (int) RAS_IPolyMaterial*. + * --> m_matid == lhs.m_matid should be *m_matid == *lhs.m_matid + */ +class RAS_MatArrayIndex +{ +public: + + int m_arrayindex1; + RAS_IPolyMaterial* m_matid; + int m_array; + int m_index; + +/* + inline bool Less(const RAS_MatArrayIndex& lhs) const { + bool result = + ( (m_matid < lhs.m_matid) || + ((m_matid == lhs.m_matid)&&(m_array < lhs.m_array)) || + ((m_matid == lhs.m_matid) && (m_array == lhs.m_array) && + (m_index < lhs.m_index)) + + ); + return result; + + } +*/ + +}; +/* +inline bool operator <( const RAS_MatArrayIndex& rhs,const RAS_MatArrayIndex& lhs) +{ + return ( rhs.Less(lhs)); +}*/ + +/** + * RAS_MeshObject stores mesh data for the renderer. + */ class RAS_MeshObject { -private: + + // GEN_Map m_matVertexArrayS; + //vector m_vertexArrays; + virtual KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat); + //vector m_polygons; + unsigned int m_debugcolor; - int m_lightlayer; - bool m_bModified; - bool m_bMeshModified; - + int m_lightlayer; + + vector m_Polygons; STR_String m_name; static STR_String s_emptyname; + bool m_zsort; + bool m_MeshMod; - vector m_Polygons; - - /* polygon sorting */ struct polygonSlot; struct backtofront; struct fronttoback; -protected: - list m_materials; - Mesh* m_mesh; - bool m_bDeformed; + void SchedulePoly( + const KX_VertexIndex& idx, + int numverts, + RAS_IPolyMaterial* mat + ); + void ScheduleWireframePoly( + const KX_VertexIndex& idx, + int numverts, + int edgecode, + RAS_IPolyMaterial* mat + ); + +protected: + enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192}; + enum { BUCKET_MAX_TRIANGLES = 65535 }; + + GEN_Map m_matVertexArrayS; + + RAS_MaterialBucket::Set m_materials; + Mesh* m_mesh; public: // for now, meshes need to be in a certain layer (to avoid sorting on lights in realtime) RAS_MeshObject(Mesh* mesh, int lightlayer); virtual ~RAS_MeshObject(); - - bool IsDeformed() { return m_bDeformed; } + vector m_sortedMaterials; + vector > m_xyz_index_to_vertex_index_mapping; + vector m_triangle_indices; - /* materials */ + int m_class; + + unsigned int GetLightLayer(); int NumMaterials(); const STR_String& GetMaterialName(unsigned int matid); + RAS_MaterialBucket* GetMaterialBucket(unsigned int matid); const STR_String& GetTextureName(unsigned int matid); - - RAS_MeshMaterial* GetMeshMaterial(unsigned int matid); - RAS_MeshMaterial* GetMeshMaterial(RAS_IPolyMaterial *mat); - - list::iterator GetFirstMaterial(); - list::iterator GetLastMaterial(); - - unsigned int GetLightLayer(); - - /* name */ - void SetName(STR_String name); - const STR_String& GetName(); - - /* modification state */ - bool MeshModified(); - void SetMeshModified(bool v){m_bMeshModified = v;} - - /* original blender mesh */ - Mesh* GetMesh() { return m_mesh; } - - /* mesh construction */ + virtual void AddPolygon(RAS_Polygon* poly); + void UpdateMaterialList(); - virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts); - virtual void AddVertex(RAS_Polygon *poly, int i, + int NumPolygons(); + RAS_Polygon* GetPolygon(int num); + + virtual void Bucketize( + double* oglmatrix, + void* clientobj, + bool useObjectColor, + const MT_Vector4& rgbavec + ); + + void RemoveFromBuckets( + double* oglmatrix, + void* clientobj + ); + + void MarkVisible( + double* oglmatrix, + void* clientobj, + bool visible, + bool useObjectColor, + const MT_Vector4& rgbavec + ); + + void DebugColor(unsigned int abgr); + void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); + + /** + * Sorts the polygons by their transformed z values. + */ + void SortPolygons(const MT_Transform &transform); + + void SchedulePolygons(int drawingmode); + + void ClearArrayData(); + + RAS_MaterialBucket::Set::iterator GetFirstMaterial(); + RAS_MaterialBucket::Set::iterator GetLastMaterial(); + + virtual RAS_TexVert* GetVertex( + short array, + unsigned int index, + RAS_IPolyMaterial* polymat + ); + + virtual int FindVertexArray( + int numverts, + RAS_IPolyMaterial* polymat + ); + + + // find (and share) or add vertices + // for some speedup, only the last 20 added vertices are searched for equality + + virtual int FindOrAddVertex( + int vtxarray, const MT_Point3& xyz, const MT_Point2& uv, const MT_Point2& uv2, @@ -117,43 +239,27 @@ public: const unsigned int rgbacolor, const MT_Vector3& normal, bool flat, - int origindex); - - void SchedulePolygons(int drawingmode); - - /* vertex and polygon acces */ - int NumVertices(RAS_IPolyMaterial* mat); - RAS_TexVert* GetVertex(unsigned int matid, unsigned int index); - - int NumPolygons(); - RAS_Polygon* GetPolygon(int num) const; + RAS_IPolyMaterial* mat, + int origindex + ); - /* buckets */ - virtual void AddMeshUser(void *clientobj); - virtual void UpdateBuckets( - void* clientobj, - double* oglmatrix, - bool useObjectColor, - const MT_Vector4& rgbavec, - bool visible, - bool culled); - - void RemoveFromBuckets(void *clientobj); - - /* colors */ - void DebugColor(unsigned int abgr); - void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); + vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat); - /* polygon sorting by Z for alpha */ - void SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform); + int GetVertexArrayLength(RAS_IPolyMaterial* mat); - /* for construction to find shared vertices */ - struct SharedVertex { - RAS_DisplayArray *m_darray; - int m_offset; - }; + RAS_TexVert* GetVertex( + unsigned int matid, + unsigned int index + ); + + const vecIndexArrays& GetIndexCache (RAS_IPolyMaterial* mat); + void SetName(STR_String name); + const STR_String& GetName(); + + bool MeshModified(); + void SetMeshModified(bool v){m_MeshMod = v;} + Mesh* GetMesh() { return m_mesh; } - vector > m_sharedvertex_map; }; #endif //__RAS_MESHOBJECT diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index e4403ace69f..2a6d64ecc73 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -32,7 +32,6 @@ SET(INC ../../../../intern/moto/include ../../../../source/gameengine/Rasterizer ../../../../extern/glew/include - ../../../../source/blender/gpu ) BLENDERLIB(bf_oglrasterizer "${SRC}" "${INC}") diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile index aee485a22be..f01978b8eb1 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile @@ -41,11 +41,12 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../../kernel/gen_system -CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../BlenderRoutines CPPFLAGS += -I.. - ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings endif +ifeq ($(WITH_BF_GLEXT),true) + CPPFLAGS += -DWITH_GLEXT +endif diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index 2c4b55ff964..c2687319717 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -9,7 +9,6 @@ #include "GL/glew.h" -#include "RAS_MaterialBucket.h" #include "RAS_TexVert.h" #include "MT_assert.h" @@ -126,20 +125,20 @@ void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) } } -RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) +RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot) { /* Keep a copy of constant lists submitted for rendering, this guards against (replicated)new...delete every frame, and we can reuse lists! - :: sorted by mesh slot + :: sorted by vertex array */ - RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList; + RAS_ListSlot* localSlot = (RAS_ListSlot*)*slot; if(!localSlot) { - RAS_Lists::iterator it = mLists.find(&ms); + RAS_Lists::iterator it = mLists.find(vertexarrays); if(it == mLists.end()) { localSlot = new RAS_ListSlot(this); - mLists.insert(std::pair(&ms, localSlot)); + mLists.insert(std::pair(vertexarrays, localSlot)); } else { localSlot = static_cast(it->second->AddRef()); } @@ -158,45 +157,69 @@ void RAS_ListRasterizer::ReleaseAlloc() mLists.clear(); } -void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) + +void RAS_ListRasterizer::IndexPrimitives( + const vecVertexArray & vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot) { RAS_ListSlot* localSlot =0; - if(ms.m_bDisplayList) { - localSlot = FindOrAdd(ms); + // useObjectColor(are we updating every frame?) + if(!useObjectColor && slot) { + localSlot = FindOrAdd(vertexarrays, slot); localSlot->DrawList(); if(localSlot->End()) { // save slot here too, needed for replicas and object using same mesh // => they have the same vertexarray but different mesh slot - ms.m_DisplayList = localSlot; + *slot = localSlot; return; } } - if (mUseVertexArrays) - RAS_VAOpenGLRasterizer::IndexPrimitives(ms); - else - RAS_OpenGLRasterizer::IndexPrimitives(ms); + if (mUseVertexArrays) { + RAS_VAOpenGLRasterizer::IndexPrimitives( + vertexarrays, indexarrays, + mode, useObjectColor, + rgbacolor,slot + ); + } else { + RAS_OpenGLRasterizer::IndexPrimitives( + vertexarrays, indexarrays, + mode, useObjectColor, + rgbacolor,slot + ); + } - if(ms.m_bDisplayList) { + if(!useObjectColor && slot) { localSlot->EndList(); - ms.m_DisplayList = localSlot; + *slot = localSlot; } } -void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) +void RAS_ListRasterizer::IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot) { RAS_ListSlot* localSlot =0; - if(ms.m_bDisplayList) { - localSlot = FindOrAdd(ms); + // useObjectColor(are we updating every frame?) + if(!useObjectColor && slot) { + localSlot = FindOrAdd(vertexarrays, slot); localSlot->DrawList(); if(localSlot->End()) { // save slot here too, needed for replicas and object using same mesh // => they have the same vertexarray but different mesh slot - ms.m_DisplayList = localSlot; + *slot = localSlot; return; } } @@ -204,14 +227,23 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) // workaround: note how we do not use vertex arrays for making display // lists, since glVertexAttribPointerARB doesn't seem to work correct // in display lists on ATI? either a bug in the driver or in Blender .. - if (mUseVertexArrays && !localSlot) - RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms); - else - RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); + if (mUseVertexArrays && !localSlot) { + RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( + vertexarrays, indexarrays, + mode, useObjectColor, + rgbacolor,slot + ); + } else { + RAS_OpenGLRasterizer::IndexPrimitivesMulti( + vertexarrays, indexarrays, + mode, useObjectColor, + rgbacolor,slot + ); + } - if(ms.m_bDisplayList) { + if(!useObjectColor && slot) { localSlot->EndList(); - ms.m_DisplayList = localSlot; + *slot = localSlot; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index 96d6d2a995d..b1b19144c12 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -4,7 +4,6 @@ #include "RAS_MaterialBucket.h" #include "RAS_VAOpenGLRasterizer.h" #include -#include class RAS_ListRasterizer; class RAS_ListSlot : public KX_ListSlot @@ -35,14 +34,14 @@ enum RAS_ListSlotFlags { LIST_REGEN =64 }; -typedef std::map RAS_Lists; +typedef std::map RAS_Lists; class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer { bool mUseVertexArrays; RAS_Lists mLists; - RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms); + RAS_ListSlot* FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot); void ReleaseAlloc(); public: @@ -50,8 +49,23 @@ public: RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false); virtual ~RAS_ListRasterizer(); - virtual void IndexPrimitives(class RAS_MeshSlot& ms); - virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); + virtual void IndexPrimitives( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot + ); + + virtual void IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot + ); virtual bool Init(); virtual void Exit(); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 87a0a1d8b9e..1dcc6e70934 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -38,9 +38,6 @@ #include "MT_CmMatrix4x4.h" #include "RAS_IRenderTools.h" // rendering text -#include "GPU_draw.h" -#include "GPU_material.h" - /** * 32x32 bit masks for vinterlace stereo mode */ @@ -70,12 +67,10 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), - m_last_blendmode(GPU_BLEND_SOLID), - m_last_frontface(true), + m_last_blendmode(0), m_materialCachingInfo(0) { - m_viewmatrix.setIdentity(); - m_viewinvmatrix.setIdentity(); + m_viewmatrix.Identity(); for (int i = 0; i < 32; i++) { @@ -92,9 +87,81 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() { } + + +static void Myinit_gl_stuff(void) +{ + float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + float mat_shininess[] = { 35.0 }; +/* float one= 1.0; */ + int a, x, y; + GLubyte pat[32*32]; + const GLubyte *patc= pat; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + +#if defined(__FreeBSD) || defined(__linux__) + glDisable(GL_DITHER); /* op sgi/sun hardware && 12 bits */ +#endif + + /* no local viewer, looks ugly in ortho mode */ + /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ + + glDepthFunc(GL_LEQUAL); + /* scaling matrices */ + glEnable(GL_NORMALIZE); + + glShadeModel(GL_FLAT); + + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_LOGIC_OP); + glDisable(GL_STENCIL_TEST); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glPixelTransferi(GL_MAP_COLOR, GL_FALSE); + glPixelTransferi(GL_RED_SCALE, 1); + glPixelTransferi(GL_RED_BIAS, 0); + glPixelTransferi(GL_GREEN_SCALE, 1); + glPixelTransferi(GL_GREEN_BIAS, 0); + glPixelTransferi(GL_BLUE_SCALE, 1); + glPixelTransferi(GL_BLUE_BIAS, 0); + glPixelTransferi(GL_ALPHA_SCALE, 1); + glPixelTransferi(GL_ALPHA_BIAS, 0); + + a = 0; + for(x=0; x<32; x++) + { + for(y=0; y<4; y++) + { + if( (x) & 1) pat[a++]= 0x88; + else pat[a++]= 0x22; + } + } + + glPolygonStipple(patc); + + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glEnable(GL_CULL_FACE); +} + + + bool RAS_OpenGLRasterizer::Init() { - GPU_state_init(); + + Myinit_gl_stuff(); m_redback = 0.4375; m_greenback = 0.4375; @@ -105,12 +172,7 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - m_last_blendmode = GPU_BLEND_SOLID; - - glFrontFace(GL_CCW); - m_last_frontface = true; + SetBlendingMode(0); glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -254,10 +316,21 @@ void RAS_OpenGLRasterizer::Exit() EndFrame(); } +bool RAS_OpenGLRasterizer::InterlacedStereo() const +{ + return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; +} + bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) { m_time = time; m_drawingmode = drawingmode; + + if (!InterlacedStereo() || m_curreye == RAS_STEREO_LEFTEYE) + { + m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); + m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); + } // Blender camera routine destroys the settings if (m_drawingmode < KX_SOLID) @@ -271,12 +344,7 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - m_last_blendmode = GPU_BLEND_SOLID; - - glFrontFace(GL_CCW); - m_last_frontface = true; + SetBlendingMode(0); glShadeModel(GL_SMOOTH); @@ -291,28 +359,34 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) { m_drawingmode = drawingmode; - if(m_drawingmode == KX_WIREFRAME) - glDisable(GL_CULL_FACE); + switch (m_drawingmode) + { + case KX_WIREFRAME: + { + glDisable (GL_CULL_FACE); + break; + } + default: + { + } + } } + + int RAS_OpenGLRasterizer::GetDrawingMode() { return m_drawingmode; } + void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask) { glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE); } -void RAS_OpenGLRasterizer::ClearColorBuffer() -{ - m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); - m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); -} - void RAS_OpenGLRasterizer::ClearDepthBuffer() { @@ -423,10 +497,6 @@ bool RAS_OpenGLRasterizer::Stereo() return true; } -bool RAS_OpenGLRasterizer::InterlacedStereo() -{ - return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; -} void RAS_OpenGLRasterizer::SetEye(const StereoEye eye) { @@ -503,84 +573,294 @@ void RAS_OpenGLRasterizer::SwapBuffers() -const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const +void RAS_OpenGLRasterizer::GetViewMatrix(MT_Matrix4x4 &mat) const { - return m_viewmatrix; + float viewmat[16]; + glGetFloatv(GL_MODELVIEW_MATRIX, viewmat); + mat.setValue(viewmat); } -const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewInvMatrix() const -{ - return m_viewinvmatrix; -} -void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, - class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools) + +void RAS_OpenGLRasterizer::IndexPrimitives(const vecVertexArray & vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot + ) { - bool obcolor = ms.m_bObjectColor; - MT_Vector4& rgba = ms.m_RGBAcolor; - RAS_MeshSlot::iterator it; + const RAS_TexVert* vertexarray; + unsigned int numindices, vt; - // handle object color - if (obcolor) { + for (vt=0;vtm_type; - - if(it.array->m_type == RAS_DisplayArray::LINE) { - // line drawing, no text - glBegin(GL_LINES); - - for(i=0; igetXYZ()); - - vertex = &it.vertex[it.index[i+1]]; - glVertex3fv(vertex->getXYZ()); - } - - glEnd(); - } - else { - // triangle and quad text drawing - for(i=0; igetXYZ()[0]; - v[j][1] = vertex->getXYZ()[1]; - v[j][2] = vertex->getXYZ()[2]; - } - - // find the right opengl attribute - glattrib = -1; - if(GLEW_ARB_vertex_program) - for(unit=0; unitRenderText(polymat->GetDrawingMode(), polymat, - v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib); - - ClearCachingInfo(); - } - } } - - glDisableClientState(GL_COLOR_ARRAY); + + for (vt=0;vtRenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,v4); + ClearCachingInfo(); + } + break; + } + case KX_MODE_TRIANGLES: + { + glBegin(GL_TRIANGLES); + vindex=0; + for (unsigned int i=0;iRenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,NULL); + ClearCachingInfo(); + } + glEnd(); + break; + } + default: + { + } + } //switch + } //for each vertexarray } void RAS_OpenGLRasterizer::SetTexCoordNum(int num) @@ -617,14 +897,14 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) if(GLEW_ARB_multitexture) { for(unit=0; unitm_type; + const RAS_TexVert* vertexarray; + unsigned int numindices,vt; - if(it.array->m_type == RAS_DisplayArray::LINE) { - // line drawing - glBegin(GL_LINES); + for (vt=0;vtgetXYZ()); - - vertex = &it.vertex[it.index[i+1]]; - glVertex3fv(vertex->getXYZ()); - } - - glEnd(); - } - else { - // triangle and quad drawing - if(it.array->m_type == RAS_DisplayArray::TRIANGLE) - glBegin(GL_TRIANGLES); - else - glBegin(GL_QUADS); - - for(i=0; igetRGBA())); - - glNormal3fv(vertex->getNormal()); - - if(multi) - TexCoord(*vertex); - else - glTexCoord2fv(vertex->getUV1()); - } - - glVertex3fv(vertex->getXYZ()); + glBegin(GL_LINES); + vindex=0; + for (unsigned int i=0;i #include "GL/glew.h" -#include "GPU_extensions.h" #include "STR_String.h" #include "RAS_TexVert.h" @@ -78,16 +77,16 @@ void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode) { case KX_BOUNDINGBOX: case KX_WIREFRAME: - //glDisableClientState(GL_COLOR_ARRAY); - //glDisable(GL_CULL_FACE); + glDisableClientState(GL_COLOR_ARRAY); + glDisable(GL_CULL_FACE); break; case KX_SOLID: - //glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); break; case KX_TEXTURED: case KX_SHADED: case KX_SHADOW: - //glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); default: break; } @@ -99,121 +98,141 @@ void RAS_VAOpenGLRasterizer::Exit() glEnableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + EnableTextures(false); RAS_OpenGLRasterizer::Exit(); } -void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) +void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot) { - static const GLsizei stride = sizeof(RAS_TexVert); - bool wireframe = m_drawingmode <= KX_WIREFRAME; - RAS_MeshSlot::iterator it; + static const GLsizei vtxstride = sizeof(RAS_TexVert); GLenum drawmode; + if(mode == KX_MODE_TRIANGLES) + drawmode = GL_TRIANGLES; + else if(mode == KX_MODE_QUADS) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; - if(!wireframe) - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + const RAS_TexVert* vertexarray; + unsigned int numindices, vt; + + if (drawmode != GL_LINES) + { + if (useObjectColor) + { + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + } else + { + glColor4d(0,0,0,1.0); + glEnableClientState(GL_COLOR_ARRAY); + } + } + else + { + glColor3d(0,0,0); + } + + EnableTextures(false); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); // use glDrawElements to draw each vertexarray - for(ms.begin(it); !ms.end(it); ms.next(it)) { - if(it.totindex == 0) + for (vt=0;vtgetLocalXYZ()); + glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); + glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1()); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); - // drawing mode - if(it.array->m_type == RAS_DisplayArray::TRIANGLE) - drawmode = GL_TRIANGLES; - else if(it.array->m_type == RAS_DisplayArray::QUAD) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - - // colors - if (drawmode != GL_LINES && !wireframe) { - if (ms.m_bObjectColor) { - const MT_Vector4& rgba = ms.m_RGBAcolor; - - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - } - else { - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - glEnableClientState(GL_COLOR_ARRAY); - } - } - else - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - - glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); - glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); - if(!wireframe) { - glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1()); - if(glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); - } + //if(m_Lock) + // local->Begin(vertexarrays[vt]->size()); // here the actual drawing takes places - glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0])); + + //if(m_Lock) + // local->End(); } - if(!wireframe) { - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - } + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } -void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) +void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot) { - static const GLsizei stride = sizeof(RAS_TexVert); - bool wireframe = m_drawingmode <= KX_WIREFRAME; - RAS_MeshSlot::iterator it; + static const GLsizei vtxstride = sizeof(RAS_TexVert); + GLenum drawmode; + if(mode == KX_MODE_TRIANGLES) + drawmode = GL_TRIANGLES; + else if(mode == KX_MODE_QUADS) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; - if(!wireframe) - EnableTextures(true); + const RAS_TexVert* vertexarray; + unsigned int numindices, vt; - // use glDrawElements to draw each vertexarray - for(ms.begin(it); !ms.end(it); ms.next(it)) { - if(it.totindex == 0) - continue; - - // drawing mode - if(it.array->m_type == RAS_DisplayArray::TRIANGLE) - drawmode = GL_TRIANGLES; - else if(it.array->m_type == RAS_DisplayArray::QUAD) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - - // colors - if (drawmode != GL_LINES && !wireframe) { - if (ms.m_bObjectColor) { - const MT_Vector4& rgba = ms.m_RGBAcolor; - - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); - } - else { - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - glEnableClientState(GL_COLOR_ARRAY); - } + if (drawmode != GL_LINES) + { + if (useObjectColor) + { + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); } else - glColor4f(0.0f, 0.0f, 0.0f, 1.0f); - - glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); - glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); - if(!wireframe) { - TexCoordPtr(it.vertex); - if(glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); + { + glColor4d(0,0,0,1.0); + glEnableClientState(GL_COLOR_ARRAY); } - - // here the actual drawing takes places - glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + else + { + glColor3d(0,0,0); } - if(!wireframe) { - glDisableClientState(GL_COLOR_ARRAY); - EnableTextures(false); + // use glDrawElements to draw each vertexarray + for (vt=0;vtgetLocalXYZ()); + glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); + TexCoordPtr(vertexarray); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); + + //if(m_Lock) + // local->Begin(vertexarrays[vt]->size()); + + // here the actual drawing takes places + glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0])); + + //if(m_Lock) + // local->End(); } } @@ -229,7 +248,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) for(unit=0; unitgetFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) { + if(tv->getFlag() & TV_2NDUV && (int)tv->getUnit() == unit) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2()); continue; @@ -238,7 +257,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ()); break; case RAS_TEXCO_UV1: glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1()); @@ -265,7 +284,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) switch(m_attrib[unit]) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ()); break; case RAS_TEXCO_UV1: glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); @@ -294,6 +313,11 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) TexCoGen *texco, *attrib; int unit, texco_num, attrib_num; + /* disable previously enabled texture coordinates and attributes. ideally + * this shouldn't be necessary .. */ + if(enable) + EnableTextures(false); + /* we cache last texcoords and attribs to ensure we disable the ones that * were actually last set */ if(enable) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h index 766bbfbed0e..e4cc4ace0e8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h @@ -50,10 +50,22 @@ public: virtual void SetDrawingMode(int drawingmode); - virtual void IndexPrimitives(class RAS_MeshSlot& ms); - virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); + virtual void IndexPrimitives( const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot); + + virtual void IndexPrimitivesMulti( + const vecVertexArray& vertexarrays, + const vecIndexArrays & indexarrays, + DrawMode mode, + bool useObjectColor, + const MT_Vector4& rgbacolor, + class KX_ListSlot** slot); + -private: virtual void EnableTextures(bool enable); //virtual bool QueryArrays(){return true;} //virtual bool QueryLists(){return m_Lock;} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 8d46528f7f0..0cf9c326370 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -1,9 +1,12 @@ #!/usr/bin/python Import ('env') +if env['WITH_BF_GLEXT'] == 1: + env['CPPFLAGS'].append('-DWITH_GLEXT') + sources = env.Glob('*.cpp') incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' -incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] +incs += ' #extern/glew/include ' + env['BF_OPENGL_INC'] env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120] ) diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index 50331d7a664..b74cb9cfcac 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -26,82 +26,99 @@ * ***** END GPL LICENSE BLOCK ***** */ +#ifdef HAVE_CONFIG_H +#include +#endif + #ifdef WIN32 + #pragma warning (disable:4786) #endif #include "RAS_Polygon.h" -RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray *darray, int numvert) +RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, + bool visible, + int numverts, + int vtxarrayindex) + :m_bucket(bucket), + m_vertexindexbase(numverts), + m_numverts(numverts), + m_edgecode(65535) { - m_bucket = bucket; - m_darray = darray; - m_offset[0]= m_offset[1]= m_offset[2]= m_offset[3]= 0; - m_numvert = numvert; - - m_edgecode = 255; - m_polyflags = 0; + m_vertexindexbase.m_vtxarray = vtxarrayindex ;//m_bucket->FindVertexArray(numverts); + m_polyFlags.Visible = visible; } + + int RAS_Polygon::VertexCount() { - return m_numvert; + return m_numverts; } -void RAS_Polygon::SetVertexOffset(int i, unsigned short offset) + + +void RAS_Polygon::SetVertex(int i, + unsigned int vertexindex ) //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal) { - m_offset[i] = offset; + m_vertexindexbase.SetIndex(i,vertexindex); //m_bucket->FindOrAddVertex(m_vertexindexbase.m_vtxarray, + //xyz,uv,rgbacolor,normal)); } -RAS_TexVert *RAS_Polygon::GetVertex(int i) + + +const KX_VertexIndex& RAS_Polygon::GetIndexBase() { - return &m_darray->m_vertex[m_offset[i]]; + return m_vertexindexbase; } -int RAS_Polygon::GetVertexOffset(int i) + + +void RAS_Polygon::SetVisibleWireframeEdges(int edgecode) { - return m_offset[i]; + m_edgecode = edgecode; } + + +// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. int RAS_Polygon::GetEdgeCode() { return m_edgecode; } -void RAS_Polygon::SetEdgeCode(int edgecode) -{ - m_edgecode = edgecode; -} bool RAS_Polygon::IsVisible() { - return (m_polyflags & VISIBLE) != 0; + return m_polyFlags.Visible; } -void RAS_Polygon::SetVisible(bool visible) -{ - if(visible) m_polyflags |= VISIBLE; - else m_polyflags &= ~VISIBLE; -} + bool RAS_Polygon::IsCollider() { - return (m_polyflags & COLLIDER) != 0; + return m_polyFlags.Collider; } -void RAS_Polygon::SetCollider(bool visible) + + +void RAS_Polygon::SetCollider(bool col) { - if(visible) m_polyflags |= COLLIDER; - else m_polyflags &= ~COLLIDER; + m_polyFlags.Collider = col; } -RAS_MaterialBucket* RAS_Polygon::GetMaterial() + + +KX_VertexIndex& RAS_Polygon::GetVertexIndexBase() +{ + return m_vertexindexbase; +} + + + +RAS_MaterialBucket* RAS_Polygon::GetMaterial() { return m_bucket; } - -RAS_DisplayArray* RAS_Polygon::GetDisplayArray() -{ - return m_darray; -} diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h index 18526ba45f7..7ce7926a816 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.h +++ b/source/gameengine/Rasterizer/RAS_Polygon.h @@ -35,47 +35,55 @@ #include using namespace std; -/* polygon flags */ + +// +// Bitfield that stores the flags for each CValue derived class +// +struct PolygonFlags { + PolygonFlags() : + Visible(true), + Collider(true) + { + } + unsigned char Visible : 1; + unsigned char Collider : 1; + //int Visible : 1; + //int Collider : 1; +}; class RAS_Polygon { - /* location */ RAS_MaterialBucket* m_bucket; - RAS_DisplayArray* m_darray; - unsigned short m_offset[4]; - unsigned short m_numvert; - - /* flags */ - unsigned char m_edgecode; - unsigned char m_polyflags; + KX_VertexIndex m_vertexindexbase; + int m_numverts; + int m_edgecode; + PolygonFlags m_polyFlags; + public: - enum { - VISIBLE = 1, - COLLIDER = 2 - }; - - RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray* darray, int numvert); + RAS_Polygon(RAS_MaterialBucket* bucket, + bool visible, + int numverts, + int vtxarrayindex) ; virtual ~RAS_Polygon() {}; +// RAS_TexVert* GetVertex(int index); int VertexCount(); - RAS_TexVert* GetVertex(int i); - - void SetVertexOffset(int i, unsigned short offset); - int GetVertexOffset(int i); + void SetVertex(int i, unsigned int vertexindex); //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal) + const KX_VertexIndex& GetIndexBase(); + + void SetVisibleWireframeEdges(int edgecode); // each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. int GetEdgeCode(); - void SetEdgeCode(int edgecode); bool IsVisible(); - void SetVisible(bool visible); - bool IsCollider(); - void SetCollider(bool collider); + void SetCollider(bool col); + KX_VertexIndex& GetVertexIndexBase(); RAS_MaterialBucket* GetMaterial(); - RAS_DisplayArray* GetDisplayArray(); + }; #endif diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index d6f1fe912be..935633dc636 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -27,7 +27,12 @@ */ #include "RAS_TexVert.h" -#include "MT_Matrix4x4.h" + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define SHORT(x) short(x*32767.0) RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Point2& uv, @@ -35,7 +40,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const bool flat, + const short flag, const unsigned int origindex) { xyz.getValue(m_localxyz); @@ -44,7 +49,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, SetRGBA(rgba); SetNormal(normal); tangent.getValue(m_tangent); - m_flag = (flat)? FLAT: 0; + m_flag = flag; m_origindex = origindex; m_unit = 2; } @@ -96,7 +101,7 @@ void RAS_TexVert::SetFlag(const short flag) void RAS_TexVert::SetUnit(const unsigned int u) { - m_unit = u<=MAX_UNIT?u:MAX_UNIT; + m_unit = u<=TV_MAX?u:TV_MAX; } void RAS_TexVert::SetNormal(const MT_Vector3& normal) @@ -104,18 +109,12 @@ void RAS_TexVert::SetNormal(const MT_Vector3& normal) normal.getValue(m_normal); } -void RAS_TexVert::SetTangent(const MT_Vector3& tangent) -{ - tangent.getValue(m_tangent); -} - // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { return (m_flag == other->m_flag && m_rgba == other->m_rgba && MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) && - MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) && MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) && MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) && // p -- MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))) ; @@ -132,10 +131,11 @@ unsigned int RAS_TexVert::getUnit() const return m_unit; } -void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) -{ - SetXYZ((mat*MT_Vector4(m_localxyz[0], m_localxyz[1], m_localxyz[2], 1.0)).getValue()); - SetNormal((nmat*MT_Vector4(m_normal[0], m_normal[1], m_normal[2], 1.0)).getValue()); - SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); -} +void RAS_TexVert::getOffsets(void* &xyz, void* &uv1, void* &rgba, void* &normal) const +{ + xyz = (void *) m_localxyz; + uv1 = (void *) m_uv1; + rgba = (void *) &m_rgba; + normal = (void *) m_normal; +} diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 4ec4db19e53..bf092b4b230 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -37,6 +37,11 @@ static MT_Point3 g_pt3; static MT_Point2 g_pt2; +#define TV_CALCFACENORMAL 0x0001 +#define TV_2NDUV 0x0002 + +#define TV_MAX 3//match Def in BL_Material.h + class RAS_TexVert { @@ -54,12 +59,6 @@ class RAS_TexVert // 32 bytes total size, fits nice = 56 = not fit nice. // We'll go for 64 bytes total size - 24 bytes left. public: - enum { - FLAT = 1, - SECOND_UV = 2, - MAX_UNIT = 8 - }; - short getFlag() const; unsigned int getUnit() const; @@ -71,7 +70,7 @@ public: const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const bool flat, + const short flag, const unsigned int origindex); ~RAS_TexVert() {}; @@ -83,7 +82,7 @@ public: return m_uv2; }; - const float* getXYZ() const { + const float* getLocalXYZ() const { return m_localxyz; }; @@ -109,19 +108,20 @@ public: void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); - void SetTangent(const MT_Vector3& tangent); void SetFlag(const short flag); void SetUnit(const unsigned u); void SetRGBA(const MT_Vector4& rgba); const MT_Point3& xyz(); - void Transform(const class MT_Matrix4x4& mat, - const class MT_Matrix4x4& nmat); - - // compare two vertices, to test if they can be shared, used for - // splitting up based on uv's, colors, etc + // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool closeTo(const RAS_TexVert* other); + + bool closeTo(const MT_Point3& otherxyz, + const MT_Point2& otheruv, + const unsigned int otherrgba, + short othernormal[3]) const; + void getOffsets(void*&xyz, void *&uv1, void *&rgba, void *&normal) const; }; #endif //__RAS_TEXVERT diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index a024f7e0ee6..e6bc657ed6d 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -3,8 +3,11 @@ Import ('env') sources = env.Glob('*.cpp') +if env['WITH_BF_GLEXT'] == 1: + env['CPPFLAGS'].append('-DWITH_GLEXT') -incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna' + +incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions' incs += ' ' + env['BF_PYTHON_INC'] if env['OURPLATFORM']=='win32-vc': diff --git a/source/kernel/gen_system/GEN_Map.h b/source/kernel/gen_system/GEN_Map.h index 88c79293223..37c75d8293a 100644 --- a/source/kernel/gen_system/GEN_Map.h +++ b/source/kernel/gen_system/GEN_Map.h @@ -50,19 +50,6 @@ public: m_buckets[i] = 0; } } - - GEN_Map(const GEN_Map& map) - { - m_num_buckets = map.m_num_buckets; - m_buckets = new Entry *[m_num_buckets]; - - for (int i = 0; i < m_num_buckets; ++i) { - m_buckets[i] = 0; - - for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) - insert(entry->m_key, entry->m_value); - } - } int size() { int count=0; diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 424a7c558d7..9c1a28de999 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -56,6 +56,9 @@ all debug:: # Object Config_Guess DIRectory export OCGDIR = $(NAN_OBJDIR)/$(CONFIG_GUESS) + export WITH_GLEXT?=true + export WITH_BF_GLEXT?=$(WITH_GLEXT) + # Determines what targets are built export WITH_BF_DYNAMICOPENGL ?= true export WITH_BF_STATICOPENGL ?= false @@ -284,7 +287,7 @@ endif export FREEDESKTOP ?= true export NAN_PYTHON ?= /usr/local - export NAN_PYTHON_VERSION ?= 2.5 + 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 ?= /usr/local @@ -299,9 +302,9 @@ endif export NAN_NSPR ?= /usr/local 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) + export NAN_SDL ?= $(shell sdl11-config --prefix) + export NAN_SDLLIBS ?= $(shell sdl11-config --libs) + export NAN_SDLCFLAGS ?= $(shell sdl11-config --cflags) # Uncomment the following line to use Mozilla inplace of netscape # CPPFLAGS +=-DMOZ_NOT_NET diff --git a/tools/Blender.py b/tools/Blender.py index 3f928ff8c97..2c982a0a46f 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -129,9 +129,6 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_STATICOPENGL']: statlibs += Split(lenv['BF_OPENGL_LIB_STATIC']) - if lenv['WITH_BF_STATICPYTHON']: - statlibs += Split(lenv['BF_PYTHON_LIB_STATIC']) - if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'): libincs += Split(lenv['BF_PTHREADS_LIBPATH']) @@ -144,12 +141,10 @@ def setup_syslibs(lenv): lenv['BF_PNG_LIB'], lenv['BF_ZLIB_LIB'] ] - - if not lenv['WITH_BF_STATICPYTHON']: - if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): - syslibs.append(lenv['BF_PYTHON_LIB']+'_d') - else: - syslibs.append(lenv['BF_PYTHON_LIB']) + if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): + syslibs.append(lenv['BF_PYTHON_LIB']+'_d') + else: + syslibs.append(lenv['BF_PYTHON_LIB']) if lenv['WITH_BF_INTERNATIONAL']: syslibs += Split(lenv['BF_FREETYPE_LIB']) syslibs += Split(lenv['BF_GETTEXT_LIB']) diff --git a/tools/btools.py b/tools/btools.py index afcc83d2002..a25120f6c4b 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -27,7 +27,7 @@ def print_arguments(args, bc): def validate_arguments(args, bc): opts_list = [ - 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', + 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', @@ -51,6 +51,7 @@ def validate_arguments(args, bc): 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', 'BF_OPENGL_LINKFLAGS', 'WITH_BF_FTGL', 'BF_FTGL', 'BF_FTGL_INC', 'BF_FTGL_LIB', 'WITH_BF_PLAYER', + 'WITH_BF_GLEXT', 'WITH_BF_BINRELOC', 'CFLAGS', 'CCFLAGS', 'CPPFLAGS', 'REL_CFLAGS', 'REL_CCFLAGS', @@ -144,10 +145,8 @@ def read_opts(cfg, args): ('BF_PYTHON_INC', 'include path for Python headers', ''), ('BF_PYTHON_BINARY', 'Path to the Python interpreter', ''), ('BF_PYTHON_LIB', 'Python library', ''), - ('BF_PYTHON_LIB_STATIC', 'Python static libraries', ''), ('BF_PYTHON_LIBPATH', 'Library path', ''), ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), - (BoolOption('WITH_BF_STATICPYTHON', 'Staticly link to python', 'false')), (BoolOption('BF_NO_ELBEEM', 'Disable Fluid Sim', 'false')), (BoolOption('WITH_BF_YAFRAY', 'Enable Yafray', 'true')), (BoolOption('WITH_BF_OPENAL', 'Use OpenAL if true', '')), @@ -293,6 +292,7 @@ def read_opts(cfg, args): ('BF_FTGL_INC', 'FTGL include path', ''), ('BF_FTGL_LIB', 'FTGL libraries', ''), + (BoolOption('WITH_BF_GLEXT', 'Enable GL Extensions', 'true')), (BoolOption('WITH_BF_PLAYER', 'Build blenderplayer if true', 'false')), ('CFLAGS', 'C-compiler flags', ''), From 656ee61718d85f9366115756ba28e4b53f36d6b2 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 19 Sep 2008 14:15:36 +0000 Subject: [PATCH 05/10] Merge from trunk (The last time there was some files missing due to failed connection to svn server while merging.. thats why this stuff of reverting last merge and redoing it) svn merge -r 16231:16608 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- CMake/macros.cmake | 4 + CMakeLists.txt | 21 +- SConstruct | 36 + blenderplayer/CMakeLists.txt | 2 + config/darwin-config.py | 14 +- config/linux2-config.py | 13 + config/linuxcross-config.py | 11 + config/openbsd3-config.py | 5 + config/sunos5-config.py | 11 + config/win32-mingw-config.py | 6 + config/win32-vc-config.py | 11 + extern/bullet2/CMakeLists.txt | 1 + extern/bullet2/Makefile | 3 +- .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 186 +- extern/bullet2/readme.txt | 5 + extern/bullet2/src/Bullet-C-Api.h | 140 +- .../BroadphaseCollision/btAxisSweep3.cpp | 638 +-- .../BroadphaseCollision/btAxisSweep3.h | 870 +++- .../btBroadphaseInterface.h | 28 +- .../BroadphaseCollision/btBroadphaseProxy.h | 57 +- .../btCollisionAlgorithm.cpp | 2 +- .../btCollisionAlgorithm.h | 11 +- .../BroadphaseCollision/btDbvt.cpp | 1289 +++++ .../BroadphaseCollision/btDbvt.h | 1112 +++++ .../BroadphaseCollision/btDbvtBroadphase.cpp | 547 +++ .../BroadphaseCollision/btDbvtBroadphase.h | 117 + .../BroadphaseCollision/btDispatcher.h | 22 +- .../btMultiSapBroadphase.cpp | 466 ++ .../btMultiSapBroadphase.h | 144 + .../btOverlappingPairCache.cpp | 535 +- .../btOverlappingPairCache.h | 351 +- .../btOverlappingPairCallback.h | 40 + .../BroadphaseCollision/btQuantizedBvh.cpp | 1025 ++++ .../BroadphaseCollision/btQuantizedBvh.h | 486 ++ .../btSimpleBroadphase.cpp | 234 +- .../BroadphaseCollision/btSimpleBroadphase.h | 94 +- .../src/BulletCollision/CMakeLists.txt | 93 + .../SphereTriangleDetector.cpp | 15 +- .../SphereTriangleDetector.h | 6 +- .../btBoxBoxCollisionAlgorithm.cpp | 85 + .../btBoxBoxCollisionAlgorithm.h | 66 + .../CollisionDispatch/btBoxBoxDetector.cpp | 683 +++ .../CollisionDispatch/btBoxBoxDetector.h | 44 + .../btCollisionConfiguration.h | 47 + .../CollisionDispatch/btCollisionCreateFunc.h | 2 +- .../btCollisionDispatcher.cpp | 237 +- .../CollisionDispatch/btCollisionDispatcher.h | 62 +- .../CollisionDispatch/btCollisionObject.cpp | 12 +- .../CollisionDispatch/btCollisionObject.h | 98 +- .../CollisionDispatch/btCollisionWorld.cpp | 644 ++- .../CollisionDispatch/btCollisionWorld.h | 202 +- .../btCompoundCollisionAlgorithm.cpp | 217 +- .../btCompoundCollisionAlgorithm.h | 33 +- .../btConvexConcaveCollisionAlgorithm.cpp | 27 +- .../btConvexConcaveCollisionAlgorithm.h | 24 +- .../btConvexConvexAlgorithm.cpp | 20 +- .../btConvexConvexAlgorithm.h | 25 +- .../btConvexPlaneCollisionAlgorithm.cpp | 108 + .../btConvexPlaneCollisionAlgorithm.h | 71 + .../btDefaultCollisionConfiguration.cpp | 291 ++ .../btDefaultCollisionConfiguration.h | 115 + .../btEmptyCollisionAlgorithm.h | 10 +- .../CollisionDispatch/btManifoldResult.cpp | 30 +- .../CollisionDispatch/btManifoldResult.h | 29 +- .../btSimulationIslandManager.cpp | 129 +- .../btSimulationIslandManager.h | 14 +- .../btSphereBoxCollisionAlgorithm.cpp | 19 +- .../btSphereBoxCollisionAlgorithm.h | 23 +- .../btSphereSphereCollisionAlgorithm.cpp | 19 +- .../btSphereSphereCollisionAlgorithm.h | 18 +- .../btSphereTriangleCollisionAlgorithm.cpp | 18 +- .../btSphereTriangleCollisionAlgorithm.h | 18 +- .../CollisionDispatch/btUnionFind.cpp | 4 +- .../CollisionDispatch/btUnionFind.h | 6 +- .../CollisionShapes/btBoxShape.cpp | 23 +- .../CollisionShapes/btBoxShape.h | 104 +- .../btBvhTriangleMeshShape.cpp | 223 +- .../CollisionShapes/btBvhTriangleMeshShape.h | 40 +- .../CollisionShapes/btCapsuleShape.cpp | 36 +- .../CollisionShapes/btCapsuleShape.h | 78 +- .../CollisionShapes/btCollisionShape.cpp | 9 +- .../CollisionShapes/btCollisionShape.h | 45 +- .../CollisionShapes/btCompoundShape.cpp | 169 +- .../CollisionShapes/btCompoundShape.h | 93 +- .../CollisionShapes/btConcaveShape.h | 6 +- .../CollisionShapes/btConeShape.h | 12 +- .../CollisionShapes/btConvexHullShape.h | 20 +- .../CollisionShapes/btConvexInternalShape.cpp | 78 + .../CollisionShapes/btConvexInternalShape.h | 98 + .../CollisionShapes/btConvexShape.cpp | 59 - .../CollisionShapes/btConvexShape.h | 93 +- .../btConvexTriangleMeshShape.cpp | 115 +- .../btConvexTriangleMeshShape.h | 24 +- .../CollisionShapes/btCylinderShape.cpp | 14 +- .../CollisionShapes/btCylinderShape.h | 20 +- .../CollisionShapes/btEmptyShape.cpp | 2 +- .../CollisionShapes/btEmptyShape.h | 14 +- .../btHeightfieldTerrainShape.cpp | 115 +- .../btHeightfieldTerrainShape.h | 17 +- .../CollisionShapes/btMaterial.h | 34 + .../CollisionShapes/btMinkowskiSumShape.cpp | 6 +- .../CollisionShapes/btMinkowskiSumShape.h | 12 +- .../CollisionShapes/btMultiSphereShape.cpp | 4 +- .../CollisionShapes/btMultiSphereShape.h | 13 +- .../btMultimaterialTriangleMeshShape.cpp | 45 + .../btMultimaterialTriangleMeshShape.h | 124 + .../CollisionShapes/btOptimizedBvh.cpp | 657 +-- .../CollisionShapes/btOptimizedBvh.h | 299 +- .../btPolyhedralConvexShape.cpp | 42 +- .../CollisionShapes/btPolyhedralConvexShape.h | 38 +- .../btScaledBvhTriangleMeshShape.cpp | 103 + .../btScaledBvhTriangleMeshShape.h | 57 + .../CollisionShapes/btShapeHull.cpp | 164 + .../CollisionShapes/btShapeHull.h | 56 + .../CollisionShapes/btSphereShape.cpp | 2 +- .../CollisionShapes/btSphereShape.h | 20 +- .../CollisionShapes/btStaticPlaneShape.cpp | 5 +- .../CollisionShapes/btStaticPlaneShape.h | 16 +- .../btStridingMeshInterface.cpp | 6 +- .../CollisionShapes/btStridingMeshInterface.h | 12 +- .../CollisionShapes/btTetrahedronShape.h | 6 +- .../CollisionShapes/btTriangleBuffer.cpp | 9 +- .../CollisionShapes/btTriangleBuffer.h | 10 +- .../CollisionShapes/btTriangleCallback.h | 4 +- .../btTriangleIndexVertexArray.cpp | 45 +- .../btTriangleIndexVertexArray.h | 40 +- .../btTriangleIndexVertexMaterialArray.cpp | 86 + .../btTriangleIndexVertexMaterialArray.h | 84 + .../CollisionShapes/btTriangleMesh.cpp | 117 +- .../CollisionShapes/btTriangleMesh.h | 60 +- .../CollisionShapes/btTriangleMeshShape.cpp | 19 +- .../CollisionShapes/btTriangleMeshShape.h | 27 +- .../CollisionShapes/btTriangleShape.h | 18 +- .../CollisionShapes/btUniformScalingShape.cpp | 114 + .../CollisionShapes/btUniformScalingShape.h | 88 + .../btContinuousConvexCollision.cpp | 41 +- .../btContinuousConvexCollision.h | 6 +- .../NarrowPhaseCollision/btConvexCast.h | 18 +- .../btConvexPenetrationDepthSolver.h | 4 +- .../btDiscreteCollisionDetectorInterface.h | 6 +- .../NarrowPhaseCollision/btGjkConvexCast.cpp | 166 +- .../NarrowPhaseCollision/btGjkConvexCast.h | 10 +- .../NarrowPhaseCollision/btGjkEpa.cpp | 10 +- .../NarrowPhaseCollision/btGjkEpa.h | 8 +- .../NarrowPhaseCollision/btGjkEpa2.cpp | 943 ++++ .../NarrowPhaseCollision/btGjkEpa2.h | 71 + .../btGjkEpaPenetrationDepthSolver.cpp | 13 +- .../btGjkEpaPenetrationDepthSolver.h | 2 +- .../btGjkPairDetector.cpp | 11 +- .../NarrowPhaseCollision/btGjkPairDetector.h | 12 +- .../NarrowPhaseCollision/btManifoldPoint.h | 26 +- .../btMinkowskiPenetrationDepthSolver.cpp | 7 +- .../btMinkowskiPenetrationDepthSolver.h | 2 +- .../btPersistentManifold.cpp | 38 +- .../btPersistentManifold.h | 62 +- .../btRaycastCallback.cpp | 66 +- .../NarrowPhaseCollision/btRaycastCallback.h | 24 +- .../btSimplexSolverInterface.h | 4 +- .../btSubSimplexConvexCast.cpp | 82 +- .../btVoronoiSimplexSolver.cpp | 2 +- .../bullet2/src/BulletDynamics/CMakeLists.txt | 20 +- .../btConeTwistConstraint.cpp | 48 +- .../ConstraintSolver/btConeTwistConstraint.h | 3 + .../ConstraintSolver/btConstraintSolver.h | 13 +- .../ConstraintSolver/btContactConstraint.cpp | 32 +- .../ConstraintSolver/btContactConstraint.h | 4 +- .../ConstraintSolver/btContactSolverInfo.h | 56 +- .../btGeneric6DofConstraint.cpp | 821 ++-- .../btGeneric6DofConstraint.h | 463 +- .../ConstraintSolver/btHingeConstraint.cpp | 270 +- .../ConstraintSolver/btHingeConstraint.h | 97 +- .../ConstraintSolver/btJacobianEntry.h | 4 +- .../btPoint2PointConstraint.cpp | 15 +- .../btPoint2PointConstraint.h | 18 +- .../btSequentialImpulseConstraintSolver.cpp | 824 ++-- .../btSequentialImpulseConstraintSolver.h | 48 +- .../ConstraintSolver/btSliderConstraint.cpp | 415 ++ .../ConstraintSolver/btSliderConstraint.h | 218 + .../btSolve2LinearConstraint.h | 4 +- .../ConstraintSolver/btSolverBody.h | 64 +- .../ConstraintSolver/btSolverConstraint.h | 21 +- .../ConstraintSolver/btTypedConstraint.cpp | 15 +- .../ConstraintSolver/btTypedConstraint.h | 38 +- .../BulletDynamics/Dynamics/Bullet-C-API.cpp | 294 +- .../Dynamics/btContinuousDynamicsWorld.cpp | 193 + .../Dynamics/btContinuousDynamicsWorld.h | 46 + .../Dynamics/btDiscreteDynamicsWorld.cpp | 535 +- .../Dynamics/btDiscreteDynamicsWorld.h | 44 +- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 84 +- .../BulletDynamics/Dynamics/btRigidBody.cpp | 222 +- .../src/BulletDynamics/Dynamics/btRigidBody.h | 189 +- .../Dynamics/btSimpleDynamicsWorld.cpp | 52 +- .../Dynamics/btSimpleDynamicsWorld.h | 32 +- .../Vehicle/btRaycastVehicle.cpp | 72 +- .../BulletDynamics/Vehicle/btRaycastVehicle.h | 14 +- .../Vehicle/btVehicleRaycaster.h | 2 +- .../src/BulletDynamics/Vehicle/btWheelInfo.h | 4 +- .../bullet2/src/BulletSoftBody/CMakeLists.txt | 21 + .../bullet2/src/BulletSoftBody/btSoftBody.cpp | 2594 ++++++++++ .../bullet2/src/BulletSoftBody/btSoftBody.h | 813 ++++ .../btSoftBodyConcaveCollisionAlgorithm.cpp | 410 ++ .../btSoftBodyConcaveCollisionAlgorithm.h | 118 + .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 653 +++ .../src/BulletSoftBody/btSoftBodyHelpers.h | 107 + .../src/BulletSoftBody/btSoftBodyInternals.h | 896 ++++ ...oftBodyRigidBodyCollisionConfiguration.cpp | 108 + ...tSoftBodyRigidBodyCollisionConfiguration.h | 48 + .../btSoftRigidCollisionAlgorithm.cpp | 79 + .../btSoftRigidCollisionAlgorithm.h | 75 + .../btSoftRigidDynamicsWorld.cpp | 126 + .../BulletSoftBody/btSoftRigidDynamicsWorld.h | 73 + .../btSoftSoftCollisionAlgorithm.cpp | 46 + .../btSoftSoftCollisionAlgorithm.h | 69 + .../bullet2/src/BulletSoftBody/btSparseSDF.h | 306 ++ extern/bullet2/src/CMakeLists.txt | 2 +- extern/bullet2/src/LinearMath/CMakeLists.txt | 29 +- extern/bullet2/src/LinearMath/btAabbUtil2.h | 83 +- .../src/LinearMath/btAlignedAllocator.cpp | 185 +- .../src/LinearMath/btAlignedAllocator.h | 28 +- .../src/LinearMath/btAlignedObjectArray.h | 69 +- .../bullet2/src/LinearMath/btConvexHull.cpp | 1153 +++++ extern/bullet2/src/LinearMath/btConvexHull.h | 242 + .../src/LinearMath/btDefaultMotionState.h | 2 +- .../bullet2/src/LinearMath/btGeometryUtil.cpp | 9 +- .../bullet2/src/LinearMath/btGeometryUtil.h | 1 + extern/bullet2/src/LinearMath/btHashMap.h | 303 ++ extern/bullet2/src/LinearMath/btIDebugDraw.h | 16 + extern/bullet2/src/LinearMath/btMatrix3x3.h | 96 +- extern/bullet2/src/LinearMath/btMinMax.h | 12 +- extern/bullet2/src/LinearMath/btMotionState.h | 2 +- .../bullet2/src/LinearMath/btPoolAllocator.h | 97 + extern/bullet2/src/LinearMath/btQuadWord.h | 71 +- extern/bullet2/src/LinearMath/btQuaternion.h | 10 +- extern/bullet2/src/LinearMath/btQuickprof.cpp | 302 +- extern/bullet2/src/LinearMath/btQuickprof.h | 822 +--- extern/bullet2/src/LinearMath/btScalar.h | 268 +- extern/bullet2/src/LinearMath/btStackAlloc.h | 19 +- extern/bullet2/src/LinearMath/btTransform.h | 19 +- .../bullet2/src/LinearMath/btTransformUtil.h | 12 +- extern/bullet2/src/LinearMath/btVector3.h | 51 + extern/bullet2/src/Makefile | 6 +- extern/bullet2/src/SConscript | 78 +- extern/bullet2/src/btBulletCollisionCommon.h | 11 +- extern/bullet2/src/btBulletDynamicsCommon.h | 6 +- extern/glew/SConscript | 2 +- extern/glew/include/GL/glew.h | 7 +- extern/glew/src/glew.c | 2 + intern/SoundSystem/SoundDefines.h | 2 +- .../SoundSystem/openal/SND_OpenALDevice.cpp | 4 + intern/ghost/GHOST_ISystem.h | 4 +- intern/ghost/GHOST_Types.h | 10 + intern/ghost/intern/GHOST_SystemCarbon.cpp | 3 +- intern/ghost/intern/GHOST_SystemCarbon.h | 4 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 8 +- intern/ghost/intern/GHOST_SystemWin32.h | 3 +- intern/ghost/intern/GHOST_SystemX11.cpp | 60 +- intern/ghost/intern/GHOST_SystemX11.h | 28 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 8 +- intern/ghost/intern/GHOST_WindowX11.cpp | 464 +- intern/ghost/intern/GHOST_WindowX11.h | 23 + intern/guardedalloc/MEM_guardedalloc.h | 10 +- intern/guardedalloc/intern/mallocn.c | 21 +- intern/iksolver/CMakeLists.txt | 2 +- intern/iksolver/SConscript | 3 +- intern/memutil/MEM_Allocator.h | 1 + intern/memutil/MEM_CacheLimiter.h | 12 +- .../memutil/intern/MEM_CacheLimiterC-Api.cpp | 8 +- intern/moto/include/GEN_Map.h | 13 + intern/moto/include/MT_Matrix4x4.h | 1 + intern/moto/include/MT_Matrix4x4.inl | 14 +- intern/opennl/superlu/BLO_sys_types.h | 2 + .../blender/BPY_python/BPY_python.vcproj | 8 +- projectfiles_vc7/blender/blender.sln | 22 + projectfiles_vc7/blender/blender.vcproj | 10 +- .../blender/blenkernel/BKE_blenkernel.vcproj | 20 +- projectfiles_vc7/blender/gpu/BL_gpu.vcproj | 372 ++ projectfiles_vc7/blender/nodes/nodes.vcproj | 8 +- .../blender/radiosity/BRA_radiosity.vcproj | 4 +- projectfiles_vc7/blender/src/BL_src.vcproj | 10 +- .../blenderhook/KX_blenderhook.vcproj | 4 +- .../gameengine/converter/KX_converter.vcproj | 12 +- .../expression/EXP_expressions.vcproj | 12 +- .../gameengine/gamelogic/SCA_GameLogic.vcproj | 12 +- .../gameplayer/ghost/GP_ghost.vcproj | 4 +- .../gameengine/ketsji/KX_ketsji.vcproj | 18 +- .../PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj | 10 +- .../RAS_openglrasterizer.vcproj | 12 +- release/datafiles/blenderbuttons | Bin 69599 -> 68242 bytes release/scripts/bpymodules/BPyTextPlugin.py | 814 ++++ release/scripts/export_obj.py | 14 +- release/scripts/import_obj.py | 6 +- release/scripts/mesh_cleanup.py | 32 +- release/scripts/object_find.py | 26 +- release/scripts/scripttemplate_gamelogic.py | 93 + .../scripts/scripttemplate_gamelogic_basic.py | 33 + release/scripts/scripttemplate_text_plugin.py | 69 + release/scripts/sysinfo.py | 2 + release/scripts/textplugin_functiondocs.py | 64 + release/scripts/textplugin_imports.py | 91 + release/scripts/textplugin_membersuggest.py | 90 + release/scripts/textplugin_outliner.py | 142 + release/scripts/textplugin_suggest.py | 94 + release/scripts/textplugin_templates.py | 123 + source/Makefile | 9 +- source/blender/CMakeLists.txt | 2 +- source/blender/Makefile | 2 +- source/blender/SConscript | 1 + source/blender/blenkernel/BKE_DerivedMesh.h | 49 +- source/blender/blenkernel/BKE_action.h | 6 +- .../blender/blenkernel/BKE_bad_level_calls.h | 6 +- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_colortools.h | 1 + source/blender/blenkernel/BKE_global.h | 9 +- source/blender/blenkernel/BKE_mesh.h | 1 - source/blender/blenkernel/BKE_node.h | 8 + source/blender/blenkernel/BKE_particle.h | 2 + source/blender/blenkernel/BKE_suggestions.h | 93 + source/blender/blenkernel/BKE_text.h | 29 +- source/blender/blenkernel/BKE_texture.h | 1 + source/blender/blenkernel/BKE_utildefines.h | 2 + source/blender/blenkernel/CMakeLists.txt | 2 +- source/blender/blenkernel/SConscript | 4 +- .../blenkernel/bad_level_call_stubs/stubs.c | 34 +- .../blender/blenkernel/intern/DerivedMesh.c | 407 +- source/blender/blenkernel/intern/Makefile | 4 + source/blender/blenkernel/intern/action.c | 59 +- source/blender/blenkernel/intern/anim.c | 21 +- source/blender/blenkernel/intern/armature.c | 21 +- source/blender/blenkernel/intern/blender.c | 36 +- .../blender/blenkernel/intern/cdderivedmesh.c | 138 +- source/blender/blenkernel/intern/colortools.c | 21 + source/blender/blenkernel/intern/constraint.c | 116 +- source/blender/blenkernel/intern/depsgraph.c | 20 +- source/blender/blenkernel/intern/effect.c | 15 +- source/blender/blenkernel/intern/exotic.c | 14 +- source/blender/blenkernel/intern/group.c | 13 + source/blender/blenkernel/intern/image.c | 11 +- source/blender/blenkernel/intern/ipo.c | 27 +- source/blender/blenkernel/intern/material.c | 7 + source/blender/blenkernel/intern/mesh.c | 39 - source/blender/blenkernel/intern/modifier.c | 14 +- source/blender/blenkernel/intern/node.c | 114 + source/blender/blenkernel/intern/object.c | 15 +- source/blender/blenkernel/intern/particle.c | 122 +- .../blenkernel/intern/particle_system.c | 682 ++- source/blender/blenkernel/intern/scene.c | 6 +- source/blender/blenkernel/intern/shrinkwrap.c | 14 +- source/blender/blenkernel/intern/softbody.c | 76 +- .../blender/blenkernel/intern/subsurf_ccg.c | 179 +- .../blender/blenkernel/intern/suggestions.c | 254 + source/blender/blenkernel/intern/text.c | 564 ++- source/blender/blenkernel/intern/texture.c | 12 + source/blender/blenlib/BLI_arithb.h | 2 + source/blender/blenlib/BLI_blenlib.h | 2 +- source/blender/blenlib/BLI_kdopbvh.h | 3 +- source/blender/blenlib/SConscript | 2 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 36 +- source/blender/blenlib/intern/arithb.c | 30 + source/blender/blenlib/intern/util.c | 43 + source/blender/blenloader/BLO_readfile.h | 2 +- source/blender/blenloader/BLO_sys_types.h | 14 +- source/blender/blenloader/intern/readfile.c | 66 +- source/blender/blenloader/intern/writefile.c | 14 +- source/blender/gpu/CMakeLists.txt | 34 + source/blender/gpu/GPU_draw.h | 116 + source/blender/gpu/GPU_extensions.h | 144 + source/blender/gpu/GPU_material.h | 169 + source/blender/gpu/Makefile | 37 + source/blender/gpu/SConscript | 11 + source/blender/gpu/intern/Makefile | 53 + source/blender/gpu/intern/gpu_codegen.c | 1441 ++++++ source/blender/gpu/intern/gpu_codegen.h | 87 + source/blender/gpu/intern/gpu_draw.c | 1168 +++++ source/blender/gpu/intern/gpu_extensions.c | 984 ++++ source/blender/gpu/intern/gpu_material.c | 1496 ++++++ .../gpu/intern/gpu_shader_material.glsl | 1555 ++++++ .../gpu/intern/gpu_shader_material.glsl.c | 1032 ++++ .../blender/gpu/intern/gpu_shader_vertex.glsl | 12 + .../gpu/intern/gpu_shader_vertex.glsl.c | 13 + source/blender/imbuf/intern/bmp.c | 4 +- .../blender/imbuf/intern/dds/ColorBlock.cpp | 37 +- source/blender/imbuf/intern/dds/ColorBlock.h | 2 + .../imbuf/intern/dds/DirectDrawSurface.cpp | 307 +- .../imbuf/intern/dds/DirectDrawSurface.h | 4 + source/blender/imbuf/intern/dds/dds_api.cpp | 1 + source/blender/include/BDR_drawmesh.h | 43 +- source/blender/include/BDR_drawobject.h | 3 +- source/blender/include/BDR_gpencil.h | 3 + source/blender/include/BDR_imagepaint.h | 4 +- source/blender/include/BIF_drawseq.h | 2 + source/blender/include/BIF_drawtext.h | 6 +- source/blender/include/BIF_editaction.h | 2 +- source/blender/include/BIF_editarmature.h | 4 +- source/blender/include/BIF_editview.h | 1 + source/blender/include/BIF_gl.h | 15 +- source/blender/include/BIF_glutil.h | 1 + source/blender/include/BIF_keyframing.h | 99 + source/blender/include/BIF_keyval.h | 3 + source/blender/include/BIF_meshlaplacian.h | 2 +- source/blender/include/BIF_meshtools.h | 2 + source/blender/include/BIF_resources.h | 10 +- source/blender/include/BIF_space.h | 4 + source/blender/include/BSE_drawipo.h | 3 + source/blender/include/BSE_drawview.h | 6 +- source/blender/include/BSE_editipo.h | 13 +- source/blender/include/blendef.h | 8 + source/blender/include/transform.h | 2 +- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/makesdna/DNA_actuator_types.h | 14 +- source/blender/makesdna/DNA_brush_types.h | 4 +- source/blender/makesdna/DNA_curve_types.h | 41 - source/blender/makesdna/DNA_gpencil_types.h | 2 +- source/blender/makesdna/DNA_group_types.h | 2 +- source/blender/makesdna/DNA_image_types.h | 4 +- source/blender/makesdna/DNA_ipo_types.h | 149 +- source/blender/makesdna/DNA_lamp_types.h | 16 +- source/blender/makesdna/DNA_material_types.h | 11 +- source/blender/makesdna/DNA_meshdata_types.h | 1 + source/blender/makesdna/DNA_object_types.h | 19 +- source/blender/makesdna/DNA_particle_types.h | 1 + source/blender/makesdna/DNA_scene_types.h | 3 +- source/blender/makesdna/DNA_sensor_types.h | 9 +- source/blender/makesdna/DNA_space_types.h | 14 +- source/blender/makesdna/DNA_text_types.h | 25 +- source/blender/makesdna/DNA_texture_types.h | 1 + source/blender/makesdna/DNA_userdef_types.h | 5 +- source/blender/makesdna/DNA_view3d_types.h | 3 +- source/blender/makesdna/DNA_world_types.h | 4 +- source/blender/nodes/CMakeLists.txt | 2 +- source/blender/nodes/SConscript | 1 + .../nodes/intern/CMP_nodes/CMP_tonemap.c | 9 +- .../blender/nodes/intern/CMP_nodes/Makefile | 1 + source/blender/nodes/intern/Makefile | 2 + .../blender/nodes/intern/SHD_nodes/Makefile | 2 + .../nodes/intern/SHD_nodes/SHD_camera.c | 10 +- .../nodes/intern/SHD_nodes/SHD_curves.c | 24 +- .../blender/nodes/intern/SHD_nodes/SHD_geom.c | 16 +- .../nodes/intern/SHD_nodes/SHD_hueSatVal.c | 9 +- .../nodes/intern/SHD_nodes/SHD_invert.c | 8 +- .../nodes/intern/SHD_nodes/SHD_mapping.c | 17 +- .../nodes/intern/SHD_nodes/SHD_material.c | 79 +- .../blender/nodes/intern/SHD_nodes/SHD_math.c | 43 +- .../nodes/intern/SHD_nodes/SHD_mixRgb.c | 14 +- .../nodes/intern/SHD_nodes/SHD_normal.c | 11 +- .../nodes/intern/SHD_nodes/SHD_output.c | 16 +- .../blender/nodes/intern/SHD_nodes/SHD_rgb.c | 11 +- .../nodes/intern/SHD_nodes/SHD_sepcombRGB.c | 16 +- .../nodes/intern/SHD_nodes/SHD_squeeze.c | 8 +- .../nodes/intern/SHD_nodes/SHD_texture.c | 17 +- .../nodes/intern/SHD_nodes/SHD_valToRgb.c | 20 +- .../nodes/intern/SHD_nodes/SHD_value.c | 9 +- .../nodes/intern/SHD_nodes/SHD_vectMath.c | 31 +- source/blender/nodes/intern/SHD_util.h | 2 + source/blender/python/BPY_extern.h | 7 +- source/blender/python/BPY_interface.c | 149 +- source/blender/python/BPY_menus.c | 40 +- source/blender/python/BPY_menus.h | 2 + source/blender/python/CMakeLists.txt | 6 +- source/blender/python/SConscript | 4 + source/blender/python/api2_2x/BGL.h | 9 +- source/blender/python/api2_2x/Blender.c | 22 +- source/blender/python/api2_2x/Camera.c | 1 + source/blender/python/api2_2x/Constraint.c | 3 +- source/blender/python/api2_2x/Draw.c | 110 +- source/blender/python/api2_2x/Group.c | 31 + source/blender/python/api2_2x/Image.c | 4 +- source/blender/python/api2_2x/Ipo.c | 1 + source/blender/python/api2_2x/Ipocurve.c | 1 + source/blender/python/api2_2x/Ipocurve.h | 2 +- source/blender/python/api2_2x/Lamp.c | 122 +- source/blender/python/api2_2x/MTex.c | 347 +- source/blender/python/api2_2x/MTex.h | 8 +- source/blender/python/api2_2x/Makefile | 6 + source/blender/python/api2_2x/Material.c | 296 +- source/blender/python/api2_2x/Mathutils.c | 2 +- source/blender/python/api2_2x/Mathutils.h | 2 +- source/blender/python/api2_2x/Mesh.c | 5 +- source/blender/python/api2_2x/Modifier.c | 53 +- source/blender/python/api2_2x/Object.c | 9 +- source/blender/python/api2_2x/Particle.c | 14 +- source/blender/python/api2_2x/Pose.c | 1 + source/blender/python/api2_2x/Text.c | 409 +- source/blender/python/api2_2x/Text.h | 2 + source/blender/python/api2_2x/Texture.c | 9 +- source/blender/python/api2_2x/Window.c | 13 +- source/blender/python/api2_2x/World.c | 103 + source/blender/python/api2_2x/bpy_data.c | 15 +- source/blender/python/api2_2x/doc/Draw.py | 8 +- source/blender/python/api2_2x/doc/Group.py | 2 + source/blender/python/api2_2x/doc/Lamp.py | 2 + source/blender/python/api2_2x/doc/Material.py | 62 +- source/blender/python/api2_2x/doc/Mesh.py | 3 +- source/blender/python/api2_2x/doc/Modifier.py | 5 + source/blender/python/api2_2x/doc/Text.py | 103 +- source/blender/python/api2_2x/doc/Texture.py | 151 +- source/blender/python/api2_2x/doc/World.py | 2 + source/blender/python/api2_2x/gen_utils.h | 1 + source/blender/python/api2_2x/sceneRender.c | 17 +- source/blender/python/api2_2x/sceneSequence.c | 115 +- source/blender/radiosity/CMakeLists.txt | 2 +- source/blender/radiosity/SConscript | 2 +- .../blender/radiosity/intern/source/Makefile | 1 + .../readblenfile/intern/BLO_readblenfile.c | 2 +- .../render/intern/include/render_types.h | 3 +- .../render/intern/source/convertblender.c | 20 +- .../render/intern/source/imagetexture.c | 8 +- .../blender/render/intern/source/pipeline.c | 27 +- .../blender/render/intern/source/rayshade.c | 5 +- .../blender/render/intern/source/rendercore.c | 30 +- .../render/intern/source/renderdatabase.c | 14 +- source/blender/render/intern/source/shadbuf.c | 4 +- .../render/intern/source/shadeoutput.c | 16 +- source/blender/render/intern/source/zbuf.c | 92 +- source/blender/src/CMakeLists.txt | 2 +- source/blender/src/Makefile | 1 + source/blender/src/SConscript | 11 +- source/blender/src/blenderbuttons.c | 4310 ++++++++--------- source/blender/src/buttons_editing.c | 25 +- source/blender/src/buttons_logic.c | 456 +- source/blender/src/buttons_object.c | 47 +- source/blender/src/buttons_scene.c | 8 +- source/blender/src/buttons_shading.c | 139 +- source/blender/src/drawaction.c | 13 + source/blender/src/drawarmature.c | 3 + source/blender/src/drawgpencil.c | 223 +- source/blender/src/drawimage.c | 56 +- source/blender/src/drawipo.c | 11 +- source/blender/src/drawmesh.c | 771 +-- source/blender/src/drawobject.c | 403 +- source/blender/src/drawseq.c | 17 +- source/blender/src/drawtext.c | 2783 ++++++++--- source/blender/src/drawview.c | 510 +- source/blender/src/editaction.c | 7 +- source/blender/src/editarmature.c | 103 + source/blender/src/editdeform.c | 2 +- source/blender/src/editface.c | 7 +- source/blender/src/editipo.c | 1475 +----- source/blender/src/editipo_lib.c | 10 +- source/blender/src/editipo_mods.c | 1 - source/blender/src/editkey.c | 5 +- source/blender/src/editlattice.c | 2 +- source/blender/src/editmesh.c | 4 + source/blender/src/editmesh_add.c | 152 +- source/blender/src/editmesh_lib.c | 4 + source/blender/src/editmesh_loop.c | 11 +- source/blender/src/editmesh_mods.c | 17 +- source/blender/src/editmesh_tools.c | 399 +- source/blender/src/editmode_undo.c | 40 +- source/blender/src/editnode.c | 6 +- source/blender/src/editobject.c | 35 +- source/blender/src/editscreen.c | 9 +- source/blender/src/editsound.c | 15 + source/blender/src/editview.c | 5 +- source/blender/src/filesel.c | 22 +- source/blender/src/glutil.c | 79 +- source/blender/src/gpencil.c | 595 ++- source/blender/src/header_image.c | 11 +- source/blender/src/header_info.c | 115 +- source/blender/src/header_ipo.c | 2 +- source/blender/src/header_node.c | 6 +- source/blender/src/header_text.c | 215 +- source/blender/src/header_view3d.c | 70 +- source/blender/src/headerbuttons.c | 7 +- source/blender/src/imagepaint.c | 309 +- source/blender/src/keyframing.c | 1839 +++++++ source/blender/src/keyval.c | 195 + source/blender/src/meshlaplacian.c | 10 +- source/blender/src/meshtools.c | 5 +- source/blender/src/mywindow.c | 12 - source/blender/src/outliner.c | 3 +- source/blender/src/playanim.c | 20 +- source/blender/src/poselib.c | 2 +- source/blender/src/poseobject.c | 2 + source/blender/src/previewrender.c | 32 + source/blender/src/renderwin.c | 32 +- source/blender/src/resources.c | 2 + source/blender/src/sculptmode.c | 7 +- source/blender/src/seqaudio.c | 20 +- source/blender/src/sequence.c | 13 +- source/blender/src/space.c | 101 +- source/blender/src/toets.c | 9 +- source/blender/src/toolbox.c | 14 +- source/blender/src/transform_conversions.c | 138 +- source/blender/src/transform_generics.c | 47 +- source/blender/src/transform_numinput.c | 14 + source/blender/src/transform_orientations.c | 2 +- source/blender/src/transform_snap.c | 2 +- source/blender/src/usiblender.c | 52 +- source/blender/src/verse_image.c | 4 +- source/blender/src/view.c | 135 +- source/blender/yafray/intern/export_File.cpp | 2 +- .../blender/yafray/intern/export_Plugin.cpp | 2 +- source/creator/CMakeLists.txt | 7 +- source/creator/Makefile | 2 + source/creator/SConscript | 2 +- source/creator/creator.c | 79 +- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 41 +- .../gameengine/BlenderRoutines/CMakeLists.txt | 1 + .../BlenderRoutines/KX_BlenderGL.cpp | 75 - .../gameengine/BlenderRoutines/KX_BlenderGL.h | 3 - .../BlenderRoutines/KX_BlenderRenderTools.cpp | 280 +- .../BlenderRoutines/KX_BlenderRenderTools.h | 71 +- source/gameengine/BlenderRoutines/Makefile | 5 +- source/gameengine/BlenderRoutines/SConscript | 5 +- .../Converter/BL_ActionActuator.cpp | 9 +- .../Converter/BL_ArmatureObject.cpp | 91 +- .../gameengine/Converter/BL_ArmatureObject.h | 10 +- .../Converter/BL_BlenderDataConversion.cpp | 205 +- .../Converter/BL_DeformableGameObject.cpp | 8 +- .../gameengine/Converter/BL_MeshDeformer.cpp | 89 +- source/gameengine/Converter/BL_MeshDeformer.h | 3 +- .../Converter/BL_ShapeActionActuator.cpp | 4 +- .../gameengine/Converter/BL_ShapeDeformer.cpp | 7 +- .../gameengine/Converter/BL_ShapeDeformer.h | 11 - .../gameengine/Converter/BL_SkinDeformer.cpp | 49 +- source/gameengine/Converter/BL_SkinDeformer.h | 16 +- .../Converter/BL_SkinMeshObject.cpp | 74 +- .../gameengine/Converter/BL_SkinMeshObject.h | 45 +- source/gameengine/Converter/CMakeLists.txt | 1 + .../Converter/KX_BlenderSceneConverter.cpp | 72 +- .../Converter/KX_BlenderSceneConverter.h | 2 + .../Converter/KX_ConvertActuators.cpp | 132 +- .../Converter/KX_ConvertSensors.cpp | 24 +- .../gameengine/Converter/KX_ConvertSensors.h | 1 + source/gameengine/Converter/Makefile | 1 + source/gameengine/Converter/SConscript | 2 +- source/gameengine/Expressions/Makefile | 1 + .../gameengine/Expressions/PyObjectPlus.cpp | 4 +- source/gameengine/Expressions/PyObjectPlus.h | 39 + source/gameengine/Expressions/Value.cpp | 30 +- .../GameLogic/Joystick/SCA_Joystick.cpp | 203 +- .../GameLogic/Joystick/SCA_Joystick.h | 214 +- .../GameLogic/Joystick/SCA_JoystickDefines.h | 8 +- .../GameLogic/Joystick/SCA_JoystickEvents.cpp | 56 +- .../GameLogic/Joystick/SCA_JoystickPrivate.h | 4 - source/gameengine/GameLogic/Makefile | 1 + .../GameLogic/SCA_2DFilterActuator.cpp | 8 +- .../gameengine/GameLogic/SCA_IController.cpp | 2 + .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 1 + source/gameengine/GameLogic/SCA_ISensor.cpp | 48 +- source/gameengine/GameLogic/SCA_ISensor.h | 13 +- .../GameLogic/SCA_JoystickManager.cpp | 35 +- .../GameLogic/SCA_JoystickManager.h | 4 +- .../GameLogic/SCA_JoystickSensor.cpp | 162 +- .../gameengine/GameLogic/SCA_JoystickSensor.h | 43 +- .../GameLogic/SCA_KeyboardSensor.cpp | 2 +- .../gameengine/GameLogic/SCA_LogicManager.cpp | 31 +- .../gameengine/GameLogic/SCA_LogicManager.h | 2 + .../GameLogic/SCA_PythonController.cpp | 13 +- .../GameLogic/SCA_PythonController.h | 6 + source/gameengine/GamePlayer/CMakeLists.txt | 4 + .../GamePlayer/common/CMakeLists.txt | 2 +- .../GamePlayer/common/GPC_RenderTools.cpp | 546 +-- .../GamePlayer/common/GPC_RenderTools.h | 156 +- source/gameengine/GamePlayer/common/Makefile | 5 +- .../gameengine/GamePlayer/common/SConscript | 2 +- .../common/unix/GPU_PolygonMaterial.h | 4 +- .../GamePlayer/ghost/CMakeLists.txt | 1 + .../GamePlayer/ghost/GPG_Application.cpp | 124 +- .../GamePlayer/ghost/GPG_Application.h | 32 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 122 +- source/gameengine/GamePlayer/ghost/Makefile | 6 +- source/gameengine/GamePlayer/ghost/SConscript | 4 +- source/gameengine/Ketsji/BL_BlenderShader.cpp | 124 +- source/gameengine/Ketsji/BL_BlenderShader.h | 10 +- source/gameengine/Ketsji/BL_Material.h | 6 +- source/gameengine/Ketsji/BL_Shader.cpp | 12 +- source/gameengine/Ketsji/BL_Shader.h | 2 +- source/gameengine/Ketsji/CMakeLists.txt | 1 + .../KXNetwork/KX_NetworkMessageSensor.cpp | 68 +- .../KXNetwork/KX_NetworkMessageSensor.h | 10 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 126 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 3 +- .../gameengine/Ketsji/KX_CameraActuator.cpp | 2 + .../Ketsji/KX_ConstraintActuator.cpp | 55 +- .../gameengine/Ketsji/KX_ConstraintActuator.h | 5 +- .../Ketsji/KX_ConstraintWrapper.cpp | 1 + .../Ketsji/KX_ConvertPhysicsObject.h | 1 + .../Ketsji/KX_ConvertPhysicsObjects.cpp | 165 +- source/gameengine/Ketsji/KX_GameActuator.cpp | 66 + source/gameengine/Ketsji/KX_GameActuator.h | 2 + source/gameengine/Ketsji/KX_GameObject.cpp | 358 +- source/gameengine/Ketsji/KX_GameObject.h | 109 +- .../gameengine/Ketsji/KX_IPO_SGController.cpp | 2 +- source/gameengine/Ketsji/KX_ISceneConverter.h | 4 + source/gameengine/Ketsji/KX_IpoActuator.cpp | 7 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 204 +- source/gameengine/Ketsji/KX_KetsjiEngine.h | 14 +- source/gameengine/Ketsji/KX_Light.cpp | 64 +- source/gameengine/Ketsji/KX_Light.h | 11 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 46 +- source/gameengine/Ketsji/KX_MeshProxy.h | 2 + .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 34 +- .../gameengine/Ketsji/KX_MouseFocusSensor.h | 16 +- .../gameengine/Ketsji/KX_ParentActuator.cpp | 2 + .../Ketsji/KX_PhysicsObjectWrapper.cpp | 2 + source/gameengine/Ketsji/KX_PolyProxy.cpp | 265 + source/gameengine/Ketsji/KX_PolyProxy.h | 71 + .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 50 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 2 - .../Ketsji/KX_PyConstraintBinding.cpp | 2 + source/gameengine/Ketsji/KX_PythonInit.cpp | 668 ++- source/gameengine/Ketsji/KX_PythonInit.h | 6 +- source/gameengine/Ketsji/KX_RayCast.cpp | 85 +- source/gameengine/Ketsji/KX_RayCast.h | 60 +- source/gameengine/Ketsji/KX_RaySensor.cpp | 58 +- source/gameengine/Ketsji/KX_RaySensor.h | 8 +- .../Ketsji/KX_SCA_AddObjectActuator.cpp | 122 +- .../Ketsji/KX_SCA_AddObjectActuator.h | 30 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.cpp | 41 +- .../Ketsji/KX_SCA_ReplaceMeshActuator.h | 2 +- .../KX_SG_BoneParentNodeRelationship.cpp | 2 +- source/gameengine/Ketsji/KX_Scene.cpp | 33 +- source/gameengine/Ketsji/KX_Scene.h | 10 +- source/gameengine/Ketsji/KX_SoundActuator.cpp | 64 +- .../gameengine/Ketsji/KX_TrackToActuator.cpp | 2 + .../gameengine/Ketsji/KX_VehicleWrapper.cpp | 2 + source/gameengine/Ketsji/KX_VertexProxy.cpp | 14 +- .../Ketsji/KX_VisibilityActuator.cpp | 10 +- .../gameengine/Ketsji/KX_VisibilityActuator.h | 2 + source/gameengine/Ketsji/Makefile | 11 +- source/gameengine/Ketsji/SConscript | 5 +- .../Physics/BlOde/OdePhysicsEnvironment.cpp | 5 +- .../Physics/BlOde/OdePhysicsEnvironment.h | 3 +- .../Physics/Bullet/CcdPhysicsController.cpp | 450 +- .../Physics/Bullet/CcdPhysicsController.h | 45 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 346 +- .../Physics/Bullet/CcdPhysicsEnvironment.h | 11 +- source/gameengine/Physics/Bullet/Makefile | 5 + .../Physics/Dummy/DummyPhysicsEnvironment.cpp | 3 +- .../Physics/Dummy/DummyPhysicsEnvironment.h | 3 +- .../Physics/Sumo/SumoPhysicsEnvironment.cpp | 31 +- .../Physics/Sumo/SumoPhysicsEnvironment.h | 3 +- .../Physics/common/PHY_IPhysicsEnvironment.h | 47 +- source/gameengine/PyDoc/GameKeys.py | 9 + source/gameengine/PyDoc/GameLogic.py | 9 +- source/gameengine/PyDoc/KX_GameObject.py | 90 +- source/gameengine/PyDoc/KX_MeshProxy.py | 15 + source/gameengine/PyDoc/KX_ObjectActuator.py | 4 +- source/gameengine/PyDoc/KX_PolyProxy.py | 100 + .../PyDoc/KX_SCA_AddObjectActuator.py | 17 + .../PyDoc/KX_SCA_ReplaceMeshActuator.py | 5 +- source/gameengine/PyDoc/KX_TrackToActuator.py | 2 +- source/gameengine/PyDoc/Rasterizer.py | 39 +- source/gameengine/PyDoc/SCA_DelaySensor.py | 2 +- source/gameengine/PyDoc/SCA_ISensor.py | 7 +- source/gameengine/Rasterizer/Makefile | 4 - .../Rasterizer/RAS_BucketManager.cpp | 264 +- .../gameengine/Rasterizer/RAS_BucketManager.h | 21 +- .../Rasterizer/RAS_FramingManager.h | 15 +- .../Rasterizer/RAS_IPolygonMaterial.cpp | 25 +- .../Rasterizer/RAS_IPolygonMaterial.h | 9 +- .../gameengine/Rasterizer/RAS_IRasterizer.h | 50 +- .../Rasterizer/RAS_IRenderTools.cpp | 24 +- .../gameengine/Rasterizer/RAS_IRenderTools.h | 39 +- .../Rasterizer/RAS_MaterialBucket.cpp | 609 ++- .../Rasterizer/RAS_MaterialBucket.h | 219 +- .../gameengine/Rasterizer/RAS_MeshObject.cpp | 993 ++-- source/gameengine/Rasterizer/RAS_MeshObject.h | 242 +- .../RAS_OpenGLRasterizer/CMakeLists.txt | 1 + .../Rasterizer/RAS_OpenGLRasterizer/Makefile | 5 +- .../RAS_ListRasterizer.cpp | 84 +- .../RAS_OpenGLRasterizer/RAS_ListRasterizer.h | 24 +- .../RAS_OpenGLRasterizer.cpp | 790 +-- .../RAS_OpenGLRasterizer.h | 49 +- .../RAS_VAOpenGLRasterizer.cpp | 234 +- .../RAS_VAOpenGLRasterizer.h | 18 +- .../RAS_OpenGLRasterizer/SConscript | 5 +- source/gameengine/Rasterizer/RAS_Polygon.cpp | 87 +- source/gameengine/Rasterizer/RAS_Polygon.h | 56 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 30 +- source/gameengine/Rasterizer/RAS_TexVert.h | 28 +- source/gameengine/Rasterizer/SConscript | 5 +- source/kernel/gen_system/GEN_Map.h | 13 + source/nan_definitions.mk | 11 +- tools/Blender.py | 38 +- tools/btools.py | 27 +- 777 files changed, 61444 insertions(+), 18725 deletions(-) create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp create mode 100644 extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMaterial.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp create mode 100644 extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp create mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletSoftBody/CMakeLists.txt create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBody.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBody.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletSoftBody/btSparseSDF.h create mode 100644 extern/bullet2/src/LinearMath/btConvexHull.cpp create mode 100644 extern/bullet2/src/LinearMath/btConvexHull.h create mode 100644 extern/bullet2/src/LinearMath/btHashMap.h create mode 100644 extern/bullet2/src/LinearMath/btPoolAllocator.h create mode 100644 projectfiles_vc7/blender/gpu/BL_gpu.vcproj create mode 100644 release/scripts/bpymodules/BPyTextPlugin.py create mode 100644 release/scripts/scripttemplate_gamelogic.py create mode 100644 release/scripts/scripttemplate_gamelogic_basic.py create mode 100644 release/scripts/scripttemplate_text_plugin.py create mode 100644 release/scripts/textplugin_functiondocs.py create mode 100644 release/scripts/textplugin_imports.py create mode 100644 release/scripts/textplugin_membersuggest.py create mode 100644 release/scripts/textplugin_outliner.py create mode 100644 release/scripts/textplugin_suggest.py create mode 100644 release/scripts/textplugin_templates.py create mode 100644 source/blender/blenkernel/BKE_suggestions.h create mode 100644 source/blender/blenkernel/intern/suggestions.c create mode 100644 source/blender/gpu/CMakeLists.txt create mode 100644 source/blender/gpu/GPU_draw.h create mode 100644 source/blender/gpu/GPU_extensions.h create mode 100644 source/blender/gpu/GPU_material.h create mode 100644 source/blender/gpu/Makefile create mode 100644 source/blender/gpu/SConscript create mode 100644 source/blender/gpu/intern/Makefile create mode 100644 source/blender/gpu/intern/gpu_codegen.c create mode 100644 source/blender/gpu/intern/gpu_codegen.h create mode 100644 source/blender/gpu/intern/gpu_draw.c create mode 100644 source/blender/gpu/intern/gpu_extensions.c create mode 100644 source/blender/gpu/intern/gpu_material.c create mode 100644 source/blender/gpu/intern/gpu_shader_material.glsl create mode 100644 source/blender/gpu/intern/gpu_shader_material.glsl.c create mode 100644 source/blender/gpu/intern/gpu_shader_vertex.glsl create mode 100644 source/blender/gpu/intern/gpu_shader_vertex.glsl.c create mode 100644 source/blender/include/BIF_keyframing.h create mode 100644 source/blender/src/keyframing.c create mode 100644 source/gameengine/Ketsji/KX_PolyProxy.cpp create mode 100644 source/gameengine/Ketsji/KX_PolyProxy.h create mode 100644 source/gameengine/PyDoc/KX_PolyProxy.py diff --git a/CMake/macros.cmake b/CMake/macros.cmake index 6b6837d25f0..95799a2c1fd 100644 --- a/CMake/macros.cmake +++ b/CMake/macros.cmake @@ -38,6 +38,10 @@ MACRO(BLENDERLIB ENDMACRO(BLENDERLIB) MACRO(SETUP_LIBDIRS) + # see "cmake --help-policy CMP0003" + if(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) + endif(COMMAND cmake_policy) LINK_DIRECTORIES(${PYTHON_LIBPATH} ${SDL_LIBPATH} ${JPEG_LIBPATH} ${PNG_LIBPATH} ${ZLIB_LIBPATH} ${ICONV_LIBPATH} ${OPENEXR_LIBPATH} ${QUICKTIME_LIBPATH} ${FFMPEG_LIBPATH}) IF(WITH_INTERNATIONAL) LINK_DIRECTORIES(${GETTEXT_LIBPATH}) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b86ca8f21e..4c1b863178f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,7 @@ OPTION(WITH_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) OPTION(WITH_FFMPEG "Enable FFMPeg Support (http://ffmpeg.mplayerhq.hu/)" OFF) OPTION(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) OPTION(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" OFF) +OPTION(WITH_WEBPLUGIN "Enable Web Plugin (Mozilla-Unix only)" OFF) IF(NOT WITH_GAMEENGINE AND WITH_PLAYER) MESSAGE("WARNING: WITH_PLAYER needs WITH_GAMEENGINE") @@ -248,7 +249,11 @@ IF(WIN32) SET(GETTEXT ${LIBDIR}/gettext) SET(GETTEXT_INC ${GETTEXT}/include) - SET(GETTEXT_LIB gnu_gettext) + IF(CMAKE_CL_64) + SET(GETTEXT_LIB gettextlib) + ELSE(CMAKE_CL_64) + SET(GETTEXT_LIB gnu_gettext) + ENDIF(CMAKE_CL_64) SET(GETTEXT_LIBPATH ${GETTEXT}/lib) SET(FREETYPE ${LIBDIR}/freetype) @@ -279,7 +284,12 @@ IF(WIN32) SET(FFMPEG_LIB avcodec-51 avformat-52 avdevice-52 avutil-49 swscale-0) SET(FFMPEG_LIBPATH ${FFMPEG}/lib) + IF(CMAKE_CL_64) + SET(LLIBS kernel32 user32 vfw32 winmm ws2_32 ) + ELSE(CMAKE_CL_64) SET(LLIBS kernel32 user32 gdi32 comdlg32 advapi32 shell32 ole32 oleaut32 uuid ws2_32 vfw32 winmm) + ENDIF(CMAKE_CL_64) + IF(WITH_OPENAL) SET(LLIBS ${LLIBS} dxguid) ENDIF(WITH_OPENAL) @@ -317,7 +327,7 @@ IF(WIN32) SET(WINTAB_INC ${LIBDIR}/wintab/include) IF(CMAKE_CL_64) - SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib;MSVCRT.lib ") + SET(PLATFORM_LINKFLAGS "/MACHINE:X64 /NODEFAULTLIB:libc.lib;MSVCRT.lib ") ELSE(CMAKE_CL_64) SET(PLATFORM_LINKFLAGS "/NODEFAULTLIB:libc.lib ") ENDIF(CMAKE_CL_64) @@ -447,6 +457,13 @@ SUBDIRS( # Blender Application SUBDIRS(source/creator) +#----------------------------------------------------------------------------- +# Blender WebPlugin +IF(WITH_WEBPLUGIN) + SET(MOZILLA_DIR "${CMAKE_SOURCE_DIR}/../gecko-sdk/" CACHE PATH "Gecko SDK path") + SET(WITH_PLAYER ON) +ENDIF(WITH_WEBPLUGIN) + #----------------------------------------------------------------------------- # Blender Player IF(WITH_PLAYER) diff --git a/SConstruct b/SConstruct index 4c3bbf8fad7..96b8c239c9c 100644 --- a/SConstruct +++ b/SConstruct @@ -241,6 +241,13 @@ if len(B.quickdebug) > 0 and printdebug != 0: for l in B.quickdebug: print "\t" + l +# remove stdc++ from LLIBS if we are building a statc linked CXXFLAGS +if env['WITH_BF_STATICCXX']: + if 'stdc++' in env['LLIBS']: + env['LLIBS'] = env['LLIBS'].replace('stdc++', ' ') + else: + print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform' + # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline if 'blenderplayer' in B.targets: env['WITH_BF_PLAYER'] = True @@ -248,6 +255,31 @@ if 'blenderplayer' in B.targets: if 'blendernogame' in B.targets: env['WITH_BF_GAMEENGINE'] = False +if 'blenderlite' in B.targets: + env['WITH_BF_GAMEENGINE'] = False + env['WITH_BF_OPENAL'] = False + env['WITH_BF_OPENEXR'] = False + env['WITH_BF_ICONV'] = False + env['WITH_BF_INTERNATIONAL'] = False + env['WITH_BF_OPENJPEG'] = False + env['WITH_BF_FFMPEG'] = False + env['WITH_BF_QUICKTIME'] = False + env['WITH_BF_YAFRAY'] = False + env['WITH_BF_REDCODE'] = False + env['WITH_BF_FTGL'] = False + env['WITH_BF_DDS'] = False + env['WITH_BF_ZLIB'] = False + env['WITH_BF_SDL'] = False + env['WITH_BF_JPEG'] = False + env['WITH_BF_PNG'] = False + env['WITH_BF_ODE'] = False + env['WITH_BF_BULLET'] = False + env['WITH_BF_BINRELOC'] = False + env['BF_BUILDINFO'] = False + env['BF_NO_ELBEEM'] = True + + + # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep) B.root_build_dir = env['BF_BUILDDIR'] @@ -488,6 +520,10 @@ if not env['WITH_BF_GAMEENGINE']: blendernogame = env.Alias('blendernogame', B.program_list) Depends(blendernogame,installtarget) +if 'blenderlite' in B.targets: + blenderlite = env.Alias('blenderlite', B.program_list) + Depends(blenderlite,installtarget) + Depends(nsiscmd, allinstall) Default(B.program_list) diff --git a/blenderplayer/CMakeLists.txt b/blenderplayer/CMakeLists.txt index d90639562d2..9786b7e61b2 100644 --- a/blenderplayer/CMakeLists.txt +++ b/blenderplayer/CMakeLists.txt @@ -86,10 +86,12 @@ IF(UNIX) bf_oglrasterizer bf_expressions bf_scenegraph + bf_IK bf_moto bf_soundsystem bf_kernel bf_nodes + bf_gpu bf_imbuf bf_avi kx_network diff --git a/config/darwin-config.py b/config/darwin-config.py index 8fd6c3251ba..0eb275dcaf4 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -87,10 +87,18 @@ if MAC_PROC == 'powerpc': BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal' else : BF_OPENAL = LIBDIR + '/openal' - + +WITH_BF_STATICOPENAL = 'false' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'openal' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' + +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' WITH_BF_SDL = 'true' BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix) @@ -102,10 +110,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '${LCGDIR}/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' @@ -143,7 +154,6 @@ BF_FTGL_LIB = 'extern_ftgl' WITH_BF_GAMEENGINE='true' WITH_BF_PLAYER='true' -WITH_BF_GLEXT= '1' WITH_BF_ODE = 'false' BF_ODE = LIBDIR + '/ode' diff --git a/config/linux2-config.py b/config/linux2-config.py index fe4325361a8..cd7e6659af1 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -6,18 +6,28 @@ BF_VERSE_INCLUDE = "#extern/verse/dist" BF_PYTHON = '/usr' BF_PYTHON_VERSION = '2.5' +WITH_BF_STATICPYTHON = 'false' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] +BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = '/usr' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'openal' +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' + # some distros have a separate libalut # if you get linker complaints, you need to uncomment the line below # BF_OPENAL_LIB = 'openal alut' +# BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a ${BF_OPENAL}/lib/libalut.a' + +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' WITH_BF_SDL = 'true' BF_SDL = '/usr' #$(shell sdl-config --prefix) @@ -28,14 +38,17 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '/usr' # when compiling with your own openexr lib you might need to set... # BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include' BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' # BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' + WITH_BF_DDS = 'true' WITH_BF_JPEG = 'true' diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py index e6c4e8769b4..9d58512151b 100644 --- a/config/linuxcross-config.py +++ b/config/linuxcross-config.py @@ -14,10 +14,18 @@ BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'openal_static' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' + +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' WITH_BF_SDL = 'true' BF_SDL = LIBDIR + '/sdl' @@ -34,10 +42,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = LIBDIR + '/gcc/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = ' Half IlmImf Iex ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/openbsd3-config.py b/config/openbsd3-config.py index f7f254973af..5ef3d90f168 100644 --- a/config/openbsd3-config.py +++ b/config/openbsd3-config.py @@ -9,10 +9,12 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}/config' WITH_BF_OPENAL = 'false' +# WITH_BF_STATICOPENAL = 'false' #BF_OPENAL = LIBDIR + '/openal' #BF_OPENAL_INC = '${BF_OPENAL}/include' #BF_OPENAL_LIB = 'openal' #BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_SDL = 'true' BF_SDL = '/usr/local' #$(shell sdl-config --prefix) @@ -24,9 +26,12 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'false' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '/usr/local' BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/sunos5-config.py b/config/sunos5-config.py index b3ca0e267ff..bfb1513ca3f 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -9,10 +9,18 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_ BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = '/usr/local' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' BF_OPENAL_LIB = 'openal' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' + +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' WITH_BF_SDL = 'true' BF_SDL = '/usr/local' #$(shell sdl-config --prefix) @@ -24,10 +32,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '/usr/local' BF_OPENEXR_INC = ['${BF_OPENEXR}/include', '${BF_OPENEXR}/include/OpenEXR' ] BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index d9fd6ce8d4f..4ff93bf7078 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -12,10 +12,13 @@ BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'dxguid openal_static' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_FFMPEG = 'false' BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264' @@ -37,10 +40,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = LIBDIR + '/gcc/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = ' Half IlmImf Iex ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index 02e5dbb7f8f..063d1461def 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -19,10 +19,18 @@ BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL ' BF_OPENAL_LIB = 'dxguid openal_static' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' + +# TODO - are these useful on win32? +# BF_CXX = '/usr' +# WITH_BF_STATICCXX = 'false' +# BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' WITH_BF_ICONV = 'true' BF_ICONV = LIBDIR + '/iconv' @@ -45,10 +53,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = LIBDIR + '/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib_msvc' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt index c5495fdf92b..e28e811087f 100644 --- a/extern/bullet2/CMakeLists.txt +++ b/extern/bullet2/CMakeLists.txt @@ -35,6 +35,7 @@ FILE(GLOB SRC src/BulletDynamics/ConstraintSolver/*.cpp src/BulletDynamics/Vehicle/*.cpp src/BulletDynamics/Dynamics/*.cpp + src/BulletSoftBody/*.cpp ) ADD_DEFINITIONS(-D_LIB) diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile index e05d441a6be..d26289c8b01 100644 --- a/extern/bullet2/Makefile +++ b/extern/bullet2/Makefile @@ -40,7 +40,8 @@ BulletCollision/NarrowPhaseCollision \ BulletCollision//CollisionDispatch \ BulletDynamics/ConstraintSolver \ BulletDynamics/Vehicle \ -BulletDynamics/Dynamics +BulletDynamics/Dynamics \ +BulletSoftBody include nan_subdirs.mk diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 6de2fd3a2bd..be4f78102a4 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -58,9 +58,11 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\C IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Vehicle MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\LinearMath MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath +IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletSoftBody MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody XCOPY /Y ..\..\src\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include XCOPY /Y ..\..\src\LinearMath\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath +XCOPY /Y ..\..\src\BulletSoftBody\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody XCOPY /Y ..\..\src\BulletCollision\BroadphaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\BroadphaseCollision XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision @@ -394,12 +396,24 @@ ECHO Done + + + + + + + + @@ -410,6 +424,12 @@ ECHO Done + + + + @@ -482,18 +502,45 @@ ECHO Done + + + + + + + + + + + + + + + + + + @@ -534,6 +581,12 @@ ECHO Done + + + + @@ -589,6 +642,21 @@ ECHO Done + + + + + + + + + + @@ -628,6 +696,18 @@ ECHO Done + + + + + + + + @@ -731,6 +811,12 @@ ECHO Done + + + + @@ -761,12 +847,21 @@ ECHO Done + + + + + + @@ -785,6 +880,18 @@ ECHO Done + + + + + + + + @@ -827,6 +934,12 @@ ECHO Done + + + + @@ -842,6 +955,12 @@ ECHO Done + + + + + + + + @@ -868,6 +993,9 @@ ECHO Done + + @@ -886,6 +1014,9 @@ ECHO Done + + @@ -904,9 +1035,6 @@ ECHO Done - - @@ -920,6 +1048,58 @@ ECHO Done RelativePath="..\..\src\LinearMath\btVector3.h"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt index 4d1a4c11706..02430cb5c0e 100644 --- a/extern/bullet2/readme.txt +++ b/extern/bullet2/readme.txt @@ -1,3 +1,8 @@ +*** +Apply bullet_compound_raycast.patch if not already applied in Bullet source +This patch is needed to return correct raycast results on compound shape. +/ben + *** These files in extern/bullet2 are NOT part of the Blender build yet *** diff --git a/extern/bullet2/src/Bullet-C-Api.h b/extern/bullet2/src/Bullet-C-Api.h index 078dcae63bb..8074aed3038 100644 --- a/extern/bullet2/src/Bullet-C-Api.h +++ b/extern/bullet2/src/Bullet-C-Api.h @@ -23,15 +23,153 @@ subject to the following restrictions: #ifndef BULLET_C_API_H #define BULLET_C_API_H +#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name + +#ifdef BT_USE_DOUBLE_PRECISION +typedef double plReal; +#else +typedef float plReal; +#endif + +typedef plReal plVector3[3]; +typedef plReal plQuaternion[4]; + #ifdef __cplusplus extern "C" { #endif -double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); +/* Particular physics SDK */ + PL_DECLARE_HANDLE(plPhysicsSdkHandle); + +/* Dynamics world, belonging to some physics SDK */ + PL_DECLARE_HANDLE(plDynamicsWorldHandle); + +/* Rigid Body that can be part of a Dynamics World */ + PL_DECLARE_HANDLE(plRigidBodyHandle); + +/* Collision Shape/Geometry, property of a Rigid Body */ + PL_DECLARE_HANDLE(plCollisionShapeHandle); + +/* Constraint for Rigid Bodies */ + PL_DECLARE_HANDLE(plConstraintHandle); + +/* Triangle Mesh interface */ + PL_DECLARE_HANDLE(plMeshInterfaceHandle); + +/* Broadphase Scene/Proxy Handles */ + PL_DECLARE_HANDLE(plCollisionBroadphaseHandle); + PL_DECLARE_HANDLE(plBroadphaseProxyHandle); + PL_DECLARE_HANDLE(plCollisionWorldHandle); + +/* + Create and Delete a Physics SDK +*/ + + extern plPhysicsSdkHandle plNewBulletSdk(); //this could be also another sdk, like ODE, PhysX etc. + extern void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk); + +/* Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */ + + typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2); + + extern plCollisionBroadphaseHandle plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback); + + extern void plDestroyBroadphase(plCollisionBroadphaseHandle bp); + + extern plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + + extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle); + + extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ); + +/* todo: add pair cache support with queries like add/remove/find pair */ + + extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk); + +/* todo: add/remove objects */ + + +/* Dynamics World */ + + extern plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk); + + extern void plDeleteDynamicsWorld(plDynamicsWorldHandle world); + + extern void plStepSimulation(plDynamicsWorldHandle, plReal timeStep); + + extern void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + extern void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object); + + +/* Rigid Body */ + + extern plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ); + + extern void plDeleteRigidBody(plRigidBodyHandle body); + + +/* Collision Shape definition */ + + extern plCollisionShapeHandle plNewSphereShape(plReal radius); + extern plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z); + extern plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewConeShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height); + extern plCollisionShapeHandle plNewCompoundShape(); + extern void plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn); + + extern void plDeleteShape(plCollisionShapeHandle shape); + + /* Convex Meshes */ + extern plCollisionShapeHandle plNewConvexHullShape(); + extern void plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z); +/* Concave static triangle meshes */ + extern plMeshInterfaceHandle plNewMeshInterface(); + extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); + extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + extern void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling); + +/* SOLID has Response Callback/Table/Management */ +/* PhysX has Triggers, User Callbacks and filtering */ +/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */ + +/* typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle rbHandle, plVector3 pos); */ +/* typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle rbHandle, plQuaternion orientation); */ + + /* get world transform */ + extern void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix); + extern void plGetPosition(plRigidBodyHandle object,plVector3 position); + extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation); + + /* set world transform (position/orientation) */ + extern void plSetPosition(plRigidBodyHandle object, const plVector3 position); + extern void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation); + extern void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient); + + typedef struct plRayCastResult { + plRigidBodyHandle m_body; + plCollisionShapeHandle m_shape; + plVector3 m_positionWorld; + plVector3 m_normalWorld; + } plRayCastResult; + + extern int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res); + + /* Sweep API */ + + /* extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */ + + /* Continuous Collision Detection API */ + + // needed for source/blender/blenkernel/intern/collision.c + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]); #ifdef __cplusplus } #endif + #endif //BULLET_C_API_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp index be4a11506df..d7eea33ea41 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp @@ -21,640 +21,18 @@ #include -#ifdef DEBUG_BROADPHASE -#include -void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache) { - int numEdges = m_pHandles[0].m_maxEdges[axis]; - printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); - - int i; - for (i=0;im_handle); - int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; - char beginOrEnd; - beginOrEnd=pEdge->IsMax()?'E':'B'; - printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); - } - - if (checkCardinality) - assert(numEdges == m_numHandles*2+1); -} -#endif //DEBUG_BROADPHASE - - -btBroadphaseProxy* btAxisSweep3::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) -{ - (void)shapeType; - BP_FP_INT_TYPE handleId = addHandle(min,max, userPtr,collisionFilterGroup,collisionFilterMask); - - Handle* handle = getHandle(handleId); - - return handle; -} - -void btAxisSweep3::destroyProxy(btBroadphaseProxy* proxy) -{ - Handle* handle = static_cast(proxy); - removeHandle(handle->m_handleId); -} - -void btAxisSweep3::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax) -{ - Handle* handle = static_cast(proxy); - updateHandle(handle->m_handleId,aabbMin,aabbMax); - -} - - - - - - -btAxisSweep3::btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles) -:btOverlappingPairCache() -{ - m_invalidPair = 0; - //assert(bounds.HasVolume()); - // 1 handle is reserved as sentinel - btAssert(maxHandles > 1 && maxHandles < BP_MAX_HANDLES); - - // init bounds - m_worldAabbMin = worldAabbMin; - m_worldAabbMax = worldAabbMax; - - btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; - - BP_FP_INT_TYPE maxInt = BP_HANDLE_SENTINEL; - - m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; - - // allocate handles buffer and put all handles on free list - m_pHandles = new Handle[maxHandles]; - m_maxHandles = maxHandles; - m_numHandles = 0; - - // handle 0 is reserved as the null index, and is also used as the sentinel - m_firstFreeHandle = 1; - { - for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) - m_pHandles[i].SetNextFree(i + 1); - m_pHandles[maxHandles - 1].SetNextFree(0); - } - - { - // allocate edge buffers - for (int i = 0; i < 3; i++) - m_pEdges[i] = new Edge[maxHandles * 2]; - } - //removed overlap management - - // make boundary sentinels - - m_pHandles[0].m_clientObject = 0; - - for (int axis = 0; axis < 3; axis++) - { - m_pHandles[0].m_minEdges[axis] = 0; - m_pHandles[0].m_maxEdges[axis] = 1; - - m_pEdges[axis][0].m_pos = 0; - m_pEdges[axis][0].m_handle = 0; - m_pEdges[axis][1].m_pos = BP_HANDLE_SENTINEL; - m_pEdges[axis][1].m_handle = 0; -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - - } + btAssert(maxHandles > 1 && maxHandles < 32767); } -btAxisSweep3::~btAxisSweep3() + +bt32BitAxisSweep3::bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache ) +:btAxisSweep3Internal(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache) { - - for (int i = 2; i >= 0; i--) - delete[] m_pEdges[i]; - delete[] m_pHandles; -} - -void btAxisSweep3::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const -{ - btPoint3 clampedPoint(point); - - - - clampedPoint.setMax(m_worldAabbMin); - clampedPoint.setMin(m_worldAabbMax); - - btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; - out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & BP_HANDLE_MASK) | isMax); - out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & BP_HANDLE_MASK) | isMax); - out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & BP_HANDLE_MASK) | isMax); - -} - - - -BP_FP_INT_TYPE btAxisSweep3::allocHandle() -{ - assert(m_firstFreeHandle); - - BP_FP_INT_TYPE handle = m_firstFreeHandle; - m_firstFreeHandle = getHandle(handle)->GetNextFree(); - m_numHandles++; - - return handle; -} - -void btAxisSweep3::freeHandle(BP_FP_INT_TYPE handle) -{ - assert(handle > 0 && handle < m_maxHandles); - - getHandle(handle)->SetNextFree(m_firstFreeHandle); - m_firstFreeHandle = handle; - - m_numHandles--; -} - - - -BP_FP_INT_TYPE btAxisSweep3::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask) -{ - // quantize the bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // allocate a handle - BP_FP_INT_TYPE handle = allocHandle(); - assert(handle!= 0xcdcd); - - Handle* pHandle = getHandle(handle); - - pHandle->m_handleId = handle; - //pHandle->m_pOverlaps = 0; - pHandle->m_clientObject = pOwner; - pHandle->m_collisionFilterGroup = collisionFilterGroup; - pHandle->m_collisionFilterMask = collisionFilterMask; - - // compute current limit of edge arrays - BP_FP_INT_TYPE limit = m_numHandles * 2; - - - // insert new edges just inside the max boundary edge - for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) - { - - m_pHandles[0].m_maxEdges[axis] += 2; - - m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; - - m_pEdges[axis][limit - 1].m_pos = min[axis]; - m_pEdges[axis][limit - 1].m_handle = handle; - - m_pEdges[axis][limit].m_pos = max[axis]; - m_pEdges[axis][limit].m_handle = handle; - - pHandle->m_minEdges[axis] = limit - 1; - pHandle->m_maxEdges[axis] = limit; - } - - // now sort the new edges to their correct position - sortMinDown(0, pHandle->m_minEdges[0], false); - sortMaxDown(0, pHandle->m_maxEdges[0], false); - sortMinDown(1, pHandle->m_minEdges[1], false); - sortMaxDown(1, pHandle->m_maxEdges[1], false); - sortMinDown(2, pHandle->m_minEdges[2], true); - sortMaxDown(2, pHandle->m_maxEdges[2], true); - - - return handle; -} - - -void btAxisSweep3::removeHandle(BP_FP_INT_TYPE handle) -{ - - Handle* pHandle = getHandle(handle); - - //explicitly remove the pairs containing the proxy - //we could do it also in the sortMinUp (passing true) - //todo: compare performance - removeOverlappingPairsContainingProxy(pHandle); - - - // compute current limit of edge arrays - int limit = m_numHandles * 2; - - int axis; - - for (axis = 0;axis<3;axis++) - { - m_pHandles[0].m_maxEdges[axis] -= 2; - } - - // remove the edges by sorting them up to the end of the list - for ( axis = 0; axis < 3; axis++) - { - Edge* pEdges = m_pEdges[axis]; - BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; - pEdges[max].m_pos = BP_HANDLE_SENTINEL; - - sortMaxUp(axis,max,false); - - - BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; - pEdges[i].m_pos = BP_HANDLE_SENTINEL; - - - sortMinUp(axis,i,false); - - pEdges[limit-1].m_handle = 0; - pEdges[limit-1].m_pos = BP_HANDLE_SENTINEL; - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis,false); -#endif //DEBUG_BROADPHASE - - - } - - - // free the handle - freeHandle(handle); - - -} - -extern int gOverlappingPairs; - - -void btAxisSweep3::refreshOverlappingPairs() -{ - -} -void btAxisSweep3::processAllOverlappingPairs(btOverlapCallback* callback) -{ - - //perform a sort, to find duplicates and to sort 'invalid' pairs to the end - m_overlappingPairArray.heapSort(btBroadphasePairSortPredicate()); - - //remove the 'invalid' ones -#ifdef USE_POPBACK_REMOVAL - while (m_invalidPair>0) - { - m_invalidPair--; - m_overlappingPairArray.pop_back(); - } -#else - m_overlappingPairArray.resize(m_overlappingPairArray.size() - m_invalidPair); - m_invalidPair = 0; -#endif - - - int i; - - btBroadphasePair previousPair; - previousPair.m_pProxy0 = 0; - previousPair.m_pProxy1 = 0; - previousPair.m_algorithm = 0; - - - for (i=0;iprocessOverlap(pair); - } else - { - needsRemoval = true; - } - } else - { - //remove duplicate - needsRemoval = true; - //should have no algorithm - btAssert(!pair.m_algorithm); - } - - if (needsRemoval) - { - cleanOverlappingPair(pair); - - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); - pair.m_pProxy0 = 0; - pair.m_pProxy1 = 0; - m_invalidPair++; - gOverlappingPairs--; - } - - } -} - - -bool btAxisSweep3::testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - const Handle* pHandleA = static_cast(proxy0); - const Handle* pHandleB = static_cast(proxy1); - - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - return true; -} - -bool btAxisSweep3::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) -{ - //optimization 1: check the array index (memory address), instead of the m_pos - - for (int axis = 0; axis < 3; axis++) - { - if (axis != ignoreAxis) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } - } - - //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) - - /*for (int axis = 0; axis < 3; axis++) - { - if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || - m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) - { - return false; - } - } - */ - - return true; -} - -void btAxisSweep3::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax) -{ -// assert(bounds.IsFinite()); - //assert(bounds.HasVolume()); - - Handle* pHandle = getHandle(handle); - - // quantize the new bounds - BP_FP_INT_TYPE min[3], max[3]; - quantize(min, aabbMin, 0); - quantize(max, aabbMax, 1); - - // update changed edges - for (int axis = 0; axis < 3; axis++) - { - BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; - BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; - - int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; - int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; - - m_pEdges[axis][emin].m_pos = min[axis]; - m_pEdges[axis][emax].m_pos = max[axis]; - - // expand (only adds overlaps) - if (dmin < 0) - sortMinDown(axis, emin); - - if (dmax > 0) - sortMaxUp(axis, emax); - - // shrink (only removes overlaps) - if (dmin > 0) - sortMinUp(axis, emin); - - if (dmax < 0) - sortMaxDown(axis, emax); - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - } - - -} - - - - -// sorting a min edge downwards can only ever *add* overlaps -void btAxisSweep3::sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (pPrev->IsMax()) - { - // if previous edge is a maximum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) - { - addOverlappingPair(pHandleEdge,pHandlePrev); - - //AddOverlap(pEdge->m_handle, pPrev->m_handle); - - } - - // update edge reference in other handle - pHandlePrev->m_maxEdges[axis]++; - } - else - pHandlePrev->m_minEdges[axis]++; - - pHandleEdge->m_minEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a min edge upwards can only ever *remove* overlaps -void btAxisSweep3::sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (pNext->IsMax()) - { - // if next edge is maximum remove any overlap between the two handles - if (updateOverlaps) - { - /* - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - btBroadphasePair tmpPair(*handle0,*handle1); - removeOverlappingPair(tmpPair); - */ - - } - - // update edge reference in other handle - pHandleNext->m_maxEdges[axis]--; - } - else - pHandleNext->m_minEdges[axis]--; - - pHandleEdge->m_minEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - - -} - -// sorting a max edge downwards can only ever *remove* overlaps -void btAxisSweep3::sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pPrev = pEdge - 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pEdge->m_pos < pPrev->m_pos) - { - Handle* pHandlePrev = getHandle(pPrev->m_handle); - - if (!pPrev->IsMax()) - { - // if previous edge was a minimum remove any overlap between the two handles - if (updateOverlaps) - { - //this is done during the overlappingpairarray iteration/narrowphase collision - /* - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pPrev->m_handle); - btBroadphasePair* pair = findPair(handle0,handle1); - //assert(pair); - - if (pair) - { - removeOverlappingPair(*pair); - } - */ - - } - - // update edge reference in other handle - pHandlePrev->m_minEdges[axis]++;; - } - else - pHandlePrev->m_maxEdges[axis]++; - - pHandleEdge->m_maxEdges[axis]--; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pPrev; - *pPrev = swap; - - // decrement - pEdge--; - pPrev--; - } - - -#ifdef DEBUG_BROADPHASE - debugPrintAxis(axis); -#endif //DEBUG_BROADPHASE - -} - -// sorting a max edge upwards can only ever *add* overlaps -void btAxisSweep3::sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps) -{ - Edge* pEdge = m_pEdges[axis] + edge; - Edge* pNext = pEdge + 1; - Handle* pHandleEdge = getHandle(pEdge->m_handle); - - while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) - { - Handle* pHandleNext = getHandle(pNext->m_handle); - - if (!pNext->IsMax()) - { - // if next edge is a minimum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) - { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); - addOverlappingPair(handle0,handle1); - } - - // update edge reference in other handle - pHandleNext->m_minEdges[axis]--; - } - else - pHandleNext->m_maxEdges[axis]--; - - pHandleEdge->m_maxEdges[axis]++; - - // swap the edges - Edge swap = *pEdge; - *pEdge = *pNext; - *pNext = swap; - - // increment - pEdge++; - pNext++; - } - + // 1 handle is reserved as sentinel + btAssert(maxHandles > 1 && maxHandles < 2147483647); } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index 57bbb368672..d0ad09a385a 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -19,34 +19,26 @@ #ifndef AXIS_SWEEP_3_H #define AXIS_SWEEP_3_H -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btVector3.h" #include "btOverlappingPairCache.h" +#include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" - - -//Enable BP_USE_FIXEDPOINT_INT_32 if you need more then 32767 objects -//#define BP_USE_FIXEDPOINT_INT_32 1 - -#ifdef BP_USE_FIXEDPOINT_INT_32 - #define BP_FP_INT_TYPE unsigned int - #define BP_MAX_HANDLES 1500000 //arbitrary maximum number of handles - #define BP_HANDLE_SENTINEL 0x7fffffff - #define BP_HANDLE_MASK 0xfffffffe -#else - #define BP_FP_INT_TYPE unsigned short int - #define BP_MAX_HANDLES 32767 - #define BP_HANDLE_SENTINEL 0xffff - #define BP_HANDLE_MASK 0xfffe -#endif //BP_USE_FIXEDPOINT_INT_32 +#include "btOverlappingPairCallback.h" //#define DEBUG_BROADPHASE 1 +#define USE_OVERLAP_TEST_ON_REMOVES 1 -/// btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. -/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using integer coordinates instead of floats. -/// The testOverlap check is optimized to check the array index, rather then the actual AABB coordinates/pos -class btAxisSweep3 : public btOverlappingPairCache +/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. +/// It uses quantized integers to represent the begin and end points for each of the 3 axis. +/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead. +template +class btAxisSweep3Internal : public btBroadphaseInterface { +protected: + + BP_FP_INT_TYPE m_bpHandleMask; + BP_FP_INT_TYPE m_handleSentinel; public: @@ -57,47 +49,57 @@ public: BP_FP_INT_TYPE m_pos; // low bit is min/max BP_FP_INT_TYPE m_handle; - BP_FP_INT_TYPE IsMax() const {return m_pos & 1;} + BP_FP_INT_TYPE IsMax() const {return static_cast(m_pos & 1);} }; public: - class Handle : public btBroadphaseProxy + class Handle : public btBroadphaseProxy { public: - + BT_DECLARE_ALIGNED_ALLOCATOR(); + // indexes into the edge arrays BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12 - BP_FP_INT_TYPE m_handleId; +// BP_FP_INT_TYPE m_uniqueId; BP_FP_INT_TYPE m_pad; //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject - inline void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} - inline BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} + SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;} + SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];} }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry -private: +protected: btPoint3 m_worldAabbMin; // overall system bounds btPoint3 m_worldAabbMax; // overall system bounds btVector3 m_quantize; // scaling factor for quantization BP_FP_INT_TYPE m_numHandles; // number of active handles - int m_maxHandles; // max number of handles + BP_FP_INT_TYPE m_maxHandles; // max number of handles Handle* m_pHandles; // handles pool + BP_FP_INT_TYPE m_firstFreeHandle; // free handles list Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) + void* m_pEdgesRawPtr[3]; - int m_invalidPair; + btOverlappingPairCache* m_pairCache; + + ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. + btOverlappingPairCallback* m_userPairCallback; + + bool m_ownsPairCache; + + int m_invalidPair; // allocation/deallocation BP_FP_INT_TYPE allocHandle(); void freeHandle(BP_FP_INT_TYPE handle); - bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); + bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1); #ifdef DEBUG_BROADPHASE void debugPrintAxis(int axis,bool checkCardinality=true); @@ -108,29 +110,803 @@ private: void quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const; - void sortMinDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMinUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMaxDown(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); - void sortMaxUp(int axis, BP_FP_INT_TYPE edge, bool updateOverlaps = true); + void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); + void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps ); public: - btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, int maxHandles = 16384); - virtual ~btAxisSweep3(); - virtual void refreshOverlappingPairs(); + btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0); + + virtual ~btAxisSweep3Internal(); + + BP_FP_INT_TYPE getNumHandles() const + { + return m_numHandles; + } + + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask); - void removeHandle(BP_FP_INT_TYPE handle); - void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax); - inline Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} + BP_FP_INT_TYPE addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher); + void updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher); + SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;} void processAllOverlappingPairs(btOverlapCallback* callback); //Broadphase Interface - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); - virtual void destroyProxy(btBroadphaseProxy* proxy); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); - bool testOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback) + { + m_userPairCallback = pairCallback; + } + const btOverlappingPairCallback* getOverlappingPairUserCallback() const + { + return m_userPairCallback; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_worldAabbMin; + aabbMax = m_worldAabbMax; + } + + virtual void printStats() + { +/* printf("btAxisSweep3.h\n"); + printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(), + m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ()); + */ + + } + +}; + +//////////////////////////////////////////////////////////////////// + + + + +#ifdef DEBUG_BROADPHASE +#include + +template +void btAxisSweep3::debugPrintAxis(int axis, bool checkCardinality) +{ + int numEdges = m_pHandles[0].m_maxEdges[axis]; + printf("SAP Axis %d, numEdges=%d\n",axis,numEdges); + + int i; + for (i=0;im_handle); + int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis]; + char beginOrEnd; + beginOrEnd=pEdge->IsMax()?'E':'B'; + printf(" [%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex); + } + + if (checkCardinality) + assert(numEdges == m_numHandles*2+1); +} +#endif //DEBUG_BROADPHASE + +template +btBroadphaseProxy* btAxisSweep3Internal::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + (void)shapeType; + BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy); + + Handle* handle = getHandle(handleId); + + return handle; +} + + + +template +void btAxisSweep3Internal::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + removeHandle(static_cast(handle->m_uniqueId), dispatcher); +} + +template +void btAxisSweep3Internal::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher) +{ + Handle* handle = static_cast(proxy); + updateHandle(static_cast(handle->m_uniqueId), aabbMin, aabbMax,dispatcher); + +} + + + + + +template +btAxisSweep3Internal::btAxisSweep3Internal(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache ) +:m_bpHandleMask(handleMask), +m_handleSentinel(handleSentinel), +m_pairCache(pairCache), +m_userPairCallback(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + BP_FP_INT_TYPE maxHandles = static_cast(userMaxHandles+1);//need to add one sentinel handle + + if (!m_pairCache) + { + void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16); + m_pairCache = new(ptr) btHashedOverlappingPairCache(); + m_ownsPairCache = true; + } + + //assert(bounds.HasVolume()); + + // init bounds + m_worldAabbMin = worldAabbMin; + m_worldAabbMax = worldAabbMax; + + btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin; + + BP_FP_INT_TYPE maxInt = m_handleSentinel; + + m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; + + // allocate handles buffer, using btAlignedAlloc, and put all handles on free list + m_pHandles = new Handle[maxHandles]; + + m_maxHandles = maxHandles; + m_numHandles = 0; + + // handle 0 is reserved as the null index, and is also used as the sentinel + m_firstFreeHandle = 1; + { + for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++) + m_pHandles[i].SetNextFree(static_cast(i + 1)); + m_pHandles[maxHandles - 1].SetNextFree(0); + } + + { + // allocate edge buffers + for (int i = 0; i < 3; i++) + { + m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16); + m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2]; + } + } + //removed overlap management + + // make boundary sentinels + + m_pHandles[0].m_clientObject = 0; + + for (int axis = 0; axis < 3; axis++) + { + m_pHandles[0].m_minEdges[axis] = 0; + m_pHandles[0].m_maxEdges[axis] = 1; + + m_pEdges[axis][0].m_pos = 0; + m_pEdges[axis][0].m_handle = 0; + m_pEdges[axis][1].m_pos = m_handleSentinel; + m_pEdges[axis][1].m_handle = 0; +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + + } + +} + +template +btAxisSweep3Internal::~btAxisSweep3Internal() +{ + + for (int i = 2; i >= 0; i--) + { + btAlignedFree(m_pEdgesRawPtr[i]); + } + delete [] m_pHandles; + + if (m_ownsPairCache) + { + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); + } +} + +template +void btAxisSweep3Internal::quantize(BP_FP_INT_TYPE* out, const btPoint3& point, int isMax) const +{ + btPoint3 clampedPoint(point); + + + + clampedPoint.setMax(m_worldAabbMin); + clampedPoint.setMin(m_worldAabbMax); + + btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize; + out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax); + out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax); + out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax); + +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::allocHandle() +{ + assert(m_firstFreeHandle); + + BP_FP_INT_TYPE handle = m_firstFreeHandle; + m_firstFreeHandle = getHandle(handle)->GetNextFree(); + m_numHandles++; + + return handle; +} + +template +void btAxisSweep3Internal::freeHandle(BP_FP_INT_TYPE handle) +{ + assert(handle > 0 && handle < m_maxHandles); + + getHandle(handle)->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; +} + + +template +BP_FP_INT_TYPE btAxisSweep3Internal::addHandle(const btPoint3& aabbMin,const btPoint3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy) +{ + // quantize the bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // allocate a handle + BP_FP_INT_TYPE handle = allocHandle(); + + + Handle* pHandle = getHandle(handle); + + pHandle->m_uniqueId = static_cast(handle); + //pHandle->m_pOverlaps = 0; + pHandle->m_clientObject = pOwner; + pHandle->m_collisionFilterGroup = collisionFilterGroup; + pHandle->m_collisionFilterMask = collisionFilterMask; + pHandle->m_multiSapParentProxy = multiSapProxy; + + // compute current limit of edge arrays + BP_FP_INT_TYPE limit = static_cast(m_numHandles * 2); + + + // insert new edges just inside the max boundary edge + for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++) + { + + m_pHandles[0].m_maxEdges[axis] += 2; + + m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1]; + + m_pEdges[axis][limit - 1].m_pos = min[axis]; + m_pEdges[axis][limit - 1].m_handle = handle; + + m_pEdges[axis][limit].m_pos = max[axis]; + m_pEdges[axis][limit].m_handle = handle; + + pHandle->m_minEdges[axis] = static_cast(limit - 1); + pHandle->m_maxEdges[axis] = limit; + } + + // now sort the new edges to their correct position + sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false); + sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false); + sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false); + sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false); + sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true); + sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true); + + + return handle; +} + + +template +void btAxisSweep3Internal::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher) +{ + + Handle* pHandle = getHandle(handle); + + //explicitly remove the pairs containing the proxy + //we could do it also in the sortMinUp (passing true) + //todo: compare performance + if (!m_pairCache->hasDeferredRemoval()) + { + m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher); + } + + // compute current limit of edge arrays + int limit = static_cast(m_numHandles * 2); + + int axis; + + for (axis = 0;axis<3;axis++) + { + m_pHandles[0].m_maxEdges[axis] -= 2; + } + + // remove the edges by sorting them up to the end of the list + for ( axis = 0; axis < 3; axis++) + { + Edge* pEdges = m_pEdges[axis]; + BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis]; + pEdges[max].m_pos = m_handleSentinel; + + sortMaxUp(axis,max,dispatcher,false); + + + BP_FP_INT_TYPE i = pHandle->m_minEdges[axis]; + pEdges[i].m_pos = m_handleSentinel; + + + sortMinUp(axis,i,dispatcher,false); + + pEdges[limit-1].m_handle = 0; + pEdges[limit-1].m_pos = m_handleSentinel; + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis,false); +#endif //DEBUG_BROADPHASE + + + } + + + // free the handle + freeHandle(handle); + + +} + +extern int gOverlappingPairs; +//#include + +template +void btAxisSweep3Internal::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + + if (m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + + + + + +} + + +template +bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + const Handle* pHandleA = static_cast(proxy0); + const Handle* pHandleB = static_cast(proxy1); + + //optimization 1: check the array index (memory address), instead of the m_pos + + for (int axis = 0; axis < 3; axis++) + { + if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || + pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) + { + return false; + } + } + return true; +} + +template +bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1) +{ + //optimization 1: check the array index (memory address), instead of the m_pos + + if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || + pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] || + pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] || + pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) + { + return false; + } + return true; +} + +template +void btAxisSweep3Internal::updateHandle(BP_FP_INT_TYPE handle, const btPoint3& aabbMin,const btPoint3& aabbMax,btDispatcher* dispatcher) +{ +// assert(bounds.IsFinite()); + //assert(bounds.HasVolume()); + + Handle* pHandle = getHandle(handle); + + // quantize the new bounds + BP_FP_INT_TYPE min[3], max[3]; + quantize(min, aabbMin, 0); + quantize(max, aabbMax, 1); + + // update changed edges + for (int axis = 0; axis < 3; axis++) + { + BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis]; + BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis]; + + int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos; + int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos; + + m_pEdges[axis][emin].m_pos = min[axis]; + m_pEdges[axis][emax].m_pos = max[axis]; + + // expand (only adds overlaps) + if (dmin < 0) + sortMinDown(axis, emin,dispatcher,true); + + if (dmax > 0) + sortMaxUp(axis, emax,dispatcher,true); + + // shrink (only removes overlaps) + if (dmin > 0) + sortMinUp(axis, emin,dispatcher,true); + + if (dmax < 0) + sortMaxDown(axis, emax,dispatcher,true); + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + } + + +} + + + + +// sorting a min edge downwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (pPrev->IsMax()) + { + // if previous edge is a maximum check the bounds and add an overlap if necessary + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2)) + { + m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev); + + //AddOverlap(pEdge->m_handle, pPrev->m_handle); + + } + + // update edge reference in other handle + pHandlePrev->m_maxEdges[axis]++; + } + else + pHandlePrev->m_minEdges[axis]++; + + pHandleEdge->m_minEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a min edge upwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + if (pNext->IsMax()) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + // if next edge is maximum remove any overlap between the two handles + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + } + + + // update edge reference in other handle + pHandleNext->m_maxEdges[axis]--; + } + else + pHandleNext->m_minEdges[axis]--; + + pHandleEdge->m_minEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + + +} + +// sorting a max edge downwards can only ever *remove* overlaps +template +void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps) +{ + + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pPrev = pEdge - 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pEdge->m_pos < pPrev->m_pos) + { + Handle* pHandlePrev = getHandle(pPrev->m_handle); + + if (!pPrev->IsMax()) + { + // if previous edge was a minimum remove any overlap between the two handles + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) + { + //this is done during the overlappingpairarray iteration/narrowphase collision + + + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); + if (m_userPairCallback) + m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); + + + + } + + // update edge reference in other handle + pHandlePrev->m_minEdges[axis]++;; + } + else + pHandlePrev->m_maxEdges[axis]++; + + pHandleEdge->m_maxEdges[axis]--; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pPrev; + *pPrev = swap; + + // decrement + pEdge--; + pPrev--; + } + + +#ifdef DEBUG_BROADPHASE + debugPrintAxis(axis); +#endif //DEBUG_BROADPHASE + +} + +// sorting a max edge upwards can only ever *add* overlaps +template +void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps) +{ + Edge* pEdge = m_pEdges[axis] + edge; + Edge* pNext = pEdge + 1; + Handle* pHandleEdge = getHandle(pEdge->m_handle); + + while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos)) + { + Handle* pHandleNext = getHandle(pNext->m_handle); + + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (!pNext->IsMax()) + { + // if next edge is a minimum check the bounds and add an overlap if necessary + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2)) + { + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + m_pairCache->addOverlappingPair(handle0,handle1); + if (m_userPairCallback) + m_userPairCallback->addOverlappingPair(handle0,handle1); + } + + // update edge reference in other handle + pHandleNext->m_minEdges[axis]--; + } + else + pHandleNext->m_maxEdges[axis]--; + + pHandleEdge->m_maxEdges[axis]++; + + // swap the edges + Edge swap = *pEdge; + *pEdge = *pNext; + *pNext = swap; + + // increment + pEdge++; + pNext++; + } + +} + + + +//////////////////////////////////////////////////////////////////// + + +/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase. +/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats. +/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance. +class btAxisSweep3 : public btAxisSweep3Internal +{ +public: + + btAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0); + +}; + +/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune. +/// This comes at the cost of more memory per handle, and a bit slower performance. +/// It uses arrays rather then lists for storage of the 3 axis. +class bt32BitAxisSweep3 : public btAxisSweep3Internal +{ +public: + + bt32BitAxisSweep3(const btPoint3& worldAabbMin,const btPoint3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0); }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h index b6ace03c07a..200ac365329 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h @@ -20,20 +20,34 @@ subject to the following restrictions: struct btDispatcherInfo; class btDispatcher; -struct btBroadphaseProxy; -#include "../../LinearMath/btVector3.h" +#include "btBroadphaseProxy.h" +class btOverlappingPairCache; -///BroadphaseInterface for aabb-overlapping object pairs +#include "LinearMath/btVector3.h" + +///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs. +///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase. +///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class. class btBroadphaseInterface { public: virtual ~btBroadphaseInterface() {} - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) =0; - virtual void destroyProxy(btBroadphaseProxy* proxy)=0; - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax)=0; - virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy)=0; + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0; + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0; + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0; + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher)=0; + + virtual btOverlappingPairCache* getOverlappingPairCache()=0; + virtual const btOverlappingPairCache* getOverlappingPairCache() const =0; + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0; + + virtual void printStats() = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index 40d9748ffa9..e0bb67f8521 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -16,7 +16,8 @@ subject to the following restrictions: #ifndef BROADPHASE_PROXY_H #define BROADPHASE_PROXY_H -#include "../../LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE +#include "LinearMath/btAlignedAllocator.h" /// btDispatcher uses these types @@ -38,6 +39,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE, CONE_SHAPE_PROXYTYPE, CONVEX_SHAPE_PROXYTYPE, CYLINDER_SHAPE_PROXYTYPE, + UNIFORM_SCALING_SHAPE_PROXYTYPE, MINKOWSKI_SUM_SHAPE_PROXYTYPE, MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE, //concave shapes @@ -50,6 +52,8 @@ CONCAVE_SHAPES_START_HERE, TERRAIN_SHAPE_PROXYTYPE, ///Used for GIMPACT Trimesh integration GIMPACT_SHAPE_PROXYTYPE, +///Multimaterial mesh + MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE, EMPTY_SHAPE_PROXYTYPE, STATIC_PLANE_PROXYTYPE, @@ -57,13 +61,18 @@ CONCAVE_SHAPES_END_HERE, COMPOUND_SHAPE_PROXYTYPE, + SOFTBODY_SHAPE_PROXYTYPE, + MAX_BROADPHASE_COLLISION_TYPES }; -///btBroadphaseProxy -struct btBroadphaseProxy +///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. +///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody. +ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy { + +BT_DECLARE_ALIGNED_ALLOCATOR(); ///optional filtering to cull potential collisions enum CollisionFilterGroups @@ -73,44 +82,60 @@ struct btBroadphaseProxy KinematicFilter = 4, DebrisFilter = 8, SensorTrigger = 16, - AllFilter = DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger + AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger }; //Usually the client btCollisionObject or Rigidbody class void* m_clientObject; + short int m_collisionFilterGroup; short int m_collisionFilterMask; - //used for memory pools - btBroadphaseProxy() :m_clientObject(0){} + void* m_multiSapParentProxy; - btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) + + int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc. + + SIMD_FORCE_INLINE int getUid() const + { + return m_uniqueId; + } + + //used for memory pools + btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0) + { + } + + btBroadphaseProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0) :m_clientObject(userPtr), m_collisionFilterGroup(collisionFilterGroup), m_collisionFilterMask(collisionFilterMask) { + m_multiSapParentProxy = multiSapParentProxy; } - static inline bool isPolyhedral(int proxyType) + + + static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType) { return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE); } - static inline bool isConvex(int proxyType) + static SIMD_FORCE_INLINE bool isConvex(int proxyType) { return (proxyType < CONCAVE_SHAPES_START_HERE); } - static inline bool isConcave(int proxyType) + static SIMD_FORCE_INLINE bool isConcave(int proxyType) { return ((proxyType > CONCAVE_SHAPES_START_HERE) && (proxyType < CONCAVE_SHAPES_END_HERE)); } - static inline bool isCompound(int proxyType) + static SIMD_FORCE_INLINE bool isCompound(int proxyType) { return (proxyType == COMPOUND_SHAPE_PROXYTYPE); } - static inline bool isInfinite(int proxyType) + static SIMD_FORCE_INLINE bool isInfinite(int proxyType) { return (proxyType == STATIC_PLANE_PROXYTYPE); } @@ -124,8 +149,9 @@ struct btBroadphaseProxy; -/// contains a pair of aabb-overlapping objects -struct btBroadphasePair +///The btBroadphasePair class contains a pair of aabb-overlapping objects. +///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes. +ATTRIBUTE_ALIGNED16(struct) btBroadphasePair { btBroadphasePair () : @@ -136,6 +162,8 @@ struct btBroadphasePair { } +BT_DECLARE_ALIGNED_ALLOCATOR(); + btBroadphasePair(const btBroadphasePair& other) : m_pProxy0(other.m_pProxy0), m_pProxy1(other.m_pProxy1), @@ -181,6 +209,7 @@ SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePa */ + class btBroadphasePairSortPredicate { public: diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp index 2ad0c86d8a2..c95d1be0f2c 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp @@ -18,6 +18,6 @@ subject to the following restrictions: btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) { - m_dispatcher = ci.m_dispatcher; + m_dispatcher = ci.m_dispatcher1; } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h index 55cec386a7b..1618ad9fdd3 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h @@ -16,7 +16,8 @@ subject to the following restrictions: #ifndef COLLISION_ALGORITHM_H #define COLLISION_ALGORITHM_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" +#include "LinearMath/btAlignedObjectArray.h" struct btBroadphaseProxy; class btDispatcher; @@ -25,21 +26,22 @@ class btCollisionObject; struct btDispatcherInfo; class btPersistentManifold; +typedef btAlignedObjectArray btManifoldArray; struct btCollisionAlgorithmConstructionInfo { btCollisionAlgorithmConstructionInfo() - :m_dispatcher(0), + :m_dispatcher1(0), m_manifold(0) { } btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp) - :m_dispatcher(dispatcher) + :m_dispatcher1(dispatcher) { (void)temp; } - btDispatcher* m_dispatcher; + btDispatcher* m_dispatcher1; btPersistentManifold* m_manifold; int getDispatcherId(); @@ -71,6 +73,7 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0; + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp new file mode 100644 index 00000000000..7c41c8d8f71 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -0,0 +1,1289 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvt implementation by Nathanael Presson + +#include "btDbvt.h" + +// +typedef btAlignedObjectArray tNodeArray; +typedef btAlignedObjectArray tConstNodeArray; + +// +struct btDbvtNodeEnumerator : btDbvt::ICollide +{ +tConstNodeArray nodes; +void Process(const btDbvtNode* n) { nodes.push_back(n); } +}; + +// +static DBVT_INLINE int indexof(const btDbvtNode* node) +{ +return(node->parent->childs[1]==node); +} + +// +static DBVT_INLINE btDbvtVolume merge( const btDbvtVolume& a, + const btDbvtVolume& b) +{ +#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE +DBVT_ALIGN char locals[sizeof(btDbvtAabbMm)]; +btDbvtVolume& res=*(btDbvtVolume*)locals; +#else +btDbvtVolume res; +#endif +Merge(a,b,res); +return(res); +} + +// volume+edge lengths +static DBVT_INLINE btScalar size(const btDbvtVolume& a) +{ +const btVector3 edges=a.Lengths(); +return( edges.x()*edges.y()*edges.z()+ + edges.x()+edges.y()+edges.z()); +} + +// +static void getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth) +{ +if(node->isinternal()) + { + getmaxdepth(node->childs[0],depth+1,maxdepth); + getmaxdepth(node->childs[0],depth+1,maxdepth); + } else maxdepth=btMax(maxdepth,depth); +} + +// +static DBVT_INLINE void deletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ +btAlignedFree(pdbvt->m_free); +pdbvt->m_free=node; +} + +// +static void recursedeletenode( btDbvt* pdbvt, + btDbvtNode* node) +{ +if(!node->isleaf()) + { + recursedeletenode(pdbvt,node->childs[0]); + recursedeletenode(pdbvt,node->childs[1]); + } +if(node==pdbvt->m_root) pdbvt->m_root=0; +deletenode(pdbvt,node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + void* data) +{ +btDbvtNode* node; +if(pdbvt->m_free) + { node=pdbvt->m_free;pdbvt->m_free=0; } + else + { node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); } +node->parent = parent; +node->data = data; +node->childs[1] = 0; +return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume, + void* data) +{ +btDbvtNode* node=createnode(pdbvt,parent,data); +node->volume=volume; +return(node); +} + +// +static DBVT_INLINE btDbvtNode* createnode( btDbvt* pdbvt, + btDbvtNode* parent, + const btDbvtVolume& volume0, + const btDbvtVolume& volume1, + void* data) +{ +btDbvtNode* node=createnode(pdbvt,parent,data); +Merge(volume0,volume1,node->volume); +return(node); +} + +// +static void insertleaf( btDbvt* pdbvt, + btDbvtNode* root, + btDbvtNode* leaf) +{ +if(!pdbvt->m_root) + { + pdbvt->m_root = leaf; + leaf->parent = 0; + } + else + { + if(!root->isleaf()) + { + do { + root=root->childs[Select( leaf->volume, + root->childs[0]->volume, + root->childs[1]->volume)]; + } while(!root->isleaf()); + } + btDbvtNode* prev=root->parent; + btDbvtNode* node=createnode(pdbvt,prev,leaf->volume,root->volume,0); + if(prev) + { + prev->childs[indexof(root)] = node; + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + do { + if(!prev->volume.Contain(node->volume)) + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + else + break; + node=prev; + } while(0!=(prev=node->parent)); + } + else + { + node->childs[0] = root;root->parent=node; + node->childs[1] = leaf;leaf->parent=node; + pdbvt->m_root = node; + } + } +} + +// +static btDbvtNode* removeleaf( btDbvt* pdbvt, + btDbvtNode* leaf) +{ +if(leaf==pdbvt->m_root) + { + pdbvt->m_root=0; + return(0); + } + else + { + btDbvtNode* parent=leaf->parent; + btDbvtNode* prev=parent->parent; + btDbvtNode* sibling=parent->childs[1-indexof(leaf)]; + if(prev) + { + prev->childs[indexof(parent)]=sibling; + sibling->parent=prev; + deletenode(pdbvt,parent); + while(prev) + { + const btDbvtVolume pb=prev->volume; + Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume); + if(NotEqual(pb,prev->volume)) + { + prev=prev->parent; + } else break; + } + return(prev?prev:pdbvt->m_root); + } + else + { + pdbvt->m_root=sibling; + sibling->parent=0; + deletenode(pdbvt,parent); + return(pdbvt->m_root); + } + } +} + +// +static void fetchleaves(btDbvt* pdbvt, + btDbvtNode* root, + tNodeArray& leaves, + int depth=-1) +{ +if(root->isinternal()&&depth) + { + fetchleaves(pdbvt,root->childs[0],leaves,depth-1); + fetchleaves(pdbvt,root->childs[1],leaves,depth-1); + deletenode(pdbvt,root); + } + else + { + leaves.push_back(root); + } +} + +// +static void split( const tNodeArray& leaves, + tNodeArray& left, + tNodeArray& right, + const btVector3& org, + const btVector3& axis) +{ +left.resize(0); +right.resize(0); +for(int i=0,ni=leaves.size();ivolume.Center()-org)<0) + left.push_back(leaves[i]); + else + right.push_back(leaves[i]); + } +} + +// +static btDbvtVolume bounds( const tNodeArray& leaves) +{ +#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE +DBVT_ALIGN char locals[sizeof(btDbvtVolume)]; +btDbvtVolume& volume=*(btDbvtVolume*)locals; +volume=leaves[0]->volume; +#else +btDbvtVolume volume=leaves[0]->volume; +#endif +for(int i=1,ni=leaves.size();ivolume,volume); + } +return(volume); +} + +// +static void bottomup( btDbvt* pdbvt, + tNodeArray& leaves) +{ +while(leaves.size()>1) + { + btScalar minsize=SIMD_INFINITY; + int minidx[2]={-1,-1}; + for(int i=0;ivolume,leaves[j]->volume)); + if(szvolume,n[1]->volume,0); + p->childs[0] = n[0]; + p->childs[1] = n[1]; + n[0]->parent = p; + n[1]->parent = p; + leaves[minidx[0]] = p; + leaves.swap(minidx[1],leaves.size()-1); + leaves.pop_back(); + } +} + +// +static btDbvtNode* topdown(btDbvt* pdbvt, + tNodeArray& leaves, + int bu_treshold) +{ +static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; +if(leaves.size()>1) + { + if(leaves.size()>bu_treshold) + { + const btDbvtVolume vol=bounds(leaves); + const btVector3 org=vol.Center(); + tNodeArray sets[2]; + int bestaxis=-1; + int bestmidp=leaves.size(); + int splitcount[3][2]={{0,0},{0,0},{0,0}}; + int i; + for( i=0;ivolume.Center()-org; + for(int j=0;j<3;++j) + { + ++splitcount[j][dot(x,axis[j])>0?1:0]; + } + } + for( i=0;i<3;++i) + { + if((splitcount[i][0]>0)&&(splitcount[i][1]>0)) + { + const int midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1])); + if(midp=0) + { + sets[0].reserve(splitcount[bestaxis][0]); + sets[1].reserve(splitcount[bestaxis][1]); + split(leaves,sets[0],sets[1],org,axis[bestaxis]); + } + else + { + sets[0].reserve(leaves.size()/2+1); + sets[1].reserve(leaves.size()/2); + for(int i=0,ni=leaves.size();ichilds[0]=topdown(pdbvt,sets[0],bu_treshold); + node->childs[1]=topdown(pdbvt,sets[1],bu_treshold); + node->childs[0]->parent=node; + node->childs[1]->parent=node; + return(node); + } + else + { + bottomup(pdbvt,leaves); + return(leaves[0]); + } + } +return(leaves[0]); +} + +// +static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n,btDbvtNode*& r) +{ +btDbvtNode* p=n->parent; +btAssert(n->isinternal()); +if(p>n) + { + const int i=indexof(n); + const int j=1-i; + btDbvtNode* s=p->childs[j]; + btDbvtNode* q=p->parent; + btAssert(n==p->childs[i]); + if(q) q->childs[indexof(p)]=n; else r=n; + s->parent=n; + p->parent=n; + n->parent=q; + p->childs[0]=n->childs[0]; + p->childs[1]=n->childs[1]; + n->childs[0]->parent=p; + n->childs[1]->parent=p; + n->childs[i]=p; + n->childs[j]=s; + btSwap(p->volume,n->volume); + return(p); + } +return(n); +} + +// +static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count) +{ +while(n&&(count--)) n=n->parent; +return(n); +} + +// +// Api +// + +// + btDbvt::btDbvt() +{ +m_root = 0; +m_free = 0; +m_lkhd = -1; +m_leaves = 0; +m_opath = 0; +} + +// + btDbvt::~btDbvt() +{ +clear(); +} + +// +void btDbvt::clear() +{ +if(m_root) recursedeletenode(this,m_root); +btAlignedFree(m_free); +m_free=0; +} + +// +void btDbvt::optimizeBottomUp() +{ +if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + bottomup(this,leaves); + m_root=leaves[0]; + } +} + +// +void btDbvt::optimizeTopDown(int bu_treshold) +{ +if(m_root) + { + tNodeArray leaves; + leaves.reserve(m_leaves); + fetchleaves(this,m_root,leaves); + m_root=topdown(this,leaves,bu_treshold); + } +} + +// +void btDbvt::optimizeIncremental(int passes) +{ +if(passes<0) passes=m_leaves; +if(m_root&&(passes>0)) + { + do { + btDbvtNode* node=m_root; + unsigned bit=0; + while(node->isinternal()) + { + node=sort(node,m_root)->childs[(m_opath>>bit)&1]; + bit=(bit+1)&(sizeof(unsigned)*8-1); + } + update(node); + ++m_opath; + } while(--passes); + } +} + +// +btDbvtNode* btDbvt::insert(const btDbvtVolume& volume,void* data) +{ +btDbvtNode* leaf=createnode(this,0,volume,data); +insertleaf(this,m_root,leaf); +++m_leaves; +return(leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,int lookahead) +{ +btDbvtNode* root=removeleaf(this,leaf); +if(root) + { + if(lookahead>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } +insertleaf(this,root,leaf); +} + +// +void btDbvt::update(btDbvtNode* leaf,const btDbvtVolume& volume) +{ +btDbvtNode* root=removeleaf(this,leaf); +if(root) + { + if(m_lkhd>=0) + { + for(int i=0;(iparent;++i) + { + root=root->parent; + } + } else root=m_root; + } +leaf->volume=volume; +insertleaf(this,root,leaf); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin) +{ +if(leaf->volume.Contain(volume)) return(false); +volume.Expand(btVector3(margin,margin,margin)); +volume.SignedExpand(velocity); +update(leaf,volume); +return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity) +{ +if(leaf->volume.Contain(volume)) return(false); +volume.SignedExpand(velocity); +update(leaf,volume); +return(true); +} + +// +bool btDbvt::update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin) +{ +if(leaf->volume.Contain(volume)) return(false); +volume.Expand(btVector3(margin,margin,margin)); +update(leaf,volume); +return(true); +} + +// +void btDbvt::remove(btDbvtNode* leaf) +{ +removeleaf(this,leaf); +deletenode(this,leaf); +--m_leaves; +} + +// +void btDbvt::write(IWriter* iwriter) const +{ +btDbvtNodeEnumerator nodes; +nodes.nodes.reserve(m_leaves*2); +enumNodes(m_root,nodes); +iwriter->Prepare(m_root,nodes.nodes.size()); +for(int i=0;iparent) p=nodes.nodes.findLinearSearch(n->parent); + if(n->isinternal()) + { + const int c0=nodes.nodes.findLinearSearch(n->childs[0]); + const int c1=nodes.nodes.findLinearSearch(n->childs[1]); + iwriter->WriteNode(n,i,p,c0,c1); + } + else + { + iwriter->WriteLeaf(n,i,p); + } + } +} + +// +void btDbvt::clone(btDbvt& dest,IClone* iclone) const +{ +dest.clear(); +if(m_root!=0) + { + btAlignedObjectArray stack; + stack.reserve(m_leaves); + stack.push_back(sStkCLN(m_root,0)); + do { + const int i=stack.size()-1; + const sStkCLN e=stack[i]; + btDbvtNode* n=createnode(&dest,e.parent,e.node->volume,e.node->data); + stack.pop_back(); + if(e.parent!=0) + e.parent->childs[i&1]=n; + else + dest.m_root=n; + if(e.node->isinternal()) + { + stack.push_back(sStkCLN(e.node->childs[0],n)); + stack.push_back(sStkCLN(e.node->childs[1],n)); + } + else + { + iclone->CloneLeaf(n); + } + } while(stack.size()>0); + } +} + +// +int btDbvt::maxdepth(const btDbvtNode* node) +{ +int depth=0; +if(node) getmaxdepth(node,1,depth); +return(depth); +} + +// +int btDbvt::countLeaves(const btDbvtNode* node) +{ +if(node->isinternal()) + return(countLeaves(node->childs[0])+countLeaves(node->childs[1])); + else + return(1); +} + +// +void btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves) +{ +if(node->isinternal()) + { + extractLeaves(node->childs[0],leaves); + extractLeaves(node->childs[1],leaves); + } + else + { + leaves.push_back(node); + } +} + +// +#if DBVT_ENABLE_BENCHMARK + +#include +#include +#include "LinearMath/btQuickProf.h" + +/* +q6600,2.4ghz + +/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32" +/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch" +/Fo"..\..\out\release8\build\libbulletcollision\\" +/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb" +/W3 /nologo /c /Wp64 /Zi /errorReport:prompt + +Benchmarking dbvt... + World scale: 100.000000 + Extents base: 1.000000 + Extents range: 4.000000 + Leaves: 8192 + sizeof(btDbvtVolume): 32 bytes + sizeof(btDbvtNode): 44 bytes +[1] btDbvtVolume intersections: 3499 ms (-1%) +[2] btDbvtVolume merges: 1934 ms (0%) +[3] btDbvt::collideTT: 5485 ms (-21%) +[4] btDbvt::collideTT self: 2814 ms (-20%) +[5] btDbvt::collideTT xform: 7379 ms (-1%) +[6] btDbvt::collideTT xform,self: 7270 ms (-2%) +[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s) +[8] insert/remove: 2093 ms (0%),(1001983 ir/s) +[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) +[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) +[11] optimize (incremental): 2514 ms (0%),(1668000 o/s) +[12] btDbvtVolume notequal: 3659 ms (0%) +[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) +[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) +[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) +[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) +[17] btDbvtVolume select: 3419 ms (0%) +*/ + +struct btDbvtBenchmark +{ +struct NilPolicy : btDbvt::ICollide + { + NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true) {} + void Process(const btDbvtNode*,const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*) { ++m_pcount; } + void Process(const btDbvtNode*,btScalar depth) + { + ++m_pcount; + if(m_checksort) + { if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); } + } + int m_pcount; + btScalar m_depth; + bool m_checksort; + }; +struct P14 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf,btScalar depth) + { + Node n; + n.leaf = leaf; + n.depth = depth; + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + }; +struct P15 : btDbvt::ICollide + { + struct Node + { + const btDbvtNode* leaf; + btScalar depth; + }; + void Process(const btDbvtNode* leaf) + { + Node n; + n.leaf = leaf; + n.depth = dot(leaf->volume.Center(),m_axis); + } + static int sortfnc(const Node& a,const Node& b) + { + if(a.depthb.depth) return(-1); + return(0); + } + btAlignedObjectArray m_nodes; + btVector3 m_axis; + }; +static btScalar RandUnit() + { + return(rand()/(btScalar)RAND_MAX); + } +static btVector3 RandVector3() + { + return(btVector3(RandUnit(),RandUnit(),RandUnit())); + } +static btVector3 RandVector3(btScalar cs) + { + return(RandVector3()*cs-btVector3(cs,cs,cs)/2); + } +static btDbvtVolume RandVolume(btScalar cs,btScalar eb,btScalar es) + { + return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es)); + } +static btTransform RandTransform(btScalar cs) + { + btTransform t; + t.setOrigin(RandVector3(cs)); + t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized()); + return(t); + } +static void RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt) + { + dbvt.clear(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark5_Iterations); + for(int i=0;i transforms; + btDbvtBenchmark::NilPolicy policy; + transforms.resize(cfgBenchmark6_Iterations); + for(int i=0;i rayorg; + btAlignedObjectArray raydir; + btDbvtBenchmark::NilPolicy policy; + rayorg.resize(cfgBenchmark7_Iterations); + raydir.resize(cfgBenchmark7_Iterations); + for(int i=0;i leaves; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + dbvt.extractLeaves(dbvt.m_root,leaves); + printf("[9] updates (teleport): "); + wallclock.reset(); + for(int i=0;i(leaves[rand()%cfgLeaves]), + btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale)); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time); + } +if(cfgBenchmark10_Enable) + {// Benchmark 10 + srand(380843); + btDbvt dbvt; + btAlignedObjectArray leaves; + btAlignedObjectArray vectors; + vectors.resize(cfgBenchmark10_Iterations); + for(int i=0;i(leaves[rand()%cfgLeaves]); + btDbvtVolume v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d); + dbvt.update(l,v); + } + } + const int time=(int)wallclock.getTimeMilliseconds(); + const int up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations; + printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time); + } +if(cfgBenchmark11_Enable) + {// Benchmark 11 + srand(380843); + btDbvt dbvt; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + printf("[11] optimize (incremental): "); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + for(int i=0;i vectors; + btDbvtBenchmark::NilPolicy policy; + vectors.resize(cfgBenchmark13_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P14 policy; + vectors.resize(cfgBenchmark14_Iterations); + for(int i=0;i vectors; + btDbvtBenchmark::P15 policy; + vectors.resize(cfgBenchmark15_Iterations); + for(int i=0;i batch; + btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt); + dbvt.optimizeTopDown(); + batch.reserve(cfgBenchmark16_BatchCount); + printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount); + wallclock.reset(); + for(int i=0;i volumes; + btAlignedObjectArray results; + btAlignedObjectArray indices; + volumes.resize(cfgLeaves); + results.resize(cfgLeaves); + indices.resize(cfgLeaves); + for(int i=0;i= 1400) + #define DBVT_USE_TEMPLATE 1 + #else + #define DBVT_USE_TEMPLATE 0 +#endif +#else +#define DBVT_USE_TEMPLATE 0 +#endif + +// Use only intrinsics instead of inline asm +#define DBVT_USE_INTRINSIC_SSE 1 + +// Using memmov for collideOCL +#define DBVT_USE_MEMMOVE 1 + +// Enable benchmarking code +#define DBVT_ENABLE_BENCHMARK 0 + +// Inlining +#define DBVT_INLINE SIMD_FORCE_INLINE +// Align +#ifdef WIN32 +#define DBVT_ALIGN __declspec(align(16)) +#else +#define DBVT_ALIGN +#endif + +// Specific methods implementation + +#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds +#define DBVT_SELECT_IMPL DBVT_IMPL_SSE +#define DBVT_MERGE_IMPL DBVT_IMPL_SSE +#define DBVT_INT0_IMPL DBVT_IMPL_SSE +#else +#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC +#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC +#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC +#endif + +#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_INT0_IMPL==DBVT_IMPL_SSE) +#include +#endif + +// +// Auto config and checks +// + +#if DBVT_USE_TEMPLATE +#define DBVT_VIRTUAL +#define DBVT_VIRTUAL_DTOR(a) +#define DBVT_PREFIX template +#define DBVT_IPOLICY T& policy +#define DBVT_CHECKTYPE static const ICollide& typechecker=*(T*)0; +#else +#define DBVT_VIRTUAL_DTOR(a) virtual ~a() {} +#define DBVT_VIRTUAL virtual +#define DBVT_PREFIX +#define DBVT_IPOLICY ICollide& policy +#define DBVT_CHECKTYPE +#endif + +#if DBVT_USE_MEMMOVE +#ifndef __CELLOS_LV2__ +#include +#endif +#include +#endif + +#ifndef DBVT_USE_TEMPLATE +#error "DBVT_USE_TEMPLATE undefined" +#endif + +#ifndef DBVT_USE_MEMMOVE +#error "DBVT_USE_MEMMOVE undefined" +#endif + +#ifndef DBVT_ENABLE_BENCHMARK +#error "DBVT_ENABLE_BENCHMARK undefined" +#endif + +#ifndef DBVT_SELECT_IMPL +#error "DBVT_SELECT_IMPL undefined" +#endif + +#ifndef DBVT_MERGE_IMPL +#error "DBVT_MERGE_IMPL undefined" +#endif + +#ifndef DBVT_INT0_IMPL +#error "DBVT_INT0_IMPL undefined" +#endif + +// +// Defaults volumes +// + +/* btDbvtAabbMm */ +struct btDbvtAabbMm +{ +DBVT_INLINE btVector3 Center() const { return((mi+mx)/2); } +DBVT_INLINE btVector3 Lengths() const { return(mx-mi); } +DBVT_INLINE btVector3 Extents() const { return((mx-mi)/2); } +DBVT_INLINE const btVector3& Mins() const { return(mi); } +DBVT_INLINE const btVector3& Maxs() const { return(mx); } +static inline btDbvtAabbMm FromCE(const btVector3& c,const btVector3& e); +static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); +static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); +static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); +static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); +DBVT_INLINE void Expand(const btVector3& e); +DBVT_INLINE void SignedExpand(const btVector3& e); +DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; +DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; +DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + const btTransform& xform); +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btVector3& b); +DBVT_INLINE friend bool Intersect( const btDbvtAabbMm& a, + const btVector3& org, + const btVector3& invdir, + const unsigned* signs); +DBVT_INLINE friend btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +DBVT_INLINE friend int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +DBVT_INLINE friend void Merge( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + btDbvtAabbMm& r); +DBVT_INLINE friend bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b); +private: +DBVT_INLINE void AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const; +private: +btVector3 mi,mx; +}; + +// Types +typedef btDbvtAabbMm btDbvtVolume; + +/* btDbvtNode */ +struct btDbvtNode +{ + btDbvtVolume volume; + btDbvtNode* parent; + DBVT_INLINE bool isleaf() const { return(childs[1]==0); } + DBVT_INLINE bool isinternal() const { return(!isleaf()); } + union { + btDbvtNode* childs[2]; + void* data; + int dataAsInt; + }; +}; + +///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). +///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes. +///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. +struct btDbvt + { + /* Stack element */ + struct sStkNN + { + const btDbvtNode* a; + const btDbvtNode* b; + sStkNN() {} + sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {} + }; + struct sStkNP + { + const btDbvtNode* node; + int mask; + sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {} + }; + struct sStkNPS + { + const btDbvtNode* node; + int mask; + btScalar value; + sStkNPS() {} + sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {} + }; + struct sStkCLN + { + const btDbvtNode* node; + btDbvtNode* parent; + sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {} + }; + // Policies/Interfaces + + /* ICollide */ + struct ICollide + { + DBVT_VIRTUAL_DTOR(ICollide) + DBVT_VIRTUAL void Process(const btDbvtNode*,const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode*) {} + DBVT_VIRTUAL void Process(const btDbvtNode* n,btScalar) { Process(n); } + DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return(true); } + DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return(true); } + }; + /* IWriter */ + struct IWriter + { + virtual ~IWriter() {} + virtual void Prepare(const btDbvtNode* root,int numnodes)=0; + virtual void WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0; + virtual void WriteLeaf(const btDbvtNode*,int index,int parent)=0; + }; + /* IClone */ + struct IClone + { + virtual ~IClone() {} + virtual void CloneLeaf(btDbvtNode*) {} + }; + + // Constants + enum { + SIMPLE_STACKSIZE = 64, + DOUBLE_STACKSIZE = SIMPLE_STACKSIZE*2 + }; + + // Fields + btDbvtNode* m_root; + btDbvtNode* m_free; + int m_lkhd; + int m_leaves; + unsigned m_opath; + // Methods + btDbvt(); + ~btDbvt(); + void clear(); + bool empty() const { return(0==m_root); } + void optimizeBottomUp(); + void optimizeTopDown(int bu_treshold=128); + void optimizeIncremental(int passes); + btDbvtNode* insert(const btDbvtVolume& box,void* data); + void update(btDbvtNode* leaf,int lookahead=-1); + void update(btDbvtNode* leaf,const btDbvtVolume& volume); + bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity,btScalar margin); + bool update(btDbvtNode* leaf,btDbvtVolume volume,const btVector3& velocity); + bool update(btDbvtNode* leaf,btDbvtVolume volume,btScalar margin); + void remove(btDbvtNode* leaf); + void write(IWriter* iwriter) const; + void clone(btDbvt& dest,IClone* iclone=0) const; + static int maxdepth(const btDbvtNode* node); + static int countLeaves(const btDbvtNode* node); + static void extractLeaves(const btDbvtNode* node,btAlignedObjectArray& leaves); + #if DBVT_ENABLE_BENCHMARK + static void benchmark(); + #else + static void benchmark(){} + #endif + // DBVT_IPOLICY must support ICollide policy/interface + DBVT_PREFIX + static void enumNodes( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + static void enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideTV( const btDbvtNode* root, + const btDbvtVolume& volume, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideRAY( const btDbvtNode* root, + const btVector3& origin, + const btVector3& direction, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY); + DBVT_PREFIX + static void collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fullsort=true); + DBVT_PREFIX + static void collideTU( const btDbvtNode* root, + DBVT_IPOLICY); + // Helpers + static DBVT_INLINE int nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h) + { + int m=0; + while(l>1; + if(a[i[m]].value>=v) l=m+1; else h=m; + } + return(h); + } + static DBVT_INLINE int allocate( btAlignedObjectArray& ifree, + btAlignedObjectArray& stock, + const sStkNPS& value) + { + int i; + if(ifree.size()>0) + { i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; } + else + { i=stock.size();stock.push_back(value); } + return(i); + } + // + private: + btDbvt(const btDbvt&) {} + }; + +// +// Inline's +// + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e) +{ +btDbvtAabbMm box; +box.mi=c-e;box.mx=c+e; +return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c,btScalar r) +{ +return(FromCE(c,btVector3(r,r,r))); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx) +{ +btDbvtAabbMm box; +box.mi=mi;box.mx=mx; +return(box); +} + +// +inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts,int n) +{ +btDbvtAabbMm box; +box.mi=box.mx=pts[0]; +for(int i=1;i0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); +if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); +if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); +} + +// +DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const +{ +return( (mi.x()<=a.mi.x())&& + (mi.y()<=a.mi.y())&& + (mi.z()<=a.mi.z())&& + (mx.x()>=a.mx.x())&& + (mx.y()>=a.mx.y())&& + (mx.z()>=a.mx.z())); +} + +// +DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const +{ +btVector3 pi,px; +switch(s) + { + case (0+0+0): px=btVector3(mi.x(),mi.y(),mi.z()); + pi=btVector3(mx.x(),mx.y(),mx.z());break; + case (1+0+0): px=btVector3(mx.x(),mi.y(),mi.z()); + pi=btVector3(mi.x(),mx.y(),mx.z());break; + case (0+2+0): px=btVector3(mi.x(),mx.y(),mi.z()); + pi=btVector3(mx.x(),mi.y(),mx.z());break; + case (1+2+0): px=btVector3(mx.x(),mx.y(),mi.z()); + pi=btVector3(mi.x(),mi.y(),mx.z());break; + case (0+0+4): px=btVector3(mi.x(),mi.y(),mx.z()); + pi=btVector3(mx.x(),mx.y(),mi.z());break; + case (1+0+4): px=btVector3(mx.x(),mi.y(),mx.z()); + pi=btVector3(mi.x(),mx.y(),mi.z());break; + case (0+2+4): px=btVector3(mi.x(),mx.y(),mx.z()); + pi=btVector3(mx.x(),mi.y(),mi.z());break; + case (1+2+4): px=btVector3(mx.x(),mx.y(),mx.z()); + pi=btVector3(mi.x(),mi.y(),mi.z());break; + } +if((dot(n,px)+o)<0) return(-1); +if((dot(n,pi)+o)>=0) return(+1); +return(0); +} + +// +DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const +{ +const btVector3* b[]={&mx,&mi}; +const btVector3 p( b[(signs>>0)&1]->x(), + b[(signs>>1)&1]->y(), + b[(signs>>2)&1]->z()); +return(dot(p,v)); +} + +// +DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const +{ +for(int i=0;i<3;++i) + { + if(d[i]<0) + { smi+=mx[i]*d[i];smx+=mi[i]*d[i]; } + else + { smi+=mi[i]*d[i];smx+=mx[i]*d[i]; } + } +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_INT0_IMPL == DBVT_IMPL_SSE +const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), + _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); +const __int32* pu((const __int32*)&rt); +return((pu[0]|pu[1]|pu[2])==0); +#else +return( (a.mi.x()<=b.mx.x())&& + (a.mx.x()>=b.mi.x())&& + (a.mi.y()<=b.mx.y())&& + (a.mx.y()>=b.mi.y())&& + (a.mi.z()<=b.mx.z())&& + (a.mx.z()>=b.mi.z())); +#endif +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btDbvtAabbMm& b, + const btTransform& xform) +{ +const btVector3 d0=xform*b.Center()-a.Center(); +const btVector3 d1=d0*xform.getBasis(); +btScalar s0[2]={0,0}; +btScalar s1[2]={dot(xform.getOrigin(),d0),s1[0]}; +a.AddSpan(d0,s0[0],s0[1]); +b.AddSpan(d1,s1[0],s1[1]); +if(s0[0]>(s1[1])) return(false); +if(s0[1]<(s1[0])) return(false); +return(true); +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btVector3& b) +{ +return( (b.x()>=a.mi.x())&& + (b.y()>=a.mi.y())&& + (b.z()>=a.mi.z())&& + (b.x()<=a.mx.x())&& + (b.y()<=a.mx.y())&& + (b.z()<=a.mx.z())); +} + +// +DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, + const btVector3& org, + const btVector3& invdir, + const unsigned* signs) +{ +#if 0 +const btVector3 b0((a.mi-org)*invdir); +const btVector3 b1((a.mx-org)*invdir); +const btVector3 tmin(btMin(b0[0],b1[0]),btMin(b0[1],b1[1]),btMin(b0[2],b1[2])); +const btVector3 tmax(btMax(b0[0],b1[0]),btMax(b0[1],b1[1]),btMax(b0[2],b1[2])); +const btScalar tin=btMax(tmin[0],btMax(tmin[1],tmin[2])); +const btScalar tout=btMin(tmax[0],btMin(tmax[1],tmax[2])); +return(tinx()-org[0])*invdir[0]; +btScalar txmax=(bounds[1-signs[0]]->x()-org[0])*invdir[0]; +const btScalar tymin=(bounds[ signs[1]]->y()-org[1])*invdir[1]; +const btScalar tymax=(bounds[1-signs[1]]->y()-org[1])*invdir[1]; +if((txmin>tymax)||(tymin>txmax)) return(false); +if(tymin>txmin) txmin=tymin; +if(tymaxz()-org[2])*invdir[2]; +const btScalar tzmax=(bounds[1-signs[2]]->z()-org[2])*invdir[2]; +if((txmin>tzmax)||(tzmin>txmax)) return(false); +if(tzmin>txmin) txmin=tzmin; +if(tzmax0); +#endif +} + +// +DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); +return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); +} + +// +DBVT_INLINE int Select( const btDbvtAabbMm& o, + const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE +static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; + // TODO: the intrinsic version is 11% slower + #if DBVT_USE_INTRINSIC_SSE + __m128 omi(_mm_load_ps(o.mi)); + omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); + __m128 ami(_mm_load_ps(a.mi)); + ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); + ami=_mm_sub_ps(ami,omi); + ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); + __m128 bmi(_mm_load_ps(b.mi)); + bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); + bmi=_mm_sub_ps(bmi,omi); + bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); + __m128 t0(_mm_movehl_ps(ami,ami)); + ami=_mm_add_ps(ami,t0); + ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); + __m128 t1(_mm_movehl_ps(bmi,bmi)); + bmi=_mm_add_ps(bmi,t1); + bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); + return(_mm_cmple_ss(bmi,ami).m128_u32[0]&1); + #else + DBVT_ALIGN __int32 r[1]; + __asm + { + mov eax,o + mov ecx,a + mov edx,b + movaps xmm0,[eax] + movaps xmm5,mask + addps xmm0,[eax+16] + movaps xmm1,[ecx] + movaps xmm2,[edx] + addps xmm1,[ecx+16] + addps xmm2,[edx+16] + subps xmm1,xmm0 + subps xmm2,xmm0 + andps xmm1,xmm5 + andps xmm2,xmm5 + movhlps xmm3,xmm1 + movhlps xmm4,xmm2 + addps xmm1,xmm3 + addps xmm2,xmm4 + pshufd xmm3,xmm1,1 + pshufd xmm4,xmm2,1 + addss xmm1,xmm3 + addss xmm2,xmm4 + cmpless xmm2,xmm1 + movss r,xmm2 + } + return(r[0]&1); + #endif +#else +return(Proximity(o,a)b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i]; + } +#endif +} + +// +DBVT_INLINE bool NotEqual( const btDbvtAabbMm& a, + const btDbvtAabbMm& b) +{ +return( (a.mi.x()!=b.mi.x())|| + (a.mi.y()!=b.mi.y())|| + (a.mi.z()!=b.mi.z())|| + (a.mx.x()!=b.mx.x())|| + (a.mx.y()!=b.mx.y())|| + (a.mx.z()!=b.mx.z())); +} + +// +// Inline's +// + +// +DBVT_PREFIX +inline void btDbvt::enumNodes( const btDbvtNode* root, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +policy.Process(root); +if(root->isinternal()) + { + enumNodes(root->childs[0],policy); + enumNodes(root->childs[1],policy); + } +} + +// +DBVT_PREFIX +inline void btDbvt::enumLeaves( const btDbvtNode* root, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root->isinternal()) + { + enumLeaves(root->childs[0],policy); + enumLeaves(root->childs[1],policy); + } + else + { + policy.Process(root); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root0&&root1) + { + btAlignedObjectArray stack; + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=sStkNN(root0,root1); + do { + sStkNN p=stack[--depth]; + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-4; + } + if(p.a==p.b) + { + if(p.a->isinternal()) + { + stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]); + stack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]); + stack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]); + } + } + else if(Intersect(p.a->volume,p.b->volume)) + { + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stack[depth++]=sStkNN(p.a->childs[0],p.b); + stack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a,p.b->childs[0]); + stack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btDbvtNode* root1, + const btTransform& xform, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root0&&root1) + { + btAlignedObjectArray stack; + int depth=1; + int treshold=DOUBLE_STACKSIZE-4; + stack.resize(DOUBLE_STACKSIZE); + stack[0]=sStkNN(root0,root1); + do { + sStkNN p=stack[--depth]; + if(Intersect(p.a->volume,p.b->volume,xform)) + { + if(depth>treshold) + { + stack.resize(stack.size()*2); + treshold=stack.size()-4; + } + if(p.a->isinternal()) + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]); + stack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]); + stack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]); + } + else + { + stack[depth++]=sStkNN(p.a->childs[0],p.b); + stack[depth++]=sStkNN(p.a->childs[1],p.b); + } + } + else + { + if(p.b->isinternal()) + { + stack[depth++]=sStkNN(p.a,p.b->childs[0]); + stack[depth++]=sStkNN(p.a,p.b->childs[1]); + } + else + { + policy.Process(p.a,p.b); + } + } + } + } while(depth); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTT( const btDbvtNode* root0, + const btTransform& xform0, + const btDbvtNode* root1, + const btTransform& xform1, + DBVT_IPOLICY) +{ +const btTransform xform=xform0.inverse()*xform1; +collideTT(root0,root1,xform,policy); +} + +// +DBVT_PREFIX +inline void btDbvt::collideTV( const btDbvtNode* root, + const btDbvtVolume& vol, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(n->volume,volume)) + { + if(n->isinternal()) + { + stack.push_back(n->childs[0]); + stack.push_back(n->childs[1]); + } + else + { + policy.Process(n); + } + } + } while(stack.size()>0); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideRAY( const btDbvtNode* root, + const btVector3& origin, + const btVector3& direction, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + const btVector3 normal=direction.normalized(); + const btVector3 invdir( 1/normal.x(), + 1/normal.y(), + 1/normal.z()); + const unsigned signs[]={ direction.x()<0, + direction.y()<0, + direction.z()<0}; + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* node=stack[stack.size()-1]; + stack.pop_back(); + if(Intersect(node->volume,origin,invdir,signs)) + { + if(node->isinternal()) + { + stack.push_back(node->childs[0]); + stack.push_back(node->childs[1]); + } + else + { + policy.Process(node); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideKDOP(const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + int count, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + const int inside=(1< stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(sStkNP(root,0)); + do { + sStkNP se=stack[stack.size()-1]; + bool out=false; + stack.pop_back(); + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(!out) + { + if((se.mask!=inside)&&(se.node->isinternal())) + { + stack.push_back(sStkNP(se.node->childs[0],se.mask)); + stack.push_back(sStkNP(se.node->childs[1],se.mask)); + } + else + { + if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideOCL( const btDbvtNode* root, + const btVector3* normals, + const btScalar* offsets, + const btVector3& sortaxis, + int count, + DBVT_IPOLICY, + bool fsort) +{ +DBVT_CHECKTYPE +if(root) + { + const unsigned srtsgns=(sortaxis[0]>=0?1:0)+ + (sortaxis[1]>=0?2:0)+ + (sortaxis[2]>=0?4:0); + const int inside=(1< stock; + btAlignedObjectArray ifree; + btAlignedObjectArray stack; + int signs[sizeof(unsigned)*8]; + btAssert(count=0)?1:0)+ + ((normals[i].y()>=0)?2:0)+ + ((normals[i].z()>=0)?4:0); + } + stock.reserve(SIMPLE_STACKSIZE); + stack.reserve(SIMPLE_STACKSIZE); + ifree.reserve(SIMPLE_STACKSIZE); + stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns)))); + do { + const int id=stack[stack.size()-1]; + sStkNPS se=stock[id]; + stack.pop_back();ifree.push_back(id); + if(se.mask!=inside) + { + bool out=false; + for(int i=0,j=1;(!out)&&(ivolume.Classify(normals[i],offsets[i],signs[i]); + switch(side) + { + case -1: out=true;break; + case +1: se.mask|=j;break; + } + } + } + if(out) continue; + } + if(policy.Descent(se.node)) + { + if(se.node->isinternal()) + { + const btDbvtNode* pns[]={ se.node->childs[0],se.node->childs[1]}; + sStkNPS nes[]={ sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)), + sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))}; + const int q=nes[0].value0)) + { + /* Insert 0 */ + j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size()); + stack.push_back(0); + #if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); + #else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; + #endif + stack[j]=allocate(ifree,stock,nes[q]); + /* Insert 1 */ + j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size()); + stack.push_back(0); + #if DBVT_USE_MEMMOVE + memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1)); + #else + for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1]; + #endif + stack[j]=allocate(ifree,stock,nes[1-q]); + } + else + { + stack.push_back(allocate(ifree,stock,nes[q])); + stack.push_back(allocate(ifree,stock,nes[1-q])); + } + } + else + { + policy.Process(se.node,se.value); + } + } + } while(stack.size()); + } +} + +// +DBVT_PREFIX +inline void btDbvt::collideTU( const btDbvtNode* root, + DBVT_IPOLICY) +{ +DBVT_CHECKTYPE +if(root) + { + btAlignedObjectArray stack; + stack.reserve(SIMPLE_STACKSIZE); + stack.push_back(root); + do { + const btDbvtNode* n=stack[stack.size()-1]; + stack.pop_back(); + if(policy.Descent(n)) + { + if(n->isinternal()) + { stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); } + else + { policy.Process(n); } + } + } while(stack.size()>0); + } +} + +// +// PP Cleanup +// + +#undef DBVT_USE_MEMMOVE +#undef DBVT_USE_TEMPLATE +#undef DBVT_VIRTUAL_DTOR +#undef DBVT_VIRTUAL +#undef DBVT_PREFIX +#undef DBVT_IPOLICY +#undef DBVT_CHECKTYPE +#undef DBVT_IMPL_GENERIC +#undef DBVT_IMPL_SSE +#undef DBVT_USE_INTRINSIC_SSE +#undef DBVT_SELECT_IMPL +#undef DBVT_MERGE_IMPL +#undef DBVT_INT0_IMPL + +#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp new file mode 100644 index 00000000000..fd82fd7cae3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -0,0 +1,547 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvtBroadphase implementation by Nathanael Presson + +#include "btDbvtBroadphase.h" + +// +// Profiling +// + +#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK +#include +#endif + +#if DBVT_BP_PROFILE +struct ProfileScope + { + __forceinline ProfileScope(btClock& clock,unsigned long& value) : + m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds()) + { + } + __forceinline ~ProfileScope() + { + (*m_value)+=m_clock->getTimeMicroseconds()-m_base; + } + btClock* m_clock; + unsigned long* m_value; + unsigned long m_base; + }; +#define SPC(_value_) ProfileScope spc_scope(m_clock,_value_) +#else +#define SPC(_value_) +#endif + +// +// Helpers +// + +// +template +static inline void listappend(T* item,T*& list) +{ +item->links[0]=0; +item->links[1]=list; +if(list) list->links[0]=item; +list=item; +} + +// +template +static inline void listremove(T* item,T*& list) +{ +if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1]; +if(item->links[1]) item->links[1]->links[0]=item->links[0]; +} + +// +template +static inline int listcount(T* root) +{ +int n=0; +while(root) { ++n;root=root->links[1]; } +return(n); +} + +// +template +static inline void clear(T& value) +{ +static const struct ZeroDummy : T {} zerodummy; +value=zerodummy; +} + +// +// Colliders +// + +/* Tree collider */ +struct btDbvtTreeCollider : btDbvt::ICollide +{ +btDbvtBroadphase* pbp; +btDbvtProxy* proxy; + btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} +void Process(const btDbvtNode* na,const btDbvtNode* nb) + { + if(na!=nb) + { + btDbvtProxy* pa=(btDbvtProxy*)na->data; + btDbvtProxy* pb=(btDbvtProxy*)nb->data; + #if DBVT_BP_SORTPAIRS + if(pa>pb) btSwap(pa,pb); + #endif + pbp->m_paircache->addOverlappingPair(pa,pb); + ++pbp->m_newpairs; + } + } +void Process(const btDbvtNode* n) + { + Process(n,proxy->leaf); + } +}; + +// +// btDbvtBroadphase +// + +// +btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) +{ +m_deferedcollide = false; +m_needcleanup = true; +m_releasepaircache = (paircache!=0)?false:true; +m_prediction = 1/(btScalar)2; +m_stageCurrent = 0; +m_fixedleft = 0; +m_fupdates = 1; +m_dupdates = 0; +m_cupdates = 10; +m_newpairs = 1; +m_updates_call = 0; +m_updates_done = 0; +m_updates_ratio = 0; +m_paircache = paircache? + paircache : + new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); +m_gid = 0; +m_pid = 0; +m_cid = 0; +for(int i=0;i<=STAGECOUNT;++i) + { + m_stageRoots[i]=0; + } +#if DBVT_BP_PROFILE +clear(m_profiling); +#endif +} + +// +btDbvtBroadphase::~btDbvtBroadphase() +{ +if(m_releasepaircache) +{ + m_paircache->~btOverlappingPairCache(); + btAlignedFree(m_paircache); +} +} + +// +btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, + const btVector3& aabbMax, + int /*shapeType*/, + void* userPtr, + short int collisionFilterGroup, + short int collisionFilterMask, + btDispatcher* dispatcher, + void* /*multiSapProxy*/) +{ +btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr, + collisionFilterGroup, + collisionFilterMask); +proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); +proxy->stage = m_stageCurrent; +proxy->m_uniqueId = ++m_gid; +proxy->leaf = m_sets[0].insert(proxy->aabb,proxy); +listappend(proxy,m_stageRoots[m_stageCurrent]); +if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + collider.proxy=proxy; + btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider); + } +return(proxy); +} + +// +void btDbvtBroadphase::destroyProxy( btBroadphaseProxy* absproxy, + btDispatcher* dispatcher) +{ +btDbvtProxy* proxy=(btDbvtProxy*)absproxy; +if(proxy->stage==STAGECOUNT) + m_sets[1].remove(proxy->leaf); + else + m_sets[0].remove(proxy->leaf); +listremove(proxy,m_stageRoots[proxy->stage]); +m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); +btAlignedFree(proxy); +m_needcleanup=true; +} + +// +void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, + const btVector3& aabbMin, + const btVector3& aabbMax, + btDispatcher* /*dispatcher*/) +{ +btDbvtProxy* proxy=(btDbvtProxy*)absproxy; +ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); +#if DBVT_BP_PREVENTFALSEUPDATE +if(NotEqual(aabb,proxy->leaf->volume)) +#endif + { + bool docollide=false; + if(proxy->stage==STAGECOUNT) + {/* fixed -> dynamic set */ + m_sets[1].remove(proxy->leaf); + proxy->leaf=m_sets[0].insert(aabb,proxy); + docollide=true; + } + else + {/* dynamic set */ + ++m_updates_call; + if(Intersect(proxy->leaf->volume,aabb)) + {/* Moving */ + const btVector3 delta=aabbMin-proxy->aabb.Mins(); + btVector3 velocity(aabb.Extents()*m_prediction); + if(delta[0]<0) velocity[0]=-velocity[0]; + if(delta[1]<0) velocity[1]=-velocity[1]; + if(delta[2]<0) velocity[2]=-velocity[2]; + if ( + #ifdef DBVT_BP_MARGIN + m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN) + #else + m_sets[0].update(proxy->leaf,aabb,velocity) + #endif + ) + { + ++m_updates_done; + docollide=true; + } + } + else + {/* Teleporting */ + m_sets[0].update(proxy->leaf,aabb); + ++m_updates_done; + docollide=true; + } + } + listremove(proxy,m_stageRoots[proxy->stage]); + proxy->aabb = aabb; + proxy->stage = m_stageCurrent; + listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) + { + m_needcleanup=true; + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + btDbvt::collideTT(m_sets[1].m_root,proxy->leaf,collider); + btDbvt::collideTT(m_sets[0].m_root,proxy->leaf,collider); + } + } + } +} + +// +void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ +collide(dispatcher); +#if DBVT_BP_PROFILE +if(0==(m_pid%DBVT_BP_PROFILING_RATE)) + { + printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs()); + unsigned int total=m_profiling.m_total; + if(total<=0) total=1; + printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE); + printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE); + printf("cleanup: %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE); + printf("total: %uus\r\n",total/DBVT_BP_PROFILING_RATE); + const unsigned long sum=m_profiling.m_ddcollide+ + m_profiling.m_fdcollide+ + m_profiling.m_cleanup; + printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE); + printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE)); + clear(m_profiling); + m_clock.reset(); + } +#endif +} + +// +void btDbvtBroadphase::collide(btDispatcher* dispatcher) +{ +SPC(m_profiling.m_total); +/* optimize */ +m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); +if(m_fixedleft) + { + const int count=1+(m_sets[1].m_leaves*m_fupdates)/100; + m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); + m_fixedleft=btMax(0,m_fixedleft-count); + } +/* dynamic -> fixed set */ +m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; +btDbvtProxy* current=m_stageRoots[m_stageCurrent]; +if(current) + { + btDbvtTreeCollider collider(this); + do { + btDbvtProxy* next=current->links[1]; + listremove(current,m_stageRoots[current->stage]); + listappend(current,m_stageRoots[STAGECOUNT]); + #if DBVT_BP_ACCURATESLEEPING + m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher); + collider.proxy=current; + btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider); + btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider); + #endif + m_sets[0].remove(current->leaf); + current->leaf = m_sets[1].insert(current->aabb,current); + current->stage = STAGECOUNT; + current = next; + } while(current); + m_fixedleft=m_sets[1].m_leaves; + m_needcleanup=true; + } +/* collide dynamics */ + { + btDbvtTreeCollider collider(this); + if(m_deferedcollide) + { + SPC(m_profiling.m_fdcollide); + btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider); + } + if(m_deferedcollide) + { + SPC(m_profiling.m_ddcollide); + btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider); + } + } +/* clean up */ +if(m_needcleanup) + { + SPC(m_profiling.m_cleanup); + btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); + if(pairs.size()>0) + { + const int ci=pairs.size(); + int ni=btMin(ci,btMax(m_newpairs,(ci*m_cupdates)/100)); + for(int i=0;ileaf->volume,pb->leaf->volume)) + { + #if DBVT_BP_SORTPAIRS + if(pa>pb) btSwap(pa,pb); + #endif + m_paircache->removeOverlappingPair(pa,pb,dispatcher); + --ni;--i; + } + } + if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0; + } + } +++m_pid; +m_newpairs=1; +m_needcleanup=false; +if(m_updates_call>0) + { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; } + else + { m_updates_ratio=0; } +m_updates_done/=2; +m_updates_call/=2; +} + +// +void btDbvtBroadphase::optimize() +{ +m_sets[0].optimizeTopDown(); +m_sets[1].optimizeTopDown(); +} + +// +btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() +{ +return(m_paircache); +} + +// +const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const +{ +return(m_paircache); +} + +// +void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const +{ + + ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds; + +if(!m_sets[0].empty()) + if(!m_sets[1].empty()) Merge( m_sets[0].m_root->volume, + m_sets[1].m_root->volume,bounds); + else + bounds=m_sets[0].m_root->volume; +else if(!m_sets[1].empty()) bounds=m_sets[1].m_root->volume; + else + bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0); +aabbMin=bounds.Mins(); +aabbMax=bounds.Maxs(); +} + +// +void btDbvtBroadphase::printStats() +{} + +// +#if DBVT_BP_ENABLE_BENCHMARK + +struct btBroadphaseBenchmark + { + struct Experiment + { + const char* name; + int object_count; + int update_count; + int spawn_count; + int iterations; + btScalar speed; + btScalar amplitude; + }; + struct Object + { + btVector3 center; + btVector3 extents; + btBroadphaseProxy* proxy; + btScalar time; + void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi) + { + time += speed; + center[0] = btCos(time*(btScalar)2.17)*amplitude+ + btSin(time)*amplitude/2; + center[1] = btCos(time*(btScalar)1.38)*amplitude+ + btSin(time)*amplitude; + center[2] = btSin(time*(btScalar)0.777)*amplitude; + pbi->setAabb(proxy,center-extents,center+extents,0); + } + }; + static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); } + static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); } + static void OutputTime(const char* name,btClock& c,unsigned count=0) + { + const unsigned long us=c.getTimeMicroseconds(); + const unsigned long ms=(us+500)/1000; + const btScalar sec=us/(btScalar)(1000*1000); + if(count>0) + printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec); + else + printf("%s : %u us (%u ms)\r\n",name,us,ms); + } + }; + +void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi) +{ +static const btBroadphaseBenchmark::Experiment experiments[]= + { + {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100}, + /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100}, + {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/ + }; +static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]); +btAlignedObjectArray objects; +btClock wallclock; +/* Begin */ +for(int iexp=0;iexpcenter[0]=btBroadphaseBenchmark::UnitRand()*50; + po->center[1]=btBroadphaseBenchmark::UnitRand()*50; + po->center[2]=btBroadphaseBenchmark::UnitRand()*50; + po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2; + po->time=btBroadphaseBenchmark::UnitRand()*2000; + po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0); + objects.push_back(po); + } + btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock); + /* First update */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock); + /* Updates */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + pbi->calculateOverlappingPairs(0); + } + btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations); + /* Clean up */ + wallclock.reset(); + for(int i=0;idestroyProxy(objects[i]->proxy,0); + delete objects[i]; + } + objects.resize(0); + btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); + } + +} +#else +void btDbvtBroadphase::benchmark(btBroadphaseInterface*) +{} +#endif + +#if DBVT_BP_PROFILE +#undef SPC +#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h new file mode 100644 index 00000000000..4576e48f3f4 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -0,0 +1,117 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btDbvtBroadphase implementation by Nathanael Presson +#ifndef BT_DBVT_BROADPHASE_H +#define BT_DBVT_BROADPHASE_H + +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" + +// +// Compile time config +// + +#define DBVT_BP_PROFILE 0 +#define DBVT_BP_SORTPAIRS 1 +#define DBVT_BP_PREVENTFALSEUPDATE 0 +#define DBVT_BP_ACCURATESLEEPING 0 +#define DBVT_BP_ENABLE_BENCHMARK 0 +#define DBVT_BP_MARGIN (btScalar)0.05 + +#if DBVT_BP_PROFILE + #define DBVT_BP_PROFILING_RATE 256 + #include "LinearMath/btQuickprof.h" +#endif + +// +// btDbvtProxy +// +struct btDbvtProxy : btBroadphaseProxy +{ +/* Fields */ +btDbvtAabbMm aabb; +btDbvtNode* leaf; +btDbvtProxy* links[2]; +int stage; +/* ctor */ +btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : + btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask) + { + links[0]=links[1]=0; + } +}; + +typedef btAlignedObjectArray btDbvtProxyArray; + +///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt). +///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other. +///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3. +struct btDbvtBroadphase : btBroadphaseInterface +{ +/* Config */ +enum { + DYNAMIC_SET = 0, /* Dynamic set index */ + FIXED_SET = 1, /* Fixed set index */ + STAGECOUNT = 2 /* Number of stages */ + }; +/* Fields */ +btDbvt m_sets[2]; // Dbvt sets +btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list +btOverlappingPairCache* m_paircache; // Pair cache +btScalar m_prediction; // Velocity prediction +int m_stageCurrent; // Current stage +int m_fupdates; // % of fixed updates per frame +int m_dupdates; // % of dynamic updates per frame +int m_cupdates; // % of cleanup updates per frame +int m_newpairs; // Number of pairs created +int m_fixedleft; // Fixed optimization left +unsigned m_updates_call; // Number of updates call +unsigned m_updates_done; // Number of updates done +btScalar m_updates_ratio; // m_updates_done/m_updates_call +int m_pid; // Parse id +int m_cid; // Cleanup index +int m_gid; // Gen id +bool m_releasepaircache; // Release pair cache on delete +bool m_deferedcollide; // Defere dynamic/static collision to collide call +bool m_needcleanup; // Need to run cleanup? +bool m_initialize; // Initialization +#if DBVT_BP_PROFILE +btClock m_clock; +struct { + unsigned long m_total; + unsigned long m_ddcollide; + unsigned long m_fdcollide; + unsigned long m_cleanup; + unsigned long m_jobcount; + } m_profiling; +#endif +/* Methods */ +btDbvtBroadphase(btOverlappingPairCache* paircache=0); +~btDbvtBroadphase(); +void collide(btDispatcher* dispatcher); +void optimize(); +/* btBroadphaseInterface Implementation */ +btBroadphaseProxy* createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy); +void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); +void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher); +void calculateOverlappingPairs(btDispatcher* dispatcher); +btOverlappingPairCache* getOverlappingPairCache(); +const btOverlappingPairCache* getOverlappingPairCache() const; +void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; +void printStats(); +static void benchmark(btBroadphaseInterface*); +}; + +#endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h index 3d958cc8fef..6db71a0170e 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDispatcher.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef _DISPATCHER_H #define _DISPATCHER_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" class btCollisionAlgorithm; struct btBroadphaseProxy; @@ -43,7 +43,9 @@ struct btDispatcherInfo m_useContinuous(false), m_debugDraw(0), m_enableSatConvex(false), - m_enableSPU(false), + m_enableSPU(true), + m_useEpa(true), + m_allowedCcdPenetration(btScalar(0.04)), m_stackAllocator(0) { @@ -51,17 +53,19 @@ struct btDispatcherInfo btScalar m_timeStep; int m_stepCount; int m_dispatchFunc; - btScalar m_timeOfImpact; + mutable btScalar m_timeOfImpact; bool m_useContinuous; class btIDebugDraw* m_debugDraw; bool m_enableSatConvex; bool m_enableSPU; + bool m_useEpa; + btScalar m_allowedCcdPenetration; btStackAlloc* m_stackAllocator; }; -/// btDispatcher can be used in combination with broadphase to dispatch overlapping pairs. -/// For example for pairwise collision detection or user callbacks (game logic). +///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs. +///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic). class btDispatcher { @@ -81,12 +85,18 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0; - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo)=0; + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) =0; virtual int getNumManifolds() const = 0; virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0; + virtual btPersistentManifold** getInternalManifoldPointer() = 0; + + virtual void* allocateCollisionAlgorithm(int size) = 0; + + virtual void freeCollisionAlgorithm(void* ptr) = 0; + }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp new file mode 100644 index 00000000000..3f866ab7c5f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp @@ -0,0 +1,466 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btMultiSapBroadphase.h" + +#include "btSimpleBroadphase.h" +#include "LinearMath/btAabbUtil2.h" +#include "btQuantizedBvh.h" + +/// btSapBroadphaseArray m_sapBroadphases; + +/// btOverlappingPairCache* m_overlappingPairs; +extern int gOverlappingPairs; + +/* +class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache +{ +public: + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy); + } +}; + +*/ + +btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache) +:m_overlappingPairs(pairCache), +m_optimizedAabbTree(0), +m_ownsPairCache(false), +m_invalidPair(0) +{ + if (!m_overlappingPairs) + { + m_ownsPairCache = true; + void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16); + m_overlappingPairs = new (mem)btSortedOverlappingPairCache(); + } + + struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback + { + virtual ~btMultiSapOverlapFilterCallback() + {} + // return true when pairs need collision + virtual bool needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const + { + btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy; + btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy; + + bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0; + collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask); + + return collides; + } + }; + + void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16); + m_filterCallback = new (mem)btMultiSapOverlapFilterCallback(); + + m_overlappingPairs->setOverlapFilterCallback(m_filterCallback); +// mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16); +// m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs); +} + +btMultiSapBroadphase::~btMultiSapBroadphase() +{ + if (m_ownsPairCache) + { + m_overlappingPairs->~btOverlappingPairCache(); + btAlignedFree(m_overlappingPairs); + } +} + + +void btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) +{ + m_optimizedAabbTree = new btQuantizedBvh(); + m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax); + QuantizedNodeArray& nodes = m_optimizedAabbTree->getLeafNodeArray(); + for (int i=0;igetBroadphaseAabb(aabbMin,aabbMax); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + int partId = 0; + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i; + nodes.push_back(node); + } + m_optimizedAabbTree->buildInternal(); +} + +btBroadphaseProxy* btMultiSapBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/) +{ + //void* ignoreMe -> we could think of recursive multi-sap, if someone is interested + + void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16); + btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin, aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask); + m_multiSapProxies.push_back(proxy); + + ///this should deal with inserting/removal into child broadphases + setAabb(proxy,aabbMin,aabbMax,dispatcher); + return proxy; +} + +void btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) +{ + ///not yet + btAssert(0); + +} + + +void btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase) +{ + void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16); + btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy; + bridgeProxyRef->m_childProxy = childProxy; + bridgeProxyRef->m_childBroadphase = childBroadphase; + parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef); +} + + +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax); +bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax) +{ +return +amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() && +amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() && +amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ(); +} + + + + + + +//#include + +void btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher) +{ + btMultiSapProxy* multiProxy = static_cast(proxy); + multiProxy->m_aabbMin = aabbMin; + multiProxy->m_aabbMax = aabbMax; + + +// bool fullyContained = false; +// bool alreadyInSimple = false; + + + + + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btMultiSapBroadphase* m_multiSap; + btMultiSapProxy* m_multiProxy; + btDispatcher* m_dispatcher; + + MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher) + :m_multiSap(multiSap), + m_multiProxy(multiProxy), + m_dispatcher(dispatcher) + { + + } + + virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex) + { + btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex]; + + int containingBroadphaseIndex = -1; + //already found? + for (int i=0;im_bridgeProxies.size();i++) + { + + if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + break; + } + } + if (containingBroadphaseIndex<0) + { + //add it + btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy); + m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase); + + } + } + }; + + MyNodeOverlapCallback myNodeCallback(this,multiProxy,dispatcher); + + + + + m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax); + int i; + + for ( i=0;im_bridgeProxies.size();i++) + { + btVector3 worldAabbMin,worldAabbMax; + multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + if (!overlapsBroadphase) + { + //remove it now + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + + } + } + + + /* + + if (1) + { + + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;igetBroadphaseAabb(worldAabbMin,worldAabbMax); + bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + + // fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax); + int containingBroadphaseIndex = -1; + + //if already contains this + + for (int i=0;im_bridgeProxies.size();i++) + { + if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase) + { + containingBroadphaseIndex = i; + } + alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase); + } + + if (overlapsBroadphase) + { + if (containingBroadphaseIndex<0) + { + btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,childBroadphase); + } + } else + { + if (containingBroadphaseIndex>=0) + { + //remove + btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex]; + + btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy; + bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher); + + multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1); + multiProxy->m_bridgeProxies.pop_back(); + } + } + } + + + ///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force) + ///hopefully we don't end up with many entries here (can assert/provide feedback on stats) + if (0)//!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } + } + + if (!multiProxy->m_bridgeProxies.size()) + { + ///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision + ///this is needed to be able to calculate the aabb overlap + btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher); + childProxy->m_multiSapParentProxy = multiProxy; + addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase); + } +*/ + + + //update + for ( i=0;im_bridgeProxies.size();i++) + { + btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i]; + bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher); + } + +} +bool stopUpdating=false; + + + +class btMultiSapBroadphasePairSortPredicate +{ + public: + + bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 ) + { + btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0; + + return aProxy0 > bProxy0 || + (aProxy0 == bProxy0 && aProxy1 > bProxy1) || + (aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); + } +}; + + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb +void btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) +{ + +// m_simpleBroadphase->calculateOverlappingPairs(dispatcher); + + if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray(); + + // quicksort(overlappingPairArray,0,overlappingPairArray.size()); + + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + // overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + int i; + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;im_multiSapParentProxy : 0; + btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0; + btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0; + + bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1); + + previousPair = pair; + + bool needsRemoval = false; + + if (!isDuplicate) + { + bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1); + + if (hasOverlap) + { + needsRemoval = false;//callback->processOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: + #define CLEAN_INVALID_PAIRS 1 + #ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + //overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate()); + overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + #endif//CLEAN_INVALID_PAIRS + + //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size()); + } + + +} + + +bool btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) +{ + btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy; + btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy; + + return TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax, + multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax); + +} + + +void btMultiSapBroadphase::printStats() +{ +/* printf("---------------------------------\n"); + + printf("btMultiSapBroadphase.h\n"); + printf("numHandles = %d\n",m_multiSapProxies.size()); + //find broadphase that contain this multiProxy + int numChildBroadphases = getBroadphaseArray().size(); + for (int i=0;iprintStats(); + + } + */ + +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h new file mode 100644 index 00000000000..a0c002de856 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h @@ -0,0 +1,144 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BT_MULTI_SAP_BROADPHASE +#define BT_MULTI_SAP_BROADPHASE + +#include "btBroadphaseInterface.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCache.h" + + +class btBroadphaseInterface; +class btSimpleBroadphase; + + +typedef btAlignedObjectArray btSapBroadphaseArray; + +///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases. +///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time. +///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy. +///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328 +///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329 +class btMultiSapBroadphase :public btBroadphaseInterface +{ + btSapBroadphaseArray m_sapBroadphases; + + btSimpleBroadphase* m_simpleBroadphase; + + btOverlappingPairCache* m_overlappingPairs; + + class btQuantizedBvh* m_optimizedAabbTree; + + + bool m_ownsPairCache; + + btOverlapFilterCallback* m_filterCallback; + + int m_invalidPair; + + struct btBridgeProxy + { + btBroadphaseProxy* m_childProxy; + btBroadphaseInterface* m_childBroadphase; + }; + + +public: + + struct btMultiSapProxy : public btBroadphaseProxy + { + + ///array with all the entries that this proxy belongs to + btAlignedObjectArray m_bridgeProxies; + btVector3 m_aabbMin; + btVector3 m_aabbMax; + + int m_shapeType; + +/* void* m_userPtr; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; +*/ + btMultiSapProxy(const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask) + :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), + m_aabbMin(aabbMin), + m_aabbMax(aabbMax), + m_shapeType(shapeType) + { + m_multiSapParentProxy =this; + } + + + }; + +protected: + + + btAlignedObjectArray m_multiSapProxies; + +public: + + btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0); + + + btSapBroadphaseArray& getBroadphaseArray() + { + return m_sapBroadphases; + } + + const btSapBroadphaseArray& getBroadphaseArray() const + { + return m_sapBroadphases; + } + + virtual ~btMultiSapBroadphase(); + + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); + + void addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface* childBroadphase); + + ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + virtual btOverlappingPairCache* getOverlappingPairCache() + { + return m_overlappingPairs; + } + virtual const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_overlappingPairs; + } + + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-1e30f,-1e30f,-1e30f); + aabbMax.setValue(1e30f,1e30f,1e30f); + } + + void buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + + virtual void printStats(); + + void quicksort (btBroadphasePairArray& a, int lo, int hi); + +}; + +#endif //BT_MULTI_SAP_BROADPHASE diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp index 60f0a41a9d7..ff65cdde79f 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp @@ -1,4 +1,3 @@ - /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -21,44 +20,43 @@ subject to the following restrictions: #include "btDispatcher.h" #include "btCollisionAlgorithm.h" +#include + int gOverlappingPairs = 0; -btOverlappingPairCache::btOverlappingPairCache(): -m_blockedForChanges(false), -m_overlapFilterCallback(0) -//m_NumOverlapBroadphasePair(0) +int gRemovePairs =0; +int gAddedPairs =0; +int gFindPairs =0; + + + + +btHashedOverlappingPairCache::btHashedOverlappingPairCache(): + m_overlapFilterCallback(0), + m_blockedForChanges(false) { + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); + growTables(); } -btOverlappingPairCache::~btOverlappingPairCache() + + +btHashedOverlappingPairCache::~btHashedOverlappingPairCache() { //todo/test: show we erase/delete data, or is it automatic } -void btOverlappingPairCache::removeOverlappingPair(btBroadphasePair& findPair) -{ - - int findIndex = m_overlappingPairArray.findLinearSearch(findPair); - if (findIndex < m_overlappingPairArray.size()) - { - gOverlappingPairs--; - btBroadphasePair& pair = m_overlappingPairArray[findIndex]; - cleanOverlappingPair(pair); - - m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.size()-1); - m_overlappingPairArray.pop_back(); - } -} - -void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) +void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) { if (pair.m_algorithm) { { - delete pair.m_algorithm;; + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); pair.m_algorithm=0; } } @@ -67,60 +65,20 @@ void btOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair) - -void btOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - //don't add overlap with own - assert(proxy0 != proxy1); - - if (!needsBroadphaseCollision(proxy0,proxy1)) - return; - - - btBroadphasePair pair(*proxy0,*proxy1); - - m_overlappingPairArray.push_back(pair); - gOverlappingPairs++; - -} - -///this findPair becomes really slow. Either sort the list to speedup the query, or -///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. -///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) -///Also we can use a 2D bitmap, which can be useful for a future GPU implementation - btBroadphasePair* btOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) -{ - if (!needsBroadphaseCollision(proxy0,proxy1)) - return 0; - - btBroadphasePair tmpPair(*proxy0,*proxy1); - int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); - - if (findIndex < m_overlappingPairArray.size()) - { - //assert(it != m_overlappingPairSet.end()); - btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; - return pair; - } - return 0; -} - - - - - -void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) +void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) { class CleanPairCallback : public btOverlapCallback { btBroadphaseProxy* m_cleanProxy; btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; public: - CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache) + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :m_cleanProxy(cleanProxy), - m_pairCache(pairCache) + m_pairCache(pairCache), + m_dispatcher(dispatcher) { } virtual bool processOverlap(btBroadphasePair& pair) @@ -128,22 +86,23 @@ void btOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy) if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { - m_pairCache->cleanOverlappingPair(pair); + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); } return false; } }; - CleanPairCallback cleanPairs(proxy,this); + CleanPairCallback cleanPairs(proxy,this,dispatcher); - processAllOverlappingPairs(&cleanPairs); + processAllOverlappingPairs(&cleanPairs,dispatcher); } -void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy) + +void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) { class RemovePairCallback : public btOverlapCallback @@ -166,12 +125,346 @@ void btOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseP RemovePairCallback removeCallback(proxy); - processAllOverlappingPairs(&removeCallback); + processAllOverlappingPairs(&removeCallback,dispatcher); } -void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback) + + +btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + gFindPairs++; + if(proxy0>proxy1) btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1), static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + if (hash >= m_hashTable.size()) + { + return NULL; + } + + int index = m_hashTable[hash]; + while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if (index == BT_NULL_PAIR) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; +} + +//#include + +void btHashedOverlappingPairCache::growTables() +{ + + int newCapacity = m_overlappingPairArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_NULL_PAIR; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_NULL_PAIR; + } + + for(i=0;igetUid(); + int proxyId2 = pair.m_pProxy1->getUid(); + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + int hashValue = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + m_next[i] = m_hashTable[hashValue]; + m_hashTable[hashValue] = i; + } + + + } +} + +btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) +{ + if(proxy0>proxy1) btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); // New hash value with new mask + + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair != NULL) + { + return pair; + } + /*for(int i=0;i%u\r\n",proxyId1,proxyId2); + internalFindPair(proxy0, proxy1, hash); + } + }*/ + int count = m_overlappingPairArray.size(); + int oldCapacity = m_overlappingPairArray.capacity(); + void* mem = &m_overlappingPairArray.expand(); + int newCapacity = m_overlappingPairArray.capacity(); + + if (oldCapacity < newCapacity) + { + growTables(); + //hash with new capacity + hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + } + + pair = new (mem) btBroadphasePair(*proxy0,*proxy1); +// pair->m_pProxy0 = proxy0; +// pair->m_pProxy1 = proxy1; + pair->m_algorithm = 0; + pair->m_userInfo = 0; + + + m_next[count] = m_hashTable[hash]; + m_hashTable[hash] = count; + + return pair; +} + + + +void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher) +{ + gRemovePairs++; + if(proxy0>proxy1) btSwap(proxy0,proxy1); + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + + /*if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2);*/ + + int hash = static_cast(getHash(static_cast(proxyId1),static_cast(proxyId2)) & (m_overlappingPairArray.capacity()-1)); + + btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash); + if (pair == NULL) + { + return 0; + } + + cleanOverlappingPair(*pair,dispatcher); + + void* userData = pair->m_userInfo; + + btAssert(pair->m_pProxy0->getUid() == proxyId1); + btAssert(pair->m_pProxy1->getUid() == proxyId2); + + int pairIndex = int(pair - &m_overlappingPairArray[0]); + btAssert(pairIndex < m_overlappingPairArray.size()); + + // Remove the pair from the hash table. + int index = m_hashTable[hash]; + btAssert(index != BT_NULL_PAIR); + + int previous = BT_NULL_PAIR; + while (index != pairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == pairIndex); + m_next[previous] = m_next[pairIndex]; + } + else + { + m_hashTable[hash] = m_next[pairIndex]; + } + + // We now move the last pair into spot of the + // pair being removed. We need to fix the hash + // table indices to support the move. + + int lastPairIndex = m_overlappingPairArray.size() - 1; + + // If the removed pair is the last pair, we are done. + if (lastPairIndex == pairIndex) + { + m_overlappingPairArray.pop_back(); + return userData; + } + + // Remove the last pair from the hash table. + const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex]; + /* missing swap here too, Nat. */ + int lastHash = static_cast(getHash(static_cast(last->m_pProxy0->getUid()), static_cast(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1)); + + index = m_hashTable[lastHash]; + btAssert(index != BT_NULL_PAIR); + + previous = BT_NULL_PAIR; + while (index != lastPairIndex) + { + previous = index; + index = m_next[index]; + } + + if (previous != BT_NULL_PAIR) + { + btAssert(m_next[previous] == lastPairIndex); + m_next[previous] = m_next[lastPairIndex]; + } + else + { + m_hashTable[lastHash] = m_next[lastPairIndex]; + } + + // Copy the last pair into the remove pair's spot. + m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex]; + + // Insert the last pair into the hash table + m_next[pairIndex] = m_hashTable[lastHash]; + m_hashTable[lastHash] = pairIndex; + + m_overlappingPairArray.pop_back(); + + return userData; +} +//#include + +void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) +{ + + int i; + +// printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size()); + for (i=0;iprocessOverlap(*pair)) + { + removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher); + + gOverlappingPairs--; + } else + { + i++; + } + } +} + + + +void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher ) +{ + if (!hasDeferredRemoval()) + { + btBroadphasePair findPair(*proxy0,*proxy1); + + int findIndex = m_overlappingPairArray.findLinearSearch(findPair); + if (findIndex < m_overlappingPairArray.size()) + { + gOverlappingPairs--; + btBroadphasePair& pair = m_overlappingPairArray[findIndex]; + void* userData = pair.m_userInfo; + cleanOverlappingPair(pair,dispatcher); + + m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1); + m_overlappingPairArray.pop_back(); + return userData; + } + } + + return 0; +} + + + + + + + + +btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + //don't add overlap with own + assert(proxy0 != proxy1); + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + void* mem = &m_overlappingPairArray.expand(); + btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1); + gOverlappingPairs++; + gAddedPairs++; + return pair; + +} + +///this findPair becomes really slow. Either sort the list to speedup the query, or +///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed. +///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address) +///Also we can use a 2D bitmap, which can be useful for a future GPU implementation + btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + btBroadphasePair tmpPair(*proxy0,*proxy1); + int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair); + + if (findIndex < m_overlappingPairArray.size()) + { + //assert(it != m_overlappingPairSet.end()); + btBroadphasePair* pair = &m_overlappingPairArray[findIndex]; + return pair; + } + return 0; +} + + + + + + + + + + +//#include + +void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher) { int i; @@ -182,9 +475,9 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb btBroadphasePair* pair = &m_overlappingPairArray[i]; if (callback->processOverlap(*pair)) { - cleanOverlappingPair(*pair); + cleanOverlappingPair(*pair,dispatcher); - m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + m_overlappingPairArray.swap(i,m_overlappingPairArray.capacity()-1); m_overlappingPairArray.pop_back(); gOverlappingPairs--; } else @@ -194,3 +487,93 @@ void btOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callb } } + + + +btSortedOverlappingPairCache::btSortedOverlappingPairCache(): + m_blockedForChanges(false), + m_hasDeferredRemoval(true), + m_overlapFilterCallback(0) +{ + int initialAllocatedSize= 2; + m_overlappingPairArray.reserve(initialAllocatedSize); +} + +btSortedOverlappingPairCache::~btSortedOverlappingPairCache() +{ + //todo/test: show we erase/delete data, or is it automatic +} + +void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) +{ + if (pair.m_algorithm) + { + { + pair.m_algorithm->~btCollisionAlgorithm(); + dispatcher->freeCollisionAlgorithm(pair.m_algorithm); + pair.m_algorithm=0; + gRemovePairs--; + } + } +} + + +void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class CleanPairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_cleanProxy; + btOverlappingPairCache* m_pairCache; + btDispatcher* m_dispatcher; + + public: + CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + if ((pair.m_pProxy0 == m_cleanProxy) || + (pair.m_pProxy1 == m_cleanProxy)) + { + m_pairCache->cleanOverlappingPair(pair,m_dispatcher); + } + return false; + } + + }; + + CleanPairCallback cleanPairs(proxy,this,dispatcher); + + processAllOverlappingPairs(&cleanPairs,dispatcher); + +} + + +void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher) +{ + + class RemovePairCallback : public btOverlapCallback + { + btBroadphaseProxy* m_obsoleteProxy; + + public: + RemovePairCallback(btBroadphaseProxy* obsoleteProxy) + :m_obsoleteProxy(obsoleteProxy) + { + } + virtual bool processOverlap(btBroadphasePair& pair) + { + return ((pair.m_pProxy0 == m_obsoleteProxy) || + (pair.m_pProxy1 == m_obsoleteProxy)); + } + + }; + + RemovePairCallback removeCallback(proxy); + + processAllOverlappingPairs(&removeCallback,dispatcher); +} diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h index a81fe3264df..66679bd218a 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h @@ -1,4 +1,3 @@ - /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -20,9 +19,13 @@ subject to the following restrictions: #include "btBroadphaseInterface.h" #include "btBroadphaseProxy.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "btOverlappingPairCallback.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; + +typedef btAlignedObjectArray btBroadphasePairArray; struct btOverlapCallback { @@ -30,6 +33,7 @@ struct btOverlapCallback {} //return true for deletion of the pair virtual bool processOverlap(btBroadphasePair& pair) = 0; + }; struct btOverlapFilterCallback @@ -40,38 +44,261 @@ struct btOverlapFilterCallback virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0; }; -///btOverlappingPairCache maintains the objects with overlapping AABB + + + + + + +extern int gRemovePairs; +extern int gAddedPairs; +extern int gFindPairs; + +const int BT_NULL_PAIR=0xffffffff; + +///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases. +///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations. +class btOverlappingPairCache : public btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor + + virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0; + + virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0; + + virtual btBroadphasePairArray& getOverlappingPairArray() = 0; + + virtual void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0; + + virtual int getNumOverlappingPairs() const = 0; + + virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0; + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0; + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0; + + virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0; + + virtual bool hasDeferredRemoval() = 0; + +}; + +/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com +class btHashedOverlappingPairCache : public btOverlappingPairCache +{ + btBroadphasePairArray m_overlappingPairArray; + btOverlapFilterCallback* m_overlapFilterCallback; + bool m_blockedForChanges; + + +public: + btHashedOverlappingPairCache(); + virtual ~btHashedOverlappingPairCache(); + + + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); + + SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const + { + if (m_overlapFilterCallback) + return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1); + + bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0; + collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask); + + return collides; + } + + // Add a pair and return the new pair. If the pair already exists, + // no new pair is created and the old one is returned. + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) + { + gAddedPairs++; + + if (!needsBroadphaseCollision(proxy0,proxy1)) + return 0; + + return internalAddPair(proxy0,proxy1); + } + + + + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); + + + + btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1); + + int GetCount() const { return m_overlappingPairArray.size(); } +// btBroadphasePair* GetPairs() { return m_pairs; } + + btOverlapFilterCallback* getOverlapFilterCallback() + { + return m_overlapFilterCallback; + } + + void setOverlapFilterCallback(btOverlapFilterCallback* callback) + { + m_overlapFilterCallback = callback; + } + + int getNumOverlappingPairs() const + { + return m_overlappingPairArray.size(); + } +private: + + btBroadphasePair* internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + + void growTables(); + + SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2) + { + return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2; + } + + /* + // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm + // This assumes proxyId1 and proxyId2 are 16-bit. + SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2) + { + int key = (proxyId2 << 16) | proxyId1; + key = ~key + (key << 15); + key = key ^ (key >> 12); + key = key + (key << 2); + key = key ^ (key >> 4); + key = key * 2057; + key = key ^ (key >> 16); + return key; + } + */ + + + + SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2) + { + int key = static_cast(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16)); + // Thomas Wang's hash + + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return static_cast(key); + } + + + + + + SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash) + { + int proxyId1 = proxy0->getUid(); + int proxyId2 = proxy1->getUid(); + #if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat. + if (proxyId1 > proxyId2) + btSwap(proxyId1, proxyId2); + #endif + + int index = m_hashTable[hash]; + + while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false) + { + index = m_next[index]; + } + + if ( index == BT_NULL_PAIR ) + { + return NULL; + } + + btAssert(index < m_overlappingPairArray.size()); + + return &m_overlappingPairArray[index]; + } + + virtual bool hasDeferredRemoval() + { + return false; + } + +public: + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + +}; + + + + +///btSortedOverlappingPairCache maintains the objects with overlapping AABB ///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase -class btOverlappingPairCache : public btBroadphaseInterface +class btSortedOverlappingPairCache : public btOverlappingPairCache { protected: //avoid brute-force finding all the time - btAlignedObjectArray m_overlappingPairArray; - + btBroadphasePairArray m_overlappingPairArray; + //during the dispatch, check that user doesn't destroy/create proxy bool m_blockedForChanges; + + ///by default, do the removal during the pair traversal + bool m_hasDeferredRemoval; //if set, use the callback instead of the built in filter in needBroadphaseCollision btOverlapFilterCallback* m_overlapFilterCallback; + public: - btOverlappingPairCache(); - virtual ~btOverlappingPairCache(); + btSortedOverlappingPairCache(); + virtual ~btSortedOverlappingPairCache(); - virtual void processAllOverlappingPairs(btOverlapCallback*); + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher); - void removeOverlappingPair(btBroadphasePair& pair); + void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher); - void cleanOverlappingPair(btBroadphasePair& pair); + void cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher); - void addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); btBroadphasePair* findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); - void cleanProxyFromPairs(btBroadphaseProxy* proxy); + void cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher); - void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy); + void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const @@ -84,10 +311,19 @@ class btOverlappingPairCache : public btBroadphaseInterface return collides; } - + + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + const btBroadphasePairArray& getOverlappingPairArray() const + { + return m_overlappingPairArray; + } + - virtual void refreshOverlappingPairs() =0; btBroadphasePair* getOverlappingPairArrayPtr() { @@ -114,7 +350,88 @@ class btOverlappingPairCache : public btBroadphaseInterface m_overlapFilterCallback = callback; } + virtual bool hasDeferredRemoval() + { + return m_hasDeferredRemoval; + } + + }; + + + +///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and testing. +class btNullPairCache : public btOverlappingPairCache +{ + + btBroadphasePairArray m_overlappingPairArray; + +public: + + virtual btBroadphasePair* getOverlappingPairArrayPtr() + { + return &m_overlappingPairArray[0]; + } + const btBroadphasePair* getOverlappingPairArrayPtr() const + { + return &m_overlappingPairArray[0]; + } + btBroadphasePairArray& getOverlappingPairArray() + { + return m_overlappingPairArray; + } + + virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual int getNumOverlappingPairs() const + { + return 0; + } + + virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/) + { + + } + + virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/) + { + } + + virtual void processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/) + { + } + + virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual bool hasDeferredRemoval() + { + return true; + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/) + { + return 0; + } + + virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/) + { + return 0; + } + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/) + { + } + + +}; + + #endif //OVERLAPPING_PAIR_CACHE_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h new file mode 100644 index 00000000000..9c7b6f81367 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h @@ -0,0 +1,40 @@ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef OVERLAPPING_PAIR_CALLBACK_H +#define OVERLAPPING_PAIR_CALLBACK_H + +class btDispatcher; +struct btBroadphasePair; + +///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache. +class btOverlappingPairCallback +{ +public: + virtual ~btOverlappingPairCallback() + { + + } + + virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0; + + virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0; + + virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0; + +}; + +#endif //OVERLAPPING_PAIR_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp new file mode 100644 index 00000000000..a30bd1fd9e1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp @@ -0,0 +1,1025 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btQuantizedBvh.h" + +#include "LinearMath/btAabbUtil2.h" +#include "LinearMath/btIDebugDraw.h" + + +btQuantizedBvh::btQuantizedBvh() : m_useQuantization(false), + //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) + m_traversalMode(TRAVERSAL_STACKLESS) + //m_traversalMode(TRAVERSAL_RECURSIVE) + ,m_subtreeHeaderCount(0) //PCK: add this line +{ + +} + + + + + +void btQuantizedBvh::buildInternal() +{ + ///assumes that caller filled in the m_quantizedLeafNodes + m_useQuantization = true; + int numLeafNodes = 0; + + if (m_useQuantization) + { + //now we have an array of leafnodes in m_leafNodes + numLeafNodes = m_quantizedLeafNodes.size(); + + m_quantizedContiguousNodes.resize(2*numLeafNodes); + + } + + m_curNodeIndex = 0; + + buildTree(0,numLeafNodes); + + ///if the entire tree is small then subtree size, we need to create a header info for the tree + if(m_useQuantization && !m_SubtreeHeaders.size()) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]); + subtree.m_rootNodeIndex = 0; + subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); +} + + + +///just for debugging, to visualize the individual patches/subtrees +#ifdef DEBUG_PATCH_COLORS +btVector3 color[4]= +{ + btVector3(255,0,0), + btVector3(0,255,0), + btVector3(0,0,255), + btVector3(0,255,255) +}; +#endif //DEBUG_PATCH_COLORS + + + +void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +{ + //enlarge the AABB to avoid division by zero when initializing the quantization values + btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); + m_bvhAabbMin = bvhAabbMin - clampValue; + m_bvhAabbMax = bvhAabbMax + clampValue; + btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; + m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize; + m_useQuantization = true; +} + + + + +btQuantizedBvh::~btQuantizedBvh() +{ +} + +#ifdef DEBUG_TREE_BUILDING +int gStackDepth = 0; +int gMaxStackDepth = 0; +#endif //DEBUG_TREE_BUILDING + +void btQuantizedBvh::buildTree (int startIndex,int endIndex) +{ +#ifdef DEBUG_TREE_BUILDING + gStackDepth++; + if (gStackDepth > gMaxStackDepth) + gMaxStackDepth = gStackDepth; +#endif //DEBUG_TREE_BUILDING + + + int splitAxis, splitIndex, i; + int numIndices =endIndex-startIndex; + int curIndex = m_curNodeIndex; + + assert(numIndices>0); + + if (numIndices==1) + { +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); + + m_curNodeIndex++; + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + splitAxis = calcSplittingAxis(startIndex,endIndex); + + splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); + + int internalNodeIndex = m_curNodeIndex; + + setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin); + setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax); + + for (i=startIndex;im_escapeIndex; + + int leftChildNodexIndex = m_curNodeIndex; + + //build left child tree + buildTree(startIndex,splitIndex); + + int rightChildNodexIndex = m_curNodeIndex; + //build right child tree + buildTree(splitIndex,endIndex); + +#ifdef DEBUG_TREE_BUILDING + gStackDepth--; +#endif //DEBUG_TREE_BUILDING + + int escapeIndex = m_curNodeIndex - curIndex; + + if (m_useQuantization) + { + //escapeIndex is the number of nodes of this subtree + const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); + const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; + if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) + { + updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); + } + } + + setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); + +} + +void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) +{ + btAssert(m_useQuantization); + + btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; + int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); + int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; + int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); + int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast(sizeof(btQuantizedBvhNode)); + + if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(leftChildNode); + subtree.m_rootNodeIndex = leftChildNodexIndex; + subtree.m_subtreeSize = leftSubTreeSize; + } + + if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) + { + btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); + subtree.setAabbFromQuantizeNode(rightChildNode); + subtree.m_rootNodeIndex = rightChildNodexIndex; + subtree.m_subtreeSize = rightSubTreeSize; + } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); +} + + +int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) +{ + int i; + int splitIndex =startIndex; + int numIndices = endIndex - startIndex; + btScalar splitValue; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + for (i=startIndex;i splitValue) + { + //swap + swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + (void)unbal; + btAssert(!unbal); + + return splitIndex; +} + + +int btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex) +{ + int i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + int numIndices = endIndex-startIndex; + + for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); + isLeafNode = rootNode->m_escapeIndex == -1; + + //PCK: unsigned instead of bool + if (isLeafNode && (aabbOverlap != 0)) + { + nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->m_escapeIndex; + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +/* +///this was the original recursive traversal, before we optimized towards stackless traversal +void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); + if (aabbOverlap) + { + isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); + if (isLeafNode) + { + nodeCallback->processNode(rootNode); + } else + { + walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); + walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); + } + } + +} +*/ + +void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); + isLeafNode = currentNode->isLeafNode(); + + //PCK: unsigned instead of bool + if (aabbOverlap != 0) + { + if (isLeafNode) + { + nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex()); + } else + { + //process left and right children + const btQuantizedBvhNode* leftChildNode = currentNode+1; + walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + + const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); + walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); + } + } +} + + + + + +void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned boxBoxOverlap = 0; + unsigned rayBoxOverlap = 0; + + btScalar lambda_max = 1.0; +#define RAYAABB2 +#ifdef RAYAABB2 + btVector3 rayFrom = raySource; + btVector3 rayDirection = (rayTarget-raySource); + rayDirection.normalize (); + lambda_max = rayDirection.dot(rayTarget-raySource); + ///what about division by zero? --> just set rayDirection[i] to 1.0 + rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[0]; + rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[1]; + rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDirection[2]; + unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0}; +#endif + + /* Quick pruning by quantized box */ + btVector3 rayAabbMin = raySource; + btVector3 rayAabbMax = raySource; + rayAabbMin.setMin(rayTarget); + rayAabbMax.setMax(rayTarget); + + /* Add box cast extents to bounding box */ + rayAabbMin += aabbMin; + rayAabbMax += aabbMax; + + unsigned short int quantizedQueryAabbMin[3]; + unsigned short int quantizedQueryAabbMax[3]; + quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0); + quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1); + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + assert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + // only interested if this is closer than any previous hit + btScalar param = 1.0; + rayBoxOverlap = 0; + boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + if (boxBoxOverlap) + { + btVector3 bounds[2]; + bounds[0] = unQuantize(rootNode->m_quantizedAabbMin); + bounds[1] = unQuantize(rootNode->m_quantizedAabbMax); + /* Add box cast extents */ + bounds[0] += aabbMin; + bounds[1] += aabbMax; + btVector3 normal; +#if 0 + bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max); + bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal); + if (ra2 != ra) + { + printf("functions don't match\n"); + } +#endif +#ifdef RAYAABB2 + ///careful with this check: need to check division by zero (above) and fix the unQuantize method + ///thanks Joerg/hiker for the reproduction case! + ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858 + + rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max); +#else + rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal); +#endif + } + + if (isLeafNode && rayBoxOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((rayBoxOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const +{ + btAssert(m_useQuantization); + + int curIndex = startNodeIndex; + int walkIterations = 0; + int subTreeSize = endNodeIndex - startNodeIndex; + (void)subTreeSize; + + const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; + int escapeIndex; + + bool isLeafNode; + //PCK: unsigned instead of bool + unsigned aabbOverlap; + + while (curIndex < endNodeIndex) + { + +//#define VISUALLY_ANALYZE_BVH 1 +#ifdef VISUALLY_ANALYZE_BVH + //some code snippet to debugDraw aabb, to visually analyze bvh structure + static int drawPatch = 0; + //need some global access to a debugDrawer + extern btIDebugDraw* debugDrawerPtr; + if (curIndex==drawPatch) + { + btVector3 aabbMin,aabbMax; + aabbMin = unQuantize(rootNode->m_quantizedAabbMin); + aabbMax = unQuantize(rootNode->m_quantizedAabbMax); + btVector3 color(1,0,0); + debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); + } +#endif//VISUALLY_ANALYZE_BVH + + //catch bugs in tree data + assert (walkIterations < subTreeSize); + + walkIterations++; + //PCK: unsigned instead of bool + aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); + isLeafNode = rootNode->isLeafNode(); + + if (isLeafNode && aabbOverlap) + { + nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex()); + } + + //PCK: unsigned instead of bool + if ((aabbOverlap != 0) || isLeafNode) + { + rootNode++; + curIndex++; + } else + { + escapeIndex = rootNode->getEscapeIndex(); + rootNode += escapeIndex; + curIndex += escapeIndex; + } + } + if (maxIterations < walkIterations) + maxIterations = walkIterations; + +} + +//This traversal can be called from Playstation 3 SPU +void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const +{ + btAssert(m_useQuantization); + + int i; + + + for (i=0;im_SubtreeHeaders.size();i++) + { + const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; + + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) + { + walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, + subtree.m_rootNodeIndex, + subtree.m_rootNodeIndex+subtree.m_subtreeSize); + } + } +} + + +void btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const +{ + bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS; + if (fast_path) + { + walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0), 0, m_curNodeIndex); + } else { + /* Otherwise fallback to AABB overlap test */ + btVector3 aabbMin = raySource; + btVector3 aabbMax = raySource; + aabbMin.setMin(rayTarget); + aabbMax.setMax(rayTarget); + reportAabbOverlappingNodex(nodeCallback,aabbMin,aabbMax); + } +} + + +void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const +{ + bool fast_path = m_useQuantization && m_traversalMode == TRAVERSAL_STACKLESS; + if (fast_path) + { + walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex); + } else { + /* Slow path: + Construct the bounding box for the entire box cast and send that down the tree */ + btVector3 qaabbMin = raySource; + btVector3 qaabbMax = raySource; + qaabbMin.setMin(rayTarget); + qaabbMax.setMax(rayTarget); + qaabbMin += aabbMin; + qaabbMax += aabbMax; + reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax); + } +} + + +void btQuantizedBvh::swapLeafNodes(int i,int splitIndex) +{ + if (m_useQuantization) + { + btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; + m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; + m_quantizedLeafNodes[splitIndex] = tmp; + } else + { + btOptimizedBvhNode tmp = m_leafNodes[i]; + m_leafNodes[i] = m_leafNodes[splitIndex]; + m_leafNodes[splitIndex] = tmp; + } +} + +void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) +{ + if (m_useQuantization) + { + m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; + } else + { + m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; + } +} + +//PCK: include +#include + +//PCK: consts +static const unsigned BVH_ALIGNMENT = 16; +static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1; + +static const unsigned BVH_ALIGNMENT_BLOCKS = 2; + + + +unsigned int btQuantizedBvh::getAlignmentSerializationPadding() +{ + return BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT; +} + +unsigned btQuantizedBvh::calculateSerializeBufferSize() +{ + unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding(); + baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + if (m_useQuantization) + { + return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode); + } + return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode); +} + +bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) +{ + assert(m_subtreeHeaderCount == m_SubtreeHeaders.size()); + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + +/* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + ///check alignedment for buffer? + btAssert(0); + return false; + } +*/ + + btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer; + + // construct the class so the virtual function table, etc will be set up + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (targetBvh) btQuantizedBvh; + + if (i_swapEndian) + { + targetBvh->m_curNodeIndex = static_cast(btSwapEndian(m_curNodeIndex)); + + + btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin); + btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax); + btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization); + + targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode); + targetBvh->m_subtreeHeaderCount = static_cast(btSwapEndian(m_subtreeHeaderCount)); + } + else + { + targetBvh->m_curNodeIndex = m_curNodeIndex; + targetBvh->m_bvhAabbMin = m_bvhAabbMin; + targetBvh->m_bvhAabbMax = m_bvhAabbMax; + targetBvh->m_bvhQuantization = m_bvhQuantization; + targetBvh->m_traversalMode = m_traversalMode; + targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount; + } + + targetBvh->m_useQuantization = m_useQuantization; + + unsigned char *nodeData = (unsigned char *)targetBvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = m_curNodeIndex; + + if (m_useQuantization) + { + targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]; + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]; + + targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex; + + + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex)); + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart)); + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + else + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg; + targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg; + + targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex; + targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart; + targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex; + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex)); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize)); + } + } + else + { + for (int i = 0; i < m_subtreeHeaderCount; i++) + { + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex); + targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize); + targetBvh->m_SubtreeHeaders[i] = m_SubtreeHeaders[i]; + } + } + + nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount; + + return true; +} + +btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) +{ + + if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0)) + { + return NULL; + } + btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer; + + if (i_swapEndian) + { + bvh->m_curNodeIndex = static_cast(btSwapEndian(bvh->m_curNodeIndex)); + + btUnSwapVector3Endian(bvh->m_bvhAabbMin); + btUnSwapVector3Endian(bvh->m_bvhAabbMax); + btUnSwapVector3Endian(bvh->m_bvhQuantization); + + bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode); + bvh->m_subtreeHeaderCount = static_cast(btSwapEndian(bvh->m_subtreeHeaderCount)); + } + + unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize(); + btAssert(calculatedBufSize <= i_dataBufferSize); + + if (calculatedBufSize > i_dataBufferSize) + { + return NULL; + } + + unsigned char *nodeData = (unsigned char *)bvh; + nodeData += sizeof(btQuantizedBvh); + + unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + int nodeCount = bvh->m_curNodeIndex; + + // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor + // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor + new (bvh) btQuantizedBvh(*bvh, false); + + if (bvh->m_useQuantization) + { + bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]); + bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]); + + bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex)); + } + } + nodeData += sizeof(btQuantizedBvhNode) * nodeCount; + } + else + { + bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount); + + if (i_swapEndian) + { + for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg); + btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg); + + bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex)); + bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart)); + bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex)); + } + } + nodeData += sizeof(btOptimizedBvhNode) * nodeCount; + } + + sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK; + nodeData += sizeToAdd; + + // Now serialize the subtree headers + bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount); + if (i_swapEndian) + { + for (int i = 0; i < bvh->m_subtreeHeaderCount; i++) + { + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]); + + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]); + bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]); + + bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex)); + bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize)); + } + } + + return bvh; +} + +// Constructor that prevents btVector3's default constructor from being called +btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) : +m_bvhAabbMin(self.m_bvhAabbMin), +m_bvhAabbMax(self.m_bvhAabbMax), +m_bvhQuantization(self.m_bvhQuantization) +{ + + +} + + + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h new file mode 100644 index 00000000000..8a149b533fa --- /dev/null +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btQuantizedBvh.h @@ -0,0 +1,486 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef QUANTIZED_BVH_H +#define QUANTIZED_BVH_H + +//#define DEBUG_CHECK_DEQUANTIZATION 1 +#ifdef DEBUG_CHECK_DEQUANTIZATION +#ifdef __SPU__ +#define printf spu_printf +#endif //__SPU__ + +#include +#include +#endif //DEBUG_CHECK_DEQUANTIZATION + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedAllocator.h" + + +//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp + + +//Note: currently we have 16 bytes per quantized node +#define MAX_SUBTREE_SIZE_IN_BYTES 2048 + +// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one +// actually) triangles each (since the sign bit is reserved +#define MAX_NUM_PARTS_IN_BITS 10 + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrTriangleIndex; + + bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrTriangleIndex >= 0); + } + int getEscapeIndex() const + { + btAssert(!isLeafNode()); + return -m_escapeIndexOrTriangleIndex; + } + int getTriangleIndex() const + { + btAssert(isLeafNode()); + // Get only the lower bits where the triangle index is stored + return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS))); + } + int getPartId() const + { + btAssert(isLeafNode()); + // Get only the highest bits where the part index is stored + return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS)); + } +} +; + +/// btOptimizedBvhNode contains both internal and leaf node information. +/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. +ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //32 bytes + btVector3 m_aabbMinOrg; + btVector3 m_aabbMaxOrg; + + //4 + int m_escapeIndex; + + //8 + //for child nodes + int m_subPart; + int m_triangleIndex; + int m_padding[5];//bad, due to alignment + + +}; + + +///btBvhSubtreeInfo provides info to gather a subtree of limited size +ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo +{ +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes, points to the root of the subtree + int m_rootNodeIndex; + //4 bytes + int m_subtreeSize; + int m_padding[3]; + + btBvhSubtreeInfo() + { + //memset(&m_padding[0], 0, sizeof(m_padding)); + } + + + void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) + { + m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; + m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; + m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; + m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; + m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; + m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; + } +} +; + + +class btNodeOverlapCallback +{ +public: + virtual ~btNodeOverlapCallback() {}; + + virtual void processNode(int subPart, int triangleIndex) = 0; +}; + +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btAlignedObjectArray.h" + + + +///for code readability: +typedef btAlignedObjectArray NodeArray; +typedef btAlignedObjectArray QuantizedNodeArray; +typedef btAlignedObjectArray BvhSubtreeInfoArray; + + +///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU. +///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase. +///It is recommended to use quantization for better performance and lower memory requirements. +ATTRIBUTE_ALIGNED16(class) btQuantizedBvh +{ +protected: + + NodeArray m_leafNodes; + NodeArray m_contiguousNodes; + + QuantizedNodeArray m_quantizedLeafNodes; + + QuantizedNodeArray m_quantizedContiguousNodes; + + int m_curNodeIndex; + + + //quantization data + bool m_useQuantization; + btVector3 m_bvhAabbMin; + btVector3 m_bvhAabbMax; + btVector3 m_bvhQuantization; +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + enum btTraversalMode + { + TRAVERSAL_STACKLESS = 0, + TRAVERSAL_STACKLESS_CACHE_FRIENDLY, + TRAVERSAL_RECURSIVE + }; +protected: + + btTraversalMode m_traversalMode; + + BvhSubtreeInfoArray m_SubtreeHeaders; + + //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray + int m_subtreeHeaderCount; + + + ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) + ///this might be refactored into a virtual, it is usually not calculated at run-time + void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; + + } + } + void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) + { + if (m_useQuantization) + { + quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1); + } else + { + m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; + } + } + + btVector3 getAabbMin(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMinOrg; + + } + btVector3 getAabbMax(int nodeIndex) const + { + if (m_useQuantization) + { + return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); + } + //non-quantized + return m_leafNodes[nodeIndex].m_aabbMaxOrg; + + } + + + void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) + { + if (m_useQuantization) + { + m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; + } + else + { + m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; + } + + } + + void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) + { + if (m_useQuantization) + { + unsigned short int quantizedAabbMin[3]; + unsigned short int quantizedAabbMax[3]; + quantize(quantizedAabbMin,newAabbMin,0); + quantize(quantizedAabbMax,newAabbMax,1); + for (int i=0;i<3;i++) + { + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; + + if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) + m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; + + } + } else + { + //non-quantized + m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); + m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); + } + } + + void swapLeafNodes(int firstIndex,int secondIndex); + + void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + +protected: + + + + void buildTree (int startIndex,int endIndex); + + int calcSplittingAxis(int startIndex,int endIndex); + + int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); + + void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const; + void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; + + ///tree traversal designed for small-memory processors like PS3 SPU + void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; + + ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal + void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; + + +#define USE_BANCHLESS 1 +#ifdef USE_BANCHLESS + //This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360) + SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + return static_cast(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) + & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) + & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])), + 1, 0)); + } +#else + SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const + { + bool overlap = true; + overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; + overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; + overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; + return overlap; + } +#endif //USE_BANCHLESS + + void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); + +public: + btQuantizedBvh(); + + virtual ~btQuantizedBvh(); + + + ///***************************************** expert/internal use only ************************* + void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); + QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; } + ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized + void buildInternal(); + ///***************************************** expert/internal use only ************************* + + void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; + void reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const; + void reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const; + + SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const + { + + btAssert(m_useQuantization); + + btAssert(point.getX() <= m_bvhAabbMax.getX()); + btAssert(point.getY() <= m_bvhAabbMax.getY()); + btAssert(point.getZ() <= m_bvhAabbMax.getZ()); + + btAssert(point.getX() >= m_bvhAabbMin.getX()); + btAssert(point.getY() >= m_bvhAabbMin.getY()); + btAssert(point.getZ() >= m_bvhAabbMin.getZ()); + + btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization; + ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative + ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly) + ///todo: double-check this + if (isMax) + { + out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1)); + out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1)); + } else + { + out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe)); + out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe)); + out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe)); + } + + +#ifdef DEBUG_CHECK_DEQUANTIZATION + btVector3 newPoint = unQuantize(out); + if (isMax) + { + if (newPoint.getX() < point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() < point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() < point.getZ()) + { + + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } else + { + if (newPoint.getX() > point.getX()) + { + printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX()); + } + if (newPoint.getY() > point.getY()) + { + printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY()); + } + if (newPoint.getZ() > point.getZ()) + { + printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ()); + } + } +#endif //DEBUG_CHECK_DEQUANTIZATION + + } + + + SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const + { + + btAssert(m_useQuantization); + + btVector3 clampedPoint(point2); + clampedPoint.setMax(m_bvhAabbMin); + clampedPoint.setMin(m_bvhAabbMax); + + quantize(out,clampedPoint,isMax); + + } + + SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const + { + btVector3 vecOut; + vecOut.setValue( + (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), + (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), + (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); + vecOut += m_bvhAabbMin; + return vecOut; + } + + ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. + void setTraversalMode(btTraversalMode traversalMode) + { + m_traversalMode = traversalMode; + } + + + SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray() + { + return m_quantizedContiguousNodes; + } + + + SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray() + { + return m_SubtreeHeaders; + } + + + /////Calculate space needed to store BVH for serialization + unsigned calculateSerializeBufferSize(); + + /// Data buffer MUST be 16 byte aligned + virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian); + + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + static unsigned int getAlignmentSerializationPadding(); + + SIMD_FORCE_INLINE bool isQuantized() + { + return m_useQuantization; + } + +private: + // Special "copy" constructor that allows for in-place deserialization + // Prevents btVector3's default constructor from being called, but doesn't inialize much else + // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need) + btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory); + +} +; + + +#endif //QUANTIZED_BVH_H diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index 30bcbe0c5f1..a57952ffa06 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -14,83 +14,84 @@ subject to the following restrictions: */ #include "btSimpleBroadphase.h" -#include -#include +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" #include "LinearMath/btMatrix3x3.h" #include +extern int gOverlappingPairs; void btSimpleBroadphase::validate() { - for (int i=0;i=0;i--) + if (m_ownsPairCache) { - BP_Proxy* proxy = m_pProxies[i]; - destroyProxy(proxy); + m_pairCache->~btOverlappingPairCache(); + btAlignedFree(m_pairCache); } - */ } -btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask) +btBroadphaseProxy* btSimpleBroadphase::createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy) { - if (m_numProxies >= m_maxProxies) + if (m_numHandles >= m_maxHandles) { - assert(0); + btAssert(0); return 0; //should never happen, but don't let the game crash ;-) } - assert(min[0]<= max[0] && min[1]<= max[1] && min[2]<= max[2]); + assert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]); - int freeIndex= m_freeProxies[m_firstFreeProxy]; - btSimpleBroadphaseProxy* proxy = new (&m_proxies[freeIndex])btSimpleBroadphaseProxy(min,max,shapeType,userPtr,collisionFilterGroup,collisionFilterMask); - m_firstFreeProxy++; - - btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; - - int index = int(proxy - proxy1); - btAssert(index == freeIndex); - - m_pProxies[m_numProxies] = proxy; - m_numProxies++; - //validate(); + int newHandleIndex = allocHandle(); + btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy); return proxy; } @@ -124,34 +125,19 @@ protected: }; }; -void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg) +void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher) { - int i; - btSimpleBroadphaseProxy* proxy0 = static_cast(proxyOrg); - btSimpleBroadphaseProxy* proxy1 = &m_proxies[0]; - - int index = int(proxy0 - proxy1); - btAssert (index < m_maxProxies); - m_freeProxies[--m_firstFreeProxy] = index; + freeHandle(proxy0); + + m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher); - removeOverlappingPairsContainingProxy(proxyOrg); - - for (i=0;im_min = aabbMin; @@ -186,37 +172,129 @@ public: } }; -void btSimpleBroadphase::refreshOverlappingPairs() +void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) { //first check for new overlapping pairs int i,j; - for (i=0;i= 0) { - btBroadphaseProxy* proxy0 = m_pProxies[i]; - for (j=i+1;jfindPair(proxy0,proxy1)) + { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } else + { + if (!m_pairCache->hasDeferredRemoval()) + { + if ( m_pairCache->findPair(proxy0,proxy1)) + { + m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); + } + } } } + } + + if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) + { + + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); + + //perform a sort, to find duplicates and to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; + + + btBroadphasePair previousPair; + previousPair.m_pProxy0 = 0; + previousPair.m_pProxy1 = 0; + previousPair.m_algorithm = 0; + + + for (i=0;iprocessOverlap(pair); + } else + { + needsRemoval = true; + } + } else + { + //remove duplicate + needsRemoval = true; + //should have no algorithm + btAssert(!pair.m_algorithm); + } + + if (needsRemoval) + { + m_pairCache->cleanOverlappingPair(pair,dispatcher); + + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); + pair.m_pProxy0 = 0; + pair.m_pProxy1 = 0; + m_invalidPair++; + gOverlappingPairs--; + } + + } + + ///if you don't like to skip the invalid pairs in the array, execute following code: +#define CLEAN_INVALID_PAIRS 1 +#ifdef CLEAN_INVALID_PAIRS + + //perform a sort, to sort 'invalid' pairs to the end + overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); + + overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); + m_invalidPair = 0; +#endif//CLEAN_INVALID_PAIRS } } - - - CheckOverlapCallback checkOverlap; - - processAllOverlappingPairs(&checkOverlap); - - } +bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) +{ + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + return aabbOverlap(p0,p1); +} + + + diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index fb155e7047c..e2ebb825725 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -24,35 +24,69 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy { btVector3 m_min; btVector3 m_max; + int m_nextFree; + +// int m_handleId; + btSimpleBroadphaseProxy() {}; - btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask) - :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask), + btSimpleBroadphaseProxy(const btPoint3& minpt,const btPoint3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy) + :btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy), m_min(minpt),m_max(maxpt) { (void)shapeType; } + + SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} + SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} + + + }; -///SimpleBroadphase is a brute force aabb culling broadphase based on O(n^2) aabb checks -class btSimpleBroadphase : public btOverlappingPairCache +///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead. +///It is a brute force aabb culling broadphase based on O(n^2) aabb checks +class btSimpleBroadphase : public btBroadphaseInterface { protected: - btSimpleBroadphaseProxy* m_proxies; - int* m_freeProxies; - int m_firstFreeProxy; - - btSimpleBroadphaseProxy** m_pProxies; - int m_numProxies; - + int m_numHandles; // number of active handles + int m_maxHandles; // max number of handles + btSimpleBroadphaseProxy* m_pHandles; // handles pool + + void* m_pHandlesRawPtr; + int m_firstFreeHandle; // free handles list + + int allocHandle() + { + btAssert(m_numHandles < m_maxHandles); + int freeHandle = m_firstFreeHandle; + m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); + m_numHandles++; + return freeHandle; + } + + void freeHandle(btSimpleBroadphaseProxy* proxy) + { + int handle = int(proxy-m_pHandles); + btAssert(handle >= 0 && handle < m_maxHandles); + + proxy->SetNextFree(m_firstFreeHandle); + m_firstFreeHandle = handle; + + m_numHandles--; + } + + btOverlappingPairCache* m_pairCache; + bool m_ownsPairCache; + + int m_invalidPair; - int m_maxProxies; inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) @@ -67,26 +101,48 @@ protected: protected: - virtual void refreshOverlappingPairs(); + + public: - btSimpleBroadphase(int maxProxies=16384); + btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0); virtual ~btSimpleBroadphase(); static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1); - virtual btBroadphaseProxy* createProxy( const btVector3& min, const btVector3& max,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask); + virtual btBroadphaseProxy* createProxy( const btVector3& aabbMin, const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy); + virtual void calculateOverlappingPairs(btDispatcher* dispatcher); - virtual void destroyProxy(btBroadphaseProxy* proxy); - virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax); + virtual void destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher); + virtual void setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher); - - + btOverlappingPairCache* getOverlappingPairCache() + { + return m_pairCache; + } + const btOverlappingPairCache* getOverlappingPairCache() const + { + return m_pairCache; + } + + bool testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1); + ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame + ///will add some transform later + virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin.setValue(-1e30f,-1e30f,-1e30f); + aabbMax.setValue(1e30f,1e30f,1e30f); + } + virtual void printStats() + { +// printf("btSimpleBroadphase.h\n"); +// printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles); + } }; diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt index e565bf7edea..d77ca6444c7 100644 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -5,56 +5,149 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletCollision BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btAxisSweep3.h BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btBroadphaseProxy.h BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btCollisionAlgorithm.h BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btDispatcher.h + BroadphaseCollision/btDbvtBroadphase.cpp + BroadphaseCollision/btDbvtBroadphase.h + BroadphaseCollision/btDbvt.cpp + BroadphaseCollision/btDbvt.h + BroadphaseCollision/btMultiSapBroadphase.cpp + BroadphaseCollision/btMultiSapBroadphase.h BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btOverlappingPairCache.h + BroadphaseCollision/btOverlappingPairCallback.h + BroadphaseCollision/btQuantizedBvh.cpp + BroadphaseCollision/btQuantizedBvh.h BroadphaseCollision/btSimpleBroadphase.cpp + BroadphaseCollision/btSimpleBroadphase.h CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionDispatcher.h CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionObject.h CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCollisionWorld.h CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.h CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.h + CollisionDispatch/btDefaultCollisionConfiguration.cpp + CollisionDispatch/btDefaultCollisionConfiguration.h CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.h + CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxCollisionAlgorithm.h + CollisionDispatch/btBoxBoxDetector.cpp + CollisionDispatch/btBoxBoxDetector.h CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.h + CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + CollisionDispatch/btConvexPlaneCollisionAlgorithm.h + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.h CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.h CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.h CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btManifoldResult.h CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btSimulationIslandManager.h CollisionDispatch/btUnionFind.cpp + CollisionDispatch/btUnionFind.h + CollisionDispatch/SphereTriangleDetector.cpp + CollisionDispatch/SphereTriangleDetector.h CollisionShapes/btBoxShape.cpp + CollisionShapes/btBoxShape.h CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btBvhTriangleMeshShape.h + CollisionShapes/btCapsuleShape.cpp + CollisionShapes/btCapsuleShape.h CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCollisionShape.h CollisionShapes/btCompoundShape.cpp + CollisionShapes/btCompoundShape.h CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConcaveShape.h CollisionShapes/btConeShape.cpp + CollisionShapes/btConeShape.h CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexHullShape.h CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvexShape.h + CollisionShapes/btConvexInternalShape.cpp + CollisionShapes/btConvexInternalShape.h CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btConvexTriangleMeshShape.h CollisionShapes/btCylinderShape.cpp + CollisionShapes/btCylinderShape.h CollisionShapes/btEmptyShape.cpp + CollisionShapes/btEmptyShape.h + CollisionShapes/btHeightfieldTerrainShape.cpp + CollisionShapes/btHeightfieldTerrainShape.h CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMinkowskiSumShape.h + CollisionShapes/btMaterial.h + CollisionShapes/btMultimaterialTriangleMeshShape.cpp + CollisionShapes/btMultimaterialTriangleMeshShape.h CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btMultiSphereShape.h CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btOptimizedBvh.h CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btPolyhedralConvexShape.h + CollisionShapes/btScaledBvhTriangleMeshShape.cpp + CollisionShapes/btScaledBvhTriangleMeshShape.h CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btTetrahedronShape.h CollisionShapes/btSphereShape.cpp + CollisionShapes/btSphereShape.h + CollisionShapes/btShapeHull.h + CollisionShapes/btShapeHull.cpp CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStaticPlaneShape.h CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btStridingMeshInterface.h CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleCallback.h CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleBuffer.h CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleIndexVertexArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.cpp CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMesh.h CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btTriangleMeshShape.h + CollisionShapes/btUniformScalingShape.cpp + CollisionShapes/btUniformScalingShape.h NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btContinuousConvexCollision.h NarrowPhaseCollision/btGjkEpa.cpp + NarrowPhaseCollision/btGjkEpa.h + NarrowPhaseCollision/btGjkEpa2.cpp + NarrowPhaseCollision/btGjkEpa2.h NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btConvexCast.h NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.h NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btGjkPairDetector.h NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btPersistentManifold.h NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btRaycastCallback.h NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.h NarrowPhaseCollision/btVoronoiSimplexSolver.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.h ) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp index 81133670f0c..f6c1e32ac7c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp @@ -26,7 +26,7 @@ m_triangle(triangle) } -void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) { (void)debugDraw; @@ -42,7 +42,16 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact)) { - output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + if (swapResults) + { + btVector3 normalOnB = transformB.getBasis()*normal; + btVector3 normalOnA = -normalOnB; + btVector3 pointOnA = transformB*point+normalOnB*depth; + output.addContactPoint(normalOnA,pointOnA,depth); + } else + { + output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth); + } } } @@ -53,6 +62,8 @@ void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Res // See also geometrictools.com // Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv +btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest); + btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) { btVector3 diff = p - from; btVector3 v = to - from; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h index b32806a6846..26dabaa480e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/SphereTriangleDetector.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_DETECTOR_H #define SPHERE_TRIANGLE_DETECTOR_H -#include "../NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btPoint3.h" +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" +#include "LinearMath/btPoint3.h" class btSphereShape; @@ -28,7 +28,7 @@ class btTriangleShape; /// sphere-triangle to match the btDiscreteCollisionDetectorInterface struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface { - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw); + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp new file mode 100644 index 00000000000..cd0c028012c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp @@ -0,0 +1,85 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btBoxBoxDetector.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf) +{ + if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1); + m_ownManifold = true; + } +} + +btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + +void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + if (!m_manifoldPtr) + return; + + btCollisionObject* col0 = body0; + btCollisionObject* col1 = body1; + btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape(); + btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape(); + + + + /// report a contact. internally this will be kept persistent, and contact reduction is done + resultOut->setPersistentManifold(m_manifoldPtr); +#ifndef USE_PERSISTENT_CONTACTS + m_manifoldPtr->clearManifold(); +#endif //USE_PERSISTENT_CONTACTS + + btDiscreteCollisionDetectorInterface::ClosestPointInput input; + input.m_maximumDistanceSquared = 1e30f; + input.m_transformA = body0->getWorldTransform(); + input.m_transformB = body1->getWorldTransform(); + + btBoxBoxDetector detector(box0,box1); + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + +#ifdef USE_PERSISTENT_CONTACTS + // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } +#endif //USE_PERSISTENT_CONTACTS + +} + +btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h new file mode 100644 index 00000000000..35afaf175a1 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h @@ -0,0 +1,66 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BOX_BOX__COLLISION_ALGORITHM_H +#define BOX_BOX__COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; + +///box-box collision detection +class btBoxBoxCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + +public: + btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btBoxBoxCollisionAlgorithm(); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btBoxBoxCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //BOX_BOX__COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp new file mode 100644 index 00000000000..45ebff5dc45 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp @@ -0,0 +1,683 @@ + +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + Bullet Continuous Collision Detection and Physics Library + Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///ODE box-box collision detection is adapted to work with Bullet + +#include "btBoxBoxDetector.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" + +#include +#include + +btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2) +: m_box1(box1), +m_box2(box2) +{ + +} + + +// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and +// generate contact points. this returns 0 if there is no contact otherwise +// it returns the number of contacts generated. +// `normal' returns the contact normal. +// `depth' returns the maximum penetration depth along that normal. +// `return_code' returns a number indicating the type of contact that was +// detected: +// 1,2,3 = box 2 intersects with a face of box 1 +// 4,5,6 = box 1 intersects with a face of box 2 +// 7..15 = edge-edge contact +// `maxc' is the maximum number of contacts allowed to be generated, i.e. +// the size of the `contact' array. +// `contact' and `skip' are the contact array information provided to the +// collision functions. this function only fills in the position and depth +// fields. +struct dContactGeom; +#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) +#define dInfinity FLT_MAX + + +/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); } +PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); } +PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); } +*/ +static btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); } +static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); } +static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); } +static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); } +#define dMULTIPLYOP1_331(A,op,B,C) \ +{\ + (A)[0] op dDOT41((B),(C)); \ + (A)[1] op dDOT41((B+1),(C)); \ + (A)[2] op dDOT41((B+2),(C)); \ +} + +#define dMULTIPLYOP0_331(A,op,B,C) \ +{ \ + (A)[0] op dDOT((B),(C)); \ + (A)[1] op dDOT((B+4),(C)); \ + (A)[2] op dDOT((B+8),(C)); \ +} + +#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C) +#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) + +typedef btScalar dMatrix3[4*3]; + +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta); +void dLineClosestApproach (const btVector3& pa, const btVector3& ua, + const btVector3& pb, const btVector3& ub, + btScalar *alpha, btScalar *beta) +{ + btVector3 p; + p[0] = pb[0] - pa[0]; + p[1] = pb[1] - pa[1]; + p[2] = pb[2] - pa[2]; + btScalar uaub = dDOT(ua,ub); + btScalar q1 = dDOT(ua,p); + btScalar q2 = -dDOT(ub,p); + btScalar d = 1-uaub*uaub; + if (d <= btScalar(0.0001f)) { + // @@@ this needs to be made more robust + *alpha = 0; + *beta = 0; + } + else { + d = 1.f/d; + *alpha = (q1 + uaub*q2)*d; + *beta = (uaub*q1 + q2)*d; + } +} + + + +// find all the intersection points between the 2D rectangle with vertices +// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]), +// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]). +// +// the intersection points are returned as x,y pairs in the 'ret' array. +// the number of intersection points is returned by the function (this will +// be in the range 0 to 8). + +static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16]) +{ + // q (and r) contain nq (and nr) coordinate points for the current (and + // chopped) polygons + int nq=4,nr=0; + btScalar buffer[16]; + btScalar *q = p; + btScalar *r = ret; + for (int dir=0; dir <= 1; dir++) { + // direction notation: xy[0] = x axis, xy[1] = y axis + for (int sign=-1; sign <= 1; sign += 2) { + // chop q along the line xy[dir] = sign*h[dir] + btScalar *pq = q; + btScalar *pr = r; + nr = 0; + for (int i=nq; i > 0; i--) { + // go through all points in q and all lines between adjacent points + if (sign*pq[dir] < h[dir]) { + // this point is inside the chopping line + pr[0] = pq[0]; + pr[1] = pq[1]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + btScalar *nextq = (i > 1) ? pq+2 : q; + if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) { + // this line crosses the chopping line + pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) / + (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]); + pr[dir] = sign*h[dir]; + pr += 2; + nr++; + if (nr & 8) { + q = r; + goto done; + } + } + pq += 2; + } + q = r; + r = (q==ret) ? buffer : ret; + nq = nr; + } + } + done: + if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar)); + return nr; +} + + +#define M__PI 3.14159265f + +// given n points in the plane (array p, of size 2*n), generate m points that +// best represent the whole set. the definition of 'best' here is not +// predetermined - the idea is to select points that give good box-box +// collision detection behavior. the chosen point indexes are returned in the +// array iret (of size m). 'i0' is always the first entry in the array. +// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be +// in the range [0..n-1]. + +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]); +void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) +{ + // compute the centroid of the polygon in cx,cy + int i,j; + btScalar a,cx,cy,q; + if (n==1) { + cx = p[0]; + cy = p[1]; + } + else if (n==2) { + cx = btScalar(0.5)*(p[0] + p[2]); + cy = btScalar(0.5)*(p[1] + p[3]); + } + else { + a = 0; + cx = 0; + cy = 0; + for (i=0; i<(n-1); i++) { + q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1]; + a += q; + cx += q*(p[i*2]+p[i*2+2]); + cy += q*(p[i*2+1]+p[i*2+3]); + } + q = p[n*2-2]*p[1] - p[0]*p[n*2-1]; + a = 1.f/(btScalar(3.0)*(a+q)); + cx = a*(cx + q*(p[n*2-2]+p[0])); + cy = a*(cy + q*(p[n*2-1]+p[1])); + } + + // compute the angle of each point w.r.t. the centroid + btScalar A[8]; + for (i=0; i M__PI) a -= 2*M__PI; + btScalar maxdiff=1e9,diff; +#if defined(DEBUG) || defined (_DEBUG) + *iret = i0; // iret is not allowed to keep this value +#endif + for (i=0; i M__PI) diff = 2*M__PI - diff; + if (diff < maxdiff) { + maxdiff = diff; + *iret = i; + } + } + } +#if defined(DEBUG) || defined (_DEBUG) + btAssert (*iret != i0); // ensure iret got set +#endif + avail[*iret] = 0; + iret++; + } +} + + + +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output); +int dBoxBox2 (const btVector3& p1, const dMatrix3 R1, + const btVector3& side1, const btVector3& p2, + const dMatrix3 R2, const btVector3& side2, + btVector3& normal, btScalar *depth, int *return_code, + int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output) +{ + const btScalar fudge_factor = btScalar(1.05); + btVector3 p,pp,normalC; + const btScalar *normalR = 0; + btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33, + Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l; + int i,j,invert_normal,code; + + // get vector from centers of box 1 to box 2, relative to box 1 + p = p2 - p1; + dMULTIPLY1_331 (pp,R1,p); // get pp = p relative to body 1 + + // get side lengths / 2 + A[0] = side1[0]*btScalar(0.5); + A[1] = side1[1]*btScalar(0.5); + A[2] = side1[2]*btScalar(0.5); + B[0] = side2[0]*btScalar(0.5); + B[1] = side2[1]*btScalar(0.5); + B[2] = side2[2]*btScalar(0.5); + + // Rij is R1'*R2, i.e. the relative rotation between R1 and R2 + R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2); + R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2); + R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2); + + Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13); + Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23); + Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33); + + // for all 15 possible separating axes: + // * see if the axis separates the boxes. if so, return 0. + // * find the depth of the penetration along the separating axis (s2) + // * if this is the largest depth so far, record it. + // the normal vector will be set to the separating axis with the smallest + // depth. note: normalR is set to point to a column of R1 or R2 if that is + // the smallest depth normal so far. otherwise normalR is 0 and normalC is + // set to a vector relative to body 1. invert_normal is 1 if the sign of + // the normal should be flipped. + +#define TST(expr1,expr2,norm,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > 0) return 0; \ + if (s2 > s) { \ + s = s2; \ + normalR = norm; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } + + s = -dInfinity; + invert_normal = 0; + code = 0; + + // separating axis = u1,u2,u3 + TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1); + TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2); + TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3); + + // separating axis = v1,v2,v3 + TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4); + TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5); + TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6); + + // note: cross product axes need to be scaled when s is computed. + // normal (n1,n2,n3) is relative to box 1. +#undef TST +#define TST(expr1,expr2,n1,n2,n3,cc) \ + s2 = btFabs(expr1) - (expr2); \ + if (s2 > 0) return 0; \ + l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \ + if (l > 0) { \ + s2 /= l; \ + if (s2*fudge_factor > s) { \ + s = s2; \ + normalR = 0; \ + normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \ + invert_normal = ((expr1) < 0); \ + code = (cc); \ + } \ + } + + // separating axis = u1 x (v1,v2,v3) + TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7); + TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8); + TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9); + + // separating axis = u2 x (v1,v2,v3) + TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10); + TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11); + TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12); + + // separating axis = u3 x (v1,v2,v3) + TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13); + TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14); + TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15); + +#undef TST + + if (!code) return 0; + + // if we get to this point, the boxes interpenetrate. compute the normal + // in global coordinates. + if (normalR) { + normal[0] = normalR[0]; + normal[1] = normalR[4]; + normal[2] = normalR[8]; + } + else { + dMULTIPLY0_331 (normal,R1,normalC); + } + if (invert_normal) { + normal[0] = -normal[0]; + normal[1] = -normal[1]; + normal[2] = -normal[2]; + } + *depth = -s; + + // compute contact point(s) + + if (code > 6) { + // an edge from box 1 touches an edge from box 2. + // find a point pa on the intersecting edge of box 1 + btVector3 pa; + btScalar sign; + for (i=0; i<3; i++) pa[i] = p1[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0); + for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j]; + } + + // find a point pb on the intersecting edge of box 2 + btVector3 pb; + for (i=0; i<3; i++) pb[i] = p2[i]; + for (j=0; j<3; j++) { + sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0); + for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j]; + } + + btScalar alpha,beta; + btVector3 ua,ub; + for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4]; + for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4]; + + dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta); + for (i=0; i<3; i++) pa[i] += ua[i]*alpha; + for (i=0; i<3; i++) pb[i] += ub[i]*beta; + + { + + //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]); + //contact[0].depth = *depth; + btVector3 pointInWorld; + +#ifdef USE_CENTER_POINT + for (i=0; i<3; i++) + pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5); + output.addContactPoint(-normal,pointInWorld,-*depth); +#else + output.addContactPoint(-normal,pb,-*depth); +#endif // + *return_code = code; + } + return 1; + } + + // okay, we have a face-something intersection (because the separating + // axis is perpendicular to a face). define face 'a' to be the reference + // face (i.e. the normal vector is perpendicular to this) and face 'b' to be + // the incident face (the closest face of the other box). + + const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb; + if (code <= 3) { + Ra = R1; + Rb = R2; + pa = p1; + pb = p2; + Sa = A; + Sb = B; + } + else { + Ra = R2; + Rb = R1; + pa = p2; + pb = p1; + Sa = B; + Sb = A; + } + + // nr = normal vector of reference face dotted with axes of incident box. + // anr = absolute values of nr. + btVector3 normal2,nr,anr; + if (code <= 3) { + normal2[0] = normal[0]; + normal2[1] = normal[1]; + normal2[2] = normal[2]; + } + else { + normal2[0] = -normal[0]; + normal2[1] = -normal[1]; + normal2[2] = -normal[2]; + } + dMULTIPLY1_331 (nr,Rb,normal2); + anr[0] = btFabs (nr[0]); + anr[1] = btFabs (nr[1]); + anr[2] = btFabs (nr[2]); + + // find the largest compontent of anr: this corresponds to the normal + // for the indident face. the other axis numbers of the indicent face + // are stored in a1,a2. + int lanr,a1,a2; + if (anr[1] > anr[0]) { + if (anr[1] > anr[2]) { + a1 = 0; + lanr = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + else { + if (anr[0] > anr[2]) { + lanr = 0; + a1 = 1; + a2 = 2; + } + else { + a1 = 0; + a2 = 1; + lanr = 2; + } + } + + // compute center point of incident face, in reference-face coordinates + btVector3 center; + if (nr[lanr] < 0) { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr]; + } + else { + for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr]; + } + + // find the normal and non-normal axis numbers of the reference box + int codeN,code1,code2; + if (code <= 3) codeN = code-1; else codeN = code-4; + if (codeN==0) { + code1 = 1; + code2 = 2; + } + else if (codeN==1) { + code1 = 0; + code2 = 2; + } + else { + code1 = 0; + code2 = 1; + } + + // find the four corners of the incident face, in reference-face coordinates + btScalar quad[8]; // 2D coordinate of incident face (x,y pairs) + btScalar c1,c2,m11,m12,m21,m22; + c1 = dDOT14 (center,Ra+code1); + c2 = dDOT14 (center,Ra+code2); + // optimize this? - we have already computed this data above, but it is not + // stored in an easy-to-index format. for now it's quicker just to recompute + // the four dot products. + m11 = dDOT44 (Ra+code1,Rb+a1); + m12 = dDOT44 (Ra+code1,Rb+a2); + m21 = dDOT44 (Ra+code2,Rb+a1); + m22 = dDOT44 (Ra+code2,Rb+a2); + { + btScalar k1 = m11*Sb[a1]; + btScalar k2 = m21*Sb[a1]; + btScalar k3 = m12*Sb[a2]; + btScalar k4 = m22*Sb[a2]; + quad[0] = c1 - k1 - k3; + quad[1] = c2 - k2 - k4; + quad[2] = c1 - k1 + k3; + quad[3] = c2 - k2 + k4; + quad[4] = c1 + k1 + k3; + quad[5] = c2 + k2 + k4; + quad[6] = c1 + k1 - k3; + quad[7] = c2 + k2 - k4; + } + + // find the size of the reference face + btScalar rect[2]; + rect[0] = Sa[code1]; + rect[1] = Sa[code2]; + + // intersect the incident and reference faces + btScalar ret[16]; + int n = intersectRectQuad2 (rect,quad,ret); + if (n < 1) return 0; // this should never happen + + // convert the intersection points into reference-face coordinates, + // and compute the contact position and depth for each point. only keep + // those points that have a positive (penetrating) depth. delete points in + // the 'ret' array as necessary so that 'point' and 'ret' correspond. + btScalar point[3*8]; // penetrating contact points + btScalar dep[8]; // depths for those points + btScalar det1 = 1.f/(m11*m22 - m12*m21); + m11 *= det1; + m12 *= det1; + m21 *= det1; + m22 *= det1; + int cnum = 0; // number of penetrating contact points found + for (j=0; j < n; j++) { + btScalar k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2); + btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2); + for (i=0; i<3; i++) point[cnum*3+i] = + center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2]; + dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3); + if (dep[cnum] >= 0) { + ret[cnum*2] = ret[j*2]; + ret[cnum*2+1] = ret[j*2+1]; + cnum++; + } + } + if (cnum < 1) return 0; // this should never happen + + // we can't generate more contacts than we actually have + if (maxc > cnum) maxc = cnum; + if (maxc < 1) maxc = 1; + + if (cnum <= maxc) { + // we have less contacts than we need, so we use them all + for (j=0; j < cnum; j++) { + + //AddContactPoint... + + //dContactGeom *con = CONTACT(contact,skip*j); + //for (i=0; i<3; i++) con->pos[i] = point[j*3+i] + pa[i]; + //con->depth = dep[j]; + + btVector3 pointInWorld; + for (i=0; i<3; i++) + pointInWorld[i] = point[j*3+i] + pa[i]; + output.addContactPoint(-normal,pointInWorld,-dep[j]); + + } + } + else { + // we have more contacts than are wanted, some of them must be culled. + // find the deepest point, it is always the first contact. + int i1 = 0; + btScalar maxdepth = dep[0]; + for (i=1; i maxdepth) { + maxdepth = dep[i]; + i1 = i; + } + } + + int iret[8]; + cullPoints2 (cnum,ret,maxc,i1,iret); + + for (j=0; j < maxc; j++) { +// dContactGeom *con = CONTACT(contact,skip*j); + // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i]; + // con->depth = dep[iret[j]]; + + btVector3 posInWorld; + for (i=0; i<3; i++) + posInWorld[i] = point[iret[j]*3+i] + pa[i]; + output.addContactPoint(-normal,posInWorld,-dep[iret[j]]); + } + cnum = maxc; + } + + *return_code = code; + return cnum; +} + +void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/) +{ + + const btTransform& transformA = input.m_transformA; + const btTransform& transformB = input.m_transformB; + + int skip = 0; + dContactGeom *contact = 0; + + dMatrix3 R1; + dMatrix3 R2; + + for (int j=0;j<3;j++) + { + R1[0+4*j] = transformA.getBasis()[j].x(); + R2[0+4*j] = transformB.getBasis()[j].x(); + + R1[1+4*j] = transformA.getBasis()[j].y(); + R2[1+4*j] = transformB.getBasis()[j].y(); + + + R1[2+4*j] = transformA.getBasis()[j].z(); + R2[2+4*j] = transformB.getBasis()[j].z(); + + } + + + + btVector3 normal; + btScalar depth; + int return_code; + int maxc = 4; + + + dBoxBox2 (transformA.getOrigin(), + R1, + 2.f*m_box1->getHalfExtentsWithMargin(), + transformB.getOrigin(), + R2, + 2.f*m_box2->getHalfExtentsWithMargin(), + normal, &depth, &return_code, + maxc, contact, skip, + output + ); + +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h new file mode 100644 index 00000000000..605294d47bd --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.h @@ -0,0 +1,44 @@ +/* + * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith + * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. + * All rights reserved. Email: russ@q12.org Web: www.q12.org + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#ifndef BOX_BOX_DETECTOR_H +#define BOX_BOX_DETECTOR_H + + +class btBoxShape; +#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" + + +/// btBoxBoxDetector wraps the ODE box-box collision detector +/// re-distributed under the Zlib license with permission from Russell L. Smith +struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface +{ + btBoxShape* m_box1; + btBoxShape* m_box2; + +public: + + btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2); + + virtual ~btBoxBoxDetector() {}; + + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false); + +}; + +#endif //BT_BOX_BOX_DETECTOR_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h new file mode 100644 index 00000000000..fad770ac26d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionConfiguration.h @@ -0,0 +1,47 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_COLLISION_CONFIGURATION +#define BT_COLLISION_CONFIGURATION +struct btCollisionAlgorithmCreateFunc; + +class btStackAlloc; +class btPoolAllocator; + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator size, default collision algorithms and persistent manifold pool size +///todo: describe the meaning +class btCollisionConfiguration +{ + +public: + + virtual ~btCollisionConfiguration() + { + } + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() = 0; + + virtual btPoolAllocator* getCollisionAlgorithmPool() = 0; + + virtual btStackAlloc* getStackAllocator() = 0; + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0; + +}; + +#endif //BT_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h index d51a59af7f0..c6728918d16 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_CREATE_FUNC #define COLLISION_CREATE_FUNC -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" typedef btAlignedObjectArray btCollisionObjectArray; class btCollisionAlgorithm; class btCollisionObject; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp index b535fac6563..a031a9f9784 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp @@ -19,69 +19,39 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" + #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btPoolAllocator.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" int gNumManifold = 0; +#ifdef BT_DEBUG #include +#endif - -btCollisionDispatcher::btCollisionDispatcher(bool noDefaultAlgorithms): -m_count(0), -m_useIslands(true), -m_convexConvexCreateFunc(0), -m_convexConcaveCreateFunc(0), -m_swappedConvexConcaveCreateFunc(0), -m_compoundCreateFunc(0), -m_swappedCompoundCreateFunc(0), -m_emptyCreateFunc(0) -{ - (void)noDefaultAlgorithms; - int i; - setNearCallback(defaultNearCallback); - - m_emptyCreateFunc = new btEmptyAlgorithm::CreateFunc; - for (i=0;igetCollisionAlgorithmPool(); + + m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool(); for (i=0;igetCollisionAlgorithmCreateFunc(i,j); assert(m_doubleDispatch[i][j]); } } @@ -89,8 +59,6 @@ btCollisionDispatcher::btCollisionDispatcher (): }; -#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION - void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc) { @@ -99,12 +67,6 @@ void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int prox btCollisionDispatcher::~btCollisionDispatcher() { - delete m_convexConvexCreateFunc; - delete m_convexConcaveCreateFunc; - delete m_swappedConvexConcaveCreateFunc; - delete m_compoundCreateFunc; - delete m_swappedCompoundCreateFunc; - delete m_emptyCreateFunc; } btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) @@ -117,7 +79,18 @@ btPersistentManifold* btCollisionDispatcher::getNewManifold(void* b0,void* b1) btCollisionObject* body0 = (btCollisionObject*)b0; btCollisionObject* body1 = (btCollisionObject*)b1; - btPersistentManifold* manifold = new btPersistentManifold (body0,body1); + void* mem = 0; + + if (m_persistentManifoldPoolAllocator->getFreeCount()) + { + mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold)); + } else + { + mem = btAlignedAlloc(sizeof(btPersistentManifold),16); + + } + btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0); + manifold->m_index1a = m_manifoldsPtr.size(); m_manifoldsPtr.push_back(manifold); return manifold; @@ -137,13 +110,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) //printf("releaseManifold: gNumManifold %d\n",gNumManifold); clearManifold(manifold); - ///todo: this can be improved a lot, linear search might be slow part! - int findIndex = m_manifoldsPtr.findLinearSearch(manifold); - if (findIndex < m_manifoldsPtr.size()) + int findIndex = manifold->m_index1a; + btAssert(findIndex < m_manifoldsPtr.size()); + m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); + m_manifoldsPtr[findIndex]->m_index1a = findIndex; + m_manifoldsPtr.pop_back(); + + manifold->~btPersistentManifold(); + if (m_persistentManifoldPoolAllocator->validPtr(manifold)) { - m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1); - m_manifoldsPtr.pop_back(); - delete manifold; + m_persistentManifoldPoolAllocator->freeMemory(manifold); + } else + { + btAlignedFree(manifold); } } @@ -152,99 +131,19 @@ void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold) btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) { - -#ifdef USE_DISPATCH_REGISTRY_ARRAY btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = this; + + ci.m_dispatcher1 = this; ci.m_manifold = sharedManifold; - btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()] - ->CreateCollisionAlgorithm(ci,body0,body1); -#else - btCollisionAlgorithm* algo = internalFindAlgorithm(body0,body1); -#endif //USE_DISPATCH_REGISTRY_ARRAY + btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1); + return algo; } -#ifndef BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION - -btCollisionAlgorithmCreateFunc* btCollisionDispatcher::internalFindCreateFunc(int proxyType0,int proxyType1) -{ - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) - { - return m_convexConvexCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) - { - return m_convexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) - { - return m_swappedConvexConcaveCreateFunc; - } - - if (btBroadphaseProxy::isCompound(proxyType0)) - { - return m_compoundCreateFunc; - } else - { - if (btBroadphaseProxy::isCompound(proxyType1)) - { - return m_swappedCompoundCreateFunc; - } - } - - //failed to find an algorithm - return m_emptyCreateFunc; -} - -#endif //BT_EXCLUDE_DEFAULT_COLLISIONALGORITHM_REGISTRATION -#ifndef USE_DISPATCH_REGISTRY_ARRAY - -btCollisionAlgorithm* btCollisionDispatcher::internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold) -{ - m_count++; - - btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = this; - - if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConvex() ) - { - return new btConvexConvexAlgorithm(sharedManifold,ci,body0,body1); - } - - if (body0->getCollisionShape()->isConvex() && body1->getCollisionShape()->isConcave()) - { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); - } - - if (body1->getCollisionShape()->isConvex() && body0->getCollisionShape()->isConcave()) - { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); - } - - if (body0->getCollisionShape()->isCompound()) - { - return new btCompoundCollisionAlgorithm(ci,body0,body1,false); - } else - { - if (body1->getCollisionShape()->isCompound()) - { - return new btCompoundCollisionAlgorithm(ci,body0,body1,true); - } - } - - //failed to find an algorithm - return new btEmptyAlgorithm(ci); - -} -#endif //USE_DISPATCH_REGISTRY_ARRAY bool btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1) { @@ -264,13 +163,19 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO bool needsCollision = true; - //broadphase filtering already deals with this - if ((body0->isStaticObject() || body0->isKinematicObject()) && - (body1->isStaticObject() || body1->isKinematicObject())) +#ifdef BT_DEBUG + if (!m_staticWarningReported) { - printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + //broadphase filtering already deals with this + if ((body0->isStaticObject() || body0->isKinematicObject()) && + (body1->isStaticObject() || body1->isKinematicObject())) + { + m_staticWarningReported = true; + printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n"); + } } - +#endif //BT_DEBUG + if ((!body0->isActive()) && (!body1->isActive())) needsCollision = false; else if (!body0->checkCollideWith(body1)) @@ -286,23 +191,25 @@ bool btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionO ///this is useful for the collision dispatcher. class btCollisionPairCallback : public btOverlapCallback { - btDispatcherInfo& m_dispatchInfo; + const btDispatcherInfo& m_dispatchInfo; btCollisionDispatcher* m_dispatcher; public: - btCollisionPairCallback(btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) + btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher* dispatcher) :m_dispatchInfo(dispatchInfo), m_dispatcher(dispatcher) { } - btCollisionPairCallback& operator=(btCollisionPairCallback& other) + /*btCollisionPairCallback& operator=(btCollisionPairCallback& other) { m_dispatchInfo = other.m_dispatchInfo; m_dispatcher = other.m_dispatcher; return *this; } + */ + virtual ~btCollisionPairCallback() {} @@ -316,13 +223,14 @@ public: }; -void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo) + +void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) { //m_blockedForChanges = true; btCollisionPairCallback collisionCallback(dispatchInfo,this); - pairCache->processAllOverlappingPairs(&collisionCallback); + pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher); //m_blockedForChanges = false; @@ -332,7 +240,7 @@ void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pa //by default, Bullet will use this near callback -void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo) +void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo) { btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; @@ -365,3 +273,26 @@ void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, } } + + +void* btCollisionDispatcher::allocateCollisionAlgorithm(int size) +{ + if (m_collisionAlgorithmPoolAllocator->getFreeCount()) + { + return m_collisionAlgorithmPoolAllocator->allocate(size); + } + + //warn user for overflow? + return btAlignedAlloc(static_cast(size), 16); +} + +void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr) +{ + if (m_collisionAlgorithmPoolAllocator->validPtr(ptr)) + { + m_collisionAlgorithmPoolAllocator->freeMemory(ptr); + } else + { + btAlignedFree(ptr); + } +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h index ca5aba8f01c..a9c9cd414c1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionDispatcher.h @@ -16,17 +16,18 @@ subject to the following restrictions: #ifndef COLLISION__DISPATCHER_H #define COLLISION__DISPATCHER_H -#include "../BroadphaseCollision/btDispatcher.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" -#include "../CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btAlignedObjectArray.h" class btIDebugDraw; class btOverlappingPairCache; - +class btPoolAllocator; +class btCollisionConfiguration; #include "btCollisionCreateFunc.h" @@ -34,7 +35,7 @@ class btOverlappingPairCache; class btCollisionDispatcher; ///user can override this nearcallback for collision filtering and more finegrained control over collision detection -typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); +typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); ///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs. @@ -46,26 +47,22 @@ class btCollisionDispatcher : public btDispatcher btAlignedObjectArray m_manifoldsPtr; bool m_useIslands; + + bool m_staticWarningReported; btManifoldResult m_defaultManifoldResult; btNearCallback m_nearCallback; + btPoolAllocator* m_collisionAlgorithmPoolAllocator; + + btPoolAllocator* m_persistentManifoldPoolAllocator; + btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES]; - btCollisionAlgorithmCreateFunc* internalFindCreateFunc(int proxyType0,int proxyType1); - //default CreationFunctions, filling the m_doubleDispatch table - btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; - btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; - btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; - btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionConfiguration* m_collisionConfiguration; -#ifndef USE_DISPATCH_REGISTRY_ARRAY - btCollisionAlgorithm* internalFindAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0); -#endif //USE_DISPATCH_REGISTRY_ARRAY public: @@ -92,11 +89,7 @@ public: return m_manifoldsPtr[index]; } - ///the default constructor creates/register default collision algorithms, for convex, compound and concave shape support - btCollisionDispatcher (); - - ///a special constructor that doesn't create/register the default collision algorithms - btCollisionDispatcher(bool noDefaultAlgorithms); + btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration); virtual ~btCollisionDispatcher(); @@ -114,7 +107,7 @@ public: virtual bool needsResponse(btCollisionObject* body0,btCollisionObject* body1); - virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,btDispatcherInfo& dispatchInfo); + virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ; void setNearCallback(btNearCallback nearCallback) { @@ -127,7 +120,26 @@ public: } //by default, Bullet will use this near callback - static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo); + static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo); + + virtual void* allocateCollisionAlgorithm(int size); + + virtual void freeCollisionAlgorithm(void* ptr); + + btCollisionConfiguration* getCollisionConfiguration() + { + return m_collisionConfiguration; + } + + const btCollisionConfiguration* getCollisionConfiguration() const + { + return m_collisionConfiguration; + } + + void setCollisionConfiguration(btCollisionConfiguration* config) + { + m_collisionConfiguration = config; + } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp index d4c0a4e8cb3..eebd0c99fcb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.cpp @@ -13,18 +13,25 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ + #include "btCollisionObject.h" btCollisionObject::btCollisionObject() : m_broadphaseHandle(0), m_collisionShape(0), - m_collisionFlags(0), + m_rootCollisionShape(0), + m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT), + m_islandTag1(-1), + m_companionId(-1), m_activationState1(1), m_deactivationTime(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), m_userObjectPointer(0), + m_internalType(CO_COLLISION_OBJECT), m_hitFraction(btScalar(1.)), m_ccdSweptSphereRadius(btScalar(0.)), - m_ccdSquareMotionThreshold(btScalar(0.)), + m_ccdMotionThreshold(btScalar(0.)), m_checkCollideWith(false) { @@ -55,3 +62,4 @@ void btCollisionObject::activate(bool forceActivation) } + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index 9fb6a67c4a3..7ef3787b3ac 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef COLLISION_OBJECT_H #define COLLISION_OBJECT_H -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btTransform.h" //island management, m_activationState1 #define ACTIVE_TAG 1 @@ -27,7 +27,8 @@ subject to the following restrictions: struct btBroadphaseProxy; class btCollisionShape; -#include "../../LinearMath/btMotionState.h" +#include "LinearMath/btMotionState.h" +#include "LinearMath/btAlignedAllocator.h" @@ -50,6 +51,11 @@ protected: btVector3 m_interpolationAngularVelocity; btBroadphaseProxy* m_broadphaseHandle; btCollisionShape* m_collisionShape; + + ///m_rootCollisionShape is temporarily used to store the original collision shape + ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes + ///If it is NULL, the m_collisionShape is not temporarily replaced. + btCollisionShape* m_rootCollisionShape; int m_collisionFlags; @@ -65,8 +71,9 @@ protected: ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer void* m_userObjectPointer; - ///m_internalOwner is reserved to point to Bullet's btRigidBody. Don't use this, use m_userObjectPointer instead. - void* m_internalOwner; + ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody etc. + ///do not assign your own m_internalType unless you write a new dynamics object class. + int m_internalType; ///time of impact calculation btScalar m_hitFraction; @@ -74,21 +81,23 @@ protected: ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm:: btScalar m_ccdSweptSphereRadius; - /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold - btScalar m_ccdSquareMotionThreshold; + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + btScalar m_ccdMotionThreshold; /// If some object should have elaborate collision filtering by sub-classes bool m_checkCollideWith; char m_pad[7]; - virtual bool checkCollideWithOverride(btCollisionObject* co) + virtual bool checkCollideWithOverride(btCollisionObject* /* co */) { return true; } public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + enum CollisionFlags { CF_STATIC_OBJECT= 1, @@ -97,29 +106,35 @@ public: CF_CUSTOM_MATERIAL_CALLBACK = 8//this allows per-triangle material (friction/restitution) }; + enum CollisionObjectTypes + { + CO_COLLISION_OBJECT =1, + CO_RIGID_BODY, + CO_SOFT_BODY + }; - inline bool mergesSimulationIslands() const + SIMD_FORCE_INLINE bool mergesSimulationIslands() const { ///static objects, kinematic and object without contact response don't merge islands return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0); } - inline bool isStaticObject() const { + SIMD_FORCE_INLINE bool isStaticObject() const { return (m_collisionFlags & CF_STATIC_OBJECT) != 0; } - inline bool isKinematicObject() const + SIMD_FORCE_INLINE bool isKinematicObject() const { return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0; } - inline bool isStaticOrKinematicObject() const + SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const { return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ; } - inline bool hasContactResponse() const { + SIMD_FORCE_INLINE bool hasContactResponse() const { return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0; } @@ -131,20 +146,35 @@ public: void setCollisionShape(btCollisionShape* collisionShape) { m_collisionShape = collisionShape; + m_rootCollisionShape = collisionShape; } - const btCollisionShape* getCollisionShape() const + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - btCollisionShape* getCollisionShape() + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { return m_collisionShape; } - + SIMD_FORCE_INLINE const btCollisionShape* getRootCollisionShape() const + { + return m_rootCollisionShape; + } + SIMD_FORCE_INLINE btCollisionShape* getRootCollisionShape() + { + return m_rootCollisionShape; + } + + ///Avoid using this internal API call + ///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape. + void internalSetTemporaryCollisionShape(btCollisionShape* collisionShape) + { + m_collisionShape = collisionShape; + } int getActivationState() const { return m_activationState1;} @@ -186,14 +216,9 @@ public: } ///reserved for Bullet internal usage - void* getInternalOwner() + int getInternalType() const { - return m_internalOwner; - } - - const void* getInternalOwner() const - { - return m_internalOwner; + return m_internalType; } btTransform& getWorldTransform() @@ -243,6 +268,15 @@ public: m_interpolationWorldTransform = trans; } + void setInterpolationLinearVelocity(const btVector3& linvel) + { + m_interpolationLinearVelocity = linvel; + } + + void setInterpolationAngularVelocity(const btVector3& angvel) + { + m_interpolationAngularVelocity = angvel; + } const btVector3& getInterpolationLinearVelocity() const { @@ -307,16 +341,22 @@ public: m_ccdSweptSphereRadius = radius; } + btScalar getCcdMotionThreshold() const + { + return m_ccdMotionThreshold; + } + btScalar getCcdSquareMotionThreshold() const { - return m_ccdSquareMotionThreshold; + return m_ccdMotionThreshold*m_ccdMotionThreshold; } - /// Don't do continuous collision detection if square motion (in one step) is less then m_ccdSquareMotionThreshold - void setCcdSquareMotionThreshold(btScalar ccdSquareMotionThreshold) + + /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold + void setCcdMotionThreshold(btScalar ccdMotionThreshold) { - m_ccdSquareMotionThreshold = ccdSquareMotionThreshold; + m_ccdMotionThreshold = ccdMotionThreshold*ccdMotionThreshold; } ///users can point to their objects, userPointer is not used by Bullet @@ -331,6 +371,7 @@ public: m_userObjectPointer = userPointer; } + inline bool checkCollideWith(btCollisionObject* co) { if (m_checkCollideWith) @@ -338,9 +379,6 @@ public: return true; } - - -} -; +}; #endif //COLLISION_OBJECT_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index b49036a5b50..d8674a320a7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -4,8 +4,8 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. @@ -18,59 +18,57 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" - +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting -#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" //for raycasting +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" + #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "LinearMath/btAabbUtil2.h" #include "LinearMath/btQuickprof.h" #include "LinearMath/btStackAlloc.h" + //When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h" -btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize) +btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration) :m_dispatcher1(dispatcher), m_broadphasePairCache(pairCache), -m_ownsDispatcher(false), -m_ownsBroadphasePairCache(false) +m_debugDrawer(0) { - m_stackAlloc = new btStackAlloc(stackSize); + m_stackAlloc = collisionConfiguration->getStackAllocator(); m_dispatchInfo.m_stackAllocator = m_stackAlloc; } btCollisionWorld::~btCollisionWorld() { - m_stackAlloc->destroy(); - delete m_stackAlloc; //clean up remaining objects int i; for (i=0;igetBroadphaseHandle(); if (bp) { // // only clear the cached algorithms // - getBroadphase()->cleanProxyFromPairs(bp); - getBroadphase()->destroyProxy(bp); + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); } } - if (m_ownsDispatcher) - delete m_dispatcher1; - if (m_ownsBroadphasePairCache) - delete m_broadphasePairCache; } @@ -105,66 +103,105 @@ void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,sho type, collisionObject, collisionFilterGroup, - collisionFilterMask + collisionFilterMask, + m_dispatcher1,0 )) ; - + } +void btCollisionWorld::updateAabbs() +{ + BT_PROFILE("updateAabbs"); + + btTransform predictedTrans; + for ( int i=0;iisActive()) + { + btPoint3 minAabb,maxAabb; + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + //need to increase the aabb for contact thresholds + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; + + //moving objects should be moderately sized, probably something wrong if not + if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + { + bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); + } else + { + //something went wrong, investigate + //this assert is unwanted in 3D modelers (danger of loosing work) + colObj->setActivationState(DISABLE_SIMULATION); + + static bool reportMe = true; + if (reportMe && m_debugDrawer) + { + reportMe = false; + m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); + m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); + m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); + m_debugDrawer->reportErrorWarning("Thanks.\n"); + } + } + } + } + +} void btCollisionWorld::performDiscreteCollisionDetection() { + BT_PROFILE("performDiscreteCollisionDetection"); + btDispatcherInfo& dispatchInfo = getDispatchInfo(); - BEGIN_PROFILE("perform Broadphase Collision Detection"); + updateAabbs(); - - //update aabb (of all moved objects) - - btVector3 aabbMin,aabbMax; - for (int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),aabbMin,aabbMax); - m_broadphasePairCache->setAabb(m_collisionObjects[i]->getBroadphaseHandle(),aabbMin,aabbMax); + BT_PROFILE("calculateOverlappingPairs"); + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); } - m_broadphasePairCache->refreshOverlappingPairs(); - - - END_PROFILE("perform Broadphase Collision Detection"); - - BEGIN_PROFILE("performDiscreteCollisionDetection"); btDispatcher* dispatcher = getDispatcher(); - if (dispatcher) - dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache,dispatchInfo); - - END_PROFILE("performDiscreteCollisionDetection"); + { + BT_PROFILE("dispatchAllCollisionPairs"); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + } } + void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject) { - - + + //bool removeFromBroadphase = false; - + { - + btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle(); if (bp) { // // only clear the cached algorithms // - getBroadphase()->cleanProxyFromPairs(bp); - getBroadphase()->destroyProxy(bp); + getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1); + getBroadphase()->destroyProxy(bp,m_dispatcher1); collisionObject->setBroadphaseHandle(0); } } @@ -181,172 +218,412 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback,short int collisionFilterMask) + RayResultCallback& resultCallback) { - btSphereShape pointShape(btScalar(0.0)); pointShape.setMargin(0.f); + const btConvexShape* castShape = &pointShape; - objectQuerySingle(&pointShape,rayFromTrans,rayToTrans, - collisionObject, - collisionShape, - colObjWorldTransform, - resultCallback,collisionFilterMask); + if (collisionShape->isConvex()) + { + btConvexCast::CastResult castResult; + castResult.m_fraction = resultCallback.m_closestHitFraction; + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; +#define USE_SUBSIMPLEX_CONVEX_CAST 1 +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); +#else + //btGjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); + //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < resultCallback.m_closestHitFraction) + { +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST + + castResult.m_normal.normalize(); + btCollisionWorld::LocalRayResult localRayResult + ( + collisionObject, + 0, + castResult.m_normal, + castResult.m_fraction + ); + + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localRayResult, normalInWorldSpace); + + } + } + } + } else { + if (collisionShape->isConcave()) + { + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + ///optimized version for btBvhTriangleMeshShape + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): + btTriangleRaycastCallback(from,to), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitFraction); + + bool normalInWorldSpace = false; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + } + + }; + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal); + } else + { + btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; + + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + + btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); + btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); + + //ConvexCast::CastResult + + struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + { + btCollisionWorld::RayResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, + btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): + btTriangleRaycastCallback(from,to), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + + btCollisionWorld::LocalRayResult rayResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitFraction); + + bool normalInWorldSpace = false; + return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace); + + + } + + }; + + + BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); + rcb.m_hitFraction = resultCallback.m_closestHitFraction; + + btVector3 rayAabbMinLocal = rayFromLocal; + rayAabbMinLocal.setMin(rayToLocal); + btVector3 rayAabbMaxLocal = rayFromLocal; + rayAabbMaxLocal.setMax(rayToLocal); + + triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); + } + } else { + //todo: use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); + rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback); + // restore + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); + } + } + } + } } -void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& rayFromTrans,const btTransform& rayToTrans, +void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback,short int collisionFilterMask) + ConvexResultCallback& resultCallback, btScalar allowedPenetration) { - - if (collisionShape->isConvex()) + { + btConvexCast::CastResult castResult; + castResult.m_allowedPenetration = allowedPenetration; + castResult.m_fraction = btScalar(1.);//?? + + btConvexShape* convexShape = (btConvexShape*) collisionShape; + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + + btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver); + //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver); + //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver); + + btConvexCast* castPtr = &convexCaster1; + + + + if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) { - btConvexCast::CastResult castResult; - castResult.m_fraction = btScalar(1.);//?? - - btConvexShape* convexShape = (btConvexShape*) collisionShape; - btVoronoiSimplexSolver simplexSolver; - btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //GjkConvexCast convexCaster(castShape,convexShape,&simplexSolver); - //ContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0); - - if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult)) + if (castResult.m_fraction < resultCallback.m_closestHitFraction) { - //add hit - if (castResult.m_normal.length2() > btScalar(0.0001)) - { - castResult.m_normal.normalize(); - if (castResult.m_fraction < resultCallback.m_closestHitFraction) - { - - btCollisionWorld::LocalRayResult localRayResult + castResult.m_normal.normalize(); + btCollisionWorld::LocalConvexResult localConvexResult ( - collisionObject, + collisionObject, 0, castResult.m_normal, + castResult.m_hitPoint, castResult.m_fraction ); - resultCallback.AddSingleResult(localRayResult); + bool normalInWorldSpace = true; + resultCallback.addSingleResult(localConvexResult, normalInWorldSpace); - } - } } } - else + } + } else { + if (collisionShape->isConcave()) + { + if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE) { - - if (collisionShape->isConcave()) - { + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); - btTriangleMeshShape* triangleMesh = (btTriangleMeshShape*)collisionShape; - - btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; - btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin(); - btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin(); - - //ConvexCast::CastResult - - struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) { - btCollisionWorld::RayResultCallback* m_resultCallback; - btCollisionObject* m_collisionObject; - btTriangleMeshShape* m_triangleMesh; - - BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to, - btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh): - btTriangleRaycastCallback(from,to), - m_resultCallback(resultCallback), - m_collisionObject(collisionObject), - m_triangleMesh(triangleMesh) - { - } - - - virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) - { - btCollisionWorld::LocalShapeInfo shapeInfo; - shapeInfo.m_shapePart = partId; - shapeInfo.m_triangleIndex = triangleIndex; - - btCollisionWorld::LocalRayResult rayResult - (m_collisionObject, - &shapeInfo, - hitNormalLocal, - hitFraction); - - return m_resultCallback->AddSingleResult(rayResult); - - - } - - }; - - - BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh); - rcb.m_hitFraction = resultCallback.m_closestHitFraction; - - btVector3 rayAabbMinLocal = rayFromLocal; - rayAabbMinLocal.setMin(rayToLocal); - btVector3 rayAabbMaxLocal = rayFromLocal; - rayAabbMaxLocal.setMax(rayToLocal); - - triangleMesh->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal); - - } else - { - //todo: use AABB tree or other BVH acceleration structure! - if (collisionShape->isCompound()) - { - const btCompoundShape* compoundShape = static_cast(collisionShape); - int i=0; - for (i=0;igetNumChildShapes();i++) - { - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; - objectQuerySingle(castShape, rayFromTrans,rayToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback, collisionFilterMask); - - } - - } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = true; + + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal); + } else + { + btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape; + btTransform worldTocollisionObject = colObjWorldTransform.inverse(); + btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin(); + btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin(); + // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation + btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis()); + + //ConvexCast::CastResult + struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback + { + btCollisionWorld::ConvexResultCallback* m_resultCallback; + btCollisionObject* m_collisionObject; + btTriangleMeshShape* m_triangleMesh; + + BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to, + btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld): + btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()), + m_resultCallback(resultCallback), + m_collisionObject(collisionObject), + m_triangleMesh(triangleMesh) + { + } + + + virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex ) + { + btCollisionWorld::LocalShapeInfo shapeInfo; + shapeInfo.m_shapePart = partId; + shapeInfo.m_triangleIndex = triangleIndex; + if (hitFraction <= m_resultCallback->m_closestHitFraction) + { + + btCollisionWorld::LocalConvexResult convexResult + (m_collisionObject, + &shapeInfo, + hitNormalLocal, + hitPointLocal, + hitFraction); + + bool normalInWorldSpace = false; + + return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace); + } + return hitFraction; + } + + }; + + BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform); + tccb.m_hitFraction = resultCallback.m_closestHitFraction; + btVector3 boxMinLocal, boxMaxLocal; + castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal); + + btVector3 rayAabbMinLocal = convexFromLocal; + rayAabbMinLocal.setMin(convexToLocal); + btVector3 rayAabbMaxLocal = convexFromLocal; + rayAabbMaxLocal.setMax(convexToLocal); + rayAabbMinLocal += boxMinLocal; + rayAabbMaxLocal += boxMaxLocal; + triangleMesh->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal); } + } else { + //todo: use AABB tree or other BVH acceleration structure! + if (collisionShape->isCompound()) + { + const btCompoundShape* compoundShape = static_cast(collisionShape); + int i=0; + for (i=0;igetNumChildShapes();i++) + { + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback, allowedPenetration); + // restore + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); + } + } + } + } } -void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback,short int collisionFilterMask) +void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const { - + btTransform rayFromTrans,rayToTrans; rayFromTrans.setIdentity(); rayFromTrans.setOrigin(rayFromWorld); rayToTrans.setIdentity(); - + rayToTrans.setOrigin(rayToWorld); /// go over all objects, and if the ray intersects their aabb, do a ray-shape query using convexCaster (CCD) - + int i; for (i=0;igetBroadphaseHandle()->m_collisionFilterGroup & collisionFilterMask) { + if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) { //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); btVector3 collisionObjectAabbMin,collisionObjectAabbMax; collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); - btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btScalar hitLambda = resultCallback.m_closestHitFraction; btVector3 hitNormal; if (btRayAabb(rayFromWorld,rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) { @@ -355,7 +632,52 @@ void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& r collisionObject->getCollisionShape(), collisionObject->getWorldTransform(), resultCallback); - } + } + } + + } + +} + +void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback) const +{ + btTransform convexFromTrans,convexToTrans; + convexFromTrans = convexFromWorld; + convexToTrans = convexToWorld; + btVector3 castShapeAabbMin, castShapeAabbMax; + /* Compute AABB that encompasses angular movement */ + { + btVector3 linVel, angVel; + btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel); + btTransform R; + R.setIdentity (); + R.setRotation (convexFromTrans.getRotation()); + castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax); + } + + /// go over all objects, and if the ray intersects their aabb + cast shape aabb, + // do a ray-shape query using convexCaster (CCD) + int i; + for (i=0;igetBroadphaseHandle())) { + //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject(); + btVector3 collisionObjectAabbMin,collisionObjectAabbMax; + collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax); + AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax); + btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing + btVector3 hitNormal; + if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal)) + { + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + collisionObject->getCollisionShape(), + collisionObject->getWorldTransform(), + resultCallback, + getDispatchInfo().m_allowedCcdPenetration); + } } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h index b6d80233ab7..7557691a9a9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.h @@ -68,12 +68,12 @@ class btStackAlloc; class btCollisionShape; class btConvexShape; class btBroadphaseInterface; -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" #include "btCollisionObject.h" #include "btCollisionDispatcher.h" //for definition of btCollisionObjectArray -#include "../BroadphaseCollision/btOverlappingPairCache.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h" +#include "LinearMath/btAlignedObjectArray.h" ///CollisionWorld is interface and container for the collision detection class btCollisionWorld @@ -90,18 +90,22 @@ protected: btStackAlloc* m_stackAlloc; - btOverlappingPairCache* m_broadphasePairCache; - - bool m_ownsDispatcher; - bool m_ownsBroadphasePairCache; + btBroadphaseInterface* m_broadphasePairCache; + btIDebugDraw* m_debugDrawer; + + public: //this constructor doesn't own the dispatcher and paircache/broadphase - btCollisionWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache, int stackSize = 2*1024*1024); + btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration); virtual ~btCollisionWorld(); + void setBroadphase(btBroadphaseInterface* pairCache) + { + m_broadphasePairCache = pairCache; + } btBroadphaseInterface* getBroadphase() { @@ -110,7 +114,7 @@ public: btOverlappingPairCache* getPairCache() { - return m_broadphasePairCache; + return m_broadphasePairCache->getOverlappingPairCache(); } @@ -119,6 +123,24 @@ public: return m_dispatcher1; } + const btDispatcher* getDispatcher() const + { + return m_dispatcher1; + } + + virtual void updateAabbs(); + + virtual void setDebugDrawer(btIDebugDraw* debugDrawer) + { + m_debugDrawer = debugDrawer; + } + + virtual btIDebugDraw* getDebugDrawer() + { + return m_debugDrawer; + } + + ///LocalShapeInfo gives extra information for complex shapes ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart struct LocalShapeInfo @@ -153,28 +175,43 @@ public: ///RayResultCallback is used to report new raycast results struct RayResultCallback { + btScalar m_closestHitFraction; + btCollisionObject* m_collisionObject; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + virtual ~RayResultCallback() { } - btScalar m_closestHitFraction; - bool HasHit() + bool hasHit() const { - return (m_closestHitFraction < btScalar(1.)); + return (m_collisionObject != 0); } RayResultCallback() - :m_closestHitFraction(btScalar(1.)) + :m_closestHitFraction(btScalar(1.)), + m_collisionObject(0), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) { } - virtual btScalar AddSingleResult(LocalRayResult& rayResult) = 0; + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0; }; struct ClosestRayResultCallback : public RayResultCallback { ClosestRayResultCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld) :m_rayFromWorld(rayFromWorld), - m_rayToWorld(rayToWorld), - m_collisionObject(0) + m_rayToWorld(rayToWorld) { } @@ -183,24 +220,121 @@ public: btVector3 m_hitNormalWorld; btVector3 m_hitPointWorld; - btCollisionObject* m_collisionObject; - - virtual btScalar AddSingleResult(LocalRayResult& rayResult) + + virtual btScalar addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) { - -//caller already does the filter on the m_closestHitFraction - assert(rayResult.m_hitFraction <= m_closestHitFraction); + //caller already does the filter on the m_closestHitFraction + btAssert(rayResult.m_hitFraction <= m_closestHitFraction); m_closestHitFraction = rayResult.m_hitFraction; m_collisionObject = rayResult.m_collisionObject; - m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + if (normalInWorldSpace) + { + m_hitNormalWorld = rayResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal; + } m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction); return rayResult.m_hitFraction; } }; - + struct LocalConvexResult + { + LocalConvexResult(btCollisionObject* hitCollisionObject, + LocalShapeInfo* localShapeInfo, + const btVector3& hitNormalLocal, + const btVector3& hitPointLocal, + btScalar hitFraction + ) + :m_hitCollisionObject(hitCollisionObject), + m_localShapeInfo(localShapeInfo), + m_hitNormalLocal(hitNormalLocal), + m_hitPointLocal(hitPointLocal), + m_hitFraction(hitFraction) + { + } + + btCollisionObject* m_hitCollisionObject; + LocalShapeInfo* m_localShapeInfo; + btVector3 m_hitNormalLocal; + btVector3 m_hitPointLocal; + btScalar m_hitFraction; + }; + + ///RayResultCallback is used to report new raycast results + struct ConvexResultCallback + { + btScalar m_closestHitFraction; + short int m_collisionFilterGroup; + short int m_collisionFilterMask; + + ConvexResultCallback() + :m_closestHitFraction(btScalar(1.)), + m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter), + m_collisionFilterMask(btBroadphaseProxy::AllFilter) + { + } + + virtual ~ConvexResultCallback() + { + } + + bool hasHit() const + { + return (m_closestHitFraction < btScalar(1.)); + } + + + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0; + collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask); + return collides; + } + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0; + }; + + struct ClosestConvexResultCallback : public ConvexResultCallback + { + ClosestConvexResultCallback(const btVector3& convexFromWorld,const btVector3& convexToWorld) + :m_convexFromWorld(convexFromWorld), + m_convexToWorld(convexToWorld), + m_hitCollisionObject(0) + { + } + + btVector3 m_convexFromWorld;//used to calculate hitPointWorld from hitFraction + btVector3 m_convexToWorld; + + btVector3 m_hitNormalWorld; + btVector3 m_hitPointWorld; + btCollisionObject* m_hitCollisionObject; + + virtual btScalar addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) + { +//caller already does the filter on the m_closestHitFraction + btAssert(convexResult.m_hitFraction <= m_closestHitFraction); + + m_closestHitFraction = convexResult.m_hitFraction; + m_hitCollisionObject = convexResult.m_hitCollisionObject; + if (normalInWorldSpace) + { + m_hitNormalWorld = convexResult.m_hitNormalLocal; + } else + { + ///need to transform normal into worldspace + m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal; + } + m_hitPointWorld = convexResult.m_hitPointLocal; + return convexResult.m_hitFraction; + } + }; int getNumCollisionObjects() const { @@ -209,7 +343,12 @@ public: /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback. - void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback, short int collisionFilterMask=-1); + void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; + + // convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback + // This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback. + void convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback) const; + /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest. /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape. @@ -218,16 +357,16 @@ public: btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback, short int collisionFilterMask=-1); + RayResultCallback& resultCallback); /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest. static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans, btCollisionObject* collisionObject, const btCollisionShape* collisionShape, const btTransform& colObjWorldTransform, - RayResultCallback& resultCallback, short int collisionFilterMask=-1); + ConvexResultCallback& resultCallback, btScalar allowedPenetration); - void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=1,short int collisionFilterMask=1); + void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter); btCollisionObjectArray& getCollisionObjectArray() { @@ -249,6 +388,11 @@ public: return m_dispatchInfo; } + const btDispatcherInfo& getDispatchInfo() const + { + return m_dispatchInfo; + } + }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 92f4c8b28a6..535b61992b0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -16,11 +16,17 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" - +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btAabbUtil2.h" btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) -:m_isSwapped(isSwapped) +:btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_sharedManifold(ci.m_manifold) { + m_ownsManifold = false; + btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; assert (colObj->getCollisionShape()->isCompound()); @@ -32,11 +38,17 @@ btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlg m_childCollisionAlgorithms.resize(numChildren); for (i=0;igetChildShape(i); - btCollisionShape* orgShape = colObj->getCollisionShape(); - colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher->findAlgorithm(colObj,otherObj); - colObj->setCollisionShape( orgShape ); + if (compoundShape->getDynamicAabbTree()) + { + m_childCollisionAlgorithms[i] = 0; + } else + { + btCollisionShape* tmpShape = colObj->getCollisionShape(); + btCollisionShape* childShape = compoundShape->getChildShape(i); + colObj->internalSetTemporaryCollisionShape( childShape ); + m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold); + colObj->internalSetTemporaryCollisionShape( tmpShape ); + } } } @@ -47,10 +59,109 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() int i; for (i=0;i~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + } } } + + + +struct btCompoundLeafCallback : btDbvt::ICollide +{ + +public: + + btCollisionObject* m_compoundColObj; + btCollisionObject* m_otherObj; + btDispatcher* m_dispatcher; + const btDispatcherInfo& m_dispatchInfo; + btManifoldResult* m_resultOut; + btCollisionAlgorithm** m_childCollisionAlgorithms; + btPersistentManifold* m_sharedManifold; + + + + + btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold) + :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), + m_childCollisionAlgorithms(childCollisionAlgorithms), + m_sharedManifold(sharedManifold) + { + + } + + + void ProcessChildShape(btCollisionShape* childShape,int index) + { + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + + + //backup + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(index); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + + m_compoundColObj->setWorldTransform( newChildWorldTrans); + m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans); + + //the contactpoint is still projected back using the original inverted worldtrans + btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape(); + m_compoundColObj->internalSetTemporaryCollisionShape( childShape ); + + if (!m_childCollisionAlgorithms[index]) + m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold); + + m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); + } + + //revert back transform + m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape); + m_compoundColObj->setWorldTransform( orgTrans ); + m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans); + } + } + void Process(const btDbvtNode* leaf) + { + int index = leaf->dataAsInt; + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + btCollisionShape* childShape = compoundShape->getChildShape(index); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); + m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); + } + ProcessChildShape(childShape,index); + + } +}; + + + + + + void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) { btCollisionObject* colObj = m_isSwapped? body1 : body0; @@ -59,33 +170,69 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt assert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps - //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals - //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: - //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 - //then use each overlapping node AABB against Tree0 - //and vise versa. + btDbvt* tree = compoundShape->getDynamicAabbTree(); + //use a dynamic aabb tree to cull potential child-overlaps + btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;igetChildShape(i); - //backup - btTransform orgTrans = colObj->getWorldTransform(); - btCollisionShape* orgShape = colObj->getCollisionShape(); + btVector3 localAabbMin,localAabbMax; + btTransform otherInCompoundSpace; + otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform(); + otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); + + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //process all children, that overlap with the given AABB bounds + tree->collideTV(tree->m_root,bounds,callback); + + } else + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i),i); + } + } + + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btManifoldArray manifoldArray; + + for (i=0;igetChildShape(i); + //if not longer overlapping, remove the algorithm + btTransform orgTrans = colObj->getWorldTransform(); + btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(i); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + m_childCollisionAlgorithms[i] = 0; + } + + } + + } + + - const btTransform& childTrans = compoundShape->getChildTransform(i); - //btTransform newChildWorldTrans = orgTrans*childTrans ; - colObj->setWorldTransform( orgTrans*childTrans ); - //the contactpoint is still projected back using the original inverted worldtrans - colObj->setCollisionShape( childShape ); - m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); - //revert back - colObj->setCollisionShape( orgShape); - colObj->setWorldTransform( orgTrans ); } } @@ -117,20 +264,20 @@ btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* //backup btTransform orgTrans = colObj->getWorldTransform(); - btCollisionShape* orgShape = colObj->getCollisionShape(); - + const btTransform& childTrans = compoundShape->getChildTransform(i); //btTransform newChildWorldTrans = orgTrans*childTrans ; colObj->setWorldTransform( orgTrans*childTrans ); - colObj->setCollisionShape( childShape ); + btCollisionShape* tmpShape = colObj->getCollisionShape(); + colObj->internalSetTemporaryCollisionShape( childShape ); btScalar frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut); if (fracsetCollisionShape( orgShape); + colObj->internalSetTemporaryCollisionShape( tmpShape); colObj->setWorldTransform( orgTrans); } return hitFraction; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 7091b233b46..624a3cf10f5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -16,22 +16,25 @@ subject to the following restrictions: #ifndef COMPOUND_COLLISION_ALGORITHM_H #define COMPOUND_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btDispatcher.h" -#include "../BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" +class btDispatcher; /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes -/// Place holder, not fully implemented yet class btCompoundCollisionAlgorithm : public btCollisionAlgorithm { btAlignedObjectArray m_childCollisionAlgorithms; bool m_isSwapped; + + class btPersistentManifold* m_sharedManifold; + bool m_ownsManifold; public: @@ -43,11 +46,22 @@ public: btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + int i; + for (i=0;igetAllContactManifolds(manifoldArray); + } + } + struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btCompoundCollisionAlgorithm(ci,body0,body1,false); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false); } }; @@ -55,7 +69,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btCompoundCollisionAlgorithm(ci,body0,body1,true); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm)); + return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp index 24ceacfd40d..6d28904cb03 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp @@ -29,7 +29,7 @@ subject to the following restrictions: btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) : btCollisionAlgorithm(ci), m_isSwapped(isSwapped), -m_btConvexTriangleCallback(ci.m_dispatcher,body0,body1,isSwapped) +m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) { } @@ -37,6 +37,13 @@ btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm() { } +void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray) +{ + if (m_btConvexTriangleCallback.m_manifoldPtr) + { + manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr); + } +} btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): @@ -79,7 +86,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i //aabb filter is already applied! btCollisionAlgorithmConstructionInfo ci; - ci.m_dispatcher = m_dispatcher; + ci.m_dispatcher1 = m_dispatcher; btCollisionObject* ob = static_cast(m_triBody); @@ -109,13 +116,11 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i { btTriangleShape tm(triangle[0],triangle[1],triangle[2]); tm.setMargin(m_collisionMarginTriangle); - btCollisionShape* tmpShape = ob->getCollisionShape(); - ob->setCollisionShape( &tm ); + ob->internalSetTemporaryCollisionShape( &tm ); - - btCollisionAlgorithm* colAlgo = ci.m_dispatcher->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr); ///this should use the btDispatcher, so the actual registered algorithm is used // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); @@ -123,12 +128,11 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, i // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); // cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); - delete colAlgo; - ob->setCollisionShape( tmpShape ); - + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape); } - } @@ -188,9 +192,10 @@ void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* bod concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax()); + resultOut->refreshContactPoints(); } - + } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h index 4915b6c20c8..34b9a107be9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h @@ -16,13 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H #define CONVEX_CONCAVE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btDispatcher.h" -#include "../BroadphaseCollision/btBroadphaseInterface.h" -#include "../CollisionShapes/btTriangleCallback.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btDispatcher; -#include "../BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" #include "btCollisionCreateFunc.h" ///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called. @@ -55,11 +55,11 @@ int m_triangleCount; void clearCache(); - inline const btVector3& getAabbMin() const + SIMD_FORCE_INLINE const btVector3& getAabbMin() const { return m_aabbMin; } - inline const btVector3& getAabbMax() const + SIMD_FORCE_INLINE const btVector3& getAabbMax() const { return m_aabbMax; } @@ -88,13 +88,16 @@ public: btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray); + void clearCache(); struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false); } }; @@ -102,7 +105,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm)); + return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp index 9105fe20b49..cb830f889be 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp @@ -15,7 +15,7 @@ subject to the following restrictions: #include "btConvexConvexAlgorithm.h" -#include +//#include #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" @@ -33,7 +33,6 @@ subject to the following restrictions: -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -48,26 +47,16 @@ subject to the following restrictions: -btConvexConvexAlgorithm::CreateFunc::CreateFunc() -{ - m_ownsSolvers = true; - m_simplexSolver = new btVoronoiSimplexSolver(); - m_pdSolver = new btGjkEpaPenetrationDepthSolver; -} + btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) { - m_ownsSolvers = false; m_simplexSolver = simplexSolver; m_pdSolver = pdSolver; } btConvexConvexAlgorithm::CreateFunc::~CreateFunc() { - if (m_ownsSolvers){ - delete m_simplexSolver; - delete m_pdSolver; - } } btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver) @@ -152,6 +141,11 @@ void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btColl m_gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); #endif + if (m_ownManifold) + { + resultOut->refreshContactPoints(); + } + } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h index cbea9a92b75..a0030e6793d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h @@ -16,12 +16,13 @@ subject to the following restrictions: #ifndef CONVEX_CONVEX_ALGORITHM_H #define CONVEX_CONVEX_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../NarrowPhaseCollision/btGjkPairDetector.h" -#include "../NarrowPhaseCollision/btPersistentManifold.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../NarrowPhaseCollision/btVoronoiSimplexSolver.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" #include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" class btConvexPenetrationDepthSolver; @@ -46,6 +47,14 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + ///should we use m_ownManifold to avoid adding duplicates? + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + void setLowLevelOfDetail(bool useLowLevel); @@ -58,15 +67,15 @@ public: { btConvexPenetrationDepthSolver* m_pdSolver; btSimplexSolverInterface* m_simplexSolver; - bool m_ownsSolvers; CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver); - CreateFunc(); + virtual ~CreateFunc(); virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm)); + return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp new file mode 100644 index 00000000000..391cf6c7bc4 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp @@ -0,0 +1,108 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btConvexPlaneCollisionAlgorithm.h" + +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" + +//#include + +btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped) +: btCollisionAlgorithm(ci), +m_ownManifold(false), +m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ + btCollisionObject* convexObj = m_isSwapped? col1 : col0; + btCollisionObject* planeObj = m_isSwapped? col0 : col1; + + if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj)) + { + m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj); + m_ownManifold = true; + } +} + + +btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm() +{ + if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } +} + + + +void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + if (!m_manifoldPtr) + return; + + btCollisionObject* convexObj = m_isSwapped? body1 : body0; + btCollisionObject* planeObj = m_isSwapped? body0: body1; + + btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape(); + btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape(); + + bool hasCollision = false; + const btVector3& planeNormal = planeShape->getPlaneNormal(); + const btScalar& planeConstant = planeShape->getPlaneConstant(); + btTransform planeInConvex; + planeInConvex= convexObj->getWorldTransform().inverse() * planeObj->getWorldTransform(); + btTransform convexInPlaneTrans; + convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexObj->getWorldTransform(); + + btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal); + btVector3 vtxInPlane = convexInPlaneTrans(vtx); + btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant); + + btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal; + btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected; + + hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold(); + resultOut->setPersistentManifold(m_manifoldPtr); + if (hasCollision) + { + /// report a contact. internally this will be kept persistent, and contact reduction is done + btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal; + btVector3 pOnB = vtxInPlaneWorld; + resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance); + } + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } +} + +btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h new file mode 100644 index 00000000000..7b258554171 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H +#define CONVEX_PLANE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" + +/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. +/// Other features are frame-coherency (persistent data) and collision response. +class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + bool m_isSwapped; + +public: + + btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btConvexPlaneCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp new file mode 100644 index 00000000000..1c317080544 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -0,0 +1,291 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btDefaultCollisionConfiguration.h" + +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM +#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" +#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" + + + +#include "LinearMath/btStackAlloc.h" +#include "LinearMath/btPoolAllocator.h" + + + + + +btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool) +{ + + void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16); + m_simplexSolver = new (mem)btVoronoiSimplexSolver(); + +#define USE_EPA 1 +#ifdef USE_EPA + mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16); + m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver; +#else + mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16); + m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver; +#endif//USE_EPA + + + //default CreationFunctions, filling the m_doubleDispatch table + mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16); + m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver); + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16); + m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16); + m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc; + mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16); + m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); + m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); + m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; + m_boxSphereCF->m_swapped = true; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); + m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; + m_triangleSphereCF->m_swapped = true; + + mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16); + m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc; + + //convex versus plane + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16); + m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc; + m_planeConvexCF->m_swapped = true; + + ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool + int maxSize = sizeof(btConvexConvexAlgorithm); + int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm); + int maxSize3 = sizeof(btCompoundCollisionAlgorithm); + int maxSize4 = sizeof(btEmptyAlgorithm); + + int collisionAlgorithmMaxElementSize = btMax(maxSize,maxSize2); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3); + collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize4); + + if (constructionInfo.m_stackAlloc) + { + m_ownsStackAllocator = false; + this->m_stackAlloc = constructionInfo.m_stackAlloc; + } else + { + m_ownsStackAllocator = true; + void* mem = btAlignedAlloc(sizeof(btStackAlloc),16); + m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize); + } + + if (constructionInfo.m_persistentManifoldPool) + { + m_ownsPersistentManifoldPool = false; + m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool; + } else + { + m_ownsPersistentManifoldPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize); + } + + if (constructionInfo.m_collisionAlgorithmPool) + { + m_ownsCollisionAlgorithmPool = false; + m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool; + } else + { + m_ownsCollisionAlgorithmPool = true; + void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16); + m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize); + } + + +} + +btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() +{ + if (m_ownsStackAllocator) + { + m_stackAlloc->destroy(); + m_stackAlloc->~btStackAlloc(); + btAlignedFree(m_stackAlloc); + } + if (m_ownsCollisionAlgorithmPool) + { + m_collisionAlgorithmPool->~btPoolAllocator(); + btAlignedFree(m_collisionAlgorithmPool); + } + if (m_ownsPersistentManifoldPool) + { + m_persistentManifoldPool->~btPoolAllocator(); + btAlignedFree(m_persistentManifoldPool); + } + + m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConvexCreateFunc); + + m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexConcaveCreateFunc); + m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedConvexConcaveCreateFunc); + + m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_compoundCreateFunc); + + m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedCompoundCreateFunc); + + m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_emptyCreateFunc); + + m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereSphereCF); + +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereBoxCF); + m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxSphereCF); +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_sphereTriangleCF); + m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_triangleSphereCF); + m_boxBoxCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_boxBoxCF); + + m_convexPlaneCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_convexPlaneCF); + m_planeConvexCF->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_planeConvexCF); + + m_simplexSolver->~btVoronoiSimplexSolver(); + btAlignedFree(m_simplexSolver); + + m_pdSolver->~btConvexPenetrationDepthSolver(); + + btAlignedFree(m_pdSolver); + + +} + + +btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_sphereSphereCF; + } +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) + { + return m_sphereBoxCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_boxSphereCF; + } +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) + { + return m_sphereTriangleCF; + } + + if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE)) + { + return m_triangleSphereCF; + } + + if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE)) + { + return m_boxBoxCF; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE)) + { + return m_convexPlaneCF; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE)) + { + return m_planeConvexCF; + } + + + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_convexConvexCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_convexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0)) + { + return m_swappedConvexConcaveCreateFunc; + } + + if (btBroadphaseProxy::isCompound(proxyType0)) + { + return m_compoundCreateFunc; + } else + { + if (btBroadphaseProxy::isCompound(proxyType1)) + { + return m_swappedCompoundCreateFunc; + } + } + + //failed to find an algorithm + return m_emptyCreateFunc; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h new file mode 100644 index 00000000000..4f5af5f048c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -0,0 +1,115 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_DEFAULT_COLLISION_CONFIGURATION +#define BT_DEFAULT_COLLISION_CONFIGURATION + +#include "btCollisionConfiguration.h" +class btVoronoiSimplexSolver; +class btConvexPenetrationDepthSolver; + +struct btDefaultCollisionConstructionInfo +{ + btStackAlloc* m_stackAlloc; + btPoolAllocator* m_persistentManifoldPool; + btPoolAllocator* m_collisionAlgorithmPool; + int m_defaultMaxPersistentManifoldPoolSize; + int m_defaultMaxCollisionAlgorithmPoolSize; + int m_defaultStackAllocatorSize; + + btDefaultCollisionConstructionInfo() + :m_stackAlloc(0), + m_persistentManifoldPool(0), + m_collisionAlgorithmPool(0), + m_defaultMaxPersistentManifoldPoolSize(65535), + m_defaultMaxCollisionAlgorithmPoolSize(65535), + m_defaultStackAllocatorSize(5*1024*1024) + { + } +}; + + + +///btCollisionConfiguration allows to configure Bullet collision detection +///stack allocator, pool memory allocators +///todo: describe the meaning +class btDefaultCollisionConfiguration : public btCollisionConfiguration +{ + + int m_persistentManifoldPoolSize; + + btStackAlloc* m_stackAlloc; + bool m_ownsStackAllocator; + + btPoolAllocator* m_persistentManifoldPool; + bool m_ownsPersistentManifoldPool; + + btPoolAllocator* m_collisionAlgorithmPool; + bool m_ownsCollisionAlgorithmPool; + + //default simplex/penetration depth solvers + btVoronoiSimplexSolver* m_simplexSolver; + btConvexPenetrationDepthSolver* m_pdSolver; + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_compoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; + btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; + btCollisionAlgorithmCreateFunc* m_sphereSphereCF; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM + btCollisionAlgorithmCreateFunc* m_sphereBoxCF; + btCollisionAlgorithmCreateFunc* m_boxSphereCF; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + + btCollisionAlgorithmCreateFunc* m_boxBoxCF; + btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; + btCollisionAlgorithmCreateFunc* m_triangleSphereCF; + btCollisionAlgorithmCreateFunc* m_planeConvexCF; + btCollisionAlgorithmCreateFunc* m_convexPlaneCF; + +public: + + + btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btDefaultCollisionConfiguration(); + + ///memory pools + virtual btPoolAllocator* getPersistentManifoldPool() + { + return m_persistentManifoldPool; + } + + virtual btPoolAllocator* getCollisionAlgorithmPool() + { + return m_collisionAlgorithmPool; + } + + virtual btStackAlloc* getStackAllocator() + { + return m_stackAlloc; + } + + + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + + +}; + +#endif //BT_DEFAULT_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h index b1a193d2cfd..e54721dec21 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h @@ -15,8 +15,9 @@ subject to the following restrictions: #ifndef EMPTY_ALGORITH #define EMPTY_ALGORITH -#include "../BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" #include "btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" #define ATTRIBUTE_ALIGNED(a) @@ -33,13 +34,18 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + } + struct CreateFunc :public btCollisionAlgorithmCreateFunc { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { (void)body0; (void)body1; - return new btEmptyAlgorithm(ci); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm)); + return new(mem) btEmptyAlgorithm(ci); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp index 490acc0b611..d5b12598be2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.cpp @@ -79,12 +79,30 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b } btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth); - + newPt.m_positionWorldOnA = pointA; + newPt.m_positionWorldOnB = pointInWorld; + int insertIndex = m_manifoldPtr->getCacheEntry(newPt); newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1); newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1); + //BP mod, store contact triangles. + newPt.m_partId0 = m_partId0; + newPt.m_partId1 = m_partId1; + newPt.m_index0 = m_index0; + newPt.m_index1 = m_index1; + + ///todo, check this for any side effects + if (insertIndex >= 0) + { + //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); + m_manifoldPtr->replaceContactPoint(newPt,insertIndex); + } else + { + insertIndex = m_manifoldPtr->addManifoldPoint(newPt); + } + //User can override friction and/or restitution if (gContactAddedCallback && //and if either of the two bodies requires custom material @@ -94,16 +112,8 @@ void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const b //experimental feature info, for per-triangle material etc. btCollisionObject* obj0 = isSwapped? m_body1 : m_body0; btCollisionObject* obj1 = isSwapped? m_body0 : m_body1; - (*gContactAddedCallback)(newPt,obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); + (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,m_partId0,m_index0,obj1,m_partId1,m_index1); } - if (insertIndex >= 0) - { - //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex); - m_manifoldPtr->replaceContactPoint(newPt,insertIndex); - } else - { - m_manifoldPtr->AddManifoldPoint(newPt); - } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h index 77192625513..5aac9a46f6a 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btManifoldResult.h @@ -18,12 +18,12 @@ subject to the following restrictions: #define MANIFOLD_RESULT_H class btCollisionObject; -class btPersistentManifold; +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" class btManifoldPoint; #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btTransform.h" typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1); extern ContactAddedCallback gContactAddedCallback; @@ -60,6 +60,15 @@ public: m_manifoldPtr = manifoldPtr; } + const btPersistentManifold* getPersistentManifold() const + { + return m_manifoldPtr; + } + btPersistentManifold* getPersistentManifold() + { + return m_manifoldPtr; + } + virtual void setShapeIdentifiers(int partId0,int index0, int partId1,int index1) { m_partId0=partId0; @@ -70,6 +79,22 @@ public: virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth); + SIMD_FORCE_INLINE void refreshContactPoints() + { + btAssert(m_manifoldPtr); + if (!m_manifoldPtr->getNumContacts()) + return; + + bool isSwapped = m_manifoldPtr->getBody0() != m_body0; + + if (isSwapped) + { + m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA); + } else + { + m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB); + } + } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index ac2e8554c3a..1cc78f76acd 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -1,3 +1,17 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ #include "LinearMath/btScalar.h" @@ -7,7 +21,7 @@ #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionDispatch/btCollisionWorld.h" -#include +//#include #include "LinearMath/btQuickprof.h" btSimulationIslandManager::btSimulationIslandManager() @@ -25,17 +39,17 @@ void btSimulationIslandManager::initUnionFind(int n) } -void btSimulationIslandManager::findUnions(btDispatcher* dispatcher) +void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld) { { - for (int i=0;igetNumManifolds();i++) - { - const btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); - //static objects (invmass btScalar(0.)) don't merge ! + btBroadphasePair* pairPtr = colWorld->getPairCache()->getOverlappingPairArrayPtr(); - const btCollisionObject* colObj0 = static_cast(manifold->getBody0()); - const btCollisionObject* colObj1 = static_cast(manifold->getBody1()); + for (int i=0;igetPairCache()->getNumOverlappingPairs();i++) + { + const btBroadphasePair& collisionPair = pairPtr[i]; + btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject; + btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject; if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && ((colObj1) && ((colObj1)->mergesSimulationIslands()))) @@ -71,7 +85,7 @@ void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld } // do the union find - findUnions(dispatcher); + findUnions(dispatcher,colWorld); @@ -129,30 +143,13 @@ class btPersistentManifoldSortPredicate }; - - - -// -// todo: this is random access, it can be walked 'cache friendly'! -// -void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) +void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects) { + BT_PROFILE("islandUnionFindAndQuickSort"); - - /*if (0) - { - int maxNumManifolds = dispatcher->getNumManifolds(); - btCollisionDispatcher* colDis = (btCollisionDispatcher*)dispatcher; - btPersistentManifold** manifold = colDis->getInternalManifoldPointer(); - callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, 0); - return; - } - */ + m_islandmanifold.resize(0); - - BEGIN_PROFILE("islandUnionFindAndHeapSort"); - //we are going to sort the unionfind array, and store the element id in the size //afterwards, we clean unionfind, to make sure no-one uses it anymore @@ -183,7 +180,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { - printf("error in island management\n"); +// printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -210,7 +207,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { - printf("error in island management\n"); +// printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -231,7 +228,7 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionObject* colObj0 = collisionObjects[i]; if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1)) { - printf("error in island management\n"); +// printf("error in island management\n"); } assert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1)); @@ -247,11 +244,17 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, } } - btAlignedObjectArray islandmanifold; + int i; int maxNumManifolds = dispatcher->getNumManifolds(); - islandmanifold.reserve(maxNumManifolds); +#define SPLIT_ISLANDS 1 +#ifdef SPLIT_ISLANDS + + +#endif //SPLIT_ISLANDS + + for (i=0;igetManifoldByIndexInternal(i); @@ -265,29 +268,52 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, { //kinematic objects don't merge islands, but wake up all connected objects - if (colObj0->isStaticOrKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) + if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING) { colObj1->activate(); } - if (colObj1->isStaticOrKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) + if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING) { colObj0->activate(); } - - //filtering for response +#ifdef SPLIT_ISLANDS + // //filtering for response if (dispatcher->needsResponse(colObj0,colObj1)) - islandmanifold.push_back(manifold); + m_islandmanifold.push_back(manifold); +#endif //SPLIT_ISLANDS } } +} - int numManifolds = int (islandmanifold.size()); + +// +// todo: this is random access, it can be walked 'cache friendly'! +// +void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback) +{ + + buildIslands(dispatcher,collisionObjects); + + int endIslandIndex=1; + int startIslandIndex; + int numElem = getUnionFind().getNumElements(); + + BT_PROFILE("processIslands"); + +#ifndef SPLIT_ISLANDS + btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer(); + + callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1); +#else // Sort manifolds, based on islands // Sort the vector using predicate and std::sort //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate); + int numManifolds = int (m_islandmanifold.size()); + //we should do radix sort, it it much faster (O(n) instead of O (n log2(n)) - islandmanifold.heapSort(btPersistentManifoldSortPredicate()); + m_islandmanifold.quickSort(btPersistentManifoldSortPredicate()); //now process all active islands (sets of manifolds for now) @@ -296,10 +322,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, //int islandId; - END_PROFILE("islandUnionFindAndHeapSort"); - - btAlignedObjectArray islandBodies; + +// printf("Start Islands\n"); //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated for ( startIslandIndex=0;startIslandIndexisActive()) islandSleeping = true; } @@ -325,12 +350,12 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, if (startManifoldIndexProcessIsland(&islandBodies[0],islandBodies.size(),startManifold,numIslandManifolds, islandId); + callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId); +// printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds); } if (numIslandManifolds) @@ -350,8 +376,9 @@ void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, startManifoldIndex = endManifoldIndex; } - islandBodies.resize(0); + m_islandBodies.resize(0); } +#endif //SPLIT_ISLANDS + - } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h index d91ed1c20eb..5f4d54cd803 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.h @@ -16,18 +16,26 @@ subject to the following restrictions: #ifndef SIMULATION_ISLAND_MANAGER_H #define SIMULATION_ISLAND_MANAGER_H -#include "../CollisionDispatch/btUnionFind.h" +#include "BulletCollision/CollisionDispatch/btUnionFind.h" #include "btCollisionCreateFunc.h" +#include "LinearMath/btAlignedObjectArray.h" + class btCollisionObject; class btCollisionWorld; class btDispatcher; +class btPersistentManifold; + ///SimulationIslandManager creates and handles simulation islands, using btUnionFind class btSimulationIslandManager { btUnionFind m_unionFind; + btAlignedObjectArray m_islandmanifold; + btAlignedObjectArray m_islandBodies; + + public: btSimulationIslandManager(); virtual ~btSimulationIslandManager(); @@ -42,7 +50,7 @@ public: virtual void storeIslandActivationState(btCollisionWorld* world); - void findUnions(btDispatcher* dispatcher); + void findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld); @@ -55,6 +63,8 @@ public: void buildAndProcessIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects, IslandCallback* callback); + void buildIslands(btDispatcher* dispatcher,btCollisionObjectArray& collisionObjects); + }; #endif //SIMULATION_ISLAND_MANAGER_H diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp index 05556bd34e2..1e4bbce451d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp @@ -68,18 +68,25 @@ void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,b btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius); + resultOut->setPersistentManifold(m_manifoldPtr); + if (dist < SIMD_EPSILON) { btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize(); /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist); } - + if (m_ownManifold) + { + if (m_manifoldPtr->getNumContacts()) + { + resultOut->refreshContactPoints(); + } + } } @@ -102,8 +109,8 @@ btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* box btVector3 bounds[2]; btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape(); - bounds[0] = -boxShape->getHalfExtents(); - bounds[1] = boxShape->getHalfExtents(); + bounds[0] = -boxShape->getHalfExtentsWithoutMargin(); + bounds[1] = boxShape->getHalfExtentsWithoutMargin(); margins = boxShape->getMargin();//also add sphereShape margin? @@ -209,6 +216,10 @@ btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* btVector3 p0, tmp, prel, n[6], normal; btScalar fSep = btScalar(-10000000.0), fSepThis; + // set p0 and normal to a default value to shup up GCC + p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + n[0].setValue( btScalar(-1.0), btScalar(0.0), btScalar(0.0) ); n[1].setValue( btScalar(0.0), btScalar(-1.0), btScalar(0.0) ); n[2].setValue( btScalar(0.0), btScalar(0.0), btScalar(-1.0) ); diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h index 07592909200..158f0ffcc74 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h @@ -16,11 +16,13 @@ subject to the following restrictions: #ifndef SPHERE_BOX_COLLISION_ALGORITHM_H #define SPHERE_BOX_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; -#include "../../LinearMath/btVector3.h" +#include "btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" /// btSphereBoxCollisionAlgorithm provides sphere-box collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -40,6 +42,14 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } + btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius ); btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax); @@ -48,12 +58,13 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm)); if (!m_swapped) { - return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false); } else { - return new btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); + return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true); } } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp index 424ff432f84..c9256473c00 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp @@ -46,6 +46,8 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 if (!m_manifoldPtr) return; + resultOut->setPersistentManifold(m_manifoldPtr); + btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape(); btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape(); @@ -54,23 +56,34 @@ void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0 btScalar radius0 = sphere0->getRadius(); btScalar radius1 = sphere1->getRadius(); + //m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting + ///iff distance positive, don't generate a new contact if ( len > (radius0+radius1)) + { return; - + } ///distance (negative means penetration) btScalar dist = len - (radius0+radius1); - btVector3 normalOnSurfaceB = diff / len; + btVector3 normalOnSurfaceB(1,0,0); + if (len > SIMD_EPSILON) + { + normalOnSurfaceB = diff / len; + } + ///point on A (worldspace) btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB; ///point on B (worldspace) btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB; /// report a contact. internally this will be kept persistent, and contact reduction is done - resultOut->setPersistentManifold(m_manifoldPtr); + + resultOut->addContactPoint(normalOnSurfaceB,pos1,dist); + //no resultOut->refreshContactPoints(); needed, because of clearManifold (all points are new) + } btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h index 7a19ff31edf..afdc2ee7fa0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h @@ -16,9 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H #define SPHERE_SPHERE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btCollisionDispatcher.h" + class btPersistentManifold; /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. @@ -39,6 +41,13 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } virtual ~btSphereSphereCollisionAlgorithm(); @@ -46,7 +55,8 @@ public: { virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btSphereSphereCollisionAlgorithm(0,ci,body0,body1); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm)); + return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index b011b707e3f..fdbd4abef27 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -48,8 +48,11 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co if (!m_manifoldPtr) return; - btSphereShape* sphere = (btSphereShape*)col0->getCollisionShape(); - btTriangleShape* triangle = (btTriangleShape*)col1->getCollisionShape(); + btCollisionObject* sphereObj = m_swapped? col1 : col0; + btCollisionObject* triObj = m_swapped? col0 : col1; + + btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape(); + btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape(); /// report a contact. internally this will be kept persistent, and contact reduction is done resultOut->setPersistentManifold(m_manifoldPtr); @@ -57,11 +60,16 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co btDiscreteCollisionDetectorInterface::ClosestPointInput input; input.m_maximumDistanceSquared = btScalar(1e30);//todo: tighter bounds - input.m_transformA = col0->getWorldTransform(); - input.m_transformB = col1->getWorldTransform(); + input.m_transformA = sphereObj->getWorldTransform(); + input.m_transformB = triObj->getWorldTransform(); - detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw); + bool swapResults = m_swapped; + detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); + + if (m_ownManifold) + resultOut->refreshContactPoints(); + } btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h index 57c6e6af619..bbaf228c44c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h @@ -16,10 +16,11 @@ subject to the following restrictions: #ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H #define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H -#include "../BroadphaseCollision/btCollisionAlgorithm.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" class btPersistentManifold; +#include "btCollisionDispatcher.h" /// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection. /// Other features are frame-coherency (persistent data) and collision response. @@ -40,6 +41,13 @@ public: virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + { + manifoldArray.push_back(m_manifoldPtr); + } + } virtual ~btSphereTriangleCollisionAlgorithm(); @@ -49,7 +57,9 @@ public: virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) { - return new btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm)); + + return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped); } }; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp index 62254335796..bb01b60fa85 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.cpp @@ -18,6 +18,7 @@ subject to the following restrictions: + btUnionFind::~btUnionFind() { Free(); @@ -76,8 +77,7 @@ void btUnionFind::sortIslands() // Sort the vector using predicate and std::sort //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate); - //perhaps use radix sort? - m_elements.heapSort(btUnionFindElementSortPredicate()); + m_elements.quickSort(btUnionFindElementSortPredicate()); } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h index 236cc33b94f..820c8bc858e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btUnionFind.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef UNION_FIND_H #define UNION_FIND_H -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" #define USE_PATH_COMPRESSION 1 @@ -46,11 +46,11 @@ class btUnionFind void reset(int N); - inline int getNumElements() const + SIMD_FORCE_INLINE int getNumElements() const { return int(m_elements.size()); } - inline bool isRoot(int x) const + SIMD_FORCE_INLINE bool isRoot(int x) const { return (x == m_elements[x].m_id); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp index 636b0046c13..8bc2cfa6ffa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -15,35 +15,20 @@ subject to the following restrictions: #include "btBoxShape.h" -btVector3 btBoxShape::getHalfExtents() const -{ - return m_implicitShapeDimensions * m_localScaling; -} + //{ void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { - btVector3 halfExtents = getHalfExtents(); - - btMatrix3x3 abs_b = t.getBasis().absolute(); - btPoint3 center = t.getOrigin(); - btVector3 extent = btVector3(abs_b[0].dot(halfExtents), - abs_b[1].dot(halfExtents), - abs_b[2].dot(halfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - - aabbMin = center - extent; - aabbMax = center + extent; - - + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); } -void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //btScalar margin = btScalar(0.); - btVector3 halfExtents = getHalfExtents(); + btVector3 halfExtents = getHalfExtentsWithMargin(); btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h index bc42f146c7c..4d4fbefea37 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.h @@ -18,11 +18,11 @@ subject to the following restrictions: #include "btPolyhedralConvexShape.h" #include "btCollisionMargin.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btSimdMinMax.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btMinMax.h" -///btBoxShape implements both a feature based (vertex/edge/plane) and implicit (getSupportingVertex) Box +///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space. class btBoxShape: public btPolyhedralConvexShape { @@ -31,47 +31,52 @@ class btBoxShape: public btPolyhedralConvexShape public: - btVector3 getHalfExtents() const; - + btVector3 getHalfExtentsWithMargin() const + { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; + return halfExtents; + } + + const btVector3& getHalfExtentsWithoutMargin() const + { + return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included + } + + virtual int getShapeType() const { return BOX_SHAPE_PROXYTYPE;} virtual btVector3 localGetSupportingVertex(const btVector3& vec) const { + btVector3 halfExtents = getHalfExtentsWithoutMargin(); + btVector3 margin(getMargin(),getMargin(),getMargin()); + halfExtents += margin; - btVector3 halfExtents = getHalfExtents(); - - btVector3 supVertex; - supVertex = btPoint3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); - - return supVertex; + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); } - virtual inline btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - btVector3 halfExtents = getHalfExtents(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents -= margin; - - return btVector3(vec.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), - vec.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), - vec.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + + return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()), + btFsels(vec.y(), halfExtents.y(), -halfExtents.y()), + btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); } virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { - btVector3 halfExtents = getHalfExtents(); - btVector3 margin(getMargin(),getMargin(),getMargin()); - halfExtents -= margin; - - + const btVector3& halfExtents = getHalfExtentsWithoutMargin(); + for (int i=0;icalculateAabbBruteForce(bvhAabbMin,bvhAabbMax); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + if(meshInterface->hasPremadeAabb()) + { + meshInterface->getPremadeAabb(&bvhAabbMin, &bvhAabbMax); + } + else + { + meshInterface->calculateAabbBruteForce(bvhAabbMin,bvhAabbMax); + } + + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } #endif //DISABLE_BVH } -btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax) -:btTriangleMeshShape(meshInterface),m_useQuantizedAabbCompression(useQuantizedAabbCompression) +btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh) +:btTriangleMeshShape(meshInterface), +m_bvh(0), +m_useQuantizedAabbCompression(useQuantizedAabbCompression), +m_ownsBvh(false) { //construct bvh from meshInterface #ifndef DISABLE_BVH - m_bvh = new btOptimizedBvh(); - m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + if (buildBvh) + { + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new (mem) btOptimizedBvh(); + + m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax); + m_ownsBvh = true; + } #endif //DISABLE_BVH @@ -58,16 +82,140 @@ void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btV } -void btBvhTriangleMeshShape::refitTree() +void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax) { - m_bvh->refit( m_meshInterface ); + m_bvh->refit( m_meshInterface, aabbMin,aabbMax ); recalcLocalAabb(); } btBvhTriangleMeshShape::~btBvhTriangleMeshShape() { - delete m_bvh; + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } +} + +void btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget); +} + +void btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) +{ + struct MyNodeOverlapCallback : public btNodeOverlapCallback + { + btStridingMeshInterface* m_meshInterface; + btTriangleCallback* m_callback; + + MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface) + :m_meshInterface(meshInterface), + m_callback(callback) + { + } + + virtual void processNode(int nodeSubPart, int nodeTriangleIndex) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + nodeSubPart); + + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + + const btVector3& meshScaling = m_meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + + /* Perform ray vs. triangle collision here */ + m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex); + m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + } + }; + + MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface); + + m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax); } //perform bvh tree traversal and report overlapping triangles to 'callback' @@ -118,13 +266,14 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co indicestype, nodeSubPart); - int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); const btVector3& meshScaling = m_meshInterface->getScaling(); for (int j=2;j>=0;j--) { - int graphicsindex = gfxbase[j]; + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; #ifdef DEBUG_TRIANGLE_MESH @@ -157,17 +306,37 @@ void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,co } - -void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) { - if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) - { - btTriangleMeshShape::setLocalScaling(scaling); - delete m_bvh; - ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work - m_bvh = new btOptimizedBvh(); - //rebuild the bvh... - m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); - - } + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + if (m_ownsBvh) + { + m_bvh->~btOptimizedBvh(); + btAlignedFree(m_bvh); + } + ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work + void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16); + m_bvh = new(mem) btOptimizedBvh(); + //rebuild the bvh... + m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax); + m_ownsBvh = true; + } } + +void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling) +{ + btAssert(!m_bvh); + btAssert(!m_ownsBvh); + + m_bvh = bvh; + m_ownsBvh = false; + // update the scaling without rebuilding the bvh + if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON) + { + btTriangleMeshShape::setLocalScaling(scaling); + } +} + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h index 4914d9f959c..6e587340dc1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h @@ -18,45 +18,55 @@ subject to the following restrictions: #include "btTriangleMeshShape.h" #include "btOptimizedBvh.h" +#include "LinearMath/btAlignedAllocator.h" -///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization. -///Uses an interface to access the triangles to allow for sharing graphics/physics triangles. + +///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage. +///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method. +///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk. +///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example. ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape { btOptimizedBvh* m_bvh; bool m_useQuantizedAabbCompression; - bool m_pad[12];////need padding due to alignment + bool m_ownsBvh; + bool m_pad[11];////need padding due to alignment public: - btBvhTriangleMeshShape() :btTriangleMeshShape(0) {}; - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression); + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btBvhTriangleMeshShape() :btTriangleMeshShape(0),m_bvh(0),m_ownsBvh(false) {}; + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true); ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb - btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax); + btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true); virtual ~btBvhTriangleMeshShape(); - - /* + bool getOwnsBvh () const + { + return m_ownsBvh; + } + virtual int getShapeType() const { return TRIANGLE_MESH_SHAPE_PROXYTYPE; } - */ - - + + void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget); + void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax); virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - void refitTree(); + void refitTree(const btVector3& aabbMin,const btVector3& aabbMax); ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks void partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax); //debugging - virtual char* getName()const {return "BVHTRIANGLEMESH";} + virtual const char* getName()const {return "BVHTRIANGLEMESH";} virtual void setLocalScaling(const btVector3& scaling); @@ -65,6 +75,10 @@ public: { return m_bvh; } + + + void setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1)); + bool usesQuantizedAabbCompression() const { return m_useQuantizedAabbCompression; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp index b7e15172da2..26ba276b900 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.cpp @@ -21,6 +21,7 @@ subject to the following restrictions: btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) { + m_upAxis = 1; m_implicitShapeDimensions.setValue(radius,0.5f*height,radius); } @@ -50,7 +51,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) { - btVector3 pos(0,getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = getHalfHeight(); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -60,7 +63,9 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } } { - btVector3 pos(0,-getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); + vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -88,7 +93,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) btVector3 vtx; btScalar newDot; { - btVector3 pos(0,getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = getHalfHeight(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -98,7 +104,8 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } } { - btVector3 pos(0,-getHalfHeight(),0); + btVector3 pos(0,0,0); + pos[getUpAxis()] = -getHalfHeight(); vtx = pos +vec*m_localScaling*(radius) - vec * getMargin(); newDot = vec.dot(vtx); if (newDot > maxDot) @@ -112,7 +119,7 @@ btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) } -void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //as an approximation, take the inertia of the box that bounds the spheres @@ -122,7 +129,8 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) btScalar radius = getRadius(); - btVector3 halfExtents(radius,radius+getHalfHeight(),radius); + btVector3 halfExtents(radius,radius,radius); + halfExtents[getUpAxis()]+=getHalfHeight(); btScalar margin = CONVEX_DISTANCE_MARGIN; @@ -140,6 +148,22 @@ void btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) } +btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height) +{ + m_upAxis = 0; + m_implicitShapeDimensions.setValue(0.5f*height, radius,radius); +} + + + + + + +btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height) +{ + m_upAxis = 2; + m_implicitShapeDimensions.setValue(radius,radius,0.5f*height); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h index 27da8adefa5..d4b046d40c9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -16,20 +16,27 @@ subject to the following restrictions: #ifndef BT_CAPSULE_SHAPE_H #define BT_CAPSULE_SHAPE_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -///btCapsuleShape represents a capsule around the Y axis -///A more general solution that can represent capsules is the btMultiSphereShape -class btCapsuleShape : public btConvexShape +///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis. +///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres. +class btCapsuleShape : public btConvexInternalShape { +protected: + int m_upAxis; + +protected: + ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses. + btCapsuleShape() {}; public: btCapsuleShape(btScalar radius,btScalar height); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -38,23 +45,76 @@ public: virtual int getShapeType() const { return CAPSULE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const + { + btVector3 halfExtents(getRadius(),getRadius(),getRadius()); + halfExtents[m_upAxis] = getRadius() + getHalfHeight(); + halfExtents += btVector3(getMargin(),getMargin(),getMargin()); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btPoint3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); + + aabbMin = center - extent; + aabbMax = center + extent; + } + + virtual const char* getName()const { return "CapsuleShape"; } + int getUpAxis() const + { + return m_upAxis; + } + btScalar getRadius() const { - return m_implicitShapeDimensions.getX(); + int radiusAxis = (m_upAxis+2)%3; + return m_implicitShapeDimensions[radiusAxis]; } btScalar getHalfHeight() const { - return m_implicitShapeDimensions.getY(); + return m_implicitShapeDimensions[m_upAxis]; } }; +///btCapsuleShapeX represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeX : public btCapsuleShape +{ +public: + + btCapsuleShapeX(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleX"; + } + + + +}; + +///btCapsuleShapeZ represents a capsule around the Z axis +///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps. +class btCapsuleShapeZ : public btCapsuleShape +{ +public: + btCapsuleShapeZ(btScalar radius,btScalar height); + + //debugging + virtual const char* getName()const + { + return "CapsuleZ"; + } + + +}; + #endif //BT_CAPSULE_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp index 81d82428f4c..39e621aa946 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.cpp @@ -21,7 +21,12 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" void btBulletCollisionProbe () {} +extern "C" +{ +void btBulletCollisionProbe (); + +void btBulletCollisionProbe () {} +} @@ -46,7 +51,7 @@ btScalar btCollisionShape::getAngularMotionDisc() const return disc; } -void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) +void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const { //start with static aabb getAabb(curTrans,temporalAabbMin,temporalAabbMax); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h index 96268734a83..3a352b90777 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCollisionShape.h @@ -16,18 +16,21 @@ subject to the following restrictions: #ifndef COLLISION_SHAPE_H #define COLLISION_SHAPE_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btMatrix3x3.h" -#include "../../LinearMath/btPoint3.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" //for the shape types +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btPoint3.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types -///btCollisionShape provides interface for collision shapes that can be shared among btCollisionObjects. +///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects. class btCollisionShape { + + void* m_userPointer; + public: - btCollisionShape() + btCollisionShape() : m_userPointer(0) { } virtual ~btCollisionShape() @@ -45,30 +48,30 @@ public: ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep) ///result is conservative - void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax); + void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const; #ifndef __SPU__ - inline bool isPolyhedral() const + SIMD_FORCE_INLINE bool isPolyhedral() const { return btBroadphaseProxy::isPolyhedral(getShapeType()); } - inline bool isConvex() const + SIMD_FORCE_INLINE bool isConvex() const { return btBroadphaseProxy::isConvex(getShapeType()); } - inline bool isConcave() const + SIMD_FORCE_INLINE bool isConcave() const { return btBroadphaseProxy::isConcave(getShapeType()); } - inline bool isCompound() const + SIMD_FORCE_INLINE bool isCompound() const { return btBroadphaseProxy::isCompound(getShapeType()); } ///isInfinite is used to catch simulation error (aabb check) - inline bool isInfinite() const + SIMD_FORCE_INLINE bool isInfinite() const { return btBroadphaseProxy::isInfinite(getShapeType()); } @@ -76,11 +79,11 @@ public: virtual int getShapeType() const=0; virtual void setLocalScaling(const btVector3& scaling) =0; virtual const btVector3& getLocalScaling() const =0; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) = 0; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0; //debugging support - virtual char* getName()const =0 ; + virtual const char* getName()const =0 ; #endif //__SPU__ @@ -88,6 +91,18 @@ public: virtual void setMargin(btScalar margin) = 0; virtual btScalar getMargin() const = 0; + + ///optional user data pointer + void setUserPointer(void* userPtr) + { + m_userPointer = userPtr; + } + + void* getUserPointer() const + { + return m_userPointer; + } + }; #endif //COLLISION_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index a4712b3e925..f08b810eadb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -14,29 +14,42 @@ subject to the following restrictions: */ #include "btCompoundShape.h" - - #include "btCollisionShape.h" - +#include "BulletCollision/BroadphaseCollision/btDbvt.h" btCompoundShape::btCompoundShape() :m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), -m_aabbTree(0), m_collisionMargin(btScalar(0.)), -m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_dynamicAabbTree(0) { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); } btCompoundShape::~btCompoundShape() { + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->~btDbvt(); + btAlignedFree(m_dynamicAabbTree); + } } void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) { - m_childTransforms.push_back(localTransform); - m_childShapes.push_back(shape); + //m_childTransforms.push_back(localTransform); + //m_childShapes.push_back(shape); + btCompoundShapeChild child; + child.m_transform = localTransform; + child.m_childShape = shape; + child.m_childShapeType = shape->getShapeType(); + child.m_childMargin = shape->getMargin(); + + m_children.push_back(child); //extend the local aabbMin/aabbMax btVector3 localAabbMin,localAabbMax; @@ -53,39 +66,100 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio } } + if (m_dynamicAabbTree) + { + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + int index = m_children.size()-1; + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + } +void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) +{ + btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); + } + m_children.swap(childShapeIndex,m_children.size()-1); + m_children.pop_back(); + +} + +void btCompoundShape::removeChildShape(btCollisionShape* shape) +{ + // Find the children containing the shape specified, and remove those children. + //note: there might be multiple children using the same shape! + for(int i = m_children.size()-1; i >= 0 ; i--) + { + if(m_children[i].m_childShape == shape) + { + m_children.swap(i,m_children.size()-1); + m_children.pop_back(); + //remove it from the m_dynamicAabbTree too + //m_dynamicAabbTree->remove(m_aabbProxies[i]); + //m_aabbProxies.swap(i,m_children.size()-1); + //m_aabbProxies.pop_back(); + } + } - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + + recalculateLocalAabb(); +} + +void btCompoundShape::recalculateLocalAabb() +{ + // Recalculate the local aabb + // Brute force, it iterates over all the shapes left. + m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + + //extend the local aabbMin/aabbMax + for (int j = 0; j < m_children.size(); j++) + { + btVector3 localAabbMin,localAabbMax; + m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + m_localAabbMin[i] = localAabbMin[i]; + if (m_localAabbMax[i] < localAabbMax[i]) + m_localAabbMax[i] = localAabbMax[i]; + } + } +} + +///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - + btMatrix3x3 abs_b = trans.getBasis().absolute(); btPoint3 center = trans(localCenter); btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center-extent; + aabbMax = center+extent; - aabbMin = center - extent; - aabbMax = center + extent; } -void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //approximation: take the inertia from the aabb for now btTransform ident; ident.setIdentity(); btVector3 aabbMin,aabbMax; getAabb(ident,aabbMin,aabbMax); - + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); - + btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); btScalar lz=btScalar(2.)*(halfExtents.z()); @@ -96,5 +170,62 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) } - - + + + +void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const +{ + int n = m_children.size(); + + btScalar totalMass = 0; + btVector3 center(0, 0, 0); + for (int k = 0; k < n; k++) + { + center += m_children[k].m_transform.getOrigin() * masses[k]; + totalMass += masses[k]; + } + center /= totalMass; + principal.setOrigin(center); + + btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); + for (int k = 0; k < n; k++) + { + btVector3 i; + m_children[k].m_childShape->calculateLocalInertia(masses[k], i); + + const btTransform& t = m_children[k].m_transform; + btVector3 o = t.getOrigin() - center; + + //compute inertia tensor in coordinate system of compound shape + btMatrix3x3 j = t.getBasis().transpose(); + j[0] *= i[0]; + j[1] *= i[1]; + j[2] *= i[2]; + j = t.getBasis() * j; + + //add inertia tensor + tensor[0] += j[0]; + tensor[1] += j[1]; + tensor[2] += j[2]; + + //compute inertia tensor of pointmass at o + btScalar o2 = o.length2(); + j[0].setValue(o2, 0, 0); + j[1].setValue(0, o2, 0); + j[2].setValue(0, 0, o2); + j[0] += o * -o.x(); + j[1] += o * -o.y(); + j[2] += o * -o.z(); + + //add inertia tensor of pointmass + tensor[0] += masses[k] * j[0]; + tensor[1] += masses[k] * j[1]; + tensor[2] += masses[k] * j[2]; + } + + tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); +} + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index 86dc1f80947..3624749f768 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -18,58 +18,97 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" -class btOptimizedBvh; +//class btOptimizedBvh; +struct btDbvt; + +ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild +{ + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTransform m_transform; + btCollisionShape* m_childShape; + int m_childShapeType; + btScalar m_childMargin; + struct btDbvtNode* m_node; +}; + +SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) +{ + return ( c1.m_transform == c2.m_transform && + c1.m_childShape == c2.m_childShape && + c1.m_childShapeType == c2.m_childShapeType && + c1.m_childMargin == c2.m_childMargin ); +} /// btCompoundShape allows to store multiple other btCollisionShapes -/// This allows for concave collision objects. This is more general then the Static Concave btTriangleMeshShape. -class btCompoundShape : public btCollisionShape +/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape. +ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape { - btAlignedObjectArray m_childTransforms; - btAlignedObjectArray m_childShapes; + //btAlignedObjectArray m_childTransforms; + //btAlignedObjectArray m_childShapes; + btAlignedObjectArray m_children; btVector3 m_localAabbMin; btVector3 m_localAabbMax; - btOptimizedBvh* m_aabbTree; + //btOptimizedBvh* m_aabbTree; + btDbvt* m_dynamicAabbTree; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btCompoundShape(); virtual ~btCompoundShape(); void addChildShape(const btTransform& localTransform,btCollisionShape* shape); + /// Remove all children shapes that contain the specified shape + virtual void removeChildShape(btCollisionShape* shape); + + void removeChildShapeByIndex(int childShapeindex); + + int getNumChildShapes() const { - return int (m_childShapes.size()); + return int (m_children.size()); } btCollisionShape* getChildShape(int index) { - return m_childShapes[index]; + return m_children[index].m_childShape; } const btCollisionShape* getChildShape(int index) const { - return m_childShapes[index]; + return m_children[index].m_childShape; } - btTransform& getChildTransform(int index) + btTransform getChildTransform(int index) { - return m_childTransforms[index]; + return m_children[index].m_transform; } - const btTransform& getChildTransform(int index) const + const btTransform getChildTransform(int index) const { - return m_childTransforms[index]; + return m_children[index].m_transform; + } + + + btCompoundShapeChild* getChildList() + { + return &m_children[0]; } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. + Use this yourself if you modify the children or their transforms. */ + virtual void recalculateLocalAabb(); virtual void setLocalScaling(const btVector3& scaling) { @@ -80,8 +119,8 @@ public: return m_localScaling; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); - + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} virtual void setMargin(btScalar margin) @@ -92,7 +131,7 @@ public: { return m_collisionMargin; } - virtual char* getName()const + virtual const char* getName()const { return "Compound"; } @@ -100,11 +139,19 @@ public: //this is optional, but should make collision queries faster, by culling non-overlapping nodes void createAabbTreeFromChildren(); - const btOptimizedBvh* getAabbTree() const + btDbvt* getDynamicAabbTree() { - return m_aabbTree; + return m_dynamicAabbTree; } + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform + ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. + void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; + + private: btScalar m_collisionMargin; protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h index 73f974e4ee9..f3f57206ab7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConcaveShape.h @@ -17,12 +17,12 @@ subject to the following restrictions: #define CONCAVE_SHAPE_H #include "btCollisionShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types #include "btTriangleCallback.h" -///Concave shape proves an interface concave shapes that can produce triangles that overlapping a given AABB. -///Static triangle mesh, infinite plane, height field/landscapes are example that implement this interface. +///The btConcaveShape class provides an interface for non-moving (static) concave shapes. +///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape. class btConcaveShape : public btCollisionShape { protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h index 3ccda5b12c6..685369742e4 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConeShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef CONE_MINKOWSKI_H #define CONE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -///btConeShape implements a Cone shape, around the Y axis -class btConeShape : public btConvexShape +///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis. +class btConeShape : public btConvexInternalShape { @@ -42,7 +42,7 @@ public: btScalar getHeight() const { return m_height;} - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { btTransform identity; identity.setIdentity(); @@ -72,7 +72,7 @@ public: virtual int getShapeType() const { return CONE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual const char* getName()const { return "Cone"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h index 3fd5e382525..c029ca19403 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexHullShape.h @@ -17,18 +17,17 @@ subject to the following restrictions: #define CONVEX_HULL_SHAPE_H #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types -#include "../../LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "LinearMath/btAlignedObjectArray.h" -///ConvexHullShape implements an implicit (getSupportingVertex) Convex Hull of a Point Cloud (vertices) -///No connectivity is needed. localGetSupportingVertex iterates linearly though all vertices. -///on modern hardware, due to cache coherency this isn't that bad. Complex algorithms tend to trash the cash. -///(memory is much slower then the cpu) +///The btConvexHullShape implements an implicit convex hull of an array of vertices. +///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex. ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexShape { btAlignedObjectArray m_points; public: + BT_DECLARE_ALIGNED_ALLOCATOR(); ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory. @@ -43,7 +42,12 @@ public: return &m_points[0]; } - int getNumPoints() + const btPoint3* getPoints() const + { + return &m_points[0]; + } + + int getNumPoints() const { return m_points.size(); } @@ -56,7 +60,7 @@ public: virtual int getShapeType()const { return CONVEX_HULL_SHAPE_PROXYTYPE; } //debugging - virtual char* getName()const {return "Convex";} + virtual const char* getName()const {return "Convex";} virtual int getNumVertices() const; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp new file mode 100644 index 00000000000..f828d28e18c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.cpp @@ -0,0 +1,78 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btConvexInternalShape.h" + + +btConvexInternalShape::btConvexInternalShape() +: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_collisionMargin(CONVEX_DISTANCE_MARGIN) +{ +} + + +void btConvexInternalShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + + + +void btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const +{ + + btScalar margin = getMargin(); + for (int i=0;i<3;i++) + { + btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); + vec[i] = btScalar(1.); + + btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); + + btVector3 tmp = trans(sv); + maxAabb[i] = tmp[i]+margin; + vec[i] = btScalar(-1.); + tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); + minAabb[i] = tmp[i]-margin; + } +}; + + +btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const +{ +#ifndef __SPU__ + + btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); + + if ( getMargin()!=btScalar(0.) ) + { + btVector3 vecnorm = vec; + if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) + { + vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); + } + vecnorm.normalize(); + supVertex+= getMargin() * vecnorm; + } + return supVertex; + +#else + return btVector3(0,0,0); +#endif //__SPU__ + + } + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h new file mode 100644 index 00000000000..9388ccf31f2 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexInternalShape.h @@ -0,0 +1,98 @@ + +#ifndef BT_CONVEX_INTERNAL_SHAPE_H +#define BT_CONVEX_INTERNAL_SHAPE_H + +#include "btConvexShape.h" + +///The btConvexInternalShape is an internal base class, shared by most convex shape implementations. +class btConvexInternalShape : public btConvexShape +{ + + protected: + + //local scaling. collisionMargin is not scaled ! + btVector3 m_localScaling; + + btVector3 m_implicitShapeDimensions; + + btScalar m_collisionMargin; + + btScalar m_padding; + +public: + + btConvexInternalShape(); + + virtual ~btConvexInternalShape() + { + + } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; +#ifndef __SPU__ + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; + + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; +#endif //#ifndef __SPU__ + + const btVector3& getImplicitShapeDimensions() const + { + return m_implicitShapeDimensions; + } + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + getAabbSlow(t,aabbMin,aabbMax); + } + + + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const + { + return m_localScaling; + } + + const btVector3& getLocalScalingNV() const + { + return m_localScaling; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + } + virtual btScalar getMargin() const + { + return m_collisionMargin; + } + + btScalar getMarginNV() const + { + return m_collisionMargin; + } + + virtual int getNumPreferredPenetrationDirections() const + { + return 0; + } + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const + { + (void)penetrationVector; + (void)index; + btAssert(0); + } + + + +}; + + +#endif //BT_CONVEX_INTERNAL_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp index 7edf1ea6db8..7afcccf8b03 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.cpp @@ -16,62 +16,3 @@ subject to the following restrictions: #include "btConvexShape.h" -btConvexShape::btConvexShape() -: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), -m_collisionMargin(CONVEX_DISTANCE_MARGIN) -{ -} - - -void btConvexShape::setLocalScaling(const btVector3& scaling) -{ - m_localScaling = scaling; -} - - - -void btConvexShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const -{ - - btScalar margin = getMargin(); - for (int i=0;i<3;i++) - { - btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.)); - vec[i] = btScalar(1.); - - btVector3 sv = localGetSupportingVertex(vec*trans.getBasis()); - - btVector3 tmp = trans(sv); - maxAabb[i] = tmp[i]+margin; - vec[i] = btScalar(-1.); - tmp = trans(localGetSupportingVertex(vec*trans.getBasis())); - minAabb[i] = tmp[i]-margin; - } -}; - - -btVector3 btConvexShape::localGetSupportingVertex(const btVector3& vec)const -{ -#ifndef __SPU__ - - btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec); - - if ( getMargin()!=btScalar(0.) ) - { - btVector3 vecnorm = vec; - if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON)) - { - vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.)); - } - vecnorm.normalize(); - supVertex+= getMargin() * vecnorm; - } - return supVertex; - -#else - return btVector3(0,0,0); -#endif //__SPU__ - - } - - diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h index 746f383dfc7..e4eb7f6dbf6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexShape.h @@ -18,37 +18,25 @@ subject to the following restrictions: #include "btCollisionShape.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" #include "btCollisionMargin.h" +#include "LinearMath/btAlignedAllocator.h" //todo: get rid of this btConvexCastResult thing! struct btConvexCastResult; #define MAX_PREFERRED_PENETRATION_DIRECTIONS 10 -/// btConvexShape is an abstract shape interface. -/// The explicit part provides plane-equations, the implicit part provides GetClosestPoint interface. -/// used in combination with GJK or btConvexCast +/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc. +/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector. ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape { -protected: - - //local scaling. collisionMargin is not scaled ! - btVector3 m_localScaling; - - btVector3 m_implicitShapeDimensions; - - btScalar m_collisionMargin; - - btScalar m_padding[2]; - - - public: - btConvexShape(); + + BT_DECLARE_ALIGNED_ALLOCATOR(); virtual ~btConvexShape() { @@ -56,7 +44,7 @@ public: } - virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const =0; #ifndef __SPU__ virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const= 0; @@ -64,63 +52,24 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0; #endif //#ifndef __SPU__ - const btVector3& getImplicitShapeDimensions() const - { - return m_implicitShapeDimensions; - } ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version - void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const - { - getAabbSlow(t,aabbMin,aabbMax); - } + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0; + virtual void setLocalScaling(const btVector3& scaling) =0; + virtual const btVector3& getLocalScaling() const =0; + + virtual void setMargin(btScalar margin)=0; + + virtual btScalar getMargin() const=0; + + virtual int getNumPreferredPenetrationDirections() const=0; - virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0; - - virtual void setLocalScaling(const btVector3& scaling); - virtual const btVector3& getLocalScaling() const - { - return m_localScaling; - } - - const btVector3& getLocalScalingNV() const - { - return m_localScaling; - } - - virtual void setMargin(btScalar margin) - { - m_collisionMargin = margin; - } - virtual btScalar getMargin() const - { - return m_collisionMargin; - } - - btScalar getMarginNV() const - { - return m_collisionMargin; - } - - virtual int getNumPreferredPenetrationDirections() const - { - return 0; - } - - virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const - { - (void)penetrationVector; - (void)index; - btAssert(0); - } - - - -} -; +}; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp index 6941030b15f..02a293e82ba 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -19,10 +19,11 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" -btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface) +btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb) :m_stridingMesh(meshInterface) { - recalcLocalAabb(); + if ( calcAabb ) + recalcLocalAabb(); } @@ -203,3 +204,113 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const { return m_stridingMesh->getScaling(); } + +void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const +{ + class CenterCallback: public btInternalTriangleIndexCallback + { + bool first; + btVector3 ref; + btVector3 sum; + btScalar volume; + + public: + + CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + if (first) + { + ref = triangle[0]; + first = false; + } + else + { + btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); + sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); + volume += vol; + } + } + + btVector3 getCenter() + { + return (volume > 0) ? sum / volume : ref; + } + + btScalar getVolume() + { + return volume * btScalar(1. / 6); + } + + }; + + class InertiaCallback: public btInternalTriangleIndexCallback + { + btMatrix3x3 sum; + btVector3 center; + + public: + + InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + btMatrix3x3 i; + btVector3 a = triangle[0] - center; + btVector3 b = triangle[1] - center; + btVector3 c = triangle[2] - center; + btVector3 abc = a + b + c; + btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); + for (int j = 0; j < 3; j++) + { + for (int k = 0; k <= j; k++) + { + i[j][k] = i[k][j] = volNeg * (center[j] * center[k] + + btScalar(0.25) * (center[j] * abc[k] + center[k] * abc[j]) + + btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); + } + } + btScalar i00 = -i[0][0]; + btScalar i11 = -i[1][1]; + btScalar i22 = -i[2][2]; + i[0][0] = i11 + i22; + i[1][1] = i22 + i00; + i[2][2] = i00 + i11; + sum[0] += i[0]; + sum[1] += i[1]; + sum[2] += i[2]; + } + + btMatrix3x3& getInertia() + { + return sum; + } + + }; + + CenterCallback centerCallback; + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); + btVector3 center = centerCallback.getCenter(); + principal.setOrigin(center); + volume = centerCallback.getVolume(); + + InertiaCallback inertiaCallback(center); + m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); + + btMatrix3x3& i = inertiaCallback.getInertia(); + i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(i[0][0], i[1][1], i[2][2]); + inertia /= volume; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h index 34ee7af744c..6ff0bf5d43b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -3,20 +3,24 @@ #include "btPolyhedralConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -/// btConvexTriangleMeshShape is a convex hull of a triangle mesh. If you just have a point cloud, you can use btConvexHullShape instead. -/// It uses the btStridingMeshInterface instead of a point cloud. This can avoid the duplication of the triangle mesh data. +/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape. +/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead. class btConvexTriangleMeshShape : public btPolyhedralConvexShape { class btStridingMeshInterface* m_stridingMesh; public: - btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface); + btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true); - class btStridingMeshInterface* getStridingMesh() + class btStridingMeshInterface* getMeshInterface() + { + return m_stridingMesh; + } + const class btStridingMeshInterface* getMeshInterface() const { return m_stridingMesh; } @@ -28,7 +32,7 @@ public: virtual int getShapeType()const { return CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE; } //debugging - virtual char* getName()const {return "ConvexTrimesh";} + virtual const char* getName()const {return "ConvexTrimesh";} virtual int getNumVertices() const; virtual int getNumEdges() const; @@ -42,6 +46,13 @@ public: virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" + ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. This method also computes the volume of the convex mesh. + void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; + }; @@ -49,3 +60,4 @@ public: #endif //CONVEX_TRIANGLEMESH_SHAPE_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp index 1666afb3b88..3afef1c7550 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCylinderShape.cpp @@ -45,7 +45,7 @@ void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& } -inline btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) +SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) { const int cylinderUpAxis = 0; const int XX = 1; @@ -163,24 +163,24 @@ const int ZZ = 1; btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportX(getHalfExtents(),vec); + return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec); } btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportZ(getHalfExtents(),vec); + return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec); } btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const { - return CylinderLocalSupportY(getHalfExtents(),vec); + return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec); } void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const { for (int i=0;i=0); btAssert(y>=0); - btAssert(xstartX) startX = quantizedAabbMin[1]; @@ -243,10 +240,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback } case 1: { - quantizedAabbMin[0]+=m_width/2-1; - quantizedAabbMax[0]+=m_width/2+1; - quantizedAabbMin[2]+=m_length/2-1; - quantizedAabbMax[2]+=m_length/2+1; + quantizedAabbMin[0]+=m_heightStickWidth/2-1; + quantizedAabbMax[0]+=m_heightStickWidth/2+1; + quantizedAabbMin[2]+=m_heightStickLength/2-1; + quantizedAabbMax[2]+=m_heightStickLength/2+1; if (quantizedAabbMin[0]>startX) startX = quantizedAabbMin[0]; @@ -260,10 +257,10 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback }; case 2: { - quantizedAabbMin[0]+=m_width/2-1; - quantizedAabbMax[0]+=m_width/2+1; - quantizedAabbMin[1]+=m_length/2-1; - quantizedAabbMax[1]+=m_length/2+1; + quantizedAabbMin[0]+=m_heightStickWidth/2-1; + quantizedAabbMax[0]+=m_heightStickWidth/2+1; + quantizedAabbMin[1]+=m_heightStickLength/2-1; + quantizedAabbMax[1]+=m_heightStickLength/2+1; if (quantizedAabbMin[0]>startX) startX = quantizedAabbMin[0]; @@ -290,7 +287,7 @@ void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback for(int x=startX; xlocalGetSupportingVertexWithoutMargin(vec*m_transA.getBasis())); + btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(-vec*m_transA.getBasis())); btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(vec*m_transB.getBasis())); - return supVertexA + supVertexB; + return supVertexA - supVertexB; } void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const @@ -49,7 +49,7 @@ btScalar btMinkowskiSumShape::getMargin() const } -void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; btAssert(0); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h index 198faaff9f9..f9c8427c2f3 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMinkowskiSumShape.h @@ -16,11 +16,11 @@ subject to the following restrictions: #ifndef MINKOWSKI_SUM_SHAPE_H #define MINKOWSKI_SUM_SHAPE_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -/// btMinkowskiSumShape represents implicit (getSupportingVertex) based minkowski sum of two convex implicit shapes. -class btMinkowskiSumShape : public btConvexShape +/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes. +class btMinkowskiSumShape : public btConvexInternalShape { btTransform m_transA; @@ -37,7 +37,7 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; void setTransformA(const btTransform& transA) { m_transA = transA;} void setTransformB(const btTransform& transB) { m_transB = transB;} @@ -53,7 +53,7 @@ public: const btConvexShape* getShapeA() const { return m_shapeA;} const btConvexShape* getShapeB() const { return m_shapeB;} - virtual char* getName()const + virtual const char* getName()const { return "MinkowskiSum"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp index 6015a618082..c709205efc2 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.cpp @@ -47,7 +47,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons btVector3 vec = vec0; btScalar lenSqr = vec.length2(); - if (lenSqr < btScalar(0.0001)) + if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON)) { vec.setValue(1,0,0); } else @@ -116,7 +116,7 @@ btMultiSphereShape::btMultiSphereShape (const btVector3& inertiaHalfExtents,cons -void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //as an approximation, take the inertia of the box that bounds the spheres diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h index 1897b474057..45968f3947f 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultiSphereShape.h @@ -16,13 +16,14 @@ subject to the following restrictions: #ifndef MULTI_SPHERE_MINKOWSKI_H #define MULTI_SPHERE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types #define MAX_NUM_SPHERES 5 -///btMultiSphereShape represents implicit convex hull of a collection of spheres (using getSupportingVertex) -class btMultiSphereShape : public btConvexShape +///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes. +///It is possible to animate the spheres for deformation. +class btMultiSphereShape : public btConvexInternalShape { @@ -39,7 +40,7 @@ public: btMultiSphereShape (const btVector3& inertiaHalfExtents,const btVector3* positions,const btScalar* radi,int numSpheres); ///CollisionShape Interface - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; /// btConvexShape Interface virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; @@ -63,7 +64,7 @@ public: virtual int getShapeType() const { return MULTI_SPHERE_SHAPE_PROXYTYPE; } - virtual char* getName()const + virtual const char* getName()const { return "MultiSphere"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp new file mode 100644 index 00000000000..fc47e86411d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp @@ -0,0 +1,45 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/// This file was created by Alex Silverman + +#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h" +//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h" + + +///Obtains the material for a specific triangle +const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex) +{ + const unsigned char * materialBase = 0; + int numMaterials; + PHY_ScalarType materialType; + int materialStride; + const unsigned char * triangleMaterialBase = 0; + int numTriangles; + int triangleMaterialStride; + PHY_ScalarType triangleType; + + ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, + &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID); + + // return the pointer to the place with the friction for the triangle + // TODO: This depends on whether it's a moving mesh or not + // BUG IN GIMPACT + //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]); + int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)])); + btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride])); + return (matVal); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h new file mode 100644 index 00000000000..2f108020cdf --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h @@ -0,0 +1,124 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/// This file was created by Alex Silverman + +#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H +#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H + +#include "btBvhTriangleMeshShape.h" +#include "btMaterial.h" + +///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution. +ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape +{ + btAlignedObjectArray m_materialList; + int ** m_triangleMaterials; + +public: + + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {} + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16)); + } + } + + ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb + btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true): + btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh) + { + btVector3 m_triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16)); + + for(int i = 0; i < meshInterface->getNumSubParts(); i++) + { + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + i); + //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16)); + } + } + + virtual ~btMultimaterialTriangleMeshShape() + { +/* + for(int i = 0; i < m_meshInterface->getNumSubParts(); i++) + { + btAlignedFree(m_materialValues[i]); + m_materialLookup[i] = NULL; + } + btAlignedFree(m_materialValues); + m_materialLookup = NULL; +*/ + } + virtual int getShapeType() const + { + return MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE; + } + + //debugging + virtual const char* getName()const {return "MULTIMATERIALTRIANGLEMESH";} + + ///Obtains the material for a specific triangle + const btMaterial * getMaterialProperties(int partID, int triIndex); + +} +; + +#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp index 44438a24455..a248c55b571 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -19,13 +19,12 @@ subject to the following restrictions: #include "LinearMath/btIDebugDraw.h" - -btOptimizedBvh::btOptimizedBvh() : m_useQuantization(false), - m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY) - //m_traversalMode(TRAVERSAL_STACKLESS) - //m_traversalMode(TRAVERSAL_RECURSIVE) +btOptimizedBvh::btOptimizedBvh() { +} +btOptimizedBvh::~btOptimizedBvh() +{ } @@ -80,7 +79,7 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback { QuantizedNodeArray& m_triangleNodes; - const btOptimizedBvh* m_optimizedTree; // for quantization + const btQuantizedBvh* m_optimizedTree; // for quantization QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other) { @@ -89,14 +88,16 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized return *this; } - QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btOptimizedBvh* tree) + QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes,const btQuantizedBvh* tree) :m_triangleNodes(triangleNodes),m_optimizedTree(tree) { } virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex) { - btAssert(partId==0); + // The partId and triangle index must fit in the same (positive) integer + btAssert(partId < (1<=0); @@ -111,10 +112,29 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized aabbMin.setMin(triangle[2]); aabbMax.setMax(triangle[2]); - m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMin[0],aabbMin); - m_optimizedTree->quantizeWithClamp(&node.m_quantizedAabbMax[0],aabbMax); + //PCK: add these checks for zero dimensions of aabb + const btScalar MIN_AABB_DIMENSION = btScalar(0.002); + const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001); + if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION) + { + aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION); + aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION) + { + aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION); + aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION); + } + if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION) + { + aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION); + aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION); + } - node.m_escapeIndexOrTriangleIndex = triangleIndex; + m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0); + m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1); + + node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex; m_triangleNodes.push_back(node); } @@ -170,10 +190,45 @@ void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantized subtree.m_rootNodeIndex = 0; subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex(); } + + //PCK: update the copy of the size + m_subtreeHeaderCount = m_SubtreeHeaders.size(); + + //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary + m_quantizedLeafNodes.clear(); + m_leafNodes.clear(); } + +void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax) +{ + if (m_useQuantization) + { + + setQuantizationValues(aabbMin,aabbMax); + + updateBvhNodes(meshInterface,0,m_curNodeIndex,0); + + ///now update all subtree headers + + int i; + for (i=0;im_SubtreeHeaders.size();i++) { btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) + //PCK: unsigned instead of bool + unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); + if (overlap != 0) { updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i); @@ -212,36 +268,23 @@ void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const b } -///just for debugging, to visualize the individual patches/subtrees -#ifdef DEBUG_PATCH_COLORS -btVector3 color[4]= -{ - btVector3(255,0,0), - btVector3(0,255,0), - btVector3(0,0,255), - btVector3(0,255,255) -}; -#endif //DEBUG_PATCH_COLORS - - void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index) { (void)index; btAssert(m_useQuantization); - int nodeSubPart=0; + int curNodeSubPart=-1; //get access info to trianglemesh data - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + const unsigned char *vertexbase = 0; + int numverts = 0; + PHY_ScalarType type = PHY_INTEGER; + int stride = 0; + const unsigned char *indexbase = 0; + int indexstride = 0; + int numfaces = 0; + PHY_ScalarType indicestype = PHY_INTEGER; btVector3 triangleVerts[3]; btVector3 aabbMin,aabbMax; @@ -256,16 +299,26 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f if (curNode.isLeafNode()) { //recalc aabb from triangle data + int nodeSubPart = curNode.getPartId(); int nodeTriangleIndex = curNode.getTriangleIndex(); + if (nodeSubPart != curNodeSubPart) + { + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); + meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + + curNodeSubPart = nodeSubPart; + btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); + } //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, - int* gfxbase = (int*)(indexbase+nodeTriangleIndex*indexstride); + unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride); for (int j=2;j>=0;j--) { - int graphicsindex = gfxbase[j]; + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); #ifdef DEBUG_PATCH_COLORS btVector3 mycolor = color[index&3]; @@ -292,8 +345,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f aabbMin.setMin(triangleVerts[2]); aabbMax.setMax(triangleVerts[2]); - quantizeWithClamp(&curNode.m_quantizedAabbMin[0],aabbMin); - quantizeWithClamp(&curNode.m_quantizedAabbMax[0],aabbMax); + quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0); + quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1); } else { @@ -321,525 +374,17 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f } - meshInterface->unLockReadOnlyVertexBase(nodeSubPart); + if (curNodeSubPart >= 0) + meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); } -void btOptimizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin) +///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' +btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian) { - //enlarge the AABB to avoid division by zero when initializing the quantization values - btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin); - m_bvhAabbMin = bvhAabbMin - clampValue; - m_bvhAabbMax = bvhAabbMax + clampValue; - btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin; - m_bvhQuantization = btVector3(btScalar(65535.0),btScalar(65535.0),btScalar(65535.0)) / aabbSize; -} - - -void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface) -{ - if (m_useQuantization) - { - //calculate new aabb - btVector3 aabbMin,aabbMax; - meshInterface->calculateAabbBruteForce(aabbMin,aabbMax); - - setQuantizationValues(aabbMin,aabbMax); - - updateBvhNodes(meshInterface,0,m_curNodeIndex,0); - - ///now update all subtree headers - - int i; - for (i=0;i gMaxStackDepth) - gMaxStackDepth = gStackDepth; -#endif //DEBUG_TREE_BUILDING - - - int splitAxis, splitIndex, i; - int numIndices =endIndex-startIndex; - int curIndex = m_curNodeIndex; - - assert(numIndices>0); - - if (numIndices==1) - { -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex); - - m_curNodeIndex++; - return; - } - //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian); - splitAxis = calcSplittingAxis(startIndex,endIndex); - - splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis); - - int internalNodeIndex = m_curNodeIndex; - - setInternalNodeAabbMax(m_curNodeIndex,btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30))); - setInternalNodeAabbMin(m_curNodeIndex,btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30))); - - for (i=startIndex;im_escapeIndex; - - int leftChildNodexIndex = m_curNodeIndex; - - //build left child tree - buildTree(startIndex,splitIndex); - - int rightChildNodexIndex = m_curNodeIndex; - //build right child tree - buildTree(splitIndex,endIndex); - -#ifdef DEBUG_TREE_BUILDING - gStackDepth--; -#endif //DEBUG_TREE_BUILDING - - int escapeIndex = m_curNodeIndex - curIndex; - - if (m_useQuantization) - { - //escapeIndex is the number of nodes of this subtree - const int sizeQuantizedNode =sizeof(btQuantizedBvhNode); - const int treeSizeInBytes = escapeIndex * sizeQuantizedNode; - if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES) - { - updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex); - } - } - - setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex); - -} - -void btOptimizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex) -{ - btAssert(m_useQuantization); - - btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex]; - int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex(); - int leftSubTreeSizeInBytes = leftSubTreeSize * sizeof(btQuantizedBvhNode); - - btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex]; - int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex(); - int rightSubTreeSizeInBytes = rightSubTreeSize * sizeof(btQuantizedBvhNode); - - if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(leftChildNode); - subtree.m_rootNodeIndex = leftChildNodexIndex; - subtree.m_subtreeSize = leftSubTreeSize; - } - - if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES) - { - btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand(); - subtree.setAabbFromQuantizeNode(rightChildNode); - subtree.m_rootNodeIndex = rightChildNodexIndex; - subtree.m_subtreeSize = rightSubTreeSize; - } -} - - -int btOptimizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis) -{ - int i; - int splitIndex =startIndex; - int numIndices = endIndex - startIndex; - btScalar splitValue; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - for (i=startIndex;i splitValue) - { - //swap - swapLeafNodes(i,splitIndex); - splitIndex++; - } - } - - //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex - //otherwise the tree-building might fail due to stack-overflows in certain cases. - //unbalanced1 is unsafe: it can cause stack overflows - //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); - - //unbalanced2 should work too: always use center (perfect balanced trees) - //bool unbalanced2 = true; - - //this should be safe too: - int rangeBalancedIndices = numIndices/3; - bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); - - if (unbalanced) - { - splitIndex = startIndex+ (numIndices>>1); - } - - bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); - btAssert(!unbal); - - return splitIndex; -} - - -int btOptimizedBvh::calcSplittingAxis(int startIndex,int endIndex) -{ - int i; - - btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); - btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); - int numIndices = endIndex-startIndex; - - for (i=startIndex;im_aabbMinOrg,rootNode->m_aabbMaxOrg); - isLeafNode = rootNode->m_escapeIndex == -1; - - if (isLeafNode && aabbOverlap) - { - nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex); - } - - if (aabbOverlap || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->m_escapeIndex; - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -/* -///this was the original recursive traversal, before we optimized towards stackless traversal -void btOptimizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax); - if (aabbOverlap) - { - isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild); - if (isLeafNode) - { - nodeCallback->processNode(rootNode); - } else - { - walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax); - walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax); - } - } - -} -*/ - -void btOptimizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - bool aabbOverlap, isLeafNode; - - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax); - isLeafNode = currentNode->isLeafNode(); - - if (aabbOverlap) - { - if (isLeafNode) - { - nodeCallback->processNode(0,currentNode->getTriangleIndex()); - } else - { - //process left and right children - const btQuantizedBvhNode* leftChildNode = currentNode+1; - walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - - const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex(); - walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax); - } - } -} - - - - - - - -void btOptimizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const -{ - btAssert(m_useQuantization); - - int curIndex = startNodeIndex; - int walkIterations = 0; - int subTreeSize = endNodeIndex - startNodeIndex; - - const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex]; - int escapeIndex; - - bool aabbOverlap, isLeafNode; - - while (curIndex < endNodeIndex) - { - -//#define VISUALLY_ANALYZE_BVH 1 -#ifdef VISUALLY_ANALYZE_BVH - //some code snippet to debugDraw aabb, to visually analyze bvh structure - static int drawPatch = 0; - //need some global access to a debugDrawer - extern btIDebugDraw* debugDrawerPtr; - if (curIndex==drawPatch) - { - btVector3 aabbMin,aabbMax; - aabbMin = unQuantize(rootNode->m_quantizedAabbMin); - aabbMax = unQuantize(rootNode->m_quantizedAabbMax); - btVector3 color(1,0,0); - debugDrawerPtr->drawAabb(aabbMin,aabbMax,color); - } -#endif//VISUALLY_ANALYZE_BVH - - //catch bugs in tree data - assert (walkIterations < subTreeSize); - - walkIterations++; - aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax); - isLeafNode = rootNode->isLeafNode(); - - if (isLeafNode && aabbOverlap) - { - nodeCallback->processNode(0,rootNode->getTriangleIndex()); - } - - if (aabbOverlap || isLeafNode) - { - rootNode++; - curIndex++; - } else - { - escapeIndex = rootNode->getEscapeIndex(); - rootNode += escapeIndex; - curIndex += escapeIndex; - } - } - if (maxIterations < walkIterations) - maxIterations = walkIterations; - -} - -//This traversal can be called from Playstation 3 SPU -void btOptimizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const -{ - btAssert(m_useQuantization); - - int i; - - - for (i=0;im_SubtreeHeaders.size();i++) - { - const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i]; - - bool overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax); - if (overlap) - { - walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax, - subtree.m_rootNodeIndex, - subtree.m_rootNodeIndex+subtree.m_subtreeSize); - } - } -} - - - - -void btOptimizedBvh::reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const -{ - (void)nodeCallback; - (void)aabbMin; - (void)aabbMax; - //not yet, please use aabb - btAssert(0); -} - - -void btOptimizedBvh::quantizeWithClamp(unsigned short* out, const btVector3& point) const -{ - - btAssert(m_useQuantization); - - btVector3 clampedPoint(point); - clampedPoint.setMax(m_bvhAabbMin); - clampedPoint.setMin(m_bvhAabbMax); - - btVector3 v = (clampedPoint - m_bvhAabbMin) * m_bvhQuantization; - out[0] = (unsigned short)(v.getX()+0.5f); - out[1] = (unsigned short)(v.getY()+0.5f); - out[2] = (unsigned short)(v.getZ()+0.5f); -} - -btVector3 btOptimizedBvh::unQuantize(const unsigned short* vecIn) const -{ - btVector3 vecOut; - vecOut.setValue( - (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()), - (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()), - (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ())); - vecOut += m_bvhAabbMin; - return vecOut; -} - - -void btOptimizedBvh::swapLeafNodes(int i,int splitIndex) -{ - if (m_useQuantization) - { - btQuantizedBvhNode tmp = m_quantizedLeafNodes[i]; - m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex]; - m_quantizedLeafNodes[splitIndex] = tmp; - } else - { - btOptimizedBvhNode tmp = m_leafNodes[i]; - m_leafNodes[i] = m_leafNodes[splitIndex]; - m_leafNodes[splitIndex] = tmp; - } -} - -void btOptimizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex) -{ - if (m_useQuantization) - { - m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex]; - } else - { - m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex]; - } + //we don't add additional data so just do a static upcast + return static_cast(bvh); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h index d5159586344..d7536417d7e 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.h @@ -16,315 +16,48 @@ subject to the following restrictions: #ifndef OPTIMIZED_BVH_H #define OPTIMIZED_BVH_H - -#include "../../LinearMath/btVector3.h" - - -//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp - - +#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" class btStridingMeshInterface; -//Note: currently we have 16 bytes per quantized node -#define MAX_SUBTREE_SIZE_IN_BYTES 2048 - -///btQuantizedBvhNode is a compressed aabb node, 16 bytes. -///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). -ATTRIBUTE_ALIGNED16 (struct) btQuantizedBvhNode +///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface. +ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh { - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes - int m_escapeIndexOrTriangleIndex; - - bool isLeafNode() const - { - //skipindex is negative (internal node), triangleindex >=0 (leafnode) - return (m_escapeIndexOrTriangleIndex >= 0); - } - int getEscapeIndex() const - { - btAssert(!isLeafNode()); - return -m_escapeIndexOrTriangleIndex; - } - int getTriangleIndex() const - { - btAssert(isLeafNode()); - return m_escapeIndexOrTriangleIndex; - } -} -; - -/// btOptimizedBvhNode contains both internal and leaf node information. -/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes. -ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode -{ - //32 bytes - btVector3 m_aabbMinOrg; - btVector3 m_aabbMaxOrg; - - //4 - int m_escapeIndex; - - //8 - //for child nodes - int m_subPart; - int m_triangleIndex; - int m_padding[5];//bad, due to alignment - - -}; - - -///btBvhSubtreeInfo provides info to gather a subtree of limited size -ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo -{ public: - //12 bytes - unsigned short int m_quantizedAabbMin[3]; - unsigned short int m_quantizedAabbMax[3]; - //4 bytes, points to the root of the subtree - int m_rootNodeIndex; - //4 bytes - int m_subtreeSize; - int m_padding[3]; - - - void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode) - { - m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0]; - m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1]; - m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2]; - m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0]; - m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1]; - m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2]; - } -} -; - - -class btNodeOverlapCallback -{ -public: - virtual ~btNodeOverlapCallback() {}; - - virtual void processNode(int subPart, int triangleIndex) = 0; -}; - -#include "../../LinearMath/btAlignedAllocator.h" -#include "../../LinearMath/btAlignedObjectArray.h" - - - -///for code readability: -typedef btAlignedObjectArray NodeArray; -typedef btAlignedObjectArray QuantizedNodeArray; -typedef btAlignedObjectArray BvhSubtreeInfoArray; - - -///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future) -ATTRIBUTE_ALIGNED16(class) btOptimizedBvh -{ - NodeArray m_leafNodes; - NodeArray m_contiguousNodes; - - QuantizedNodeArray m_quantizedLeafNodes; - - QuantizedNodeArray m_quantizedContiguousNodes; - - int m_curNodeIndex; - - - //quantization data - bool m_useQuantization; - btVector3 m_bvhAabbMin; - btVector3 m_bvhAabbMax; - btVector3 m_bvhQuantization; - - enum btTraversalMode - { - TRAVERSAL_STACKLESS = 0, - TRAVERSAL_STACKLESS_CACHE_FRIENDLY, - TRAVERSAL_RECURSIVE - }; - - btTraversalMode m_traversalMode; - - - - - BvhSubtreeInfoArray m_SubtreeHeaders; - - - ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!) - ///this might be refactored into a virtual, it is usually not calculated at run-time - void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin) - { - if (m_useQuantization) - { - quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin; - - } - } - void setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax) - { - if (m_useQuantization) - { - quantizeWithClamp(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax); - } else - { - m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax; - } - } - - btVector3 getAabbMin(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMinOrg; - - } - btVector3 getAabbMax(int nodeIndex) const - { - if (m_useQuantization) - { - return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]); - } - //non-quantized - return m_leafNodes[nodeIndex].m_aabbMaxOrg; - - } - - void setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0)); - - void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex) - { - if (m_useQuantization) - { - m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex; - } - else - { - m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex; - } - - } - - void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) - { - if (m_useQuantization) - { - unsigned short int quantizedAabbMin[3]; - unsigned short int quantizedAabbMax[3]; - quantizeWithClamp(quantizedAabbMin,newAabbMin); - quantizeWithClamp(quantizedAabbMax,newAabbMax); - for (int i=0;i<3;i++) - { - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i]; - - if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i]) - m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i]; - - } - } else - { - //non-quantized - m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin); - m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax); - } - } - - void swapLeafNodes(int firstIndex,int secondIndex); - - void assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex); + BT_DECLARE_ALIGNED_ALLOCATOR(); protected: - - - void buildTree (int startIndex,int endIndex); - - int calcSplittingAxis(int startIndex,int endIndex); - - int sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis); - - void walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const; - - ///tree traversal designed for small-memory processors like PS3 SPU - void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const; - - ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal - void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const; - - - inline bool testQuantizedAabbAgainstQuantizedAabb(unsigned short int* aabbMin1,unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2) const - { - bool overlap = true; - overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap; - overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap; - overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap; - return overlap; - } - - void updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex); - public: + btOptimizedBvh(); virtual ~btOptimizedBvh(); void build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax); - void reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void reportSphereOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const; - - void quantizeWithClamp(unsigned short* out, const btVector3& point) const; - - btVector3 unQuantize(const unsigned short* vecIn) const; - - ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees. - void setTraversalMode(btTraversalMode traversalMode) - { - m_traversalMode = traversalMode; - } - - void refit(btStridingMeshInterface* triangles); + void refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax); void refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax); void updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index); - - QuantizedNodeArray& getQuantizedNodeArray() - { - return m_quantizedContiguousNodes; - } - - BvhSubtreeInfoArray& getSubtreeInfoArray() + /// Data buffer MUST be 16 byte aligned + virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) { - return m_SubtreeHeaders; + return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian); + } -} -; + ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place' + static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian); + + +}; #endif //OPTIMIZED_BVH_H + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp index bbc4ba62af6..71c3af38a02 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -13,7 +13,7 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include +#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h" btPolyhedralConvexShape::btPolyhedralConvexShape() :m_localAabbMin(1,1,1), @@ -95,7 +95,7 @@ void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin( -void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { //not yet, return box inertia @@ -128,10 +128,46 @@ void btPolyhedralConvexShape::getAabb(const btTransform& trans,btVector3& aabbMi +void btPolyhedralConvexShape::setLocalScaling(const btVector3& scaling) +{ + btConvexInternalShape::setLocalScaling(scaling); + recalcLocalAabb(); +} void btPolyhedralConvexShape::recalcLocalAabb() { m_isLocalAabbValid = true; + + #if 1 + static const btVector3 _directions[] = + { + btVector3( 1., 0., 0.), + btVector3( 0., 1., 0.), + btVector3( 0., 0., 1.), + btVector3( -1., 0., 0.), + btVector3( 0., -1., 0.), + btVector3( 0., 0., -1.) + }; + + btVector3 _supporting[] = + { + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.), + btVector3( 0., 0., 0.) + }; + + batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6); + + for ( int i = 0; i < 3; ++i ) + { + m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin; + m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin; + } + + #else for (int i=0;i<3;i++) { @@ -143,6 +179,8 @@ void btPolyhedralConvexShape::recalcLocalAabb() tmp = localGetSupportingVertex(vec); m_localAabbMin[i] = tmp[i]-m_collisionMargin; } + #endif } + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h index c35f7512663..4c4ce7feaa7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -16,13 +16,14 @@ subject to the following restrictions: #ifndef BU_SHAPE #define BU_SHAPE -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btMatrix3x3.h" -#include "btConvexShape.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAabbUtil2.h" +#include "btConvexInternalShape.h" -///PolyhedralConvexShape is an interface class for feature based (vertex/edge/face) convex shapes. -class btPolyhedralConvexShape : public btConvexShape +///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes. +class btPolyhedralConvexShape : public btConvexInternalShape { protected: @@ -38,7 +39,7 @@ public: virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const @@ -46,33 +47,14 @@ public: //lazy evaluation of local aabb btAssert(m_isLocalAabbValid); - - btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX()); - btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY()); - btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ()); - - - btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(margin,margin,margin); - - aabbMin = center - extent; - aabbMax = center + extent; - - + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); } virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + void recalcLocalAabb(); virtual int getNumVertices() const = 0 ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp new file mode 100644 index 00000000000..5a17b4e2df0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btScaledBvhTriangleMeshShape.h" + +btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling) +:m_bvhTriMeshShape(childShape), +m_localScaling(localScaling) +{ + +} + +btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape() +{ +} + + +class btScaledTriangleCallback : public btTriangleCallback +{ + btTriangleCallback* m_originalCallback; + + btVector3 m_localScaling; + +public: + + btScaledTriangleCallback(btTriangleCallback* originalCallback,btVector3 localScaling) + :m_originalCallback(originalCallback), + m_localScaling(localScaling) + { + } + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btVector3 newTriangle[3]; + newTriangle[0] = triangle[0]*m_localScaling; + newTriangle[1] = triangle[1]*m_localScaling; + newTriangle[2] = triangle[2]*m_localScaling; + m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex); + } +}; + +void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + btScaledTriangleCallback scaledCallback(callback,m_localScaling); + + btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ()); + btVector3 scaledAabbMin = aabbMin * invLocalScaling; + btVector3 scaledAabbMax = aabbMax * invLocalScaling; + m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax); +} + + +void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin(); + btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax(); + localAabbMin *= m_localScaling; + localAabbMax *= m_localScaling; + + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + btScalar margin = m_bvhTriMeshShape->getMargin(); + localHalfExtents += btVector3(margin,margin,margin); + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center - extent; + aabbMax = center + extent; + +} + +void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + +const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const +{ + return m_localScaling; +} + +void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///don't make this a movable object! + btAssert(0); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h new file mode 100644 index 00000000000..8e1d29fc005 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -0,0 +1,57 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" + + +///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape. +///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling' +ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape +{ + + + btVector3 m_localScaling; + + btBvhTriangleMeshShape* m_bvhTriMeshShape; + +public: + + + btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling); + + virtual ~btScaledBvhTriangleMeshShape(); + + virtual int getShapeType() const + { + //use un-used 'FAST_CONCAVE_MESH_PROXYTYPE' for now, later add SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE to btBroadphaseProxy.h + return FAST_CONCAVE_MESH_PROXYTYPE; + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + //debugging + virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} + +}; + +#endif //BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp new file mode 100644 index 00000000000..a87b87f1a6f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.cpp @@ -0,0 +1,164 @@ +/* +btbtShapeHull implemented by John McCutchan. + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btShapeHull.h" +#include "LinearMath/btConvexHull.h" + +#define NUM_UNITSPHERE_POINTS 42 + +static btVector3 btUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = +{ + btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)), + btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)), + btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)), + btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)), + btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)), + btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)), + btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)), + btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)), + btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)), + btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)), + btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)), + btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)), + btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)), + btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)), + btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)), + btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)), + btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)), + btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)), + btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)), + btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)), + btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)), + btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)), + btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)), + btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)), + btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)), + btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)), + btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)), + btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)), + btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)), + btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)), + btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)), + btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)), + btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)), + btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)), + btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)), + btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654)) +}; + +btShapeHull::btShapeHull (const btConvexShape* shape) +{ + m_shape = shape; + m_vertices.clear (); + m_indices.clear(); + m_numIndices = 0; +} + +btShapeHull::~btShapeHull () +{ + m_indices.clear(); + m_vertices.clear (); +} + +bool +btShapeHull::buildHull (btScalar /*margin*/) +{ + int numSampleDirections = NUM_UNITSPHERE_POINTS; + { + int numPDA = m_shape->getNumPreferredPenetrationDirections(); + if (numPDA) + { + for (int i=0;igetPreferredPenetrationDirection(i,norm); + btUnitSpherePoints[numSampleDirections] = norm; + numSampleDirections++; + } + } + } + + btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2]; + int i; + for (i = 0; i < numSampleDirections; i++) + { + supportPoints[i] = m_shape->localGetSupportingVertex(btUnitSpherePoints[i]); + } + + HullDesc hd; + hd.mFlags = QF_TRIANGLES; + hd.mVcount = static_cast(numSampleDirections); + +#ifdef BT_USE_DOUBLE_PRECISION + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof(btVector3); +#else + hd.mVertices = &supportPoints[0]; + hd.mVertexStride = sizeof (btVector3); +#endif + + HullLibrary hl; + HullResult hr; + if (hl.CreateConvexHull (hd, hr) == QE_FAIL) + { + return false; + } + + m_vertices.resize (static_cast(hr.mNumOutputVertices)); + + + for (i = 0; i < static_cast(hr.mNumOutputVertices); i++) + { + m_vertices[i] = hr.m_OutputVertices[i]; + } + m_numIndices = hr.mNumIndices; + m_indices.resize(static_cast(m_numIndices)); + for (i = 0; i < static_cast(m_numIndices); i++) + { + m_indices[i] = hr.m_Indices[i]; + } + + // free temporary hull result that we just copied + hl.ReleaseResult (hr); + + return true; +} + +int +btShapeHull::numTriangles () const +{ + return static_cast(m_numIndices / 3); +} + +int +btShapeHull::numVertices () const +{ + return m_vertices.size (); +} + +int +btShapeHull::numIndices () const +{ + return static_cast(m_numIndices); +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h new file mode 100644 index 00000000000..583c6b99eb6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btShapeHull.h @@ -0,0 +1,56 @@ +/* +btShapeHull implemented by John McCutchan. + +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SHAPE_HULL_H +#define _SHAPE_HULL_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" + + +///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices. +///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object. +///It approximates the convex hull using the supporting vertex of 42 directions. +class btShapeHull +{ +public: + btShapeHull (const btConvexShape* shape); + ~btShapeHull (); + + bool buildHull (btScalar margin); + + int numTriangles () const; + int numVertices () const; + int numIndices () const; + + const btVector3* getVertexPointer() const + { + return &m_vertices[0]; + } + const unsigned int* getIndexPointer() const + { + return &m_indices[0]; + } + +protected: + btAlignedObjectArray m_vertices; + btAlignedObjectArray m_indices; + unsigned int m_numIndices; + const btConvexShape* m_shape; +}; + +#endif //_SHAPE_HULL_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp index ca65dd03f3e..15cfe432e27 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.cpp @@ -68,7 +68,7 @@ void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& a -void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin(); inertia.setValue(elem,elem,elem); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h index 66521664087..83421d69e0d 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btSphereShape.h @@ -16,15 +16,17 @@ subject to the following restrictions: #ifndef SPHERE_MINKOWSKI_H #define SPHERE_MINKOWSKI_H -#include "btConvexShape.h" -#include "../BroadphaseCollision/btBroadphaseProxy.h" // for the types +#include "btConvexInternalShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types -///btSphereShape implements an implicit (getSupportingVertex) Sphere -ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexShape +///The btSphereShape implements an implicit sphere, centered around a local origin with radius. +ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape { public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + btSphereShape (btScalar radius); @@ -34,26 +36,26 @@ public: virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual int getShapeType() const { return SPHERE_SHAPE_PROXYTYPE; } - btScalar getRadius() const { return m_implicitShapeDimensions.getX();} + btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();} //debugging - virtual char* getName()const {return "SPHERE";} + virtual const char* getName()const {return "SPHERE";} virtual void setMargin(btScalar margin) { - btConvexShape::setMargin(margin); + btConvexInternalShape::setMargin(margin); } virtual btScalar getMargin() const { //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case //this means, non-uniform scaling is not supported anymore - return m_localScaling.getX() * getRadius() + btConvexShape::getMargin(); + return getRadius(); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp index 4fbaafa1b93..3c98ca08ddc 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp @@ -19,10 +19,11 @@ subject to the following restrictions: btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant) -:m_planeNormal(planeNormal), +:m_planeNormal(planeNormal.normalized()), m_planeConstant(planeConstant), m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.)) { + // btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) ); } @@ -86,7 +87,7 @@ void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const } -void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h index f59cc0c3347..ddebca73dea 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStaticPlaneShape.h @@ -19,8 +19,7 @@ subject to the following restrictions: #include "btConcaveShape.h" -///StaticPlaneShape simulates an 'infinite' plane by dynamically reporting triangles approximated by intersection of the plane with the AABB. -///Assumed is that the other objects is not also infinite, so a reasonable sized AABB. +///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane. class btStaticPlaneShape : public btConcaveShape { protected: @@ -46,14 +45,23 @@ public: virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; + const btVector3& getPlaneNormal() const + { + return m_planeNormal; + } + + const btScalar& getPlaneConstant() const + { + return m_planeConstant; + } //debugging - virtual char* getName()const {return "STATICPLANE";} + virtual const char* getName()const {return "STATICPLANE";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp index 03ca1ae7736..752a5fc1dfa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp @@ -51,7 +51,7 @@ void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleInde { for (gfxindex=0;gfxindexprocessAllTriangles(&triBuf,aabbMin, aabbMax); -// for (int i=0;iprocessAllTriangles(&triBuf,aabbMin, aabbMax); +/// for (int i=0;i IndexedMeshArray; -///TriangleIndexVertexArray allows to use multiple meshes, by indexing into existing triangle/index arrays. +///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays. ///Additional meshes can be added using addIndexedMesh ///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays. ///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray. ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface { +protected: IndexedMeshArray m_indexedMeshes; - int m_pad[3]; + int m_pad[2]; + int m_hasAabb; // using int instead of bool to maintain alignment + btVector3 m_aabbMin; + btVector3 m_aabbMax; - public: - btTriangleIndexVertexArray() + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexArray() : m_hasAabb(0) { } + virtual ~btTriangleIndexVertexArray(); + //just to be backwards compatible - btTriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); + btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride); - void addIndexedMesh(const btIndexedMesh& mesh) + void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER) { m_indexedMeshes.push_back(mesh); + m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType; } @@ -91,6 +105,10 @@ public: virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateIndices(int numindices){(void) numindices;} + virtual bool hasPremadeAabb() const; + virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ); + virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const; + } ; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp new file mode 100644 index 00000000000..492854ff646 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp @@ -0,0 +1,86 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///This file was created by Alex Silverman + +#include "btTriangleIndexVertexMaterialArray.h" + +btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride) : +btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride) +{ + btMaterialProperties mat; + + mat.m_numMaterials = numMaterials; + mat.m_materialBase = materialBase; + mat.m_materialStride = materialStride; +#ifdef BT_USE_DOUBLE_PRECISION + mat.m_materialType = PHY_DOUBLE; +#else + mat.m_materialType = PHY_FLOAT; +#endif + + mat.m_numTriangles = numTriangles; + mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase; + mat.m_triangleMaterialStride = materialIndexStride; + mat.m_triangleType = PHY_INTEGER; + + addMaterialProperties(mat); +} + + +void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btAssert(subpart< getNumSubParts() ); + + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} + +void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart) +{ + btMaterialProperties& mats = m_materials[subpart]; + + numMaterials = mats.m_numMaterials; + (*materialBase) = (const unsigned char *) mats.m_materialBase; +#ifdef BT_USE_DOUBLE_PRECISION + materialType = PHY_DOUBLE; +#else + materialType = PHY_FLOAT; +#endif + materialStride = mats.m_materialStride; + + numTriangles = mats.m_numTriangles; + (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase; + triangleMaterialStride = mats.m_triangleMaterialStride; + triangleType = mats.m_triangleType; +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h new file mode 100644 index 00000000000..69a2e631458 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h @@ -0,0 +1,84 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///This file was created by Alex Silverman + +#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H +#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H + +#include "btTriangleIndexVertexArray.h" + + +ATTRIBUTE_ALIGNED16( struct) btMaterialProperties +{ + ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution + int m_numMaterials; + const unsigned char * m_materialBase; + int m_materialStride; + PHY_ScalarType m_materialType; + ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're + /// padding the structure, it can be reproduced at no real cost + ///m_triangleMaterials =====> 1 integer value makes up one entry + /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5 + int m_numTriangles; + const unsigned char * m_triangleMaterialsBase; + int m_triangleMaterialStride; + ///m_triangleType <========== Automatically set in addMaterialProperties + PHY_ScalarType m_triangleType; +}; + +typedef btAlignedObjectArray MaterialArray; + +///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray +///The addition of a material array allows for the utilization of the partID and +///triangleIndex that are returned in the ContactAddedCallback. As with +///TriangleIndexVertexArray, no duplicate is made of the material data, so it +///is the users responsibility to maintain the array during the lifetime of the +///TriangleIndexVertexMaterialArray. +ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray +{ +protected: + MaterialArray m_materials; + +public: + BT_DECLARE_ALIGNED_ALLOCATOR(); + + btTriangleIndexVertexMaterialArray() + { + } + + btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride, + int numVertices,btScalar* vertexBase,int vertexStride, + int numMaterials, unsigned char* materialBase, int materialStride, + int* triangleMaterialsBase, int materialIndexStride); + + virtual ~btTriangleIndexVertexMaterialArray() {} + + void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER) + { + m_materials.push_back(mat); + m_materials[m_materials.size()-1].m_triangleType = triangleType; + } + + virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0); + + virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride, + const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0); + +} +; + +#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp index 98c54ef45f8..bcea97052d6 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp @@ -14,47 +14,102 @@ subject to the following restrictions: */ #include "btTriangleMesh.h" -#include -btTriangleMesh::btTriangleMesh () + +btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices) +:m_use32bitIndices(use32bitIndices), +m_use4componentVertices(use4componentVertices) { + btIndexedMesh meshIndex; + meshIndex.m_numTriangles = 0; + meshIndex.m_numVertices = 0; + meshIndex.m_indexType = PHY_INTEGER; + meshIndex.m_triangleIndexBase = 0; + meshIndex.m_triangleIndexStride = 3*sizeof(int); + meshIndex.m_vertexBase = 0; + meshIndex.m_vertexStride = sizeof(btVector3); + m_indexedMeshes.push_back(meshIndex); + + if (m_use32bitIndices) + { + m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3; + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; + m_indexedMeshes[0].m_indexType = PHY_INTEGER; + m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int); + } else + { + m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3; + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; + m_indexedMeshes[0].m_indexType = PHY_SHORT; + m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int); + } + + if (m_use4componentVertices) + { + m_indexedMeshes[0].m_numVertices = m_4componentVertices.size(); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; + m_indexedMeshes[0].m_vertexStride = sizeof(btVector3); + } else + { + m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3; + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; + m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar); + } + } -void btTriangleMesh::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) + +void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) { - (void)subpart; - numverts = m_vertices.size(); - *vertexbase = (unsigned char*)&m_vertices[0]; - type = PHY_FLOAT; - stride = sizeof(btVector3); + m_indexedMeshes[0].m_numTriangles++; + m_indexedMeshes[0].m_numVertices+=3; - numfaces = m_indices.size()/3; - *indexbase = (unsigned char*) &m_indices[0]; - indicestype = PHY_INTEGER; - indexstride = 3*sizeof(int); + if (m_use4componentVertices) + { + m_4componentVertices.push_back(vertex0); + m_4componentVertices.push_back(vertex1); + m_4componentVertices.push_back(vertex2); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; + } else + { + m_3componentVertices.push_back(vertex0.getX()); + m_3componentVertices.push_back(vertex0.getY()); + m_3componentVertices.push_back(vertex0.getZ()); + m_3componentVertices.push_back(vertex1.getX()); + m_3componentVertices.push_back(vertex1.getY()); + m_3componentVertices.push_back(vertex1.getZ()); + + m_3componentVertices.push_back(vertex2.getX()); + m_3componentVertices.push_back(vertex2.getY()); + m_3componentVertices.push_back(vertex2.getZ()); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; + } + + if (m_use32bitIndices) + { + int curIndex = m_32bitIndices.size(); + m_32bitIndices.push_back(curIndex++); + m_32bitIndices.push_back(curIndex++); + m_32bitIndices.push_back(curIndex++); + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; + } else + { + short curIndex = static_cast(m_16bitIndices.size()); + m_16bitIndices.push_back(curIndex++); + m_16bitIndices.push_back(curIndex++); + m_16bitIndices.push_back(curIndex++); + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; + } } -void btTriangleMesh::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const +int btTriangleMesh::getNumTriangles() const { - (void)subpart; - numverts = m_vertices.size(); - *vertexbase = (unsigned char*)&m_vertices[0]; - type = PHY_FLOAT; - stride = sizeof(btVector3); - - numfaces = m_indices.size()/3; - *indexbase = (unsigned char*) &m_indices[0]; - indicestype = PHY_INTEGER; - indexstride = 3*sizeof(int); - -} - - - -int btTriangleMesh::getNumSubParts() const -{ - return 1; + if (m_use32bitIndices) + { + return m_32bitIndices.size() / 3; + } + return m_16bitIndices.size() / 3; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index 525f5336b48..e4d41d5ede0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -17,54 +17,42 @@ subject to the following restrictions: #ifndef TRIANGLE_MESH_H #define TRIANGLE_MESH_H -#include "btStridingMeshInterface.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btAlignedObjectArray.h" +#include "btTriangleIndexVertexArray.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" -///TriangleMesh provides storage for a concave triangle mesh. It can be used as data for the btTriangleMeshShape. -class btTriangleMesh : public btStridingMeshInterface +///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape. +///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices. +///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface. +///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same. +class btTriangleMesh : public btTriangleIndexVertexArray { - btAlignedObjectArray m_vertices; - btAlignedObjectArray m_indices; + btAlignedObjectArray m_4componentVertices; + btAlignedObjectArray m_3componentVertices; + + btAlignedObjectArray m_32bitIndices; + btAlignedObjectArray m_16bitIndices; + bool m_use32bitIndices; + bool m_use4componentVertices; + public: - btTriangleMesh (); + btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); - void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) + bool getUse32bitIndices() const { - int curIndex = m_indices.size(); - m_vertices.push_back(vertex0); - m_vertices.push_back(vertex1); - m_vertices.push_back(vertex2); - - m_indices.push_back(curIndex++); - m_indices.push_back(curIndex++); - m_indices.push_back(curIndex++); + return m_use32bitIndices; } - int getNumTriangles() const + bool getUse4componentVertices() const { - return m_indices.size() / 3; + return m_use4componentVertices; } - - -//StridingMeshInterface interface implementation - - virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0); - - virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const; - - /// unLockVertexBase finishes the access to a subpart of the triangle mesh - /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished - virtual void unLockVertexBase(int subpart) {(void) subpart;} - - virtual void unLockReadOnlyVertexBase(int subpart) const { (void) subpart;} - - /// getNumSubParts returns the number of seperate subparts - /// each subpart has a continuous array of vertices and indices - virtual int getNumSubParts() const; + void addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2); + int getNumTriangles() const; + virtual void preallocateVertices(int numverts){(void) numverts;} virtual void preallocateIndices(int numindices){(void) numindices;} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp index ed81897b515..0a2c77096d1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -20,12 +20,18 @@ subject to the following restrictions: #include "LinearMath/btAabbUtil2.h" #include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "stdio.h" btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface) : m_meshInterface(meshInterface) { - recalcLocalAabb(); + if(meshInterface->hasPremadeAabb()) + { + meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax); + } + else + { + recalcLocalAabb(); + } } @@ -41,6 +47,7 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); btMatrix3x3 abs_b = trans.getBasis().absolute(); @@ -50,12 +57,10 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), abs_b[1].dot(localHalfExtents), abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - aabbMin = center - extent; aabbMax = center + extent; - + } void btTriangleMeshShape::recalcLocalAabb() @@ -138,6 +143,7 @@ const btVector3& btTriangleMeshShape::getLocalScaling() const //#define DEBUG_TRIANGLE_MESH + void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const { struct FilteredCallback : public btInternalTriangleIndexCallback @@ -174,8 +180,7 @@ void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const - -void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) +void btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; //moving concave objects not supported diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index e6173e47640..c9eabafe290 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -20,17 +20,19 @@ subject to the following restrictions: #include "btStridingMeshInterface.h" -///Concave triangle mesh. Uses an interface to access the triangles to allow for sharing graphics/physics triangles. +///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead. class btTriangleMeshShape : public btConcaveShape { protected: btVector3 m_localAabbMin; btVector3 m_localAabbMax; btStridingMeshInterface* m_meshInterface; - + + ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class. + ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead! + btTriangleMeshShape(btStridingMeshInterface* meshInterface); public: - btTriangleMeshShape(btStridingMeshInterface* meshInterface); virtual ~btTriangleMeshShape(); @@ -44,16 +46,11 @@ public: void recalcLocalAabb(); - virtual int getShapeType() const - { - return TRIANGLE_MESH_SHAPE_PROXYTYPE; - } - virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia); + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; @@ -68,9 +65,19 @@ public: return m_meshInterface; } + const btVector3& getLocalAabbMin() const + { + return m_localAabbMin; + } + const btVector3& getLocalAabbMax() const + { + return m_localAabbMax; + } + + //debugging - virtual char* getName()const {return "TRIANGLEMESH";} + virtual const char* getName()const {return "TRIANGLEMESH";} }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h index c2e240c051c..ba7aa0c32a0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleShape.h @@ -27,7 +27,6 @@ public: btVector3 m_vertices1[3]; - virtual int getNumVertices() const { return 3; @@ -84,14 +83,13 @@ public: - btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) - { - m_vertices1[0] = p0; - m_vertices1[1] = p1; - m_vertices1[2] = p2; - } + btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) + { + m_vertices1[0] = p0; + m_vertices1[1] = p1; + m_vertices1[2] = p2; + } - virtual void getPlane(btVector3& planeNormal,btPoint3& planeSupport,int i) const { @@ -116,7 +114,7 @@ public: planeSupport = m_vertices1[0]; } - virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const { (void)mass; btAssert(0); @@ -155,7 +153,7 @@ public: return false; } //debugging - virtual char* getName()const + virtual const char* getName()const { return "Triangle"; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp new file mode 100644 index 00000000000..ef340286cb0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.cpp @@ -0,0 +1,114 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btUniformScalingShape.h" + +btUniformScalingShape::btUniformScalingShape( btConvexShape* convexChildShape,btScalar uniformScalingFactor): +m_childConvexShape(convexChildShape), +m_uniformScalingFactor(uniformScalingFactor) +{ +} + +btUniformScalingShape::~btUniformScalingShape() +{ +} + + +btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const +{ + btVector3 tmpVertex; + tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec); + return tmpVertex*m_uniformScalingFactor; +} + +void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const +{ + m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors); + int i; + for (i=0;ilocalGetSupportingVertex(vec); + return tmpVertex*m_uniformScalingFactor; +} + + +void btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + + ///this linear upscaling is not realistic, but we don't deal with large mass ratios... + btVector3 tmpInertia; + m_childConvexShape->calculateLocalInertia(mass,tmpInertia); + inertia = tmpInertia * m_uniformScalingFactor; +} + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version +void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabb(t,aabbMin,aabbMax); + btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); + btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; + + aabbMin = aabbCenter - scaledAabbHalfExtends; + aabbMax = aabbCenter + scaledAabbHalfExtends; + +} + +void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const +{ + m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax); + btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5); + btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor; + + aabbMin = aabbCenter - scaledAabbHalfExtends; + aabbMax = aabbCenter + scaledAabbHalfExtends; +} + +void btUniformScalingShape::setLocalScaling(const btVector3& scaling) +{ + m_childConvexShape->setLocalScaling(scaling); +} + +const btVector3& btUniformScalingShape::getLocalScaling() const +{ + return m_childConvexShape->getLocalScaling(); +} + +void btUniformScalingShape::setMargin(btScalar margin) +{ + m_childConvexShape->setMargin(margin); +} +btScalar btUniformScalingShape::getMargin() const +{ + return m_childConvexShape->getMargin() * m_uniformScalingFactor; +} + +int btUniformScalingShape::getNumPreferredPenetrationDirections() const +{ + return m_childConvexShape->getNumPreferredPenetrationDirections(); +} + +void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const +{ + m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h new file mode 100644 index 00000000000..1e17fc8e198 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btUniformScalingShape.h @@ -0,0 +1,88 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_UNIFORM_SCALING_SHAPE_H +#define BT_UNIFORM_SCALING_SHAPE_H + +#include "btConvexShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types + +///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way. +///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it. +class btUniformScalingShape : public btConvexShape +{ + btConvexShape* m_childConvexShape; + + btScalar m_uniformScalingFactor; + + public: + + btUniformScalingShape( btConvexShape* convexChildShape, btScalar uniformScalingFactor); + + virtual ~btUniformScalingShape(); + + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const; + + virtual btVector3 localGetSupportingVertex(const btVector3& vec)const; + + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const; + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + btScalar getUniformScalingFactor() const + { + return m_uniformScalingFactor; + } + + btConvexShape* getChildShape() + { + return m_childConvexShape; + } + + const btConvexShape* getChildShape() const + { + return m_childConvexShape; + } + + virtual const char* getName()const + { + return "UniformScalingShape"; + } + + virtual int getShapeType() const { return UNIFORM_SCALING_SHAPE_PROXYTYPE; } + + + /////////////////////////// + + + ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + + virtual void setLocalScaling(const btVector3& scaling) ; + virtual const btVector3& getLocalScaling() const ; + + virtual void setMargin(btScalar margin); + virtual btScalar getMargin() const; + + virtual int getNumPreferredPenetrationDirections() const; + + virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const; + + +}; + +#endif //BT_UNIFORM_SCALING_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp index 2c565734e97..6551cfb92fe 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp @@ -16,7 +16,6 @@ subject to the following restrictions: #include "btContinuousConvexCollision.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "LinearMath/btTransformUtil.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" @@ -26,7 +25,7 @@ subject to the following restrictions: -btContinuousConvexCollision::btContinuousConvexCollision ( btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) +btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_simplexSolver(simplexSolver), m_penetrationDepthSolver(penetrationDepthSolver), m_convexA(convexA),m_convexB(convexB) @@ -35,7 +34,7 @@ m_convexA(convexA),m_convexB(convexB) /// This maximum should not be necessary. It allows for untested/degenerate cases in production code. /// You don't want your game ever to lock-up. -#define MAX_ITERATIONS 1000 +#define MAX_ITERATIONS 64 bool btContinuousConvexCollision::calcTimeOfImpact( const btTransform& fromA, @@ -52,10 +51,18 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA); btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB); + btScalar boundingRadiusA = m_convexA->getAngularMotionDisc(); btScalar boundingRadiusB = m_convexB->getAngularMotionDisc(); btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB; + btVector3 relLinVel = (linVelB-linVelA); + + btScalar relLinVelocLength = (linVelB-linVelA).length(); + + if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f) + return false; + btScalar radius = btScalar(0.001); @@ -93,7 +100,7 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btGjkPairDetector::ClosestPointInput input; //we don't use margins during CCD - gjk.setIgnoreMargin(true); + // gjk.setIgnoreMargin(true); input.m_transformA = fromA; input.m_transformB = fromB; @@ -108,25 +115,31 @@ bool btContinuousConvexCollision::calcTimeOfImpact( btScalar dist; dist = pointCollector1.m_distance; n = pointCollector1.m_normalOnBInWorld; + + btScalar projectedLinearVelocity = relLinVel.dot(n); //not close enough while (dist > radius) { numIter++; if (numIter > maxIter) + { return false; //todo: report a failure - + } btScalar dLambda = btScalar(0.); + projectedLinearVelocity = relLinVel.dot(n); + //calculate safe moving fraction from distance / (linear+rotational velocity) //btScalar clippedDist = GEN_min(angularConservativeRadius,dist); //btScalar clippedDist = dist; - btScalar projectedLinearVelocity = (linVelB-linVelA).dot(n); dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity); + + lambda = lambda + dLambda; if (lambda > btScalar(1.)) @@ -135,9 +148,14 @@ bool btContinuousConvexCollision::calcTimeOfImpact( if (lambda < btScalar(0.)) return false; + //todo: next check with relative epsilon if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); break; + } lastLambda = lambda; @@ -163,11 +181,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact( { //degenerate ?! result.m_fraction = lastLambda; - result.m_normal = n; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n;//.setValue(1,1,1);// = n; + result.m_hitPoint = pointCollector.m_pointInWorld; return true; } c = pointCollector.m_pointInWorld; - + n = pointCollector.m_normalOnBInWorld; dist = pointCollector.m_distance; } else { @@ -177,8 +197,13 @@ bool btContinuousConvexCollision::calcTimeOfImpact( } + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON) + return false; + result.m_fraction = lambda; result.m_normal = n; + result.m_hitPoint = c; return true; } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h index 9901bab4b45..28c2b4d6156 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h @@ -30,13 +30,13 @@ class btContinuousConvexCollision : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; btConvexPenetrationDepthSolver* m_penetrationDepthSolver; - btConvexShape* m_convexA; - btConvexShape* m_convexB; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; public: - btContinuousConvexCollision (btConvexShape* shapeA,btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); + btContinuousConvexCollision (const btConvexShape* shapeA,const btConvexShape* shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver); virtual bool calcTimeOfImpact( const btTransform& fromA, diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h index 3101b59993d..0edf4dcd496 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexCast.h @@ -17,11 +17,11 @@ subject to the following restrictions: #ifndef CONVEX_CAST_H #define CONVEX_CAST_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" class btMinkowskiSumShape; -#include "../../LinearMath/btIDebugDraw.h" +#include "LinearMath/btIDebugDraw.h" /// btConvexCast is an interface for Casting class btConvexCast @@ -42,19 +42,21 @@ public: CastResult() :m_fraction(btScalar(1e30)), - m_debugDrawer(0) + m_debugDrawer(0), + m_allowedPenetration(btScalar(0)) { } virtual ~CastResult() {}; - btVector3 m_normal; - btScalar m_fraction; btTransform m_hitTransformA; btTransform m_hitTransformB; - + btVector3 m_normal; + btVector3 m_hitPoint; + btScalar m_fraction; //input and output btIDebugDraw* m_debugDrawer; + btScalar m_allowedPenetration; }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h index 7caeba4be45..99690921317 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h @@ -21,7 +21,7 @@ class btStackAlloc; class btVector3; #include "btSimplexSolverInterface.h" class btConvexShape; -#include "../../LinearMath/btPoint3.h" +#include "LinearMath/btPoint3.h" class btTransform; ///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation. @@ -31,7 +31,7 @@ public: virtual ~btConvexPenetrationDepthSolver() {}; virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* convexA,btConvexShape* convexB, + const btConvexShape* convexA,const btConvexShape* convexB, const btTransform& transA,const btTransform& transB, btVector3& v, btPoint3& pa, btPoint3& pb, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h index 15000c1ab61..db797d5141f 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H #define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H -#include "../../LinearMath/btTransform.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" class btStackAlloc; /// This interface is made to be used by an iterative approach to do TimeOfImpact calculations @@ -58,7 +58,7 @@ struct btDiscreteCollisionDetectorInterface // give either closest points (distance > 0) or penetration (distance) // the normal always points from B towards A // - virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) = 0; + virtual void getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0; }; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp index 93edffeafd6..bef697a0a11 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp @@ -17,12 +17,17 @@ subject to the following restrictions: #include "btGjkConvexCast.h" #include "BulletCollision/CollisionShapes/btSphereShape.h" -#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "btGjkPairDetector.h" #include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" +#ifdef BT_USE_DOUBLE_PRECISION +#define MAX_ITERATIONS 64 +#else +#define MAX_ITERATIONS 32 +#endif -btGjkConvexCast::btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) +btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), m_convexA(convexA), m_convexB(convexB) @@ -38,120 +43,113 @@ bool btGjkConvexCast::calcTimeOfImpact( { - btMinkowskiSumShape combi(m_convexA,m_convexB); - btMinkowskiSumShape* convex = &combi; + m_simplexSolver->reset(); - btTransform rayFromLocalA; - btTransform rayToLocalA; - - rayFromLocalA = fromA.inverse()* fromB; - rayToLocalA = toA.inverse()* toB; - - - btTransform trA,trB; - trA = btTransform(fromA); - trB = btTransform(fromB); - trA.setOrigin(btPoint3(0,0,0)); - trB.setOrigin(btPoint3(0,0,0)); - - convex->setTransformA(trA); - convex->setTransformB(trB); - - - - - btScalar radius = btScalar(0.01); + /// compute linear velocity for this interval, to interpolate + //assume no rotation/angular velocity, assert here? + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); + btScalar radius = btScalar(0.001); btScalar lambda = btScalar(0.); - btVector3 s = rayFromLocalA.getOrigin(); - btVector3 r = rayToLocalA.getOrigin()-rayFromLocalA.getOrigin(); - btVector3 x = s; + btVector3 v(1,0,0); + + int maxIter = MAX_ITERATIONS; + btVector3 n; - n.setValue(0,0,0); + n.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); bool hasResult = false; btVector3 c; + btVector3 r = (linVelA-linVelB); btScalar lastLambda = lambda; + //btScalar epsilon = btScalar(0.001); + int numIter = 0; //first solution, using GJK - //no penetration support for now, perhaps pass a pointer when we really want it - btConvexPenetrationDepthSolver* penSolverPtr = 0; btTransform identityTrans; identityTrans.setIdentity(); - btSphereShape raySphere(btScalar(0.0)); - raySphere.setMargin(btScalar(0.)); - btTransform sphereTr; - sphereTr.setIdentity(); - sphereTr.setOrigin( rayFromLocalA.getOrigin()); +// result.drawCoordSystem(sphereTr); - result.drawCoordSystem(sphereTr); - { - btPointCollector pointCollector1; - btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); + btPointCollector pointCollector; - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = sphereTr; - input.m_transformB = identityTrans; - gjk.getClosestPoints(input,pointCollector1,0); + + btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver); + btGjkPairDetector::ClosestPointInput input; - hasResult = pointCollector1.m_hasResult; - c = pointCollector1.m_pointInWorld; - n = pointCollector1.m_normalOnBInWorld; - } + //we don't use margins during CCD + // gjk.setIgnoreMargin(true); - + input.m_transformA = fromA; + input.m_transformB = fromB; + gjk.getClosestPoints(input,pointCollector,0); + + hasResult = pointCollector.m_hasResult; + c = pointCollector.m_pointInWorld; if (hasResult) { btScalar dist; - dist = (c-x).length(); - if (dist < radius) - { - //penetration - lastLambda = btScalar(1.); - } + dist = pointCollector.m_distance; + n = pointCollector.m_normalOnBInWorld; + + //not close enough while (dist > radius) { - - n = x - c; - btScalar nDotr = n.dot(r); + numIter++; + if (numIter > maxIter) + { + return false; //todo: report a failure + } + btScalar dLambda = btScalar(0.); - if (nDotr >= -(SIMD_EPSILON*SIMD_EPSILON)) + btScalar projectedLinearVelocity = r.dot(n); + + dLambda = dist / (projectedLinearVelocity); + + lambda = lambda - dLambda; + + if (lambda > btScalar(1.)) return false; - - lambda = lambda - n.dot(n) / nDotr; - if (lambda <= lastLambda) - break; + if (lambda < btScalar(0.)) + return false; + + //todo: next check with relative epsilon + if (lambda <= lastLambda) + { + return false; + //n.setValue(0,0,0); + break; + } lastLambda = lambda; - x = s + lambda * r; - - sphereTr.setOrigin( x ); - result.drawCoordSystem(sphereTr); - btPointCollector pointCollector; - btGjkPairDetector gjk(&raySphere,convex,m_simplexSolver,penSolverPtr); - btGjkPairDetector::ClosestPointInput input; - input.m_transformA = sphereTr; - input.m_transformB = identityTrans; + //interpolate to next lambda + result.DebugDraw( lambda ); + input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + gjk.getClosestPoints(input,pointCollector,0); if (pointCollector.m_hasResult) { if (pointCollector.m_distance < btScalar(0.)) { - //degeneracy, report a hit result.m_fraction = lastLambda; - result.m_normal = n; + n = pointCollector.m_normalOnBInWorld; + result.m_normal=n; + result.m_hitPoint = pointCollector.m_pointInWorld; return true; } - c = pointCollector.m_pointInWorld; - dist = (c-x).length(); + c = pointCollector.m_pointInWorld; + n = pointCollector.m_normalOnBInWorld; + dist = pointCollector.m_distance; } else { //?? @@ -160,15 +158,19 @@ bool btGjkConvexCast::calcTimeOfImpact( } - if (lastLambda < btScalar(1.)) - { - - result.m_fraction = lastLambda; - result.m_normal = n; - return true; - } + //is n normalized? + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (n.dot(r)>=-result.m_allowedPenetration) + return false; + + result.m_fraction = lambda; + result.m_normal = n; + result.m_hitPoint = c; + return true; } return false; + + } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h index 3905c45e6d6..a977c9e83f7 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h @@ -18,9 +18,9 @@ subject to the following restrictions: #ifndef GJK_CONVEX_CAST_H #define GJK_CONVEX_CAST_H -#include "../CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btConvexCast.h" class btConvexShape; class btMinkowskiSumShape; @@ -30,12 +30,12 @@ class btMinkowskiSumShape; class btGjkConvexCast : public btConvexCast { btSimplexSolverInterface* m_simplexSolver; - btConvexShape* m_convexA; - btConvexShape* m_convexB; + const btConvexShape* m_convexA; + const btConvexShape* m_convexB; public: - btGjkConvexCast(btConvexShape* convexA,btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); + btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver); /// cast a convex against another convex object virtual bool calcTimeOfImpact( diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp index 8abdfdbb7e5..36cdeeaefdb 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp @@ -26,7 +26,7 @@ Nov.2006 #include "btGjkEpa.h" #include //for memset -#include +#include "LinearMath/btStackAlloc.h" #if defined(DEBUG) || defined (_DEBUG) #include //for debug printf @@ -580,8 +580,8 @@ using namespace gjkepa_impl; // -bool btGjkEpaSolver::Collide(btConvexShape *shape0,const btTransform &wtrs0, - btConvexShape *shape1,const btTransform &wtrs1, +bool btGjkEpaSolver::Collide(const btConvexShape *shape0,const btTransform &wtrs0, + const btConvexShape *shape1,const btTransform &wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results) @@ -602,13 +602,13 @@ GJK gjk(stackAlloc, wtrs1.getBasis(),wtrs1.getOrigin(),shape1, radialmargin+EPA_accuracy); const Z collide(gjk.SearchOrigin()); -results.gjk_iterations = gjk.iterations+1; +results.gjk_iterations = static_cast(gjk.iterations+1); if(collide) { /* Then EPA for penetration depth */ EPA epa(&gjk); const F pd(epa.EvaluatePD()); - results.epa_iterations = epa.iterations+1; + results.epa_iterations = static_cast(epa.iterations+1); if(pd>0) { results.status = sResults::Penetrating; diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h index 759b30bb17f..1c256f41939 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa.h @@ -21,7 +21,7 @@ Nov.2006 #ifndef _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ #define _05E48D53_04E0_49ad_BB0A_D74FE62E7366_ -#include "../CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btConvexShape.h" class btStackAlloc; @@ -35,7 +35,7 @@ struct sResults Separated, /* Shapes doesnt penetrate */ Penetrating, /* Shapes are penetrating */ GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ - EPA_Failed, /* EPA phase fail, bigger problem, need to save parameters, and debug */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ } status; btVector3 witnesses[2]; btVector3 normal; @@ -43,8 +43,8 @@ struct sResults int epa_iterations; int gjk_iterations; }; -static bool Collide(btConvexShape* shape0,const btTransform& wtrs0, - btConvexShape* shape1,const btTransform& wtrs1, +static bool Collide(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, btScalar radialmargin, btStackAlloc* stackAlloc, sResults& results); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp new file mode 100644 index 00000000000..ccfc22ee673 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp @@ -0,0 +1,943 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "btGjkEpa2.h" + +#if defined(DEBUG) || defined (_DEBUG) +#include //for debug printf +#ifdef __SPU__ +#include +#define printf spu_printf +#endif //__SPU__ +#endif + +namespace gjkepa2_impl +{ + +// Config + + /* GJK */ +#define GJK_MAX_ITERATIONS 128 +#define GJK_ACCURARY ((btScalar)0.0001) +#define GJK_MIN_DISTANCE ((btScalar)0.0001) +#define GJK_DUPLICATED_EPS ((btScalar)0.0001) +#define GJK_SIMPLEX2_EPS ((btScalar)0.0) +#define GJK_SIMPLEX3_EPS ((btScalar)0.0) +#define GJK_SIMPLEX4_EPS ((btScalar)0.0) + + /* EPA */ +#define EPA_MAX_VERTICES 64 +#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) +#define EPA_MAX_ITERATIONS 255 +#define EPA_ACCURACY ((btScalar)0.0001) +#define EPA_FALLBACK (10*EPA_ACCURACY) +#define EPA_PLANE_EPS ((btScalar)0.00001) +#define EPA_INSIDE_EPS ((btScalar)0.01) + + +// Shorthands +typedef unsigned int U; +typedef unsigned char U1; + +// MinkowskiDiff +struct MinkowskiDiff + { + const btConvexShape* m_shapes[2]; + btMatrix3x3 m_toshape1; + btTransform m_toshape0; + btVector3 (btConvexShape::*Ls)(const btVector3&) const; + void EnableMargin(bool enable) + { + if(enable) + Ls=&btConvexShape::localGetSupportingVertex; + else + Ls=&btConvexShape::localGetSupportingVertexWithoutMargin; + } + inline btVector3 Support0(const btVector3& d) const + { + return(((m_shapes[0])->*(Ls))(d)); + } + inline btVector3 Support1(const btVector3& d) const + { + return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d)); + } + inline btVector3 Support(const btVector3& d) const + { + return(Support0(d)-Support1(-d)); + } + btVector3 Support(const btVector3& d,U index) const + { + if(index) + return(Support1(d)); + else + return(Support0(d)); + } + }; + +typedef MinkowskiDiff tShape; + + +// GJK +struct GJK +{ +/* Types */ +struct sSV + { + btVector3 d,w; + }; +struct sSimplex + { + sSV* c[4]; + btScalar p[4]; + U rank; + }; +struct eStatus { enum _ { + Valid, + Inside, + Failed };}; +/* Fields */ +tShape m_shape; +btVector3 m_ray; +btScalar m_distance; +sSimplex m_simplices[2]; +sSV m_store[4]; +sSV* m_free[4]; +U m_nfree; +U m_current; +sSimplex* m_simplex; +eStatus::_ m_status; +/* Methods */ + GJK() + { + Initialize(); + } +void Initialize() + { + m_ray = btVector3(0,0,0); + m_nfree = 0; + m_status = eStatus::Failed; + m_current = 0; + m_distance = 0; + } +eStatus::_ Evaluate(const tShape& shapearg,const btVector3& guess) + { + U iterations=0; + btScalar sqdist=0; + btScalar alpha=0; + btVector3 lastw[4]; + U clastw=0; + /* Initialize solver */ + m_free[0] = &m_store[0]; + m_free[1] = &m_store[1]; + m_free[2] = &m_store[2]; + m_free[3] = &m_store[3]; + m_nfree = 4; + m_current = 0; + m_status = eStatus::Valid; + m_shape = shapearg; + m_distance = 0; + /* Initialize simplex */ + m_simplices[0].rank = 0; + m_ray = guess; + const btScalar sqrl= m_ray.length2(); + appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0)); + m_simplices[0].p[0] = 1; + m_ray = m_simplices[0].c[0]->w; + sqdist = sqrl; + lastw[0] = + lastw[1] = + lastw[2] = + lastw[3] = m_ray; + /* Loop */ + do { + const U next=1-m_current; + sSimplex& cs=m_simplices[m_current]; + sSimplex& ns=m_simplices[next]; + /* Check zero */ + const btScalar rl=m_ray.length(); + if(rlw; + bool found=false; + for(U i=0;i<4;++i) + { + if((w-lastw[i]).length2()w, + cs.c[1]->w, + weights,mask);break; + case 3: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + weights,mask);break; + case 4: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + cs.c[3]->w, + weights,mask);break; + } + if(sqdist>=0) + {/* Valid */ + ns.rank = 0; + m_ray = btVector3(0,0,0); + m_current = next; + for(U i=0,ni=cs.rank;iw*weights[i]; + } + else + { + m_free[m_nfree++] = cs.c[i]; + } + } + if(mask==15) m_status=eStatus::Inside; + } + else + {/* Return old simplex */ + removevertice(m_simplices[m_current]); + break; + } + m_status=((++iterations)rank) + { + case 1: + { + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + appendvertice(*m_simplex, axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 2: + { + const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; + for(U i=0;i<3;++i) + { + btVector3 axis=btVector3(0,0,0); + axis[i]=1; + const btVector3 p=cross(d,axis); + if(p.length2()>0) + { + appendvertice(*m_simplex, p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + } + break; + case 3: + { + const btVector3 n=cross(m_simplex->c[1]->w-m_simplex->c[0]->w, + m_simplex->c[2]->w-m_simplex->c[0]->w); + if(n.length2()>0) + { + appendvertice(*m_simplex,n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 4: + { + if(btFabs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, + m_simplex->c[1]->w-m_simplex->c[3]->w, + m_simplex->c[2]->w-m_simplex->c[3]->w))>0) + return(true); + } + break; + } + return(false); + } +/* Internals */ +void getsupport(const btVector3& d,sSV& sv) const + { + sv.d = d/d.length(); + sv.w = m_shape.Support(sv.d); + } +void removevertice(sSimplex& simplex) + { + m_free[m_nfree++]=simplex.c[--simplex.rank]; + } +void appendvertice(sSimplex& simplex,const btVector3& v) + { + simplex.p[simplex.rank]=0; + simplex.c[simplex.rank]=m_free[--m_nfree]; + getsupport(v,*simplex.c[simplex.rank++]); + } +static btScalar det(const btVector3& a,const btVector3& b,const btVector3& c) + { + return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()- + a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+ + a.x()*b.y()*c.z()-a.z()*b.y()*c.x()); + } +static btScalar projectorigin( const btVector3& a, + const btVector3& b, + btScalar* w,U& m) + { + const btVector3 d=b-a; + const btScalar l=d.length2(); + if(l>GJK_SIMPLEX2_EPS) + { + const btScalar t(l>0?-dot(a,d)/l:0); + if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length2()); } + else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length2()); } + else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); } + } + return(-1); + } +static btScalar projectorigin( const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar* w,U& m) + { + static const U imd3[]={1,2,0}; + const btVector3* vt[]={&a,&b,&c}; + const btVector3 dl[]={a-b,b-c,c-a}; + const btVector3 n=cross(dl[0],dl[1]); + const btScalar l=n.length2(); + if(l>GJK_SIMPLEX3_EPS) + { + btScalar mindist=-1; + btScalar subw[2]; + U subm; + for(U i=0;i<3;++i) + { + if(dot(*vt[i],cross(dl[i],n))>0) + { + const U j=imd3[i]; + const btScalar subd(projectorigin(*vt[i],*vt[j],subw,subm)); + if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) + { + btScalar mindist=-1; + btScalar subw[3]; + U subm; + for(U i=0;i<3;++i) + { + const U j=imd3[i]; + const btScalar s=vl*dot(d,cross(dl[i],dl[j])); + if(s>0) + { + const btScalar subd=projectorigin(*vt[i],*vt[j],d,subw,subm); + if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; + fb->e[eb]=(U1)ea;fb->f[eb]=fa; + } +static inline void append(sList& list,sFace* face) + { + face->l[0] = 0; + face->l[1] = list.root; + if(list.root) list.root->l[0]=face; + list.root = face; + ++list.count; + } +static inline void remove(sList& list,sFace* face) + { + if(face->l[1]) face->l[1]->l[0]=face->l[0]; + if(face->l[0]) face->l[0]->l[1]=face->l[1]; + if(face==list.root) list.root=face->l[1]; + --list.count; + } + + +void Initialize() + { + m_status = eStatus::Failed; + m_normal = btVector3(0,0,0); + m_depth = 0; + m_nextsv = 0; + for(U i=0;i1)&&gjk.EncloseOrigin()) + { + + /* Clean up */ + while(m_hull.root) + { + sFace* f = m_hull.root; + remove(m_hull,f); + append(m_stock,f); + } + m_status = eStatus::Valid; + m_nextsv = 0; + /* Orient simplex */ + if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, + simplex.c[1]->w-simplex.c[3]->w, + simplex.c[2]->w-simplex.c[3]->w)<0) + { + btSwap(simplex.c[0],simplex.c[1]); + btSwap(simplex.p[0],simplex.p[1]); + } + /* Build initial hull */ + sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), + newface(simplex.c[1],simplex.c[0],simplex.c[3],true), + newface(simplex.c[2],simplex.c[1],simplex.c[3],true), + newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; + if(m_hull.count==4) + { + sFace* best=findbest(); + sFace outer=*best; + U pass=0; + U iterations=0; + bind(tetra[0],0,tetra[1],0); + bind(tetra[0],1,tetra[2],0); + bind(tetra[0],2,tetra[3],0); + bind(tetra[1],1,tetra[3],2); + bind(tetra[1],2,tetra[2],1); + bind(tetra[2],2,tetra[3],1); + m_status=eStatus::Valid; + for(;iterationspass = (U1)(++pass); + gjk.getsupport(best->n,*w); + const btScalar wdist=dot(best->n,w->w)-best->d; + if(wdist>EPA_ACCURACY) + { + for(U j=0;(j<3)&&valid;++j) + { + valid&=expand( pass,w, + best->f[j],best->e[j], + horizon); + } + if(valid&&(horizon.nf>=3)) + { + bind(horizon.cf,1,horizon.ff,2); + remove(m_hull,best); + append(m_stock,best); + best=findbest(); + if(best->p>=outer.p) outer=*best; + } else { m_status=eStatus::InvalidHull;break; } + } else { m_status=eStatus::AccuraryReached;break; } + } else { m_status=eStatus::OutOfVertices;break; } + } + const btVector3 projection=outer.n*outer.d; + m_normal = outer.n; + m_depth = outer.d; + m_result.rank = 3; + m_result.c[0] = outer.c[0]; + m_result.c[1] = outer.c[1]; + m_result.c[2] = outer.c[2]; + m_result.p[0] = cross( outer.c[1]->w-projection, + outer.c[2]->w-projection).length(); + m_result.p[1] = cross( outer.c[2]->w-projection, + outer.c[0]->w-projection).length(); + m_result.p[2] = cross( outer.c[0]->w-projection, + outer.c[1]->w-projection).length(); + const btScalar sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; + m_result.p[0] /= sum; + m_result.p[1] /= sum; + m_result.p[2] /= sum; + return(m_status); + } + } + /* Fallback */ + m_status = eStatus::FallBack; + m_normal = -guess; + const btScalar nl=m_normal.length(); + if(nl>0) + m_normal = m_normal/nl; + else + m_normal = btVector3(1,0,0); + m_depth = 0; + m_result.rank=1; + m_result.c[0]=simplex.c[0]; + m_result.p[0]=1; + return(m_status); + } +sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) + { + if(m_stock.root) + { + sFace* face=m_stock.root; + remove(m_stock,face); + append(m_hull,face); + face->pass = 0; + face->c[0] = a; + face->c[1] = b; + face->c[2] = c; + face->n = cross(b->w-a->w,c->w-a->w); + const btScalar l=face->n.length(); + const bool v=l>EPA_ACCURACY; + face->p = btMin(btMin( + dot(a->w,cross(face->n,a->w-b->w)), + dot(b->w,cross(face->n,b->w-c->w))), + dot(c->w,cross(face->n,c->w-a->w))) / + (v?l:1); + face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; + if(v) + { + face->d = dot(a->w,face->n)/l; + face->n /= l; + if(forced||(face->d>=-EPA_PLANE_EPS)) + { + return(face); + } else m_status=eStatus::NonConvex; + } else m_status=eStatus::Degenerated; + remove(m_hull,face); + append(m_stock,face); + return(0); + } + m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; + return(0); + } +sFace* findbest() + { + sFace* minf=m_hull.root; + btScalar mind=minf->d*minf->d; + btScalar maxp=minf->p; + for(sFace* f=minf->l[1];f;f=f->l[1]) + { + const btScalar sqd=f->d*f->d; + if((f->p>=maxp)&&(sqdp; + } + } + return(minf); + } +bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon) + { + static const U i1m3[]={1,2,0}; + static const U i2m3[]={2,0,1}; + if(f->pass!=pass) + { + const U e1=i1m3[e]; + if((dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) + { + sFace* nf=newface(f->c[e1],f->c[e],w,false); + if(nf) + { + bind(nf,0,f,e); + if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; + horizon.cf=nf; + ++horizon.nf; + return(true); + } + } + else + { + const U e2=i2m3[e]; + f->pass = (U1)pass; + if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& + expand(pass,w,f->f[e2],f->e[e2],horizon)) + { + remove(m_hull,f); + append(m_stock,f); + return(true); + } + } + } + return(false); + } + +}; + +// +static void Initialize( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + btGjkEpaSolver2::sResults& results, + tShape& shape, + bool withmargins) +{ +/* Results */ +results.witnesses[0] = +results.witnesses[1] = btVector3(0,0,0); +results.status = btGjkEpaSolver2::sResults::Separated; +/* Shape */ +shape.m_shapes[0] = shape0; +shape.m_shapes[1] = shape1; +shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis()); +shape.m_toshape0 = wtrs0.inverseTimes(wtrs1); +shape.EnableMargin(withmargins); +} + +} + +// +// Api +// + +using namespace gjkepa2_impl; + +// +int btGjkEpaSolver2::StackSizeRequirement() +{ +return(sizeof(GJK)+sizeof(EPA)); +} + +// +bool btGjkEpaSolver2::Distance( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ +tShape shape; +Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); +if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + results.normal = w0-w1; + results.distance = results.normal.length(); + results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; + return(true); + } + else + { + results.status = gjk_status==GJK::eStatus::Inside? + sResults::Penetrating : + sResults::GJK_Failed ; + return(false); + } +} + +// +bool btGjkEpaSolver2::Penetration( const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins) +{ +tShape shape; +Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); +switch(gjk_status) + { + case GJK::eStatus::Inside: + { + EPA epa; + EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); + if(epa_status!=EPA::eStatus::Failed) + { + btVector3 w0=btVector3(0,0,0); + for(U i=0;id,0)*epa.m_result.p[i]; + } + results.status = sResults::Penetrating; + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*(w0-epa.m_normal*epa.m_depth); + results.normal = -epa.m_normal; + results.distance = -epa.m_depth; + return(true); + } else results.status=sResults::EPA_Failed; + } + break; + case GJK::eStatus::Failed: + results.status=sResults::GJK_Failed; + break; + } +return(false); +} + +// +btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position, + btScalar margin, + const btConvexShape* shape0, + const btTransform& wtrs0, + sResults& results) +{ +tShape shape; +btSphereShape shape1(margin); +btTransform wtrs1(btQuaternion(0,0,0,1),position); +Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false); +GJK gjk; +GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1)); +if(gjk_status==GJK::eStatus::Valid) + { + btVector3 w0=btVector3(0,0,0); + btVector3 w1=btVector3(0,0,0); + for(U i=0;irank;++i) + { + const btScalar p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = wtrs0*w0; + results.witnesses[1] = wtrs0*w1; + const btVector3 delta= results.witnesses[1]- + results.witnesses[0]; + const btScalar margin= shape0->getMargin()+ + shape1.getMargin(); + const btScalar length= delta.length(); + results.normal = delta/length; + results.witnesses[0] += results.normal*margin; + return(length-margin); + } + else + { + if(gjk_status==GJK::eStatus::Inside) + { + if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results)) + { + const btVector3 delta= results.witnesses[0]- + results.witnesses[1]; + const btScalar length= delta.length(); + if (length >= SIMD_EPSILON) + results.normal = delta/length; + return(-length); + } + } + } +return(SIMD_INFINITY); +} + +// +bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0, + const btTransform& wtrs0, + const btConvexShape* shape1, + const btTransform& wtrs1, + const btVector3& guess, + sResults& results) +{ +if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results)) + return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false)); + else + return(true); +} + +/* Symbols cleanup */ + +#undef GJK_MAX_ITERATIONS +#undef GJK_ACCURARY +#undef GJK_MIN_DISTANCE +#undef GJK_DUPLICATED_EPS +#undef GJK_SIMPLEX2_EPS +#undef GJK_SIMPLEX3_EPS +#undef GJK_SIMPLEX4_EPS + +#undef EPA_MAX_VERTICES +#undef EPA_MAX_FACES +#undef EPA_MAX_ITERATIONS +#undef EPA_ACCURACY +#undef EPA_FALLBACK +#undef EPA_PLANE_EPS +#undef EPA_INSIDE_EPS diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h new file mode 100644 index 00000000000..a55214203d3 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h @@ -0,0 +1,71 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ +#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ +#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_ +#include "BulletCollision/CollisionShapes/btConvexShape.h" + +///btGjkEpaSolver contributed under zlib by Nathanael Presson +struct btGjkEpaSolver2 +{ +struct sResults + { + enum eStatus + { + Separated, /* Shapes doesnt penetrate */ + Penetrating, /* Shapes are penetrating */ + GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ + } status; + btVector3 witnesses[2]; + btVector3 normal; + btScalar distance; + }; + +static int StackSizeRequirement(); + +static bool Distance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); + +static bool Penetration(const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results, + bool usemargins=true); + +static btScalar SignedDistance( const btVector3& position, + btScalar margin, + const btConvexShape* shape, + const btTransform& wtrs, + sResults& results); + +static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0, + const btConvexShape* shape1,const btTransform& wtrs1, + const btVector3& guess, + sResults& results); +}; + +#endif diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp index 87330493b60..c4f84ed4d75 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp @@ -18,9 +18,10 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexShape.h" #include "btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* pConvexA, btConvexShape* pConvexB, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc ) @@ -32,10 +33,20 @@ bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& sim const btScalar radialmargin(btScalar(0.)); +//#define USE_ORIGINAL_GJK 1 +#ifdef USE_ORIGINAL_GJK btGjkEpaSolver::sResults results; if(btGjkEpaSolver::Collide( pConvexA,transformA, pConvexB,transformB, radialmargin,stackAlloc,results)) +#else + btVector3 guessVector(transformA.getOrigin()-transformB.getOrigin()); + btGjkEpaSolver2::sResults results; + if(btGjkEpaSolver2::Penetration(pConvexA,transformA, + pConvexB,transformB, + guessVector,results)) + +#endif { // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0)); //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h index 3916ba0776c..2dc069ce5cf 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h @@ -26,7 +26,7 @@ class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver public : bool calcPenDepth( btSimplexSolverInterface& simplexSolver, - btConvexShape* pConvexA, btConvexShape* pConvexB, + const btConvexShape* pConvexA, const btConvexShape* pConvexB, const btTransform& transformA, const btTransform& transformB, btVector3& v, btPoint3& wWitnessOnA, btPoint3& wWitnessOnB, class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc ); diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp index f1f3f7f7f6c..01fb1a4b068 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp @@ -35,7 +35,7 @@ int gNumGjkChecks = 0; -btGjkPairDetector::btGjkPairDetector(btConvexShape* objectA,btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) +btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver) :m_cachedSeparatingAxis(btScalar(0.),btScalar(0.),btScalar(1.)), m_penetrationDepthSolver(penetrationDepthSolver), m_simplexSolver(simplexSolver), @@ -47,7 +47,7 @@ m_catchDegeneracies(1) { } -void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw) +void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults) { btScalar distance=btScalar(0.); btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.)); @@ -144,6 +144,13 @@ void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& break; } + if(m_cachedSeparatingAxis.length2() @@ -169,7 +162,7 @@ int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const return nearestPoint; } -void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) +int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint) { assert(validContactDistance(newPoint)); @@ -182,7 +175,7 @@ void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) #else insertIndex = 0; #endif - + clearUserCache(m_pointCache[insertIndex]); } else { @@ -190,7 +183,9 @@ void btPersistentManifold::AddManifoldPoint(const btManifoldPoint& newPoint) } - replaceContactPoint(newPoint,insertIndex); + btAssert(m_pointCache[insertIndex].m_userPersistentData==0); + m_pointCache[insertIndex] = newPoint; + return insertIndex; } btScalar btPersistentManifold::getContactBreakingThreshold() const @@ -198,10 +193,20 @@ btScalar btPersistentManifold::getContactBreakingThreshold() const return gContactBreakingThreshold; } + + void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB) { int i; - +#ifdef DEBUG_PERSISTENCY + printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n", + trA.getOrigin().getX(), + trA.getOrigin().getY(), + trA.getOrigin().getZ(), + trB.getOrigin().getX(), + trB.getOrigin().getY(), + trB.getOrigin().getZ()); +#endif //DEBUG_PERSISTENCY /// first refresh worldspace positions and distance for (i=getNumContacts()-1;i>=0;i--) { @@ -232,6 +237,11 @@ void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btT if (distance2d > getContactBreakingThreshold()*getContactBreakingThreshold() ) { removeContactPoint(i); + } else + { + //contact point processed callback + if (gContactProcessedCallback) + (*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1); } } } diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h index a5918b84db3..c122eb865e8 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h @@ -17,9 +17,10 @@ subject to the following restrictions: #define PERSISTENT_MANIFOLD_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" #include "btManifoldPoint.h" +#include "LinearMath/btAlignedAllocator.h" struct btCollisionResult; @@ -27,6 +28,7 @@ struct btCollisionResult; extern btScalar gContactBreakingThreshold; typedef bool (*ContactDestroyedCallback)(void* userPersistentData); +typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1); extern ContactDestroyedCallback gContactDestroyedCallback; @@ -34,8 +36,13 @@ extern ContactDestroyedCallback gContactDestroyedCallback; #define MANIFOLD_CACHE_SIZE 4 -///btPersistentManifold maintains contact points, and reduces them to 4. -///It does contact filtering/contact reduction. +///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase. +///Those contact points are created by the collision narrow phase. +///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time. +///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large) +///reduces the cache to 4 points, when more then 4 points are added, using following rules: +///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points +///note that some pairs of objects might have more then one contact manifold. ATTRIBUTE_ALIGNED16( class) btPersistentManifold { @@ -55,20 +62,23 @@ ATTRIBUTE_ALIGNED16( class) btPersistentManifold public: - int m_index1; + BT_DECLARE_ALIGNED_ALLOCATOR(); + + int m_index1a; btPersistentManifold(); - btPersistentManifold(void* body0,void* body1) + btPersistentManifold(void* body0,void* body1,int bla) : m_body0(body0),m_body1(body1),m_cachedPoints(0) { + (void)bla; } - inline void* getBody0() { return m_body0;} - inline void* getBody1() { return m_body1;} + SIMD_FORCE_INLINE void* getBody0() { return m_body0;} + SIMD_FORCE_INLINE void* getBody1() { return m_body1;} - inline const void* getBody0() const { return m_body0;} - inline const void* getBody1() const { return m_body1;} + SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;} + SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;} void setBodies(void* body0,void* body1) { @@ -82,15 +92,15 @@ public: void DebugPersistency(); #endif // - inline int getNumContacts() const { return m_cachedPoints;} + SIMD_FORCE_INLINE int getNumContacts() const { return m_cachedPoints;} - inline const btManifoldPoint& getContactPoint(int index) const + SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const { btAssert(index < m_cachedPoints); return m_pointCache[index]; } - inline btManifoldPoint& getContactPoint(int index) + SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index) { btAssert(index < m_cachedPoints); return m_pointCache[index]; @@ -101,7 +111,7 @@ public: int getCacheEntry(const btManifoldPoint& newPoint) const; - void AddManifoldPoint( const btManifoldPoint& newPoint); + int addManifoldPoint( const btManifoldPoint& newPoint); void removeContactPoint (int index) { @@ -114,6 +124,11 @@ public: m_pointCache[index] = m_pointCache[lastUsedIndex]; //get rid of duplicated userPersistentData pointer m_pointCache[lastUsedIndex].m_userPersistentData = 0; + m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f; + m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f; + m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f; + m_pointCache[lastUsedIndex].m_lifeTime = 0; } btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0); @@ -126,12 +141,20 @@ public: #define MAINTAIN_PERSISTENCY 1 #ifdef MAINTAIN_PERSISTENCY int lifeTime = m_pointCache[insertIndex].getLifeTime(); + btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse; + btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1; + btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2; + btAssert(lifeTime>=0); void* cache = m_pointCache[insertIndex].m_userPersistentData; m_pointCache[insertIndex] = newPoint; m_pointCache[insertIndex].m_userPersistentData = cache; + m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse; + m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1; + m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2; + m_pointCache[insertIndex].m_lifeTime = lifeTime; #else clearUserCache(m_pointCache[insertIndex]); @@ -147,7 +170,16 @@ public: /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin void refreshContactPoints( const btTransform& trA,const btTransform& trB); - void clearManifold(); + + SIMD_FORCE_INLINE void clearManifold() + { + int i; + for (i=0;i +#include "BulletCollision/CollisionShapes/btConvexShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h" +#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "btRaycastCallback.h" btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to) @@ -29,8 +36,6 @@ btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) { - - const btVector3 &vert0=triangle[0]; const btVector3 &vert1=triangle[1]; const btVector3 &vert2=triangle[2]; @@ -99,3 +104,60 @@ void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, } } } + + +btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin) +{ + m_convexShape = convexShape; + m_convexShapeFrom = convexShapeFrom; + m_convexShapeTo = convexShapeTo; + m_triangleToWorld = triangleToWorld; + m_hitFraction = 1.0; + m_triangleCollisionMargin = triangleCollisionMargin; +} + +void +btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex) +{ + btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]); + triangleShape.setMargin(m_triangleCollisionMargin); + + btVoronoiSimplexSolver simplexSolver; + btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver; + +//#define USE_SUBSIMPLEX_CONVEX_CAST 1 +//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver); +#else + //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver); + btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver); +#endif //#USE_SUBSIMPLEX_CONVEX_CAST + + btConvexCast::CastResult castResult; + castResult.m_fraction = btScalar(1.); + if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult)) + { + //add hit + if (castResult.m_normal.length2() > btScalar(0.0001)) + { + if (castResult.m_fraction < m_hitFraction) + { +/* btContinuousConvexCast's normal is already in world space */ +/* +#ifdef USE_SUBSIMPLEX_CONVEX_CAST + //rotate normal into worldspace + castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal; +#endif //USE_SUBSIMPLEX_CONVEX_CAST +*/ + castResult.m_normal.normalize(); + + reportHit (castResult.m_normal, + castResult.m_hitPoint, + castResult.m_fraction, + partId, + triangleIndex); + } + } + } +} diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h index a0bbc9f8fe9..d2b4b80f8ba 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h @@ -16,15 +16,16 @@ subject to the following restrictions: #ifndef RAYCAST_TRI_CALLBACK_H #define RAYCAST_TRI_CALLBACK_H -#include "../CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "LinearMath/btTransform.h" struct btBroadphaseProxy; - +class btConvexShape; class btTriangleRaycastCallback: public btTriangleCallback { public: - //input + //input btVector3 m_from; btVector3 m_to; @@ -38,5 +39,22 @@ public: }; +class btTriangleConvexcastCallback : public btTriangleCallback +{ +public: + const btConvexShape* m_convexShape; + btTransform m_convexShapeFrom; + btTransform m_convexShapeTo; + btTransform m_triangleToWorld; + btScalar m_hitFraction; + btScalar m_triangleCollisionMargin; + + btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin); + + virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex); + + virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0; +}; + #endif //RAYCAST_TRI_CALLBACK_H diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h index 58393b2eab9..cf65f46505b 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h @@ -18,8 +18,8 @@ subject to the following restrictions: #ifndef SIMPLEX_SOLVER_INTERFACE_H #define SIMPLEX_SOLVER_INTERFACE_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btPoint3.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btPoint3.h" #define NO_VIRTUAL_INTERFACE 1 #ifdef NO_VIRTUAL_INTERFACE diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp index 687738b7fa9..4c709a8c3a9 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp @@ -16,9 +16,11 @@ subject to the following restrictions: #include "btSubSimplexConvexCast.h" #include "BulletCollision/CollisionShapes/btConvexShape.h" + #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" - +#include "btPointCollector.h" +#include "LinearMath/btTransformUtil.h" btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver) :m_simplexSolver(simplexSolver), @@ -41,34 +43,24 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( CastResult& result) { - btMinkowskiSumShape combi(m_convexA,m_convexB); - btMinkowskiSumShape* convex = &combi; - - btTransform rayFromLocalA; - btTransform rayToLocalA; - - rayFromLocalA = fromA.inverse()* fromB; - rayToLocalA = toA.inverse()* toB; - - m_simplexSolver->reset(); - convex->setTransformB(btTransform(rayFromLocalA.getBasis())); - - //btScalar radius = btScalar(0.01); + btVector3 linVelA,linVelB; + linVelA = toA.getOrigin()-fromA.getOrigin(); + linVelB = toB.getOrigin()-fromB.getOrigin(); btScalar lambda = btScalar(0.); - //todo: need to verify this: - //because of minkowski difference, we need the inverse direction - - btVector3 s = -rayFromLocalA.getOrigin(); - btVector3 r = -(rayToLocalA.getOrigin()-rayFromLocalA.getOrigin()); - btVector3 x = s; - btVector3 v; - btVector3 arbitraryPoint = convex->localGetSupportingVertex(r); - - v = x - arbitraryPoint; + btTransform interpolatedTransA = fromA; + btTransform interpolatedTransB = fromB; + + ///take relative motion + btVector3 r = (linVelA-linVelB); + btVector3 v; + + btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis())); + btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis())); + v = supVertexA-supVertexB; int maxIter = MAX_ITERATIONS; btVector3 n; @@ -90,11 +82,17 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( while ( (dist2 > epsilon) && maxIter--) { - p = convex->localGetSupportingVertex( v); - w = x - p; + supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis())); + supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis())); + w = supVertexA-supVertexB; btScalar VdotW = v.dot(w); + if (lambda > btScalar(1.0)) + { + return false; + } + if ( VdotW > btScalar(0.)) { VdotR = v.dot(r); @@ -104,20 +102,25 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( else { lambda = lambda - VdotW / VdotR; - x = s + lambda * r; - m_simplexSolver->reset(); + //interpolate to next lambda + // x = s + lambda * r; + interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda); + interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda); + //m_simplexSolver->reset(); //check next line - w = x-p; + w = supVertexA-supVertexB; lastLambda = lambda; n = v; hasResult = true; } } - m_simplexSolver->addVertex( w, x , p); + m_simplexSolver->addVertex( w, supVertexA , supVertexB); if (m_simplexSolver->closest(v)) { dist2 = v.length2(); hasResult = true; + //todo: check this normal for validity + //n=v; //printf("V=%f , %f, %f\n",v[0],v[1],v[2]); //printf("DIST2=%f\n",dist2); //printf("numverts = %i\n",m_simplexSolver->numVertices()); @@ -129,11 +132,26 @@ bool btSubsimplexConvexCast::calcTimeOfImpact( //int numiter = MAX_ITERATIONS - maxIter; // printf("number of iterations: %d", numiter); - result.m_fraction = lambda; - result.m_normal = n; + + //don't report a time of impact when moving 'away' from the hitnormal + + result.m_fraction = lambda; + if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON)) + result.m_normal = n.normalized(); + else + result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (result.m_normal.dot(r)>=-result.m_allowedPenetration) + return false; + + btVector3 hitA,hitB; + m_simplexSolver->compute_points(hitA,hitB); + result.m_hitPoint=hitB; return true; } + diff --git a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp index 105b7eccefa..cf8a3ab5eb1 100644 --- a/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp +++ b/extern/bullet2/src/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp @@ -26,7 +26,7 @@ subject to the following restrictions: #include "btVoronoiSimplexSolver.h" #include -#include +//#include #define VERTA 0 #define VERTB 1 diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt index 8598575799a..58b023e9775 100644 --- a/extern/bullet2/src/BulletDynamics/CMakeLists.txt +++ b/extern/bullet2/src/BulletDynamics/CMakeLists.txt @@ -5,16 +5,32 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletDynamics ConstraintSolver/btContactConstraint.cpp + ConstraintSolver/btContactConstraint.h + ConstraintSolver/btConeTwistConstraint.cpp + ConstraintSolver/btConeTwistConstraint.h ConstraintSolver/btGeneric6DofConstraint.cpp + ConstraintSolver/btGeneric6DofConstraint.h ConstraintSolver/btHingeConstraint.cpp + ConstraintSolver/btHingeConstraint.h ConstraintSolver/btPoint2PointConstraint.cpp + ConstraintSolver/btPoint2PointConstraint.h ConstraintSolver/btSequentialImpulseConstraintSolver.cpp + ConstraintSolver/btSequentialImpulseConstraintSolver.h + ConstraintSolver/btSliderConstraint.cpp + ConstraintSolver/btSliderConstraint.h ConstraintSolver/btSolve2LinearConstraint.cpp + ConstraintSolver/btSolve2LinearConstraint.h ConstraintSolver/btTypedConstraint.cpp - Dynamics/btDiscreteDynamicsWorld.cpp - Dynamics/btSimpleDynamicsWorld.cpp + ConstraintSolver/btTypedConstraint.h Dynamics/Bullet-C-API.cpp + Dynamics/btDiscreteDynamicsWorld.cpp + Dynamics/btDiscreteDynamicsWorld.h + Dynamics/btSimpleDynamicsWorld.cpp + Dynamics/btSimpleDynamicsWorld.h Dynamics/btRigidBody.cpp + Dynamics/btRigidBody.h Vehicle/btRaycastVehicle.cpp + Vehicle/btRaycastVehicle.h Vehicle/btWheelInfo.cpp + Vehicle/btWheelInfo.h ) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index 2289621e8e3..61dad522a5b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -19,24 +19,20 @@ Written by: Marcus Hennix #include "btConeTwistConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" -#include "LinearMath/btSimdMinMax.h" +#include "LinearMath/btMinMax.h" #include btConeTwistConstraint::btConeTwistConstraint() +:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE) { } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame,const btTransform& rbBFrame) - :btTypedConstraint(rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false) { - // flip axis for correct angles - m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - m_swingSpan1 = btScalar(1e30); m_swingSpan2 = btScalar(1e30); m_twistSpan = btScalar(1e30); @@ -49,20 +45,11 @@ btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, } btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame) - :btTypedConstraint(rbA),m_rbAFrame(rbAFrame), + :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame), m_angularOnly(false) { m_rbBFrame = m_rbAFrame; - // flip axis for correct angles - m_rbBFrame.getBasis()[1][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); - - m_rbBFrame.getBasis()[2][0] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][1] *= btScalar(-1.); - m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); - m_swingSpan1 = btScalar(1e30); m_swingSpan2 = btScalar(1e30); m_twistSpan = btScalar(1e30); @@ -127,22 +114,39 @@ void btConeTwistConstraint::buildJacobian() btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + btScalar swx=btScalar(0.),swy = btScalar(0.); + btScalar thresh = btScalar(10.); + btScalar fact; + // Get Frame into world space if (m_swingSpan1 >= btScalar(0.05f)) { b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); - swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); +// swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis2); + swing1 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing1 *= fact; + } if (m_swingSpan2 >= btScalar(0.05f)) { b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); - swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); +// swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis3); + swing2 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing2 *= fact; } btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2); - btScalar EllipseAngle = btFabs(swing1)* RMaxAngle1Sq + btFabs(swing2) * RMaxAngle2Sq; + btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq; if (EllipseAngle > 1.0f) { @@ -246,7 +250,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, 0.0f ); + m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) ); impulseMag = m_accSwingLimitImpulse - temp; btVector3 impulse = m_swingAxis * impulseMag; @@ -264,7 +268,7 @@ void btConeTwistConstraint::solveConstraint(btScalar timeStep) // Clamp the accumulated impulse btScalar temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, 0.0f ); + m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) ); impulseMag = m_accTwistLimitImpulse - temp; btVector3 impulse = m_twistAxis * impulseMag; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h index 874669c80b3..f121919c8f9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h @@ -30,6 +30,9 @@ class btRigidBody; ///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc) class btConeTwistConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btTransform m_rbAFrame; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h index 7e8458c2c7b..7a8e9c1953d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConstraintSolver.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef CONSTRAINT_SOLVER_H #define CONSTRAINT_SOLVER_H -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" class btPersistentManifold; class btRigidBody; @@ -26,7 +26,7 @@ struct btContactSolverInfo; struct btBroadphaseProxy; class btIDebugDraw; class btStackAlloc; - +class btDispatcher; /// btConstraintSolver provides solver interface class btConstraintSolver { @@ -35,8 +35,15 @@ public: virtual ~btConstraintSolver() {} - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc) = 0; + virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;} + ///solve a group of constraints + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0; + + virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */, btStackAlloc* /* stackAlloc */) {;} + + ///clear internal cached data and reset random seed + virtual void reset() = 0; }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp index bb3fe832592..4d7cd05feb7 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.cpp @@ -192,8 +192,8 @@ btScalar resolveSingleFriction( j1 = -vrel * cpd->m_jacDiagABInvTangent0; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = oldTangentImpulse + j1; - GEN_set_min(cpd->m_accumulatedTangentImpulse0, limit); - GEN_set_max(cpd->m_accumulatedTangentImpulse0, -limit); + btSetMin(cpd->m_accumulatedTangentImpulse0, limit); + btSetMax(cpd->m_accumulatedTangentImpulse0, -limit); j1 = cpd->m_accumulatedTangentImpulse0 - oldTangentImpulse; } @@ -206,8 +206,8 @@ btScalar resolveSingleFriction( j2 = -vrel * cpd->m_jacDiagABInvTangent1; btScalar oldTangentImpulse = cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = oldTangentImpulse + j2; - GEN_set_min(cpd->m_accumulatedTangentImpulse1, limit); - GEN_set_max(cpd->m_accumulatedTangentImpulse1, -limit); + btSetMin(cpd->m_accumulatedTangentImpulse1, limit); + btSetMax(cpd->m_accumulatedTangentImpulse1, -limit); j2 = cpd->m_accumulatedTangentImpulse1 - oldTangentImpulse; } @@ -233,6 +233,12 @@ btScalar resolveSingleFriction( } +btScalar resolveSingleFrictionOriginal( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo); + btScalar resolveSingleFrictionOriginal( btRigidBody& body1, btRigidBody& body2, @@ -270,8 +276,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent0; btScalar total = cpd->m_accumulatedTangentImpulse0 + j; - GEN_set_min(total, limit); - GEN_set_max(total, -limit); + btSetMin(total, limit); + btSetMax(total, -limit); j = total - cpd->m_accumulatedTangentImpulse0; cpd->m_accumulatedTangentImpulse0 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential0, rel_pos1); @@ -290,8 +296,8 @@ btScalar resolveSingleFrictionOriginal( // calculate j that moves us to zero relative velocity btScalar j = -vrel * cpd->m_jacDiagABInvTangent1; btScalar total = cpd->m_accumulatedTangentImpulse1 + j; - GEN_set_min(total, limit); - GEN_set_max(total, -limit); + btSetMin(total, limit); + btSetMax(total, -limit); j = total - cpd->m_accumulatedTangentImpulse1; cpd->m_accumulatedTangentImpulse1 = total; body1.applyImpulse(j * cpd->m_frictionWorldTangential1, rel_pos1); @@ -388,8 +394,8 @@ btScalar resolveSingleCollisionCombined( (body1.getInvMass() + body2.getInvMass() + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); btScalar normal_impulse = cpd->m_appliedImpulse * combinedFriction; - GEN_set_min(friction_impulse, normal_impulse); - GEN_set_max(friction_impulse, -normal_impulse); + btSetMin(friction_impulse, normal_impulse); + btSetMax(friction_impulse, -normal_impulse); body1.applyImpulse(lat_vel * -friction_impulse, rel_pos1); body2.applyImpulse(lat_vel * friction_impulse, rel_pos2); } @@ -400,6 +406,12 @@ btScalar resolveSingleCollisionCombined( return normalImpulse; } +btScalar resolveSingleFrictionEmpty( + btRigidBody& body1, + btRigidBody& body2, + btManifoldPoint& contactPoint, + const btContactSolverInfo& solverInfo); + btScalar resolveSingleFrictionEmpty( btRigidBody& body1, btRigidBody& body2, diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h index 0834deddeac..826e79f78bd 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactConstraint.h @@ -19,8 +19,8 @@ subject to the following restrictions: //todo: make into a proper class working with the iterative constraint solver class btRigidBody; -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btScalar.h" struct btContactSolverInfo; class btManifoldPoint; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h index c3c73e300f4..916d4581f79 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btContactSolverInfo.h @@ -16,21 +16,17 @@ subject to the following restrictions: #ifndef CONTACT_SOLVER_INFO #define CONTACT_SOLVER_INFO - -struct btContactSolverInfo +enum btSolverMode { + SOLVER_RANDMIZE_ORDER = 1, + SOLVER_FRICTION_SEPARATE = 2, + SOLVER_USE_WARMSTARTING = 4, + SOLVER_CACHE_FRIENDLY = 8 +}; - inline btContactSolverInfo() - { - m_tau = btScalar(0.6); - m_damping = btScalar(1.0); - m_friction = btScalar(0.3); - m_restitution = btScalar(0.); - m_maxErrorReduction = btScalar(20.); - m_numIterations = 10; - m_erp = btScalar(0.4); - m_sor = btScalar(1.3); - } +struct btContactSolverInfoData +{ + btScalar m_tau; btScalar m_damping; @@ -40,8 +36,40 @@ struct btContactSolverInfo int m_numIterations; btScalar m_maxErrorReduction; btScalar m_sor; - btScalar m_erp; + btScalar m_erp;//used as Baumgarte factor + btScalar m_erp2;//used in Split Impulse + int m_splitImpulse; + btScalar m_splitImpulsePenetrationThreshold; + btScalar m_linearSlop; + btScalar m_warmstartingFactor; + + int m_solverMode; + }; +struct btContactSolverInfo : public btContactSolverInfoData +{ + + + + inline btContactSolverInfo() + { + m_tau = btScalar(0.6); + m_damping = btScalar(1.0); + m_friction = btScalar(0.3); + m_restitution = btScalar(0.); + m_maxErrorReduction = btScalar(20.); + m_numIterations = 10; + m_erp = btScalar(0.2); + m_erp2 = btScalar(0.1); + m_sor = btScalar(1.3); + m_splitImpulse = false; + m_splitImpulsePenetrationThreshold = -0.02f; + m_linearSlop = btScalar(0.0); + m_warmstartingFactor=btScalar(0.85); + m_solverMode = SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY | SOLVER_USE_WARMSTARTING; + } +}; + #endif //CONTACT_SOLVER_INFO diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp index 747d10d1f8b..077b326d13a 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp @@ -4,14 +4,20 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +/* +2007-09-09 +Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ #include "btGeneric6DofConstraint.h" @@ -19,371 +25,504 @@ subject to the following restrictions: #include "LinearMath/btTransformUtil.h" #include + static const btScalar kSign[] = { btScalar(1.0), btScalar(-1.0), btScalar(1.0) }; static const int kAxisA[] = { 1, 0, 0 }; static const int kAxisB[] = { 2, 2, 1 }; #define GENERIC_D6_DISABLE_WARMSTARTING 1 -btGeneric6DofConstraint::btGeneric6DofConstraint() +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index); +btScalar btGetMatrixElem(const btMatrix3x3& mat, int index) { -} - -btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) -: btTypedConstraint(rbA, rbB) -, m_frameInA(frameInA) -, m_frameInB(frameInB) -{ - //free means upper < lower, - //locked means upper == lower - //limited means upper > lower - //so start all locked - for (int i=0; i<6;++i) - { - m_lowerLimit[i] = btScalar(0.0); - m_upperLimit[i] = btScalar(0.0); - m_accumulatedImpulse[i] = btScalar(0.0); - } - -} - - -void btGeneric6DofConstraint::buildJacobian() -{ - btVector3 localNormalInA(0,0,0); - - const btVector3& pivotInA = m_frameInA.getOrigin(); - const btVector3& pivotInB = m_frameInB.getOrigin(); - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - int i; - //linear part - for (i=0;i<3;i++) - { - if (isLimited(i)) - { - localNormalInA[i] = 1; - btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; - - - // Create linear atom - new (&m_jacLinear[i]) btJacobianEntry( - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*pivotInB - m_rbB.getCenterOfMassPosition(), - normalWorld, - m_rbA.getInvInertiaDiagLocal(), - m_rbA.getInvMass(), - m_rbB.getInvInertiaDiagLocal(), - m_rbB.getInvMass()); - - //optionally disable warmstarting -#ifdef GENERIC_D6_DISABLE_WARMSTARTING - m_accumulatedImpulse[i] = btScalar(0.); -#endif //GENERIC_D6_DISABLE_WARMSTARTING - - // Apply accumulated impulse - btVector3 impulse_vector = m_accumulatedImpulse[i] * normalWorld; - - m_rbA.applyImpulse( impulse_vector, rel_pos1); - m_rbB.applyImpulse(-impulse_vector, rel_pos2); - - localNormalInA[i] = 0; - } - } - - // angular part - for (i=0;i<3;i++) - { - if (isLimited(i+3)) - { - btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); - btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); - - // Dirk: This is IMO mathematically the correct way, but we should consider axisA and axisB being near parallel maybe - btVector3 axis = kSign[i] * axisA.cross(axisB); - - // Create angular atom - new (&m_jacAng[i]) btJacobianEntry(axis, - m_rbA.getCenterOfMassTransform().getBasis().transpose(), - m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getInvInertiaDiagLocal(), - m_rbB.getInvInertiaDiagLocal()); - -#ifdef GENERIC_D6_DISABLE_WARMSTARTING - m_accumulatedImpulse[i + 3] = btScalar(0.); -#endif //GENERIC_D6_DISABLE_WARMSTARTING - - // Apply accumulated impulse - btVector3 impulse_vector = m_accumulatedImpulse[i + 3] * axis; - - m_rbA.applyTorqueImpulse( impulse_vector); - m_rbB.applyTorqueImpulse(-impulse_vector); - } - } -} - -btScalar getMatrixElem(const btMatrix3x3& mat,int index) -{ - int row = index%3; - int col = index / 3; - return mat[row][col]; + int i = index%3; + int j = index/3; + return mat[i][j]; } ///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html -bool MatrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz); +bool matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz) { - // rot = cy*cz -cy*sz sy - // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx - // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +// // rot = cy*cz -cy*sz sy +// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx +// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy +// + + if (btGetMatrixElem(mat,2) < btScalar(1.0)) + { + if (btGetMatrixElem(mat,2) > btScalar(-1.0)) + { + xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8)); + xyz[1] = btAsin(btGetMatrixElem(mat,2)); + xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0)); + return true; + } + else + { + // WARNING. Not unique. XA - ZA = -atan2(r10,r11) + xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = -SIMD_HALF_PI; + xyz[2] = btScalar(0.0); + return false; + } + } + else + { + // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) + xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4)); + xyz[1] = SIMD_HALF_PI; + xyz[2] = 0.0; + + } -/// 0..8 - if (getMatrixElem(mat,2) < btScalar(1.0)) - { - if (getMatrixElem(mat,2) > btScalar(-1.0)) - { - xyz[0] = btAtan2(-getMatrixElem(mat,5),getMatrixElem(mat,8)); - xyz[1] = btAsin(getMatrixElem(mat,2)); - xyz[2] = btAtan2(-getMatrixElem(mat,1),getMatrixElem(mat,0)); - return true; - } - else - { - // WARNING. Not unique. XA - ZA = -atan2(r10,r11) - xyz[0] = -btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); - xyz[1] = -SIMD_HALF_PI; - xyz[2] = btScalar(0.0); - return false; - } - } - else - { - // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11) - xyz[0] = btAtan2(getMatrixElem(mat,3),getMatrixElem(mat,4)); - xyz[1] = SIMD_HALF_PI; - xyz[2] = 0.0; - - } - return false; } -void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) + +//////////////////////////// btRotationalLimitMotor //////////////////////////////////// + + +int btRotationalLimitMotor::testLimitValue(btScalar test_value) { - btScalar tau = btScalar(0.1); - btScalar damping = btScalar(1.0); - - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_frameInA.getOrigin(); - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_frameInB.getOrigin(); - - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 localNormalInA(0,0,0); - int i; - - // linear - for (i=0;i<3;i++) - { - if (isLimited(i)) - { - btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); - btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - localNormalInA.setValue(0,0,0); - localNormalInA[i] = 1; - btVector3 normalWorld = m_rbA.getCenterOfMassTransform().getBasis() * localNormalInA; - - btScalar jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); - - //velocity error (first order error) - btScalar rel_vel = m_jacLinear[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - - //positional error (zeroth order error) - btScalar depth = -(pivotAInW - pivotBInW).dot(normalWorld); - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - //handle the limits - if (m_lowerLimit[i] < m_upperLimit[i]) - { - { - if (depth > m_upperLimit[i]) - { - depth -= m_upperLimit[i]; - lo = btScalar(0.); - - } else - { - if (depth < m_lowerLimit[i]) - { - depth -= m_lowerLimit[i]; - hi = btScalar(0.); - } else - { - continue; - } - } - } - } - - btScalar normalImpulse= (tau*depth/timeStep - damping*rel_vel) * jacDiagABInv; - btScalar oldNormalImpulse = m_accumulatedImpulse[i]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[i] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[i] - oldNormalImpulse; - - btVector3 impulse_vector = normalWorld * normalImpulse; - m_rbA.applyImpulse( impulse_vector, rel_pos1); - m_rbB.applyImpulse(-impulse_vector, rel_pos2); - - localNormalInA[i] = 0; - } - } - - btVector3 axis; - btScalar angle; - btTransform frameAWorld = m_rbA.getCenterOfMassTransform() * m_frameInA; - btTransform frameBWorld = m_rbB.getCenterOfMassTransform() * m_frameInB; - - btTransformUtil::calculateDiffAxisAngle(frameAWorld,frameBWorld,axis,angle); - btQuaternion diff(axis,angle); - btMatrix3x3 diffMat (diff); - btVector3 xyz; - ///this is not perfect, we can first check which axis are limited, and choose a more appropriate order - MatrixToEulerXYZ(diffMat,xyz); - - // angular - for (i=0;i<3;i++) + if(m_loLimit>m_hiLimit) { - if (isLimited(i+3)) - { - btVector3 angvelA = m_rbA.getCenterOfMassTransform().getBasis().transpose() * m_rbA.getAngularVelocity(); - btVector3 angvelB = m_rbB.getCenterOfMassTransform().getBasis().transpose() * m_rbB.getAngularVelocity(); - - btScalar jacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); - - //velocity error (first order error) - btScalar rel_vel = m_jacAng[i].getRelativeVelocity(m_rbA.getLinearVelocity(),angvelA, - m_rbB.getLinearVelocity(),angvelB); - - //positional error (zeroth order error) - btVector3 axisA = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn( kAxisA[i] ); - btVector3 axisB = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn( kAxisB[i] ); - - btScalar rel_pos = kSign[i] * axisA.dot(axisB); - - btScalar lo = btScalar(-1e30); - btScalar hi = btScalar(1e30); - - //handle the twist limit - if (m_lowerLimit[i+3] < m_upperLimit[i+3]) - { - //clamp the values - btScalar loLimit = m_lowerLimit[i+3] > -3.1415 ? m_lowerLimit[i+3] : btScalar(-1e30); - btScalar hiLimit = m_upperLimit[i+3] < 3.1415 ? m_upperLimit[i+3] : btScalar(1e30); - - btScalar projAngle = btScalar(-1.)*xyz[i]; - - if (projAngle < loLimit) - { - hi = btScalar(0.); - rel_pos = (loLimit - projAngle); - } else - { - if (projAngle > hiLimit) - { - lo = btScalar(0.); - rel_pos = (hiLimit - projAngle); - } else - { - continue; - } - } - } - - //impulse - - btScalar normalImpulse= -(tau*rel_pos/timeStep + damping*rel_vel) * jacDiagABInv; - btScalar oldNormalImpulse = m_accumulatedImpulse[i+3]; - btScalar sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[i+3] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; - normalImpulse = m_accumulatedImpulse[i+3] - oldNormalImpulse; - - // Dirk: Not needed - we could actually project onto Jacobian entry here (same as above) - btVector3 axis = kSign[i] * axisA.cross(axisB); - btVector3 impulse_vector = axis * normalImpulse; - - m_rbA.applyTorqueImpulse( impulse_vector); - m_rbB.applyTorqueImpulse(-impulse_vector); - } + m_currentLimit = 0;//Free from violation + return 0; } + + if (test_value < m_loLimit) + { + m_currentLimit = 1;//low limit violation + m_currentLimitError = test_value - m_loLimit; + return 1; + } + else if (test_value> m_hiLimit) + { + m_currentLimit = 2;//High limit violation + m_currentLimitError = test_value - m_hiLimit; + return 2; + }; + + m_currentLimit = 0;//Free from violation + return 0; + +} + + +btScalar btRotationalLimitMotor::solveAngularLimits( + btScalar timeStep,btVector3& axis,btScalar jacDiagABInv, + btRigidBody * body0, btRigidBody * body1) +{ + if (needApplyTorques()==false) return 0.0f; + + btScalar target_velocity = m_targetVelocity; + btScalar maxMotorForce = m_maxMotorForce; + + //current error correction + if (m_currentLimit!=0) + { + target_velocity = -m_ERP*m_currentLimitError/(timeStep); + maxMotorForce = m_maxLimitForce; + } + + maxMotorForce *= timeStep; + + // current velocity difference + btVector3 vel_diff = body0->getAngularVelocity(); + if (body1) + { + vel_diff -= body1->getAngularVelocity(); + } + + + + btScalar rel_vel = axis.dot(vel_diff); + + // correction velocity + btScalar motor_relvel = m_limitSoftness*(target_velocity - m_damping*rel_vel); + + + if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON ) + { + return 0.0f;//no need for applying force + } + + + // correction impulse + btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv; + + // clip correction impulse + btScalar clippedMotorImpulse; + + //todo: should clip against accumulated impulse + if (unclippedMotorImpulse>0.0f) + { + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse; + } + else + { + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse; + } + + + // sort with accumulated impulses + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + btScalar oldaccumImpulse = m_accumulatedImpulse; + btScalar sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + + + btVector3 motorImp = clippedMotorImpulse * axis; + + + body0->applyTorqueImpulse(motorImp); + if (body1) body1->applyTorqueImpulse(-motorImp); + + return clippedMotorImpulse; + + +} + +//////////////////////////// End btRotationalLimitMotor //////////////////////////////////// + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// +btScalar btTranslationalLimitMotor::solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos) +{ + +///find relative velocity +// btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition(); +// btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition(); + btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition(); + btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition(); + + btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + + btScalar rel_vel = axis_normal_on_a.dot(vel); + + + +/// apply displacement correction + +//positional error (zeroth order error) + btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a); + btScalar lo = btScalar(-1e30); + btScalar hi = btScalar(1e30); + + btScalar minLimit = m_lowerLimit[limit_index]; + btScalar maxLimit = m_upperLimit[limit_index]; + + //handle the limits + if (minLimit < maxLimit) + { + { + if (depth > maxLimit) + { + depth -= maxLimit; + lo = btScalar(0.); + + } + else + { + if (depth < minLimit) + { + depth -= minLimit; + hi = btScalar(0.); + } + else + { + return 0.0f; + } + } + } + } + + btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv; + + + + + btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index]; + btScalar sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum; + normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; + + btVector3 impulse_vector = axis_normal_on_a * normalImpulse; + body1.applyImpulse( impulse_vector, rel_pos1); + body2.applyImpulse(-impulse_vector, rel_pos2); + return normalImpulse; +} + +//////////////////////////// btTranslationalLimitMotor //////////////////////////////////// + + +btGeneric6DofConstraint::btGeneric6DofConstraint() + :btTypedConstraint(D6_CONSTRAINT_TYPE), + m_useLinearReferenceFrameA(true) +{ +} + +btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB) + , m_frameInA(frameInA) + , m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + +} + + + + + +void btGeneric6DofConstraint::calculateAngleInfo() +{ + btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis(); + + matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff); + + + + // in euler angle mode we do not actually constrain the angular velocity + // along the axes axis[0] and axis[2] (although we do use axis[1]) : + // + // to get constrain w2-w1 along ...not + // ------ --------------------- ------ + // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] + // d(angle[1])/dt = 0 ax[1] + // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] + // + // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. + // to prove the result for angle[0], write the expression for angle[0] from + // GetInfo1 then take the derivative. to prove this for angle[2] it is + // easier to take the euler rate expression for d(angle[2])/dt with respect + // to the components of w and set that to 0. + + btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0); + btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2); + + m_calculatedAxis[1] = axis2.cross(axis0); + m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); + m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); + + +// if(m_debugDrawer) +// { +// +// char buff[300]; +// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", +// m_calculatedAxisAngleDiff[0], +// m_calculatedAxisAngleDiff[1], +// m_calculatedAxisAngleDiff[2]); +// m_debugDrawer->reportErrorWarning(buff); +// } + +} + +void btGeneric6DofConstraint::calculateTransforms() +{ + m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + + calculateAngleInfo(); +} + + +void btGeneric6DofConstraint::buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW) +{ + new (&jacLinear) btJacobianEntry( + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normalWorld, + m_rbA.getInvInertiaDiagLocal(), + m_rbA.getInvMass(), + m_rbB.getInvInertiaDiagLocal(), + m_rbB.getInvMass()); + +} + +void btGeneric6DofConstraint::buildAngularJacobian( + btJacobianEntry & jacAngular,const btVector3 & jointAxisW) +{ + new (&jacAngular) btJacobianEntry(jointAxisW, + m_rbA.getCenterOfMassTransform().getBasis().transpose(), + m_rbB.getCenterOfMassTransform().getBasis().transpose(), + m_rbA.getInvInertiaDiagLocal(), + m_rbB.getInvInertiaDiagLocal()); + +} + +bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index) +{ + btScalar angle = m_calculatedAxisAngleDiff[axis_index]; + + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); +} + +void btGeneric6DofConstraint::buildJacobian() +{ + + // Clear accumulated impulses for the next simulation step + m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.)); + int i; + for(i = 0; i < 3; i++) + { + m_angularLimits[i].m_accumulatedImpulse = btScalar(0.); + } + //calculates transform + calculateTransforms(); + +// const btVector3& pivotAInW = m_calculatedTransformA.getOrigin(); +// const btVector3& pivotBInW = m_calculatedTransformB.getOrigin(); + calcAnchorPos(); + btVector3 pivotAInW = m_AnchorPos; + btVector3 pivotBInW = m_AnchorPos; + +// not used here +// btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); +// btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 normalWorld; + //linear part + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + if (m_useLinearReferenceFrameA) + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + else + normalWorld = m_calculatedTransformB.getBasis().getColumn(i); + + buildLinearJacobian( + m_jacLinear[i],normalWorld , + pivotAInW,pivotBInW); + + } + } + + // angular part + for (i=0;i<3;i++) + { + //calculates error angle + if (testAngularLimitMotor(i)) + { + normalWorld = this->getAxis(i); + // Create angular atom + buildAngularJacobian(m_jacAng[i],normalWorld); + } + } + + +} + + +void btGeneric6DofConstraint::solveConstraint(btScalar timeStep) +{ + m_timeStep = timeStep; + + //calculateTransforms(); + + int i; + + // linear + + btVector3 pointInA = m_calculatedTransformA.getOrigin(); + btVector3 pointInB = m_calculatedTransformB.getOrigin(); + + btScalar jacDiagABInv; + btVector3 linear_axis; + for (i=0;i<3;i++) + { + if (m_linearLimits.isLimited(i)) + { + jacDiagABInv = btScalar(1.) / m_jacLinear[i].getDiagonal(); + + if (m_useLinearReferenceFrameA) + linear_axis = m_calculatedTransformA.getBasis().getColumn(i); + else + linear_axis = m_calculatedTransformB.getBasis().getColumn(i); + + m_linearLimits.solveLinearAxis( + m_timeStep, + jacDiagABInv, + m_rbA,pointInA, + m_rbB,pointInB, + i,linear_axis, m_AnchorPos); + + } + } + + // angular + btVector3 angular_axis; + btScalar angularJacDiagABInv; + for (i=0;i<3;i++) + { + if (m_angularLimits[i].needApplyTorques()) + { + + // get axis + angular_axis = getAxis(i); + + angularJacDiagABInv = btScalar(1.) / m_jacAng[i].getDiagonal(); + + m_angularLimits[i].solveAngularLimits(m_timeStep,angular_axis,angularJacDiagABInv, &m_rbA,&m_rbB); + } + } } void btGeneric6DofConstraint::updateRHS(btScalar timeStep) { - (void)timeStep; + (void)timeStep; } -btScalar btGeneric6DofConstraint::computeAngle(int axis) const +btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const +{ + return m_calculatedAxis[axis_index]; +} + +btScalar btGeneric6DofConstraint::getAngle(int axis_index) const +{ + return m_calculatedAxisAngleDiff[axis_index]; +} + +void btGeneric6DofConstraint::calcAnchorPos(void) +{ + btScalar imA = m_rbA.getInvMass(); + btScalar imB = m_rbB.getInvMass(); + btScalar weight; + if(imB == btScalar(0.0)) { - btScalar angle = btScalar(0.f); - - switch (axis) - { - case 0: - { - btVector3 v1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(1); - btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); - btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); - - btScalar s = v1.dot(w2); - btScalar c = v1.dot(v2); - - angle = btAtan2( s, c ); - } - break; - - case 1: - { - btVector3 w1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(2); - btVector3 w2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(2); - btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); - - btScalar s = w1.dot(u2); - btScalar c = w1.dot(w2); - - angle = btAtan2( s, c ); - } - break; - - case 2: - { - btVector3 u1 = m_rbA.getCenterOfMassTransform().getBasis() * m_frameInA.getBasis().getColumn(0); - btVector3 u2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(0); - btVector3 v2 = m_rbB.getCenterOfMassTransform().getBasis() * m_frameInB.getBasis().getColumn(1); - - btScalar s = u1.dot(v2); - btScalar c = u1.dot(u2); - - angle = btAtan2( s, c ); - } - break; - default: - btAssert ( 0 ) ; - - break ; - } - - return angle; + weight = btScalar(1.0); } + else + { + weight = imA / (imA + imB); + } + const btVector3& pA = m_calculatedTransformA.getOrigin(); + const btVector3& pB = m_calculatedTransformB.getOrigin(); + m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight); + return; +} // btGeneric6DofConstraint::calcAnchorPos() diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h index b114e54fa69..f0718d2d4a0 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h @@ -4,116 +4,433 @@ Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +/* +2007-09-09 +btGeneric6DofConstraint Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + #ifndef GENERIC_6DOF_CONSTRAINT_H #define GENERIC_6DOF_CONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; +//! Rotation Limit structure for generic joints +class btRotationalLimitMotor +{ +public: + //! limit_parameters + //!@{ + btScalar m_loLimit;//!< joint limit + btScalar m_hiLimit;//!< joint limit + btScalar m_targetVelocity;//!< target motor velocity + btScalar m_maxMotorForce;//!< max force on motor + btScalar m_maxLimitForce;//!< max force on limit + btScalar m_damping;//!< Damping. + btScalar m_limitSoftness;//! Relaxation factor + btScalar m_ERP;//!< Error tolerance factor when joint is at limit + btScalar m_bounce;//!< restitution factor + bool m_enableMotor; + + //!@} + + //! temp_variables + //!@{ + btScalar m_currentLimitError;//! How much is violated this limit + int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit + btScalar m_accumulatedImpulse; + //!@} + + btRotationalLimitMotor() + { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 0.1f; + m_maxLimitForce = 300.0f; + m_loLimit = -SIMD_INFINITY; + m_hiLimit = SIMD_INFINITY; + m_ERP = 0.5f; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + } + + btRotationalLimitMotor(const btRotationalLimitMotor & limot) + { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_ERP = limot.m_ERP; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } + + + + //! Is limited + bool isLimited() + { + if(m_loLimit>=m_hiLimit) return false; + return true; + } + + //! Need apply correction + bool needApplyTorques() + { + if(m_currentLimit == 0 && m_enableMotor == false) return false; + return true; + } + + //! calculates error + /*! + calculates m_currentLimit and m_currentLimitError. + */ + int testLimitValue(btScalar test_value); + + //! apply the correction impulses for two bodies + btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1); + + +}; + + + +class btTranslationalLimitMotor +{ +public: + btVector3 m_lowerLimit;//!< the constraint lower limits + btVector3 m_upperLimit;//!< the constraint upper limits + btVector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + btScalar m_limitSoftness;//!< Softness for linear limit + btScalar m_damping;//!< Damping for linear limit + btScalar m_restitution;//! Bounce parameter for linear limit + //!@} + + btTranslationalLimitMotor() + { + m_lowerLimit.setValue(0.f,0.f,0.f); + m_upperLimit.setValue(0.f,0.f,0.f); + m_accumulatedImpulse.setValue(0.f,0.f,0.f); + + m_limitSoftness = 0.7f; + m_damping = btScalar(1.0f); + m_restitution = btScalar(0.5f); + } + + btTranslationalLimitMotor(const btTranslationalLimitMotor & other ) + { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; + + m_limitSoftness = other.m_limitSoftness ; + m_damping = other.m_damping; + m_restitution = other.m_restitution; + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + inline bool isLimited(int limitIndex) + { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + + + btScalar solveLinearAxis( + btScalar timeStep, + btScalar jacDiagABInv, + btRigidBody& body1,const btVector3 &pointInA, + btRigidBody& body2,const btVector3 &pointInB, + int limit_index, + const btVector3 & axis_normal_on_a, + const btVector3 & anchorPos); + + +}; /// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space -/// btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked' -/// Work in progress (is still a Hinge actually) +/*! +btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'. +currently this limit supports rotational motors
+
    +
  • For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method. +At this moment translational motors are not supported. May be in the future.
  • + +
  • For Angular limits, use the btRotationalLimitMotor structure for configuring the limit. +This is accessible through btGeneric6DofConstraint.getLimitMotor method, +This brings support for limit parameters and motors.
  • + +
  • Angulars limits have these possible ranges: + +AXIS + + + + + + + + + + + + +
    MIN ANGLEMAX ANGLEX-PIPIY-PI/2PI/2Z-PI/2PI/2
    +
  • +
+ +*/ class btGeneric6DofConstraint : public btTypedConstraint { - btJacobianEntry m_jacLinear[3]; // 3 orthogonal linear constraints - btJacobianEntry m_jacAng[3]; // 3 orthogonal angular constraints +protected: - btTransform m_frameInA; // the constraint space w.r.t body A - btTransform m_frameInB; // the constraint space w.r.t body B + //! relative_frames + //!@{ + btTransform m_frameInA;//!< the constraint space w.r.t body A + btTransform m_frameInB;//!< the constraint space w.r.t body B + //!@} + + //! Jacobians + //!@{ + btJacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints + btJacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints + //!@} + + //! Linear_Limit_parameters + //!@{ + btTranslationalLimitMotor m_linearLimits; + //!@} + + + //! hinge_parameters + //!@{ + btRotationalLimitMotor m_angularLimits[3]; + //!@} + + +protected: + //! temporal variables + //!@{ + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + btVector3 m_calculatedAxisAngleDiff; + btVector3 m_calculatedAxis[3]; + + btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes + + bool m_useLinearReferenceFrameA; + + //!@} + + btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) + { + btAssert(0); + (void) other; + return *this; + } + + + + void buildLinearJacobian( + btJacobianEntry & jacLinear,const btVector3 & normalWorld, + const btVector3 & pivotAInW,const btVector3 & pivotBInW); + + void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW); + + + //! calcs the euler angles between the two bodies. + void calculateAngleInfo(); - btScalar m_lowerLimit[6]; // the constraint lower limits - btScalar m_upperLimit[6]; // the constraint upper limits - btScalar m_accumulatedImpulse[6]; - btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other) - { - btAssert(0); - (void) other; - return *this; - } - public: - btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ); + btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); - btGeneric6DofConstraint(); + btGeneric6DofConstraint(); - - virtual void buildJacobian(); + //! Calcs global transform of the offsets + /*! + Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. + \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo + */ + void calculateTransforms(); - virtual void solveConstraint(btScalar timeStep); + //! Gets the global transform of the offset for body A + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformA() const + { + return m_calculatedTransformA; + } - void updateRHS(btScalar timeStep); + //! Gets the global transform of the offset for body B + /*! + \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo. + */ + const btTransform & getCalculatedTransformB() const + { + return m_calculatedTransformB; + } - btScalar computeAngle(int axis) const; + const btTransform & getFrameOffsetA() const + { + return m_frameInA; + } - void setLinearLowerLimit(const btVector3& linearLower) - { - m_lowerLimit[0] = linearLower.getX(); - m_lowerLimit[1] = linearLower.getY(); - m_lowerLimit[2] = linearLower.getZ(); - } + const btTransform & getFrameOffsetB() const + { + return m_frameInB; + } - void setLinearUpperLimit(const btVector3& linearUpper) - { - m_upperLimit[0] = linearUpper.getX(); - m_upperLimit[1] = linearUpper.getY(); - m_upperLimit[2] = linearUpper.getZ(); - } - void setAngularLowerLimit(const btVector3& angularLower) - { - m_lowerLimit[3] = angularLower.getX(); - m_lowerLimit[4] = angularLower.getY(); - m_lowerLimit[5] = angularLower.getZ(); - } + btTransform & getFrameOffsetA() + { + return m_frameInA; + } - void setAngularUpperLimit(const btVector3& angularUpper) - { - m_upperLimit[3] = angularUpper.getX(); - m_upperLimit[4] = angularUpper.getY(); - m_upperLimit[5] = angularUpper.getZ(); - } + btTransform & getFrameOffsetB() + { + return m_frameInB; + } - //first 3 are linear, next 3 are angular - void SetLimit(int axis, btScalar lo, btScalar hi) - { - m_lowerLimit[axis] = lo; - m_upperLimit[axis] = hi; - } - //free means upper < lower, - //locked means upper == lower - //limited means upper > lower - //limitIndex: first 3 are linear, next 3 are angular - bool isLimited(int limitIndex) - { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } + //! performs Jacobian calculation, and also calculates angle differences and axis + virtual void buildJacobian(); - const btRigidBody& getRigidBodyA() const - { - return m_rbA; - } - const btRigidBody& getRigidBodyB() const - { - return m_rbB; - } - + virtual void solveConstraint(btScalar timeStep); + + void updateRHS(btScalar timeStep); + + //! Get the rotation axis in global coordinates + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btVector3 getAxis(int axis_index) const; + + //! Get the relative Euler angle + /*! + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + btScalar getAngle(int axis_index) const; + + //! Test angular limit. + /*! + Calculates angular correction and returns true if limit needs to be corrected. + \pre btGeneric6DofConstraint.buildJacobian must be called previously. + */ + bool testAngularLimitMotor(int axis_index); + + void setLinearLowerLimit(const btVector3& linearLower) + { + m_linearLimits.m_lowerLimit = linearLower; + } + + void setLinearUpperLimit(const btVector3& linearUpper) + { + m_linearLimits.m_upperLimit = linearUpper; + } + + void setAngularLowerLimit(const btVector3& angularLower) + { + m_angularLimits[0].m_loLimit = angularLower.getX(); + m_angularLimits[1].m_loLimit = angularLower.getY(); + m_angularLimits[2].m_loLimit = angularLower.getZ(); + } + + void setAngularUpperLimit(const btVector3& angularUpper) + { + m_angularLimits[0].m_hiLimit = angularUpper.getX(); + m_angularLimits[1].m_hiLimit = angularUpper.getY(); + m_angularLimits[2].m_hiLimit = angularUpper.getZ(); + } + + //! Retrieves the angular limit informacion + btRotationalLimitMotor * getRotationalLimitMotor(int index) + { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + btTranslationalLimitMotor * getTranslationalLimitMotor() + { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, btScalar lo, btScalar hi) + { + if(axis<3) + { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } + else + { + m_angularLimits[axis-3].m_loLimit = lo; + m_angularLimits[axis-3].m_hiLimit = hi; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + bool isLimited(int limitIndex) + { + if(limitIndex<3) + { + return m_linearLimits.isLimited(limitIndex); + + } + return m_angularLimits[limitIndex-3].isLimited(); + } + + const btRigidBody& getRigidBodyA() const + { + return m_rbA; + } + const btRigidBody& getRigidBodyB() const + { + return m_rbB; + } + + virtual void calcAnchorPos(void); // overridable }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index 27e30987549..a0523a8c76b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -17,58 +17,185 @@ subject to the following restrictions: #include "btHingeConstraint.h" #include "BulletDynamics/Dynamics/btRigidBody.h" #include "LinearMath/btTransformUtil.h" +#include "LinearMath/btMinMax.h" #include -btHingeConstraint::btHingeConstraint(): + +btHingeConstraint::btHingeConstraint() +: btTypedConstraint (HINGE_CONSTRAINT_TYPE), m_enableAngularMotor(false) { } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, - btVector3& axisInA,btVector3& axisInB) -:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB), -m_axisInA(axisInA), -m_axisInB(-axisInB), -m_angularOnly(false), -m_enableAngularMotor(false) + btVector3& axisInA,btVector3& axisInB) + :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB), + m_angularOnly(false), + m_enableAngularMotor(false) { + m_rbAFrame.getOrigin() = pivotInA; + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + + btVector3 rbAxisA2; + btScalar projection = axisInA.dot(rbAxisA1); + if (projection >= 1.0f - SIMD_EPSILON) { + rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else if (projection <= -1.0f + SIMD_EPSILON) { + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2); + rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + } else { + rbAxisA2 = axisInA.cross(rbAxisA1); + rbAxisA1 = rbAxisA2.cross(axisInA); + } + + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.getOrigin() = pivotInB; + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),-axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),-axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),-axisInB.getZ() ); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; } btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA) -:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), -m_axisInA(axisInA), -//fixed axis in worldspace -m_axisInB(rbA.getCenterOfMassTransform().getBasis() * -axisInA), +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false) +{ + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + // fixed axis in worldspace + btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0); + btScalar projection = rbAxisA1.dot(axisInA); + if (projection > SIMD_EPSILON) + rbAxisA1 = rbAxisA1*projection - axisInA; + else + rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(1); + + btVector3 rbAxisA2 = axisInA.cross(rbAxisA1); + + m_rbAFrame.getOrigin() = pivotInA; + m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(), + rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(), + rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() ); + + + btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA; + + btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB); + btVector3 rbAxisB1 = quatRotate(rotationArc,rbAxisA1); + btVector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + + m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA); + m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(), + rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(), + rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() ); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +} + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, + const btTransform& rbAFrame, const btTransform& rbBFrame) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame), m_angularOnly(false), m_enableAngularMotor(false) { - + // flip axis + m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; +} + + + +btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame) +:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame), +m_angularOnly(false), +m_enableAngularMotor(false) +{ + ///not providing rigidbody B means implicitly using worldspace for body B + + // flip axis + m_rbBFrame.getBasis()[0][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[1][2] *= btScalar(-1.); + m_rbBFrame.getBasis()[2][2] *= btScalar(-1.); + + m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin()); + + //start with free + m_lowerLimit = btScalar(1e30); + m_upperLimit = btScalar(-1e30); + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; } void btHingeConstraint::buildJacobian() { m_appliedImpulse = btScalar(0.); - btVector3 normal(0,0,0); - if (!m_angularOnly) { + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); + btVector3 relPos = pivotBInW - pivotAInW; + + btVector3 normal[3]; + if (relPos.length2() > SIMD_EPSILON) + { + normal[0] = relPos.normalized(); + } + else + { + normal[0].setValue(btScalar(1.0),0,0); + } + + btPlaneSpace1(normal[0], normal[1], normal[2]); + for (int i=0;i<3;i++) { - normal[i] = 1; new (&m_jac[i]) btJacobianEntry( m_rbA.getCenterOfMassTransform().getBasis().transpose(), m_rbB.getCenterOfMassTransform().getBasis().transpose(), - m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(), - m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(), - normal, + pivotAInW - m_rbA.getCenterOfMassPosition(), + pivotBInW - m_rbB.getCenterOfMassPosition(), + normal[i], m_rbA.getInvInertiaDiagLocal(), m_rbA.getInvMass(), m_rbB.getInvInertiaDiagLocal(), m_rbB.getInvMass()); - normal[i] = 0; } } @@ -79,12 +206,12 @@ void btHingeConstraint::buildJacobian() btVector3 jointAxis0local; btVector3 jointAxis1local; - btPlaneSpace1(m_axisInA,jointAxis0local,jointAxis1local); + btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local); - getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local; btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local; - btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; + btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); new (&m_jacAng[0]) btJacobianEntry(jointAxis0, m_rbA.getCenterOfMassTransform().getBasis().transpose(), @@ -105,44 +232,73 @@ void btHingeConstraint::buildJacobian() m_rbB.getInvInertiaDiagLocal()); + // Compute limit information + btScalar hingeAngle = getHingeAngle(); + + //set bias, sign, clear accumulator + m_correction = btScalar(0.); + m_limitSign = btScalar(0.); + m_solveLimit = false; + m_accLimitImpulse = btScalar(0.); + +// if (m_lowerLimit < m_upperLimit) + if (m_lowerLimit <= m_upperLimit) + { +// if (hingeAngle <= m_lowerLimit*m_limitSoftness) + if (hingeAngle <= m_lowerLimit) + { + m_correction = (m_lowerLimit - hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } +// else if (hingeAngle >= m_upperLimit*m_limitSoftness) + else if (hingeAngle >= m_upperLimit) + { + m_correction = m_upperLimit - hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } + + //Compute K = J*W*J' for hinge axis + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) + + getRigidBodyB().computeAngularImpulseDenominator(axisA)); } void btHingeConstraint::solveConstraint(btScalar timeStep) { - btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_pivotInA; - btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_pivotInB; + btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin(); + btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin(); - btVector3 normal(0,0,0); btScalar tau = btScalar(0.3); - btScalar damping = btScalar(1.); -//linear part + //linear part if (!m_angularOnly) { + btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); + btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); + + btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); + btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); + btVector3 vel = vel1 - vel2; + for (int i=0;i<3;i++) { - normal[i] = 1; + const btVector3& normal = m_jac[i].m_linearJointAxis; btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal(); - btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); - btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition(); - - btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2); - btVector3 vel = vel1 - vel2; btScalar rel_vel; rel_vel = normal.dot(vel); //positional error (zeroth order error) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - btScalar impulse = depth*tau/timeStep * jacDiagABInv - damping * rel_vel * jacDiagABInv * damping; + btScalar impulse = depth*tau/timeStep * jacDiagABInv - rel_vel * jacDiagABInv; m_appliedImpulse += impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition()); - - normal[i] = 0; } } @@ -151,8 +307,8 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) ///solve angular part // get axes in world space - btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_axisInA; - btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_axisInB; + btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2); + btVector3 axisB = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(2); const btVector3& angVelA = getRigidBodyA().getAngularVelocity(); const btVector3& angVelB = getRigidBodyB().getAngularVelocity(); @@ -174,7 +330,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) getRigidBodyB().computeAngularImpulseDenominator(normal); // scale for mass and relaxation //todo: expose this 0.9 factor to developer - velrelOrthog *= (btScalar(1.)/denom) * btScalar(0.9); + velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor; } //solve angular positional correction @@ -190,10 +346,28 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) m_rbA.applyTorqueImpulse(-velrelOrthog+angularError); m_rbB.applyTorqueImpulse(velrelOrthog-angularError); + + // solve limit + if (m_solveLimit) + { + btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor ) * m_limitSign; + + btScalar impulseMag = amplitude * m_kHinge; + + // Clamp the accumulated impulse + btScalar temp = m_accLimitImpulse; + m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) ); + impulseMag = m_accLimitImpulse - temp; + + + btVector3 impulse = axisA * impulseMag * m_limitSign; + m_rbA.applyTorqueImpulse(impulse); + m_rbB.applyTorqueImpulse(-impulse); + } } //apply motor - if (m_enableAngularMotor) + if (m_enableAngularMotor) { //todo: add limits too btVector3 angularLimit(0,0,0); @@ -204,10 +378,7 @@ void btHingeConstraint::solveConstraint(btScalar timeStep) btScalar desiredMotorVel = m_motorTargetVelocity; btScalar motor_relvel = desiredMotorVel - projRelVel; - btScalar denom3 = getRigidBodyA().computeAngularImpulseDenominator(axisA) + - getRigidBodyB().computeAngularImpulseDenominator(axisA); - - btScalar unclippedMotorImpulse = (btScalar(1.)/denom3) * motor_relvel;; + btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;; //todo: should clip against accumulated impulse btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; @@ -227,3 +398,12 @@ void btHingeConstraint::updateRHS(btScalar timeStep) } +btScalar btHingeConstraint::getHingeAngle() +{ + const btVector3 refAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(0); + const btVector3 refAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1); + const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1); + + return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1) ); +} + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h index 5c1ceafbc5b..4fa9972f6d8 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.h @@ -13,39 +13,61 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */ + #ifndef HINGECONSTRAINT_H #define HINGECONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" class btRigidBody; - /// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space /// axis defines the orientation of the hinge axis class btHingeConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - btVector3 m_pivotInA; - btVector3 m_pivotInB; - btVector3 m_axisInA; - btVector3 m_axisInB; + btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + btTransform m_rbBFrame; + + btScalar m_motorTargetVelocity; + btScalar m_maxMotorImpulse; + + btScalar m_limitSoftness; + btScalar m_biasFactor; + btScalar m_relaxationFactor; + + btScalar m_lowerLimit; + btScalar m_upperLimit; + + btScalar m_kHinge; + + btScalar m_limitSign; + btScalar m_correction; + + btScalar m_accLimitImpulse; bool m_angularOnly; - - btScalar m_motorTargetVelocity; - btScalar m_maxMotorImpulse; bool m_enableAngularMotor; + bool m_solveLimit; + public: - btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,btVector3& axisInA,btVector3& axisInB); + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, btVector3& axisInA,btVector3& axisInB); btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA); + + btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame); + + btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame); btHingeConstraint(); @@ -76,6 +98,61 @@ public: m_maxMotorImpulse = maxMotorImpulse; } + void setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f) + { + m_lowerLimit = low; + m_upperLimit = high; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + + } + + btScalar getLowerLimit() const + { + return m_lowerLimit; + } + + btScalar getUpperLimit() const + { + return m_upperLimit; + } + + + btScalar getHingeAngle(); + + + const btTransform& getAFrame() { return m_rbAFrame; }; + const btTransform& getBFrame() { return m_rbBFrame; }; + + inline int getSolveLimit() + { + return m_solveLimit; + } + + inline btScalar getLimitSign() + { + return m_limitSign; + } + + inline bool getAngularOnly() + { + return m_angularOnly; + } + inline bool getEnableAngularMotor() + { + return m_enableAngularMotor; + } + inline btScalar getMotorTargetVelosity() + { + return m_motorTargetVelocity; + } + inline btScalar getMaxMotorImpulse() + { + return m_maxMotorImpulse; + } + }; #endif //HINGECONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h index aae3ed0373f..bfeb24c2dfb 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btJacobianEntry.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef JACOBIAN_ENTRY_H #define JACOBIAN_ENTRY_H -#include "../../LinearMath/btVector3.h" -#include "../Dynamics/btRigidBody.h" +#include "LinearMath/btVector3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" //notes: diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp index aacb0a3ea66..2b69ad90438 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp @@ -21,18 +21,19 @@ subject to the following restrictions: btPoint2PointConstraint::btPoint2PointConstraint() +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB) -:btTypedConstraint(rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB) { } btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA) -:btTypedConstraint(rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) +:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)) { } @@ -99,6 +100,16 @@ void btPoint2PointConstraint::solveConstraint(btScalar timeStep) btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal btScalar impulse = depth*m_setting.m_tau/timeStep * jacDiagABInv - m_setting.m_damping * rel_vel * jacDiagABInv; + + btScalar impulseClamp = m_setting.m_impulseClamp; + if (impulseClamp > 0) + { + if (impulse < -impulseClamp) + impulse = -impulseClamp; + if (impulse > impulseClamp) + impulse = impulseClamp; + } + m_appliedImpulse+=impulse; btVector3 impulse_vector = normal * impulse; m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition()); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h index 71da8ac0347..c9d5968530c 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h @@ -16,7 +16,7 @@ subject to the following restrictions: #ifndef POINT2POINTCONSTRAINT_H #define POINT2POINTCONSTRAINT_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" #include "btJacobianEntry.h" #include "btTypedConstraint.h" @@ -26,16 +26,21 @@ struct btConstraintSetting { btConstraintSetting() : m_tau(btScalar(0.3)), - m_damping(btScalar(1.)) + m_damping(btScalar(1.)), + m_impulseClamp(btScalar(0.)) { } btScalar m_tau; btScalar m_damping; + btScalar m_impulseClamp; }; /// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space class btPoint2PointConstraint : public btTypedConstraint { +#ifdef IN_PARALLELL_SOLVER +public: +#endif btJacobianEntry m_jac[3]; //3 orthogonal linear constraints btVector3 m_pivotInA; @@ -70,6 +75,15 @@ public: m_pivotInB = pivotB; } + const btVector3& getPivotInA() const + { + return m_pivotInA; + } + + const btVector3& getPivotInB() const + { + return m_pivotInB; + } }; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp index 14b36ad44fd..b8afbd6aac5 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp @@ -13,6 +13,9 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ +//#define COMPUTE_IMPULSE_DENOM 1 +//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms. +//#define FORCE_REFESH_CONTACT_MANIFOLDS 1 #include "btSequentialImpulseConstraintSolver.h" #include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" @@ -30,11 +33,9 @@ subject to the following restrictions: #include "btSolverBody.h" #include "btSolverConstraint.h" + #include "LinearMath/btAlignedObjectArray.h" -#ifdef USE_PROFILE -#include "LinearMath/btQuickprof.h" -#endif //USE_PROFILE int totalCpd = 0; @@ -64,7 +65,7 @@ unsigned long btSequentialImpulseConstraintSolver::btRand2() int btSequentialImpulseConstraintSolver::btRandInt2 (int n) { // seems good; xor-fold and modulus - const unsigned long un = n; + const unsigned long un = static_cast(n); unsigned long r = btRand2(); // note: probably more aggressive than it needs to be -- might be @@ -91,12 +92,12 @@ int btSequentialImpulseConstraintSolver::btRandInt2 (int n) - +bool MyContactDestroyedCallback(void* userPersistentData); bool MyContactDestroyedCallback(void* userPersistentData) { assert (userPersistentData); btConstraintPersistentData* cpd = (btConstraintPersistentData*)userPersistentData; - delete cpd; + btAlignedFree(cpd); totalCpd--; //printf("totalCpd = %i. DELETED Ptr %x\n",totalCpd,userPersistentData); return true; @@ -105,8 +106,7 @@ bool MyContactDestroyedCallback(void* userPersistentData) btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver() -:m_solverMode(SOLVER_RANDMIZE_ORDER | SOLVER_CACHE_FRIENDLY), //not using SOLVER_USE_WARMSTARTING, -m_btSeed2(0) +:m_btSeed2(0) { gContactDestroyedCallback = &MyContactDestroyedCallback; @@ -121,27 +121,42 @@ m_btSeed2(0) } } - -void initSolverBody(btSolverBody* solverBody, btRigidBody* rigidbody) +btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver() { -/* int size = sizeof(btSolverBody); - int sizeofrb = sizeof(btRigidBody); - int sizemanifold = sizeof(btPersistentManifold); - int sizeofmp = sizeof(btManifoldPoint); - int sizeofPersistData = sizeof (btConstraintPersistentData); -*/ - solverBody->m_angularVelocity = rigidbody->getAngularVelocity(); - solverBody->m_centerOfMassPosition = rigidbody->getCenterOfMassPosition(); - solverBody->m_friction = rigidbody->getFriction(); -// solverBody->m_invInertiaWorld = rigidbody->getInvInertiaTensorWorld(); - solverBody->m_invMass = rigidbody->getInvMass(); - solverBody->m_linearVelocity = rigidbody->getLinearVelocity(); - solverBody->m_originalBody = rigidbody; - solverBody->m_angularFactor = rigidbody->getAngularFactor(); } -btScalar penetrationResolveFactor = btScalar(0.9); +void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject); +void initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject) +{ + btRigidBody* rb = btRigidBody::upcast(collisionObject); + if (rb) + { + solverBody->m_angularVelocity = rb->getAngularVelocity() ; + solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin(); + solverBody->m_friction = collisionObject->getFriction(); + solverBody->m_invMass = rb->getInvMass(); + solverBody->m_linearVelocity = rb->getLinearVelocity(); + solverBody->m_originalBody = rb; + solverBody->m_angularFactor = rb->getAngularFactor(); + } else + { + solverBody->m_angularVelocity.setValue(0,0,0); + solverBody->m_centerOfMassPosition = collisionObject->getWorldTransform().getOrigin(); + solverBody->m_friction = collisionObject->getFriction(); + solverBody->m_invMass = 0.f; + solverBody->m_linearVelocity.setValue(0,0,0); + solverBody->m_originalBody = 0; + solverBody->m_angularFactor = 1.f; + } + solverBody->m_pushVelocity.setValue(0.f,0.f,0.f); + solverBody->m_turnVelocity.setValue(0.f,0.f,0.f); +} + + +int gNumSplitImpulseRecoveries = 0; + +btScalar restitutionCurve(btScalar rel_vel, btScalar restitution); btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) { btScalar rest = restitution * -rel_vel; @@ -149,30 +164,95 @@ btScalar restitutionCurve(btScalar rel_vel, btScalar restitution) } +void resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo); + +//SIMD_FORCE_INLINE +void resolveSplitPenetrationImpulseCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo) +{ + (void)solverInfo; + + if (contactConstraint.m_penetration < solverInfo.m_splitImpulsePenetrationThreshold) + { + + gNumSplitImpulseRecoveries++; + btScalar normalImpulse; + + // Optimized version of projected relative velocity, use precomputed cross products with normal + // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + // btVector3 vel = vel1 - vel2; + // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); + + btScalar rel_vel; + btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_pushVelocity) + + contactConstraint.m_relpos1CrossNormal.dot(body1.m_turnVelocity); + btScalar vel2Dotn = contactConstraint.m_contactNormal.dot(body2.m_pushVelocity) + + contactConstraint.m_relpos2CrossNormal.dot(body2.m_turnVelocity); + + rel_vel = vel1Dotn-vel2Dotn; + btScalar positionalError = -contactConstraint.m_penetration * solverInfo.m_erp2/solverInfo.m_timeStep; + // btScalar positionalError = contactConstraint.m_penetration; + + btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; + + btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; + btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; + normalImpulse = penetrationImpulse+velocityImpulse; + + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse + btScalar oldNormalImpulse = contactConstraint.m_appliedPushImpulse; + btScalar sum = oldNormalImpulse + normalImpulse; + contactConstraint.m_appliedPushImpulse = btScalar(0.) > sum ? btScalar(0.): sum; + + normalImpulse = contactConstraint.m_appliedPushImpulse - oldNormalImpulse; + + body1.internalApplyPushImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); + + body2.internalApplyPushImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); + + } + +} //velocity + friction //response between two dynamic objects with friction -SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( + +btScalar resolveSingleCollisionCombinedCacheFriendly( btSolverBody& body1, btSolverBody& body2, - btSolverConstraint& contactConstraint, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo); + +//SIMD_FORCE_INLINE +btScalar resolveSingleCollisionCombinedCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo) { (void)solverInfo; - btScalar normalImpulse(0.f); - { - if (contactConstraint.m_penetration < 0.f) - return 0.f; + btScalar normalImpulse; - // Optimized version of projected relative velocity, use precomputed cross products with normal - // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); - // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); - // btVector3 vel = vel1 - vel2; - // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); + { + + + // Optimized version of projected relative velocity, use precomputed cross products with normal + // body1.getVelocityInLocalPoint(contactConstraint.m_rel_posA,vel1); + // body2.getVelocityInLocalPoint(contactConstraint.m_rel_posB,vel2); + // btVector3 vel = vel1 - vel2; + // btScalar rel_vel = contactConstraint.m_contactNormal.dot(vel); btScalar rel_vel; btScalar vel1Dotn = contactConstraint.m_contactNormal.dot(body1.m_linearVelocity) @@ -182,50 +262,51 @@ SIMD_FORCE_INLINE btScalar resolveSingleCollisionCombinedCacheFriendly( rel_vel = vel1Dotn-vel2Dotn; + btScalar positionalError = 0.f; + if (!solverInfo.m_splitImpulse || (contactConstraint.m_penetration > solverInfo.m_splitImpulsePenetrationThreshold)) + { + positionalError = -contactConstraint.m_penetration * solverInfo.m_erp/solverInfo.m_timeStep; + } - btScalar positionalError = contactConstraint.m_penetration; btScalar velocityError = contactConstraint.m_restitution - rel_vel;// * damping; btScalar penetrationImpulse = positionalError * contactConstraint.m_jacDiagABInv; btScalar velocityImpulse = velocityError * contactConstraint.m_jacDiagABInv; - btScalar normalImpulse = penetrationImpulse+velocityImpulse; + normalImpulse = penetrationImpulse+velocityImpulse; + // See Erin Catto's GDC 2006 paper: Clamp the accumulated impulse btScalar oldNormalImpulse = contactConstraint.m_appliedImpulse; btScalar sum = oldNormalImpulse + normalImpulse; contactConstraint.m_appliedImpulse = btScalar(0.) > sum ? btScalar(0.): sum; - btScalar oldVelocityImpulse = contactConstraint.m_appliedVelocityImpulse; - btScalar velocitySum = oldVelocityImpulse + velocityImpulse; - contactConstraint.m_appliedVelocityImpulse = btScalar(0.) > velocitySum ? btScalar(0.): velocitySum; - normalImpulse = contactConstraint.m_appliedImpulse - oldNormalImpulse; - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass, contactConstraint.m_angularComponentA,normalImpulse); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, + + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass, contactConstraint.m_angularComponentB,-normalImpulse); - } - } - - return normalImpulse; } #ifndef NO_FRICTION_TANGENTIALS -SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( +btScalar resolveSingleFrictionCacheFriendly( btSolverBody& body1, btSolverBody& body2, - btSolverConstraint& contactConstraint, + const btSolverConstraint& contactConstraint, + const btContactSolverInfo& solverInfo, + btScalar appliedNormalImpulse); + +//SIMD_FORCE_INLINE +btScalar resolveSingleFrictionCacheFriendly( + btSolverBody& body1, + btSolverBody& body2, + const btSolverConstraint& contactConstraint, const btContactSolverInfo& solverInfo, btScalar appliedNormalImpulse) { @@ -252,22 +333,42 @@ SIMD_FORCE_INLINE btScalar resolveSingleFrictionCacheFriendly( // calculate j that moves us to zero relative velocity j1 = -rel_vel * contactConstraint.m_jacDiagABInv; +#define CLAMP_ACCUMULATED_FRICTION_IMPULSE 1 +#ifdef CLAMP_ACCUMULATED_FRICTION_IMPULSE btScalar oldTangentImpulse = contactConstraint.m_appliedImpulse; contactConstraint.m_appliedImpulse = oldTangentImpulse + j1; - GEN_set_min(contactConstraint.m_appliedImpulse, limit); - GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + + if (limit < contactConstraint.m_appliedImpulse) + { + contactConstraint.m_appliedImpulse = limit; + } else + { + if (contactConstraint.m_appliedImpulse < -limit) + contactConstraint.m_appliedImpulse = -limit; + } j1 = contactConstraint.m_appliedImpulse - oldTangentImpulse; +#else + if (limit < j1) + { + j1 = limit; + } else + { + if (j1 < -limit) + j1 = -limit; + } + +#endif //CLAMP_ACCUMULATED_FRICTION_IMPULSE + + //GEN_set_min(contactConstraint.m_appliedImpulse, limit); + //GEN_set_max(contactConstraint.m_appliedImpulse, -limit); + + } - if (body1.m_invMass) - { - body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); - } - if (body2.m_invMass) - { - body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); - } + body1.internalApplyImpulse(contactConstraint.m_contactNormal*body1.m_invMass,contactConstraint.m_angularComponentA,j1); + + body2.internalApplyImpulse(contactConstraint.m_contactNormal*body2.m_invMass,contactConstraint.m_angularComponentB,-j1); } return 0.f; @@ -309,7 +410,6 @@ btScalar resolveSingleFrictionCacheFriendly( const btVector3& rel_pos2 = contactConstraint.m_rel_posB; - //if (contactConstraint.m_appliedVelocityImpulse > 0.f) if (lat_rel_vel > SIMD_EPSILON*SIMD_EPSILON) { lat_rel_vel = btSqrt(lat_rel_vel); @@ -319,7 +419,7 @@ btScalar resolveSingleFrictionCacheFriendly( btVector3 temp2 = body2.m_invInertiaWorld * rel_pos2.cross(lat_vel); btScalar friction_impulse = lat_rel_vel / (body1.m_invMass + body2.m_invMass + lat_vel.dot(temp1.cross(rel_pos1) + temp2.cross(rel_pos2))); - btScalar normal_impulse = contactConstraint.m_appliedVelocityImpulse * combinedFriction; + btScalar normal_impulse = contactConstraint.m_appliedImpulse * combinedFriction; GEN_set_min(friction_impulse, normal_impulse); GEN_set_max(friction_impulse, -normal_impulse); @@ -333,39 +433,111 @@ btScalar resolveSingleFrictionCacheFriendly( #endif //NO_FRICTION_TANGENTIALS -btAlignedObjectArray tmpSolverBodyPool; -btAlignedObjectArray tmpSolverConstraintPool; -btAlignedObjectArray tmpSolverFrictionConstraintPool; -btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) + + +void btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation) { + + btRigidBody* body0=btRigidBody::upcast(colObj0); + btRigidBody* body1=btRigidBody::upcast(colObj1); + + btSolverConstraint& solverConstraint = m_tmpSolverFrictionConstraintPool.expand(); + solverConstraint.m_contactNormal = normalAxis; + + solverConstraint.m_solverBodyIdA = solverBodyIdA; + solverConstraint.m_solverBodyIdB = solverBodyIdB; + solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; + solverConstraint.m_frictionIndex = frictionIndex; + + solverConstraint.m_friction = cp.m_combinedFriction; + solverConstraint.m_originalContactPoint = 0; + + solverConstraint.m_appliedImpulse = btScalar(0.); + solverConstraint.m_appliedPushImpulse = 0.f; + solverConstraint.m_penetration = 0.f; + { + btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0); + } + { + btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); + solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; + solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1 : btVector3(0,0,0); + } + +#ifdef COMPUTE_IMPULSE_DENOM + btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); + btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (body0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = body0->getInvMass() + normalAxis.dot(vec); + } + if (body1) + { + vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = body1->getInvMass() + normalAxis.dot(vec); + } + + +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); + solverConstraint.m_jacDiagABInv = denom; + + +} + + + +btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** /*bodies */,int /*numBodies */,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc) +{ + BT_PROFILE("solveGroupCacheFriendlySetup"); (void)stackAlloc; (void)debugDrawer; + if (!(numConstraints + numManifolds)) { // printf("empty\n"); return 0.f; } + btPersistentManifold* manifold = 0; + btCollisionObject* colObj0=0,*colObj1=0; + + //btRigidBody* rb0=0,*rb1=0; + + +#ifdef FORCE_REFESH_CONTACT_MANIFOLDS BEGIN_PROFILE("refreshManifolds"); int i; + + + for (i=0;igetBody0(); - btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); - + manifold = manifoldPtr[i]; + rb1 = (btRigidBody*)manifold->getBody1(); + rb0 = (btRigidBody*)manifold->getBody0(); + manifold->refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); } - + END_PROFILE("refreshManifolds"); +#endif //FORCE_REFESH_CONTACT_MANIFOLDS + + - BEGIN_PROFILE("gatherSolverData"); //int sizeofSB = sizeof(btSolverBody); //int sizeofSC = sizeof(btSolverConstraint); @@ -382,10 +554,12 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio //todo: use stack allocator for this temp memory - int minReservation = numManifolds*2; +// int minReservation = numManifolds*2; - tmpSolverBodyPool.reserve(minReservation); + //m_tmpSolverBodyPool.reserve(minReservation); + //don't convert all bodies, only the one we need so solver the constraints +/* { for (int i=0;igetIslandTag() >= 0)) { btAssert(rb->getCompanionId() < 0); - int solverBodyId = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); + int solverBodyId = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); initSolverBody(&solverBody,rb); rb->setCompanionId(solverBodyId); } } } - +*/ - tmpSolverConstraintPool.reserve(minReservation); - tmpSolverFrictionConstraintPool.reserve(minReservation); + //m_tmpSolverConstraintPool.reserve(minReservation); + //m_tmpSolverFrictionConstraintPool.reserve(minReservation); + { int i; for (i=0;igetBody0(); - btRigidBody* rb1 = (btRigidBody*)manifold->getBody1(); - + manifold = manifoldPtr[i]; + colObj0 = (btCollisionObject*)manifold->getBody0(); + colObj1 = (btCollisionObject*)manifold->getBody1(); int solverBodyIdA=-1; int solverBodyIdB=-1; @@ -422,61 +596,108 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio - if (rb0->getIslandTag() >= 0) + if (colObj0->getIslandTag() >= 0) { - solverBodyIdA = rb0->getCompanionId(); + if (colObj0->getCompanionId() >= 0) + { + //body has already been converted + solverBodyIdA = colObj0->getCompanionId(); + } else + { + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj0); + colObj0->setCompanionId(solverBodyIdA); + } } else { //create a static body - solverBodyIdA = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb0); + solverBodyIdA = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj0); } - if (rb1->getIslandTag() >= 0) + if (colObj1->getIslandTag() >= 0) { - solverBodyIdB = rb1->getCompanionId(); + if (colObj1->getCompanionId() >= 0) + { + solverBodyIdB = colObj1->getCompanionId(); + } else + { + solverBodyIdB = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj1); + colObj1->setCompanionId(solverBodyIdB); + } } else { //create a static body - solverBodyIdB = tmpSolverBodyPool.size(); - btSolverBody& solverBody = tmpSolverBodyPool.expand(); - initSolverBody(&solverBody,rb1); + solverBodyIdB = m_tmpSolverBodyPool.size(); + btSolverBody& solverBody = m_tmpSolverBodyPool.expand(); + initSolverBody(&solverBody,colObj1); } } + btVector3 rel_pos1; + btVector3 rel_pos2; + btScalar relaxation; + for (int j=0;jgetNumContacts();j++) { btManifoldPoint& cp = manifold->getContactPoint(j); - - int frictionIndex = tmpSolverConstraintPool.size(); - + if (cp.getDistance() <= btScalar(0.)) { const btVector3& pos1 = cp.getPositionWorldOnA(); const btVector3& pos2 = cp.getPositionWorldOnB(); - btVector3 rel_pos1 = pos1 - rb0->getCenterOfMassPosition(); - btVector3 rel_pos2 = pos2 - rb1->getCenterOfMassPosition(); + rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); + rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin(); - btScalar relaxation = 1.f; + relaxation = 1.f; + btScalar rel_vel; + btVector3 vel; + + int frictionIndex = m_tmpSolverConstraintPool.size(); { - btSolverConstraint& solverConstraint = tmpSolverConstraintPool.expand(); + btSolverConstraint& solverConstraint = m_tmpSolverConstraintPool.expand(); + btRigidBody* rb0 = btRigidBody::upcast(colObj0); + btRigidBody* rb1 = btRigidBody::upcast(colObj1); solverConstraint.m_solverBodyIdA = solverBodyIdA; solverConstraint.m_solverBodyIdB = solverBodyIdB; solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_CONTACT_1D; - + solverConstraint.m_originalContactPoint = &cp; + btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0 : btVector3(0,0,0); + btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); + solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*torqueAxis1 : btVector3(0,0,0); { - //can be optimized, the cross products are already calculated +#ifdef COMPUTE_IMPULSE_DENOM btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB); btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB); +#else + btVector3 vec; + btScalar denom0 = 0.f; + btScalar denom1 = 0.f; + if (rb0) + { + vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1); + denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } + if (rb1) + { + vec = ( solverConstraint.m_angularComponentB).cross(rel_pos2); + denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec); + } +#endif //COMPUTE_IMPULSE_DENOM + btScalar denom = relaxation/(denom0+denom1); solverConstraint.m_jacDiagABInv = denom; } @@ -486,121 +707,115 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(cp.m_normalWorldOnB); - btVector3 vel1 = rb0->getVelocityInLocalPoint(rel_pos1); - btVector3 vel2 = rb1->getVelocityInLocalPoint(rel_pos2); + btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0); + btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0); - btVector3 vel = vel1 - vel2; - btScalar rel_vel; + vel = vel1 - vel2; + rel_vel = cp.m_normalWorldOnB.dot(vel); + solverConstraint.m_penetration = btMin(cp.getDistance()+infoGlobal.m_linearSlop,btScalar(0.)); + //solverConstraint.m_penetration = cp.getDistance(); - solverConstraint.m_penetration = cp.getDistance();///btScalar(infoGlobal.m_numIterations); solverConstraint.m_friction = cp.m_combinedFriction; - btScalar rest = restitutionCurve(rel_vel, cp.m_combinedRestitution); - if (rest <= btScalar(0.)) + solverConstraint.m_restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution); + if (solverConstraint.m_restitution <= btScalar(0.)) { - rest = 0.f; + solverConstraint.m_restitution = 0.f; }; + btScalar penVel = -solverConstraint.m_penetration/infoGlobal.m_timeStep; - if (rest > penVel) - { - rest = btScalar(0.); - } - solverConstraint.m_restitution = rest; - solverConstraint.m_penetration *= -(infoGlobal.m_erp/infoGlobal.m_timeStep); - - solverConstraint.m_appliedImpulse = 0.f; - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*torqueAxis0; - btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB); - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*torqueAxis1; - } - - //create 2 '1d axis' constraints for 2 tangential friction directions - - //re-calculate friction direction every frame, todo: check if this is really needed - btVector3 frictionTangential0a, frictionTangential1b; - - btPlaneSpace1(cp.m_normalWorldOnB,frictionTangential0a,frictionTangential1b); - - { - btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = frictionTangential0a; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; + if (solverConstraint.m_restitution > penVel) { - btVector3 ftorqueAxis0 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis0; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis0; + solverConstraint.m_penetration = btScalar(0.); } + + + + ///warm starting (or zero if disabled) + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) { - btVector3 ftorqueAxis0 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis0; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis0; + solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor; + if (rb0) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass(),solverConstraint.m_angularComponentB,-solverConstraint.m_appliedImpulse); + } else + { + solverConstraint.m_appliedImpulse = 0.f; } - } - - - { - - btSolverConstraint& solverConstraint = tmpSolverFrictionConstraintPool.expand(); - solverConstraint.m_contactNormal = frictionTangential1b; - - solverConstraint.m_solverBodyIdA = solverBodyIdA; - solverConstraint.m_solverBodyIdB = solverBodyIdB; - solverConstraint.m_constraintType = btSolverConstraint::BT_SOLVER_FRICTION_1D; - solverConstraint.m_frictionIndex = frictionIndex; - - solverConstraint.m_friction = cp.m_combinedFriction; - - solverConstraint.m_appliedImpulse = btScalar(0.); - solverConstraint.m_appliedVelocityImpulse = 0.f; - - btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal); - btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal); - btScalar denom = relaxation/(denom0+denom1); - solverConstraint.m_jacDiagABInv = denom; + solverConstraint.m_appliedPushImpulse = 0.f; + + solverConstraint.m_frictionIndex = m_tmpSolverFrictionConstraintPool.size(); + if (!cp.m_lateralFrictionInitialized) { - btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos1CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentA = rb0->getInvInertiaTensorWorld()*ftorqueAxis1; + cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel; + btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2(); + if (lat_rel_vel > SIMD_EPSILON)//0.0f) + { + cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB); + cp.m_lateralFrictionDir2.normalize();//?? + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } else + { + //re-calculate friction direction every frame, todo: check if this is really needed + + btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2); + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); } + cp.m_lateralFrictionInitialized = true; + + } else { - btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal); - solverConstraint.m_relpos2CrossNormal = ftorqueAxis1; - solverConstraint.m_angularComponentB = rb1->getInvInertiaTensorWorld()*ftorqueAxis1; + addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation); + } + + { + btSolverConstraint& frictionConstraint1 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor; + if (rb0) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass(),frictionConstraint1.m_angularComponentB,-frictionConstraint1.m_appliedImpulse); + } else + { + frictionConstraint1.m_appliedImpulse = 0.f; } } + { + btSolverConstraint& frictionConstraint2 = m_tmpSolverFrictionConstraintPool[solverConstraint.m_frictionIndex+1]; + if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING) + { + frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor; + if (rb0) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse); + if (rb1) + m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB].internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),frictionConstraint2.m_angularComponentB,-frictionConstraint2.m_appliedImpulse); + } else + { + frictionConstraint2.m_appliedImpulse = 0.f; + } + } + } + } } } } } - END_PROFILE("gatherSolverData"); - - BEGIN_PROFILE("prepareConstraints"); - + btContactSolverInfo info = infoGlobal; { @@ -612,57 +827,60 @@ btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendly(btCollisio } } - btAlignedObjectArray gOrderTmpConstraintPool; - btAlignedObjectArray gOrderFrictionConstraintPool; + - int numConstraintPool = tmpSolverConstraintPool.size(); - int numFrictionPool = tmpSolverFrictionConstraintPool.size(); + int numConstraintPool = m_tmpSolverConstraintPool.size(); + int numFrictionPool = m_tmpSolverFrictionConstraintPool.size(); ///todo: use stack allocator for such temporarily memory, same for solver bodies/constraints - gOrderTmpConstraintPool.resize(numConstraintPool); - gOrderFrictionConstraintPool.resize(numFrictionPool); + m_orderTmpConstraintPool.resize(numConstraintPool); + m_orderFrictionConstraintPool.resize(numFrictionPool); { int i; for (i=0;igetRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].writebackVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].writebackVelocity(); } - constraint->solveConstraint(info.m_timeStep); + constraint->solveConstraint(infoGlobal.m_timeStep); if ((constraint->getRigidBodyA().getIslandTag() >= 0) && (constraint->getRigidBodyA().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyA().getCompanionId()].readVelocity(); } if ((constraint->getRigidBodyB().getIslandTag() >= 0) && (constraint->getRigidBodyB().getCompanionId() >= 0)) { - tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); + m_tmpSolverBodyPool[constraint->getRigidBodyB().getCompanionId()].readVelocity(); } } { - int numPoolConstraints = tmpSolverConstraintPool.size(); + int numPoolConstraints = m_tmpSolverConstraintPool.size(); for (j=0;jm_appliedImpulse = solveManifold.m_appliedImpulse; + pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse; + pt->m_appliedImpulseLateral1 = m_tmpSolverFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse; + + //do a callback here? + } - END_PROFILE("solveConstraints"); + if (infoGlobal.m_splitImpulse) + { + for ( i=0;igetBody0(), (btRigidBody*)manifold->getBody1(),manifold->getContactPoint(gOrder[j].m_pointIndex),info,iteration,debugDrawer); } + } } - END_PROFILE("solveConstraints"); - - -#ifdef USE_PROFILE - btProfiler::endBlock("solve"); -#endif //USE_PROFILE - @@ -878,13 +1140,14 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol //only necessary to refresh the manifold once (first iteration). The integration is done outside the loop { +#ifdef FORCE_REFESH_CONTACT_MANIFOLDS manifoldPtr->refreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform()); - +#endif //FORCE_REFESH_CONTACT_MANIFOLDS int numpoints = manifoldPtr->getNumContacts(); gTotalContactPoints += numpoints; - btVector3 color(0,1,0); + for (int i=0;igetContactPoint(i); @@ -925,7 +1188,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol } else { - cpd = new btConstraintPersistentData; + //todo: should this be in a pool? + void* mem = btAlignedAlloc(sizeof(btConstraintPersistentData),16); + cpd = new (mem)btConstraintPersistentData; assert(cpd); totalCpd ++; @@ -972,10 +1237,9 @@ void btSequentialImpulseConstraintSolver::prepareConstraints(btPersistentManifol cpd->m_penetration = btScalar(0.); } - btScalar relaxation = info.m_damping; - if (m_solverMode & SOLVER_USE_WARMSTARTING) + if (info.m_solverMode & SOLVER_USE_WARMSTARTING) { cpd->m_appliedImpulse *= relaxation; } else @@ -1060,16 +1324,12 @@ btScalar btSequentialImpulseConstraintSolver::solveCombinedContactFriction(btRig { - btVector3 color(0,1,0); + { if (cp.getDistance() <= btScalar(0.)) { - if (iter == 0) - { - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } + { @@ -1098,16 +1358,12 @@ btScalar btSequentialImpulseConstraintSolver::solve(btRigidBody* body0,btRigidBo { - btVector3 color(0,1,0); + { if (cp.getDistance() <= btScalar(0.)) { - if (iter == 0) - { - if (debugDrawer) - debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } + { @@ -1136,7 +1392,7 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b { - btVector3 color(0,1,0); + { if (cp.getDistance() <= btScalar(0.)) @@ -1156,3 +1412,11 @@ btScalar btSequentialImpulseConstraintSolver::solveFriction(btRigidBody* body0,b } return btScalar(0.); } + + +void btSequentialImpulseConstraintSolver::reset() +{ + m_btSeed2 = 0; +} + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h index 13e70c41be4..7143bc41991 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h @@ -19,7 +19,8 @@ subject to the following restrictions: #include "btConstraintSolver.h" class btIDebugDraw; #include "btContactConstraint.h" - +#include "btSolverBody.h" +#include "btSolverConstraint.h" /// btSequentialImpulseConstraintSolver uses a Propagation Method and Sequentially applies impulses @@ -29,29 +30,29 @@ class btIDebugDraw; class btSequentialImpulseConstraintSolver : public btConstraintSolver { + btAlignedObjectArray m_tmpSolverBodyPool; + btAlignedObjectArray m_tmpSolverConstraintPool; + btAlignedObjectArray m_tmpSolverFrictionConstraintPool; + btAlignedObjectArray m_orderTmpConstraintPool; + btAlignedObjectArray m_orderFrictionConstraintPool; + + protected: btScalar solve(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); btScalar solveFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); void prepareConstraints(btPersistentManifold* manifoldPtr, const btContactSolverInfo& info,btIDebugDraw* debugDrawer); + void addFrictionConstraint(const btVector3& normalAxis,int solverBodyIdA,int solverBodyIdB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation); ContactSolverFunc m_contactDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; ContactSolverFunc m_frictionDispatch[MAX_CONTACT_SOLVER_TYPES][MAX_CONTACT_SOLVER_TYPES]; - //choose between several modes, different friction model etc. - int m_solverMode; + ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction unsigned long m_btSeed2; public: - enum eSolverMode - { - SOLVER_RANDMIZE_ORDER = 1, - SOLVER_FRICTION_SEPARATE = 2, - SOLVER_USE_WARMSTARTING = 4, - SOLVER_CACHE_FRIENDLY = 8 - }; - + btSequentialImpulseConstraintSolver(); ///Advanced: Override the default contact solving function for contacts, for certain types of rigidbody @@ -68,25 +69,22 @@ public: m_frictionDispatch[type0][type1] = func; } - virtual ~btSequentialImpulseConstraintSolver() {} + virtual ~btSequentialImpulseConstraintSolver(); - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc); + virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher); virtual btScalar solveGroupCacheFriendly(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc); + + + ///clear internal cached data and reset random seed + virtual void reset(); btScalar solveCombinedContactFriction(btRigidBody* body0,btRigidBody* body1, btManifoldPoint& cp, const btContactSolverInfo& info,int iter,btIDebugDraw* debugDrawer); - void setSolverMode(int mode) - { - m_solverMode = mode; - } - - int getSolverMode() const - { - return m_solverMode; - } - + unsigned long btRand2(); int btRandInt2 (int n); @@ -102,7 +100,9 @@ public: }; - +#ifndef BT_PREFER_SIMD +typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered; +#endif #endif //SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp new file mode 100644 index 00000000000..4128f504bf1 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -0,0 +1,415 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 +*/ + +//----------------------------------------------------------------------------- + +#include "btSliderConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btTransformUtil.h" +#include + +//----------------------------------------------------------------------------- + +void btSliderConstraint::initParams() +{ + m_lowerLinLimit = btScalar(1.0); + m_upperLinLimit = btScalar(-1.0); + m_lowerAngLimit = btScalar(0.); + m_upperAngLimit = btScalar(0.); + m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirLin = btScalar(0.); + m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirAng = btScalar(0.); + m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; + + m_poweredLinMotor = false; + m_targetLinMotorVelocity = btScalar(0.); + m_maxLinMotorForce = btScalar(0.); + m_accumulatedLinMotorImpulse = btScalar(0.0); + + m_poweredAngMotor = false; + m_targetAngMotorVelocity = btScalar(0.); + m_maxAngMotorForce = btScalar(0.); + m_accumulatedAngMotorImpulse = btScalar(0.0); + +} // btSliderConstraint::initParams() + +//----------------------------------------------------------------------------- + +btSliderConstraint::btSliderConstraint() + :btTypedConstraint(SLIDER_CONSTRAINT_TYPE), + m_useLinearReferenceFrameA(true) +{ + initParams(); +} // btSliderConstraint::btSliderConstraint() + +//----------------------------------------------------------------------------- + +btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA) + : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB) + , m_frameInA(frameInA) + , m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) +{ + initParams(); +} // btSliderConstraint::btSliderConstraint() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::buildJacobian() +{ + if(m_useLinearReferenceFrameA) + { + buildJacobianInt(m_rbA, m_rbB, m_frameInA, m_frameInB); + } + else + { + buildJacobianInt(m_rbB, m_rbA, m_frameInB, m_frameInA); + } +} // btSliderConstraint::buildJacobian() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB) +{ + //calculate transforms + m_calculatedTransformA = rbA.getCenterOfMassTransform() * frameInA; + m_calculatedTransformB = rbB.getCenterOfMassTransform() * frameInB; + m_realPivotAInW = m_calculatedTransformA.getOrigin(); + m_realPivotBInW = m_calculatedTransformB.getOrigin(); + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + m_delta = m_realPivotBInW - m_realPivotAInW; + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + m_relPosA = m_projPivotInW - rbA.getCenterOfMassPosition(); + m_relPosB = m_realPivotBInW - rbB.getCenterOfMassPosition(); + btVector3 normalWorld; + int i; + //linear part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + new (&m_jacLin[i]) btJacobianEntry( + rbA.getCenterOfMassTransform().getBasis().transpose(), + rbB.getCenterOfMassTransform().getBasis().transpose(), + m_relPosA, + m_relPosB, + normalWorld, + rbA.getInvInertiaDiagLocal(), + rbA.getInvMass(), + rbB.getInvInertiaDiagLocal(), + rbB.getInvMass() + ); + m_jacLinDiagABInv[i] = btScalar(1.) / m_jacLin[i].getDiagonal(); + m_depth[i] = m_delta.dot(normalWorld); + } + testLinLimits(); + // angular part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + new (&m_jacAng[i]) btJacobianEntry( + normalWorld, + rbA.getCenterOfMassTransform().getBasis().transpose(), + rbB.getCenterOfMassTransform().getBasis().transpose(), + rbA.getInvInertiaDiagLocal(), + rbB.getInvInertiaDiagLocal() + ); + } + testAngLimits(); + btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0); + m_kAngle = btScalar(1.0 )/ (rbA.computeAngularImpulseDenominator(axisA) + rbB.computeAngularImpulseDenominator(axisA)); + // clear accumulator for motors + m_accumulatedLinMotorImpulse = btScalar(0.0); + m_accumulatedAngMotorImpulse = btScalar(0.0); +} // btSliderConstraint::buildJacobianInt() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::solveConstraint(btScalar timeStep) +{ + m_timeStep = timeStep; + if(m_useLinearReferenceFrameA) + { + solveConstraintInt(m_rbA, m_rbB); + } + else + { + solveConstraintInt(m_rbB, m_rbA); + } +} // btSliderConstraint::solveConstraint() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB) +{ + int i; + // linear + btVector3 velA = rbA.getVelocityInLocalPoint(m_relPosA); + btVector3 velB = rbB.getVelocityInLocalPoint(m_relPosB); + btVector3 vel = velA - velB; + for(i = 0; i < 3; i++) + { + const btVector3& normal = m_jacLin[i].m_linearJointAxis; + btScalar rel_vel = normal.dot(vel); + // calculate positional error + btScalar depth = m_depth[i]; + // get parameters + btScalar softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin); + btScalar restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin); + btScalar damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin); + // calcutate and apply impulse + btScalar normalImpulse = softness * (restitution * depth / m_timeStep - damping * rel_vel) * m_jacLinDiagABInv[i]; + btVector3 impulse_vector = normal * normalImpulse; + rbA.applyImpulse( impulse_vector, m_relPosA); + rbB.applyImpulse(-impulse_vector, m_relPosB); + if(m_poweredLinMotor && (!i)) + { // apply linear motor + if(m_accumulatedLinMotorImpulse < m_maxLinMotorForce) + { + btScalar desiredMotorVel = m_targetLinMotorVelocity; + btScalar motor_relvel = desiredMotorVel + rel_vel; + normalImpulse = -motor_relvel * m_jacLinDiagABInv[i]; + // clamp accumulated impulse + btScalar new_acc = m_accumulatedLinMotorImpulse + btFabs(normalImpulse); + if(new_acc > m_maxLinMotorForce) + { + new_acc = m_maxLinMotorForce; + } + btScalar del = new_acc - m_accumulatedLinMotorImpulse; + if(normalImpulse < btScalar(0.0)) + { + normalImpulse = -del; + } + else + { + normalImpulse = del; + } + m_accumulatedLinMotorImpulse = new_acc; + // apply clamped impulse + impulse_vector = normal * normalImpulse; + rbA.applyImpulse( impulse_vector, m_relPosA); + rbB.applyImpulse(-impulse_vector, m_relPosB); + } + } + } + // angular + // get axes in world space + btVector3 axisA = m_calculatedTransformA.getBasis().getColumn(0); + btVector3 axisB = m_calculatedTransformB.getBasis().getColumn(0); + + const btVector3& angVelA = rbA.getAngularVelocity(); + const btVector3& angVelB = rbB.getAngularVelocity(); + + btVector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); + btVector3 angVelAroundAxisB = axisB * axisB.dot(angVelB); + + btVector3 angAorthog = angVelA - angVelAroundAxisA; + btVector3 angBorthog = angVelB - angVelAroundAxisB; + btVector3 velrelOrthog = angAorthog-angBorthog; + //solve orthogonal angular velocity correction + btScalar len = velrelOrthog.length(); + if (len > btScalar(0.00001)) + { + btVector3 normal = velrelOrthog.normalized(); + btScalar denom = rbA.computeAngularImpulseDenominator(normal) + rbB.computeAngularImpulseDenominator(normal); + velrelOrthog *= (btScalar(1.)/denom) * m_dampingOrthoAng * m_softnessOrthoAng; + } + //solve angular positional correction + btVector3 angularError = axisA.cross(axisB) *(btScalar(1.)/m_timeStep); + btScalar len2 = angularError.length(); + if (len2>btScalar(0.00001)) + { + btVector3 normal2 = angularError.normalized(); + btScalar denom2 = rbA.computeAngularImpulseDenominator(normal2) + rbB.computeAngularImpulseDenominator(normal2); + angularError *= (btScalar(1.)/denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; + } + // apply impulse + rbA.applyTorqueImpulse(-velrelOrthog+angularError); + rbB.applyTorqueImpulse(velrelOrthog-angularError); + btScalar impulseMag; + //solve angular limits + if(m_solveAngLim) + { + impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / m_timeStep; + impulseMag *= m_kAngle * m_softnessLimAng; + } + else + { + impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / m_timeStep; + impulseMag *= m_kAngle * m_softnessDirAng; + } + btVector3 impulse = axisA * impulseMag; + rbA.applyTorqueImpulse(impulse); + rbB.applyTorqueImpulse(-impulse); + //apply angular motor + if(m_poweredAngMotor) + { + if(m_accumulatedAngMotorImpulse < m_maxAngMotorForce) + { + btVector3 velrel = angVelAroundAxisA - angVelAroundAxisB; + btScalar projRelVel = velrel.dot(axisA); + + btScalar desiredMotorVel = m_targetAngMotorVelocity; + btScalar motor_relvel = desiredMotorVel - projRelVel; + + btScalar angImpulse = m_kAngle * motor_relvel; + // clamp accumulated impulse + btScalar new_acc = m_accumulatedAngMotorImpulse + btFabs(angImpulse); + if(new_acc > m_maxAngMotorForce) + { + new_acc = m_maxAngMotorForce; + } + btScalar del = new_acc - m_accumulatedAngMotorImpulse; + if(angImpulse < btScalar(0.0)) + { + angImpulse = -del; + } + else + { + angImpulse = del; + } + m_accumulatedAngMotorImpulse = new_acc; + // apply clamped impulse + btVector3 motorImp = angImpulse * axisA; + m_rbA.applyTorqueImpulse(motorImp); + m_rbB.applyTorqueImpulse(-motorImp); + } + } +} // btSliderConstraint::solveConstraint() + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +void btSliderConstraint::calculateTransforms(void){ + if(m_useLinearReferenceFrameA) + { + m_calculatedTransformA = m_rbA.getCenterOfMassTransform() * m_frameInA; + m_calculatedTransformB = m_rbB.getCenterOfMassTransform() * m_frameInB; + } + else + { + m_calculatedTransformA = m_rbB.getCenterOfMassTransform() * m_frameInB; + m_calculatedTransformB = m_rbA.getCenterOfMassTransform() * m_frameInA; + } + m_realPivotAInW = m_calculatedTransformA.getOrigin(); + m_realPivotBInW = m_calculatedTransformB.getOrigin(); + m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X + m_delta = m_realPivotBInW - m_realPivotAInW; + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + btVector3 normalWorld; + int i; + //linear part + for(i = 0; i < 3; i++) + { + normalWorld = m_calculatedTransformA.getBasis().getColumn(i); + m_depth[i] = m_delta.dot(normalWorld); + } +} // btSliderConstraint::calculateTransforms() + +//----------------------------------------------------------------------------- + +void btSliderConstraint::testLinLimits(void) +{ + m_solveLinLim = false; + m_linPos = m_depth[0]; + if(m_lowerLinLimit <= m_upperLinLimit) + { + if(m_depth[0] > m_upperLinLimit) + { + m_depth[0] -= m_upperLinLimit; + m_solveLinLim = true; + } + else if(m_depth[0] < m_lowerLinLimit) + { + m_depth[0] -= m_lowerLinLimit; + m_solveLinLim = true; + } + else + { + m_depth[0] = btScalar(0.); + } + } + else + { + m_depth[0] = btScalar(0.); + } +} // btSliderConstraint::testLinLimits() + +//----------------------------------------------------------------------------- + + +void btSliderConstraint::testAngLimits(void) +{ + m_angDepth = btScalar(0.); + m_solveAngLim = false; + if(m_lowerAngLimit <= m_upperAngLimit) + { + const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1); + const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2); + const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1); + btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); + if(rot < m_lowerAngLimit) + { + m_angDepth = rot - m_lowerAngLimit; + m_solveAngLim = true; + } + else if(rot > m_upperAngLimit) + { + m_angDepth = rot - m_upperAngLimit; + m_solveAngLim = true; + } + } +} // btSliderConstraint::testAngLimits() + + +//----------------------------------------------------------------------------- + + + +btVector3 btSliderConstraint::getAncorInA(void) +{ + btVector3 ancorInA; + ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis; + ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA; + return ancorInA; +} // btSliderConstraint::getAncorInA() + +//----------------------------------------------------------------------------- + +btVector3 btSliderConstraint::getAncorInB(void) +{ + btVector3 ancorInB; + ancorInB = m_frameInB.getOrigin(); + return ancorInB; +} // btSliderConstraint::getAncorInB(); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h new file mode 100644 index 00000000000..580dfa1178d --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -0,0 +1,218 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +TODO: + - add clamping od accumulated impulse to improve stability + - add conversion for ODE constraint solver +*/ + +#ifndef SLIDER_CONSTRAINT_H +#define SLIDER_CONSTRAINT_H + +//----------------------------------------------------------------------------- + +#include "LinearMath/btVector3.h" +#include "btJacobianEntry.h" +#include "btTypedConstraint.h" + +//----------------------------------------------------------------------------- + +class btRigidBody; + +//----------------------------------------------------------------------------- + +#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0)) +#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7)) + +//----------------------------------------------------------------------------- + +class btSliderConstraint : public btTypedConstraint +{ +protected: + btTransform m_frameInA; + btTransform m_frameInB; + // use frameA fo define limits, if true + bool m_useLinearReferenceFrameA; + // linear limits + btScalar m_lowerLinLimit; + btScalar m_upperLinLimit; + // angular limits + btScalar m_lowerAngLimit; + btScalar m_upperAngLimit; + // softness, restitution and damping for different cases + // DirLin - moving inside linear limits + // LimLin - hitting linear limit + // DirAng - moving inside angular limits + // LimAng - hitting angular limit + // OrthoLin, OrthoAng - against constraint axis + btScalar m_softnessDirLin; + btScalar m_restitutionDirLin; + btScalar m_dampingDirLin; + btScalar m_softnessDirAng; + btScalar m_restitutionDirAng; + btScalar m_dampingDirAng; + btScalar m_softnessLimLin; + btScalar m_restitutionLimLin; + btScalar m_dampingLimLin; + btScalar m_softnessLimAng; + btScalar m_restitutionLimAng; + btScalar m_dampingLimAng; + btScalar m_softnessOrthoLin; + btScalar m_restitutionOrthoLin; + btScalar m_dampingOrthoLin; + btScalar m_softnessOrthoAng; + btScalar m_restitutionOrthoAng; + btScalar m_dampingOrthoAng; + + // for interlal use + bool m_solveLinLim; + bool m_solveAngLim; + + btJacobianEntry m_jacLin[3]; + btScalar m_jacLinDiagABInv[3]; + + btJacobianEntry m_jacAng[3]; + + btScalar m_timeStep; + btTransform m_calculatedTransformA; + btTransform m_calculatedTransformB; + + btVector3 m_sliderAxis; + btVector3 m_realPivotAInW; + btVector3 m_realPivotBInW; + btVector3 m_projPivotInW; + btVector3 m_delta; + btVector3 m_depth; + btVector3 m_relPosA; + btVector3 m_relPosB; + + btScalar m_linPos; + + btScalar m_angDepth; + btScalar m_kAngle; + + bool m_poweredLinMotor; + btScalar m_targetLinMotorVelocity; + btScalar m_maxLinMotorForce; + btScalar m_accumulatedLinMotorImpulse; + + bool m_poweredAngMotor; + btScalar m_targetAngMotorVelocity; + btScalar m_maxAngMotorForce; + btScalar m_accumulatedAngMotorImpulse; + + //------------------------ + void initParams(); +public: + // constructors + btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA); + btSliderConstraint(); + // overrides + virtual void buildJacobian(); + virtual void solveConstraint(btScalar timeStep); + // access + const btRigidBody& getRigidBodyA() const { return m_rbA; } + const btRigidBody& getRigidBodyB() const { return m_rbB; } + const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; } + const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; } + const btTransform & getFrameOffsetA() const { return m_frameInA; } + const btTransform & getFrameOffsetB() const { return m_frameInB; } + btTransform & getFrameOffsetA() { return m_frameInA; } + btTransform & getFrameOffsetB() { return m_frameInB; } + btScalar getLowerLinLimit() { return m_lowerLinLimit; } + void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; } + btScalar getUpperLinLimit() { return m_upperLinLimit; } + void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; } + btScalar getLowerAngLimit() { return m_lowerAngLimit; } + void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = lowerLimit; } + btScalar getUpperAngLimit() { return m_upperAngLimit; } + void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = upperLimit; } + bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; } + btScalar getSoftnessDirLin() { return m_softnessDirLin; } + btScalar getRestitutionDirLin() { return m_restitutionDirLin; } + btScalar getDampingDirLin() { return m_dampingDirLin ; } + btScalar getSoftnessDirAng() { return m_softnessDirAng; } + btScalar getRestitutionDirAng() { return m_restitutionDirAng; } + btScalar getDampingDirAng() { return m_dampingDirAng; } + btScalar getSoftnessLimLin() { return m_softnessLimLin; } + btScalar getRestitutionLimLin() { return m_restitutionLimLin; } + btScalar getDampingLimLin() { return m_dampingLimLin; } + btScalar getSoftnessLimAng() { return m_softnessLimAng; } + btScalar getRestitutionLimAng() { return m_restitutionLimAng; } + btScalar getDampingLimAng() { return m_dampingLimAng; } + btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; } + btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; } + btScalar getDampingOrthoLin() { return m_dampingOrthoLin; } + btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; } + btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; } + btScalar getDampingOrthoAng() { return m_dampingOrthoAng; } + void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; } + void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } + void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; } + void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; } + void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } + void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; } + void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; } + void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } + void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; } + void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; } + void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } + void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; } + void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } + void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } + void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } + void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } + void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } + void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } + void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } + bool getPoweredLinMotor() { return m_poweredLinMotor; } + void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } + btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } + void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } + btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; } + void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } + bool getPoweredAngMotor() { return m_poweredAngMotor; } + void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } + btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } + void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } + btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } + btScalar getLinearPos() { return m_linPos; } + + // access for ODE solver + bool getSolveLinLimit() { return m_solveLinLim; } + btScalar getLinDepth() { return m_depth[0]; } + bool getSolveAngLimit() { return m_solveAngLim; } + btScalar getAngDepth() { return m_angDepth; } + // internal + void buildJacobianInt(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB); + void solveConstraintInt(btRigidBody& rbA, btRigidBody& rbB); + // shared code used by ODE solver + void calculateTransforms(void); + void testLinLimits(void); + void testAngLimits(void); + // access for PE Solver + btVector3 getAncorInA(void); + btVector3 getAncorInB(void); +}; + +//----------------------------------------------------------------------------- + +#endif //SLIDER_CONSTRAINT_H + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h index e7d26645c6a..057d3fac827 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h @@ -16,8 +16,8 @@ subject to the following restrictions: #ifndef SOLVE_2LINEAR_CONSTRAINT_H #define SOLVE_2LINEAR_CONSTRAINT_H -#include "../../LinearMath/btMatrix3x3.h" -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btVector3.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h index 0ab536f42b3..b3f0c9d7444 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverBody.h @@ -19,38 +19,78 @@ subject to the following restrictions: class btRigidBody; #include "LinearMath/btVector3.h" #include "LinearMath/btMatrix3x3.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "LinearMath/btAlignedAllocator.h" +#include "LinearMath/btTransformUtil.h" - - +///btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance. ATTRIBUTE_ALIGNED16 (struct) btSolverBody { - btVector3 m_centerOfMassPosition; - btVector3 m_linearVelocity; + BT_DECLARE_ALIGNED_ALLOCATOR(); + btVector3 m_angularVelocity; - btRigidBody* m_originalBody; + float m_angularFactor; float m_invMass; float m_friction; - float m_angularFactor; - - inline void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const + btRigidBody* m_originalBody; + btVector3 m_linearVelocity; + btVector3 m_centerOfMassPosition; + + btVector3 m_pushVelocity; + btVector3 m_turnVelocity; + + + SIMD_FORCE_INLINE void getVelocityInLocalPoint(const btVector3& rel_pos, btVector3& velocity ) const { velocity = m_linearVelocity + m_angularVelocity.cross(rel_pos); } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { - m_linearVelocity += linearComponent*impulseMagnitude; - m_angularVelocity += angularComponent*impulseMagnitude*m_angularFactor; + if (m_invMass) + { + m_linearVelocity += linearComponent*impulseMagnitude; + m_angularVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } + } + + SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + { + if (m_invMass) + { + m_pushVelocity += linearComponent*impulseMagnitude; + m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor); + } } + void writebackVelocity() { if (m_invMass) { m_originalBody->setLinearVelocity(m_linearVelocity); m_originalBody->setAngularVelocity(m_angularVelocity); + + //m_originalBody->setCompanionId(-1); + } + } + + + void writebackVelocity(btScalar timeStep) + { + if (m_invMass) + { + m_originalBody->setLinearVelocity(m_linearVelocity); + m_originalBody->setAngularVelocity(m_angularVelocity); + + //correct the position/orientation based on push/turn recovery + btTransform newTransform; + btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform); + m_originalBody->setWorldTransform(newTransform); + + //m_originalBody->setCompanionId(-1); } } @@ -69,3 +109,5 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverBody }; #endif //BT_SOLVER_BODY_H + + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h index f1f40ffdf19..2c71360c5b9 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSolverConstraint.h @@ -1,5 +1,3 @@ - - /* Bullet Continuous Collision Detection and Physics Library Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ @@ -27,24 +25,34 @@ class btRigidBody; ///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints. ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint { + BT_DECLARE_ALIGNED_ALLOCATOR(); + btVector3 m_relpos1CrossNormal; - btVector3 m_relpos2CrossNormal; btVector3 m_contactNormal; + + btVector3 m_relpos2CrossNormal; btVector3 m_angularComponentA; + btVector3 m_angularComponentB; - btScalar m_appliedVelocityImpulse; + mutable btScalar m_appliedPushImpulse; + + mutable btScalar m_appliedImpulse; int m_solverBodyIdA; int m_solverBodyIdB; + btScalar m_friction; btScalar m_restitution; btScalar m_jacDiagABInv; btScalar m_penetration; - btScalar m_appliedImpulse; + + int m_constraintType; int m_frictionIndex; - int m_unusedPadding[2]; + void* m_originalContactPoint; + int m_unusedPadding[1]; + enum btSolverConstraintType { @@ -61,3 +69,4 @@ ATTRIBUTE_ALIGNED16 (struct) btSolverConstraint #endif //BT_SOLVER_CONSTRAINT_H + diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp index a15b3e026cd..6e8b552dbbc 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp @@ -19,18 +19,20 @@ subject to the following restrictions: static btRigidBody s_fixed(0, 0,0); -btTypedConstraint::btTypedConstraint() -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(s_fixed), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) { s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); } -btTypedConstraint::btTypedConstraint(btRigidBody& rbA) -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(rbA), m_rbB(s_fixed), m_appliedImpulse(btScalar(0.)) @@ -40,9 +42,10 @@ m_appliedImpulse(btScalar(0.)) } -btTypedConstraint::btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB) -: m_userConstraintType(-1), +btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB) +:m_userConstraintType(-1), m_userConstraintId(-1), +m_constraintType (type), m_rbA(rbA), m_rbB(rbB), m_appliedImpulse(btScalar(0.)) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h index dfee6e80d0e..c50ec6ec579 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btTypedConstraint.h @@ -17,7 +17,17 @@ subject to the following restrictions: #define TYPED_CONSTRAINT_H class btRigidBody; -#include "../../LinearMath/btScalar.h" +#include "LinearMath/btScalar.h" + +enum btTypedConstraintType +{ + POINT2POINT_CONSTRAINT_TYPE, + HINGE_CONSTRAINT_TYPE, + CONETWIST_CONSTRAINT_TYPE, + D6_CONSTRAINT_TYPE, + VEHICLE_CONSTRAINT_TYPE, + SLIDER_CONSTRAINT_TYPE +}; ///TypedConstraint is the baseclass for Bullet constraints and vehicles class btTypedConstraint @@ -25,6 +35,8 @@ class btTypedConstraint int m_userConstraintType; int m_userConstraintId; + btTypedConstraintType m_constraintType; + btTypedConstraint& operator=(btTypedConstraint& other) { btAssert(0); @@ -40,11 +52,11 @@ protected: public: - btTypedConstraint(); + btTypedConstraint(btTypedConstraintType type); virtual ~btTypedConstraint() {}; - btTypedConstraint(btRigidBody& rbA); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA); - btTypedConstraint(btRigidBody& rbA,btRigidBody& rbB); + btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB); virtual void buildJacobian() = 0; @@ -59,7 +71,7 @@ public: return m_rbB; } - btRigidBody& getRigidBodyA() + btRigidBody& getRigidBodyA() { return m_rbA; } @@ -83,14 +95,26 @@ public: m_userConstraintId = uid; } - int getUserConstraintId() + int getUserConstraintId() const { return m_userConstraintId; } - btScalar getAppliedImpulse() + + int getUid() const + { + return m_userConstraintId; + } + + btScalar getAppliedImpulse() const { return m_appliedImpulse; } + + btTypedConstraintType getConstraintType () const + { + return m_constraintType; + } + }; #endif //TYPED_CONSTRAINT_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp index 248c582dcd8..c2fd71d67fe 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp @@ -25,6 +25,7 @@ subject to the following restrictions: #include "LinearMath/btAlignedAllocator.h" + #include "LinearMath/btVector3.h" #include "LinearMath/btScalar.h" #include "LinearMath/btMatrix3x3.h" @@ -39,18 +40,296 @@ subject to the following restrictions: #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpa.h" #include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h" -#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" -#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" - #include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h" #include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h" #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h" -#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "LinearMath/btStackAlloc.h" -extern "C" +/* + Create and Delete a Physics SDK +*/ + +struct btPhysicsSdk +{ + +// btDispatcher* m_dispatcher; +// btOverlappingPairCache* m_pairCache; +// btConstraintSolver* m_constraintSolver + + btVector3 m_worldAabbMin; + btVector3 m_worldAabbMax; + + + //todo: version, hardware/optimization settings etc? + btPhysicsSdk() + :m_worldAabbMin(-1000,-1000,-1000), + m_worldAabbMax(1000,1000,1000) + { + + } + + +}; + +plPhysicsSdkHandle plNewBulletSdk() +{ + void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16); + return (plPhysicsSdkHandle)new (mem)btPhysicsSdk; +} + +void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk) +{ + btPhysicsSdk* phys = reinterpret_cast(physicsSdk); + btAlignedFree(phys); +} + + +/* Dynamics World */ +plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle) +{ + btPhysicsSdk* physicsSdk = reinterpret_cast(physicsSdkHandle); + void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16); + btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration(); + mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16); + btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration); + mem = btAlignedAlloc(sizeof(btAxisSweep3),16); + btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax); + mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver(); + + mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16); + return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration); +} +void plDeleteDynamicsWorld(plDynamicsWorldHandle world) +{ + //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAlignedFree(dynamicsWorld); +} + +void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + dynamicsWorld->stepSimulation(timeStep); +} + +void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->addRigidBody(body); +} + +void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + assert(dynamicsWorld); + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + assert(body); + + dynamicsWorld->removeRigidBody(body); +} + +/* Rigid Body */ + +plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape ) +{ + btTransform trans; + trans.setIdentity(); + btVector3 localInertia(0,0,0); + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + if (mass) + { + shape->calculateLocalInertia(mass,localInertia); + } + void* mem = btAlignedAlloc(sizeof(btRigidBody),16); + btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia); + btRigidBody* body = new (mem)btRigidBody(rbci); + body->setWorldTransform(trans); + body->setUserPointer(user_data); + return (plRigidBodyHandle) body; +} + +void plDeleteRigidBody(plRigidBodyHandle cbody) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody); + assert(body); + btAlignedFree( body); +} + + +/* Collision Shape definition */ + +plCollisionShapeHandle plNewSphereShape(plReal radius) +{ + void* mem = btAlignedAlloc(sizeof(btSphereShape),16); + return (plCollisionShapeHandle) new (mem)btSphereShape(radius); + +} + +plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z) +{ + void* mem = btAlignedAlloc(sizeof(btBoxShape),16); + return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z)); +} + +plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height) +{ + //capsule is convex hull of 2 spheres, so use btMultiSphereShape + btVector3 inertiaHalfExtents(radius,height,radius); + const int numSpheres = 2; + btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)}; + btScalar radi[numSpheres] = {radius,radius}; + void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16); + return (plCollisionShapeHandle) new (mem)btMultiSphereShape(inertiaHalfExtents,positions,radi,numSpheres); +} +plCollisionShapeHandle plNewConeShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btConeShape),16); + return (plCollisionShapeHandle) new (mem)btConeShape(radius,height); +} + +plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height) +{ + void* mem = btAlignedAlloc(sizeof(btCylinderShape),16); + return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius)); +} + +/* Convex Meshes */ +plCollisionShapeHandle plNewConvexHullShape() +{ + void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16); + return (plCollisionShapeHandle) new (mem)btConvexHullShape(); +} + + +/* Concave static triangle meshes */ +plMeshInterfaceHandle plNewMeshInterface() +{ + return 0; +} + +plCollisionShapeHandle plNewCompoundShape() +{ + void* mem = btAlignedAlloc(sizeof(btCompoundShape),16); + return (plCollisionShapeHandle) new (mem)btCompoundShape(); +} + +void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn) +{ + btCollisionShape* colShape = reinterpret_cast(compoundShapeHandle); + btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE); + btCompoundShape* compoundShape = reinterpret_cast(colShape); + btCollisionShape* childShape = reinterpret_cast(childShapeHandle); + btTransform localTrans; + localTrans.setIdentity(); + localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2])); + localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3])); + compoundShape->addChildShape(localTrans,childShape); +} + +void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient) +{ + btQuaternion orn; + orn.setEuler(yaw,pitch,roll); + orient[0] = orn.getX(); + orient[1] = orn.getY(); + orient[2] = orn.getZ(); + orient[3] = orn.getW(); + +} + + +// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2); +// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle); + + +void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z) +{ + btCollisionShape* colShape = reinterpret_cast( cshape); + (void)colShape; + btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE); + btConvexHullShape* convexHullShape = reinterpret_cast( cshape); + convexHullShape->addPoint(btPoint3(x,y,z)); + +} + +void plDeleteShape(plCollisionShapeHandle cshape) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btAlignedFree(shape); +} +void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling) +{ + btCollisionShape* shape = reinterpret_cast( cshape); + assert(shape); + btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]); + shape->setLocalScaling(scaling); +} + + + +void plSetPosition(plRigidBodyHandle object, const plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btVector3 pos(position[0],position[1],position[2]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setOrigin(pos); + body->setWorldTransform(worldTrans); +} + +void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]); + btTransform worldTrans = body->getWorldTransform(); + worldTrans.setRotation(orn); + body->setWorldTransform(worldTrans); +} + +void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + body->getWorldTransform().getOpenGLMatrix(matrix); + +} + +void plGetPosition(plRigidBodyHandle object,plVector3 position) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btVector3& pos = body->getWorldTransform().getOrigin(); + position[0] = pos.getX(); + position[1] = pos.getY(); + position[2] = pos.getZ(); +} + +void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation) +{ + btRigidBody* body = reinterpret_cast< btRigidBody* >(object); + btAssert(body); + const btQuaternion& orn = body->getWorldTransform().getRotation(); + orientation[0] = orn.getX(); + orientation[1] = orn.getY(); + orientation[2] = orn.getZ(); + orientation[3] = orn.getW(); +} + + + +//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + +// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); + double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]) { btVector3 vp(p1[0], p1[1], p1[2]); @@ -118,3 +397,4 @@ double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float } return -1.0f; } + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp new file mode 100644 index 00000000000..19443adc723 --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp @@ -0,0 +1,193 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btContinuousDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//collision detection +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" + +//rigidbody & constraints +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" + + + +#include + +btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ +} + +btContinuousDynamicsWorld::~btContinuousDynamicsWorld() +{ +} + + +void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) +{ + + startProfiling(timeStep); + + + ///update aabbs information + updateAabbs(); + //static int frame=0; +// printf("frame %d\n",frame++); + + ///apply gravity, predict motion + predictUnconstraintMotion(timeStep); + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_debugDraw = getDebugDrawer(); + + ///perform collision detection + performDiscreteCollisionDetection(); + + calculateSimulationIslands(); + + + getSolverInfo().m_timeStep = timeStep; + + + + ///solve contact and other joint constraints + solveConstraints(getSolverInfo()); + + ///CallbackTriggers(); + calculateTimeOfImpacts(timeStep); + + btScalar toi = dispatchInfo.m_timeOfImpact; +// if (toi < 1.f) +// printf("toi = %f\n",toi); + if (toi < 0.f) + printf("toi = %f\n",toi); + + + ///integrate transforms + integrateTransforms(timeStep * toi); + + ///update vehicle simulation + updateVehicles(timeStep); + + + updateActivationState( timeStep ); + + if(0 != m_internalTickCallback) { + (*m_internalTickCallback)(this, timeStep); + } +} + +void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep) +{ + ///these should be 'temporal' aabbs! + updateTemporalAabbs(timeStep); + + ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually. + ///so we handle the case moving versus static properly, and we cheat for moving versus moving + btScalar toi = 1.f; + + + btDispatcherInfo& dispatchInfo = getDispatchInfo(); + dispatchInfo.m_timeStep = timeStep; + dispatchInfo.m_timeOfImpact = 1.f; + dispatchInfo.m_stepCount = 0; + dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS; + + ///calculate time of impact for overlapping pairs + + + btDispatcher* dispatcher = getDispatcher(); + if (dispatcher) + dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1); + + toi = dispatchInfo.m_timeOfImpact; + + dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE; + +} + +void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep) +{ + + btVector3 temporalAabbMin,temporalAabbMax; + + for ( int i=0;igetCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax); + const btVector3& linvel = body->getLinearVelocity(); + + //make the AABB temporal + btScalar temporalAabbMaxx = temporalAabbMax.getX(); + btScalar temporalAabbMaxy = temporalAabbMax.getY(); + btScalar temporalAabbMaxz = temporalAabbMax.getZ(); + btScalar temporalAabbMinx = temporalAabbMin.getX(); + btScalar temporalAabbMiny = temporalAabbMin.getY(); + btScalar temporalAabbMinz = temporalAabbMin.getZ(); + + // add linear motion + btVector3 linMotion = linvel*timeStep; + + if (linMotion.x() > 0.f) + temporalAabbMaxx += linMotion.x(); + else + temporalAabbMinx += linMotion.x(); + if (linMotion.y() > 0.f) + temporalAabbMaxy += linMotion.y(); + else + temporalAabbMiny += linMotion.y(); + if (linMotion.z() > 0.f) + temporalAabbMaxz += linMotion.z(); + else + temporalAabbMinz += linMotion.z(); + + //add conservative angular motion + btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep; + btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion); + temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz); + temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz); + + temporalAabbMin -= angularMotion3d; + temporalAabbMax += angularMotion3d; + + m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1); + } + } + + //update aabb (of all moved objects) + + m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1); + + + +} + + + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h new file mode 100644 index 00000000000..61c8dea03eb --- /dev/null +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H +#define BT_CONTINUOUS_DYNAMICS_WORLD_H + +#include "btDiscreteDynamicsWorld.h" + +///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld. +///This copes with fast moving objects that otherwise would tunnel/miss collisions. +///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead. +class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld +{ + + void updateTemporalAabbs(btScalar timeStep); + + public: + + btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + virtual ~btContinuousDynamicsWorld(); + + ///time stepping with calculation of time of impact for selected fast moving objects + virtual void internalSingleStepSimulation( btScalar timeStep); + + virtual void calculateTimeOfImpacts(btScalar timeStep); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_CONTINUOUS_DYNAMICS_WORLD; + } + +}; + +#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index 1017c8af6ea..e46c4e6136b 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -21,7 +21,8 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/CollisionShapes/btCollisionShape.h" #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" -#include +#include "LinearMath/btTransformUtil.h" +#include "LinearMath/btQuickprof.h" //rigidbody & constraints #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -41,6 +42,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btSphereShape.h" #include "BulletCollision/CollisionShapes/btTriangleCallback.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" #include "LinearMath/btIDebugDraw.h" @@ -57,17 +59,29 @@ subject to the following restrictions: -btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) -:btDynamicsWorld(dispatcher,pairCache), -m_constraintSolver(constraintSolver? constraintSolver: new btSequentialImpulseConstraintSolver), -m_debugDrawer(0), +btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), +m_constraintSolver(constraintSolver), m_gravity(0,-10,0), m_localTime(btScalar(1.)/btScalar(60.)), m_profileTimings(0) { - m_islandManager = new btSimulationIslandManager(); + if (!m_constraintSolver) + { + void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16); + m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver; + m_ownsConstraintSolver = true; + } else + { + m_ownsConstraintSolver = false; + } + + { + void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16); + m_islandManager = new (mem) btSimulationIslandManager(); + } + m_ownsIslandManager = true; - m_ownsConstraintSolver = (constraintSolver==0); } @@ -75,9 +89,16 @@ btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld() { //only delete it when we created it if (m_ownsIslandManager) - delete m_islandManager; + { + m_islandManager->~btSimulationIslandManager(); + btAlignedFree( m_islandManager); + } if (m_ownsConstraintSolver) - delete m_constraintSolver; + { + + m_constraintSolver->~btConstraintSolver(); + btAlignedFree(m_constraintSolver); + } } void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) @@ -102,14 +123,35 @@ void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep) } } -void btDiscreteDynamicsWorld::synchronizeMotionStates() +void btDiscreteDynamicsWorld::debugDrawWorld() { - //debug vehicle wheels - - + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints) { + int numManifolds = getDispatcher()->getNumManifolds(); + btVector3 color(0,0,0); + for (int i=0;igetManifoldByIndexInternal(i); + //btCollisionObject* obA = static_cast(contactManifold->getBody0()); + //btCollisionObject* obB = static_cast(contactManifold->getBody1()); + + int numContacts = contactManifold->getNumContacts(); + for (int j=0;jgetContactPoint(j); + getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); + } + } + } + + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)) + { + int i; + //todo: iterate over awake simulation islands! - for ( int i=0;igetDebugMode() & btIDebugDraw::DBG_DrawWireframe) @@ -135,26 +177,17 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color); } - btRigidBody* body = btRigidBody::upcast(colObj); - if (body && body->getMotionState() && !body->isStaticOrKinematicObject()) + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) { - //we need to call the update at least once, even for sleeping objects - //otherwise the 'graphics' transform never updates properly - //so todo: add 'dirty' flag - //if (body->getActivationState() != ISLAND_SLEEPING) - { - btTransform interpolatedTransform; - btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime,interpolatedTransform); - body->getMotionState()->setWorldTransform(interpolatedTransform); - } + btPoint3 minAabb,maxAabb; + btVector3 colorvec(1,0,0); + colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); } - } - } - if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) - { - for ( int i=0;im_vehicles.size();i++) + } + + for ( i=0;im_vehicles.size();i++) { for (int v=0;vgetNumWheels();v++) { @@ -166,10 +199,7 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() { wheelColor.setValue(255,0,255); } - - //synchronize the wheels with the (interpolated) chassis worldtransform - m_vehicles[i]->updateWheelTransform(v,true); - + btVector3 wheelPosWS = m_vehicles[i]->getWheelInfo(v).m_worldTransform.getOrigin(); btVector3 axle = btVector3( @@ -186,12 +216,87 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() } } } +} + +void btDiscreteDynamicsWorld::clearForces() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } + } +} + +///apply gravity, call this once per timestep +void btDiscreteDynamicsWorld::applyGravity() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iisActive()) + { + body->applyGravity(); + } + } +} + + + +void btDiscreteDynamicsWorld::synchronizeMotionStates() +{ + { + //todo: iterate over awake simulation islands! + for ( int i=0;igetMotionState() && !body->isStaticOrKinematicObject()) + { + //we need to call the update at least once, even for sleeping objects + //otherwise the 'graphics' transform never updates properly + //so todo: add 'dirty' flag + //if (body->getActivationState() != ISLAND_SLEEPING) + { + btTransform interpolatedTransform; + btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform); + body->getMotionState()->setWorldTransform(interpolatedTransform); + } + } + } + } + + if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe) + { + for ( int i=0;im_vehicles.size();i++) + { + for (int v=0;vgetNumWheels();v++) + { + //synchronize the wheels with the (interpolated) chassis worldtransform + m_vehicles[i]->updateWheelTransform(v,true); + } + } + } } int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) { + startProfiling(timeStep); + + BT_PROFILE("stepSimulation"); + int numSimulationSubSteps = 0; if (maxSubSteps) @@ -229,6 +334,8 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, saveKinematicState(fixedTimeStep); + applyGravity(); + //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps; @@ -242,16 +349,19 @@ int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, synchronizeMotionStates(); + clearForces(); + +#ifndef BT_NO_PROFILE + CProfileManager::Increment_Frame_Counter(); +#endif //BT_NO_PROFILE + return numSimulationSubSteps; } void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) { - startProfiling(timeStep); - - ///update aabbs information - updateAabbs(); + BT_PROFILE("internalSingleStepSimulation"); ///apply gravity, predict motion predictUnconstraintMotion(timeStep); @@ -286,8 +396,9 @@ void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep) updateActivationState( timeStep ); - - + if(0 != m_internalTickCallback) { + (*m_internalTickCallback)(this, timeStep); + } } void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) @@ -304,6 +415,11 @@ void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity) } } +btVector3 btDiscreteDynamicsWorld::getGravity () const +{ + return m_gravity; +} + void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body) { @@ -343,19 +459,18 @@ void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short void btDiscreteDynamicsWorld::updateVehicles(btScalar timeStep) { - BEGIN_PROFILE("updateVehicles"); - + BT_PROFILE("updateVehicles"); + for ( int i=0;iupdateVehicle( timeStep); } - END_PROFILE("updateVehicles"); } void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) { - BEGIN_PROFILE("updateActivationState"); + BT_PROFILE("updateActivationState"); for ( int i=0;igetActivationState() == ACTIVE_TAG) body->setActivationState( WANTS_DEACTIVATION ); + if (body->getActivationState() == ISLAND_SLEEPING) + { + body->setAngularVelocity(btVector3(0,0,0)); + body->setLinearVelocity(btVector3(0,0,0)); + } + } } else { @@ -382,7 +503,6 @@ void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep) } } } - END_PROFILE("updateActivationState"); } void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies) @@ -412,7 +532,7 @@ void btDiscreteDynamicsWorld::removeVehicle(btRaycastVehicle* vehicle) m_vehicles.remove(vehicle); } -inline int btGetConstraintIslandId(const btTypedConstraint* lhs) +SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs) { int islandId; @@ -442,6 +562,7 @@ class btSortConstraintOnIslandPredicate void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { + BT_PROFILE("solveConstraints"); struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback { @@ -452,7 +573,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) int m_numConstraints; btIDebugDraw* m_debugDrawer; btStackAlloc* m_stackAlloc; - + btDispatcher* m_dispatcher; InplaceSolverIslandCallback( btContactSolverInfo& solverInfo, @@ -460,13 +581,15 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer, - btStackAlloc* stackAlloc) + btStackAlloc* stackAlloc, + btDispatcher* dispatcher) :m_solverInfo(solverInfo), m_solver(solver), m_sortedConstraints(sortedConstraints), m_numConstraints(numConstraints), m_debugDrawer(debugDrawer), - m_stackAlloc(stackAlloc) + m_stackAlloc(stackAlloc), + m_dispatcher(dispatcher) { } @@ -479,30 +602,42 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) } virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId) { - //also add all non-contact constraints/joints for this island - btTypedConstraint** startConstraint = 0; - int numCurConstraints = 0; - int i; - - //find the first constraint for this island - for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } else { - if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId) + //also add all non-contact constraints/joints for this island + btTypedConstraint** startConstraint = 0; + int numCurConstraints = 0; + int i; + + //find the first constraint for this island + for (i=0;isolveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc); + ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive + if (numManifolds + numCurConstraints) + { + m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + } + + } } }; @@ -520,18 +655,18 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) - sortedConstraints.heapSort(btSortConstraintOnIslandPredicate()); + sortedConstraints.quickSort(btSortConstraintOnIslandPredicate()); btTypedConstraint** constraintsPtr = getNumConstraints() ? &sortedConstraints[0] : 0; - InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc); - + InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc,m_dispatcher1); + m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds()); /// solve all the constraints for this island m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld()->getCollisionObjectArray(),&solverCallback); - + m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc); } @@ -539,7 +674,7 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) void btDiscreteDynamicsWorld::calculateSimulationIslands() { - BEGIN_PROFILE("calculateSimulationIslands"); + BT_PROFILE("calculateSimulationIslands"); getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher()); @@ -569,66 +704,85 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() //Store the island id in each body getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld()); - END_PROFILE("calculateSimulationIslands"); - + } -void btDiscreteDynamicsWorld::updateAabbs() +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" + +class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback { - BEGIN_PROFILE("updateAabbs"); - - btVector3 colorvec(1,0,0); - btTransform predictedTrans; - for ( int i=0;i=-m_allowedPenetration) + return 1.f; + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + //don't collide with itself + if (proxy0->m_clientObject == m_me) + return false; + + ///don't do CCD when the collision filters are not matching + if (!btCollisionWorld::ClosestConvexResultCallback::needsCollision(proxy0)) + return false; + + ///don't do CCD when there are already contact points (touching contact/penetration) + btAlignedObjectArray manifoldArray; + btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); + if (collisionPair) { - // if (body->IsActive() && (!body->IsStatic())) + if (collisionPair->m_algorithm) { - btPoint3 minAabb,maxAabb; - colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); - btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; - - //moving objects should be moderately sized, probably something wrong if not - if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12))) + manifoldArray.resize(0); + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + for (int j=0;jsetAabb(body->getBroadphaseHandle(),minAabb,maxAabb); - } else - { - //something went wrong, investigate - //this assert is unwanted in 3D modelers (danger of loosing work) - body->setActivationState(DISABLE_SIMULATION); - - static bool reportMe = true; - if (reportMe && m_debugDrawer) - { - reportMe = false; - m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation"); - m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n"); - m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n"); - m_debugDrawer->reportErrorWarning("Thanks.\n"); - } - - - } - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) - { - m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec); + btPersistentManifold* manifold = manifoldArray[j]; + if (manifold->getNumContacts()>0) + return false; } } } + return true; } - - END_PROFILE("updateAabbs"); -} + +}; + +///internal debugging variable. this value shouldn't be too high +int gNumClampedCcdMotions=0; + +//#include "stdio.h" void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { - BEGIN_PROFILE("integrateTransforms"); + BT_PROFILE("integrateTransforms"); btTransform predictedTrans; for ( int i=0;isetHitFraction(1.f); + if (body->isActive() && (!body->isStaticOrKinematicObject())) { body->predictIntegratedTransform(timeStep, predictedTrans); + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + + if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + { + BT_PROFILE("CCD motion clamping"); + if (body->getCollisionShape()->isConvex()) + { + gNumClampedCcdMotions++; + + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache()); + btConvexShape* convexShape = static_cast(body->getCollisionShape()); + btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults); + if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) + { + body->setHitFraction(sweepResults.m_closestHitFraction); + body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); + body->setHitFraction(0.f); +// printf("clamped integration to hit fraction = %f\n",fraction); + } + } + } + body->proceedToTransform( predictedTrans); } } } - END_PROFILE("integrateTransforms"); } void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { - BEGIN_PROFILE("predictUnconstraintMotion"); + BT_PROFILE("predictUnconstraintMotion"); for ( int i=0;iisActive()) { - body->applyForces( timeStep); body->integrateVelocities( timeStep); + //damping + body->applyDamping(timeStep); + body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } } } - END_PROFILE("predictUnconstraintMotion"); } void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep) { (void)timeStep; - #ifdef USE_QUICKPROF +#ifndef BT_NO_PROFILE + CProfileManager::Reset(); +#endif //BT_NO_PROFILE - //toggle btProfiler - if ( m_debugDrawer && m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_ProfileTimings) - { - if (!m_profileTimings) - { - m_profileTimings = 1; - // To disable profiling, simply comment out the following line. - static int counter = 0; - - char filename[128]; - sprintf(filename,"quickprof_bullet_timings%i.csv",counter++); - btProfiler::init(filename, btProfiler::BLOCK_CYCLE_SECONDS);//BLOCK_TOTAL_MICROSECONDS - } else - { - btProfiler::endProfilingCycle(); - } - - } else - { - if (m_profileTimings) - { - btProfiler::endProfilingCycle(); - - m_profileTimings = 0; - btProfiler::destroy(); - } - } -#endif //USE_QUICKPROF } @@ -827,27 +980,52 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = capsuleShape->getRadius(); btScalar halfHeight = capsuleShape->getHalfHeight(); + + int upAxis = capsuleShape->getUpAxis(); + + + btVector3 capStart(0.f,0.f,0.f); + capStart[upAxis] = -halfHeight; + + btVector3 capEnd(0.f,0.f,0.f); + capEnd[upAxis] = halfHeight; // Draw the ends { + btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * btVector3(0,halfHeight,0); + childTransform.getOrigin() = worldTransform * capStart; debugDrawSphere(radius, childTransform, color); } { btTransform childTransform = worldTransform; - childTransform.getOrigin() = worldTransform * btVector3(0,-halfHeight,0); + childTransform.getOrigin() = worldTransform * capEnd; debugDrawSphere(radius, childTransform, color); } // Draw some additional lines btVector3 start = worldTransform.getOrigin(); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(-radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(-radius,-halfHeight,0), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(radius,halfHeight,0),start+worldTransform.getBasis() * btVector3(radius,-halfHeight,0), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,-radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,-radius), color); - getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(0,halfHeight,radius),start+worldTransform.getBasis() * btVector3(0,-halfHeight,radius), color); + + capStart[(upAxis+1)%3] = radius; + capEnd[(upAxis+1)%3] = radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + capStart[(upAxis+1)%3] = -radius; + capEnd[(upAxis+1)%3] = -radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + + capStart[(upAxis+1)%3] = 0.f; + capEnd[(upAxis+1)%3] = 0.f; + + capStart[(upAxis+2)%3] = radius; + capEnd[(upAxis+2)%3] = radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + capStart[(upAxis+2)%3] = -radius; + capEnd[(upAxis+2)%3] = -radius; + getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color); + + break; } case CONE_SHAPE_PROXYTYPE: @@ -856,9 +1034,10 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btScalar radius = coneShape->getRadius();//+coneShape->getMargin(); btScalar height = coneShape->getHeight();//+coneShape->getMargin(); btVector3 start = worldTransform.getOrigin(); - // insert here Bullet 2.69 that fixes representation of cone + int upAxis= coneShape->getConeUpIndex(); + btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = height * btScalar(0.5); btVector3 offsetRadius(0,0,0); @@ -871,11 +1050,8 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color); getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color); - // buggy code that does not take into account the direction of the cone - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(radius,btScalar(0.),btScalar(-0.5)*height),color); - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(-radius,btScalar(0.),btScalar(-0.5)*height),color); - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),radius,btScalar(-0.5)*height),color); - //getDebugDrawer()->drawLine(start+worldTransform.getBasis() * btVector3(btScalar(0.),btScalar(0.),btScalar(0.5)*height),start+worldTransform.getBasis() * btVector3(btScalar(0.),-radius,btScalar(-0.5)*height),color); + + break; } @@ -884,7 +1060,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, const btCylinderShape* cylinder = static_cast(shape); int upAxis = cylinder->getUpAxis(); btScalar radius = cylinder->getRadius(); - btScalar halfHeight = cylinder->getHalfExtents()[upAxis]; + btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis]; btVector3 start = worldTransform.getOrigin(); btVector3 offsetHeight(0,0,0); offsetHeight[upAxis] = halfHeight; @@ -894,6 +1070,25 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color); break; } + + case STATIC_PLANE_PROXYTYPE: + { + const btStaticPlaneShape* staticPlaneShape = static_cast(shape); + btScalar planeConst = staticPlaneShape->getPlaneConstant(); + const btVector3& planeNormal = staticPlaneShape->getPlaneNormal(); + btVector3 planeOrigin = planeNormal * planeConst; + btVector3 vec0,vec1; + btPlaneSpace1(planeNormal,vec0,vec1); + btScalar vecLen = 100.f; + btVector3 pt0 = planeOrigin + vec0*vecLen; + btVector3 pt1 = planeOrigin - vec0*vecLen; + btVector3 pt2 = planeOrigin + vec1*vecLen; + btVector3 pt3 = planeOrigin - vec1*vecLen; + getDebugDrawer()->drawLine(worldTransform*pt0,worldTransform*pt1,color); + getDebugDrawer()->drawLine(worldTransform*pt2,worldTransform*pt3,color); + break; + + } default: { @@ -918,7 +1113,7 @@ void btDiscreteDynamicsWorld::debugDrawObject(const btTransform& worldTransform, btVector3 aabbMin(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); //DebugDrawcallback drawCallback; DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color); - convexMesh->getStridingMesh()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); + convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax); } @@ -950,12 +1145,18 @@ void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - delete m_constraintSolver; + btAlignedFree( m_constraintSolver); } m_ownsConstraintSolver = false; m_constraintSolver = solver; } +btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} + + int btDiscreteDynamicsWorld::getNumConstraints() const { return int(m_constraints.size()); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index 83b90bfeebc..d9e2652aaf6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -23,11 +23,11 @@ class btOverlappingPairCache; class btConstraintSolver; class btSimulationIslandManager; class btTypedConstraint; -#include "../ConstraintSolver/btContactSolverInfo.h" + class btRaycastVehicle; class btIDebugDraw; -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" ///btDiscreteDynamicsWorld provides discrete rigid body simulation @@ -42,7 +42,6 @@ protected: btAlignedObjectArray m_constraints; - btIDebugDraw* m_debugDrawer; btVector3 m_gravity; @@ -53,16 +52,14 @@ protected: bool m_ownsIslandManager; bool m_ownsConstraintSolver; - btContactSolverInfo m_solverInfo; - - + btAlignedObjectArray m_vehicles; int m_profileTimings; - void predictUnconstraintMotion(btScalar timeStep); + virtual void predictUnconstraintMotion(btScalar timeStep); - void integrateTransforms(btScalar timeStep); + virtual void integrateTransforms(btScalar timeStep); void calculateSimulationIslands(); @@ -86,14 +83,13 @@ public: ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those - btDiscreteDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); virtual ~btDiscreteDynamicsWorld(); ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - virtual void updateAabbs(); void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false); @@ -118,17 +114,9 @@ public: return this; } - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - } - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } virtual void setGravity(const btVector3& gravity); + virtual btVector3 getGravity () const; virtual void addRigidBody(btRigidBody* body); @@ -138,7 +126,11 @@ public: void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color); + virtual void debugDrawWorld(); + virtual void setConstraintSolver(btConstraintSolver* solver); + + virtual btConstraintSolver* getConstraintSolver(); virtual int getNumConstraints() const; @@ -146,11 +138,21 @@ public: virtual const btTypedConstraint* getConstraint(int index) const; - btContactSolverInfo& getSolverInfo() + + virtual btDynamicsWorldType getWorldType() const { - return m_solverInfo; + return BT_DISCRETE_DYNAMICS_WORLD; } + + ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep. + virtual void clearForces(); + ///apply gravity, call this once per timestep + virtual void applyGravity(); + + virtual void setNumTasks(int numTasks) + { + } }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index 65b63fad4b5..929e24d337c 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -16,20 +16,39 @@ subject to the following restrictions: #ifndef BT_DYNAMICS_WORLD_H #define BT_DYNAMICS_WORLD_H -#include "../../BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" + class btTypedConstraint; class btRaycastVehicle; class btConstraintSolver; +class btDynamicsWorld; +/// Type for the callback for each tick +typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep); -///btDynamicsWorld is the baseclass for several dynamics implementation, basic, discrete, parallel, and continuous +enum btDynamicsWorldType +{ + BT_SIMPLE_DYNAMICS_WORLD=1, + BT_DISCRETE_DYNAMICS_WORLD=2, + BT_CONTINUOUS_DYNAMICS_WORLD=3 +}; + +///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc. class btDynamicsWorld : public btCollisionWorld { - public: + +protected: + btInternalTickCallback m_internalTickCallback; + void* m_worldUserInfo; + + btContactSolverInfo m_solverInfo; + +public: - btDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache) - :btCollisionWorld(dispatcher,pairCache) + btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration) + :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0), m_worldUserInfo(0) { } @@ -37,34 +56,37 @@ class btDynamicsWorld : public btCollisionWorld { } - ///stepSimulation proceeds the simulation over timeStep units - ///if maxSubSteps > 0, it will interpolate time steps + ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds. + ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'. + ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'. + ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant. virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; - virtual void updateAabbs() = 0; + virtual void debugDrawWorld() = 0; - virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) { (void)constraint;}; + virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) + { + (void)constraint; (void)disableCollisionsBetweenLinkedBodies; + } - virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}; + virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;} - virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; + virtual void addVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} - virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;}; - - - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) = 0; - - virtual btIDebugDraw* getDebugDrawer() = 0; + virtual void removeVehicle(btRaycastVehicle* vehicle) {(void)vehicle;} //once a rigidbody is added to the dynamics world, it will get this gravity assigned //existing rigidbodies in the world get gravity assigned too, during this method virtual void setGravity(const btVector3& gravity) = 0; + virtual btVector3 getGravity () const = 0; virtual void addRigidBody(btRigidBody* body) = 0; virtual void removeRigidBody(btRigidBody* body) = 0; virtual void setConstraintSolver(btConstraintSolver* solver) = 0; + + virtual btConstraintSolver* getConstraintSolver() = 0; virtual int getNumConstraints() const { return 0; } @@ -72,7 +94,35 @@ class btDynamicsWorld : public btCollisionWorld virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; } + virtual btDynamicsWorldType getWorldType() const=0; + + virtual void clearForces() = 0; + + /// Set the callback for when an internal tick (simulation substep) happens, optional user info + void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0) + { + m_internalTickCallback = cb; + m_worldUserInfo = worldUserInfo; + } + + void setWorldUserInfo(void* worldUserInfo) + { + m_worldUserInfo = worldUserInfo; + } + + void* getWorldUserInfo() const + { + return m_worldUserInfo; + } + + btContactSolverInfo& getSolverInfo() + { + return m_solverInfo; + } + + }; #endif //BT_DYNAMICS_WORLD_H + diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp index 9ed3579d89c..e2afb687ac6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.cpp @@ -20,36 +20,53 @@ subject to the following restrictions: #include "LinearMath/btMotionState.h" #include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" -btScalar gLinearAirDamping = btScalar(1.); //'temporarily' global variables btScalar gDeactivationTime = btScalar(2.); bool gDisableDeactivation = false; - -btScalar gLinearSleepingThreshold = btScalar(0.8); -btScalar gAngularSleepingThreshold = btScalar(1.0); static int uniqueId = 0; -btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_angularFactor(btScalar(1.)), - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_optionalMotionState(motionState), - m_contactSolverType(0), - m_frictionSolverType(0) + +btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) +{ + setupRigidBody(constructionInfo); +} + +btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia) +{ + btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia); + setupRigidBody(cinfo); +} + +void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo) { - if (motionState) + m_internalType=CO_RIGID_BODY; + + m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + m_angularFactor = btScalar(1.); + m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)); + m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)), + m_linearDamping = btScalar(0.); + m_angularDamping = btScalar(0.5); + m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold; + m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold; + m_optionalMotionState = constructionInfo.m_motionState; + m_contactSolverType = 0; + m_frictionSolverType = 0; + m_additionalDamping = constructionInfo.m_additionalDamping; + m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor; + m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr; + m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr; + m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor; + + if (m_optionalMotionState) { - motionState->getWorldTransform(m_worldTransform); + m_optionalMotionState->getWorldTransform(m_worldTransform); } else { - m_worldTransform = btTransform::getIdentity(); + m_worldTransform = constructionInfo.m_startWorldTransform; } m_interpolationWorldTransform = m_worldTransform; @@ -57,90 +74,21 @@ btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionS m_interpolationAngularVelocity.setValue(0,0,0); //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; + m_friction = constructionInfo.m_friction; + m_restitution = constructionInfo.m_restitution; - m_collisionShape = collisionShape; + setCollisionShape( constructionInfo.m_collisionShape ); m_debugBodyId = uniqueId++; - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); + setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia); + setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping); updateInertiaTensor(); } -#ifdef OBSOLETE_MOTIONSTATE_LESS -btRigidBody::btRigidBody( btScalar mass,const btTransform& worldTransform,btCollisionShape* collisionShape,const btVector3& localInertia,btScalar linearDamping,btScalar angularDamping,btScalar friction,btScalar restitution) -: - m_gravity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalForce(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_totalTorque(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_linearVelocity(btScalar(0.0), btScalar(0.0), btScalar(0.0)), - m_angularVelocity(btScalar(0.),btScalar(0.),btScalar(0.)), - m_linearDamping(btScalar(0.)), - m_angularDamping(btScalar(0.5)), - m_optionalMotionState(0), - m_contactSolverType(0), - m_frictionSolverType(0) -{ - - m_worldTransform = worldTransform; - m_interpolationWorldTransform = m_worldTransform; - m_interpolationLinearVelocity.setValue(0,0,0); - m_interpolationAngularVelocity.setValue(0,0,0); - - //moved to btCollisionObject - m_friction = friction; - m_restitution = restitution; - - m_collisionShape = collisionShape; - m_debugBodyId = uniqueId++; - - //m_internalOwner is to allow upcasting from collision object to rigid body - m_internalOwner = this; - - setMassProps(mass, localInertia); - setDamping(linearDamping, angularDamping); - updateInertiaTensor(); - -} - -#endif //OBSOLETE_MOTIONSTATE_LESS - - - - -//#define EXPERIMENTAL_JITTER_REMOVAL 1 -#ifdef EXPERIMENTAL_JITTER_REMOVAL -//Bullet 2.20b has experimental damping code to reduce jitter just before objects fall asleep/deactivate -//doesn't work very well yet (value 0 disabled this damping) -//note there this influences deactivation thresholds! -btScalar gClippedAngvelThresholdSqr = btScalar(0.01); -btScalar gClippedLinearThresholdSqr = btScalar(0.01); -#endif //EXPERIMENTAL_JITTER_REMOVAL - -btScalar gJitterVelocityDampingFactor = btScalar(0.7); void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) { - -#ifdef EXPERIMENTAL_JITTER_REMOVAL - //if (wantsSleeping()) - { - //clip to avoid jitter - if ((m_angularVelocity.length2() < gClippedAngvelThresholdSqr) && - (m_linearVelocity.length2() < gClippedLinearThresholdSqr)) - { - m_angularVelocity *= gJitterVelocityDampingFactor; - m_linearVelocity *= gJitterVelocityDampingFactor; - } - } - -#endif //EXPERIMENTAL_JITTER_REMOVAL - btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform); } @@ -191,50 +139,63 @@ void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping) -#include + +///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping +void btRigidBody::applyDamping(btScalar timeStep) +{ + m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); + + if (m_additionalDamping) + { + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) && + (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr)) + { + m_angularVelocity *= m_additionalDampingFactor; + m_linearVelocity *= m_additionalDampingFactor; + } + + + btScalar speed = m_linearVelocity.length(); + if (speed < m_linearDamping) + { + btScalar dampVel = btScalar(0.005); + if (speed > dampVel) + { + btVector3 dir = m_linearVelocity.normalized(); + m_linearVelocity -= dir * dampVel; + } else + { + m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + + btScalar angSpeed = m_angularVelocity.length(); + if (angSpeed < m_angularDamping) + { + btScalar angDampVel = btScalar(0.005); + if (angSpeed > angDampVel) + { + btVector3 dir = m_angularVelocity.normalized(); + m_angularVelocity -= dir * angDampVel; + } else + { + m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); + } + } + } +} -void btRigidBody::applyForces(btScalar step) +void btRigidBody::applyGravity() { if (isStaticOrKinematicObject()) return; applyCentralForce(m_gravity); - - m_linearVelocity *= GEN_clamped((btScalar(1.) - step * gLinearAirDamping * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); - m_angularVelocity *= GEN_clamped((btScalar(1.) - step * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); -#define FORCE_VELOCITY_DAMPING 1 -#ifdef FORCE_VELOCITY_DAMPING - btScalar speed = m_linearVelocity.length(); - if (speed < m_linearDamping) - { - btScalar dampVel = btScalar(0.005); - if (speed > dampVel) - { - btVector3 dir = m_linearVelocity.normalized(); - m_linearVelocity -= dir * dampVel; - } else - { - m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } - - btScalar angSpeed = m_angularVelocity.length(); - if (angSpeed < m_angularDamping) - { - btScalar angDampVel = btScalar(0.005); - if (angSpeed > angDampVel) - { - btVector3 dir = m_angularVelocity.normalized(); - m_angularVelocity -= dir * angDampVel; - } else - { - m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.)); - } - } -#endif //FORCE_VELOCITY_DAMPING - } void btRigidBody::proceedToTransform(const btTransform& newTrans) @@ -285,7 +246,6 @@ void btRigidBody::integrateVelocities(btScalar step) m_angularVelocity *= (MAX_ANGVEL/step) /angvel; } - clearForces(); } btQuaternion btRigidBody::getOrientation() const diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h index 0707595d48e..4596f90a00f 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btRigidBody.h @@ -16,27 +16,29 @@ subject to the following restrictions: #ifndef RIGIDBODY_H #define RIGIDBODY_H -#include "../../LinearMath/btAlignedObjectArray.h" -#include "../../LinearMath/btPoint3.h" -#include "../../LinearMath/btTransform.h" -#include "../../BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" -#include "../../BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btTransform.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" class btCollisionShape; class btMotionState; class btTypedConstraint; -extern btScalar gLinearAirDamping; - extern btScalar gDeactivationTime; extern bool gDisableDeactivation; -extern btScalar gLinearSleepingThreshold; -extern btScalar gAngularSleepingThreshold; -/// btRigidBody class for btRigidBody Dynamics -/// +///btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape. +///It is recommended for performance and memory use to share btCollisionShape objects whenever possible. +///There are 3 types of rigid bodies: +///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics. +///- B) Fixed objects with zero mass. They are not moving (basically collision objects) +///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform. +///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time. +///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects) class btRigidBody : public btCollisionObject { @@ -53,7 +55,16 @@ class btRigidBody : public btCollisionObject btScalar m_linearDamping; btScalar m_angularDamping; - + + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; //m_optionalMotionState allows to automatic synchronize the world transform for active objects btMotionState* m_optionalMotionState; @@ -63,12 +74,85 @@ class btRigidBody : public btCollisionObject public: -#ifdef OBSOLETE_MOTIONSTATE_LESS - //not supported, please use btMotionState - btRigidBody(btScalar mass, const btTransform& worldTransform, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); -#endif //OBSOLETE_MOTIONSTATE_LESS - btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0),btScalar linearDamping=btScalar(0.),btScalar angularDamping=btScalar(0.),btScalar friction=btScalar(0.5),btScalar restitution=btScalar(0.)); + ///btRigidBodyConstructionInfo provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body. + ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument) + ///You can use the motion state to synchronize the world transform between physics and graphics objects. + ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state, + ///m_startWorldTransform is only used when you don't provide a motion state. + struct btRigidBodyConstructionInfo + { + btScalar m_mass; + + ///When a motionState is provided, the rigid body will initialize its world transform from the motion state + ///In this case, m_startWorldTransform is ignored. + btMotionState* m_motionState; + btTransform m_startWorldTransform; + + btCollisionShape* m_collisionShape; + btVector3 m_localInertia; + btScalar m_linearDamping; + btScalar m_angularDamping; + + ///best simulation results when friction is non-zero + btScalar m_friction; + ///best simulation results using zero restitution. + btScalar m_restitution; + + btScalar m_linearSleepingThreshold; + btScalar m_angularSleepingThreshold; + + //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc. + //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete + bool m_additionalDamping; + btScalar m_additionalDampingFactor; + btScalar m_additionalLinearDampingThresholdSqr; + btScalar m_additionalAngularDampingThresholdSqr; + btScalar m_additionalAngularDampingFactor; + + + btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)): + m_mass(mass), + m_motionState(motionState), + m_collisionShape(collisionShape), + m_localInertia(localInertia), + m_linearDamping(btScalar(0.)), + m_angularDamping(btScalar(0.)), + m_friction(btScalar(0.5)), + m_restitution(btScalar(0.)), + m_linearSleepingThreshold(btScalar(0.8)), + m_angularSleepingThreshold(btScalar(1.f)), + m_additionalDamping(false), + m_additionalDampingFactor(btScalar(0.005)), + m_additionalLinearDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingThresholdSqr(btScalar(0.01)), + m_additionalAngularDampingFactor(btScalar(0.01)) + { + m_startWorldTransform.setIdentity(); + } + }; + + ///btRigidBody constructor using construction info + btRigidBody( const btRigidBodyConstructionInfo& constructionInfo); + + ///btRigidBody constructor for backwards compatibility. + ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo) + btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)); + + + virtual ~btRigidBody() + { + //No constraints should point to this rigidbody + //Remove constraints from the dynamics world before you delete the related rigidbodies. + btAssert(m_constraintRefs.size()==0); + } + +protected: + + ///setupRigidBody is only used internally by the constructor + void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo); + +public: void proceedToTransform(const btTransform& newTrans); @@ -76,11 +160,15 @@ public: ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast static const btRigidBody* upcast(const btCollisionObject* colObj) { - return (const btRigidBody*)colObj->getInternalOwner(); + if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY) + return (const btRigidBody*)colObj; + return 0; } static btRigidBody* upcast(btCollisionObject* colObj) { - return (btRigidBody*)colObj->getInternalOwner(); + if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY) + return (btRigidBody*)colObj; + return 0; } /// continuous collision detection needs prediction @@ -88,8 +176,7 @@ public: void saveKinematicState(btScalar step); - - void applyForces(btScalar step); + void applyGravity(); void setGravity(const btVector3& acceleration); @@ -99,12 +186,34 @@ public: } void setDamping(btScalar lin_damping, btScalar ang_damping); - - inline const btCollisionShape* getCollisionShape() const { + + btScalar getLinearDamping() const + { + return m_linearDamping; + } + + btScalar getAngularDamping() const + { + return m_angularDamping; + } + + btScalar getLinearSleepingThreshold() const + { + return m_linearSleepingThreshold; + } + + btScalar getAngularSleepingThreshold() const + { + return m_angularSleepingThreshold; + } + + void applyDamping(btScalar timeStep); + + SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_collisionShape; } - inline btCollisionShape* getCollisionShape() { + SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() { return m_collisionShape; } @@ -134,6 +243,12 @@ public: m_invInertiaLocal = diagInvInertia; } + void setSleepingThresholds(btScalar linear,btScalar angular) + { + m_linearSleepingThreshold = linear; + m_angularSleepingThreshold = angular; + } + void applyTorque(const btVector3& torque) { m_totalTorque += torque; @@ -142,7 +257,7 @@ public: void applyForce(const btVector3& force, const btVector3& rel_pos) { applyCentralForce(force); - applyTorque(rel_pos.cross(force)); + applyTorque(rel_pos.cross(force)*m_angularFactor); } void applyCentralImpulse(const btVector3& impulse) @@ -168,7 +283,7 @@ public: } //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position - inline void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) + SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude) { if (m_inverseMass != btScalar(0.)) { @@ -238,7 +353,7 @@ public: - inline btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const + SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btPoint3& pos, const btVector3& normal) const { btVector3 r0 = pos - getCenterOfMassPosition(); @@ -250,19 +365,19 @@ public: } - inline btScalar computeAngularImpulseDenominator(const btVector3& axis) const + SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const { btVector3 vec = axis * getInvInertiaTensorWorld(); return axis.dot(vec); } - inline void updateDeactivation(btScalar timeStep) + SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep) { if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION)) return; - if ((getLinearVelocity().length2() < gLinearSleepingThreshold*gLinearSleepingThreshold) && - (getAngularVelocity().length2() < gAngularSleepingThreshold*gAngularSleepingThreshold)) + if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) && + (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold)) { m_deactivationTime += timeStep; } else @@ -273,7 +388,7 @@ public: } - inline bool wantsSleeping() + SIMD_FORCE_INLINE bool wantsSleeping() { if (getActivationState() == DISABLE_DEACTIVATION) @@ -348,6 +463,16 @@ public: void addConstraintRef(btTypedConstraint* c); void removeConstraintRef(btTypedConstraint* c); + btTypedConstraint* getConstraintRef(int index) + { + return m_constraintRefs[index]; + } + + int getNumConstraintRefs() + { + return m_constraintRefs.size(); + } + int m_debugBodyId; }; diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp index 4ebcb8e7517..3be04d1a4ad 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp @@ -27,16 +27,19 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" void btBulletDynamicsProbe () {} +extern "C" +{ + void btBulletDynamicsProbe (); + void btBulletDynamicsProbe () {} +} -btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver) -:btDynamicsWorld(dispatcher,pairCache), +btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration), m_constraintSolver(constraintSolver), m_ownsConstraintSolver(false), -m_debugDrawer(0), m_gravity(0,0,-10) { @@ -46,7 +49,7 @@ m_gravity(0,0,-10) btSimpleDynamicsWorld::~btSimpleDynamicsWorld() { if (m_ownsConstraintSolver) - delete m_constraintSolver; + btAlignedFree( m_constraintSolver); } int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep) @@ -74,8 +77,9 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b btContactSolverInfo infoGlobal; infoGlobal.m_timeStep = timeStep; - - m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc); + m_constraintSolver->prepareSolve(0,numManifolds); + m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1); + m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc); } ///integrate transforms @@ -85,10 +89,27 @@ int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, b synchronizeMotionStates(); + clearForces(); + return 1; } +void btSimpleDynamicsWorld::clearForces() +{ + //todo: iterate over awake simulation islands! + for ( int i=0;iclearForces(); + } + } +} + void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) { @@ -104,6 +125,11 @@ void btSimpleDynamicsWorld::setGravity(const btVector3& gravity) } } +btVector3 btSimpleDynamicsWorld::getGravity () const +{ + return m_gravity; +} + void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body) { removeCollisionObject(body); @@ -133,7 +159,7 @@ void btSimpleDynamicsWorld::updateAabbs() btPoint3 minAabb,maxAabb; colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); btBroadphaseInterface* bp = getBroadphase(); - bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb); + bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1); } } } @@ -171,8 +197,9 @@ void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) { if (body->isActive()) { - body->applyForces( timeStep); + body->applyGravity(); body->integrateVelocities( timeStep); + body->applyDamping(timeStep); body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform()); } } @@ -204,8 +231,13 @@ void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver) { if (m_ownsConstraintSolver) { - delete m_constraintSolver; + btAlignedFree(m_constraintSolver); } m_ownsConstraintSolver = false; m_constraintSolver = solver; } + +btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver() +{ + return m_constraintSolver; +} diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h index 25f4ccd8e68..5c56fdf1327 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h @@ -22,11 +22,8 @@ class btDispatcher; class btOverlappingPairCache; class btConstraintSolver; -///btSimpleDynamicsWorld demonstrates very basic usage of Bullet rigid body dynamics -///It can be used for basic simulations, and as a starting point for porting Bullet -///btSimpleDynamicsWorld lacks object deactivation, island management and other concepts. -///For more complicated simulations, btDiscreteDynamicsWorld and btContinuousDynamicsWorld are recommended -///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController +///btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds. +///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished). class btSimpleDynamicsWorld : public btDynamicsWorld { protected: @@ -35,8 +32,6 @@ protected: bool m_ownsConstraintSolver; - btIDebugDraw* m_debugDrawer; - void predictUnconstraintMotion(btScalar timeStep); void integrateTransforms(btScalar timeStep); @@ -48,25 +43,17 @@ public: ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver - btSimpleDynamicsWorld(btDispatcher* dispatcher,btOverlappingPairCache* pairCache,btConstraintSolver* constraintSolver); + btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); virtual ~btSimpleDynamicsWorld(); ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.)); - virtual void setDebugDrawer(btIDebugDraw* debugDrawer) - { - m_debugDrawer = debugDrawer; - }; - - virtual btIDebugDraw* getDebugDrawer() - { - return m_debugDrawer; - } - virtual void setGravity(const btVector3& gravity); + virtual btVector3 getGravity () const; + virtual void addRigidBody(btRigidBody* body); virtual void removeRigidBody(btRigidBody* body); @@ -77,6 +64,15 @@ public: virtual void setConstraintSolver(btConstraintSolver* solver); + virtual btConstraintSolver* getConstraintSolver(); + + virtual btDynamicsWorldType getWorldType() const + { + return BT_SIMPLE_DYNAMICS_WORLD; + } + + virtual void clearForces(); + }; #endif //BT_SIMPLE_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp index d53de7f3687..fe65245c2a1 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.cpp @@ -23,12 +23,11 @@ #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" - - static btRigidBody s_fixedObject( 0,0,0); btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis, btVehicleRaycaster* raycaster ) -:m_vehicleRaycaster(raycaster), +: btTypedConstraint(VEHICLE_CONSTRAINT_TYPE), +m_vehicleRaycaster(raycaster), m_pitchControl(btScalar(0.)) { m_chassisBody = chassis; @@ -487,6 +486,7 @@ struct btWheelContactPoint }; +btScalar calcRollingFriction(btWheelContactPoint& contactPoint); btScalar calcRollingFriction(btWheelContactPoint& contactPoint) { @@ -507,8 +507,8 @@ btScalar calcRollingFriction(btWheelContactPoint& contactPoint) // calculate j that moves us to zero relative velocity j1 = -vrel * contactPoint.m_jacDiagABInv; - GEN_set_min(j1, maxImpulse); - GEN_set_max(j1, -maxImpulse); + btSetMin(j1, maxImpulse); + btSetMax(j1, -maxImpulse); return j1; } @@ -525,11 +525,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) if (!numWheel) return; - - btVector3* forwardWS = new btVector3[numWheel]; - btVector3* axle = new btVector3[numWheel]; - btScalar* forwardImpulse = new btScalar[numWheel]; - btScalar* sideImpulse = new btScalar[numWheel]; + m_forwardWS.resize(numWheel); + m_axle.resize(numWheel); + m_forwardImpulse.resize(numWheel); + m_sideImpulse.resize(numWheel); int numWheelsOnGround = 0; @@ -541,8 +540,8 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; if (groundObject) numWheelsOnGround++; - sideImpulse[i] = btScalar(0.); - forwardImpulse[i] = btScalar(0.); + m_sideImpulse[i] = btScalar(0.); + m_forwardImpulse[i] = btScalar(0.); } @@ -561,25 +560,25 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) const btTransform& wheelTrans = getWheelTransformWS( i ); btMatrix3x3 wheelBasis0 = wheelTrans.getBasis(); - axle[i] = btVector3( + m_axle[i] = btVector3( wheelBasis0[0][m_indexRightAxis], wheelBasis0[1][m_indexRightAxis], wheelBasis0[2][m_indexRightAxis]); const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS; - btScalar proj = axle[i].dot(surfNormalWS); - axle[i] -= surfNormalWS * proj; - axle[i] = axle[i].normalize(); + btScalar proj = m_axle[i].dot(surfNormalWS); + m_axle[i] -= surfNormalWS * proj; + m_axle[i] = m_axle[i].normalize(); - forwardWS[i] = surfNormalWS.cross(axle[i]); - forwardWS[i].normalize(); + m_forwardWS[i] = surfNormalWS.cross(m_axle[i]); + m_forwardWS[i].normalize(); resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS, *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, - btScalar(0.), axle[i],sideImpulse[i],timeStep); + btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep); - sideImpulse[i] *= sideFrictionStiffness2; + m_sideImpulse[i] *= sideFrictionStiffness2; } @@ -608,7 +607,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) { btScalar defaultRollingFrictionImpulse = 0.f; btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; - btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,forwardWS[wheel],maxImpulse); + btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse); rollingFriction = calcRollingFriction(contactPt); } } @@ -618,7 +617,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) - forwardImpulse[wheel] = btScalar(0.); + m_forwardImpulse[wheel] = btScalar(0.); m_wheelInfo[wheel].m_skidInfo= btScalar(1.); if (groundObject) @@ -631,10 +630,10 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btScalar maximpSquared = maximp * maximpSide; - forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; + m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; - btScalar x = (forwardImpulse[wheel] ) * fwdFactor; - btScalar y = (sideImpulse[wheel] ) * sideFactor; + btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor; + btScalar y = (m_sideImpulse[wheel] ) * sideFactor; btScalar impulseSquared = (x*x + y*y); @@ -658,12 +657,12 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) { for (int wheel = 0;wheel < getNumWheels(); wheel++) { - if (sideImpulse[wheel] != btScalar(0.)) + if (m_sideImpulse[wheel] != btScalar(0.)) { if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) { - forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; - sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; + m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; } } } @@ -678,11 +677,11 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS - m_chassisBody->getCenterOfMassPosition(); - if (forwardImpulse[wheel] != btScalar(0.)) + if (m_forwardImpulse[wheel] != btScalar(0.)) { - m_chassisBody->applyImpulse(forwardWS[wheel]*(forwardImpulse[wheel]),rel_pos); + m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); } - if (sideImpulse[wheel] != btScalar(0.)) + if (m_sideImpulse[wheel] != btScalar(0.)) { class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; @@ -690,7 +689,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) groundObject->getCenterOfMassPosition(); - btVector3 sideImp = axle[wheel] * sideImpulse[wheel]; + btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; rel_pos[2] *= wheelInfo.m_rollInfluence; m_chassisBody->applyImpulse(sideImp,rel_pos); @@ -701,10 +700,7 @@ void btRaycastVehicle::updateFriction(btScalar timeStep) } } - delete []forwardWS; - delete [] axle; - delete[]forwardImpulse; - delete[] sideImpulse; + } @@ -716,11 +712,11 @@ void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& m_dynamicsWorld->rayTest(from, to, rayCallback); - if (rayCallback.HasHit()) + if (rayCallback.hasHit()) { btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); - if (body) + if (body && body->hasContactResponse()) { result.m_hitPointInWorld = rayCallback.m_hitPointWorld; result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h index f4249599615..8361dcabe4b 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btRaycastVehicle.h @@ -11,11 +11,11 @@ #ifndef RAYCASTVEHICLE_H #define RAYCASTVEHICLE_H -#include "../Dynamics/btRigidBody.h" -#include "../ConstraintSolver/btTypedConstraint.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" +#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h" #include "btVehicleRaycaster.h" class btDynamicsWorld; -#include "../../LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btAlignedObjectArray.h" #include "btWheelInfo.h" class btVehicleTuning; @@ -23,6 +23,12 @@ class btVehicleTuning; ///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle. class btRaycastVehicle : public btTypedConstraint { + + btAlignedObjectArray m_forwardWS; + btAlignedObjectArray m_axle; + btAlignedObjectArray m_forwardImpulse; + btAlignedObjectArray m_sideImpulse; + public: class btVehicleTuning { @@ -114,7 +120,7 @@ public: void updateSuspension(btScalar deltaTime); - void updateFriction(btScalar timeStep); + virtual void updateFriction(btScalar timeStep); diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h index 64a47fcaada..5112ce6d420 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btVehicleRaycaster.h @@ -11,7 +11,7 @@ #ifndef VEHICLE_RAYCASTER_H #define VEHICLE_RAYCASTER_H -#include "../../LinearMath/btVector3.h" +#include "LinearMath/btVector3.h" /// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting struct btVehicleRaycaster diff --git a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h index 2e349b3fde4..ac2729f4fd7 100644 --- a/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h +++ b/extern/bullet2/src/BulletDynamics/Vehicle/btWheelInfo.h @@ -11,8 +11,8 @@ #ifndef WHEEL_INFO_H #define WHEEL_INFO_H -#include "../../LinearMath/btVector3.h" -#include "../../LinearMath/btTransform.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" class btRigidBody; diff --git a/extern/bullet2/src/BulletSoftBody/CMakeLists.txt b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt new file mode 100644 index 00000000000..a725e10ff77 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/CMakeLists.txt @@ -0,0 +1,21 @@ + +INCLUDE_DIRECTORIES( +${BULLET_PHYSICS_SOURCE_DIR}/src } +) + +ADD_LIBRARY(LibBulletSoftBody + btSoftBody.cpp + btSoftBody.h + btSoftBodyHelpers.cpp + btSparseSDF.h + btSoftBodyHelpers.h + btSoftBodyRigidBodyCollisionConfiguration.cpp + btSoftRigidCollisionAlgorithm.cpp + btSoftRigidCollisionAlgorithm.h + btSoftSoftCollisionAlgorithm.cpp + btSoftSoftCollisionAlgorithm.h + btSoftBodyConcaveCollisionAlgorithm.cpp + btSoftBodyConcaveCollisionAlgorithm.h + btSoftRigidDynamicsWorld.h + btSoftRigidDynamicsWorld.cpp +) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp new file mode 100644 index 00000000000..91b9d6f1bbd --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -0,0 +1,2594 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#include "btSoftBodyInternals.h" + +// +btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo,int node_count, const btVector3* x, const btScalar* m) +:m_worldInfo(worldInfo) +{ + /* Init */ + m_internalType = CO_SOFT_BODY; + m_cfg.aeromodel = eAeroModel::V_Point; + m_cfg.kVCF = 1; + m_cfg.kDG = 0; + m_cfg.kLF = 0; + m_cfg.kDP = 0; + m_cfg.kPR = 0; + m_cfg.kVC = 0; + m_cfg.kDF = (btScalar)0.2; + m_cfg.kMT = 0; + m_cfg.kCHR = (btScalar)1.0; + m_cfg.kKHR = (btScalar)0.1; + m_cfg.kSHR = (btScalar)1.0; + m_cfg.kAHR = (btScalar)0.7; + m_cfg.kSRHR_CL = (btScalar)0.1; + m_cfg.kSKHR_CL = (btScalar)1; + m_cfg.kSSHR_CL = (btScalar)0.5; + m_cfg.kSR_SPLT_CL = (btScalar)0.5; + m_cfg.kSK_SPLT_CL = (btScalar)0.5; + m_cfg.kSS_SPLT_CL = (btScalar)0.5; + m_cfg.maxvolume = (btScalar)1; + m_cfg.timescale = 1; + m_cfg.viterations = 0; + m_cfg.piterations = 1; + m_cfg.diterations = 0; + m_cfg.citerations = 4; + m_cfg.collisions = fCollision::Default; + m_pose.m_bvolume = false; + m_pose.m_bframe = false; + m_pose.m_volume = 0; + m_pose.m_com = btVector3(0,0,0); + m_pose.m_rot.setIdentity(); + m_pose.m_scl.setIdentity(); + m_tag = 0; + m_timeacc = 0; + m_bUpdateRtCst = true; + m_bounds[0] = btVector3(0,0,0); + m_bounds[1] = btVector3(0,0,0); + m_worldTransform.setIdentity(); + setSolver(eSolverPresets::Positions); + /* Default material */ + Material* pm=appendMaterial(); + pm->m_kLST = 1; + pm->m_kAST = 1; + pm->m_kVST = 1; + pm->m_flags = fMaterial::Default; + /* Collision shape */ + ///for now, create a collision shape internally + setCollisionShape(new btSoftBodyCollisionShape(this)); + m_collisionShape->setMargin(0.25); + /* Nodes */ + const btScalar margin=getCollisionShape()->getMargin(); + m_nodes.resize(node_count); + for(int i=0,ni=node_count;i0?1/n.m_im:0; + n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); + n.m_material= pm; + } + updateBounds(); + + +} + +// +btSoftBody::~btSoftBody() +{ + //for now, delete the internal shape + delete m_collisionShape; + int i; + + releaseClusters(); + for(i=0;i0) + *pm=*m_materials[0]; + else + ZeroInitialize(*pm); +m_materials.push_back(pm); +return(pm); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + const btVector4& c, + Node* n0, + Node* n1, + Node* n2, + Node* n3) +{ +Note n; +ZeroInitialize(n); +n.m_rank = 0; +n.m_text = text; +n.m_offset = o; +n.m_coords[0] = c.x(); +n.m_coords[1] = c.y(); +n.m_coords[2] = c.z(); +n.m_coords[3] = c.w(); +n.m_nodes[0] = n0;n.m_rank+=n0?1:0; +n.m_nodes[1] = n1;n.m_rank+=n1?1:0; +n.m_nodes[2] = n2;n.m_rank+=n2?1:0; +n.m_nodes[3] = n3;n.m_rank+=n3?1:0; +m_notes.push_back(n); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Node* feature) +{ +appendNote(text,o,btVector4(1,0,0,0),feature); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Link* feature) +{ +static const btScalar w=1/(btScalar)2; +appendNote(text,o,btVector4(w,w,0,0), feature->m_n[0], + feature->m_n[1]); +} + +// +void btSoftBody::appendNote( const char* text, + const btVector3& o, + Face* feature) +{ +static const btScalar w=1/(btScalar)3; +appendNote(text,o,btVector4(w,w,w,0), feature->m_n[0], + feature->m_n[1], + feature->m_n[2]); +} + +// +void btSoftBody::appendNode( const btVector3& x,btScalar m) +{ +if(m_nodes.capacity()==m_nodes.size()) + { + pointersToIndices(); + m_nodes.reserve(m_nodes.size()*2+1); + indicesToPointers(); + } +const btScalar margin=getCollisionShape()->getMargin(); +m_nodes.push_back(Node()); +Node& n=m_nodes[m_nodes.size()-1]; +ZeroInitialize(n); +n.m_x = x; +n.m_q = n.m_x; +n.m_im = m>0?1/m:0; +n.m_material = m_materials[0]; +n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x,margin),&n); +} + +// +void btSoftBody::appendLink(int model,Material* mat) +{ +Link l; +if(model>=0) + l=m_links[model]; + else + { ZeroInitialize(l);l.m_material=mat?mat:m_materials[0]; } +m_links.push_back(l); +} + +// +void btSoftBody::appendLink( int node0, + int node1, + Material* mat, + bool bcheckexist) +{ + appendLink(&m_nodes[node0],&m_nodes[node1],mat,bcheckexist); +} + +// +void btSoftBody::appendLink( Node* node0, + Node* node1, + Material* mat, + bool bcheckexist) +{ + if((!bcheckexist)||(!checkLink(node0,node1))) + { + appendLink(-1,mat); + Link& l=m_links[m_links.size()-1]; + l.m_n[0] = node0; + l.m_n[1] = node1; + l.m_rl = (l.m_n[0]->m_x-l.m_n[1]->m_x).length(); + m_bUpdateRtCst=true; + } +} + +// +void btSoftBody::appendFace(int model,Material* mat) +{ +Face f; +if(model>=0) + { f=m_faces[model]; } + else + { ZeroInitialize(f);f.m_material=mat?mat:m_materials[0]; } +m_faces.push_back(f); +} + +// +void btSoftBody::appendFace(int node0,int node1,int node2,Material* mat) +{ + appendFace(-1,mat); + Face& f=m_faces[m_faces.size()-1]; + btAssert(node0!=node1); + btAssert(node1!=node2); + btAssert(node2!=node0); + f.m_n[0] = &m_nodes[node0]; + f.m_n[1] = &m_nodes[node1]; + f.m_n[2] = &m_nodes[node2]; + f.m_ra = AreaOf( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + m_bUpdateRtCst=true; +} + +// +void btSoftBody::appendAnchor(int node,btRigidBody* body) +{ + Anchor a; + a.m_node = &m_nodes[node]; + a.m_body = body; + a.m_local = body->getInterpolationWorldTransform().inverse()*a.m_node->m_x; + a.m_node->m_battach = 1; + m_anchors.push_back(a); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1) +{ +LJoint* pj = new(btAlignedAlloc(sizeof(LJoint),16)) LJoint(); +pj->m_bodies[0] = body0; +pj->m_bodies[1] = body1; +pj->m_refs[0] = pj->m_bodies[0].xform().inverse()*specs.position; +pj->m_refs[1] = pj->m_bodies[1].xform().inverse()*specs.position; +pj->m_cfm = specs.cfm; +pj->m_erp = specs.erp; +pj->m_split = specs.split; +m_joints.push_back(pj); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,Body body) +{ +appendLinearJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body) +{ +appendLinearJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1) +{ +AJoint* pj = new(btAlignedAlloc(sizeof(AJoint),16)) AJoint(); +pj->m_bodies[0] = body0; +pj->m_bodies[1] = body1; +pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis()*specs.axis; +pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis()*specs.axis; +pj->m_cfm = specs.cfm; +pj->m_erp = specs.erp; +pj->m_split = specs.split; +pj->m_icontrol = specs.icontrol; +m_joints.push_back(pj); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,Body body) +{ +appendAngularJoint(specs,m_clusters[0],body); +} + +// +void btSoftBody::appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body) +{ +appendAngularJoint(specs,m_clusters[0],body->m_clusters[0]); +} + +// +void btSoftBody::addForce(const btVector3& force) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_f += force; + } +} + +// +void btSoftBody::addVelocity(const btVector3& velocity) +{ + for(int i=0,ni=m_nodes.size();i0) + { + n.m_v += velocity; + } +} + +// +void btSoftBody::setMass(int node,btScalar mass) +{ + m_nodes[node].m_im=mass>0?1/mass:0; + m_bUpdateRtCst=true; +} + +// +btScalar btSoftBody::getMass(int node) const +{ + return(m_nodes[node].m_im>0?1/m_nodes[node].m_im:0); +} + +// +btScalar btSoftBody::getTotalMass() const +{ + btScalar mass=0; + for(int i=0;im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x); + for(int j=0;j<3;++j) + { + f.m_n[j]->m_im+=twicearea; + } + } + for( i=0;igetMargin(); + for(int i=0,ni=m_nodes.size();igetMargin(); + for(int i=0,ni=m_nodes.size();i0 ? + 1/(m_nodes[i].m_im*tmass) : + kmass/tmass; + } + /* Pos */ + const btVector3 com=evaluateCom(); + m_pose.m_pos.resize(m_nodes.size()); + for( i=0,ni=m_nodes.size();i0) + { + int i,ni; + + const btVector3 org=m_nodes[0].m_x; + for(i=0,ni=m_faces.size();im_x-org,cross(f.m_n[1]->m_x-org,f.m_n[2]->m_x-org)); + } + vol/=(btScalar)6; + } + return(vol); +} + +// +int btSoftBody::clusterCount() const +{ +return(m_clusters.size()); +} + +// +btVector3 btSoftBody::clusterCom(const Cluster* cluster) +{ +btVector3 com(0,0,0); +for(int i=0,ni=cluster->m_nodes.size();im_nodes[i]->m_x*cluster->m_masses[i]; + } +return(com*cluster->m_imass); +} + +// +btVector3 btSoftBody::clusterCom(int cluster) const +{ +return(clusterCom(m_clusters[cluster])); +} + +// +btVector3 btSoftBody::clusterVelocity(const Cluster* cluster,const btVector3& rpos) +{ +return(cluster->m_lv+cross(cluster->m_av,rpos)); +} + +// +void btSoftBody::clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ +const btVector3 li=cluster->m_imass*impulse; +const btVector3 ai=cluster->m_invwi*cross(rpos,impulse); +cluster->m_vimpulses[0]+=li;cluster->m_lv+=li; +cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; +cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse) +{ +const btVector3 li=cluster->m_imass*impulse; +const btVector3 ai=cluster->m_invwi*cross(rpos,impulse); +cluster->m_dimpulses[0]+=li; +cluster->m_dimpulses[1]+=ai; +cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse) +{ +if(impulse.m_asVelocity) clusterVImpulse(cluster,rpos,impulse.m_velocity); +if(impulse.m_asDrift) clusterDImpulse(cluster,rpos,impulse.m_drift); +} + +// +void btSoftBody::clusterVAImpulse(Cluster* cluster,const btVector3& impulse) +{ +const btVector3 ai=cluster->m_invwi*impulse; +cluster->m_vimpulses[1]+=ai;cluster->m_av+=ai; +cluster->m_nvimpulses++; +} + +// +void btSoftBody::clusterDAImpulse(Cluster* cluster,const btVector3& impulse) +{ +const btVector3 ai=cluster->m_invwi*impulse; +cluster->m_dimpulses[1]+=ai; +cluster->m_ndimpulses++; +} + +// +void btSoftBody::clusterAImpulse(Cluster* cluster,const Impulse& impulse) +{ +if(impulse.m_asVelocity) clusterVAImpulse(cluster,impulse.m_velocity); +if(impulse.m_asDrift) clusterDAImpulse(cluster,impulse.m_drift); +} + +// +void btSoftBody::clusterDCImpulse(Cluster* cluster,const btVector3& impulse) +{ +cluster->m_dimpulses[0]+=impulse*cluster->m_imass; +cluster->m_ndimpulses++; +} + +// +int btSoftBody::generateBendingConstraints(int distance,Material* mat) +{ + int i,j; + + if(distance>1) + { + /* Build graph */ + const int n=m_nodes.size(); + const unsigned inf=(~(unsigned)0)>>1; + unsigned* adj=new unsigned[n*n]; +#define IDX(_x_,_y_) ((_y_)*n+(_x_)) + for(j=0;jsum) + { + adj[IDX(i,j)]=adj[IDX(j,i)]=sum; + } + } + } + } + /* Build links */ + int nlinks=0; + for(j=0;jm_leaf) m_cdbvt.remove(c->m_leaf); +c->~Cluster(); +btAlignedFree(c); +m_clusters.remove(c); +} + +// +void btSoftBody::releaseClusters() +{ +while(m_clusters.size()>0) releaseCluster(0); +} + +// +int btSoftBody::generateClusters(int k,int maxiterations) +{ +int i; +releaseClusters(); +m_clusters.resize(btMin(k,m_nodes.size())); +for(i=0;im_collide= true; + } +k=m_clusters.size(); +if(k>0) + { + /* Initialize */ + btAlignedObjectArray centers; + btVector3 cog(0,0,0); + int i; + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + cog/=(btScalar)m_nodes.size(); + centers.resize(k,cog); + /* Iterate */ + const btScalar slope=16; + bool changed; + int iterations=0; + do { + const btScalar w=2-btMin(1,iterations/slope); + changed=false; + iterations++; + int i; + + for(i=0;im_nodes.size();++j) + { + c+=m_clusters[i]->m_nodes[j]->m_x; + } + if(m_clusters[i]->m_nodes.size()) + { + c /= (btScalar)m_clusters[i]->m_nodes.size(); + c = centers[i]+(c-centers[i])*w; + changed |= ((c-centers[i]).length2()>SIMD_EPSILON); + centers[i] = c; + m_clusters[i]->m_nodes.resize(0); + } + } + for(i=0;im_nodes.push_back(&m_nodes[i]); + } + } while(changed&&(iterations cids; + cids.resize(m_nodes.size(),-1); + for(i=0;im_nodes.size();++j) + { + cids[int(m_clusters[i]->m_nodes[j]-&m_nodes[0])]=i; + } + } + for(i=0;im_nodes.findLinearSearch(&m_nodes[kid])==m_clusters[cid]->m_nodes.size()) + { + m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]); + } + } + } + } + } + /* Master */ + if(m_clusters.size()>1) + { + Cluster* pmaster=new(btAlignedAlloc(sizeof(Cluster),16)) Cluster(); + pmaster->m_collide = false; + pmaster->m_nodes.reserve(m_nodes.size()); + for(int i=0;im_nodes.push_back(&m_nodes[i]); + m_clusters.push_back(pmaster); + btSwap(m_clusters[0],m_clusters[m_clusters.size()-1]); + } + /* Terminate */ + for(i=0;im_nodes.size()==0) + { + releaseCluster(i--); + } + } + + initializeClusters(); + updateClusters(); + return(m_clusters.size()); + } +return(0); +} + +// +void btSoftBody::refine(ImplicitFn* ifn,btScalar accurary,bool cut) +{ +const Node* nbase = &m_nodes[0]; +int ncount = m_nodes.size(); +btSymMatrix edges(ncount,-2); +int newnodes=0; +int i,j,k,ni; + +/* Filter out */ +for(i=0;iEval(l.m_n[0]->m_x),ifn->Eval(l.m_n[1]->m_x))) + { + btSwap(m_links[i],m_links[m_links.size()-1]); + m_links.pop_back();--i; + } + } + } +/* Fill edges */ +for(i=0;i0) + { + const btVector3 x=Lerp(a.m_x,b.m_x,t); + const btVector3 v=Lerp(a.m_v,b.m_v,t); + btScalar m=0; + if(a.m_im>0) + { + if(b.m_im>0) + { + const btScalar ma=1/a.m_im; + const btScalar mb=1/b.m_im; + const btScalar mc=Lerp(ma,mb,t); + const btScalar f=(ma+mb)/(ma+mb+mc); + a.m_im=1/(ma*f); + b.m_im=1/(mb*f); + m=mc*f; + } + else + { a.m_im/=0.5;m=1/a.m_im; } + } + else + { + if(b.m_im>0) + { b.m_im/=0.5;m=1/b.m_im; } + else + m=0; + } + appendNode(x,m); + edges(i,j)=m_nodes.size()-1; + m_nodes[edges(i,j)].m_v=v; + ++newnodes; + } + } + } + } +nbase=&m_nodes[0]; +/* Refine links */ +for(i=0,ni=m_links.size();i0) + { + appendLink(i); + Link* pft[]={ &m_links[i], + &m_links[m_links.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[0]]; + pft[0]->m_n[1]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[1]]; + } + } + } +/* Refine faces */ +for(i=0;i0) + { + appendFace(i); + const int l=(k+1)%3; + Face* pft[]={ &m_faces[i], + &m_faces[m_faces.size()-1]}; + pft[0]->m_n[0]=&m_nodes[idx[l]]; + pft[0]->m_n[1]=&m_nodes[idx[j]]; + pft[0]->m_n[2]=&m_nodes[ni]; + pft[1]->m_n[0]=&m_nodes[ni]; + pft[1]->m_n[1]=&m_nodes[idx[k]]; + pft[1]->m_n[2]=&m_nodes[idx[l]]; + appendLink(ni,idx[l],pft[0]->m_material); + --i;break; + } + } + } + } +/* Cut */ +if(cut) + { + btAlignedObjectArray cnodes; + const int pcount=ncount; + int i; + ncount=m_nodes.size(); + cnodes.resize(ncount,0); + /* Nodes */ + for(i=0;i=pcount)||(btFabs(ifn->Eval(x))0) { m*=0.5;m_nodes[i].m_im/=0.5; } + appendNode(x,m); + cnodes[i]=m_nodes.size()-1; + m_nodes[cnodes[i]].m_v=v; + } + } + nbase=&m_nodes[0]; + /* Links */ + for(i=0,ni=m_links.size();iEval(m_nodes[id[0]].m_x)Eval(m_nodes[id[1]].m_x)Eval(n[0]->m_x)Eval(n[1]->m_x)Eval(n[2]->m_x) ranks; + btAlignedObjectArray todelete; + ranks.resize(nnodes,0); + for(i=0,ni=m_links.size();i=0;--i) + { + if(!ranks[i]) todelete.push_back(i); + } + if(todelete.size()) + { + btAlignedObjectArray& map=ranks; + for(int i=0;im_v=v; +pn[1]->m_v=v; +for(i=0,ni=m_links.size();im_n[1]=pn[mtch]; + pft[1]->m_n[0]=pn[1-mtch]; + done=true; + } + } +for(i=0,ni=m_faces.size();im_n[l]=pn[mtch]; + pft[1]->m_n[k]=pn[1-mtch]; + appendLink(pn[0],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + appendLink(pn[1],pft[0]->m_n[(l+1)%3],pft[0]->m_material,true); + } + } + } +if(!done) + { + m_ndbvt.remove(pn[0]->m_leaf); + m_ndbvt.remove(pn[1]->m_leaf); + m_nodes.pop_back(); + m_nodes.pop_back(); + } +return(done); +} + +// +bool btSoftBody::rayCast(const btVector3& org, + const btVector3& dir, + sRayCast& results, + btScalar maxtime) +{ +if(m_faces.size()&&m_fdbvt.empty()) initializeFaceTree(); +results.body = this; +results.time = maxtime; +results.feature = eFeature::None; +results.index = -1; +return(rayCast(org,dir,results.time,results.feature,results.index,false)!=0); +} + +// +void btSoftBody::setSolver(eSolverPresets::_ preset) +{ +m_cfg.m_vsequence.clear(); +m_cfg.m_psequence.clear(); +m_cfg.m_dsequence.clear(); +switch(preset) + { + case eSolverPresets::Positions: + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + m_cfg.m_psequence.push_back(ePSolver::Linear); + break; + case eSolverPresets::Velocities: + m_cfg.m_vsequence.push_back(eVSolver::Linear); + + m_cfg.m_psequence.push_back(ePSolver::Anchors); + m_cfg.m_psequence.push_back(ePSolver::RContacts); + m_cfg.m_psequence.push_back(ePSolver::SContacts); + + m_cfg.m_dsequence.push_back(ePSolver::Linear); + break; + } +} + +// +void btSoftBody::predictMotion(btScalar dt) +{ + int i,ni; + + /* Update */ + if(m_bUpdateRtCst) + { + m_bUpdateRtCst=false; + updateConstants(); + m_fdbvt.clear(); + if(m_cfg.collisions&fCollision::VF_SS) + { + initializeFaceTree(); + } + } + + /* Prepare */ + m_sst.sdt = dt*m_cfg.timescale; + m_sst.isdt = 1/m_sst.sdt; + m_sst.velmrg = m_sst.sdt*3; + m_sst.radmrg = getCollisionShape()->getMargin(); + m_sst.updmrg = m_sst.radmrg*(btScalar)0.25; + /* Forces */ + addVelocity(m_worldInfo->m_gravity*m_sst.sdt); + applyForces(); + /* Integrate */ + for(i=0,ni=m_nodes.size();im_v+ + f.m_n[1]->m_v+ + f.m_n[2]->m_v)/3; + m_fdbvt.update( f.m_leaf, + VolumeOf(f,m_sst.radmrg), + v*m_sst.velmrg, + m_sst.updmrg); + } + } + /* Pose */ + updatePose(); + /* Match */ + if(m_pose.m_bframe&&(m_cfg.kMT>0)) + { + const btMatrix3x3 posetrs=m_pose.m_rot; + for(int i=0,ni=m_nodes.size();i0) + { + const btVector3 x=posetrs*m_pose.m_pos[i]+m_pose.m_com; + n.m_x=Lerp(n.m_x,x,m_cfg.kMT); + } + } + } + /* Clear contacts */ + m_rcontacts.resize(0); + m_scontacts.resize(0); + /* Optimize dbvt's */ + m_ndbvt.optimizeIncremental(1); + m_fdbvt.optimizeIncremental(1); + m_cdbvt.optimizeIncremental(1); +} + +// +void btSoftBody::solveConstraints() +{ +/* Apply clusters */ +applyClusters(false); +/* Prepare links */ + +int i,ni; + +for(i=0,ni=m_links.size();im_q-l.m_n[0]->m_q; + l.m_c2 = 1/(l.m_c3.length2()*l.m_c0); + } +/* Prepare anchors */ +for(i=0,ni=m_anchors.size();igetWorldTransform().getBasis()*a.m_local; + a.m_c0 = ImpulseMatrix( m_sst.sdt, + a.m_node->m_im, + a.m_body->getInvMass(), + a.m_body->getInvInertiaTensorWorld(), + ra); + a.m_c1 = ra; + a.m_c2 = m_sst.sdt*a.m_node->m_im; + a.m_body->activate(); + } +/* Solve velocities */ +if(m_cfg.viterations>0) + { + /* Solve */ + for(int isolve=0;isolve0) + { + for(int isolve=0;isolve0) + { + const btScalar vcf=m_cfg.kVCF*m_sst.isdt; + for(i=0,ni=m_nodes.size();i& bodies) +{ +const int nb=bodies.size(); +int iterations=0; +int i; + +for(i=0;im_cfg.citerations); + } +for(i=0;iprepareClusters(iterations); + } +for(i=0;isolveClusters(sor); + } + } +for(i=0;icleanupClusters(); + } +} + +// +void btSoftBody::integrateMotion() +{ + /* Update */ + updateNormals(); +} + +// + btSoftBody::RayCaster::RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt) +{ +o = org; +d = dir; +mint = mxt; +face = 0; +tests = 0; +} + +// +void btSoftBody::RayCaster::Process(const btDbvtNode* leaf) +{ +btSoftBody::Face& f=*(btSoftBody::Face*)leaf->data; +const btScalar t=rayTriangle( o,d, + f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + mint); +if((t>0)&&(tteps)&&(tceps) && + (dot(n,cross(b-hit,c-hit))>ceps) && + (dot(n,cross(c-hit,a-hit))>ceps)) + { + return(t); + } + } + } + return(-1); +} + +// +void btSoftBody::pointersToIndices() +{ +#define PTR2IDX(_p_,_b_) reinterpret_cast((_p_)-(_b_)) + btSoftBody::Node* base=&m_nodes[0]; + int i,ni; + + for(i=0,ni=m_nodes.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_links.size();idata=*(void**)&i; + } + } + for(i=0,ni=m_anchors.size();idata=&m_nodes[i]; + } + } + for(i=0,ni=m_links.size();idata=&m_faces[i]; + } + } + for(i=0,ni=m_anchors.size();im_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + mint); + if(t>0) + { + ++cnt; + if(!bcountonly) + { + feature=btSoftBody::eFeature::Face; + index=i; + mint=t; + } + } + } + } + else + {/* Use dbvt */ + RayCaster collider(org,dir,mint); + btDbvt::collideRAY(m_fdbvt.m_root,org,dir,collider); + if(collider.face) + { + mint=collider.mint; + feature=btSoftBody::eFeature::Face; + index=(int)(collider.face-&m_faces[0]); + cnt=1; + } + } + return(cnt); +} + +// +void btSoftBody::initializeFaceTree() +{ +m_fdbvt.clear(); +for(int i=0;igetCollisionShape(); + const btTransform& wtr=prb->getInterpolationWorldTransform(); + btScalar dst=m_worldInfo->m_sparsesdf.Evaluate( wtr.invXform(x), + shp, + nrm, + margin); + if(dst<0) + { + cti.m_body = prb; + cti.m_normal = wtr.getBasis()*nrm; + cti.m_offset = -dot( cti.m_normal, + x-cti.m_normal*dst); + return(true); + } + return(false); +} + +// +void btSoftBody::updateNormals() +{ + const btVector3 zv(0,0,0); + int i,ni; + + for(i=0,ni=m_nodes.size();im_x-f.m_n[0]->m_x, + f.m_n[2]->m_x-f.m_n[0]->m_x); + f.m_normal=n.normalized(); + f.m_n[0]->m_n+=n; + f.m_n[1]->m_n+=n; + f.m_n[2]->m_n+=n; + } + for(i=0,ni=m_nodes.size();iSIMD_EPSILON) + m_nodes[i].m_n /= len; + } +} + +// +void btSoftBody::updateBounds() +{ + if(m_ndbvt.m_root) + { + const btVector3& mins=m_ndbvt.m_root->volume.Mins(); + const btVector3& maxs=m_ndbvt.m_root->volume.Maxs(); + const btScalar csm=getCollisionShape()->getMargin(); + const btVector3 mrg=btVector3( csm, + csm, + csm)*1; // ??? to investigate... + m_bounds[0]=mins-mrg; + m_bounds[1]=maxs+mrg; + if(0!=getBroadphaseHandle()) + { + m_worldInfo->m_broadphase->setAabb( getBroadphaseHandle(), + m_bounds[0], + m_bounds[1], + m_worldInfo->m_dispatcher); + } + } + else + { + m_bounds[0]= + m_bounds[1]=btVector3(0,0,0); + } +} + + +// +void btSoftBody::updatePose() +{ + if(m_pose.m_bframe) + { + btSoftBody::Pose& pose=m_pose; + const btVector3 com=evaluateCom(); + /* Com */ + pose.m_com = com; + /* Rotation */ + btMatrix3x3 Apq; + const btScalar eps=SIMD_EPSILON; + Apq[0]=Apq[1]=Apq[2]=btVector3(0,0,0); + Apq[0].setX(eps);Apq[1].setY(eps*2);Apq[2].setZ(eps*3); + for(int i=0,ni=m_nodes.size();i1) + { + const btScalar idet=Clamp( 1/pose.m_scl.determinant(), + 1,m_cfg.maxvolume); + pose.m_scl=Mul(pose.m_scl,idet); + } + + } +} + +// +void btSoftBody::updateConstants() +{ + int i,ni; + + /* Links */ + for(i=0,ni=m_links.size();im_x-l.m_n[1]->m_x).length(); + l.m_c0 = (l.m_n[0]->m_im+l.m_n[1]->m_im)/m.m_kLST; + l.m_c1 = l.m_rl*l.m_rl; + } + /* Faces */ + for(i=0,ni=m_faces.size();im_x,f.m_n[1]->m_x,f.m_n[2]->m_x); + } + /* Area's */ + btAlignedObjectArray counts; + counts.resize(m_nodes.size(),0); + for(i=0,ni=m_nodes.size();im_area+=btFabs(f.m_ra); + } + } + for(i=0,ni=m_nodes.size();i0) + m_nodes[i].m_area/=(btScalar)counts[i]; + else + m_nodes[i].m_area=0; + } +} + +// +void btSoftBody::initializeClusters() +{ + int i; + +for( i=0;im_im>0?1/c.m_nodes[j]->m_im:0; + c.m_imass += c.m_masses[j]; + } + c.m_imass = 1/c.m_imass; + c.m_com = btSoftBody::clusterCom(&c); + c.m_lv = btVector3(0,0,0); + c.m_av = btVector3(0,0,0); + c.m_leaf = 0; + /* Inertia */ + btMatrix3x3& ii=c.m_locii; + ii[0]=ii[1]=ii[2]=btVector3(0,0,0); + { + int i,ni; + + for(i=0,ni=c.m_nodes.size();im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=c.m_masses[i]; + ii[0][0] += m*(q[1]+q[2]); + ii[1][1] += m*(q[0]+q[2]); + ii[2][2] += m*(q[0]+q[1]); + ii[0][1] -= m*k[0]*k[1]; + ii[0][2] -= m*k[0]*k[2]; + ii[1][2] -= m*k[1]*k[2]; + } + } + ii[1][0]=ii[0][1]; + ii[2][0]=ii[0][2]; + ii[2][1]=ii[1][2]; + ii=ii.inverse(); + /* Frame */ + c.m_framexform.setIdentity(); + c.m_framexform.setOrigin(c.m_com); + c.m_framerefs.resize(c.m_nodes.size()); + { + int i; + for(i=0;im_x-c.m_com; + } + } + } +} + +// +void btSoftBody::updateClusters() +{ +BT_PROFILE("UpdateClusters"); +int i; + +for(i=0;im_x-c.m_com; + const btVector3& b=c.m_framerefs[i]; + m[0]+=a[0]*b;m[1]+=a[1]*b;m[2]+=a[2]*b; + } + PolarDecompose(m,r,s); + c.m_framexform.setOrigin(c.m_com); + c.m_framexform.setBasis(r); + /* Inertia */ + #if 1/* Constant */ + c.m_invwi=c.m_framexform.getBasis()*c.m_locii*c.m_framexform.getBasis().transpose(); + #else + #if 0/* Sphere */ + const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass); + const btVector3 inertia(rk,rk,rk); + const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0, + btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0, + btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0); + + c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose(); + #else/* Actual */ + c.m_invwi[0]=c.m_invwi[1]=c.m_invwi[2]=btVector3(0,0,0); + for(int i=0;im_x-c.m_com; + const btVector3 q=k*k; + const btScalar m=1/c.m_nodes[i]->m_im; + c.m_invwi[0][0] += m*(q[1]+q[2]); + c.m_invwi[1][1] += m*(q[0]+q[2]); + c.m_invwi[2][2] += m*(q[0]+q[1]); + c.m_invwi[0][1] -= m*k[0]*k[1]; + c.m_invwi[0][2] -= m*k[0]*k[2]; + c.m_invwi[1][2] -= m*k[1]*k[2]; + } + c.m_invwi[1][0]=c.m_invwi[0][1]; + c.m_invwi[2][0]=c.m_invwi[0][2]; + c.m_invwi[2][1]=c.m_invwi[1][2]; + c.m_invwi=c.m_invwi.inverse(); + #endif + #endif + /* Velocities */ + c.m_lv=btVector3(0,0,0); + c.m_av=btVector3(0,0,0); + { + int i; + + for(i=0;im_v*c.m_masses[i]; + c.m_lv += v; + c.m_av += cross(c.m_nodes[i]->m_x-c.m_com,v); + } + } + c.m_lv=c.m_imass*c.m_lv*(1-c.m_ldamping); + c.m_av=c.m_invwi*c.m_av*(1-c.m_adamping); + c.m_vimpulses[0] = + c.m_vimpulses[1] = btVector3(0,0,0); + c.m_dimpulses[0] = + c.m_dimpulses[1] = btVector3(0,0,0); + c.m_nvimpulses = 0; + c.m_ndimpulses = 0; + /* Matching */ + if(c.m_matching>0) + { + for(int j=0;jm_x; + btVector3 mx=mi; + for(int j=1;jm_x); + mx.setMax(c.m_nodes[j]->m_x); + } + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); + if(c.m_leaf) + m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); + else + c.m_leaf=m_cdbvt.insert(bounds,&c); + } + } + } +} + +// +void btSoftBody::cleanupClusters() +{ +for(int i=0;iTerminate(m_sst.sdt); + if(m_joints[i]->m_delete) + { + btAlignedFree(m_joints[i]); + m_joints.remove(m_joints[i--]); + } + } +} + +// +void btSoftBody::prepareClusters(int iterations) +{ +for(int i=0;iPrepare(m_sst.sdt,iterations); + } +} + + +// +void btSoftBody::solveClusters(btScalar sor) +{ +for(int i=0,ni=m_joints.size();iSolve(m_sst.sdt,sor); + } +} + +// +void btSoftBody::applyClusters(bool drift) +{ +BT_PROFILE("ApplyClusters"); +const btScalar f0=m_sst.sdt; +const btScalar f1=f0/2; +btAlignedObjectArray deltas; +btAlignedObjectArray weights; +deltas.resize(m_nodes.size(),btVector3(0,0,0)); +weights.resize(m_nodes.size(),0); +int i; + +if(drift) + { + for(i=0;im_x; + const btScalar q=c.m_masses[j]; + deltas[idx] += (v+cross(w,x-c.m_com))*q; + weights[idx] += q; + } + } + } + for(i=0;i0) m_nodes[i].m_x+=deltas[i]/weights[i]; + } +} + +// +void btSoftBody::dampClusters() +{ + int i; + +for(i=0;i0) + { + for(int j=0;j0) + { + const btVector3 vx=c.m_lv+cross(c.m_av,c.m_nodes[j]->m_q-c.m_com); + n.m_v += c.m_ndamping*(vx-n.m_v); + } + } + } + } +} + +// +void btSoftBody::Joint::Prepare(btScalar dt,int) +{ +m_bodies[0].activate(); +m_bodies[1].activate(); +} + +// +void btSoftBody::LJoint::Prepare(btScalar dt,int iterations) +{ +static const btScalar maxdrift=4; +Joint::Prepare(dt,iterations); +m_rpos[0] = m_bodies[0].xform()*m_refs[0]; +m_rpos[1] = m_bodies[1].xform()*m_refs[1]; +m_drift = Clamp(m_rpos[0]-m_rpos[1],maxdrift)*m_erp/dt; +m_rpos[0] -= m_bodies[0].xform().getOrigin(); +m_rpos[1] -= m_bodies[1].xform().getOrigin(); +m_massmatrix = ImpulseMatrix( m_bodies[0].invMass(),m_bodies[0].invWorldInertia(),m_rpos[0], + m_bodies[1].invMass(),m_bodies[1].invWorldInertia(),m_rpos[1]); +if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } +m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::LJoint::Solve(btScalar dt,btScalar sor) +{ +const btVector3 va=m_bodies[0].velocity(m_rpos[0]); +const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); +const btVector3 vr=va-vb; +btSoftBody::Impulse impulse; +impulse.m_asVelocity = 1; +impulse.m_velocity = m_massmatrix*(m_drift+vr*m_cfm)*sor; +m_bodies[0].applyImpulse(-impulse,m_rpos[0]); +m_bodies[1].applyImpulse( impulse,m_rpos[1]); +} + +// +void btSoftBody::LJoint::Terminate(btScalar dt) +{ +if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::AJoint::Prepare(btScalar dt,int iterations) +{ +static const btScalar maxdrift=SIMD_PI/16; +m_icontrol->Prepare(this); +Joint::Prepare(dt,iterations); +m_axis[0] = m_bodies[0].xform().getBasis()*m_refs[0]; +m_axis[1] = m_bodies[1].xform().getBasis()*m_refs[1]; +m_drift = NormalizeAny(cross(m_axis[1],m_axis[0])); +m_drift *= btMin(maxdrift,btAcos(Clamp(dot(m_axis[0],m_axis[1]),-1,+1))); +m_drift *= m_erp/dt; +m_massmatrix= AngularImpulseMatrix(m_bodies[0].invWorldInertia(),m_bodies[1].invWorldInertia()); +if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } +m_drift /=(btScalar)iterations; +} + +// +void btSoftBody::AJoint::Solve(btScalar dt,btScalar sor) +{ +const btVector3 va=m_bodies[0].angularVelocity(); +const btVector3 vb=m_bodies[1].angularVelocity(); +const btVector3 vr=va-vb; +const btScalar sp=dot(vr,m_axis[0]); +const btVector3 vc=vr-m_axis[0]*m_icontrol->Speed(this,sp); +btSoftBody::Impulse impulse; +impulse.m_asVelocity = 1; +impulse.m_velocity = m_massmatrix*(m_drift+vc*m_cfm)*sor; +m_bodies[0].applyAImpulse(-impulse); +m_bodies[1].applyAImpulse( impulse); +} + +// +void btSoftBody::AJoint::Terminate(btScalar dt) +{ +if(m_split>0) + { + m_bodies[0].applyDAImpulse(-m_sdrift); + m_bodies[1].applyDAImpulse( m_sdrift); + } +} + +// +void btSoftBody::CJoint::Prepare(btScalar dt,int iterations) +{ +Joint::Prepare(dt,iterations); +const bool dodrift=(m_life==0); +m_delete=(++m_life)>m_maxlife; +if(dodrift) + { + m_drift=m_drift*m_erp/dt; + if(m_split>0) + { + m_sdrift = m_massmatrix*(m_drift*m_split); + m_drift *= 1-m_split; + } + m_drift/=(btScalar)iterations; + } + else + { + m_drift=m_sdrift=btVector3(0,0,0); + } +} + +// +void btSoftBody::CJoint::Solve(btScalar dt,btScalar sor) +{ +const btVector3 va=m_bodies[0].velocity(m_rpos[0]); +const btVector3 vb=m_bodies[1].velocity(m_rpos[1]); +const btVector3 vrel=va-vb; +const btScalar rvac=dot(vrel,m_normal); +btSoftBody::Impulse impulse; +impulse.m_asVelocity = 1; +impulse.m_velocity = m_drift; +if(rvac<0) + { + const btVector3 iv=m_normal*rvac; + const btVector3 fv=vrel-iv; + impulse.m_velocity += iv+fv*m_friction; + } +impulse.m_velocity=m_massmatrix*impulse.m_velocity*sor; +m_bodies[0].applyImpulse(-impulse,m_rpos[0]); +m_bodies[1].applyImpulse( impulse,m_rpos[1]); +} + +// +void btSoftBody::CJoint::Terminate(btScalar dt) +{ +if(m_split>0) + { + m_bodies[0].applyDImpulse(-m_sdrift,m_rpos[0]); + m_bodies[1].applyDImpulse( m_sdrift,m_rpos[1]); + } +} + +// +void btSoftBody::applyForces() +{ + BT_PROFILE("SoftBody applyForces"); + const btScalar dt=m_sst.sdt; + const btScalar kLF=m_cfg.kLF; + const btScalar kDG=m_cfg.kDG; + const btScalar kPR=m_cfg.kPR; + const btScalar kVC=m_cfg.kVC; + const bool as_lift=kLF>0; + const bool as_drag=kDG>0; + const bool as_pressure=kPR!=0; + const bool as_volume=kVC>0; + const bool as_aero= as_lift || + as_drag ; + const bool as_vaero= as_aero && + (m_cfg.aeromodel=btSoftBody::eAeroModel::F_TwoSided); + const bool use_medium= as_aero; + const bool use_volume= as_pressure || + as_volume ; + btScalar volume=0; + btScalar ivolumetp=0; + btScalar dvolumetv=0; + btSoftBody::sMedium medium; + if(use_volume) + { + volume = getVolume(); + ivolumetp = 1/btFabs(volume)*kPR; + dvolumetv = (m_pose.m_volume-volume)*kVC; + } + /* Per vertex forces */ + int i,ni; + + for(i=0,ni=m_nodes.size();i0) + { + if(use_medium) + { + EvaluateMedium(m_worldInfo,n.m_x,medium); + /* Aerodynamics */ + if(as_vaero) + { + const btVector3 rel_v=n.m_v-medium.m_velocity; + const btScalar rel_v2=rel_v.length2(); + if(rel_v2>SIMD_EPSILON) + { + btVector3 nrm=n.m_n; + /* Setup normal */ + switch(m_cfg.aeromodel) + { + case btSoftBody::eAeroModel::V_Point: + nrm=NormalizeAny(rel_v);break; + case btSoftBody::eAeroModel::V_TwoSided: + nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break; + } + const btScalar dvn=dot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = n.m_area*dvn*rel_v2/2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + ApplyClampedForce(n,force,dt); + } + } + } + } + /* Pressure */ + if(as_pressure) + { + n.m_f += n.m_n*(n.m_area*ivolumetp); + } + /* Volume */ + if(as_volume) + { + n.m_f += n.m_n*(n.m_area*dvolumetv); + } + } + } + /* Per face forces */ + for(i=0,ni=m_faces.size();im_v+f.m_n[1]->m_v+f.m_n[2]->m_v)/3; + const btVector3 x=(f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3; + EvaluateMedium(m_worldInfo,x,medium); + const btVector3 rel_v=v-medium.m_velocity; + const btScalar rel_v2=rel_v.length2(); + if(rel_v2>SIMD_EPSILON) + { + btVector3 nrm=f.m_normal; + /* Setup normal */ + switch(m_cfg.aeromodel) + { + case btSoftBody::eAeroModel::F_TwoSided: + nrm*=(btScalar)(dot(nrm,rel_v)<0?-1:+1);break; + } + const btScalar dvn=dot(rel_v,nrm); + /* Compute forces */ + if(dvn>0) + { + btVector3 force(0,0,0); + const btScalar c0 = f.m_ra*dvn*rel_v2; + const btScalar c1 = c0*medium.m_density; + force += nrm*(-c1*kLF); + force += rel_v.normalized()*(-c1*kDG); + force /= 3; + for(int j=0;j<3;++j) ApplyClampedForce(*f.m_n[j],force,dt); + } + } + } + } +} + +// +void btSoftBody::PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti) +{ + const btScalar kAHR=psb->m_cfg.kAHR*kst; + const btScalar dt=psb->m_sst.sdt; + for(int i=0,ni=psb->m_anchors.size();im_anchors[i]; + const btTransform& t=a.m_body->getInterpolationWorldTransform(); + Node& n=*a.m_node; + const btVector3 wa=t*a.m_local; + const btVector3 va=a.m_body->getVelocityInLocalPoint(a.m_c1)*dt; + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=(va-vb)+(wa-n.m_x)*kAHR; + const btVector3 impulse=a.m_c0*vr; + n.m_x+=impulse*a.m_c2; + a.m_body->applyImpulse(-impulse,a.m_c1); + } +} + +// +void btSoftBody::PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti) +{ + const btScalar dt=psb->m_sst.sdt; + const btScalar mrg=psb->getCollisionShape()->getMargin(); + for(int i=0,ni=psb->m_rcontacts.size();im_rcontacts[i]; + const sCti& cti=c.m_cti; + const btVector3 va=cti.m_body->getVelocityInLocalPoint(c.m_c1)*dt; + const btVector3 vb=c.m_node->m_x-c.m_node->m_q; + const btVector3 vr=vb-va; + const btScalar dn=dot(vr,cti.m_normal); + if(dn<=SIMD_EPSILON) + { + const btScalar dp=btMin(dot(c.m_node->m_x,cti.m_normal)+cti.m_offset,mrg); + const btVector3 fv=vr-cti.m_normal*dn; + const btVector3 impulse=c.m_c0*((vr-fv*c.m_c3+cti.m_normal*(dp*c.m_c4))*kst); + c.m_node->m_x-=impulse*c.m_c2; + c.m_cti.m_body->applyImpulse(impulse,c.m_c1); + } + } +} + +// +void btSoftBody::PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti) +{ +for(int i=0,ni=psb->m_scontacts.size();im_scontacts[i]; + const btVector3& nr=c.m_normal; + Node& n=*c.m_node; + Face& f=*c.m_face; + const btVector3 p=BaryEval( f.m_n[0]->m_x, + f.m_n[1]->m_x, + f.m_n[2]->m_x, + c.m_weights); + const btVector3 q=BaryEval( f.m_n[0]->m_q, + f.m_n[1]->m_q, + f.m_n[2]->m_q, + c.m_weights); + const btVector3 vr=(n.m_x-n.m_q)-(p-q); + btVector3 corr(0,0,0); + if(dot(vr,nr)<0) + { + const btScalar j=c.m_margin-(dot(nr,n.m_x)-dot(nr,p)); + corr+=c.m_normal*j; + } + corr -= ProjectOnPlane(vr,nr)*c.m_friction; + n.m_x += corr*c.m_cfm[0]; + f.m_n[0]->m_x -= corr*(c.m_cfm[1]*c.m_weights.x()); + f.m_n[1]->m_x -= corr*(c.m_cfm[1]*c.m_weights.y()); + f.m_n[2]->m_x -= corr*(c.m_cfm[1]*c.m_weights.z()); + } +} + +// +void btSoftBody::PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti) +{ + for(int i=0,ni=psb->m_links.size();im_links[i]; + if(l.m_c0>0) + { + Node& a=*l.m_n[0]; + Node& b=*l.m_n[1]; + const btVector3 del=b.m_x-a.m_x; + const btScalar len=del.length2(); + const btScalar k=((l.m_c1-len)/(l.m_c0*(l.m_c1+len)))*kst; + const btScalar t=k*a.m_im; + a.m_x-=del*(k*a.m_im); + b.m_x+=del*(k*b.m_im); + } + } +} + +// +void btSoftBody::VSolve_Links(btSoftBody* psb,btScalar kst) +{ +for(int i=0,ni=psb->m_links.size();im_links[i]; + Node** n=l.m_n; + const btScalar j=-dot(l.m_c3,n[0]->m_v-n[1]->m_v)*l.m_c2*kst; + n[0]->m_v+= l.m_c3*(j*n[0]->m_im); + n[1]->m_v-= l.m_c3*(j*n[1]->m_im); + } +} + +// +btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver) +{ +switch(solver) + { + case ePSolver::Anchors: return(&btSoftBody::PSolve_Anchors); + case ePSolver::Linear: return(&btSoftBody::PSolve_Links); + case ePSolver::RContacts: return(&btSoftBody::PSolve_RContacts); + case ePSolver::SContacts: return(&btSoftBody::PSolve_SContacts); + } +return(0); +} + +// +btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver) +{ +switch(solver) + { + case eVSolver::Linear: return(&btSoftBody::VSolve_Links); + } +return(0); +} + +// +void btSoftBody::defaultCollisionHandler(btCollisionObject* pco) +{ +switch(m_cfg.collisions&fCollision::RVSmask) + { + case fCollision::SDF_RS: + { + btSoftColliders::CollideSDF_RS docollide; + btRigidBody* prb=btRigidBody::upcast(pco); + const btTransform wtr=prb->getInterpolationWorldTransform(); + const btTransform ctr=prb->getWorldTransform(); + const btScalar timemargin=(wtr.getOrigin()-ctr.getOrigin()).length(); + const btScalar basemargin=getCollisionShape()->getMargin(); + btVector3 mins; + btVector3 maxs; + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(), + mins, + maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(basemargin,basemargin,basemargin)); + docollide.psb = this; + docollide.prb = prb; + docollide.dynmargin = basemargin+timemargin; + docollide.stamargin = basemargin; + btDbvt::collideTV(m_ndbvt.m_root,volume,docollide); + } + break; + case fCollision::CL_RS: + { + btSoftColliders::CollideCL_RS collider; + collider.Process(this,btRigidBody::upcast(pco)); + } + break; + } +} + +// +void btSoftBody::defaultCollisionHandler(btSoftBody* psb) +{ +const int cf=m_cfg.collisions&psb->m_cfg.collisions; +switch(cf&fCollision::SVSmask) + { + case fCollision::CL_SS: + { + btSoftColliders::CollideCL_SS docollide; + docollide.Process(this,psb); + } + break; + case fCollision::VF_SS: + { + btSoftColliders::CollideVF_SS docollide; + /* common */ + docollide.mrg= getCollisionShape()->getMargin()+ + psb->getCollisionShape()->getMargin(); + /* psb0 nodes vs psb1 faces */ + docollide.psb[0]=this; + docollide.psb[1]=psb; + btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + /* psb1 nodes vs psb0 faces */ + docollide.psb[0]=psb; + docollide.psb[1]=this; + btDbvt::collideTT( docollide.psb[0]->m_ndbvt.m_root, + docollide.psb[1]->m_fdbvt.m_root, + docollide); + } + break; + } +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h new file mode 100644 index 00000000000..91d732b4e9a --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -0,0 +1,813 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_H +#define _BT_SOFT_BODY_H + +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btPoint3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletDynamics/Dynamics/btRigidBody.h" + +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "btSparseSDF.h" +#include "BulletCollision/BroadphaseCollision/btDbvt.h" + +class btBroadphaseInterface; +class btCollisionDispatcher; + +/* btSoftBodyWorldInfo */ +struct btSoftBodyWorldInfo +{ + btScalar air_density; + btScalar water_density; + btScalar water_offset; + btVector3 water_normal; + btBroadphaseInterface* m_broadphase; + btCollisionDispatcher* m_dispatcher; + btVector3 m_gravity; + btSparseSdf<3> m_sparsesdf; +}; + + +/// btSoftBody is work-in-progress +class btSoftBody : public btCollisionObject +{ +public: + // + // Enumerations + // + + ///eAeroModel + struct eAeroModel { enum _ { + V_Point, ///Vertex normals are oriented toward velocity + V_TwoSided, ///Vertex normals are fliped to match velocity + V_OneSided, ///Vertex normals are taken as it is + F_TwoSided, ///Face normals are fliped to match velocity + F_OneSided, ///Face normals are taken as it is + END + };}; + + ///eVSolver : velocities solvers + struct eVSolver { enum _ { + Linear, ///Linear solver + END + };}; + + ///ePSolver : positions solvers + struct ePSolver { enum _ { + Linear, ///Linear solver + Anchors, ///Anchor solver + RContacts, ///Rigid contacts solver + SContacts, ///Soft contacts solver + END + };}; + + ///eSolverPresets + struct eSolverPresets { enum _ { + Positions, + Velocities, + Default = Positions, + END + };}; + + ///eFeature + struct eFeature { enum _ { + None, + Node, + Link, + Face, + END + };}; + + typedef btAlignedObjectArray tVSolverArray; + typedef btAlignedObjectArray tPSolverArray; + + // + // Flags + // + + ///fCollision + struct fCollision { enum _ { + RVSmask = 0x000f, ///Rigid versus soft mask + SDF_RS = 0x0001, ///SDF based rigid vs soft + CL_RS = 0x0002, ///Cluster vs convex rigid vs soft + + SVSmask = 0x00f0, ///Rigid versus soft mask + VF_SS = 0x0010, ///Vertex vs face soft vs soft handling + CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling + /* presets */ + Default = SDF_RS, + END + };}; + + ///fMaterial + struct fMaterial { enum _ { + DebugDraw = 0x0001, /// Enable debug draw + /* presets */ + Default = DebugDraw, + END + };}; + + // + // API Types + // + + /* sRayCast */ + struct sRayCast + { + btSoftBody* body; /// soft body + eFeature::_ feature; /// feature type + int index; /// feature index + btScalar time; /// time of impact (rayorg+raydir*time) + }; + + /* ImplicitFn */ + struct ImplicitFn + { + virtual btScalar Eval(const btVector3& x)=0; + }; + + // + // Internal types + // + + typedef btAlignedObjectArray tScalarArray; + typedef btAlignedObjectArray tVector3Array; + + /* sCti is Softbody contact info */ + struct sCti + { + btRigidBody* m_body; /* Rigid body */ + btVector3 m_normal; /* Outward normal */ + btScalar m_offset; /* Offset from origin */ + }; + + /* sMedium */ + struct sMedium + { + btVector3 m_velocity; /* Velocity */ + btScalar m_pressure; /* Pressure */ + btScalar m_density; /* Density */ + }; + + /* Base type */ + struct Element + { + void* m_tag; // User data + Element() : m_tag(0) {} + }; + /* Material */ + struct Material : Element + { + btScalar m_kLST; // Linear stiffness coefficient [0,1] + btScalar m_kAST; // Area/Angular stiffness coefficient [0,1] + btScalar m_kVST; // Volume stiffness coefficient [0,1] + int m_flags; // Flags + }; + + /* Feature */ + struct Feature : Element + { + Material* m_material; // Material + }; + /* Node */ + struct Node : Feature + { + btVector3 m_x; // Position + btVector3 m_q; // Previous step position + btVector3 m_v; // Velocity + btVector3 m_f; // Force accumulator + btVector3 m_n; // Normal + btScalar m_im; // 1/mass + btScalar m_area; // Area + btDbvtNode* m_leaf; // Leaf data + int m_battach:1; // Attached + }; + /* Link */ + struct Link : Feature + { + Node* m_n[2]; // Node pointers + btScalar m_rl; // Rest length + int m_bbending:1; // Bending link + btScalar m_c0; // (ima+imb)*kLST + btScalar m_c1; // rl^2 + btScalar m_c2; // |gradient|^2/c0 + btVector3 m_c3; // gradient + }; + /* Face */ + struct Face : Feature + { + Node* m_n[3]; // Node pointers + btVector3 m_normal; // Normal + btScalar m_ra; // Rest area + btDbvtNode* m_leaf; // Leaf data + }; + /* RContact */ + struct RContact + { + sCti m_cti; // Contact infos + Node* m_node; // Owner node + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + btScalar m_c3; // Friction + btScalar m_c4; // Hardness + }; + /* SContact */ + struct SContact + { + Node* m_node; // Node + Face* m_face; // Face + btVector3 m_weights; // Weigths + btVector3 m_normal; // Normal + btScalar m_margin; // Margin + btScalar m_friction; // Friction + btScalar m_cfm[2]; // Constraint force mixing + }; + /* Anchor */ + struct Anchor + { + Node* m_node; // Node pointer + btVector3 m_local; // Anchor position in body space + btRigidBody* m_body; // Body + btMatrix3x3 m_c0; // Impulse matrix + btVector3 m_c1; // Relative anchor + btScalar m_c2; // ima*dt + }; + /* Note */ + struct Note : Element + { + const char* m_text; // Text + btVector3 m_offset; // Offset + int m_rank; // Rank + Node* m_nodes[4]; // Nodes + btScalar m_coords[4]; // Coordinates + }; + /* Pose */ + struct Pose + { + bool m_bvolume; // Is valid + bool m_bframe; // Is frame + btScalar m_volume; // Rest volume + tVector3Array m_pos; // Reference positions + tScalarArray m_wgh; // Weights + btVector3 m_com; // COM + btMatrix3x3 m_rot; // Rotation + btMatrix3x3 m_scl; // Scale + btMatrix3x3 m_aqq; // Base scaling + }; + /* Cluster */ + struct Cluster + { + btAlignedObjectArray m_nodes; + tScalarArray m_masses; + tVector3Array m_framerefs; + btTransform m_framexform; + btScalar m_idmass; + btScalar m_imass; + btMatrix3x3 m_locii; + btMatrix3x3 m_invwi; + btVector3 m_com; + btVector3 m_vimpulses[2]; + btVector3 m_dimpulses[2]; + int m_nvimpulses; + int m_ndimpulses; + btVector3 m_lv; + btVector3 m_av; + btDbvtNode* m_leaf; + btScalar m_ndamping; + btScalar m_ldamping; + btScalar m_adamping; + btScalar m_matching; + bool m_collide; + Cluster() : m_leaf(0),m_ndamping(0),m_ldamping(0),m_adamping(0),m_matching(0) {} + }; + /* Impulse */ + struct Impulse + { + btVector3 m_velocity; + btVector3 m_drift; + int m_asVelocity:1; + int m_asDrift:1; + Impulse() : m_velocity(0,0,0),m_drift(0,0,0),m_asVelocity(0),m_asDrift(0) {} + Impulse operator -() const + { + Impulse i=*this; + i.m_velocity=-i.m_velocity; + i.m_drift=-i.m_drift; + return(i); + } + Impulse operator*(btScalar x) const + { + Impulse i=*this; + i.m_velocity*=x; + i.m_drift*=x; + return(i); + } + }; + /* Body */ + struct Body + { + Cluster* m_soft; + btRigidBody* m_rigid; + Body() : m_soft(0),m_rigid(0) {} + Body(Cluster* p) : m_soft(p),m_rigid(0) {} + Body(btRigidBody* p) : m_soft(0),m_rigid(p) {} + void activate() const + { + if(m_rigid) m_rigid->activate(); + } + const btMatrix3x3& invWorldInertia() const + { + static const btMatrix3x3 iwi(0,0,0,0,0,0,0,0,0); + if(m_rigid) return(m_rigid->getInvInertiaTensorWorld()); + if(m_soft) return(m_soft->m_invwi); + return(iwi); + } + btScalar invMass() const + { + if(m_rigid) return(m_rigid->getInvMass()); + if(m_soft) return(m_soft->m_imass); + return(0); + } + const btTransform& xform() const + { + static const btTransform identity=btTransform::getIdentity(); + if(m_rigid) return(m_rigid->getInterpolationWorldTransform()); + if(m_soft) return(m_soft->m_framexform); + return(identity); + } + btVector3 linearVelocity() const + { + if(m_rigid) return(m_rigid->getLinearVelocity()); + if(m_soft) return(m_soft->m_lv); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity(const btVector3& rpos) const + { + if(m_rigid) return(cross(m_rigid->getAngularVelocity(),rpos)); + if(m_soft) return(cross(m_soft->m_av,rpos)); + return(btVector3(0,0,0)); + } + btVector3 angularVelocity() const + { + if(m_rigid) return(m_rigid->getAngularVelocity()); + if(m_soft) return(m_soft->m_av); + return(btVector3(0,0,0)); + } + btVector3 velocity(const btVector3& rpos) const + { + return(linearVelocity()+angularVelocity(rpos)); + } + void applyVImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterVImpulse(m_soft,rpos,impulse); + } + void applyDImpulse(const btVector3& impulse,const btVector3& rpos) const + { + if(m_rigid) m_rigid->applyImpulse(impulse,rpos); + if(m_soft) btSoftBody::clusterDImpulse(m_soft,rpos,impulse); + } + void applyImpulse(const Impulse& impulse,const btVector3& rpos) const + { + if(impulse.m_asVelocity) applyVImpulse(impulse.m_velocity,rpos); + if(impulse.m_asDrift) applyDImpulse(impulse.m_drift,rpos); + } + void applyVAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterVAImpulse(m_soft,impulse); + } + void applyDAImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyTorqueImpulse(impulse); + if(m_soft) btSoftBody::clusterDAImpulse(m_soft,impulse); + } + void applyAImpulse(const Impulse& impulse) const + { + if(impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity); + if(impulse.m_asDrift) applyDAImpulse(impulse.m_drift); + } + void applyDCImpulse(const btVector3& impulse) const + { + if(m_rigid) m_rigid->applyCentralImpulse(impulse); + if(m_soft) btSoftBody::clusterDCImpulse(m_soft,impulse); + } + }; + /* Joint */ + struct Joint + { + struct eType { enum _ { + Linear, + Angular, + Contact, + };}; + struct Specs + { + Specs() : erp(1),cfm(1),split(1) {} + btScalar erp; + btScalar cfm; + btScalar split; + }; + Body m_bodies[2]; + btVector3 m_refs[2]; + btScalar m_cfm; + btScalar m_erp; + btScalar m_split; + btVector3 m_drift; + btVector3 m_sdrift; + btMatrix3x3 m_massmatrix; + bool m_delete; + virtual ~Joint() {} + Joint() : m_delete(false) {} + virtual void Prepare(btScalar dt,int iterations); + virtual void Solve(btScalar dt,btScalar sor)=0; + virtual void Terminate(btScalar dt)=0; + virtual eType::_ Type() const=0; + }; + /* LJoint */ + struct LJoint : Joint + { + struct Specs : Joint::Specs + { + btVector3 position; + }; + btVector3 m_rpos[2]; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Linear); } + }; + /* AJoint */ + struct AJoint : Joint + { + struct IControl + { + virtual void Prepare(AJoint*) {} + virtual btScalar Speed(AJoint*,btScalar current) { return(current); } + static IControl* Default() { static IControl def;return(&def); } + }; + struct Specs : Joint::Specs + { + Specs() : icontrol(IControl::Default()) {} + btVector3 axis; + IControl* icontrol; + }; + btVector3 m_axis[2]; + IControl* m_icontrol; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Angular); } + }; + /* CJoint */ + struct CJoint : Joint + { + int m_life; + int m_maxlife; + btVector3 m_rpos[2]; + btVector3 m_normal; + btScalar m_friction; + void Prepare(btScalar dt,int iterations); + void Solve(btScalar dt,btScalar sor); + void Terminate(btScalar dt); + eType::_ Type() const { return(eType::Contact); } + }; + /* Config */ + struct Config + { + eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point) + btScalar kVCF; // Velocities correction factor (Baumgarte) + btScalar kDP; // Damping coefficient [0,1] + btScalar kDG; // Drag coefficient [0,+inf] + btScalar kLF; // Lift coefficient [0,+inf] + btScalar kPR; // Pressure coefficient [-inf,+inf] + btScalar kVC; // Volume conversation coefficient [0,+inf] + btScalar kDF; // Dynamic friction coefficient [0,1] + btScalar kMT; // Pose matching coefficient [0,1] + btScalar kCHR; // Rigid contacts hardness [0,1] + btScalar kKHR; // Kinetic contacts hardness [0,1] + btScalar kSHR; // Soft contacts hardness [0,1] + btScalar kAHR; // Anchors hardness [0,1] + btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only) + btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only) + btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only) + btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only) + btScalar maxvolume; // Maximum volume ratio for pose + btScalar timescale; // Time scale + int viterations; // Velocities solver iterations + int piterations; // Positions solver iterations + int diterations; // Drift solver iterations + int citerations; // Cluster solver iterations + int collisions; // Collisions flags + tVSolverArray m_vsequence; // Velocity solvers sequence + tPSolverArray m_psequence; // Position solvers sequence + tPSolverArray m_dsequence; // Drift solvers sequence + }; + /* SolverState */ + struct SolverState + { + btScalar sdt; // dt*timescale + btScalar isdt; // 1/sdt + btScalar velmrg; // velocity margin + btScalar radmrg; // radial margin + btScalar updmrg; // Update margin + }; + /* RayCaster */ + struct RayCaster : btDbvt::ICollide + { + btVector3 o; + btVector3 d; + btScalar mint; + Face* face; + int tests; + RayCaster(const btVector3& org,const btVector3& dir,btScalar mxt); + void Process(const btDbvtNode* leaf); + static inline btScalar rayTriangle(const btVector3& org, + const btVector3& dir, + const btVector3& a, + const btVector3& b, + const btVector3& c, + btScalar maxt=SIMD_INFINITY); + }; + + // + // Typedef's + // + + typedef void (*psolver_t)(btSoftBody*,btScalar,btScalar); + typedef void (*vsolver_t)(btSoftBody*,btScalar); + typedef btAlignedObjectArray tClusterArray; + typedef btAlignedObjectArray tNoteArray; + typedef btAlignedObjectArray tNodeArray; + typedef btAlignedObjectArray tLeafArray; + typedef btAlignedObjectArray tLinkArray; + typedef btAlignedObjectArray tFaceArray; + typedef btAlignedObjectArray tAnchorArray; + typedef btAlignedObjectArray tRContactArray; + typedef btAlignedObjectArray tSContactArray; + typedef btAlignedObjectArray tMaterialArray; + typedef btAlignedObjectArray tJointArray; + typedef btAlignedObjectArray tSoftBodyArray; + + // + // Fields + // + + Config m_cfg; // Configuration + SolverState m_sst; // Solver state + Pose m_pose; // Pose + void* m_tag; // User data + btSoftBodyWorldInfo* m_worldInfo; // World info + tNoteArray m_notes; // Notes + tNodeArray m_nodes; // Nodes + tLinkArray m_links; // Links + tFaceArray m_faces; // Faces + tAnchorArray m_anchors; // Anchors + tRContactArray m_rcontacts; // Rigid contacts + tSContactArray m_scontacts; // Soft contacts + tJointArray m_joints; // Joints + tMaterialArray m_materials; // Materials + btScalar m_timeacc; // Time accumulator + btVector3 m_bounds[2]; // Spatial bounds + bool m_bUpdateRtCst; // Update runtime constants + btDbvt m_ndbvt; // Nodes tree + btDbvt m_fdbvt; // Faces tree + btDbvt m_cdbvt; // Clusters tree + tClusterArray m_clusters; // Clusters + + // + // Api + // + + /* ctor */ + btSoftBody( btSoftBodyWorldInfo* worldInfo,int node_count, + const btVector3* x, + const btScalar* m); + /* dtor */ + virtual ~btSoftBody(); + /* Check for existing link */ + bool checkLink( int node0, + int node1) const; + bool checkLink( const Node* node0, + const Node* node1) const; + /* Check for existring face */ + bool checkFace( int node0, + int node1, + int node2) const; + /* Append material */ + Material* appendMaterial(); + /* Append note */ + void appendNote( const char* text, + const btVector3& o, + const btVector4& c=btVector4(1,0,0,0), + Node* n0=0, + Node* n1=0, + Node* n2=0, + Node* n3=0); + void appendNote( const char* text, + const btVector3& o, + Node* feature); + void appendNote( const char* text, + const btVector3& o, + Link* feature); + void appendNote( const char* text, + const btVector3& o, + Face* feature); + /* Append node */ + void appendNode( const btVector3& x,btScalar m); + /* Append link */ + void appendLink(int model=-1,Material* mat=0); + void appendLink( int node0, + int node1, + Material* mat=0, + bool bcheckexist=false); + void appendLink( Node* node0, + Node* node1, + Material* mat=0, + bool bcheckexist=false); + /* Append face */ + void appendFace(int model=-1,Material* mat=0); + void appendFace( int node0, + int node1, + int node2, + Material* mat=0); + /* Append anchor */ + void appendAnchor( int node, + btRigidBody* body); + /* Append linear joint */ + void appendLinearJoint(const LJoint::Specs& specs,Cluster* body0,Body body1); + void appendLinearJoint(const LJoint::Specs& specs,Body body=Body()); + void appendLinearJoint(const LJoint::Specs& specs,btSoftBody* body); + /* Append linear joint */ + void appendAngularJoint(const AJoint::Specs& specs,Cluster* body0,Body body1); + void appendAngularJoint(const AJoint::Specs& specs,Body body=Body()); + void appendAngularJoint(const AJoint::Specs& specs,btSoftBody* body); + /* Add force (or gravity) to the entire body */ + void addForce( const btVector3& force); + /* Add force (or gravity) to a node of the body */ + void addForce( const btVector3& force, + int node); + /* Add velocity to the entire body */ + void addVelocity( const btVector3& velocity); + /* Add velocity to a node of the body */ + void addVelocity( const btVector3& velocity, + int node); + /* Set mass */ + void setMass( int node, + btScalar mass); + /* Get mass */ + btScalar getMass( int node) const; + /* Get total mass */ + btScalar getTotalMass() const; + /* Set total mass (weighted by previous masses) */ + void setTotalMass( btScalar mass, + bool fromfaces=false); + /* Set total density */ + void setTotalDensity(btScalar density); + /* Transform */ + void transform( const btTransform& trs); + /* Translate */ + void translate( const btVector3& trs); + /* Rotate */ + void rotate( const btQuaternion& rot); + /* Scale */ + void scale( const btVector3& scl); + /* Set current state as pose */ + void setPose( bool bvolume, + bool bframe); + /* Return the volume */ + btScalar getVolume() const; + /* Cluster count */ + int clusterCount() const; + /* Cluster center of mass */ + static btVector3 clusterCom(const Cluster* cluster); + btVector3 clusterCom(int cluster) const; + /* Cluster velocity at rpos */ + static btVector3 clusterVelocity(const Cluster* cluster,const btVector3& rpos); + /* Cluster impulse */ + static void clusterVImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterDImpulse(Cluster* cluster,const btVector3& rpos,const btVector3& impulse); + static void clusterImpulse(Cluster* cluster,const btVector3& rpos,const Impulse& impulse); + static void clusterVAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterDAImpulse(Cluster* cluster,const btVector3& impulse); + static void clusterAImpulse(Cluster* cluster,const Impulse& impulse); + static void clusterDCImpulse(Cluster* cluster,const btVector3& impulse); + /* Generate bending constraints based on distance in the adjency graph */ + int generateBendingConstraints( int distance, + Material* mat=0); + /* Randomize constraints to reduce solver bias */ + void randomizeConstraints(); + /* Release clusters */ + void releaseCluster(int index); + void releaseClusters(); + /* Generate clusters (K-mean) */ + int generateClusters(int k,int maxiterations=8192); + /* Refine */ + void refine(ImplicitFn* ifn,btScalar accurary,bool cut); + /* CutLink */ + bool cutLink(int node0,int node1,btScalar position); + bool cutLink(const Node* node0,const Node* node1,btScalar position); + /* Ray casting */ + bool rayCast(const btVector3& org, + const btVector3& dir, + sRayCast& results, + btScalar maxtime=SIMD_INFINITY); + /* Solver presets */ + void setSolver(eSolverPresets::_ preset); + /* predictMotion */ + void predictMotion(btScalar dt); + /* solveConstraints */ + void solveConstraints(); + /* staticSolve */ + void staticSolve(int iterations); + /* solveCommonConstraints */ + static void solveCommonConstraints(btSoftBody** bodies,int count,int iterations); + /* solveClusters */ + static void solveClusters(const btAlignedObjectArray& bodies); + /* integrateMotion */ + void integrateMotion(); + /* defaultCollisionHandlers */ + void defaultCollisionHandler(btCollisionObject* pco); + void defaultCollisionHandler(btSoftBody* psb); + + // + // Cast + // + + static const btSoftBody* upcast(const btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (const btSoftBody*)colObj; + return 0; + } + static btSoftBody* upcast(btCollisionObject* colObj) + { + if (colObj->getInternalType()==CO_SOFT_BODY) + return (btSoftBody*)colObj; + return 0; + } + + // + // ::btCollisionObject + // + + virtual void getAabb(btVector3& aabbMin,btVector3& aabbMax) const + { + aabbMin = m_bounds[0]; + aabbMax = m_bounds[1]; + } + // + // Private + // + void pointersToIndices(); + void indicesToPointers(const int* map=0); + int rayCast(const btVector3& org,const btVector3& dir, + btScalar& mint,eFeature::_& feature,int& index,bool bcountonly) const; + void initializeFaceTree(); + btVector3 evaluateCom() const; + bool checkContact(btRigidBody* prb,const btVector3& x,btScalar margin,btSoftBody::sCti& cti) const; + void updateNormals(); + void updateBounds(); + void updatePose(); + void updateConstants(); + void initializeClusters(); + void updateClusters(); + void cleanupClusters(); + void prepareClusters(int iterations); + void solveClusters(btScalar sor); + void applyClusters(bool drift); + void dampClusters(); + void applyForces(); + static void PSolve_Anchors(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_RContacts(btSoftBody* psb,btScalar kst,btScalar ti); + static void PSolve_SContacts(btSoftBody* psb,btScalar,btScalar ti); + static void PSolve_Links(btSoftBody* psb,btScalar kst,btScalar ti); + static void VSolve_Links(btSoftBody* psb,btScalar kst); + static psolver_t getSolver(ePSolver::_ solver); + static vsolver_t getSolver(eVSolver::_ solver); + +}; + + + +#endif //_BT_SOFT_BODY_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp new file mode 100644 index 00000000000..5e3211ed73b --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp @@ -0,0 +1,410 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "BulletCollision/CollisionShapes/btConvexHullShape.h" + + + +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h" +#include "BulletSoftBody/btSoftBody.h" + +#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.3) + +btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) +: btCollisionAlgorithm(ci), +m_isSwapped(isSwapped), +m_btSoftBodyTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped) +{ +} + + + +btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm() +{ +} + + + +btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped): + m_dispatcher(dispatcher), + m_dispatchInfoPtr(0) +{ + m_softBody = (btSoftBody*) (isSwapped? body1:body0); + m_triBody = isSwapped? body0:body1; + + // + // create the manifold from the dispatcher 'manifold pool' + // +// m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody); + + clearCache(); +} + +btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback() +{ + clearCache(); +// m_dispatcher->releaseManifold( m_manifoldPtr ); + +} + + +void btSoftBodyTriangleCallback::clearCache() +{ + //m_dispatcher->clearManifold(m_manifoldPtr); +}; + + +static const int maxParts = 1; +static const int maxTriangleIndex = 100*100; + +btCollisionShape* shapeCache[maxParts][maxTriangleIndex]; + + +void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex) +{ + static bool hackedFirst = true; + if (hackedFirst) + { + hackedFirst = false; + int i,j; + for (i=0;i(m_triBody); + btCollisionAlgorithmConstructionInfo ci; + ci.m_dispatcher1 = m_dispatcher; + + ///debug drawing of the overlapping triangles + if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && m_dispatchInfoPtr->m_debugDraw->getDebugMode() > 0) + { + btVector3 color(255,255,0); + btTransform& tr = ob->getWorldTransform(); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color); + m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color); + + //btVector3 center = triangle[0] + triangle[1]+triangle[2]; + //center *= btScalar(0.333333); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color); + //m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color); + + } + + if (shapeCache[partId][triangleIndex]) + { + btCollisionShape* tm = shapeCache[partId][triangleIndex]; + + //copy over user pointers to temporary shape + tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); + + colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape); + return; + } + + //aabb filter is already applied! + + + + + + + + + //btCollisionObject* colObj = static_cast(m_convexProxy->m_clientObject); + +// if (m_softBody->getCollisionShape()->getShapeType()== + { +// btVector3 other; + btVector3 normal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + normal.normalize(); + normal*= BT_SOFTBODY_TRIANGLE_EXTRUSION; +// other=(triangle[0]+triangle[1]+triangle[2])*0.333333f; +// other+=normal*22.f; + btVector3 pts[6] = {triangle[0]+normal, + triangle[1]+normal, + triangle[2]+normal, + triangle[0]-normal, + triangle[1]-normal, + triangle[2]-normal}; + + btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(),6); + + +// btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other); + + //btTriangleShape tm(triangle[0],triangle[1],triangle[2]); + // tm.setMargin(m_collisionMarginTriangle); + + //copy over user pointers to temporary shape + tm->setUserPointer(ob->getRootCollisionShape()->getUserPointer()); + + btCollisionShape* tmpShape = ob->getCollisionShape(); + ob->internalSetTemporaryCollisionShape( tm ); + + + btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_softBody,m_triBody,0);//m_manifoldPtr); + ///this should use the btDispatcher, so the actual registered algorithm is used + // btConvexConvexAlgorithm cvxcvxalgo(m_manifoldPtr,ci,m_convexBody,m_triBody); + + //m_resultOut->setShapeIdentifiers(-1,-1,partId,triangleIndex); + // cvxcvxalgo.setShapeIdentifiers(-1,-1,partId,triangleIndex); +// cvxcvxalgo.processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->processCollision(m_softBody,m_triBody,*m_dispatchInfoPtr,m_resultOut); + colAlgo->~btCollisionAlgorithm(); + ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo); + ob->internalSetTemporaryCollisionShape( tmpShape ); +// delete tm; + + shapeCache[partId][triangleIndex] = tm; + + } + + + +} + + + +void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + m_dispatchInfoPtr = &dispatchInfo; + m_collisionMarginTriangle = collisionMarginTriangle; + m_resultOut = resultOut; + + //recalc aabbs +// btTransform softbodyInTriangleSpace; +// softbodyInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_softBody->getWorldTransform(); +// btCollisionShape* convexShape = static_cast(m_convexBody->getCollisionShape()); + //CollisionShape* triangleShape = static_cast(triBody->m_collisionShape); + btVector3 aabbWorldSpaceMin,aabbWorldSpaceMax; + m_softBody->getAabb(aabbWorldSpaceMin,aabbWorldSpaceMax); + + btVector3 halfExtents = (aabbWorldSpaceMax-aabbWorldSpaceMin)*btScalar(0.5); + btVector3 softBodyCenter = (aabbWorldSpaceMax+aabbWorldSpaceMin)*btScalar(0.5); + + btTransform triInverse = m_triBody->getWorldTransform().inverse(); + + btMatrix3x3 abs_b = triInverse.getBasis().absolute(); + btPoint3 center = softBodyCenter + triInverse.getOrigin(); + + btVector3 extent = btVector3(abs_b[0].dot(halfExtents), + abs_b[1].dot(halfExtents), + abs_b[2].dot(halfExtents)); +// extent += btVector3(getMargin(),getMargin(),getMargin()); + + m_aabbMin = center - extent; + m_aabbMax = center + extent; + + btScalar extraMargin = collisionMarginTriangle+btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION); + btVector3 extra(extraMargin,extraMargin,extraMargin); + + m_aabbMax += extra; + m_aabbMin -= extra; + +/* btVector3 extra(2,2,2); + m_aabbMin = aabbWorldSpaceMin-extra; + m_aabbMax = aabbWorldSpaceMax+extra; +*/ + +} + +void btSoftBodyConcaveCollisionAlgorithm::clearCache() +{ + m_btSoftBodyTriangleCallback.clearCache(); + +} + +void btSoftBodyConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + + + btCollisionObject* convexBody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + if (triBody->getCollisionShape()->isConcave()) + { + + + btCollisionObject* triOb = triBody; + btConcaveShape* concaveShape = static_cast( triOb->getCollisionShape()); + + // if (convexBody->getCollisionShape()->isConvex()) + { + btScalar collisionMarginTriangle = concaveShape->getMargin(); + +// resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut); + + //Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here. + //m_dispatcher->clearManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr); + +// m_btSoftBodyTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody); + + + concaveShape->processAllTriangles( &m_btSoftBodyTriangleCallback,m_btSoftBodyTriangleCallback.getAabbMin(),m_btSoftBodyTriangleCallback.getAabbMax()); + + // resultOut->refreshContactPoints(); + + } + + } + +} + + +btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + btCollisionObject* convexbody = m_isSwapped ? body1 : body0; + btCollisionObject* triBody = m_isSwapped ? body0 : body1; + + + //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast) + + //only perform CCD above a certain threshold, this prevents blocking on the long run + //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame... + btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2(); + if (squareMot0 < convexbody->getCcdSquareMotionThreshold()) + { + return btScalar(1.); + } + + //const btVector3& from = convexbody->m_worldTransform.getOrigin(); + //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin(); + //todo: only do if the motion exceeds the 'radius' + + btTransform triInv = triBody->getWorldTransform().inverse(); + btTransform convexFromLocal = triInv * convexbody->getWorldTransform(); + btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform(); + + struct LocalTriangleSphereCastCallback : public btTriangleCallback + { + btTransform m_ccdSphereFromTrans; + btTransform m_ccdSphereToTrans; + btTransform m_meshTransform; + + btScalar m_ccdSphereRadius; + btScalar m_hitFraction; + + + LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction) + :m_ccdSphereFromTrans(from), + m_ccdSphereToTrans(to), + m_ccdSphereRadius(ccdSphereRadius), + m_hitFraction(hitFraction) + { + } + + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + (void)partId; + (void)triangleIndex; + //do a swept sphere for now + btTransform ident; + ident.setIdentity(); + btConvexCast::CastResult castResult; + castResult.m_fraction = m_hitFraction; + btSphereShape pointShape(m_ccdSphereRadius); + btTriangleShape triShape(triangle[0],triangle[1],triangle[2]); + btVoronoiSimplexSolver simplexSolver; + btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver); + //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver); + //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0); + //local space? + + if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans, + ident,ident,castResult)) + { + if (m_hitFraction > castResult.m_fraction) + m_hitFraction = castResult.m_fraction; + } + + } + + }; + + + + + + if (triBody->getCollisionShape()->isConcave()) + { + btVector3 rayAabbMin = convexFromLocal.getOrigin(); + rayAabbMin.setMin(convexToLocal.getOrigin()); + btVector3 rayAabbMax = convexFromLocal.getOrigin(); + rayAabbMax.setMax(convexToLocal.getOrigin()); + btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius(); + rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0); + + btScalar curHitFraction = btScalar(1.); //is this available? + LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal, + convexbody->getCcdSweptSphereRadius(),curHitFraction); + + raycastCallback.m_hitFraction = convexbody->getHitFraction(); + + btCollisionObject* concavebody = triBody; + + btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape(); + + if (triangleMesh) + { + triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax); + } + + + + if (raycastCallback.m_hitFraction < convexbody->getHitFraction()) + { + convexbody->setHitFraction( raycastCallback.m_hitFraction); + return raycastCallback.m_hitFraction; + } + } + + return btScalar(1.); + +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h new file mode 100644 index 00000000000..adb91329a4c --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h @@ -0,0 +1,118 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H +#define SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionShapes/btTriangleCallback.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btSoftBody; + +///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called. +class btSoftBodyTriangleCallback : public btTriangleCallback +{ + btSoftBody* m_softBody; + btCollisionObject* m_triBody; + + btVector3 m_aabbMin; + btVector3 m_aabbMax ; + + btManifoldResult* m_resultOut; + + btDispatcher* m_dispatcher; + const btDispatcherInfo* m_dispatchInfoPtr; + btScalar m_collisionMarginTriangle; + +public: +int m_triangleCount; + +// btPersistentManifold* m_manifoldPtr; + + btSoftBodyTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + void setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual ~btSoftBodyTriangleCallback(); + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex); + + void clearCache(); + + SIMD_FORCE_INLINE const btVector3& getAabbMin() const + { + return m_aabbMin; + } + SIMD_FORCE_INLINE const btVector3& getAabbMax() const + { + return m_aabbMax; + } + +}; + + + + +/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes. +class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm +{ + + bool m_isSwapped; + + btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback; + +public: + + btSoftBodyConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped); + + virtual ~btSoftBodyConcaveCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + void clearCache(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,false); + } + }; + + struct SwappedCreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm)); + return new(mem) btSoftBodyConcaveCollisionAlgorithm(ci,body0,body1,true); + } + }; + +}; + +#endif //SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp new file mode 100644 index 00000000000..d9919967233 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -0,0 +1,653 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBodyHelpers.cpp by Nathanael Presson + +#include "btSoftBodyInternals.h" +#include +#include +#include "btSoftBodyHelpers.h" +#include "LinearMath/btConvexHull.h" + +// +static void drawVertex( btIDebugDraw* idraw, + const btVector3& x,btScalar s,const btVector3& c) + { + idraw->drawLine(x-btVector3(s,0,0),x+btVector3(s,0,0),c); + idraw->drawLine(x-btVector3(0,s,0),x+btVector3(0,s,0),c); + idraw->drawLine(x-btVector3(0,0,s),x+btVector3(0,0,s),c); + } + +// +static void drawBox( btIDebugDraw* idraw, + const btVector3& mins, + const btVector3& maxs, + const btVector3& color) +{ +const btVector3 c[]={ btVector3(mins.x(),mins.y(),mins.z()), + btVector3(maxs.x(),mins.y(),mins.z()), + btVector3(maxs.x(),maxs.y(),mins.z()), + btVector3(mins.x(),maxs.y(),mins.z()), + btVector3(mins.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),mins.y(),maxs.z()), + btVector3(maxs.x(),maxs.y(),maxs.z()), + btVector3(mins.x(),maxs.y(),maxs.z())}; +idraw->drawLine(c[0],c[1],color);idraw->drawLine(c[1],c[2],color); +idraw->drawLine(c[2],c[3],color);idraw->drawLine(c[3],c[0],color); +idraw->drawLine(c[4],c[5],color);idraw->drawLine(c[5],c[6],color); +idraw->drawLine(c[6],c[7],color);idraw->drawLine(c[7],c[4],color); +idraw->drawLine(c[0],c[4],color);idraw->drawLine(c[1],c[5],color); +idraw->drawLine(c[2],c[6],color);idraw->drawLine(c[3],c[7],color); +} + +// +static void drawTree( btIDebugDraw* idraw, + const btDbvtNode* node, + int depth, + const btVector3& ncolor, + const btVector3& lcolor, + int mindepth, + int maxdepth) +{ +if(node) + { + if(node->isinternal()&&((depthchilds[0],depth+1,ncolor,lcolor,mindepth,maxdepth); + drawTree(idraw,node->childs[1],depth+1,ncolor,lcolor,mindepth,maxdepth); + } + if(depth>=mindepth) + { + const btScalar scl=(btScalar)(node->isinternal()?1:1); + const btVector3 mi=node->volume.Center()-node->volume.Extents()*scl; + const btVector3 mx=node->volume.Center()+node->volume.Extents()*scl; + drawBox(idraw,mi,mx,node->isleaf()?lcolor:ncolor); + } + } +} + +// +template +static inline T sum(const btAlignedObjectArray& items) +{ +T v; +if(items.size()) + { + v=items[0]; + for(int i=1,ni=items.size();i +static inline void add(btAlignedObjectArray& items,const Q& value) +{ +for(int i=0,ni=items.size();i +static inline void mul(btAlignedObjectArray& items,const Q& value) +{ +for(int i=0,ni=items.size();i +static inline T average(const btAlignedObjectArray& items) +{ +const btScalar n=(btScalar)(items.size()>0?items.size():1); +return(sum(items)/n); +} + +// +static inline btScalar tetravolume(const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(dot(a,cross(b,c))); +} + +// +#if 0 +static btVector3 stresscolor(btScalar stress) + { + static const btVector3 spectrum[]= { btVector3(1,0,1), + btVector3(0,0,1), + btVector3(0,1,1), + btVector3(0,1,0), + btVector3(1,1,0), + btVector3(1,0,0), + btVector3(1,0,0)}; + static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1; + static const btScalar one=1; + stress=btMax(0,btMin(1,stress))*ncolors; + const int sel=(int)stress; + const btScalar frc=stress-sel; + return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc); + } +#endif + +// +void btSoftBodyHelpers::Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags) +{ + const btScalar scl=(btScalar)0.1; + const btScalar nscl=scl*5; + const btVector3 lcolor=btVector3(0,0,0); + const btVector3 ncolor=btVector3(1,1,1); + const btVector3 ccolor=btVector3(1,0,0); + int i,j,nj; + + /* Nodes */ + if(0!=(drawflags&fDrawFlags::Nodes)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(n.m_x-btVector3(scl,0,0),n.m_x+btVector3(scl,0,0),btVector3(1,0,0)); + idraw->drawLine(n.m_x-btVector3(0,scl,0),n.m_x+btVector3(0,scl,0),btVector3(0,1,0)); + idraw->drawLine(n.m_x-btVector3(0,0,scl),n.m_x+btVector3(0,0,scl),btVector3(0,0,1)); + } + } + /* Links */ + if(0!=(drawflags&fDrawFlags::Links)) + { + for(i=0;im_links.size();++i) + { + const btSoftBody::Link& l=psb->m_links[i]; + if(0==(l.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + idraw->drawLine(l.m_n[0]->m_x,l.m_n[1]->m_x,lcolor); + } + } + /* Normals */ + if(0!=(drawflags&fDrawFlags::Normals)) + { + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 d=n.m_n*nscl; + idraw->drawLine(n.m_x,n.m_x+d,ncolor); + idraw->drawLine(n.m_x,n.m_x-d,ncolor*0.5); + } + } + /* Contacts */ + if(0!=(drawflags&fDrawFlags::Contacts)) + { + static const btVector3 axis[]={btVector3(1,0,0), + btVector3(0,1,0), + btVector3(0,0,1)}; + for(i=0;im_rcontacts.size();++i) + { + const btSoftBody::RContact& c=psb->m_rcontacts[i]; + const btVector3 o= c.m_node->m_x-c.m_cti.m_normal* + (dot(c.m_node->m_x,c.m_cti.m_normal)+c.m_cti.m_offset); + const btVector3 x=cross(c.m_cti.m_normal,axis[c.m_cti.m_normal.minAxis()]).normalized(); + const btVector3 y=cross(x,c.m_cti.m_normal).normalized(); + idraw->drawLine(o-x*nscl,o+x*nscl,ccolor); + idraw->drawLine(o-y*nscl,o+y*nscl,ccolor); + idraw->drawLine(o,o+c.m_cti.m_normal*nscl*3,btVector3(1,1,0)); + } + } + /* Anchors */ + if(0!=(drawflags&fDrawFlags::Anchors)) + { + for(i=0;im_anchors.size();++i) + { + const btSoftBody::Anchor& a=psb->m_anchors[i]; + const btVector3 q=a.m_body->getWorldTransform()*a.m_local; + drawVertex(idraw,a.m_node->m_x,0.25,btVector3(1,0,0)); + drawVertex(idraw,q,0.25,btVector3(0,1,0)); + idraw->drawLine(a.m_node->m_x,q,btVector3(1,1,1)); + } + for(i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + if(0==(n.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + if(n.m_im<=0) + { + drawVertex(idraw,n.m_x,0.25,btVector3(1,0,0)); + } + } + } + /* Faces */ + if(0!=(drawflags&fDrawFlags::Faces)) + { + const btScalar scl=(btScalar)0.8; + const btScalar alp=(btScalar)1; + const btVector3 col(0,(btScalar)0.7,0); + for(i=0;im_faces.size();++i) + { + const btSoftBody::Face& f=psb->m_faces[i]; + if(0==(f.m_material->m_flags&btSoftBody::fMaterial::DebugDraw)) continue; + const btVector3 x[]={f.m_n[0]->m_x,f.m_n[1]->m_x,f.m_n[2]->m_x}; + const btVector3 c=(x[0]+x[1]+x[2])/3; + idraw->drawTriangle((x[0]-c)*scl+c, + (x[1]-c)*scl+c, + (x[2]-c)*scl+c, + col,alp); + } + } + /* Clusters */ + if(0!=(drawflags&fDrawFlags::Clusters)) + { + srand(1806); + for(i=0;im_clusters.size();++i) + { + if(psb->m_clusters[i]->m_collide) + { + btVector3 color( rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX, + rand()/(btScalar)RAND_MAX); + color=color.normalized()*0.75; + btAlignedObjectArray vertices; + vertices.resize(psb->m_clusters[i]->m_nodes.size()); + for(j=0,nj=vertices.size();jm_clusters[i]->m_nodes[j]->m_x; + } + HullDesc hdsc(QF_TRIANGLES,vertices.size(),&vertices[0]); + HullResult hres; + HullLibrary hlib; + hdsc.mMaxVertices=vertices.size(); + hlib.CreateConvexHull(hdsc,hres); + const btVector3 center=average(hres.m_OutputVertices); + add(hres.m_OutputVertices,-center); + mul(hres.m_OutputVertices,(btScalar)1); + add(hres.m_OutputVertices,center); + for(j=0;j<(int)hres.mNumFaces;++j) + { + const int idx[]={hres.m_Indices[j*3+0],hres.m_Indices[j*3+1],hres.m_Indices[j*3+2]}; + idraw->drawTriangle(hres.m_OutputVertices[idx[0]], + hres.m_OutputVertices[idx[1]], + hres.m_OutputVertices[idx[2]], + color,1); + } + hlib.ReleaseResult(hres); + } + /* Velocities */ + #if 0 + for(int j=0;jm_clusters[i].m_nodes.size();++j) + { + const btSoftBody::Cluster& c=psb->m_clusters[i]; + const btVector3 r=c.m_nodes[j]->m_x-c.m_com; + const btVector3 v=c.m_lv+cross(c.m_av,r); + idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0)); + } + #endif + /* Frame */ + btSoftBody::Cluster& c=*psb->m_clusters[i]; + idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0)); + idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0)); + idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1)); + } + } + /* Notes */ + if(0!=(drawflags&fDrawFlags::Notes)) + { + for(i=0;im_notes.size();++i) + { + const btSoftBody::Note& n=psb->m_notes[i]; + btVector3 p=n.m_offset; + for(int j=0;jm_x*n.m_coords[j]; + } + idraw->draw3dText(p,n.m_text); + } + } + /* Node tree */ + if(0!=(drawflags&fDrawFlags::NodeTree)) DrawNodeTree(psb,idraw); + /* Face tree */ + if(0!=(drawflags&fDrawFlags::FaceTree)) DrawFaceTree(psb,idraw); + /* Cluster tree */ + if(0!=(drawflags&fDrawFlags::ClusterTree)) DrawClusterTree(psb,idraw); + /* Joints */ + if(0!=(drawflags&fDrawFlags::Joints)) + { + for(i=0;im_joints.size();++i) + { + const btSoftBody::Joint* pj=psb->m_joints[i]; + switch(pj->Type()) + { + case btSoftBody::Joint::eType::Linear: + { + const btSoftBody::LJoint* pjl=(const btSoftBody::LJoint*)pj; + const btVector3 a0=pj->m_bodies[0].xform()*pjl->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform()*pjl->m_refs[1]; + idraw->drawLine(pj->m_bodies[0].xform().getOrigin(),a0,btVector3(1,1,0)); + idraw->drawLine(pj->m_bodies[1].xform().getOrigin(),a1,btVector3(0,1,1)); + drawVertex(idraw,a0,0.25,btVector3(1,1,0)); + drawVertex(idraw,a1,0.25,btVector3(0,1,1)); + } + break; + case btSoftBody::Joint::eType::Angular: + { + const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj; + const btVector3 o0=pj->m_bodies[0].xform().getOrigin(); + const btVector3 o1=pj->m_bodies[1].xform().getOrigin(); + const btVector3 a0=pj->m_bodies[0].xform().getBasis()*pj->m_refs[0]; + const btVector3 a1=pj->m_bodies[1].xform().getBasis()*pj->m_refs[1]; + idraw->drawLine(o0,o0+a0*10,btVector3(1,1,0)); + idraw->drawLine(o0,o0+a1*10,btVector3(1,1,0)); + idraw->drawLine(o1,o1+a0*10,btVector3(0,1,1)); + idraw->drawLine(o1,o1+a1*10,btVector3(0,1,1)); + } + } + } + } +} + +// +void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool /*stress*/) +{ + for(int i=0;im_nodes.size();++i) + { + const btSoftBody::Node& n=psb->m_nodes[i]; + char text[2048]={0}; + char buff[1024]; + if(masses) + { + sprintf(buff," M(%.2f)",1/n.m_im); + strcat(text,buff); + } + if(areas) + { + sprintf(buff," A(%.2f)",n.m_area); + strcat(text,buff); + } + if(text[0]) idraw->draw3dText(n.m_x,text); + } +} + +// +void btSoftBodyHelpers::DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_ndbvt.m_root,0,btVector3(1,0,1),btVector3(1,1,1),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_fdbvt.m_root,0,btVector3(0,1,0),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawClusterTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth, + int maxdepth) +{ +drawTree(idraw,psb->m_cdbvt.m_root,0,btVector3(0,1,1),btVector3(1,0,0),mindepth,maxdepth); +} + +// +void btSoftBodyHelpers::DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw) +{ + if(psb->m_pose.m_bframe) + { + static const btScalar ascl=10; + static const btScalar nscl=(btScalar)0.1; + const btVector3 com=psb->m_pose.m_com; + const btMatrix3x3 trs=psb->m_pose.m_rot*psb->m_pose.m_scl; + const btVector3 Xaxis=(trs*btVector3(1,0,0)).normalized(); + const btVector3 Yaxis=(trs*btVector3(0,1,0)).normalized(); + const btVector3 Zaxis=(trs*btVector3(0,0,1)).normalized(); + idraw->drawLine(com,com+Xaxis*ascl,btVector3(1,0,0)); + idraw->drawLine(com,com+Yaxis*ascl,btVector3(0,1,0)); + idraw->drawLine(com,com+Zaxis*ascl,btVector3(0,0,1)); + for(int i=0;im_pose.m_pos.size();++i) + { + const btVector3 x=com+trs*psb->m_pose.m_pos[i]; + drawVertex(idraw,x,nscl,btVector3(1,0,1)); + } + } +} + +// +btSoftBody* btSoftBodyHelpers::CreateRope( btSoftBodyWorldInfo& worldInfo, const btVector3& from, + const btVector3& to, + int res, + int fixeds) +{ + /* Create nodes */ + const int r=res+2; + btVector3* x=new btVector3[r]; + btScalar* m=new btScalar[r]; + int i; + + for(i=0;isetMass(0,0); + if(fixeds&2) psb->setMass(r-1,0); + delete[] x; + delete[] m; + /* Create links */ + for(i=1;iappendLink(i-1,i); + } + /* Finished */ + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo,const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags) +{ +#define IDX(_x_,_y_) ((_y_)*rx+(_x_)) + /* Create nodes */ + if((resx<2)||(resy<2)) return(0); + const int rx=resx; + const int ry=resy; + const int tot=rx*ry; + btVector3* x=new btVector3[tot]; + btScalar* m=new btScalar[tot]; + int iy; + + for(iy=0;iysetMass(IDX(0,0),0); + if(fixeds&2) psb->setMass(IDX(rx-1,0),0); + if(fixeds&4) psb->setMass(IDX(0,ry-1),0); + if(fixeds&8) psb->setMass(IDX(rx-1,ry-1),0); + delete[] x; + delete[] m; + /* Create links and faces */ + for(iy=0;iyappendLink(idx,IDX(ix+1,iy)); + if(mdy) psb->appendLink(idx,IDX(ix,iy+1)); + if(mdx&&mdy) + { + if((ix+iy)&1) + { + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy),IDX(ix+1,iy+1)); + psb->appendFace(IDX(ix,iy),IDX(ix+1,iy+1),IDX(ix,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix,iy),IDX(ix+1,iy+1)); + } + } + else + { + psb->appendFace(IDX(ix,iy+1),IDX(ix,iy),IDX(ix+1,iy)); + psb->appendFace(IDX(ix,iy+1),IDX(ix+1,iy),IDX(ix+1,iy+1)); + if(gendiags) + { + psb->appendLink(IDX(ix+1,iy),IDX(ix,iy+1)); + } + } + } + } + } + /* Finished */ +#undef IDX + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,const btVector3& center, + const btVector3& radius, + int res) +{ + struct Hammersley + { + static void Generate(btVector3* x,int n) + { + for(int i=0;i>=1) if(j&1) t+=p; + btScalar w=2*t-1; + btScalar a=(SIMD_PI+2*i*SIMD_PI)/n; + btScalar s=btSqrt(1-w*w); + *x++=btVector3(s*btCos(a),s*btSin(a),w); + } + } + }; + btAlignedObjectArray vtx; + vtx.resize(3+res); + Hammersley::Generate(&vtx[0],vtx.size()); + for(int i=0;i chks; + btAlignedObjectArray vtx; + chks.resize(maxidx*maxidx,false); + vtx.resize(maxidx); + for(i=0,j=0,ni=maxidx*3;iappendLink(idx[j],idx[k]); + } + } +#undef IDX + psb->appendFace(idx[0],idx[1],idx[2]); + } + psb->randomizeConstraints(); + return(psb); +} + +// +btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices, + int nvertices) +{ + HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); + HullResult hres; + HullLibrary hlib;/*??*/ + hdsc.mMaxVertices=nvertices; + hlib.CreateConvexHull(hdsc,hres); + btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0],0); + for(int i=0;i<(int)hres.mNumFaces;++i) + { + const int idx[]={ hres.m_Indices[i*3+0], + hres.m_Indices[i*3+1], + hres.m_Indices[i*3+2]}; + if(idx[0]appendLink( idx[0],idx[1]); + if(idx[1]appendLink( idx[1],idx[2]); + if(idx[2]appendLink( idx[2],idx[0]); + psb->appendFace(idx[0],idx[1],idx[2]); + } + hlib.ReleaseResult(hres); + psb->randomizeConstraints(); + return(psb); +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h new file mode 100644 index 00000000000..e9c6cb20657 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.h @@ -0,0 +1,107 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_BODY_HELPERS_H +#define SOFT_BODY_HELPERS_H + +#include "btSoftBody.h" + +// +// Helpers +// + +/* fDrawFlags */ +struct fDrawFlags { enum _ { + Nodes = 0x0001, + Links = 0x0002, + Faces = 0x0004, + Tetras = 0x0008, + Normals = 0x0010, + Contacts = 0x0020, + Anchors = 0x0040, + Notes = 0x0080, + Clusters = 0x0100, + NodeTree = 0x0200, + FaceTree = 0x0400, + ClusterTree = 0x0800, + Joints = 0x1000, + /* presets */ + Std = Links+Faces+Tetras+Anchors+Notes+Joints, + StdTetra = Std-Faces+Tetras, +};}; + +struct btSoftBodyHelpers +{ + /* Draw body */ + static void Draw( btSoftBody* psb, + btIDebugDraw* idraw, + int drawflags=fDrawFlags::Std); + /* Draw body infos */ + static void DrawInfos( btSoftBody* psb, + btIDebugDraw* idraw, + bool masses, + bool areas, + bool stress); + /* Draw node tree */ + static void DrawNodeTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw face tree */ + static void DrawFaceTree( btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw cluster tree */ + static void DrawClusterTree(btSoftBody* psb, + btIDebugDraw* idraw, + int mindepth=0, + int maxdepth=-1); + /* Draw rigid frame */ + static void DrawFrame( btSoftBody* psb, + btIDebugDraw* idraw); + /* Create a rope */ + static btSoftBody* CreateRope( btSoftBodyWorldInfo& worldInfo, + const btVector3& from, + const btVector3& to, + int res, + int fixeds); + /* Create a patch */ + static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo, + const btVector3& corner00, + const btVector3& corner10, + const btVector3& corner01, + const btVector3& corner11, + int resx, + int resy, + int fixeds, + bool gendiags); + /* Create an ellipsoid */ + static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, + const btVector3& center, + const btVector3& radius, + int res); + /* Create from trimesh */ + static btSoftBody* CreateFromTriMesh( btSoftBodyWorldInfo& worldInfo, + const btScalar* vertices, + const int* triangles, + int ntriangles); + /* Create from convex-hull */ + static btSoftBody* CreateFromConvexHull( btSoftBodyWorldInfo& worldInfo, + const btVector3* vertices, + int nvertices); +}; + +#endif //SOFT_BODY_HELPERS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h new file mode 100644 index 00000000000..1a7be2cb840 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h @@ -0,0 +1,896 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSoftBody implementation by Nathanael Presson + +#ifndef _BT_SOFT_BODY_INTERNALS_H +#define _BT_SOFT_BODY_INTERNALS_H + +#include "btSoftBody.h" + +#include "LinearMath/btQuickprof.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btConvexInternalShape.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +// +// btSymMatrix +// +template +struct btSymMatrix +{ + btSymMatrix() : dim(0) {} + btSymMatrix(int n,const T& init=T()) { resize(n,init); } +void resize(int n,const T& init=T()) { dim=n;store.resize((n*(n+1))/2,init); } +int index(int c,int r) const { if(c>r) btSwap(c,r);btAssert(r store; +int dim; +}; + +// +// btSoftBodyCollisionShape +// +class btSoftBodyCollisionShape : public btConcaveShape +{ +public: + btSoftBody* m_body; + + btSoftBodyCollisionShape(btSoftBody* backptr) + { + m_body=backptr; + } + + virtual ~btSoftBodyCollisionShape() + { + + } + + void processAllTriangles(btTriangleCallback* /*callback*/,const btVector3& /*aabbMin*/,const btVector3& /*aabbMax*/) const + { + //not yet + btAssert(0); + } + + ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t. + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + /* t should be identity, but better be safe than...fast? */ + const btVector3 mins=m_body->m_bounds[0]; + const btVector3 maxs=m_body->m_bounds[1]; + const btVector3 crns[]={t*btVector3(mins.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),mins.y(),mins.z()), + t*btVector3(maxs.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),maxs.y(),mins.z()), + t*btVector3(mins.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),mins.y(),maxs.z()), + t*btVector3(maxs.x(),maxs.y(),maxs.z()), + t*btVector3(mins.x(),maxs.y(),maxs.z())}; + aabbMin=aabbMax=crns[0]; + for(int i=1;i<8;++i) + { + aabbMin.setMin(crns[i]); + aabbMax.setMax(crns[i]); + } + } + + virtual int getShapeType() const + { + return SOFTBODY_SHAPE_PROXYTYPE; + } + virtual void setLocalScaling(const btVector3& /*scaling*/) + { + ///na + btAssert(0); + } + virtual const btVector3& getLocalScaling() const + { + static const btVector3 dummy(1,1,1); + return dummy; + } + virtual void calculateLocalInertia(btScalar /*mass*/,btVector3& /*inertia*/) const + { + ///not yet + btAssert(0); + } + virtual const char* getName()const + { + return "SoftBody"; + } + +}; + +// +// btSoftClusterCollisionShape +// +class btSoftClusterCollisionShape : public btConvexInternalShape +{ +public: + const btSoftBody::Cluster* m_cluster; + + btSoftClusterCollisionShape (const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); } + + + virtual btVector3 localGetSupportingVertex(const btVector3& vec) const + { + btSoftBody::Node* const * n=&m_cluster->m_nodes[0]; + btScalar d=dot(vec,n[0]->m_x); + int j=0; + for(int i=1,ni=m_cluster->m_nodes.size();im_x); + if(k>d) { d=k;j=i; } + } + return(n[j]->m_x); + } + virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec)const + { + return(localGetSupportingVertex(vec)); + } + //notice that the vectors should be unit length + virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const + {} + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const + {} + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + {} + + virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; } + + //debugging + virtual const char* getName()const {return "SOFTCLUSTER";} + + virtual void setMargin(btScalar margin) + { + btConvexInternalShape::setMargin(margin); + } + virtual btScalar getMargin() const + { + return getMargin(); + } +}; + +// +// Inline's +// + +// +template +static inline void ZeroInitialize(T& value) +{ +static const T zerodummy; +value=zerodummy; +} +// +template +static inline bool CompLess(const T& a,const T& b) +{ return(a +static inline bool CompGreater(const T& a,const T& b) +{ return(a>b); } +// +template +static inline T Lerp(const T& a,const T& b,btScalar t) +{ return(a+(b-a)*t); } +// +template +static inline T InvLerp(const T& a,const T& b,btScalar t) +{ return((b+a*t-b*t)/(a*b)); } +// +static inline btMatrix3x3 Lerp( const btMatrix3x3& a, + const btMatrix3x3& b, + btScalar t) +{ +btMatrix3x3 r; +r[0]=Lerp(a[0],b[0],t); +r[1]=Lerp(a[1],b[1],t); +r[2]=Lerp(a[2],b[2],t); +return(r); +} +// +static inline btVector3 Clamp(const btVector3& v,btScalar maxlength) +{ +const btScalar sql=v.length2(); +if(sql>(maxlength*maxlength)) + return((v*maxlength)/btSqrt(sql)); + else + return(v); +} +// +template +static inline T Clamp(const T& x,const T& l,const T& h) +{ return(xh?h:x); } +// +template +static inline T Sq(const T& x) +{ return(x*x); } +// +template +static inline T Cube(const T& x) +{ return(x*x*x); } +// +template +static inline T Sign(const T& x) +{ return((T)(x<0?-1:+1)); } +// +template +static inline bool SameSign(const T& x,const T& y) +{ return((x*y)>0); } +// +static inline btScalar ClusterMetric(const btVector3& x,const btVector3& y) +{ +const btVector3 d=x-y; +return(btFabs(d[0])+btFabs(d[1])+btFabs(d[2])); +} +// +static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a,btScalar s) +{ + const btScalar xx=a.x()*a.x(); + const btScalar yy=a.y()*a.y(); + const btScalar zz=a.z()*a.z(); + const btScalar xy=a.x()*a.y(); + const btScalar yz=a.y()*a.z(); + const btScalar zx=a.z()*a.x(); + btMatrix3x3 m; + m[0]=btVector3(1-xx+xx*s,xy*s-xy,zx*s-zx); + m[1]=btVector3(xy*s-xy,1-yy+yy*s,yz*s-yz); + m[2]=btVector3(zx*s-zx,yz*s-yz,1-zz+zz*s); + return(m); +} +// +static inline btMatrix3x3 Cross(const btVector3& v) +{ + btMatrix3x3 m; + m[0]=btVector3(0,-v.z(),+v.y()); + m[1]=btVector3(+v.z(),0,-v.x()); + m[2]=btVector3(-v.y(),+v.x(),0); + return(m); +} +// +static inline btMatrix3x3 Diagonal(btScalar x) +{ + btMatrix3x3 m; + m[0]=btVector3(x,0,0); + m[1]=btVector3(0,x,0); + m[2]=btVector3(0,0,x); + return(m); +} +// +static inline btMatrix3x3 Add(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]+b[i]; + return(r); +} +// +static inline btMatrix3x3 Sub(const btMatrix3x3& a, + const btMatrix3x3& b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]-b[i]; + return(r); +} +// +static inline btMatrix3x3 Mul(const btMatrix3x3& a, + btScalar b) +{ + btMatrix3x3 r; + for(int i=0;i<3;++i) r[i]=a[i]*b; + return(r); +} +// +static inline void Orthogonalize(btMatrix3x3& m) +{ +m[2]=cross(m[0],m[1]).normalized(); +m[1]=cross(m[2],m[0]).normalized(); +m[0]=cross(m[1],m[2]).normalized(); +} +// +static inline btMatrix3x3 MassMatrix(btScalar im,const btMatrix3x3& iwi,const btVector3& r) +{ + const btMatrix3x3 cr=Cross(r); + return(Sub(Diagonal(im),cr*iwi*cr)); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar dt, + btScalar ima, + btScalar imb, + const btMatrix3x3& iwi, + const btVector3& r) +{ + return(Diagonal(1/dt)*Add(Diagonal(ima),MassMatrix(imb,iwi,r)).inverse()); +} + +// +static inline btMatrix3x3 ImpulseMatrix( btScalar ima,const btMatrix3x3& iia,const btVector3& ra, + btScalar imb,const btMatrix3x3& iib,const btVector3& rb) +{ +return(Add(MassMatrix(ima,iia,ra),MassMatrix(imb,iib,rb)).inverse()); +} + +// +static inline btMatrix3x3 AngularImpulseMatrix( const btMatrix3x3& iia, + const btMatrix3x3& iib) +{ +return(Add(iia,iib).inverse()); +} + +// +static inline btVector3 ProjectOnAxis( const btVector3& v, + const btVector3& a) +{ + return(a*dot(v,a)); +} +// +static inline btVector3 ProjectOnPlane( const btVector3& v, + const btVector3& a) +{ + return(v-ProjectOnAxis(v,a)); +} + +// +static inline void ProjectOrigin( const btVector3& a, + const btVector3& b, + btVector3& prj, + btScalar& sqd) +{ +const btVector3 d=b-a; +const btScalar m2=d.length2(); +if(m2>SIMD_EPSILON) + { + const btScalar t=Clamp(-dot(a,d)/m2,0,1); + const btVector3 p=a+d*t; + const btScalar l2=p.length2(); + if(l2SIMD_EPSILON) + { + const btVector3 n=q/btSqrt(m2); + const btScalar k=dot(a,n); + const btScalar k2=k*k; + if(k20)&& + (dot(cross(b-p,c-p),q)>0)&& + (dot(cross(c-p,a-p),q)>0)) + { + prj=p; + sqd=k2; + } + else + { + ProjectOrigin(a,b,prj,sqd); + ProjectOrigin(b,c,prj,sqd); + ProjectOrigin(c,a,prj,sqd); + } + } + } +} + +// +template +static inline T BaryEval( const T& a, + const T& b, + const T& c, + const btVector3& coord) +{ + return(a*coord.x()+b*coord.y()+c*coord.z()); +} +// +static inline btVector3 BaryCoord( const btVector3& a, + const btVector3& b, + const btVector3& c, + const btVector3& p) +{ +const btScalar w[]={ cross(a-p,b-p).length(), + cross(b-p,c-p).length(), + cross(c-p,a-p).length()}; +const btScalar isum=1/(w[0]+w[1]+w[2]); +return(btVector3(w[1]*isum,w[2]*isum,w[0]*isum)); +} + +// +static btScalar ImplicitSolve( btSoftBody::ImplicitFn* fn, + const btVector3& a, + const btVector3& b, + const btScalar accuracy, + const int maxiterations=256) +{ +btScalar span[2]={0,1}; +btScalar values[2]={fn->Eval(a),fn->Eval(b)}; +if(values[0]>values[1]) + { + btSwap(span[0],span[1]); + btSwap(values[0],values[1]); + } +if(values[0]>-accuracy) return(-1); +if(values[1]<+accuracy) return(-1); +for(int i=0;iEval(Lerp(a,b,t)); + if((t<=0)||(t>=1)) break; + if(btFabs(v)SIMD_EPSILON) + return(v/l); + else + return(btVector3(0,0,0)); +} + +// +static inline btDbvtVolume VolumeOf( const btSoftBody::Face& f, + btScalar margin) +{ +const btVector3* pts[]={ &f.m_n[0]->m_x, + &f.m_n[1]->m_x, + &f.m_n[2]->m_x}; +btDbvtVolume vol=btDbvtVolume::FromPoints(pts,3); +vol.Expand(btVector3(margin,margin,margin)); +return(vol); +} + +// +static inline btVector3 CenterOf( const btSoftBody::Face& f) +{ +return((f.m_n[0]->m_x+f.m_n[1]->m_x+f.m_n[2]->m_x)/3); +} + +// +static inline btScalar AreaOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 cr=cross(a,b); + const btScalar area=cr.length(); + return(area); +} + +// +static inline btScalar VolumeOf( const btVector3& x0, + const btVector3& x1, + const btVector3& x2, + const btVector3& x3) +{ + const btVector3 a=x1-x0; + const btVector3 b=x2-x0; + const btVector3 c=x3-x0; + return(dot(a,cross(b,c))); +} + +// +static void EvaluateMedium( const btSoftBodyWorldInfo* wfi, + const btVector3& x, + btSoftBody::sMedium& medium) +{ + medium.m_velocity = btVector3(0,0,0); + medium.m_pressure = 0; + medium.m_density = wfi->air_density; + if(wfi->water_density>0) + { + const btScalar depth=-(dot(x,wfi->water_normal)+wfi->water_offset); + if(depth>0) + { + medium.m_density = wfi->water_density; + medium.m_pressure = depth*wfi->water_density*wfi->m_gravity.length(); + } + } +} + +// +static inline void ApplyClampedForce( btSoftBody::Node& n, + const btVector3& f, + btScalar dt) +{ + const btScalar dtim=dt*n.m_im; + if((f*dtim).length2()>n.m_v.length2()) + {/* Clamp */ + n.m_f-=ProjectOnAxis(n.m_v,f.normalized())/dtim; + } + else + {/* Apply */ + n.m_f+=f; + } +} + +// +static inline int MatchEdge( const btSoftBody::Node* a, + const btSoftBody::Node* b, + const btSoftBody::Node* ma, + const btSoftBody::Node* mb) +{ +if((a==ma)&&(b==mb)) return(0); +if((a==mb)&&(b==ma)) return(1); +return(-1); +} + +// +// btEigen : Extract eigen system, +// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html +// outputs are NOT sorted. +// +struct btEigen +{ +static int system(btMatrix3x3& a,btMatrix3x3* vectors,btVector3* values=0) + { + static const int maxiterations=16; + static const btScalar accuracy=(btScalar)0.0001; + btMatrix3x3& v=*vectors; + int iterations=0; + vectors->setIdentity(); + do { + int p=0,q=1; + if(btFabs(a[p][q])accuracy) + { + const btScalar w=(a[q][q]-a[p][p])/(2*a[p][q]); + const btScalar z=btFabs(w); + const btScalar t=w/(z*(btSqrt(1+w*w)+z)); + if(t==t)/* [WARNING] let hope that one does not get thrown aways by some compilers... */ + { + const btScalar c=1/btSqrt(t*t+1); + const btScalar s=c*t; + mulPQ(a,c,s,p,q); + mulTPQ(a,c,s,p,q); + mulPQ(v,c,s,p,q); + } else break; + } else break; + } while((++iterations)accuracy) det=ndet; else break; + } + /* Final orthogonalization */ + Orthogonalize(q); + /* Compute 'S' */ + s=q.transpose()*m; + } + else + { + q.setIdentity(); + s.setIdentity(); + } +return(i); +} + +// +// btSoftColliders +// +struct btSoftColliders +{ + // + // ClusterBase + // + struct ClusterBase : btDbvt::ICollide + { + btScalar erp; + btScalar idt; + btScalar margin; + btScalar friction; + btScalar threshold; + ClusterBase() + { + erp =(btScalar)1; + idt =0; + margin =0; + friction =0; + threshold =(btScalar)0; + } + bool SolveContact( const btGjkEpaSolver2::sResults& res, + btSoftBody::Body ba,btSoftBody::Body bb, + btSoftBody::CJoint& joint) + { + if(res.distancedata; + btSoftClusterCollisionShape cshape(cluster); + const btConvexShape* rshape=(const btConvexShape*)prb->getCollisionShape(); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &cshape,btTransform::getIdentity(), + rshape,prb->getInterpolationWorldTransform(), + btVector3(1,0,0),res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cluster,prb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;psb->m_joints.push_back(pj); + if(prb->isStaticOrKinematicObject()) + { + pj->m_erp *= psb->m_cfg.kSKHR_CL; + pj->m_split *= psb->m_cfg.kSK_SPLT_CL; + } + else + { + pj->m_erp *= psb->m_cfg.kSRHR_CL; + pj->m_split *= psb->m_cfg.kSR_SPLT_CL; + } + } + } + } + void Process(btSoftBody* ps,btRigidBody* pr) + { + psb = ps; + prb = pr; + idt = ps->m_sst.isdt; + margin = ps->getCollisionShape()->getMargin()+ + pr->getCollisionShape()->getMargin(); + friction = btMin(psb->m_cfg.kDF,prb->getFriction()); + btVector3 mins; + btVector3 maxs; + + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; + pr->getCollisionShape()->getAabb(pr->getInterpolationWorldTransform(),mins,maxs); + volume=btDbvtVolume::FromMM(mins,maxs); + volume.Expand(btVector3(1,1,1)*margin); + btDbvt::collideTV(ps->m_cdbvt.m_root,volume,*this); + } + }; + // + // CollideCL_SS + // + struct CollideCL_SS : ClusterBase + { + btSoftBody* bodies[2]; + void Process(const btDbvtNode* la,const btDbvtNode* lb) + { + btSoftBody::Cluster* cla=(btSoftBody::Cluster*)la->data; + btSoftBody::Cluster* clb=(btSoftBody::Cluster*)lb->data; + btSoftClusterCollisionShape csa(cla); + btSoftClusterCollisionShape csb(clb); + btGjkEpaSolver2::sResults res; + if(btGjkEpaSolver2::SignedDistance( &csa,btTransform::getIdentity(), + &csb,btTransform::getIdentity(), + cla->m_com-clb->m_com,res)) + { + btSoftBody::CJoint joint; + if(SolveContact(res,cla,clb,joint)) + { + btSoftBody::CJoint* pj=new(btAlignedAlloc(sizeof(btSoftBody::CJoint),16)) btSoftBody::CJoint(); + *pj=joint;bodies[0]->m_joints.push_back(pj); + pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL,bodies[1]->m_cfg.kSSHR_CL); + pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL+bodies[1]->m_cfg.kSS_SPLT_CL)/2; + } + } + } + void Process(btSoftBody* psa,btSoftBody* psb) + { + idt = psa->m_sst.isdt; + margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2; + friction = btMin(psa->m_cfg.kDF,psb->m_cfg.kDF); + bodies[0] = psa; + bodies[1] = psb; + btDbvt::collideTT(psa->m_cdbvt.m_root,psb->m_cdbvt.m_root,*this); + } + }; + // + // CollideSDF_RS + // + struct CollideSDF_RS : btDbvt::ICollide + { + void Process(const btDbvtNode* leaf) + { + btSoftBody::Node* node=(btSoftBody::Node*)leaf->data; + DoNode(*node); + } + void DoNode(btSoftBody::Node& n) const + { + const btScalar m=n.m_im>0?dynmargin:stamargin; + btSoftBody::RContact c; + if( (!n.m_battach)&& + psb->checkContact(prb,n.m_x,m,c.m_cti)) + { + const btScalar ima=n.m_im; + const btScalar imb=prb->getInvMass(); + const btScalar ms=ima+imb; + if(ms>0) + { + const btTransform& wtr=prb->getInterpolationWorldTransform(); + const btMatrix3x3& iwi=prb->getInvInertiaTensorWorld(); + const btVector3 ra=n.m_x-wtr.getOrigin(); + const btVector3 va=prb->getVelocityInLocalPoint(ra)*psb->m_sst.sdt; + const btVector3 vb=n.m_x-n.m_q; + const btVector3 vr=vb-va; + const btScalar dn=dot(vr,c.m_cti.m_normal); + const btVector3 fv=vr-c.m_cti.m_normal*dn; + const btScalar fc=psb->m_cfg.kDF*prb->getFriction(); + c.m_node = &n; + c.m_c0 = ImpulseMatrix(psb->m_sst.sdt,ima,imb,iwi,ra); + c.m_c1 = ra; + c.m_c2 = ima*psb->m_sst.sdt; + c.m_c3 = fv.length2()<(btFabs(dn)*fc)?0:1-fc; + c.m_c4 = prb->isStaticOrKinematicObject()?psb->m_cfg.kKHR:psb->m_cfg.kCHR; + psb->m_rcontacts.push_back(c); + prb->activate(); + } + } + } + btSoftBody* psb; + btRigidBody* prb; + btScalar dynmargin; + btScalar stamargin; + }; + // + // CollideVF_SS + // + struct CollideVF_SS : btDbvt::ICollide + { + void Process(const btDbvtNode* lnode, + const btDbvtNode* lface) + { + btSoftBody::Node* node=(btSoftBody::Node*)lnode->data; + btSoftBody::Face* face=(btSoftBody::Face*)lface->data; + btVector3 o=node->m_x; + btVector3 p; + btScalar d=SIMD_INFINITY; + ProjectOrigin( face->m_n[0]->m_x-o, + face->m_n[1]->m_x-o, + face->m_n[2]->m_x-o, + p,d); + const btScalar m=mrg+(o-node->m_q).length()*2; + if(d<(m*m)) + { + const btSoftBody::Node* n[]={face->m_n[0],face->m_n[1],face->m_n[2]}; + const btVector3 w=BaryCoord(n[0]->m_x,n[1]->m_x,n[2]->m_x,p+o); + const btScalar ma=node->m_im; + btScalar mb=BaryEval(n[0]->m_im,n[1]->m_im,n[2]->m_im,w); + if( (n[0]->m_im<=0)|| + (n[1]->m_im<=0)|| + (n[2]->m_im<=0)) + { + mb=0; + } + const btScalar ms=ma+mb; + if(ms>0) + { + btSoftBody::SContact c; + c.m_normal = p/-btSqrt(d); + c.m_margin = m; + c.m_node = node; + c.m_face = face; + c.m_weights = w; + c.m_friction = btMax(psb[0]->m_cfg.kDF,psb[1]->m_cfg.kDF); + c.m_cfm[0] = ma/ms*psb[0]->m_cfg.kSHR; + c.m_cfm[1] = mb/ms*psb[1]->m_cfg.kSHR; + psb[0]->m_scontacts.push_back(c); + } + } + } + btSoftBody* psb[2]; + btScalar mrg; + }; +}; + +#endif //_BT_SOFT_BODY_INTERNALS_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp new file mode 100644 index 00000000000..e62f35567b0 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp @@ -0,0 +1,108 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftBodyRigidBodyCollisionConfiguration.h" +#include "btSoftRigidCollisionAlgorithm.h" +#include "btSoftBodyConcaveCollisionAlgorithm.h" +#include "btSoftSoftCollisionAlgorithm.h" + +#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1 + +btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo) +:btDefaultCollisionConfiguration(constructionInfo) +{ + void* mem; + + mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc),16); + m_softSoftCreateFunc = new(mem) btSoftSoftCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_softRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConvexCreateFunc = new(mem) btSoftRigidCollisionAlgorithm::CreateFunc; + m_swappedSoftRigidConvexCreateFunc->m_swapped=true; + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_softRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc; + + mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc),16); + m_swappedSoftRigidConcaveCreateFunc = new(mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc; + m_swappedSoftRigidConcaveCreateFunc->m_swapped=true; +#endif + +} + +btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration() +{ + m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softSoftCreateFunc); + + m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConvexCreateFunc); + + m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConvexCreateFunc); + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_softRigidConcaveCreateFunc); + + m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc(); + btAlignedFree( m_swappedSoftRigidConcaveCreateFunc); +#endif +} + +///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation +btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) +{ + + ///try to handle the softbody interactions first + + if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE ) && (proxyType1==SOFTBODY_SHAPE_PROXYTYPE)) + { + return m_softSoftCreateFunc; + } + + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1)) + { + return m_softRigidConvexCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConvexCreateFunc; + } + +#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS + ///softbody versus convex + if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1)) + { + return m_softRigidConcaveCreateFunc; + } + + ///convex versus soft body + if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE ) + { + return m_swappedSoftRigidConcaveCreateFunc; + } +#endif + + ///fallback to the regular rigid collision shape + return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0,proxyType1); +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h new file mode 100644 index 00000000000..41c3af96939 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h @@ -0,0 +1,48 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION +#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" + +class btVoronoiSimplexSolver; +class btGjkEpaPenetrationDepthSolver; + + +///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration +class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration +{ + + //default CreationFunctions, filling the m_doubleDispatch table + btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc; + btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc; + btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc; + +public: + + btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo()); + + virtual ~btSoftBodyRigidBodyCollisionConfiguration(); + + ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation + virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1); + +}; + +#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION + diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp new file mode 100644 index 00000000000..835a03b8e3c --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp @@ -0,0 +1,79 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftRigidCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btSphereShape.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btSoftBody.h" +///TODO: include all the shapes that the softbody can collide with +///alternatively, implement special case collision algorithms (just like for rigid collision shapes) + +//#include + +btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*col0*/,btCollisionObject* /*col1*/, bool isSwapped) +: btCollisionAlgorithm(ci), +//m_ownManifold(false), +//m_manifoldPtr(mf), +m_isSwapped(isSwapped) +{ +} + + +btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm() +{ + + //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject); + + /*if (m_ownManifold) + { + if (m_manifoldPtr) + m_dispatcher->releaseManifold(m_manifoldPtr); + } + */ + +} + + +#include + +void btSoftRigidCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)dispatchInfo; + (void)resultOut; + //printf("btSoftRigidCollisionAlgorithm\n"); + + btSoftBody* softBody = m_isSwapped? (btSoftBody*)body1 : (btSoftBody*)body0; + btCollisionObject* rigidCollisionObject = m_isSwapped? body0 : body1; + + softBody->defaultCollisionHandler(rigidCollisionObject); + + +} + +btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + (void)resultOut; + (void)dispatchInfo; + (void)col0; + (void)col1; + + //not yet + return btScalar(1.); +} + + + diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h new file mode 100644 index 00000000000..74327e6c635 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidCollisionAlgorithm.h @@ -0,0 +1,75 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_RIGID_COLLISION_ALGORITHM_H +#define SOFT_RIGID_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +class btPersistentManifold; +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btVector3.h" +class btSoftBody; + +/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody +class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm +{ +// bool m_ownManifold; +// btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody; + btCollisionObject* m_rigidCollisionObject; + + ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean + bool m_isSwapped; + +public: + + btSoftRigidCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped); + + virtual ~btSoftRigidCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + //we don't add any manifolds + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm)); + if (!m_swapped) + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,false); + } else + { + return new(mem) btSoftRigidCollisionAlgorithm(0,ci,body0,body1,true); + } + } + }; + +}; + +#endif //SOFT_RIGID_COLLISION_ALGORITHM_H + + diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp new file mode 100644 index 00000000000..01b9fc0fd35 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -0,0 +1,126 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btSoftRigidDynamicsWorld.h" +#include "LinearMath/btQuickprof.h" + +//softbody & helpers +#include "btSoftBody.h" +#include "btSoftBodyHelpers.h" + +btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) +:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) +{ +m_drawFlags = fDrawFlags::Std; +m_drawNodeTree = true; +m_drawFaceTree = false; +m_drawClusterTree = false; +} + +btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() +{ + +} + +void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep) +{ + btDiscreteDynamicsWorld::predictUnconstraintMotion( timeStep); + + for ( int i=0;ipredictMotion(timeStep); + } +} + +void btSoftRigidDynamicsWorld::internalSingleStepSimulation( btScalar timeStep) +{ + btDiscreteDynamicsWorld::internalSingleStepSimulation( timeStep ); + + ///solve soft bodies constraints + solveSoftBodiesConstraints(); + + ///update soft bodies + updateSoftBodies(); + +} + +void btSoftRigidDynamicsWorld::updateSoftBodies() +{ + BT_PROFILE("updateSoftBodies"); + + for ( int i=0;iintegrateMotion(); + } +} + +void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints() +{ + BT_PROFILE("solveSoftConstraints"); + + if(m_softBodies.size()) + { + btSoftBody::solveClusters(m_softBodies); + } + + for(int i=0;isolveConstraints(); + } +} + +void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body) +{ + m_softBodies.push_back(body); + + btCollisionWorld::addCollisionObject(body, + btBroadphaseProxy::DefaultFilter, + btBroadphaseProxy::AllFilter); + +} + +void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body) +{ + m_softBodies.remove(body); + + btCollisionWorld::removeCollisionObject(body); +} + +void btSoftRigidDynamicsWorld::debugDrawWorld() +{ + btDiscreteDynamicsWorld::debugDrawWorld(); + + if (getDebugDrawer()) + { + int i; + for ( i=0;im_softBodies.size();i++) + { + btSoftBody* psb=(btSoftBody*)this->m_softBodies[i]; + btSoftBodyHelpers::DrawFrame(psb,m_debugDrawer); + btSoftBodyHelpers::Draw(psb,m_debugDrawer,m_drawFlags); + if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + if(m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb,m_debugDrawer); + if(m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb,m_debugDrawer); + if(m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb,m_debugDrawer); + } + } + } +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h new file mode 100644 index 00000000000..d0010b65aad --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -0,0 +1,73 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" + +#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H +#define BT_SOFT_RIGID_DYNAMICS_WORLD_H + +class btSoftBody; +typedef btAlignedObjectArray btSoftBodyArray; + +class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld +{ + + btSoftBodyArray m_softBodies; + int m_drawFlags; + bool m_drawNodeTree; + bool m_drawFaceTree; + bool m_drawClusterTree; + +protected: + + virtual void predictUnconstraintMotion(btScalar timeStep); + + virtual void internalSingleStepSimulation( btScalar timeStep); + + void updateSoftBodies(); + + void solveSoftBodiesConstraints(); + + + +public: + + btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration); + + virtual ~btSoftRigidDynamicsWorld(); + + virtual void debugDrawWorld(); + + void addSoftBody(btSoftBody* body); + + void removeSoftBody(btSoftBody* body); + + int getDrawFlags() const { return(m_drawFlags); } + void setDrawFlags(int f) { m_drawFlags=f; } + + + btSoftBodyArray& getSoftBodyArray() + { + return m_softBodies; + } + + const btSoftBodyArray& getSoftBodyArray() const + { + return m_softBodies; + } + +}; + +#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp new file mode 100644 index 00000000000..85a727944e0 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp @@ -0,0 +1,46 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btSoftSoftCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "btSoftBody.h" + +#define USE_PERSISTENT_CONTACTS 1 + +btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* /*obj0*/,btCollisionObject* /*obj1*/) +: btCollisionAlgorithm(ci) +//m_ownManifold(false), +//m_manifoldPtr(mf) +{ +} + +btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm() +{ +} + +void btSoftSoftCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + btSoftBody* soft0 = (btSoftBody*)body0; + btSoftBody* soft1 = (btSoftBody*)body1; + soft0->defaultCollisionHandler(soft1); +} + +btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/) +{ + //not yet + return 1.f; +} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h new file mode 100644 index 00000000000..7ca9c3415c9 --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSoftSoftCollisionAlgorithm.h @@ -0,0 +1,69 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SOFT_SOFT_COLLISION_ALGORITHM_H +#define SOFT_SOFT_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" + +class btPersistentManifold; +class btSoftBody; + +///collision detection between two btSoftBody shapes +class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm +{ + bool m_ownManifold; + btPersistentManifold* m_manifoldPtr; + + btSoftBody* m_softBody0; + btSoftBody* m_softBody1; + + +public: + btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci) + : btCollisionAlgorithm(ci) {} + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr && m_ownManifold) + manifoldArray.push_back(m_manifoldPtr); + } + + btSoftSoftCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btSoftSoftCollisionAlgorithm(); + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + int bbsize = sizeof(btSoftSoftCollisionAlgorithm); + void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize); + return new(ptr) btSoftSoftCollisionAlgorithm(0,ci,body0,body1); + } + }; + +}; + +#endif //SOFT_SOFT_COLLISION_ALGORITHM_H + + diff --git a/extern/bullet2/src/BulletSoftBody/btSparseSDF.h b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h new file mode 100644 index 00000000000..eafe74be1ae --- /dev/null +++ b/extern/bullet2/src/BulletSoftBody/btSparseSDF.h @@ -0,0 +1,306 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +///btSparseSdf implementation by Nathanael Presson + +#ifndef _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ +#define _14F9D17F_EAE8_4aba_B41C_292DB2AA70F3_ + +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h" + +// Modified Paul Hsieh hash +template +unsigned int HsiehHash(const void* pdata) + { + const unsigned short* data=(const unsigned short*)pdata; + unsigned hash=DWORDLEN<<2,tmp; + for(int i=0;i>11; + } + hash^=hash<<3;hash+=hash>>5; + hash^=hash<<4;hash+=hash>>17; + hash^=hash<<25;hash+=hash>>6; + return(hash); + } + +template +struct btSparseSdf + { + // + // Inner types + // + struct IntFrac + { + int b; + int i; + btScalar f; + }; + struct Cell + { + btScalar d[CELLSIZE+1][CELLSIZE+1][CELLSIZE+1]; + int c[3]; + int puid; + unsigned hash; + btCollisionShape* pclient; + Cell* next; + }; + // + // Fields + // + + btAlignedObjectArray cells; + btScalar voxelsz; + int puid; + int ncells; + int nprobes; + int nqueries; + + // + // Methods + // + + // + void Initialize(int hashsize=2383) + { + cells.resize(hashsize,0); + Reset(); + } + // + void Reset() + { + for(int i=0,ni=cells.size();inext; + delete pc; + pc=pn; + } + } + voxelsz =0.25; + puid =0; + ncells =0; + nprobes =1; + nqueries =1; + } + // + void GarbageCollect(int lifetime=256) + { + const int life=puid-lifetime; + for(int i=0;inext; + if(pc->puidnext=pn; else root=pn; + delete pc;pc=pp;--ncells; + } + pp=pc;pc=pn; + } + } + //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries); + nqueries=1; + nprobes=1; + ++puid; /* TODO: Reset puid's when int range limit is reached */ + /* else setup a priority list... */ + } + // + int RemoveReferences(btCollisionShape* pcs) + { + int refcount=0; + for(int i=0;inext; + if(pc->pclient==pcs) + { + if(pp) pp->next=pn; else root=pn; + delete pc;pc=pp;++refcount; + } + pp=pc;pc=pn; + } + } + return(refcount); + } + // + btScalar Evaluate( const btVector3& x, + btCollisionShape* shape, + btVector3& normal, + btScalar margin) + { + /* Lookup cell */ + const btVector3 scx=x/voxelsz; + const IntFrac ix=Decompose(scx.x()); + const IntFrac iy=Decompose(scx.y()); + const IntFrac iz=Decompose(scx.z()); + const unsigned h=Hash(ix.b,iy.b,iz.b,shape); + Cell*& root=cells[static_cast(h%cells.size())]; + Cell* c=root; + ++nqueries; + while(c) + { + ++nprobes; + if( (c->hash==h) && + (c->c[0]==ix.b) && + (c->c[1]==iy.b) && + (c->c[2]==iz.b) && + (c->pclient==shape)) + { break; } + else + { c=c->next; } + } + if(!c) + { + ++nprobes; + ++ncells; + c=new Cell(); + c->next=root;root=c; + c->pclient=shape; + c->hash=h; + c->c[0]=ix.b;c->c[1]=iy.b;c->c[2]=iz.b; + BuildCell(*c); + } + c->puid=puid; + /* Extract infos */ + const int o[]={ ix.i,iy.i,iz.i}; + const btScalar d[]={ c->d[o[0]+0][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+0][o[2]+0], + c->d[o[0]+1][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+1][o[2]+0], + c->d[o[0]+0][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+0][o[2]+1], + c->d[o[0]+1][o[1]+1][o[2]+1], + c->d[o[0]+0][o[1]+1][o[2]+1]}; + /* Normal */ + #if 1 + const btScalar gx[]={ d[1]-d[0],d[2]-d[3], + d[5]-d[4],d[6]-d[7]}; + const btScalar gy[]={ d[3]-d[0],d[2]-d[1], + d[7]-d[4],d[6]-d[5]}; + const btScalar gz[]={ d[4]-d[0],d[5]-d[1], + d[7]-d[3],d[6]-d[2]}; + normal.setX(Lerp( Lerp(gx[0],gx[1],iy.f), + Lerp(gx[2],gx[3],iy.f),iz.f)); + normal.setY(Lerp( Lerp(gy[0],gy[1],ix.f), + Lerp(gy[2],gy[3],ix.f),iz.f)); + normal.setZ(Lerp( Lerp(gz[0],gz[1],ix.f), + Lerp(gz[2],gz[3],ix.f),iy.f)); + normal = normal.normalized(); + #else + normal = btVector3(d[1]-d[0],d[3]-d[0],d[4]-d[0]).normalized(); + #endif + /* Distance */ + const btScalar d0=Lerp(Lerp(d[0],d[1],ix.f), + Lerp(d[3],d[2],ix.f),iy.f); + const btScalar d1=Lerp(Lerp(d[4],d[5],ix.f), + Lerp(d[7],d[6],ix.f),iy.f); + return(Lerp(d0,d1,iz.f)-margin); + } + // + void BuildCell(Cell& c) + { + const btVector3 org=btVector3( (btScalar)c.c[0], + (btScalar)c.c[1], + (btScalar)c.c[2]) * + CELLSIZE*voxelsz; + for(int k=0;k<=CELLSIZE;++k) + { + const btScalar z=voxelsz*k+org.z(); + for(int j=0;j<=CELLSIZE;++j) + { + const btScalar y=voxelsz*j+org.y(); + for(int i=0;i<=CELLSIZE;++i) + { + const btScalar x=voxelsz*i+org.x(); + c.d[i][j][k]=DistanceToShape( btVector3(x,y,z), + c.pclient); + } + } + } + } + // + static inline btScalar DistanceToShape(const btVector3& x, + btCollisionShape* shape) + { + btTransform unit; + unit.setIdentity(); + if(shape->isConvex()) + { + btGjkEpaSolver2::sResults res; + btConvexShape* csh=static_cast(shape); + return(btGjkEpaSolver2::SignedDistance(x,0,csh,unit,res)); + } + return(0); + } + // + static inline IntFrac Decompose(btScalar x) + { + /* That one need a lot of improvements... */ + /* Remove test, faster floor... */ + IntFrac r; + x/=CELLSIZE; + const int o=x<0?(int)(-x+1):0; + x+=o;r.b=(int)x; + const btScalar k=(x-r.b)*CELLSIZE; + r.i=(int)k;r.f=k-r.i;r.b-=o; + return(r); + } + // + static inline btScalar Lerp(btScalar a,btScalar b,btScalar t) + { + return(a+(b-a)*t); + } + + + + // + static inline unsigned int Hash(int x,int y,int z,btCollisionShape* shape) + { + struct btS + { + int x,y,z; + void* p; + }; + + btS myset; + + myset.x=x;myset.y=y;myset.z=z;myset.p=shape; + const void* ptr = &myset; + + unsigned int result = HsiehHash (ptr); + + + return result; + } +}; + + +#endif diff --git a/extern/bullet2/src/CMakeLists.txt b/extern/bullet2/src/CMakeLists.txt index 0ae1a7ab6ab..043fd3f6e7f 100644 --- a/extern/bullet2/src/CMakeLists.txt +++ b/extern/bullet2/src/CMakeLists.txt @@ -1 +1 @@ -SUBDIRS( BulletCollision BulletDynamics LinearMath ) +SUBDIRS( BulletCollision BulletDynamics LinearMath BulletSoftBody ) diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt index 207eed94a3e..02ffaad7228 100644 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -4,7 +4,32 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ) ADD_LIBRARY(LibLinearMath -btQuickprof.cpp -btGeometryUtil.cpp + btAlignedObjectArray.h + btList.h + btPoolAllocator.h + btRandom.h + btVector3.h + btDefaultMotionState.h + btMatrix3x3.h + btQuadWord.h + btHashMap.h + btScalar.h + btAabbUtil2.h + btConvexHull.h + btConvexHull.cpp + btMinMax.h + btQuaternion.h + btStackAlloc.h + btGeometryUtil.h + btMotionState.h + btTransform.h + btAlignedAllocator.h + btIDebugDraw.h + btPoint3.h + btQuickprof.h + btTransformUtil.h + btQuickprof.cpp + btGeometryUtil.cpp + btAlignedAllocator.cpp ) diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 429163c8138..275c4914628 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -17,12 +17,18 @@ subject to the following restrictions: #ifndef AABB_UTIL2 #define AABB_UTIL2 +#include "btTransform.h" #include "btVector3.h" -#include "btSimdMinMax.h" +#include "btMinMax.h" - -#define btMin(a,b) ((a < b ? a : b)) -#define btMax(a,b) ((a > b ? a : b)) +SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin, + btVector3& aabbMax, + const btVector3& expansionMin, + const btVector3& expansionMax) +{ + aabbMin = aabbMin + expansionMin; + aabbMax = aabbMax + expansionMax; +} /// conservative test for overlap between two aabbs @@ -67,6 +73,41 @@ SIMD_FORCE_INLINE int btOutcode(const btVector3& p,const btVector3& halfExtent) } +SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom, + const btVector3& rayInvDirection, + const unsigned int raySign[3], + const btVector3 bounds[2], + btScalar& tmin, + btScalar lambda_min, + btScalar lambda_max) +{ + btScalar tmax, tymin, tymax, tzmin, tzmax; + tmin = (bounds[raySign[0]][0] - rayFrom[0]) * rayInvDirection[0]; + tmax = (bounds[1-raySign[0]][0] - rayFrom[0]) * rayInvDirection[0]; + tymin = (bounds[raySign[1]][1] - rayFrom[1]) * rayInvDirection[1]; + tymax = (bounds[1-raySign[1]][1] - rayFrom[1]) * rayInvDirection[1]; + + if ( (tmin > tymax) || (tymin > tmax) ) + return false; + + if (tymin > tmin) + tmin = tymin; + + if (tymax < tmax) + tmax = tymax; + + tzmin = (bounds[raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; + tzmax = (bounds[1-raySign[2]][2] - rayFrom[2]) * rayInvDirection[2]; + + if ( (tmin > tzmax) || (tzmin > tmax) ) + return false; + if (tzmin > tmin) + tmin = tzmin; + if (tzmax < tmax) + tmax = tzmax; + return ( (tmin < lambda_max) && (tmax > lambda_min) ); +} + SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, const btVector3& rayTo, const btVector3& aabbMin, @@ -123,5 +164,39 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, } + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin), + abs_b[1].dot(halfExtentsWithMargin), + abs_b[2].dot(halfExtentsWithMargin)); + aabbMinOut = center - extent; + aabbMaxOut = center + extent; +} + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btAssert(localAabbMin.getX() <= localAabbMax.getX()); + btAssert(localAabbMin.getY() <= localAabbMax.getY()); + btAssert(localAabbMin.getZ() <= localAabbMax.getZ()); + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + localHalfExtents+=btVector3(margin,margin,margin); + + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + btMatrix3x3 abs_b = trans.getBasis().absolute(); + btVector3 center = trans(localCenter); + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMinOut = center-extent; + aabbMaxOut = center+extent; +} + + #endif + diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp index 1f5877fa37e..e120289e061 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.cpp @@ -15,56 +15,187 @@ subject to the following restrictions: #include "btAlignedAllocator.h" +int gNumAlignedAllocs = 0; +int gNumAlignedFree = 0; +int gTotalBytesAlignedAllocs = 0;//detect memory leaks -#if defined (BT_HAS_ALIGNED_ALOCATOR) - +#if defined (BT_HAS_ALIGNED_ALLOCATOR) #include -void* btAlignedAlloc (int size, int alignment) +static void *btAlignedAllocDefault(size_t size, int alignment) { - return _aligned_malloc(size,alignment); + return _aligned_malloc(size, (size_t)alignment); } -void btAlignedFree (void* ptr) +static void btAlignedFreeDefault(void *ptr) { _aligned_free(ptr); } - -#else - -#ifdef __CELLOS_LV2__ - +#elif defined(__CELLOS_LV2__) #include -int numAllocs = 0; -int numFree = 0; - -void* btAlignedAlloc (int size, int alignment) +static inline void *btAlignedAllocDefault(size_t size, int alignment) { - numAllocs++; return memalign(alignment, size); } -void btAlignedFree (void* ptr) +static inline void btAlignedFreeDefault(void *ptr) +{ + free(ptr); +} +#else +static inline void *btAlignedAllocDefault(size_t size, int alignment) +{ + void *ret; + char *real; + unsigned long offset; + + real = (char *)malloc(size + sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); + ret = (void *)((real + sizeof(void *)) + offset); + *((void **)(ret)-1) = (void *)(real); + } else { + ret = (void *)(real); + } + return (ret); +} + +static inline void btAlignedFreeDefault(void *ptr) +{ + void* real; + + if (ptr) { + real = *((void **)(ptr)-1); + free(real); + } +} +#endif + +static void *btAllocDefault(size_t size) +{ + return malloc(size); +} + +static void btFreeDefault(void *ptr) { - numFree++; free(ptr); } +static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault; +static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault; +static btAllocFunc *sAllocFunc = btAllocDefault; +static btFreeFunc *sFreeFunc = btFreeDefault; + +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc) +{ + sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault; + sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault; +} + +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc) +{ + sAllocFunc = allocFunc ? allocFunc : btAllocDefault; + sFreeFunc = freeFunc ? freeFunc : btFreeDefault; +} + +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS +//this generic allocator provides the total allocated number of bytes +#include + +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename) +{ + void *ret; + char *real; + unsigned long offset; + + gTotalBytesAlignedAllocs += size; + gNumAlignedAllocs++; + + + real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) & +(alignment-1); + ret = (void *)((real + 2*sizeof(void *)) + offset); + *((void **)(ret)-1) = (void *)(real); + *((int*)(ret)-2) = size; + + } else { + ret = (void *)(real);//?? + } + + printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size); + + int* ptr = (int*)ret; + *ptr = 12; + return (ret); +} + +void btAlignedFreeInternal (void* ptr,int line,char* filename) +{ + + void* real; + gNumAlignedFree++; + + if (ptr) { + real = *((void **)(ptr)-1); + int size = *((int*)(ptr)-2); + gTotalBytesAlignedAllocs -= size; + + printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size); + + sFreeFunc(real); + } else + { + printf("NULL ptr\n"); + } +} + +#else //BT_DEBUG_MEMORY_ALLOCATIONS + +void* btAlignedAllocInternal (size_t size, int alignment) +{ + gNumAlignedAllocs++; + void* ptr; +#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) + ptr = sAlignedAllocFunc(size, alignment); #else -///todo -///will add some multi-platform version that works without _aligned_malloc/_aligned_free + char *real; + unsigned long offset; -void* btAlignedAlloc (int size, int alignment) -{ - return new char[size]; + real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1)); + if (real) { + offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1); + ptr = (void *)((real + sizeof(void *)) + offset); + *((void **)(ptr)-1) = (void *)(real); + } else { + ptr = (void *)(real); + } +#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) +// printf("btAlignedAllocInternal %d, %x\n",size,ptr); + return ptr; } -void btAlignedFree (void* ptr) +void btAlignedFreeInternal (void* ptr) { - delete [] (char*) ptr; + if (!ptr) + { + return; + } + + gNumAlignedFree++; +// printf("btAlignedFreeInternal %x\n",ptr); +#if defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) + sAlignedFreeFunc(ptr); +#else + void* real; + + if (ptr) { + real = *((void **)(ptr)-1); + sFreeFunc(real); + } +#endif // defined (BT_HAS_ALIGNED_ALLOCATOR) || defined(__CELLOS_LV2__) } -#endif // - -#endif +#endif //BT_DEBUG_MEMORY_ALLOCATIONS diff --git a/extern/bullet2/src/LinearMath/btAlignedAllocator.h b/extern/bullet2/src/LinearMath/btAlignedAllocator.h index 07585717f45..a252f324d77 100644 --- a/extern/bullet2/src/LinearMath/btAlignedAllocator.h +++ b/extern/bullet2/src/LinearMath/btAlignedAllocator.h @@ -21,15 +21,39 @@ subject to the following restrictions: ///that is better portable and more predictable #include "btScalar.h" +//#define BT_DEBUG_MEMORY_ALLOCATIONS 1 +#ifdef BT_DEBUG_MEMORY_ALLOCATIONS -void* btAlignedAlloc (int size, int alignment); +#define btAlignedAlloc(a,b) \ + btAlignedAllocInternal(a,b,__LINE__,__FILE__) -void btAlignedFree (void* ptr); +#define btAlignedFree(ptr) \ + btAlignedFreeInternal(ptr,__LINE__,__FILE__) +void* btAlignedAllocInternal (size_t size, int alignment,int line,char* filename); +void btAlignedFreeInternal (void* ptr,int line,char* filename); + +#else + void* btAlignedAllocInternal (size_t size, int alignment); + void btAlignedFreeInternal (void* ptr); + + #define btAlignedAlloc(a,b) btAlignedAllocInternal(a,b) + #define btAlignedFree(ptr) btAlignedFreeInternal(ptr) + +#endif typedef int size_type; +typedef void *(btAlignedAllocFunc)(size_t size, int alignment); +typedef void (btAlignedFreeFunc)(void *memblock); +typedef void *(btAllocFunc)(size_t size); +typedef void (btFreeFunc)(void *memblock); +void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc); +void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc); + +///The btAlignedAllocator is a portable class for aligned memory allocations. +///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned. template < typename T , unsigned Alignment > class btAlignedAllocator { diff --git a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h index 8bef5eb5d06..5598f0d7236 100644 --- a/extern/bullet2/src/LinearMath/btAlignedObjectArray.h +++ b/extern/bullet2/src/LinearMath/btAlignedObjectArray.h @@ -39,8 +39,8 @@ subject to the following restrictions: #endif //BT_USE_PLACEMENT_NEW -///btAlignedObjectArray uses a subset of the stl::vector interface for its methods -///It is developed to replace stl::vector to avoid STL alignment issues to add SIMD/SSE data +///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods +///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data template //template class btAlignedObjectArray @@ -50,6 +50,8 @@ class btAlignedObjectArray int m_size; int m_capacity; T* m_data; + //PCK: added this line + bool m_ownsMemory; protected: SIMD_FORCE_INLINE int allocSize(int size) @@ -69,6 +71,8 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void init() { + //PCK: added this line + m_ownsMemory = true; m_data = 0; m_size = 0; m_capacity = 0; @@ -92,7 +96,11 @@ class btAlignedObjectArray SIMD_FORCE_INLINE void deallocate() { if(m_data) { - m_allocator.deallocate(m_data); + //PCK: enclosed the deallocation in this block + if (m_ownsMemory) + { + m_allocator.deallocate(m_data); + } m_data = 0; } } @@ -223,6 +231,9 @@ class btAlignedObjectArray destroy(0,size()); deallocate(); + + //PCK: added this line + m_ownsMemory = true; m_data = s; @@ -242,6 +253,46 @@ class btAlignedObjectArray } }; + template + void quickSortInternal(L CompareFunc,int lo, int hi) + { + // lo is the lower index, hi is the upper index + // of the region of array a that is to be sorted + int i=lo, j=hi; + T x=m_data[(lo+hi)/2]; + + // partition + do + { + while (CompareFunc(m_data[i],x)) + i++; + while (CompareFunc(x,m_data[j])) + j--; + if (i<=j) + { + swap(i,j); + i++; j--; + } + } while (i<=j); + + // recursion + if (lo + void quickSort(L CompareFunc) + { + //don't sort 0 or 1 elements + if (size()>1) + { + quickSortInternal(CompareFunc,0,size()-1); + } + } + ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ template @@ -360,8 +411,16 @@ class btAlignedObjectArray } } + //PCK: whole function + void initializeFromBuffer(void *buffer, int size, int capacity) + { + clear(); + m_ownsMemory = false; + m_data = (T*)buffer; + m_size = size; + m_capacity = capacity; + } + }; #endif //BT_OBJECT_ARRAY__ - - diff --git a/extern/bullet2/src/LinearMath/btConvexHull.cpp b/extern/bullet2/src/LinearMath/btConvexHull.cpp new file mode 100644 index 00000000000..a20b2059ae9 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btConvexHull.cpp @@ -0,0 +1,1153 @@ +/* +Stan Melax Convex Hull Computation +Copyright (c) 2003-2006 Stan Melax http://www.melax.com/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include + +#include "btConvexHull.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btVector3.h" + + + +template +void Swap(T &a,T &b) +{ + T tmp = a; + a=b; + b=tmp; +} + + +//---------------------------------- + +class int3 +{ +public: + int x,y,z; + int3(){}; + int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + + +//------- btPlane ---------- + + +inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);} +inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); } +inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); } + + +//--------- Utility Functions ------ + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1); +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point); + +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2); +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2) +{ + btVector3 N1 = p0.normal; + btVector3 N2 = p1.normal; + btVector3 N3 = p2.normal; + + btVector3 n2n3; n2n3 = N2.cross(N3); + btVector3 n3n1; n3n1 = N3.cross(N1); + btVector3 n1n2; n1n2 = N1.cross(N2); + + btScalar quotient = (N1.dot(n2n3)); + + btAssert(btFabs(quotient) > btScalar(0.000001)); + + quotient = btScalar(-1.) / quotient; + n2n3 *= p0.dist; + n3n1 *= p1.dist; + n1n2 *= p2.dist; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ()); + return result; + +} + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL); +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2); +btVector3 NormalOf(const btVector3 *vert, const int n); + + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1) +{ + // returns the point where the line p0-p1 intersects the plane n&d + static btVector3 dif; + dif = p1-p0; + btScalar dn= dot(plane.normal,dif); + btScalar t = -(plane.dist+dot(plane.normal,p0) )/dn; + return p0 + (dif*t); +} + +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point) +{ + return point - plane.normal * (dot(point,plane.normal)+plane.dist); +} + +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) +{ + // return the normal of the triangle + // inscribed by v0, v1, and v2 + btVector3 cp=cross(v1-v0,v2-v1); + btScalar m=cp.length(); + if(m==0) return btVector3(1,0,0); + return cp*(btScalar(1.0)/m); +} + + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint) +{ + static btVector3 cp; + cp = cross(udir,vdir).normalized(); + + btScalar distu = -dot(cp,ustart); + btScalar distv = -dot(cp,vstart); + btScalar dist = (btScalar)fabs(distu-distv); + if(upoint) + { + btPlane plane; + plane.normal = cross(vdir,cp).normalized(); + plane.dist = -dot(plane.normal,vstart); + *upoint = PlaneLineIntersection(plane,ustart,ustart+udir); + } + if(vpoint) + { + btPlane plane; + plane.normal = cross(udir,cp).normalized(); + plane.dist = -dot(plane.normal,ustart); + *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir); + } + return dist; +} + + + + + + + +#define COPLANAR (0) +#define UNDER (1) +#define OVER (2) +#define SPLIT (OVER|UNDER) +#define PAPERWIDTH (btScalar(0.001)) + +btScalar planetestepsilon = PAPERWIDTH; + + + +typedef ConvexH::HalfEdge HalfEdge; + +ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size) +{ + vertices.resize(vertices_size); + edges.resize(edges_size); + facets.resize(facets_size); +} + + +int PlaneTest(const btPlane &p, const btVector3 &v); +int PlaneTest(const btPlane &p, const btVector3 &v) { + btScalar a = dot(v,p.normal)+p.dist; + int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR); + return flag; +} + +int SplitTest(ConvexH &convex,const btPlane &plane); +int SplitTest(ConvexH &convex,const btPlane &plane) { + int flag=0; + for(int i=0;i +int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + btAssert(count); + int m=-1; + for(int i=0;idot(p[m],dir)) + m=i; + } + btAssert(m!=-1); + return m; +} + +btVector3 orth(const btVector3 &v); +btVector3 orth(const btVector3 &v) +{ + btVector3 a=cross(v,btVector3(0,0,1)); + btVector3 b=cross(v,btVector3(0,1,0)); + if (a.length() > b.length()) + { + return a.normalized(); + } else { + return b.normalized(); + } +} + + +template +int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + int m=-1; + while(m==-1) + { + m = maxdirfiltered(p,count,dir,allow); + if(allow[m]==3) return m; + T u = orth(dir); + T v = cross(u,dir); + int ma=-1; + for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0)) + { + btScalar s = sinf(SIMD_RADS_PER_DEG*(x)); + btScalar c = cosf(SIMD_RADS_PER_DEG*(x)); + int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(ma==m && mb==m) + { + allow[m]=3; + return m; + } + if(ma!=-1 && ma!=mb) // Yuck - this is really ugly + { + int mc = ma; + for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0)) + { + btScalar s = sinf(SIMD_RADS_PER_DEG*(xx)); + btScalar c = cosf(SIMD_RADS_PER_DEG*(xx)); + int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(mc==m && md==m) + { + allow[m]=3; + return m; + } + mc=md; + } + } + ma=mb; + } + allow[m]=0; + m=-1; + } + btAssert(0); + return m; +} + + + + +int operator ==(const int3 &a,const int3 &b); +int operator ==(const int3 &a,const int3 &b) +{ + for(int i=0;i<3;i++) + { + if(a[i]!=b[i]) return 0; + } + return 1; +} + + +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon); +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) +{ + btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]); + return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON??? +} +int hasedge(const int3 &t, int a,int b); +int hasedge(const int3 &t, int a,int b) +{ + for(int i=0;i<3;i++) + { + int i1= (i+1)%3; + if(t[i]==a && t[i1]==b) return 1; + } + return 0; +} +int hasvert(const int3 &t, int v); +int hasvert(const int3 &t, int v) +{ + return (t[0]==v || t[1]==v || t[2]==v) ; +} +int shareedge(const int3 &a,const int3 &b); +int shareedge(const int3 &a,const int3 &b) +{ + int i; + for(i=0;i<3;i++) + { + int i1= (i+1)%3; + if(hasedge(a,b[i1],b[i])) return 1; + } + return 0; +} + +class Tri; + + + +class Tri : public int3 +{ +public: + int3 n; + int id; + int vmax; + btScalar rise; + Tri(int a,int b,int c):int3(a,b,c),n(-1,-1,-1) + { + vmax=-1; + rise = btScalar(0.0); + } + ~Tri() + { + } + int &neib(int a,int b); +}; + + +int &Tri::neib(int a,int b) +{ + static int er=-1; + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + if((*this)[i]==a && (*this)[i1]==b) return n[i2]; + if((*this)[i]==b && (*this)[i1]==a) return n[i2]; + } + btAssert(0); + return er; +} +void HullLibrary::b2bfix(Tri* s,Tri*t) +{ + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*s)[i1]; + int b = (*s)[i2]; + btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id); + btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id); + m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a); + m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b); + } +} + +void HullLibrary::removeb2b(Tri* s,Tri*t) +{ + b2bfix(s,t); + deAllocateTriangle(s); + + deAllocateTriangle(t); +} + +void HullLibrary::checkit(Tri *t) +{ + (void)t; + + int i; + btAssert(m_tris[t->id]==t); + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*t)[i1]; + int b = (*t)[i2]; + + // release compile fix + (void)i1; + (void)i2; + (void)a; + (void)b; + + btAssert(a!=b); + btAssert( m_tris[t->n[i]]->neib(b,a) == t->id); + } +} + +Tri* HullLibrary::allocateTriangle(int a,int b,int c) +{ + void* mem = btAlignedAlloc(sizeof(Tri),16); + Tri* tr = new (mem)Tri(a,b,c); + tr->id = m_tris.size(); + m_tris.push_back(tr); + + return tr; +} + +void HullLibrary::deAllocateTriangle(Tri* tri) +{ + btAssert(m_tris[tri->id]==tri); + m_tris[tri->id]=NULL; + tri->~Tri(); + btAlignedFree(tri); +} + + +void HullLibrary::extrude(Tri *t0,int v) +{ + int3 t= *t0; + int n = m_tris.size(); + Tri* ta = allocateTriangle(v,t[1],t[2]); + ta->n = int3(t0->n[0],n+1,n+2); + m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0; + Tri* tb = allocateTriangle(v,t[2],t[0]); + tb->n = int3(t0->n[1],n+2,n+0); + m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1; + Tri* tc = allocateTriangle(v,t[0],t[1]); + tc->n = int3(t0->n[2],n+0,n+1); + m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2; + checkit(ta); + checkit(tb); + checkit(tc); + if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]); + if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]); + if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]); + deAllocateTriangle(t0); + +} + +Tri* HullLibrary::extrudable(btScalar epsilon) +{ + int i; + Tri *t=NULL; + for(i=0;iriserise)) + { + t = m_tris[i]; + } + } + return (t->rise >epsilon)?t:NULL ; +} + + + + +int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow) +{ + btVector3 basis[3]; + basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) ); + int p0 = maxdirsterid(verts,verts_count, basis[0],allow); + int p1 = maxdirsterid(verts,verts_count,-basis[0],allow); + basis[0] = verts[p0]-verts[p1]; + if(p0==p1 || basis[0]==btVector3(0,0,0)) + return int4(-1,-1,-1,-1); + basis[1] = cross(btVector3( btScalar(1),btScalar(0.02), btScalar(0)),basis[0]); + basis[2] = cross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)),basis[0]); + if (basis[1].length() > basis[2].length()) + { + basis[1].normalize(); + } else { + basis[1] = basis[2]; + basis[1].normalize (); + } + int p2 = maxdirsterid(verts,verts_count,basis[1],allow); + if(p2 == p0 || p2 == p1) + { + p2 = maxdirsterid(verts,verts_count,-basis[1],allow); + } + if(p2 == p0 || p2 == p1) + return int4(-1,-1,-1,-1); + basis[1] = verts[p2] - verts[p0]; + basis[2] = cross(basis[1],basis[0]).normalized(); + int p3 = maxdirsterid(verts,verts_count,basis[2],allow); + if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow); + if(p3==p0||p3==p1||p3==p2) + return int4(-1,-1,-1,-1); + btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3)); + if(dot(verts[p3]-verts[p0],cross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);} + return int4(p0,p1,p2,p3); +} + +int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) +{ + if(verts_count <4) return 0; + if(vlimit==0) vlimit=1000000000; + int j; + btVector3 bmin(*verts),bmax(*verts); + btAlignedObjectArray isextreme; + isextreme.reserve(verts_count); + btAlignedObjectArray allow; + allow.reserve(verts_count); + + for(j=0;jn=int3(2,3,1); + Tri *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); + Tri *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); + Tri *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2); + isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; + checkit(t0);checkit(t1);checkit(t2);checkit(t3); + + for(j=0;jvmax<0); + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); + } + Tri *te; + vlimit-=4; + while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) + { + int3 ti=*te; + int v=te->vmax; + btAssert(v != -1); + btAssert(!isextreme[v]); // wtf we've already done this vertex + isextreme[v]=1; + //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already + j=m_tris.size(); + while(j--) { + if(!m_tris[j]) continue; + int3 t=*m_tris[j]; + if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) + { + extrude(m_tris[j],v); + } + } + // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle + j=m_tris.size(); + while(j--) + { + if(!m_tris[j]) continue; + if(!hasvert(*m_tris[j],v)) break; + int3 nt=*m_tris[j]; + if(above(verts,nt,center,btScalar(0.01)*epsilon) || cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) ) + { + Tri *nb = m_tris[m_tris[j]->n[0]]; + btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->idvmax>=0) break; + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + if(isextreme[t->vmax]) + { + t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. + } + else + { + t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); + } + } + vlimit --; + } + return 1; +} + +int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) +{ + int rc=calchullgen(verts,verts_count, vlimit) ; + if(!rc) return 0; + btAlignedObjectArray ts; + int i; + + for(i=0;i(ts[i]); + } + m_tris.resize(0); + + return 1; +} + + + + + +bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit) +{ + + int tris_count; + int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast(vlimit) ); + if(!ret) return false; + result.mIndexCount = (unsigned int) (tris_count*3); + result.mFaceCount = (unsigned int) tris_count; + result.mVertices = (btVector3*) vertices; + result.mVcount = (unsigned int) vcount; + return true; + +} + + +void ReleaseHull(PHullResult &result); +void ReleaseHull(PHullResult &result) +{ + if ( result.m_Indices.size() ) + { + result.m_Indices.clear(); + } + + result.mVcount = 0; + result.mIndexCount = 0; + result.mVertices = 0; +} + + +//********************************************************************* +//********************************************************************* +//******** HullLib header +//********************************************************************* +//********************************************************************* + +//********************************************************************* +//********************************************************************* +//******** HullLib implementation +//********************************************************************* +//********************************************************************* + +HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request + HullResult &result) // contains the resulst +{ + HullError ret = QE_FAIL; + + + PHullResult hr; + + unsigned int vcount = desc.mVcount; + if ( vcount < 8 ) vcount = 8; + + btAlignedObjectArray vertexSource; + vertexSource.resize(static_cast(vcount)); + + btVector3 scale; + + unsigned int ovcount; + + bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates! + + if ( ok ) + { + + +// if ( 1 ) // scale vertices back to their original size. + { + for (unsigned int i=0; i(i)]; + v[0]*=scale[0]; + v[1]*=scale[1]; + v[2]*=scale[2]; + } + } + + ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices); + + if ( ok ) + { + + // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. + btAlignedObjectArray vertexScratch; + vertexScratch.resize(static_cast(hr.mVcount)); + + BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount ); + + ret = QE_OK; + + if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle! + { + result.mPolygons = false; + result.mNumOutputVertices = ovcount; + result.m_OutputVertices.resize(static_cast(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount; + + result.m_Indices.resize(static_cast(hr.mIndexCount)); + + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + + if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) + { + + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + + for (unsigned int i=0; i(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount+hr.mFaceCount; + result.m_Indices.resize(static_cast(result.mNumIndices)); + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + +// if ( 1 ) + { + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + btVector3 center; + + center[0] = dx*btScalar(0.5) + bmin[0]; + center[1] = dy*btScalar(0.5) + bmin[1]; + center[2] = dz*btScalar(0.5) + bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 ) + { + + btScalar len = FLT_MAX; + + if ( dx > EPSILON && dx < len ) len = dx; + if ( dy > EPSILON && dy < len ) len = dy; + if ( dz > EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = center[0] - dx; + btScalar x2 = center[0] + dx; + + btScalar y1 = center[1] - dy; + btScalar y2 = center[1] + dy; + + btScalar z1 = center[2] - dz; + btScalar z2 = center[2] + dz; + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; // return cube + + + } + else + { + if ( scale ) + { + scale[0] = dx; + scale[1] = dy; + scale[2] = dz; + + recip[0] = 1 / dx; + recip[1] = 1 / dy; + recip[2] = 1 / dz; + + center[0]*=recip[0]; + center[1]*=recip[1]; + center[2]*=recip[2]; + + } + + } + + + + vtx = (const char *) svertices; + + for (unsigned int i=0; igetX(); + btScalar py = p->getY(); + btScalar pz = p->getZ(); + + if ( scale ) + { + px = px*recip[0]; // normalize + py = py*recip[1]; // normalize + pz = pz*recip[2]; // normalize + } + +// if ( 1 ) + { + unsigned int j; + + for (j=0; j dist2 ) + { + v[0] = px; + v[1] = py; + v[2] = pz; + } + + break; + } + } + + if ( j == vcount ) + { + btVector3& dest = vertices[vcount]; + dest[0] = px; + dest[1] = py; + dest[2] = pz; + vcount++; + } + } + } + + // ok..now make sure we didn't prune so many vertices it is now invalid. +// if ( 1 ) + { + btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; + btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3) + { + btScalar cx = dx*btScalar(0.5) + bmin[0]; + btScalar cy = dy*btScalar(0.5) + bmin[1]; + btScalar cz = dz*btScalar(0.5) + bmin[2]; + + btScalar len = FLT_MAX; + + if ( dx >= EPSILON && dx < len ) len = dx; + if ( dy >= EPSILON && dy < len ) len = dy; + if ( dz >= EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = cx - dx; + btScalar x2 = cx + dx; + + btScalar y1 = cy - dy; + btScalar y2 = cy + dy; + + btScalar z1 = cz - dz; + btScalar z2 = cz + dz; + + vcount = 0; // add box + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; + } + } + + return true; +} + +void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount) +{ + TUIntArray usedIndices; + usedIndices.resize(static_cast(vcount)); + memset(&usedIndices[0],0,sizeof(unsigned int)*vcount); + + ocount = 0; + + for (unsigned int i=0; i= 0 && v < vcount ); + + if ( usedIndices[static_cast(v)] ) // if already remapped + { + indices[i] = usedIndices[static_cast(v)]-1; // index to new array + } + else + { + + indices[i] = ocount; // new index mapping + + overts[ocount][0] = verts[v][0]; // copy old vert to new vert array + overts[ocount][1] = verts[v][1]; + overts[ocount][2] = verts[v][2]; + + ocount++; // increment output vert count + + btAssert( ocount >=0 && ocount <= vcount ); + + usedIndices[static_cast(v)] = ocount; // assign new index remapping + } + } + + +} diff --git a/extern/bullet2/src/LinearMath/btConvexHull.h b/extern/bullet2/src/LinearMath/btConvexHull.h new file mode 100644 index 00000000000..8bb80de0225 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btConvexHull.h @@ -0,0 +1,242 @@ + +/* +Stan Melax Convex Hull Computation +Copyright (c) 2008 Stan Melax http://www.melax.com/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +///includes modifications/improvements by John Ratcliff, see BringOutYourDead below. + +#ifndef CD_HULL_H +#define CD_HULL_H + +#include "LinearMath/btVector3.h" +#include "LinearMath/btAlignedObjectArray.h" + +typedef btAlignedObjectArray TUIntArray; + +class HullResult +{ +public: + HullResult(void) + { + mPolygons = true; + mNumOutputVertices = 0; + mNumFaces = 0; + mNumIndices = 0; + } + bool mPolygons; // true if indices represents polygons, false indices are triangles + unsigned int mNumOutputVertices; // number of vertices in the output hull + btAlignedObjectArray m_OutputVertices; // array of vertices + unsigned int mNumFaces; // the number of faces produced + unsigned int mNumIndices; // the total number of indices + btAlignedObjectArray m_Indices; // pointer to indices. + +// If triangles, then indices are array indexes into the vertex list. +// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc.. +}; + +enum HullFlag +{ + QF_TRIANGLES = (1<<0), // report results as triangles, not polygons. + QF_REVERSE_ORDER = (1<<1), // reverse order of the triangle indices. + QF_DEFAULT = QF_TRIANGLES +}; + + +class HullDesc +{ +public: + HullDesc(void) + { + mFlags = QF_DEFAULT; + mVcount = 0; + mVertices = 0; + mVertexStride = sizeof(btVector3); + mNormalEpsilon = 0.001f; + mMaxVertices = 4096; // maximum number of points to be considered for a convex hull. + mMaxFaces = 4096; + }; + + HullDesc(HullFlag flag, + unsigned int vcount, + const btVector3 *vertices, + unsigned int stride = sizeof(btVector3)) + { + mFlags = flag; + mVcount = vcount; + mVertices = vertices; + mVertexStride = stride; + mNormalEpsilon = btScalar(0.001); + mMaxVertices = 4096; + } + + bool HasHullFlag(HullFlag flag) const + { + if ( mFlags & flag ) return true; + return false; + } + + void SetHullFlag(HullFlag flag) + { + mFlags|=flag; + } + + void ClearHullFlag(HullFlag flag) + { + mFlags&=~flag; + } + + unsigned int mFlags; // flags to use when generating the convex hull. + unsigned int mVcount; // number of vertices in the input point cloud + const btVector3 *mVertices; // the array of vertices. + unsigned int mVertexStride; // the stride of each vertex, in bytes. + btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on. + unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull! + unsigned int mMaxFaces; +}; + +enum HullError +{ + QE_OK, // success! + QE_FAIL // failed. +}; + +class btPlane +{ + public: + btVector3 normal; + btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0 + btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){} + btPlane():normal(),dist(0){} + +}; + + + +class ConvexH +{ + public: + class HalfEdge + { + public: + short ea; // the other half of the edge (index into edges list) + unsigned char v; // the vertex at the start of this edge (index into vertices list) + unsigned char p; // the facet on which this edge lies (index into facets list) + HalfEdge(){} + HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){} + }; + ConvexH() + { + int i; + i=0; + } + ~ConvexH() + { + int i; + i=0; + } + btAlignedObjectArray vertices; + btAlignedObjectArray edges; + btAlignedObjectArray facets; + ConvexH(int vertices_size,int edges_size,int facets_size); +}; + + +class int4 +{ +public: + int x,y,z,w; + int4(){}; + int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + +class PHullResult +{ +public: + + PHullResult(void) + { + mVcount = 0; + mIndexCount = 0; + mFaceCount = 0; + mVertices = 0; + } + + unsigned int mVcount; + unsigned int mIndexCount; + unsigned int mFaceCount; + btVector3* mVertices; + TUIntArray m_Indices; +}; + + + +///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method. +///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape. +class HullLibrary +{ + + btAlignedObjectArray m_tris; + +public: + + HullError CreateConvexHull(const HullDesc& desc, // describes the input request + HullResult& result); // contains the resulst + HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. + +private: + + bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit); + + class Tri* allocateTriangle(int a,int b,int c); + void deAllocateTriangle(Tri*); + void b2bfix(Tri* s,Tri*t); + + void removeb2b(Tri* s,Tri*t); + + void checkit(Tri *t); + + Tri* extrudable(btScalar epsilon); + + int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit); + + int calchullgen(btVector3 *verts,int verts_count, int vlimit); + + int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow); + + class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice); + + void extrude(class Tri* t0,int v); + + ConvexH* test_cube(); + + //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. + //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud. + //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull. + //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation. + void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount); + + bool CleanupVertices(unsigned int svcount, + const btVector3* svertices, + unsigned int stride, + unsigned int &vcount, // output number of vertices + btVector3* vertices, // location to store the results. + btScalar normalepsilon, + btVector3& scale); +}; + + +#endif + diff --git a/extern/bullet2/src/LinearMath/btDefaultMotionState.h b/extern/bullet2/src/LinearMath/btDefaultMotionState.h index d4ec8e8879c..d758f77ed81 100644 --- a/extern/bullet2/src/LinearMath/btDefaultMotionState.h +++ b/extern/bullet2/src/LinearMath/btDefaultMotionState.h @@ -1,7 +1,7 @@ #ifndef DEFAULT_MOTION_STATE_H #define DEFAULT_MOTION_STATE_H -///btDefaultMotionState provides a common implementation to synchronize world transforms with offsets +///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets. struct btDefaultMotionState : public btMotionState { btTransform m_graphicsWorldTrans; diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp index 3d0fb122a6b..5ac230f712f 100644 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.cpp +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.cpp @@ -22,7 +22,12 @@ subject to the following restrictions: can be used by probes that are checking whether the library is actually installed. */ -extern "C" void btBulletMathProbe () {} +extern "C" +{ + void btBulletMathProbe (); + + void btBulletMathProbe () {} +} bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray& planeEquations, const btVector3& point, btScalar margin) @@ -57,6 +62,8 @@ bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const return true; } +bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations); + bool notExist(const btVector3& planeEquation,const btAlignedObjectArray& planeEquations) { int numbrushes = planeEquations.size(); diff --git a/extern/bullet2/src/LinearMath/btGeometryUtil.h b/extern/bullet2/src/LinearMath/btGeometryUtil.h index 766cd75c383..a4b13b45609 100644 --- a/extern/bullet2/src/LinearMath/btGeometryUtil.h +++ b/extern/bullet2/src/LinearMath/btGeometryUtil.h @@ -19,6 +19,7 @@ subject to the following restrictions: #include "btVector3.h" #include "btAlignedObjectArray.h" +///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices. class btGeometryUtil { public: diff --git a/extern/bullet2/src/LinearMath/btHashMap.h b/extern/bullet2/src/LinearMath/btHashMap.h new file mode 100644 index 00000000000..f883e0e489a --- /dev/null +++ b/extern/bullet2/src/LinearMath/btHashMap.h @@ -0,0 +1,303 @@ +#ifndef BT_HASH_MAP_H +#define BT_HASH_MAP_H + +#include "btAlignedObjectArray.h" + +const int BT_HASH_NULL=0xffffffff; + +template +class btHashKey +{ + int m_uid; +public: + + btHashKey(int uid) + :m_uid(uid) + { + } + + int getUid() const + { + return m_uid; + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + btHashKey getKey(const Value& value) const + { + return btHashKey(value.getUid()); + } +}; + + +template +class btHashKeyPtr +{ + int m_uid; +public: + + btHashKeyPtr(int uid) + :m_uid(uid) + { + } + + int getUid() const + { + return m_uid; + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + btHashKeyPtr getKey(const Value& value) const + { + return btHashKeyPtr(value->getUid()); + } +}; + +///The btHashMap template class implements a generic and lightweight hashmap. +///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp +template +class btHashMap +{ + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + btAlignedObjectArray m_valueArray; + + + + void growTables(const Key& key) + { + int newCapacity = m_valueArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_HASH_NULL; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_HASH_NULL; + } + + for(i=0;i= m_hashTable.size()) + { + return BT_HASH_NULL; + } + + int index = m_hashTable[hash]; + while ((index != BT_HASH_NULL) && (key.getUid() == key.getKey(m_valueArray[index]).getUid()) == false) + { + index = m_next[index]; + } + return index; + } + + void clear() + { + m_hashTable.clear(); + m_next.clear(); + m_valueArray.clear(); + } + +}; + +#endif //BT_HASH_MAP_H diff --git a/extern/bullet2/src/LinearMath/btIDebugDraw.h b/extern/bullet2/src/LinearMath/btIDebugDraw.h index 5f40ca39157..563615a9a32 100644 --- a/extern/bullet2/src/LinearMath/btIDebugDraw.h +++ b/extern/bullet2/src/LinearMath/btIDebugDraw.h @@ -31,6 +31,9 @@ DEALINGS IN THE SOFTWARE. #include "btVector3.h" +///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations. +///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld. +///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum. class btIDebugDraw { public: @@ -55,11 +58,24 @@ class btIDebugDraw virtual ~btIDebugDraw() {}; virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0; + + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha) + { + drawTriangle(v0,v1,v2,color,alpha); + } + virtual void drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/) + { + drawLine(v0,v1,color); + drawLine(v1,v2,color); + drawLine(v2,v0,color); + } virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0; virtual void reportErrorWarning(const char* warningString) = 0; + virtual void draw3dText(const btVector3& location,const char* textString) = 0; + virtual void setDebugMode(int debugMode) =0; virtual int getDebugMode() const = 0; diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h index 94f53c3c0a5..14aa4ae2348 100644 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -22,6 +22,9 @@ subject to the following restrictions: #include "btQuaternion.h" + +///The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3. +///Make sure to only include a pure orthogonal matrix without scaling. class btMatrix3x3 { public: btMatrix3x3 () {} @@ -281,6 +284,91 @@ class btMatrix3x3 { } + ///diagonalizes this matrix by the Jacobi method. rot stores the rotation + ///from the coordinate system in which the matrix is diagonal to the original + ///coordinate system, i.e., old_this = rot * new_this * rot^T. The iteration + ///stops when all off-diagonal elements are less than the threshold multiplied + ///by the sum of the absolute values of the diagonal, or when maxSteps have + ///been executed. Note that this matrix is assumed to be symmetric. + void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps) + { + rot.setIdentity(); + for (int step = maxSteps; step > 0; step--) + { + // find off-diagonal element [p][q] with largest magnitude + int p = 0; + int q = 1; + int r = 2; + btScalar max = btFabs(m_el[0][1]); + btScalar v = btFabs(m_el[0][2]); + if (v > max) + { + q = 2; + r = 1; + max = v; + } + v = btFabs(m_el[1][2]); + if (v > max) + { + p = 1; + q = 2; + r = 0; + max = v; + } + + btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2])); + if (max <= t) + { + if (max <= SIMD_EPSILON * t) + { + return; + } + step = 1; + } + + // compute Jacobi rotation J which leads to a zero for element [p][q] + btScalar mpq = m_el[p][q]; + btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq); + btScalar theta2 = theta * theta; + btScalar cos; + btScalar sin; + if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON)) + { + t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2)) + : 1 / (theta - btSqrt(1 + theta2)); + cos = 1 / btSqrt(1 + t * t); + sin = cos * t; + } + else + { + // approximation for large theta-value, i.e., a nearly diagonal matrix + t = 1 / (theta * (2 + btScalar(0.5) / theta2)); + cos = 1 - btScalar(0.5) * t * t; + sin = cos * t; + } + + // apply rotation to matrix (this = J^T * this * J) + m_el[p][q] = m_el[q][p] = 0; + m_el[p][p] -= t * mpq; + m_el[q][q] += t * mpq; + btScalar mrp = m_el[r][p]; + btScalar mrq = m_el[r][q]; + m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq; + m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp; + + // apply rotation to rot (rot = rot * J) + for (int i = 0; i < 3; i++) + { + btVector3& row = rot[i]; + mrp = row[p]; + mrq = row[q]; + row[p] = cos * mrp - sin * mrq; + row[q] = cos * mrq + sin * mrp; + } + } + } + + protected: btScalar cofac(int r1, int c1, int r2, int c2) const @@ -356,7 +444,7 @@ class btMatrix3x3 { m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(), m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(), m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(), - m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].x()); + m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z()); } SIMD_FORCE_INLINE btMatrix3x3 @@ -406,5 +494,11 @@ class btMatrix3x3 { } */ +SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2) +{ + return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] && + m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] && + m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] ); +} #endif diff --git a/extern/bullet2/src/LinearMath/btMinMax.h b/extern/bullet2/src/LinearMath/btMinMax.h index 1b8a3633f38..5e27d62a4a4 100644 --- a/extern/bullet2/src/LinearMath/btMinMax.h +++ b/extern/bullet2/src/LinearMath/btMinMax.h @@ -18,15 +18,15 @@ subject to the following restrictions: #define GEN_MINMAX_H template -SIMD_FORCE_INLINE const T& GEN_min(const T& a, const T& b) +SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) { - return b < a ? b : a; + return a < b ? a : b ; } template -SIMD_FORCE_INLINE const T& GEN_max(const T& a, const T& b) +SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) { - return a < b ? b : a; + return a > b ? a : b; } template @@ -36,7 +36,7 @@ SIMD_FORCE_INLINE const T& GEN_clamped(const T& a, const T& lb, const T& ub) } template -SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) +SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) { if (b < a) { @@ -45,7 +45,7 @@ SIMD_FORCE_INLINE void GEN_set_min(T& a, const T& b) } template -SIMD_FORCE_INLINE void GEN_set_max(T& a, const T& b) +SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) { if (a < b) { diff --git a/extern/bullet2/src/LinearMath/btMotionState.h b/extern/bullet2/src/LinearMath/btMotionState.h index 1975e5ff900..94318140902 100644 --- a/extern/bullet2/src/LinearMath/btMotionState.h +++ b/extern/bullet2/src/LinearMath/btMotionState.h @@ -18,7 +18,7 @@ subject to the following restrictions: #include "btTransform.h" -///btMotionState allows the dynamics world to synchronize the updated world transforms with graphics +///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics ///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation) class btMotionState { diff --git a/extern/bullet2/src/LinearMath/btPoolAllocator.h b/extern/bullet2/src/LinearMath/btPoolAllocator.h new file mode 100644 index 00000000000..e9620ac5faa --- /dev/null +++ b/extern/bullet2/src/LinearMath/btPoolAllocator.h @@ -0,0 +1,97 @@ +/* +Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef _BT_POOL_ALLOCATOR_H +#define _BT_POOL_ALLOCATOR_H + +#include "btScalar.h" +#include "btAlignedAllocator.h" + +///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately. +class btPoolAllocator +{ + int m_elemSize; + int m_maxElements; + int m_freeCount; + void* m_firstFree; + unsigned char* m_pool; + +public: + + btPoolAllocator(int elemSize, int maxElements) + :m_elemSize(elemSize), + m_maxElements(maxElements) + { + m_pool = (unsigned char*) btAlignedAlloc( static_cast(m_elemSize*m_maxElements),16); + + unsigned char* p = m_pool; + m_firstFree = p; + m_freeCount = m_maxElements; + int count = m_maxElements; + while (--count) { + *(void**)p = (p + m_elemSize); + p += m_elemSize; + } + *(void**)p = 0; + } + + ~btPoolAllocator() + { + btAlignedFree( m_pool); + } + + int getFreeCount() const + { + return m_freeCount; + } + + void* allocate(int size) + { + // release mode fix + (void)size; + btAssert(!size || size<=m_elemSize); + btAssert(m_freeCount>0); + void* result = m_firstFree; + m_firstFree = *(void**)m_firstFree; + --m_freeCount; + return result; + } + + bool validPtr(void* ptr) + { + if (ptr) { + if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize)) + { + return true; + } + } + return false; + } + + void freeMemory(void* ptr) + { + if (ptr) { + btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize); + + *(void**)ptr = m_firstFree; + m_firstFree = ptr; + ++m_freeCount; + } + } + + +}; + +#endif //_BT_POOL_ALLOCATOR_H diff --git a/extern/bullet2/src/LinearMath/btQuadWord.h b/extern/bullet2/src/LinearMath/btQuadWord.h index 961ac484d20..2e80fc2ca47 100644 --- a/extern/bullet2/src/LinearMath/btQuadWord.h +++ b/extern/bullet2/src/LinearMath/btQuadWord.h @@ -17,19 +17,31 @@ subject to the following restrictions: #define SIMD_QUADWORD_H #include "btScalar.h" +#include "btMinMax.h" +#include +///The btQuadWordStorage class is base class for btVector3 and btQuaternion. +///Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword. todo: look into this +///ATTRIBUTE_ALIGNED16(class) btQuadWordStorage +class btQuadWordStorage +{ +protected: + + btScalar m_x; + btScalar m_y; + btScalar m_z; + btScalar m_unusedW; + +public: + +}; + ///btQuadWord is base-class for vectors, points -class btQuadWord +class btQuadWord : public btQuadWordStorage { - protected: - btScalar m_x; - btScalar m_y; - btScalar m_z; - btScalar m_unusedW; - public: // SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_x)[i]; } @@ -61,6 +73,8 @@ class btQuadWord SIMD_FORCE_INLINE operator btScalar *() { return &m_x; } SIMD_FORCE_INLINE operator const btScalar *() const { return &m_x; } + + SIMD_FORCE_INLINE void setValue(const btScalar& x, const btScalar& y, const btScalar& z) { m_x=x; @@ -89,47 +103,36 @@ class btQuadWord { } - SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) - :m_x(x),m_y(y),m_z(z) - //todo, remove this in release/simd ? - ,m_unusedW(btScalar(0.)) + SIMD_FORCE_INLINE btQuadWord(const btQuadWordStorage& q) { + *((btQuadWordStorage*)this) = q; + } + + SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z) + { + m_x = x, m_y = y, m_z = z, m_unusedW = 0.0f; } SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) - :m_x(x),m_y(y),m_z(z),m_unusedW(w) { + m_x = x, m_y = y, m_z = z, m_unusedW = w; } SIMD_FORCE_INLINE void setMax(const btQuadWord& other) { - if (other.m_x > m_x) - m_x = other.m_x; - - if (other.m_y > m_y) - m_y = other.m_y; - - if (other.m_z > m_z) - m_z = other.m_z; - - if (other.m_unusedW > m_unusedW) - m_unusedW = other.m_unusedW; + btSetMax(m_x, other.m_x); + btSetMax(m_y, other.m_y); + btSetMax(m_z, other.m_z); + btSetMax(m_unusedW, other.m_unusedW); } SIMD_FORCE_INLINE void setMin(const btQuadWord& other) { - if (other.m_x < m_x) - m_x = other.m_x; - - if (other.m_y < m_y) - m_y = other.m_y; - - if (other.m_z < m_z) - m_z = other.m_z; - - if (other.m_unusedW < m_unusedW) - m_unusedW = other.m_unusedW; + btSetMin(m_x, other.m_x); + btSetMin(m_y, other.m_y); + btSetMin(m_z, other.m_z); + btSetMin(m_unusedW, other.m_unusedW); } diff --git a/extern/bullet2/src/LinearMath/btQuaternion.h b/extern/bullet2/src/LinearMath/btQuaternion.h index 50334970ba6..264751b33e7 100644 --- a/extern/bullet2/src/LinearMath/btQuaternion.h +++ b/extern/bullet2/src/LinearMath/btQuaternion.h @@ -19,6 +19,7 @@ subject to the following restrictions: #include "btVector3.h" +///The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. class btQuaternion : public btQuadWord { public: btQuaternion() {} @@ -158,7 +159,7 @@ public: btQuaternion inverse() const { - return btQuaternion(m_x, m_y, m_z, -m_unusedW); + return btQuaternion(-m_x, -m_y, -m_z, m_unusedW); } SIMD_FORCE_INLINE btQuaternion @@ -285,7 +286,7 @@ slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) } SIMD_FORCE_INLINE btVector3 -quatRotate(btQuaternion& rotation, btVector3& v) +quatRotate(const btQuaternion& rotation, const btVector3& v) { btQuaternion q = rotation * v; q *= rotation.inverse(); @@ -293,7 +294,7 @@ quatRotate(btQuaternion& rotation, btVector3& v) } SIMD_FORCE_INLINE btQuaternion -shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized +shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized { btVector3 c = v0.cross(v1); btScalar d = v0.dot(v1); @@ -308,7 +309,7 @@ shortestArcQuat(btVector3& v0,btVector3& v1) // Game Programming Gems 2.10. make } SIMD_FORCE_INLINE btQuaternion -shortestArcQuatNormalize(btVector3& v0,btVector3& v1) +shortestArcQuatNormalize2(btVector3& v0,btVector3& v1) { v0.normalize(); v1.normalize(); @@ -319,3 +320,4 @@ shortestArcQuatNormalize(btVector3& v0,btVector3& v1) + diff --git a/extern/bullet2/src/LinearMath/btQuickprof.cpp b/extern/bullet2/src/LinearMath/btQuickprof.cpp index 37a0c8c3be5..e5b1196149b 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.cpp +++ b/extern/bullet2/src/LinearMath/btQuickprof.cpp @@ -1,38 +1,282 @@ /* -Copyright (c) 2006 Tyler Streeter -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. +/*************************************************************************************************** +** +** profile.cpp +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). #include "LinearMath/btQuickprof.h" -#ifdef USE_QUICKPROF -// Note: We must declare these private static variables again here to -// avoid link errors. -bool btProfiler::mEnabled = false; -btClock btProfiler::mClock; -unsigned long int btProfiler::mCurrentCycleStartMicroseconds = 0; -unsigned long int btProfiler::mLastCycleDurationMicroseconds = 0; -std::map btProfiler::mProfileBlocks; -std::ofstream btProfiler::mOutputFile; -bool btProfiler::mFirstFileOutput = true; -btProfiler::BlockTimingMethod btProfiler::mFileOutputMethod; -unsigned long int btProfiler::mCycleNumber = 0; -#endif //USE_QUICKPROF +#ifdef USE_BT_CLOCK + +static btClock gProfileClock; + +inline void Profile_Get_Ticks(unsigned long int * ticks) +{ + *ticks = gProfileClock.getTimeMicroseconds(); +} + +inline float Profile_Get_Tick_Rate(void) +{ +// return 1000000.f; + return 1000.f; + +} + + + +/*************************************************************************************************** +** +** CProfileNode +** +***************************************************************************************************/ + +/*********************************************************************************************** + * INPUT: * + * name - pointer to a static string which is the name of this profile node * + * parent - parent pointer * + * * + * WARNINGS: * + * The name is assumed to be a static pointer, only the pointer is stored and compared for * + * efficiency reasons. * + *=============================================================================================*/ +CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) : + Name( name ), + TotalCalls( 0 ), + TotalTime( 0 ), + StartTime( 0 ), + RecursionCounter( 0 ), + Parent( parent ), + Child( NULL ), + Sibling( NULL ) +{ + Reset(); +} + + +void CProfileNode::CleanupMemory() +{ + delete ( Child); + Child = NULL; + delete ( Sibling); + Sibling = NULL; +} + +CProfileNode::~CProfileNode( void ) +{ + delete ( Child); + delete ( Sibling); +} + + +/*********************************************************************************************** + * INPUT: * + * name - static string pointer to the name of the node we are searching for * + * * + * WARNINGS: * + * All profile names are assumed to be static strings so this function uses pointer compares * + * to find the named node. * + *=============================================================================================*/ +CProfileNode * CProfileNode::Get_Sub_Node( const char * name ) +{ + // Try to find this sub node + CProfileNode * child = Child; + while ( child ) { + if ( child->Name == name ) { + return child; + } + child = child->Sibling; + } + + // We didn't find it, so add it + + CProfileNode * node = new CProfileNode( name, this ); + node->Sibling = Child; + Child = node; + return node; +} + + +void CProfileNode::Reset( void ) +{ + TotalCalls = 0; + TotalTime = 0.0f; + gProfileClock.reset(); + + if ( Child ) { + Child->Reset(); + } + if ( Sibling ) { + Sibling->Reset(); + } +} + + +void CProfileNode::Call( void ) +{ + TotalCalls++; + if (RecursionCounter++ == 0) { + Profile_Get_Ticks(&StartTime); + } +} + + +bool CProfileNode::Return( void ) +{ + if ( --RecursionCounter == 0 && TotalCalls != 0 ) { + unsigned long int time; + Profile_Get_Ticks(&time); + time-=StartTime; + TotalTime += (float)time / Profile_Get_Tick_Rate(); + } + return ( RecursionCounter == 0 ); +} + + +/*************************************************************************************************** +** +** CProfileIterator +** +***************************************************************************************************/ +CProfileIterator::CProfileIterator( CProfileNode * start ) +{ + CurrentParent = start; + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::First(void) +{ + CurrentChild = CurrentParent->Get_Child(); +} + + +void CProfileIterator::Next(void) +{ + CurrentChild = CurrentChild->Get_Sibling(); +} + + +bool CProfileIterator::Is_Done(void) +{ + return CurrentChild == NULL; +} + + +void CProfileIterator::Enter_Child( int index ) +{ + CurrentChild = CurrentParent->Get_Child(); + while ( (CurrentChild != NULL) && (index != 0) ) { + index--; + CurrentChild = CurrentChild->Get_Sibling(); + } + + if ( CurrentChild != NULL ) { + CurrentParent = CurrentChild; + CurrentChild = CurrentParent->Get_Child(); + } +} + + +void CProfileIterator::Enter_Parent( void ) +{ + if ( CurrentParent->Get_Parent() != NULL ) { + CurrentParent = CurrentParent->Get_Parent(); + } + CurrentChild = CurrentParent->Get_Child(); +} + + +/*************************************************************************************************** +** +** CProfileManager +** +***************************************************************************************************/ + +CProfileNode CProfileManager::Root( "Root", NULL ); +CProfileNode * CProfileManager::CurrentNode = &CProfileManager::Root; +int CProfileManager::FrameCounter = 0; +unsigned long int CProfileManager::ResetTime = 0; + + +/*********************************************************************************************** + * CProfileManager::Start_Profile -- Begin a named profile * + * * + * Steps one level deeper into the tree, if a child already exists with the specified name * + * then it accumulates the profiling; otherwise a new child node is added to the profile tree. * + * * + * INPUT: * + * name - name of this profiling record * + * * + * WARNINGS: * + * The string used is assumed to be a static string; pointer compares are used throughout * + * the profiling code for efficiency. * + *=============================================================================================*/ +void CProfileManager::Start_Profile( const char * name ) +{ + if (name != CurrentNode->Get_Name()) { + CurrentNode = CurrentNode->Get_Sub_Node( name ); + } + + CurrentNode->Call(); +} + + +/*********************************************************************************************** + * CProfileManager::Stop_Profile -- Stop timing and record the results. * + *=============================================================================================*/ +void CProfileManager::Stop_Profile( void ) +{ + // Return will indicate whether we should back up to our parent (we may + // be profiling a recursive function) + if (CurrentNode->Return()) { + CurrentNode = CurrentNode->Get_Parent(); + } +} + + +/*********************************************************************************************** + * CProfileManager::Reset -- Reset the contents of the profiling system * + * * + * This resets everything except for the tree structure. All of the timing data is reset. * + *=============================================================================================*/ +void CProfileManager::Reset( void ) +{ + Root.Reset(); + Root.Call(); + FrameCounter = 0; + Profile_Get_Ticks(&ResetTime); +} + + +/*********************************************************************************************** + * CProfileManager::Increment_Frame_Counter -- Increment the frame counter * + *=============================================================================================*/ +void CProfileManager::Increment_Frame_Counter( void ) +{ + FrameCounter++; +} + + +/*********************************************************************************************** + * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset * + *=============================================================================================*/ +float CProfileManager::Get_Time_Since_Reset( void ) +{ + unsigned long int time; + Profile_Get_Ticks(&time); + time -= ResetTime; + return (float)time / Profile_Get_Tick_Rate(); +} + +#endif //USE_BT_CLOCK + diff --git a/extern/bullet2/src/LinearMath/btQuickprof.h b/extern/bullet2/src/LinearMath/btQuickprof.h index a885967c5fa..b033940ca5c 100644 --- a/extern/bullet2/src/LinearMath/btQuickprof.h +++ b/extern/bullet2/src/LinearMath/btQuickprof.h @@ -1,20 +1,11 @@ -/* -Copyright (c) 2006 Tyler Streeter -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -*/ - -// Please visit the project website (http://quickprof.sourceforge.net) -// for usage instructions. +/*************************************************************************************************** +** +** Real-Time Hierarchical Profiling for Game Programming Gems 3 +** +** by Greg Hjelstrom & Byon Garrabrant +** +***************************************************************************************************/ // Credits: The Clock class was inspired by the Timer classes in // Ogre (www.ogre3d.org). @@ -23,9 +14,10 @@ subject to the following restrictions: #define QUICK_PROF_H #include "btScalar.h" - -//#define USE_QUICKPROF 1 -//Don't use quickprof for now, because it contains STL. TODO: replace STL by Bullet container classes. +#include "LinearMath/btAlignedAllocator.h" +#include +//To disable built-in profiling, please comment out next line +//#define BT_NO_PROFILE 1 //if you don't need btClock, you can comment next line @@ -34,678 +26,332 @@ subject to the following restrictions: #ifdef USE_BT_CLOCK #ifdef __CELLOS_LV2__ #include +#include #include -typedef uint64_t __int64; #endif #if defined (SUNOS) || defined (__SUNOS__) - #include +#include #endif #if defined(WIN32) || defined(_WIN32) - #define USE_WINDOWS_TIMERS - #define WIN32_LEAN_AND_MEAN - #define NOWINRES - #define NOMCX - #define NOIME +#define USE_WINDOWS_TIMERS +#define WIN32_LEAN_AND_MEAN +#define NOWINRES +#define NOMCX +#define NOIME #ifdef _XBOX - #include +#include #else - #include +#include #endif - #include +#include #else - #include +#include #endif #define mymin(a,b) (a > b ? a : b) -/// basic clock +///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling. class btClock +{ +public: + btClock() { - public: - btClock() - { #ifdef USE_WINDOWS_TIMERS - QueryPerformanceFrequency(&mClockFrequency); + QueryPerformanceFrequency(&mClockFrequency); #endif - reset(); - } + reset(); + } - ~btClock() - { - } + ~btClock() + { + } - /// Resets the initial reference time. - void reset() - { + /// Resets the initial reference time. + void reset() + { #ifdef USE_WINDOWS_TIMERS - QueryPerformanceCounter(&mStartTime); - mStartTick = GetTickCount(); - mPrevElapsedTime = 0; + QueryPerformanceCounter(&mStartTime); + mStartTick = GetTickCount(); + mPrevElapsedTime = 0; #else #ifdef __CELLOS_LV2__ - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - mStartTime = newTime; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + mStartTime = newTime; #else - gettimeofday(&mStartTime, 0); + gettimeofday(&mStartTime, 0); #endif #endif - } + } - /// Returns the time in ms since the last call to reset or since - /// the btClock was created. - unsigned long int getTimeMilliseconds() - { + /// Returns the time in ms since the last call to reset or since + /// the btClock was created. + unsigned long int getTimeMilliseconds() + { #ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; + + // Recompute the number of millisecond ticks elapsed. + msecTicks = (unsigned long)(1000 * elapsedTime / mClockFrequency.QuadPart); + } - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; - // Recompute the number of millisecond ticks elapsed. - msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); - } - - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; - - return msecTicks; + return msecTicks; #else - + #ifdef __CELLOS_LV2__ - __int64 freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq) / 1000.0; - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - - return (newTime-mStartTime) / dFreq; + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq) / 1000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + SYS_TIMEBASE_GET( newTime ); + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + + return (unsigned long int)((double(newTime-mStartTime)) / dFreq); #else - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + - (currentTime.tv_usec - mStartTime.tv_usec) / 1000; + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000 + + (currentTime.tv_usec - mStartTime.tv_usec) / 1000; #endif //__CELLOS_LV2__ #endif + } + + /// Returns the time in us since the last call to reset or since + /// the Clock was created. + unsigned long int getTimeMicroseconds() + { +#ifdef USE_WINDOWS_TIMERS + LARGE_INTEGER currentTime; + QueryPerformanceCounter(¤tTime); + LONGLONG elapsedTime = currentTime.QuadPart - + mStartTime.QuadPart; + + // Compute the number of millisecond ticks elapsed. + unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / + mClockFrequency.QuadPart); + + // Check for unexpected leaps in the Win32 performance counter. + // (This is caused by unexpected data across the PCI to ISA + // bridge, aka south bridge. See Microsoft KB274323.) + unsigned long elapsedTicks = GetTickCount() - mStartTick; + signed long msecOff = (signed long)(msecTicks - elapsedTicks); + if (msecOff < -100 || msecOff > 100) + { + // Adjust the starting time forwards. + LONGLONG msecAdjustment = mymin(msecOff * + mClockFrequency.QuadPart / 1000, elapsedTime - + mPrevElapsedTime); + mStartTime.QuadPart += msecAdjustment; + elapsedTime -= msecAdjustment; } - /// Returns the time in us since the last call to reset or since - /// the Clock was created. - unsigned long int getTimeMicroseconds() - { -#ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER currentTime; - QueryPerformanceCounter(¤tTime); - LONGLONG elapsedTime = currentTime.QuadPart - - mStartTime.QuadPart; + // Store the current elapsed time for adjustments next time. + mPrevElapsedTime = elapsedTime; - // Compute the number of millisecond ticks elapsed. - unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / - mClockFrequency.QuadPart); + // Convert to microseconds. + unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / + mClockFrequency.QuadPart); - // Check for unexpected leaps in the Win32 performance counter. - // (This is caused by unexpected data across the PCI to ISA - // bridge, aka south bridge. See Microsoft KB274323.) - unsigned long elapsedTicks = GetTickCount() - mStartTick; - signed long msecOff = (signed long)(msecTicks - elapsedTicks); - if (msecOff < -100 || msecOff > 100) - { - // Adjust the starting time forwards. - LONGLONG msecAdjustment = mymin(msecOff * - mClockFrequency.QuadPart / 1000, elapsedTime - - mPrevElapsedTime); - mStartTime.QuadPart += msecAdjustment; - elapsedTime -= msecAdjustment; - } - - // Store the current elapsed time for adjustments next time. - mPrevElapsedTime = elapsedTime; - - // Convert to microseconds. - unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / - mClockFrequency.QuadPart); - - return usecTicks; + return usecTicks; #else #ifdef __CELLOS_LV2__ - __int64 freq=sys_time_get_timebase_frequency(); - double dFreq=((double) freq)/ 1000000.0; - typedef uint64_t __int64; - typedef __int64 ClockSize; - ClockSize newTime; - __asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); - - return (newTime-mStartTime) / dFreq; + uint64_t freq=sys_time_get_timebase_frequency(); + double dFreq=((double) freq)/ 1000000.0; + typedef uint64_t ClockSize; + ClockSize newTime; + //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory"); + SYS_TIMEBASE_GET( newTime ); + + return (unsigned long int)((double(newTime-mStartTime)) / dFreq); #else - struct timeval currentTime; - gettimeofday(¤tTime, 0); - return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + - (currentTime.tv_usec - mStartTime.tv_usec); + struct timeval currentTime; + gettimeofday(¤tTime, 0); + return (currentTime.tv_sec - mStartTime.tv_sec) * 1000000 + + (currentTime.tv_usec - mStartTime.tv_usec); #endif//__CELLOS_LV2__ #endif - } + } - private: +private: #ifdef USE_WINDOWS_TIMERS - LARGE_INTEGER mClockFrequency; - DWORD mStartTick; - LONGLONG mPrevElapsedTime; - LARGE_INTEGER mStartTime; + LARGE_INTEGER mClockFrequency; + DWORD mStartTick; + LONGLONG mPrevElapsedTime; + LARGE_INTEGER mStartTime; #else #ifdef __CELLOS_LV2__ - uint64_t mStartTime; + uint64_t mStartTime; #else - struct timeval mStartTime; + struct timeval mStartTime; #endif #endif //__CELLOS_LV2__ - }; +}; #endif //USE_BT_CLOCK -#ifdef USE_QUICKPROF -#include -#include -#include -#include +///A node in the Profile Hierarchy Tree +class CProfileNode { +public: + CProfileNode( const char * name, CProfileNode * parent ); + ~CProfileNode( void ); + CProfileNode * Get_Sub_Node( const char * name ); + CProfileNode * Get_Parent( void ) { return Parent; } + CProfileNode * Get_Sibling( void ) { return Sibling; } + CProfileNode * Get_Child( void ) { return Child; } -namespace hidden -{ - /// A simple data structure representing a single timed block - /// of code. - struct ProfileBlock - { - ProfileBlock() - { - currentBlockStartMicroseconds = 0; - currentCycleTotalMicroseconds = 0; - lastCycleTotalMicroseconds = 0; - totalMicroseconds = 0; - } + void CleanupMemory(); + void Reset( void ); + void Call( void ); + bool Return( void ); - /// The starting time (in us) of the current block update. - unsigned long int currentBlockStartMicroseconds; + const char * Get_Name( void ) { return Name; } + int Get_Total_Calls( void ) { return TotalCalls; } + float Get_Total_Time( void ) { return TotalTime; } - /// The accumulated time (in us) spent in this block during the - /// current profiling cycle. - unsigned long int currentCycleTotalMicroseconds; +protected: - /// The accumulated time (in us) spent in this block during the - /// past profiling cycle. - unsigned long int lastCycleTotalMicroseconds; - - /// The total accumulated time (in us) spent in this block. - unsigned long int totalMicroseconds; - }; + const char * Name; + int TotalCalls; + float TotalTime; + unsigned long int StartTime; + int RecursionCounter; + CProfileNode * Parent; + CProfileNode * Child; + CProfileNode * Sibling; }; -/// A static class that manages timing for a set of profiling blocks. -class btProfiler +///An iterator to navigate through the tree +class CProfileIterator { public: - /// A set of ways to retrieve block timing data. - enum BlockTimingMethod - { - /// The total time spent in the block (in seconds) since the - /// profiler was initialized. - BLOCK_TOTAL_SECONDS, + // Access all the children of the current parent + void First(void); + void Next(void); + bool Is_Done(void); + bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); } - /// The total time spent in the block (in ms) since the - /// profiler was initialized. - BLOCK_TOTAL_MILLISECONDS, + void Enter_Child( int index ); // Make the given child the new parent + void Enter_Largest_Child( void ); // Make the largest child the new parent + void Enter_Parent( void ); // Make the current parent's parent the new parent - /// The total time spent in the block (in us) since the - /// profiler was initialized. - BLOCK_TOTAL_MICROSECONDS, + // Access the current child + const char * Get_Current_Name( void ) { return CurrentChild->Get_Name(); } + int Get_Current_Total_Calls( void ) { return CurrentChild->Get_Total_Calls(); } + float Get_Current_Total_Time( void ) { return CurrentChild->Get_Total_Time(); } - /// The total time spent in the block, as a % of the total - /// elapsed time since the profiler was initialized. - BLOCK_TOTAL_PERCENT, + // Access the current parent + const char * Get_Current_Parent_Name( void ) { return CurrentParent->Get_Name(); } + int Get_Current_Parent_Total_Calls( void ) { return CurrentParent->Get_Total_Calls(); } + float Get_Current_Parent_Total_Time( void ) { return CurrentParent->Get_Total_Time(); } - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle. - BLOCK_CYCLE_SECONDS, +protected: - /// The time spent in the block (in ms) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MILLISECONDS, + CProfileNode * CurrentParent; + CProfileNode * CurrentChild; - /// The time spent in the block (in us) in the most recent - /// profiling cycle. - BLOCK_CYCLE_MICROSECONDS, - - /// The time spent in the block (in seconds) in the most recent - /// profiling cycle, as a % of the total cycle time. - BLOCK_CYCLE_PERCENT - }; - - /// Initializes the profiler. This must be called first. If this is - /// never called, the profiler is effectively disabled; all other - /// functions will return immediately. The first parameter - /// is the name of an output data file; if this string is not empty, - /// data will be saved on every profiling cycle; if this string is - /// empty, no data will be saved to a file. The second parameter - /// determines which timing method is used when printing data to the - /// output file. - inline static void init(const std::string outputFilename="", - BlockTimingMethod outputMethod=BLOCK_CYCLE_MILLISECONDS); - - /// Cleans up allocated memory. - inline static void destroy(); - - /// Begins timing the named block of code. - inline static void beginBlock(const std::string& name); - - /// Updates the accumulated time spent in the named block by adding - /// the elapsed time since the last call to startBlock for this block - /// name. - inline static void endBlock(const std::string& name); - - /// Returns the time spent in the named block according to the - /// given timing method. See comments on BlockTimingMethod for details. - inline static double getBlockTime(const std::string& name, - BlockTimingMethod method=BLOCK_CYCLE_MILLISECONDS); - - /// Defines the end of a profiling cycle. Use this regularly if you - /// want to generate detailed timing information. This must not be - /// called within a timing block. - inline static void endProfilingCycle(); - - /// A helper function that creates a string of statistics for - /// each timing block. This is mainly for printing an overall - /// summary to the command line. - inline static std::string createStatsString( - BlockTimingMethod method=BLOCK_TOTAL_PERCENT); - -//private: - inline btProfiler(); - - inline ~btProfiler(); - - /// Prints an error message to standard output. - inline static void printError(const std::string& msg) - { - //btAssert(0); - std::cout << "[QuickProf error] " << msg << std::endl; - } - - /// Determines whether the profiler is enabled. - static bool mEnabled; - - /// The clock used to time profile blocks. - static btClock mClock; - - /// The starting time (in us) of the current profiling cycle. - static unsigned long int mCurrentCycleStartMicroseconds; - - /// The duration (in us) of the most recent profiling cycle. - static unsigned long int mLastCycleDurationMicroseconds; - - /// Internal map of named profile blocks. - static std::map mProfileBlocks; - - /// The data file used if this feature is enabled in 'init.' - static std::ofstream mOutputFile; - - /// Tracks whether we have begun print data to the output file. - static bool mFirstFileOutput; - - /// The method used when printing timing data to an output file. - static BlockTimingMethod mFileOutputMethod; - - /// The number of the current profiling cycle. - static unsigned long int mCycleNumber; + CProfileIterator( CProfileNode * start ); + friend class CProfileManager; }; -btProfiler::btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} +///The Manager for the Profile system +class CProfileManager { +public: + static void Start_Profile( const char * name ); + static void Stop_Profile( void ); -btProfiler::~btProfiler() -{ - // This never gets called because a btProfiler instance is never - // created. -} - -void btProfiler::init(const std::string outputFilename, - BlockTimingMethod outputMethod) -{ - mEnabled = true; - - if (!outputFilename.empty()) + static void CleanupMemory(void) { - mOutputFile.open(outputFilename.c_str()); + Root.CleanupMemory(); } - mFileOutputMethod = outputMethod; + static void Reset( void ); + static void Increment_Frame_Counter( void ); + static int Get_Frame_Count_Since_Reset( void ) { return FrameCounter; } + static float Get_Time_Since_Reset( void ); - mClock.reset(); + static CProfileIterator * Get_Iterator( void ) + { + + return new CProfileIterator( &Root ); + } + static void Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); } - // Set the start time for the first cycle. - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} +private: + static CProfileNode Root; + static CProfileNode * CurrentNode; + static int FrameCounter; + static unsigned long int ResetTime; +}; -void btProfiler::destroy() -{ - if (!mEnabled) - { - return; + +///ProfileSampleClass is a simple way to profile a function's scope +///Use the BT_PROFILE macro at the start of scope to time +class CProfileSample { +public: + CProfileSample( const char * name ) + { + CProfileManager::Start_Profile( name ); } - if (mOutputFile.is_open()) - { - mOutputFile.close(); + ~CProfileSample( void ) + { + CProfileManager::Stop_Profile(); } +}; - // Destroy all ProfileBlocks. - while (!mProfileBlocks.empty()) - { - delete (*mProfileBlocks.begin()).second; - mProfileBlocks.erase(mProfileBlocks.begin()); - } -} - -void btProfiler::beginBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - if (name.empty()) - { - printError("Cannot allow unnamed profile blocks."); - return; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // Create a new ProfileBlock. - mProfileBlocks[name] = new hidden::ProfileBlock(); - block = mProfileBlocks[name]; - } - - // We do this at the end to get more accurate results. - block->currentBlockStartMicroseconds = mClock.getTimeMicroseconds(); -} - -void btProfiler::endBlock(const std::string& name) -{ - if (!mEnabled) - { - return; - } - - // We do this at the beginning to get more accurate results. - unsigned long int endTick = mClock.getTimeMicroseconds(); - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return; - } - - unsigned long int blockDuration = endTick - - block->currentBlockStartMicroseconds; - block->currentCycleTotalMicroseconds += blockDuration; - block->totalMicroseconds += blockDuration; -} - -double btProfiler::getBlockTime(const std::string& name, - BlockTimingMethod method) -{ - if (!mEnabled) - { - return 0; - } - - hidden::ProfileBlock* block = mProfileBlocks[name]; - - if (!block) - { - // The named block does not exist. Print an error. - printError("The profile block named '" + name + - "' does not exist."); - return 0; - } - - double result = 0; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - result = (double)block->totalMicroseconds * (double)0.000001; - break; - case BLOCK_TOTAL_MILLISECONDS: - result = (double)block->totalMicroseconds * (double)0.001; - break; - case BLOCK_TOTAL_MICROSECONDS: - result = (double)block->totalMicroseconds; - break; - case BLOCK_TOTAL_PERCENT: - { - double timeSinceInit = (double)mClock.getTimeMicroseconds(); - if (timeSinceInit <= 0) - { - result = 0; - } - else - { - result = 100.0 * (double)block->totalMicroseconds / - timeSinceInit; - } - break; - } - case BLOCK_CYCLE_SECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.000001; - break; - case BLOCK_CYCLE_MILLISECONDS: - result = (double)block->lastCycleTotalMicroseconds * - (double)0.001; - break; - case BLOCK_CYCLE_MICROSECONDS: - result = (double)block->lastCycleTotalMicroseconds; - break; - case BLOCK_CYCLE_PERCENT: - { - if (0 == mLastCycleDurationMicroseconds) - { - // We have not yet finished a cycle, so just return zero - // percent to avoid a divide by zero error. - result = 0; - } - else - { - result = 100.0 * (double)block->lastCycleTotalMicroseconds / - mLastCycleDurationMicroseconds; - } - break; - } - default: - break; - } - - return result; -} - -void btProfiler::endProfilingCycle() -{ - if (!mEnabled) - { - return; - } - - // Store the duration of the cycle that just finished. - mLastCycleDurationMicroseconds = mClock.getTimeMicroseconds() - - mCurrentCycleStartMicroseconds; - - // For each block, update data for the cycle that just finished. - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - hidden::ProfileBlock* block = (*iter).second; - block->lastCycleTotalMicroseconds = - block->currentCycleTotalMicroseconds; - block->currentCycleTotalMicroseconds = 0; - } - - if (mOutputFile.is_open()) - { - // Print data to the output file. - if (mFirstFileOutput) - { - // On the first iteration, print a header line that shows the - // names of each profiling block. - mOutputFile << "#cycle, "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << (*iter).first << ", "; - } - - mOutputFile << std::endl; - mFirstFileOutput = false; - } - - mOutputFile << mCycleNumber << ", "; - - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); - ++iter) - { - mOutputFile << getBlockTime((*iter).first, mFileOutputMethod) - << ", "; - } - - mOutputFile << std::endl; - } - - ++mCycleNumber; - mCurrentCycleStartMicroseconds = mClock.getTimeMicroseconds(); -} - -std::string btProfiler::createStatsString(BlockTimingMethod method) -{ - if (!mEnabled) - { - return ""; - } - - std::string s; - std::string suffix; - - switch(method) - { - case BLOCK_TOTAL_SECONDS: - suffix = "s"; - break; - case BLOCK_TOTAL_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_TOTAL_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_TOTAL_PERCENT: - { - suffix = "%"; - break; - } - case BLOCK_CYCLE_SECONDS: - suffix = "s"; - break; - case BLOCK_CYCLE_MILLISECONDS: - suffix = "ms"; - break; - case BLOCK_CYCLE_MICROSECONDS: - suffix = "us"; - break; - case BLOCK_CYCLE_PERCENT: - { - suffix = "%"; - break; - } - default: - break; - } - - std::map::iterator iter; - for (iter = mProfileBlocks.begin(); iter != mProfileBlocks.end(); ++iter) - { - if (iter != mProfileBlocks.begin()) - { - s += "\n"; - } - - char blockTime[64]; - sprintf(blockTime, "%lf", getBlockTime((*iter).first, method)); - - s += (*iter).first; - s += ": "; - s += blockTime; - s += " "; - s += suffix; - } - - return s; -} +#if !defined(BT_NO_PROFILE) +#define BT_PROFILE( name ) CProfileSample __profile( name ) +#else +#define BT_PROFILE( name ) +#endif -#define BEGIN_PROFILE(a) btProfiler::beginBlock(a) -#define END_PROFILE(a) btProfiler::endBlock(a) -#else //USE_QUICKPROF -#define BEGIN_PROFILE(a) -#define END_PROFILE(a) - -#endif //USE_QUICKPROF #endif //QUICK_PROF_H diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 01ad93e786a..3c96857d4eb 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -18,57 +18,123 @@ subject to the following restrictions: #define SIMD___SCALAR_H #include +#include //size_t for MSVC 6.0 #include #include #include +#define BT_BULLET_VERSION 272 + +inline int btGetVersion() +{ + return BT_BULLET_VERSION; +} + +#if defined(DEBUG) || defined (_DEBUG) +#define BT_DEBUG +#endif + + #ifdef WIN32 #if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300) + #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED128(a) a #else - #define BT_HAS_ALIGNED_ALOCATOR - #pragma warning(disable:4530) - #pragma warning(disable:4996) - #pragma warning(disable:4786) + #define BT_HAS_ALIGNED_ALLOCATOR + #pragma warning(disable : 4324) // disable padding warning +// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning. +// #pragma warning(disable:4996) //Turn off warnings about deprecated C routines +// #pragma warning(disable:4786) // Disable the "debug name too long" warning + #define SIMD_FORCE_INLINE __forceinline #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a + #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a #ifdef _XBOX #define BT_USE_VMX128 + + #include + #define BT_HAVE_NATIVE_FSEL + #define btFsel(a,b,c) __fsel((a),(b),(c)) #else #define BT_USE_SSE #endif #endif //__MINGW32__ #include +#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert +#else + #define btAssert(x) +#endif //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + #else #if defined (__CELLOS_LV2__) #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) #ifndef assert #include #endif #define btAssert assert //btFullAssert is optional, slows down a lot #define btFullAssert(x) + + #define btLikely(_c) _c + #define btUnlikely(_c) _c + #else +#ifdef USE_LIBSPE2 + + #define SIMD_FORCE_INLINE __inline + #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16))) + #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128))) + #ifndef assert + #include + #endif + #define btAssert assert + //btFullAssert is optional, slows down a lot + #define btFullAssert(x) + + + #define btLikely(_c) __builtin_expect((_c), 1) + #define btUnlikely(_c) __builtin_expect((_c), 0) + + +#else //non-windows systems #define SIMD_FORCE_INLINE inline #define ATTRIBUTE_ALIGNED16(a) a + #define ATTRIBUTE_ALIGNED128(a) a #ifndef assert #include #endif + +#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot #define btFullAssert(x) + #define btLikely(_c) _c + #define btUnlikely(_c) _c + + +#endif // LIBSPE2 + #endif //__CELLOS_LV2__ #endif @@ -81,6 +147,7 @@ subject to the following restrictions: #endif #endif +///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision. #if defined(BT_USE_DOUBLE_PRECISION) typedef double btScalar; #else @@ -88,6 +155,19 @@ typedef float btScalar; #endif + +#define BT_DECLARE_ALIGNED_ALLOCATOR() \ + SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ + + + #if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS) SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); } @@ -105,12 +185,34 @@ SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); } #else -SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrtf(x); } +SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) +{ +#ifdef USE_APPROXIMATION + double x, z, tempf; + unsigned long *tfptr = ((unsigned long *)&tempf) + 1; + + tempf = y; + *tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */ + x = tempf; + z = y*btScalar(0.5); /* hoist out the “/2” */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); /* iteration formula */ + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + x = (btScalar(1.5)*x)-(x*x)*(x*z); + return x*y; +#else + return sqrtf(y); +#endif +} SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); } SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } +SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { + btAssert(x <= btScalar(1.)); + return acosf(x); +} SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } @@ -159,14 +261,6 @@ SIMD_FORCE_INLINE bool btGreaterEqual (btScalar a, btScalar eps) { return (!((a) <= eps)); } -/*SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); } -SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); } -SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); } -SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acosf(x); } -SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asinf(x); } -SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); } -SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); } -*/ SIMD_FORCE_INLINE int btIsNegative(btScalar x) { return x < btScalar(0.0) ? 1 : 0; @@ -177,5 +271,151 @@ SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; #define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +#ifndef btFsel +SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c) +{ + return a >= 0 ? b : c; +} +#endif +#define btFsels(a,b,c) (btScalar)btFsel(a,b,c) + + +SIMD_FORCE_INLINE bool btMachineIsLittleEndian() +{ + long int i = 1; + const char *p = (const char *) &i; + if (p[0] == 1) // Lowest address contains the least significant byte + return true; + else + return false; +} + + + +///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360 +///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html +SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) +{ + // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero + // Rely on positive value or'ed with its negative having sign bit on + // and zero value or'ed with its negative (which is still zero) having sign bit off + // Use arithmetic shift right, shifting the sign bit through all 32 bits + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero) +{ + unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31); + unsigned testEqz = ~testNz; + return static_cast((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); +} +SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero) +{ +#ifdef BT_HAVE_NATIVE_FSEL + return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero); +#else + return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; +#endif +} + +template SIMD_FORCE_INLINE void btSwap(T& a, T& b) +{ + T tmp = a; + a = b; + b = tmp; +} + + +//PCK: endian swapping functions +SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val) +{ + return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24)); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val) +{ + return static_cast(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8)); +} + +SIMD_FORCE_INLINE unsigned btSwapEndian(int val) +{ + return btSwapEndian((unsigned)val); +} + +SIMD_FORCE_INLINE unsigned short btSwapEndian(short val) +{ + return btSwapEndian((unsigned short) val); +} + +///btSwapFloat uses using char pointers to swap the endianness +////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values +///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. +///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. +///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. +///so instead of returning a float/double, we return integer/long long integer +SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d) +{ + unsigned int a = 0; + unsigned char *dst = (unsigned char *)&a; + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + return a; +} + +// unswap using char pointers +SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) +{ + float d = 0.0f; + unsigned char *src = (unsigned char *)&a; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[3]; + dst[1] = src[2]; + dst[2] = src[1]; + dst[3] = src[0]; + + return d; +} + + +// swap using char pointers +SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char* dst) +{ + unsigned char *src = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + +} + +// unswap using char pointers +SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) +{ + double d = 0.0; + unsigned char *dst = (unsigned char *)&d; + + dst[0] = src[7]; + dst[1] = src[6]; + dst[2] = src[5]; + dst[3] = src[4]; + dst[4] = src[3]; + dst[5] = src[2]; + dst[6] = src[1]; + dst[7] = src[0]; + + return d; +} + #endif //SIMD___SCALAR_H diff --git a/extern/bullet2/src/LinearMath/btStackAlloc.h b/extern/bullet2/src/LinearMath/btStackAlloc.h index d219b453537..050d44bdfe9 100644 --- a/extern/bullet2/src/LinearMath/btStackAlloc.h +++ b/extern/bullet2/src/LinearMath/btStackAlloc.h @@ -21,6 +21,7 @@ Nov.2006 #define BT_STACK_ALLOC #include "btScalar.h" //for btAssert +#include "btAlignedAllocator.h" struct btBlock { @@ -28,7 +29,7 @@ struct btBlock unsigned char* address; }; -///StackAlloc provides some fast stack-based memory allocator (LIFO last-in first-out) +///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out) class btStackAlloc { public: @@ -39,7 +40,7 @@ public: inline void create(unsigned int size) { destroy(); - data = new unsigned char[size]; + data = (unsigned char*) btAlignedAlloc(size,16); totalsize = size; } inline void destroy() @@ -49,12 +50,20 @@ public: if(usedsize==0) { - if(!ischild) delete[] data; + if(!ischild && data) + btAlignedFree(data); + data = 0; usedsize = 0; } } + + int getAvailableMemory() const + { + return static_cast(totalsize - usedsize); + } + unsigned char* allocate(unsigned int size) { const unsigned int nus(usedsize+size); @@ -68,7 +77,7 @@ public: return(0); } - inline btBlock* beginBlock() + SIMD_FORCE_INLINE btBlock* beginBlock() { btBlock* pb = (btBlock*)allocate(sizeof(btBlock)); pb->previous = current; @@ -76,7 +85,7 @@ public: current = pb; return(pb); } - inline void endBlock(btBlock* block) + SIMD_FORCE_INLINE void endBlock(btBlock* block) { btAssert(block==current); //Raise(L"Unmatched blocks"); diff --git a/extern/bullet2/src/LinearMath/btTransform.h b/extern/bullet2/src/LinearMath/btTransform.h index 2d55fec83a4..a8cdb428100 100644 --- a/extern/bullet2/src/LinearMath/btTransform.h +++ b/extern/bullet2/src/LinearMath/btTransform.h @@ -21,7 +21,8 @@ subject to the following restrictions: #include "btMatrix3x3.h" -///btTransform supports rigid transforms (only translation and rotation, no scaling/shear) +///The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear. +///It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. class btTransform { @@ -92,13 +93,7 @@ public: m_basis.getRotation(q); return q; } - template - void setValue(const Scalar2 *m) - { - m_basis.setValue(m); - m_origin.setValue(&m[12]); - } - + void setFromOpenGLMatrix(const btScalar *m) { @@ -194,8 +189,13 @@ btTransform::operator*(const btTransform& t) const { return btTransform(m_basis * t.m_basis, (*this)(t.m_origin)); -} +} +SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2) +{ + return ( t1.getBasis() == t2.getBasis() && + t1.getOrigin() == t2.getOrigin() ); +} #endif @@ -204,3 +204,4 @@ btTransform::operator*(const btTransform& t) const + diff --git a/extern/bullet2/src/LinearMath/btTransformUtil.h b/extern/bullet2/src/LinearMath/btTransformUtil.h index bc42fd166b6..86ee1da5edf 100644 --- a/extern/bullet2/src/LinearMath/btTransformUtil.h +++ b/extern/bullet2/src/LinearMath/btTransformUtil.h @@ -25,7 +25,7 @@ subject to the following restrictions: #define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x)))) /* reciprocal square root */ -inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) +SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir) { return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(), supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(), @@ -33,7 +33,7 @@ inline btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& sup } -inline void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) +SIMD_FORCE_INLINE void btPlaneSpace1 (const btVector3& n, btVector3& p, btVector3& q) { if (btFabs(n.z()) > SIMDSQRT12) { // choose p in y-z plane @@ -70,7 +70,9 @@ public: predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5)); predictedOrn.normalize(); #else - //exponential map + //Exponential map + //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia + btVector3 axis; btScalar fAngle = angvel.length(); //limit the angular motion @@ -121,6 +123,10 @@ public: dmat.getRotation(dorn); #endif//USE_QUATERNION_DIFF + ///floating point inaccuracy can lead to w component > 1..., which breaks + + dorn.normalize(); + angle = dorn.getAngle(); axis = btVector3(dorn.x(),dorn.y(),dorn.z()); axis[3] = btScalar(0.); diff --git a/extern/bullet2/src/LinearMath/btVector3.h b/extern/bullet2/src/LinearMath/btVector3.h index 74d41ad2a19..96548c6ba60 100644 --- a/extern/bullet2/src/LinearMath/btVector3.h +++ b/extern/bullet2/src/LinearMath/btVector3.h @@ -27,6 +27,10 @@ class btVector3 : public btQuadWord { public: SIMD_FORCE_INLINE btVector3() {} + SIMD_FORCE_INLINE btVector3(const btQuadWordStorage& q) + : btQuadWord(q) + { + } SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z) @@ -43,6 +47,7 @@ public: SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v) { + m_x += v.x(); m_y += v.y(); m_z += v.z(); return *this; } @@ -399,4 +404,50 @@ public: }; + +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal) +{ + #ifdef BT_USE_DOUBLE_PRECISION + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[7]; + dest[1] = src[6]; + dest[2] = src[5]; + dest[3] = src[4]; + dest[4] = src[3]; + dest[5] = src[2]; + dest[6] = src[1]; + dest[7] = src[0]; +#else + unsigned char* dest = (unsigned char*) &destVal; + unsigned char* src = (unsigned char*) &sourceVal; + dest[0] = src[3]; + dest[1] = src[2]; + dest[2] = src[1]; + dest[3] = src[0]; +#endif //BT_USE_DOUBLE_PRECISION +} +///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec) +{ + for (int i=0;i<4;i++) + { + btSwapScalarEndian(sourceVec[i],destVec[i]); + } + +} + +///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization +SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector) +{ + + btVector3 swappedVec; + for (int i=0;i<4;i++) + { + btSwapScalarEndian(vector[i],swappedVec[i]); + } + vector = swappedVec; +} + #endif //SIMD__VECTOR3_H diff --git a/extern/bullet2/src/Makefile b/extern/bullet2/src/Makefile index 24f3ca9767d..8bbada24b31 100644 --- a/extern/bullet2/src/Makefile +++ b/extern/bullet2/src/Makefile @@ -38,7 +38,8 @@ BulletCollision/NarrowPhaseCollision \ BulletCollision/CollisionDispatch \ BulletDynamics/ConstraintSolver \ BulletDynamics/Vehicle \ -BulletDynamics/Dynamics +BulletDynamics/Dynamics \ +BulletSoftBody CCSRCS = $(wildcard \ LinearMath/*.cpp \ @@ -48,7 +49,8 @@ BulletCollision/NarrowPhaseCollision/*.cpp \ BulletCollision/CollisionDispatch/*.cpp \ BulletDynamics/ConstraintSolver/*.cpp \ BulletDynamics/Vehicle/*.cpp \ -BulletDynamics/Dynamics/*.cpp) +BulletDynamics/Dynamics/*.cpp \ +BulletSoftBody/*.cpp) CPPFLAGS += -D_LIB -I. -IBulletCollision -IBulletDynamics -ILinearMath diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 19702782b0d..77d94bc8dab 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -22,77 +22,17 @@ elif sys.platform=='darwin': cflags += ['-O2','-pipe', '-fPIC', '-funsigned-char', '-ffast-math'] linearmath_src = env.Glob("LinearMath/*.cpp") -bulletdyn_src = ["BulletDynamics/ConstraintSolver/btContactConstraint.cpp", - "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp", - "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp", - "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp", - "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp", - "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp", - "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp", - "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp", - "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp", - "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp", - "BulletDynamics/Dynamics/btRigidBody.cpp", - "BulletDynamics/Vehicle/btRaycastVehicle.cpp", - "BulletDynamics/Dynamics/Bullet-C-API.cpp", - "BulletDynamics/Vehicle/btWheelInfo.cpp"] -collision_src = ["BulletCollision/BroadphaseCollision/btAxisSweep3.cpp", - "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp", - "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp", - "BulletCollision/BroadphaseCollision/btDispatcher.cpp", - "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp", - "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp", - "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp", - "BulletCollision/CollisionDispatch/btCollisionObject.cpp", - "BulletCollision/CollisionDispatch/btCollisionWorld.cpp", - "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp", - "BulletCollision/CollisionDispatch/btManifoldResult.cpp", - "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp", - "BulletCollision/CollisionDispatch/btUnionFind.cpp", - "BulletCollision/CollisionShapes/btBoxShape.cpp", - "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCollisionShape.cpp", - "BulletCollision/CollisionShapes/btCompoundShape.cpp", - "BulletCollision/CollisionShapes/btConcaveShape.cpp", - "BulletCollision/CollisionShapes/btConeShape.cpp", - "BulletCollision/CollisionShapes/btConvexHullShape.cpp", - "BulletCollision/CollisionShapes/btConvexShape.cpp", - "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btCylinderShape.cpp", - "BulletCollision/CollisionShapes/btEmptyShape.cpp", - "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp", - "BulletCollision/CollisionShapes/btMultiSphereShape.cpp", - "BulletCollision/CollisionShapes/btOptimizedBvh.cpp", - "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp", - "BulletCollision/CollisionShapes/btTetrahedronShape.cpp", - "BulletCollision/CollisionShapes/btSphereShape.cpp", - "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp", - "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp", - "BulletCollision/CollisionShapes/btTriangleCallback.cpp", - "BulletCollision/CollisionShapes/btTriangleBuffer.cpp", - "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp", - "BulletCollision/CollisionShapes/btTriangleMesh.cpp", - "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp", - "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp", - "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpa.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp", - "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp", - "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp", - "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp", - "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp", - "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"] -incs = '. BulletCollision BulletDynamics LinearMath' +bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") + +collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") +collision_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") + +softbody_src = env.Glob("BulletSoftBody/*.cpp") + +incs = '. BulletCollision BulletDynamics LinearMath BulletSoftBody' env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[19, 169], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2collision', sources=collision_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[18,168], compileflags=cflags ) diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h index 8417ccc671f..4b14f6d00f3 100644 --- a/extern/bullet2/src/btBulletCollisionCommon.h +++ b/extern/bullet2/src/btBulletCollisionCommon.h @@ -32,23 +32,28 @@ subject to the following restrictions: #include "BulletCollision/CollisionShapes/btConvexHullShape.h" #include "BulletCollision/CollisionShapes/btTriangleMesh.h" #include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h" +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "BulletCollision/CollisionShapes/btTetrahedronShape.h" #include "BulletCollision/CollisionShapes/btEmptyShape.h" -#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" #include "BulletCollision/CollisionShapes/btMultiSphereShape.h" +#include "BulletCollision/CollisionShapes/btUniformScalingShape.h" ///Narrowphase Collision Detector #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" + +//btSphereBoxCollisionAlgorithm is broken, use gjk for now +//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" ///Dispatching and generation of collision pairs (broadphase) #include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" #include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h" #include "BulletCollision/BroadphaseCollision/btAxisSweep3.h" - +#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h" +#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h" ///Math library & Utils #include "LinearMath/btQuaternion.h" diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h index 25f016cba8a..b95972cd15d 100644 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -20,6 +20,8 @@ subject to the following restrictions: #include "btBulletCollisionCommon.h" #include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h" + #include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h" #include "BulletDynamics/Dynamics/btRigidBody.h" @@ -27,9 +29,11 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btHingeConstraint.h" #include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h" #include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" - +#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" + + ///Vehicle simulation, with wheel contact simulated by raycasts #include "BulletDynamics/Vehicle/btRaycastVehicle.h" diff --git a/extern/glew/SConscript b/extern/glew/SConscript index 32b3b478113..3badbeb040e 100644 --- a/extern/glew/SConscript +++ b/extern/glew/SConscript @@ -9,4 +9,4 @@ sources = ['src/glew.c'] defs = '' incs = 'include' -env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['intern', 'player'], priority=[25, 50]) +env.BlenderLib ( 'extern_glew', sources, Split(incs), Split(defs), libtype=['blender', 'player'], priority=[50, 50]) diff --git a/extern/glew/include/GL/glew.h b/extern/glew/include/GL/glew.h index fd3fe10b938..6b88e6eb4c9 100644 --- a/extern/glew/include/GL/glew.h +++ b/extern/glew/include/GL/glew.h @@ -58,8 +58,11 @@ ** version 1.2.1 Specification. */ -/* added this here for blender, should be moved elsewhere */ +#define BLENDER_CHANGES + +#ifdef BLENDER_CHANGES #define GLEW_STATIC +#endif #ifndef __glew_h__ #define __glew_h__ @@ -1805,6 +1808,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4UIVPROC) (GLuint index, const GLuin typedef void (GLAPIENTRY * PFNGLVERTEXATTRIB4USVPROC) (GLuint index, const GLushort* v); typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); +#ifndef BLENDER_CHANGES #define glAttachShader GLEW_GET_FUN(__glewAttachShader) #define glBindAttribLocation GLEW_GET_FUN(__glewBindAttribLocation) #define glBlendEquationSeparate GLEW_GET_FUN(__glewBlendEquationSeparate) @@ -1898,6 +1902,7 @@ typedef void (GLAPIENTRY * PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint si #define glVertexAttrib4uiv GLEW_GET_FUN(__glewVertexAttrib4uiv) #define glVertexAttrib4usv GLEW_GET_FUN(__glewVertexAttrib4usv) #define glVertexAttribPointer GLEW_GET_FUN(__glewVertexAttribPointer) +#endif #define GLEW_VERSION_2_0 GLEW_GET_VAR(__GLEW_VERSION_2_0) diff --git a/extern/glew/src/glew.c b/extern/glew/src/glew.c index 593f0e58f7c..f20463630dc 100644 --- a/extern/glew/src/glew.c +++ b/extern/glew/src/glew.c @@ -1836,6 +1836,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) { GLboolean r = GL_FALSE; +#ifndef BLENDER_CHANGES r = ((glAttachShader = (PFNGLATTACHSHADERPROC)glewGetProcAddress((const GLubyte*)"glAttachShader")) == NULL) || r; r = ((glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)glewGetProcAddress((const GLubyte*)"glBindAttribLocation")) == NULL) || r; r = ((glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)glewGetProcAddress((const GLubyte*)"glBlendEquationSeparate")) == NULL) || r; @@ -1929,6 +1930,7 @@ static GLboolean _glewInit_GL_VERSION_2_0 (GLEW_CONTEXT_ARG_DEF_INIT) r = ((glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4uiv")) == NULL) || r; r = ((glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC)glewGetProcAddress((const GLubyte*)"glVertexAttrib4usv")) == NULL) || r; r = ((glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)glewGetProcAddress((const GLubyte*)"glVertexAttribPointer")) == NULL) || r; +#endif return r; } diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h index 5d425a8dc94..450fde187b5 100644 --- a/intern/SoundSystem/SoundDefines.h +++ b/intern/SoundSystem/SoundDefines.h @@ -44,7 +44,7 @@ enum /* general stuff */ #define NUM_BUFFERS 128 -#define NUM_SOURCES 16 +#define NUM_SOURCES 24 /* 24 is the limit for openal on windows, was 16 in 2.47 and previous */ /* openal related stuff */ #define AL_LOOPING 0x1007 diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp index 82ed1c8a808..c660e9aecba 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.cpp +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -294,6 +294,10 @@ SND_OpenALDevice::SND_OpenALDevice() // let openal generate its sources if (alc_error == ALC_NO_ERROR) { + int i; + + for (i=0;i" because it conflits with Window defined in winlay.h +typedef int GHOST_TEmbedderWindowID; +#endif // _WIN32 + /** * A timer task callback routine. * @param task The timer task object. diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp index 78c25997806..067c8deee32 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ b/intern/ghost/intern/GHOST_SystemCarbon.cpp @@ -402,7 +402,8 @@ GHOST_IWindow* GHOST_SystemCarbon::createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual + bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow ) { GHOST_IWindow* window = 0; diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h index 2afc8e0885a..2a1d6325784 100644 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ b/intern/ghost/intern/GHOST_SystemCarbon.h @@ -103,6 +103,7 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( @@ -113,7 +114,8 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index f5c7c08ebfe..feb0fe39040 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -169,7 +169,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual) + bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow ) { GHOST_Window* window = 0; window = new GHOST_WindowWin32 (title, left, top, width, height, state, type, stereoVisual); @@ -917,8 +917,12 @@ GHOST_TUns8* GHOST_SystemWin32::getClipboard(int flag) const char *buffer; char *temp_buff; - if ( OpenClipboard(NULL) ) { + if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) { HANDLE hData = GetClipboardData( CF_TEXT ); + if (hData == NULL) { + CloseClipboard(); + return NULL; + } buffer = (char*)GlobalLock( hData ); temp_buff = (char*) malloc(strlen(buffer)+1); diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index c26ef25e366..00f7af00162 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -109,13 +109,14 @@ public: * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ virtual GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual); + const bool stereoVisual, const GHOST_TEmbedderWindowID parentWindow = 0 ); /*************************************************************************************** ** Event management functionality diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 3003e0b8b14..047bc654559 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -96,15 +96,26 @@ GHOST_SystemX11( if (!m_display) return; #ifdef __sgi - m_delete_window_atom - = XSGIFastInternAtom(m_display, + m_delete_window_atom = XSGIFastInternAtom(m_display, "WM_DELETE_WINDOW", SGI_XA_WM_DELETE_WINDOW, False); #else - m_delete_window_atom - = XInternAtom(m_display, "WM_DELETE_WINDOW", True); + m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", False); #endif + m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False); + m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False); + m_wm_state= XInternAtom(m_display, "WM_STATE", False); + m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False); + m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False); + m_net_max_horz= XInternAtom(m_display, + "_NET_WM_STATE_MAXIMIZED_HORZ", False); + m_net_max_vert= XInternAtom(m_display, + "_NET_WM_STATE_MAXIMIZED_VERT", False); + m_net_fullscreen= XInternAtom(m_display, + "_NET_WM_STATE_FULLSCREEN", False); + m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False); + // compute the initial time timeval tv; if (gettimeofday(&tv,NULL) == -1) { @@ -191,6 +202,7 @@ getMainDisplayDimensions( * @param height The height the window. * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -203,14 +215,18 @@ createWindow( GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - bool stereoVisual + bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow ){ GHOST_WindowX11 * window = 0; if (!m_display) return 0; + + + window = new GHOST_WindowX11 ( - this,m_display,title, left, top, width, height, state, type, stereoVisual + this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual ); if (window) { @@ -472,7 +488,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) XClientMessageEvent & xcme = xe->xclient; #ifndef __sgi - if (xcme.data.l[0] == m_delete_window_atom) { + if (((Atom)xcme.data.l[0]) == m_delete_window_atom) { g_event = new GHOST_Event( getMilliSeconds(), @@ -506,12 +522,22 @@ GHOST_SystemX11::processEvent(XEvent *xe) GHOST_kEventNDOFButton, window, data); } + } + else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { + /* as ICCCM say, we need reply this event + * with a SetInputFocus, the data[1] have + * the valid timestamp (send by the window + * manager). + */ + XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]); } else { /* Unknown client message, ignore */ } break; } - + + case DestroyNotify: + ::exit(-1); // We're not interested in the following things.(yet...) case NoExpose : case GraphicsExpose : @@ -521,6 +547,24 @@ GHOST_SystemX11::processEvent(XEvent *xe) // XCrossingEvents pointer leave enter window. break; case MapNotify: + /* + * From ICCCM: + * [ Clients can select for StructureNotify on their + * top-level windows to track transition between + * Normal and Iconic states. Receipt of a MapNotify + * event will indicate a transition to the Normal + * state, and receipt of an UnmapNotify event will + * indicate a transition to the Iconic state. ] + */ + if (window->m_post_init == True) { + /* + * Now we are sure that the window is + * mapped, so only need change the state. + */ + window->setState(window->m_post_state); + window->m_post_init= False; + } + break; case UnmapNotify: break; case MappingNotify: diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 726cdfb2fff..683337b47e1 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -108,6 +108,7 @@ public: * @param state The state of the window when opened. * @param type The type of drawing context installed in this window. * @param stereoVisual Create a stereo visual for quad buffered stereo. + * @param parentWindow Parent (embedder) window * @return The new window (or 0 if creation failed). */ GHOST_IWindow* @@ -119,9 +120,10 @@ public: GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, - const bool stereoVisual + const bool stereoVisual, + const GHOST_TEmbedderWindowID parentWindow = 0 ); - + /** * @section Interface Inherited from GHOST_ISystem */ @@ -213,15 +215,27 @@ public: */ virtual void putClipboard(GHOST_TInt8 *buffer, int flag) const; + /** + * Atom used for ICCCM, WM-spec and Motif. + * We only need get this atom at the start, it's relative + * to the display not the window and are public for every + * window that need it. + */ + Atom m_wm_protocols; + Atom m_wm_take_focus; + Atom m_wm_state; + Atom m_wm_change_state; + Atom m_net_state; + Atom m_net_max_horz; + Atom m_net_max_vert; + Atom m_net_fullscreen; + Atom m_motif; + Atom m_delete_window_atom; + private : Display * m_display; - /** - * Atom used to detect window close events - */ - Atom m_delete_window_atom; - /// The vector of windows that need to be updated. std::vector m_dirty_windows; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index fef58d071a4..c30b915c019 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -437,7 +437,13 @@ GHOST_TSuccess GHOST_WindowWin32::swapBuffers() // adding a glFinish() here is to prevent Geforce in 'full scene antialias' mode // from antialising the Blender window. Officially a swapbuffers does a glFinish // itself, so this feels really like a hack... but it won't harm. (ton) - glFinish(); + // + // disabled this because it is a performance killer for the game engine, glFinish + // forces synchronization with the graphics card and calling it is strongly + // discouraged for good performance. (brecht) + // + // glFinish(); + return ::SwapBuffers(m_hDC) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index a98a59377c7..2f7aee95b82 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -54,6 +54,16 @@ typedef struct { #define MWM_HINTS_DECORATIONS (1L << 1) +/* + * A client can't change the window property, that is the + * work of the window manager. We send a ClientMessage + * event to the Root window with the property + * and the Action (WM-spec define this): + */ +#define _NET_WM_STATE_REMOVE 0 +#define _NET_WM_STATE_ADD 1 +#define _NET_WM_STATE_TOGGLE 2 + /* import bpy I = bpy.data.images['blender.png'] # the 48x48 icon @@ -138,6 +148,7 @@ GHOST_WindowX11( GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type, const bool stereoVisual ) : @@ -153,7 +164,8 @@ GHOST_WindowX11( // Set up the minimum atrributes that we require and see if // X can find us a visual matching those requirements. - + Atom atoms[2]; + int natom; int attributes[40], i = 0; @@ -205,66 +217,81 @@ GHOST_WindowX11( // create the window! - m_window = - XCreateWindow( - m_display, - RootWindow(m_display, m_visual->screen), - left, - top, - width, - height, - 0, // no border. - m_visual->depth, - InputOutput, - m_visual->visual, - CWBorderPixel|CWColormap|CWEventMask, - &xattributes - ); + ; + if (parentWindow == 0) { + m_window = + XCreateWindow( + m_display, + RootWindow(m_display, m_visual->screen), + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + } else { + + Window root_return; + int x_return,y_return; + unsigned int w_return,h_return,border_w_return,depth_return; + + XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return, + &w_return, &h_return, &border_w_return, &depth_return ); + + left = 0; + top = 0; + width = w_return; + height = h_return; + + + m_window = XCreateWindow( + m_display, + parentWindow, // reparent against embedder + left, + top, + width, + height, + 0, // no border. + m_visual->depth, + InputOutput, + m_visual->visual, + CWBorderPixel|CWColormap|CWEventMask, + &xattributes + ); + + XSelectInput(m_display , parentWindow, SubstructureNotifyMask); + + } // Are we in fullscreen mode - then include // some obscure blut code to remove decorations. - if (state == GHOST_kWindowStateFullScreen) { + /* + * One of the problem with WM_spec is that can't set a property + * to a window that isn't mapped. That is why we can't "just + * call setState" here. + * + * To fix this, we first need know that the window is really + * mapped waiting for the MapNotify event. + * + * So, m_post_init indicate that we need wait for the MapNotify + * event and then set the window state to the m_post_state. + */ + if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) { + m_post_init = True; + m_post_state = state; + } + else { + m_post_init = False; + m_post_state = GHOST_kWindowStateNormal; + } - MotifWmHints hints; - Atom atom; - - atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False); - - if (atom == None) { - GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n"); - } else { - hints.flags = MWM_HINTS_DECORATIONS; - hints.decorations = 0; /* Absolutely no decorations. */ - // other hints.decorations make no sense - // you can't select individual decorations - - XChangeProperty(m_display, m_window, - atom, atom, 32, - PropModeReplace, (unsigned char *) &hints, 4); - } - } else if (state == GHOST_kWindowStateMaximized) { - // With this, xprop should report the following just after launch - // _NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ - // After demaximization the right side is empty, though (maybe not the most correct then?) - Atom state, atomh, atomv; - - state = XInternAtom(m_display, "_NET_WM_STATE", False); - atomh = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); - atomv = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); - if (state == None ) { - GHOST_PRINT("Atom _NET_WM_STATE requested but not avaliable nor created.\n"); - } else { - XChangeProperty(m_display, m_window, - state, XA_ATOM, 32, - PropModeAppend, (unsigned char *) &atomh, 1); - XChangeProperty(m_display, m_window, - state, XA_ATOM, 32, - PropModeAppend, (unsigned char *) &atomv, 1); - } - } - // Create some hints for the window manager on how // we want this window treated. @@ -287,6 +314,25 @@ GHOST_WindowX11( free(wmclass); XFree(xclasshint); + /* The basic for a good ICCCM "work" */ + if (m_system->m_wm_protocols) { + natom= 0; + + if (m_system->m_delete_window_atom) { + atoms[natom]= m_system->m_delete_window_atom; + natom++; + } + + if (m_system->m_wm_take_focus) { + atoms[natom]= m_system->m_wm_take_focus; + natom++; + } + + if (natom) { + /* printf("Register atoms: %d\n", natom); */ + XSetWMProtocols(m_display, m_window, atoms, natom); + } + } // Set the window icon XWMHints *xwmhints = XAllocWMHints(); @@ -608,28 +654,298 @@ clientToScreen( outY = ay; } +void GHOST_WindowX11::icccmSetState(int state) +{ + XEvent xev; - GHOST_TWindowState -GHOST_WindowX11:: -getState( -) const { - //FIXME - return GHOST_kWindowStateNormal; + if (state != IconicState) + return; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.display = m_display; + xev.xclient.window = m_window; + xev.xclient.format = 32; + xev.xclient.message_type = m_system->m_wm_change_state; + xev.xclient.data.l[0] = state; + XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)), + False, SubstructureNotifyMask | SubstructureRedirectMask, &xev); } - GHOST_TSuccess -GHOST_WindowX11:: -setState( - GHOST_TWindowState state -){ - //TODO +int GHOST_WindowX11::icccmGetState(void) const +{ + unsigned char *prop_ret; + unsigned long bytes_after, num_ret; + Atom type_ret; + int format_ret, st; - if (state == (int)getState()) { - return GHOST_kSuccess; - } else { - return GHOST_kFailure; + prop_ret = NULL; + st = XGetWindowProperty(m_display, m_window, m_system->m_wm_state, 0, + 0x7fffffff, False, m_system->m_wm_state, &type_ret, + &format_ret, &num_ret, &bytes_after, &prop_ret); + + if ((st == Success) && (prop_ret) && (num_ret == 2)) + st = prop_ret[0]; + else + st = NormalState; + + if (prop_ret) + XFree(prop_ret); + return (st); +} + +void GHOST_WindowX11::netwmMaximized(bool set) +{ + XEvent xev; + + xev.xclient.type= ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.window = m_window; + xev.xclient.message_type = m_system->m_net_state; + xev.xclient.format = 32; + + if (set == True) + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + else + xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE; + + xev.xclient.data.l[1] = m_system->m_net_max_horz; + xev.xclient.data.l[2] = m_system->m_net_max_vert; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)), + False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +bool GHOST_WindowX11::netwmIsMaximized(void) const +{ + unsigned char *prop_ret; + unsigned long bytes_after, num_ret, i; + Atom type_ret; + bool st; + int format_ret, count; + + prop_ret = NULL; + st = False; + i = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0, + 0x7fffffff, False, XA_ATOM, &type_ret, &format_ret, + &num_ret, &bytes_after, &prop_ret); + if ((i == Success) && (prop_ret) && (format_ret == 32)) { + count = 0; + for (i = 0; i < num_ret; i++) { + if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_horz) + count++; + if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_vert) + count++; + if (count == 2) { + st = True; + break; + } + } } + if (prop_ret) + XFree(prop_ret); + return (st); +} + +void GHOST_WindowX11::netwmFullScreen(bool set) +{ + XEvent xev; + + xev.xclient.type = ClientMessage; + xev.xclient.serial = 0; + xev.xclient.send_event = True; + xev.xclient.window = m_window; + xev.xclient.message_type = m_system->m_net_state; + xev.xclient.format = 32; + + if (set == True) + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; + else + xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE; + + xev.xclient.data.l[1] = m_system->m_net_fullscreen; + xev.xclient.data.l[2] = 0; + xev.xclient.data.l[3] = 0; + xev.xclient.data.l[4] = 0; + XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)), + False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + +bool GHOST_WindowX11::netwmIsFullScreen(void) const +{ + unsigned char *prop_ret; + unsigned long bytes_after, num_ret, i; + Atom type_ret; + bool st; + int format_ret; + + prop_ret = NULL; + st = False; + i = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0, + 0x7fffffff, False, XA_ATOM, &type_ret, &format_ret, + &num_ret, &bytes_after, &prop_ret); + if ((i == Success) && (prop_ret) && (format_ret == 32)) { + for (i = 0; i < num_ret; i++) { + if (((unsigned long *)prop_ret)[i] == m_system->m_net_fullscreen) { + st = True; + break; + } + } + } + + if (prop_ret) + XFree(prop_ret); + return (st); +} + +void GHOST_WindowX11::motifFullScreen(bool set) +{ + MotifWmHints hints; + + hints.flags = MWM_HINTS_DECORATIONS; + if (set == True) + hints.decorations = 0; + else + hints.decorations = 1; + + XChangeProperty(m_display, m_window, m_system->m_motif, + m_system->m_motif, 32, PropModeReplace, + (unsigned char *)&hints, 4); +} + +bool GHOST_WindowX11::motifIsFullScreen(void) const +{ + unsigned char *prop_ret; + unsigned long bytes_after, num_ret; + MotifWmHints *hints; + Atom type_ret; + bool state; + int format_ret, st; + + prop_ret = NULL; + state = False; + st = XGetWindowProperty(m_display, m_window, m_system->m_motif, 0, + 0x7fffffff, False, m_system->m_motif, + &type_ret, &format_ret, &num_ret, + &bytes_after, &prop_ret); + if ((st == Success) && (prop_ret)) { + hints = (MotifWmHints *)prop_ret; + if (hints->flags & MWM_HINTS_DECORATIONS) { + if (!hints->decorations) + state = True; + } + } + + if (prop_ret) + XFree(prop_ret); + return (state); +} + +GHOST_TWindowState GHOST_WindowX11::getState() const +{ + GHOST_TWindowState state_ret; + int state; + + state_ret = GHOST_kWindowStateNormal; + state = icccmGetState(); + /* + * In the Iconic and Withdrawn state, the window is + * unmaped, so only need return a Minimized state. + */ + if ((state == IconicState) || (state == WithdrawnState)) + state_ret = GHOST_kWindowStateMinimized; + else if (netwmIsMaximized() == True) + state_ret = GHOST_kWindowStateMaximized; + else if (netwmIsFullScreen() == True) + state_ret = GHOST_kWindowStateFullScreen; + else if (motifIsFullScreen() == True) + state_ret = GHOST_kWindowStateFullScreen; + return (state_ret); +} + +GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state) +{ + GHOST_TWindowState cur_state; + bool is_max, is_full, is_motif_full; + + cur_state = getState(); + if (state == (int)cur_state) + return GHOST_kSuccess; + + if (cur_state != GHOST_kWindowStateMinimized) { + /* + * The window don't have this property's + * if it's not mapped. + */ + is_max = netwmIsMaximized(); + is_full = netwmIsFullScreen(); + } + else { + is_max = False; + is_full = False; + } + + is_motif_full = motifIsFullScreen(); + + if (state == GHOST_kWindowStateNormal) { + if (is_max == True) + netwmMaximized(False); + if (is_full == True) + netwmFullScreen(False); + if (is_motif_full == True) + motifFullScreen(False); + icccmSetState(NormalState); + return (GHOST_kSuccess); + } + + if (state == GHOST_kWindowStateFullScreen) { + /* + * We can't change to full screen if the window + * isn't mapped. + */ + if (cur_state == GHOST_kWindowStateMinimized) + return (GHOST_kFailure); + + if (is_max == True) + netwmMaximized(False); + if (is_full == False) + netwmFullScreen(True); + if (is_motif_full == False) + motifFullScreen(True); + return (GHOST_kSuccess); + } + + if (state == GHOST_kWindowStateMaximized) { + /* + * We can't change to Maximized if the window + * isn't mapped. + */ + if (cur_state == GHOST_kWindowStateMinimized) + return (GHOST_kFailure); + + if (is_full == True) + netwmFullScreen(False); + if (is_motif_full == True) + motifFullScreen(False); + if (is_max == False) + netwmMaximized(True); + return (GHOST_kSuccess); + } + + if (state == GHOST_kWindowStateMinimized) { + /* + * The window manager need save the current state of + * the window (maximized, full screen, etc). + */ + icccmSetState(IconicState); + return (GHOST_kSuccess); + } + + return (GHOST_kFailure); } #include @@ -664,9 +980,9 @@ setOrder( xev.xclient.message_type = atom; xev.xclient.format = 32; - xev.xclient.data.l[0] = 0; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = CurrentTime; + xev.xclient.data.l[2] = m_window; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 1203dbde80d..1d73faaf3f6 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -64,6 +64,7 @@ public: * @param width The width the window. * @param height The height the window. * @param state The state the window is initially opened with. + * @param parentWindow Parent (embedder) window * @param type The type of drawing context installed in this window. * @param stereoVisual Stereo visual for quad buffered stereo. */ @@ -76,6 +77,7 @@ public: GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, const bool stereoVisual = false ); @@ -210,6 +212,15 @@ public: const GHOST_TabletData* GetTabletData() { return &m_xtablet.CommonData; } + + /* + * Need this in case that we want start the window + * in FullScreen or Maximized state. + * Check GHOST_WindowX11.cpp + */ + bool m_post_init; + GHOST_TWindowState m_post_state; + protected: /** * Tries to install a rendering context in this window. @@ -325,6 +336,18 @@ private : /* Tablet devices */ XTablet m_xtablet; + + void icccmSetState(int state); + int icccmGetState() const; + + void netwmMaximized(bool set); + bool netwmIsMaximized() const; + + void netwmFullScreen(bool set); + bool netwmIsFullScreen() const; + + void motifFullScreen(bool set); + bool motifIsFullScreen() const; }; diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index d004e7952cc..1d4c753802b 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -58,8 +58,8 @@ #ifndef MEM_MALLOCN_H #define MEM_MALLOCN_H -/* Needed for FILE* */ -#include "stdio.h" +#include "stdio.h" /* needed for FILE* */ +#include "BLO_sys_types.h" /* needed for uintptr_t */ #ifdef __cplusplus extern "C" { @@ -123,6 +123,12 @@ extern "C" { /** Attempt to enforce OSX (or other OS's) to have malloc and stack nonzero */ void MEM_set_memory_debug(void); + /* Memory usage stats + * - MEM_get_memory_in_use is all memory + * - MEM_get_mapped_memory_in_use is a subset of all memory */ + uintptr_t MEM_get_memory_in_use(void); + uintptr_t MEM_get_mapped_memory_in_use(void); + int MEM_get_memory_blocks_in_use(void); #ifdef __cplusplus } diff --git a/intern/guardedalloc/intern/mallocn.c b/intern/guardedalloc/intern/mallocn.c index a36549d0cc7..7bdca7339fc 100644 --- a/intern/guardedalloc/intern/mallocn.c +++ b/intern/guardedalloc/intern/mallocn.c @@ -49,8 +49,6 @@ #include "MEM_guardedalloc.h" -#include "BLO_sys_types.h" // needed for intptr_t - /* --------------------------------------------------------------------- */ /* Data definition */ /* --------------------------------------------------------------------- */ @@ -113,8 +111,8 @@ static const char *check_memlist(MemHead *memh); /* --------------------------------------------------------------------- */ -volatile int totblock= 0; -volatile uintptr_t mem_in_use= 0, mmap_in_use= 0; +static volatile int totblock= 0; +static volatile uintptr_t mem_in_use= 0, mmap_in_use= 0; static volatile struct localListBase _membase; static volatile struct localListBase *membase = &_membase; @@ -698,4 +696,19 @@ static const char *check_memlist(MemHead *memh) return(name); } +uintptr_t MEM_get_memory_in_use(void) +{ + return mem_in_use; +} + +uintptr_t MEM_get_mapped_memory_in_use(void) +{ + return mmap_in_use; +} + +int MEM_get_memory_blocks_in_use(void) +{ + return totblock; +} + /* eof */ diff --git a/intern/iksolver/CMakeLists.txt b/intern/iksolver/CMakeLists.txt index da69f2a3332..736a2a78bb2 100644 --- a/intern/iksolver/CMakeLists.txt +++ b/intern/iksolver/CMakeLists.txt @@ -28,5 +28,5 @@ SET(INC intern ../moto/include ../memutil) FILE(GLOB SRC intern/*.cpp) -BLENDERLIB_NOLIST(blender_IK "${SRC}" "${INC}") +BLENDERLIB(bf_IK "${SRC}" "${INC}") #, libtype=['blender'], priority = [10] ) diff --git a/intern/iksolver/SConscript b/intern/iksolver/SConscript index 81bf61dfcd8..543ee46487c 100644 --- a/intern/iksolver/SConscript +++ b/intern/iksolver/SConscript @@ -5,4 +5,5 @@ sources = env.Glob('intern/*.cpp') incs = 'intern ../moto/include ../memutil' -env.BlenderLib ('blender_IK', sources, Split(incs), [], libtype='blender', priority=10 ) +env.BlenderLib ('bf_IK', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] ) + diff --git a/intern/memutil/MEM_Allocator.h b/intern/memutil/MEM_Allocator.h index d5ae94cc6b8..b2c3c5e82e2 100644 --- a/intern/memutil/MEM_Allocator.h +++ b/intern/memutil/MEM_Allocator.h @@ -25,6 +25,7 @@ #define __MEM_Allocator_h_included__ 1 #include "guardedalloc/MEM_guardedalloc.h" +#include "guardedalloc/BLO_sys_types.h" #ifdef _MSC_VER #if _MSC_VER < 1300 // 1200 == VC++ 6.0 according to boost diff --git a/intern/memutil/MEM_CacheLimiter.h b/intern/memutil/MEM_CacheLimiter.h index cada06ae523..43149efc977 100644 --- a/intern/memutil/MEM_CacheLimiter.h +++ b/intern/memutil/MEM_CacheLimiter.h @@ -61,11 +61,8 @@ class MEM_CacheLimiter; #ifndef __MEM_cache_limiter_c_api_h_included__ extern "C" { - extern void MEM_CacheLimiter_set_maximum(int m); - extern int MEM_CacheLimiter_get_maximum(); - // this is rather _ugly_! - extern int mem_in_use; - extern int mmap_in_use; + extern void MEM_CacheLimiter_set_maximum(intptr_t m); + extern intptr_t MEM_CacheLimiter_get_maximum(); }; #endif @@ -141,7 +138,10 @@ public: delete handle; } void enforce_limits() { - int max = MEM_CacheLimiter_get_maximum(); + intptr_t max = MEM_CacheLimiter_get_maximum(); + intptr_t mem_in_use= MEM_get_memory_in_use(); + intptr_t mmap_in_use= MEM_get_mapped_memory_in_use(); + if (max == 0) { return; } diff --git a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp index 4cf0ef305d4..d998c9a3e80 100644 --- a/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp +++ b/intern/memutil/intern/MEM_CacheLimiterC-Api.cpp @@ -27,18 +27,18 @@ #include "MEM_CacheLimiter.h" #include "MEM_CacheLimiterC-Api.h" -static int & get_max() +static intptr_t & get_max() { - static int m = 32*1024*1024; + static intptr_t m = 32*1024*1024; return m; } -void MEM_CacheLimiter_set_maximum(int m) +void MEM_CacheLimiter_set_maximum(intptr_t m) { get_max() = m; } -int MEM_CacheLimiter_get_maximum() +intptr_t MEM_CacheLimiter_get_maximum() { return get_max(); } diff --git a/intern/moto/include/GEN_Map.h b/intern/moto/include/GEN_Map.h index 9f56924419e..d85e9af175b 100644 --- a/intern/moto/include/GEN_Map.h +++ b/intern/moto/include/GEN_Map.h @@ -50,6 +50,19 @@ public: m_buckets[i] = 0; } } + + GEN_Map(const GEN_Map& map) + { + m_num_buckets = map.m_num_buckets; + m_buckets = new Entry *[m_num_buckets]; + + for (int i = 0; i < m_num_buckets; ++i) { + m_buckets[i] = 0; + + for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) + insert(entry->m_key, entry->m_value); + } + } int size() { int count=0; diff --git a/intern/moto/include/MT_Matrix4x4.h b/intern/moto/include/MT_Matrix4x4.h index 823541347b7..b4ee84a718b 100644 --- a/intern/moto/include/MT_Matrix4x4.h +++ b/intern/moto/include/MT_Matrix4x4.h @@ -212,6 +212,7 @@ public: MT_Matrix4x4 transposed() const; void transpose(); + MT_Matrix4x4 inverse() const; void invert(); protected: diff --git a/intern/moto/include/MT_Matrix4x4.inl b/intern/moto/include/MT_Matrix4x4.inl index a2aa893a6b3..074bd6e4b05 100644 --- a/intern/moto/include/MT_Matrix4x4.inl +++ b/intern/moto/include/MT_Matrix4x4.inl @@ -52,14 +52,14 @@ GEN_INLINE void MT_Matrix4x4::invert() { } } -/* We do things slightly different here, because the invert() modifies - * the buffer itself. This makes it impossible to make this op right - * away. Like other, still missing facilities, I will repair this - * later. */ -/* GEN_INLINE T_Matrix4x4 MT_Matrix4x4::inverse() const */ -/* { */ -/* } */ +GEN_INLINE MT_Matrix4x4 MT_Matrix4x4::inverse() const +{ + MT_Matrix4x4 invmat = *this; + invmat.invert(); + + return invmat; +} GEN_INLINE MT_Matrix4x4& MT_Matrix4x4::operator*=(const MT_Matrix4x4& m) { diff --git a/intern/opennl/superlu/BLO_sys_types.h b/intern/opennl/superlu/BLO_sys_types.h index 5ed3117c890..411a8582f96 100644 --- a/intern/opennl/superlu/BLO_sys_types.h +++ b/intern/opennl/superlu/BLO_sys_types.h @@ -54,6 +54,7 @@ extern "C" { /* The __intXX are built-in types of the visual complier! So we don't * need to include anything else here. */ + typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; @@ -102,6 +103,7 @@ typedef unsigned long uintptr_t; #endif /* ifdef platform for types */ + #ifdef _WIN32 #ifndef htonl #define htonl(x) correctByteOrder(x) diff --git a/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj b/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj index 97f70a26db4..01a29d2d24e 100644 --- a/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj +++ b/projectfiles_vc7/blender/BPY_python/BPY_python.vcproj @@ -21,7 +21,7 @@ + + @@ -723,6 +726,9 @@ + + diff --git a/projectfiles_vc7/blender/gpu/BL_gpu.vcproj b/projectfiles_vc7/blender/gpu/BL_gpu.vcproj new file mode 100644 index 00000000000..a780bfc9e0c --- /dev/null +++ b/projectfiles_vc7/blender/gpu/BL_gpu.vcproj @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projectfiles_vc7/blender/nodes/nodes.vcproj b/projectfiles_vc7/blender/nodes/nodes.vcproj index 3e19417de9f..e08a2e04f98 100644 --- a/projectfiles_vc7/blender/nodes/nodes.vcproj +++ b/projectfiles_vc7/blender/nodes/nodes.vcproj @@ -19,7 +19,7 @@ + + @@ -746,6 +749,9 @@ + + diff --git a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj index edf0faf4ab7..faa7f184197 100644 --- a/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj +++ b/projectfiles_vc7/gameengine/blenderhook/KX_blenderhook.vcproj @@ -21,7 +21,7 @@ + + @@ -621,6 +624,9 @@ + + diff --git a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj index 76fde7612e3..19394024d5f 100644 --- a/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj +++ b/projectfiles_vc7/gameengine/physics/PHY_Physics/PHY_Bullet/PHY_Bullet.vcproj @@ -19,7 +19,7 @@ eh9TI)opD9K@>k)QzpfcaitS`7f;z(WXtf&~8RjUTiAcjm4pCka%I zk^KQrkjy^FNdqtcUU}^$N#GS!7kOQG06@q8_l5u&Sw!GPDTXux(4Sv;Xlf` z7|BD^Uvd=cf8(V!7~p+UQCFKZ7($eRNF-QlS+%`4HU2A^-c<|9{2^ zP6+71PZbMuWZZA6QY@4*vP5tlWRJP#;k;zx-~ixw$#xvZA6QNZLrr zpQ&Xs)?_Y@_+?*^7Ihi5HXpx0ypZG}zS?*>@vxxe$#=p{7zmQF%;tAB8>upEweZ}l zZS_1Jvc+XhtpA(+rD5K4@D(8;98je8XRQq1RZl2e(Br?Uai@j4-d8d)OFupAM+e8U zg>YZL);@d=QG>gUc*o-bEXa-G=Ug~~M|1Irvlu>F|SC}=8{UUhjq#`bi3)6?lyVDJXT{|XMH)l)M68v-H}l9-~yA`o+Jme;KU?Y);y3*@7w zrl#lOQrFtkbFi|qQbM=aA60XHp+8+ZvcYGe5rqpfBS04@R8!VGoT-?#xzGJZzNZ4I z!TWJsU-l|^snPy*s*@pB?)7tNM_KnnM3g1#@}|>!Dz&m?W)>D{Q&Z~e)3vyTdg~?) zI@l~!URE}YNOJ8-2krM{?x+%=-TP48&1 zQ&cAfaw6diXP_EL@hy~cJ^XU6GaTXAq>m#x$Q5Z1?LYRr9!#ZxcJQ8+@O~nWKi)_8 z2q#4AN9RSnEBJc_ff}j0KSe(~W#!{pD-g0`ZXtPU+K347FJ3OF({rzMZY~Z|Wi2p0gs}x< zcobmswdSfiIw)lti<=ip^!0y9Yin!C047>mT44c!7H%G%tA=_>qA-YJrrp=IoX5+H z3mkItW3>W2eEj15k5|y$Qf9U^sZXD{(*-@4_^d|0`JIsSyTEq;)cA;GrLJZ5 zKsHp5RsT~l?LR8P{TPIecJ8JGyR%zUGVZv%oHyUXJH}8PSzD z^|~YE)$3JzJ0D);KfEOv-1QX?=N+S;i;CX71F+%GYFjH1Tmq+x72T|N{Og|aBdfU4 zYzieRpzm35&hG3&zTu%=v5b#r=F`#RcOIplAHL%y$?>x-UP!;uVoG_beag+vHU4va ztZ3V)H~X9}5rP!3Jo2j}ugqu2%i_uS=O@(cfXAbD$cZ<^ZlF_5JM>i?TUpEbW0iKW ziiw&XjVIgkfdZXkZl2zq(uMTBX_iPvj%Cm!}roILXR8|lQHm0qKur>@_R9THw( zpVebPP`t-%Yeu>IW_LDumi>bS{-%?X-r&f;VJE_1WMmX?*+BbA)z)QQ>2%h2AX?jq ze^@Wz)bP%1u1bJ!iP-i_b9Pn8RlBplzpxxiE#?mQPJp9h`qt&0BGV=K_=A8XEDGUU z=TyrWPmhT4t@E~|#6+XT2HPp4@aPsBNauxCs16m5kGlV6|GBggOI*J-Dq`x{C|R8K zcI~gcopg^?Nyy#iyiw0`aym;Sd5LPiN~wn+IXs|OnHq4j;$@HW5`r!2U08M%@OOW* z-tooS+PZ{KjDz63 zZ~c6uX60UXSGUKVPBR;&yOv?M`|vYt`$cH!Z){c3ueZJH)igne-^Avi3;=yb-?~Id zhScEt52uyLO8q8D`lJ~$HYVY$kMvRw4i1=iOKTsMl(Yn=I5?sg%U6+ z;`_=tfB*UP(XhPpdx%|hbL*!+pT|T4CsJ1Www{oiKThz{nf;mF0aT=(dEa$|ImpdH zK|JD~5Q&9sGchrL27HW}uB}5~f1|-Wt#UNW`2XnJ{Q5{qK%xp~k{1JptRn9CpatiA z-++{)DpAHc6AT>MwtfnsckcIXAJf-}><4jQW`aV`P6007P5nT&nVheh>V^g)LGF}<=7hF!x zDV>Jz!^N~PNB>tJVP{dPhZX+IRvXy?2CS)U5YWnI>=y2qA3-Q;mz?@kuUXU)@W7kN z5@`PGX-)UtD&10IrgynDUqu~G!w0?c(fg)^!0fd$0qm2N#qYng4@W2ViAozWG-fc8 zN&2p|bd|R|+f$rhUak)3@->)V>L_SMM99_32!7;s3YtF|`1%TB_y(vG08Tw&n2c{( zL!tdrI)}53122r5o*`LU$B?P4flwcYOl0!yU(5TBci4G?i!pm-k52XFL* z`zdGgR#GuAFg)Dt<>p>LoOZ4y)k}0q99@43cz5AXwuV(aeturXdP#H+e$%z#WxQCfc%zgUw=g%LumczM# zA6WEBsK?zsrkt6iG(p;ecxrKnomK~C<~h-R1i+$()N_ea&S$0SaM{9Oh3}u$$|@`u zTF{o*#qs-|R5f)&|NBotLu*h~R}(y9($Lgn`R%mQD&_RFrg=yS+~1rA%^loahsDLc z^AGUPpR_T{lz(=@Mkc7pLhPEd$B8yw->V9?eXtjYQhIih#1*XYu~U2C!(O7&UU3je z;IRd3m4|kjK$S|QoSfK1AJ2MxDQ_<7d{nAhq*hP#X0Go(WC=S*CT`eeR?;zWaV5QZ z^Jacv&2bzdcboyEXIc|&-HruTte9Cv|K`o#l{TNtfkL^s`&bH*`=Xe~N~AZ^G`QLt z8gJ&CoQ>yTFqk?R>CC0dvs~&qrb2QalNiLDZ=N@M#VA$nc`60^enCG+aHz=^PL^sH zejFvi%=o>@xw|Lgr>=(>o;=ksmValIdsVH%cnhrW?ai5mBbJ6$yi~sU&K2;atyFo8 z&*(t^<*+J0A0FTXZ0%pc&ilKm5*6oWR2_hFm31y`!ap-jYxE^1CX(2%$=-X0qQ}U> zhjf|DMLc@gW{E7}J(!vifgpq1nJW;|5pdsa!Y*FT2g{q=T5|3PJ{GVh@zv8K@%?lP zNgDi8u3i0^W0H~et>dh4W48VrOHHNW`aHY|=VuQ6C)2n8xnNi?zdVS38Msabz~pQ zx{jZkqP+aq+Sb?Vdqx#e$Di%Lz%tEcgNIXt0!}m2)8GGaT$0VW?PyE}yav|7ZdUzH zAJvsbcpQ5pUm1>P3-NuVNjS^#zj#lB7XhndA?9;hzPr2JyZJLyK6jF4+GYAhaOY>UElA$Hh99nOIXw}xP8u2y z&okSJNh>8;gO--vBv`@rJY4dQCeNPvSHLBK=jg4f)zqrPwsZZnVY+3FxlHG-sg9(} zpWk%zO!kI1b>dV|aVl{c8N|LA(i^Iw2>I`7Y#?@rAYp#)viY)_7v4p(T*Rjn2AQog zjB0V;6Fm6XJUy-PZPY4DGyn;%qt|h%#oc5$mE)0G^B!LqEyjn|K{&U=Wy4h&fTmG`k-$YT@(6LVpB3%&Dce3Rfl$&ylt<@>)z zLl_JJ;NRfX)z?3D+#i%<1MAae>LI?@M=dYT`M^Bkv(Mk9(O4Eg?P7$)Z1g5KctR`* zm(y9EBI7Nkc9k#?2wDz)*i{LXApmpjeqIL6F8PGDj44BK0J-7x?r90bdd}M8b*8f^ zJCR9IOr9-CSy@>OYhus$;^Nt?nhIjG2<*SU@N9-{C>`PezGBbt61x5m2S{AMl$jX~ zMZjOxs{j7m0IH{_r=P&K<&&(eY$>brK?VGJqP_b@cPPK-5z&9;<*Jo4l7(9OgT|OK zdLed-JPn@Y9b7)I$;n4|c6MfTUal13KY8L(9U469S(?%YEX@}(mlG^%-NFNu?=qyddl5PhX@7gaVL*FxZz%`NE@NmHkRQH>E4|zew0cY2#K7m6fIDq|XUITgU zXUOV9yUKMER^*OXb;d{fXd(_c0EdFHtD5+@_M#{A_9%KaLB>Ih6$|sp`NkoZG(gLJ zw9+}2Lj0G0+_^dhUZj6>)25pLgGUY9duTU2S(gn0~9FG2M(J1P6_I z1l#5Fyy0>!iti;Q?&D+Lg!Xe)^|9$(I?XPog;Qw;1`^|D0_4K`HuVuF;3#S*B_$1W zadLWtqsWe!UM3iU2fO4yXE6_?L&ncJA9O zhY2_T>xU6@@7{Z9>VA9NK!Q1Kp(dzeg&jmM*ybklt8%)shQM%Km z(+(DCF6mHSYm=N;=+BXlkL7&uH24fk(F-YyG&gWmKyx^SFN)vI36IYET*P&cTw!d* zFjje&lVyRdnTsGQTYd1>Edre0x7vQG(h=GgO>obELDEdqOch|d+m(HZ7FXu zSs>FK_~cvvy*GU)z_2&H=@mcx2b28)1k^x*Nkmg4(Oa%lte=AKpOvONQ-6}NwJ5KF zl)wquB5!?LLnqTl(47<1Lj=Rg8}FnQkKJjR|9q_i?x*Df-<-3xg~hy9scB+TQl?
za#;S4BZT|k%M{)O!2hy^utMN}*+S$Ol<5pam+K?lCR+7Fbo##om;du}S2HS{lGcX` zE8qEU&vY|axBbR~!a*l~&iF(rlOHC1$}&C%sHmt~&!0TuSBqk5M(D^980fS> zo?4ksib8Lh1`|F|FVt-mSm8BTQQOV{2Ltz=K6kaNhk(gOQTRZ2Ng?99xIa6y88p`) zCPBJxcG17&?Y6V_X{LMSQ}K`kmd|p4io>&-%%2E`oUaS5Ue!mG6MYypEQDUhJ`IXB zUk{cAlPRekqdc~JOr@h=4x+@f5|@Hwe)B#t*A@%l%4os z?z@vYYH-^lrGMvfEO-Q!mwq++p7?L>OCox6;cpS@^`u}ZUEwpm6IIo9w zP+-$!e^AlTGU(EV#k?*L1A%0l4$T^SQ=Qzv>G};-GfQb^Q=1zX(cCX;f+>->w9z1s zSD2g09_Do5%wPWg3*fzczwmnD)AxULw(H(lgW@NE_NMn=|pk-=;Phx zDRmGa|KUSawpdWdu+~`LT-zzNJzx@q@(VnqENuf(n<%oN**d4CwdfcO89aDs)Yq@; zi;edEV5{#A;$MS0Ctpz@fqNE7H)~96b#34rtKn-d?D7@?T+(LZ;~#EYAvf+Jf-LSs zf+rJf6&@dv-`*@{5%=vlw-2!To090E->tO^J?K{WZ&^AmEWe(23KW$EY*qxnIkUd_ zx?1f`W%u;7!{wyorSrO~`9X$jf5&UloW>c8CGeh>1+Ixc>tqgmMLFFJdUtYs!kd0g zD$~+nn+!ipIl7K&<4OS?8TptPAFp!R{^bioRYyKPv#n6226r-+kbvUJ{?TAi*Jnf` z0k=0dht-`wX(OFvw;EX(8Eq0X*D#w%veW>11%=3u3JQx!$;rv~UPs`en=R>%@@!DI zvSI4x&23Ur_bYfm&-EtE(^B5ALRy(u#}T<+`hp__eaS0mxA##olCOQ1SrPL@pw7TA zeX*q`sz7w4n%@7i$dK7*eJPeP>Plb{=f6{{0RCWVpbGfv*8j7%WrCK5#_YH$7wMTKQH2U z&7Trpscew!Y6iL2K(W{D`LbD4b?bAX_?{*qwjF19ndEfBkz`6@NCt(jY0cl`XKi+z zO6gDUXz!HV{x;m~NnY{K7hH0K*;Dt3#g_t9<&6K73mAXW zys%3KTKu^=ISFjg?)Zu|rW2;#V8i}FOTG0t1u-=OfeiJ#ci3`q6doT^7aT;LuK;d2 z;V5agv{MW;G~dOT(?#L243G#h0ui><4H9q7WAx znDF5qgW|xEIPd{Ds@3`{GJ7e`w?hu8c`eQfy#iKihJ=6rQrK{Q`s;**PO61&|K2=x z7XFtM5DT$!)Xd58*ck?yY)-%7e}Prk(9kdszIFWQs90H9d6}6%>_!XweaOxzfX%dX zxplKYY;;}~DqKRRqI>UyXl$7y8T_9=#2j!^Usy_GR;lmCeQnX6s_(e?O(%&>*R#>LyB&GD zrP|J2;@BHBjk-KyDEw2UfDP2=)80SJ_SJ1Jbj2YJ62Da$dBAe=uIP&5qIr<7v~Yld zDmmrWn-pXYNF}?ME?>FD$XA->sSq2wn)mZdWhwQ+FPq=Zl_a<3A;kNN9#UM1>?I33 z*{_R)M_rH%P0=TK8h)ptl?vXa2?7BGWRV7SQhUKUh9!vtcEo7Iv#l(yQWQ2B&*Z=q zMh+kVfDFR1goH#bTVNVCz-2u~02vq>8#}3USl}$K!XqIgiU~2;ConzaExj(s zWuRX;Io&%_*FM4`1p6re?#%lbmD*9<+mt07CDv-G?5a3kMNC#6^Y=0zBGt0pdG!~| zEc5SI!pkvh8IZhry>vndN?jn{p@;U(;u9a#9+-vTz&OK3f!h(^_O}o3;t*6ICK_A` zN9e$6Q{WHozX)fvP`S#SH9+jB0;!X?D%|ip;2hBr2MU?&nW5{6P^oP04y1rGMp*D7#d@ zxO6@>Q2s~D(99(i#Af%=;N;YC@5`5a4+m1*Uhntwv9y%RfB&$v`}iNSDfb~Z#+)!$ zJCQpVC>9?g>Xn48Rv_$XWDkstBnx~aRyh@6Ff)3_t%pxcf=|fu*KTRV^>UB*6hVt# zN)_vOWlulBTEM0hU7j^sPI1ITL7-2yjMEo^D5}EQg^BLCwSc(ExDa|uNKa3HPcG{3 zE#v9w36A)4hGCmGN6_W&=>G5T=l~TbCmu)wd`M&Cp%nbYDEjv8pBY)Yy6Db@5$OzK zcjcso>0G%4M(SL=2t;9?wGZA)OKD!=47<^06z{%{PdGYd-K}_mETvO_yMP)%QLh(% z&2QCyf>sRiCQq$Ryn#GIh93vTD)!V4pKO(eF5%eG#S^cVZMe~3vOogi(puncLX^|?OE66+bM715Nai@qY} zAUsCU(Y_U4P$O2B?a(6e<5p*i3h=fJ*-@9|Di?k6cb~Yv{LaUh`&P?|KhV&xa0I4G zh8Qvy9f?Nb(~EXl)vY#~qi;DxE<=|Vmy#0KV#^&c9sjWtcIJ6+C$mH`8K=S>L8j|_ zCl_E6-&7=Z6Zncu-8JXzQBo&$XQidkt1n7>j>j;Uv`s6y6@P2IsOr13&yy6St#y1ld0HR>AVM+6~?ku9ukXy8UyL`RvPc0(T6AqHnC ze%2KMDMr{c`fE1-ixh364d0s+MZjb*k#1nT=}1<&Zi_N&B?F3{m zgI0&j1MSRo$Ku`3)_-(&AC6}#?y~2Io2}#4M&hArCeN2=5qfKW##^!KwF;5doKg7k zaOAhE-q}iivnvlFf?rq3whynE%SOb8wE}n$4W6@)DOb;}E=~s4Bv5!j19Mqh_f*-P zR+%E0E^J-uaF158)ZkpJdJxCnH%w=I%P<)qg$fqYGn1d34`kyooc*sCKxxwn!6jj4 zYD+6i&M>O8N)D!3BZg3L+3ajLCKUHjyeclLy*)#XKlaK8?5B1>)!OC$uWf_PT43hGO`A=Ql}U8F{rJ`22Ny7KC6;V1~f=hu}{rC52&RQ8vj%` zdepDgGeT1#NU*ng(T#W_pCMHX*En!5pF=}v5Pi{>*?KuPalV?nLTNtKL_r&Jsv`sb z6+&LOXQtr&L$~<-AJ6+iZtkn1s(UL20a|DR4(BGwErgw&oi)?@dcXn04#43a2H>Eg z63-QuVRv(~^8MlF^u-RG>f8I1g%+UXmK6g|N6#COi;UuV#M=r_AnJ=!y=Nizk-WJ#z zHn#cV4pw0y?y1i#d9EIU|>)oG6^OF4|Dj< z%}ulVx;m18V9;8jV>h(o>USM3uA)VkccRm=bWzO6@3oyR;zx*!i`(pf=cbrV%ZV7+QlOzWb0>U&6u*n`a;djeKf4JA;of|2B-%3jMCR=m8}YAYc@3ZR!9=aK=tvEn zek{C1?=?+&_1$vQ(~_>_7Y>346ANd!cFM{Z6-Ja};$0ENGL8WB^3Bi0F&BxeJpb(+XD$Mu8V6T zH8C?{AcOJKN@bq_M2xB9X!Sw^wzaKoFJfQ^^o%5mTurM_GHX@roAYKyNYh9d7?1_t z?YstY!*#3A^>S~V;pzU03lzu%IH{>OlsW^S4zyvrZ@4((q8Fyiy(nMQ8I-FYv&T0x{+wi)JB2yut_fL(d_`i%fN=uV zy38S7lU}g1Dy8F(HVL+*5hzN?MiT`Or@dRFb1mccJe;kp1F6Jcbu7$L z(b3yFsi8*I{o`UU(fj-R^I*X>!(46e#MXh0Rhgo_vKJfdxudu~sp7)I&Tzq8m2nkp zaEj~`h;tu1Pwr$t`(p5;|UeQKjXg^53X|%~y8lxLM+=&2!+wAvW^kVbYcY zvUJjxbcv!tgheNEVP#I*k+gQF?PZuiR_qpBtSc(C92+xPnMj@P$6XTTzy3NK0=7cCr%oJPd=?*!eOHyHnD*B;(9_kDnC zqYTyl{`z<=*eW{C7^Gck^mWeQfUgp+Anhvhii9MwXA6Dpd3-bZKshzw$WwN<1ZXpz z3G0JzMu3&%oE|so9i7*V&??)3!YFa-zMC}xlVps(SqGXV?HGu=sMv0I?hPy9+@ibbFl0DE>+9D`c=A zI%+_D3sjTvY&%8}M zsIam?J0GbfcZZnLQX6|w%TT`quQmh*g}`StP{o5%S!qL{U@I(k!tPr(1PXEt+>dwZ z8(P`O>B?;XgoUS=!KDT_V-0=$nG{=CDYI!dV4@M`+s7S6RRcjOBS56PU-rJBhM zzA+Zc5C5S5K=w(0WMW;Mt2vydIKOH^S zZJNcXr^}+;0fez*}oG}}Vc}~L8q8JD9KaTAm z%9C_g9_s}6Sn1I9mldEvuZ4dYxOc84AWnc?;u;0J39Qh1EX%e|yu~1p9i%aeLDb#< z3`n+w0bML7|q6*ByDHh_Ln8**SS?Vv&pI+6%ibg`%P{o+f7N z4{0}EP=gXb$QdUD#k4Dh1mo{+U0tO6Z0zvcwwpWWEg$%a#M1xU-9!o%X9WO!g-x`1~!A2 z@|_jF-jcTpL_9JONtB!{{_<5(3($o)dR1i!$h*gPX5-aNhW5i(9?L&?9aG+3Y5dxa z{&qg_U_E@9_njGV6JSUiw&u|sQ+Gbu1J)N3L&ab@6U|B3tEEAS?C)sDC#;t2PW*T^}>tmCCg0s>2&6_IF?j+h*6CR}S!bHe^NqX5Cd#Rl}a znf=DPp1S4v3aLG}<&-(Uvv1!51CWMKl2g0&H)AsC5NmxHu79#tx2$=ca5GsAtYdLT z@L~H?Akxr#yB)}ER<&)vq>)}utcP1XiwZ-r-(XY)#ZHCz8ppK}GFMNQS+PC^2w`|< zT$-bw*xv^RH4PlcHoPDw+!#DGYnClttd_QU^=K*wJb&0eR~;wN)!y#y>ystMK$3BC zs=AQqs2)ZWm(n2*83P1ibxPu0k7Ua(*T{Vsr#MnDnm1G^E#cz>tLZ}UJ+j#Fg)@V` zpGZ+tLmgJ5u=_#RB=TIV#O$rz0`Q>7RQ51*6sG*YbZ}12R2=W|DDfP|+CU|Lp zV7wr2d@jaFxc-cM{PX;uh22FjRst-g)1d+U#t~?N5XoEbOX_5m^-DluKyGY&GAm+> z+Nm401ikG>z1+OJr)RRtTqu3j1c5FQpf^!kEF)@HimHBom2?Tb8cgMly9*+&N)4SF zXK1S*AcaX)(iy$HWo134$BBaZ`UIeu1nh>tonfVeFYt|yY;iqz3Gl;wq&=_!dHy@A zsp4Upe3kCHiq59ExbZIxxqsorL1%|MEB7b?@P>h*ew1o#d~GdA0(1v4L`fHT(t$tU zzkg@2&3FdHgGn#o;NaoY#4ZMC85vnp17<2hMl&!4YUy3y{-X$Zqma--~KwQ4V zuF2fRr+&M&`AYa^`7z^x0P!)k6}OV6+tQ(tg!_ZbzKYY)VvHO~Jkembs4MQTVQgzQ z!mZ`rz4Muy&go@KU6Z4Ud~pwAz?i_G89|~Pz##qop?I37pdJT}is1f=7&^Nu+2BYQ zX6%9kC)0sKa7nd(Zo-+FZ=sX*->0_a-QU_v?sz$Hfks9swy!Y6#NN3i6JzLOa*cq3 zzhwFBv5HFz`dsZ2UyP^1)7G5JbI0l#Hj1=-xd~`KL6I>-!AR}BD=13fY>|wRGg>Cn zH*iCbtfSG$9(F0h;9q$kog*N~>u2s6i(hwAj;ErdGXQ~VFwwEf759y1JGLkQ0ejjT6~WBVK9t)|oBS z{&>_V=4PNBiNDPzlJo7`*Gkld7*YI8LqFz33P`FpD__k7SE}2Lo){Mra$Zz*o~lo| zR^^b-%~g{mgHq16Is1O?{Z?FQqx~Go?pQV{*1DE^Q#5+7+EuSf?aRByM%ovn&veH3X*?}{iDnWkz_;^LOd`48nb@LbM-gs^<`g-RW8Yl?Z zwAxJ4fV_b#Neq47m?K4&zGkB?C_yd!G=keBfX;B(U=L$?3jHkHRdoj;b6h-hC^MFq#faHX=c^_9=ba*O(LAZ_2u%;tgR2gzmu z_uXIMu+7q?gCg@F=)$-+@$L*{kB|m+9CK^sbiB0Z9_$6SXHhLyT{ZWP^{1PJAD?Us z_r|_fN}XhR)Dt=V-NzDv7%0CVoNkqWZfW|Be`#5|O*#mHeYVN#vjxfq{) zHdc_6PFc*amzkY@)1~)ZudKZ8m8zgyjt9M&nw{1vc-@8sc;8&LI5{#L6W%Sw6K{9- z6dK|kk23H#{guJ#)M7UlL*BX)OL#X&<7?cazIG~R0-MyGN~B3L@};J_Y(3R2(@zjfLh%SQG*S+*6TG=EqN{*33o4uj~bs^SWI9(~27 zl?Am*N`>!uO-?J_pr?}EYJ|vXA2L|czdiBNG^0N?6LJQ!*MhT#`!5BGRkD3pSFqy)WH^AqldN^Bg$HD)S9KVvK0> z*H5y^MlW2RYpI$7n2u=!ZoqJzi7ug4J+UkV8J{D#*ml1S17Jq#O*bWUD=o&H_)jyY znDtjbim37D^>vd^2h*sgmB{eIXjYfDDp`0)tnggrG7GE%lAoDz$=ER{tL_DMADmB9 z=s4Kdqf?*~2pOCb%-e-}G=MP`f{rr|g+!wkvWzY+ni6G5TQd>M@aIi$C(VrN*)`29 zWA7cr{wIs$nSKngwToKyzZ_iv+gt+bH(;@~<)_2zb>Y@TGp-dzRBiGPJSC06zh-uZ_p-sOV~jwNCetHvRt5DfekycSREd}8C*sJ0Tf$Qo^k8vlULIA0(+UabDuV^XBU`XFw0r^Sqo4*b z+Ic{$h@moyDa0RXodb|Vq5fdHV7$W$e8^5{vO8I(3}bi`ztZXzGQKB8pR}>u;=Vs! zh7Yb73Nvc=H3jkd5%jV-r_h@I3w!`JJbdUWE)M)Ml#ixY#W6alXjgS71oX&L}_eY}KALK5k9}KsbkT< zpl}CZAgSI1`RJlHA_WN!UhyUf-P_vA*Cqn<3+E%l(0LT2k3%v|yUH=Jl!Dj{|VIyhzBJB)mw=53TV0^n9qS@_YeA z5B(<|2Z(wHN|+Grd|lPXa_$JF^v2q?SZVgGJh+U0@qD`PG~SweC&qm5Fe7)`dAHbx zIxMDx6;aJ6i$NR)GIIe>4!`T2I_qN|9rr*xVxJVY$TTkOll96o=>LUB!Y~=N;xhiO z)@8%pZNt5Ju`?V$Xz|Yn2CAH(rT9xam$hKhY*|D^MDE8N;RR=q3Jm;$Lk;Z#Gyo*v zc2MbD7$q-_)<v5sXb-Xx@^MPAtO#)Fu2M_#>QAR(`9NeWS}Zvu zW?coXXdrRmC2>edP_ntrxVSLQ6LCkU|3r|3*q^_na%|74xo5oD_$d7;F8H~bafsCc zNa9$-b%V0fp5#F7SM2s#lnFw_uDQ9_I~Pbd!(m2Vp};!Z^EDl#og*u4@XQNp$Rt8U z91)Hl0YZ#kOukh3=791Vk3(z?w@xZ{n5hXjiR$QHu(CSLk%#CVk`*<&5-cRPAGvTw z!q$O*c5qG(J&cpS=H*cl|>BsEH`b^zlKp_yT{++O}Keyr( zSc&vZDT~Dnn)fXq?~ms;d4HCaCA&p^1aaQ(SE{VO^lG)u-m}GN5LpxEcbBW(7)GGLq z_Y1C}il`jMB(1vX*b;XABA&B~=$@&x)pqv?uaV|Y&y&U3;o+sjsdux)W^yrjSQLWW zt?+(9K93iT{?HvN!U%SUb@ro$c4YJZ*d4H=J^iGuGIt>6vJO-kcPhc-fZSqY4(P#X zh>ni7CLeqYE*R{OC5J$nSXh36{#YDh;)v2xMn(cOuwn*>918^#Q^vyL4X729Rx=W$ zB!ByM`_Bs$0Gj)E`q@W5;6+#z7*!i14$tn@Fah=^3)yk9v{Orna1v^}Z9b%wSg6#m z&|jM|4x5dhtQeFj-O!vk4R?TYbJQVm*v7-{EtRnFa=!(q1QiayZ$S0$-@mK)oL9eS zmD8bx76|2z$C(oq_nz=;t>K6hL1U8&XpI~xk3`7nMJ9N#tR?9;5?YKUjLQ(l$6wdY zyeFF6;zP(DCqbnu$fw-jp2G^tS~J~qnSf*0#Y)2UPemS5*c1x-)D|`Hj84{feX7}y zvICC;z;O_nh0S2~CI7hu#8WR$mXSz5r|-aO2pGd4GNk#1EFN;>TV0uxQk8q+2nb;P zBFLpu<>=j{9%f~Va|SygVy{5Uu*3J3258OUMkh@^a#LAI;6lIZl>W6!*4)qI;k+Ul zB;c6CAi;I>lAp7fkfKWqp%Fg2BZHlH(Vk=qYDZR07}B<)WxGD`6=ilgVIPA|5mdm5 zO|PM}v$Hb@s_>mj;k|1>_y{;e9W_oXf?$qae9mwi&EQ$U_BiCdpWYcp&Mc=M0sY;x zPK`uMNov%c-Cpq2{toiftr z)#8T!ob7}^h4wHN#t*mN-QE|d0D#f|6ptX1(?ufV(nDzblgZx`_Hg{|671i=cnG4Wf!E@_3P@L)RlYVzkVl} zUkmPa?jwhm2GaBif+i=<8F{(R^ph&tIaNhsgCwN8Iq3Twzs44TRSXjvL$BhZ0 zR?xQ}j(e*s=h=mVw4j}2K*Sxxygz#5nv#G0Ec>|f8LY0T*x1I3SLAl$Mw*_MpMD{)e#f>m(E;4lAv$y^%l^o1WH6ZgJx>xG({+ZK(L+2tGuSx}O`V zmrv5cu%mICQ!iNsdxf>kVd*yb2ze@wHAgB!yjH-Qt__{W^AaR{;U9cmtL|h7X5vKW zMEjeCJVrpU3IaaHS%Qw|o0WDi^k@F`snQRLmbxgmA|G)+7ZAZr{>*=*$B#yWc>6<4 z0RCA{X`Ht)aBhdWs(D;B>*pvRqfwD)(Hr~JuoYR57YE?{p$zN6?~uN(Vx+R0v*O*kXZo)=q?C(jD%m#U~UKmmONQHXe=_pHDkmBo)UrG^s}_i0Cf~0E0gm3_YsI^ z(*-h7eV|>+2BOijQwNsYRr*aQ!(cBYuiyAz3!CE%6YKyH#Rms7tk^c)@hEr7=BzsC z3BB(>rg@q*LEV&B!INK6@#&M(Qqz>(`+ht1QK#!sKxKsy_yg{_%anaezfY6cGTI7Y zAi={uK2Z}!ns9Qh^J9TQ!L8V1!5M5hGS;Xb>$5rdf2Xjltx)&8#+fThK3Z^>l`#qGJ~tLII8}&kYETKRjM$i!p%EWcSe)&9E@U;@;V@@U{OI} z&cOXF?deS;=Rzd3t<5Xfl*k{W##l>xyp;B|3|trxAZ$O&0(ybq{jQH7J?!Ct@Yb(G zb%?N03bvxu!^5co%CKD(B%||Z+`(Kml?Lk8Y24 zGHBj3>qDx-Ogm>m)rv4!j@rnFKr&^|qF{7n80s4g63kgu8e?6I4iut?ZPNM2KjDPt zs@7k0u^$r1bMPts4Fdl9!a1o z=)qWNmK}FB`5L+&(?EASZZjcOGL`@HCkaU-8c7Ti=-S7anVC4e!qk4YgKO`?0Jq99 z1jR;Nv>03k9?X)VL-p3qV#^IC4;%H^HYo* zt!$cCwuhH@oS#UwZq2Wn-|kGj<5B2JDPXReZE*p})z#IMWm4j`S4v_h**4M>!z}@ z^lqvQTJT8l@Cv+fB8T=T$sI1M>s9<1(1@oH={%Po3IMDA|>AQ^h@5$;lrb2l0&_A40g)BSQf| zf(l`}H8Ocb$Ci|e%AZn_gcvGY8t{g6olep^a(knpYC=-ZQ!%V7rPKm%Ik<>FcDG2GgUX zqvskL8jKKYvdz;+32d+LZY~4x8iIGicsX}(!7vyT6&I(d{VZJTiQbF1$X-b1ZM`!- z%GBd}XWES9-s2g}- zB-wZ}@Khqce!*5KpCFbl(Ec95AhUj3D|7?)@*%7kRuzKruW^I1xdAE~{bu!6<)v(P z*+Fje%grfdAEiyVyMfj=#&hjIUvK7R+l-@@Q|REHD-v=@U-X3?wUskcHuQZS45IK3 z7AWUU86vy=bsCmCs5BQx<4`CAn|w7XxOu&T;Yadw|s*LgWC`X=Eh!KhQ?NU@*{n z0Qeg9sRl#nUoi4v;^TWL>|zMMh(kRLnXfBhR)~J)yH%J1|NZ-ScPJrthpN6UY|fRz zWeF>Rt*N5Lj(l(G>R+vx^&H36Pcc`bmoHzI8I}jYlBdyBz3U%eUZL0WaQt|kh3|w4 zcX6RR2;!<=tTby+|53sSL1;#?i>VxwRB9+cF-9JpJ9KX_H;1+Mw!1Q6QrkjIE*-^a zqWF)pFNQ{?T>>K%bj@aN=IyF~e`e`}WCqe-zc9eIZy^q2m#zROVTTeXWfU22ngtOS>^s7rrJVGeG3@lO-YMDfzwmWI85KrSF>gv0 zL>gR2p+nON#)vAfV*U-fa$sOCPsF7hNo#VytdWeW4xXAv3Tw)kSM!^ro+ZJdVgx)f zgQCOWvRPbpK5HiCm0||i5jmi@5rWWxGI;N~lG0;|mt&tqnn1;83a!0bO;9`IGHvmi z=}+R&+GfltJLU1)DX&j%J)JO`s<9*ZSMSh1Fh5h)J;K4#WQi~#v{s6m!prh!Kv~>8F($Rt^7@UT+n7~q1 z3OGb9O)V{g)r}2b2G6<^NRRXfs8aq6J!UjAJ*uxI)m|y)m>R0Y?e3jru(ZAsmPMaehdA+L{j0*-p-Q z^3q&J9yf9w{|OK`GbxuUR;A|Zmxja>#?e8&&1va|D?|J9&A*RGvU`U1#H)eH%kOaE zda6ha^tFf))x6Qd!c!iTg>Oz7J*udm!0=m6gi{rW3@~omTbd@P#lt{P2eSnaYRKD_vDyuKP1_UDmbqm&N(jo?gU5og~5AUt|Pq z`lAM7ddIja_PIu=G}m9fuHpX3x5uL_^gi};A5>fp_ecjGQ5%t?dJ)_2=EVvIgufC`G-$*jY?_W{GXgbH`A1@ao6&XWWx}avl4_X%w6`8Nh7F zW8CUf*9$;gen=uEG4WsK$smVb#UD=77X5E;)|Aw+ziTkMy1KeA{97)qobf{}JVeju zb`FF(;ul(N9?&GVTR~F(GeqT&%gm%-$;o}+07YF8q}Dw5+M5x23&sN{z{F(2Ne?vW zAiK2y4uA!T^{hl|N&5Z=`;t`p@3{Mj$5i4qZ@G=Rc@)11)-PLu;#IY)6i97JY@*ba4;C+p>aQ}aUaP*r;~M+Aesmcl4hgI0{sfco?&h$`CZOJL~+ z^x1cyRL#>ZJp#OXF6d=}?J+meP%T@cFI=9mm4^)Zu#T6A59K7)y z=9PVLG!5dBYE$d#X>V5cp>)^;9x2#M~v7*IQTi_PN3beEB)Q(0Bsz z)seuOkL%YU)Q%573$q$jnXWu?Z4=1ln$O>BVn?Or_oF5zWmv$&()bA@G56>A#|?&7 zdi97P0MZLTe3Wsj22)pp9O@~HA$jw#advs#GhNl;n;B`-1e3u=!yGty=Qr&FslC94A8_<^3sl*058~W2dH6)B_UFZ+OzImKqk8XX??@xpY`b? zM)}Gd!M`(vw1-3P_rmhVc*F_VbsuKi?`&V`*H^^p=;?J@^8awC%lCfGt5j#Gd+Elg z@h~v(q|ymSSyO3BR&#>fVhQZ^GN^So_->c|5k-vG&Qzk+Yb*bk!6iyZaZz>x?c8l zy1P|yMA~4Csb+P6zy*)-4fKlln7?K~M!+QK{ivG&sWlWv4H%VTAj+f#oD0kM@89qF zN)SX~lLR`u9C1(l#>U3zXa9W%`_c+f02_M+**siaCUxMDy@I2(cDkSyeJi^V+nV;| zcv6&ie4)7$^Mn4yxrXU@T|U!jhJnE)c}S4hAaDK|T-L&ZL<}}(gYr)h?JxO>&Cp?OSsgEJyVPFT@O z{cN1JG7PofE!TzL(7d>&fFXV|MzKz19^#rm6!t_G?$Vl)9q*jCPYB8(m#r(R`WO31 z{0<2q8Vou07s`#Ad38#3O}J+LStD{3n+Y~0TG zbM-TWf}_~jKC?f0SVoTHqbUFLaj5jWmG=F=y1j`i)7LxPy-QWS-)R=l@0v;{T>bNo z%mN&ke-`BUn0nk<;yas)7oa0Td;>M=eLq$1>Mj^m&iWs(_8khhR)$@S`$`^!on4$N zj7!oVf>AS2hdoKf*7oyhM>T1!!+gJc;d?!h&onEdRCp{NCTDTH?s-o-Q$cBbR_KF$ zeX>CA1H`gF0JRsZTW%?q67kIj_#3Xu|1s_l8K>I`2@{k06uu|dc`6l;l6CK|;hsW-;FPzsv z8=jYy$0cI*`;1x2a|F+ru!Hj zUmcRZ$bJrYSY!8KrdP~Z&pdU`x@#fJxs>lQu7`W{1hq=PGQOTEmsmW;@S2(GO+v|t zpl46J()+ZYm_f8)>}6(3c5Qg8;JeYHb0^eew>}YNX@>PI~;z_mbGye*CF91Nrpxs@^HYTsbznv?LupfG`xE`qT#v8m0VSyy> ze>((&ARGGMpXnsL;2q#K`1#QO%^%DclJ47y!x|a;!C2njEfS^+D9n`$o3GpMyu4dl zq?08ou@JvymbfJFBx2a&dPA`K>t~-#<7Xb|u_pyV*}wqtQxP6yo|=#;pSqJ;@EEq}89k+nBVVxx;?q5ql$e>3y& zkCs~B+5UX#61#w)VC_U$a4>wblaxIv@-^p*Bs0u??Zk!M8>FbvwSrl2wXBR2k^w5$ z8jzhM?&oB-5unEA-a^0YeP&Xf!$S8{VAA7I;ZoWIaJJ>Z)7;twlCpq?C-=)2Z0McS ze3K3>C8d`}iMA9-h}oW3ItG!CrVmg-hsqx&mv^)-!k(nWl`>${_8%hO^pQm>P(zCx zU_iOb6tnmZAaS9%;#;BY%n;zmMi4@tDX6_&8jQv2nwr6YD<>r* zJDsVqQ+uabvRk6gioKIC39u0GJ%xtNgV-v-np2&3_4cAbv9#i!&k7d>|GQoR2Irlo z)v3}BJydk`Wq|n+M#%G0#oUh!AZVl7y6+?U=?V}~z!0f`z}bt4jcq#x!$Q5Xs_Hu# z2K(P%ZIoeNHzi5ZzC%fKiBY`-3KrcrHFGT z**!N;LPr-H8X8JJTl?|}_-}fBEnF8$x#gIcm{_lkfpyLN9L0P#tY+4%=(iJDR5ur7 z4kSgX!cJ7+@7~EN zvo~FXaWB*XVObiQnwBj&RtX?UbA4k&t5B28-IGgPJi`<)=xQGjv6?fbY)OHRH%eVS zm1PN(a};oyx!kssHU>#alX=Sj%mGJCfQMzzii`e)t8_7C-6pB;)AIxx-2hEZVyZ6} zS>=IAN>4%39h+8(wvYrIuM;%Jm=G~7EtlJ=;A@(zOj030jY*gOR8Tr+gS z-RJgTsL^ImT3Ok}(ywzM1HbJb;GCpXSgi&trrt8C;BXb$I6B!LF9m^`6v;ehvD_w2 zx!^Mn9%U!U{34{J#DoYjsjQ1VQvqO^7aE95-@h>{O(C^!Q-@LrM z@R%5#jn!3kyES@h>e7IJql!m}gO9V#LG9-#Bktf&4u2{tQbgHYBqdlXyU1!63By1% zUHwDG#oD2HmE)bQ)mp|7079+W`Bldy~ zKBw%!qq*DgdDI@rB$gTAQn@SOq&jK8T&M2pniA&Uo~mXB*6H)Awa@L~6eOie_Ino= zwglE8QRj~Ha%Z}RCFRHh6LDZZdr~H)0ukcmzF=lUz9UB918hI3^<+pqAC&oin7m}M z%0^okG&js3BaRghOxmyfl1A%Z>8WH0;{l&jNF^T(6}nw|Pd{fm*Xk>>JJ|w^BK=mB zGkX%){3*i4*_j(RAZvw)gd}8YO8@;a$Y67`if=y07W2fnK8N&R3W zJ%0SyaC@(%^*!?8iW~%TB%7kLuEAM+zqx?kiGer*1b)2-Th{#Ycx`0s?XzdkF1*+J zlM2XrOv}!4tzX5%)c9aD+cb0@&|4J@FQ0|@_;`!)@p0aaK~bN7tf+7pSaNm_4vRWN z+JovoYdLp!p=;Ii)BozZMFRc&TA1k=I5}~FUk~q5zG^AF;p{0Fg3yyRf?} z+ymICs^1||{<4_m_=8RD zzv#V@r3vxeJDx^V)rk-E=4+Z^6=ro)7MGRaN7ubJ62x^3Mi?r1ATez~!c=D*)W(YJ zsl9_W)ZH1Bn*B$d2SDxTN$oYK2Q(vvx}{mI(7B|!00##S2;hr^$;g8^|p7O>Wk>&urfgruaX($dl( z>`Gn9qFNsaHZ1tl%&YY?v2L@ju+uU!jF_SLEd1AJn4)GbtbUl7iGSQX#U6D~^H%}? zpGqn(44myxfyfG|bHTp|YG&T=ttyKj=)BRB_|vNQ%h_b!33psxF}QFj6esve52BhvlBA<#Q84~?$O;M5;=Ya# zw$h_}H6oxOFV6rl9grxwIoBv~FCwlRFVuddlqDe=lYcXPd6A#bl(tiMU(D~r}wF$3BHPpi)9Q99w;d*gVGYQz3t%PEK)9&R?$Ci!cemF1*)iOzADLZ zTVTkop0!%(iHTP##Kgqx0C8&|0T7(6;qAA3F82v@$(#nuTrhiSxAk8;T1Beez*p48 zj*KOUJg$$yQDQ5-ftiCTe>;kT$49)b|06W@9I^AZ!=~uK8yXUnxkSeK&mB)+v4k1} zRfh@=4vsQYC@PU$`t-p3f3NZ2j>PcS(!mh5(d8_er#ypj9`#N?s0}4HEOz_{^wbT zpnD0Aj{e7bV%h~&CD-C$<#KMVL;}B*O3gGbNF1H5cPXf{dYK2X7!eGExp` z6RTZU6k34Uj4-O35EGRUTTI+qd@xh&WF5GLK`dzyfz$<}F2H3OX3&!fQg5ckkU(5( z2?PTC&?Y#AGf_~epTXCEtefVbn&Ts$U98`=L*}Kofhw;sVO1-F2zMwOb|`@uJg?cG zeirB{i>N4t_9sc9)8iZZr?a?nZE?}d>jIOBwbo__-SGy>EL*&-n?PlzPjEReX>1(lNrDf{8_hD z@+|A$zkj#Dr%IUxlD&b9h6XfVU~7H{t>3RqF%rY_GeZXlhm^y^*PlLr{@BnUsv?&%XyuDb`}m(pjDo@8SbNmKE4C9|3i4e0Sb;3 zAb2&^WF@ure6F}H2Ne6@wFBy{w>aA0vdum2!0kEd-BLJ}ukngRz*ps4AgFy|FG%&% znjbun0)racp92FSG7NvWVGQ@j21wt0OC#k+8F)Rr2r-a$;LQypM^=-i#oIt&3^>Sw z_w2rcYUHl3PYD_lc`L~XYA4@PbAM>0s{|PlCy)mT7bVGniC`f3wR$}Hvw3PO1>lP(6!<{SdqA2Jp)}b zf5M(kDLhPzPB`|Y`bB$k1-3=tb5OVfmb)VE%g4Q<-3GLgU%}r{J>J)#Lr|R>zh7QS zb<0^o{?rGy|5DIyF~v}D+9$~`J;ImMCmL_|yB=61tw4`I$_ zH-^8}&t)!s@sd#i4ob@kf&*5-|bPbVnx1V-}Vgx2haewY0FeG{~q_4f{9WuyTtX3&jg1I7GsrR`BalT zhu!}a(wen0GL#Np+%jE`1@8@7A-y$&oEESrW88G*>96Jk!T0PcE+phmpjV2N@|q1V ztuMm=-W!41)!pr1tj(SfaIy5>4Wu3Jet}BIBSEt(SM*z!JB1m9aDa$QFXO+1u{=Ya zfnW}hQBhHeIqLc?N=i?!=H}*RQ^6fz_8Sua@dA|GE3KI0#SQh6XSbkW8{5>91^SvG8H$3JTAFwl$jun%ayNw{<;weKXBev!vDV)|35?`?meNcSG5UW zoHR?QAKCwa6w=>LE)qOHf;x0bOzC3aja%?)dlWXbJG+^8YCF^OlKrP+R~H^eEAdP1>CJ^>kyE=$WR@w>~z z1ktyfghd{g1JQbgxQyG%6g*(t<^f^9{X~n{w}(z^a}^1XUVJ%Pe)RC+cymgyWOKgS z?YsHn2+f(Q0G7!KKOG&$wt+}}l+ad(>+EKjXm#;Y%;PQ9!Q+Q@>;D7_HJ_jQv^s)8 zVta1R_~+B|kv2DK?JbTa7hbCiqe`pQF1D%57fc>BqPcY99%Z|*&F==}QHA#dZygB6 zUk2xSriAzLJZSL1K+La@r*6Npyj*t5g#~i%I6S59mZNx5C6N&aqc109S_D3+WmsL` zwc6}F*eap(S1e};wI{=VdI$Dvna5a%FV&s3Gm}didXb|Q=t_ACa*`D4wmv<|{aL{( z`##oW{81^I@)h0_jTGUpE*^K^BQU#E(e}o(B#F&ur8w~Ei^8+8|83)QUKLwJX3Xb) z%A4++`w-Fdah6bBi7lBZo?xdHLtlaSGWaIQ;FZ7LrB?GXeFVsndwu0JQ%zAa{RfAA z{KcoDY2pcMlNOLBQWrI%oWjyaKDaT#ZPgQ9y}#I=1Blb_07HBA-w)TYI5utC!PU>q zTH7dj=D)*4MD1j!N@HU@K>z<+6t$xyd$*b7jhw0~zM#>!V(I9#XxQ&{nK^Ds!kL6y z12%KAPQw>`cjNl2{!PSS_}Ae`>ZjUr&Vb0@SNct3MIZCm`~5~^SoMKD285%gmhuQJ$dymcb9rQZCHY3jj2@6^RFd-2u=#hYvCfa zYGSJ?oSZ6IX=xE4S?=amy69;0!b=F+UP~@Y+)?CC@ePPd zncijv(A1kokPr*N9F<*U(4R&Lk}IwRVFh2%^UF2?`;ZVLs!M>%;mOhmQNIh`qDALv z{uhr0`SF<*=DNUvXt**nz=N{Vi-NQ9utYELd-)6fwaQU@P$@pEq``w^MhI=p297;N z7)X{gj$H)h%g~`Rlji%x&$=w?#1ZRmF|R|0HZMleG7Ll^M=4Nl zF1bMQX!xXAR>)VBw4Z%_8XQSVZ0Y#_2?z*$0kf|qs3f2S-47jrx&=+%b`=n;1x_8T zkP?ELgQkdobB?6L`sq@{L-BXbhV0^IF$WsF#zxXEelr^Cqc`;!qgA2piWg;bw-kRt zvzRr!SkTJrCHNJiV^k^Q>_&a;c66VMjK0nJR8#z8csOSN=ZEe}YD%pyW=s5*bhfmz z=yjq>e;p#vXL+fk<6AC?g1d;dBiQpQzl2I-eyOA=L0%3A_Jeu}JSYd`SWFxuJR z%l~)ntjK`IQ0^;6OOZE-Z0jhukbb+G!Qx(+_0VI?a~ZYXLs#Ou@$Kzd`xnp5JBWk) zCi>Y+QDJ{?O0$C+Cqlt%9{QgXw;L!q&vd>w=XP)xw}}JVGriuQ<~;%ZJO9OCpMm-- zl16QAmqPS5=ulwnchJwD&6CKZxaLKQA!W^L49=v%0Dte+HS456aPtZ11f-BRCkpN( z5Mtb+y!__n?E#N~f!@lR-TT+2bA$f)(m8v|$h*3YsWi4GD#1mEtROTTa?uJN{VE7N zf3)9L6Z1%i_QfoTCDQXXxA{Ip(J-S+aF&g8EBIyH;mQ%~vd^H5_Xx!uMh!RJU_$w*gM7a#bLI>F@v=5>ayV2%VrF<7hb zxq`j@CI@8dsWIX1gTh)^-pso-h94JAlJY52wq%H4@j%e(yc%hqJ!i%$sL#C1hvtk0 zRgPrPxxYAXIKkzmdCVm4g1PnagMLoFW15>7Mp2tMN}=Xf(rE`fM#vHdC2mIUcu&kfX_12gwa4!_^`HwNeBcB4zo6n<4V%Kd{^1_ z)!=R*8D?Q2O!TlmJ#ST40C&?L>C_;T+*)H~wTNSCEwe0Ux-3sGa=6O{*d~${{rLV$LVdCe6lsd zw=%G3Ukl+4Z=|~!SE1AF9sXZVC1;^0-qlVx>vy+7bdm@?)5g-9fv8&z)7`juM8;`9 zxLu0an*V`943*B0(}SBM8>NnU-yNLg%=LOK##l9zjb&2o7^aDnOfN^rvYD*47Jwpk z_4G`D`*HfN4NAIzhM$((YvZxil8>{8apoh{rGQdfzCv^OjX8S@`r26GR4z{tw@>lP zl?ZYgL9pP1w-jai{kF8H^A8hJ=YMi%RoUJ6d3GJ~33(4e1#>GXn`E*$j<=GL1>POmg3 z7M|)+a6R9wvNBLKW+lw8m4i57ksQ&vJ!xG4p$tA|@j{UpJrS0>>EJYGl zWYcGeRZlNgF7NOyiF@6hQ^hxzonw5jn<9V1daYL_Sj(1N|4GxM67kC<5!D(KSPDNu z?T{-k{+g=cEDYBj)+ME0t-or0EXL(18yq92AECvN(@T+?d`bYWmU>(4D&ghIE&mT+ z<&%&$`?zccPx2?Zn0NwY$gE4xQtSjh?TZcb>Qy*Yk>#*xP3tj`J^ZIKMrT6(j`JNl zPj{760wLKOe4{f?Jzs(FXd1DPpFe%dZSWE_tb2^GEx!)d#C~TXipI3I25W4z+fyV% ze1aQF@>+-QsdxwOk&BfitMkP0MA^Dg zR4ykSUeAflywG^K$FK8s?|CoGi;`drRQIn9z`J9Z^AS#~g#FgEPUyPvRrd^)>6;t& zn;~+U)JiK!NNB%O`S0b81Wmge%0|WN@{g5HrkOp;kJBH>k^Sx)Q?uMXD~j++!arg+!3!G>$X^y<$oFLU^!Uazx%-zl z_TLFt{eOcHgd|7LyP6QPzNQD<5S;|5i zfS?~%S6)t+?Yzf?wKJ5c^x_DigXw4c!0jd0cn34@mQGICpNDM>cSi}IOGE!QWve~7 zMhflF=%{_DpC~N$obaTHri@N6+r|C(@q-8uf1ocD@*wl|o6M{R`Q>TiVS9)9<)$%! zXmk4-Y8H6wE<}BKfDcC5vNg2V@1Ja(@VZSHXHL~(DJOH5BxF{ti38i(HqI3FUi z;+`P=IWz>`?I~}XSmFK~j<*K6*}wUX`+{m@3AhJ$$E~8!iJ8mS|&_Xh#AHQCzCAw=%ExD{1*V zulD_Oa6cC+5HWm~1R$V=BXW`~X}MIXXJJ3f8*lVg0@BMrY$M`z>#hih{a zu}CQ{Yw;Jvgf?E*IBLPT+u=@vTEm0G%w@P~#uzTCrFvyOtev{`V4cQpb^gouAd<(p zrkO@H+?%u)29=$|K6vyJ59LiwvpB!G>7vJ9iAt6&b=`E z3_<;otZ;VvkhjT%$QqT^i~k(GAA~j^spU|A2-c&RPLyUuZT~crj@U^LBwuRvnc&=b z^!H>KB)U0eBifN!kLL~&HBrG0T695s{)t)V$cvS@4+#k&Knq|EV#~$E9sr#QImn+( zFO$@Nx-s-ITRKn*lQA=ikrDOuL&Q~u*h-Zd7UpkUv-WGE^gR^?M@LRm+i6PZX zJs&PWMehS1?|BZ8H&d!troVJ{d;OUKN90=K-N=Y~8t67t)c<(KguHp{m6@NPZ><_h z4Cw77@5Ah9DzP`#Q7tVJ_mE%}T%J`Vv!Gz&&fC!OyTIq?rYI|u2d^R)J$Zg4 zXtWZsS`bp22eq3CWd}HaB|}VHz6XBZ?Dc$_Qb-g$Wv>wl2nyFMag++Y^ZS(}O%FvQ z!>=(^p4whqEB{qq>0A4DxP&O;4#B2uK_+xgUu}dUz<1ba0KNSaeBwhpluW*2JWZR) z@q4+&G-?2yHnOx--9mWfo$SFy&goKEHEQW1iTSB7Tpd#eD`ct!wNj1DY9dj1bD@>C zjL`e`XIbf@w`p7UCmHv?c$RGN($|;3uW|&q#pNEnebWb?C#OP{zApaY!cWt0wu4ml*cqj# z2dh36WJMixM&)ywQ`A^Nnndb@Q^6~%q+5-%PPeIOzr1T!hZC#>XX|cB`I(M2)x}? ze^5xetBrW?qf8VbA9p{ch=GJ60EpjH;(*T?0lJ4;$LTSxH3O6ItnT6A;X}*0qOW+p z7%SVS{Ixj53}09}SLRvaMzyRk^AbfDfE`MFnvni$@gP?&uNc&;00>To9TtM-5xKuf za$=Km)wlMBJ$o(uhDG%RNr$oO>FG4;M{`1hyY7&yytv-aPIo^mCOiuas@kW+$5(yYX6Q1&wQZ*~-4ClhHy- zx*tBoTNcM9upo|;ytLUUb#b1Yk~b&z{^SN(8f8gH{LxW*Y^qNam$lBo3VQnN89$4` z_4&TrYOU9$jm#tF1~*AepDffQ8_S!959W7%k*}Vvg-26GCWbhu>Q;AKy8b$6VVUjU zE<20@LKbc9E(4@E8*V?Z3Rj^LTX_9*1ju7u2baKA65(|CptiV%k+A4mx*O=qV4jPK z%VGXnTO+K)4`RrDaMdD;MITEW;yG>Oi-OUqX@I6t>ai)J9a)jpwDcS2<>qXCz>JE%E1uDFmqMoOslQj>8H~;VQ|EPNwL0O&}6xhBBb6Nm1Avf-Qa#yR9N`3ffd=+ zB`=3*F!R-BKY}DDe_n8 z*3ol?Q%cV2tQ=>_L~p)qf_J#n4QQHWh}vZ`g^JQQt@|&Hb`ieu+KPdqRYR}`)sB1u z8s5FBd~)PEM5+IIyiWy2?9OKO)ItZ%oWIl3Z1QbhJ}TNfe!#&F^W-jRwtx@(PGHL{ z3(q>#+LXbFXp`+>1pLcGe zpN;V0@a`@i>j?4nH|%EMabq&x3yu%R^=!;_qW5@guwdmcrx#1KO#iW_ajxYWN;;65 zbM8j(JPfFsu`?3ioL$hUoth)}CP{w0m>cGbSWAEm!^w*Z{!X;~0J7T*!j zb1Q@ECf##b)?6w%I1rLR<3@8aZI|-^+;?Xp1TLG|;1>`;+VWCH0+mwv#lPQbb;dht zpk_l7{DS;nU(A(>8uzv5XGwAF_x-!2CUH)F^&T&l&dO<$?IzH;{N_p%XZD)XbvdUi z2LJW#(2DFs=+uCsjWtkr`p*a6cO+Q)-pBFiP}*bG$nR!wTA?5I!atPC?a4?({ruTl zo^!7{doRvYLI)F;&2C2`f+m%caUER%#XJa)i=%iS8mjNI&=P^>@6yB`ID{;y2$huT z%w8LQ@v+G8{Pol2STQQdTCUw@%*5`lLUk5SNO+IaIreT52pT6z&!$91DQe|L*99!8 z9ymS|?Ks2GTwJH}D9t9_xl-aDN~NaWsFnl__%onI zYJGn|&srEtD3`@NlO+jT_z8%;bilW9>Q{BhvZk|>?H6kl@OlpT`01Ml!$z4qYH_|L z^~pPx_%gzYFlD>oen|~fTnYpVK-AV6JL7_xS?23*ZT*Q;NT^QMJt-l9#0@AfUIAs| zb%L7IWgL(W&6(Can_!z~yg8I3MPazl#eC8>TlIkm=cYo<=cOhR@BrIwz)6J#1@A_- zXU;Q(M=1vNhQPS@1I@5xLa;(G)_!=)Tpd|ceNg+TT%PiE{K|p(7dcK7!GqA(ZlCJ0 z>qmn%rannSf69cM<529?@%@sN>VVD)8;D!LwGegNIjXCci6_YAZ4GF|zEAm)nfVIm zc0gMn#i|tF?fp7i%)Sq{1WWA4Uhtxkq@~IJk4a6+TOJ0xm`i)N<(YTt-|giMnYN!GAT=;UGkpXo zE|DDE+!NQi7g;<0)iW>lz}=BSMf0)Hq4#sEIX4~)twYi%DJAE( z)7hH0KBH})eGM>T>b4@~@Dqf6^WZ4q!?`{4($C=*_UPx9gR{I}p<`r15 zw7TC(cLKk!BYs7Bs_6bBU>*@v@RvO5A{n=>5ko`V0r{0nJaJ4^6!SqlQc8#_2CAy8 zxYn&Oeh%b7yBB6>+8w8{dlj8o68k(2J`LfO*O({wa@n{?K@Viepy$lguGt>At1Sf# zaqm(5td9SO%|c^D*aBk+>>IS-GlrpiIB<9Onl|EpB(*n3gdICLbS)T&|5e!j?IeNz zm-t#4j-}$x`X5T`!wz@qp==6;@K1uf03exDHm{pW4#PslrDUqQwZX)+kcl7+CFJF` z>g6V4EyT1i?94cx7GVGOjtfyl^9>c{kw@R;5B)$O)}`Z#OX(f(_s3aR z+i!jT(=oBJe74U*bj3f<Yo#MpU)G-ywgEXdSYOBtzMc{YGVkE_6B-XgVQbAOS zg%)?kOW8i_3dn^X*P>+8x^xHa%_Sn&a16ZuRqt<7&JbTta(iGoEaH`m8y@cPw1aEI z8&O}hFee*x(^qPic!<$TulW5caQ>CWT(thh?JFZur$cESWg#ucc-Bmu!c%t)zq&i= zz^SYuODn5!aETGbi27=xOhZIL6%wX}Dv<}$Elehf!MrN|doQwP6P$iG_tiUmt2r48 zm!P6>6qaG(fr-FJw9WTxxM`#(P_bd5aH4lliEEvH$go=fWg*Vh6AgJaIY>#|nX40y z+D_*Pg9t~I)E&Z#NISL6vQz_yf5}hAW*z#@@O`3wF)}|YyE{qKih-|)T(Zhr$P3Q2 za=!7+y-+OC{(=JBN#Jq`YjG7Ugg1MVLlNkufhHN_&Yq`xS5)kj#DUQ|y7(4n&7w4ZbZ^eA8MsH0%kriT0Sd1z^AU)RNdQ&jyoqWd0*Qc#ZYn zt&kn9%kamosq_AzN#awwh&gaW#kMG&h%*h)QfnRX#ral(U~w^$px1vc3;$0G;DaTz z{oySxJ(2e!w$mxM_@|RWsn*bFbtp?W{LJa8{h}_ou7T)3CPq#890X3jDk${@d)9@+(keb_PV}$>{fV&EK-zEt}38albm{%m$>7t_h?>=fUcmM zcvHyk=L!{Lbi7Bn4^1amMuEKNdo6DetIA>0_@?j*sH298#=%W2z5DZX7^q7Hm%B{m(^o`3FG&QbX%b(6ctNd5jYM0MKp=<&dxhtN_O7Y=JWuw z%KzKtLV0KXN$`}{Gyj+&r0#BSRyE`l6)<-buXrHw`Ga(pgc>94M-ZdXUE6%UE z1Aw6Uky^G&z2h|8!>aI#G~1tJ&TuU*GV+tDi4Gfa%@mgdfxXVQ3e;`dR4W z(6=BNR(ZD%3*;Ch(cq7`Ni6hY%VDk#r^}Y(%G}7vSm3OB5y;EkKxyhrNTnC8ZBE^tx!JK&;=3yA*= z&rFoId!~q&pcE>ybg)QFEX~*Cz7siQ(wtwWf>QnsZdna6b`oRW8u`$ugw;ZW8Fj&V zW6?EsHLe9!q#`&R>IPh$%z3uYZcu*?^>-J{H?Q;z@@uCXy{5{|n!j_;I`?>-%bnKt z)3O{1$gw|<+g~rq<+MQi9xQLO#GN@Suvv zKK^_0oDnd7h*|f3$x9=AcJ}R|j_GoL-!CF0+PcZ#Err|yhJadb;>BZJbk)e7@zaCY z2m4diKQ8Z9KOe#y+>XRK0RBUm6*>e0M z@9!gFCf{N_ItX1})=W&I&K=jue_DD+d3Le#^Vxhztb%~jfYNAu5JTm{J+4;9#+YC#(ky8IiY^C$vEk-7{cCT4@Qb`x zc*VUNwSiqvPfZ7`a5|n}LE;#|4aXY-Kxj%GOA&@Ll|J!b$L>j+O!z*bf$f7GCbYxYtv`IiC8cX zHg%CVFc5N{A6x2)5ohJ8RCpSOMMkEudHN_ZIngIk$HYlNCkgFQ0?}Yb)Tmf38XS%S zgDmEo^R;@(F&!9Th2*KfbhY(%z_LCEbc_$6S5Mhbz%(#KUgEF3^tiIppa$K{|1@dR z2v6KeeCMJHyDm2uF)#U>V^0`J>e3SvQSFYwY5Nm+9ky@hftyDb6E+)n?<#?K?{S&Z zp9ZBlt*UJ9#v6yVLS)Dp&;-oCRO`i8KXJM&;yy;Gn0Q@@Nhf`(2)XK>zjq zgJ#E!m*H@TfwZK!Db%As#;&#$9)R2&*MFND^^?F}CQ6X}ILlcOx+jSRY=6DZ6y6smJsVfV$#MFGs|wPxb4x37t|o) zq+@uPUIb@A7PT|8e{=VvOPLN7(;A%1{ff4M8m9xGOL8RC)KT}W$uWD?Z``&DPGEm} zgNKvs-wuZMqi%{1iHY(JA0fSg#mn^4qE0ffip&sjm;mZyW}#9D7)Y-5@DRXhAzm?A zpY;lCb02VL&esA(r-Lr=WWb%QF8sP-_k`G>6mlf*iRAy|>${_|j^DpOZd+z%GRxk{ z&dlB;*%_&j%(7=jLPoZ1vXY3bvdK({D0|D^dp(!$@B2H?AI~|@InF8FPPjksab2(L zH9RjZ2Sa!tH6@h|nR|T-eku4#)6mv&a8WH8XOc!Bpj}paWLAHOX}pMH7AUi0`e(4~gClpB5zZ7}Dbm-`(j;(4 zzEU)r+StG@iboC3#BMtbeY$ObU+W*QEdvwEr2efU&vV`L{g+^Jf9$dcBZ6^>l2?|Z zZDf>`8&>h+h+3)$3D_4oj@{GKdj*v4)v=n`2R!bRcS?MwbRfpG;IH|u6Va0RyUWur zBGjnSjI^+1b8*EQIJEw0-G8hAJ0xtK%5nAyW_p|pTC`EgM-@xkIn$bmQv0Y(<0=h6 z*#f5$D0csm1XbEKGi)6wDl21Zq}IMZ4dDN>F}RpTD}6OyMFr>4M;;fw4|~OdT(_=Sn)6(4DIEcb>ZHIN&&ejh-{ihj&RpwL|`#qCcX5}DBYOP7POoS|$2 zT3Pq;rOiaU=+G}-PEH72Z-h=04KedQVnzy5vh4FJ0596z2qiAWKz?Bs1&y~!&n6-U=C62cmCpa>j$bACOG zDgSm7DzYHk8V|N=?SR2ASNh_yEqY(66BYNqa7}HVIL9a_$7?ThEDHZ+MTOD|>B@x9 zcik+TuA=Z*jp!&TvGsWyVZbAUBV&?!*KT+*i8fyv*eCPgbMJThVX_c7y`&A|GGKlp~mtcqCbT+4M2V+x^iT9uLUy%$_R zo)ZVu<*(46jLoA>St4{gD86Th(O&$E0|p5V&lR^Zjc8>;T=Ai4q{2EO{IhUycFMF# zdSWp%fB{v*DKo~%Lo|L3fspS{WfnCidRE|o^1OM0_agaQe@;1$)fMjyN^oPW#3I1& zf`X(B5^_v>z8(RQFJDeUK@TYSe#6guC4?)htCQ3+Bz;OG%%o#oe(vtRP={aR&DjL8 z;iSWuTwcR5f6rHUI$`IMmlil&6nLS2IL%%M-_y-vMTeInM)i^_4_|%#(DlaGr-gXr zvmhL30qbgnJdfw68=EGbiv4HY7Ys8-mSmLAEyrnAcYM&L7T9Ny!v>c>SMKO< zSwnT}b55AKaRTq@+rNJoEZ7ib_lV#f9`_(m^;^+M*I)CtE`@4+Iu#db8o3(D+XIbW{7>unqt;f>lZm$02z9}Q`j4M#)A z5<#60l^B_b$&btZGIY0}20Xn3o zRvQTND=y)p?v=z}&A^qjzUkOU$3?sYqu;Bv4XypMjTP3wA7;>kLe zh#tnA{j+VW9kQ_l#g;!-c>*8if3_py227be^Beu>n^s6L_lFEV2(n=0X4i?tVI&Ek zVx^e*yG0gfL^9TeUmo1}wBir8RIhujEhbAXn__S&_K47x)^6S)^MT6SgjdbWPJ?b! zrnshwsA8l>9#yqtmo(FpJSvOq<8G=D4CH8K^;mJ?B)MK&y&p^({%&mf;NG1LQ6TxR_mvGU4)YKUN59SltPLD3A zhn6bl(zR%<<<=Aw!R;{eLnNwU!1fC5B)aU#o%)MSyNAVIqaCI@Yz`OizFpgC<2oJN zI;%XkJ=CfHI%Rvb9Pn*hLh8ZvmRs`jgMT9xoS#hV!kWr(BX^|yN@^GP77H7gf?lai za=hbbwd?+w@dFL19Ueu)!AZ198Swfx;5DZ-iqS_|-knG)Ki zM3x{XcbMV^-}^e*t*VVNazxAh?1Sd^eu)RVC57+0mWkQ3-b26rPvW(qAG{i3-y41{ ziSyyq)ng|kF(myPgzD1yqANv`g+}uD-usLOA}LA?`LHr9xv9W1aydgNLR9{K(aBtm z(@_!5^cs1h`NY>xfOH^QC|2O(&lB+-rt-N*3qR`)Bo@b>_hKSHsK!@n29e%QqU?Mo z)Z!ert&*L$0K&k!*qLa?#_$tkF3X>ZG`g3YO?u>16Ah_L@IH|1=H}oC8~JRBEkLba zJbO1wi;kQ;7})Gm#RKRkb$xk%pLAL4K3a^#pCTd?W9r^r0o z9ZVV4$0YCjGM5*({=J@$Yc@xUJpSu*duw=+#Qb65e%Lv_;;f{A@cXZyiX0+y_x!ex zPT%QCYcq7d+Xp6m&q43>*ISj@Xqn16?{w3?cHvnQU?I{KSqi2pSsOVI7T4drrboW+ zT?=}?9r$FXWaVqSq3?_Qx47m>A=oi-Dx&JA;D_DOe=Jt)xivoI(7MFzm&G8AzGl4F z))rND$0P)Z#HN$r-l2Yug-|2wh*E??3u&m_>({S|N4GJ=Eif9$hW506?N_9C1+4s| z6!jS$cRp)CPWQjKsDa!iuKdcT0ZGn11Hd3eV4Pa-u`?MO3KEuRpb~?0?p%|LLUo}h zrTyPo*CYO)z?C__G8OOJGC^zyviQT|gFFv3K9u#tudA3yDhSC45jxZ5S{|J>^0RBd zW+?BuR0v~_V8?q35t#50DdeDqeR!%yb07xBO24(5^GuFR4gQ1_KlbAm$J{6Pf84GA z`uokcZexM%m*1kXW0)+M(C8BV8#J+B*iY)Dr@qiC^W1y-IY*^2jGVKTR#v0?n@cr1 zPdl60XXo5U3nBDkOtOZq^fxk)Lw7GU|D%B+mk8r8l`8}y)CY{7@_w(}CTXr93!28m z#UqIe(XKu7&i%C>&mC(_K-L zn1qIBfnR@J^{h$QzX+cAxGcq<}wk?xP;;9#=UzSLwq9KP}0f$wP7{9JY z(=jCGB;)7gQS#`>ihJ@^0u4TzvPH*=!n0G~#JPVQd}}{EAd&P$y;#o@{(J`|3oe>F zib2?JaF@GFCUsFMaA}q%KYeY|0EPpC!8k46+TUOv>WM__q-7 z-S3|C+K}i3`PseILCS})lZ=lEye#i71mCV*P``eC!qWj9<_-><%s^c{ObD-EpMbyk zAdbs}g`T6>vHN-hk~obTH`3wkyB87@Inx|(yI@HjK`~iupfBO0L#Fzt_ZA%<%H->d z!s^MsTib-(=nRgt{!Gea4Sw{Aw|S(k7-V9|P~Ky=UK}db7}+`=5@FiQOSIpoGF`Al1Wb3%KK${czKW}I8`%0`1>^}sV9jJVB!=2|Sfd#EizJ9+zS|{$_%SJMJ?Z=M;3!##z7I>S4 zdDJo~^_Tq`*daJ07&64}NAroaJmqt9b0HlUAlwEaS+<8+$uMY5uWti+$+IpA9@I(c zWT~)%FX^3>#OP@M41KQoWO0Qj+nP#BjXrbkzk-P zG1InP2st$8zQOnAx1y*vAym4F>)?iF)bK|WTojz!2%do)eCFrcMpvE0{lmx4NklM$ zO&>UP>3=d=(z;n8e=e|9M4nqgh9Unr{((m&HR*UXoFKzDs(bGEJ$?}dV|$R$N`uA0 zp|_+64dLKZLGZI_njaEyR-`Z<*%>wcVdRV9rSBbi`MB4oqr@%IDqCT6Q#dfiA7>SQ zYBQrxHlYx*5TTX(OL~e2d86=c3)$~-XgWr(_B`kM`eh9xxWE3FQtU;~O~oyE_{mYM z?D0xE9B;YLcq2`|1^uiWLFMizKA{sSDRw_r44jjpqs_|ufY^~7j__MY-0zEi8tttq zurf(1n^%>+YWRG&xIP;*c9wim8Qik{DYy0yV=?t>o@CnC`;O;#av))y%{#ahc-pKkMa zcZZ0pbkm=ocfO8{baj8-7qiJ8cH`gt`{Wr=;gUzPg8I`tE6bJCID%}(ajAzq~#^J-2m?;uIt@n|GggF zdNz^vCOrmcZZrwgyySHML5{yy<3AaUA^Hvlf3xdv)>Qd8q(;Uw-k*9cJz5SI$xKGI z4hCnQpO80d2PzrMxpBBqJn0b8^x&Ly)TJ)U;)V-i%uYn`D@|IS65oqFRyki@>5d(A zhcBpm`1cAjhA*C#$Hu7Sk`;e(5~0x|%e~FsPfZw-lg$Q_!B8x<5}1{$LhNqR`!8Q~ z)8pcFa}Jr9vjC#}*OwI-B)Nd|;me$2?8Qd@*`%Vtf)+JqUYpf2f#;b@F-bTgQbG0o zy2C#@(IZIx$QQ9ZGbT(X#&`+oDWS=qIBW!{X?3WebVN^9QvjB8+mH>TzXsx7qVT2| z@XLL5O-;qScTvsd<)UEggZP8YtX8O$wN?VtpvK9eAIdAs;g5#5NBj3(H>$pGE^`H0 zof!V9aL4=VV)KSl!Pli4_;OGrmX;U3W-20ktZ>hSO|>A|ZPQyEcF zL=ZuPANaCn`^&8(3~wX!nZ9>tYO)b0^aY~(N5js#|7fnqbn<@0)qD20gWgnk}A!=J1cB5W3j(mvq_RgxJyS52=n(c@Fy#yz91W2td&MbHa_QZ#U7 zv9Eq7O2UkI7bn~Uh^YwD#Xf+iop*-C2uk2wc-B|l+}yyprg?mv7Ce#Uz=9}@bcQ+# z+#b$8xHLFYwP3sG{7mS@Z)*VY4L+|_&SU_3GO+E?(vNRO0WtXIX#2xV1WPu zsq8)5$r(=>+L?DKYdamhakJ|Om2JOBrH#)^cGqnGP7o^P>O|aJ<9;%T)KX2LnU2>& z4lgA!9-sX}L*GhT29-p4let_|9X8g;cK%y8;ry(Ugb$XMTV!k)rH>1>@_t6VM{XMC zU=U+$uB4As-F6j61yU#9k?wlw);Uj>_57Ro&UyHQv7WCMQ5t`zoM{eF2H#HX(%f2) zt6UF8#T-Nv>m)Bdtic`1sF;FDIlH?0&+0kIL&49`)f&fqBdqtWGp5!Y;wiW};2rw+ z%_gTSoNl>$?u82SVwn>A;sx!H|8T_sYFo2t=uv^buc4uQ<(McouPH%!yV(h7g9J%U9r; z5TXS(;lyN{GuQ?w-R3cEEDC(}ySkGNUZA|sL5nX|?6cyx_tYun$-$h=IbL}}e|};< zyFwxY8+YQCYW>r_r){Rl$k!5Hsy_CWiu5UJ#Y>YIh@{2AKtT*3BO6->4Ov0IwU)N_ zbTo>1r-$%Vzzmf!B;7?mmBZ}pzFkdqvQ^c=x^dI@Z~l~XQg=@A#pb3KMulC3g3QaQ z=Qvb2c;8h7yNU#0*Aj*MwOpqiZ5+LWtjnlp@p85YqmOE9C#>i)pFiFTXDqT?I~JLZe}%F{5?&gVm)HIR8|^{a!IDXUi{6?p!DSr?Oqe;;tGToXyruMrGabU~VxZtHEKk zvZvONK4*GkgQ!r~NS`%{C=-RS!X*tp`?hpDL_|c`TIHwvKYc>kN`4g}T&YAVwExQm zfV)LOab$GEtD&*<==QCLtqd4=)de@$m>w@oug0T7UV9$DFGwsaFLU>BdoJz3vW;z9 zA(hhV;PZn5LSNx|jD2-g{`Ix6!DOy2uwN;F0f!ia_+}bf*bNJTd2}rsf$H>R0?A2x zU19uV{udiB+RNG-vCB8idx!QHKKw54wmW^>-*2%pNpV@kAyaXC4n?#*0gZKc^qs1dUPd$co%){Re=-Yf8M>(Md_J{6LQ7(zs(wyF>F;O0#oezKua+ zKT3g%i+gFll~rjs4webkTW}}8868atGI~({v?7xx3QhG@Cop zXsR_k_{uY8R5n)}GL-H2Q>z<&vk9A?nEas3@lFYuxG)dC!d1^elEvQqS-*=>oV2$A z6G{QSvzZ08)R@D)Do=Xe-FFBy0vF$E%Z~AeV!wNJBjti$@+6(u{AFLZF!p~Nbvb&9 zWr`RNHOzA%L>Fy@ZyUH*Ciy?OcC5w|zSURHH;9CrzPhF+x!5m;sV5_n12LYVnDTDI zbr<@Cd%QE_r0p$rWdbFv8#f==&Dc20cilIy_=4ixv^v2D8!L?vMMwYpH}xrxR3KDp zaNYAX3`?EjZAqQskmG*Av5Dl=zi5P~oXR1EB$56iJ#nDLCc~1ZdYxl4EbVmsS=4zk zpJ+xgdZpko^_8jVX_A)NEqh~nv&v_N+}-quQN`0>04yEKtS;s#CrZfIE{-mGUir5x zIy&?-O?u-%PzyJ=FF5DrgMbWHLiPDbf*T`tWK=_dXZ1SsvX zpnn)ZN06O`9@QgXcE+rN{_P=k^r?9s>3klGe}gsG-Dxt7?Bv$#_}}N!#JPJ`kDj6D zss#7x9c1?7sT&$U{qR<)08Jk4F*(W~sTIfnNBu4^c5&6}bNQEZZf@VVn#dTNg!$pO zhTGe#lR3G24mMi@?PZ@#`OLbRy3=#7B1pvbVYZuK@wmCaFZAt#RvWQqMh+T+lCVyY!Rv6_q?FSPy!WvfmzKl%DS8u$1tyA>7v{an^trA8I zQz&b{q2B%bK2l&X(7!TVLV0|6D9w{-33y?=SlYUv{yCA|*1*6#4FQIlk`jZOvM;sT zIbtre>e@YK`U<#^A7VQn)w!*WxF{Fu3iYqp<|P}&`sHh+!Q6M_txn1H;JQb~p%kE)_U3o6?>d-_jk(ifCOx`OJ3m2pBbqF8XgNA9En;Rh{3@>| z5sZe$?OVukga5d=X9h+3mkiT3O*gg#*6hh?qU~-v;QuNpVe}*24N4g&`!C9hazMY&JwN>|3@O=_G-C74Mn zlqN~G^S6#e%q%pCh`dGe0#&;lG?X-dj8|Q06~5xccKDd9q+Vy`)PUZMOHWrsj)pbi zN&ey1D~5(sp)l2rX_-9MY6XW~pU+aRsS{grcLXUPpWLZ}D}fP1hUN_Xw}KsNw-j^Vm`2`PFeL4zo8OuS^P7 zICYG%oxYQ0!TmAFFj`R6=0P)ONo_!Q6&~@QyywOH`yU}R8IUnM^-O0)hNhMb^G&|!E!M9(? z z?o&M4z$vA?*XK{K{7ilE;MT(2T$29DfUO|W+lHI1nzLpS;wE~&h;*yZQx@NMryFeX zF`p&tl~6hqoE)j1`;!#(7604^5r10!WY*OzwlEMeKjB5rXc3sKTdbT|wiUvB_VFdj zX%VXFHZ-N@d-T;0movgUJLkc7>?!hG%{XwP9jql!P}Zb>^2$|8epjcA7&9Z7{wv(* zW0Sy7B)tERF{8xKq;(@Mdwy<@%f!F5luu#KVHmOdr{WWZ+WjM`ernCIHDEaqmhH_J zwoO7tHpmc8kKil(ve=M?2JoJU5ARTB`~Cy@)2Pf-9E56NTE@`mY}~`1;KsQh)%k~y zAKyF-2N(|SF8*Y-{f04}c=$mKA{9NW@Es4HKirc-6kr zL{SBBOO0;R=ppH(0&JafFn6W$f83>|eE05MydqA?Yu*RrZX1^|1EU~YUc|#d73hA@ ze9Zq>2kY7&gVXWPTF9Gc%HrdfP&`QJ`M!5fs$3-{jrzuxMFvh+6JUHa_8I1^e#m{~ zjpo;${yBPDT6J*AB?n2vBTjYnEfWH?q>gVg4U-kNi7xey9bA<3SfpqLVrmQ#rbp2OZ*~KQcCs5xcX=5cg^XRwWCM zno6#*zQ*F7tpq=kBe3W}2AO`B7Nj~`)#81*E3XVdVAq1tVnG28NWCGoT}E5Ge+z1MC2&1XnVGti z_3uR~hKxBxUQvm=mp%d`*EjR4qX#KRC;$2#{)|^)?DJs zXeX<+Iki4C^L$ZwbaM9Iivb5UD(Q+XJ#|vm;3dJwM~syE>8x_RUcu9Y~!cZo63coMG!-)*X<3BkX114|kl)2{E{$zsEU zgs~aUM z$Y|*l(xXt3HD72z3?#`WDtaU$uPq0=DeUH)8Rb694|x+48l{+4fI+UYlO@a%At8jc zBarcpAeXW=etZZV0=p`K?>&55{6ixUk}Eplo!cffw*MK&VQ+eNz#@asmj#+Fd@4Q! z-o=IULC>5Liw~<{u^KDg!@q(|t(i8Ld7^hVm}2^~6akp}d_-AwrBge*;-8$!IJ+Sy zI*$v%DAiR*ssy~?&SO8im1~dxCc`j2NfQ!SZtGEjl~@%={IVTkNJ}y}z>(o$Ld@p$ z!U7gu6gGSa3k$=WSMd8OpA#cU)bzZ8!X_$1OeN(j&K8y(FaGfKa0~IDn|mZWdVf&! zJnw+>vu@0io5Rv?=e7U<_ZieSFu`)gC6vDs{1ryntV^vPf>pLGxL_oXLGAU$b~thw z6n1}~KQub)XWxb*^%_n964KHHVw}d->z4Cx-P0IwY9WpWYk={AuC8vb0aqJ5s}ArP z|KsD@eP4NlbsQas;XJ3IoWkMc53RNjX41t-{+o^P(D~lEcd!6BAla}GB5rPk2A z5@b=mX;{+Q5SY;jy8oW`j|Xc87h^3UL{ShIj&N8`jkU0 z!J>t1Dj4H6uPvE~>U?}Qn>pi4Sbb@Pam+XY{B@MKuO&}V_7i)+8Rz$UEHzk~A@h3F3;KXc5 zp7@M~*o+X9lix>c6uxx}bi5=FRfB6K2MsQWN-TA5(;&|#U7Hv^2)={ivLj%(M(uCN z-OT%95pB%L;aw4{ia&zaX*%AVuIwR6AN`vDgX+OrC1CXPLQ~P`EZK*}IJG34zj{1x+|K{^vl4{*;B}c_L-OlnXm|+C%+K$F2e3FO z>_wh0;6o;>mWc^|g%N@0o49PY%Yd>9BL!Lf7vlxtW29HF!l~alc)Q$T(qSQ@vtFX0 z*V`cc-%^kBA*F4WewAj++-Tldg$Xd z2(ibteLQTqJ(w@1y{76+p*~r zc0I@ZH82ng465wq5y!X;n}D!;H?-!-r3D+cuW5P2pzmdP>!#WSwT!;Xgh>nG)_@eP zI7>wAK8DECquvau45P9~q22aF>EicT=gYb}U*H!@{`wq!pF3VfVnu9&i>v+oK^BHV z%6X42dyZka*jeha9sgE<%&Fhq`vkC(~m zZ)|VJM!iI^0?{sM1p=4ehb6-;)&gQ=X6ATCMLV^*i^&h>e9h&!) zNNdE{N4t)zL?R(K{SFPjwcVL<*K-Q^-f{iba!|9lfRyzH7uTC#D|=uZO~6?3?q_0q z%O$sSeN6OJV!gLkgC5LF9N|VnYwVUg=0G60Loo-~!|o{~*cQiMINgt;y0`Q;LW(c` zW$6BKQXmS;?(=!*X7b1NrF&}IeNRs@#v^?Z7k3ZN%@3StvOQ+8$f0=VR6TFx;;ZY! zcDxHyVJwgZu4oDLJVA<|p`?4ETfIMj4*kyvKIi>= z4DkEcD%6D!K!X)v>Ia7;jQqfjI7#3|07I$Qfqe*BrPVb6z$=7Qe?SoBvzp#VKmN8Q z`EhsGF>0Sw`l@P^eTFYfY(uS1)QwIHjpZm3by*9%BmEK-9IVZxJOd3mh`Ti;b{ZCm zpe$vTUf;!(*M1!ye!C%O@HSIYq_>=$TrC;`EI~{bOzCevUfwxN1Np*YPBR#ncTelv zROBFb{U!3!{mP2pOcaOXq>lN?HClj9f|)}ayjERA#l=%qInhdb`2BTGka&ax&7NHA z2oZUah0E2Ek(i$T$)a;o@@RAqF^D=bZbRpDDQ9A0dY^;}n$t^XvbysoWUjvjmFJ|C zSnUVC;@-@l%jzCD46rGhyl?L}vh3ElW_AU9@fS8O&Nlom9dD67w5fqsA_R)CihQI% zR#rAkr!aG1>2f2#lt$>Hto9M0I)Gss>}5!Mesf(|qwF%gU?ZxMe@)HyJE*SLIPe7V zdUC?i92aT@x$;gVg24au2o@SMuv^(RzYq>voEbO2HSquX(a#DVBGEE1F=2)Np?vWh zT$Zj#h>JtY!Hh2b&XE;5WDuhsx*^C^$D%3Ku?smCK9#>iLMkG!{icrm@@59F4{3yL z;mbtaWe+4wms@G>7@h0|#Kev%lK~N*b3%HX{B(97(XeNSJew z;A))m8N}w`;n6q;*P(}yTJ_VjyEP%5)H8#SD%DXU26lvAT0=hRIha^fYebF1rAg)W zq^k?-9>VuXNeGf1>=Y6c69`dSgpIxpzYFiNUcTKyh2^IxM1w151j^z&LB*q0-2m6+Yc$tIOY z8>=FNP{Q)X9}2Ts>eNa46;F(KA8b&^DD%PM9oaLy=bkXpwAQs?eUlAKJfP{Gq<>Wz zne@%__C_Nc^XVY$M(3{?zXgOi7#W)^5(_bHzRk69&-d?KWDG31^kRJMsvjczEcR1k z@EVMp0@YYXZ#zykCWGw;Cq(mtbNr862m*`q4MZerkzpz>4@5J{GJ!>7JSzmbmq{*7 z5?$kO&3Ysqg<8H%FD83PL{gi^lfr-#;QZ=TJsrkvb|eT_0P30rl;#WDz3u6z4}cjZYM(#eRK`Tl{r&vHPc?yfi;rwIK8J3G7QElCfzHQX~y%FV;WlyGD^3Z%@yj=ZOJdn026T>sU={5_sd z!M|LPq_w0t)GI?12Bf*h{$sAndlQ2}D{rr|OjLtZdya9onHsou?B4}C?s4pub82$z zSu&|HUF}a}lGi4Ku{)HgX>>bPt)(SJPuGNlP9qe6g{on2I>c~rR^L$fm_=GYOEUP! zT{QDYXR7TXWalxVd1d2Ow(>_r2ILyF8T%-E3F0it64EQ!5=b7UqKNY;u5l*2=HD}7 zLW3W!WN({zzLh|vvr?+khH**olNMBQuh?TU0hV|b0^~J-MWJ91JpZ(U8ulXS&|-F1 z{|+o2fZd;cH@lUFM+BVs`ygr=%m1K#yiI|3(UxDwy>Wh=2_9n z=nJWK*O5|aEt~J#MJx#-S|BSBvK!HY?QQ-0134JOnfw}dn&85QqV3ERf9+M%FXn+C zle9faOB}F*o!3Guc;ZEEelf)k%P-(Invbv*>Z%x-%=V#oyH46a?UeXZBqbq{7ER|B z{;>0cgbnE>rXEwu7&@K(R9~Vv73}eT{t5N0@I^al1~N9UGlu3Ho2na%zSI7s!S%5s z67%s&YUj3w2c1~V$-zd-q$2o5c29(=RVKu!}zJo*C(7Gtib63&s!Y40;nd3xRj z`vAY*X~)KSXZjdL-XC%?g5|Z#MqD924KA`Q#;gn57@11wc^W=a->-QMXcIbWS+S=dP#ZuI!rkwfINd?}g_m9xGbUVGIqEY@a1k6G62UxG4 znLGC?@@&wD?{OxChL@x^Aq@{bZp+f~7Yd2w?m@ z)QMYVgVbZ*dwlac_@wT!*qfmUK#$xF5@;2wP3*ao1(vQyDD33@e)<+tT3y#hB-}O> zK`{mWq0u+j;zOWt!8j*j3^o_IN!V$fnN``>88GaIluTZ6e(dt{(fHSl??w7|5>70@ zsd@&)nzP_JC<5+PcV%U7fmZ+1{FoQ(TxYq1Rn`L~<4sHyj0I1ACnZsdj_PFGBWf%U zVw8RL=eK(#oy5~Bi(eRa>SI5fe{a*F;b1F|+CMd1NE!Tv|9s?CtF<9>p->1~wt^QD;h2VH5$ZTVNC% z+c4Nh7TP-^RMascrts!~UbHnfAI{asf_wSR#r>R}i)WpQ*^% zUSp{-mgq6=^}@!9w*g1->b*!X_po%-9W-t?SoS`a$v>~yCgamVKHjSu8TDJ8yMV#g zpqILbhbW?@7Kgn1c>QUy6rM*yLc^7heu~N|?1tZr(&sA@G7$f=vUfjT17)gLUbg4x z_O-R`xovUs(9dht?u;GCuZ(~cDa!k~-mgCl{!99-Q_sw!xBYWf-h~4VLuLx5LQ^|O z?t8!Wd)}`>vkpV@uxtpcvEZZ1gawqCh+Si1x){?%Lx}BJM|bVowSSWhQn1!AP%jPX ziV>){Aj)7Ch*m%rSg=5`fQ9YV=QSoC@a6%f4Mb>?GwVpSq_2l`AMJ`oiu(7hh10KSWT42G_vRs(4Xtuou z%Qhs!>Ss`g1l8~OngZRigw|FyH5tg8l#KRe3zj!c+89XoXj&-A@9o0B)WIdX&) z8|h5dcVL&;8E;llTWc=L6ivNU{VEe%D_`&XTc>mIT4e~j^?^6^_>k|#@Ky;JMgaLY z&2IhBYf#9Mv9Ms&NEJbYhd>w-cszG4LIDy-$zdr4R#gcH-DUhwH;(>7j21Fwwua68 zWQu+Vw9h76qOE3KnrUAbw(o$%o4~Fv6~L+l?8n^a!Tqs6Uz0u^YLtJkul67l+9*dT@+ zH|$9{kogJunHF0f=zo-+6@E8+vf&q}mVR1!?`#Ry{G8wU5v%0MYPkwe;tDqz-sLw2 zwJ)@l*^rq)_(dFLT)uA6TZ~#g@wr`Xf_na>Ue?u?ro&L!mT~9~N7Q#xMn7BTUkN%> zyIlUPb+vZBHH)tQ%LM@DC-Z(~yWQm;;Q4Z#98-Dw5rOJTYGt3gGaKvt@4wn7C#-iK zpOqL@sE9*c%ZE>vLyOA+^Lv-m4&#h+Nj(RT2NJxzTm^DBdFe(xwWly+rs}q-#lPCU zENCYpK78F+q9>cnpUtcvJb3u^UZ=AN&8E9JOnRq5Qh2$VU|dQCaQYj(=SUAJBQo9BhUT8QRXz&}-MO`OouuXz8BX?n_|Sj_fJ?D?RA{IBXqf zD=PBN8y|L|r66^WZr+?31hv3CzEd+zEEr;xFHfISCmx0U(%?@n%RnqWfN z0uS{v+6^4*+T(s*sVd!#;xuS@(Zo!rPZ0STZ<6~Wxcs&tZ7>a;srxi$!s86m%~a+? z)(ZFUH_J;e{)RQ)yr%DvS(IM-e2g*oGP-OA_Izh~S=q8UxLUR;QTRMCGNSJ4>Y9UJ zBK}8;zGeKVm>zwtV6M`S-df-c3IZZ>optjEhy)V+0*)!?|at$wJ(ba+6|Fw^p{36cztt!m6O z82?a9e(2`ZO8lVlhF)soR{#sdjIE6NJ<--Fds#Y`F67a8)9GT^szUf*dRoO#+ATyR z3=FIwlJ&&)Z9}o;PX59Z~Zj$r>0 zzm0_*$>vxS*Zln<`lkeHEhF~^(~{KOt8f%L9jrfqp#{3My2%env(~odYN+4x3}EGRyLVFV0uj*tW@mjzx+YGGmd>D zuj5gfE;0#>1`Eg}dGh@;Y*jH97q6|E?>PUea)-T9py?hm*AKvI-wBNVejrnSH>#H7stS50zZNluK&9%B-BVvUSOS|aFAR52 z&+Pj}dY4ekY~@vyVRz2r!F7Brn1*PP1ygVvWoBj~>hA>5AQV-vC|D!^_62Y3^ktqR z^dgWzMSFB~3eM=m&do9 zFT`=u%2E@C--SBM-eh2qt_KIpa>{(joVtwjQ+uzD!l{hk?4ZU9q{i|Ql%tDaBs;on zZW2^-U&)74U>bC^Kxvqz#rBW=4Uq-ZWxDV<3h5*~wO}wmzmcOD)drO=8Uo!%3Gkk! zU>+fL3}+E`a@^l+`S1c@8fiQDY%-dT`=EBt1u5u##AvA>2(FL)3{;>yU&V}eucWy=kPLSV}@`Zg%EwWF^n#R_ z?gDVv53@7R!$vJrQ`1Y>VG`2&`r%R->;1CM!a^5RRmF;h?`=pvG%Nq+$edp{2<^N4 z<0PRSPOhcDgc8)EB}{-Bryj3=+c03BV%NraHeG0VWlFi1!||0r?e|wP)R@gN1xuEi zfwlR+bIj*)GikPvK2SQEc4f*0GC}3@VJB(6=Gffh3_gE~dGc3Guf&CIGx~+y)z|fC zsM@)9#e0m{sIUMnTWM8Ix-ND+{SO2ky3~CiwGpERfl>{_FTXW4_iX=`F$3oKYJ1xm zCVQFL*(msZAec<}g;<&>t28__PEzP!Fl4}qhYa8rP}H+=aNKorx&@Y*(AHj7;M>bx zoaV)GnAq5=z=pUCiezGDX5{83SYKbiY>@h4>Ku4C%aL%v#tT;4B>foMzqM$V`hxm1 zR{mI_OolbLL)osnY>5B`;UkG7!stM|~ z^P>i4rV}4z2_1-0~r@oC7XoMyF`V_pcE>lv?zlV{3yt+wcA-e8B6va)N$!SHN z6mwF|M4BmKz&hg;e055t%(X&XzxHW0gG6aON@j5Svm?&ss{DMOHvbv)J;`s?j>U|J zZ^z3(N_HCi&SWwoYjnez%%64om0mgx85OQ0ruch`Ygvph8PF&hC9tPvb64&y--8-d z0{R+2Is@T&$t)|o3Vd^MDag=mnw+GE-lqj>j2>B3B_uxf7-B%WJ5Fp09emALx{c;t zAfs!;&Rbqy78@-SOwJJZ;AaMBpWiSRrms@M(Cvqg2L!o%Mqr9Y!`=-$uMH}c`>yL_ z9vQ*4G4NlPoPzoDHLI0m@aF1zCkVkjuLxQIubzWGNg8U4+S=MVDEFxNAL00(A6WrH z7rRwgcX57)UFxD%IlDiuX_!}ced#yKbb>qUBgdZx_f9OiIzg&YDOcgdSnhDU*4HFT zYHD)6zLNQnMn@fi1x@P!)<6WDO5m~uboYnDf^zr1m9lW(6QC6p_2c1^ohnA*m zfxaUujXk2CV5}js2V&`@0U7Yxocgv=kB%(E$o1LCChL1Lab-+@n4;I_UWq7mJ|Kp5s72#CVB>1-uXCJ*CE0e%HW-CA9Ws1!S-*T%>p2HqEl$7fLNdtGB7uz3F zyz%KJX`m>3uCx%x9;@@H%;jO41|!M+g^oHO*{SuvWb5hbPIG_Ii369bszFSxrj{la z51n$$Ym%EUz>?cLhUsle%1WssJ_6vVno{nqxPyupKa#d2--T2z`U$W2I1eoMq{f>> z+;i~&#C#A&64NUy;ZV5)bs?Gw7x)w2J3Yde8-34&&q)ASwHHD<*yCha|s+aKfwcUd$a^g3V5AHBz8fMN7 z2#)HwzE`hWk+&VlBY->CiY{u=xdwRU3xjnDEg0NJU!*VJag< zK(e2es7s$SBLg4>K$E)(Jg;efJ`d~b{lw4+7?=lwHp&nj1M7G|U&9WZ5gaKJinsZp`tYgMA4T)K@=9&Y6_oJvjV= z?N4}|qYvsQTr?SCs3zKFw=ZLygMu)2Dim`1*PR;y)dMCOM(n>sD+4h0d5};3l3Hid z|D7Y3&QG~?Wy2eYIe?afP+W&vwx?#ilX~1WD9ciU8^WY~Go*z?RP6L_V8wa{4|Aiv z;@YZM^M4WKa4SlhN}T@>1ux(}^50h}dNH5&psL-svIj^~D+6#1JwA%-O+06h@;oD8 z_q|ZZ0%p_a_~IyTDLqqItUbdJ0(n(4rFQYmN8}^Y7x69q|FreiK~a8j-|)3dm!yC+ zNVkL{5)0BHr2^8Rf`sq`X@R8#q(SKp0ZD13mXJn3QaYu(Yk3a${XFkqud_1_><%+~ z#ks!clbfk^EtdLe!b0gMtHoI0<2ds~sF~-CN)X#`Rt@*|48!9-=P&EziA|Ls*0uLR zBj7Sn$V1Sr$Oiy6W+^IX$_+u|b5Z8)dkol!o>-M!)`@rNyhXR6;MODgB!_79b;ee7 zwWK=%<~0IK8aQM<-bR2RA@89*kPaYkznob9>oJQhb*OXQAhK`L_`z|h zWSa*^^gSh6k>=XM(h}I))O7z&t^W#=2aL4~jw0?0<;MQh`dcIX-xEdu22YAtBFrRz zUIkY(XGYoexV@q&hCU>Vh-q+5A9T793SOnHzke|9dXIt3ejsa$TU1>~^ zW8R$8Wf6}qujeYN$;5oB%4W`Nixy)jEAi1sFHFwT!Hjuhg5Skk2Plk7@90v)A6r4h zmcRAQG-f*)pHa+pOE3v=_o0$W5pxbqId`MJK3y1jEK0U=k6Lmh*_vEj`(UZZ?l)N? z51&u#r!9^wOdyz8$c}uDiw|eH@B1sX@IQb^gU(lg$cR{vD0$DLU|?Z-Q4U%pf_mPA z#cmNaOf!jz={14*%N!^WAtntFfPcB$90~04Vi!dpAti|qX&6QKZKN1~?+^G@f&Pl= zT1h39@8@A5bwrc*=kp&S;{Y~bu(w$%nr_jNg1Jp<+6X%)Z(jM&h7CysuUx=#OY1ga zkKK=8-@Y&u%1{jYL7KTXR!0iIl4C-krgV^lB%mm6f(GN#+1^>?-T10dV$l!DL{}l= zuFD`@^KlhZN7liX;N!k^wo7B)64Amup#^2N`IJ@mj6dIpAKN2zoHU`E*P27-2=<-!1) z?(7w1IBK`KJIZZMV)b3lByQdZ@Y3*LQ=>zVD_IB3Mi<}46&y|YzKYAWe@~%Z< z5nNdGC79TF{n0DSkhXBYVFl~z=%g(dP7!=hqzq-zKB~$=RRajMO5I5IDjs+cls*us z)a9Q{i^FVpMMCzcWC(nM7;IL>CFTDp&v5c{KkyXF7=pVVAc4J43(s~6r|$|LY=nQb z4s*y?QQ~m6p#6^Z(`B3c{Q5M)Y6LeyEIOzo+@uwxxv>GUDU(739T)J*QiC?^{{TDy z62Ww&-cO6|gYx9(0lMIg9HVOt`8&b1oDg;IE)dr$1NfZlEhgo%288(V zp|TAh^o1n37w#s+_QzQ%9U6nfRl5xg^q|4G$Kdr_UlaWh_QXd_=%peF&ihaKowV_k z0Mhq`OD7*JG~&f_gF*>(7Tg0#Yl(CfI7vtA8Z-GWMAkea>%-}fJh6VzD@nEwU=DnT zBmPbpvY(O8GOjF6<NN%*Ay^(kit=U{O(}QAlG*0&ZCxFs5Khx*|>-{fGnXW|sJ37ywzaHlyr>74G zVrM7=$hDj)cl|O#r2iL;(I}U8I7v{qDm9czmc9|;^ULw~WtG_oXFA5lOjVO-Ydap> zWSMS8U#OyccuFN4*--a(WuJDNJo=v6&&S2yUEuliFHhIMlg$JZ{c3wATW+X5;2`Ls zC0-DWS)4mE-_n!&3z2nvdVevjr}ydj)H!i-RQKzK4)v$vqIO$&pW)gA%L{uyZ0V%p z!n4Tka(;t$=QGp zr-)rrNJ>hI_#5Dwu8(VG+lZCFFC~@6?peWtu%~R-NGS0nd-i1WWZ+0I)yhPhdwl(P z5WMcG^KiznDrJ)@+zF>G0o2L+y>)&uACY!8lEC|`qs**nnVrA;9y>anLn3t?cSN|0Y;RYH8RPM{y z$>KoH_`mBFnR8zB-!wmja5v=;C>%m;Q!5|TI6>EMtWQMHE78(AG+s78+k74MH5WIx zV?O=M7Y|Il9)a%;!UevmsUUM*=R@L+0JTuCwPoA-_i)UiJ{7Cj7{{;IKROEm2~sPs z5wUV+leQNp^VjX(F4Ka7nrIM2pe%KLG)!Un71}hTPz;%Ru?#xZZ~Hi6Xlho?0!=4= zn$7PHw4$$T`lByTI(FW<@7lWSF;myO@)|4gbkxkHz2@CbS3--V<>^Dm(fMtdQz)(o z=U%V&3cO&vl?XJ>?Zfu~p9p?ELwbI*?d5LxeDw0>@{S;(AZINL4c^Wo4S&9VSY0@7 zZM0X5W(=2|{diu_q?S0)BI6FH_NI8*kpX0!8 zWMXK%S)8XO_7ADkYmfa~iM{1-$<^6I@3d8k)yMmiW+Fp-$H#v0N|>^^>=E036Az3K zT8MLczE{;pFyzz;rqrOX?7|DbG$W)|TVLw60c^08gJc>W1(I2bKuS$~Nx~+T(S5_t zxB(ki#;dn~v1`rRJ|%$e@7pqT>8m~ei^kL0SmoS57Z#T4?6F&|fi4?0vp?^A&eD82 zMi1g!I&xL3LI>&i5nH$-AdC32R6N8R_Ef0@<(prjsX%_P0ih0zUcstV>SJ#FwqCng^RF1&Ju z;dMRUOwu$iOm28rL_fP*x8>j5d(WS*J5Epv6dEsG)_GeZ&;O0vWg&G|eRF(ZMvNl$*K_A2B$p5i>7GSXT@x+l_Bu8G z=6=)aSQ|)zW{OU@d<}L0XQ0|`)ZP6pzh0w7=N2mm7_V+tc1v>uoE2BDNKtz=& z=??ZeDLzwHBIs>K!-waJa&jb|J|DjZwpMSyc0F>=|FfAnN~>up(uz>a7p2xL9?xbK zdH(NN{q^-VAh(#N8r+3{xq9Y_4n5&n%EkoMvF-2fQ3)U=4=fFCJ}&>g?^As&fMh%; zz(+|UbnLlUO|blt6LzhGr|cr?F4j91~Y}@ zcdxF59kvqiQpHnm8J!WJ)_c7>+qjXELO0#uPEIU&MDk4|oxiuQug~dAdk_gr#VS@A zcDCCdRs|-?7~hJ&jPC*@Z1&8i7hgn>NH{R{C`$QFy`tZt-pCN9(XtTC)Gk##&hH## z=kAd&WeNm?Xa*qW%K=lhQg`29{iwQUS_?kmKN&aeYX97uNIv(@ja7ggCzZan) zrKawh`dlS<4Uz+dca5q{6Qvd3eEb4wj9@_Wj*e;GYnp$5{jhkQ3$T}wPMlmx&&5Br z{|OD3StYiX%e7Gfu>aGOm(m8GDuhbBta>+q>!)m3NEfw?TboRgKgdUr)=i31!Dn^D z6pN8&dJVVL?!EH9A_|n%LNEM09d^32qj$C%zQJ$Q=1=;hn!wMWwN@vyt-!=SYrcn` zf|8Ps{*m_uKQx}wO}Hzim!OLG%}hU)^)zKxSUCbvoyx zJ5@0Ov?5>t`^;xhy~o15S>-e4xv0X6d*5YTc6Hd^ z(5H9!fG%2^_M)}~>OA)GTpsvTb|2Nmfl4!cXgqqHNw&xpM#p~+OCS6(_D&*i&*+g z{)HQ_*Q>nHc=z1>JF%DHSFrgIjx-b)$o94>I3UO$o2Ydu@-)8jVx#bQ`D!Ur`XHtb zEU6OEb6ZavA33I?ejyd+w3h33JhL(_07!AXN21Hz?HBW!~)V0bU9ovby?xb|S z-kquu7|v)WfBB0K+9QRiFGt5Gr}1Mny%X^XrDYiv$!)4vFLh24!qsYv6lNJX7m!dY<)eWlY!iMDJ!J} zVg_bnf{!0Rx`4Xck3aOTXrbKr`1sFR`N!bTs*@l2La=bndMncXJ^!)SPH7ct$N-Yd z=6>NvB0q4CzDO8T7I8cPe@0tVbN-9r3jno&JsGI3tVncpMqiz$3{Y4u7wcCjJoG_- zJO)~X(U+f*st0QXz04ce52dc35knaQyv>F5C*H}r%^%N=p-jB8>kR$4D=kJj7fE7N z5hm~f9nvIMM!tS<*XK*N0%OtG2o^%B1Wx~yGazVy^~DSEt%)Dm`W#2g?uW+M>XGVc zk9OZcz0+}zTxSmhzICz=RPhaHsl0We2d(n`sZVy_Bs~lVNbGE{N8|fMB6*o*l@gps znU-@tfS`D;ktie|2ZU*>5re=i)7#kC$hZ#(vDV&R9z9kvWgQ(Id7$-5u@g!(6Sz0=s`0*1~_lN_UZVeFXucbxG%Wob@zp0{VYU>$~S<6nJZ_AQD8wuy>A?KYgo0;#&4cl|{ zc^!mn3vm*Gvdnkz)&+N?E(AsMeR9%AV~1Sd~6$`1M7H0_(H?C{X7!)C*0lMEo=G?CR-p+`Lr(&cwmdsaLN3 zGyE148WbT4=FTV`mf7NgtuX=k71)ka#NYlB?!NOnRoW-*R%Vmd00sgUA)y$@DlfgX zh`aX9vJ=}*tCQEmf82cLjA=|u@F9+a)!TygJm*@Hc*z5kD(kzTtjD(aL+!}=vK)oX z=1xXybIt_i4d4s7AXD^|fzuCm8^vY&eL}ISNpO=)PPSV1OnCL_rrjs-8G63M@$1bu zoT&H2pXXOq7g{t0rhh(dGd+@Z$C7zNB-4^E!UUf@OMi3GxsX$KbjASG9 zQe|B5oE_xIw?w}%k{)nxwJ3Pb{RRZoS<42u?E++4@AwINVUN9#B7`;~Del~i+v}F$N!vOpl zW%XprXU~&AK~oIuUyknP`J09o6)XQ8Do09|-Te$io`u=j*|fFj^PWrd%#oetlM!no z%f}#@J$V246>c={-YEw6cdHRnKS&y1oMv#0^n*1I+zyl9L>QQFm9~{0C!Zc9B<$f_ zkD5PdIjs29`kIB4Z#etR18d%i$h*b4R_g>uZc)XsR?|1GC1OQ1^?c6yoP0oH=@Od= zQ^4EEA?1q&pML_wW7g9zpxU(f1uI^)K4GE%7UcwUN=L0XJEMMFRe=1n z@Pg9PU59Xm;R@YSV}L~@fGSh4}`K?6Nv*xfy zP*|t*-w1>@Q1@jEmZ(Lgc-ne6PB>tKbSt{yOKI+VUKf z%juH?Y`4Rz2}$+Joz}$@SFe|$a2Xurq>Z;jzRdYZ<-3Jr|3;_PXZXpVNNhA9-Ey$f z+aP|IM2YH_eYumz+Vab&%kgHar~%lE4#v-QhcfG_L?-KBRINgLe1!7 zTPa{~x8OHvvORo+fx$CMQ;ci(3M+Hb1tk9RI9$nbmCUh{;EZHhjMG@z*k>9@V~C%A zZ;OaLeBgetoB$Am>DbGD^B<9EV$QEFW8zvkMd04qow5|uKZ%T9h*F}MKNZ2wfMuz% z!krP7P}{9Db;D*IQYeazDJeoT>)T?dR^_?^gQyO01mFKz=GqR47vL6kULzMJ{6on% zWo08u^jegPdNVzX6GUZ2LnvSojRs2W*qE5Ce^1dWxqoW1vdq7=n39}dUM@u|GPD5L z6<`Y(fwI0~VT9m`y#%~bXCTgNA7}uxfaSw3Okv5tYzb{yk4WW%fraZCj-hODY_V4B`lm%>*ylrs9DQe=MO0eDTPiNkCzTuWX5DxU0wcjk3w9i|%8 zQZh!4g;HjEzIv6t0@(z=AqukrHy`ch@lWpRYPeJ^!3ozMu25AYO&=d3D*TeAlWiI~g~W`Zdzpp8G6t&ImDGdQNC09Kp3@;0?to=;`z}T0 z)n7JM)+c%tWDU#C>)XEw;u5*J@BHX`HSi{^F;}K{wc)3pdoK_;p4Fz6>d1BZ|rp~_08rJ#WQb|5VrNCf;y{D36}Z_ejN65y(#KvQ)4 z3g5T=Cjuj_lN{t{YdoX_MD1VmvYJRyOo%CE&fN7hk;pdx2Z=E0eqn)wz z+;qZjJ~mPC%*`Mxni*t(JJWsT?xnFwb;HZz>j&PgnqeTJ-F|3&aGVdw=mEBYT4*ER zU-+r&wipu1%DW|#lY4%+m^U3XhhiymaBHI%7rF9LfH48@mC#sHW)&IYM=?>T>MUD- zDDyR#9ksu!KZSl!kNi$OJu*+s_W=!0Z0zi0ma`=&dBEZ?3(m=|G^ZFZq2lg=XpY8j)b^KiEyx3-7WFi9 zP1LPD+y7P2r-k-`;|GpbJeO1@-VL?U5*)_JS&U0!Y6_Z3JgR52$H8H4yp$%~x`*!# zbhs<~4sGb0NvWvDIniATypZsk5iG^H(rU;7h)mW&L(=ElTm(=X`s@3PLWCB@E$%~u#B}AaJ7IeUGA{AtIe_6~`ikf!3P|$JN;c7KI*Ujcg=Zp|B zkY{PJvH$f#B8s<$t`c!IwkZgi`aWz|DSeOY-f)(!pkh*?(YQM zS8Rxm`?p#aQFt;i_Xoq&f{u)tEA-HpBfo)jc!h zDz;@RlsARgrO%5r#;DSHN3BGJlg{^ZL6*l<{#O5^Iabfp9eEd*hpU;8!yVK*@D?2b z^Ct)JSd`GWONjEJTQ7aP`m!u zv1sP_w2chOCxFZ=_EBITXG0RSee(727Wadqw6yXi-R~s1KAPRG$>|*0Uhia%PAI*( za_=;#NE}!p?^BUOhg6(x-Bh>vtdWe+gbhB8RAiu^$d{sWA6N5`_=}bwu4?k)A{b}p+n!6=P4@flH$>&IkbFjID1lwV2EQ=ihQRpoEW4R6-HCjS z7J9MDh>UE-YsEnFJ7;*j);VMP?!7&i`Ucu8MxIn-i#ybh#Wp)bOiS99Jt=Mwr;Tdg zO!w7-;*v$loLI)UsXrv{7*cWWLkM!}aD=m{?<_=3^fs5tEatDLMduq0dE(H>g8C{G z`g_Vtd#CK0Ec2z>_+--am;Oj&RbLiFbI?akZMCH#MT_XKUw^IZ*_;bTRZ{hj?|vsk zSPhHmY(C7wI5MKNCT0qNS88d^>V|#$uVIT9f${^jsJOA_f$%iW1dMtd8> z%T}=Va*hXr&hCA{C29rQv!JtDGb_fscyjW79^M{LbE#1M+I%Ok8J`9XGVL75UXh6A z(`I2i+dPjfZBYDn)Vdkz4PB%pUaj(`tj9>$@ZuRB^!IFhwMaVf{h$gf+xpv_M>-Mq zwNSf&IyAmqD@bs8p!~DDZzBPcYsu!^00(-dX>to4RK0oZA1m?jeCjjaJkP+rKSIt9 z?4Wmtr_`AwurtdGfg!l|?(B2_%=2RAd|?u5bp-k`xtfS?1)rxr5NdBvX}gJZ5X7b* z$f}FVIJ0FGd?T3+N4?IN=Znc$d>9@heO!A*TZ4Q6&diZJ;#AOd#s)QgYNP{KDt_Ce zs)cbH^m;oUJJOAM8&;VI4G-P#N`0K&p;?&Nr^rxTn0j@!CIgI2$5oX^%?nmbs+q+B zekY5O6Neo|H2&3b6%FF4E(Zaf3JeK1J09(>gsO>GbXzRB8`5NQLs}lWe2!YGoR&cuC1)F?Vmof|JBpi*A5bLGDodJ zoQI~aE)ED>6HZjq4~Wu^7^_nJSKZu822By58s6Vov?O6*@MA0GSeW-s-#gxk-Md?Z zN@sJ`EfWtsQAlmVCzd~MpFCnM`sj)w;0}g2uMNbsWfubO zLL%I`IKROOVpW(q>HI2|Qlsxr>-?7&(7F@u)hn2Hv0Lf&6tm9+lg%^YPon1rotS%H zJN>Ux0ZYm>(jGr{Xx(GGz{vmZ3B?nPxkvtUm?(bRyFw8tp zRNE9J2-}A4PuzW!sbFHnhvN`nsmu7_UEvDVT*?Qgqek9$oh|n>>f9*Oo4;u4==K`S zlBQO_Z2EWX!w4AA8l~(YBE^<-Q0@6nLETP0oX5^aTTJQXDJXWW+rr+%$Hx~h9<`PR z`u~k-AQ;5W9$MR8TJkR{;sw$sZ1L1PU_k{IAjcOD4tuVzicfTszKPB!z@q4*P~*op zt_E;ZPnZOA=htaiwV<&S#nQ@CfC-M9(e@-Sr#Vtpk~>>k3p#o6q7P@ZYo_8#G&ov1 zO#6<~-8Bep;wg~-%C7A67~8)~rj=`Nd0^IhKoaWcuyTu)S&l8Crh}AU@V&2jL!>I% z7^ES{`{)0vyxHdm8g`@u;~O@tWwqkoxTw62+dm{me*1)->3epjw>4SSyYAK%a6{S5A1Niz^0h9oKN#&f7s8BjYNjBlE^ii z!j+)0=C7HB#c8?VD*h>+NE_bKreG2N(aYnNg1UOY8l+hCrVfElL-^ktO}a{~rFV%k z1;V`h?!P=5XX8n<)rTv!OUG{jIWqPwE6eW{h}(Pt(ra#mmkVvItwlTAwOODo++2Aq zlAuAcP`EuOcuc=&9Mdd`g&HQZDkmt9;(XKl>K_KN;;~aV<=PnW-s7WA@>z(gqkYHI zbp?ntBgggX$oB^VE1gGQ7)fwx80gIWdKxz!owTvRfBLsV4Tk!ro*b;i3P0?0G3#A% z1PETzx7&ih$A9l4fRoWjHaO(ly10MKo_~Bi6&qQ|N7&gP5u(`cI|i2`Ony$W=0agkz3oN!oqhTSnm&X00Fatb&l%{^dCl#AkMghAP+u z3E?pO4~cMAk1*GQTT$+ZI)KDydx)O5^j&5>AQ%3JW4ID#f-}8ovS^gjJqiu6E#qT{|rD@|FEx(pqWZ zcA;MeeOleFjFtm|$~LJm{hz}Bo7UMyW2MQ~B+SN^#VAn%El ze`lwpb<38-QUxhoWLzQsb|6zSI5KyTN_L_MXXBZGN zS)4v>QryW*{_a!9=|7C)8q0r)9P#xWLl4E5jN}q4HXq!;@=B8}9N!Bv5boDMU`T7g zjuBM$#XAW4fRr_7_K5fP&qcV=d3fPFI>rdTpJs3WmCN#EYFf916Ry#GB~oDJOl$MC zkaUZYaMH>zVx)i={lRMb!|>8;w|3mWphhi)8!l}5n-!#`JiL6a3CEl!Xz%PCAGqiA zukY4*L*p<2!eMCXo~`iKeGzsyjQlR;bx~OrkIKe}O3z>hc@yq%+OItcRMTontsFrQ z6?;>`7c~XtWsv60+=&Lc_bf7lQp})|-g^y`+*|JNzgRIHy$G(t>W5Pp4kzPIYvVP< zR`8T3mfl3uUj6)ec&iVX={o%v#ThEz_QR1EHxENnv!G6Cbq3EZsOkFUjuxA#-&N*h zP7bS&DS3I5OZddhkG)j=8%WUEn%&W{?VbesT*G7dEVDz=gV~>F25ZgggvP`>R>vYnlbOyM;&7h9fkGPfs zP@b6-=uMEq*_&$IVLZ_%1_xBe#l;2VS)!!p!?V}?&g`XV_kkW3kjh6vbzs?3^c9JX zj{r;w(CEM+kWPg3ng|0KpL??xPKuOZEKGcrtNq^zre3=9Zg7A}Sx#%^KUfq02>`1e z7sn#A9*FGun3N}J6 z1p$&UPv-H`J=1v4$#PfOcGd?EhWOV(Ryh&S=0`r47 zZhT`IqFoOg$L>@moDlRrmSnOW_tDnAv$*(k(>U^u9v*3^0-$C7du&kGEyw0+G+( z`xDo@!U}9B(2flo=&XPIt-L&DKdx@{H-Kv1K66!$kj>%-z=rI*)#FE7R6;w098xBbZ0?(j-vj*$8aP*9^Mbtt1%^&2Tpz8Mt(h% zw$Ffo^+cQy{<^saJ*`Co&wk#QE^U$u(v3F#9gBzuK!tq7A1ZCSo}}YUKs}dkku}Q? zedo9VCPb&0b4#rUBK7f4#V?!JsL{}5&B@cD9TwqpoGL*9*qPh@dmHdj3u`1abstd0 zR!5dW^KJJ~PE*KgH0l@r)XM7ao=v)>d_?5Y)wG7`;S9RPY_nMvq}o zgaOetLMe@yZwXAyhX1UVqwNXanYcad=6HJ1=i_Cl8(cvk=F|MrAe3}Cs4)8pp?sPfC+My3@qYuhHH}pS(#*`hVosoFyScd~W*>yPjo22Z7s~cUNgsOX zY%D4mBRykqkX0w2fhYxJ7M4W&p@3fa>wo=DyS&sPkRRvyO+^9V>vw@vG z#P?ZC*qu{p9&UOhG%~MhdZ--wwi=QeDDofbk{;3r_ZCBa`dN%L^u-I_P(|vNLGIvG zN`24ZD4}Y``?0`bnp<4^M2q*MCgVVq5?;=Xaf@zY+S3~;=Cud=^v{-Ba@Qr|@HwIO z&sSWZ&W!ZOSFIPEe5FbX`w!@NG?2p6ob|pxLM%upSg6^1g4^b9kQ+%f?Y}ygO3Q_| z`lbUP5B%O(?+4tdKIyUoIK6Ar zC17dn-n3)Vhm&7zw(Z>6y`VFUU`z)XLJ{P~a!c&>{lwf{N?QeOA0{2Odx>>np_Y@g zjvF8j%Mih$ z-keRVPcH9*(V!G$lj7}0h3*~g;@2Q(ThEQT2{DjTbu+fvb2IbE|@xSxgx9uwTKmXX8s43y#ky7Ex-yiRiuK@A#JV#-;j-st;7T7?dRUujQ@80Mh}XI9brUanesqEk3zKz zD1g`~GSB~Q{g%G3$8mZ^Jf@1OsznO@kvwiDwV!4E1xP=%jq}uoF}=)Da`WB+qZH|J z4#@B2voOb?-bKjC1tjV7Ta|>2$2wGx4V0r(&3ii3qRt$q=}t&qSzum$EAij&FhOV% zxW)T~G_Ic`z4MI%jJCEg5(tqs|v%?wr%ME4?8IU6*&%@}ZF|rju zC>qYm>%}&~s18b(0=4`#ld2fMx_*~%mY#UU?VvJf+j`1+J{8@K2b_D)L2h7T(qBzx z2nmj{Oo|b5YpeAl71}a{Rlk3f^vx^_CQG}p$&cIS!u|Qx&`M&Oo`s%v^z4J zj48esge3bFX{1YS0K2C`dQe~>U`J&>T}rT{j5g=g1t0^nHE5m?*$s&?zL}(0CKdy* zj9K6ElAcvb5=``iIJiy9y7gQGlQ=VbJt?iv@31dvpNn5sN~g+e!VWL(86A6i2m1{y{xGG z-eIl{wbzb#-oKBR#nb$MF_0@x$;Y)Z&8eOveCB)YcYJeFfEY3(dSw8U@U11)Rdp9)D(-i!qCF-tZ?9p;ME1?`$fe7H9ex|FEbs6;UAQZ zL;n;LK#cZ?5sAdqP*FswOYGzLM?pAXbgg=Ov6lJh)t?sPkygc+Iv4)2UCHpkCB}}T z(`HoV&8d(229e{35PcIKGiA73U17@4r483*ETx`q=IX9=yXz-Ut?D)DBvSkrhzWyy zkQ5^7Oe_k66j-vjYM6q5Fo9-kQibT`x}4ZNHsN&4Y|{u@%PcbM=)`>lFe zxI55hsBg}_ShN&;Gx~B1F6jM+H`p4M-#I?7X7)J$Weew7MUU4^xv^?~@uIQ(qWOYNRp*19K_!p0PiF0P5rK))P+z?QU6inA$fwl^_&^)w zxp15`ln3(#vZm}$(hnt!C0PV`e(Z`oU;mB>ft*xGY1qkOb|NgOMCS z=&eQ<*WBn|#Ltwb(Dre{Vs*XYF?f}UxpK2S!+Q=JtH?-VIP2ouI^z=tAA?e(J`7V# zrgG3g*1uo-*z0I8M)%>HAc0ijYI!TAFb33LphJrjWMtd?<0e=$T{G8{80@3_ z)vm}V~X}xavH}Db@ ztX+l|CE4N3W37x}FfxH;`&8b_6FZS(0_;pM88 zC0Sh6Fp!QYTkxC)#PBupsp1fxM>;ypJT!Z(raXiB^eNpJo&FDpm#=nu-^8)R%4WJv zs{d%Rm^~9SDR?dwlbjqnJ#9!2RD%QL?HYBlG!yr_In=a8s0EtZw?o)`|Nn%S`;dXu zglw@<{lmALJ;k`27a25=xAbYU?P7vhj=j>rRKzxamGJ%h{xl#qE87T$?cY+oc`BlR zGn{q3i}5E1u*v5fhM^pB6x0Gp=X;h|s6@8kZQ8EK3LNUZb2@W1Tmpa}1C~RNip$V# zvxS0;Wl>V*xyV>eCM1oMtoLX5JPyaD=i`V@#=5$?zK0p#K}<+B*!47>J~ermJ2e|y z4*J>)76X4VY+}4jySdn%P~oR=Apq90n>WDgXc&@8zX6000jB6#}3jfj@fUMlJt4a?y~J1jXX6-Sj5BERZ<(Z!hyMW1YFfev#l!0Wyzo2pjShz zHuJ@Me}C%Qyt46dL8O?DTO?4#L&TAYvo{I(HFX0>tM@PA9?6$Np;yC_Re(4 z+sW5}e-EhA1=0`!>SGkx|9RD+ffo3mxBd69062DI z@Gbt&1JeKdhO-o4<=SMq#q-a{pS8Ag%e=`QBRku+h^|NTwf;KyzpJaQ4GhSgcKWhX zP8J(oIEdN`3z-@&x<_ubw_WCeTOlcyBwjDr+wW1Xo37>h^_W4}>!Sj5=N{LG|KwFw zq5LWe3ipb_Ln7W|HS^eXDlyNBDJ0=9Dq(J|I1u>#Dx$mjdOc6#av+hawL#9Z{FYoDp{h+^BYZ3R2F5# zz;E6iV;yNepo2XFvs4Qzs#}5p&@nR7($M7eT$ZWosL~F-&bWWNHQu1;Cwldm)e0E) zsxaYCb8HD!FOIh0_G9?Di2K+S8Jf2vU-h8R|t+($mSa;^N|#;`g<@Ya#w2 z53P6}JJCd8DIF=hJ(9&0GjFf-=x;h1OI`@8Hx5aG|1P-t8Cs&IPxj5do;^UD&v<&J zuzP_SI>7z*?P^`fkrYEhJb1-=nwmjBf4)9ksITbu!kukN9|&TwVGKDVGwd6@nCa*Ylf=ki%eCQ_rraT|g<7YYmGBj{J?EnVH$4 zGdLy;@3`mZ9Fc&U4v+V5G4HcNs9?l0QQceh%#)Loo7UFW6hB*k=U0i$!^FCu z>iBrebQLKvB3IkvF8Mis`4e|D(nx>M?hD7UF>7+=*>f=B7Pvih5S$2ccY;9!@O(;+ z3n6jw@iZ&fCwy_|%Nm|$X0NRkA=Rj2fTneEfVjz7r+YS=rucnD47~;W$1pL$=sMXB zcr0NU_#p*_hPpRcGNzoO#Sq(WLKb-@ofgSKkN2rh9bn|>Hf-|quO-AIlIv) zR>NAlWX=%Va&4)zKF(`xgm=r*JIuk`xkip|Rb>V0O~c682j3wAwAiW4!SzQ*N0&Jz z$_-hQNF^C@dG5Pb!O2#MckHmbnaMIuI}1~(&QiZ2z1!luGRu@N;NDZ#C`x?C_xTTD zZEfvKZQIz`SjG9}rNy)jkEQoWe>|<2>$~Vgjpi;D6y5Pz%fb4cr<=VgwzXvS@3R*ae?b=;AiyqIVYxT6E4A9x#};8@vnX7o zx~2N{$1$FeQD`A#_3OX7yyPVl;zd$T8_Fs>9m^CU>kh$i2`^}Ef>%I|%vrvp@({Ut)AhQE=AGKt zu8iQ%XEzsb+#x6)m`=5!r|{xgk=jlhNA%{iEq+}zyEGzhO=z52y|W7{*O zDyH22cs|6t<*A|)!wK6%#-e=0>T~iU!`Zy>5LN|VqN1ah%wrkbxw1HMB6{Eg`V-dh zs0Q&o9fc{gXwmt*_|z#?$2P)LM!2nogW!*VPZY(!1-2P0hmu=kOO4X{9cf+B+{#2J|N4{d;1HLmPR$gY zJZjJ%T4a2+XxelRV}h<~1$R;r9gqKqe}R4;Z?fx=;NvXRbbcF;`q z@r9|z0s(-HW{0X2xO`t=nV%IsUtKlPhZ4r{GAN6zB}<0Kyz@fJT|T@!zyNzzWc!3w zkX~7cLeag{#UDGaynjfWrT%~G*hfCmf>m7BHO7Vh$Lx)8tMGi{Hn{GNCmUV2HAByY zP^8)Z2JJuqqeg9~w(NPkN_t_ejbQhHVw-|VZuesYn|T3uz+m2SjxhZ61>)j6 zu)qPZ8eBcr=h?$EseQsBwc(JaPW%xKt9kc}j!|fdVqEhP5e_2#8V4NUKW0^mH%o;^ z_2cv=6^gdKO-I=uXdP{p-ofFZ4GgPxCVzzU6J6DY_QXh> zfBycBYdcroGoB-Lw(NaEBPd9!S5{XP`kANbr1(^bWxV_ga*c(2Lsvq2`XcpX`E>O5 zpLPkmTc1j{13Pz^yOGf{!C7V&!bD$7gn{n&psf-OuIv#j<3AEx`u|xmW`IxiZsvc znN`c&Uj2P==zMUYNxfqRN7V1QfXl(3^7Nv!+%mz@caBH6!3?jXeP}3Rw_FOBApmR$ zDg}YyRB~|ONM_fcJ=~(CoJAS@SkSZZv10!Ej@NgYoua;{->O`{gCsL32;p0LdepC9 zbRZh+-0J_6V(j-`r_L#D_%~ZR1sXOPnK!+FfaflFrd}!$uW2C~nzf*hkL)ol;M{BV zdulQ{S#I@xdU{gr?d>Ie*Y{CdzfVT?QazedL~w7t$N1z!@y84%TZ_(){(X{Gql!5e z_43V2!H?EX0uLLM|Dh1Wn(#J-mS)RSZ*WLZU8$8Zlk7f!4=17G|7EDQ$%t#c>tS>;@0&g`@o57n zDJf6S&%f5E5Vf=jtK}AkBggp`NIkKy`AG0Y5iQH`IE&+IfBo}}jCeBEGfiMD#byFP zRvw)p-6V%ky0BSHC_}v#nAqB!4snmwG`$-Mq15SxJxlgu~jxA+{ z^O)bN+v@#3x6TrrEKVFlEQaD=s@ap(nDlS{?=+d+wkRaM=Xo$yV6YApO!{rPD23! ztJ63+)lB|3=5xm{>>_UK(gl%s?co)PgyT@LXQOXT`%e(vX7`HyrIMRiqnu1RGjnrg zN3Japbn$zhTTC~(9W2l6xqiI?8&RNP^Oq40cJ|ihu8CO=Sck1lVO7wx{Toq!V%D>? z4Wm%{KQ9Y=k*5b_L9bSXgQEKU;`Fi@#>RH$${4jO^>*#DhH@BvRnT zfv6uH!N=t<@7uSya}g10dU_FM`t99^|FAYzI|HYAamV%G=@JHl0G%SuL7p9m0Qbj< z{kxs*ZArrlYp#w&7W%|NL8hcDj?k{M<@QhX;wk6>AhF;Rj6uPYYk%IBaB4Sf3bIWO zlbbpq?@aaX6{o|OcpWd!Mkqyxo72*=XnIypwD0Z~4I>%iH9>|UYrJ5+JNg)x_>tdO z4Fh*IwuD}x`sT!fNPMasC@4U-sRb&s-+QdEU4qTZ*yjwfH}=KX;BO~mHw+cy{#c!w zr9n;+!{bXr8&qI?{BbDF=pe$ReinLCymL}a<5X}mXNFMYNht2&aXSk(Z=|fDA;k%s zTB*%*DcpFSKb9zgQlXfhSj1c=ADo@f{aIL9kGu}5Ek`!}79Td&a->4p-&Nitmv0;E z4iXSl0)@m;PL3yS)-*Jo-X1<{^)J4*jcW_hWNf}Z?B<*O@l*_SbN~RJB|a%>>taUR zm>m(8z^EES&hNO|CKe1axf(rr`J#AW6oU5wu51>1*)@SezE~u2X)pC+sr7i6xHWI& zqETjju+lEZVbCxxuVZ6tiw0cU91E3~w=T}Q@`}71@vZz<=g{$P6D|{QR4W;uwH(u5 znS~S8=uvPOwxG0$1G$|5mMWIrQWJqN<(Qy*+l;p%2xUc!G;QJrENH;f=puI%jcIt?55I`pzGmRf%Hlh5IU-0zWMnft zXX#IWPz6DPE>C#Jgoo$M%J{Viw@@dCyiHU{Vc`_ zXLG>VsFnVw>Z@DGg*d-$_p+;6diB)0UEfK~%muVu*)jM)Wx1jZXPj~iy4n$tRhU@Z zN^2GptI3=MDGi?q4GGZ-2@XzTO&YvNN=m}yL;b*@x(3*Zcx_5M9R95mlc&Qqh8x6@ z>~N}4DbecZ+#x7wTWaXc`LcXJ3|xrs=fhut3&nL7IC63S$u-G{{^ZQ1T2dV>k4MbA z_U{+KnsGYce6Oj+8-(Hw5qGN<_<8x)JoYK)`^+VYy24&=tVqO6$(+vpuhz~cfubWLhWA~*1<{)8~-p-YLw7i8*-{gePg4e?Qbmkd~Q$k zy&>;>jt^1)6Qe9FEvL%#>v{DG`v#8`JYymwX=P_oatHsG-z@9xuKa6-d}dn!{<1x~ zoRGE0Dr(e!@FJ4|km?+Kl6#YX;)`ECJnJ|&VSR;Y5*AK0yF-BvM#aZB*3w+B8McHj z7emMH;9`bTNkP#8dt*@`or*nAQKGY-6PtsRf zO}xe@B&^fdBiCJ?(@pnO4&dg(LZ`@L>wMnu#ok{FHdbAdG)C@OF}gb_99paE(}VNR ze>j4TwJQo;lr`yFw;wb^mWxoNyh$No*IXCVh0yt*LiM!^P0NsA&1bv(R<%Jk+jx#$ASkTWY_8aphmdwhyH)1$Fm!_4L^kc)ggI-|06+yI%GZM zf0avz1`Oc;N|TNooB^`c!1hSm&Uydz_I7ylogn23C_RFoC$HUKdmqcOOg91Fk+Ub= z^X`9^4SrAe&EMLtM`N46w_oRn3qCx~r;RPOHQfDJJ3tkOh@)iJ<>rl9!*@iti_TUU zpZKBpbKlaagu^w0l% zp|aeU-f0%tjl%)>p1raYdFS{4&Y*P6*V-N#af1Y@VR(30mNim2m5b)NBLJS`BdBa# ze!lzm?VBKiu^bXj&?O3njJl^lSy@@_@!0A#ZeU&SdJ#p5B1)&r?^aKe$pNXh9Q?tn zhx1JRcjj~usXNr97|g7@mMMMb&!0Z^=%%FCKDt{s{sSp5`;GmQRYBuP)8Ic!AN!@Z zf0L{RGO%Anys!HUR5I=@`9@10Dpw}TFWr|t0?u%6-+EQWP0iWdfr{e;s5mZs3hi7# zhh5{NXg8*B(FSo5vMMPuZwcz%&nucNbOV*V`*qgzLA%U(KkKAXQE2c1tunnCtG-G^ zG{XK@G}(!`mSpt6YTFIeHS>ECGpJd(HbLxE+r*^sgEbU3yk*93jc@>%GrUkiLR|a5 z`#b2Mm-=^jvI3xE;3#X`g}m#S1aI@AQ_&m?on+npsd0<;1r4a*fA_+;n(zYITn7gl zS@6N`2Zzi;^44ejo_3KaSaRD&u}&Sbv9t4AkmZv%FM*6o~1*zdES$ zy!b3=IZD26L5cS1t!{H^N~_1&dSg*hQMr~CRpd@Z8=jlT)Q{TXTvMENqHmN$A(vPi z7w=JWi%QIUPLO30N7*xzKB zKi0vYxF=4A8WQ}CfeSI!J0YWcQzNyd!7SgJ~yU;}wRnsAJNVJ!8Dz5E#4V21onI zpz@M$_NH*o_FIXf zZShtM4u>1X>ZV)oL7l)Q5mYLO*mPhY3REVt{O(_Y7Kc;vATcdq&y#x1P_cc35~ z1wStT-&Ii8Mtctj?u`&8u$b=XP+IGiK#rvh%{UjMY#e@TrtDv8{N)H@*5&j^n-%12QP!92V zegJ@E!0#+_ynW5=yeeH1?dVg1GH=M#$vQSV5$g3S_#=^X7-M%I+Q#dN9@Vc0jdJ0$ z;sakBV@cM*s`R5=X3G6&@wd`+MA$yt^8C(hptOL94e-lR`o5u}S+_9wWz zXql+RH3!u5p8N0!_B}VAQ{fih9YXc_GI-!h=l;gfR=Q`j9@Q@-fbwtL06u^pr|>k9 zZY30v9EGYVov*BprGK{4>Rq31O3Z~G2*Q-L-HF`j^C9(ArF>z^Sj$9(JfH7Mv$JPx z-}d+SPvGI!fEJ*G`wPEH2a9FSLnUI0)tRhK)&K#HFhtl?K&%oYB)DR$ zj1kD=ru>42gHHqF1K5%VERbB;qJTK~Y&;r^5_;7(Yn$;Ji)@R}p9k%`pV0`}toZAE z+ihlwJt9rVZKA=}n79zK_gxp&;Gg+&aQyqne2JRIlc&z%!Ni4y@d5!+Tl3!GZyJ_& zOnFWqiR(@ma5)7@*6Q$gZl{TfiGRu!IFUW)pzI-pTM~QVb4X;6iHBUl$pK5WUbnKu zLZhlO_{twp-YlH$a-jdO_a-9S2EHz^Bvqnn$X9^M;}9~X~lq;R9ekl8UkJoAN%>!2!T zs- z(9w~)b#v7E>!j$ikwDF)q#hXwskb0Me=y^gg9^y>Ie)JX>V%)Qw6qH76_YEWtyfyK zhMl3|2F1)EHdMFAIT zKcaTGx^2G4vy?BP!x((KO@StLg|e?NqBNU9nk*Q(iOGT+ow$;e)nQl203pO<8dvf? zlA02VXR^k9G~Vkc5bZGM*`mZwPkD&LkiAGvG=A48fAws1>47D%VNG(@y{CJ}c+u{r)9G zulDPo@70&qXmR4c?R$B=_4$Q4G|TK$lxucE;4?`nJoeK~q;J`?_kHq*-#S(A|cDYFy*RMRB=C zq(XxwNkdyIpW>CWh<~*QytVZapM0f=u)hMc&b50qrO+3)7)p`-Z@2m;_$UYrF&i;& z(9P{~aj?yNKNuRaW1*ubf*nGz$wfk z#pcdVE+{QCadP%GpS0O}Jsj010K#NsWDmNLQRD}*bdv6GXae>XTkulYYy#Acf5@w6MuV>c&sUC?cx&XO1@l8BQbxtGoX^dp^Hjbd?VWo!P9M>l@? zU?f^BCN6(nk&}NLumiU#h zz8~o2)J^U~QZKzk^!4<9kPs4nt|8L3Lu6S9+~2p+H8EKY1i@ZR%|n}DM)?@X*9%6| z_+l|Bg;N15Z2$kSF8wxE_#99`oa+0qW6uyG;u zuPrvDHs>J<10AkKlqhyBw6&JhX-mGhd$+y|mIDE;BfMX<9Tq*ZMHMb3B_(s4EGhAs&UB%Yl-kx=6V`I zQd{Wtk)fE$YW59=pt5f>@qhM`e4d8wx{$6>DErhQ>CbF{5L>dTL%0hE_)$B~{_`Ae z82+-HXU#goHu=DaI>=`ll?uWI-{CCeV+^k&jdC}ra&L#G%s;$AVP@f$n1#AHMyvbUi%{qLns}UE3LB>Ec zn>Ajyu<9cbkc&cd0eM6)aaY`fAHLYt-#w6>7ne7mKu}bEb9x#V*|Sb~*ENVy#Hm-Yo}dw8SBOdThD>_ZxA4@k>zP! z#Y0eWCj20D^edlVTAv;XJ21R6Sz!(NQ!jd_;v0s#c-f85FYWO2f*;53pK5B}&1 z>+?<>9@@pZR-5{)vO|>&es7VYh$zT zfZRR=SJ)5Q7h;#=Qr#fC2~AaEcpWd#W!i;sxYABV-beH1O?=z!dL$hSi-MSWZxkgD z4^O?TprK;K@Uz$6V7^3P=xwI3)B01j&vSOBh?n0U9+mHrsBR}M1=OG z0@bW;P-(Y)aF2ci)_biY0u1@WwOt1|fp{#x7S61@dbKTKrVV*qn51_sM)X74miUYe zc<{$%nga|!w}J_Xflj~+;I|LGsM%`5u36+8=xB+`ZO>a+rHORh(Qmk5@6!h!fr}`3 zL?Do&O*gq;N-Q$oB5m|7paHb&mOm|Ht|)SiIXM1e?S}6V1=5Z-`;>r}+D9?l1knI` z&MCkL)g*lD;&-y&DJYrz3&O?+S#lXSf`TZ306Leb9wE<>hM2F^`yyO|YTm&052Pu+gbRTV!&7LLE5T z(9pwgss!fzpQQ^|+98WnaDxy}MZ}uS3(4qNWYo9lQhi4e(6Yb!pB?RxD_h-TE8760 z*);xNI|QZ%g^kS#YQ-8=hu-xLOHEti-@T|{md{Y0*xAfwLQQq8zzBVo)4Q3>E7Sqe zA`A@q-Ndgk0x8PYv-->e7Y+L6S)ONqpB+|@Azj=(Mws`-_R=m+g6V>b-HH&dCW0DPHjA*Z&+gwUbH%Z(Ew@>lT4@e3gm@i<5H2v^fK9?>0%HJ; zJk3v^@|Fboyl0iJ`&z~P1YLJ4Gm*5!?rffu3L1ZYEda#PLokn*ZY<>G9eHCpeU93p z>=iFxat}lXM@Rrp{n8v}fCF-Bv+eE8M(K?Uizhs@;~jiOjoYDxi~+M5x@yt7T?Y)D z;!YyA?kUPnM-WfxU}#)pY7MhN`VME$S=AohWC4V72B&P44;#QwHua$G$)Xycwox+# zJGxGUy?Qc9h5k-s&4{>YG*lo%qLu&>-tW zIkx}Xx^t$wwxUq52M(ty#59^5zZNN3KJ1rD&o!p?KN>47wjXUTv?(X8Q`Nxy;M}*q z|7Ig5?epTzGk=^VWkS8WLx+1GdUj%+Vw;|T62k``Kw3_&-dcjXH61EyFrHt#BiLq+bA+9cDgNo8j9|-brQO>Qh%Y!eI$b&e zvUuhzC(i8-M{DyEzlGy5_Ua<8@FJWHYIJ~0@vnk{zBkqLmV3+B+Yj8?*_-*IzxC^* zFP4pOeqE(YblA;WH~4P#^st1YPTgPC>|Y}Neta+{JT~%O8QowU%zSmdmH!qZ>X!%? zq}H0bH7Jlhn7#9;FjNyF&p4S1hAE*76rhGgzM`IKENAfQbnNSUMNRih%1>`e7?Tu) zz!l^7?(XixLLfH}&y@)X1rxyPAj{wabQCx70WPoM-7O%QueEZIm`3i6!()Gz$#I1J zSFX!r?!u9q#dJuvOF(EH?(2!>yXW6N(IzUQZce4 z+b8Gd#uMC_R-)XnC6EEvF)>1w5L94vcY4<7nI$Ur@D~XDA&r1?D?u&2LBFPrxxbTe z!sae12?xq?E}pG-LiCyb$tdD|+?2yrIqecxsMY+#%eM)~Nb)~_{(PpCvRDEY`%_O? zXc%l`*xt2u*6?Y`aRa(Q*+3OQ=J4p-@dL=~Wx01abMKCB=O(_P{ol0l|BuRF5he>F zjQ>&jN495Y9b!)WSNtjYtmL7dJLRTlEM0=)~A){g`o?&xuK!+VVnJKf_H*M_;-~k`5o5Nvu>O~k397%(Bj@~Zn4Nx*ei0wp=c_p?T3#B$QaxI# zai}mq=D9I#TMQMi9ZI=TYfO_K4^r&+geBaSd+3%EK7xqXO`@W)?$>?Qx{b6kF?j0U z%nN!G;(jr|9rn!~V_6RmtS~yCMYaK`lT&;bMV5Mw8cMkI*RNmUTwk3@V6UJVHa&D2 zucN7&!F6+Gr@tb_p>nI=S9`PgY;fN6m1kOCBlHceSLaXyR!$Hk3zIzXol@fJx&Hk-JvB3y~c0Umi3?8r8`1#5O zi{wBzt}+2x*KZz=^))p$S>kMPJ8Mzk_zL_n7gv|(=U$HcnpmmYl?R2iLS+-5%gdxSil+PK=G-Mfpl%r^{j;1Nyn&3G z5mcHqzAI_1!ewQ(x4(P?V`$Lx>M>EWXHb1xY;s)ddXu4YQ?A6&yo%EI{Pb|P(N95K zeX~peM!zaNy}Zo8s8E6BXu80oDjvj2;?Xnn^>bKX@3r25da;n#-7I5DodQ;vw@Zl*p8`KX{zaMz4uicNU{j_9+>5_LI0A5kfJydQ+_Q2MhD? zC5^GMsL~sCqArMD0xH@TR!#-_AXrf(@Y5;qr?Q>Fir5HuG+!>MJh-_z-6xAeE}#8@o@@C_VVYpiGyK`t zsOfnWHg)WzUMCihUzoa!gqyycRkqw@H{6~+WAQ`r8Rz)jJQWmB>*y_Oy_9{lHp=9Y zZofloCHo|Xeq4OCzvCp^3Kd=cs&%JTZt(r7SFs{QDecXYV!_n<29}r!7!WB-6Z7{Y zhNT@D-drCoq*S`>j4E|B@*q3AxLB*J>L}=$N#H@#vMWyYBGgXxsGW$~Ge2v^NSpa^|n4j9Q@LJMMya z3Qhg>3iWUeY?cjHq}Umu72;$jsnB8N*O z1cnDIn8)3aEHwvrIZdM&tm-jidR%)%M~13 z&)C%@o4vBSe0u#YySxo|D``t@dg-gW-0Ip|!0M{baJpZB!^*$a%UXg$z+eQR6h zSFXlnm9UWtgTZ_x!(ucB!5s1p6B84PlA_{JrjWY>kv7_Iu6M3qx}kv6vv{+N&}>28 z#7?F+$Fh$48vahKfWRb}D&n9ZBS6fR4+3pJC+?GGC|usVA!h9u>{6edjF1gPXnXX> zleUHZDv@_QaLJsixnQuWe~{(Zt5+h(a7+em!paA~Zg(&#`N#Y8EQNb;6F+K+7Zu7} z_N!Bh`PI_c4t{tcM!DEVEDP{8-LrYl<)+${3kh}68aqAun8n+)yM#EFhS8p~-6tmM z_I2tG)KvL&`XMR?>8tp)j9IIX&8mU72%VZ9l=of6@y5Bmr>z8-zWy0XUoHvuTtp~e zc0Tx7r?qc%b$5TKAJXo4$e_Pn3#C$^^4g_IL7yND^6vue2rQjgkX|0gITvXbH-P&g z`lDrOy{`6yL9eHCZjJ~{KQ?$?Fq9iMhotdAC;tPB-rn9q>8ju?zxTaax;Yz6Vy(v{ z<2^JlsRD%&qTzIb1UhPq)-L63pY7v)D{XiHg2 z8yagzh=Ioq#RUw3OPC5&d=egy=Gwf{dPtNDJ??o)Hj(g|^hM3U;(Duk#Kj4Jl^>J5 zuhZhK1ZOrEE-g9|{5wiP7+zowLuwHI6%xhtV3XDq;b9(f7N>-X3ANYFarC%KE^bY99>HV>UX}G8KcjOKRK6MpZ|=2mOSs|IIDwxq=ouVe9!I>lnz$ zxr5?Nz@9@foF?R1lf#BKTdG^V1@my_1Hr&BO?~uJuh4mwukTf zji%4QDenTLvdYLPedvVhi5NECI6U?CS?0B>Fe>>9W=6a=e2ZY`ew4fLc$8UhD{*(` z)VdthjrWztLmg==9p&^%DjoMF5E&~u)cx4`B5O=^>gXzk$m}Y_jYv*b?#AF|PcSxx zuq|T5T-Fp!u*ZsksphnKrbj0bx!5_TvYB2HnJlv`abS}3Q)6Lb_Ews9>x7uzZtt=o z2Z)2+1aRG-el=Ha*c||myvc1j>RMP1N@|;S zPZ;Cpgi~o7vInP()L1N{^iE)$|P_;gww+@6&o(oPh?W-5O z4Vc*L_(?9@Dd4(S{->b6%P^?S^jZ=O&*#03v6y-Y< zkdzaYXjhEFVT;+FuJX!39s}&G6;N@4g8q~lwd!%8yb5<=z%{`Sryf73@_qOc6cl9A z`zL(X3UKR1Y4}hX(Wb;uZGY={d%9LRk()pzJ+vUZU>20s?k`5!y-M}|ePP*$pTF}- z;UH8#ZFlt8DAeCPvb8;KL$y^iL|42$q82Ill77DSX@2sr_k5g{?cByy$ybEq zOS8}Mn&o{|a>q+a$uK7r#!(w8#b&|JAG+DxW%pA!>SNt9@?(Xiu z*t4XP68hlKP<&dN;*lFNSP1_>jgOVeV-->X`oQ--k7s?7sqX9}2-p}GNS0KcEg26I zsqVt|NzfhE3Oma2b}`+ILdJ4s`&W@xsMArPNNhr11N;eQ^ zT>daE6MHQA2JJ`$ADn1H+xl^uQrU26(tQ)9j>U+a|ChZ@H?x)B*+A)lub=tjykQ(HJwFFZT2poo#YmCcu`re7faJY$y5pAnj+y16z9MPzDJ5B92s z6nlvbDjYbj&Dr*kh(vz-eNHG~ABn18AUn{gc>C#u#=_wiJG9P0{C(#~$7z(9IHWcA z{Otv_iv{?sF=UuN;BfcwkmBL(eL%#n=Zd=xF-IS^{j}3O*#3Fs$27Qi01%gUbPUT= zO`pq5>Snp0m50Hvy&wQOwKfFhiAkp5oUfFHKR-VQ0HICieNZX$c(8A|9~Ht_^F8oB zsJd#UUGr!C{TtQ#!&$w^=pf7EEDoiZ=u5j`Af+%RRyzS^~Uu*tAv%@I-L5dyr z<1I?_jYN;j4fV-EYzNl<;;H(72lB%mp(|cadu0FWBSS+A`WTH%Cwf-AD;%d&C(v;inYn^(B3<#i-&Tks0kQd88 zS*xb0i7+(#M+xKuZ@IbSQ&Ny?^)P}Z1HhP5PD2ARpTnYfETsteu4$H)7S9Vxe-L1; z#70J5fEDyBRyOypK>GCn(rJ+rgFairz&`MZ)qx@z7N=ojH?o&1=Ks7Q#->v#z)KfY ziAH1=)d@>z{xShB*ae^7{#yX!YPcP}pey{FZ3x^;f@W%JY9yOmrF)k3&KeiY6o5OU z!JWc#;I`Zqux7-|wD5u@C$h$NR4WPm8x3NRseG_05J%h~L2$b~z8*K0&4^y30qSU% z88Gh7DW{dkitMst#IZiI^H{3B28b9fHK&U(?3n#Y9GX>rOAif=Zq2E4#Uq8}Qu@Ro z_iCKDKbssoL}a8-I!m;QpLK98*kgxp@gl&)(UVgLpe2_C7B8bv;)sut znr0(`bBubk0~;2`KW(kdR52}HW|@Z3%k^j41i(IT&Lnozo1U45(FmX3;b;4th8_;FNXn4;Z*%T__MC5U}a7=Z-3xe%n*<#^$3fGgPn7|mZjVB0yn zE>;Z&ut_M5oQ~Ex?FZ+AHa~6FbMHBMyZbRiW94DorZ2Ll|Ln79_rp_YB8bf#Sc?ba zjLny&Ro;C@jZkJ2)}n$YNfl|{htru|#)M%Tvo=mNHvJ~8rp%ySapA(F;?z%Sa~UiD z)gLA=EPC-~GjpJG^k`wv6~0+MV#TR9R9u5P3*xcFr0M zqPO3J$Thlb>1D3Mr3|W+pY$MC%oa=xFD|xtXJ>^sQz*pDl1=wK_ z)0_8P_*C|e)kF&!L-|~`kRGUHi>WZ}iwSig#X>k8zWCGvN^P9+G5%#67x zDT&M2;qQ0N_6o5e{{06T4qE-_bS?|=?adxs+E9O%^RT$KOPk=|iQ9fVI;#>Z3pM7^ z{)89*kcDvGK+RpNU}tA1EnS9X$4P%NG6WUPA#|m2L5F|smzQFPA-LzbDT!9o%7)|jt{#j>4*W0_j zN89s_G|Bwl{#?sF49?hl4_bmD^hoN?_|n$)&onirXS=hBCOI*(G zMEPSbZtjYCfFW%WV|6uhC)$O*yv&^kO?{~y5NJ{&u%KSZ2aU6eyroh-pJ#M$B%hz! zLdOfk!EkI`d@NuugVexnv7_E;eF+GJCz?I^wc|xm78b{LrwLJwuHBk!IQ)?|D=n=# zd-6+Q1&!>t;29GDdg4ktxTiiOnv1vB(kV|*rjtLiBkq#zDCkDNaQJG5My34x0-fMF zCl!YRqp1xCvcn>jC-LL^XuDAL&r)_YLlhCt6LY%@Gja$y{clGWs!vp!^qAsN_>Yp= z$8GyNVOmRSu*?S&)t)p#s$O&3H_}ilib7&cc;~?|1U((cZrj8uetR72_te67obtE- z-LVim4+ZY#)>el4m}IuPWPU+#NeeZwp|1WgR81dEy#E>_%P1I^&KSznw3bNu6*8rJ zbeCj9!iz=1>&#YQgH!ir)RBT*$rvW_0wrKk0uz-9HCyCs-F#(aWfk?G?(VC|jmU4J zf)j8nxc@7Mi%aw1mcHeKHvV-jGK2xEW|07%(aBb6>#aJlGUzx(wSD7c>`KFsmUe|n zSXuphMfC_Kl{plG57+>>5$P zwcSNyocH9(u^Ah#?l4;G-*p#U5t_YufiIZ9C{POu3e@xq5xSYa;H#j8dQ<4BM)h4< zGi#*%_o>@?VV$HJ2~w9|x>?&5L>Z{QDC&9iEJ{d=pS)3%m(b|NG&E+^+{Ll$hDI3u z_IxG6u#?$*vnr}a{IJ6$G6tn|uwFJiwXUge6_3HRR{WxzZLW(^l*KZzH6y`nkx^0zA3K=)+~tA~bdB0fY#>@dXtI1;dkn zsP7g}8}5+wQm2UZTdv8ore`@<%`(r^{P9_yOe73ajQz4DtH{JLuz)y$m+x?8Mo_?M zlgN?x3V%!lC-S8?&LaEc4^LX5{!YSxprG&G;}6a~ZpPiL|FY)g@3$)L+$()=Re+WF zm5z>JxG|X%a4~Rx{HJ!jGfi5oTkR)9FA1h+E~7RGK&rq!+n@~IyBMf_$HB;Gd8TFP z{d8#KW9iuAtt?eAGNvqVfD>Gb#BEv zbiCEwWe(d9G-Zpx0Db?5Y@w##N2iJSUlgU_caKsuSP0+fvOp3E>~DjBjp#Pxrnp7E zln&4EMv_*cEo$xQ>SeVdK>schOy0HpmHV@BDX7rmjDZ2#|3xe^EC@63CbstNT=B9_U@@-a)Bc9%E|DlDP3S#{f8?@ zhU;}7?VVo#cR736h<2=$u^`7{)KwwuUw!O#KC|J4 zDE%Sj&4aXlZg63sU;o3KaZ&V`Ne0R_t3eJg2%~aWJ z?}~x(=q7f^2iWyeC&9fLgUI5|{n<#A14eD$Ey^JoiPqhc!hv4zOf^-6d{(!1jn{dU zEM%%G8rBwN&}=sMXXkH83Y)0tqn@y^!j{QuZ15lYsCxq(ECI`3FOu~e)%5hjU!$VR z*>l^=;y{p)$ML^hJ;k&uaX!BI1YuGLOEs0fOt+Xb`Q@Midq;Jjmcz}jH+rp(#8VZv zc}yI^ilwzZ0~#7eQF^<@xW!?^;v~;h?zAz|u^?f){aOB$6++TBO2*G-%E|*IdFVLJ zA8^zY}n8!GBJj{GeRMZ?AP4N865bG^wm~fi}FGB8!1>ors7? z4KF}};bqbj(0o&2(1E&r_VU>cso@F@<4A?MvR=bSOeg>Z64bfuP+XqvMS?vADCn=R zy*P1@r7)fWyD0G3dBo*wu*~x&_h-f`t)h`u_}Bp&a{~wtKHsZ~@TJJ0d6;&(21}_& z^jWDiNnh0EVGjGX#d79w8pGK@FJf&F6VUaQZ{ECNR?0pUiDZ_6jP`8iM4E=_dUxffHFwku zbj;6)zZTc&Wyss(@sE}}i9Cy65t@5JM~FUQ3b{~K8?BGo={5UcvUlvTV*co&pAqdm z@=$vofM2OOK?^BkkWpf57nOYqfQ;Lkzpw?0Y9Y`?M0TDY&caCt@wo!kR+fy*AWf{1 zB&6hCG%1XbuWdHS#|%cAhpnF)H9qr^;zpQj;|E{Omk{AkXrqOHzULn_=w25QAl*Ew&(id=mYR^90Y5f2=w8DqWJ1++#@w6B9k7Tb_b~5>kH)kXmFi)d6jipyRbN+rGhYSywn#T zEw&=BxEM8?C|3QO@PRO!#lu|+!mVOl{hn_Q(C?dyzuVxqv)?V%Ym}xBhY9vs34ciP zkkV}vo}IU(lBPSaw{y?P;ap_kpq?Qio31i>dI(H;yWr%Ui2EVKfGrrW8xFnx zD6K|xI$;Ga9e9Gxt+C7?yB%?Ve}5WIiU=AYoY`~#b=CD|4tb!&&}nZ% zab=zb@zD)`uf#3T23s`;yn)TWLa)g#Ysw@aA00I#P&?cxxj(CR(yrG3`r`X%7_IvY zcfG6XrK%OKr~KJEj@!0fc%#*tH)V~wvoz%Nb@E09xYg=84NX(u5dYx1z_cJGoB%VU|4h-r3AN<+SVXSaqHCe+3c{`pLpc<(?S~OL{vJeD{_c1oY zMr@prhDH?>WSK}RL3(NtH_q?f zg%c*el59bPsVBiVnVydl(A!22U26x5Sw{n}>v!hES~X*d3`=`a2j>nBlb~1_Q;bN? z@#Yeh$bw}5!Mu_g-_(npOUIFag|zrVNG~vMPmu12zI=Lk8ST0zLW^pu*2rgHX<=NZ z^AQ@&JU3!U6lDKf$cBvqWxIS2f=o8mP^eby2aqrj>r?$JBU*}UJ@#save+4>#vIv1 ze5|s?sCfl7KVVp_=CnivZ0=iM(Dpn}?L4E#l143=$|s89SO|5PT5y*HDlLqJjkOaS zyZgYVW72*gK1JMf?jcf`kzv8&rxa}nAOnLN9~-~}-r3!K3)G2&=^&kE5hP2Ut{Stk z&Q@7}naV)Pb7w+|&+6>VD!I9u-rX2g-usuyFrrWJDNE+6a_84$=D{$I7A9l_ov7#B zM>dx>gdBm)-CVP{DOtD6VQ!if$h`7wp5I@zeV;407c_EGUS3}EckGXIkr)#aBU;3x z=XOW%mI|8NjVeis#PO)#IgKBb08ySlj+wEKx?-i9|I zP`h_|+fBHj6n3}O(WB54RjSm|U_TSkxuYs3W_ve_d^z8EamD`gW|dR@_3PSVyEciV z?-;)?Pp9qgj&^G2yPq;J9JbT}!Zl*@KC=;YVe}xt2Y4tju(5^pb#%y`uFpS!>d6J> zQ1GTNR~~7f+uE|<*4SBdat_M7i?b4ip0)J(>=T=g;E=&R;+m`MdzV{&IWZwscbS`i zCsj#nv3gGS)sS3nM1{8QyBgE`J|aY;9bzsAnvpvEs*bn7-;-wOc70&UV{OgR%N=W9 znAva)8Tm0O_=P1Da(XPiSZZuS=XE^^ZQpz|57}`+bVb#2GSzrroZlO--W^VBV*n2a zeL#q=Jrk@9HiFjTYh0q>eToZ%!VFWTWu+Rc?agwI4_&k099pvDD?PsmSKG z93hm7WVm)a8&y9yYy;5@A*FdaoEG^&D2z^yY}IIwwUcq1O-;>rOfS>75MtMJf=W5N z*T%_CPHt&d>+31vc8%84udS{(`UnE72_nmvKW%sRR@UixY2ZQtjw^jX4J_w(W$^PN zloyHIs4Y2X)dU0XwaN_D9e4>g_7@0ou$j_8oT#X%+o?@dRd%C<5%~krU%#HqnwTtU z?WfMwKS<)YFY!74E3XJbe?SAxc6f9IvW6ZF6IDZ0W>;{mK&jZ|4Hl_laI{~xq&W2M;G~D~37L&U2u) zjpqlT>A#5-$(XD;!f|(#!g%*^6m!akRZi7yX74jTT$O_mKESHRWRTnTMuvy7mtBU&7v}b2q{I4x0ZPAJ@2NZv)BN_N?WK1V6 zzS!RE=1Y9RncS~Jzl_1A_H-}|dnow0!{vC=aPEcE0-oz zlyZjthY!8^uGLzJ93EXY%6`k)8x%Nx6e?GnUHe1q#My`y(=YmuJg5p zlU;byd)A7+2Yr~U&BagXRtA__(E*x>j7uN^A))LuB0aS7gOXrKhj_FI2!_D~Uc|ru z3BH5`62^aCy8j2(e_sNxJ50Y~jB+FJt`Dm~9{zJ+;LO9oz<^rRWt$9e6N;@qHx%rV9bf=nR5XC# zCU_9K;n0^u#n@#P1L;-c8^xw0EtWMl7jA6iC zQ6hfeF%O=LgZVp;KWetziU0N&JMJSriu4<6fYs9Zy_LQj(2iLA{@T7}P-@T|3hbo| zDu3S5wBe4ZqJ3n2h=f`+@it`dc~dTrkK3OIX=VkZ{5V;|xvGzOct!*<>Z{OcY{SOp zOT-aiHcJA5HnpgLW*6E3h7iiwc{1QX`U^~ay*WTM^H9fbs!DM*=Orajy*w03`TSB< zb-rkLBS%(7<~&w59N!O26YcdWU%!St5_WN$ISsm0LP%w#gPrQ<@84N^CJctXtrZpA zwVr3Y?2rU~G_8ODnYp=nUS6Jrwl>*)%Ha;c7sa`_${7)?sR1Wj<9LA24*A>?ePR#X zNX~zB>Ky1SdkgLrJV!^T!PkOC+U4Ifr2pum-qQ2%5HYHJLnu7)o3sNhjj$R>z5}^n zlZ=8|Tg1H{0Ln#$R>W`5mp}i_lsEJS)YUY|zy!weJbfxVtSty9(Q+Aya(%D8gIap|R62JUtXBc{sNcU|Xeo!3Ryz;Z=soM% zoo!^MTgh3zUFe~KYqSC%%+Ei6x>tI?Bxl{Y?9M2H&=hIr?4P~8uhv&q&a=|L0kQ;$ zD$I~LP0GK5uo6koY_M&lUN!ATb-kNs!Bzq$i6ZXY zgoK0`5Qx9w@8tz?%qp8@{}gm|5_wozmGw0>8BRt`T!TTtQw;cR0@Cn?K<|A50=T?l z3Wqm}2nYz4UMBOkFXHBb`||?aOuiHq{%7>`CTBZdEmRwgr{;lDl7deo7-BDn_%lFevvaJp3etiI5?ISE zdYQsohVgN6+3&;Gdr`;Gx|QbU5Mc2#S ze2yy$Y`Rq#%JFR0X)!U}C*?iV(m=rufsC);c9RvWB-!fL2O2n5;KG`kAW)~i^1Y)F zM}EqJ1snmJAQU)HgQesq8~lrnitmGkF~7&~-RHR|*NfDMptbTFO#G%%r8Y3&%v-4< zIL=o4>_skrtJqzdd3~uOK7;XTyai#OizJ z#^msk8ixrqx64G(vLQV8N87au75T=g4pu!@R$Yk>i)1Lz+Nw!Sbj zFpPcrRKM49wdsa-UUxIgG&`byx0D*T^%21cW@J-EAe?~iqX9r%D#&H~(|{+HfggZB zVaEr!7cXFS24SuSh0p3^;9!})UF~uXZKHWA@hkyQypoh#xK^PbhD^$h_7~cLu#}A3 z4CC0N*~vye^RE%`%9J@i{pnqKU2fJJ^8ozskb=h!d%YYiGb11xx?5GAc!|>wT-OAY zlwtq=S>XUrEpRZ(bVtL%6b=CVG_tr1C>3d672NzIhdC7J71Z*EC2kxxa)<6>CwBhW zA4-}(tDMwoQ8sJJ)YVX?p z(f@+DV1`$h6sF!E#_m8ROL1PyR?jbDZicAjBB|Ly8ptb8VSA8)Mn)#DIm+%)#Tm)NL88!ga7|m^=GCIK&CFID zfFrhWG!zKIq-gQm?D#qW?_{pC?rB%94H)P;*D2etZqm>00gW6L7k@NdM-Pd*<4N$%4{#NOpx~#O?M~O?0d9C3? zfyUi>Hx>$%I>13hK1vQF!jk349`gKj*~(pKgGf|1Y_P^!;GjfyU}QmhZt*)kjD)?R zm-rvvh4|%*;XlJ0Czr{7*8+uxz@vIE!;HJuFNSONfkkRf5g|9cVgMP6FoJ^017Tp| z;&$1VHlsx=tcaw3`-TIBgoLz#{F!q2-EA|N=dYzphO3+P*Y9TO`1op6vb%%E2$K6P ztg3ZK#>VK`*l@sy08m;$1m z;j+;@AJcs&pwjy+(R&UV1ke-H(a`~21<1a^z{L$z$?e!2Eo|p(=^_O&ixs9yO1~}u zGGq++fO}Uwls*f1;*!f@l?Q>anXg?DZ(3qn3mJ_-rgR1P2nvw?^WCpsN)dQBlSOJw z7LfLqB&LGH#SFOwd?FzWZ9(c9cab9z(*baB6*(9f$Ky(_kD?OTbcU=B*E!t=CAKFE zyBnJ6RI+LJ^wQ*JP3`R1LPJBNQc@zohh*HJ#OtH2ukp(pV5hc(hwDXmV4v2xG0l`? z)eblPpB5k@#@y0Uc)%J9l!&|wkF<|MvwLL&*p(pKstsHn60|j53SxklRVo2of&~V< z7WO@aZB?uAYPfyk8gSzHgMmgUUHBWw5Y#;D8&A!Ajh53dQ8_-;fW-CHV3Ac&zyP`xqzF0x!9leq5Ir;jR2Qz0!|0c%1M-;K6=sUBqr@Qv!9#S!{e1#$V_y|_ed$GIkjEPkBPQwt`%<}e%9Y{&rg0JhTpp!G+9JqsKD`nXH zFIOCPHnvW1i;O^q2MrDQ;|LHj_98`y80eydBxo0kA;1}bT=^+3E>2_LbbtnZOa)!Q zDkzIF-dCr*HaM#yND*{*6BF9MPAWm+0MMpHd{R=u?qnq+NMUux#5taR2(0UCu&M!?Z1LB*MGo*ow5u9 zlMfZ=Kzo&fCE?=22N1rkBCP$@+wmfuOf&@OK|4ARENbV6nyX zzI-DuFAvVOP#5z>oWvrmp)uiDgg-vE3=^@(8=`V>~$@k zQoaws7{kCGdYdz916r%V=io?_d&PZdD3+R%VBu_Tugm+}*4v8K%MUQG-uV;3d23~N z!KVw^2?qD_oBKxtOp16QvYxjL99Kz16A@$><9H5QhKL;6 zJK+z5Uxi&uw!s2>$uew=o1d)CAn!Ia2K(8~e96r_SppXR?^I0ZqK%c#m!HxKNXZ zbuDP3ma&Ba&J1k$&p?a_L}}>X#(Ta8hCR?wICnp^UsePC3Ofr+%&6-Dzhf^A0&VtY z42ZInp|8e~X-l_W>M*^BcOoYvum22yVbs8|vaU{GsMg-_66BMLHi7(?J;4fnU|REv zxLkMG74>eH;aq==B|@Uce}ibb>JxsNgHQDPVUSaCy9u2_7ibFTXzGe6GDV(4W0KG29G_PZ2DM9H=Is**%M&vjy$QpKh5;esdf| zqu6%u^s;oCIJo2C7NB+VsLje+5d>E!{;`->!=PiMStUjWvSi^3yw`<@tFLc2s@9W---1n<+jeKfW9;1>4=;E!uRc70B; z(H~IJf@^AhidEd2h`z}vmaT2v;pmy$16e3;)!)$`P?3>^ApaK)S+GZA z7)1FWNTLQHlm82nAYlK+P1@4%H6gona@anKaXRLIe{AXr!H-n9LC#<6<7cz7&Ym&r z?{3OV50fr0{{xon9{TuXPwe@c4>syM6s|ta03@w0#Y`VP)&Z7w%e<6Ml7Lv#*!i8_z2m{gUX8C&`n9 z75i+MXxxoH_3iWkhivwAt-V%mtI7QB`*{VhbNY`vO(uA%{lfn)=6v`BsHPe|ZunXB zCqL#grrKL?0MLLC$9oqS5bTKsxJsWh$`ZBLa&mIZm-;bd2fi>`3C*m#3X=rnzp4}B zq{V0t2JEk;Q@omYPt0qVPI#p-Mz>BXKn!y}$eW6KV)Mx*MK@E^UZ$))lmI)mGw;*u z@{=$eyU9v<(f2a~laB@iRj2K0PC*sgMj#<~0-935apfl~umL>;#62BjfE9E0Tn?;2 zpT9_x^~kn;Kvd`tMF1RkXIjX99G#N?QQYlN=KR+)s>5eOL}+{q*5}FfpS=3#_mru< z414Em-Y4_4ILq^X3Y9Z{i8|%_ub`%k@7uK*?yrWbc-#~>aSqvqGF?ee=k*$ta~IMu zZ}C@ID##wr=xZF-R3DsBl_-)^ey4E%)o`Tr9~sdI?Lt{84jRaag@s|}T&I5QDXMOf zyd9Ce%`Ai8`P{c9TdsT5Wnrfq&rx)A5oZ~%$b%5dOM~*nu36Algb+C2CTX1H zL^=?bt1bTz=2T*?>`g!Rtz&4ze`(Z&5}T6Ak5$THb&6LnzeJ`s-GYZLSk zFLe~JS4&jP2BP8#U8fzOox)wWH{6~VZaJy!8)9#5S=4Z2I5uSS+)sQELG8eAKgR}6 zcS=q&CTrS%_HA_Fe55@j~!+M`xaO7!!ITy(y6+dQckn64?lf7oh=A4*_hVJ!)RRIX?L zmA9&-ihKeI`<*>KwT9I;qtmZ*UbqjTqe_&)2gVJ>xCaMM9jc*W((#2kNt&fZ_t$|m zY(@WS_Wi4eGtpmaefQ=0SrV`-l#`pC{mS(!xq(&>s%=AFxQrUx(SG~)ret?9v^Ldj zJ>0E3!A9lD^XFe2trhFo6J;fQ?H`jaW;pd5DYTC@OOI zcwd?qJFN^5h(kzxxLYn3?91&mILSnwITWdY=!J@SO0Wb^#L|9i>1; zvtg*j%W}WZHV!V2t68jV)IE9knGt&q|L{5OCL)&YTfLW$ zjt0yNpWhC@?k-CaF<_Lx1)V7xXd+g=s3vWr0<=%%u(Xhf$x1G0-SukjB611d$OO&+`y#AQ55H-lw`Ke9VpT(&z^^a7~Pzi$lwSOZJ?L>QBfCYYXfQX zS^gEZ8k5h=l$o*@Q%Gf}u+K__vLtp*!w(9ZrhvQW?Gxs5$)F=!=>}wODQZJR`0%?q~sCpVHK^ zCRsD16EksC17WRR&O~I3Ud3*{kG=hk*&)BFsW&0v8g#6z*ezKHR1_mpvpHjEy-T@9 zjU|C6L(Ujo^a1!tQlFp<7#+PV;lBb_2lqWm=ZUNgDcy{`9l(OKS z^SSm%S!{g(d$%+ zBWk47DE$Vl6WS^OI$!~!4>{&V>P1*;FVvUb)L)Q0d#x0nuQcjdb$>*IL{98famXkl zs?*ktR`2FCSmiI*g`S|OiNJpg{+k6V*@;^FG%e8YkPpk)7;zv>^XjH>M1_#k;0DOm z6hM3%^0_7qy!QK+`}9u#X1X*bgz<15q;YA-JI5Rc;Zjn(q%D~~>7{|1qQxOIrnmr@ zI?M_Xt(4p6MSba|Ah(kMR&;H*`jU%-^?7W`EirSp#trbn3b}d#$XmPI1eKecds8#| zaa6;X1Y=cW*34KNkWbl*Rywe`B-?v^?LJi>RlM{n2aJywpCF)8Mr&Y25V7`}{+O{W~qv}51Ujtq#c@h&5dF@Zx zmY&=IBU-0LB{?88`;+;D4NBz!WAQyRv%Uc}wdhVw3PYJWqNvVoA(y|E?bEf10lL+R zNk|}$keq_UY6E#F{4JM}f}NEmM`{3wulmIdEAcMR7(klwa9A-k6f|nWrPpiT6MFxr zlU&SD!oq@~`pcaV%0gQ6_M0~uQ}4blZm`SSk5c9HDh`ssr9(G7z5DvIM5X{sd^U=i}u4170A;{ z8+X-NgS{JG<7d3kN|;vW#3M6egqPr_-)M6d^!XEzJ5FZ)?)}0Dj@L5=d;eD@#*!A%g$IoOiaI3C9c@gmeA2ltbcMnf|2lp)=@XpcDv5sa2)$b zvtbbpP6}@Ok{}M~N(8kGm}m0=*HfrjTreDbba*(Dnv(%yMx}m6-Ot+qFtP%&@4z}$ zu?rcnT9?^|^#E-FoLIyvps`;MA$Tn0`RWOoltMygeey4ry>D=z+rEvRTDD!pymDY( z5dq?e~3$>0$S}dP)Z1sM(?wkNImC<0F;5BB|zMEhx4?oQMVg zLcL&rJF?Gdg-2+2jR5oz=K9dOY4N<-4f6SA;;C~@aFYfKLGuG_>p&2g*X-2{#Zd6l z&tKA%G)Dz(O&NVGqYCcVM1h!YvuEFJl~KBS6{U)*=m4UsQ?@B|(VOwH*r5R5uA985 z3*nul8Q}Jh@8Ng%3+*bqdh~wX6Xa|noQ{1g85U-w(9q8x9%3T0&~!yPKjwL>8q@7> z(>*dw- z+lr@vQf-^f-QE2LzzToAzpZ^g(c;~hQBk1|+Q6N;2R+w4U?efcplgp+&!prE4-?7x zH^RX>cdn&W882F~?=<%Cd_5kP zy^gqNtNwvHr!Iy`M2kY)wZA$E7|6jAyvEjhVx&2N zx>u8c;=hS6E`KX&$K^L+(!^yD0?@kWhKb34%B@mT7iYwBYZsR$)xQZjP-*?qnmPU4 zxcj^jru#;Yz+@YFgN=?_ht2Ue+y2`F*bh$$kAHJiB3y=_Lz+Zs0~W53PvzSZK*2cP z)KM*m#4b<-oVs^0-Hu*ver$cM1W3+BZxol~SIPZo07bcf@PW;#3&1h}p0NgqByd3*0a^wR^S28=si?si{tlq&@n2{{HyU5(P624GqU~ z2q6Rx@Gvu&djC7`RiUkJrk0t;FHF#+ys7 z`%Eq`K+-A%w_TE9=4_CN1X0scviY)pWjAu*qXblo7oHmoE+u&&MVJ&+GF0ej+ST&-|Y2Cp5(oMkj_DNfXEKChU0@HuQ8bwv*q3PJj*uS}EcI^=8 z+@-n@-XI7jKp$NHUEt=h-?Dxm#U%4dQ1n?i>;!qA!5tc)+wIFRp zhq7^`L}Rjby*n_C6FhwQdVLR^PWa=keRH64!nvpUO#gTzJ$t_^Hrw;(uWP(69BTvm z$1hz!h|Uw`w!N!lYb83hkZPlNfnU7^>k{6h7385>OwwCF(799Srlh$>5A18{-n!{A zQj+1{o@*ipu*m!Q*5F~Hf77LD;n+4SMBL*WnKD2S0B`p{YfyW0Z0=_6EdB*#(<+t-p#G9w%c^8w-N}$$f;jmDb!r% z(h0ybu-2qyqBbVq+9LPn$dnO4p(tfyj$3k|h2AN?SE*pEDT*j}D=ShT~b{W5Qe(qYWRH>6s4la;;Nh#3{N>}FH& zUoi=^z{N@M+fcnWayl2LJz?}?&$6K0MmkRQY)k1Fl>687*b4>BzR7r zLw}h#S_!@}T5xpyuId@SQC&VXzmh1@U^&~5PCk8U@u-Ux%qBBgotK&D-nwyrN8A?j zPm|cOLXiuWA;hBhPU68WuRYfT>b)>LK9yj{t=BfIGCnA`onC_UkKdF8u~q2`GW9#w zu`pLu#JKe)UH{B9JNu(gRMvQF&h58F`XhZ@(Wr>f^oGK(-ibN1uYik9?7?uZ%Cb4} zv>o5NSF4hFtEScu4pvrhkXquvt~cP!$%E=YX*}nS?TmaPL7`*~B&wv5kiAx2p>3R1HF9&0FC`~`urzv^J_)OVl*r&h4zY&2=s6)PW{W~~$ zpaL9nvBB_^_GJbnF#_#t=q5RBq*qf4HQ`$+?zGLSv{o(5~HnA_pHbXCvWB*Ei+1 zkMq6radtDfx?XVzmSPnP%;-E;auO{YTPO^bPe~HGHhAr;E=|motw%^njr>q{lgID( z3IF9vZ>2=(t|mshJ<&y@iwj)e0BlGVMMb$I5=d3L#r0WPGIcyizkkeTa+c0Z<`Q>n zc>ik>5C{pbgV%Fs6y*6ZI+QOAFMq73Y56`6-MM=$PiZ+y9wqXk-Q<`ok zsAUL~l*O-2$l~qv*7Q=>h|Tt&txs!@JP#Y>KA&?KG+{t>j;o==&mB%S->kQ7;>9XG zT_i*rP3!1aW5G=Gf=bS>j|R3nVQhviGnRm1G(N`$>3FPN>wk+q@yawGhK!;aACXvz zxnU&XHlP>HVI{Yt*i<9&kzi~2Ao7QEL3&qRoTWZZ`q#Y~JIL zahU{6*DOii(gu`4F2~!GPJ^I_wQB*&h<8#_KcvBfT?)4RLvZvC^F3p5lCdKT3H9Jo zjtRZfr1+yRlI!iIIrUSzaXibgWb6SAw~+6*SEoirPTp(K;zfRRsb3;}+j1S$czQ^oMXs z$G?g>Cs|yMSZC>-m5*rZ7c;=x)F^S(-vvey{Ag1!Th93%6h&A%o){G+vD>iq%%gBl zys5=0*4*~&B)GPcQop!jp>`ihCC)^wlZxdl$@+}BUF1+1J7$IV7laucP!Qakyc zbT9%8$xfJ8YB>&j_X9~_+_@VZY5wMX-+58<*?qMG2Hs2bd-0a*vk6obN=r=GvYq2F*k|Lj*683==WO-~q{ zo8B9f@Zv(W_wQ%i`FWzaUmP#*+AW2wsAZPZB2#8CQ@@ILC+2>m?9t5KleAjL0k^%E zF>#SSb(D$;%{UQTJ+s{aomPW>JV3TRmpJp;jq1vvK(d!X+-q2pRQzKSiGJ_*MIvym zc;~&jM?0yWDm5nK&z%2G&(kT65H5aR5|#5Ob|P)UkyLn6Q~GLYToYxPBD!|oqVmT$ zS^A|CM8i6-EF2BUA;ZkroU_f*t-ixU$7Vn|j@o3izpeS`p#cK@!8x|WVJnhzd7$c* zY5FZbMr-t(7{G&5Fa8@8)w1NbNq?#H&M`q+}!cBO|9x?8M>Kanr z8ztZQ&abrNw30sZvR{N^AxG@BzwaFDukThIFYb7|PIwn@VsZr5HGjMxMgB~5b@KTs zuM%H}%TR!l5O0^c?t61e9^=2n5gbk@2Cbc;HE9WU$VCIGOg5`hmzCUk%&A%Z|!69(OH8m=1j1@ZH&7&M3* zL;)ihNbcpr`|G~M66}!TL&^_xSZD_&Ok{0o$iBhk|NWUCzQl9t6?=qeNMrsvLe^+< z-mv5`>VGJ-{c&jp1P2Vm?f)m&Bp|r!$cGIeC+pe6P;u?@-2LeO*WVwX>LV)s2UP8` z7Pc3(Ms4`MH}D_?aE@W@*cusk#lNFhQzGcC3WyvhMM)>#MiLn<<2b8m(l`(aCn9It~fYrl`RAVy-LV04IU@)6XV038>LI(TYr4C0ApI~2jS$pND?8Q z%gl$^0WK8lNGI(#M3BsgpYh`!qO{u`#@9M;-i7z8Vb|+XKS<|J55BFBzUhZ&i#E8v zHf+?K&I?e5(<^`wb^RlVXEPOibEASz1?~$^G&-UqskCLG_@xM!Q~Y>Bb^a>v(?e_- zg%@Ru5PnJNu^v*O4Z*IV3z`|z*zIHZTSE%ax zF$AlpYw3&rk11#A!UufU`!{C*sUoiR^lnnhZV(4LFv{AL*w|x)-m`fUH{Pb@TEjOZ zx}JJ`JMFtR@$B;E=$V%*&Y)jd%Y(QqBYdwsz@$Q*!gVD5Q=P$n5hSzSZ6%7U#C z#L@#mo6>7e&yQx@&Q}i?DM1(ZXMJ0joC}eInt&VS-#7!g#-bzIX{PaZX)KWfAt_%B zpvVM{b$;^L|;K~M=uKU@%cfr?nS7)WjA1>HQ* zGMrtn8ic03;Zev7jN;0y84FVK=G=Y6+m(Ad|Me!WO16yT?yC@)expd<`@i%!B!$Gl zyDdK*gUuxJHozaf>f?Dx@U=$?n5Rd~9a@Ib_k9`vU5IiuNf!`jb zfx}VZ%^uj?#?gnX5=)uzz3roumedBC#!V=9I^+dYNst-!g z@aii@_x0BC-^Ju(&%Q}&JUPns_JM2F#WV|Nw-ur^^}_SEsGkSLclc1asfcPJj+^<8ZZa6l}cC$GAXn6->Qk z{|+33xa0g3&Tkc$nrd+H1Dj*JW%e}@ZuA{c_lyA1YEvmYgOK{8(Hg8`-JtKL8o~hq zLFsjMM0}KCc@O$OT%YL`iM?TZ>EjjO(+;#VH^-wdN_cnSrMIrSLPs>$#Bst@>TL#Ip&ek={d{+|f(p>z?2>23TG&IQ zPiKjSvF%%L_`tdEuQQzv`c@sKFz)3($6rm;q;+*EoY(2Jn?0&ySs$#Ze0sw~RF$Do zQgTAY1e_*ABM}EuBMJP+s}$GA29-jcG;L|am!Fy9jdT|EN^SC+)hPbn zV~7fyQa?#WVLTfwkQ480&Z_3W?D8%wE#>rg2FP3psvz|mgk1qOtB6}Eyl+mCta5Uu zJwj^9b_N$0JF1`JqP?;p8r1P*elPt)iP3i4VFo*02Y1`{AL#TA|9L+Fy&u=#yfgnA zTxMK|<+VI<63Bys+}b{U`vx*Chy+pOBvasIrxn8zT2YsD*CBqVfs?KtT4_#c@s0os ziLHT^Pja{#O2*%fRXLnC!6BClyrvd9$!XKt4|uru%tUpX+YLOYmqAWRuOmf_XQHGv zy}$k7#ze`J@b#md@mXA_+bBtJJG(gj=DzyQ+`18Pa~y^?zDK5I3ASEU=9FlUVcd=JNKJK6S?l z3;L;Rcg|}W6r;J8bm9)lxqPRuaX&~nnlL#ko>}@(A-uDn_I`?Ng^|;9*ZTf=hZ7Ra40~hK?;=jqF--1p zewKOXUetVGp@O_+qNz+STr9S^;1V(+#nZ>EP1%ZsToL%pm82g&sQj$YrzLkLgY6mT zegN68TLk3AION64?>`h?_lo8B-M&8XQ+}Y%kR~uFM6o&Hk!8{8Y_i2U=FI!w_Oxlp zj`2Ant+tjC1k1JdI(~kB^}m17&;3I-0;kibWZ}8Eykn7kp+rVbS75HLE98bt<>ab= z%`Q&+(oS4A70^Yr%_pMH#b;}0U!?cLX38ky!K3SB{qyF|!c)@1R- zTx9i}9Q)pdb{pWe%-@p?={pCd*<83UI}}3~$p>?^d@G*5yrzw6Xg`W$Xkb9o3g)Lq zuibz=BPuOD9(&3b-~AnwauyY@1cf8+9YByHCx^>xlBY znUt2FGdxhJpJ@t`9y@8{mTYWnwfOhJ6f!Kl!+P`PSXBdLl^?+*feu_q6^ou=_Ob!9 z6#yP{t@U-0pdFKvZfu{7B1s)j>% zItxsm7}q^;UR-niyEVx~CB>wqh^PIFCcV(Ce_25Gcez94+qYymxVZDXv9@FiIHmzt z1r|m*a}fz%xC*z2r8KTlqXk6~Lhf4=iM2!mgT(Zx0++5B9#{TR(A{41ls#U_P*G7~ z^`XeBEIv*Cy8Y~H6iDdERkH`X`d|`6p_r8E9~~Vn22XrvPmlKhG~#bY6+#bQ0X|q| z8_ZTxD{~?(3<@*|ChHS<(|j?en>gEh#0Ajsu!m2se5h_lG~QyGd7aHi-1|@MT^QDn zlu9_T^`yDOPU~&--xPNNeu|(UC3+=v-Ts?1XRpO>3D%3*e8xS^2(7<$A+3G6+?5!NZV^C_~#APDNj+8MyzulUD(G#7~T@F-2 z)6fXA-y(Tl0y3Mgf<~22gJ%yw$~R*65qioRCMNZX9G-{|V0H(T`KC-3h{oZTjaIwz zK?}Bh;!Q6^Nne9x9qr}i<=iT>Vh}$zEIB>Ja4epWo$T&>$vHhcnAk9WcAw||SY`ku zud&);;Zhc{f9vEjwX&wC)itA3US9t3m0JMK!SOBP^(CrjRQ!54M1)*5}_t)xHL){2p~jp?JAnV1U%-(=8bC;6-%D3oa88 zi}6HhsuHp(<-d7xqW)LPqPN#Am;ieFo>k`z!IW;ES5fuA z^7}tNSHx)y&u2rh=@khG*i_Uua#hvThN^i8_D8Vl+b>;<`j~@#P0;>v79OeX+G`2{ zPaoC=#Kg^=Y{bMHYPk?V^NOvX5Vy#4zNq)&6j~V>M}B;~^%%iPPE3c>X@yqeyxkr5 zB2>xMNm8#U@7%%L@|RfWe9gQMh9;EihR5mRRlkSaVDqi9`cAIx5{Klvc5ONLm+gg$ zwZJkdvv6eHT$ElI*k6c7s9Zw9$N2R2)aWtdv91m3wb zXVHI^GXC*=2+Ko7U52o`EVP~-$7;)cTG(hj)(?d`H3UiftiHi)5A4%Z;tA39CUcQ{ zL$*Xj6>3xg5S5K*f_|FnOC3n|BQa~(X@eB&?`GmkWUbMbhbd=A{HZK>J70r?E;nH? z>JdvWi>S?8TQCCtZttyW`^SJAFWtyv+ADf4?x!zKaKud$;p-5}0jl5}FF1ND2O z2sEW0!|;B<$pHgK%nkqzT8#pv%^d;Tj>#8zMlMoIGevr|X$Ux@0ot4j`Q%rTAlR$_ZXY<2a+UsB~z|G!pZeUS!J{c#! zvanc(kd?k~t2Wx!n-P9IhzghHyJ>Bx3Fj3Wx&=)hX6A>DWC8y7+!#;Pk-?Idm|wq$ zf0tAHvuQHkW^%-)Y136KXe{;9y%C2U%YkXGD^bJ!R2u0(xZ zJOQjLCOYS?6dN0I&ya8TO|5=XG@J*DJDb1lzA8kU$6cR;f2E=$^<2cTGj8scDK*kK zRsPjtP|&5s+rvGWdwWaDH9X`^Y@(*0H%OmJRHXPd$P^AMvu?BL zQVC6=^s*L`z)cpDXgob#*h`9){D$?jn1Y(9f+mV#LGy~0CWFPN#r5MX zI$W7+AEBZ3dvA(>-|L^L(7pLT>VCr2T$0xhic%{q`ln4kZP$6P$DkJ$tlp=l78;d5 z|JXh$O-8)9=61)oIMsT3{)fJ8$$2BQfr&oJpcu!(E^Vv(7R6gl=d31u5^0qR{cj`% zR7mC2sa@~A*a`Ov^NrSy(~=3_BjzAR^!R;3n}}0iF9e20e)h-OHDX*`<(HRU%bv8o zy?^!Xy*3rPhYCF5UumT`NU-8uhaURX_h&^TDZYGeV%-YXF;D;S$40b7oXLd;Dc&Jb zaf-RAEKe)q?@hHe?A<+7r#z5hQkz0ol7Sr?^7kuEq1>a&B7L0(^b*_tcWs6B7WbMz zPFXz2TbF0x3bNU7$fFTRES%FQ1@6E6|NS)q(SJTfK*lPsfxx-=3I06*#L55taHaH5 zGpa^lA7S^-{M9j(9^JL>O9a(3t!uC+BJbr87R)Eg^;OP-mo`^7aYK;0 zSg-19xr!A$=43#e^hJjzFSG&@xA z^;q8sRl!muV02^nOfGCC^0B-sA!O1)7YnV&?+}+)onuE3>9EO;8Qzpef~BLL>}_o_ zUrO@_++3s9{nQC8L}N4$wzI_C+a+nvY_1vj3DFoh^bvu+MC0Ila#r*0u_ygcPDIWi z+J$t#O%Q>=6YxHXD^JwP&4l3tz!fgPf%B=lk`fL8#O$jWUz3S!0Fv!iCP~PjznOM| zk5ns&+%zauv)V+~z&mjT2I2W&r#2*}6-twokvZLyUxczD^1`W<0srpZeeH3pF6K_n(xZfileqY}nLyoNYh~LO`Z1Ac?z4RTkQ&xI6-qMCkne)r-fnyYr*75ZIlTisW^?!mWh>&foPw&*2A(Jc z%YE0GA2h`-ZCVBXL!++h`Ne-vQ#G?G(WPo!-BKMDEwfH%es?%$?Uk|R6LoqulXZN> z_}$jAS$_x!+|R=*ClCREvh!0I5{|Malp)NzH^$Sk(d<+VJDv0 zMihkQRcEr=L*WD#?k!B~)Ob0niYu?+kTW>5r;k1G$Cns~`bn-Y7YjquF{O_){Wo2BjP(?y4rVnHUgP&y9CshzSa{CVvq{Ivo_uj?EQb}xvdCnpj z5tVPe9nV}j4yRZoriN_A?4Q>&{@;fU#-@=ZZ}lUT&Mn$F@%3|+#%eD*8sG_RiMOX|t%6c)n z7K7nM>f~yVWh{HDPj4-=SuoOXrn~WGE6v46z~ic+)Xplx&WJEV)ftae`(8_(LSH`nCjf-M&p1h@4X$E&RhnB|xn)vCSfY~l z7i*_9opy1gcW#eL@aW0@0h0**ANyps_a1@^)9?oCN`lYHsER!1-@KO5e)fQ-lz=E@ zq3k{ntBa4AH_V+;ue0rQL9e9*U?lpJKv=lw6lFh4*w}Q zo0v>lLvIO2>K~VXeB{63-a@y)p)RK7kJ;f~}us9rUo?qaK^^!%wwDCg72hNCedKr(RLciN3B_+35#2p5P217_g=f}&-A9`Duyz+EE zaGy?d-=3NTga`8)cnt&)AZTp3r@46J;%4Krp`&Ed-dte_~cv@XSUM7@2c z(f3h+?4NPO`g;UWt7BW*Z{@5`vEhjjVuR{<^S2nI^b1-Y=}U2$fYWUn4dJp?qpq1g z*Wlv0Jwh^qxYFc1DR7%hV1Inq{o46Dzl`s7ScKpWRLd~&|I*n_k?Oa9IYo^w)c=O* z^P!x5yzIwB?^FUqLkR#kq>wdulPVkWy+J)!GB8ZpBFuDw6oE3`XF2u#g)&-bs4F1pi%MRRq2pV0 zolZ6JxqlR|Olp&|a;U5FK`4+NhgivmMuPHTUAczVkQ=U`m}2g)--sDVNf*O<>oU$= zXjt(Emu#*+zeEQP1OiV*>0>dB%jQR*{cOG4HHBFGs_dvSikyB6{hH`x3F!9KXkN*-1j_VGX#Rp&{OVpxTpc*_IV-k^<*QJ@#9W3yKIuB@ix_SV{)Y}5#)=bBxvpI# zX=`q+ZkB0oBOyb0vq4~AtpD9*263?M-_F+wfz+}_IxMt7{++XBuS;DK@R>td8wkJ7 zg#AB#3GfbCfn=8v8{-vGz?+Gwho~E*eGj964;RR%ya2xOeLL>6YGak8&R@<^UXsXpD zt_dPy{@5Gd2dgIn5fl_OdNwJs%Xf7|@1jw8{d$ks6r7;SKi!<)+`LKgXS}N0W-{}# z#?uAg?I%>RMPnQLE@e#OiA?c=CT}H{KYDqQ;y5;M2H_QOhqndzP1e{cQj!<(2ff1e z8?9hD_t|tUqLg&`$Nz@;hzjcGAQdGi$9NCQGmDUbZEXPgz zet*$hWFa?33uOKMCdWD0)q)?o?7sV)faWvNK_1#ROi)l(5`B)~(yJ*W5Pp;_?8!a* z%P*-0UlzEu6*>d=uy!W32WFiPGlecfdw>IB zo7d2ZoWPftv29)e6v-#*AZx|}`~TGf1O;7yZqT3DzZ4abA;6e|kdYK2ykahrcWk9K z7D0C-4%{MM{tfe+YfBYmQ(A9|9Qw@X4N-TdP4b<$TSq_!q>#`>Uf4eZI0YoM4}>G` zxM-y2%O6+Z`8ndXmhdZDY3glK5+iA`YL5#?X3hMorLe&={JIia*D*npB%N0+LOD;3 ziri|9JxxdW65<|tp~G zW<;fV=Q8I^yV;1H4Xm*i4>wIED|_-ZeD3#J?2&;WMO_@`=b6c?rk{yP)LJLhir9X_TU%q?#^yw>(bMR`kmOY!lHC5hxU8(VDZKj+I7XJM%vMCA1 zw(&mX3%V~dvJCxyC_H<6NGMIOm)+;I5MD+i(A_kGqU%-S)KX-W0ft#*9=ym135pO+ zqBtxPa9faJ`RuupFefLyjw{YLqF~*(EPQ@ND>&uA$jx_akgs)-a~)-RMM>@Bw8X;d z)`8m;%lh=-URUdjXT;}2?=3!XOoJ_Nr1hdVS2~%&F$8tf$FDttZWR+zF?%o_zK~An zF>ks(R~PGfh%()1uYGi{@}E7k?Mtszt3-Ie2Q--jd#vT2myT_25g{O7b3YSJXvlhO zc*(IC^{`ML8y9U(J472nCXC}&gUz2=RNBiqz|p|m{ zl8_RYn%soZ75ex%VJou_E~8{v@S^Wa<`zpcs@6+%=pU$G#m2L$6MttkPYTNwG>}O? zss#ga90;A&@3G(<3xStsnuvkvQ8Y?WhpmJn?d-CL^+!CY=DFlfxC)9!iu{f)kqMtJ z0=@^0Bn;ggAk4QgRO})fB~5O+GE5ZCzWY>3sg;$p{Q7fkDaNVet2wy> zxIp;d{V!VPuOKKzWYz*>6;AO1r14ZcxfpF?nSCp-wisk4oT-$%?*o` z&3h(SNg$?noqq^to`!$HeAb5_bwHS6h|79;xbX~gvW-Ll+vYK7nT$_XGNP*a@7!8o zVPL4S2Ny{?lz5*2+dNaXoRR^Kc3L%_Nr!L!%rOJ0rxi<|=v`0n6Ub=Qb`Ll`+=HF~ z?B#P>8am$Y9Nf70l?O12EQntgCIK=K;^!!*2d=yrVoCM8*eSI93O>MB4}W%V1?#P(%iPx-t#O-3MfTv9rU1Bs=$HG^u$X7mGo$;T zw|^g0eyi#$UA$S&`?qGh_Jsd+gMegIVZ+MOKytKKa!V73EGu=}@sl%e4nHmRs|Xyc zGj9eP*#5B)Q^RsIM$6OHu6BC-)G={!&9hEvPrBp2=H)3t2;Ta5tekngsdTum$w=A~ z)=uxIS)oxTy-I$DZNUdEpB4?-xN!V->?`Cj5!m3Oz%lBkCqP z`r1szzTA^7MU_v;J2-jW(ouzSKFluDU5(8lCv)HXna*q*pdj=Re8Q`79X}MuW83&M zrj}ItP9MJK-m|x_1b0d>$eEE`VOpyke+9OHM*??8c*ym>5{gCOxN)MTB8s$)+DKW3 z%$6bwDy)7|Q&SIkS+HI#?NYv$4~SWAC0%?cJtDOqFW)=>SBCWpXgFBkselB)AKX^I zxic4gj(pYgzmv8~lfhm8hDmPqI@?vaRfT~3q^I@AYq@N0(hXD(0KVWrk!6QW!WWwP zJB#fUb#(5!_1I@R^HQZ#W4VB_A}kqy!sO;Rix(6^tuo94aZC$6=vf@jsQTn2iCyBJ zvbnA<`{~bYwFTBPQ4DWSC)>;*$-LE8*0<3hLQv6l|cJgOplz#jFx@-#W@rP1msTB}*^4I}(o4JMYaVGDW?cNt&l65&|2Ph0}C2JwB-*T4H_L zmrCB|rCmekbmIPYing?M6K_Lj_f4KPpwqzDZ8R*`T~g41;YFktdJr~HZY${7JsmKu z)C=6TdwPW}I<0z*NQv10!z_*8Qr`K${#nUKFPYtPsYHq?@m|qQ+mf)}6KfLOUH-lO zF3Y6l7}Y?^ap~JOebn?DmR7i>ctd`Oq9Qx;@}#lLL!(H~`y2d{$layEi(>BZy&U4l zO1a)iOD|TV!6oeMpf|#4cb>oMNe}t)Jg{~_Mx6iVs|R6(HtfhEB&Ea0LJ+OLsG3;6 zS+7^)c73?Ocs#F(k(n9u0|foIIoR2Oh(pH26bV8@GR26dBvHw50PLh<^#;nL-ebK| z$6TDt-yfT-_u45#$cIg}9{;UnPamN9UFJt2R)C)PK012js039IV`TSs^So=CMxHB< zT|j_jVhw$~mkx`y9N)=ImHYHv`)70(90s$8VfR0j%3Oj4gp;gfseT#b>wYuf+DvaF zxN3e|!Pg>-*pCh^*Qn7~e)jr{);MioNT-u&q0+=isbDLynb1wARa+{eZ`0Y$ino0* zucR`r5Hb}uKY#b?#huHzlrL^@LvY9w1hV<|=1Q^?@`PmnHV6nE*QY1vbd}oW746Yy zQAfRO|IQdD^HJ{MsnTx$4$Vi(d~!Cb_>hR7)n!_A**Q6iN=kv-PBT$TDMkJB~G zzyj+RbB%}@?AFtskdUqgcbP9LA|mikMiVT!`#QP%O=cLD-nr$t?xRGq4@pUCFRO(` zX`zR}SiHx^%}j-t4|*%+T0kUcKoE~T$oxgL9_}^(U{AhR^xg!6Jz72N)vTi~U`FpCL^h)vYyr z4}tyrZpgepK67K?)7SkaE`50On{d4&5VvMP>4eGKcqM!!XTFr1YTg=p1;{LWIX1Yt z3X)eFQ_CIH*eGH`4euV;sv@!F;h`SZbk#o!|M!i^$$CIjl`Z-^8C_Eio;W9Yn7Af8 z;c<_1f#17Hg3-tVVvje6XU5@eRmXkIauKB+q#WYn)QgLY$SWwT=Z1QooOgHIevI7e z@b~?l_PxewHo&ezF0svr>FDJ4DWmlP>1BfxBtrjBK=|R!T{%vA}6N9&>5Z`M9Btn(6cE(wd`Lj|E;_nYqj01! zEruHB1chTsXeRW16|aesnYkW>r2@~tB%Ohxk%1`9rMp))Qat?TXTRE2j7iM##eDwttbh*6+9IuVs`vnU>pm&RDX3g2{Tjj|?}qe(2_0j5j| zACT1Sx$rXRrZ#{3oQC;mr ze7SVpdHn)AM2tu^&Jm@zr!MuD5&3jmO@;Dw;w*|o+g;+E>GNa4$}m-g;B7u(;YTVP z|DEDsVLBQK)c<#q^Z%Li@crL85Bq-kz+Vkqs=)7tRxY?9nj$oBG#f?wL} zm0GKdCVA6KI$g>!tcLR&z#Rs__CpA#ybH_6Pv-zo=nTGtVc+xK1IRhbflRy%>$Rcm ztq?IF)m_#joT0oR$QC@#GA+3{Po|z1e&27DcK4erl!<*n68jP2jL`s96IU%i>s&JatF ztd;hwzLXBi+dhstt@hV8-oQ<^0J8FkEMyNH2JAkUcmn7pyu$Zh0qQk=bAGX+ zUW!cWxW5Evj-Nn8P5b5zK!@m*l->(Y{NJopKgHG62lC1>jcb1I8?Jr$!nF%eoRzh; zrXz(7tMqNL5ygY6eLYksi9Y7I)EzP& z1Qq4y8Vla)IAcSp@>EWa`D_j>S7D+#^10hDUDY!if#0di=$M-b9Hg*oQ*H#;AteMlU{hdU`qu7{#jq)J~7% zIA1c;`o|8eYb@Z-^?y>H;TTLlMVi6<&T!3m_7Pm;3UK_8!|ZI)?wiM({#ZWUxnlgJ za`WL*A~go~woCIV%f1i6a|bUn4!oN8KnOWP<9^xniJ+`(GH%j%9&AP`L5*uYoabCr zh&Oq#0UAHKHkp476*l}t0moBw_Y?8gfH4mk5e?xe1m90r0U?O9y@x~-{5?RaJnFgy zl}#;GJFG?$;9=ztHvd3(!#WLswlIQytHMbZ-Ui>`7m)P>oKKVcpS(WK#6Sx95Sijz z5Xit5^Y%hY0F45WEmdJMu6%j@<$FW@b?phxEzAb=p&!GgHDE1z{|$b&f)gw!Oetap z(zq=J>;94h`_Xg%is|7}qGLOw)JyILSdhS9C@Lx%bHS}e^L-a#-8HTExkNc6bStF`0?0qNJ6lop$#fm#TPFI&7**K_6)%)CbnPg zXL$bcg;G^smj>z^?mc}JcdDGaOY2l&jj)-QObG-yj}swYeRk{wp7OJ0`2?qQ#dY>IqE$JI;P zx$F46Br+&1{5kyH%efLyV zKPB{8m=|KG0`u`0dy{qO-Z35f5_4(_^S_~%^hg&p(JyELonL6hlV4b;j}bDmNQ?mn z%6ZWbTMnkXYc1pod!n##z6S*xx_;wO!=|N3<4KHPNS zQoMcp3N>{w;3<{v+$jP4u^I$1Fr!YLM_l1F3(|=ogZwX%8#+{$Wd@Ice+t=tot-M3 zRwARDZW^kyPLgJ22Ii$>Ffl*v65OFGQB_xO+ayc)6HB%tD0!822D4w-KJKvg{o8SE zVxyI}!THu}E7tGmlwp+CYaY{GnlL3%c6KZ$uAwW4A&5qSMFqseL@V_-EmircEt>*x zC10+PVM0&#wg;zCP~*3Rkm94ABwMQPAb^H^I~TG=lr&V0yTnsn=lG^g!=Ak=tiU|Q zjE7#vf1VceX*$C1gTxDF!k3etX{u;jH?A|kCwD_Hdo^yIj_@P0X}Rl%v1$Y_J6ZYZ z3jj%x46gnAc@(2h9twT;Y9l-Y@$1vFaJB)Ep(3d00;r>x*#u_}kD*q}Ugm?-`=SnR zWj+DHH;RzS9wvbsHz=U5>iDxza`)lAdjJU~LYRS!T0JZb_-i84j3i)~fBg8dJY)<& z6byVb6Ou0+$$+mK(%h)S+hQq)IK!?409Lz!vRs-D7;g4EFFJtK8?%*q)S4t~iAjm` zb}9K+=j(p4Oo9;jYt;oUrFL21%_&`Q`u;_*{`Y5>fy4Cga|45)s(VR5mI1M+g2 zi%iQ9nUp{eagxob!}nO;WP_)Y9HEwatFF=nS>$uHc&r1Yd&e^Py)t0ewmjAU;$eTH zO-7dIUW$2I>lkQbaJgQ_tj(oQHsr~4gD>9_)s-w9nZqQeAxgp(87{_8fNIG9s`GZ=%-?8<)IZ>k8*c|7EN2!UEFcO$a+iN9=?xS_x{4pGTPnWtYPW`3#J>2#tF4+d4Jye3qpJ zTAbdV*V5F~EI+)FjOZOb|Hk${m|BjTTBZWwY-u=M5}*(G=gXo#2A4YX5cdf;NQmfg z=O`mi_T31ab`MHu7_`YGN%KBLEy|fSqStqkr_TMJ@7>5c$Fx$G@LtxM9334gM7vjT zVVr}WNJ=;ZF*(I!ju7$o#YkmpZt6GsmOntPmn-;XTgpU&560H#;)#4)j^c^N_lc`o z8=+pe_54foJ~>%^y$*5t*d7pG?u@V(*VbxFNaHu&;GbFd6m>Pp*BPYZ)3IUp-VpYI zR0*W4OW$I}#BwBqgzZ51uMcZ21I!R0DT~6$)SqKc?u?&+O71@%o|9AAXV1n&uiJ~Z zNAM^d|6E=_ixwdd8`5%`O;lL2vJ|uI?*MB2@EzsEZ$MPE=_{1BV^n=ry`MmK)X)rfp~k95wuu z-Nc=`D?VDP@^|jweUxxyz8rYUz=^1qb+7m=kE%mN@@~-x7&-CS_*}kxps~1r(BoK; zlbxLo$Ahhf^PDydg?sl1r65Xx>z-KTjl=AZ-(S?5BW?_(Ud)?Vy<`f&_pSvpo&n}UN>DICi;oF0~&CVfYahQjX z{bjV|QwEtaa;Db!KVC2BZvC9>@qf*nYZ*eVK|=Kcc|eQT(m&Dx@~8 z;QW9ae?tP+$wm(IcM|k22l(`OHa{j=RA?LPYV)ogiMkdP8(s~}O8|_10=(7ZpEY^- zsV{A~NrU$o0s%nG@pfr>pcHVZ_O`aXV^uEKdcJ>GfXBJA8sxo;Rc04)*Dsp`3Bes; zSNeTAdSN%2=;K4j38=SG$g<`fZfpu-hnn zj+YWOV#na)KyrivW?s`;>GQ1$!|EzsEMn>e&CcO`!{zw>!UvlMyMLa2>*>6S@4iL% zCsnQ5d#X-SE2j|-3~8F#tgHmg2!u_u!eUED=}zP~7a_6;6zyIMqHfoEpIw z)^HDMH~bX4d^07`E){m#v0}@R-GR*e^q}GjY4JbVs(Ba-r`4T3W`F}gK}{^tf=`)H z)qfLFe`~K;a=o;Lf&5LXvUR0+b8g@g$EK9G5ES%ZXmSHlg0;)7Fey4*3_ zGvhJiRxqrn_C_4x}%c9AhyzaO;DHQ+BVKU)VSSRUwdCyhU@{MPGN7ETl;B|EP7zC@ZshVED-MEcuG8+dVlpkz3l<ZDDm?W;u4*T6*9&IK_ zAW8c0;R9(@jyJMP3j#@SApXa|ymr#_qSb?;`Lo-NdzpSKQUdS&xT;B0Hzi_<_7Kk* z#qw3AKr;!%LGX{(h?wV;G4n*+s`Iq-dA&itTk<^L0qROb*#mvdI5HxXcjQ~CY5TL^ zbRlb>w674pV!eEM-jkd}})1Nj|rX1#1x z!hfk|k_5g1bqj=-@YxnKp$Y2a$G&owJ9pU<&^NulzrUK-F#)(z1IP=&`G)X?4_x-^ zThv7Lk*a6niBjV{iMlzt?P*&xDJ9M%8mG;UnfNTajh2BEP&< z3fC~?3Hme~$b47l84<-&b_5$!S)}269LT{Ae9YSh6fmRD*Wal$3K4T>LYzm@_$JWa zDt(SbMCsKt40&%5V*|Dfx^8BNJG0OXxKQ4BCSk$h3r2ZP8>7M>daN6WZagb9$W-AR z0NE+@UOwgJZDa%Ja-?fj!{wG7aQCk;BFZ${3cuM+?gmPo3qf0pn|E(1Lf@7>xDmV z`5vd`Z^*HmW6UJ+izOS9GvEE>eik-tlirR zvFVW9nXT#GyQ`kaRM$Z53A6c`1klvppbkfC2SVhhd#39mBWsX1U zD*9OrKA*BO-u`{fgzNdib`2%YEjGj!${Vx)7csFaq^rw)SC7Q5ONnHHg7D>rJlh&a zQ009ZmFw1eewD=cBWc-nuv{?9^wy`PygD1QjEz;xaDE8?`js1)X|M{ZWNL=CS;YT> z+U=31W&l)|psau}?k@{B8A%xB{1_or<~B&^7hc?iLojTtP#8nK=Z86Z3e_oQCih131cX|0?4Unp^EiDq;h9mg~8)5I2z^pp=f z2G*MCokh+@-<9Kd_&h-!3dm$a{mx5nwHbQC~N>=#;@pE=Yy*MccnR ze`&zY!m8v1NWZ|qzzgw$&959P3row3b2zm7!0=wBh!e>}nG%P3_AGk|^jRwtRX5rr z8A8Al2Zu%rsDUm>_IIsIKe}&P5vzL4qIvluQeWb&&w?{P zoc!tNl=h+Z3?a?fAAE?7cwSyD>mM->R_lbs#Bd(1FGj?qq)$PEMs$gY=mJp>=UP@a zwkAQ(ZI)ZF+(|LPW!v>HAM=a&I}gom# z>0}X${zs*6(c+|v@=Ta|Y4%C3a3NZ-u-SECSc7h7L`#8QdTW(x<`t~Jiy#aX1qxLp zvy0pa&6J zcL;oZq;Ge7+va0%6c%gr_lwAdBnUGCZ49sr6oF?5CrL18lZGi_Wk3GCU_zASj@H8B z&g2Go`pcK1bMx~TQDYFu0;*?dfv98-;PH{xs`E`GLfzj3o!Os|k|%RG^9szYpKRw^ z!*U?W3pUw{%s{0_kNV9JwR40pkg2(!YfCm+CP@B%Ic+)cXhqnZS?bmfci!XH@ALaU z>n<#!ApV=(($;=>`UCD$(aTj$2z2=y^VCG%k}Pbo>+1@0!tiGBvriUYXdw%qzhQVT zav0i+@Au;clp)FQuxqdAbT#g}p^#N48AN6`a3GH0%Hdu3j5?xNLcUu;4NY<9Pi*}D z$&=cHJ)S(z`Jl$9E%Mp z6bj&^j`fk7{!Z{E6Sg2^lgqh;ZBTXF(AiZK&}bc!@v-aQlb-p5J0mV8#-_5zm|mKi zpchs$P_n8+3sGA&Q*(T@_)b{voCt}Ln7N_~!9Qc`{_+OmwGCUg6L`U zDBH?NxLb)g#74-*0tdDVa9|ZQs`a=6Qz}JR8q)_?opxpvbor-sYg5SPcCnmxxic@e zBoMVnLjR_SA0Ry>VM=obR~tL9FTzn^69UT+;?JKyy#MtF5YvmQxWfOV=VB-^vJOYV zZVc4vW^_EiuX1H5`(V+&!+9O5_mWl=Nkh8y$z%%G^aXcj7le4KJ39+Q*9d*#xrIb+ zH|R*g>vZ)cR2Tn_J#Vmyh>-6Sz0TnI_`;Le!s4XaHd{e?(Oi$ex?eoeoE0qrmR({5 zcb(hi{asF{@xNbqz`HG&4HL!=03clyatJeUc(C<$celVQ(D83|@M)Hu@6orZ&^B+s zHbaz_iqvgfalcZ0Iu_qZ`%BAd_s6LC2TgCkd>Qc;$0MY1a&!B-X=XnoqHnam z5IVyFbvS|=wSMR8yo#OnV^hrc&*&GB9=zC1MwkxWn-})-xVShVYT8A2Bw$0e0j-os zlR{lj>A3gr2Ubd@HJ>O(#6#U?LvG;i zSlioQf8pX{+_eBjtmXdI!g^FDcv-9-eh_L>#sI1kyVP^fnme{D4Dl*9+A0DBE{n41*wl31row3oA{>+WnjbGgTMP{;bCSsspSe8)T@zU3q+G(=Y@Ah}O zpC6>|o~DdpmN%KbC98Ybuy#%O+XoMr|Jjm_Yf%K+$t3O-LKcl~^qkkoDE zClcDWFps!k2)55UL3c442EF$zg=is87axKKWjfv8to=;KrX7Ag*K+i={snzr3tn_R zW4zxn$*>gDwL%J(#o*g&Y7xOt^y9N!V1T#)Oy{rH?5X9GDgy4N6pgDFjT37GmIoVM zxs2vUjzS_P{X7>bq@phpaeLM+!yA4)_B6F0hGWNtsI&EPIOM7&Nxs{|Td8Awi!L`YHR2`gPn5I`N(Tqc8f$k*#a8`M&kTD9c?U6TgqtwWlG{(|e_Y50#1* zs$RJqp>|iEa*`dOV942B;>bVM$K>8HOyjdidPu>n!5jM<+~<0WCQ0q%#qv&Y3Yr0) zzQfGgfm>exwtEf!q@psxHFTtA(vW^JCJ)z?nY*cPIY+|+i?@d)>4t_;nFej1xVF|p z+x4DOgM1i&UECBeFjEz-C|g1*vq1BbN{w*y62T;d4ce9kkOjax{0Zi~@q(szw6&=q z{sRY$EYL(R)-#&^69k!R+F(U{!y@-)yWyM}5Zk|=!=rTo34(B<-f6@pO@lR_Ylq*8 zf`K8CoQ5f^>yzo9lir6;r!~JMkBspIFqL#7!HWx2C+|6^!^@nVopZngb%ExDz>0q8 zie}cZYitvm4Hue5rO0|8pW5r(zigY+r^rsI9KN!Z@UzJ6t%_o7pwO!-yXM@z^rH>B zh*gJ~n5FfdN%v`mbd5A%60ZzpQ>?Y%yCpw(3X!+ZAo}}*i0#nV>pmwACR6V4=e2~s zdleCOb~4l7&>Qq_^pS~9kmtjO;3xME(ongLu?vtDFjz6|XQ+YYK%v~o;E-5{aM;fY zkS7>5CH85_man7`bKkK3?o!d5Ix5Nl#oXjf-HC8LbxqB+ro_AHRi4PL6hvQx&lP6o z0!ZKcW($}4KQ)0>O^vaf*IyfLk3*L3-C8EQ0jZdv9IuLJVd=sm6D(Ji4R2!8Wxh4s zSRvyIexrG6T{QnPnQ7CYEp70OgCVv}|7=3D0TM>j9H;AluD<+QP;kf9Rjj$CMc8A< zOfO$YR~_9>kf_D=T$}-*3Mwk-?^cSi;exFmbjWXDvE=0BgcEknf|!nOqZUtic(|4; z=yObJE3*4*x@%K)yLTHbvU^mFKw*D=vP-DO3G7&r?d|el|Ec;| zQli!XJQnU4Ki~&8H=xiw;!JRGo1~sGH8ecq|G6~uc;*AD$`z89%A*K)AaM!&KY zc;<>Fa%nARr*<2oH}u6p9S}=mTL5eeTp4tYjU&Lx>NTJv2mY>kG7L~_wxF9UA#tC` zA2m-n87rGF?{c}g=;)e;96CMfa7l>oS|fPc$8-ZKpnSk+00j^sf_0wl@0eAvTMYrq z8)tW0e($=B3s_UJek(z&;by<~3(Z3yUR|QSA2TU_q}?-}^QMJPEwq$F$7`p@@`-2N zF`6lC-hE~UfDs?6?6Oy>74*jr-hW$wEpxafrM5pxjKCF^rA*4TqkLtH8KTP8H7kJG zdyj~lG|%NX*3Tx^CmDJW7$a~90w8HDz(o`)$2wd^nnqX6%Z)&+fgRYZ$AQ}sH_JRe zK}5&>$jbaKyQ`!2fuwVXE9y`v`D> ze0!Gn)1cn#nq|No8Fi^O3k3Cu*UXY308L)Lx8S{bS9v$wrUvu_3;{$=03Ly{+iDZ6 zm-4_V`6B>4DFNzt8*9hJ$r*LxQ9Ttm={&Q`Ro#HYlTRXKv#?D}Hw5#p?KGb?J0||9 zt=^R~5bo#3P5?;RDxgaTGmG8Ocehk=M1Zs`))Z*})EH6QVP`=Nl^ zhRtgSpIK37W`!3SsPOn`p6ysBj%$jUsV7;vM7$&Vu7hKkK_2N$TN+LO;n3!ZxD=En z?%j?GL9-D^127H4do|0jKGSs&wnPa!{a-!iWj<|I8;yCh>`tZd<|!H2gfWAyLyIs02E-%t*DNbOXrpAc$3eugJ8J zEaMCTP6H)C#fg&dTkWK1M0Dhr3zBh{k5a#v50)bx%IB7EpJZYw68K` zG}C*vCt$JeN}%_Mi;7D6axVrf!Y~+%y7V53i0N(j( zoYiXf1V#5fW}DLh1V_nZRwD}_d*G!HuwMHI*}0TfNh z)C)s7{V>wVqq$T`ZS^d#nG2?E>mIKY1j4_Svl58rWUhZ*SfO?BO@1F*R5i?cNcE)d zu_8r`XTmmDyWL;D55B(NYg~$>HSVr^z0^?yR&q{YYWLnr0IgPl)>Qm%*|7-)OOf5$ zVBVl}ONU1g_^^D9hq?s;0)0@xqmD1e4LkpKR;_3)a$8{zCWYBpYm@xI%DAnhIw$&>nUoA0N#SH2~tg6u+^ zm8}&rFLql_OaS@~fpv4Q^zw_u`3b$O;>q02;B;_v%IZ6nw6L&%B)%uV?^T&JOB1C5 zLO&_Sky}1ONa@_hr|8nOxcw01s(#YbX!Ge z4)~ZT7#O_c?#KZJ3~tT=1Pp7ZoB(e(hm{n|22^yV&H)O3rjW11zVrAqjx{jpf;o9sJZd>_w3nC5X3$RbJ?Yjj9XU*T==`z?>|Rt z;kiu|8*n`Ov99D)$8Gz@WA|4_dj05$#6v8Y962%ZdoG6PdWIdd_a=#S38_5;_(vnYp&?eJvjb-Zi zhGD$_LQ)c&{q23h)!xjLt5&amUuR}Q5D^bjlIS68a5|=x@VU2X(7ruHp#Q0xh=L{$ z-JU5;L-}TeMD*Y1_`}2JZxV_A{0(+tLaIopK$MA^<)X-3$B9;t#$tl@?3tUpZUcXg zCcXM-ul%Y0-WT_>w$vS3SGn{@c$Zd;qB=UTMLpgP+Sn-UgyYl6kf0oRF|_Yq$G%Ip zQ0%^Qry_;)a6^l+s15;S8j+L-Cj|fYGDt{zAE9l_*@F_tFf3xXYqA#q=K$vH%L8_c zwjj%e)m2QOAOz{j>ma&!0ZR^e;llJREqUVNCTeY@Ku}UDQ`fYxJ#PO|sCwah>8ZM)!pIlTkDb|{ei9zt%93chzrWwPjl<~7 z7l6a(PDyk~r1SFi{QOf^A1*DsA1j?7v{jp*qZl@+wkNqJZFr*@QhJJyNnk*|->H6I zIM>CPffL)LDxcsM;590Jt;iHoSy^d&0Ys)#b(PNnihFif0{IhE8qYUJHHm3yH3LDQ zJCqB+x(-rp$q-;4_^icFyH5inveRJ<_9#cA;o}aqAhG$M8pENk9~FCNte=Sl0NtGQvSri?|-r{ zODIzpalGX2&%?Wrb`KKep=y5lw8{4JGxg;Gl`O{}T#h*MwI!S|477rdknL#dyAN6{ z`K<>PGw5Eb;KNccq?zG6zIJ{A0d^NY6o(syib2vkrkwJgo_wLNUftF>!0K*kbrrBL zl!q#+eT}u}e6I#r5h)xzJgf;a*J3H>A7BjZ<^-~AgKd-X zfEyz`CR!c!rdUAaFTnfG~6Ob|-0s472>7`DG`VA+zV1xQ;2l z!3cCSgLBV>;GQ{pY#fC6fWb}>+!YXmK?yvn0I!j(wG~CG9XY=$3I{m)J2n;;9RP^@ zPEDl*BaP3lm5Dl;3$8p}|CGZ-Lqo&NGjVx5<-rWTyrZS1MILMpx;-ExH_27i2N)V6 zkY>CoF}qR70Q*J&1hyN>-j?KN1A1vZ`SEUPtowwQ+oGL^`k%;Jc*zwk^k3~z1S>2h zbwpQu(&m;`{lK#wc(|quu+vyFa&qNK{{cRc@po0VP8x@{4to0o?P(IqqZ8H51gF4$oo6H4t2qB-Iwq2GQEXr)xzVNI z!5xurGc!_c6%7B^wqAdP1TJ)nE;?$9c= z65OvwMgs@(dOPRJc-JND=g908T|uowSAF5b*I&m4k7#Mwd802cUtyeHG=vb%qZT$F z>umU1#!>!_sIau~yi(?|eA%GKK!QCeI*5CH{VjXYW5}6=)!2Yi6z}mLsOcCM-GR8C z;Xq(O36gk+g!v348+GLLv;>#x6}Ey5pqUTWWN~8<(%loj z*5DxH!oVv+eR1%AaXuSB@pM@&)zqBp{jZW$k4RwqWg_JWz{fuTe@yQVTI`DZZo;6E z%9m%kQNhy;WKIDW@$%(EvJ6B>tk=0usHxL2%7^7X6%183Tj&ZtFX|hc9vppj*?cU4=3TEP#JRY*ChtZ6R^0ES3l4bO2Eai9RX}oZ*j(-Mm^iCs!0+tum&Zbf6Uh_FJiyY=e zKe*wie`F3gTnhmyN}%^(#UFI(SDcYSgMiCPLx2vq-r&_5T{qhZi_X{4B@RtYoUQl! zm;WGutw+>t@{f45A{KD@?psgCSCUm>3Ra0kC`@lpp#7cWMT)^})7RL)Zq(?I(o)x$ zalE>aSega`S*+-MSEgWy^1(9}>{_oAaB1UBu1545cQVWFJ7S`*H+@*OpSRQ9{&61(}|fw z-w{^TLd0KB!@*wiLP>Ub^k02Y0XZl&EHJD`%kegNzTHPxJ0yg^42P+&qT#N>>2}UP z-Jro-WSB0{{&E<$~4(%4^Ww;pN?|^1!7ND}B0iv${;pUjO_>z7`tlaTv%B=i2B-jVPJ136Fnj5axc&?T;kf}Qu zmitx~k(U^nyf&CSlxtM3oYvO%=STd3kGD6vlJ0L}X62HsU1`F%>>B zVkR6yrH;x&b=X*Isnt1!uvQz{UdPzc(#?V~k|4{iAM0_YlRHo7 z;GgDF89Cy{KFo>28kY$BQ6N075xaseOXI&n zdnmf|T~hp_;I<^aZfO?bs868ys6h~#@(BT!jZDb^+|Cqk(1U)-u`)Cv1Fv`Qv(8EM zTMr2Z_TA{hsRG!ie***AP;W|6DH(^^Z3J0E>@1I*H)|&a5vb(LDLVq$7cUzA^z^7a zy*#CdkTDbzcHbjmYrhL|SxB$}m$MMmBbjEMP9FSkNk{28C28{x~PCh?8Gc93P$;y!;rO5i8we&A)AjtUn3d+g+ z*)jV05f-)EX9`r(=g*8Pi=;W07`fSTEwEQ?D}XElFc$z%A(JJwaM(=%urmv}1v_Ykdz`FQnm9o^Dq zE$N8Os~<8{B7Tx@`MdCugve)*nowcja%d!f@F&-Y`@^G0gGu{plpP}@!oeU&^iL{( zd}TdgvAh)HXkZoG@zB^OWz)z7Q%Y65{Ut<4tBo*`h9uAGVB?N31jGf_fBJw0fU^+N zNnYE|pTOt;|7$-O>ObEDl2vpFTmzrKy`q5r|1)NS45nEbJQc8y`>F*rS)a{s*TzYS zWQ^B*YH4n6R)wO0?Qz8T6u@LyG=~YQf6N7MJ9>y9HQinYX+bQ5?B%+0ZRxL398vgl zbj>X?O;SLAP5mGhEv3*P{;RJ{Ql^0>139x-0dDC*Pft%wFUb5A+wjNVE`QWw2Eq&S zKRX22=pWQn2aTDP0`$G@Yq6CGG2uyAq~ z7fjPzuC~0{@0%nvl0ly*#2m*>z4_f^_42wqLOZ=`6(Nh;Lp70^J1{-&z0jW0c6Pc* zm=hW#$WBf0bII}Yu2-`tL7kz34%r=cA}kCnM5tVaeL|SJ{wQ1FJ0t(J3zai@$jHs`s z8)IoAcYQY9I<=n5n|Klf2^Tixc?Ui+xyw{qF&*+Iy{O1zD{MTK>u|5Y^YWBYPrso3 z!^5|ehFHB;^?R&?hf8O;6s?D6Kj_=s>sruptr&!8rGme;r$}4b{mu@5O@$9Re+zwm zf2hWNKNMUxvzttYM3($NlR9@??1Hw64tU@c#9!<$y$p!OdEIW3q$(uGLL$XWhSP$8 zhnRzgj5TQK4QxCYe|+R;@oAV9IxT#ND9Si*6QReLsj|bgnVJJ_uBVNkfOGc4tutxD z9~}y0Lyfk+2q7k^#L^GBPsH{ZpPKNt%Fcsu=|<) z!tx)1S>nx`G?KFEGFwAqx?f}he2S6&tlzk`A9{XJ#dVO9dqtfXPLa2kAFnTzdw3r4 zVZ)KV-j}?ivWceA2e)g4MA)Bj5cN8pjnDydE__9vQcRZ%+k;MHB2grAVb|upJ+4w(hZa!kkYN`Mkca`4oL!*~SFk zdt^XE1oULpw);!n<&%6&Orgz3qvilw`#j#tl=S$G$vrv_@)!zmmK_5fHIJ|LH=e=oE zErQpB%?RYqiw1ds^XC)T#`6@2Lw|zh?4=5z;%<`XJ)tHtkeewA9XEv!W)oo{ZsiBU z<6_UAFjDn*5XxwXc+BE?9Xs}CMuBxh?`t+a^lnaE8*gAB+og^*-I^Dlj~fQ|g$X8M z;gJn~*T|l`XO%z`2Vhn=UH4KfRl4MdgJ1|{l=Q;sfμ9qM%fZ^TAnH2G&6r-1c{ zi&OhyI9=<%!BC##doNDa9ly+R_N$!XtY0J&@%EF^?Nj{qVa1O#ij*)!jCdnD+lGiO*1{yS9`FECo$ z)FdRKfLS2VLbC8yTRKDwn1{)|+FMMJx%F`q^IE|RlV5NW&vGwe%>b-px1H6pqgSq2 z#=I%&SC^MS6B$D=2%!E4yYIh^e?7Xu)6J0yp0#Zwrl#gvR$Bqx2xGuh2j>X|=L90L zr~5=NHnYyw{&W|PI2|3SEnWIiJ1sqPRy)~Q^0&=DYrR4_2inn@#O=KO%NRvTV5w@- zvp3;OGkTmzTf>oo+wK3QAgtW zHAeIpIP%|k`HKx&bU+L+X?$L+32!Gk%nlN`m7TnK|A2&u8#|*aSl`}F<5zMxdha(K z9nic~hX0xMHRVo>|e+SxUTo$C!c0 zcyYRc%g@jB>zI+}@o~`NzqYHsGhymIv-B08&BNj`Hx^SkL_)YLdcE7-_Moz{OkrT6 z*quUcAoYurw~7cbA?l~g_UL`F&$%i%#+7uc_+_eX?qSu@bg%M$?|XCNS@9LBsDuO+ zz?2FyG9rJc=HNvmkR1%#y`>`FK0b8jR#tN|LPBJ~mjEpEemf1Thgl8EuK-cLAU7BK zFDOG;s7IwS{Jabd`bUkYYgaXPKM0HzyvUR|>%;f(-KO@hJ`Q>Yfu1F3NooY`?Cuhp zV>bi#Bk;!c!447pbpLM#{uDTbnS|kQ3|TySevAQ{iDC4jHyU3a1>PAWC0!73zx%H3 z()PF3$|)HR#Or3FfMLAVr5{kIKtY1BoWBe~DTX}@fb0>Y-nn*h7#eV761@AM_IZ%* z(4twE)oiwv=gOgyA|9>F!IfQ4VyI31oSu;E_Ypf^p`pnbu=O{!=45g*uMya@tw~h$ zhAxrY1hxFI(u`$>xpp@KMnq_k+R4b>HVzb!M=Wh#YTqyoaq^-L%GAvdu!GO8;SD-OEziv zJ;y2Qy^r}EN-a@-H)KjSfbPU1Elme3yCPy@)a^kKM=0(YnrB5xiN9IF5SE3dCBIEO z0_1Gt0BjBXEub@r2CO|jmwpmof~dz^k?2eCQDe5P@L2%y23U%e;lpk@oMrvhJQ2`W z_nD1EMu?D*@CgVBZJ%~J{@TPNFKebJzf)!rMF`FB*-U3qMT{uOrz;%Wpn*f`7U!Df z3mP!gLk`^}9HF5_-@tJHdqAvCudM3ILVo`R#f?0%Q9^cD2(vQdsXOOr0D)5R4<5WX zs*!4iwj-^-A1dtq8U81BzG=GEe}(M1+Qekb8kiLU0^wvwIiPB1U3j zKWoT*_PxwIe7ZXM5k{CTi}nt_-?6gea473nyPNp%g2-P*IQ?wAwv!i`6s^)vB=nk%)?CW(`&@`^JXD8hEZaQBs4L>$f zf?3Q=TLrJbS99J^jFFGPx|U^aC|@vMNg`aQ~bKJekgm-8Mpbte~qS<6EsQApXgL$$Ngh9RsB3 z#v!uvE`6t<2j3fQ@A&vu%9h!FNb8M-(j!CB?an=7)G;+2xttYsqr>>v_rtHij#uXV zuK$iq{2QhF^Txr!^^h2IiauY}J*{GcH`!7WiyOiW_n62`&Zr+2F{Hz6U~BMJ>|UHGp3g0L<8%_}DEz?0Qrd>G(Ys_N;zc}FEEL=Fq5B@v|a*nA0v z9|Fs6&MQ77Wg5-y?vX(CbwPf95g?V?@=)8lP2{o4uZrK@J1jlg+hs$MV%ru`!w7wG z;3eIgm?0&wB4g4&+}In22q74Pe8obh@e`#XdDgDZ)K+E+SvQE>ZdKFcak_yb6(zA^>RTI z%8@v@6zG8PZoAda*GW+gkVXL}npiDh0#-34{oLNHZ0iCg(q6CNfHlZF%H_ZTM4S-4 zVnqP{)tK=BX8{#`GKV9W=aTDryfng^6K5W4ch1Ol{4*?AJ^S@Wi84bV&j#ULl~4aV zGGr=Mtzwv*oOEvd=+K;GqB}NyZT9Ag9k(qT4I=p$ZFNnSUf1S0*j%1g`K=B+_;EWE zw4x8*6gyQNSKo{5e3UBgCf2%Qy}L*#VxxG;&@A!z4$i0gZ`=z%$bX#It9c4pg&^Dd zmMsV|38OzhD~!1VJE4e%C=-}7m`^`0nlM+($|zWBU#27;bvvvX!)nOTUBh8_X-5Zo zdYHp!Wk`wnEQtuswIIY(1P*U=lbyOI{z@*J5LamtsZW|2yW;AuF)HR8`7 zA|h%(KN9pPL}Xl6G%#rT()e-fNI<}?V!Kok;htp`XrmOaPe5E_ZAJ4UglN)aD!$J<&+=|EV2H%+1JCkWvvtsqdKwN z>Hv0);J;L#GH-%9*QY1BoSjPUfg(Fo>?s_q=q^WDVPS~3ny_3VRPjiuG2uVZue58Q zw+cMElO1?$T4r8XF%e@0>~=~@N_0R1iHN;B)vo^%m$4} zgs=YWQjeliPA4((DDdFtjTDJD!RqmR@SM)*N9g7CgGn}G9Ti16xsZ{GC19tLRF*;} z?kjJ!dxiXp%++RR`E(-Z7$k{q|0W=mVRFR=S}a7aBx9s+-g6Kz6+ENShV11xG|~#O zka@U%l(=xTMnzCZsAB3*Q9T0c)tF|G$5|d zm#e+~@!j!HXspn6{X@CG@U1EQqW5GRaJ+a=`3Yfa(5RBLu(;dFMrw5IPi1<>^m$2t zN(svI=5OSc4z)a#BHzG3CBWZxgh%nZc=Km&5sQOe0N$x-S=~}Wf>M$H<~_)#JLLO3 z_QCzhcja0;*`cL%CFzmqp1x1Rn@TB(7ZjAtTUq(HFW1t`yc|bCVfOMs>X+g!IJG?K zMk`12JOh#xZ@|9U#d#%s1xDIXu-jRP8i3dqjnA|B<{%Eh-CKw581T#9HRt(mCnR$ts z@H#>8bp;8|uY)%0O&70CpGJ?3mx-3U7)LRO`=brzyTa z!ueqQOXpiBuZE95gMo2gdHW@x|Gr{kWP~}sLGUY9VtAGSVhbzR`;rJ9j(7Eq8!5JK zv&~e%d^1e1I83cj-p-C09F7gdvv?zjp1tks7Izj#y%IoJQ=(hX)?xk=TpRvDSox9F z?xeyhsbv|F*_rh(V4{V%Ec+VVxeB@OpRZ5%3hbM6t{<=mw6@Z5h#UX8d@+vX12wptPc*Ydk{1bV5+sz>(}oFvwkBy4Dn`K|iam zq5@+IYWE~I4+?;0eD^fXuNw1EW2lMm&_kL)^;j@b;z5&`vXd+*rGVwEN*Wm>D$usD zb7Y>rJ&-6oCA`(OBEfuRc3t`PYh;hqg1%JbRm2}O)C%{qULwI0l%H#a%r;E|q%4 zm+2qZ{Xh3YKUvUi<+m*4ZwM!ekTzr};%yi89Z26#$cKzBj&|fQ=ZgAkVat=_D2W03 zLBB=9w@fo|Q6saM^p%D70#w9U$XDp+RY8vJIYHCG80-Ncim7m=&*Rra z#=$AEM*5=40=dTw{7-RgZEefGs(`iaVIaxgbF^RXXuSQ9CQ^%p!4l&`w;Krz6RfhX za<CWs1UIiIU+mV2y=}`Y2apc`PF!&7XD>Omk|`&8 zN4}-t$?w&b%eGUKgT!O2ePm}K=r;jiF2JrpnIrlO3u5|@vv-y(!_R}0lU-AD^NYX# z7JoDWy3V^%=UV)ck&!x({t;LR)Sj%s2Ab25>wQM8**1?nmJ1BUf-Vq=Gyc2vx5ySQ zt^1Vj;`Q;QF6V0ksoA095-#+ggTILU#tExsYI!xlOFs_OKL5$v%RU?s198}^#+)S&JxFY_+M`ER4lE|Z0pNV0xY`cvZ-!dRcT~(RBBe&yu1cmG+~gEt|DltpV`Te1JD2%9^QML zj-ffs5N2{ArB*u9NFx7SNK@2VDE&%4FOdWb(GO)lNe|chL<;6sl~L(-#qfGR&C9wz zQP|%FN@CAK10|o`=}?zD!g~kKkFU2J3%TJhB?^LXu8q1I%eU~U1i~6kM^#5()}VE^ z&AB_=um3~{M?*7B3O4_y7f*KERG6cC3t9?9ho ze;Nt@Ai3Wx@W*I>DduO1BCupnKAs3!S%MY=90`6lm;ei^r@9;&UZ}Q_E=A>~ant9+Mu>29E?L;BcJ|wNZ2FkNpuEhTHej?=+qeVTntGrc zqmqFQ@lT-v&0pU{eQ}>HWh#^IVw}i0NjVSA;%8#A*co86U~g~F(Ywvlf7j_r`Nw|` zj@O29Ay4(fP@{>W`(-7t+_?*+x;sK)AM>!Gv!SdOKp={;>(!e;pBHKTCmVtYZf>~% z%O^RNEjOXP^-`37>uRO$a&l4aC&a|*zyuy@eVtyJvqpqHficu=N{(z8EUmBsc?&5v zHdP-n%sdSBE&tV0US7*y-pf197A>+a-a1LjojX>+(GyL(P68sHnFdTrCU@Y#*NaIr z>9r9Z@qM`8<@;OsnfxYWV|a@g%3L8#o$Txu^1!05^Q#o_io=EaD%rYo@*&)lR~l^036fuM1x(8nlw>Vj6%~Nz8h2t; zrmOpR_qBy7_5BsVWC892pBi z94S4)i^XliXMzr0Ou4V2TUHx@U?C(5B}?fpf|lEP^HEwfB03sJ34oKEs>pwjPLfqq zoz-4H(a5(@*a8MBMhV?LJ$6dhpo(;S7!0IAKY#v2=E+*Wq6_q2P<9Xw$`mEFEPBdu zW=jnJglVfS@m2=u*p7(=y49~7PE2Uw%kjrsJjDFNbStXCSLa9I$7Q$b^Tv;Q9->-E zb@YAbHa%A>NGoL7e0IbahysS4lTBZWR7LRB#=3gLlo{MXk(I<4)deEit%S8#W+&kMvX^@dw(dLMT=Y&Yle!f!A-QWiVHY?5u(r`Dg*!%kM#`OZ( zX$qKbWdXqr+I7JR`NL5ru`4(H8nd0KejxchFm-Km238+;_D0QejkV`TefULQ7I#hW z_NI6>9z@v*8q#PTa}PX%o$z5#pI?(^7)d5DqFoK%zqT~m{zq5Px+rHlSI5htEUsUTASmYJtZJDl%ico|Z z!QZ_GdbbzuJq<^SF|skS?S|UMX+E-Za44J^15Sj{7C8)@an3IkUk+>cU zYUsO1`-Ri&)U$H5^vJ=ed=6vC2I_~c0go(a$e?@qnRL07%5WYQh=$% z-_;dzJ8pjwk8J2hCQGV#!3%j%ekUvKSFSC=(D>EHGnVEXSdH!?1AN}6o-#mf2ZCyJ zadRJRqLpmUJ$Oqt#Sz0gopvm9&u>MXx8FSUJZA*Nz+3D@Vj+3{T7wzyFPzB-Q~AX; zFa4cX^qD#oCFsa|O4A(BRX6qOvHNISLB3hC5tfNLZDK}dOlmJ>?=&9E>c-qE+v>A; z_@83ug~i|KW`<~yNbB!ElWz4p8wG^YiGyL*{cpYIXF6%{y}buFYCL^6@Zx0chL4O4 z4QowkQQq>_-1|<}1z5m*h7I_x0&19j%syC^n53j=!5+WO2A_;RjRWryO!;bIoIUQt z#Vg^#h--GVdW1C}@-DPFSfl@`a0ek0{`-amj!Gp;m0F#6>HcI?2+h$iB#r22FTQm? z8kq1nj`g`M;*V6?CrxA)ud1tr?Y12gzf0E(v%xL-2zUj@WX-QJ=O?K0C2l&76L6rs z#Dm(YFF5U#pRCSg@CY&C6l6@j+f){Q9N4EPB-P8?cVJ+ZM4b{}5ef4muwNxxAF1Rl zT71Lr%@DdP>gAK)_@#^S4xEr10)jC$Pza^XVAo}>Aa|8#{o0&06)8O2hu`IfQHvE8G{qvUz`*IV(|Sp2a!qMwQVQuhQi^ZBSTjm+`5U7xqt+8|^5p=fw18elz{TCD=G zzv$f!vMi_-D=*OO=K8G1`NJhUo@=-NWX%%;aLcIxu@UeA%>o|*8Zj^yQwm55ek-a~ zyFA{;xD^TKOU1id+EvbOr{#bqabi~qAz%=d?C9XYnL5};^^~Cnz-^)2*i(}a#r>&r z^G-aXPpR@cmS1Y8Ooyy&nb*Izny0A40a(Vv6(&UA4Uy;=4?I&5nHwk|VO5GLANZ-7 z*CPQ7*p?~JY!&G))72PPVu(Ey0j-7{H<{O+3DU6*^p_L~Ehm~y8gveb$NF^8uSZXv zwTtHT$QT;Bt3}y@6?W&SF9WZtE@XMTj;V3SwA^!_z+pq7A32ERbD5FJY=h3VI!0r5 zKdNYnHos@G7gAT^sG9Q;=wGTQy@+kW_hLeFpV3UJtE)2uLa`#?i0xuuydeR_Y%a6k zbv!xzV{>poKBPII$byW3nvW?`FEJr`s1ef)q8vEaR#S7P^A#n-4By@UH}AIoleQLb zF!RKN`=4NHl`U-$VsGt2U-k=mNO~a*TSlvoCxf7QNzQefFkp4f4OI9sQo&g2o4HR z^L$7kt&9e0`$*%!fh2=igNfNK$CA5t)#)HF;t+sYtH-^T2Q8Y=QYi(dH7rga{FdOw zmw6a=%C4w`m#O9)`0Ri}GlpCWgfGj+oAVlR9> zWCADZt15;)LDz=?MMN+D3rVTX_429fCj7>UNkP&8&AZc`Ew~2Mcd!_VV!jvYiOm1p zm9e|3qhX+B@K*i%`L?96>A<*W_FW1SB}EK1{hS+|1vI2oNoeh--F3J;DtUJ@LjtwO zj|^&Q!$EOF@nF-V^-C=cxK&}^Rt?LrHN<@-=-G*&9JKe%DX`Q^zl0b51h6z2Q) z6L@)egjoch0ACQNT}Nz$S5ywc8boIhI>++FUx38KG|70NP0z6 za1gXDx!PCBn9|b;@bj4=fvj51?V-^m$mI-x-#p=n-lR5AON~3u@V_Oc5?n2 zs!4m(KD7GSJ$7QKVdp_R6;hQqrOllP9`Nf?#!zLTE?AY>mzI}rZNJfFe;+!D{u9)N z%r|?fyS1~}T%O)F{_FESQT9LF^GvNvic|HWsY8B;?gpH%2QcOExDV9S)J$V7Z3M7y zgq+a4{DQ~t(=|j`c*Nv19iZ$N0vgb?vmsKsplTE2nULwtgyV%Tw5NWlp$LoZF~Nmg zvc=4`XGXP>+?dD%qJ9l2{ul=gKW1<%nL5sK@bGHZ>(a4)Ezl~fP+o|@d?D}iuuC#@ z6#D4c$(JVy+~EK9HhxJ*p->fIFYc$!;M1& diff --git a/release/scripts/bpymodules/BPyTextPlugin.py b/release/scripts/bpymodules/BPyTextPlugin.py new file mode 100644 index 00000000000..cd5a085de37 --- /dev/null +++ b/release/scripts/bpymodules/BPyTextPlugin.py @@ -0,0 +1,814 @@ +"""The BPyTextPlugin Module + +Use get_cached_descriptor(txt) to retrieve information about the script held in +the txt Text object. + +Use print_cache_for(txt) to print the information to the console. + +Use line, cursor = current_line(txt) to get the logical line and cursor position + +Use get_targets(line, cursor) to find out what precedes the cursor: + aaa.bbb.cc|c.ddd -> ['aaa', 'bbb', 'cc'] + +Use resolve_targets(txt, targets) to turn a target list into a usable object if +one is found to match. +""" + +import bpy, sys, os +import __builtin__, tokenize +from Blender.sys import time +from tokenize import generate_tokens, TokenError, \ + COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL, STRING, NUMBER + +class Definition: + """Describes a definition or defined object through its name, line number + and docstring. This is the base class for definition based descriptors. + """ + + def __init__(self, name, lineno, doc=''): + self.name = name + self.lineno = lineno + self.doc = doc + +class ScriptDesc: + """Describes a script through lists of further descriptor objects (classes, + defs, vars) and dictionaries to built-in types (imports). If a script has + not been fully parsed, its incomplete flag will be set. The time of the last + parse is held by the time field and the name of the text object from which + it was parsed, the name field. + """ + + def __init__(self, name, imports, classes, defs, vars, incomplete=False): + self.name = name + self.imports = imports + self.classes = classes + self.defs = defs + self.vars = vars + self.incomplete = incomplete + self.parse_due = 0 + + def set_delay(self, delay): + self.parse_due = time() + delay + +class ClassDesc(Definition): + """Describes a class through lists of further descriptor objects (defs and + vars). The name of the class is held by the name field and the line on + which it is defined is held in lineno. + """ + + def __init__(self, name, parents, defs, vars, lineno, doc=''): + Definition.__init__(self, name, lineno, doc) + self.parents = parents + self.defs = defs + self.vars = vars + +class FunctionDesc(Definition): + """Describes a function through its name and list of parameters (name, + params) and the line on which it is defined (lineno). + """ + + def __init__(self, name, params, lineno, doc=''): + Definition.__init__(self, name, lineno, doc) + self.params = params + +class VarDesc(Definition): + """Describes a variable through its name and type (if ascertainable) and the + line on which it is defined (lineno). If no type can be determined, type + will equal None. + """ + + def __init__(self, name, type, lineno): + Definition.__init__(self, name, lineno) + self.type = type # None for unknown (supports: dict/list/str) + +# Context types +CTX_UNSET = -1 +CTX_NORMAL = 0 +CTX_SINGLE_QUOTE = 1 +CTX_DOUBLE_QUOTE = 2 +CTX_COMMENT = 3 + +# Python keywords +KEYWORDS = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global', + 'or', 'with', 'assert', 'else', 'if', 'pass', 'yield', + 'break', 'except', 'import', 'print', 'class', 'exec', 'in', + 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for', + 'lambda', 'try' ] + +# Module file extensions +MODULE_EXTS = ['.py', '.pyc', '.pyo', '.pyw', '.pyd'] + +ModuleType = type(__builtin__) +NoneScriptDesc = ScriptDesc('', dict(), dict(), dict(), dict(), True) + +_modules = {} +_modules_updated = 0 +_parse_cache = dict() + +def _load_module_names(): + """Searches the sys.path for module files and lists them, along with + sys.builtin_module_names, in the global dict _modules. + """ + + global _modules + + for n in sys.builtin_module_names: + _modules[n] = None + for p in sys.path: + if p == '': p = os.curdir + if not os.path.isdir(p): continue + for f in os.listdir(p): + for ext in MODULE_EXTS: + if f.endswith(ext): + _modules[f[:-len(ext)]] = None + break + +_load_module_names() + +def _trim_doc(doc): + """Trims the quotes from a quoted STRING token (eg. "'''text'''" -> "text") + """ + + l = len(doc) + i = 0 + while i < l/2 and (doc[i] == "'" or doc[i] == '"'): + i += 1 + return doc[i:-i] + +def resolve_targets(txt, targets): + """Attempts to return a useful object for the locally or externally defined + entity described by targets. If the object is local (defined in txt), a + Definition instance is returned. If the object is external (imported or + built in), the object itself is returned. If no object can be found, None is + returned. + """ + + count = len(targets) + if count==0: return None + + obj = None + local = None + i = 1 + + desc = get_cached_descriptor(txt) + b = targets[0].find('(') + if b==-1: b = None # Trick to let us use [:b] and get the whole string + + if desc.classes.has_key(targets[0][:b]): + local = desc.classes[targets[0][:b]] + elif desc.defs.has_key(targets[0]): + local = desc.defs[targets[0]] + elif desc.vars.has_key(targets[0]): + obj = desc.vars[targets[0]].type + + if local: + while i < count: + b = targets[i].find('(') + if b==-1: b = None + if hasattr(local, 'classes') and local.classes.has_key(targets[i][:b]): + local = local.classes[targets[i][:b]] + elif hasattr(local, 'defs') and local.defs.has_key(targets[i]): + local = local.defs[targets[i]] + elif hasattr(local, 'vars') and local.vars.has_key(targets[i]): + obj = local.vars[targets[i]].type + local = None + i += 1 + break + else: + local = None + break + i += 1 + + if local: return local + + if not obj: + if desc.imports.has_key(targets[0]): + obj = desc.imports[targets[0]] + else: + builtins = get_builtins() + if builtins.has_key(targets[0]): + obj = builtins[targets[0]] + + while obj and i < count: + if hasattr(obj, targets[i]): + obj = getattr(obj, targets[i]) + else: + obj = None + break + i += 1 + + return obj + +def get_cached_descriptor(txt, force_parse=0): + """Returns the cached ScriptDesc for the specified Text object 'txt'. If the + script has not been parsed in the last 'period' seconds it will be reparsed + to obtain this descriptor. + + Specifying TP_AUTO for the period (default) will choose a period based on the + size of the Text object. Larger texts are parsed less often. + """ + + global _parse_cache + + parse = True + key = hash(txt) + if not force_parse and _parse_cache.has_key(key): + desc = _parse_cache[key] + if desc.parse_due > time(): + parse = desc.incomplete + + if parse: + desc = parse_text(txt) + + return desc + +def parse_text(txt): + """Parses an entire script's text and returns a ScriptDesc instance + containing information about the script. + + If the text is not a valid Python script (for example if brackets are left + open), parsing may fail to complete. However, if this occurs, no exception + is thrown. Instead the returned ScriptDesc instance will have its incomplete + flag set and information processed up to this point will still be accessible. + """ + + start_time = time() + txt.reset() + tokens = generate_tokens(txt.readline) # Throws TokenError + + curl, cursor = txt.getCursorPos() + linen = curl + 1 # Token line numbers are one-based + + imports = dict() + imp_step = 0 + + classes = dict() + cls_step = 0 + + defs = dict() + def_step = 0 + + vars = dict() + var1_step = 0 + var2_step = 0 + var3_step = 0 + var_accum = dict() + var_forflag = False + + indent = 0 + prev_type = -1 + prev_text = '' + incomplete = False + + while True: + try: + type, text, start, end, line = tokens.next() + except StopIteration: + break + except (TokenError, IndentationError): + incomplete = True + break + + # Skip all comments and line joining characters + if type == COMMENT or type == NL: + continue + + ################# + ## Indentation ## + ################# + + if type == INDENT: + indent += 1 + elif type == DEDENT: + indent -= 1 + + ######################### + ## Module importing... ## + ######################### + + imp_store = False + + # Default, look for 'from' or 'import' to start + if imp_step == 0: + if text == 'from': + imp_tmp = [] + imp_step = 1 + elif text == 'import': + imp_from = None + imp_tmp = [] + imp_step = 2 + + # Found a 'from', create imp_from in form '???.???...' + elif imp_step == 1: + if text == 'import': + imp_from = '.'.join(imp_tmp) + imp_tmp = [] + imp_step = 2 + elif type == NAME: + imp_tmp.append(text) + elif text != '.': + imp_step = 0 # Invalid syntax + + # Found 'import', imp_from is populated or None, create imp_name + elif imp_step == 2: + if text == 'as': + imp_name = '.'.join(imp_tmp) + imp_step = 3 + elif type == NAME or text == '*': + imp_tmp.append(text) + elif text != '.': + imp_name = '.'.join(imp_tmp) + imp_symb = imp_name + imp_store = True + + # Found 'as', change imp_symb to this value and go back to step 2 + elif imp_step == 3: + if type == NAME: + imp_symb = text + else: + imp_store = True + + # Both imp_name and imp_symb have now been populated so we can import + if imp_store: + + # Handle special case of 'import *' + if imp_name == '*': + parent = get_module(imp_from) + imports.update(parent.__dict__) + + else: + # Try importing the name as a module + try: + if imp_from: + module = get_module(imp_from +'.'+ imp_name) + else: + module = get_module(imp_name) + except (ImportError, ValueError, AttributeError, TypeError): + # Try importing name as an attribute of the parent + try: + module = __import__(imp_from, globals(), locals(), [imp_name]) + imports[imp_symb] = getattr(module, imp_name) + except (ImportError, ValueError, AttributeError, TypeError): + pass + else: + imports[imp_symb] = module + + # More to import from the same module? + if text == ',': + imp_tmp = [] + imp_step = 2 + else: + imp_step = 0 + + ################### + ## Class parsing ## + ################### + + # If we are inside a class then def and variable parsing should be done + # for the class. Otherwise the definitions are considered global + + # Look for 'class' + if cls_step == 0: + if text == 'class': + cls_name = None + cls_lineno = start[0] + cls_indent = indent + cls_step = 1 + + # Found 'class', look for cls_name followed by '(' parents ')' + elif cls_step == 1: + if not cls_name: + if type == NAME: + cls_name = text + cls_sline = False + cls_parents = dict() + cls_defs = dict() + cls_vars = dict() + elif type == NAME: + if classes.has_key(text): + parent = classes[text] + cls_parents[text] = parent + cls_defs.update(parent.defs) + cls_vars.update(parent.vars) + elif text == ':': + cls_step = 2 + + # Found 'class' name ... ':', now check if it's a single line statement + elif cls_step == 2: + if type == NEWLINE: + cls_sline = False + else: + cls_sline = True + cls_doc = '' + cls_step = 3 + + elif cls_step == 3: + if not cls_doc and type == STRING: + cls_doc = _trim_doc(text) + if cls_sline: + if type == NEWLINE: + classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc) + cls_step = 0 + else: + if type == DEDENT and indent <= cls_indent: + classes[cls_name] = ClassDesc(cls_name, cls_parents, cls_defs, cls_vars, cls_lineno, cls_doc) + cls_step = 0 + + ################# + ## Def parsing ## + ################# + + # Look for 'def' + if def_step == 0: + if text == 'def': + def_name = None + def_lineno = start[0] + def_step = 1 + + # Found 'def', look for def_name followed by '(' + elif def_step == 1: + if type == NAME: + def_name = text + def_params = [] + elif def_name and text == '(': + def_step = 2 + + # Found 'def' name '(', now identify the parameters upto ')' + # TODO: Handle ellipsis '...' + elif def_step == 2: + if type == NAME: + def_params.append(text) + elif text == ':': + def_step = 3 + + # Found 'def' ... ':', now check if it's a single line statement + elif def_step == 3: + if type == NEWLINE: + def_sline = False + else: + def_sline = True + def_doc = '' + def_step = 4 + + elif def_step == 4: + if type == STRING: + def_doc = _trim_doc(text) + newdef = None + if def_sline: + if type == NEWLINE: + newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc) + else: + if type == NAME: + newdef = FunctionDesc(def_name, def_params, def_lineno, def_doc) + if newdef: + if cls_step > 0: # Parsing a class + cls_defs[def_name] = newdef + else: + defs[def_name] = newdef + def_step = 0 + + ########################## + ## Variable assignation ## + ########################## + + if cls_step > 0: # Parsing a class + # Look for 'self.???' + if var1_step == 0: + if text == 'self': + var1_step = 1 + elif var1_step == 1: + if text == '.': + var_name = None + var1_step = 2 + else: + var1_step = 0 + elif var1_step == 2: + if type == NAME: + var_name = text + if cls_vars.has_key(var_name): + var_step = 0 + else: + var1_step = 3 + elif var1_step == 3: + if text == '=': + var1_step = 4 + elif text != ',': + var1_step = 0 + elif var1_step == 4: + var_type = None + if type == NUMBER: + close = end[1] + if text.find('.') != -1: var_type = float + else: var_type = int + elif type == STRING: + close = end[1] + var_type = str + elif text == '[': + close = line.find(']', end[1]) + var_type = list + elif text == '(': + close = line.find(')', end[1]) + var_type = tuple + elif text == '{': + close = line.find('}', end[1]) + var_type = dict + elif text == 'dict': + close = line.find(')', end[1]) + var_type = dict + if var_type and close+1 < len(line): + if line[close+1] != ' ' and line[close+1] != '\t': + var_type = None + cls_vars[var_name] = VarDesc(var_name, var_type, start[0]) + var1_step = 0 + + elif def_step > 0: # Parsing a def + # Look for 'global ???[,???]' + if var2_step == 0: + if text == 'global': + var2_step = 1 + elif var2_step == 1: + if type == NAME: + if not vars.has_key(text): + vars[text] = VarDesc(text, None, start[0]) + elif text != ',' and type != NL: + var2_step == 0 + + else: # In global scope + if var3_step == 0: + # Look for names + if text == 'for': + var_accum = dict() + var_forflag = True + elif text == '=' or (var_forflag and text == 'in'): + var_forflag = False + var3_step = 1 + elif type == NAME: + if prev_text != '.' and not vars.has_key(text): + var_accum[text] = VarDesc(text, None, start[0]) + elif not text in [',', '(', ')', '[', ']']: + var_accum = dict() + var_forflag = False + elif var3_step == 1: + if len(var_accum) != 1: + var_type = None + vars.update(var_accum) + else: + var_name = var_accum.keys()[0] + var_type = None + if type == NUMBER: + if text.find('.') != -1: var_type = float + else: var_type = int + elif type == STRING: var_type = str + elif text == '[': var_type = list + elif text == '(': var_type = tuple + elif text == '{': var_type = dict + vars[var_name] = VarDesc(var_name, var_type, start[0]) + var3_step = 0 + + ####################### + ## General utilities ## + ####################### + + prev_type = type + prev_text = text + + desc = ScriptDesc(txt.name, imports, classes, defs, vars, incomplete) + desc.set_delay(10 * (time()-start_time) + 0.05) + + global _parse_cache + _parse_cache[hash(txt)] = desc + return desc + +def get_modules(since=1): + """Returns the set of built-in modules and any modules that have been + imported into the system upto 'since' seconds ago. + """ + + global _modules, _modules_updated + + t = time() + if _modules_updated < t - since: + _modules.update(sys.modules) + _modules_updated = t + return _modules.keys() + +def suggest_cmp(x, y): + """Use this method when sorting a list of suggestions. + """ + + return cmp(x[0].upper(), y[0].upper()) + +def get_module(name): + """Returns the module specified by its name. The module itself is imported + by this method and, as such, any initialization code will be executed. + """ + + mod = __import__(name) + components = name.split('.') + for comp in components[1:]: + mod = getattr(mod, comp) + return mod + +def type_char(v): + """Returns the character used to signify the type of a variable. Use this + method to identify the type character for an item in a suggestion list. + + The following values are returned: + 'm' if the parameter is a module + 'f' if the parameter is callable + 'v' if the parameter is variable or otherwise indeterminable + + """ + + if isinstance(v, ModuleType): + return 'm' + elif callable(v): + return 'f' + else: + return 'v' + +def get_context(txt): + """Establishes the context of the cursor in the given Blender Text object + + Returns one of: + CTX_NORMAL - Cursor is in a normal context + CTX_SINGLE_QUOTE - Cursor is inside a single quoted string + CTX_DOUBLE_QUOTE - Cursor is inside a double quoted string + CTX_COMMENT - Cursor is inside a comment + + """ + + l, cursor = txt.getCursorPos() + lines = txt.asLines(0, l+1) + + # FIXME: This method is too slow in large files for it to be called as often + # as it is. So for lines below the 1000th line we do this... (quorn) + if l > 1000: return CTX_NORMAL + + # Detect context (in string or comment) + in_str = CTX_NORMAL + for line in lines: + if l == 0: + end = cursor + else: + end = len(line) + l -= 1 + + # Comments end at new lines + if in_str == CTX_COMMENT: + in_str = CTX_NORMAL + + for i in range(end): + if in_str == 0: + if line[i] == "'": in_str = CTX_SINGLE_QUOTE + elif line[i] == '"': in_str = CTX_DOUBLE_QUOTE + elif line[i] == '#': in_str = CTX_COMMENT + else: + if in_str == CTX_SINGLE_QUOTE: + if line[i] == "'": + in_str = CTX_NORMAL + # In again if ' escaped, out again if \ escaped, and so on + for a in range(i-1, -1, -1): + if line[a] == '\\': in_str = 1-in_str + else: break + elif in_str == CTX_DOUBLE_QUOTE: + if line[i] == '"': + in_str = CTX_NORMAL + # In again if " escaped, out again if \ escaped, and so on + for a in range(i-1, -1, -1): + if line[i-a] == '\\': in_str = 2-in_str + else: break + + return in_str + +def current_line(txt): + """Extracts the Python script line at the cursor in the Blender Text object + provided and cursor position within this line as the tuple pair (line, + cursor). + """ + + lineindex, cursor = txt.getCursorPos() + lines = txt.asLines() + line = lines[lineindex] + + # Join previous lines to this line if spanning + i = lineindex - 1 + while i > 0: + earlier = lines[i].rstrip() + if earlier.endswith('\\'): + line = earlier[:-1] + ' ' + line + cursor += len(earlier) + i -= 1 + + # Join later lines while there is an explicit joining character + i = lineindex + while i < len(lines)-1 and lines[i].rstrip().endswith('\\'): + later = lines[i+1].strip() + line = line + ' ' + later[:-1] + i += 1 + + return line, cursor + +def get_targets(line, cursor): + """Parses a period separated string of valid names preceding the cursor and + returns them as a list in the same order. + """ + + brk = 0 + targets = [] + j = cursor + i = j-1 + while i >= 0: + if line[i] == ')': brk += 1 + elif brk: + if line[i] == '(': brk -= 1 + else: + if line[i] == '.': + targets.insert(0, line[i+1:j]); j=i + elif not (line[i].isalnum() or line[i] == '_' or line[i] == '.'): + break + i -= 1 + targets.insert(0, line[i+1:j]) + return targets + +def get_defs(txt): + """Returns a dictionary which maps definition names in the source code to + a list of their parameter names. + + The line 'def doit(one, two, three): print one' for example, results in the + mapping 'doit' : [ 'one', 'two', 'three' ] + """ + + return get_cached_descriptor(txt).defs + +def get_vars(txt): + """Returns a dictionary of variable names found in the specified Text + object. This method locates all names followed directly by an equal sign: + 'a = ???' or indirectly as part of a tuple/list assignment or inside a + 'for ??? in ???:' block. + """ + + return get_cached_descriptor(txt).vars + +def get_imports(txt): + """Returns a dictionary which maps symbol names in the source code to their + respective modules. + + The line 'from Blender import Text as BText' for example, results in the + mapping 'BText' : + + Note that this method imports the modules to provide this mapping as as such + will execute any initilization code found within. + """ + + return get_cached_descriptor(txt).imports + +def get_builtins(): + """Returns a dictionary of built-in modules, functions and variables.""" + + return __builtin__.__dict__ + + +################################# +## Debugging utility functions ## +################################# + +def print_cache_for(txt, period=sys.maxint): + """Prints out the data cached for a given Text object. If no period is + given the text will not be reparsed and the cached version will be returned. + Otherwise if the period has expired the text will be reparsed. + """ + + desc = get_cached_descriptor(txt, period) + print '================================================' + print 'Name:', desc.name, '('+str(hash(txt))+')' + print '------------------------------------------------' + print 'Defs:' + for name, ddesc in desc.defs.items(): + print ' ', name, ddesc.params, ddesc.lineno + print ' ', ddesc.doc + print '------------------------------------------------' + print 'Vars:' + for name, vdesc in desc.vars.items(): + print ' ', name, vdesc.type, vdesc.lineno + print '------------------------------------------------' + print 'Imports:' + for name, item in desc.imports.items(): + print ' ', name.ljust(15), item + print '------------------------------------------------' + print 'Classes:' + for clsnme, clsdsc in desc.classes.items(): + print ' *********************************' + print ' Name:', clsnme + print ' ', clsdsc.doc + print ' ---------------------------------' + print ' Defs:' + for name, ddesc in clsdsc.defs.items(): + print ' ', name, ddesc.params, ddesc.lineno + print ' ', ddesc.doc + print ' ---------------------------------' + print ' Vars:' + for name, vdesc in clsdsc.vars.items(): + print ' ', name, vdesc.type, vdesc.lineno + print ' *********************************' + print '================================================' diff --git a/release/scripts/export_obj.py b/release/scripts/export_obj.py index 8e7374f02b5..6ea890879dd 100644 --- a/release/scripts/export_obj.py +++ b/release/scripts/export_obj.py @@ -185,7 +185,7 @@ def write(filename, objects,\ EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\ EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\ -EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_MORPH_TARGET=False): +EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False): ''' Basic write function. The context and options must be alredy set This can be accessed externaly @@ -322,7 +322,7 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_MORPH_TARGET=False) # Sort by Material, then images # so we dont over context switch in the obj file. - if EXPORT_MORPH_TARGET: + if EXPORT_KEEP_VERT_ORDER: pass elif faceuv: try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth)) @@ -550,7 +550,7 @@ def write_ui(filename): EXPORT_BLEN_OBS = Draw.Create(1) EXPORT_GROUP_BY_OB = Draw.Create(0) EXPORT_GROUP_BY_MAT = Draw.Create(0) - EXPORT_MORPH_TARGET = Draw.Create(0) + EXPORT_KEEP_VERT_ORDER = Draw.Create(1) # removed too many options are bad! @@ -563,7 +563,7 @@ def write_ui(filename): ('Object Prefs...'),\ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object. May break vert order for morph targets.'),\ ('Rotate X90', EXPORT_ROTX90 , 'Rotate on export so Blenders UP is translated into OBJs UP'),\ - ('Morph Target', EXPORT_MORPH_TARGET, 'Keep vert and face order, disables some other options.'),\ + ('Keep Vert Order', EXPORT_KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\ ('Extra Data...'),\ ('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ ('Normals', EXPORT_NORMALS, 'Export vertex normal data (Ignored on import).'),\ @@ -581,7 +581,7 @@ def write_ui(filename): if not Draw.PupBlock('Export...', pup_block): return - if EXPORT_MORPH_TARGET.val: + if EXPORT_KEEP_VERT_ORDER.val: EXPORT_BLEN_OBS.val = False EXPORT_GROUP_BY_OB.val = False EXPORT_GROUP_BY_MAT.val = False @@ -606,7 +606,7 @@ def write_ui(filename): EXPORT_BLEN_OBS = EXPORT_BLEN_OBS.val EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val - EXPORT_MORPH_TARGET = EXPORT_MORPH_TARGET.val + EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val @@ -656,7 +656,7 @@ def write_ui(filename): EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\ EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\ EXPORT_ROTX90, EXPORT_BLEN_OBS,\ - EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_MORPH_TARGET) + EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER) Blender.Set('curframe', orig_frame) diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py index e5bdc796e16..b467cca112f 100644 --- a/release/scripts/import_obj.py +++ b/release/scripts/import_obj.py @@ -763,7 +763,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False): SPLIT_OBJECTS= Draw.Create(1) SPLIT_GROUPS= Draw.Create(1) SPLIT_MATERIALS= Draw.Create(1) - MORPH_TARGET= Draw.Create(0) + KEEP_VERT_ORDER= Draw.Create(1) CLAMP_SIZE= Draw.Create(10.0) IMAGE_SEARCH= Draw.Create(1) @@ -779,7 +779,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False): ('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),\ ('Material', SPLIT_MATERIALS, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)'),\ 'Options...',\ - ('Morph Target', MORPH_TARGET, 'Keep vert and face order, disables some other options.'),\ + ('Keep Vert Order', KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\ ('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),\ ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\ ] @@ -787,7 +787,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False): if not Draw.PupBlock('Import OBJ...', pup_block): return - if MORPH_TARGET.val: + if KEEP_VERT_ORDER.val: SPLIT_OBJECTS.val = False SPLIT_GROUPS.val = False SPLIT_MATERIALS.val = False diff --git a/release/scripts/mesh_cleanup.py b/release/scripts/mesh_cleanup.py index 608201acb98..27adca335cb 100644 --- a/release/scripts/mesh_cleanup.py +++ b/release/scripts/mesh_cleanup.py @@ -121,25 +121,29 @@ def rem_unused_materials(me): material_users= dict( [(i,0) for i in xrange(len_materials)] ) for f in me.faces: + f_mat = f.mat # Make sure the face index isnt too big. this happens sometimes. - if f.mat >= len_materials: - f.mat=0 - material_users[f.mat] += 1 + if f_mat >= len_materials: + f_mat = f.mat = 0 + material_users[f_mat] += 1 - mat_idx_subtract= 0 - reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) - i= len_materials - while i: - i-=1 - + # mat_idx_subtract= 0 + # reindex_mapping= dict( [(i,0) for i in xrange(len_materials)] ) + + reindex_mapping_ls = range(len_materials) + for i in range(len_materials-1, -1, -1): if material_users[i] == 0: - mat_idx_subtract+=1 - reindex_mapping[i]= mat_idx_subtract - materials.pop(i) + del reindex_mapping_ls[i] + del materials[i] rem_materials+=1 + reindex_mapping= {} + + for i, mat in enumerate(reindex_mapping_ls): + reindex_mapping[mat] = i + for f in me.faces: - f.mat= f.mat - reindex_mapping[f.mat] + f.mat= reindex_mapping[f.mat] me.materials= materials return rem_materials @@ -449,4 +453,4 @@ def main(): if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/release/scripts/object_find.py b/release/scripts/object_find.py index 0cfd6ad1d92..f12af07e3e4 100644 --- a/release/scripts/object_find.py +++ b/release/scripts/object_find.py @@ -61,8 +61,20 @@ def get_object_images(ob): me.activeUVLayer = orig_uvlayer + + # Now get material images + for mat in me.materials: + if mat: + for mtex in mat.getTextures(): + if mtex: + tex = mtex.tex + i = tex.getImage() + if i: unique_images[i.name] = i + return unique_images.values() + + # Todo, support other object types, materials return [] @@ -118,7 +130,7 @@ def main(): def activate(ob, scn): bpy.data.scenes.active = scn scn.objects.selected = [] - scn.Layers = ob.Layers + scn.Layers = ob.Layers & (1<<20)-1 ob.sel = 1 def name_cmp(name_search, name_found): @@ -195,11 +207,13 @@ def main(): activate(ob, scn) return if NAME_TEXTURE: - for tex in mat.getTextures(): - if tex: - if name_cmp(NAME_MATERIAL, tex.name): - activate(ob, scn) - return + for mtex in mat.getTextures(): + if mtex: + tex = mtex.tex + if tex: + if name_cmp(NAME_TEXTURE, tex.name): + activate(ob, scn) + return Draw.PupMenu('No Objects Found') diff --git a/release/scripts/scripttemplate_gamelogic.py b/release/scripts/scripttemplate_gamelogic.py new file mode 100644 index 00000000000..17095251155 --- /dev/null +++ b/release/scripts/scripttemplate_gamelogic.py @@ -0,0 +1,93 @@ +#!BPY +""" +Name: 'GameLogic Example' +Blender: 245 +Group: 'ScriptTemplate' +Tooltip: 'Script template with examples of how to use game logic' +""" + +from Blender import Window +import bpy + +script_data = \ +''' +# GameLogic has been added to the global namespace no need to import + +# for keyboard event comparison +# import GameKeys + +# support for Vector(), Matrix() types and advanced functions like AngleBetweenVecs(v1,v2) and RotationMatrix(...) +# import Mathutils + +# for functions like getWindowWidth(), getWindowHeight() +# import Rasterizer + +def main(): + cont = GameLogic.getCurrentController() + + # The KX_GameObject that owns this controller. + own = cont.getOwner() + + # for scripts that deal with spacial logic + own_pos = own.getPosition() + + + # Some example functions, remove to write your own script. + # check for a positive sensor, will run on any object without errors. + print 'Logic info for KX_GameObject', own.getName() + input = False + + for sens in cont.getSensors(): + # The sensor can be on another object, we may want to use it + own_sens = sens.getOwner() + print ' sensor:', sens.getName(), + if sens.isPositive(): + print '(true)' + input = True + else: + print '(false)' + + for actu in cont.getActuators(): + # The actuator can be on another object, we may want to use it + own_actu = actu.getOwner() + print ' actuator:', sens.getName() + + # This runs the actuator or turns it off + # note that actuators will continue to run unless explicitly turned off. + if input: + GameLogic.addActiveActuator(actu, True) + else: + GameLogic.addActiveActuator(actu, False) + + # Its also good practice to get sensors and actuators by names + # so any changes to their order wont break the script. + + # sens_key = cont.getSensor('key_sensor') + # actu_motion = cont.getActuator('motion') + + + # Loop through all other objects in the scene + sce = GameLogic.getCurrentScene() + print 'Scene Objects:', sce.getName() + for ob in sce.getObjectList(): + print ' ', ob.getName(), ob.getPosition() + + + # Example where collision objects are checked for their properties + # adding to our objects "life" property + """ + actu_collide = cont.getSensor('collision_sens') + for ob in actu_collide.getHitObjectList(): + # Check to see the object has this property + if hasattr(ob, 'life'): + own.life += ob.life + ob.life = 0 + print own.life + """ +main() +''' + +new_text = bpy.data.texts.new('gamelogic_example.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() diff --git a/release/scripts/scripttemplate_gamelogic_basic.py b/release/scripts/scripttemplate_gamelogic_basic.py new file mode 100644 index 00000000000..dfd52a9f749 --- /dev/null +++ b/release/scripts/scripttemplate_gamelogic_basic.py @@ -0,0 +1,33 @@ +#!BPY +""" +Name: 'GameLogic Template' +Blender: 245 +Group: 'ScriptTemplate' +Tooltip: 'Basic template for new game logic scripts' +""" + +from Blender import Window +import bpy + +script_data = \ +''' +def main(): + + cont = GameLogic.getCurrentController() + own = cont.getOwner() + + sens = cont.getSensor('mySensor') + actu = cont.getActuator('myActuator') + + if sens.isPositive(): + GameLogic.addActiveActuator(actu, True) + else: + GameLogic.addActiveActuator(actu, False) + +main() +''' + +new_text = bpy.data.texts.new('gamelogic_example.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() diff --git a/release/scripts/scripttemplate_text_plugin.py b/release/scripts/scripttemplate_text_plugin.py new file mode 100644 index 00000000000..4ae562736d3 --- /dev/null +++ b/release/scripts/scripttemplate_text_plugin.py @@ -0,0 +1,69 @@ +#!BPY +""" +Name: 'Text Plugin' +Blender: 246 +Group: 'ScriptTemplate' +Tooltip: 'Add a new text for writing a text plugin' +""" + +from Blender import Window +import bpy + +script_data = \ +'''#!BPY +""" +Name: 'My Plugin Script' +Blender: 246 +Group: 'TextPlugin' +Shortcut: 'Ctrl+Alt+U' +Tooltip: 'Put some useful info here' +""" + +# Add a licence here if you wish to re-distribute, we recommend the GPL + +from Blender import Window, sys +import BPyTextPlugin, bpy + +def my_script_util(txt): + # This function prints out statistical information about a script + + desc = BPyTextPlugin.get_cached_descriptor(txt) + print '---------------------------------------' + print 'Script Name:', desc.name + print 'Classes:', len(desc.classes) + print ' ', desc.classes.keys() + print 'Functions:', len(desc.defs) + print ' ', desc.defs.keys() + print 'Variables:', len(desc.vars) + print ' ', desc.vars.keys() + +def main(): + + # Gets the active text object, there can be many in one blend file. + txt = bpy.data.texts.active + + # Silently return if the script has been run with no active text + if not txt: + return + + # Text plug-ins should run quickly so we time it here + Window.WaitCursor(1) + t = sys.time() + + # Run our utility function + my_script_util(txt) + + # Timing the script is a good way to be aware on any speed hits when scripting + print 'Plugin script finished in %.2f seconds' % (sys.time()-t) + Window.WaitCursor(0) + + +# This lets you import the script without running it +if __name__ == '__main__': + main() +''' + +new_text = bpy.data.texts.new('textplugin_template.py') +new_text.write(script_data) +bpy.data.texts.active = new_text +Window.RedrawAll() diff --git a/release/scripts/sysinfo.py b/release/scripts/sysinfo.py index 9f24885829c..3a671e7221e 100644 --- a/release/scripts/sysinfo.py +++ b/release/scripts/sysinfo.py @@ -94,6 +94,8 @@ output = Blender.Text.New(output_filename) output.write(header + "\n\n") +output.write("%s\n\n" % Blender.Get('buildinfo')) + output.write("Platform: %s\n========\n\n" % sys.platform) output.write("Python:\n======\n\n") diff --git a/release/scripts/textplugin_functiondocs.py b/release/scripts/textplugin_functiondocs.py new file mode 100644 index 00000000000..41c8d4842a0 --- /dev/null +++ b/release/scripts/textplugin_functiondocs.py @@ -0,0 +1,64 @@ +#!BPY +""" +Name: 'Function Documentation | Ctrl I' +Blender: 246 +Group: 'TextPlugin' +Shortcut: 'Ctrl+I' +Tooltip: 'Attempts to display documentation about the function preceding the cursor.' +""" + +# Only run if we have the required modules +try: + import bpy + from BPyTextPlugin import * +except ImportError: + OK = False +else: + OK = True + +def main(): + txt = bpy.data.texts.active + if not txt: + return + + (line, c) = current_line(txt) + + # Check we are in a normal context + if get_context(txt) != CTX_NORMAL: + return + + # Identify the name under the cursor + llen = len(line) + while c= 0: + if line[i] == '"' or line[i] == "'": + targets[0] = 'str' + elif line[i] == '}': + targets[0] = 'dict' + elif line[i] == ']': # Could be array elem x[y] or list [y] + i = line.rfind('[', 0, i) - 1 + while i >= 0: + if line[i].isalnum() or line[i] == '_': + break + elif line[i] != ' ' and line[i] != '\t': + i = -1 + break + i -= 1 + if i < 0: + targets[0] = 'list' + + obj = resolve_targets(txt, targets[:-1]) + if not obj: + return + + items = [] + + if isinstance(obj, VarDesc): + obj = obj.type + + if isinstance(obj, Definition): # Locally defined + if hasattr(obj, 'classes'): + items.extend([(s, 'f') for s in obj.classes.keys()]) + if hasattr(obj, 'defs'): + items.extend([(s, 'f') for s in obj.defs.keys()]) + if hasattr(obj, 'vars'): + items.extend([(s, 'v') for s in obj.vars.keys()]) + + else: # Otherwise we have an imported or builtin object + try: + attr = obj.__dict__.keys() + except AttributeError: + attr = dir(obj) + else: + if not attr: attr = dir(obj) + + for k in attr: + try: + v = getattr(obj, k) + except (AttributeError, TypeError): # Some attributes are not readable + pass + else: + items.append((k, type_char(v))) + + if items != []: + items.sort(cmp = suggest_cmp) + txt.suggest(items, targets[-1]) + +# Check we are running as a script and not imported as a module +if __name__ == "__main__" and OK: + main() diff --git a/release/scripts/textplugin_outliner.py b/release/scripts/textplugin_outliner.py new file mode 100644 index 00000000000..3879a2819a5 --- /dev/null +++ b/release/scripts/textplugin_outliner.py @@ -0,0 +1,142 @@ +#!BPY +""" +Name: 'Code Outline | Ctrl T' +Blender: 246 +Group: 'TextPlugin' +Shortcut: 'Ctrl+T' +Tooltip: 'Provides a menu for jumping to class and functions definitions.' +""" + +# Only run if we have the required modules +try: + import bpy + from BPyTextPlugin import * + from Blender import Draw +except ImportError: + OK = False +else: + OK = True + +def make_menu(items, eventoffs): + n = len(items) + if n < 20: + return [(items[i], i+1+eventoffs) for i in range(len(items))] + + letters = [] + check = 'abcdefghijklmnopqrstuvwxyz_' # Names cannot start 0-9 + for c in check: + for item in items: + if item[0].lower() == c: + letters.append(c) + break + + entries = {} + i = 0 + for item in items: + i += 1 + c = item[0].lower() + entries.setdefault(c, []).append((item, i+eventoffs)) + + subs = [] + for c in letters: + subs.append((c, entries[c])) + + return subs + +def find_word(txt, word): + i = 0 + txt.reset() + while True: + try: + line = txt.readline() + except StopIteration: + break + c = line.find(word) + if c != -1: + txt.setCursorPos(i, c) + break + i += 1 + +def main(): + txt = bpy.data.texts.active + if not txt: + return + + # Identify word under cursor + if get_context(txt) == CTX_NORMAL: + line, c = current_line(txt) + start = c-1 + end = c + while start >= 0: + if not line[start].lower() in 'abcdefghijklmnopqrstuvwxyz0123456789_': + break + start -= 1 + while end < len(line): + if not line[end].lower() in 'abcdefghijklmnopqrstuvwxyz0123456789_': + break + end += 1 + word = line[start+1:end] + if word in KEYWORDS: + word = None + else: + word = None + + script = get_cached_descriptor(txt) + items = [] + desc = None + + tmp = script.classes.keys() + tmp.sort(cmp = suggest_cmp) + class_menu = make_menu(tmp, len(items)) + class_menu_length = len(tmp) + items.extend(tmp) + + tmp = script.defs.keys() + tmp.sort(cmp = suggest_cmp) + defs_menu = make_menu(tmp, len(items)) + defs_menu_length = len(tmp) + items.extend(tmp) + + tmp = script.vars.keys() + tmp.sort(cmp = suggest_cmp) + vars_menu = make_menu(tmp, len(items)) + vars_menu_length = len(tmp) + items.extend(tmp) + + menu = [('Script %t', 0), + ('Classes', class_menu), + ('Functions', defs_menu), + ('Variables', vars_menu)] + if word: + menu.extend([None, ('Locate', [(word, -10)])]) + + i = Draw.PupTreeMenu(menu) + if i == -1: + return + + # Chosen to search for word under cursor + if i == -10: + if script.classes.has_key(word): + desc = script.classes[word] + elif script.defs.has_key(word): + desc = script.defs[word] + elif script.vars.has_key(word): + desc = script.vars[word] + else: + find_word(txt, word) + return + else: + i -= 1 + if i < class_menu_length: + desc = script.classes[items[i]] + elif i < class_menu_length + defs_menu_length: + desc = script.defs[items[i]] + elif i < class_menu_length + defs_menu_length + vars_menu_length: + desc = script.vars[items[i]] + + if desc: + txt.setCursorPos(desc.lineno-1, 0) + +# Check we are running as a script and not imported as a module +if __name__ == "__main__" and OK: + main() diff --git a/release/scripts/textplugin_suggest.py b/release/scripts/textplugin_suggest.py new file mode 100644 index 00000000000..d8122212d3b --- /dev/null +++ b/release/scripts/textplugin_suggest.py @@ -0,0 +1,94 @@ +#!BPY +""" +Name: 'Suggest All | Ctrl Space' +Blender: 246 +Group: 'TextPlugin' +Shortcut: 'Ctrl+Space' +Tooltip: 'Performs suggestions based on the context of the cursor' +""" + +# Only run if we have the required modules +try: + import bpy + from BPyTextPlugin import * +except ImportError: + OK = False +else: + OK = True + +def check_membersuggest(line, c): + pos = line.rfind('.', 0, c) + if pos == -1: + return False + for s in line[pos+1:c]: + if not s.isalnum() and s != '_': + return False + return True + +def check_imports(line, c): + pos = line.rfind('import ', 0, c) + if pos > -1: + for s in line[pos+7:c]: + if not s.isalnum() and s != '_': + return False + return True + pos = line.rfind('from ', 0, c) + if pos > -1: + for s in line[pos+5:c]: + if not s.isalnum() and s != '_': + return False + return True + return False + +def main(): + txt = bpy.data.texts.active + if not txt: + return + + line, c = current_line(txt) + + # Check we are in a normal context + if get_context(txt) != CTX_NORMAL: + return + + # Check the character preceding the cursor and execute the corresponding script + + if check_membersuggest(line, c): + import textplugin_membersuggest + textplugin_membersuggest.main() + return + + elif check_imports(line, c): + import textplugin_imports + textplugin_imports.main() + return + + # Otherwise we suggest globals, keywords, etc. + list = [] + targets = get_targets(line, c) + desc = get_cached_descriptor(txt) + + for k in KEYWORDS: + list.append((k, 'k')) + + for k, v in get_builtins().items(): + list.append((k, type_char(v))) + + for k, v in desc.imports.items(): + list.append((k, type_char(v))) + + for k, v in desc.classes.items(): + list.append((k, 'f')) + + for k, v in desc.defs.items(): + list.append((k, 'f')) + + for k, v in desc.vars.items(): + list.append((k, 'v')) + + list.sort(cmp = suggest_cmp) + txt.suggest(list, targets[-1]) + +# Check we are running as a script and not imported as a module +if __name__ == "__main__" and OK: + main() diff --git a/release/scripts/textplugin_templates.py b/release/scripts/textplugin_templates.py new file mode 100644 index 00000000000..8f949563ac0 --- /dev/null +++ b/release/scripts/textplugin_templates.py @@ -0,0 +1,123 @@ +#!BPY +""" +Name: 'Template Completion | Tab' +Blender: 246 +Group: 'TextPlugin' +Shortcut: 'Tab' +Tooltip: 'Completes templates based on the text preceding the cursor' +""" + +# Only run if we have the required modules +try: + import bpy + from BPyTextPlugin import * + from Blender import Text +except ImportError: + OK = False +else: + OK = True + +templates = { + 'ie': + 'if ${1:cond}:\n' + '\t${2}\n' + 'else:\n' + '\t${3}\n', + 'iei': + 'if ${1:cond}:\n' + '\t${2}\n' + 'elif:\n' + '\t${3}\n' + 'else:\n' + '\t${4}\n', + 'def': + 'def ${1:name}(${2:params}):\n' + '\t"""(${2}) - ${3:comment}"""\n' + '\t${4}', + 'cls': + 'class ${1:name}(${2:parent}):\n' + '\t"""${3:docs}"""\n' + '\t\n' + '\tdef __init__(self, ${4:params}):\n' + '\t\t"""Creates a new ${1}"""\n' + '\t\t${5}', + 'class': + 'class ${1:name}(${2:parent}):\n' + '\t"""${3:docs}"""\n' + '\t\n' + '\tdef __init__(self, ${4:params}):\n' + '\t\t"""Creates a new ${1}"""\n' + '\t\t${5}' +} + +def main(): + txt = bpy.data.texts.active + if not txt: + return + + row, c = txt.getCursorPos() + line = txt.asLines(row, row+1)[0] + indent=0 + while indentexec, now in use for composites (#define for break is same as ready yes) */ @@ -252,6 +258,8 @@ void nodeShaderSynchronizeID(struct bNode *node, int copyto); extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *)); +void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat); + /* ************** COMPOSITE NODES *************** */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 944a9081679..a1a9a883c4f 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -73,6 +73,7 @@ typedef struct ParticleEffectorCache { short type, psys_nbr; struct Object obcopy; /* for restoring transformation data */ + struct RNG *rng; /* random noise generator for e.g. wind */ } ParticleEffectorCache; typedef struct ParticleReactEvent { @@ -302,6 +303,7 @@ int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int #define PSYS_RESET_ALL 1 #define PSYS_RESET_DEPSGRAPH 2 #define PSYS_RESET_CHILDREN 3 +#define PSYS_RESET_CACHE_MISS 4 /* ParticleEffectorCache->type */ #define PSYS_EC_EFFECTOR 1 diff --git a/source/blender/blenkernel/BKE_suggestions.h b/source/blender/blenkernel/BKE_suggestions.h new file mode 100644 index 00000000000..d58b8f58bf5 --- /dev/null +++ b/source/blender/blenkernel/BKE_suggestions.h @@ -0,0 +1,93 @@ +/** + * $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. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef BKE_SUGGESTIONS_H +#define BKE_SUGGESTIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* **************************************************************************** +Suggestions should be added in sorted order although a linear sorting method is +implemented. The list is then divided up based on the prefix provided by +update_suggestions: + +Example: + Prefix: ab + aaa <-- first + aab + aba <-- firstmatch + abb <-- lastmatch + baa + bab <-- last +**************************************************************************** */ + +struct Text; + +typedef struct SuggItem { + struct SuggItem *prev, *next; + char *name; + char type; +} SuggItem; + +typedef struct SuggList { + SuggItem *first, *last; + SuggItem *firstmatch, *lastmatch; + SuggItem *selected; + int top; +} SuggList; + +/* Free all text tool memory */ +void free_texttools(); + +/* Used to identify which Text object the current tools should appear against */ +void texttool_text_set_active(Text *text); +void texttool_text_clear(); +short texttool_text_is_active(Text *text); + +/* Suggestions */ +void texttool_suggest_add(const char *name, char type); +void texttool_suggest_prefix(const char *prefix); +void texttool_suggest_clear(); +SuggItem *texttool_suggest_first(); +SuggItem *texttool_suggest_last(); +void texttool_suggest_select(SuggItem *sel); +SuggItem *texttool_suggest_selected(); +int *texttool_suggest_top(); + +/* Documentation */ +void texttool_docs_show(const char *docs); +char *texttool_docs_get(); +void texttool_docs_clear(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 6f891ab4887..002c804f17f 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -52,20 +52,24 @@ void txt_free_cut_buffer (void); char* txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); void txt_order_cursors (struct Text *text); -int txt_find_string (struct Text *text, char *findstr); +int txt_find_string (struct Text *text, char *findstr, int wrap); int txt_has_sel (struct Text *text); int txt_get_span (struct TextLine *from, struct TextLine *to); void txt_move_up (struct Text *text, short sel); void txt_move_down (struct Text *text, short sel); void txt_move_left (struct Text *text, short sel); void txt_move_right (struct Text *text, short sel); +void txt_jump_left (struct Text *text, short sel); +void txt_jump_right (struct Text *text, short sel); void txt_move_bof (struct Text *text, short sel); void txt_move_eof (struct Text *text, short sel); void txt_move_bol (struct Text *text, short sel); void txt_move_eol (struct Text *text, short sel); void txt_move_toline (struct Text *text, unsigned int line, short sel); +void txt_move_to (struct Text *text, unsigned int line, unsigned int ch, short sel); void txt_pop_sel (struct Text *text); void txt_delete_char (struct Text *text); +void txt_delete_word (struct Text *text); void txt_copy_sel (struct Text *text); void txt_sel_all (struct Text *text); void txt_sel_line (struct Text *text); @@ -80,8 +84,10 @@ void txt_do_undo (struct Text *text); void txt_do_redo (struct Text *text); void txt_split_curline (struct Text *text); void txt_backspace_char (struct Text *text); +void txt_backspace_word (struct Text *text); int txt_add_char (struct Text *text, char add); -void txt_find_panel (struct SpaceText *st, int again); +int txt_replace_char (struct Text *text, char add); +void find_and_replace (struct SpaceText *st, short mode); void run_python_script (struct SpaceText *st); int jumptoline_interactive (struct SpaceText *st); void txt_export_to_object (struct Text *text); @@ -94,6 +100,17 @@ int setcurr_tab (struct Text *text); void convert_tabs (struct SpaceText *st, int tab); void txt_copy_clipboard (struct Text *text); void txt_paste_clipboard (struct Text *text); + +void txt_add_marker (struct Text *text, struct TextLine *line, int start, int end, char color[4], int group, int flags); +short txt_clear_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); +short txt_clear_markers (struct Text *text, int group, int flags); +struct TextMarker *txt_find_marker (struct Text *text, struct TextLine *line, int curs, int group, int flags); +struct TextMarker *txt_find_marker_region (struct Text *text, struct TextLine *line, int start, int end, int group, int flags); +struct TextMarker *txt_prev_marker (struct Text *text, struct TextMarker *marker); +struct TextMarker *txt_next_marker (struct Text *text, struct TextMarker *marker); +struct TextMarker *txt_prev_marker_color (struct Text *text, struct TextMarker *marker); +struct TextMarker *txt_next_marker_color (struct Text *text, struct TextMarker *marker); + /* Undo opcodes */ /* Simple main cursor movement */ @@ -135,6 +152,14 @@ void txt_paste_clipboard (struct Text *text); #define UNDO_COMMENT 034 #define UNDO_UNCOMMENT 035 +/* Find and replace flags */ +#define TXT_FIND_WRAP 0x01 +#define TXT_FIND_ALLTEXTS 0x02 + +/* Marker flags */ +#define TMARK_TEMP 0x01 /* Remove on non-editing events, don't save */ +#define TMARK_EDITALL 0x02 /* Edit all markers of the same group as one */ + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index c162a04e055..cfcae3c44bc 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -53,6 +53,7 @@ void free_plugin_tex(struct PluginTex *pit); void init_colorband(struct ColorBand *coba, int rangetype); struct ColorBand *add_colorband(int rangetype); int do_colorband(struct ColorBand *coba, float in, float out[4]); +void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size); void default_tex(struct Tex *tex); struct Tex *add_texture(char *name); diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index f389521ffa0..d647a74c6e2 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -55,6 +55,8 @@ #define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) #define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) #define ELEM9(a, b, c, d, e, f, g, h, i, j) ( ELEM4(a, b, c, d, e) || ELEM5(a, f, g, h, i, j) ) +#define ELEM10(a, b, c, d, e, f, g, h, i, j, k) ( ELEM4(a, b, c, d, e) || ELEM6(a, f, g, h, i, j, k) ) +#define ELEM11(a, b, c, d, e, f, g, h, i, j, k, l) ( ELEM4(a, b, c, d, e) || ELEM7(a, f, g, h, i, j, k, l) ) /* shift around elements */ #define SHIFT3(type, a, b, c) { type tmp; tmp = a; a = c; c = b; b = tmp; } diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9088b410e27..0345711c9c3 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -32,7 +32,7 @@ SET(INC ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern ../../../intern/iksolver/extern ../blenloader ../quicktime ../../../intern/bmfont ../../../extern/bullet2/src - ../nodes + ../nodes ../../../extern/glew/include ../gpu ${SDL_INC} ${ZLIB_INC} ${PYTHON_INC} diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1bb98239a68..f891b307b2c 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -10,6 +10,7 @@ incs += ' #/intern/iksolver/extern ../blenloader ../quicktime' incs += ' #/extern/bullet2/src' incs += ' #/intern/bmfont' incs += ' #/intern/opennl/extern' +incs += ' ../gpu #/extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] @@ -42,7 +43,8 @@ if env['WITH_BF_QUICKTIME'] == 1: defs += ' WITH_QUICKTIME' incs += ' ' + env['BF_QUICKTIME_INC'] -defs += ' WITH_CCGSUBSURF' +if env['BF_NO_ELBEEM'] == 1: + defs += ' DISABLE_ELBEEM' if env['WITH_BF_PLAYER']: SConscript(['bad_level_call_stubs/SConscript']) diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 561d8d7c2a6..ae336d0fc26 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -60,7 +60,7 @@ struct EditFace; char *getIpoCurveName( struct IpoCurve * icu ); void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e); +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f); void elbeemDebugOut(char *msg); void fluidsimSettingsFree(struct FluidsimSettings* sb); void fluidsimSettingsCopy(struct FluidsimSettings* sb); @@ -88,7 +88,7 @@ void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast) } -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e) +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f) { return 0; } @@ -176,10 +176,6 @@ void free_editMesh(struct EditMesh *em){} void docenter_new(void){} int saveover(char *str){ return 0;} -/* image.c */ -#include "DNA_image_types.h" -void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff - /* ipo.c */ void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible @@ -205,7 +201,7 @@ short pupmenu(char *instr){ return 0;} // will be general callback /* scene.c */ #include "DNA_sequence_types.h" void free_editing(struct Editing *ed){} // scenes and sequences problem... -void BPY_do_all_scripts (short int event){} +void BPY_do_all_scripts (short int event, short int anim){} /*editmesh_lib.c*/ void EM_select_face(struct EditFace *efa, int sel) {} @@ -220,30 +216,6 @@ struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2) { retur void countall(void) {} - -/* IKsolver stubs */ -#include "IK_solver.h" - -IK_Segment *IK_CreateSegment(int flag) { return 0; } -void IK_FreeSegment(IK_Segment *seg) {} - -void IK_SetParent(IK_Segment *seg, IK_Segment *parent) {} -void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length) {} -void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) {} -void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) {}; -void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lower, float upper) {}; -void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) {}; - -IK_Solver *IK_CreateSolver(IK_Segment *root) { return 0; } -void IK_FreeSolver(IK_Solver *solver) {}; - -void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) {} -void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) {} -void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle) {} -float IK_SolverGetPoleAngle(IK_Solver *solver) { return 0.0f; } - -int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) { return 0; } - /* exotic.c */ int BPY_call_importloader(char *name) { diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 8bbda2da976..a5eb1f258f1 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -89,6 +89,10 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + // headers for fluidsim bobj meshes #include #include "LBM_fluidsim.h" @@ -416,6 +420,8 @@ void DM_swap_face_data(DerivedMesh *dm, int index, int *corner_indices) CustomData_swap(&dm->faceData, index, corner_indices); } +/// + static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]) { DerivedMesh *dm = CDDM_from_mesh(me, ob); @@ -899,6 +905,162 @@ static void emDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void emDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } +static void emDM_drawMappedFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs), + int (*setDrawOptions)(void *userData, int index), void *userData) +{ + EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditMesh *em= emdm->em; + float (*vertexCos)[3]= emdm->vertexCos; + float (*vertexNos)[3]= emdm->vertexNos; + EditVert *eve; + EditFace *efa; + DMVertexAttribs attribs; + GPUVertexAttribs gattribs; + MTFace *tf; + int transp, new_transp, orig_transp, tfoffset; + int i, b, matnr, new_matnr, dodraw, layer; + + dodraw = 0; + matnr = -1; + + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + layer = CustomData_get_layer_index(&em->fdata, CD_MTFACE); + tfoffset = (layer == -1)? -1: em->fdata.layers[layer].offset; + + memset(&attribs, 0, sizeof(attribs)); + + /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ + glShadeModel(GL_SMOOTH); + + for (i=0,eve=em->verts.first; eve; eve= eve->next) + eve->tmp.l = (long) i++; + +#define PASSATTRIB(efa, eve, vert) { \ + if(attribs.totorco) { \ + float *orco = attribs.orco.array[eve->tmp.l]; \ + glVertexAttrib3fvARB(attribs.orco.glIndex, orco); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = (MTFace*)((char*)efa->data + attribs.tface[b].emOffset); \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = (MCol*)((char*)efa->data + attribs.mcol[b].emOffset); \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[i*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + for (i=0,efa= em->faces.first; efa; i++,efa= efa->next) { + int drawSmooth= (efa->flag & ME_SMOOTH); + + if(setDrawOptions && !setDrawOptions(userData, i)) + continue; + + new_matnr = efa->mat_nr + 1; + if(new_matnr != matnr) { + dodraw = setMaterial(matnr = new_matnr, &gattribs); + if(dodraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + if(tfoffset != -1) { + tf = (MTFace*)((char*)efa->data)+tfoffset; + new_transp = tf->transp; + + if(new_transp != transp) { + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + } + } + + if(dodraw) { + glBegin(efa->v4?GL_QUADS:GL_TRIANGLES); + if (!drawSmooth) { + if(vertexCos) glNormal3fv(emdm->faceNos[i]); + else glNormal3fv(efa->n); + + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + else glVertex3fv(efa->v1->co); + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + else glVertex3fv(efa->v2->co); + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + else glVertex3fv(efa->v3->co); + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + else glVertex3fv(efa->v4->co); + } + } else { + PASSATTRIB(efa, efa->v1, 0); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v1->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v1->tmp.l]); + } + else { + glNormal3fv(efa->v1->no); + glVertex3fv(efa->v1->co); + } + + PASSATTRIB(efa, efa->v2, 1); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v2->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v2->tmp.l]); + } + else { + glNormal3fv(efa->v2->no); + glVertex3fv(efa->v2->co); + } + + PASSATTRIB(efa, efa->v3, 2); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v3->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v3->tmp.l]); + } + else { + glNormal3fv(efa->v3->no); + glVertex3fv(efa->v3->co); + } + + if(efa->v4) { + PASSATTRIB(efa, efa->v4, 3); + if(vertexCos) { + glNormal3fv(vertexNos[(int) efa->v4->tmp.l]); + glVertex3fv(vertexCos[(int) efa->v4->tmp.l]); + } + else { + glNormal3fv(efa->v4->no); + glVertex3fv(efa->v4->co); + } + } + } + glEnd(); + } + } +} + +static void emDM_drawFacesGLSL(DerivedMesh *dm, + int (*setMaterial)(int, void *attribs)) +{ + dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + static void emDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3]) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1104,6 +1266,43 @@ void emDM_copyFaceArray(DerivedMesh *dm, MFace *face_r) } } +static void *emDM_getFaceDataArray(DerivedMesh *dm, int type) +{ + EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; + EditMesh *em= emdm->em; + EditFace *efa; + char *data, *emdata; + void *datalayer; + int index, offset, size; + + datalayer = DM_get_face_data_layer(dm, type); + if(datalayer) + return datalayer; + + /* layers are store per face for editmesh, we convert to a temporary + * data layer array in the derivedmesh when these are requested */ + if(type == CD_MTFACE || type == CD_MCOL) { + index = CustomData_get_layer_index(&em->fdata, type); + + if(index != -1) { + offset = em->fdata.layers[index].offset; + size = CustomData_sizeof(type); + + DM_add_face_layer(dm, type, CD_CALLOC, NULL); + index = CustomData_get_layer_index(&dm->faceData, type); + dm->faceData.layers[index].flag |= CD_FLAG_TEMPORARY; + + data = datalayer = DM_get_face_data_layer(dm, type); + for(efa=em->faces.first; efa; efa=efa->next, data+=size) { + emdata = CustomData_em_get(&em->fdata, efa->data, type); + memcpy(data, emdata, size); + } + } + } + + return datalayer; +} + static void emDM_release(DerivedMesh *dm) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; @@ -1139,6 +1338,7 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, emdm->dm.copyVertArray = emDM_copyVertArray; emdm->dm.copyEdgeArray = emDM_copyEdgeArray; emdm->dm.copyFaceArray = emDM_copyFaceArray; + emdm->dm.getFaceDataArray = emDM_getFaceDataArray; emdm->dm.foreachMappedVert = emDM_foreachMappedVert; emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; @@ -1149,7 +1349,9 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob, emdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; emdm->dm.drawMappedFaces = emDM_drawMappedFaces; emdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; + emdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; emdm->dm.drawFacesTex = emDM_drawFacesTex; + emdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; emdm->dm.drawUVEdges = emDM_drawUVEdges; emdm->dm.release = emDM_release; @@ -1579,7 +1781,7 @@ static void vDM_drawUVEdges(DerivedMesh *dm) } /* draw all VerseFaces */ -static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) +static void vDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { VDerivedMesh *vdm = (VDerivedMesh*)dm; struct VerseFace *vface; @@ -1679,6 +1881,8 @@ static void vDM_drawMappedFacesTex( int (*setDrawParams)(void *userData, int index), void *userData) { + /* not supported yet */ + vDM_drawFacesTex(dm, NULL); } /**/ @@ -1820,19 +2024,23 @@ CustomDataMask get_viewedit_datamask() ScrArea *sa; /* check if we need tfaces & mcols due to face select or texture paint */ - if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) { + if(FACESEL_PAINT_TEST || G.f & G_TEXTUREPAINT) mask |= CD_MASK_MTFACE | CD_MASK_MCOL; - } else { - /* check if we need tfaces & mcols due to view mode */ - for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { - if(sa->spacetype == SPACE_VIEW3D) { - View3D *view = sa->spacedata.first; - if(view->drawtype == OB_SHADED) { - /* this includes normals for mesh_create_shadedColors */ - mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; - } - if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { - mask |= CD_MASK_MTFACE | CD_MASK_MCOL; + + /* check if we need tfaces & mcols due to view mode */ + for(sa = G.curscreen->areabase.first; sa; sa = sa->next) { + if(sa->spacetype == SPACE_VIEW3D) { + View3D *view = sa->spacedata.first; + if(view->drawtype == OB_SHADED) { + /* this includes normals for mesh_create_shadedColors */ + mask |= CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_NORMAL | CD_MASK_ORCO; + } + if((view->drawtype == OB_TEXTURE) || ((view->drawtype == OB_SOLID) && (view->flag2 & V3D_SOLID_TEX))) { + mask |= CD_MASK_MTFACE | CD_MASK_MCOL; + + if((G.fileflags & G_FILE_GAME_MAT) && + (G.fileflags & G_FILE_GAME_MAT_GLSL)) { + mask |= CD_MASK_ORCO; } } } @@ -1845,13 +2053,41 @@ CustomDataMask get_viewedit_datamask() return mask; } -static DerivedMesh *create_orco_dm(Object *ob, Mesh *me) +static float *get_editmesh_orco_verts(EditMesh *em) +{ + EditVert *eve; + float *orco; + int a, totvert; + + /* these may not really be the orco's, but it's only for preview. + * could be solver better once, but isn't simple */ + + totvert= 0; + for(eve=em->verts.first; eve; eve=eve->next) + totvert++; + + orco = MEM_mallocN(sizeof(float)*3*totvert, "EditMesh Orco"); + + for(a=0, eve=em->verts.first; eve; eve=eve->next, a+=3) + VECCOPY(orco+a, eve->co); + + return orco; +} + +static DerivedMesh *create_orco_dm(Object *ob, Mesh *me, EditMesh *em) { DerivedMesh *dm; float (*orco)[3]; - dm= CDDM_from_mesh(me, ob); - orco= (float(*)[3])get_mesh_orco_verts(ob); + if(em) { + dm= CDDM_from_editmesh(em, me); + orco= (float(*)[3])get_editmesh_orco_verts(em); + } + else { + dm= CDDM_from_mesh(me, ob); + orco= (float(*)[3])get_mesh_orco_verts(ob); + } + CDDM_apply_vert_coords(dm, orco); CDDM_calc_normals(dm); MEM_freeN(orco); @@ -1859,7 +2095,7 @@ static DerivedMesh *create_orco_dm(Object *ob, Mesh *me) return dm; } -static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) +static void add_orco_dm(Object *ob, EditMesh *em, DerivedMesh *dm, DerivedMesh *orcodm) { float (*orco)[3], (*layerorco)[3]; int totvert; @@ -1874,8 +2110,10 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) else dm->getVertCos(dm, orco); } - else - orco= (float(*)[3])get_mesh_orco_verts(ob); + else { + if(em) orco= (float(*)[3])get_editmesh_orco_verts(em); + else orco= (float(*)[3])get_mesh_orco_verts(ob); + } transform_mesh_orco_verts(ob->data, orco, totvert, 0); @@ -2021,7 +2259,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if(dm && mti->requiredDataMask) { mask = mti->requiredDataMask(md); if(mask & CD_MASK_ORCO) - add_orco_dm(ob, dm, orcodm); + add_orco_dm(ob, NULL, dm, orcodm); } /* How to apply modifier depends on (a) what we already have as @@ -2074,7 +2312,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], mask= (CustomDataMask)curr->link; if(mask & CD_MASK_ORCO) { if(!orcodm) - orcodm= create_orco_dm(ob, me); + orcodm= create_orco_dm(ob, me, NULL); mask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, mask); @@ -2151,10 +2389,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], /* add an orco layer if needed */ if(dataMask & CD_MASK_ORCO) { - add_orco_dm(ob, finaldm, orcodm); + add_orco_dm(ob, NULL, finaldm, orcodm); if(deform_r && *deform_r) - add_orco_dm(ob, *deform_r, NULL); + add_orco_dm(ob, NULL, *deform_r, NULL); } *final_r = finaldm; @@ -2210,7 +2448,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, EditMesh *em = G.editMesh; ModifierData *md; float (*deformedVerts)[3] = NULL; - DerivedMesh *dm; + CustomDataMask mask; + DerivedMesh *dm, *orcodm = NULL; int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL); LinkNode *datamasks, *curr; @@ -2235,6 +2474,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, if(!editmesh_modifier_is_enabled(md, dm)) continue; + /* add an orco layer if needed by this modifier */ + if(dm && mti->requiredDataMask) { + mask = mti->requiredDataMask(md); + if(mask & CD_MASK_ORCO) + add_orco_dm(ob, em, dm, orcodm); + } + /* How to apply modifier depends on (a) what we already have as * a result of previous modifiers (could be a DerivedMesh or just * deformed vertices) and (b) what type the modifier is. @@ -2285,6 +2531,23 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, } } + /* create an orco derivedmesh in parallel */ + mask= (CustomDataMask)curr->link; + if(mask & CD_MASK_ORCO) { + if(!orcodm) + orcodm= create_orco_dm(ob, ob->data, em); + + mask &= ~CD_MASK_ORCO; + DM_set_only_copy(orcodm, mask); + ndm = mti->applyModifierEM(md, ob, em, orcodm); + + if(ndm) { + /* if the modifier returned a new dm, release the old one */ + if(orcodm && orcodm != ndm) orcodm->release(orcodm); + orcodm = ndm; + } + } + /* set the DerivedMesh to only copy needed data */ DM_set_only_copy(dm, (CustomDataMask)curr->link); @@ -2343,6 +2606,13 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, deformedVerts = NULL; } + /* add an orco layer if needed */ + if(dataMask & CD_MASK_ORCO) + add_orco_dm(ob, em, *final_r, orcodm); + + if(orcodm) + orcodm->release(orcodm); + if(deformedVerts) MEM_freeN(deformedVerts); } @@ -2638,7 +2908,7 @@ void multires_render_final(Object *ob, Mesh *me, DerivedMesh **dm, float *vert_c old->release(old); if(dataMask & CD_MASK_ORCO) - add_orco_dm(ob, *dm, NULL); + add_orco_dm(ob, NULL, *dm, NULL); /* Restore the original verts */ me->mr->newlvl= BLI_countlist(&me->mr->levels); @@ -2853,6 +3123,8 @@ int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**defo return numleft; } +/* ******************* GLSL ******************** */ + void DM_add_tangent_layer(DerivedMesh *dm) { /* mesh vars */ @@ -2973,6 +3245,91 @@ void DM_add_tangent_layer(DerivedMesh *dm) MEM_freeN(vtangents); } +void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs) +{ + CustomData *vdata, *fdata, *tfdata = NULL; + int a, b, layer; + + /* From the layers requested by the GLSL shader, figure out which ones are + * actually available for this derivedmesh, and retrieve the pointers */ + + memset(attribs, 0, sizeof(DMVertexAttribs)); + + vdata = &dm->vertData; + fdata = &dm->faceData; + + /* ugly hack, editmesh derivedmesh doesn't copy face data, this way we + * can use offsets instead */ + if(dm->release == emDM_release) + tfdata = &((EditMeshDerivedMesh*)dm)->em->fdata; + else + tfdata = fdata; + + /* add a tangent layer if necessary */ + for(b = 0; b < gattribs->totlayer; b++) + if(gattribs->layer[b].type == CD_TANGENT) + if(CustomData_get_layer_index(fdata, CD_TANGENT) == -1) + DM_add_tangent_layer(dm); + + for(b = 0; b < gattribs->totlayer; b++) { + if(gattribs->layer[b].type == CD_MTFACE) { + /* uv coordinates */ + if(gattribs->layer[b].name[0]) + layer = CustomData_get_named_layer_index(tfdata, CD_MTFACE, + gattribs->layer[b].name); + else + layer = CustomData_get_active_layer_index(tfdata, CD_MTFACE); + + if(layer != -1) { + a = attribs->tottface++; + + attribs->tface[a].array = tfdata->layers[layer].data; + attribs->tface[a].emOffset = tfdata->layers[layer].offset; + attribs->tface[a].glIndex = gattribs->layer[b].glindex; + } + } + else if(gattribs->layer[b].type == CD_MCOL) { + /* vertex colors */ + if(gattribs->layer[b].name[0]) + layer = CustomData_get_named_layer_index(tfdata, CD_MCOL, + gattribs->layer[b].name); + else + layer = CustomData_get_active_layer_index(tfdata, CD_MCOL); + + if(layer != -1) { + a = attribs->totmcol++; + + attribs->mcol[a].array = tfdata->layers[layer].data; + attribs->mcol[a].emOffset = tfdata->layers[layer].offset; + attribs->mcol[a].glIndex = gattribs->layer[b].glindex; + } + } + else if(gattribs->layer[b].type == CD_TANGENT) { + /* tangents */ + layer = CustomData_get_layer_index(fdata, CD_TANGENT); + + if(layer != -1) { + attribs->tottang = 1; + + attribs->tang.array = fdata->layers[layer].data; + attribs->tang.emOffset = fdata->layers[layer].offset; + attribs->tang.glIndex = gattribs->layer[b].glindex; + } + } + else if(gattribs->layer[b].type == CD_ORCO) { + /* original coordinates */ + layer = CustomData_get_layer_index(vdata, CD_ORCO); + + if(layer != -1) { + attribs->totorco = 1; + + attribs->orco.array = vdata->layers[layer].data; + attribs->orco.emOffset = vdata->layers[layer].offset; + attribs->orco.glIndex = gattribs->layer[b].glindex; + } + } + } +} /* ************************* fluidsim bobj file handling **************************** */ diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 74c6c551a83..8921ea5d3b7 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) # OpenGL and Python +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) @@ -74,6 +75,9 @@ CPPFLAGS += -I$(NAN_ZLIB)/include #path to nodes CPPFLAGS += -I../../nodes +#path to gpu +CPPFLAGS += -I../../gpu + # path to our own external headerfiles CPPFLAGS += -I.. diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 5b96bf11056..d65a99f23f0 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -62,6 +62,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "nla.h" @@ -340,6 +341,60 @@ void free_pose(bPose *pose) } } +void game_copy_pose(bPose **dst, bPose *src) +{ + bPose *out; + bPoseChannel *pchan, *outpchan; + GHash *ghash; + + /* the game engine copies the current armature pose and then swaps + * the object pose pointer. this makes it possible to change poses + * without affecting the original blender data. */ + + if (!src) { + *dst=NULL; + return; + } + else if (*dst==src) { + printf("copy_pose source and target are the same\n"); + *dst=NULL; + return; + } + + out= MEM_dupallocN(src); + out->agroups.first= out->agroups.last= NULL; + duplicatelist(&out->chanbase, &src->chanbase); + + /* remap pointers */ + ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + pchan= src->chanbase.first; + outpchan= out->chanbase.first; + for (; pchan; pchan=pchan->next, outpchan=outpchan->next) + BLI_ghash_insert(ghash, pchan, outpchan); + + for (pchan=out->chanbase.first; pchan; pchan=pchan->next) { + pchan->parent= BLI_ghash_lookup(ghash, pchan->parent); + pchan->child= BLI_ghash_lookup(ghash, pchan->child); + pchan->path= NULL; + } + + BLI_ghash_free(ghash, NULL, NULL); + + *dst=out; +} + +void game_free_pose(bPose *pose) +{ + if (pose) { + /* we don't free constraints, those are owned by the original pose */ + if(pose->chanbase.first) + BLI_freelistN(&pose->chanbase); + + MEM_freeN(pose); + } +} + static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) { bConstraint *pcon, *con; @@ -347,6 +402,8 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan VECCOPY(pchan->loc, chan->loc); VECCOPY(pchan->size, chan->size); QUATCOPY(pchan->quat, chan->quat); + Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat); + Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat); pchan->flag= chan->flag; con= chan->constraints.first; @@ -860,7 +917,7 @@ typedef struct NlaIpoChannel { int type; } NlaIpoChannel; -void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, char *name, float ctime) +void extract_ipochannels_from_action(ListBase *lb, ID *id, bAction *act, const char *name, float ctime) { bActionChannel *achan= get_action_channel(act, name); IpoCurve *icu; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 1592c3e5504..ceb0e132ff9 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -303,7 +303,7 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4]; + float mat[4][4], tmat[4][4]; if(ob->dup_group==NULL) return; group= ob->dup_group; @@ -320,7 +320,15 @@ static void group_duplilist(ListBase *lb, Object *ob, int level, int animated) /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if(go->ob!=ob) { - Mat4MulMat4(mat, go->ob->obmat, ob->obmat); + /* Group Dupli Offset, should apply after everything else */ + if (group->dupli_ofs[0] || group->dupli_ofs[1] || group->dupli_ofs[2]) { + Mat4CpyMat4(tmat, go->ob->obmat); + VecSubf(tmat[3], tmat[3], group->dupli_ofs); + Mat4MulMat4(mat, tmat, ob->obmat); + } else { + Mat4MulMat4(mat, go->ob->obmat, ob->obmat); + } + dob= new_dupli_object(lb, go->ob, mat, ob->lay, 0, OB_DUPLIGROUP, animated); dob->no_draw= (dob->origlay & group->layer)==0; @@ -775,6 +783,10 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ hair= (totchild == 0 || psys->childcache) && psys->pathcache; if(!hair) return; + + /* we use cache, update totchild according to cached data */ + totchild = psys->totchildcache; + totpart = psys->totcached; } psys->lattice = psys_get_lattice(par, psys); @@ -857,6 +869,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ } VECCOPY(pamat[3], cache->co); + pamat[3][3]= 1.0f; + } else if(step_nbr) { /* other keys */ @@ -1059,7 +1073,8 @@ static void object_duplilist_recursive(ID *id, Object *ob, ListBase *duplilist, } } -/* note; group dupli's already set transform matrix. see note in group_duplilist() */ +/* Returns a list of DupliObject + * note; group dupli's already set transform matrix. see note in group_duplilist() */ ListBase *object_duplilist(Scene *sce, Object *ob) { ListBase *duplilist= MEM_mallocN(sizeof(ListBase), "duplilist"); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index fb7d59c137a..720ed0513ed 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1690,7 +1690,7 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) were executed & assigned. Now as last we do an IK pass */ static void execute_posetree(Object *ob, PoseTree *tree) { - float R_parmat[3][3]; + float R_parmat[3][3], identity[3][3]; float iR_parmat[3][3]; float R_bonemat[3][3]; float goalrot[3][3], goalpos[3]; @@ -1699,7 +1699,8 @@ static void execute_posetree(Object *ob, PoseTree *tree) float irest_basis[3][3], full_basis[3][3]; float end_pose[4][4], world_pose[4][4]; float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - int a, flag, hasstretch=0; + float resultinf=0.0f; + int a, flag, hasstretch=0, resultblend=0; bPoseChannel *pchan; IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; @@ -1844,6 +1845,12 @@ static void execute_posetree(Object *ob, PoseTree *tree) Mat4MulMat4(goal, rootmat, goalinv); VECCOPY(polepos, goal[3]); poleconstrain= 1; + + /* for pole targets, we blend the result of the ik solver + * instead of the target position, otherwise we can't get + * a smooth transition */ + resultblend= 1; + resultinf= target->con->enforce; if(data->flag & CONSTRAINT_IK_GETANGLE) { poleangledata= data; @@ -1853,7 +1860,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) } /* do we need blending? */ - if (target->con->enforce!=1.0) { + if (!resultblend && target->con->enforce!=1.0) { float q1[4], q2[4], q[4]; float fac= target->con->enforce; float mfac= 1.0-fac; @@ -1903,7 +1910,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); if(hasstretch) ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - + for(a=0; atotchannel; a++) { IK_GetBasisChange(iktree[a], tree->basis_change[a]); @@ -1931,6 +1938,12 @@ static void execute_posetree(Object *ob, PoseTree *tree) VecMulf(tree->basis_change[a][1], stretch); VecMulf(tree->basis_change[a][2], stretch); } + + if(resultblend && resultinf!=1.0f) { + Mat3One(identity); + Mat3BlendMat3(tree->basis_change[a], identity, + tree->basis_change[a], resultinf); + } IK_FreeSegment(iktree[a]); } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index aca51e56c6e..1fe6447752e 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -525,6 +525,7 @@ typedef struct UndoElem { char str[FILE_MAXDIR+FILE_MAXFILE]; char name[MAXUNDONAME]; MemFile memfile; + uintptr_t undosize; } UndoElem; static ListBase undobase={NULL, NULL}; @@ -555,6 +556,7 @@ static int read_undosave(UndoElem *uel) /* name can be a dynamic string */ void BKE_write_undo(char *name) { + uintptr_t maxmem, totmem, memused; int nr, success; UndoElem *uel; @@ -616,8 +618,36 @@ void BKE_write_undo(char *name) if(curundo->prev) prevfile= &(curundo->prev->memfile); + memused= MEM_get_memory_in_use(); success= BLO_write_file_mem(prevfile, &curundo->memfile, G.fileflags, &err); - + curundo->undosize= MEM_get_memory_in_use() - memused; + } + + if(U.undomemory != 0) { + /* limit to maximum memory (afterwards, we can't know in advance) */ + totmem= 0; + maxmem= ((uintptr_t)U.undomemory)*1024*1024; + + /* keep at least two (original + other) */ + uel= undobase.last; + while(uel && uel->prev) { + totmem+= uel->undosize; + if(totmem>maxmem) break; + uel= uel->prev; + } + + if(uel) { + if(uel->prev && uel->prev->prev) + uel= uel->prev; + + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + BLI_remlink(&undobase, first); + /* the merge is because of compression */ + BLO_merge_memfile(&first->memfile, &first->next->memfile); + MEM_freeN(first); + } + } } } @@ -683,14 +713,14 @@ char *BKE_undo_menu_string(void) UndoElem *uel; DynStr *ds= BLI_dynstr_new(); char *menu; - + BLI_dynstr_append(ds, "Global Undo History %t"); for(uel= undobase.first; uel; uel= uel->next) { BLI_dynstr_append(ds, "|"); BLI_dynstr_append(ds, uel->name); } - + menu= BLI_dynstr_get_cstring(ds); BLI_dynstr_free(ds); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 472df3d0f26..9d5dcb8109b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -58,6 +58,10 @@ #include "MEM_guardedalloc.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + #include #include @@ -243,7 +247,7 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) glEnd(); } -static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) +static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; MVert *mvert = cddm->mvert; @@ -271,7 +275,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) || new_shademodel != shademodel) { glEnd(); - drawCurrentMat = setMaterial(matnr = new_matnr); + drawCurrentMat = setMaterial(matnr = new_matnr, NULL); glShadeModel(shademodel = new_shademodel); glBegin(glmode = new_glmode); @@ -556,6 +560,134 @@ static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData); } +static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) +{ + CDDerivedMesh *cddm = (CDDerivedMesh*) dm; + GPUVertexAttribs gattribs; + DMVertexAttribs attribs; + MVert *mvert = cddm->mvert; + MFace *mface = cddm->mface; + MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); + float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL); + int a, b, dodraw, smoothnormal, matnr, new_matnr; + int transp, new_transp, orig_transp; + int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX); + + matnr = -1; + smoothnormal = 0; + dodraw = 0; + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + + memset(&attribs, 0, sizeof(attribs)); + + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + + for(a = 0; a < dm->numFaceData; a++, mface++) { + new_matnr = mface->mat_nr + 1; + + if(new_matnr != matnr) { + glEnd(); + + dodraw = setMaterial(matnr = new_matnr, &gattribs); + if(dodraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + + glBegin(GL_QUADS); + } + + if(!dodraw) { + continue; + } + else if(setDrawOptions) { + orig = index[a]; + + if(orig == ORIGINDEX_NONE) + continue; + else if(!setDrawOptions(userData, orig)) + continue; + } + + if(tf) { + new_transp = tf[a].transp; + + if(new_transp != transp) { + glEnd(); + + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + + glBegin(GL_QUADS); + } + } + + smoothnormal = (mface->flag & ME_SMOOTH); + + if(!smoothnormal) { + if(nors) { + glNormal3fv(nors[a]); + } + else { + /* TODO ideally a normal layer should always be available */ + float nor[3]; + if(mface->v4) { + CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, mvert[mface->v4].co, + nor); + } else { + CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, nor); + } + glNormal3fv(nor); + } + } + +#define PASSVERT(index, vert) { \ + if(attribs.totorco) \ + glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = &attribs.tface[b].array[a]; \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[a*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ + if(smoothnormal) \ + glNormal3sv(mvert[index].no); \ + glVertex3fv(mvert[index].co); \ +} + + PASSVERT(mface->v1, 0); + PASSVERT(mface->v2, 1); + PASSVERT(mface->v3, 2); + if(mface->v4) + PASSVERT(mface->v4, 3) + else + PASSVERT(mface->v3, 2) + +#undef PASSVERT + } + glEnd(); + + glShadeModel(GL_FLAT); +} + +static void cdDM_drawFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) +{ + dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData) { CDDerivedMesh *cddm = (CDDerivedMesh*) dm; @@ -713,8 +845,10 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->drawFacesSolid = cdDM_drawFacesSolid; dm->drawFacesColored = cdDM_drawFacesColored; dm->drawFacesTex = cdDM_drawFacesTex; + dm->drawFacesGLSL = cdDM_drawFacesGLSL; dm->drawMappedFaces = cdDM_drawMappedFaces; dm->drawMappedFacesTex = cdDM_drawMappedFacesTex; + dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL; dm->foreachMappedVert = cdDM_foreachMappedVert; dm->foreachMappedEdge = cdDM_foreachMappedEdge; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 295b8fe3552..45b8bb7935c 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -730,3 +730,24 @@ void curvemapping_initialize(CurveMapping *cumap) curvemap_make_table(cumap->cm+a, &cumap->clipr); } } + +void curvemapping_table_RGBA(CurveMapping *cumap, float **array, int *size) +{ + int a; + + *size = CM_TABLE+1; + *array = MEM_callocN(sizeof(float)*(*size)*4, "CurveMapping"); + curvemapping_initialize(cumap); + + for(a=0; a<*size; a++) { + if(cumap->cm[0].table) + (*array)[a*4+0]= cumap->cm[0].table[a].y; + if(cumap->cm[1].table) + (*array)[a*4+1]= cumap->cm[1].table[a].y; + if(cumap->cm[2].table) + (*array)[a*4+2]= cumap->cm[2].table[a].y; + if(cumap->cm[3].table) + (*array)[a*4+3]= cumap->cm[3].table[a].y; + } +} + diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 1d7d4d1fda0..db173126375 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -369,19 +369,12 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */ { /* world to pose */ - if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_LOCAL || to==CONSTRAINT_SPACE_PARLOCAL) { - Mat4Invert(imat, ob->obmat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, imat); - } + Mat4Invert(imat, ob->obmat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, imat); - /* pose to local */ - if (to == CONSTRAINT_SPACE_LOCAL) { - /* call self with slightly different values */ - constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); - } - /* pose to local + parent */ - else if (to == CONSTRAINT_SPACE_PARLOCAL) { + /* use pose-space as stepping stone for other spaces... */ + if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } @@ -447,68 +440,65 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4 break; case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ { - /* local to pose */ - if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) { - /* do inverse procedure that was done for pose to local */ - if (pchan->bone) { - /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ - if (pchan->parent) { - float offs_bone[4][4]; + /* local to pose - do inverse procedure that was done for pose to local */ + if (pchan->bone) { + /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ + if (pchan->parent) { + float offs_bone[4][4]; + + /* construct offs_bone the same way it is done in armature.c */ + Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); + VECCOPY(offs_bone[3], pchan->bone->head); + offs_bone[3][1]+= pchan->bone->parent->length; + + if (pchan->bone->flag & BONE_HINGE) { + /* pose_mat = par_pose-space_location * chan_mat */ + float tmat[4][4]; - /* construct offs_bone the same way it is done in armature.c */ - Mat4CpyMat3(offs_bone, pchan->bone->bone_mat); - VECCOPY(offs_bone[3], pchan->bone->head); - offs_bone[3][1]+= pchan->bone->parent->length; - if (pchan->bone->flag & BONE_HINGE) { - /* pose_mat = par_pose-space_location * chan_mat */ - float tmat[4][4]; - - /* the rotation of the parent restposition */ - Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat); - - /* the location of actual parent transform */ - VECCOPY(tmat[3], offs_bone[3]); - offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; - Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]); - - Mat4MulMat4(diff_mat, offs_bone, tmat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, diff_mat); - } - else { - /* pose_mat = par_pose_mat * bone_mat * chan_mat */ - Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, tempmat, diff_mat); - } + /* the rotation of the parent restposition */ + Mat4CpyMat4(tmat, pchan->bone->parent->arm_mat); + /* the location of actual parent transform */ + VECCOPY(tmat[3], offs_bone[3]); + offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; + Mat4MulVecfl(pchan->parent->pose_mat, tmat[3]); + + Mat4MulMat4(diff_mat, offs_bone, tmat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, diff_mat); } else { - Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); - + /* pose_mat = par_pose_mat * bone_mat * chan_mat */ + Mat4MulMat4(diff_mat, offs_bone, pchan->parent->pose_mat); Mat4CpyMat4(tempmat, mat); Mat4MulMat4(mat, tempmat, diff_mat); } } + else { + Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); + + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, tempmat, diff_mat); + } } - /* local to world */ - if (to == CONSTRAINT_SPACE_WORLD) { + + /* use pose-space as stepping stone for other spaces */ + if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); - } + } } break; case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */ { - /* local to pose */ - if (to==CONSTRAINT_SPACE_POSE || to==CONSTRAINT_SPACE_WORLD) { - if (pchan->bone) { - Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); - Mat4CpyMat4(tempmat, mat); - Mat4MulMat4(mat, diff_mat, tempmat); - } + /* local + parent to pose */ + if (pchan->bone) { + Mat4CpyMat4(diff_mat, pchan->bone->arm_mat); + Mat4CpyMat4(tempmat, mat); + Mat4MulMat4(mat, diff_mat, tempmat); } - /* local to world */ - if (to == CONSTRAINT_SPACE_WORLD) { + + /* use pose-space as stepping stone for other spaces */ + if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { /* call self with slightly different values */ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); } @@ -1883,7 +1873,7 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT { bPythonConstraint *data= con->data; - if ((G.f & G_DOSCRIPTLINKS) && VALID_CONS_TARGET(ct)) { + if (VALID_CONS_TARGET(ct)) { /* special exception for curves - depsgraph issues */ if (ct->tar->type == OB_CURVE) { Curve *cu= ct->tar->data; @@ -1897,7 +1887,10 @@ static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintT * this matrix if it needs to do so */ constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); - BPY_pyconstraint_target(data, ct); + + /* only execute target calculation if allowed */ + if (G.f & G_DOSCRIPTLINKS) + BPY_pyconstraint_target(data, ct); } else if (ct) Mat4One(ct->matrix); @@ -1907,6 +1900,7 @@ static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targ { bPythonConstraint *data= con->data; + /* only evaluate in python if we're allowed to do so */ if ((G.f & G_DOSCRIPTLINKS)==0) return; /* currently removed, until I this can be re-implemented for multiple targets */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 80f450000bb..d958c43aa40 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -581,9 +581,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int for(; psys; psys=psys->next) { ParticleSettings *part= psys->part; - + dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); + if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) + continue; + if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob && BLI_findlink(&psys->keyed_ob->particlesystem,psys->keyed_psys-1)) { node2 = dag_get_node(dag, psys->keyed_ob); @@ -1924,8 +1927,10 @@ static void dag_object_time_update_flags(Object *ob) } } } - else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; - else if(ob->parent) { + + if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; + + if(ob->parent) { /* motion path or bone child */ if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB; } @@ -1946,10 +1951,11 @@ static void dag_object_time_update_flags(Object *ob) } } } - else if(modifiers_isSoftbodyEnabled(ob)) ob->recalc |= OB_RECALC_DATA; - else if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; - else if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; - else { + + if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; + if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; + + { Mesh *me; Curve *cu; Lattice *lt; diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 0842e55a0ea..327008c60de 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -267,7 +267,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) hit.dist = len + FLT_EPSILON; // check if the way is blocked - if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0) + if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) { // visibility is only between 0 and 1, calculated from 1-absorption visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01))); @@ -406,12 +406,15 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); + Normalize(mag_vec); + VecMulf(mag_vec,force_val*falloff); VecAddf(field,field,mag_vec); break; case PFIELD_VORTEX: Crossf(mag_vec,eff_vel,vec_to_part); + Normalize(mag_vec); VecMulf(mag_vec,force_val*distance*falloff); @@ -425,6 +428,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, /* magnetic field of a moving charge */ Crossf(temp,eff_vel,vec_to_part); + Normalize(temp); + Crossf(temp2,velocity,temp); VecAddf(mag_vec,mag_vec,temp2); @@ -437,6 +442,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); + Normalize(mag_vec); + VecMulf(mag_vec,force_val*falloff); VecSubf(field,field,mag_vec); @@ -451,6 +458,8 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val, else VecCopyf(mag_vec,vec_to_part); + Normalize(mag_vec); + VecMulf(mag_vec,charge*force_val*falloff); VecAddf(field,field,mag_vec); break; @@ -535,10 +544,6 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float where_is_object_time(ob,cur_time); /* use center of object for distance calculus */ - obloc= ob->obmat[3]; - VECSUB(vect_to_vert, obloc, opco); - distance = VecLength(vect_to_vert); - VecSubf(vec_to_part, opco, ob->obmat[3]); distance = VecLength(vec_to_part); diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index fb48c875995..479be2ee644 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -2632,17 +2632,17 @@ static void write_videoscape_mesh(Object *ob, char *str) if(evl->v4==0) { fprintf(fp, "3 %ld %ld %ld 0x%x\n", - evl->v1->tmp.l, - evl->v2->tmp.l, - evl->v3->tmp.l, + (long int) evl->v1->tmp.l, + (long int) evl->v2->tmp.l, + (long int) evl->v3->tmp.l, kleur[evl->mat_nr]); } else { fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - evl->v1->tmp.l, - evl->v2->tmp.l, - evl->v3->tmp.l, - evl->v4->tmp.l, + (long int) evl->v1->tmp.l, + (long int) evl->v2->tmp.l, + (long int) evl->v3->tmp.l, + (long int) evl->v4->tmp.l, kleur[evl->mat_nr]); } evl= evl->next; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 2ffe8590b59..0d2f86bb151 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -91,6 +91,16 @@ void unlink_group(Group *group) ma->group= NULL; } for (sce= G.main->scene.first; sce; sce= sce->id.next) { + Base *base= sce->base.first; + + /* ensure objects are not in this group */ + for(; base; base= base->next) { + if(rem_from_group(group, base->object) && find_group(base->object, NULL)==NULL) { + base->object->flag &= ~OB_FROMGROUP; + base->flag &= ~OB_FROMGROUP; + } + } + for(srl= sce->r.layers.first; srl; srl= srl->next) { if (srl->light_override==group) srl->light_override= NULL; @@ -117,6 +127,9 @@ void unlink_group(Group *group) psys->part->eff_group= NULL; } } + + /* group stays in library, but no members */ + free_group(group); group->id.us= 0; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 07537e3a81c..27fa00ac239 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -53,6 +53,7 @@ #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_camera_types.h" +#include "DNA_sequence_types.h" #include "DNA_texture_types.h" #include "DNA_userdef_types.h" @@ -77,15 +78,15 @@ #include "RE_pipeline.h" -/* bad level; call to free_realtime_image */ -#include "BKE_bad_level_calls.h" - /* for stamp drawing to an image */ #include "BMF_Api.h" #include "blendef.h" #include "BSE_time.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + #include "BLO_sys_types.h" // for intptr_t support /* max int, to indicate we don't store sequences in ibuf */ @@ -240,7 +241,7 @@ static void image_free_buffers(Image *ima) ima->rr= NULL; } - free_realtime_image(ima); + GPU_free_image(ima); ima->ok= IMA_OK; } @@ -620,7 +621,7 @@ void free_old_images() This gives textures a "second chance" to be used before dying. */ if(ima->bindcode || ima->repbind) { - free_realtime_image(ima); + GPU_free_image(ima); ima->lastused = ctime; } /* Otherwise, just kill the buffers */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 4af25ee99e7..e8a25aaaf80 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1390,6 +1390,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= ma->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= ma->mtex[9]; + else if(icu->adrcode & MA_MAP12) mtex= ma->mtex[11]; + else if(icu->adrcode & MA_MAP11) mtex= ma->mtex[10]; + else if(icu->adrcode & MA_MAP13) mtex= ma->mtex[12]; + else if(icu->adrcode & MA_MAP14) mtex= ma->mtex[13]; + else if(icu->adrcode & MA_MAP15) mtex= ma->mtex[14]; + else if(icu->adrcode & MA_MAP16) mtex= ma->mtex[15]; + else if(icu->adrcode & MA_MAP17) mtex= ma->mtex[16]; + else if(icu->adrcode & MA_MAP18) mtex= ma->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); @@ -1479,7 +1487,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= wo->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= wo->mtex[9]; - + else if(icu->adrcode & MA_MAP11) mtex= wo->mtex[10]; + else if(icu->adrcode & MA_MAP12) mtex= wo->mtex[11]; + else if(icu->adrcode & MA_MAP13) mtex= wo->mtex[12]; + else if(icu->adrcode & MA_MAP14) mtex= wo->mtex[13]; + else if(icu->adrcode & MA_MAP15) mtex= wo->mtex[14]; + else if(icu->adrcode & MA_MAP16) mtex= wo->mtex[15]; + else if(icu->adrcode & MA_MAP17) mtex= wo->mtex[16]; + else if(icu->adrcode & MA_MAP18) mtex= wo->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); } @@ -1524,6 +1539,14 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7]; else if(icu->adrcode & MA_MAP9) mtex= la->mtex[8]; else if(icu->adrcode & MA_MAP10) mtex= la->mtex[9]; + else if(icu->adrcode & MA_MAP11) mtex= la->mtex[10]; + else if(icu->adrcode & MA_MAP12) mtex= la->mtex[11]; + else if(icu->adrcode & MA_MAP13) mtex= la->mtex[12]; + else if(icu->adrcode & MA_MAP14) mtex= la->mtex[13]; + else if(icu->adrcode & MA_MAP15) mtex= la->mtex[14]; + else if(icu->adrcode & MA_MAP16) mtex= la->mtex[15]; + else if(icu->adrcode & MA_MAP17) mtex= la->mtex[16]; + else if(icu->adrcode & MA_MAP18) mtex= la->mtex[17]; if(mtex) { poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); @@ -1672,6 +1695,8 @@ void set_icu_vars(IpoCurve *icu) icu->ymax= 5.0; break; case MA_ADD: icu->ymax= 1.0; break; + case MA_EMIT: + icu->ymax= 2.0; break; default: icu->ymax= 1.0; break; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 3983eecdaba..f05b84f6e90 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -61,6 +61,8 @@ #include "BPY_extern.h" +#include "GPU_material.h" + /* used in UI and render */ Material defmaterial; @@ -96,6 +98,9 @@ void free_material(Material *ma) ntreeFreeTree(ma->nodetree); MEM_freeN(ma->nodetree); } + + if(ma->gpumaterial.first) + GPU_material_free(ma); } void init_material(Material *ma) @@ -207,6 +212,8 @@ Material *copy_material(Material *ma) if(ma->nodetree) { man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */ } + + man->gpumaterial.first= man->gpumaterial.last= NULL; return man; } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 43e48c3bacd..77b9ea4fa2d 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -79,45 +79,6 @@ #include "BLI_editVert.h" #include "BLI_arithb.h" -int update_realtime_texture(MTFace *tface, double time) -{ - Image *ima; - int inc = 0; - float diff; - int newframe; - - ima = tface->tpage; - - if (!ima) - return 0; - - if (ima->lastupdate<0) - ima->lastupdate = 0; - - if (ima->lastupdate>time) - ima->lastupdate=(float)time; - - if(ima->tpageflag & IMA_TWINANIM) { - if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; - - /* check: is the bindcode not in the array? Then free. (still to do) */ - - diff = (float)(time-ima->lastupdate); - - inc = (int)(diff*(float)ima->animspeed); - - ima->lastupdate+=((float)inc/(float)ima->animspeed); - - newframe = ima->lastframe+inc; - - if (newframe > (int)ima->twend) - newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); - - ima->lastframe = newframe; - } - return inc; -} - void mesh_update_customdata_pointers(Mesh *me) { me->mvert = CustomData_get_layer(&me->vdata, CD_MVERT); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3b8bb25d601..16287d360b5 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -794,12 +794,18 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, if(amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob) { Curve *cu = amd->curve_ob->data; if(cu) { + float tmp_mat[3][3]; + float scale; + + object_to_mat3(amd->curve_ob, tmp_mat); + scale = Mat3ToScalef(tmp_mat); + if(!cu->path) { cu->flag |= CU_PATH; // needed for path & bevlist makeDispListCurveTypes(amd->curve_ob, 0); } if(cu->path) - length = cu->path->totdist; + length = scale*cu->path->totdist; } } @@ -5288,6 +5294,11 @@ static void softbodyModifier_deformVerts( sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); } +static int softbodyModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + /* Cloth */ @@ -7637,6 +7648,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_RequiresOriginalData; mti->deformVerts = softbodyModifier_deformVerts; + mti->dependsOnTime = softbodyModifier_dependsOnTime; mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_Nonconstructive; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 4e36df35a14..94a21cdd5df 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -68,6 +68,9 @@ #include "SHD_node.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + static ListBase empty_list = {NULL, NULL}; ListBase node_all_composit = {NULL, NULL}; ListBase node_all_shaders = {NULL, NULL}; @@ -2352,6 +2355,117 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeEndExecTree(ntree); } +/* GPU material from shader nodes */ + +static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) +{ + bNodeSocket *sock; + int i; + + for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { + memset(&gs[i], 0, sizeof(gs[i])); + + QUATCOPY(gs[i].vec, ns[i]->vec); + gs[i].link= ns[i]->data; + + if (sock->type == SOCK_VALUE) + gs[i].type= GPU_FLOAT; + else if (sock->type == SOCK_VECTOR) + gs[i].type= GPU_VEC3; + else if (sock->type == SOCK_RGBA) + gs[i].type= GPU_VEC4; + else + gs[i].type= GPU_NONE; + + gs[i].name = ""; + gs[i].hasinput= ns[i]->hasinput && ns[i]->data; + gs[i].hasoutput= ns[i]->hasinput && ns[i]->data; + gs[i].sockettype= ns[i]->sockettype; + } + + gs[i].type= GPU_NONE; +} + +static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs) +{ + bNodeSocket *sock; + int i; + + for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { + ns[i]->data= gs[i].link; + ns[i]->hasinput= gs[i].hasinput && gs[i].link; + ns[i]->hasoutput= gs[i].hasoutput; + ns[i]->sockettype= gs[i].sockettype; + } +} + +static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in, bNodeStack **out) +{ + bNode *node; + bNodeTree *ntree= (bNodeTree *)gnode->id; + bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ + bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ + GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; + int doit = 0; + + if(ntree==NULL) return; + + stack+= gnode->stack_index; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->gpufunc) { + group_node_get_stack(node, stack, nsin, nsout, in, out); + + doit = 0; + + /* for groups, only execute outputs for edited group */ + if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { + if(gnode->flag & NODE_GROUP_EDIT) + if(node->flag & NODE_DO_OUTPUT) + doit = 1; + } + else + doit = 1; + + if(doit) { + gpu_from_node_stack(&node->inputs, nsin, gpuin); + gpu_from_node_stack(&node->outputs, nsout, gpuout); + if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) + data_from_gpu_stack(&node->outputs, nsout, gpuout); + } + } + } +} + +void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) +{ + bNode *node; + bNodeStack *stack; + bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */ + bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */ + GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1]; + + if((ntree->init & NTREE_EXEC_INIT)==0) + ntreeBeginExecTree(ntree); + + stack= ntree->stack; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->typeinfo->gpufunc) { + node_get_stack(node, stack, nsin, nsout); + gpu_from_node_stack(&node->inputs, nsin, gpuin); + gpu_from_node_stack(&node->outputs, nsout, gpuout); + if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout)) + data_from_gpu_stack(&node->outputs, nsout, gpuout); + } + else if(node->type==NODE_GROUP && node->id) { + node_get_stack(node, stack, nsin, nsout); + gpu_node_group_execute(stack, mat, node, nsin, nsout); + } + } + + ntreeEndExecTree(ntree); +} /* **************** call to switch lamploop for material node ************ */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7b36e46d45e..6cbcba65f56 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -112,6 +112,8 @@ #include "BPY_extern.h" +#include "GPU_material.h" + #include "blendef.h" /* Local function protos */ @@ -268,6 +270,7 @@ void free_object(Object *ob) } if(ob->soft) sbFree(ob->soft); if(ob->fluidsimSettings) fluidsimSettingsFree(ob->fluidsimSettings); + if(ob->gpulamp.first) GPU_lamp_free(ob); } static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin) @@ -694,9 +697,11 @@ float dof_camera(Object *ob) if (cam->dof_ob) { /* too simple, better to return the distance on the view axis only * return VecLenf(ob->obmat[3], cam->dof_ob->obmat[3]); */ + float mat[4][4], obmat[4][4]; - float mat[4][4]; - Mat4Invert(ob->imat, ob->obmat); + Mat4CpyMat4(obmat, ob->obmat); + Mat4Ortho(obmat); + Mat4Invert(ob->imat, obmat); Mat4MulMat4(mat, cam->dof_ob->obmat, ob->imat); return fabs(mat[3][2]); } @@ -918,7 +923,7 @@ Object *add_only_object(int type, char *name) QuatOne(ob->dquat); #endif - ob->col[0]= ob->col[1]= ob->col[2]= 0.0; + ob->col[0]= ob->col[1]= ob->col[2]= 1.0; ob->col[3]= 1.0; ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0; @@ -955,7 +960,8 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[0] = 1.0f; ob->anisotropicFriction[1] = 1.0f; ob->anisotropicFriction[2] = 1.0f; - ob->gameflag= OB_PROP; + ob->gameflag= OB_PROP|OB_COLLISION; + ob->margin = 0.0; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; @@ -1226,6 +1232,7 @@ Object *copy_object(Object *ob) obn->vnode = NULL; #endif + obn->gpulamp.first = obn->gpulamp.last = NULL; return obn; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2f4696fc442..3ff57f55992 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -46,6 +46,7 @@ #include "DNA_object_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" +#include "DNA_ipo_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -295,7 +296,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) ParticleSystemModifierData *psmd; Mesh *me; - if(psys->flag & PSYS_DISABLED) + if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) return 0; if(ob->type == OB_MESH) { @@ -379,8 +380,11 @@ void psys_free_children(ParticleSystem *psys) } /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) -{ +{ if(psys){ + int nr = 0; + ParticleSystem * tpsys; + if(ob->particlesystem.first == NULL && G.f & G_PARTICLEEDIT) G.f &= ~G_PARTICLEEDIT; @@ -406,6 +410,21 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->effectors.first) psys_end_effectors(psys); + + // check if we are last non-visible particle system + for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){ + if(tpsys->part) + { + if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + { + nr++; + break; + } + } + } + // clear do-not-draw-flag + if(!nr) + ob->transflag &= ~OB_DUPLIPARTS; if(psys->part){ psys->part->id.us--; @@ -417,7 +436,7 @@ void psys_free(Object *ob, ParticleSystem * psys) if(psys->pointcache) BKE_ptcache_free(psys->pointcache); - + MEM_freeN(psys); } } @@ -1756,37 +1775,17 @@ static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleC static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec) { if(*cur_length + length > max_length){ - //if(ptime){ - // /* parents need to be calculated fully first so that they don't mess up their children */ - // /* we'll make a note of where we got to though so that they're easy to finish later */ - // state->time=(max_length-*cur_length)/length; - // cache[totpart+p]->time=(float)k; - // } - //} - //else{ VecMulf(dvec, (max_length - *cur_length) / length); VECADD(state->co, (state - 1)->co, dvec); keys->steps = k; /* something over the maximum step value */ return k=100000; - //} } else { *cur_length+=length; return k; } } -static void finalize_path_length(ParticleCacheKey *keys) -{ - ParticleCacheKey *state = keys; - float dvec[3]; - state += state->steps; - - VECSUB(dvec, state->co, (state - 1)->co); - VecMulf(dvec, state->steps); - VECADD(state->co, (state - 1)->co, dvec); -} static void offset_child(ChildParticle *cpa, ParticleKey *par, ParticleKey *child, float flat, float radius) { VECCOPY(child->co,cpa->fuv); @@ -1967,7 +1966,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey **cache= psys->childcache; ParticleCacheKey **pcache= psys->pathcache; ParticleCacheKey *state, *par = NULL, *key[4]; - ParticleData *pa; + ParticleData *pa=NULL; ParticleTexture ptex; float *cpa_fuv=0; float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3]; @@ -2268,10 +2267,6 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, get_strand_normal(ctx->ma, ornor, cur_length, state->vel); } } - - /* now let's finalise the interpolated parents that we might have left half done before */ - if(itotparent) - finalize_path_length(keys); } void *exec_child_path_cache(void *data) @@ -2345,6 +2340,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda ParticleCacheKey *ca, **cache=psys->pathcache; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); ParticleEditSettings *pset = &G.scene->toolsettings->particle; + ParticleSettings *part = psys->part; ParticleData *pa; ParticleKey keys[4], result, *kkey[2] = {NULL, NULL}; @@ -2370,6 +2366,8 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda float nosel_col[3]; float length, vec[3]; float *vg_effector= NULL, effector=0.0f; + float *vg_length= NULL, pa_length=1.0f, max_length=1.0f, cur_length=0.0f; + float len, dvec[3]; /* we don't have anything valid to create paths from so let's quit here */ if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) @@ -2421,6 +2419,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(psys->part->from!=PART_FROM_PARTICLE) { if(!(psys->part->flag & PART_CHILD_EFFECT)) vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR); + + if(!edit && !psys->totchild) + vg_length = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_LENGTH); } /*---first main loop: create all actual particles' paths---*/ @@ -2434,6 +2435,12 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(editupdate && !(pa->flag & PARS_EDIT_RECALC)) continue; else memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); + if(!edit && !psys->totchild) { + pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]); + if(vg_length) + pa_length *= psys_interpolate_value_from_verts(psmd->dm,part->from,pa->num,pa->fuv,vg_length); + } + cache[i]->steps = steps; if(edit) @@ -2659,6 +2666,27 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda } + if(!edit && !psys->totchild) { + /* check if path needs to be cut before actual end of data points */ + if(k){ + VECSUB(dvec,ca->co,(ca-1)->co); + if(part->flag&PART_ABS_LENGTH) + len=VecLength(dvec); + else + len=1.0f/(float)steps; + + k=check_path_length(k,cache[i],ca,max_length,&cur_length,len,dvec); + } + else{ + /* initialize length calculation */ + if(part->flag&PART_ABS_LENGTH) + max_length= part->abslength*pa_length; + else + max_length= pa_length; + + cur_length= 0.0f; + } + } } } @@ -2671,6 +2699,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(vg_effector) MEM_freeN(vg_effector); + + if(vg_length) + MEM_freeN(vg_length); } /************************************************/ /* Particle Key handling */ @@ -3359,16 +3390,24 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float size, time; if(part->childtype==PART_CHILD_FACES){ - if(pa_time) - time=*pa_time; - else - time=psys_get_child_time(psys,cpa,cfra); + size=part->size; if((part->flag&PART_ABS_TIME)==0 && part->ipo){ + IpoCurve *icu; + + if(pa_time) + time=*pa_time; + else + time=psys_get_child_time(psys,cpa,cfra); + + /* correction for lifetime */ calc_ipo(part->ipo, 100*time); - execute_ipo((ID *)part, part->ipo); + + for(icu = part->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == PART_SIZE) + size = icu->curval; + } } - size=part->size; } else size=psys->particles[cpa->parent].size; @@ -3848,11 +3887,24 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys Mat4MulMat4(mat, obrotmat, qmat); } else { + /* make sure that we get a proper side vector */ + if(fabs(Inpf(nor,vec))>0.999999) { + if(fabs(Inpf(nor,xvec))>0.999999) { + nor[0] = 0.0f; + nor[1] = 1.0f; + nor[2] = 0.0f; + } + else { + nor[0] = 1.0f; + nor[1] = 0.0f; + nor[2] = 0.0f; + } + } Crossf(side, nor, vec); Normalize(side); Crossf(nor, vec, side); - Mat4One(mat); + Mat4One(mat); VECCOPY(mat[0], vec); VECCOPY(mat[1], side); VECCOPY(mat[2], nor); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index ef8373ee977..11e69262bbe 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -53,12 +53,14 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_kdtree.h" +#include "BLI_kdopbvh.h" #include "BLI_linklist.h" #include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" +#include "BKE_collision.h" #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_particle.h" @@ -76,6 +78,8 @@ #include "BKE_modifier.h" #include "BKE_scene.h" +#include "PIL_time.h" + #include "BSE_headerbuttons.h" #include "blendef.h" @@ -146,6 +150,14 @@ void psys_reset(ParticleSystem *psys, int mode) BLI_freelistN(&psys->reactevents); } } + else if(mode == PSYS_RESET_CACHE_MISS) { + /* set all particles to be skipped */ + ParticleData *pa = psys->particles; + int p=0; + + for(; ptotpart; p++, pa++) + pa->flag |= PARS_NO_DISP; + } /* reset children */ if(psys->child) { @@ -1116,12 +1128,14 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm if(children){ if(G.f & G_DEBUG) fprintf(stderr,"Particle child distribution error: Nothing to emit from!\n"); - for(p=0,cpa=psys->child; pfuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0; - cpa->foffset= 0.0f; - cpa->parent=0; - cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->num= -1; + if(psys->child) { + for(p=0,cpa=psys->child; pfuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0; + cpa->foffset= 0.0f; + cpa->parent=0; + cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; + cpa->num= -1; + } } } else { @@ -2096,22 +2110,18 @@ static void react_to_events(ParticleSystem *psys, int pa_num) for(re=psys->reactevents.first; re; re=re->next){ birth=0; if(part->from==PART_FROM_PARTICLE){ - if(pa->num==re->pa_num){ + if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ if(re->event==PART_EVENT_NEAR){ ParticleData *tpa = re->psys->particles+re->pa_num; float pa_time=tpa->time + pa->foffset*tpa->lifetime; - if(re->time > pa_time){ - pa->alive=PARS_ALIVE; + if(re->time >= pa_time){ pa->time=pa_time; pa->dietime=pa->time+pa->lifetime; } } else{ - if(pa->alive==PARS_UNBORN){ - pa->alive=PARS_ALIVE; - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - } + pa->time=re->time; + pa->dietime=pa->time+pa->lifetime; } } } @@ -2119,7 +2129,6 @@ static void react_to_events(ParticleSystem *psys, int pa_num) dist=VecLenf(pa->state.co, re->state.co); if(dist <= re->size){ if(pa->alive==PARS_UNBORN){ - pa->alive=PARS_ALIVE; pa->time=re->time; pa->dietime=pa->time+pa->lifetime; birth=1; @@ -2301,7 +2310,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy } } else if(pd->forcefield) + { type |= PSYS_EC_EFFECTOR; + } } if(pd && pd->deflect) @@ -2313,6 +2324,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy ec->type=type; ec->distances=0; ec->locations=0; + ec->rng = rng_new(1); + rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed + BLI_addtail(lb, ec); } @@ -2331,7 +2345,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy if((epsys->part->pd && epsys->part->pd->forcefield) || (epsys->part->pd2 && epsys->part->pd2->forcefield)) + { type=PSYS_EC_PARTICLE; + } if(epart->type==PART_REACTOR) { tob=epsys->target_ob; @@ -2346,6 +2362,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy ec->ob= ob; ec->type=type; ec->psys_nbr=i; + ec->rng = rng_new(1); + rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); + BLI_addtail(lb, ec); } } @@ -2395,6 +2414,9 @@ void psys_init_effectors(Object *obsrc, Group *group, ParticleSystem *psys) void psys_end_effectors(ParticleSystem *psys) { + /* NOTE: + ec->ob is not valid in here anymore! - dg + */ ListBase *lb=&psys->effectors; if(lb->first) { ParticleEffectorCache *ec; @@ -2413,13 +2435,17 @@ void psys_end_effectors(ParticleSystem *psys) if(ec->tree) BLI_kdtree_free(ec->tree); + + if(ec->rng) + rng_free(ec->rng); + } BLI_freelistN(lb); } } -static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -2459,96 +2485,20 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } - else if(ec->type==PSYS_EC_DEFLECT){ - DerivedMesh *dm; - MFace *mface=0; - MVert *mvert=0; - int i, totface; - float v1[3],v2[3],v3[3],v4[4], *min, *max; - - if(ob==ec->ob) - dm=psmd->dm; - else{ - psys_disable_all(ec->ob); - - dm=mesh_get_derived_final(ec->ob,0); - - psys_enable_all(ec->ob); - } - - if(dm){ - totvert=dm->getNumVerts(dm); - totface=dm->getNumFaces(dm); - mface=dm->getFaceDataArray(dm,CD_MFACE); - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* Decide which is faster to calculate by the amount of*/ - /* matrice multiplications needed to convert spaces. */ - /* With size deflect we have to convert allways because */ - /* the object can be scaled nonuniformly (sphere->ellipsoid). */ - if(totvert<2*psys->totpart || part->flag & PART_SIZE_DEFL){ - co=ec->vert_cos=MEM_callocN(sizeof(float)*3*totvert,"Particle deflection vert cos"); - /* convert vert coordinates to global (particle) coordinates */ - for(i=0; iob->obmat,co); - } - co=ec->vert_cos; - } - else - ec->vert_cos=0; - - INIT_MINMAX(ec->ob_minmax,ec->ob_minmax+3); - - min=ec->face_minmax=MEM_callocN(sizeof(float)*6*totface,"Particle deflection face minmax"); - max=min+3; - - for(i=0; iv1); - VECCOPY(v2,co+3*mface->v2); - VECCOPY(v3,co+3*mface->v3); - } - else{ - VECCOPY(v1,mvert[mface->v1].co); - VECCOPY(v2,mvert[mface->v2].co); - VECCOPY(v3,mvert[mface->v3].co); - } - INIT_MINMAX(min,max); - DO_MINMAX(v1,min,max); - DO_MINMAX(v2,min,max); - DO_MINMAX(v3,min,max); - - if(mface->v4){ - if(co){ - VECCOPY(v4,co+3*mface->v4); - } - else{ - VECCOPY(v4,mvert[mface->v4].co); - } - DO_MINMAX(v4,min,max); - } - - DO_MINMAX(min,ec->ob_minmax,ec->ob_minmax+3); - DO_MINMAX(max,ec->ob_minmax,ec->ob_minmax+3); - } - } - else - ec->face_minmax=0; - } else if(ec->type==PSYS_EC_PARTICLE){ + Object *eob = ec->ob; + ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); + ParticleSettings *epart = epsys->part; + ParticleData *epa = epsys->particles; + int totepart = epsys->totpart; + if(psys->part->phystype==PART_PHYS_BOIDS){ - Object *eob = ec->ob; - ParticleSystem *epsys; - ParticleSettings *epart; ParticleData *epa; ParticleKey state; PartDeflect *pd; - int totepart, p; - epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); - epart= epsys->part; + int p; + pd= epart->pd; - totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && totepart){ KDTree *tree; @@ -2563,6 +2513,11 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } + else if(ec->type==PSYS_EC_DEFLECT) { + CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); + if(collmd) + collision_move_object(collmd, 1.0, 0.0); + } } } @@ -2618,7 +2573,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P } else { do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance, falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, - pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,pd->rng,pd->f_noise,charge,pa->size); + pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } } if(ec->type & PSYS_EC_PARTICLE){ @@ -2662,10 +2617,10 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P else do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance, falloff,epart->size,pd->f_damp,estate.vel,vec_to_part, - state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size); + state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size); } } - else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ + else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ psys_get_particle_state(eob,epsys,p,&estate,1); VECADD(vel,vel,estate.vel); @@ -3011,37 +2966,124 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, } return intersect; } + +/* container for moving data between deflet_particle and particle_intersect_face */ +typedef struct ParticleCollision +{ + struct Object *ob, *ob_t; // collided and current objects + struct CollisionModifierData *md; // collision modifier for ob_t; + float nor[3]; // normal at collision point + float vel[3]; // velocity of collision point + float co1[3], co2[3]; // ray start and end points + float ray_len; // original length of co2-co1, needed for collision time evaluation + float t; // time of previous collision, needed for substracting face velocity +} +ParticleCollision; + +static void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + ParticleCollision *col = (ParticleCollision *) userdata; + MFace *face = col->md->mfaces + index; + MVert *x = col->md->x; + MVert *v = col->md->current_v; + float dir[3], vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], dist, t, threshold; + int ret=0; + + float *t0, *t1, *t2, *t3; + t0 = x[ face->v1 ].co; + t1 = x[ face->v2 ].co; + t2 = x[ face->v3 ].co; + t3 = face->v4 ? x[ face->v4].co : NULL; + + /* calculate average velocity of face */ + VECCOPY(vel, v[ face->v1 ].co); + VECADD(vel, vel, v[ face->v2 ].co); + VECADD(vel, vel, v[ face->v3 ].co); + VecMulf(vel, 0.33334f); + + /* substract face velocity, in other words convert to + a coordinate system where only the particle moves */ + VECADDFAC(co1, col->co1, vel, -col->t); + VECSUB(co2, col->co2, vel); + + do + { + if(ray->radius == 0.0f) { + if(LineIntersectsTriangle(co1, co2, t0, t1, t2, &t, uv)) { + if(t >= 0.0f && t < hit->dist/col->ray_len) { + hit->dist = col->ray_len * t; + hit->index = index; + + /* calculate normal that's facing the particle */ + CalcNormFloat(t0, t1, t2, col->nor); + VECSUB(temp, co2, co1); + if(Inpf(col->nor, temp) > 0.0f) + VecMulf(col->nor, -1.0f); + + VECCOPY(col->vel,vel); + + col->ob = col->ob_t; + } + } + } + else { + if(SweepingSphereIntersectsTriangleUV(co1, co2, ray->radius, t0, t1, t2, &t, ipoint)) { + if(t >=0.0f && t < hit->dist/col->ray_len) { + hit->dist = col->ray_len * t; + hit->index = index; + + VecLerpf(temp, co1, co2, t); + + VECSUB(col->nor, temp, ipoint); + Normalize(col->nor); + + VECCOPY(col->vel,vel); + + col->ob = col->ob_t; + } + } + } + + t1 = t2; + t2 = t3; + t3 = NULL; + + } while(t2); +} /* particle - mesh collision code */ /* in addition to basic point to surface collisions handles friction & damping,*/ /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float dfra, float cfra, ParticleKey *state, int *pa_die){ - Object *ob, *min_ob; - MFace *mface; - MVert *mvert; - DerivedMesh *dm; +static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){ + Object *ob; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; - ParticleKey cstate; - float imat[4][4]; - float co1[3],co2[3],def_loc[3],def_nor[3],unit_nor[3],def_tan[3],dvec[3],def_vel[3],dave[3],dvel[3]; - float pa_minmax[6]; - float min_w[4], zerovec[3]={0.0,0.0,0.0}, ipoint[3]; - float min_d,dotprod,damp,frict,o_len,d_len,radius=-1.0f; - int min_face=0, intersect=1, through=0; - short deflections=0, global=0; + ParticleKey reaction_state; + ParticleCollision col; + CollisionModifierData *collmd; + BVHTreeRayHit hit; + float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; + float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f); + int deflections=0, max_deflections=10; - VECCOPY(def_loc,pa->state.co); - VECCOPY(def_vel,pa->state.vel); + VECCOPY(col.co1, pa->state.co); + VECCOPY(col.co2, state->co); + col.t = 0.0f; /* 10 iterations to catch multiple deflections */ - if(lb->first) while(deflections<10){ - intersect=0; - global=0; - min_d=20000.0; - min_ob=NULL; + if(lb->first) while(deflections < max_deflections){ /* 1. */ + + VECSUB(ray_dir, col.co2, col.co1); + hit.index = -1; + hit.dist = col.ray_len = VecLength(ray_dir); + + /* even if particle is stationary we want to check for moving colliders */ + /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */ + if(hit.dist == 0.0f) + hit.dist = col.ray_len = 0.000001f; + for(ec=lb->first; ec; ec=ec->next){ if(ec->type & PSYS_EC_DEFLECT){ ob= ec->ob; @@ -3049,263 +3091,169 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part if(part->type!=PART_HAIR) where_is_object_time(ob,cfra); - if(ob==pob){ - dm=psmd->dm; - /* particles should not collide with emitter at birth */ - if(pa->time < cfra && pa->time >= psys->cfra) - continue; - } - else - dm=0; - - VECCOPY(co1,def_loc); - VECCOPY(co2,state->co); + /* particles should not collide with emitter at birth */ + if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) + continue; - if(ec->vert_cos==0){ - /* convert particle coordinates to object coordinates */ - Mat4Invert(imat,ob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - } + col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); + col.ob_t = ob; - INIT_MINMAX(pa_minmax,pa_minmax+3); - DO_MINMAX(co1,pa_minmax,pa_minmax+3); - DO_MINMAX(co2,pa_minmax,pa_minmax+3); - if(part->flag&PART_SIZE_DEFL){ - pa_minmax[0]-=pa->size; - pa_minmax[1]-=pa->size; - pa_minmax[2]-=pa->size; - pa_minmax[3]+=pa->size; - pa_minmax[4]+=pa->size; - pa_minmax[5]+=pa->size; - - radius=pa->size; - } - - if(ec->face_minmax==0 || AabbIntersectAabb(pa_minmax,pa_minmax+3,ec->ob_minmax,ec->ob_minmax+3)) { - if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w, - ec->face_minmax,pa_minmax,radius,ipoint)){ - - min_ob=ob; - - if(ec->vert_cos) - global=1; - else - global=0; - } - } + if(col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); } } /* 2. */ - if(min_ob){ - BLI_srandom((int)cfra+p); - ob=min_ob; + if(hit.index>=0) { + PartDeflect *pd = col.ob->pd; + int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; + float co[3]; /* point of collision */ + float vec[3]; /* movement through collision */ + float vel[3]; /* velocity after collision */ + float t = hit.dist/col.ray_len; /* time of collision between this iteration */ + float dt = col.t + t * (1.0f - col.t); /* time of collision between frame change*/ - if(ob==pob){ - dm=psmd->dm; - } - else{ - psys_disable_all(ob); + VecLerpf(co, col.co1, col.co2, t); + VECSUB(vec, col.co2, col.co1); - dm=mesh_get_derived_final(ob,0); + VecMulf(col.vel, 1.0f-col.t); - psys_enable_all(ob); - } + /* particle dies in collision */ + if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) { + pa->alive = PARS_DYING; + pa->dietime = pa->state.time + (cfra - pa->state.time) * dt; + + /* we have to add this for dying particles too so that reactors work correctly */ + VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - mface=dm->getFaceDataArray(dm,CD_MFACE); - mface+=min_face; - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* permeability check */ - if(BLI_frand()pd->pdef_perm) - through=1; - else - through=0; - - if(through==0 && (part->flag & PART_DIE_ON_COL || ob->pd->flag & PDEFLE_KILL_PART)){ - pa->dietime = cfra-(1.0f-min_d)*dfra; - VecLerpf(def_loc,def_loc,state->co,min_d); - - VECCOPY(state->co,def_loc); - VecLerpf(state->vel,pa->state.vel,state->vel,min_d); - QuatInterpol(state->rot,pa->state.rot,state->rot,min_d); - VecLerpf(state->ave,pa->state.ave,state->ave,min_d); - - *pa_die=1; + VECCOPY(state->co, co); + VecLerpf(state->vel, pa->state.vel, state->vel, dt); + QuatInterpol(state->rot, pa->state.rot, state->rot, dt); + VecLerpf(state->ave, pa->state.ave, state->ave, dt); /* particle is dead so we don't need to calculate further */ - deflections=10; + deflections=max_deflections; /* store for reactors */ - copy_particle_key(&cstate,state,0); + copy_particle_key(&reaction_state,state,0); if(part->flag & PART_STICKY){ pa->stick_ob=ob; pa->flag |= PARS_STICKY; } } - else{ - VECCOPY(co1,def_loc); - VECCOPY(co2,state->co); - - if(global==0){ - /* convert particle coordinates to object coordinates */ - Mat4Invert(imat,ob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - } - - VecLerpf(def_loc,co1,co2,min_d); - - if(radius>0.0f){ - VECSUB(unit_nor,def_loc,ipoint); - } - else{ - /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,0,min_w,ipoint,unit_nor,0,0,0,0); - if(global){ - Mat4Mul3Vecfl(ob->obmat,unit_nor); - Mat4MulVecfl(ob->obmat,ipoint); - } - } - - Normalize(unit_nor); - - VECSUB(dvec,co1,co2); - /* scale to remaining length after deflection */ - VecMulf(dvec,1.0f-min_d); - - /* flip normal to face particle */ - if(Inpf(unit_nor,dvec)<0.0f) - VecMulf(unit_nor,-1.0f); - - /* store for easy velocity calculation */ - o_len=VecLength(dvec); - - /* project particle movement to normal & create tangent */ - dotprod=Inpf(dvec,unit_nor); - VECCOPY(def_nor,unit_nor); - VecMulf(def_nor,dotprod); - VECSUB(def_tan,def_nor,dvec); - - damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); - - /* create location after deflection */ - VECCOPY(dvec,def_nor); - damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); + else { + float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; + float damp, frict; + float inp, inp_v; + + /* get damping & friction factors */ + damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); CLAMP(damp,0.0,1.0); - VecMulf(dvec,1.0f-damp); - if(through) - VecMulf(dvec,-1.0); - - frict=ob->pd->pdef_frict+ob->pd->pdef_rfrict*2.0f*(BLI_frand()-0.5f); + + frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f); CLAMP(frict,0.0,1.0); - VECADDFAC(dvec,dvec,def_tan,1.0f-frict); - /* store for easy velocity calculation */ - d_len=VecLength(dvec); + /* treat normal & tangent components separately */ + inp = Inpf(col.nor, vec); + inp_v = Inpf(col.nor, col.vel); - /* just to be sure we don't hit the current face again */ - if(through){ - VECADDFAC(ipoint,ipoint,unit_nor,-0.0001f); - VECADDFAC(def_loc,def_loc,unit_nor,-0.0001f); + VECADDFAC(tan_vec, vec, col.nor, -inp); + VECADDFAC(tan_vel, col.vel, col.nor, -inp_v); + if((part->flag & PART_ROT_DYN)==0) + VecLerpf(tan_vec, tan_vec, tan_vel, frict); - if(part->flag & PART_ROT_DYN){ - VECADDFAC(def_tan,def_tan,unit_nor,-0.0001f); - VECADDFAC(def_nor,def_nor,unit_nor,-0.0001f); - } - } - else{ - VECADDFAC(ipoint,ipoint,unit_nor,0.0001f); - VECADDFAC(def_loc,def_loc,unit_nor,0.0001f); + VECCOPY(nor_vec, col.nor); + inp *= 1.0f - damp; - if(part->flag & PART_ROT_DYN){ - VECADDFAC(def_tan,def_tan,unit_nor,0.0001f); - VECADDFAC(def_nor,def_nor,unit_nor,0.0001f); - } + if(through) + inp_v *= damp; + + /* special case for object hitting the particle from behind */ + if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v linear velocity - slightly more physical and looks even nicer than before */ + if(part->flag & PART_ROT_DYN) { + float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3]; + + /* apparent velocity along collision surface */ + VECSUB(surface_vel, tan_vec, tan_vel); + + /* direction of rolling friction */ + Crossf(rot_vel, state->ave, col.nor); + /* convert to current dt */ + VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t)); + VecMulf(rot_vel, pa->size); + + /* apply sliding friction */ + VECSUB(surface_vel, surface_vel, rot_vel); + VECCOPY(friction, surface_vel); + + VecMulf(surface_vel, 1.0 - frict); + VecMulf(friction, frict); + + /* sliding changes angular velocity */ + Crossf(dave, col.nor, friction); + VecMulf(dave, 1.0f/MAX2(pa->size, 0.001)); + + /* we assume rolling friction is around 0.01 of sliding friction */ + VecMulf(rot_vel, 1.0 - frict*0.01); + + /* change in angular velocity has to be added to the linear velocity too */ + Crossf(dvel, dave, col.nor); + VecMulf(dvel, pa->size); + VECADD(rot_vel, rot_vel, dvel); + + VECADD(surface_vel, surface_vel, rot_vel); + VECADD(tan_vec, surface_vel, tan_vel); + + /* convert back to normal time */ + VecMulf(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); + + VecMulf(state->ave, 1.0 - frict*0.01); + VECADD(state->ave, state->ave, dave); } - /* lets get back to global space */ - if(global==0){ - Mat4Mul3Vecfl(ob->obmat,dvec); - Mat4MulVecfl(ob->obmat,ipoint); - Mat4MulVecfl(ob->obmat,def_loc);/* def_loc remains as intersection point for next iteration */ - } + /* combine components together again */ + VECADD(vec, nor_vec, tan_vec); - /* store for reactors */ - VECCOPY(cstate.co,ipoint); - VecLerpf(cstate.vel,pa->state.vel,state->vel,min_d); - QuatInterpol(cstate.rot,pa->state.rot,state->rot,min_d); + /* calculate velocity from collision vector */ + VECCOPY(vel, vec); + VecMulf(vel, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - /* slightly unphysical but looks nice enough */ - if(part->flag & PART_ROT_DYN){ - if(global==0){ - Mat4Mul3Vecfl(ob->obmat,def_nor); - Mat4Mul3Vecfl(ob->obmat,def_tan); - } + /* make sure we don't hit the current face again */ + VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - Normalize(def_tan); - Normalize(def_nor); - VECCOPY(unit_nor,def_nor); + /* store state for reactors */ + VECCOPY(reaction_state.co, co); + VecLerpf(reaction_state.vel, pa->state.vel, state->vel, dt); + QuatInterpol(reaction_state.rot, pa->state.rot, state->rot, dt); - /* create normal velocity */ - VecMulf(def_nor,Inpf(pa->state.vel,def_nor)); + /* set coordinates for next iteration */ + VECCOPY(col.co1, co); + VECADDFAC(col.co2, co, vec, 1.0f - t); + col.t = dt; - /* create tangential velocity */ - VecMulf(def_tan,Inpf(pa->state.vel,def_tan)); - - /* angular velocity change due to tangential velocity */ - Crossf(dave,unit_nor,def_tan); - VecMulf(dave,1.0f/pa->size); - - /* linear velocity change due to angular velocity */ - VecMulf(unit_nor,pa->size); /* point of impact from particle center */ - Crossf(dvel,pa->state.ave,unit_nor); - - if(through) - VecMulf(def_nor,-1.0); - - VecMulf(def_nor,1.0f-damp); - VECSUB(dvel,dvel,def_nor); - - VecMulf(dvel,1.0f-frict); - VecMulf(dave,1.0f-frict); - } - - if(d_len<0.001 && VecLength(pa->state.vel)<0.001){ + if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) { /* kill speed to stop slipping */ VECCOPY(state->vel,zerovec); - VECCOPY(state->co,def_loc); - if(part->flag & PART_ROT_DYN) + VECCOPY(state->co, co); + if(part->flag & PART_ROT_DYN) { VECCOPY(state->ave,zerovec); - deflections=10; - } - else{ - - /* apply new coordinates */ - VECADD(state->co,def_loc,dvec); - - Normalize(dvec); - - /* we have to use original velocity because otherwise we get slipping */ - /* when forces like gravity balance out damping & friction */ - VecMulf(dvec,VecLength(pa->state.vel)*(d_len/o_len)); - VECCOPY(state->vel,dvec); - - if(part->flag & PART_ROT_DYN){ - VECADD(state->vel,state->vel,dvel); - VecMulf(state->vel,0.5); - VECADD(state->ave,state->ave,dave); - VecMulf(state->ave,0.5); } } + else { + VECCOPY(state->co, col.co2); + VECCOPY(state->vel, vel); + } } deflections++; - cstate.time=cfra-(1.0f-min_d)*dfra; - //particle_react_to_collision(min_ob,pob,psys,pa,p,&cstate); - push_reaction(pob,psys,p,PART_EVENT_COLLIDE,&cstate); + reaction_state.time = cfra - (1.0f - dt) * dfra; + push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); } else return; @@ -3469,7 +3417,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l } } /* determines the acceleration that the boid tries to acchieve */ -static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc, int *pa_die) +static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc) { ParticleData *pars=psys->particles; KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1]; @@ -3536,7 +3484,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS distance=Normalize(dvec); if(part->flag & PART_DIE_ON_COL && distance < pd->mindist){ - *pa_die=1; + pa->alive = PARS_DYING; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3565,7 +3513,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){ + if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0 && ec->tree){ count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); for(p=0; pflag & PART_DIE_ON_COL && distance < (epsys->particles+ptn2[p].index)->size){ - *pa_die=1; + pa->alive = PARS_DYING; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3712,7 +3660,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){ + if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0 && ec->tree){ count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); for(p=0; pvel[2]=0.0; state->co[2]=part->groundz; - if(psys->keyed_ob){ + if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ Object *zob=psys->keyed_ob; int min_face; float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; @@ -3984,7 +3932,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); Material *ma=give_current_material(ob,part->omat); float timestep; - int p, totpart, pa_die; + int p, totpart; /* current time */ float ctime, ipotime; /* frame & time changes */ @@ -4064,7 +4012,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); if(part->phystype==PART_PHYS_BOIDS){ /* create particle tree for fast inter-particle comparisons */ @@ -4093,15 +4041,13 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); - pa_die=0; - birthtime = pa->time + pa->loop * pa->lifetime; + /* allways reset particles to emitter before birth */ if(pa->alive==PARS_UNBORN || pa->alive==PARS_KILLED || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ - /* allways reset particles to emitter before birth */ reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); copy_particle_key(key,&pa->state,1); } @@ -4114,9 +4060,11 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi pa_dfra = dfra; pa_dtime = dtime; + /* we need to calculate this once again because reactions might have changed pa->time */ + birthtime = pa->time + pa->loop * pa->lifetime; dietime = birthtime + pa->lifetime; - if(birthtime < cfra && birthtime >= psys->cfra){ + if(birthtime <= cfra && birthtime >= psys->cfra){ /* particle is born some time between this and last step*/ pa->alive = PARS_ALIVE; pa_dfra = cfra - birthtime; @@ -4126,40 +4074,37 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi /* particle dies some time between this and last step */ pa_dfra = dietime - psys->cfra; pa_dtime = pa_dfra * timestep; - pa_die = 1; + pa->alive = PARS_DYING; } else if(dietime < cfra){ - /* TODO: figure out if there's something to be done when particle is dead */ + /* nothing to be done when particle is dead */ } copy_particle_key(key,&pa->state,1); - if(dfra>0.0 && pa->alive==PARS_ALIVE){ + if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra,key); - + /* deflection */ - deflect_particle(ob,psmd,psys,part,pa,p,pa_dfra,cfra,key,&pa_die); + deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key); /* rotations */ rotate_particle(part,pa,pa_dfra,timestep,key); - break; case PART_PHYS_BOIDS: { float acc[3]; - boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc,&pa_die); - if(pa_die==0) + boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); + if(pa->alive != PARS_DYING) boid_body(&bvf,pa,psys,part,timestep,acc,key); break; } } - push_reaction(ob,psys,p,PART_EVENT_NEAR,key); - - if(pa_die){ + if(pa->alive == PARS_DYING){ push_reaction(ob,psys,p,PART_EVENT_DEATH,key); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ @@ -4178,9 +4123,12 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } else key->time=cfra; + + push_reaction(ob,psys,p,PART_EVENT_NEAR,key); } } } + /* apply outstates to particles */ for(p=0, pa=psys->particles, key=outstate; pstate,key,1); @@ -4260,7 +4208,7 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); if(psys_in_edit_mode(psys)) PE_recalc_world_cos(ob, psys); @@ -4288,7 +4236,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); //} disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; @@ -4542,7 +4490,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(usecache) { /* frame clamping */ if(framenr < startframe) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra = cfra; psys->recalc = 0; return; @@ -4622,14 +4570,14 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier return; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; return; } if(framenr != startframe && framedelta != 1) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra = cfra; psys->recalc = 0; return; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 553107dd264..701e8ecb311 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -350,7 +350,7 @@ void set_scene_bg(Scene *sce) /* no full animation update, this to enable render code to work (render code calls own animation updates) */ /* do we need FRAMECHANGED in set_scene? */ -// if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED); +// if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED, 0); } /* called from creator.c */ @@ -570,8 +570,8 @@ void scene_update_for_newframe(Scene *sce, unsigned int lay) /* object ipos are calculated in where_is_object */ do_all_data_ipos(); - if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED); - + if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED, 0); + /* sets first, we allow per definition current scene to have dependencies on sets */ for(sce= sce->set; sce; sce= sce->set) scene_update(sce, lay); diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 050cca15721..931519a1b4a 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -113,23 +113,23 @@ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float void space_transform_apply(const SpaceTransform *data, float *co) { - VecMat4MulVecfl(co, data->local2target, co); + VecMat4MulVecfl(co, ((SpaceTransform*)data)->local2target, co); } void space_transform_invert(const SpaceTransform *data, float *co) { - VecMat4MulVecfl(co, data->target2local, co); + VecMat4MulVecfl(co, ((SpaceTransform*)data)->target2local, co); } void space_transform_apply_normal(const SpaceTransform *data, float *no) { - Mat4Mul3Vecfl(data->local2target, no); + Mat4Mul3Vecfl( ((SpaceTransform*)data)->local2target, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } void space_transform_invert_normal(const SpaceTransform *data, float *no) { - Mat4Mul3Vecfl(data->target2local, no); + Mat4Mul3Vecfl(((SpaceTransform*)data)->target2local, no); Normalize(no); // TODO: could we just determine de scale value from the matrix? } @@ -335,7 +335,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa space_transform_apply_normal( transf, tmp_no ); no = tmp_no; - hit_tmp.dist *= Mat4ToScalef( transf->local2target ); + hit_tmp.dist *= Mat4ToScalef( ((SpaceTransform*)transf)->local2target ); } else { @@ -345,7 +345,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa hit_tmp.index = -1; - BLI_bvhtree_ray_cast(tree, co, no, &hit_tmp, callback, userdata); + BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); if(hit_tmp.index != -1) { @@ -362,7 +362,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa space_transform_invert( transf, hit_tmp.co ); space_transform_invert_normal( transf, hit_tmp.no ); - hit_tmp.dist = VecLenf( vert, hit_tmp.co ); + hit_tmp.dist = VecLenf( (float*)vert, hit_tmp.co ); } memcpy(hit, &hit_tmp, sizeof(hit_tmp) ); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index d465c058d30..508b2233536 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1622,23 +1622,23 @@ void *exec_scan_for_ext_spring_forces(void *data) void sb_sfesf_threads_run(struct Object *ob, float timenow,int totsprings,int *ptr_to_break_func()) { - ListBase *do_effector = NULL; + ListBase *do_effector = NULL; ListBase threads; SB_thread_context *sb_threads; int i, totthread,left,dec; - int lowsprings =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ + int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ do_effector= pdInitEffectors(ob,NULL); /* figure the number of threads while preventing pretty pointless threading overhead */ - if(totsprings < lowsprings) {totthread=1;} - else{ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; - else - totthread= BLI_system_thread_count(); + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); + /* what if we got zillions of CPUs running but less to spread*/ + while ((totsprings/totthread < lowsprings) && (totthread > 1)) { + totthread--; } - /*left to do--> what if we got zillions of CPUs running but 'totsprings' tasks to spread*/ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBSpringsThread"); memset(sb_threads, 0, sizeof(SB_thread_context)*totthread); @@ -2279,6 +2279,11 @@ int _softbody_calc_forces_slice_in_a_thread(Object *ob, float forcetime, float t float kd = 1.0f; if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ + if (intrusion < 0.0f){ + sb->scratch->flag |= SBF_DOFUZZY; + bp->flag |= SBF_DOFUZZY; + bp->choke = sb->choke*0.01f; + } VECSUB(cfforce,bp->vec,vel); Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); @@ -2326,17 +2331,19 @@ void sb_cf_threads_run(struct Object *ob, float forcetime, float timenow,int tot ListBase threads; SB_thread_context *sb_threads; int i, totthread,left,dec; - int lowpoints =10; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ + int lowpoints =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ /* figure the number of threads while preventing pretty pointless threading overhead */ - if(totpoint < lowpoints) {totthread=1;} - else{ - if(G.scene->r.mode & R_FIXED_THREADS) - totthread= G.scene->r.threads; - else - totthread= BLI_system_thread_count(); + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); + /* what if we got zillions of CPUs running but less to spread*/ + while ((totpoint/totthread < lowpoints) && (totthread > 1)) { + totthread--; } - /*left to do--> what if we got zillions of CPUs running but 'totpoint' tasks to spread*/ + + /* printf("sb_cf_threads_run spawning %d threads \n",totthread); */ sb_threads= MEM_callocN(sizeof(SB_thread_context)*totthread, "SBThread"); memset(sb_threads, 0, sizeof(SB_thread_context)*totthread); @@ -2425,7 +2432,7 @@ static void softbody_calc_forcesEx(Object *ob, float forcetime, float timenow, i static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int nl_flags) { /* redirection to the new threaded Version */ - if (G.rt !=16){ + if (!(G.rt & 0x10)){ // 16 softbody_calc_forcesEx(ob, forcetime, timenow, nl_flags); return; } @@ -2433,6 +2440,10 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int /* so the following will die */ /* |||||||||||||||||||||||||| */ /* VVVVVVVVVVVVVVVVVVVVVVVVVV */ + /*backward compatibility note: + fixing bug [17428] which forces adaptive step size to tiny steps + in some situations + .. keeping G.rt==17 0x11 option for old files 'needing' the bug*/ /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2681,14 +2692,25 @@ static void softbody_calc_forces(Object *ob, float forcetime, float timenow, int if (sb_deflect_face(ob,bp->pos,facenormal,defforce,&cf,timenow,vel,&intrusion)){ if ((!nl_flags)&&(intrusion < 0.0f)){ - /*bjornmose: uugh.. what an evil hack - violation of the 'don't touch bp->pos in here' rule - but works nice, like this--> - we predict the solution beeing out of the collider - in heun step No1 and leave the heun step No2 adapt to it - so we kind of introduced a implicit solver for this case - */ - Vec3PlusStVec(bp->pos,-intrusion,facenormal); + if(G.rt & 0x01){ // 17 we did check for bit 0x10 before + /*fixing bug [17428] this forces adaptive step size to tiny steps + in some situations .. keeping G.rt==17 option for old files 'needing' the bug + */ + /*bjornmose: uugh.. what an evil hack + violation of the 'don't touch bp->pos in here' rule + but works nice, like this--> + we predict the solution beeing out of the collider + in heun step No1 and leave the heun step No2 adapt to it + so we kind of introduced a implicit solver for this case + */ + Vec3PlusStVec(bp->pos,-intrusion,facenormal); + } + else{ + + VECSUB(cfforce,bp->vec,vel); + Vec3PlusStVec(bp->force,-cf*50.0f,cfforce); + } + sb->scratch->flag |= SBF_DOFUZZY; bp->flag |= SBF_DOFUZZY; @@ -4040,7 +4062,7 @@ static void softbody_step(Object *ob, SoftBody *sb, float dtime) if(sb->solverflags & SBSO_MONITOR ){ sct=PIL_check_seconds_timer(); - if (sct-sst > 0.5f) printf(" solver time %f sec %s \n",sct-sst,ob->id.name); + if ((sct-sst > 0.5f) || (G.f & G_DEBUG)) printf(" solver time %f sec %s \n",sct-sst,ob->id.name); } } diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index bba79bd6d28..e6797186b53 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -61,6 +61,10 @@ #include "BIF_gl.h" +#include "GPU_draw.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + #include "CCGSubSurf.h" typedef struct _VertData { @@ -696,6 +700,7 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, for(index = 0; index < totedge; index++) { CCGEdge *e = edgeMap2[index]; unsigned int flags = 0; + char bweight = 0; int edgeIdx = GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(ss, e)); if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE; @@ -706,12 +711,14 @@ DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh, dm->getEdge(dm, edgeIdx, &origMed); flags |= origMed.flag; + bweight = origMed.bweight; } for(x = 0; x < edgeSize - 1; x++) { med->v1 = getEdgeIndex(ss, e, x, edgeSize); med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize); med->flag = flags; + med->bweight = bweight; *origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e); ++med; ++origIndex; @@ -973,7 +980,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) memset(mv, 0, sizeof(*mv)); - if(vertNum < ccgdm->edgeMap[0].startVert) { + if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { /* this vert comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -1014,7 +1021,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) x = offset % gridSideVerts + 1; VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y)); } - } else if(vertNum < ccgdm->vertMap[0].startVert) { + } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) { /* this vert comes from edge data */ CCGEdge *e; int lastedge = ccgSubSurf_getNumEdges(ss) - 1; @@ -1599,7 +1606,7 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) } /* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { +static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *attribs)) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); @@ -1621,7 +1628,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { mat_nr= 0; } - if (!setMaterial(mat_nr+1)) + if (!setMaterial(mat_nr+1, NULL)) continue; glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); @@ -1666,6 +1673,168 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int)) { ccgFaceIterator_free(fi); } + + /* Only used by non-editmesh types */ +static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, void *attribs), int (*setDrawOptions)(void *userData, int index), void *userData) { + CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; + CCGSubSurf *ss = ccgdm->ss; + CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss); + GPUVertexAttribs gattribs; + DMVertexAttribs attribs; + MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); + int gridSize = ccgSubSurf_getGridSize(ss); + int gridFaces = gridSize - 1; + int edgeSize = ccgSubSurf_getEdgeSize(ss); + int transp, orig_transp, new_transp; + char *faceFlags = DM_get_face_data_layer(dm, CD_FLAGS); + int a, b, i, doDraw, numVerts, matnr, new_matnr, totface; + + doDraw = 0; + numVerts = 0; + matnr = -1; + transp = GPU_get_material_blend_mode(); + orig_transp = transp; + + memset(&attribs, 0, sizeof(attribs)); + +#define PASSATTRIB(dx, dy, vert) { \ + if(attribs.totorco) { \ + index = getFaceIndex(ss, f, S, x+dx, y+dy, edgeSize, gridSize); \ + glVertexAttrib3fvARB(attribs.orco.glIndex, attribs.orco.array[index]); \ + } \ + for(b = 0; b < attribs.tottface; b++) { \ + MTFace *tf = &attribs.tface[b].array[a]; \ + glVertexAttrib2fvARB(attribs.tface[b].glIndex, tf->uv[vert]); \ + } \ + for(b = 0; b < attribs.totmcol; b++) { \ + MCol *cp = &attribs.mcol[b].array[a*4 + vert]; \ + GLubyte col[4]; \ + col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a; \ + glVertexAttrib4ubvARB(attribs.mcol[b].glIndex, col); \ + } \ + if(attribs.tottang) { \ + float *tang = attribs.tang.array[a*4 + vert]; \ + glVertexAttrib3fvARB(attribs.tang.glIndex, tang); \ + } \ +} + + totface = ccgSubSurf_getNumFaces(ss); + for(a = 0, i = 0; i < totface; i++) { + CCGFace *f = ccgdm->faceMap[i].face; + int S, x, y, drawSmooth; + int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(ss, f)); + int origIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f); + + numVerts = ccgSubSurf_getFaceNumVerts(ss, f); + + if(faceFlags) { + drawSmooth = (faceFlags[index*4] & ME_SMOOTH); + new_matnr= faceFlags[index*4 + 1] + 1; + } + else { + drawSmooth = 1; + new_matnr= 1; + } + + if(new_matnr != matnr) { + doDraw = setMaterial(matnr = new_matnr, &gattribs); + if(doDraw) + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + } + + if(!doDraw || (setDrawOptions && !setDrawOptions(userData, origIndex))) { + a += gridFaces*gridFaces*numVerts; + continue; + } + + if(tf) { + new_transp = tf[i].transp; + + if(new_transp != transp) { + if(new_transp == GPU_BLEND_SOLID && orig_transp != GPU_BLEND_SOLID) + GPU_set_material_blend_mode(orig_transp); + else + GPU_set_material_blend_mode(new_transp); + transp = new_transp; + } + } + + glShadeModel(drawSmooth? GL_SMOOTH: GL_FLAT); + for (S=0; Sno); + glVertex3fv(vda->co); + + PASSATTRIB(0, 1, 1); + glNormal3fv(vdb->no); + glVertex3fv(vdb->co); + + if(x != gridFaces-1) + a++; + } + + vda = &faceGridData[(y+0)*gridSize + x]; + vdb = &faceGridData[(y+1)*gridSize + x]; + + PASSATTRIB(0, 0, 3); + glNormal3fv(vda->no); + glVertex3fv(vda->co); + + PASSATTRIB(0, 1, 2); + glNormal3fv(vdb->no); + glVertex3fv(vdb->co); + + glEnd(); + + a++; + } + } else { + glBegin(GL_QUADS); + for (y=0; ydrawMappedFacesGLSL(dm, setMaterial, NULL, NULL); +} + static void ccgDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm; CCGSubSurf *ss = ccgdm->ss; @@ -2143,8 +2312,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid; ccgdm->dm.drawFacesColored = ccgDM_drawFacesColored; ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex; + ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL; ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; + ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL; ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; diff --git a/source/blender/blenkernel/intern/suggestions.c b/source/blender/blenkernel/intern/suggestions.c new file mode 100644 index 00000000000..6530909336c --- /dev/null +++ b/source/blender/blenkernel/intern/suggestions.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) 2008, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Ian Thompson. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "DNA_text_types.h" +#include "BKE_text.h" +#include "BKE_suggestions.h" + +/**********************/ +/* Static definitions */ +/**********************/ + +static Text *activeToolText = NULL; +static SuggList suggestions = {NULL, NULL, NULL, NULL, NULL}; +static char *documentation = NULL; +//static int doc_lines = 0; + +static int txttl_cmp(const char *first, const char *second, int len) { + int cmp, i; + for (cmp=0, i=0; iprev; + MEM_freeN(item); + } + suggestions.first = suggestions.last = NULL; + suggestions.firstmatch = suggestions.lastmatch = NULL; + suggestions.selected = NULL; + suggestions.top = 0; +} + +static void txttl_free_docs() { + if (documentation) { + MEM_freeN(documentation); + documentation = NULL; + } +} + +/**************************/ +/* General tool functions */ +/**************************/ + +void free_texttools() { + txttl_free_suggest(); + txttl_free_docs(); +} + +void texttool_text_set_active(Text *text) { + if (activeToolText == text) return; + texttool_text_clear(); + activeToolText = text; +} + +void texttool_text_clear() { + free_texttools(); + activeToolText = NULL; +} + +short texttool_text_is_active(Text *text) { + return activeToolText==text ? 1 : 0; +} + +/***************************/ +/* Suggestion list methods */ +/***************************/ + +void texttool_suggest_add(const char *name, char type) { + SuggItem *newitem, *item; + int len, cmp; + + newitem = MEM_mallocN(sizeof(SuggItem) + strlen(name) + 1, "SuggestionItem"); + if (!newitem) { + printf("Failed to allocate memory for suggestion.\n"); + return; + } + + newitem->name = (char *) (newitem + 1); + len = strlen(name); + strncpy(newitem->name, name, len); + newitem->name[len] = '\0'; + newitem->type = type; + newitem->prev = newitem->next = NULL; + + /* Perform simple linear search for ordered storage */ + if (!suggestions.first || !suggestions.last) { + suggestions.first = suggestions.last = newitem; + } else { + cmp = -1; + for (item=suggestions.last; item; item=item->prev) { + cmp = txttl_cmp(name, item->name, len); + + /* Newitem comes after this item, insert here */ + if (cmp >= 0) { + newitem->prev = item; + if (item->next) + item->next->prev = newitem; + newitem->next = item->next; + item->next = newitem; + + /* At last item, set last pointer here */ + if (item == suggestions.last) + suggestions.last = newitem; + break; + } + } + /* Reached beginning of list, insert before first */ + if (cmp < 0) { + newitem->next = suggestions.first; + suggestions.first->prev = newitem; + suggestions.first = newitem; + } + } + suggestions.firstmatch = suggestions.lastmatch = suggestions.selected = NULL; + suggestions.top= 0; +} + +void texttool_suggest_prefix(const char *prefix) { + SuggItem *match, *first, *last; + int cmp, len = strlen(prefix), top = 0; + + if (!suggestions.first) return; + if (len==0) { + suggestions.selected = suggestions.firstmatch = suggestions.first; + suggestions.lastmatch = suggestions.last; + return; + } + + first = last = NULL; + for (match=suggestions.first; match; match=match->next) { + cmp = txttl_cmp(prefix, match->name, len); + if (cmp==0) { + if (!first) { + first = match; + suggestions.top = top; + } + } else if (cmp<0) { + if (!last) { + last = match->prev; + break; + } + } + top++; + } + if (first) { + if (!last) last = suggestions.last; + suggestions.firstmatch = first; + suggestions.lastmatch = last; + suggestions.selected = first; + } else { + suggestions.firstmatch = NULL; + suggestions.lastmatch = NULL; + suggestions.selected = NULL; + suggestions.top = 0; + } +} + +void texttool_suggest_clear() { + txttl_free_suggest(); +} + +SuggItem *texttool_suggest_first() { + return suggestions.firstmatch; +} + +SuggItem *texttool_suggest_last() { + return suggestions.lastmatch; +} + +void texttool_suggest_select(SuggItem *sel) { + suggestions.selected = sel; +} + +SuggItem *texttool_suggest_selected() { + return suggestions.selected; +} + +int *texttool_suggest_top() { + return &suggestions.top; +} + +/*************************/ +/* Documentation methods */ +/*************************/ + +void texttool_docs_show(const char *docs) { + int len; + + if (!docs) return; + + len = strlen(docs); + + if (documentation) { + MEM_freeN(documentation); + documentation = NULL; + } + + /* Ensure documentation ends with a '\n' */ + if (docs[len-1] != '\n') { + documentation = MEM_mallocN(len+2, "Documentation"); + strncpy(documentation, docs, len); + documentation[len++] = '\n'; + } else { + documentation = MEM_mallocN(len+1, "Documentation"); + strncpy(documentation, docs, len); + } + documentation[len] = '\0'; +} + +char *texttool_docs_get() { + return documentation; +} + +void texttool_docs_clear() { + txttl_free_docs(); +} diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 53b7bb975a3..5f1a1e63da4 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -30,6 +30,8 @@ */ #include /* strstr */ +#include +#include #include "MEM_guardedalloc.h" @@ -81,12 +83,19 @@ The st->top determines at what line the top of the text is displayed. If the user moves the cursor the st containing that cursor should be popped ... other st's retain their own top location. -*/ /***************/ +Markers +-- +The mrk->flags define the behaviour and relationships between markers. The +upper two bytes are used to hold a group ID, the lower two are normal flags. If +TMARK_EDITALL is set the group ID defines which other markers should be edited. +The mrk->clr field is used to visually group markers where the flags may not +match. A template system, for example, may allow editing of repeating tokens +(in one group) but include other marked positions (in another group) all in the +same template with the same colour. -/****************/ /* - Undo - +Undo +-- Undo/Redo works by storing events in a queue, and a pointer to the current position in the @@ -145,6 +154,7 @@ void free_text(Text *text) } BLI_freelistN(&text->lines); + BLI_freelistN(&text->markers); if(text->name) MEM_freeN(text->name); MEM_freeN(text->undo_buf); @@ -169,10 +179,11 @@ Text *add_empty_text(char *name) ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM; ta->lines.first= ta->lines.last= NULL; + ta->markers.first= ta->markers.last= NULL; tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(1, "textline_string"); - tmp->format= (char*) MEM_mallocN(2, "Syntax_format"); + tmp->format= NULL; tmp->line[0]=0; tmp->len= 0; @@ -209,11 +220,12 @@ static void cleanup_textline(TextLine * tl) int reopen_text(Text *text) { FILE *fp; - int i, llen, len; + int i, llen, len, res; unsigned char *buffer; TextLine *tmp; char sfile[FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE]; + struct stat st; if (!text || !text->name) return 0; @@ -242,7 +254,7 @@ int reopen_text(Text *text) text->undo_len= TXT_INIT_UNDO; text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); - text->flags= TXT_ISDIRTY | TXT_ISTMP; + text->flags= TXT_ISTMP; fseek(fp, 0L, SEEK_END); len= ftell(fp); @@ -256,6 +268,9 @@ int reopen_text(Text *text) len = fread(buffer, 1, len, fp); fclose(fp); + + res= stat(str, &st); + text->mtime= st.st_mtime; text->nlines=0; i=0; @@ -264,7 +279,7 @@ int reopen_text(Text *text) if (buffer[i]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); tmp->line[llen]=0; @@ -284,7 +299,7 @@ int reopen_text(Text *text) if (llen!=0 || text->nlines==0) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); @@ -307,12 +322,13 @@ int reopen_text(Text *text) Text *add_text(char *file) { FILE *fp; - int i, llen, len; + int i, llen, len, res; unsigned char *buffer; TextLine *tmp; Text *ta; char sfile[FILE_MAXFILE]; char str[FILE_MAXDIR+FILE_MAXFILE]; + struct stat st; BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE); if (G.scene) /* can be NULL (bg mode) */ @@ -326,6 +342,7 @@ Text *add_text(char *file) ta->id.us= 1; ta->lines.first= ta->lines.last= NULL; + ta->markers.first= ta->markers.last= NULL; ta->curl= ta->sell= NULL; /* ta->flags= TXT_ISTMP | TXT_ISEXT; */ @@ -348,6 +365,9 @@ Text *add_text(char *file) len = fread(buffer, 1, len, fp); fclose(fp); + + res= stat(str, &st); + ta->mtime= st.st_mtime; ta->nlines=0; i=0; @@ -356,7 +376,7 @@ Text *add_text(char *file) if (buffer[i]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); tmp->line[llen]=0; @@ -376,7 +396,7 @@ Text *add_text(char *file) if (llen!=0 || ta->nlines==0) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); - tmp->format= (char*) MEM_mallocN(llen+2, "Syntax_format"); + tmp->format= NULL; if(llen) memcpy(tmp->line, &buffer[i-llen], llen); @@ -410,6 +430,7 @@ Text *copy_text(Text *ta) tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP; tan->lines.first= tan->lines.last= NULL; + tan->markers.first= tan->markers.last= NULL; tan->curl= tan->sell= NULL; tan->nlines= ta->nlines; @@ -419,7 +440,7 @@ Text *copy_text(Text *ta) while (line) { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(line->len+1, "textline_string"); - tmp->format= MEM_mallocN(line->len+2, "Syntax_format"); + tmp->format= NULL; strcpy(tmp->line, line->line); @@ -440,14 +461,14 @@ Text *copy_text(Text *ta) /* Editing utility functions */ /*****************************/ -static void make_new_line (TextLine *line, char *newline, char *newformat) +static void make_new_line (TextLine *line, char *newline) { if (line->line) MEM_freeN(line->line); if (line->format) MEM_freeN(line->format); line->line= newline; line->len= strlen(newline); - line->format= newformat; + line->format= NULL; } static TextLine *txt_new_line(char *str) @@ -458,7 +479,7 @@ static TextLine *txt_new_line(char *str) tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(strlen(str)+1, "textline_string"); - tmp->format= MEM_mallocN(strlen(str)+2, "Syntax_format"); + tmp->format= NULL; strcpy(tmp->line, str); @@ -476,7 +497,7 @@ static TextLine *txt_new_linen(char *str, int n) tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= MEM_mallocN(n+1, "textline_string"); - tmp->format= MEM_mallocN(n+2, "Syntax_format"); + tmp->format= NULL; BLI_strncpy(tmp->line, str, n+1); @@ -553,6 +574,19 @@ static void txt_make_dirty (Text *text) if (text->compiled) BPY_free_compiled_text(text); } +/* 0:whitespace, 1:punct, 2:alphanumeric */ +static short txt_char_type (char ch) +{ + if (ch <= ' ') return 0; + if (ch <= '/') return 1; + if (ch <= '9') return 2; + if (ch <= '@') return 1; + if (ch <= 'Z') return 2; + if (ch <= '`') return 1; + if (ch <= 'z') return 2; + return 1; +} + /****************************/ /* Cursor utility functions */ /****************************/ @@ -606,8 +640,7 @@ void txt_move_up(Text *text, short sel) if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); } } else { - *charp= 0; - if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); + txt_move_bol(text, sel); } if(!sel) txt_pop_sel(text); @@ -632,8 +665,7 @@ void txt_move_down(Text *text, short sel) } else if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); } else { - *charp= (*linep)->len; - if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); + txt_move_eol(text, sel); } if(!sel) txt_pop_sel(text); @@ -689,6 +721,68 @@ void txt_move_right(Text *text, short sel) if(!sel) txt_pop_sel(text); } +void txt_jump_left(Text *text, short sel) +{ + TextLine **linep, *oldl; + int *charp, oldc, count, i; + unsigned char oldu; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + + oldl= *linep; + oldc= *charp; + oldu= undoing; + undoing= 1; /* Don't push individual moves to undo stack */ + + count= 0; + for (i=0; i<3; i++) { + if (count < 2) { + while (*charp>0 && txt_char_type((*linep)->line[*charp-1])==i) { + txt_move_left(text, sel); + count++; + } + } + } + if (count==0) txt_move_left(text, sel); + + undoing= oldu; + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +void txt_jump_right(Text *text, short sel) +{ + TextLine **linep, *oldl; + int *charp, oldc, count, i; + unsigned char oldu; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + + oldl= *linep; + oldc= *charp; + oldu= undoing; + undoing= 1; /* Don't push individual moves to undo stack */ + + count= 0; + for (i=0; i<3; i++) { + if (count < 2) { + while (*charp<(*linep)->len && txt_char_type((*linep)->line[*charp])==i) { + txt_move_right(text, sel); + count++; + } + } + } + if (count==0) txt_move_right(text, sel); + + undoing= oldu; + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + void txt_move_bol (Text *text, short sel) { TextLine **linep; @@ -760,6 +854,11 @@ void txt_move_eof (Text *text, short sel) } void txt_move_toline (Text *text, unsigned int line, short sel) +{ + txt_move_to(text, line, 0, sel); +} + +void txt_move_to (Text *text, unsigned int line, unsigned int ch, short sel) { TextLine **linep, *oldl; int *charp, oldc; @@ -777,10 +876,12 @@ void txt_move_toline (Text *text, unsigned int line, short sel) if ((*linep)->next) *linep= (*linep)->next; else break; } - *charp= 0; + if (ch>(*linep)->len) + ch= (*linep)->len; + *charp= ch; if(!sel) txt_pop_sel(text); - if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); } /****************************/ @@ -865,7 +966,9 @@ int txt_has_sel(Text *text) static void txt_delete_sel (Text *text) { TextLine *tmpl; - char *buf, *format; + TextMarker *mrk; + char *buf; + int move, lineno; if (!text) return; if (!text->curl) return; @@ -882,13 +985,33 @@ static void txt_delete_sel (Text *text) } buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string"); - format= MEM_mallocN(text->curc+(text->sell->len - text->selc)+2, "Syntax_format"); + if (text->curl != text->sell) { + txt_clear_marker_region(text, text->curl, text->curc, text->curl->len, 0, 0); + move= txt_get_span(text->curl, text->sell); + } else { + mrk= txt_find_marker_region(text, text->curl, text->curc, text->selc, 0, 0); + if (mrk && (mrk->start > text->curc || mrk->end < text->selc)) + txt_clear_marker_region(text, text->curl, text->curc, text->selc, 0, 0); + move= 0; + } + + mrk= txt_find_marker_region(text, text->sell, text->selc-1, text->sell->len, 0, 0); + if (mrk) { + lineno= mrk->lineno; + do { + mrk->lineno -= move; + if (mrk->start > text->curc) mrk->start -= text->selc - text->curc; + mrk->end -= text->selc - text->curc; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } + strncpy(buf, text->curl->line, text->curc); strcpy(buf+text->curc, text->sell->line + text->selc); buf[text->curc+(text->sell->len - text->selc)]=0; - make_new_line(text->curl, buf, format); + make_new_line(text->curl, buf); tmpl= text->sell; while (tmpl != text->curl) { @@ -995,22 +1118,31 @@ char *txt_to_buf (Text *text) return buf; } -int txt_find_string(Text *text, char *findstr) +int txt_find_string(Text *text, char *findstr, int wrap) { TextLine *tl, *startl; char *s= NULL; + int oldcl, oldsl, oldcc, oldsc; if (!text || !text->curl || !text->sell) return 0; txt_order_cursors(text); + oldcl= txt_get_span(text->lines.first, text->curl); + oldsl= txt_get_span(text->lines.first, text->sell); tl= startl= text->sell; + oldcc= text->curc; + oldsc= text->selc; s= strstr(&tl->line[text->selc], findstr); while (!s) { tl= tl->next; - if (!tl) - tl= text->lines.first; + if (!tl) { + if (wrap) + tl= text->lines.first; + else + break; + } s= strstr(tl->line, findstr); if (tl==startl) @@ -1018,10 +1150,10 @@ int txt_find_string(Text *text, char *findstr) } if (s) { - text->curl= text->sell= tl; - text->curc= (int) (s-tl->line); - text->selc= text->curc + strlen(findstr); - + int newl= txt_get_span(text->lines.first, tl); + int newc= (int)(s-tl->line); + txt_move_to(text, newl, newc, 0); + txt_move_to(text, newl, newc + strlen(findstr), 1); return 1; } else return 0; @@ -1621,7 +1753,6 @@ void txt_do_undo(Text *text) case UNDO_SWAP: txt_curs_swap(text); - txt_do_undo(text); /* swaps should appear transparent */ break; case UNDO_DBLOCK: @@ -1736,6 +1867,19 @@ void txt_do_undo(Text *text) break; } + + /* next undo step may need evaluating */ + if (text->undo_pos>=0) { + switch (text->undo_buf[text->undo_pos]) { + case UNDO_STO: + txt_do_undo(text); + txt_do_redo(text); /* selections need restoring */ + break; + case UNDO_SWAP: + txt_do_undo(text); /* swaps should appear transparent */ + break; + } + } undoing= 0; } @@ -1810,7 +1954,7 @@ void txt_do_redo(Text *text) case UNDO_SWAP: txt_curs_swap(text); - txt_do_undo(text); /* swaps should appear transparent a*/ + txt_do_redo(text); /* swaps should appear transparent a*/ break; case UNDO_CTO: @@ -1947,22 +2091,37 @@ void txt_do_redo(Text *text) void txt_split_curline (Text *text) { TextLine *ins; - char *left, *right, *fleft, *fright; + TextMarker *mrk; + char *left, *right; + int lineno= -1; if (!text) return; if (!text->curl) return; - txt_delete_sel(text); + txt_delete_sel(text); + + /* Move markers */ + + lineno= txt_get_span(text->lines.first, text->curl); + mrk= text->markers.first; + while (mrk) { + if (mrk->lineno==lineno && mrk->start>text->curc) { + mrk->lineno++; + mrk->start -= text->curc; + mrk->end -= text->curc; + } else if (mrk->lineno > lineno) { + mrk->lineno++; + } + mrk= mrk->next; + } /* Make the two half strings */ left= MEM_mallocN(text->curc+1, "textline_string"); - fleft= MEM_mallocN(text->curc+2, "Syntax_format"); if (text->curc) memcpy(left, text->curl->line, text->curc); left[text->curc]=0; right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string"); - fright= MEM_mallocN(text->curl->len - text->curc+2, "Syntax_format"); if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc); right[text->curl->len - text->curc]=0; @@ -1973,11 +2132,11 @@ void txt_split_curline (Text *text) ins= MEM_mallocN(sizeof(TextLine), "textline"); ins->line= left; - ins->format= fleft; + ins->format= NULL; ins->len= text->curc; text->curl->line= right; - text->curl->format= fright; + text->curl->format= NULL; text->curl->len= text->curl->len - text->curc; BLI_insertlinkbefore(&text->lines, text->curl, ins); @@ -1993,9 +2152,23 @@ void txt_split_curline (Text *text) static void txt_delete_line (Text *text, TextLine *line) { + TextMarker *mrk=NULL, *nxt; + int lineno= -1; + if (!text) return; if (!text->curl) return; + lineno= txt_get_span(text->lines.first, line); + mrk= text->markers.first; + while (mrk) { + nxt= mrk->next; + if (mrk->lineno==lineno) + BLI_freelinkN(&text->markers, mrk); + else if (mrk->lineno > lineno) + mrk->lineno--; + mrk= nxt; + } + BLI_remlink (&text->lines, line); if (line->line) MEM_freeN(line->line); @@ -2009,21 +2182,35 @@ static void txt_delete_line (Text *text, TextLine *line) static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb) { - char *tmp, *format; + char *tmp; + TextMarker *mrk= NULL; + int lineno=-1; if (!text) return; if(!linea || !lineb) return; + + mrk= txt_find_marker_region(text, lineb, 0, lineb->len, 0, 0); + if (mrk) { + lineno= mrk->lineno; + do { + mrk->lineno--; + mrk->start += linea->len; + mrk->end += linea->len; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } + if (lineno==-1) lineno= txt_get_span(text->lines.first, lineb); + if (!mrk) mrk= text->markers.first; tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string"); - format= MEM_mallocN(linea->len+lineb->len+1, "Syntax_format"); strcpy(tmp, linea->line); strcat(tmp, lineb->line); - make_new_line(linea, tmp, format); + make_new_line(linea, tmp); - txt_delete_line(text, lineb); + txt_delete_line(text, lineb); txt_make_dirty(text); txt_clean_text(text); @@ -2037,8 +2224,9 @@ void txt_delete_char (Text *text) if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ - txt_delete_sel(text); - return; + txt_delete_sel(text); + txt_make_dirty(text); + return; } else if (text->curc== text->curl->len) { /* Appending two lines */ if (text->curl->next) { @@ -2047,6 +2235,25 @@ void txt_delete_char (Text *text) } } else { /* Just deleting a char */ int i= text->curc; + + TextMarker *mrk= txt_find_marker_region(text, text->curl, i-1, text->curl->len, 0, 0); + if (mrk) { + int lineno= mrk->lineno; + if (mrk->end==i) { + if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { + txt_clear_markers(text, mrk->group, TMARK_TEMP); + } else { + //TextMarker *nxt= mrk->next; + BLI_freelinkN(&text->markers, mrk); + } + return; + } + do { + if (mrk->start>i) mrk->start--; + mrk->end--; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } c= text->curl->line[i]; while(i< text->curl->len) { @@ -2064,6 +2271,12 @@ void txt_delete_char (Text *text) if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c); } +void txt_delete_word (Text *text) +{ + txt_jump_right(text, 1); + txt_delete_sel(text); +} + void txt_backspace_char (Text *text) { char c='\n'; @@ -2072,8 +2285,9 @@ void txt_backspace_char (Text *text) if (!text->curl) return; if (txt_has_sel(text)) { /* deleting a selection */ - txt_delete_sel(text); - return; + txt_delete_sel(text); + txt_make_dirty(text); + return; } else if (text->curc==0) { /* Appending two lines */ if (!text->curl->prev) return; @@ -2083,19 +2297,38 @@ void txt_backspace_char (Text *text) txt_combine_lines(text, text->curl, text->curl->next); txt_pop_sel(text); - } + } else { /* Just backspacing a char */ - int i= text->curc-1; + int i= text->curc-1; + + TextMarker *mrk= txt_find_marker_region(text, text->curl, i, text->curl->len, 0, 0); + if (mrk) { + int lineno= mrk->lineno; + if (mrk->start==i+1) { + if ((mrk->flags & TMARK_TEMP) && !(mrk->flags & TMARK_EDITALL)) { + txt_clear_markers(text, mrk->group, TMARK_TEMP); + } else { + //TextMarker *nxt= mrk->next; + BLI_freelinkN(&text->markers, mrk); + } + return; + } + do { + if (mrk->start>i) mrk->start--; + mrk->end--; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } - c= text->curl->line[i]; - while(i< text->curl->len) { - text->curl->line[i]= text->curl->line[i+1]; - i++; - } - text->curl->len--; - text->curc--; - - txt_pop_sel(text); + c= text->curl->line[i]; + while(i< text->curl->len) { + text->curl->line[i]= text->curl->line[i+1]; + i++; + } + text->curl->len--; + text->curc--; + + txt_pop_sel(text); } txt_make_dirty(text); @@ -2104,10 +2337,17 @@ void txt_backspace_char (Text *text) if(!undoing) txt_undo_add_charop(text, UNDO_BS, c); } +void txt_backspace_word (Text *text) +{ + txt_jump_left(text, 1); + txt_delete_sel(text); +} + int txt_add_char (Text *text, char add) { - int len; - char *tmp, *format; + int len, lineno; + char *tmp; + TextMarker *mrk; if (!text) return 0; if (!text->curl) return 0; @@ -2119,8 +2359,17 @@ int txt_add_char (Text *text, char add) txt_delete_sel(text); + mrk= txt_find_marker_region(text, text->curl, text->curc-1, text->curl->len, 0, 0); + if (mrk) { + lineno= mrk->lineno; + do { + if (mrk->start>text->curc) mrk->start++; + mrk->end++; + mrk= mrk->next; + } while (mrk && mrk->lineno==lineno); + } + tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - format= MEM_mallocN(text->curl->len+4, "Syntax_format"); if(text->curc) memcpy(tmp, text->curl->line, text->curc); tmp[text->curc]= add; @@ -2128,7 +2377,7 @@ int txt_add_char (Text *text, char add) len= text->curl->len - text->curc; if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp, format); + make_new_line(text->curl, tmp); text->curc++; @@ -2141,10 +2390,42 @@ int txt_add_char (Text *text, char add) return 1; } +int txt_replace_char (Text *text, char add) +{ + char del; + + if (!text) return 0; + if (!text->curl) return 0; + + /* If text is selected or we're at the end of the line just use txt_add_char */ + if (text->curc==text->curl->len || txt_has_sel(text) || add=='\n') { + TextMarker *mrk; + int i= txt_add_char(text, add); + mrk= txt_find_marker(text, text->curl, text->curc, 0, 0); + if (mrk && mrk->end==text->curc) mrk->end--; + return i; + } + + del= text->curl->line[text->curc]; + text->curl->line[text->curc]= (unsigned char) add; + text->curc++; + txt_pop_sel(text); + + txt_make_dirty(text); + txt_clean_text(text); + + /* Should probably create a new op for this */ + if(!undoing) { + txt_undo_add_charop(text, UNDO_DEL, del); + txt_undo_add_charop(text, UNDO_INSERT, add); + } + return 1; +} + void indent(Text *text) { int len, num; - char *tmp, *format; + char *tmp; char add = '\t'; if (!text) return; @@ -2155,7 +2436,6 @@ void indent(Text *text) while (TRUE) { tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - format= MEM_mallocN(text->curl->len+3, "Syntax_format"); text->curc = 0; if(text->curc) memcpy(tmp, text->curl->line, text->curc); @@ -2165,7 +2445,7 @@ void indent(Text *text) if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp, format); + make_new_line(text->curl, tmp); text->curc++; @@ -2246,7 +2526,7 @@ void unindent(Text *text) void comment(Text *text) { int len, num; - char *tmp, *format; + char *tmp; char add = '#'; if (!text) return; @@ -2257,7 +2537,6 @@ void comment(Text *text) while (TRUE) { tmp= MEM_mallocN(text->curl->len+2, "textline_string"); - format = MEM_mallocN(text->curl->len+3, "Syntax_format"); text->curc = 0; if(text->curc) memcpy(tmp, text->curl->line, text->curc); @@ -2267,7 +2546,7 @@ void comment(Text *text) if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); tmp[text->curl->len+1]=0; - make_new_line(text->curl, tmp, format); + make_new_line(text->curl, tmp); text->curc++; @@ -2398,3 +2677,148 @@ int setcurr_tab (Text *text) return i; } +/*********************************/ +/* Text marker utility functions */ +/*********************************/ + +static int color_match(TextMarker *a, TextMarker *b) { + return (a->color[0]==b->color[0] && + a->color[1]==b->color[1] && + a->color[2]==b->color[2] && + a->color[3]==b->color[3]); +} + +/* Creates and adds a marker to the list maintaining sorted order */ +void txt_add_marker(Text *text, TextLine *line, int start, int end, char color[4], int group, int flags) { + TextMarker *tmp, *marker; + + marker= MEM_mallocN(sizeof(TextMarker), "text_marker"); + + marker->lineno= txt_get_span(text->lines.first, line); + marker->start= MIN2(start, end); + marker->end= MAX2(start, end); + marker->group= group; + marker->flags= flags; + + marker->color[0]= color[0]; + marker->color[1]= color[1]; + marker->color[2]= color[2]; + marker->color[3]= color[3]; + + for (tmp=text->markers.last; tmp; tmp=tmp->prev) + if (tmp->lineno < marker->lineno || (tmp->lineno==marker->lineno && tmp->start < marker->start)) + break; + + if (tmp) BLI_insertlinkafter(&text->markers, tmp, marker); + else BLI_addhead(&text->markers, marker); +} + +/* Returns the first matching marker on the specified line between two points. + If the group or flags fields are non-zero the returned flag must be in the + specified group and have at least the specified flags set. */ +TextMarker *txt_find_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) { + TextMarker *marker, *next; + int lineno= txt_get_span(text->lines.first, line); + + for (marker=text->markers.first; marker; marker=next) { + next= marker->next; + + if (group && marker->group != group) continue; + else if ((marker->flags & flags) != flags) continue; + else if (marker->lineno < lineno) continue; + else if (marker->lineno > lineno) break; + + if ((marker->start==marker->end && start<=marker->start && marker->start<=end) || + (marker->startend>start)) + return marker; + } + return NULL; +} + +/* Clears all markers on the specified line between two points. If the group or + flags fields are non-zero the returned flag must be in the specified group + and have at least the specified flags set. */ +short txt_clear_marker_region(Text *text, TextLine *line, int start, int end, int group, int flags) { + TextMarker *marker, *next; + int lineno= txt_get_span(text->lines.first, line); + short cleared= 0; + + for (marker=text->markers.first; marker; marker=next) { + next= marker->next; + + if (group && marker->group != group) continue; + else if ((marker->flags & flags) != flags) continue; + else if (marker->lineno < lineno) continue; + else if (marker->lineno > lineno) break; + + if ((marker->start==marker->end && start<=marker->start && marker->start<=end) || + (marker->startend>start)) { + BLI_freelinkN(&text->markers, marker); + cleared= 1; + } + } + return cleared; +} + +/* Clears all markers in the specified group (if given) with at least the + specified flags set. Useful for clearing temporary markers (group=0, + flags=TMARK_TEMP) */ +short txt_clear_markers(Text *text, int group, int flags) { + TextMarker *marker, *next; + short cleared= 0; + + for (marker=text->markers.first; marker; marker=next) { + next= marker->next; + + if ((!group || marker->group==group) && + (marker->flags & flags) == flags) { + BLI_freelinkN(&text->markers, marker); + cleared= 1; + } + } + return cleared; +} + +/* Finds the marker at the specified line and cursor position with at least the + specified flags set in the given group (if non-zero). */ +TextMarker *txt_find_marker(Text *text, TextLine *line, int curs, int group, int flags) { + TextMarker *marker; + int lineno= txt_get_span(text->lines.first, line); + + for (marker=text->markers.first; marker; marker=marker->next) { + if (group && marker->group != group) continue; + else if ((marker->flags & flags) != flags) continue; + else if (marker->lineno < lineno) continue; + else if (marker->lineno > lineno) break; + + if (marker->start <= curs && curs <= marker->end) + return marker; + } + return NULL; +} + +/* Finds the previous marker in the same group. If no other is found, the same + marker will be returned */ +TextMarker *txt_prev_marker(Text *text, TextMarker *marker) { + TextMarker *tmp= marker; + while (tmp) { + if (tmp->prev) tmp= tmp->prev; + else tmp= text->markers.last; + if (tmp->group == marker->group) + return tmp; + } + return NULL; /* Only if marker==NULL */ +} + +/* Finds the next marker in the same group. If no other is found, the same + marker will be returned */ +TextMarker *txt_next_marker(Text *text, TextMarker *marker) { + TextMarker *tmp= marker; + while (tmp) { + if (tmp->next) tmp= tmp->next; + else tmp= text->markers.first; + if (tmp->group == marker->group) + return tmp; + } + return NULL; /* Only if marker==NULL */ +} diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 936381c85cc..bb726887d32 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -53,6 +53,7 @@ #include "DNA_world_types.h" #include "DNA_brush_types.h" #include "DNA_node_types.h" +#include "DNA_color_types.h" #include "DNA_scene_types.h" #include "IMB_imbuf_types.h" @@ -390,6 +391,17 @@ int do_colorband(ColorBand *coba, float in, float out[4]) return 1; /* OK */ } +void colorband_table_RGBA(ColorBand *coba, float **array, int *size) +{ + int a; + + *size = CM_TABLE+1; + *array = MEM_callocN(sizeof(float)*(*size)*4, "ColorBand"); + + for(a=0; a<*size; a++) + do_colorband(coba, (float)a/(float)CM_TABLE, &(*array)[a*4]); +} + /* ******************* TEX ************************ */ void free_texture(Tex *tex) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index c22b6f79e08..6e54fae58d0 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -164,6 +164,7 @@ void Mat3Inv(float m1[][3], float m2[][3]); void Mat3CpyMat4(float m1[][3],float m2[][4]); void Mat4CpyMat3(float m1[][4], float m2[][3]); +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight); void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight); float Det2x2(float a,float b,float c, float d); @@ -260,6 +261,7 @@ void Vec2Mulf(float *v1, float f); void Vec2Addf(float *v, float *v1, float *v2); void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); +void Vec2Lerpf(float *target, float *a, float *b, float t); void AxisAngleToQuat(float *q, float *axis, float angle); void vectoquat(float *vec, short axis, short upflag, float *q); diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index e24ccad12fb..a1db7adf33d 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -73,7 +73,6 @@ extern ListBase fillvertbase; * @attention Defined in scanfill.c */ extern ListBase filledgebase; -extern int totblock; extern char btempdir[]; /* creator.c temp dir used instead of U.tempdir, set with BLI_where_is_temp( btempdir, 1 ); */ @@ -152,6 +151,7 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds */ int BLI_convertstringcode(char *path, const char *basepath); int BLI_convertstringframe(char *path, int frame); +int BLI_convertstringcwd(char *path); void BLI_makestringcode(const char *relfile, char *file); diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6d9a17efebf..e3591a84e98 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -54,6 +54,7 @@ typedef struct BVHTreeRay { float origin[3]; /* ray origin */ float direction[3]; /* ray direction */ + float radius; /* radius around ray */ } BVHTreeRay; typedef struct BVHTreeRayHit @@ -90,7 +91,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index 649d3cb5659..65cebf02f62 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -24,4 +24,4 @@ if env['OURPLATFORM'] == 'linux2': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] -env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core','player'], priority = [85,195], compileflags =cflags ) +env.BlenderLib ( 'bf_blenlib', sources, Split(incs), Split(defs), libtype=['core', 'intern', 'player'], priority = [85,150,195], compileflags =cflags ) diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index c41c3d8c3ab..30472beb3e6 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -51,6 +51,7 @@ typedef struct BVHNode { struct BVHNode **children; + struct BVHNode *parent; // some user defined traversed need that 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 @@ -82,7 +83,7 @@ typedef struct BVHOverlapData typedef struct BVHNearestData { BVHTree *tree; - float *co; + const float *co; BVHTree_NearestPointCallback callback; void *userdata; float proj[13]; //coordinates projection over axis @@ -481,7 +482,7 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) { int i; for(i=0; iindex, node - tree->nodearray); + printf(" - %d (%ld): ", node->index, node - tree->nodearray); for(i=2*tree->start_axis; i<2*tree->stop_axis; i++) printf("%.3f ", node->bv[i]); printf("\n"); @@ -496,10 +497,10 @@ static void bvhtree_info(BVHTree *tree) printf("BVHTree info\n"); printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); - printf("Memory per node = %dbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); + printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode*)*tree->tree_type + sizeof(float)*tree->axis); printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv)); - printf("Total memory = %dbytes\n", sizeof(BVHTree) + printf("Total memory = %ldbytes\n", sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + MEM_allocN_len(tree->nodearray) + MEM_allocN_len(tree->nodechild) @@ -700,6 +701,10 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, BVHBuildHelper data; int depth; + + // set parent from root node to NULL + BVHNode *tmp = branches_array+0; + tmp->parent = NULL; //Most of bvhtree code relies on 1-leaf trees having at least one branch //We handle that special case here @@ -709,7 +714,8 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, refit_kdop_hull(tree, root, 0, num_leafs); root->main_axis = get_largest_axis(root->bv) / 2; root->totnode = 1; - root->children[0] = leafs_array[0]; + root->children[0] = leafs_array[0]; + root->children[0]->parent = root; return; } @@ -772,9 +778,15 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, int child_leafs_end = implicit_leafs_index(&data, depth+1, child_level_index+1); if(child_leafs_end - child_leafs_begin > 1) + { parent->children[k] = branches_array + child_index; + parent->children[k]->parent = parent; + } else if(child_leafs_end - child_leafs_begin == 1) + { parent->children[k] = leafs_array[ child_leafs_begin ]; + parent->children[k]->parent = parent; + } else break; @@ -1096,7 +1108,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, int *result) BVHOverlapData **data; // check for compatibility of both trees (can't compare 14-DOP with 18-DOP) - if((tree1->axis != tree2->axis) && ((tree1->axis == 14) || tree2->axis == 14)) + if((tree1->axis != tree2->axis) && (tree1->axis == 14 || tree2->axis == 14) && (tree1->axis == 18 || tree2->axis == 18)) return 0; // fast check root nodes for collision before doing big splitting + traversal @@ -1248,7 +1260,6 @@ static void dfs_find_nearest_dfs(BVHNearestData *data, BVHNode *node) static void dfs_find_nearest_begin(BVHNearestData *data, BVHNode *node) { - int i; float nearest[3], sdist; sdist = calc_nearest_point(data, node, nearest); if(sdist >= data->nearest.dist) return; @@ -1403,14 +1414,14 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) if(data->ray_dot_axis[i] == 0.0f) { //axis aligned ray - if(data->ray.origin[i] < bv[0] - || data->ray.origin[i] > bv[1]) + if(data->ray.origin[i] < bv[0] - data->ray.radius + || data->ray.origin[i] > bv[1] + data->ray.radius) return FLT_MAX; } else { - float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; + float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; if(data->ray_dot_axis[i] > 0.0f) { @@ -1469,7 +1480,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; @@ -1482,6 +1493,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTr VECCOPY(data.ray.origin, co); VECCOPY(data.ray.direction, dir); + data.ray.radius = radius; Normalize(data.ray.direction); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index c1edb7d3ac1..844c0cc909a 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -758,6 +758,28 @@ void Mat4MulSerie(float answ[][4], float m1[][4], } } +void Mat3BlendMat3(float out[][3], float dst[][3], float src[][3], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float rmat[3][3], smat[3][3]; + + Mat3ToQuat(dst, dquat); + Mat3ToSize(dst, dsize); + + Mat3ToQuat(src, squat); + Mat3ToSize(src, ssize); + + /* do blending */ + QuatInterpol(fquat, dquat, squat, srcweight); + VecLerpf(fsize, dsize, ssize, srcweight); + + /* compose new matrix */ + QuatToMat3(fquat, rmat); + SizeToMat3(fsize, smat); + Mat3MulMat3(out, rmat, smat); +} + void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight) { float squat[4], dquat[4], fquat[4]; @@ -2112,6 +2134,14 @@ void VecLerpf(float *target, float *a, float *b, float t) target[2]= s*a[2] + t*b[2]; } +void Vec2Lerpf(float *target, float *a, float *b, float t) +{ + float s = 1.0f-t; + + target[0]= s*a[0] + t*b[0]; + target[1]= s*a[1] + t*b[1]; +} + void VecMidf(float *v, float *v1, float *v2) { v[0]= 0.5f*(v1[0]+ v2[0]); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index a31121148e3..c27efcb7934 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1211,6 +1211,49 @@ int BLI_convertstringcode(char *path, const char *basepath) return wasrelative; } + +/* + * Should only be done with command line paths. + * this is NOT somthing blenders internal paths support like the // prefix + */ +int BLI_convertstringcwd(char *path) +{ + int wasrelative = 1; + int filelen = strlen(path); + +#ifdef WIN32 + if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) + wasrelative = 0; +#else + if (filelen >= 2 && path[0] == '/') + wasrelative = 0; +#endif + + if (wasrelative==1) { + char cwd[FILE_MAXDIR + FILE_MAXFILE]; + BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + + if (cwd[0] == '\0') { + printf( "Could not get the current working directory - $PWD for an unknown reason."); + } else { + /* uses the blend path relative to cwd important for loading relative linked files. + * + * cwd should contain c:\ etc on win32 so the relbase can be NULL + * relbase being NULL also prevents // being misunderstood as relative to the current + * blend file which isnt a feature we want to use in this case since were dealing + * with a path from the command line, rather then from inside Blender */ + + char origpath[FILE_MAXDIR + FILE_MAXFILE]; + BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE); + + BLI_make_file_string(NULL, path, cwd, origpath); + } + } + + return wasrelative; +} + + /* copy di to fi, filename only */ void BLI_splitdirstring(char *di, char *fi) { diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index ff2a256f606..4aa2a229dcc 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -237,7 +237,7 @@ void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode); void BLO_library_append_(BlendHandle **libfiledata, struct direntry* filelist, int totfile, char *dir, char* file, short flag, int idcode); void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Scene *scene); -BlendFileData* blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r); +BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r); #ifdef __cplusplus } diff --git a/source/blender/blenloader/BLO_sys_types.h b/source/blender/blenloader/BLO_sys_types.h index a9d29375eac..49155260b31 100644 --- a/source/blender/blenloader/BLO_sys_types.h +++ b/source/blender/blenloader/BLO_sys_types.h @@ -49,6 +49,7 @@ extern "C" { /* The __intXX are built-in types of the visual complier! So we don't * need to include anything else here. */ + typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; @@ -59,13 +60,23 @@ typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; +#ifndef _INTPTR_T_DEFINED #ifdef _WIN64 typedef __int64 intptr_t; -typedef unsigned __int64 uintptr_t; #else typedef long intptr_t; +#endif +#define _INTPTR_T_DEFINED +#endif + +#ifndef _UINTPTR_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 uintptr_t; +#else typedef unsigned long uintptr_t; #endif +#define _UINTPTR_T_DEFINED +#endif #elif defined(__linux__) @@ -87,6 +98,7 @@ typedef unsigned long uintptr_t; #endif /* ifdef platform for types */ + #ifdef _WIN32 #define htonl(x) correctByteOrder(x) #define ntohl(x) correctByteOrder(x) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 35ca42a4949..1d30d9e5bc6 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -970,9 +970,11 @@ FileData *blo_openblenderfile(char *name, BlendReadError *error_r) } else { FileData *fd = filedata_new(); fd->gzfiledes = gzfile; - BLI_strncpy(fd->filename, name, sizeof(fd->filename)); // now only in use by library append fd->read = fd_read_gzip_from_file; + /* needed for library_append and read_libraries */ + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); + return blo_decode_and_check(fd, error_r); } } @@ -1138,6 +1140,8 @@ void blo_make_image_pointer_map(FileData *fd) Link *ibuf= ima->ibufs.first; for(; ibuf; ibuf= ibuf->next) oldnewmap_insert(fd->imamap, ibuf, ibuf, 0); + if(ima->gputexture) + oldnewmap_insert(fd->imamap, ima->gputexture, ima->gputexture, 0); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -1172,8 +1176,11 @@ void blo_end_image_pointer_map(FileData *fd) if(NULL==newimaadr(fd, ibuf)) { /* so was restored */ BLI_remlink(&ima->ibufs, ibuf); ima->bindcode= 0; + ima->gputexture= NULL; } } + + ima->gputexture= newimaadr(fd, ima->gputexture); } for(; sce; sce= sce->id.next) { if(sce->nodetree) { @@ -2280,6 +2287,7 @@ static void direct_link_text(FileData *fd, Text *text) */ link_list(fd, &text->lines); + link_list(fd, &text->markers); text->curl= newdataadr(fd, text->curl); text->sell= newdataadr(fd, text->sell); @@ -2346,8 +2354,10 @@ static void direct_link_image(FileData *fd, Image *ima) ima->ibufs.first= ima->ibufs.last= NULL; /* if not restored, we keep the binded opengl index */ - if(ima->ibufs.first==NULL) + if(ima->ibufs.first==NULL) { ima->bindcode= 0; + ima->gputexture= NULL; + } ima->anim= NULL; ima->rr= NULL; @@ -2558,6 +2568,7 @@ static void direct_link_material(FileData *fd, Material *ma) direct_link_nodetree(fd, ma->nodetree); ma->preview = direct_link_preview_image(fd, ma->preview); + ma->gpumaterial.first = ma->gpumaterial.last = NULL; } /* ************ READ PARTICLE SETTINGS ***************** */ @@ -2592,19 +2603,33 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part) part->pd2= newdataadr(fd, part->pd2); } -static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles) +static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles) { - ParticleSystem *psys; + ParticleSystem *psys, *psysnext; int a; - for(psys=particles->first; psys; psys=psys->next){ + for(psys=particles->first; psys; psys=psysnext){ ParticleData *pa; + + psysnext= psys->next; + psys->part = newlibadr_us(fd, id->lib, psys->part); - psys->target_ob = newlibadr(fd, id->lib, psys->target_ob); - psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob); + if(psys->part) { + psys->target_ob = newlibadr(fd, id->lib, psys->target_ob); + psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob); - for(a=0,pa=psys->particles; atotpart; a++,pa++){ - pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob); + for(a=0,pa=psys->particles; atotpart; a++,pa++){ + pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob); + } + } + else { + /* particle modifier must be removed before particle system */ + ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys); + BLI_remlink(&ob->modifiers, psmd); + modifier_free((ModifierData *)psmd); + + BLI_remlink(particles, psys); + MEM_freeN(psys); } } } @@ -3056,7 +3081,7 @@ static void lib_link_object(FileData *fd, Main *main) ob->pd->tex=newlibadr_us(fd, ob->id.lib, ob->pd->tex); lib_link_scriptlink(fd, &ob->id, &ob->scriptlink); - lib_link_particlesystems(fd, &ob->id, &ob->particlesystem); + lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem); lib_link_modifiers(fd, ob); } ob= ob->id.next; @@ -3396,6 +3421,7 @@ static void direct_link_object(FileData *fd, Object *ob) ob->bb= NULL; ob->derivedDeform= NULL; ob->derivedFinal= NULL; + ob->gpulamp.first= ob->gpulamp.last= NULL; } /* ************ READ SCENE ***************** */ @@ -4170,6 +4196,9 @@ static void direct_link_screen(FileData *fd, bScreen *sc) sima->cumap= newdataadr(fd, sima->cumap); if(sima->cumap) direct_link_curvemapping(fd, sima->cumap); + sima->gpd= newdataadr(fd, sima->gpd); + if (sima->gpd) + link_gpencil(fd, sima->gpd); sima->iuser.ok= 1; } else if(sl->spacetype==SPACE_NODE) { @@ -7754,14 +7783,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if(main->versionfile <= 246 && main->subversionfile < 1){ + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) { Mesh *me; for(me=main->mesh.first; me; me= me->id.next) alphasort_version_246(fd, lib, me); } - if(main->versionfile <= 246 && main->subversionfile < 1){ + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)){ Object *ob; for(ob = main->object.first; ob; ob= ob->id.next) { if(ob->pd && (ob->pd->forcefield == PFIELD_WIND)) @@ -7769,6 +7798,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 2)){ + Object *ob; + for(ob = main->object.first; ob; ob= ob->id.next) { + ob->gameflag |= OB_COLLISION; + ob->margin = 0.06; + } + } + /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ @@ -9124,7 +9161,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) /* reading runtime */ -BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r) +BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r) { BlendFileData *bfd = NULL; FileData *fd = filedata_new(); @@ -9132,6 +9169,9 @@ BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadErr fd->buffersize = actualsize; fd->read = fd_read_from_file; + /* needed for library_append and read_libraries */ + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); + fd = blo_decode_and_check(fd, error_r); if (!fd) return NULL; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d596f57990f..44634a7468c 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1698,7 +1698,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "SpaceImage", 1, sl); if(sima->cumap) - write_curvemapping(wd, sima->cumap); + write_curvemapping(wd, sima->cumap); + if(sima->gpd) + write_gpencil(wd, sima->gpd); } else if(sl->spacetype==SPACE_IMASEL) { writestruct(wd, DATA, "SpaceImaSel", 1, sl); @@ -1849,6 +1851,7 @@ static void write_texts(WriteData *wd, ListBase *idbase) { Text *text; TextLine *tmp; + TextMarker *mrk; text= idbase->first; while(text) { @@ -1872,7 +1875,16 @@ static void write_texts(WriteData *wd, ListBase *idbase) writedata(wd, DATA, tmp->len+1, tmp->line); tmp= tmp->next; } + + /* write markers */ + mrk= text->markers.first; + while (mrk) { + writestruct(wd, DATA, "TextMarker", 1, mrk); + mrk= mrk->next; + } } + + text= text->id.next; } diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt new file mode 100644 index 00000000000..4d376f47d91 --- /dev/null +++ b/source/blender/gpu/CMakeLists.txt @@ -0,0 +1,34 @@ +# $Id: CMakeLists.txt 14444 2008-04-16 22:40:48Z hos $ +# ***** 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/*.c) + +SET(INC + . ../blenlib ../blenkernel ../makesdna ../include + ../../../extern/glew/include ../../../intern/guardedalloc ../imbuf) + +BLENDERLIB(bf_gpu "${SRC}" "${INC}") + diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h new file mode 100644 index 00000000000..2399e7b6a8c --- /dev/null +++ b/source/blender/gpu/GPU_draw.h @@ -0,0 +1,116 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef GPU_GAME_H +#define GPU_GAME_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct MTFace; +struct Image; +struct Scene; +struct Object; + +/* OpenGL drawing functions related to shading. These are also + * shared with the game engine, where there were previously + * duplicates of some of these functions. */ + +/* Initialize + * - sets the default Blender opengl state, if in doubt, check + * the contents of this function + * - this is called when starting Blender, for opengl rendering, + * and for switching back from the game engine for example. */ + +void GPU_state_init(void); + +/* Material drawing + * - first the state is initialized by a particular object and + * it's materials + * - after this, materials can be quickly enabled by their number, + * GPU_enable_material returns 0 if drawing should be skipped + * - after drawing, the material must be disabled again */ + +void GPU_set_object_materials(struct Scene *scene, struct Object *ob, + int glsl, int *do_alpha_pass); +int GPU_enable_material(int nr, void *attribs); +void GPU_disable_material(void); + +void GPU_set_material_blend_mode(int blendmode); +int GPU_get_material_blend_mode(void); + +/* TexFace drawing + * - this is mutually exclusive with material drawing, a mesh should + * be drawn using one or the other + * - passing NULL clears the state again */ + +int GPU_set_tpage(struct MTFace *tface); + +/* Lights + * - returns how many lights were enabled + * - this affects fixed functions materials and texface, not glsl */ + +int GPU_default_lights(void); +int GPU_scene_object_lights(struct Scene *scene, struct Object *ob, + int lay, float viewmat[][4]); + +/* Text render + * - based on moving uv coordinates */ + +void GPU_render_text(struct MTFace *tface, int mode, + const char *textstr, int textlen, unsigned int *col, + float *v1, float *v2, float *v3, float *v4, int glattrib); + +/* Mipmap settings + * - these will free textures on changes */ + +void GPU_set_mipmap(int mipmap); +void GPU_set_linear_mipmap(int linear); +void GPU_paint_set_mipmap(int mipmap); + +/* Image updates and free + * - these deal with images bound as opengl textures */ + +void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h); +void GPU_update_images_framechange(void); +int GPU_update_image_time(struct Image *ima, double time); +int GPU_verify_image(struct Image *ima, int tftile, int tfmode, int compare); +void GPU_free_image(struct Image *ima); +void GPU_free_images(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h new file mode 100644 index 00000000000..d3faa81ebb1 --- /dev/null +++ b/source/blender/gpu/GPU_extensions.h @@ -0,0 +1,144 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef GPU_EXTENSIONS_H +#define GPU_EXTENSIONS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* GPU extensions support */ + +struct Image; +struct ImageUser; + +struct GPUTexture; +typedef struct GPUTexture GPUTexture; + +struct GPUFrameBuffer; +typedef struct GPUFrameBuffer GPUFrameBuffer; + +struct GPUShader; +typedef struct GPUShader GPUShader; + +void GPU_extensions_init(void); /* call this before running any of the functions below */ +void GPU_extensions_exit(void); +int GPU_extensions_minimum_support(void); +int GPU_print_error(char *str); + +/* GPU Texture + - always returns unsigned char RGBA textures + - if texture with non square dimensions is created, depending on the + graphics card capabilities the texture may actually be stored in a + larger texture with power of two dimensions. the actual dimensions + may be querd with GPU_texture_opengl_width/height. GPU_texture_coord_2f + calls glTexCoord2f with the coordinates adjust for this. + - can use reference counting: + - reference counter after GPU_texture_create is 1 + - GPU_texture_ref increases by one + - GPU_texture_free decreases by one, and frees if 0 + - if created with from_blender, will not free the texture +*/ + +GPUTexture *GPU_texture_create_1D(int w, float *pixels); +GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels); +GPUTexture *GPU_texture_create_depth(int w, int h); +GPUTexture *GPU_texture_from_blender(struct Image *ima, + struct ImageUser *iuser, double time); +void GPU_texture_free(GPUTexture *tex); + +void GPU_texture_ref(GPUTexture *tex); + +void GPU_texture_bind(GPUTexture *tex, int number); +void GPU_texture_unbind(GPUTexture *tex); + +GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex); + +int GPU_texture_target(GPUTexture *tex); +int GPU_texture_opengl_width(GPUTexture *tex); +int GPU_texture_opengl_height(GPUTexture *tex); + +/* GPU Framebuffer + - this is a wrapper for an OpenGL framebuffer object (FBO). in practice + multiple FBO's may be created, to get around limitations on the number + of attached textures and the dimension requirements. + - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must + be called before rendering to the window framebuffer again */ + +GPUFrameBuffer *GPU_framebuffer_create(); +int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_free(GPUFrameBuffer *fb); + +void GPU_framebuffer_restore(); + +/* GPU Shader + - only for fragment shaders now + - must call texture bind before setting a texture as uniform! */ + +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib); +GPUShader *GPU_shader_create_lib(const char *code); +void GPU_shader_free(GPUShader *shader); + +void GPU_shader_bind(GPUShader *shader); +void GPU_shader_unbind(); + +int GPU_shader_get_uniform(GPUShader *shader, char *name); +void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, + int arraysize, float *value); +void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex); + +int GPU_shader_get_attribute(GPUShader *shader, char *name); + +/* Vertex attributes for shaders */ + +#define GPU_MAX_ATTRIB 32 + +typedef struct GPUVertexAttribs { + struct { + int type; + int glindex; + char name[32]; + } layer[GPU_MAX_ATTRIB]; + + int totlayer; +} GPUVertexAttribs; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h new file mode 100644 index 00000000000..ccc687858f4 --- /dev/null +++ b/source/blender/gpu/GPU_material.h @@ -0,0 +1,169 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This shader 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 shader 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 shader; 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __GPU_MATERIAL__ +#define __GPU_MATERIAL__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Image; +struct ImageUser; +struct Material; +struct Object; +struct Lamp; +struct bNode; +struct LinkNode; +struct Scene; +struct GPUVertexAttribs; +struct GPUNode; +struct GPUNodeLink; +struct GPUNodeStack; +struct GPUMaterial; +struct GPUTexture; +struct GPULamp; + +typedef struct GPUNode GPUNode; +typedef struct GPUNodeLink GPUNodeLink; +typedef struct GPUMaterial GPUMaterial; +typedef struct GPULamp GPULamp; + +/* Functions to create GPU Materials nodes */ + +typedef enum GPUType { + GPU_NONE = 0, + GPU_FLOAT = 1, + GPU_VEC2 = 2, + GPU_VEC3 = 3, + GPU_VEC4 = 4, + GPU_MAT3 = 9, + GPU_MAT4 = 16, + GPU_TEX1D = 1001, + GPU_TEX2D = 1002, + GPU_SHADOW2D = 1003, + GPU_ATTRIB = 3001 +} GPUType; + +typedef enum GPUBuiltin { + GPU_VIEW_MATRIX = 1, + GPU_OBJECT_MATRIX = 2, + GPU_INVERSE_VIEW_MATRIX = 4, + GPU_INVERSE_OBJECT_MATRIX = 8, + GPU_VIEW_POSITION = 16, + GPU_VIEW_NORMAL = 32, + GPU_OBCOLOR = 64 +} GPUBuiltin; + +typedef enum GPUBlendMode { + GPU_BLEND_SOLID = 0, + GPU_BLEND_ADD = 1, + GPU_BLEND_ALPHA = 2, + GPU_BLEND_CLIP = 4 +} GPUBlendMode; + +typedef struct GPUNodeStack { + GPUType type; + char *name; + float vec[4]; + struct GPUNodeLink *link; + short hasinput; + short hasoutput; + short sockettype; +} GPUNodeStack; + +GPUNodeLink *GPU_attribute(int type, char *name); +GPUNodeLink *GPU_uniform(float *num); +GPUNodeLink *GPU_dynamic_uniform(float *num); +GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser); +GPUNodeLink *GPU_texture(int size, float *pixels); +GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex); +GPUNodeLink *GPU_socket(GPUNodeStack *sock); +GPUNodeLink *GPU_builtin(GPUBuiltin builtin); + +int GPU_link(GPUMaterial *mat, char *name, ...); +int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...); + +void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); +void GPU_material_enable_alpha(GPUMaterial *material); +GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[4]); + +/* High level functions to create and use GPU materials */ + +GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma); +void GPU_material_free(struct Material *ma); + +void GPU_materials_free(); + +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time); +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]); +void GPU_material_unbind(GPUMaterial *material); +int GPU_material_bound(GPUMaterial *material); + +void GPU_material_vertex_attributes(GPUMaterial *material, + struct GPUVertexAttribs *attrib); + +/* Exported shading */ + +typedef struct GPUShadeInput { + GPUMaterial *gpumat; + struct Material *mat; + + GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref; + GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb; +} GPUShadeInput; + +typedef struct GPUShadeResult { + GPUNodeLink *diff, *spec, *combined, *alpha; +} GPUShadeResult; + +void GPU_shadeinput_set(GPUMaterial *mat, struct Material *ma, GPUShadeInput *shi); +void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr); + +/* Lamps */ + +GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par); +void GPU_lamp_free(struct Object *ob); + +int GPU_lamp_has_shadow_buffer(GPULamp *lamp); +void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]); +void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); + +void GPU_lamp_update(GPULamp *lamp, int lay, float obmat[][4]); +int GPU_lamp_shadow_layer(GPULamp *lamp); + +#ifdef __cplusplus +} +#endif + +#endif /*__GPU_MATERIAL__*/ + diff --git a/source/blender/gpu/Makefile b/source/blender/gpu/Makefile new file mode 100644 index 00000000000..b9bde147115 --- /dev/null +++ b/source/blender/gpu/Makefile @@ -0,0 +1,37 @@ +# +# $Id$ +# +# ***** 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. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# Makes module object directory and bounces make to subdirectories. + +SOURCEDIR = source/blender/gpu +DIRS = intern + +include nan_subdirs.mk diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript new file mode 100644 index 00000000000..8ccd4b7b24c --- /dev/null +++ b/source/blender/gpu/SConscript @@ -0,0 +1,11 @@ +#!/usr/bin/python +Import ('env') + +sources = env.Glob('intern/*.c') + +incs = '../blenlib ../blenkernel ../makesdna ../include' +incs += ' #/extern/glew/include #intern/guardedalloc ../imbuf .' + +incs += ' ' + env['BF_OPENGL_INC'] + +env.BlenderLib ( 'bf_gpu', sources, Split(incs), [], libtype=['core', 'player'], priority=[65, 20] ) diff --git a/source/blender/gpu/intern/Makefile b/source/blender/gpu/intern/Makefile new file mode 100644 index 00000000000..733ee3f764c --- /dev/null +++ b/source/blender/gpu/intern/Makefile @@ -0,0 +1,53 @@ +# +# $Id$ +# +# ***** 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. +# +# The Original Code is: all of this file. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# + +LIBNAME = gpu +DIR = $(OCGDIR)/blender/$(LIBNAME) + +include nan_compile.mk + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) + CFLAGS += -funsigned-char +endif + +CFLAGS += $(LEVEL_1_C_WARNINGS) + +CPPFLAGS += -I$(OPENGL_HEADERS) + +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../blenkernel +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_GLEW)/include +CPPFLAGS += -I../ + diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c new file mode 100644 index 00000000000..78a99cab447 --- /dev/null +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -0,0 +1,1441 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GL/glew.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_customdata_types.h" +#include "DNA_image_types.h" +#include "DNA_listBase.h" +#include "DNA_material_types.h" + +#include "BLI_dynstr.h" +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_heap.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" + +#include "GPU_material.h" +#include "GPU_extensions.h" + +#include "BLO_sys_types.h" // for intptr_t support + +#include "gpu_codegen.h" + +#include +#include + +#ifdef _WIN32 +#ifndef vsnprintf +#define vsnprintf _vsnprintf +#endif +#ifndef snprintf +#define snprintf _snprintf +#endif +#endif + +extern char datatoc_gpu_shader_material_glsl[]; +extern char datatoc_gpu_shader_vertex_glsl[]; + +/* structs and defines */ + +typedef enum GPUDataSource { + GPU_SOURCE_VEC_UNIFORM, + GPU_SOURCE_BUILTIN, + GPU_SOURCE_TEX_PIXEL, + GPU_SOURCE_TEX, + GPU_SOURCE_ATTRIB +} GPUDataSource; + +static char* GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4", + 0, 0, 0, 0, "mat3", 0, 0, 0, 0, 0, 0, "mat4"}; + +struct GPUNode { + struct GPUNode *next, *prev; + + char *name; + int tag; + + ListBase inputs; + ListBase outputs; +}; + +struct GPUNodeLink { + GPUNodeStack *socket; + + int attribtype; + char *attribname; + + int image; + + int texture; + int texturesize; + + void *ptr1, *ptr2; + + int dynamic; + + int type; + int users; + + GPUTexture *dynamictex; + + GPUBuiltin builtin; + + struct GPUOutput *output; +}; + +typedef struct GPUOutput { + struct GPUOutput *next, *prev; + + GPUNode *node; + int type; /* data type = length of vector/matrix */ + GPUNodeLink *link; /* output link */ + int id; /* unique id as created by code generator */ +} GPUOutput; + +typedef struct GPUInput { + struct GPUInput *next, *prev; + + GPUNode *node; + + int type; /* datatype */ + int source; /* data source */ + + int id; /* unique id as created by code generator */ + int texid; /* number for multitexture */ + int attribid; /* id for vertex attributes */ + int bindtex; /* input is responsible for binding the texture? */ + int definetex; /* input is responsible for defining the pixel? */ + int textarget; /* GL_TEXTURE_* */ + int textype; /* datatype */ + + struct Image *ima; /* image */ + struct ImageUser *iuser;/* image user */ + float *dynamicvec; /* vector data in case it is dynamic */ + GPUTexture *tex; /* input texture, only set at runtime */ + int shaderloc; /* id from opengl */ + char shadername[32]; /* name in shader */ + + float vec[16]; /* vector data */ + GPUNodeLink *link; + int dynamictex; /* dynamic? */ + int attribtype; /* attribute type */ + char attribname[32]; /* attribute name */ + int attribfirst; /* this is the first one that is bound */ + GPUBuiltin builtin; /* builtin uniform */ +} GPUInput; + +struct GPUPass { + struct GPUPass *next, *prev; + + ListBase inputs; + struct GPUOutput *output; + struct GPUShader *shader; +}; + +/* Strings utility */ + +static void BLI_dynstr_printf(DynStr *dynstr, const char *format, ...) +{ + va_list args; + int retval; + char str[2048]; + + va_start(args, format); + retval = vsnprintf(str, sizeof(str), format, args); + va_end(args); + + if (retval >= sizeof(str)) + fprintf(stderr, "BLI_dynstr_printf: limit exceeded\n"); + else + BLI_dynstr_append(dynstr, str); +} + +/* GLSL code parsing for finding function definitions. + * These are stored in a hash for lookup when creating a material. */ + +static GHash *FUNCTION_HASH= NULL; +static char *FUNCTION_PROTOTYPES= NULL; +static GPUShader *FUNCTION_LIB= NULL; + +static int gpu_str_prefix(char *str, char *prefix) +{ + while(*str && *prefix) { + if(*str != *prefix) + return 0; + + str++; + prefix++; + } + + return (*prefix == '\0'); +} + +static char *gpu_str_skip_token(char *str, char *token, int max) +{ + int len = 0; + + /* skip a variable/function name */ + while(*str) { + if(ELEM6(*str, ' ', '(', ')', ',', '\t', '\n')) + break; + else { + if(token && len < max-1) { + *token= *str; + token++; + len++; + } + str++; + } + } + + if(token) + *token= '\0'; + + /* skip the next special characters: + * note the missing ')' */ + while(*str) { + if(ELEM5(*str, ' ', '(', ',', '\t', '\n')) + str++; + else + break; + } + + return str; +} + +static void gpu_parse_functions_string(GHash *hash, char *code) +{ + GPUFunction *function; + int i, type, qual; + + while((code = strstr(code, "void "))) { + function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); + + code = gpu_str_skip_token(code, NULL, 0); + code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME); + + /* get parameters */ + while(*code && *code != ')') { + /* test if it's an input or output */ + qual = FUNCTION_QUAL_IN; + if(gpu_str_prefix(code, "out ")) + qual = FUNCTION_QUAL_OUT; + if(gpu_str_prefix(code, "inout ")) + qual = FUNCTION_QUAL_INOUT; + if((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in ")) + code = gpu_str_skip_token(code, NULL, 0); + + /* test for type */ + type= 0; + for(i=1; i<=16; i++) { + if(GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) { + type= i; + break; + } + } + + if(!type && gpu_str_prefix(code, "sampler2DShadow")) + type= GPU_SHADOW2D; + if(!type && gpu_str_prefix(code, "sampler1D")) + type= GPU_TEX1D; + if(!type && gpu_str_prefix(code, "sampler2D")) + type= GPU_TEX2D; + + if(type) { + /* add paramater */ + code = gpu_str_skip_token(code, NULL, 0); + code = gpu_str_skip_token(code, NULL, 0); + function->paramqual[function->totparam]= qual; + function->paramtype[function->totparam]= type; + function->totparam++; + } + else { + fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name); + break; + } + } + + if(strlen(function->name) == 0 || function->totparam == 0) { + fprintf(stderr, "GPU functions parse error.\n"); + MEM_freeN(function); + break; + } + + BLI_ghash_insert(hash, function->name, function); + } +} + +static char *gpu_generate_function_prototyps(GHash *hash) +{ + DynStr *ds = BLI_dynstr_new(); + GHashIterator *ghi; + GPUFunction *function; + char *name, *prototypes; + int a; + + /* automatically generate function prototypes to add to the top of the + * generated code, to avoid have to add the actual code & recompile all */ + ghi = BLI_ghashIterator_new(hash); + + for(; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) { + name = BLI_ghashIterator_getValue(ghi); + function = BLI_ghashIterator_getValue(ghi); + + BLI_dynstr_printf(ds, "void %s(", name); + for(a=0; atotparam; a++) { + if(function->paramqual[a] == FUNCTION_QUAL_OUT) + BLI_dynstr_append(ds, "out "); + else if(function->paramqual[a] == FUNCTION_QUAL_INOUT) + BLI_dynstr_append(ds, "inout "); + + if(function->paramtype[a] == GPU_TEX1D) + BLI_dynstr_append(ds, "sampler1D"); + else if(function->paramtype[a] == GPU_TEX2D) + BLI_dynstr_append(ds, "sampler2D"); + else if(function->paramtype[a] == GPU_SHADOW2D) + BLI_dynstr_append(ds, "sampler2DShadow"); + else + BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); + + //BLI_dynstr_printf(ds, " param%d", a); + + if(a != function->totparam-1) + BLI_dynstr_append(ds, ", "); + } + BLI_dynstr_append(ds, ");\n"); + } + + BLI_dynstr_append(ds, "\n"); + + prototypes = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return prototypes; +} + +GPUFunction *GPU_lookup_function(char *name) +{ + if(!FUNCTION_HASH) { + FUNCTION_HASH = BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + gpu_parse_functions_string(FUNCTION_HASH, datatoc_gpu_shader_material_glsl); + FUNCTION_PROTOTYPES = gpu_generate_function_prototyps(FUNCTION_HASH); + FUNCTION_LIB = GPU_shader_create_lib(datatoc_gpu_shader_material_glsl); + } + + return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, name); +} + +void GPU_extensions_exit(void) +{ + extern Material defmaterial; // render module abuse... + + if(defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial); + + if(FUNCTION_HASH) { + BLI_ghash_free(FUNCTION_HASH, NULL, (GHashValFreeFP)MEM_freeN); + FUNCTION_HASH = NULL; + } + if(FUNCTION_PROTOTYPES) { + MEM_freeN(FUNCTION_PROTOTYPES); + FUNCTION_PROTOTYPES = NULL; + } + if(FUNCTION_LIB) { + GPU_shader_free(FUNCTION_LIB); + FUNCTION_LIB = NULL; + } +} + +/* GLSL code generation */ + +static void codegen_convert_datatype(DynStr *ds, int from, int to, char *tmp, int id) +{ + char name[1024]; + + snprintf(name, sizeof(name), "%s%d", tmp, id); + + if (from == to) { + BLI_dynstr_append(ds, name); + } + else if (to == GPU_FLOAT) { + if (from == GPU_VEC4) + BLI_dynstr_printf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name); + else if (from == GPU_VEC3) + BLI_dynstr_printf(ds, "dot(%s, vec3(0.33))", name); + else if (from == GPU_VEC2) + BLI_dynstr_printf(ds, "%s.r", name); + } + else if (to == GPU_VEC2) { + if (from == GPU_VEC4) + BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name); + else if (from == GPU_VEC3) + BLI_dynstr_printf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name); + else if (from == GPU_FLOAT) + BLI_dynstr_printf(ds, "vec2(%s, 1.0)", name); + } + else if (to == GPU_VEC3) { + if (from == GPU_VEC4) + BLI_dynstr_printf(ds, "%s.rgb", name); + else if (from == GPU_VEC2) + BLI_dynstr_printf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_printf(ds, "vec3(%s, %s, %s)", name, name, name); + } + else { + if (from == GPU_VEC3) + BLI_dynstr_printf(ds, "vec4(%s, 1.0)", name); + else if (from == GPU_VEC2) + BLI_dynstr_printf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_printf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); + } +} + +static void codegen_print_datatype(DynStr *ds, int type, float *data) +{ + int i; + + BLI_dynstr_printf(ds, "%s(", GPU_DATATYPE_STR[type]); + + for(i=0; ilink) + return 0; + else if(input->ima) + return 1; + else + return input->tex != 0; +} + +char *GPU_builtin_name(GPUBuiltin builtin) +{ + if(builtin == GPU_VIEW_MATRIX) + return "unfviewmat"; + else if(builtin == GPU_OBJECT_MATRIX) + return "unfobmat"; + else if(builtin == GPU_INVERSE_VIEW_MATRIX) + return "unfinvviewmat"; + else if(builtin == GPU_INVERSE_OBJECT_MATRIX) + return "unfinvobmat"; + else if(builtin == GPU_VIEW_POSITION) + return "varposition"; + else if(builtin == GPU_VIEW_NORMAL) + return "varnormal"; + else if(builtin == GPU_OBCOLOR) + return "unfobcolor"; + else + return ""; +} + +static void codegen_set_unique_ids(ListBase *nodes) +{ + GHash *bindhash, *definehash; + GPUNode *node; + GPUInput *input; + GPUOutput *output; + int id = 1, texid = 0; + + bindhash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + definehash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + for (node=nodes->first; node; node=node->next) { + for (input=node->inputs.first; input; input=input->next) { + /* set id for unique names of uniform variables */ + input->id = id++; + input->bindtex = 0; + input->definetex = 0; + + /* set texid used for settings texture slot with multitexture */ + if (codegen_input_has_texture(input) && + ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL))) { + if (input->link) { + /* input is texture from buffer, assign only one texid per + buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->link)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link)); + } + else if(input->ima) { + /* input is texture from image, assign only one texid per + buffer to avoid sampling the same texture twice */ + if (!BLI_ghash_haskey(bindhash, input->ima)) { + input->texid = texid++; + input->bindtex = 1; + BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid)); + } + else + input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima)); + } + else { + /* input is user created texture, we know there there is + only one, so assign new texid */ + input->bindtex = 1; + input->texid = texid++; + } + + /* make sure this pixel is defined exactly once */ + if (input->source == GPU_SOURCE_TEX_PIXEL) { + if(input->ima) { + if (!BLI_ghash_haskey(definehash, input->ima)) { + input->definetex = 1; + BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid)); + } + } + else { + if (!BLI_ghash_haskey(definehash, input->link)) { + input->definetex = 1; + BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid)); + } + } + } + } + } + + for (output=node->outputs.first; output; output=output->next) + /* set id for unique names of tmp variables storing output */ + output->id = id++; + } + + BLI_ghash_free(bindhash, NULL, NULL); + BLI_ghash_free(definehash, NULL, NULL); +} + +static void codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes) +{ + GPUNode *node; + GPUInput *input; + char *name; + int builtins = 0; + + /* print uniforms */ + for (node=nodes->first; node; node=node->next) { + for (input=node->inputs.first; input; input=input->next) { + if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) { + /* create exactly one sampler for each texture */ + if (codegen_input_has_texture(input) && input->bindtex) + BLI_dynstr_printf(ds, "uniform %s samp%d;\n", + (input->textype == GPU_TEX1D)? "sampler1D": + (input->textype == GPU_TEX2D)? "sampler2D": "sampler2DShadow", + input->texid); + } + else if(input->source == GPU_SOURCE_BUILTIN) { + /* only define each builting uniform/varying once */ + if(!(builtins & input->builtin)) { + builtins |= input->builtin; + name = GPU_builtin_name(input->builtin); + + if(gpu_str_prefix(name, "unf")) { + BLI_dynstr_printf(ds, "uniform %s %s;\n", + GPU_DATATYPE_STR[input->type], name); + } + else { + BLI_dynstr_printf(ds, "varying %s %s;\n", + GPU_DATATYPE_STR[input->type], name); + } + } + } + else if (input->source == GPU_SOURCE_VEC_UNIFORM) { + if(input->dynamicvec) { + /* only create uniforms for dynamic vectors */ + BLI_dynstr_printf(ds, "uniform %s unf%d;\n", + GPU_DATATYPE_STR[input->type], input->id); + } + else { + /* for others use const so the compiler can do folding */ + BLI_dynstr_printf(ds, "const %s cons%d = ", + GPU_DATATYPE_STR[input->type], input->id); + codegen_print_datatype(ds, input->type, input->vec); + BLI_dynstr_append(ds, ";\n"); + } + } + else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + BLI_dynstr_printf(ds, "varying %s var%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + } + } + } + + BLI_dynstr_append(ds, "\n"); +} + +static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) +{ + GPUNode *node; + GPUInput *input; + GPUOutput *output; + + for (node=nodes->first; node; node=node->next) { + /* load pixels from textures */ + for (input=node->inputs.first; input; input=input->next) { + if (input->source == GPU_SOURCE_TEX_PIXEL) { + if (codegen_input_has_texture(input) && input->definetex) { + BLI_dynstr_printf(ds, "\tvec4 tex%d = texture2D(", input->texid); + BLI_dynstr_printf(ds, "samp%d, gl_TexCoord[%d].st);\n", + input->texid, input->texid); + } + } + } + + /* declare temporary variables for node output storage */ + for (output=node->outputs.first; output; output=output->next) + BLI_dynstr_printf(ds, "\t%s tmp%d;\n", + GPU_DATATYPE_STR[output->type], output->id); + } + + BLI_dynstr_append(ds, "\n"); +} + +static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput) +{ + GPUNode *node; + GPUInput *input; + GPUOutput *output; + + for (node=nodes->first; node; node=node->next) { + BLI_dynstr_printf(ds, "\t%s(", node->name); + + for (input=node->inputs.first; input; input=input->next) { + if (input->source == GPU_SOURCE_TEX) { + BLI_dynstr_printf(ds, "samp%d", input->texid); + if (input->link) + BLI_dynstr_printf(ds, ", gl_TexCoord[%d].st", input->texid); + } + else if (input->source == GPU_SOURCE_TEX_PIXEL) { + if (input->link && input->link->output) + codegen_convert_datatype(ds, input->link->output->type, input->type, + "tmp", input->link->output->id); + else + codegen_convert_datatype(ds, input->link->output->type, input->type, + "tex", input->texid); + } + else if(input->source == GPU_SOURCE_BUILTIN) + BLI_dynstr_printf(ds, "%s", GPU_builtin_name(input->builtin)); + else if(input->source == GPU_SOURCE_VEC_UNIFORM) { + if(input->dynamicvec) + BLI_dynstr_printf(ds, "unf%d", input->id); + else + BLI_dynstr_printf(ds, "cons%d", input->id); + } + else if (input->source == GPU_SOURCE_ATTRIB) + BLI_dynstr_printf(ds, "var%d", input->attribid); + + BLI_dynstr_append(ds, ", "); + } + + for (output=node->outputs.first; output; output=output->next) { + BLI_dynstr_printf(ds, "tmp%d", output->id); + if (output->next) + BLI_dynstr_append(ds, ", "); + } + + BLI_dynstr_append(ds, ");\n"); + } + + BLI_dynstr_append(ds, "\n\tgl_FragColor = "); + codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); + BLI_dynstr_append(ds, ";\n"); +} + +static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *name) +{ + DynStr *ds = BLI_dynstr_new(); + char *code; + + BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); + + codegen_set_unique_ids(nodes); + codegen_print_uniforms_functions(ds, nodes); + + //if(G.f & G_DEBUG) + // BLI_dynstr_printf(ds, "/* %s */\n", name); + + BLI_dynstr_append(ds, "void main(void)\n"); + BLI_dynstr_append(ds, "{\n"); + + codegen_declare_tmps(ds, nodes); + codegen_call_functions(ds, nodes, output); + + BLI_dynstr_append(ds, "}\n"); + + /* create shader */ + code = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + //if(G.f & G_DEBUG) printf("%s\n", code); + + return code; +} + +static char *code_generate_vertex(ListBase *nodes) +{ + DynStr *ds = BLI_dynstr_new(); + GPUNode *node; + GPUInput *input; + char *code; + + for (node=nodes->first; node; node=node->next) { + for (input=node->inputs.first; input; input=input->next) { + if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + BLI_dynstr_printf(ds, "attribute %s att%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + BLI_dynstr_printf(ds, "varying %s var%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + } + } + } + + BLI_dynstr_append(ds, "\n"); + BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl); + + for (node=nodes->first; node; node=node->next) + for (input=node->inputs.first; input; input=input->next) + if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + if(input->attribtype == CD_TANGENT) /* silly exception */ + BLI_dynstr_printf(ds, "\tvar%d = gl_NormalMatrix * ", input->attribid); + else + BLI_dynstr_printf(ds, "\tvar%d = ", input->attribid); + + BLI_dynstr_printf(ds, "att%d;\n", input->attribid); + } + + BLI_dynstr_append(ds, "}\n\n"); + + code = BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + + //if(G.f & G_DEBUG) printf("%s\n", code); + + return code; +} + +/* GPU pass binding/unbinding */ + +GPUShader *GPU_pass_shader(GPUPass *pass) +{ + return pass->shader; +} + +void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes) +{ + GPUShader *shader = pass->shader; + GPUNode *node; + GPUInput *next, *input; + ListBase *inputs = &pass->inputs; + int extract, z; + + memset(inputs, 0, sizeof(*inputs)); + + if(!shader) + return; + + GPU_shader_bind(shader); + + for (node=nodes->first; node; node=node->next) { + z = 0; + for (input=node->inputs.first; input; input=next, z++) { + next = input->next; + + /* attributes don't need to be bound, they already have + * an id that the drawing functions will use */ + if(input->source == GPU_SOURCE_ATTRIB || + input->source == GPU_SOURCE_BUILTIN) + continue; + + if (input->ima || input->tex) + snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); + else + snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); + + /* pass non-dynamic uniforms to opengl */ + extract = 0; + + if(input->ima || input->tex) { + if (input->bindtex) + extract = 1; + } + else if(input->dynamicvec) + extract = 1; + + if(extract) + input->shaderloc = GPU_shader_get_uniform(shader, input->shadername); + + /* extract nodes */ + if(extract) { + BLI_remlink(&node->inputs, input); + BLI_addtail(inputs, input); + } + } + } + + GPU_shader_unbind(shader); +} + +void GPU_pass_bind(GPUPass *pass, double time) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + GPU_shader_bind(shader); + + /* now bind the textures */ + for (input=inputs->first; input; input=input->next) { + if (input->ima) + input->tex = GPU_texture_from_blender(input->ima, input->iuser, time); + + if(input->ima || input->tex) { + if(input->tex) { + GPU_texture_bind(input->tex, input->texid); + GPU_shader_uniform_texture(shader, input->shaderloc, input->tex); + } + } + } +} + +void GPU_pass_update_uniforms(GPUPass *pass) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + /* pass dynamic inputs to opengl, others were removed */ + for (input=inputs->first; input; input=input->next) + if(!(input->ima || input->tex)) + GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1, + input->dynamicvec); +} + +void GPU_pass_unbind(GPUPass *pass) +{ + GPUInput *input; + GPUShader *shader = pass->shader; + ListBase *inputs = &pass->inputs; + + if (!shader) + return; + + for (input=inputs->first; input; input=input->next) { + if (input->tex) + if(input->bindtex) + GPU_texture_unbind(input->tex); + if (input->ima) + input->tex = 0; + } + + GPU_shader_unbind(shader); +} + +/* Node Link Functions */ + +GPUNodeLink *GPU_node_link_create(int type) +{ + GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink"); + link->type = type; + link->users++; + + return link; +} + +void GPU_node_link_free(GPUNodeLink *link) +{ + link->users--; + + if (link->users < 0) + fprintf(stderr, "GPU_node_link_free: negative refcount\n"); + + if (link->users == 0) { + if (link->output) + link->output->link = NULL; + MEM_freeN(link); + } +} + +/* Node Functions */ + +GPUNode *GPU_node_begin(char *name) +{ + GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode"); + + node->name = name; + + return node; +} + +void GPU_node_end(GPUNode *node) +{ + /* empty */ +} + +static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type) +{ + GPUInput *input; + GPUNode *outnode; + char *name; + + if(link->output) { + outnode = link->output->node; + name = outnode->name; + + if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { + input = MEM_dupallocN(outnode->inputs.first); + input->type = type; + if(input->link) + input->link->users++; + BLI_addtail(&node->inputs, input); + return; + } + } + + input = MEM_callocN(sizeof(GPUInput), "GPUInput"); + input->node = node; + + if(link->builtin) { + /* builtin uniform */ + input->type = type; + input->source = GPU_SOURCE_BUILTIN; + input->builtin = link->builtin; + + MEM_freeN(link); + } + else if(link->output) { + /* link to a node output */ + input->type = type; + input->source = GPU_SOURCE_TEX_PIXEL; + input->link = link; + link->users++; + } + else if(link->dynamictex) { + /* dynamic texture, GPUTexture is updated/deleted externally */ + input->type = type; + input->source = GPU_SOURCE_TEX; + + input->tex = link->dynamictex; + input->textarget = GL_TEXTURE_2D; + input->textype = type; + input->dynamictex = 1; + MEM_freeN(link); + } + else if(link->texture) { + /* small texture created on the fly, like for colorbands */ + input->type = GPU_VEC4; + input->source = GPU_SOURCE_TEX; + input->textype = type; + + if (type == GPU_TEX1D) { + input->tex = GPU_texture_create_1D(link->texturesize, link->ptr1); + input->textarget = GL_TEXTURE_1D; + } + else { + input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2); + input->textarget = GL_TEXTURE_2D; + } + + MEM_freeN(link->ptr1); + MEM_freeN(link); + } + else if(link->image) { + /* blender image */ + input->type = GPU_VEC4; + input->source = GPU_SOURCE_TEX; + + input->ima = link->ptr1; + input->textarget = GL_TEXTURE_2D; + input->textype = GPU_TEX2D; + MEM_freeN(link); + } + else if(link->attribtype) { + /* vertex attribute */ + input->type = type; + input->source = GPU_SOURCE_ATTRIB; + + input->attribtype = link->attribtype; + BLI_strncpy(input->attribname, link->attribname, sizeof(input->attribname)); + MEM_freeN(link); + } + else { + /* uniform vector */ + input->type = type; + input->source = GPU_SOURCE_VEC_UNIFORM; + + memcpy(input->vec, link->ptr1, type*sizeof(float)); + if(link->dynamic) + input->dynamicvec= link->ptr1; + MEM_freeN(link); + } + + BLI_addtail(&node->inputs, input); +} + +static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock) +{ + GPUNodeLink *link; + + if(sock->link) { + gpu_node_input_link(node, sock->link, sock->type); + } + else { + link = GPU_node_link_create(0); + link->ptr1 = sock->vec; + gpu_node_input_link(node, link, sock->type); + } +} + +void GPU_node_output(GPUNode *node, int type, char *name, GPUNodeLink **link) +{ + GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput"); + + output->type = type; + output->node = node; + + if (link) { + *link = output->link = GPU_node_link_create(type); + output->link->output = output; + + /* note: the caller owns the reference to the linkfer, GPUOutput + merely points to it, and if the node is destroyed it will + set that pointer to NULL */ + } + + BLI_addtail(&node->outputs, output); +} + +void GPU_inputs_free(ListBase *inputs) +{ + GPUInput *input; + + for(input=inputs->first; input; input=input->next) { + if(input->link) + GPU_node_link_free(input->link); + else if(input->tex && !input->dynamictex) + GPU_texture_free(input->tex); + } + + BLI_freelistN(inputs); +} + +void GPU_node_free(GPUNode *node) +{ + GPUOutput *output; + + GPU_inputs_free(&node->inputs); + + for (output=node->outputs.first; output; output=output->next) + if (output->link) { + output->link->output = NULL; + GPU_node_link_free(output->link); + } + + BLI_freelistN(&node->outputs); + MEM_freeN(node); +} + +void GPU_nodes_free(ListBase *nodes) +{ + GPUNode *node; + + while (nodes->first) { + node = nodes->first; + BLI_remlink(nodes, node); + GPU_node_free(node); + } +} + +/* vertex attributes */ + +void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *attribs) +{ + GPUNode *node; + GPUInput *input; + int a; + + /* convert attributes requested by node inputs to an array of layers, + * checking for duplicates and assigning id's starting from zero. */ + + memset(attribs, 0, sizeof(*attribs)); + + for(node=nodes->first; node; node=node->next) { + for(input=node->inputs.first; input; input=input->next) { + if(input->source == GPU_SOURCE_ATTRIB) { + for(a=0; atotlayer; a++) { + if(attribs->layer[a].type == input->attribtype && + strcmp(attribs->layer[a].name, input->attribname) == 0) + break; + } + + if(a == attribs->totlayer && a < GPU_MAX_ATTRIB) { + input->attribid = attribs->totlayer++; + input->attribfirst = 1; + + attribs->layer[a].type = input->attribtype; + attribs->layer[a].glindex = input->attribid; + BLI_strncpy(attribs->layer[a].name, input->attribname, + sizeof(attribs->layer[a].name)); + } + else + input->attribid = attribs->layer[a].glindex; + } + } + } +} + +void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin) +{ + GPUNode *node; + GPUInput *input; + + *builtin= 0; + + for(node=nodes->first; node; node=node->next) + for(input=node->inputs.first; input; input=input->next) + if(input->source == GPU_SOURCE_BUILTIN) + *builtin |= input->builtin; +} + +/* varargs linking */ + +GPUNodeLink *GPU_attribute(int type, char *name) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->attribtype= type; + link->attribname= name; + + return link; +} + +GPUNodeLink *GPU_uniform(float *num) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->ptr1= num; + link->ptr2= NULL; + + return link; +} + +GPUNodeLink *GPU_dynamic_uniform(float *num) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->ptr1= num; + link->ptr2= NULL; + link->dynamic= 1; + + return link; +} + +GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->image= 1; + link->ptr1= ima; + link->ptr2= iuser; + + return link; +} + +GPUNodeLink *GPU_texture(int size, float *pixels) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->texture = 1; + link->texturesize = size; + link->ptr1= pixels; + + return link; +} + +GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->dynamic = 1; + link->dynamictex = tex; + + return link; +} + +GPUNodeLink *GPU_socket(GPUNodeStack *sock) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->socket= sock; + + return link; +} + +GPUNodeLink *GPU_builtin(GPUBuiltin builtin) +{ + GPUNodeLink *link = GPU_node_link_create(0); + + link->builtin= builtin; + + return link; +} + +int GPU_link(GPUMaterial *mat, char *name, ...) +{ + GPUNode *node; + GPUFunction *function; + GPUNodeLink *link, **linkptr; + va_list params; + int i; + + function = GPU_lookup_function(name); + if(!function) { + fprintf(stderr, "GPU failed to find function %s\n", name); + return 0; + } + + node = GPU_node_begin(name); + + va_start(params, name); + for(i=0; itotparam; i++) { + if(function->paramqual[i] != FUNCTION_QUAL_IN) { + linkptr= va_arg(params, GPUNodeLink**); + GPU_node_output(node, function->paramtype[i], "", linkptr); + } + else { + link= va_arg(params, GPUNodeLink*); + gpu_node_input_link(node, link, function->paramtype[i]); + } + } + va_end(params); + + GPU_node_end(node); + + gpu_material_add_node(mat, node); + + return 1; +} + +int GPU_stack_link(GPUMaterial *mat, char *name, GPUNodeStack *in, GPUNodeStack *out, ...) +{ + GPUNode *node; + GPUFunction *function; + GPUNodeLink *link, **linkptr; + va_list params; + int i, totin, totout; + + function = GPU_lookup_function(name); + if(!function) { + fprintf(stderr, "GPU failed to find function %s\n", name); + return 0; + } + + node = GPU_node_begin(name); + totin = 0; + totout = 0; + + if(in) { + for(i = 0; in[i].type != GPU_NONE; i++) { + gpu_node_input_socket(node, &in[i]); + totin++; + } + } + + if(out) { + for(i = 0; out[i].type != GPU_NONE; i++) { + GPU_node_output(node, out[i].type, out[i].name, &out[i].link); + totout++; + } + } + + va_start(params, out); + for(i=0; itotparam; i++) { + if(function->paramqual[i] != FUNCTION_QUAL_IN) { + if(totout == 0) { + linkptr= va_arg(params, GPUNodeLink**); + GPU_node_output(node, function->paramtype[i], "", linkptr); + } + else + totout--; + } + else { + if(totin == 0) { + link= va_arg(params, GPUNodeLink*); + if(link->socket) + gpu_node_input_socket(node, link->socket); + else + gpu_node_input_link(node, link, function->paramtype[i]); + } + else + totin--; + } + } + va_end(params); + + GPU_node_end(node); + + gpu_material_add_node(mat, node); + + return 1; +} + +int GPU_link_changed(GPUNodeLink *link) +{ + GPUNode *node; + GPUInput *input; + char *name; + + if(link->output) { + node = link->output->node; + name = node->name; + + if(strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) { + input = node->inputs.first; + return (input->link != NULL); + } + + return 1; + } + else + return 0; +} + +/* Pass create/free */ + +void gpu_nodes_tag(GPUNodeLink *link) +{ + GPUNode *node; + GPUInput *input; + + if(!link->output) + return; + + node = link->output->node; + if(node->tag) + return; + + node->tag= 1; + for(input=node->inputs.first; input; input=input->next) + if(input->link) + gpu_nodes_tag(input->link); +} + +void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) +{ + GPUNode *node, *next; + + for(node=nodes->first; node; node=node->next) + node->tag= 0; + + gpu_nodes_tag(outlink); + + for(node=nodes->first; node; node=next) { + next = node->next; + + if(!node->tag) { + BLI_remlink(nodes, node); + GPU_node_free(node); + } + } +} + +GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name) +{ + GPUShader *shader; + GPUPass *pass; + char *vertexcode, *fragmentcode; + + if(!FUNCTION_LIB) { + GPU_nodes_free(nodes); + return NULL; + } + + /* prune unused nodes */ + gpu_nodes_prune(nodes, outlink); + + gpu_nodes_get_vertex_attributes(nodes, attribs); + gpu_nodes_get_builtin_flag(nodes, builtins); + + /* generate code and compile with opengl */ + fragmentcode = code_generate_fragment(nodes, outlink->output, name); + vertexcode = code_generate_vertex(nodes); + shader = GPU_shader_create(vertexcode, fragmentcode, FUNCTION_LIB); + MEM_freeN(fragmentcode); + MEM_freeN(vertexcode); + + /* failed? */ + if (!shader) { + memset(attribs, 0, sizeof(*attribs)); + memset(builtins, 0, sizeof(*builtins)); + GPU_nodes_free(nodes); + return NULL; + } + + /* create pass */ + pass = MEM_callocN(sizeof(GPUPass), "GPUPass"); + + pass->output = outlink->output; + pass->shader = shader; + + /* extract dynamic inputs and throw away nodes */ + GPU_nodes_extract_dynamic_inputs(pass, nodes); + GPU_nodes_free(nodes); + + return pass; +} + +void GPU_pass_free(GPUPass *pass) +{ + GPU_shader_free(pass->shader); + GPU_inputs_free(&pass->inputs); + MEM_freeN(pass); +} + diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h new file mode 100644 index 00000000000..53b52f24f16 --- /dev/null +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -0,0 +1,87 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __GPU_CODEGEN_H__ +#define __GPU_CODEGEN_H__ + +#include "DNA_listBase.h" + +struct ListBase; +struct GPUShader; +struct GPUOutput; +struct GPUNode; +struct GPUVertexAttribs; + +#define MAX_FUNCTION_NAME 64 +#define MAX_PARAMETER 32 + +#define FUNCTION_QUAL_IN 0 +#define FUNCTION_QUAL_OUT 1 +#define FUNCTION_QUAL_INOUT 2 + +typedef struct GPUFunction { + char name[MAX_FUNCTION_NAME]; + int paramtype[MAX_PARAMETER]; + int paramqual[MAX_PARAMETER]; + int totparam; +} GPUFunction; + +GPUFunction *GPU_lookup_function(char *name); + +/* Pass Generation + - Takes a list of nodes and a desired output, and makes a pass. This + will take ownership of the nodes and free them early if unused or + at the end if used. +*/ + +struct GPUPass; +typedef struct GPUPass GPUPass; + +GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, + struct GPUVertexAttribs *attribs, int *builtin, const char *name); + +struct GPUShader *GPU_pass_shader(GPUPass *pass); + +void GPU_pass_bind(GPUPass *pass, double time); +void GPU_pass_update_uniforms(GPUPass *pass); +void GPU_pass_unbind(GPUPass *pass); + +void GPU_pass_free(GPUPass *pass); + +/* Material calls */ + +char *GPU_builtin_name(GPUBuiltin builtin); +void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node); +int GPU_link_changed(struct GPUNodeLink *link); + +#endif + diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c new file mode 100644 index 00000000000..fe47fa3c60e --- /dev/null +++ b/source/blender/gpu/intern/gpu_draw.c @@ -0,0 +1,1168 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "GL/glew.h" + +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BKE_bmfont.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_utildefines.h" + +#include "GPU_extensions.h" +#include "GPU_material.h" +#include "GPU_draw.h" + +/* These are some obscure rendering functions shared between the + * game engine and the blender, in this module to avoid duplicaten + * and abstract them away from the rest a bit */ + +/* Text Rendering */ + +static void gpu_mcol(unsigned int ucol) +{ + /* mcol order is swapped */ + char *cp= (char *)&ucol; + glColor3ub(cp[3], cp[2], cp[1]); +} + +void GPU_render_text(MTFace *tface, int mode, + const char *textstr, int textlen, unsigned int *col, + float *v1, float *v2, float *v3, float *v4, int glattrib) +{ + if (mode & TF_BMFONT) { + Image* ima; + int characters, index, character; + float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; + + characters = textlen; + + ima = (Image*)tface->tpage; + if (ima == NULL) + characters = 0; + + // color has been set + if (tface->mode & TF_OBCOL) + col= NULL; + else if (!col) + glColor3f(1.0f, 1.0f, 1.0f); + + glPushMatrix(); + for (index = 0; index < characters; index++) { + float uv[4][2]; + + // lets calculate offset stuff + character = textstr[index]; + + // space starts at offset 1 + // character = character - ' ' + 1; + matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, + &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); + + uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx; + uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy; + uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx; + uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy; + uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx; + uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy; + + glBegin(GL_POLYGON); + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]); + else glTexCoord2fv(uv[0]); + if(col) gpu_mcol(col[0]); + glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); + + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[1]); + else glTexCoord2fv(uv[1]); + if(col) gpu_mcol(col[1]); + glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); + + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[2]); + else glTexCoord2fv(uv[2]); + if(col) gpu_mcol(col[2]); + glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); + + if(v4) { + uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx; + uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy; + + if(glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]); + else glTexCoord2fv(uv[3]); + if(col) gpu_mcol(col[3]); + glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); + } + glEnd(); + + glTranslatef(advance, 0.0, 0.0); + } + glPopMatrix(); + } +} + +/* Checking powers of two for images since opengl 1.x requires it */ + +static int is_pow2(int num) +{ + /* (n&(n-1)) zeros the least significant bit of n */ + return ((num)&(num-1))==0; +} + +static int smaller_pow2(int num) +{ + while (!is_pow2(num)) + num= num&(num-1); + + return num; +} + +static int is_pow2_limit(int num) +{ + /* take texture clamping into account */ + if (U.glreslimit != 0 && num > U.glreslimit) + return 0; + + return ((num)&(num-1))==0; +} + +static int smaller_pow2_limit(int num) +{ + /* take texture clamping into account */ + if (U.glreslimit != 0 && num > U.glreslimit) + return U.glreslimit; + + return smaller_pow2(num); +} + +/* Current OpenGL state caching for GPU_set_tpage */ + +static struct GPUTextureState { + int curtile, tile; + int curtilemode, tilemode; + int curtileXRep, tileXRep; + int curtileYRep, tileYRep; + Image *ima, *curima; + + int domipmap, linearmipmap; + + int alphamode; + MTFace *lasttface; +} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, -1, NULL}; + +/* Mipmap settings */ + +void GPU_set_mipmap(int mipmap) +{ + if (GTS.domipmap != (mipmap != 0)) { + GPU_free_images(); + GTS.domipmap = mipmap != 0; + } +} + +void GPU_set_linear_mipmap(int linear) +{ + if (GTS.linearmipmap != (linear != 0)) { + GPU_free_images(); + GTS.linearmipmap = linear != 0; + } +} + +static int gpu_get_mipmap(void) +{ + return GTS.domipmap && (!(G.f & G_TEXTUREPAINT)); +} + +static GLenum gpu_get_mipmap_filter() +{ + return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST; +} + +/* Set OpenGL state for an MTFace */ + +static void gpu_make_repbind(Image *ima) +{ + ImBuf *ibuf; + + ibuf = BKE_image_get_ibuf(ima, NULL); + if(ibuf==NULL) + return; + + if(ima->repbind) { + glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); + MEM_freeN(ima->repbind); + ima->repbind= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } + + ima->totbind= ima->xrep*ima->yrep; + + if(ima->totbind>1) + ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); +} + +static void gpu_clear_tpage() +{ + if(GTS.lasttface==0) + return; + + GTS.lasttface= 0; + GTS.curtile= 0; + GTS.curima= 0; + if(GTS.curtilemode!=0) { + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + GTS.curtilemode= 0; + GTS.curtileXRep=0; + GTS.curtileYRep=0; + GTS.alphamode= -1; + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_ALPHA_TEST); +} + +static void gpu_set_blend_mode(GPUBlendMode blendmode) +{ + if(blendmode == GPU_BLEND_SOLID) { + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else if(blendmode==GPU_BLEND_ADD) { + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glDisable(GL_ALPHA_TEST); + } + else if(blendmode==GPU_BLEND_ALPHA) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + /* if U.glalphaclip == 1.0, some cards go bonkers... + * turn off alpha test in this case */ + + /* added after 2.45 to clip alpha */ + if(U.glalphaclip == 1.0) { + glDisable(GL_ALPHA_TEST); + } + else { + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, U.glalphaclip); + } + } + else if(blendmode==GPU_BLEND_CLIP) { + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + } +} + +static void gpu_verify_alpha_mode(MTFace *tface) +{ + /* verify alpha blending modes */ + if(GTS.alphamode == tface->transp) + return; + + gpu_set_blend_mode(tface->transp); + GTS.alphamode= tface->transp; +} + +static void gpu_verify_reflection(Image *ima) +{ + if (ima && (ima->flag & IMA_REFLECT)) { + /* enable reflection mapping */ + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + } + else { + /* disable reflection mapping */ + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + } +} + +int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare) +{ + ImBuf *ibuf = NULL; + unsigned int *bind = NULL; + int rectw, recth, tpx=0, tpy=0, y; + unsigned int *rectrow, *tilerectrow; + unsigned int *tilerect= NULL, *scalerect= NULL, *rect= NULL; + short texwindx, texwindy, texwinsx, texwinsy; + + /* initialize tile mode and number of repeats */ + GTS.ima = ima; + GTS.tilemode= (tfmode & TF_TILES) || (ima && (ima->tpageflag & IMA_TWINANIM)); + GTS.tileXRep = 0; + GTS.tileYRep = 0; + + /* setting current tile according to frame */ + if(ima && (ima->tpageflag & IMA_TWINANIM)) + GTS.tile= ima->lastframe; + else + GTS.tile= tftile; + + if(ima) { + GTS.tileXRep = ima->xrep; + GTS.tileYRep = ima->yrep; + } + + /* if same image & tile, we're done */ + if(compare && ima == GTS.curima && GTS.curtile == GTS.tile && + GTS.tilemode == GTS.curtilemode && GTS.curtileXRep == GTS.tileXRep && + GTS.curtileYRep == GTS.tileYRep) + return (ima!=0); + + /* if tiling mode or repeat changed, change texture matrix to fit */ + if(GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep || + GTS.curtileYRep != GTS.tileYRep) { + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + if((tfmode & TF_TILES) && ima!=NULL) + glScalef(ima->xrep, ima->yrep, 1.0); + + glMatrixMode(GL_MODELVIEW); + } + + /* check if we have a valid image */ + if(ima==NULL || ima->ok==0) + return 0; + + /* check if we have a valid image buffer */ + ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf==NULL) + return 0; + + /* ensure we have a char buffer and not only float */ + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); + + if(GTS.tilemode) { + /* tiled mode */ + if(ima->repbind==0) gpu_make_repbind(ima); + if(GTS.tile>=ima->totbind) GTS.tile= 0; + + /* this happens when you change repeat buttons */ + if(ima->repbind) bind= &ima->repbind[GTS.tile]; + else bind= &ima->bindcode; + + if(*bind==0) { + + texwindx= ibuf->x/ima->xrep; + texwindy= ibuf->y/ima->yrep; + + if(GTS.tile>=ima->xrep*ima->yrep) + GTS.tile= ima->xrep*ima->yrep-1; + + texwinsy= GTS.tile / ima->xrep; + texwinsx= GTS.tile - texwinsy*ima->xrep; + + texwinsx*= texwindx; + texwinsy*= texwindy; + + tpx= texwindx; + tpy= texwindy; + + rect= ibuf->rect + texwinsy*ibuf->x + texwinsx; + } + } + else { + /* regular image mode */ + bind= &ima->bindcode; + + if(*bind==0) { + tpx= ibuf->x; + tpy= ibuf->y; + rect= ibuf->rect; + } + } + + if(*bind != 0) { + /* enable opengl drawing with textures */ + glBindTexture(GL_TEXTURE_2D, *bind); + return *bind; + } + + rectw = tpx; + recth = tpy; + + /* for tiles, copy only part of image into buffer */ + if (GTS.tilemode) { + tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); + + for (y=0; yx]; + tilerectrow= &tilerect[y*rectw]; + + memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); + } + + rect= tilerect; + } + + /* scale if not a power of two */ + if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { + rectw= smaller_pow2_limit(rectw); + recth= smaller_pow2_limit(recth); + + scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); + gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); + rect= scalerect; + } + + /* create image */ + glGenTextures(1, (GLuint *)bind); + glBindTexture( GL_TEXTURE_2D, *bind); + + if (!gpu_get_mipmap()) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else { + gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + ima->tpageflag |= IMA_MIPMAP_COMPLETE; + } + + /* set to modulate with vertex color */ + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + /* clean up */ + if (tilerect) + MEM_freeN(tilerect); + if (scalerect) + MEM_freeN(scalerect); + + return *bind; +} + +static void gpu_verify_repeat(Image *ima) +{ + /* set either clamp or repeat in X/Y */ + if (ima->tpageflag & IMA_CLAMP_U) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + + if (ima->tpageflag & IMA_CLAMP_V) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +} + +int GPU_set_tpage(MTFace *tface) +{ + Image *ima; + + /* check if we need to clear the state */ + if(tface==0) { + gpu_clear_tpage(); + return 0; + } + + ima= tface->tpage; + GTS.lasttface= tface; + + gpu_verify_alpha_mode(tface); + gpu_verify_reflection(ima); + + if(GPU_verify_image(ima, tface->tile, tface->mode, 1)) { + GTS.curtile= GTS.tile; + GTS.curima= GTS.ima; + GTS.curtilemode= GTS.tilemode; + GTS.curtileXRep = GTS.tileXRep; + GTS.curtileYRep = GTS.tileYRep; + + glEnable(GL_TEXTURE_2D); + } + else { + glDisable(GL_TEXTURE_2D); + + GTS.curtile= 0; + GTS.curima= 0; + GTS.curtilemode= 0; + GTS.curtileXRep = 0; + GTS.curtileYRep = 0; + + return 0; + } + + gpu_verify_repeat(ima); + + /* Did this get lost in the image recode? */ + /* tag_image_time(ima);*/ + + return 1; +} + +/* these two functions are called on entering and exiting texture paint mode, + temporary disabling/enabling mipmapping on all images for quick texture + updates with glTexSubImage2D. images that didn't change don't have to be + re-uploaded to OpenGL */ +void GPU_paint_set_mipmap(int mipmap) +{ + Image* ima; + + if(!GTS.domipmap) + return; + + if(mipmap) { + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + GPU_free_image(ima); + } + } + + } + else { + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->bindcode) { + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + } + } +} + +void GPU_paint_update_image(Image *ima, int x, int y, int w, int h) +{ + ImBuf *ibuf; + + ibuf = BKE_image_get_ibuf(ima, NULL); + + if (ima->repbind || gpu_get_mipmap() || !ima->bindcode || !ibuf || + (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || + (w == 0) || (h == 0)) { + /* these cases require full reload still */ + GPU_free_image(ima); + } + else { + /* for the special case, we can do a partial update + * which is much quicker for painting */ + GLint row_length, skip_pixels, skip_rows; + + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); + + if ((ibuf->rect==NULL) && ibuf->rect_float) + IMB_rect_from_float(ibuf); + + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei(GL_UNPACK_SKIP_ROWS, y); + + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_UNSIGNED_BYTE, ibuf->rect); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } +} + +void GPU_update_images_framechange(void) +{ + Image *ima; + + for(ima=G.main->image.first; ima; ima=ima->id.next) { + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) + ima->twend= ima->xrep*ima->yrep-1; + + /* check: is bindcode not in the array? free. (to do) */ + + ima->lastframe++; + if(ima->lastframe > ima->twend) + ima->lastframe= ima->twsta; + } + } +} + +int GPU_update_image_time(Image *ima, double time) +{ + int inc = 0; + float diff; + int newframe; + + if (!ima) + return 0; + + if (ima->lastupdate<0) + ima->lastupdate = 0; + + if (ima->lastupdate>time) + ima->lastupdate=(float)time; + + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; + + /* check: is the bindcode not in the array? Then free. (still to do) */ + + diff = (float)(time-ima->lastupdate); + inc = (int)(diff*(float)ima->animspeed); + + ima->lastupdate+=((float)inc/(float)ima->animspeed); + + newframe = ima->lastframe+inc; + + if(newframe > (int)ima->twend) { + if(ima->twend-ima->twsta != 0) + newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); + else + newframe = ima->twsta; + } + + ima->lastframe = newframe; + } + + return inc; +} + +void GPU_free_image(Image *ima) +{ + /* free regular image binding */ + if(ima->bindcode) { + glDeleteTextures(1, (GLuint *)&ima->bindcode); + ima->bindcode= 0; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } + + /* free glsl image binding */ + if(ima->gputexture) { + GPU_texture_free(ima->gputexture); + ima->gputexture= NULL; + } + + /* free repeated image binding */ + if(ima->repbind) { + glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); + + MEM_freeN(ima->repbind); + ima->repbind= NULL; + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + } +} + +void GPU_free_images(void) +{ + Image* ima; + + if(G.main) + for(ima=G.main->image.first; ima; ima=ima->id.next) + GPU_free_image(ima); +} + +/* OpenGL Materials */ + +/* materials start counting at # one.... */ +#define MAXMATBUF (MAXMAT+1) + +/* OpenGL state caching for materials */ + +static struct GPUMaterialState { + float matbuf[MAXMATBUF][2][4]; + int totmat; + + Material *gmatbuf[MAXMATBUF]; + Material *gboundmat; + Object *gob; + Scene *gscene; + + GPUBlendMode blendmode[MAXMATBUF]; + int alphapass; + + int lastmatnr, lastretval; + GPUBlendMode lastblendmode; +} GMS; + +Material *gpu_active_node_material(Material *ma) +{ + if(ma && ma->use_nodes && ma->nodetree) { + bNode *node= nodeGetActiveID(ma->nodetree, ID_MA); + + if(node) + return (Material *)node->id; + else + return NULL; + } + + return ma; +} + +void GPU_set_object_materials(Scene *scene, Object *ob, int glsl, int *do_alpha_pass) +{ + extern Material defmaterial; /* from material.c */ + Material *ma; + GPUMaterial *gpumat; + GPUBlendMode blendmode; + int a; + + /* initialize state */ + memset(&GMS, 0, sizeof(GMS)); + GMS.lastmatnr = -1; + GMS.lastretval = -1; + GMS.lastblendmode = GPU_BLEND_SOLID; + + GMS.gob = ob; + GMS.gscene = scene; + GMS.totmat= ob->totcol; + + GMS.alphapass = (G.vd && G.vd->transp); + if(do_alpha_pass) + *do_alpha_pass = 0; + + /* no materials assigned? */ + if(ob->totcol==0) { + GMS.matbuf[0][0][0]= defmaterial.r; + GMS.matbuf[0][0][1]= defmaterial.g; + GMS.matbuf[0][0][2]= defmaterial.b; + GMS.matbuf[0][0][3]= 1.0; + + GMS.matbuf[0][1][0]= defmaterial.specr; + GMS.matbuf[0][1][1]= defmaterial.specg; + GMS.matbuf[0][1][2]= defmaterial.specb; + GMS.matbuf[0][1][3]= 1.0; + + /* do material 1 too, for displists! */ + QUATCOPY(GMS.matbuf[1][0], GMS.matbuf[0][0]); + QUATCOPY(GMS.matbuf[1][1], GMS.matbuf[0][1]); + + if(glsl) { + GMS.gmatbuf[0]= &defmaterial; + GPU_material_from_blender(GMS.gscene, &defmaterial); + } + + GMS.blendmode[0]= GPU_BLEND_SOLID; + } + + /* setup materials */ + for(a=1; a<=ob->totcol; a++) { + /* find a suitable material */ + ma= give_current_material(ob, a); + if(!glsl) ma= gpu_active_node_material(ma); + if(ma==NULL) ma= &defmaterial; + + /* this shouldn't happen .. */ + if(a>=MAXMATBUF) + continue; + + /* create glsl material if requested */ + gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL; + + if(gpumat) { + /* do glsl only if creating it succeed, else fallback */ + GMS.gmatbuf[a]= ma; + blendmode = GPU_material_blend_mode(gpumat, ob->col); + } + else { + /* fixed function opengl materials */ + if (ma->mode & MA_SHLESS) { + GMS.matbuf[a][0][0]= ma->r; + GMS.matbuf[a][0][1]= ma->g; + GMS.matbuf[a][0][2]= ma->b; + } else { + GMS.matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r; + GMS.matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; + GMS.matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; + + GMS.matbuf[a][1][0]= ma->spec*ma->specr; + GMS.matbuf[a][1][1]= ma->spec*ma->specg; + GMS.matbuf[a][1][2]= ma->spec*ma->specb; + GMS.matbuf[a][1][3]= 1.0; + } + + blendmode = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA; + if(do_alpha_pass && GMS.alphapass) + GMS.matbuf[a][0][3]= ma->alpha; + else + GMS.matbuf[a][0][3]= 1.0f; + } + + /* setting do_alpha_pass = 1 indicates this object needs to be + * drawn in a second alpha pass for improved blending */ + if(do_alpha_pass) { + GMS.blendmode[a]= blendmode; + if(ELEM(blendmode, GPU_BLEND_ALPHA, GPU_BLEND_ADD) && !GMS.alphapass) + *do_alpha_pass= 1; + } + } + + /* let's start with a clean state */ + GPU_disable_material(); +} + +int GPU_enable_material(int nr, void *attribs) +{ + GPUVertexAttribs *gattribs = attribs; + GPUMaterial *gpumat; + GPUBlendMode blendmode; + + /* prevent index to use un-initialized array items */ + if(nr>GMS.totmat) + nr= GMS.totmat; + + if(gattribs) + memset(gattribs, 0, sizeof(*gattribs)); + + /* keep current material */ + if(nr>=MAXMATBUF || nr==GMS.lastmatnr) + return GMS.lastretval; + + /* unbind glsl material */ + if(GMS.gboundmat) { + if(GMS.alphapass) glDepthMask(0); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); + GMS.gboundmat= NULL; + } + + /* draw materials with alpha in alpha pass */ + GMS.lastmatnr = nr; + GMS.lastretval = ELEM(GMS.blendmode[nr], GPU_BLEND_SOLID, GPU_BLEND_CLIP); + if(GMS.alphapass) + GMS.lastretval = !GMS.lastretval; + + if(GMS.lastretval) { + if(gattribs && GMS.gmatbuf[nr]) { + /* bind glsl material and get attributes */ + Material *mat = GMS.gmatbuf[nr]; + + gpumat = GPU_material_from_blender(GMS.gscene, mat); + GPU_material_vertex_attributes(gpumat, gattribs); + GPU_material_bind(gpumat, GMS.gob->lay, G.vd->lay, 1.0); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, G.vd->viewmat, G.vd->viewinv, GMS.gob->col); + GMS.gboundmat= mat; + + if(GMS.alphapass) glDepthMask(1); + } + else { + /* or do fixed function opengl material */ + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, GMS.matbuf[nr][0]); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, GMS.matbuf[nr][1]); + } + + /* set (alpha) blending mode */ + blendmode = (GMS.alphapass)? GPU_BLEND_ALPHA: GPU_BLEND_SOLID; + GPU_set_material_blend_mode(blendmode); + } + + return GMS.lastretval; +} + +void GPU_set_material_blend_mode(int blendmode) +{ + if(GMS.lastblendmode == blendmode) + return; + + gpu_set_blend_mode(blendmode); + GMS.lastblendmode = blendmode; +} + +int GPU_get_material_blend_mode(void) +{ + return GMS.lastblendmode; +} + +void GPU_disable_material(void) +{ + GMS.lastmatnr= -1; + GMS.lastretval= 1; + + if(GMS.gboundmat) { + if(GMS.alphapass) glDepthMask(0); + GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat)); + GMS.gboundmat= NULL; + } + + GPU_set_material_blend_mode(GPU_BLEND_SOLID); +} + +/* Lights */ + +int GPU_default_lights(void) +{ + int a, count = 0; + + /* initialize */ + if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { + U.light[0].flag= 1; + U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; + U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; + U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; + U.light[0].spec[3]= 1.0; + + U.light[1].flag= 0; + U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; + U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; + U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; + U.light[1].spec[3]= 1.0; + + U.light[2].flag= 0; + U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; + U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; + U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; + U.light[2].spec[3]= 1.0; + } + + glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); + glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); + glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); + + glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); + glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); + glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); + + glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); + glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); + glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); + + for(a=0; a<8; a++) { + if(a<3) { + if(U.light[a].flag) { + glEnable(GL_LIGHT0+a); + count++; + } + else + glDisable(GL_LIGHT0+a); + + // clear stuff from other opengl lamp usage + glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); + glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); + } + else + glDisable(GL_LIGHT0+a); + } + + glDisable(GL_LIGHTING); + + glDisable(GL_COLOR_MATERIAL); + + return count; +} + +int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4]) +{ + Base *base; + Lamp *la; + int count; + float position[4], direction[4], energy[4]; + + /* disable all lights */ + for(count=0; count<8; count++) + glDisable(GL_LIGHT0+count); + + count= 0; + + for(base=scene->base.first; base; base=base->next) { + if(base->object->type!=OB_LAMP) + continue; + + if(!(base->lay & lay) || !(base->lay & ob->lay)) + continue; + + la= base->object->data; + + /* setup lamp transform */ + glPushMatrix(); + glLoadMatrixf((float *)viewmat); + + where_is_object_simul(base->object); + + if(la->type==LA_SUN) { + /* sun lamp */ + VECCOPY(position, base->object->obmat[2]); + direction[3]= 0.0; + + glLightfv(GL_LIGHT0+count, GL_POSITION, direction); + } + else { + /* other lamps with attenuation */ + VECCOPY(position, base->object->obmat[3]); + position[3]= 1.0f; + + glLightfv(GL_LIGHT0+count, GL_POSITION, position); + glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); + glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); + glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); + + if(la->type==LA_SPOT) { + /* spot lamp */ + direction[0]= -base->object->obmat[2][0]; + direction[1]= -base->object->obmat[2][1]; + direction[2]= -base->object->obmat[2][2]; + glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction); + glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0); + glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend); + } + else + glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); + } + + /* setup energy */ + energy[0]= la->energy*la->r; + energy[1]= la->energy*la->g; + energy[2]= la->energy*la->b; + energy[3]= 1.0; + + glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy); + glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy); + glEnable(GL_LIGHT0+count); + + glPopMatrix(); + + count++; + if(count==8) + break; + } + + return count; +} + +/* Default OpenGL State */ + +void GPU_state_init(void) +{ + /* also called when doing opengl rendering and in the game engine */ + float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; + float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; + float mat_shininess[] = { 35.0 }; + int a, x, y; + GLubyte pat[32*32]; + const GLubyte *patc= pat; + + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); + + GPU_default_lights(); + + /* no local viewer, looks ugly in ortho mode */ + /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ + + glDepthFunc(GL_LEQUAL); + /* scaling matrices */ + glEnable(GL_NORMALIZE); + + glShadeModel(GL_FLAT); + + glDisable(GL_ALPHA_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_FOG); + glDisable(GL_LIGHTING); + glDisable(GL_LOGIC_OP); + glDisable(GL_STENCIL_TEST); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + + /* default on, disable/enable should be local per function */ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); + + glPixelTransferi(GL_MAP_COLOR, GL_FALSE); + glPixelTransferi(GL_RED_SCALE, 1); + glPixelTransferi(GL_RED_BIAS, 0); + glPixelTransferi(GL_GREEN_SCALE, 1); + glPixelTransferi(GL_GREEN_BIAS, 0); + glPixelTransferi(GL_BLUE_SCALE, 1); + glPixelTransferi(GL_BLUE_BIAS, 0); + glPixelTransferi(GL_ALPHA_SCALE, 1); + glPixelTransferi(GL_ALPHA_BIAS, 0); + + glPixelTransferi(GL_DEPTH_BIAS, 0); + glPixelTransferi(GL_DEPTH_SCALE, 1); + glDepthRange(0.0, 1.0); + + a= 0; + for(x=0; x<32; x++) { + for(y=0; y<4; y++) { + if( (x) & 1) pat[a++]= 0x88; + else pat[a++]= 0x22; + } + } + + glPolygonStipple(patc); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glDisable(GL_CULL_FACE); +} + diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c new file mode 100644 index 00000000000..4c3090dd2c1 --- /dev/null +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -0,0 +1,984 @@ +/** + * $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. 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GL/glew.h" + +#include "DNA_listBase.h" +#include "DNA_image_types.h" +#include "DNA_userdef_types.h" + +#include "MEM_guardedalloc.h" + +#include "BKE_image.h" +#include "BKE_global.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BLI_blenlib.h" + +#include "GPU_draw.h" +#include "GPU_extensions.h" + +#include +#include +#include + +/* Extensions support */ + +/* extensions used: + - texture border clamp: 1.3 core + - fragement shader: 2.0 core + - framebuffer object: ext specification + - multitexture 1.3 core + - arb non power of two: 2.0 core + - pixel buffer objects? 2.1 core + - arb draw buffers? 2.0 core +*/ + +struct GPUGlobal { + GLint maxtextures; + GLuint currentfb; + int minimumsupport; +} GG = {1, 0, 0}; + +void GPU_extensions_init() +{ + glewInit(); + + /* glewIsSupported("GL_VERSION_2_0") */ + + if (GLEW_ARB_multitexture) + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &GG.maxtextures); + + GG.minimumsupport = 1; + if (!GLEW_ARB_multitexture) GG.minimumsupport = 0; + if (!GLEW_ARB_vertex_shader) GG.minimumsupport = 0; + if (!GLEW_ARB_fragment_shader) GG.minimumsupport = 0; +} + +int GPU_extensions_minimum_support() +{ + return GG.minimumsupport; +} + +int GPU_print_error(char *str) +{ + GLenum errCode; + + if (G.f & G_DEBUG) { + if ((errCode = glGetError()) != GL_NO_ERROR) { + fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode)); + return 1; + } + } + + return 0; +} + +static void GPU_print_framebuffer_error(GLenum status) +{ + fprintf(stderr, "GPUFrameBuffer: framebuffer incomplete error %d\n", + (int)status); + + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + fprintf(stderr, "Incomplete attachment.\n"); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + fprintf(stderr, "Unsupported framebuffer format.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + fprintf(stderr, "Missing attachment.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + fprintf(stderr, "Attached images must have same dimensions.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: + fprintf(stderr, "Attached images must have same format.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: + fprintf(stderr, "Missing draw buffer.\n"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: + fprintf(stderr, "Missing read buffer.\n"); + break; + default: + fprintf(stderr, "Unknown.\n"); + break; + } +} + +/* GPUTexture */ + +struct GPUTexture { + int w, h; /* width/height */ + int number; /* number for multitexture binding */ + int refcount; /* reference count */ + GLenum target; /* GL_TEXTURE_* */ + GLuint bindcode; /* opengl identifier for texture */ + int fromblender; /* we got the texture from Blender */ + + GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ + int depth; /* is a depth texture? */ +}; + +#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) +static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels) +{ + unsigned char *pixels, *p; + float *fp; + int a, len; + + len = 4*length; + fp = fpixels; + p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels"); + + for (a=0; aw = w; + tex->h = h; + tex->number = -1; + tex->refcount = 1; + tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; + tex->depth = depth; + + glGenTextures(1, &tex->bindcode); + + if (!tex->bindcode) { + fprintf(stderr, "GPUTexture: texture create failed: %d\n", + (int)glGetError()); + GPU_texture_free(tex); + return NULL; + } + + if (!GLEW_ARB_texture_non_power_of_two) { + tex->w = larger_pow2(tex->w); + tex->h = larger_pow2(tex->h); + } + + tex->number = 0; + glBindTexture(tex->target, tex->bindcode); + + if(depth) { + type = GL_UNSIGNED_BYTE; + format = GL_DEPTH_COMPONENT; + internalformat = GL_DEPTH_COMPONENT; + } + else { + type = GL_UNSIGNED_BYTE; + format = GL_RGBA; + internalformat = GL_RGBA8; + + if (fpixels) + pixels = GPU_texture_convert_pixels(w*h, fpixels); + } + + if (tex->target == GL_TEXTURE_1D) { + glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, 0); + + if (fpixels) { + glTexSubImage1D(tex->target, 0, 0, w, format, type, + pixels? pixels: fpixels); + + if (tex->w > w) + GPU_glTexSubImageEmpty(tex->target, format, w, 0, + tex->w-w, 1); + } + } + else { + glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, + format, type, 0); + + if (fpixels) { + glTexSubImage2D(tex->target, 0, 0, 0, w, h, + format, type, pixels? pixels: fpixels); + + if (tex->w > w) + GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); + if (tex->h > h) + GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); + } + } + + if (pixels) + MEM_freeN(pixels); + + if(depth) { + glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); + } + else { + glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (tex->target != GL_TEXTURE_1D) { + /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */ + GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER; + glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode); + glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode); + +#if 0 + float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); +#endif + } + else + glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + + return tex; +} + +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, double time) +{ + GPUTexture *tex; + GLint w, h, border, lastbindcode, bindcode; + + glGetIntegerv(GL_TEXTURE_BINDING_2D, &lastbindcode); + + GPU_update_image_time(ima, time); + bindcode = GPU_verify_image(ima, 0, 0, 0); + + if(ima->gputexture) { + ima->gputexture->bindcode = bindcode; + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return ima->gputexture; + } + + if(!bindcode) { + glBindTexture(GL_TEXTURE_2D, lastbindcode); + return NULL; + } + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_2D; + tex->fromblender = 1; + + ima->gputexture= tex; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error("Blender Texture"); + } + else { + glBindTexture(GL_TEXTURE_2D, tex->bindcode); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border); + + tex->w = w - border; + tex->h = h - border; + } + + glBindTexture(GL_TEXTURE_2D, lastbindcode); + + return tex; +} + +GPUTexture *GPU_texture_create_1D(int w, float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels) +{ + GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +GPUTexture *GPU_texture_create_depth(int w, int h) +{ + GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1); + + if (tex) + GPU_texture_unbind(tex); + + return tex; +} + +void GPU_texture_bind(GPUTexture *tex, int number) +{ + GLenum arbnumber; + + if (number >= GG.maxtextures) { + GPU_print_error("Not enough texture slots."); + return; + } + + if(number == -1) + return; + + GPU_print_error("Pre Texture Bind"); + + arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number); + if (number != 0) glActiveTextureARB(arbnumber); + glBindTexture(tex->target, tex->bindcode); + glEnable(tex->target); + if (number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); + + tex->number = number; + + GPU_print_error("Post Texture Bind"); +} + +void GPU_texture_unbind(GPUTexture *tex) +{ + GLenum arbnumber; + + if (tex->number >= GG.maxtextures) { + GPU_print_error("Not enough texture slots."); + return; + } + + if(tex->number == -1) + return; + + GPU_print_error("Pre Texture Unbind"); + + arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); + if (tex->number != 0) glActiveTextureARB(arbnumber); + glBindTexture(tex->target, 0); + glDisable(tex->target); + if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); + + tex->number = -1; + + GPU_print_error("Post Texture Unbind"); +} + +void GPU_texture_free(GPUTexture *tex) +{ + tex->refcount--; + + if (tex->refcount < 0) + fprintf(stderr, "GPUTexture: negative refcount\n"); + + if (tex->refcount == 0) { + if (tex->fb) + GPU_framebuffer_texture_detach(tex->fb, tex); + if (tex->bindcode && !tex->fromblender) + glDeleteTextures(1, &tex->bindcode); + + MEM_freeN(tex); + } +} + +void GPU_texture_ref(GPUTexture *tex) +{ + tex->refcount++; +} + +int GPU_texture_target(GPUTexture *tex) +{ + return tex->target; +} + +int GPU_texture_opengl_width(GPUTexture *tex) +{ + return tex->w; +} + +int GPU_texture_opengl_height(GPUTexture *tex) +{ + return tex->h; +} + +GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex) +{ + return tex->fb; +} + +/* GPUFrameBuffer */ + +struct GPUFrameBuffer { + GLuint object; + GPUTexture *colortex; + GPUTexture *depthtex; +}; + +GPUFrameBuffer *GPU_framebuffer_create() +{ + GPUFrameBuffer *fb; + + if (!GLEW_EXT_framebuffer_object) + return NULL; + + fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); + glGenFramebuffersEXT(1, &fb->object); + + if (!fb->object) { + fprintf(stderr, "GPUFFrameBuffer: framebuffer gen failed. %d\n", + (int)glGetError()); + GPU_framebuffer_free(fb); + return NULL; + } + + return fb; +} + +int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex) +{ + GLenum status; + GLenum attachment; + + if(tex->depth) + attachment = GL_DEPTH_ATTACHMENT_EXT; + else + attachment = GL_COLOR_ATTACHMENT0_EXT; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object); + GG.currentfb = fb->object; + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + tex->target, tex->bindcode, 0); + + if(tex->depth) { + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } + else { + glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadBuffer(GL_NONE); + } + + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + GPU_framebuffer_restore(); + GPU_print_framebuffer_error(status); + return 0; + } + + if(tex->depth) + fb->depthtex = tex; + else + fb->colortex = tex; + + tex->fb= fb; + + return 1; +} + +void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) +{ + GLenum attachment; + + if(!tex->fb) + return; + + if(GG.currentfb != tex->fb->object) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); + GG.currentfb = tex->fb->object; + } + + if(tex->depth) { + fb->depthtex = NULL; + attachment = GL_DEPTH_ATTACHMENT_EXT; + } + else { + fb->colortex = NULL; + attachment = GL_COLOR_ATTACHMENT0_EXT; + } + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, + tex->target, 0, 0); + + tex->fb = NULL; +} + +void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex) +{ + /* push attributes */ + glPushAttrib(GL_ENABLE_BIT); + glPushAttrib(GL_VIEWPORT_BIT); + glDisable(GL_SCISSOR_TEST); + + /* bind framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); + + /* push matrices and set default viewport and matrix */ + glViewport(0, 0, tex->w, tex->h); + GG.currentfb = tex->fb->object; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); +} + +void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex) +{ + /* restore matrix */ + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + /* restore attributes */ + glPopAttrib(); + glPopAttrib(); + glEnable(GL_SCISSOR_TEST); +} + +void GPU_framebuffer_free(GPUFrameBuffer *fb) +{ + if(fb->depthtex) + GPU_framebuffer_texture_detach(fb, fb->depthtex); + if(fb->colortex) + GPU_framebuffer_texture_detach(fb, fb->colortex); + + if(fb->object) { + glDeleteFramebuffersEXT(1, &fb->object); + + if (GG.currentfb == fb->object) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + GG.currentfb = 0; + } + } + + MEM_freeN(fb); +} + +void GPU_framebuffer_restore() +{ + if (GG.currentfb != 0) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + GG.currentfb = 0; + } +} + +/* GPUShader */ + +struct GPUShader { + GLhandleARB object; /* handle for full shader */ + GLhandleARB vertex; /* handle for vertex shader */ + GLhandleARB fragment; /* handle for fragment shader */ + GLhandleARB lib; /* handle for libment shader */ + int totattrib; /* total number of attributes */ +}; + +static void shader_print_errors(char *task, char *log, const char *code) +{ + const char *c, *pos, *end = code + strlen(code); + int line = 1; + + fprintf(stderr, "GPUShader: %s error:\n", task); + + if(G.f & G_DEBUG) { + c = code; + while ((c < end) && (pos = strchr(c, '\n'))) { + fprintf(stderr, "%2d ", line); + fwrite(c, (pos+1)-c, 1, stderr); + c = pos+1; + line++; + } + + fprintf(stderr, "%s", c); + } + + fprintf(stderr, "%s\n", log); +} + +GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUShader *lib) +{ + GLint status; + GLcharARB log[5000]; + GLsizei length = 0; + GPUShader *shader; + + if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) + return NULL; + + shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); + + if(vertexcode) + shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + if(fragcode) + shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + shader->object = glCreateProgramObjectARB(); + + if (!shader->object || + (vertexcode && !shader->vertex) || + (fragcode && !shader->fragment)) { + fprintf(stderr, "GPUShader, object creation failed.\n"); + GPU_shader_free(shader); + return NULL; + } + + if(vertexcode) { + glAttachObjectARB(shader->object, shader->vertex); + glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL); + + glCompileShaderARB(shader->vertex); + glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glGetInfoLogARB(shader->vertex, sizeof(log), &length, log); + shader_print_errors("compile", log, vertexcode); + + GPU_shader_free(shader); + return NULL; + } + } + + if(fragcode) { + glAttachObjectARB(shader->object, shader->fragment); + glShaderSourceARB(shader->fragment, 1, (const char**)&fragcode, NULL); + + glCompileShaderARB(shader->fragment); + glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glGetInfoLogARB(shader->fragment, sizeof(log), &length, log); + shader_print_errors("compile", log, fragcode); + + GPU_shader_free(shader); + return NULL; + } + } + + if(lib && lib->lib) + glAttachObjectARB(shader->object, lib->lib); + + glLinkProgramARB(shader->object); + glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status); + if (!status) { + glGetInfoLogARB(shader->object, sizeof(log), &length, log); + shader_print_errors("linking", log, fragcode); + + GPU_shader_free(shader); + return NULL; + } + + return shader; +} + +GPUShader *GPU_shader_create_lib(const char *code) +{ + GLint status; + GLcharARB log[5000]; + GLsizei length = 0; + GPUShader *shader; + + if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader) + return NULL; + + shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); + + shader->lib = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + + if (!shader->lib) { + fprintf(stderr, "GPUShader, object creation failed.\n"); + GPU_shader_free(shader); + return NULL; + } + + glShaderSourceARB(shader->lib, 1, (const char**)&code, NULL); + + glCompileShaderARB(shader->lib); + glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status); + + if (!status) { + glGetInfoLogARB(shader->lib, sizeof(log), &length, log); + shader_print_errors("compile", log, code); + + GPU_shader_free(shader); + return NULL; + } + + return shader; +} + +void GPU_shader_bind(GPUShader *shader) +{ + GPU_print_error("Pre Shader Bind"); + glUseProgramObjectARB(shader->object); + GPU_print_error("Post Shader Bind"); +} + +void GPU_shader_unbind() +{ + GPU_print_error("Pre Shader Unbind"); + glUseProgramObjectARB(0); + GPU_print_error("Post Shader Unbind"); +} + +void GPU_shader_free(GPUShader *shader) +{ + if (shader->lib) + glDeleteObjectARB(shader->lib); + if (shader->vertex) + glDeleteObjectARB(shader->vertex); + if (shader->fragment) + glDeleteObjectARB(shader->fragment); + if (shader->object) + glDeleteObjectARB(shader->object); + MEM_freeN(shader); +} + +int GPU_shader_get_uniform(GPUShader *shader, char *name) +{ + return glGetUniformLocationARB(shader->object, name); +} + +void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, int arraysize, float *value) +{ + if(location == -1) + return; + + GPU_print_error("Pre Uniform Vector"); + + if (length == 1) glUniform1fvARB(location, arraysize, value); + else if (length == 2) glUniform2fvARB(location, arraysize, value); + else if (length == 3) glUniform3fvARB(location, arraysize, value); + else if (length == 4) glUniform4fvARB(location, arraysize, value); + else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value); + else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value); + + GPU_print_error("Post Uniform Vector"); +} + +void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex) +{ + GLenum arbnumber; + + if (tex->number >= GG.maxtextures) { + GPU_print_error("Not enough texture slots."); + return; + } + + if(tex->number == -1) + return; + + if(location == -1) + return; + + GPU_print_error("Pre Uniform Texture"); + + arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number); + + if (tex->number != 0) glActiveTextureARB(arbnumber); + glBindTexture(tex->target, tex->bindcode); + glUniform1iARB(location, tex->number); + glEnable(tex->target); + if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB); + + GPU_print_error("Post Uniform Texture"); +} + +int GPU_shader_get_attribute(GPUShader *shader, char *name) +{ + int index; + + GPU_print_error("Pre Get Attribute"); + + index = glGetAttribLocationARB(shader->object, name); + + GPU_print_error("Post Get Attribute"); + + return index; +} + +#if 0 +/* GPUPixelBuffer */ + +typedef struct GPUPixelBuffer { + GLuint bindcode[2]; + GLuint current; + int datasize; + int numbuffers; + int halffloat; +} GPUPixelBuffer; + +void GPU_pixelbuffer_free(GPUPixelBuffer *pb) +{ + if (pb->bindcode[0]) + glDeleteBuffersARB(pb->numbuffers, pb->bindcode); + MEM_freeN(pb); +} + +GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffers) +{ + GPUPixelBuffer *pb; + + if (!GLEW_ARB_multitexture || !GLEW_EXT_pixel_buffer_object) + return NULL; + + pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO"); + pb->datasize = x*y*4*((halffloat)? 16: 8); + pb->numbuffers = numbuffers; + pb->halffloat = halffloat; + + glGenBuffersARB(pb->numbuffers, pb->bindcode); + + if (!pb->bindcode[0]) { + fprintf(stderr, "GPUPixelBuffer allocation failed\n"); + GPU_pixelbuffer_free(pb); + return NULL; + } + + return pb; +} + +void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb) +{ + void *pixels; + int i; + + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); + + for (i = 0; i < pb->numbuffers; i++) { + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->bindcode[pb->current]); + glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, pb->datasize, NULL, + GL_STREAM_DRAW_ARB); + + pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); + /*memcpy(pixels, _oImage.data(), pb->datasize);*/ + + if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { + fprintf(stderr, "Could not unmap opengl PBO\n"); + break; + } + } + + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); +} + +static int pixelbuffer_map_into_gpu(GLuint bindcode) +{ + void *pixels; + + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); + pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY); + + /* do stuff in pixels */ + + if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) { + fprintf(stderr, "Could not unmap opengl PBO\n"); + return 0; + } + + return 1; +} + +static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLuint bindcode) +{ + GLenum type = (pb->halffloat)? GL_HALF_FLOAT_NV: GL_UNSIGNED_BYTE; + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode); + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode); + + glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, + GL_RGBA, type, NULL); + + glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0); +} + +void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb) +{ + int newbuffer; + + if (pb->numbuffers == 1) { + pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[0]); + pixelbuffer_map_into_gpu(pb->bindcode[0]); + } + else { + pb->current = (pb->current+1)%pb->numbuffers; + newbuffer = (pb->current+1)%pb->numbuffers; + + pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]); + pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]); + } +} +#endif + diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c new file mode 100644 index 00000000000..d4da2866d96 --- /dev/null +++ b/source/blender/gpu/intern/gpu_material.c @@ -0,0 +1,1496 @@ +/** + * $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): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include + +#include "GL/glew.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_image_types.h" +#include "DNA_lamp_types.h" +#include "DNA_listBase.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_anim.h" +#include "BKE_colortools.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_scene.h" +#include "BKE_texture.h" +#include "BKE_utildefines.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "GPU_extensions.h" +#include "GPU_material.h" + +#include "gpu_codegen.h" + +#include + +/* Structs */ + +typedef enum DynMatProperty { + DYN_LAMP_CO = 1, + DYN_LAMP_VEC = 2, + DYN_LAMP_IMAT = 4, + DYN_LAMP_PERSMAT = 8, +} DynMatProperty; + +struct GPUMaterial { + Scene *scene; + Material *ma; + + /* for creating the material */ + ListBase nodes; + GPUNodeLink *outlink; + + /* for binding the material */ + GPUPass *pass; + GPUVertexAttribs attribs; + int bound; + int builtins; + int alpha, obcolalpha; + int dynproperty; + + /* for passing uniforms */ + int viewmatloc, invviewmatloc; + int obmatloc, invobmatloc; + int obcolloc; + + ListBase lamps; +}; + +struct GPULamp { + Scene *scene; + Object *ob; + Object *par; + Lamp *la; + + int type, mode, lay; + + float dynenergy, dyncol[3]; + float energy, col[3]; + + float co[3], vec[3]; + float dynco[3], dynvec[3]; + float obmat[4][4]; + float imat[4][4]; + float dynimat[4][4]; + + float spotsi, spotbl, k; + float dist, att1, att2; + + float bias, d, clipend; + int size; + + int falloff_type; + struct CurveMapping *curfalloff; + + float winmat[4][4]; + float viewmat[4][4]; + float persmat[4][4]; + float dynpersmat[4][4]; + + GPUFrameBuffer *fb; + GPUTexture *tex; + + ListBase materials; +}; + +/* Functions */ + +static GPUMaterial *GPU_material_construct_begin(Material *ma) +{ + GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); + + material->ma= ma; + + return material; +} + +static void gpu_material_set_attrib_id(GPUMaterial *material) +{ + GPUVertexAttribs *attribs; + GPUShader *shader; + GPUPass *pass; + char name[32]; + int a, b; + + attribs= &material->attribs; + pass= material->pass; + if(!pass) { + attribs->totlayer = 0; + return; + } + + shader= GPU_pass_shader(pass); + if(!shader) { + attribs->totlayer = 0; + return; + } + + /* convert from attribute number to the actual id assigned by opengl, + * in case the attrib does not get a valid index back, it was probably + * removed by the glsl compiler by dead code elimination */ + + for(a=0, b=0; atotlayer; a++) { + sprintf(name, "att%d", attribs->layer[a].glindex); + attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name); + + if(attribs->layer[a].glindex >= 0) { + attribs->layer[b] = attribs->layer[a]; + b++; + } + } + + attribs->totlayer = b; +} + +static int GPU_material_construct_end(GPUMaterial *material) +{ + if (material->outlink) { + GPUNodeLink *outlink; + GPUShader *shader; + + outlink = material->outlink; + material->pass = GPU_generate_pass(&material->nodes, outlink, + &material->attribs, &material->builtins, material->ma->id.name); + + if(!material->pass) + return 0; + + gpu_material_set_attrib_id(material); + + shader = GPU_pass_shader(material->pass); + + if(material->builtins & GPU_VIEW_MATRIX) + material->viewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_VIEW_MATRIX)); + if(material->builtins & GPU_INVERSE_VIEW_MATRIX) + material->invviewmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_VIEW_MATRIX)); + if(material->builtins & GPU_OBJECT_MATRIX) + material->obmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBJECT_MATRIX)); + if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) + material->invobmatloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_INVERSE_OBJECT_MATRIX)); + if(material->builtins & GPU_OBCOLOR) + material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR)); + + return 1; + } + + return 0; +} + +void GPU_material_free(Material *ma) +{ + LinkData *link; + LinkData *nlink, *mlink, *next; + + for(link=ma->gpumaterial.first; link; link=link->next) { + GPUMaterial *material = link->data; + + if(material->pass) + GPU_pass_free(material->pass); + + for(nlink=material->lamps.first; nlink; nlink=nlink->next) { + GPULamp *lamp = nlink->data; + + for(mlink=lamp->materials.first; mlink; mlink=next) { + next = mlink->next; + if(mlink->data == ma) + BLI_freelinkN(&lamp->materials, mlink); + } + } + + BLI_freelistN(&material->lamps); + + MEM_freeN(material); + } + + BLI_freelistN(&ma->gpumaterial); +} + +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time) +{ + if(material->pass) { + LinkData *nlink; + GPULamp *lamp; + + /* handle layer lamps */ + for(nlink=material->lamps.first; nlink; nlink=nlink->next) { + lamp= nlink->data; + + if((lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))) { + lamp->dynenergy = lamp->energy; + VECCOPY(lamp->dyncol, lamp->col); + } + else { + lamp->dynenergy = 0.0f; + lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; + } + } + + GPU_pass_bind(material->pass, time); + material->bound = 1; + } +} + +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[][4], float viewmat[][4], float viewinv[][4], float obcol[4]) +{ + if(material->pass) { + GPUShader *shader = GPU_pass_shader(material->pass); + LinkData *nlink; + GPULamp *lamp; + float invmat[4][4], col[4]; + + /* handle builtins */ + if(material->builtins & GPU_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); + } + if(material->builtins & GPU_INVERSE_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); + } + if(material->builtins & GPU_OBJECT_MATRIX) { + GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); + } + if(material->builtins & GPU_INVERSE_OBJECT_MATRIX) { + Mat4Invert(invmat, obmat); + GPU_shader_uniform_vector(shader, material->invobmatloc, 16, 1, (float*)invmat); + } + if(material->builtins & GPU_OBCOLOR) { + QUATCOPY(col, obcol); + CLAMP(col[3], 0.0f, 1.0f); + GPU_shader_uniform_vector(shader, material->obcolloc, 4, 1, col); + } + + /* update lamps */ + for(nlink=material->lamps.first; nlink; nlink=nlink->next) { + lamp= nlink->data; + + if(material->dynproperty & DYN_LAMP_VEC) { + VECCOPY(lamp->dynvec, lamp->vec); + Normalize(lamp->dynvec); + VecMulf(lamp->dynvec, -1.0f); + Mat4Mul3Vecfl(viewmat, lamp->dynvec); + } + + if(material->dynproperty & DYN_LAMP_CO) { + VECCOPY(lamp->dynco, lamp->co); + Mat4MulVecfl(viewmat, lamp->dynco); + } + + if(material->dynproperty & DYN_LAMP_IMAT) + Mat4MulMat4(lamp->dynimat, viewinv, lamp->imat); + if(material->dynproperty & DYN_LAMP_PERSMAT) + Mat4MulMat4(lamp->dynpersmat, viewinv, lamp->persmat); + } + + GPU_pass_update_uniforms(material->pass); + } +} + +void GPU_material_unbind(GPUMaterial *material) +{ + if (material->pass) { + material->bound = 0; + GPU_pass_unbind(material->pass); + } +} + +int GPU_material_bound(GPUMaterial *material) +{ + return material->bound; +} + +void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs) +{ + *attribs = material->attribs; +} + +void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) +{ + if(!material->outlink) + material->outlink= link; +} + +void GPU_material_enable_alpha(GPUMaterial *material) +{ + material->alpha= 1; +} + +GPUBlendMode GPU_material_blend_mode(GPUMaterial *material, float obcol[3]) +{ + if(material->alpha || (material->obcolalpha && obcol[3] < 1.0f)) + return GPU_BLEND_ALPHA; + else + return GPU_BLEND_SOLID; +} + +void gpu_material_add_node(GPUMaterial *material, GPUNode *node) +{ + BLI_addtail(&material->nodes, node); +} + +/* Code generation */ + +static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **lv, GPUNodeLink **dist) +{ + GPUNodeLink *visifac, *inpr; + + /* from get_lamp_visibility */ + if(lamp->type==LA_SUN || lamp->type==LA_HEMI) { + mat->dynproperty |= DYN_LAMP_VEC; + GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec), lv, dist, &visifac); + return visifac; + } + else { + mat->dynproperty |= DYN_LAMP_CO; + GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), lv, dist, &visifac); + + if(lamp->type==LA_AREA) + return visifac; + + switch(lamp->falloff_type) + { + case LA_FALLOFF_CONSTANT: + break; + case LA_FALLOFF_INVLINEAR: + GPU_link(mat, "lamp_falloff_invlinear", GPU_uniform(&lamp->dist), *dist, &visifac); + break; + case LA_FALLOFF_INVSQUARE: + GPU_link(mat, "lamp_falloff_invsquare", GPU_uniform(&lamp->dist), *dist, &visifac); + break; + case LA_FALLOFF_SLIDERS: + GPU_link(mat, "lamp_falloff_sliders", GPU_uniform(&lamp->dist), GPU_uniform(&lamp->att1), GPU_uniform(&lamp->att2), *dist, &visifac); + break; + case LA_FALLOFF_CURVE: + { + float *array; + int size; + + curvemapping_table_RGBA(lamp->curfalloff, &array, &size); + GPU_link(mat, "lamp_falloff_curve", GPU_uniform(&lamp->dist), GPU_texture(size, array), *dist, &visifac); + } + break; + } + + if(lamp->mode & LA_SPHERE) + GPU_link(mat, "lamp_visibility_sphere", GPU_uniform(&lamp->dist), *dist, visifac, &visifac); + + if(lamp->type == LA_SPOT) { + if(lamp->mode & LA_SQUARE) { + mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_IMAT; + GPU_link(mat, "lamp_visibility_spot_square", GPU_dynamic_uniform(lamp->dynvec), GPU_dynamic_uniform((float*)lamp->dynimat), *lv, &inpr); + } + else { + mat->dynproperty |= DYN_LAMP_VEC; + GPU_link(mat, "lamp_visibility_spot_circle", GPU_dynamic_uniform(lamp->dynvec), *lv, &inpr); + } + + GPU_link(mat, "lamp_visibility_spot", GPU_uniform(&lamp->spotsi), GPU_uniform(&lamp->spotbl), inpr, visifac, &visifac); + } + + GPU_link(mat, "lamp_visibility_clamp", visifac, &visifac); + + return visifac; + } +} + +#if 0 +static void area_lamp_vectors(LampRen *lar) +{ + float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac; + + /* make it smaller, so area light can be multisampled */ + multifac= 1.0f/sqrt((float)lar->ray_totsamp); + xsize *= multifac; + ysize *= multifac; + + /* corner vectors */ + lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; + lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; + lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + + /* corner vectors */ + lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; + lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; + lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + + /* corner vectors */ + lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0]; + lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1]; + lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2]; + + /* corner vectors */ + lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0]; + lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1]; + lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2]; + /* only for correction button size, matrix size works on energy */ + lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize); +} +#endif + +static void ramp_blend(GPUMaterial *mat, GPUNodeLink *fac, GPUNodeLink *col1, GPUNodeLink *col2, int type, GPUNodeLink **outcol) +{ + static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", + "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", + "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", + "mix_val", "mix_color"}; + + GPU_link(mat, names[type], fac, col1, col2, outcol); +} + +static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *fac, float rampfac, int type, GPUNodeLink *incol, GPUNodeLink **outcol) +{ + GPUNodeLink *tmp, *alpha, *col; + float *array; + int size; + + /* do colorband */ + colorband_table_RGBA(coba, &array, &size); + GPU_link(mat, "valtorgb", fac, GPU_texture(size, array), &col, &tmp); + + /* use alpha in fac */ + GPU_link(mat, "mtex_alpha_from_col", col, &alpha); + GPU_link(mat, "math_multiply", alpha, GPU_uniform(&rampfac), &fac); + + /* blending method */ + ramp_blend(mat, fac, incol, col, type, outcol); +} + +static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *fac; + + if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS)) { + if(ma->ramp_col) { + if(ma->rampin_col==MA_RAMP_IN_RESULT) { + GPU_link(mat, "ramp_rgbtobw", *diff, &fac); + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, *diff, diff); + } + } + } +} + +static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *rgb, GPUNodeLink **diff) +{ + GPUNodeLink *fac, *tmp, *addcol; + + if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS) && + ma->ramp_col && (ma->mode & MA_RAMP_COL)) { + /* MA_RAMP_IN_RESULT is exceptional */ + if(ma->rampin_col==MA_RAMP_IN_RESULT) { + addcol = shi->rgb; + } + else { + /* input */ + switch(ma->rampin_col) { + case MA_RAMP_IN_ENERGY: + GPU_link(mat, "ramp_rgbtobw", rgb, &fac); + break; + case MA_RAMP_IN_SHADER: + fac= is; + break; + case MA_RAMP_IN_NOR: + GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); + break; + default: + GPU_link(mat, "set_value_zero", &fac); + break; + } + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_col, fac, ma->rampfac_col, ma->rampblend_col, shi->rgb, &addcol); + } + } + else + addcol = shi->rgb; + + /* output to */ + GPU_link(mat, "shade_madd", *diff, rgb, addcol, diff); +} + +static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *fac; + + if(!(G.fileflags & G_FILE_GLSL_NO_RAMPS) && + ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT) { + GPU_link(mat, "ramp_rgbtobw", *spec, &fac); + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); + } +} + +static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *fac, *tmp; + + *spec = shi->specrgb; + + /* MA_RAMP_IN_RESULT is exception */ + if(ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) { + + /* input */ + switch(ma->rampin_spec) { + case MA_RAMP_IN_ENERGY: + fac = t; + break; + case MA_RAMP_IN_SHADER: + fac = is; + break; + case MA_RAMP_IN_NOR: + GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac); + break; + default: + GPU_link(mat, "set_value_zero", &fac); + break; + } + + /* colorband + blend */ + do_colorband_blend(mat, ma->ramp_spec, fac, ma->rampfac_spec, ma->rampblend_spec, *spec, spec); + } +} + +void add_user_list(ListBase *list, void *data) +{ + LinkData *link = MEM_callocN(sizeof(LinkData), "GPULinkData"); + link->data = data; + BLI_addtail(list, link); +} + +static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view; + GPUNodeLink *outcol, *specfac, *t, *shadfac; + float one = 1.0f; + + if((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW)) + return; + + vn= shi->vn; + view= shi->view; + + visifac= lamp_get_visibility(mat, lamp, &lv, &dist); + + /*if(ma->mode & MA_TANGENT_V) + GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/ + + GPU_link(mat, "shade_inp", vn, lv, &inp); + + if(lamp->mode & LA_NO_DIFF) { + GPU_link(mat, "shade_is_no_diffuse", &is); + } + else if(lamp->type == LA_HEMI) { + GPU_link(mat, "shade_is_hemi", inp, &is); + } + else { + if(lamp->type == LA_AREA) { + float area[4][4], areasize; + + memset(&area, 0, sizeof(area)); + memset(&areasize, 0, sizeof(areasize)); + mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO; + GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco), GPU_dynamic_uniform(lamp->dynvec), vn, GPU_uniform((float*)area), + GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp); + } + + is= inp; /* Lambert */ + + if(!(G.fileflags & G_FILE_GLSL_NO_SHADERS)) { + if(ma->diff_shader==MA_DIFF_ORENNAYAR) + GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is); + else if(ma->diff_shader==MA_DIFF_TOON) + GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); + else if(ma->diff_shader==MA_DIFF_MINNAERT) + GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is); + else if(ma->diff_shader==MA_DIFF_FRESNEL) + GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is); + } + } + + if(!(G.fileflags & G_FILE_GLSL_NO_SHADERS)) + if(ma->shade_flag & MA_CUBIC) + GPU_link(mat, "shade_cubic", is, &is); + + i = is; + GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i); + + vn = shi->vn; + /*if(ma->mode & MA_TANGENT_VN) + GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/ + + /* this replaces if(i > 0.0) conditional until that is supported */ + // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); + + if((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) { + if(!(G.fileflags & G_FILE_GLSL_NO_SHADOWS)) { + mat->dynproperty |= DYN_LAMP_PERSMAT; + + GPU_link(mat, "test_shadowbuf", + GPU_builtin(GPU_VIEW_POSITION), + GPU_dynamic_texture(lamp->tex), + GPU_dynamic_uniform((float*)lamp->dynpersmat), + GPU_uniform(&lamp->bias), inp, &shadfac); + + if(lamp->mode & LA_ONLYSHADOW) { + GPU_link(mat, "shade_only_shadow", i, shadfac, + GPU_dynamic_uniform(&lamp->dynenergy), &shadfac); + + if(!(lamp->mode & LA_NO_DIFF)) + GPU_link(mat, "shade_only_shadow_diffuse", shadfac, shi->rgb, + shr->diff, &shr->diff); + + if(!(lamp->mode & LA_NO_SPEC)) + GPU_link(mat, "shade_only_shadow_specular", shadfac, shi->specrgb, + shr->spec, &shr->spec); + + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, ma); + return; + } + + GPU_link(mat, "math_multiply", i, shadfac, &i); + } + } + else if((G.fileflags & G_FILE_GLSL_NO_SHADOWS) && (lamp->mode & LA_ONLYSHADOW)) { + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, ma); + return; + } + else + GPU_link(mat, "set_value", GPU_uniform(&one), &shadfac); + + if(GPU_link_changed(shi->refl) || ma->ref != 0.0f) { + if(!(lamp->mode & LA_NO_DIFF)) { + GPUNodeLink *rgb; + GPU_link(mat, "shade_mul_value", i, GPU_dynamic_uniform(lamp->dyncol), &rgb); + add_to_diffuse(mat, ma, shi, is, rgb, &shr->diff); + } + } + + if(G.fileflags & G_FILE_GLSL_NO_SHADERS); + else if(!(lamp->mode & LA_NO_SPEC) && !(lamp->mode & LA_ONLYSHADOW) && + (GPU_link_changed(shi->spec) || ma->spec != 0.0f)) { + if(lamp->type == LA_HEMI) { + GPU_link(mat, "shade_hemi_spec", vn, lv, view, GPU_uniform(&ma->spec), shi->har, visifac, &t); + GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol); + GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); + } + else { + if(ma->spec_shader==MA_SPEC_PHONG) + GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac); + else if(ma->spec_shader==MA_SPEC_COOKTORR) + GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac); + else if(ma->spec_shader==MA_SPEC_BLINN) + GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac); + else if(ma->spec_shader==MA_SPEC_WARDISO) + GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac); + else + GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac); + + if(lamp->type==LA_AREA) + GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac); + + GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t); + + if(ma->mode & MA_RAMP_SPEC) { + GPUNodeLink *spec; + do_specular_ramp(shi, specfac, t, &spec); + GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), spec, &outcol); + GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); + } + else { + GPU_link(mat, "shade_add_spec", t, GPU_dynamic_uniform(lamp->dyncol), shi->specrgb, &outcol); + GPU_link(mat, "shade_add", shr->spec, outcol, &shr->spec); + } + } + } + + add_user_list(&mat->lamps, lamp); + add_user_list(&lamp->materials, ma); +} + +static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) +{ + Base *base; + Object *ob; + Scene *sce; + GPULamp *lamp; + + for(SETLOOPER(shi->gpumat->scene, base)) { + ob= base->object; + + if(ob->type==OB_LAMP) { + lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL); + if(lamp) + shade_one_light(shi, shr, lamp); + } + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(shi->gpumat->scene, ob); + + for(dob=lb->first; dob; dob=dob->next) { + Object *ob = dob->ob; + + if(ob->type==OB_LAMP) { + Mat4CpyMat4(ob->obmat, dob->mat); + + lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, base->object); + if(lamp) + shade_one_light(shi, shr, lamp); + } + } + + free_object_duplilist(lb); + } + } +} + +static void texture_rgb_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, GPUNodeLink **in) +{ + switch(blendtype) { + case MTEX_BLEND: + GPU_link(mat, "mtex_rgb_blend", out, tex, fact, facg, in); + break; + case MTEX_MUL: + GPU_link(mat, "mtex_rgb_mul", out, tex, fact, facg, in); + break; + case MTEX_SCREEN: + GPU_link(mat, "mtex_rgb_screen", out, tex, fact, facg, in); + break; + case MTEX_OVERLAY: + GPU_link(mat, "mtex_rgb_overlay", out, tex, fact, facg, in); + break; + case MTEX_SUB: + GPU_link(mat, "mtex_rgb_sub", out, tex, fact, facg, in); + break; + case MTEX_ADD: + GPU_link(mat, "mtex_rgb_add", out, tex, fact, facg, in); + break; + case MTEX_DIV: + GPU_link(mat, "mtex_rgb_div", out, tex, fact, facg, in); + break; + case MTEX_DIFF: + GPU_link(mat, "mtex_rgb_diff", out, tex, fact, facg, in); + break; + case MTEX_DARK: + GPU_link(mat, "mtex_rgb_dark", out, tex, fact, facg, in); + break; + case MTEX_LIGHT: + GPU_link(mat, "mtex_rgb_light", out, tex, fact, facg, in); + break; + case MTEX_BLEND_HUE: + GPU_link(mat, "mtex_rgb_hue", out, tex, fact, facg, in); + break; + case MTEX_BLEND_SAT: + GPU_link(mat, "mtex_rgb_sat", out, tex, fact, facg, in); + break; + case MTEX_BLEND_VAL: + GPU_link(mat, "mtex_rgb_val", out, tex, fact, facg, in); + break; + case MTEX_BLEND_COLOR: + GPU_link(mat, "mtex_rgb_color", out, tex, fact, facg, in); + break; + default: + GPU_link(mat, "set_rgb_zero", &in); + break; + } +} + +static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, int blendtype, int flip, GPUNodeLink **in) +{ + float flipf = (flip)? 1.0f: 0.0; + + switch(blendtype) { + case MTEX_BLEND: + GPU_link(mat, "mtex_value_blend", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_MUL: + GPU_link(mat, "mtex_value_mul", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_SCREEN: + GPU_link(mat, "mtex_value_screen", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_SUB: + GPU_link(mat, "mtex_value_sub", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_ADD: + GPU_link(mat, "mtex_value_add", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_DIV: + GPU_link(mat, "mtex_value_div", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_DIFF: + GPU_link(mat, "mtex_value_diff", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_DARK: + GPU_link(mat, "mtex_value_dark", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + case MTEX_LIGHT: + GPU_link(mat, "mtex_value_light", out, tex, fact, facg, GPU_uniform(&flipf), in); + break; + default: + GPU_link(mat, "set_value_zero", &in); + break; + } +} + +static void do_material_tex(GPUShadeInput *shi) +{ + Material *ma= shi->mat; + GPUMaterial *mat= shi->gpumat; + MTex *mtex; + Tex *tex; + GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac; + GPUNodeLink *texco_norm, *texco_orco, *texco_object, *texco_tangent; + GPUNodeLink *texco_global, *texco_uv = NULL; + GPUNodeLink *colfac, *newnor, *varfac, *orn; + char *lastuvname = NULL; + float one = 1.0f, norfac, ofs[3]; + int tex_nr, rgbnor, talpha; + + GPU_link(mat, "set_value", GPU_uniform(&one), &stencil); + + GPU_link(mat, "texco_norm", GPU_builtin(GPU_VIEW_NORMAL), &texco_norm); + GPU_link(mat, "texco_orco", GPU_attribute(CD_ORCO, ""), &texco_orco); + GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), + GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), + GPU_builtin(GPU_VIEW_POSITION), &texco_object); + GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent); + GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX), + GPU_builtin(GPU_VIEW_POSITION), &texco_global); + + orn= texco_norm; + + /* go over texture slots */ + for(tex_nr=0; tex_nrseptex & (1<mtex[tex_nr]) { + mtex= ma->mtex[tex_nr]; + + tex= mtex->tex; + if(tex==0) continue; + + /* which coords */ + if(mtex->texco==TEXCO_ORCO) + texco= texco_orco; + else if(mtex->texco==TEXCO_OBJECT) + texco= texco_object; + else if(mtex->texco==TEXCO_NORM) + texco= texco_norm; + else if(mtex->texco==TEXCO_TANGENT) + texco= texco_object; + else if(mtex->texco==TEXCO_GLOB) + texco= texco_global; + else if(mtex->texco==TEXCO_REFL) + texco= shi->ref; + else if(mtex->texco==TEXCO_UV) { + if(1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) { + GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv); + lastuvname = mtex->uvname; + } + texco= texco_uv; + } + else + continue; + + /* in case of uv, this would just undo a multiplication in texco_uv */ + if(mtex->texco != TEXCO_UV) + GPU_link(mat, "mtex_2d_mapping", texco, &texco); + + if(mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f) + GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco); + + ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0]; + ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1]; + ofs[2] = 0.0f; + if(ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f) + GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco); + + talpha = 0; + rgbnor = 0; + + if(tex && tex->type == TEX_IMAGE && tex->ima) { + GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, NULL), &tin, &trgb, &tnor); + rgbnor= TEX_RGB; + + if(tex->imaflag & TEX_USEALPHA) + talpha= 1; + } + else continue; + + /* texture output */ + if((rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { + GPU_link(mat, "mtex_rgbtoint", trgb, &tin); + rgbnor -= TEX_RGB; + } + + if(mtex->texflag & MTEX_NEGATIVE) { + if(rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgb_invert", trgb, &trgb); + else + GPU_link(mat, "mtex_value_invert", tin, &tin); + } + + if(mtex->texflag & MTEX_STENCIL) { + if(rgbnor & TEX_RGB) + GPU_link(mat, "mtex_rgb_stencil", stencil, trgb, &stencil, &trgb); + else + GPU_link(mat, "mtex_value_stencil", stencil, tin, &stencil, &tin); + } + + /* mapping */ + if(mtex->mapto & (MAP_COL+MAP_COLSPEC)) { + /* stencil maps on the texture control slider, not texture intensity value */ + if(mtex->colfac == 1.0f) + colfac = stencil; + else + GPU_link(mat, "math_multiply", GPU_uniform(&mtex->colfac), stencil, &colfac); + + if((rgbnor & TEX_RGB)==0) { + GPU_link(mat, "set_rgb", GPU_uniform(&mtex->r), &tcol); + } + else { + GPU_link(mat, "set_rgba", trgb, &tcol); + + if(mtex->mapto & MAP_ALPHA) + GPU_link(mat, "set_value", stencil, &tin); + else if(talpha) + GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); + else + GPU_link(mat, "set_value_one", &tin); + } + + if(mtex->mapto & MAP_COL) + texture_rgb_blend(mat, tcol, shi->rgb, tin, colfac, mtex->blendtype, &shi->rgb); + + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_COLSPEC)) + texture_rgb_blend(mat, tcol, shi->specrgb, tin, colfac, mtex->blendtype, &shi->specrgb); + } + + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) { + if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; + else tex->norfac= mtex->norfac; + + if((tex->type==TEX_IMAGE) && (tex->imaflag & TEX_NORMALMAP)) { + tex->norfac = mtex->norfac; + + if(mtex->maptoneg & MAP_NORM) + GPU_link(mat, "mtex_negate_texnormal", tnor, &tnor); + + if(mtex->normapspace == MTEX_NSPACE_TANGENT) + GPU_link(mat, "mtex_nspace_tangent", GPU_attribute(CD_TANGENT, ""), shi->vn, tnor, &newnor); + else + newnor = tnor; + + norfac = MIN2(mtex->norfac, 1.0); + if(norfac == 1.0f && !GPU_link_changed(stencil)) { + shi->vn = newnor; + } + else { + tnorfac = GPU_uniform(&norfac); + + if(GPU_link_changed(stencil)) + GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac); + + GPU_link(mat, "mtex_blend_normal", tnorfac, shi->vn, newnor, &shi->vn); + } + } + + GPU_link(mat, "vec_math_negate", shi->vn, &orn); + GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); + } + + if((mtex->mapto & MAP_VARS)) { + if(mtex->varfac == 1.0f) + varfac = stencil; + else + GPU_link(mat, "math_multiply", GPU_uniform(&mtex->varfac), stencil, &varfac); + + if(rgbnor & TEX_RGB) { + if(talpha) + GPU_link(mat, "mtex_alpha_from_col", trgb, &tin); + else + GPU_link(mat, "mtex_rgbtoint", trgb, &tin); + } + + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_REF) { + int flip= mtex->maptoneg & MAP_REF; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->refl, tin, varfac, mtex->blendtype, flip, &shi->refl); + GPU_link(mat, "mtex_value_clamp_positive", shi->refl, &shi->refl); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_SPEC) { + int flip= mtex->maptoneg & MAP_SPEC; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->spec, tin, varfac, mtex->blendtype, flip, &shi->spec); + GPU_link(mat, "mtex_value_clamp_positive", shi->spec, &shi->spec); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_EMIT) { + int flip= mtex->maptoneg & MAP_EMIT; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->emit, tin, varfac, mtex->blendtype, flip, &shi->emit); + GPU_link(mat, "mtex_value_clamp_positive", shi->emit, &shi->emit); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_HAR) { + int flip= mtex->maptoneg & MAP_HAR; + GPU_link(mat, "mtex_har_divide", shi->har, &shi->har); + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->har, tin, varfac, mtex->blendtype, flip, &shi->har); + GPU_link(mat, "mtex_har_multiply_clamp", shi->har, &shi->har); + } + if(mtex->mapto & MAP_ALPHA) { + int flip= mtex->maptoneg & MAP_ALPHA; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->alpha, tin, varfac, mtex->blendtype, flip, &shi->alpha); + GPU_link(mat, "mtex_value_clamp", shi->alpha, &shi->alpha); + } + if(!(G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX) && mtex->mapto & MAP_AMB) { + int flip= mtex->maptoneg & MAP_AMB; + texture_value_blend(mat, GPU_uniform(&mtex->def_var), shi->amb, tin, varfac, mtex->blendtype, flip, &shi->amb); + GPU_link(mat, "mtex_value_clamp", shi->amb, &shi->amb); + } + } + } + } +} + +void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi) +{ + float hard = ma->har; + + memset(shi, 0, sizeof(*shi)); + + shi->gpumat = mat; + shi->mat = ma; + + GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb); + GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb); + GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn); + GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha); + GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl); + GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec); + GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit); + GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har); + GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb); + GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view); + GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol); + GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref); +} + +void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) +{ + GPUMaterial *mat= shi->gpumat; + GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac; + Material *ma= shi->mat; + World *world= mat->scene->world; + float linfac, logfac, misttype; + + memset(shr, 0, sizeof(*shr)); + + if(ma->mode & MA_VERTEXCOLP) + shi->rgb = shi->vcol; + + do_material_tex(shi); + + if(ma->mode & MA_ZTRA) + GPU_material_enable_alpha(mat); + + if((G.fileflags & G_FILE_GLSL_NO_LIGHTS) || (ma->mode & MA_SHLESS)) { + shr->combined = shi->rgb; + shr->alpha = shi->alpha; + } + else { + if(GPU_link_changed(shi->emit) || ma->emit != 0.0f) { + if((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) { + GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit); + GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff); + } + else + GPU_link(mat, "shade_mul_value", shi->emit, shi->rgb, &shr->diff); + } + else + GPU_link(mat, "set_rgb_zero", &shr->diff); + + GPU_link(mat, "set_rgb_zero", &shr->spec); + + material_lights(shi, shr); + + shr->combined = shr->diff; + shr->alpha = shi->alpha; + + if(world) { + /* exposure correction */ + if(world->exp!=0.0f || world->range!=1.0f) { + linfac= 1.0 + pow((2.0*world->exp + 0.5), -10); + logfac= log((linfac-1.0)/linfac)/world->range; + + GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac); + GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac); + + GPU_link(mat, "shade_exposure_correct", shr->combined, + ulinfac, ulogfac, &shr->combined); + GPU_link(mat, "shade_exposure_correct", shr->spec, + ulinfac, ulogfac, &shr->spec); + } + + /* ambient color */ + if(world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) { + if(GPU_link_changed(shi->amb) || ma->amb != 0.0f) + GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb), + GPU_uniform(&world->ambr), &shr->combined); + } + } + + if(ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined); + if(ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec); + + if(GPU_link_changed(shi->spec) || ma->spec != 0.0f) + GPU_link(mat, "shade_add", shr->combined, shr->spec, &shr->combined); + } + + GPU_link(mat, "mtex_alpha_to_col", shr->combined, shr->alpha, &shr->combined); + + if(ma->shade_flag & MA_OBCOLOR) + GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); + + if(world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) { + misttype = world->mistype; + + GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION), + GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist), + GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac); + + GPU_link(mat, "mix_blend", mistfac, shr->combined, + GPU_uniform(&world->horr), &shr->combined); + } + + if(!(ma->mode & MA_ZTRA)) { + if(world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f)) + GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr), + shr->combined, &shr->combined); + + GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined); + } + + if(ma->shade_flag & MA_OBCOLOR) { + mat->obcolalpha = 1; + GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); + } +} + +GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) +{ + GPUShadeInput shi; + GPUShadeResult shr; + + GPU_shadeinput_set(mat, ma, &shi); + GPU_shaderesult_set(&shi, &shr); + + return shr.combined; +} + +GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) +{ + GPUMaterial *mat; + GPUNodeLink *outlink; + LinkData *link; + + for(link=ma->gpumaterial.first; link; link=link->next) + if(((GPUMaterial*)link->data)->scene == scene) + return link->data; + + mat = GPU_material_construct_begin(ma); + mat->scene = scene; + + if(!(G.fileflags & G_FILE_GLSL_NO_NODES) && ma->nodetree && ma->use_nodes) { + ntreeGPUMaterialNodes(ma->nodetree, mat); + } + else { + outlink = GPU_blender_material(mat, ma); + GPU_material_output_link(mat, outlink); + } + + /*if(!GPU_material_construct_end(mat)) { + GPU_material_free(mat); + mat= NULL; + return 0; + }*/ + + GPU_material_construct_end(mat); + + link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); + link->data = mat; + BLI_addtail(&ma->gpumaterial, link); + + return mat; +} + +void GPU_materials_free() +{ + Object *ob; + Material *ma; + extern Material defmaterial; + + for(ma=G.main->mat.first; ma; ma=ma->id.next) + GPU_material_free(ma); + + GPU_material_free(&defmaterial); + + for(ob=G.main->object.first; ma; ma=ma->id.next) + GPU_lamp_free(ob); +} + +/* Lamps and shadow buffers */ + +void GPU_lamp_update(GPULamp *lamp, int lay, float obmat[][4]) +{ + float mat[4][4]; + + lamp->lay = lay; + + Mat4CpyMat4(mat, obmat); + Mat4Ortho(mat); + + VECCOPY(lamp->vec, mat[2]); + VECCOPY(lamp->co, mat[3]); + Mat4CpyMat4(lamp->obmat, mat); + Mat4Invert(lamp->imat, mat); +} + +static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) +{ + float temp, angle, pixsize, wsize; + + lamp->scene = scene; + lamp->ob = ob; + lamp->par = par; + lamp->la = la; + + /* add_render_lamp */ + lamp->mode = la->mode; + lamp->type = la->type; + + lamp->energy = la->energy; + if(lamp->mode & LA_NEG) lamp->energy= -lamp->energy; + + lamp->col[0]= la->r*lamp->energy; + lamp->col[1]= la->g*lamp->energy; + lamp->col[2]= la->b*lamp->energy; + + GPU_lamp_update(lamp, ob->lay, ob->obmat); + + lamp->spotsi= la->spotsize; + if(lamp->mode & LA_HALO) + if(lamp->spotsi > 170.0) + lamp->spotsi = 170.0; + lamp->spotsi= cos(M_PI*lamp->spotsi/360.0); + lamp->spotbl= (1.0 - lamp->spotsi)*la->spotblend; + lamp->k= la->k; + + lamp->dist= la->dist; + lamp->falloff_type= la->falloff_type; + lamp->att1= la->att1; + lamp->att2= la->att2; + lamp->curfalloff= la->curfalloff; + + /* initshadowbuf */ + lamp->bias = 0.02f*la->bias; + lamp->size = la->bufsize; + lamp->d= la->clipsta; + lamp->clipend= la->clipend; + + /* arbitrary correction for the fact we do no soft transition */ + lamp->bias *= 0.25f; + + /* makeshadowbuf */ + angle= saacos(lamp->spotsi); + temp= 0.5f*lamp->size*cos(angle)/sin(angle); + pixsize= (lamp->d)/temp; + wsize= pixsize*0.5f*lamp->size; + + i_window(-wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend, lamp->winmat); +} + +static void gpu_lamp_shadow_free(GPULamp *lamp) +{ + if(lamp->tex) + GPU_texture_free(lamp->tex); + if(lamp->fb) + GPU_framebuffer_free(lamp->fb); +} + +GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) +{ + Lamp *la; + GPULamp *lamp; + LinkData *link; + + for(link=ob->gpulamp.first; link; link=link->next) { + lamp = (GPULamp*)link->data; + + if(lamp->par == par && lamp->scene == scene) + return link->data; + } + + lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); + + link = MEM_callocN(sizeof(LinkData), "GPULampLink"); + link->data = lamp; + BLI_addtail(&ob->gpulamp, link); + + la = ob->data; + gpu_lamp_from_blender(scene, ob, par, la, lamp); + + if(la->type==LA_SPOT && (la->mode & LA_SHAD_BUF)) { + /* opengl */ + lamp->fb = GPU_framebuffer_create(); + if(!lamp->fb) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size); + if(!lamp->tex) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if(!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + GPU_framebuffer_restore(); + } + + return lamp; +} + +void GPU_lamp_free(Object *ob) +{ + GPULamp *lamp; + LinkData *link; + LinkData *nlink; + Material *ma; + + for(link=ob->gpulamp.first; link; link=link->next) { + lamp = link->data; + + while(lamp->materials.first) { + nlink = lamp->materials.first; + ma = nlink->data; + BLI_freelinkN(&lamp->materials, nlink); + + if(ma->gpumaterial.first) + GPU_material_free(ma); + } + + gpu_lamp_shadow_free(lamp); + + MEM_freeN(lamp); + } + + BLI_freelistN(&ob->gpulamp); +} + +int GPU_lamp_has_shadow_buffer(GPULamp *lamp) +{ + return (!(G.fileflags & G_FILE_GLSL_NO_SHADOWS) && + !(G.fileflags & G_FILE_GLSL_NO_LIGHTS) && + lamp->tex && lamp->fb); +} + +void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize, float winmat[][4]) +{ + float rangemat[4][4], persmat[4][4]; + + /* initshadowbuf */ + Mat4Invert(lamp->viewmat, lamp->obmat); + Normalize(lamp->viewmat[0]); + Normalize(lamp->viewmat[1]); + Normalize(lamp->viewmat[2]); + + /* makeshadowbuf */ + Mat4MulMat4(persmat, lamp->viewmat, lamp->winmat); + + /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ + Mat4One(rangemat); + rangemat[0][0] = 0.5f; + rangemat[1][1] = 0.5f; + rangemat[2][2] = 0.5f; + rangemat[3][0] = 0.5f; + rangemat[3][1] = 0.5f; + rangemat[3][2] = 0.5f; + + Mat4MulMat4(lamp->persmat, persmat, rangemat); + + /* opengl */ + GPU_framebuffer_texture_bind(lamp->fb, lamp->tex); + + /* set matrices */ + Mat4CpyMat4(viewmat, lamp->viewmat); + Mat4CpyMat4(winmat, lamp->winmat); + *winsize = lamp->size; +} + +void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) +{ + GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); + GPU_framebuffer_restore(); +} + +int GPU_lamp_shadow_layer(GPULamp *lamp) +{ + if(lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER|LA_LAYER_SHADOW))) + return lamp->lay; + else + return -1; +} + diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl b/source/blender/gpu/intern/gpu_shader_material.glsl new file mode 100644 index 00000000000..16ed38cb47d --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_material.glsl @@ -0,0 +1,1555 @@ + +float exp_blender(float f) +{ + return pow(2.71828182846, f); +} + +void rgb_to_hsv(vec4 rgb, out vec4 outcol) +{ + float cmax, cmin, h, s, v, cdelta; + vec3 c; + + cmax = max(rgb[0], max(rgb[1], rgb[2])); + cmin = min(rgb[0], min(rgb[1], rgb[2])); + cdelta = cmax-cmin; + + v = cmax; + if (cmax!=0.0) + s = cdelta/cmax; + else { + s = 0.0; + h = 0.0; + } + + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(cmax, cmax, cmax) - rgb.xyz)/cdelta; + + if (rgb.x==cmax) h = c[2] - c[1]; + else if (rgb.y==cmax) h = 2.0 + c[0] - c[2]; + else h = 4.0 + c[1] - c[0]; + + h /= 6.0; + + if (h<0.0) + h += 1.0; + } + + outcol = vec4(h, s, v, rgb.w); +} + +void hsv_to_rgb(vec4 hsv, out vec4 outcol) +{ + float i, f, p, q, t, h, s, v; + vec3 rgb; + + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; + + if(s==0.0) { + rgb = vec3(v, v, v); + } + else { + if(h==1.0) + h = 0.0; + + h *= 6.0; + i = floor(h); + f = h - i; + rgb = vec3(f, f, f); + p = v*(1.0-s); + q = v*(1.0-(s*f)); + t = v*(1.0-(s*(1.0-f))); + + if (i == 0.0) rgb = vec3(v, t, p); + else if (i == 1.0) rgb = vec3(q, v, p); + else if (i == 2.0) rgb = vec3(p, v, t); + else if (i == 3.0) rgb = vec3(p, q, v); + else if (i == 4.0) rgb = vec3(t, p, v); + else rgb = vec3(v, p, q); + } + + outcol = vec4(rgb, hsv.w); +} + +#define M_PI 3.14159265358979323846 + +/*********** SHADER NODES ***************/ + +void vcol_attribute(vec4 attvcol, out vec4 vcol) +{ + vcol = vec4(attvcol.x/255.0, attvcol.y/255.0, attvcol.z/255.0, 1.0); +} + +void uv_attribute(vec2 attuv, out vec3 uv) +{ + uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); +} + +void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 attvcol, out vec3 global, out vec3 local, out vec3 view, out vec3 orco, out vec3 uv, out vec3 normal, out vec4 vcol, out float frontback) +{ + local = co; + view = normalize(local); + global = (viewinvmat*vec4(local, 1.0)).xyz; + orco = attorco; + uv_attribute(attuv, uv); + normal = -normalize(nor); /* blender render normal is negated */ + vcol_attribute(attvcol, vcol); + frontback = 1.0; +} + +void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec) +{ + outvec = (mat * vec4(vec, 1.0)).xyz; + if(domin == 1.0) + outvec = max(outvec, minvec); + if(domax == 1.0) + outvec = min(outvec, maxvec); +} + +void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) +{ + outdepth = abs(co.z); + outdist = length(co); + outview = normalize(co); +} + +void math_add(float val1, float val2, out float outval) +{ + outval = val1 + val2; +} + +void math_subtract(float val1, float val2, out float outval) +{ + outval = val1 - val2; +} + +void math_multiply(float val1, float val2, out float outval) +{ + outval = val1 * val2; +} + +void math_divide(float val1, float val2, out float outval) +{ + if (val2 == 0.0) + outval = 0.0; + else + outval = val1 / val2; +} + +void math_sine(float val, out float outval) +{ + outval = sin(val); +} + +void math_cosine(float val, out float outval) +{ + outval = cos(val); +} + +void math_tangent(float val, out float outval) +{ + outval = tan(val); +} + +void math_asin(float val, out float outval) +{ + if (val <= 1.0 && val >= -1.0) + outval = asin(val); + else + outval = 0.0; +} + +void math_acos(float val, out float outval) +{ + if (val <= 1.0 && val >= -1.0) + outval = acos(val); + else + outval = 0.0; +} + +void math_atan(float val, out float outval) +{ + outval = atan(val); +} + +void math_pow(float val1, float val2, out float outval) +{ + if (val1 >= 0.0) + outval = pow(val1, val2); + else + outval = 0.0; +} + +void math_log(float val1, float val2, out float outval) +{ + if(val1 > 0.0 && val2 > 0.0) + outval= log2(val1) / log2(val2); + else + outval= 0.0; +} + +void math_max(float val1, float val2, out float outval) +{ + outval = max(val1, val2); +} + +void math_min(float val1, float val2, out float outval) +{ + outval = min(val1, val2); +} + +void math_round(float val, out float outval) +{ + outval= floor(val + 0.5); +} + +void math_less_than(float val1, float val2, out float outval) +{ + if(val1 < val2) + outval = 1.0; + else + outval = 0.0; +} + +void math_greater_than(float val1, float val2, out float outval) +{ + if(val1 > val2) + outval = 1.0; + else + outval = 0.0; +} + +void squeeze(float val, float width, float center, out float outval) +{ + outval = 1.0/(1.0 + pow(2.71828183, -((val-center)*width))); +} + +void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = v1 + v2; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0; +} + +void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = v1 - v2; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2]))/3.0; +} + +void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = v1 + v2; + outval = length(outvec); + outvec = normalize(outvec); +} + +void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = vec3(0, 0, 0); + outval = dot(v1, v2); +} + +void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval) +{ + outvec = cross(v1, v2); + outval = length(outvec); +} + +void vec_math_normalize(vec3 v, out vec3 outvec, out float outval) +{ + outval = length(v); + outvec = normalize(v); +} + +void vec_math_negate(vec3 v, out vec3 outv) +{ + outv = -v; +} + +void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot) +{ + outnor = dir; + outdot = -dot(dir, nor); +} + +void curves_vec(vec3 vec, sampler1D curvemap, out vec3 outvec) +{ + outvec.x = texture1D(curvemap, (vec.x + 1.0)*0.5).x; + outvec.y = texture1D(curvemap, (vec.y + 1.0)*0.5).y; + outvec.z = texture1D(curvemap, (vec.z + 1.0)*0.5).z; +} + +void curves_rgb(vec4 col, sampler1D curvemap, out vec4 outcol) +{ + outcol.r = texture1D(curvemap, texture1D(curvemap, col.r).a).r; + outcol.g = texture1D(curvemap, texture1D(curvemap, col.g).a).g; + outcol.b = texture1D(curvemap, texture1D(curvemap, col.b).a).b; + outcol.a = col.a; +} + +void set_value(float val, out float outval) +{ + outval = val; +} + +void set_rgb(vec3 col, out vec3 outcol) +{ + outcol = col; +} + +void set_rgba(vec4 col, out vec4 outcol) +{ + outcol = col; +} + +void set_value_zero(out float outval) +{ + outval = 0.0; +} + +void set_value_one(out float outval) +{ + outval = 1.0; +} + +void set_rgb_zero(out vec3 outval) +{ + outval = vec3(0.0); +} + +void set_rgba_zero(out vec4 outval) +{ + outval = vec4(0.0); +} + +void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col2, fac); + outcol.a = col1.a; +} + +void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 + col2, fac); + outcol.a = col1.a; +} + +void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 * col2, fac); + outcol.a = col1.a; +} + +void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = vec4(1.0) - (vec4(facm) + fac*(vec4(1.0) - col2))*(vec4(1.0) - col1); + outcol.a = col1.a; +} + +void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if(outcol.r < 0.5) + outcol.r *= facm + 2.0*fac*col2.r; + else + outcol.r = 1.0 - (facm + 2.0*fac*(1.0 - col2.r))*(1.0 - outcol.r); + + if(outcol.g < 0.5) + outcol.g *= facm + 2.0*fac*col2.g; + else + outcol.g = 1.0 - (facm + 2.0*fac*(1.0 - col2.g))*(1.0 - outcol.g); + + if(outcol.b < 0.5) + outcol.b *= facm + 2.0*fac*col2.b; + else + outcol.b = 1.0 - (facm + 2.0*fac*(1.0 - col2.b))*(1.0 - outcol.b); +} + +void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 - col2, fac); + outcol.a = col1.a; +} + +void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + if(col2.r != 0.0) outcol.r = facm*outcol.r + fac*outcol.r/col2.r; + if(col2.g != 0.0) outcol.g = facm*outcol.g + fac*outcol.g/col2.g; + if(col2.b != 0.0) outcol.b = facm*outcol.b + fac*outcol.b/col2.b; +} + +void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, abs(col1 - col2), fac); + outcol.a = col1.a; +} + +void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = min(col1.rgb, col2.rgb*fac); + outcol.a = col1.a; +} + +void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = max(col1.rgb, col2.rgb*fac); + outcol.a = col1.a; +} + +void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + outcol = col1; + + if(outcol.r != 0.0) { + float tmp = 1.0 - fac*col2.r; + if(tmp <= 0.0) + outcol.r = 1.0; + else if((tmp = outcol.r/tmp) > 1.0) + outcol.r = 1.0; + else + outcol.r = tmp; + } + if(outcol.g != 0.0) { + float tmp = 1.0 - fac*col2.g; + if(tmp <= 0.0) + outcol.g = 1.0; + else if((tmp = outcol.g/tmp) > 1.0) + outcol.g = 1.0; + else + outcol.g = tmp; + } + if(outcol.b != 0.0) { + float tmp = 1.0 - fac*col2.b; + if(tmp <= 0.0) + outcol.b = 1.0; + else if((tmp = outcol.b/tmp) > 1.0) + outcol.b = 1.0; + else + outcol.b = tmp; + } +} + +void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float tmp, facm = 1.0 - fac; + + outcol = col1; + + tmp = facm + fac*col2.r; + if(tmp <= 0.0) + outcol.r = 0.0; + else if((tmp = (1.0 - (1.0 - outcol.r)/tmp)) < 0.0) + outcol.r = 0.0; + else if(tmp > 1.0) + outcol.r = 1.0; + else + outcol.r = tmp; + + tmp = facm + fac*col2.g; + if(tmp <= 0.0) + outcol.g = 0.0; + else if((tmp = (1.0 - (1.0 - outcol.g)/tmp)) < 0.0) + outcol.g = 0.0; + else if(tmp > 1.0) + outcol.g = 1.0; + else + outcol.g = tmp; + + tmp = facm + fac*col2.b; + if(tmp <= 0.0) + outcol.b = 0.0; + else if((tmp = (1.0 - (1.0 - outcol.b)/tmp)) < 0.0) + outcol.b = 0.0; + else if(tmp > 1.0) + outcol.b = 1.0; + else + outcol.b = tmp; +} + +void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if(hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2; + rgb_to_hsv(outcol, hsv); + + if(hsv.y != 0.0) { + rgb_to_hsv(col2, hsv2); + + hsv.y = facm*hsv.y + fac*hsv2.y; + hsv_to_rgb(hsv, outcol); + } +} + +void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + vec4 hsv, hsv2; + rgb_to_hsv(col1, hsv); + rgb_to_hsv(col2, hsv2); + + hsv.z = facm*hsv.z + fac*hsv2.z; + hsv_to_rgb(hsv, outcol); +} + +void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) +{ + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; + + outcol = col1; + + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); + + if(hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv.y = hsv2.y; + hsv_to_rgb(hsv, tmp); + + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } +} + +void valtorgb(float fac, sampler1D colormap, out vec4 outcol, out float outalpha) +{ + outcol = texture1D(colormap, fac); + outalpha = outcol.a; +} + +void rgbtobw(vec4 color, out float outval) +{ + outval = color.r*0.35 + color.g*0.45 + color.b*0.2; +} + +void invert(float fac, vec4 col, out vec4 outcol) +{ + outcol.xyz = mix(col.xyz, vec3(1.0, 1.0, 1.0) - col.xyz, fac); + outcol.w = col.w; +} + +void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) +{ + vec4 hsv; + + rgb_to_hsv(col, hsv); + + hsv[0] += (hue - 0.5); + if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0; + hsv[1] *= sat; + if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0; + hsv[2] *= value; + if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0; + + hsv_to_rgb(hsv, outcol); + + outcol = mix(col, outcol, fac); +} + +void separate_rgb(vec4 col, out float r, out float g, out float b) +{ + r = col.r; + g = col.g; + b = col.b; +} + +void combine_rgb(float r, float g, float b, out vec4 col) +{ + col = vec4(r, g, b, 1.0); +} + +void output_node(vec4 rgb, float alpha, out vec4 outrgb) +{ + outrgb = vec4(rgb.rgb, alpha); +} + +/*********** TEXTURES ***************/ + +void texture_flip_blend(vec3 vec, out vec3 outvec) +{ + outvec = vec.yxz; +} + +void texture_blend_lin(vec3 vec, out float outval) +{ + outval = (1.0+vec.x)/2.0; +} + +void texture_blend_quad(vec3 vec, out float outval) +{ + outval = max((1.0+vec.x)/2.0, 0.0); + outval *= outval; +} + +void texture_wood_sin(vec3 vec, out float value, out vec4 color, out vec3 normal) +{ + float a = sqrt(vec.x*vec.x + vec.y*vec.y + vec.z*vec.z)*20.0; + float wi = 0.5 + 0.5*sin(a); + + value = wi; + color = vec4(wi, wi, wi, 1.0); + normal = vec3(0.0, 0.0, 0.0); +} + +void texture_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) +{ + color = texture2D(ima, (vec.xy + vec2(1.0, 1.0))*0.5); + value = 1.0; + + normal.x = 2.0*(color.r - 0.5); + normal.y = 2.0*(0.5 - color.g); + normal.z = 2.0*(color.b - 0.5); +} + +/************* MTEX *****************/ + +void texco_orco(vec3 attorco, out vec3 orco) +{ + orco = attorco; +} + +void texco_uv(vec2 attuv, out vec3 uv) +{ + /* disabled for now, works together with leaving out mtex_2d_mapping + uv = vec3(attuv*2.0 - vec2(1.0, 1.0), 0.0); */ + uv = vec3(attuv, 0.0); +} + +void texco_norm(vec3 normal, out vec3 outnormal) +{ + /* corresponds to shi->orn, which is negated so cancels + out blender normal negation */ + outnormal = normalize(normal); +} + +void texco_tangent(vec3 tangent, out vec3 outtangent) +{ + outtangent = normalize(tangent); +} + +void texco_global(mat4 viewinvmat, vec3 co, out vec3 global) +{ + global = (viewinvmat*vec4(co, 1.0)).xyz; +} + +void texco_object(mat4 viewinvmat, mat4 obinvmat, vec3 co, out vec3 object) +{ + object = (obinvmat*(viewinvmat*vec4(co, 1.0))).xyz; +} + +void texco_refl(vec3 vn, vec3 view, out vec3 ref) +{ + ref = view - 2.0*dot(vn, view)*vn; +} + +void shade_norm(vec3 normal, out vec3 outnormal) +{ + /* blender render normal is negated */ + outnormal = -normalize(normal); +} + +void mtex_rgb_blend(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-fact; + + incol = fact*texcol + facm*outcol; +} + +void mtex_rgb_mul(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-facg; + + incol = (facm + fact*texcol)*outcol; +} + +void mtex_rgb_screen(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-facg; + + incol = vec3(1.0) - (vec3(facm) + fact*(vec3(1.0) - texcol))*(vec3(1.0) - outcol); +} + +void mtex_rgb_overlay(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-facg; + + if(outcol.r < 0.5) + incol.r = outcol.r*(facm + 2.0*fact*texcol.r); + else + incol.r = 1.0 - (facm + 2.0*fact*(1.0 - texcol.r))*(1.0 - outcol.r); + + if(outcol.g < 0.5) + incol.g = outcol.g*(facm + 2.0*fact*texcol.g); + else + incol.g = 1.0 - (facm + 2.0*fact*(1.0 - texcol.g))*(1.0 - outcol.g); + + if(outcol.b < 0.5) + incol.b = outcol.b*(facm + 2.0*fact*texcol.b); + else + incol.b = 1.0 - (facm + 2.0*fact*(1.0 - texcol.b))*(1.0 - outcol.b); +} + +void mtex_rgb_sub(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + incol = -fact*facg*texcol + outcol; +} + +void mtex_rgb_add(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + incol = fact*facg*texcol + outcol; +} + +void mtex_rgb_div(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-fact; + + if(texcol.r != 0.0) incol.r = facm*outcol.r + fact*outcol.r/texcol.r; + if(texcol.g != 0.0) incol.g = facm*outcol.g + fact*outcol.g/texcol.g; + if(texcol.b != 0.0) incol.b = facm*outcol.b + fact*outcol.b/texcol.b; +} + +void mtex_rgb_diff(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm; + + fact *= facg; + facm = 1.0-fact; + + incol = facm*outcol + fact*abs(texcol - outcol); +} + +void mtex_rgb_dark(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm, col; + + fact *= facg; + facm = 1.0-fact; + + col = fact*texcol.r; + if(col < outcol.r) incol.r = col; else incol.r = outcol.r; + col = fact*texcol.g; + if(col < outcol.g) incol.g = col; else incol.g = outcol.g; + col = fact*texcol.b; + if(col < outcol.b) incol.b = col; else incol.b = outcol.b; +} + +void mtex_rgb_light(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + float facm, col; + + fact *= facg; + facm = 1.0-fact; + + col = fact*texcol.r; + if(col > outcol.r) incol.r = col; else incol.r = outcol.r; + col = fact*texcol.g; + if(col > outcol.g) incol.g = col; else incol.g = outcol.g; + col = fact*texcol.b; + if(col > outcol.b) incol.b = col; else incol.b = outcol.b; +} + +void mtex_rgb_hue(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_hue(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_rgb_sat(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_sat(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_rgb_val(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_val(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) +{ + vec4 col; + + mix_color(fact*facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; +} + +void mtex_value_vars(inout float fact, float facg, out float facm, float flip) +{ + fact *= facg; + facm = 1.0-fact; + + if(flip != 0.0) { + float tmp = fact; + fact = facm; + facm = tmp; + } +} + +void mtex_value_blend(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + incol = fact*texcol + facm*outcol; +} + +void mtex_value_mul(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + facm = 1.0 - facg; + incol = (facm + fact*texcol)*outcol; +} + +void mtex_value_screen(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + facm = 1.0 - facg; + incol = 1.0 - (facm + fact*(1.0 - texcol))*(1.0 - outcol); +} + +void mtex_value_sub(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + fact = -fact; + incol = fact*texcol + outcol; +} + +void mtex_value_add(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + fact = fact; + incol = fact*texcol + outcol; +} + +void mtex_value_div(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + if(texcol != 0.0) + incol = facm*outcol + fact*outcol/texcol; + else + incol = 0.0; +} + +void mtex_value_diff(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + incol = facm*outcol + fact*abs(texcol - outcol); +} + +void mtex_value_dark(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + float col = fact*texcol; + if(col < outcol) incol = col; else incol = outcol; +} + +void mtex_value_light(float outcol, float texcol, float fact, float facg, float flip, out float incol) +{ + float facm; + mtex_value_vars(fact, facg, facm, flip); + + float col = fact*texcol; + if(col > outcol) incol = col; else incol = outcol; +} + +void mtex_value_clamp_positive(float fac, out float outfac) +{ + outfac = max(fac, 0.0); +} + +void mtex_value_clamp(float fac, out float outfac) +{ + outfac = clamp(fac, 0.0, 1.0); +} + +void mtex_har_divide(float har, out float outhar) +{ + outhar = har/128.0; +} + +void mtex_har_multiply_clamp(float har, out float outhar) +{ + har *= 128.0; + + if(har < 1.0) outhar = 1.0; + else if(har > 511.0) outhar = 511.0; + else outhar = har; +} + +void mtex_alpha_from_col(vec4 col, out float alpha) +{ + alpha = col.a; +} + +void mtex_alpha_to_col(vec4 col, float alpha, out vec4 outcol) +{ + outcol = vec4(col.rgb, alpha); +} + +void mtex_rgbtoint(vec4 rgb, out float intensity) +{ + intensity = dot(vec3(0.35, 0.45, 0.2), rgb.rgb); +} + +void mtex_value_invert(float invalue, out float outvalue) +{ + outvalue = 1.0 - invalue; +} + +void mtex_rgb_invert(vec4 inrgb, out vec4 outrgb) +{ + outrgb = vec4(vec3(1.0) - inrgb.rgb, inrgb.a); +} + +void mtex_value_stencil(float stencil, float intensity, out float outstencil, out float outintensity) +{ + float fact = intensity; + outintensity = intensity*stencil; + outstencil = stencil*fact; +} + +void mtex_rgb_stencil(float stencil, vec4 rgb, out float outstencil, out vec4 outrgb) +{ + float fact = rgb.a; + outrgb = vec4(rgb.rgb, rgb.a*stencil); + outstencil = stencil*fact; +} + +void mtex_mapping_ofs(vec3 texco, vec3 ofs, out vec3 outtexco) +{ + outtexco = texco + ofs; +} + +void mtex_mapping_size(vec3 texco, vec3 size, out vec3 outtexco) +{ + outtexco = size*texco; +} + +void mtex_2d_mapping(vec3 vec, out vec3 outvec) +{ + outvec = vec3(vec.xy*0.5 + vec2(0.5, 0.5), vec.z); +} + +void mtex_image(vec3 vec, sampler2D ima, out float value, out vec4 color, out vec3 normal) +{ + color = texture2D(ima, vec.xy); + value = 1.0; + + normal = 2.0*(vec3(color.r, -color.g, color.b) - vec3(0.5, -0.5, 0.5)); +} + +void mtex_negate_texnormal(vec3 normal, out vec3 outnormal) +{ + outnormal = vec3(-normal.x, -normal.y, normal.z); +} + +void mtex_nspace_tangent(vec3 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) +{ + tangent = normalize(tangent); + vec3 B = cross(normal, tangent); + + outnormal = texnormal.x*tangent + texnormal.y*B + texnormal.z*normal; + outnormal = normalize(outnormal); +} + +void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) +{ + outnormal = (1.0 - norfac)*normal + norfac*newnormal; + outnormal = normalize(outnormal); +} + +/******* MATERIAL *********/ + +void lamp_visibility_sun_hemi(vec3 lampvec, out vec3 lv, out float dist, out float visifac) +{ + lv = lampvec; + dist = 1.0; + visifac = 1.0; +} + +void lamp_visibility_other(vec3 co, vec3 lampco, out vec3 lv, out float dist, out float visifac) +{ + lv = co - lampco; + dist = length(lv); + lv = normalize(lv); + visifac = 1.0; +} + +void lamp_falloff_invlinear(float lampdist, float dist, out float visifac) +{ + visifac = lampdist/(lampdist + dist); +} + +void lamp_falloff_invsquare(float lampdist, float dist, out float visifac) +{ + visifac = lampdist/(lampdist + dist*dist); +} + +void lamp_falloff_sliders(float lampdist, float ld1, float ld2, float dist, out float visifac) +{ + float lampdistkw = lampdist*lampdist; + + visifac = lampdist/(lampdist + ld1*dist); + visifac *= lampdistkw/(lampdistkw + ld2*dist*dist); +} + +void lamp_falloff_curve(float lampdist, sampler1D curvemap, float dist, out float visifac) +{ + visifac = texture1D(curvemap, dist/lampdist).x; +} + +void lamp_visibility_sphere(float lampdist, float dist, float visifac, out float outvisifac) +{ + float t= lampdist - dist; + + outvisifac= visifac*max(t, 0.0)/lampdist; +} + +void lamp_visibility_spot_square(vec3 lampvec, mat4 lampimat, vec3 lv, out float inpr) +{ + if(dot(lv, lampvec) > 0.0) { + vec3 lvrot = (lampimat*vec4(lv, 0.0)).xyz; + float x = max(abs(lvrot.x/lvrot.z), abs(lvrot.y/lvrot.z)); + + inpr = 1.0/sqrt(1.0 + x*x); + } + else + inpr = 0.0; +} + +void lamp_visibility_spot_circle(vec3 lampvec, vec3 lv, out float inpr) +{ + inpr = dot(lv, lampvec); +} + +void lamp_visibility_spot(float spotsi, float spotbl, float inpr, float visifac, out float outvisifac) +{ + float t = spotsi; + + if(inpr <= t) { + outvisifac = 0.0; + } + else { + t = inpr - t; + + /* soft area */ + if(spotbl != 0.0) + inpr *= smoothstep(0.0, 1.0, t/spotbl); + + outvisifac = visifac*inpr; + } +} + +void lamp_visibility_clamp(float visifac, out float outvisifac) +{ + outvisifac = (visifac < 0.001)? 0.0: visifac; +} + +void shade_view(vec3 co, out vec3 view) +{ + /* handle perspective/orthographic */ + view = (gl_ProjectionMatrix[3][3] == 0.0)? normalize(co): vec3(0.0, 0.0, -1.0); +} + +void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn) +{ + vec3 c = cross(lv, tang); + vec3 vnor = cross(c, tang); + + vn = -normalize(vnor); +} + +void shade_inp(vec3 vn, vec3 lv, out float inp) +{ + inp = dot(vn, lv); +} + +void shade_is_no_diffuse(out float is) +{ + is = 0.0; +} + +void shade_is_hemi(float inp, out float is) +{ + is = 0.5*inp + 0.5; +} + +float area_lamp_energy(mat4 area, vec3 co, vec3 vn) +{ + vec3 vec[4], c[4]; + float rad[4], fac; + + vec[0] = normalize(co - area[0].xyz); + vec[1] = normalize(co - area[1].xyz); + vec[2] = normalize(co - area[2].xyz); + vec[3] = normalize(co - area[3].xyz); + + c[0] = normalize(cross(vec[0], vec[1])); + c[1] = normalize(cross(vec[1], vec[2])); + c[2] = normalize(cross(vec[2], vec[3])); + c[3] = normalize(cross(vec[3], vec[0])); + + rad[0] = acos(dot(vec[0], vec[1])); + rad[1] = acos(dot(vec[1], vec[2])); + rad[2] = acos(dot(vec[2], vec[3])); + rad[3] = acos(dot(vec[3], vec[0])); + + fac= rad[0]*dot(vn, c[0]); + fac+= rad[1]*dot(vn, c[1]); + fac+= rad[2]*dot(vn, c[2]); + fac+= rad[3]*dot(vn, c[3]); + + return max(fac, 0.0); +} + +void shade_inp_area(vec3 position, vec3 lampco, vec3 lampvec, vec3 vn, mat4 area, float areasize, float k, out float inp) +{ + vec3 co = position; + vec3 vec = co - lampco; + + if(dot(vec, lampvec) < 0.0) { + inp = 0.0; + } + else { + float intens = area_lamp_energy(area, co, vn); + + inp = pow(intens*areasize, k); + } +} + +void shade_diffuse_oren_nayer(float nl, vec3 n, vec3 l, vec3 v, float rough, out float is) +{ + vec3 h = normalize(v + l); + float nh = max(dot(n, h), 0.0); + float nv = max(dot(n, v), 0.0); + float realnl = dot(n, l); + + if(realnl < 0.0) { + is = 0.0; + } + else if(nl < 0.0) { + is = 0.0; + } + else { + float vh = max(dot(v, h), 0.0); + float Lit_A = acos(realnl); + float View_A = acos(nv); + + vec3 Lit_B = normalize(l - realnl*n); + vec3 View_B = normalize(v - nv*n); + + float t = max(dot(Lit_B, View_B), 0.0); + + float a, b; + + if(Lit_A > View_A) { + a = Lit_A; + b = View_A; + } + else { + a = View_A; + b = Lit_A; + } + + float A = 1.0 - (0.5*((rough*rough)/((rough*rough) + 0.33))); + float B = 0.45*((rough*rough)/((rough*rough) + 0.09)); + + b *= 0.95; + is = nl*(A + (B * t * sin(a) * tan(b))); + } +} + +void shade_diffuse_toon(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float is) +{ + float rslt = dot(n, l); + float ang = acos(rslt); + + if(ang < size) is = 1.0; + else if(ang > (size + tsmooth) || tsmooth == 0.0) is = 0.0; + else is = 1.0 - ((ang - size)/tsmooth); +} + +void shade_diffuse_minnaert(float nl, vec3 n, vec3 v, float darkness, out float is) +{ + if(nl <= 0.0) { + is = 0.0; + } + else { + float nv = max(dot(n, v), 0.0); + + if(darkness <= 1.0) + is = nl*pow(max(nv*nl, 0.1), darkness - 1.0); + else + is = nl*pow(1.0001 - nv, darkness - 1.0); + } +} + +float fresnel_fac(vec3 view, vec3 vn, float grad, float fac) +{ + float t1, t2; + float ffac; + + if(fac==0.0) { + ffac = 1.0; + } + else { + t1= dot(view, vn); + if(t1>0.0) t2= 1.0+t1; + else t2= 1.0-t1; + + t2= grad + (1.0-grad)*pow(t2, fac); + + if(t2<0.0) ffac = 0.0; + else if(t2>1.0) ffac = 1.0; + else ffac = t2; + } + + return ffac; +} + +void shade_diffuse_fresnel(vec3 vn, vec3 lv, vec3 view, float fac_i, float fac, out float is) +{ + is = fresnel_fac(lv, vn, fac_i, fac); +} + +void shade_cubic(float is, out float outis) +{ + if(is>0.0 && is<1.0) + outis= smoothstep(0.0, 1.0, is); + else + outis= is; +} + +void shade_visifac(float i, float visifac, float refl, out float outi) +{ + /*if(i > 0.0)*/ + outi = max(i*visifac*refl, 0.0); + /*else + outi = i;*/ +} + +void shade_tangent_v_spec(vec3 tang, out vec3 vn) +{ + vn = tang; +} + +void shade_add_to_diffuse(float i, vec3 lampcol, vec3 col, out vec3 outcol) +{ + if(i > 0.0) + outcol = i*lampcol*col; + else + outcol = vec3(0.0, 0.0, 0.0); +} + +void shade_hemi_spec(vec3 vn, vec3 lv, vec3 view, float spec, float hard, float visifac, out float t) +{ + lv += view; + lv = normalize(lv); + + t = dot(vn, lv); + t = 0.5*t + 0.5; + + t = visifac*spec*pow(t, hard); +} + +void shade_phong_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) +{ + vec3 h = normalize(l + v); + float rslt = max(dot(h, n), 0.0); + + specfac = pow(rslt, hard); +} + +void shade_cooktorr_spec(vec3 n, vec3 l, vec3 v, float hard, out float specfac) +{ + vec3 h = normalize(v + l); + float nh = dot(n, h); + + if(nh < 0.0) { + specfac = 0.0; + } + else { + float nv = max(dot(n, v), 0.0); + float i = pow(nh, hard); + + i = i/(0.1+nv); + specfac = i; + } +} + +void shade_blinn_spec(vec3 n, vec3 l, vec3 v, float refrac, float spec_power, out float specfac) +{ + if(refrac < 1.0) { + specfac = 0.0; + } + else if(spec_power == 0.0) { + specfac = 0.0; + } + else { + if(spec_power<100.0) + spec_power= sqrt(1.0/spec_power); + else + spec_power= 10.0/spec_power; + + vec3 h = normalize(v + l); + float nh = dot(n, h); + if(nh < 0.0) { + specfac = 0.0; + } + else { + float nv = max(dot(n, v), 0.01); + float nl = dot(n, l); + if(nl <= 0.01) { + specfac = 0.0; + } + else { + float vh = max(dot(v, h), 0.01); + + float a = 1.0; + float b = (2.0*nh*nv)/vh; + float c = (2.0*nh*nl)/vh; + + float g = 0.0; + + if(a < b && a < c) g = a; + else if(b < a && b < c) g = b; + else if(c < a && c < b) g = c; + + float p = sqrt(((refrac * refrac)+(vh*vh)-1.0)); + float f = (((p-vh)*(p-vh))/((p+vh)*(p+vh)))*(1.0+((((vh*(p+vh))-1.0)*((vh*(p+vh))-1.0))/(((vh*(p-vh))+1.0)*((vh*(p-vh))+1.0)))); + float ang = acos(nh); + + specfac = max(f*g*exp_blender((-(ang*ang)/(2.0*spec_power*spec_power))), 0.0); + } + } + } +} + +void shade_wardiso_spec(vec3 n, vec3 l, vec3 v, float rms, out float specfac) +{ + vec3 h = normalize(l + v); + float nh = max(dot(n, h), 0.001); + float nv = max(dot(n, v), 0.001); + float nl = max(dot(n, l), 0.001); + float angle = tan(acos(nh)); + float alpha = max(rms, 0.001); + + specfac= nl * (1.0/(4.0*M_PI*alpha*alpha))*(exp_blender(-(angle*angle)/(alpha*alpha))/(sqrt(nv*nl))); +} + +void shade_toon_spec(vec3 n, vec3 l, vec3 v, float size, float tsmooth, out float specfac) +{ + vec3 h = normalize(l + v); + float rslt = dot(h, n); + float ang = acos(rslt); + + if(ang < size) rslt = 1.0; + else if(ang >= (size + tsmooth) || tsmooth == 0.0) rslt = 0.0; + else rslt = 1.0 - ((ang - size)/tsmooth); + + specfac = rslt; +} + +void shade_spec_area_inp(float specfac, float inp, out float outspecfac) +{ + outspecfac = specfac*inp; +} + +void shade_spec_t(float shadfac, float spec, float visifac, float specfac, out float t) +{ + t = shadfac*spec*visifac*specfac; +} + +void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol) +{ + outcol = t*lampcol*speccol; +} + +void shade_add(vec4 col1, vec4 col2, out vec4 outcol) +{ + outcol = col1 + col2; +} + +void shade_madd(vec4 col, vec4 col1, vec4 col2, out vec4 outcol) +{ + outcol = col + col1*col2; +} + +void shade_maddf(vec4 col, float f, vec4 col1, out vec4 outcol) +{ + outcol = col + f*col1; +} + +void shade_mul(vec4 col1, vec4 col2, out vec4 outcol) +{ + outcol = col1*col2; +} + +void shade_mul_value(float fac, vec4 col, out vec4 outcol) +{ + outcol = col*fac; +} + +void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol) +{ + outcol = vec4(col.rgb*obcol.rgb, col.a); +} + +void ramp_rgbtobw(vec3 color, out float outval) +{ + outval = color.r*0.3 + color.g*0.58 + color.b*0.12; +} + +void shade_only_shadow(float i, float shadfac, float energy, out float outshadfac) +{ + outshadfac = i*energy*(1.0 - shadfac); +} + +void shade_only_shadow_diffuse(float shadfac, vec3 rgb, vec4 diff, out vec4 outdiff) +{ + outdiff = diff - vec4(rgb*shadfac, 0.0); +} + +void shade_only_shadow_specular(float shadfac, vec3 specrgb, vec4 spec, out vec4 outspec) +{ + outspec = spec - vec4(specrgb*shadfac, 0.0); +} + +void test_shadowbuf(vec3 rco, sampler2DShadow shadowmap, mat4 shadowpersmat, float shadowbias, float inp, out float result) +{ + if(inp <= 0.0) { + result = 0.0; + } + else { + vec4 co = shadowpersmat*vec4(rco, 1.0); + + //float bias = (1.5 - inp*inp)*shadowbias; + co.z -= shadowbias*co.w; + + result = shadow2DProj(shadowmap, co).x; + } +} + +void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outcol) +{ + outcol = linfac*(1.0 - exp(col*logfac)); +} + +void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac) +{ + float fac, zcor; + + zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2]; + + fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0); + if(misttype == 0.0) fac *= fac; + else if(misttype == 1.0); + else fac = sqrt(fac); + + outfac = 1.0 - (1.0-fac)*(1.0-misi); +} + +void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol) +{ + float fac = clamp(col.a, 0.0, 1.0); + outcol = vec4(mix(hor, col.rgb, fac), col.a); +} + +void shade_alpha_opaque(vec4 col, out vec4 outcol) +{ + outcol = vec4(col.rgb, 1.0); +} + +void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol) +{ + outcol = vec4(col.rgb, col.a*obcol.a); +} + diff --git a/source/blender/gpu/intern/gpu_shader_material.glsl.c b/source/blender/gpu/intern/gpu_shader_material.glsl.c new file mode 100644 index 00000000000..8287efe84ea --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_material.glsl.c @@ -0,0 +1,1032 @@ +/* DataToC output of file */ + +int datatoc_gpu_shader_material_glsl_size= 32828; +char datatoc_gpu_shader_material_glsl[]= { + 10,102,108,111, 97,116, 32,101,120,112, 95, 98,108,101,110,100,101,114, 40,102,108,111, 97,116, 32,102, 41, 10, +123, 10, 9,114,101,116,117,114,110, 32,112,111,119, 40, 50, 46, 55, 49, 56, 50, 56, 49, 56, 50, 56, 52, 54, 44, 32,102, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,114,103, 98, 95,116,111, 95,104,115,118, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,111,117, +116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, 99,109, 97,120, 44, 32, 99,109, +105,110, 44, 32,104, 44, 32,115, 44, 32,118, 44, 32, 99,100,101,108,116, 97, 59, 10, 9,118,101, 99, 51, 32, 99, 59, 10, 10, 9, + 99,109, 97,120, 32, 61, 32,109, 97,120, 40,114,103, 98, 91, 48, 93, 44, 32,109, 97,120, 40,114,103, 98, 91, 49, 93, 44, 32,114, +103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,109,105,110, 32, 61, 32,109,105,110, 40,114,103, 98, 91, 48, 93, 44, 32,109,105,110, + 40,114,103, 98, 91, 49, 93, 44, 32,114,103, 98, 91, 50, 93, 41, 41, 59, 10, 9, 99,100,101,108,116, 97, 32, 61, 32, 99,109, 97, +120, 45, 99,109,105,110, 59, 10, 10, 9,118, 32, 61, 32, 99,109, 97,120, 59, 10, 9,105,102, 32, 40, 99,109, 97,120, 33, 61, 48, + 46, 48, 41, 10, 9, 9,115, 32, 61, 32, 99,100,101,108,116, 97, 47, 99,109, 97,120, 59, 10, 9,101,108,115,101, 32,123, 10, 9, + 9,115, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 10, 9,105,102, 32, 40,115, 32, + 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, + 9, 9, 99, 32, 61, 32, 40,118,101, 99, 51, 40, 99,109, 97,120, 44, 32, 99,109, 97,120, 44, 32, 99,109, 97,120, 41, 32, 45, 32, +114,103, 98, 46,120,121,122, 41, 47, 99,100,101,108,116, 97, 59, 10, 10, 9, 9,105,102, 32, 40,114,103, 98, 46,120, 61, 61, 99, +109, 97,120, 41, 32,104, 32, 61, 32, 99, 91, 50, 93, 32, 45, 32, 99, 91, 49, 93, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, + 40,114,103, 98, 46,121, 61, 61, 99,109, 97,120, 41, 32,104, 32, 61, 32, 50, 46, 48, 32, 43, 32, 99, 91, 48, 93, 32, 45, 32, 32, + 99, 91, 50, 93, 59, 10, 9, 9,101,108,115,101, 32,104, 32, 61, 32, 52, 46, 48, 32, 43, 32, 99, 91, 49, 93, 32, 45, 32, 99, 91, + 48, 93, 59, 10, 10, 9, 9,104, 32, 47, 61, 32, 54, 46, 48, 59, 10, 10, 9, 9,105,102, 32, 40,104, 60, 48, 46, 48, 41, 10, 9, + 9, 9,104, 32, 43, 61, 32, 49, 46, 48, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,104, + 44, 32,115, 44, 32,118, 44, 32,114,103, 98, 46,119, 41, 59, 10,125, 10, 10,118,111,105,100, 32,104,115,118, 95,116,111, 95,114, +103, 98, 40,118,101, 99, 52, 32,104,115,118, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, + 9,102,108,111, 97,116, 32,105, 44, 32,102, 44, 32,112, 44, 32,113, 44, 32,116, 44, 32,104, 44, 32,115, 44, 32,118, 59, 10, 9, +118,101, 99, 51, 32,114,103, 98, 59, 10, 10, 9,104, 32, 61, 32,104,115,118, 91, 48, 93, 59, 10, 9,115, 32, 61, 32,104,115,118, + 91, 49, 93, 59, 10, 9,118, 32, 61, 32,104,115,118, 91, 50, 93, 59, 10, 10, 9,105,102, 40,115, 61, 61, 48, 46, 48, 41, 32,123, + 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, 32,118, 44, 32,118, 41, 59, 10, 9,125, 10, 9,101,108,115,101, + 32,123, 10, 9, 9,105,102, 40,104, 61, 61, 49, 46, 48, 41, 10, 9, 9, 9,104, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9, 10, 9, + 9,104, 32, 42, 61, 32, 54, 46, 48, 59, 10, 9, 9,105, 32, 61, 32,102,108,111,111,114, 40,104, 41, 59, 10, 9, 9,102, 32, 61, + 32,104, 32, 45, 32,105, 59, 10, 9, 9,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,102, 44, 32,102, 44, 32,102, 41, 59, 10, 9, + 9,112, 32, 61, 32,118, 42, 40, 49, 46, 48, 45,115, 41, 59, 10, 9, 9,113, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, +102, 41, 41, 59, 10, 9, 9,116, 32, 61, 32,118, 42, 40, 49, 46, 48, 45, 40,115, 42, 40, 49, 46, 48, 45,102, 41, 41, 41, 59, 10, + 9, 9, 10, 9, 9,105,102, 32, 40,105, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,118, 44, + 32,116, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 49, 46, 48, 41, 32,114,103, 98, + 32, 61, 32,118,101, 99, 51, 40,113, 44, 32,118, 44, 32,112, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, + 61, 32, 50, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,118, 44, 32,116, 41, 59, 10, 9, 9,101,108, +115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 51, 46, 48, 41, 32,114,103, 98, 32, 61, 32,118,101, 99, 51, 40,112, 44, 32,113, + 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,105,102, 32, 40,105, 32, 61, 61, 32, 52, 46, 48, 41, 32,114,103, 98, 32, 61, + 32,118,101, 99, 51, 40,116, 44, 32,112, 44, 32,118, 41, 59, 10, 9, 9,101,108,115,101, 32,114,103, 98, 32, 61, 32,118,101, 99, + 51, 40,118, 44, 32,112, 44, 32,113, 41, 59, 10, 9,125, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,114, +103, 98, 44, 32,104,115,118, 46,119, 41, 59, 10,125, 10, 10, 35,100,101,102,105,110,101, 32, 77, 95, 80, 73, 32, 51, 46, 49, 52, + 49, 53, 57, 50, 54, 53, 51, 53, 56, 57, 55, 57, 51, 50, 51, 56, 52, 54, 10, 10, 47, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 32, 83, 72, 65, 68, 69, 82, 32, 78, 79, 68, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10, +118,111,105,100, 32,118, 99,111,108, 95, 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 41, 10,123, 10, 9,118, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, + 97,116,116,118, 99,111,108, 46,120, 47, 50, 53, 53, 46, 48, 44, 32, 97,116,116,118, 99,111,108, 46,121, 47, 50, 53, 53, 46, 48, + 44, 32, 97,116,116,118, 99,111,108, 46,122, 47, 50, 53, 53, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,117,118, 95, 97,116,116,114,105, 98,117,116,101, 40,118,101, 99, 50, 32, 97,116,116,117,118, 44, 32,111,117,116, 32,118,101, + 99, 51, 32,117,118, 41, 10,123, 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32, +118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,103,101, +111,109, 40,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,109, 97,116, 52, 32,118,105,101,119,105, +110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 97,116,116,111,114, 99,111, 44, 32,118,101, 99, 50, 32, 97,116,116,117,118, 44, + 32,118,101, 99, 52, 32, 97,116,116,118, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 44, 32, +111,117,116, 32,118,101, 99, 51, 32,108,111, 99, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,114, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,118, 99,111,108, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,102,114,111,110,116, 98, 97, 99,107, 41, 10,123, 10, 9,108,111, 99, 97,108, 32, 61, 32, 99,111, 59, 10, 9, +118,105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,111, 99, 97,108, 41, 59, 10, 9,103,108,111, 98, 97,108, + 32, 61, 32, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40,108,111, 99, 97,108, 44, 32, 49, 46, 48, 41, 41, + 46,120,121,122, 59, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116,111,114, 99,111, 59, 10, 9,117,118, 95, 97,116,116,114,105, + 98,117,116,101, 40, 97,116,116,117,118, 44, 32,117,118, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32, 45,110,111,114,109, + 97,108,105,122,101, 40,110,111,114, 41, 59, 9, 47, 42, 32, 98,108,101,110,100,101,114, 32,114,101,110,100,101,114, 32,110,111, +114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,118, 99,111,108, 95, 97,116,116,114,105, 98,117, +116,101, 40, 97,116,116,118, 99,111,108, 44, 32,118, 99,111,108, 41, 59, 10, 9,102,114,111,110,116, 98, 97, 99,107, 32, 61, 32, + 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,109, + 97,116, 52, 32,109, 97,116, 44, 32,118,101, 99, 51, 32,109,105,110,118,101, 99, 44, 32,118,101, 99, 51, 32,109, 97,120,118,101, + 99, 44, 32,102,108,111, 97,116, 32,100,111,109,105,110, 44, 32,102,108,111, 97,116, 32,100,111,109, 97,120, 44, 32,111,117,116, + 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 40,109, 97,116, 32, 42, + 32,118,101, 99, 52, 40,118,101, 99, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9,105,102, 40,100,111,109,105,110, 32, + 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118,101, 99, 32, 61, 32,109, 97,120, 40,111,117,116,118,101, 99, 44, 32,109, +105,110,118,101, 99, 41, 59, 10, 9,105,102, 40,100,111,109, 97,120, 32, 61, 61, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116,118, +101, 99, 32, 61, 32,109,105,110, 40,111,117,116,118,101, 99, 44, 32,109, 97,120,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105, +100, 32, 99, 97,109,101,114, 97, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,105, +101,119, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,100,101,112,116,104, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,100,105,115,116, 41, 10,123, 10, 9,111,117,116,100,101,112,116,104, 32, 61, 32, 97, 98,115, 40, 99,111, 46, +122, 41, 59, 10, 9,111,117,116,100,105,115,116, 32, 61, 32,108,101,110,103,116,104, 40, 99,111, 41, 59, 10, 9,111,117,116,118, +105,101,119, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116, +104, 95, 97,100,100, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, + 32, 43, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,115,117, 98,116,114, 97, 99,116, 40,102, +108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, + 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 45, 32,118, 97,108, 50, + 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109,117,108,116,105,112,108,121, 40,102,108,111, 97,116, 32,118, 97, +108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 42, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111, +105,100, 32,109, 97,116,104, 95,100,105,118,105,100,101, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, + 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40, +118, 97,108, 50, 32, 61, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, +115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 49, 32, 47, 32,118, 97,108, 50, 59, 10,125, 10, 10,118,111, +105,100, 32,109, 97,116,104, 95,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,115,105,110, 40,118, 97,108, 41, 59, 10, +125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 99,111,115,105,110,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,115, + 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,116, 97,110,103,101,110,116, 40,102,108,111, 97, +116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, + 97,108, 32, 61, 32,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,115,105,110, + 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, + 9,105,102, 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, + 9, 9,111,117,116,118, 97,108, 32, 61, 32, 97,115,105,110, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117, +116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97, 99,111,115, 40,102,108, +111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, + 32, 40,118, 97,108, 32, 60, 61, 32, 49, 46, 48, 32, 38, 38, 32,118, 97,108, 32, 62, 61, 32, 45, 49, 46, 48, 41, 10, 9, 9,111, +117,116,118, 97,108, 32, 61, 32, 97, 99,111,115, 40,118, 97,108, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97, +108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95, 97,116, 97,110, 40,102,108,111, 97,116, + 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97, +108, 32, 61, 32, 97,116, 97,110, 40,118, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,112,111,119, 40, +102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 32, 40,118, 97,108, 49, 32, 62, 61, 32, 48, 46, 48, 41, 10, 9, 9, +111,117,116,118, 97,108, 32, 61, 32,112,111,119, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, + 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,111,103, + 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32, 48, 46, 48, 32, 32, 38, 38, 32, +118, 97,108, 50, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116,118, 97,108, 61, 32,108,111,103, 50, 40,118, 97,108, 49, 41, + 32, 47, 32,108,111,103, 50, 40,118, 97,108, 50, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 61, 32, 48, + 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,109, 97,120, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, + 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, 97,120, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,109, 97,116,104, 95,109,105,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, 32,102,108,111, 97,116, 32,118, + 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, + 32, 61, 32,109,105,110, 40,118, 97,108, 49, 44, 32,118, 97,108, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, + 95,114,111,117,110,100, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, + 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 61, 32,102,108,111,111,114, 40,118, 97,108, 32, 43, 32, 48, 46, 53, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109, 97,116,104, 95,108,101,115,115, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97, +108, 49, 44, 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, + 41, 10,123, 10, 9,105,102, 40,118, 97,108, 49, 32, 60, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, + 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111, +105,100, 32,109, 97,116,104, 95,103,114,101, 97,116,101,114, 95,116,104, 97,110, 40,102,108,111, 97,116, 32,118, 97,108, 49, 44, + 32,102,108,111, 97,116, 32,118, 97,108, 50, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,105,102, 40,118, 97,108, 49, 32, 62, 32,118, 97,108, 50, 41, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, + 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32, +115,113,117,101,101,122,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,102,108,111, 97,116, 32,119,105,100,116,104, 44, 32, +102,108,111, 97,116, 32, 99,101,110,116,101,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, +123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 49, 46, 48, 47, 40, 49, 46, 48, 32, 43, 32,112,111,119, 40, 50, 46, 55, 49, 56, + 50, 56, 49, 56, 51, 44, 32, 45, 40, 40,118, 97,108, 45, 99,101,110,116,101,114, 41, 42,119,105,100,116,104, 41, 41, 41, 59, 10, +125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,100,100, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, + 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97, +116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, 32,118, 50, 59, 10, 9, +111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98,115, 40,111, +117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, 46, 48, 59, + 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,115,117, 98, 40,118,101, 99, 51, 32,118, 49, 44, 32,118, +101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 45, 32,118, 50, 59, 10, + 9,111,117,116,118, 97,108, 32, 61, 32, 40, 97, 98,115, 40,111,117,116,118,101, 99, 91, 48, 93, 41, 32, 43, 32, 97, 98,115, 40, +111,117,116,118,101, 99, 91, 49, 93, 41, 32, 43, 32, 97, 98,115, 40,111,117,116,118,101, 99, 91, 50, 93, 41, 41, 47, 51, 46, 48, + 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95, 97,118,101,114, 97,103,101, 40,118,101, 99, 51, 32, +118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118, 49, 32, 43, + 32,118, 50, 59, 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10, 9, +111,117,116,118,101, 99, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,100,111,116, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, + 50, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117, +116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32,118,101, 99, 51, 40, 48, 44, 32, 48, 44, 32, 48, 41, 59, + 10, 9,111,117,116,118, 97,108, 32, 61, 32,100,111,116, 40,118, 49, 44, 32,118, 50, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +118,101, 99, 95,109, 97,116,104, 95, 99,114,111,115,115, 40,118,101, 99, 51, 32,118, 49, 44, 32,118,101, 99, 51, 32,118, 50, 44, + 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, + 97,108, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, 99,114,111,115,115, 40,118, 49, 44, 32,118, 50, 41, 59, 10, 9, +111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,111,117,116,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,118,101, 99, 95,109, 97,116,104, 95,110,111,114,109, 97,108,105,122,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32, +118,101, 99, 51, 32,111,117,116,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,111,117,116,118, 97,108, 32, 61, 32,108,101,110,103,116,104, 40,118, 41, 59, 10, 9,111,117,116,118,101, 99, 32, 61, 32, +110,111,114,109, 97,108,105,122,101, 40,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,118,101, 99, 95,109, 97,116,104, 95,110, +101,103, 97,116,101, 40,118,101, 99, 51, 32,118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118, 41, 10,123, 10, 9, +111,117,116,118, 32, 61, 32, 45,118, 59, 10,125, 10, 10,118,111,105,100, 32,110,111,114,109, 97,108, 40,118,101, 99, 51, 32,100, +105,114, 44, 32,118,101, 99, 51, 32,110,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114, 44, 32,111, +117,116, 32,102,108,111, 97,116, 32,111,117,116,100,111,116, 41, 10,123, 10, 9,111,117,116,110,111,114, 32, 61, 32,100,105,114, + 59, 10, 9,111,117,116,100,111,116, 32, 61, 32, 45,100,111,116, 40,100,105,114, 44, 32,110,111,114, 41, 59, 10,125, 10, 10,118, +111,105,100, 32, 99,117,114,118,101,115, 95,118,101, 99, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, + 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, + 9,111,117,116,118,101, 99, 46,120, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, + 40,118,101, 99, 46,120, 32, 43, 32, 49, 46, 48, 41, 42, 48, 46, 53, 41, 46,120, 59, 10, 9,111,117,116,118,101, 99, 46,121, 32, + 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 40,118,101, 99, 46,121, 32, 43, 32, 49, + 46, 48, 41, 42, 48, 46, 53, 41, 46,121, 59, 10, 9,111,117,116,118,101, 99, 46,122, 32, 61, 32,116,101,120,116,117,114,101, 49, + 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 40,118,101, 99, 46,122, 32, 43, 32, 49, 46, 48, 41, 42, 48, 46, 53, 41, 46,122, + 59, 10,125, 10, 10,118,111,105,100, 32, 99,117,114,118,101,115, 95,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,115, + 97,109,112,108,101,114, 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118, +101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46,114, 41, + 46, 97, 41, 46,114, 59, 10, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114, +118,101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46,103, + 41, 46, 97, 41, 46,103, 59, 10, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117, +114,118,101,109, 97,112, 44, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32, 99,111,108, 46, + 98, 41, 46, 97, 41, 46, 98, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 46, 97, 59, 10,125, 10, 10,118, +111,105,100, 32,115,101,116, 95,118, 97,108,117,101, 40,102,108,111, 97,116, 32,118, 97,108, 44, 32,111,117,116, 32,102,108,111, + 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118, 97,108, 59, 10,125, 10, 10,118, +111,105,100, 32,115,101,116, 95,114,103, 98, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111, +117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32, +115,101,116, 95,114,103, 98, 97, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, + 95,118, 97,108,117,101, 95,122,101,114,111, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, + 9,111,117,116,118, 97,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,118, 97,108,117,101, + 95,111,110,101, 40,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, + 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 95,122,101,114,111, 40,111,117,116, + 32,118,101, 99, 51, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, + 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,116, 95,114,103, 98, 97, 95,122,101,114,111, 40,111,117,116, 32,118, +101, 99, 52, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,118,101, 99, 52, 40, 48, 46, 48, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, +118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, +117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, + 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 50, 44, 32, +102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105, +100, 32,109,105,120, 95, 97,100,100, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32, +118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, + 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99, +111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, + 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105, +120, 95,109,117,108,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, + 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, + 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, + 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 42, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9, +111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, + 99,114,101,101,110, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, + 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, + 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, + 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, + 49, 46, 48, 41, 32, 45, 32, 40,118,101, 99, 52, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99, 42, 40,118,101, 99, 52, 40, 49, + 46, 48, 41, 32, 45, 32, 99,111,108, 50, 41, 41, 42, 40,118,101, 99, 52, 40, 49, 46, 48, 41, 32, 45, 32, 99,111,108, 49, 41, 59, + 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, + 95,111,118,101,114,108, 97,121, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, +101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, + 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, +108, 49, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,111,117,116, 99,111, +108, 46,114, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,101, +108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, + 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117, +116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9, +111,117,116, 99,111,108, 46,103, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 99,111,108, 50, 46, +103, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99, +109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46,103, 41, 41, 42, 40, 49, 46, 48, + 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, + 53, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 42, 61, 32,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, + 99,111,108, 50, 46, 98, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, + 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99, 42, 40, 49, 46, 48, 32, 45, 32, 99,111,108, 50, 46, 98, 41, 41, + 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,115, +117, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111, +108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, + 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105, +120, 40, 99,111,108, 49, 44, 32, 99,111,108, 49, 32, 45, 32, 99,111,108, 50, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99, +111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,118, 40,102, +108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32, +111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, +102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, + 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, 40, 99, +111,108, 50, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,114, 32, 61, 32,102, 97, 99,109, 42,111,117, +116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,114, 47, 99,111,108, 50, 46,114, 59, 10, 9,105, +102, 40, 99,111,108, 50, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, + 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46,103, 47, 99,111,108, 50, 46,103, 59, + 10, 9,105,102, 40, 99,111,108, 50, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,111,117,116, 99,111,108, 46, 98, 32, 61, 32,102, + 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, 43, 32,102, 97, 99, 42,111,117,116, 99,111,108, 46, 98, 47, 99,111,108, 50, + 46, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,105,102,102, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32, +118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111, +117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, + 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99,111,108, 49, 44, 32, 97, 98,115, 40, 99,111, +108, 49, 32, 45, 32, 99,111,108, 50, 41, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111, +108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,102, 97, 99, + 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, + 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109,105,110, 40, 99,111,108, 49, 46,114, +103, 98, 44, 32, 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99, +111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,108,105,103,104,116, 40,102,108,111, 97,116, 32,102, + 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, + 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 46,114,103, 98, 32, 61, 32,109, 97,120, 40, 99,111,108, 49, + 46,114,103, 98, 44, 32, 99,111,108, 50, 46,114,103, 98, 42,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46, 97, 32, 61, + 32, 99,111,108, 49, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,100,111,100,103,101, 40,102,108,111, 97,116, + 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32, +118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, + 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,105,102, + 40,111,117,116, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, + 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, + 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105, +102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46,114, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, + 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111, +108, 46,114, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, + 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109,112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, + 50, 46,103, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, +103, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, + 46,103, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, + 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32,116,109,112, 59, 10, 9,125, 10, 9, +105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97,116, 32,116,109, +112, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, 9, 9,105,102, 40,116,109,112, 32, 60, + 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, + 32,105,102, 40, 40,116,109,112, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 47,116,109,112, 41, 32, 62, 32, 49, 46, 48, 41, 10, + 9, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,111,117,116, + 99,111,108, 46, 98, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95, 98,117,114,110, + 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109, +112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,116,109,112, 44, 32,102, 97, + 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, + 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,114, 59, 10, 9,105,102, 40, +116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, 48, 46, 48, 59, 10, 9,101, +108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99, +111,108, 46,114, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32, + 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, 99,111, +108, 46,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,114, 32, 61, 32,116,109, +112, 59, 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46,103, 59, 10, 9,105, +102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, 48, 46, 48, 59, 10, + 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32,111,117, +116, 99,111,108, 46,103, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, + 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111,117,116, + 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46,103, 32, 61, 32, +116,109,112, 59, 10, 10, 9,116,109,112, 32, 61, 32,102, 97, 99,109, 32, 43, 32,102, 97, 99, 42, 99,111,108, 50, 46, 98, 59, 10, + 9,105,102, 40,116,109,112, 32, 60, 61, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, 61, 32, 48, 46, 48, + 59, 10, 9,101,108,115,101, 32,105,102, 40, 40,116,109,112, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 32, 45, 32, +111,117,116, 99,111,108, 46, 98, 41, 47,116,109,112, 41, 41, 32, 60, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 46, + 98, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, 32,105,102, 40,116,109,112, 32, 62, 32, 49, 46, 48, 41, 10, 9, 9,111, +117,116, 99,111,108, 46, 98, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 46, 98, 32, + 61, 32,116,109,112, 59, 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,104,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, + 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, + 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, + 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115, +118, 50, 44, 32,116,109,112, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, + 59, 10, 10, 9,105,102, 40,104,115,118, 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, + 95,104,115,118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, + 50, 46,120, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116,109,112, 41, 59, 32, 10, 10, 9, + 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109,112, 44, 32,102, 97, 99, 41, 59, + 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, + 32,109,105,120, 95,115, 97,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118, +101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,102, 97, + 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111, +108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115, +118, 40,111,117,116, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, 9,105,102, 40,104,115,118, 46,121, 32, 33, 61, 32, 48, 46, + 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, + 9, 9,104,115,118, 46,121, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,121, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46, +121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 9,125, + 10,125, 10, 10,118,111,105,100, 32,109,105,120, 95,118, 97,108, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, + 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, + 59, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,118,101, 99, + 52, 32,104,115,118, 44, 32,104,115,118, 50, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 49, 44, 32,104, +115,118, 41, 59, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9, +104,115,118, 46,122, 32, 61, 32,102, 97, 99,109, 42,104,115,118, 46,122, 32, 43, 32,102, 97, 99, 42,104,115,118, 50, 46,122, 59, + 10, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111, +105,100, 32,109,105,120, 95, 99,111,108,111,114, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, + 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, + 10, 9,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,102, +108,111, 97,116, 32,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 32, 45, 32,102, 97, 99, 59, 10, 10, 9,111,117,116, 99,111,108, 32, + 61, 32, 99,111,108, 49, 59, 10, 10, 9,118,101, 99, 52, 32,104,115,118, 44, 32,104,115,118, 50, 44, 32,116,109,112, 59, 10, 9, +114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 50, 44, 32,104,115,118, 50, 41, 59, 10, 10, 9,105,102, 40,104,115,118, + 50, 46,121, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,103, 98, 95,116,111, 95,104,115,118, 40,111,117,116, 99,111, +108, 44, 32,104,115,118, 41, 59, 10, 9, 9,104,115,118, 46,120, 32, 61, 32,104,115,118, 50, 46,120, 59, 10, 9, 9,104,115,118, + 46,121, 32, 61, 32,104,115,118, 50, 46,121, 59, 10, 9, 9,104,115,118, 95,116,111, 95,114,103, 98, 40,104,115,118, 44, 32,116, +109,112, 41, 59, 32, 10, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40,111,117,116, 99,111,108, 44, 32,116,109, +112, 44, 32,102, 97, 99, 41, 59, 10, 9, 9,111,117,116, 99,111,108, 46, 97, 32, 61, 32, 99,111,108, 49, 46, 97, 59, 10, 9,125, + 10,125, 10, 10,118,111,105,100, 32,118, 97,108,116,111,114,103, 98, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,115, 97,109, +112,108,101,114, 49, 68, 32, 99,111,108,111,114,109, 97,112, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, 97,108,112,104, 97, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, + 61, 32,116,101,120,116,117,114,101, 49, 68, 40, 99,111,108,111,114,109, 97,112, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, + 97,108,112,104, 97, 32, 61, 32,111,117,116, 99,111,108, 46, 97, 59, 10,125, 10, 10,118,111,105,100, 32,114,103, 98,116,111, 98, +119, 40,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10, +123, 10, 9,111,117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 53, 32, 43, 32, 99,111,108,111,114, + 46,103, 42, 48, 46, 52, 53, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 50, 59, 10,125, 10, 10,118,111,105,100, 32,105, +110,118,101,114,116, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118, +101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 46,120,121,122, 32, 61, 32,109,105,120, 40, + 99,111,108, 46,120,121,122, 44, 32,118,101, 99, 51, 40, 49, 46, 48, 44, 32, 49, 46, 48, 44, 32, 49, 46, 48, 41, 32, 45, 32, 99, +111,108, 46,120,121,122, 44, 32,102, 97, 99, 41, 59, 10, 9,111,117,116, 99,111,108, 46,119, 32, 61, 32, 99,111,108, 46,119, 59, + 10,125, 10, 10,118,111,105,100, 32,104,117,101, 95,115, 97,116, 40,102,108,111, 97,116, 32,104,117,101, 44, 32,102,108,111, 97, +116, 32,115, 97,116, 44, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118, +101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,118,101, 99, + 52, 32,104,115,118, 59, 10, 10, 9,114,103, 98, 95,116,111, 95,104,115,118, 40, 99,111,108, 44, 32,104,115,118, 41, 59, 10, 10, + 9,104,115,118, 91, 48, 93, 32, 43, 61, 32, 40,104,117,101, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,105,102, 40,104,115,118, 91, + 48, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 48, 93, 45, 61, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, + 91, 48, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 48, 93, 43, 61, 32, 49, 46, 48, 59, 10, 9,104,115,118, 91, 49, 93, 32, 42, + 61, 32,115, 97,116, 59, 10, 9,105,102, 40,104,115,118, 91, 49, 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, 49, + 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, 49, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 49, 93, 61, 32, + 48, 46, 48, 59, 10, 9,104,115,118, 91, 50, 93, 32, 42, 61, 32,118, 97,108,117,101, 59, 10, 9,105,102, 40,104,115,118, 91, 50, + 93, 62, 49, 46, 48, 41, 32,104,115,118, 91, 50, 93, 61, 32, 49, 46, 48, 59, 32,101,108,115,101, 32,105,102, 40,104,115,118, 91, + 50, 93, 60, 48, 46, 48, 41, 32,104,115,118, 91, 50, 93, 61, 32, 48, 46, 48, 59, 10, 10, 9,104,115,118, 95,116,111, 95,114,103, + 98, 40,104,115,118, 44, 32,111,117,116, 99,111,108, 41, 59, 10, 10, 9,111,117,116, 99,111,108, 32, 61, 32,109,105,120, 40, 99, +111,108, 44, 32,111,117,116, 99,111,108, 44, 32,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,101,112, 97,114, 97, +116,101, 95,114,103, 98, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, 98, 41, 10,123, 10, 9,114, 32, 61, 32, 99, +111,108, 46,114, 59, 10, 9,103, 32, 61, 32, 99,111,108, 46,103, 59, 10, 9, 98, 32, 61, 32, 99,111,108, 46, 98, 59, 10,125, 10, + 10,118,111,105,100, 32, 99,111,109, 98,105,110,101, 95,114,103, 98, 40,102,108,111, 97,116, 32,114, 44, 32,102,108,111, 97,116, + 32,103, 44, 32,102,108,111, 97,116, 32, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108, 41, 10,123, 10, 9, 99,111, +108, 32, 61, 32,118,101, 99, 52, 40,114, 44, 32,103, 44, 32, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +111,117,116,112,117,116, 95,110,111,100,101, 40,118,101, 99, 52, 32,114,103, 98, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, + 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,111,117,116,114,103, 98, 32, 61, 32, +118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, 44, 32, 97,108,112,104, 97, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 32, 84, 69, 88, 84, 85, 82, 69, 83, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, + 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,102,108,105,112, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,118,101, + 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, +118,101, 99, 46,121,120,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,108, +105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, + 10, 9,111,117,116,118, 97,108, 32, 61, 32, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 59, 10,125, 10, 10,118, +111,105,100, 32,116,101,120,116,117,114,101, 95, 98,108,101,110,100, 95,113,117, 97,100, 40,118,101, 99, 51, 32,118,101, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111,117,116,118, 97,108, 32, 61, 32,109, + 97,120, 40, 40, 49, 46, 48, 43,118,101, 99, 46,120, 41, 47, 50, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10, 9,111,117,116,118, 97, +108, 32, 42, 61, 32,111,117,116,118, 97,108, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,119,111,111, +100, 95,115,105,110, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, + 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, + 41, 10,123, 10, 9,102,108,111, 97,116, 32, 97, 32, 61, 32,115,113,114,116, 40,118,101, 99, 46,120, 42,118,101, 99, 46,120, 32, + 43, 32,118,101, 99, 46,121, 42,118,101, 99, 46,121, 32, 43, 32,118,101, 99, 46,122, 42,118,101, 99, 46,122, 41, 42, 50, 48, 46, + 48, 59, 10, 9,102,108,111, 97,116, 32,119,105, 32, 61, 32, 48, 46, 53, 32, 43, 32, 48, 46, 53, 42,115,105,110, 40, 97, 41, 59, + 10, 10, 9,118, 97,108,117,101, 32, 61, 32,119,105, 59, 10, 9, 99,111,108,111,114, 32, 61, 32,118,101, 99, 52, 40,119,105, 44, + 32,119,105, 44, 32,119,105, 44, 32, 49, 46, 48, 41, 59, 10, 9,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 48, 46, + 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120,116,117,114,101, 95,105,109, + 97,103,101, 40,118,101, 99, 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114, +101, 50, 68, 40,105,109, 97, 44, 32, 40,118,101, 99, 46,120,121, 32, 43, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, + 41, 41, 42, 48, 46, 53, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 10, 9,110,111,114,109, 97,108, 46, +120, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108,111,114, 46,114, 32, 45, 32, 48, 46, 53, 41, 59, 10, 9,110,111,114,109, 97,108, + 46,121, 32, 61, 32, 50, 46, 48, 42, 40, 48, 46, 53, 32, 45, 32, 99,111,108,111,114, 46,103, 41, 59, 10, 9,110,111,114,109, 97, +108, 46,122, 32, 61, 32, 50, 46, 48, 42, 40, 99,111,108,111,114, 46, 98, 32, 45, 32, 48, 46, 53, 41, 59, 10,125, 10, 10, 47, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 32, 77, 84, 69, 88, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 47, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,111,114, 99,111, 40,118,101, 99, 51, 32, 97,116,116,111,114, + 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,114, 99,111, 41, 10,123, 10, 9,111,114, 99,111, 32, 61, 32, 97,116,116, +111,114, 99,111, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,117,118, 40,118,101, 99, 50, 32, 97,116,116,117, +118, 44, 32,111,117,116, 32,118,101, 99, 51, 32,117,118, 41, 10,123, 10, 9, 47, 42, 32,100,105,115, 97, 98,108,101,100, 32,102, +111,114, 32,110,111,119, 44, 32,119,111,114,107,115, 32,116,111,103,101,116,104,101,114, 32,119,105,116,104, 32,108,101, 97,118, +105,110,103, 32,111,117,116, 32,109,116,101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 10, 9, 32, 32, 32,117,118, 32, 61, + 32,118,101, 99, 51, 40, 97,116,116,117,118, 42, 50, 46, 48, 32, 45, 32,118,101, 99, 50, 40, 49, 46, 48, 44, 32, 49, 46, 48, 41, + 44, 32, 48, 46, 48, 41, 59, 32, 42, 47, 10, 9,117,118, 32, 61, 32,118,101, 99, 51, 40, 97,116,116,117,118, 44, 32, 48, 46, 48, + 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97, +108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 99,111,114, +114,101,115,112,111,110,100,115, 32,116,111, 32,115,104,105, 45, 62,111,114,110, 44, 32,119,104,105, 99,104, 32,105,115, 32,110, +101,103, 97,116,101,100, 32,115,111, 32, 99, 97,110, 99,101,108,115, 10, 9, 32, 32, 32,111,117,116, 32, 98,108,101,110,100,101, +114, 32,110,111,114,109, 97,108, 32,110,101,103, 97,116,105,111,110, 32, 42, 47, 10, 9,111,117,116,110,111,114,109, 97,108, 32, + 61, 32,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, + 99,111, 95,116, 97,110,103,101,110,116, 40,118,101, 99, 51, 32,116, 97,110,103,101,110,116, 44, 32,111,117,116, 32,118,101, 99, + 51, 32,111,117,116,116, 97,110,103,101,110,116, 41, 10,123, 10, 9,111,117,116,116, 97,110,103,101,110,116, 32, 61, 32,110,111, +114,109, 97,108,105,122,101, 40,116, 97,110,103,101,110,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95, +103,108,111, 98, 97,108, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, + 32,111,117,116, 32,118,101, 99, 51, 32,103,108,111, 98, 97,108, 41, 10,123, 10, 9,103,108,111, 98, 97,108, 32, 61, 32, 40,118, +105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 46,120,121,122, 59, 10,125, 10, + 10,118,111,105,100, 32,116,101,120, 99,111, 95,111, 98,106,101, 99,116, 40,109, 97,116, 52, 32,118,105,101,119,105,110,118,109, + 97,116, 44, 32,109, 97,116, 52, 32,111, 98,105,110,118,109, 97,116, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32, +118,101, 99, 51, 32,111, 98,106,101, 99,116, 41, 10,123, 10, 9,111, 98,106,101, 99,116, 32, 61, 32, 40,111, 98,105,110,118,109, + 97,116, 42, 40,118,105,101,119,105,110,118,109, 97,116, 42,118,101, 99, 52, 40, 99,111, 44, 32, 49, 46, 48, 41, 41, 41, 46,120, +121,122, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,120, 99,111, 95,114,101,102,108, 40,118,101, 99, 51, 32,118,110, 44, 32, +118,101, 99, 51, 32,118,105,101,119, 44, 32,111,117,116, 32,118,101, 99, 51, 32,114,101,102, 41, 10,123, 10, 9,114,101,102, 32, + 61, 32,118,105,101,119, 32, 45, 32, 50, 46, 48, 42,100,111,116, 40,118,110, 44, 32,118,105,101,119, 41, 42,118,110, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,110,111,114,109, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9, 47, 42, 32, 98,108,101,110,100,101,114, + 32,114,101,110,100,101,114, 32,110,111,114,109, 97,108, 32,105,115, 32,110,101,103, 97,116,101,100, 32, 42, 47, 10, 9,111,117, +116,110,111,114,109, 97,108, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,110,111,114,109, 97,108, 41, 59, 10,125, 10, + 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 98,108,101,110,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, + 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, +102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, + 48, 45,102, 97, 99,116, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32, +102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,109,117, +108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99, +111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99, +103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32, 40, +102, 97, 99,109, 32, 43, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115, 99,114,101,101,110, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, + 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32, +102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, + 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, + 45,102, 97, 99,103, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32, 40,118,101, + 99, 51, 40,102, 97, 99,109, 41, 32, 43, 32,102, 97, 99,116, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,116,101,120, + 99,111,108, 41, 41, 42, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,111,118,101,114,108, 97,121, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, + 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32, +102, 97, 99,109, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, + 48, 45,102, 97, 99,103, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46,114, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105, +110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, + 99,116, 42,116,101,120, 99,111,108, 46,114, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,114, 32, 61, 32, + 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101, +120, 99,111,108, 46,114, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46,114, 41, 59, 10, 10, 9,105,102, 40, +111,117,116, 99,111,108, 46,103, 32, 60, 32, 48, 46, 53, 41, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32,111,117,116, 99, +111,108, 46,103, 42, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 41, 59, + 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 46,103, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, + 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 46,103, 41, 41, 42, 40, 49, 46, 48, + 32, 45, 32,111,117,116, 99,111,108, 46,103, 41, 59, 10, 10, 9,105,102, 40,111,117,116, 99,111,108, 46, 98, 32, 60, 32, 48, 46, + 53, 41, 10, 9, 9,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 42, 40,102, 97, 99,109, 32, 43, 32, + 50, 46, 48, 42,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111, +108, 46, 98, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, 43, 32, 50, 46, 48, 42,102, 97, 99,116, 42, 40, 49, 46, + 48, 32, 45, 32,116,101,120, 99,111,108, 46, 98, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117,116, 99,111,108, 46, 98, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115,117, 98, 40,118,101, 99, 51, 32,111,117,116, 99,111, +108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, + 32, 61, 32, 45,102, 97, 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, + 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95, 97,100,100, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, + 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32, +102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,105,110, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,102, 97, 99,103, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,100,105,118, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, + 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, + 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, + 99,116, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,114, 32, 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46, +114, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,114, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46, +114, 47,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46,103, 32, 33, 61, 32, 48, 46, 48, 41, + 32,105,110, 99,111,108, 46,103, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46,103, 32, 43, 32,102, 97, 99,116, 42, +111,117,116, 99,111,108, 46,103, 47,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40,116,101,120, 99,111,108, 46, 98, 32, + 33, 61, 32, 48, 46, 48, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 46, 98, 32, + 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 46, 98, 47,116,101,120, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111,105, +100, 32,109,116,101,120, 95,114,103, 98, 95,100,105,102,102, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, + 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, + 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, + 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, 99, +116, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, + 97, 98,115, 40,116,101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, +101,120, 95,114,103, 98, 95,100, 97,114,107, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, +120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32, 99,111,108, + 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45,102, 97, + 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, 10, 9,105,102, 40, 99, +111,108, 32, 60, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99,111,108, 59, 32,101,108, +115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, + 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46,103, 41, + 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,103, 32, 61, 32,111, +117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46, 98, 59, 10, 9, +105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, 32, 61, 32, 99,111,108, + 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, 10,125, 10, 10,118,111, +105,100, 32,109,116,101,120, 95,114,103, 98, 95,108,105,103,104,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118, +101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, + 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, +109, 44, 32, 99,111,108, 59, 10, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, + 49, 46, 48, 45,102, 97, 99,116, 59, 10, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,114, 59, + 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46,114, 41, 32,105,110, 99,111,108, 46,114, 32, 61, 32, 99, +111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46,114, 32, 61, 32,111,117,116, 99,111,108, 46,114, 59, 10, 9, 99,111, +108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 46,103, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, + 99,111,108, 46,103, 41, 32,105,110, 99,111,108, 46,103, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, + 46,103, 32, 61, 32,111,117,116, 99,111,108, 46,103, 59, 10, 9, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111, +108, 46, 98, 59, 10, 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 46, 98, 41, 32,105,110, 99,111,108, 46, 98, + 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 46, 98, 32, 61, 32,111,117,116, 99,111,108, 46, 98, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,104,117,101, 40,118,101, 99, 51, 32,111,117,116, 99,111, +108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, + 99,111,108, 59, 10, 10, 9,109,105,120, 95,104,117,101, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111, +117,116, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, + 99,111,108, 41, 59, 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,115, 97,116, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, + 99, 51, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, + 10, 9,109,105,120, 95,115, 97,116, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, + 44, 32, 49, 46, 48, 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, + 10, 9,105,110, 99,111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109, +116,101,120, 95,114,103, 98, 95,118, 97,108, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101, +120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117, +116, 32,118,101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, + 95,118, 97,108, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, + 41, 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99, +111,108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, +103, 98, 95, 99,111,108,111,114, 40,118,101, 99, 51, 32,111,117,116, 99,111,108, 44, 32,118,101, 99, 51, 32,116,101,120, 99,111, +108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,111,117,116, 32,118, +101, 99, 51, 32,105,110, 99,111,108, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111,108, 59, 10, 10, 9,109,105,120, 95, 99,111, +108,111,114, 40,102, 97, 99,116, 42,102, 97, 99,103, 44, 32,118,101, 99, 52, 40,111,117,116, 99,111,108, 44, 32, 49, 46, 48, 41, + 44, 32,118,101, 99, 52, 40,116,101,120, 99,111,108, 44, 32, 49, 46, 48, 41, 44, 32, 99,111,108, 41, 59, 10, 9,105,110, 99,111, +108, 46,114,103, 98, 32, 61, 32, 99,111,108, 46,114,103, 98, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97, +108,117,101, 95,118, 97,114,115, 40,105,110,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, + 32,102, 97, 99,103, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,102, 97, 99,109, 44, 32,102,108,111, 97,116, 32,102,108,105, +112, 41, 10,123, 10, 9,102, 97, 99,116, 32, 42, 61, 32,102, 97, 99,103, 59, 10, 9,102, 97, 99,109, 32, 61, 32, 49, 46, 48, 45, +102, 97, 99,116, 59, 10, 10, 9,105,102, 40,102,108,105,112, 32, 33, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,102,108,111, 97, +116, 32,116,109,112, 32, 61, 32,102, 97, 99,116, 59, 10, 9, 9,102, 97, 99,116, 32, 61, 32,102, 97, 99,109, 59, 10, 9, 9,102, + 97, 99,109, 32, 61, 32,116,109,112, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, + 95, 98,108,101,110,100, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111, +108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, + 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, + 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42, +116,101,120, 99,111,108, 32, 43, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116, +101,120, 95,118, 97,108,117,101, 95,109,117,108, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, + 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, + 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, + 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, + 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, + 49, 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 40,102, 97, 99,109, 32, 43, 32,102, 97, 99, +116, 42,116,101,120, 99,111,108, 41, 42,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, + 97,108,117,101, 95,115, 99,114,101,101,110, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32, +116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32, +102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9, +102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99, +116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,109, 32, 61, 32, 49, + 46, 48, 32, 45, 32,102, 97, 99,103, 59, 10, 9,105,110, 99,111,108, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40,102, 97, 99,109, 32, + 43, 32,102, 97, 99,116, 42, 40, 49, 46, 48, 32, 45, 32,116,101,120, 99,111,108, 41, 41, 42, 40, 49, 46, 48, 32, 45, 32,111,117, +116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,115,117, 98, 40,102,108, +111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32, +102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109, +116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, + 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, 32, 45,102, 97, 99,116, 59, 10, 9,105,110, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109, +116,101,120, 95,118, 97,108,117,101, 95, 97,100,100, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97, +116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, + 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, + 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, + 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102, 97, 99,116, 32, 61, + 32,102, 97, 99,116, 59, 10, 9,105,110, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 32, 43, 32,111,117, +116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,118, 40,102,108,111, + 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, + 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116, +101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32, +102,108,105,112, 41, 59, 10, 10, 9,105,102, 40,116,101,120, 99,111,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, 9,105,110, 99, +111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42,111,117,116, 99,111,108, 47,116, +101,120, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,105,110, 99,111,108, 32, 61, 32, 48, 46, 48, 59, 10,125, 10, 10,118, +111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,100,105,102,102, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, + 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97, +116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, + 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95, +118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9, +105,110, 99,111,108, 32, 61, 32,102, 97, 99,109, 42,111,117,116, 99,111,108, 32, 43, 32,102, 97, 99,116, 42, 97, 98,115, 40,116, +101,120, 99,111,108, 32, 45, 32,111,117,116, 99,111,108, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97, +108,117,101, 95,100, 97,114,107, 40,102,108,111, 97,116, 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, + 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99,116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, + 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, + 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32, +102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108,105,112, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, + 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, 9,105,102, 40, 99,111,108, 32, 60, 32,111,117,116, 99,111,108, 41, 32, +105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101,108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, + 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, 95,108,105,103,104,116, 40,102,108,111, 97,116, + 32,111,117,116, 99,111,108, 44, 32,102,108,111, 97,116, 32,116,101,120, 99,111,108, 44, 32,102,108,111, 97,116, 32,102, 97, 99, +116, 44, 32,102,108,111, 97,116, 32,102, 97, 99,103, 44, 32,102,108,111, 97,116, 32,102,108,105,112, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,105,110, 99,111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,109, 59, 10, 9,109,116,101,120, + 95,118, 97,108,117,101, 95,118, 97,114,115, 40,102, 97, 99,116, 44, 32,102, 97, 99,103, 44, 32,102, 97, 99,109, 44, 32,102,108, +105,112, 41, 59, 10, 10, 9,102,108,111, 97,116, 32, 99,111,108, 32, 61, 32,102, 97, 99,116, 42,116,101,120, 99,111,108, 59, 10, + 9,105,102, 40, 99,111,108, 32, 62, 32,111,117,116, 99,111,108, 41, 32,105,110, 99,111,108, 32, 61, 32, 99,111,108, 59, 32,101, +108,115,101, 32,105,110, 99,111,108, 32, 61, 32,111,117,116, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, + 95,118, 97,108,117,101, 95, 99,108, 97,109,112, 95,112,111,115,105,116,105,118,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32,109, + 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, + 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,102, + 97, 99, 41, 10,123, 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40,102, 97, 99, 44, 32, 48, 46, 48, 44, 32, + 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, 97,114, 95,100,105,118,105,100,101, 40,102,108, +111, 97,116, 32,104, 97,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,111,117, +116,104, 97,114, 32, 61, 32,104, 97,114, 47, 49, 50, 56, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,104, + 97,114, 95,109,117,108,116,105,112,108,121, 95, 99,108, 97,109,112, 40,102,108,111, 97,116, 32,104, 97,114, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,111,117,116,104, 97,114, 41, 10,123, 10, 9,104, 97,114, 32, 42, 61, 32, 49, 50, 56, 46, 48, 59, 10, + 10, 9,105,102, 40,104, 97,114, 32, 60, 32, 49, 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 49, 46, 48, 59, 10, 9,101, +108,115,101, 32,105,102, 40,104, 97,114, 32, 62, 32, 53, 49, 49, 46, 48, 41, 32,111,117,116,104, 97,114, 32, 61, 32, 53, 49, 49, + 46, 48, 59, 10, 9,101,108,115,101, 32,111,117,116,104, 97,114, 32, 61, 32,104, 97,114, 59, 10,125, 10, 10,118,111,105,100, 32, +109,116,101,120, 95, 97,108,112,104, 97, 95,102,114,111,109, 95, 99,111,108, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117, +116, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 41, 10,123, 10, 9, 97,108,112,104, 97, 32, 61, 32, 99,111,108, 46, 97, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 97,108,112,104, 97, 95,116,111, 95, 99,111,108, 40,118,101, 99, 52, 32, + 99,111,108, 44, 32,102,108,111, 97,116, 32, 97,108,112,104, 97, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 97,108,112, +104, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98,116,111,105,110,116, 40,118,101, 99, 52, 32, +114,103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,105,110,116, +101,110,115,105,116,121, 32, 61, 32,100,111,116, 40,118,101, 99, 51, 40, 48, 46, 51, 53, 44, 32, 48, 46, 52, 53, 44, 32, 48, 46, + 50, 41, 44, 32,114,103, 98, 46,114,103, 98, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117,101, + 95,105,110,118,101,114,116, 40,102,108,111, 97,116, 32,105,110,118, 97,108,117,101, 44, 32,111,117,116, 32,102,108,111, 97,116, + 32,111,117,116,118, 97,108,117,101, 41, 10,123, 10, 9,111,117,116,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 32, 45, 32,105, +110,118, 97,108,117,101, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114,103, 98, 95,105,110,118,101,114,116, 40, +118,101, 99, 52, 32,105,110,114,103, 98, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9, +111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,118,101, 99, 51, 40, 49, 46, 48, 41, 32, 45, 32,105,110,114,103, 98, 46, +114,103, 98, 44, 32,105,110,114,103, 98, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,118, 97,108,117, +101, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116,101,110, 99,105,108, 44, 32,102,108,111, 97,116, 32,105, +110,116,101,110,115,105,116,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,111,117,116,105,110,116,101,110,115,105,116,121, 41, 10,123, 10, 9,102,108,111, 97,116, + 32,102, 97, 99,116, 32, 61, 32,105,110,116,101,110,115,105,116,121, 59, 10, 9,111,117,116,105,110,116,101,110,115,105,116,121, + 32, 61, 32,105,110,116,101,110,115,105,116,121, 42,115,116,101,110, 99,105,108, 59, 10, 9,111,117,116,115,116,101,110, 99,105, +108, 32, 61, 32,115,116,101,110, 99,105,108, 42,102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,114, +103, 98, 95,115,116,101,110, 99,105,108, 40,102,108,111, 97,116, 32,115,116,101,110, 99,105,108, 44, 32,118,101, 99, 52, 32,114, +103, 98, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,116,101,110, 99,105,108, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116,114,103, 98, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99,116, 32, 61, 32,114,103, 98, 46, 97, + 59, 10, 9,111,117,116,114,103, 98, 32, 61, 32,118,101, 99, 52, 40,114,103, 98, 46,114,103, 98, 44, 32,114,103, 98, 46, 97, 42, +115,116,101,110, 99,105,108, 41, 59, 10, 9,111,117,116,115,116,101,110, 99,105,108, 32, 61, 32,115,116,101,110, 99,105,108, 42, +102, 97, 99,116, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97,112,112,105,110,103, 95,111,102,115, 40,118, +101, 99, 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,111,102,115, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117, +116,116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, 32, 61, 32,116,101,120, 99,111, 32, 43, 32,111,102, +115, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,109, 97,112,112,105,110,103, 95,115,105,122,101, 40,118,101, 99, + 51, 32,116,101,120, 99,111, 44, 32,118,101, 99, 51, 32,115,105,122,101, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, +116,101,120, 99,111, 41, 10,123, 10, 9,111,117,116,116,101,120, 99,111, 32, 61, 32,115,105,122,101, 42,116,101,120, 99,111, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 50,100, 95,109, 97,112,112,105,110,103, 40,118,101, 99, 51, 32,118,101, + 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,118,101, 99, 41, 10,123, 10, 9,111,117,116,118,101, 99, 32, 61, 32, +118,101, 99, 51, 40,118,101, 99, 46,120,121, 42, 48, 46, 53, 32, 43, 32,118,101, 99, 50, 40, 48, 46, 53, 44, 32, 48, 46, 53, 41, + 44, 32,118,101, 99, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,105,109, 97,103,101, 40,118,101, 99, + 51, 32,118,101, 99, 44, 32,115, 97,109,112,108,101,114, 50, 68, 32,105,109, 97, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +118, 97,108,117,101, 44, 32,111,117,116, 32,118,101, 99, 52, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,118,101, 99, 51, 32, +110,111,114,109, 97,108, 41, 10,123, 10, 9, 99,111,108,111,114, 32, 61, 32,116,101,120,116,117,114,101, 50, 68, 40,105,109, 97, + 44, 32,118,101, 99, 46,120,121, 41, 59, 10, 9,118, 97,108,117,101, 32, 61, 32, 49, 46, 48, 59, 10, 9, 10, 9,110,111,114,109, + 97,108, 32, 61, 32, 50, 46, 48, 42, 40,118,101, 99, 51, 40, 99,111,108,111,114, 46,114, 44, 32, 45, 99,111,108,111,114, 46,103, + 44, 32, 99,111,108,111,114, 46, 98, 41, 32, 45, 32,118,101, 99, 51, 40, 48, 46, 53, 44, 32, 45, 48, 46, 53, 44, 32, 48, 46, 53, + 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95,110,101,103, 97,116,101, 95,116,101,120,110,111,114,109, 97, +108, 40,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97, +108, 41, 10,123, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32,118,101, 99, 51, 40, 45,110,111,114,109, 97,108, 46,120, + 44, 32, 45,110,111,114,109, 97,108, 46,121, 44, 32,110,111,114,109, 97,108, 46,122, 41, 59, 10,125, 10, 10,118,111,105,100, 32, +109,116,101,120, 95,110,115,112, 97, 99,101, 95,116, 97,110,103,101,110,116, 40,118,101, 99, 51, 32,116, 97,110,103,101,110,116, + 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,116,101,120,110,111,114,109, 97,108, 44, 32,111, +117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,116, 97,110,103,101,110,116, 32, 61, 32, +110,111,114,109, 97,108,105,122,101, 40,116, 97,110,103,101,110,116, 41, 59, 10, 9,118,101, 99, 51, 32, 66, 32, 61, 32, 99,114, +111,115,115, 40,110,111,114,109, 97,108, 44, 32,116, 97,110,103,101,110,116, 41, 59, 10, 10, 9,111,117,116,110,111,114,109, 97, +108, 32, 61, 32,116,101,120,110,111,114,109, 97,108, 46,120, 42,116, 97,110,103,101,110,116, 32, 43, 32,116,101,120,110,111,114, +109, 97,108, 46,121, 42, 66, 32, 43, 32,116,101,120,110,111,114,109, 97,108, 46,122, 42,110,111,114,109, 97,108, 59, 10, 9,111, +117,116,110,111,114,109, 97,108, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, + 10,125, 10, 10,118,111,105,100, 32,109,116,101,120, 95, 98,108,101,110,100, 95,110,111,114,109, 97,108, 40,102,108,111, 97,116, + 32,110,111,114,102, 97, 99, 44, 32,118,101, 99, 51, 32,110,111,114,109, 97,108, 44, 32,118,101, 99, 51, 32,110,101,119,110,111, +114,109, 97,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116,110,111,114,109, 97,108, 41, 10,123, 10, 9,111,117,116, +110,111,114,109, 97,108, 32, 61, 32, 40, 49, 46, 48, 32, 45, 32,110,111,114,102, 97, 99, 41, 42,110,111,114,109, 97,108, 32, 43, + 32,110,111,114,102, 97, 99, 42,110,101,119,110,111,114,109, 97,108, 59, 10, 9,111,117,116,110,111,114,109, 97,108, 32, 61, 32, +110,111,114,109, 97,108,105,122,101, 40,111,117,116,110,111,114,109, 97,108, 41, 59, 10,125, 10, 10, 47, 42, 42, 42, 42, 42, 42, + 42, 32, 77, 65, 84, 69, 82, 73, 65, 76, 32, 42, 42, 42, 42, 42, 42, 42, 42, 42, 47, 10, 10,118,111,105,100, 32,108, 97,109,112, + 95,118,105,115,105, 98,105,108,105,116,121, 95,115,117,110, 95,104,101,109,105, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, + 99, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32,108, 97,109,112,118, +101, 99, 59, 10, 9,100,105,115,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, + 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,111,116,104,101,114, 40,118, +101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,108,118, + 44, 32,111,117,116, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105, +102, 97, 99, 41, 10,123, 10, 9,108,118, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, 59, 10, 9,100,105,115,116, 32, + 61, 32,108,101,110,103,116,104, 40,108,118, 41, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,118, + 41, 59, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95, +102, 97,108,108,111,102,102, 95,105,110,118,108,105,110,101, 97,114, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, + 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, + 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, + 32, 43, 32,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,105, +110,118,115,113,117, 97,114,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100, +105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, + 97, 99, 32, 61, 32,108, 97,109,112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,100,105,115,116, 42,100, +105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, 97,108,108,111,102,102, 95,115,108,105,100,101, +114,115, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,108,100, 49, 44, 32,102,108, +111, 97,116, 32,108,100, 50, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,118, +105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116,107,119, 32, 61, 32,108, 97, +109,112,100,105,115,116, 42,108, 97,109,112,100,105,115,116, 59, 10, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,108, 97,109, +112,100,105,115,116, 47, 40,108, 97,109,112,100,105,115,116, 32, 43, 32,108,100, 49, 42,100,105,115,116, 41, 59, 10, 9,118,105, +115,105,102, 97, 99, 32, 42, 61, 32,108, 97,109,112,100,105,115,116,107,119, 47, 40,108, 97,109,112,100,105,115,116,107,119, 32, + 43, 32,108,100, 50, 42,100,105,115,116, 42,100,105,115,116, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,102, + 97,108,108,111,102,102, 95, 99,117,114,118,101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,115, 97,109, +112,108,101,114, 49, 68, 32, 99,117,114,118,101,109, 97,112, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,118,105,115,105,102, 97, 99, 32, 61, 32,116,101,120, +116,117,114,101, 49, 68, 40, 99,117,114,118,101,109, 97,112, 44, 32,100,105,115,116, 47,108, 97,109,112,100,105,115,116, 41, 46, +120, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112,104,101,114, +101, 40,102,108,111, 97,116, 32,108, 97,109,112,100,105,115,116, 44, 32,102,108,111, 97,116, 32,100,105,115,116, 44, 32,102,108, +111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, + 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 61, 32,108, 97,109,112,100,105,115,116, 32, 45, 32,100,105,115,116, 59, 10, + 10, 9,111,117,116,118,105,115,105,102, 97, 99, 61, 32,118,105,115,105,102, 97, 99, 42,109, 97,120, 40,116, 44, 32, 48, 46, 48, + 41, 47,108, 97,109,112,100,105,115,116, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108, +105,116,121, 95,115,112,111,116, 95,115,113,117, 97,114,101, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,109, 97, +116, 52, 32,108, 97,109,112,105,109, 97,116, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +105,110,112,114, 41, 10,123, 10, 9,105,102, 40,100,111,116, 40,108,118, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 62, 32, 48, + 46, 48, 41, 32,123, 10, 9, 9,118,101, 99, 51, 32,108,118,114,111,116, 32, 61, 32, 40,108, 97,109,112,105,109, 97,116, 42,118, +101, 99, 52, 40,108,118, 44, 32, 48, 46, 48, 41, 41, 46,120,121,122, 59, 10, 9, 9,102,108,111, 97,116, 32,120, 32, 61, 32,109, + 97,120, 40, 97, 98,115, 40,108,118,114,111,116, 46,120, 47,108,118,114,111,116, 46,122, 41, 44, 32, 97, 98,115, 40,108,118,114, +111,116, 46,121, 47,108,118,114,111,116, 46,122, 41, 41, 59, 10, 10, 9, 9,105,110,112,114, 32, 61, 32, 49, 46, 48, 47,115,113, +114,116, 40, 49, 46, 48, 32, 43, 32,120, 42,120, 41, 59, 10, 9,125, 10, 9,101,108,115,101, 10, 9, 9,105,110,112,114, 32, 61, + 32, 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95,115,112, +111,116, 95, 99,105,114, 99,108,101, 40,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,108,118, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112,114, 41, 10,123, 10, 9,105,110,112,114, 32, 61, 32,100,111,116, 40,108, +118, 44, 32,108, 97,109,112,118,101, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105, +108,105,116,121, 95,115,112,111,116, 40,102,108,111, 97,116, 32,115,112,111,116,115,105, 44, 32,102,108,111, 97,116, 32,115,112, +111,116, 98,108, 44, 32,102,108,111, 97,116, 32,105,110,112,114, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, + 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32, +116, 32, 61, 32,115,112,111,116,115,105, 59, 10, 10, 9,105,102, 40,105,110,112,114, 32, 60, 61, 32,116, 41, 32,123, 10, 9, 9, +111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, + 32, 61, 32,105,110,112,114, 32, 45, 32,116, 59, 10, 10, 9, 9, 47, 42, 32,115,111,102,116, 32, 97,114,101, 97, 32, 42, 47, 10, + 9, 9,105,102, 40,115,112,111,116, 98,108, 32, 33, 61, 32, 48, 46, 48, 41, 10, 9, 9, 9,105,110,112,114, 32, 42, 61, 32,115, +109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, 46, 48, 44, 32,116, 47,115,112,111,116, 98,108, 41, 59, 10, 10, + 9, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32,118,105,115,105,102, 97, 99, 42,105,110,112,114, 59, 10, 9,125, 10, +125, 10, 10,118,111,105,100, 32,108, 97,109,112, 95,118,105,115,105, 98,105,108,105,116,121, 95, 99,108, 97,109,112, 40,102,108, +111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118,105,115,105,102, 97, + 99, 41, 10,123, 10, 9,111,117,116,118,105,115,105,102, 97, 99, 32, 61, 32, 40,118,105,115,105,102, 97, 99, 32, 60, 32, 48, 46, + 48, 48, 49, 41, 63, 32, 48, 46, 48, 58, 32,118,105,115,105,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, +101, 95,118,105,101,119, 40,118,101, 99, 51, 32, 99,111, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,105,101,119, 41, 10,123, + 10, 9, 47, 42, 32,104, 97,110,100,108,101, 32,112,101,114,115,112,101, 99,116,105,118,101, 47,111,114,116,104,111,103,114, 97, +112,104,105, 99, 32, 42, 47, 10, 9,118,105,101,119, 32, 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97, +116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, 48, 46, 48, 41, 63, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, + 41, 58, 32,118,101, 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 45, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, + 32,115,104, 97,100,101, 95,116, 97,110,103,101,110,116, 95,118, 40,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, 51, 32,116, + 97,110,103, 44, 32,111,117,116, 32,118,101, 99, 51, 32,118,110, 41, 10,123, 10, 9,118,101, 99, 51, 32, 99, 32, 61, 32, 99,114, +111,115,115, 40,108,118, 44, 32,116, 97,110,103, 41, 59, 10, 9,118,101, 99, 51, 32,118,110,111,114, 32, 61, 32, 99,114,111,115, +115, 40, 99, 44, 32,116, 97,110,103, 41, 59, 10, 10, 9,118,110, 32, 61, 32, 45,110,111,114,109, 97,108,105,122,101, 40,118,110, +111,114, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,110,112, 40,118,101, 99, 51, 32,118,110, 44, 32, +118,101, 99, 51, 32,108,118, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10,123, 10, 9,105,110,112, 32, 61, + 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,110, +111, 95,100,105,102,102,117,115,101, 40,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, + 48, 46, 48, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,105,115, 95,104,101,109,105, 40,102,108,111, 97,116, + 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32, 48, 46, 53, 42, +105,110,112, 32, 43, 32, 48, 46, 53, 59, 10,125, 10, 10,102,108,111, 97,116, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110, +101,114,103,121, 40,109, 97,116, 52, 32, 97,114,101, 97, 44, 32,118,101, 99, 51, 32, 99,111, 44, 32,118,101, 99, 51, 32,118,110, + 41, 10,123, 10, 9,118,101, 99, 51, 32,118,101, 99, 91, 52, 93, 44, 32, 99, 91, 52, 93, 59, 10, 9,102,108,111, 97,116, 32,114, + 97,100, 91, 52, 93, 44, 32,102, 97, 99, 59, 10, 9, 10, 9,118,101, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122, +101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 48, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, 91, 49, 93, 32, 61, 32,110, +111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 49, 93, 46,120,121,122, 41, 59, 10, 9,118,101, 99, + 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, 91, 50, 93, 46,120,121,122, + 41, 59, 10, 9,118,101, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,111, 32, 45, 32, 97,114,101, 97, + 91, 51, 93, 46,120,121,122, 41, 59, 10, 10, 9, 99, 91, 48, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111, +115,115, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, 41, 59, 10, 9, 99, 91, 49, 93, 32, 61, 32,110,111,114, +109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9, + 99, 91, 50, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, 40,118,101, 99, 91, 50, 93, 44, 32,118, +101, 99, 91, 51, 93, 41, 41, 59, 10, 9, 99, 91, 51, 93, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40, 99,114,111,115,115, + 40,118,101, 99, 91, 51, 93, 44, 32,118,101, 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,114, 97,100, 91, 48, 93, 32, 61, 32, 97, 99, +111,115, 40,100,111,116, 40,118,101, 99, 91, 48, 93, 44, 32,118,101, 99, 91, 49, 93, 41, 41, 59, 10, 9,114, 97,100, 91, 49, 93, + 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 49, 93, 44, 32,118,101, 99, 91, 50, 93, 41, 41, 59, 10, 9,114, + 97,100, 91, 50, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 50, 93, 44, 32,118,101, 99, 91, 51, 93, 41, + 41, 59, 10, 9,114, 97,100, 91, 51, 93, 32, 61, 32, 97, 99,111,115, 40,100,111,116, 40,118,101, 99, 91, 51, 93, 44, 32,118,101, + 99, 91, 48, 93, 41, 41, 59, 10, 10, 9,102, 97, 99, 61, 32, 32,114, 97,100, 91, 48, 93, 42,100,111,116, 40,118,110, 44, 32, 99, + 91, 48, 93, 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 49, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 49, 93, + 41, 59, 10, 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 50, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 50, 93, 41, 59, 10, + 9,102, 97, 99, 43, 61, 32,114, 97,100, 91, 51, 93, 42,100,111,116, 40,118,110, 44, 32, 99, 91, 51, 93, 41, 59, 10, 10, 9,114, +101,116,117,114,110, 32,109, 97,120, 40,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,105,110,112, 95, 97,114,101, 97, 40,118,101, 99, 51, 32,112,111,115,105,116,105,111,110, 44, 32,118,101, 99, 51, 32, +108, 97,109,112, 99,111, 44, 32,118,101, 99, 51, 32,108, 97,109,112,118,101, 99, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,109, + 97,116, 52, 32, 97,114,101, 97, 44, 32,102,108,111, 97,116, 32, 97,114,101, 97,115,105,122,101, 44, 32,102,108,111, 97,116, 32, +107, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,110,112, 41, 10,123, 10, 9,118,101, 99, 51, 32, 99,111, 32, 61, 32,112, +111,115,105,116,105,111,110, 59, 10, 9,118,101, 99, 51, 32,118,101, 99, 32, 61, 32, 99,111, 32, 45, 32,108, 97,109,112, 99,111, + 59, 10, 10, 9,105,102, 40,100,111,116, 40,118,101, 99, 44, 32,108, 97,109,112,118,101, 99, 41, 32, 60, 32, 48, 46, 48, 41, 32, +123, 10, 9, 9,105,110,112, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97, +116, 32,105,110,116,101,110,115, 32, 61, 32, 97,114,101, 97, 95,108, 97,109,112, 95,101,110,101,114,103,121, 40, 97,114,101, 97, + 44, 32, 99,111, 44, 32,118,110, 41, 59, 10, 10, 9, 9,105,110,112, 32, 61, 32,112,111,119, 40,105,110,116,101,110,115, 42, 97, +114,101, 97,115,105,122,101, 44, 32,107, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105, +102,102,117,115,101, 95,111,114,101,110, 95,110, 97,121,101,114, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32, +110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,111,117,103,104, 44, 32, +111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108, +105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40, +110, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, + 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9,102,108,111, 97,116, 32,114,101, 97,108,110,108, 32, 61, 32,100,111, +116, 40,110, 44, 32,108, 41, 59, 10, 10, 9,105,102, 40,114,101, 97,108,110,108, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, +105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105,102, 40,110,108, 32, 60, 32, 48, 46, 48, 41, 32, +123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, + 32,118,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, + 97,116, 32, 76,105,116, 95, 65, 32, 61, 32, 97, 99,111,115, 40,114,101, 97,108,110,108, 41, 59, 10, 9, 9,102,108,111, 97,116, + 32, 86,105,101,119, 95, 65, 32, 61, 32, 97, 99,111,115, 40,110,118, 41, 59, 10, 10, 9, 9,118,101, 99, 51, 32, 76,105,116, 95, + 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 45, 32,114,101, 97,108,110,108, 42,110, 41, 59, 10, 9, 9,118, +101, 99, 51, 32, 86,105,101,119, 95, 66, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 45, 32,110,118, 42,110, 41, + 59, 10, 10, 9, 9,102,108,111, 97,116, 32,116, 32, 61, 32,109, 97,120, 40,100,111,116, 40, 76,105,116, 95, 66, 44, 32, 86,105, +101,119, 95, 66, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,102,108,111, 97,116, 32, 97, 44, 32, 98, 59, 10, 10, 9, 9,105, +102, 40, 76,105,116, 95, 65, 32, 62, 32, 86,105,101,119, 95, 65, 41, 32,123, 10, 9, 9, 9, 97, 32, 61, 32, 76,105,116, 95, 65, + 59, 10, 9, 9, 9, 98, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, + 9, 97, 32, 61, 32, 86,105,101,119, 95, 65, 59, 10, 9, 9, 9, 98, 32, 61, 32, 76,105,116, 95, 65, 59, 10, 9, 9,125, 10, 10, + 9, 9,102,108,111, 97,116, 32, 65, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 48, 46, 53, 42, 40, 40,114,111,117,103,104, 42,114, +111,117,103,104, 41, 47, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, 46, 51, 51, 41, 41, 41, 59, 10, + 9, 9,102,108,111, 97,116, 32, 66, 32, 61, 32, 48, 46, 52, 53, 42, 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 47, + 40, 40,114,111,117,103,104, 42,114,111,117,103,104, 41, 32, 43, 32, 48, 46, 48, 57, 41, 41, 59, 10, 10, 9, 9, 98, 32, 42, 61, + 32, 48, 46, 57, 53, 59, 10, 9, 9,105,115, 32, 61, 32,110,108, 42, 40, 65, 32, 43, 32, 40, 66, 32, 42, 32,116, 32, 42, 32,115, +105,110, 40, 97, 41, 32, 42, 32,116, 97,110, 40, 98, 41, 41, 41, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,100,105,102,102,117,115,101, 95,116,111,111,110, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32, +118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116, +104, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, + 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115, +108,116, 41, 59, 10, 10, 9,105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,105,115, 32, 61, 32, 49, 46, 48, 59, 10, + 9,101,108,115,101, 32,105,102, 40, 97,110,103, 32, 62, 32, 40,115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32, +124,124, 32,116,115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108, +115,101, 32,105,115, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111, +111,116,104, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,100,105,102,102,117,115,101, 95,109,105,110,110, + 97,101,114,116, 40,102,108,111, 97,116, 32,110,108, 44, 32,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,118, 44, 32,102, +108,111, 97,116, 32,100, 97,114,107,110,101,115,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9, +105,102, 40,110,108, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,105,115, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9, +101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, + 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9, 9,105,102, 40,100, 97,114,107,110,101,115,115, 32, 60, 61, 32, 49, 46, 48, 41, 10, + 9, 9, 9,105,115, 32, 61, 32,110,108, 42,112,111,119, 40,109, 97,120, 40,110,118, 42,110,108, 44, 32, 48, 46, 49, 41, 44, 32, +100, 97,114,107,110,101,115,115, 32, 45, 32, 49, 46, 48, 41, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,105,115, 32, 61, 32, +110,108, 42,112,111,119, 40, 49, 46, 48, 48, 48, 49, 32, 45, 32,110,118, 44, 32,100, 97,114,107,110,101,115,115, 32, 45, 32, 49, + 46, 48, 41, 59, 10, 9,125, 10,125, 10, 10,102,108,111, 97,116, 32,102,114,101,115,110,101,108, 95,102, 97, 99, 40,118,101, 99, + 51, 32,118,105,101,119, 44, 32,118,101, 99, 51, 32,118,110, 44, 32,102,108,111, 97,116, 32,103,114, 97,100, 44, 32,102,108,111, + 97,116, 32,102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,116, 49, 44, 32,116, 50, 59, 10, 9,102,108,111, 97,116, 32, +102,102, 97, 99, 59, 10, 10, 9,105,102, 40,102, 97, 99, 61, 61, 48, 46, 48, 41, 32,123, 10, 9, 9,102,102, 97, 99, 32, 61, 32, + 49, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,116, 49, 61, 32,100,111,116, 40,118,105,101,119, 44, 32, +118,110, 41, 59, 10, 9, 9,105,102, 40,116, 49, 62, 48, 46, 48, 41, 32, 32,116, 50, 61, 32, 49, 46, 48, 43,116, 49, 59, 10, 9, + 9,101,108,115,101, 32,116, 50, 61, 32, 49, 46, 48, 45,116, 49, 59, 10, 10, 9, 9,116, 50, 61, 32,103,114, 97,100, 32, 43, 32, + 40, 49, 46, 48, 45,103,114, 97,100, 41, 42,112,111,119, 40,116, 50, 44, 32,102, 97, 99, 41, 59, 10, 10, 9, 9,105,102, 40,116, + 50, 60, 48, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,105,102, 40,116, 50, 62, + 49, 46, 48, 41, 32,102,102, 97, 99, 32, 61, 32, 49, 46, 48, 59, 10, 9, 9,101,108,115,101, 32,102,102, 97, 99, 32, 61, 32,116, + 50, 59, 10, 9,125, 10, 10, 9,114,101,116,117,114,110, 32,102,102, 97, 99, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,100,105,102,102,117,115,101, 95,102,114,101,115,110,101,108, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, + 32,108,118, 44, 32,118,101, 99, 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,102, 97, 99, 95,105, 44, 32,102,108,111, + 97,116, 32,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,105,115, 41, 10,123, 10, 9,105,115, 32, 61, 32,102,114, +101,115,110,101,108, 95,102, 97, 99, 40,108,118, 44, 32,118,110, 44, 32,102, 97, 99, 95,105, 44, 32,102, 97, 99, 41, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 99,117, 98,105, 99, 40,102,108,111, 97,116, 32,105,115, 44, 32,111,117,116, + 32,102,108,111, 97,116, 32,111,117,116,105,115, 41, 10,123, 10, 9,105,102, 40,105,115, 62, 48, 46, 48, 32, 38, 38, 32,105,115, + 60, 49, 46, 48, 41, 10, 9, 9,111,117,116,105,115, 61, 32,115,109,111,111,116,104,115,116,101,112, 40, 48, 46, 48, 44, 32, 49, + 46, 48, 44, 32,105,115, 41, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116,105,115, 61, 32,105,115, 59, 10,125, 10, 10,118, +111,105,100, 32,115,104, 97,100,101, 95,118,105,115,105,102, 97, 99, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, + 32,118,105,115,105,102, 97, 99, 44, 32,102,108,111, 97,116, 32,114,101,102,108, 44, 32,111,117,116, 32,102,108,111, 97,116, 32, +111,117,116,105, 41, 10,123, 10, 9, 47, 42,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, 42, 47, 10, 9, 9,111,117,116,105, 32, + 61, 32,109, 97,120, 40,105, 42,118,105,115,105,102, 97, 99, 42,114,101,102,108, 44, 32, 48, 46, 48, 41, 59, 10, 9, 47, 42,101, +108,115,101, 10, 9, 9,111,117,116,105, 32, 61, 32,105, 59, 42, 47, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, +116, 97,110,103,101,110,116, 95,118, 95,115,112,101, 99, 40,118,101, 99, 51, 32,116, 97,110,103, 44, 32,111,117,116, 32,118,101, + 99, 51, 32,118,110, 41, 10,123, 10, 9,118,110, 32, 61, 32,116, 97,110,103, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95, 97,100,100, 95,116,111, 95,100,105,102,102,117,115,101, 40,102,108,111, 97,116, 32,105, 44, 32,118,101, 99, 51, 32, +108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 51, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,105,102, 40,105, 32, 62, 32, 48, 46, 48, 41, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,105, 42, +108, 97,109,112, 99,111,108, 42, 99,111,108, 59, 10, 9,101,108,115,101, 10, 9, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, + 99, 51, 40, 48, 46, 48, 44, 32, 48, 46, 48, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,104,101,109,105, 95,115,112,101, 99, 40,118,101, 99, 51, 32,118,110, 44, 32,118,101, 99, 51, 32,108,118, 44, 32,118,101, 99, + 51, 32,118,105,101,119, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32, +102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,108, +118, 32, 43, 61, 32,118,105,101,119, 59, 10, 9,108,118, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108,118, 41, 59, 10, + 10, 9,116, 32, 61, 32,100,111,116, 40,118,110, 44, 32,108,118, 41, 59, 10, 9,116, 32, 61, 32, 48, 46, 53, 42,116, 32, 43, 32, + 48, 46, 53, 59, 10, 10, 9,116, 32, 61, 32,118,105,115,105,102, 97, 99, 42,115,112,101, 99, 42,112,111,119, 40,116, 44, 32,104, + 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,112,104,111,110,103, 95,115,112,101, 99, 40,118, +101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114, +100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, + 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, + 61, 32,109, 97,120, 40,100,111,116, 40,104, 44, 32,110, 41, 44, 32, 48, 46, 48, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, + 32, 61, 32,112,111,119, 40,114,115,108,116, 44, 32,104, 97,114,100, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100, +101, 95, 99,111,111,107,116,111,114,114, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32, +118,101, 99, 51, 32,118, 44, 32,102,108,111, 97,116, 32,104, 97,114,100, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112, +101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, + 32,108, 41, 59, 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 10, 9,105,102, + 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, + 10, 9,101,108,115,101, 32,123, 10, 9, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, + 32,118, 41, 44, 32, 48, 46, 48, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,105, 32, 61, 32,112,111,119, 40,110,104, 44, 32,104, + 97,114,100, 41, 59, 10, 10, 9, 9,105, 32, 61, 32,105, 47, 40, 48, 46, 49, 43,110,118, 41, 59, 10, 9, 9,115,112,101, 99,102, + 97, 99, 32, 61, 32,105, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 98,108,105,110,110, 95,115, +112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32,102,108,111, 97, +116, 32,114,101,102,114, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 95,112,111,119,101,114, 44, 32,111,117,116, 32, +102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,105,102, 40,114,101,102,114, 97, 99, 32, 60, 32, 49, 46, + 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,105, +102, 40,115,112,101, 99, 95,112,111,119,101,114, 32, 61, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,115,112,101, 99,102, 97, 99, + 32, 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,105,102, 40,115,112,101, 99, 95,112,111,119, +101,114, 60, 49, 48, 48, 46, 48, 41, 10, 9, 9, 9,115,112,101, 99, 95,112,111,119,101,114, 61, 32,115,113,114,116, 40, 49, 46, + 48, 47,115,112,101, 99, 95,112,111,119,101,114, 41, 59, 10, 9, 9,101,108,115,101, 10, 9, 9, 9,115,112,101, 99, 95,112,111, +119,101,114, 61, 32, 49, 48, 46, 48, 47,115,112,101, 99, 95,112,111,119,101,114, 59, 10, 10, 9, 9,118,101, 99, 51, 32,104, 32, + 61, 32,110,111,114,109, 97,108,105,122,101, 40,118, 32, 43, 32,108, 41, 59, 10, 9, 9,102,108,111, 97,116, 32,110,104, 32, 61, + 32,100,111,116, 40,110, 44, 32,104, 41, 59, 10, 9, 9,105,102, 40,110,104, 32, 60, 32, 48, 46, 48, 41, 32,123, 10, 9, 9, 9, +115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, 9, 9,125, 10, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9,102, +108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, + 9, 9, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,100,111,116, 40,110, 44, 32,108, 41, 59, 10, 9, 9, 9,105,102, 40,110, +108, 32, 60, 61, 32, 48, 46, 48, 49, 41, 32,123, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, 32, 48, 46, 48, 59, 10, + 9, 9, 9,125, 10, 9, 9, 9,101,108,115,101, 32,123, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,118,104, 32, 61, 32,109, 97, +120, 40,100,111,116, 40,118, 44, 32,104, 41, 44, 32, 48, 46, 48, 49, 41, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 97, + 32, 61, 32, 49, 46, 48, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 98, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,118, + 41, 47,118,104, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32, 99, 32, 61, 32, 40, 50, 46, 48, 42,110,104, 42,110,108, 41, 47, +118,104, 59, 10, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,103, 32, 61, 32, 48, 46, 48, 59, 10, 10, 9, 9, 9, 9,105,102, 40, + 97, 32, 60, 32, 98, 32, 38, 38, 32, 97, 32, 60, 32, 99, 41, 32,103, 32, 61, 32, 97, 59, 10, 9, 9, 9, 9,101,108,115,101, 32, +105,102, 40, 98, 32, 60, 32, 97, 32, 38, 38, 32, 98, 32, 60, 32, 99, 41, 32,103, 32, 61, 32, 98, 59, 10, 9, 9, 9, 9,101,108, +115,101, 32,105,102, 40, 99, 32, 60, 32, 97, 32, 38, 38, 32, 99, 32, 60, 32, 98, 41, 32,103, 32, 61, 32, 99, 59, 10, 10, 9, 9, + 9, 9,102,108,111, 97,116, 32,112, 32, 61, 32,115,113,114,116, 40, 40, 40,114,101,102,114, 97, 99, 32, 42, 32,114,101,102,114, + 97, 99, 41, 43, 40,118,104, 42,118,104, 41, 45, 49, 46, 48, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97,116, 32,102, 32, 61, + 32, 40, 40, 40,112, 45,118,104, 41, 42, 40,112, 45,118,104, 41, 41, 47, 40, 40,112, 43,118,104, 41, 42, 40,112, 43,118,104, 41, + 41, 41, 42, 40, 49, 46, 48, 43, 40, 40, 40, 40,118,104, 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 42, 40, 40,118,104, + 42, 40,112, 43,118,104, 41, 41, 45, 49, 46, 48, 41, 41, 47, 40, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, + 41, 42, 40, 40,118,104, 42, 40,112, 45,118,104, 41, 41, 43, 49, 46, 48, 41, 41, 41, 41, 59, 10, 9, 9, 9, 9,102,108,111, 97, +116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,110,104, 41, 59, 10, 10, 9, 9, 9, 9,115,112,101, 99,102, 97, 99, 32, 61, + 32,109, 97,120, 40,102, 42,103, 42,101,120,112, 95, 98,108,101,110,100,101,114, 40, 40, 45, 40, 97,110,103, 42, 97,110,103, 41, + 47, 40, 50, 46, 48, 42,115,112,101, 99, 95,112,111,119,101,114, 42,115,112,101, 99, 95,112,111,119,101,114, 41, 41, 41, 44, 32, + 48, 46, 48, 41, 59, 10, 9, 9, 9,125, 10, 9, 9,125, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, +119, 97,114,100,105,115,111, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, + 51, 32,118, 44, 32,102,108,111, 97,116, 32,114,109,115, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,115,112,101, 99,102, 97, + 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108,105,122,101, 40,108, 32, 43, 32,118, 41, 59, + 10, 9,102,108,111, 97,116, 32,110,104, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,104, 41, 44, 32, 48, 46, 48, 48, + 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,118, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,118, 41, 44, 32, 48, + 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32,110,108, 32, 61, 32,109, 97,120, 40,100,111,116, 40,110, 44, 32,108, 41, + 44, 32, 48, 46, 48, 48, 49, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103,108,101, 32, 61, 32,116, 97,110, 40, 97, 99,111, +115, 40,110,104, 41, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,108,112,104, 97, 32, 61, 32,109, 97,120, 40,114,109,115, 44, 32, + 48, 46, 48, 48, 49, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 61, 32,110,108, 32, 42, 32, 40, 49, 46, 48, 47, 40, 52, 46, + 48, 42, 77, 95, 80, 73, 42, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 42, 40,101,120,112, 95, 98,108,101,110,100,101, +114, 40, 45, 40, 97,110,103,108,101, 42, 97,110,103,108,101, 41, 47, 40, 97,108,112,104, 97, 42, 97,108,112,104, 97, 41, 41, 47, + 40,115,113,114,116, 40,110,118, 42,110,108, 41, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,116,111, +111,110, 95,115,112,101, 99, 40,118,101, 99, 51, 32,110, 44, 32,118,101, 99, 51, 32,108, 44, 32,118,101, 99, 51, 32,118, 44, 32, +102,108,111, 97,116, 32,115,105,122,101, 44, 32,102,108,111, 97,116, 32,116,115,109,111,111,116,104, 44, 32,111,117,116, 32,102, +108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 41, 10,123, 10, 9,118,101, 99, 51, 32,104, 32, 61, 32,110,111,114,109, 97,108, +105,122,101, 40,108, 32, 43, 32,118, 41, 59, 10, 9,102,108,111, 97,116, 32,114,115,108,116, 32, 61, 32,100,111,116, 40,104, 44, + 32,110, 41, 59, 10, 9,102,108,111, 97,116, 32, 97,110,103, 32, 61, 32, 97, 99,111,115, 40,114,115,108,116, 41, 59, 10, 10, 9, +105,102, 40, 97,110,103, 32, 60, 32,115,105,122,101, 41, 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 59, 10, 9,101,108,115,101, + 32,105,102, 40, 97,110,103, 32, 62, 61, 32, 40,115,105,122,101, 32, 43, 32,116,115,109,111,111,116,104, 41, 32,124,124, 32,116, +115,109,111,111,116,104, 32, 61, 61, 32, 48, 46, 48, 41, 32,114,115,108,116, 32, 61, 32, 48, 46, 48, 59, 10, 9,101,108,115,101, + 32,114,115,108,116, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 40, 97,110,103, 32, 45, 32,115,105,122,101, 41, 47,116,115,109,111, +111,116,104, 41, 59, 10, 10, 9,115,112,101, 99,102, 97, 99, 32, 61, 32,114,115,108,116, 59, 10,125, 10, 10,118,111,105,100, 32, +115,104, 97,100,101, 95,115,112,101, 99, 95, 97,114,101, 97, 95,105,110,112, 40,102,108,111, 97,116, 32,115,112,101, 99,102, 97, + 99, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,115,112,101, 99,102, + 97, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99,102, 97, 99, 32, 61, 32,115,112,101, 99,102, 97, 99, 42,105,110,112, 59, + 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,115,112,101, 99, 95,116, 40,102,108,111, 97,116, 32,115,104, 97,100, +102, 97, 99, 44, 32,102,108,111, 97,116, 32,115,112,101, 99, 44, 32,102,108,111, 97,116, 32,118,105,115,105,102, 97, 99, 44, 32, +102,108,111, 97,116, 32,115,112,101, 99,102, 97, 99, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,116, 41, 10,123, 10, 9,116, + 32, 61, 32,115,104, 97,100,102, 97, 99, 42,115,112,101, 99, 42,118,105,115,105,102, 97, 99, 42,115,112,101, 99,102, 97, 99, 59, + 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 95,115,112,101, 99, 40,102,108,111, 97,116, 32,116, 44, + 32,118,101, 99, 51, 32,108, 97,109,112, 99,111,108, 44, 32,118,101, 99, 51, 32,115,112,101, 99, 99,111,108, 44, 32,111,117,116, + 32,118,101, 99, 51, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,116, 42,108, 97,109,112, + 99,111,108, 42,115,112,101, 99, 99,111,108, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,100,100, 40,118, +101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117, +116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 49, 32, 43, 32, 99,111,108, 50, 59, 10,125, + 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, + 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99,111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 32, 43, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10, +125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109, 97,100,100,102, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,102,108, +111, 97,116, 32,102, 44, 32,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111, +108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 32, 43, 32,102, 42, 99,111,108, 49, 59, 10,125, 10, 10, +118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 40,118,101, 99, 52, 32, 99,111,108, 49, 44, 32,118,101, 99, 52, 32, 99, +111,108, 50, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, + 61, 32, 99,111,108, 49, 42, 99,111,108, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,109,117,108, 95,118, + 97,108,117,101, 40,102,108,111, 97,116, 32,102, 97, 99, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, + 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32, 99,111,108, 42,102, 97, 99, 59, 10, +125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32, +118,101, 99, 52, 32,111, 98, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9, +111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40, 99,111,108, 46,114,103, 98, 42,111, 98, 99,111,108, 46,114,103, 98, 44, + 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105,100, 32,114, 97,109,112, 95,114,103, 98,116,111, 98,119, 40,118,101, + 99, 51, 32, 99,111,108,111,114, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116,118, 97,108, 41, 10,123, 10, 9,111, +117,116,118, 97,108, 32, 61, 32, 99,111,108,111,114, 46,114, 42, 48, 46, 51, 32, 43, 32, 99,111,108,111,114, 46,103, 42, 48, 46, + 53, 56, 32, 43, 32, 99,111,108,111,114, 46, 98, 42, 48, 46, 49, 50, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,111,110,108,121, 95,115,104, 97,100,111,119, 40,102,108,111, 97,116, 32,105, 44, 32,102,108,111, 97,116, 32,115,104, 97,100, +102, 97, 99, 44, 32,102,108,111, 97,116, 32,101,110,101,114,103,121, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, +115,104, 97,100,102, 97, 99, 41, 10,123, 10, 9,111,117,116,115,104, 97,100,102, 97, 99, 32, 61, 32,105, 42,101,110,101,114,103, +121, 42, 40, 49, 46, 48, 32, 45, 32,115,104, 97,100,102, 97, 99, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,100,105,102,102,117,115,101, 40,102,108,111, 97,116, 32,115,104, 97,100,102, + 97, 99, 44, 32,118,101, 99, 51, 32,114,103, 98, 44, 32,118,101, 99, 52, 32,100,105,102,102, 44, 32,111,117,116, 32,118,101, 99, + 52, 32,111,117,116,100,105,102,102, 41, 10,123, 10, 9,111,117,116,100,105,102,102, 32, 61, 32,100,105,102,102, 32, 45, 32,118, +101, 99, 52, 40,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115, +104, 97,100,101, 95,111,110,108,121, 95,115,104, 97,100,111,119, 95,115,112,101, 99,117,108, 97,114, 40,102,108,111, 97,116, 32, +115,104, 97,100,102, 97, 99, 44, 32,118,101, 99, 51, 32,115,112,101, 99,114,103, 98, 44, 32,118,101, 99, 52, 32,115,112,101, 99, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116,115,112,101, 99, 41, 10,123, 10, 9,111,117,116,115,112,101, 99, 32, 61, + 32,115,112,101, 99, 32, 45, 32,118,101, 99, 52, 40,115,112,101, 99,114,103, 98, 42,115,104, 97,100,102, 97, 99, 44, 32, 48, 46, + 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,116,101,115,116, 95,115,104, 97,100,111,119, 98,117,102, 40,118,101, 99, 51, 32, +114, 99,111, 44, 32,115, 97,109,112,108,101,114, 50, 68, 83,104, 97,100,111,119, 32,115,104, 97,100,111,119,109, 97,112, 44, 32, +109, 97,116, 52, 32,115,104, 97,100,111,119,112,101,114,115,109, 97,116, 44, 32,102,108,111, 97,116, 32,115,104, 97,100,111,119, + 98,105, 97,115, 44, 32,102,108,111, 97,116, 32,105,110,112, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,114,101,115,117,108, +116, 41, 10,123, 10, 9,105,102, 40,105,110,112, 32, 60, 61, 32, 48, 46, 48, 41, 32,123, 10, 9, 9,114,101,115,117,108,116, 32, + 61, 32, 48, 46, 48, 59, 10, 9,125, 10, 9,101,108,115,101, 32,123, 10, 9, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,115,104, + 97,100,111,119,112,101,114,115,109, 97,116, 42,118,101, 99, 52, 40,114, 99,111, 44, 32, 49, 46, 48, 41, 59, 10, 10, 9, 9, 47, + 47,102,108,111, 97,116, 32, 98,105, 97,115, 32, 61, 32, 40, 49, 46, 53, 32, 45, 32,105,110,112, 42,105,110,112, 41, 42,115,104, + 97,100,111,119, 98,105, 97,115, 59, 10, 9, 9, 99,111, 46,122, 32, 45, 61, 32,115,104, 97,100,111,119, 98,105, 97,115, 42, 99, +111, 46,119, 59, 10, 10, 9, 9,114,101,115,117,108,116, 32, 61, 32,115,104, 97,100,111,119, 50, 68, 80,114,111,106, 40,115,104, + 97,100,111,119,109, 97,112, 44, 32, 99,111, 41, 46,120, 59, 10, 9,125, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, + 95,101,120,112,111,115,117,114,101, 95, 99,111,114,114,101, 99,116, 40,118,101, 99, 51, 32, 99,111,108, 44, 32,102,108,111, 97, +116, 32,108,105,110,102, 97, 99, 44, 32,102,108,111, 97,116, 32,108,111,103,102, 97, 99, 44, 32,111,117,116, 32,118,101, 99, 51, + 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,108,105,110,102, 97, 99, 42, 40, 49, 46, 48, + 32, 45, 32,101,120,112, 40, 99,111,108, 42,108,111,103,102, 97, 99, 41, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97, +100,101, 95,109,105,115,116, 95,102, 97, 99,116,111,114, 40,118,101, 99, 51, 32, 99,111, 44, 32,102,108,111, 97,116, 32,109,105, +115,116,115,116, 97, 44, 32,102,108,111, 97,116, 32,109,105,115,116,100,105,115,116, 44, 32,102,108,111, 97,116, 32,109,105,115, +116,116,121,112,101, 44, 32,102,108,111, 97,116, 32,109,105,115,105, 44, 32,111,117,116, 32,102,108,111, 97,116, 32,111,117,116, +102, 97, 99, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 44, 32,122, 99,111,114, 59, 10, 10, 9,122, 99,111,114, 32, + 61, 32, 40,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 91, 51, 93, 91, 51, 93, 32, 61, 61, 32, + 48, 46, 48, 41, 63, 32,108,101,110,103,116,104, 40, 99,111, 41, 58, 32, 45, 99,111, 91, 50, 93, 59, 10, 9, 10, 9,102, 97, 99, + 32, 61, 32, 99,108, 97,109,112, 40, 40,122, 99,111,114, 45,109,105,115,116,115,116, 97, 41, 47,109,105,115,116,100,105,115,116, + 44, 32, 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,105,102, 40,109,105,115,116,116,121,112,101, 32, 61, 61, 32, 48, 46, 48, + 41, 32,102, 97, 99, 32, 42, 61, 32,102, 97, 99, 59, 10, 9,101,108,115,101, 32,105,102, 40,109,105,115,116,116,121,112,101, 32, + 61, 61, 32, 49, 46, 48, 41, 59, 10, 9,101,108,115,101, 32,102, 97, 99, 32, 61, 32,115,113,114,116, 40,102, 97, 99, 41, 59, 10, + 10, 9,111,117,116,102, 97, 99, 32, 61, 32, 49, 46, 48, 32, 45, 32, 40, 49, 46, 48, 45,102, 97, 99, 41, 42, 40, 49, 46, 48, 45, +109,105,115,105, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95,119,111,114,108,100, 95,109,105,120, 40,118, +101, 99, 51, 32,104,111,114, 44, 32,118,101, 99, 52, 32, 99,111,108, 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99, +111,108, 41, 10,123, 10, 9,102,108,111, 97,116, 32,102, 97, 99, 32, 61, 32, 99,108, 97,109,112, 40, 99,111,108, 46, 97, 44, 32, + 48, 46, 48, 44, 32, 49, 46, 48, 41, 59, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, 40,109,105,120, 40,104,111, +114, 44, 32, 99,111,108, 46,114,103, 98, 44, 32,102, 97, 99, 41, 44, 32, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10,118,111,105, +100, 32,115,104, 97,100,101, 95, 97,108,112,104, 97, 95,111,112, 97,113,117,101, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,111, +117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118,101, 99, 52, + 40, 99,111,108, 46,114,103, 98, 44, 32, 49, 46, 48, 41, 59, 10,125, 10, 10,118,111,105,100, 32,115,104, 97,100,101, 95, 97,108, +112,104, 97, 95,111, 98, 99,111,108,111,114, 40,118,101, 99, 52, 32, 99,111,108, 44, 32,118,101, 99, 52, 32,111, 98, 99,111,108, + 44, 32,111,117,116, 32,118,101, 99, 52, 32,111,117,116, 99,111,108, 41, 10,123, 10, 9,111,117,116, 99,111,108, 32, 61, 32,118, +101, 99, 52, 40, 99,111,108, 46,114,103, 98, 44, 32, 99,111,108, 46, 97, 42,111, 98, 99,111,108, 46, 97, 41, 59, 10,125, 10, 10, + 0}; + diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl b/source/blender/gpu/intern/gpu_shader_vertex.glsl new file mode 100644 index 00000000000..ba9ef7dead6 --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_vertex.glsl @@ -0,0 +1,12 @@ + +varying vec3 varposition; +varying vec3 varnormal; + +void main() +{ + vec4 co = gl_ModelViewMatrix * gl_Vertex; + + varposition = co.xyz; + varnormal = gl_NormalMatrix * gl_Normal; + gl_Position = gl_ProjectionMatrix * co; + diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl.c b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c new file mode 100644 index 00000000000..edf93d838d5 --- /dev/null +++ b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c @@ -0,0 +1,13 @@ +/* DataToC output of file */ + +int datatoc_gpu_shader_vertex_glsl_size= 217; +char datatoc_gpu_shader_vertex_glsl[]= { + 10,118, 97,114,121,105,110,103, 32,118,101, 99, 51, 32,118, 97,114,112,111,115,105,116,105,111,110, + 59, 10,118, 97,114,121,105,110,103, 32,118,101, 99, 51, 32,118, 97,114,110,111,114,109, 97,108, 59, 10, 10,118,111,105,100, 32, +109, 97,105,110, 40, 41, 10,123, 10, 9,118,101, 99, 52, 32, 99,111, 32, 61, 32,103,108, 95, 77,111,100,101,108, 86,105,101,119, + 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 86,101,114,116,101,120, 59, 10, 10, 9,118, 97,114,112,111,115,105,116,105,111, +110, 32, 61, 32, 99,111, 46,120,121,122, 59, 10, 9,118, 97,114,110,111,114,109, 97,108, 32, 61, 32,103,108, 95, 78,111,114,109, + 97,108, 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 78,111,114,109, 97,108, 59, 10, 9,103,108, 95, 80,111,115,105,116,105, +111,110, 32, 61, 32,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 32, 42, 32, 99,111, 59, 10, 10, + 0}; + diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 2aa276a5f53..141b8a985cf 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -164,9 +164,9 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags) } } else if (depth == 32) { for (i = x * y; i > 0; i--) { - rect[0] = bmp[0]; + rect[0] = bmp[2]; rect[1] = bmp[1]; - rect[2] = bmp[2]; + rect[2] = bmp[0]; rect[3] = bmp[3]; rect += 4; bmp += 4; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index d298e8b5ea8..043fba9d675 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -53,6 +53,14 @@ ColorBlock::ColorBlock() { } +/// Init the color block from an array of colors. +ColorBlock::ColorBlock(const uint * linearImage) +{ + for(uint i = 0; i < 16; i++) { + color(i) = Color32(linearImage[i]); + } +} + /// Init the color block with the contents of the given block. ColorBlock::ColorBlock(const ColorBlock & block) { @@ -125,9 +133,36 @@ void ColorBlock::splatY() /// Returns true if the block has a single color. bool ColorBlock::isSingleColor() const { + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = m_color[0].u & mask.u; + for(int i = 1; i < 16; i++) { - if (m_color[0] != m_color[i]) + if (u != (m_color[i].u & mask.u)) + { + return false; + } + } + + return true; +} + +/// Returns true if the block has a single color, ignoring transparent pixels. +bool ColorBlock::isSingleColorNoAlpha() const +{ + Color32 c; + int i; + for(i = 0; i < 16; i++) + { + if (m_color[i].a != 0) c = m_color[i]; + } + + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = c.u & mask.u; + + for(; i < 16; i++) + { + if (u != (m_color[i].u & mask.u)) { return false; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 141411f37af..537c17346a1 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -41,6 +41,7 @@ struct ColorBlock { ColorBlock(); + ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); ColorBlock(const Image * img, uint x, uint y); @@ -51,6 +52,7 @@ struct ColorBlock void splatY(); bool isSingleColor() const; + bool isSingleColorNoAlpha() const; uint countUniqueColors() const; Color32 averageColor() const; bool hasAlpha() const; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 01838281dee..0981ae88db6 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -80,6 +80,10 @@ static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); +static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y'); + +static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0'); + // 32 bit RGB formats. static const uint D3DFMT_R8G8B8 = 20; static const uint D3DFMT_A8R8G8B8 = 21; @@ -279,6 +283,144 @@ static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, }; + + const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) + { +#define CASE(format) case DXGI_FORMAT_##format: return #format + switch(dxgiFormat) + { + CASE(UNKNOWN); + + CASE(R32G32B32A32_TYPELESS); + CASE(R32G32B32A32_FLOAT); + CASE(R32G32B32A32_UINT); + CASE(R32G32B32A32_SINT); + + CASE(R32G32B32_TYPELESS); + CASE(R32G32B32_FLOAT); + CASE(R32G32B32_UINT); + CASE(R32G32B32_SINT); + + CASE(R16G16B16A16_TYPELESS); + CASE(R16G16B16A16_FLOAT); + CASE(R16G16B16A16_UNORM); + CASE(R16G16B16A16_UINT); + CASE(R16G16B16A16_SNORM); + CASE(R16G16B16A16_SINT); + + CASE(R32G32_TYPELESS); + CASE(R32G32_FLOAT); + CASE(R32G32_UINT); + CASE(R32G32_SINT); + + CASE(R32G8X24_TYPELESS); + CASE(D32_FLOAT_S8X24_UINT); + CASE(R32_FLOAT_X8X24_TYPELESS); + CASE(X32_TYPELESS_G8X24_UINT); + + CASE(R10G10B10A2_TYPELESS); + CASE(R10G10B10A2_UNORM); + CASE(R10G10B10A2_UINT); + + CASE(R11G11B10_FLOAT); + + CASE(R8G8B8A8_TYPELESS); + CASE(R8G8B8A8_UNORM); + CASE(R8G8B8A8_UNORM_SRGB); + CASE(R8G8B8A8_UINT); + CASE(R8G8B8A8_SNORM); + CASE(R8G8B8A8_SINT); + + CASE(R16G16_TYPELESS); + CASE(R16G16_FLOAT); + CASE(R16G16_UNORM); + CASE(R16G16_UINT); + CASE(R16G16_SNORM); + CASE(R16G16_SINT); + + CASE(R32_TYPELESS); + CASE(D32_FLOAT); + CASE(R32_FLOAT); + CASE(R32_UINT); + CASE(R32_SINT); + + CASE(R24G8_TYPELESS); + CASE(D24_UNORM_S8_UINT); + CASE(R24_UNORM_X8_TYPELESS); + CASE(X24_TYPELESS_G8_UINT); + + CASE(R8G8_TYPELESS); + CASE(R8G8_UNORM); + CASE(R8G8_UINT); + CASE(R8G8_SNORM); + CASE(R8G8_SINT); + + CASE(R16_TYPELESS); + CASE(R16_FLOAT); + CASE(D16_UNORM); + CASE(R16_UNORM); + CASE(R16_UINT); + CASE(R16_SNORM); + CASE(R16_SINT); + + CASE(R8_TYPELESS); + CASE(R8_UNORM); + CASE(R8_UINT); + CASE(R8_SNORM); + CASE(R8_SINT); + CASE(A8_UNORM); + + CASE(R1_UNORM); + + CASE(R9G9B9E5_SHAREDEXP); + + CASE(R8G8_B8G8_UNORM); + CASE(G8R8_G8B8_UNORM); + + CASE(BC1_TYPELESS); + CASE(BC1_UNORM); + CASE(BC1_UNORM_SRGB); + + CASE(BC2_TYPELESS); + CASE(BC2_UNORM); + CASE(BC2_UNORM_SRGB); + + CASE(BC3_TYPELESS); + CASE(BC3_UNORM); + CASE(BC3_UNORM_SRGB); + + CASE(BC4_TYPELESS); + CASE(BC4_UNORM); + CASE(BC4_SNORM); + + CASE(BC5_TYPELESS); + CASE(BC5_UNORM); + CASE(BC5_SNORM); + + CASE(B5G6R5_UNORM); + CASE(B5G5R5A1_UNORM); + CASE(B8G8R8A8_UNORM); + CASE(B8G8R8X8_UNORM); + + default: + return "UNKNOWN"; + } +#undef CASE + } + + const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) + { + switch(resourceDimension) + { + default: + case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; + case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; + } + } + /*** implementation ***/ void mem_read(Stream & mem, DDSPixelFormat & pf) @@ -451,7 +593,16 @@ void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3) // set fourcc pixel format. this->pf.flags = DDPF_FOURCC; this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3); - this->pf.bitcount = 0; + + if (this->pf.fourcc == FOURCC_ATI2) + { + this->pf.bitcount = FOURCC_A2XY; + } + else + { + this->pf.bitcount = 0; + } + this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; @@ -508,7 +659,8 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask void DDSHeader::setDX10Format(uint format) { - this->pf.flags = 0; + //this->pf.flags = 0; + this->pf.fourcc = FOURCC_DX10; this->header10.dxgiFormat = format; } @@ -520,12 +672,18 @@ void DDSHeader::setNormalFlag(bool b) bool DDSHeader::hasDX10Header() const { - return this->pf.flags == 0; + return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD + //return this->pf.flags == 0; // @@ This is according to MS } DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() { mem_read(stream, header); + + // some ATI2 compressed normal maps do not have their + // normal flag set, so force it here (the original nvtt don't do + // this, but the decompressor has a -forcenormal flag) + if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true); } DirectDrawSurface::~DirectDrawSurface() @@ -539,7 +697,7 @@ bool DirectDrawSurface::isValid() const return false; } - const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); + const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); if( (header.flags & required) != required ) { return false; } @@ -560,40 +718,46 @@ bool DirectDrawSurface::isValid() const bool DirectDrawSurface::isSupported() const { - if (header.pf.flags & DDPF_FOURCC) + if (header.hasDX10Header()) { - if (header.pf.fourcc != FOURCC_DXT1 && - header.pf.fourcc != FOURCC_DXT2 && - header.pf.fourcc != FOURCC_DXT3 && - header.pf.fourcc != FOURCC_DXT4 && - header.pf.fourcc != FOURCC_DXT5 && - header.pf.fourcc != FOURCC_RXGB && - header.pf.fourcc != FOURCC_ATI1 && - header.pf.fourcc != FOURCC_ATI2) - { - // Unknown fourcc code. - return false; - } - } - else if (header.pf.flags & DDPF_RGB) - { - // All RGB formats are supported now. } else { - return false; - } + if (header.pf.flags & DDPF_FOURCC) + { + if (header.pf.fourcc != FOURCC_DXT1 && + header.pf.fourcc != FOURCC_DXT2 && + header.pf.fourcc != FOURCC_DXT3 && + header.pf.fourcc != FOURCC_DXT4 && + header.pf.fourcc != FOURCC_DXT5 && + header.pf.fourcc != FOURCC_RXGB && + header.pf.fourcc != FOURCC_ATI1 && + header.pf.fourcc != FOURCC_ATI2) + { + // Unknown fourcc code. + return false; + } + } + else if (header.pf.flags & DDPF_RGB) + { + // All RGB formats are supported now. + } + else + { + return false; + } + + if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) + { + // Cubemaps must contain all faces. + return false; + } - if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) - { - // Cubemaps must contain all faces. - return false; - } - - if (isTexture3D()) - { - // @@ 3D textures not supported yet. - return false; + if (isTexture3D()) + { + // @@ 3D textures not supported yet. + return false; + } } return true; @@ -641,14 +805,37 @@ bool DirectDrawSurface::hasAlpha() const } } +bool DirectDrawSurface::isTexture1D() const +{ + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + return false; +} + bool DirectDrawSurface::isTexture2D() const { - return !isTexture3D() && !isTextureCube(); + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; + } + else + { + return !isTexture3D() && !isTextureCube(); + } } bool DirectDrawSurface::isTexture3D() const { + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; + } + else + { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; + } } bool DirectDrawSurface::isTextureCube() const @@ -656,6 +843,11 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } +void DirectDrawSurface::setNormalFlag(bool b) +{ + header.setNormalFlag(b); +} + void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { stream.seek(offset(face, mipmap)); @@ -709,7 +901,13 @@ void DirectDrawSurface::readLinearImage(Image * img) return; } - if (header.pf.amask != 0) + // set image format: RGB or ARGB + // alpha channel exists if and only if the alpha mask is non-zero + if (header.pf.amask == 0) + { + img->setFormat(Image::Format_RGB); + } + else { img->setFormat(Image::Format_ARGB); } @@ -735,6 +933,20 @@ void DirectDrawSurface::readLinearImage(Image * img) void DirectDrawSurface::readBlockImage(Image * img) { + + // set image format: RGB or ARGB + if (header.pf.fourcc == FOURCC_RXGB || + header.pf.fourcc == FOURCC_ATI1 || + header.pf.fourcc == FOURCC_ATI2 || + header.pf.flags & DDPF_NORMAL) + { + img->setFormat(Image::Format_RGB); + } + else + { + img->setFormat(Image::Format_ARGB); + } + const uint w = img->width(); const uint h = img->height(); @@ -971,8 +1183,23 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); - printf("\tBit count: %d\n", header.pf.bitcount); + printf("\tFourCC: '%c%c%c%c'\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF)); + if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) + { + printf("\tSwizzle: '%c%c%c%c'\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF); + } + else + { + printf("\tBit count: %d\n", header.pf.bitcount); + } printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); @@ -1003,11 +1230,11 @@ void DirectDrawSurface::printInfo() const printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); - if (header.pf.flags == 0) + if (header.hasDX10Header()) { printf("DX10 Header:\n"); - printf("\tDXGI Format: %u\n", header.header10.dxgiFormat); - printf("\tResource dimension: %u\n", header.header10.resourceDimension); + printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); + printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); printf("\tMisc flag: %u\n", header.header10.miscFlag); printf("\tArray size: %u\n", header.header10.arraySize); } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index d8abfc69167..28fcc95fe83 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -142,9 +142,13 @@ public: uint width() const; uint height() const; uint depth() const; + bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; + + void setNormalFlag(bool b); + bool hasAlpha() const; /* false for DXT1, true for all other DXTs */ void mipmap(Image * img, uint f, uint m); diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index b41b940dca7..cf2f6c16d08 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -94,6 +94,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) } /* convert DDS into ImBuf */ + // TODO use the image RGB or RGBA tag to determine the bits per pixel if (dds.hasAlpha()) bits_per_pixel = 32; else bits_per_pixel = 24; ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0); diff --git a/source/blender/include/BDR_drawmesh.h b/source/blender/include/BDR_drawmesh.h index 93e08ab452d..34351549345 100644 --- a/source/blender/include/BDR_drawmesh.h +++ b/source/blender/include/BDR_drawmesh.h @@ -30,52 +30,11 @@ #ifndef BDR_DRAWMESH_H #define BDR_DRAWMESH_H -struct Image; -struct MTFace; struct Object; struct DerivedMesh; -struct Mesh; -struct EdgeHash; - -/** - * Enables or disable mipmapping for realtime images (textures). - * Note that this will will destroy all texture bindings in OpenGL. - * @see free_realtime_image() - * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0). - */ -void set_mipmap(int mipmap); - -/** - * Enables or disable linear mipmap setting for realtime images (textures). - * Note that this will will destroy all texture bindings in OpenGL. - * @see free_realtime_image() - * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0). - */ -void set_linear_mipmap(int linear); - -/** - * Returns the current setting for linear mipmapping. - */ -int get_linear_mipmap(void); - -/** - * Resets the realtime image cache variables. - */ -void clear_realtime_image_cache(void); - - -void update_realtime_image(struct Image *ima, int x, int y, int w, int h); -void free_realtime_image(struct Image *ima); -void free_all_realtime_images(void); -void make_repbind(struct Image *ima); -int set_tpage(struct MTFace *tface); - -void texpaint_enable_mipmap(void); -void texpaint_disable_mipmap(void); void draw_mesh_textured(struct Object *ob, struct DerivedMesh *dm, int facesel); -struct EdgeHash *get_tface_mesh_marked_edge_info(struct Mesh *me); -void init_realtime_GL(void); +void draw_mesh_text(struct Object *ob, int glsl); #endif /* BDR_DRAWMESH_H */ diff --git a/source/blender/include/BDR_drawobject.h b/source/blender/include/BDR_drawobject.h index de28db64c3b..635b73af80c 100644 --- a/source/blender/include/BDR_drawobject.h +++ b/source/blender/include/BDR_drawobject.h @@ -47,8 +47,7 @@ struct EditVert; struct EditFace; struct EditEdge; -int set_gl_material(int nr); -int init_gl_materials(struct Object *ob, int check_alpha); +int draw_glsl_material(struct Object *ob, int dt); void mesh_foreachScreenVert(void (*func)(void *userData, struct EditVert *eve, int x, int y, int index), void *userData, int clipVerts); void mesh_foreachScreenEdge(void (*func)(void *userData, struct EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts); diff --git a/source/blender/include/BDR_gpencil.h b/source/blender/include/BDR_gpencil.h index 7340a2e44e0..9b9294b0343 100644 --- a/source/blender/include/BDR_gpencil.h +++ b/source/blender/include/BDR_gpencil.h @@ -76,6 +76,9 @@ void gpencil_delete_laststroke(struct bGPdata *gpd); void gpencil_delete_operation(short mode); void gpencil_delete_menu(void); +void gpencil_convert_operation(short mode); +void gpencil_convert_menu(void); + //short gpencil_paint(short mousebutton); short gpencil_do_paint(struct ScrArea *sa, short mousebutton); diff --git a/source/blender/include/BDR_imagepaint.h b/source/blender/include/BDR_imagepaint.h index 26f2375e60a..bd1ac301416 100644 --- a/source/blender/include/BDR_imagepaint.h +++ b/source/blender/include/BDR_imagepaint.h @@ -34,8 +34,8 @@ void imagepaint_redraw_tool(void); void imagepaint_pick(short mousebutton); void imagepaint_paint(short mousebutton, short texturepaint); -void imagepaint_undo(); -void free_imagepaint(); +void undo_imagepaint_step(int step); +void undo_imagepaint_clear(void); #endif /* BDR_IMAGEPAINT_H */ diff --git a/source/blender/include/BIF_drawseq.h b/source/blender/include/BIF_drawseq.h index 462075cdf3d..85a6c7a9e2d 100644 --- a/source/blender/include/BIF_drawseq.h +++ b/source/blender/include/BIF_drawseq.h @@ -33,6 +33,8 @@ struct ScrArea; struct Sequence; +#define SEQ_ZOOM_FAC(szoom) (szoom > 0)? (szoom) : (szoom == 0)? (1.0) : (-1.0/szoom) + void drawprefetchseqspace(struct ScrArea *sa, void *spacedata); void drawseqspace(struct ScrArea *sa, void *spacedata); void set_special_seq_update(int val); diff --git a/source/blender/include/BIF_drawtext.h b/source/blender/include/BIF_drawtext.h index a75e0f1bd86..51000f8c81a 100644 --- a/source/blender/include/BIF_drawtext.h +++ b/source/blender/include/BIF_drawtext.h @@ -33,19 +33,21 @@ struct ScrArea; struct SpaceText; struct Text; +struct TextLine; void unlink_text(struct Text *text); void free_textspace(struct SpaceText *st); +int txt_file_modified(struct Text *text); void txt_write_file(struct Text *text); void add_text_fs(char *file); void free_txt_data(void); void pop_space_text(struct SpaceText *st); -void get_format_string(struct SpaceText *st); -void do_brackets(void); +void txt_format_text(struct SpaceText *st); +void txt_format_line(struct SpaceText *st, struct TextLine *line, int do_next); #endif diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 77c2f19bb9b..1425cf6a67c 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -78,7 +78,7 @@ enum { #define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT)) #define NLA_ACTION_SCALED (G.saction->mode==SACTCONT_ACTION && G.saction->pin==0 && OBACT && OBACT->action) -#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) +#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo && G.sipo->pin==0 && G.sipo->actname) /* constants for setting ipo-interpolation type */ enum { diff --git a/source/blender/include/BIF_editarmature.h b/source/blender/include/BIF_editarmature.h index 07fc8f08b4a..fdd00a67465 100644 --- a/source/blender/include/BIF_editarmature.h +++ b/source/blender/include/BIF_editarmature.h @@ -91,6 +91,7 @@ void free_editArmature(void); int join_armature(void); void separate_armature(void); +void apply_armature_pose2bones(void); void load_editArmature(void); void make_bone_parent(void); @@ -99,13 +100,14 @@ struct Bone *get_indexed_bone (struct Object *ob, int index); void make_editArmature(void); void make_trans_bones (char mode); +void remake_editArmature(void); +void editbones_to_armature(struct ListBase *list, struct Object *ob); int do_pose_selectbuffer(struct Base *base, unsigned int *buffer, short hits); void generateSkeleton(void); void mouse_armature(void); -void remake_editArmature(void); void selectconnected_armature(void); void selectconnected_posearmature(void); void armature_select_hierarchy(short direction, short add_to_sel); diff --git a/source/blender/include/BIF_editview.h b/source/blender/include/BIF_editview.h index d2c6c56d01a..204733a19d6 100644 --- a/source/blender/include/BIF_editview.h +++ b/source/blender/include/BIF_editview.h @@ -40,6 +40,7 @@ void arrows_move_cursor(unsigned short event); void lasso_select_boundbox(struct rcti *rect, short mcords[][2], short moves); int lasso_inside(short mcords[][2], short moves, short sx, short sy); int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1); +int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2); void borderselect(void); void circle_select(void); void deselectall(void); diff --git a/source/blender/include/BIF_gl.h b/source/blender/include/BIF_gl.h index 2468abdff60..c1b3b056d62 100644 --- a/source/blender/include/BIF_gl.h +++ b/source/blender/include/BIF_gl.h @@ -49,20 +49,7 @@ #endif #endif -#ifdef __APPLE__ - #include - #include -#else -/* #if defined (__sun) || defined (__sun__) - #include - #include - #else -*/ - #include - #include -/* #endif */ -#endif - +#include "GL/glew.h" /* * these should be phased out. cpack should be replaced in diff --git a/source/blender/include/BIF_glutil.h b/source/blender/include/BIF_glutil.h index f530e7ba8d0..ed9096549ca 100644 --- a/source/blender/include/BIF_glutil.h +++ b/source/blender/include/BIF_glutil.h @@ -204,6 +204,7 @@ void bglVertex2fv(float *vec); /* intel gfx cards frontbuffer problem */ void bglFlush(void); int is_a_really_crappy_intel_card(void); +int is_a_really_crappy_nvidia_card(void); void set_inverted_drawing(int enable); diff --git a/source/blender/include/BIF_keyframing.h b/source/blender/include/BIF_keyframing.h new file mode 100644 index 00000000000..eeaef957b90 --- /dev/null +++ b/source/blender/include/BIF_keyframing.h @@ -0,0 +1,99 @@ +/** + * $Id: BIF_keyframing.h 14444 2008-04-16 22:40:48Z aligorith $ + * + * ***** 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 + * This is a new part of Blender (with some old code) + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_KEYFRAMING_H +#define BIF_KEYFRAMING_H + +struct ListBase; +struct ID; + +struct IpoCurve; +struct BezTriple; + +/* ************ Keyframing Management **************** */ + +/* Lesser Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it already + * exists, and there is a beztriple that can be directly copied into the array. + */ +int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + */ +void insert_vert_icu(struct IpoCurve *icu, float x, float y, short flag); + + +/* flags for use in insert_key(), and insert_vert_icu() */ +enum { + INSERTKEY_NEEDED = (1<<0), /* only insert keyframes where they're needed */ + INSERTKEY_MATRIX = (1<<1), /* insert 'visual' keyframes where possible/needed */ + INSERTKEY_FAST = (1<<2), /* don't recalculate handles,etc. after adding key */ + INSERTKEY_FASTR = (1<<3), /* don't realloc mem (or increase count, as array has already been set out) */ + INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */ +} eInsertKeyFlags; + +/* -------- */ + +/* Main Keyframing API calls: + * Use this to create any necessary animation data,, and then insert a keyframe + * using the current value being keyframed, in the relevant place. Returns success. + */ + // TODO: adapt this for new data-api -> this blocktype, etc. stuff is evil! +short insertkey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); + +/* Main Keyframing API call: + * Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case. + */ +short deletekey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); + + +/* Main Keyframe Management calls: + * These handle keyframes management from various spaces. They will handle the menus + * required for each space. + */ +void common_insertkey(void); +void common_deletekey(void); + +/* ************ Keyframe Checking ******************** */ + +/* Checks whether a keyframe exists for the given ID-block one the given frame */ +short id_cfra_has_keyframe(struct ID *id, short filter); + +/* filter flags fr id_cfra_has_keyframe */ +enum { + /* general */ + ANIMFILTER_ALL = 0, /* include all available animation data */ + ANIMFILTER_LOCAL = (1<<0), /* only include locally available anim data */ + + /* object specific */ + ANIMFILTER_MAT = (1<<1), /* include material keyframes too */ + ANIMFILTER_SKEY = (1<<2), /* shape keys (for geometry) */ +} eAnimFilterFlags; + +#endif /* BIF_KEYFRAMING_H */ diff --git a/source/blender/include/BIF_keyval.h b/source/blender/include/BIF_keyval.h index 70d248ded91..9693684e425 100644 --- a/source/blender/include/BIF_keyval.h +++ b/source/blender/include/BIF_keyval.h @@ -31,6 +31,9 @@ #define BIF_KEYVAL_H char *key_event_to_string(unsigned short event); +int decode_key_string(char *str, unsigned short *key, unsigned short *qual); #endif + + diff --git a/source/blender/include/BIF_meshlaplacian.h b/source/blender/include/BIF_meshlaplacian.h index 9fb8aad0eb6..71db8d0bba2 100644 --- a/source/blender/include/BIF_meshlaplacian.h +++ b/source/blender/include/BIF_meshlaplacian.h @@ -47,7 +47,7 @@ struct EditMesh; struct LaplacianSystem; typedef struct LaplacianSystem LaplacianSystem; -LaplacianSystem *laplacian_construct_begin(int totvert, int totface); +LaplacianSystem *laplacian_construct_begin(int totvert, int totface, int lsq); void laplacian_add_vertex(LaplacianSystem *sys, float *co, int pinned); void laplacian_add_triangle(LaplacianSystem *sys, int v1, int v2, int v3); diff --git a/source/blender/include/BIF_meshtools.h b/source/blender/include/BIF_meshtools.h index d809d1f21f9..a894d66cb10 100644 --- a/source/blender/include/BIF_meshtools.h +++ b/source/blender/include/BIF_meshtools.h @@ -30,6 +30,8 @@ #ifndef BIF_MESHTOOLS_H #define BIF_MESHTOOLS_H +#include "BLO_sys_types.h" + struct Object; struct EditVert; diff --git a/source/blender/include/BIF_resources.h b/source/blender/include/BIF_resources.h index 0d27804dd1a..b6a9882309d 100644 --- a/source/blender/include/BIF_resources.h +++ b/source/blender/include/BIF_resources.h @@ -57,8 +57,8 @@ typedef enum { ICON_TRIA_UP, ICON_FONTPREVIEW, ICON_BLANK4, - ICON_BLANK5, - ICON_BLANK6, + ICON_WORDWRAP, + ICON_WORDWRAP_OFF, ICON_ORTHO, ICON_PERSP, @@ -108,7 +108,7 @@ typedef enum { ICON_FF, ICON_REW, ICON_PYTHON, - ICON_BLANK11, + ICON_PYTHON_ON, ICON_BLANK12, ICON_BLANK13, ICON_BLANK14, @@ -266,8 +266,8 @@ typedef enum { ICON_WINDOW_WINDOW, ICON_PANEL_CLOSE, ICON_PHYSICS, - ICON_BLANK36, - ICON_BLANK37, + ICON_LAYER_USED, + ICON_LAYER_ACTIVE, ICON_BLANK38, ICON_BLENDER, diff --git a/source/blender/include/BIF_space.h b/source/blender/include/BIF_space.h index 4b2b8e14bb6..c7d0f4a1ada 100644 --- a/source/blender/include/BIF_space.h +++ b/source/blender/include/BIF_space.h @@ -65,6 +65,7 @@ struct SpaceOops; #define IMAGE_HANDLER_PREVIEW 33 #define IMAGE_HANDLER_GAME_PROPERTIES 34 #define IMAGE_HANDLER_VIEW_PROPERTIES 35 +#define IMAGE_HANDLER_GREASEPENCIL 36 /*#define IMAGE_HANDLER_TRANSFORM_PROPERTIES 36*/ /* action handler codes */ @@ -83,6 +84,9 @@ struct SpaceOops; /* nodes handler codes */ #define NODES_HANDLER_GREASEPENCIL 80 +/* text handler codes */ +#define TEXT_HANDLER_FIND 90 + /* theme codes */ #define B_ADD_THEME 3301 #define B_DEL_THEME 3302 diff --git a/source/blender/include/BSE_drawipo.h b/source/blender/include/BSE_drawipo.h index 932f103a579..b8388b2172a 100644 --- a/source/blender/include/BSE_drawipo.h +++ b/source/blender/include/BSE_drawipo.h @@ -42,6 +42,7 @@ struct ScrArea; struct EditIpo; struct View2D; struct rctf; +struct SpaceLink; void calc_ipogrid(void); void draw_ipogrid(void); @@ -50,6 +51,8 @@ void areamouseco_to_ipoco (struct View2D *v2d, short *mval, float *x, float *y); void ipoco_to_areaco (struct View2D *v2d, float *vec, short *mval); void ipoco_to_areaco_noclip (struct View2D *v2d, float *vec, short *mval); +struct View2D *spacelink_get_view2d(struct SpaceLink *sl); + void view2d_do_locks (struct ScrArea *cursa, int flag); void view2d_zoom (struct View2D *v2d, float factor, int winx, int winy); void view2d_getscale (struct View2D *v2d, float *x, float *y); diff --git a/source/blender/include/BSE_drawview.h b/source/blender/include/BSE_drawview.h index e6f22a4fb67..1b2834b2e3b 100644 --- a/source/blender/include/BSE_drawview.h +++ b/source/blender/include/BSE_drawview.h @@ -36,8 +36,6 @@ struct rctf; struct ScrArea; struct ImBuf; -void default_gl_light(void); -void init_gl_stuff(void); void circf(float x, float y, float rad); void circ(float x, float y, float rad); @@ -55,8 +53,8 @@ struct ImBuf *read_backbuf(short xmin, short ymin, short xmax, short ymax); unsigned int sample_backbuf_rect(short mval[2], int size, unsigned int min, unsigned int max, int *dist, short strict, unsigned int (*indextest)(unsigned int index)); void drawview3dspace(struct ScrArea *sa, void *spacedata); -void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]); -void draw_depth(struct ScrArea *sa, void *spacedata); +void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int winy, float winmat[][4], int shadow); +void draw_depth(struct ScrArea *sa, void *spacedata, int (*func)(void *) ); void view3d_update_depths(struct View3D *v3d); int update_time(int cfra); diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index e7445efc63e..807e338f514 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -86,13 +86,10 @@ void do_ipo_selectbuttons(void); /* gets ipo curve, creates if needed */ -struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); -struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *); +struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); +struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *, short); int texchannel_to_adrcode(int channel); -int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); -void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -void add_vert_ipo(void); void add_duplicate_editipo(void); void remove_doubles_ipo(void); @@ -121,10 +118,8 @@ void paste_editipo(void); void set_exprap_ipo(int mode); void set_speed_editipo(float speed); -void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast); -void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode); void insertkey_editipo(void); -void common_insertkey(void); +void add_vert_ipo(void); void free_ipokey(struct ListBase *lb); void add_to_ipokey(struct ListBase *lb, struct BezTriple *bezt, int nr, int len); void make_ipokey(void); @@ -163,8 +158,6 @@ void duplicate_ipo_keys(struct Ipo *ipo); void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val); void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, int (*select_function)(struct BezTriple *)); -int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode); -void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey); void select_ipo_key(struct Ipo *ipo, float selx, int sel); void select_icu_key(struct IpoCurve *icu, float selx, int selectmode); void setexprap_ipoloop(struct Ipo *ipo, int code); diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 6f8b94d7cd1..a7f7bc2e4b8 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -241,6 +241,7 @@ #define B_SEL_END 168 #define B_MAN_MODE 169 #define B_NDOF 170 +#define B_VIEW_BUTSEDIT 171 /* IPO: 200 */ #define B_IPOHOME 201 @@ -377,6 +378,13 @@ #define B_TEXTLINENUM 507 #define B_TAB_NUMBERS 508 #define B_SYNTAX 509 +#define B_WORDWRAP 510 +#define B_TEXTPLUGINS 511 +#define B_PASTEFIND 512 +#define B_PASTEREPLACE 513 +#define B_TEXTREPLACE 514 +#define B_TEXTFIND 515 +#define B_TEXTMARKALL 516 /* SCRIPT: 525 */ #define B_SCRIPTBROWSE 526 diff --git a/source/blender/include/transform.h b/source/blender/include/transform.h index 720b856a149..51fa39ff9d6 100644 --- a/source/blender/include/transform.h +++ b/source/blender/include/transform.h @@ -466,7 +466,6 @@ int validSnappingNormal(TransInfo *t); /*********************** Generics ********************************/ void initTrans(TransInfo *t); -void initTransModeFlags(TransInfo *t, int mode); void postTrans (TransInfo *t); void drawLine(float *center, float *dir, char axis, short options); @@ -498,6 +497,7 @@ TransInfo * BIF_GetTransInfo(void); /*********************** NumInput ********************************/ +void initNumInput(NumInput *n); void outputNumInput(NumInput *n, char *str); short hasNumInput(NumInput *n); void applyNumInput(NumInput *n, float *vec); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 2e8d95335cc..4a10ecf2368 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -277,7 +277,9 @@ typedef enum POSE_FLAG { /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ POSE_DO_UNLOCK = (1<<2), /* pose has constraints which depend on time (used when depsgraph updates for a new frame) */ - POSE_CONSTRAINTS_TIMEDEPEND = (1<<3) + POSE_CONSTRAINTS_TIMEDEPEND = (1<<3), + /* recalculate bone paths */ + POSE_RECALCPATHS = (1<<4), } POSE_FLAG; /* PoseChannel (transform) flags */ diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 7444ce95f56..750bdf2cfff 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -81,7 +81,9 @@ typedef struct bEditObjectActuator { struct Mesh *me; char name[32]; float linVelocity[3]; /* initial lin. velocity on creation */ - short localflag; /* flag for the lin. vel: apply locally */ + float angVelocity[3]; /* initial ang. velocity on creation */ + float pad; + short localflag; /* flag for the lin & ang. vel: apply locally */ short dyn_operation; } bEditObjectActuator; @@ -191,7 +193,8 @@ typedef struct bGameActuator { } bGameActuator; typedef struct bVisibilityActuator { - /** bit 0: Is this object visible? */ + /** bit 0: Is this object visible? + ** bit 1: Apply recursively */ int flag; } bVisibilityActuator; @@ -298,6 +301,7 @@ typedef struct FreeCamera { #define ACT_NEW 4 #define ACT_LINKED 8 #define ACT_VISIBLE 16 +#define ACT_PIN 32 /* link codes */ #define LINK_SENSOR 0 @@ -384,6 +388,9 @@ typedef struct FreeCamera { #define ACT_EDOB_TRACK_TO 3 #define ACT_EDOB_DYNAMICS 4 +/* editObjectActuator->localflag */ +#define ACT_EDOB_LOCAL_LINV 2 +#define ACT_EDOB_LOCAL_ANGV 4 /* editObjectActuator->flag */ @@ -438,10 +445,13 @@ typedef struct FreeCamera { #define ACT_GAME_START 1 #define ACT_GAME_RESTART 2 #define ACT_GAME_QUIT 3 +#define ACT_GAME_SAVECFG 4 +#define ACT_GAME_LOADCFG 5 /* visibilityact->flag */ /* Set means the object will become invisible */ #define ACT_VISIBILITY_INVISIBLE (1 << 0) +#define ACT_VISIBILITY_RECURSIVE (1 << 1) /* twodfilter->type */ #define ACT_2DFILTER_ENABLED -2 diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 1c272105067..c7196763358 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -33,7 +33,7 @@ #include "DNA_ID.h" #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif struct MTex; @@ -58,7 +58,7 @@ typedef struct Brush { float alpha; /* opacity */ short texact, pad; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ struct BrushClone clone; } Brush; diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index a4fb8dc1150..3722c365f39 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -187,37 +187,6 @@ typedef struct Curve { struct CharInfo curinfo; } Curve; -typedef struct IpoDriver { - struct Object *ob; - short blocktype, adrcode, type, flag; - char name[128]; /* bone or constraint(?), or python expression here */ -} IpoDriver; - -/* temp? we store more bone names in 1 driver... */ -#define DRIVER_NAME_OFFS 32 - -typedef struct IpoCurve { - struct IpoCurve *next, *prev; - - struct BPoint *bp; /* are these even used anywhere? */ - struct BezTriple *bezt; /* array of BezTriples (sizeof(BezTriple)*totvert. i.e. keyframes */ - - rctf maxrct, totrct; /* bounding boxes */ - - short blocktype, adrcode, vartype; /* blocktype= ipo-blocktype; adrcode= type of ipo-curve; vartype= 'format' of data */ - short totvert; /* total number of BezTriples (i.e. keyframes) on curve */ - short ipo, extrap; /* interpolation and extrapolation modes */ - short flag, rt; /* flag= settings; rt= ??? */ - float ymin, ymax; /* minimum/maximum y-extents for curve */ - unsigned int bitmask; /* ??? */ - - float slide_min, slide_max; /* minimum/maximum values for sliders (in action editor) */ - float curval; /* value of ipo-curve for current frame */ - - IpoDriver *driver; /* pointer to ipo-driver for this curve */ - -} IpoCurve; - /* **************** CURVE ********************* */ /* texflag */ @@ -273,15 +242,5 @@ typedef struct IpoCurve { #define CU_UNDERLINE 4 #define CU_WRAP 8 /* wordwrap occured here */ -/* *************** driver ****************** */ - -/* driver->type */ -#define IPO_DRIVER_TYPE_NORMAL 0 -#define IPO_DRIVER_TYPE_PYTHON 1 - -/* driver->flag */ -/* invalid flag: currently only used for buggy pydriver expressions: */ -#define IPO_DRIVER_FLAG_INVALID 1 - #endif diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 13d412c2c42..cc0c9912057 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -61,7 +61,7 @@ typedef struct bGPDstroke { #define GP_STROKE_2DSPACE (1<<1) /* stroke is in 2d-space (but with special 'image' scaling) */ #define GP_STROKE_2DIMAGE (1<<2) - /* stroke is an "eraser" stroke */ + /* only for use with stroke-buffer (while drawing eraser) */ #define GP_STROKE_ERASER (1<<15) diff --git a/source/blender/makesdna/DNA_group_types.h b/source/blender/makesdna/DNA_group_types.h index 1bb18ca2ca2..0987050261d 100644 --- a/source/blender/makesdna/DNA_group_types.h +++ b/source/blender/makesdna/DNA_group_types.h @@ -54,7 +54,7 @@ typedef struct Group { * the objects that show in the group can change depending * on the last used scene */ unsigned int layer; - int pad; + float dupli_ofs[3]; } Group; diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index 42b651a7555..e1d79f0f875 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -37,6 +37,7 @@ struct PackedFile; struct anim; struct ImBuf; struct RenderResult; +struct GPUTexture; /* ImageUser is in Texture, in Nodes, Background Image, Image Window, .... */ @@ -62,7 +63,8 @@ typedef struct Image { char name[240]; /* file path */ - ListBase ibufs; /* not written in file */ + ListBase ibufs; /* not written in file */ + struct GPUTexture *gputexture; /* not written in file */ /* sources from: */ struct anim *anim; diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index 1e30f3f7640..fe75148fb3b 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -24,7 +24,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Joshua Leung * * ***** END GPL LICENSE BLOCK ***** */ @@ -32,10 +32,54 @@ #define DNA_IPO_TYPES_H #include "DNA_listBase.h" +#include "DNA_curve_types.h" #include "DNA_vec_types.h" #include "DNA_ID.h" +/* -------------------------- Type Defines --------------------------- */ + +/* sometimes used - mainly for GE/Ketsji */ +typedef short IPO_Channel; + + +/* --- IPO Curve Driver --- */ + +/* IPO Curve Driver */ +typedef struct IpoDriver { + struct Object *ob; /* target/driver ob */ + short blocktype, adrcode; /* sub-channel to use */ + + short type, flag; /* driver settings */ + char name[128]; /* bone, or python expression here */ +} IpoDriver; + +/* --- IPO Curve --- */ + +/* IPO Curve */ +typedef struct IpoCurve { + struct IpoCurve *next, *prev; + + struct BPoint *bp; /* array of BPoints (sizeof(BPoint)*totvert) - i.e. baked/imported data */ + struct BezTriple *bezt; /* array of BezTriples (sizeof(BezTriple)*totvert) - i.e. user-editable keyframes */ + + rctf maxrct, totrct; /* bounding boxes */ + + short blocktype, adrcode, vartype; /* blocktype= ipo-blocktype; adrcode= type of ipo-curve; vartype= 'format' of data */ + short totvert; /* total number of BezTriples (i.e. keyframes) on curve */ + short ipo, extrap; /* interpolation and extrapolation modes */ + short flag, rt; /* flag= settings; rt= ??? */ + float ymin, ymax; /* minimum/maximum y-extents for curve */ + unsigned int bitmask; /* ??? */ + + float slide_min, slide_max; /* minimum/maximum values for sliders (in action editor) */ + float curval; /* value of ipo-curve for current frame */ + + IpoDriver *driver; /* pointer to ipo-driver for this curve */ +} IpoCurve; + +/* --- ID-Datablock --- */ + /* IPO Data-Block */ typedef struct Ipo { ID id; @@ -47,13 +91,9 @@ typedef struct Ipo { short muteipo, pad; /* muteipo: either 0 or 1 (whether ipo block is muted) */ } Ipo; -/* NOTE: IpoCurve struct is defined in DNA_curve_types.h, not in here... */ - -/* sometimes used */ -typedef short IPO_Channel; +/* ----------- adrcodes (for matching ipo-curves to data) ------------- */ /* defines: are these duped or new? */ - #define IPOBUTY 17 #define TOB_IPO 1 @@ -64,7 +104,7 @@ typedef short IPO_Channel; #define IPO_DISPBITS 2 #define IPO_DISPTIME 3 -/* ******************** */ +/* ********** Object (ID_OB) ********** */ #define OB_TOTIPO 30 #define OB_TOTNAM 30 @@ -110,7 +150,7 @@ typedef short IPO_Channel; #define OB_ROT_DIFF 100 -/* ******************** */ +/* ********** Material (ID_MA) ********** */ #define MA_TOTIPO 40 #define MA_TOTNAM 26 @@ -142,16 +182,24 @@ typedef short IPO_Channel; #define MA_FRESTRAI 25 #define MA_ADD 26 -#define MA_MAP1 0x20 -#define MA_MAP2 0x40 -#define MA_MAP3 0x80 -#define MA_MAP4 0x100 -#define MA_MAP5 0x200 -#define MA_MAP6 0x400 -#define MA_MAP7 0x800 -#define MA_MAP8 0x1000 -#define MA_MAP9 0x2000 -#define MA_MAP10 0x4000 +#define MA_MAP1 (1<<5) +#define MA_MAP2 (1<<6) +#define MA_MAP3 (1<<7) +#define MA_MAP4 (1<<8) +#define MA_MAP5 (1<<9) +#define MA_MAP6 (1<<10) +#define MA_MAP7 (1<<11) +#define MA_MAP8 (1<<12) +#define MA_MAP9 (1<<13) +#define MA_MAP10 (1<<14) +#define MA_MAP11 (1<<15) +#define MA_MAP12 (1<<16) +#define MA_MAP13 (1<<17) +#define MA_MAP14 (1<<18) +#define MA_MAP15 (1<<19) +#define MA_MAP16 (1<<20) +#define MA_MAP17 (1<<21) +#define MA_MAP18 (1<<22) #define TEX_TOTNAM 14 @@ -171,7 +219,7 @@ typedef short IPO_Channel; #define MAP_VARF 13 #define MAP_DISP 14 -/* ******************** */ +/* ********** Texture (ID_TE) ********** */ #define TE_TOTIPO 26 #define TE_TOTNAM 26 @@ -208,21 +256,21 @@ typedef short IPO_Channel; #define TE_BRIGHT 25 #define TE_CONTRA 26 -/* ******************** */ +/* ******** Sequence (ID_SEQ) ********** */ #define SEQ_TOTIPO 1 #define SEQ_TOTNAM 1 #define SEQ_FAC1 1 -/* ******************** */ +/* ********* Curve (ID_CU) *********** */ #define CU_TOTIPO 1 #define CU_TOTNAM 1 #define CU_SPEED 1 -/* ******************** */ +/* ********* ShapeKey (ID_KE) *********** */ #define KEY_TOTIPO 64 #define KEY_TOTNAM 64 @@ -230,7 +278,7 @@ typedef short IPO_Channel; #define KEY_SPEED 0 #define KEY_NR 1 -/* ******************** */ +/* ********* World (ID_WO) *********** */ #define WO_TOTIPO 29 #define WO_TOTNAM 16 @@ -255,7 +303,7 @@ typedef short IPO_Channel; #define WO_STARDIST 15 #define WO_STARSIZE 16 -/* ******************** */ +/* ********** Lamp (ID_LA) ********** */ #define LA_TOTIPO 21 #define LA_TOTNAM 10 @@ -271,9 +319,8 @@ typedef short IPO_Channel; #define LA_QUAD2 9 #define LA_HALOINT 10 -/* ******************** */ +/* ********* Camera (ID_CA) ************ */ -/* yafray: totipo & totnam +2 because of added curves */ #define CAM_TOTIPO 7 #define CAM_TOTNAM 7 @@ -288,7 +335,7 @@ typedef short IPO_Channel; #define CAM_SHIFT_X 6 #define CAM_SHIFT_Y 7 -/* ******************** */ +/* ********* Sound (ID_SO) *********** */ #define SND_TOTIPO 4 #define SND_TOTNAM 4 @@ -298,9 +345,9 @@ typedef short IPO_Channel; #define SND_PANNING 3 #define SND_ATTEN 4 -/* ******************** */ +/* ******* PoseChannel (ID_PO) ********* */ -#define AC_TOTIPO 10 /* __NLA */ +#define AC_TOTIPO 10 #define AC_TOTNAM 10 #define AC_LOC_X 1 @@ -316,25 +363,15 @@ typedef short IPO_Channel; #define AC_QUAT_Y 27 #define AC_QUAT_Z 28 -/* ******************** */ -#define CO_TOTIPO 2 /* Constraint Ipos */ +/* ******** Constraint (ID_CO) ********** */ + +#define CO_TOTIPO 2 #define CO_TOTNAM 2 #define CO_ENFORCE 1 #define CO_HEADTAIL 2 -/* -#define CO_TIME 2 -#define CO_OFFSET_X 3 -#define CO_OFFSET_Y 4 -#define CO_OFFSET_Z 5 -#define CO_ORIENT_X 6 -#define CO_ORIENT_Y 7 -#define CO_ORIENT_Z 8 -#define CO_ROLL 9 -*/ -/* ******************** */ -/* fluidsim ipos NT */ +/* ****** FluidSim (ID_FLUIDSIM) ****** */ #define FLUIDSIM_TOTIPO 9 #define FLUIDSIM_TOTNAM 9 @@ -352,8 +389,8 @@ typedef short IPO_Channel; #define FLUIDSIM_ACTIVE 9 -/* ******************** */ -/* particle ipos */ +/* ******* Particle (ID_PA) ******** */ + #define PART_TOTIPO 25 #define PART_TOTNAM 25 @@ -390,8 +427,9 @@ typedef short IPO_Channel; #define PART_PD2_FMAXD 25 -/* these are IpoCurve specific */ -/* **************** IPO ********************* */ +/* -------------------- Defines: Flags and Types ------------------ */ + +/* ----- IPO Curve Defines ------- */ /* icu->vartype */ #define IPO_CHAR 0 @@ -401,6 +439,7 @@ typedef short IPO_Channel; #define IPO_FLOAT 4 #define IPO_DOUBLE 5 #define IPO_FLOAT_DEGR 6 + /* very special case, in keys */ #define IPO_BEZTRIPLE 100 #define IPO_BPOINT 101 @@ -415,7 +454,8 @@ typedef short IPO_Channel; #define IPO_CONST 0 #define IPO_LIN 1 #define IPO_BEZ 2 -#define IPO_MIXED 3 /* not used yet */ + /* not used yet */ +#define IPO_MIXED 3 /* icu->extrap */ #define IPO_HORIZ 0 @@ -433,6 +473,19 @@ typedef short IPO_Channel; #define IPO_PROTECT 64 #define IPO_MUTE 128 +/* ---------- IPO Drivers ----------- */ + +/* offset in driver->name for finding second posechannel for rot-diff */ +#define DRIVER_NAME_OFFS 32 + +/* driver->type */ +#define IPO_DRIVER_TYPE_NORMAL 0 +#define IPO_DRIVER_TYPE_PYTHON 1 + +/* driver->flag */ + /* invalid flag: currently only used for buggy pydriver expressions */ +#define IPO_DRIVER_FLAG_INVALID (1<<0) + #endif diff --git a/source/blender/makesdna/DNA_lamp_types.h b/source/blender/makesdna/DNA_lamp_types.h index c00dae08eb4..2a39580bb5c 100644 --- a/source/blender/makesdna/DNA_lamp_types.h +++ b/source/blender/makesdna/DNA_lamp_types.h @@ -35,7 +35,7 @@ #include "DNA_scriptlink_types.h" #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif struct MTex; @@ -45,7 +45,8 @@ struct CurveMapping; typedef struct Lamp { ID id; - short type, mode; + short type, pad3; + int mode; short colormodel, totex; float r, g, b, k; @@ -55,10 +56,9 @@ typedef struct Lamp { float att1, att2; /* Quad1 and Quad2 attenuation */ - int pad2; struct CurveMapping *curfalloff; short falloff_type; - short pad3; + short pad2; float clipsta, clipend, shadspotsize; float bias, soft; @@ -99,7 +99,7 @@ typedef struct Lamp { float YF_glowint, YF_glowofs; short YF_glowtype, YF_pad2; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ struct Ipo *ipo; /* preview */ @@ -137,6 +137,12 @@ typedef struct Lamp { /* yafray: lamp shadowbuffer flag, softlight */ /* Since it is used with LOCAL lamp, can't use LA_SHAD */ #define LA_YF_SOFT 16384 +#define LA_LAYER_SHADOW 32768 + +/* layer_shadow */ +#define LA_LAYER_SHADOW_BOTH 0 +#define LA_LAYER_SHADOW_CAST 1 +#define LA_LAYER_SHADOW_RECEIVE 2 /* sun effect type*/ #define LA_SUN_EFFECT_SKY 1 diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 9412a09d0f4..c92a33bbcbb 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -36,7 +36,7 @@ #include "DNA_listBase.h" #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif struct MTex; @@ -88,11 +88,11 @@ typedef struct Material { float sbias; /* shadow bias to prevent terminator prob */ float lbias; /* factor to multiply lampbias with (0.0 = no mult) */ float shad_alpha; /* in use for irregular shadowbuffer */ - float padf; /* free padding, take me! */ + int septex; /* for buttons and render*/ char rgbsel, texact, pr_type, use_nodes; - short pr_back, pr_lamp, septex, ml_flag; /* ml_flag is for disable base material */ + short pr_back, pr_lamp, pad4, ml_flag; /* ml_flag is for disable base material */ /* shaders */ short diff_shader, spec_shader; @@ -110,7 +110,7 @@ typedef struct Material { short ramp_show, pad3; float rampfac_col, rampfac_spec; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ struct bNodeTree *nodetree; struct Ipo *ipo; struct Group *group; /* light group */ @@ -133,6 +133,8 @@ typedef struct Material { int YF_dsmp, YF_preset, YF_djit; ScriptLink scriptlink; + + ListBase gpumaterial; /* runtime */ } Material; /* **************** MATERIAL ********************* */ @@ -203,6 +205,7 @@ typedef struct Material { /* shade_flag */ #define MA_CUBIC 1 +#define MA_OBCOLOR 2 /* diff_shader */ #define MA_DIFF_LAMBERT 0 diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 4e427ed733c..fc686a4cc10 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -82,6 +82,7 @@ typedef struct MLoopUV{ typedef struct MLoopCol{ char a, r, g, b; + int pad; /*waste!*/ }MLoopCol; typedef struct MSticky { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 85c49a03569..66bdaf2c98b 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -156,7 +156,9 @@ typedef struct Object { float formfactor; float rdamping, sizefac; - + float margin, pad3; + + char dt, dtx; char totcol; /* copy of mesh or curve or meta */ char actcol; /* currently selected material in the user interface */ @@ -210,7 +212,8 @@ typedef struct Object { short shapenr, shapeflag; /* current shape key for menu or pinned, flag for pinning */ float smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */ - short recalco, pad4; /* recalco for temp storage of ob->recalc, bad design warning */ + short recalco; /* recalco for temp storage of ob->recalc, bad design warning */ + short body_type; /* for now used to temporarily holds the type of collision object */ struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */ @@ -223,6 +226,8 @@ typedef struct Object { /*#ifdef WITH_VERSE*/ void *vnode; /* pointer at object VerseNode */ /*#endif*/ + + ListBase gpulamp; /* runtime, for lamps only */ } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -425,11 +430,21 @@ extern Object workob; #define OB_PROP 16384 #define OB_MAINACTOR 32768 +#define OB_COLLISION 65536 +#define OB_SOFT_BODY 0x20000 + /* ob->gameflag2 */ #define OB_NEVER_DO_ACTIVITY_CULLING 1 #define OB_LIFE (OB_PROP|OB_DYNAMIC|OB_ACTOR|OB_MAINACTOR|OB_CHILD) +/* ob->body_type */ +#define OB_BODY_TYPE_NO_COLLISION 0 +#define OB_BODY_TYPE_STATIC 1 +#define OB_BODY_TYPE_DYNAMIC 2 +#define OB_BODY_TYPE_RIGID 3 +#define OB_BODY_TYPE_SOFT 4 + /* ob->scavisflag */ #define OB_VIS_SENS 1 #define OB_VIS_CONT 2 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 363f0075e23..8618bee3638 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -416,6 +416,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PARS_DEAD 1 #define PARS_UNBORN 2 #define PARS_ALIVE 3 +#define PARS_DYING 4 /* psys->vg */ #define PSYS_TOT_VG 12 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 75affbfa7f5..32522d1e866 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -464,7 +464,7 @@ typedef struct SculptData struct SculptSession *session; /* Pointers to all of sculptmodes's textures */ - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* Editable brush shape */ struct CurveMapping *cumap; @@ -790,6 +790,7 @@ typedef struct Scene { /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 #define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */ +#define UVCALC_TRANSFORM_CORRECT 4 /* adjust UV's while transforming to avoid distortion */ /* toolsettings->edge_mode */ #define EDGE_MODE_SELECT 0 diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index b5d8511c698..1fd97fe0158 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -164,7 +164,7 @@ typedef struct bSensor { typedef struct bJoystickSensor { char name[32]; short type; - short pad; + short joyindex; int axis; int axisf; int button; @@ -218,6 +218,7 @@ typedef struct bJoystickSensor { #define SENS_NEW 4 #define SENS_NOT 8 #define SENS_VISIBLE 16 +#define SENS_PIN 32 /* sensor->pulse */ #define SENS_PULSE_CONT 0 @@ -237,6 +238,9 @@ typedef struct bJoystickSensor { * */ /* #define SENS_COLLISION_PROPERTY 0 */ #define SENS_COLLISION_MATERIAL 1 +/* ray specific mode */ +/* X-Ray means that the ray will traverse objects that don't have the property/material */ +#define SENS_RAY_XRAY 2 /* Some stuff for the mouse sensor Type: */ #define BL_SENS_MOUSE_LEFT_BUTTON 1 @@ -263,6 +267,7 @@ typedef struct bJoystickSensor { #define SENS_JOY_HAT_DIR 0 #define SENS_DELAY_REPEAT 1 - +// should match JOYINDEX_MAX in SCA_JoystickDefines.h */ +#define SENS_JOY_MAXINDEX 8 #endif diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 39d457058c1..c59cafc1ef0 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -276,22 +276,23 @@ typedef struct SpaceText { struct Text *text; int top, viewlines; - short flags, menunr; - - int font_id; + short flags, menunr; + int font_id; + int lheight; int left; int showlinenrs; - int tabnumber; + int currtab_set; int showsyntax; - int unused_padd; - + int overwrite; float pix_per_line; struct rcti txtscroll, txtbar; + int wordwrap, doplugins; + } SpaceText; typedef struct Script { @@ -537,6 +538,7 @@ typedef struct SpaceImaSel { #define SI_DRAW_TILE 1<<19 #define SI_SMOOTH_UV 1<<20 #define SI_DRAW_STRETCH 1<<21 +#define SI_DISPGP 1<<22 /* SpaceIpo->flag */ #define SIPO_LOCK_VIEW 1<<0 diff --git a/source/blender/makesdna/DNA_text_types.h b/source/blender/makesdna/DNA_text_types.h index d1859d22115..48ecccd517a 100644 --- a/source/blender/makesdna/DNA_text_types.h +++ b/source/blender/makesdna/DNA_text_types.h @@ -38,25 +38,36 @@ typedef struct TextLine { struct TextLine *next, *prev; char *line; - char *format; - int len, blen; + char *format; /* may be NULL if syntax is off or not yet formatted */ + int len, blen; /* blen unused */ } TextLine; +typedef struct TextMarker { + struct TextMarker *next, *prev; + + int lineno, start, end, pad1; /* line number and start/end character indices */ + + int group, flags; /* see BKE_text.h for flag defines */ + char color[4], pad[4]; /* draw color of the marker */ +} TextMarker; + typedef struct Text { ID id; char *name; - + int flags, nlines; ListBase lines; TextLine *curl, *sell; int curc, selc; + ListBase markers; char *undo_buf; int undo_pos, undo_len; void *compiled; + double mtime; } Text; @@ -74,4 +85,12 @@ typedef struct Text { #define TXT_READONLY 0x0100 #define TXT_FOLLOW 0x0200 /* always follow cursor (console) */ +/* format continuation flags */ +#define TXT_NOCONT 0x00 /* no continuation */ +#define TXT_SNGQUOTSTR 0x01 /* single quotes */ +#define TXT_DBLQUOTSTR 0x02 /* double quotes */ +#define TXT_TRISTR 0x04 /* triplets of quotes: """ or ''' */ +#define TXT_SNGTRISTR 0x05 /*(TXT_TRISTR | TXT_SNGQUOTSTR)*/ +#define TXT_DBLTRISTR 0x06 /*(TXT_TRISTR | TXT_DBLQUOTSTR)*/ + #endif diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index 8a79ce845d7..111dc08ee02 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -367,6 +367,7 @@ typedef struct TexMapping { #define MTEX_BLEND_SAT 11 #define MTEX_BLEND_VAL 12 #define MTEX_BLEND_COLOR 13 +#define MTEX_NUM_BLENDTYPES 14 /* **************** EnvMap ********************* */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 856324695a9..5d36d5ca973 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -188,6 +188,8 @@ typedef struct UserDef { char fontname[256]; // FILE_MAXDIR+FILE length struct ListBase themes; short undosteps; + short undomemory; + short gp_manhattendist, gp_euclideandist, pad; short curssize; short tb_leftmouse, tb_rightmouse; struct SolidLight light[3]; @@ -267,6 +269,7 @@ extern UserDef U; /* from usiblender.c !!!! */ #define USER_GLOBALUNDO (1 << 13) #define USER_ORBIT_SELECTION (1 << 14) // old flag for #define USER_KEYINSERTAVAI (1 << 15) +#define USER_ORBIT_ZBUF (1 << 15) #define USER_HIDE_DOT (1 << 16) #define USER_SHOW_ROTVIEWICON (1 << 17) #define USER_SHOW_VIEWPORTNAME (1 << 18) @@ -290,7 +293,7 @@ extern UserDef U; /* from usiblender.c !!!! */ /* Auto-Keying macros */ #define IS_AUTOKEY_ON (U.autokey_mode & AUTOKEY_ON) #define IS_AUTOKEY_MODE(mode) (U.autokey_mode == AUTOKEY_MODE_##mode) -#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag == AUTOKEY_FLAG_##flag) +#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag & AUTOKEY_FLAG_##flag) /* transopts */ #define USER_TR_TOOLTIPS (1 << 0) diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 135272b9ac2..b30a7162b93 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -86,7 +86,8 @@ typedef struct View3D { float winmat1[4][4]; // persp(1) storage, for swap matrices float viewmat1[4][4]; - float viewquat[4], dist, zfac, pad0; /* zfac is initgrabz() result */ + float viewquat[4], dist, zfac; /* zfac is initgrabz() result */ + int lay_used; /* used while drawing */ short persp; short view; diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 26b3f051944..ab7e25190ad 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -38,7 +38,7 @@ struct Ipo; struct MTex; #ifndef MAX_MTEX -#define MAX_MTEX 10 +#define MAX_MTEX 18 #endif @@ -108,7 +108,7 @@ typedef struct World { struct Ipo *ipo; - struct MTex *mtex[10]; + struct MTex *mtex[18]; /* MAX_MTEX */ /* previews */ struct PreviewImage *preview; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 2cb855ed440..cf83804b999 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -30,7 +30,7 @@ SET(INC ../python ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/iksolver/extern ../blenloader ../quicktime - ../blenkernel + ../blenkernel ../../../extern/glew/include ../gpu ${SDL_INC} ${ZLIB_INC} ${PYTHON_INC} diff --git a/source/blender/nodes/SConscript b/source/blender/nodes/SConscript index 8682f626b80..8af7b67520e 100644 --- a/source/blender/nodes/SConscript +++ b/source/blender/nodes/SConscript @@ -11,6 +11,7 @@ incs += ' ../python ../render/extern/include ' incs += ' ../imbuf ../avi ' incs += ' ../blenloader ../quicktime' incs += ' ../blenkernel ../renderconverter ' +incs += ' ../gpu #/extern/glew/include ' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c index 5e1803a6774..950ad97a397 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c @@ -130,13 +130,16 @@ static void node_composit_exec_tonemap(void *data, bNode *node, bNodeStack **in, if ((img==NULL) || (out[0]->hasoutput==0)) return; if (img->type != CB_RGBA) - new = typecheck_compbuf(img, CB_RGBA); - else - new = dupalloc_compbuf(img); + img = typecheck_compbuf(img, CB_RGBA); + + new = dupalloc_compbuf(img); tonemap(node->storage, new, img); out[0]->data = new; + + if(img!=in[0]->data) + free_compbuf(img); } static void node_composit_init_tonemap(bNode* node) diff --git a/source/blender/nodes/intern/CMP_nodes/Makefile b/source/blender/nodes/intern/CMP_nodes/Makefile index 61b03f237db..8a8d323ac5b 100644 --- a/source/blender/nodes/intern/CMP_nodes/Makefile +++ b/source/blender/nodes/intern/CMP_nodes/Makefile @@ -42,4 +42,5 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/Makefile b/source/blender/nodes/intern/Makefile index 7cf2411ed84..6167cf6bc72 100644 --- a/source/blender/nodes/intern/Makefile +++ b/source/blender/nodes/intern/Makefile @@ -42,4 +42,6 @@ CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../include CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../render/extern/include +CPPFLAGS += -I../../gpu +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/Makefile b/source/blender/nodes/intern/SHD_nodes/Makefile index 1917e9ba15c..ae3cae029d2 100644 --- a/source/blender/nodes/intern/SHD_nodes/Makefile +++ b/source/blender/nodes/intern/SHD_nodes/Makefile @@ -44,4 +44,6 @@ CPPFLAGS += -I../../../blenlib CPPFLAGS += -I../../../include CPPFLAGS += -I../../../imbuf CPPFLAGS += -I../../../render/extern/include +CPPFLAGS += -I../../../gpu +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c index 63260ff91ed..20136d75540 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_camera.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_camera.c @@ -46,8 +46,13 @@ static void node_shader_exec_camera(void *data, bNode *node, bNodeStack **in, bN VECCOPY(out[0]->vec, shi->co); /* get view vector */ out[1]->vec[0]= fabs(shi->co[2]); /* get view z-depth */ out[2]->vec[0]= Normalize(out[0]->vec); /* get view distance */ - } } +} + +static int gpu_shader_camera(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "camera", in, out, GPU_builtin(GPU_VIEW_POSITION)); +} bNodeType sh_node_camera= { /* *next,*prev */ NULL, NULL, @@ -63,6 +68,7 @@ bNodeType sh_node_camera= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_camera }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c index b6f1f8d52cd..d277547b636 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_curves.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_curves.c @@ -56,6 +56,15 @@ static void node_shader_init_curve_vec(bNode* node) node->storage= curvemapping_add(3, -1.0f, -1.0f, 1.0f, 1.0f); } +static int gpu_shader_curve_vec(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_vec", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_curve_vec= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_VEC, @@ -70,7 +79,8 @@ bNodeType sh_node_curve_vec= { /* initfunc */ node_shader_init_curve_vec, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_curve_vec }; @@ -100,6 +110,15 @@ static void node_shader_init_curve_rgb(bNode *node) node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f); } +static int gpu_shader_curve_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + curvemapping_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "curves_rgb", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_curve_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_CURVE_RGB, @@ -114,6 +133,7 @@ bNodeType sh_node_curve_rgb= { /* initfunc */ node_shader_init_curve_rgb, /* freestoragefunc */ node_free_curves, /* copystoragefunc */ node_copy_curves, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_curve_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c index 24395059c60..bc345759b98 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_geom.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_geom.c @@ -29,6 +29,7 @@ #include "../SHD_util.h" +#include "DNA_customdata_types.h" /* **************** GEOMETRY ******************** */ @@ -124,6 +125,18 @@ static void node_shader_init_geometry(bNode *node) node->storage= MEM_callocN(sizeof(NodeGeometry), "NodeGeometry"); } +static int gpu_shader_geom(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + NodeGeometry *ngeo= (NodeGeometry*)node->storage; + GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); + GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ngeo->uvname); + GPUNodeLink *mcol = GPU_attribute(CD_MCOL, ngeo->colname); + + return GPU_stack_link(mat, "geom", in, out, + GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), + GPU_builtin(GPU_INVERSE_VIEW_MATRIX), orco, mtface, mcol); +} + /* node type definition */ bNodeType sh_node_geom= { /* *next,*prev */ NULL, NULL, @@ -139,6 +152,7 @@ bNodeType sh_node_geom= { /* initfunc */ node_shader_init_geometry, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_geom }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c index 67dfc619080..1b7b2dfb8e7 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c @@ -71,6 +71,12 @@ static void node_shader_exec_hue_sat(void *data, bNode *node, bNodeStack **in, b do_hue_sat_fac(node, out[0]->vec, in[0]->vec, in[1]->vec, in[2]->vec, in[4]->vec, in[3]->vec); } + +static int gpu_shader_hue_sat(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "hue_sat", in, out); +} + bNodeType sh_node_hue_sat= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_HUE_SAT, @@ -85,7 +91,8 @@ bNodeType sh_node_hue_sat= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_hue_sat }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c index 4d1ce282fce..72ee1483ecf 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_invert.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_invert.c @@ -64,6 +64,11 @@ bNodeStack **out) VECCOPY(out[0]->vec, col); } +static int gpu_shader_invert(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "invert", in, out); +} + bNodeType sh_node_invert= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_INVERT, @@ -78,6 +83,7 @@ bNodeType sh_node_invert= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_invert }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c index 589954c8f7b..c081929a2fc 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mapping.c @@ -69,6 +69,20 @@ static void node_shader_init_mapping(bNode *node) node->storage= add_mapping(); } +static int gpu_shader_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + TexMapping *texmap= node->storage; + float domin= (texmap->flag & TEXMAP_CLIP_MIN) != 0; + float domax= (texmap->flag & TEXMAP_CLIP_MAX) != 0; + GPUNodeLink *tmat = GPU_uniform((float*)texmap->mat); + GPUNodeLink *tmin = GPU_uniform(texmap->min); + GPUNodeLink *tmax = GPU_uniform(texmap->max); + GPUNodeLink *tdomin = GPU_uniform(&domin); + GPUNodeLink *tdomax = GPU_uniform(&domax); + + return GPU_stack_link(mat, "mapping", in, out, tmat, tmin, tmax, tdomin, tdomax); +} + bNodeType sh_node_mapping= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MAPPING, @@ -83,7 +97,8 @@ bNodeType sh_node_mapping= { /* initfunc */ node_shader_init_mapping, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_mapping }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index 9396410f850..c0a2534ac4a 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -182,6 +182,77 @@ static void node_shader_init_material(bNode* node) node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; } +static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + if(node->id) { + GPUShadeInput shi; + GPUShadeResult shr; + + GPU_shadeinput_set(mat, (Material*)node->id, &shi); + + /* write values */ + if(in[MAT_IN_COLOR].hasinput) + shi.rgb = in[MAT_IN_COLOR].link; + + if(in[MAT_IN_SPEC].hasinput) + shi.specrgb = in[MAT_IN_SPEC].link; + + if(in[MAT_IN_REFL].hasinput) + shi.refl = in[MAT_IN_REFL].link; + + /* retrieve normal */ + if(in[MAT_IN_NORMAL].hasinput) { + GPUNodeLink *tmp; + shi.vn = in[MAT_IN_NORMAL].link; + GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); + } + + /* custom option to flip normal */ + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + + if (node->type == SH_NODE_MATERIAL_EXT) { + if(in[MAT_IN_AMB].hasinput) + shi.amb= in[MAT_IN_AMB].link; + if(in[MAT_IN_EMIT].hasinput) + shi.emit= in[MAT_IN_EMIT].link; + if(in[MAT_IN_ALPHA].hasinput) + shi.alpha= in[MAT_IN_ALPHA].link; + } + + GPU_shaderesult_set(&shi, &shr); /* clears shr */ + + /* write to outputs */ + if(node->custom1 & SH_NODE_MAT_DIFF) { + if(node->custom1 & SH_NODE_MAT_SPEC) + out[MAT_OUT_COLOR].link= shr.combined; + else + out[MAT_OUT_COLOR].link= shr.diff; + } + else if(node->custom1 & SH_NODE_MAT_SPEC) { + out[MAT_OUT_COLOR].link= shr.spec; + } + else + GPU_link(mat, "set_rgb_zero", &out[MAT_OUT_COLOR].link); + + GPU_link(mat, "mtex_alpha_to_col", out[MAT_OUT_COLOR].link, shr.alpha, &out[MAT_OUT_COLOR].link); + + out[MAT_OUT_ALPHA].link = shr.alpha; // + + if(node->custom1 & SH_NODE_MAT_NEG) + GPU_link(mat, "vec_math_negate", shi.vn, &shi.vn); + out[MAT_OUT_NORMAL].link = shi.vn; + + if (node->type == SH_NODE_MATERIAL_EXT) { + out[MAT_OUT_DIFFUSE].link = shr.diff; + out[MAT_OUT_SPEC].link = shr.spec; + } + + return 1; + } + + return 0; +} bNodeType sh_node_material= { /* *next,*prev */ NULL, NULL, @@ -197,8 +268,8 @@ bNodeType sh_node_material= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL - + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_material }; bNodeType sh_node_material_ext= { @@ -215,7 +286,7 @@ bNodeType sh_node_material_ext= { /* initfunc */ node_shader_init_material, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL - + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_material }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_math.c b/source/blender/nodes/intern/SHD_nodes/SHD_math.c index 2e156cf12bf..050c2cdcc95 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_math.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_math.c @@ -194,6 +194,46 @@ bNodeStack **out) } } +static int gpu_shader_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"math_add", "math_subtract", "math_multiply", + "math_divide", "math_sine", "math_cosine", "math_tangnet", "math_asin", + "math_acos", "math_atan", "math_pow", "math_log", "math_min", "math_max", + "math_round", "math_less_than", "math_greater_than"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 10: + case 11: + case 12: + case 13: + case 15: + case 16: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 14: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + bNodeType sh_node_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MATH, @@ -208,6 +248,7 @@ bNodeType sh_node_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_math }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c index dba70253fda..2da1dee5623 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c @@ -60,6 +60,17 @@ static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, b VECCOPY(out[0]->vec, col); } +static int gpu_shader_mix_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"mix_blend", "mix_add", "mix_mult", "mix_sub", + "mix_screen", "mix_div", "mix_diff", "mix_dark", "mix_light", + "mix_overlay", "mix_dodge", "mix_burn", "mix_hue", "mix_sat", + "mix_val", "mix_color"}; + + return GPU_stack_link(mat, names[node->custom1], in, out); +} + + bNodeType sh_node_mix_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_MIX_RGB, @@ -74,6 +85,7 @@ bNodeType sh_node_mix_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_mix_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c index f1ffd3446af..9d4ea1ccf67 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_normal.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_normal.c @@ -57,6 +57,14 @@ static void node_shader_exec_normal(void *data, bNode *node, bNodeStack **in, bN out[1]->vec[0]= -INPR(out[0]->vec, vec); } +static int gpu_shader_normal(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + + return GPU_stack_link(mat, "normal", in, out, vec); +} + bNodeType sh_node_normal= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_NORMAL, @@ -71,6 +79,7 @@ bNodeType sh_node_normal= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_normal }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_output.c b/source/blender/nodes/intern/SHD_nodes/SHD_output.c index 0a9a30c452b..76856cfd2e8 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_output.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_output.c @@ -62,6 +62,19 @@ static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bN } } +static int gpu_shader_output(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + GPUNodeLink *outlink; + + /*if(in[1].hasinput) + GPU_material_enable_alpha(mat);*/ + + GPU_stack_link(mat, "output_node", in, out, &outlink); + GPU_material_output_link(mat, outlink); + + return 1; +} + bNodeType sh_node_output= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_OUTPUT, @@ -76,7 +89,8 @@ bNodeType sh_node_output= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_output }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c index 4e56e26d3ad..1aa1a2ffc33 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_rgb.c @@ -42,6 +42,14 @@ static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNode VECCOPY(out[0]->vec, sock->ns.vec); } +static int gpu_shader_rgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + + return GPU_stack_link(mat, "set_rgba", in, out, vec); +} + bNodeType sh_node_rgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGB, @@ -56,6 +64,7 @@ bNodeType sh_node_rgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_rgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c index 2b52a8e2229..6d5df2a1321 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c @@ -48,6 +48,11 @@ static void node_shader_exec_seprgb(void *data, bNode *node, bNodeStack **in, bN out[2]->vec[0] = in[0]->vec[2]; } +static int gpu_shader_seprgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "separate_rgb", in, out); +} + bNodeType sh_node_seprgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SEPRGB, @@ -62,7 +67,8 @@ bNodeType sh_node_seprgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_seprgb }; @@ -86,6 +92,11 @@ static void node_shader_exec_combrgb(void *data, bNode *node, bNodeStack **in, b out[0]->vec[2] = in[2]->vec[0]; } +static int gpu_shader_combrgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "combine_rgb", in, out); +} + bNodeType sh_node_combrgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_COMBRGB, @@ -100,6 +111,7 @@ bNodeType sh_node_combrgb= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_combrgb }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c index 30abad666c4..d3480a6ae9d 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c @@ -54,6 +54,11 @@ bNodeStack **out) out[0]->vec[0] = 1.0f / (1.0f + pow(2.71828183,-((vec[0]-vec[2])*vec[1]))) ; } +static int gpu_shader_squeeze(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "squeeze", in, out); +} + bNodeType sh_node_squeeze= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_SQUEEZE, @@ -68,6 +73,7 @@ bNodeType sh_node_squeeze= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_squeeze }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c index ace11a20d42..31dbde940fd 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_texture.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_texture.c @@ -27,6 +27,8 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "DNA_texture_types.h" + #include "../SHD_util.h" /* **************** TEXTURE ******************** */ @@ -110,6 +112,18 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b } } +static int gpu_shader_texture(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + Tex *tex = (Tex*)node->id; + + if(tex && tex->type == TEX_IMAGE && tex->ima) { + GPUNodeLink *texlink = GPU_image(tex->ima, NULL); + return GPU_stack_link(mat, "texture_image", in, out, texlink); + } + else + return 0; +} + bNodeType sh_node_texture= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_TEXTURE, @@ -124,7 +138,8 @@ bNodeType sh_node_texture= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_texture }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c index cf7e33d9dca..301c0cb7031 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c @@ -59,6 +59,15 @@ static void node_shader_init_valtorgb(bNode *node) node->storage= add_colorband(1); } +static int gpu_shader_valtorgb(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + float *array; + int size; + + colorband_table_RGBA(node->storage, &array, &size); + return GPU_stack_link(mat, "valtorgb", in, out, GPU_texture(size, array)); +} + bNodeType sh_node_valtorgb= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VALTORGB, @@ -73,7 +82,8 @@ bNodeType sh_node_valtorgb= { /* initfunc */ node_shader_init_valtorgb, /* freestoragefunc */ node_free_standard_storage, /* copystoragefunc */ node_copy_standard_storage, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_valtorgb }; @@ -96,6 +106,11 @@ static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, b out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f; } +static int gpu_shader_rgbtobw(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "rgbtobw", in, out); +} + bNodeType sh_node_rgbtobw= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_RGBTOBW, @@ -110,7 +125,8 @@ bNodeType sh_node_rgbtobw= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_rgbtobw }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_value.c b/source/blender/nodes/intern/SHD_nodes/SHD_value.c index 57ef7226066..768ef3cda3d 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_value.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_value.c @@ -42,7 +42,13 @@ static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNo out[0]->vec[0]= sock->ns.vec[0]; } +static int gpu_shader_value(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + bNodeSocket *sock= node->outputs.first; + GPUNodeLink *vec = GPU_uniform(sock->ns.vec); + return GPU_stack_link(mat, "set_value", in, out, vec); +} bNodeType sh_node_value= { /* *next,*prev */ NULL, NULL, @@ -58,7 +64,8 @@ bNodeType sh_node_value= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_value }; diff --git a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c index 8d0a4b3abe3..96db8db18a6 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c @@ -99,6 +99,34 @@ static void node_shader_exec_vect_math(void *data, bNode *node, bNodeStack **in, } +static int gpu_shader_vect_math(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) +{ + static char *names[] = {"vec_math_add", "vec_math_subtract", + "vec_math_average", "vec_math_dot", "vec_math_cross", + "vec_math_normalize"}; + + switch (node->custom1) { + case 0: + case 1: + case 2: + case 3: + case 4: + GPU_stack_link(mat, names[node->custom1], NULL, out, + GPU_socket(&in[0]), GPU_socket(&in[1])); + break; + case 5: + if(in[0].hasinput || !in[1].hasinput) + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[0])); + else + GPU_stack_link(mat, names[node->custom1], NULL, out, GPU_socket(&in[1])); + break; + default: + return 0; + } + + return 1; +} + bNodeType sh_node_vect_math= { /* *next,*prev */ NULL, NULL, /* type code */ SH_NODE_VECT_MATH, @@ -113,6 +141,7 @@ bNodeType sh_node_vect_math= { /* initfunc */ NULL, /* freestoragefunc */ NULL, /* copystoragefunc */ NULL, - /* id */ NULL + /* id */ NULL, NULL, NULL, + /* gpufunc */ gpu_shader_vect_math }; diff --git a/source/blender/nodes/intern/SHD_util.h b/source/blender/nodes/intern/SHD_util.h index bdb2bb3707d..eda985529c1 100644 --- a/source/blender/nodes/intern/SHD_util.h +++ b/source/blender/nodes/intern/SHD_util.h @@ -88,6 +88,8 @@ #include "RE_pipeline.h" #include "RE_shader_ext.h" +#include "GPU_material.h" + #include "butspace.h" #include "blendef.h" #include "mydevice.h" diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index f6a27b80733..146093d6b99 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -48,6 +48,7 @@ struct bPythonConstraint; /* DNA_constraint_types.h */ struct bConstraintOb; /* DNA_constraint_types.h */ struct bConstraintTarget; /* DNA_constraint_types.h*/ struct Script; /* DNA_screen_types.h */ +struct BPyMenu; #ifdef __cplusplus extern "C" { #endif @@ -91,13 +92,15 @@ extern "C" { int BPY_txt_do_python_Text( struct Text *text ); int BPY_menu_do_python( short menutype, int event ); - void BPY_run_python_script( char *filename ); + int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers ); + int BPY_menu_invoke( struct BPyMenu *pym, short menutype ); + void BPY_run_python_script( const char *filename ); int BPY_run_script(struct Script *script); void BPY_free_compiled_text( struct Text *text ); void BPY_clear_bad_scriptlinks( struct Text *byebye ); int BPY_has_onload_script( void ); - void BPY_do_all_scripts( short event ); + void BPY_do_all_scripts( short event, short anim ); int BPY_check_all_scriptlinks( struct Text *text ); void BPY_do_pyscript( struct ID *id, short event ); void BPY_free_scriptlink( struct ScriptLink *slink ); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 69bff059356..c0dab4df651 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -292,7 +292,7 @@ void syspath_append( char *dirname ) short ok=1; PyErr_Clear( ); - dir = Py_BuildValue( "s", dirname ); + dir = PyString_FromString( dirname ); mod_sys = PyImport_ImportModule( "sys" ); /* new ref */ @@ -308,32 +308,29 @@ void syspath_append( char *dirname ) } if (PySequence_Contains(path, dir)==0) { /* Only add if we need to */ - if (ok && PyList_Append( path, dir ) != 0) + if (ok && PyList_Append( path, dir ) != 0) /* decref below */ ok = 0; /* append failed */ if( (ok==0) || PyErr_Occurred( ) ) Py_FatalError( "could import or build sys.path, can't continue" ); } + Py_DECREF( dir ); Py_XDECREF( mod_sys ); } void init_syspath( int first_time ) { - PyObject *path; PyObject *mod, *d; char *progname; char execdir[FILE_MAXDIR]; /*defines from DNA_space_types.h */ int n; - - - path = Py_BuildValue( "s", bprogname ); mod = PyImport_ImportModule( "Blender.sys" ); if( mod ) { d = PyModule_GetDict( mod ); - EXPP_dict_set_item_str( d, "progname", path ); + EXPP_dict_set_item_str( d, "progname", PyString_FromString( bprogname ) ); Py_DECREF( mod ); } else printf( "Warning: could not set Blender.sys.progname\n" ); @@ -556,6 +553,7 @@ void BPY_Err_Handle( char *script_name ) if( exception && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) { /* no traceback available when SyntaxError */ + PyErr_NormalizeException( &exception, &err, &tb ); PyErr_Restore( exception, err, tb ); /* takes away reference! */ PyErr_Print( ); v = PyObject_GetAttrString( err, "lineno" ); @@ -722,13 +720,23 @@ int BPY_txt_do_python_Text( struct Text *text ) * automatically. The script can be a file or a Blender Text in the current * .blend. ****************************************************************************/ -void BPY_run_python_script( char *fn ) +void BPY_run_python_script( const char *fn ) { + char filename[FILE_MAXDIR + FILE_MAXFILE]; Text *text = NULL; int is_blender_text = 0; - - if (!BLI_exists(fn)) { /* if there's no such filename ... */ - text = G.main->text.first; /* try an already existing Blender Text */ + + BLI_strncpy(filename, fn, FILE_MAXDIR + FILE_MAXFILE); + + if (!BLI_exists(filename)) + BLI_convertstringcwd(filename); + + if (!BLI_exists(filename)) { /* if there's no such filename ... */ + /* try an already existing Blender Text. + * use 'fn' rather then filename for this since were looking for + * internal text + */ + text = G.main->text.first; while (text) { if (!strcmp(fn, text->id.name + 2)) break; @@ -743,11 +751,14 @@ void BPY_run_python_script( char *fn ) } else { - text = add_text(fn); + /* use filename here since we know it exists, + * 'fn' may have been a relative path + */ + text = add_text(filename); if (text == NULL) { printf("\nError in BPY_run_python_script:\n" - "couldn't create Blender text from %s\n", fn); + "couldn't create Blender text from \"%s\"\n", filename); /* Chris: On Windows if I continue I just get a segmentation * violation. To get a baseline file I exit here. */ exit(2); @@ -764,13 +775,8 @@ void BPY_run_python_script( char *fn ) /* We can't simply free the text, since the script might have called * Blender.Load() to load a new .blend, freeing previous data. * So we check if the pointer is still valid. */ - Text *txtptr = G.main->text.first; - while (txtptr) { - if (txtptr == text) { - free_libblock(&G.main->text, text); - break; - } - txtptr = txtptr->id.next; + if (BLI_findindex(&G.main->text, text) != -1) { + free_libblock(&G.main->text, text); } } } @@ -780,9 +786,6 @@ int BPY_run_script(Script *script) PyObject *py_dict, *py_res, *pyarg; Text *text = NULL; BPy_constant *info; - int len; - - FILE *fp = NULL; PyGILState_STATE gilstate = PyGILState_Ensure(); @@ -827,12 +830,8 @@ int BPY_run_script(Script *script) Py_INCREF( Py_None ); pyarg = Py_None; } else { - if (BLI_exists(script->scriptname)) { - fp = fopen( script->scriptname, "rb" ); - } - - if( !fp ) { - printf( "Error loading script: couldn't open file %s\n", script->scriptname ); + if (!BLI_exists(script->scriptname)) { + printf( "Script does not exit %s\n", script->scriptname ); free_libblock( &G.main->script, script ); PyGILState_Release(gilstate); return 0; @@ -877,51 +876,17 @@ int BPY_run_script(Script *script) if (text) { py_res = RunPython( text, py_dict ); } else { + char pystring[sizeof(script->scriptname) + 15]; + sprintf(pystring, "execfile(r'%s')", script->scriptname); + py_res = PyRun_String( pystring, Py_file_input, py_dict, py_dict ); + } + + if( !py_res ) { /* Failed execution of the script */ /* Previously we used PyRun_File to run directly the code on a FILE * object, but as written in the Python/C API Ref Manual, chapter 2, * 'FILE structs for different C libraries can be different and * incompatible'. * So now we load the script file data to a buffer */ - char *buffer=NULL, *buffer_ofs=NULL, *b_to, *b_from; - - fseek( fp, 0L, SEEK_END ); - len = ftell( fp ); - fseek( fp, 0L, SEEK_SET ); - - buffer = buffer_ofs = MEM_mallocN( len + 2, "pyfilebuf" ); /* len+2 to add '\n\0' */ - len = fread( buffer, 1, len, fp ); - - buffer[len] = '\n'; /* fix syntax error in files w/o eol */ - buffer[len + 1] = '\0'; - - - /* fast clean-up of dos cr/lf line endings, remove convert '\r\n's to '\n' */ - if (*buffer_ofs == '\r' && *(buffer_ofs+1) == '\n') { - buffer_ofs++; - } - b_from = b_to = buffer_ofs; - - while(*b_from != '\0') { - if (*b_from == '\r' && *( b_from+1 ) == '\n') { - b_from++; - } - if (b_from != b_to) { - *b_to = *b_from; - } - b_to++; - b_from++; - } - *b_to = '\0'; - /* done cleaning the string */ - - fclose( fp ); - - py_res = PyRun_String( buffer_ofs, Py_file_input, py_dict, py_dict ); - MEM_freeN( buffer ); - } - - if( !py_res ) { /* Failed execution of the script */ - BPY_Err_Handle( script->id.name + 2 ); ReleaseGlobalDictionary( py_dict ); script->py_globaldict = NULL; @@ -965,8 +930,38 @@ int BPY_run_script(Script *script) *****************************************************************************/ int BPY_menu_do_python( short menutype, int event ) { - char *argstr = NULL; BPyMenu *pym; + pym = BPyMenu_GetEntry( menutype, ( short ) event ); + return BPY_menu_invoke( pym, menutype ); +} + +/**************************************************************************** +* Description: This function executes the script by its shortcut. +* Notes: It is called by the ui code in src/???.c when a user presses an +* unassigned key combination. Scripts are searched in the BPyMenuTable, +* using the given menutype and event values to know which one to invoke. +*****************************************************************************/ +int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short qual ) +{ + BPyMenu *pym; + pym = BPyMenu_GetEntry( menutype, 0 ); + + while ( pym ) { + if ( pym->key && pym->key == key && pym->qual == qual ) { + return BPY_menu_invoke( pym, menutype ); + } + pym = pym->next; + } + + return 0; +} + +/**************************************************************************** +* Description: This function executes the script described by a menu item. +*****************************************************************************/ +int BPY_menu_invoke( BPyMenu *pym, short menutype ) +{ + char *argstr = NULL; BPySubMenu *pysm; char scriptname[21]; Script *script = NULL; @@ -974,8 +969,6 @@ int BPY_menu_do_python( short menutype, int event ) PyGILState_STATE gilstate; char filestr[FILE_MAX]; - pym = BPyMenu_GetEntry( menutype, ( short ) event ); - if( !pym ) return 0; @@ -1059,6 +1052,7 @@ int BPY_menu_do_python( short menutype, int event ) case PYMENU_RENDER: case PYMENU_WIZARDS: case PYMENU_SCRIPTTEMPLATE: + case PYMENU_TEXTPLUGIN: case PYMENU_MESHFACEKEY: break; @@ -2169,8 +2163,14 @@ void BPY_clear_bad_scriptlinks( struct Text *byebye ) * For the scene, only the current active scene the scripts are * executed (if any). *****************************************************************************/ -void BPY_do_all_scripts( short event ) +void BPY_do_all_scripts( short event, short anim ) { + /* during stills rendering we disable FRAMECHANGED events */ + static char disable_frame_changed = 0; + + if ((event == SCRIPT_FRAMECHANGED) && disable_frame_changed) + return; + DoAllScriptsFromList( &( G.main->object ), event ); DoAllScriptsFromList( &( G.main->lamp ), event ); DoAllScriptsFromList( &( G.main->camera ), event ); @@ -2186,9 +2186,12 @@ void BPY_do_all_scripts( short event ) * "import sys; sys.setcheckinterval(sys.maxint)" */ if (event == SCRIPT_RENDER) { _Py_CheckInterval = PyInt_GetMax(); + if (!anim) + disable_frame_changed = 1; } else if (event == SCRIPT_POSTRENDER) { _Py_CheckInterval = 100; /* Python default */ + disable_frame_changed = 0; } return; diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c index 82da9edbee6..69b50e5c47a 100644 --- a/source/blender/python/BPY_menus.c +++ b/source/blender/python/BPY_menus.c @@ -42,6 +42,7 @@ #endif #include "BKE_global.h" #include "BKE_utildefines.h" +#include "BIF_keyval.h" #include "BLI_blenlib.h" #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" /* for U.pythondir */ @@ -106,6 +107,8 @@ static int bpymenu_group_atoi( char *str ) return PYMENU_ARMATURE; else if( !strcmp( str, "ScriptTemplate" ) ) return PYMENU_SCRIPTTEMPLATE; + else if( !strcmp( str, "TextPlugin" ) ) + return PYMENU_TEXTPLUGIN; else if( !strcmp( str, "MeshFaceKey" ) ) return PYMENU_MESHFACEKEY; else if( !strcmp( str, "AddMesh" ) ) @@ -184,6 +187,9 @@ char *BPyMenu_group_itoa( short menugroup ) case PYMENU_SCRIPTTEMPLATE: return "ScriptTemplate"; break; + case PYMENU_TEXTPLUGIN: + return "TextPlugin"; + break; case PYMENU_MESHFACEKEY: return "MeshFaceKey"; break; @@ -328,6 +334,23 @@ static void bpymenu_set_tooltip( BPyMenu * pymenu, char *tip ) return; } +static void bpymenu_set_shortcut( BPyMenu * pymenu, char *combi ) +{ + unsigned short key, qual; + + if( !pymenu ) + return; + + if (!decode_key_string(combi, &key, &qual)) { + return; /* TODO: Print some error */ + } + + pymenu->key = key; + pymenu->qual = qual; + + 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. @@ -688,6 +711,7 @@ void BPyMenu_PrintAllEntries( void ) * # Blender: short int (minimal Blender version) * # Group: 'group name' (defines menu) * # Submenu: 'submenu name' related_1word_arg + * # Shortcut: Modifier+Key (optional shortcut combination for supported groups) * # Tooltip: 'tooltip for the menu' * # \"\"\" * @@ -796,13 +820,19 @@ static int bpymenu_ParseFile(FILE *file, char *fname, int is_userdir) if ((matches == 3) && (strstr(head, "Submenu:") != NULL)) { bpymenu_AddSubEntry(scriptMenu, middle, tail); } else { - /* Tooltip: 'tooltip for the menu */ + /* Shortcut: 'key+combination' */ matches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail); - if ((matches == 3) && ((strstr(head, "Tooltip:") != NULL) || - (strstr(head, "Tip:") != NULL))) { - bpymenu_set_tooltip(scriptMenu, middle); + if ((matches == 3) && (strstr(head, "Shortcut:") != NULL)) { + bpymenu_set_shortcut(scriptMenu, middle); + } 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; } - parser_state = 0; } break; diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h index 1b557f79286..576d7b8dcd6 100644 --- a/source/blender/python/BPY_menus.h +++ b/source/blender/python/BPY_menus.h @@ -59,6 +59,7 @@ typedef struct BPyMenu { char *name; char *filename; char *tooltip; + unsigned short key, qual; /* Registered shortcut key */ short version; /* Blender version */ int dir; /* 0: default, 1: U.pythondir */ struct BPySubMenu *submenus; @@ -99,6 +100,7 @@ typedef enum { PYMENU_UVCALCULATION, PYMENU_ARMATURE, PYMENU_SCRIPTTEMPLATE, + PYMENU_TEXTPLUGIN, PYMENU_HELP,/*Main Help menu items - prob best to leave for 'official' ones*/ PYMENU_HELPSYSTEM,/* Resources, troubleshooting, system tools */ PYMENU_HELPWEBSITES,/* Help -> Websites submenu */ diff --git a/source/blender/python/CMakeLists.txt b/source/blender/python/CMakeLists.txt index 0106ab77843..63a1e67236e 100644 --- a/source/blender/python/CMakeLists.txt +++ b/source/blender/python/CMakeLists.txt @@ -34,7 +34,7 @@ SET(INC api2_2x ../blenkernel ../blenlib ../blenloader ../render/extern/include ../radiosity/extern/include ../makesdna ../../../intern/guardedalloc ../../../intern/bmfont ../imbuf ../include - ${PYTHON_INC} + ${PYTHON_INC} ../../../extern/glew/include ../gpu ) IF(WITH_QUICKTIME) @@ -50,5 +50,9 @@ IF(WITH_FFMPEG) ADD_DEFINITIONS(-DWITH_FFMPEG) ENDIF(WITH_FFMPEG) +IF(BF_BUILDINFO) + ADD_DEFINITIONS(-DNAN_BUILDINFO) +ENDIF(BF_BUILDINFO) + BLENDERLIB_NOLIST(blender_python "${SRC}" "${INC}") #env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] ) diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript index 481fdcbe13e..27dd510f944 100644 --- a/source/blender/python/SConscript +++ b/source/blender/python/SConscript @@ -6,6 +6,7 @@ sources = Split('BPY_interface.c BPY_menus.c') + env.Glob('api2_2x/*.c') incs = 'api2_2x ../blenkernel ../nodes ../blenlib ../blenloader' incs += ' ../render/extern/include ../radiosity/extern/include' incs += ' ../makesdna #intern/guardedalloc #intern/bmfont ../imbuf ../include' +incs += ' #extern/glew/include ../gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_OPENGL_INC'] @@ -23,4 +24,7 @@ if env['WITH_BF_OPENEXR'] == 1: if env['WITH_BF_FFMPEG'] == 1: defs.append('WITH_FFMPEG') +if env['BF_BUILDINFO'] == 1: + defs.append('NAN_BUILDINFO') + env.BlenderLib ( libname='blender_python', sources = Split(sources), includes = Split(incs), defines = defs, libtype=['core','game2'], priority = [60,115] ) diff --git a/source/blender/python/api2_2x/BGL.h b/source/blender/python/api2_2x/BGL.h index ce972795322..461f5bc9372 100644 --- a/source/blender/python/api2_2x/BGL.h +++ b/source/blender/python/api2_2x/BGL.h @@ -323,8 +323,13 @@ typedef struct _Buffer { #define ret_def_GLstring const unsigned char *ret_str; #define ret_set_GLstring ret_str= -#define ret_ret_GLstring return PyString_FromString(ret_str); - +#define ret_ret_GLstring \ + if (ret_str) {\ + return PyString_FromString(ret_str);\ + } else {\ + PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\ + return NULL;\ + } #endif /* EXPP_BGL_H */ diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 2b190a6c828..47e7bcb2007 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -34,7 +34,7 @@ struct ID; /*keep me up here */ /* for open, close in Blender_Load */ #include #include "BDR_editobject.h" /* exit_editmode() */ -#include "BDR_drawmesh.h" /* set_mipmap() */ +#include "GPU_draw.h" /* GPU_set_mipmap() */ #include "BIF_usiblender.h" #include "BLI_blenlib.h" #include "BLI_bpath.h" @@ -314,8 +314,8 @@ static PyObject *Blender_Set( PyObject * self, PyObject * args ) else U.gameflags |= USER_DISABLE_MIPMAP; - set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); - }else + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + } else return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "value given is not a blender setting" ) ); Py_RETURN_NONE; @@ -543,7 +543,21 @@ static PyObject *Blender_Get( PyObject * self, PyObject * value ) } /* End 'quick hack' part. */ else if(StringEqual( str, "version" )) ret = PyInt_FromLong( G.version ); - + else if(StringEqual( str, "buildinfo" )) { +#ifdef NAN_BUILDINFO + char buffer[1024]; + extern char * build_date; + extern char * build_time; + extern char * build_rev; + extern char * build_platform; + extern char * build_type; + + sprintf(buffer, "Built on %s %s, Rev-%s Version %s %s", build_date, build_time, build_rev, build_platform, build_type); + ret = PyString_FromString( buffer ); +#else + ret = PyString_FromString( "No Build Info" ); +#endif + } else if(StringEqual( str, "compressfile" )) ret = PyInt_FromLong( (U.flag & USER_FILECOMPRESS) >> 15 ); else if(StringEqual( str, "mipmap" )) diff --git a/source/blender/python/api2_2x/Camera.c b/source/blender/python/api2_2x/Camera.c index b35fcf410a4..87c605ef612 100644 --- a/source/blender/python/api2_2x/Camera.c +++ b/source/blender/python/api2_2x/Camera.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" /* for M_PI */ #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "gen_utils.h" diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index a62a5ee7ed8..b0b9aa04a08 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -44,6 +44,7 @@ #include "BKE_constraint.h" #include "BLI_blenlib.h" #include "BIF_editconstraint.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" @@ -441,7 +442,7 @@ static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * value ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "constraint doesn't belong to anything" ); } - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index bd19a6a6a3e..b04366d5579 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -928,6 +928,11 @@ static PyObject *Method_Register( PyObject * self, PyObject * args ) Script *script; int startspace = 0; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Register() in background mode." ); + } + if( !PyArg_ParseTuple ( args, "O|OO", &newdrawc, &neweventc, &newbuttonc ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1008,6 +1013,10 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) { int after = 0; + if (G.background) { + Py_RETURN_NONE; + } + if( !PyArg_ParseTuple( args, "|i", &after ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected int argument (or nothing)" ); @@ -1022,6 +1031,10 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) static PyObject *Method_Draw( PyObject * self ) { + if (G.background) { + Py_RETURN_NONE; + } + /*@ If forced drawing is disable queue a redraw event instead */ if( EXPP_disable_force_draw ) { scrarea_queue_winredraw( curarea ); @@ -1089,6 +1102,11 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args ) PyObject *result = NULL; ListBase listb= {NULL, NULL}; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.UIBlock() in background mode." ); + } + if ( !PyArg_ParseTuple( args, "O", &val ) || !PyCallable_Check( val ) ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected 1 python function and 2 ints" ); @@ -1201,6 +1219,11 @@ static PyObject *Method_Button( PyObject * self, PyObject * args ) int x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Button() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiii|sO", &name, &event, &x, &y, &w, &h, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1225,6 +1248,11 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Menu() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1255,6 +1283,11 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Toggle() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1322,6 +1355,11 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args ) PyObject *mino, *maxo, *inio; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Sider() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiiOOO|isO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip, &callback ) ) @@ -1395,6 +1433,11 @@ static PyObject *Method_Scrollbar( PyObject * self, PyObject * args ) float ini, min, max; uiBut *ubut; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Scrollbar() in background mode." ); + } + if( !PyArg_ParseTuple( args, "iiiiiOOO|isO", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1454,6 +1497,11 @@ static PyObject *Method_ColorPicker( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.ColorPicker() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1504,6 +1552,11 @@ static PyObject *Method_Normal( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Normal() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1546,6 +1599,11 @@ static PyObject *Method_Number( PyObject * self, PyObject * args ) PyObject *callback=NULL; uiBut *ubut= NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Number() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiiOOO|sO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1617,6 +1675,11 @@ static PyObject *Method_String( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.String() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiisi|sO", &info_arg, &event, &x, &y, &w, &h, &newstr, &len, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1693,6 +1756,11 @@ static PyObject *Method_Text( PyObject * self, PyObject * args ) char *font_str = NULL; struct BMF_Font *font; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Text() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|s", &text, &font_str ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected one or two string arguments" ); @@ -1724,6 +1792,11 @@ static PyObject *Method_Label( PyObject * self, PyObject * args ) char *text; int x, y, w, h; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Label() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiii", &text, &x, &y, &w, &h ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and four ints" ); @@ -1740,7 +1813,12 @@ static PyObject *Method_PupMenu( PyObject * self, PyObject * args ) char *text; int maxrow = -1; PyObject *ret; - + + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupMenu() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|i", &text, &maxrow ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and optionally an int as arguments" ); @@ -1827,6 +1905,11 @@ static PyObject *Method_PupTreeMenu( PyObject * self, PyObject * args ) ListBase storage = {NULL, NULL}; TBitem *tb; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupMenuTree() in background mode." ); + } + if( !PyArg_ParseTuple( args, "O!", &PyList_Type, ¤t_menu ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "Expected a list" ); @@ -1857,6 +1940,11 @@ static PyObject *Method_PupIntInput( PyObject * self, PyObject * args ) short var = 0; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupIntInput() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|hii", &text, &var, &min, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 1 string and 3 int arguments" ); @@ -1879,6 +1967,11 @@ static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args ) float min = 0, max = 1, var = 0, a1 = 10, a2 = 2; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupFloatInput() in background mode." ); + } + if( !PyArg_ParseTuple ( args, "s|fffff", &text, &var, &min, &max, &a1, &a2 ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1903,6 +1996,11 @@ static PyObject *Method_PupStrInput( PyObject * self, PyObject * args ) char max = 20; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupStrInput() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ss|b", &textMsg, &text, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 strings and 1 int" ); @@ -1937,6 +2035,11 @@ static PyObject *Method_PupBlock( PyObject * self, PyObject * args ) int len, i; char *title; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupBlock() in background mode." ); + } + if (!PyArg_ParseTuple( args, "sO", &title, &pyList ) || !PySequence_Check( pyList )) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and a sequence" ); @@ -2070,6 +2173,11 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) int clipX = 0, clipY = 0, clipW = -1, clipH = -1; /*GLfloat scissorBox[4];*/ + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Image() in background mode." ); + } + /* parse the arguments passed-in from Python */ if( !PyArg_ParseTuple( args, "O!ff|ffiiii", &Image_Type, &pyObjImage, &originX, &originY, &zoomX, &zoomY, diff --git a/source/blender/python/api2_2x/Group.c b/source/blender/python/api2_2x/Group.c index 3e7f02c3797..3152d3a973f 100644 --- a/source/blender/python/api2_2x/Group.c +++ b/source/blender/python/api2_2x/Group.c @@ -46,6 +46,8 @@ #include "gen_utils.h" #include "gen_library.h" +#include "vector.h" + /* checks for the group being removed */ #define GROUP_DEL_CHECK_PY(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "Group has been removed" ) ) #define GROUP_DEL_CHECK_INT(bpy_group) if (!(bpy_group->group)) return ( EXPP_ReturnIntError( PyExc_RuntimeError, "Group has been removed" ) ) @@ -200,6 +202,31 @@ static int Group_setObjects( BPy_Group * self, PyObject * args ) return 0; } +static PyObject *Group_getDupliOfs( BPy_Group * self ) +{ + GROUP_DEL_CHECK_PY(self); + return newVectorObject( self->group->dupli_ofs, 3, Py_WRAP ); +} + +static int Group_setDupliOfs( BPy_Group * self, PyObject * value ) +{ + VectorObject *bpy_vec; + GROUP_DEL_CHECK_INT(self); + if (!VectorObject_Check(value)) + return ( EXPP_ReturnIntError( PyExc_TypeError, + "expected a vector" ) ); + + bpy_vec = (VectorObject *)value; + + if (bpy_vec->size != 3) + return ( EXPP_ReturnIntError( PyExc_ValueError, + "can only assign a 3D vector" ) ); + + self->group->dupli_ofs[0] = bpy_vec->vec[0]; + self->group->dupli_ofs[1] = bpy_vec->vec[1]; + self->group->dupli_ofs[2] = bpy_vec->vec[2]; + return 0; +} /*****************************************************************************/ @@ -251,6 +278,10 @@ static PyGetSetDef BPy_Group_getseters[] = { (getter)Group_getObjects, (setter)Group_setObjects, "objects in this group", NULL}, + {"dupliOffset", + (getter)Group_getDupliOfs, (setter)Group_setDupliOfs, + "offset to use when instancing this group as a DupliGroup", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; diff --git a/source/blender/python/api2_2x/Image.c b/source/blender/python/api2_2x/Image.c index 94da5a77170..5ef2cbadbdc 100644 --- a/source/blender/python/api2_2x/Image.c +++ b/source/blender/python/api2_2x/Image.c @@ -29,7 +29,6 @@ */ #include "Image.h" /*This must come first */ -#include "BDR_drawmesh.h" /* free_realtime_image */ #include "BKE_main.h" #include "BKE_global.h" #include "BKE_library.h" @@ -48,6 +47,7 @@ #include "BKE_icons.h" #include "IMB_imbuf.h" #include "IDProp.h" +#include "GPU_draw.h" /* used so we can get G.scene->r.cfra for getting the current image frame, some images change frame if they are a sequence */ @@ -1003,7 +1003,7 @@ static PyObject *Image_glFree( BPy_Image * self ) { Image *image = self->image; - free_realtime_image( image ); + GPU_free_image( image ); /* remove the nocollect flag, image is available for garbage collection again */ image->flag &= ~IMA_NOCOLLECT; Py_RETURN_NONE; diff --git a/source/blender/python/api2_2x/Ipo.c b/source/blender/python/api2_2x/Ipo.c index 68768fc9346..7c2e18bcdf6 100644 --- a/source/blender/python/api2_2x/Ipo.c +++ b/source/blender/python/api2_2x/Ipo.c @@ -36,6 +36,7 @@ #include "BKE_object.h" #include "BKE_ipo.h" #include "BLI_blenlib.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Ipocurve.c b/source/blender/python/api2_2x/Ipocurve.c index b9bfb77d19e..4a8cba30e8e 100644 --- a/source/blender/python/api2_2x/Ipocurve.c +++ b/source/blender/python/api2_2x/Ipocurve.c @@ -35,6 +35,7 @@ #include "BKE_depsgraph.h" #include "BKE_ipo.h" #include "BKE_utildefines.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Ipocurve.h b/source/blender/python/api2_2x/Ipocurve.h index 8263bf2022f..6f474d4d167 100644 --- a/source/blender/python/api2_2x/Ipocurve.h +++ b/source/blender/python/api2_2x/Ipocurve.h @@ -31,7 +31,7 @@ #define EXPP_IPOCURVE_H #include -#include "DNA_curve_types.h" /* declaration of IpoCurve */ +#include "DNA_ipo_types.h" /* declaration of IpoCurve */ /*****************************************************************************/ /* Python C_IpoCurve structure definition: */ diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 53d25a6429d..38968b64cf5 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -34,15 +34,19 @@ #include "BKE_global.h" #include "BKE_object.h" #include "BKE_library.h" +#include "BKE_texture.h" #include "BLI_blenlib.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "mydevice.h" #include "Ipo.h" +#include "MTex.h" #include "constant.h" #include "gen_utils.h" #include "gen_library.h" #include "BKE_utildefines.h" +#include "MEM_guardedalloc.h" /*****************************************************************************/ /* Python BPy_Lamp defaults: */ @@ -84,6 +88,8 @@ #define EXPP_LAMP_MODE_NODIFFUSE 2048 #define EXPP_LAMP_MODE_NOSPECULAR 4096 #define EXPP_LAMP_MODE_SHAD_RAY 8192 +#define EXPP_LAMP_MODE_LAYER_SHADOW 32768 + /* Lamp MIN, MAX values */ #define EXPP_LAMP_SAMPLES_MIN 1 @@ -204,6 +210,7 @@ static PyObject *Lamp_getQuad2( BPy_Lamp * self ); static PyObject *Lamp_getCol( BPy_Lamp * self ); static PyObject *Lamp_getIpo( BPy_Lamp * self ); static PyObject *Lamp_getComponent( BPy_Lamp * self, void * closure ); +static PyObject *Lamp_getTextures( BPy_Lamp * self ); static PyObject *Lamp_clearIpo( BPy_Lamp * self ); static PyObject *Lamp_insertIpoKey( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_oldsetIpo( BPy_Lamp * self, PyObject * args ); @@ -251,6 +258,7 @@ static int Lamp_setHaloInt( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad1( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad2( BPy_Lamp * self, PyObject * args ); static int Lamp_setCol( BPy_Lamp * self, PyObject * args ); +static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_getScriptLinks( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_addScriptLink( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ); @@ -498,6 +506,10 @@ static PyGetSetDef BPy_Lamp_getseters[] = { (getter)Lamp_getComponent, (setter)Lamp_setComponent, "Lamp color blue component", (void *)EXPP_LAMP_COMP_B}, + {"textures", + (getter)Lamp_getTextures, (setter)Lamp_setTextures, + "The Lamp's texture list as a tuple", + NULL}, {"Modes", (getter)Lamp_getModesConst, (setter)NULL, "Dictionary of values for 'mode' attribute", @@ -780,6 +792,8 @@ static PyObject *Lamp_ModesDict( void ) PyInt_FromLong( EXPP_LAMP_MODE_NOSPECULAR ) ); PyConstant_Insert( c, "RayShadow", PyInt_FromLong( EXPP_LAMP_MODE_SHAD_RAY ) ); + PyConstant_Insert( c, "LayerShadow", + PyInt_FromLong( EXPP_LAMP_MODE_LAYER_SHADOW ) ); } return Modes; @@ -1011,8 +1025,8 @@ static int Lamp_setType( BPy_Lamp * self, PyObject * value ) static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) { - short param; - static short bitmask = EXPP_LAMP_MODE_SHADOWS + int param; + static int bitmask = EXPP_LAMP_MODE_SHADOWS | EXPP_LAMP_MODE_HALO | EXPP_LAMP_MODE_LAYER | EXPP_LAMP_MODE_QUAD @@ -1022,14 +1036,15 @@ static int Lamp_setMode( BPy_Lamp * self, PyObject * value ) | EXPP_LAMP_MODE_SQUARE | EXPP_LAMP_MODE_NODIFFUSE | EXPP_LAMP_MODE_NOSPECULAR - | EXPP_LAMP_MODE_SHAD_RAY; + | EXPP_LAMP_MODE_SHAD_RAY + | EXPP_LAMP_MODE_LAYER_SHADOW; if( !PyInt_Check ( value ) ) { char errstr[128]; sprintf ( errstr , "expected int bitmask of 0x%04x", bitmask ); return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - param = (short)PyInt_AS_LONG ( value ); + param = PyInt_AS_LONG ( value ); if ( ( param & bitmask ) != param ) return EXPP_ReturnIntError( PyExc_ValueError, @@ -1373,7 +1388,8 @@ static PyObject *Lamp_getModesConst( void ) EXPP_LAMP_MODE_SQUARE, "NoDiffuse", EXPP_LAMP_MODE_NODIFFUSE, "NoSpecular", EXPP_LAMP_MODE_NOSPECULAR, "RayShadow", - EXPP_LAMP_MODE_SHAD_RAY); + EXPP_LAMP_MODE_SHAD_RAY, "LayerShadow", + EXPP_LAMP_MODE_LAYER_SHADOW); } static PyObject *Lamp_getTypesConst( void ) @@ -1387,6 +1403,100 @@ static PyObject *Lamp_getTypesConst( void ) "Photon", EXPP_LAMP_TYPE_YF_PHOTON ); } +static PyObject *Lamp_getTextures( BPy_Lamp * self ) +{ + int i; + PyObject *tuple; + + /* build a texture list */ + tuple = PyTuple_New( MAX_MTEX ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->lamp->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_LA ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } + + return tuple; +} + +static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_LA ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing lamp MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->lamp->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->lamp->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->lamp->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->lamp->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} + /* #####DEPRECATED###### */ static PyObject *Lamp_oldsetSamples( BPy_Lamp * self, PyObject * args ) @@ -1597,6 +1707,8 @@ static PyObject *Lamp_oldsetMode( BPy_Lamp * self, PyObject * args ) flag |= ( short ) EXPP_LAMP_MODE_NOSPECULAR; else if( !strcmp( name, "RayShadow" ) ) flag |= ( short ) EXPP_LAMP_MODE_SHAD_RAY; + else if( !strcmp( name, "LayerShadow" ) ) + flag |= ( short ) EXPP_LAMP_MODE_LAYER_SHADOW; else return EXPP_ReturnPyObjError( PyExc_AttributeError, "unknown lamp flag argument" ); diff --git a/source/blender/python/api2_2x/MTex.c b/source/blender/python/api2_2x/MTex.c index b9a8f7fff65..4db9715a465 100644 --- a/source/blender/python/api2_2x/MTex.c +++ b/source/blender/python/api2_2x/MTex.c @@ -22,10 +22,11 @@ * * This is a new part of Blender. * - * Contributor(s): Alex Mole, Yehoshua Sapir + * Contributor(s): Alex Mole, Yehoshua Sapir, Ken Hughes * * ***** END GPL LICENSE BLOCK ***** */ + #include "MTex.h" /*This must come first*/ #include "BKE_utildefines.h" @@ -35,7 +36,8 @@ #include "gen_utils.h" #include "gen_library.h" -#include +#include "DNA_material_types.h" +#include "DNA_world_types.h" /*****************************************************************************/ /* Python BPy_MTex methods declarations: */ @@ -94,6 +96,7 @@ MTEXGETSET(ProjX) MTEXGETSET(ProjY) MTEXGETSET(ProjZ) MTEXGETSET(MapToFlag) +MTEXGETSET(WorldMapToFlag) /*****************************************************************************/ /* Python get/set methods table */ @@ -154,8 +157,14 @@ static PyGetSetDef MTex_getseters[] = { "Projection of Y axis to Texture space", NULL }, { "zproj", (getter) MTex_getProjZ, (setter) MTex_setProjZ, "Projection of Z axis to Texture space", NULL }, + + /* MapTo for Material and Lamp MTex */ + { "mtCol", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to color", (void*) MAP_COL }, + + /* MapTo for Material MTex */ + { "mtNor", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to normals", (void*) MAP_NORM }, { "mtCsp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, @@ -182,6 +191,18 @@ static PyGetSetDef MTex_getseters[] = { "How texture maps to displacement", (void*) MAP_DISPLACE }, { "mtWarp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to warp", (void*) MAP_WARP }, + + /* MapTo for World MTex */ + + { "mtBlend", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color progression of background", (void*) WOMAP_BLEND }, + { "mtHoriz", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the horizon", (void*) WOMAP_HORIZ }, + { "mtZenUp", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the zenith above", (void*) WOMAP_ZENUP }, + { "mtZenDown", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the zenith below", (void*) WOMAP_ZENDOWN }, + { NULL, NULL, NULL, NULL, NULL } }; @@ -252,7 +273,7 @@ PyObject *MTex_Init( void ) return submodule; } -PyObject *MTex_CreatePyObject( MTex * mtex ) +PyObject *MTex_CreatePyObject( MTex * mtex, unsigned short type ) { BPy_MTex *pymtex; @@ -262,6 +283,7 @@ PyObject *MTex_CreatePyObject( MTex * mtex ) "couldn't create BPy_MTex PyObject" ); pymtex->mtex = mtex; + pymtex->type = type; return ( PyObject * ) pymtex; } @@ -286,7 +308,12 @@ static int MTex_compare( BPy_MTex * a, BPy_MTex * b ) static PyObject *MTex_repr( BPy_MTex * self ) { - return PyString_FromFormat( "[MTex]" ); + if( self->type == ID_MA ) + return PyString_FromFormat( "[MTex (Material)]" ); + else if( self->type == ID_LA ) + return PyString_FromFormat( "[MTex (Lamp)]" ); + else + return PyString_FromFormat( "[MTex (World)]" ); } @@ -316,19 +343,37 @@ static int MTex_setTexCo( BPy_MTex *self, PyObject *value, void *closure) { int texco; - if( !PyInt_Check( value ) ) { + if( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.TexCo dictionary" ); - } texco = PyInt_AsLong( value ) ; - if (texco != TEXCO_ORCO && texco != TEXCO_REFL && texco != TEXCO_NORM && - texco != TEXCO_GLOB && texco != TEXCO_UV && texco != TEXCO_OBJECT && - texco != TEXCO_STRESS && texco != TEXCO_TANGENT && texco != TEXCO_WINDOW && - texco != TEXCO_VIEW && texco != TEXCO_STICKY ) - return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be a member of Texture.TexCo dictionary" ); + switch ( self->type ) { + case ID_MA : + if( texco != TEXCO_ORCO && texco != TEXCO_REFL && + texco != TEXCO_NORM && texco != TEXCO_GLOB && + texco != TEXCO_UV && texco != TEXCO_OBJECT && + texco != TEXCO_STRESS && texco != TEXCO_TANGENT && + texco != TEXCO_WINDOW && texco != TEXCO_VIEW && + texco != TEXCO_STICKY ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + case ID_LA : + if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && + texco != TEXCO_OBJECT ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + default: /* ID_WO */ + if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && + texco != TEXCO_ANGMAP && texco != TEXCO_OBJECT && + texco != TEXCO_H_SPHEREMAP && texco != TEXCO_H_TUBEMAP ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + } self->mtex->texco = (short)texco; @@ -350,6 +395,10 @@ static int MTex_setObject( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getUVLayer( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a Material MTex object" ); + return PyString_FromString(self->mtex->uvname); } @@ -364,6 +413,10 @@ static int MTex_setUVLayer( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapTo( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a Material MTex object" ); + return PyInt_FromLong( self->mtex->mapto ); } @@ -371,18 +424,20 @@ static int MTex_setMapTo( BPy_MTex *self, PyObject *value, void *closure) { int mapto; - if( !PyInt_Check( value ) ) { + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + + if( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "expected an int" ); - } + "expected an int" ); mapto = PyInt_AsLong( value ); /* This method is deprecated anyway. */ - if ( mapto < 0 || mapto > 16383 ) { + if ( mapto < 0 || mapto > 16383 ) return EXPP_ReturnIntError( PyExc_ValueError, "Value must be a sum of values from Texture.MapTo dictionary" ); - } self->mtex->mapto = (short)mapto; @@ -400,11 +455,9 @@ static int MTex_setCol( BPy_MTex *self, PyObject *value, void *closure) float rgb[3]; int i; - if( !PyArg_ParseTuple( value, "fff", - &rgb[0], &rgb[1], &rgb[2] ) ) - + if( !PyArg_ParseTuple( value, "fff", &rgb[0], &rgb[1], &rgb[2] ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple of 3 floats" ); + "expected tuple of 3 floats" ); for( i = 0; i < 3; ++i ) if( rgb[i] < 0 || rgb[i] > 1 ) @@ -453,18 +506,13 @@ static int MTex_setBlendMode( BPy_MTex *self, PyObject *value, void *closure) if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "Value must be member of Texture.BlendModes dictionary" ); + "Value must be member of Texture.BlendModes dictionary" ); n = PyInt_AsLong(value); -/* if (n != MTEX_BLEND && n != MTEX_MUL && n != MTEX_ADD && - n != MTEX_SUB && n != MTEX_DIV && n != MTEX_DARK && - n != MTEX_DIFF && n != MTEX_LIGHT && n != MTEX_SCREEN)*/ if (n < 0 || n > 8) - { return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be member of Texture.BlendModes dictionary" ); - } + "Value must be member of Texture.BlendModes dictionary" ); self->mtex->blendtype = (short)n; @@ -478,117 +526,84 @@ static PyObject *MTex_getColFac( BPy_MTex *self, void *closure ) static int MTex_setColFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; - - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->colfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->colfac, 0.0f, 1.0f ); } static PyObject *MTex_getNorFac( BPy_MTex *self, void *closure ) { + if( self->type == ID_LA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material or world MTex object" ); + return PyFloat_FromDouble(self->mtex->norfac); } static int MTex_setNorFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; - - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 25) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,25]" ); - - self->mtex->norfac = f; - - return 0; + switch( self->type ) + { + case ID_WO: + return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 1.0f ); + case ID_MA: + return EXPP_setFloatRange( value, &self->mtex->norfac, 0.0f, 25.0f ); + default: + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material or world MTex object" ); + } } static PyObject *MTex_getVarFac( BPy_MTex *self, void *closure ) { + if( self->type == ID_LA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material or world MTex object" ); + return PyFloat_FromDouble(self->mtex->varfac); } static int MTex_setVarFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type == ID_LA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material or world MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->varfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->varfac, 0.0f, 1.0f ); } static PyObject *MTex_getDispFac( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyFloat_FromDouble(self->mtex->dispfac); } static int MTex_setDispFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->dispfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->dispfac, 0.0f, 1.0f ); } static PyObject *MTex_getWarpFac( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyFloat_FromDouble(self->mtex->warpfac); } static int MTex_setWarpFac( BPy_MTex *self, PyObject *value, void *closure) { - float f; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); - if ( !PyFloat_Check( value ) ) - return EXPP_ReturnIntError( PyExc_TypeError, - "expected a float" ); - - f = (float)PyFloat_AsDouble(value); - - if (f < 0 || f > 1) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [0,1]" ); - - self->mtex->warpfac = f; - - return 0; + return EXPP_setFloatRange( value, &self->mtex->warpfac, 0.0f, 1.0f ); } static PyObject *MTex_getOfs( BPy_MTex *self, void *closure ) @@ -601,16 +616,24 @@ static int MTex_setOfs( BPy_MTex *self, PyObject *value, void *closure) { float f[3]; int i; + float max; if( !PyArg_ParseTuple( value, "fff", &f[0], &f[1], &f[2] ) ) - return EXPP_ReturnIntError( PyExc_TypeError, "expected tuple of 3 floats" ); + if( self->type == ID_MA ) + max = 10.0f; + else + max = 20.0f; + for( i = 0; i < 3; ++i ) - if( f[i] < -10 || f[i] > 10 ) - return EXPP_ReturnIntError( PyExc_ValueError, - "values must be in range [-10,10]" ); + if( f[i] < -max || f[i] > max ) { + char errstr[64]; + sprintf( errstr, "values must be in range [-%6.0f,%6.0f]", + max, max ); + return EXPP_ReturnIntError( PyExc_ValueError, errstr ); + } self->mtex->ofs[0] = f[0]; self->mtex->ofs[1] = f[1]; @@ -649,6 +672,10 @@ static int MTex_setSize( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapping( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->mapping ); } @@ -656,6 +683,11 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) { int n; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + + if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be member of Texture.Mappings dictionary" ); @@ -664,8 +696,7 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) /* if (n != MTEX_FLAT && n != MTEX_TUBE && n != MTEX_CUBE && n != MTEX_SPHERE) */ - if (n < 0 || n > 3) - { + if (n < 0 || n > 3) { return EXPP_ReturnIntError( PyExc_ValueError, "Value must be member of Texture.Mappings dictionary" ); } @@ -677,25 +708,43 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getFlag( BPy_MTex *self, void *closure ) { - return PyBool_FromLong( self->mtex->texflag & ((int) closure) ); + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_MA && + flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "attribute only vaild for material MTex object" ); + + return PyBool_FromLong( self->mtex->texflag & flag ); } static int MTex_setFlag( BPy_MTex *self, PyObject *value, void *closure) { + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_MA && + flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute only vaild for material MTex object" ); + if ( !PyBool_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected a bool"); if ( value == Py_True ) - self->mtex->texflag |= (int)closure; + self->mtex->texflag |= flag; else - self->mtex->texflag &= ~((int) closure); + self->mtex->texflag &= ~flag; return 0; } static PyObject *MTex_getProjX( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projx ); } @@ -703,6 +752,10 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -722,6 +775,10 @@ static int MTex_setProjX( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getProjY( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projy ); } @@ -729,6 +786,10 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -748,6 +809,10 @@ static int MTex_setProjY( BPy_MTex *self, PyObject *value, void *closure ) static PyObject *MTex_getProjZ( BPy_MTex *self, void *closure ) { + if( self->type != ID_MA ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a material MTex object" ); + return PyInt_FromLong( self->mtex->projz ); } @@ -755,6 +820,10 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) { int proj; + if( self->type != ID_MA ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "not a material MTex object" ); + if( !PyInt_Check( value ) ) { return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.Proj dictionary" ); @@ -774,29 +843,45 @@ static int MTex_setProjZ( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getMapToFlag( BPy_MTex *self, void *closure ) { - int flag = (int) closure; + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type == ID_LA && flag != MAP_COL ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "attribute not available for a lamp MTex" ); if ( self->mtex->mapto & flag ) - { return PyInt_FromLong( ( self->mtex->maptoneg & flag ) ? -1 : 1 ); - } else { + else return PyInt_FromLong( 0 ); - } +} + +static PyObject *MTex_getWorldMapToFlag( BPy_MTex *self, void *closure ) +{ + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_WO ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a world MTex object" ); + + return PyInt_FromLong( (long)( (self->mtex->mapto & flag) != 0 ) ); } static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) { - int flag = (int) closure; + int flag = GET_INT_FROM_POINTER(closure); int intVal; + if( self->type == ID_LA && flag != MAP_COL ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute not available for a lamp MTex" ); + if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected an int"); - intVal = PyInt_AsLong( value ); + intVal = PyInt_AsLong( value ) ; - if (flag == MAP_COL || flag == MAP_COLSPEC || flag == MAP_COLMIR || - flag == MAP_WARP) { + if( flag & ( MAP_COL | MAP_COLSPEC | MAP_COLMIR | MAP_WARP ) ) { if (intVal < 0 || intVal > 1) { return EXPP_ReturnIntError( PyExc_ValueError, "value for that mapping must be 0 or 1" ); @@ -828,3 +913,31 @@ static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) return 0; } + +static int MTex_setWorldMapToFlag( BPy_MTex *self, PyObject *value, void *closure) +{ + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_WO ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute only available for a world MTex" ); + + if ( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected an int"); + + switch( PyInt_AsLong( value ) ) { + case 0: + self->mtex->mapto &= ~flag; + break; + case 1: + self->mtex->mapto |= flag; + break; + default: + return EXPP_ReturnIntError( PyExc_ValueError, + "value for mapping must be 0 or 1" ); + } + + return 0; +} + diff --git a/source/blender/python/api2_2x/MTex.h b/source/blender/python/api2_2x/MTex.h index 5e67ebc47ca..b6c98a40d2e 100644 --- a/source/blender/python/api2_2x/MTex.h +++ b/source/blender/python/api2_2x/MTex.h @@ -38,22 +38,26 @@ /* Python BPy_MTex structure definition */ /*****************************************************************************/ +#define MATERIAL_MTEX_TYPE 1 +#define WORLD_MTEX_TYPE 2 +#define LAMP_MTEX_TYPE 3 + typedef struct { PyObject_HEAD MTex * mtex; + unsigned short type; } BPy_MTex; extern PyTypeObject MTex_Type; #define BPy_MTex_Check(v) ((v)->ob_type == &MTex_Type) - /*****************************************************************************/ /* Module Blender.Texture.MTex - public functions */ /*****************************************************************************/ PyObject *MTex_Init( void ); -PyObject *MTex_CreatePyObject( struct MTex *obj ); +PyObject *MTex_CreatePyObject( struct MTex *obj, unsigned short type ); MTex *MTex_FromPyObject( PyObject * py_obj ); diff --git a/source/blender/python/api2_2x/Makefile b/source/blender/python/api2_2x/Makefile index 7c831952042..a2b77bf8c98 100644 --- a/source/blender/python/api2_2x/Makefile +++ b/source/blender/python/api2_2x/Makefile @@ -37,6 +37,10 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) +ifdef NAN_BUILDINFO + CPPFLAGS += -DNAN_BUILDINFO +endif + ifeq ($(WITH_FFMPEG), true) CPPFLAGS += -DWITH_FFMPEG endif @@ -45,6 +49,7 @@ ifeq ($(WITH_OPENEXR),true) CPPFLAGS += -DWITH_OPENEXR endif +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../makesdna @@ -52,6 +57,7 @@ CPPFLAGS += -I../../blenkernel CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader CPPFLAGS += -I../../include +CPPFLAGS += -I../../gpu CPPFLAGS += -I../../render/extern/include CPPFLAGS += -I../../radiosity/extern/include CPPFLAGS += -I$(NAN_BMFONT)/include diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 20747a167e6..b118bdb30e7 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -37,11 +37,13 @@ #include "BKE_library.h" #include "BKE_material.h" #include "BKE_texture.h" +#include "BKE_node.h" #include "BKE_idprop.h" #include "BKE_utildefines.h" /* for CLAMP */ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "constant.h" @@ -154,6 +156,8 @@ #define EXPP_MAT_SPECTRANS_MAX 1.0 #define EXPP_MAT_MIRRTRANSADD_MIN 0.0 #define EXPP_MAT_MIRRTRANSADD_MAX 1.0 +#define EXPP_MAT_COLORBAND_FACTOR_MIN 0.0 +#define EXPP_MAT_COLORBAND_FACTOR_MAX 1.0 /* closure values for getColorComponent()/setColorComponent() */ @@ -402,19 +406,62 @@ static PyObject *Material_ShadersDict( void ) return Shaders; } +static PyObject *Material_ColorRampMethodsDict( void ) +{ + PyObject *Methods = PyConstant_New( ); + if( Methods ) { + BPy_constant *c = (BPy_constant * ) Methods; + + PyConstant_Insert(c, "BLEND", PyInt_FromLong(MA_RAMP_BLEND)); + PyConstant_Insert(c, "MIX", PyInt_FromLong(MA_RAMP_BLEND)); /* This one is added to solve confusion between Blend-Mix name. */ + PyConstant_Insert(c, "ADD", PyInt_FromLong(MA_RAMP_ADD)); + PyConstant_Insert(c, "MULT", PyInt_FromLong(MA_RAMP_MULT)); + PyConstant_Insert(c, "SUB", PyInt_FromLong(MA_RAMP_SUB)); + PyConstant_Insert(c, "SCREEN", PyInt_FromLong(MA_RAMP_SCREEN)); + PyConstant_Insert(c, "DIV", PyInt_FromLong(MA_RAMP_DIV)); + PyConstant_Insert(c, "DIFF", PyInt_FromLong(MA_RAMP_DIFF)); + PyConstant_Insert(c, "DARK", PyInt_FromLong(MA_RAMP_DARK)); + PyConstant_Insert(c, "LIGHT", PyInt_FromLong(MA_RAMP_LIGHT)); + PyConstant_Insert(c, "OVERLAY", PyInt_FromLong(MA_RAMP_OVERLAY)); + PyConstant_Insert(c, "DODGE", PyInt_FromLong(MA_RAMP_DODGE)); + PyConstant_Insert(c, "BURN", PyInt_FromLong(MA_RAMP_BURN)); + PyConstant_Insert(c, "HUE", PyInt_FromLong(MA_RAMP_HUE)); + PyConstant_Insert(c, "SAT", PyInt_FromLong(MA_RAMP_SAT)); + PyConstant_Insert(c, "VAL", PyInt_FromLong(MA_RAMP_VAL)); + PyConstant_Insert(c, "COLOR", PyInt_FromLong(MA_RAMP_COLOR)); + + } + return Methods; +} + +static PyObject *Material_ColorRampInputDict( void ) +{ + PyObject *Inputs = PyConstant_New( ); + if( Inputs ) { + BPy_constant *c = (BPy_constant * ) Inputs; + + PyConstant_Insert(c, "SHADER", PyInt_FromLong(MA_RAMP_IN_SHADER)); + PyConstant_Insert(c, "ENERGY", PyInt_FromLong(MA_RAMP_IN_ENERGY)); + PyConstant_Insert(c, "NORMAL", PyInt_FromLong(MA_RAMP_IN_NOR)); + PyConstant_Insert(c, "RESULT", PyInt_FromLong(MA_RAMP_IN_RESULT)); + } + return Inputs; +} /*****************************************************************************/ /* Function: Material_Init */ /*****************************************************************************/ PyObject *Material_Init( void ) { - PyObject *submodule, *Modes, *Shaders; + PyObject *submodule, *Modes, *Shaders, *ColorbandInput, *ColorbandMethod; if( PyType_Ready( &Material_Type ) < 0) return NULL; Modes = Material_ModesDict( ); Shaders = Material_ShadersDict( ); + ColorbandMethod = Material_ColorRampMethodsDict( ); + ColorbandInput = Material_ColorRampInputDict( ); submodule = Py_InitModule3( "Blender.Material", M_Material_methods, M_Material_doc ); @@ -423,6 +470,10 @@ PyObject *Material_Init( void ) PyModule_AddObject( submodule, "Modes", Modes ); if( Shaders ) PyModule_AddObject( submodule, "Shaders", Shaders ); + if( ColorbandMethod ) + PyModule_AddObject( submodule, "ColorbandMethod", ColorbandMethod ); + if( ColorbandInput ) + PyModule_AddObject( submodule, "ColorbandInput", ColorbandInput ); PyModule_AddIntConstant( submodule, "RGB", IPOKEY_RGB ); PyModule_AddIntConstant( submodule, "ALPHA", IPOKEY_ALPHA ); @@ -555,6 +606,7 @@ static int Material_setSssFront( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setSssBack( BPy_Material * self, PyObject * value ); static int Material_setTexChannel( BPy_Material * self, PyObject * value ); +static int Material_setTextures( BPy_Material * self, PyObject * value ); static PyObject *Material_getColorComponent( BPy_Material * self, void * closure ); @@ -648,6 +700,21 @@ static PyObject *Material_insertIpoKey( BPy_Material * self, PyObject * args ); static PyObject *Material_getColorband( BPy_Material * self, void * type); int Material_setColorband( BPy_Material * self, PyObject * value, void * type); static PyObject *Material_copy( BPy_Material * self ); +static PyObject *Material_freeNodes( BPy_Material * self ); + +static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ); +static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ); +static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ); +static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ); +static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value); +static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value); +static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ); +static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value); +static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value); + /*****************************************************************************/ @@ -886,6 +953,8 @@ static PyMethodDef BPy_Material_methods[] = { "() - Return a copy of the material."}, {"copy", ( PyCFunction ) Material_copy, METH_NOARGS, "() - Return a copy of the material."}, + {"freeNodes", ( PyCFunction ) Material_freeNodes, METH_NOARGS, + "() - Free this materials nodes."}, {NULL, NULL, 0, NULL} }; @@ -1168,7 +1237,35 @@ static PyGetSetDef BPy_Material_getseters[] = { (getter)Material_getColorband, (setter)Material_setColorband, "The specular colorband for this material", (void *) 1}, - + {"textures", + (getter)Material_getTextures, (setter)Material_setTextures, + "The Material's texture list as a tuple", + NULL}, + {"colorbandSpecularFactor", + (getter)Material_getColorbandSpecularFactor, (setter)Material_setColorbandSpecularFactor, + "The specular colorband factor for this material", + NULL}, + {"colorbandSpecularMethod", + (getter)Material_getColorbandSpecularMethod, (setter)Material_setColorbandSpecularMethod, + "The specular colorband method for this material", + NULL}, + {"colorbandSpecularInput", + (getter)Material_getColorbandSpecularInput, (setter)Material_setColorbandSpecularInput, + "The specular colorband input for this material", + NULL}, + {"colorbandDiffuseFactor", + (getter)Material_getColorbandDiffuseFactor, (setter)Material_setColorbandDiffuseFactor, + "The diffuse colorband factor for this material", + NULL}, + {"colorbandDiffuseMethod", + (getter)Material_getColorbandDiffuseMethod, (setter)Material_setColorbandDiffuseMethod, + "The diffuse colorband method for this material", + NULL}, + {"colorbandDiffuseInput", + (getter)Material_getColorbandDiffuseInput, (setter)Material_setColorbandDiffuseInput, + "The diffuse colorband input for this material", + NULL}, + /* SSS settings */ {"enableSSS", (getter)Material_getSssEnable, (setter)Material_setSssEnable, @@ -1737,28 +1834,23 @@ static PyObject* Material_getSssBack( BPy_Material * self ) static PyObject *Material_getTextures( BPy_Material * self ) { int i; - struct MTex *mtex; - PyObject *t[MAX_MTEX]; PyObject *tuple; /* build a texture list */ - for( i = 0; i < MAX_MTEX; ++i ) { - mtex = self->material->mtex[i]; - - if( mtex ) { - t[i] = MTex_CreatePyObject( mtex ); - } else { - Py_INCREF( Py_None ); - t[i] = Py_None; - } - } - - /* turn the array into a tuple */ - tuple = Py_BuildValue( "NNNNNNNNNN", t[0], t[1], t[2], t[3], - t[4], t[5], t[6], t[7], t[8], t[9] ); + tuple = PyTuple_New( MAX_MTEX ); if( !tuple ) return EXPP_ReturnPyObjError( PyExc_MemoryError, - "Material_getTextures: couldn't create PyTuple" ); + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->material->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_MA ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } return tuple; } @@ -2433,14 +2525,86 @@ static PyObject *Material_setTexture( BPy_Material * self, PyObject * args ) Py_RETURN_NONE; } +static int Material_setTextures( BPy_Material * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_MA ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing material MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->material->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->material->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->material->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->material->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} + static PyObject *Material_clearTexture( BPy_Material * self, PyObject * value ) { int texnum = (int)PyInt_AsLong(value); struct MTex *mtex; /* non ints will be -1 */ - if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected int in [0,9]" ); + if( ( texnum < 0 ) || ( texnum >= MAX_MTEX ) ) { + char errstr[64]; + sprintf( errstr, "expected int in [0,%d]", MAX_MTEX ); + return EXPP_ReturnPyObjError( PyExc_TypeError, errstr ); + } mtex = self->material->mtex[texnum]; if( mtex ) { @@ -2519,6 +2683,22 @@ static PyObject *Material_copy( BPy_Material * self ) return ( PyObject * ) pymat; } +/* mat.freeNodes() */ +static PyObject *Material_freeNodes( BPy_Material * self ) +{ + if (self->material->nodetree) { + if(self->material->nodetree) { + ntreeFreeTree(self->material->nodetree); + MEM_freeN(self->material->nodetree); + } + self->material->nodetree = NULL; + self->material->use_nodes = 0; + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + /* mat_a==mat_b or mat_a!=mat_b*/ static int Material_compare( BPy_Material * a, BPy_Material * b ) { @@ -3221,3 +3401,75 @@ static PyObject *Material_clearIpo( BPy_Material * self ) return EXPP_incr_ret_False(); /* no ipo found */ } +/* RampCol Factor */ + +static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ) +{ + return PyFloat_FromDouble( (double) self->material->rampfac_col); +} + +static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ) +{ + return PyFloat_FromDouble( (double) self->material->rampfac_spec); +} + +static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ) +{ + return EXPP_setFloatClamped(value, &self->material->rampfac_col, + EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); +} + +static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ) +{ + return EXPP_setFloatClamped(value, &self->material->rampfac_spec, + EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); +} + +/* RampCol Method */ + +static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampblend_col); +} + +static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampblend_spec); +} + +static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampblend_col, + MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); +} + +static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampblend_spec, + MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); +} + +/* RampCol Input */ + +static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampin_col); +} + +static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampin_spec); +} + +static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampin_col, + MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); +} + +static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampin_spec, + MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); +} + diff --git a/source/blender/python/api2_2x/Mathutils.c b/source/blender/python/api2_2x/Mathutils.c index 217e096060f..f0b51285376 100644 --- a/source/blender/python/api2_2x/Mathutils.c +++ b/source/blender/python/api2_2x/Mathutils.c @@ -108,7 +108,7 @@ struct PyMethodDef M_Mathutils_methods[] = { }; /*----------------------------MODULE INIT-------------------------*/ /* from can be Blender.Mathutils or GameLogic.Mathutils for the BGE */ -PyObject *Mathutils_Init(char *from) +PyObject *Mathutils_Init(const char *from) { PyObject *submodule; diff --git a/source/blender/python/api2_2x/Mathutils.h b/source/blender/python/api2_2x/Mathutils.h index 76d53cb6c4c..0db83216178 100644 --- a/source/blender/python/api2_2x/Mathutils.h +++ b/source/blender/python/api2_2x/Mathutils.h @@ -38,7 +38,7 @@ #include "euler.h" #include "point.h" -PyObject *Mathutils_Init( char * from ); +PyObject *Mathutils_Init( const char * from ); PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); PyObject *column_vector_multiplication(MatrixObject * mat, VectorObject* vec); PyObject *row_point_multiplication(PointObject* pt, MatrixObject * mat); diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c index b3e8fefdb7b..6471fb16e92 100644 --- a/source/blender/python/api2_2x/Mesh.c +++ b/source/blender/python/api2_2x/Mesh.c @@ -4163,6 +4163,7 @@ static int MFace_setMode( BPy_MFace *self, PyObject *value ) { int param; static short bitmask = TF_DYNAMIC + | TF_ALPHASORT | TF_TEX | TF_SHAREDVERT | TF_LIGHT @@ -8696,11 +8697,11 @@ static PyObject *M_Mesh_FaceModesDict( void ) if( FM ) { BPy_constant *d = ( BPy_constant * ) FM; - PyConstant_Insert( d, "BILLBOARD", - PyInt_FromLong( TF_BILLBOARD2 ) ); + PyConstant_Insert( d, "BILLBOARD", PyInt_FromLong( TF_BILLBOARD2 ) ); PyConstant_Insert( d, "ALL", PyInt_FromLong( 0xffff ) ); PyConstant_Insert( d, "HALO", PyInt_FromLong( TF_BILLBOARD ) ); PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( TF_DYNAMIC ) ); + PyConstant_Insert( d, "ALPHASORT", PyInt_FromLong( TF_ALPHASORT ) ); PyConstant_Insert( d, "INVISIBLE", PyInt_FromLong( TF_INVISIBLE ) ); PyConstant_Insert( d, "LIGHT", PyInt_FromLong( TF_LIGHT ) ); PyConstant_Insert( d, "OBCOL", PyInt_FromLong( TF_OBCOL ) ); diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c index 9775bce2235..3bef0eead09 100644 --- a/source/blender/python/api2_2x/Modifier.c +++ b/source/blender/python/api2_2x/Modifier.c @@ -83,7 +83,12 @@ enum mod_constants { EXPP_MOD_UV, /*ARMATURE SPECIFIC*/ + EXPP_MOD_VGROUPS, EXPP_MOD_ENVELOPES, + EXPP_MOD_QUATERNION, + EXPP_MOD_B_BONE_REST, + EXPP_MOD_INVERT_VERTGROUP, + EXPP_MOD_MULTIMODIFIER, /*ARRAY SPECIFIC*/ EXPP_MOD_OBJECT_OFFSET, @@ -376,12 +381,23 @@ static PyObject *armature_getter( BPy_Modifier * self, int type ) case EXPP_MOD_OBJECT: return Object_CreatePyObject( md->object ); case EXPP_MOD_VERTGROUP: - return PyBool_FromLong( ( long )( md->deformflag & 1 ) ) ; + return PyString_FromString( md->defgrp_name ) ; + case EXPP_MOD_VGROUPS: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_VGROUP, 'h' ); case EXPP_MOD_ENVELOPES: - return PyBool_FromLong( ( long )( md->deformflag & 2 ) ) ; + return EXPP_getBitfield( &md->deformflag, ARM_DEF_ENVELOPE, 'h' ); + case EXPP_MOD_QUATERNION: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_QUATERNION, 'h' ); + case EXPP_MOD_B_BONE_REST: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_B_BONE_REST, 'h' ); + case EXPP_MOD_INVERT_VERTGROUP: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_INVERT_VGROUP, 'h' ); + case EXPP_MOD_MULTIMODIFIER: + return EXPP_getBitfield( &md->multi, 1, 'h' ); default: return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); } + return 0; } static int armature_setter( BPy_Modifier *self, int type, PyObject *value ) @@ -391,13 +407,30 @@ static int armature_setter( BPy_Modifier *self, int type, PyObject *value ) switch( type ) { case EXPP_MOD_OBJECT: return GenericLib_assignData(value, (void **) &md->object, 0, 0, ID_OB, OB_ARMATURE); - case EXPP_MOD_VERTGROUP: - return EXPP_setBitfield( value, &md->deformflag, 1, 'h' ); + case EXPP_MOD_VERTGROUP: { + char *defgrp_name = PyString_AsString( value ); + if( !defgrp_name ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected string arg" ); + BLI_strncpy( md->defgrp_name, defgrp_name, sizeof( md->defgrp_name ) ); + break; + } + case EXPP_MOD_VGROUPS: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_VGROUP, 'h' ); case EXPP_MOD_ENVELOPES: - return EXPP_setBitfield( value, &md->deformflag, 2, 'h' ); + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_ENVELOPE, 'h' ); + case EXPP_MOD_QUATERNION: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_QUATERNION, 'h' ); + case EXPP_MOD_B_BONE_REST: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_B_BONE_REST, 'h' ); + case EXPP_MOD_INVERT_VERTGROUP: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_INVERT_VGROUP, 'h' ); + case EXPP_MOD_MULTIMODIFIER: + return EXPP_setBitfield( value, &md->multi, 1, 'h' ); default: return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); } + return 0; } static PyObject *lattice_getter( BPy_Modifier * self, int type ) @@ -1595,8 +1628,18 @@ for var in st.replace(',','').split('\n'): PyInt_FromLong( EXPP_MOD_OPTIMAL ) ); PyConstant_Insert( d, "UV", PyInt_FromLong( EXPP_MOD_UV ) ); + PyConstant_Insert( d, "VGROUPS", + PyInt_FromLong( EXPP_MOD_VGROUPS ) ); PyConstant_Insert( d, "ENVELOPES", PyInt_FromLong( EXPP_MOD_ENVELOPES ) ); + PyConstant_Insert( d, "QUATERNION", + PyInt_FromLong( EXPP_MOD_QUATERNION ) ); + PyConstant_Insert( d, "B_BONE_REST", + PyInt_FromLong( EXPP_MOD_B_BONE_REST ) ); + PyConstant_Insert( d, "INVERT_VERTGROUP", + PyInt_FromLong( EXPP_MOD_INVERT_VERTGROUP ) ); + PyConstant_Insert( d, "MULTIMODIFIER", + PyInt_FromLong( EXPP_MOD_MULTIMODIFIER ) ); PyConstant_Insert( d, "OBJECT_OFFSET", PyInt_FromLong( EXPP_MOD_OBJECT_OFFSET ) ); PyConstant_Insert( d, "OBJECT_CURVE", diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index dc70921492c..0d5af06377c 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -81,6 +81,7 @@ struct rctf; #include "BIF_editarmature.h" #include "BIF_editaction.h" #include "BIF_editnla.h" +#include "BIF_keyframing.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -2734,7 +2735,7 @@ static PyObject *Object_setConstraintInfluenceForBone( BPy_Object * self, "expects bonename, constraintname, influenceval" ); icu = verify_ipocurve((ID *)self->object, ID_CO, boneName, constName, NULL, - CO_ENFORCE); + CO_ENFORCE, 1); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, @@ -3518,8 +3519,8 @@ static int Object_setRBMass( BPy_Object * self, PyObject * args ) /* this is too low level, possible to add helper methods */ -#define GAMEFLAG_MASK ( OB_DYNAMIC | OB_CHILD | OB_ACTOR | OB_DO_FH | \ - OB_ROT_FH | OB_ANISOTROPIC_FRICTION | OB_GHOST | OB_RIGID_BODY | \ +#define GAMEFLAG_MASK ( OB_COLLISION | OB_DYNAMIC | OB_CHILD | OB_ACTOR | OB_DO_FH | \ + OB_ROT_FH | OB_ANISOTROPIC_FRICTION | OB_GHOST | OB_RIGID_BODY | OB_SOFT_BODY | \ OB_BOUNDS | OB_COLLISION_RESPONSE | OB_SECTOR | OB_PROP | \ OB_MAINACTOR ) @@ -5496,6 +5497,7 @@ static PyObject *M_Object_RBFlagsDict( void ) if( M ) { BPy_constant *d = ( BPy_constant * ) M; + PyConstant_Insert( d, "COLLISION", PyInt_FromLong( OB_COLLISION ) ); PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( OB_DYNAMIC ) ); PyConstant_Insert( d, "CHILD", PyInt_FromLong( OB_CHILD ) ); PyConstant_Insert( d, "ACTOR", PyInt_FromLong( OB_ACTOR ) ); @@ -5505,6 +5507,7 @@ static PyObject *M_Object_RBFlagsDict( void ) PyInt_FromLong( OB_ANISOTROPIC_FRICTION ) ); PyConstant_Insert( d, "GHOST", PyInt_FromLong( OB_GHOST ) ); PyConstant_Insert( d, "RIGIDBODY", PyInt_FromLong( OB_RIGID_BODY ) ); + PyConstant_Insert( d, "SOFTBODY", PyInt_FromLong( OB_SOFT_BODY ) ); PyConstant_Insert( d, "BOUNDS", PyInt_FromLong( OB_BOUNDS ) ); PyConstant_Insert( d, "COLLISION_RESPONSE", PyInt_FromLong( OB_COLLISION_RESPONSE ) ); diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index bc65426e16c..893ee077d67 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -526,15 +526,18 @@ throws NameError if name not found PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) { +#if 1 + return EXPP_ReturnPyObjError( PyExc_NotImplementedError, + "Particle.Get() not implemented" ); +#else ParticleSettings *psys_iter; char *name = NULL; -#if 0 ParticleSystem *blparticlesys = 0; Object *ob; PyObject *partsyslist,*current; -#endif + if( !PyArg_ParseTuple( args, "|s", &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected string argument" ); @@ -577,7 +580,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } while( psys_iter ){ -#if 0 pyobj = ParticleSystem_CreatePyObject( psys_iter); if( !pyobj){ Py_DECREF( pylist ); @@ -586,7 +588,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) "could not create ParticleSystem PyObject"); } PyList_SET_ITEM( pylist, index, pyobj); -#endif printf("name is %s\n", psys_iter->id.name+2); psys_iter = psys_iter->id.next; index++; @@ -596,10 +597,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } - - -#if 0 - for( ob = G.main->particlesystem.first; ob; ob = ob->id.next ) if( !strcmp( name, ob->id.name + 2 ) ) break; @@ -626,7 +623,6 @@ PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) } return partsyslist; - #endif } diff --git a/source/blender/python/api2_2x/Pose.c b/source/blender/python/api2_2x/Pose.c index 1021eac5fc4..52ede1cb3ee 100644 --- a/source/blender/python/api2_2x/Pose.c +++ b/source/blender/python/api2_2x/Pose.c @@ -43,6 +43,7 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" //1 - this order #include "BSE_editipo.h" //2 +#include "BIF_keyframing.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "Mathutils.h" diff --git a/source/blender/python/api2_2x/Text.c b/source/blender/python/api2_2x/Text.c index 308ad094c7b..9719daaa3d4 100644 --- a/source/blender/python/api2_2x/Text.c +++ b/source/blender/python/api2_2x/Text.c @@ -34,9 +34,13 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BIF_drawtext.h" +#include "BIF_screen.h" #include "BKE_text.h" +#include "BKE_suggestions.h" #include "BLI_blenlib.h" +#include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "MEM_guardedalloc.h" #include "gen_utils.h" #include "gen_library.h" #include "../BPY_extern.h" @@ -90,9 +94,20 @@ struct PyMethodDef M_Text_methods[] = { static PyObject *Text_getFilename( BPy_Text * self ); static PyObject *Text_getNLines( BPy_Text * self ); static PyObject *Text_clear( BPy_Text * self ); +static PyObject *Text_reset( BPy_Text * self ); +static PyObject *Text_readline( BPy_Text * self ); static PyObject *Text_write( BPy_Text * self, PyObject * value ); +static PyObject *Text_insert( BPy_Text * self, PyObject * value ); +static PyObject *Text_delete( BPy_Text * self, PyObject * value ); static PyObject *Text_set( BPy_Text * self, PyObject * args ); -static PyObject *Text_asLines( BPy_Text * self ); +static PyObject *Text_asLines( BPy_Text * self, PyObject * args ); +static PyObject *Text_getCursorPos( BPy_Text * self ); +static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ); +static PyObject *Text_getSelectPos( BPy_Text * self ); +static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args ); +static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ); +static PyObject *Text_suggest( BPy_Text * self, PyObject * args ); +static PyObject *Text_showDocs( BPy_Text * self, PyObject * args ); /*****************************************************************************/ /* Python BPy_Text methods table: */ @@ -109,12 +124,34 @@ static PyMethodDef BPy_Text_methods[] = { "(str) - Change Text Object name"}, {"clear", ( PyCFunction ) Text_clear, METH_NOARGS, "() - Clear Text buffer"}, + {"reset", ( PyCFunction ) Text_reset, METH_NOARGS, + "() - Moves the IO pointer back to the start of the Text buffer for reading"}, + {"readline", ( PyCFunction ) Text_readline, METH_NOARGS, + "() - Reads a line of text from the buffer and returns it incrementing the internal IO pointer."}, {"write", ( PyCFunction ) Text_write, METH_O, "(line) - Append string 'str' to Text buffer"}, + {"insert", ( PyCFunction ) Text_insert, METH_O, + "(line) - Insert string 'str' to Text buffer at cursor location"}, + {"delete", ( PyCFunction ) Text_delete, METH_O, + "(chars) - Deletes a number of characters to the left (chars<0) or right (chars>0)"}, {"set", ( PyCFunction ) Text_set, METH_VARARGS, "(name, val) - Set attribute 'name' to value 'val'"}, - {"asLines", ( PyCFunction ) Text_asLines, METH_NOARGS, - "() - Return text buffer as a list of lines"}, + {"asLines", ( PyCFunction ) Text_asLines, METH_VARARGS, + "(start=0, end=nlines) - Return text buffer as a list of lines between start and end"}, + {"getCursorPos", ( PyCFunction ) Text_getCursorPos, METH_NOARGS, + "() - Return cursor position as (row, col) tuple"}, + {"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS, + "(row, col) - Set the cursor position to (row, col)"}, + {"getSelectPos", ( PyCFunction ) Text_getSelectPos, METH_NOARGS, + "() - Return the selection cursor position as (row, col) tuple"}, + {"setSelectPos", ( PyCFunction ) Text_setSelectPos, METH_VARARGS, + "(row, col) - Set the selection cursor position to (row, col)"}, + {"markSelection", ( PyCFunction ) Text_markSelection, METH_VARARGS, + "(group, (r, g, b), flags) - Places a marker over the current selection. Group: number > 0, flags: TMARK_TEMP, TMARK_EDITALL, etc."}, + {"suggest", ( PyCFunction ) Text_suggest, METH_VARARGS, + "(list, prefix='') - Presents a list of suggestions. List is of strings, or tuples. Tuples must be of the form (name, type) where type is one of 'm', 'v', 'f', 'k' for module, variable, function and keyword respectively or '?' for other types"}, + {"showDocs", ( PyCFunction ) Text_showDocs, METH_VARARGS, + "(docs) - Documentation string"}, {NULL, NULL, 0, NULL} }; @@ -302,7 +339,7 @@ static PyObject *M_Text_unlink( PyObject * self, PyObject * args ) /*****************************************************************************/ PyObject *Text_Init( void ) { - PyObject *submodule; + PyObject *submodule, *dict; if( PyType_Ready( &Text_Type ) < 0 ) return NULL; @@ -310,6 +347,19 @@ PyObject *Text_Init( void ) submodule = Py_InitModule3( "Blender.Text", M_Text_methods, M_Text_doc ); + dict = PyModule_GetDict( submodule ); + +#define EXPP_ADDCONST(x) \ + EXPP_dict_set_item_str(dict, #x, PyInt_FromLong(x)) + + /* So, for example: + * EXPP_ADDCONST(LEFTMOUSE) becomes + * EXPP_dict_set_item_str(dict, "LEFTMOUSE", PyInt_FromLong(LEFTMOUSE)) + */ + + EXPP_ADDCONST( TMARK_TEMP ); + EXPP_ADDCONST( TMARK_EDITALL ); + return ( submodule ); } @@ -327,6 +377,8 @@ PyObject *Text_CreatePyObject( Text * txt ) "couldn't create BPy_Text PyObject" ); pytxt->text = txt; + pytxt->iol = NULL; + pytxt->ioc = -1; return ( PyObject * ) pytxt; } @@ -376,25 +428,49 @@ static PyObject *Text_clear( BPy_Text * self) Py_RETURN_NONE; } -static PyObject *Text_set( BPy_Text * self, PyObject * args ) +static PyObject *Text_reset( BPy_Text * self ) { - int ival; - char *attr; - - if( !PyArg_ParseTuple( args, "si", &attr, &ival ) ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expected a string and an int as arguments" ); - - if( strcmp( "follow_cursor", attr ) == 0 ) { - if( ival ) - self->text->flags |= EXPP_TEXT_MODE_FOLLOW; - else - self->text->flags &= EXPP_TEXT_MODE_FOLLOW; - } + self->iol = NULL; + self->ioc = -1; Py_RETURN_NONE; } +static PyObject *Text_readline( BPy_Text * self ) +{ + PyObject *tmpstr; + + if( !self->text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + /* Reset */ + if (!self->iol && self->ioc == -1) { + self->iol = self->text->lines.first; + self->ioc = 0; + } + + if (!self->iol) { + PyErr_SetString( PyExc_StopIteration, "End of buffer reached" ); + return PyString_FromString( "" ); + } + + if (self->ioc > self->iol->len) { + self->iol = NULL; + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Line length exceeded, text may have changed while reading" ); + } + + tmpstr = PyString_FromString( self->iol->line + self->ioc ); + if (self->iol->next) + PyString_ConcatAndDel( &tmpstr, PyString_FromString("\n") ); + + self->iol = self->iol->next; + self->ioc = 0; + + return tmpstr; +} + static PyObject *Text_write( BPy_Text * self, PyObject * value ) { char *str = PyString_AsString(value); @@ -413,35 +489,324 @@ static PyObject *Text_write( BPy_Text * self, PyObject * value ) txt_move_eof( self->text, 0 ); txt_set_undostate( oldstate ); + Text_reset( self ); + Py_RETURN_NONE; } -static PyObject *Text_asLines( BPy_Text * self ) +static PyObject *Text_insert( BPy_Text * self, PyObject * value ) { - TextLine *line; - PyObject *list, *tmpstr; + char *str = PyString_AsString(value); + int oldstate; if( !self->text ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); + if( !str ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected string argument" ); + + oldstate = txt_get_undostate( ); + txt_insert_buf( self->text, str ); + txt_set_undostate( oldstate ); + + Text_reset( self ); + + Py_RETURN_NONE; +} + +static PyObject *Text_delete( BPy_Text * self, PyObject * value ) +{ + int num = PyInt_AsLong(value); + int oldstate; + + if( !self->text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + if( !num ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected non-zero int argument" ); + + oldstate = txt_get_undostate( ); + while (num<0) { + txt_backspace_char(self->text); + num++; + } + while (num>0) { + txt_delete_char(self->text); + num--; + } + txt_set_undostate( oldstate ); + + Text_reset( self ); + + Py_RETURN_NONE; +} + +static PyObject *Text_set( BPy_Text * self, PyObject * args ) +{ + int ival; + char *attr; + + if( !PyArg_ParseTuple( args, "si", &attr, &ival ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a string and an int as arguments" ); + + if( strcmp( "follow_cursor", attr ) == 0 ) { + if( ival ) + self->text->flags |= EXPP_TEXT_MODE_FOLLOW; + else + self->text->flags &= EXPP_TEXT_MODE_FOLLOW; + } + + Py_RETURN_NONE; +} + +static PyObject *Text_asLines( BPy_Text * self, PyObject * args ) +{ + TextLine *line; + PyObject *list, *tmpstr; + int start=0, end=-1, i; + + if( !self->text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + if( !PyArg_ParseTuple( args, "|ii", &start, &end ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected upto two optional ints as arguments" ); + + if (start<0) + start=0; + line = self->text->lines.first; + for (i = 0; i < start && line->next; i++) + line= line->next; + list = PyList_New( 0 ); if( !list ) return EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyList" ); - while( line ) { + while( line && (i < end || end == -1) ) { tmpstr = PyString_FromString( line->line ); PyList_Append( list, tmpstr ); Py_DECREF(tmpstr); line = line->next; + i++; } return list; } +static PyObject *Text_getCursorPos( BPy_Text * self ) +{ + Text *text; + TextLine *linep; + int row, col; + + text = self->text; + if( !text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + for (row=0,linep=text->lines.first; linep!=text->curl; linep=linep->next) + row++; + col= text->curc; + + return Py_BuildValue( "ii", row, col ); +} + +static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args ) +{ + int row, col; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "ii", &row, &col)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected two ints as arguments."); + if (row<0) row=0; + if (col<0) col=0; + + txt_move_to(self->text, row, col, 0); + + if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) + pop_space_text(st); + + Py_RETURN_NONE; +} + +static PyObject *Text_getSelectPos( BPy_Text * self ) +{ + Text *text; + TextLine *linep; + int row, col; + + text = self->text; + if( !text ) + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object" ); + + for (row=0,linep=text->lines.first; linep!=text->sell; linep=linep->next) + row++; + col= text->selc; + + return Py_BuildValue( "ii", row, col ); +} + +static PyObject *Text_setSelectPos( BPy_Text * self, PyObject * args ) +{ + int row, col; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "ii", &row, &col)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected two ints as arguments."); + if (row<0) row=0; + if (col<0) col=0; + + txt_move_to(self->text, row, col, 1); + + if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first)) + pop_space_text(st); + + Py_RETURN_NONE; +} + +static PyObject *Text_markSelection( BPy_Text * self, PyObject * args ) +{ + int group = 0, flags = 0,r, g, b; + Text *text; + char color[4]; + + text = self->text; + if (!text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "i(iii)i", &group, &r, &g, &b, &flags)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected int, 3-tuple of ints and int as arguments."); + + if (text->curl != text->sell) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Cannot mark multi-line selection."); + + color[0] = (char) (r&0xFF); + color[1] = (char) (g&0xFF); + color[2] = (char) (b&0xFF); + color[3] = 255; + + group &= 0xFFFF; + + txt_add_marker(text, text->curl, text->curc, text->selc, color, group, flags); + + Py_RETURN_NONE; +} + +static PyObject *Text_suggest( BPy_Text * self, PyObject * args ) +{ + PyObject *item = NULL, *tup1 = NULL, *tup2 = NULL; + PyObject *list = NULL; + int list_len, i; + char *prefix = NULL, *name, type; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + /* Parse args for a list of strings/tuples */ + if (!PyArg_ParseTuple(args, "O!|s", &PyList_Type, &list, &prefix)) + return EXPP_ReturnPyObjError(PyExc_TypeError, + "expected list of strings or tuples followed by an optional string"); + + if (curarea->spacetype != SPACE_TEXT) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active space type is not text"); + + st = curarea->spacedata.first; + if (!st || !st->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active text area has no Text object"); + + texttool_suggest_clear(); + texttool_text_set_active(st->text); + list_len = PyList_Size(list); + + for (i = 0; i < list_len; i++) { + item = PyList_GetItem(list, i); + + if (PyString_Check(item)) { + name = PyString_AsString(item); + type = '?'; + } else if (PyTuple_Check(item) && PyTuple_GET_SIZE(item) == 2) { + tup1 = PyTuple_GetItem(item, 0); + tup2 = PyTuple_GetItem(item, 1); + if (PyString_Check(tup1) && PyString_Check(tup2)) { + name = PyString_AsString(tup1); + type = PyString_AsString(tup2)[0]; + } else + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "list must contain tuples of two strings only: (name, type)" ); + } else + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "list must contain only individual strings or tuples of size 2" ); + + if (!strlen(name) || (type!='m' && type!='v' && type!='f' && type!='k' && type!='?')) + return EXPP_ReturnPyObjError(PyExc_AttributeError, + "names must be non-empty and types in ['m', 'v', 'f', 'k', '?']" ); + + texttool_suggest_add(name, type); + } + if (!prefix) + prefix = ""; + texttool_suggest_prefix(prefix); + scrarea_queue_redraw(curarea); + + Py_RETURN_NONE; +} + +static PyObject *Text_showDocs( BPy_Text * self, PyObject * args ) +{ + char *docs; + SpaceText *st; + + if (!self->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "This object isn't linked to a Blender Text Object"); + + if (!PyArg_ParseTuple(args, "s", &docs)) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a string as argument" ); + + if (curarea->spacetype != SPACE_TEXT) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active space type is not text"); + + st = curarea->spacedata.first; + if (!st || !st->text) + return EXPP_ReturnPyObjError(PyExc_RuntimeError, + "Active text area has no Text object"); + + texttool_text_set_active(st->text); + texttool_docs_show(docs); + scrarea_queue_redraw(curarea); + + Py_RETURN_NONE; +} + /*****************************************************************************/ /* Function: Text_compare */ /* Description: This is a callback function for the BPy_Text type. It */ diff --git a/source/blender/python/api2_2x/Text.h b/source/blender/python/api2_2x/Text.h index 0c5e2607f03..73943ddb9cd 100644 --- a/source/blender/python/api2_2x/Text.h +++ b/source/blender/python/api2_2x/Text.h @@ -41,6 +41,8 @@ extern PyTypeObject Text_Type; typedef struct { PyObject_HEAD Text * text; /* libdata must be second */ + TextLine * iol; /* current line being read or NULL if reset */ + int ioc; /* character offset in line being read */ } BPy_Text; PyObject *Text_Init( void ); diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 7ba8ad88ea6..51e1c389528 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -42,6 +42,7 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "MTex.h" #include "Image.h" @@ -1142,6 +1143,11 @@ static PyObject *M_Texture_TexCoDict( void ) PyConstant_Insert(d, "STICK", PyInt_FromLong(TEXCO_STICKY)); PyConstant_Insert(d, "STRESS", PyInt_FromLong(TEXCO_STRESS)); PyConstant_Insert(d, "TANGENT", PyInt_FromLong(TEXCO_TANGENT)); + + /* World TexCo Settings */ + PyConstant_Insert(d, "ANGMAP", PyInt_FromLong(TEXCO_ANGMAP)); + PyConstant_Insert(d, "HSPHERE", PyInt_FromLong(TEXCO_H_SPHEREMAP)); + PyConstant_Insert(d, "HTUBE", PyInt_FromLong(TEXCO_H_TUBEMAP)); } return TexCo; } @@ -1195,6 +1201,7 @@ static PyObject *M_Texture_ExtendModesDict( void ) PyConstant_Insert(d, "CLIP", PyInt_FromLong(TEX_CLIP)); PyConstant_Insert(d, "CLIPCUBE", PyInt_FromLong(TEX_CLIPCUBE)); PyConstant_Insert(d, "REPEAT", PyInt_FromLong(TEX_REPEAT)); + PyConstant_Insert(d, "CHECKER", PyInt_FromLong(TEX_CHECKER)); } return ExtendModes; } @@ -2125,7 +2132,7 @@ static PyObject *Texture_getFlags( BPy_Texture *self ) static PyObject *Texture_getHFracDim( BPy_Texture *self ) { - return PyInt_FromLong( (long)self->texture->mg_H ); + return PyFloat_FromDouble( self->texture->mg_H ); } static PyObject *Texture_getImageFlags( BPy_Texture *self, void *type ) diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index fe789fb4811..41a4e4e215f 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -1249,9 +1249,10 @@ static PyObject *M_Window_TestBreak( PyObject * self ) static PyObject *M_Window_GetMouseCoords( PyObject * self ) { - short mval[2]; + short mval[2] = {0, 0}; - getmouse( mval ); + if (!G.background) + getmouse( mval ); return Py_BuildValue( "hh", mval[0], mval[1] ); } @@ -1283,16 +1284,12 @@ static PyObject *M_Window_SetMouseCoords( PyObject * self, PyObject * args ) static PyObject *M_Window_GetMouseButtons( PyObject * self ) { - short mbut = get_mbut( ); - - return Py_BuildValue( "h", mbut ); + return PyInt_FromLong(G.background ? 0 : (int)get_mbut() ); } static PyObject *M_Window_GetKeyQualifiers( PyObject * self ) { - short qual = get_qual( ); - - return Py_BuildValue( "h", qual ); + return PyInt_FromLong( (int)get_qual() ); } static PyObject *M_Window_SetKeyQualifiers( PyObject * self, PyObject * args ) diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 6021f8552ad..0c57488a266 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -47,13 +47,17 @@ #include "BKE_world.h" #include "BKE_main.h" #include "BKE_library.h" +#include "BKE_texture.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "Ipo.h" +#include "MTex.h" #include "gen_utils.h" #include "gen_library.h" +#include "MEM_guardedalloc.h" #define IPOKEY_ZENITH 0 #define IPOKEY_HORIZON 1 @@ -99,6 +103,8 @@ static PyObject *World_getScriptLinks( BPy_World * self, PyObject * value ); static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ); static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_setCurrent( BPy_World * self ); +static PyObject *World_getTextures( BPy_World * self ); +static int World_setTextures( BPy_World * self, PyObject * value ); static PyObject *World_copy( BPy_World * self ); @@ -250,6 +256,9 @@ static PyGetSetDef BPy_World_getseters[] = { "world mist settings", NULL}, {"ipo", (getter)World_getIpo, (setter)World_setIpo, "world ipo", NULL}, + {"textures", (getter)World_getTextures, (setter)World_setTextures, + "The World's texture list as a tuple", + NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ }; @@ -1029,3 +1038,97 @@ static PyObject *World_insertIpoKey( BPy_World * self, PyObject * args ) Py_RETURN_NONE; } + +static PyObject *World_getTextures( BPy_World * self ) +{ + int i; + PyObject *tuple; + + /* build a texture list */ + tuple = PyTuple_New( MAX_MTEX ); + if( !tuple ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, + "couldn't create PyTuple" ); + + for( i = 0; i < MAX_MTEX; ++i ) { + struct MTex *mtex = self->world->mtex[i]; + if( mtex ) { + PyTuple_SET_ITEM( tuple, i, MTex_CreatePyObject( mtex, ID_WO ) ); + } else { + Py_INCREF( Py_None ); + PyTuple_SET_ITEM( tuple, i, Py_None ); + } + } + + return tuple; +} + +static int World_setTextures( BPy_World * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_WO ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing world MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->world->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->world->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->world->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->world->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} diff --git a/source/blender/python/api2_2x/bpy_data.c b/source/blender/python/api2_2x/bpy_data.c index 4705c1bdd03..47232c6707a 100644 --- a/source/blender/python/api2_2x/bpy_data.c +++ b/source/blender/python/api2_2x/bpy_data.c @@ -263,9 +263,12 @@ PyObject *LibBlockSeq_getActive(BPy_LibBlockSeq *self) } break; case ID_TXT: { - SpaceText *st= curarea->spacedata.first; + SpaceText *st = NULL; - if (st->spacetype!=SPACE_TEXT || st->text==NULL) { + if (curarea) + st = curarea->spacedata.first; + + if (st==NULL || st->spacetype!=SPACE_TEXT || st->text==NULL) { Py_RETURN_NONE; } else { return Text_CreatePyObject( st->text ); @@ -330,9 +333,15 @@ static int LibBlockSeq_setActive(BPy_LibBlockSeq *self, PyObject *value) return EXPP_ReturnIntError(PyExc_TypeError, "Must be a text" ); } else { - SpaceText *st= curarea->spacedata.first; + SpaceText *st= NULL; Text *data = ((BPy_Text *)value)->text; + if (curarea==NULL) { + return 0; + } else { + st= curarea->spacedata.first; + } + if( !data ) return EXPP_ReturnIntError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); diff --git a/source/blender/python/api2_2x/doc/Draw.py b/source/blender/python/api2_2x/doc/Draw.py index 18234754315..97e22797902 100644 --- a/source/blender/python/api2_2x/doc/Draw.py +++ b/source/blender/python/api2_2x/doc/Draw.py @@ -357,12 +357,14 @@ def PupTreeMenu( menu ): """ Create a popup menu tree. - Each item in the list is a menu item - (str, event), separator - None or submenu - (str, [...]). + Each item in the list is: a menu item - (str, event); a separator - None; + or submenu - (str, [...]). - Submenus list uses the same syntax as the menu list. + Submenus list uses the same syntax as the menu list. To add a title to the + main menu, end the first entry str with '%t' - the event is ignored. Example:: - result = Draw.PupTreeMenu( [ ("Menu Item 1", 10), ("Menu Item 2", 12), ("SubMenu", [("Menu Item 3", 100), ("MenuItem4", 101) ] ) ] ) + result = Draw.PupTreeMenu( [ ("Title%t", 0), ("Menu Item 1", 10), ("Menu Item 2", 12), ("SubMenu", [("Menu Item 3", 100), ("MenuItem4", 101) ] ) ] ) @type menu: string @param menu: A menu list diff --git a/source/blender/python/api2_2x/doc/Group.py b/source/blender/python/api2_2x/doc/Group.py index 6bd6e105ec3..1266d2efb6e 100644 --- a/source/blender/python/api2_2x/doc/Group.py +++ b/source/blender/python/api2_2x/doc/Group.py @@ -105,6 +105,8 @@ class Group: This object gives access to Groups in Blender. @ivar layers: Layer bitmask for this group. @type layers: int + @ivar dupliOffset: Object offset when instanced as a dupligroup + @type dupliOffset: vector @ivar objects: Objects that this group uses. This is a sequence with-list like access so use list(grp.objects) if you need to use a list (where grp is a group). The groups objects can be set by assigning a list or iterator of objects to the groups objects. diff --git a/source/blender/python/api2_2x/doc/Lamp.py b/source/blender/python/api2_2x/doc/Lamp.py index a7a1fb94620..162d94ccff3 100644 --- a/source/blender/python/api2_2x/doc/Lamp.py +++ b/source/blender/python/api2_2x/doc/Lamp.py @@ -161,6 +161,8 @@ class Lamp: @type type: int @ivar falloffType: Lamp falloff type. See L{Falloffs} for values. @type falloffType: int + @type textures: a tuple of Blender MTex objects. + @ivar textures: The Lamp's texture list. Empty texture channels contains None. @warning: Most member variables assume values in some [Min, Max] interval. When trying to set them, the given parameter will be clamped to lie in diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 02f7edd77f5..fa6a9f7047a 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -80,6 +80,35 @@ Example:: - SPEC_BLINN - Make Material use the Blinn specular shader. - SPEC_TOON - Make Material use the toon specular shader. - SPEC_WARDISO - Make Material use the Ward-iso specular shader. + +@type ColorbandMethod: readonly dictionary +@var ColorbandMethod: The available Colorband mixing methods. + - ADD - Make Material use the Add method. + - BLEND - Make Material use the Blend/Mix method. + - BURN - Make Material use the Burn method. + - COLOR - Make Material use the Color method. + - DARK - Make Material use the Darken method. + - DIFF - Make Material use the Difference method. + - DIV - Make Material use the Divide method. + - DODGE - Make Material use the Dodge method. + - HUE - Make Material use the Hue method. + - LIGHT - Make Material use the Lighten method. + - MIX - Make Material use the Blend/Mix method. + - MULT - Make Material use the Multiply method. + - OVERLAY - Make Material use the Overlay method. + - SAT - Make Material use the Saturation method. + - SCREEN - Make Material use the Screen method. + - SUB - Make Material use the Substract method. + - VAL - Make Material use the Value method. + +@type ColorbandInput: readonly dictionary +@var ColorbandInput: The available Colorband Input sources. + - ENERGY - Make Material use the Energy input. + - NORMAL - Make Material use the Normal input. + - RESULT - Make Material use the Result input. + - SHADER - Make Material use the Shader input. + + """ def New (name = 'Mat'): @@ -323,6 +352,28 @@ class Material: each color a list of 5 floats [0 - 1], [r,g,b,a,pos]. The colorband can have between 1 and 31 colors. @type colorbandSpecular: list + @ivar colorbandDiffuseInput: Material Diffuse colorband input. + The integer result must be compared with L{ColorbandInput} + dictionary. + @type colorbandDiffuseInput: int + @ivar colorbandDiffuseMethod: Material Diffuse colorband method. + The integer result must be compared with L{ColorbandMethod} + dictionary. + @type colorbandDiffuseMethod: int + @ivar colorbandDiffuseFactor: Material Diffuse colorband factor. + Value is clamped to the range [0.0,1.0]. + @type colorbandDiffuseFactor: float + @ivar colorbandSpecularInput: Material Specular colorband input. + The integer result must be compared with L{ColorbandInput} + dictionary. + @type colorbandSpecularInput: int + @ivar colorbandSpecularMethod: Material Specular colorband method. + The integer result must be compared with L{ColorbandMethod} + dictionary. + @type colorbandSpecularMethod: int + @ivar colorbandSpecularFactor: Material Specular colorband factor. + Value is clamped to the range [0.0,1.0]. + @type colorbandSpecularFactor: float @type enabledTextures: list of integers @ivar enabledTextures: The texture channels enabled in this material. The attribute returns is list of integers in the range [0, 9], each @@ -338,7 +389,9 @@ class Material: ch.append(4) mat.enabledTextures = ch print mat.enabledTextures # will print: [0, 4, 6] - + + @type textures: a tuple of Blender MTex objects. + @ivar textures: the Material's Texture list. Empty texture channels contains None. @ivar enableSSS: If True, subsurface scattering will be rendered on this material. @type enableSSS: bool @ivar sssScale: If True, subsurface scattering will be rendered on this material. @@ -1085,5 +1138,12 @@ class Material: @return: a copy of this material """ + def freeNodes (): + """ + Removes the node tree from this material. + @rtype: bool + @return: true if nodes were freed from this material. + """ + import id_generics Material.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index 4a53f869283..e48f41e8f9c 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -69,6 +69,7 @@ done once. - BILLBOARD - always orient after camera. - HALO - halo face, always point to camera. - DYNAMIC - respond to collisions. + - ALPHASORT - game engine sorts these faces only. - INVISIBLE - invisible face. - LIGHT - dynamic lighting. - OBCOL - use object color instead of vertex colors. @@ -635,7 +636,7 @@ class MFaceSeq: This object provides sequence and iterator access to the mesh's faces. """ - def extend(vertseq,ignoreDups=True,indexList=True): + def extend(vertseq,ignoreDups=True,indexList=True,smooth=False): """ Add zero or more faces and edges to the mesh. Faces which already exist in the mesh, or faces which contain the same vertex multiple times are diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py index 1d7d2e121c9..47f72e566b2 100644 --- a/source/blender/python/api2_2x/doc/Modifier.py +++ b/source/blender/python/api2_2x/doc/Modifier.py @@ -93,7 +93,12 @@ Example:: - SCALE_VEC - Used for Array only (3d Vector) - MERGE_DIST - Used for Array only (float) + - INVERT_VERTGROUP - Used for Armature only (bool) - ENVELOPES - Used for Armature only (bool) + - VGROUPS - Used for Armature only (bool) + - QUATERNION - Used for Armature only (bool) + - B_BONE_REST - Used for Armature only (bool) + - MULTIMODIFIER - Used for Armature only (bool) - START - Used for Build only (int) - SEED - Used for Build only (int) diff --git a/source/blender/python/api2_2x/doc/Text.py b/source/blender/python/api2_2x/doc/Text.py index 98ecb664b71..022205573aa 100644 --- a/source/blender/python/api2_2x/doc/Text.py +++ b/source/blender/python/api2_2x/doc/Text.py @@ -100,6 +100,19 @@ class Text: Clear this Text object: its buffer becomes empty. """ + def reset(): + """ + Reset the read IO pointer to the start of the buffer. + """ + + def readline(): + """ + Reads a line of text from the buffer from the current IO pointer + position to the end of the line. If the text has changed since the last + read, reset() *must* be called. + @rtype: string + """ + def set(attribute, value): """ Set this Text's attributes. @@ -118,12 +131,94 @@ class Text: @param data: The string to append to the text buffer. """ - def asLines(): + def insert(data): """ - Retrieve the contents of this Text buffer as a list of strings. + Inserts a string into this Text buffer at the cursor. + @type data: string + @param data: The string to insert into the text buffer. + """ + + def asLines(start=0, end=-1): + """ + Retrieve the contents of this Text buffer as a list of strings between + the start and end lines specified. If end < 0 all lines from start will + be included. + @type start int + @param start: Optional index of first line of the span to return + @type end int + @param end: Optional index of the line to which the span is taken or + -1 to include all lines from start @rtype: list of strings - @return: A list of strings, one for each line in the buffer + @return: A list of strings, one for each line in the buffer between + start and end. + """ + + def getCursorPos(): + """ + Retrieve the position of the cursor in this Text buffer. + @rtype: (int, int) + @return: A pair (row, col) indexing the line and character of the + cursor. + """ + + def setCursorPos(row, col): + """ + Set the position of the cursor in this Text buffer. Any selection will + be cleared. Use setSelectPos to extend a selection from the point + specified here. + @type row: int + @param row: The index of the line in which to position the cursor. + @type col: int + @param col: The index of the character within the line to position the + cursor. + """ + + def getSelectPos(): + """ + Retrieve the position of the selection cursor in this Text buffer. + @rtype: (int, int) + @return: A pair (row, col) indexing the line and character of the + selection cursor. + """ + + def setSelectPos(row, col): + """ + Set the position of the selection cursor in this Text buffer. This + method should be called after setCursorPos to extend the selection to + the specified point. + @type row: int + @param row: The index of the line in which to position the cursor. + @type col: int + @param col: The index of the character within the line to position the + cursor. + """ + + def suggest(list, prefix=''): + """ + Suggest a list of names. If list is a list of tuples (name, type) the + list will be formatted to syntax-highlight each entry type. Types must + be strings in the list ['m', 'f', 'v', 'k', '?']. It is recommended that + the list be sorted, case-insensitively by name. + + @type list: list of tuples or strings + @param list: List of pair-tuples of the form (name, type) where name is + the suggested name and type is one of 'm' (module or class), 'f' + (function or method), 'v' (variable), 'k' (keyword), '?' (other). + Lists of plain strings are also accepted where the type is always + '?'. + @type prefix: string + @param prefix: The optional prefix used to limit what is suggested from + the list. This is usually whatever precedes the cursor so that + backspace will update it. + """ + + def showDocs(docs): + """ + Displays a word-wrapped message box containing the specified + documentation when this Text object is visible. + @type docs: string + @param docs: The documentation string to display. """ import id_generics -Text.__doc__ += id_generics.attributes \ No newline at end of file +Text.__doc__ += id_generics.attributes diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index cebb7de7011..b5b82b1a519 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -195,20 +195,23 @@ Example:: - DN_CELLNOISE - Steven Worley's cellular basis algorithm (1996) @var TexCo: Flags for MTex.texco. - - ORCO - Use the original coordinates of the mesh - - REFL - Use reflection vector as texture coordinates - - NOR - Use normal vector as texture coordinates + - ORCO - Use the original coordinates of the mesh (material texture only) + - REFL - Use reflection vector as texture coordinates (material texture only) + - NOR - Use normal vector as texture coordinates (material texture only) - GLOB - Use global coordinates for the texture coordinates - - UV - Use UV coordinates for texture coordinates + - UV - Use UV coordinates for texture coordinates (material texture only) - OBJECT - Use linked object's coordinates for texture coordinates - - WIN - Use screen coordinates as texture coordinates - - VIEW - Pass camera view vector on to the texture (World texture only!) - - STICK - Use mesh sticky coordinates for the texture coordinates - - STRESS - Use mesh stress coordinates for the texture coordinates - - TANGENT - Use mesh tangent coordinates for the texture coordinates + - WIN - Use screen coordinates as texture coordinates (material texture only) + - VIEW - Use view coordinates for the texture (world and lamp texture only) + - STICK - Use mesh sticky coordinates for the texture coordinates (material texture only) + - STRESS - Use mesh stress coordinates for the texture coordinates (material texture only) + - TANGENT - Use mesh tangent coordinates for the texture coordinates (material texture only) + - ANGMAP - Uses 360 degree angular coordinates, e.g. for spherical light probes (world texture only) + - HSPHERE - For 360 degree panorama sky, spherical mapped, only top half (world texture only) + - HTUBE - For 360 degree panorama sky, cylindrical mapped, only top half (world texture only) @type TexCo: readonly dictionary -@var MapTo: Flags for MTex.mapto. +@var MapTo: Flags for MTex.mapto - COL - Make the texture affect the basic color of the material - NOR - Make the texture affect the rendered normal - CSP - Make the texture affect the specularity color @@ -500,48 +503,92 @@ class MTex: This object links a material to a texture. It allows the same texture to be used in several different ways. - @ivar tex: The Texture this is linked to. - @type tex: Blender Texture - @ivar texco: Texture coordinates ("Map input"). See L{TexCo} - @ivar mapto: "Map to" field of texture. OR'd values of L{MapTo} - @ivar object: Object whose space to use when texco is Object - @type object: Blender Object - @ivar col: Color that the texture blends with - @ivar dvar: Value that the texture blends with when not blending colors - @ivar blendmode: Texture blending mode. L{BlendModes} - @ivar colfac: Factor by which texture affects color - @ivar norfac: Factor by which texture affects normal - @ivar varfac: Factor by which texture affects most variables - @ivar dispfac: Factor by which texture affects displacement - @ivar warpfac: Factor by which texture affects warp - @ivar ofs: Offset to adjust texture space - @ivar size: Size to scale texture space - @ivar mapping: Mapping of texture coordinates (flat, cube, etc.). L{Mappings} - @ivar stencil: Stencil mode - @ivar neg: Negate texture values mode - @ivar noRGB: Convert texture RGB values to intensity values - @ivar correctNor: Correct normal mapping for Texture space and Object space - @ivar fromDupli: Dupli's instanced from verts, faces or particles, inherit texture coordinate from their parent - @ivar fromOrig: Dupli's derive their object coordinates from the original objects transformation - @ivar xproj: Projection of X axis to Texture space. L{Proj} - @ivar yproj: Projection of Y axis to Texture space. L{Proj} - @ivar zproj: Projection of Z axis to Texture space. L{Proj} - @ivar mtCol: How texture maps to color - @ivar mtNor: How texture maps to normals - @ivar mtCsp: How texture maps to specularity color - @ivar mtCmir: How texture maps to mirror color - @ivar mtRef: How texture maps to reflectivity - @ivar mtSpec: How texture maps to specularity - @ivar mtEmit: How texture maps to emit value - @ivar mtAlpha: How texture maps to alpha value - @ivar mtHard: How texture maps to hardness - @ivar mtRayMir: How texture maps to RayMir value - @ivar mtTranslu: How texture maps to translucency - @ivar mtAmb: How texture maps to ambient value - @ivar mtDisp: How texture maps to displacement - @ivar mtWarp: How texture maps to warp - @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) - @type uvlayer: string + @ivar blendmode: Texture blending mode. See L{BlendModes} + @type blendmode: int + @ivar col: Color that the texture blends with. + @type col: tuple + @ivar colfac: Factor by which texture affects color. + @type colfac: float + @ivar correctNor: Correct normal mapping for Texture space and Object space (material only). + @type correctNor: boolean + @ivar dispfac: Factor by which texture affects displacement (material only). + @type dispfac: float + @ivar dvar: Value that the texture blends with when not blending colors. + @type dvar: float + @ivar fromDupli: Duplis instanced from verts, faces or particles, inherit texture coordinate from their parent (material only). + @type fromDupli: boolean + @ivar fromOrig: Duplis derive their object coordinates from the original objects transformation (material only). + @type fromOrig: boolean + @ivar mapping: Mapping of texture coordinates (flat, cube, etc.) (material only). See L{Mappings}. + @type mapping: int + @ivar mapto: "Map to" field of texture (material only). OR'd values of L{MapTo}. + @type mapto: int + @ivar mtCol: How texture maps to color (material and lamp only). + @type mtCol: int + @ivar mtAlpha: How texture maps to alpha value (material only). + @type mtAlpha: int + @ivar mtAmb: How texture maps to ambient value (material only). + @type mtAmb: int + @ivar mtCmir: How texture maps to mirror color (material only). + @type mtCmir: int + @ivar mtCsp: How texture maps to specularity color (material only). + @type mtCsp: int + @ivar mtDisp: How texture maps to displacement (material only). + @type mtDisp: int + @ivar mtEmit: How texture maps to emit value (material only). + @type mtEmit: int + @ivar mtHard: How texture maps to hardness (material only). + @type mtHard: int + @ivar mtNor: How texture maps to normals (material only). + @type mtNor: int + @ivar mtRayMir: How texture maps to RayMir value (material only). + @type mtRayMir: int + @ivar mtRef: How texture maps to reflectivity (material only). + @type mtRef: int + @ivar mtSpec: How texture maps to specularity (material only). + @type mtSpec: int + @ivar mtTranslu: How texture maps to translucency (material only). + @type mtTranslu: int + @ivar mtWarp: How texture maps to warp (material only). + @type mtWarp: int + @ivar mtBlend: Texture affects color progression of background (world only). + @type mtBlend: int + @ivar mtHoriz: Texture affects color of the horizon (world only). + @type mtHoriz: int + @ivar mtZenUp: Texture affects color of the zenith above (world only). + @type mtZenUp: int + @ivar mtZenDown: Texture affects color of the zenith below (world only). + @type mtZenDown: int + @ivar neg: Negate texture values mode. + @type neg: boolean + @ivar norfac: Factor by which texture affects normal (material and world only). + @type norfac: float + @ivar noRGB: Convert texture RGB values to intensity values. + @type noRGB: boolean + @ivar object: Object whose space to use when texco is Object. + @type object: Blender Object or None + @ivar ofs: Offset to adjust texture space. + @type ofs: tuple + @ivar size: Size to scale texture space. + @type size: tuple + @ivar stencil: Stencil mode. + @type stencil: boolean + @ivar tex: The Texture this is linked to. + @type tex: Blender Texture + @ivar texco: Texture coordinates ("Map input"). See L{TexCo}. + @type texco: int + @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) (material only). + @type uvlayer: string + @ivar varfac: Factor by which texture affects most variables (material and world only). + @type varfac: float + @ivar warpfac: Factor by which texture affects warp (material only). + @type warpfac: float + @ivar xproj: Projection of X axis to Texture space (material only). See L{Proj} + @type xproj: int + @ivar yproj: Projection of Y axis to Texture space (material only). See L{Proj} + @type yproj: int + @ivar zproj: Projection of Z axis to Texture space (material only). See L{Proj} + @type zproj: int """ def getIpo(): diff --git a/source/blender/python/api2_2x/doc/World.py b/source/blender/python/api2_2x/doc/World.py index d9e9bae750d..d8052c609cd 100644 --- a/source/blender/python/api2_2x/doc/World.py +++ b/source/blender/python/api2_2x/doc/World.py @@ -82,6 +82,8 @@ class World: @ivar mist: the mist parameters of a world object. See getMist for the semantics of these parameters. @type ipo: Blender Ipo @ivar ipo: The world type ipo linked to this world object. + @type textures: a tuple of Blender MTex objects. + @ivar textures: The World's texture list. Empty texture channels contains None. """ def getRange(): diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h index 1f2fd55cf1b..f33dc69d703 100644 --- a/source/blender/python/api2_2x/gen_utils.h +++ b/source/blender/python/api2_2x/gen_utils.h @@ -45,6 +45,7 @@ Py_RETURN_NONE Python 2.4 macro. defined here until we switch to 2.4 + also in PyObjectPlus.h for gameengine */ #ifndef Py_RETURN_NONE #define Py_RETURN_NONE return Py_BuildValue("O", Py_None) diff --git a/source/blender/python/api2_2x/sceneRender.c b/source/blender/python/api2_2x/sceneRender.c index 22e165cbe9f..7958e66b44f 100644 --- a/source/blender/python/api2_2x/sceneRender.c +++ b/source/blender/python/api2_2x/sceneRender.c @@ -481,7 +481,6 @@ PyObject *RenderData_Render( BPy_RenderData * self ) set_scene( oldsce ); } else { /* background mode (blender -b file.blend -P script) */ - int slink_flag = 0; Render *re= RE_NewRender(G.scene->id.name); int end_frame = G.scene->r.efra; @@ -492,20 +491,14 @@ PyObject *RenderData_Render( BPy_RenderData * self ) G.scene->r.efra = G.scene->r.sfra; - if (G.f & G_DOSCRIPTLINKS) { - BPY_do_all_scripts(SCRIPT_RENDER); - G.f &= ~G_DOSCRIPTLINKS; /* avoid FRAMECHANGED events*/ - slink_flag = 1; - } + if (G.f & G_DOSCRIPTLINKS) + BPY_do_all_scripts(SCRIPT_RENDER, 0); tstate = PyEval_SaveThread(); RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra); - if (slink_flag) { - G.f |= G_DOSCRIPTLINKS; - BPY_do_all_scripts(SCRIPT_POSTRENDER); - } + BPY_do_all_scripts(SCRIPT_POSTRENDER, 0); G.scene->r.efra = end_frame; } @@ -603,13 +596,13 @@ PyObject *RenderData_RenderAnim( BPy_RenderData * self ) "start frame must be less or equal to end frame"); if (G.f & G_DOSCRIPTLINKS) - BPY_do_all_scripts(SCRIPT_RENDER); + BPY_do_all_scripts(SCRIPT_RENDER, 1); tstate = PyEval_SaveThread(); RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra); if (G.f & G_DOSCRIPTLINKS) - BPY_do_all_scripts(SCRIPT_POSTRENDER); + BPY_do_all_scripts(SCRIPT_POSTRENDER, 1); } PyEval_RestoreThread(tstate); diff --git a/source/blender/python/api2_2x/sceneSequence.c b/source/blender/python/api2_2x/sceneSequence.c index 0d3ad3fcb44..ddc4eb6aea8 100644 --- a/source/blender/python/api2_2x/sceneSequence.c +++ b/source/blender/python/api2_2x/sceneSequence.c @@ -33,12 +33,14 @@ #include "DNA_scene_types.h" /* for Base */ #include "BKE_mesh.h" +#include "BKE_image.h" // RFS: openanim #include "BKE_library.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_scene.h" #include "BIF_editseq.h" /* get_last_seq */ +#include "BIF_editsound.h" // RFS: sound_open_hdaudio #include "BLI_blenlib.h" #include "BSE_sequence.h" #include "Ipo.h" @@ -48,6 +50,9 @@ #include "Sound.h" #include "gen_utils.h" +#include "IMB_imbuf_types.h" // RFS: IB_rect +#include "IMB_imbuf.h" // RFS: IMB_anim_get_duration + enum seq_consts { EXPP_SEQ_ATTR_TYPE = 0, EXPP_SEQ_ATTR_CHAN, @@ -145,7 +150,6 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) seq->len = PyList_Size( list ); - /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= seq->len; @@ -185,12 +189,103 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->us= 1; strip->stripdata= se= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + } else if (PyTuple_Check(py_data) && PyTuple_GET_SIZE(py_data) == 4) { + // MOVIE or AUDIO_HD + char *filename; + char *dir; + char *fullpath; + char *type; + int totframe; + + if (!PyArg_ParseTuple( py_data, "ssss", &filename, &dir, &fullpath, &type )) { + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "movie/audio hd data needs to be a tuple of a string and a list of images - (filename, dir, fullpath, type)" ); + } + + // RFS - Attempting to support Movie and Audio (HD) strips +#define RFS +#ifdef RFS + // Movie strips + if( strcmp( type, "movie" ) == 0 ) + { + /* open it as an animation */ + struct anim * an = openanim(fullpath, IB_rect); + if(an==0) { + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + "invalid movie strip" ); + } + + /* get the length in frames */ + totframe = IMB_anim_get_duration( an ); + + /* set up sequence */ + seq->type= SEQ_MOVIE; + seq->len= totframe; + seq->anim= an; + seq->anim_preseek = IMB_anim_get_preseek(an); + + calc_sequence(seq); + + /* strip and stripdata */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len= totframe; + strip->us= 1; + strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + + /* name movie in first strip */ + strncpy(se->name, filename, FILE_MAXFILE-1); // ???? + } + + // Audio (HD) strips + if( strcmp( type, "audio_hd" ) == 0 ) + { + struct hdaudio *hdaudio; + + totframe= 0; + + /* is it a sound file? */ + hdaudio = sound_open_hdaudio( fullpath ); + if(hdaudio==0) { + BLI_remlink(seqbase, seq); + MEM_freeN(seq); + + return EXPP_ReturnPyObjError( PyExc_ValueError, + fullpath ); + } + + totframe= sound_hdaudio_get_duration(hdaudio, FPS); + + /* set up sequence */ + seq->type= SEQ_HD_SOUND; + seq->len= totframe; + seq->hdaudio= hdaudio; + + calc_sequence(seq); + + /* strip and stripdata - same as for MOVIE */ + seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); + strip->len= totframe; + strip->us= 1; + strncpy(strip->dir, dir, FILE_MAXDIR-1); // ???? + strip->stripdata= se= MEM_callocN(sizeof(StripElem), "stripelem"); + + /* name movie in first strip */ + strncpy(se->name, filename, FILE_MAXFILE-1); // ???? + } +#endif + } else if (BPy_Sound_Check(py_data)) { - /* sound */ + /* RAM sound */ int totframe; bSound *sound = (( BPy_Sound * )py_data)->sound; - seq->type= SEQ_RAM_SOUND; seq->sound = sound; @@ -198,7 +293,6 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) sound->flags |= SOUND_FLAGS_SEQUENCE; - /* strip and stripdata */ seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); strip->len= totframe; @@ -225,18 +319,7 @@ static PyObject *NewSeq_internal(ListBase *seqbase, PyObject * args, Scene *sce) strip->len= seq->len; strip->us= 1; } else { - /* movie, pydata is a path to a movie file */ - char *name = PyString_AsString ( py_data ); - if (!name) { - /* only free these 2 because other stuff isnt set */ - BLI_remlink(seqbase, seq); - MEM_freeN(seq); - - return EXPP_ReturnPyObjError( PyExc_TypeError, - "expects a string for chan/bone name and an int for the frame where to put the new key" ); - } - - seq->type= SEQ_MOVIE; + // RFS: REMOVED MOVIE FROM HERE } strncpy(seq->name+2, "Untitled", 21); intern_pos_update(seq); diff --git a/source/blender/radiosity/CMakeLists.txt b/source/blender/radiosity/CMakeLists.txt index 941da41a5b2..502acf1e211 100644 --- a/source/blender/radiosity/CMakeLists.txt +++ b/source/blender/radiosity/CMakeLists.txt @@ -29,7 +29,7 @@ FILE(GLOB SRC intern/source/*.c) SET(INC extern/include ../blenlib ../blenkernel ../makesdna ../include ../../../intern/guardedalloc ../render/extern/include - ../render/intern/include ../blenloader + ../render/intern/include ../blenloader ../../../extern/glew/include ) BLENDERLIB_NOLIST(blender_radiosity "${SRC}" "${INC}") diff --git a/source/blender/radiosity/SConscript b/source/blender/radiosity/SConscript index a86b76bb4b1..82d84f5ef16 100644 --- a/source/blender/radiosity/SConscript +++ b/source/blender/radiosity/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('intern/source/*.c') incs = 'extern/include ../blenlib ../blenkernel ../makesdna ../include' incs += ' #/intern/guardedalloc ../render/extern/include' -incs += ' ../render/intern/include ../blenloader' +incs += ' ../render/intern/include ../blenloader #/extern/glew/include' incs += ' ' + env['BF_OPENGL_INC'] diff --git a/source/blender/radiosity/intern/source/Makefile b/source/blender/radiosity/intern/source/Makefile index e5ff8c40d08..5912cdba590 100644 --- a/source/blender/radiosity/intern/source/Makefile +++ b/source/blender/radiosity/intern/source/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CFLAGS += $(LEVEL_1_C_WARNINGS) +CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) # not very neat.... diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c index 6e5bf149c7a..ec71611b31d 100644 --- a/source/blender/readblenfile/intern/BLO_readblenfile.c +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -159,7 +159,7 @@ blo_read_runtime( } else { //printf("starting to read runtime from %s at datastart %d\n", path, datastart); lseek(fd, datastart, SEEK_SET); - bfd = blo_read_blendafterruntime(fd, actualsize-datastart, error_r); + bfd = blo_read_blendafterruntime(fd, path, actualsize-datastart, error_r); fd= -1; // file was closed in blo_read_blendafterruntime() } diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index f83bbd7e8b2..7e2194549cc 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -418,7 +418,8 @@ typedef struct LampRen { float xs, ys, dist; float co[3]; - short type, mode; + short type; + int mode; float r, g, b, k; float energy, haint; int lay; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index e4a5ad67631..322d2066a6c 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1565,7 +1565,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(ob,(float)CFRA,0.0); float adapt_angle=0.0, adapt_pix=0.0, random, simplify[2]; int i, a, k, max_k=0, totpart, totuv=0, totcol=0, override_uv=-1, dosimplify = 0, dosurfacecache = 0; - int path_possible=0, keys_possible=0, baked_keys=0, totchild=psys->totchild; + int path_possible=0, keys_possible=0, baked_keys=0, totchild=0; int seed, path_nbr=0, path=0, orco1=0, adapt=0, uv[3]={0,0,0}, num; int totface, *origindex = 0; char **uv_name=0; @@ -1573,6 +1573,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem /* 1. check that everything is ok & updated */ if(psys==NULL) return 0; + + totchild=psys->totchild; part=psys->part; pars=psys->particles; @@ -1764,7 +1766,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem psys->lattice=psys_get_lattice(ob,psys); /* 3. start creating renderable things */ - for(a=0,pa=pars; amode & MA_HALO) + if(totmaterial) { + for(a= 0; a<*totmaterial; a++) { + ma= give_current_material(obd, a); + if(ma && (ma->mode & MA_HALO)) return 0; + } } for(psys=obd->particlesystem.first; psys; psys=psys->next) diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index c2d27f8f3a7..b9a2acb8b1c 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -577,10 +577,10 @@ static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float max if(texres->talpha==0) texres->ta= 1.0; if(alphaclip!=1.0) { - /* this is for later investigation, premul or not? */ - /* texres->tr*= alphaclip; */ - /* texres->tg*= alphaclip; */ - /* texres->tb*= alphaclip; */ + /* premul it all */ + texres->tr*= alphaclip; + texres->tg*= alphaclip; + texres->tb*= alphaclip; texres->ta*= alphaclip; } } diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 3cd7bdc6772..bf2a72b4f9b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -138,7 +138,7 @@ static void print_error(char *str) {printf("ERROR: %s\n", str);} static void stats_background(RenderStats *rs) { - extern uintptr_t mem_in_use; + uintptr_t mem_in_use= MEM_get_memory_in_use(); float megs_used_memory= mem_in_use/(1024.0*1024.0); char str[400], *spos= str; @@ -1889,6 +1889,7 @@ static void do_render_fields_blur_3d(Render *re) re->result->tilerect= re->disprect; /* this copying sequence could become function? */ + /* weak is: it chances disprect from border */ re->disprect.xmin= re->disprect.ymin= 0; re->disprect.xmax= re->winx; re->disprect.ymax= re->winy; @@ -2346,6 +2347,12 @@ static int is_rendering_allowed(Render *re) if(re->osa==0) re->r.scemode &= ~R_FULL_SAMPLE; + /* no fullsample and edge */ + if((re->r.scemode & R_FULL_SAMPLE) && (re->r.mode & R_EDGE)) { + re->error("Full Sample doesn't support Edge Enhance"); + return 0; + } + } else re->r.scemode &= ~R_FULL_SAMPLE; /* clear to be sure */ @@ -2407,7 +2414,7 @@ static int is_rendering_allowed(Render *re) } /* evaluating scene options for general Blender render */ -static int render_initialize_from_scene(Render *re, Scene *scene) +static int render_initialize_from_scene(Render *re, Scene *scene, int anim) { int winx, winy; rcti disprect; @@ -2435,6 +2442,12 @@ static int render_initialize_from_scene(Render *re, Scene *scene) re->scene= scene; + /* not too nice, but it survives anim-border render */ + if(anim) { + re->disprect= disprect; + return 1; + } + /* check all scenes involved */ tag_scenes_for_render(re); @@ -2466,7 +2479,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) scene->r.cfra= frame; - if(render_initialize_from_scene(re, scene)) { + if(render_initialize_from_scene(re, scene, 0)) { do_render_all_options(re); } @@ -2551,8 +2564,8 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype); int cfrao= scene->r.cfra; - /* do not call for each frame, it initializes & pops output window */ - if(!render_initialize_from_scene(re, scene)) + /* do not fully call for each frame, it initializes & pops output window */ + if(!render_initialize_from_scene(re, scene, 0)) return; /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ @@ -2580,6 +2593,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) } else { for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) { char name[FILE_MAX]; + + /* only border now, todo: camera lens. (ton) */ + render_initialize_from_scene(re, scene, 1); + if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index c352a83d0f4..0fd9365477c 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -2056,7 +2056,10 @@ void ray_shadow(ShadeInput *shi, LampRen *lar, float *shadfac) if(shi->mat->mode & MA_SHADOW_TRA) isec.mode= RE_RAY_SHADOW_TRA; else isec.mode= RE_RAY_SHADOW; - if(lar->mode & LA_LAYER) isec.lay= lar->lay; else isec.lay= -1; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) + isec.lay= lar->lay; + else + isec.lay= -1; /* only when not mir tracing, first hit optimm */ if(shi->depth==0) { diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 4a2ad995b39..bda02bea8d7 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -158,7 +158,7 @@ static int calchalo_z(HaloRen *har, int zz) { if(har->type & HA_ONLYSKY) { - if(zz!=0x7FFFFFFF) zz= - 0x7FFFFF; + if(zz < 0x7FFFFFF0) zz= - 0x7FFFFF; /* edge render messes zvalues */ } else { zz= (zz>>8); @@ -931,17 +931,23 @@ static void edge_enhance_add(RenderPart *pa, float *rectf, float *arect) } } - -static void convert_to_key_alpha(RenderPart *pa, float *rectf) +static void convert_to_key_alpha(RenderPart *pa, RenderLayer *rl) { - int y; + RenderLayer *rlpp[RE_MAX_OSA]; + int y, sample, totsample; - for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { - if(rectf[3] >= 1.0f); - else if(rectf[3] > 0.0f) { - rectf[0] /= rectf[3]; - rectf[1] /= rectf[3]; - rectf[2] /= rectf[3]; + totsample= get_sample_layers(pa, rl, rlpp); + + for(sample= 0; samplerectf; + + for(y= pa->rectx*pa->recty; y>0; y--, rectf+=4) { + if(rectf[3] >= 1.0f); + else if(rectf[3] > 0.0f) { + rectf[0] /= rectf[3]; + rectf[1] /= rectf[3]; + rectf[2] /= rectf[3]; + } } } } @@ -1229,7 +1235,7 @@ void zbufshadeDA_tile(RenderPart *pa) /* de-premul alpha */ if(R.r.alphamode & R_ALPHAKEY) - convert_to_key_alpha(pa, rl->rectf); + convert_to_key_alpha(pa, rl); /* free stuff within loop! */ MEM_freeN(pa->rectdaps); pa->rectdaps= NULL; @@ -1393,7 +1399,7 @@ void zbufshade_tile(RenderPart *pa) /* de-premul alpha */ if(R.r.alphamode & R_ALPHAKEY) - convert_to_key_alpha(pa, rl->rectf); + convert_to_key_alpha(pa, rl); if(edgerect) MEM_freeN(edgerect); edgerect= NULL; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index 98b1426e8ff..d44b49cc706 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -483,16 +483,16 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) DerivedMesh which stores the layers is freed */ CustomDataLayer *layer; - int numlayers, i, mtfn, mcn; + int numtf = 0, numcol = 0, i, mtfn, mcn; if (CustomData_has_layer(data, CD_MTFACE)) { - numlayers= CustomData_number_of_layers(data, CD_MTFACE); - obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numlayers, "mtfacenames"); + numtf= CustomData_number_of_layers(data, CD_MTFACE); + obr->mtface= MEM_callocN(sizeof(*obr->mtface)*numtf, "mtfacenames"); } if (CustomData_has_layer(data, CD_MCOL)) { - numlayers= CustomData_number_of_layers(data, CD_MCOL); - obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numlayers, "mcolnames"); + numcol= CustomData_number_of_layers(data, CD_MCOL); + obr->mcol= MEM_callocN(sizeof(*obr->mcol)*numcol, "mcolnames"); } for (i=0, mtfn=0, mcn=0; i < data->totlayer; i++) { @@ -500,12 +500,12 @@ void RE_set_customdata_names(ObjectRen *obr, CustomData *data) if (layer->type == CD_MTFACE) { strcpy(obr->mtface[mtfn++], layer->name); - obr->actmtface= layer->active_rnd; + obr->actmtface= CLAMPIS(layer->active_rnd, 0, numtf); obr->bakemtface= layer->active; } else if (layer->type == CD_MCOL) { strcpy(obr->mcol[mcn++], layer->name); - obr->actmcol= layer->active_rnd; + obr->actmcol= CLAMPIS(layer->active_rnd, 0, numcol); } } } diff --git a/source/blender/render/intern/source/shadbuf.c b/source/blender/render/intern/source/shadbuf.c index f477df3ed8c..c53a2b68c9c 100644 --- a/source/blender/render/intern/source/shadbuf.c +++ b/source/blender/render/intern/source/shadbuf.c @@ -296,7 +296,7 @@ static void shadowbuf_autoclip(Render *re, LampRen *lar) minz= 1.0e30f; maxz= -1.0e30f; Mat4CpyMat4(viewmat, lar->shb->viewmat); - if(lar->mode & LA_LAYER) lay= lar->lay; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; maxtotvert= 0; for(obr=re->objecttable.first; obr; obr=obr->next) @@ -1520,7 +1520,7 @@ static void isb_bsp_fillfaces(Render *re, LampRen *lar, ISBBranch *root) minmaxf[2]= (2.0f*root->box.ymin - size-2.0f)/size; minmaxf[3]= (2.0f*root->box.ymax - size+2.0f)/size; - if(lar->mode & LA_LAYER) lay= lar->lay; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; /* (ab)use zspan, since we use zbuffer clipping code */ zbuf_alloc_span(&zspan, size, size, re->clipcrop); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 5b69323667e..5a80173d1f1 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1761,7 +1761,21 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) if(shi->combinedflag & SCE_PASS_SPEC) VECADD(shr->combined, shr->combined, shr->spec); + /* modulate by the object color */ + if((ma->shade_flag & MA_OBCOLOR) && shi->obr->ob) { + if(!(ma->sss_flag & MA_DIFF_SSS) || !has_sss_tree(&R, ma)) { + float obcol[4]; + + QUATCOPY(obcol, shi->obr->ob->col); + CLAMP(obcol[3], 0.0f, 1.0f); + + shr->combined[0] *= obcol[0]; + shr->combined[1] *= obcol[1]; + shr->combined[2] *= obcol[2]; + shr->alpha *= obcol[3]; + } + } + shr->combined[3]= shr->alpha; } - diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 29aa6e3be29..76a47a11338 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2410,7 +2410,7 @@ void zbuffer_shadow(Render *re, float winmat[][4], LampRen *lar, int *rectz, int float obwinmat[4][4], ho1[4], ho2[4], ho3[4], ho4[4]; int a, b, c, i, c1, c2, c3, c4, ok=1, lay= -1; - if(lar->mode & LA_LAYER) lay= lar->lay; + if(lar->mode & (LA_LAYER|LA_LAYER_SHADOW)) lay= lar->lay; /* 1.0f for clipping in clippyra()... bad stuff actually */ zbuf_alloc_span(&zspan, size, size, 1.0f); @@ -2981,10 +2981,11 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * { ZSpan zspan; DrawBufPixel *rectdraw, *dr; - static float jit[16][2]; + static float jit[256][2]; float v1[3], v2[3], v3[3], v4[3], fx, fy; - float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz, *minvecbufrect= NULL; - float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed; + float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz; + float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro; + float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed, totfac; int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples; int tsktsk= 0; static int firsttime= 1; @@ -3003,6 +3004,9 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * rectmove= MEM_mapallocN(xsize*ysize, "rectmove"); rectdraw= MEM_mapallocN(sizeof(DrawBufPixel)*xsize*ysize, "rect draw"); zspan.rectp= (int *)rectdraw; + + rectweight= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect weight"); + rectmax= MEM_mapallocN(sizeof(float)*xsize*ysize, "rect max"); /* debug... check if PASS_VECTOR_MAX still is in buffers */ dvec1= vecbufrect; @@ -3142,7 +3146,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dm= rectmove; dvec1= vecbufrect; for(x=xsize*ysize; x>0; x--, dm++, dvec1+=4) { - if(dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f) + if((dvec1[0]!=0.0f || dvec1[1]!=0.0f || dvec1[2]!=0.0f || dvec1[3]!=0.0f)) *dm= 255; } @@ -3151,9 +3155,12 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ if(firsttime) { firsttime= 0; - BLI_initjit(jit[0], 16); + BLI_initjit(jit[0], 256); } + memset(newrect, 0, sizeof(float)*xsize*ysize*4); + totfac= 0.0f; + /* accumulate */ samples/= 2; for(step= 1; step<=samples; step++) { @@ -3161,7 +3168,7 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * int side; for(side=0; side<2; side++) { - float blendfac= 1.0f/((ABS(step)*2+side)+1), ipodata[4]; + float blendfac, ipodata[4]; /* clear zbuf, if we draw future we fill in not moving pixels */ if(0) @@ -3193,30 +3200,32 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * set_quad_bezier_ipo(0.5f + 0.5f*speedfac, ipodata); - for(fy= -0.5f+jit[step & 15][0], y=0; y1) { + float jfx = fx + 0.5f; + float jfy = fy + 0.5f; DrawBufPixel col; /* make vertices */ if(nbd->curved) { /* curved */ quad_bezier_2d(v1, dz1, dz1+2, ipodata); - v1[0]+= fx; v1[1]+= fy; v1[2]= *dz; + v1[0]+= jfx; v1[1]+= jfy; v1[2]= *dz; quad_bezier_2d(v2, dz1+4, dz1+4+2, ipodata); - v2[0]+= fx+1.0f; v2[1]+= fy; v2[2]= *dz; + v2[0]+= jfx+1.0f; v2[1]+= jfy; v2[2]= *dz; quad_bezier_2d(v3, dz2+4, dz2+4+2, ipodata); - v3[0]+= fx+1.0f; v3[1]+= fy+1.0f; v3[2]= *dz; + v3[0]+= jfx+1.0f; v3[1]+= jfy+1.0f; v3[2]= *dz; quad_bezier_2d(v4, dz2, dz2+2, ipodata); - v4[0]+= fx; v4[1]+= fy+1.0f; v4[2]= *dz; + v4[0]+= jfx; v4[1]+= jfy+1.0f; v4[2]= *dz; } else { - v1[0]= speedfac*dz1[0]+fx; v1[1]= speedfac*dz1[1]+fy; v1[2]= *dz; - v2[0]= speedfac*dz1[4]+fx+1.0f; v2[1]= speedfac*dz1[5]+fy; v2[2]= *dz; - v3[0]= speedfac*dz2[4]+fx+1.0f; v3[1]= speedfac*dz2[5]+fy+1.0f; v3[2]= *dz; - v4[0]= speedfac*dz2[0]+fx; v4[1]= speedfac*dz2[1]+fy+1.0f; v4[2]= *dz; + v1[0]= speedfac*dz1[0]+jfx; v1[1]= speedfac*dz1[1]+jfy; v1[2]= *dz; + v2[0]= speedfac*dz1[4]+jfx+1.0f; v2[1]= speedfac*dz1[5]+jfy; v2[2]= *dz; + v3[0]= speedfac*dz2[4]+jfx+1.0f; v3[1]= speedfac*dz2[5]+jfy+1.0f; v3[2]= *dz; + v4[0]= speedfac*dz2[0]+jfx; v4[1]= speedfac*dz2[1]+jfy+1.0f; v4[2]= *dz; } if(*dm==255) col.alpha= 1.0f; else if(*dm<2) col.alpha= 0.0f; @@ -3229,26 +3238,59 @@ void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float * dz1+=4; dz2+=4; } - + + /* blend with a falloff. this fixes the ugly effect you get with + * a fast moving object. then it looks like a solid object overlayed + * over a very transparent moving version of itself. in reality, the + * whole object should become transparent if it is moving fast, be + * we don't know what is behind it so we don't do that. this hack + * overestimates the contribution of foreground pixels but looks a + * bit better without a sudden cutoff. */ + blendfac= ((samples - step)/(float)samples); + /* smoothstep to make it look a bit nicer as well */ + blendfac= 3.0f*pow(blendfac, 2.0f) - 2.0f*pow(blendfac, 3.0f); + /* accum */ - for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4) { + rw= rectweight; + rm= rectmax; + for(dr= rectdraw, dz2=newrect, x= xsize*ysize-1; x>=0; x--, dr++, dz2+=4, rw++, rm++) { if(dr->colpoin) { - float bfac= dr->alpha*blendfac*dr->colpoin[3]; - float mf= 1.0f - bfac; + float bfac= dr->alpha*blendfac; - dz2[0]= mf*dz2[0] + bfac*dr->colpoin[0]; - dz2[1]= mf*dz2[1] + bfac*dr->colpoin[1]; - dz2[2]= mf*dz2[2] + bfac*dr->colpoin[2]; - dz2[3]= mf*dz2[3] + bfac*dr->colpoin[3]; + dz2[0] += bfac*dr->colpoin[0]; + dz2[1] += bfac*dr->colpoin[1]; + dz2[2] += bfac*dr->colpoin[2]; + dz2[3] += bfac*dr->colpoin[3]; + + *rw += bfac; + *rm= MAX2(*rm, bfac); } } } } + /* blend between original images and accumulated image */ + rw= rectweight; + rm= rectmax; + ro= imgrect; + dm= rectmove; + for(dz2=newrect, x= xsize*ysize-1; x>=0; x--, dz2+=4, ro+=4, rw++, rm++, dm++) { + float mfac = *rm; + float fac = (*rw == 0.0f)? 0.0f: mfac/(*rw); + float nfac = 1.0f - mfac; + + dz2[0]= fac*dz2[0] + nfac*ro[0]; + dz2[1]= fac*dz2[1] + nfac*ro[1]; + dz2[2]= fac*dz2[2] + nfac*ro[2]; + dz2[3]= fac*dz2[3] + nfac*ro[3]; + } + MEM_freeN(rectz); MEM_freeN(rectmove); MEM_freeN(rectdraw); MEM_freeN(rectvz); + MEM_freeN(rectweight); + MEM_freeN(rectmax); if(minvecbufrect) MEM_freeN(vecbufrect); /* rects were swapped! */ zbuf_free_span(&zspan); } diff --git a/source/blender/src/CMakeLists.txt b/source/blender/src/CMakeLists.txt index 342579fb3b0..d95551940f8 100644 --- a/source/blender/src/CMakeLists.txt +++ b/source/blender/src/CMakeLists.txt @@ -35,7 +35,7 @@ SET(INC ../../kernel/gen_system ../../../intern/SoundSystem ../readstreamglue ../quicktime ../../../intern/elbeem/extern ../../../intern/ghost ../../../intern/opennl/extern - ../nodes ../../../extern/glew/include + ../nodes ../../../extern/glew/include ../gpu ${PYTHON_INC} ${SDL_INC} ) diff --git a/source/blender/src/Makefile b/source/blender/src/Makefile index 001efc58b5d..46e916b0437 100644 --- a/source/blender/src/Makefile +++ b/source/blender/src/Makefile @@ -68,6 +68,7 @@ CPPFLAGS += -I.. CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../../gameengine/SoundSystem CPPFLAGS += -I../ftfont +CPPFLAGS += -I../gpu # Only used by py_demo.c !!! CPPFLAGS += -I../radiosity/extern/include diff --git a/source/blender/src/SConscript b/source/blender/src/SConscript index 229cc87ef37..c421d1e8388 100644 --- a/source/blender/src/SConscript +++ b/source/blender/src/SConscript @@ -26,7 +26,8 @@ incs += ' #/intern/bsp/extern ../radiosity/extern/include' incs += ' #/intern/decimation/extern ../blenloader ../python' incs += ' ../../kernel/gen_system #/intern/SoundSystem ../readstreamglue ../nodes' incs += ' ../quicktime #/intern/elbeem/extern' -incs += ' #/intern/ghost #/intern/opennl/extern #/extern/glew/include' +incs += ' #/intern/ghost #/intern/opennl/extern' +incs += ' ../gpu #extern/glew/include' incs += ' ' + env['BF_PYTHON_INC'] @@ -74,7 +75,13 @@ if env['WITH_BF_VERSE']: # TODO buildinfo if env['BF_BUILDINFO'] == 1: defs.append('NAN_BUILDINFO') - + +if env['BF_NO_ELBEEM'] == 1: + defs.append('DISABLE_ELBEEM') + +if env['WITH_BF_SDL'] == 0: + defs.append('DISABLE_SDL') + if (env['BF_SPLIT_SRC'] == 1) and (env['OURPLATFORM'] == 'win32-mingw'): for i in range(numlibs): env.BlenderLib ( libname = 'src%d' % (i), sources = subsources[i], includes = Split(incs), defines = defs, libtype=['core', 'intern'], priority = [5, 25] ) diff --git a/source/blender/src/blenderbuttons.c b/source/blender/src/blenderbuttons.c index e15ef3fd898..f29397b2156 100644 --- a/source/blender/src/blenderbuttons.c +++ b/source/blender/src/blenderbuttons.c @@ -1,2181 +1,2139 @@ /* DataToC output of file */ -int datatoc_blenderbuttons_size= 69599; +int datatoc_blenderbuttons_size= 68242; char datatoc_blenderbuttons[]= { -137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144, -206,103, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167, -147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0,154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,216, - 5, 19, 11, 8, 1, 11,126, 22,156, 0, 0, 32, 0, 73, 68, 65, 84,120,218,236,125,121, 92, 84,229,254,255,251, 57,179,179,239, -168,184,128,138,251,130,224, 26,106, 80,168,201,215, 52, 21, 48,179,237,214,189, 78,150,173,150,102,117,111,245,203, 43,106,218, -170,233,216,162, 89,106, 9,106,120,115, 5, 29,212,144,220, 21, 75, 19, 5, 17, 65,144,109, 96,134,217,207,156,231,247,199,204, -208,128,192, 44,160, 81,205,251,197,188,152,115,230,204,123,158,115,158,229,253,249,124,158,141, 68, 69, 69, 81,184,225,134, 27, -110,184,225,134, 27,127, 43, 48,238, 71,224,134, 27,110,184,225,134, 27,127, 31,156, 57,155, 5, 0, 32,238, 8,128, 27,110,184, -225,134, 27,110,184, 35, 0,110,184,225,134, 27,110,184,225,134,219, 0,112,195, 13, 55,220,112,195, 13, 55,220, 6,128, 27,110, -184,225,134, 27,110,184,241,151, 0,223,246, 96,222,188,121,196, 85,162,181,107,215,222, 54,150,192,205,231,230,107, 5,116,237, -218,181,127, 88,250,178,179,179,105, 92, 92, 28,113,231,199,159,151,239,220,185,115, 46, 23,190,168,168, 40,184,243,195,205,247, - 87,230,115,218, 0,248, 59, 67, 42,149, 54,122,128, 50,153,140,116,228,116,174, 91,183, 14,132, 16,226,206, 57,215,242,120,246, -236,217, 72, 79, 79,111, 56, 78, 74, 74,250, 75, 60,203, 61,123,207,180,218, 16, 36, 78,142,254, 75,151, 25,137,255, 78,136,117, -189, 17, 1, 3,234,177, 23,249,218,183, 58,108, 89,236,168,109,140, 27,127,211, 8,192,221, 40,172,123,246,236,137,203,200,200, -144, 91,143,167, 77,155, 22,159,152,152,152,221, 17, 30, 6,165,230,182,179,163,234,170, 84, 42,165, 69, 69, 69, 0,128,240,240, -112, 0,248, 83, 52, 34, 77,141, 43,139,129,213,162,103,238, 40,239,214,173, 91, 29, 54,212,164, 82, 41,221,182,109, 91,195,241, -206,157, 59, 49, 97,194,132,134,227,244,244,116,250, 71, 25, 1, 49, 49, 49, 20, 0, 78,159, 62, 77,218,227,186,140, 31,100,173, - 24, 0,178, 54,231, 95, 88, 68, 55, 0,192, 45,157, 14,172, 86,111, 62, 89,171, 4, 0, 36, 39, 39, 35, 33, 33,161,197,244,173, - 79, 88, 79, 35,203, 34,157,250,253,248, 95,227, 29,200, 23, 9,252,159,189, 0, 93,198, 78, 40, 20,211,161, 0, 16, 45,121, 31, -111, 73, 78,163,155, 24,168,212, 21,224, 45,109,138, 83,191,155,149,149, 21,151,150,150, 38,183, 61,151,156,156, 28,159,144,144, -144,221,145,234, 86,123,181, 1,127,134,251,189, 19,120,231,141, 23,136,151,192,151,232,197, 66,170,175,213, 50,245, 90, 37,247, -193, 39,171,255, 22,179,227,236, 26, 0,123,246,236,137,179,254,111,171, 80, 91, 27,146,119,183, 45,129, 87, 55, 95,212,223,168, -195,219, 41,111,201, 51, 50, 50,224,182,134,237, 67, 38,147,145,240,240,112, 90, 84, 84,132,162,162, 34,236,219,183,175,195,122, - 18,214,188,150,201,100, 68, 38,147, 9,164, 82,169,113,197,138, 21, 39, 1, 96,225,194,133, 35, 90,251,238,244,233,211, 27,222, -179,172, 9, 6,163, 30, 6,189, 1, 6,131,249,197,178, 44, 22, 46, 92,232, 84, 90,108,197,191, 57, 76,152, 48,225, 15, 53, 2, - 28, 49,126, 98, 98, 98,236,114, 36, 78,142, 38,174,136,188,195,240,243, 65, 94,225,119,144,160, 43, 76,200, 65,197, 23,103,112, -190,160, 26, 51,150,109,112,232,235,145,101,145, 14, 10,186, 25,242,129,114,187, 13,177, 36,241, 45, 4, 76,123, 26,165, 47, 69, - 3, 90, 69,195,249, 51,218,215,112, 6, 0,180,192,120, 73, 50, 14,250,159,134, 31,128, 24, 69,140,195,229,183, 41,210,210,210, -228,105,105,105, 29,162,189,178,166,177, 61,218,128, 63,195,253,182, 55, 54,173, 89, 75, 30, 13,139,224,191,144,244, 56, 47,164, -127, 24,195, 39, 33, 68, 83, 87,199,137, 17,106, 98,186,116, 53,233,110, 94, 51, 57,248,236,110, 58,209,134,119,113,128,111,129, - 19,124,171,238,168, 1,144,145,145, 33,223,246,239, 55,144,242,222, 82,121, 98, 98, 34,105, 75, 1,179, 10, 63, 0, 84,105,170, -129, 64, 96,241,193,119,160, 44, 84, 64,250,175,142, 37,100, 45, 85,136, 63, 58,141,182, 70,192, 3, 15, 60,128,162,162, 34,132, -135,135,119,184,103, 39,151,155, 29,137,248,248,120, 42,147,201, 24,153, 76, 22, 38,149, 74, 75, 87,172, 88,113,218, 81, 30,150, -101, 97, 48, 24, 27,132,223, 86,252, 79,157, 58,133,225,195,135, 59,149,174,148,148,223, 61,192,217,179,103, 35, 51, 51,179,145, - 1,208, 30,101,197,149,124, 56,125,250, 52,201,206,206,166, 19, 39, 78,188,237,179, 3, 7, 14, 96,235,214,173, 13,199,173,141, - 91,184,205,120,111,199,238,128,176,136,110, 40, 85,212, 97,199, 51, 51, 17, 72, 98, 81,240,249,171,232, 57,189, 39, 50,157, 16, -127, 43,230,206,157, 75, 1, 96,253,250,245,109, 46,179, 97,219,114,160,185, 94,143, 82,105, 68,171,215, 93, 16,103,225,221,193, -183,144,122,225,205, 54,229,103,123,136,110,123,114,180, 71, 36,224, 78,223,111,123, 33, 39, 39,199, 3,192, 61, 0,188,108, 78, -215, 2,200,139,141,141,173,113,148, 71,203,105, 25, 67,149, 94, 48,121,234,116,177, 2, 70,177, 64,192,231, 43,117, 98, 70, 40, -212,114, 60, 31, 79,214, 32, 49, 26,249,229, 55,245, 98,158, 72,167, 51,233, 77, 82,169,148, 52, 55,102,196, 22,181,181,181,255, -181,190,207,207,207,175,242,244,244,100,212,106, 53,103,123,205,200,145, 35, 63,116, 52,141,148, 82,187,194, 78, 8, 89,208,214, -103,202,183,231,253,247,233,211, 7,145, 94, 62,104, 75, 20,192, 86,252,171, 52,213, 72,189,255,157,134,207,254,145,241, 44, 16, - 2, 76, 95,145,226, 84, 33,107, 73,160,219, 75,164,111,220,184, 1, 0,232,214,173, 91,163,247,214,223,181, 87, 32,238,100,136, -207,214, 8, 48, 26, 89,172, 91,183,238,142,121, 1,206,114, 54, 17,127,219,239,223,148,201,100,254, 82,169, 84,225,176,248, 27, -141, 48, 24,244,208, 27, 12, 48, 54, 17,127,202, 57, 23,161, 75, 73, 73,193,169, 83,167, 26,142, 87,173, 90,133,164,164,164,134, -227,244,244,244, 54, 27, 59, 54, 6, 79,155,203,159,173,240,207,158, 61, 27,195,134, 13,115,137,167,189,186, 3, 74, 10,139,161, -222,249, 31,120, 61,245, 49,194, 34,186, 33, 52, 80,130,194,157,133,102,241,247,243, 49,119, 1, 8,120, 14,113,181,135,240, 3, - 64,159,139, 87,113,227,237, 37,208,166,109,108, 61, 66, 32,145, 64,167,211,161,160,160, 0, 21,186,203,232,131,176, 22,175,205, -202,202,138,107,173,236,203,100, 50, 98,173, 39, 89, 89, 89,113,206,132,199,109,163, 98,214,250,106,123,206, 89, 71,160, 37,225, -118,166, 45,104,238,126, 51, 51, 51, 41, 33, 4, 9, 9, 9,164, 45,247,107,197,211, 79, 63, 77,191,252,242,203, 54,229,121, 78, - 78,142, 47,128,233, 7, 15, 30,252, 15,199,113,122, 27, 17,228,243,120, 60, 79, 0,255,140,141,141,221, 99,143, 39,191, 48,159, - 47, 17,138,197, 2,129,200,147,225, 19, 31,202, 19,121,112, 60, 30,159, 35, 12, 56,194, 55, 81, 30, 79,207,227,136, 78,205, 51, -105, 60,133, 2,194,235,213, 77, 39,158, 26,194,161,216,126, 26, 21, 10,133, 82,163,209,176, 0,160, 86,171,185, 55,222,120,163, - 65,240,151, 46, 93,250,114, 91,203,251,132, 9, 19,158,177,190,207,204,204, 92,215, 30,117,136,177,231,253, 47,153,149, 4, 93, -101, 37, 94, 29,216, 15,182,125,247, 14,123, 33,150, 46, 4, 91,241,159, 54,109, 90,188, 76, 38, 35,211,166, 77,139,223, 48,237, - 51,115,100,177,111, 80,163,235, 29,193,194, 53,249, 88,184, 38, 31,207,173,188,132, 39,222,251, 5, 51, 22,159,107,243, 3, 41, - 41, 41,113,200, 48,184, 91,226, 95, 84, 84,212,162, 48,135,135,135,195,104, 48, 96,212,200,145,109,254, 29,107,152,124,219,182, -109,144,203,229, 13,175,214, 12,173,150,196, 48, 62, 62,190,169,248, 55, 24,202,142, 52, 76, 44,107, 50,123,254,122,115,232,191, -169,248,155, 76, 38,168,181,106,167,238,209, 26, 49,104, 26, 53, 72, 79, 79, 71,122,122,122, 35, 99,192,169,251,205,110,220, 30, -202,179,179,157,122,102,173,137,255,236,217,179,177, 98,197,138, 6,241, 23,240, 5, 78,241, 36, 78,142, 38,150, 46,152,102, 95, -206,112,105, 81,140,250,233,163, 64,211, 94, 69, 73, 97, 49,232,244,254,191,123, 43,105,175,130,223, 57, 24,240,243,187,171, 30, -161,186,170, 0,218,180,141,160,148,226,194,133, 11, 24, 63,126, 60, 36, 18, 73, 35,225,247,247,247,135, 86,171,133, 86,171, 69, -105,105, 41, 30,209,190,128, 47,252, 95,106,145,211,218, 7,222,218,243,177,126,214,180,191,220, 81,225,110, 47,103,197,250,221, -166,226,111,207, 65,106,237,126, 51, 51, 51,105,122,122, 58,210,210,210,144,149,149, 69,219,122,191, 79, 63,253, 52,229,243,249, -120,250,233,167, 93,174, 19, 57, 57, 57, 98, 0,255,202,202,202,122,227,189,247,222, 59, 78, 8, 9,183,190, 0,116, 13, 12, 12, -244, 56,116,232,208,218,156,156,156,241,173,241,152, 40,199,227, 17,129,200,192, 82, 31,189,222, 24, 98,226,184,174, 38,142,139, - 48, 17,210, 29, 60, 94, 32, 33,196, 15,132,231,195, 81, 4, 80, 3,231,167,212, 26, 61, 67,124, 88, 30, 51, 82,229, 80, 30,105, - 52, 26,182,169,215,223,209,193, 56,226,253,107,202,203, 48,121, 88,180,211, 2,109, 53, 34,222,221,182, 4, 0, 26,196,223, 26, - 69, 72, 76, 76,204,182, 26, 1, 37,202,155,136, 94, 56,218, 41, 35, 67,173, 53, 65,173, 53,161,172, 90,143,210, 74, 29,110,220, -210,185, 36,124,214,202, 98, 79,252,255, 40,180,100, 4, 0,128,206,160,135, 78,167,115,153,219, 42,218,214, 62,242,224,224, 96, - 91,111, 22,142, 54, 38, 77, 61,225,150, 66,137,142, 52,122, 6,163,222,236,249,235, 13, 48, 24, 27,139,191,209,104,132, 90,173, -134, 74,169,250, 67,243,196,108, 48,165,217, 6,228,172,127,216,182, 45,205,101, 35,192, 86,252,173,194,207, 48, 12,196, 98, 49, - 60,189, 60,218,148,230, 61,123,207,208,150, 94,246,190,187,111,241, 59, 8, 68, 44,216,132,231, 1, 0, 94,185, 87,113,190,160, -218,108,176, 37, 60, 15,227,133,119,129,170,106,167,210, 51,119,238, 92,106,237, 14,112, 5,158,168, 2, 0,108,220,184, 17, 25, - 25, 25,120,255,253,247,113,226,196, 9,232,245,122, 84, 84, 84, 88,189,178,134,235,195,194,194,160, 5,192,195,181, 63,164,188, -180, 84,238,155,122,243,174, 26, 20,205,117, 11, 56,203,103, 27, 9, 75, 75, 75,107,211, 61, 91,197, 31, 0, 92, 53, 2,114,114, -114, 58, 89,196,127,238,215, 95,127,125,241,173,183,222,122,104,203,150, 45,232,211,167, 15, 0,160, 71,143, 30,168,171,171, 19, -189,251,238,187,167, 15, 29, 58,244,109, 78, 78, 78,120,179, 68, 4, 0, 71, 9, 56, 86,108, 50,177, 1, 38,214,212,213,104, 50, -246,230, 49,164,139,144,207, 8,196, 2,158,150,239, 33,172,245,244,230, 41,121, 98,202,138,121, 60, 79, 62,107,240,185,118,230, -172,232,177,224,143,236,166, 59, 63, 63,191, 74,173, 86,115,205,133,249,135, 14, 29,122,217, 96, 48,180, 91, 89, 26, 58,116,104, -187,113,241, 91, 19,238,207,231, 62,253,187,216,150,220,192,171, 3,251, 97,101, 70,134,211, 99, 1,172,222,191, 85,244, 27,121, - 41,137,137,217, 25, 25, 25, 0,128,192,193,157,156, 74,124,189,214, 4,149,134,133, 82,205,162,174,158, 69,173,138,117,250, 1, - 52, 55,242,223,214,203,183,125, 95, 88, 88,136,218,218,218,187,214,104,172, 91,183, 14,225,225,225,176, 14,250,179,237,235,151, - 74,165,116,221,186,117,208,105,181, 46, 27, 0, 82,169,148,110,216,176, 1, 37,165,165, 16,240,120, 8,237,212,169,145,248,223, -127,255,253, 72, 73, 73,113,168,113,146,201,100, 36, 62, 62,190,145, 17,208, 52,146,225,232, 88, 5,131,222, 0,131, 94, 15,163, -209, 0,150, 53, 53,136,191, 94,175,135, 70,163, 65,125,125, 61, 84, 42,231, 13, 0,219, 46, 0, 43, 92,245,252,183,165,109, 3, - 40, 80,101, 17, 26,106, 46, 68, 32,148,154,141,128,180, 52,164, 36, 39, 59,221, 29,208, 84,252, 5, 2, 1, 68, 34, 17,196, 98, - 49,196, 98,177, 75,247,221,168, 94,183,208, 37, 96,175, 75,107,198,186,237,160, 83, 35,112,107, 76, 52, 2, 17, 11,201,204, 79, -193,150, 85, 2,126, 62,224, 87,111,197,143, 31,157, 6,120, 60,167,210,210,214,174, 0, 53,207,220,166,164,166,166,162,178,178, - 18,107,215,174,197,208,161, 67,241,222,123,239, 33, 58, 58, 26, 90,173,182,169,135,102, 53,169,239,170,240, 59, 42,208,174,118, - 7,180,100, 72,184,194,147,156,156,220, 32,252,174,212,141,230,196,191, 65,108,248,124,176, 44,235,108,119,128,119, 94, 94,222, - 39,243,230,205, 59, 50,120,240, 96, 31, 0,120,231,157,119,144,159,159, 15, 0, 24, 61,122, 52,118,236,216,129,177, 99,199,122, - 62,242,200, 35, 5,217,217,217, 89, 60, 30,239,145,219, 27,122, 32, 32, 48,128, 43, 44, 44, 96,179,229, 7,247,246,238, 29,153, - 29,209, 35,252, 34,207, 91, 82,193, 35, 66, 53, 35, 18,104, 24,177,135,202,192,231, 25, 64,141, 60, 78,108,244, 86,149, 86,123, -157, 56,116,110,100,144,127,232, 14,187,198,168, 77,159,255,206,157, 59,159,152, 62,125,250,215,214,176,191, 82,169,100,132, 66, - 97,155,203, 82,123,133,253,237, 70, 0,172, 94,254,240, 94,145,208, 85, 86, 66, 93, 98, 22,193,241, 22,239,208,217, 40, 64,225, - 47, 87,111,227,110,238,184,250, 66,185, 83,137,111,171,248,219, 10, 63,165, 20,221,186,117,107,244,153,209,104,108,120,213,214, -214, 66,173, 86,163,166,166,230,174, 53, 30,214,121,254,251,246,237,107, 20, 9,176,138,255,144, 33, 67,160,211,105, 27, 26, 58, -106,181,102, 28,108,152,214,124,182, 6, 70,163, 17, 93,195,194, 96, 52,153,154, 21,127,103, 26, 18,139, 17,112,155, 87, 98,157, -186,216, 90, 36,227, 54, 3,192, 96,108, 16,255,147, 39, 78, 66,163,213, 66,165, 82,161,174,174, 14,181,181,181,141, 60, 59,103, - 97,237, 6,112,181,223, 31, 0,170,171,170, 81, 93, 93,133,170,234, 26, 84, 85, 87,163,186,186, 26,213, 85,102,143,180, 95,255, -254,168,177,188,119,214,251, 7,128, 97,195,134,253,238,245,123,122,194,203,203, 27,222, 94,222, 80,169, 84,241,109, 41, 79,173, -117, 9,216,251,110,193,251,115, 33,152,249, 41, 2, 17, 11,126,238,167, 48,110,127, 30,240,243,193,174,103,147,112,125,215, 53, - 60,184, 98, 19,192,191,203,203,138,232,174, 67, 18, 38,129, 90,173,134, 78,167,131, 70,163, 65,110,110, 46,150, 45, 91,214,236, -229, 30, 30,214, 8,202, 85,167,197,219, 85,175,218,246,249, 54,125,222, 45, 29,183,197,200,104,174, 91,192, 25,158,132,132, 4, -146,156,156,140,164,164, 36, 76,152, 48,193,229,200,196,151, 95,126, 73, 88,182,113,155,204,178, 44,156, 29, 11, 16, 27, 27,123, - 37, 57, 57,121,232,150, 45, 91,198, 31, 61,122,212, 59, 33, 33,225,132, 85,252, 45,142, 42, 68, 34, 17,189,126,253,186, 96,239, -222,189,125,253,253,253, 79,198,198,198, 22, 52,199, 85, 87, 91,199, 69, 70,244, 81,141, 30, 61, 58,233,226,197, 95,239, 83,170, - 85,157, 40,107,100,193,192,200,234, 25,189, 94,175,215, 42, 81,174,228,244, 58, 85,105,113, 57,251,227,238, 61,203,131, 2,131, - 43, 12, 6,141, 93,247,189, 57,239, 95,161, 80,240, 1,192,199,199,167,195,118, 11, 48, 45,121,255,219,254,253,134,217,106, 46, - 47,107,244,153,179, 99, 1,166, 77,155, 22,191,230, 95, 31, 3, 48, 15,248,203,200,200,144,219, 78, 45,204,200,200,144, 79,248, -230, 33, 0,192,153, 21, 63, 99,218,180,105,241,119,235,230,109, 43, 73, 73, 73, 73,131,183,111, 21,125,155,204,133, 74,165,130, - 78,167,179,105, 68,238, 94, 26,159,121,198, 60,246,195,200,178,184,120,241, 34,206,158, 57,131,161, 67,134, 66,167,211, 65,171, -213, 65,167,213,226,219,111,190,129,245, 58, 71, 42,250,170, 85,171, 48,160,255, 0, 24,141, 70, 92,185,114, 5,172,209,128,210, -146,210,118,125,166,214, 99,203,154, 5, 8, 15, 15,119,168, 97, 50, 24,245, 96, 77,230,176,255,241,227, 63, 67,173, 85,163, 94, -165, 68, 93, 93, 29, 20,181,181, 80, 40,106,218,100,136, 89, 35, 1,109,241,112,142, 28, 57, 2,149, 74, 5,149, 74,105,249,175, - 66, 80, 96, 32,250,245,239,143,223, 46, 93,194,225, 35, 71,156,230,180,122,255,124,190, 0, 30, 30, 30,240,242,242,130,183,151, - 23,188,188, 60, 80,163,168,137, 7,144,125,167, 67,253, 45,225,124, 65, 53,140, 23,222, 69, 53,114, 64, 18, 87,130,196,254, 7, - 5,239,207,197,212, 21, 95, 67, 44, 96, 0, 1,223,252,114, 1,174,118, 5,148, 78,249, 12, 1, 91,167, 64,163,209, 32, 32, 32, - 0, 10,133, 2, 10,133, 2,199,142, 29, 67, 89, 89, 89, 67,152,184,225,250,210, 82, 60,235, 47, 65,144, 71,101,107, 30,112,188, -173,168,218, 14,146,179,190,183,126,102,189,214, 21,239,220,209,238, 1, 71,197,223, 85,207,191,185,251, 77, 72, 72, 32, 19, 38, - 76, 32,109,185,223,166, 70,128, 43,226,111, 69, 80, 80, 80,222, 67, 15, 61,244, 72,106,106,106,223,243,231,207,199, 74, 36, 18, -222,212,169, 83,137, 72, 36, 2,199,113, 36, 49, 49, 49,239,197, 23, 95, 28, 50,104,208,160, 93,255,252,231, 63,159, 48,153, 76, -213,173,196,188,185, 95, 47, 93, 57, 57,104,240,144, 71, 79,158, 56, 49, 99,215,238,255, 45, 61,117,226, 68,167,139,249,191,137, -175,148, 22,208,111, 63,254, 94,146,186,234,253, 1, 89,187,119,175,234,221,171,247,143, 94,161,158, 71, 98, 99, 99, 77,112, 48, -229, 9, 9, 9, 56,121,242,100,212,186,117,235,222,213,233,116,130,247,222,123,239,131, 93,187,118,205, 46, 45, 45,189,187,194, -209,214, 46,128,192,107, 69,168,177,132,254,109, 49, 62, 56, 24, 43,241,155,227, 94,135, 37,196,255,219,233,139,240,235, 27,132, - 9,223, 60,132,140,199,126,144, 91,195,254, 86,241,183,122,255,206,204, 50,216,145,218, 62, 35,241, 9, 33,184,116,233, 18,172, -133,181,105,152, 85, 32, 16, 64, 32, 16,160,178,178, 18,137,137,137,119, 61,147,172,163,254,215,173, 91,135,145, 35, 71, 66,167, -215, 67,171,211, 66,103, 25,220,164,213,153,187, 1, 86,175, 94,109,183, 49,145, 74,165,116,197,138, 21, 48,153, 76, 56,125,250, - 12, 4,124,115,216, 54, 50, 50, 18,215,138,138, 80, 90, 90,138,173, 91,191,195,236,217, 15,227,224,193,131,212, 54, 18,208, 90, - 3, 36,147,201,132, 0, 88,169, 84,202, 53,231, 1, 57, 51, 85,209,234,249,231,230,230, 66, 93,175,105, 48,192,148, 42, 37,148, -202, 58, 40,149,245, 46,135,194,173,222,191,101, 37, 64,151, 12,129,217,179,103, 55, 58,142, 8, 15, 71,191,254,230, 65,113,191, - 93,186,132,107,150,136, 71,211,235, 28,193,152,123,198, 64, 36, 20, 65, 34,145, 64, 44, 22, 67, 36, 18,161,188,188,220, 97,241, -183, 23,234,119,117,141,128, 25,203, 54, 96, 7,128, 7, 82,255, 15, 52,237, 85,144,148, 85, 56, 95, 80, 13, 18,224,143,171, 37, - 74,179,247,239,100, 23, 64,211,174, 0,167,167, 7,106,181, 0,175,160, 73,120,223, 44,244, 70,163, 17, 95,124,241, 5,198,143, -255,125, 92,216,193, 39,195,128, 10, 13,250,238, 81, 32, 42,184, 71, 75, 13,120,118,147,190,111, 57,208,208,252,203,155, 94,235, -138, 96,183,214,111,239,170,231,239,170, 33,113,167,239,215, 98, 4,180,121, 22, 64,120,120,248,214,177, 99,199, 6,159,203,203, - 75,209,106,181, 67,228,242, 67, 18,145, 88,196,103, 8,131, 67,135, 14,121, 15, 24, 48, 96, 83,114,114,242,127, 42, 43, 43,237, -122,235,179,103,205,228,126,220,251,227,225,161, 67,135, 45, 52,176,250, 7,174,230, 95, 89,202, 21, 21,176, 0,168, 24,140,113, -112,239,190,105, 33, 33,193,123,120,124,225,183,255,125,107,185,225,219,141, 27, 44,125,124, 45, 99,228,200,145, 31, 38, 36, 36, - 0, 0, 42, 43, 43,145,149,149,229,243,213, 87, 95, 45, 5,128,147, 39, 79,142, 28, 56,112,224,190, 63,133, 1, 96,245,206,239, -255,118, 75,235, 94,134, 19, 83, 2,173,214,111,244,194,209, 8, 28,220,169, 65,244,109, 67,255,103, 86,252,236,148,229,218, 94, -115, 82,173,105,235,223,191, 63, 46, 92,184,208, 72, 88,106,107,107, 11, 0,244,106,238, 59,174,174,189,220,214,116, 54, 61,255, -237, 55,223, 66,167,211, 65,111,208,195, 96, 48, 96,197,138, 21,176, 39,254, 86,112,156, 9, 98,137, 23,180, 90, 29, 46, 93,188, - 8,190, 64, 0,163,193, 0, 15, 79, 15,108,221,186, 21, 60, 30,207, 58,119,190,213,123, 93,177, 98,197, 62,169, 84,106,144,201, -100, 33,214,116, 54, 89, 7,192,169,208,230,194,133, 11,145,147,147,131,250,250,122,212,171,213, 80, 41,149, 22,241, 87, 66,165, - 84,161, 94, 85, 15,181, 77,131,239,200,179, 27, 62,124, 56, 61,117,234, 84,131,247,223,220, 52, 64, 71, 23, 1,138,139,139,187, - 45, 47,172,162,127,246,236,217, 6,111,222,209,123,142,137,137,161,214, 69,126,188, 60,188, 32,150,136,161, 82,169,226,109,250, -176,157,106,120,239,212, 98, 64, 86, 35, 96,122,234, 87,160,219,129,160, 39,101,200,126, 41, 9, 99,151,111, 6, 4, 2,120,138, -219,214,207,217,212, 16, 0, 0,121,142,189, 96,227, 45, 12,222,231,129,242,255,105,160, 88,242,251, 89,163,209,136,113,227,198, - 1, 0,194,252, 37,248, 73,214, 13,239, 47,187,129,207,206,104, 91,101,179,245,248, 1,243, 64, 56,107,195,222,116, 80,156,179, -211,226,108,199,239,180,213,243,111,174, 77,112,133,235, 78,222,175,173, 17,208, 30,229,111,224,192,129,159,168,148,170,189, 35, - 98,134,143, 84, 41,149, 1,172,137,213,135,134,134, 86,134,133,133,149, 43,149,202,243,149,149,149, 14, 55, 10, 83, 38, 79,225, - 0,108, 61,122,228, 68,110,236,216,177, 63, 72, 36, 18, 95, 2,202, 17, 66,192,113,180, 78,171, 86,200, 47,231, 21,171,190,221, -184,193,161,118,222,250,204, 0,243, 64,234,166, 3,245,150, 45, 91,246,159, 63,133, 1,144,152,152,152,221,150, 5,127, 28, 41, -172, 86, 67,192, 42,252,237, 41,232,109, 73,219,224,193,131,113,242,228, 73, 84, 86, 54,132, 8,123, 1, 64,117,181, 57,162,244, -216, 99,143,253,161,153,213,244, 25, 81, 74,233,163,143, 61,138,213,171,215, 88,250,204, 89,248,250,250, 18, 71,191,111,133, 68, - 34,182,242,153,189, 41,181,198,246, 59, 0,236,110, 54,209,127,197,138, 21, 87,164, 82,105,133, 76, 38,227,217, 14, 8,180, 76, - 11,116,184,161,179,206,125,143,141,141,109,247,103, 55,124,248,240,166,123, 1, 52,124,238,236, 10,128, 50,153,140,100,103,103, -211,173, 91,183, 54, 90,168,199,202,237, 74,121,142,139,139, 35, 70,214, 8,163,202,216,174,247,222, 90,232,223,217,189, 1,102, - 44,219, 0,216, 44,252,115,239, 27,191,143, 75, 82,183, 83,122, 27, 69, 0, 6,182,110,124,150,198,150,162, 20, 64,244,251,254, - 88,114,186, 15,130, 1, 84, 22,168,209,187,119,111, 0,192, 39, 75,252, 49,105, 68, 48, 34, 38,229, 59,244,219,206, 76,117, 75, - 75, 75,147,183,182,236,177,189,246,166, 61,218,188,182,114,221,141,251,109, 79,140, 30, 51,250, 10,128, 43,183, 69,172, 3, 3, - 93,226, 27, 55,126,100, 17,154, 29, 21, 26,134,222,125, 6, 57, 99, 72,181,235,125,182,199, 34, 63, 46, 25, 0,119, 90,192,246, -236,217, 19,151,177,162,227,237, 5, 96,173, 72, 35, 70,140,192,158, 61,123,116, 22,209,231, 0,120,220,137,200, 67, 59, 21, 18, - 34,147,201, 26, 60,251,214,196,255, 78, 98,225,194,133,182,241,212,134, 6,219, 58,141,208, 25,111,231, 78, 62, 95, 91,238,236, -236,236, 54, 47,251, 27, 23, 23, 71,226,226,226,218,156, 46,123,107,251,183, 7,218,210, 37,176,104,209, 34, 20, 22, 22,182, 91, - 90, 28, 89,222,215, 89,156,121, 77,129, 51, 48, 15, 12, 29,159, 44,193,254,227,125, 16,234,225,133, 95, 79,221, 66, 95, 7,197, -223, 94,249,235,168,203,225,182,199, 90, 2,127,166,251,237,128,207,191, 75, 59,243,173,186, 91,105,191,235,187, 1,222,169, 8, - 67,123, 26, 1,137,137,137,226, 63, 89, 1, 36,127,240,111, 91, 87,168, 97,173, 6,128,187,241,232, 56,104,107,151, 64,207,158, - 61, 73,207,158, 61,219,165,189,113,102, 31, 0, 87,113, 36, 77,139, 35,105,249,238, 58,235,134, 27,246,156,200,168,168, 40,234, -126, 12,110,184,225,134, 27,110,184,241,247, 2,227,126, 4,110,184,225,134, 27,110,184,225, 54, 0,220,112,195, 13, 55,220,112, -195, 13,183, 1,224,134, 27,110,184,225,134, 27,110,184, 13, 0, 55,220,112,195, 13, 55,220,112,227, 47,129, 70,179, 0,230,205, -155,231,242,200,212,230,230,137,187,249, 58, 30,223,220,185,115, 93,226, 27, 54,108,216,109,124,103,207,158,117, 57,125,205,241, -253, 89,242,195,217,103,184,126,253,250,187,146,190,246,206,143,187,153,191,246,166,137, 58,251,252,218,155,207,221,190,184,249, -154,225,235, 10, 64, 1, 64, 8,160,182,163,165,207,105, 3,192,141,191, 62,214,175, 95,239,126, 8,127, 51,248,249,249, 49, 48, - 79,207,228,215,213,213,113,148, 82, 83, 71, 74,159,117,223,249,172,172, 44,218, 30, 11,205,180,215, 74,123,110,220, 57,236,218, -181, 43,110,234,212,169,217,127,242,219,176,174,125, 37,113,214, 0,232,144, 17, 0, 55,254,122,160,148, 54,218,234,216,213, 8, -192,218,181,107,237, 94, 51,113,226,196,184,204,204,204, 70, 43,139, 77,152, 48, 33,254,192,129, 3, 46, 85,244,244,244,244,102, -249,146,146,146, 58, 4, 95, 71, 6, 33,132,244, 8, 13, 69, 81,121, 57,173,173,173,181,238,207,224,212, 18,131,182,198,226,169, - 29,171, 75, 8,193,115,178,189,121, 25,210,201, 67,190,161, 20,202,245,251,242,158, 91, 52, 99, 36, 1, 67,249, 10,149,142, 14, -159,249,188,211, 91,114,102,101,101,197, 89,151,156,181,252,119,105,185,217,166,226,111, 45,247,109,221,104,167,185,239,186,202, -217, 30,124,109,221, 50,216,149,104,201,157, 16,255, 61,123,246,200,167, 78,157,250,103, 55,206,172,251,176,223,209,174,244,119, -222,120,129,241, 18,248, 50,122,177,144,211,215,106,249,245, 90, 37,251,193, 39,171,219,101,135,193,219, 12,128,246, 20, 8, 87, -185,156,229, 35,132, 48, 22, 43, 76, 75, 41,229, 58, 90,250,218, 75, 96,219,195, 0,176, 54,234,182,105, 37,132,232, 41,165,162, -182, 68, 10, 8, 33, 20, 0, 86,173, 90,213,104,199,176, 5, 11, 22,200, 9, 33,160,148, 18,103, 27, 37, 0,224,190,247,111,116, -158,153,149, 41,207,204,204,116,186, 1,108, 79,190, 63, 67, 20,133, 82, 74,227,123, 69,208,248, 94, 17, 0,128,114, 3, 59,167, -147,144,191,217,250,249,111,202,122, 81,153, 3, 27,167, 0,192,201,237,159,230,115, 28,194,238, 25, 19,228,243,193, 75, 99, 15, - 12, 25,226,119,253,185,229, 35,255, 11, 0,183,234, 52,255, 39,224,147,255, 1,228,226,220,185,115, 7, 58,251,108,154, 46, 69, -219,150,229,102,109,197,191, 61,140,128,150,190,227,170, 88,182, 7, 95,114,114, 50,210,210,210, 28,186, 39,103, 34, 42,173,241, -181, 87,100,198, 86,252, 57,142,195,250,245,235,177,121,243,102, 58,103,206, 28,226,100, 30, 11,101, 50, 89,187,172,151,189,120, -241,226,185,169,169,169,174, 86,104, 31,139,231,175,190, 19,117,120,211,154,181,204,163, 97, 17,226, 23,146, 30, 23,134,244, 15, -227,243, 73, 8,163,169,171, 99,197, 8, 53, 48, 93,186, 26,116, 55,175, 25,218,250, 27,124, 71, 26, 55,169, 84, 26, 12, 96, 56, -128, 83, 50,153,172,178,131,121, 58, 62, 0, 18, 0, 76, 7,176,147, 16,146, 69, 41, 85,182, 3,239,119,148,210,135, 93, 21,216, -142, 2,134, 97, 90, 53, 82, 8, 33, 35, 1, 8, 9, 33, 33,148,210,138,150,174,107,205, 64, 33,132,208, 23, 95,124, 17,221,187, -119,191,109,187,208, 85,171, 86,197, 23, 23, 23,203, 9, 33,212, 81, 35, 64, 42,149,210,141,207,123,226,241,177,183,111, 46,195, -125,239,143, 77, 63, 25,240,164,147, 94, 83,123,242,213,213,213,197,189,254,250,235,242,148,148, 20,196,199,155, 87,182, 59,119, -238, 92,220,218,181,107,229,221,187,119, 7,199,113,208,106,181,136,139,139,195,196,137, 19,237,114, 10,235,212,113,125, 95,223, - 38,207,140,238, 26,223,233, 95, 19,178, 1,128, 45,103,227, 46,191,205,202, 77,221,125,160,228, 60,161,208,250,160,194,247,100, -252,211,139, 66,236,122,199,189,186,117,234,212, 93, 40, 41,123,254,185,199,244,161, 18,161, 80, 89,163, 37, 43,190,218,178,249, -141,103, 30,133,191, 68, 66,117, 70, 19,253,247,234,175,244, 0, 72,231,206, 65,252,242,242,106, 38, 42,170,249,157, 53, 71,132, - 28,136,188, 25,230,225, 23,123, 79,240,170, 97, 49, 1,130,141, 27,175,134, 7, 7, 73,170, 62,124,233,248,170,162,235,195, 76, -147, 39,117,206,205,191,162, 42,126,242,241, 94,137,214,114,227, 76, 29,176,221, 32,167, 45, 94,104, 83,241,111, 90, 63, 93,225, -239,136, 17, 0,139, 16, 83,171, 17,144,156,156,108,123,190,145,104,219,110,236,227,170, 81, 97,229, 73, 75, 75,107,115,148,192, - 86,252, 23, 44, 88,128, 83,167, 78,209,159,126,250, 9,115,230,204,113,150,202, 32,149, 74, 5, 50,153,140,109,135, 38,178,124, -241,226,197,211, 83, 83, 83,119,186,240,221, 48, 0, 53, 0,194, 1,156,203,201,201,233, 1,224, 51, 0, 1,182,252, 0, 62,137, -141,141,117,120,207, 5, 45,167,229, 27,170,244, 30,147,167, 78,247, 85,192,232, 43, 16,240, 69, 74,157,152, 47, 20,106, 89,158, -143,167,222, 32, 49,106,249,229, 55, 85, 98,158,168, 86,103,210, 27,164, 82,105,139,245,183,205, 17, 0, 66, 72, 55, 0,159, 3, - 40, 5,240,162, 84, 42,253, 23,165,244,198,221,242, 96,237,136,116, 32,128, 77, 0,110, 2, 56, 6,224, 1, 0, 79, 19, 66, 30, -167,148, 86,183,145,126, 22, 33,100,142,189,254,210,187, 25, 98,191, 67, 24, 13,224, 50,128, 8, 0, 21,196,162,212,142, 26, 52, - 19, 39, 78,140, 3,208, 72,252, 23, 44, 88, 32,183,141, 6, 88, 62,147, 79,156, 56, 49,206, 94,119, 64,122,122,122, 28,128, 70, - 98,205,204, 82,192,214,123,127,124,172, 16, 79,126,170, 70,122,122,122,156,189,240,125,123,243, 1,192,241,227,199,229, 98,177, - 24,185,185,185,141,246, 59, 96, 24, 6,111,190,249, 38,177, 54,118,187,119,239,150, 79,156, 56,209,110, 6,116, 58,126, 81, 78, -197, 2, 12,169, 20,202, 43,126,223,138, 21,132,161, 24,242,166,129, 0, 6, 92, 56,114, 61,238,230,246, 41,114,224, 68,171,141, -112,124,175, 8,218, 93, 40,193, 43,207,206,209,135,122, 9,133, 85, 23,114,136, 39,195,199, 11,227, 34,209,197, 79,130,235,185, - 71,137,214, 64,201,130,185,143, 25,226,123, 69,208,126, 30,222, 40,163, 85,100,216,176, 97,205,242, 5, 5, 9,239, 21, 10, 25, -241,177, 99,101, 47,178, 38,221, 71,161, 93,123, 26,253,130, 4, 68,169,188,234,209, 51,194, 35, 40, 32, 64, 84,201, 81,165,254, -199, 19, 21,234,121,227,254,152, 2,220, 52,236,111, 91, 55,157, 53, 2,172,215,216,142, 35,176,119,157,189,237,183,219,147,207, -214, 8,144,201, 20, 0, 20,144, 74,253,209,156,104, 59,138,150,140, 10, 75, 68,166, 77, 81, 15, 91,241,223,189,123,183,156, 97, - 24, 48, 12,131,113,227,198,225,232,209,163,141,242,203, 81,152, 76,166, 60, 30,143,103,148, 74,165,124,153, 76,214,214,241, 44, -146,234,234,234,239, 3, 3, 3,103,166,166,166,110,119,242,187, 90,152,247,139, 81,229,228,228, 12, 2,176,253,224,193,131,125, - 56,142,179,213, 40,240,120,188,135, 0,100,199,198,198,198,219, 35,204, 47,204, 23, 75,132, 98, 95,129, 64, 20,204,240, 73,103, -202, 19,249,113, 60,158,136, 35, 12, 56,194, 55, 82, 30,175,158,199, 17,149,154,103,170,241, 20, 10, 8,175, 87,183, 58,241,212, - 16, 22,197,119, 46, 2,240, 17,128,131, 22,203,230, 89, 0, 31,173, 95,191,126,166,139,130,237, 15,224, 69, 0, 35, 0, 36, 2, -216, 3,224, 36,128,143, 41,165, 10, 23, 40,143, 88,210,181,150, 82,202, 17, 66, 60, 1, 60, 97, 57, 63,176, 13,134,133,175,229, -173, 39, 0,165, 51, 30,118, 11, 17, 20, 33,128, 55, 0, 44,149,201,100, 6,116, 44,140, 0,144, 3,160, 19, 33,100,171, 37, 79, -190,105,106,208,180,100,160,100,102,102,202,109,195,254, 11, 22, 44,104, 56,182,125,191,106,213,170,120,139, 97,208,106,141,207, -204,204,148,219,134,233,153, 89, 10, 92,217, 99,222,133,145, 73,252,166, 65,180,185,239,253,193,204,202,148,219,219,208,167, 57, - 62,107, 99,198,204,146, 82,103,249, 40,165,113,199,142, 29,195,156, 57,115,240,197, 23, 95,224,204,153, 51,113,209,209,209,217, - 77,175, 17,139,197,242,206,157, 59, 59, 18,171,143,235,124,236, 23, 92,158, 19, 7,175, 47, 46,128,148,105,226,104,103, 15, 11, - 31,177, 92,130, 56,129,174,187, 60,160,115,235, 91,217,198,247,138,160,115,255, 57,203, 16,234, 41, 20, 24,175,158, 18,250, 7, -123, 19,121,153, 18, 51,163,186,161, 95,152, 31,132,181,151, 33, 87,105,209, 77, 32,130, 31,225, 9, 22, 63, 61,135,214, 11, 69, -249,241,189, 34, 40,124,252,154,229, 84,212,170, 2, 70,142,244, 90,165,100, 71, 45,242,246,175, 20,233, 24, 79, 78,226,101,208, - 7, 4, 5, 50, 30,126, 98,190,162,166, 76,164,172, 99, 33,168,211, 19,219, 50,211,154, 65,107,233,247,151,219, 19,206,228,228, -228,120,123,227, 1,154,243,252,155, 26, 2,206, 24, 1,214,207, 90, 19, 99,219,243,246,132,177, 41, 31,221,230,127,123,123,147, -162,128,163,124,173,133,251,219, 34,218, 77,141, 10, 0, 8, 8,200,106, 23,241,159, 55,111,158,185,251,141,227,240,234,171,175, -226,163,143, 62,106, 16,255,181,107,215, 58,205,205, 48, 12, 12, 6,195, 89,161, 80,200,182, 67, 36,160, 6, 0,170,171,171,183, - 7, 6, 6,198,167,166,166,202,157,248, 46, 31, 0,158,124,242, 73, 81, 78, 78, 78,102, 86, 86, 86,167, 37, 75,150,176,111,189, -245, 86, 35, 93, 13, 12, 12,196,161, 67,135,226, 0,164,197,198,198, 38,183, 70,200, 35, 2, 31, 3, 75,187,112,156, 49, 66,200, -227,245,160,132,132, 16, 62,159,240,121,188, 58, 66,136, 22,132,167,228, 40,252,169,129,243, 80,154,140,232,229,195,106,153,145, - 42,174,221, 12,128, 38,125,195, 97, 0,186, 81, 74,173,130,255, 62, 33,228,132, 84, 42, 13,163,148,150, 58,227,193, 18, 66, 30, -179,136,245, 7, 0, 22, 1,120,212, 18, 66, 73, 6, 80, 76, 8,121,150, 82,250,141, 19, 34,253, 31, 0, 87, 41,165,107, 8, 33, - 34, 75,133,103, 41,165,159, 17, 66, 38, 17, 66,254, 67, 41,253,127, 46, 22,138,241, 0, 42, 1,220, 11,224,127,206,124,177,185, - 8,128, 84, 42,125, 10,192,219, 0,202,231,206,157,187,174,131, 69, 0, 6, 90,210, 54, 1,192,100, 0,215,237, 25, 52, 45,193, - 86,240,109, 69,191,233,184, 0,135, 43,186,141,248, 3,192,149, 61,143, 53, 50, 2, 92,225,179,109,204,100, 50, 25,177, 53, 2, - 28,193,225,195,135, 97, 48, 24, 16, 19, 19, 19,255,211, 79, 63,201,139,138,138,228,209,209,230, 45,117, 57,142, 67,106,106, 42, -173,175,175,135, 64, 32,192,140, 25, 51,236,222,183, 46,247, 36, 24, 3,139,218,152,240,120,193, 79, 55,229, 87, 55, 28, 70,175, - 55, 38,155, 69,139,163,200, 75, 21,210,154,122,111,104, 5, 94,152, 48,239,138,253,231,200,240,234, 43, 47,228,250,234,244, 38, -198, 87, 34,162, 73, 81,221,225, 35, 17,144,146,234,122,120, 50,124,164, 12,235, 78,143,255, 90,129,159,255,183, 15, 61, 60,189, -232,121,149,242, 58,128,190, 45,209,229,158,237,242,220,232, 97, 85,135,189,248, 17,172,144,189,213,107,252,152, 20, 47,157,193, -115, 10,207,235, 36,163,172,173,241, 40,186,116, 50,194,104,184, 84, 89, 88,160,246,177,212, 25,187, 66,229,168,119,106, 29, 31, -208, 82,255,115, 75,222,180, 61,175, 82, 42,149, 82, 87, 67,166, 29, 9, 77, 61,127,179,120, 3,105,105,237, 55, 72,176, 61, 60, -127, 74, 41, 88,246,119,141, 30, 59,118, 44,142, 30, 61,234,146,248, 91, 96, 20, 8, 4, 38,142,227,142, 49, 12, 99,108,163, 17, - 16, 98,125, 83, 93, 93, 45, 15, 12, 12,148,166,166,166, 58,186,115, 86, 81, 74, 74,138,207,225,195,135, 83,179,178,178, 58,125, -253,245,215,220, 19, 79, 60,193,223,178,101, 11,222,121,231, 29,228,231,231,163, 71,143, 30, 40, 47, 47,199,187,239,190,107,122, -251,237,183,147, 0, 60, 27, 27, 27,251, 89,139,140, 28,235,107, 2,211,131,112, 24,104, 4, 23,233, 33, 16, 9,133,124,166, 76, - 44,224, 41,121, 18, 97,149, 72,196,171,215,155, 56, 15,190,145, 31, 96, 96,245,166,107,103,206, 42, 30, 11,254, 72,115, 28,174, -233,135,189, 8,192, 36, 0, 57, 77, 6,142,229, 0,152,180,126,253,250,175,156, 16,235, 71, 0,188, 4, 32,188, 73,104, 94, 1, -224, 23, 66,200, 39, 0, 14, 16, 66, 76,148,210, 45, 14,240,121, 0, 19, 92,166, 19, 0, 0, 32, 0, 73, 68, 65, 84,152,107,245, -242, 41,165,250, 38,151, 60, 14,224, 87, 66,200, 74, 74,169,198,149,240, 63,128,175, 44,255,157, 50, 0,154, 10,166, 84, 42,253, - 7,128,231, 44,207,114, 21, 33, 68, 47,147,201, 54,116,132, 6,132, 16,210,219, 18,194,250, 17, 64, 6, 0,107, 62,193,209, 8, -192,223, 13,165,165,165,242, 81,163, 70,129, 16,146, 61,106,212, 40,252,240,195, 15,120,232,161,135,226, 58,117,234, 36,103, 24, - 6,139, 23, 47, 38,150,198, 36,110,235,214,173,114,189, 94,143, 17, 35, 70,180,216,208,141,185,118, 83, 94, 62,170, 63, 64, 72, -246,175,161,166,248,129,231, 2,228, 58, 14,241,230, 46, 0, 96,200, 98, 3, 1,170,161,174,174,139, 59,180,181,183, 92,237,125, - 34,254,225, 39,124,154,245,138, 75, 12,236,202,245,235,183,188, 26, 28, 36, 41,170, 83, 27,124,195,253, 61, 5,201, 67,123,122, - 12, 11, 23, 17,157,198, 4,141,150,195, 85,162, 53,101, 20,149,106, 10,202,235, 77,157,132,226,178,114,131,110,226, 13,189,241, - 3,111,224,149,230, 56,125,252,195,186,106,235,175,116, 25,144,112, 31,115,241,120,217,248,210,223,126,184,209,123,248,220, 16, - 94,255,168,146,179, 71,191,175, 35, 60,159, 17, 28,199,213,220,186,165,181,107, 69, 53, 21,108,123,199, 86,111, 54, 45, 45,173, - 69,193,182, 13,175, 55,141, 4, 56,114,253,159, 21, 9, 9, 9,196,214,235,183,133,109, 8,191, 45,104, 15,158,250,250,122, 57, - 0,240,249,124,188,252,242,203, 56,117,234, 20,126,250,233,167,182,210,234, 1,152,244,122, 61, 91, 90, 90,154, 25, 22, 22,102, -180, 23, 89,108, 5, 42,219,131,234,234,106, 89, 96, 96,224,131,169,169,169,142,180,251,190, 58,157,174,207,194,133, 11,167,206, -155, 55,143, 14, 30, 60,152, 0,104, 16,127, 0, 24, 61,122, 52,118,236,216,129,177, 99,199, 50,143, 60,242, 8,205,206,206, 94, -195,227,241,180, 30, 30, 30,208,104,110,151, 38,142,163,186,108,249,193,244,222,189, 35,139, 35,122,132, 95,225,121, 75,202,120, - 68, 88,199,136, 4,117,140,216,163,194,192,231,105, 64,141, 2, 78,108, 12, 81,149, 86, 7,157, 56,116,238,205, 32,255,208,183, - 92,125,144,173, 70, 0,164, 82,233, 68, 0,155,155,120,181,135, 0,204,153, 59,119,238, 87,142,120,176,132, 16,158, 37,252, 61, -173,165,126,121, 74,105, 53, 33, 36, 5, 64, 6, 33,228,123, 7,230, 41, 63, 2,224, 0,165,180,174, 5,190, 58, 66,200, 1,203, -117, 95, 56, 41,138,247, 1, 8, 4, 48, 31,192, 86, 66,200,125,148,210, 67,174, 68, 0, 8, 33, 73, 0,222, 7,208,131, 82,170, - 38,132,140, 6,112, 93, 42,149,170, 40,165,233,142, 70, 0,164,102, 83,223,145, 70,139,200,172,110,128, 99, 24, 3,224, 4,165, -148, 18,179,219,116, 29,128,154, 16,210,205, 58,206,195,153, 8, 64, 83,143,191, 45,222,127, 67, 88, 62,241,155,134, 40, 64,100, - 27,188,255,223,195,252,191,135,111,165, 82,231,188,127,163,209, 72, 79,157, 58, 5,111,111,111,228,229,229, 81,147,201, 4,165, - 82,137, 75,151, 46,201, 3, 3, 3,209, 36,236,151, 61, 96,192,128,248,109,219,182,201, 71,140, 24,209,124,184,207,104,164,221, - 78, 93,128,208, 59, 12,130,188,106, 26,106,242,134, 74,201,192,116,169, 30, 8,108,188, 35,181,103, 32,155,221,125,248,233,248, -125,219,103,201,129,189,205, 54,118, 87,110,220,120, 45,178, 91, 55,160, 74,251, 42, 0,228,107,149,216, 45, 42,173, 28,112,239, -248,224, 1,134, 60,252,114, 93,129,221,231,110,241, 11, 42,235,125, 0,160,220,160,243,191,161, 55, 38, 23,148,150,238,136, 10, - 14,110,214, 0,184,119, 74, 10,227, 33,156, 56,152, 85,255, 82,220,189,127, 66,159,186, 27,219, 13, 87,127,201,172, 53,114, 94, -183, 42,138,127,174, 80,214,120,142, 0,195,144, 26,149,206, 87, 58, 43,186,155,236,251, 51, 55, 90, 42, 51, 50,153,140,216, 70, - 0,108,189,203,166,225,118,171, 72, 39, 39, 39, 35, 33, 33,129, 52,183,208, 73, 91, 70,227,187,186,112, 74, 71,131,181,186, 75, -165,254,183, 69, 4, 92,141, 42,164,165,165,181,139,248,111,222,188,153, 30, 57,114, 4,116,155, 63, 72,138, 2, 31,126,248, 33, - 40,165, 96, 24, 6,235,214,173,115, 57,178,160, 80, 40,244, 1, 1, 1,241, 71,142, 28,217, 59,126,252,248,201,205,149, 31, 39, -224,103,169,175,115,171,171,171,215, 7, 6, 6, 62, 6,160,102,241,226,197,255, 72, 77, 77,181,231,168,213,237,218,181,171,116, -223,190,125, 95,197,199,199, 63,213,175, 95, 63, 36, 36, 36,208,172,172,172,134,116,100,100,100, 64, 36, 18,225,250,245,235,216, -187,119, 47,233,210,165, 11, 27, 27, 27,251,211,165, 75,151,154, 37,140,140,232, 83,166,213,234,230, 30, 57,114,100,125, 96, 80, -160,210,215,199,167, 24, 66,161,158,213, 51,245, 44, 79, 95,171,227, 43,171, 60,245,158,226,155, 21,149,190,135,246,237, 93, 63, - 96,224,160,247, 13, 58, 77,125,187, 24, 0, 82,169,148, 72,165, 82,107,226, 59, 89, 94,135, 45,211,236, 26,162,160, 0, 22, 16, - 66,186,192, 60,194, 17, 0,154,181,208, 45,162,242, 2,204, 3,244,174, 53,225,105,138,107,150,235, 94, 32,132,124,212, 10, 31, - 1, 48, 3,192,114, 59,124, 95, 3, 88, 68, 8,249,202, 78,250,108, 11, 77, 56,204,227, 29, 98, 96,238,251,127, 19,192,105, 66, - 72, 47, 0, 69,182, 54,134, 3,124, 15, 3,120,218, 34,178, 90, 75, 90,181,150,227,117,132, 16, 33,128,239, 90,227,179,228,197, - 99, 0,230, 57,106, 0, 72,165,210,181, 0,190,105,137,207,194,185, 18,128, 55, 0, 95, 0,187, 44,105, 19,195, 60, 79,252, 23, - 0,163, 8, 33,243, 1,252, 4, 96,119, 75,233, 3,204,243,232, 91,232,235, 71,211,177, 1, 19, 38, 76,176,107, 12, 76,152, 48, - 33,158,153,245,123,191,189,213, 8,176,190,183, 13,231,187,204, 55,235,246, 41,129,142,240,157, 59,119, 14,221,187,119,199,203, - 47,191,220, 80,102, 54,109,218, 68,115,115,115, 49,101,202,148,219,174,247,240,240,144,139,197,226, 22,249,194,207,157, 67,109, -247,206, 56,254,242, 83, 13,124,151, 95,219, 17, 23,145, 91, 39,103,166,136,111, 75, 75,113,190, 1, 34,113,235,179,159,174,150, -148, 44, 68,215,174, 63, 3, 24, 77, 65,121,184, 86,249,178,134,101,193,234,204, 65,178,139,149,149,184,166, 51,108,226, 19,162, - 2, 33,198,171, 37, 37,233, 0,208,210, 32,192, 46,225,253, 22, 2, 88,145,127,244,197, 34,113,232, 12, 69,105,185,184,107,121, -201, 73, 49, 4, 1,189,139,174,155,194,170,203,111, 64, 40, 20,132, 12, 12,245,124,164, 86,101,252, 22,192, 13,123,158, 43,128, -184,166,211,255, 90,240, 64,227, 93, 89, 19,160,185,254,255,191, 3,218, 58, 85,207,250,253,180,180, 52,218, 86,190, 45, 91, 54, -211,236,236,108,144,116,179, 97,124,224, 45,111, 76, 92,162,194,248,241,227,225,204,180,191,230, 16, 16, 16, 16, 15, 0,247,220, -115,143,166, 29,186, 41, 20,129,129,129,115, 0, 88,157, 83,125,106,106,234,110, 7,191,203, 2,168,200,200,200,144, 63,244,208, - 67,195, 83, 83, 83,135,152, 76, 38, 34,145, 72, 48, 97,194, 4,236,223,191, 31, 28,199, 33, 49, 49,145,190,248,226,139, 36, 42, - 42, 74, 63, 99,198,140, 30, 53, 53, 53,183,116, 58, 93, 75,138,204,254,122,233,202,166, 65,131,135,248,158, 60,113,226,253,179, -124,254,160,158, 61,122,126,233, 19, 24, 92, 34, 8, 22,211,195,123, 15,249,215, 40,170,199,133, 5, 4,191,221,167, 79,159,195, - 94,161,158,107,251,119,141, 49,228,229,229,181, 75, 4,128, 7,243,116,191, 88, 0,239, 1,120,222, 34, 60,158,182,245, 9,230, - 65, 98, 87, 1,252,219,210, 37,112,170, 5,126, 6,230, 65,102, 7, 0,120, 56,144,158, 99, 0, 38,162,229,133, 21, 24, 0,193, - 0,122, 0, 56,109,135,243,180,229,186, 16,180,220, 55,201,192,188,140,163,191,165,219,224, 33,139,112,231, 91,184,243, 45,199, - 91, 0,252, 0,243,140, 3, 5, 0,131, 29,190, 89,150,200, 67, 63,139,145,100,155,206, 50, 0, 82, 0,191, 89,174,253,222, 14, -223, 75, 48,207,110,112,164, 43,195, 3,192, 62, 0,155,237,228,199, 76, 0,255,181,252, 63,107,147, 62,129, 37, 47,211, 0,124, - 10, 96,137,229,243,178,150,126,240,192,129, 3,217,132, 16, 20, 23, 23,203,173, 51, 1,154,122,253,197,197,197,114,235,181,246, -110, 32, 41, 41, 41, 59, 51, 51, 19,155,126, 50, 52,140,220,111,234,165,111,250,201,208,112,237,221,228,203,205,205,197,184,113, -141,135,186,135,135,135,199,111,219,182, 77,222,179,103,207,120,142,227,228, 75,151, 46,165,214,105,128,132, 16, 12, 31, 62,188, - 69,163,162,111,110, 46,190, 11, 12,137,247,177, 57,215,127,254, 68,168,223,191, 1,220, 31, 2,202, 1,121, 75, 5,180,158,243, - 66,141,214, 7, 10, 50, 12, 67,199,237,138,111,173,216, 91,102,112,108, 7,176,189,119,143,176,190, 0, 94,214,155, 56,164,231, - 21, 97, 92,168,185,187,147, 80,170, 82,177,236,123,183,110,221,186,229, 64,153,122, 31,128,103,254,111, 53,143,214,158,222, 22, - 84, 81, 86,131,138, 91, 42,240,249,213,158,245, 10,138, 90,165,137,134, 4, 11,253,248, 28,166,107,245,166,239,150,188, 28,235, - 23,210,255,137, 90, 59, 66,147,109, 79, 92,218,220,135,157,176,205,252, 63, 43,197, 73, 15,248,206,206, 2, 32, 41, 10,180,133, -175, 37,143, 61, 38, 38,166,195, 24, 34, 13,131, 29,173,226,159,199, 98,131,220, 92,199,218, 42,254,214,178,241,236,179,207, 6, -243,249,252,138, 99,199,142,125,121,207, 61,247,180,101,138, 98,247,212,212,212, 53,150, 40,192, 44,203,140,128, 89,169,169,169, -223, 59, 18, 84, 4, 80, 15,160, 42, 60, 60,124,232,216,177, 99, 75,207,229,229,117,214,106,181, 68, 46, 63, 4,145, 88, 4,134, - 48, 56,116,232, 16, 25, 48, 96,128, 38, 57, 57,121, 84,101,101,165,221, 58, 55,123,214, 76,246,199,189, 63,126, 58,116,232,176, -158, 6, 86, 63,249,106,254,149,167,185,162,130,167, 0, 64, 12,134, 14,238,221,247,100, 72, 72,112, 54,143, 47,124,237,191,111, - 45,175,255,118,163,235, 61,202,205, 25, 0, 47, 91,172,161, 41, 0, 46, 1,240,106,230,123,123, 44, 30,123, 18,128,145, 22,241, -108, 54,202, 9, 32, 18,192, 86, 7, 13,128,106,203,245,188, 86,248,226, 0, 92,113,144,239,138,229,250, 29,173,240,205, 5,240, - 36,128, 11, 48,207, 80,184,214,132, 91,110,241,254,159,179,120,195, 27,129, 22, 71, 92,240, 44, 30,251,227, 0,162, 44, 81,132, -230,210,169,180,124,190,206, 98, 4,108,108,133,239,107,139,209,229,200,253, 82,203,245,173, 61,191, 15, 44,145,141, 3, 22,163, - 6, 77,184,247, 3, 24, 96,201,139,124,139, 33,213,173,213, 31, 53,247, 32, 80, 0,242,230, 22, 2,178, 94,227, 76, 5,127, 82, - 42,165, 79,126,170,110,102,225, 30,133,211, 2,209, 94,124, 47,188,240,194,109,215,140, 31, 63, 62,123,252,248,241, 4, 0,238, -187,239, 62,167, 26,161, 61, 47,188, 64,124,154,182, 40, 61,188,178, 37,171,251, 19, 0, 24, 40, 19, 16,115, 80,198, 58, 50,251, -186,131,197,192,146, 47, 38, 90, 4, 62,192,171, 71,131,248, 91, 92,228, 91, 98,177,216,209,217, 40, 4,192, 59, 71,179,206,122, -132,118,237,241, 32, 7,143,200,146,226,114,158, 81, 87, 75, 59,133,120, 17, 47, 79, 1, 97,141, 28, 20,181, 6,150, 72,136,164, - 78,197,246, 14,105,217, 33,104, 86, 44,154,190,255, 35,151,239,189,211,179, 0,218,202,215,146,199,222,179,103,207, 14, 35,254, -220,247,254, 56,144,103, 30,147,183, 81,110,192,119,199, 12,160,148,182, 75,190, 90, 57, 76, 38, 83, 53, 0, 68, 71, 71,183,105, - 65, 32,171,248, 91, 80,101,249,239,104,221, 16, 90, 28,179, 51, 0, 48,112,224,192, 48,149, 82,181,104, 68,204,240,199, 84, 74, -165, 47,107, 98,141,161,161,161,183,194,194,194,174, 40,149,202, 37,149,149,149,249,142,166,107,202,228, 41, 44,128,231,143, 30, - 57, 49, 54,118,236,216, 41, 18,137, 36,136,128,154, 8, 33,224, 56, 90,173, 85, 43,214, 92,206, 43, 46,251,118,227,134, 54,173, - 8,216,212, 0, 48, 1,248, 71, 43, 2, 98,139,147,150,151,201,242,106, 14, 38,152, 71,212,243, 28, 76,143, 28, 64,150, 29,190, - 12,152, 7,173, 57,130, 71, 29, 72,223,122, 0, 95,218,225,249, 21,230, 41,144,112,128,239, 27, 75,196,192, 30,138, 44,158,189, - 35,233,227, 57,145,167,235,237,240,221,239, 0,159, 53,218,176,209,242,108,236,206,181,165,148,146,137, 19, 39,198, 89, 5,223, - 54, 4,239,202, 82,192, 50,153,140,164,167,167,199, 49,179,218,103,233,222,246,230,251, 51,160,160,228,166, 62,178, 91,183,141, -243,222, 95,247,164,245,156, 65,192,108,214,105,184,125,229,197,197, 42,135, 10,211,250,245,180,234,244, 6,178,252,251, 95, 22, -238, 94,125,223,206,227, 39,202,158, 9,246,229,166, 50, 1, 62,126,148, 2,132, 80,189,158,229,202, 57,160,202,160,231,252, 74, -203,180,134, 72, 39,210,152,156,156, 28,111,219, 29,144,156,156, 28,223, 81,158, 95, 71, 92, 9,240,207,130, 73, 75, 84,119,244, - 30,101, 50, 25, 39,149, 74, 59,139,197,226,178,232,232,232,251,219,131, 51, 53, 53,245, 96, 96, 96,224,147,169,169,169, 27,157, - 48, 0, 88, 75,228, 20, 0, 48,122,204,232,229, 0,150, 55,189,176,233, 24, 33, 71, 49,110,252,200,159, 96,238,138,109,130, 48, -244,238, 51,168,205,247,220,156, 1,160,115,129,135,182, 18, 34,209,187,249,254,178,124,141, 96, 17,250,118,171,232, 73, 73, 73, -217,246,230,229,255,145,124,127, 6,212,104, 52, 79, 1, 30, 70, 0,193, 28,104,169, 78,103,216, 82, 94, 94,121,158, 82,234,240, -180,169,160,152,127,208,140, 15, 39,147, 91,158, 15,231,118, 29,139,220,172,175, 62,120, 57, 32, 64,180,136,207, 35,180,172, 90, -119,185,204,192,110,146, 8, 24,177,132,207,227, 25, 89, 78,236, 76,250,172,125,252,214,129,103,174,238, 3,112,219,212, 63,155, -208,191, 43,139,205, 52,245,204, 29, 57,127,183,249,238,182,225,227, 40,152, 89, 10, 16, 66, 48,117,218,239, 3,162,247,236, 61, -211,208,134, 36, 78,142,110,175, 41,138,229,237,217,222, 88,140,128,141, 78, 92,238,111, 49, 0,212,127,214,246,129,223,228,129, - 82, 71, 27,251,166,104,110, 20,187,155,239,175,205,231, 70,199, 71,117,117, 53,133,185,155,171, 77,184,229, 57,157, 2,192,209, -205, 31,147,132,167, 94,249,240,241,185,121,159, 62, 63,251,216, 0,131,154, 68, 4, 8,248, 65, 32, 68,227, 37,225, 87, 14,234, -231,147,239, 44,119, 66, 66, 2, 73, 75, 75,115,121,189,249, 59, 37,158,127,150, 8, 64,199, 51, 30,204,177,161,191, 65,245, 10, -179, 56,204,222,248,147,238, 6, 72,162,162,162,254, 30, 67,100,221,112,195, 13,240,121,128,135,136,128,227,204,109,116,189,214, - 93,253,221,112,227,111,219, 30,184, 31,129, 27,110,252,125,192,154, 0,165,198, 42,250,110,241,119,195,141,191, 51, 24,247, 35, -112,195, 13, 55,220,112,195, 13,183, 1,224,134, 27,110,184,225,134, 27,110,184, 13, 0, 55,220,112,195, 13, 55,220,112,227,175, -136, 70, 99, 0,230,205,155,231,242,200,205,230,214,214,110,142,239,127,223,127, 30, 55,104, 72,111,121,231,174, 97,241, 42,173, - 90,126, 88,158, 27,159, 52,235,217,108, 87,249, 86,127,181, 61, 46,106,200, 40,249,173,210, 82,120, 74, 60,113,163,164, 32,254, - 95, 79, 77,115,153,175,189,239,247,194,225,121,113,163, 71,245,148, 75, 60,121,224,243, 24, 16, 49, 65,153,242, 69,226, 42,223, -153, 91, 67,226, 70,140, 26, 33,247,245,226, 1,124,160,230,220,122,226,104,250, 34, 39, 69,186,124,191, 87,246, 95,185,141,111, -228,200,145, 46,243,157, 56,113,226,118,190, 72,215,211,119,226,202,237,233, 27,213,167,143,203,124,199,243,243,255,116,124,147, - 90,201,223,229,203,211,232,162, 69,201, 45,126,190,191,153,252,141,124, 96,146,235,229,101,223,254,219,203,243, 36,215,203,203, -242,204,106,234,195, 21, 52, 58, 23, 20,249,176,203,124, 85, 87,190,187, 45,125,103,223,184,238,114, 67, 58,108,105,143,219,206, -125, 24, 84,234, 50,223,203, 85, 97,248, 35,218,171,191, 59,159, 84, 42,229, 55,183,179,160, 35,124,251,247,239, 7, 0, 40, 20, -138, 8,157, 78,167,120,242,201, 39,107,255,200,251,117,218, 0,104, 9,186,173,210, 72, 0, 61, 97, 94, 39,160, 64, 60, 91,118, -205,209, 31,216,254,205,242, 56, 2, 14,193,126, 1,200, 61,124, 70,254,245,215, 31, 35, 54, 33, 22,172, 90, 35, 31,208,111, 60, - 56, 14,242, 95, 35,190,142, 31, 54,108, 8,174, 94,189,142,186, 90, 53, 6,143,153,147,221, 18,223,250,111,229,113, 20, 4, 61, -122,247,148, 75, 95, 89,130,234, 79,182,227,155,207, 63, 3, 32,198,158,243, 37, 96, 24,200, 63,126,231, 45,228,231, 95, 70,120, -120, 15,136, 36,124,220, 44,201,111,113,113,145,194, 29,159, 81,161, 80, 8,137, 68,130,130,130, 2,116, 9,241, 65, 16,223, 11, - 93,186,251,193, 95,226, 11, 79, 98, 2,195, 48,160,156, 9, 26, 17, 31,117,183,234, 80, 49,220,254, 92,242,186,130, 53,212, 91, - 82,135, 49, 35,122,193,203,147, 15,161,132, 1,159, 7, 48, 66, 62,250,134,125, 78,141,148,135,194,155, 79, 57,156,225,171,247, -234,226,194,194,194, 16,123, 79, 87,185, 86,167, 7, 35,146, 0, 70, 32,175, 62, 58, 78,171, 81, 99, 84,200,229,236, 63,202,138, - 92,191,126, 61,157, 59,119,238,223,106,126,125, 71,133, 61,161,111,227,245,158, 0, 70,116,146,120,252,183,180,180,180,159, 64, - 44, 2,231,225,177, 12,230,149, 49,235, 59,202, 51, 40,248,117,111,220,181,139,135,111,219,107, 32, 33,121,217, 95,165,140,146, -111, 54,109,250, 77, 36, 20, 74, 56,142,243,245,244,242,242,122,112,234, 84, 15,152, 87,176,235,168, 35, 59,173,209,102,174,173, - 68, 82,169,212,199,215,215,119, 65,223,190,125,103,136, 68,162,174, 37, 37, 37, 37,165,165,165, 39, 12, 6,195, 82,153, 76, 86, -224, 2,159,159,191,191,255,146,251,238,187,111,242,179,207, 62, 27,254,197, 23, 95,220,186,112,225,194, 49,157, 78,247,174, 76, - 38,187,224, 8,199,254,253,251,241,227,200, 29, 24,179,247,222, 21,225,225,225,175,121,122,122, 98,251,246,237,167,103,206,156, - 57,252, 79, 19, 1,104, 65,252,121,158, 34,254,136,199,198,246, 90,201, 81,170, 59,122,249,214, 39,151,182, 74, 15,136,103,203, - 46,218,251,110,242,212,222,116,234,125,203, 97,172,175, 5,223,196,224,151,139,151,241,196, 19, 47,254, 94, 34, 24,224,231,220, -141, 8,234, 30, 38,231,234,149, 48,112, 4,135, 14,229,198,151,104, 91,202,168,165, 20, 66, 95, 16, 15, 31,156,185, 88,140,243, - 23,255,129,175,190,219,223,240, 57,199, 1, 15,140, 25, 3,212,151, 3,240, 70,193,133, 75, 16, 4,249, 33,118,244, 32,121,173, -166, 21,155,133, 48, 0, 97, 16, 53, 36, 26,157, 60,133,232, 18, 36,134, 79, 96, 0,252, 69,222,240, 23,243, 32,224,241, 96, 52, -153, 80,203,114, 56, 89,117,218,238, 67, 45, 63,191,132, 6,248, 2, 62, 30, 30, 8, 14, 10,132,143,143, 7, 40, 99, 2,203,213, -195, 4, 19,188,188, 60, 16,212,169, 43,122, 70,254, 68,179, 14,143,109,181, 81, 90,151,105,160,190,222,158,232, 25, 17,130,224, -160, 64,168,213,106, 8, 69, 98, 8,116,230,197,249, 34,194,123,200,107, 20,181,248, 62,183, 40,190,184,228, 38, 20,229,215,177, -244,217,232, 86,141,129,180,229,105, 14, 55, 18, 9, 79, 38,196,251,135,250,103,183, 38,254,119,195, 8,120,227,253,247, 41, 0, - 44,125,237,181,118,249,141,197, 43, 86, 80, 0, 72, 93,184,208,101,190, 31,115,114,158, 48, 24, 12, 27, 1, 96, 70,124, 60,227, - 74,227, 43,219,182,205,188, 70,188,205,180,105, 74, 41, 8, 33, 13,255,173,231,172,215,205, 77,110, 89,176, 23, 45, 74, 38,142, -138,186,147,226, 63,192,211,200,110,247,246,243,237, 7, 0, 66,137, 24, 6,173, 14,156, 90,179,226,216,145,195,239,220, 59,115, -102,127, 0,197,246, 72,244, 60, 33,133,121,241, 20,214, 34, 10,156,165, 29,106,182, 45, 26,122,239,100,252,118, 40,195,169, 60, -186,118,241,176,188,247,160,184,248,240,254, 15, 56,111, 20, 39,215, 56,117,121, 74, 74, 10,182, 37,103,181,122, 77,124, 86,227, -173, 72, 6,248,153,111,181, 66,199, 65,203,154,243, 85,109,249, 47, 27,229,135, 62,222,130, 86,249, 86,174, 92,153,253,198, 75, -175,134, 76,155, 49,221, 75,167,211,226,227, 15, 63, 96, 86,175, 94,173,155, 63,127,126, 24,128,155,237, 93,247,246,237,219,151, -176,115,231,206, 76,192,185, 53, 7,114,115,115,105, 81, 81, 17,170,171,171,161, 82,169,224,237,237,141,192,192, 64,132,135,135, - 99,204,152, 49, 46,213, 59,169, 84, 58, 62, 58, 58,122,211, 43,175,188,114,181,111,223,190, 27,135, 13, 27,118,233,214,173, 91, - 93,115,115,115,163,159,122,234,169,221, 82,169,116,133, 76, 38,251,202, 9,190,248, 25, 51,102,164, 45, 95,190, 60,208,104, 52, - 66, 34,145,192,211,211,179,179, 90,173,158, 57,109,218,180, 7,165, 82,233,124,153, 76,246,121,107, 28,207, 43,164,192, 72, 96, -202,137, 25,240,236,238,217,101,209,162, 69, 56,117,234, 20, 85,169, 84,126, 54,191, 3, 0,188,153, 51,103,154, 38, 78,156,120, - 87,196,253,220,185,115,141,142,155,219,208,141,223,130,232,119, 3,208, 11,230, 37, 99, 77,106, 61,123, 35,247, 74,197, 71, 99, - 34, 67, 94,188,111, 64,231,119, 58,249, 74,186,200,183, 74,183, 2,184, 44,158, 45,107,113,147, 26,125,125, 13, 58,245,190, 31, - 75, 94,155,129,141,178,223,235,226,225, 99,235,160,214,232,145,152,240, 34,238,137,125, 18, 15,167,220, 7,137, 68, 4,131,137, -133, 74, 99,144,247, 25,221,187,133,194,113, 29, 48, 0, 51,230,172,197,191, 94,121,166,225,236, 3,247,196, 65, 44, 22,225,135, - 67,251,177, 39, 39, 23,155, 54,124, 6,157, 86, 15, 33,143, 15, 47, 15, 33,212,213, 37,241,181, 37,104,118,247, 49, 74, 41, 64, - 57,243,139,225, 64, 41,133,222, 32, 50, 55, 79, 34,128, 26, 76, 48,241, 0, 19, 76, 48, 25, 56,176,166,214, 13,216,130, 19,169, -180,107, 48,133,143,183, 39,194,186, 70,160,223,224,222,240,246,146,160,174,190, 18,229,149,229, 80,212,221,130, 81, 71,224,225, -225,129,224,224, 88,204,156,126,129,110,223,217,183,249, 48,254,230, 27,212,228,237, 13, 45, 31, 16,138,133,208,106,132, 48,104, -132,208,137, 69,224, 19, 22, 20, 60,232,180,245,208,106, 84,232,218,181,139, 92,200,227,163, 6, 74,124,244,209, 17,136, 68,173, - 23,142,247, 55,189,111,183, 0,189,246,248,107,173,126,174, 80, 40,104,147,227,152,128,128,128,124, 66,136,142, 82,202,247,247, -247,247, 40, 40, 40, 8, 76, 75, 75,203,158, 59,119,110, 23, 87, 11,178, 48, 52,116,118,195,111, 0,113,254, 64,187, 69, 59,214, -167,165,209,231,158,123, 46,222, 88, 81,225, 20,231,143, 57, 57,210,145, 35, 71, 46, 29, 27, 21, 5,163, 72,132, 85,171, 86,113, - 51,239,187,111, 2,165, 52,203, 41, 87,142, 16,172,124,231,157,134,227, 5,111,191,141, 85,239,190,219,234,177, 61, 52, 53, 2, -150, 47, 79,163, 49, 49, 49,200,202, 42,164, 9, 9, 61, 7, 2, 40, 92,190, 60, 77,235,164,248,231, 14, 30, 56,208,199, 90,103, - 60,197, 18,148, 85, 86, 64,169,168, 69,244,200, 81, 30, 63,126,181, 33,107,202, 83,255, 24, 8,243,230, 5,173,129,125, 97,233, -106,254,163, 51, 31,228, 71,134,135,115, 86,207,240,237, 85,159, 54,186,232,221, 5,207,155, 13,191,151,230,199, 63, 62,117,130, -211,249,234,146,248, 55, 88,200, 1, 78, 92,156,224, 20,181, 39,159,224,252,187, 79,131,248, 4,193, 84,120, 30,250,194, 95,145, - 95,163,198,240,189, 21, 14,125,127,157, 76,118,244, 21,233,115, 61, 30,255,231, 83,126,105,155,191,227,194,195,195,153, 37,203, - 87,192,251,157, 37,248,225,135, 31, 74, 31,122,232, 33,151, 12,209, 22,132,127,194,206,157, 59, 15, 88,143,167, 79,159,238,144, -114,169, 84,170,184, 3, 7, 14,200,141, 70, 35,122,245,234,133,113,227,198,193,215,215, 23,181,181,181,184,121,243, 38,174, 93, -187,134,155, 55,111,210,137, 19, 39,198,123,123,123, 59,156, 79, 82,169,116,250,125,247,221,247,241,202,149, 43,183, 14, 27, 54, -236, 99,171,177,211,165, 75, 23,204,156, 57,147, 36, 37, 37,121, 1,200,149, 74,165,185, 45,237, 94,218,148,111,254,252,249,233, -207, 61,247, 28,115,250,244,105, 16, 66, 16, 24, 24,216,240,218,187,119,175,112,244,232,209,159, 73,165,210,227, 45,241, 61,175, -144, 98,202,137, 25, 0, 64,182,167,236,160,247,126, 54,190,123,126,126, 62, 10, 11, 11, 73, 93, 93, 93, 47,169, 84,202,159, 54, -109,154, 9, 0,157, 54,109,154,137,101, 89,220, 13, 52, 21,127,235,185,166,247,193,111, 70,252, 3,135, 71, 4, 62, 30,213, 35, - 96, 14, 33, 68, 64, 41, 53,114,230,151,193,100,212,105,133, 12,215,101,112, 39,241,107, 65, 62,189,122,239, 60,121,237, 59,221, - 86,233, 81,241,108, 89, 89, 43,205, 55, 6,244,239, 11,134,201, 70,126,109, 53,128, 75,168, 43,189, 2,129, 88,132,140,221,159, - 64, 83,101,194,156,127,188, 12,142, 3,166, 62, 56, 6, 38,190,151,221,155,203,207,191, 4,142, 3, 18,135, 18, 0, 93, 0,244, -128, 78,111, 64,210, 3, 19, 33,246, 99,176,105,203, 62, 48, 12,144,254,221, 70,148, 22,254, 26,255, 80, 92,100,246,229,179,205, -115,113, 20,224, 56, 14, 28,199,193,100, 50, 65, 47,160, 48, 18, 35, 12, 6, 3, 52, 30, 58,128, 19,131,161, 38,152,132, 20,245, - 6, 29,212,202,186, 86,211, 22,236,165, 7,159, 47, 65, 96, 96, 32,122,247,238,141,208, 78,163, 0, 30, 3,147,233, 52, 24, 90, - 11,157,154,133,137, 83,163,252,102, 13,130, 3,171, 16,232, 23, 11,133,106,113, 92,115,155,188, 72,116, 44,168,190, 10,208,137, - 96, 96,140, 80, 11,249,168,151, 8,192, 23, 8, 1,206, 19,132, 71, 80,175,214, 64, 81,126, 29, 5,167,115, 80, 83, 92, 12,142, -227,192, 80,158, 75,133,230,171,181,191, 27,206, 79,205,123,202,126, 59,105,217,215,221, 90,116,210,210,210, 22,189,242,202, 43, -207, 20, 23, 23, 51,132,144, 96,153, 76,246, 29,204,155, 59,121,180,161, 44, 11,214,172, 89,179,229,214,173, 91, 72, 79, 79,199, -240,190,125,121,254,131, 7,183,185,130,164, 46, 92, 72, 20, 64, 28,165, 84,190,122,245,106, 57, 0, 72, 83, 82, 28,246, 74, 12, - 6,195,186,177,150,202, 36, 20, 10,209,167, 79, 31,108, 63,116, 40,211, 18, 13,112,152,231, 78,109, 85,187,104, 81, 50,201,202, - 42,164,167, 79,155, 35, 86, 54,255,127,189,247,222,123, 75, 23, 45, 74,246,117, 84,179, 60,141,236,246,193, 3, 7,250,240, 24, - 6,207, 62, 58, 7, 90,157, 30,171,190,252, 18, 30, 18, 9,116, 58, 29,116, 90, 45,134, 14,139,138,220,191,121,243,115,147,230, -204,249,200, 94,212,241,221, 5,207,115, 0,152, 43, 69, 69, 76, 83,193,111, 90, 61, 93,185,247,110,253,198,199,103,165,189, 78, - 39, 76,125, 58,158,138, 34, 93, 50, 4,108,119,237,163,219,252,237,158,183,107, 65,249,241,113,189,222,132,195, 19,130, 33,120, - 81, 6,229,156, 8,240,253, 67,156, 18,255,131, 7, 15,150,135,119,238,114,243,159,207, 62,211,237,245,151, 23, 98,245,134,117, - 23, 71, 70, 71,247, 92,247,233, 58,143,151, 22,190,138,205, 99, 70, 97,203,150, 45,143, 61,242,200, 35,155,218, 40,252,113, 59, -119,238,108,112,152, 44, 97,245, 23, 96,222, 42,221, 46, 14, 28, 56, 32, 15, 14, 14,198,176, 97,195, 88,134, 97,248,230,232, 44, - 7,129, 64,128,128,128, 0,116,234,212, 9,215,174, 93,195,129, 3, 7,228, 51,103,206,116,168,174, 72,165,210,228, 41, 83,166, -124,176,114,229,202, 79,251,246,237,187,150, 16,194, 1,248, 12,192, 36, 0, 71, 0,188, 75, 41, 45, 34,132,188, 10,224, 93, 71, -248, 86,206,159,255,253,216,228,100,178,107,215, 46,240,249,124,200,229,114,156, 63,127, 30,189,123,247,198,123,239,189,135, 65, -131, 6,225,153,103,158,225,191,249,230,155, 43, 91,244,252, 45,216,158,178,131, 2,128,135,135, 71,153,159,159, 31,196, 98, 49, -132, 66, 97,189,112, 25, 88,122,140,146,105,211,166, 97,217,178,101, 56,127,254, 60,182,110,221,122, 87,196,127,238,162,101,191, - 59, 58,203, 95,111,214, 8,104, 46, 2,192,240,121, 12,159,229,168,138,229, 76, 58,137,128,223,213, 75,200,244, 7,199, 2,145, -247, 2,157,122, 3,183,174,160,243,229,156,233,143,197, 70,132,103,156, 43, 19,215,108,149,102,152, 55,183,107,190, 14,243,120, - 86, 65,242, 1,208, 21,190, 97,125,113,253,114, 58,214,202, 54,128,209,123, 96, 98,124, 44,246, 29,204,129, 70, 3,120, 4,180, -220, 46, 73, 60,250, 66,171,185, 12,147,201,118,111,154,114, 0, 55,193,240,226,240,248, 19, 79,131, 19,169,241,227,238,175, 48, -245,193,167,224,225, 9,168,235,203, 44, 26,212, 60,140,224, 65, 96, 17,127, 35,107,130, 94,105,132,198,168, 65,173,132, 15,163, - 70, 0, 61,223, 8,158,145,128, 53,113, 80,106, 89,212,212,179, 45,170,217,121,249,114,218,179, 19, 1,143, 71, 64, 24, 17, 76, - 38, 10, 86, 83, 12,189,201,136,210,242, 58,212, 40,234, 81,167, 50,129,209,233,192,162, 28, 60,193, 57,116,233,174,196,168,232, - 24,249,119,223, 94,106,150,147, 7,128,170,116,208,170,110,194,116,171, 14,188, 94, 93,193, 48, 12, 76,172, 30,181,229, 69,184, -124, 34, 23,149,215,139, 45, 66,194, 7,195, 7,192,187, 59,221,128,214,144,255,250,245,235,245, 73, 73, 73,253,163,162,162, 88, -145, 72,164,254,224,131, 15, 70,194,188, 41, 81, 31,180,113,166,137, 48, 52,116, 1, 0,140, 30, 52, 8,161,161,161, 21,171, 87, -175,206, 2, 16, 63,108,240,224, 54, 71, 1,252,129,108,105, 74, 10, 17,132,132,196,173, 94,189, 90, 46, 8, 9,137,115, 38, 18, - 96, 20,137, 32,208,235,177,125,251,118,132,132,132, 96,198,196,137,214,104, 0,117,198, 8,184, 83,176,138,190, 76, 38,179,109, -248,112,248,240,225,176,209,163,147, 31, 68,203,219, 70,219, 98,132,159,191,127, 63, 30,195,224, 31, 73, 73,168,173, 83,162,178, -166, 26, 2, 1, 31,124,190,249, 37, 16, 8, 32,146,120,160, 87,120,248,135, 87, 79,157, 62,223,123,120,140,220, 30,233,149,162, - 34,124,187,253,127,183,121,252,214, 72,192,168,232, 33, 72,140,191,215,201, 59, 86,197, 1,222,217,125, 7, 39,102,247,237, 19, - 25,159,185,235, 75, 57,208, 49,250,254,243,190,254, 8,250,125, 27, 16,242,249, 25, 12,240,227,131,231, 19, 0, 86, 81,129,225, -123, 43,224,201, 39, 80,179, 20, 60, 59, 53,229,218,213,171,213,123,118,237,238,251,245,231, 95,227,147, 47, 63,187,190,238,131, -143,222, 14, 8, 12,168, 93,178,116,201,193, 77, 91, 54, 99,220,232, 88,124,155,182,245,235,110, 61,186,125, 61, 46,118,156, 75, -247,220, 84,252,119,237,218,133,174, 93,187,246, 58,121,242,228, 28,152,183, 26,183, 27,246, 55, 26,141,136,142,142,230, 88,150, -229,171, 84, 42,136,197, 98,112, 28,135,223,126,251, 13,249,249,249,240,242,242, 66, 76, 76, 12,202,203,203,145,155,155, 75,237, -117, 7, 72,165,210,217, 41, 41, 41, 43, 31,120,224, 1,175,181,107,215,250,124,252,241,199, 66,152,119, 45,205, 4, 16, 13,243, - 6,103, 31,193,188,157,251, 65,152,119, 60,109,149,111,231, 43,175,108, 30,208,191, 63, 89,157,148, 4,114,255,253,216,126,244, - 40, 87, 90, 90,186, 4,192,234, 27, 55,110, 76, 91,180,104,209,231, 63,252,240, 3, 98, 99, 99,225,233,233, 57,166, 37,174, 41, - 39,102, 96,199,142, 29, 88, 63,201, 92,199,252,252,228, 85,157, 58,117,130,151,151, 23,245,244,244,188, 97,120, 29, 32,211, 8, - 93,182,108, 25,172,134, 70, 99,253,186, 59,152,187,104, 89,131, 17,208, 72,236,155,158, 16,207,150, 85,254,124,181,114,221,198, - 35, 87, 95,254,173,180,238, 0, 3,202, 7, 40, 48,229, 61,252, 28,243, 1,254,171, 72,194,161,129, 43,128, 73,139,225, 45,224, -134, 61, 16, 21, 62,199,210, 93,112, 27,118, 29,170, 33,128, 18,211,158,120, 17, 28, 7, 0, 53, 48, 47,155,108, 68,143,190,209, - 16,139,248, 48,177,122, 80,131, 57, 44,226,237,237,141,234, 26, 69,139, 55,241,209,135,175, 16, 0,184,248,243,151, 96,152,198, - 78, 2,167,253, 21, 58,189, 17, 60,129, 24, 68,104,238, 67, 83, 41,149, 24, 51,102, 76,235,238, 8,103, 0,199,113, 96, 89, 22, -122,189, 30,245, 28,139, 58,131, 17,202, 50, 37,234,110,214, 65, 89, 94,131, 26,101, 45,202,117, 26, 40,213,181,168,213,183, 60, -214,201,219, 75, 13,150,229,160, 55,152, 80, 91,167, 68,254,213, 98,156, 56,157,135,159, 79,228,225,210,111, 5, 40,185, 81,133, -122,181, 1,170,122, 61,202, 74,235,112,225,215,107,200,205, 61,139,146,178,242, 22, 57,109,139, 10, 91,167, 70,201,185, 75,248, -101,239, 33,100,110,248, 16,135,182,110, 64, 73,193, 85,112,212, 8,142,144, 6,225,119,166,230,219, 11,243,219, 3,159,207, 7, -128, 91, 0,110,249,251,251,151,120,123,123,235, 23, 45, 90,116, 18,230, 1, 99, 12,204,107,101,231,187,202,191,102,205,154,212, -164,164, 36, 0, 64, 68,112,112,136,165, 79,156,215,158,149,195, 42,250,214, 72,128, 3,225,255, 4, 0, 88,181,106, 21,174,148, -149, 97,198,196,137,176, 70, 3,242,242,242, 0, 0, 59,228,114,234,104, 86, 44,120,251,109,188,250,206, 59, 13,225,125,235,123, -235,177,245,189, 35,225,127, 43,178,178, 10,105, 83,241,183, 61,206,202, 42,252,214, 17, 30, 63, 62,255,191, 58,131, 30, 60, 30, - 15,191, 21, 22,160,176,228, 6,142,159, 59, 15,131,193, 8, 6, 4,124, 62, 31,132, 16,112, 38, 19,180,106, 13,242, 14,103, 31, -114,128,150,177, 21,255, 71,103, 62,120,155,199,127,252, 76, 30,108, 35, 4,142,193, 38,156, 44,138,204,182, 10,127, 86,218,235, - 84,192, 94,137,251, 67, 45,128,154, 50, 8,187,247, 65,197,115,247, 32,239,235,143,192, 15,234,220,240, 81,197,115,247, 32, 72, -204,192,135,223,122,113,233, 27,217,183,139,135,135,167,199, 39, 95,172,209,197,223,123,175,112,212,152,209,155,175, 93,189,198, -253,118, 53, 31,224, 40,196, 34, 17, 98, 99, 98,177,123,215,110,236,220,185,211, 41, 47, 96,223,190,125,113, 82,169,148, 90,197, -255,192,129, 3, 88,183,110,157, 1, 0, 78,156, 56, 97,144, 74,165,143, 56,210,181, 80, 84, 84, 4,203,214,196, 76, 81, 81, 17, - 50, 51, 51,145,151,151, 7,181, 90, 13,133, 66,129, 83,167, 78,161,184,184, 24, 55,110,220, 64,143, 30, 61, 80, 84, 84,212, 42, -223,188,121,243, 30,127,248,225,135,223,143,139,139,243, 58,121,242,164,143, 70,163,249,167, 68, 34,201, 6,240,169, 76, 38, 91, - 44,147,201,234, 0,252, 15,192, 8, 66,136,144, 82,106,108,205,233,152, 63,127,254,227, 63, 44, 88,176, 57, 54, 36,132,176, 11, - 23, 98,140,193,128,147,187,118,209,210,210,210,167,101, 50,217,219, 50,153,172, 18,192,198,139, 23, 47,178, 44,203,194,203,203, - 11, 97, 97, 97, 94, 70,163,177, 89,241,159, 52,105, 18,100, 50, 25,164, 82, 41,164, 82,169, 71,105,105,105,223, 27, 55,110, 64, -173, 86, 19,133, 66,209,159,207,231, 79,176, 21,127,185, 92,142, 7, 31,124, 16, 29, 5,205,117, 1,132, 2,232, 53,125,120,247, -103,187, 5,122,206,129, 81, 11,244,157,128, 51,193,211,113,223,252,175,160,173,170, 5,207,199, 27,242,143, 31,199,184, 1, 63, - 35, 32, 47,115, 60,128,238, 45,253, 64,111,159,174,248, 37,111,135,141,189,161,182,116, 19, 26, 1,163, 30,124,142, 7,198, 82, -239,119,254, 96,238,110,138,157,156,210,114, 65,189, 64,241,192, 48,219,109, 16,137,229, 54, 4,128, 64, 12,150,152,192, 89,218, -221, 89,115, 94, 0, 0,249,245, 99,235, 91,172, 89, 38,142,130,229, 24, 48, 44, 11,198,160,135,198, 98, 89,104,121, 60,120,178, - 90, 40,181, 20, 68, 64, 96, 50,153,160, 49, 1, 21,106, 3, 90,234,204,102, 13, 28,116, 2, 30, 56, 13, 11,150,171,131,170,222, - 8, 30, 17, 64,207, 26, 97,160, 6,176, 70, 3, 32,228,192, 16,128,136, 56,212,105, 77, 40,175,212, 64,173,103,155, 13,198, 48, -196,212, 96, 0, 16,242,187,158, 24,117, 90,212,213,212,128, 33, 60,240,249, 20,160,124,240,136,235, 29,127,151,175, 95, 54,244, -237,209, 87,232, 72,216,191, 81,152,148, 16, 72, 36, 18, 0,208, 2, 48,240,249,124, 20, 22, 22, 98,249,242,229, 15, 2,184,177, -104,209,162, 97,190,190,190,126,117,117,117,215,107,107,107,157, 14,119, 11, 67, 67,159, 2,128, 78,157, 58,217, 86,224,218, 79, - 63,253, 52, 11, 64,194,176,193,131, 15,182, 87, 69,152, 63,127,126,188, 35, 6,192,143, 57, 57,113, 35, 71,142, 12,150, 42,201, -129, 0, 0, 32, 0, 73, 68, 65, 84, 27, 27, 21, 5,226,237,141,229,203,151, 99,225,194,133, 16, 8, 4, 48, 42, 20,240,245,245, -197,235,243,231, 55,140, 11,112,100,112, 96,211, 62,126,123, 99, 2, 90,194,114, 39, 6,119,158, 62,125, 26,167, 79,159,110,184, -190,165, 62, 78, 69, 77, 77, 63, 47,111,111, 84, 41, 20,144, 31, 63, 14, 62,195,131,222,104,132, 70,171, 5,199,113, 13,131, 21, - 89,163, 1, 6,189,222,145, 60,230, 0, 48,150,110, 0,206,166,224,235, 44,231,241,246,170, 79,133, 0, 16, 25, 30, 94,113,237, -226, 47,109,202,215,132,228,101,228,183, 51,233,113,123,119,126, 41,111,143, 72,128, 51, 97,255, 70, 97,217,109,159, 35,234,137, -151, 33,138, 24, 98,110, 43,170,202,144, 95, 99,222, 68, 78, 52,102, 10,138, 77, 44, 60, 86, 31,111,149, 67,169, 84,250,137, 36, - 98,244,142,136, 16, 95, 43,185,209,185,186,178, 26,179, 30,157, 35,223,115, 48, 19, 31, 47, 91,149,190,115,207,174,164,200,136, - 72, 60, 62,243, 49,228,158,201,193,206,237,219,233,116, 7, 66,236,182, 94,255,129, 3, 7, 48, 97,194, 4,171,177, 40,188,121, -243, 38,158,121,230, 25,161,245,246,237,113, 85, 87, 87, 99,220,184,113, 48,153, 76, 40, 42, 42, 66, 78, 78, 14, 6, 12, 24, 0, - 95, 95, 95,116,235,214, 13, 81, 81, 81, 96, 24, 6, 12,195,160,115,231,206, 13, 81,170, 22, 60,245, 1, 67,134, 12,249,104,204, -152, 49,188,188,188, 60, 31,147,201, 84,190,125,251,118,165, 86,171, 93, 46,147,201,108, 13,216,103, 39, 79,158, 92,188,103,207, -158, 8, 66, 72, 25, 90,216,209, 86, 42,149, 14,155, 31, 31,191,113, 20,159, 79, 42,151, 46, 5, 53, 26, 33,231,241,184, 92,141, -230, 73,153, 76,246,141,173,221,241,214, 91,111,241, 25,134, 65, 77, 77, 13, 10, 11, 11, 43, 6, 13, 26, 20,210,148,111,210,164, - 73,183,253, 70, 88, 88, 88,128,137, 82,104, 53, 26, 92,188,120, 17, 44,203,146,142, 42,254,183, 25, 0,186,173,210,200, 80, 95, -201,216,201, 67,195,158,241,145, 8, 70,178, 38, 78,193,167, 38, 31,248,117,230,149,213,234,160,173,170, 3,132,124,152,106, 85, - 40, 81, 24,128,192,238, 96, 56,131, 24,173,204, 38,184,170, 84,162,143,159, 15, 88, 61,112, 53,251, 91,244,142,155,212,224,192, - 25, 13, 70, 8,192,160, 94,103,222,161,246,129,184,104, 72, 2,195, 90, 77,240, 3,131, 9,246,156,167, 16,136, 1, 97,247, 73, - 48, 20, 31,109,112, 28, 4, 66, 17,140,208,193, 75, 98,222,145,116,215,158,173,248,229, 68,118,252,156,137, 49, 45,183, 70, 28, - 7,161, 65, 11, 35,132, 96, 24, 22,208,153, 27, 54,163,209, 8,189, 78, 0, 30, 95, 0,232, 0,202,153,187, 8,122,132, 71,180, -200,165,209,113,224,241, 8,140,172, 17, 58, 61, 7,165,202, 92, 14,141, 28,133, 65,207, 1,124,128, 39,224,129, 47, 6,136,214, - 4,142,176,224,160,133, 74,107, 9, 72,219,129, 9, 0,195, 1,148, 0, 12,195,129, 16, 30, 56, 74,192, 48,150,177, 84, 28, 3, -142, 97, 64, 56,199, 28,100, 27,239, 95,232,106, 1,242,240,240,128,197,219, 15, 46, 44, 44,172, 88,190,124,121, 60,128,135, 22, - 45, 90, 52,177,103,207,158,106,149, 74, 85,205,178,108,131, 80, 56,163,255,107,214,172,249, 50, 41, 41, 9,225, 65, 65, 13, 39, -195,131,130,252, 44, 81,128,224, 63,162,194, 24, 12, 6,185,213,219,167, 42, 21,254,253,239,127, 67, 95, 93,221, 48,242,173,183, -197, 88, 17,232,245,120,240,193, 7, 43, 74, 43, 42, 30, 9,243,240,216,124, 55,210,102, 59,168,207,182,255,191, 57,196,196,196, - 32, 33,161,103,195,245,205,173, 3, 0, 0,172,222,128, 90, 67, 13,116, 58, 29,252,124,125, 33, 22,138, 96, 52,177,160,148,194, -100, 50,193, 96, 48,192,104, 52,130, 99, 77,142,230, 47,119,165,168,136,137, 12, 15,183,122, 4,220,149,162, 34,230,219,237,255, - 19,219, 70, 4, 34,195,195,107,209, 78,131,217,250, 69, 39,101,151, 20,156,106,151,103,236,234, 24,128,123, 51, 43, 81, 17,158, - 14, 97,247, 62, 32, 17, 67,208, 99,195, 89, 84,233, 56,120,242, 9, 12, 63,253,128,203,133,215,236,238,159,167,101, 13, 56,157, -123, 2, 31,173,252, 16,247,196,141,197, 91,255,239, 29,236,223,187, 31,155, 55,125,131, 49,227,199, 38,117, 11,239, 14,190,135, - 0, 7,143, 30,196,150,175,191,193,142, 31,182, 99,247,238,221,244,255,254,239,255, 72, 43, 34, 75,155, 10,191, 21,181,181,206, -111,112,167, 82,169,224,235,235,123, 28,192,168,240,240,112,196,196,196,128,199,227,129,227, 56,244,232,209, 3, 34,145, 8,117, -117,117, 8, 15, 15,135,183,183,247,117,149, 74,213,163, 37, 46,153, 76,118, 81, 42,149,166,238,216,177, 35, 49, 50, 50,178,223, -246,237,219,235, 21, 10,197,187, 50,153,108,139, 77,250,167,223,123,239,189,175,108,216,176, 97, 27,128, 10, 0,201, 0,126, 6, - 48,180, 25,190,179, 82,169, 52,213,239,212,169, 55, 30,102, 89,124, 8,112, 95,214,215, 63,214,132,239,161, 23, 94,120,225,195, -185,115,231,226,218,181,107,216,189,123, 55, 88,150, 61, 4,224,225,214,238,219, 18, 5, 96,252,120,188,106, 47,131, 1,234,179, -103,105, 48,199,169,174, 2,170,187, 45,254, 81, 81, 81, 56,119,238, 92,179, 33,127,123, 93, 0, 61,167, 15,239,190,196, 71, 34, - 24, 89,169,212,237, 63,118,165,114, 57,120, 34,224,242, 81,220, 31, 78,177,248,249, 7, 17, 51, 48, 28, 47, 72, 39, 99,106, 47, - 3,112,225, 0,168, 64,194,162,213,193, 58,181,200,175, 45, 6, 95, 4, 60, 48,245,101,108,249,100, 25, 0, 3,160,209,195,164, - 5,126,144,159, 67,214, 73,243,140,194,174,221, 35,192,240,237,139, 87,226, 80, 2,163, 14,216,181,123, 31,134, 79,124,222,236, -253, 67, 0,158, 4, 72,153,146,140,196,241,211, 0, 0, 37,215, 11,192,234, 12,173, 91,244,148,130, 37,102,129,215, 27,204,131, -255,244, 58, 45, 52, 26, 13,234,235,235,161, 82,214, 65,165, 82, 65,169,170,135,174,190, 30, 90,173,182,229,194, 95, 79,160,213, -153,160,213,153,160,214, 24,161,170,215, 67,161,210,163, 86,105, 64,157,202,136,218, 90,243,255,154,106, 22, 53, 10, 22, 53,117, - 44,170,106, 12,184, 85,213,114, 26, 25, 74, 97, 2, 64, 76, 4,132,225, 64, 9, 5, 40, 5,165, 60,152,184,223,179,143,179,180, - 30,206,198,198,251,143,233,143,156, 61, 57,216,127,104,127,131, 81,112,249,250,101,135,190,203,227,241,192, 55,231, 87, 24,128, - 94, 43, 86,172, 56, 15, 96,245,235,175,191,254, 82,207,158, 61, 89,115,144,192,156, 48, 39,197,159, 8, 67, 67,119, 2, 64,104, -104,232,109, 31, 62,247,220,115,236,169,203,151,183,158,189,112,161,221,194,186,171, 87,175,150, 59,186,111,188,209,102,138,197, -247,223,127,143,171,229,230, 46,156, 31,179,179, 27,125,118,249,242,229,144,224,224, 96,197, 31, 97,168, 36, 36,244,100, 44, 13, - 90,211, 6,191,209,231,118, 13, 60, 31,239,223, 56,147, 9,202, 26, 5,170,170,170, 80, 93,171,128, 90,163,129, 90,163,129,170, -190, 30,234, 58, 37, 84,181,255,159,189, 43,143,111,162,218,254,223, 59, 89,154,182, 64, 23,118,202, 90,164,236,178, 20,161, 5, -129, 4, 82,168, 34, 42, 74, 1,225,137,125, 5,155,226, 6, 34, 62, 84, 84,220, 80,121, 63, 11,184,210,212, 39,130,239,129, 64, -139, 11,155, 44,129,164,178,180,212,130, 11,139, 64,161,208, 66, 89, 10, 77,186, 37,105,182,185,191, 63,146, 9,105, 73,147, 73, - 90, 4, 53,223,207,167,144, 89,114, 50,115,231,206,253,158,115,238,185,231, 84,160,214,104,128,185,182, 22,172,213,235,252, 38, -211,163,107, 87,110,204, 96, 1,152, 93,167, 3, 0,224,127,155,182, 96,113,250,199,225, 0,218,250,122,223,191, 31,201,150,170, -178, 94,170,211,217,206, 30,255,225,246,186,255, 1, 92,158,218, 21, 93,190,252, 25,164,219,221, 48,229,100,163,248,159,131, 16, - 42, 36,216,151,208, 26,214,202,107, 24,178,163, 12, 94,102, 0, 48,121,242,100,242,228,220, 57, 56,115,234, 20,114, 53,251, 16, -214, 60, 12,143, 77,125, 12,225, 45, 35,113, 36,191, 0,205,196, 18,132,134,134,162,125,215, 14,248,122,253,215,120,105,209, 43, -168,169,240,191, 74,237,224,193,131,125,254, 78,243,230,205, 81, 89, 89, 57,140, 97, 24,115,167, 78,157, 48,116,232, 80,244,237, -219, 23,173, 90,181,130, 68, 34, 65,215,174, 93, 49, 96,192, 0,132,135,135,163,186,186,186, 75,243,230,205,225,133, 88,255, 47, - 39, 39,103,247, 87, 95,125, 37,210,233,116,175,214, 35,235,164,145, 35, 71,174,248,242,203, 47, 87,181,109,219,246, 93, 66, 72, - 51, 0, 47, 1, 88,236, 65,222,162,119,170,171,255,111,150,213,106,251,194,104,156, 94, 79,222,228,105,138,215,191,121,118,222, - 11,130, 83,167, 78,225,208,161, 67,248,242,203, 47,107, 0,188,204,243,246,153, 16,147, 73, 66,127,255, 29,157, 84, 42, 18, 85, - 90, 42, 0, 64,151, 45, 91,134,173, 91,183,254,161,253,173,190, 71,175, 33, 15, 95,253, 65, 32, 72,192,144,230, 37,229,250,181, - 95,231,158,123,249,151, 98,109,190,209, 70,206,224,250, 57, 72,190,121, 10,239,142,168, 70,193,155, 67,241,161,172, 6,161,223, - 61, 13,104, 47,162,134, 74,142, 58, 52,175, 6,112, 35,170,255,215,223,182,224,245,215,191,194, 93, 45,250,227,248,193, 95,177, - 75,253, 59,100,241,125,145, 48,210,222,209,168, 64, 8,179, 15,241, 17,137,131,122,225,157,255,123, 31, 59,142, 86,161, 89,215, - 62,120,224,129,137,216,185,247, 91,108,219,105,143,178,100,108, 22, 4,137, 60,143,115,148,181,193,198,218,173, 25, 56,172, 25, -179,217,140,218,218, 90, 24,141, 70,232, 13, 70, 24, 13,122, 24, 13,122, 24, 76,181, 48,155,106, 27,118,127, 25,155,163,178,198, -134, 42, 35,139, 42, 35,107,255, 92,205,162, 70,111, 69,141,193, 10,157,214,134,114,173, 5,229, 58, 11,202,203, 45,184,126,221, -140,171,215, 45, 30, 21,128, 27,238,127,151,107,230,220, 55, 2, 10, 1, 33,160,245,162,254, 41,241, 78,182, 47,206,124, 17,189, -227,123, 59,183, 85,171, 85, 78,143,192,129,237, 7,112,170,248, 20,175,100, 79, 44,107,255,173,236,236,236,253,148,210,126,147, - 39, 79,158,217,173, 91,183,214, 0, 24,150,101,131, 44, 22, 75,132,213,106,109,225, 70, 1, 96, 61,184,254, 23,127,250,233,167, -247, 79,158, 60, 25,221, 90,183,230, 53,117,213, 24,136,218,180,145, 2,192,144, 94,189,100,222,206,237,209,174,157, 44, 61, 61, - 29,199,139,139,171,190,217,181, 11, 39, 79,158,116, 90,253, 61,123,246,132,227,152,249,155, 93,187, 80, 92, 92,140, 83, 5, 5, - 70,111, 50,111, 69, 12, 0, 0, 58,122,244,232,167, 92, 73,159,251, 63, 54, 54,150,151, 59, 23, 0, 10, 79,158, 45,176, 90,173, - 48,155, 77,208, 94, 45,195,181,203, 87,112,253,202, 85, 92,191,114, 21,218,178,107,168, 40, 47,135, 73,175,183,199,207, 84, 84, - 96,144, 92,238,173, 13,173,139,211, 63, 22, 46, 78,255, 88, 8,160, 10, 0, 59,108,240,221, 55,157,228, 18, 23,192, 27, 39,142, -100, 75, 75,207, 22,168, 7, 12,189,113, 13,231,206, 28,148, 86, 92, 43, 82, 55,166,127,144, 41,186, 58,150,191, 63, 56,173,213, -163,100,246, 61,160,231,126, 67,155,207,143, 32,116,229, 97, 92,158,218, 21,177, 59,202, 64, 68, 65, 16, 18, 64,200,120, 87, 64, -159,126,230, 25,242,218,251,239,224,185, 5,243, 97, 97,109, 56,121,190, 16, 51, 30,155, 14,177, 68,130,239,191,219, 12, 88,108, - 48,213,154,176,175,224, 32,140,198, 26,164, 38, 39,231, 20, 20, 20, 80, 15,132, 72, 38, 77,154, 36, 27, 55,110, 28, 8, 33,216, -189,123,247, 77, 46,253, 23, 95,228, 31, 39,212,178,101, 75, 92,186,116, 9, 0,132, 25, 25, 25,184,118,237, 26,250,247,239,143, -240,240,112, 48, 12,131,252,252,124, 48, 12, 3, 66, 8, 46, 93,186,132,150, 45, 91,122,149,169, 84, 42,223, 53,155,205,163,148, - 74,229, 6, 23,178,126,108,228,200,145,233,179,103,207,142,200,200,200,144, 16, 66, 24, 0,223, 2, 88,160, 84, 42,175,122,145, -247,175, 67, 22,203,144,250,242,166, 45,252,102,227,163,211,159, 38,247,207,201,128,230,208, 9,164,167,167,179, 85, 85, 85, 41, - 74,165,242, 60,143, 41, 68, 0, 96,239,106,222, 60,188,211,149, 43,184,215, 96, 64,123,145, 40, 52, 84, 32, 96, 74, 75, 75,111, -138,197,249,163,148, 0,238,143,215, 20, 0,128,179, 95, 31, 60,247,140, 86,111, 58, 12,123,224, 86,251,220,194,107,153,163,122, -181, 93, 36, 60,119, 40, 18, 95, 62, 14, 4,133, 2, 38, 61, 64, 41, 44, 2,201,213,125,199, 47,127, 1,160,193,236, 75,235,214, -126, 38,155, 62, 99,166, 26, 0,244,172, 5,103, 42, 74, 0,216,112, 87,139,110,144,201,238, 70,219, 86,237, 80, 94, 89,101,247, - 21,152,173,184, 92,161, 71,111, 15, 55,213,177,115, 60, 46,150,228, 58,222, 76, 33, 18, 7,216, 99, 0,118, 28,181, 96,231,214, -108, 92,189,126, 9, 45,195,237, 43, 9,194,197, 34,220, 61,196,243,122, 80, 51,132, 16,179, 86,216, 32, 0, 75, 8, 24, 27, 11, - 88,172,176,137,132, 0, 97,192,189,147, 44,133, 61, 87,128, 7, 60, 60,237, 37,242,221,127, 23,208, 16, 49,133, 80,228,226, 97, -176, 0, 86, 10,212,154, 1,155,201, 6, 66, 8,136,152,192,106, 3,244, 38, 96, 86,242,191,137,187, 84,142, 54, 23, 13,141,101, - 88, 16,135,251,223,174, 20, 16,216, 88, 6,140,192,110,245, 51, 0,168,128, 2,148,159, 23,192,149,252,221,109, 31,216,126,160, -155,215, 41, 9,155, 13, 38,147, 9,147, 39, 79,238,155,157,157,189, 28,192,192,236,236,236, 29,217,217,217,251, 38, 79,158,252, - 76,247,238,221, 45,132,144,150, 31,126,248,225,174,151, 94,122,105,134, 86,171,205,241,160,124, 58,251,228,130, 5, 11, 22, 47, - 88,176, 0, 59,118,236,128,254,234,205,239,114,183,214,173,113,238,220, 57, 0, 80,243, 73, 12,212, 80,210, 31, 81,155, 54,210, - 79, 63,253, 84, 77, 41,197,144,158, 61,101,131,121,172, 44,232,223,187,183,134, 48,204,248,147, 63,253,212, 21, 64, 16,128,143, -184,213, 0, 61,218,183,199,252,249,243,113,224,192,129,165, 49, 49, 49, 57,253,162,162,188,198, 40,184,203, 3,224,111, 12,128, - 43,184, 60, 0,113,113, 73, 63,229,229,149, 29, 80, 40, 20, 98,199, 52,193,112, 0,185,124,147, 0,117, 29,208,231, 21,227,229, - 43,227, 88,171,173,151,190,178, 18,149,215,175,129, 16, 6,148,178,168,173,173, 5,165, 20,148, 82,156, 59,241, 59, 44,102, 19, -238, 26, 18,235,173, 13, 93,199,156,112, 0,204,253,178,209,236,253,178,209,117,130,254, 28, 83, 4,188,113,242,151,111,164,151, -206, 22,168, 1,160,107,151, 46,248,190,158, 23,160,117,231,193, 50,220, 70, 12,249,161, 12, 5,247, 1, 3, 99,229, 40,123,122, - 56,218,125,118, 16,167,181,122, 68,136, 9,202,181, 58, 8, 9,241,234, 1,224, 48,115,230,204, 58,103,110,217,178,133,222, 63, -225, 62,108,221,188, 21, 27, 55,110,196, 27,139, 94,195, 46,205, 30, 8,132, 2, 68,117,140, 26, 93, 89,233,121,233,114, 98, 98, -162, 38, 49, 49,145,236,216,177, 67, 58,110,220,184, 58,177, 0,187,119,239,198,153, 51,103,106,149, 74,101,123, 62,215,214,181, -107, 87, 20, 21, 21,161, 79,159, 62,214,121,243,230,137,215,175, 95,143,176,176, 48,156, 60,121,242, 38,207,107, 81, 81, 17,186, -242,124,206, 74,229,141,196,115, 10,133,226,241,123,238,185,231,173,199, 30,123, 44,172,160,160,160,121,109,109,237, 63,131,131, -131, 31, 48, 26,141, 31, 40,149,202,239,121,202,251,197, 85,222, 3,207,174, 95,115,239,216, 73,228,223, 42,128,116,120, 16,239, -174,120,133,106, 11, 79,166, 40,149,202, 44,111,178, 92,188,108,164,218, 98,169, 16, 7, 5,161,133, 88,140, 96,155,205,164,183, -217,108,183,131,252,249,162,142, 2, 32,121, 76,121, 92,251,181,226,180,228, 49, 37, 55,165, 89,114,236,107,197, 15,213,181, 86, -253,176,187, 90,221, 31, 25, 34,184, 71, 96,170, 13,181, 82,166,186,188,218,156,151,123,230,202,206, 82,173, 33, 71,242,152,242, - 50, 86,174,116,251, 3, 53,250,214,154,180,167,231,200, 0,168, 89, 1, 55,205, 39,192,153,170,203,120,253,153, 20, 24, 12, 38, - 84, 25,237, 49, 0,102, 38, 8, 99, 18, 61,167,217,125,109, 81, 50,217,177,109,136,253,229,182,113,150,179, 21,137,253, 9,166, - 61,181, 12, 33, 33, 65,104, 17, 44,145, 1, 80, 23, 30, 59, 34,139,239,231, 57, 33,136,144, 90, 97, 38,118, 37, 0,132,192, 70, -169, 93, 17,224, 18, 54, 16, 6, 66,150,133,149, 91,118,224, 69, 9,168, 48,134,195,104, 42,135, 88,200, 56,211,156, 89, 89,192, - 98,161,176, 88, 41,106,140, 44,136,128,192, 6, 2, 11,123,195,117,239,150, 96, 89, 6, 12,177,129,216, 8, 40, 67,157,238,127, -210,128,241,204, 73,122,238,121, 25, 89,185,242,164, 71, 11,239,247,220,223, 27,219,119,204,148, 82, 24,141, 70,244,239,223,255, -114,116,116,244,164,243,231,207,247,216,184,113, 99, 62,128,135,178,179,179, 31,114, 61,249,253,247,223,215,188,244,210, 75, 50, -173, 86,235,141, 32,156, 13,146,150,150,214,224, 73,143, 62,241, 4, 0,223, 18, 3,113, 89,247,234, 99,104,239,222, 62, 45, 43, -236,215,179,231, 46, 87, 79, 70,122,122,250, 39, 19, 39, 78,180,158, 58,117, 74, 88, 92, 92,140,174, 45, 91,230, 70,133,132,240, - 10, 80,188, 21,121, 0,234,145,251,213,156,156, 28,215, 24,143,163, 14, 69,128,111,198, 64,125,112,251,118,143,158,220,179, 55, - 55, 60, 52,180, 69,149,174, 2, 86,171, 21,212,241, 30,232,174,150,161, 74,167, 3,165,148,143,245,111,127, 89,111,196,156, 48, -142,229,128,140, 99,217,159, 51, 49, 80,225,249,243,252,149, 0,195,175,210,139,133,249, 78, 43,255,251, 44,251,242,191,214,209, - 35,100, 3, 98, 39,106,110,223,240, 74,111, 86, 2,240, 57, 6,166,189,142, 43, 44,139, 1,171,243,145,159,216, 22,125,183, 94, -133,144, 0,205, 69,254,173,152,157, 56,113, 34,217,171,217, 75,199, 36,140,197,230, 77,223,225,237,165,239, 99, 97,101, 37, 40, -203, 98,195,134, 77, 40, 45, 45,125, 0,128, 87, 31,180, 59, 69, 0, 0, 38, 77,154,244, 11,128,106, 62,215, 18, 31, 31, 79, 46, - 93,186, 68,143, 28, 57, 34, 30, 60,120, 48,198,142, 29, 11,181, 90,141,206,157, 59,195,100, 50, 97,244,232,209,160,148,178, 71, -142, 28, 97, 68, 34,145,207, 25, 1, 21, 10, 69,159,176,176,176,229, 83,167, 78, 21,157, 56,113,162,133,201,100,106, 40, 48,144, -175,188, 65, 81, 3,167,172, 25, 56,106, 42,249, 34, 7,168, 50, 2,230,115, 59, 88,109,161,186,126, 96,160, 39,101,130, 83, 2, -132,218,202, 74,171,216, 98,129, 65, 44,134,208,158,245,135,253,163,123, 29,151, 7,192,213,242,119,183,207,173, 43,213,133,252, -185,237,223,139,191, 86,148, 20, 95,175,201, 5,208,222,241,242,154, 0,148, 2, 40,146, 60,166,244,234,226, 28, 60,224, 65,205, -241,223, 74,100, 54,218, 76,237,250,114,212,232,171, 32, 16,134, 1, 76, 8,254,245, 1,255, 20,147,137, 19,250,145,119,230, 60, - 32, 5, 99, 80,187, 54,111,179,102, 97,176, 89,116, 0,213,163,248, 96, 38,153, 57, 45,209,171, 44, 11, 4, 0,165,118,162,134, - 0, 98,234, 80, 4, 28,228,111,207, 1, 8,128,231,218,205,228,212, 87, 73,230,199,111, 80,171, 69, 11,161, 99, 97, 47,165, 20, - 54, 43, 69,173, 5,168,170,182,194, 2, 10, 43,101, 32, 20, 17, 44,121,235,147, 6,239,123,246,108,123,144,214,154,213,103, 40, -177,216,173,127, 10,128, 82, 2, 80,135,197, 64, 5, 32, 2, 22, 44, 43,196, 11, 11,198,241,106,195,217,111,207,150,157, 63,123, -222, 19, 1,139, 96, 95,170,225,137,157, 88, 0, 48,153, 76,208,233,116,186,176,176, 48,196,198,198,254, 58,116,232,208,160,107, -215,174,225,236,217,179,246,229, 97, 44, 43,221,180,105,147,218,161, 4,168,121, 40, 1,150,164,196,196,164,174,253,251,219,238, -233,213, 75,239,232,163, 38,212, 93, 17,137,164, 68,251,179,237,202, 35, 41,208,139, 47,190, 40, 3,128, 33, 61,123,222,116, 44, -118,192,128, 70, 17, 68,255,222,189, 63, 99, 24,198,118,242,167,159, 66,219,182,109,123,189,223,240,225,107,110,167, 70,239,134, -212,245,177,177,177,174,209,214,206,117,172, 62, 40, 1, 39, 6,141, 29, 51,108,243,127,190,216, 20,221,173,107, 31,147,169, 22, - 54,139, 21, 44,203,162,121, 68, 4, 42,181, 90, 12,146,203,101, 60,172,127, 0,168,120,243,133,103,219, 0, 48, 23,158, 63, 47, -230,230,255, 15, 29,249, 13,247,203, 70,179,139,211, 63,246,150, 28,200,137,152,246, 58,122,242,212, 73,217,222,157,223,215,113, -241,143, 25,255,144,140,105, 17,223,168,231,218, 80,128,159,251,253,252, 57,108,200, 15,101,192, 15,207, 56,183,239,250,254,198, - 18,224, 74,139,255,235,195,199, 72,199,144,175, 74,190,186,111,220,132,196,237, 79, 62, 62,107,255,221, 3,250,223,187,249,251, - 45,200,253,229, 48, 82, 83, 83,183,173,108,192, 64,243,162, 8,204,250,246,219,111,255,243,237,183,223,198, 37, 38, 38,242,190, -184,113,227,198,141,217,181,107,215,222,173, 91,183, 34, 58, 58, 26, 9, 9, 9, 8, 11, 11, 59, 93, 89, 89, 25,115,252,248,113, - 20, 21, 21, 49, 34,145, 8,227,198,141,147,251,122,159,142,192,192,165, 91,182,108,105, 48, 48,208, 71,121, 63, 43, 20,138,247, -190,203,126,240, 21, 99,212, 12, 24,127,122,149,189,180,111,201,227,190,202,115, 40, 1,181,197,101,101,162, 23, 78,159,190,104, - 51, 24,152, 95, 25, 70,212, 78, 32,184,162, 80, 40,110,203, 20,128,187,108,128,222,166, 0,220, 66,242,152, 82, 15,224, 55,199, -159, 95,120,252,241,103, 52,105,105, 47,201, 50,148,111,171,163,186,244, 0, 96,130, 40, 72,130,139,151,171, 48,122,226, 76,226, -187,188, 7, 53,119,245,138,193,234, 85,223, 0,108, 49, 0, 33,172,181, 70, 68,181, 15,147,117,110, 97,229,255,242,219, 88, 8, - 25, 22, 22, 34,132,136, 90,111, 40, 2,176, 2,212, 6,190,129, 97,174, 72,125,246, 13, 2, 0,139, 95,158, 67, 69, 66,187,181, -111,101,237, 46,243,138,106, 10,155, 21, 16, 8, 89,124,246, 41, 63,165,231,137,100,123,106,228, 85, 95,156,162,224,114,194, 51, - 0, 75,236,238,254,249, 11, 30,240,233, 34, 43,107, 42, 53, 17,109, 35, 26,219,191, 24,192,190,138,194,104, 52,194,102,179,161, -170,170, 10, 2,129, 0, 54,155, 13,237,218,181,131,197, 98,129, 82,169, 84,215,243, 4,168,189,213, 12, 24,212,191,127, 54, 0, - 52, 69,198, 63, 0,136, 36, 68, 3, 0,145, 3, 6,220, 18, 51,175,111,207,158, 25,141, 17,240,194,226,197,117, 86, 73, 44,120, -227,141, 58,158, 1, 95,230,254,221,144,185,222,211,106, 0, 31,210, 1,159,124,112,246,172,126, 0, 4, 39,115,114, 44,181, 6, - 35, 88,155, 13,189, 99, 99,101,237, 99,250,160,235,128, 62,252,222, 57, 74,166,238,252, 97,155,115,115,120,159,104,231,231,157, - 63,108,187,105,219, 83,104,252,233,203, 17,132,105, 17,143,177,227,137,236,196,201,179,184, 92,124, 84, 13, 0,123,119,126,175, -110,219,249,172,172,255,176,127,248,172, 4, 76,153, 50, 5,190,166,247,181, 17,207,121,183, 75, 38,181,195, 15,151,106,111,249, -128, 63,115,230,204, 31, 0, 48, 5, 5, 5,236,158,188, 28,180,108,213, 18,141,169,207,145,152,152,248, 69, 98, 98,226, 87,240, -158,222,185, 14,154, 55,111,174,126,244,209, 71, 73,110,110, 46, 61,123,246, 44,242,243,243, 81, 93, 93, 29,211, 20,181, 0, 28, -100,251,127, 10,133, 66,148,155,155,219,223,108, 54,191,234, 58,151,239,167,188, 69, 10,197, 63, 68, 97,221,191,154, 95,121,118, -215,140, 70,200,179,174, 63,116,232, 1, 0, 9, 0,126, 6,203, 86, 3,184, 58,109,225, 55, 72, 13,123, 4,153,149,127,140, 18, -192,173, 2,112,183,223, 47, 5,192,215,169,132, 6, 93, 85,143, 60,161,217,182,243, 12,121,120, 66, 8,109, 19,213, 9,218,106, - 43, 70, 79,120,220,239,142, 16,127, 79, 47, 18,127,207, 43, 80, 40, 94,167,192, 85, 68, 52, 23,162,115, 36,235,211, 75, 63,228, -159, 11,110, 89,150,176, 55,223, 91, 73, 0, 96,238,188,103,168,217,104, 1, 11,251,178,185,229,159, 46,247,235, 55, 83,102,217, -107, 6,172,250,207, 73,202, 82, 1, 94,126,233,161,219,153,225, 76,236,234,198, 54,153, 76, 48,155,205, 78, 34,227, 8, 44, 80, - 37,208,139, 11,210,135,244,195,126,194,188,112, 97, 82,144,195,131,210,216, 20,100, 20,128,181,215,232,209,117,174,185,107,251, -118,188, 5, 4,177, 38,205, 19, 19,125, 54,252, 80,191, 20,112, 29,251,187, 69,156,166,239,208, 56,244, 29,138, 70,183,165,183, -194, 62,245,117, 96, 43, 9,130,145,241,188, 34,245,108,181, 21, 49,205,249, 12,145, 77,210, 21,232,144, 33, 67,154,178, 79, 89, -252,253, 98,124,124, 60,241,150,136,173, 17,164,253,174, 66,161,248,206, 53, 54,160,145,242,254,165, 80, 40,214,185,198, 6,248, - 33,195, 2,160, 2, 64,189,184,129,107,127, 24,249,123, 34,123,183, 61,110,224,192,129,119,106,249,200, 0,254, 68,232,209,163, - 7, 10, 11, 11, 3, 13, 17, 64, 0, 1, 4,240, 39, 1, 19,104,130, 0,154, 2, 1,242, 15, 32,128, 0, 2, 8, 40, 0, 1, 4, - 16, 64, 0, 1, 4, 16, 64, 64, 1, 8, 32,128, 0, 2, 8, 32,128, 0, 2, 10, 64, 0, 1, 4, 16, 64, 0, 1, 4,112,219, 81, - 39, 52,117,206,156, 57,126, 71,143,186,203,100, 23,144, 23,144, 23,144,119,103,200, 83, 40, 20, 84,169,108,120,217,105,160,253, - 2,242, 2,242,254, 90,242,124, 86, 0,184,129,194, 87, 33,158, 6,150,166,150, 23,192,157, 9,111, 4, 19,192,157,249, 28,124, - 60, 63, 20,192, 61,251,247,239, 95, 34, 16, 8,134, 7, 5, 5,193, 96, 48, 28,188,247,222,123, 23, 1,200, 7, 96,184, 19,218, - 64,165, 82, 73,179,178,178,212,127,197,113,229,216,177, 99,200,207,207,247,122, 94, 94, 94, 30, 61,118,236, 24, 50, 51, 51, 73, -191,126,253, 26, 45,143,195,208,161, 67,225, 73, 94, 0,127, 98, 15, 0, 7, 95,210,147,242, 73,148,227, 78, 94, 67,229, 97,253, - 73,188,243, 87, 31,208,249,158, 59,126,252,120,217, 35,143, 60,162,225, 43, 51, 42,234,230,210,203,165,165,165,117,182,147,146, -146, 32,151,203, 9, 31,121,183, 82, 9, 24, 63,126, 60, 5,128,157, 59,119,146, 59, 65,158, 94,175, 31,187,105,211, 38,213,233, -211,167, 1, 0,209,209,209, 15,166,164,164,108,241,247,249,186,246,123, 74,169,243,253,224,246,115,239, 10, 33, 4, 25, 25, 25, -196,147,242,204,247, 57,248,248,188,250, 28, 59,118,108, 83, 85, 85, 85,175, 46, 93,186,224,250,245,235,168,173,173, 5,128,225, -155, 54,109, 82,135,134,134,158, 76, 76, 76,124, 24,128,199, 82,146, 35, 70,140,240,201, 32, 56,112,224,128, 12, 60, 83, 61,115, -200,202,202, 82, 39, 37, 37,201,228,114,185,198,215,231,145,154,154,234,211,245, 77,153, 50,133,247,251,193,161, 75, 23,123, 5, -220,234,234,106,152, 76, 38,174, 63,241,122,223,242,243,243,241,223,255,122,206, 80,107, 50,153,232,240,225,195,209,187,119,111, -172, 93,187,182,204,100, 50,117,110,104, 93,120,126,126, 62,102,204,152,193,235, 94,175, 94,189,138, 37, 75,150,224, 78,206,109, - 31,192, 13,212, 79, 6,116, 43, 19, 1, 5,172,216, 91,136,239, 51,188,167, 52,126,120,206, 14,159,100,170,213, 55, 12,164,211, -167, 79, 35, 52, 52,212, 57, 8,185,180, 7, 31,107,139,214,223,174, 63,128,169, 84, 42,154,149,149,229,183, 5,182,110,221, 58, -233,248,241,227, 27,148,223, 24,164,165,165,209, 81,163, 70,201,166, 79,159,238, 19, 89,108,218,180, 73,213,166, 77, 27,204,156, - 57, 19, 58,157,142, 77, 79, 79,223,172,211,233,166, 69, 68, 68,248,148, 69,140, 16,130, 31,126,248,193,185,157,152,152,136, 29, - 59,118,120,220,246,134,250, 74,128, 66,161,160,177,177,177,200,204,204,164, 92, 98, 38, 95,201,191,178,178, 50,183,123,247,238, - 45, 0, 64, 34,145, 32, 56, 56, 24,101,101,101,168,168,168, 64, 88, 88, 24,202,202,202,122,237,216,177, 35, 63, 49, 49,177, 39, -128, 43,158,132,245,235,215, 15, 73, 73, 73,136,142,190,145,245,111,233,210,165,117,206, 89,184,112, 33,103,201,170,167, 79,159, -238,243,243,246,135,252, 57,172, 88,177,162,161, 67,206, 90, 5,254, 34, 52, 52, 20, 39, 78,156,128, 72, 36,130,217,108,198,142, - 29, 59, 80, 88, 88,136,151, 95,126,217, 39, 57, 87,235, 21,201,122,240,193, 7, 5, 0,228, 63,254,248,227,142,209,163, 71, 95, -125,248,225,135,219,170, 84, 42, 8, 4,130,214,225,225,225, 2, 95,100, 53,132,243,231,207, 7, 72,226, 79, 74,254,220, 62,175, -181, 0,254,172, 88,181,106,149, 52, 37, 37, 69,211, 88, 57,127, 22, 87,118,212,144,119,110, 88,237, 5,175,250, 37, 67,167,211, -193, 96, 48, 56, 45,144,204,204, 76, 87, 75,136,175,181,117,211,182, 92, 46,199,238,221,187, 41, 33,228,166,227,254,224,199, 31, -127, 84,191,248,226,139,200,206,206,198,228,201,147,155,164,253,118,238,220, 73,246,236,217, 67, 41,165,200,201,201, 81,231,228, -228,248,164,160,156, 62,125, 26, 51,103,206,100, 1, 48, 98,177,152,137,137,137, 65,122,122,250,122, 0,235,163,163,163, 39,164, -164,164,108,231, 35,231, 86, 20, 3,226,148,128,204,204, 76,202,165, 1,230,254, 87, 40, 20, 52, 41, 41,201,151,123, 13,213,233, -116,155, 36, 18, 73, 11, 0,120,250,233,167, 81, 91, 91,139,140,140, 12, 4, 7, 7, 59,203,102, 11, 4, 2, 84, 86, 86,182, 0, -144, 14,224, 31,158, 4,114,228, 94, 84, 84,116,211,190,166, 64, 82, 82,146,204,113,159, 50,127, 21,129,231,159,127,222,249,121, -249,242,229,220, 71,166,222,126,222, 10, 1,231, 53,121,245,213, 87, 17, 26, 26,138,236,236,108,140, 30, 61,218, 47,242,175,143, -145, 35, 71, 2,246, 44,141,255,124,252,241,199,209,163, 71,143,182, 59,118,236, 64,121,121, 57, 87,114,215,236,229, 93,104,234, -238, 39,157, 48, 97,130,122,219,182,109,238,188, 55,210, 49, 99,198,168, 9, 33,216,179,103, 79,192,221,123,139,201, 63,117,225, -251, 0,128,204,165, 47,185, 85, 2,254, 16, 5, 32, 51, 51,211,221,131,166, 13,237,247,231, 55, 14, 29, 58,164, 6, 32,107,172, - 18, 48, 99,198,140,191,205,124,182,193, 96,184,201,234,247,135,104, 56, 98,153, 60,121, 50, 18, 18, 18, 8, 0,100,103,103, 55, -201, 53,174, 91,183, 78,234,176,232, 72, 89, 89,153, 52, 43, 43, 75, 93, 86, 86, 38,245,213, 98,119,135,177, 99,199,146,177, 99, -199, 98,221,186,117,210,156,156, 28,245,186,117,235,124,146,171,211,233,172, 17, 17, 17,226, 77,155, 54,193,225, 13,168,213,233, -116, 76,122,122,250, 54,157, 78, 55, 46, 34, 34, 98,247,237,124,190, 28,233,187,246,101,133, 66, 65, 57, 37,141, 39,238, 41, 44, - 44,236,213,191,127,127,204,154, 53, 11,149,149,149, 40, 47, 47,135, 72, 36,130, 80, 40,132, 80, 40,132, 72, 36, 66,112,112, 48, -180, 90, 45, 84, 42,213,116,185, 92,254,172, 55,161, 69, 69, 69,117,148, 67, 78, 1,224, 60, 1,177,177,177,190, 92,163, 59,235, - 95,150,149,149,165,110,140,231,201, 5,214, 6,198, 74,222,222,128,243,231,207, 35, 39, 39, 7, 19, 38, 76, 64,151, 46, 93,208, -170, 85, 43,228,228,228,224,229,151, 95,118,122,223, 4, 2,129,207, 23, 54,114,228, 72, 44, 90,180, 8, 75,150, 44,105,159,146, -146, 50,245,177,199, 30, 67, 66, 66, 2, 0, 64, 32, 16,204,108,217,178,229, 22,165, 82,105,241, 84, 12,104,221,186,117,188,188, - 0,165,165,165,152, 54,109, 26, 63, 3, 37, 42, 10,169,169,169,234,162,162, 34,168, 84, 42,174,253,165,169,169,169,106, 78,129, - 14,224,214,130, 35,127,238, 51,167, 4,252,225, 30,128,134,230,177,253, 9, 16,188,213, 74,192,253,247,223,223,104, 79,128, 47, -247,229,203,111, 60,250,204, 78,108,250,100,124,147,180, 21,247, 2, 54, 84,169,234,224,193,131,141, 86, 12,154,226,249,254,248, -227,143,106,206,234,159, 62,125,186,230,199, 31,127, 68,155, 54,109,212,104,162,196,233,156,220,156,156, 28,228,228,228,120,117, - 55,235,245,250,251, 55,109,218,180, 13, 0,210,211,211,197,209,209,209, 72, 73, 73,225, 14, 75,126,251,205, 94, 47, 43, 61, 61, -125, 87,116,116,244,195, 41, 41, 41, 94,235,147, 39, 38, 38,214,137,137,185,239,190,251,234,120, 6,248,184,253,221, 40,221,212, - 93,255,226,158,139,235,116,128, 39,236,216,177, 99, 73, 76, 76, 12, 0,224,204,153, 51,160,148,226,212,169, 83,206,186, 15, 66, -161, 16,132, 16,216,108, 54, 24, 12, 6,124,251,237,183,144,203,229, 94,171, 46,185,146,127, 82, 82,146, 91,229,197,117,138,192, - 31, 37, 64, 46,151, 19,133, 66, 65, 27,235, 13,104,138,113,210, 98,177, 96,240,224,193,208,104, 52, 24, 50,100, 8,244,122,189, -115,106, 71,163,209, 96,252,248,241,176,114, 37,200,125,179,252,177,100,201,146, 14, 41, 41, 41, 23,191,248,226, 11,231,177, 14, - 29, 58, 96,217,178,101,255,229, 75,216, 77, 12,205,225,195,135, 17, 27, 27,139,232,232,104, 12, 30, 60,152, 30, 57,114, 68,198, -145,127, 81, 81, 17, 52, 26, 13,159, 24,149,161, 0,158, 1,240, 79,165, 82,105,243,112,222, 4, 0, 81, 0,190, 85, 42,149,215, - 2,212,255, 7,118,108, 62,248, 35,131, 0,155, 66, 9,232,218,181,107,163, 60, 1,220, 32,187,118,237, 90,183,199,183,111,223, -142,181,107,215,250,101,153,228,157,235,131,184,110, 39,252,118,251,115,112,157,243, 87,169, 84,144,203,229, 78,183,255,193,131, - 7,209,169, 83,167, 38, 81,250, 26, 99,125,113,214,255,245,235,215,157,117,230,165, 82,169,172, 41,189, 0, 28, 70,143, 30, 45, -203,201,201, 81,123, 59,111,211,166, 77,219,184,185,127,189, 94,143,165, 75,151,162,166,166, 6, 34,145, 8, 65, 65, 65, 56,119, -238, 28,222,121,231, 29,232,116, 58,164,167,167,127,167,211,233,198, 68, 68, 68,168,189,144,108, 29,178,247, 22, 19,208, 20,138, -231,225,195,135,235,156,223, 80,144, 88,100,100,228,112,147,201, 4,171,213,138,131, 7, 15, 66, 32, 16,192,108, 54,195,104, 52, -130,101, 89,231,123,108,177, 88, 96, 50,153,184,119,218,107,152,120, 67, 46,255,133, 11, 23, 58,189, 0,209,209,209, 40, 43, 43, -107,180, 34,202,173, 10,240, 33,118, 68, 11, 32,210,221, 1,151,233, 0,159,144,158,158,142, 23, 95,124, 17,131, 6, 13,114,122, - 64,184,244,217,131, 6, 13,194,169, 83,167,208,166, 77, 27,159,100,238,219,183, 15, 35, 71,142,236,146,146,146,114,158, 35,127, -199,248, 25,181, 97,195,134, 75,245, 3,122,249, 42, 20, 13,253,150,143,222, 39,114,248,240, 97,105,106,106,170,122,200,144, 33, - 24, 50,100,136, 26, 0, 78,157, 58,133,156,156, 28,190,207,225, 23, 0,193, 0,214, 43, 20,138,105,238,148, 0,133, 66,241, 12, -128,143, 29,155,139, 20, 10, 69, 47,165,210,123,137,250,191, 50,184,106,128,153, 75, 95,186,105, 10,224, 47, 27, 3,112, 39, 42, - 1, 51,102,204,160,139, 22, 45,186,201, 21,232, 15,249, 63,250, 76,211,206,211,233,245,250,155,130,252, 56,171, 95, 36, 18,225, -202,149, 43,183,149,252, 93,173,127, 87,203,109,218,180,105, 26,141, 70,211,228, 94, 0, 95, 60, 39, 51,103,206, 52, 0, 8, 9, - 13, 13,197,107,175,189, 6,145, 72,228, 60,158,156,156, 12, 0,136,136,136,192,196,137, 19,177,127,255,254,189, 19, 39, 78,252, - 67,174,211,181,189, 93,231,255,221, 33, 54, 54,182, 78,165,198,134,214, 17,155,205,102,104,181, 90,212,214,214, 34, 44, 44, 12, - 65, 65, 65,176, 90,173,160,148,194,102,179,193,108, 54,195, 98,177,192,102,179,185, 42,244,215, 61, 93,103, 81, 81, 81, 29,235, -190,254,116, 64,253, 0,193,198, 66, 46,151,107,124,140, 69,145, 52,116,160,129,216, 0,175,120,231,157,119, 48, 97,194, 4,116, -237,218, 21, 33, 33, 33,144, 74,165,208,106,181, 8, 13, 13,133, 78,167,195,234,213,171,193, 48,190,197, 23,142, 28, 57,178, 99, - 74, 74,202,249,121,243,230, 97,243,230,205,120,232,161,135, 0,160,221,190,125,251,174,250,211, 78, 14,133, 2,220,152,197,141, - 85,190,146,191,171, 39, 96,195,134, 13,178,169, 83,167,170, 1, 96,195,134, 13,178,202,202, 74,141, 15,253,217,172, 80, 40,102, - 0, 88,235, 65, 9, 72,112,249,220, 25, 64,127,216,151,164, 6,224, 66,252, 13,225, 47,153, 9,112,216,176, 97,178,166, 8, 8, -244,215, 74,119, 29,144,151, 44, 89,210,104,242,231, 48,120,208, 64,236,217,171,198,186,189, 33, 78,165, 32,239, 92,159, 70,221, - 99,108,108, 44,138,138,138,144,157,157,141, 78,157, 58, 97,205,154, 53,126, 88, 93, 84,202,125, 74, 75, 75,107, 18,242,231,172, -255,178,178, 50, 89,253, 99,163, 70, 43, 88,140, 99, 0, 0, 32, 0, 73, 68, 65, 84,141,146,101,103,103, 59,207,105, 10,228,228, -228,168,249,122,159,116, 58,221,239,176,207, 11,179, 27, 54,108,192,234,213,171, 1, 0,235,215,175,135, 78,167,227, 78,179,158, - 58,117, 10,173, 91,183,190, 45,239,128,107,180,191, 59,229,140,111,153,230,162,162,162,131, 54,155, 13, 58,157, 14,215,175, 95, -119, 6,142, 26, 12, 6,212,212,212,160,170,170, 10,149,149,149, 48, 26,141, 48,153, 76,176,217,108, 0,144,235, 73,102,125,114, -119, 23, 72, 90,127, 85, 0, 95,168, 84, 42,105,253,123, 86,169, 84,190,246,147,144,166,126, 30,107,214,172,129, 84, 42, 69, 72, - 72, 8, 78,156, 56, 1,141, 70,131,208,208, 80,188,254,250,235,216,191,127, 63, 94,126,249,101,159, 20,128,145, 35, 71,182, 75, - 73, 73,185, 48,109,218, 52,124,243,205, 55, 28,249,119, 0,112,213,147, 37,207, 71, 9, 88,178,100, 73, 83,144, 63, 0, 72, 57, -242, 7,128,169, 83,167,170, 71,143, 30, 77,125, 28, 67,205, 0,184,117,138,235, 21, 10, 69,253, 64,137, 51, 46,159, 75, 0, 28, - 13,208,190,203, 56,176,240,253, 58,177, 0,245,241,151, 9, 2,108,106,242,119,172,119,109,180,229,198, 77, 7,204,152, 49,195, -111,242,127,244,153,157, 24, 60,232,134,235,102,211, 55,223, 98,211, 55,246,207,123,246,170,129, 49, 50, 0,190, 45, 3, 84, 40, - 20,136,141,141, 5, 96, 15, 6, 60,124,248, 48,118,239,182,199,172, 29, 61,122, 20,163, 71,143,246, 65, 26,209, 0, 55, 2,255, - 26, 27,169,191,110,221, 58,169, 59,235,191, 62,154,202, 11,192, 41, 18, 82,169, 84,230,237,220,232,232,232,113,233,233,233,187, - 38, 78,156,136, 83,167, 78,225,244,233,211,120,231,157,119,172, 0,132, 6,131, 1,233,233,233,112, 28, 19, 22, 23, 23,227,241, -199, 31,247, 42,243, 86,196, 0,112,150,116, 86, 86,150,211,139,197, 17, 35,247,220,249, 32, 38, 38,166,192, 96, 48, 12, 55,155, -205,184,118,237, 26,130,130,130, 32, 20, 10,157, 30, 0,189, 94, 15,131,193, 0,147,201,132,202,202, 74,110, 62,255,162, 39,153, - 28,185,115,211, 0,177,177,177,168,239,173,112, 23, 23,192,135,252,185, 28, 0,245,247, 53,166,127,112, 86,191, 27,139,223,202, -119, 12, 45, 44, 44,196,169, 83,167, 96, 48, 24, 16, 31, 31, 15,131,193,128,172,172, 44, 76,157, 58, 21,155, 55,111,134, 64, 32, -224,173, 0,196,196,196,116,228,200, 63, 63, 63, 31,111,188,241, 6, 0,116,158, 49, 99,198,229,181,107,215,146,125,251,246, 53, -106, 12,229, 60, 1,141, 33,255,216,216, 88,202,245,179, 35, 71,142,160,160,160, 64,150,154,154,170,238,217,179, 39, 68, 34, 17, -117, 9, 12,244,219, 19,160, 80, 40,230, 2,152, 0, 96, 50,128, 54,176,199, 0,252,173,221,255,192,141, 85, 0,238,130, 0,111, -203, 42,128, 63, 42, 8,240, 78, 35,255,250, 74, 64, 99, 44,127, 79,219,123,246,170,253,121, 65,111,152, 59, 33, 33,232,221,187, -119,157,227,135, 14, 29,242, 73,222,228,201,147,157, 10, 64,118,118, 54,178,179,179,235,172, 10,240,229,254,215,172, 89,163, 6, -128, 29, 59,118,184, 37,207,233,211,167,107,214,172, 89, 3,128,223, 18,166,134,146,254,112,138, 6,165, 20,163, 71,143,150, 77, -155, 54,205,107,223, 73, 73, 73,217,173,213,106,199, 30, 56,112, 96, 79, 76, 76, 12, 78,159, 62, 13,157, 78, 39,140,136,136, 64, - 74, 74, 10,180, 90,109,241,129, 3, 7,186,196,196,196, 96,230,204,153, 94,239,215, 93, 30, 0,127, 99, 0,234,191, 91, 74,165, -146,200,229,114,168, 84, 42, 90,127, 90,134,239,243,136,139,139,123, 69,163,209, 60,103,179,217, 80, 85, 85, 5,139,197,226, 84, - 86,106,107,107, 65, 41,173, 19, 24, 40,151,203, 31,115, 16, 35,111,200,229,114,200,229,242, 58,203, 2,125,157, 2,112, 37,122, -185, 92,174,169, 63,182,184, 42, 5, 77, 8,222,227, 39,183,212,239,133, 23, 94,128, 70,163,129, 76, 38, 67, 97, 97, 33,154, 53, -107,134,146,146, 18,222, 10,192,161, 67,135, 72, 74, 74,202,133,199, 31,127, 28,251,246,237,195,235,175,191, 14, 0, 81, 51,102, -204,184,212, 20,228,239,170, 4, 52,198,242,231,198,151,162,162, 34, 20, 20, 20, 16,135, 33, 40, 75, 77, 77, 85, 71, 71, 71, 67, - 42,149, 82, 62,129,128,245,148,128,105, 0,214, 59,148,128,131, 0, 20, 0,164, 74,165,242, 10, 2,104,186, 14,220,212,217,248, -220, 5,252, 44, 93,186,180,193,253,183,147,252,103,204,152,113, 75, 82,134, 54, 70,230,133,139,222,251,119,112,176,111, 94, 75, - 79,243,195,254, 64, 46,151,203, 18, 18, 18, 52,123,246,236,161, 27, 55,110,172,163, 8,212, 39, 37,190, 50,211,210,210, 26,212, -108,184,164, 36,190, 36, 6,106, 72,225,148,201,100,188,200,159, 67,100,100,164,115, 94,255,196,137, 19,255, 72, 79, 79,255, 47, -231, 17, 40, 46, 46,238,242,234,171,175,202, 8, 33,188,228,221,138, 60, 0,245,219,217,221,252,183, 15, 74,169,126,244,232,209, -139,183,111,223,254,166,213,106, 69, 69, 69,133, 51, 6, 0, 0,174, 93,187,134,138,138, 10, 80, 74, 57,171,221,167,201,118,110, -254,191,254,178,191,250,113, 2,124,201,223,245, 57,223,105, 75,121, 57, 37,224,165,151, 94, 66, 78, 78, 14, 38, 78,156,136,247, -222,123, 15, 11, 22, 44,128, 80, 40,132, 68, 34,241,246, 92, 9,165,148,157, 53,107, 22,254,251,223,255, 98,213,170, 85, 0,208, -105,223,190,125,151, 28, 22,187, 95,157,201,101,218,170,201, 80, 90, 90, 10, 55,121, 0, 52,153,153,153,178, 49, 99,198,168,253, - 89,242,232,176,250,167, 1,216, 10, 96, 46,128,184, 0,249, 55, 12,119, 65,128,188, 20, 0, 95,146,114,248, 75,216, 77,141,166, - 32,255, 59,113,208,152, 59,119,174,236,228,201,147, 77, 42,211, 97, 13,169,155, 82, 38, 71,120,220,218,122, 0,206,100, 64, 44, -203, 98,211,166, 77,188,149,128, 23, 95,124,145,187,206,155, 98, 0, 24,134, 1,203,178,248,215,191,254,165,230, 75,158,158,228, - 53,118, 37, 65, 74, 74,202,255,180, 90,237,181, 3, 7, 14,236,224,107,245,223,106,111, 91,253,246,117,231, 98,247, 69, 9, 32, -132,188, 53, 97,194,132,236,181,107,215, 30, 23,139,197,224, 86, 5,176, 44,139,240,240,112,232,116, 58, 46,133,109, 8, 0, 27, - 95,131,192, 53,248,239,240,225,195,144,203,229,117,198, 19,111,227, 80, 81, 81, 17, 45, 42, 42,146,213,119,241, 55,114,201, 31, -128, 6,221,253,214,229,203,151, 75, 0,152, 97,143,159,226,254,124, 82, 2, 92, 19,255, 60,245,212, 83,206,207, 85, 85, 85, 94, - 95,179,184,184, 56,210,183,111, 95,250,213, 87, 95, 61,188,126,253,250,239, 57,178, 93,191,126, 61,124,141,250,231,112,233,210, - 37,103, 74,226, 38,130,102,219,182,109, 13,245, 41,205,222,189,123,125,170, 85,225,225,240,101,119,217, 74,255,238, 53, 73,184, - 85, 0,238,136,159,215, 42,128,166, 38,245,134,228,221, 41,202,195,157,220,113,250,244,233,163,233,211,167, 79,147,202,116, 12, -142,183,252, 94, 93,221,255,245, 95,234,134,150,157, 57,174,143,207,181, 17, 31,238,247,150,222,107,100,100,228,206,198, 68,250, - 55,101, 12,128,187, 62,236,201,219,227, 67,159, 63, 49, 99,198,140,102,187,118,237,122,183,164,164,228, 57,163,209, 8,155,205, -134,129, 3, 7, 98,200,144, 33,233,114,185,124, 33, 31,242, 7,128,188,188, 60,231,103,215, 88,147,188,188,188,155,182, 61, 33, - 58, 58,154, 56,188, 4, 50, 0,106, 78,153,112,153, 10,240,249,153, 76,153, 50,165,161, 67, 66,151,241, 82,124, 59,198, 21,165, - 82,201, 30, 59,118, 12, 31,127,252, 49, 1,192, 43, 41,207,179,207,122,206,201, 52,116,232, 80, 76,154, 52,137,247, 53,120,147, - 23,192,157,167, 4, 52, 68,254,110, 21,128,166, 38,193, 64,133,184, 0,220,245, 1,127,203, 87,254, 29,218,230, 14,254, 13,253, -184,113,227,230,194,238,126,245, 11, 7, 14, 28, 32,211,167, 79,191, 37, 10,173,191,153, 3,255, 72,101,177,177,232,215,175, 95, -147, 22,227,105,106,121,127, 7,163,236,207,164, 4,120,181,162, 6, 14, 28, 24, 24,136, 3, 8, 32,128, 0, 2, 8,224,111, 6, - 38,208, 4, 1, 4, 16, 64, 0, 1, 4, 16, 80, 0, 2, 8, 32,128, 0, 2, 8, 32,128,128, 2, 16, 64, 0, 1, 4, 16,192,159, - 16, 86, 0,108,160, 25, 2,240, 4, 97,160, 9, 2, 8, 32,128, 0, 2, 99,123, 0,127,243, 78, 50,103,206, 28,191, 35, 46,221, - 69,117,123,146,231,109,253,177,175,242,154,250,250, 2,242, 2,242,254,238,242,126,126,165,216,239,129,101,208,187, 93,112,171, -229, 29,126,217,127,121,177,239,221, 44, 47, 45, 45,141, 0, 0, 33, 68,106,177, 88,112,238,220, 57,181,217,108,134, 80, 40,196, -197,139, 23,241, 88, 88, 87,236, 44, 40,128,241,238, 78,136,139,139,147, 9, 4, 2, 80, 74, 53, 0,144,145,145,113,203,159, 7, -119,125,174, 32,132,244, 1,208,230,248,241,227,219, 58,116,232,192,104,181, 90, 73,135, 14, 29,222, 9, 14, 14, 94, 9,224,146, - 99, 57, 41,147,145,145, 97,243, 32,175,185,195, 91, 96, 32,132, 80, 0,184,112,236,127,159, 43, 70,150,164,172, 43,136, 57, 39, -108, 51, 46,174, 89,243, 22, 53, 0, 40,165, 84, 8, 32, 34, 35, 35,227, 66,224,125,187,179,229,221, 82, 45,145,111,182, 45, 95, -179,191,249,147, 50,183, 98,245, 55, 82, 97,100,152,250,236,233, 51,178,187,130,154, 33,244,217, 25,154, 59, 73,203,106, 40, 31, -121, 96,137,203,237,199,230,205,155,165,219,183,111, 87,167,191, 98,223,254,110,223, 72,204,152, 49,131,215,115,217,151,123, 80, -202, 16,162, 62,117,242, 36,116, 58, 29,186,116,233,130,102,205,155, 35, 49, 97, 28,239,231,186,123,247,238, 58, 47,110,118,118, -182,199, 90, 10,217,217,217,126,247, 27,174, 80, 83, 70, 70, 70,227,250, 93,146,214,241,129, 2, 32, 64, 86,164,255,178, 98,151, - 3,209, 79,216, 63, 23,173, 6, 14,207,111,252, 67,157,124,189,238,245,101,183,226,245, 53, 66, 8,213,235,245,178, 93,187,118, -169,139,138,138,144, 36,106,137,118,157, 90,163, 86,111, 68,176,193,138, 17, 11,158,196,168,137, 83,177,245,139, 12,108,217,179, - 71, 61,110,220, 56,217, 29,208,133, 79,219,108,182,246, 69, 69, 69,236,128, 1, 3,196, 49, 49, 49, 56,114,228,200, 43,181,181, -181, 19,122,244,232, 33, 39,132,104, 41,165,222,166, 2,170, 93, 55,172, 86, 43,243,107,193,207, 61, 58,206, 26,132,127, 13,237, -219, 58,111,215, 7, 27, 55, 29,149,254,210,163,223,152,247, 28,242, 46, 58, 20, 6, 54,224,105,248,155,185,137,124,205,223,239, - 75, 30,124, 95,201,223,182,110,155, 52,190,117, 71, 53,137,138, 70, 97, 77, 5,218,119,232,170,182,176, 54,156,252,100, 13,202, -186,180,150, 13,157,120, 63, 47, 69,224,176, 90, 65,123,117,231,182, 4,248,118, 23,139,125, 63, 81,164, 78, 3,122,117, 7,230, - 47,105, 28,113,115, 5, 74, 26,155,157,204,157, 50,209, 84,114, 27,131,212,212, 84,138,197, 4,228,173,134,207,161,148, 2,139, - 9,166,252,158,116,199,172,181,190, 65,254,212, 65,254,163,176,127,255,126,204,152, 49,195,235,119,239, 30,176,139,246,233, 51, - 4, 89, 89,151,113, 40,215,158,176,230,244,201, 83, 0,128,217,255,252,134,158, 58, 51, 89, 22, 42,225,247, 92, 18, 18, 18,216, -221,187,119, 51,217,217,217,216,187,119,175,199, 66, 76,254,164, 80,245,244,222,166, 41, 20, 52,195, 15,133,130, 75, 23,222,232, - 84,198,209, 79,212, 45,182,211, 20, 10,128, 75, 59, 57,170, 19,242,194,217,179,103,161,217,184, 81,253,150,124, 10, 6,206,120, - 10,226,182, 17,128,208,145,236,143,165, 0, 43, 2,107,162,184,255,137, 84,148,124,244, 62, 14, 30, 60,168, 30, 62,124,184,140, -243, 2,220, 38,216, 24,134,105,211,170, 85, 43,104, 52, 26,225,128, 1, 3, 48,116,232, 80,230,202,149, 43,131,126,253,245,215, - 99,119,223,125,247, 96, 66,200, 21, 7, 89, 51, 60,219,174,217,216, 49, 9,209,239, 45,219,204, 44, 76, 62,218, 34, 46,113,142, - 44,110,152,106,228,130,143, 47, 62, 16,115,207,204, 88, 66, 72, 53,236, 49, 6, 76, 67,253,204, 53,177,149,183,126,212,104,133, - 52,128, 58,168,159, 0,168, 62,252, 42, 6,228, 58,128, 12,156,217, 31,115, 70, 60,195,128,103,229,190,250, 74,128, 66,161,160, -177,177,177,200,204,204,164,174,101, 75,125, 34,214,156,195,210,233,131,226,213, 98, 27, 11, 27, 40,130, 43, 66,112,229,218, 53, - 92,169,174, 68,183,160,102, 48, 21, 94, 82, 31,218,178, 93, 54,140,135, 18,208,171, 59,112,242, 44, 3, 74, 37,176,145, 32, 60, -156, 96,193,164,113, 70,220,136,161,105,124,170,132,198,146, 52, 71,252, 11, 23, 46, 68, 65, 65, 1, 0, 96,219, 73, 17,106, 45, - 22,181,226,159, 67,124, 82, 4,124, 81,226, 28, 41, 94, 61, 63,151,197,246,195,177,177,177, 13,231,111, 95,236,223, 59,190,245, -179,203,210, 45,191,190,225, 84,120, 38,244, 95, 44,123,240,153, 14,141, 30,112, 55,111,222, 44,221,182,109,155,154, 97, 24,188, -240, 46,156,213,207,248,212,193,136,136,248, 81, 26, 55, 44, 13,192, 22,140, 28,249, 81,157, 99,211,167, 3,247,223, 15,220,143, -108,245,242,143,192, 75, 9,224,200, 95,163,177,159, 58,117,234, 84,103, 97, 37, 95, 8,204,147,229,207,165,100,118,189,191,180, - 52,255,200,191,201, 16,187, 12, 0,176, 98,197,138, 27, 10,192,224,116,224,200, 11,183,229,114,246,238,221,139,149,147, 82,209, -109, 76, 2, 32, 48,129,136, 24, 16, 33, 3, 34, 16,129, 82, 2, 86,111, 5,181,217, 64,205, 54, 60,249,196, 83,120,234,245,185, - 56,219,182,173,186,123,247,238,183,211, 19, 64, 10, 10, 10,226, 59,117,234, 36, 46, 42, 42, 66, 78, 78, 14, 78,158, 60,137,132, -132, 4,196,199,199,183, 95,181,106,213,219, 83,166, 76,121,210, 7, 5, 64,176,127,207,215, 95, 62, 50,208,208,246,112,181, 0, -211, 23,215,224,222, 65, 31,226,153,121, 83,133, 31, 44,172,232,182,240,131,181,211,163, 7, 77, 87,162,129, 52,200,174,132,238, - 58,166,167,165,165, 81,119,251,155,186, 32, 92, 0,183,192, 3,224,250,144,214,237, 88, 91,209,253,174,238,225,138,183,158,100, -231,140,120,198,151,106, 78, 36, 51, 51,147,114,105, 73,185,255, 21, 10, 5, 77, 74, 74,242,205,170,222,113, 80, 58, 62,166,175, - 90, 92,107, 69,240, 7, 47,194,106, 48, 67,242,194, 18,132,137, 37,168, 21, 25,161,175, 53, 34, 24, 4,166, 11,101,234,202,202, - 74, 89, 88, 88,152,199, 65,248,228, 89, 32,115, 61, 11,192,224,248, 3, 70,222,195, 96,210, 56, 2,215, 64,218,212,105, 64,230, -122, 63, 60,166, 73, 73, 50,199,125,250,101,173,115,228,207, 17, 63, 0, 40,247, 91, 96, 52,235, 1, 0, 99, 23,238, 70,214,210, - 4, 53, 0,222,242,207,190,127, 22, 34, 82,120,163, 35,144, 82,144, 86,189, 92,182,203,208,250,159,252, 82,132,146,183,236,228, -239,169,198, 60, 81,100, 81,251, 57,252,172,255, 35,219, 44,210,204,205,207,170, 41, 40,222,155,247, 29,134, 73, 99,176,238,179, -125,248,207,174, 52,245, 54, 5,197,156,127,188, 33, 27, 56,178,189, 95,138, 64, 77,177,130,142, 25, 0,100,125,117, 28,148, 82, - 52,111,115,183,147,252, 87,174, 92,233,241,250,244,181, 42,105,106, 82,123, 53,240, 41,128,239,112,232, 16, 48,108,216,141,227, -111,191,125,227,243,243,207,101,171, 51,254,211, 83,198,176,157, 60, 94, 39, 71,254,163, 71,143, 6,203,178,248,228,147, 79,154, -236, 5, 87, 40, 20, 78,242,175,171, 20, 40,104, 70,134,231,119,142,153,162,171,163,254, 18,199, 63,108,146,155,243,136,227, 68, - 98,255, 48, 96,192,205,115,236,204, 84,157,211, 43, 15, 0, 44,155,140,121,243,230, 57,143,207,155, 55, 15, 43, 86,172, 0,211, - 99,214,141, 95,117,156,239, 78,158,112,170,251,235,179, 90,221,156,199,227,250,106,107,107,209,174, 75, 87,128, 53,131, 9, 2, -136, 80, 0,107,117, 37,106,139,206,225,218,197, 82,116, 28, 46, 5, 17,135,131, 88,204,128,128,193,210, 57, 11,144,144,249, 6, -230,207,159,223,164,131,178,183, 84,217, 46,100, 75, 40,165,225, 70,163,113,120,100,100, 36, 78,157, 58, 5,150,101,113,238,220, - 57,172, 94,189, 26,189,123,247, 70, 84, 84,212, 76, 0, 79,214, 35,107,182, 33,242,166,148,182,234,194, 28,146,182,239,156, 40, -174,200, 57,138, 74, 93, 16,254,187,213,138,237,121,255,195,115, 73,193, 66,161,129,141, 5,166, 55, 88, 7,225, 86, 20,183, 10, -192, 55, 52,212,119,220,121, 6,132,124,137,159, 82, 10,217, 43,163,145,153,163, 12, 79,133, 2,191,124,117, 20, 24,225,124,173, -120,129, 35,125,131, 97, 45, 0,130,218,218, 85,136,140, 84, 33, 43, 43, 11,190,164,241, 28, 26,212, 66,221,166,214, 6,201,226, -167, 96,187,174,133,245,210,117, 8,197, 34,132, 16, 1, 66,137, 0,161, 2, 33, 34, 69, 18,232,170, 43,112,121,239, 65,117,216, -164,251, 60, 14,116,238, 72,125,223, 79,172, 67, 1, 0,150, 45, 34,160, 4,176,135,199,248,222,193, 29,164, 44,203,202,202, 82, -103,101,101,249, 53,133,224, 74,254, 16, 10, 80,116,217, 62,248,149, 92,173, 69,231,182, 18,244, 72,222,130,172,213, 19,213,124, -221,235, 34, 82, 8, 33, 41,133,128, 92,135,141,182, 66, 80, 27,130,208,105,151,192,178, 90,212,214,102,193, 86,240, 47,223, 60, -185, 60, 42,183,249, 82,226, 85,185,249, 25,117,124,228,171,248,228,187, 89,104,198,116, 6, 0, 60,245,108, 79, 12, 24, 26,141, -181,159,230, 96,229,255,222, 84, 43, 71,250,231, 58, 36, 4, 80, 60,127,204, 57,232,221,123,239,189,216,183,111,159, 87,242, 7, -128, 25,211, 68,106, 96, 47,128, 99,168,184,218, 12, 61, 58, 3,159,127, 94, 3,181, 26,232,209, 3,136,142,182,139,168,184,218, -204,254, 50,246,255, 93,253,219,175,157,136, 39,242,223,187,119, 47, 88,150,117,146,244,134, 13, 27, 26, 77, 32,174,219,245,201, - 31, 0,188,145, 63, 0,100, 40,149,132, 2, 82, 2,104, 82, 83, 83, 27,236,248,172,203,160,175,204,204,148, 17, 2,172,252,108, -229, 77, 49, 47, 43, 51,148,174,254, 21, 41,165, 84,253,225,135, 31, 58,119,124,248,225,135, 88,177, 98, 5, 50, 50, 50,234, 86, -145, 35,144,186,147,151, 97, 79, 97, 43,163,148,106,158,124,242,201, 6,175,207,234,226, 69,201,252,252,115, 25, 33, 64,198,202, - 12,181, 59,242, 18, 54,111, 14,136, 4,176, 25, 42,240,251,246, 61, 88,187, 49, 27,159, 93, 58, 7, 0,200,127,179, 5,122,140, -186, 31,166,146, 11, 56,254,235, 97, 28, 61,119, 26,149, 87,174,224,216,177, 99, 77, 86, 88,107,245,234,213, 82,126,125,152,132, - 81, 74,123, 21, 20, 20,124,240,218,107,175,245,253,224,131, 15,196,102,179, 25, 2,129, 0,205,155, 55,135, 94,175, 71,126,126, - 62,162,163,163,185,186, 5,158,172,255, 80, 66, 8, 75, 41,141,172,184,120,224,167, 55,191, 44,137,252, 98, 94, 7,104,245, 98, -136,133, 12, 58, 70, 72,112,229,186, 25,138,127, 91, 49, 96, 72,108,104,103, 47,158,132,180,180, 52,202, 41, 2,174,125,177,161, -207, 1,220,122,112,228, 95, 95, 57, 96,188, 13, 34, 92,189,239, 58,110,206,196, 25, 62, 95, 64,102,102, 38,181,147,255, 58, 39, -249, 75,126, 58, 15,195,206,187,234, 28,247,106,185, 42,215, 73,195,180,213, 96,197, 66,152, 15, 31,135,233,247, 34,212,238,218, - 7, 24, 77, 16, 83,138, 16, 8, 32, 4,129,137,181, 66,107,170,197,103,187,183,122,149,185,108,145,221,186,119,133,125,155, 51, - 87, 40, 78,157,161,152,191,196,255, 62, 43,151,203, 53,174,110, 47,149, 74,197,235, 69, 87,169, 84,206,218,218, 28, 30, 91,113, - 17,123, 14,235, 80,114,181,214,169, 4, 20, 94, 52, 2,242,141, 80,169, 84,188,220,145, 66, 98,175, 28, 38,170, 62,138,208,208, - 51, 8,146, 84,131,101,181,176, 88, 14, 67, 32,136,134, 89, 95,126,219, 58,235,158,111,143, 73, 1, 82,135,252, 47,159,162, 24, - 60, 81,128,103,223, 73,192,189, 9,125, 1, 80,199,121,190, 97,221,186,117,244,133,119, 9,154,181,238, 15, 10, 32,113,210, 28, -236,223,191,159,215,119, 89,230, 2,109,211,230, 55, 39,249, 87,151,219, 75, 48, 15, 24, 96, 39,127,174, 16,160,253, 88, 48,170, -203,131, 17, 25,114,217,163,204,201,147, 39, 67, 38,147, 97,204,152, 49,152, 58,117, 42, 4, 2,193, 77,127,174,251,249,194,221, -123,235,151,178,228, 66,196,132, 16,231, 95, 67,251, 8,160, 1,133,166, 1, 89, 55,222,175,212, 84,181, 59,203,121,222,188,121, - 72, 77, 77,173, 75,168, 13,200,251, 78,169,196,177, 99,199,212,132, 16, 41,128, 58,109,230,244,103,215,219,231,233,250,196,148, -130, 9, 9,130,229, 74, 49,148,175,190,138,213,250, 10,232, 70,199, 57,143,127,241,191,213,120, 99,193,108,196,204,127, 12,111, - 29,221,139,141,186,115, 72,120,240, 65, 68, 71, 71,251, 60, 5,176,122,245,106,169, 66,161,160,171, 86,173,170,211,135,243,242, -242,212,158,166,161, 8, 33, 34, 66,200,144,163, 71,143,150,228,228,228,104, 94,120,225,133,184, 79, 62,249, 68, 82, 83, 83,227, - 44,211, 92, 91, 91,139,102,205,154, 21, 78,153, 50,165,231,136, 17, 35, 58,123, 81, 36, 24, 66, 72,151,163,185,155,202, 78,239, -156,127,126,254,203,233,237,183, 44,238,128,223, 75,133,168,172, 17,128, 37, 64,121,141, 25,180,101,247,218,231, 95, 89,210,247, -129,135,255,225,117, 58, 33, 35, 35,131,112, 99,157, 82,169,244,250, 57,128,219, 67,254,110, 61, 0,174,196,207,103,156,241,197, - 18,185,225,106, 91,229,214, 59, 80, 39,206,160, 1, 55, 70,223, 86,109,213, 90,106,129,184, 92, 11,201,119,123, 65,132, 12, 80, -107, 6,173,214,131, 88,173, 16, 1,176, 81, 22,181, 54, 43,170,173,102,128,245, 62,135,202, 5,249, 45, 91,212,240, 48,104, 15, - 18,108,252,128,170, 84, 42, 9,231,210,231, 99,173,223,100,253, 3,248,250,153,246,117,182,135,188, 84, 4, 17,189, 14, 11,105, -133,172,172,172,189,124,189, 0,146, 26, 53, 34,223,250, 31,174,189,144,134,235,218, 96,116,176, 28,135,205, 86, 4, 0, 40,254, -165,221,109,235,176, 27,119,124,172,158, 61, 78, 89,135,252, 57,196, 69,188,138,225,125, 39, 35, 62,242, 56, 54,238,120, 71, 61, -118, 18,255, 65,100,237,218,181,244,199, 31,127, 68,121,249, 88,180,108,185, 7,205, 90,245, 3,165, 20, 12,195,240, 10, 68, 42, - 41, 1,138,138,142,113, 19, 9,128,164, 6, 90, 61, 48,116,168,125, 79, 97, 33,240,233,167, 64,117, 21,160,175, 1,106,244, 64, -104, 68, 21,175,107,107,104,174,255,236,217,179, 0,128,119,223,125, 23, 0, 16, 19, 19,211,100,110,102,215, 62,201,231, 59,115, -231,206,133,171,197, 94,159,184,125,128, 20,184, 49,247,239, 10,206, 11,224, 56, 71,227, 73,200,172,168, 24,156, 62,126, 2,165, - 17, 17,106,134, 97,240,220,115,207,225,163,143, 62,242,251,250, 70,154,194, 65,217, 26,204,126,119, 17,250, 79,158, 12,229,187, -239,130, 97,110,240,156,178,240,216, 13, 15,225,190,125,216,189,123, 55,206,157, 59,231,115, 16,224,234,213,171,165,185,185,185, -106, 0,200,207,207, 87, 51, 12, 35, 75, 78, 78,214,172, 90,181, 74, 74, 41, 69,124,124,188,204,104, 52,170, 27, 80,236, 44,121, -121,121,253,103,204,152,209,162, 91,183,110,216,190,125,187,161,178,178, 82,104, 52, 26,237,222, 14,199,252,199,248,241,227, 99, - 8, 33,193,148, 82,163, 27, 49,140,139, 60,166,232,212, 47, 43,222,248, 87, 74,179,150, 61,178,240,115,214, 19,248,237, 2, 65, -201, 85, 33, 64, 25,152,204, 22,104,105,203,210,167,103, 61, 21, 71, 8, 41,165, 77,160, 85,242,137,179, 9,224,143, 65,131, 83, - 0, 57, 57, 57, 55,237,171, 40,213,249, 76,118,174, 30, 0,251, 20,128,189,255, 72,126, 58,143,160, 99,165,176,133,219,173,168, -250,115,200, 13,173,107, 60,113,177, 4,134,160, 96, 68, 91,173,232, 24,220, 12, 33, 34, 49,136,197, 2,176, 20, 86,155, 13,213, - 54, 51, 12, 54, 43, 76,212, 6, 27, 40,168, 15,157,109,254,146, 27, 74,128, 61, 46,224, 6,233, 47, 91, 36, 64,250, 34,130, 23, -150, 88, 27,221,232,114,185, 92,195,149, 46,229,131,133, 89,246,118, 95,154, 20,225, 36,124,167, 43,159, 94,135, 8,128,144,234, -240,213,236, 8,235, 99, 42,126,113, 29,162,171, 63,193, 6,187,155,250, 3, 97, 24, 30,187, 90,140,130,127,119, 68,104,187,222, -168, 44, 45,197,149,243,151,110,107,199, 28, 48, 52, 26,122, 71,119, 51, 4,159, 64,136,177, 15,190,121,211,226, 60, 62, 66,222, - 23,185, 27,125,179,252, 39,141,250, 17,223,125, 39, 71,120,174, 10,203, 23, 1,207, 47,161, 24, 53,106, 20,239,101,127, 93, 59, -118, 34,221,187,215,213, 2,183,110,181, 7,254,173, 91, 7,244,232, 65,177, 98, 5,193, 91,111,213,216, 21, 4, 0, 61,122, 70, -224,133,231,249, 93, 35,103,165, 78,158, 60, 25, 27, 54,108,168, 99,201, 38, 38, 38, 54, 72,110,254, 42,162, 62,122,240,100, 43, - 86,172, 80, 55,164, 0, 44, 91,182, 12,153,153,153,188, 44,225, 39,159,124, 82,205, 69,254,187,195,243,207, 63,143,229,203,151, -171, 51, 51, 51, 61, 94,227,143, 39, 74,240,202, 91, 11, 48,107,241,191,240,178,217,140, 15, 63,252,176,193, 54, 90,182,108, 25, - 84, 42, 21, 8, 33,210,134, 8,123, 84,159,206, 88,245,197,167,136,157, 62, 29,111,190,249,166, 71,165, 97,222,188,121, 88,182, -108, 25, 62,255,252,115,141,175,109,159,155,155,171,230,130,229, 20, 10, 5,205,203,203, 83, 39, 39, 39,147, 67,135, 14,169, 9, - 33, 72, 78, 78,214,172, 92,185,178,193,239, 27, 12,134,240,173, 91,183, 98,236,216,177, 40, 44, 44, 12,209,235,245,176, 88, 44, - 96, 24, 6,102,179, 25, 73, 73, 73,196, 65,238, 70, 62,142, 45,147,201, 36, 62,188,105, 58, 70, 61,242, 22,118,230,156,197,185, -203, 2, 84,233, 25, 8,132, 64,169, 62, 24,207,189,180, 40, 30,192, 69,190,220,207,197,157, 0,252,166, 3, 2,184, 61,214, 63, -220,185,113, 56,215,140, 84, 42,133, 84, 42,197,175,191,254,234,252, 43,250,169, 24,149,198, 74,180, 28,234,251,186, 95,142,220, - 67, 66,102, 64,242,211,121,136,138,203, 65, 9,129,120, 86,121,157,227, 94,137, 75, 44,128,141, 2, 23,245, 21, 40,169,212,226, - 90,149, 14,149,181,181,208,153,141,184,102, 50,226,114,173, 1,165,181, 53,208, 90, 76,208,177, 22,152, 89,239,217, 48, 71,222, -227,102,192,115,137, 11,152, 61,181, 25, 40,196,160,190,149, 1,119,186,240,235,119,118,190,238,127,167,229,121,181, 22,123, 14, -235,234, 16, 63, 71,254, 65,108, 49,130,216, 98,188, 49, 94,136,146,146, 18, 51, 95,153,155,206,177,104,157,158,225,220, 62,167, -183,225,226,217, 82,156, 58,112, 28, 87,206, 87,220,246,142,187,238, 51,187, 2, 90, 85, 70, 17, 98,236, 3,233, 44, 33, 30, 89, - 44,114,254,165,111,156, 14, 2,194,123, 64,122,232,222, 28, 60, 49, 95,142,136,188, 61, 32,132,224,251, 3,246, 71,192,151,252, - 57,196,244,234, 89, 79,177, 0, 62,249, 4, 56,115,198,238, 9,120,243, 77,234,116,191, 83, 74, 17, 17, 17,225,125, 4,118,244, - 81,155,205, 6,155,205,134,119,223,125, 23,103,207,158,197,233,211,167,113,250,244,105,168, 84, 42, 44, 88,176, 0, 37, 37, 37, -183,243,145,104, 26,178,164,231,206,157,203, 89,117,188,200,144, 16,226,214,250,231,224,233,152, 43,246, 5, 85,128, 48,205,240, -159, 87,150,160,217, 86, 21, 82, 83, 83,225, 90,106, 88,209,163, 31,230,198, 14, 71, 72, 72, 8, 70,141, 26,133,215, 94,123, 13, - 42,149, 74,173,211,233,220,190,127, 95,148,158,198,229,190,125, 16, 21, 21, 37, 99, 89,182, 65,111, 7,231,169,240,215,243,226, - 26, 41, 31, 31, 31, 47,227,136, 18, 0,226,226,226,100, 94,218,110,204,168, 81,163, 90,148,148,148, 96,223,190,125,184,235,174, -187, 32, 20, 10,157,202, 98, 84, 84, 20,223,233, 8,214, 33,143,116,239, 53,104, 97,230,174,112,252,182,125, 49, 70,198,247, 70, -168,132, 65,104,136, 13,193, 65, 38,220,247,208, 20, 22,128,182,190,174,234, 77,185,228,238,143,207,116, 64, 0,183, 15,140,167, -135,168, 84, 42,155,207,157, 59, 23,115,231,206, 5, 0,243,219,105,111,195, 82,102, 69,112,176,196,175,100, 36, 73, 73,246,240, -225,144,241,103, 64, 5, 12, 94,251,198,224,180,254,249, 34, 36, 42, 74,102,109, 22, 2, 29,181,225,132, 94,135, 99,149,229, 56, - 94,117, 29,199,171,180, 56,161,215,226,140, 65,135,114, 83, 45,106,172, 86, 92, 50,232,157,191,233, 9,147,198, 17, 44, 91, 36, -192,178, 69, 2, 80, 8, 64, 9,131,212,105, 4, 79, 78, 19, 99,214,212,214,232,222,189, 45, 88,136, 0,248,118,203,156,171, 63, - 41, 41, 73, 86,127,159, 15,109, 38, 43,188,104, 87,228, 11,222,183, 7,209,237,124, 49,204,238,190,161, 58, 8,168, 30, 38,198, - 30,209,172,213,106, 67,146,146,146,124, 42,138, 30, 27, 27, 11,149, 74,133,117, 53,122, 24,205, 12,158, 88,255, 31,148, 73,130, - 97, 52,223,190, 50, 17, 19, 7,188, 33,203,213, 46,193,186,255,222, 48,241,191,121,211,130,184,136, 87,111, 40,148, 15,124, 42, -203, 80,102,240,202, 45,177,252, 85, 32,121,254, 88,132,231,169, 32,251,247,104, 48, 19, 0,141, 70,227, 87, 31,238,210,165,110, -244,248,152, 49, 64,120, 56, 16, 29, 13, 12, 27,208, 28, 18,177, 0, 2,230,134, 88, 73,112,176,215, 1,153, 97, 24,231, 92,255, -217,179,103, 17, 19, 19, 83,231,239,173,183,222,194, 91,111,189,133, 75,151,248,123,101,220,205,215,187, 34, 45,205,119, 11, 44, - 51, 51, 83,182,124,249,114,183,132,205,215,250,119,113, 61,223, 20,167,192,109,179, 44,191, 20,246,102, 66,192, 26, 76, 16,181, -235, 2,197, 59,239, 32, 57, 52, 28,225,154, 92,231,241, 89,255, 72,198, 27, 31,252, 7,133,203,190,198,235,253,199, 96, 74, 68, - 55,236,222,188, 25, 69, 69, 69,110,223,191,135,211, 20,232,219,175,159,140, 11,106,228, 20, 50,215,233, 25,119,251, 60, 88, 95, - 52, 45, 45,141,114,129,125,220,124,191, 43,201, 39, 39, 39,107,226,226,226,100,156,235, 63, 57, 57, 89,227,165,221,114, 68, 34, -209, 93, 15, 63,252,240,217,202,202, 74,232,116, 58, 4, 7, 7,163,117,235,214, 8, 15, 15, 71,120,120,184,183,198, 99,235,201, -179, 5, 5, 5, 25, 30, 77,251, 72,182,250,167, 33, 56,127,161, 10,109,195, 4,136,239, 73,112,119, 55,138,208, 22, 45, 42, 0, -216, 60,240, 70,160,222,192,159,212,250, 7,188, 47, 3,172, 81, 42,149, 65, 0, 66, 21, 10,133, 83, 11,236, 56,186,131, 95,154, -175, 82,169, 36,114,185, 28, 42,149,138,138,103,101,213,113, 69,242,205, 3,208,242,193,177,154,242,172,237, 48, 88, 77,168,210, - 27,112,214, 98,129,136,181, 59,234, 43, 45,181, 96, 41, 5, 5,176,253,234, 57,232,173, 22, 0,224, 49, 48, 17,204, 95, 82,183, -143,219,167, 2, 88,216, 96,194,239,103,170,177,106, 67,149, 79,247,235, 74,244,114,185, 92, 83,223, 11,224,170, 20,120,130, 92, - 46,215,100, 41,166, 64, 52,246, 51, 0,209, 40, 47,191, 17,156, 39,102, 47,195,204,180,199,211,253, 79,227,242,101,251, 64,172, - 84, 42,247,240,145,155,246, 77,102, 29,197, 43, 43, 43, 11,220,164,196,250,163, 7,125, 90,149,209,212,120,224,169,246,154, 45, - 10,138, 3,170,227, 0,128,225,125,237,153,241,254, 53,111, 49, 14, 30,239,139, 15, 54, 78,135,114,235, 83,106,229, 68,126, 4, -254,196,124, 57, 34, 35, 85,174,134, 44,180, 90, 57, 40,205,114,184, 42, 41,178,178,146,120,201,154,252,200,163,100,247,206, 93, - 20,176,187,254,101, 50,130,235, 23,194,160,215, 73, 96,172, 18, 99,253, 26,130,185,115, 41,138,203,170, 49, 44, 62, 14,211,167, - 78,227,101, 21,219,108, 54,231,124,191, 74,101,191, 86, 87,194, 47, 43, 43, 67, 89, 89,153,207,238,125,133, 66, 65, 25,134,185, -137, 84, 51, 50,148,196,143, 36, 64, 26, 74,105,157, 88, 0, 23,143, 0,111, 87,184,171,107,191,126,244,190, 55,183,127,125, 37, -199, 90, 93, 13, 81,171, 72, 8, 66,154,161,239,163,147,241,214,184, 4,188,194, 45,219, 27, 52, 24, 54, 99, 45, 68, 45,219,162, -127,156, 20, 93, 59,118,195, 71,191,231,162, 95,191,126,178,159,126,250,233, 38, 37, 32, 77,161, 0, 64,212, 0,240, 84, 90,154, -115,233,160,181, 30,217, 11,133, 2,128,222, 88,168, 72, 0, 12,112, 51,200, 14, 28, 56,144, 80, 74,157, 46,254,252,252,124,167, -139,223,245, 60,199,182, 87,242,119, 24,236,175,134,135,135,247,141,139,139,235,126,242,228, 73, 28, 57,114, 4, 54,155, 13,161, -161,161, 48, 24, 12,101,145,145,145,231,125, 49,250, 8, 33, 76,219,182,109,119, 63,244,208, 67,109,243,246,231, 99, 69,214,110, -180, 32, 98,244,108,107,194,153,235,161,184,183,167,229, 28, 0, 11,167,160, 57, 20, 74,155,167,103,226, 58,214, 5,166, 0,238, -108,240,153, 47, 54, 3, 48,187, 18,245,197,156, 75,192,116,223,201,223,149,108,220, 13, 90,124,149,128, 42,173, 78,102, 9,145, -168, 43, 25, 22, 87,106,107, 0,139, 5, 54, 74, 65, 0,252, 94, 83,129, 82, 67, 21, 40,165, 92, 18, 27, 30, 3, 19, 69,234, 52, -130,204,245, 55,250,228,201,179, 64,175,238, 86, 8,160,111, 20,249,187,118,118,127, 93, 94, 73, 73, 73,178,172,172,167,212, 64, - 1,180, 90,173,185,164,164, 68,184, 52, 1,204,194,221,163, 48,175,223, 65,167, 21,198, 87,169,112,231,117,169,191,205,145, 16, - 95,107, 14,139, 9,134,100, 22, 81,192,253,114, 63,103, 38, 64, 21, 40,159, 32,197,180,137,159,201,148, 91,158, 86,231,110,164, -136,143, 60,142, 17,242,190,216,191,251, 56,242,116,239,128,128, 64, 49,241, 83,222,247, 26, 25,169, 2, 33, 4,147, 38, 77,194, -231,159, 87,129, 51,138,237,255, 83, 71, 27,103,213, 25,144, 60, 76,193, 98,244, 24,153, 44,103,175, 90, 61,102, 12, 96,190,210, - 9, 23, 42,130,192, 58,102, 91,219,235,219,226,197,212,106,236,206,235,137,230, 29,123,242,186, 70,142,248, 47, 94,188, 8, 0, -184,114,229,138,211, 51,112,245,234, 85,231,192,234, 15,148, 74, 37,225, 18, 1,213,159,195,205, 80, 42, 9,159,124, 0,174,248, -252,243,207,235,196, 2, 44, 95,190,220,103,235,191, 62, 97,248, 11,137, 68,130, 43,197,231,209,173,123, 15,176, 86, 19,136,213, - 6, 97,243, 22,104, 62,120, 8,154, 13,186, 7,172,222, 10,155,193, 4,106,181, 1, 54, 22, 11, 87,126,128,169,211,167, 66, 34, -145,184,149,103, 93, 31,193,235,119,221,157, 23,251,158,251,115,227,227,227,101,121,121,121,106,110, 12, 24, 49, 98,132,219,182, -226, 65,254, 32,132,176, 0,118,244,236,217,115,208,199, 31,127,108,190,118,237, 90,109, 66, 66,194, 67, 5, 5, 5,175, 27, 12, -134,242, 86,173, 90, 41,250,244,233,163,245,161,237, 69, 0, 58,199, 13, 27,214, 58,109, 86, 26,206, 93, 60,167,125,124, 86,218, -200, 67,187,215,164, 95,174,214, 14, 31, 50, 58,129,109,219, 49,230, 17, 55, 94, 3,214,211, 88,224,202, 21, 13, 37,255, 9, 36, - 2,250,243, 40, 0, 13, 90, 23,254,144, 63, 71, 54, 92, 78, 0,127,148,128,110,138, 25, 26, 0,164, 84,185,154, 34, 88, 2, 29, -181,194,108,181,130,165, 44, 90,134,133,225,162,190,146, 95, 6, 59, 7,220, 45,239,187, 17, 3,224, 91, 38, 54,119, 46,254,198, -166,235,117,124,119,226,144, 33, 67,182, 44, 92,184, 80, 28, 25, 25,201, 94,190,124, 25,243,250, 93,174, 67,254,190,252,134,187, -246,247, 27,142, 44,127,245,147, 60,185, 59,135, 47, 6, 61, 32,208,100, 60,144, 65, 54,127,114, 73,186,237,232,155,234,220,141, - 0, 1,193,196, 1,111,200, 30,120,138,127, 2, 32,174, 47,217, 9,190,202, 49, 72, 1,238,120,103,117,186,221,121, 18,218, 57, -131, 0, 13, 23,215,152, 62,117,154,102,250,212,105,164, 92,247,177,212, 86, 93,173, 38, 2,192, 80, 27, 12, 82,109,133,144, 17, -194,192, 72,100,227,166,204,134,144, 18,175,215,153,144,144, 64,238,186,235, 46,122,171,222, 63,187,181,159, 65,210,210,210,168, -107, 68,187,171, 39,192, 71,113, 26,206,242,119, 81, 40, 52,183, 99,240, 26, 51,102, 12,158,222,152,137,183,170, 43, 48,112,244, -189, 96,218, 70,216,175,201, 66,237,169,123, 33, 2, 17, 8, 65,196, 2,124,158,177, 12, 45,198, 14, 65,247,238,221,255,208,212, -189,156,117,159,155,155,171, 30, 54,108,152,108,230,204,153,141,250,237,179,103,207,202,247,236,217, 83, 44, 16, 8, 54,143, 28, - 57,242,109,134, 97,174,197,197,197,229, 56, 45, 25, 23,143, 18, 33, 4,238,158,185,139, 39, 64,117,228,200,145,161, 95,173, 94, -195,136, 5, 65, 23, 38, 63, 54,121, 0,195, 48,186,123,239,159, 61, 1, 64,152,131,248,171, 1, 80,171,213,234,148, 87, 79,105, - 11,148,148,191, 3,193,199,253,239,151, 2,208, 20, 10,131, 39,242,241,101,128,147, 10,122,251,182, 0, 0, 32, 0, 73, 68, 65, - 84, 41,146,137,106,183, 74,202,158, 42, 84,235, 77,102, 88,109, 54,116, 31, 58, 24, 49,214, 97, 62,145, 97, 83, 6,163,112, 73, -127, 0,168, 57, 79,135,203, 84, 0,105,132,220,173,114,185, 92,168, 82,169,230, 47, 93,186,244,223, 46,202,197, 24,165, 82,233, - 83, 34, 18,135,167,160,201,146,151, 76,249, 61,201,209,142, 13,223,223, 20,149,202, 47, 77,255,193,103, 58,104, 30, 68,227,159, -143,157,220, 9,158,152, 63,198,153,167,156, 27,199, 86,167,239, 65,104,231, 12, 18,218, 57,201, 39,153,225, 45,158,213, 28, 40, - 6, 97,153, 11, 82,163,193, 94, 7, 32, 84, 34,215,132, 69,193,167, 21,163, 46,253, 79,228,208, 56,155,124, 94,149, 83, 2,154, - 66,150, 35, 22, 64,205,125,110,172, 60,127, 87,150,117,239,222, 29,237,158,123, 78,182, 98,215, 46,117,209,219,223, 33, 73,212, - 18,225,142,226, 61, 70,131, 21,115, 23,188, 12, 65, 72, 36,182,175, 81,226,215, 86, 4,227, 26,145,183,223,102,179,194,215, 24, -160,250, 74, 0, 31, 43,223, 75, 59,145,211,167, 79, 95,163,148,166,247,234,213,235,203,242,242,114,189, 80, 40,132,213,106,165, - 45, 91,182,116,122, 84,244,122, 61,196, 98,177,211,139,228, 65,222,168,252,252,124,176, 86,130,225, 35, 6,188,113,241,226, 69, -157, 86,171, 69,100,100, 36,219,177, 99, 71, 29,247,108, 42, 43, 43, 33,145, 72, 64, 8, 65, 80, 80, 16, 47,163,143, 83, 18,234, -127,174,239, 21, 13,224, 79,230, 1,184, 85, 74,129,223,196,152, 32,215, 32, 65,126, 71, 69,147, 58,148, 0,114, 11,230,209,109, -114,185,252,255,228,114,249,255, 53,197,245, 53,225,253,146,166, 56,231, 86,194,110,213, 3,142, 20,251,245,142, 37, 53, 74, 54, -195,118,210,132, 74, 58, 53,197,101, 90,110,101, 27, 52, 97,209, 21,141, 47,115,245, 94,148, 9,191,229, 80, 74, 73, 72, 72, 8, - 38, 77,154, 4, 71,249, 94,148,184,148,239, 61,176,103,183,179,124,239,216,184,177,112, 40,189, 13,254,222,231,186,247,200,147, - 17, 47,223, 76, 76, 60,171, 9,242, 80, 2, 26,141,123,238,185,199,100,181, 90,115, 0,232, 89,150,165,102,179,125,225,207,181, -107,215, 0, 0,205,154,217,151,246,114,251, 69, 34,145,199,246,123,224,129, 7, 56, 25,187, 88,150, 69,120,120, 56, 88,150,117, -174, 56,113,172, 98, 33,181,181,181, 20, 0,196, 98, 49, 8, 33,204, 31, 49,182, 7,224, 63,248,164,146, 6, 0, 50,112,224,192, -128, 38, 22, 64, 0, 1, 4,240,231,129, 21, 64, 45, 0, 73, 19, 27,113,222, 10, 6,241,174, 40, 24,192,159, 3,129,135, 25, 64, - 0, 1, 4,240,231,130, 16, 64, 51, 30,228,111,128, 61,136,187,169,248,128, 69, 96,217,223, 95,174, 35, 5, 16, 64, 0, 1, 4, -240,215, 67, 72,128, 47, 2, 8,120, 0, 2, 8, 32,128, 0, 2, 8, 32,128,128, 2, 16, 64, 0, 1, 4, 16, 64, 0,127,119,212, -113,233,204,153, 51,199,239, 8, 78,119,197,123,238,116,121,209,131,131, 16, 28,116, 5, 34,113, 5, 88,214,190, 44, 76, 32, 96, -192, 16,129,253,127,134,128, 16, 6,148, 8,237,107, 96, 97,197,150,109, 34, 80, 74, 17,201,180,132,143,215, 23, 4,160, 21,236, - 1, 60,213,176, 47,247,178,192, 49,167,246,103,108,191,128,188,128,188,128,188,128,188,128,188, 59, 83,158,207, 10,192,223, 13, - 63,238, 63,131,161, 67, 44,136, 8, 7,180, 58,130,159,127,149, 64,200, 8,113,255,120, 27,118,171, 91,131, 16, 6,132, 97, 32, -105, 14,140, 25, 90, 1, 64,136,123,227, 41,242, 11,132,118, 26,231, 1,245,193,253, 20, 0, 68,212,130, 97, 35,199, 20,159,254, -237, 39, 83, 89, 85,109,140,205, 80, 11,185, 92, 30, 14,160, 50,160,135,254,185,145,253,205,127,165, 61,186,119, 83, 95,187, 86, -219,168,132, 79,127, 34, 72, 83, 83, 83, 93,243, 0, 52,234,158, 83, 83, 83,253, 78, 7, 28, 64, 0, 1, 52,145, 7,128,195,154, -175,190,224,173, 77, 60, 49,115,150,215,151,181,169,229, 53, 37,242, 11, 68, 72, 76,176,225,215,223,130, 33, 22, 9, 33, 20, 8, - 33, 18, 81, 4, 9, 44,128,176, 57,132, 48, 98,104, 95, 43, 36,226, 32, 80, 0,237,219, 2, 15,222,207, 98,207,102,126,228,127, -230,247,211,184,171, 79,119,116,136, 10,199,197,226,147, 93,194,218,117, 67,171, 14, 54,252,240,253,247, 80,169, 84, 21,183,123, -125,188, 74,165,186, 63, 43, 43,107, 27,183,157,148,148,244,128, 92, 46,223, 22,120, 53,188,227,183, 95, 85,212, 90,123, 92, 54, -237,193,238,106,150, 45, 71,101, 7,163,250,228,177,141,168, 49,181,199,144,216,145,127, 89, 18, 75, 77, 77, 85,207,155, 55, 15, -132, 16, 94,101,123,249,128, 75, 22,211, 4,229,230, 3,104,164, 2,230, 17,148, 34,243,243,207, 27,124,222, 92,130, 31,215,108, -129, 92, 13, 1,151, 90, 2,206,231,236, 90, 25, 49,128,166, 5,151, 13,144,131,187,220, 0,119,148, 7,128,193, 31,219, 15,238, - 31,103, 1,133, 0, 66,129, 8,195,135, 17,180,105,205, 64, 40,100, 16, 36, 18,160, 87, 12,131,226, 11, 86, 12,141,101,208, 50, - 82,130, 31,246,182, 0, 0, 8,168, 17,246, 84,216, 54,175,228,255, 91, 65, 1,186,118,232,136,223,114,243,112,200,108,129,238, -186, 14,226,160,230,232, 61,104, 4, 6,140, 24, 7,245,150, 44, 0,252,114,227,223, 2,226, 31,147,149,149,181,103,225,194,133, - 40, 40, 40,224, 58, 76, 5,128,231,102,207,158,189, 53, 41, 41, 73, 46,151,203,247,252,229, 94,138,159, 85, 52, 72,168,133,144, - 49,163,182,214,134, 74,125, 48,238, 29, 53,197,167,246,223,152,253,149,180, 69,176, 22,255,152, 58, 24, 93,187, 60,168,110,209, - 34, 12, 22,171, 21,215,174, 93, 71,219,146, 11, 40, 60, 91,132,131, 7,180,116,248,136,135,252,122,174,153,153,153,212,101,112, -190,211, 6, 71, 41,112,163, 28,174,163, 58,160, 20,183, 41, 29,240, 31,248,190,208, 77,155, 54,221, 92, 79,225,182,145, 23,149, - 18, 16,208, 38,104,119, 90,242, 13,200,161,217,174, 28,239,200,146,233,168,134,228,130,217, 25,122, 12,157,250,177, 71, 69,238, -135, 31,126,112,110, 39, 38, 38, 98,199,142, 29, 30,183, 3,184,245,228,239,186,207, 85, 17,240,168, 0, 28,216,127, 8, 35,238, - 29,246,135, 93, 52,235, 67,254, 84,215, 84,146,254,102,159, 98,132, 2,232,180, 66,180,107, 35, 66,187, 54, 98,212,212,136, 32, - 17, 9, 97, 19, 6, 97,112,127,130,129,119, 11,192, 16,145, 61, 5,166, 72, 12, 17, 99, 2,145,136, 97, 53, 0, 86,232, 61,146, -255,254,189,123,208,173,125,107, 28,251,245, 24, 22,189,253, 70,157,235, 91,242,230,187,148, 17, 16, 12,142, 29,140, 31,118,236, -241,169,242, 30,203,178,210,130,130, 2,245,153, 51,103, 16, 28, 28,140,224,224, 96, 89, 98, 98,162,198,199,193, 76,150,149,149, -181,135, 35,126,151,206, 17, 14, 96,220,127,254,243,159,235,179,103,207, 86, 1, 72,144,203,229,170, 59,177,131,175, 90,181, 74, -154,146,146,194,251,190,191,222,176, 70,218, 47,166,185,186, 75,251, 90,132,181, 8, 2,195,132,192,104,180,162, 92,107, 68,142, -106, 5,149,180, 24,140, 97, 67, 71,241,234, 71, 34, 92,193,164, 7,238, 86,247,237,219, 27,151,175,232,112,248,231, 35,168,169, -209, 35, 44,172, 57,162,163,187,128, 17,136, 96,179,149,224,231, 95,246,211, 65, 3,239,253, 75, 89, 55,169,169,169,234,231,159, -127,222,185, 61,111,222, 60, 44, 95,190, 92,253,185, 7,171,208, 39, 50,186, 67, 61, 0, 14, 37,157,102,103,103,195, 93, 97,165, - 63, 18,174, 86,182, 82,153, 33,163,180,113, 74, 0,211,229, 81, 39,121,231,191,215,204,173, 25,214, 46,156, 65, 84, 36,243,167, -125,126,127, 87,184,146,189, 59,165,192,171, 7,224,192,254, 67, 0,208,104, 69, 96,255,115,133, 30,143,223,251, 81, 15,191, 7, - 11, 66,136, 95,213,246, 84,154, 54, 16, 9, 69,232,212,161, 6,213,213, 34, 28, 62,214, 9, 2,129, 0, 2, 34,128, 88,100, 69, -223, 30, 6,244,236, 33, 0, 1, 3,177, 40, 8, 98, 1, 65,236,221,102, 68, 70,176, 88,247,165,103,217,189,187,181, 69,241,217, -178,155,200, 31, 0, 22, 45,126,133,188,251,246,191,105,251,248,187, 17, 17,222,156,247,245, 26,141, 70,233,242,229,203,213,197, -197,197,117,244, 13,147,201,132,135, 30,226,111,109,102,101,101,237,117, 37,127, 55,104,149,158,158, 94,241,194, 11, 47,236,190, -221, 83, 20, 13,145,255,161, 67,135,212, 41, 41, 41,188,175, 45, 38, 58, 82, 29,213,182, 10,173, 90,134,162, 99, 84, 59,132,132, -134,160,184,184, 20, 54, 27,139,168, 14,205,113,252,247, 92,172, 62, 85, 40, 77,126,124,150,199,193,244,232,209,253,244,145,137, -189,209,185,115, 71,156,248,189, 24,135, 15,255,142,107,215,171, 65, 41, 16, 17, 17, 12,131,161, 6,131, 6,245, 69, 69, 69, 37, - 74, 15,255,140,175,254,119, 90, 58,243, 31,252, 21,149, 59, 28, 82,192, 94,124,138,195,135, 31,126,200,109,251,228, 5, 72, 77, - 77,165,174, 46, 97, 87, 11,210,213, 37,221, 20,211, 11,111,191,253, 54,237,212,169, 83,163,115,241,203,229,114, 66, 8,161, 27, - 55,110,244,152, 99,159, 67, 90, 90, 26,117,231, 33, 88,189,122,181,148, 43, 14,228, 78,137, 85, 40, 20,180,161, 84,174,174,245, - 28, 40,165, 80, 40,210,212,141,241, 66,212,151, 55,244,229, 26,252,244, 94,179, 58,196, 31,192,159,211,250,175,223,135, 26, 53, - 5,208, 88, 69,224,222,143,122, 52,168, 4,248, 67,254, 28,114,114,114, 80, 90, 90, 10, 0,136,138,138,162,190, 40, 1, 2,106, -132,144,216, 32, 22,137,240,243,177,214, 16, 8,133,104, 46,210,219,227, 0,154, 49, 40, 45,109,142,187,251,178, 32,132, 32,233, - 65, 43, 40,203, 0, 36,200,238,120, 67,117,131,114, 13, 21, 23,112, 69, 91,131, 23, 94,127,189,193,107,169,168,212, 66,119,237, -138, 67, 22,111,226,174, 79,254, 0,128,237,219,183,195,102,179, 73, 31,121,228, 17,175, 3,156, 74,165, 26, 83,191,244, 47,215, - 97, 42, 43,235,196, 35,134, 47, 94,188, 24, 42,149,106,236,157, 52, 21,192,145,191, 47,223,249,122,195, 26,233,221, 49, 38, 4, - 7,135, 67, 18, 36, 70,183,110, 93,209,169,107, 87, 84, 85,105,160,213,214, 64, 44, 22, 32, 50, 66, 2, 97,112,184,199, 92,241, - 0, 32,164,165,104,222,172, 37, 12, 70, 43,142, 29, 43,196,165, 43,149,184,124,165, 6, 70,147, 4,157,163,172,144, 4, 9, 80, -120,186, 8,119,117,239,142, 75,151,171, 96,180,182,240, 42,211, 65,116,212,219,126, 95,167, 3, 26,146,233,143, 44,206,250,159, - 55,111,222, 77,251,159,127,254,121,191, 98, 1,220,145,104,253,185,227,166,242, 42,228,230,230,170,209,200,130, 60,123,246,236, -161, 89, 89, 89, 72, 74, 74,130,187,233, 0, 62,158, 42,142,252, 1, 32, 63, 63, 95,205, 48, 76,157,107, 90,189,122,181,148,143, -209, 19, 31, 31, 47,227,228, 52,133,199,101,227,243,161,152,178, 92,239,150,248,163, 34, 25,199, 40,197,239,241, 38, 38, 38,214, -241,146,220,119,223,125,117,218, 42,224,246,191,115,224,115, 12, 64, 83,121, 4,154, 18,133,133,118,197,162,180,180,212, 39, 37, - 64, 40, 20, 66, 36, 16, 65, 36, 34, 24, 53, 2, 48,232, 77, 56,119, 86, 12,145, 80, 4,161, 77,136,184, 97, 20, 98,145, 8, 2, - 1, 3, 80, 2,173, 14,248,233,136, 16, 44,203, 2,184,214,160,220, 35, 63,159, 69, 77, 77,195, 25, 56,223, 95,188,152, 6, 5, - 73, 96, 52, 86,194,198, 90,121,223,231,145, 35, 71, 26, 86, 58, 12, 6, 94, 68, 83,223,245,239, 78, 51,220,178,101,139,235,249, -170,219,225, 5,112,231,226,119, 37,255,248,248,120,222, 85,232, 58, 70,181, 85, 51,204, 5, 88,109, 44,204, 22, 43,174, 93,215, - 66, 36,150,192,100,178,192, 98,181,193,106,101, 97,181, 81, 84,232,174,123,149, 37, 22,233, 33, 9,238,136,242,242, 74, 84, 85, - 27,160,213, 25,209,162,229, 0, 12,191,251,110,228, 31,216,129, 14,102, 43, 42,171, 42,209,179,103,119, 4,137,133,208, 87,107, -255, 42, 99,133,148, 82,234,156,251,119,197,138, 21, 43,252,138, 5,152, 55,111, 94, 29,111, 66,253, 99,124, 21, 0,123,169,103, -206,162,141,196,216,177, 99,235,244, 87,206, 64, 40, 41, 41, 81,171, 84, 42,191, 10, 83,169, 84, 42, 39,249,115,211, 1,155, 54, -109,242, 74,174,245, 61, 85,185,185,185,106, 46,240, 77,161, 80,208,188,188, 60,117,114,114,178,243,120, 94, 94,158,154, 16,207, -151, 23, 31, 31, 47,115, 45, 51,156,150,150, 70, 61,181,149,183,241, 48, 41, 41, 9,147,227, 85,216, 0, 96,234,114, 61,238,121, -185,198, 99,219, 15,157,234,185,173,234,207,241,123,139, 9, 8,224,214,123, 3, 26,242, 0,252,161,254, 29,119,150,126, 99,172, -255,122, 22, 43, 10, 11, 11,177, 98,197, 10,222,165, 38, 5, 2, 33,226,134,178, 16, 48, 66,252, 84, 32,193,169, 66, 9, 38,140, - 7, 30,184, 15,152,152, 72,208,190,173, 24, 18,113, 16, 36,226, 32, 4, 75,130, 16,213, 62, 8, 18,177, 4, 18,177,231,146,152, -175, 45,122,149, 44,125,239, 45,210,208, 64,210,189, 91, 23,132,133,135, 66,194,154, 81, 99,176,252,225,157, 98,255,254,253,123, -246,239,223, 95,135,240, 93,255, 0,160,188,188, 28, 19, 39, 78,188,109, 86,126,126,126,190,218,213, 26,226,246, 1,192,176, 97, -195,124,178,228,108, 54, 64,111,176, 64,175, 55,163,170,202,132,171, 87,117,184,116,233, 58,170,171, 77,168,169,177,160,166,198, - 12,189,222,130,202, 10,239, 43, 50, 77, 38, 43,106,107,109,176, 88,204,104,222, 92,140, 78, 81, 45, 16, 18, 26, 10, 0,136,238, -222, 21, 29, 59,180, 64, 88, 11, 9, 40,181,193, 98,101, 97, 50,233,255, 18, 3, 73,106,106,170,122,254,252,249, 30,201,156, 91, - 26,200,211, 59, 33,115, 40, 13,110,177,124,249,114,124,254,249,231, 62,151, 26,182,187,197, 21,212,245,143, 35,212,210,210, 82, -100,101,101,249, 92,138,118,207,158, 61, 52, 59, 59,219,149,252, 33,151,203,201,228,201,147, 61,126,111,206,156, 57, 32,132, 56, -173,250, 85,171, 86, 73, 1, 32, 46, 46, 78,230,170,196,186, 30,167,148, 58,143,243,184,219, 58, 86,188, 59,197,193,155, 50, 1, - 0,173, 90,181, 2,113,177, 30, 26, 43, 47,128, 59,143,252,221,109,251,229, 1,184,147, 44,255, 27, 3,188, 13, 2,129,192,231, -239,141, 24,202,162, 77,235, 32, 84, 85, 9, 17, 36,180, 34, 72, 44,128,230,144, 24, 19,100, 34,136, 69, 34, 84, 85,137,112,160, - 32, 20, 45, 36, 4, 12,195, 32, 81,110,198, 67, 19, 40, 24,134,226,157, 95,124,191, 78,149, 74, 69, 5, 33, 18,104, 69,173, 16, - 98,185,136, 51,165, 20, 99,164,163,120,127,127,208,160, 65, 56,120,240,160,219, 99, 33, 33, 33,188, 7, 75,157, 78, 55,214, 49, -240, 32, 57, 57,217,185,191,188,188,220,249, 57, 57, 57, 25,101,101,101,183,229,121,166,164,164,104,242,243,243,145,155,155,171, -102, 89, 86,198, 48, 12, 56,203,191,161,121, 83, 79, 40,185,112, 73,214,186,133, 65, 29, 36, 22,192,108, 97, 81,107,186,136, 11, - 23,203,161,213, 85, 65,171, 53,160, 92,107, 68,185,214,136,240,200,174, 94,101, 93,189, 78,113,229,234,117,244,238,221, 29, 21, - 58, 29, 68, 66, 6, 85,213, 23,161,175, 96,209,231, 46, 61,218,182,110,141,144,144, 16, 4, 5, 5,227,242,149,106, 16, 65, 4, - 95,130, 37, 46,228,216, 36,171, 0,154,122, 5, 65, 67,214, 58, 80, 39, 22,128, 47, 52, 0, 48,119,238,220,155,188, 10, 46,211, - 12, 26,127,174,115,202,148, 41,117, 44,216,172,172, 44, 39,121, 61,250,232,163, 72, 72, 72, 32,124, 19,167,184,177,252,157,168, -239,105,168,143,129, 3, 7, 18, 74,169,211,202,207,207,207, 87, 19, 66,156,165,129,147,147,147, 53,185,185,185,200,205,205, 85, - 39, 39, 39,147, 67,135, 14, 57,143,175, 92,185,178, 65,185,185,185,185,106,134, 33,178,188, 60,251, 59, 49,103,206, 28,252,242, -203,207, 50,142,194,243,242,242,212,220,253,243, 81, 38, 86,174, 92,137, 79,101, 17,152,186,194, 0,192, 62, 29,224,138,169, 43, - 12,206,246, 76,145,137, 2,204,250,103, 81,218, 23,190, 95, 87,233, 94,250, 18,126,249,229, 23,254,171, 0,110, 5,241,187,198, - 2, 52,198,250,175,107,201,215, 37,255,196,196, 68, 40, 20, 10,175, 83, 1,173, 90, 9,192, 16, 1, 90,183, 18,160, 71,119,138, - 75,151,132, 96, 4, 4, 34,161, 16, 34,161, 8,191, 29, 13, 69,100,168, 8, 2,129, 0, 35,134,217, 16, 28, 28, 4,150,165, 0, -181,249, 69,254,205,218,118,194,213, 26, 10,253, 25, 13,132, 68,128, 23, 23, 47, 34, 62, 14,108,178, 11, 23, 46,168, 47, 92,184, -112,211,253, 78,154, 52,137,215, 96,153,148,148,148, 80, 94, 94,190,155, 35,121, 0,152, 56,113, 34, 86,175, 94,237, 60,167,170, -170, 10,101,101,101,216,186,117, 43,146,146,146,198,220,142,206, 27, 23, 23, 39,203,205,205, 85,231,231,231,171,185, 96,177,184, -184, 56,191,230,112,103,254, 35,229,255,217,251,242,240,166,170,252,253,247,220,236, 93,105, 75, 41, 75,217,165,130,108, 5, 42, - 32,107, 2, 5, 20,176, 34,180,200, 38, 95,100,102, 26, 24, 87, 96, 20, 69,231,231,204,168, 40, 46,128, 35, 35,180,140,138, 11, - 21,105, 21, 44, 88, 4, 10, 9,139,136,149,138,128, 44,178,148,181,133,174,105,211, 52,123,238,249,253,145,222,152,134,180,185, - 73,195, 58,247,125,158, 60, 77,238,189,249, 52,247,220,115,206,251,217,206,231,104, 55,124,153, 9, 90,172,135,209,100,131, 78, -102, 6,133, 14,102,179, 29,122,189, 5,101, 21, 70,148, 92, 53, 96,184,170,163, 79, 89, 38,107, 75, 20,157, 47, 71,151,206, 29, -208,185,115, 60, 42, 43, 43, 16,213,194,129,110,221, 34,209, 42,182, 11,228, 10, 5,170,171, 13, 40,252,229, 20,174, 20,235,209, - 58,190,231, 29, 59,129, 80,128, 18, 2, 21,199,165,238,164,218,212,186,125, 90,159, 44,120,189,249,136, 6,171,202, 50, 51, 51, - 85, 43, 87,174,212,120, 42, 0,203,151, 47,231, 10, 12, 53, 41,143, 82, 74, 9, 33, 68,173,142,114,251, 77,244, 58, 98,206,206, -118,134, 8, 82, 83, 83,121,185,255, 27,134, 20,118,121, 37,127,190,120,224,129, 7, 84, 7, 15, 30,212,112, 94,135,161, 67,135, -170,188,157,231,146,241,124, 17, 54, 23, 91,255,225,135, 3, 26, 66, 8, 8, 33, 72, 76,236,171, 74, 76, 76,212,186, 41, 8,245, -215, 2,190,198, 11, 39,143,153,170, 3, 39, 47,109, 84,167, 6, 15,106,234,138, 19, 46,121,124, 32,228, 0,220, 57,240,169, 0, -220,142, 22, 63,135,105,211,166, 53,235,251, 12,195, 64, 36,114,190,122, 36, 48,232,215,219, 1,153, 84,238, 84, 0, 36, 18, 12, - 25, 4,200,100,128, 68, 36, 67,203,150,114,136, 68,117,112, 56, 88,176,172,255,110,123, 99,213, 53,200,227,187,227,124,254, 23, -136, 21, 51,120,252,229, 37,126, 79, 40, 10,133, 66,187,100,201, 18, 85,115,150, 1, 38, 39, 39,231,171,213,106, 60,245,212, 83, -174, 99,156,165,175,215,235, 97, 52, 26, 49,119,238, 92, 0,192,135, 31,126,136,140,140, 12,205,173,120,182,115,230,204,209,178, - 44,171,226, 44,255,129, 3, 7, 54, 43,129, 43,190,227,189, 56,116,112, 59, 90,181, 12, 65, 72,136,179,219, 91, 44, 14,232,107, -173,168,210,153,208,190,115, 79, 12, 27, 50,210,231, 51, 25, 63,126, 10,217,177,237, 19,122,176,224, 56,134, 15,237,139,142, 29, - 59,194,102, 53,163, 95, 98, 31,132, 70, 70,226, 98,209, 37, 20,151, 84,227,135, 31, 79, 66, 87, 27,137, 71, 31, 24,121,199,250, - 76,231,207, 83, 3,128, 6, 32,152,175, 86,187, 8,156,245, 32,125,134, 33, 78,109,161,158,151, 9,128,190, 94,226,141,243,212, -106, 10, 10,183, 76, 21,130,244,244,244, 6, 94,128,103,159,125, 22,132, 16,204,155,167,214,112,236, 15, 2,244,237,155,232,141, -188, 92,238,120, 95, 36,199,151,252, 61,145,154,154,138,209,163, 71,171,154,211,143, 81, 31,171, 31, 52,104,144,106,246,236,217, -218,198,206,187,197,246, 27, 5,151, 59,192, 41, 95,206, 48, 2,209,122, 42, 21,124,127,159,167,188,141, 11,194,156,141, 46,143, -115, 93,179,113,193, 37,151, 66,176,253, 72,211,115,159,183, 58, 0, 66, 14,192, 29,170, 0, 12, 25, 58,240,134,196,124,130,101, -249,187,119,164, 64, 80,165, 35,104, 19,199,184, 74,254,238,216,229,140,239,203,100,114,200,164, 50, 60,252, 16,129, 92, 38,133, - 66, 78, 80, 85, 41, 66, 65, 97, 56, 28,172, 3,237,227,253,139,235,230,231,231,211,106,163, 9,186, 67,121,232,214, 94,130,223, -138, 3,143, 11, 51, 12,163, 29, 56,112, 32, 25, 56,112, 96,192, 50,210,210,210, 84,171, 86,173,210,112,110,254,202,202,202,199, - 6, 13, 26,100,216,185,115,231,119,143, 60,242,200,216,202,202, 74,242,248,227,143,111, 79, 75, 75, 83,221,202,206, 89,239,234, - 87,185,189, 15,188,207, 57,201,157,158, 62,117, 2, 37, 69, 23,193, 48, 4, 14, 7,133, 92, 17,141,132, 30,189,240,232,164, 52, -222, 29,189,164,156, 85, 85, 85,150,104,204,102, 59,122,247,234,130,118,109, 91,226,210,229, 82,232,142,157,195,239,167, 47, 97, -215,238,163,184, 88, 76,241,231,191, 60, 29,208,224,185, 93,138,255,176, 95, 69, 5,124, 93,191,165, 60,229,157,251, 4, 43, 87, -174,116, 41, 0, 43, 87,174, 4,138,214, 93,119,173, 55,121,141,120, 5,174,155,179,154, 91,172,135, 16,210,172,190,199,145,124, - 99,228,238,235,188, 55,175,130,199,119,189,201,227,255,156, 47,126,141,156,149,179,157,115,195,168, 14, 13,200, 31, 0,210,198, -223,239,124,163,251,213,167, 2, 32,212, 1,184,125,144,185,236,197,235,194, 0,126, 41, 0,183,115,194, 71,160,197,127,220,113, -232, 23, 25,228, 82, 41, 30, 30, 79,192, 16,130,129, 73,118, 28,251, 77, 1,134, 56, 99,254,213,213, 12,218,182, 22,129, 33, 82, - 28, 57, 38,133, 92, 6, 88,109, 86, 92,188,164,240,139,252,207,157, 62,140, 65,163, 39, 66,220,114, 16,206,157, 46,128,248, 90, - 14, 94,120,254, 37,250,246, 59,111,222,146, 6,174,175, 87,175, 74, 74, 74,210, 44, 94,188, 24,189,122,245, 42,211,233,116, 72, - 74, 74, 82,233,116, 58, 60,243,204, 51,154,180,180,180,219,162,174,125,115,137,223, 83, 9, 24, 54,100, 36,214,125,254,145,178, - 77,235, 54,154,208,208, 80, 94, 86,255,117, 19,236,236, 63,105, 1,144,245, 95,100,208, 19,191,255,132, 54,113, 97,144,203, 37, - 48, 24,172, 40,190,170, 7, 17,183,199,159,255, 50, 91,200,150,226,131, 95, 22, 1, 93,159, 64,131,229,133,133, 11,155, 67,214, -205,254, 73,243,230, 69,187, 41, 18,193, 33, 52, 95,164,236, 15,105, 55,183,158,129,183, 54, 75,123, 64,230,188, 87,211, 85,231, - 75,192, 29,139,196,196, 68, 87,194, 95,230,178, 23,175, 59,231, 83, 1, 8,118, 61,254,155, 93,223,223,175,206, 15, 2,157,142, - 32,164, 53, 65, 76, 52, 65, 82,127, 27,228, 82, 17,100, 82, 27, 98,162,229,245,147, 0,193,224, 36, 7, 10,126,145, 56,189, 5, - 60, 39,153,252,252,124,218,243,222, 8, 44,122,246, 95, 48, 73,227,241, 77,126, 49,186, 38, 56, 45,247,176,159,183, 98,209,223, - 94,162,239,189,123,235,148,128,228,228,100,146,159,159,175, 92,182,108,153,198,221, 59, 16, 12,229,234,118, 70,125,177,159,102, -223,227,204, 89,106,178,255,192, 30, 90, 94, 89, 14,211, 53, 35,228,242, 24,196,119,238, 19,144, 82,113,167,193, 89, 14, 59, 72, -183, 89,180, 14,174, 21, 1, 69,159,222,242,123,243,149,220,119,183, 97,236,196,199,252,178,220,125,249, 30,133, 28,128,219, 75, - 9,104,140,252,125,122, 0,254, 23, 64,225,204,234, 39, 12, 5, 5, 69,116, 11,138, 61,251,197,144, 75, 37,144, 73,197, 72, 25, - 79, 65, 41,139,168, 24, 59,236, 14, 2,150,117,212, 79,126,190,209,167,147, 1, 19,166,164,193, 32,238,134, 86, 97,161,152,241, -104, 52,178, 54, 29,115, 41, 1, 54,199, 55,183,252,254, 57, 69, 64, 24, 50,129,123, 21,238,214,123,203,212,189, 69,210,163, 94, -188,158, 25,178,163, 3,149,135,244,168, 23,175, 63, 81,184,176, 89, 86,191,128,230, 33,245,201, 85, 65,235,195,119,187,241,112, -167, 41, 1, 62, 13,224,196,196, 68, 33,104, 35, 64,128, 0, 1, 2, 4,252,143, 65, 40,244, 44, 64,128, 0, 1, 2, 4, 8, 10, -128, 0, 1, 2, 4, 8, 16, 32, 64, 80, 0, 4, 8, 16, 32, 64,128, 0, 1,130, 2, 32, 64,128, 0, 1, 2, 4, 8,184, 59,208, - 96, 21,192,252,249,243, 3,206,224,244, 86, 91, 59,216,242,102,206,157,231,243,123,117, 85,215, 92,239, 67,163, 91,187,222,175, -255,120,205,117,215,198,170,254,236, 83,222,206, 21,127, 84,204, 27,179, 96,149,235,125,185,230,191, 8,228,247, 53,134, 64,127, - 95, 99,240,246,251, 38, 61,174,246,249,189, 67,154,239,208,169, 83, 39, 92,184,112, 1, 73,170, 9,174,227,155, 63,207,184,225, -237,247,231,171, 87,155,236, 47, 22,177, 88,185,168,184,216,181,100,113, 85, 92,156,235,250,255,182,105,115,195,251,159,167,188, -220,220, 92,101, 94, 94, 94,131, 74,137,227,199,143, 87,165,164,164,104,111,197,248, 56,124,248,112,192,242,250,245,235,119,163, -127, 31,153, 63,127, 62,110,231,249,229, 86,200,203,202,202,154,222,187,119,239,172, 99,199,142, 77,153, 49, 99,198, 55,205,149, -231,190,209,145,123, 70,254,221,218,126,130,188,198,229,249,173, 0,120,194,110,183, 43,205,102, 51,136, 72, 2, 66, 8, 28,118, - 27,164, 18, 49,100, 50,153,182,185,154,135,221,110, 87, 2,128, 88, 44,110,150,172,186,170,107, 8,141,110,237, 34,254,214,237, - 59, 1, 0,174, 93,190, 16,144,188,157, 43,158,194,152, 5,171, 92,196,245,159,220, 2, 0,192,147, 41, 3,113, 55,226,144,230, - 59, 36,169, 38,224,144,230, 59, 0,192,132,212,153, 0,128, 11, 23,110,125,251,253,187,180, 84,121, 26,208, 36, 0,170,211,128, -115, 15,245,197, 47, 0, 0, 6, 46,123,251,150,182,155, 86,171,165,121,121,121, 48,155,205, 13,142,203,229,114, 77, 68, 68, 4, -148, 74,229,109,185, 28,138, 16, 50,236,222,206,237, 62,165, 14,135,241,244,165,107, 47, 81, 74,183, 10,118, 80, 19, 74,167,197, - 50,234,240,225,195, 17, 37, 37, 37,173,163,163,163, 91, 12, 24, 48,160, 56, 60, 60,252,243, 64,229,101,101,101,141,158, 49, 99, -198,158,172,172,172, 63, 3,136,156,246,196,188,185, 0,216, 99,199,142,205, 6,176, 25, 0,235,143, 60,110,207, 19,142,248,155, - 51,222, 60,119, 73, 12,214,146,190,198,148, 18, 1,183,153, 7,192, 29,250, 90,131,178, 77,194,253,154,145,189,187, 35, 68, 38, - 1,165, 20, 14, 7,197,111,103, 46,226,252,209,125, 42,133, 76, 2,145, 72, 20, 16,121,135,201, 47, 40,123,118, 43,210,252,118, -186,139,170,206,210, 41, 96,226, 7, 0, 69,100, 12,234,170,174,185,136,191, 41,143, 0, 31, 75,117,224,204, 23,177,115,197, 83, -174,129,212,216,117, 77,173,177,244,252,159, 82,169, 20,128,179, 76, 38,203, 58,199,183,195,225,112,253,126, 70, 36,225,109, 69, - 3, 64,155, 86,206, 82,157, 86,125, 53, 44,118, 59, 0,192, 96,119,202,235, 60,246, 79,184,167,103, 63, 94,196, 15, 0,125,135, -140,198, 33,205,119, 46,226,111,236,186,155,217,126, 0,240, 84,105, 41, 5,128,113,161,161,216, 94, 87,167,225,136, 31, 0,126, -223,177,243,186,235, 18,219,180,225,245, 59,107, 66, 43,148,133, 21, 63,163,248,210, 17,116,235, 56, 24,131,229, 74,191,251,112, -110,110,238, 35,219,182,109,227,200,223, 14,192, 12, 32, 4, 0,107, 54,155,197, 10,133, 2,122,189, 94,233,205, 19,112,139,201, - 63,238,254,196,222,219,182,127,185, 38,172,174,248, 36,134,165,205,207, 34,132,204,166,148,110,190,221, 38,166,252,252,124,218, -156,250, 20,124, 54, 3,107, 10, 54,155, 77, 89, 80, 80,160, 57,126,252,184,235, 88, 69, 69, 5, 78,159, 62,141, 54,109,218,124, -166, 84, 42, 85,225,225,225,124,159, 47,147,149,149,245, 79, 0, 15, 12, 27, 55, 73,145,149,149, 21, 55,237,137,121,225, 0, 28, - 0,184,142,123,111,253,117, 35,248,222, 31, 55,222,212,106, 53,109,108,188,113,215,249, 26,111,106,181,154,238,253,177, 0, 34, -145, 24, 14,135, 29, 53,181, 6,204,152,242, 8,125,247,221,119,155, 69,216,158, 74, 69,115,159,139, 0,223,240,182,237, 47, 7, - 94,149, 0,235, 76, 86,229,232,148, 25,154,246,173, 34, 17, 34, 23,131,101, 89, 56, 88, 64, 44, 34,136,142,236,142,158,221, 58, -104,242,183,127,167,114,216,234,148,254, 42, 1, 86,171, 85,217,163,231,121, 77,223,238,231, 33, 98, 28, 26,237,161,118, 42,169, - 68,226,151,140,186,170,107, 80, 68,198, 32, 50, 34, 28, 0, 92,127,189, 93,215,186,125, 39,159,222,128,157, 43,158,194,192,153, - 47,226,255, 30,155, 12, 0,174,191,222,174,251, 79,110,129, 95,218,181, 72, 36, 66,124,124, 60, 68, 34, 17,172, 86, 43,234,234, -234,224,112, 56,160,211,233, 2,122,184, 97, 98, 17, 62, 94,185, 9,178, 72,160,244, 2,240,179,161, 24,229,215,206,226,243, 21, - 47,249,101,245,247, 29, 50, 26,241,109,157, 33,146,120, 47,228,223,169, 83, 39, 87, 56, 0, 0,174, 92,185, 18,148,246,227, 83, - 92,245,169,210, 82, 58, 46, 52, 20,175, 61,245, 36, 0,224, 53, 55,226,255,226,244,233,134,228,239, 71,181,214, 61, 23,190, 80, -118,124, 66,172,121,177,195, 44, 88,216,100,200, 88,138,147, 21,187,240,201, 59, 27, 85,169,125, 50,248,246, 65,113, 94, 94,222, -102,147,201,132,117,235,214,153,231,204,153, 35, 7, 16, 6,128, 93,183,110,157,117,206,156, 57, 98,147,201, 4,185, 92,174, 73, - 73, 73,105,214, 68,247,205, 55,223, 40,119,236,216,161,105,110, 45,123, 87,223,145, 50,255,239,131,215, 94, 80,180, 56,241, 37, - 20,191,239,198, 63, 70, 69,133, 63,179,165,252, 95,245,150,231,109, 69,254, 27, 55,110,132, 78, 55,134,102,103,167,249,125,239, - 31,127,252,177,178, 57,100, 83, 87, 87,167,204,205,205,213,212,214,214,122, 61,127,245,234, 85,228,228,228,104,122,244,232,161, - 26, 60,120,176,175,126, 67,178,178,178, 62, 31, 54,110,210,212,211,135, 15,136,227,219,182,182, 79,123, 98, 94,131,121,119,247, -119,223,160,119,239,222,221,179,178,178, 30,234,221,187,119, 46, 0,236,223,191,191, 73, 82,229, 51,222,212,106, 53, 5, 33,128, -143, 42,127,107,214,172,161,215,202, 42,112,248,183, 19,174, 99,102,179, 5,111,127,144,105, 80,207,153, 46, 16,246, 93,140,235, -146, 0,107,107,107,149,195,198, 62,170,233,222, 33, 6, 50, 9, 3,150,101,113,237,218, 53, 28, 59,114, 24, 86, 59, 11,150,165, -136,137, 12,193,216,135, 38,106, 76, 22,187,223,255, 80, 38, 41, 67,215, 14,215, 0, 17,193,125,221, 46, 67, 38, 46,245,219,242, -119, 39,255,235, 44, 60,125, 45,174, 93,190, 0, 69,100, 76,163, 94,129,166,200,203, 19,159,126,245, 13,158, 76, 25,136,129, 51, - 95,108,212,170,245, 6,169, 84, 10,145, 72,132,136,136, 8, 20, 21, 21, 65,167,211, 57, 21,169, 0,201,191, 77,171, 56,132,137, - 69,120,244,233,215,241,208,140, 33,216,250, 91, 49,174,153,208,108,242,247,196,149,146,107, 56,126,232, 7,196, 70, 69, 56,201, - 95, 44, 10, 74,251, 61, 56,229,255, 0, 0, 81, 98,137, 95,228, 15, 0,127, 95,245, 31,252,125,213,127, 92,228,191,189,174, 14, -207,143,157,232, 60, 25, 43,229,117,223,159, 94,124, 75,249,151, 69, 15,104,158,232,248, 87, 72,152, 48,132, 34, 4, 12, 68,104, - 23, 55, 20, 79,189,182, 80, 83,212,118, 5, 47, 53, 66,171,213,218, 0,224,211, 79, 63, 53, 2,144,115,219, 40,175, 91,183,142, - 5, 16,226,190,173,178, 86,171, 13, 40, 46,103, 52, 26,149,254, 28,231, 97,249, 15,187,191,127,162, 49,251,155, 77,234,126,189, - 18, 68,117, 39,118,225, 66, 89, 45,174, 86, 27,193, 82, 26, 80, 34,112,122,122, 58, 77, 75,203,166,235,215,175, 15,106, 33, 49, - 55,242, 71,116,116,126, 64, 50, 10, 10, 10, 52, 25, 25, 25,132, 16,226, 82, 6,252,252, 13,215,145,255,161, 67,135, 48, 99,198, - 12,119, 15, 1, 78,157, 58,165, 49, 26,141, 77,110,152,149,149,149,245,212,176,113,147, 38,190,177,100,129, 56, 59, 59, 27,255, -253,224, 93,113,189,199,200, 69,254,217,217,217, 88,181,106, 21,122,247,238,157,235,107,188,121,146,127, 99,227,237,161,161,245, - 94,192,240, 80,159,242,222,251, 96,181,139,252,203, 42, 42, 81, 86, 81,137,154, 90, 3, 36, 18,113,216,234,117, 95,154, 61,173, -120, 1,119, 6, 18, 19, 19,175,123, 53,169, 0, 56, 28, 14, 26,211,169, 15, 58,181,110, 1,179,205, 1, 66,128,237,219,191,199, -103,159,174,195,209, 35, 71,240,252,194,231, 32, 18, 49, 96, 29, 44, 34, 66,100,232,212,103,152,198,100, 50,241, 30, 96, 54,155, - 77,217,179,219, 69, 77, 68,152, 17, 31,127, 90, 6,134, 80, 12,236,253,187,198,102,179,249, 53, 72,189,145, 63, 71,252,166,154, -202, 6, 10, 66,141,190,214,167, 60,111,131,137, 27, 72, 5,235,223,106, 64,112,159,126,197,175,124,111,215,174, 93, 17, 19, 19, - 3,189, 94, 15,169, 84, 10,134, 97, 96, 50,153,160,211,233, 32, 18,137,184,137,153,247, 61,127,189,121, 19,158, 91,185, 3,155, - 62,120, 5,109, 90,197, 33, 36, 52, 26,151, 29,197,248,124,197, 75, 8,171,159, 52, 68, 60,229,121, 35,127,142,248,107, 74,206, -161,123,124, 43,212, 26,205,144,133,200, 0,135,195,103, 62,128,175,246,123,105,237, 86, 28,255,229, 71,244,234,114, 31,106, 28, -190,149, 70,142,252,127,223,177, 19,127, 95,245, 31,215,241,237,117,117,216, 94, 87,135, 34,245, 63,177,227,196, 81,244, 28,216, - 5,168,244,189, 53,115,214,153,101,202,249,207,140,214,196,134,246,128,137,214, 2,150, 50, 72, 45, 85,176, 56,106, 97,102, 77, - 96,165, 97,104, 55, 60, 9, 57,191, 46,245, 53,209,145, 13, 27, 54,192,108, 54, 67,173, 86,135,168,213,106,192, 25, 2,128, 90, -173, 70,253,231,122, 11,202,140, 13, 27, 54,248, 61,104, 79,157, 58,165, 92,184,112,161,230,253,247,223,167,132, 16, 13, 0,236, -219,183,143, 46, 93,186,148,190,242,202, 43, 1,109,205, 28, 46, 99,214,253,231,197, 39, 20,227,218, 89, 68, 7, 78, 93,195,214, - 11, 12, 94,220, 86,106,249,167,214, 80, 83,103,195,255, 5, 34, 83,167, 27,115, 35, 45,127, 68, 71,231, 99,230,204,153,126,239, - 70,233, 78,248,107,214,172, 33,220,118,210,124,113,224,192, 1,101,105, 41, 63,163,196,106,181,226,216,177, 99,187,155,234, 47, - 0,148,241,109, 91, 75,211,210,210, 0, 0,133,133,133,216,253,221, 55,242, 43, 37,215, 88,142,252, 1, 32, 45, 45,205, 53,222, -142, 29, 59,182,162, 57,227,237,237, 57, 19,241,219,185,203,104,221,165, 13, 80,103,228,125,239,101, 21,149,176,217,236,245,115, -181, 29, 54,155, 29,151, 47, 94,144, 55,231,153,122,122, 15, 4,111,194,237,133, 6,174, 40,139,197,130,126,221,187,107, 66, 20, - 18,176, 44,133,131, 5,126,216,183, 31,255,124,237,117,176, 20, 56,115,246, 44,142, 30,249, 21,189,122,245,133, 72, 68,112,111, -151,120, 20,253, 98,135,130,231,230,120, 82,113, 25, 18, 58,149, 0, 98,130,203, 87,109,128,152,160, 79,247,139, 40, 56, 86, 6, -138,118, 1,221,128,187,123,223,155,103,192, 84, 83,217, 96, 53,128, 47,184,187,247,189,105,218, 5,235,223,194,152, 5,171,188, -102,177,187,195,110,183, 35, 36, 36, 4, 12,195, 32, 42, 42, 10, 70,163, 17,117,117,206,109,128, 99, 99, 99, 81, 89, 89,233,215, - 6, 28,102, 29, 48, 80,161,192,243, 31,236,195,152,190,192,197,195,192,207,245,231,158,255, 96, 31,254,189, 64, 5, 7,235,240, -187,253,142, 31,250,193,245,126,244,128,238, 16,135, 51,216,174, 61,129,126,221,219, 35, 34, 76,134, 79,115,242,145,164,154,128, - 43, 94, 86, 1,248,106,191,220, 19, 20,184, 10,164,140, 38, 88,187,181, 8, 49, 81,157, 49,121, 40,225,213,126,156,187,127,123, -221, 31, 91, 39,211,127,172, 0,218,213,128,252,229, 85,208,127,190, 6, 48, 38,144,130,165, 88, 21, 23, 71,254,219, 68, 32,160, -235,148, 48, 77,199, 22, 3,160,119, 24, 96,209,157,197,231,151,178,176, 63, 69,135,251,254,172,194,216,167,195,160,136,186, 23, -114,113, 20,196, 41, 53,248,249,155,159,233,253, 73,247, 55, 54, 73,185,254, 7,195, 48,160,148, 90,235,149,104, 51,195, 48, 70, - 74,105, 52,156, 73, 92, 1, 47,175,237,222,189,187,118,236,216,177,170,202,202, 74,205,246,237,219,157,138,207,246,237,232,209, -163, 7,186,119,239, 30,208,246,204,181, 22,246,153,185,127,255,247,150,119, 38,180,102,168,185, 6,127, 89,127,218,102,183,217, - 86, 89, 28, 88, 74, 41,173, 10, 68,230,164, 73,214, 27, 78,254, 35, 70,140,208,250, 43,167,160,160,160, 65,200,132,243, 2,240, -221, 85,210,225,112,248,165, 48,156, 63,127, 30,131, 6, 13,106,172,191,200, 1,220, 7, 64, 60,106,194,228,234,162,162,162, 22, -133,102, 28,210,109, 0, 0, 32, 0, 73, 68, 65, 84,133,133,200,206,206,198,128,162, 34,166,176,176, 16, 0, 48, 96,192, 0, 60, - 56, 50, 9, 17, 97, 50,172,250,100, 83,217,140, 25, 51,150,172, 94,189,122,129,191,227,237,234,230,183, 16,222, 83,142,176,110, -207, 97,227, 91,127, 70,223, 94,173,113,239,196,215,145,145,145, 65,154,202, 18,175,209,215, 66, 46,151, 1, 0, 36, 18, 49,140, - 70,115, 80,159,173, 64,250,183, 6,126,111, 6,196,178, 44, 66,100, 82, 88,237, 20, 12, 1, 24, 2,188,250,175,215,225, 96,129, -186, 58, 3,174, 93,187,138,184,184,214,160,148,133,221, 14,200, 37, 98,136, 36,252, 92,176,118,187, 93,121, 95,215, 43,154,150, - 81,122,128, 16,167,110, 76, 0, 66, 40,250,247, 60,163,249,233,104,156,202,223, 21, 1,156,117,223, 88, 72,128,143,245,239,169, - 69, 55, 70,252,254, 88,255,128, 51, 97,168, 85,171, 86,144,201,100, 46,151, 33,151,248, 23, 25, 25, 9,137, 68,130,203,151, 47, - 67,194, 83,222, 39,249,123,240,231,137, 35,193,153, 55,167,237, 78,247, 63, 0, 40, 19,128,136,215, 53, 88,240,183, 33,136,242, -227,126,175,148, 56,147, 21, 59,180,138,134,206, 98,129, 56, 66, 4,115,185, 17, 96, 24,180,233, 24,143, 29,187,127, 14,168,253, -254,111,209, 27, 56,255,195, 46,136,175, 1,213,113, 64, 8,195, 96,112,167,206, 24, 53, 50,142,151, 28,207, 88,255, 23,143,253, - 25, 95, 91,126, 7,238, 49, 3, 63,137,129, 48, 49,240,240, 0,196, 63,204,207,120,237,218, 46, 26, 86,107, 21, 36,118, 27, 62, -191,148,133, 31,231, 68, 98,196,163,143,160,123,171, 30,170,223,118,104, 53,253,210,234, 32,177,214,193,222,157, 69,121, 41,191, -164,209,122,229,205, 60,103,206,156, 48, 0, 58, 74,169, 4, 0,230,204,153,211,236,218, 26,147, 39, 79,214,238,223,191, 95,117, -242,228, 73, 77, 72, 72, 8, 66, 66, 66, 48,115,230,204,128, 38, 81, 66, 72,235,137, 19, 39,174,253,219,223,254,198, 60,191,224, - 25,182, 23,123,150,177, 88,109,117, 86, 7,253,155, 63,114,210,211,211,169, 78, 55, 6,147, 38, 89, 49,115,230, 76, 18,232,239, -185,145,228,239,205,221,191,102,205, 26,162, 86,171,233,220,185,115,121,253, 94,131,193,208,192,237,239,142,133, 11, 23, 98,225, - 66,231,166, 69, 73, 73, 73,238,215,203, 26, 17,215, 22, 64,167,122,165, 48,228,193, 41,179,204, 93,186,116,145,103,103,103,131, - 35,255,180,180, 52,196,181,105,227, 62,222,182,194, 45, 68,192,103,188,165, 63, 60, 2, 7, 75,202, 16,222, 55, 28,197,219,207, - 1,114, 25,166, 60, 61, 27,209,241, 19,121,206,205, 14, 20, 95, 45,181, 75, 36, 98, 49,231, 1, 0,128,203, 23, 47, 52,235,185, - 54, 22, 58, 16, 20,130, 91,167, 16,120, 42, 1,140, 55, 19,135, 82, 10,150, 2, 14,214,169, 4, 16, 2,124,243,117, 14, 30,157, -156,138,150,177,173, 92, 19, 32,245, 99,175,108, 17, 83,134,158,247, 92,118,125,238,211, 43,196,229, 36,235,127, 95, 17, 68, 76, -153,223, 55,228,233,238,247,118,222, 31,235,223,211,221,239,237,188,251, 90,246,166,160,215,235, 81, 91, 91, 11,139,197, 2,150, -101, 81, 94, 94,238,114,255, 27,141, 70, 24, 12, 6,191, 66, 0,155, 62,120, 5,218,223,128,154, 11,128,205, 4,252,123,177,202, -229,254,255,229, 48,240,235,213, 31, 32,242,179,253,106, 74,206, 33, 58, 50, 20, 49,209,161,184, 55,161, 7,138,206,151,227,116, -113, 37, 58,196, 68,194, 82, 90,134,179,103,206, 54,168, 5,192,167,253,134, 40, 31,193, 48,213,116,108,218,178, 17,154,189, 27, -145,181,124, 17,166, 44, 90,138,163, 54,160,188,178,140, 87,251,185,199,250,159, 24, 50, 8, 51,239,235,136,141,155,118,227,232, -209, 11, 88,126,172, 16, 27,198,204, 6, 62, 58,128,226,226,242, 6,181, 0, 26, 67,188, 89, 6,135,181, 2, 86,107, 13, 0, 32, -174, 93,123,116,239,209, 67,165, 87, 56,115, 49, 76,172, 17,140,165, 14,138, 58, 17, 74,175, 94,243, 69,168, 78,143,140,217, 12, -179,217, 44, 7, 96, 5, 16,110, 54,155, 35, 60,151, 4, 6, 10,163,209,168,220,187,119,175,166, 71,143, 30,152, 53,107,150,170, -162,162, 2,219,183,111,231, 61,216, 8, 33,195,100, 50,153, 33, 60, 60,220, 62,102,204,152,171,139, 23, 47,110,187,100,201,146, -162,159, 15, 31, 29,191,225,184,229,148,141,133,223,251,177,222, 8,151,127, 48,201,223,211,250,231,114, 20,220,189, 0,124,100, - 72, 36,127,168,228,203,151, 47,119,189,188,125, 6, 92, 43,124, 26,123, 54,210,250, 23, 3, 64, 92, 83,114,206,171, 59,157, 27, -111,135,127, 57,124,126,198,140, 25,233,254,140,183,225,247,223,139,228,161, 9,120,227, 95,239,226,189,149,121,248,127, 95,236, -198,188, 81, 73,184,246,109, 30,106,116,122,159,100,155,145,145, 65,210, 82, 30,132,205,102, 63,108,179,217,237,238, 10, 0, 0, - 44,125,245,165,128, 9, 91, 32,250, 91, 11,111,177,127, 79,175, 64, 3, 5,128, 97, 24,212, 24,140, 16, 49, 4,118,187, 3, 44, -165,176,179,206, 36,210, 35,191, 30,198,168,209,227,156,110, 50, 74, 33, 98, 68,168, 53, 90, 97,183, 90,124,107,152, 14,135,178, -115,187,171,154,216,232, 26,151,150, 49,100, 96,152,115,216, 16, 2, 66, 40,250,245, 56,171,177, 59, 28, 74,190, 55,199, 89,247, - 77, 37, 3, 6,100,189, 54,145, 92,227, 15,162,162,162, 80, 94, 94, 14,153, 76,134,218,218, 90,196,198,198,186,146, 2,205,102, - 51,170,171,171,253, 82, 0,210,223,216,128,127, 47, 86, 33,178, 19,160,253, 13,120,102,153, 6, 97, 98, 17, 38, 63,251, 38,174, -176,215,176,126,249, 11, 16, 49,252,229,113,214,255,128, 1, 9,136,237,210, 9,173, 98, 91, 66,202, 16,216, 9, 69,121,157, 9, -186, 90,115, 64,237,247,222, 91,155, 49,169, 71,103, 68, 68,196, 32, 36,182, 45,108, 85, 58, 28,222,250, 37,170,171, 46, 5,212, -137, 63,126,235, 41, 96, 65, 50,196,118, 43, 58,213, 1,101, 34, 61,254,125,245,103, 64, 26,193, 91,198, 47, 91, 14,170, 42, 24, - 19, 46, 73,141, 72,186, 71,133,251,102,135,161, 40, 74,171,137,141, 61,172,105, 63,184, 8, 53, 76, 45, 44,212, 4,227, 23, 44, -228, 97,225,124, 44,127,247, 9,158, 91, 5, 32, 13,214,192,253,254,251,239, 1, 0, 51,103,206, 84,117,239,222, 93,251,232,163, -143,186, 44, 70, 62,228, 31, 27, 27,187,109,237,218,181,161, 25, 25, 25,162, 5, 11, 22,224,185,231,158,163, 7, 14, 28, 24, 76, - 41,221,110,180,209, 30,148,210,159,252,183,230,162, 26,117,251, 7,154, 16, 24, 76,242,247, 36,120,119,133,101,205,154, 53,164, -160,160,128,151,107,255,202,149, 43, 7,184,247, 89, 89, 89,174,151,231, 49, 14,209,209,209, 0,208,216, 36,120, 5, 64, 53, 0, -230, 74,201, 53,252,248,227,143,174,152,255,128, 1, 3, 0, 0,217,217,217,248, 42, 55, 15,186, 90,179, 17,192, 82, 56,151, 6, -242, 30,111,223,110,250, 7,198, 45,126, 26,227,199,143, 70, 75,153, 8,181,132, 98,251,233,203,248,241,183, 98,191,136,122,254, -156,233,247, 23,157, 61, 43,190,124,241, 2,184,215,210, 87, 95,106,210,146, 23,112,123, 19,191,231, 49,111,104, 16, 2,144,201, -100, 56,115,226,168,170, 83,219,104,141, 66, 34,134,195,193,130, 16, 2, 66,128,116,245,147,160,148,133,163,190, 30,128,209,108, -198,201,211, 69,144, 74,125, 59,177,237,182, 42,244,187,239,188,251, 44,138,191, 46, 56,143,175,191,232,230,210,157,147,122,157, -195,193, 35, 61, 32, 22,197,250,101,253,123, 35,126, 83, 77, 37, 0, 4,100,253,123, 27,104, 5,235,223, 2, 0,222,214, 63,224, - 92,231,223,186,117,107, 88, 44, 22,148,150,150,194,225,112,160,101,203,150,168,172,172, 68,203,150, 45,235,219,149, 63, 97,151, - 95, 59,139, 87, 94,215,160,230, 2,240,206,162,225, 48,216, 29, 88,184, 44, 27,239, 47, 78,195,162,229, 91, 33, 38, 4,126,240, - 63,106, 74,206,161, 77,203, 22,144, 64, 2, 7, 8,174,158, 63,142,139,101, 53,232, 26, 27,141,111,127, 57,128,147, 39,224,183, -245, 63,101,238, 66, 72,162, 1, 70, 4,172,203, 59,143,175, 63,124, 30,115,223,202,192,194,135,251,226,201,209, 29,253,106,191, -237,117,117,120, 47,101, 42, 80, 45, 7,136, 4,120,239, 93,164,254,188, 15, 59, 70,207, 7,121,243,105,144,131, 47,240,178,254, - 1,224,215,171, 49, 24,100,170,129, 65, 33,130, 81, 46, 71,215, 41, 18, 88,168, 9, 53,140, 4,118, 36,128, 58,140,176, 85, 92, -197, 15, 31,212, 96,230,140,174,183,100,208, 22, 22, 22,210,122, 98, 32,147, 39, 79,214, 58,125, 99, 78, 12, 31, 62,156, 12, 31, - 62,156, 15,249, 15,109,219,182,237,247,111,190,249,102,232,153, 51,103, 32,145, 72, 16, 17, 17,129,163, 71,143,218, 40,165,229, -205,249,125, 77,173,201, 15,196, 59, 16, 76,242,247,180,254,157,196,122,253,242, 65, 62,185, 0,105,105,105,103,190,250,234,171, - 33,118, 59,191, 21, 78,114,185,124,110, 19,167,107, 1,156, 7, 48,224,244,225, 3,112,143,249,255,117,238, 84,124,223,165, 11, -184,112,192,182, 46, 93, 66,102,204,152,241,137, 63,227,237,177,228, 65,136,100,163, 96,132, 4, 95,175,120, 26, 31,110,253, 21, -207, 63, 56, 12,115,150,103, 33,117,233,231,126, 89,224,238,197,132,188, 29, 19,214,239,223,157,104,224, 1, 16,137, 68,164,250, -234, 89,156,187, 92, 9,177, 68, 4,187,131,133,205,238,192, 47,191, 20,226,179,207, 62,129,213, 65, 97,115,176,144,138, 25,148, -233, 12, 40, 62,249,163, 74,161, 80,104,125, 16,161,178, 71,215,139,127, 88,255,206,169, 10, 95,127,145,224,156,227, 24, 10, 48, - 20, 12,195, 98,112,223,147, 26, 7, 15, 47,128, 55,235,223,125, 21, 64,104,116,107,191,200,223,155,245,239,158, 85, 59,102,193, - 42,191,200,203, 57, 41,234, 96, 48, 24, 32,145, 72, 92,214, 63,203,178,174,191,254, 42, 0,159,175,120, 9,191, 20,239, 65, 88, -107,103,210, 95,184, 88,132,242,107,103, 17, 33,147,160,186,234, 10, 68, 12,129,152,225, 23,126,230,172,255,246,209,225, 56, 81, -116, 30,118,171, 21, 50,177, 20, 6,131, 25,223,106, 14, 32, 73, 53,193, 47,242,231,218,239,145,167, 94,195,250,127,191, 15, 35, - 11,180,239, 26,143,223,142, 31,196,194,135,251, 6,212,126, 0,176,176,107, 18,182,156,217, 13,212,216, 1,121, 75,236, 44, 56, - 1,242,230,211, 88, 21, 23, 71,248,146, 63, 0,204,232,182, 88,251,195,206, 2,192, 90, 11, 3,169,133,142, 49,160, 70,108,131, -205,161,135,204,108,132,188,228, 60, 54, 44, 57,131, 78,137, 9,104, 34, 1,176, 1, 20,110,153,175,114,185, 28,114,185,220,235, - 57,190, 88,187,118, 45,214,174, 93,219,172,193, 28, 30, 30,254,204,217,179,103, 67, 35, 34, 34,160, 80, 40, 16, 29, 29,141,242, -242,114, 16, 66,140,193,156, 52, 56,139, 63, 63, 63,159, 2,206,132, 64,127,146, 2,131, 77,254, 31,127,252,177,146,250, 94,235, -206,107, 69, 64,104,104,104,186, 88, 44, 62,231,121,124,249,242,229, 13, 44,127, 0,232,216,177, 35,146,147,147,215,249,178,127, -174,148, 92,107,144,237,255,202,223, 23, 64, 38,150, 34, 46, 46, 14,220,234,128,250,243,161,254,140,183, 63, 43,251,224,185,119, -223, 71,109,105, 25, 98, 35, 90,225,248,137, 75,152,179, 60, 11, 25, 25, 25, 36, 16,178,230,190,231,254,125,119, 57,130, 39,224, -206,192,175,191,254,218,100, 49,160, 70, 61, 0,245,147,136,182, 80,187, 89, 69,105,138,166, 83,219, 24,132,135,200,112, 95,175, - 68,220,215,179, 47,196, 12, 96, 48, 57,112,233,106, 21, 10,180,223,169,194, 66, 67,124,254,131, 58,163, 17, 9, 29,175,194,108, -145,131,114, 70, 13, 5, 20,114, 51, 40, 5,170,170,101, 0, 1,194, 67,237,232,157,112, 1,251, 14,245, 67,120,120, 56,111,235, -223,221,226, 87, 68,198, 64, 66,109,128,253,143,249,206, 33,246,253, 27,221,173,127,119,139,159, 59,118,246,248, 97,215,181,124, -170,236,185, 43, 1, 0,208,186,181, 83, 25,169,170,170, 66, 68, 68,132,203,253,239,143, 2,192, 41, 1,192,155,152,159, 54, 18, -248,247, 62,124,248,242, 4,164, 46,122, 31, 89,111, 61, 9, 49, 33,144,202,248,173,216,225,172,255, 19,151,202,112, 79,251,150, -248,232,191, 27,208,169, 83, 39, 68,182,237,138,190,109,187,194,102,249,195,253, 47,225, 33,147,179,254, 95,159, 59, 26,207,188, -186, 14,237,187,144,102,181, 31,103,253,143,221,244, 49,118,204,156, 14, 18, 63, 24,128,179, 42, 32,224, 44, 17,204, 93,251, 76, - 92, 28, 47,226,232, 99,121,129,100,189,187, 76,217,117,114,173,166, 83,183, 94,208, 43,128,243,184,136,218, 11,229, 40, 95,234, -128, 65, 23,143, 5,179, 23,241,126, 32,171, 87,175, 38, 10,133,130,154, 76, 38,184, 89,158, 84,161, 80, 96,245,234,213,126,148, - 39, 10, 30,106,107,107,223,121,242,201, 39, 83,214,174, 93, 43,143,140,140,132, 70,163,193,202,149, 43,245, 86,171,245,193, 96, -254, 31,206,226,231,150,203,249,155, 16,152,156,156, 76,116,186, 49, 52, 24,228, 15, 0, 28,177,243, 33, 40, 30, 21, 6,173,179, -103,207, 30,188,113,227,198,163,117,117,117,109,108, 54,231, 50, 83, 79,242,191,239,190,251, 48,120,240,224,137, 60,158,179,184, -166,228, 28,222,248,199, 43,248,102,203, 54,140, 27,214, 31,187,242, 15, 58, 13,152,182, 93, 17,217,182, 43, 6, 20, 21,225,193, - 41,179, 42, 46, 85, 26,199,118,136, 9,201,225,107,253, 63,151,185, 5, 75,254, 52, 22,109, 91, 43, 93,202, 5,119,143,124, 60, - 55,129,120, 7, 4, 79,192,157,171, 20,240, 82, 0, 0, 32, 34, 60, 76,251,139,118,179,234,124,252,189,232,210,173,135, 38, 34, - 84, 1,150, 2, 38,139, 21, 69, 69, 69, 40, 47,250, 85, 21, 30, 22, 10,134, 97,124, 14, 92,133, 92,142,141,223,143, 84,113, 25, -240, 77,186, 35, 24, 6,161,161,252,173, 39,110, 9, 96,104,116,107,176, 14,155,147,252,235, 97, 35, 18,159, 37,118, 61,193, 45, -169, 25,179, 96, 85, 3,210, 10,132,252,221,149, 0,247,194, 63, 85, 85, 85,190, 31,128, 15, 37,224,115,183, 85,194,107,151,254, -245,143, 15, 54, 3,194,120,202,105, 31, 29,142,141,135,126,197,111,167,126, 71,146,106, 66, 3,210,247,135,252, 57, 60,242,212, -107,248,186,127, 40,158,122,180,123, 80,218,111, 97,215, 36, 44,202,221, 8,242,198,171,216, 22, 55, 8, 43, 13,191, 53, 56, 63, - 57,178, 5,226,229,254,237, 73, 49,163,219, 98,237,182,220, 28, 92,209,157, 67,121,229, 85,148,158, 14,131,200, 17,129,161,125, -134, 67, 53, 91,117, 75, 39,181, 96, 84,251,163,148, 30, 34,132,140, 33,132,236,124,255,253,247,229,147, 38, 77,210, 27,141,198, -177,129,196,252,155, 66, 48,150, 0,170,213, 81, 65, 33,127, 79, 43, 53, 72,168,152, 58,117,106,215,218,218,218, 55, 10, 11, 11, - 23, 20, 23, 23,163,174,174, 14, 82,169, 20,109,218,180, 65,108,108,236,164,254,253,251,127,203, 83,214, 73, 0, 3,218, 71,135, -227,129, 7, 30,192,175,103,138,209,178,115,207, 6,227,237,193, 41,179,140, 0, 62,224, 67,254, 28,254,172,236,131, 49,249, 63, - 97,230,171,159, 97,196,136, 17,136,139,139,243,170,104, 5,171, 65, 56, 37,192,159,182,110, 76, 33, 19,148,136, 91, 71,250,188, - 74, 1, 3, 64, 68, 68,132,214, 82,117, 89,249,139,246,180, 10,112,102,210, 82, 74, 33,147,201, 16, 25,193,187, 6, 54, 36, 18, -137, 54, 82, 34, 9,250,205,113,174,126,145,221, 8,216,141,174, 12,120,142,248,253, 93,139,197,185,250,207, 30, 63,140,179,199, - 15, 35, 54, 54, 22,229,229,229, 1, 17,127,100,108, 91, 88,121, 36, 71,242,197,204,215, 62,199,129,125,218,160,201,187,112,225, -130,107,183, 63,155,197,124, 29,249,251, 67,252, 28,102,247, 15, 13, 90,251, 1, 0, 89,241,130,139,248, 57,242, 63, 95, 87,167, -154, 28,217, 2, 15,243,180,250,189,225,161,206,169, 4,157,235, 63, 4,144,216,190,102,205, 26,194, 85,251, 91,189,122, 53,113, -175,252,183,110,221, 58,178,122,245,106,215,251, 53,107,214,220,244, 65, 79, 41,221, 79, 8, 25,145,147,147,179, 80,175,215,175, -160,148, 22, 4,251,127, 4, 99, 9, 96, 48,201,233, 6,193, 20, 30, 30,190, 80,169, 84, 46,108,166,156,253,199,142, 29, 27, 10, -160,115,203,206, 61,141, 54,139, 57,164,126,188,233, 1,212, 0, 56,217, 33, 38,228, 49, 56,147, 5,121, 99,204, 43,107,111, 10, -241, 55, 71,209, 18, 72,254,214, 32, 49, 49,145, 23,249,251, 52, 64,197, 98,177,214,151, 59,254,102,131,139,237,115,196,143,102, - 18, 63, 23,155,174, 41,187,130,154,178, 43,136,141,141,109,150,197, 15, 0,118, 7,235,183,247,161, 41,148, 85,213, 4,252, 91, - 60,193,197,246,131, 69,252,193,110, 63, 46,182,191,197, 96,160,238, 86,127, 63,177,164, 89,196,255,191, 4, 74,233,207, 0,166, - 11, 45,113,235, 49, 99,198,140, 12, 0,159, 93,170, 52, 26,109, 22,179,123, 60, 50,162, 67, 76, 72, 20,252,220,253,143, 35, 85, -119, 55,255, 29,164, 84, 9,184,137, 74, 0, 47, 67, 43, 49, 49, 81, 72,236, 16, 32, 64,128, 0, 1, 2,254,199,192, 8, 77, 32, - 64,128, 0, 1, 2, 4, 8, 10,128, 0, 1, 2, 4, 8, 16, 32, 64, 80, 0, 4, 8, 16, 32, 64,128, 0, 1,130, 2, 32, 64,128, - 0, 1, 2, 4, 8,184, 43,208, 96, 21,192,252,249,243, 3,206, 34,245,182,221,228,237, 46,239,240,225,195, 1,203,235,215,175, -223, 13,151, 23,236,251,109,217, 50, 49, 96,121, 21, 21,191,222,234,231, 75,234, 21, 86, 22, 94,138,175,220,137,253,239,102,201, -171, 47, 76,196,212,183, 33, 5, 64,231,207,159,207, 10,237, 39,200,187,147,228,101,102,102,138,211,211,211,237, 0,240,209, 71, - 31,209,110,221,186, 97,196,136, 17, 68,104, 63,239,242,252, 86, 0,238, 6, 52,183,200,196,212,169, 83,149, 0,220, 75,134,170, - 54,110,220,168, 21,116,197, 91,131,154,154,154,199,143, 29, 59,214, 87, 36, 18, 45,146,201,100, 48, 26,141, 47, 12, 27, 54,236, - 93, 4,161,210, 30,165,212,239,106,140,119, 34,230,207,159, 79,193,115,147, 25, 1,183, 14,185,185,185,202,148,148, 20,109,128, -223, 85,229,229,229,237, 14, 70, 65,169,122,121,143,229,229,229,109, 88,179,102, 77, 52,156,123, 26, 56,112, 11,170, 91,186,131, - 35,255,189,123,247,210,159,126,250, 9, 73, 73, 73, 24, 49, 98,132,208,113,130,229, 1,184,211,145,159,159,175,108,206,247,167, - 78,157,170,220,184,113,163,102,234,212,169,238,135, 53, 83,167, 78, 13, 88, 9,224, 20,138,236,236,108,174, 84,167, 95,178,210, -211,211,169,159,255,175,201,245,192, 59,119,126,226,175, 60,149, 78, 23,122, 43, 20, 32,242,219,111,191,189,163,215,235,255,212, -177, 99,199, 22, 21, 21, 21,168,223,110,247,237,175,191,254,250,237,208,208,208, 81, 15, 62,248,160,166, 89,255, 32, 0,242, 87, -171,231,251, 61, 9,102,100,172, 38, 55, 79, 94,211,229,112, 27,219,244,133,239,248,218,184,113,163, 6,175, 18,144,127,121, 87, -168,240, 42,193,212,147,105,126,183,235,184,113,227, 40, 0,108,223,190, 61, 40, 4,198,109, 5,172, 86, 71, 5,125,125,124,110, -110,174, 50, 47, 47, 79,227, 15,217,254,229, 47,233,148, 82,231,214,234,222,240,240,195, 19, 85,121,121,121,154,148,148, 20, 18, - 64, 63, 30,181,109,219,182, 93, 35, 71,142,196,188,121,243,104, 86, 86,214, 24,189, 94,159,239,207,111,243,162, 52, 98,218, 16, - 41,212,243,212, 85, 47,124,177,248,219,183,166,191,245, 8,119,110,237,218,204, 38,127,227,172, 89,179, 40, 0,132,134, 54,190, -181, 65, 93, 93, 29, 0, 96,206,156, 57, 1, 61,159, 83,135, 84,200,207, 60,130,228,244, 76,154,158,158, 46,212, 63,224, 1,174, - 56,144,123,141, 0,177,143, 1,239,181,110, 54,143,122,218,183, 10,205, 34, 4,119,242,223,184,113, 35,153, 58,117, 42,117,147, -235,247,253,114, 10, 5, 71, 52,245, 27,126,248,175, 80,100, 71,251,241, 95,147,125, 94, 81,247,240, 95,249,139,243,115, 95,155, -198, 8,200, 79,175, 12,169,169,169,249,170, 87,175, 94, 83, 0, 48,148, 82, 40, 20, 10,148,149,149,161,186,186, 26,145,145,145, - 40, 43, 43,219,253,253,247,223,171, 30,124,240, 65,191,148,147,252,252,124,202,109,204, 66, 8,193,148, 41, 83,144,156,156,172, - 34,132,240,150,147,155,187,217,245, 62, 37,101,146,207,207,190, 96, 58,240,212, 31,205, 61,100, 85,131,207,158,199, 20, 67,124, -111,170,196,109, 39,236,142,189,123,247, 98,233,210,165,215, 61,139, 47,190,248,130,242,108, 55,101,118,118,182, 6,175,146,122, -130, 77,187,126,226,126,149, 52,219, 66,188,141,231,150, 6,150,118, 70, 70,134,138, 82,138,245,235,215,211,253,251,247,163, 79, -159, 62, 62,191,123,160,145,154,140,155,178, 23, 33, 47, 47, 79,195,178, 44, 50, 51, 51,225,107, 91,101, 66,136,146, 82,234,234, -175,223,126,251,109, 8, 33, 4,211,167, 79, 47, 5, 16, 55, 99,198,140,157,107,214,172, 97,252,177,216,223,221,249,174,235,253, -181,237, 87, 65, 8, 65,214,179, 33, 0, 8,222,153,245,246, 35, 45, 91,182, 4, 0,124,249,105, 22,230,141,156,199, 75,230,128, - 1, 3,208,165, 75,151,160,180,123,102,102, 38,147,158,158,206,126,244,209, 71,244,167,159,126, 66,233,233, 78, 64, 69,148,192, -234,126,146,191, 39,152,166, 38,242,236,236,108,100,102,102, 82,111, 19,104, 32, 59, 67, 53,215, 66,247, 37,207,205,202, 14,216, - 40,220,184,113, 35,217,184,113, 35,225,148, 0, 0,170,230, 40, 20,132, 16,164,165,165,129, 82, 74,220,126,155,223,138, 10,153, -170,115,189,248, 28,247,133,176,173,171, 93, 47, 62,199,253, 33,127, 74, 41,184,221,217,124,237,210,230,173, 79,234,116,186,207, - 34, 35, 35,167, 0, 96,230,206,157,139,153, 51,103, 66, 42,149, 66,161, 80, 64, 46,151,131, 16, 2,145, 72,132,154,154, 26,222, -237,152,147,147,163, 84,171,213, 52, 39, 39, 7,110,207, 4, 95,127,253, 53,230,205,155,167,201,201,201, 81,222,142, 3,215,155, - 66,112, 43, 60,107,217,217,217,154,140,140, 12,242,216,169,169, 94, 45,124,181, 90, 77,167,158, 76, 83,121,243, 12,248,194,188, -121,243,232,243,207, 63,143,206,157, 59, 7,229,247,206,155, 55,143,170,213, 81,136,137,217, 21,212,118,216,188,121,243,232,252, -252,252,221,125,251,246, 37, 31,126,248,161,150, 35,255,230, 96, 83,246, 34,172, 88,177, 2, 44,203, 98,209,162, 69,224, 35,211, -157,252, 1, 96,219,182,109, 91,234, 93,225, 81,211,167, 79,183,143, 28, 57, 18,106,181,154,229,107,180,120,142,209,149, 43, 87, -226,177, 7,156,182, 97,214,179, 10, 76, 27, 34,197, 11,227,158,231,125, 79,161,161,161, 24, 49, 98, 4,210,211,211, 73,114,114, -178,215, 23,119, 13, 95,101, 47, 61, 61,157, 5,156,219,172, 3, 64, 68, 72,133,192,234,205, 36,255, 38, 21, 0,142,172, 10, 11, - 11, 93,101, 39,221,173, 39,127,137,214,101, 65, 4,121, 82,242,162, 12,168,130,217,120, 27, 55,110,212, 4, 65,134, 75,161, 72, - 75, 75, 83,113,109,120, 55,193,157,252, 1,160,184,184,216,117,238,202,149, 43,188, 21,198,154,154,154, 55,141, 70,227, 44,134, - 97,152, 25, 51,102,160,166,166, 6, 37, 37, 37,144, 72, 36, 16,139,197, 16,139,197,144, 72, 36, 80, 40, 20, 48,153, 76, 94, 75, -162,122,153,224,148, 59,119,238,212, 16, 66,144,154,154,138, 53,107,214,144,228,228,100,146,145,145, 65, 82, 83, 83,185,254,163, - 17,166,138,166,201,191,190, 45, 85,220, 36,238,254,236,211,210,210, 84,201,201,201, 90, 32,176,146,180,201,201,201,100,205,154, - 53, 36, 59, 59, 27,148,210,160, 40, 99, 47,189,244, 18,178,179,179,121,245, 17, 95,248,230,155,111,198, 28, 58,116, 40,191, 83, -167, 78, 48, 24, 12, 52, 52, 52,148,238,219,183, 15,128, 43,201, 50, 32,242, 95,190,124, 57, 8, 33, 96, 24, 6,135, 14, 29, 2, - 39,211, 15,143,196, 35,132, 16, 76,155, 54,205, 94,127,200, 58,125,250,116,189, 82,169,196,188,121,243,216,111,191,253,214,231, -189,187,135,194,174,109,191, 10, 16, 96,253, 51,127, 84, 45,206,122, 54, 4,211,135,202,176,248,193, 23,120,255, 46, 62,150, 63, -159,107,246,238,221, 75, 51, 51, 51, 93,175, 67,135, 14,193,112,105, 0, 96, 53,129,132,217,145,255,250, 73,184,159,231, 94,194, -200,109, 72,254,233,139,223,242,122, 94,220,212,128, 44, 42, 42,162,133,133,133,200,206,206, 6,247,158,115,237,248, 51,200,111, - 52,249,187, 91,213,220, 36,116,187,194, 61, 36,112,183,129, 82,138,226,226, 98, 92,187,118,205,117,204,243,179, 15,136,126,252, -241,199,241, 9, 9, 9, 16,137, 68, 56,123,246, 44, 40,165,248,253,247,223, 97,181, 90, 65, 8,129, 88, 44, 6, 33, 4, 14,135, - 3, 70,163, 17,155, 54,109, 66,114,114,211, 97,143, 93,187,118,105, 0, 32, 53, 53,245,186,126, 91,255,153,114, 68,193,167, 95, -123,186,245,125,125,230, 99,229,115,104, 44, 28,192,199,245,239,101,242,108,118,146,148, 43,230,239,166,192,113, 10, 44, 23,243, -207,119, 35,255, 64,172,117, 78, 9,227,200,104,215,174, 93,154, 64,195, 0,156,188,110,221,186, 93, 71,110,129, 96,245,234,213, - 56,121,242, 36,141,141,141, 69,187,118,237, 92,219, 62, 95,184,112, 1, 34,145, 8,255,249,207,127, 2,250, 7, 35,135, 58,183, - 47, 99, 89, 22,127,251,219,223,176,114,229, 74,236,219,183, 15,132, 16, 60,156,242, 23, 92,188,192,111, 3,199,109,219,182,109, -174,127,198,102, 56, 87,200,176, 0, 48,125,250,244,106, 0, 45,242,242,242, 64, 8,225,173, 80, 57,173,255,235,247, 49,113,134, - 3,128, 47,179, 14, 35,183, 38,247,166,121,203, 78,157, 58,133, 67,135, 14, 53, 56,230,168, 62, 15,187,141, 5, 72, 45, 90, 60, -104,195, 33,143,205,174,147,146,146, 4,230,231, 65,254, 77, 42, 0,245,110, 23,194, 89,253, 28,249,123,141,253,249, 65,214, 77, - 89,130,124,226,196,190,228,121,158,191, 85, 59, 82, 77,157, 58,213, 61,214, 76,189,157,231, 60, 3,205, 34,221,141,193,141,131, - 25, 38,206, 15,200,242,111,108,178,141,143,143,191,238,218, 38,158, 73,139,232,232,232, 94, 22,139, 5, 85, 85, 85, 56,112,224, - 0, 68, 34, 17,172, 86, 43, 76, 38, 19, 88,150,117,237, 74,105,179,217, 96,177, 88,120,133, 24,184,231,208, 88,191, 77, 78, 78, - 38, 57, 57, 57, 52, 59, 59,219,167, 50,225,180,186,110, 76, 14,128, 98,200,170,235,136,158,251, 28,136, 34, 48, 98,196,136,230, - 43, 1, 30, 49,255,252,252,124,165,139,236,255,136,249, 7,148, 35,227,161,132, 1,112,238,182,168, 86,171, 41,159,231,192,215, - 11, 80,159,251,224,119,110, 1,183,179, 99,187,118,237, 16, 17, 17, 65, 60,149,221, 94,189,122, 5,108,249, 83, 74, 97,183,219, - 93,199,134, 13, 27,134,125,251,246, 97,207, 15, 14,188,187,140, 95,140, 61, 55, 55,119, 92,125,236,255, 4,128,150, 0,220, 55, - 27, 42, 1,208, 2, 0,242,242,242, 52,125,251,246,245, 41,175, 97,236,223,139,167,160,254, 47, 95,121,193, 64,122,122, 58, 73, - 74, 74,162,154,207, 98, 97,175,254, 21,132,173, 6, 28,206,157, 86, 25,145, 29,250,125, 12, 36, 82, 49, 44,142, 22, 56,120,161, - 47, 94, 89,174,195,161, 67,135,136,183,101,213, 2,252, 84, 0, 60, 61, 1,254, 90,254, 69, 69, 69, 52,152,238,110, 95,242,234, -195, 18, 65,243, 52,100,102,102,146,244,244,244,128,190,235,249, 59, 51, 50, 50, 12,106,181, 58,172,177,243,129,194, 61,246, 31, - 12,101,192, 61,246,207, 87, 25,152, 57,115, 38, 66, 67, 67, 17, 22, 22,134,240,240,112, 68, 70, 70,178, 81, 81, 81, 76, 94, 94, - 30, 30,127,252,113,215,117,114,185, 28, 99,199,142,133, 90,173,166,141,236, 86, 21, 99,181, 90, 81, 85, 85, 5,179,217,140,200, -200, 72,200,100, 50,216,237,118, 80, 74,225,112, 56, 96,181, 90, 97,179,217,224,112, 56,252,202, 47,240, 21,178, 74, 77, 77,197, -237, 16,154,241,149, 16,232, 47, 56, 37, 32,224,254,245,175,198,219,110,234,201,180,250,188,155,192,100,123, 90,255,238,138,100, - 32,201,128,158,214,127, 83,138, 41, 95,242, 23,137, 68, 52, 34, 34, 2,112, 38,212, 17, 0,212,102,179,161,166,166, 6,173, 90, -181, 10,232,190, 57, 99, 74, 44, 22, 99,193,130, 5, 56,116,232, 16,254,136,251,243,239,211,223,127,255,253,247,195,135, 15, 7, -128,112, 56,195,185, 70, 0,216,176, 97, 67,171, 61,123,246, 68, 80, 74, 93,202, 54,159,117,226, 43,223, 95,137,105,131,175,183, -254,103,254,219,136, 13, 7,108,160,148,162,223,140,126,152, 55,114, 30, 9,116,221,121,160, 74,128,106,118, 38,253,126,101, 71, -136, 13,122,192,238,252,215, 44, 0,169, 24, 40,190,214, 2,187, 47, 13,112,100,126, 89, 46, 58,116,232, 16, 73, 74, 74,146,227, -127, 28,124,172,127,128, 71, 37,192,252,252,124,151,235,223, 61, 31,128, 15,186,116,233, 66,210,210,210,130, 22,147,231, 33, 47, -224,248,250,212,169, 83,169,231, 43, 63, 63,159,229, 86, 5,184,173, 8, 8,180, 19,135,221,205, 29, 46, 51, 51, 19,203,151, 47, -111,208,175, 56,242, 79, 73, 73, 65, 74, 74, 10, 0, 96,207,158, 61, 77,137,137, 46, 42, 42, 50, 59, 28, 14,232,116, 58, 84, 84, - 84, 64,167,211,193,104, 52,194,104, 52,194, 96, 48, 64,175,215,163,166,166, 6, 38,147, 9, 22,139,197,149, 20,212, 36,137, 17, -130,156,156, 28,191, 20,182, 59, 25,123,247,238,109,240,114,199,169, 83,167,148,238,159,249,196,156, 61, 99,254,158,150,123,115, -178,246,189,125,119,205,154, 53, 36, 39, 39, 39,168,185, 0, 57, 57, 57,188,231, 46,142,252, 25,134,161,245,253,203,229,250,103, - 89, 22,165,165,165,232,214,173, 27,153, 63,127,190,223,191,229,229,197, 35,177,103,207, 30,176, 95,181, 0,165, 20, 43, 86,172, -112, 61,163,189, 7,120,231,237, 33, 55, 55,119, 18, 0, 76,159, 62,189,184, 94, 1,176,124,249,229,250, 86,243,231,207,111,181, -103,207, 30, 60,244,208, 67, 99,252, 89,166,120,109,251, 85, 16, 16,172,119,179,254,103,188,111,132,104, 90, 13,190, 60, 96,197, -115,207, 61,135,101,223,191,125, 43,230, 21, 17,167, 4, 60,248,156, 29,212, 20, 9,232, 1,232, 1, 81, 45,160, 47, 5,182, 29, -110,131,204, 47,203, 69,245,222, 2,113,122,122,186, 89, 32,127,223,228,239,211, 3,144,153,153,217, 32,238,239,158, 15,192,119, -237,101,189,187, 80,197,185,229,155,235,146,247, 38,143,115,251, 39, 39, 39,107,131,181,132, 40, 57, 57,249,183,252,252,252, 94, -183,227, 3,230,172,254, 96,185,255, 57,171,223, 95,247, 63,135,245,235,215,187,222,255,243,159,255,196, 39,159,124, 2, 0, 86, - 0, 82,142,248, 1, 96,236,216,177,190, 20, 0, 83, 66, 66, 2,140, 70, 35,172, 86, 43,202,203,203, 33,147,201, 32, 22,139, 93, - 30,128,186,186, 58, 24,141, 70, 88, 44, 22,212,212,212, 96,202,148, 41, 62, 21, 76,206,186,111,106, 89, 43,119, 29, 31,220,200, - 28,128, 64,206,123,130, 91,238,231, 13, 43, 86,172,208, 44, 88,176, 64,213,189,123,119,237,173,236,195,141, 89,255,238,240, 39, - 23,160, 49,235, 63, 80,203,159, 97, 24,202,178, 44, 1,240, 15,174,107, 59, 28,142, 87, 67, 67, 67, 17, 31, 31, 31,208, 28,243, -202,139, 35,161,213,106, 65,114, 98, 0, 0, 59, 94, 9,199,216,215,107, 49, 98,196, 8,188,177,108,143, 95,133,169,182,109,219, -182,105,228,200,145, 0, 80,190, 97, 67, 86,187, 61,123,246,181,160,132, 98,252, 67,227, 83, 82, 82, 82,182,248, 51,157, 0,206, -216,255,180, 33,146,134, 22, 63, 40, 22, 60,183, 0,113, 99, 91,223,178,130, 89,233,233,233, 13, 52,124, 90, 11,200,172, 0, 75, - 9,236, 14, 10, 25, 5,226, 20,140,251,245,118, 8,112,242,247,178, 23, 27, 85, 16, 56, 15,172,152,143,229, 63, 96,192,128,235, -242, 1,252,113,209,121,146,118, 16,200,217, 83,158,230, 6,116,188, 94,249,249,249, 65,147,119,183, 38,254,113,133,101, 56, 55, -113,118,118, 54,158,120,226, 9, 0,144,114,215,184,159,171,159,180, 26,195,241,193,131, 7, 63,174,213,106,179, 29, 14, 7,244, -122, 61,108, 54,155, 43,238,111, 54,155, 93, 75, 12,185,196,192,177, 99,199,106,121,244, 23,146,157,157, 77,235,189, 0, 13,250, -109,126,126, 62,119, 28,201,201,201,188,188, 85, 55, 59, 7,192, 51, 44,224,235,121, 52,117, 94,173, 86,211, 21, 43, 86,104, 30, -123,236, 49,124,245,213, 87, 1, 61,115,207,229,183,220,231,141, 27, 55,106,210,139,213,152,234,195,210, 30, 55,110, 28, 61,127, -254, 60,190,255,254,251, 70,219,251,252,249,243, 0,128,237,219,183,251,252, 61,105,105,217, 52, 45,109, 52,198,140, 41, 66, 81, - 81,145,215,236,242,202,202,209, 0,116, 80,171, 27,159,183, 56,242,183, 90,173, 84, 42,149,114,215,252,163, 94, 33,120,245,226, -197,139,232,216,177, 99, 64,150, 63,195, 16,167,194,206,145,255, 81, 59, 62,209, 88, 1, 0,111, 44,219,227,247, 28,193,141,137, -249,243,231, 39, 82, 74, 49, 97,226,132, 41, 15, 79,124,248,155, 64,166,166, 73,143, 62,114,130, 16,114, 31,165,128,104, 90, 13, - 40,165, 88,176,112, 1, 90,143,109,243, 71,224, 35,112,112,236, 76,209,140, 74,130,153,153,153,116,227,139,109, 17, 86,121, 30, -231,244,241,232, 44, 43, 7, 66,227, 32,174, 43, 69, 68, 93, 37,128, 86, 46,143,129,167,210, 32, 32, 0, 15,128,251,114, 63, 15, - 87, 31,205,206,206, 6,223,132, 41, 79,210, 14,214, 15,119,151, 23,132,245,255, 2,154, 9,119, 23,186, 59, 9,113,245, 36, 60, -207, 53, 18, 67,180, 3,248,122,228,200,145, 79,231,229,229,125, 96,183,219, 81, 93, 93,237,202, 1, 0,128,242,242,114, 84, 87, - 87,131, 82, 10,127,194, 75, 99,198,140, 81,237,220,185, 83,147,157,157,141,156,156, 28,234, 25,243, 31, 51,102,140, 95,197,128, -110, 4, 76, 7,158,242,155,240,189, 17,124, 83, 74, 64, 70, 70, 6,153, 55,111, 30, 13,132,252, 27, 36, 0,186, 61,119,183,164, - 64,127,189, 0,141, 42,238, 23, 46, 92,112, 41,104,124, 13, 13,247, 80,229,245,247,205,111,174,170,169,169,161,145,145,145,238, -228,255,170,197, 98, 65, 73, 73, 9, 58,119,238, 28, 16,249,171,213,106,202,126, 21,133, 29, 71,157,198,233, 58,141, 21, 27, 14, - 88, 65, 41,197,190, 31, 3,143, 44,238,221,187, 23, 15, 61,244,144, 42,208,242,193, 28, 65,179, 44, 43, 1,128,175,126,180,225, -185,231,158, 67,235,113,109, 60,252, 3,254,129,171,242, 55, 98,196, 8, 10,120, 95,238,231, 86, 9,144,247,243,237,200,212, 1, -177,137,120,124,109, 13,128, 56,103, 27, 60,217, 18, 29,196,151,241,122,114, 25, 62,213,104,132,170,128,104, 88,233,207,211,242, -247, 60, 47,110,106,162,200,204,204,164,222,150, 77,249, 19, 2,240, 66,218, 65,131,135,188,160,174,255,247, 40, 7,236, 55,210, -210,210,192, 35, 97,145, 55, 26,115,247, 7, 26, 6,104,204,221, 31, 72, 24,192,189,188,172, 39,249, 52,117,174,177, 91, 37,132, -172,154, 48, 97,194,154,245,235,215,219,164, 82, 41, 44, 22, 11,236,118, 59, 88,150, 69,139, 22, 45,160,211,233,144,230,231,210, -179,212,212, 84,109,106,106, 42,217,185,115, 39,205,201,201, 65,118,118, 54,184,186, 0,183,115,229,185, 96, 99,247,238,221,116, -194,132, 9,216,186,117,107,179,201,223,147,228,242,157, 10,153, 79,111,220,243,207, 63,127,157,113,225,137, 23, 94,120,129,242, - 77,242, 84,171,163,124,202, 83,171,249,197,255, 21, 10, 87,233, 75, 74, 41,133,209,104, 68, 73, 73, 73,192, 49,255, 6,158,143, -215,107, 27,124,110, 14,249,127,248,225,135,193,234,179,108,238,183, 91,186,185, 87, 2, 12, 22,154, 82,200,214,173, 91,231,151, -245,175, 78,237, 90,242,241,105,180,205,200, 57, 7,119,238, 25,241,159, 76,186,123,222,189, 56, 83,170,192,153, 51,103,160, 82, -169, 32, 32, 8, 30, 0, 0,104,140,228,111, 71, 45,235,118, 91,255, 31,140, 37,126,127, 40, 34,201, 65,251, 93, 83,167, 78, 85, -249, 91,222,215, 7, 49, 80,119,133,198, 91,162,149,231, 57,158,132,107,159, 57,115, 38,217,177, 99,135,242,210,165, 75, 26,147, -201, 4,135,195,129,251,238,187, 79,149,148,148, 20,240,243, 30, 51,102, 12, 25, 51,102, 12, 55,195, 7, 20,154,185,209, 57, 0, -190, 62,243,177, 56,235,179,195, 27, 18,142,159, 69,102,184, 54,194,171,132,230, 35,237, 58,123, 48, 61, 61,157,166, 23,171, 65, - 26, 22, 2, 34, 0,112,230,204, 25,218,196, 88,245,217,232,163, 71,143, 38,126,140,125, 18,140,107, 0,160,170,170, 10, 10,133, -130, 18, 66,208,177, 99, 71, 16, 66, 72,183,110,221,208, 92,242,103, 30,211,129, 16,130,148, 71,156,171,138, 8, 33,174,229,126, -156, 59,255, 22,129, 29, 48,171,127, 80, 5,206,153, 51,135, 83,254,195,234,189,122,118, 56,221,255,172,219, 53,126,221,112, 70, -206,185,182,238,220,195,185,250,211,211,211,137,122,195, 61,135,103, 0, 0, 32, 0, 73, 68, 65, 84,151,134,158, 57,115, 70, 96, -243, 96, 43, 0,119, 10,130,177,214, 63, 88,132,125, 3, 20,155,160,254,174, 96,111,236,115,163,173,231,250, 24,191,215,255, 97, -181, 90, 33, 18,137, 32, 18,137,110, 98, 95, 91, 77,110,111,121,141,143,133, 89,179,102,249, 47,240,213, 63,246,177,200,206,206, -110, 48,105,167, 23,171,221, 45,111,237,221, 48,151,180,110,221,154,252, 49, 86,156,201,182,205, 37,127,231, 51,105,106, 43,160, -235,177,122,245, 79, 55, 77, 35,152, 55,114, 30,185,217,115,130,159,243, 70, 40,156, 57, 69, 54, 55,229,211, 21,231, 87,169, 84, - 68,176,252,125,195, 91,104,128, 36, 38, 38, 10, 5, 19, 4, 8, 16, 32, 64,128,128,255, 49, 48, 66, 19, 8, 16, 32, 64,128, 0, - 1,130, 2, 32, 64,128, 0, 1, 2, 4, 8, 16, 20, 0, 1, 2, 4, 8, 16, 32, 64,128,160, 0, 8, 16, 32, 64,128, 0, 1, 2, -238, 10, 52, 88, 5, 48,127,254,252,128,179, 65,189, 21,118, 17,228, 9,242, 4,121, 55, 79,222,146, 37, 75, 26,106,247, 12,227, - 90,230,232,190,212,140,171,166,232,190,244,204, 91,249,224,176,176, 48,200,229,114,215,247, 25,134,113,173,184,112,151,199,109, -204,196,178,206, 85, 94,220,102, 57,194,243,245, 71, 30, 81,138,196, 50, 80,214, 14,150,181,107, 3,145, 71, 41, 85, 29, 57,114, - 68,156,152,152,152, 15,143,170,123, 1,202, 83, 30, 57,114, 4,137,137,137, 90, 97,188,221,121,242,252, 86, 0,254, 23,241,242, -203, 5, 13, 26,238,141, 55, 6,146,219, 74, 94,193,203, 20, 0,222, 24,248, 6,113,127, 31,168, 60,174, 82,156, 90,173, 70, 70, - 70, 70, 83,215, 53,121,222, 93, 30,220,150,233,113,223,113,255,190, 90,173,118,157,227, 43,247,127, 17,140,181, 78, 89,254,219, - 1,140,136, 42,215,180,179, 95,198,105,218, 25,135,234,162, 85, 17, 9,131, 32, 13, 13,215,250,250,254,254,253,251, 49,108,216, - 48, 23,241,115,132, 77, 8,185,142,176, 89,150,117,189, 46, 94,188,232, 85,222, 47,191,252,130, 1, 3, 6, 64,161, 80, 64, 44, - 22, 67, 36, 18, 53,144,201,145,190,195,225,112,189, 44, 22, 11, 10, 11, 11,113,207, 61,247,220,141,143,136, 56,121,145, 42,127, -255,253,119,156, 57,115, 70,211,162, 69, 11, 12, 31, 62,188, 89, 99,156, 16, 70, 41,147, 71,163, 69,212,189,154, 58, 67,177,202, - 80,123, 89,233,175, 12,150,101,149, 57, 57, 57,187, 79,159, 62,141,173, 91,183, 66,161, 80, 96,209,162, 69, 34,184,173,189, 15, - 64,158,166,232,220, 89,236,220,177, 29, 82,153, 12,207, 61,183, 96, 20,165, 84, 35,140,212,187,212, 3,112, 39, 33, 39, 39,199, -167,198,147,154,154,234,115, 96,114, 4,237, 73,220,129, 34,216,242,130, 13,183,202,124,188, 38, 45, 62,165,101,249,202,171, 87, - 4,154, 85, 93,156,171, 42,232,254,255,239,248, 81, 72,169,242,196,254, 29,136, 56,255,163,198,104,180,192, 54,136,129, 34,158, -160,219,165,163,184, 63,156,106,116,229, 63,227,215,144,217,170, 10,210,174, 73, 37,224,196,137, 19, 16,137, 68, 24, 62,124, 56, -196, 98,177,235,197, 41, 4,156,213,111,183,219,225,112, 56, 96,179,217,112,241,226, 69,236,222,189,219,171, 60,163,209,136,195, -135, 15, 99,240,224,193,144, 74,165,144, 72, 36, 13,100,178, 44, 11,187,221, 14,187,221, 14,155,205, 6,147,201,132,195,135, 15, -195, 96, 48,220, 22,250, 84,125, 63, 99,240, 71, 33,154,128, 57,122,201,146, 37,172,199,220,130,218,218, 90,196,196,196, 4,180, - 0,125,201,146, 37, 13,126,207,231, 89,133, 80, 40, 90, 65, 36,146,106, 12,181,151,253,150, 89, 80, 80, 0,131,193,128,193,131, - 7, 95, 76, 78, 78,110, 83, 89, 89,137, 29, 59,118, 56,162,163,163,145,148,148,212,228, 24,153, 51,110,244,117,109,115,236,212, - 41,104,195, 67,176,112,197,191, 46,247,235,223,171,253,213, 43,101,216,145,167,221,221,169, 87,191,100,189,190,102,151, 64,157, -183, 63,184,210,191,238,240,172, 5, 32,110,106,146,229, 38, 87, 95,159,111, 5,249,255,245,175,127,109,242, 26,157, 78,135, 47, -191,252,146,242, 81, 2, 56,178,110,174,181,126, 35,228,185, 91,254,205,181,254,221, 72,152, 0,160,106,181,218,231,198, 49, 60, -201,154,112,196,206, 89,251,238,150,191, 59,213,241,237, 51,110,158, 10,234, 94, 78, 24, 0,170,170,156,149, 17,163,163,243,239, -138,129,122,225,167,124,220,115, 89,163,185,108,100, 49,249, 30, 17,238,141,181,131,141,166,144, 68,139, 80, 91, 41,133,162,214, -132, 30, 71, 86,105, 10, 19,230,169,140, 33, 29,181,141, 91,146, 4, 39, 79,158,132, 84, 42,197,168, 81,163, 92,164, 45,145, 72, -192, 48, 12, 40,165,176,217,108,176,219,237,176, 88, 44,184,124,249, 50, 52, 26, 77,163, 91, 42, 51, 12, 3,155,205,134, 35, 71, -142, 96,248,240,225, 80, 40, 20,144,201,100, 46,121,156, 2, 96,177, 88, 96, 48, 24,112,236,216, 49,152,205,102,191, 10, 51,105, -181, 90,165, 72, 36,210,212,214,214, 66, 42,149,162,172,172,236,169,201,147, 39,215,202,229,242,207, 3, 33,109,173, 86, 59, 85, - 36, 18,125,229, 38,239,244,228,201,147,127,151,203,229,169,112,238, 80,233,183, 37,252,202, 43,175,104,150, 46, 93, 90,134,250, - 29,103,150, 44, 89,130, 19, 39, 78,160, 85,171, 86,141,214, 93,247, 69,254, 31,207,157,139,241,253,250, 1, 0, 90, 63,253, 52, - 20, 33,113, 48,232, 47, 65, 95,115, 78, 69,169, 67,235,175,204, 62,125,250,160,172,172, 12,251,247,239,239,200, 48, 12,142, 29, - 59,134,232,232,104,236,221,187, 23, 86,171,213,103, 59, 86,190,185,176,193,231, 48,171, 13,109,237,102, 60,247,252,171,237, 87, -188,251, 79,188,243,238,135,104,199, 56,240,225,187,203,243, 71, 77,155, 33,176,235, 29, 72,254,220,113, 94,123, 1, 0,215,215, -255,246,245,249,102, 34,152, 59,245,221, 9,112, 87, 2,154,233, 1,224, 8,150, 0,160,159, 60,250,153, 87, 66,126, 98,211,108, -222,100, 93,239,218, 39, 94, 38,108,247,239,187, 20, 4, 62, 33, 0,238,127,123,254,245,244, 0,220,233, 48, 87, 87, 40, 71, 88, - 14,107,202, 68, 14,220, 19, 9,116,236, 64, 33,234, 35,133,184, 75, 23, 72, 45,102, 88,126,184, 12, 75,141, 24, 34, 86, 2,115, -254,231, 26,102,252,179, 42, 86,236, 61, 28,192,185,231,207,158, 61,139,168,168, 40,168, 84, 42,200,229,114, 72,165, 82,136,197, - 98,151,213,111, 54,155, 81, 82, 82,130, 61,123,246,128, 97, 24, 48, 12,131,166,228, 57, 28, 14, 28, 63,126, 28,195,134, 13, 67, - 68, 68, 4,228,114, 57, 68, 34, 17,236,118, 59,172, 86, 43,244,122, 61,126,254,249,103, 88, 44, 22,136,197, 98, 87, 46,128, 47, -124,241,197, 23, 74,131,193,160, 57,127,254, 60,244,122, 61,164, 82, 41, 90,183,110,189,106,223,190,125, 24, 50,100,136, 56, 52, - 52,244, 19,127,148,128, 47,190,248,226, 81,131,193,240,149,135,188,132,125,251,246, 37, 12, 25, 50,228,203,208,208,208, 84,190, -242, 88,150, 85, 90,173, 86, 84, 85, 85,105,220, 60, 10, 0,128,165, 75,151, 22, 47, 89,178,164, 93,106,106,234, 40,185, 92,238, -215,252,199,136,164, 74,207, 99,215, 62,248, 0,173, 39,197,227,157,119,222, 87,217,108,117, 1,205,167,251,247,239,215,252,244, -211, 79,120,241,197, 23,245, 34,145, 40, 66, 46,151, 99,200,144, 33,208,104, 52,200,203,203, 67,187,118,237,252,240,119, 16,124, -113,246, 42,190, 62, 83,140,220,111, 63,133, 72, 68,176,240,233,199,217,190,173, 91, 50,153,207,189,138,181,254,202, 19,112, 75, -200,223, 83, 57,245,166, 20, 4,188, 10,224, 86,111,111,219,165, 75, 23,149,175,215,205,182,214,111,132,188, 96, 88,253,141,225, -147, 71, 63, 35, 79,108,154, 77,189,145, 63,248,135, 8, 26, 88,250, 85, 85,201, 46, 11, 29,127,108, 1,234,183,219,191, 41,162, -143,142,206, 15,200,250,183,219,237,202,159,127,254,153, 54,118,204,243, 92, 99,112,191,222,110,183, 43, 61,207,121, 30,107, 10, - 85,199,127,209,148, 20,235,209, 42, 92,140, 46,225, 20,226,150, 44,196, 15, 60,136,208,190,159, 67,209,255, 61,200, 34, 21,144, - 26, 76, 48, 26, 29,232, 32, 50, 98,239,250,198,149, 39,134, 97, 32, 22,139, 33,145, 72,112,230,204, 25, 28, 59,118, 12, 17, 17, - 17,136,137,137, 65, 76, 76, 12, 90,182,108,137, 22, 45, 90,160,166,166, 6,123,247,238,133, 72, 36,114,197,246,189,129, 59, 47, -149, 74,225,112, 56,112,250,244,105,132,132,132,160,101,203,150,104,213,170, 21, 98, 99, 99, 17, 22, 22,134,211,167, 79,195,102, -179,185, 66, 4,141, 41, 20,158,150,127,105,105,169,230,220,185,115,232,220,185, 51,198,141, 27,135,129, 3, 7,194,104, 52, 98, -247,238,221, 56,114,228,200, 71,102,179,153,119,237, 98,173, 86,171, 42, 45, 43,255,166,232,106, 13,194,239, 25,140,132,113,127, - 66,187,129, 41,208, 89, 24,236,204,223,133, 35, 71,142, 76, 54,155,205,127,225, 75,254,122,189, 30, 71,143, 30,213,236,223,191, - 31,125,250,244,193,146, 37, 75, 90,162, 62,158,190,100,201,146,118, 0,224, 15,249, 51, 34,169, 50, 52,172,173, 50, 58,166,151, -102,253,134,163,152,251,241,199,200, 59,124, 24,121,135, 15,163,245,211, 79, 3, 0,108,182,186, 61,129,140,227,188,188, 60,154, -155,155,139, 41, 83,166, 92, 12, 15, 15,103, 66, 66, 66, 10, 11, 10, 10,176,127,255,126, 84, 84, 84, 32, 33, 33,193, 47,121,239, - 31, 62,131,119, 15,254,134,181,239,190,116, 84, 44, 50,129,113,212,226,237,149, 31, 51, 95,237, 45, 68, 9, 35,198,189,247,222, - 43,176,236, 93, 2, 38, 80,130,191,133,155, 87,220, 24, 11,251,229, 2, 26,204,184,125,176,229,221, 72, 69,224,137, 77,179,169, -251,171, 49,175,128, 47,175,194,117,228,214, 80, 25,240,215, 83, 65, 26, 59,238,233, 21,224,131,218,218, 90,229,174, 93,187, 52, - 5, 5, 5,141, 30,115, 63,215, 20,220,175,223,181,107,151,166,182,182, 86,233,126,206,243, 88, 83,136, 48, 87, 34,239,146, 25, -219,206,179,184,172, 35, 40, 45, 7, 24,113, 36, 24, 18, 3, 98,150,161,174,148,224,232, 37, 22,199, 46,153, 81, 89,107, 67,239, -104,153,134,143, 2, 32,147,201,112,238,220, 57,156, 58,117, 10,209,209,209,136,138,138, 66, 84, 84, 20,140, 70, 35,246,239,223, - 15,137, 68, 2,169, 84,218,228, 94, 10,156,119,128, 83, 2, 40,165, 40, 42, 42, 66,116,116, 52,226,227,227, 17, 27, 27,139,162, -162, 34, 56, 28, 14,200,100, 50, 72,165,210, 6, 43, 15,188, 77, 43,220,155,242,242,114,205,149, 43, 87,208,179,103, 79, 60,248, -224,131,152, 56,113,162,106,226,196,137,170,225,195,135,195,225,112,224,199, 31,127, 68, 81, 81,209, 96, 0,188,226, 9,229,229, -229,187, 75,171,106, 16,221,181, 47, 18,146,231,160,231,132,249,232, 49, 97, 30, 58, 62,240, 40,172, 84,196,201,227,245,124,235, -115, 31, 52,103,206,156,225,238, 85, 85, 79,252,204,146, 37, 75,176,116,233, 82, 44, 93,186,244,148,103, 94, 64, 99, 16,137,229, -202,168,232, 30,154,214,237,134,105,162, 98,122,128, 48, 98,124,244,137, 6,115, 63,254, 24,115, 63,254, 24, 75,151, 46, 69,121, -121, 57,248,202,243,176,252,233,150, 45, 91, 48,100,200, 16,244,239,223,191, 35, 0,249,174, 93,187, 6, 92,184,112, 1,199,143, - 31,135,201,100,194,132, 9, 19, 70,241,149,151,245,251,101,188,247,243, 41,172,121,227,249,170,248,123, 59,246, 49, 26,116,200, -250,102, 23,142, 30,251, 29,123,191,219,137,154,107,165,152, 48, 97,124, 50, 4,220,182, 72, 76, 76,108,212,250,231,149, 3,144, -145,145, 65,242,243,243,149,124, 63,223,201, 8,166,165,126, 35,228, 1,193,115,255, 55,106,133,186,197,212,253, 37,127,206, 11, -224,110,157, 7, 3,190,146, 15,253,129, 86,171, 85,150,148,148,104,184,205, 93, 26, 59, 22, 8,206,158, 61,139,202,202, 74, 77, -219,182,109, 85, 74,165, 82,219,216,177, 70,137,171,226, 50, 14, 92, 53, 97, 66, 72, 8,246, 93,102,209,182,191, 12,157, 45,133, -208,157,248, 43, 54,189,125, 20,236,133, 26, 24,172, 20,197,181, 14, 40,196, 12,236, 53,215, 16,217,132,210,238,174, 4,200,229, -114, 92,188,120, 17,167, 78,157, 66,207,158, 61,161,211,233,112,240,224, 65, 87, 44,223, 87,188,158, 16,226,242, 2,112,242, 40, -165,184,124,249, 50,122,247,238,141,252,252,124,176, 44, 11,185, 92, 14,137, 68,226, 90, 37,192,199, 3,112,233,210, 37,152,205, -102, 12, 24, 48, 0,241,241,241, 42,145, 72,132,136,136, 8, 12, 26, 52, 72,117,240,224, 65,205,165, 75,151,160,215,235,143,129, -167,203,254,210,165, 75, 96, 25, 41,218, 37, 38,163, 69,124, 2, 24,145, 4,138,136, 88,116, 24, 52, 1, 23, 15,230,162, 94,222, - 5, 95,114, 40,165,202,234,234,106, 77,113,113, 49, 58,116,232,128,161, 67,135,170, 68, 34,145,118,216,176, 97,100,201,146, 37, -116,240,224,193,246,250,121, 51, 33, 50, 50, 18,245, 10,138,163, 41,153,114,121, 12, 98, 98,251,194,106,169, 65, 69,229, 97, 88, - 44,186,209, 54,155, 97, 32,128, 55, 7, 15, 30, 12, 0, 40,189,118, 13,245,242, 36,112,219,244,166, 41,252,242,203, 47,169,235, -215,175,199,204,153, 51, 49,108,216, 48, 0, 96,119,236,216, 33,206,203,203,195,220,185,115,199,246,233,211,103,167, 63,125,249, -180,222,136,197,123,126,197, 91,127, 83, 99,248,196,228,232, 58, 67, 5, 54,126,179, 7, 25, 31,125,141,109, 11,231,160, 75,217, - 21, 44,211, 95, 67,116,116,140,144, 4,120,135,192,221,237,239, 45, 95,165,209, 28, 0,207,216,190,175,207,119, 35,130,189, 4, - 47, 80,188,126,255,235, 42, 66,200,109,217,222, 30, 75,253, 26,228, 1,120, 42, 3,193, 92,254,199, 87, 57,200,205,205, 85,150, -150,150,106,172, 86,107,147,199,154, 3,157, 78,135,186,186, 58,141, 94,175, 87,121, 59,150,146,146,210,232,179, 59, 82,101, 66, -141,149,197,145,114, 59, 74,170,237,136, 59, 40, 70,159,141,103,113,241,194,113,252,254,147, 21,118,177, 8, 86, 22, 48, 91, 41, -116,148, 69,108, 20,109,146,176,221,151,255,113, 25,251,165,165,165,232,216,177, 35, 46, 92,184,224,114,249,139,197, 98,215,245, -254,134,243,220,107, 8,112,127,111, 80, 72,176, 26,205,203,222,191,206, 24,247,117, 1,203,178,168,171,171,115, 78,142, 98,177, - 74, 36, 18,105, 61, 60, 73,226,220,220, 92,164,164,164, 48,139, 23, 47, 46, 93,182,108,153,125,241,226,197, 77,222, 60, 33, 78, -133,200,100, 44,133,161,246,178,202,225, 48,107, 1,236, 5,240,102,109,109, 45,114,115,115, 93,202,228, 61,247,220, 99,245, 37, -175,190,127,165,228,228,228,100, 79,152, 48,193, 69,254, 63,252,240, 3,179,121,243,102, 40,149,202,137,254,146,255, 85,163, 5, -143,231, 29,196,115, 83, 39, 32,245,241, 41, 48,154,245,216,148,171,197,202, 15,179,240,217,216,251,209,165,236,138,192,166,119, -129, 50,224,169, 4,220,148, 74,128,106,181,154,186,199,116,125,125, 22,112,221,196,126, 67,201, 63,208,152, 58, 71,252,158,217, -254, 30,174,127, 82,255,242,122,109, 99,253,197, 87,191,224,219, 95, 82, 82, 82,180,221,186,117, 83, 69, 69, 69, 53,121,172, 57, -136,138,138, 66,183,110,221, 26, 16,189,183, 99,222, 96,114, 68,192, 70,128, 67, 21, 22,148, 57, 28,216, 85,100,198,198,108, 51, -118, 95,137,197, 89,105, 36,174,212,216,112,185,150, 69,157, 29, 48,218, 41,100, 49,173,125, 18, 51,183,190,223,225,112,192,110, -183, 35, 38, 38, 6, 97, 97, 97,232,216,177, 35,108, 54,155,235,184,183,130, 64,158,242,184,245,253,118,187, 29, 38,147, 9,148, - 82,180,111,223, 30,197,197,197,104,211,166, 13,196, 98, 49, 44, 22, 11,172, 86,171,235,255,242, 9, 15,118,232,208, 1,114,185, - 28,133,133,133,184,114,229,138,198,225,112, 64,175,215,147,159,126,250, 73, 99, 48, 24,208,161, 67, 7, 68, 68, 68, 60,200,119, -142,234,208,161, 3, 24,214,138,226,195,249,168,190,114, 26,172,195, 6,147,190, 28,151,126,250, 14,214, 58, 29, 39,175, 19, 31, -229,134, 67, 76, 76,140,134,101, 89,151,167,115,233,210,165,228,248,241,227,168, 39,109, 22, 64,156,183,130, 71,158,176,219, 77, -176,219, 12, 80,132,182,134, 92, 17, 13,128, 40, 1,216,151, 46, 93, 26,227, 38, 15,107,215,174,229, 10, 40,121,189,231,202,202, - 74,250,217,103,159,209,140,140, 12,250,175,127,253,235,219,148,148, 20, 76,156, 56,145,243, 6,232,183,108,217,130,212,212,212, -148,169, 83,167,126,199,167,205, 42, 43, 43,233,231,159,127, 78,167,253,245, 41,140,202,217,131,191,205,158,140,103, 94,152, 15, -179,213,128,243,231, 46, 35, 35, 99, 35, 54, 63, 60, 4,202,246,173, 2, 30, 27,155, 55,111, 22,230,245, 91, 8,207,112,128,103, - 34,224, 77, 45, 5,236, 25, 54,240,245,249,166, 89,250,141,196,234, 61,173,125,190,214,127, 99,242, 10, 94,126,153, 22,188,252, -135, 59,223,243,179, 47, 79, 68,176,228,185,131,115,249,127,242,232,103, 36, 16,247,127, 70, 70,134,203,178,111, 44,222,207, 29, -119,191,214, 23,124,229, 15,248, 19, 30, 80, 42,149,218,135, 31,126, 88,229, 94,156,198,219,177, 64,112,207, 61,247,224,225,135, - 31,110,224,234,247,118,172,209,239,119,187, 7,221, 66, 69, 8, 39,128,141, 82,156,212, 89,177,254,172, 5, 95, 30, 40,193,207, -231,170, 80, 98, 2, 42,205, 14,156, 51, 80, 92,181, 80, 24,172, 54, 85, 83,228,197, 45,205,179, 90,173, 48,153, 76,104,211,166, - 13,122,245,234, 85,175,232, 69, 99,224,192,129, 46,194,230, 72,187, 49,194,230, 8,221,102,179,193,106,181,130, 16,130,174, 93, -187,162,186,186, 26,151, 47, 95, 70, 85, 85, 21, 58,117,234, 4,134, 97, 96,181, 90, 97,177, 88, 92,223,241,133,216,216, 88, 85, -124,124, 60,142, 31, 63,142,239,191,255, 30, 91,183,110,213,108,221,186,117,247,190,125,251, 32, 18,137,240,192, 3, 15,160, 75, -151, 46, 38,240, 44,100, 19, 27, 27,155, 18, 23, 29,137,202,162, 95,241,251,206, 79,112,252,187,213, 56,249, 93, 6, 46,254,184, - 25, 50,134,229,228, 21,251,146, 35, 22,139,181,113,113,113,170,136,136, 8, 28, 57,114, 4, 87,174, 92,209, 24,141, 70,165,187, - 34, 80,239, 9, 96,214,175, 95,143,158, 61,123,250,252,109, 86, 75, 13,106,170,207, 66, 34, 9, 69,139,232,238,154,208,176,118, -144, 72, 66,149,132, 48,131,185,107,194,171,243,161,249,236, 25,140,233,110,224,148,230,235,240,221,119,223, 65,161, 80,160,103, -207,158,232,212,169, 19,234,195, 7,118,157, 78,103,200,201,201,105,145,152,152,152, 50,106,212,168, 45,124,251,110, 94,222,119, -136,136, 8,195,136,145,131,140,137,253,251,224,209,191,206,133,145,216, 81, 94, 86,133,121, 79,191,134,101, 73,247,160,127,171, -192,149,228,205,155, 55,211,183,223,126, 91, 80, 2,110, 19, 69,192, 27,110,155,189, 0,110,245,170,130, 64, 8,216, 95, 12,124, -195,169, 64,184, 19, 53,119,236,102,201,115,183,194,159,216, 52, 27, 79,108,154,221,224,189,251, 49,190, 22,187,187, 39,193,155, - 71,161,185,121, 1,238,158, 0,207,191,124, 17, 30, 30,174, 29, 61,122,180,106,224,192,129,141, 30,115, 63,215,100,187,187, 93, - 63,122,244,104, 85,120,248, 31,203,242,188, 29,107,210, 58,148,133,170,122,183,105,137,161, 49, 50,220, 31, 37, 69, 91, 57, 3, - 25,165,144, 91,236,232, 16, 38,134,142, 82,252,102,176,227,116,157, 29,237, 90,197,160,211,253, 35, 27,149,197, 89,253,220, 82, -191, 14, 29, 58,160,111,223,190,208,233,116,168,174,174, 70,117,117, 53,194,195,195, 49,120,240, 96, 88,173, 86, 87, 77,128,198, - 8,155, 83, 38,108, 54, 27, 8, 33, 72, 72, 72,128,201,100, 66,121,121, 57,202,202,202, 80, 94, 94,142,186,186, 58, 36, 36, 36, - 64, 44, 22,187,228, 53, 86, 87,192, 83, 41,139,139,139, 83,117,237,218, 21,231,207,159,199,246,237,219, 81, 80, 80,128,144,144, - 16,140, 26, 53, 10,125,251,246,253, 78, 46,151, 47, 4,207, 16,128, 82,169,220, 18,215, 42,118, 86,215, 54, 45, 96, 56,247, 19, - 78,111,255, 8,197, 5,223, 34, 74,230, 64,242,232, 81,232,219,183,239, 28,185, 92,158,203, 71, 86, 68, 68, 4,250,247,239, 15, - 74, 41, 14, 28, 56,128,194,194, 66, 77,113,113,177,166,170,170, 74,185,100,201, 18, 21, 87, 57, 49, 41, 41, 9,123,247,238,245, - 41,143,101,109,218, 26,221, 89, 85, 85,249, 49,200,228,209,104,221,246, 1, 77,108,235,129,154,240,136, 78,223,189,243,238,191, - 31,230,228,125,249,108, 8, 54,252, 96, 65, 99, 74,207,233,211,167,209,178,101, 75, 12, 27, 54,140,189,255,254,251, 97, 52, 26, - 81, 87, 87,135, 85,171, 86,133,117,239,222,125,210,180,105,211,182,248, 51, 38,126,255,253, 52, 58,118,136,199,180,105, 41, 33, -175,188,252, 28, 42,107,107, 80, 81, 89,129,244,103, 94,195,107,143,142,198,232, 14,113,205, 34,255,149, 43, 87,162, 87,175, 94, -248,224,131, 15, 4, 37,224, 38,226,215, 95,127,109,180, 14,192,117, 10,239,237, 66,240,254,172, 42, 72, 77, 77, 37,193,170, 4, -232, 11,158,133,120,130,161, 4, 4,131,252, 3,149,215, 88,169, 94, 79,203,220,159,146,189, 30, 74,130,171, 40, 80,115,238,203, - 93,105,112,183,246, 3, 89, 1,224,110,221,221,127,255,253,164,177, 99,158,231, 26, 67, 83,215,243,149,193,225, 1,229, 40,109, -145,152,194, 94,144,135, 11, 53, 64, 24,145,160, 99, 24,131, 98, 7,129, 72, 38,198,222, 50, 7,204, 44, 16, 43, 19,161,107,210, - 8,200,187, 37,105,155, 82, 0,108, 54, 27, 68, 34, 17, 58,119,238,140,254,253,251, 67,175,215,195,108, 54,187,214,231, 91,173, - 86, 68, 71, 71, 99,216,176, 97,216,178,101,139, 43, 36,224, 13, 14,135,195,149,213,223,163, 71, 15,212,187,233, 97, 54,155, 93, -227,153,243, 36,244,232,209, 3, 85, 85, 85, 48, 24, 12, 77,141,229, 6, 39,102,205,154,165,213,106,181,163,122,246,236,185,219, -173,112, 79,245,240,225,195,119,203,229,242,153, 0,204,254,180,229,172, 89,179,214,107,181, 90,125,207,158, 61,115,221,228, 85, - 12, 31, 62,124,149, 92, 46,255,148,175, 28,134, 97,180,109,219,182, 85,141, 27, 55, 14,231,207,159,215,156, 58,117, 10,151, 46, - 93, 66,120,120,184,166, 69,139, 22, 24, 51,102, 12,254,251,223,255, 34, 41, 41,137,247,111,179,219,141,218,106,221,239, 42,179, -185, 10, 45,162, 18, 52, 97,225,237, 17, 30,209, 1,117,181,197, 91,222, 90,246, 17,166, 79, 75,198,151,207,134,120,109, 39, 14, -227,199,143, 71, 94, 94, 30,174, 92,185,194, 84, 85, 85,193,108, 54, 99,239,222,189,226,122,165, 83,239,239,120,152, 48, 97, 60, - 54,109,218, 2,125,117, 37,174,148, 92,197,179, 79,206,182, 62,255,226, 82,233,163,163,134, 96,152, 69, 15, 72, 2,163,135,205, -155, 55,211,127,252,227, 31,174,114,208, 93,187,118,197,219,111,191,141, 23, 94,120,129, 78,154, 52,233,206,175,220,121,135, 42, - 5,183, 76, 1,184, 17,171, 10,130, 65,238, 28, 42, 42, 62,194,203, 5,223, 54, 89,109,207,159,228,191,138,138,143, 80,240,242, - 31,242,220,137,217,211,101,207,135,180, 43, 62,170, 64,193,183, 47, 7, 77, 94, 48,193,199, 67,192,237, 1,224, 79,127,249, 95, - 26,156,157,134,168, 84, 71, 45,118, 77,249,238, 93,144,216, 77, 56, 90, 75,145, 95,107,135,148, 16,196, 80, 10, 85,155, 22,136, -106, 29,171,138, 31,164,244, 97,105, 58, 61, 0,157, 58,117,194,192,129, 3, 97, 50,153, 96,179,217, 32,149, 74, 93,132,205, 89, -233,177,177,177, 24, 58,116, 40,182,111,223,222,164, 7, 64, 44, 22,163,111,223,190, 32,132,192,104, 52,186,188, 11,156,210,206, - 85, 23,100, 89, 22,189,123,247,198,193,131, 7,225, 79,114,165, 82,169,212,224,143, 60,145, 48, 56,171,237, 93, 2,207, 76,120, -111,158, 0, 55, 89,209, 0,170, 0,248, 93,155,152, 97, 24,109,139, 22, 45,208,187,119,111,149, 68, 34,225,150, 63,106, 0,160, -184,184, 24, 15, 61,244, 16,150, 47, 95,238,151, 76,135,195,162,173, 51, 20, 43,173,214, 26,149, 66,127, 65, 19,209,162, 43, 66, -194,218, 34, 36,172, 45,118,236, 42, 5, 25,221,180,197, 61,100,200, 16, 34,149, 74,105, 85, 85, 21,198,143, 31,111,141,137,137, -145,178, 44,139, 75,151, 46, 1, 1, 36, 75, 62,240,192, 16, 34,147,201,104,196,137, 66, 60,249,228,159, 16,159,208, 77,250,246, -115,127, 98,215,125,248, 41,179, 74,100, 14,168, 47,111,222,188,153, 46, 94,188, 24, 45, 90,180, 64, 73, 73, 9, 20, 10, 5, 88, -150, 69,104,104, 40,222,120,227, 13,188,252,242,203,130, 18,112,131,145,152,152,216,168, 23,128,215, 50,192, 27,129,219,121, 85, - 65, 83,132, 19,136,245,223,152, 60, 79, 75,157,115,221,251, 34,237, 96,203,115,247, 4, 4,122,190, 41,175,130,231,230, 63,254, -202,251, 95, 3,195, 48,218,196,209,227, 72, 85,157, 73, 25,105,183,104, 68, 23,139,112,143,237, 42,194, 99,226, 48,164,119,119, -196,180,107,169,138, 76, 28,233,115,124, 80, 74,209,185,115,103, 12, 27, 54,204, 21,143, 23,137, 68,176, 88, 44,174,210,189,238, - 97,130,246,237,219, 99,232,208,161,208,106,189,139, 86, 40, 20, 72, 76, 76,132, 88, 44,134,213,106,117,125,207,125,233,160,251, - 70, 64, 12,195,160, 95,191,126, 40, 44, 44, 12,164, 25, 40,128,218,250, 87, 48, 96, 8,132,248,189,121,141,122,245,234,197,229, - 81, 16,150,101,149, 70,163, 17, 22,139, 5,221,187,119,199,138, 21, 43,252,220, 28,135,106,109,214, 90,216,172, 6,149,201, 84, - 14,153, 44, 10, 18,105,184,134, 97,196,248, 98,253,119,170, 89, 51, 39, 52, 41,175,190,174, 63,121,239,189,247, 88,147,201, 4, - 0, 72, 72, 72,240,171,252,178, 59,250,247, 31, 64, 68,247,223,255,208,220,127,188,151,231,148, 71,153,132,132,123,145, 48,105, -210, 44,177, 88,188, 62, 16,153,203,150, 45, 19, 6,245,109,162, 4, 52, 69,254, 55, 85, 1,184, 83, 17,204,101,127,158,196,220, - 92,107, 61, 88,242,154, 99,113,187, 19, 59,247,222,195,101, 47,116, 34,158, 24,149, 50, 73, 91,111,189, 98, 68, 0,223, 79, 75, - 75, 67, 84, 84,148, 43,195,159,101, 89,151, 11,159,243, 0,112, 73,127,220,142,128, 93,187,118, 5, 33, 4, 27, 54,108,184, 78, -222,202,149, 43,145,157,157,237,186,214,225,112,248,220, 14, 88, 42,149, 34, 41, 41, 9,124,178,227,239, 84,101, 45, 44, 44, 12, - 97, 97, 97,136,137,137,105,198,216,225, 20,129, 90, 48,140, 24,206,116, 44, 86,195, 83, 30, 93,180,104, 17,169,127,158,148, 97, -152,102,205, 35, 14, 7,187,109,193,130, 5, 4, 0,195,178,172,131, 97, 24, 5,252, 12,191,112, 16,172,251,219, 75, 9,240, 5, -146,152,152, 40, 36,103, 8, 16, 32, 64,128, 0, 1,255, 99, 96,132, 38, 16, 32, 64,128, 0, 1, 2, 4, 5, 64,128, 0, 1, 2, - 4, 8, 16, 32, 40, 0, 2, 4, 8, 16, 32, 64,128, 0, 65, 1, 16, 32, 64,128, 0, 1, 2, 4,220, 21,104,176, 10, 96,254,252, -249, 1,103,112,174, 94,189,250,186,100, 66, 65,158, 32, 79,144,119,247,201, 83,171,213,244,145, 73,106,124,187, 57, 3, 25, 25, - 25, 12,188,172, 65, 23,218, 79,144,247,198, 27,111,184,174,121,249,229,151,137,208,126, 55, 87,158,223, 10, 0, 55,184, 27,187, - 56,144, 37, 47,119,178,188, 64,100,222,238,247,235, 5, 82, 0, 17, 0, 66,234,251, 3, 11,160, 2, 65, 88, 67, 29, 76,112,237, - 16,140,123,246,214,166,183,170,248, 80,109,237,255,111,239,202,195,154,184,214,247, 59, 73, 8, 1, 65, 22, 17, 17,149, 42, 32, -138,184, 32,238, 90,149, 88,144,130,128, 91,209,254,106,123,107, 55,162,183,215,122, 91, 84,172,116,177, 11,173,120,181,155,183, -173,161,183, 85,219,122,111, 43,181,130, 59,149, 26, 92,170, 86,197, 21,180, 42,224, 86, 65,169,202, 78, 66,150, 57,191, 63,194, - 96, 8, 89,102,146, 32,216,206,251, 60, 60, 9, 39,147, 47, 51,231,204,156,247,253,190,115,206,119,106, 35, 15, 29, 58,164,216, -183,111, 31, 0, 96,226,196,137, 24, 59,118, 44,235, 84,194,237,209, 14, 83,167,201, 16, 23, 27,161, 5,100, 34,153, 76, 70,255, -213, 18, 55,241,176,142,244,244,116,146,144, 16,212,226,127,107, 34,128, 71, 59, 71, 0, 24,144, 77,173, 55,128,160,102,217,190, -111,186,169, 14,194,158,221,255, 28,109,207,212,245,218,115,205, 29,253,122, 25,226, 47, 58,115, 96, 93, 81,209,233, 71,252,122, - 4,117,171,174,214,192,195,195, 9, 55,111,148,208, 97, 97, 67,238,134, 13, 30, 63, 18,192,101, 46, 6, 79, 28,254,140,148,150, - 92, 68,201, 21, 21,174,151, 19,244,234, 78, 33,168,183, 4,129, 65, 33,136, 24,243,247, 14,241,240,155, 18, 18,204, 94, 3,237, - 65,100,103,207,158, 85,132,135,239,198,218,181, 13,200,207, 7,222,124,243, 39, 92,191,126, 93,225,231,231, 7,137, 68,130,178, -178, 50,233,244,233,211,225, 8, 65,112,224,192, 1, 82, 93, 93, 45,141,142,142,134,179,179,179, 45,246, 4, 0, 16, 23, 27, 65, - 39, 39, 39,139,128, 76,228,100,235, 31, 21, 56,118,219, 94, 30,127, 2,168,213,169,200,205, 77, 70, 76, 76, 38, 18, 18, 50,154, - 35, 2,188, 16,184, 63,224, 19, 1,113,128, 33,217, 83, 20, 64,127,239,245,167,189, 86,141,186,254,169,220,221,223, 47, 11, 14, -238,219,127,198,180,137,232,213,163, 51, 60, 61,156, 81, 89,165,194,141,242, 94,130, 75,165,149, 62,219,183,126,165,136,121,116, -246,106, 39,113,167, 53,214,236,157, 59,187, 47,242,242,197,237, 10, 33,106, 48,123, 10, 48,110, 24, 16,244, 16, 80,124,133,224, -224,113, 37,118, 42, 78, 99,199,230,197,164, 79, 72,188,116,192, 32,235, 25,237,218, 42,218, 97, 46,138, 32,151,203,169,246, 18, - 1,119,239,222,197, 75, 47, 53,160,107, 87, 32, 41, 9, 88,177,162, 14, 39, 79,158,132, 86,171,133, 68, 34,129,175,175,175, 98, -251,246,237,232,219,183,175,116,248,240,225,249, 28, 59,128,200,194,194, 66,116,235,214, 77, 17, 29, 29, 77,125,251,237,183, 0, -160,200,203,203,195, 19, 79, 60,129,145, 35, 71,114,189, 86, 49, 0,236,220,117, 66, 0,100,210,250, 87,189,134,230,123, 16, 30, -134,222, 62, 0,204,156,185, 25,185,185,250,215,228,228, 18, 48, 17, 1, 62, 26,112,127,137,223,176,188,221, 82, 1,119,116,144, - 77, 94,205, 34,224,207, 76,254, 0, 68,123,114, 55,189, 38,157, 16, 17, 50, 98,104,119, 80,148, 62,171, 27, 77, 19,116,118,115, - 70,167, 32, 49,122,247,242, 64, 15, 63,183,135,246,228,110,122, 45, 46,225,153, 44, 0, 55, 45, 25,188,124,113,187, 98,252,176, - 26,252,243, 25, 64, 40,212, 11, 40,141, 22,232,228, 10,132, 6, 3,163,195,129,237,138, 26, 28, 57,189, 93, 49, 96,208, 68,155, - 30,124, 71, 13, 1,152,251, 62, 35, 2,238,119, 99,120,123,123, 99,251,118, 23,244,234,165, 68,126, 62, 80, 89, 41, 66,112,112, - 48,130,131,131, 81, 87, 87,135,210,210, 82,228,231,231,163,166,166, 70,209,175, 95, 63,214, 67, 3, 63,254,248, 99,164, 82,169, - 84,136,197, 98, 84, 86,182,140,100, 41,149, 74,124,249,229,151, 40, 45, 45, 37,143, 63,254, 56,151,250,164, 1, 32, 39, 91, 14, - 64, 38,208,191,218,142, 99,199,142, 53,215, 55,179,137,146,169, 50, 54,247,133, 97,219,178, 45,179,234, 20, 16, 18,137, 11, 23, - 48,178,174, 78,209,229,198, 13,252,238,235,139, 19,157, 59, 75,157, 6, 12, 0,161,168,124, 91,175,153,235,134, 81,108,108,176, - 45,107,107,123,134,161,255,228,228, 92, 36, 36, 4, 53,191, 50, 72, 72, 8,226, 69,192,125,128, 49,217, 51,251, 3, 24,150,243, -171, 0,140, 31,250, 63,249,245, 21,157, 57,176, 34, 56, 56, 56,100,100, 68,247, 22,229, 2, 1, 5,177, 88, 8, 23,137, 8, 78, - 78, 2, 4,245,241, 66, 80, 80,176,111,209,153, 3,219, 45, 9,197, 19,135, 63, 35, 66,212,224,229,103, 1, 85, 35,112,249, 58, - 80, 89, 13, 84,213, 0,255,221, 10, 44, 88, 14, 44, 91, 5,140,141, 0, 4,164, 6, 39, 14,127,198,123,139, 6, 24, 52,104,144, - 52, 39, 39, 20,190,190,192, 19, 79,136,224,231, 55, 2, 19, 39, 78,148, 38, 36, 36, 80,241,241,241,210,152,152, 24,116,235,214, - 13, 39, 78,156,192,247,223,127,175,248,233,167,159, 34, 27, 27, 27, 35, 45,217,252,246,219,111, 35, 27, 27, 27, 21, 78, 78, 78, - 22,127, 91,161, 80, 96,211,166, 77,145,108, 72,118,255,254,253, 4,128, 90, 46,151,139,239,137,128,123,100,186,127,255,126,194, - 85, 64, 29, 61,122,180,249,207, 82,153, 45,162,142,109,153, 37,242, 15,252,237, 55,197,244, 83,167, 20,189, 46, 22, 67, 92, 83, -131,238, 23,127, 67,228,145,195,138,174,167, 79, 43, 64, 72,164, 45,237,125,244,232, 81, 28, 59,118,140, 20, 22, 22, 70,218,122, -207, 48, 54,216,148,177,181,103, 76,244,108,202,172,129, 33,125,230, 85,157, 16,204, 63,240,247,137,248,217,164, 1,126, 96, 35, - 0,109,233,169,145, 54, 60, 63, 71,133,152, 25,251,230,126,199,210,111, 20,157, 59, 29, 59,107,134,180,153,244, 77, 65,226, 44, - 66, 85,117, 35, 66,130,188,145,181, 69, 17, 20, 54,120,188,135, 57,123,165, 37, 23, 49,123,138,254,253,238,253,192,167,223, 0, -147,199, 3,113,145,192,111,197,192,201, 34, 2, 23, 9,133,161, 97, 64,204, 68,224,199,220,139,136, 24,227, 56,207,221,150,186, -107,163, 57, 21, 54,193,221,221, 61,191,174, 78, 63,223,242,137, 39,158,192,184,113,227, 40,195,207,238,222,189, 43, 13, 13, 21, - 41, 18, 19, 1,138, 58,142,138,138, 6,197,239,191, 7, 89, 10,255, 69, 82, 20,165, 96,187, 57, 76, 69, 69,133,194,154,238,157, - 51,103, 14, 54,110,220,136,141, 27, 55,146, 57,115,230,180,104,139,253,251,247,147,141, 27, 55, 54, 31,215, 81,250, 3,182,101, -230,208, 88, 88,136, 62, 5, 5, 80, 11, 4,112,162, 0, 45, 77, 64,107,116,160,181, 90,116, 61,176, 31,197,132,160,243,208,161, - 54, 19,184,171,171,171,226,248,241,227,210,185,115,231,230,219,106, 3, 64, 11,143,220, 84,153, 45,209, 5,123,201,223, 28,209, -231, 26, 69, 2,120,180, 63, 76, 10, 0,115,147,223,108, 33, 28,107,132,200,213,222,253, 30,163,181,101,198,184,165, 73,133,182, -216, 51,245, 29, 27, 39, 46,138,252,252,131, 6,248,251,185,129, 16,224,192,225,235,104, 80,234,119, 93,141, 24,226,135,174, 93, - 92,112,253, 70, 45, 93,124,185, 82, 32, 18, 9,208, 55,208, 11,254,254,193,158,208,111,209,106, 18, 37, 87, 84, 24, 55, 12,104, -212, 0,187,246, 1,138,195, 4,254,221, 40, 4, 6, 0,143, 60, 12,244, 15,162, 32, 18,234,183, 22, 31, 29, 14,252, 75,174, 98, - 85,223,134, 33,121, 54,239,217, 40, 94,195,177,126,195,122,119,228, 10, 3, 91,208,180,157, 43, 6, 15, 30, 44, 53,254, 76, 40, - 20, 42, 6, 12,168,192,178,101,122,121,250,222,123, 23,113,229, 74,152, 89, 91, 42,149,202,170,231,111,136, 43, 87,174, 88, 61, -102,194,132, 9,212,132, 9, 19,154,201,126,227,198,141,196, 88, 32, 76,152, 48,161, 93,234,174, 45,188,127, 0,232,123,251,142, - 66,173,209, 64, 32, 16,128, 8,133,160,105, 26, 26,154, 6,173,211, 65,167,163,209,179,188, 92, 81, 51,116,168,205,215,220,208, -208, 0, 0,138, 99,199,142,129,162, 40,206,243, 59,218, 66, 4, 56,202,243,207, 77,206, 69, 76,102, 12,102,110, 6,146,115,245, -239,115,147,115,155,197,129,120, 91, 49,207,188,247, 17,134,115, 2, 88,205, 1, 48,183, 10,192,214,213, 1,230, 60, 46, 91, 60, - 49, 75,162,193, 86,129, 98,233,186,141,191,203,214,139, 48, 55,169,208, 22,123,150,190,195,252, 14, 5,128,222,100,117,238, 2, -173,159,237,239, 12, 0,184, 94, 86, 3,165, 82, 11, 0, 8, 14,244, 66,215, 46, 46, 56, 93, 84, 33,184,112,233, 46, 36, 18, 33, -130,250,120,162,178, 90, 13, 0,102, 13, 95, 47, 39, 8,122, 72,255,251,143, 78, 0,194, 7, 80,112, 22, 3, 90,173, 62, 18,224, -233, 14,148, 94, 3, 98, 38, 0, 15,245,212, 31,223,158, 48, 36,125, 91,198,133, 59, 58, 42, 42, 42,218, 44,138,210, 68,242,205, - 30,127,123,147,191, 33, 50, 50, 50, 72,106,106, 42,101,235,231,198,112, 42, 41, 70,163, 70, 13, 74, 40,130,142, 16, 80, 0,180, - 58, 26, 26, 45, 13,162,211,129,186,116, 1, 64,156,221,231, 93, 88, 88, 8, 31, 31, 31, 69,117,117,181,212,195,195,195,102, 17, - 96,173,236,126,145,127, 90, 90, 26,149,158,158, 78,102,110,110, 41, 8, 0, 32, 38, 51, 6,226,109,197,216,182,173,164,121, 37, - 0, 51, 97,208,219,219,155,103,234,251, 76,254,102, 5, 64, 71,135, 37, 66,180,133, 96,237, 89,226,104,209,110, 27,175, 38,160, -102, 85,114,253, 13,202,195,195, 9,149, 85, 42,248,120,187, 34, 41,177, 63,180, 58, 26,206,206, 66, 8, 5, 2, 16, 66, 16, 63, - 57, 8, 83,162,131, 64, 81,192,157, 74, 37, 60, 60,156, 0,224,174, 57,131,189,186, 83, 40,185, 74,189,136,105, 47, 0, 0, 32, - 0, 73, 68, 65, 84,208, 63, 8,152, 52, 70,223,235,252, 86, 12, 12,238, 15,120,117, 6, 98, 35, 1,154, 6, 68, 66,224,226,101, -253,241,108,219,150,203,123, 91, 19, 97, 88, 19,164,109, 13,154,166, 35,123,244,232,129,146,146, 18,236,223,191, 95, 49,126,252, -120,169,155,155, 27, 4, 2, 65, 62, 0,232,116, 58,233,185,115,190,138,183,222,186, 1,138,162, 80, 81, 17,130,144,144,222,184, -120,241,162, 57,123, 38,203, 55,109,218,212, 58,138, 68, 8,102,207,158,205,233,154, 13, 69, 64, 71, 34,127, 71,136, 4, 67,220, -237,217, 3,226,223, 46,128, 56, 1, 98,154,232, 39,182,234,180, 80, 19, 29, 26,180, 90, 40,131,251, 59,228,220, 7, 14, 28, 8, -138,162,108, 34,127, 0, 24, 57,114, 36, 70,140, 24, 65, 29, 61,122,148, 88, 42,179,134,166,136, 65, 11,194, 55, 85,198, 5,201, -185,247,136, 31, 64, 43,207,159,153, 48,184,109, 91, 9,207,212,237, 64,254, 15,172, 0,104,107, 65,225, 40, 66, 32, 4, 16,204, -174,108, 51, 17,192,172, 92, 16,204,170,100,227,253, 3,128,232,230,141,146,219,215,111,244,244,241,241,118,197, 7,159, 31,195, -132,177,189, 16, 49,184, 27, 40, 39,170,121, 69, 64,211,214,241,184,126,163, 22, 55,111,148, 92, 6, 96,214,173, 12,234, 45,193, - 47, 5, 74,244, 15, 2,124,134, 1, 75,231, 3, 11,231, 2, 30,238,250,176,255, 91,159, 0,203, 23,234,143,253,165, 64,127,188, -173, 4,237, 40, 79,189, 35,229, 2, 56,119,238, 28, 36, 18,125,157,236,216,177, 3,215,174, 93, 83,244,235,215, 79, 58,105,210, - 36,212,214,214, 70,122,123,123, 43, 14, 30,212, 34, 63, 31, 24, 49, 98, 56, 2, 2, 2,164, 61,123,246, 4, 0,133, 41,123,157, - 58,117,130, 90,173,102,245,219, 90,173,246,129,127,118, 13,201,159,141, 16, 96, 43, 2, 74,186,250, 74,157,207,156, 81,208,132, -160,147, 64, 4,161,144,130,150,232,208,160,209,160, 86,173, 70,153,191,191,212,199,142,243,118,117,117, 5, 69, 81,210, 17, 35, - 70,228,219,106,131, 33,122,107,101,247, 91, 4,164,165,165, 81,201, 77,158,189, 49,249, 27,122,255, 60,218,151,252,121, 1,112, - 63, 60,188, 54, 94, 82,216, 44, 2,216, 9, 13,109, 88,216,144,178,226,203,149, 62, 67,194,124,177,116,225,104,172,255,223, 89, -184, 72, 68, 8, 31,232, 11,138,162, 12, 60, 73,130,226,203,149, 8, 11, 27, 82, 8,160,214,156,193,192,160, 16,236,216,123, 26, -115,103, 2,164, 20, 24, 61, 3, 8,236, 5,108,204, 49, 56,104, 33,160,211, 1, 59,246,234,143,111, 47, 88,138, 20,181,215, 50, -192,187,119,239, 42, 66, 67, 47, 99,221, 58, 0,208,225,237,183,207,224,228,201, 6, 69, 67, 67, 3,106,107,107, 81, 90, 90,138, - 91,183,110, 33, 34, 34, 2,179,103,207,182,186, 12,144, 16, 34,165,105, 90, 33, 16, 88, 95,224,195, 8, 15,174, 96,134, 0, 54, -110,220,136, 9, 19, 38,180,235,243,149,154,154, 74, 49,196,111,109, 8,192,218, 49,134,240, 26, 58, 20,119,212,106,232, 20,249, - 80,139,157,224, 70, 68, 80,209, 52,170,213,106,212, 78,122, 4, 62,195,134,217, 24, 21,164, 48, 98,196, 8,155,199,253, 13,109, - 24, 18,189,169, 50,123, 68,192,177, 99,199, 44,150,177,129, 41,242,103, 60,127, 0,252,132,192,118, 38,127, 94, 0, 60,224,104, - 30,255,103, 63, 12,160, 11, 27, 60,126,210,246,173, 95, 29,252,181,192,189,255,168, 97,254,136,141, 10,196,238,159, 75,177,227, - 39,253,195,249, 90,202, 88,208, 52,193,175, 5,101, 40, 41, 41,190, 26,159,248,236, 63, 0,104,204, 25,140, 24,243,119,106,199, -230,197,228,195,175,244, 75, 1,215,190,171, 95,250, 23, 53, 78,191, 20,240,195,215,245,228,255,225, 87,128, 14,157,109,206, 8, -104,175,103,110, 45,130,208, 94,171, 0,234,235,235, 49,116,168, 10, 35, 70,232,255, 31, 62,156, 96,247,238, 82, 92,188,120,145, - 73, 4,132,200,200, 72,244,237,219,151, 85, 14,128,201,147, 39,231,103,103,103, 91,141, 2,104,181, 90,120,122,122, 74,185,158, -111,211,114,192,230,149, 1,251,247,239, 39,182, 14, 3,140, 28, 57,146, 85, 25, 23, 17, 96,237, 56,214, 70, 5,130,124,245,168, - 81,210,243, 78, 78,232, 85, 94,174,112,187,118, 13,170, 62,125,112,197,215, 87,234, 29, 17, 1, 52, 13,209,216, 64,176,142, 32, -233, 86, 54, 76,149,177,173, 75,227,227, 24,194,183, 86,102, 11,140, 73,159,137, 8,216, 59,132,199,163, 53,216, 76,140,230, 5, - 64, 27,122,230, 29,244, 55,238,196, 60, 58,251,163,220,221,223, 47,254,189,188, 54, 40,184,143, 23,166, 76, 14,130,151,167, 4, -149, 85, 42,156, 60,123, 11,197,151, 43, 81, 82, 82,124, 40,230,209,217, 63, 2,184,110,205, 96,159,144,120,233,129,130,237,138, - 67, 5, 53,152, 50, 9,248,226,125,125, 38,192,146,171,192,151,155,244,158,191, 14,157,209, 39, 36, 94,106,235,181,218, 51, 4, -192,150,252,219, 99, 14, 64,121,121,185,212,203,203, 71,113,252,248, 31, 0,128,139, 23, 59, 99,196,136, 1,232,210,165, 11, 36, - 18, 9,202,203,203,165,241,241,241,156, 82, 1,247,238,221, 91,122,225,194, 5,133, 97, 68,199,152,252,131,131,131, 49,114,228, - 72, 78, 36,198,172, 2, 48, 24,251,103, 38, 4,218, 36, 2, 76, 17,161,173,228,104,141,220, 57,145,191,129, 8,232, 50,124, 56, - 26, 0,170,161,169,200,222,169,106,246,146, 63,151,122, 99,251, 91,142,182,199,150,252,213, 9,193, 0, 63,254,127, 95, 34, 1, -230,132, 1,167,101,128,182, 78,150,227,186, 12,208, 86,123,182,218,116,244,249, 89,170, 39, 71,157,159, 61, 19, 23,157,196,157, -228,241,137,207,126, 87,116,230,192,103, 91,114,246, 5,250,245, 8, 26,109,176, 23,192,145,176,176, 33, 71,227, 19,159, 93, 6, -160,158,141,189, 1,131, 38,230, 15, 24, 52,145, 58,113,248, 51,242,253,142,139,120,239,211,142,183, 23, 64, 71, 36,127, 0,120, -252,241,199,113,250,244,105, 60,243,204,241,166, 8,192,112,204,154, 53, 68,234,234,234,154,111,171,205,240,240,240,252,240,240, -112,106,235,214,173,145,181,181,181, 10,161, 80, 8,129, 64, 0,173, 86, 11,177, 88, 12, 55, 55, 55,169, 3,200,223, 33, 34,128, -199,159, 19,105,105,105, 84,122,114, 58,241, 95,224, 47, 69,111,211,199,148, 37,231, 42,248,249, 0,237, 11, 17,219,142,210,209, - 29,111, 91,216,179,229,183, 30,228,235,181, 19,213, 97,131,199, 63, 25, 54,120, 60,147, 49,198, 13,128, 15,128,114, 0, 74, 52, -165,125,229,130,136, 49,127,167,108, 73,242,211,214,245,208,145,242, 74, 24,195,213,213, 53,127,204,152, 49,212,152, 49,142,175, -184,196,196,196,124, 56, 40,185, 37, 51,238,111, 76,242, 19, 38, 76,160, 54,110,220, 72, 58,194,124, 0, 30, 29, 79, 4, 88, 62, - 0, 60,249,183, 1,216,102, 1, 4, 0, 42, 60, 60,156, 31,123,225,193,131, 7, 15, 30, 60,254, 98,224,247, 2,224,193,131, 7, - 15, 30, 60,120, 1,192,131, 7, 15, 30, 60,120,240,224, 5, 0, 15, 30, 60,120,240,224,193,131, 23, 0, 60,120,240,224,193,131, - 7,143, 63, 7, 90,172, 2,152, 63,127,190,205,179, 50, 77, 37,114,224,237,181,141, 61, 54,155,216,180,167,189,188,188,188, 72, - 0,138,172,172, 44,135,216,219,187,119,111, 36, 77,211, 14,179,199,223,127,237,102,111, 54,128, 77,109,124,126, 78, 0, 36,208, - 39,173, 81, 65,191,154,133,192, 40,137, 13,223, 30,188,189, 63,187, 61,206, 2,192, 26, 57,152, 3,151,165, 84,142,182,119, 63, -145,156, 84, 77, 32, 22, 35,115,163, 11,171,243,203,203,203,139,204,202,202, 82, 56,234,122, 13,237,173, 94,189, 90,154,146,146, -162,176,101,123, 97, 83,246, 10, 63,237,140,129, 47,214,192, 30,123, 12,166,141,216,169, 56,125, 65, 7, 0,200,204,204, 36,201, -201,201,118,181,103, 72,183,239,161,212,122,195,197,197, 5, 89, 89, 89, 36, 41, 41,169,163,220, 31, 93,231,189,146,242,205,218, - 15, 86, 63, 5,224, 15, 7,216, 11,152,255,210,203, 95,124,254,201,135, 79,154,177,231, 4, 64, 11,203, 25,217,156,160,207,220, -216,117,225,194,151,191,249,248,227, 15,159,130,126, 51, 39, 26, 14,200,228,102,252, 28,115,188, 55, 14,183, 85, 67, 80, 20, 21, - 39, 16, 8, 6, 8, 4,130, 72,138,162, 66, 0,184,170,213,234, 92,161, 80,232, 73,211,116, 5, 33,228,117, 0,119, 28, 89, 7, - 60,120,152,194, 83, 37, 37,228,155,160, 32,135,245, 81,201, 50, 25,201,108, 35, 78, 20, 89,123,200, 9, 33,150, 30, 58,206, 29, -134,163,236,113,245, 96, 29,137, 61,123,246, 88,237, 68, 24,114, 77, 77, 77,133,175,175,175,201, 12,120, 41, 41, 41, 10,182,191, -201,216, 99,136,255,200,145, 35,205, 66,192, 30,123,244,185, 55, 32, 24,240, 54,190,222,171, 79, 29, 75,159,123,163,249, 24,193, -128,183, 57,213, 75,231,154, 87, 8, 77,128,239,118,235,109,197, 78,116, 66, 88,112, 17, 50, 51, 51, 9, 0,112, 21, 2,213,218, -239, 34,171,174,220,129,146,154,168,168,111,236,132,216,152, 42,244,240,163,112,252,248, 33, 82, 83,163,194,164, 73,147,218, 85, - 8,204, 95,184,240, 37,208,244,228,249, 11, 23,190,244,249,199, 31,191,110,183,189, 5, 11, 95, 32, 52, 29, 61,127,193,194,151, - 62, 95, 99,210,158,134,133, 25, 13, 0,106,193,130,133, 47,209,180,110,242,130, 5, 11, 95, 90, 99,218,150, 0, 54,228,122,176, - 19,106,195,251,239,135, 31,126, 80,204,152, 49, 67, 58,121,242,228,124,123,140, 10,133,194, 88,145, 72, 52, 65, 36, 18, 61, 46, - 20, 10,189, 4, 2,129, 91, 70, 70,134, 96,241,226,197,207,234,116, 58,104,245,120, 92,167,211, 37, 0,248,165, 73, 4,168,155, -250,191, 54, 31, 6,221,177, 99, 7, 97,219,223,197,197,197,113,186,167,119,238,220, 73,236,249, 62, 15,199,195,101,229, 74, 64, - 46,119,152, 61,229,146, 37,118,125,159,201, 8,200,105, 59, 96, 54,228, 63,108,216, 48, 20, 20, 20,112,242,248, 45,145, 60, 27, -123,166,236,167,166,166,162,180,180, 20, 89, 89, 89, 14,221,214, 53, 57, 33,147,192, 37, 4,153,155, 34, 41, 0,200,204,242,160, -184,144,255,234,213,171,165, 21, 21, 21, 10,115,228,159,154,154,138,140,140, 12, 78,228, 15, 0, 73, 73, 73, 24, 61,122,180,116, -244,232,209,118,217, 99,200,158,121, 93,241, 14, 90,144,255,146,153, 18,172,220,172, 98, 85, 87, 30,202, 20, 50, 48, 68,136,122, - 37,193, 43, 79, 73,112,164, 72, 11,101, 61, 65,131, 26,144,134, 23,161,232,162,142, 83, 52,160,244,250,135,164,234,102, 39,184, -119, 22,195,175,187, 27,186,118, 11,198,213, 18, 53,122, 15,208,192, 73, 82,129,188, 45,183,177,101,203, 22, 50,125,250,244,118, -233,240,100, 50,153,179, 79,143, 30, 11,191, 61,114,148,138,237,215,247, 37,153, 76,246,174, 92, 46,111,180,199, 94, 87,191, 30, - 11,191,219,123,132,138, 14,239,103,151, 61,153, 76, 38,246,243,235,190,240, 39,197, 1,106,248,144, 48,115,182,232,118,168,182, -230,237, 7,179,178,178, 20, 9, 9, 9,216,188,121,179, 98,242,228,201,173,218, 48, 34, 34,130,188,245,214, 91, 72, 72, 72,176, -216,190, 34,145,104,146, 88, 44, 30, 40, 22,139, 23,136,197, 98,215,235,215,175,163,111,223,190, 16, 10,133,112,119,119, 71,113, -113, 49,220,220,220, 68,199,142, 29,243, 60,124,248,240,129, 23, 95,124,177, 55,128,171, 0,196,230,234, 32, 57, 57,185,149,179, - 98,216,111, 49,229, 20, 69, 33, 51, 51,211,234,253,183,117,235, 86,179, 54, 12,203, 9, 33,136,139,139,227, 84,161, 57, 57, 57, -118,125,191, 45,113,234,212,169,200,240,240,240,124, 71,216,186,117,235, 22,161,105, 26, 16, 84, 65,221,168,130,216, 89, 2,208, -158, 16, 8, 4,232,214,173, 27, 53,216, 56,114,105, 33, 25,206,195, 15, 63, 76, 54,111,222, 12,115,246,102,206,156,137,131, 7, - 15, 82,182,158, 31, 0,148,223, 58, 79, 12,207,207,158,107,183, 37,154, 96, 46, 13, 48, 43, 1,192,150,252,217, 34, 53, 53,213, -234, 49,108,136,203, 28,249,175, 88,177, 2, 75,151, 46,109, 81,110,171, 8, 72, 30,150, 73,208, 37, 4,153, 63, 69, 82,134, 30, -127,116,116, 52, 5, 0,204,107,113,113, 49, 97, 67,214,150,200,191, 41, 50, 96,213,107,103,194,244,134, 30,190,241,208,130, 45, -246, 44,121,248, 75,102,178,223, 41,206, 71,249, 10,233,251,144, 16, 46,206, 20, 30,242, 23,226,118, 37, 13,141, 86,136, 59, 85, - 4,213,117, 4,197,191,211,128, 0,240,113, 61,131,188,188,188,200,168,168, 40,139,157,194,213,107, 31, 68,134, 6, 7,225,240, -205, 91,232, 19,208, 21, 3, 7, 7, 66,232,236,141,135,250, 84,162, 82,169, 66,197, 77, 29,126,191,165,130,171,168, 20,121,121, -238, 86,237,181, 17,230, 60,181,120,177,184,180,187, 63,156,135, 13, 23,168, 14,236,159, 3,224, 43, 27,236, 48,158,248,156,167, - 95, 90, 36,254, 93,236, 7,183,144, 8, 65, 77,225, 65, 91,237, 1,192,156, 23, 23,190, 44,134,179, 59,250,244, 11, 19, 92, 56, -123,194, 30, 91,142, 4,205, 60, 35, 20, 69, 65, 34,145, 72, 1, 40,140,239,137, 97,195,134,177, 34,127, 0,112,114,114,242,148, - 72, 36,115,111,223,190,237, 26, 18, 18,130,161, 67,135, 66, 36, 18,225,147, 79, 62,129, 78,167,195,160, 65,131,240,227,143, 63, -226,216,177, 99, 56,115,230, 12,132, 66,225,103, 58,157,110,170, 37,155, 83,167, 78,109,238,231,172,245,131,108, 8, 87, 46,151, - 75,253,252,252, 20,132, 16,139, 14,208,205,155, 55, 57,239,149,193,216,182,245,251, 12, 81,159, 63,127,222, 98,191, 17, 26, 26, - 42,229, 74,230,231,207,159, 87, 84, 87, 87,195,195,195, 67,106,143, 16, 56,113,242, 16,121,235,157,249,232,212,201,165,213,103, -245,245, 74,228,252,120, 26,103,228,114,106, 74,247,238,228,122, 98,162,249,190,253,192,106,125, 99, 30, 88,141,238,147,226, 33, -137, 24, 14, 93, 72, 88,203,240,217,119, 27,224,245,254,116, 12, 48, 24, 42, 82, 62,250, 60, 62,183,114,126,203,210,230,193,187, -139,171,190,224,141,143,144,178,232, 25, 0,192,221, 59, 13,120, 47,125, 45,137, 24, 58,214,102, 17,224,232, 33, 5,139, 2,128, -241,216,173,121,234, 29, 5,165,165,165, 88,186,116,169, 77, 2,194, 18,244,158,126, 50,181,103,207, 30,146,149, 57, 18, 16, 43, - 9,155,177,127, 83,100,109, 76,202,150,134, 5,204,193, 80, 80, 28, 57,114, 68, 49,122,244,232, 22,161,127,174,246,254,187,216, -205,108,231, 54,103, 85, 61,107, 59, 52, 77, 71, 58,187, 82, 16, 8, 0, 87, 23,160,170,134, 70, 35, 33,232,228, 66, 65, 69, 3, -202, 70,130,158, 93, 5,160,181,192,165,235, 58,148,150,150, 42, 96, 33, 61,237,185,162, 31, 34, 7, 14,236,175, 16,139, 9, 94, -152, 59, 10, 58, 29,193,205, 10, 53,174,221,168, 2,156,174,195,197,171, 17,229, 21, 87, 32, 16, 87,227,220,185, 42,120,120, 89, -182,215, 86,112,246,246,126,227,241,191,253,205,249, 53, 26,240, 90,154,230,118,235,244,169,215,109, 36, 89, 2, 0, 18, 15,239, - 55,254,239,201,191, 57,175,186,172, 67,207,217,169,110, 23, 74,207,152,178,103,117, 71, 54,153, 76,134,206, 30,158,111,204,121, -242, 41,231, 51,215, 42,145,248, 68,178,219,191,223, 73,177,245,220,204, 70,242,204,149, 91, 17,222, 58,230, 25,137,143,143, 71, - 84, 84, 84,126, 86, 86, 22,148, 74,101,115, 27, 50,158,127,124,124, 60,171, 54,117,118,118, 30, 91, 95, 95,223, 63, 52, 52, 20, - 82,169, 20, 41, 41, 41,120,238,185,231,244,157,185, 70,131,245,235,215,163,160,160, 0, 39, 78,156,192,247,223,127, 15,165, 82, - 25, 76,211,116,172, 37,155, 83,166, 76,113,232,253,180, 99,199, 14, 86, 67,115, 20, 69, 41,184,134,240, 13,109,219,242,253,166, -208,112,126,117,117, 53,202,202,202, 76,126,238,239,239, 15, 91, 9,188,172,172, 12,101,101,101,118, 9,129, 51,167, 47,226,155, - 13,219, 49,126,252, 88,132, 13,234,209, 92, 94,116,246, 6, 14, 28, 56,132, 31, 55,255, 76,178, 94,125, 21,215, 19, 19,225, 50, -110, 28,148,191,252, 98,210, 78,230,248, 20, 10, 0, 46,109, 88, 67, 6, 87,236,198, 83,123,183, 67, 23, 18, 6,229,162,229, 0, - 0,151, 85,203,225,118,177, 8,139, 75,197,232,251,244,130,123,245, 88,127,239, 57,181,116,126, 81,209,227, 90,157, 95,222,158, - 95,112,230,244, 69, 68, 12, 29,107,243,253, 99,203,144,130, 97,184,223, 82, 52, 64,196,213, 99,119, 52,209,218,139,172,172, 44, -187,190,159,156, 41, 35,232, 14,100, 38,232, 59,174,204,130,228, 22, 97,126,189,199, 95, 77,140, 35, 1,108,201,186,162,162,162, - 5, 57,219, 66,214,108,193,136, 14,153, 76, 70,172,229,131,182,228,217, 48, 96,194,255,230,236, 17, 66,200,237,115,175,160,123, - 83,232,191, 89, 49,235, 8, 84,106, 64,211, 84,166,209, 18, 16,129,254,253,217, 51, 5,204, 42, 1,147,112,119,175, 86,212, 43, - 5,240,241,246, 68,213,221, 6, 84, 85, 87,225,200,241,155,184,113,139, 64,220,169, 1, 61,130,235,160,108,184,141,190,131, 53, -232, 29,218,136,239,191, 40,192,238,221,187, 35,239,227, 45, 39,144,201,100, 81, 51, 95, 72,238, 86,230,225,133, 18, 45,224, 18, - 53, 25, 2,175, 46, 62, 50,153,108,178, 92, 46,255,201,128,172,157, 96, 48,238,109,174,223,151,201,100,209, 73,115, 95,232,246, -135,192, 3, 87,235, 52,240,140,136,130,200,221,203,216, 30,192,110, 2, 91,204,180,233, 51,186, 17,161, 51,170,235, 27, 49,112, -216, 24,184,117,246, 48,101,171, 93,192,120,255, 20, 69, 97,219,182,109, 36, 62, 62, 30,219,183,111,135,139,139, 75,100,106,106, -170,130, 11,249, 3,112,174,170,170,122, 90,163,209, 8, 92, 93, 93, 49, 97,194, 4,172, 90,181, 10, 78, 78, 78,144,201,100,216, -176, 97, 3, 10, 10, 10,112,228,200, 17,252,252,243,207, 56,123,246, 44,124,124,124,124,180, 90,237, 67,176, 50, 4,146,156,156, - 76,172, 13, 1,124,241,197, 23,172,206,179, 45,135, 0,182,110,221,234,144, 33, 0, 15, 15, 15,105, 89, 89,153,194,220,103,246, -182,187, 45, 66, 64, 90, 82, 66,238,172, 92,137, 15, 0,224,240, 97,220,157, 25,135,213, 67, 66,154, 67,246, 97, 3, 6, 96,214, -236, 41,232, 93,121, 27,215, 19, 19,209,101,201, 18, 40,130,130,168,193,191,252, 98,241, 57, 17, 75, 31, 70, 72,108, 36, 22, 47, -121, 23,255, 66, 17, 86,143,158,132,129, 35, 70, 33,248,110, 41,214,123, 14, 69,169,199, 45, 12,146, 72,136, 74,165, 98,213,190, -210, 73, 67,240,212,211,241, 56,250,235, 89,236,206,253, 9,111, 2, 88,189,106, 29,194, 6, 12,192, 83, 79,199,163, 65,121, 7, - 18, 14,246,140, 97,239, 28, 0, 78, 17,128, 7, 9,114,185,156,114,196,172,117,134,220,179,150, 94, 6,132, 98, 36, 79,238, 13, -120,246, 70,102,211,130, 37,182, 99,255,142,134,225,181, 49,147,254, 12, 61,127, 99, 48,115, 3,204, 77, 6,180,101, 39,194,141, -139, 58,153,141, 8,184,215,164,224,138,154,224,230,109, 26,128, 0,110,174,250, 16,167, 70, 75,160,106, 4, 84,106, 64,213, 8, -168, 53,128, 74, 9,168, 27,239, 69, 73, 76, 9, 10, 55,237, 43,228,198,181, 0,244,234,227, 6,226, 36,194,109,165, 18,138,125, -215,113,174,248, 6,238,222,173, 67,216, 48, 29,234, 85, 90,168, 26,117, 80, 54,208,184,121, 13, 80,214, 3, 91,182,108, 81,112, -217, 0,195,206, 54,161,133,158,158,111, 60,243,234,171,146,239, 13, 40,196,235,213, 52,183,187, 75, 23,189, 14,224, 39, 3,178, - 86,179, 48, 73, 68,110,158,111, 60,247,242, 82,201,174, 27,186,230,194,158,143, 47,117,187,250,229,171,134,246, 88, 69, 1, 92, -221,220, 95,127,233,149, 69,146,146,178,123,187, 69, 38, 60,145,236,246, 93,230,106, 83,182, 56, 61,107,166,238, 37,142,207, 26, - 97,188,127,137, 68, 34,141,138,138,202,103,150,140, 42,149, 74, 69, 65, 65, 1, 21, 31, 31,207,214,150, 22, 64, 48, 0, 58, 60, - 60,156,150, 72, 36,130, 13, 27, 54,224,217,103,159,197,251,239,191, 15, 66, 8,126,253,245, 87,236,219,183, 15,103,206,156, 65, -117,117, 53,250,246,237,139,154,154, 26, 87,129, 64,224,107,205,248,180,105,211,204,138,100,102,104, 96,202,148, 41,156,194,244, - 29,117, 8,192, 82, 20,192, 30,239,223, 94, 33, 80, 89, 85,213,252,222, 55,109, 30, 6,166,205,199,120,163, 99, 46, 63,250, 28, -122,238, 63,142,146, 69, 47,224, 87,127,127,184, 0, 56, 35,151, 83, 48,177, 44, 78,169, 84,146,158, 61, 59,227,234, 53, 32, 44, - 34, 20, 88,249, 26, 94,254,114, 11,230, 6,157,198,144,198, 98, 44,190, 37,198, 59, 27,151,225,253,244,207,113,230,236, 65,244, -234, 25, 70, 92, 92,204, 71,125, 13,237,121,119,113,197,163,113,163,240,104,220, 40,188, 69,127, 4,117,227, 82,156, 60, 9,156, - 60, 9, 28, 56, 16,143,127,175,185,136,184,184, 88, 18, 16,240, 16,130,130,190,225,196, 79,121, 15,191,134,146,131, 34, 43,125, -247,231,127, 13, 1, 32,147,201, 72, 82, 82,146,148, 25, 51, 52, 22, 1,134, 29, 18, 51, 30,111,235,124, 0,134,244,163,163,163, - 41,253, 48,128, 24,153, 27,239,239,245, 50,179,254,163,162,162,168,188,188, 60, 98, 45, 26, 98,109,217,161, 37, 66,231, 58, 28, -240,244,171,245,240,239, 38,192, 19, 9, 98,168, 26, 1, 15,119, 10, 2,170,201,235, 7,129,170, 1,168, 87, 19,212, 43, 9,234, - 85, 4, 52, 1, 4, 22,230, 92, 63,189,176, 30,131,134,148,194,175,255, 93,236,217, 85,129,187,119, 85, 8, 31, 83,131,193,222, -117,128, 83, 35, 84, 13, 52, 42,110, 16,212,215, 83,208,106, 41,120,251, 80, 0,117,223,231,178,133, 13, 29, 50,100,184, 87, 64, - 0, 14,233, 12,196,203, 19, 79,226,110,106,202, 48,153, 76, 54, 64, 46,151,159,227,112, 63,135,142, 24, 55,113,120, 23,255, 0, - 28, 63,218, 60, 71, 14, 93,165,255,135,171, 95, 44, 53,101,207,210, 86,216, 3,198,141, 27, 63,220,223,191, 39,206,157,184,220, - 92, 62,238,145, 41,248,159,124, 21,231,115,107, 3, 52,159, 59,243,252, 50,195, 0, 12,182,111,223,222,106,254,145,137,185, 0, - 76,163, 7, 3, 56,181,100,201,146,177, 34,145,200,237,235,175,191,198,186,117,235,240,204, 51,207, 96,197,138, 21,160, 40, 10, - 87,174, 92,129, 82,169, 68,106,106, 42,180, 90, 45,230,205,155, 71, 83, 20,101,245, 1,112,228,108,250,142, 62, 4, 96, 41, 10, -224, 8,239,223, 86,108,216,176, 1,127, 75,158,133,234,170, 70, 32,125, 45,234, 15, 28, 71,167,241,195,155, 63,175, 72, 95,139, - 34,103,103, 80,255,120, 30, 3,103, 63,138,195,235,119, 97,240,224, 17,102,237, 93,186, 84,136, 49,227, 98, 81, 88,228,133,181, -159,101, 97,252,248,177,120,231,211,101,120, 43,106, 14,190, 5,208,255,169,103,177,246,179, 44,136,197, 94,152, 58,109, 56,190, -230, 96,239,227, 15, 54, 97, 68,252, 32,188, 59,104, 21, 10,167,184,193, 43,225,199, 22,199,250,184, 74,112, 52, 95,129,128,191, -205,229, 92, 15, 7, 15,138,176,114,165,139, 21, 1,247, 23,138, 0, 24,143, 35,155, 35,248,166,227, 88, 35,179, 64, 63, 67, 93, - 79,252,151,144,245,201,101,232, 87, 1,180, 20, 5,108,134, 1, 28, 29,214,207,203,203, 35,134,222, 63, 19, 17, 48,252, 63, 41, - 41, 9, 76,178, 28,115,137, 33,184,144, 63,179, 10,192,156, 61,173, 14,168,111, 32,104, 84,235, 39,251, 53,170, 9, 68,206,247, - 62, 83, 53, 0, 74, 13,193,157,187, 4,127, 84, 18,156, 56,167, 5, 77, 3, 73, 73, 73,210, 75,151, 46,181,106, 27,173, 22, 40, -187,174,198,245,146, 74, 28, 60, 92, 9, 66, 40,156,251,141, 70,252, 19, 90,136, 69, 4,127,220, 2, 14,254, 4,212,212, 16, 16, - 26,120,120, 18, 5,137, 4,136,141,157,138,171, 87,175,178,186,166,236,245, 50, 50,109,174,237,171, 68, 4,110,157, 95,125, 97, - 69,134, 83, 14, 17,180, 96, 98, 31,103,103, 56,253, 99,161,211,149, 53, 31, 45, 3,240, 36, 91,123, 66, 23,183,101,243, 95, 95, -225,244, 83, 25,105, 97,175, 75, 39,103, 12,156,253,162,211,185, 77,159, 24,219, 51, 27, 1,144,184,116, 90,182,244,141,229, 78, -151,111, 86,183, 56,160,179,123, 39, 76,127,226, 25,167,156,255,126,197,233,220,218, 42,106,103,170, 44, 34, 34,130,156, 56,113, - 2,219,182,109,107,245,157,132,132, 4,147, 77, 1,160, 16,192,169,213,171, 87, 15,241,244,244,116, 99,194,224, 95,125,245, 21, -158,125,246, 89,172, 91,183,174,217,139, 95,189,122, 53,170,170,170, 80, 83, 83, 83,215,208,208, 80,218, 20, 65, 16, 91, 58,215, - 23, 94,120,129, 24,135,232, 25,239,159,109,248,255, 65, 25, 2, 48, 21, 5,112,180,247,207,216,100, 59, 4,112,110,204, 24, 80, - 47,204,134, 39, 0, 50,105, 24, 26, 78, 20,162, 62,125,237,189,122, 75,158,133,190, 79,205,130, 68,162,191,254,162,162, 98,139, -132, 93, 84, 84, 12, 0,136,141,211,139,136,130,227,103,240,237, 55,223,193,117,212, 72, 52,104,180, 80, 67,141, 9, 19,135,182, - 56,158,173,189,235, 58, 53,158,232,246, 34,232, 19,141, 72,250,215, 36,136, 31, 59,130, 1, 97, 3, 16, 54, 48,184,249,252, 82, - 23,175, 65, 80,144,144,245,125,243,200,255, 61, 18,117, 14,231,246,224,127,223, 80,214,166, 0,124,254, 57,218, 38, 17, 80, 71, - 68, 65, 65,129,213,217,228,121,121,121,145,172,151, 20, 58,119, 66, 86,239,253,128,182,128,160, 79, 39, 36,167,247, 65,102,126, - 60, 5,100,146,123,130, 32,218,230, 97, 0,227,165,128,230,150, 6,154,235, 44,101, 50, 89, 51,249, 27, 79, 0,100, 66,234, 76, -153,165, 8,128,161, 61, 71,117,230, 59,119,238,140,188, 81,190, 75, 65,119,165, 33, 16, 1, 78, 2,253,253,173,161, 9,180, 90, -160,182,150, 64,173, 1,180, 26,189, 40,152, 58, 77, 31,189,185,116,233,146, 89,123,141,183,119, 42,194,194,104, 28,216,167, 3, - 37, 0,254,184, 73, 65,226, 2,236,219, 13,168,149, 20, 40, 2, 12,142,112, 66,217, 53, 26, 19, 39, 78, 65, 92, 92, 28,197, 38, - 19, 86,246,122, 25, 89,249, 34,176,228, 83,219, 69, 0,161,117, 49,186, 46, 62,130, 93,244, 61, 22,234, 6,192,143, 2,148,195, -134,137, 46,107,117, 49,156,236, 17, 58, 6,238,222, 2,197, 77, 93,179,189,174, 18,192, 71, 66,193,117,208, 48, 81,209,119,116, -140, 57, 47,218,148,173, 78,238,158,130,171,183,170,154,136, 5,112,119,113,134,187,171, 24, 17,225, 67, 69, 91,190, 37, 49,237, -252,232,154,172,115,102,214,127,124,124,124,243, 61,202, 68,239,102,206,156,105,201, 3,173, 3,112,249,228,201,147,117,227,199, -143,239, 10,131, 53,253, 95,125,245, 85, 51,201,106, 52, 26,232,116, 58, 92,186,116, 9, 93,187,118,189, 77,211, 52, 43,181, 56, -109,218, 52,179, 67, 0, 92,136,246, 65, 24, 2, 48, 21, 5,112,164,247,207,133,248, 25,116,247,247,196, 23, 95,236, 69, 98,194, - 24,116, 27, 22, 6, 12, 11, 3,245,194,236,150,162, 23,192,173,155, 74,108,221,118, 24,221,253, 61,217,219,243,115,193,176,225, -125, 49,108,120,223, 86,199,113,181, 55, 97, 70, 40,210, 38,126, 2,186, 80, 79,254,207, 45,126,218, 38,123,198,120,213,253,213, - 61,239,215,190, 31, 93,142,242, 54,123, 32,237, 18, 0, 5, 5, 5,247, 61,107, 31,227,229, 50, 68, 23, 21, 21, 69,153, 32,127, -194,132, 21,147,146,146,108,250, 29,195, 85, 0, 76, 25, 87,207,223,120, 2, 96, 19,154,203, 82, 82, 82, 20, 73, 73, 73,172, 31, - 50, 67,242, 55, 53, 39,128,171, 61,107, 88,185, 89, 5,107,246,226,226,226,242,151,165,110,197, 35,163,157, 64, 3,208,168,105, - 56,139,245,213, 84, 91, 79,208,168, 33,208,234,128,130, 66, 29,116, 52,129,181, 37,123,113,113,113,249,111,188,182, 21, 19, 35, -133,152, 62, 71,136,186, 90,130,218,106,160,190,150, 66,159,190, 4, 58, 13, 5,145, 64,130,170,187, 52,202,126, 87, 99,209,203, -236, 38,140,101,175,151,145,143, 22, 2, 33, 1,192,154, 87,128, 5, 31,216, 38, 2, 72, 67,253,140,127, 12, 27,186,211, 47,103, -167,155,215,184,135,209, 13, 64, 55, 10,208, 29, 58,136,188,167,159,172,211, 52,212, 79,231, 98,143, 86, 53, 76,127, 33,106,248, -174,208,183,178,221,124, 7,143,133,143, 51,133,174, 18, 10,202,243,191, 96,235,107,115,235, 52,202, 6,214,246, 26, 85,202,233, -113,143,140,223,149,146,254,153,219,128, 33,195,224,238, 42,134,187,139, 51, 74,206,157,194, 27,169, 47,213, 41, 57,216,178,197, -147,103,115,185,166,200,127,249,242,229,173,194,252, 63,252,240,131, 34, 33, 33, 1,102,146, 4, 49, 68,175, 6,112,170, 95,191, -126, 37, 42,149,170,135, 80, 40,148,184,186,234,151, 98,109,222,188, 25, 51,103,206,132, 82,169,132, 74,165, 66, 99, 99, 35,220, -220,220, 84, 58,157, 46,135, 16,114,147,205,201, 58,106, 53,192,131, 50, 4, 96, 24, 5, 96,222,183, 7,241, 51,232,211,199, 15, -175,166, 37, 99,247,174, 95,145,189,229, 4,156,197,157,241,123,217,189, 17,172,158,254, 3,208,168,174, 65,196,176,254,248,240, -163,100,188,159,254, 57, 39,123,190,190, 30, 40, 58, 87,212,252,121,216,128, 48, 84, 84, 84,115,178, 55,101,225,116,204, 20, 60, -137,198,194, 58,140, 94, 48, 16,244, 96, 9,190,248,226,251,230,243,171,174,174,198,216,135, 67, 89,217, 51, 70, 84,102, 20,245, - 51,126,110, 83, 62,181, 89, 0,180, 5,249,179,177, 25, 21, 21, 69,101,101,101,145, 38,111, 23, 89, 89, 89,196,112, 89,162,177, -215,111, 74, 32,180,142,195, 82,128, 88, 0,184, 8, 1, 55, 17,208, 88,139,172,247,157, 0,151,163, 36,249,177, 62,128,139, 55, - 50,191,225,238,245, 91,154,237,207,144, 53,219, 53,236,198,228,111, 60, 39,128,171, 61,182,228,207,198,222,123, 25,107,169, 87, - 22,206, 35, 18, 9, 64,211,192,160,126,194,123,237,113, 86, 7,141,142, 64, 71, 11, 49, 99,198, 12, 86,226,228,237,119,215, 82, -139, 22,205, 35, 90, 45,160,214, 16,232,180,128,128, 2, 34,167, 0,181, 85, 20,126, 59,173,132, 82, 37, 64, 98,194, 12,214, 97, -255,229,207, 1,193, 61,245,255, 7,245, 0,108,141, 4,200,229,242, 35, 50,153, 44,246,230,212,184, 93, 1, 91,119,186, 5,140, -123, 24,154, 67, 7,241, 99, 66, 92,157,186,182, 54, 86, 46,151, 31,228,104,239,160, 76, 38,139, 61,255,230,180, 93,254,255,202, -113,235, 49, 98, 28,234,207, 31,194,198,127, 76,173,107,108,224,102,143,177,181, 58,237,239,187,222,249,248, 75,183,209, 99,198, -162,184,232, 20, 94, 74,126,178,174,161,174,142,243,185,181, 53,204, 37,251,145,201,100, 36, 62, 62,158,205,106, 0,161,167,167, -231, 41,165, 82,249,109,105,105,105,239, 33, 67,134, 4,106,181, 90,145,147,147, 19,114,114,114, 16, 29, 29, 13,149, 74,133,134, -134, 6, 92,186,116,169,198,203,203,107,175, 82,169,252,154,166,233,122,176,204, 0,200, 36, 5, 98, 66,236, 92, 66,255, 15,218, - 16,128, 97, 20,192, 17,237,107, 75,238, 0, 83,120, 52,118, 20, 30,141, 29,213,244,159,253, 26,182,165,189,105,246,137, 59,207, - 31,208,120,186, 14, 79,127, 54, 5,239,236, 93,102,247,185, 41,159, 81, 18, 47,173, 23, 84,223,168,238,139, 99,109,147, 0,104, - 15,207,223,216,251, 48, 12, 99,155, 11,245, 59,242, 28,185,140,253, 59,154,252, 13,196,142, 97, 34, 32, 70, 4, 41,154, 34, 29, -156,236, 89,155, 11,192,213,222, 7, 31,175,165,100, 50, 25, 17, 8,128,131, 5,250,177,126,102,194,159,126,220,127, 6, 39,123, -171, 86,173,165,230,205,111,202, 73, 33,208,219, 56,186, 31,168,175,163, 65,104, 32, 49,113, 10, 98, 98, 98,172,182, 71,246,122, - 25, 73,125, 18,240,116, 3,202,110, 3, 46,206, 0, 77,128, 78, 18, 32, 93, 6,164,201,109, 18, 1, 7,101, 50, 89,108, 65, 98, -220, 46,143,229,111,187,229, 47,127,163,174,209, 6,242, 55,182,151,191,100,234, 46,151,127,188,233,150,251,239,183, 56,147,191, -161,173, 23, 95,124, 49,238,141,127,190,176,115, 65, 74,170,219,103, 31,102, 48,228,127,218,196,179,175,229, 98,219,218,208, 17, -215,231,205, 20,249,207,155, 55,143, 48, 43, 1,182,109,219, 70, 40,138,178, 36, 4,220,212,106,117,157, 64, 32,200,243,247,247, -239, 89, 91, 91,251,226,241,227,199,187, 15, 29, 58,148,214,106,181, 13,213,213,213,183, 78,159, 62,125,165, 79,159, 62, 37, 93, -186,116, 41, 85, 42,149,155,181, 90,237, 45, 66, 8,107, 1,192, 36, 5, 50,136, 10,216,210,190,210, 54,236, 11, 29,110,219, 81, -227,254,246,218, 81, 41,133, 14, 61,222,209,246,170, 42, 5,200,208,202, 16,120,216, 15,179, 63,181, 46, 76,170, 42, 5,120, 40, -192,242, 49,247,147,252,205, 10, 0,107,107,253,185, 62,232,108,115, 7,112,177, 43,151,203, 41,115,155,237,112, 33,175,204,100, -185, 62,204,127, 17,192, 69,227, 79,171,155,254, 46,195,134,235, 85, 56,138, 92, 13,235, 69, 38,147, 17, 38,207, 64, 74, 74,138, - 77, 43, 28,140,237,109, 92,212,169, 89, 20,216, 35,154,140,219,132,153,240,103,107, 84, 98,237,231, 45,237,213,213,232, 59,224, -196,196, 68,110,247,223,183, 14,125,102, 52,134,164,189,111,249,155, 27, 26,107,107,159,182,215,187,102,236,253,244,217, 91, 27, - 84, 13,181,115,229,114,249, 33, 91,109,125,250,233,167, 7,100, 50, 89,236,103, 31,173,220, 80, 87, 87,103,238,220,180,184,255, -104,209,163, 26,147,127, 94, 94, 94, 36, 33, 4,219,183,111, 55, 60,198,146,189,107,106,181,218,153, 16, 82, 75,211,180, 92,173, - 86,255, 26, 16, 16,224, 83, 85, 85, 69,189,254,250,235, 53,213,213,213,119,122,244,232, 81, 91, 87, 87, 87,175, 86,171,107, 52, - 26, 77,163, 78,167, 83,114, 57, 97, 7, 13, 3,228,183, 97,157,230,227, 79,138,126,253, 6, 83,111,190,150, 73,102, 61, 30,141, -176,129,125,204, 30, 87, 84,120, 25,155,190,219,131,126,253, 6, 83,247,211,222,144, 33, 67,168,212, 69,114, 50,235,241,104,203, - 14,243,241, 82,108,250,110, 15,134, 12, 25, 98,245, 94,186,159,228,111, 82, 0, 56,218,179,111,203, 72, 65, 84, 84, 84, 62,171, - 16,191, 21, 56,114, 86,255,253,136,140,112,217,244,199, 17,209, 0,174,109, 98,184,172,203,222, 33, 9, 99,123, 92,201,223,158, - 25,255,108, 72, 27, 64, 80, 71,180,231,232,115,115,208,189, 77, 1, 0, 69, 81, 68, 32, 16,128,249, 99, 66,216, 83,166, 76, 65, -108,108, 44,104,154, 6, 77,211, 32,132, 88,251, 61, 74,171,213,186, 18, 66,116, 52, 77, 55,106, 52,154,253, 66,161,144, 18, 8, - 4,206, 0,156,105,154,134, 78,167, 19,106,181, 90,177, 86,171,237,174,211,233,206, 27,124,183,205, 55, 1,226,225, 24, 17,112, -165, 84, 69,118,239,220,130,107, 21, 53,240,243,106,104,254,236,102,165, 43, 2,124, 59,163,127,255,254, 86,201,186,173,236, 13, - 25, 50,132,186, 89,214, 72,214,124,180, 3,197,191,223,110,101, 47,184,167, 15, 2, 3, 3, 89,145,127, 91,193, 82,142, 20, 42, - 60, 60,156,223, 30,147, 7, 15, 30, 15, 42, 26, 12, 8,157, 54,112,108, 68, 6,229,229, 0, 60,160,159, 52,206, 19, 63, 15, 30, -230, 34, 0, 60,120,240,224,241, 0, 65,210, 36, 2,104, 3,226, 23,224,222, 16,135, 8, 64,247,166,247, 52, 95, 93, 60,120,240, - 2,128, 7, 15, 30,127, 14, 8, 0,184, 25,252,207, 16,191,216,128,244,233,166,227,120,239,159, 7, 15, 94, 0,240,224,193,227, - 47,210,167,241,164,207,131,135, 5,245,204,131, 7, 15, 30, 60,120,240,248, 43,171,229,249,243,231, 27,110,164, 67, 12,103,216, -203,100, 50, 98,180,209,206,181,168,168,168,230, 85,141,166, 82,177, 26,218,227,138, 63,163, 61,227,101,139,134,245,201,215, 31, -223, 30, 29,221, 94,122,122,122,243, 49,105,105,105,148, 13,246, 0, 51,233,128,249,251,217,186, 77,254,249,229,237,113,177,199, - 89, 0,112, 68, 87, 54, 7, 49,187,247, 57, 74,177, 24, 39, 35, 49,181, 27,160,169, 99,218, 67, 93, 49, 4,147,148,148, 36,101, -136,134,201, 0,102, 41, 39,248,253,196,246,237,219, 35,183,109,219,214, 76,130, 83,166, 76,145, 38, 38, 38,230,255, 25,213,174, -169,246, 56,127, 94,191, 50, 44, 52, 52,180, 93,207, 77, 38,147,145,169,211,100,200,201,150,155,188,103,119,238, 58, 65,114,178, -229, 22,239,229,157,187, 78, 88,236, 4,226, 98, 35,108,190,233,210,211,211, 73, 66, 66, 80,139,255,173,137, 0,107,168,173,171, -141,220,250,211, 86, 4,134, 5, 42, 64, 1,231, 79,158,147,142, 9, 31,139,208,126,161,156,238,191, 67,135, 14,181,186,238,177, - 99,199, 82,224,193,131, 71,155, 9, 0, 49,219, 3, 71,143, 30,205,217,184,169,205, 98, 24,152, 34, 81,227,141, 54,216, 18,173, - 45, 27,227,176, 17, 20,140,221,212,212, 84,100,100,100, 40,204,237, 45,206, 28,103,105,173,166,241, 57,246,232,211, 11, 0,112, - 75,165,130, 86,217,168, 47,172,170, 1,160,223,251,128, 75,110, 4, 67,242, 7,244,185,197,185,172,181,151,201,100, 68, 64,233, -179,235, 49,175,128,136, 87,212,158, 0, 0, 14,255, 73, 68, 65, 84,229,247,159,175,189,255,130,204,184, 61, 24,226,183,181, 61, - 28, 41, 42, 25,242,143,139,141, 80, 1, 50, 73, 78,182,220,230,223, 96, 4,132,105, 1, 32,183,235, 60,213,234, 84,228,230, 38, - 35, 38, 38, 19, 9, 9, 25,205, 17, 1, 91,132,192,193,162,131,228,161,161,189,240,161,124, 21,188, 92,189, 64,107,117, 80,145, - 70,197,238, 95,127,138,217,187,239,103, 50, 54,112,156, 84, 34,145, 88, 21, 2,135, 14, 29, 34, 77,145,133, 86, 30, 17, 47, 2, -120,252,149,113,234,212,169, 22,255,155,234,211,236, 17, 0,156,230, 15,152,218,197,206, 17, 32, 64,164,221, 54, 8,123, 13,192, -198,115,151,201,100, 36, 53, 53, 21, 43, 86,172, 0,128,230, 87, 83,199, 89,219, 33,172, 21, 60, 59,227, 76,233,119,112, 65, 79, -232,240, 11, 42,254,115, 2,167, 75,238, 96,198,138,117,237,118,163,157, 57, 91,136,193,131, 6,130, 38, 64, 97,161,254, 61,112, -239,189, 97, 57,205,178,170, 13,115,176, 91, 66,102,102, 38,197,182, 61,230,206,157, 11, 0,205,175, 38,201,159,162, 0, 11,247, -131, 76, 38, 35,143, 60,178, 11, 50, 89,172, 67, 69, 64, 92,108, 68, 67,114,114,178, 43,144,137,156,108,110,196,110,232,225,219, - 75,242,230,188,127, 0,152, 57,115, 51,114,115,245,175,201,201, 37, 96, 34, 2, 92,162, 1,132,144, 72,197,133,189,138, 23,255, - 49, 31,195,187, 14,133,139,135, 7,136, 90, 11,154,232, 32, 20,137, 17, 28, 21,156,251,219,176, 11, 88,145,153,161, 24,229, 51, - 90,234,234,234,106, 85, 4,220,190,125,187,197,255, 83,198,119,194,168,133,191,224,241, 12, 85,139,134,156, 52,105,146,205,237, -149,157,157, 77,166, 77,155,230,176,246,118,180,189, 54, 38,146, 72,123,211,250,158, 58,117, 42,178,137,132,108,181, 51,248,149, - 87, 94, 41,175,175,175, 15, 0, 48, 25,250, 77, 56, 67, 1,156,130,126, 83, 40, 0,216, 40,151,203,127,227,169,191, 53,249, 51, -101,198, 34,160,133, 0, 40, 45, 45, 37,165,165,165, 0,128,192,192, 64, 24,110, 54, 3,160,197,255,166, 62, 55,135,138,138, 10, - 69, 86, 86, 22,235, 72,128,241, 94,247,150, 72,152,106, 74,133,105, 76,162, 92, 67,236,153,153,153, 86,143,201,203,203, 99, 69, -254, 73, 73, 73,102, 73,127,233,210,165,200,200,200,128,161, 64, 96,131, 30,125,122,225, 70,101, 53,126,156, 55, 19, 93,168,113, - 40,249, 98, 17, 2,167, 7, 98, 79, 59,147, 63,128,102,194, 7,128,129, 3, 7,182, 40,103, 34, 3,134,229,142,246,236, 45, 17, - 49,211, 30,230, 72,127,253,250,245,200,200,200, 64,236,184,161,216,245,203, 73,192,189, 19, 80, 83,119,223,235,112,231,174, 19, -174, 64, 38,118,238, 58,225, 16,123,211,106,150, 89,124, 54,179, 59,191,199,234, 1, 49, 12,253, 39, 39,231, 34, 33, 33,168,249, -149, 65, 66, 66, 16,107, 17,240,197,255,190,192,251,159,190,139,241,125, 35,161,107,108,132, 86,167, 5, 37,162, 0, 8, 65, 64, -227,214, 31,101, 8,237,218, 31,203,230, 45,195,187, 43,223, 85, 60, 50,208,122, 52,203,184,179,155,226,191,222, 36,225,239,221, -187,151,216, 34, 2,178,179,179,201,206,215,119, 33,238, 29, 56,132,180,179,179,179,201,202,149, 43,177,100,201,146, 14, 45, 2, - 78,157, 58, 21, 89, 93, 93,173, 40, 43, 43, 67,120,120,184, 93,231, 89, 93, 93,173,184,215,101,219,244,156,151, 2,152, 11,224, - 36,128,175, 1, 68, 3,120, 20,192,223, 13, 4,192,237, 63, 41,159, 83,176,176, 13,184, 69, 71, 42, 85,207, 49,153, 25, 75, 77, -126,222, 66, 0, 4, 6, 6, 82,129,129,129,205,100,111, 24, 74,206,202,202,106,241,191,241,231,151, 46, 93, 50,123,130,140,168, - 72, 73, 73, 81,164,166,166,194,120,163, 28,227,205,115,178,178,178,204,134, 96, 77,117,246,198,101,237,185, 81, 17, 0,108,218, -180,201, 44,241, 3,104, 65,254, 75,151, 46,101,101,243,247,210,107,168,223,242, 6,220,158,253, 24, 61,250,244, 66,183, 46, 46, - 40,221, 82,170, 39,127,207,206,250, 33, 0, 39, 33,231,115, 77, 72, 72,144, 26, 14, 3, 36, 36, 36,112,142,210,208, 4, 8,232, - 4,252,251, 73,224,249,245, 64, 87, 87,224,124,149,233,242,162, 74,142,119,190, 25, 33,199, 37,106,243,246,219,111,155, 37,126, - 0, 88, 57, 55, 30,107,118, 31,129, 95, 96,119,220,188,122,203,170,247, 15, 0,108,162, 0, 92,194,248,122, 15, 95,102,210,211, -103,198,246,185,222,215, 43,255,107,190,142, 66,230,193,134,123, 37,168,197,171, 58, 33, 24,226,109,197,172,191,223,160,108,192, -184,217, 99, 21,163,187,143, 66, 99,125, 61, 68,206,206, 16,137,238,117, 65,165,197,197,216,154,147,115,227,217,103,230,246,232, -237, 28,128,161, 19,195,163,126,205,253, 53,114,212,240, 81,156,188,198,244,157,115,177,111,223, 62, 60,246, 88,203,242, 73,147, - 38, 81, 92, 69, 0, 67,254,232,253, 33,118,190,254,178,221, 34, 32, 59, 59,155,124,244,209, 71, 8, 9, 9,193,154, 53,107,176, - 96,193,130, 14, 39, 2, 12,137,223, 81,246, 24, 91,118, 68, 19,164, 0, 38, 2, 88, 79, 8,169,163, 40,202, 15,192, 5, 0, 87, -229,114,185, 22,127,110, 16,142,245,221,130,252,153,247,153, 25, 75, 91, 69, 1,238, 75, 30,128,172,172, 44,102,236, 21,165,165, -165,240,245,245,109, 37, 16,152,178,138,138, 10, 86,121,238,173, 77, 6,228,210, 97,206,154, 53,171,237,164,155, 1,129,153,242, -250, 51, 50, 50, 32,151,203, 41,107,179, 56,149,184,134,186,233,163, 64,220, 23, 1, 81,175,163, 14,255, 3,254,163,247, 22, 73, -214, 34, 56,253,109, 13,180, 90,238,137,206,226,227,227,243, 89,108,187,106, 57,194,243, 21,240,214, 90,160, 87, 79,224,214,118, - 49, 54,124,169,198,220,239,204,151,115,186,243,137, 99, 51, 85, 27, 78,246, 43,207, 94, 1,247, 48, 9,220,250,254, 19,155, 86, - 60,143, 33, 3,253,208, 47,254, 93, 86,237,193,230,254,100, 59, 84,192,220,187,134,228, 47,151,203, 41,102,226,159, 77, 68,211, -249, 61,202, 22,146, 55, 5,117, 66,176,201,242, 92,163, 72,128, 53,148, 87,148, 99,114,210,100,184,119,246,130,142,210,226,192, -190,253,168,173,171, 67, 66, 98, 34,254,168,168,192, 15,155,127,196,115,207,204,237,225, 44,113,134,128, 56, 33, 38, 34, 38,239, -130, 98,141, 77, 94, 99,101,101,165,221,215,109, 72,254, 0,236, 22, 1,217,217,217,100,249,242,229, 8, 14,214,215,103, 80, 80, - 16, 58, 82, 36,192,209,196,111,194,251,103,222,219,114,173, 3,154,136,208,137,162, 40, 87, 0, 97, 0,206, 1,232, 33,147,201, -106, 0, 84,201,229,114, 62,173, 61, 71,220,183, 68, 64,190,190,190,210,164,164,164, 86, 67, 1, 71,142, 28, 81, 52,109,246,194, -121,142,128,185,201,128,150, 60, 71,115, 2,165, 45,192,120,247,230,194,253,108,189,127, 0,216,253,234,114, 36,188,255, 1,180, - 81,227, 32, 2,224,118,184, 24,123, 74,238, 0, 0,180, 81, 11,160, 57,235, 3,170,235,223, 57,147, 20,219, 40,139, 37,220,153, -246, 63, 44,120,230, 58, 46,206, 91,130,250,159,213,240,243,177, 92,238,136, 8,128, 45,226, 96,253,250,245,122, 53,156, 48, 1, - 71,202, 42,224, 62,196, 29, 55,114, 75, 0,137, 51,102, 46,248, 27,188,123,198,183,219,131,104,110,214,191,163,162, 90,150, 86, - 8, 88, 91, 29,144,155,156,139,152,204, 24,204,220, 12, 36,231,234,223,231, 38,231,114,142, 2,212,169,106,225,227,210, 5, 90, - 85, 3,136,128, 96,196,200,145,216,178,101,139,234,163, 15, 62,144,208,132, 96,206,147,115,224,221,197, 27, 13,117,117,208,234, -180,112,119,234, 12,141, 64, 99,211,245, 86, 85, 85,181, 88, 29,192,117, 66, 96, 43,242,103, 96,163, 8,200,206,206, 38,169,169, -169, 24, 57,114,100,139,242,129, 3, 7, 34, 61, 61, 29,105,105,105,237, 38, 2,218,138,248,141,189,127, 0, 40, 43, 43,179, 53, - 10,240, 43,244,227,253, 53,208,135,254, 39, 3,184, 4, 96, 48,128, 28, 0,235,208,180, 83,167,165,238, 4, 54,134,210,255, 18, - 2,192,152, 16,152, 61,231,217,124,110,105,214, 52, 3,102,120,129,153, 16,200,204, 13, 96,162, 3,129,129,129, 10,102,184,160, -189, 58, 94, 71,194,218, 88, 63,227,253,179,177, 53, 99,237,102,144,196, 62,184, 53, 38, 2, 93, 48, 14, 46, 51,215, 64, 91,254, - 7,224,217, 25,162, 59,255,195,246,143, 10, 0,161,144,243,181,219,178, 10,194, 24,167, 95,249, 63, 12, 15, 7, 2, 23, 20, 34, -204,237, 25, 92,120, 40, 9,248,247, 18,179,229,237, 21, 1,200,200,200,192,248, 17,253, 16, 53, 46, 4, 9,131,150, 96,245, 71, -159,227, 92,193, 13,204,155, 52, 28, 55,115,118,162,186,178,198, 33,247,131,169,161, 2,107,207,135, 37,111,223, 81,247,168, 57, -251,150, 38, 14,166,165,165, 81,233,233,233,100,230,230,150,130, 0, 0, 98, 50, 99, 32,222, 86,140,109,219, 74,154, 87, 2, 48, - 19, 6,189,189,189, 77,246,191, 52, 77, 67, 71, 3,132,214,194,217, 69,130, 39,159,122, 74,242,214,155,111,162, 91,183,110,116, - 15, 63, 63,129,170,190, 14, 58, 2, 16, 90, 7,154,182, 30,209, 26, 59,118, 44,245,195, 15, 63,144, 59,119,238,160,166,166,166, -133,112, 52, 92, 29,192,101, 85, 64,118,118, 54, 89,253,124, 17, 32, 9, 6,110,126,218,250, 0, 73, 48, 86, 63, 95,132,148,255, -176, 19, 1,217,217,217,100,234,212,169,210,129, 3, 7, 42,238,220,185,211,234,243,128,128, 0, 76,157, 58, 85,250, 32, 77, 12, -180,197,251,183, 39, 10, 32,151,203,243, 13,158,175,238, 0, 78, 3,152, 46,151,203,185,108,101,202,147,191, 37, 1, 96,148,232, -199, 90, 34,160, 22,159, 91, 10,153, 38, 37, 37,153,140, 2, 48,100,239,235,235, 43, 77, 77, 77, 85, 48, 99,178, 73, 73, 73, 22, -151, 1, 90,242, 14,185, 78,254,107,171,101,128,140,119,111,105, 50, 32, 23,148,252, 43, 25, 78, 51,215, 64, 89,118, 17,162,195, -107,160,217,188, 0, 84,220, 42,108,253,251, 99,184,186,245, 50, 18, 86,126, 13,136,218, 39,179,243,146, 44, 32,119,229, 22,132, - 93,141, 1,110,215, 99,113,244, 18,139,229,142,136, 0,216,234,253,231,108, 89, 14, 97,143, 1,112, 67, 8,174,237,203, 68, 45, - 69,112,244,226,117, 68, 21,222, 96,217,238,215,154,255,159, 53, 75,222,130,236, 1,224,231,159, 99, 77, 30,103,233,249,176, 22, -234,119,196,178, 67, 71,172, 16, 72,206,189, 71,252, 0, 90,121,254,204,132,193,109,219, 74, 76,126,223,221,197, 29,101,213,101, - 24,217,123, 20,148,141, 42, 64,169,130, 86,173,193,178,212, 84, 80, 2, 8, 26,234,235, 64,211, 58,104,117, 4,206, 34, 39,252, - 81,247, 7,156,116,214, 87, 27, 63,246,216, 99,205,117,115,232,208, 33,194,244, 55,134,171, 3,202,203,203, 89, 95,231,180,105, -211,168,148,255,128,172,126,190, 8,161,125, 90,255,254,249,203,106,164,252, 39, 12,108,201,122,218,180,105, 84,118,118, 54, 25, - 57,114, 36, 2, 2, 2, 90,125, 94, 88, 88,136,156,156, 28, 69,123,145,127,147, 55, 78,181,229,216,191, 33,236,136, 2, 48,152, - 12,253,228,239, 70,158,194, 29, 40, 0,218, 10,140,231, 15, 0,163, 71,143,150,102,101,101, 41,152,208,191, 25,113, 32,189,116, -233,146,130, 43, 9,219,218, 73, 58,122, 25,160,161,247,111,138,248, 25,161,195,229,124, 79,151,220,129,230,236, 91,184,133, 95, -224, 23,183, 10,168,174, 65, 73,230, 34, 4,205,255, 16, 55,215, 45, 2,156, 68,128,160,125, 50, 59, 95,171, 7, 66,125,167,179, - 46,111,143, 8, 64, 70, 70, 70,221,236,168, 81,229, 30,180, 87,175, 6, 56, 73, 54,127,184, 0,159,109, 63,133,197,143, 62,140, -185, 31,252, 23,143,189,247, 77,187, 76, 30,101, 4,104, 83, 30, 0,202, 94,113,106, 79,168,223, 82, 20, 32,185,201,179, 55, 38, -127, 67,239,223, 26,252,125,253,177,251, 64, 46,198,246, 26, 11,215, 78,110,160,105, 2, 1,209,130,166, 40, 16, 66,160, 35,128, -150, 38,208,106,181, 80, 86,215, 99,199,177, 29, 16,235,196,156, 39,165, 26,175, 10, 72, 91, 48, 14, 83,252, 75,145,121,140,189, - 13,115, 34,128, 43,249, 27,218, 75, 75, 75, 35, 43, 87,174, 68,247,238,221,239, 9,251,146, 18,100,100,100,160, 35,120,254,142, - 22, 2,166,188,127,123,162, 0, 77,207, 68, 36,128,135, 0,188,246, 23,152,252, 7, 0, 66, 0,186, 7, 90, 0, 24,207,250, 79, - 74, 74,106, 30,119, 55, 20, 7,134,239,237,241,224,109,233,200, 29,181, 12,208,156,247,111, 43,241, 51,152,177, 98, 29,126, 4, -240,232,251, 83, 64,178, 22,129,154,181, 26,167, 75,238,128,242,246, 66,241,239, 53,122,239, 95, 40,108,151, 59,212,220,122,127, -123,242, 0,176, 17, 92,108,197,193,250,245,235,213, 0,106,159,143, 28, 92,243,207, 85, 31,171, 95, 93,150,170,234,218,217,247, - 78,209,185,107,221,230,158,251,175, 91,123,175, 26, 49, 71,206,134, 67, 52,220, 87, 20,152,250, 13,251, 34, 0,166,200,159,241, -252, 1, 88,157, 16, 40,145, 72,168,115, 91,207, 39, 42,198,229,231, 36, 13,122, 12, 53,170, 26, 80, 2, 64,159, 82,132,134, 78, - 71, 64,107,181,232,228,236,142, 67,213, 39,113,233,112, 49,162, 35,162,243,237,174,220,146, 23, 0,112, 95, 6,216, 66, 4,116, -191,134,243,229, 1, 54,145,191,161,189, 37, 75,150,144, 53,107,214,192,211,211, 19,119,238,220,193,242,229,203,209,209,194,254, -142, 16, 2,230,188,127, 91,162, 0, 50,153,172, 27, 0,191,166, 27,101, 40,128, 20, 0, 37,127, 17, 39, 93,215,150,198,239, 75, - 30, 0,115, 17,129,213,171, 87, 75,141,133, 66, 82, 82,146,130,171, 61, 67, 34,232, 8, 41,118, 13,189,127,227,229,127,165,165, -165, 45,234,141, 75,214, 62, 70, 4, 76,127,255, 43,144,205,128,207, 92, 57,242,255,249, 24, 30,206,216, 8, 56, 57,161,147, 68, -220, 46,215,107,184,198,223,212,123, 27,243, 0,104, 1, 8,154,218, 86, 96,103,123,220,154, 29, 53,170,236,159,153,219,250, 44, -123,110,114,103,127,191, 72, 53,128, 51, 73, 73, 73, 30, 0,220,108,109,143,123, 36, 29, 75, 30,121,100,151, 65,248,159,219,247, - 45,121,240,134,233,129,217, 10,137,182, 72, 6,100, 14,198,164,207, 68, 4,204, 13,121, 60, 61,235,233,173,219,254,187, 13,186, -217,218, 51, 19,123, 77, 28,220,197,189, 11, 84, 26, 21, 8, 33, 16,139,196,168, 82, 54,224,200,239, 63, 99,253,183, 27, 32, 29, - 32,117, 72,226,176,244,157,115,177, 97,195, 6, 44, 90,196, 61, 7,192, 61, 17, 0,187,200,223,208,222,130, 5, 11,152, 60, 0, -232,200, 99,254,134, 66,192,150,239,218,155, 59,192,240, 49,128,126,189,191, 10,192, 43, 0,142,201,229,114, 29,120,152,171,123, -156, 58,117, 10,153, 25, 75, 91,229, 1,176,152, 8,168,173,242, 0,152,138, 8,152, 35,122, 91,162, 0,246,162,173,150, 1, 50, - 98, 68, 46,151, 35, 47, 47,143, 46, 45, 45, 53, 36, 50,105, 84, 84, 20,103,239,102,198,138,117,128, 65,226,159,137,203,214, 54, -191,175,111,135,155,173,173,188,103,138,162, 62, 2,112, 23,250,229, 63, 79,218,105,238,230,243,145,131, 27,163,243,126,237, 60, -231,205,175, 33,151,203,197,121,121,121,221,209, 50,157,181, 77,237,209,214,145, 0,107,249,253,173,161, 45,134, 4,204,145,191, - 58, 33, 24,216,102,221, 49,147, 14,158, 68,237,251,225, 0, 57, 28,112, 4,227, 70,141, 67, 15,247, 30, 0, 77,240,135,234, 14, - 14,157, 56,132,155, 69, 55, 49, 41,116,146,212,217,217,185,221,219,195, 80, 4, 56,138,172,153, 72,192,131, 50,225,207,222, 44, -128, 14,232, 99, 50, 1,100,130, 7,103,152, 75, 0,100, 82, 0,180, 21, 82, 82, 82, 76,146,189,225, 78,108, 70, 80,176, 89, 85, -224, 40,175,191, 45,150, 1, 54,205,240,215,230,229,229,137,154,134, 14, 24,242,159, 20, 21, 21,197, 41,202,209,180,153,146,194, -209,231,104,110,140,217,209,185,238, 57,194, 25,128, 72, 46,151,191,110, 16, 2,123,202, 94,155,209,175,125, 81, 32,151,203, 39, -228,229,229, 33, 47, 47, 79, 5, 64,210,244,103, 55,241, 51, 81, 0, 91,235,204, 26,201, 79,157, 38,107,113, 28, 87,226,118,196, -144, 64, 90, 90, 26,149,158,156, 78,252, 23,248, 75,209,219,244, 49,101,201,185, 10,182,243, 1, 70,134,141,164, 26, 26, 26, 34, -215,189,191, 14, 1,193, 15, 41, 0,224, 66,225,111,210,248,232, 4,132,134,135,218,220, 30, 99,199,142,165, 54,111,222,220,106, - 85,128, 70,163,177,235, 6,114, 52, 89,255,217,102,251,119, 0,240, 75,252, 76, 68, 1,140,203, 88, 11, 0,107,158, 56, 91, 79, -221,214, 78,145,109, 34, 22,123,137,202,209, 68,199,216,203,203,203, 35,121,121,121, 34,195,250, 10, 12, 12,180,233,183,154, 8, -202,225, 29, 70, 71, 24,251, 54, 1,119, 0,117,250,132,252, 20, 5,192, 5,214,215,247,178,105,143, 43,121,121,121,204,186,178, -154,192,192,192,174,129,129,129,206, 29,161, 46,237,245,196,173,217,118,212,144,128, 85,114, 79,227,118,143,186,186,186,230,207, -154, 58,155,233,188, 49, 58,108,180, 67,206,115,230,204,153, 60,185,254,249,201,222,144,195, 52, 14, 38,127, 9,244,195, 13, 15, -188, 8,176, 90,145,225,225,225,188,106,226,193,131, 7, 15, 30, 60,254, 98, 16,240, 85,192,131, 7, 15, 30, 60,120,240, 2,128, - 7, 15, 30, 60,120,240,224,241, 23,192,255, 3,211,238,250, 72,118, 88, 93,170, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, +137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, + 2, 0, 0, 0, 1, 0, 8, 6, 0, 0, 0,197,144,206,103, 0, 0, 0, 1,115, 82, 71, 66, 0,174,206, 28,233, 0, 0, 0, 6, + 98, 75, 71, 68, 0,255, 0,255, 0,255,160,189,167,147, 0, 0, 0, 9,112, 72, 89,115, 0, 0, 11, 19, 0, 0, 11, 19, 1, 0, +154,156, 24, 0, 0, 0, 7,116, 73, 77, 69, 7,216, 9, 7, 16, 32, 48, 13, 5,217, 84, 0, 0, 32, 0, 73, 68, 65, 84,120,218, +236,125,121, 92, 84, 85,255,255,251,220,217,217, 23, 1, 21,133,193,125, 95,201, 37, 55, 40, 49, 51,205, 52,192,212, 36,219,196, +210,180,178,180,111,249, 60,233, 79,159, 12,148,202,212,132,158, 74,179,210, 18,151,180, 92, 18,116, 80, 83, 82,209, 92,202, 5, + 69, 1, 65,145,101, 86,102,187,115,231,222,223, 31, 51,131, 3, 2,179,128, 73, 61,243,126,113, 95,195, 93,230, 51,231,158,237, +253,249,124,206,231,156, 67,250,245,235,199,193, 3, 15, 60,240,192, 3, 15, 60,248,159, 2,229,201, 2, 15, 60,240,192, 3, 15, + 60,248,223,193,153,223,179, 1, 0,196,227, 1,240,192, 3, 15, 60,240,192, 3,143, 7,192, 3, 15, 60,240,192, 3, 15, 60,240, + 40, 0, 30,120,224,129, 7, 30,120,224,129, 71, 1,240,192, 3, 15, 60,240,192, 3, 15,254, 17,224,219,159,156, 61,123,150,184, + 43,168,190, 88, 2,143, 60,143,188,134,144,145,145,193,173, 95,191,254,129,165,111,234,212,169,220,150, 45, 91,136,167, 60,254, +214,242,208, 4,121,240,228,159, 71,222, 63, 89,158,203, 10,192,255, 56,234,102, 32,105,201,233, 76, 79, 79,199,236,217,179,137, +167,216,220, 47,227,184,184,184,154,243,172,172,172,127, 68, 94, 78,124, 42,185,209,142, 96,215,143, 25,255,232, 58, 35, 9,220, + 9,177,161, 19,162, 64,163, 26,251,144,175, 95,220,146,235,162,167,253,122,208,114, 60, 0,127, 69,101,157, 56,113, 98,204,174, + 93,187,100,118,231,177,187,118,237,202,105, 17, 45,146,179,244,157,132,180,216,118,201, 21, 22, 22, 2, 0,164, 82,233,223,169, + 19,113, 90, 59,157, 58,117,170,211,207,110,217,178,197, 21, 69,141,219,186,117,107,205,201,206,157, 59, 17, 23, 23, 87,235,254, +131, 82, 2,242,242,242, 56, 0,136,142,142, 38,205,241,220,174, 31, 51,238,107,249,133, 71,181, 7, 0,220, 49, 24,192,232,141, +150,139, 74, 53, 0, 32, 33, 33, 1,153,153,153, 13,166,111, 96,193, 64,174,243,237,206, 46,253,248,247,195,191,119,162, 92, 36, + 8,124,245, 2, 12,187,118, 66,161,152, 4, 5,128, 1,146,149, 88, 44, 57,141,246, 98,160,194, 80,128,197,250, 68,151,126, 55, + 33, 33, 33, 38, 51, 51, 83, 86,231, 90,108,102,102,102, 78, 11,107, 91,205, 82,111,255, 38,239,219,236,104, 19, 44, 34, 62, 2, +127, 98, 20, 11, 57,163, 82, 79, 85,235,213,172,214,104,250,159,152, 29,231, 80, 1,176, 18,182,237,179,169, 21,129,219,181,107, + 23,150,110, 93, 14,159,246,254,168,190,169,194,251,137,139,101, 45,220,226,110, 73, 32, 82,169,148, 43, 44, 44, 68, 97, 97, 33, +246,239,223,143,217,179,103,183, 84, 37,192,214,128, 72, 70, 70,134, 32, 57, 57,217,148,154,154,122, 10, 0, 22, 46, 92,248, 80, + 99, 95,156, 52,105, 82,205,255, 12, 99, 6,109, 50,130, 54,210,160,105,203,193, 48, 12, 22, 46, 92,232, 82, 90,236,201,191, 62, + 88,149, 1,238, 65,122, 2, 92, 81,126, 30,152,133, 31,224,135,243,215,191,135, 4,237, 96,198, 49,148,127,113, 6,231, 10,170, + 48,249,195, 13, 78,125,189,243,237,206, 78, 18,186, 5,207,252,250,140,195, 60,145,140, 91,140,160,137, 47,162,244,245, 1,128, + 94, 81,115,253,140,254,109,156, 1, 0, 61, 48, 82,146,128,131,129,167, 17, 0, 96,160, 98,160, 83,117, 38, 51, 51,243,158,139, +118, 4, 73, 90, 80, 27,107,142, 62,224,239,240,190,205,138, 97,125,250,145,103,195,163,248,202,136, 86,188,208,238,225, 20,159, +132, 18,157, 74,197,138, 17,102,166,250,183, 51, 63, 55, 97,140,217, 73, 81,183, 92,248,217,182, 78, 60,179,192, 5,121,105,247, + 85, 1,216,181,107,151,108,235,191,222, 69,226,178, 15,100, 77,172, 4,156,141,248, 1,160, 82, 87, 5, 4, 3,255,119,112, 9, +212,215, 21, 88,247,242,234,150, 70,100, 13,117, 60, 15, 58,141, 53, 74,192,216,177, 99, 81, 88, 88, 8,169, 84,218,226,242, 78, + 38,179,244, 27,177,177,177, 28, 0, 42, 35, 35, 35, 60, 57, 57,185, 52, 53, 53,245,180,179, 66, 24,134, 1, 77,155,106,136,223, +158,252,243,242,242, 16, 29, 29,237, 82,162, 18, 19, 19,237,201, 22, 89, 89, 89,117, 21,128,230,168, 43, 46,151, 67,116,116, 52, +153, 58,117, 42, 55,102,204,152,123,238, 29, 56,112,192,230,233,176,121, 61,156,150,223,156,195, 1,225, 81,237, 81,170, 80, 97, +199,236,167, 17, 76,134,161,224,191,111,161,195,164, 14,200,114,129,252,107, 50,203,234,106, 35,205,224,106, 11,223,122, 12,186, +162,106,148, 38, 71, 53,250,220, 5,113, 54,150,246,190,131, 21, 23,222,107,106,121, 54, 7,233, 54,167, 12, 52,179,172,251,241, +190,205,130,164,164, 36, 47, 0, 15, 3,240,177,187,172, 4,112,126,211,166, 77,114,103,229,124,178,254, 19,138,174, 52, 10,104, +163, 65,172,128, 73, 44, 16,240,249,106,131,152, 18, 10,245, 44,207,207,155,161, 37, 38, 19,191,236,150,241,235, 47, 54, 26,158, +123,105,166,217,153,247, 86, 42,149,255,177,253,159,159,159, 95,233,237,237, 77,105,181, 90,214,254,153, 65,131, 6,125,220,204, +196,190,160,169,121,202,119,100,253, 95,186,116, 9,157,125,252,236,189, 1,238,120, 1,106,200,191, 82, 87,133, 21,143, 46,169, +185,241,252,174, 87,129, 80, 96, 82,106, 34,118, 46,220,234, 74, 37,107,172,115,107,114, 69,189,121,243, 38, 0,160,125,251,246, +181,254,135, 11,238,236,102, 84, 68, 72, 67, 74,128,201,196,216,226, 1,154,197, 10,104,134,188,180, 39,127, 0, 32,201,201,201, + 0,112, 43, 35, 35, 35, 48, 57, 57, 89,225, 52,249,155, 76,160,105, 35,140, 52, 13, 83, 29,242,231, 88,215,138, 33, 49, 49, 17, +121,121,121,119, 91, 87, 90, 26,226,227,227,107,206,183,109,219,214,100,101,199, 78,225,105,114,253,179, 39,254,169, 83,167,162, +127,255,254, 54, 5,192, 85,143, 64,179, 84,194,146,235,197,208,238,252, 55,124, 94, 88,141,240,168,246, 8, 11,150,224,250,206, +235, 22,242, 15,240,179, 12, 1, 8,120,206,105,176,205, 52,198,214,229,226, 53,220,124,127, 57,244,153, 27, 27,247, 16, 72, 36, + 48, 24, 12, 40, 40, 40, 64,185,225, 10,186, 32,188,193,103,173,110,240,198,234, 62,177,181, 19,235,179, 57,110,180, 47, 98,215, +174, 57, 55,219, 25,105,132,184,157,174,131,245,189,111,124,124, 60, 71, 8,177, 13,229, 52,229,125,109,109,153,227,243,249, 77, + 42,243,164,164, 36,127, 0,147, 14, 30, 60,248,111,150,101,141,118,117,137,207,227,241,188,147,146,146, 94,218,180,105,211, 94, +135,140,185,104, 1,191,242, 86,133, 88, 32, 16,121, 83,124,226,199,241, 68, 94, 44,143,199,103, 9, 5,150,240,205, 28,143,103, +228,177,196,160,229,153,117,222, 66, 1,249,226,216, 94,195,220,148,153, 44,138, 29,167, 81,161, 80,168,117, 58, 29, 3, 0, 90, +173,150,125,247,221,119,107, 8,255,131, 15, 62,120,163,169,245,125,244,232,209,179,109,255,103,103,103,167, 55, 71, 27,162, 28, + 89,255,203,167,196,195, 80, 81,129,183,122,118,131,253,216,189,211, 86,200,196,137, 49, 0,106,145,255,196,137, 19, 99, 1,144, +137, 19, 39,198,110,152,248,153,197,179,216,181, 85,173,231,157,193,194,117,249, 88,184, 46, 31,115, 86, 93,194,115,203,254,192, +228,255, 59,219,244,142,174,164,196, 41,197,224,175, 34,127,235,152, 63,215,128, 39, 0, 38,154,198,224, 65,131,154, 67,201,224, +182,110,221,138,173, 91,183, 66, 38,147,213, 28, 46, 42, 60,156, 76, 38, 67,108,108,108, 13,249,219,223, 76, 78, 78, 86, 58,211, + 49, 49,140,217, 98,249, 27, 45,174,255,186,228,111, 54,155,161,213,107, 93,122, 65,155,199,160,174,215, 96,219,182,109,216,182, +109, 91, 45,101,192,165,247,205,169,221, 31, 90,207,155,164, 36,218,200,127,234,212,169, 72, 77, 77,173, 33,127, 1, 95,224, 42, +249,219, 58,240,134, 14,167,161, 71, 49,170, 39, 13, 6,151,249, 22, 74,174, 23,131,155,212,253,110, 38,100,190, 5,126,155, 16, + 32, 32,224, 47,213,140,181,149, 5,208,103,110, 4,199,113,184,112,225, 2, 70,142, 28, 9,137, 68, 82,139,248, 3, 3, 3,161, +215,235,161,215,235, 81, 90, 90,138,105,250,121,248, 34,240,245, 6,101, 58,233,242, 38,117,158,117,149,184,155,203, 88, 33, 13, +144,191,211,117,176,238,251,198,199,199,115,219,182,109, 67,102,102, 38, 18, 18, 18,184,166,190,175,149,252,193, 48,140,219,109, + 34, 41, 41, 73, 12,224,229,236,236,236,119,151, 45, 91,118,130, 16, 34,181, 29, 0,218, 5, 7, 7,123, 29, 58,116,104,125, 82, + 82,210,200,198,228,124,150,190,158,199, 35, 2, 17,205,112,126, 70,163, 41,212,204,178,237,204, 44, 27,101, 38, 36, 2, 60, 94, + 48, 33, 36, 0,132,231,199,114, 8,226,104, 54, 64,173, 55,121,135,250, 49, 60,106,144,198,169, 50,210,233,116, 76, 93,171,191, +165,131,106,140,184,187,116,233,130,206, 62,126,208,149,221,198,227,253, 7,184, 76,208, 54, 37, 98,233,214,229, 0, 80, 67,254, + 54, 47,194,174, 93,187,114,108, 74, 64,137,250, 22, 6, 44, 28,226,146,146,161,213,155,161,213,155,113,187,202,136,210, 10, 3, +110,222, 49,184, 69,124,182,198,226,136,252, 31, 20, 26, 81, 2, 96,160,141, 48, 24, 12, 77, 17,207,201,100, 50,216,198,200, 67, + 66, 66,236,173, 89,184,208,153,212,178,132, 27,113, 37, 58,236,244,104,147,209, 98,249, 27,105,208,166,218,228,111, 50,153,160, +213,106,161, 81,107, 30,116,177,112, 91,183,102,214,126, 37,203, 31,172,215,221,234,240,236,201,223, 70,252, 20, 69, 65, 44, 22, +195,219,199,171, 73, 9,158,248, 84, 50,215,208,225,232,187,251,255,111, 9,130, 49, 12,204,232,215, 0, 0, 62,185,215,112,174, +160,202,210,201,143,126, 13,166, 11, 75,129,202, 42,215, 50,208, 10,119,223,199, 27,149, 0,128,141, 27, 55, 98,215,174, 93, 88, +185,114, 37, 78,158, 60, 9,163,209,136,242,242,114,155, 85, 86,243,124,120,120, 56,244, 0,120,184,241, 64,234, 75, 35,245,158, + 52, 65,105, 36,141,120,240, 92,150,105,239, 9,171, 47, 38,192, 29,242, 7, 0,119,149,128,164,164,164,214, 86,242,159,245,245, +215, 95, 95, 92,188,120,241, 83,155, 55,111, 70,151, 46, 93, 0, 0,145,145,145, 80,169, 84,162,165, 75,151,158, 62,116,232,208, +183, 73, 73, 73,210, 6,115,137,229, 8, 88, 70,108, 54, 51, 65,102,198,220,206,100, 54,117,226, 81,164,173,144, 79, 9,196, 2, +158,158,239, 37, 84,122,251,242,212, 60, 49,199,136,121, 60,111, 62, 67,251,221, 56,243,187,104, 70,200, 39, 14,211,157,159,159, + 95,169,213,106,217,250,220,252,125,251,246,189, 66,211,116,179, 85,164,190,125,251, 54,155, 44,126, 99,196,253,223, 89, 47,222, + 37,219,146,155,120,171,103, 55,172,178, 16,180, 75, 90,171,205,250,183,145,126,157,223,169, 57, 15,238,221,218,165,196, 87,235, +205,208,232, 24,168,181, 12, 84,213, 12,148, 26,198,245, 86, 89, 79,228,191,189,149,111,255,255,245,235,215,161, 84, 42,255,178, + 30, 35, 61, 61, 29, 82,169, 20,182,160,191, 58, 99,253, 92,122,122, 58, 12,122,125, 83, 20, 0,110,195,134, 13, 40, 41, 45,133, +128,199, 67, 88,235,214,181,200,255,209, 71, 31,197,193,131, 7,157,237,156, 72,108,108,108, 93, 37,160,150, 39,195,217, 88, 5, +218, 72,131, 54, 26, 97, 50,209, 96, 24,115, 13,249, 27,141, 70,232,116, 58, 84, 87, 87, 67,163,113, 93, 1,176, 31, 2,176,193, + 93,203,127,107,230, 86,128, 3, 42,173, 68, 99, 29,212, 6,225, 56,139, 18,144,153,137, 68,139, 5,229, 82, 91,169, 75,254, 2, +129, 0, 34,145, 8, 98,177, 24, 98,177,184,201,117,170,161, 33,129,250,230,197,219, 99,114,250,118,112, 79, 70,225,206,208, 1, + 8,198, 48, 72,158, 94, 3,230,118, 5, 16,224, 7,126,213, 22,252,252,201,105,128,199,115, 41, 45, 77, 29, 10,208,242, 44,125, +202,138, 21, 43, 80, 81, 81,129,245,235,215,163,111,223,190, 88,182,108, 25, 6, 12, 24, 0,189, 94, 95,215, 66,179,169,212,127, + 53,241, 59, 75,208,238, 14, 7, 52,164, 72,184, 44,199, 58,139,163,166,109,184, 59, 52,102, 79,254, 53,100, 99, 85, 2, 92, 28, + 14,240, 61,127,254,252,167,175,188,242,202,145,222,189,123,251, 1,192,146, 37, 75,144,159,159, 15, 0, 24, 50,100, 8,118,236, +216,129,225,195,135,123, 79,155, 54,173, 32, 39, 39, 39,251,249,231,159,159,246,251,239,191,223,147,179, 65,193, 65,236,245,235, + 5, 76,142,236,224,190, 78,157, 58,231, 68, 69, 74, 47,242,124, 37,229, 60, 34,212, 82, 34,129,142, 18,123,105,104, 62,143, 6, +103,226,177, 98,147,175,166,180,202,231,228,161,179,131, 90, 5,134,237,112,168,140,218,141,249,239,220,185,243,185, 73,147, 38, +125,109,115,251,171,213,106, 74, 40, 20, 54,185, 34,217,220,254,217,217,217,247,215, 3, 96,179,242,163, 59,118,134,161,162, 2, +218, 18, 11, 9,142,180, 90,135,174,122, 1,174,255,113,237, 30,217,245,157, 87, 93, 40,115, 41,241, 77, 37,127,123,226,231, 56, +206, 54,198, 95, 3,147,201, 84,115, 40,149, 74,104,181, 90,200,229,242,191,172,231,176,205,243,223,191,127,127, 93, 79, 0,151, +158,158,142, 62,125,250,192, 96,208,215,116,116,233,233,233, 46,185,235,215,125,182, 14, 38,147, 9,237,194,195, 97, 50,155, 27, + 34,127, 87, 58, 18, 82,143,235,191,102,234, 98, 99,158,140,123, 20, 0,218, 84, 67,254,167, 78,158,130, 78,175,135, 70,163,129, + 74,165,130, 82,169,172,101,217,185, 10,219, 48, 64, 19,198,253, 81, 85, 89,133,170,170, 74, 84, 86,201, 81, 89, 85,133,170,170, + 42, 84, 85, 90, 44,210,110,221,187, 67,110,253,223, 85,235, 31, 0,250,247,239,127,215,234,247,246,134,143,143, 47,124,125,124, +161,209,104, 98,155, 72,254,110, 15, 7, 20,172,156, 5,193,211,107, 16,140, 97,224,231,174,129,105,251,107, 64,128, 31,118,191, + 26,143,162,221, 55, 48, 33,117, 19,192,255,139,151, 21, 49, 20, 65, 18, 46,129, 86,171,133,193, 96,128, 78,167, 67,110,110, 46, + 62,252,240,195,122, 31,247,242,178,121, 80,174,185, 67,222,238, 90,213,246,249, 75,156, 60,111,138,146,225,106,155,173, 37, 39, + 51, 51,147, 36, 36, 36,216,200,223,109,207, 4,159,207, 39, 12,195,212, 85, 10,224,106, 44,192,166, 77,155,174, 38, 36, 36,244, +221,188,121,243,200,163, 71,143,250,142, 30, 61,250,164,141,252,173, 6, 36, 68, 34, 17, 87, 84, 84, 36,216,183,111, 95,215,192, +192,192, 83,195,134, 13, 43,168, 79,214, 51, 83,158, 97, 59, 71,117,209, 12, 25, 50, 36,254,226,197, 63, 31, 81,107, 53,173, 57, +198,196,128,130,137, 49, 82, 70,163,209,168, 87,163, 76,205, 26, 13,154,210,226, 50,230,231, 61,123, 83, 90, 5,135,148,211,180, +206,161,249, 94,159,245,175, 80, 40,248, 0,224,231,231,215, 98,135, 5,168,134,172,255,173,255,122,215,162, 53,151,221,174,117, +207,213, 88,128,137, 19, 39,198,174,123,121, 53, 0, 75,192,223,174, 93,187,100, 54,210,183,173, 9, 16,247,205, 83, 0,128, 51, +169,191,217,226, 3,254, 42,212, 84,198,146,146,146, 26,107,223, 70,250,118,133, 11,141, 70, 3,131,193, 96,215,137,252,117,105, +156, 61,219, 18,251, 97, 98, 24, 92,188,120, 17,191,159, 57,131,190,125,250,194, 96, 48, 64,175, 55,192,160,215,227,219,111,190, +129,237, 57,103, 26,122, 90, 90, 26,122,116,239, 1,147,201,132,171, 87,175,130, 49,209, 40, 45, 41,109,214, 60,181,157, 91,215, + 44,176,173, 93,224,216, 3, 96, 50,130, 49, 91,220,254, 39, 78,252, 6,173, 94,139,106,141, 26, 42,149, 10, 10,165, 18, 10,133, +188, 73,138,152,205, 19,224,166,245, 15, 0, 56,114,228, 8, 52, 26, 13, 52, 26,181,245, 83,131, 86,193,193,232,214,189, 59, 46, + 95,186,132,195, 71,142,184, 44,211,102,253,243,249, 2,120,121,121,193,199,199, 7,190, 62, 62,240,241,241,130, 92, 33,143, 77, + 78, 78,206,113,170,205, 53,193,213,223, 16,206, 21, 84,193,116, 97, 41,170,112, 12,100,220, 42,144, 97,255, 70,193,202, 89,120, + 50,245,107,136, 5, 20, 32,224, 91, 14,119, 88,199,205,161,128,210,241,159, 33,104,203,120,232,116, 58, 4, 5, 5, 65,161, 80, + 64,161, 80,224,248,241,227,184,125,251,118,141,155,184,230,249,210, 82,188, 26, 40, 65, 43,175,138,198, 44,224, 88,123, 82, 77, + 72, 72,136,177,187, 23, 83,231, 94,172,139,237,130,107,132,192,155, 99, 70,129,203,150,127,125,239,155,153,153, 73,182,109,219, + 70,154,248,190,181,148, 0,119,200,223,134,247,222,123,239,252, 83, 79, 61, 53,109,197,138, 21, 93,207,157, 59, 55, 76, 34,145, +240,158,124,242, 73, 34, 18,137,192,178, 44, 25, 55,110,220,249,249,243,231,247,233,213,171,215,238,151, 94,122,233,185,151, 94, +122,169,193,177,168,228, 57,201,236,159,151,174,158,234,213,187,207,179,167, 78,158,156,188,123,207, 79, 31,228,157, 60,217,250, + 98,254,101,241,213,210, 2,238,219,213, 63, 72, 86,164,173,236,145,189,103, 79, 90,167,142,157,126,246, 9,243, 62,178,105,211, + 38,179,179, 57, 58,122,244,104,156, 58,117,170, 95,122,122,250, 82,131,193, 32, 88,182,108,217, 71,187,119,239,158, 90, 90, 90, +250,151, 19,135, 83,101,212,208,141,224, 27,133,144, 3, 53,214,191, 13, 35, 67, 66,176, 10,151,157,183, 58,172, 46,254,203,167, + 47, 34,160,107, 43,196,125,243, 20,118,205,248, 81,102,211,222,108,228,111,179,254, 93,153,101,176, 99, 69,191,230, 97, 88, 66, +112,233,210, 37,216, 42,107, 93,247,178, 64, 32,128, 64, 32, 64, 69, 69, 5,198,141, 27,247, 32,202,137, 72,165, 82, 46, 61, 61, + 29,131, 6, 13,130,193,104,132,222,160,135,193, 26,220,164, 55, 88,134, 1,214,174, 93,139,185,115,231, 58,234, 76,184,212,212, + 84,152,205,102,156, 62,125, 6, 2,190,197,109,219,185,115,103,220, 40, 44, 68,105,105, 41,182,108,249, 30, 83,167, 62, 3, 0, + 92, 29, 79, 64,131, 29, 80, 70, 70,134, 16, 0,147,156,156,204,214,103, 1,185, 50, 85,209,102,249,231,230,230, 66, 91,173,171, + 81,192,212, 26, 53,212,106, 21,212,106,247,134, 0,236,173,255,169, 83,167,214,120, 0, 92, 85, 4,166, 78,157, 90,235, 60, 74, + 42, 69,183,238,150,160,184,203,151, 46,225,134,213,227, 49,117,234, 84,151,163,246,135, 62, 60, 20, 34,161, 8, 18,137, 4, 98, +177, 24, 34,145, 8,101,101,101, 78,147,191,157,181,223,172, 21,112,242,135, 27,176, 3,192,216, 21, 79,128,203,124, 11, 36, 49, + 13,231, 10,170, 64,130, 2,113,173, 68,109,177,254, 93, 28, 2,176,107,127,196,166, 8,216,159, 59,132, 94, 15,240, 44,198,222, + 93,247,190,133,232, 77, 38, 19,190,248,226, 11,140, 28,121, 55, 46,236,224,204,112,160, 92,135,174,123, 21,232, 23, 18, 89,175, +200,122,162,220,237,135, 60,101, 14,158,117,150,176, 73, 19, 60, 10,141,121, 35, 92, 86, 36,238,247,251, 90,149,128, 38,207, 2, + 88,177, 98,197,150,121,243,230,133,156, 61,127, 62, 81,175,215,247,145,201, 14, 73, 68, 98, 17,159, 34, 20, 14, 29, 58,228,219, +163, 71,143, 77, 9, 9, 9,255,158, 60,121,178, 67,107, 61,231,208, 1,118,194, 83, 19, 14,247,237,219,127, 33,205, 24,199, 94, +203,191,250, 1, 91, 88,192, 0,224,196,160, 76,189, 59,117,205, 12, 13, 13,217,203,227, 11,191,253,207,226, 20,250,147,101, 31, + 59, 44,165, 65,131, 6,125, 60,122,244,104, 0, 64, 69, 69, 5,178,179,179,253,190,250,234,171, 15, 0,224,212,169, 83,131,122, +246,236,185,255,111,161, 0,216, 22,254,121,244,219,205,142, 44,123, 87,166, 4,146,157, 11,183,114, 3, 22, 14, 65,112,239,214, + 53,164, 95,227, 78,189, 80,134, 51,169,191,185,234,182,106,174, 57,169, 4, 0,215,189,123,119, 92,184,112,161, 22,177, 40,149, +202, 2, 0, 29, 93,212,230,239,167, 39,224,158,223,252,246,155,111, 97, 48, 24, 96,164,141,160,105, 26,169,169,169,141, 45,146, +195,165,166,166,214,156,176,172, 25, 98,137, 15,244,122, 3, 46, 93,188, 8,190, 64, 0, 19, 77,195,203,219, 11, 91,182,108, 1, +143,199, 67, 98, 98, 34, 30,125,244, 81,174,170,170,225, 0,175,212,212,212,253,201,201,201,116, 70, 70, 70,168, 45,111,234,172, + 3,224,146,107,115,225,194,133, 56,118,236, 24,170,171,171, 81,173,213, 66,163, 86, 91,201, 95, 13,141, 90,131,106, 77, 53,180, +118, 29,190, 51,121, 23, 29, 29,205,229,229,229,213, 88,255,245, 77, 3,116,118, 17, 32,235, 92,252, 90,101, 97, 35,125,219,216, +163, 43,171, 20,218, 86,248, 3, 0, 31, 47, 31,136, 37, 98,104, 52,154, 88,219,208,142, 27,228,127, 95,230,107,219,148,128, 73, + 43,190, 2,183, 29,104, 53, 51, 3, 57,175,199, 99,120,202,119,128, 64, 0,111,113,211,198, 57,235, 42, 2, 0, 48,245,216, 84, + 7,223,186,131,222,251,189, 80,246,147, 14,138,229,119,175,154, 76, 38,140, 24, 49, 2, 0, 16, 30, 40,193,175, 25,237,177,242, +195,155,248,236,140,222,145, 69,108, 63, 45, 14, 13,253,111,247,108,142, 27,125, 86,115,205,173,111,142, 49,255,251,249,190, 53, + 74, 64,115,212,191, 79, 63,253,244,211,231,103, 62,191,239,161,129,209,131, 52,106,117, 16, 99,102,140, 97, 97, 97, 21,225,225, +225,101,106,181,250,220,228,201,147,157,238, 20,126,250,241, 39, 22,192,150,103,167,191,152, 59,108,248,240, 31, 37, 18,137, 63, + 1,199, 18, 66,192,178,156, 74,175, 85,200,174,156, 47,214,120,139,132, 78,245,243, 54,242, 7, 44,129,212,117, 3,245, 62,252, +240,195,127,255, 45, 20, 0, 43,169, 59, 44,176, 93,187,118,185, 92, 89,207,164,254,198, 1,128, 77, 17,176, 35,254,230, 36,116, +183, 27, 82,239,222,189,113,234,212, 41, 84, 84,212,184, 8, 59, 2,128,141,252,102,204,152,241,160,203,171, 86, 30,165,167,167, +115,207,206,120, 22,107,215,174,179,142,153, 51, 88,184,112, 97,163,211,151, 92, 92, 65,207, 98, 57, 29, 60,232,104,179,137,238, +169,169,169, 87,147,147,147,203, 51, 50, 50,120,201,201,201, 53, 1,129,214,105,129, 78,119,116, 54,139,121,216,176, 97,205,158, +119,209,209,209,156,189, 21,111, 31, 3,224,198, 10,128, 4, 0,183,101,203,150,123,172,124,171,135,192,229,250,188,101,203, 22, +226,170,199,192, 25, 52,230,250,119, 85, 89,152,252,225, 6,192,110,225,159, 81,239,222,157,142,172,109,174,130,178,243, 0, 56, + 90, 9,176,116, 88, 41, 74, 1, 12, 88, 25,136,229,167,187, 32, 4, 64, 69,129, 22,157, 58,117,178,144,198,242, 64, 60,246, 80, + 8,162, 30,203,119,214, 34,118,122,120,211,250, 44,113,183,191,105,166, 62,175, 73,178,254,162,247,109, 54,108,216,184,225, 42, +128,171,205, 37,239,219,239,190, 44, 68, 51, 68,133, 54,103, 96,158, 21, 11,254,138,252,252,171, 55, 3, 34, 19, 39, 78,140,217, +149,218, 34,247, 2, 32, 0,184,135, 30,122, 8,123,247,238, 53, 88, 73,159, 5,224,117,159, 60, 15, 77,134, 45, 72,112,238,220, + 57,156,213,242,127, 32,105, 91,184,112, 97,100,125,110, 73,187,105,132,174, 88, 59,228, 62,151,113, 77,122,154,186,236,111, 67, +171,242,185, 74,226,142,214,246,111, 14, 52,101, 72, 96,209,162, 69,184,126,253,122,179,165,197,153,229,125, 93,197,153,183, 21, + 56, 3, 75, 96,232,200, 4, 9,126, 57,209, 5, 97, 94, 62,248, 51,239, 14,186, 58, 73,254, 78,212,191,150,186, 28, 46,185, 79, +223,245, 44,207,238, 28,218, 54,179,188,180,191, 42,225,127,249,110,128,117, 61, 12,110,120, 18,238,187, 18, 48,110,220, 56,241, +223,172, 2,186,101,217, 55,215,111,103,100,100,216, 86,168, 97,146,147,147,155, 58,149,201,131,230, 39,255, 38,149, 69, 74, 74, + 74,179,148,101, 70, 70, 6, 63,121,120,242,125,175, 23, 71, 50,245, 56,146,153,223,226,219,172,167,102,122,240,192, 43,161,187, +251, 8,123,224,129, 7, 30,120,224,129, 7,127, 95, 80,158, 44,240,192, 3, 15, 60,240,192, 3,143, 2,224,129, 7, 30,120,224, +129, 7, 30,120, 20, 0, 15, 60,240,192, 3, 15, 60,240,192,163, 0,120,224,129, 7, 30,120,224,129, 7,255, 8,212,154, 5,112, +246,236, 89,183, 35, 83,235, 11, 38,244,200,243,200,243,200,243,200,115, 82, 94,163,211, 68, 91,128, 60, 79,249,122,228,213,194, + 43,175,188,210, 14,128, 2,128,208,186,213,121,139, 74,159,199, 3,224,129, 7, 30,192,223,223,159,242,247,247, 39,254,254,254, + 2, 0,188,150,150, 62,219,190,243,118,251,207, 55, 21,245,173,143,239, 65, 11,194, 19, 79, 60, 17,243, 15,120, 13,219,218, 87, +146,191,235, 11,120, 20,128,127, 56,154,176,221,186,203,136,139,139,139,177,118,186, 53,135,245,218, 63, 82, 94, 11, 7,137, 12, + 11, 35, 0,160, 82,169, 88,149, 74,197,169, 84, 42, 19, 0,179, 59,194, 94,126,172,119,201,172,177,189, 39, 2,192,172,177,189, +191,121,249,177,222,235, 0, 96,225,164,135,200,194,167,163, 5, 47,143,233,229,214,154, 34,246, 75,209,102,102,102,214,218,124, +167, 41,228,111, 87,239,155,115,173,253,166,202,108, 14,121,220,125, 80,108,254, 82, 69,233,137, 39,158,136,217,187,119,175,236, + 31,208,198, 12,176, 44, 22,119, 95,121,180, 77,176,136,234,220, 58,148, 31, 33,109, 71,133, 5, 4, 11,189, 69,130,102,251, 61, + 62,254, 25,160,172, 90,152,222, 90, 32, 30,216, 41, 0, 78,236,173, 98, 4, 32,106,234, 79,101,101,101, 33, 45, 45,173,214,242, +127, 11, 22, 44,176, 53,116,226,142, 60,246,135,192,218, 5, 61, 37,171,165,200,107,241, 69, 31,229, 45,225,162, 58, 72, 1, 0, +101, 52, 51,189,181,144,255,157,237,230,101,117,181,168,172,178,146,118, 70,208, 75, 99,122,229,155,205, 92,248,195, 67, 91,249, +117,237, 58,236,128, 72, 68, 21,205, 73, 25,244,159,255,146, 11,184,163,210, 61, 33,224,147,159, 0,114, 17, 64, 79, 87, 19, 89, +119, 41,218, 38, 46, 55, 91,139,252,237,234,190,187, 75,229, 18, 23,175,223,119,121, 9, 9, 9,182, 53,250, 29,190, 83, 66, 66, + 2,151,153,153, 73, 92,200, 59,210, 12,114,156, 34,127,150,101, 65, 8,193,200,145, 35,185, 35, 71,142, 16, 23,203, 88, 8,192, +212, 28,233, 9, 10, 10,154, 37,151,203, 63,119,243,235,126, 0,148,104,190, 85,176,107, 97, 88,159,126,212,179,225, 81, 98,101, + 68, 43, 97,104,247,112, 62,159,132, 82, 58,149,138, 17, 35,140,166,250,183,163,159,155, 48,134,110,234,111, 56,171, 73,132, 0, +120,220,250,217,210,224, 7,224, 41, 0,233,214, 79,191,102,146,251,125, 75,179,176,221, 42, 96,202, 97, 17, 15,178, 54,168,208, +166,144,205,252,249,243,239, 33,127, 0, 72, 75, 75,139,157, 63,127,190,203, 86,206,198,215,188,239, 33,107, 0, 96,127, 8,196, +198,215,188, 31,168,188,212,212,212, 24,138,162,184,103,158,185,187,164,237, 43,175,188, 18, 3,128,139,136,136,224,218,181,107, +199, 5, 7, 7,115, 79, 63,253,180, 83, 50, 55,164,126, 20,115,156, 26,194, 45,141,142,175,177,126,215, 45, 93, 23, 51, 15,171, +185, 57, 17, 27,184, 25,237,182,114,227,131,247,115,131, 58, 44,115,202, 58,238,208, 46,172,117, 76, 7, 41,247,218,156, 25,198, +229,111,189,200, 45,124, 97, 26, 90, 11,249,223,189, 59,251, 89,172,124,227,101,110,217,220, 23,216,110,126, 62, 70, 0,104,221, + 58,152,111, 45,255,122,113,102,231,211,157,195,195,189, 2,158,153, 18,153, 54,113, 82,123, 1,203,177,210,144, 86, 34,239,143, + 95, 63,145, 54,239,169,126,223, 62,254, 88,155,200,136, 8,239,226,127, 47,238,237,238, 54,153,246, 27, 69,185,180,105,148, 3, +203, 31,205,224, 9,104,113, 30,128,204,204, 76,146,144,144, 80,243,189,132,132, 4,174,190,161, 19, 43,105, 59,173, 84, 52,148, + 14, 59, 57, 77,238,232,236,201,127,193,130, 5, 24, 57,114, 36,247,235,175,191,186, 35,138,110, 70,227,181, 44, 40, 40,104,146, +155,223, 13,183, 26,156, 82, 0, 72, 74, 74,138, 76, 74, 74,218,147,148,148,148,107,119,236, 76, 74, 74,114,105, 27,229, 79,214, +127,194, 79, 93,150,226,247,248,147,147,194, 21, 3,123,118,224,183, 13,239,168, 54,136, 59, 86,155,245,237,137,159,119, 91, 58, +204, 20,198,148,221, 10,248,250,139,141, 66, 23,121,220, 45, 5,160, 61,128,111, 0,196, 91, 63,219,183, 32,126, 11, 6,176,197, +170,156, 28, 7, 48,214,122, 30,220, 12,178,167,192,137,241,210,150,174, 0, 56,129, 33, 0,174, 0,136,114,199,186,177,185,208, + 35, 34, 34, 98,237,173,126, 59,203,191,230,158, 51,238,118,219, 51, 73,195,133,118, 86,186, 2,212, 20, 69,205,185,237,222,131, +144, 7, 0, 39, 78,156,144,137,197, 98,228,230,230,222,163,108, 21, 23, 23,147,146,146, 18, 50,100,200,144,216, 61,123,246, 56, +149,135,173, 79, 92,148,113, 98, 1,250, 84, 8,107, 89,195,132,226,176,174,248,121,242, 77, 73, 34,145,142,189, 16,203,220, 26, +239,208,109, 26,211, 65,202, 69, 8, 37,183,223,124,117,186,177,157,143, 80,168,186,120,140,120,149,159,199,188, 17,157,209, 54, + 64,130,242, 51, 71,201,157,211,199,168, 5,179,102,208, 49, 29,164, 92, 55, 47, 95,147,181, 67,173, 23,173, 90, 9, 71, 9,133, +148,248,248,241,219,243, 79,157,188,213, 61,172, 93, 7, 83, 64,171,118,196,215, 23, 94, 29,162,188,162,130,130, 68,157, 88,142, + 51,254,124,178, 92,251, 0,235, 48,103,111,241,219, 14, 55,149, 0,174,158,207,186, 71,125,207,253, 85,242,106,148, 0,185,124, + 52, 50, 50, 20,104, 10,249, 55,166, 84,212,145,211, 36, 15,192, 19, 79, 60, 17,179,103,207, 30, 25, 33, 4, 20, 69, 33, 47, 47, + 15, 71,143, 30,117, 75,150,217,108, 62,111,245, 0, 52, 71, 60,139, 68, 46,151,239, 12, 10, 10,122,218,141,239,218, 60,206,154, +164,164,164, 94, 0, 14, 28, 60,120,112, 92, 86, 86,214, 16,219,145,157,157,253,148, 76, 38, 59,148,148,148,228,212,144,199,130, + 69, 11,196,149,183, 42,130,245,156, 49,130,227,147,110,156, 72,212,157, 21, 8,187,179,132,234,204, 18,126, 39,134,199,139,100, + 89, 18,174, 37,230, 80, 70, 72, 5,126,113,108,175, 88,252,100,232,125, 85, 0, 62, 1,112, 16,192, 60,235,231, 39, 77,200,236, + 64, 0, 75, 0,236,177, 86,244, 61,214,243, 64, 55,229, 29, 1,176, 23, 64, 50,128,245, 0,222,176,202, 60,210,196, 74,225,111, +253,244,110, 6, 11, 27, 86, 11,107, 73, 99,150,214, 3,196, 67, 0,142, 1,104,109, 85,158,158,117,229,203, 89, 89, 89, 50,123, +203,127,193,130, 5,178,180,180,180,216,180,180,180, 88,123, 37, 32, 45, 45, 45, 54, 43, 43, 75,230,140, 60,123, 75,157,154,162, +192,213,189, 51,112,117,239,140, 90,164,205,254, 16, 8,119,229,217, 44, 77,119,228,165,167,167,199, 28, 63,126, 28,211,167, 79, + 71,113,113, 49,146,147,147, 99,234,123, 70, 44, 22,203,218,180,105,227, 48,255, 50,210,211, 99,218, 28,255, 3, 37,211,135, 65, + 88,172,194,231, 75, 62,142,169,109, 28, 3,233,233, 25, 49, 2, 67,132, 44,168,141,222, 33,249,207,122,105, 10,253,175,249, 51, + 56, 97,209, 25, 97,224,157, 11,228,194,109, 53,194, 67,188,241,112,143, 48,180, 85, 94,193,117,141, 30,124,150, 67, 0,225, 9, +254,239,197,233,220,107,175,188,112, 37,166,131,180, 65,210, 81, 40, 53, 65,131, 6,249,164,245, 30,242,184,201, 55,168,163,200, + 39, 32,148,149,248,120, 27,131, 90, 5, 27, 66,194,219,243, 21,114,141, 72,173, 98,160, 80, 25, 93,113, 99,199, 56, 67,156, 78, +198, 3,220, 99,249,215,167,148,187,160, 4,144,122, 62,235, 30,245, 61,231,148, 60,110,107,224, 61,135,139,242, 26,202,211, 38, +145,118, 93,165, 34, 35, 67,129,230, 34,127,138,162,184,125,251,246,201, 88,150,197,235,175,191, 14, 66, 8,142, 30, 61, 10,203, +214,187, 44,113, 67, 30,104,154,254, 29, 0,211, 12,158, 0, 57, 0,200,229,242,237, 65, 65, 65,177, 46,126,151, 15, 0, 51,103, +206, 20, 1,200,202,206,206,238,178,108,217, 50,166,174, 18, 26, 28, 28,140, 67,135, 14,197, 36, 37, 37, 57,212,202,120, 68,224, + 71, 51, 92, 91,163,209,212,197,204,178,189,204, 44, 59,192, 76, 72, 47,240,120,237, 9, 33,109, 64,120, 97, 44,135, 8,142,102, +219,169,245,166,144, 80, 63, 70, 72, 13,210,220, 55, 5, 32,220,106,241,175,132,101,156, 99,165,245, 60,220,141,223,154, 1,160, +216, 90,153, 22, 1, 8,178,126, 18,235,117, 87,247,218,253, 55,128,107, 0,214, 1, 16,192, 50,134,205, 0,248,204,122,189, 41, +251, 47,143, 4, 80, 1, 96, 84, 51,145,236, 11, 0,222,183,126,182, 52,244, 4,240, 35,128, 71,173,158,148,158,238, 10,178,145, +191, 61,233,219, 43, 1, 46, 87, 78, 43,249,219, 80, 87, 9,112, 71, 94,157,206,140,184, 42,239,240,225,195,160,105, 26, 3, 7, + 14,140,237,214,173, 27, 10, 11, 11,107,222,143,101, 89, 72,165, 82,110,241,226,197,178,227,199,143, 99,220,184,113, 14, 59, 20, + 67,238, 41, 80, 52, 3,229, 64,105,172,177, 91, 48,174,109, 56,124,151,180, 88, 14,115,164, 27,184,195,139,131,101, 55,142,251, + 35,238,249,171,142, 59, 40,138, 87, 93,113, 33,151, 45, 83, 26, 80, 85, 77,115,241,253, 34, 56,127,137, 16,183,148, 90, 84,168, +244, 72,236, 31,193, 81,132,112,191,253,180, 31,170, 35, 39,184, 51, 59,127, 46,106, 76, 92,238,239,109,231,132,132,250,117,108, + 27, 17,197,120, 73,216,142, 35, 31, 79,244,233, 48, 48,121,124,235, 46, 79,198, 5,181,141,238, 43,175,110, 29,111,162, 77,166, +235, 5, 90,167,134,222,172, 4,229, 84,157,200,204,204,148, 57,152, 25, 80,239, 61, 39, 98, 94,254, 17,179, 3,146,147, 3,145, +156,124, 87,185,181, 17,119,115,144,118, 61, 10,140,219,150, 63,199,113, 48,153,238, 14,217, 15, 31, 62,220,214, 94,220,149,109, + 18, 8, 4, 38,150,101,143, 91, 61, 1, 77, 81, 2,106,134, 62,229,114,185, 44, 40, 40, 40,217,133,239, 22, 38, 38, 38,250, 29, + 62,124,120, 69,118,118,118,235,175,191,254,154, 93,188,120, 49,127,243,230,205,232,210,165, 11, 0, 32, 50, 50, 18, 42,149, 10, + 75,151, 46, 53, 31, 58,116, 40, 62, 41, 41,233,213, 70, 37,178,140,191,217,204, 68,154, 25,115, 79,147,217,212,159, 71,145, 40, + 33,159, 18,137, 5, 60, 53,223, 75,120,219,219,151,119,135, 39,230,140, 98, 30, 47,136,207,208,109,110,156,249,221,119, 70,200, + 39,110,199,189, 57, 82, 0, 30,179, 90,135,246, 56,102,189,238, 10,166, 1,120, 29,150,177,146,247, 1,252, 1,203,252,201, 63, +172,231, 82,235,253,105, 78,202,243, 2, 48, 11, 64,146,245,220,104,119,192,122,125, 22,238,221,202,215, 89, 76, 1,240,149,245, +179,169,120, 30,192, 28,107,158,205,177,158,183, 20,116,178,186,176,126, 6, 48, 23,192,108, 0, 49,240,160, 65,148,150,150,202, + 6, 15, 30,140,217,179,103,231, 12, 30, 60, 24, 39, 78,156,192,250,245,235, 99, 90,183,110, 45,163, 40, 10,133,133,133,164,178, +178,146,188,246,218,107,177, 71,142, 28,145,189,244,210, 75,141,146,205,208, 27,183,100,101,131,187, 35,121,246,236,156, 63,195, +204,177, 61, 85, 65,178,140,245, 25, 49, 22,237, 4, 88, 87,248, 60,217, 82, 25, 79, 70,190, 86, 26,123, 52, 83, 42,139,125,120, +101,131,229, 83, 66, 51,171, 62,255,124,115,208,246,243,165, 55, 55,159, 41, 86,110, 56,126, 93,123,163,204,192, 81, 28, 5,131, +206,140,138, 10, 26,121,197, 10,243,174,194, 82,205,158, 91,101,202, 29, 69, 37,151,143,149,149,143,185,105, 52,125,212,144, 76, +191,192,240,118,250,106, 69,219, 30,209,143, 80, 52,137, 28, 89,122,249, 71,125, 96,144,183,164, 67,247,126, 21, 28, 83,113,158, +240,252, 66, 88,150,229,221,185,163,119,198,139, 87,215, 53, 93,159, 27,188, 86,148,187, 19,227,207,164,174,165,111, 59,238, 7, +161,181, 20, 52, 22,148,103,231,206,111, 18,154, 67, 78,117,117,181, 12, 0,248,124, 62,222,122,235, 45,228,229,229,193,205,113, +127,123, 24, 1, 24,141, 70,163,177,180,180, 52, 11, 77, 11, 8,212,212,114, 7,200,229, 25, 65, 65, 65, 19,156,245, 20, 27, 12, +134,254, 11, 23, 46,124,242,149, 87, 94,225,122,247,238, 77, 0, 96,201,146, 37,200,207,183,236, 70, 57,100,200, 16,176, 44,139, +225,195,135, 83,211,166, 77,227, 46, 95,190,188,238,249,231,159,127,222,203,171,126,106, 98, 89,206,144,115,240,224,182,194,194, +235,207,155, 77,230, 48,158, 64, 98,224, 17,177,138, 18, 9, 85,148,216,171,156, 22,120, 85,130, 18,221,102,197,102,131, 70, 85, +213, 74,182,251,236,123,230, 83,191,187, 29,247,230, 72, 1, 24, 3,224, 80,157,107,135,172,215,157, 5, 15,192,187, 0, 18, 1, + 84, 53,240, 76,149,245,254,187,112,110, 92,103, 26,128, 3, 0, 84, 13,220, 87, 89,239, 79,115, 35, 79, 30,129, 37,134,224, 67, +235,231, 35, 77,168, 92,241, 86,175,201, 16,107,122,134, 88,207,227, 93,148, 19, 8, 32,192,137,195,213,161,148,161, 0,157, 16, + 39,240, 0, 0, 32, 0, 73, 68, 65, 84, 78,226,110, 4,112,145,213,211,227, 86,156, 71, 93,139,191,174, 71,192, 85,176, 63, 4, +162,243,184,111,106,206, 59,143,251,166,222, 64, 62, 87,228,213, 33, 19,206, 21,121,107,215,174,229,242,242,242,112,250,244,105, +180,107,215,142,251,229,151, 95,160, 86,171,113,233,210,165,123, 44,218,119,223,125, 55,167, 71,143, 30,177, 91,183,110,109, 80, +222, 23,107,215,114,237,243, 46, 32,244,116, 62,100,237,198,113,189,175, 48, 50, 74,109,130,249, 82,245, 61,207,190,249,238,139, + 57, 17,209,167, 99,139,254,152,210,160,245,124,173,164,228,237, 18,154, 89, 85, 81,169,151,210,122,115, 96,254, 45,181,207,158, +203,165, 85,198,200,190,232, 17, 26, 4, 0,216,115,246, 14,191,160,172,218, 15, 64, 96, 25,109,232,113,211,104, 74, 40, 40, 45, +125,187, 33,153,163,198, 39, 82,221, 70,126,208,155,209,254, 81, 28,209,125,180, 68, 32, 48,211,215,254,200, 82,150, 22, 95,186, + 83, 94,252, 91,177, 90, 94, 10, 80, 20,145,107,104,255, 89,137,253, 29,213, 27, 82,135, 84,234,115,171,215, 10, 4,180, 62,255, + 87, 69,227,255,237, 96,111,245,215,245, 8,184,235, 85, 8, 10,202,110,178, 28, 0, 24, 57,114, 36,119,248,240, 97,176, 63, 4, +128,227, 56,124,252,241,199, 56,114,228,136, 77, 81,115,187, 12, 20, 10,133,145, 16, 50,226,212,169, 83,134,240,240,240,184, 38, +122,117, 2, 0,203,108, 0,235,231, 12, 0,108, 80, 80,144, 51,134,154,106,247,238,221,165,251,247,239,255,106,243,230,205,228, +232,209,163,100,244,232,209,156,141,252, 1,203,118,247, 34,145, 8, 69, 69, 69,216,183,111, 31, 9, 12, 12,100,134, 13, 27,246, + 43,203,214,111,180,119,142,234,114,123,200,144, 33,179, 46, 94,252, 51, 66,173,213,132,113,140,201, 4, 10, 70,198, 72, 85, 27, +141, 70,165, 26,101,183, 88,163,225, 78,105,113,153,241,231, 61,123,215,180, 10, 14, 41,162,105, 93,181,187,121,201,175,167, 97, +216, 10,166,181,245, 56, 92, 71, 81, 56, 12, 96, 1,128,182, 0,202, 28,100, 62,129, 37,118,224, 56,128, 27, 14, 20,142, 27,214, +231,230,161,225, 56, 3, 91,250, 38, 3, 72,113, 32,239,107, 88,134, 24,190,114,144, 62,251,138, 40,133, 37,206, 97, 32, 0, 53, +128,247, 0,156, 6,208, 17, 64,161, 19, 46, 68,123,121,207, 0,120,209, 74,178,122,107, 90,245,214,243,116, 88,226, 1,190,119, + 66,222, 12, 0,175, 56, 89,193, 9, 44,177, 16,223, 56, 72,223, 42, 0,190,176,196, 58,236,182,166, 77,108,213,164,255, 0, 48, +216,234, 17,248, 21,119,227, 53,234, 69, 92, 92, 92,172, 61,209,219, 43, 1,117, 99, 3,226,226,226, 98,179,178,178, 26,125,129, +184,184,184, 88,106,202,221,113,123,246,135, 64, 80, 86, 37,160,238, 88,190,219,242,166, 40, 56,119,228,157, 61,123, 22, 17, 17, + 17,184,124,249,114, 77,157, 25, 54,108, 24,151,155,155,139,241,227,199,223,235,166,242,242,146,137,197, 98,168,213,234,122,229, + 73,207,158,133, 50,162, 13,250, 93, 62, 81, 35,239, 77,191,199, 98,162,114, 85, 50,106,188,248, 30,197,169, 56,159,134, 72,108, +178,212,204,134,149,128,133,104,215,238, 55, 0, 67, 56,112, 60,220,168,120, 67,199, 48, 96, 12, 22,231,216,197,138, 10,220, 48, +208,155,248,132,104, 64,136,169,160,180,116, 91, 99,249,215, 86,218,109, 33,128,212,252,163,243, 11,197, 97,147, 21,165,101,226, +118,101, 37,167,196, 16, 4,117, 42, 44, 50,135, 87,149,221,132, 80, 40, 8,237, 25,230, 61, 77,169, 49,125, 11,224,166, 35,203, +213, 58,247,223,225, 48, 64, 66, 66, 66,108,102,102,102,142,203,236, 94,103, 8,224, 31, 16,168,219,100,175,128,139,223,231,154, + 42,111,212,168,145,156, 76,150, 3,178,205, 18,143,125, 96,177, 47,198, 44,215, 96,228,200,145,112,113,218,223, 61,176,141,213, + 63,252,240,195,186,102, 80,232, 20, 65, 65, 65,211,237,140, 83,163, 92, 46,223,227,228,119, 25, 0,229,187,118,237,146, 61,245, +212, 83,209, 43, 86,172,232, 99, 54,155,137, 68, 34, 65, 92, 92, 28,126,249,229, 23,176, 44,139,113,227,198,113,243,231,207, 39, +253,250,245, 51, 78,158, 60, 57, 50, 33, 33,225, 78,191,126,253,234, 87,192,230, 36, 51, 49,143,140,217,212,171,119, 31,255, 83, + 39, 79,174,252,157,207,239,213, 33,178,195,151,126,193, 33, 37,130, 16, 49,119,120,223,161, 64,185,162,106, 68,120, 80,200,251, + 93,186,116, 57,236, 19,230,189,254,147,101,159,211, 13,201,115, 85, 1,224, 1,136, 6, 48, 12,192, 50, 0,175, 89, 43,131,119, + 29,242,251, 6,150,113,246,127,193, 50, 36,144,215,136,135,225, 33,171,245,235,140, 59,254,184,213,187, 64, 53, 34, 47, 4, 64, +164,149,152, 27,147,121,218,250, 92, 40, 44,227,249, 13,201, 19, 90, 45,231, 36, 88,166, 17, 62, 3, 32,223, 42, 59,223,122,190, + 25,150,113,242, 77,176, 12, 93,208, 14,228, 77, 1,240, 5,128,110, 86, 37,201, 62,157,183, 97, 9, 90,188,108,125,246, 7, 7, +242, 94,135,101,118,131,206,137,252,243, 2,176, 31,192,119, 14,202,227,105, 0,255,177,126,254,110,151, 62,129,181, 44, 51, 1, +172, 1,176,220,122,255,118, 67, 63,152,149,149,149, 3, 0,197,197,197, 50, 91,180,127, 93,171,191,184,184, 88,102,255,108, 99, +176, 61,179,233, 87,186, 38, 58,191,174,149,190,233, 87, 26, 15, 66, 94,110,110, 46, 70,140, 24,129,203,151, 47,223, 37,113,169, + 52,118,235,214,173,178, 14, 29, 58,196,178, 44, 43,139,140,140,228, 88,150,133, 94,175,199,207, 63,255,140,232,232,232,216,125, +251,246,213, 43,175,107,110, 46,190, 15, 14,173,149, 87,221,231,142,129,118,229, 77,224,209, 80,112, 44, 48, 39,242, 43,174,154, +245,129, 92,239, 7,121,126, 16,250,142,216, 29,123,105, 71,227,110,246,107, 37, 37,219, 1,108,239, 24,209,182, 43,128, 55,140, +102, 22,219,206, 23, 98, 68,152,101,184,147,112,156, 70,195, 48,203,202,203,203,239, 56, 65,166, 43, 57,142,243,206,191, 44,127, + 86,121,122,107,171,242,219,114,148,223,209,128,207,175,242,174, 86,112, 80,170,205, 92,104,136, 48,128,207, 98,146,222,104,254, +126,217,235, 15, 7,252,235,147,227, 74, 7, 68,147,227, 68,167, 77, 92,137,100,191, 7,163,173,158,151,236, 68, 87,191,105,243, +134, 57,138,202,183,127,142, 56, 43,143, 36, 42,208, 68,121,247, 88,236,153,153,153, 24, 56,112, 96, 75,210, 69,184,156, 57, 23, + 0, 27,249,159,103,176, 65,102,105, 99, 77, 37,127, 91,221,224,241,120, 33,124, 62,191,252,248,241,227, 95, 62,252,240,195,238, +174,243, 0, 0, 17,114,185,124,157, 85,177,152, 34,151,203,127,176,125, 58,227, 84, 4, 80, 13,160,114,197,138, 21,125,231,205, +155, 87,122,246,252,249, 54,122,189,158,200,100,135, 32, 18,139, 64, 17, 10,135, 14, 29, 34, 61,122,244,208, 37, 36, 36, 12,158, + 60,121,178,195, 54,151,115,232, 0, 51,225,169, 9,107,250,246,237,223,129,102,140,143, 95,203,191,250, 34, 91, 88,240, 2, 0, +136, 65,113,189, 59,117, 61, 21, 26, 26,146,195,227, 11,223,254,207,226,148,234, 79,150,125,236,118, 70,214,167, 0,188, 97,213, +134,198, 3,184, 4,192,167,158,239,237,181, 90,236,241,176,204, 35, 79,106,196,253,223, 25,150,232,114,103, 20,128, 42,235,243, +188, 70,228,197, 0,184,234,164,188,171,214,231,119, 52, 34,111, 22,128,153, 0, 46, 0,152,111,125, 47,123,217, 50,171,245, 63, +199,106, 13,111,180, 90,217, 13,201,155, 97,205,143,126, 86, 47, 66,125,233, 84, 91,239,219, 60, 1, 27, 27,145,247,181,181, 83, +240,114,178,243,250,218, 65,254,125,100,245,108, 28,176, 42, 53,168, 35,251, 23, 0, 61,172,101,145,111, 85,164, 28,186,118, 87, +175, 94,205, 1,144, 53,211, 66, 64,100,230, 26, 45, 55,115,141,182,158,133,123,220, 10,114,106, 22,121,127,254,249, 39,249,243, +207, 63,107, 93,251,238,187,239,114, 0,144, 31,126,248, 1, 0, 72, 81, 81,237,152,186,134,200, 31, 0,218,255,249, 39, 1,106, +203,123,249,131, 5, 22,114,252,208,154,166,186, 33,122, 59, 92,232,133,205, 92, 33,248, 0,175, 26, 53,228,111,101,245, 59, 98, +177,216,169, 69, 68, 56,142, 35,132,144, 37, 11, 19,123,122,133,181,139,156,192,194,171,115, 73,113, 25,207,100, 80,114,173, 67, +125,136,143,183,128, 48, 38, 22, 10, 37,205, 16, 9,145,168, 52, 76,167, 70, 12,130,134,234,108,221,255, 31,164,139,222,126, 56, +162, 33, 98,225,224,222, 44,128,230,144, 87,175,197,222,161, 67, 7,156, 62,125,186, 69,144, 63,251, 67, 32, 14,156,103, 0, 0, + 27,101, 52,190, 63, 78,219,188, 48,164,185,202,199,108, 54, 87, 1,192,128, 1, 3,154,180, 32,144,141,252,173,168,180,126, 58, +187,192,142,208,106,152,157, 1,128, 79, 63,253, 52,252,249,153,207, 47,122,104, 96,244, 12,141, 90,237,207,152, 25, 83, 88, 88, +216,157,240,240,240,171,106,181,122,249,228,201,147,243,157, 77,215, 79, 63,254,196, 0,120,237,217,233, 47, 14, 31, 54,124,248, +120,137, 68,210,138,128, 51, 91,102, 78,112, 85,122,173, 98,221,149,243,197,183,189, 69,194, 38, 45,124, 87, 87, 1, 48,195, 18, +164,230,204, 56,252, 41,235, 97, 70,195,203,139,154, 97,137,168,119,118,190,166, 12, 64,182, 3,121,187, 96, 9, 90,115, 6,207, + 58,145,190,207, 1,124,233,168,239, 7,240,170,221,119, 26,147,247,141,213, 99,224, 8,133, 86,203,222,153,244,185, 50,223,245, +115, 7,242, 30,117, 66,158,205,219,176,209,154, 55,206, 44, 31, 75,226,226,226, 98,234, 70,253, 91,221,234, 57,238, 52,244,184, +184,184, 24,187,149,250, 90,154,188, 22,143,235,165,183,141, 84,187,118, 27, 95, 89,153, 62,211,118,141, 22, 80,223, 25,116,236, +254,178,226, 98,141, 83,153, 70, 8,247,159, 89, 67,200,123,159,255,182,240,231, 53,161, 59, 79,156,188, 61, 59,196,159,125,146, + 10,242, 11,224, 56,128, 16,206,104,100,216, 50, 22,168,164,141,108, 64,233,109,189, 75,171,147, 89,221,252,178, 58,231, 45, 37, + 11, 91,220, 74,128,127, 23, 60,182, 92,115,191,223,145, 5,208, 70, 44, 22,223, 30, 48, 96,192,163,103,206,156,105,178, 64,185, + 92,126, 48, 40, 40,104,166, 92, 46,223,232,130, 2,192, 88, 61,167, 0,128, 13, 27, 55,164,192, 50, 60,221, 44,248,246,187, 47, +127,133,101, 40,246,190,160, 62, 5,192,224,142,214,215, 72, 33, 25, 61,242,254,177,242,106,193, 74,164,164,206, 53,183, 43,103, + 75,151,247,119,128, 92,167,123, 1,240, 50, 1, 8, 97,193,149, 26, 12,244,230,178,178,138,115,214,142,203, 41,188,247,249,111, +220,143, 31,141, 37,227, 95,219,159, 11, 32, 55, 97,112,215, 55,130,130, 68,139,248, 60,194,221,174, 50, 92,185, 77, 51,155, 36, + 2, 74, 44,225,243,120, 38,134, 21,187,146,190,204,204,204, 28,219,242,182,214, 79,183,148,177,123,166,254,217,185,254,157,152, + 22,216, 88,189, 39, 46, 92,255,171,229,221, 55,197,167, 41, 74, 24, 53, 69, 1, 66, 8,158,156, 56,171,222, 62,100,215,143, 25, +205,245,174,101, 0, 72,115,144,191,157, 18,176,209,133,199, 3,173,237, 72,251,119,237, 31,248,245, 84,196,230,140,152,241,200, +251,103,203,243,160,165, 43, 0,114, 57, 39,151,203,103, 53, 85,206, 83,111,238,231, 0,224,217,145, 61,200,183, 71, 46,126,172, +231,230,172,121,109,234,241, 30,180,150, 68, 5, 9,248,173, 64,136,206, 71,194,175,232,213,205, 47,127,219, 1,215,100, 91, 93, +217, 77, 89,111,254,126,145,231,223,197, 3, 64, 90,146,215, 36, 35, 35,157, 75, 78,158, 77,118,253,152,241, 79,111, 94,225, 86, +131,217, 23,150, 61, 1,254,118, 32,238,238, 35,236,129, 7, 30,252, 13, 53,126, 30,224, 37, 34, 96, 89, 14, 32, 4,213,122, 79, +243,247,192,131,255,217,254,192,147, 5, 30,120,240,191, 3,198, 12,168,117, 78, 47, 59,239,129, 7, 30,252,131, 65,121,178,192, + 3, 15, 60,240,192, 3, 15, 60, 10,128, 7, 30,120,224,129, 7, 30,120,224, 81, 0, 60,240,192, 3, 15, 60,240,192,131,127, 34, +106,197, 0,156, 61,123,214,237,104,212,250,130, 9,235,147, 55,254,145,232,152, 94,125, 58,201,218,180, 11,143,213,232,181,178, +195,178,220,216,172, 67,231,114,220,149,215,123,240,152,152,126,125, 6,203,238,148,150,194, 91,226,141,155, 37, 5,177,121, 39, +246,186, 45,175,185,223,119,238, 52, 42,102,200,224, 14, 50,137, 55, 15,124, 30, 5, 34, 38,120,114,234, 69,226,174,188,228,255, +151, 27,243,208,224,135,100,254, 62, 60,128, 15, 36, 12,174,127,142,211,131,122, 95,143,188, 22, 43,175,209,169,102, 45,253,125, + 59, 12,120,154,243, 99, 11,238,107,250,126,127,183,200,237,142,180,255, 7,145,247, 92,251,184, 85,169,219,242,222,168,188,119, +195, 85, 79,125,254, 75,228,241, 81,207, 20, 89, 87,228,197,198,198, 70, 25, 12, 6, 69,110,110,174,242, 65,190,175,203, 10, 64, + 67, 88, 29,131,206, 0, 58,192,178, 78, 64,193,252, 28,220,112,246, 7,198, 12,239, 16, 67,192, 34, 36, 32, 8,185,135,207,200, +222,153, 59, 3,195, 70, 15, 3,163,213,201,122,116, 27, 9,150,133,108,222,139, 15,199,246,239,223, 7,215,174, 21, 65,165,212, + 98,237,198, 35, 57, 13,201, 27, 56,226,153, 24, 14, 4,145,157, 58,200,146,223, 92,142, 23,158,121, 12,223,252,247, 51, 0, 98, +236, 61, 87, 2,138,130,108,245,146,197,200,207,191, 2,169, 52, 18, 34, 9, 31,183, 74,242, 99,161,171, 63,201,139, 30,235,203, + 9,133, 66, 72, 36, 18, 20, 20, 20,160,109,168, 31, 90,241,125,208, 54, 34, 0,129, 18,127,120, 19, 51, 40,138, 2,199,154,161, + 19,241,161,186,163,194,164,255,102, 57, 44,168,212,133,125, 56, 95,137, 10,126, 1, 66,248,120,243, 33,148, 80,224,243, 0, 74, +200, 71,206,207,209,156,137,227, 33,110,194, 9,167, 11,188,247, 83,171, 99,194,195,195,209,174, 99, 59,153,222, 96, 4, 37,146, + 0, 38, 96, 78,218,169, 24,189, 78,139,175,254, 21,147,243, 0, 21,201,150, 54,143,249,127, 25,174,150,133,211,207, 39,188,179, +200, 27,192, 67,173, 37, 94,255, 41, 45, 45,237, 38, 16,139,192,122,121,125, 8, 96,125,230,135, 41,213, 45, 37, 3,162,122,140, +138,185,113,241,112,125,123, 13,252, 35,234,104, 70, 70, 6,249,102,211,166,203, 34,161, 80,194,178,172,191,183,143,143,207,132, + 39,159,244, 2, 64, 39, 39, 39,115, 45, 52,205, 20, 0, 36, 39, 39,179,205, 32,206,207,223,223,127, 65,215,174, 93, 39,139, 68, +162,118, 37, 37, 37, 37,165,165,165, 39,105,154,254, 0, 64,129, 27,242, 2, 2, 3, 3,151, 63,242,200, 35,143,135,133,133, 73, + 79,157, 58,117,231,194,133, 11,199, 13, 6,195, 82, 88, 86,136,117, 26,163, 70,141, 74,141,136,136,120,219,219,219, 27,190,190, +190,167, 15, 28, 56, 16,253,183,241, 0, 52, 64,254, 60,111, 17,255,161, 25,195, 59,174, 98, 57,206,112,244,202,157, 79, 87,199, +168, 14,204,207,193, 69, 71,223,149,223, 62,200, 25,171,229, 48, 85, 43,193, 55, 83,248,227,226, 21, 60,247,220,252,154,251, 20, + 5,252,150,187, 17,173, 34,194,101,108,181, 26, 52, 75,112,232, 80,110,236,218,141, 71, 26,144, 24,201,157, 62,113, 17,196,203, + 15,103, 46, 22,227,220,197,231,241,213,247,191,212,220,101, 89, 96,236,208,161, 64,117, 25, 0, 95, 20, 92,184, 4, 65,171, 0, + 12, 27,210, 75,166,212, 53,162,179, 16, 10, 32, 20,250,245, 25,128,214,222, 66,180,109, 37,134, 95,112, 16, 2, 69,190, 8, 20, +243, 32,224,241, 96, 50,155,161,100, 88,156,170,116,188,220,230,210, 87,219,115, 18,158, 2,126, 94, 94, 8,105, 21, 12, 63, 63, + 47,112,148, 25, 12, 91, 13, 51,204,240,241,241, 66,171,214,237, 80,112,185, 11,215,177,219, 55,141,118, 74,253,227,215,112,254, +190,222,240, 15, 8, 68, 72,171, 96,104,181, 90, 8, 69, 98, 8, 12,150,197,249,162,164,145, 50,185, 66,137, 71, 94,220, 24, 91, + 92,114, 11,138,178, 34, 84,157,203,112,164, 12, 56,221, 73,140,158, 57, 58, 54,123, 99,118,142, 19,178,238,171, 18, 80, 88, 88, +200, 1,128, 84, 42, 37, 45, 69, 94,120,120,248,115, 52, 77,111, 4,128,201,177,177, 84,198,214,173,238,116,190,150, 53, 82,237, + 28, 57, 28,199,129, 16, 82,243,105,187,102,123,206,193, 78,106,174,172, 39,239, 10,249,247,240, 54, 49,219,125, 3,252,187, 1, +128, 80, 34, 6,173, 55,128,213,234, 82,143, 31, 57,188, 36,225,157, 69,221, 51, 63, 76, 41,118, 36,231,211,119,231,114, 86, 11, +139,129,101, 8,146,181,246, 67,245,246, 69,125, 71, 61,142, 81,143, 61,225, 82, 25,221,184,120, 88,214,169, 87, 76,236,181, 63, +114, 92, 87,138, 19,228, 46, 61,158,152,152,136,173, 9,217,141, 62, 19,155, 93,123, 43,146, 30, 1,150, 87, 45, 55,176,208, 51, +150,114,213, 90, 63, 51, 6, 7,160,139,175,160, 81,121,171, 86,173,202,121,247,245,183, 66, 39, 78,158,228, 99, 48,232,177,250, +227,143,168,181,107,215, 26,230,206,157, 27, 14,224, 86,115,183,189, 73,147, 38,141,222,185,115,103,150,171, 74,212,204,153, 51, +185,194,194, 66, 84, 85, 85, 97,197,138, 21,240,245,245, 69, 76, 76, 12,164, 82, 41, 54,110,220,232,110,187, 27, 57, 96,192,128, + 77,111,190,249,230,181,174, 93,187,110,236,223,191,255,165, 59,119,238,180,203,205,205, 29,240,194, 11, 47,236, 81,171,213,169, +176,108, 0,231, 44, 98, 39, 79,158,156,153,146,146, 18,108, 50,153, 32,145, 72,224,237,237,221, 70,171,213, 62, 61,113,226,196, + 9,231,207,159,159, 11,224,191,206, 10,139,136,136,104,187,104,209, 34,228,229,229,113, 26,141, 38,160,206,109, 30,156, 91, 85, +181, 89,112,246,236,217,186, 94, 2,231, 20,128,213, 49,104, 15,203, 14,120, 60, 0,102,173,145,185,153,123,181,252,147,161,157, + 67,231, 63,210,163,205,146,214,254,146,182,171, 81,182, 5,192,149,249, 57, 13,111, 82, 99,172,150,163,117,167, 71,177,252,237, +201,216,104,199, 73,135,143,167, 67,171, 51, 98,220,232,249,120,120,216, 76, 60,147,248, 8, 36, 18, 17,104, 51, 3,141,142,150, + 53, 92,201,138, 0, 26,152, 60,125, 61, 94,126,115,118,205,213,177, 15,199, 64, 44, 22,225,199, 67,191, 96,239,177, 92,108,218, +240, 25, 12,122, 35,132, 60, 62,124,188,132,208, 86,149,196, 42, 75, 80,239,238, 99, 28,199, 1, 28,107, 57, 40, 22, 28,199,193, + 72,139, 44,221,147, 8,224,104, 51,204, 60,192, 12, 51,204, 52, 11,198,220,184, 2,187,240, 69, 41, 23,232,199,192,207,215, 27, +225,237,162,208,173,119, 39,248,250, 72,160,170,174, 64, 89, 69, 25, 20,170, 59, 48, 25, 8,188,188,188, 16, 18, 50, 12,149,229, + 33, 92,171,208,143,234,119,227,143, 92,204, 49,122, 29,244,124, 64, 40, 22, 66,175, 19,130,214, 9, 97, 16,139,192, 39, 12, 56, +240, 96,208, 87, 67,175,211,160, 93,187,182, 50, 33,143, 15, 57,212, 8,165,167,163,238, 26,243,117,177,114,211, 74,135, 21,232, +237,164,183, 27,239, 43, 19, 18,106,237,239,158,144,144, 48, 48, 40, 40, 40,159, 16, 98,224, 56,142, 31, 24, 24,232, 85, 80, 80, + 16,108, 93,221,173,173,187, 21,121,238,220,185, 83,237,126, 35,198,221,213,226,234,101, 75, 66,184, 57,115,230,196,174, 93,187, +214, 37,153,225,225,225,201,131, 6, 13,250, 96,120,191,126, 48,137, 68, 72, 75, 75, 99,103, 79,153, 18,151,254,195, 15,217, 46, +254, 62, 86, 45, 89, 82,115,190,224,253,247,145,182,116,105,163,231,206,136,173, 67,238,156,117,179, 24,110,244,232, 14, 61, 1, + 92, 79, 73,201,212,187, 72,254,185,189,123,246,244,179,181, 25,111,177, 4,183, 43,202,161, 86, 40, 49, 96,208, 96,175,159,191, +218,144,157,240,206,162,158,153, 31,166, 56, 90,155,157,153,247,193, 90,254,179, 79, 79,224,119,150, 74, 89,171, 18,128,247,211, +214,212, 86,162, 23,188, 6, 0,120,247,245,185,110,109, 39,237, 22,249,219,144, 25,228,194,195,163, 93, 18,237,205, 39, 56,183, +244, 69, 16,191, 86, 48, 95, 63, 7,227,245, 63,145, 47,215, 34,122, 95,185, 83,223,239, 63, 96,192,209, 89,211,146, 34,147, 94, +122, 33, 32,243,187,239, 89,169, 84, 74, 45, 79, 73,133,239,146,229,248,241,199, 31, 75, 51, 50, 50,168,230,242, 2, 76,154, 52, + 41,110,231,206,157, 7,118,238,220,105, 59, 31, 99,251,223,129,130, 18,115,224,192, 1, 89, 81, 81, 17, 58,118,236,136, 17, 35, + 70,192,223,223, 31, 74,165, 18,183,110,221,194,141, 27, 55, 48,102,204, 24,110,204,152, 49,177,111,189,245,150, 43,229, 52,233, +145, 71, 30, 89,189,106,213,170, 45,253,251,247, 95, 77, 8,185,101,215,143,147,248,248,120, 31, 0,185,214,195, 41,121,115,231, +206,221, 54,103,206, 28,234,244,233,211, 32,132, 32, 56, 56,184,230,216,183,111,159,112,200,144, 33,159,221,188,121,243,132, 35, + 65,147, 39, 79, 38, 59,118,236,224,138,138,138, 34,242,243,243,113,253,250,117,162, 82,169, 58, 2,224, 79,156, 56,209,188,107, +215, 46,238, 65,146,191,237, 90, 93, 37,128, 95, 15,249, 7, 71, 71, 5, 39,245,139, 12,154, 78, 8, 17,112, 28,103, 98, 45, 7, +109, 54, 25,244, 66,138,109,219,187,181,248,237, 86,126, 29, 59,237, 60,117,227,251,213, 49,236,209,249, 57, 13,239, 22, 7, 8, +209,163,123, 87, 80, 84, 14,242,149, 85, 0, 46, 65, 85,122, 21, 2,177, 8,187,246,124, 10, 93,165, 25,211,159,127, 3, 44, 11, + 60, 57, 97, 40,204,124, 31,135, 47,151,159,127, 9, 44, 11,140,235, 75,172,188, 18, 9,131,145, 70,252,216, 49, 16, 7, 80,216, +180,121, 63, 40, 10,216,246,253, 70,148, 94,255, 51,118,223,150, 85, 57, 13,109,151,200,114, 0,203,178, 96, 89, 22,102,179, 25, + 70, 1, 7, 19, 49,129,166,105,232,188, 12, 0, 43, 6,197,153, 97, 22,114,168,166, 13,208,170, 85,141,166, 45,196,199, 8, 62, + 95,130,224,224, 96,116,234,212, 9, 97,173, 7, 3, 60, 10,102,243,105, 80,156, 18, 6, 45, 3, 51,171, 69,217, 45, 57, 66,130, + 43, 17, 28, 48, 12, 31,174,250, 57,230,251,111,239,149, 37, 49, 48,224,140,149,128, 65, 4,154, 50, 65, 43,228,163, 90, 34, 0, + 95, 32, 4, 88,111, 16, 30, 65,181, 86, 7, 69, 89, 17, 10, 78, 31,131,188,184, 24, 44,203,130,226,120,110, 85,154,175,214,223, + 85,156, 95,120,229, 5,199,253,100,237,213,199, 12,153,153,153,139,222,124,243,205,217,197,197,197, 20, 33, 36, 36, 35, 35,227, +123, 88, 54,119,242,114,183, 34,207, 74, 72, 16,172, 91,183,110,243,157, 59,119,176,109,219, 54, 68,119,237,202,107,142, 6, 34, +149, 74, 73, 98, 98, 98, 12,199,113,178,181,107,215,186,188, 97, 17, 77,211,233,195,173,117, 74, 40, 20,162, 75,151, 46,216,126, +232, 80, 86, 72, 72, 8, 42, 42, 42,156,150,115, 31,183,170, 37, 3, 7, 14,228,108, 27,196,216,125,254, 57,106,212,168,210, 69, +139, 18,252, 83, 82, 28,175, 30,151,240,206, 34,111,111, 19,179,189,119,207,158,126, 60,138,194,171,207, 78,135,222, 96, 68,218, +151, 95,194, 75, 34,129,193, 96,128, 65,175, 71,223,254,253, 58,255,242,221,119,115,208,240, 86,222, 53,125,206,210, 5,175,177, + 0,168,171,133,133, 84, 93,194,175,219, 60,221,121,241,246,221, 70,198,222,188,124,132,139,123,242,197,216,172,221, 95,186,165, + 8,216,239,218,199,109, 13,116,120,221, 17,122, 4,240, 81, 84,109,198,225,184, 16, 8,230,103, 64, 61, 61, 10,252,192, 80,151, +200, 63, 49, 49,177,204,164,213,221,122,233,213,217,237,223,121, 99, 33,214,110, 72,191, 56,104,192,128, 14,233,107,210,189, 94, + 95,248, 22,190, 27, 58, 24,155, 55,111,158, 1,203,174,165, 77, 33,254,152,157, 59,119,202,108,100,159,145,145, 81, 0,203, 54, +237, 7,157, 81, 0, 14, 28, 56, 32, 11, 9, 9, 65,255,254,253, 25,138,162,248, 22,239, 44, 11,129, 64,128,160,160, 32,180,110, +221, 26, 55,110,220,192,129, 3, 7,100, 46,180,185,132,241,227,199,127,180,106,213,170, 53, 93,187,118, 93, 79, 8, 97, 1,124, + 6,224, 49, 0, 71, 8, 33, 75, 97,217, 95,229, 45, 0, 75,157,145,183,106,238,220, 31,134, 39, 36,144,221,187,119,131,207,231, + 67, 38,147,225,220,185,115,232,212,169, 19,150, 45, 91,134, 94,189,122, 97,246,236,217,252,247,222,123,111,149, 35, 97, 59,118, +236,224, 0,192,203,203,235,118, 64, 64, 0,196, 98, 49,132, 66, 97, 53, 0,198,129,199,238,190,145,255,172, 69, 31,214, 92,251, + 60,229,157,122,149,128,250,102, 1, 80,124, 30,197,103, 88, 78,163, 55, 49,183, 8, 33, 34, 31, 17,175,143,159, 16,209,146,158, +163, 58, 34,246,101,160,219, 8,180,241,230, 38,205, 24, 22,245, 78,144,159, 87,220,234, 24,248, 55,156, 28, 22, 60,158,173,207, +246, 3,208, 14,254,225,227,161, 55, 27,176, 62, 99, 3,190,217,188, 13, 99, 98,135, 1, 0,116, 58,128,199,111, 88,148,196,171, + 43, 0,192,108,182, 87,164,202, 0,228,130,226,137,144,244,220,139,136, 79, 76,196,207,123, 44, 68,230,229, 13,104,171,111, 55, +154, 89, 38,240,106,200,223,196,152, 97, 84,155,160, 83,234,160, 52,209,144,235,104, 40,140, 26, 40, 53,213, 80,148,107, 32, 87, + 26, 32,175,110,120, 9,245, 87,159,233,192, 17, 66,192,227, 17, 16, 74, 4,179,153, 3,163, 43,134, 86,121, 21,165,101, 42,200, + 21,213, 80,105,204,144, 43, 12, 40, 41, 41,195,197,203,103,161, 84,157,197,224, 1, 3, 27,220, 27,157, 7,128,210, 24,160,191, +118, 11, 85,127, 92, 66, 85,113, 17,212, 42, 57,212, 42, 57,138, 46,158,198,241,204,175,144,187,117, 19, 42,174, 93,131,153,102, + 45,173,137,247,151, 13, 3, 18,235, 65,199,199,199,119, 95,190,124,249,155,109,218,180,209,110,219,182,173, 79,102,102,230, 79, + 0,250, 91, 11,221,237, 5,167,132, 97, 97, 11, 0, 96, 72,175, 94,152, 51,103, 78,249,169,203,151,179, 31,234,214, 45,166, 57, + 18,191,117,235,214, 28, 0,100,238, 92,139,149, 57,119,238, 92,151,228,154, 68, 34, 0,192,246,237,219, 17, 26, 26,138,119,230, +206,197,130, 5, 11, 16, 18, 18,210, 34,198, 97,109,164,159,145,145, 81,115, 0,192,225,195,135,195, 1, 76,112, 82,204, 67, 1, +129,129,221,120, 20,133,231,227,227,161, 84,169, 81,114,251, 22, 4, 2, 62,248,124,203, 33, 16, 8, 32,146,120,161,163, 84,250, +113,255,209,163,157,178,216,175, 22, 22,226,219,237, 63,213, 28, 54,188,159,182, 6,239,167,173,193, 94,217, 97,151,223,119,116, +194,123, 49, 0,112,243,242,145,156,209, 22,242,151,161,133,172,118,116,254,235, 79, 80,254,242, 0,140,202,170, 64,143, 0, 62, +120,126, 65, 96, 20,229,136,222, 87, 14,111,190,133, 31,120, 14,230,100,221,184,118,173,234,243,140,255,118,253,250,191, 95,227, +211, 47, 63, 43,250,108,213, 71,239,191,249,218,188, 9,203, 63, 88, 14,137,175, 55, 70, 12, 25,134, 83, 39, 79,125,253,108,210, +179,110,191,179,141,252,109,231,187,119,239,198, 67, 15, 61,212, 17,192,116,103,221,254, 38,147, 9, 3, 6, 12, 96,205,102, 51, + 95,165, 82,193,104, 52,194,104, 52,226,242,229,203,144,201,100, 56,118,236, 24,218,180,105, 3,147,201,132,153, 51,103, 58,147, +214,169,137,137,137,159, 76,158, 60,217,111,253,250,245,126,132, 16, 33,128,195, 0, 84, 0, 6, 0,248,201, 78,241, 60, 8,160, +151, 35,121, 59,223,124,243,135, 9,125,251,146,239,226,227, 81,250,251,239,248,232,163,143,216,159,127,254,249,255,221,188,121, + 51, 84, 38,147,189,188,104,209, 34,152, 76, 38, 12, 27, 54, 12,222,222,222, 67,157,205,191,128,128,128,202,214,173, 91,195,199, +199,135,243,246,246,190,105,205,195, 7, 94, 7,237,149,129, 70, 61, 0,243,115, 80,177, 26, 21,233,191, 93,171,200,138,142, 10, +142, 29, 40, 13,178,172, 35, 62,126, 25,126,243, 25,131,131,127,148, 99,104,207, 64, 60, 34,253, 25,190,191,124,208,127,108, 63, +233,244,205, 71, 46,254, 81,159,240, 54,157, 19, 8,199,149,112, 19,159,155,143, 5,175,125, 6, 64, 14,203,178,201, 70, 68,118, + 29, 0,177,136, 15,189,214, 8,208, 22, 5,193,215,215, 23,229,242, 6,247,203,134, 94,119,133, 0,224, 46,254,246, 37, 40,106, +109, 45, 35,129,213,255, 9,131,209, 4,137,143, 24, 16, 90, 20, 4,141, 90,141,161, 67,135,226,200, 79,223, 53,108,142,176, 52, + 88,150, 15,134, 97, 96, 52, 26, 81,205,231,129, 79, 83,192,109, 53, 24, 47, 6,102, 33, 11, 78,192,131,142,199, 7,163,213, 65, +105,108, 56,214,201,215, 71, 11,134, 33, 48,210,102, 40, 85,106,228, 95, 43, 70,201,237, 74,232,105, 19,212,213,114, 84,107,148, + 48,152,105, 16, 62,129, 86,167,130, 90,119, 3, 69,165, 42, 84,105, 26,222, 75,194,108,167,165, 49, 42, 45, 74,206, 94,194,157, + 75, 55,160,214, 92,131, 70,169, 4, 7, 62, 4, 60, 2,142, 8, 64, 81, 22,175,175, 43,234,230,219, 73,111, 59, 53, 28,224, 0, +119, 0,220, 89,188,120,177, 30, 0, 22, 45, 90,116, 42, 37, 37,197,219,154,116, 3,128, 98,119, 5,175, 91,183,110, 69,124,124, + 60, 0, 32, 42, 36, 36,212, 58, 38,206,107,206,198, 97,115,255, 91, 61, 1, 14,179, 47, 60, 60,124, 52, 77,211, 72, 75, 75,195, +211, 79, 63,141,201, 99,198,220,237,232,207,159,183,120,130, 66, 66, 56,103,227, 2, 22,188,255,126,205,152, 63, 0,188,181,100, + 73, 45,207,128,147,110,255, 90,176, 89,255, 54,210,183, 33, 35, 35, 3,201,201,201,200,206,190,254, 45,128,239, 28,118,104,124, +254,127, 12,180, 17, 60, 30, 15,151,175, 23,128,227, 56, 92,204,191, 10,154, 54,129, 2, 1,159,207, 7, 33, 4,172,217, 12,189, + 86,135,171,191,253,118,200,137, 60,164,236, 73,255,217,167, 39,216, 91,252, 20, 0,156, 56,115, 30,157,163, 34, 93,154,166,156, +157,249,159, 26,107, 63,219, 98,249,219,134, 66,184,199, 39,189, 24,187,111,167,123,222,128,102,129,252, 54,132, 17, 93, 80, 62, + 71, 12,209, 35, 83, 97,206,219, 15,179,218, 18,111, 80, 62,231, 97, 68,102,228,194,204, 54, 94, 85,186,118,238,218,214,203,203, +219,235,211, 47,214, 25, 98, 71,141, 18, 14, 30, 58,228,187, 3,123,127,121,252,242,181,124,128,229, 32, 22,137, 48,108,224, 48, +236,217,189, 7, 99,199,142,229,246,239,223,239,116, 87, 80,215,234, 63,112,224, 0,174, 95,191, 78, 3, 16,158, 60,121,146,158, + 61,123,246,180,140,140,140,103, 29,201, 41, 44, 44, 68,199,142, 29, 1,128, 42, 44, 44,196,185,115,231, 16, 25, 25,137,168,168, + 40, 40, 20, 10,228,229,229,161, 67,135, 14, 8, 13, 13, 69,100,100, 36, 10, 11, 11, 27,175, 40, 20,149,148,152,152,248,193,200, +145, 35,125, 78,157, 58,229,199, 48,204, 75, 18,137,100,162, 94,175, 95, 5,203,214,231,176, 42, 0,107, 96,217,157,143, 70, 35, +211,219, 5, 2, 65, 82,230,188,121, 27, 31, 14, 9, 33, 21, 11, 23, 98, 40,203, 98,205,238,221, 92,169, 78,247, 34,238,110,203, +190,241,226,197,139,235, 25,134,225,251,248,248, 32, 60, 60,220,199,100, 50, 65, 32, 16, 56,122,125,175,210,210,210,174, 55,111, +222,132, 86,171, 37, 10,133,162, 59,159,207,143, 99, 24,166,197,238, 56, 86,223, 16, 64, 24,128,142,147,162, 35, 94,109, 31,236, + 61, 29, 38, 61,208, 53, 14,103, 66, 38,225,145,185, 95, 65, 95,169, 4,207,207, 23,178,213, 73, 24,209,227, 55, 4,157,207, 26, + 9, 32,162,161, 31,232,228,215, 14,127,156,223, 97,231,112,208, 2, 48, 89, 14,147, 17,124,150, 7,202, 74,226, 59,127,116,188, +139,200,254, 11, 28,198,246,239, 85,199, 8,229, 3, 16, 0, 2, 49, 24, 98,134,213, 14,198,148,233,243, 0, 64,150,242,238,220, + 6, 27,130,153,229,192,176, 20, 40,134, 1, 69, 27,161,163, 44,117, 71,207,227,193,155,209, 67,173,231, 64, 4, 4,102,179, 25, + 58, 51, 80,174,109,120,183, 83,134,102, 97, 16,240,192,234, 24, 48,172, 10,154,106, 19,120, 68, 0, 35, 99, 2,205,209, 96, 76, + 52, 32,100, 65, 17,128,136, 88,168,244,102,148, 85,232,160, 53, 50,245, 26,201, 20, 49,215, 12, 26, 17,114,119, 72,215,100,208, + 67, 37,151,131, 34, 60,240,249, 28,192,241,193, 35,238,155, 58, 87,138,174,208, 93, 35,187, 10,157,113,251, 55,164,155,193,110, + 15,237,148,148,148, 9, 0,110, 46, 90,180,168,191,191,191,127,128, 74,165, 42, 74, 73,113,125,135,204,185,115,231,190,176,110, +221, 58,180,110,221,218,254,154,114,205,154, 53,217, 15,117,235, 54,250,212,229,203, 7,155,171, 33,204,157, 59, 55,214,110, 40, +160, 49,242,143, 25, 52,104, 80,248,240,126,253, 64,124,125,145,146,146,130,133, 11, 23, 66, 32, 16,192,164, 80,192,223,223, 31, +239,204,157, 91, 19, 23,144,156,152,232, 80, 9,168, 59,198,239, 40, 38,160,177, 17,133,186,214,191, 3,239,128,195, 42,163,144, +203,187,249,248,250,162, 82,161,128,236,196, 9,240, 41, 30,140, 38, 19,116,122, 61, 88,150,173, 81, 92, 24, 19, 13,218,104,116, +102, 72,131, 5, 64, 89,135, 1, 88,187,138,111,176, 94,199,251,105,107,132, 0,208, 89, 42, 45,191, 81,191,109,225,146,151,170, + 93,199,232,152,125, 59,191,116,197,221,220,112, 6,187,224,246,175,229,150,221,250, 95,244,123,238, 13,136,162,250, 88,250,138, +202,219,200,151, 91, 20,127,209,208,241, 40, 54, 51,240, 90,219,248, 80,179, 90,173, 14, 16, 73,196,232, 20, 21, 37,190, 81,114, +179, 77, 85, 69, 21,166, 60, 59, 93,182,247, 96, 22, 86,127,152,182,109,231,222,221,241,157,163, 58, 35,233,233, 25,200, 61,115, + 12, 99,199,140,225,246, 31, 56,224,240,157,237,173,254, 3, 7, 14, 32, 46, 46,206,166, 44, 10,111,221,186,133,217,179,103, 11, + 1,192,153,216,130,170,170, 42,140, 24, 49, 2,102,179, 25,133,133,133, 56,118,236, 24,122,244,232, 1,127,127,127,180,111,223, + 30,253,250,245, 3, 69, 81,160, 40, 10,109,218,180,113, 84, 79,123,244,234,213,235,147,161, 67,135,242,206,159, 63,239,103, 54, +155,203,182,111,223,174,214,235,245, 41, 0,236, 7, 77, 95,125,252,241,199,139,247,238,221, 27, 69, 8,185,141,134,119,180,237, +159, 60,124,248,198,193,124, 62,169,248,224, 3,112, 38, 19,100, 60, 30,155,171,211,205,132,101, 27,119, 27, 94, 89,188,120, 49, +159,162, 40,200,229,114, 92,191,126,189,188, 87,175, 94,161,206,148,115,120,120,120,144,153,227,160,215,233,112,241,226, 69, 48, + 12,211,162,103,158,240,235,144,127,231, 48,127,201,240,199,251,134,207,246,147, 8, 6, 49,102, 86,193,231,204,126, 8,104,195, +187,173, 52, 64, 95,169, 2,132,124,152,149, 26,148, 40,104, 32, 56, 2, 20, 75,139, 27,115,241, 94, 83,171,209, 37,192, 15,140, + 17,184,150,243, 45, 58,197, 60, 86, 99,192,153,104, 19, 4,160, 80,109,176,236, 80, 59, 54,102, 0, 36,193,225, 88,181,241,167, + 6, 19, 60,182, 55,193,222,115, 28, 4, 98, 64, 24,241, 24,232,226,163, 53, 94, 0,129, 80, 4, 19, 12,240,145, 88,118, 36,221, +189,119, 11,254, 56,153,211,168, 75,146,101, 89, 8,105, 61, 76, 16,130,162, 24,192, 96,233,216, 76, 38, 19,140, 6, 1,120,124, + 1, 96, 0, 56,214, 50, 68, 16, 41,141, 2,114,235,159, 81,160, 51,176,224,241, 8, 76,140, 9, 6, 35, 11,181,198, 82, 15, 77, + 44, 7,218,200, 2,124,128, 39,224,129, 47, 6,136,222, 12,150, 48, 96,161,135, 70, 15, 88,118,150,108, 28,102, 0, 20, 11,112, + 4,160, 40, 22,132,240,192,114, 4, 20,101, 53,156, 88, 10, 44, 69,129,176,206, 25,200,118, 65,126,194, 38,214, 35,111, 0, 33, +139, 22, 45, 42, 79, 73, 73,137, 5,240,212,162, 69,139,198,164,164,164,104, 1, 84,185,229,178, 74, 72, 16,174, 91,183,238,203, +248,248,120, 72, 91,181,170,185, 46,109,213, 42,192,234, 5, 8,121, 16, 13,134,166,105,153,109,236,159,211,104,240,175,127,253, + 11,198,170, 42,216, 34,223, 58, 89,149, 21,129,209,136, 9, 19, 38,148,151,150,151, 79,115,198,210,110,198, 33,153, 90, 30,128, + 70, 60, 4, 56,125,250, 52,169, 79,121,168,165,212, 26,105, 40,105, 57, 12, 6, 3, 2,252,253, 33, 22,138, 96, 50, 51,224, 56, + 14,102,179, 25, 52, 77,195,100, 50,129,101,204,206,198, 51,176, 87, 11, 11,169,206, 82,169,205, 34, 96,175, 22, 22, 82,223,110, +255, 73,108,239, 17,232, 44,149, 42,155,203,125, 95, 82,144,215,108,150,191,187, 49, 0,163,178, 42, 80, 46,221, 6, 97, 68, 23, +144,168, 62,136,220,240, 59, 42, 13, 44,188,249, 4,244,175, 63,226,202,245, 27,112,180,107,177,158,161,113, 58,247, 36, 62, 89, +245, 49, 30,142, 25,142,197,255,111, 9,126,217,247, 11,190,219,244, 13,134,142, 28, 30,223, 94, 26, 1,190,151, 0, 7,143, 30, +196,230,175,191,193,142, 31,183, 67, 40, 22,115,187,119,239,110,116,125,136,157, 59,119,214, 34,126, 27,148, 74,215, 55,184,211, +104, 52,240,247,247, 63, 1, 96,176, 84,103, 60,227,177, 0, 0, 32, 0, 73, 68, 65, 84, 42,197,192,129, 3,193,227, 89,134, 89, + 35, 35, 35, 33, 18,137,160, 82,169, 32,149, 74,225,235,235, 91,164,209,104, 34, 27, 17,119,241,252,249,243, 43,118,236,216, 49, +174,115,231,206,221,182,111,223, 94,173, 80, 40,150, 2,216,108,175,191,140, 26, 53,234,205, 13, 27, 54,108, 5, 80, 14, 32, 1, +192,111, 0,250,214, 35,239,247,181, 50,217,138,128,188,188,119,159, 97, 24,124, 12,176, 95, 86, 87,207,168, 35,239,169,121,243, +230,125, 60,107,214, 44,220,184,113, 3,123,246,236, 1,195, 48,135, 0, 60,227,196,235, 83, 1, 60, 94,149, 15, 77, 67,251,251, +239, 92, 8,203,106,174, 1,154,191,186,143,234,215,175, 31,206,158, 61, 91, 51,238,223,104,130,235,156,119,152, 20, 29,177,220, + 79, 34, 24, 84,161, 54,252,114,252,106, 69, 10,120, 34,224,202, 81, 60, 42,229,240,127,175, 77,192,192,158, 82,204, 75,126, 28, + 79,118,164,129, 11, 7,192, 9, 36, 12, 26, 13,214, 81, 34, 95, 89, 12,190, 8, 24,251,228, 27,216,252,233,135, 22, 99, 81,103, +132, 89, 15,252, 40, 59,139,236, 83,150, 25,133,237, 34,162, 64,241, 29,147,215,184,190, 4, 38, 3,176,123,207,126, 68,143,121, +205, 98,253, 67, 0,158, 4, 72, 28,159,128,113, 35, 39, 90, 26,126, 81, 1, 24, 3,221,184, 70,207,113, 96,136,133,224,141,180, + 37,248,207,104,208, 67,167,211,161,186,186, 26, 26,181, 10, 26,141, 6,106, 77, 53, 12,213,213,208,235,245, 13, 87,254,106, 2, +189,193, 12,189,193, 12,173,206, 4, 77,181, 17, 10,141, 17, 74, 53, 13,149,198, 4,165,210,242, 41,175, 98, 32, 87, 48,144,171, + 24, 84,202,105,220,169,108, 56,141, 20,199,193, 12,128,152, 9, 8,197,130, 35, 28,192,113,224, 56, 30,204,236,221,226, 99,173, +189,135,171,190,241,238, 67,187,227,216,222, 99,248,229,208, 47, 53, 74,193,149,162, 43,174,214,185,112, 0, 29, 83, 83, 83,207, + 1, 88,251,206, 59,239,188,222,161, 67, 7, 38, 35, 35,131,164,165,165,185,172, 1,207, 74, 72, 32,194,176,176,157, 0, 16, 22, + 22,118,207,253, 57,115,230, 48,121, 87,174,108,105,174, 88, 0,155,251,223,217,125,227,109, 99,255, 0,240,195, 15, 63,224, 90, + 89, 25, 0,224,231,156,156, 90,247,174, 92,185, 18, 26, 18, 18,162,120, 16,138,202,232,209, 29,108,243,174,107, 93,183,157,219, +238, 59,244,105,250,249, 94,102,205,102,168,229, 10, 84, 86, 86,162, 74,169,128, 86,167,131, 86,167,131,166,186, 26, 90,149, 26, + 26,165, 18, 6,189, 14,180,193, 0,150,113, 24,232, 76,117,150, 74,109,125, 6, 11,128,182, 31, 14, 0,128,111,183,255,132,247, +211,214, 4, 0, 8,115,185, 34,118,140,142,169,171, 56, 68,245, 24, 21,131, 7,140,219, 83,164,136,220,240, 59, 72, 84, 31, 24, + 15,111, 67,209,243,253,225,205, 39, 56, 26, 23, 2, 70, 85,129,232,253,229,224, 59,168,126, 89, 89, 89,228,229,249,175,224,218, +149, 43,200,205, 57, 10,127, 95,127, 76,157, 50, 21, 1,193, 65, 56,115, 50, 15, 62, 66, 49,188,189,189,209, 70,218, 22, 91,190, +223,130,119,222,123, 23,213, 74,247,119,169, 29, 48, 96,128,203,223,241,245,245,133, 74,165, 26, 76, 81, 20,221,190,125,123, 12, + 26, 52, 8, 61,123,246, 68,171, 86,173, 32, 22,139, 33,149, 74,209,183,111, 95, 4, 4, 4, 64,163,209, 68,250,250,250, 58, 18, +185,242,240,225,195, 89,155, 54,109, 18, 40, 20,138,197,117,200, 58, 97,196,136, 17,159,108,216,176,225,171,176,176,176, 15, 8, + 33, 62, 0,222, 1,208,152,155,236,189,229, 26,205,202, 23, 25,198,252,165, 94, 63,173,142,188,248,103,146,255,189,227,181,215, + 23,240,174, 92,185,130, 19, 39, 78, 96,195,134, 13,213, 0,254,207,201,215,167,188,140, 70, 49,119,233, 18,218,103,103,147,240, +210, 82, 30, 30, 80, 12, 74,221,160,247,134,130,224,235,118, 2, 34, 30, 69,124,139,171,180,223,109,201,189,241,127,103,139,228, + 39,245,102,114, 13,149, 55, 32,222,241, 42, 62, 24,166, 65,222,210, 65, 88, 29, 91, 13,239, 31,231, 0,242, 18, 84,115,226, 11, + 86,205,171, 1,220,141,234, 63,119,254, 39,252,251,223,155,208,201,175, 55,254, 60,126, 14, 7,100,151, 16, 59,180, 39,226, 70, + 88, 42, 26,199,227,131,118, 97,162,196,216,254,221,176,124,229,135,216,127, 65, 13, 31,105, 15,140, 31, 63, 1,191, 28,218,137, + 61,191,108,177,188,156,217, 4,145,160,241,126,142, 99,205, 48,179, 22,107, 6, 86,107,134,166,105, 24, 12, 6,232,245,122,104, +117,122,232,117, 90,232,117, 90,232,140, 6,208, 70, 67,195,238, 47,189, 47, 84,213,102,168,245, 44,212,122,214,242,191,134, 69, +181,150, 65,181,142,129, 66,110, 70,149,220,132, 42,133, 9, 85, 85, 38, 84, 86,210,184, 83,105,106, 84, 1,184,235,254,191,215, + 84,227,243, 56,240, 8, 1, 87, 39,234,159, 35,142,235,220,219, 73,111,163,251,208,238, 53,231,217, 27,179,107, 60, 2,199,246, + 30,195,149,162, 43, 55, 92,169,112,219,182,109,251,149,227,184, 94,241,241,241, 73, 81, 81, 81, 33, 0, 40,150,101, 69, 38,147, + 41,112,254,252,249,126, 13,184,130,235,133, 48, 44,236,253,117,235,214,141,139,143,143, 71, 84, 72,136, 83, 67, 87, 77,116,255, +199, 0, 64,116,183,110, 14, 3,216, 58,183,110, 29,155,150,150,134, 63,139,138,212, 59, 14, 28,192,229,203,151,107,172,254,174, + 93,187,194,122,143,222,113,224, 0,138,138,138,112, 37, 47, 79,239, 72,230,130,247,223,199, 91, 75,150,212,184,247,109,255,219, +206,109,255,187, 18, 11,144,146,146,201,141, 26, 53,234, 85,123,210,183,125, 14, 28, 56, 16, 41, 41,153, 78,117, 76, 87, 47, 23, +228, 49, 12, 3,154, 54, 66,126,167, 28, 21,183,203, 80, 89,118, 7,149,101,119, 32, 47,175,128,178,170, 10, 70,173,214, 18, 63, +163, 84,194,137, 32, 64,230,253,180, 53,252,247,211,214,240, 1,168, 1,176,131, 7,244,185,231, 33,187,184, 0,167,209,182, 99, +116, 76,105, 65,158,172,239,160,187,105,232,216,255,201, 24,101,197,117, 89, 83,234, 7, 73, 84,212,178,252,221, 65,190, 92,139, +226,151, 30, 2,119,227, 60, 66,255,123, 6,222,235, 79,227,246, 20, 41, 6,238, 47, 7, 17,136,192, 39, 0,159,114,172,128,158, +191,112,129,252,235,195,229,152,247,214,155, 48,177,102, 92, 46,188,138,233, 83,167, 65, 40, 22, 99,215,143,187, 1,147, 25, 70, +131, 17, 71,243,142, 67,175,175,198,172,153, 51, 15,191,252,242,203,141,149, 53,153, 52,105, 82,236,152, 49, 99, 64, 8, 65, 86, + 86,214, 61, 46,253,183,223,126,219,233,247, 12, 14, 14,198,173, 91,183, 0,128,159,158,158,142,138,138, 10,244,238,221, 27, 1, + 1, 1,160, 40, 10, 39, 79,158, 4, 69, 81, 32,132,224,214,173, 91, 8, 14, 14,118, 70,236, 7, 52, 77,143, 4,240,131,221,181, +169, 35, 70,140, 72,123,233,165,151, 2,211,211,211,197,132, 16, 10,192, 78, 88,102, 1,220,113, 32,111,225, 9,147, 41,186,174, +188,103, 22,237,216,250,244,180, 57,100,220, 43,233,200, 57,113, 17,105,105,105,172, 90,173,126, 1,150,217, 5, 78,121,183, 58, +249,250, 6,180, 47, 43,195,112,157, 14,109, 4, 2,111,111, 30,239,129, 45,183,223,175, 95,191,154,195,169, 33, 0, 0, 5, 91, +142,223,152, 43,215, 26, 79, 3,200, 7,208, 38,247,106,197,231, 35,187,133,189,199,191,113, 34, 8, 27,102, 0, 34,111,192,168, + 5, 56, 14, 38,158,248,206,209, 63,111,127,137, 70, 86, 95,218,252,221,103,177,211,166, 39,201, 0, 64,203,154,112, 77, 89, 12, +192,140, 78,126, 81,136,141,237,131,176, 86,255,159,189, 43, 13,107,234,218,218,239, 62, 25, 8,160, 34, 56,139, 86,197,138, 90, +181, 14, 88, 17,181,146, 40, 90,171,181,195, 87,163,182, 94, 91, 63,109, 9,106,175, 83, 7,180,181,215,222, 94, 91,245,222,139, +218, 81, 98,135, 79,219, 91,111, 53, 88, 91,167, 58,160, 9, 42, 34,136, 86,235, 12,130,138,160,136,146, 48, 37, 64,166,253,253, + 72, 78, 12, 33,144,147,128,162,237,121,159, 39, 15, 57, 67, 22,251,236,189,207, 94,239, 90,123,237,181,219,163,184,180,204,230, + 43, 48,154,113,179, 68, 95,239, 67,117,122, 36, 10,249,121,246,101,158, 68,136,113,253,109, 49, 0,123,206,152,176,119,103, 18, +110,221,185,129, 86, 45,109, 43, 9, 90,138, 69,120,124,240, 0,168,127,174,199,165, 11, 33,196, 86, 51, 44, 16,192, 74, 8, 24, +139, 21, 48,153, 97, 17, 9, 1,194,128,125, 39,173, 20,182, 92, 1,245,224, 87,245, 21,242,244,136,230, 52, 64, 76, 33, 20, 57, +121, 24, 76,128,153, 2, 85, 70,192, 82,109, 1, 33, 4, 68, 76, 96,182, 0,250,106, 32, 35,173,148, 12, 24,208,153,186,117,249, +179, 61,139,177,130,216,221,255, 54, 82, 64, 96,177, 50, 96, 4,246,149, 2, 0,168,128, 2,148,155, 23,192, 89,249,187, 59, 78, +221,157,218,141,107, 71,155, 52,105, 82,159,164,164,164, 53, 0, 6, 36, 37, 37,237, 73, 74, 74, 58, 60,105,210,164, 55,186,119, +239,110, 34,132,180,250,228,147, 79,246, 45, 94,188,120,218,202,149, 43, 83,234, 33,159,172,245, 47,124,235,173,183,150,189,245, +214, 91,216,179,103, 15,244,183,106,191,203,221,218,180,193,149, 43, 87, 0, 64,205, 37,145, 79, 93, 73,127,222,120,227, 13,233, + 23, 95,124,161,254,252,243,207, 49,184,103, 79,217,241, 11, 23, 60,186,138,143,158, 57,163, 25,222,191,255, 83, 23,143, 31,239, + 10,192, 15,192,167, 38, 63, 63,136,170,171,209,163, 67, 7, 44, 90,180, 8,169,169,169,171,194,195,195, 83, 82, 83, 83, 15,228, +231,231,123, 32,119,181,243, 0, 52, 32, 6,160, 6, 15, 76, 73, 73, 33,241,241,242,227,199,142, 21,165, 42, 20, 10, 49, 0,196, +199,203,135,173, 90,165, 74, 3,199, 36, 64, 93,251, 63,246,110,229,205,194,177, 86,179,165,151,190,180, 20,165,119,110,131, 16, + 6,148, 90, 81, 85, 85, 5, 74, 41, 40,165,184,114,254, 2, 76,198,106,252,150,156,236,169, 14,157,199,156,150, 0,152,241,178, +104,235,120, 89, 52,156,151, 5,218,167, 8, 56,163, 83,143, 33,210,252,236, 12, 53, 0,116,237,210, 5,167, 51,108, 60, 57,231, +183,237, 0,128, 54,143, 12,146,221,206, 59,217,100, 30,128,193,191, 22, 33,243,105, 96, 64, 68, 12,138,230, 14, 67,251, 47,143, + 34, 75,171, 71,176,152,160, 88,171,131,144, 16,143, 30, 0,199,187,153,154, 90,227,206,238,221,187,211,241, 19,158,198,206,237, + 59,177,101,203, 22,124,240,222,251,216,167, 57, 0,129, 80,128,208, 78,161,209,165,165,245, 47, 93,222,182,109,155,198, 78, 4, +164, 99,199,142,173, 17, 11,176,127,255,126, 92,190,124,185, 74,169, 84,118,112,245, 38,185,237, 47, 93,187, 34, 55, 55, 23,143, + 61,246,152,121,193,130, 5,226, 31,127,252, 17, 65, 65, 65,184,120,241, 98, 45,207,107,110,110, 46,186,114,111,103,231,196,115, +211,159,120,226,137, 15, 95,122,233,165,160,204,204,204,230, 85, 85, 85,255,235,239,239,255,140, 61, 48,240, 23,142,242,156, 23, +202, 79,127,230,175, 63,110, 28, 49,250, 5,242,207,100,128,116,124, 22, 31,175,125,151,106,179, 47,206, 4,160,242,162,153, 73, +185,201, 84, 34,246,243, 67, 11,177, 24,254, 22, 75,181,190,230,146,181, 7, 14, 53, 8,192,124, 13,206,125, 34,173,206,154,175, +113, 76,105,230,125, 34, 45,249,181,188,202,172,143,124,180,245,248,144, 0,193, 19,130,234,170, 64, 51,101,202,139,203,141,199, +210, 46, 23,238, 45,208, 26, 82,230,107,112,179, 46,146, 49,237, 47, 75, 53,135,142,166,201, 0,168,173, 2,118,154, 79,128,203, +101, 55,241,183, 55,102,194, 96,168, 70, 89,165, 45, 6,192,200,248, 97,243,182,250,211,236,230,231,165,145, 23,158,253,171, 77, + 89, 90, 88,203,217,140,113,253, 8,166,206, 89,141,128, 0, 63,180,240,151,200, 0,168,179,207,158,148,109,248,108, 91,189, 3, +146,144,154, 97, 36, 54, 18, 0, 66, 96,161,212, 70, 4,204,246,229,126,132,129,208,106,133,217, 30, 28,232,137, 4,148, 84,182, + 68,101,117, 49,196, 66,198,145,230,204,108, 5, 76, 38, 10,147,153,162,162,210, 10, 34, 32,176,128,192,100,189,235,186,119, 7, +139,149, 1, 67, 44, 32, 22, 2,202, 80,135,251,159,212, 97, 60,179,146,206, 93,252,145,120,202, 13,125, 33,237, 66, 67,251,142, +195,109,209,175, 95,191,155, 97, 97, 97, 47, 92,189,122,181,199,150, 45, 91, 50, 0, 60,151,148,148,244,156,243,205, 43, 87,174, +212, 44, 94,188, 88,182,114,229, 74, 79, 10,194, 81, 33,113,113,113,117,222,244,226,171,175,218,124,128,222, 37, 6,162, 46,110, +127, 0,192,144,222,189,101, 25, 28,148,191, 99, 0, 62,125,218, 17,173, 58,172, 95, 63,107, 66, 66,194,231, 19, 39, 78, 52, 95, +186,116, 73,120,237,218, 53,116,109,213, 42,109,231,206,157,156, 2, 20,239, 81, 30, 0,103,229,126, 43, 37, 37,197, 57,198,227, +140, 83, 61,123, 36, 1,170,149,171,244,242,197,241, 47, 94, 60,112, 48,173,101, 96, 96,139, 50, 93, 9,204,102, 51,168,253, 61, +208,221, 42, 66,153, 78, 7, 74, 41, 6,198,196,200,126, 75,246,152, 7,201,140,187, 49, 39,140,125, 57, 32, 19, 57,232,113,140, +151, 69, 59, 86, 1,100, 95,189,202,153, 4,196, 76,120, 73,154,188,235,191, 14, 43,255, 23,213, 55,106, 0,104, 19, 54, 92,118, + 59, 55, 85, 3, 0, 77,163,252,105,109, 18,128,175, 48, 32,238,111, 40,180, 90,209,127, 67, 6, 50,198,181, 67,159,157,183, 32, + 36, 64,115,145,111,198,226,206,157, 59,201,148,151,166,208, 81, 99, 70, 99,251,214,159,241,143, 85, 43, 17, 95, 90, 10,106,181, + 98,243,230,173, 40, 40, 40,120, 6,192, 78, 79,114,220, 17, 1, 0,120,225,133, 23, 78,129,227, 92,246,134, 13, 27,200,216,177, + 99,233,201,147, 39,197,131, 6, 13,194,232,209,163,161, 86,171,241,200, 35,143,160,186,186, 26,209,209,209,160,148, 90, 79,158, + 60,201,136, 68, 34, 95, 50, 2, 62, 22, 20, 20,180,102,202,148, 41,162,243,231,207,183,168,174,174,174, 43, 48,144, 43, 6,134, + 14,152,188,113,192,200, 41,228,155, 20,160,172, 18, 48, 94,217, 99,213,102,171,103,160,102, 96, 32, 39,125,170, 45, 45, 53,139, + 77, 38, 24,196, 98, 8,205,102, 15,211,227,247, 6,108, 30, 0,103,203,223,221, 57,183,174, 84, 39,229,207, 30, 95,248, 68, 90, +145,119,237, 78, 69, 26,128, 14,246,151,183, 26, 64, 1,128,220,249, 26,120,116,113, 42,191,220,165, 25, 49,162,159,204, 66,155, +169,157, 95,142, 10,125,153,109,221, 63, 19,128,156,114,144,181, 95,110,226,244,128,219,182,127, 70,110,107,115,165, 96, 12,106, +231,234,109,214, 44, 8, 22,147, 14,160,122,140,235,199,109, 66,215, 4, 1, 64,169, 77, 81, 67, 0, 49,181, 19, 1,187,242,183, +229, 0, 4,192,145,200,165,157,184, 78, 34,250,118,160,102,147, 22, 66,187,247,135, 82, 10,139,153,162,202, 4,148,149,155, 97, + 2,133,153, 50, 16,138, 8,238,220, 50,213, 89,206,227,199, 87, 17, 0, 24, 22,245, 54, 37, 38,155,245, 79, 1, 80, 74, 0,106, +183, 24,168, 0, 68, 96,133,213, 42, 68, 86,246, 86, 78,207,252,218, 63, 94,147, 93,205,185, 90,159, 2, 22,193,182, 84,163, 62, +237,228,168,249,101,203,150,177,254,209,211,118,171,248,174,162,126,241, 69,233,214,173, 91,213,118, 18,160,246, 68, 2,214,171, + 84,166,223,206,156,145,119,237,215,207,242, 68,175, 94,122,123, 31,173,134, 75, 22, 45,249,184,113, 54,139,163, 95, 63,207,211, + 29,111,191, 45, 3,128,193, 61,123,214,186,150,121,233,146, 38,227,130,239,100,168, 95,239,222, 95, 50, 12, 99,185,120,252,120, + 96,187,118,237,238,164,230,231,111,244,100,245,223, 7,173,227,220, 15,244,246,128, 63,118,106,160,194,165,173,185,144,128,243, +242,197,241,145,219,191,254,102,107, 88,183,174,143, 85, 87, 87,193, 98, 50,195,106,181,162,121,112, 48, 74,181, 90, 86,249,115, + 33, 81, 37,127,127,243,175,109, 1, 24,179,175, 94, 21,179,243,255,233, 39,127,199,120, 89,180,117, 89,194,103,158,146, 3, 57, + 48,103, 94, 60,189,120,233,162,204, 89,249, 3,192,168,167,158,147, 29,220,251,139,230,118,110,170,239,149, 88, 71,128,159,251, +243,220,117,216,224, 95,139,128, 95,223,112, 28, 63,250, 75,161,227,123,169,201,119, 99,113,243,127, 55,147,225,195,135, 63, 61, +118,194,184,221,175, 79,159,117,228,241,254,253, 70,108,255,101, 7,210, 78,157,192,137, 19, 39,118,213,231, 6,174,135, 8,204, +218,182,109,219,215,219,182,109, 27,186,109,219, 54,206,133, 27, 59,118,236,168,125,251,246, 29,220,185,115, 39,194,194,194, 48, +102,204, 24, 4, 5, 5,101,149,150,150,134,159, 59,119, 14,185,185,185,140, 72, 36,194,216,177, 99, 99,246,237,219,231,237,163, +158, 47, 45, 45, 93,181, 99,199,142,250, 2, 3,189,193,111, 5,167,182,172,248, 57,233,217,119, 43, 67,167,161,242,248, 82,235, +141,195, 31, 77,247, 81, 94,213,181,162, 34,209,155, 89, 89,249, 22,131,129, 57,205, 48,162,246, 2, 65, 97, 97, 19, 57, 1,220, +101, 3,244, 52, 5,224, 22,243, 53,208, 3,248,221,254,241, 9, 71,142,156,209,196,197, 45,150, 37, 42,255,161, 14,237,210, 3, + 64, 53, 68,126, 18,228,223, 44,195,166,157,169,196,123,121,187, 52, 51, 94, 91,136, 13,223,254, 4, 88,175, 1, 16,194, 92, 85, +137,208, 14, 65,178,143,222,158,197,217,154,131,197, 10, 33, 99,133,137, 8, 33,162,230,187, 68, 0,102,128, 90,192, 53, 48,204, + 25, 39,206,222, 36, 0,208, 62,132,161, 34,161,205,218, 55, 91,109, 9,140, 74,202, 41, 44,102, 64, 32,180,194, 98,230, 54,114, + 28, 77,251, 23, 1,128,200, 33,139, 40,216,156,240, 12, 96, 37, 54,119,255,165,236, 29, 94, 21,242,235,247,191,214, 52, 66,255, +226,100,174,176,202,223,201, 19,224,113, 57,214,241,139, 23,147,142,187,184, 12,235,185,215,227, 61,141,153, 58,184, 22,185,181, + 45,241, 75,180,217,214,103,124,146,209,200,121, 0, 92,235, 86,239, 97,169, 21,167,190,163, 90,185,234,162,124,113,124, 95, 0, +130,139, 41, 41,166, 42, 67, 37,172, 22, 11,122, 71, 68,200, 58,132, 63,134,227,191,238,224, 86,199,148, 76,217,251,235, 46,199, +225,176,199,194, 28,223,247,254,186,171,214,113,125,161,241, 95,126,106, 35,200,163,159,122, 94,118,254, 98, 14,110, 94, 59,163, + 6,128,131,123,127, 81,183,123,164,175,236, 86,222, 89,175,219,125,242,228,201,240, 54,189,175,133,248,213,123, 61,239,133,246, +248,245, 70,213, 61, 31,240, 83, 83, 83,127, 85, 42,149, 76,102,102,166,245,192,177, 20,180,106,221,202,117,165,135, 87,216,182, +109,219, 55, 74,165,242, 59,133, 66, 97,242,230,119,111,189,245,150, 26, 0,153, 49, 99, 6,205,201,201, 65, 70, 70, 6,202,203, +203,195,155, 55,111,142, 86,173, 90, 57,246, 2,240, 65,249,179,248, 87, 74, 74,138, 40, 45, 45,173,159,209,104, 92,138,154,115, +249,190,224,189,179,155,255, 34, 10,234,254,221,162,210,156,125,211, 26, 32,207,252, 99,122,250, 51, 0,198, 0,248, 13, 86,107, + 57, 60,199, 35, 52, 58,216, 85, 0,238,206,251, 68, 0, 60, 14,130, 74,165,112,221,186,117,158, 93, 85,123,143,106, 58,117, 29, + 77,110,229,167,209,182,161,157,161, 45, 55, 99,211,246, 35, 62,119,208, 13, 95,175,177,255,182, 29, 5,110, 33,184,185, 16, 31, + 45,121,221,171,151,254,171, 99,217,247,108,157,102,161,214, 74, 0, 64,226, 47,162,198, 74, 19,172, 0, 2, 2, 2, 96, 48, 27, +136,197,236,189,188,244, 12,219,158, 1,145, 79, 44,164, 86, 42,192,213, 43,187,155,114,141, 41,215,165,131,252, 46,129, 28,234, +199, 89,225, 55,242,180,128, 49, 62, 94,238, 7,192,178,106,149,170, 65,166,136,106,229, 42,118, 35, 31, 71,155,230,156,245,110, +157,254,188, 21,159,249, 68,198, 92,183, 2,118,198,129,189, 63,107, 92,251,218,173, 60,223,242, 7,120,218,216,199,149, 3,155, +137, 31, 42,153,250, 87,164,230,148,155, 17,222, 92,120, 95, 94, 21,251, 90,253, 70,123,231,188, 85,254, 53,198,103,223, 55,252, +225,130,143,141, 70,227,207,128,231, 77,233, 56,226,157,210,156,125,155, 80, 51, 54,192, 91,152, 0,148,192,187,184,129,123, 70, + 2, 56, 13, 62,190,238, 35,204,131,135, 51,122,244,232,129,236,236,108,190, 34,120,240,224,193,227, 33, 1,195, 87, 1,143,198, + 0,175,252,121,240,224,193,131, 39, 0, 60,120,240,224,193,131, 7, 15,158, 0,240,224,193,131, 7, 15, 30, 60,120, 2,192,131, + 7, 15, 30, 60,120,240,104,114,212, 8, 77, 61,117,234,148,207, 81,155,238,130, 9,121,121,188, 60, 94,222, 3, 35,175,222,232, +112,190,254,120,121,188,188, 63,150, 60,175, 9,128,211, 64,225, 45, 60, 13, 60,141, 41,143,199,131, 9,202,183,219, 67,217, 14, +156,239, 87, 42,149,129, 0,158, 56,114,228,200, 71, 2,129, 96,152,159,159, 31, 12, 6,195,209, 17, 35, 70,188, 7, 32, 67,161, + 80, 24, 30,132, 10,176,103,135, 84,255,153,199, 21, 74, 41, 61,123,246, 44,250,245,235,199,191,147, 60,188, 34, 0, 94,173, 67, +230,146, 40,199,157, 60,231,196, 39,222,202,251, 19, 14,232,156,240,212, 83, 79,201,246,238,221,171,225, 42, 51, 52, 52,180,214, +133,130,130, 2,215,193, 20, 42,149,138,112, 44,227, 61, 35, 1,117,229,243,111, 42,121,171, 87,175, 30,189,117,235,214,228,172, +172, 44, 0, 64, 88, 88,216,179,233,233,233, 59,124,109, 95,231,126, 79, 41,117,188, 31,236,121,246, 93,177,159, 39, 30,200, 51, +215,118,240, 70,249, 63,118,246,236,217,173,101,101,101,189,186,116,233,130, 59,119,238,160,170,170, 10, 0,134,109,221,186, 85, + 29, 24, 24,120, 81,169, 84, 62,175, 80, 40,234,221, 74,242,236,217,179, 94, 25, 4,169,169,169, 50,133, 66,161,241,230, 55, 42, +149, 74, 45,151,203,101,190, 36,128,162, 94, 38, 97,152, 60,121,178, 55,239, 7, 0,160, 75, 23,219, 14,184,229,229,229,168,174, +182,165, 65,215,235,245,222,188,111,245,226,204,153, 51,116,216,176, 97,232,221,187, 55,252,252,252,138,170,171,171, 31,225,135, +209, 63, 31, 92,147, 1,221,179, 68, 64,188, 21,123,111,241, 75,226, 56,143,247, 60, 63,123,143, 87, 50,213,234,187, 6, 82, 86, + 86, 22, 2, 3, 3, 29,131, 16, 11, 46,155,127,200,229,114,170, 82,169, 92,143, 73, 29,247,248, 84,183,209,209,119,183,115,117, + 39,191, 33, 32,132,208,145, 35, 71,202, 82, 82, 82,188, 82, 22, 91,183,110, 77,110,219,182, 45, 94,121,229, 21,232,116, 58,107, + 66, 66,194,246,149, 43, 87, 78, 93,188,120,241,102, 47,255, 63,126,253,245, 87,199,241,184,113,227,176,103,207,158,122,143,185, +136,117,233,203, 52, 34, 34, 2, 0,168, 83,102, 56,175,148,127,105,105,105, 90,247,238,221, 91, 0,128, 68, 34,129,191,191, 63, +138,138,138, 80, 82, 82,130,160,160, 32, 20, 21, 21,245,218,179,103, 79,134, 82,169,236,169, 80, 40, 10,235,147,215,183,111, 95, +200,229,114,132,133,221,205,250,183,106,213,170, 26,247,196,199,199, 3, 0,142, 29, 59,166,246,165,223, 52, 36,251,227,218,181, +107,235,186,228,216,171,192, 87, 4, 6, 6,226,252,249,243, 16,137, 68, 48, 26,141,216,179,103, 15,178,179,179,177,100,201,146, + 6,245,227,224,224, 96, 1,128,152, 67,135, 14,237,137,142,142,190,245,252,243,207,183, 75, 78, 78,134, 64, 32,104,211,178,101, + 75, 1,120,252,169,149, 63,123,206,149, 4,252, 97,130, 0, 35, 35, 35,165,247,219,226,110, 74,132, 14, 94,238,248,248, 10,157, + 78,231,176,248,245,122, 61,214,175, 95,239,248,120, 49,208,186, 61,158, 52,105, 18,149,203,229, 20, 0,117,189,199, 91, 28, 58, +116, 72,253,246,219,111,163, 91,183,110,141, 86,127, 93,187,118, 37,239,188,243, 14, 40,165, 72, 73, 73, 81,123,219,238, 89, 89, + 89, 24, 55,110,156, 21, 0,196, 98, 49, 19, 30, 30,142,132,132,132, 31,219,180,105, 67, 35, 35, 35,199,123, 97,113,222,171, 46, + 66, 34, 34, 34, 40,251, 92, 39, 78,156, 96,247, 3, 96,219,133,179,219, 95,167,211,109, 21,139,197, 45, 0, 96,238,220,185,152, + 54,109, 26,196, 98, 49,252,253,253, 33,145, 72, 64, 8,129, 64, 32, 64,105,105,105, 11, 0, 9, 74,165,178, 94,217,241,241,241, + 8, 11, 11, 67,110,110,174,227, 19, 31, 31, 95,227,211, 16,200,229,114,153,253, 57,125, 30, 19, 22, 46, 92,232,248, 56,143,151, + 46,231, 57,111,244,210,165, 75, 23, 4, 6, 6, 98,233,210,165, 8, 12, 12,196,246,237,219, 81, 89, 89,217, 40,202,223,254, 46, + 83,157, 78,247,191,211,167, 79, 71,143, 30, 61,218,237,217,179, 7,183,110,221,194,245,235,215, 81, 82, 82, 98,188,159, 99,147, + 82,169,148,230,231,231, 83,165, 82, 41,117,119, 45, 59, 59,155, 94,190,124,249, 79,145,128,142, 82,218,171, 41,149,127,108,252, + 74,196,198,175,172,147, 24,220, 23, 2, 64,220,160,190,243,190, 32, 61, 61, 93,221, 24, 36, 96,218,180,105, 15, 13, 9,104, 40, + 12, 6, 67, 45,171,223,151,230,101,149,201,164, 73,147, 28, 86,126, 82, 82, 18, 26,170,248,157,173,127,149, 74, 69, 70,142, 28, + 41, 83,169, 84, 53, 60, 2, 13,193,150, 45, 91, 8, 0, 18, 29, 29, 45,115,245, 52,112, 28,116,205,118,111, 0,218,182,109,139, +229,203,151, 87,189,249,230,155,198,220,220,220, 93, 43, 87,174, 28,211,212,237,235,180, 7, 0,113,110, 39, 47,219,229,137,236, +236,236, 94, 0, 48,107,214, 44,148,150,150,226,198,141, 27, 16,137, 68, 16, 10,133, 16, 10,133, 16,137, 68,240,247,247, 71,101, +101, 37,146,147,147, 95, 6, 16,236, 73,104,110,110, 46, 84, 42,149,227,227,236, 9, 88,181,106, 21,146,147,147,125,126,110,149, + 74,165,177, 79, 1,168, 27,233, 93,174, 43,113, 55,231,241,243,234,213,171,216,181,107, 23,150, 47, 95,142, 46, 93,186,160,117, +235,214, 72, 73, 73,193,146, 37, 75, 16, 24, 24, 8, 0, 16, 8, 26,100,168,119,152, 57,115,230,148,127,253,235, 95, 72, 79, 79, +199,141, 27, 55, 96, 54,155, 95,105,213,170, 85, 48, 0,211,253,238,123,161,161,161,136,141,141, 85,231,228,228, 80,103,229, 31, + 27, 27,171,126,244,209, 71,241,128,239,146,219,187,129,191,247, 3,208,117,213,170, 85,207,164,167,167, 71, 3,232,223, 20, 15, +225,172,248,157,191, 55,133, 7,128,186,249,212,119,190,201, 72,192,248,241,227, 27,131, 4, 80, 47, 62,156,241,226, 27,123, 27, +173, 65,178,178,178,160,215,235,235,116,243, 31, 61,122,180, 49,136, 65,131,113,232,208, 33,181,157, 88, 32, 37, 37, 69, 67, 8, + 65,219,182,109,213,141,217, 57, 89,247,191,221, 19, 80, 47, 86,175, 94, 61,126,248,240,225, 20, 0, 18, 18, 18,196,223,126,251, + 45, 94,121,229, 21,214, 53, 47,249,253,247,223,197,246,107,251, 34, 35, 35,159,227,242,255,199,141, 27,135,167,159,126,218,225, +222,103,191,179,199,236,119,142,238,127, 0,128,221,250,119,215, 14,196,229,122,189,216,179,103,207, 71,173, 91,183, 6, 0, 92, +190,124, 25,121,121,121, 56,121,242, 36,140, 70, 35, 8, 33, 16, 10,133, 32,132,192, 98,177,192, 96, 48, 96,219,182,109,224, 50, +224,185, 76, 27,185, 37, 47,185,185,185, 13, 34, 1, 78,207,222, 32,111, 0, 26, 97,170,212,100, 50, 97,208,160, 65,208,104, 52, +184,122,245, 42, 6, 15, 30,236,184,166,209,104, 16, 18, 18,226, 32, 2, 62,160,227,204,153, 51,243,191,249,230, 27,196,196,216, + 54, 50,234,216,177, 35, 44, 22,203,247,176,229,166,191,175, 80, 40, 20, 26,150,124,134,133,133,225,248,241,227,148, 85,254, 44, +249,235,217,179, 39,151,241, 97, 8,128,239, 96,219,243,172, 62, 76, 0, 16, 11,160, 77, 35, 41,255,134, 18,128, 14,115,231,206, +149,189,243,206, 59,162,182,109,219,202, 1, 68, 61,168, 76,231,190,196, 0,220,207, 32, 64, 59, 9,144,165,167,167,107,124,149, +209,181,107, 87, 76,155, 54, 13, 63,252,240,131,175, 49, 1, 4, 0,253,225,135, 31,220, 94,220,189,123, 55,236,215,188,150,125, +236,202, 99, 24,218,237, 60, 10, 50,151, 54,168,158,156,231,252,147,147,147, 17, 19, 19,131,216,216, 88,135,242,239,220,185,115, + 99,144,190, 6, 17,129,232,232,104,233,161, 67,135,112,231,206, 29, 25,123, 78, 42,149,202, 84, 42,149, 58, 58, 58, 90,234,237, +188,189,135,255, 37,227, 66, 0,182,110,221,186,139,157,251,215,235,245, 88,181,106, 21, 42, 42, 42, 32, 18,137,224,231,231,135, + 43, 87,174, 96,249,242,229,208,233,116, 72, 72, 72,248,121,229,202,149,163, 22, 47, 94,172,246,160,100,107,144, 1, 79, 49, 1, + 28,234, 28, 30,118, 0,116, 76, 7,120,122,222,144,144,144, 97,213,213,213, 48,155,205, 56,122,244, 40, 4, 2, 1,140, 70, 35, + 42, 43, 43, 97,181, 90, 29,239,177,201,100, 66,117,117, 53,251, 78,247,245, 36,183, 46, 55,127,124,124,188, 35, 30, 32, 44, 44, + 12, 69, 69, 69, 13, 38,162, 78,171, 2,184,246, 69, 45,128, 16,119, 23,214,172, 89,227, 83, 33, 18, 18, 18,240,246,219,111, 99, +224,192,129, 14, 15, 8,155, 62,123,224,192,129,184,116,233, 18,218,182,109,235,139,232, 46, 51,103,206,188,250,205, 55,223, 56, +143,159,161, 55,110,220,184,209,148,138,101,240,224,193,132, 85,250,131, 7, 15,198,224,193,131,213, 0,112,233,210, 37,244,234, +213,139,107, 59,156, 2,224, 15,224, 71, 0, 83,225,178, 37,184, 29,111, 0,248,204,254,253, 61, 0,189, 0,207, 91,212,123, 80, +254,255, 3,224, 39, 95,159,125,213,170, 85,125,223,121,231,157, 82, 0, 47,118,235,214,173,208, 78, 80, 18,239, 87,221,179,187, + 1,174, 95,181,216, 97,249,175, 95,181,216,113,237,190, 19,128,251,141, 7,133, 4, 76,155, 54,141,190,247,222,123,181, 92,129, +190, 40,255,198,180,254, 1,184,181,254, 89,171, 95, 36, 18,161,176,176,176, 73,149,191,179,245,239, 28,208,165, 86,171,157,189, + 0,247, 61, 96, 51, 43, 43, 11,175,188,242,138, 1, 64, 64, 96, 96, 32,222,127,255,125,136, 68, 34,199,245, 25, 51,102, 0, 0, +130,131,131, 49,113,226, 68, 28, 57,114,228,224,125, 44, 39,113,246, 0,212, 71, 2, 34, 34, 34, 92,183,138,117, 75, 6,140, 70, + 35,180, 90, 45,170,170,170, 16, 20, 20, 4, 63, 63, 63,152,205,102, 80, 74, 97,177, 88, 96, 52, 26, 97, 50,153, 96,177, 88,156, + 9,253,157,250, 10,153,155,155, 91, 35, 0,144,157, 14,112,246, 8, 56, 95,111, 40,124, 8, 8,148,212,117,193, 57, 38,192, 27, + 50,176,124,249,114, 76,152, 48, 1, 93,187,118, 69, 64, 64, 0,164, 82, 41,180, 90, 45, 2, 3, 3,161,211,233,176, 97,195, 6, + 48,140,215, 14,217, 78, 51,103,206,188,186, 96,193, 2,108,223,190, 29,207, 61,247, 28, 0,180, 71, 19,108, 65, 91,151, 39, 32, + 40, 40, 72, 54,101,202, 20, 53, 0,108,222,188, 89, 54,117,234, 84,111,218,194, 8, 96, 26,128, 31,234, 33, 1,206, 83,109,143, + 0,232, 7, 32,195, 71,229,255, 24,128, 23, 26,104,236,246,202,200,200,232,116,229,202, 21,185, 93,249,179, 59,104, 54, 9, 88, +197, 95, 23,254,144,153, 0, 27,170,252, 89,248,106,165, 59, 15,200, 31,125,244, 81,131,149, 63,139, 65, 3, 7,224,192, 65, 53, + 54, 29, 12,112,144,130, 99, 87, 30,107,208, 51, 70, 68, 68, 32, 55, 55, 23, 73, 73, 73,232,220,185, 51, 54,110,220,232,181,213, +165, 84, 38, 74,157, 60, 56,141,162,252,217,249,248,162,162, 34,153,235,181,145, 35, 71,202,146,146,146, 26, 45, 22, 0,176,185, +255,185,122,159,116, 58,221, 5,251, 75,109,221,188,121, 51, 54,108,216, 0, 0,248,241,199, 31,161,211,233,216,219,204,151, 46, + 93, 66,155, 54,109,154,228, 29,112,137,246,175, 69,206,184,238, 19,159,155,155,123,212, 98,177, 64,167,211,225,206,157, 59,208, +233,116, 48, 24, 12, 48, 24, 12,168,168,168, 64, 89, 89, 25, 74, 75, 75, 81, 89, 89,137,234,234,106,118,110, 55,173, 62,153,174, +202,221, 93, 32,169,235,170, 0,174,176,187,250,169,155,115,222, 32,160,177,219, 99,227,198,141,144, 74,165, 8, 8, 8,192,249, +243,231,161,209,104, 16, 24, 24,136,191,253,237,111, 56,114,228, 8,150, 44, 89,226, 45, 1,104, 63,115,230,204,235, 83,167, 78, +197, 79, 63,253,196, 42,255,142, 15,138,242,183,141, 11, 74, 41,171,252, 1, 96,202,148, 41,234,139, 23, 47,122, 59,181,202,146, + 0,216, 73,128,235,116,192,101,167,239,121, 0,206, 52, 64,249,255,143,125,220,242,217,250, 39,132, 92,140,140,140, 76, 11, 11, + 11, 75, 34,132, 4, 17, 66,154,217,203,221, 36,112, 13, 2,108, 18, 2,112, 63,130, 0, 27, 91,249,219, 21,119, 99, 88,110,228, +163,143, 62,106,144,242,127,241,141,189, 24, 52,240,174,235,102,235, 79,219, 28, 30,129, 3, 7,213, 62,145, 0,133, 66, 1,251, +210, 48, 24, 12, 6,236,223,191, 31,203,151,219, 86, 20,156, 57,115, 6,102,179,217, 11, 89,113, 26,192, 22,248, 71, 41,101,131, + 1, 27,164,252, 89,235,191, 62, 55,127, 99,197, 2,176, 68, 66, 42,149,202, 60,221, 27, 22, 22, 54, 54, 33, 33, 33, 34, 61, 61, + 93,248,221,119,223, 49, 23, 47, 94,196,140, 25, 51,204,108, 61, 38, 36, 36, 32, 61, 61, 29,223,125,247,157,240,218,181,107,136, +140,140,244, 40,243, 94,196, 0,176,150,180, 11, 9,160, 44,233,227,138,240,240,240, 76,179,217, 12,163,209,136,219,183,111,163, +176,176, 16,183,110,221,194,173, 91,183,112,251,246,109,104,181, 90, 24, 12, 6, 84, 87, 87,163,180,180,148,253,159,249,245,201, +100, 3,253,156, 73,104, 61,101,247, 74,249,179, 57, 0, 92,207, 53,164,127,184, 89, 13,224, 32,121, 92,101,100,103,103,227,210, +165, 75, 48, 24, 12,136,138,138, 66,255,254,253,177,113,227, 70,188,251,238,187, 16,139,197, 16, 8, 4, 16, 10, 57, 59,100, 59, +205,156, 57,243,230,212,169, 83,145,145,145,129, 15, 62,248,128,181,126,111,226, 1, 89,198,156,153,153, 73,217, 57,255,147, 39, + 79, 98,253,250,245, 50, 0,232,217,179, 39,156, 3, 3, 27, 72, 2,230,195,230, 94,159, 4, 96, 14,128, 72,248,230,254,191, 0, + 96,171,253,127, 76,107, 8, 1,176,227, 52,128,117, 0,158, 1,240, 60,128,205,247,179,238,217, 72,127,119, 65,128,174,171, 0, +238,215, 20, 0,245,242,252, 31, 69,249, 59, 72, 64, 3,166, 18,106, 40,127,119,199, 7, 14,122, 63,190, 57, 15,186, 1, 1, 1, +232,221,187,102,220, 75,122,122,186, 87,242, 38, 77,154,132,164,164, 36,176, 68, 0, 0,181,159,243,122,221,249,198,141, 27,213, + 0,176,103,207, 30,153,187,136,245,148,148, 20,205,213,171, 87,221, 90,143,238, 80, 87,210, 31,150,104,164,164,164, 32, 58, 58, + 90,166, 86,171, 61,246,157,244,244,244,253, 43, 86,172, 24,157,154,154,122, 32, 60, 60, 28, 89, 89, 89,208,233,116,194,224,224, + 96,204,156, 57, 19, 90,173,246, 90,106,106,106,151,240,240,112,164,166,166,146,184,184, 56, 79,228,184,214,156,127, 3, 98, 0, +106,188, 91,108,190, 4,123,238, 4,135,103,198,105,254,223, 99,123, 12, 29, 58,244, 93,141, 70, 51,207, 98,177,160,172,172, 12, + 38,147,201, 49,239, 95, 85, 85, 5, 74, 41, 40,165,184,116,233, 18,140, 70, 35, 98, 98, 98, 94, 82, 40, 20,102,119, 73, 71,234, + 66, 76, 76, 12, 98, 98, 98,106, 4,253,121, 59, 5,224,172,232,237, 46,127,234,220, 63,236,171, 2, 26,123, 92,227, 60,126,178, + 75,253,222,124,243, 77,104, 52, 26,200,100, 50,100,103,103,163, 89,179,102,200,203,203,131, 64, 32,224,234, 1, 32, 51,103,206, +188, 62,125,250,116, 28, 62,124, 24,127,251,219,223, 0, 32, 20,192, 13,220,205,255,208,228,150, 63, 59,190,228,230,230, 34, 34, + 34,130,237,103,178,216,216, 88,117, 88, 88, 24, 46, 93,186, 68, 57, 6, 2, 58,147,128,169,118, 2,240, 35,128,163, 0, 20, 0, +164, 0, 10,193,163,241, 58,112, 99,103,227,115, 23,240,179,106,213,170, 58,207, 55,165,242,183,175, 0,184, 23, 44,218,103,153, +215,243, 61,247,111,127,127,239,188,150,158,130,196,188, 69, 76, 76,140, 44, 41, 41, 73, 51,121,242,100,186,101,203,150, 26, 68, +192,133,240,113,174,135,184,184, 56,143,204,198,203,196, 64,212,133, 72,216, 70, 37,153,140,147,242,119, 26,204, 29,243,250,145, +145,145,127, 73, 72, 72,248,126,226,196,137,184,116,233, 18,174, 93,187,214,101,233,210,165,178,184,184, 56, 78,242,238, 81, 30, +128, 26,245, 92,135,226,227,148, 49, 80,161, 80,232, 19, 19, 19,151,237,222,189,251,239,102,179, 25, 37, 37, 37,142, 24, 0, 0, +184,125,251, 54, 74, 74, 74, 64, 41,101,173,118,175,180, 44, 59,255, 31, 17, 17,225,136, 96,103,207,115, 37, 1,110,172,252, 90, +211, 80,247, 64,249,123, 13,150, 4, 44, 94,188, 24, 41, 41, 41,152, 56,113, 34, 86,172, 88,129,183,222,122, 11, 66,161, 16, 18, +137,196,227, 24, 66, 41,181,206,154, 53, 11,223,127,255, 61,190,253,246, 91, 0,232,108,202,132,133,197, 0, 0, 32, 0, 73, 68, + 65, 84, 87,254,141,110, 80, 53, 4, 5, 5, 5,216,181,107, 87,141, 44,142,246,239,178, 81,163, 70,169,125, 92,242,104,177,147, +128,157,118,235,127, 40,175,252,235,134,187, 32, 64, 78, 4,192,155, 68, 28,190, 42,236,198, 70, 99, 40,255,134, 42,234,123,129, +249,243,231,203, 46, 94,188,216,168, 50,237, 46,210, 70, 93, 74,199, 42, 60,251,218,122,214, 43, 64, 9, 33,176, 90,173,216,186, +117, 43,103, 18,240,246,219,111,179,229,172, 21, 3,192, 48, 12,172, 86, 43,222,121,231, 29, 53, 87,229, 89,159,188,148,148, 20, +141,115, 86, 68, 31,250,221,127, 86,172, 88,113, 59, 53, 53,117, 15, 87,171,255, 62,120,219,136,171,183,167, 14,194,199,137, 4, +196,197,197,125,168, 84, 42,147,126,248,225,135,115, 98,177, 24,236,170, 0,171,213,138,150, 45, 91, 66,167,211, 65, 46,151, 35, + 38, 38, 38, 64,161, 80,120, 92,224,205,142, 47,206,193,127, 39, 78,156, 64, 76, 76, 76,141,241,196,211, 56, 20, 31, 31, 79,115, +115,115,101,174, 46,126, 95,211, 0, 59,195, 77,128,159, 25,128,121,205,154, 53, 18,187, 53,202, 56,125,188, 34, 1,206,137,127, +230,204,153,227,248, 94, 86, 86,230,113,108, 34,132,144,153, 51,103,210,239,190,251,238,121, 0,191, 60,136,138,199,174,232,137, +183,215,184,144,118, 23,220,124, 24,198,240,251, 13,118, 21,128, 59,197,207,105, 21, 64, 99, 43,245,186,228, 61, 40,228,225, 65, +238, 56,159,124,242,137,166,177,101,186,172,145,190,103,112,113,255,115,125,169,185,230, 66, 39, 94, 60,239, 61,125,214, 37, 75, +150,236,109, 72,125,142, 27, 55,174,198,178,216,167,159,126,186,134,103,192,203,185,127,226,165,183,135, 83,185, 21, 10,197,121, +165, 82,217,108,223,190,125, 31,231,229,229,205,171,172,172,132,197, 98,193,128, 1, 3, 48,120,240,224,132,152,152,152,120, 46, +202, 31, 0,142, 29, 59,230,248, 30, 29, 29, 93,227,188,235,177,135,113,133, 56, 19, 90,150, 76,216,227, 0,124,106,247,201,147, + 39,215,117, 73,232, 52, 94,138,239,213,184,226,193, 83, 97, 5,128,111,191,253,150,223, 48,133, 7,103, 18, 80,151,242,175,139, + 0, 52,118,231,226, 59, 43, 15,226, 37,179,255,211,213,141,179,194,191, 7,211, 2,141,242, 14, 42, 20, 10, 61,108,174,215,249, +236,185, 11, 23, 46,112, 81, 92, 14,244,237,219,183,209,199, 3,119,132,214, 87,151,255,189, 38,139, 60,120,253,113, 63, 73,128, +199,202,245,117, 31, 97, 30, 60,120,240,224,193,131,199,195, 11,134,175, 2, 30, 60,120,240,224,193,131, 39, 0, 60,120,240,224, +193,131, 7, 15,158, 0,240,224,193,131, 7,143,135, 16,102,120,177, 93, 49,143, 63, 39,132,124, 21,240,224,193,131, 7, 63,182, +243,248,147,119,146, 83,167, 78,249, 28,113,233, 46,152,208,131,188,122,215, 31,251, 32,175,177,203,199,203,227,229,253,169,229, +253,246,238, 53,159, 7,150,129, 31,119,193,189,150,119, 98,137,239,242, 34, 86,212,150,199,214,159, 82,169,148,154, 76, 38, 92, +185,114, 69,109, 52, 26, 33, 20, 10,145,159,159,143,151,130,186, 98,111,102, 38, 42, 31,239,140,161, 67,135,202, 4, 2, 1,187, +174,189,201,218, 87,169, 84, 62, 6,160,237,185,115,231,118,117,236,216,145,209,106,181,146,142, 29, 59, 46,247,247,247, 95,167, + 80, 40,110, 0, 64, 98, 98, 34,147,152,152,104,169, 75, 94, 98, 98, 98,115,187,183,192, 16, 23, 23, 71, 1, 96,233, 95,159,252, + 74,241,100,222,204, 77,153,225, 87,132,109,199, 14,109,214,188, 69, 5, 0, 74, 41, 21, 2, 8, 78, 76, 76,188,206,191,111, 15, +182,188,123,205, 18,185,110,250,226,109, 10, 92,175, 83,230,174,138,122, 74, 42, 12, 9, 82,231,100, 93,150, 61,234,215, 12,139, +206, 30,210, 60, 72, 44,171,158,124,228,252, 18,151, 38,198,132, 9, 19,164,187,119,239, 86, 39,188,107, 59,254,249,240,147, 56, +116,232, 16,167,118,249,203,140, 87,165, 12, 33,234, 75, 23, 47, 66,167,211,161, 75,151, 46,104,214,188, 57,182, 37,109,229,220, +174,147, 38, 77,170,241,226, 38, 37, 37,213,187,151,130, 61,187,162, 79,253,134,221,168,137, 82,218,176,126, 39,215,214,124, 85, + 85, 33,190,203,138, 88, 3,132,189,106,251,158,187, 1, 56,177,168,225,141, 58,233, 78,205,242, 37,181,230,244, 51,165, 82, 73, +245,122,189,108,219,182,109,234,220,220, 92,200, 69,173,208,190,115, 27, 84,233, 43,225,111, 48, 99,248, 91,175, 99,228,196, 41, +216,249, 77, 34,118, 28, 56,160, 30, 59,118,172,236, 1,232,194, 89, 22,139,165, 67,110,110,174,181,127,255,254,226,240,240,112, +156, 60,121,242,221,170,170,170, 9, 74,165, 50, 70,161, 80,104,227,226,226,172,245, 45, 9,139,139,139, 43,119, 62,254,226,139, + 47,152, 61,255,137,239,209,105,214, 64,188, 51,164, 79,155, 99,251,254,189,101,235, 25,233,169, 30,125, 71,173, 32,132,104, 21, + 10, 69,254,128, 1, 3,172,118,210,192,123, 26,254,100,110, 34,111,153, 6,167,108, 99,190, 40,255, 47,163,159,149, 70,181,233, +164, 38,160,200,174, 40, 65,135,142, 93,213, 38,171, 5, 75,250, 13, 67, 81,151, 54,178,111,118,254,194,137, 8,196, 78, 5,237, +213,157, 61, 18, 96,219, 62, 43, 14, 31,167,136,157, 10,244,234, 14, 44,250,168, 97,138,155,221,160,164,161,217,201,220,145,137, +198,146,219, 16, 80, 74, 41,150, 17,144, 15,235,189, 7, 88, 70, 48,249,130,252,129, 89,107,125, 87,249, 83,187,242, 31,137, 35, + 71,142,112,250,109,218,177, 23,169,217,212, 11, 42,213, 77,164,167,217, 18,214,100, 93,188, 4, 0,216,181,139,208, 75,151, 39, +201, 22,205,231,214, 46, 99,198,140,177,238,223,191,159, 73, 74, 74,194,193,131, 7,107, 36,195,113,133,143, 41, 84, 29,205,228, +166, 35, 83,234, 3,161, 96,211,133, 55, 56,103, 65,216,171,142,141,118,214,172, 89,211, 56, 4,192,169,158,236,187, 19,114, 66, + 78, 78, 14, 52, 91,182,168, 63,140,153,140, 1,211,230, 64,220, 46, 24, 16,218,147,253, 89, 41, 96, 21,193, 90, 77, 49,254,213, + 88,228,125,186, 18, 71,143, 30, 85, 43,149,202, 26,233,110,155, 0, 22,134, 97,218,182,110,221, 26, 26,141, 70,216,191,127,127, + 12, 25, 50,132, 41, 44, 44, 28,120,250,244,233,179, 74,165,114,144, 66,161, 40,180, 43,107,134, 99,221, 53, 27, 61,106, 76,216, +138,213,219,153,248, 25,103, 90, 12, 29, 55, 91, 54, 52, 50,249,201,183, 62,203,127, 38,252,137, 87, 34, 0,148,195, 22, 99,192, +212,165, 31,156, 19, 91,121,234, 71, 13, 38,164, 60, 92, 61, 9,158,188, 5,142,239,222, 4, 1, 82,182,113, 7,188,210, 15, 74, +165,146,241, 66, 17,186,110, 82, 65, 35, 34, 34, 16, 17, 17,225,115,158,120,229,203,177,210,151, 7, 70,169,123,118, 8, 69,247, + 14,161,120,188, 77, 71,132,250, 55,131,196, 10,116,243,107,134,160,236, 27,234,153,207, 60, 39,229, 34,171, 87,119,224, 98, 14, +131, 11,151, 3,112, 54,167, 5,158, 31, 19,136,213,239, 9,208,171, 59,105, 52, 35,189,161, 74,154,221,230, 52, 44, 44, 76,157, +153,153,137,204,204, 76,252,253, 63,167,241,232,248,120, 53, 0,234,229,150,167,148,235, 71, 46,151,123,126,139,151,217,234, 40, + 34, 34, 2,114,185,220,237,135,189,199, 91, 76,236,255,129,212,185, 60, 19,250, 45,147, 54, 70,123, 76,152, 48, 65,186,107,215, + 46, 53, 33, 4,111,126, 76,240,243,225,145, 56,124,248, 48,167,223,110,217, 50, 77, 58, 52, 50, 14, 35, 70,220,196,167,159,126, + 90,227,218,203, 47, 3,227,199, 3, 11,231, 37,169, 87,127,194,173, 77, 88,229,175,209,104,192, 48, 12,166, 76,153, 2,129, 64, +208, 16,101, 95,203,242,119, 55, 32, 19,226,155,242,111, 52, 68,172, 6, 0,172, 93,187, 22,107,215,174,181,157, 27,148,208,100, +197, 57,120,240, 32,190,120, 33, 22,131,159,147, 67,216, 42, 4, 68, 36, 0, 35, 18, 64, 32, 17,131,241,151, 0,160,160, 22, 51, +168,209,136,215, 95,157,131,178, 3,153,200,201,201, 81, 43,149, 74, 41,154, 14, 36, 51, 51, 51,170,115,231,206, 98,171,213,138, +148,148, 20,108,223,190, 29, 65, 65, 65,136,138,138,234,176,121,243,230,127,216,239,227, 20, 16,168, 84, 42, 5, 71, 14,252,247, +255, 30, 9,200,111,167, 47, 23,224,229,101, 21,248,252,223,159, 0,205,251, 10,255, 29,223,182, 91,206,201, 31, 94,118,210, 29, + 76, 29,196,144, 56, 41,117, 98, 59, 77, 28,223,157,207,223,163,189, 48,120, 52,178, 7,192,209, 74,155,246,252, 80,210,253,209, +238, 45, 21, 31,190,110,245, 82, 59,146,136,136, 8,202,166, 37,117, 74, 79, 74,189, 77,219,169,124,225, 85,233, 83,157, 31, 85, +139,171,204,240,255,247,219, 48, 27,140,144,188,249, 17,130,196, 18, 84,137, 42,161,175,170,132, 63, 8,170,175, 23,169,255,249, +207,127,202,222,121,231,157,122,149,239,197, 28, 96,253,143, 86, 0, 6,251, 7,120,242, 9, 6, 47,140, 37, 53,222,155,216,169, +192,122, 31,118,118,182, 91,233,212, 87,107,157,181,250, 51, 51, 51,239,214,193, 17, 19, 42,141,122, 0,192,232,248,253, 80,173, + 26,227,149,151, 33,103,101, 14, 68, 36,251,110, 71, 32, 5, 32,173,123, 57, 29, 23,161,205,255,190,192,173, 97, 63,116,228,155, + 39,117,165,157, 37,118,210,119,226, 4,183,118, 86, 60,251,185,116,253,246,191,170,119,156,254, 0, 43, 22,252,140, 72,105, 56, + 54,125,121, 24, 95,239,179,109, 16, 52,251, 47, 31,200,214,253,231, 3,159, 72, 85,194,187,160,192, 46,168,190, 59, 7, 74, 41, +154,183,125, 28,135, 15, 31,134,125,223,130,122,203,183,250, 19,185, 84, 46,111,165, 6,190, 0,240, 51,210,211,129,200,200,187, +215,255,241,143,187,223, 23,206, 75, 82,251, 7, 44,149,205,126,125,121,189,229,100,149,127,116,116, 52,172, 86, 43, 62,255,252, +243, 70,117,208, 0,128,213,106,173,173,252,105,253,239, 47, 51, 89, 87,227,229,103,135,112,171,220,205,125, 14, 63,159,237, 75, +255,254,181,231,216,153, 41,186, 26, 52,223,106,157,129, 5, 11, 22, 56,174, 47, 88,176, 0,107,215,174, 5,211, 99,214,221,255, +106,191,223,157, 60,225, 20,247,229,115,221,201, 90, 56,133, 91,249,170,170,170,208,190, 75, 87,192,106, 4,227, 7, 16,161, 0, +230,242, 82, 84,229, 94,193,237,252, 2,116, 26, 38, 5, 17,183, 4, 49, 25, 1, 1,131, 85,179,223,194,152,245, 31, 96,209,162, + 69,141, 61, 46,115,210,138, 74,165,146, 80, 74, 91, 86, 86, 86, 14, 11, 9, 9,193,165, 75,151, 96,181, 90,113,229,202, 21,108, +216,176, 1,189,123,247, 70,104,104,232, 43, 0, 94,119, 81,214,117,122, 3, 40,165,173,187, 48,233,210, 14,143,140, 19,151,164, +156, 65,169,206, 15,223,239, 52, 99,247,177,255, 96,158,220, 95, 40, 52, 88, 35,236, 49, 5,110, 9, 0,175,208,155, 30,117, 77, +247,184,243, 12, 48, 28, 58, 34, 59,111, 8,233,146,145, 88,159,162,108,153,115, 57, 7,167,190, 59, 3,165, 82,233,149,245,192, + 42, 7,131,225, 7, 24, 12,155,160,213,198,176,214,177, 87, 15, 56,196,175,133,186,109,149, 5,146,101,115, 96,185,163,133,249, +242, 85, 8,197, 34, 4, 16, 1, 2,137, 0,129, 2, 33, 66, 68, 18,208,114, 61,110, 30, 60,234,113,167, 23,119, 74,253,240,113, +171,227, 61, 92,253, 30, 65,194, 82, 98,247, 8,248,102,253,219,149,179, 26, 62,164,192,117, 85,254, 16, 10,144,123,179, 2, 55, +139,141, 72, 63,111,219, 64,164,199,140, 29,240,102,223,115, 17,201,134,144, 20,192,143, 57,109,251,219,150, 32,248,229, 27, 8, +154,122, 22,126,207, 47, 3, 66, 3,189,243,228,114,216,185,205,155, 45, 94,149,219,223, 80, 15, 13,121, 15, 39, 14, 93,193,255, + 76,154,136,208,214, 61, 49,231,175,175,225,179,165,251, 48, 52,120, 41,214,253,231,239, 62,239,224, 67, 8, 16,183,232,172,195, + 98, 25, 49, 98,132, 93, 33, 89, 61, 54,240,180,169, 34, 53,112, 16,192,207, 40,185,213, 12, 61, 30,105,134,175,190,178, 89,254, +203,150, 1, 97, 97, 54, 17, 37,183,154,161,228, 86, 51, 12,232,119, 65,237, 73,249, 31, 60,120, 16, 86,171,213,161,164, 55,111, +222, 12,139,197,226,149,251,186, 30, 15, 79, 45,229,111,123,159, 61,147,119, 10,144,117, 74,165,140,181,212,172,148,194,106,173, +221,125,217,243, 86, 74,177, 46, 49, 81,150,104,251,141,219,255, 73, 1, 66, 41, 72, 98,162, 82, 70, 41,197, 39,159,124,226,184, +206,126, 79, 76, 76,148, 81,106,187,143, 2,164, 46,121,137, 74, 37,236,215,136,197, 98,129,217, 98,129,217, 92,187,206,216,243, +102,139, 5, 95,174, 91, 39, 91,151,152, 88, 71,249, 40,132,205,155, 3, 34, 1, 44,134, 10,156,219,154,132,191,189,166, 64,167, + 55, 20, 24,184,242, 67, 92,249,237, 36, 4,254, 18,152,138,111,225,204, 49, 13,118, 28,222,139,210,194, 66,156, 61,123,182,209, + 54,214,138,138,138,226,228, 77, 80, 42,149, 65,148,210, 33,153,153,153,191,188,255,254,251,125,206,157, 59, 39, 54, 26,141, 16, + 8, 4,104,222,188, 57,204,102, 51, 50, 50, 50, 64, 8, 17,123, 26,235, 19, 19, 19, 3,149, 74,165,127, 98, 98, 98,104, 73,126, +234,111,127,255,191,188,144,223, 15,239,132, 86,207, 64, 44,100,208, 41, 88,130,210, 59, 98, 40,254,105,198,153, 59, 3, 3, 61, +233, 13,123,172, 9,117,238,139,118, 98, 80,235, 60,175,174,239, 15, 88,229,239, 74, 14, 24, 79, 44,148,221,239,187,134,155,115, +220, 52,239,189,125,118,119,191,193,176, 9, 0, 65, 85,213,183,144, 28,191, 10,195,222, 71,107, 92,247,132,119, 6, 69, 75,131, +180,229,176,138,133, 48,158, 56,135,234, 11,185,168,218,119, 24,168,172,134,152, 82, 4, 64, 0, 33, 8,170,173,102,104,171,171, +240,229,254,157, 30,101,174,126,207,102,221, 59,195,118,204,154, 43, 20,151, 46, 83, 44,250,200,247,254,234,146,175,156,179,203, + 94, 46,151, 59,246,214,102,241,210,218,124, 28, 56,161, 67,222,173, 42, 0, 64,222,173, 42,100,231, 87, 2, 49, 91,216,141, 81, + 60,187,126, 72,129,141, 8,148,159, 65, 96,224,101,248, 73,202, 97,181,106, 97, 50,157,128, 64, 16, 6,163,190,184,201, 58,235, +228,113,127,149, 2, 4,159,255, 60, 11,205,152, 71, 0, 0, 55, 47, 81, 12,154, 40,192, 95,151,143,193,136, 49,125, 0, 80,251, +125,222, 33, 58, 58,154,190,249, 49, 65,179, 54,253, 64, 1,140,123, 97, 54,231,121,255,117, 95, 45,165,109,219,254, 14,224, 44, + 74,110, 53, 67,121,177,109, 11,230,254,253,129, 30, 61,128, 87, 94,185,171,252,203,139,253, 81, 94,236,143,144,128,155,245,202, +156, 52,105, 18,100, 50, 25, 70,141, 26, 85,195,245,239,252,241,101, 74,192,221,123,235, 11,226,156,230,183, 9, 33,142, 79, 93, +231,226, 20, 10,141, 34,214,243,156,120,108,108,172,218,157,229,188, 96,193, 2,196,198,198,214, 80,168,117,201,251, 89,169,196, +217,179,103, 29, 46,120,231, 58, 99,225,122,110,118, 92,156, 38, 78,225,126,171,102, 49,165, 96, 2,252, 96, 42,188, 6,229,210, +165,216,160, 47,129, 46,122,168,227,250, 55,255,217,128, 15,222,122, 13,225,139, 94,194,135,103, 14, 98,139,238, 10,198, 60,251, + 44,194,194,194,188, 14, 6,180, 43,122, 26, 25, 25, 89,163, 15, 31, 59,118, 76, 93,223,118,236, 74,165, 82,164, 84, 42, 7,159, + 57,115, 38, 47, 37, 37, 69,243,230,155,111, 14,253,252,243,207, 37, 21, 21, 21,142,109,154,171,170,170,208,172, 89,179,236,201, +147, 39,247, 28, 62,124,248, 35, 30,136, 4, 67, 8,233,114, 38,109,107, 81,214,222, 69, 87, 23, 45, 73,232,176, 99, 89, 71, 92, + 40, 16,162,180, 66, 0, 43, 1,138, 43,140,160,173,186, 87, 45,124,247,163, 62,207, 60,255,151,215,225, 33,158,192,238,254,175, +225,234,247,240,157, 71, 19, 40,255,186,166, 0, 40, 87, 87,142, 66,161,240,116, 19,117,181,254,109,174,182,111,235,242, 14,120, +252,167,125, 90,183, 83,107,169, 9,226, 98, 45, 36, 63, 31, 4, 17, 50, 64,149, 17,180, 92, 15, 98, 54, 67, 4,192, 66,173,168, +178,152, 81,110, 54, 2, 86,207, 86, 20, 27,228,183,250,189, 58, 57, 45,108, 65,130,141, 66, 88,137, 83, 32,159,199, 23,160,150, +245, 15,224,191,111,116,168,113, 60,120,113, 46, 68,244, 14, 76,164, 53, 84, 42,213, 65,174, 47,150,164, 66,141,144, 15,255,131, +219,111,198,225,142,214, 31, 29, 77,231, 96,177,228, 2, 0,174,157,106,223,100, 29,118,203,158,207,212,175,141, 85,214, 80,254, + 44,134, 6, 47,197,176, 62,147, 16, 21,114, 14, 91,246, 44, 87,123, 51,136,140, 28, 57,146,166,164,164,160,184,120, 52, 90,181, + 58,128,102,173,251,130, 82, 10,134, 97, 56, 5, 34,229,229, 1,185,185,103,237, 71, 21,128,164, 2, 90, 61, 48,100,136,237, 76, +118, 54,240,197, 23, 64,121, 25,160,175, 0, 42,244, 64, 96,112, 25,167,178,213,101,237,231,228,228, 0, 0, 62,254,248, 99, 0, + 64,120,120,248,189,112, 51,115,170,195,249,243,231,215,176,216, 93, 21, 55,103,239,142, 93, 97, 59,230,253,157,240,201, 39,159, + 96,237,218,181, 80, 42,149, 82, 79,193,117,179, 66,195,145,117,238, 60, 10,130,131,213, 12,195, 96,222,188,121,181, 98, 50,188, + 41,223,147,213, 45, 65,173, 21,120,237,227,247,208,111,210, 36, 40, 63,254, 24, 12,115, 87,207, 41,179,207,222,245, 16, 30, 62, +140,253,251,247,227,202,149, 43, 50,133, 66,161,225,178,241,138,179,242, 79, 75, 75, 83, 3, 64, 70, 70,134, 58, 42, 42, 74,150, +150,150,166,137,140,140,148,166,167,167, 35, 42, 42, 74, 86, 89, 89,169,174, 99,204, 53,205,152, 49,163,223,180,105,211, 90,116, +235,214, 13,187,119,239, 54,148,150,150, 10, 43, 43, 43,109,222, 14,251,252,199,182,109,219,194,199,141, 27,231,175, 80, 40, 42, +221,136, 97,156,148, 53,147,123,233,212,218, 15,222,153,217,172, 85, 15, 21,126, 83,189,138,223,175, 19,228,221, 18, 2,148, 65, +181,209, 4, 45,109, 85, 48,119,214,156,161,132,144, 2,118,204,247,230,121,221,120, 8,248,169,130, 7, 4,117,178,184,148,148, +148, 90,159,146, 2, 29, 74, 10,116, 94,181, 53,251,185,107,197,218, 26, 94,114,252, 42,252,206, 22, 64,152,175, 99, 61, 0, 53, +238,175, 75,224,249,252, 60, 28,191,115, 3,231,174,228,226,214,149,171, 40,187,154,143,242,235, 5, 48, 27, 42, 97, 50,153, 81, +110, 49,194, 96, 49,163,154, 90, 96, 1, 5, 37,220, 73,166,115,180,255,197, 28,219,241,162,143, 88,203,159, 65,194,123,141,179, +226,197,219, 56,128,120,149, 14,241, 42, 93, 13,133,207,126,162,226, 51, 32,162,119, 32,164, 58,252,119,150,197,204,121, 10,224, +214,113, 88,244,205, 0, 0,255, 22, 6,161,250,214, 53,100,254,179, 3,178,126,152,128,227,255, 28,128,236, 75, 55,154,180, 99, +246, 31, 18, 6,189, 14,208,235, 0,131,255,121, 0,192, 79,127, 55,225,157, 5,203, 0, 0,195, 99,250,120,109,249,191, 48,242, + 16,180,218, 24, 4, 31, 59,128, 53,239,217, 72,238,200,145, 35, 57,185,254, 1, 96,197, 63,150,147,238,221, 1,231,207,197,139, + 54,247, 63, 0,244,232, 65,177,118, 45,208,165,103, 5, 30, 27,122, 27, 67, 70,223,198,243, 47,153, 56,151,209,217,226,103,143, +195,195,195, 17, 30, 30,142,121,243,230, 53,118, 21,123,124,215,156,177,126,253,122,153, 59,133,237,240,162,173, 94,141,245,235, +215,115,178,132, 95,127,253,117, 53, 27,249,239, 14, 11, 23, 46,172,229, 5,112,135, 67,231,243, 48,115,214, 92,156,216,180, 9, + 75,150, 44,169,147,156,176,229, 59,112,224, 0,234, 11,216, 27,249,216, 35,248,246,155, 47, 16,241,242,203, 88,177, 98, 5,234, + 43,227,130, 5, 11, 48,122,244,104,248,178, 2, 32, 45, 45, 77,237, 20, 44,135, 99,199,142,169, 1, 32, 61, 61, 93, 77, 8, 65, + 90, 90, 90,189, 50, 13, 6, 67,203,157, 59,119,226,252,249,243,200,206,206, 14,208,235,245, 48,153,108,253,204,104, 52, 98,207, +158, 61,196, 78, 22, 42, 57, 20,199, 90, 93, 93, 45, 62,177,245,101, 84,101,125,134,189, 41, 57,184,114, 83,128, 50, 61, 3, 11, + 5, 10,244,254,152,187,232,189,168,184,184,184,124, 14, 6,159,131, 87,176, 75, 78, 57, 78, 7,240,104, 2,235,191, 46, 2, 64, + 0, 16,169, 84, 10,169, 84,138,211,167, 79, 59, 62,185,199,175,161,180,178, 20,173,134,120,191,238,247,196,137, 19, 4, 0, 2, + 2,166, 65,114,252, 42, 68,215,138, 65, 9,129,120, 86,113,141,235, 30, 21,151, 88, 0, 11, 5,242,245, 37,200, 43,213,226,118, +153, 14,165, 85, 85,208, 25, 43,113,187,186, 18, 55,171, 12, 40,168,170,128,214, 84, 13,157,213, 4,163,213,115,240,235,147, 79, +184, 25,240,156,226, 2, 94,155,210, 12, 20, 98, 80,175,183, 1,191, 27,189,239,230, 28,103,228,221,170,194,129, 19, 58, 12, 94, +156, 91,179, 46,232, 29,248, 89,175,193,207,122, 13, 31, 60, 37, 68, 94, 94,158,145,171,204,173, 87,172,104,147,144,232, 56,190, +162,183, 32, 63,167, 0,151, 82,207,161,240,106, 73,147,119,220, 77, 95,166, 0, 0,202,138, 40, 2, 42, 31,131,116,150, 16,255, +179, 76,228,248, 36,108,121, 25,132,187,241, 79,159, 27,145,130, 87, 23,217,148, 63, 33, 4,191,164,218,154,128,235,154,127, 22, +225,189,122,214, 44,231, 38,224,243,207,129,203,151,109,158,128,191,255,157, 58,220,239,148, 82, 4, 7, 7,123, 30,129,237,125, +148,157,247,255,248,227,143,145,147,147,131,172,172, 44,100,101,101, 33, 57, 57, 25,111,189,245, 22,242,242,242,154,172, 61, 88, + 69,231,206,146,158, 63,127, 62, 8, 33,156,149, 33, 33, 4,245,145,137,250,174, 57,227,176, 95, 9, 8,211, 12, 95,191,251, 17, +154,237, 76, 70,108,108, 44, 94,102,217, 24, 0, 69,143,190,152, 31, 49, 12, 1, 1, 1, 24, 57,114, 36,222,127,255,125, 36, 39, + 39,171, 87,172, 88,225,246,253,251,166, 32, 11, 55,251, 60,134,208,208, 80,153,213,106,173,151, 80,212,119,141,131,114,116,120, +156,162,162,162,100, 78,138, 18, 67,135, 14,149,121,240,158,140, 26, 57,114,100,139,188,188, 60, 28, 62,124, 24,143, 62,250, 40, +132, 66,161, 99,138, 35, 52, 52,148,235,116,132,213,254,127, 73,247, 94, 3,227,215,239,107,137,223,119, 47,195,147, 81,189, 17, + 40, 97, 16, 24, 96,129,191, 95, 53,158,126,110,178, 21,128,214,249,135,137,137,137,158,230,162, 28,171, 0, 56, 78, 7,240,120, +208, 60, 0, 0,136, 82,169,108, 62,127,254,124,204,159, 63, 31, 0,140,255,136,251, 7, 76, 69,102,248,251, 75,224, 75,227,201, +229,182,240,225,128,167, 46,131, 10, 24,188,255,147,193,217,250,231,132,128,208, 80,153,185, 89, 0,116,212,130,243,122, 29,206, +150, 22,227, 92,217, 29,156, 43,211,226,188, 94,139,203, 6, 29,138,171,171, 80, 97, 54,227,134, 65,239,248,159,245,225,133,177, + 4,171,223, 19, 96,245,123, 2, 80, 8, 64, 9,131,216,169, 4,175, 79, 21, 99,214,148, 54,232,222,189, 29,172, 16,121,253,200, +172,171,223,121, 94,190,158,164, 64,117,201,144,101,231,219,136,124,230, 74, 91, 16,221,222,183,131, 0, 0, 66,170,131,128,234, + 81,205,216, 34,154,181, 90,109,128, 92, 46,143,241,166,140, 17, 17, 17, 72, 78, 78,198,166, 10, 61, 42,141, 12, 94,253,241,107, + 20, 73,252, 81,105,108,186,109, 34, 38,246,255, 64,150,166,253, 8,155,190,223,226, 56,247,211,223, 77, 24, 26,188,212,113, 28, +251,204, 23, 50, 10, 78,235,135,233,154,165,192,140, 69,163,209,242, 88, 50,100,255,140, 6, 51, 1,208,104, 52, 62,245,225, 46, + 93,106, 70,143,143, 26, 5,180,108, 9,132,133, 1,145,253,155, 67, 34, 22, 64,192,220, 21, 43,241,247,247, 56, 32, 51, 12,227, +176,252,115,114,114, 28, 86, 63,251,249,240,195, 15,241,225,135, 31,226,198, 13,238, 94, 25,119,243,245, 53,175,123,111,125,173, + 95,191, 94,182,102,205, 26,183, 10,155,171,245,239,228,122,174, 21,167,192, 30, 91,173,220, 82,216, 27, 9,129,213, 80, 13, 81, +251, 46, 80, 44, 95,142, 25,129, 45,209, 82,147,230,184, 62,235, 47, 51,240,193,191,191, 70,246,234,255,226,111,253, 70, 97,114, +112, 55,236,223,190, 29,185,185,185,110,223,191,231,227, 20,232,211,183,175,204,106, 47, 19, 75,200,156,167,103,220,157,171, 11, +179,103,207,166,132, 16,202, 6,246,177,243,253,206, 74, 62, 45, 45, 77, 51,116,232, 80, 25,165, 20,236, 84,128,135,122, 75, 17, +137, 68,143, 62,255,252,243, 57,165,165,165,208,233,116,240,247,247, 71,155, 54,109,208,178,101, 75,180,108,217,210, 83,229, 89, + 93,136,157,197,207,207,207,240, 98,220,167,178, 13,199, 7,227,234,245, 50,180, 11, 18, 32,170, 39,193,227,221, 40, 2, 91,180, + 40, 1, 96,169, 71,111,240,251, 13, 60,164,214, 63,224, 97, 25,160, 66,161,168, 80, 42,149,126, 0, 2, 21, 10,133,131, 5,118, +138,238,232, 19,243,101,151,250,201,229,114, 42,158,229,136,252, 39, 78,243,255, 30, 7,228,119,119,109,209,124, 28,243, 28, 12, +230,106,148,233, 13,200, 49,153, 32,178,218,126, 92,106,170,130,149, 82, 80, 0,187,111, 93,129,222,108, 2, 0, 14, 3, 19,193, +162,143,106,246,113, 91, 60,128, 21, 22, 84,227,194,229,114,124,187,185,204,171,135,117, 86,244,118,151, 63,181,127,119, 40,118, + 46,171, 31,108,191, 85, 65, 52,250, 75, 0, 97, 40, 46,190, 27,156, 39,182,222,132,145,233,128,185,253,178,112,243,166,195,114, + 58,192,165,124,113, 63,173,175, 65,188, 84, 42, 21,216,210,252,120,230, 40, 98, 98, 98,154,172,227,238, 56,109, 91,222,151,154, +124, 14, 0, 48,172,143, 45, 51,222, 59, 11,150,225,232,185, 62,248,247,150,151,161,220, 57,135,243,252,255,171,139, 98, 16, 18, +146,108, 63,210,216,201, 82, 12, 40,181, 89, 99, 0, 69, 72, 72, 50, 39, 89,251,247,238,115,228,180,120,249,101, 64, 38, 35,184, +115, 61, 8,122,157, 4,149,101, 98,252,184,145, 96,254,124,138,107, 69,229,136,140, 26,138,148,131,106, 78, 86,177,197, 98,113, +204,247, 39, 39,219,202,234,172,240,139,138,138, 80, 84, 84,196, 89,255, 59, 41, 12,202, 48, 76, 45,165, 74, 41,136,183, 73,128, + 20, 10,133,230,245,215, 95,175, 17, 11,192,122, 4,188,113,133, 19, 39, 86, 98,117, 89, 86, 64, 8,247, 57, 59, 66, 8,204,229, +229, 16,181, 14,129, 32,160, 25,250,188, 56, 9, 31,142, 29,131,119,217,101,123, 3, 7,193, 82, 89, 5, 81,171,118,232, 55, 84, +138,174,157,186,225,211, 11,105,232,219,183,175,236,248,241,227,181, 72, 64,156, 66, 1,128,168, 1, 96, 78, 92,156, 99,233,160, +217, 69,217, 11,133, 2,128,222, 93,168, 88, 87,129,215,173, 91, 71, 0, 80,187,139,159,100,100,100,184,117,241,167,165,165,105, +184, 40,255,196,196, 68, 66, 8, 89,218,178,101,203, 62, 67,135, 14,237,126,241,226, 69,156, 60,121, 18, 22,139, 5,129,129,129, + 48, 24, 12, 69, 33, 33, 33, 87,189, 49,250,148, 74, 37,211,174, 93,187,253,207, 61,247, 92,187, 99, 71, 50,176, 86,181, 31, 45, +136, 24, 61,219, 85,227,242,157, 64,140,232,105,186, 2,192,117, 30,203, 82, 95,155, 56,103,156, 34,132, 56, 31,186,230,125,225, +209,196, 16,114,120,233,141, 0,140, 78,131, 10,205, 79,241,122,126,184,134,114,175, 67,241,113,206, 24, 88,166,213,201, 76, 1, + 18,117, 41, 99, 69, 97, 85, 5, 96, 50,193, 98, 95,215,116,161,162, 4, 5,134, 50, 80, 74, 97,207, 47,160,225, 82,188,216,169, + 4,235,127,188,219, 39, 47,230, 0,189,186,155, 33,128,190, 65,202,223,165,179,123,170,131, 58,189, 0, 42,213, 28, 53,144, 9, +173, 86,107,204,203,203, 19,174, 26, 3, 38,126,255, 72, 44,232,123,212, 97,133,113, 37, 21,238,188, 46,174,199,172, 18,226,106, +205, 97, 25,193, 96,251, 74, 14,119,203,253,182,108,217, 98,203, 4, 40,151, 83, 46, 57, 31,226, 38,126, 41, 83,238,152,171, 78, +219, 66, 17, 21,114, 14,195, 99,250,224,200,254,115, 56,166, 91, 14, 2, 2,197,196, 47,100,137, 59,230,114, 42, 95, 72, 72, 50, + 8, 33,120,225,133, 23,240,213, 87,101, 96, 85,140,237, 47,101, 9, 1,173,105,217,223,169, 83, 94,244, 40,153, 44,229,160, 90, + 61,106, 20, 96, 44,236,140,235, 37,126,176,218,103, 91, 59,232,219,225,237,216,114,236, 63,214, 19,205, 59,245,148,177, 89, 2, +235, 3,171,248,243,243,243, 1, 0,133,133,133, 14,207,192,173, 91,183, 28, 3,171,143, 32, 78,110,103,215,151,146,112,201, 7, +224,140,175,190,250, 74,182,118,237, 90, 53, 75, 0,214,172, 89,227,181,245,239,170, 48,124,133, 68, 34, 65,225,181,171,232,214, +189, 7,172,230,106, 16,179, 5,194,230, 45,208,124,208, 96, 52, 27,248, 4,172,122, 51, 44,134,106, 80,179, 5,176, 88, 17,191, +238,223,152,242,242, 20, 72, 36, 18,183,242,204, 63, 6,115,250,191,238,238,139, 88,225,254,222,168,168, 40,153,157, 0, 80, 74, + 41,134, 15, 31, 46, 75, 77, 77,173,117,159, 39,229,111,175, 43, 43,128, 61, 61,123,246, 28,248,217,103,159, 25,111,223,190, 93, + 53,102,204,152,231, 50, 51, 51,255,102, 48, 24,138, 91,183,110,173,248,244,211, 79,181, 92,235, 79,169, 84,138, 0, 60, 50, 52, + 50,178, 77,220,172, 56, 92,201,191,162,157, 62, 43,238,201,244,253, 27, 19,110,150,107,135, 13,142, 30, 99,109,215, 41,252,127, + 92,173,252,250, 82, 11,219,251, 24,113,226,159,196,141, 14,112,253,206,227, 65, 37, 0,245, 89, 23,190, 40,127, 86,217,212,145, + 48,134, 19, 9, 88,121,242,144, 6, 0,153, 58, 40,138,194, 95, 2, 29, 53,195,104, 54,195, 74,173,104, 21, 20,132,124,125, 41, +188, 73, 46,228,110,121,223,221, 24, 0,239,214, 98,187,115,241, 55, 52, 93,175, 61,143,192,196,193,131, 7,239,136,143,143, 23, +135,132,132, 88,111,222,188,137, 5,125,111,186, 42,127,206,255,163,174,132, 61, 62,193,158,229,207, 77,146,167, 90,247,112, 69, +226,142, 57, 26, 0,100, 66,191,101,210, 93,103,254,174, 78,219, 2, 16, 16, 76,236,255,129,108,199,233, 15, 52, 92,149, 63,219, +151,138,139, 71, 83,160,140,181,126,225, 78,239,108, 72, 56,192,246, 7, 82,223,230, 26,118,171,158, 20,235,250, 74, 45,229,229, +106, 34, 0, 12, 85,254, 32,229,102, 8, 25, 33, 12,140, 68, 54,118,242,107,152, 27, 27,231,177, 61,146,146,146, 72, 82, 82, 18, +189,135,239, 31, 40,165,132, 16, 66,157, 35,218,157, 61, 1,222,200, 82, 40, 20,154,216,216, 88, 44, 88,176,192, 65, 40,154, 42, + 21,238,168, 81,163, 48,119,203,122,124, 88, 94,130, 1,209, 35,192,180, 11,182,149,201, 68,109,169,123, 33, 2, 17, 8, 65,196, + 2,124,149,184, 26, 45, 70, 15, 70,247,238,221,189,142,218,111, 8,156,172,123,117,100,100,164, 44, 53, 53,181, 65,117,149,147, +147, 19,115,224,192,129,107, 2,129, 96,251,147, 79, 62,249,143, 57,115,230,220, 94,183,110, 93, 10, 96,155,114,240, 66, 20, 3, + 32,249,228,201,147, 67,190,219,176,145, 17, 11,252,174, 79,122,105, 82,255,185,115,231,234,190,252,242,203, 9, 0,130,236,138, +191,156,221, 32,136,139, 71,129,199,131, 1, 46,238,127, 95, 9, 64,131, 9,131, 7,229,195,121, 64,250,241,100, 26,145, 79,146, + 75,173,151,178,213,250,106, 35,204, 22, 11,186, 15, 25,132,112,115,164,183, 10,183,209,130, 81,216,164, 63, 0,212,172, 53,110, +143, 3,104, 80, 14,124,149, 74,181, 83,169, 84, 10,147,147,147, 23,173, 90,181,234,159, 78,228, 98,148,243,255,226,234, 81, 0, +208,104,201, 75, 38, 95, 96,227, 44,234,126,190,201, 23,228, 62, 49,253, 93,103,254,174, 97,219,135,130, 98,199,233, 15,124, 42, +163, 77,185, 19,188,186,104,212, 93,179,151,220,189,182,232, 35,239,243,145,199,191,125, 86, 19, 15,144,117, 95, 45,149, 86, 26, +108,251, 0,220,205,255, 31,231,245, 59, 98,183,200, 44, 10,133,162,209,231, 85, 89, 18,208, 24,178,236,177, 0,106,246,123, 35, +148,205,167,223,117,239,222, 29,237,231,205,147,173,221,183, 79,157,251,143,159, 33, 23,181, 66, 75,251,230, 61,149, 6, 51,230, +191,181, 4,130,128, 16,236,222,168,196,233,214, 4, 99,135, 13,243, 57,111,191,197, 98,246,121,152,224,234,226,231, 64,190,200, +243,207, 63,127,155, 82,154,208,171, 87,175,255, 43, 46, 46,214,251,160,248,157,235,125,100, 70, 70, 6,172,102,130, 97,195,251, +127, 48,119,238, 92, 29, 0,204,153, 51,199, 10, 64,215,144, 38,117,242, 56,213,248,238,198, 43,202,227, 33,243, 0,220, 19, 82, +224,179, 98, 76,170,145, 96, 7, 25, 57,151,154,188, 82, 93,146,254,176,231, 26, 44, 87,161, 80, 88, 0,252,203,254,241, 89,174, +187,242, 53,240,121, 73, 99,220,115, 47, 97, 83,240, 20,139, 62, 74,110,116,217,158, 82,253,122,209,190,166,123, 89, 7,141,181, +233,138, 66,161,208, 40, 20,138, 70,145, 69, 26, 48, 7,192,150, 65,169, 84,194,190,125, 47,242,156,182,239, 77, 61,176,223,177, +125,239,232,161,163, 97, 39,189,117,254, 63,193, 20, 29,177,108, 14,174,173,152, 56,238, 38,232,137, 4, 52, 70,125, 61,241,196, + 19,213,102,179, 57, 5,128,254,253,247,223,111,144, 18,141,139,139, 35,239,191,255, 62, 53, 26,141, 0,176,175,174,251, 86,174, + 92, 73, 22, 47, 94,236,248, 95,246, 84,192,245,142,237,174,193,157, 60,238, 47,184,122,184,136,175,251, 8,243,224,193,131, 7, +143, 38,129, 25, 64, 21, 0, 73, 35, 27,113,158,118, 12,228,188,163, 32,143,135, 3,124, 99,242,224,193,131,199,195, 5, 33,128, +102, 28,148,191, 1,182, 0,238,198,210, 7, 86,240,203,254,254,112, 29,137, 7, 15, 30, 60,120,252,241, 16,192,235, 11, 30,188, + 7,128, 7, 15, 30, 60,120,240,224,193, 19, 0, 30, 60,120,240,224,193,227,207,142, 26, 46,157, 83,167, 78,249, 28,145,235, 46, +152,240, 65,151, 23, 54,200, 15,254,126,133, 16,137, 75, 96,181,218,150,133, 9, 4, 12, 24, 34,176,253,101, 8, 8, 97, 64,137, + 16,132, 16, 48, 48, 99,199, 46, 17, 40,165, 8, 97, 90,193,155,242,217, 51, 42,182,134, 45,128,167, 28,182, 4, 3, 38,118,201, +215,195, 88,127,188, 60, 94, 30, 47,143,151,199,203,123, 48,229,241, 30, 0, 15, 56,116,228, 50,116,165, 58,152, 76, 20,183,239, + 16,236, 77,246,199,190,253,129, 96,136, 8,251,213,237,177,239, 96, 7,236, 83,119,192,225,227,109, 32,132, 16, 12, 36, 24, 17, +197,192, 79,236,199,249,127, 76,125,117, 58,157,250,234,116,122, 36, 85, 93,101, 98, 72,234,185,179,153,135,212, 71,143,232,147, +147,147,171, 0, 52,231, 57,232,195,143, 49, 79,141,144,206,153, 51,157,122,187,201,211,195, 10,165, 82, 41,165,118,212,183,187, + 30, 87, 80, 23,240, 61,138, 7,143, 38,240, 0,176, 24, 54,124, 8,231,151,240,104,106,134, 71,214,210,216,242, 26, 19, 25,153, + 34,140, 27, 99,193,233,223,253, 33, 22, 9, 33, 20, 8, 33, 18, 81,248, 9, 76,128,176, 57,132,168,196,144, 62,102, 72,196,126, +160, 0, 58,180, 3,158, 29,111,197,129,237,220,148,255,229, 11, 89,120,244,177,238,232, 24,218, 18,249,215, 46,118, 9,106,223, + 13,173, 59, 90,240,235, 47,191, 32, 57, 57,185, 4, 77,188, 35,150, 92, 46, 31,175, 82,169,118, 57, 29, 63,227,124,204,163,110, +204,157, 35,167,230,170,115,178, 33, 17,193,106,171,181, 24,165, 29, 43,213,157,218,143, 70, 69,117, 7,124,181,254, 63,127,216, +157,206, 98, 99, 99,213, 11, 22, 44, 0, 33, 4,107,214,172, 81, 55, 70, 78, 0, 54, 29, 0,175,255,239, 63,188, 34, 93,148,130, + 48, 76,125,237, 77,157,219,147,109,211,187,201,183,106,182,179,243,206,136, 60, 26, 23,108, 54, 64, 39, 47, 1, 55, 2,208, 84, + 96,238,179, 46, 28, 63,214, 4, 10, 1,132, 2, 17,134, 69, 18,180,109,195, 64, 40,100,224, 39, 18,160, 87, 56,131,107,215,205, + 24, 18,193,160, 85,136, 4,191, 30,108, 1, 0, 16,208, 74, 80,106,133,167, 20,193, 83, 95,157, 78,127,207,204, 68,215,142,157, +240,123,218, 49,164, 27, 77,208,221,209, 65,236,215, 28,189, 7, 14, 71,255,225, 99,161,222,161,130,156, 99,110,252,123,160,248, + 71,169, 84,170, 3, 97, 97, 97,200,204,204,100, 59, 76, 9,128,121, 42,149,106,167, 92, 46,143, 81,169, 84, 7,254,104, 47,197, +236, 56, 57,245, 19,106, 33,100,140,168,170,178,160, 84,239,143,239,127, 56,224, 85,253,143, 30, 51, 92,218,194, 95,139, 81,195, +197,232,218,229, 89,117,139, 22, 65, 48,153,205,184,125,251, 14,218,229, 93, 71,118, 78, 46, 94,125,101, 60,221,248,221,110,159, +218, 53,194,190,167, 2,192,125,155,236,251,105,253, 3,119,183,195, 93,179,102, 13,148, 74,165,180,169,210, 1,223,199,247,133, +110,221,186,181,246,126, 10, 77,164,188,148,202, 68, 41, 1, 65,108, 35,212, 59,205,251, 9, 36,253, 53,103, 29,111,207,146,233, +216,247,202,129,215, 18,245, 30,137,220,175,191,254,234, 56, 30, 55,110, 28,246,236,217, 83,239, 49,143,123,175,252,157,207, 57, + 19,129,112,212,249,165, 0, 0, 32, 0, 73, 68, 65, 84,122, 9, 64,234,145,116, 12, 31, 17,121,223, 10,109,245, 46, 59,164,243, +205, 62,189,132,140, 80, 0,157, 86,136,246,109, 69,104,223, 86,140,138, 10, 17, 36, 34, 33, 44, 66, 63, 12,234, 71, 48,224,113, + 1, 24, 34, 2, 33, 4,126, 34, 49, 68, 76, 53,136, 68, 12,179, 1, 48, 67, 95,175,242, 63,114,240, 0,186,117,104,131,179,167, +207, 34,175,232,230,221,242,149, 87, 64,114,238, 56,101, 4, 4,131, 34, 6,225,215, 61,222,233,216,117,235,214, 73, 51, 51, 51, +213,151, 47, 95,134,191,191, 63,252,253,253,101,219,182,109,211,120, 57,152,201, 84, 42,213, 1, 86,241, 59,117,142,150, 0,198, +126,253,245,215,119, 94,123,237,181,100,185, 92, 62, 70,165, 82, 37, 63,136, 29, 60, 50, 50, 82,154,158,158,206,249,185,165,163, +134, 73,251,134, 55, 87,119,234, 80,132,160, 22,126, 96,152, 0, 84, 86,154, 81,172,173,196,203,242,222, 84,210, 98, 16,190,253, +230, 7, 78,253, 72,132, 66,188,240,204,227,234, 62,125,122,227,102,161, 14, 39,126, 59,137,138, 10, 61,130,130,154, 35, 44,172, + 11, 24,129, 8, 22, 75, 30,226,102, 79,167,137,235,190,255, 67, 89, 55,177,177,177,234,133, 11, 23, 58,142, 23, 44, 88,208,104, + 94,128, 7,217, 3,160, 82,169,136, 92, 46,167, 73, 73, 73,112,183,177,210,253, 54,218, 21,138, 56, 16, 66,176,126,189, 82, 22, + 27,219, 48, 18,192,116,121,209,161,188, 51, 86, 52,115, 59,152,182,111,201, 32, 52,132,121,104,219,239,207, 10,103,101,239,142, + 20,120,244, 0,164, 30, 73, 7,128, 6, 19,129, 35,243,178,235,189, 62,226,211, 30, 62, 15, 22, 78, 57,206,189, 26,132,146, 53, +109, 33, 18,138,208,185, 99, 5,202,203, 69, 56,113,182, 51, 4, 2, 1, 4, 68, 0,177,200,140, 62, 61, 12,232,217, 67, 0, 2, + 6, 98,145, 31,196, 2,130,136,199,141, 8, 9,182, 98,211,255,213, 47,187,119,183,118,184,150, 83, 84, 83,249,219,145,119,227, + 26, 33,140,144,118,136,122, 28,193, 45,155,163, 68,119,135, 83,121,215,174, 93, 43, 93,185,114,165,250,218,181,107,206,167,213, +227,199,143,199,238,221,220,173, 77,149, 74,117,208, 89,249,187, 65,235,132,132,132,146, 55,223,124,115, 63,154,120,138,162, 30, +229,175,246,166,108,225, 97, 33,234,208,118,101,104,221, 42, 16,157, 66,219, 35, 32, 48, 0,215,174, 21,192, 98,177, 34,180, 99, +115,156,187,144,134,168, 17, 67,164,105, 71, 50,234, 29, 76,223,120, 99, 58,125, 60, 92,135, 71, 30,233,132,243, 23,174,225,196, +137, 11,184,125,167, 28,148, 2,193,193,254, 48, 24, 42, 48,112, 96, 31,148,148,148,162,224,196,111, 24,254,100,164, 52,245, 48, +119,162,242, 32,131,181,254,237,219, 78,131,245, 4,172, 93,187,214,107, 47, 0, 59,221,239,154, 9,216,205,118,178, 13,238,127, +157, 58,117,162,157, 59,119,110,112, 46,126,149, 74, 69, 38, 79,158, 76,183,108,217, 2,118, 99,165,250, 20,158,125, 43,220, 90, +229,143,138,138,146,178,155, 3,213, 65, 98,169, 7,153,142,255,173, 80,196,169, 27,242,142,186,202, 27,178,164, 2,199, 87, 52, +171,161,248,121, 60,156,214,191,171,203,191, 65, 83, 0, 13, 37, 2, 35, 62,237, 81, 39, 9,240, 69,249,179, 72, 73, 73, 65, 65, + 65, 1, 0, 32, 52, 52,148,122,243, 50, 8,104, 37,132,196, 2,177, 72,132,223,206,182,129, 64, 40, 68,115,145,222, 22, 7,208, +140, 65, 65, 65,115, 60,222,199, 10, 66, 8,228,207,154, 65,173, 12, 64,252, 64, 64, 97, 11,228,119, 15, 67,201,117, 20,106, 43, +144, 85, 80, 80,103, 89, 74, 74,181,208,221, 46,180,203,226, 60, 0,185, 42,127, 0,192,238,221,187,241,212, 83, 79, 73,247,238, +221,235,113,128,147,203,229,163,114,115,115,221,118,152,210,210, 82,231,211, 45,151, 45, 91,134,243,231,207,143,126,144,166, 2, +156,148, 63,103, 72, 71, 13,147, 74,132, 55,225,239,223, 18, 18, 63, 49,186,117,235,138,206, 93,187,162,172, 76, 3,173,182, 2, + 98,177, 0, 33,193, 18, 8,253, 91,122, 28, 76,133,180, 0,205,155,181,130,161,210,140,179,103,179,113,163,176, 20, 55, 11, 43, + 80, 89, 45,193, 35,161,102, 72,252, 4,200,206,202,197,163,221,187,227,198,205, 50, 84,154, 91,112, 26,160,157,221,254,117,157, +247,118, 58,160, 46,153,190,200, 98,173,255, 5, 11, 22,212, 58,191,112,225, 66,159,188, 0,238,118, 39,116,157, 59,110, 44,175, + 66, 90, 90,154,186,161, 27,242, 76,158, 60,153,170, 84, 42,200,229,114,184,155, 14,224,226,169, 98,149, 63, 0,100,100,100,212, + 42,147,253,186, 71,163,135,221, 97,176,177, 60, 46, 91, 22, 6, 98,242, 26,189, 91,197, 31, 26,194,216, 71, 41,110,205, 59,110, +220,184, 26, 94,146,167,159,126,186, 70, 93,241,110,255, 7, 7, 94,199, 0, 52,150, 71,160, 49,145,157,109, 35, 22, 5, 5, 5, + 94,145, 0,161, 80, 8,145, 64, 4,145,136, 96,228,112,192,160,175,198,149, 28, 49, 68, 66, 17,132, 22, 33,134, 70, 82,136, 69, + 34, 8, 4, 12, 64, 9,180, 58,224,248, 73, 33,172, 86, 43,128,219,117,202, 61,249, 91, 14, 42, 42,234,206,192,217,173,125,123, +170, 55, 19, 84, 86,150,194, 98, 53,115,126,206,147, 39, 79,214, 77, 58, 12, 6, 78,138,198,213,245,239,142, 25,238,216,177,195, +249,254,228,166,240, 2,184,115,241, 59, 43,127,251, 0,200,205, 2, 12,109,167,102,152,235, 48, 91,172, 48,154,204,184,125, 71, + 11,145, 88,130,234,106, 19, 76,102, 11,204,102, 43,204, 22,202,201, 19, 35, 22,233, 33,241,239,132,226,226, 82,148,149, 27,160, +213, 85,162, 69,171,254, 24,246,248,227,200, 72,221,131,142, 70, 51, 74,203, 74,209,179,103,119,248,137,133,208,151,107,255, 16, + 3,133, 61,242,223, 49,247,239,226,153,242, 41, 22, 96,193,130, 5, 53,188, 9,174,215,184, 18, 0,173, 54,198,113, 99, 92, 92, + 8,182,108,217, 82,163,191,178, 6, 66, 94, 94,158,207,187,114,202,229,114,186,101,203, 22,199, 54,227,117,197, 4,184, 42, 87, + 87, 79, 85, 90, 90,154,154, 13,124,163,148,210, 99,199,142,213,184,126,236,216, 49,181, 39,167, 7, 75, 26, 88, 18,224,108,197, +215,101,232,123,120, 54, 76,138, 74,198,102, 0, 83,214,232,241,196,146,138, 6,145, 47,215, 57,126, 79, 49, 1, 60,238,189, 55, +160, 46, 15,192,125,245,239,184,179,244, 27, 98,253,187, 88,172,200,206,206,102, 7, 20, 78,189, 87, 32, 16, 98,232, 16, 43, 4, +140, 16,199, 51, 37,184,148, 45,193,132,167,128,103,158, 6, 38,142, 35,232,208, 78, 12,137,216, 15, 18,177, 31,252, 37,126, 8, +237,224, 7,137, 88, 2,137,135,101,128,249,121,215, 73,137,246, 22,169,107, 32,233,222,173, 11,130, 90, 6, 66, 98, 53,162,194, + 96,186,239,157,226,200,145, 35, 7,142, 28, 57, 82, 67,225, 59,127, 0,160,184,184, 24, 19, 39, 78,108, 50, 43,223,110, 29, 73, + 93,207,217,191,123,101,201, 89, 44,128,222, 96,130, 94,111, 68, 89, 89, 53,110,221,210,225,198,141, 59, 40, 47,175, 70, 69,133, + 9, 21, 21, 70,232,245, 38,148,150,148,122,148, 85, 93,109, 70, 85,149, 5, 38,147, 17,205,155,139,209, 57,180, 5, 2, 2, 3, + 1, 0, 97,221,187,162, 83,199, 22, 8,106, 33, 1,165, 22,152,204, 86, 84, 87,235,255, 16, 3, 73,108,108,172,122,209,162, 69, +245, 42,243,216,216, 88,206, 22,169,125, 75,225, 58,175,175, 89,179, 6, 95,125,245,149,215, 91, 13, 59,109, 59,235,248,176, 10, +181,160,160,128,221, 61,211, 43,237, 54,121,242,100,154,148,148, 4,103,242,160, 82,169,200,164, 73,147,234,253,221,236,217,179, + 65, 8, 1,219,143, 35, 35, 35,165, 0, 48,116,232, 80, 25,171,200, 89,171,159,189, 78, 41,117, 92,231,240,180, 53,172,120,119, +196,129,203, 12, 74,235,214,173, 65,156, 88, 66, 67,229,241,120,240,148,191,187, 99,159, 60, 0, 15,146,229,127,119,128,183, 64, + 32, 16,120,253,187,225, 67,172,104,219,198, 15,101,101, 66,248, 9,205,240, 19, 11,160, 73, 23, 99,130, 76, 4,177, 72,132,178, + 50, 17, 82, 51, 3,209, 66, 66,192, 48, 12,198,197, 24,241,220, 4, 10,134,161, 88,126,202,251,114,202,229,114, 42, 8,144, 64, + 43,106,141, 0, 83, 62, 46, 23, 80,140,146,142,228,188,165,239,192,129, 3,113,244,232, 81,183,215, 2, 2, 2, 56, 15,150, 58, +157,110, 52, 0,108,216,176, 1, 51,102,204,112,156, 47, 46, 46,118,124,159, 49, 99, 6,138,138,138,154,164, 61,211,211,211, 53, +132, 16,176,243,164, 12,195,128,117,119,214, 51,111, 90, 39,242,174,223,144,181,105, 97, 80,251,137, 5, 48,154,172,168,170,206, +199,245,252, 98,104,117,101,208,106, 13, 40,214, 86,162, 88, 91,137,150, 33, 93, 1,228,212, 43,235,214, 29,138,194, 91,119,208, +187,119,119,148,232,116, 16, 9, 25,148,149,231, 67, 95, 98,197, 99,143,234,209,174, 77, 27, 4, 4, 4,192,207,207, 31, 55, 11, +203, 65, 4,193,156,202,232,236,146,111,172, 85, 0,141,189,130,160, 46,107, 29,184, 27, 11,192, 21, 10,133, 66, 19, 27, 27,139, +249,243,231,215,242, 42,176,211, 12,190,174, 44,152, 60,121,114, 13, 11,150,125,191, 8, 33,120,241,197, 23,145,148,148, 68,184, +146, 0, 87,203,223,249,154,171,167,193, 21,235,214,173, 35, 0, 28, 86,126, 70, 70,134,218,222,175, 53,118,111, 0,251, 87, 13, +128,164,167,167, 59,174,215,183,157,107, 90, 90,154,122,248,240, 97,178,163, 71,109,239,196,236,217,179,113,234,212,111, 50, 86, +133, 31, 59,118, 76,205, 62,255,208,161, 67, 61,122,202,214,173, 91,135, 47,100,193,152,178,214, 96,123,174,133,129, 53,174, 79, + 89,107,112,212,231, 76,153, 8,223, 28, 52,130,199, 67, 64,218,227, 87,214, 36,221,171, 22,227,212,169, 83,220, 87, 1,220, 11, +197,239, 28, 11,208, 16,235,191,166, 37, 95, 83,249,219,221, 76, 30,167, 2, 90,183, 22,128, 33, 2,180,105, 45, 64,143,238, 20, + 55,110, 8,193, 8, 8, 68, 66, 33, 68, 66, 17,126, 63, 19,136,144, 64, 17, 4, 2, 1,134, 71, 90,224,239,239, 7,171,149, 2, +212,226,147,242,111,214,174, 51,110, 85, 80,232, 47,107, 32, 36, 2, 92,190,145, 71, 46,115, 84,254,246,129, 77,118,253,250,117, +245,245,235,215,221, 61,175,134, 99, 57,198, 20, 23, 23,239,103,149, 60, 0, 76,156, 56, 17, 27, 54,108,112,220, 83, 86, 86,134, +162,162, 34,236,220,185,147, 93, 46,120,223, 59,175,125,224, 82,103,100,100,168,217, 96, 49,251, 57,175,149, 66,234,225,116,141, + 76, 26, 1, 90, 80, 6, 67,165, 9, 58,191, 42, 80,232, 80, 85,101, 70, 89, 89, 53,138,238, 24,112,227,102, 5,158,148,117, 1, +144, 90,175,172, 74, 99,107,228, 94,185,141,176,110,143,160, 91,183, 78, 40, 46,190,131,224,150, 22,244,232, 17,132,182,109,194, + 32,241,247, 71, 73, 73, 5, 78,156,188,136,252,130, 50,180,239,212,231,161, 29, 64, 18,149, 74, 74, 8,100,172, 46,117, 86,170, +245,173,219, 79, 84, 42,165,137,235,214,113,242, 2,172, 93,187, 86,237, 74, 0, 86,175, 94,141,245,235,215,203, 60,201, 75, 76, + 76,164,113,113,113, 68,161, 8,118, 42, 19,117,167,152, 41, 0, 76,154, 52,137,147,251,223,121, 74,161, 85,171, 36,248, 58,109, +192, 90,249,118, 2, 64, 41,165, 24, 62,124,184, 44, 53, 53,181,206,235,158, 20, 54, 59,183,158,154,122, 84, 77, 8, 1, 33, 4, + 3, 6,244,151,173, 91,183, 78, 83,251,222,187, 36,195,147, 60,102,178, 14,172, 60,249,168,174, 53,248,209,228, 53,231, 29,242, +184,128,143, 1,120,120,224,145, 0, 60,136, 22, 63,139,169, 83,167, 54,232,247, 12,195, 64, 32,176,125,122,135, 51, 24,216,207, + 2, 63,177,196, 70, 0, 68, 34, 12,139, 4,252,252, 0,145,192, 15,173, 91, 75, 32, 16,232, 97,177, 88, 97,181,122,239,182, 55, +104, 11, 33,233,212, 11, 87,146,255,131, 54, 66, 6, 71,242,174,121, 61,160, 44, 88,176, 64,179,110,221, 58, 89, 67,150, 1,178, +203,250,222,120,227, 13,199, 57,214,210, 47, 43, 43,131,193, 96,192,204,153, 51, 1, 0, 95,126,249, 37, 0,168,155,162,109,211, +210,210, 52,118,107, 95, 13, 0, 67,134, 12,105, 80, 0, 87,167, 46, 61,145,121,108, 47,218,182, 14, 64, 64,128,173,219, 87, 87, + 91, 80, 86,110,132, 86, 87,137,206,221,250,224,251,141,155, 60,182,201, 47,191,236, 35, 47, 62, 63,148, 30,203, 56,135, 39,135, +247, 71,151, 46, 93, 96, 50, 86, 97,224,128,199, 17, 24, 20,132,107,185,121, 40,184, 81,130,212,180, 11,208,149, 7, 97,207,134, + 77, 15,173,207,116,118,156,194,222,254, 4,179, 21, 10,199,178,112,171,139,210,103, 24, 2, 80,135,202,160,179, 21, 10,244,119, + 99,193, 18, 2, 10, 39, 90, 30, 23, 23, 7, 87, 47,192,252,249,243, 65, 8, 65, 92,156, 66,109,215,231,152, 29,167, 64,255,254, +181,229,197,197,197, 57,220,241,158,148, 28, 87,229,239,138, 73,147, 38, 97,244,232,209, 50, 95, 73,176,243, 92,125,100,100,164, + 44, 53, 53, 85, 83,215,117, 46, 65,138,246, 85, 5,148, 37, 95, 81, 81, 81, 50,133, 34, 78,227, 74, 58,156,228,195, 27,121, 91, + 22, 54,179, 29, 74,218,221,245,116, 44,204,115, 16,130,189,167,235, 31,251,220,229, 1,224, 99, 0, 30, 82, 2, 48,108,248,144, +123, 50,231,211, 88,150,191,115, 71,242, 5, 90, 29, 65,135,118, 12, 8, 97, 64, 24, 6,251, 14,216,230,247,253,252, 36,240, 19, +251, 97,226,211, 4, 18, 63, 49,252, 37, 4,218, 98, 1, 50, 78, 52,135,197,106, 65,231, 78,222,205,235,202,229,114,122, 35,255, + 10,116,153,187,209,163,179, 8,103, 11,124,159, 23,158, 61,123,182, 6, 13, 12,202,147,203,229,178,207, 63,255, 92,205,186,249, +139,139,139,167, 68, 70, 70, 86,236,223,191,127,215,115,207, 61, 55,182,184,184,152, 76,159, 62,125,175, 61, 95, 64,147,117,206, +244,244,116, 77,100,100,164,140,253,222, 16, 89,223,111,220, 68,166,191,250, 50,205,186,120, 30, 55,114,175,129, 97, 8, 44, 22, + 10,137,127, 8,194,123,247,197,158, 95,147, 57,215,233,141,219, 86,153,182,248,134,186,170,202,140,126,125,195, 16,218,177, 53, +242,174,223,130,238, 76, 14, 46,101,229,225,192,193,223,113,173,128,226,120,230, 89,159,218,233, 65, 73,254, 99,221, 28,236,243, +125, 3, 63,230, 40, 47,231,255,176,118,237, 90, 7, 1, 88,187,118, 45,144,187,161,214,189,238,228,113, 5,165,148, 52,164, 31, +199,197,197, 53,168,239, 57, 41,121,141, 47,215,221,121, 21,156,127,235, 78,158, 87,237,124,109, 43,146,214,190, 98, 27, 27, 70, + 61, 82, 67,249, 3,128,124,252, 19,182, 47,186, 83, 30, 9, 0,159, 7,224,193,193,250, 85,139,107, 77, 3,120, 69, 0, 30,240, +128,143, 6, 23, 46,243,164, 31, 36, 98, 49, 38,142, 39, 96, 8,193,144,193,102,156, 57,235, 15,134,216,230,252, 75, 74, 24,116, +108, 47, 0, 67,196, 56,125, 70, 12,137, 31, 96, 52, 25,113, 45,207,223, 43,229,159,147,245, 27, 34, 71, 63, 3, 97,235, 72,228, +100,101, 64, 88,152,132,160, 22, 33,180,180, 76,219, 36, 21,172, 82,169, 52,114,185, 92, 54,120,240, 96,117,124,124, 60,250,246, +237, 91,164,211,233, 48,120,240, 96,153, 78,167,195,188,121,243,212,118,229,175,105,234, 70,110,168,226,119, 37, 1, 0, 16, 53, + 98,136,180, 67,251, 14,234,192,192, 64,124,191,113, 19, 57,123, 46,199,187, 1, 61, 53, 67, 3,128, 88,208,154,158,191,148,142, + 14,237,154, 65, 34, 17,161,162,194,136,130,155,101, 32,194,206, 56,158,153,202, 71, 75,113,193,201, 55,129,238,255,139, 26,203, + 11, 79, 44,106,210, 34,197,197,133, 56,165,173,109, 28,133,230, 73, 41,123,163,180, 27,154,207,192,221, 56, 47,143,242,179, 61, +107,229, 77,219,135,199, 67,139, 1, 3, 6, 56, 2,254,214,175, 90, 92,235,154, 71, 2,208,216,249,248,239,119,126,127,239, 88, + 4,129, 78, 71, 16,208,158,160, 85, 8,193,224, 65, 38, 72,196, 2,248,137, 77,104, 21, 34,177, 15, 2, 4, 67, 7, 91,144,113, + 82,100,243, 22,112, 36, 70,114,185,156,246,233,217, 2,111,206,255, 16,149,226, 78,248, 41,185, 0,221,195,135, 0, 0,154, 29, +223,137,172, 60,208,138,242,166, 35, 1, 0, 72,110,110,174,116,213,170, 85,106,103,239, 0, 0,210,148,150,255,189,134, 61,217, + 79,131,235,253,208,225,147,100,250,171, 47,211,219,197,183, 81, 89,104,128, 68,210, 10,157,186, 61,206,105, 42,225, 97,135, 45, + 29,118, 35, 61,102,238, 6, 56, 86, 4,228,110,108,242,103,243, 20,220,247, 71,195,216,103,166, 52,170,229,206,199, 0, 60, 88, + 36,160, 46,229,239,209, 3,240,103, 0,133, 45,170,159, 48, 20, 20, 20, 33, 45, 41, 82,142, 8, 33, 17,139,224, 39, 22,226,217, +241, 20,148, 90, 17,220,202, 12,179,133,192,106,181,216, 7, 63,207,120,188,107, 5, 38,188, 40, 71,133,176, 7,218, 54, 11,196, +203, 47,132, 96,211,182, 51, 14, 18, 96,178,252,132, 51, 23,155,118,157, 56, 75, 4,156,142,249,183,199, 7,175,194, 31, 17,100, +178,142,208, 45,193,181, 53,131, 42,196, 39,121,235,117, 43, 17, 27,188,184,246,133, 19,139,154,220,234,255, 51, 99,255,239,166, +198,236,195,196, 70, 16,169, 19, 89,228,167, 5,154,138, 4,120,108, 44, 95,247, 17,230,193,131, 7, 15, 30, 60,120, 60,188,224, + 19, 61,243,224,193,131, 7, 15, 30, 60, 1,224,193,131, 7, 15, 30, 60,120,240, 4,128, 7, 15, 30, 60,120,240,224,193, 19, 0, + 30, 60,120,240,224,193,131,199, 31, 3, 53, 86, 1,156, 58,117,202,231,104, 80,119,193,132,141, 45,111,218,204, 56,143,191,211, +107, 11, 29,223, 3, 67,218, 59,190,255,240,109, 98,173,123,219,200, 94,243, 40,111,255,154,187, 25,243,198, 44,252,220,241,253, +182,250,107,248, 82,190,186,224,107,249,234,130,187,242, 61, 63, 93,225,241,119,153,234, 93,232,218,181, 43,174, 94,189,138,193, +178, 9,142,243, 63,127,175,188,231,245,231,169,191, 36,132,134, 74,223, 44, 40,112,206, 76, 72,238,103,255,115,149, 55, 97,194, + 4,233,238,221,187,107,100, 74, 28, 63,126,188,108,215,174, 93,154,166,120, 63, 30,100,121, 13,145,245, 71,174,191,232,232,232, +151,250,245,235,183,233,204,153, 51, 47,166,164,164,252,212, 8,229,163, 15,202,251,193,203,107, 90,121, 94, 19, 0, 87,124,241, +197, 23,210,170,170, 42, 16,129, 8,132, 16, 88,204, 38,136, 69, 66,204,155, 55, 79,211, 80,230,241,197, 23, 95, 72, 1, 96,238, +220,185, 13,146,165,215, 22, 34, 48,164,189, 67,241,183,239,220, 21, 0, 80,120,253,170, 79,242,246,175,121, 3, 99, 22,126,238, + 80, 92, 95,108,207,248,127,246,174, 60,188,137,170,123,191,147,164, 89,186,175,148,125, 43, 84, 86, 41, 20, 17, 89, 19,217,132, + 2,202, 82,180, 84, 63, 17,161, 1, 17,101, 83,164,159,191, 15, 63, 23, 4, 69,138,178, 6, 68,224,131,178, 21, 68, 89, 10,133, + 66, 74,217,180, 82,160,236,148, 82, 74, 55,160,123,218,102, 79,102,126,127, 52, 19,211,144, 54,147, 52,172,206,251, 60,243, 36, +179,228,100,230,206,189,247, 61,231,220,115,207, 5, 0,204, 24,221,235,185,212, 0,207,201, 15,162,167, 36, 2,231,228, 7,107, + 72,109,124, 52, 0, 32, 39,231,201,151, 95, 40, 32,206, 4,228,161,128, 36, 19,144,207, 45, 40, 64,218,252, 79, 1, 0,189,150, +124,247, 68,203, 45, 42, 42,138,218,177, 99, 7, 52, 26, 77,173,227, 66,161, 80, 30, 21, 21,133,237,219,183, 63,173,211, 3,251, +189,208,166,217,102,202,104, 84,101,230,222, 95, 0,224, 0,107, 7,213,141,159,126,250,233,213, 11, 23, 46,120, 23, 22, 22, 54, +246,247,247,247, 13, 15, 15, 47,152, 55,111,222, 22,103,229, 13, 28, 56,112,208,196,137, 19, 79,108,219,182,109, 10, 0,159,183, +222,155, 54, 25, 0,121,249,242,229,127,201,100,178,223,164, 82, 41,233,160, 72, 58,185, 50,229,130,254,202,154, 68, 92, 85,135, +169, 71, 32,147,133,171, 61, 0,150,248,126,233, 15, 98,159, 22, 93,229, 3,187,118,128,187,192, 13, 20, 69,193,104,164,112,229, +214, 93,252, 16,247,163, 68, 36,112,195, 7, 31,124,224, 20,121,199,111, 94, 32,238,220, 62, 85,126, 37,179,173,196,217, 27,167, + 9, 95,228, 19, 0,101,217,125, 51,241,215,231, 17, 96, 98,169,246,138,254, 12, 71,227, 62, 52, 55,164,186,174,171,111,142,165, +245,127,242,249,252,154, 86, 64, 81, 32,201,154,246,109, 52, 26,205,247,207,225,186, 49,182,162, 1,160, 73,163,154, 84,157,186, +202, 10,104, 13, 6, 0, 64,181,161, 70, 94,155,161,239,163, 93,231,238,140,136, 31, 0,186,245, 25,132,115,242,131,102,226,175, +235,186,199, 89,126,116,167,145, 9, 96,152,135, 7,146,148, 74, 57, 77,252, 0,112,243,200,209,250, 58,173,122,241,221,214,111, +196,233, 37,127,161, 32, 55, 3,237, 91,245,198,198,143,183, 59, 92,135, 35, 34, 34, 94,223,185,115, 39, 77,254, 6, 0, 26, 0, +238, 0, 72,141, 70,195, 19,137, 68,136,136,136, 16,219,242, 4, 60, 97, 4,191, 20,214,245, 80,210,246,181,158,202,130,235,232, + 23, 57,125,219,221,114,253,191, 0,252,246,180,117, 76,145,145,145,148,179, 11,240, 88, 17,163, 83, 88,185,114,165, 56, 45, 45, + 77,190,121,243,223,137,137, 74, 74, 74,144,153,153,137,145, 35, 71,254, 79, 44, 22, 75,230,205,155,199,232,253,202,100, 50,206, +182,109,219,254, 11,224,149,126,195,222, 16,109,219,182, 45,248,173,247,166,121, 1, 48, 2,104, 98,186,236, 5, 0,156,129, 3, + 7, 14, 0, 30, 94,234,188, 46, 82,237, 21,253, 25,210,226, 23, 83,117,181, 55, 7,218, 7,149,122, 54, 13, 92, 46, 15, 70,163, + 1,138,170,106, 76, 28,247, 58, 85, 85, 85,213, 80,194,166, 92,249, 94, 88,216,135,173,101,127, 45, 60, 5,246, 21,128,101,203, + 87,136,197, 35,198,203, 91, 52,242,129,187,144, 7,146, 36, 97, 36, 1, 30,151,128,191, 79, 7,116,110,223, 82,158,156,116, 80, +178,122,245,106,177,163, 74,192,138, 21, 43,196, 29, 67, 78,203,187,117,184, 3, 46,199, 40, 95,177,114,165,100,230,135, 31, 58, + 36, 67, 89,118, 31, 34,159, 0,248,120,123, 1,128,249,211,214,117,141, 91,180,182,235, 13, 56, 26,247, 33,122, 69,127,134,119, +223, 28, 11, 0,230, 79, 91,215,173,218,151,230,144,118,205,229,114,209,188,121,115,112,185, 92,232,116, 58, 40,149, 74, 24,141, + 70,148,151,151, 59,245,114, 61,121, 92,252,178,124, 47, 4, 62,192,131, 28,224,175,234, 2, 20,223,207,194,150,184, 5, 14, 89, +253,221,250, 12, 66,243,166, 53, 67, 36,205,109,144,127,235,214,173,205,195, 1, 0,144,159,159,239,146,242, 99,152, 92,149, 26, +230,225,129,175, 62,156, 1, 0,248,202,130,248,183,102,102,214,238, 76, 28,200,214, 58,113, 65,127,113,121,175,100,249,103, 45, +223,134,150, 28, 12, 1, 73, 97,200,235, 70,108,252,126,151,228,232, 42, 48,237,204,121,211,166, 77,251, 77,173, 86, 99,211,166, + 77,154, 73,147, 38, 9, 1,120, 2, 32, 55,109,218,164,155, 52,105, 18, 79,173, 86, 67, 40, 20,202, 27,218,209, 13, 27, 54, 76, +124,228,200, 17,185,105,193,150, 6,195,147,207,249,207,138,175, 62, 21,249, 94,219, 14,209,205,227,248,226, 85, 63,175,143,246, + 23,127, 89,165,163,158, 42, 5,128, 94,130,183,188,124, 8,229,239,159,236,240,179,191,252,242,203,226, 63,255,252,211,105,178, + 89,182,108,153,120,247,238,221,242,170,170, 42,155,231,239,221,187,135,221,187,119,203,223,123,239, 61,201,198,141, 27, 83,236, +212, 23, 98,219,182,109, 91,250, 13,123, 99, 66,230,133, 51,188,230, 77, 27, 27,222,122,111, 90,173,126,247,248,193, 95,209,181, +107,215, 14,219,182,109, 27,222,181,107,215,125, 0,112,234,212,169,122,219, 7,147,246, 86,211, 62, 8,192, 78, 34,158,238,221, +187, 83,135,146,142,226,194,149,107,230, 99, 26,141, 22,223,173, 88, 87, 61,125, 82, 20, 75,216,207, 49, 30, 10, 2, 92,186,116, +169,184,223,208, 49,242, 14, 45, 3, 32,112,227,128, 36, 73,220,191,127, 31,151, 51, 46, 64,103, 32, 65,146, 20, 2,124,220, 49, +116,248, 72,185, 90,107,112,248, 15, 5,110, 69, 8,105,121, 31,224, 18,232,212, 62, 15, 2,222, 3,135, 45,127, 75,242,183,134, +162,178, 10,247,243,114, 32,242, 9,168,211, 43, 80, 31,121, 89, 99,243,206, 95, 49, 99,116, 47,244,138,254, 12,245,104,217, 15, +129,207,231,131,203,229,194,219,219, 27,217,217,217, 40, 47, 47,175, 81,164,156, 36,255, 38,141,130,225,201,227, 98,204,204,175, + 49,124, 98, 31, 28,184, 82,128,251,106, 52,152,252,173,145, 95,120, 31, 87,207,157, 70,144,159,119, 13,249,243,184, 46, 41,191, +215,198,189, 11, 0,240,227,185, 57, 68,254, 0,240,127, 43, 87,225,255, 86,174, 50,147,127,146, 82,137, 79,134,142,172, 57, 25, +196,103,244,220,125, 98,219,136,167,206,125, 69,254, 94,171, 15,224,198,241,132, 7,220,193, 1, 23,205,130,251,226,195,175,230, +200,231,239,239,192, 72,141, 72, 73, 73,209, 3,192,230,205,155, 85, 0,132,244, 50,202,155, 54,109, 34, 1,184, 91, 46,171, 28, + 21, 21,229,212,184, 92, 92, 92,156,216,145,227, 12,208,175,103,247,110,170,132, 95,247, 74,187,119, 9,229, 42,175, 29, 67, 78, + 81, 21,238, 85,168, 64, 82,148, 83,129,192, 20, 69, 81,101,101,131,169, 1, 3, 6,184, 52,145,152, 5,249,195,223, 63,217, 41, + 25,105,105,105,114, 0, 4, 65, 16,120,249,229,151, 29, 46,179,228,228,228,135,200,255,220,185,115,152, 56,113,162,121, 95,175, +215,227,198,141, 27,242,184,184,184,122,189,152,219,182,109,251,176,223,176, 55, 70,126, 19, 59,155,151,144,144,128,159, 87, 44, +229,153, 60, 70,102,242, 79, 72, 72,192,202,149, 43,209,181,107,215,125,246,218,155, 53,249,215,213,222,134,247, 53,121, 1,189, + 60,236,202,251, 97,197, 26, 51,249, 23,149,148,162,168,164, 20,138,170,106,184,185,241, 60,215,108,218,174,129,171, 22, 68, 96, +241, 88, 17, 22, 22,246,208, 86,175, 2,176,122,245,106, 42,160,245,139,104,221,216, 23, 26,189, 17, 4, 1, 36, 37, 29,198,255, + 54,111,194,165,140, 12,124, 50,103, 22,184, 92, 14, 72, 35, 9,111,119, 1, 90,191,216, 79,190,124,249,114,198, 13,108,229,202, +149,226,206,237,239,202,189, 61, 85,248,101,115, 17, 56, 4,133, 94, 93,111,202, 87,174, 92,233, 80, 35,181, 69,254, 52,241,171, + 21,165,181, 20, 4, 69,101,149, 93,121,182, 26, 19,221,144,210,226, 23,215, 34,184,205, 59,127,101,116,143, 33, 33, 33, 8, 8, + 8, 64,101,101, 37,248,124, 62, 56, 28, 14,212,106, 53,202,203,203,193,229,214, 52,114, 71, 22, 91,218,243,219, 94,204, 90,126, + 4,123, 87,124,142, 38,141,130,225,238,225,143, 60, 99, 1,182,196, 45,128,167,169,211,224, 50,148,103,139,252,105,226, 87, 20, +222, 70,135,230,141, 80,165,210, 64,224, 46, 0,140, 70,187,241, 0,246,202,111,193,250, 3,184,122,254, 44,186,180,237, 4,133, +209,190,210, 72,147,255,205, 35, 71,241,127, 43, 87,153,143, 39, 41,149, 72, 82, 42,145, 45,253, 47,142, 92,187,132,206,189,218, + 2,165,246,151,102, 30, 56,175,173,120,250, 71,131,228, 65, 30, 29,161,166,170, 0,109, 17,248,218, 50,104,141, 85,208,144,106, +144,124, 79, 52,235,223, 19, 67,166,183,162,236, 89,115,244,184,191, 84, 42,117,151, 74,165, 64,205, 16, 0,164, 82, 41, 76,251, + 38, 11, 74,131, 29, 59,118, 56,220,104,103,207,158, 45,158, 51,103,142,188, 83,167, 78, 20, 65, 16,114, 0,120,251,237,183,169, + 86,173, 90, 81,159,127,254,185, 83, 75, 51,123, 9, 56,155, 86,125,246,158,104, 88, 51, 45,247,204,141,251, 56,144,195,193,103, +135, 30,104,255,155, 82,173, 80,234,241,174, 51, 50,203,203,135, 60, 74,203, 31,254,254,201,136,142,142,118,120,136,208,146,240, + 41,138, 34,232,229,164,153,226,221,119,223, 21, 63,120,192,204, 40,209,233,116,184,124,249,242,241,250,234, 11, 0,113,243,166, +141,249,145,145,145, 0,128,244,244,116, 28, 63,248,171, 48,191,240, 62, 73,147,191,233,217,205,237,237,242,229,203,113, 13,105, +111,223, 77, 26,137, 43,183,243,208,184,109, 19, 64,169, 98,252,236, 69, 37,165,208,235, 13, 38, 5,199, 0,189,222,128,188,187, + 57,194, 6,190, 86,194,206, 62,139, 39,136, 90,174, 40,173, 86,139,238, 29, 58,200,221, 69,110, 32, 73, 10, 70, 18, 56,125,242, + 20,254,251,213,215, 32, 41,224, 86, 86, 22, 46,101, 92, 68,151, 46,221,192,229, 18,120,161,109,115,100,159,103,238, 5,224,243, +138, 16,218,186, 16,224, 17,200,187,167, 7,120, 4, 94,236,112, 23,105,151,139,156,126, 0, 75,247,190, 45,207,128, 90, 81, 90, +107, 54,128, 61, 88,186,247,109,105,218,105,241,139, 49,100,246, 74,155, 81,236,150, 48, 24, 12,112,119,119, 7,135,195,129,159, +159, 31, 84, 42, 21,148,202,154,101,128,131,130,130, 80, 90, 90,234, 80,142,108, 77, 57,208, 75, 36,194, 39, 43, 78, 98, 72, 55, +224,238, 5,224, 47,211,185, 79, 86,156,196, 79,179, 37, 48,146, 70,135,203,239,234,185,211,230,239,131,194, 59,128,231,197, 65, + 82,202, 53,116,239,208, 2,222,158, 2,108,222,157,140,158,146, 8,228,219,152, 5, 96,175,252,246, 93,163,128,123,192,232, 65, + 4,214, 31,200, 70,128, 95, 27,140,237, 75, 48, 42, 63,218,221,159,164,252,123,233,100,234,139, 56,160,153, 2,196,212,133,160, +254,251, 21,192, 81,131, 72, 91, 68,119, 42,117, 22,102,200, 56, 79,121, 43,223,112, 84, 26,171,161, 45,207,194,150,220,109, 56, + 53,186, 28,157,166, 72, 48,116,166, 39, 68,126, 47, 64,200,243, 3,111,180, 2, 83, 12, 83,168,159,215,255,108,179,147,146, 74, +165, 20,173,180,113, 56, 28, 80, 20,165, 51, 41,209, 26, 14,135,163,162, 40,202, 31, 0,137, 6, 76,175,141,139,139, 75, 25, 54, +108,152,164,180,180, 84,158,148,148, 84,163,248, 36, 37,161, 99,199,142,232,208,161,131,132, 62,230, 8,170,180,228, 71,147,255, +239,167,253,223, 71, 52,230, 80, 26, 5,166,198,103,234, 13,122,253, 74,173, 17,139, 0, 56,181, 24,197, 27,111,232, 30, 57,249, +199,199,199,167, 56, 99,253, 91, 14,153, 16, 4,129, 94,189,122,137,153,174, 42,105, 52, 26, 29, 82, 24,238,220,185, 3,153, 76, + 70,172, 89,179,198,214,105, 33,128, 78, 0,120,175, 70,140,173,200,206,206,246, 77, 79, 79, 71, 66, 66, 2,194,179,179, 57,233, +233,233, 0,128,240,240,112,188, 54,176, 39,188, 61, 5, 88,185,113,111,209,196,137, 19, 99,215,172, 89, 51,219,209,246,118,239, +183,197,240,234, 44,132,103,251, 89,216,181,120, 10,186,117,105,140, 23, 70,126,109,183,125, 40, 42,171, 32, 20, 10, 0, 0,110, +110, 60,168, 84, 26, 87,243, 12, 75,250, 79, 0, 76, 22, 3,170,213, 81,145, 36, 9,119, 1, 31, 58, 3, 5,146, 2, 56, 4,176, +240,203,175, 97, 36,129,234,234,106,220,191,127, 15,193,193,141, 65, 81, 36, 12, 6, 35,132,110, 60,112,221,152,185, 96, 87,173, + 90, 37,110,223, 58, 95, 30,232, 87, 89, 83, 29, 76, 27, 65, 80,232,209,249,150,156,158, 21,224, 8,104,235,158,118,247, 91,147, + 63, 19,235,223, 90,139,166,137,127,213,190,180,135,200,159,169,245, 15,212, 4, 12, 9, 4, 2,248,248,248,152, 93,134,116,224, +159,143,143, 15, 26, 55,110, 12,131,129,185,242,180, 49,249, 4,124, 90, 3,226,208,154,253, 76, 67,141,251, 31,168, 57,246,249, +215,114, 84,232, 28, 27,146,201, 47,172, 9, 86,108,217,200, 31, 94, 62, 30,224,121,115,161, 41, 81, 3, 28, 14,154,180,106,142, +211, 25, 57, 78,149,223,187,115,191,193,128,222,175,130,119, 31,168, 14, 6,220, 57, 28,244,110,221, 6,210,209,193,140,228, 88, +143,245,111,125,115, 10,198,188,209, 31,104,167, 1, 46,241, 0, 79, 30, 48, 42, 28,205,215,174,103,230,141,105,230, 15,157,174, + 12,132,182, 20, 91,114,183,225,236, 36, 31, 12, 24, 51, 9,253, 26,189, 38,185,114,196, 0, 3,169,132,155, 78, 9, 67, 7, 18, +197, 15,152, 5,141,154,148, 55,205,164, 73,147, 56, 0,202, 41,211, 10, 81,166,253, 6, 33, 41, 41, 41,165, 99,199,142, 18,119, +119,119, 4, 6, 6,194,221,221, 29,169,169,169, 68, 82, 82, 82,138, 19,226, 26,143, 28, 57,114,253,170,117,191,112, 22,166, 84, +147,187,207,100, 65,171,211, 43, 53, 70,204,115,132,252,173, 93,254,169,169,169, 4,189, 61, 45,228,111,203,221,239,168, 23,160, +186,186,218,252,253,220,185,115,230, 13, 0,230,204,153, 83,107,223,226,122, 65, 29,226,154, 2,104,109, 82, 10,221, 95, 27,247, +182,198,210, 19, 64, 91,254,175,244,237,107,217,222, 14, 72,165, 82,141, 35,237, 45,102,212, 0,188, 24,222, 1, 94,221,188, 80, +112, 44, 23, 16, 10, 48,110,230,191,208,235,157,159, 24, 61,179,193, 96, 68,193,189, 7, 6,218,242,167,145,119, 55,167,161,175, +150,170, 99, 99,241, 20, 40, 4,176,101,169, 80,166,206,141,164, 0, 35, 89,163, 4, 16, 4,240,235,158,221, 24, 51,118, 60, 2, +131, 26,153, 59, 64,202,129,119,201,229, 20,161,115,187, 60,243,254,139, 93,220,205,186, 97,143, 78,217,224,114, 28,247, 2, 88, +187,251,109,157,119,196,250,183,118,247,219, 58,111, 57,151,189, 62, 84, 86, 86,162,170,170, 10, 90,173, 22, 36, 73,162,184,184, +216,236,254, 87,169, 84,168,174,174,118,104, 8, 96,239,138,207,145,114, 5, 80,228, 0,122, 53,240,211,124,137,217,253,127,254, + 2,112,241,222,105,112, 29, 44, 63, 69,225,109,248,251,120, 32,192,223, 3, 47,132,118, 68,246,157, 98,100, 22,148,162,101,128, + 15,180, 15,138,144,117, 43,171, 86, 46, 0, 38,229,215, 71,252, 58,250, 73,162,176,119,255, 46,200, 83,119, 97,219,178,185, 24, + 55,119, 17, 46,233,129,226,210, 34, 70,229,103, 57,214,255, 94,159,151, 17,221,169, 21,118,237, 61,142, 75,151,114,176,236,114, + 58,118, 12,249, 23,176,225, 12, 10, 10,138, 25, 89, 23,205, 53, 2, 24,117, 37,208,233,106, 34,171,131,155,181, 64,135,142, 29, + 37,149,162,154, 88, 12, 53,169, 2, 71,171,132, 72,201,197,131,123,245, 43, 0,244, 59,211,104, 52,208,104, 52, 66, 0, 58, 0, + 94, 26,141,198,219,122, 74, 96, 3,188, 0,226,212,212, 84,121,199,142, 29,241,246,219,111, 75, 74, 74, 74, 48,118,236, 88, 71, + 58,206,126,124, 62,191,218,211,211,211, 48,100,200,144,123,243,231,207,111, 26, 27, 27,155,253,215,133, 75, 35,118, 92,213,222, +208,147,112,120, 61,214, 71,225,242,119, 37,249, 91, 91,255,180,194, 66,191, 51,166,177, 0,110,110,127,199,168, 44, 91,182,204, +188,217,218, 7,204, 51,124,234,122, 55,124,211,198, 1,192, 83, 20,222,182,233, 78,167,219,219,133,243, 23,238, 76,156, 56, 49, +198,145,246,214,255,165, 23, 48,184,111, 40,190,249,114, 41,126, 88,158,136,255,108, 61,142,105,175,246,196,253,223, 19,161, 40, +175,100,210, 62,136,200,209,175, 65,175, 55, 92,208,235, 13, 6, 75, 5, 0, 0, 22, 45, 92,208, 16, 11,158,181,252,159, 32,108, +141,253, 91, 43, 1,181, 20, 0, 14,135, 3, 69,181, 10, 92, 14, 1,131,193, 8,146,162, 96, 32,107,130, 72, 51, 46, 94,192,171, +131,134,213,184,201, 40, 10, 92, 14, 23, 85, 42, 29, 12, 58,173,125,235,127,245,106,113,155,102,247,228, 65,254, 10,179,150,209, +167,151,167, 41, 70,151, 0, 65, 80,232,222, 49, 75,190,106,245,106,198, 94, 0,218,186,175, 47, 24,208, 41,235,181,158,224, 26, + 71,224,231,231,135,226,226, 98, 8, 4, 2, 84, 85, 85, 33, 40, 40,200, 28, 20,168,209,104, 80, 81, 81,225,144, 2, 16,243,205, + 14,252, 52, 95, 2,159,214, 64,202, 21,224,163, 37,114,120,242,184, 24,251,241,183,200, 39,239, 35,126,217,167,224,114,152,203, +163,173,255,240,240, 80, 4,181,109,141, 70, 65,129,224,115, 8, 24, 8, 10,197, 74, 53,202,171, 52, 78,149,223, 15,139,127,195, + 27, 29,219,192,219, 59, 0,238, 65, 77,161, 47, 43,199,133, 3,219, 81, 81,150,235, 84, 37,254,101,241,135,192,236,193,224, 25, +116,104,173, 4,138,184,149,248,233,222, 95, 0,223,155,177,140,243,251,255,144,148,112,212,200,229,171,208,179,157, 4,157,254, +229,137,108,191, 20,121, 80,208, 5,121,139,222,217, 80,112,170,160,165,212, 80,109, 37, 33,244,244, 98, 98,249, 91,118,240,244, + 44, 0,190,171, 26,238,225,195,135, 1, 0,209,209,209,146,184,184,184,148, 49, 99,198,152, 45, 70, 38,228, 31, 20, 20,116,104, +253,250,245, 30, 50,153,140, 59,123,246,108,204,154, 53,139, 58,115,230, 76,111, 0, 73,106, 3, 58, 2,248,211,209,123,146, 74, +253,234,116,251, 59, 27, 16,232, 74,242,183, 38,120, 75,133,133,162, 40,194, 20, 24,104,191, 93,228,231,159,161,191,111,219,182, +205,188, 89, 31,163,225,239,239, 15,169, 84, 90, 87, 39,152, 15,160, 2, 0, 39,191,240, 62,206,158, 61,107, 30,243, 15, 15, 15, + 7, 80,179,252,246,206,125,137, 40,175,210,168, 0, 44,156, 15, 74, 29, 0, 0, 32, 0, 73, 68, 65, 84,146, 74,165, 70, 71,218, +219,239,123,191,192,176,249, 51, 49, 98,196, 32, 4, 10,184,168, 34, 40, 36,101,230,225,236,149, 2,135,136,122,250,164,168,151, +178,179,178,120,121,119,115, 64,111, 38,242, 7,107,181, 63,155,196,111,125,204, 22,106,197, 0, 8, 4, 2,220,186,118, 73,210, +186,169,191, 92,228,198,131,209, 72,130, 32, 8, 16, 4, 16, 35,157, 1,138, 34, 97, 52,229, 3, 80,105, 52,184,158,153, 13, 62, +223,110, 84, 55, 12,250, 50,116,239,116,199,178,199,192, 7,179,239, 96,207,214,246,230,170,213,179,203,109,252,145,209,209, 97, +235,223, 22,241,171, 21,165, 0,224,148,245,111,171,161,165,197, 47, 6, 0,198,214, 63, 80, 51,207,191,113,227,198,208,106,181, +120,240,224, 1,140, 70, 35, 2, 3, 3, 81, 90, 90,138,192,192, 64, 83,185, 50, 39,236,226,251, 89,248,252,107, 57, 20, 57,192, +247,115,251,163,218, 96,196,156, 37, 9,248,113,126, 36,230, 46, 59, 0, 30, 65,192, 1,254,135,162,240, 54,154, 4,250,194, 13, +110, 48,130,192,189, 59, 87,113,183, 72,129,144, 32,127,252,126,254, 12,174, 95,131,195,214,255,184,201,115,224,230, 15,112,184, +192,166,196, 59,216,179,250, 19, 76, 94, 44,195,156, 81,221, 48, 99, 80, 43,135,202, 47, 73,169,196, 15,163, 39, 0, 21, 66,128, +112, 3,126, 88,138,241,127,157,196,145, 65,211, 65,124, 59, 19,196, 31,159, 50,182, 48, 46,222, 11,192,203,106, 5,170, 69, 92, +168,132, 66,132,140,115,131,150, 82, 67,193,113,131, 1,161,160,140, 42,232, 75,238,225,244, 10, 5,162, 39,134, 32, 69, 46,127, +236,141, 54, 38, 38,134, 2,128,117,235,214,209,174,126, 98,246,236,154, 97,224,173, 91,183, 50,125,179,125,155, 54,109,122,248, +219,111,191,245,184,117,235, 22,220,220,220,224,237,237,141, 75,151, 46,233, 1, 20, 55,228,254,234,155,147,239,140,119,192,149, +228,111,109,253,215, 16,243,195,211, 7, 77,211, 3, 83,236,220,215,173,157, 59,119,246, 97, 58, 60, 39, 20, 10, 39,215,173, 52, + 73,171, 6, 14, 28,120, 7, 64,120,230,133, 51,176, 28,243,255, 96,242, 4, 28,110,219, 22, 9, 9, 9, 72, 79, 79,199,161,182, +109,221, 39, 78,156,184,241,196,137, 19,140,219,219,155,131, 95,134, 15,233, 7, 21,220,176, 39,110, 38, 86, 31,184,136, 79, 94, +235,135, 73,203,182, 97,252,162, 45,142, 90,224,196,162,133, 11,108, 37, 2,162, 44,148, 0,214,162,127,206, 80,203, 3,240,193, + 7, 31, 16, 21,247,178,112, 59,175, 20, 60, 55, 46, 12, 70, 18,122,131, 17,231,207,167,227,127,255,219, 8,157,145,130,222, 72, +130,207,227,160,168,188, 26, 5,215,207, 74,102,205,154, 85,111,131, 90,189,122,181,184, 99,200,221,191,173,127, 83,189,218,179, + 53,180,166, 62,113, 40,128, 67,129,195, 33,209,187,219,117,249,106, 6, 94, 0, 91,214,191,229, 44, 0, 15,255,198, 14,145,191, + 45,235,223, 50,170,118,200,236,149, 14,145, 87, 77,167, 88,142,234,234,106,184,185,185,153,173,127,146, 36,205,159,142, 42, 0, + 91,226, 22,224,124,193, 9,120, 54,174, 9,250,243,226,113, 81,124, 63, 11,222, 2, 55, 84,148,229,131,203, 33,192,227, 48, 27, +126,166,173,255, 22,254, 94,184,150,125, 7, 6,157, 14, 2, 30, 31,213,213, 26,252, 46, 63,131,158,146, 8,135,200,159, 46,191, +215, 63,252, 10,241, 63,253, 8, 21, 9,180, 8,105,142, 43, 87,255,192,156, 81,221,156, 42, 63, 0,152, 19,210, 19,251,111, 29, + 7, 20, 6, 64, 24,136,163,105,215, 64,124, 59,147,238,152, 24, 23,222,137,165,217, 41,167,143,166, 1,186, 42, 84, 19, 85, 40, +231, 84, 67,193,211, 67,111,172,132, 64,163,130,176,240, 14,118,196,222, 66,235,176, 80,212, 21, 0,104, 13,145, 72,100, 73, 2, + 16, 10,133, 54,207, 49,197,250,245,235,177,126,253,250, 6, 53,102, 47, 47,175,143,178,178,178, 60,188,189,189, 33, 18,137,224, +239,239,143,226,226, 98, 16, 4,161,114,101,167, 65, 91,252,145,145,145, 20, 80, 19, 16,232, 72, 80,160,171,201,255,229,151, 95, + 22,219, 11,168,101, 26, 11,224,225,225, 17,195,227,241,110, 91, 31, 95,182,108, 89, 45,203, 31, 0, 90,181,106,133,193,131, 7, +111,178,103,255,228, 23,222,175, 21,237,255,249,255,205,134,128,199, 71,112,112, 48,232,152, 0,211,121, 15, 71,218,219, 20,241, +139,152,181,244, 71, 84, 61, 40, 66,144,119, 35, 92,189,150,139, 73,203,182, 57,220, 62,172, 8,159,176,250,189,165, 28,214, 19, +240, 12,224,226,197,139,245, 38, 3,170,211, 3, 0, 0,243,230,205, 75,249,126, 41, 33,161,168,209,242,214, 77, 3,224,229, 46, + 64,167, 46, 97,232,212,185, 27,120, 28,160, 90,109, 68,238,189, 50,164,165, 28,148,120,122,184,219,253, 3,165, 74,133,208, 86, +247,160,209, 10, 77, 89, 91,106,170,145, 72,168, 1, 69, 1,101, 21, 2,128, 0,188, 60, 12,232, 26,154,131,147,231,236,103,177, +179,180,254, 45, 45,126,145, 79, 0,220, 40, 61, 96,248,187,191, 51,242,236,223,163,165,245,111,105,241,211,199,178,174, 94, 48, + 95,203, 36,203,158,165, 18, 0, 0,141, 27,215, 40, 35,101,101,101,240,246,246, 54,187,255, 29, 81, 0,104, 37, 0,248, 22,211, + 35, 7, 2, 63,157,196,234,127, 71, 96,252,220, 31,177,109,241, 12,240, 8, 2,124, 1,179, 25, 59,180,245,127, 45,183, 8,237, + 90, 4, 98,195,207, 59,208,186,117,107,248, 52, 13, 65,183,166, 33,208,107,255,118,255,187, 49,144, 73, 91,255, 95, 79, 30,132, +143, 22,110, 66,139,182, 68,131,202,143,182,254,135,238,253, 5, 71,162,163, 64, 52,239, 13,160, 38, 43, 32, 0,220, 81, 42,205, + 74, 98, 38,152, 37,240, 89, 53,233, 54, 49,112, 30, 37, 14, 25, 91, 37,111,221,190, 11, 42, 69,192, 29,220, 69, 85, 78, 49,138, + 23, 25, 81, 93,222, 28, 55, 78,103, 50,126, 33, 36, 73, 18, 34,145,136, 82,171,213,176,176, 60, 41,145, 72, 4,146, 36,137, 39, +209, 89, 86, 85, 85,125, 63, 99,198,140,209,235,215,175, 23,250,248,248, 64, 46,151, 99,249,242,229,149, 58,157,238, 53, 87,254, + 15,109,241,211,211,229, 28, 13, 4, 76, 72, 72, 32, 76, 73,126, 26, 76,254, 0, 96, 65,236,118,203,220, 94,134, 65,169, 84,170, +147,201,100,189,119,237,218,117, 73,169, 84, 54,209,235,107,166,153, 90,147,127,167, 78,157,208,187,119,239,145, 82,169,212,222, +127,242, 20,133,183,241,205, 23,159,227,215,253,135, 48,172, 95, 15, 28, 75,254,163,198,128,105, 26, 2,159,166, 33, 8,207,206, +198,107,227,222, 46,201, 45, 85, 13, 5,176,155,169,245, 63,107,221,126,196,190, 63, 20, 77, 27,139,205,202,133,117, 57, 52, 48, +155, 34,235, 9,120,142,148, 2, 70, 10, 0, 0,124, 50,111,110,202,247,223,147,146, 59,205, 95, 64,219,246, 29,229,222, 30, 34, +144, 20,160,214,234,144,157,157,141,226,236,139, 18, 47, 79, 15, 76,159, 62,221,110,195, 21, 9,133,216,117,120,160,132,142,128, +175,215, 29,193,225,192,195,131,185,245, 68, 79, 1,244,240,111, 12,210,168,175, 33,127, 19,244,132,155,221, 20,187,214,160,167, +212, 12,153,189,178, 22,105, 57, 67,254,150, 74,128,101,226,159,178,178, 50,251, 47,192,142, 18,176,197, 98,150,240,250, 69, 31, +252,189,163,175,134, 39, 67, 57, 45,252,189,176,235,220, 69, 92,185,113, 19, 61, 37, 17,181, 72,223, 17,242,167,241,250,135, 95, + 97, 79, 15, 15,124, 56,166,131, 75,202,111, 78, 72, 79,204,221,183, 11,196, 55, 11,113, 40,248,101, 44,175,190, 82,235,252, 88, + 31, 95, 44, 86, 84, 56, 68, 28, 39,150,102,167,248,241,134, 32,191,252, 54,138, 75,239,225, 65,166, 39,184, 70,111,244,125,177, + 63,118,156,222,241, 68, 59, 53, 23,101,251, 59,183,113,227,198, 33, 4, 65, 28,253,241,199, 31,133,111,188,241, 70,165, 74,165, + 26, 10, 39,198,252,235,131, 43,166, 0, 74,165,126, 46, 33,127, 27, 86,170, 61,229,131,193,189, 73, 75,100, 50, 89, 72, 85, 85, +213, 55,233,233,233,179, 11, 10, 10,160, 84, 42,193,231,243,209,164, 73, 19, 4, 5, 5,189, 33,147,201,126,223,178,133,209,146, + 0,215, 1,132,183,240,247,194, 43,175,188,130,139,183, 10, 16,216,166,115,173,246,246,218,184,183, 85, 0, 86,124, 19, 59,123, + 55,211,231,152, 34,126, 17, 67,146,255, 68,244,194,255, 97,192,128, 1, 8, 14, 14,182,169,104,185,240,181, 19, 78,144, 63, 85, +207,113, 86,137,120, 2,164,207, 40, 21, 48, 0,124,242,201, 39, 41,171, 86,173, 18,159, 79,201,148, 0, 53,145,180, 20, 69, 65, + 32, 16,224,211, 79,230, 49,110,180, 31, 58,152,230,151, 41,104, 87, 63,215,160, 2, 12, 42,115, 4, 60, 77,252,142,206,197,162, + 93,253, 89, 87, 47, 32,235,234, 5, 4, 5, 5,161,184,184,216, 41,226,247, 9,106, 10, 29,131,224, 72,166,136,254,106, 11,206, +156,116, 93, 49,230,228,228,152, 87,251,211,107, 53, 15,145,191, 35,196, 79,227, 95, 61, 60, 92, 86,126, 0, 64,196,125,106, 38, +126,154,252,239, 40,149,146,177, 62,190, 72, 2, 82, 22, 43, 42,156,122,246,223, 22, 31,181,232,120,212, 0,128, 29, 87,153, 39, +236,161, 40,138, 16, 8, 4,102, 47, 0,253, 29, 0, 4, 2, 1, 97,235,251, 99,198,169, 95,126,249,101,192,238,221,187,231, 84, + 86, 86,198, 1, 72,115,245, 31,184, 98,234,159,139,201,201,229,144, 74,165,106, 0,115, 76, 91,131,222,199,229,203,151,251, 2, +104, 19,216,166,179, 74,175,213,184,155,218, 91, 37, 0, 5,128,235, 45, 3,220,223,148, 74,165, 14, 85,232, 33,159,175,127, 92, +196,239,148,162,229,228,245, 44, 92,128,176,176, 48, 70,228,111,215, 0,109,232, 74,125,143, 2,244,216, 62, 77,252,104, 32,241, +211, 99,211,138,162,124, 40,138,242, 17, 20, 20,212, 32,139, 31, 0, 12, 70,210, 97,239, 67,125, 40, 42, 83, 56,125, 47,214,160, +199,246, 93, 69,252,143,160,252, 8, 0, 24,230,225, 65, 89, 90,253,221,121,110, 13, 34,254,127, 24,254,170,172,172,140, 98,139, +225,201,227,196,137, 19, 50,153, 76,246,191,220, 82,149, 74,175,213, 88,142, 71,122,183, 12,112,247,115, 98,245, 63, 2,168, 25, +202,120,214,148, 42, 22,143, 87, 9, 96, 84,153,156, 93, 71,152, 5, 11, 22, 44, 88,176, 96,241,236,130,195, 22, 1, 11, 22, 44, + 88,176, 96,193, 42, 0, 44, 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88,176, 10, 0, 11, 22, 44, 88,176, + 96,193,226,185, 64,173, 89, 0, 23, 47, 94,116, 58,138,212, 86, 48, 33, 43,143,149,231, 42,121,166,181,213, 57, 0, 72, 91,201, + 87,216,242,171, 91, 94, 88, 88, 24, 93,118,244, 92,110,234,226,197,139, 36, 91,126,172,188,103, 73, 94,120,120, 56, 47, 61, 61, +221, 0, 0,189,122,245,162,218,183,111,143,248,248,120,130, 45, 63,219,242, 28, 86, 0,158, 19, 52, 40,201, 68,100,100,164, 24, +128,101,202, 80, 73, 66, 66, 66, 10,171, 43, 62, 25,124,247,221,119,239, 92,190,124,185,219,217,179,103,231, 10, 4, 2,168, 84, +170, 79,101, 50,217, 82, 6, 25,216, 88,252,221,177, 80, 0,140,108, 73, 60,221,136,136,136, 16, 31, 60,120, 48,197,201,223, 74, + 18, 19, 19,143,187, 40,161, 20, 34, 34, 34,222, 76, 76, 76,220,177,118,237, 90,127, 0, 85, 0,140, 79,186,205,209,228, 31, 29, + 29, 77,109,221,186, 21, 61,123,246,100, 43, 77, 3,241, 92, 13, 1,152,200,187, 65,191,223,181,107,151,117,190,112,121, 67,228, + 70, 70, 70,138, 77,115,118,169,200,200, 72,202, 81, 89,148,131,176, 53, 63,184,129,242,196, 79,226, 93,202,100, 50, 98,230,204, +153, 75,175, 94,189,250, 83,171, 86,173,230, 10,133, 66,104,181, 90, 0,248,110,207,158, 61,228,152, 49, 99, 36, 79,168,201, 80, +142,111,143, 83, 94,157,107,176, 91,174,197,238,212,250,236,145,145,145, 98,138,162, 40,234, 63,182,101,211,231,236,213, 65, 91, +200,201,201,161,114,114,114, 92, 70, 48,101,101,131,107,173, 87,224,106,162, 38, 8,194, 33,185, 36, 73, 81, 70, 35, 69,145,164, +237, 45, 34, 34, 66,156,152,152,232,212, 42, 84,235,214,173,123,245,208,161, 67,199, 7, 14, 28, 8,130, 32,168,237,219,183, 15, +118,244,222,172,183, 67,135, 14,237,120,171, 15, 31,210,105,210,178,219,158,217,187,167, 78,141, 33,233,115,246,228, 41,149, 74, + 74,169, 84,214, 91, 15,233,107,156,125, 63, 55,206, 73,144,188, 46, 3,225,225,225,172, 33,192,220, 16,120, 40, 65, 16,207, 78, +131,183,153, 55,219, 94, 62,237, 39,136, 6, 45,227,182,107,215, 46,249,132, 9, 19, 0,212, 36,213,176,168,156,114,103,188, 10, +180, 66, 65,231,252, 55,165, 33,149, 71, 70, 70, 58,230, 85, 72,240,119,224, 95,237,183,125,229,168, 15,152,139,115,124, 93,155, +186, 26, 36,227,242,147,201,100,132, 66,161,216,217,165, 75,151,113, 0, 56, 20, 69, 65, 36, 18,161,168,168, 8, 21, 21, 21,240, +241,241, 65, 81, 81,209,241, 49, 99,198, 72,246,238,221,155,226,224, 59,161,232,116,176, 4, 65, 96,220,184,113, 24, 60,120,176, +100,218,180,105,140,229,236,219,247,155,249,251,232,209,111,216,221,183, 7,245,153, 15,255, 46,238, 62, 43,107,237, 91, 31, 19, +245,177,191,168, 18,189,156,176, 37, 82, 83, 83,177,104,209,162,135,222, 69,255,254,253,169,147, 39, 79, 50,170,203, 9, 9, 9, +114, 44, 36,232,253,135, 19,207, 44, 36, 26,220, 25, 63,197,125, 75, 45, 75, 91, 38,147, 73, 98, 98, 98, 48, 96,192, 0,234,212, +169, 83,140,126,123,166,142,156,140,123, 19,230, 34, 49, 49, 81, 78, 47, 18, 54, 96,192, 0,170,178,178,178, 62,194, 23,199,196, +196,152,235,235,239,191,255,238, 78, 16, 4,162,162,162, 30, 0, 8,158, 56,113,226, 81,153, 76,198,113,196, 98, 95,122,116,169, +249,251,253,164,123, 32, 8, 2,219, 62,118, 7, 64,224,251,183,191,123, 61, 48, 48, 16, 0,176,125,243, 54,198,101, 21, 30, 30, +142,182,109,219,186,164,220,195,195,195, 57,233,233,233,100,175, 94,189,168,173, 91,183,226, 65,102,107,160,196,143,101,117, 7, +200,223, 81, 15, 0,149,144,144,240,144,134,101,209,129, 82, 78, 52,110,151, 90,147,214,242, 18, 18, 18, 44, 23,196,112, 24, 4, + 65, 16, 9, 9, 9, 4,221, 1,153, 62,157,182, 52,105,242, 55,221, 19, 97,113,111, 14, 43, 42,196,132,114,243,198,228,184, 61, +120, 30, 88, 99,222,152, 28,119,132,252, 41,138, 2,189, 58, 27, 69, 57, 86, 77,100, 50, 25,167,188,188,252,127, 62, 62, 62,227, + 0,112, 38, 79,158,140,232,232,104,240,249,124,136, 68, 34, 8,133, 66, 16, 4, 1, 46,151, 11,133, 66,193,184, 28,135, 12, 25, + 34, 6, 64,237,222,189, 27,244, 59,161, 40, 10,123,246,236,193,180,105,211,228,166,243, 79, 29,108, 41, 4, 79,194,179,150,144, +144, 32, 7, 64,188,121, 99, 2, 38, 92,183,217,198,168, 9,215, 35, 37,196,151, 78,181, 59,234,147, 79, 62, 65,155, 54,109, 92, +114,191, 4, 65, 80, 82,169, 31, 2, 2,142,185,180, 28,134, 15, 31, 62, 40, 57, 57,249, 56, 69, 81, 68, 76, 76, 76,138, 35,228, + 95, 23,246, 38,204, 69, 92, 92, 28, 72,146,196,220,185,115, 25, 41, 20,150,228, 15, 0,135, 14, 29,218, 63, 96,192, 0, 0,240, +139,138,138, 50, 12, 28, 56, 16, 82,169,148, 52,197,205, 48,241, 50,214,218, 95,190,124, 57,222,124,165,198, 54,220,246,177, 8, +111,245,225,227,211, 97,159, 48,126, 38, 15, 15, 15, 12, 24, 48, 0,233,233,233,230,254,212,122,163,175, 97,170,236,165,167,167, +147, 64,205, 50,235, 0,224,237, 94,194,178,122, 3,201,191, 94, 5,128, 38,171,244,244,116,115,218, 73, 75,235,201, 81,162,181, +232, 68, 92,221, 41, 89, 43, 3, 46,117, 13,219, 24, 18,112, 24,150, 10,133,201,250,127, 30,235, 25,101,217,153, 20, 20, 20,152, + 79,228,231,231, 51, 86, 24, 21, 10,197,183, 42,149,234,109, 14,135,195,153, 56,113, 34, 20, 10, 5, 10, 11, 11,225,230,230, 6, + 30,143, 7, 30,143, 7, 55, 55, 55,136, 68, 34,168,213,106, 48,113, 33,174, 93,187, 86,124,244,232, 81, 57, 65, 16, 24, 63,126, + 60, 40,138,162,149, 60, 98,252,248,241, 0,128,228,228,100, 57,219, 85,212, 79,254,166,247, 43,177, 84,146,233,119,111,233,213, +114,198,130, 79, 72, 72, 32, 76,239, 5,107,215,174,117,137, 50,182, 96,193, 2,218, 40,104,176,103, 98,216,176, 97, 67,206,157, + 59,151,220,186,117,107,180,107,215,142,234,219,183,175,217,115, 98, 90,253,209, 41,242, 95,182,108, 25, 8,130, 0,135,195,193, +185,115,231,192,196, 27, 99,229,145,120,157, 32, 8,188,245,214, 91, 6,211, 33, 93, 84, 84, 84,165, 88, 44,198,180,105,211,200, + 17, 35, 70,216,125,118,203, 85, 73,239, 39,221, 3, 8, 32,254,163,191,179, 22,111,251,216, 29, 81,125, 5,152,255,218,167,140, +239,139,137,229,207,228,154,232,232,104, 42, 60, 60,220,188,157, 59,119, 14,213,185,225,128, 78, 13,194,211,128,228,175,175,195, +242, 60,189,177, 45,183, 54,249,199,204, 95,108,243, 60,175,190, 6, 25, 30, 30, 78,165,167,167,131,246, 4,208,196, 21, 30, 30, +238, 80, 35,127,212,228,111,105, 85, 63,237, 1,123,150, 67, 2,207,157, 6, 64, 81, 40, 40, 40,192,253,251,247,205,199,172,247, +237, 88,255,220,195,135, 15,143, 8, 13, 13, 5,151,203, 69, 86, 86, 22, 40,138,194,205,155, 55,161,211,233, 64, 16, 4,120, 60, + 30, 8,130,128,209,104,132, 74,165,194,222,189,123,237,202, 61,118,236,152, 28, 0,198,143, 31,255, 80,189,165,135,122,104,162, + 96, 82,175,173,221,250,246,246,153, 88,249, 52,234, 26, 14, 96,226,250,183, 70,106,106, 42, 76,150, 97,195, 20,224,133, 4,136, + 47,107, 20, 56, 75,229,149,162, 40, 96, 33,129, 9,215, 35,157, 14,148, 37, 8,130, 50,189, 23, 51, 25,153,222, 23,209, 16,121, +237,219,183,127,136,220,156,133, 64, 32,160,174, 94,189,138,226,226, 98,162,184,184, 24, 97, 97, 97, 84, 78, 78, 14,184, 92, 46, + 12, 6,131, 83,127, 48,176, 47,151, 86, 30, 48,111,222, 60, 44, 95,190, 28, 39, 79,158, 4, 65, 16, 24, 53,122, 42,238,230, 48, + 91,192,241,208,161, 67,191,153,222,177, 6, 0,105,218, 16, 21, 21, 85, 1,192, 55, 49, 49, 17, 17, 17, 17, 98, 75,133,188, 62, +212, 88,255, 15,175, 99, 82, 51, 28, 0,108,223,118,193, 33,121, 13,197,141, 27, 55,112,238,220,185, 90,199,140, 21,119, 96,208, +147, 0, 81, 5,223,215,244, 56,103,181,216, 53, 27, 28,200,140,252,235,245, 0,152,172,127,194,210, 19, 64, 91,254,233,233,233, + 13, 33,127,123, 1, 74, 78,201,179,240, 76,136,225, 68,128,211, 35,176,156, 40,139,206,199,124, 63,244, 49, 87, 5, 39, 81,187, +252,204,155, 43, 80, 61,114,186,121,115,192,242,167,232,206,182,121,243,230,232,217,179,167,185, 17,210,251,214,215,214, 1, 95, +127,127,255, 46, 90,173, 22,101,101,101, 56,115,230, 12,210,210,210, 80, 92, 92, 12,181, 90, 13,122,140,148,162, 40,232,245,122, +104,181, 90, 70, 67, 12,116,221,168,139,220, 19, 18, 18, 8,130, 32,192,212, 51,179,111,223,111,230,141,201,190, 61,168,207,124, + 88,139,232,233,205,114,223,242, 26,166, 24, 48, 96, 0, 82, 83, 83, 27, 86, 33, 44,198,252, 81, 51,140, 37, 49,145, 51, 65,159, + 67, 3, 99,111, 44,223, 11,237, 5,112, 21, 92,225, 5,104,214,172, 25,242,243,243, 9,107,101,215, 89,242,223,155, 48,215, 92, +135,105,244,235,215, 15, 0,112,226, 52,243,201, 26, 17, 17, 17,195, 76, 99,255,215, 0,168, 76,253, 57,189,153,181,110,166,193, +133,181,199,254,109, 40, 87, 14,202,115, 5,210,211,211,137,158, 61,123,162,234,218,112,148,159,105,130,138, 83, 34, 80,229, 21, + 64, 53,192, 81, 25, 80,121,146, 3,245,159,124, 84,156,105,132,195,219,134,160,103,207,158, 14,241,211, 63, 29, 60, 38,141,147, +246, 4, 56,106,249,207,159, 63,159, 90,178,100,137,203,110,214,158, 60, 83, 39,229,178,202,201,116, 12,173, 62,210,177,144, 85, + 45,149, 74, 61,235, 58,239, 44, 44,199,254, 93,161, 4, 88,142,253, 51, 85, 2,162,163,163,225,225,225, 1, 79, 79, 79,120,121, +121,193,199,199,135,244,243,243,227, 36, 38, 38,226,157,119,222, 49, 95, 39, 20, 10, 49,116,232, 80,212,163, 4, 4,232,116, 58, +148,149,149, 65,163,209,192,199,199, 7, 2,129, 0, 6,131, 1, 20, 69,193,104, 52, 66,167,211, 65,175,215,195,104, 52, 58, 20, + 95, 96, 10, 90,171,243,188,165, 21,250, 36, 97, 47, 32,208, 81, 52, 84, 9, 32,190,172,123,184,111,194,245, 72, 19,185, 58, 41, +219,202,250,183, 56,142,241,227,199, 59, 28, 12,104,109,253, 91,202,115, 22,225,225,225,148,209,104, 68, 88, 88, 24,117,241,226, + 69, 34, 44, 44,140,210,235,245, 80, 40, 20, 13, 33,181,154,206,151,199,195,236,217,179,113,238,220, 57,252, 61,238,207,188, 78, + 31, 62,124,248,112,255,254,253, 1,192,203, 68,250, 42, 0,216,177, 99, 71,163, 19, 39, 78,120,155,218, 7, 97,250,180, 43,120, +249,143,203,241, 86,239,135,173,255,232,159, 84,216,113, 70, 15,138,162,208,125, 98,119, 92,216,118,129,120,156,198, 85,122,122, + 58, 33,249, 87, 56,117,120,121, 43,240,170, 43, 1, 67,205, 95,147, 0,248, 60,160,224,190, 47,142,231,134, 27,215,109, 47,230, +166,167,167, 19,225,225,225, 66, 58, 86,128,181,254, 23,215,123,157,221,105,128,145,145,145, 20, 93, 97, 45,227, 1,152, 96,201, +146, 37,180,197,224, 18, 48,144,231,244,248,186,105,138, 94,173, 45, 57, 57,153,164,103, 5, 52,212, 98,143,137,137,241,124,158, + 43,220,186,117,235,176,108,217,178, 90,245,138, 38,255,209,163, 71, 99,244,232,209, 53, 22,206,137, 19,245,137,241,207,206,206, +214, 24,141, 70,148,151,151,163,164,164, 4,229,229,229, 80,169, 84, 80,169, 84,168,174,174, 70,101,101, 37, 20, 10, 5,212,106, + 53,180, 90, 45,152, 52,116,130, 32,176,123,247,110,135, 20,182,103, 25,169,169,169,181, 54, 75,204,158, 61, 91,108,185,207,100, +204,217,198,152,127, 45,203,189, 33, 81,251,182,126, 75, 81, 20,177,123,247,110,151,198, 2,236,222,189,219,225, 54,220,163, 71, + 15,202,104, 52,154, 19,180,132,133,133, 81, 36, 73,226,193,131, 7, 80, 42,149, 78, 61,243,191,231, 15,196,137, 19, 39, 64,238, +244, 5, 69, 81,136,139,139, 51,191,163,212, 51, 36,152,142,124, 68, 68, 68,188, 1, 0, 81, 81, 81, 5, 38, 5, 64,187,125,123, +124,163,233,211,167, 55, 58,113,226, 4,134, 15, 31, 62,196,145,156, 0,247,147,238,129, 0,129,120, 11,235,127,226,143, 42,112, +223, 82, 96,251, 25, 29,102,205,154,133, 37,135,191,123,236,117, 57, 60, 60,156, 75, 43, 1,175,205, 50,128, 82,251, 0,149, 0, + 42, 1,110, 21, 80,249, 0, 56,116,161, 9, 44,200,159,151,158,158,174, 97,201,223, 62,249,219,245, 0, 88,143,251, 91,198, 3, + 48,117,179, 36, 36, 36,164,152, 2,132,228, 86,158, 36,103, 59,140,135,228,209,195, 2,166,113, 72,151,184,127, 6, 15, 30,124, + 37, 57, 57,185,203,211,248,130,105,171,223, 85,110,127,218,234,119,192,237, 95, 11,241,241,241,230,239,255,253,239,127,177,113, +227, 70, 0,208, 1,224,211,196, 15, 0, 67,135, 14,181,167, 0,168, 67, 67, 67,161, 82,169,160,211,233, 80, 92, 92, 12,129, 64, + 0, 30,143,103,246, 0, 40,149, 74,168, 84, 42,104,181, 90, 40, 20, 10,140, 27, 55, 78,178,103,207,158,122,239,143,182, 50,237, + 76,107,197,248,241,227,237, 42, 10, 53, 10,205,163,139, 1,112,230,188, 53, 44,166,251, 61,132,184,184, 56,249,236,217,179, 37, +113,113,113, 41, 79,180, 14,215, 97,253, 91,194,145, 88,128,186,172,127,103,209,163, 71, 15,234,252,249,243, 68, 88, 88,216, 23, +116,213, 54, 26,141, 11, 61, 60, 60, 80, 82, 82,226, 84, 31,243,249,103, 3,145,146,146, 2, 98,119, 0, 0,224,200,231, 94, 24, +250,117, 21, 6, 12, 24,128,111,150,156, 0, 69, 81,140,189, 21,135, 14, 29,218, 59,112,224, 64, 0, 40,222,177, 99, 91,179, 19, + 39, 78,250, 82, 4,133, 17,195, 71,140, 62,120,240,224,254,131, 7, 15, 58,228,229, 92,190,124, 57,222,234,227, 86,219,226, 7, +133,217,179,102, 35,120,104, 99, 60,169,184,165,244,244,244, 90, 26, 62, 85, 5, 8,116, 0, 73, 17, 48, 24, 41, 8, 40, 32, 88, +196,177,188,222, 0, 22, 53, 70,217,146,207,234, 84, 16,194,194,194,234, 87, 0, 44, 35,254, 77,228,111, 14,150,162, 61, 1, 76, + 53,127, 27,164,221, 32,216,144,231,242, 49,169,152,152,152, 46,201,201,201,174,236,240,158,215,122, 70,160, 38, 10,220,108, 73, +191,247,222,123, 0,192,183,168, 75,230,115,166, 78,171, 46, 92,237,221,187,247, 59, 41, 41, 41, 9, 70,163, 17,149,149,149,208, +235,245,230,113,127,141, 70, 99,158, 98, 72, 7, 6,238,217,179, 39,133, 65,125, 33, 96,154, 2,104, 93,111, 35, 35, 35, 41,154, +244, 7, 15, 30, 44, 97,162, 0, 60,170, 60, 0,150, 99,255,150,228,111, 61, 44,192,224,125,212, 7, 42, 46, 46, 78,254,230,155, +111, 98,231,206,157,206,122,203,196,150,158, 19,122,159, 14, 24,156,112, 61,146,186,117,235, 86,157,191,167, 19,254, 28, 62,124, +184, 78,143,221,157, 59,119, 24,123,102,202,202, 6, 83, 0, 48,100, 72, 54,178,179,179,109, 70,151,151,150, 14, 2, 80, 14,192, +126,191,213,169, 83, 39,234,252,249,243,132,169,179,252, 2, 0, 56, 28,206,194,187,119,239,162,188,188,220,169,134,204,225, 16, + 53, 10, 59, 77,254,151, 12,216, 40,215, 1, 0,190, 89,114,194,225, 62,130,110, 19,211,167, 79, 15,163, 40, 10, 17, 35, 35,198, + 29,216,127,224, 87,166,196,111, 41,234,141, 49,175, 95, 35, 8,162, 19, 69, 1,220,183, 20,160, 40, 10,179,231,204, 70,227,161, + 77, 26,152, 87,181,102, 90, 47, 93,239, 26,146, 73, 48, 60, 60,156,218,245, 89, 83,120,150,222,193,237,202,230,104, 35, 40, 6, + 60,130,193, 83, 62,128,183,178, 20, 64, 35,179,199,192, 90,105, 96,225,132, 7,192,114,186,159,213, 52, 54, 42, 33, 33,193, 97, +151,169, 5,105,187,228,198, 45,229,209,243,255,159,211,233,117,207, 4,172,202,190,214, 20,177, 58,206, 61,212, 25, 72,165, 82, +131, 76, 38,219, 51,112,224,192,153,137,137,137, 43, 12, 6, 3, 42, 42, 42,204, 49, 0, 0, 80, 92, 92,140,138,138, 10, 80, 20, + 5, 71,234,211,144, 33, 67, 36, 71,143, 30,149, 39, 36, 36,212,178, 62,233,223, 15, 25, 50,196,161,100, 64,143, 2,234, 51, 31, + 58, 67,248, 15, 17,188,157, 46,155, 32, 8,130,114,134,252, 77,158,182, 20, 91,109, 17, 0, 44,130, 2, 25, 97,218,180,105,114, + 6,255, 73, 57, 48, 87,188,214,103,109, 34, 98,150, 28,175, 77,155, 54,212,181,107,215,104,151,255, 23, 0, 22,106,181, 90,220, +190,125, 27, 10,133,194, 89, 42,164,200,157,126, 56,114,169,198, 56,221, 36,215, 97,199, 25, 29, 40,138,194,201,179,206,143, 44, +166,166,166, 98,248,240,225,146,131, 7, 15,166, 28,216,127,192, 89, 49, 28,146, 36,221, 0, 96,231, 89, 61,102,205,154,133,198, +195,154, 48, 87, 39,109, 64,169, 84, 2, 0,178,179,179,169,117,235,214,153, 21, 50,203, 88,146, 77,155, 54, 89,246, 15,140,254, +165, 21, 71, 9, 4,133,225,157,245, 10, 0,193, 53,101, 48, 35, 16, 45,121,121,248,122,112, 17, 54,183,127,139,218,177, 99,199, + 63, 62, 0,144,182,238,109, 89,254,214,231,235, 27, 2, 32, 76, 67, 0, 15, 77,155,114,100, 8,192,102, 71,225, 58,210,177,148, +231,210,249,255,244,216,191,179,176,167,144, 56,170,176,212,229,238,119,118, 24,160, 46,119,191,147,195, 0,150, 65, 65,132, 3, +231, 96, 67, 9,160, 0,172,148,201,100,107,227,227,227,245,124, 62, 31, 90,173, 22, 6,131, 1, 36, 73,194,215,215, 23,229,229, +229,112, 52,155,226,209,163, 71, 83, 80, 51,239,159,218,189,123, 55, 76,138,128,121,106,224,209,163, 71,255, 17,157,195,155,111, +190, 73, 41,149, 74, 28, 56,112,192,209,250, 44,182, 83,222,212,132,235,145, 18, 38,222,184, 79, 62,249,228, 33,227,194, 26,159, +126,250, 41,197, 52,200, 83, 42,245,179, 43, 79, 42,245, 99, 36, 76, 36, 18,209,157, 36, 69, 81, 20, 84, 42, 21, 10, 11, 11,157, + 30,243,183,196,176,175,171,106,237, 55,132,252,141, 70, 35, 1, 0, 78, 88,252,214, 32,247,253,190,191,189,101, 38, 64, 87,161, + 62,133,204, 66, 1, 96,100,253, 75,199,135, 20,254,146,137,166,178,221,183,107, 69,249, 15, 88, 21, 78, 29,159,246, 2,110, 61, + 16,161, 62,175, 19, 11, 7, 61, 0,166, 23, 71, 56,114,252, 9, 91,160, 41, 79,217,253, 16, 14, 88,204,118, 20,145,193, 46,187, +175, 9, 19, 38, 72,156, 72,239, 91,175,133,102,195, 2,173,207, 58,101, 20, 52, 38,149, 74, 13, 0,136,113,227,198,137,115,115, +115,229,106,181, 26, 70,163, 17,157, 58,117,146,244,236,217,211,233,247,189,123,247,110,203, 41,103, 78,121,141, 30,117, 12,128, +189,125, 38,250,162, 41, 58,188, 54,225,156, 60,233,176,219,223, 52,215,159,154,112,253, 97, 5,142,162, 40,138,206, 17, 96,161, +144,153, 3,230,156,109, 27, 0,176,107,215, 46,194, 85,109,141,233, 53, 0, 80, 86, 86,134, 54,109,218, 80,149,149,149,104,213, +170, 21, 50, 50, 50, 92,210,215,113,222, 44, 7, 65, 16, 24,253,122, 12,237,134,193,210, 37,211,204,223, 29,205,152,233, 42, 72, +165, 82,114,237,137,181, 46,149, 57,105,210, 36,147,215, 69,230, 9,192, 96,218, 40,169, 84, 74, 90, 92,227,208, 3,203,118,223, +110,106,201, 61,180,171, 63, 61, 61,157,144, 30,123,139, 98,201,255, 17, 40, 0,207, 16, 26,220, 72,159,214,252,227,174,190,175, + 71,224,133,121,164,229,102, 26,227, 55,255,199,245,235,215,159,240, 27, 33,137,167, 91, 94, 77, 89, 57,154, 81,174, 78, 44,172, +181,142, 5,101,235,156,201,242, 78,121, 30, 58,146,251,247,239,155,223, 71,118,118,182,203,222,137, 76,182,150,146, 74,167, 17, +191,255, 38, 99,244, 3,103,151,119,117, 6,166,105,125, 46,239, 19,234, 83,174, 29,236, 55, 60, 80, 19, 83,164,183, 48, 66,205, +227,252,172,219, 31, 76,235,212,195, 21,243,113, 86, 52, 22, 44, 88,176, 96,193,130,197,211, 1, 14, 91, 4, 44, 88,176, 96,193, +130, 5,171, 0,176, 96,193,130, 5, 11, 22, 44, 88, 5,128, 5, 11, 22, 44, 88,176, 96,193, 42, 0, 44, 88,176, 96,193,130, 5, +139,231, 2,181,102, 1,208, 57,175,157,129,173, 96, 66, 86, 30, 43,143,149,247,248,228,197,198,198,214,214,238, 57, 28,115,118, + 57,203,169,102,116, 54, 69,203,169,103,182,210, 7,123,122,122, 66, 40, 20,154,127,207,225,112,192,229,114, 31,146, 71, 47,204, + 68,146, 53,179,188,234, 90, 44,135,125,191,117, 67, 38, 91, 39,230,242, 4,160, 72, 3,166, 78,125, 63,197, 25,121,107,215,174, +149,100,100,100,240,194,194,194,146,173,179,238, 57, 41, 79,156,145,145,129, 53,107,214,164,176,237,237,217,147,231,176, 2,240, + 79, 68, 96,224,251,181, 10,174,164,100, 3,241, 84,201,123, 63,144, 2,128,146, 13, 37,132,229,247, 6,136,108, 96,114,207, 71, + 46,239, 31,139,245, 43,150,137,139,175,156,193, 0,191, 98,121, 51, 67, 30, 50,169, 54, 56,167,244,151,120,135,190,140,153,115, +230,165,216,251,253,169, 83,167,208,175, 95, 63, 51,241,211,132, 77, 16,196, 67,132, 77,146,164,121,187,123,247,174, 77,121,231, +207,159, 71,120,120, 56, 68, 34, 17,120, 60, 30,184, 92,110, 45,153, 52,233, 27,141, 70,243,166,213,106,145,158,158,142,118,237, +218, 61,119,239, 71, 38,147, 17, 82,169,148, 90,187,118,173,248,230,205,155,184,117,235,150,220,215,215, 23, 91,183,110,109, 80, +253, 95,183,110,189, 88, 32,244,135,175,223, 11,114,101,117,129,100,221,186,159,197,171, 87, 59,150,251, 97,205,154, 53,226,132, +132,132,227,153,153,153, 56,112,224, 0, 66, 67, 67, 49,119,238, 92,174,229,220,123, 39,228,201,179,111,103,161, 93, 72, 91,240, + 5, 2,204,154, 53,251,213,152,152, 24, 57,219, 82,159, 83, 15,192,179,132, 33, 67,134,216,213,120,142, 30, 61,106,183, 97,210, + 4,109, 77,220,206,194,213,242, 30, 1, 8, 7, 73,219,110,106, 89, 23,203, 99,242,123,235,255,127,182,137,101,237, 90,241,181, + 83, 71,144,187,227,123,185, 74,165,133,254,101, 14, 68,205, 9,180,207,189,132,151,188, 40,121,121,241, 95,104,186,246, 63,146, +113,211,190,172, 87, 9,184,118,237, 26,184, 92, 46,250,247,239, 15, 30,143,103,222,104,133,128,182,250, 13, 6, 3,140, 70, 35, +244,122, 61,238,222,189,139,227,199,143,219,148,167, 82,169,112,225,194, 5,244,238,221, 27,124, 62, 31,110,110,110,181,100,146, + 36, 9,131,193, 0,131,193, 0,189, 94, 15,181, 90,141, 11, 23, 46,160,186,186,250,105, 32,107,142,169,110,112, 0, 24, 26,146, +135, 94, 38,147, 17,177,177,177,100,108,108, 44, 2, 2, 2,240,239,127,255, 27,227,199,143, 71, 85, 85, 21, 2, 2, 2,156,202, + 64, 26, 16, 16, 96,190,159, 5, 11, 62,195,150,109,233, 16,137, 26,129,203,229,203,171,171,242, 28,150,153,150,150,134,234,234, +106,244,238,221,251,238,224,193,131,155,148,150,150,226,200,145, 35,198,169, 83,167, 98,253,250,245,245,182, 17,109, 78,214, 67, +101,115,249,198, 13,164,120,185, 99, 78,220,151,121,221,123,116,105,113, 47,191, 8, 71, 18, 83,142,111,223,190, 99,112, 84,212, + 91,199, 88,234,124,250, 65,167,254,181,242, 20, 48, 82, 0,172, 83,183,218,219,127,236,228,255,193, 7, 31,212,123, 77,121,121, + 57, 0, 80, 76,148, 0,154,172, 27,106,173, 63, 10,121,150,150,191, 11,172,127, 71, 73,155, 41, 89,187, 90,158,229,181,150,159, + 0,128,178,178,154,204,136,254,254,201,207, 69, 67,205,249, 51, 25,237,242,228,242, 60, 21,137,177,237,184,120, 33,200, 0,210, +159,130,155, 63, 23, 85,165,124,136,170,212,232,152,177, 82,190, 37, 46, 86,242,206,236, 69,117, 42, 1, 4, 65,224,250,245,235, +224,243,249,120,245,213, 87,205,164,237,230,230, 6, 14,135, 3,138,162,160,215,235, 97, 48, 24,160,213,106,145,151,151, 7,185, + 92, 94,231,146,202, 28, 14, 7,122,189, 30, 25, 25, 25,232,223,191, 63, 68, 34, 17, 4, 2,129, 89, 30,173, 0,104,181, 90, 84, + 87, 87,227,242,229,203,208,104, 52,230, 97, 2, 38,136,138,138, 18,115,185, 92,121, 85, 85, 21,248,124, 62,138,138,138, 62, 28, + 59,118,108,149, 80, 40,220,226, 12,105, 71, 69, 69, 77,224,114,185, 59, 19, 19, 19,105,121,153, 99,199,142,189, 41,147,201,198, + 75,165, 82,157, 51,150,112,108,108,172,124,209,162, 69, 69, 48,173, 56, 19, 27, 27,139,107,215,174,161, 81,163, 70, 8, 11, 11, +195,230,205,155, 29, 38,255, 95, 38, 79,198,136,238,221, 1, 0,141,103,206,132,200, 61, 24,213,149,185,168, 84,220,150,196,196, + 76, 73,169, 43,159,123, 93,120,241,197, 23, 81, 84, 84,132, 83,167, 78,181,226,112, 56,184,124,249, 50,252,253,253,145,154,154, +138,119,223,125,151,202,200,200,168,247,247,165,223,206,169,181,239,169,211,163,169, 65,131, 89,159, 44,108, 17,183,244,191,248, +126,233,106, 52,227, 24,177,122,233,178,228,119,223,125, 23,246,228,177,120,250,200,159, 62,206,116, 45,128,135,242,127,219,219, +127,156,112,229, 74,125,207, 2, 44,149,128,199,228, 9,112,212, 82, 39,236, 88,231,206,200,179,245,249, 92, 37,174,250,113,201, + 55,226,208,140, 95,228, 69, 92, 35,218,249, 0,173, 90, 82,224,190,200, 7,175,109, 91,240,181, 26,104, 79,231, 65,171,224,129, + 75,186, 65,147,188, 69,190,126,213, 82,201,212, 25,182,135, 3,104,247,124, 86, 86, 22,252,252,252, 32,145, 72, 32, 20, 10,193, +231,243,193,227,241,204, 86,191, 70,163, 65, 97, 97, 33, 78,156, 56, 1, 14,135, 3, 14,135,131,250,228, 25,141, 70, 92,189,122, + 21,253,250,245,131,183,183, 55,132, 66, 33,184, 92, 46, 12, 6, 3,116, 58, 29, 42, 43, 43,241,215, 95,127, 65,171,213,130,199, +227,153, 99, 1,236,161,127,255,254,226, 27, 55,110,200,239,220,185,131,202,202, 74,240,249,124, 52,110,220,120,229,201,147, 39, +209,167, 79, 31,158, 76, 38,219,232,136, 18,208,191,127,255, 49, 55,110,220,216,105, 37, 47,244,228,201,147,161,125,250,244,217, +110, 82, 2, 24,201, 91,179,102,141, 88,167,211,225,254,253,251,180,203,219, 92, 72,139, 22, 45, 42,136,141,141,109, 54,126,252, +248, 87, 63,254,248, 99,135,250,191,245, 63,111, 20,127, 54,127, 94,173, 99,247, 87,172, 64,227, 55,154,227,251,239,127,148, 76, +158,252,182, 83,253,233,169, 83,167,228,127,254,249, 39, 62,251,236,179, 74, 46,151,235, 45, 20, 10,209,167, 79, 31,200,229,114, + 36, 38, 38,162, 89,179,102, 14,180, 60, 2, 91,179,238, 97,207,173, 2,236,251,125, 51,184, 92, 2,115,102,190, 67,118,107, 28, +200, 89, 55,107, 33,214, 59, 42,143,197, 19, 33,127,107, 37,210,150, 82,224,244, 44,128, 39,189,188,109,126,185,231,118, 0, 0, + 32, 0, 73, 68, 65, 84,219,182,109, 37,246,182,199,109,173, 63, 10,121, 46,180,250,153,146,182, 51,100, 13, 75,235,156,182,208, + 77,114, 40, 39,229,213,217, 81,251,251, 39, 59,101,253,175, 90,181, 74, 60,101,202, 20,170,174, 99,214,231,234,130,229,245,171, + 86,173, 18, 91,159,179, 62, 86,111,121, 93, 61, 47, 47, 44,168, 68, 35, 47, 30,218,122, 81,224, 5,146,224,189,242, 26, 60,186, +109,129,168,199, 15, 16,248,136,192,175, 86, 67,165, 50,162, 37, 87,133,212,248,186, 83,201,114, 56, 28,240,120, 60,184,185,185, +225,214,173, 91,184,124,249, 50,188,189,189, 17, 16, 16,128,128,128, 0, 4, 6, 6,194,215,215, 23, 10,133, 2,169,169,169,224, +114,185,230,177,125, 91,160,207,243,249,124, 24,141, 70,100,102,102,194,221,221, 29,129,129,129,104,212,168, 17,130,130,130,224, +233,233,137,204,204, 76,232,245,122,243, 16, 65, 93, 10,133,181,229,255,224,193, 3,249,237,219,183,209,166, 77, 27, 12, 27, 54, + 12,189,122,245,130, 74,165,194,241,227,199,145,145,145,177, 65,163,209,188,237,128,229, 47,121, 80, 84,252,107,246, 61, 5,188, +218,245, 70,232,176,247,209,172,215,104,148,107, 57, 56,154,124, 12, 25, 25, 25, 99, 53, 26,205, 84,166,228, 95, 89, 89,137, 75, +151, 46,201, 79,157, 58,133, 23, 95,124, 17,177,177,177,129, 0, 72,147, 7,160, 25, 0, 8,133, 66,198,100,189,254,231,141,226, +173,241,251,197,254, 1, 93,228,241, 59, 46, 97,242, 47,191, 32,241,194, 5, 36, 94,184,128,198, 51,103, 2, 0,244,122,229, 9, +103,218,220,235,175,191, 78,237,219,183, 15,227,198,141,187,235,229,229,197,113,119,119, 79, 79, 75, 75,195,169, 83,167, 80, 82, + 82,130,208,208, 80,199,148,210, 11,183,176,244,143, 43, 88,191,116,193, 37, 30, 87, 13,142,177, 10,223, 45,255,133,179, 51, 53, + 29,133, 28, 30, 94,120,225, 5,150,101,159, 19,240,156, 37,248, 39,181,120,197, 35,179,176,255,217,138,192, 35, 25, 87,111,160, +171,158,176,115,220, 33,165, 98,233,210,165,226, 99,199,142,201,179,178,178,234, 60,150,150,150,198, 72, 22,125, 93, 90, 90, 26, +202,202,202,228, 75,151, 46,149,204,155, 87, 99,149,219, 58, 86, 31,188, 53,165, 72,204,213,160, 89, 57, 23,221,189, 9, 4, 21, + 3,237,120, 62,224, 16, 1,160, 52, 15,160,124, 64,224,106, 46,137,251, 74, 13,120, 28, 14,186,250, 11,228,117, 61,183,165, 2, + 32, 16, 8,112,251,246,109, 52,107,214, 12, 67,134, 12, 1,151,203, 5, 73,146, 40, 45, 45,197,169, 83,167,224,230,230, 6, 62, +159, 15,157, 78, 87,167, 2, 64,123, 7,104, 37,128,162, 40,100,103,103,163, 93,187,118,240,241,241, 65,117,117, 53, 46, 92,184, + 0,163,209, 8,129, 64, 0,173, 86, 11,173, 86, 91,103,223, 65, 7,209, 1, 64,113,113,177, 60, 63, 63, 31,221,186,117,131, 88, + 44, 70,243,230,205, 37, 74,165, 18, 65, 65, 65,242,228,228,100,156, 61,123, 22,190,190,190,189,101, 50,217, 54,169, 84,106,119, +125,247,226,226,226,227, 15,202, 20,240, 15,237,141,182,253,223,132,111,243, 80,104,149, 21,200,253,243, 32,110, 29,219, 76,203, + 99,244,126, 77,177, 15,242,194,194, 66, 4, 7, 7, 67, 40, 20, 74, 46, 93,186, 36,143,141,141,229,152, 60, 0, 0,112, 35, 54, + 54,150,100, 82, 7,127,222,176, 89,236,235,247,130,220,215,255, 5,112, 56,110,208,235,149,216,176, 81,142,201,239, 73,104,143, + 2,166, 78,157,138,160,160, 32,210,209,182,247,206, 59,239, 80,241,241,241,232,223,191, 63,122,244,232,209, 10,128,225,216,177, + 99,225, 57, 57, 57, 16,137, 68, 16,137, 68,136,136,136,120,117,215,174, 93,199,153,200,219,118, 51, 15, 63,252,117, 3, 63, 47, +158, 95,214,252,133, 86, 47, 42,171,203,241,251,161,191,112,233,242, 77,248, 82, 36,248,247, 31, 32,226,195,232,193, 59,119,238, +250,103,185, 96,159, 33,216, 26, 62,170,203, 43, 80,151,170, 78,140, 31, 63,222,210,130, 38, 34, 35, 35,235,219,127,102, 81, 82, +178,129,176,220,158, 54,121,192, 35,113,255,215,103,181, 55,232,158,157,181,206, 29,241, 0, 56,138,168,168, 40,241,254,253,251, +107,145,191,173, 99,206, 32, 43, 43, 11,251,247,239,151, 71, 69, 69,137,235, 59, 86, 39,113,149,228,225,204, 61, 53, 84, 70, 18, + 39,243, 72,220, 55,240, 96,212,166,163,252,218, 7,216, 60, 51, 6, 7,142, 40,112,185,148,194,197, 98, 3,174,150, 26, 80, 90, +120,191, 94,175,156,165, 18, 32, 20, 10,113,247,238, 93,220,184,113, 3, 64, 77, 92,204, 31,127,252, 81,107, 44,191,190,241,122, +130, 32,204, 94, 0, 90, 30, 69, 81,200,203,203, 67,203,150, 45, 81, 88, 88, 8,146, 36, 33, 20, 10,205,178,234, 27, 82,176, 68, +110,110, 46, 52, 26, 13,194,195,195,209,188,121,115, 9,151,203,133,183,183, 55, 94,126,249,101,137,167,167, 39,114,115,115, 81, + 89, 89,121,153,105, 61,200,205,205, 5,201,225,163, 89,216, 96,248, 54, 15, 5,135,235, 6,145,119, 16, 90,190, 28, 1,190,135, + 31, 45, 47,199,158,156,181,107,215,138, 43, 42, 42,228, 5, 5, 5,104,209,162, 5, 36, 18,137,100,203,150, 45, 41,165,165,165, + 4, 0,244,238,221,219, 96,186, 52,212,199,199, 7, 50,153,204,110,192,131, 80, 24,128,128,160,110, 48, 26,180, 40,186,151,134, +251, 5,167, 6,149, 20, 95, 88, 96,146, 7, 0,120,112,255, 62, 76,242,220,152,214, 61,169, 84, 58, 62, 62, 62, 30,209,209,209, +152, 56,113, 34, 0,144, 71,142, 28,225,237,223,191, 31,147, 39, 79, 30,122,254,252,121,226,244,233,211, 68,108,108, 44,163,200, +253,204, 74, 21,230,159,184,136,111,231,198,160,255,200,193,254, 70,202,128, 93,191,158,192, 79, 43,183,224,208,236,119,177,190, + 91, 75,180,244,225, 97,193,130, 88, 54, 8,240, 25,193,197,139, 23,235, 36,255,122, 61, 0,214, 99,251,246,246,159, 71, 60,130, + 41,120, 78,225,235,151,190,150, 76,155, 54,237, 89, 40,239, 90, 67, 10,143, 56, 72,143,209,123,136,136,136, 16,223,186,117, 75, +174,211,233,234, 61,214, 16,148,151,151, 67,169, 84,202, 35, 34, 34, 36,121,121,121, 15, 29, 59,120,240, 96,157,239, 46,163, 76, + 13,133,142, 68, 70,177, 1,133, 21, 6, 4,255,193,195,139,187,178,112, 55,231, 42,110,254,169,131,129,199,133,142, 4, 52, 58, + 10,229, 20,137,160,122,150,181,167,167,251,209, 99,247,116,196,254,131, 7, 15,208,170, 85, 43,228,228,228,152, 93,254, 60, 30, +207,124,189,163,195,121,150, 57, 4,232,207, 71, 52, 36, 88, 1,215,198,124,216, 37,107,146, 36,161, 84, 42,107, 58, 71, 30, 79, +242,193, 7, 31,212,122,119, 85, 85, 85,188,125,251,246, 97,244,232,209,156,249,243,231, 63, 88,178,100,137,193, 94, 93, 36,136, + 26,133, 72,173,122,128,234,170, 60,201,148, 41,239,166,200,100,178, 84, 0,223, 86, 85, 85, 97,223,190,125,102,197,177, 93,187, +118, 58, 38,117,123,241,226,197,163,191,255,254,251,132,136,136, 8,244,235,215, 15, 0,200,211,167, 79,115,126,251,237, 55,136, +197,226,145,171, 86,173, 58,234, 72,193,220, 83,105,241, 78,226, 31,152, 53, 33, 2,227,223, 25, 7,149,166, 18,123,247,165, 96, +249,234,109,248,223,208,151,208,182, 40,159,101,211,231, 64, 25, 96,234, 1,112, 53, 40,171,134,108,111,159,133, 5, 30, 53,249, +187,208,106,175,203,163,224,236,248,127,125,245,130, 81,125, 57,120,240, 96, 74,251,246,237, 37,126,126,126,245, 30,107, 8,252, +252,252,208,190,125,251, 90, 68,111,235,152, 45,168,141,222,208, 19,192,185, 18, 45,138,140, 70, 28,203,214, 96, 87,130, 6,199, +243,131,144,197,247, 65,190, 66,143,188, 42, 18, 74, 3,160, 50, 80, 16, 4, 52,182, 75,204,244,252,126,163,209, 8,131,193,128, +128,128, 0,120,122,122,162, 85,171, 86,208,235,245,230,227,182, 18, 2, 89,203,163,231,247, 27, 12, 6,168,213,106, 80, 20,133, + 22, 45, 90,160,160,160, 0, 77,154, 52, 1,143,199,131, 86,171,133, 78,167, 51,255, 47,147,225,193,150, 45, 91, 66, 40, 20, 34, + 61, 61, 29,249,249,249,114,163,209,136,202,202, 74,226,207, 63,255,148, 87, 87, 87,163,101,203,150,240,246,246,126,141,105, 31, +213,178,101, 75,112, 72, 29, 10, 46, 36,163, 34, 63, 19,164, 81, 15,117,101, 49,114,255, 60, 8,157,178,156,150,215,154,137,114, + 67, 35, 32, 32, 64,190,102,205, 26,179, 23,167,180,180,148,184,122,245, 42, 76,164, 77, 2, 8,182,149,240,200, 26, 6,131, 26, + 6,125, 53, 68, 30,141, 33, 20,249, 67, 38, 91, 39,150, 74,165,134, 69,139, 22, 5, 88,200,195,250,245,235,161, 80, 40,232, 41, +140, 15, 97,209,162, 69, 84,223,190,125,169, 30, 61,122, 80, 95,126,249,229,239,163, 71,143,198,200,145, 35, 1, 0,231,207,159, +175,220,191,127, 63,198,143, 31, 63,250,216,177, 99, 7,153,148,217,162, 69,139,168,126,253,250, 81,111,125,240, 33, 94,221,125, + 2,243,254, 53, 22, 31,125, 58, 29, 26, 93, 53,238,220,206,131, 76,182, 11,191,141,234, 3,113,139, 70, 78,183,141,225,195,135, +179,253,250, 19, 68, 88, 88, 88, 45,210,183, 14, 4,124,172,169,128, 35, 35, 35,197,142,236, 63, 54, 75,191,142, 57,251,214,214, + 62, 83,235,191, 46,121,239, 7, 6, 82,239, 7,254,237,206,183,222,183,231,137,112,149,188, 58, 44,105,103,136,250,145,193, 74, +137,112,218, 3, 0, 0,219,183,111, 79, 25, 53,106,148,196, 50, 57,141,173, 99,206,160, 93,187,118, 24, 53,106,148,100,251,246, +237, 41,245, 29,171,243,247,237,219,161,189, 7, 23, 94, 4,160,167, 40, 92, 47,215, 33, 62, 75,139,237,103, 10,241,215,237, 50, + 20,170,129, 82,141, 17,183,171, 41,220,211, 82,168,214,233, 37,245,145, 23, 61, 53, 79,167,211, 65,173, 86,163, 73,147, 38,232, +210,165,139, 73,209,243, 71,175, 94,189,204,132, 77,147,118, 93,132, 77, 19,186, 94,175,135, 78,167, 3, 65, 16, 8, 9, 9, 65, + 69, 69, 5,242,242,242, 80, 86, 86,134,214,173, 91,131,195,225, 64,167,211, 65,171,213,154,127, 99, 15, 65, 65, 65,146,230,205, +155,227,234,213,171, 56,124,248, 48, 14, 28, 56, 32, 63,112,224,192,241,147, 39, 79,130,203,229,226,149, 87, 94, 65,219,182,109, +213, 48, 5,222, 49,144, 55, 58,216,223, 7,165,217, 23,113,243,232, 70, 92, 61,184, 6,215, 15,202,112,247,236,111, 16,112, 72, + 90, 94,129, 61, 57, 51,102,204, 72, 9, 14, 14,150,120,123,123, 35, 35, 35, 3,249,249,249,242,184,184, 56,177,165, 34, 96,242, + 4,112,226,227,227,209,185,115,103,187,247,166,211, 42,160,168,200,130,155,155, 7,124,253, 59,200, 61, 60,155,225,151, 95,182, +138, 9,130,211,155,190,198,171, 34, 25,242,255,125,132, 33, 29,170,235,172,219, 7, 15, 30,132, 72, 36, 66,231,206,157,209,186, +117,107,122,248,192, 80, 94, 94, 94,189,123,247,110,223,176,176,176,209, 59,119,238,220,207,180,238, 38, 38, 30,132,183,183, 39, + 6, 12,124, 89, 21,214,227, 69,140,249, 96, 50, 84,132, 1,197, 69,101,152, 54,243, 43, 44,233,217, 14, 61, 26, 57,175, 36, 15, + 31, 62,156,250,238,187,239, 88, 37,224, 41, 81, 4,108,225,169, 89, 11,224, 73,207, 42,112,134,128, 29,197,134,146, 26, 5,194, +146,168,233, 99, 79,131,188,167,213,163, 96,229, 9,160, 28,241, 0,208,152, 55,111, 94,202,160, 65,131, 36,189,122,245,170,243, +152,229,185,250, 96,121,253,160, 65,131,106, 5,251,217, 58, 86,175,117, 40,240,144,116,109, 18,136,190, 1, 2,188,228,199, 71, + 83, 33, 7, 2,138,130, 80,107, 64, 75, 79, 30,202, 41, 10, 87,170, 13,200, 84, 26,208,172, 81, 0, 90,191, 52,176, 78, 89,180, +213, 79, 79,245,107,217,178, 37,186,117,235,134,242,242,114, 84, 84, 84,160,162,162, 2, 94, 94, 94,232,221,187, 55,116, 58,157, + 57, 39, 64, 93,132, 77, 43, 19,122,189, 30, 4, 65, 32, 52, 52, 20,106,181, 26,197,197,197, 40, 42, 42, 66,113,113, 49,148, 74, + 37, 66, 67, 67,193,227,241,204,242,234,202, 43, 96,173,148, 5, 7, 7, 75, 66, 66, 66,112,231,206, 29, 36, 37, 37, 33, 45, 45, + 13,238,238,238,120,245,213, 87,209,173, 91,183,131, 66,161,112, 14,211,105,123,219,183,111,223, 31,220, 40,232,237,144, 38,190, +168,190,253, 39, 50,147, 54,160, 32,237,119,248, 9,140, 24, 60,232, 85,116,235,214,109,210,199, 31,127,188,143,137, 44,111,111, +111,244,232,209, 3, 20, 69,225,204,153, 51, 72, 79, 79,151, 23, 20, 20,200,191,253,246, 91,113,108,108,172,132,206,156,216,179, +103, 79,164,166,166,218,149, 55,117,234,228, 20, 69,121,150,164,172,248, 50, 4, 66,127, 52,110,250,138, 60,168,113, 47,185,151, +119,235,131,223, 47,253,105, 20, 45,111,251,199,238,216,113, 90,139,186,148,158,204,204, 76, 4, 6, 6,162, 95,191,126,228, 75, + 47,189, 4,149, 74, 5,165, 82,137,149, 43, 87,122,118,232,208,225, 13,185, 92,190,223,145, 54,113,243,102, 38, 90,181,108,142, +183,222, 26,237,254,249,191,103,161,180, 74,129,146,210, 18,196,124,244, 21,190, 26, 51, 8,131, 90, 6, 55,136,252,151, 47, 95, +142, 46, 93,186, 96,197,138, 21,172, 18,240, 24, 97, 57,238,111, 15,143, 45, 19,160, 43,103, 21,152,146,251,184, 36, 19,160, 61, + 88, 39,226,113,133, 18,224, 74,178,118,181, 60, 87,188,106,184, 32, 61,176,149, 2, 65,212,225,177,112, 8, 51,102,204, 72,177, +254,157,229,177,159,127,254,153,145, 76,250, 58, 91,215, 51,149, 65, 99,211,246,157, 41,243,223,153, 0, 67, 90, 34,114, 20,128, + 39,225,134, 86,158, 28, 20, 24, 9,112, 5, 60,164, 22, 25,161, 33,129, 32, 1, 23, 33, 61, 7,224,227,165,235, 83,234, 83, 0, +244,122, 61,184, 92, 46,218,180,105,131, 30, 61,122,160,178,178, 18, 26,141,198, 60, 63, 95,167,211,193,223,223, 31,253,250,245, +195,254,253,251,205, 67, 2,182, 96, 52, 26,205, 89, 4, 59,118,236, 8,147,155, 30, 26,141,198,220,158,105, 79, 66,199,142, 29, + 81, 86, 86,134,234,234,234, 58,219,178, 53,153,159, 60,121, 50, 37, 42, 42,234,213,206,157, 59, 31,183, 72, 4, 84,209,191,127, +255,227, 66,161, 48, 90, 42,149,106, 28, 41,203,147, 39, 79,198, 71, 69, 69, 85,118,238,220,121,159,133,188,146,254,253,251,175, +252,248,227,143, 25,103,235,153, 62,125,122,202,154, 53,107, 36,195,134, 13,195,157, 59,119,228, 55,110,220, 64,110,110, 46,188, +188,188,228,190,190,190, 24, 50,100, 8,126,254,249,103,244,236,217,147,241,189,189,255,254, 59, 41, 63,255,188, 73,162,209,148, +193,215, 47, 84,238,233,213, 2, 94,222, 45,161,172, 42,216,191,120,201, 6, 68,189, 53, 24,219, 63,118, 55,151,147, 45,139,109, +196,136, 17, 72, 76, 76, 68,126,126, 62,167,172,172, 12, 26,141, 6,169,169,169, 60,147,210, 89,121,250,244,105,135,218, 67, 68, +196, 8,236,221,187, 31,149, 21,165,200, 47,188,135,143,103,252, 75,247,201,103,139,248, 99, 94,237,131,126,218, 74,192,205, 57, +122, 24, 62,124, 56,245,197, 23, 95,152,211, 65,135,132,132,224,187,239,190, 3, 0,234,208,161, 67,108,218,240, 39,164, 20, 60, + 73, 5,128, 24, 63,126,188,165, 11,141,176,114,247, 19,142,186,255, 93, 65,238,102,146, 47,217, 0,123,217,246, 28, 9,254, 43, + 41,217, 0, 75, 87,188, 37, 49, 91,187,236,153,144,118,201,134, 18,151,202,123, 6,240,143,234, 36, 90,247,145, 72, 46,105, 13, +242,226,227,199,224,102, 80,227, 82, 21,133,228, 42, 3,248, 4,129, 0,138,130,164,137, 47,252, 26, 7, 73,154,191, 44, 6, 54, +237,180,235, 1,104,221,186, 53,122,245,234, 5,181, 90, 13,189, 94, 15, 62,159,111, 38,108,218, 74, 15, 10, 10, 66,223,190,125, +145,148,148, 84,175, 7,128,199,227,161, 91,183,110, 32, 8, 2, 42,149,202,236, 93,160,149,118, 58,187, 32, 73,146,232,218,181, + 43,254,248,227, 15, 56, 18, 92,185,125,251,118, 57, 0, 66, 38,147, 17, 0, 60, 81,147,109, 47, 87, 42,149,234,157, 41,203,237, +219,183,239, 55,201,243, 4,224, 15,160, 76, 42,149, 58,156,155,120,250,244,233, 41, 0,176,106,213, 42,137,155,155, 27,178,179, +179,225,239,239, 47, 7,128,130,130, 2, 12, 31, 62, 28,203,150, 45,115, 72,230,148, 41,147, 82,100,178,117, 98,157, 78, 33, 17, + 85,230,200,189,125, 67,224,238,217, 20,238,158, 77,113,228,216, 3, 16,131,234,183,184, 55,111,222, 76, 76,157, 58,149, 42, 43, + 43,195,136, 17, 35,116, 1, 1, 1,124,146, 36,145,155,155,235,176, 71, 12, 0, 54,109,218, 76, 72,165, 49,148,247,181,116,204, +152,241, 62,154,135,182,231,127, 55,235,125,114,211,234,205,156,149, 92,141, 83,117,121,248,240,225,212,252,249,243,225,235,235, +139,194,194, 66,136, 68, 34,144, 36, 9, 15, 15, 15,124,243,205, 55,172, 18,240, 24, 16, 22, 22, 86,167, 23,128,105, 42, 96,151, +227, 41,159, 85, 64,148,108, 40,177,121,194, 73,235,159,216, 80,242,176, 60,107, 75,157,118,221, 51, 32,109, 87,203, 99,241, 20, +193, 68, 54,196,155, 17,195,197, 62, 6,173,156,123, 55, 27,237,244,247,224, 21, 16,140, 62, 93, 59, 32,160, 89,160,228,211, 53, +219, 82,118,164, 77,183,235, 69,107,211,166, 13,250,245,235,103, 30,143,231,114,185,208,106,181,230,212,189,150,195, 4, 45, 90, +180, 64,223,190,125,145,146, 98,187,233,137, 68, 34,132,133,133,129,199,227, 65,167,211,153,127,103, 57,117,208,114, 33, 32, 14, +135,131,238,221,187, 35, 61, 61,221,225, 50, 48,121, 7,170, 76, 91,131, 97, 34,253, 6, 47, 74, 96,242, 16,153,219,225,154, 53, +107,196, 42,149, 10, 90,173, 22, 29, 58,116, 64, 92, 92,156,220,177,251,138, 73, 1, 0,153,108,157, 68,173, 46,134, 64,224, 7, + 55,190,151,156,195,225, 97,107,252, 65,201,219,209, 17,245,202, 91,191,126, 61, 33,147,201,136, 31,126,248,129, 84,171,213, 0, +128,208,208, 80,135,210, 47, 91, 66, 38, 91, 71,252,252,243,250,225,147,191,248, 33,177, 70, 30,197, 9, 13,125, 1,161,111,188, +241,246,140, 25, 51,226,157,145,185,100,201, 18,182, 81, 63, 37, 74, 64,125,228,255, 88, 21,128,103, 21,174,156,246,103, 77,204, + 13, 37,106, 23,202,115,181,194,192, 42, 32, 78, 96,231,193, 67, 41,181,202,174, 50, 23, 39,239,228, 50,254,125,100,100, 36,252, +252,252,204, 17,254, 36, 73,154, 93,248,180, 7,128, 14,250,163, 87, 4, 12, 9, 9, 1, 65, 16,216,177, 99,199, 67,242,150, 47, + 95,142,132,132, 4,243,181, 70,163,209,238,114,192,124, 62, 31, 61,123,246, 4,147,232,248,103, 88, 89,107,112, 93,167, 21,129, + 26, 82,223,128,154,112, 44, 82,206, 68,158, 73, 89, 34, 0, 96,205,154, 53,212,244,233,211,137, 99,199,156,159,154, 63,101,202, +212, 67, 38,175, 9,135, 36, 73, 35,135,195, 17, 57, 58,252, 66,131,181,238,159, 46, 37,192,110, 71,237,236, 58,194, 44, 88,176, + 96,193,130, 5,139,103, 23, 28,182, 8, 88,176, 96,193,130, 5, 11, 86, 1, 96,193,130, 5, 11, 22, 44, 88,176, 10, 0, 11, 22, + 44, 88,176, 96,193,130, 85, 0, 88,176, 96,193,130, 5, 11, 22,207, 5,106,205, 2,184,120,241,162,211, 17,156,182,130, 9, 89, +121,172, 60, 86,222,115, 41,143,122,253, 13, 41,126,255, 77, 6,153, 76,198,177,149,173,143, 45, 63, 86, 94,203,150, 45,205,215, +228,230,230, 18, 79,155,188,231,253,125, 56,172, 0,208,141,187,158,235,157,185,193,103, 89,158, 51, 50,159,246,231,173, 5,153, + 76,198, 7,224, 13,192,221, 84, 31, 72, 0, 37,206, 36, 79,121,196,160, 92,245,204,117,148,233, 19,153,190,180,116,233, 82,241, +153, 51,103,228, 39, 78,156, 0, 0, 12, 28, 56, 16,125,250,244, 97,156, 74,248, 73,188,135,215,223,144, 98,196,240, 30, 6, 64, +202,147, 74,165, 36,216,105,159, 44,172,208,178,101, 75,106,212,168, 16,243,254,254,253,160,236,145,182, 61,121, 11, 22,244, 55, +239,127,251,237,201, 6,201, 99, 81,183, 2, 0,106,215,195, 11, 64, 16, 19,202, 27,242, 63,132, 19,196,251,216,228,217,122,222, + 6, 62,243, 83,253,188, 52,241, 95,189,116,114,227,174,237, 43, 7, 53,110, 22, 18,172, 80,232,225,227,227,134,251, 5,183,201, +206,157,187,149,201,100,178, 94, 82,169,244,142, 35, 50,165,147,186, 81,217,183, 51,113, 59, 71,131,188,123, 20, 90, 52, 33, 16, +210, 90,136,182, 33,161,144,109,202,120, 90, 26,171, 45, 69,130, 94,107,224,177,223,227,229,203,151,229, 97, 97,135,177,118,173, + 10, 41, 41,192,194,133, 71,144,151,151, 39, 31, 53,106, 20,132, 66, 33, 10, 11, 11, 37, 99,198,140,129, 43, 20,130,183,223,126, +155, 82, 40, 20,146, 33, 67,134,224,163,143, 62, 74,113,162,206,112,164, 82, 41, 70, 12,239, 65,198,196,196,240,128,117,248,253, + 55, 64, 38,147, 17, 76,115,246,179,248,231, 64,167,155,143,164,164, 24, 12, 27,182, 14,163, 70, 45,193,254,253, 53,109,207, 89, +226,190,121,115, 14,126,253,117, 12,198,142,221,139, 5, 11,106,148,128,134,200,123,222,193, 38, 2,114,132, 97, 45,200,158, 32, + 0,114,167,223,115,251,172, 43, 87, 44,123,231,192,190, 95, 98,219,181,107,223, 97,236, 27, 3,209,162,153, 55,124,125, 4, 40, +175,208,160,224, 94, 11,206,173,236,242,192, 3,251,126,145,175, 92,177,236,135, 15,103,206, 89, 97, 79,222,199, 31, 78, 20,223, +201, 60, 32, 47, 42,204,192,155, 17, 64,223,112, 32,164, 21,144,149, 67,225,212, 57, 53, 18,229, 25, 24, 61,212,155,106, 19, 58, + 82,242,227,202,109,206, 18,153, 43, 45,127,194,134,236, 39,162, 4,148,149,149,225,163,143, 84, 8, 10, 2, 34, 35,129,197,139, +171,113,225,194, 5, 24, 12, 6, 8,133, 66, 52,106,212, 72,126,224,192, 1, 76,157, 58, 85,178,126,253,122,135,202,110,250,244, +233,226, 43, 87,174, 32, 56, 56, 88,190,123,247,110, 98,235,214,173, 0, 32, 79, 78, 78,198,251,239,191,143, 13, 27, 54, 56,250, +172,124, 0, 72, 60,116,158, 3,172, 35,107, 62, 31,206,241,207,130,181,254, 1, 96,220,184, 61, 72, 74,170,249,140,137,185, 13, +218, 35,224,168, 55,128,150,247,206, 59, 91,240,235,175, 53,159, 99,198,156, 4,237, 17, 96,189, 1,245, 19,191,229,113,107, 37, +128, 13, 2,180,225, 5,120,158,201, 95, 38,147,241,142, 38,237,250, 92, 50,160, 71,135,177, 17,161,232,214,185, 17, 2,252, 68, + 32, 64,192,219, 83,128,208, 16,127, 12, 25,216, 26, 3,251,117,111,117, 52,105,215,231, 50,153,172,177, 61,153,119, 50, 15,200, +251,135, 87, 98,215, 74, 96,114, 36,208,193,228,249,243,112, 7, 58,182, 3,190,156, 13,244,238, 86,137, 59,153, 7,228, 13,121, + 69, 13,245,122,216, 81, 36,158, 72, 7,226,239,239,143, 3, 7, 68, 40, 46, 6, 18, 18,128,242,114, 30,218,181,107,135,145, 35, + 71,210,203,189, 34, 37, 37, 5,233,233,233,242,165, 75,151,138,153,202, 29, 54,108,152,248,234,213,171,114, 62,159, 47, 47, 47, +175,237,201, 82,171,213,216,176, 97, 3, 36, 18,137,163,229, 73, 2,192,239,191,201,144,120,232, 60,231,247,223,100, 13,122,246, + 41, 83,166, 80,244, 86,223, 49,134,245,130,114,226, 88,189, 88,183,118,173,120,221,236,217,226,139, 83,167, 82,121, 35, 70, 80, +103, 39, 77,162, 86,125,244,145,120,221,218,181,226,134, 60,115, 67,235,140, 45, 25, 76,143, 61,106,121,180,235,127,212,168, 16, +196,196, 36,213,250,164, 49,106, 84, 72,173,241,124,123,242, 22, 44,232,143, 5, 11,250, 99,204,152, 95,107,125,210, 88,176,160, + 63, 99,121,255, 36,132,133,133,213,218,108, 41, 7,172, 2,240, 52,176,192, 99,196,213, 75, 39, 23,183,107,215, 46,180, 87,143, + 38,181, 43, 2,135, 0,159,207,133, 72,200,131,155, 27, 7, 33,109,252, 16, 18,210,174,209,213, 75, 39, 15,200,100,178, 58, 61, + 69,210, 73,221, 40, 46, 42, 49,123, 50,160,209, 2,119,242,128,114, 5, 80, 81, 9,108,219, 7,204,252, 2,136, 93, 10,244,233, + 1,112,168, 74, 72, 39,117, 99, 27,170, 5,186,118,237, 42,249,253,247,142,104,212, 8,152, 56,145,135,198,141, 95,194,192,129, + 3, 37, 7, 14, 28, 32, 70,142, 28, 41, 25, 54,108, 24,130,131,131,113,254,252,121,236,220,185, 83, 62,110,220, 56,241, 79, 63, +253, 84, 47, 1,245,239,223, 95,172,213,106,229,110,110,110,245,254,183, 92, 46,199,160, 65,131,152,144, 25, 21, 29, 29, 77, 73, +165, 82,157, 41,102, 4, 22,228, 79, 0, 64,116,116,180,195, 10, 90, 90, 90,154,121,171,239,152,147,205,150,104, 72,243, 94,183, +118,173,184,237,141, 27,242, 49, 23, 47,202, 91,100,102,129, 95, 89,137, 38,153, 55, 32,254,227,172, 60, 40, 35, 67, 46,115, 82, + 9, 72, 75, 75,195,148, 41, 83,168,153, 51,103, 58,173, 68,208, 50,152, 28, 99, 42,207,154,232,153, 28,179, 7,154,244,233, 79, +221,168,118, 13,106, 43, 52,233,211,159, 55,123, 5,177, 29, 72, 61,196,207, 4,207,170, 2, 64,217,216, 92, 38,248, 17,222, 31, +229,226,219,164, 28, 45,139,171,215, 50,134,135,134,248,155, 73,223,214, 50,205, 66, 1, 15, 6, 3,137,208, 16,127, 92,189,150, + 17, 2,192,167, 46,121,217,183, 51, 17,241,106,205,247,195,169,192,251,159, 1,107,183, 1,133, 15,128, 27, 89,192,133,171, 20, +146, 79, 3,199,206, 0,195, 6,214, 92,223, 0,221,140,120,132,175,248,137, 40, 38,243,230,205, 75,169,174,174,137,183,156, 56, +113, 34,206,158, 61, 75,200,100,178, 20,250, 92, 89, 89,153,164, 99, 71, 30,166, 78, 5,186,119, 63, 7,163,241,134, 60, 63, 63, +191, 78, 79,202,244,233,211,197, 4, 65,200,153, 46, 14, 83, 84, 84,100,215, 43, 19, 29, 29,141,248,248,120, 0,160, 82, 83, 83, +117, 22,239,130,160,137, 63, 62, 62, 30,209,209,209, 79,178, 63,112,246,152, 77,104,175, 92, 65,155, 63,255, 52, 45,130,164,131, +129, 36, 65,234,141, 32,245, 6, 4,157, 76, 69, 37,195,245,214,235, 34,220,191,254,250, 75,254,202, 43,175, 60,114, 37,192, 25, +239, 66, 67,201, 95, 55,170,157,205, 45, 41, 38,201,169,123,186,217, 43,200,230,246,235,152, 95, 89,182,111, 32,108, 42, 0,196, +132,242,135, 54,103, 9,135, 1, 33, 58, 42,143,168,103,123, 42,148, 13,106,151,159,205,173, 1,202,203, 67,215,219,249, 15,155, +144,201,100,188,198, 77, 67, 58, 53,109,236, 9,138, 2, 82,207,228,225,240,177,108, 28, 62,150,141,162, 18, 21, 40,138, 66,110, +126, 37,153,114, 58, 23, 89,119,202, 17, 24, 32, 66,211,166,237,124, 81,179, 68,171, 77,220,206,209,160,111, 56,160,213, 3,135, + 78, 0,242,179, 20, 86,108, 6,110,100, 3,131,250, 1, 29, 66, 8,240,184, 53, 75,139,247, 14,171,185,158,225,179, 58,243,157, +169,165,104,203, 61,252,196, 28, 64,166,229, 92,241,226,139, 47, 74,172,207,113,185, 92,121,167, 78, 69, 88,184, 16,248,207,127, + 40, 52,109,154,137,156,156,156, 58,101,105, 52, 26,187,150,191, 37,234,147, 69, 35, 62, 62,158, 38,123,179, 34, 64,111, 22,196, + 79,152,174,123, 18, 78, 59,235,246,207,244, 88,157,104, 95, 82, 42,215,233,245,208,233,245,208, 25, 77, 43, 40,146, 36, 72,163, + 17, 70, 35,137,230,247,238, 53,100, 56, 11, 42,149, 10, 74,165, 82, 62,101,202, 20,106,234,212,169, 13,242, 38,184, 74, 9,112, +149,229, 79, 19,253,184, 61,127,127,167, 63,157,241, 2,208, 68,255,206,150,191,191,211,159,172, 23,192, 62, 44,151, 6,102,180, + 28,112, 93,179, 0, 26, 48, 59,160,174, 40,118,103,162,219,169,122,254,131,114,224,255, 25, 61,183,141,223, 50,106, 92,245, 4, + 21, 58, 35,175,206,223,208,255, 67, 0, 32,119,217,141, 93, 32,107,162,253, 5, 0,128,188,194, 74,168,213, 6, 0, 64,187,182, +126, 8, 10, 16, 33,227,106, 17,231,230,173, 50, 8,133, 92,132,180,241, 69,185, 66, 7, 0,117, 10,206,187, 71, 33,164, 85,205, +255,191, 54, 0, 8,235, 68, 64,192, 7, 12, 6, 96,104,127,192,215, 11,200,206, 5,134, 13, 0, 90, 53,175,185,254, 9,163, 46, + 37,224,185, 24,253, 41, 42, 42,114,168, 29, 86, 85, 49, 95,125, 55, 62, 62,158,136,142,142,166, 76, 74,128,165,119,224,137,151, + 93,219,182,109,169,236,236,108,194,217,243,214,112,187,157, 5,173, 94, 7,130,203,131,145,162, 64, 0, 48, 24, 73,232, 13, 36, + 40,163, 17,196,173,155, 46,185,239, 43, 87,174, 32, 48, 48, 80,254,221,119,223, 73, 62,253,244,211, 20,103,149, 0,235, 97, 20, + 71,137,219, 85,228,159,155,155, 75,180,108,217,146, 26,183,231, 97,133, 96,216,186, 97,224,239,207,194,254,253,183,205,145,251, +246,198,238,105,121,239,108,121, 88, 33, 24,187,119, 44, 94, 72, 43,198,183,223,158,100, 44,239,159, 72,254, 52,158,167, 89, 0, +245,145,168,195, 4,219,192, 41,142,117,203,125,196,179, 9,136, 9,229,142,254, 7,225,227,227,134,242, 10, 13, 2,253,221, 17, +249,255,237,125,121, 92, 84,213,251,255,251, 14, 48, 12, 48, 40,184, 34, 26, 9,238,226, 26, 46,168, 89,140,185,141, 8,184,145, +125,202,210,180,152,248,148, 89,185,160,150,102,125,234,167,144, 38,159, 44,117, 76, 83,250,182,104, 35, 26,226,134, 81, 67,105, +106, 37,110,185,148, 2, 38, 38, 34,137,178, 13, 51,204,114,207,239,143,153,139,151, 97,150,123,103, 6,177, 62,247,253,122,241, + 98,230,204,153,103,206, 61,231,222,243,126,158,231, 60,231, 57,241, 61, 97, 52,209,240,245,245,130,151, 72, 4, 66, 8, 38,142, +237,130,216, 49, 93, 64, 81, 64,249, 29, 45, 90,182,244, 1,128,219,246, 4, 62,208,129, 66,225, 85,130,158, 93,128, 81,195,204, +157,253, 91, 1,208,175, 39, 16,220, 2,144,199, 0, 52, 13,120,123, 1,151,174,152,235, 23, 93, 35, 92,199,150,207,107,119, 31, +252,102,217, 6,184, 97,195,134,152,213,171, 87,163,176,176, 16, 63,252,240,131,250,189,247,222,147, 73,165,210,250, 99,103, 77, + 38,147,236,194,133,118,234,183,222,186, 14,138,162, 80, 86,214, 29,221,187,119,198,165, 75,182,151, 82,104,154,182, 89,254,216, + 99,143, 53,234, 31, 66, 8,190,251,238, 59, 94,215,204, 86, 2,238, 39,242,247,132,146,192,198,237, 78, 29, 33,254,237,119, 16, + 31, 64, 76, 19, 80, 20, 96, 48, 25,161, 39, 38,212, 26,141,208,118,237, 9, 92,248,205,237,182,247,233,211, 7, 20, 69,185, 68, +254, 0, 48,100,200, 16,108,222,188,153,234,215,175, 31,113, 84,230, 12,155, 55,111,166,172, 9,223, 86, 25, 31, 36,229,220, 37, +126, 0, 16,103, 23, 52,248,156, 9, 24,204,206, 46,228, 36,111,242,174,187,196, 15, 0, 61,126,254,171,145,188, 37, 75, 70, 98, +229,202,195, 2,243,115, 32,127, 64, 8, 2,180,229, 30,100,187, 9,221,154,220, 8, 1, 68,211,239, 52, 89,163,201, 87,193,230, +223,224,174,192,120,151, 94, 47,188,117,237,186,217,234,123,127,195, 47, 56,125,174, 12, 6, 3, 13,154, 38, 22,165,133,170,143, + 13,184,118,189, 26,165,215, 11,175, 0,176,107, 86,118,233, 44,193,143,249,230,215,109,162,128, 83,231,129,164,127, 1, 93, 31, + 52,187,253,223,249, 16, 16,251, 0, 34, 17,240, 99,190,185,190, 27, 4,237,233, 24, 10,235,241,190,231,214,195,133, 11, 23, 32, +145,152,251,100,223,190,125,248,252,243,207,213,121,121,102, 46, 88,189,122,117, 76,171, 86,173,212, 23, 47, 26,241,241,199,192, +169, 83,131,224,229,213, 83,214,169, 83, 39,153, 61,121, 1, 1, 1,156,127,219,104, 52,254,237, 31, 92, 54,249, 71, 68, 68, 16, +123,127,124,149,133,194,182,237,100,119,244,117,168,210,235,161,213, 27, 80,103, 52,194, 64, 76,168, 53, 24, 80,173,215,163, 36, + 52, 84,230, 78,187,253,253,253, 17, 16, 16, 32,219,188,121, 51,197,119,123,167, 53,209, 59, 43,227,163, 4, 12, 25, 50,196,105, + 25, 23, 47,128, 61,242,103, 91,255,124,228,217, 35,127,182,245, 47,128, 31,249, 11, 10,192, 61, 64, 83,111, 41, 36, 95, 5,131, +128,179,162, 97,140,140,236, 95, 82,112,229, 14,104,154, 96,241,188,104, 92, 42,184,141,139,151,202, 65, 81,104, 16, 16, 72,211, + 4, 5, 87,238, 32, 50,178,255, 57, 0,118,253,196, 17, 93,186, 99,223,119,128,201, 4,144, 34, 64,125, 12,200,254, 22,144, 63, + 11,200,158, 4,242,142,155,235,153, 76,192,190,239,204,245,155, 17, 4,142,115, 1,220,115,220,190,125, 91,221,171,215, 21,252, +252, 51,112,236,152, 9,157, 58,157,197,169, 83,167,212,113,113,113,100,239,222,189,234,156,156, 28,220,188,121, 19, 15, 61,244, + 16,166, 79,159, 46,203,204,204,204,115,148,196,135, 16, 34,179,231, 5,176, 6,163,120,240, 5,179, 4,192, 94, 10,104, 46,176, + 45,250,162,162, 34,202,222,159,173,250,142, 16, 60,112, 32,202, 71, 62,130,219, 90, 29,238, 24,234,160, 51, 26, 81, 99, 48,161, + 82,175, 71,245,168,199,208, 38, 42,202, 69,175, 32,133, 33, 67,134,160,111,223,190,178, 99,199,142,229,185, 35,131, 77,244,182, +202,220, 81, 2,216,115,129,173, 50, 46,176, 69,254,140,165,110,157, 41,144, 11,108,145, 63, 91, 30,123,107,160, 64,254,206,201, + 95, 80, 0,254,238,110, 11, 38, 72,147,227, 50,128, 66,161, 48, 69,246, 27, 57,170,176,176,224,183,159,242, 75, 64,211, 4,242, +209, 17, 56,123,190, 12,239,190,127, 12,239,172, 57, 90, 79,254, 63,229,151,160,176,176,224,106,100,191,145, 47, 41, 20, 10,131, + 61,153,202,109,103, 40, 19, 90, 96,237, 39,102,146,223,248, 14,240,233, 46, 64, 22, 13, 12,236, 13,228,125,105, 46, 95,251, 9, + 96, 66, 11,119, 50, 2,186, 27,232, 73,156,200,105,150,181, 67,141, 70,131,190,125,117, 24, 60, 24, 24, 60, 24, 24, 52,136,160, +168,168, 8,217,217,217, 56,126,220,172, 61,197,196,196, 32, 42, 42,138, 83,122,224,204,204,204, 60, 46,196,110, 52, 26, 17, 24, + 24,200,219,138,181, 68,253,215, 71,252, 51,239, 93,181, 96,153, 63, 71,101,124,148, 0, 79,212, 3, 0, 69,114,114,158,126,232, + 80,217,197,177, 99,100,165, 61,122,160,212,199, 7,165, 61,123,226,210,184,113, 50,211,176,104,153,194,178, 68,195, 23,131, 7, + 15,134, 59, 86, 63, 91,134,179, 50,174,125,104,203,234, 31, 60,120,176,211, 50, 87,192,228, 8,184,155, 20,168,208, 45, 11,158, +201, 17,192, 74, 10, 36,120, 4, 56,146, 63, 32,100, 2,108, 82,203,252,126,252, 13,133, 66, 81,254,225,186,247,211,115, 14,238, + 88,248,231,141,234, 46, 93,195,131, 17, 59,182, 11,130,131, 36,184, 83,161,195,169, 95,111,162,224,202, 29, 20, 22, 22, 28, 29, + 55,126,250, 46, 0,215,156,201, 12,239, 62, 81,118, 56,127,175,250,104,126, 21, 98, 71, 1, 31,175, 52,103, 2, 44,188, 10,108, +249,202,108,249,155,208, 2,225,221, 39,202,112,232, 11, 79, 16,184,167,191,219,108,187, 0,110,220,184, 33, 11, 14,110,163, 62, +113,194,108,213, 92,186,212, 2,131, 7,247, 70,235,214,173, 33,145, 72,112,227,198, 13,217,196,137, 19,121,165, 2,238,220,185, +179,236,247,223,127, 87,219,179,216,140, 70, 35,186,118,237,138, 45, 91,182,240, 34, 33,235,181,127,214,123,226, 74, 44,128, 45, +107,213, 85, 11,214, 25,185,243, 33,127,182, 18,208,224,190, 56,123,214,237,241,118,215, 66,231,211,111, 92,127,203,211,242, 28, +145, 63, 27,250,184,174, 0,199,245,127,123,228,207,134,176, 35,192,190, 39,192,158, 98,224,109,207,178,228, 83,206, 99, 2,246, +148,213, 69, 92,252,236,158,180,207, 73, 63,121,164,125,238, 4, 46,190, 52,247, 53,165, 82,169,220,126,254,236,225,245,187,179, +190,143, 8,233,216, 37,154,117, 22,192,241,200,200,254, 63, 79,140,159,189, 84,161, 80,104,184,200,179,164,247,165, 20,179,250, +147, 29,251, 46,225,255,125,100,231, 44, 0,215,201,223, 35, 14,147,251,141,252, 1,224,137, 39,158,192,153, 51,103,240,236,179, + 39, 0, 0,131, 6, 13,194,227,143,247,151,189,250,234,171,245,228,252,227,143, 63,242,146,185, 97,195,134, 60, 0, 84,108,108, +108, 76,117,117,181,218,203,203, 11, 34,145, 8, 70,163, 17, 98,177, 24, 82,169, 84,230, 46,249, 3,240,136, 18, 32,224,159,137, +226,226, 98, 42, 39, 41,135,132,206, 13,149,161,179,237, 58, 37, 73, 57,106,174,214,122,113,113, 49,181,107,242, 46,210, 45,181, +155,236,215, 32,219,117, 46, 79, 62,172, 22,172,127,126,240,230, 49, 81,122,122,226,109, 10,121,212,125,222,190,251, 65, 30,227, + 9,168, 84, 42,149, 51, 34,251,141,100, 50,198, 72, 1,180, 1,112, 3,128,214,114,202, 27, 47, 88,187,247,139,174, 17, 20, 93, +211, 2,135,207, 52,119, 63, 80,247,186,127,185,194, 66,244,245,109, 56,119,238,156,199,100,239,219,183, 47,207, 83,215,199, 90, +247,167,172,202, 41, 88,242, 1, 8, 16, 96, 77,218,197, 11,139, 61,246, 76, 23, 23, 23, 83,197,255, 42,198,253,250, 44,223, 47, +224,154, 5, 16, 0, 40, 87,207, 17, 22, 32, 64,128, 0, 1, 2, 4,252,125, 33, 4, 1, 10, 16, 32, 64,128, 0, 1,130, 2, 32, + 64,128, 0, 1, 2, 4,131, 1, 0,215, 0, 0, 32, 0, 73, 68, 65, 84, 8, 16, 20, 0, 1, 2, 4, 8, 16, 32, 64,128,160, 0, + 8, 16, 32, 64,128, 0, 1, 2,254, 25,104,176, 11,224,244,233,211, 46, 71, 81,218, 10, 38, 20,228, 53,153, 60,167,135,216, 52, +167,188,196,196,196, 24, 0,106,149, 74,229, 17,121,211,167, 79,143,161,105,218, 99,242,132,251,175,121,228, 37, 39, 39, 79, 87, + 40, 20, 95, 53,101,251,148, 74,165, 15, 0,137,229,158,214, 1,160, 1, 16,133, 66, 65,132,241, 16,228,253, 47,201,243,148, 7, +128,112,248,227, 3, 79,203,187,103, 32,183,211, 8,169, 73,231,220, 62, 11, 17,122,236,122, 89,242,176,102,205, 26,153,131,254, +228, 45,239,220, 71, 45,224,174, 60, 6,147, 6,239, 87,135,183,200, 6, 0, 68, 69, 69,185, 61,158,221,219,239,192,131,109,191, +133,159,159, 31, 70,143, 30,125,223,220, 31, 74,165,178, 45, 21, 32, 61,168, 84, 42,219,122, 72, 94,152,200,215, 63,199,158, 60, +165, 82,233,163, 84, 42, 41, 39, 50,124,152,182, 73, 36,254, 7,149, 74,101, 91,165, 82,233,229,236,123,174, 60, 14, 46,220, 27, +199,154,106, 44, 54,109,218, 52, 97,243,230,205, 11,124,124,124,118,139,197,226,124,177, 88,252, 27, 0,165,151,151,151,138,162, +168,245, 74,165,178, 77, 19,244,129, 0, 1,141, 80,187,104, 17,241,240,131,214,100,115,158,179, 76,128,132, 16,251,191,205, 51, + 55, 52,177, 8,244,148, 60, 94, 22,172, 39, 49,109,218, 52, 82, 80, 80,224,148, 92, 85, 42,149, 58, 37, 37, 5,237,218,181,179, +153,114,117,254,252,249,156,207, 20,103,228,173, 89,179, 70, 54,127,254,124,245,241,227,199,213, 86,138,128, 75,242,232, 11,203, + 33,234,253, 54, 62,253, 78, 15, 0,160, 47, 44,191,171, 29,246,126,155, 87,191,124,249, 94, 0,161, 9,176,253,160, 89,150,252, + 81, 31, 68,118, 61, 15,192,172, 4,228,231,231,243, 26,155,180,143,100, 49, 21,127,148,163, 70, 31,172,214,212, 5, 64, 62,174, + 2, 29, 67, 40,132,135,207, 36, 85, 85, 58,236,216,177,163, 89, 39,244,228,121,243, 94, 6, 77,143, 77,158, 55,239,101, 0,203, +220,150, 55,119,222,243,132,166,199, 36,207,181, 45,207, 81, 74,102,118, 29,165, 82, 73,205,157, 59,239,101,154, 54,141,157, 59, +119,222,203,122,189,110,153, 13, 69, 65,228, 74,174, 7, 55,161,103,223,127, 59,119,238, 84, 79,153, 50, 69,150,153,153,153,231, +142,208,205,155, 55,203,189,189,189, 31,241,246,246,126,194,203,203, 43, 88, 36, 18, 73, 83, 83, 83, 69, 11, 23, 46,156,109, 50, +153, 96, 52,227, 9,147,201, 20,167, 84, 42,127,180,120, 3,244,150,249,175,201,151, 65,227,227,227, 9,215,249, 46, 43, 43,139, +215, 61,157,144,144, 64,220,249,190, 0,207,195, 47, 45,205,163,242,180,139, 22, 1,110,200,100, 50, 2,242, 61, 14,216, 41,249, + 71, 69, 69, 33, 63, 63,159, 15, 57, 59, 36,121,142,242, 26,201, 79, 73, 73, 65, 81, 81, 17, 44, 46, 98,143, 29,235, 74, 74,162, + 8,252,186,131, 10,254,146, 2, 0,170,213, 34,106,218,180,105, 78,181, 49, 54, 89,151,149,149,169,237,145,127, 74, 74, 10, 82, + 83, 83,121,145,191,229, 61,162,163,163,101,209,209,209,110,201, 99,200,158,249,191,234, 63,104, 64,254,139,166, 74,144,150,169, +227,212, 87,219,211,165,164, 79,184, 8, 26, 45,193,107, 79, 75,112,252,188, 17, 90, 13, 65,173, 30,144, 13, 56,143,243,151, 76, +136,138,138, 34, 92,149,128,148, 55,122,146,194, 83, 85, 8,108, 33, 70, 72, 7, 41,218,182,239,138,171,133,122,116,238,109,128, +143,164, 12,185,187,111, 97,252,248,241,228,224,193,131,205, 53,225,249,182,106,221,122,222,103,199,127,166,228, 61,186,189, 12, +224, 29, 0,117,238,200,107,221,170,245,188,237,223, 29,167,198, 12,232,225,150, 60,133, 66, 33, 14, 9,233, 48,239,144,250, 48, + 53,168,127,164, 77, 89,205, 64,254, 0, 80,127,252,160, 74,165, 82,199,197,197, 33, 51, 51, 83,109,235,121,253,229,151, 95,200, + 91,111,189,133,189,123,247, 58, 28,223, 45, 91,182,140, 18,139,197,125,196, 98,241, 92,177, 88,236,127,237,218, 53,116,235,214, + 13, 94, 94, 94, 8, 12, 12, 68, 65, 65, 1,164, 82,169,247, 47,191,252, 18,116,236,216,177,195, 47,190,248, 98,103, 0, 87, 1, +136, 97, 94, 30,176, 59,241,177,231, 63,246,188,197,148, 83, 20, 5,138,131,213,178,103,207, 30,187, 50,216,229,142,230, 91,123, +200,202,202,114,235,251, 77,170, 32, 39, 39,199, 88,178, 82,186,141,183,223,126,155,208, 52, 13,136, 42,160,175,211, 65,236, 43, + 1,232, 32,136, 68, 34, 44, 95,190,156, 58,102,197, 51,201, 14,100,157, 63,127,158,100,102,102,194,158,188,169, 83,167, 34, 50, + 50,146,114,181,125, 88,158,142, 21,111,191, 66,216,237,115,231,218,253,211,210,120,127,223, 94, 26, 96,174, 10, 0, 39,242,231, +138,148,148, 20,167,117,184, 16,151, 61,242, 95,181,106, 21, 22, 47, 94,108,173,116,184,212,233,228, 68, 20, 65,235,238,160,194, +191,164,216, 22,255,206,157, 59, 41, 0, 96,254,219, 91,115,177, 38,107, 71,228,111,241, 12, 56,181,218, 85, 42,149,218,218,194, +103,202,216,125,204, 87,158, 35, 11,127,209, 84,238, 39,197,101,166, 7,144,110, 15,138,224,231, 75,225,193, 80, 47,220,186, 67, +195, 96,244, 66,121, 5, 65,101, 13, 65,193,159, 52, 32, 2,218,248,159,101,250,199,225,164,176,244,245, 30, 49,221,187, 68,224, + 88,233, 77,132,135,181, 69,159,126, 17,240,242,109,133, 7,195,239,224,142, 86,135,178, 82, 19,254,188,169,131,191,119, 17, 39, +121, 77,132,167,158, 94,184, 80, 92,212, 33, 20,190, 81,131, 68,186,195, 63, 60, 5,224, 19,190, 66, 88,150,248, 83, 51, 95, 94, + 32,254, 83, 28, 2,105,247,135, 68, 85,231,142,184, 36,143,105,219,139,243, 94, 21,195, 55, 16,225, 61, 34, 69,191,255,122,210, + 29, 89,158, 4,205,178,254, 33,145, 72,100, 0,212,214, 99,120,226,196, 9, 78,228, 15, 0, 62, 62, 62, 65, 18,137,100,214,173, + 91,183,252,187,119,239,142,129, 3, 7,194,219,219, 27, 31,124,240, 1, 76, 38, 19,250,246,237,139, 93,187,118,225,151, 95,126, +193,217,179,103,225,229,229,181, 94,169, 84, 38,108,216,176,193,145, 85, 93, 63,207,121,194, 99,169, 84, 42,101, 33, 33, 33,106, + 66,136,195,239,148,150,150,202, 20, 10, 5,223,251, 71, 22, 18, 18,162,118,245,251, 12, 81, 95,188,120,209,225,188,209,171, 87, + 47, 25, 95, 50,191,120,241,162,250,201, 39,159, 68,203,150, 45,101,238, 40, 2,138, 23,102,146,164,228,177, 8, 8,240,107,244, +153, 70,163,197,242,229,203, 49, 12,160,254,220,179,135, 92,139,143,183, 63,183,207,232,110, 30,204,149,147,209, 97,212, 68, 72, + 30, 26, 4, 83,247,200, 6,117, 12,219, 51, 16,188,114,242,221,186, 0,180,227,159,195,240,213, 95, 56,108,223,204,103,199,160, + 85,107,127,115,193,242,116,204, 95,240, 44, 0,224,118,121, 45,174,151, 20, 18,229,198, 12,151,149,128,218, 69,139,136, 43, 74, +128,171, 10, 0,225, 98,169,223, 47, 40, 42, 42,194,226,197,139, 93, 85, 32,236, 98,218,180,105,132, 10,221, 73, 77,155, 22, 78, + 84,155,134, 0,219, 30, 38,148,244, 21,167,131, 96,139,172,173, 73,217,209,178,128, 61,176, 21,138,227,199,143,171,163,163,163, + 27,184,254,249,202,251, 98,161,212,238,228,246,212,106, 13,103, 57, 27, 54,108,136,241,245, 90, 8,145, 8,240,247, 3, 42,170, +104,212, 17,130, 0, 63, 10, 58, 26,208,214, 17,116,106, 43, 2,109, 4, 46, 95, 51,161,168,168, 72,237, 72, 57,155,247,242,152, +152,240, 7,253,213, 98, 49,193,243,179,134,194,100, 34, 40, 45,211,163,248,122, 5,224,115, 13,126,193,117,184, 81,246, 7, 68, +226, 74, 92,184, 80,129,150,193,142,229, 53,157,249,223,106,249, 19,207, 60,227,251, 6, 13, 4, 47,126, 93,122,243,204,233,101, +116, 85,149, 43, 36, 75, 0, 64,210,178,213,242,127,205,120,198,119,245, 21, 19, 58, 77, 79,145,254, 94,116,118,153,169,182,161, + 60,165, 82, 73, 89, 7,179,217, 66,139,150, 65,203,159,154,241,180,239,217,226, 59,136,127, 50, 73,250,225,127,230, 47,211,214, +106,220, 85, 0,184,158,151,225,104, 44, 76,204, 51, 50,113,226, 68, 48,164,175,213,106,235,199,144,177,252,179,179,179, 57,141, +169,175,175,239,112,141, 70,211,179, 87,175, 94,144,201,100,152, 63,127, 62,230,204,153, 99,158,204, 13, 6,108,219,182, 13,249, +249,249, 56,121,242, 36,118,236,216, 1,173, 86,219,149,166,105,185, 19,139,221,163,247,211,190,125,251, 56, 45,205, 81, 20,197, +251, 94,102,203,118,229,251,150,103, 56,239,201, 39,159, 68, 73, 73,137,205,207, 67, 67, 67,225, 42,129,151,148,148,160,164,164, +196, 45, 69,224,236,153, 75,248,191,140,189, 24, 57,114, 56, 34,251,118,188,107,201,255,122, 29,135, 15, 31,197,176, 97,195,136, +106,201, 18, 92,139,143,135,223,136, 17,208,218, 57, 59,131,250,236, 18, 5, 0, 11,134,247, 33,253,202, 14,226,233,239,246,194, +212, 61, 18,218, 5, 43, 0, 0,126,171, 87, 64,122,233, 60, 22, 22,137,177,250,232,185,187,253,248,217, 34,135, 65,118, 76,251, + 70,143, 25,209,168,125,185,223,252,136,179,103, 46,185,117,255,184,178,164,192,118,247, 59,242, 6,120,243,181,216, 61, 77,180, +238,194,226,246,119,125, 86,139, 2, 65, 7,128,218,107,126,112,168, 65,249,212,180,105,225,245,131,189,115,231, 78, 10,155,134, + 16,107, 79, 0, 87,178, 46, 43, 43,107, 64,206,174,144, 53, 87,176,148, 14,167, 36,193,197, 93,200,114,255,219,172,188,113,227, + 70,242,215,249, 87,209,161,187, 23, 52,218,187, 85,180, 38, 2,157, 30, 48, 88,202, 12, 70, 2, 34, 50,191,254,245,108, 62, 18, + 19, 19, 99, 46, 95,190,108,243, 55, 3, 3, 43,213, 26,173, 8,109, 90, 5,161,226,118, 45, 42, 42, 43,112,252, 68, 41,174,223, + 36, 16, 7,212,162, 99,215, 26,104,107,111,161, 91, 63, 3, 58,247,170,195,142,143,243, 49,121,242,228,152, 43, 87,174,220,147, +251,205, 98,177,143,158, 56,117, 90,251,146,150,193, 40, 52, 2,126,163,199, 66, 20,220,186, 13, 93, 85, 53, 22,192, 33,134,172, + 1,248, 40, 20, 10,189,179,121, 31,192,152,184,201, 83,219,255, 37,106,137,171, 53, 6, 4, 61, 52, 26,222,129,193,109, 76,181, +119,229, 1, 0, 23,242, 7, 48,110,210,228, 41,237,137,151, 47, 42, 53,117,232, 19, 53, 12,210, 22, 45,219,104,107, 53, 13,100, + 53, 23, 24,235,159,162, 40, 76,156, 56,145, 0,192,222,189,123,145,152,152, 24,147,146,146,162,230, 67,254, 74,165,210,183,162, +162, 98,166,193, 96, 16,249,251,251,227,145, 71, 30,193,234,213,171,225,227,227, 3,133, 66,129,140,140, 12,228,231,231,227,248, +241,227,248,246,219,111,241,235,175,191,162, 77,155, 54,109,140, 70,227,131,176,227,254,103,187, 64,157, 45, 1,136, 68, 34, 78, +237,108,202, 37,128, 61,123,246,120,100, 9,160,101,203,150,178,146,146, 18,181,189,207,220, 29,119, 87, 20,129, 75,139, 22,145, +242,180, 52,224,216, 49,224,216, 49,220,158, 58, 1,107,250,119,175,119,217, 71,246,238,141,199,167,199,162,243,157, 91,184, 22, + 31,143,214,139, 22,161,123, 90, 90,163,229, 0,107,136,101, 15,163,187, 60, 6, 11, 23,189,131,247,112, 30,107,162, 71,161,207, +224,161,232,122,187, 8,219,130, 6,162,168,229, 77,100,100,100,144,153, 51,103,114, 26, 95,217,168,254,120,122,230, 68,252,252, +211,175, 56,152,115, 8,111, 2, 88,179,122, 43, 34,123,247,198,211, 51, 39,162, 86, 91,142, 23, 94,120,129,179, 60,107,184, 27, + 3,192,215, 3,240,119, 2,101,135,156,120,119,244,180,105,211,136,106,241, 21,192, 75, 12, 4,249, 0, 65,157, 65,237,180, 8, +227,184,246,223, 4, 32,108,171, 31, 0,216,150,191,141,201, 21,209,209,209, 50, 7,193,128,188,175,225,243, 5, 1,118, 61, 2, +129, 85,243,241,135,158,160,244, 22, 13, 64, 4,169,191,217,197,105, 48, 18,232,234, 0,157, 30,208,213, 1,122, 3,160,211, 2, +250,186,187, 94, 18, 91, 1, 41,159,127, 20, 64,114,143, 87,227,129,112, 41,136,143, 55,110,105,181, 80,127,127, 13, 23, 10,174, +227,246,237, 26, 68, 70,153,160,209, 25,161,171, 51, 65, 91, 75,163,180, 24,208,106,128,221,187,119,171,249, 28,128,225, 14, 20, + 10, 5,237, 21, 20,180,252,217, 37, 75, 36, 59, 88, 20, 18,188,228,117,233,237,197, 11,150,153, 42, 42, 14,177,200, 90,207,101, +140,189,165, 65,203,231,188,186, 88,114,224,186,169,190,176,211, 19,139,165, 87,183, 44, 89,102,172,169, 56,196,199, 11,224, 47, + 13, 92,246,242,107, 11, 36,133, 37,119, 79,139,140,123, 50, 73,186,125,211,154,101,181, 53,213,135,220,124,214,108,221, 75,124, +158, 53,194, 88,255, 18,137, 68,166, 82,169,242,152, 45,163, 90,173, 86, 61,104,208, 32, 62,178,140, 0,186, 2,160, 7, 12, 24, + 64, 75, 36, 18, 81, 70, 70, 6,102,207,158,141,149, 43, 87,130, 16,130,159,126,250, 9,223,127,255, 61,206,158, 61,139,202,202, + 74,116,235,214, 13, 85, 85, 85,254, 34,145,168,157, 51,225,147, 38, 77,178, 75,168,206,150, 6,236,185,233,239,215, 37, 0, 71, + 94, 0,119,172,127,119, 21,129, 59, 21, 21,245,175,219,189,254, 2,250,188,158,140,145, 86,117,174,140,159,131, 78, 63,156, 64, +225,130,231,241, 83,104, 40, 0, 96, 24, 64, 13,176, 49,215,165,167,167,147, 78,157, 90,224,228,169,159, 17,249, 80, 47, 32,237, + 13,188,186,101, 55,102,117, 57,131,254,117, 5, 88,120, 83,140,255,124,190, 20, 43,223,221,128,179,191, 30, 65,122,122, 58,121, +229, 21,251, 94, 95,182,188, 86,173,253, 49,126,194, 80,140,159, 48, 20,111,209,233,208,215, 45,198,169, 83,192,169, 83,192,225, +195, 19,241,225,186, 75,120,226,137,139, 36, 44,236, 65,164,165,249,243,226,167,220,135,223,192, 34,172,112,120,195, 29, 58, 52, +252,127, 70, 1, 32,137,137,137, 50,214,154,161,181, 18, 64,177,173, 13,139, 75,222, 37,205,139, 33,253,157, 59,119, 82,170, 77, + 67, 0,177, 24,212,206,157,247,244, 98,153,168,127,149, 74, 69, 37, 38, 38, 18,103,222, 16,235,216, 0, 62,132,110, 11,142,234, +206, 92,162, 65,104,123, 17,158,140, 19, 67, 87, 7,180, 12,164, 32,162, 44, 86, 63, 8,116,181,128, 70, 79,160,209, 18,104,116, + 4, 52, 1, 68, 14, 98,174,103,206,211,160,111,255, 34,132,244,188,141,111, 14,148,225,246,109, 29, 6, 12,171, 66,191, 86, 53, +128, 79, 29,116,181, 52,202,174, 19,104, 52, 20,140, 70, 10,173,218, 80, 0,117,207, 99,217, 34, 7,246,239, 63, 40, 56, 44, 12, + 71,239,242, 53,164, 79,206,192,237,148,249, 81, 0,122, 3,184,192, 67,161,232, 53,120,196,163,131, 90,135,134,225,196,207,245, + 49,114,104, 43,251, 23,174,126,188,184,145, 60, 39, 94,128,222, 3,251, 15, 24, 20, 26,218, 9, 23, 78,222,245,136,140,120, 44, + 22, 95, 42, 87,243,110, 91, 83, 42,180,204,243,107, 29,191, 17, 23, 23,215, 40,254,200, 70, 44, 0, 51,232, 93, 1,156, 94,180, +104,209,112,111,111,111,233,167,159,126,138,173, 91,183,226,217,103,159,197,170, 85,171, 64, 81, 20,254,248,227, 15,104,181, 90, +164,164,164,192,104, 52,226,133, 23, 94,160, 41,138,114,250, 0,120, 50,154,254,126, 95, 2,112,228, 5,240,132,245,239, 42, 50, + 50, 50,240, 76,210,227,168,172,168, 3,222,221, 8,205,225, 19, 8, 24, 57,168,254,243,178,119, 55,226,188,175, 47,168,151,158, + 67,159,233,227,113,108,219, 1,135,242, 46, 95, 62,135, 97, 35,228, 56,119, 62, 24, 27,215,171, 48,114,228,112,252,231,163,165, +120,107,244, 83,248, 12, 64,207,167,103, 99,227,122, 21,196,226, 96, 36, 76, 26,132, 79,121,200,251,239,251, 95, 97,240,196,190, +120,167,239,106,156,139,149, 34, 56,110, 87,131,186,109,252, 37,248, 57, 79,141,176,103,102,241,238,135, 35, 71,188,145,150,230, +231,176,142,171,246,207,223,210, 3, 96, 99, 29,153,114, 80,143,187,137, 51,200, 28,161, 62,109, 90, 71, 2, 92,134,234,131, 43, +128, 95,247,122, 79, 0,163, 20,112, 89, 6,240, 20, 24,107, 62, 49, 49,145,176,173,127,198, 35,192,126,159,152,152, 8, 86,178, + 28,194,151,208,173,193,218, 5, 96, 83,158,209, 4,104,106, 9,234,244,230, 96,191, 58, 61,129,183,239,221,207,116,181,128,214, + 64, 80,126,155,224,175, 59, 4, 39, 47, 24, 65,211, 64, 98, 98,162,236,242,229,203,141,198,198,104, 4, 74,174,233,113,173,240, + 14,142, 28,187, 3, 66, 40, 92,248,141,198,196, 39,141, 16,123, 19,252,117, 19, 56,114, 8,168,170, 34, 32, 52,240,240, 40, 10, + 18, 9, 32,151, 39,224,234,213,171,156,174, 73, 62, 12,228,192, 49,215, 39, 73,145,180,197,146,231, 87,165,250,100, 17, 81,131, + 14,105,227,235, 11,159,151,230,249,252,177, 46,125,169,190,170,106, 6, 87,121, 94,126,210,165,201,203, 86,249, 28, 42, 33, 13, +228,181, 14,240, 69,159,233, 47,250, 92,248,234,131,165,122, 77,205, 12, 46, 30, 0,137, 95,192,210,197,203, 87,248, 92, 41,173, +108, 32,171, 69, 96, 0, 38, 63,249,172, 79,214, 23,159, 44,213,104, 52, 51,154,249,241,165,246,238,221,219,168,236,205, 55,223, + 36,123,247,238, 69,118,118, 54,231,161, 0,112, 14,192,233, 53,107,214,244, 15, 10, 10,146, 50,110,240, 79, 62,249, 4,179,103, +207,198,214,173, 91,235, 45,245, 53,107,214,160,162,162, 2, 85, 85, 85, 53,181,181,181, 69, 22, 15,130,216,209, 15,208, 52, 77, +172, 93,244,140,245,207,213,253,207,184,233,217,114,172,221,245,247,195, 18,128, 45, 47,128,167,173,127, 70, 38,215, 37,128, 11, +195,134,129,122,126, 58,130, 0,144, 81, 81,168, 61,121, 14,154,119, 55,222,237,183,164,199,209,237,233,199, 33,145,152,175,255, +252,121,199, 91,179,153,207,229, 19,204, 74, 68,254,137,179,248,236,255,182,195,127,232, 16,212, 26,140,208, 67,143, 71, 30, 29, +216,168, 62, 23,121,215, 76,122, 60,217,254, 69,208, 39,235,144,248,222, 40,136,167, 29, 71,239,200,222,136,236,211,181,190,125, + 41, 11,215, 33, 45,237,223,156,239,155,130,170,130,209, 23,112,225,155,248, 22, 92, 60, 6,174, 37, 2,250, 91, 42, 0,249,249, +249, 78,163,191, 45,159,115, 19,232, 27, 0, 85,231, 31,128,143,194, 9,194, 3,128, 46,117,160,122,100, 83,248, 32,170,126,237, +223,157,101, 0,235,173,128,246,182, 6, 58,112,187,214,147,191,117, 0, 32,227, 82,103,202,156,120, 0, 40,107, 75,204,221,201, +252,225, 71,227, 99,174,223, 56,160,166,219,210, 16,121, 3, 62,150,121,209, 64, 19, 24,141, 64,117, 53,129,222, 0, 24, 13,102, +165, 32, 97,146,217,123, 99,199,101, 79, 69, 15,139,143,169,187,181, 95, 29, 25, 73,227,240,247, 38, 80, 34,224,175, 82, 10, 18, + 63,224,251,131,128, 94, 75,129, 34, 64,191,135,124, 80, 82, 76,227,209, 71, 99,145,149,149,197,233, 88,107,249, 48,144,180, 23, +205,215,239,170, 18, 64,104,211, 56, 83,235, 54,162, 3,244, 93, 22,106, 15, 32,132, 2,180, 81, 81,222, 87,140,166,113,188,228, + 17,122, 28, 2, 91,137,212,165,166,122,121,109, 37, 64, 27, 9, 5,255,190, 81,222,231,183,211,227,172, 60, 6,196,145,172,128, +192, 32,209,213,155, 21, 22, 98, 1, 2,253,124, 17,232, 47,198, 67, 3, 6,122,239,254,140,140,107,230, 71,215,102,159, 51, 81, +255,236, 58,140,247,110,234,212,169,178,204,204, 76,123,242,106, 0, 92, 57,117,234, 84,205,200,145, 35,219,130,181,167,255,147, + 79, 62,169, 39, 68,131,193, 0,147,201,132,203,151, 47,163,109,219,182,183,104,154,230,164, 45, 78,154, 52,201,158,165,238,146, +155,254,126, 94, 2,176,229, 5,240,164,245,207,135,248, 25,116, 8, 13,194,199, 31,127,135,248,184, 97,104, 31, 21, 9, 68, 69, +130,122,126,122, 67,165, 23,192,205, 82, 45,246,100, 31, 67,135,208, 32,238,242, 66,252, 16, 53,168, 27,162, 6,117,107, 84,143, +175,188, 71,166,244,194,235,143,126, 0,250,156,153,252,231, 44,156,233,146, 60,107, 44, 9, 92,242,205,202,234,149, 99,154,242, +129,116, 75, 1,176,236,217,191,167, 17,216,140,149,171, 82,169, 24,139,151,178, 81,135, 48,228,207,178,138,121,129,189, 11,128, + 41,227,107,249, 91, 7, 0, 90, 80, 95, 54,127,254,124,181,101, 57,131,147, 60, 54,249,219,138, 9,224, 43,207, 25,210, 50,117, +112, 38, 47, 43, 43, 43,175,117, 16,133,199,162,125, 64, 3, 48,232,105,248,138,205,221, 84,173, 33,168, 51, 16, 24, 77, 64,254, + 57, 19, 76, 52,129,179, 45,123, 89, 89, 89,121,237,219, 82,120, 52,198, 11,147,159,242, 66, 77, 53, 65,117, 37,160,169,166, 16, +222,141,192,100,160,224, 45,146,160,226, 54,141,146, 63,245,184,252, 27,183,128, 49,249, 48,144,244,121, 64,247, 48, 96,221,107, +192,220,247, 93, 83, 2, 72,173,102,202, 75, 81, 3,247,135,100,237,151, 6,143,120, 24,237, 1,180,167, 0,211,209, 35,200,157, + 57,163,198, 80,171,153,204, 71, 30,173,171,157,252,252,232, 65, 7,122,189,245,181,180, 93,191,225,104,227, 75,161,173,132,130, +246,226,143,216,243,198,172, 26,131,182,150,179,188, 58,157,118,242,132,199, 70, 30,152,255,238,122,105,239,254, 81, 8,244, 23, + 35,208,207, 23,133, 23, 78, 99,121,202,203, 53, 90, 30,178, 92, 37,115,103,151,107,139,252, 87,172, 88,209,200,205,191,115,231, + 78, 38, 79, 64,158, 29,235, 31, 48,199, 88,156,238,209,163, 71,161, 78,167,235,232,229,229, 37,241,247, 55,111,197,202,204,204, +196,212,169, 83,161,213,106,161,211,233, 80, 87, 87, 7,169, 84,170, 51,153, 76, 89,132,144, 82,142,214,181, 71,230,182,191,203, + 18, 0,219, 11,192,188,110, 14,226,103, 16, 30, 30,130, 37,175, 39,225,224,129,159,240,245,238,147,240, 21,183,192,159, 37,119, + 87,176, 58,133,246, 70,157,190, 10, 15, 69,245,196,218,244, 36,172,124,119, 3, 47,121,237,218,181,196,249, 11,231,235, 63,143, +236, 29,137,178,178, 74, 94,242, 98,231, 77,198, 84,209, 12,212,157,171, 65,244,220, 62,160,251, 73,240,241,199, 59,234,219, 87, + 89, 89,137,225, 15,247,226, 36,207, 26, 42, 74, 69,169,160, 66, 83,194,101, 5,160, 41,200,159,139, 76, 11,225, 19,203,107, 0, + 32,236,109,137,249,249,249, 13, 8,223,150,130,208,216, 15, 75, 1, 98, 17,224,231, 5, 72,189,129,186,106,168, 86,250, 0,233, +115, 8,252, 90, 1,126,173,120,175,253,219, 33,127,216, 32,107, 78, 15,134, 53,249, 91,199, 4,240,149,199,131,252,157,202, 43, +175, 32,212,190, 60, 3,145, 72, 0,154, 6,250,246,240,186, 59, 30,191,154, 96, 48, 17,152,104, 47, 76,153, 50,133,147,114,114, +243, 47, 66, 29, 56,104, 34, 70, 35,160, 55, 16,152,140,128,136, 2, 98, 98,129,234, 10, 10,191,157,209, 66,171, 19, 33, 62,110, + 10,118,237,218,197,137,252, 87,204, 1,186,118, 50,191,239,210, 17,112,213, 19,160, 84, 42,143, 43, 20, 10,121,105,194,132, 3, + 97,123,246, 75,195, 70, 60, 12,195,209, 35,216, 21, 55,161, 70, 95, 93, 45, 7,112,132,103, 87, 31, 49,105,171,229, 23,223,156, +116, 32,244,189, 44,105,199,193, 35,160,185,120, 20,159,191,148, 80, 83, 87,203, 91,222, 17,157,182, 86,190,230,245,127, 31,248, +207,127,183, 72,163,135, 13, 71,193,249,211,120, 57,105, 70, 77,109, 77,141, 43,109,107, 82, 56, 72,246, 67, 98, 99, 99,185,236, + 6,240, 10, 10, 10, 58,173,213,106, 63, 43, 42, 42,234,220,191,127,255, 8,163,209,232,237,227,227,131,172,172, 44,140, 25, 51, + 6, 58,157, 14,181,181,181,184,124,249,114, 85,112,112,240,119, 90,173,246, 83,154,166, 53,224,152, 1,144, 29,144,192,215,245, +255,119, 91, 2, 96,123, 1, 60, 33,199,149,220, 1,182, 48, 94, 62, 20,227,229, 67, 45,239,220,215, 97, 27,202,155,228,158,114, + 23,180, 19,117,103,106, 48,115,125, 44,254,243,221, 82,183,219,150,174, 79, 39,193,198, 96,204,244,159,121, 79, 12,107,151, 20, +128,230,176,252,109, 88, 31,196,170, 61,158,178, 82,236,122, 4,184,122, 0, 60, 77,254,140,178, 99,229,222, 39,236, 50,190,242, +156,197, 2,240,149,167,209, 17, 74,163, 3, 17,137,128, 35,249,230,181,126, 38,224,207,188,238, 63,133,151,188,234,106, 66, 81, +150,101,118, 74,100,150,241,243, 15,128,166,134, 6,161,129,248,248, 88,236,218,181,203,233,120,200,135,129,164,204, 0,130,164, + 64,201, 45,192,207, 23,160, 9, 16, 32, 1,222, 85,184,166, 4, 0, 56, 66, 87, 87,203,243,227, 39, 28,104,185,226,109,105,222, +138,229, 53,117,174,145,127, 3, 37, 32,111, 81,194, 1,191,151,222,148,230,124,248,150, 43,228, 95, 47,203,104,208, 79, 88,254, +202,243,251,231,206, 79,145,174, 95,155, 90, 83, 91, 83, 35, 87, 42,149,103,216,238, 97,165, 82,233,173, 80, 40,140,124, 29, 32, +158,244, 10,216, 34,127,138,162, 72,108,108, 44, 0, 96,226,196,137,132,162, 40, 71,138,128, 84,175,215,215,136, 68,162,220,208, +208,208, 78,213,213,213, 47,158, 56,113,162,195,192,129, 3,105,163,209, 88, 91, 89, 89,121,243,204,153, 51,127,132,135,135, 23, +182,110,221,186, 72,171,213,102, 26,141,198,155, 73, 73, 73,154, 1, 3, 6,112, 82, 0,152,164, 64,238, 64,169, 84,114, 38, 84, + 87,150, 0,220,249,190, 61, 47,128, 39,230, 76,119,229,232,180, 94, 30,173,239,105,121, 21,119, 68, 72, 53, 42, 16,113, 44, 4, +211, 63,114,174,152, 84,220,113,126,203,221, 75,242,183,171, 0,112,216,235,207,171,129, 60,114, 7,240,145, 75,177,162,252, 93, + 38, 47, 42, 31,212,180,240,241, 4,151, 0, 52,202,215, 80,105,249,227,183,199,220,114,189,106, 79,145,171, 85,191, 16, 38,207, +128, 37, 64,144, 98,121, 67, 92,146,247,249,130, 0,182, 82,224,138,188,122,185, 83,167,222, 29, 19, 38,224, 79,165, 82,229,185, + 34,143,208, 13,199,184,166, 10,136,141,141,197,190,125,251, 40,198,170,226, 52, 30,159,121,238,129, 97,229,227, 63, 98,168,174, +150,127,191,226,205,140,186,234,234,153, 30,176,174,143,232,107,171,229,135,214,191,149,161,171,173,158,165, 84, 42,143,186, 58, +153, 27,141,198,195, 70, 99,141,124,125,122, 90, 70, 77, 77,205, 76, 0, 71,172,101,185, 64,254,158, 64,131, 25,213,154,252,153, +184, 29,118,144, 96, 92, 92,156, 35,121,197,122,189,222,151, 16, 82, 77,211,180, 82,175,215,255, 20, 22, 22,214,166,162,162,130, + 90,182,108, 89, 85,101,101,101,121,199,142, 29,171,107,106,106, 52,122,189,190,202, 96, 48,212, 61,247,220,115, 90,158, 22, 54, +229,129,123, 38,175,169, 58,180, 41,101, 55, 55,222,127,255, 35, 10, 0,121,252,137, 49,136,236, 19,110,183,222,249,115, 87,240, +213,246,111,152,250,247, 76,222,250,245,235,235,229, 57, 52,152, 79, 20,225,171,237,223, 48,245, 29,226, 94,146,191, 61, 5,192, +211, 13,104,178, 11,178,144, 40,101,203, 90,230, 3, 15, 71,245,115,201, 22,232,214, 15,240, 57,244,199, 19,222, 0, 23,198,196, +238,123,119,229,237,219,183,143,215, 88,185, 19,241,207,133,180,117,213, 85, 93, 60, 41, 79, 91, 83,221,197, 67,150,220,145,154, +234,234, 46,247,217,179, 76, 1,192,166, 77,155,136, 72, 36, 2,243,199,118, 97,203,229,114,208, 52, 13,154,166,145,148,148, 68, + 57,217, 21, 64, 25,141, 70,127, 66,136,137,166,233, 58,131,193,240,131,151,151, 23, 37, 18,137,124, 1,248,210, 52, 13,147,201, +228,101, 52, 26,197, 70,163,177,195,115,207, 61,119,145,245,221, 38, 63, 4, 72,128,103,148,128, 33, 67, 70,146,131,251,119,163, +184,172, 10, 33,193,181,245,159,149,222,241, 71, 88,187, 22,232,217,179,167, 83,178,110, 42,121,235,215,175,167, 30,121,228, 17, +178, 46,125, 31, 10,254,188,213, 72, 94,215, 78,109, 16, 17, 17,193,137,252,155, 10,142,114,164, 80,174,158, 35, 44, 64,128, 0, + 1,247, 1,106, 89,132, 78,179, 12, 27,111, 86,249, 13, 0, 45, 97, 14, 26, 23,136, 95,128, 0, 7, 30, 0, 1, 2, 4, 8,248, +187, 64, 98, 81, 2,104, 22,241,139,112,247,228, 65,111, 0, 29, 44,175,105,161,187, 4, 8, 16, 20, 0, 1, 2, 4,252, 51, 32, + 2, 32,101,189,103,136, 95,204, 34,125,218, 82, 79,176,254, 5, 8, 16, 20, 0, 1, 2, 4,252,143,204,105, 2,233, 11, 16,224, + 64,123, 22, 32, 64,128, 0, 1, 2, 4,252, 47,107,203,167, 79,159,102, 31,164, 67,172,146,232, 16, 52, 60,104,167, 88,165, 82, +133, 49,239,109, 5, 19,178,229,241,197, 63, 81,158,141,109,139,148,208,127,194,120,252, 93,228,133,133,133,213,215, 41, 46, 46, +166,248,202, 75, 78, 78,134, 66,161,160,132,251,207, 53,153,194,243, 43,200,227, 35,143,183, 2,192, 19,109, 57,214, 35,137,137, +137,188, 51, 75,217, 59, 47, 30,141,147,145,216, 58, 13,208, 86,157,123, 14,134, 96, 44,123,225,213, 42,149,170, 62, 91, 23,223, +124,226, 77,133,184,184,184,152,236,236,236,122, 18,140,141,141,149,237,219,183, 47,239,159,168,237,218, 26,143,139, 23,205, 59, +195,122,245,234,213,220,205, 35, 9,147, 20,200,250, 90,105,243,158, 77,152,164, 32,150,207,236,222, 56, 9,147, 28,158, 20,136, +172,175,149, 46,223,116, 97, 97, 97, 36, 46,238,238,174,194,236,108, 16,103, 74,128, 51,172, 94,179, 58,102,207,161, 61,136,136, +140, 80,131, 2, 46,158,186, 32, 27, 54, 96, 56,210,223, 79,231,117,255,205,156, 57,179,209,117,103,100,100, 80, 16, 32, 64, 64, +147, 41, 0, 98,174, 21,163,163,163,121, 11,119,160, 0,216, 36, 81,235,131, 54,120, 16,173, 43,154, 19,151,201,133,168, 84, 42, +164,164,164, 32, 53, 53, 85,237, 32, 77, 39,151,223,111, 80,167, 99,248, 3, 0,128,155, 58, 29,140,218, 58,115, 97, 69, 21, 67, +114,220,210, 31,215, 79,228,217, 13,114, 10, 88,114,139,243, 58,227, 93, 68,153,179,235, 49,255, 1,167,175,155, 99,114,110, 48, + 30, 12,241,187, 49, 30,158,188, 6,146, 48, 73,129, 9,242,135,116,128, 66, 98, 33,122,151,126,131,165, 64,120, 28,122,125, 10, +114,114,146, 48,110,220, 38,196,197,165, 34, 59,219,220, 87,174, 40, 2, 79,191,252, 52,169,104,117, 27,107,149,171, 17,236, 31, + 12,218,104,130,142,212,169, 15,254,116,104,220,116,211,227,100,120,196, 8,217,188,121,243,156, 42, 2, 51,103,206, 36,201,201, +201, 54,251, 84, 80, 2, 4,220, 11,196,199,199,215,207, 25,115,230,204,193,150, 45, 91, 26,112,207,236,217,179, 27, 28, 78,229, + 44,185,148, 51,121, 92,143,170, 62,125,250,180,181,151,192,163, 10, 0,175,248, 1, 91,167,216,121, 2, 27,149,202,152, 23,220, + 76,154,194, 39,135, 54, 71,203,157,164,164,164, 96,213,170, 85, 0, 80,255,223,246, 79, 19,126,222,128,160, 22, 56, 91,180, 29, +126,232, 4, 19,126, 68,217,230,147, 56, 83, 88,142, 41,171,182, 54,219, 3,112,246,215,115,232,215,183, 15,104, 2,156, 59,103, +126, 13,220,125,205, 46,167, 9,231, 49, 33, 28,199,131,226, 58, 30,179,102,205, 2,128,250,255, 54,137,157,162, 0,199, 63, 77, + 30,123,236, 0,190,253, 86,238, 81, 37, 96,130,252,161,218,164,164, 36,127, 96, 19,178,190,118,141,216,221,177,240,157, 89,255, + 0, 48,117,106, 38,114,114,204,255,147,146, 10,193,120, 4,248,120, 3, 54,110,220, 24,163,254,253, 59,245,243,201,179, 49,168, +237, 64,248,181,108, 9,162, 55,130, 38, 38,120,121,139,209,117,116,215,156,223,162,126,199,170, 77,169,234,181,107,215,202, 94, +125,245, 85,167, 74,192,173, 91,183, 26,188,143, 29, 25,128,161,243,126,132, 78, 55,189,193, 64,238,216,177,195,229,254,145,203, +229,228,192,129, 3, 30,235, 95, 79,203,107, 74, 36, 39, 39,199,184,155,214, 55, 57, 57, 57, 6,112, 61, 61,176, 82,169,236,247, +218,107,175,221,208,104, 52, 97, 0,198,194,124, 8,103, 47, 0,167, 97, 62, 20, 10, 0, 62, 7,240,219,189,238, 31,246, 89, 15, +115,230,204, 65,118,118,118, 3, 78,153, 61,123, 54,248,100, 46,117, 38,175,254,121,207,202, 34, 9, 9, 9, 20, 23,242,103,202, +172,149,128, 6, 10, 64, 74, 74, 10, 41, 42, 42, 2, 0, 68, 68, 68,128,125,216,140, 74,165,106,240,222,250,115, 71, 22,123, 89, + 89,153, 90,165, 82,113,246, 4, 88,159,117,239,136,132, 95,176,164,194,180,230, 1,190, 46,246, 77,155, 54, 57,173,147,155,155, +203,137,187, 18, 19, 19,237,146,254,226,197,139,145,154,154, 10,182,130,192, 5, 29,195, 31,192,245, 59,149,216,245,194, 84,180, +166, 70,160,240,227, 5,136,152, 28,129,111,154,153,252, 1,212, 19, 62, 0,244,233,211,167, 65, 57,227, 25, 96,151,123,218,178, +119, 66,196, 36, 49, 49,209, 46,233,111,219,182, 13,169,169,169,144,143, 24,136, 3, 63,158, 2, 2, 3,128,170,154,123,222,135, +251, 15,156,244, 7, 54, 97,255,129,147, 30,145,119,243,189,214, 14,181,152,246, 11,203, 57, 61, 32,108,215,127, 82, 82, 14,226, +226,186,212,255,103, 16, 23,215,133,179, 18,240,241,151, 31, 99,229, 71,239, 96,100,183, 24,152,234,234, 96, 52, 25, 65,121, 83, + 0,188, 64, 64,227,230, 95, 37,232,213,182, 39,150,190,176, 20,239,164,189,195,201, 27,101, 61,217,197,134,110,179, 73,248,211, +167, 79, 39,174, 40, 1,114,185,156,236, 95,118, 0, 19,224, 25,210,150,203,229, 36, 45, 45, 13, 0,238,107, 37, 32, 57, 57, 57, +166,178,178,146,241,150,185,213,206,202,202, 74,102, 78,119, 73,142, 66,161, 40, 2, 48, 11,192, 41, 0,159, 2, 24, 3, 96, 60, +128,127,179, 20,128, 91,205,209, 79,236,227,158, 1,224,235,175, 27,107,240, 95,127,253, 53, 8, 33,152, 52,105, 18,197, 87,222, +198,141, 27, 71, 89,230, 57, 2,128, 10, 9, 9,177, 75,252,214, 72, 74, 49,115,204,166,212,197, 54, 63,111,160, 0,164,166,166, + 58, 12, 2,100,191,183,254,220, 81, 16, 2,163, 84,204,159, 63, 95,157,146,146, 2,235,131,114,172, 15,207, 81,169, 84,142,210, + 23, 82, 28,202,154,245,161,250,234,171,175,236, 18,191, 69,209,170, 39,255,197,139, 23,115,146,249,103, 81, 49, 52,187,151, 67, + 58,251,191,232, 24,254, 0,218,183,246, 67,209,238, 34, 51,249, 7,181, 48, 47, 1,248,120,241,110,107, 92, 92,156,140,189, 12, + 96,121,207, 75, 6, 77,128,176, 0,224,195, 25,192,115,219,128,182,254,192,197, 10,219,229,231,239,240,107,159, 61, 69,142,143, +215,230,237,183,223,182, 75,252, 0,144, 54,107, 34,214, 29, 60,142,144,136, 14, 40,189,122,211,169,245, 15, 0, 28,189, 0,156, +189, 4,102, 11, 95, 97,211,210,231,178,254,111, 11,105, 95,120, 54,201, 39, 67,250,204,127,125, 92, 87,136,179, 11, 56,127,191, + 86, 91,139, 17,211,135,171,163, 59, 12, 69,157, 70, 3,111, 95, 95,120,123,223,157,130,138, 10, 10,176, 39, 43,235,250,236,103, +103,117,236,236, 27,134,129,143, 14, 24, 45,213, 5,198,124,242,241, 39,188,172,198,119,247,207,194,247,223,127, 15,160, 97,219, +118,236,216, 65,241, 85, 2, 24,242, 71,231,181,216,191,236, 85,183,149, 0,185, 92, 78,210,211,211,209,189,123,119,172, 91,183, + 14,115,231,206,189,239,148, 0, 43,226,247,136, 60, 70,150, 27,222, 4, 25,128, 71, 1,108, 3, 80, 3, 32, 4,192,239, 0,174, +226,110,238,135,102,129,245,113,207,108,183,189,181, 11, 63, 33, 33,129, 56,115,225,239,223,191,191,193,146,241,158, 61,123,212, +108,171,159,171, 66,204,144, 63,243,122, 83,234,226, 70, 94,128,123,146, 7,128,181,246,138,162,162, 34,180,107,215,174,145,130, +192,148,149,149,149,113,205,115,239, 44, 24,144,243,132,249,248,227,143, 55,217,181,179, 9,204,150,213,111, 33, 33, 91,109,111, + 0, 45,138, 81, 51,121, 40, 72,224, 2, 96,244, 50,212,224, 75, 96,243, 73,139,102,182, 0, 62,207,172,131,209,200, 63,209, 89, +118,118,118, 30,187,159,248,146, 63, 0,148,125, 2,188,181, 17,120,160, 19,112,115,175, 24, 25, 91,244,152,181,221,126, 57, 47, +243,158,120,150,196,216,193,126, 55,190, 94,133,192, 72, 9,164,221, 94,193, 87,171,158, 67,255, 62, 33,232, 49,241, 29, 78,227, +193,165,233, 60,150, 10, 40, 0,196,138,252, 41,134,248, 93, 89,215,231,106,225,115,129, 62,174,171,205,242, 28, 43, 79,128, 51, +220, 40,187,129,177,137, 99, 17,216, 34, 24, 38,202,136,195,223,255,128,234,154, 26,196,197,199,227,175,178, 50,236,204,220,133, + 57,207,206,234,232, 43,241,133,136,248, 96,220, 67,227,114,127, 87,175,115, 73,161,191,115,231,142,219,215,205, 38,127, 0,110, + 43, 1,114,185,156,172, 88,177, 2, 93,187,154,251,179, 75,151, 46,184,159, 60, 1,158, 38,126, 27,214, 63,243,218,149,107,237, +109,121, 38,125, 0,248, 3,136, 4,112, 1, 64, 71, 0, 85, 0, 42, 60,240,204,186, 4,235,227,158,231,204,153, 83, 95,198,184, +240,153,185,140,139,103,218,222,114, 1,155,252,185, 40, 2, 92,112,207, 87,242, 20, 7, 0, 0, 9,178, 73, 68, 65, 84, 18, 1, +181,107,215, 78,150,152,152,216,104, 41,192,114,182, 61, 0,240,142, 17,176, 23, 12,232,200,114,180,167,160, 52, 5, 24,235,222, +158,187,159,171,245, 15, 0, 7,151,172, 64,220,202,247, 97, 28, 61, 2,222, 0,164,199, 10,240, 77, 97, 57, 0,192, 56,122, 46, + 12,191,182, 1,213,246,223,188, 73,138,135,151,197, 46,202, 39,125,137,185,207, 94,195,165, 23, 22, 65,243,173, 30, 33,109, 28, +151,123,194, 3,224,138,114,176,109,219, 54,179, 54, 28,247, 8,142,151,148, 33,176,127, 32,174,231, 20, 2, 18, 95, 76,157,251, + 12, 90,117,154,216,156,243,175,189,168,127,143,120,181, 28,237, 16,112, 22, 59,144,147,148,131,113,155,198, 97,106, 38,144,148, + 99,126,157,147,148,195,219, 11, 80,163,171, 70, 27,191,214, 48,234,106, 65, 68, 4,131,135, 12,193,238,221,187,117,233,239,191, + 47,161, 9,193, 83, 51,158, 66,171,214,173, 80, 91, 83, 3,163,201,136, 64,159, 22, 48,136, 12, 46, 93,111, 69, 69, 69,131,221, + 1,124, 3, 2, 27,145, 63, 3, 23,149, 0,185, 92, 78, 82, 82, 82, 48,100,200,144, 6,229,125,250,244,193,187,239,190,219,172, + 74, 64, 83, 17,191,181,245, 15, 0, 37, 37, 37,174,122, 1,126,130,121,189,191, 10,102,215,255, 88, 0,151, 1,244, 3,144, 5, + 96, 43, 0,135, 55,139, 82,169, 20, 41, 20, 10,143,167,131,102,187,236, 89,129,122,245,159,179,151, 4, 74, 75, 75, 99,156, 29, +244, 69, 8,161, 24,130,103,187,250, 19, 18, 18,108,150,123, 82, 1, 32, 86,164, 72,120,126,238, 16, 17, 17, 17,245,164, 31, 29, + 29, 45, 99, 98, 3, 24,239, 64, 68, 68,132,154, 89, 46,104,174,137,215,147,112,182,214,207,178,254,157, 98,202,198, 76,144,248, +112,220, 28,246, 16, 90, 99, 4,252,166,174,131,241,198, 95, 64, 80, 11,120,151,127,137,189,233,249,128,151,151, 43,215,238,182, + 38,121,230,181,127, 97,208, 0, 32, 98,238, 57, 68, 74,159,197,239, 15, 38, 2, 31, 46,178, 91,222, 92, 30,128,212,212, 84,140, + 28,220, 3,163, 71,116, 71, 92,223, 69, 88,147,190, 1, 23,242,175,227,133, 81,131, 80,154,181, 31,149,119,170, 60,117, 63,216, + 90, 42,112, 74,208,108,194,247, 36,249,219,145,201, 9,197,197,197, 84, 88, 88, 24,153,154,217, 80, 33, 0,128,113,155,198, 65, +156, 93,128,236,236,194,250,157, 0,236, 92, 1,182,110, 55,154,166, 97,162, 1, 66, 27,225,235, 39,193,140,167,159,150,188,245, +230,155,104,223,190, 61,221, 49, 36, 68,164,211,212,192, 68, 0, 66,155, 64,211,206,231,234,140,140, 12,106,204,152, 49,164,188, +188, 28, 85, 85, 85, 13, 20, 71,171,221, 1,156,119, 5,200,229,114,178,230,185,243,128,164, 43, 80,250, 81,227, 10,146,174, 88, +243,220,121,128,163, 18, 32,151,203, 73, 66, 66,130,172, 79,159, 62,234,242,242,242, 70,159,135,133,133, 33, 33, 33, 65,134,251, + 60, 38,192, 93,235,223, 77, 47, 0, 91, 97,232, 0,224, 12,128,201, 0, 56, 31,101,218, 20,228, 15, 56, 94, 2,176, 97,204,228, + 57,187,246,248,248,120,194,124, 63, 62, 62,158, 88,203,219,178,101, 11,226,227,227, 9,223, 93, 1, 92, 20, 0, 62,137,128,108, +125,110, 19,137,137,137, 54,189, 0, 12,217,183,107,215, 78,150,146,146,162,102,214,100, 19, 19, 19, 29, 6, 21, 58,178, 14, 93, +216, 95,223, 36,219, 0, 25,235,222, 81, 48, 32, 31, 20,190,151, 4,159,169,235,160, 45,185, 4,239, 99,235, 96,200,156, 11,106, +194,106,236,249,247, 52, 92,221,115, 5,113,105,159, 2,222,205,147,217,121,145, 10,200, 73,219,141,200,171,227,128, 91, 26, 44, + 28,179,200, 97,185, 39, 60, 0,174, 90,255, 89,187, 87,192,171, 99,111, 72,209, 29,197,223,111, 66, 53, 69,240,243,165,107, 24, +125,238, 58,167,230,124,251,173,220, 46,217, 3,128,229,115,155,245,184,146,191,157,123,212, 45, 98,240,196, 14,129,164,156,187, +196, 15,160,145,229,207, 4, 12,102,103, 23,218,252,126,160, 95, 32, 74, 42, 75, 48,164,243, 80,104,235,116,128, 86, 7,163,222, +128,165, 41, 41,160, 68, 16,213,106,106, 64,211, 38, 24, 77, 4,190,222, 62,248,171,230, 47,248,152,156,239, 54,254,230,155,111, +234,175,109,230,204,153,132,153,111,216,187, 3,110,220,184,193,249, 58,205, 36,108, 86, 2,122,133, 55,254,253,139, 87,244,152, +191, 57, 18, 92,201,218, 82,143, 12, 25, 50, 4, 97, 97, 97,141, 62, 63,119,238, 28,178,178,178,212,205, 69,254, 22,107,156, 98, + 60, 1, 37, 37, 37, 77, 98,253,123,192, 11,192, 96,172,133, 72,235,238, 7, 37,199,209, 18, 0,187,156,239, 18,128,167,150, 20, +248, 40, 0, 77, 2,198,242, 7,128,232,232,104,153, 74,165, 82, 51,174,127, 59,202,129,236,242,229,203,206, 98, 1, 40,142,101, + 30,181, 50,185,118, 56, 99,253,219, 34,126, 70,209,225,211,222, 51,133,229, 48,252,250, 22,110,226, 71,132, 76, 88, 13, 84, 86, +161,112,211, 2,116, 73, 94,139,210,173, 11, 0, 31,111, 64,212, 60,153,157,139, 53, 64,175,118,147, 57,151, 55,135, 7, 32, 53, + 53,181,102,250,232,161, 55, 90,210,193, 15,212,194, 71,146,185,118, 46,214,239, 61,141,133,227, 31,198,172,247,191,192,180,255, +247,127, 77,234, 13,114,116,137, 89, 95, 43, 97, 73, 2, 68,185,171,156,186,227,234,119,228, 5, 72,202,201, 33,182,200,159,109, +253, 59, 67,104,187, 80, 28, 60,156,131,225, 15, 12,135,127,128, 20, 52, 77, 32, 34, 70,208, 20, 5, 66, 8, 76, 4, 48,210, 4, + 70,163, 17,218, 74, 13,246,253,178, 15, 98,147,152,247,214, 97,235, 93, 1,175,207, 29,129,216,208, 34, 80,135,184,203,176,167, + 4,240, 37,127,107, 37, 32, 45, 45, 13, 29, 58,116,184,171,216, 23, 22, 34, 53, 53, 21,247,131,229,239,105, 69,192,150,245,239, +166, 23, 0, 0, 98, 0, 60, 8,224, 13, 52,115,240, 31, 3,165, 82,217,224, 30, 45, 45, 45,133, 82,169,116,228,137,112, 42,143, +189,164, 80, 90, 90, 26,163, 84, 42, 41, 0,164,180,180,148,218,184,113, 35, 97,121,111, 41,133, 27,219,224,239,137, 2, 96, 29, +245,111, 73, 86,211, 72, 57, 96,191,118,211,130,231,125, 99,121,112, 27,160, 77,235,223, 85,226,103, 48,101,213, 86,236, 2, 48, +126,101, 44,136,106, 1,168,199,215,224, 76, 97, 57,168, 86,193, 40,248,179,202,108,253,243, 95, 2,240, 8,236,237,247,119, 39, + 15, 0, 23,133,139,171,114,176,109,219, 54, 61,128,234,231, 98,250, 85,189,178,250,191,250, 37, 75, 83,116,109, 91,180, 43, 63, +127,161,184,253,172, 11, 95, 72,209,204,187, 70, 28,144, 51,123,137,134,231,142, 2,207,195, 22,249, 51,150, 63, 0,167, 1,129, +243,230,205,163,134, 63, 54, 60, 94, 61, 34, 47, 43,177,239, 52, 84,233,170, 64,137, 0,115, 74, 17, 26, 38, 19, 1,109, 52, 34, +192, 55, 16, 71, 43, 79,225,242,177, 2,236, 84,238,204,115,187,225,133,207, 3,224,191, 13,176,129, 18,208,161, 24, 23,111,132, +185, 68,254,214, 74,192,186,117,235, 16, 20, 20,132,242,242,114,172, 88,177, 2,247,155,219,223, 19,138,128, 61,235,223, 69, 47, + 64,123,152,163,254, 69, 0, 6, 2,152, 15,160,240,126,233, 47,133,101, 43,186,167, 96,189,164,176,103,207,158,239,155,170,237, +247, 36, 15,128, 61,143,192,154, 53,107,100,214,138, 66, 98, 98,162,154,239, 69,176,137,224,126, 72,177,203,182,254,173,183,255, + 89,250,151,221,175,156, 27,204, 40, 1,147, 87,126, 2,146, 9,180,153,165, 68,222, 43,211,240,112,234,231,128,143, 15, 2, 36, +226,102,185, 94,246, 30,127, 91,175, 93,204, 3, 96, 4, 32,178,140,173,200,205,241,184, 57,125,244,208,146, 87, 54,101,135, 47, +157, 51,182, 69,104, 72,140, 30,192,217,196,196,196,150, 48, 31, 37,235,210,120, 48,183,220,183,223,202,153,136,127, 87,148, 59, +202,153, 5,207,135,208,155, 42, 25,144, 61, 88,147, 62,227, 17,104,213,170,149, 77,237,236,232,183, 71,247,132,245,124, 0,166, +233,198,179,143, 62,240,104,191,214,129,173,161, 51,232, 64, 8,129,216, 91,140, 10,109, 45,142,255,249, 45,182,125,150, 1, 89, +111,153,108, 39,118,186,221,198,119,247,207, 66, 70, 70, 6, 46, 95,230,159, 3,224,174, 18, 0,183,200,159, 45,111,238,220,185, + 36, 45, 45, 13,139, 22, 45,194,253,188,230,207, 86, 4,242,242,242, 92,250,174,163, 58, 60,100, 38,192,188,223, 95, 7,224, 53, + 0,191, 0, 48,225, 31, 10,235, 37, 0,190, 24, 48, 96, 0, 78,159, 62,141, 77,169,139, 27,229, 1,112,152, 8,168,169,242, 0, +216,242, 8,216, 35,122, 23,189, 0,110,161,169,182, 1, 50, 3,168, 84, 42,145,155,155, 75, 23, 21, 21,177,137, 76,166, 82,169, +120,107,142, 83, 86,109, 5, 88,137,127, 30, 93,186,177,254,181,166,121,238, 87,167,119, 41, 77, 92,234,187,116, 0,183, 97,222, +254, 51,195,205, 54,150, 62, 23,211,175,110, 76,238, 79, 45,158,122,243, 83, 40,149, 74,113,110,110,110, 7, 52, 76,103,237,210, +120, 52,181, 39,192, 89,126,127,167, 51,103, 19, 44, 9,216, 35,127,125, 92, 87, 32,219,185, 97,182,253,163, 29, 84,128,151,148, + 28, 11, 59,142, 17, 67, 71,160, 99, 96, 71,128, 38,248, 75, 87,142,163, 39,143,162,244,124, 41, 70,245, 26, 37,123,249,229,151, +155,125, 60,216, 74,128,167,200,154,241, 4,252, 93, 2,254,220,205, 2,232, 1,108,178,252,253, 79,192,122, 73,193, 29, 23,191, +189, 4, 64, 54, 21,128,166,194,252,249,243,109,146,189,213, 73,108,108,168, 29, 36, 2,178, 75,180,174,162, 41,182, 1,166,166, +166, 66,169, 84, 26,115,115,115,189, 45, 75, 7, 12,249,143,114,112,221, 54, 97, 57, 76, 73,221, 4, 67, 67, 28,148, 83,205,116, +243,251, 90,238,203,101,150, 34,147, 66,161,120,218, 77,177,190, 99,222,248, 56, 95,169, 84, 62,146,155,155,139,220,220, 92, 29, + 0,137,229,207, 19,196, 79,185,147, 26,216, 25,201, 39, 76, 82, 52, 24, 47,190,196,237,137, 37,129,226,226, 98, 42, 39, 41,135, +132,206, 13,149,161,179,237, 58, 37, 73, 57,106,174,241, 0, 91, 62,216, 66,173, 93,187, 54,102,235,202,173, 8,235,250,160, 26, + 0,126, 63,247,155,108,226,152, 56,164,111, 72,207,219,142,237, 46,181, 51, 35, 35,131, 26, 59,118,108,163, 93, 1, 6,131,193, +173,235,247, 52, 89,255,211,162,253,239, 3,210,164, 20, 10, 5,249, 39, 92,139, 39,150, 20, 24, 47,128,117, 25,103, 5,192,153, + 37,206,195, 82,119,245, 70, 39, 77, 44,223, 83,223,183, 41, 47, 49, 49,145,228,230,230,122,179,251,139,237, 97,225,169,160,228, + 53, 17, 33,223,143,147, 80, 32,128, 26,115, 66,126,138, 2,224, 7, 39,251,123, 57,142,199, 31,185,185,185,204, 54,160,170,136, +136,136,182,169,169,169,190,247, 67, 95, 54,165,219,222,147,178,139,139,139,169,226,133,197, 30,235, 3, 86,158,255,250,239, 29, +253,238,152,219,237, 60,116,232,144, 64,174,255,112,178,103,115,152, 66,161, 48,120,146,252,149, 74,101,144, 66,161,168,248,187, +247, 19, 23, 35,154,114,245, 28, 97, 1, 2, 4, 8, 16, 32, 64,192,223, 23, 34,161, 11, 4, 8, 16, 32, 64,128, 0, 65, 1, 16, + 32, 64,128, 0, 1, 2, 4,252, 15,224,255, 3, 40, 50, 24,122,163,191,209,130, 0, 0, 0, 0, 73, 69, 78, 68,174, 66, 96,130, 0}; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 5d2593b46bb..5aec47965fc 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1619,6 +1619,18 @@ static void build_uvlayer_menu_vars(CustomData *data, char **menu_string, } } +void set_wave_uvlayer(void *arg1, void *arg2) +{ + WaveModifierData *wmd=arg1; + CustomDataLayer *layer = arg2; + + /*check we have UV layers*/ + if (wmd->uvlayer_tmp < 1) return; + layer = layer + (wmd->uvlayer_tmp-1); + + strcpy(wmd->uvlayer_name, layer->name); +} + void set_displace_uvlayer(void *arg1, void *arg2) { DisplaceModifierData *dmd=arg1; @@ -1896,6 +1908,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco y -= 18; if (!isVirtual && (md->type!=eModifierType_Collision)) { + uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */ + uiBlockBeginAlign(block); if (md->type==eModifierType_ParticleSystem) { but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Convert", lx,(cy-=19),60,19, 0, 0, 0, 0, 0, "Convert the current particles to a mesh object"); @@ -1911,6 +1925,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_copyModifier, ob, md); } uiBlockEndAlign(block); + + uiSetButLock(ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); } lx = x + 10; @@ -2246,7 +2262,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco 0.0, 1.0, 0, 0, "Set the UV layer to use"); MEM_freeN(strtmp); i = CustomData_get_layer_index(fdata, CD_MTFACE); - uiButSetFunc(but, set_displace_uvlayer, wmd, + uiButSetFunc(but, set_wave_uvlayer, wmd, &fdata->layers[i]); } if(wmd->texmapping == MOD_DISP_MAP_OBJECT) { @@ -2613,7 +2629,7 @@ static void editing_panel_modifiers(Object *ob) block= uiNewBlock(&curarea->uiblocks, "editing_panel_modifiers", UI_EMBOSS, UI_HELV, curarea->win); if( uiNewPanel(curarea, block, "Modifiers", "Editing", 640, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock((ob && ob->id.lib), ERROR_LIBDATA_MESSAGE); uiNewPanelHeight(block, 204); uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier"); @@ -6350,6 +6366,11 @@ static void editing_panel_mesh_uvautocalculation(void) row= 180; uiDefButBitS(block, TOGN, UVCALC_NO_ASPECT_CORRECT, B_NOP, "Image Aspect",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Scale the UV Unwrapping to correct for the current images aspect ratio"); + + row-= butHB+butS; + uiDefButBitS(block, TOG, UVCALC_TRANSFORM_CORRECT, B_NOP, "Transform Correction",100,row,200,butH,&G.scene->toolsettings->uvcalc_flag, 0, 0, 0, 0, "Correct for UV distortion while transforming, (only works with edge slide now)"); + + row= 180; uiBlockBeginAlign(block); uiDefButF(block, NUM,B_UVAUTO_CUBESIZE ,"Cube Size:",315,row,200,butH, &G.scene->toolsettings->uvcalc_cubesize, 0.0001, 100.0, 10, 3, "Defines the cubemap size for cube mapping"); diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 2dd6d705a9e..e16443460a1 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1054,10 +1054,10 @@ static void draw_default_sensor_header(bSensor *sens, (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, &sens->invert, 0.0, 0.0, 0, 0, "Invert the level (output) of this sensor"); - uiDefButS(block, TOG, 1, "Lvl", - (short)(x + 10 + 0.70 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, + uiDefButS(block, TOG, 1, "Level", + (short)(x + 10 + 0.65 * (w-20)), (short)(y - 19), (short)(0.20 * (w-20)), 19, &sens->level, 0.0, 0.0, 0, 0, - "Level detector versus edge detector (only applicable in case of logic state transition)"); + "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); } static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) @@ -1270,15 +1270,15 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short if(ps->type == SENS_PROP_INTERVAL) { uiDefBut(block, TEX, 1, "Min: ", xco,yco-92,width/2, 19, - ps->value, 0, 31, 0, 0, "test for min value"); + ps->value, 0, 31, 0, 0, "check for min value"); uiDefBut(block, TEX, 1, "Max: ", xco+width/2,yco-92,width/2, 19, - ps->maxvalue, 0, 31, 0, 0, "test for max value"); + ps->maxvalue, 0, 31, 0, 0, "check for max value"); } else if(ps->type == SENS_PROP_CHANGED); else { uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-92,width-60, 19, - ps->value, 0, 31, 0, 0, "test for value"); + ps->value, 0, 31, 0, 0, "check for value"); } yco-= ysize; @@ -1390,9 +1390,14 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short &raySens->propname, 0, 31, 0, 0, "Only look for Objects with this property"); } - + + /* X-Ray option */ + uiDefButBitS(block, TOG, SENS_RAY_XRAY, 1, "X", + xco + 10,yco - 68, 0.10 * (width-20), 19, + &raySens->mode, 0.0, 0.0, 0, 0, + "Toggle X-Ray option (see through objects that don't have the property)"); /* 2. sensing range */ - uiDefButF(block, NUM, 1, "Range", xco+10, yco-68, 0.6 * (width-20), 19, + uiDefButF(block, NUM, 1, "Range", xco+10 + 0.10 * (width-20), yco-68, 0.5 * (width-20), 19, &raySens->range, 0.01, 10000.0, 100, 0, "Sense objects no farther than this distance"); @@ -1439,10 +1444,13 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short draw_default_sensor_header(sens, block, xco, yco, width); joy= sens->data; - + + uiDefButS(block, NUM, 1, "Index:", xco+10, yco-44, 0.6 * (width-120), 19, + &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, + "Specify which joystick to use"); str= "Type %t|Button %x0|Axis %x1|Hat%x2"; - uiDefButS(block, MENU, B_REDR, str, xco+10, yco-44, 0.6 * (width-20), 19, + uiDefButS(block, MENU, B_REDR, str, xco+87, yco-44, 0.6 * (width-150), 19, &joy->type, 0, 31, 0, 0, "The type of event this joystick sensor is triggered on."); @@ -1639,6 +1647,16 @@ char *get_state_name(Object *ob, short bit) return (char*)""; } +static void check_state_mask(void *arg1_but, void *arg2_mask) +{ + unsigned int *cont_mask = arg2_mask; + uiBut *but = arg1_but; + + if (*cont_mask == 0 || !(G.qual & LR_SHIFTKEY)) + *cont_mask = (1<retval); + but->retval = B_REDR; +} + static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, short xco, short yco, short width) { bSoundActuator *sa = NULL; @@ -1666,6 +1684,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh int myline, stbit; uiBut *but; + /* yco is at the top of the rect, draw downwards */ uiBlockSetEmboss(block, UI_EMBOSSM); set_col_actuator(act->type, 0); @@ -1857,7 +1876,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE, "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19, &ia->flag, 0, 0, 0, 0, - "Convert Ipo to force. Force is applied in global or local coordinate according to Local flag"); + "Apply Ipo as a global or local force depending on the local option (dynamic objects only)"); uiButSetFunc(but, change_ipo_actuator, but, ia); but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD, @@ -1883,12 +1902,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh else { uiDefButI(block, NUM, 0, "Sta", xco+10, yco-44, (width-80)/2, 19, - &ia->sta, 0.0, MAXFRAMEF, 0, 0, - "Start frame, (subtract 1 to match blenders frame numbers)"); + &ia->sta, 1.0, MAXFRAMEF, 0, 0, + "Start frame"); uiDefButI(block, NUM, 0, "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, - &ia->end, 0.0, MAXFRAMEF, 0, 0, - "End frame, (subtract 1 to match blenders frame numbers)"); + &ia->end, 1.0, MAXFRAMEF, 0, 0, + "End frame"); } uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, "Child", xco+10+(width-80), yco-44, 60, 19, @@ -1917,7 +1936,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property"); } else { - uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value"); + uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value, use \"\" around strings"); } yco-= ysize; @@ -2022,7 +2041,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh if(eoa->type==ACT_EDOB_ADD_OBJECT) { int wval; /* just a temp width */ - ysize = 72; + ysize = 92; glRects(xco, yco-ysize, xco+width, yco); uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); @@ -2042,9 +2061,27 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-68, wval, 19, eoa->linVelocity+2, -100.0, 100.0, 10, 0, "Velocity upon creation, z component."); - uiDefButBitS(block, TOG, 2, 0, "L", xco+45+3*wval, yco-68, 15, 19, + uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_LINV, 0, "L", xco+45+3*wval, yco-68, 15, 19, &eoa->localflag, 0.0, 0.0, 0, 0, "Apply the transformation locally"); + + + uiDefBut(block, LABEL, 0, "AngV", xco, yco-90, 45, 19, + NULL, 0, 0, 0, 0, + "Angular velocity upon creation."); + uiDefButF(block, NUM, 0, "", xco+45, yco-90, wval, 19, + eoa->angVelocity, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, x component."); + uiDefButF(block, NUM, 0, "", xco+45+wval, yco-90, wval, 19, + eoa->angVelocity+1, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, y component."); + uiDefButF(block, NUM, 0, "", xco+45+2*wval, yco-90, wval, 19, + eoa->angVelocity+2, -10000.0, 10000.0, 10, 0, + "Angular velocity upon creation, z component."); + uiDefButBitS(block, TOG, ACT_EDOB_LOCAL_ANGV, 0, "L", xco+45+3*wval, yco-90, 15, 19, + &eoa->localflag, 0.0, 0.0, 0, 0, + "Apply the rotation locally"); + } else if(eoa->type==ACT_EDOB_END_OBJECT) { @@ -2095,7 +2132,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh /* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */ /* coa->flag &= ~(63); */ str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4"; - coa->flag &= ~(7); + coa->flag &= 7; coa->time = 0; uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, ""); @@ -2270,13 +2307,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file"); uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation"); } -*/ else if (gma->type == ACT_GAME_RESTART) - { - ysize = 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (gma->type == ACT_GAME_QUIT) +*/ else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) { ysize = 28; glRects(xco, yco-ysize, xco+width, yco); @@ -2284,7 +2315,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh } //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3"; - str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3"; + str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save GameLogic.globalDict %x4|Load GameLogic.globalDict %x5"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); yco -= ysize; @@ -2324,7 +2355,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh visAct = act->data; - str= "Visibility %t|Visible %x0|Invisible %x1"; + str= "Visibility %t|Visible %x0|Invisible %x1|Visible Recursive %x2|Invisible Recursive %x3"; uiDefButI(block, MENU, B_REDR, str, xco + 10, yco - 24, width - 20, 19, &visAct->flag, @@ -2360,10 +2391,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh for (wval=0; wval<15; wval+=5) { uiBlockBeginAlign(block); for (stbit=0; stbit<5; stbit++) { - uiDefButBitI(block, TOG, (1<<(stbit+wval)), 0, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(wval+stbit))); + but = uiDefButBitI(block, TOG, 1<<(stbit+wval), stbit+wval, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval))); + uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); } for (stbit=0; stbit<5; stbit++) { - uiDefButBitI(block, TOG, (1<<(stbit+wval+15)), 0, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(wval+stbit+15))); + but = uiDefButBitI(block, TOG, 1<<(stbit+wval+15), stbit+wval+15, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval+15))); + uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); } } uiBlockEndAlign(block); @@ -2816,144 +2849,202 @@ void buttons_enji(uiBlock *block, Object *ob) void buttons_ketsji(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); + uiDefButBitI(block, TOG, OB_COLLISION, B_REDR, "Physics", + 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that have a physics representation"); + if (ob->gameflag & OB_COLLISION) { + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are evaluated by the engine "); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,185,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use Fh settings in Materials"); - uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,185,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use face normal to rotate Object"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 110, 185, 80, 19, - &ob->mass, 0.01, 10000.0, 10, 0, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 190, 185, 80, 19, - &ob->inertia, 0.01, 10.0, 10, 0, - "Bounding sphere radius"); - uiDefButF(block, NUM, B_DIFF, "Form:", 270, 185, 80, 19, - &ob->formfactor, 0.01, 100.0, 10, 0, - "Form factor"); + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); - uiDefButF(block, NUM, B_DIFF, "Damp:", 10, 165, 100, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUM, B_DIFF, "RotDamp:", 110, 165, 120, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); - uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", - 230, 165, 120, 19, - &ob->gameflag, 0.0, 1.0, 10, 0, - "Enable anisotropic friction"); + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + + uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,145,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use Fh settings in Materials"); + uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,145,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use face normal to rotate Object"); + uiDefButF(block, NUM, B_DIFF, "Form:", 110, 145, 120, 19, + &ob->formfactor, 0.01, 100.0, 10, 0, + "Form factor"); + + uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", + 230, 145, 120, 19, + &ob->gameflag, 0.0, 1.0, 10, 0, + "Enable anisotropic friction"); + } + + if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { + uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 125, 114, 19, + &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the x-direction."); + uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 125, 113, 19, + &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the y-direction."); + uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 125, 113, 19, + &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the z-direction."); + } } - if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { - uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 145, 114, 19, - &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the x-direction."); - uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 145, 113, 19, - &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the y-direction."); - uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 145, 113, 19, - &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the z-direction."); + if (!(ob->gameflag & OB_GHOST)) { + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 105, 75, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + if (ob->gameflag & OB_BOUNDS) { + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static TriangleMesh %x4", + 85, 105, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,105,100,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); + } + uiBlockEndAlign(block); } } +} - if (!(ob->gameflag & OB_GHOST)) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", - 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); - } - uiBlockEndAlign(block); +static void check_actor(void *arg1_but, void *arg2_object) +{ + int *gameflag = arg2_object; + /* force enabled ACTOR for body >= dynamic */ + if (*gameflag & OB_DYNAMIC) + *gameflag |= OB_ACTOR; +} + +static void check_body_type(void *arg1_but, void *arg2_object) +{ + Object *ob = arg2_object; + + switch (ob->body_type) { + case OB_BODY_TYPE_NO_COLLISION: + ob->gameflag &= ~OB_COLLISION; + break; + case OB_BODY_TYPE_STATIC: + ob->gameflag |= OB_COLLISION; + ob->gameflag &= ~(OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY); + break; + case OB_BODY_TYPE_DYNAMIC: + ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_ACTOR; + ob->gameflag &= ~(OB_RIGID_BODY|OB_SOFT_BODY); + break; + case OB_BODY_TYPE_RIGID: + ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_RIGID_BODY|OB_ACTOR; + ob->gameflag &= ~(OB_SOFT_BODY); + break; + default: + case OB_BODY_TYPE_SOFT: + ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_SOFT_BODY|OB_ACTOR; + ob->gameflag &= ~(OB_RIGID_BODY); + break; } } void buttons_bullet(uiBlock *block, Object *ob) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); + uiBut *but; + /* determine the body_type setting based on flags */ + if (!(ob->gameflag & OB_COLLISION)) + ob->body_type = OB_BODY_TYPE_NO_COLLISION; + else if (!(ob->gameflag & OB_DYNAMIC) || !(ob->gameflag & OB_DYNAMIC)) + ob->body_type = OB_BODY_TYPE_STATIC; + else if (!(ob->gameflag & (OB_RIGID_BODY|OB_SOFT_BODY))) + ob->body_type = OB_BODY_TYPE_DYNAMIC; + else if (ob->gameflag & OB_RIGID_BODY) + ob->body_type = OB_BODY_TYPE_RIGID; + else + ob->body_type = OB_BODY_TYPE_SOFT; + + uiBlockBeginAlign(block); + but = uiDefButS(block, MENU, REDRAWVIEW3D, + "Object type%t|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3|Soft body%x4", + 10, 205, 150, 19, &ob->body_type, 0, 0, 0, 0, "Selects the type of physical representation of the object"); + uiButSetFunc(but, check_body_type, but, ob); + + if (ob->gameflag & OB_COLLISION) { + but = uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 160,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are detected by the Near and Radar sensor"); + uiButSetFunc(but, check_actor, but, &ob->gameflag); + + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 215,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 170, 19, - &ob->mass, 0.01, 10000.0, 10, 2, - "The mass of the Object"); + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 180, 185, 170, 19, - &ob->inertia, 0.01, 10.0, 10, 2, - "Bounding sphere radius"); + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius, not used for other bounding shapes"); uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + } + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + if ((ob->gameflag & (OB_ACTOR|OB_DYNAMIC)) == (OB_ACTOR|OB_DYNAMIC)) { + if (ob->margin < 0.001f) + ob->margin = 0.06f; + uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, + &ob->margin, 0.001, 1.0, 1, 0, + "Collision margin"); + } else { + uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, + &ob->margin, 0.0, 1.0, 1, 0, + "Collision margin"); + } + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 115, 105, 55, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + if (ob->gameflag & OB_BOUNDS) { + uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static Mesh%x4", + //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", + 170, 105, 105, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 275,105,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); } } uiBlockEndAlign(block); - - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", - //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", - 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); - } - uiBlockEndAlign(block); -} - -static void check_object_state(void *arg1_but, void *arg2_mask) -{ - unsigned int *cont_mask = arg2_mask; - uiBut *but = arg1_but; - - if (*cont_mask == 0 || !(G.qual & LR_SHIFTKEY)) - *cont_mask = (1<retval); - but->retval = B_REDR; } static void check_controller_state_mask(void *arg1_but, void *arg2_mask) @@ -3079,6 +3170,9 @@ void logic_buts(void) int a, iact, stbit, offset; short xco, yco, count, width, ycoo; char *pupstr, name[32]; + /* pin is a bool used for actuator and sensor drawing with states + * pin so changing states dosnt hide the logic brick */ + char pin; wrld= G.scene->world; @@ -3109,7 +3203,7 @@ void logic_buts(void) uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 90, 340, 24, + uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 70, 340, 24, NULL, 0.0, 100.0, 100, 0, ""); @@ -3118,26 +3212,26 @@ void logic_buts(void) a= 0; prop= ob->prop.first; while(prop) { - but= uiDefBut(block, BUT, 1, "Del", 10, (short)(70-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); + but= uiDefBut(block, BUT, 1, "Del", 10, (short)(50-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); uiButSetFunc(but, del_property, prop, NULL); - uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(70-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); - but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(70-20*a), 110, 20, prop->name, 0, 31, 0, 0, ""); + uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(50-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); + but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(50-20*a), 110, 20, prop->name, 0, 31, 0, 0, "Available as GameObject attributes in the game engines python api"); uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1); if(prop->type==PROP_BOOL) { - uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); - uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); } else if(prop->type==PROP_INT) - uiDefButI(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); + uiDefButI(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); else if(prop->type==PROP_FLOAT) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); else if(prop->type==PROP_STRING) - uiDefBut(block, TEX, B_REDR, "", 220, (short)(70-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); + uiDefBut(block, TEX, B_REDR, "", 220, (short)(50-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); else if(prop->type==PROP_TIME) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); - uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(70-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); + uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(50-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); a++; prop= prop->next; @@ -3226,11 +3320,11 @@ void logic_buts(void) uiBlockBeginAlign(block); for (stbit=0; stbit<5; stbit++) { but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset), stbit+offset, "", (short)(xco+35+12*stbit+13*offset), yco, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset))); - uiButSetFunc(but, check_object_state, but, &(ob->state)); + uiButSetFunc(but, check_state_mask, but, &(ob->state)); } for (stbit=0; stbit<5; stbit++) { but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset+15)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+35+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); - uiButSetFunc(but, check_object_state, but, &(ob->state)); + uiButSetFunc(but, check_state_mask, but, &(ob->state)); } } uiBlockBeginAlign(block); @@ -3264,13 +3358,13 @@ void logic_buts(void) uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); uiBlockSetEmboss(block, UI_EMBOSSP); 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 mask"); + uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)"); uiBlockSetEmboss(block, UI_EMBOSSM); if(cont->flag & CONT_SHOW) { cont->otype= cont->type; - uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type"); - but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-166), 19, cont->name, 0, 31, 0, 0, "Controller name"); + 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-136), 19, cont->name, 0, 31, 0, 0, "Controller name"); uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); ycoo= yco; @@ -3280,9 +3374,9 @@ void logic_buts(void) 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, 100, 19, cont, 0, 0, 0, 0, "Controller type"); + but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, 19, cont, 0, 0, 0, 0, "Controller type"); uiButSetFunc(but, sca_move_controller, cont, NULL); - but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-166), 19, cont, 0, 0, 0, 0, "Controller name"); + but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-136), 19, cont, 0, 0, 0, 0, "Controller name"); uiButSetFunc(but, sca_move_controller, cont, NULL); ycoo= yco; } @@ -3339,18 +3433,26 @@ void logic_buts(void) sens= ob->sensors.first; while(sens) { if (!(G.buts->scaflag & BUTS_SENS_STATE) || - sens->totlinks == 0 || /* always display sensor without links so that is can be edited */ - is_sensor_linked(block, sens)) { + (sens->totlinks == 0) || /* always display sensor without links so that is can be edited */ + (sens->flag & SENS_PIN && G.buts->scaflag & BUTS_SENS_STATE) || /* states can hide some sensors, pinned sensors ignore the visible state */ + (is_sensor_linked(block, sens)) + ) { + /* should we draw the pin? - for now always draw when there is a state */ + pin = (G.buts->scaflag & BUTS_SENS_STATE && (sens->flag & SENS_SHOW || sens->flag & SENS_PIN)) ? 1:0 ; + sens->flag |= SENS_VISIBLE; uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, SENS_DEL, B_DEL_SENS, ICON_X, xco, yco, 22, 19, &sens->flag, 0, 0, 0, 0, "Delete Sensor"); + if (pin) + uiDefIconButBitS(block, ICONTOG, SENS_PIN, B_REDR, ICON_PIN_DEHLT, (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_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &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-124), 19, sens->name, 0, 31, 0, 0, "Sensor name"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens->name, 0, 31, 0, 0, "Sensor name"); uiButSetFunc(but, make_unique_prop_names_cb, sens->name, (void*) 0); sens->otype= sens->type; @@ -3362,7 +3464,7 @@ void logic_buts(void) 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, ""); uiButSetFunc(but, sca_move_sensor, sens, NULL); - but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-124), 19, sens, 0, 31, 0, 0, ""); + but= uiDefBut(block, LABEL, 0, sens->name, (short)(xco+102), yco, (short)(width-(pin?146:124)), 19, sens, 0, 31, 0, 0, ""); uiButSetFunc(but, sca_move_sensor, sens, NULL); } @@ -3411,16 +3513,22 @@ void logic_buts(void) while(act) { if (!(G.buts->scaflag & BUTS_ACT_STATE) || !(act->flag & ACT_LINKED) || /* always display actuators without links so that is can be edited */ - (act->flag & ACT_VISIBLE)) { /* this actuator has visible connection, display it */ + (act->flag & ACT_VISIBLE) || /* this actuator has visible connection, display it */ + (act->flag & ACT_PIN && G.buts->scaflag & BUTS_ACT_STATE)) { + + pin = (G.buts->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 */ uiBlockSetEmboss(block, UI_EMBOSSM); uiDefIconButBitS(block, TOG, ACT_DEL, B_DEL_ACT, ICON_X, xco, yco, 22, 19, &act->flag, 0, 0, 0, 0, "Delete Actuator"); - uiDefIconButBitS(block, ICONTOG, ACT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &act->flag, 0, 0, 0, 0, "Actuator settings"); - + if (pin) + uiDefIconButBitS(block, ICONTOG, ACT_PIN, B_REDR, ICON_PIN_DEHLT, (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"); + 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-134), 19, act->name, 0, 31, 0, 0, "Actuator name"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+112), yco, (short)(width-(pin?156:134)), 19, act->name, 0, 31, 0, 0, "Actuator name"); uiButSetFunc(but, make_unique_prop_names_cb, act->name, (void*) 0); ycoo= yco; @@ -3432,7 +3540,7 @@ void logic_buts(void) 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"); uiButSetFunc(but, sca_move_actuator, act, NULL); - but= uiDefBut(block, LABEL, 0, act->name, (short)(xco+112), yco, (short)(width-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)), 19, act, 0, 0, 0, 0, "Actuator name"); uiButSetFunc(but, sca_move_actuator, act, NULL); ycoo= yco; } diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 78f19ad0608..a18950157b2 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -66,6 +66,7 @@ #include "BIF_glutil.h" #include "BIF_graphics.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_keyval.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" @@ -241,9 +242,9 @@ static void enable_constraint_ipo_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname); + verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname, 1); else - verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL); + verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL, 1); /* make sure ipowin shows it */ ob->ipowin= ID_CO; @@ -268,9 +269,9 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE, 1); else - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); if (!icu) { error("Cannot get a curve from this IPO, may be dealing with linked data"); @@ -2631,19 +2632,32 @@ static void object_panel_object(Object *ob) /* all groups */ for(group= G.main->group.first; group; group= group->id.next) { if(object_in_group(ob, group)) { - xco= 160; - - uiBlockBeginAlign(block); - uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */ - but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 150, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); - uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); - uiClearButLock(); + xco= 130; if(group->id.lib) { - but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 160, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local"); + uiBlockBeginAlign(block); + uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */ + uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 100, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); + uiClearButLock(); + + but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 110, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local"); uiButSetFunc(but, group_local, group, NULL); - xco= 180; - } else { /* cant remove objects from linked groups */ + uiBlockEndAlign(block); + } else { + but = uiDefBut(block, TEX, B_IDNAME, "GR:", 10, 120-yco, 120, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change."); + uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL); + } + + uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); + uiBlockBeginAlign(block); + uiDefButF(block, NUM, REDRAWALL, "X:", xco+5, 120-yco, 50, 20, &group->dupli_ofs[0], -100000, 100000, 100, 0, "Offset to use when instacing the group"); + uiDefButF(block, NUM, REDRAWALL, "Y:", xco+55, 120-yco, 50, 20, &group->dupli_ofs[1], -100000, 100000, 100, 0, "Offset to use when instacing the group"); + uiDefButF(block, NUM, REDRAWALL, "Z:", xco+105, 120-yco, 50, 20, &group->dupli_ofs[2], -100000, 100000, 100, 0, "Offset to use when instacing the group"); + uiBlockEndAlign(block); + uiClearButLock(); + + xco = 290; + if(group->id.lib==0) { /* cant remove objects from linked groups */ but = uiDefIconBut(block, BUT, B_NOP, VICON_X, xco, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove Group membership"); uiButSetFunc(but, group_ob_rem, group, ob); } @@ -2971,7 +2985,8 @@ void do_effects_panels(unsigned short event) psmd= (ParticleSystemModifierData*) md; psmd->psys=psys; BLI_addtail(&ob->modifiers, md); - } + } else + id->us--; idtest->us++; psys->part=(ParticleSettings*)idtest; @@ -3029,7 +3044,7 @@ void do_effects_panels(unsigned short event) if(ob && (psys=psys_get_current(ob))){ if(psys->part) { if(psys->part->id.us>1){ - if(okee("Make local")){ + if(okee("Make Single User")){ part=psys_copy_settings(psys->part); part->id.us=1; psys->part->id.us--; diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 5205be3e1b0..f2e20356f21 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -211,9 +211,15 @@ void do_soundbuts(unsigned short event) case B_SOUND_MENU_SAMPLE: if (G.buts->menunr > 0) { sample = BLI_findlink(samples, G.buts->menunr - 1); - if (sample && sound) { + if (sample && sound && sound->sample != sample) { + int wasrelative = (strncmp(sound->name, "//", 2)==0); + BLI_strncpy(sound->name, sample->name, sizeof(sound->name)); sound_set_sample(sound, sample); + + if (wasrelative) + BLI_makestringcode(G.sce, sound->name); + do_soundbuts(B_SOUND_REDRAW); } } diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index 1b580381ca5..6d5e1a62ad4 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -113,6 +113,8 @@ #include "RE_pipeline.h" +#include "GPU_material.h" + /* -----includes for this file specific----- */ #include "butspace.h" // own module @@ -209,6 +211,7 @@ static void load_image_cb(char *str, void *ima_pp_v, void *iuser_v) /* called fr if(GS(tex->id.name)==ID_TE) { BIF_preview_changed(ID_TE); allqueue(REDRAWBUTSSHADING, 0); + allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); } } @@ -1542,10 +1545,35 @@ static void texture_panel_colors(Tex *tex) uiDefButF(block, NUMSLI, B_TEXPRV, "Contr", 160,10,150,20, &tex->contrast, 0.01, 5.0, 0, 0, "Changes the contrast of the color or intensity of a texture"); } - -static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) +static int texture_channels_num_display(MTex **mtex) { - MTex *mt=NULL; + int a, num_mtex; + + if(!mtex) + return 0; + + /* compute number of texture channels to draw, 1 more + * than the last, used texture channel, and at least 10 */ + num_mtex = 0; + + for(a=MAX_MTEX-1; a>=0; a--) { + if (mtex[a]) { + num_mtex = a+1; + break; + } + } + + if (num_mtex < 10) + return 10; + else if(num_mtex < MAX_MTEX) + return num_mtex + 1; + else + return MAX_MTEX; +} + +static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp *la, bNode *node, Brush *br, SculptData *sd) +{ + MTex **mtex, *mt; uiBlock *block; ID *id=NULL, *idfrom; int a, yco, loos; @@ -1556,17 +1584,35 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l if(uiNewPanel(curarea, block, "Texture", "Texture", 320, 0, 318, 204)==0) return; /* first do the browse but */ - if(mtex) - id= (ID *)mtex->tex; + if(actmtex) + id= (ID *)actmtex->tex; else if(node) id= node->id; - if(ma) idfrom= &ma->id; - else if(wrld) idfrom= &wrld->id; - else if(la) idfrom= &la->id; - else if(br) idfrom= &br->id; - else if(sd) idfrom= NULL; /* Not sure what this does */ - else idfrom= NULL; + if(ma) { + idfrom= &ma->id; + mtex= ma->mtex; + } + else if(wrld) { + idfrom= &wrld->id; + mtex= wrld->mtex; + } + else if(la) { + idfrom= &la->id; + mtex= la->mtex; + } + else if(br) { + idfrom= &br->id; + mtex= br->mtex; + } + else if(sd) { + idfrom= NULL; /* Not sure what this does */ + mtex= sd->mtex; + } + else { + idfrom= NULL; + mtex= NULL; + } uiBlockSetCol(block, TH_BUT_SETTING2); if(ma) { @@ -1595,15 +1641,13 @@ static void texture_panel_texture(MTex *mtex, Material *ma, World *wrld, Lamp *l /* CHANNELS */ if(node==NULL) { + int num_mtex; uiBlockBeginAlign(block); yco= 150; - for(a= 0; amtex[a]; - else if(wrld) mt= wrld->mtex[a]; - else if(la) mt= la->mtex[a]; - else if(br) mt= br->mtex[a]; - else if(sd) mt= sd->mtex[a]; + + num_mtex= texture_channels_num_display(mtex); + for(a=0; atex) splitIDname(mt->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2030,7 +2074,7 @@ static void world_panel_texture(World *wrld) uiBlock *block; MTex *mtex; ID *id; - int a, loos; + int a, loos, num_mtex; char str[64], *strp; block= uiNewBlock(&curarea->uiblocks, "world_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -2041,7 +2085,8 @@ static void world_panel_texture(World *wrld) /* TEX CHANNELS */ uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - for(a= 0; amtex); + for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2506,7 +2551,7 @@ static void lamp_panel_texture(Object *ob, Lamp *la) uiBlock *block; MTex *mtex; ID *id; - int a, loos; + int a, loos, num_mtex; char *strp, str[64]; block= uiNewBlock(&curarea->uiblocks, "lamp_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -2517,7 +2562,8 @@ static void lamp_panel_texture(Object *ob, Lamp *la) /* TEX CHANNELS */ uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - for(a= 0; amtex); + for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -2603,9 +2649,9 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButBitI(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); if(la->type==LA_SPOT) { - uiDefButBitS(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); + uiDefButBitI(block, TOG, LA_SHAD_BUF, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets spotlight produce shadows using shadow buffer"); if(la->mode & LA_SHAD_BUF) { char *tip= "Regular buffer type"; if(la->buftype==LA_SHADBUF_IRREGULAR) @@ -2618,12 +2664,15 @@ static void lamp_panel_spot(Object *ob, Lamp *la) } uiBlockEndAlign(block); - uiDefButBitS(block, TOG, LA_ONLYSHADOW, B_LAMPPRV,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, LA_ONLYSHADOW, B_LAMPPRV,"OnlyShadow", 10,110,80,19,&la->mode, 0, 0, 0, 0, "Causes light to cast shadows only without illuminating objects"); + uiDefButBitI(block, TOG, LA_LAYER_SHADOW, B_LAMPPRV,"Layer", 10,90,80,19,&la->mode, 0, 0, 0, 0, "Causes only objects on the same layer to cast shadows"); + uiBlockEndAlign(block); if(la->type==LA_SPOT) { uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); - uiDefButBitS(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,40,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); + uiDefButBitI(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); + uiDefButBitI(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,40,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); uiBlockBeginAlign(block); uiDefButF(block, NUMSLI,B_LAMPREDRAW,"SpotSi ", 100,180,200,19,&la->spotsize, 1.0, 180.0, 0, 0, "Sets the angle of the spotlight beam in degrees"); @@ -2747,12 +2796,12 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) /* in yafray arealights always cast shadows, so ray shadow flag not needed */ /* ray shadow also not used when halo for spot enabled */ if ((la->type!=LA_AREA) && (!((la->type==LA_SPOT) && (la->mode & LA_HALO)))) - uiDefButBitS(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); + uiDefButBitI(block, TOG, LA_SHAD_RAY, B_SHADRAY,"Ray Shadow",10,180,80,19,&la->mode, 0, 0, 0, 0, "Use ray tracing for shadow"); /* in yafray the regular lamp can use shadowbuffers (softlight), used by spot with halo as well */ /* to prevent clash with blender shadowbuf flag, a special flag is used for yafray */ if (la->type==LA_LOCAL) { - uiDefButBitS(block, TOG, LA_YF_SOFT, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets light produce shadows using shadow buffer"); + uiDefButBitI(block, TOG, LA_YF_SOFT, B_SHADBUF, "Buf.Shadow",10,160,80,19,&la->mode, 0, 0, 0, 0, "Lets light produce shadows using shadow buffer"); uiDefButF(block, NUM, B_DIFF, "GloInt:", 100,155,200,19, &la->YF_glowint, 0.0, 1.0, 1, 0, "Sets light glow intensity, 0 is off"); uiDefButF(block, NUM, B_DIFF, "GloOfs:", 100,135,100,19, &la->YF_glowofs, 0.0, 2.0, 1, 0, "Sets light glow offset, the higher, the less 'peaked' the glow"); uiDefButS(block, NUM, B_DIFF, "GlowType:", 200,135,100,19, &la->YF_glowtype, 0, 1, 1, 0, "Sets light glow type"); @@ -2780,7 +2829,7 @@ static void lamp_panel_yafray(Object *ob, Lamp *la) if (la->type==LA_SPOT) { - uiDefButBitS(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,50,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); + uiDefButBitI(block, TOG, LA_HALO, B_LAMPREDRAW,"Halo", 10,50,80,19,&la->mode, 0, 0, 0, 0, "Renders spotlight with a volumetric halo"); uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); @@ -2900,15 +2949,15 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButS(block, MENU, B_LAMPREDRAW, "Falloff %t|Constant %x0|Inverse Linear %x1|Inverse Square %x2|Custom Curve %x3|Lin/Quad Weighted %x4|", 10,150,100,19, &la->falloff_type, 0,0,0,0, "Lamp falloff - intensity decay with distance"); - uiDefButBitS(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); + uiDefButBitI(block, TOG, LA_SPHERE, B_LAMPPRV,"Sphere", 10,130,100,19,&la->mode, 0, 0, 0, 0, "Sets light intensity to zero for objects beyond the distance value"); } uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_SETTING1); - uiDefButBitS(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); - uiDefButBitS(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); - uiDefButBitS(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); - uiDefButBitS(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); + uiDefButBitI(block, TOG, LA_LAYER, 0,"Layer", 10,70,100,19,&la->mode, 0, 0, 0, 0, "Illuminates objects in the same layer as the lamp only"); + uiDefButBitI(block, TOG, LA_NEG, B_LAMPPRV,"Negative", 10,50,100,19,&la->mode, 0, 0, 0, 0, "Sets lamp to cast negative light"); + uiDefButBitI(block, TOG, LA_NO_DIFF, B_LAMPPRV,"No Diffuse", 10,30,100,19,&la->mode, 0, 0, 0, 0, "Disables diffuse shading of material illuminated by this lamp"); + uiDefButBitI(block, TOG, LA_NO_SPEC, B_LAMPPRV,"No Specular", 10,10,100,19,&la->mode, 0, 0, 0, 0, "Disables specular shading of material illuminated by this lamp"); uiBlockEndAlign(block); uiBlockSetCol(block, TH_AUTO); @@ -3523,7 +3572,7 @@ static void material_panel_texture(Object *ob, Material *ma) ID *id; ParticleSystem *psys; int loos, psys_mapto=0; - int a; + int a, num_mtex; char str[64], *strp; block= uiNewBlock(&curarea->uiblocks, "material_panel_texture", UI_EMBOSS, UI_HELV, curarea->win); @@ -3539,7 +3588,8 @@ static void material_panel_texture(Object *ob, Material *ma) uiBlockSetCol(block, TH_BUT_NEUTRAL); uiBlockBeginAlign(block); - for(a= 0; amtex); + for(a= 0; amtex[a]; if(mtex && mtex->tex) splitIDname(mtex->tex->id.name+2, str, &loos); else strcpy(str, ""); @@ -3553,10 +3603,10 @@ static void material_panel_texture(Object *ob, Material *ma) /* SEPTEX */ uiBlockSetCol(block, TH_AUTO); - for(a= 0; amtex[a]; if(mtex && mtex->tex) { - but=uiDefIconButBitS(block, ICONTOGN, 1<septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel"); + but=uiDefIconButBitI(block, ICONTOGN, 1<septex, 0.0, 0.0, 0, 0, "Click to disable or enable this texture channel"); if(psys_mapto && ma->mtex[a]->mapto & MAP_PA_IVEL) uiButSetFunc(but, particle_recalc_material, ma, NULL); @@ -4091,13 +4141,14 @@ static void material_panel_material(Material *ma) uiBlockSetCol(block, TH_BUT_SETTING1); uiDefButBitI(block, TOG, MA_VERTEXCOL, B_MAT_VCOL_LIGHT, "VCol Light", 8,166,74,20, &(ma->mode), 0, 0, 0, 0, "Adds vertex colors as extra light"); uiDefButBitI(block, TOG, MA_VERTEXCOLP, B_MAT_VCOL_PAINT, "VCol Paint", 82,166,74,20, &(ma->mode), 0, 0, 0, 0, "Replaces material's colors with vertex colors"); - uiDefButBitI(block, TOG, MA_FACETEXTURE, B_REDR, "TexFace", 156,166,64,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); - if (ma->mode & MA_FACETEXTURE) uiDefButBitI(block, TOG, MA_FACETEXTURE_ALPHA, B_REDR, "A", 220,166,20,20, &(ma->mode), 0, 0, 0, 0, "Use alpha channel in 'TexFace' assigned images"); - uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 240,166,63,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); + uiDefButBitI(block, TOG, MA_FACETEXTURE, B_MATPRV, "TexFace", 156,166,60,20, &(ma->mode), 0, 0, 0, 0, "Sets UV-Editor assigned texture as color and texture info for faces"); + uiDefButBitI(block, TOG, MA_FACETEXTURE_ALPHA, B_MATPRV, "A", 216,166,20,20, &(ma->mode), 0, 0, 0, 0, "Use alpha channel in 'TexFace' assigned images"); + uiDefButBitI(block, TOG, MA_SHLESS, B_MATPRV, "Shadeless", 236,166,67,20, &(ma->mode), 0, 0, 0, 0, "Makes material insensitive to light or shadow"); - uiDefButBitI(block, TOG, MA_NOMIST, B_NOP, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); + uiDefButBitI(block, TOG, MA_NOMIST, B_MATPRV, "No Mist", 8,146,74,20, &(ma->mode), 0, 0, 0, 0, "Sets the material to ignore mist values"); uiDefButBitI(block, TOG, MA_ENV, B_MATPRV, "Env", 82,146,74,20, &(ma->mode), 0, 0, 0, 0, "Causes faces to render with alpha zero: allows sky/backdrop to show through (only for solid faces)"); - uiDefButF(block, NUM, B_NOP, "Shad A ", 156,146,147,19, &ma->shad_alpha, 0.001, 1.0f, 100, 0, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); + uiDefButBitS(block, TOG, MA_OBCOLOR, B_MATPRV, "ObColor", 156,146,60,20, &(ma->shade_flag), 0, 0, 0, 0, "Modulate the result with a per object color"); + uiDefButF(block, NUM, B_NOP, "Shad A ", 216,146,87,20, &ma->shad_alpha, 0.001, 1.0f, 10, 2, "Shadow casting alpha, only in use for Irregular Shadowbuffer"); } uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 0782ccfc7ee..f36719a1c9c 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -78,6 +78,7 @@ #include "BIF_drawgpencil.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BIF_keyframing.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_mywindow.h" @@ -682,6 +683,18 @@ static void draw_channel_names(void) special= ICON_SEQUENCE; } break; + case SPACE_IMAGE: + { + SpaceImage *sima= sa->spacedata.first; + + if (sima->image) + sprintf(name, "Image: %s", sima->image->id.name+2); + else + sprintf(name, "Image: "); + + special= ICON_IMAGE_COL; + } + break; default: { diff --git a/source/blender/src/drawarmature.c b/source/blender/src/drawarmature.c index 6d78b21dfbb..c37eaf7986c 100644 --- a/source/blender/src/drawarmature.c +++ b/source/blender/src/drawarmature.c @@ -2505,6 +2505,9 @@ int draw_armature(Base *base, int dt, int flag) Object *ob= base->object; bArmature *arm= ob->data; int retval= 0; + + if(G.f & G_SIMULATION) + return 1; if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) { /* we use color for solid lighting */ diff --git a/source/blender/src/drawgpencil.c b/source/blender/src/drawgpencil.c index f60d53a9c5d..fb21d94f39a 100644 --- a/source/blender/src/drawgpencil.c +++ b/source/blender/src/drawgpencil.c @@ -60,6 +60,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" +#include "BIF_drawseq.h" #include "BIF_graphics.h" #include "BIF_interface.h" #include "BIF_mywindow.h" @@ -97,6 +98,8 @@ void gp_ui_activelayer_cb (void *gpd, void *gpl) { gpencil_layer_setactive(gpd, gpl); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -108,6 +111,8 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info[0]), 128); gpencil_layer_setactive(gpd, gpl); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -115,6 +120,8 @@ void gp_ui_renamelayer_cb (void *gpd_arg, void *gpl_arg) void gp_ui_addlayer_cb (void *gpd, void *dummy) { gpencil_layer_addnew(gpd); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -122,6 +129,8 @@ void gp_ui_addlayer_cb (void *gpd, void *dummy) void gp_ui_dellayer_cb (void *gpd, void *dummy) { gpencil_layer_delactive(gpd); + + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } @@ -132,6 +141,8 @@ void gp_ui_delstroke_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_frame_delete_laststroke(gpf); + + scrarea_queue_winredraw(curarea); } /* delete active frame of active layer */ @@ -142,9 +153,19 @@ void gp_ui_delframe_cb (void *gpd, void *gpl) gpencil_layer_setactive(gpd, gpl); gpencil_layer_delframe(gpl, gpf); + scrarea_queue_winredraw(curarea); allqueue(REDRAWACTION, 0); } +/* convert the active layer to geometry */ +void gp_ui_convertlayer_cb (void *gpd, void *gpl) +{ + gpencil_layer_setactive(gpd, gpl); + gpencil_convert_menu(); + + scrarea_queue_winredraw(curarea); +} + /* ------- Drawing Code ------- */ /* draw the controls for a given layer */ @@ -166,7 +187,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short /* rounded header */ if (active) uiBlockSetCol(block, TH_BUT_ACTION); rb_col= (active)?-20:20; - uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); + uiDefBut(block, ROUNDBOX, B_REDR, "", *xco-8, *yco-2, width, 24, NULL, 5.0, 0.0, 15 , rb_col-20, ""); if (active) uiBlockSetCol(block, TH_AUTO); /* lock toggle */ @@ -177,7 +198,7 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short if (gpl->flag & (GP_LAYER_LOCKED|GP_LAYER_HIDE)) { char name[256]; /* gpl->info is 128, but we need space for 'locked/hidden' as well */ - height= 26; + height= 0; /* visibility button (only if hidden but not locked!) */ if ((gpl->flag & GP_LAYER_HIDE) && !(gpl->flag & GP_LAYER_LOCKED)) @@ -249,8 +270,14 @@ static void gp_drawui_layer (uiBlock *block, bGPdata *gpd, bGPDlayer *gpl, short /* options */ uiBlockBeginAlign(block); - but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); - uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); + if (curarea->spacetype == SPACE_VIEW3D) { + but= uiDefBut(block, BUT, B_REDR, "Convert to...", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Converts this layer's strokes to geometry (Hotkey = Alt-Shift-C)"); + uiButSetFunc(but, gp_ui_convertlayer_cb, gpd, gpl); + } + else { + but= uiDefBut(block, BUT, B_REDR, "Del Active Frame", *xco+160, *yco-75, 140, 20, NULL, 0, 0, 0, 0, "Erases the the active frame for this layer (Hotkey = Alt-XKEY/DEL)"); + uiButSetFunc(but, gp_ui_delframe_cb, gpd, gpl); + } but= uiDefBut(block, BUT, B_REDR, "Del Last Stroke", *xco+160, *yco-95, 140, 20, NULL, 0, 0, 0, 0, "Erases the last stroke from the active frame (Hotkey = Alt-XKEY/DEL)"); uiButSetFunc(but, gp_ui_delstroke_cb, gpd, gpl); @@ -297,7 +324,7 @@ short draw_gpencil_panel (uiBlock *block, bGPdata *gpd, ScrArea *sa) /* 'view align' button (naming depends on context) */ if (sa->spacetype == SPACE_VIEW3D) uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Sketch in 3D", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added in 3D-space"); - else if (sa->spacetype != SPACE_SEQ) /* not available for sequencer yet */ + else uiDefButBitI(block, TOG, GP_DATA_VIEWALIGN, B_REDR, "Stick to View", 170, 205, 150, 20, &gpd->flag, 0, 0, 0, 0, "New strokes are added on 2d-canvas"); } @@ -323,6 +350,9 @@ enum { GP_DRAWDATA_ONLYI2D = (1<<3), /* only draw 'image' strokes */ }; +/* thickness above which we should use special drawing */ +#define GP_DRAWTHICKNESS_SPECIAL 3 + /* ----- Tool Buffer Drawing ------ */ /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ @@ -347,23 +377,13 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick glEnd(); } else if (sflag & GP_STROKE_ERASER) { - /* draw stroke curve - just standard thickness */ - setlinestyle(4); - glLineWidth(1.0f); - - glBegin(GL_LINE_STRIP); - for (i=0, pt=points; i < totpoints && pt; i++, pt++) { - glVertex2f(pt->x, pt->y); - } - glEnd(); - - setlinestyle(0); + /* don't draw stroke at all! */ } else { float oldpressure = 0.0f; /* draw stroke curve */ - setlinestyle(2); + if (G.f & G_DEBUG) setlinestyle(2); glBegin(GL_LINE_STRIP); for (i=0, pt=points; i < totpoints && pt; i++, pt++) { @@ -381,14 +401,14 @@ static void gp_draw_stroke_buffer (tGPspoint *points, int totpoints, short thick } glEnd(); - setlinestyle(0); + if (G.f & G_DEBUG) setlinestyle(0); } } /* ----- Existing Strokes Drawing (3D and Point) ------ */ /* draw a given stroke - just a single dot (only one point) */ -static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int winy) +static void gp_draw_stroke_point (bGPDspoint *points, short thickness, short sflag, int offsx, int offsy, int winx, int winy) { /* draw point */ if (sflag & GP_STROKE_3DSPACE) { @@ -396,18 +416,42 @@ static void gp_draw_stroke_point (bGPDspoint *points, short sflag, int winx, int glVertex3f(points->x, points->y, points->z); glEnd(); } - else if (sflag & GP_STROKE_2DSPACE) { - glBegin(GL_POINTS); - glVertex2f(points->x, points->y); - glEnd(); - } else { - const float x= (points->x / 1000 * winx); - const float y= (points->y / 1000 * winy); + float co[2]; - glBegin(GL_POINTS); - glVertex2f(x, y); - glEnd(); + /* get coordinates of point */ + if (sflag & GP_STROKE_2DSPACE) { + co[0]= points->x; + co[1]= points->y; + } + else if (sflag & GP_STROKE_2DIMAGE) { + co[0]= (points->x * winx) + offsx; + co[1]= (points->y * winy) + offsy; + } + else { + co[0]= (points->x / 1000 * winx); + co[1]= (points->y / 1000 * winy); + } + + /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, simple opengl point will do */ + if (thickness < GP_DRAWTHICKNESS_SPECIAL) { + glBegin(GL_POINTS); + glVertex2fv(co); + glEnd(); + } + else { + /* draw filled circle as is done in circf (but without the matrix push/pops which screwed things up) */ + GLUquadricObj *qobj = gluNewQuadric(); + + gluQuadricDrawStyle(qobj, GLU_FILL); + + /* need to translate drawing position, but must reset after too! */ + glTranslatef(co[0], co[1], 0.); + gluDisk( qobj, 0.0, thickness, 32, 1); + glTranslatef(-co[0], -co[1], 0.); + + gluDeleteQuadric(qobj); + } } } @@ -447,10 +491,15 @@ static void gp_draw_stroke_3d (bGPDspoint *points, int totpoints, short thicknes /* ----- Fancy 2D-Stroke Drawing ------ */ /* draw a given stroke in 2d */ -static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, short debug, int winx, int winy) +static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, + short debug, int offsx, int offsy, int winx, int winy) { - /* if thickness is less than 3, 'smooth' opengl lines look better */ - if (thickness < 3) { + /* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better + * - but NOT if Image Editor 'image-based' stroke + */ + if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || + ((curarea->spacetype==SPACE_IMAGE) && (dflag & GP_DRAWDATA_ONLYV2D)) ) + { bGPDspoint *pt; int i; @@ -459,6 +508,12 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } + else if (sflag & GP_STROKE_2DIMAGE) { + const float x= (pt->x * winx) + offsx; + const float y= (pt->y * winy) + offsy; + + glVertex2f(x, y); + } else { const float x= (pt->x / 1000 * winx); const float y= (pt->y / 1000 * winy); @@ -468,7 +523,10 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, } glEnd(); } - else { /* tesselation code: currently only enabled with rt != 0 */ + + /* tesselation code: currently only enabled with rt != 0 */ + else + { bGPDspoint *pt1, *pt2; float pm[2]; int i; @@ -488,6 +546,12 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, s0[0]= pt1->x; s0[1]= pt1->y; s1[0]= pt2->x; s1[1]= pt2->y; } + else if (sflag & GP_STROKE_2DIMAGE) { + s0[0]= (pt1->x * winx) + offsx; + s0[1]= (pt1->y * winy) + offsy; + s1[0]= (pt2->x * winx) + offsx; + s1[1]= (pt2->y * winy) + offsy; + } else { s0[0]= (pt1->x / 1000 * winx); s0[1]= (pt1->y / 1000 * winy); @@ -630,6 +694,12 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, if (sflag & GP_STROKE_2DSPACE) { glVertex2f(pt->x, pt->y); } + else if (sflag & GP_STROKE_2DIMAGE) { + const float x= (pt->x * winx) + offsx; + const float y= (pt->y * winy) + offsy; + + glVertex2f(x, y); + } else { const float x= (pt->x / 1000 * winx); const float y= (pt->y / 1000 * winy); @@ -644,8 +714,8 @@ static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, /* ----- General Drawing ------ */ /* draw a set of strokes */ -static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, short debug, - short lthick, float color[4]) +static void gp_draw_strokes (bGPDframe *gpf, int offsx, int offsy, int winx, int winy, int dflag, + short debug, short lthick, float color[4]) { bGPDstroke *gps; @@ -671,16 +741,16 @@ static void gp_draw_strokes (bGPDframe *gpf, int winx, int winy, int dflag, shor /* check which stroke-drawer to use */ if (gps->totpoints == 1) - gp_draw_stroke_point(gps->points, gps->flag, winx, winy); + gp_draw_stroke_point(gps->points, lthick, gps->flag, offsx, offsy, winx, winy); else if (dflag & GP_DRAWDATA_ONLY3D) gp_draw_stroke_3d(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); else if (gps->totpoints > 1) - gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, winx, winy); + gp_draw_stroke(gps->points, gps->totpoints, lthick, dflag, gps->flag, debug, offsx, offsy, winx, winy); } } /* draw grease-pencil datablock */ -static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) +static void gp_draw_data (bGPdata *gpd, int offsx, int offsy, int winx, int winy, int dflag) { bGPDlayer *gpl, *actlay=NULL; @@ -732,7 +802,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) if ((gpf->framenum - gf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ tcolor[3] = color[3] - (i/gpl->gstep); - gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -744,7 +814,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) if ((gf->framenum - gpf->framenum) <= gpl->gstep) { /* alpha decreases with distance from curframe index */ tcolor[3] = color[3] - (i/gpl->gstep); - gp_draw_strokes(gf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } else break; @@ -757,12 +827,12 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* draw the strokes for the ghost frames (at half of the alpha set by user) */ if (gpf->prev) { tcolor[3] = (color[3] / 7); - gp_draw_strokes(gpf->prev, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->prev, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } if (gpf->next) { tcolor[3] = (color[3] / 4); - gp_draw_strokes(gpf->next, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf->next, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); } /* restore alpha */ @@ -772,7 +842,7 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) /* draw the strokes already in active frame */ tcolor[3]= color[3]; - gp_draw_strokes(gpf, winx, winy, dflag, debug, lthick, tcolor); + gp_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, debug, lthick, tcolor); /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) @@ -840,16 +910,69 @@ static void gp_draw_data (bGPdata *gpd, int winx, int winy, int dflag) void draw_gpencil_2dimage (ScrArea *sa, ImBuf *ibuf) { bGPdata *gpd; - int dflag = 0; + int offsx, offsy, sizex, sizey; + int dflag = GP_DRAWDATA_NOSTATUS; /* check that we have grease-pencil stuff to draw */ if (ELEM(NULL, sa, ibuf)) return; gpd= gpencil_data_getactive(sa); if (gpd == NULL) return; + /* calculate rect */ + switch (sa->spacetype) { + case SPACE_IMAGE: /* image */ + { + SpaceImage *sima= (SpaceImage *)sa->spacedata.first; + + /* just draw using standard scaling (settings here are currently ignored anyways) */ + // FIXME: the opengl poly-strokes don't draw at right thickness when done this way, so disabled + offsx= 0; + offsy= 0; + sizex= sa->winx; + sizey= sa->winy; + + myortho2(sima->v2d.cur.xmin, sima->v2d.cur.xmax, sima->v2d.cur.ymin, sima->v2d.cur.ymax); + + dflag |= GP_DRAWDATA_ONLYV2D; + } + break; + + case SPACE_SEQ: /* sequence */ + { + SpaceSeq *sseq= (SpaceSeq *)sa->spacedata.first; + float zoom, zoomx, zoomy; + + /* calculate accessory values */ + zoom= SEQ_ZOOM_FAC(sseq->zoom); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); + zoomy = zoom; + } + else + zoomx = zoomy = zoom; + + sizex= zoomx * ibuf->x; + sizey= zoomy * ibuf->y; + offsx= (sa->winx-sizex)/2 + sseq->xof; + offsy= (sa->winy-sizey)/2 + sseq->yof; + + dflag |= GP_DRAWDATA_ONLYI2D; + } + break; + + default: /* for spacetype not yet handled */ + offsx= 0; + offsy= 0; + sizex= sa->winx; + sizey= sa->winy; + + dflag |= GP_DRAWDATA_ONLYI2D; + break; + } + + /* draw it! */ - dflag = (GP_DRAWDATA_ONLYI2D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, offsx, offsy, sizex, sizey, dflag); } /* draw grease-pencil sketches to specified 2d-view assuming that matrices are already set correctly @@ -867,7 +990,7 @@ void draw_gpencil_2dview (ScrArea *sa, short onlyv2d) /* draw it! */ if (onlyv2d) dflag |= (GP_DRAWDATA_ONLYV2D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, 0, 0, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to specified 3d-view assuming that matrices are already set correctly @@ -884,7 +1007,7 @@ void draw_gpencil_3dview (ScrArea *sa, short only3d) /* draw it! */ if (only3d) dflag |= (GP_DRAWDATA_ONLY3D|GP_DRAWDATA_NOSTATUS); - gp_draw_data(gpd, sa->winx, sa->winy, dflag); + gp_draw_data(gpd, 0, 0, sa->winx, sa->winy, dflag); } /* draw grease-pencil sketches to opengl render window assuming that matrices are already set correctly */ @@ -898,7 +1021,7 @@ void draw_gpencil_oglrender (View3D *v3d, int winx, int winy) if (gpd == NULL) return; /* pass 1: draw 3d-strokes ------------ > */ - gp_draw_data(gpd, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D)); + gp_draw_data(gpd, 0, 0, winx, winy, (GP_DRAWDATA_NOSTATUS|GP_DRAWDATA_ONLY3D)); /* pass 2: draw 2d-strokes ------------ > */ /* adjust view matrices */ @@ -906,7 +1029,7 @@ void draw_gpencil_oglrender (View3D *v3d, int winx, int winy) glLoadIdentity(); /* draw it! */ - gp_draw_data(gpd, winx, winy, GP_DRAWDATA_NOSTATUS); + gp_draw_data(gpd, 0, 0, winx, winy, GP_DRAWDATA_NOSTATUS); } /* ************************************************** */ diff --git a/source/blender/src/drawimage.c b/source/blender/src/drawimage.c index 14849cdd450..97765690ceb 100644 --- a/source/blender/src/drawimage.c +++ b/source/blender/src/drawimage.c @@ -52,6 +52,7 @@ #include "DNA_camera_types.h" #include "DNA_color_types.h" #include "DNA_image_types.h" +#include "DNA_gpencil_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_node_types.h" @@ -79,6 +80,7 @@ #include "BDR_editface.h" #include "BDR_drawobject.h" #include "BDR_drawmesh.h" +#include "BDR_gpencil.h" #include "BDR_imagepaint.h" #include "BIF_cursors.h" @@ -86,6 +88,7 @@ #include "BIF_graphics.h" #include "BIF_mywindow.h" #include "BIF_drawimage.h" +#include "BIF_drawgpencil.h" #include "BIF_resources.h" #include "BIF_interface.h" #include "BIF_interface_icons.h" @@ -1778,6 +1781,45 @@ static void image_panel_preview(ScrArea *sa, short cntrl) // IMAGE_HANDLER_PREVI } +static void image_panel_gpencil(short cntrl) // IMAGE_HANDLER_GREASEPENCIL +{ + uiBlock *block; + SpaceImage *sima; + + sima= curarea->spacedata.first; + + block= uiNewBlock(&curarea->uiblocks, "image_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(IMAGE_HANDLER_GREASEPENCIL); // for close and esc + if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceImage", 100, 30, 318, 204)==0) return; + + /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */ + if (sima->flag & SI_DISPGP) { + if (sima->gpd == NULL) + gpencil_data_setactive(curarea, gpencil_data_addnew()); + } + + if (sima->flag & SI_DISPGP) { + bGPdata *gpd= sima->gpd; + short newheight; + + /* this is a variable height panel, newpanel doesnt force new size on existing panels */ + /* so first we make it default height */ + uiNewPanelHeight(block, 204); + + /* draw button for showing gpencil settings and drawings */ + uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor (draw using Shift-LMB)"); + + /* extend the panel if the contents won't fit */ + newheight= draw_gpencil_panel(block, gpd, curarea); + uiNewPanelHeight(block, newheight); + } + else { + uiDefButBitI(block, TOG, SI_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &sima->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Image/UV Editor"); + uiDefBut(block, LABEL, 1, " ", 160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, ""); + } +} + static void image_blockhandlers(ScrArea *sa) { SpaceImage *sima= sa->spacedata.first; @@ -1788,7 +1830,6 @@ static void image_blockhandlers(ScrArea *sa) for(a=0; ablockhandler[a]) { - case IMAGE_HANDLER_PROPERTIES: image_panel_properties(sima->blockhandler[a+1]); break; @@ -1806,7 +1847,10 @@ static void image_blockhandlers(ScrArea *sa) break; case IMAGE_HANDLER_PREVIEW: image_panel_preview(sa, sima->blockhandler[a+1]); - break; + break; + case IMAGE_HANDLER_GREASEPENCIL: + image_panel_gpencil(sima->blockhandler[a+1]); + break; } /* clear action value for event */ sima->blockhandler[a+1]= 0; @@ -2339,9 +2383,17 @@ void drawimagespace(ScrArea *sa, void *spacedata) } draw_image_transform(ibuf, xuser_asp, yuser_asp); + + /* draw grease-pencil ('image' strokes) */ + if (sima->flag & SI_DISPGP) + draw_gpencil_2dimage(sa, ibuf); mywinset(sa->win); /* restore scissor after gla call... */ myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375); + + /* draw grease-pencil (screen strokes) */ + if (sima->flag & SI_DISPGP) + draw_gpencil_2dview(sa, 0); if(G.rendering==0) { draw_image_view_tool(); diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 71854570c8c..ec6a0f0d75b 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -442,7 +442,7 @@ int in_ipo_buttons(void) else return 1; } -static View2D *spacelink_get_view2d(SpaceLink *sl) +View2D *spacelink_get_view2d(SpaceLink *sl) { if(sl->spacetype==SPACE_IPO) return &((SpaceIpo *)sl)->v2d; @@ -921,6 +921,13 @@ void drawscroll(int disptype) BIF_ThemeColor(TH_TEXT); val= ipogrid_startx; + + if (ELEM3(curarea->spacetype, SPACE_SEQ, SPACE_SOUND, SPACE_TIME)) { /* prevents printing twice same frame */ + while(ipogrid_dx < 0.9999f) { + ipogrid_dx *= 2.0f; + dfac*= 2.0f; + } + } while(fac < hor.xmax) { if(curarea->spacetype==SPACE_OOPS) { @@ -1945,7 +1952,7 @@ void do_ipobuts(unsigned short event) ei= get_active_editipo(); if(ei) { if(ei->icu==NULL) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (!ei->icu) { error("Could not add a driver to this curve, may be linked data!"); break; diff --git a/source/blender/src/drawmesh.c b/source/blender/src/drawmesh.c index 09f74c01c71..8f22c704fd0 100644 --- a/source/blender/src/drawmesh.c +++ b/source/blender/src/drawmesh.c @@ -76,534 +76,12 @@ #include "BSE_drawview.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + #include "blendef.h" #include "nla.h" -#ifndef GL_CLAMP_TO_EDGE -#define GL_CLAMP_TO_EDGE 0x812F -#endif - -//#include "glext.h" -/* some local functions */ -#if defined(GL_EXT_texture_object) && (!defined(__sun__) || (!defined(__sun))) && !defined(__APPLE__) && !defined(__linux__) && !defined(WIN32) - #define glBindTexture(A,B) glBindTextureEXT(A,B) - #define glGenTextures(A,B) glGenTexturesEXT(A,B) - #define glDeleteTextures(A,B) glDeleteTexturesEXT(A,B) - #define glPolygonOffset(A,B) glPolygonOffsetEXT(A,B) - -#else - -/* #define GL_FUNC_ADD_EXT GL_FUNC_ADD */ -/* #define GL_FUNC_REVERSE_SUBTRACT_EXT GL_FUNC_REVERSE_SUBTRACT */ -/* #define GL_POLYGON_OFFSET_EXT GL_POLYGON_OFFSET */ - -#endif - - /* (n&(n-1)) zeros the least significant bit of n */ -static int is_pow2(int num) { - return ((num)&(num-1))==0; -} -static int smaller_pow2(int num) { - while (!is_pow2(num)) - num= num&(num-1); - return num; -} - -/* These are used to enable texture clamping */ -static int is_pow2_limit(int num) { - if (U.glreslimit != 0 && num > U.glreslimit) return 0; - return ((num)&(num-1))==0; -} - -static int smaller_pow2_limit(int num) { - if (U.glreslimit != 0 && num > U.glreslimit) - return U.glreslimit; - return smaller_pow2(num); -} - -static int fCurtile=0, fCurmode=0,fCurtileXRep=0,fCurtileYRep=0; -static Image *fCurpage=0; -static short fTexwindx, fTexwindy, fTexwinsx, fTexwinsy; -static int fDoMipMap = 1; -static int fLinearMipMap = 0; - -/* local prototypes --------------- */ -void update_realtime_textures(void); - - -/* static int source, dest; also not used */ - -/** - * Enables or disable mipmapping for realtime images. - * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0). - */ -void set_mipmap(int mipmap) -{ - if (fDoMipMap != (mipmap != 0)) { - free_all_realtime_images(); - fDoMipMap = mipmap != 0; - } -} - -/** - * Returns the current setting for mipmapping. - */ -static int get_mipmap(void) -{ - return fDoMipMap && (!(G.f & G_TEXTUREPAINT)); -} - -/** - * Enables or disable linear mipmap setting for realtime images (textures). - * Note that this will will destroy all texture bindings in OpenGL. - * @see free_realtime_image() - * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0). - */ -void set_linear_mipmap(int linear) -{ - if (fLinearMipMap != (linear != 0)) { - free_all_realtime_images(); - fLinearMipMap = linear != 0; - } -} - -/** - * Returns the current setting for linear mipmapping. - */ -int get_linear_mipmap(void) -{ - return fLinearMipMap; -} - - -/** - * Resets the realtime image cache variables. - */ -void clear_realtime_image_cache() -{ - fCurpage = NULL; - fCurtile = 0; - fCurmode = 0; - fCurtileXRep = 0; - fCurtileYRep = 0; -} - -/* REMEMBER! Changes here must go into my_set_tpage() as well */ -int set_tpage(MTFace *tface) -{ - static int alphamode= -1; - static MTFace *lasttface= 0; - Image *ima; - ImBuf *ibuf; - unsigned int *rect=NULL, *bind; - int tpx=0, tpy=0, tilemode, tileXRep,tileYRep; - - /* disable */ - if(tface==0) { - if(lasttface==0) return 0; - - lasttface= 0; - fCurtile= 0; - fCurpage= 0; - if(fCurmode!=0) { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - } - fCurmode= 0; - fCurtileXRep=0; - fCurtileYRep=0; - alphamode= -1; - - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glDisable ( GL_ALPHA_TEST ); - return 0; - } - lasttface= tface; - - if( alphamode != tface->transp) { - alphamode= tface->transp; - - if(alphamode) { - if(alphamode==TF_ADD) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable ( GL_ALPHA_TEST ); - /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ - } - else if(alphamode==TF_ALPHA) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* added after 2.45 to clip alpha */ - - /*if U.glalphaclip == 1.0, some cards go bonkers... turn off alpha test in this case*/ - if(U.glalphaclip == 1.0) glDisable(GL_ALPHA_TEST); - else{ - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc ( GL_GREATER, U.glalphaclip ); - } - } else if (alphamode==TF_CLIP){ - glDisable(GL_BLEND); - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc(GL_GREATER, 0.5f); - } - /* glBlendEquationEXT(GL_FUNC_ADD_EXT); */ - /* else { */ - /* glBlendFunc(GL_ONE, GL_ONE); */ - /* glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */ - /* } */ - } else { - glDisable(GL_BLEND); - glDisable ( GL_ALPHA_TEST ); - } - } - - ima= tface->tpage; - - /* Enable or disable reflection mapping */ - if (ima && (ima->flag & IMA_REFLECT)){ - -// glActiveTextureARB(GL_TEXTURE0_ARB); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - - /* Handle multitexturing here */ - } - else{ - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - } - - tilemode= tface->mode & TF_TILES; - tileXRep = 0; - tileYRep = 0; - if (ima) { - tileXRep = ima->xrep; - tileYRep = ima->yrep; - } - - - if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0; - - if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep) { - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - - if(tilemode && ima!=NULL) - glScalef(ima->xrep, ima->yrep, 1.0); - - glMatrixMode(GL_MODELVIEW); - } - - if(ima==NULL || ima->ok==0) { - glDisable(GL_TEXTURE_2D); - - fCurtile= tface->tile; - fCurpage= 0; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - return 0; - } - - ibuf= BKE_image_get_ibuf(ima, NULL); - if(ibuf==NULL) { - - fCurtile= tface->tile; - fCurpage= 0; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - glDisable(GL_TEXTURE_2D); - return 0; - } - - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - - if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe; - else fCurtile= tface->tile; - - if(tilemode) { - if(ima->repbind==0) make_repbind(ima); - - if(fCurtile>=ima->totbind) fCurtile= 0; - - /* this happens when you change repeat buttons */ - if(ima->repbind) bind= ima->repbind+fCurtile; - else bind= &ima->bindcode; - - if(*bind==0) { - - fTexwindx= ibuf->x/ima->xrep; - fTexwindy= ibuf->y/ima->yrep; - - if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1; - - fTexwinsy= fCurtile / ima->xrep; - fTexwinsx= fCurtile - fTexwinsy*ima->xrep; - - fTexwinsx*= fTexwindx; - fTexwinsy*= fTexwindy; - - tpx= fTexwindx; - tpy= fTexwindy; - - rect= ibuf->rect + fTexwinsy*ibuf->x + fTexwinsx; - } - } - else { - bind= &ima->bindcode; - - if(*bind==0) { - tpx= ibuf->x; - tpy= ibuf->y; - rect= ibuf->rect; - } - } - - if(*bind==0) { - int rectw= tpx, recth= tpy; - unsigned int *tilerect= NULL, *scalerect= NULL; - - /* - * Maarten: - * According to Ton this code is not needed anymore. It was used only - * in really old Blenders. - * Reevan: - * Actually it is needed for backwards compatibility. Simpledemo 6 does not display correctly without it. - */ -#if 1 - if (tilemode) { - int y; - - tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect"); - for (y=0; yx]; - unsigned int *tilerectrow= &tilerect[y*rectw]; - - memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow)); - } - - rect= tilerect; - } -#endif - if (!is_pow2_limit(rectw) || !is_pow2_limit(recth)) { - rectw= smaller_pow2_limit(rectw); - recth= smaller_pow2_limit(recth); - - scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect"); - gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect); - rect= scalerect; - } - - glGenTextures(1, (GLuint *)bind); - - if((G.f & G_DEBUG) || !*bind) { - GLenum error = glGetError(); - printf("Texture: %s\n", ima->id.name+2); - printf("name: %d, tpx: %d\n", *bind, tpx); - printf("tile: %d, mode: %d\n", fCurtile, tilemode); - if (error) - printf("error: %s\n", gluErrorString(error)); - } - glBindTexture( GL_TEXTURE_2D, *bind); - - if (!get_mipmap()) - { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } else - { - int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; - - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - ima->tpageflag |= IMA_MIPMAP_COMPLETE; - } - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (tilerect) - MEM_freeN(tilerect); - if (scalerect) - MEM_freeN(scalerect); - } - else glBindTexture( GL_TEXTURE_2D, *bind); - - /* dont tile x/y as set the the game properties */ - if (ima->tpageflag & IMA_CLAMP_U) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - if (ima->tpageflag & IMA_CLAMP_V) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - else - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - /* tag_image_time(ima);*/ /* Did this get lost in the image recode? */ - - glEnable(GL_TEXTURE_2D); - - fCurpage= ima; - fCurmode= tilemode; - fCurtileXRep = tileXRep; - fCurtileYRep = tileYRep; - - return 1; -} - -void update_realtime_image(Image *ima, int x, int y, int w, int h) -{ - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - - if (ima->repbind || get_mipmap() || !ima->bindcode || !ibuf || - (!is_pow2(ibuf->x) || !is_pow2(ibuf->y)) || - (w == 0) || (h == 0)) { - /* these special cases require full reload still */ - free_realtime_image(ima); - } - else { - int row_length = glaGetOneInteger(GL_UNPACK_ROW_LENGTH); - int skip_pixels = glaGetOneInteger(GL_UNPACK_SKIP_PIXELS); - int skip_rows = glaGetOneInteger(GL_UNPACK_SKIP_ROWS); - - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); - glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); - - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } -} - -void free_realtime_image(Image *ima) -{ - if(ima->bindcode) { - glDeleteTextures(1, (GLuint *)&ima->bindcode); - ima->bindcode= 0; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } - if(ima->repbind) { - glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - - MEM_freeN(ima->repbind); - ima->repbind= NULL; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } -} - -void free_all_realtime_images(void) -{ - Image* ima; - - for(ima=G.main->image.first; ima; ima=ima->id.next) - free_realtime_image(ima); -} - -/* these two functions are called on entering and exiting texture paint mode, - temporary disabling/enabling mipmapping on all images for quick texture - updates with glTexSubImage2D. images that didn't change don't have to be - re-uploaded to OpenGL */ -void texpaint_disable_mipmap(void) -{ - Image* ima; - - if(!fDoMipMap) - return; - - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->bindcode) { - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - } -} - -void texpaint_enable_mipmap(void) -{ - Image* ima; - - if(!fDoMipMap) - return; - - for(ima=G.main->image.first; ima; ima=ima->id.next) { - if(ima->bindcode) { - if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { - int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST; - - glBindTexture(GL_TEXTURE_2D, ima->bindcode); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - else - free_realtime_image(ima); - } - } -} - -void make_repbind(Image *ima) -{ - ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); - - if(ibuf==NULL) return; - - if(ima->repbind) { - glDeleteTextures(ima->totbind, (GLuint *)ima->repbind); - MEM_freeN(ima->repbind); - ima->repbind= 0; - ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; - } - ima->totbind= ima->xrep*ima->yrep; - if(ima->totbind>1) { - ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind"); - } -} - -void update_realtime_textures() -{ - Image *ima; - - ima= G.main->image.first; - while(ima) { - if(ima->tpageflag & IMA_TWINANIM) { - if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; - - /* check: is bindcode not in the array? Free. (to do) */ - - ima->lastframe++; - if(ima->lastframe > ima->twend) ima->lastframe= ima->twsta; - - } - ima= ima->id.next; - } -} - /***/ /* Flags for marked edges */ @@ -627,7 +105,7 @@ static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flag *flags_p |= flags; } -EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) +static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me) { EdgeHash *eh = BLI_edgehash_new(); int i; @@ -775,81 +253,6 @@ static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm) BLI_edgehash_free(data.eh, NULL); } -static int set_gl_light(Object *ob) -{ - Base *base; - Lamp *la; - int count; - /* float zero[4]= {0.0, 0.0, 0.0, 0.0}; */ - float vec[4]; - - vec[3]= 1.0; - - for(count=0; count<8; count++) glDisable(GL_LIGHT0+count); - - count= 0; - - base= FIRSTBASE; - while(base) { - if(base->object->type==OB_LAMP ) { - if(base->lay & G.vd->lay) { - if(base->lay & ob->lay) - { - la= base->object->data; - - glPushMatrix(); - glLoadMatrixf((float *)G.vd->viewmat); - - where_is_object_simul(base->object); - VECCOPY(vec, base->object->obmat[3]); - - if(la->type==LA_SUN) { - vec[0]= base->object->obmat[2][0]; - vec[1]= base->object->obmat[2][1]; - vec[2]= base->object->obmat[2][2]; - vec[3]= 0.0; - glLightfv(GL_LIGHT0+count, GL_POSITION, vec); - } - else { - vec[3]= 1.0; - glLightfv(GL_LIGHT0+count, GL_POSITION, vec); - glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist); - /* post 2.25 engine supports quad lights */ - glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist)); - - if(la->type==LA_SPOT) { - vec[0]= -base->object->obmat[2][0]; - vec[1]= -base->object->obmat[2][1]; - vec[2]= -base->object->obmat[2][2]; - glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, vec); - glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0); - glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend); - } - else glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0); - } - - vec[0]= la->energy*la->r; - vec[1]= la->energy*la->g; - vec[2]= la->energy*la->b; - vec[3]= 1.0; - glLightfv(GL_LIGHT0+count, GL_DIFFUSE, vec); - glLightfv(GL_LIGHT0+count, GL_SPECULAR, vec);//zero); - glEnable(GL_LIGHT0+count); - - glPopMatrix(); - - count++; - if(count>7) break; - } - } - } - base= base->next; - } - - return count; -} - static Material *give_current_material_or_def(Object *ob, int matnr) { extern Material defmaterial; // render module abuse... @@ -893,9 +296,9 @@ static int set_draw_settings_cached(int clearcache, int textured, MTFace *texfac if (textured!=c_textured || texface!=c_texface) { if (textured ) { - c_badtex= !set_tpage(texface); + c_badtex= !GPU_set_tpage(texface); } else { - set_tpage(0); + GPU_set_tpage(0); c_badtex= 0; } c_textured= textured; @@ -950,7 +353,7 @@ static void draw_textured_begin(Object *ob) } else /* draw with lights in the scene otherwise */ - Gtexdraw.islit= set_gl_light(ob); + Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat); obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); @@ -971,12 +374,12 @@ static void draw_textured_begin(Object *ob) static void draw_textured_end() { /* switch off textures */ - set_tpage(0); + GPU_set_tpage(0); glShadeModel(GL_FLAT); glDisable(GL_CULL_FACE); - /* XXX, bad patch - default_gl_light() calls + /* XXX, bad patch - GPU_default_lights() calls * glLightfv(GL_LIGHT_POSITION, ...) which * is transformed by the current matrix... we * need to make sure that matrix is identity. @@ -987,7 +390,7 @@ static void draw_textured_end() */ glPushMatrix(); glLoadIdentity(); - default_gl_light(); + GPU_default_lights(); glPopMatrix(); } @@ -1057,50 +460,71 @@ static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmoot return 1; } -static void draw_game_text_mesh(Object *ob, Mesh *me) +void draw_mesh_text(Object *ob, int glsl) { - DerivedMesh *ddm = mesh_get_derived_deform(ob, CD_MASK_BAREMESH); - MFace *mface= me->mface; + Mesh *me = ob->data; + DerivedMesh *ddm; + MFace *mf, *mface= me->mface; MTFace *tface= me->mtface; MCol *mcol= me->mcol; /* why does mcol exist? */ bProperty *prop = get_property(ob, "Text"); - int a, start= 0, totface= me->totface; + GPUVertexAttribs gattribs; + int a, totface= me->totface; - tface+= start; - mcol+= start*4; - for (a=start; amode; int matnr= mf->mat_nr; int mf_smooth= mf->flag & ME_SMOOTH; if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) { - int badtex= set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE); float v1[3], v2[3], v3[3], v4[3]; char string[MAX_PROPSTRING]; - int characters, index; - ImBuf *ibuf; - float curpos; + int characters, i, glattrib= -1, badtex= 0; - if (badtex) - continue; + if(glsl) { + GPU_enable_material(matnr+1, &gattribs); + + for(i=0; igetVertCo(ddm, mf->v1, v1); ddm->getVertCo(ddm, mf->v2, v2); ddm->getVertCo(ddm, mf->v3, v3); if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4); - // The BM_FONT handling code is duplicated in the gameengine - // Search for 'Frank van Beek' ;-) - // string = "Frank van Beek"; + // The BM_FONT handling is in the gpu module, shared with the + // game engine, was duplicated previously set_property_valstr(prop, string); characters = strlen(string); - ibuf= BKE_image_get_ibuf(tface->tpage, NULL); - if (ibuf == NULL) { + if(!BKE_image_get_ibuf(tface->tpage, NULL)) characters = 0; - } if (!mf_smooth) { float nor[3]; @@ -1110,46 +534,11 @@ static void draw_game_text_mesh(Object *ob, Mesh *me) glNormal3fv(nor); } - curpos= 0.0; - glBegin(mf->v4?GL_QUADS:GL_TRIANGLES); - for (index = 0; index < characters; index++) { - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - int character = string[index]; - char *cp= NULL; - - // lets calculate offset stuff - // space starts at offset 1 - // character = character - ' ' + 1; - - matrixGlyph(ibuf, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - movex+= curpos; - - if (tface->mode & TF_OBCOL) - glColor3ubv(Gtexdraw.obcol); - else if (me->mcol) cp= (char *)mcol; - else glColor3ub(255, 255, 255); - - glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[3], cp[2], cp[1]); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[7], cp[6], cp[5]); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - - glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[11], cp[10], cp[9]); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(mf->v4) { - glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); - if (cp) glColor3ub(cp[15], cp[14], cp[13]); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - - curpos+= advance; - } - glEnd(); + GPU_render_text(tface, tface->mode, string, characters, + (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib); + } + if (mcol) { + mcol+=4; } } @@ -1159,7 +548,6 @@ static void draw_game_text_mesh(Object *ob, Mesh *me) void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) { Mesh *me= ob->data; - int editing= 0; /* correct for negative scale */ if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW); @@ -1168,38 +556,20 @@ void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) /* draw the textured mesh */ draw_textured_begin(ob); -#ifdef WITH_VERSE - if(me->vnode) { - /* verse-blender doesn't support uv mapping of textures yet */ - dm->drawFacesTex(dm, NULL); - } - else { -#endif - if(ob==G.obedit) { - dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh); - } else if(faceselect) { - if(G.f & G_WEIGHTPAINT) - dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); - else - dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me); - } + if(ob==G.obedit) { + dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, G.editMesh); + } else if(faceselect) { + if(G.f & G_WEIGHTPAINT) + dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1); else - dm->drawFacesTex(dm, draw_tface__set_draw); -#ifdef WITH_VERSE + dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me); } -#endif + else + dm->drawFacesTex(dm, draw_tface__set_draw); - /* draw game engine text hack - but not if we are editing the mesh */ - if (me->mtface && get_property(ob, "Text")) { - if(ob==G.obedit) - editing= 1; - else if(ob==OBACT) - if(FACESEL_PAINT_TEST) - editing= 1; - - if(!editing) - draw_game_text_mesh(ob, me); - } + /* draw game engine text hack */ + if(get_property(ob, "Text")) + draw_mesh_text(ob, 0); draw_textured_end(); @@ -1214,10 +584,3 @@ void draw_mesh_textured(Object *ob, DerivedMesh *dm, int faceselect) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } -void init_realtime_GL(void) -{ - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); -} - diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 213f49528f0..8a3176e16b2 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -93,6 +93,7 @@ #include "BKE_object.h" #include "BKE_anim.h" //for the where_on_path function #include "BKE_particle.h" +#include "BKE_property.h" #include "BKE_utildefines.h" #ifdef WITH_VERSE #include "BKE_verse.h" @@ -129,6 +130,10 @@ #include "BKE_deform.h" +#include "GPU_draw.h" +#include "GPU_material.h" +#include "GPU_extensions.h" + /* pretty stupid */ /* extern Lattice *editLatt; already in BKE_lattice.h */ /* editcurve.c */ @@ -143,114 +148,37 @@ static void drawcircle_size(float size); static void draw_empty_sphere(float size); static void draw_empty_cone(float size); -/* ************* Setting OpenGL Material ************ */ +/* check for glsl drawing */ -// Materials start counting at # one.... -#define MAXMATBUF (MAXMAT + 1) -static float matbuf[MAXMATBUF][2][4]; -static int totmat_gl= 0; - -int set_gl_material(int nr) +int draw_glsl_material(Object *ob, int dt) { - static int last_gl_matnr= -1; - static int last_ret_val= 1; + if(!GPU_extensions_minimum_support()) + return 0; + if(G.f & G_PICKSEL) + return 0; + if(!CHECK_OB_DRAWTEXTURE(G.vd, dt)) + return 0; + if(ob==OBACT && (G.f & G_WEIGHTPAINT)) + return 0; - /* prevent index to use un-initialized array items */ - if(nr>totmat_gl) nr= totmat_gl; - - if(nr<0) { - last_gl_matnr= -1; - last_ret_val= 1; - } - else if(nr= OB_SHADED)); } -/* returns 1: when there's alpha needed to be drawn in a 2nd pass */ -int init_gl_materials(Object *ob, int check_alpha) +static int check_material_alpha(Base *base, Object *ob, int glsl) { - extern Material defmaterial; // render module abuse... - Material *ma; - int a, has_alpha= 0; - - if(ob->totcol==0) { - matbuf[0][0][0]= defmaterial.r; - matbuf[0][0][1]= defmaterial.g; - matbuf[0][0][2]= defmaterial.b; - matbuf[0][0][3]= 1.0; + if(base->flag & OB_FROMDUPLI) + return 0; - matbuf[0][1][0]= defmaterial.specr; - matbuf[0][1][1]= defmaterial.specg; - matbuf[0][1][2]= defmaterial.specb; - matbuf[0][1][3]= 1.0; - - /* do material 1 too, for displists! */ - QUATCOPY(matbuf[1][0], matbuf[0][0]); - QUATCOPY(matbuf[1][1], matbuf[0][1]); - } - - for(a=1; a<=ob->totcol; a++) { - ma= give_current_material(ob, a); - ma= editnode_get_active_material(ma); - if(ma==NULL) ma= &defmaterial; - - if(amode & MA_SHLESS) { - matbuf[a][0][0]= ma->r; - matbuf[a][0][1]= ma->g; - matbuf[a][0][2]= ma->b; - } else { - matbuf[a][0][0]= (ma->ref+ma->emit)*ma->r; - matbuf[a][0][1]= (ma->ref+ma->emit)*ma->g; - matbuf[a][0][2]= (ma->ref+ma->emit)*ma->b; - } - - /* draw transparent, not in pick-select, nor editmode */ - if(check_alpha && !(G.f & G_PICKSEL) && (ob->dtx & OB_DRAWTRANSP) && !(G.obedit && G.obedit->data==ob->data)) { - if(G.vd->transp) { // drawing the transparent pass - if(ma->alpha==1.0) matbuf[a][0][3]= 0.0; // means skip solid - else matbuf[a][0][3]= ma->alpha; - } - else { // normal pass - if(ma->alpha==1.0) matbuf[a][0][3]= 1.0; - else { - matbuf[a][0][3]= 0.0; // means skip transparent - has_alpha= 1; // return value, to indicate adding to after-draw queue - } - } - } - else - matbuf[a][0][3]= 1.0; + if(G.f & G_PICKSEL) + return 0; - if (!(ma->mode & MA_SHLESS)) { - matbuf[a][1][0]= ma->spec*ma->specr; - matbuf[a][1][1]= ma->spec*ma->specg; - matbuf[a][1][2]= ma->spec*ma->specb; - matbuf[a][1][3]= 1.0; - } - } - } - - totmat_gl= ob->totcol; - set_gl_material(-1); // signal for static variable - return has_alpha; + if(G.obedit && G.obedit->data==ob->data) + return 0; + + return (glsl || (ob->dtx & OB_DRAWTRANSP)); } - /***/ static unsigned int colortab[24]= {0x0, 0xFF88FF, 0xFFBBFF, @@ -352,6 +280,9 @@ void drawaxes(float size, int flag, char drawtype) float v1[3]= {0.0, 0.0, 0.0}; float v2[3]= {0.0, 0.0, 0.0}; float v3[3]= {0.0, 0.0, 0.0}; + + if(G.f & G_SIMULATION) + return; switch(drawtype) { @@ -734,6 +665,9 @@ static void drawlamp(Object *ob) float pixsize, lampsize; float imat[4][4], curcol[4]; char col[4]; + + if(G.f & G_SIMULATION) + return; la= ob->data; @@ -1024,6 +958,9 @@ static void drawcamera(Object *ob, int flag) float vec[8][4], tmat[4][4], fac, facx, facy, depth; int i; + if(G.f & G_SIMULATION) + return; + cam= ob->data; glDisable(GL_LIGHTING); @@ -1830,6 +1767,9 @@ static void draw_verse_debug(Object *ob, EditMesh *em) struct EditFace *efa=NULL; float v1[3], v2[3], v3[3], v4[3], fvec[3], col[3]; char val[32]; + + if(G.f & G_SIMULATION) + return; if(G.vd->zbuf && (G.vd->flag & V3D_ZBUF_SELECT)==0) glDisable(GL_DEPTH_TEST); @@ -1894,6 +1834,9 @@ static void draw_em_measure_stats(Object *ob, EditMesh *em) char conv_float[5]; /* Use a float conversion matching the grid size */ float area, col[3]; /* area of the face, color of the text to draw */ + if(G.f & G_SIMULATION) + return; + /* make the precission of the pronted value proportionate to the gridsize */ if ((G.vd->grid) < 0.01) strcpy(conv_float, "%.6f"); @@ -2054,12 +1997,20 @@ static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth EditFace *efa = EM_get_face_for_index(index); if (efa->h==0) { - set_gl_material(efa->mat_nr+1); + GPU_enable_material(efa->mat_nr+1, NULL); return 1; - } else { - return 0; } + else + return 0; } + +static int draw_em_fancy__setGLSLFaceOpts(void *userData, int index) +{ + EditFace *efa = EM_get_face_for_index(index); + + return (efa->h==0); +} + static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, int dt) { Mesh *me = ob->data; @@ -2082,9 +2033,21 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived EM_init_index_arrays(1, 1, 1); if(dt>OB_WIRE) { - if( CHECK_OB_DRAWTEXTURE(G.vd, dt) ) { - draw_mesh_textured(ob, finalDM, 0); - } else { + if(CHECK_OB_DRAWTEXTURE(G.vd, dt)) { + if(draw_glsl_material(ob, dt)) { + glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); + + finalDM->drawMappedFacesGLSL(finalDM, GPU_enable_material, + draw_em_fancy__setGLSLFaceOpts, NULL); + GPU_disable_material(); + + glFrontFace(GL_CCW); + } + else { + draw_mesh_textured(ob, finalDM, 0); + } + } + else { glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED); glEnable(GL_LIGHTING); @@ -2208,6 +2171,7 @@ static void draw_em_fancy(Object *ob, EditMesh *em, DerivedMesh *cageDM, Derived if(dt>OB_WIRE) { glDepthMask(1); bglPolygonOffset(0.0); + GPU_disable_material(); } EM_free_index_arrays(); @@ -2226,8 +2190,9 @@ static void draw_mesh_object_outline(Object *ob, DerivedMesh *dm) drawFacesSolid() doesn't draw the transparent faces */ if(ob->dtx & OB_DRAWTRANSP) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - dm->drawFacesSolid(dm, set_gl_material); + dm->drawFacesSolid(dm, GPU_enable_material); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + GPU_disable_material(); } else { dm->drawEdges(dm, 0); @@ -2312,7 +2277,19 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) draw_mesh_object_outline(ob, dm); } - draw_mesh_textured(ob, dm, faceselect); + if(draw_glsl_material(ob, dt)) { + glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); + + dm->drawFacesGLSL(dm, GPU_enable_material); + if(get_property(ob, "Text")) + draw_mesh_text(ob, 1); + GPU_disable_material(); + + glFrontFace(GL_CCW); + } + else { + draw_mesh_textured(ob, dm, faceselect); + } if(!faceselect) { if(base->flag & SELECT) @@ -2323,18 +2300,17 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->drawLooseEdges(dm); } } - else if(dt==OB_SOLID ) { - - if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { + else if(dt==OB_SOLID) { + if((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) draw_mesh_object_outline(ob, dm); - } glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, me->flag & ME_TWOSIDED ); glEnable(GL_LIGHTING); glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); - dm->drawFacesSolid(dm, set_gl_material); + dm->drawFacesSolid(dm, GPU_enable_material); + GPU_disable_material(); glFrontFace(GL_CCW); glDisable(GL_LIGHTING); @@ -2352,7 +2328,8 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) if(ob==OBACT) { do_draw= 0; if( (G.f & G_WEIGHTPAINT)) { - set_gl_material(0); /* enforce defmaterial settings */ + /* enforce default material settings */ + GPU_enable_material(0, NULL); /* but set default spec */ glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR); @@ -2367,6 +2344,8 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1); glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); + + GPU_disable_material(); } else if((G.f & (G_VERTEXPAINT+G_TEXTUREPAINT)) && me->mcol) { dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1); @@ -2385,7 +2364,7 @@ static void draw_mesh_fancy(Base *base, int dt, int flag) dm->release(dm); shadeDispList(base); dl = find_displist(&ob->disp, DL_VERTCOL); - dm= mesh_get_derived_final(ob, get_viewedit_datamask()); + dm= mesh_get_derived_final(ob, get_viewedit_datamask()); } if ((G.vd->flag&V3D_SELECT_OUTLINE) && (base->flag&SELECT) && !draw_wire) { @@ -2462,7 +2441,7 @@ static int draw_mesh_object(Base *base, int dt, int flag) { Object *ob= base->object; Mesh *me= ob->data; - int has_alpha= 0, drawlinked= 0, retval= 0; + int do_alpha_pass= 0, drawlinked= 0, retval= 0, glsl, check_alpha; if(G.obedit && ob!=G.obedit && ob->data==G.obedit->data) { if(ob_get_key(ob)); @@ -2478,7 +2457,12 @@ static int draw_mesh_object(Base *base, int dt, int flag) cageDM = editmesh_get_derived_cage_and_final(&finalDM, get_viewedit_datamask()); - if(dt>OB_WIRE) init_gl_materials(ob, 0); // no transp in editmode, the fancy draw over goes bad then + if(dt>OB_WIRE) { + // no transp in editmode, the fancy draw over goes bad then + glsl = draw_glsl_material(ob, dt); + GPU_set_object_materials(G.scene, ob, glsl, NULL); + } + draw_em_fancy(ob, G.editMesh, cageDM, finalDM, dt); if (G.obedit!=ob && finalDM) @@ -2491,15 +2475,22 @@ static int draw_mesh_object(Base *base, int dt, int flag) else { /* don't create boundbox here with mesh_get_bb(), the derived system will make it, puts deformed bb's OK */ if(me->totface<=4 || boundbox_clip(ob->obmat, (ob->bb)? ob->bb: me->bb)) { - if(dt==OB_SOLID) has_alpha= init_gl_materials(ob, (base->flag & OB_FROMDUPLI)==0); + glsl = draw_glsl_material(ob, dt); + check_alpha = check_material_alpha(base, ob, glsl); + + if(dt==OB_SOLID || glsl) { + GPU_set_object_materials(G.scene, ob, glsl, + (check_alpha)? &do_alpha_pass: NULL); + } + draw_mesh_fancy(base, dt, flag); if(me->totvert==0) retval= 1; } } - /* init_gl_materials did the proper checking if this is needed */ - if(has_alpha) add_view3d_after(G.vd, base, V3D_TRANSP, flag); + /* GPU_set_object_materials checked if this is needed */ + if(do_alpha_pass) add_view3d_after(G.vd, base, V3D_TRANSP, flag); return retval; } @@ -2601,9 +2592,10 @@ static int drawDispListwire(ListBase *dlbase) return 0; } -static void drawDispListsolid(ListBase *lb, Object *ob) +static void drawDispListsolid(ListBase *lb, Object *ob, int glsl) { DispList *dl; + GPUVertexAttribs gattribs; float *data, curcol[4]; float *ndata; @@ -2667,7 +2659,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob) case DL_SURF: if(dl->index) { - set_gl_material(dl->col+1); + GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); if(dl->rt & CU_SMOOTH) glShadeModel(GL_SMOOTH); else glShadeModel(GL_FLAT); @@ -2675,12 +2667,12 @@ static void drawDispListsolid(ListBase *lb, Object *ob) glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->totindex, GL_UNSIGNED_INT, dl->index); + GPU_disable_material(); } break; case DL_INDEX3: - - set_gl_material(dl->col+1); + GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); glVertexPointer(3, GL_FLOAT, 0, dl->verts); @@ -2693,6 +2685,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob) glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_TRIANGLES, 3*dl->parts, GL_UNSIGNED_INT, dl->index); + GPU_disable_material(); if(index3_nors_incr==0) glEnableClientState(GL_NORMAL_ARRAY); @@ -2700,12 +2693,13 @@ static void drawDispListsolid(ListBase *lb, Object *ob) break; case DL_INDEX4: - - set_gl_material(dl->col+1); + GPU_enable_material(dl->col+1, (glsl)? &gattribs: NULL); glVertexPointer(3, GL_FLOAT, 0, dl->verts); glNormalPointer(GL_FLOAT, 0, dl->nors); glDrawElements(GL_QUADS, 4*dl->parts, GL_UNSIGNED_INT, dl->index); + + GPU_disable_material(); break; } @@ -2799,14 +2793,18 @@ static int drawDispList(Base *base, int dt) draw_index_wire= 1; } else { - if(dt==OB_SHADED) { + if(draw_glsl_material(ob, dt)) { + GPU_set_object_materials(G.scene, ob, 1, NULL); + drawDispListsolid(lb, ob, 1); + } + else if(dt == OB_SHADED) { if(ob->disp.first==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob, 0); + GPU_set_object_materials(G.scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob); + drawDispListsolid(lb, ob, 0); } if(ob==G.obedit && cu->bevobj==NULL && cu->taperobj==NULL && cu->ext1 == 0.0 && cu->ext2 == 0.0) { cpack(0); @@ -2833,15 +2831,19 @@ static int drawDispList(Base *base, int dt) if(dl->nors==NULL) addnormalsDispList(ob, lb); - if(dt==OB_SHADED) { + if(draw_glsl_material(ob, dt)) { + GPU_set_object_materials(G.scene, ob, 1, NULL); + drawDispListsolid(lb, ob, 1); + } + else if(dt==OB_SHADED) { if(ob->disp.first==NULL) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob, 0); + GPU_set_object_materials(G.scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob); + drawDispListsolid(lb, ob, 0); } } else { @@ -2857,16 +2859,20 @@ static int drawDispList(Base *base, int dt) if(solid) { - if(dt==OB_SHADED) { + if(draw_glsl_material(ob, dt)) { + GPU_set_object_materials(G.scene, ob, 1, NULL); + drawDispListsolid(lb, ob, 1); + } + else if(dt == OB_SHADED) { dl= lb->first; if(dl && dl->col1==0) shadeDispList(base); drawDispListshaded(lb, ob); } else { - init_gl_materials(ob, 0); + GPU_set_object_materials(G.scene, ob, 0, NULL); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); - drawDispListsolid(lb, ob); + drawDispListsolid(lb, ob, 0); } } else{ @@ -2905,6 +2911,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) float timestep, pixsize=1.0, pa_size, pa_time, r_tilt; float cfra=bsystem_time(ob,(float)CFRA,0.0); float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3]; + float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f; int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0; int path_possible=0, keys_possible=0, draw_keys=0, totchild=0; int select=ob->flag&SELECT, create_cdata=0; @@ -2957,6 +2964,12 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) ma= give_current_material(ob,part->omat); + if(ma) { + ma_r = ma->r; + ma_g = ma->g; + ma_b = ma->b; + } + if(G.vd->zbuf) glDepthMask(1); if(select) @@ -2983,11 +2996,6 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) totpart=psys->totpart; draw_as=part->draw_as; - if(part->flag&PART_ABS_TIME && part->ipo){ - calc_ipo(part->ipo, cfra); - execute_ipo((ID *)part, part->ipo); - } - if(part->flag&PART_GLOB_TIME) cfra=bsystem_time(0,(float)CFRA,0.0); @@ -3114,22 +3122,37 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue; pa_time=(cfra-pa->time)/pa->lifetime; + pa_size=pa->size; if((part->flag&PART_ABS_TIME)==0){ if(ma && ma->ipo){ + IpoCurve *icu; + /* correction for lifetime */ calc_ipo(ma->ipo, 100.0f*pa_time); - execute_ipo((ID *)ma, ma->ipo); + + for(icu = ma->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == MA_COL_R) + ma_r = icu->curval; + else if(icu->adrcode == MA_COL_G) + ma_g = icu->curval; + else if(icu->adrcode == MA_COL_B) + ma_b = icu->curval; + } } if(part->ipo) { + IpoCurve *icu; + /* correction for lifetime */ calc_ipo(part->ipo, 100*pa_time); - execute_ipo((ID *)part, part->ipo); + + for(icu = part->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == PART_SIZE) + pa_size = icu->curval; + } } } - pa_size=pa->size; - r_tilt=1.0f+pa->r_ave[0]; if(path_nbr){ @@ -3144,14 +3167,19 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) if((part->flag&PART_ABS_TIME)==0) { if(ma && ma->ipo){ + IpoCurve *icu; + /* correction for lifetime */ calc_ipo(ma->ipo, 100.0f*pa_time); - execute_ipo((ID *)ma, ma->ipo); - } - if(part->ipo) { - /* correction for lifetime */ - calc_ipo(part->ipo, 100*pa_time); - execute_ipo((ID *)part, part->ipo); + + for(icu = ma->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == MA_COL_R) + ma_r = icu->curval; + else if(icu->adrcode == MA_COL_G) + ma_g = icu->curval; + else if(icu->adrcode == MA_COL_B) + ma_b = icu->curval; + } } } @@ -3191,9 +3219,9 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) switch(draw_as){ case PART_DRAW_DOT: if(cd) { - cd[0]=ma->r; - cd[1]=ma->g; - cd[2]=ma->b; + cd[0]=ma_r; + cd[1]=ma_g; + cd[2]=ma_b; cd+=3; } if(vd){ @@ -3218,9 +3246,9 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) } else { if(cd) { - cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma->r; - cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma->g; - cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma->b; + cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r; + cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g; + cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b; cd+=18; } VECSUB(vec2,state.co,vec); @@ -3263,22 +3291,22 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3; VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3; if(cd) { - cd[0]=cd[3]=ma->r; - cd[1]=cd[4]=ma->g; - cd[2]=cd[5]=ma->b; + cd[0]=cd[3]=ma_r; + cd[1]=cd[4]=ma_g; + cd[2]=cd[5]=ma_b; cd+=3; } break; case PART_DRAW_CIRC: if(create_cdata) - glColor3f(ma->r,ma->g,ma->b); + glColor3f(ma_r,ma_g,ma_b); drawcircball(GL_LINE_LOOP, state.co, pixsize, imat); break; case PART_DRAW_BB: if(cd) { - cd[0]=cd[3]=cd[6]=cd[9]=ma->r; - cd[1]=cd[4]=cd[7]=cd[10]=ma->g; - cd[2]=cd[5]=cd[8]=cd[11]=ma->b; + cd[0]=cd[3]=cd[6]=cd[9]=ma_r; + cd[1]=cd[4]=cd[7]=cd[10]=ma_g; + cd[2]=cd[5]=cd[8]=cd[11]=ma_b; cd+=12; } if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){ @@ -4624,9 +4652,8 @@ static void drawSolidSelect(Base *base) drawDispListwire(&ob->disp); } else if(ob->type==OB_ARMATURE) { - if(!(ob->flag & OB_POSEMODE)) { + if(!(ob->flag & OB_POSEMODE)) draw_armature(base, OB_WIRE, 0); - } } glLineWidth(1.0); @@ -5094,8 +5121,9 @@ void draw_object(Base *base, int flag) drawlattice(ob); break; case OB_ARMATURE: - if(dt>OB_WIRE) set_gl_material(0); // we use defmaterial + if(dt>OB_WIRE) GPU_enable_material(0, NULL); // we use default material empty_object= draw_armature(base, dt, flag); + if(dt>OB_WIRE) GPU_disable_material(); break; default: drawaxes(1.0, flag, OB_ARROWS); @@ -5138,9 +5166,8 @@ void draw_object(Base *base, int flag) } /* draw extra: after normal draw because of makeDispList */ - if(dtx) { - if(G.f & G_SIMULATION); - else if(dtx & OB_AXIS) { + if(dtx && !(G.f & G_SIMULATION)) { + if(dtx & OB_AXIS) { drawaxes(1.0f, flag, OB_ARROWS); } if(dtx & OB_BOUNDBOX) draw_bounding_volume(ob); @@ -5411,19 +5438,6 @@ static int bbs_mesh_solid__setDrawOpts(void *userData, int index, int *drawSmoot } } -static int bbs_mesh_wire__setDrawOpts(void *userData, int index) -{ - struct { Mesh *me; EdgeHash *eh; int offset; } *data = userData; - MEdge *med = data->me->medge + index; - uintptr_t flags = (intptr_t)BLI_edgehash_lookup(data->eh, med->v1, med->v2); - - if (flags & 1) { - set_framebuffer_index_color(data->offset+index); - return 1; - } else - return 0; -} - /* TODO remove this - since face select mode now only works with painting */ static void bbs_mesh_solid(Object *ob) { @@ -5433,22 +5447,6 @@ static void bbs_mesh_solid(Object *ob) glColor3ub(0, 0, 0); dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0); - /* draw edges for seam marking in faceselect mode, but not when painting, - so that painting doesn't get interrupted on an edge */ - if ((G.f & G_FACESELECT) && !(G.f & (G_VERTEXPAINT|G_TEXTUREPAINT|G_WEIGHTPAINT))) { - struct { Mesh *me; EdgeHash *eh; int offset; } userData; - - userData.me = me; - userData.eh = get_tface_mesh_marked_edge_info(me); - userData.offset = userData.me->totface+1; - - bglPolygonOffset(1.0); - dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOpts, (void*)&userData); - bglPolygonOffset(0.0); - - BLI_edgehash_free(userData.eh, NULL); - } - dm->release(dm); } @@ -5504,6 +5502,7 @@ void draw_object_backbufsel(Object *ob) static void draw_object_mesh_instance(Object *ob, int dt, int outline) { DerivedMesh *dm=NULL, *edm=NULL; + int glsl; if(G.obedit && ob->data==G.obedit->data) edm= editmesh_get_derived_base(); @@ -5520,8 +5519,10 @@ static void draw_object_mesh_instance(Object *ob, int dt, int outline) if(outline) draw_mesh_object_outline(ob, dm?dm:edm); - if(dm) - init_gl_materials(ob, 0); + if(dm) { + glsl = draw_glsl_material(ob, dt); + GPU_set_object_materials(G.scene, ob, glsl, NULL); + } else { glEnable(GL_COLOR_MATERIAL); BIF_ThemeColor(TH_BONE_SOLID); @@ -5532,8 +5533,10 @@ static void draw_object_mesh_instance(Object *ob, int dt, int outline) glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); glEnable(GL_LIGHTING); - if(dm) - dm->drawFacesSolid(dm, set_gl_material); + if(dm) { + dm->drawFacesSolid(dm, GPU_enable_material); + GPU_disable_material(); + } else if(edm) edm->drawMappedFaces(edm, NULL, NULL, 0); diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index 71a777c9056..d7346a1ed21 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -922,17 +922,11 @@ static void draw_image_seq(ScrArea *sa) if(ibuf->rect_float && ibuf->rect==NULL) IMB_rect_from_float(ibuf); - - if (sseq->zoom > 0) { - zoom = sseq->zoom; - } else if (sseq->zoom == 0) { - zoom = 1.0; - } else { - zoom = -1.0/sseq->zoom; - } - + /* needed for gla draw */ glaDefine2DArea(&curarea->winrct); + + zoom= SEQ_ZOOM_FAC(sseq->zoom); if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); zoomy = zoom; @@ -976,7 +970,10 @@ static void draw_image_seq(ScrArea *sa) setlinestyle(0); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } - + + /* draw grease-pencil (image aligned) */ + if (sseq->flag & SEQ_DRAW_GPENCIL) + draw_gpencil_2dimage(sa, ibuf); if (free_ibuf) { IMB_freeImBuf(ibuf); diff --git a/source/blender/src/drawtext.c b/source/blender/src/drawtext.c index 71f0bbef7ca..3f21d32c2d4 100644 --- a/source/blender/src/drawtext.c +++ b/source/blender/src/drawtext.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #ifdef HAVE_CONFIG_H #include @@ -60,6 +62,7 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_suggestions.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -74,32 +77,84 @@ #include "BIF_space.h" #include "BIF_mywindow.h" #include "BIF_resources.h" +#include "BIF_mainqueue.h" #include "BSE_filesel.h" #include "BPY_extern.h" +#include "BPY_menus.h" #include "mydevice.h" #include "blendef.h" #include "winlay.h" -#define TEXTXLOC 38 +/***********************/ /* + +Notes on word-wrap +-- +All word-wrap functions follow the algorithm below to maintain consistency. + line The line to wrap (tabs converted to spaces) + view_width The maximum number of characters displayable in the region + This equals region_width/font_width for the region + wrap_chars Characters that allow wrapping. This equals [' ', '\t', '-'] + +def wrap(line, view_width, wrap_chars): + draw_start = 0 + draw_end = view_width + pos = 0 + for c in line: + if pos-draw_start >= view_width: + print line[draw_start:draw_end] + draw_start = draw_end + draw_end += view_width + elif c in wrap_chars: + draw_end = pos+1 + pos += 1 + print line[draw_start:] + +*/ /***********************/ + +#define TEXTXLOC 38 + +#define SUGG_LIST_SIZE 7 +#define SUGG_LIST_WIDTH 20 +#define DOC_WIDTH 40 +#define DOC_HEIGHT 10 + +#define TOOL_SUGG_LIST 0x01 +#define TOOL_DOCUMENT 0x02 + +#define TMARK_GRP_CUSTOM 0x00010000 /* Lower 2 bytes used for Python groups */ +#define TMARK_GRP_FINDALL 0x00020000 /* forward declarations */ void drawtextspace(ScrArea *sa, void *spacedata); void winqreadtextspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt); void txt_copy_selectbuffer (Text *text); -void do_brackets(); +void draw_brackets(SpaceText *st); -void get_selection_buffer(Text *text); -int check_bracket(char *string); -static int check_delim(char *string); -static int check_numbers(char *string); -static int check_builtinfuncs(char *string); -static int check_specialvars(char *string); +static void get_selection_buffer(Text *text); +static int check_bracket(char ch); +static int check_delim(char ch); +static int check_digit(char ch); +static int check_identifier(char ch); +static int check_whitespace(char ch); -static void *last_txt_find_string= NULL; +static int get_wrap_width(SpaceText *st); +static int get_wrap_points(SpaceText *st, char *line); +static void get_suggest_prefix(Text *text, int offset); +static void confirm_suggestion(Text *text, int skipleft); + +#define TXT_MAXFINDSTR 255 +static int g_find_flags= TXT_FIND_WRAP; +static char *g_find_str= NULL; +static char *g_replace_str= NULL; + +static int doc_scroll= 0; +static double last_check_time= 0; +static int jump_to= 0; +static double last_jump= 0; static BMF_Font *spacetext_get_font(SpaceText *st) { static BMF_Font *scr12= NULL; @@ -160,7 +215,8 @@ static void temp_char_write(char c, int accum) { void free_txt_data(void) { txt_free_cut_buffer(); - if (last_txt_find_string) MEM_freeN(last_txt_find_string); + if (g_find_str) MEM_freeN(g_find_str); + if (g_replace_str) MEM_freeN(g_replace_str); if (temp_char_buf) MEM_freeN(temp_char_buf); if (temp_char_accum) MEM_freeN(temp_char_accum); } @@ -184,352 +240,279 @@ static int render_string (SpaceText *st, char *in) { return r; } -void get_format_string(SpaceText *st) +static int find_builtinfunc(char *string) { - Text *text = st->text; - TextLine *tmp; - char *in_line; - char format[2000], check[200], other[2]; - unsigned char c; - int spot, letter, tabs, mem_amount; - size_t a, b, len; - - if(!text) return; - tmp = text->lines.first; - - while(tmp) { - in_line = tmp->line; - - len = strlen(in_line); - /* weak code... but we dont want crashes (ton) */ - if(len>2000-1) { - if (tmp->format) MEM_freeN(tmp->format); - tmp->format= NULL; + int a, i; + char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def", + "del", "elif", "else", "except", "exec", "finally", + "for", "from", "global", "if", "import", "in", + "is", "lambda", "not", "or", "pass", "print", + "raise", "return", "try", "while", "yield"}; + for (a=0; a<30; a++) { + i = 0; + while (1) { + if (builtinfuncs[a][i]=='\0') { + if (check_identifier(string[i])) + i = -1; + break; + } else if (string[i]!=builtinfuncs[a][i]) { + i = -1; + break; + } + i++; } + if (i>0) break; + } + return i; +} + +static int find_specialvar(char *string) +{ + int i = 0; + if (string[0]=='d' && string[1]=='e' && string[2]=='f') + i = 3; + else if (string[0]=='c' && string[1]=='l' && string[2]=='a' && string[3]=='s' && string[4]=='s') + i = 5; + if (i==0 || check_identifier(string[i])) + return -1; + return i; +} + +static void print_format(SpaceText *st, TextLine *line) { + int i, a; + char *s, *f; + s = line->line; + f = line->format; + for (a=0; *s; s++) { + if (*s == '\t') { + for (i=st->tabnumber-(a%st->tabnumber); i>0; i--) + printf(" "), f++, a++; + } else + printf("%c", *s), f++, a++; + } + printf("\n%s [%#x]\n", line->format, (int) (f[strlen(f)+1])); +} + +/* Ensures the format string for the given line is long enough, reallocating as needed */ +static int check_format_len(TextLine *line, unsigned int len) { + if (line->format) { + if (strlen(line->format) < len) { + MEM_freeN(line->format); + line->format = MEM_mallocN(len+2, "SyntaxFormat"); + if (!line->format) return 0; + } + } else { + line->format = MEM_mallocN(len+2, "SyntaxFormat"); + if (!line->format) return 0; + } + return 1; +} + +/* Formats the specified line and if allowed and needed will move on to the + * next line. The format string contains the following characters: + * '_' Whitespace + * '#' Comment text + * '!' Punctuation and other symbols + * 'n' Numerals + * 'l' String letters + * 'v' Special variables (class, def) + * 'b' Built-in names (print, for, etc.) + * 'q' Other text (identifiers, etc.) + * It is terminated with a null-terminator '\0' followed by a continuation + * flag indicating whether the line is part of a multi-line string. + */ +void txt_format_line(SpaceText *st, TextLine *line, int do_next) { + char *str, *fmt, orig, cont, find, prev = ' '; + int len, i; + + /* Get continuation from previous line */ + if (line->prev && line->prev->format != NULL) { + fmt= line->prev->format; + cont = fmt[strlen(fmt)+1]; /* Just after the null-terminator */ + } else cont = 0; + + /* Get original continuation from this line */ + if (line->format != NULL) { + fmt= line->format; + orig = fmt[strlen(fmt)+1]; /* Just after the null-terminator */ + } else orig = 0xFF; + + render_string(st, line->line); + str = temp_char_buf; + len = strlen(str); + if (!check_format_len(line, len)) return; + fmt = line->format; + + while (*str) { + /* Handle escape sequences by skipping both \ and next char */ + if (*str == '\\') { + *fmt = prev; fmt++; str++; + if (*str == '\0') break; + *fmt = prev; fmt++; str++; + continue; + } + /* Handle continuations */ + else if (cont) { + /* Triple strings ("""...""" or '''...''') */ + if (cont & TXT_TRISTR) { + find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; + if (*str==find && *(str+1)==find && *(str+2)==find) { + *fmt = 'l'; fmt++; str++; + *fmt = 'l'; fmt++; str++; + cont = 0; + } + /* Handle other strings */ + } else { + find = (cont & TXT_DBLQUOTSTR) ? '"' : '\''; + if (*str == find) cont = 0; + } + *fmt = 'l'; + } + /* Not in a string... */ else { - - spot = 0; - tabs = 0; - //see how many tabs we have - for(a = 0; a tabnumber)-tabs)+2)+len; // +2 for good measure - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - - for (a = 0; a < len; a++) { - c = (unsigned char) in_line[a]; - - check[0] = c; - check[1] = '\0'; - - if (check_delim(check)) - { - switch (c) { - case '\"': - if(in_line[a] == '\"' && in_line[a+1] == '\"' && in_line[a+2] == '\"') { - format[spot] = format[spot+1] = format[spot+2] = 'l'; - spot +=3; - a += 3; - while(in_line[a] != '\"' || in_line[a-1] != '\"' || in_line[a-2] != '\"') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - tabs = 0; - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } else { - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - } - format[spot] = 'l'; - spot++; - } else { - format[spot] = 'l'; - a++; spot++; - while(in_line[a] != '\"') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - format[spot] = 'l'; - spot++; - } - break; - case '\'': - if(in_line[a] == '\'' && in_line[a+1] == '\'' && in_line[a+2] == '\'') { - format[spot] = format[spot+1] = format[spot+2] = 'l'; - spot +=3; - a += 3; - while(in_line[a] != '\'' || in_line[a-1] != '\'' || in_line[a-2] != '\'') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - tabs = 0; - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } else { - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - } - format[spot] = 'l'; - spot++; - } else { - format[spot] = 'l'; - a++; spot++; - while(in_line[a] != '\'') { - c = (unsigned char) in_line[a]; - if(a >= len) { - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); - if(!(tmp= tmp->next)) { - return; - } else { - in_line = tmp->line; - len = strlen(in_line); - for(b = 0; b tabnumber)-tabs)+2)+len; - if (tmp->format) MEM_freeN(tmp->format); - tmp->format = MEM_mallocN(mem_amount, "Syntax_format"); - a = 0; spot = 0; - } - } - if(c == '\t' || c == ' ') { - if(c == '\t') { - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - a++; - } else { - format[spot] = ' '; - a++; spot++; - } - } else { - format[spot] = 'l'; - a++; spot++; - } - } - format[spot] = 'l'; - spot++; - } - break; - case '#': - while(atabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = '#'; - spot++; - } - a++; - } else { - format[spot] = '#'; - a++; spot++; - } - } else { - format[spot] = '#'; - a++; spot++; - } - } - break; - case ' ': - format[spot] = ' '; - spot++; - break; - case '\t': - for(b = st->tabnumber-(spot%st->tabnumber); b > 0; b--) { - format[spot] = ' '; - spot++; - } - break; - default: - format[spot] = 'q'; - spot++; - - break; + /* Whitespace (all ws. has been converted to spaces) */ + else if (*str == ' ') + *fmt = '_'; + /* Numbers (digits not part of an identifier and periods followed by digits) */ + else if ((prev != 'q' && check_digit(*str)) || (*str == '.' && check_digit(*(str+1)))) + *fmt = 'n'; + /* Punctuation */ + else if (check_delim(*str)) + *fmt = '!'; + /* Identifiers and other text (no previous ws. or delims. so text continues) */ + else if (prev == 'q') + *fmt = 'q'; + /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ + else { + /* Special vars(v) or built-in keywords(b) */ + if ((i=find_specialvar(str)) != -1) + prev = 'v'; + else if ((i=find_builtinfunc(str)) != -1) + prev = 'b'; + if (i>0) { + while (i>1) { + *fmt = prev; fmt++; str++; + i--; } - } else if (check_numbers(check)) { - while (a < len) { - c = (unsigned char) in_line[a]; - other[0] = c; - other[1] = '\0'; - if (check_delim(other) && c != '.') { - a--; break; - } else { - format[spot] = 'n'; - a++; spot++; - } - } - } else { - letter = 0; - while (a < len) { - c = (unsigned char) in_line[a]; - other[0] = c; - other[1] = '\0'; - if (check_delim(other)) { - a--; - break; - } else { - check[letter] = (unsigned char) in_line[a]; - letter++; - a++; - } - } - check[letter] = '\0'; - if (check_builtinfuncs(check)) { - for (b = 0; b < strlen(check); b++) { - format[spot] = 'b'; - spot++; - } - } else if (check_specialvars(check)) { /*If TRUE then color and color next word*/ - for (b = 0; b < strlen(check); b++) { - format[spot] = 'b'; - spot++; - } - a++; - format[spot] = 'q'; - spot++; a++; - letter = 0; - while (a < len) { - c = (unsigned char) in_line[a]; - other[0] = c; - other[1] = '\0'; - if (check_delim(other)) { - a--; - break; - } else { - check[letter] = (unsigned char) in_line[a]; - letter++; - a++; - } - } - check[letter] = '\0'; - for (b = 0; b < strlen(check); b++) { - format[spot] = 'v'; - spot++; - } - }else { - for (b = 0; b < strlen(check); b++) { - format[spot] = 'q'; - spot++; - } - } - } + *fmt = prev; + } else + *fmt = 'q'; } - format[spot] = '\0'; - memcpy(tmp->format, format, strlen(format)); } - - tmp = tmp->next; + prev = *fmt; + fmt++; + str++; + } + + /* Terminate and add continuation char */ + *fmt = '\0'; fmt++; + *fmt = cont; + + /* Debugging */ + //print_format(st, line); + + /* If continuation has changed and we're allowed, process the next line */ + if (cont!=orig && do_next && line->next) { + txt_format_line(st, line->next, do_next); } } -static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) { +void txt_format_text(SpaceText *st) +{ + TextLine *linep; + + if (!st->text) return; + + for (linep=st->text->lines.first; linep; linep=linep->next) + txt_format_line(st, linep, 0); +} + +static void format_draw_color(char formatchar) { + switch (formatchar) { + case '_': /* Whitespace */ + break; + case '!': /* Symbols */ + BIF_ThemeColorBlend(TH_TEXT, TH_BACK, 0.5f); + break; + case '#': /* Comments */ + BIF_ThemeColor(TH_SYNTAX_C); + break; + case 'n': /* Numerals */ + BIF_ThemeColor(TH_SYNTAX_N); + break; + case 'l': /* Strings */ + BIF_ThemeColor(TH_SYNTAX_L); + break; + case 'v': /* Specials: class, def */ + BIF_ThemeColor(TH_SYNTAX_V); + break; + case 'b': /* Keywords: for, print, etc. */ + BIF_ThemeColor(TH_SYNTAX_B); + break; + case 'q': /* Other text (identifiers) */ + default: + BIF_ThemeColor(TH_TEXT); + break; + } +} + +static int text_draw_wrapped(SpaceText *st, char *str, int x, int y, int w, char *format) +{ + int basex, i, a, len, start, end, max, lines; + + len= render_string(st, str); + str= temp_char_buf; + max= w/spacetext_get_fontwidth(st); + if (max<8) max= 8; + basex= x; + + lines= 1; + start= 0; + end= max; + for (i=0; i= max) { + /* Draw the visible portion of text on the overshot line */ + for (a=start; ashowsyntax && format) format_draw_color(format[a]); + glRasterPos2i(x, y); + BMF_DrawCharacter(spacetext_get_font(st), str[a]); + x += BMF_GetCharacterWidth(spacetext_get_font(st), str[a]); + } + y -= st->lheight; + x= basex; + lines++; + start= end; + end += max; + } else if (str[i]==' ' || str[i]=='-') { + end = i+1; + } + } + /* Draw the remaining text */ + for (a=start; ashowsyntax && format) format_draw_color(format[a]); + glRasterPos2i(x, y); + BMF_DrawCharacter(spacetext_get_font(st), str[a]); + x += BMF_GetCharacterWidth(spacetext_get_font(st), str[a]); + } + return lines; +} + +static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, char *format) +{ int r=0, w= 0; char *in; int *acc; @@ -544,40 +527,15 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra if (draw) { if(st->showsyntax && format) { int amount, a; - char out[2]; format = format+cshift; amount = strlen(in); for(a = 0; a < amount; a++) { - out[0] = (unsigned char) in[a]; - out[1] = '\0'; - switch (format[a]) { - case 'l': - BIF_ThemeColor(TH_SYNTAX_L); - break; - case 'b': - BIF_ThemeColor(TH_SYNTAX_B); - break; - case '#': - BIF_ThemeColor(TH_SYNTAX_C); - break; - case 'v': - BIF_ThemeColor(TH_SYNTAX_V); - break; - case 'n': - BIF_ThemeColor(TH_SYNTAX_N); - break; - case 'q': - BIF_ThemeColor(TH_TEXT); - break; - default: - BIF_ThemeColor(TH_TEXT); - break; - } + format_draw_color(format[a]); glRasterPos2i(x, y); - BMF_DrawString(spacetext_get_font(st), out); - x = x+BMF_GetStringWidth(spacetext_get_font(st), out); + BMF_DrawCharacter(spacetext_get_font(st), in[a]); + x = x+BMF_GetCharacterWidth(spacetext_get_font(st), in[a]); } } else { glRasterPos2i(x, y); @@ -609,14 +567,6 @@ static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) else { linep= &text->curl; charp= &text->curc; } y= (curarea->winy - y)/st->lheight; - - y-= txt_get_span(text->lines.first, *linep) - st->top; - - if (y>0) { - while (y-- != 0) if((*linep)->next) *linep= (*linep)->next; - } else if (y<0) { - while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev; - } if(st->showlinenrs) x-= TXT_OFFSET+TEXTXLOC; @@ -626,97 +576,353 @@ static void set_cursor_to_pos (SpaceText *st, int x, int y, int sel) if (x<0) x= 0; x = (x/spacetext_get_fontwidth(st)) + st->left; - w= render_string(st, (*linep)->line); - if(xlen; - + if (st->wordwrap) { + int i, j, endj, curs, max, chop, start, end, chars, loop; + char ch; + + /* Point to first visible line */ + *linep= text->lines.first; + for (i=0; itop && (*linep)->next; i++) *linep= (*linep)->next; + + max= get_wrap_width(st); + + loop= 1; + while (loop && *linep) { + start= 0; + end= max; + chop= 1; + chars= 0; + curs= 0; + endj= 0; + for (i=0, j=0; loop; j++) { + + /* Mimic replacement of tabs */ + ch= (*linep)->line[j]; + if (ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + ch= ' '; + } else + chars= 1; + + while (chars--) { + /* Gone too far, go back to last wrap point */ + if (y<0) { + *charp= endj; + loop= 0; + break; + /* Exactly at the cursor, done */ + } else if (y==0 && i-start==x) { + *charp= curs= j; + loop= 0; + break; + /* Prepare curs for next wrap */ + } else if (i-end==x) { + curs= j; + } + if (i-start>=max) { + if (chop) endj= j; + y--; + start= end; + end += max; + chop= 1; + if (y==0 && i-start>=x) { + *charp= curs; + loop= 0; + break; + } + } else if (ch==' ' || ch=='-' || ch=='\0') { + if (y==0 && i-start>=x) { + *charp= curs; + loop= 0; + break; + } + end = i+1; + endj = j; + chop= 0; + } + i++; + } + if (ch=='\0') break; + } + if (!loop || y<0) break; + + if (!(*linep)->next) { + *charp= (*linep)->len; + break; + } + + /* On correct line but didn't meet cursor, must be at end */ + if (y==0) { + *charp= (*linep)->len; + break; + } + *linep= (*linep)->next; + y--; + } + + } else { + y-= txt_get_span(text->lines.first, *linep) - st->top; + + if (y>0) { + while (y-- != 0) if((*linep)->next) *linep= (*linep)->next; + } else if (y<0) { + while (y++ != 0) if((*linep)->prev) *linep= (*linep)->prev; + } + + + w= render_string(st, (*linep)->line); + if(xlen; + } if(!sel) txt_pop_sel(text); } -static void draw_cursor(SpaceText *st) { - int h, x, i; - Text *text= st->text; - TextLine *linef, *linel; - int charf, charl; +static int get_wrap_width(SpaceText *st) { + int x, max; + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + max= (curarea->winx-x)/spacetext_get_fontwidth(st); + return max>8 ? max : 8; +} + +/* Returns the number of wrap points (or additional lines) in the given string */ +static int get_wrap_points(SpaceText *st, char *line) { + int start, end, taboffs, i, max, count; - if (text->curl==text->sell && text->curc==text->selc) { - x= text_draw(st, text->curl->line, st->left, text->curc, 0, 0, 0, NULL); + if (!st->wordwrap) return 0; - if (x) { - h= txt_get_span(text->lines.first, text->curl) - st->top; + end= max= get_wrap_width(st); + count= taboffs= start= 0; - BIF_ThemeColor(TH_HILITE); - - glRecti(x-1, curarea->winy-st->lheight*(h)-2, x+1, curarea->winy-st->lheight*(h+1)-2); + for (i=0; line[i]!='\0'; i++) { + if (i-start+taboffs>=max) { + count++; + start= end; + end += max; + taboffs= 0; + } else if (line[i]==' ' || line[i]=='\t' || line[i]=='-') { + end = i+1; + if (line[i]=='\t') + taboffs += st->tabnumber-(i-start)%st->tabnumber; } - } else { - int span= txt_get_span(text->curl, text->sell); - - if (span<0) { - linef= text->sell; - charf= text->selc; - - linel= text->curl; - charl= text->curc; - } else if (span>0) { - linef= text->curl; - charf= text->curc; - - linel= text->sell; - charl= text->selc; - } else { - linef= linel= text->curl; - - if (text->curcselc) { - charf= text->curc; - charl= text->selc; - } else { - charf= text->selc; - charl= text->curc; - } - } - - /* Walk to the beginning of visible text */ - h= txt_get_span(text->lines.first, linef) - st->top; - while (h++<-1 && linef!=linel) linef= linef->next; - - x= text_draw(st, linef->line, st->left, charf, 0, 0, 0, NULL); + } + return count; +} - BIF_ThemeColor(TH_SHADE2); +/* Sets (offl, offc) for transforming (line, curs) to its wrapped position */ +static void wrap_offset(SpaceText *st, TextLine *linein, int cursin, int *offl, int *offc) { + Text *text; + TextLine *linep; + int i, j, start, end, chars, max, chop; + char ch; - if(st->showlinenrs) { - if (!x) x= TXT_OFFSET + TEXTXLOC -4; - } else { - if (!x) x= TXT_OFFSET - 4; - } - - while (linef && linef != linel) { - h= txt_get_span(text->lines.first, linef) - st->top; - if (h>st->viewlines) break; - - glRecti(x, curarea->winy-st->lheight*(h)-2, curarea->winx, curarea->winy-st->lheight*(h+1)-2); - if(st->showlinenrs) - glRecti(TXT_OFFSET+TEXTXLOC-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET+TEXTXLOC, curarea->winy-st->lheight*(h+2)-2); - else - glRecti(TXT_OFFSET-4, curarea->winy-st->lheight*(h+1)-2, TXT_OFFSET, curarea->winy-st->lheight*(h+2)-2); + *offl= *offc= 0; - if(st->showlinenrs) - x= TXT_OFFSET + TEXTXLOC; - else - x= TXT_OFFSET; - - linef= linef->next; - } - - h= txt_get_span(text->lines.first, linef) - st->top; + if (!st->text) return; + if (!st->wordwrap) return; - i= text_draw(st, linel->line, st->left, charl, 0, 0, 0, NULL); - if(i) glRecti(x, curarea->winy-st->lheight*(h)-2, i, curarea->winy-st->lheight*(h+1)-2); + text= st->text; + /* Move pointer to first visible line (top) */ + linep= text->lines.first; + i= st->top; + while (i>0 && linep) { + if (linep == linein) return; /* Line before top */ + linep= linep->next; + i--; } - do_brackets(); - BIF_ThemeColor(TH_TEXT); + max= get_wrap_width(st); + + while (linep) { + start= 0; + end= max; + chop= 1; + chars= 0; + *offc= 0; + for (i=0, j=0; linep->line[j]!='\0'; j++) { + + /* Mimic replacement of tabs */ + ch= linep->line[j]; + if (ch=='\t') { + chars= st->tabnumber-i%st->tabnumber; + if (linep==linein && i=max) { + if (chop && linep==linein && i >= cursin) + return; + (*offl)++; + *offc -= end-start; + start= end; + end += max; + chop= 1; + } else if (ch==' ' || ch=='-') { + end = i+1; + chop= 0; + if (linep==linein && i >= cursin) + return; + } + i++; + } + } + if (linep==linein) break; + linep= linep->next; + } +} + +static int get_char_pos(SpaceText *st, char *line, int cur) { + int a=0, i; + for (i=0; itabnumber-a%st->tabnumber; + else + a++; + } + return a; +} + +static void draw_markers(SpaceText *st) { + Text *text= st->text; + TextMarker *marker, *next; + TextLine *top, *bottom, *line; + int offl, offc, i, cy, x1, x2, y1, y2, x, y; + + for (i=st->top, top= text->lines.first; top->next && i>0; i--) top= top->next; + for (i=st->viewlines-1, bottom=top; bottom->next && i>0; i--) bottom= bottom->next; + + for (marker= text->markers.first; marker; marker= next) { + next= marker->next; + for (cy= 0, line= top; line; cy++, line= line->next) { + if (cy+st->top==marker->lineno) { + /* Remove broken markers */ + if (marker->end>line->len || marker->start>marker->end) { + BLI_freelinkN(&text->markers, marker); + break; + } + + wrap_offset(st, line, marker->start, &offl, &offc); + x1= get_char_pos(st, line->line, marker->start) - st->left + offc; + y1= cy + offl; + wrap_offset(st, line, marker->end, &offl, &offc); + x2= get_char_pos(st, line->line, marker->end) - st->left + offc; + y2= cy + offl; + + glColor3ub(marker->color[0], marker->color[1], marker->color[2]); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy-3; + + if (y1==y2) { + y -= y1*st->lheight; + glBegin(GL_LINE_LOOP); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); + glEnd(); + } else { + y -= y1*st->lheight; + glBegin(GL_LINE_STRIP); + glVertex2i(curarea->winx, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y); + glVertex2i(x+x1*spacetext_get_fontwidth(st)-2, y-st->lheight); + glVertex2i(curarea->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + for (i=y1+1; iwinx, y); + glVertex2i(x, y-st->lheight); + glVertex2i(curarea->winx, y-st->lheight); + glEnd(); + y-=st->lheight; + } + glBegin(GL_LINE_STRIP); + glVertex2i(x, y); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y); + glVertex2i(x+x2*spacetext_get_fontwidth(st)+1, y-st->lheight); + glVertex2i(x, y-st->lheight); + glEnd(); + } + + break; + } + if (line==bottom) break; + } + } +} + +static void draw_cursor(SpaceText *st) { + Text *text= st->text; + int vcurl, vcurc, vsell, vselc, hidden=0; + int offl, offc, x, y, w, i; + + /* Draw the selection */ + if (text->curl!=text->sell || text->curc!=text->selc) { + + /* Convert all to view space character coordinates */ + wrap_offset(st, text->curl, text->curc, &offl, &offc); + vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl; + vcurc = get_char_pos(st, text->curl->line, text->curc) - st->left + offc; + wrap_offset(st, text->sell, text->selc, &offl, &offc); + vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; + vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + + if (vcurc<0) vcurc=0; + if (vselc<0) vselc=0, hidden=1; + + BIF_ThemeColor(TH_SHADE2); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy-2; + + if (vcurl==vsell) { + y -= vcurl*st->lheight; + if (vcurc < vselc) + glRecti(x+vcurc*spacetext_get_fontwidth(st)-1, y, x+vselc*spacetext_get_fontwidth(st), y-st->lheight); + else + glRecti(x+vselc*spacetext_get_fontwidth(st)-1, y, x+vcurc*spacetext_get_fontwidth(st), y-st->lheight); + } else { + int froml, fromc, tol, toc; + if (vcurl < vsell) { + froml= vcurl; tol= vsell; + fromc= vcurc; toc= vselc; + } else { + froml= vsell; tol= vcurl; + fromc= vselc; toc= vcurc; + } + y -= froml*st->lheight; + glRecti(x+fromc*spacetext_get_fontwidth(st)-1, y, curarea->winx, y-st->lheight); y-=st->lheight; + for (i=froml+1; iwinx, y-st->lheight), y-=st->lheight; + glRecti(x-4, y, x+toc*spacetext_get_fontwidth(st), y-st->lheight); y-=st->lheight; + } + } else { + wrap_offset(st, text->sell, text->selc, &offl, &offc); + vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl; + vselc = get_char_pos(st, text->sell->line, text->selc) - st->left + offc; + if (vselc<0) vselc=0, hidden=1; + } + + if (!hidden) { + /* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */ + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + x += vselc*spacetext_get_fontwidth(st); + y= curarea->winy-2 - vsell*st->lheight; + + if (st->overwrite) { + char ch= text->sell->line[text->selc]; + if (!ch) ch= ' '; + w= BMF_GetCharacterWidth(spacetext_get_font(st), ch); + BIF_ThemeColor(TH_HILITE); + glRecti(x, y-st->lheight-1, x+w, y-st->lheight+1); + } else { + BIF_ThemeColor(TH_HILITE); + glRecti(x-1, y, x+1, y-st->lheight); + } + } } static void calc_text_rcts(SpaceText *st) @@ -859,6 +1065,38 @@ static void screen_skip(SpaceText *st, int lines) if (st->top<0) st->top= 0; } +static void cursor_skip(SpaceText *st, int lines, int sel) +{ + Text *text; + TextLine **linep; + int oldl, oldc, *charp; + + if (!st) return; + if (st->spacetype != SPACE_TEXT) return; + if (!st->text) return; + + text= st->text; + + if (sel) linep= &text->sell, charp= &text->selc; + else linep= &text->curl, charp= &text->curc; + oldl= txt_get_span(text->lines.first, *linep); + oldc= *charp; + + while (lines>0 && (*linep)->next) { + *linep= (*linep)->next; + lines--; + } + while (lines<0 && (*linep)->prev) { + *linep= (*linep)->prev; + lines++; + } + + if (*charp > (*linep)->len) *charp= (*linep)->len; + + if (!sel) txt_pop_sel(st->text); + txt_undo_add_toop(st->text, sel?UNDO_STO:UNDO_CTO, oldl, oldc, txt_get_span(text->lines.first, *linep), *charp); +} + /* * mode 1 == view scroll * mode 2 == scrollbar @@ -874,10 +1112,8 @@ static void do_textscroll(SpaceText *st, int mode) st->flags|= ST_SCROLL_SELECT; - glDrawBuffer(GL_FRONT); - uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT); - bglFlush(); - glDrawBuffer(GL_BACK); + scrarea_do_windraw(curarea); + screen_swapbuffers(); getmouseco_areawin(mval); old[0]= hold[0]= mval[0]; @@ -895,9 +1131,12 @@ static void do_textscroll(SpaceText *st, int mode) if (delta[0] || delta[1]) { screen_skip(st, delta[1]); - st->left+= delta[0]; - if (st->left<0) st->left= 0; - + if (st->wordwrap) { + st->left= 0; + } else { + st->left+= delta[0]; + if (st->left<0) st->left= 0; + } scrarea_do_windraw(curarea); screen_swapbuffers(); @@ -912,10 +1151,8 @@ static void do_textscroll(SpaceText *st, int mode) } st->flags^= ST_SCROLL_SELECT; - glDrawBuffer(GL_FRONT); - uiEmboss(st->txtbar.xmin, st->txtbar.ymin, st->txtbar.xmax, st->txtbar.ymax, st->flags & ST_SCROLL_SELECT); - bglFlush(); - glDrawBuffer(GL_BACK); + scrarea_do_windraw(curarea); + screen_swapbuffers(); } static void do_selection(SpaceText *st, int selecting) @@ -957,7 +1194,7 @@ static void do_selection(SpaceText *st, int selecting) scrarea_do_windraw(curarea); screen_swapbuffers(); - } else if (mval[0]<0 || mval[0]>curarea->winx) { + } else if (!st->wordwrap && (mval[0]<0 || mval[0]>curarea->winx)) { if (mval[0]>curarea->winx) st->left++; else if (mval[0]<0 && st->left>0) st->left--; @@ -986,19 +1223,409 @@ static void do_selection(SpaceText *st, int selecting) if (sell!=linep2 || selc!=charp2) txt_undo_add_toop(st->text, UNDO_STO, sell, selc, linep2, charp2); + + pop_space_text(st); +} + +static int do_suggest_select(SpaceText *st) +{ + SuggItem *item, *first, *last, *sel; + short mval[2]; + TextLine *tmp; + int l, x, y, w, h, i; + int tgti, *top; + + if (!st || !st->text) return 0; + if (!texttool_text_is_active(st->text)) return 0; + + first = texttool_suggest_first(); + last = texttool_suggest_last(); + sel = texttool_suggest_selected(); + top = texttool_suggest_top(); + + if (!last || !first) + return 0; + + /* Count the visible lines to the cursor */ + for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); + if (l<0) return 0; + + if(st->showlinenrs) { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; + } else { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; + } + y = curarea->winy - st->lheight*l - 2; + + w = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20; + h = SUGG_LIST_SIZE*st->lheight + 8; + + getmouseco_areawin(mval); + + if (mval[0]next; i++, item=item->next); + + /* Work out the target item index in the visible list */ + tgti = (y-mval[1]-4) / st->lheight; + if (tgti<0 || tgti>SUGG_LIST_SIZE) + return 1; + + for (i=tgti; i>0 && item->next; i--, item=item->next); + if (item) + texttool_suggest_select(item); + return 1; +} + +static void pop_suggest_list() { + SuggItem *item, *sel; + int *top, i; + + item= texttool_suggest_first(); + sel= texttool_suggest_selected(); + top= texttool_suggest_top(); + + i= 0; + while (item && item != sel) { + item= item->next; + i++; + } + if (i > *top+SUGG_LIST_SIZE-1) + *top= i-SUGG_LIST_SIZE+1; + else if (i < *top) + *top= i; +} + +void draw_documentation(SpaceText *st) +{ + TextLine *tmp; + char *docs, buf[DOC_WIDTH+1], *p; + int len, i, br, lines; + int boxw, boxh, l, x, y, top; + + if (!st || !st->text) return; + if (!texttool_text_is_active(st->text)) return; + + docs = texttool_docs_get(); + + if (!docs) return; + + /* Count the visible lines to the cursor */ + for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); + if (l<0) return; + + if(st->showlinenrs) { + x= spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; + } else { + x= spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; + } + if (texttool_suggest_first()) { + x += SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 50; + } + + top= y= curarea->winy - st->lheight*l - 2; + len= strlen(docs); + boxw= DOC_WIDTH*spacetext_get_fontwidth(st) + 20; + boxh= (DOC_HEIGHT+1)*st->lheight; + + /* Draw panel */ + BIF_ThemeColor(TH_BACK); + glRecti(x, y, x+boxw, y-boxh); + BIF_ThemeColor(TH_SHADE1); + glBegin(GL_LINE_LOOP); + glVertex2i(x, y); + glVertex2i(x+boxw, y); + glVertex2i(x+boxw, y-boxh); + glVertex2i(x, y-boxh); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex2i(x+boxw-10, y-7); + glVertex2i(x+boxw-4, y-7); + glVertex2i(x+boxw-7, y-2); + glEnd(); + glBegin(GL_LINE_LOOP); + glVertex2i(x+boxw-10, y-boxh+7); + glVertex2i(x+boxw-4, y-boxh+7); + glVertex2i(x+boxw-7, y-boxh+2); + glEnd(); + BIF_ThemeColor(TH_TEXT); + + i= 0; br= DOC_WIDTH; lines= -doc_scroll; + for (p=docs; *p; p++) { + if (*p == '\r' && *(++p) != '\n') *(--p)= '\n'; /* Fix line endings */ + if (*p == ' ' || *p == '\t') + br= i; + else if (*p == '\n') { + buf[i]= '\0'; + if (lines>=0) { + y -= st->lheight; + text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL); + } + i= 0; br= DOC_WIDTH; lines++; + } + buf[i++]= *p; + if (i == DOC_WIDTH) { /* Reached the width, go to last break and wrap there */ + buf[br]= '\0'; + if (lines>=0) { + y -= st->lheight; + text_draw(st, buf, 0, 0, 1, x+4, y-3, NULL); + } + p -= i-br-1; /* Rewind pointer to last break */ + i= 0; br= DOC_WIDTH; lines++; + } + if (lines >= DOC_HEIGHT) break; + } + if (doc_scroll > 0 && lines < DOC_HEIGHT) { + doc_scroll--; + draw_documentation(st); + } +} + +void draw_suggestion_list(SpaceText *st) +{ + SuggItem *item, *first, *last, *sel; + TextLine *tmp; + char str[SUGG_LIST_WIDTH+1]; + int w, boxw=0, boxh, i, l, x, y, b, *top; + + if (!st || !st->text) return; + if (!texttool_text_is_active(st->text)) return; + + first = texttool_suggest_first(); + last = texttool_suggest_last(); + + if (!first || !last) return; + + pop_suggest_list(); + sel = texttool_suggest_selected(); + top = texttool_suggest_top(); + + /* Count the visible lines to the cursor */ + for (tmp=st->text->curl, l=-st->top; tmp; tmp=tmp->prev, l++); + if (l<0) return; + + if(st->showlinenrs) { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET + TEXTXLOC - 4; + } else { + x = spacetext_get_fontwidth(st)*(st->text->curc-st->left) + TXT_OFFSET - 4; + } + y = curarea->winy - st->lheight*l - 2; + + boxw = SUGG_LIST_WIDTH*spacetext_get_fontwidth(st) + 20; + boxh = SUGG_LIST_SIZE*st->lheight + 8; + + BIF_ThemeColor(TH_SHADE1); + glRecti(x-1, y+1, x+boxw+1, y-boxh-1); + BIF_ThemeColor(TH_BACK); + glRecti(x, y, x+boxw, y-boxh); + + /* Set the top 'item' of the visible list */ + for (i=0, item=first; i<*top && item->next; i++, item=item->next); + + for (i=0; inext) { + + y -= st->lheight; + + strncpy(str, item->name, SUGG_LIST_WIDTH); + str[SUGG_LIST_WIDTH] = '\0'; + + w = BMF_GetStringWidth(spacetext_get_font(st), str); + + if (item == sel) { + BIF_ThemeColor(TH_SHADE2); + glRecti(x+16, y-3, x+16+w, y+st->lheight-3); + } + b=1; /* b=1 colour block, text is default. b=0 no block, colour text */ + switch (item->type) { + case 'k': BIF_ThemeColor(TH_SYNTAX_B); b=0; break; + case 'm': BIF_ThemeColor(TH_TEXT); break; + case 'f': BIF_ThemeColor(TH_SYNTAX_L); break; + case 'v': BIF_ThemeColor(TH_SYNTAX_N); break; + case '?': BIF_ThemeColor(TH_TEXT); b=0; break; + } + if (b) { + glRecti(x+8, y+2, x+11, y+5); + BIF_ThemeColor(TH_TEXT); + } + text_draw(st, str, 0, 0, 1, x+16, y-1, NULL); + + if (item == last) break; + } +} + +static short check_blockhandler(SpaceText *st, short handler) { + short a; + for(a=0; ablockhandler[a]==handler) return 1; + return 0; +} + +static void text_panel_find(short cntrl) // TEXT_HANDLER_FIND +{ + uiBlock *block; + + if (!g_find_str || !g_replace_str) { + g_find_str= MEM_mallocN(TXT_MAXFINDSTR+1, "find_string"); + g_replace_str= MEM_mallocN(TXT_MAXFINDSTR+1, "replace_string"); + g_find_str[0]= g_replace_str[0]= '\0'; + } + + block= uiNewBlock(&curarea->uiblocks, "text_panel_find", UI_EMBOSS, UI_HELV, curarea->win); + uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE | cntrl); + uiSetPanelHandler(TEXT_HANDLER_FIND); // for close and esc + if(uiNewPanel(curarea, block, "Find & Replace", "Text", curarea->winx-230, curarea->winy-130, 260, 120)==0) return; + + uiBlockBeginAlign(block); + uiDefButC(block, TEX, 0, "Find: ", 0,80,220,20, g_find_str, 0,(float)TXT_MAXFINDSTR, 0,0, ""); + uiDefIconBut(block, BUT, B_PASTEFIND, ICON_TEXT, 220,80,20,20, NULL, 0,0,0,0, "Copy from selection"); + uiDefButC(block, TEX, 0, "Replace: ", 0,60,220,20, g_replace_str, 0,(float)TXT_MAXFINDSTR, 0,0, ""); + uiDefIconBut(block, BUT, B_PASTEREPLACE, ICON_TEXT, 220,60,20,20, NULL, 0,0,0,0, "Copy from selection"); + uiBlockEndAlign(block); + uiDefButBitI(block, TOG, TXT_FIND_WRAP, 0,"Wrap Around", 0,30,110,20,&g_find_flags,0,0,0,0,"Wrap search around current text"); + uiDefButBitI(block, TOG, TXT_FIND_ALLTEXTS,0,"Search All Texts", 110,30,130,20,&g_find_flags,0,0,0,0,"Search in each text"); + uiDefBut(block, BUT, B_TEXTFIND, "Find", 0,0,50,20, NULL, 0,0,0,0, "Find next"); + uiDefBut(block, BUT, B_TEXTREPLACE, "Replace/Find", 50,0,110,20, NULL, 0,0,0,0, "Replace then find next"); + uiDefBut(block, BUT, B_TEXTMARKALL, "Mark All", 160,0,80,20, NULL, 0,0,0,0, "Mark each occurrence to edit all from one"); +} + +/* mode: 0 find only, 1 replace/find, 2 mark all occurrences */ +void find_and_replace(SpaceText *st, short mode) { + char *tmp; + Text *start= NULL, *text= st->text; + int flags, first= 1; + + if (!check_blockhandler(st, TEXT_HANDLER_FIND)) { + toggle_blockhandler(st->area, TEXT_HANDLER_FIND, UI_PNL_TO_MOUSE); + return; + } + + if (!g_find_str || !g_replace_str) return; + if (g_find_str[0] == '\0') return; + flags= g_find_flags; + if (flags & TXT_FIND_ALLTEXTS) flags ^= TXT_FIND_WRAP; + + do { + if (first) + txt_clear_markers(text, TMARK_GRP_FINDALL, 0); + first= 0; + + /* Replace current */ + if (mode && txt_has_sel(text)) { + tmp= txt_sel_to_buf(text); + if (strcmp(g_find_str, tmp)==0) { + if (mode==1) { + txt_insert_buf(text, g_replace_str); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } else if (mode==2) { + char color[4]; + BIF_GetThemeColor4ubv(TH_SHADE2, color); + if (txt_find_marker(text, text->curl, text->selc, TMARK_GRP_FINDALL, 0)) { + if (tmp) MEM_freeN(tmp), tmp=NULL; + break; + } + txt_add_marker(text, text->curl, text->curc, text->selc, color, TMARK_GRP_FINDALL, TMARK_EDITALL); + } + } + MEM_freeN(tmp); + tmp= NULL; + } + + /* Find next */ + if (txt_find_string(text, g_find_str, flags & TXT_FIND_WRAP)) { + pop_space_text(st); + } else if (flags & TXT_FIND_ALLTEXTS) { + if (text==start) break; + if (!start) start= text; + if (text->id.next) + text= st->text= text->id.next; + else + text= st->text= G.main->text.first; + txt_move_toline(text, 0, 0); + pop_space_text(st); + first= 1; + } else { + okee("Text not found: %s", g_find_str); + break; + } + } while (mode==2); +} + +static void do_find_buttons(val) { + Text *text; + SpaceText *st; + int do_draw= 0; + char *tmp; + + st= curarea->spacedata.first; + if (!st || st->spacetype != SPACE_TEXT) return; + text= st->text; + if (!text) return; + + switch (val) { + case B_PASTEFIND: + if (!g_find_str) break; + tmp= txt_sel_to_buf(text); + strncpy(g_find_str, tmp, TXT_MAXFINDSTR); + MEM_freeN(tmp); + do_draw= 1; + break; + case B_PASTEREPLACE: + if (!g_replace_str) break; + tmp= txt_sel_to_buf(text); + strncpy(g_replace_str, tmp, TXT_MAXFINDSTR); + MEM_freeN(tmp); + do_draw= 1; + break; + case B_TEXTFIND: + find_and_replace(st, 0); + do_draw= 1; + break; + case B_TEXTREPLACE: + find_and_replace(st, 1); + do_draw= 1; + break; + case B_TEXTMARKALL: + find_and_replace(st, 2); + do_draw= 1; + break; + } +} + +static void text_blockhandlers(ScrArea *sa) +{ + SpaceText *st= sa->spacedata.first; + short a; + + /* warning; blocks need to be freed each time, handlers dont remove */ + uiFreeBlocksWin(&sa->uiblocks, sa->win); + + for(a=0; ablockhandler[a]) { + case TEXT_HANDLER_FIND: + text_panel_find(st->blockhandler[a+1]); + break; + } + } + uiDrawBlocksPanels(sa, 0); } void drawtextspace(ScrArea *sa, void *spacedata) { SpaceText *st= curarea->spacedata.first; Text *text; - int i; + int i, x, y; TextLine *tmp; char linenr[12]; float col[3]; int linecount = 0; if (st==NULL || st->spacetype != SPACE_TEXT) return; + + bwin_clear_viewmat(sa->win); /* clear buttons view */ + glLoadIdentity(); BIF_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); @@ -1022,23 +1649,23 @@ void drawtextspace(ScrArea *sa, void *spacedata) glRecti(23, 0, (st->lheight==15)?63:59, curarea->winy - 2); } - BIF_ThemeColor(TH_TEXT); - draw_cursor(st); tmp= text->lines.first; for (i= 0; itop && tmp; i++) { + if (st->showsyntax && !tmp->format) txt_format_line(st, tmp, 0); tmp= tmp->next; linecount++; } - - if(st->showsyntax) { - if (tmp && !tmp->format) { - get_format_string(st); + + y= curarea->winy-st->lheight; + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + + BIF_ThemeColor(TH_TEXT); + for (i=0; y>0 && iviewlines && tmp; i++, tmp= tmp->next) { + if (st->showsyntax && !tmp->format) { + txt_format_line(st, tmp, 0); } - } - - for (i=0; iviewlines && tmp; i++, tmp= tmp->next) { if(st->showlinenrs) { /*Change the color of the current line the cursor is on*/ if(tmp == text->curl) { @@ -1048,20 +1675,33 @@ void drawtextspace(ScrArea *sa, void *spacedata) } if(((float)(i + linecount + 1)/10000.0) < 1.0) { sprintf(linenr, "%4d", i + linecount + 1); - glRasterPos2i(TXT_OFFSET - 7, curarea->winy-st->lheight*(i+1)); + glRasterPos2i(TXT_OFFSET - 7, y); } else { sprintf(linenr, "%5d", i + linecount + 1); - glRasterPos2i(TXT_OFFSET - 11, curarea->winy-st->lheight*(i+1)); + glRasterPos2i(TXT_OFFSET - 11, y); } BIF_ThemeColor(TH_TEXT); BMF_DrawString(spacetext_get_font(st), linenr); - text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET + TEXTXLOC, curarea->winy-st->lheight*(i+1), tmp->format); - } else - text_draw(st, tmp->line, st->left, 0, 1, TXT_OFFSET, curarea->winy-st->lheight*(i+1), tmp->format); + } + if (st->wordwrap) { + int lines = text_draw_wrapped(st, tmp->line, x, y, curarea->winx-x, tmp->format); + y -= lines*st->lheight; + } else { + text_draw(st, tmp->line, st->left, 0, 1, x, y, tmp->format); + y -= st->lheight; + } } + + draw_brackets(st); + draw_markers(st); draw_textscroll(st); - + draw_documentation(st); + draw_suggestion_list(st); + + bwin_scalematrix(sa->win, st->blockscale, st->blockscale, st->blockscale); + text_blockhandlers(sa); + curarea->win_swap= WIN_BACK_OK; } @@ -1075,15 +1715,19 @@ void pop_space_text (SpaceText *st) if(!st->text) return; if(!st->text->curl) return; - i= txt_get_span(st->text->lines.first, st->text->curl); + i= txt_get_span(st->text->lines.first, st->text->sell); if (st->top+st->viewlines <= i || st->top > i) { st->top= i - st->viewlines/2; } - x= text_draw(st, st->text->curl->line, st->left, st->text->curc, 0, 0, 0, NULL); + if (st->wordwrap) { + st->left= 0; + } else { + x= text_draw(st, st->text->sell->line, st->left, st->text->selc, 0, 0, 0, NULL); - if (x==0 || x>curarea->winx) { - st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); + if (x==0 || x>curarea->winx) { + st->left= st->text->curc-0.5*(curarea->winx)/spacetext_get_fontwidth(st); + } } if (st->top < 0) st->top= 0; @@ -1103,7 +1747,7 @@ void add_text_fs(char *file) /* bad but cant pass an as arg here */ st->top= 0; - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); } @@ -1115,6 +1759,60 @@ void free_textspace(SpaceText *st) st->text= NULL; } +/* returns 0 if file on disk is the same or Text is in memory only + returns 1 if file has been modified on disk since last local edit + returns 2 if file on disk has been deleted + -1 is returned if an error occurs +*/ +int txt_file_modified(Text *text) +{ + struct stat st; + int result; + char file[FILE_MAXDIR+FILE_MAXFILE]; + + if (!text || !text->name) + return 0; + + BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_convertstringcode(file, G.sce); + + if (!BLI_exists(file)) + return 2; + + result = stat(file, &st); + + if(result == -1) + return -1; + + if((st.st_mode & S_IFMT) != S_IFREG) + return -1; + + if (st.st_mtime > text->mtime) + return 1; + + return 0; +} + +void txt_ignore_modified(Text *text) { + struct stat st; + int result; + char file[FILE_MAXDIR+FILE_MAXFILE]; + + if (!text || !text->name) return; + + BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_convertstringcode(file, G.sce); + + if (!BLI_exists(file)) return; + + result = stat(file, &st); + + if(result == -1 || (st.st_mode & S_IFMT) != S_IFREG) + return; + + text->mtime= st.st_mtime; +} + static void save_mem_text(char *str) { SpaceText *st= curarea->spacedata.first; @@ -1141,6 +1839,9 @@ void txt_write_file(Text *text) { FILE *fp; TextLine *tmp; + int res; + struct stat st; + char file[FILE_MAXDIR+FILE_MAXFILE]; /* Do we need to get a filename? */ if (text->flags & TXT_ISMEM) { @@ -1148,19 +1849,22 @@ void txt_write_file(Text *text) activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->name, save_mem_text); else activate_fileselect(FILE_SPECIAL, "SAVE TEXT FILE", text->id.name+2, save_mem_text); - return; + return; } + + BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_convertstringcode(file, G.sce); /* Should we ask to save over? */ if (text->flags & TXT_ISTMP) { - if (BLI_exists(text->name)) { + if (BLI_exists(file)) { if (!okee("Save over")) return; } else if (!okee("Create new file")) return; text->flags ^= TXT_ISTMP; } - fp= fopen(text->name, "w"); + fp= fopen(file, "w"); if (fp==NULL) { error("Unable to save file"); return; @@ -1175,6 +1879,9 @@ void txt_write_file(Text *text) } fclose (fp); + + res= stat(file, &st); + text->mtime= st.st_mtime; if (text->flags & TXT_ISDIRTY) text->flags ^= TXT_ISDIRTY; } @@ -1386,44 +2093,6 @@ void txt_copy_clipboard(Text *text) { } } -/* - * again==0 show find panel or find - * again==1 find text again */ -void txt_find_panel(SpaceText *st, int again) -{ - Text *text=st->text; - char *findstr= last_txt_find_string; - - if (again==0) { - findstr= txt_sel_to_buf(text); - } else if (again==1) { - char buf[256]; - - if (findstr && strlen(findstr)<(sizeof(buf)-1)) - strcpy(buf, findstr); - else - buf[0]= 0; - - if (sbutton(buf, 0, sizeof(buf)-1, "Find: ") && buf[0]) - findstr= BLI_strdup(buf); - else - findstr= NULL; - } - - if (findstr!=last_txt_find_string) { - if (last_txt_find_string) - MEM_freeN(last_txt_find_string); - last_txt_find_string= findstr; - } - - if (findstr) { - if (txt_find_string(text, findstr)) - pop_space_text(st); - else - error("Not found: %s", findstr); - } -} - void run_python_script(SpaceText *st) { char *py_filename; @@ -1458,6 +2127,580 @@ static void set_tabs(Text *text) st->currtab_set = setcurr_tab(text); } +static void wrap_move_bol(SpaceText *st, short sel) { + int offl, offc, lin; + Text *text= st->text; + + lin= txt_get_span(text->lines.first, text->sell); + wrap_offset(st, text->sell, text->selc, &offl, &offc); + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, -offc); + text->selc= -offc; + } else { + txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, -offc); + text->curc= -offc; + txt_pop_sel(text); + } +} + +static void wrap_move_eol(SpaceText *st, short sel) { + int offl, offc, lin, startl, c; + Text *text= st->text; + + lin= txt_get_span(text->lines.first, text->sell); + wrap_offset(st, text->sell, text->selc, &offl, &offc); + startl= offl; + c= text->selc; + while (offl==startl && text->sell->line[c]!='\0') { + c++; + wrap_offset(st, text->sell, c, &offl, &offc); + } if (offl!=startl) c--; + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, lin, text->selc, lin, c); + text->selc= c; + } else { + txt_undo_add_toop(text, UNDO_CTO, lin, text->curc, lin, c); + text->curc= c; + txt_pop_sel(text); + } +} + +static void wrap_move_up(SpaceText *st, short sel) { + int offl, offl_1, offc, fromline, toline, c, target; + Text *text= st->text; + + wrap_offset(st, text->sell, 0, &offl_1, &offc); + wrap_offset(st, text->sell, text->selc, &offl, &offc); + fromline= toline= txt_get_span(text->lines.first, text->sell); + target= text->selc + offc; + + if (offl==offl_1) { + if (!text->sell->prev) { + txt_move_bol(text, sel); + return; + } + toline--; + c= text->sell->prev->len; /* End of prev. line */ + wrap_offset(st, text->sell->prev, c, &offl, &offc); + c= -offc+target; + } else { + c= -offc-1; /* End of prev. line */ + wrap_offset(st, text->sell, c, &offl, &offc); + c= -offc+target; + } + if (c<0) c=0; + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); + if (tolinesell= text->sell->prev; + if (c>text->sell->len) c= text->sell->len; + text->selc= c; + } else { + txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); + if (tolinecurl= text->curl->prev; + if (c>text->curl->len) c= text->curl->len; + text->curc= c; + txt_pop_sel(text); + } +} + +static void wrap_move_down(SpaceText *st, short sel) { + int offl, startoff, offc, fromline, toline, c, target; + Text *text= st->text; + + wrap_offset(st, text->sell, text->selc, &offl, &offc); + fromline= toline= txt_get_span(text->lines.first, text->sell); + target= text->selc + offc; + startoff= offl; + c= text->selc; + while (offl==startoff && text->sell->line[c]!='\0') { + c++; + wrap_offset(st, text->sell, c, &offl, &offc); + } + + if (text->sell->line[c]=='\0') { + if (!text->sell->next) { + txt_move_eol(text, sel); + return; + } + toline++; + c= target; + } else { + c += target; + if (c > text->sell->len) c= text->sell->len; + } + if (c<0) c=0; + + if (sel) { + txt_undo_add_toop(text, UNDO_STO, fromline, text->selc, toline, c); + if (toline>fromline) text->sell= text->sell->next; + if (c>text->sell->len) c= text->sell->len; + text->selc= c; + } else { + txt_undo_add_toop(text, UNDO_CTO, fromline, text->curc, toline, c); + if (toline>fromline) text->curl= text->curl->next; + if (c>text->curl->len) c= text->curl->len; + text->curc= c; + txt_pop_sel(text); + } +} + +static void get_suggest_prefix(Text *text, int offset) { + int i, len; + char *line, tmp[256]; + + if (!text) return; + if (!texttool_text_is_active(text)) return; + + line= text->curl->line; + for (i=text->curc-1+offset; i>=0; i--) + if (!check_identifier(line[i])) + break; + i++; + len= text->curc-i+offset; + if (len > 255) { + printf("Suggestion prefix too long\n"); + len = 255; + } + strncpy(tmp, line+i, len); + tmp[len]= '\0'; + texttool_suggest_prefix(tmp); +} + +static void confirm_suggestion(Text *text, int skipleft) { + int i, over=0; + char *line; + SuggItem *sel; + + if (!text) return; + if (!texttool_text_is_active(text)) return; + + sel = texttool_suggest_selected(); + if (!sel) return; + + line= text->curl->line; + i=text->curc-skipleft-1; + while (i>=0) { + if (!check_identifier(line[i])) + break; + over++; + i--; + } + + for (i=0; iname); + + for (i=0; itext)) return 0; + if (!st->text || st->text->id.lib) return 0; + + if (st->doplugins && texttool_text_is_active(st->text)) { + if (texttool_suggest_first()) tools |= TOOL_SUGG_LIST; + if (texttool_docs_get()) tools |= TOOL_DOCUMENT; + } + + if (ascii) { + if (tools & TOOL_SUGG_LIST) { + if ((ascii != '_' && ascii != '*' && ispunct(ascii)) || check_whitespace(ascii)) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + } else if ((st->overwrite && txt_replace_char(st->text, ascii)) || txt_add_char(st->text, ascii)) { + get_suggest_prefix(st->text, 0); + pop_suggest_list(); + swallow= 1; + draw= 1; + } + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; + + } else if (val==1 && evnt) { + switch (evnt) { + case LEFTMOUSE: + if (do_suggest_select(st)) + swallow= 1; + else { + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + } + draw= 1; + break; + case MIDDLEMOUSE: + if (do_suggest_select(st)) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + swallow= 1; + } else { + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + } + draw= 1; + break; + case ESCKEY: + draw= swallow= 1; + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(); + else if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + else draw= swallow= 0; + break; + case RETKEY: + if (tools & TOOL_SUGG_LIST) { + confirm_suggestion(st->text, 0); + if (st->showsyntax) txt_format_line(st, st->text->curl, 1); + swallow= 1; + draw= 1; + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; + break; + case LEFTARROWKEY: + case BACKSPACEKEY: + if (tools & TOOL_SUGG_LIST) { + if (G.qual) + texttool_suggest_clear(); + else { + /* Work out which char we are about to delete/pass */ + if (st->text->curl && st->text->curc > 0) { + char ch= st->text->curl->line[st->text->curc-1]; + if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) { + get_suggest_prefix(st->text, -1); + pop_suggest_list(); + } + else + texttool_suggest_clear(); + } else + texttool_suggest_clear(); + } + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + break; + case RIGHTARROWKEY: + if (tools & TOOL_SUGG_LIST) { + if (G.qual) + texttool_suggest_clear(); + else { + /* Work out which char we are about to pass */ + if (st->text->curl && st->text->curc < st->text->curl->len) { + char ch= st->text->curl->line[st->text->curc+1]; + if ((ch=='_' || !ispunct(ch)) && !check_whitespace(ch)) { + get_suggest_prefix(st->text, 1); + pop_suggest_list(); + } + else + texttool_suggest_clear(); + } else + texttool_suggest_clear(); + } + } + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0; + break; + case PAGEDOWNKEY: + scroll= SUGG_LIST_SIZE-1; + case WHEELDOWNMOUSE: + case DOWNARROWKEY: + if (tools & TOOL_DOCUMENT) { + doc_scroll++; + swallow= 1; + draw= 1; + break; + } else if (tools & TOOL_SUGG_LIST) { + SuggItem *sel = texttool_suggest_selected(); + if (!sel) { + texttool_suggest_select(texttool_suggest_first()); + } else while (sel && sel!=texttool_suggest_last() && sel->next && scroll--) { + texttool_suggest_select(sel->next); + sel= sel->next; + } + pop_suggest_list(); + swallow= 1; + draw= 1; + break; + } + case PAGEUPKEY: + scroll= SUGG_LIST_SIZE-1; + case WHEELUPMOUSE: + case UPARROWKEY: + if (tools & TOOL_DOCUMENT) { + if (doc_scroll>0) doc_scroll--; + swallow= 1; + draw= 1; + break; + } else if (tools & TOOL_SUGG_LIST) { + SuggItem *sel = texttool_suggest_selected(); + while (sel && sel!=texttool_suggest_first() && sel->prev && scroll--) { + texttool_suggest_select(sel->prev); + sel= sel->prev; + } + pop_suggest_list(); + swallow= 1; + draw= 1; + break; + } + case RIGHTSHIFTKEY: + case LEFTSHIFTKEY: + break; + default: + if (tools & TOOL_SUGG_LIST) texttool_suggest_clear(), draw= 1; + if (tools & TOOL_DOCUMENT) texttool_docs_clear(), doc_scroll= 0, draw= 1; + } + } + + if (draw) { + ScrArea *sa; + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } + } + + return swallow; +} + +static short do_markers(SpaceText *st, char ascii, unsigned short evnt, short val) { + Text *text; + TextMarker *marker, *mrk, *nxt; + int c, s, draw=0, swallow=0; + + text= st->text; + if (!text || text->id.lib || text->curl != text->sell) return 0; + + marker= txt_find_marker(text, text->sell, text->selc, 0, 0); + if (marker && (marker->start > text->curc || marker->end < text->curc)) + marker= NULL; + + if (!marker) { + /* Find the next temporary marker */ + if (evnt==TABKEY) { + int lineno= txt_get_span(text->lines.first, text->curl); + TextMarker *mrk= text->markers.first; + while (mrk) { + if (!marker && (mrk->flags & TMARK_TEMP)) marker= mrk; + if ((mrk->flags & TMARK_TEMP) && (mrk->lineno > lineno || (mrk->lineno==lineno && mrk->end > text->curc))) { + marker= mrk; + break; + } + mrk= mrk->next; + } + if (marker) { + txt_move_to(text, marker->lineno, marker->start, 0); + txt_move_to(text, marker->lineno, marker->end, 1); + pop_space_text(st); + evnt= ascii= val= 0; + draw= 1; + swallow= 1; + } + } else if (evnt==ESCKEY) { + if (txt_clear_markers(text, 0, TMARK_TEMP)) swallow= 1; + else if (txt_clear_markers(text, 0, 0)) swallow= 1; + else return 0; + evnt= ascii= val= 0; + draw= 1; + } + if (!swallow) return 0; + } + + if (ascii) { + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt=txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + if (st->overwrite) { + if (txt_replace_char(text, ascii)) + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } else { + if (txt_add_char(text, ascii)) { + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } + } + + if (mrk==marker || mrk==nxt) break; + mrk=nxt; + } + swallow= 1; + draw= 1; + } + } else if (val) { + switch(evnt) { + case BACKSPACEKEY: + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + txt_backspace_char(text); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (mrk==marker || mrk==nxt) break; + mrk= nxt; + } + swallow= 1; + draw= 1; + } + break; + case DELKEY: + if (marker->flags & TMARK_EDITALL) { + c= text->curc-marker->start; + s= text->selc-marker->start; + if (s<0 || s>marker->end-marker->start) return 0; + + mrk= txt_next_marker(text, marker); + while (mrk) { + nxt= txt_next_marker(text, mrk); /* mrk may become invalid */ + txt_move_to(text, mrk->lineno, mrk->start+c, 0); + if (s!=c) txt_move_to(text, mrk->lineno, mrk->start+s, 1); + txt_delete_char(text); + if (st->showsyntax) txt_format_line(st, text->curl, 1); + if (mrk==marker || mrk==nxt) break; + mrk= nxt; + } + swallow= 1; + draw= 1; + } + break; + case TABKEY: + if (G.qual & LR_SHIFTKEY) { + nxt= marker->prev; + if (!nxt) nxt= text->markers.last; + } else { + nxt= marker->next; + if (!nxt) nxt= text->markers.first; + } + if (marker->flags & TMARK_TEMP) { + if (nxt==marker) nxt= NULL; + BLI_freelinkN(&text->markers, marker); + } + mrk= nxt; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + pop_space_text(st); + } + swallow= 1; + draw= 1; + break; + + /* Events that should clear markers */ + case UKEY: if (!(G.qual & LR_ALTKEY)) break; + case ZKEY: if (evnt==ZKEY && !(G.qual & LR_CTRLKEY)) break; + case RETKEY: + case ESCKEY: + if (marker->flags & (TMARK_EDITALL | TMARK_TEMP)) + txt_clear_markers(text, marker->group, 0); + else + BLI_freelinkN(&text->markers, marker); + swallow= 1; + draw= 1; + break; + case RIGHTMOUSE: /* Marker context menu? */ + case LEFTMOUSE: + break; + case FKEY: /* Allow find */ + if (G.qual & LR_SHIFTKEY) swallow= 1; + break; + + default: + if (G.qual!=0 && G.qual!=LR_SHIFTKEY) + swallow= 1; /* Swallow all other shortcut events */ + } + } + + if (draw) { + ScrArea *sa; + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } + } + return swallow; +} + +static short do_modification_check(SpaceText *st) { + Text *text= st->text; + + if (last_check_time < PIL_check_seconds_timer() - 2.0) { + switch (txt_file_modified(text)) { + case 1: + /* Modified locally and externally, ahhh. Offer more possibilites. */ + if (text->flags & TXT_ISDIRTY) { + switch (pupmenu("File Modified Outside and Inside Blender %t|Load outside changes (ignore local changes) %x0|Save local changes (ignore outside changes) %x1|Make text internal (separate copy) %x2")) { + case 0: + reopen_text(text); + if (st->showsyntax) txt_format_text(st); + return 1; + case 1: + txt_write_file(text); + return 1; + case 2: + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; + return 1; + } + } else { + switch (pupmenu("File Modified Outside Blender %t|Reload from disk %x0|Make text internal (separate copy) %x1|Ignore %x2")) { + case 0: + reopen_text(text); + if (st->showsyntax) txt_format_text(st); + return 1; + case 1: + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; + return 1; + case 2: + txt_ignore_modified(text); + return 1; + } + } + break; + case 2: + switch (pupmenu("File Deleted Outside Blender %t|Make text internal %x0|Recreate file %x1")) { + case 0: + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; + return 1; + case 1: + txt_write_file(text); + return 1; + } + break; + default: + break; + } + last_check_time = PIL_check_seconds_timer(); + } + return 0; +} + void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { unsigned short event= evt->event; @@ -1528,8 +2771,16 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } return; } + + if (val && uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING) event= 0; + + if (st->doplugins && do_texttools(st, ascii, event, val)) return; + if (do_markers(st, ascii, event, val)) return; - if (event==LEFTMOUSE) { + if (event==UI_BUT_EVENT) { + do_find_buttons(val); + do_draw= 1; + } else if (event==LEFTMOUSE) { if (val) { short mval[2]; char *buffer; @@ -1550,20 +2801,20 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } else if (event==MIDDLEMOUSE) { if (val) { - if (U.uiflag & USER_MMB_PASTE) - { + if (U.uiflag & USER_MMB_PASTE) { do_selection(st, G.qual&LR_SHIFTKEY); get_selection_buffer(text); do_draw= 1; - } - else - { + } else { do_textscroll(st, 1); } } } else if (event==RIGHTMOUSE) { if (val) { - p= pupmenu("File %t|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); + if (txt_has_sel(text)) + p= pupmenu("Text %t|Cut%x10|Copy%x11|Paste%x12|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); + else + p= pupmenu("Text %t|Paste%x12|New %x0|Open... %x1|Save %x2|Save As...%x3|Execute Script%x4"); switch(p) { case 0: @@ -1589,13 +2840,48 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) run_python_script(st); do_draw= 1; break; - default: + case 10: + if (text && text->id.lib) { + error_libdata(); + break; + } + txt_copy_clipboard(text); + txt_cut_sel(text); + pop_space_text(st); + do_draw= 1; + break; + case 11: + //txt_copy_sel(text); + txt_copy_clipboard(text); + break; + case 12: + if (text && text->id.lib) { + error_libdata(); + break; + } + txt_paste_clipboard(text); + if (st->showsyntax) txt_format_text(st); + do_draw= 1; break; } } } else if (ascii) { - if (txt_add_char(text, ascii)) { - if (st->showsyntax) get_format_string(st); + if (text && text->id.lib) { + error_libdata(); + } else { + short mval[2]; + getmouseco_areawin(mval); + if (st->showlinenrs && mval[0]>2 && mval[0]<60 && mval[1]>2 && mval[1]winy-2) { + if (ascii>='0' && ascii<='9') { + double time = PIL_check_seconds_timer(); + if (last_jump < time-1) jump_to= 0; + jump_to *= 10; jump_to += (int)(ascii-'0'); + txt_move_toline(text, jump_to-1, 0); + last_jump= time; + } + } else if ((st->overwrite && txt_replace_char(text, ascii)) || txt_add_char(text, ascii)) { + if (st->showsyntax) txt_format_line(st, text->curl, 1); + } pop_space_text(st); do_draw= 1; } @@ -1622,16 +2908,20 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } break; /* BREAK C */ case DKEY: + if (text && text->id.lib) { + error_libdata(); + break; + } if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) { //uncommenting txt_order_cursors(text); uncomment(text); do_draw = 1; - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; } else if (G.qual == LR_CTRLKEY) { txt_delete_char(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_line(st, text->curl, 1); do_draw= 1; pop_space_text(st); } @@ -1640,6 +2930,10 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { switch(pupmenu("Edit %t|Cut %x0|Copy %x1|Paste %x2|Print Cut Buffer %x3")) { case 0: + if (text && text->id.lib) { + error_libdata(); + break; + } txt_copy_clipboard(text); //First copy to clipboard txt_cut_sel(text); do_draw= 1; @@ -1650,9 +2944,13 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) do_draw= 1; break; case 2: + if (text && text->id.lib) { + error_libdata(); + break; + } //txt_paste(text); txt_paste_clipboard(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); do_draw= 1; break; case 3: @@ -1687,17 +2985,17 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; } } - else if (G.qual == LR_ALTKEY) { - if (txt_has_sel(text)) { - txt_find_panel(st,0); - do_draw= 1; - } - } - else if (G.qual == (LR_ALTKEY|LR_CTRLKEY)) { /* always search button */ - txt_find_panel(st,1); + else if (G.qual & (LR_ALTKEY|LR_CTRLKEY)) { + find_and_replace(st, 0); do_draw= 1; } break; /* BREAK F */ + case HKEY: + if (G.qual & (LR_ALTKEY|LR_CTRLKEY)) { + find_and_replace(st, 1); + do_draw= 1; + } + break; /* BREAK H */ case JKEY: if (G.qual == LR_ALTKEY) { do_draw= jumptoline_interactive(st); @@ -1706,7 +3004,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case MKEY: if (G.qual == LR_ALTKEY) { txt_export_to_object(text); - do_draw= 1; + do_draw= 1; } break; /* BREAK M */ case NKEY: @@ -1716,7 +3014,6 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); - } break; /* BREAK N */ case OKEY: @@ -1740,7 +3037,7 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (okee("Reopen text")) { if (!reopen_text(text)) error("Could not reopen file"); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); } do_draw= 1; } @@ -1780,11 +3077,13 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) //txt_print_undo(text); //debug buffer in console if (G.qual == (LR_ALTKEY|LR_SHIFTKEY)) { txt_do_redo(text); + pop_space_text(st); do_draw= 1; } if (G.qual == LR_ALTKEY) { txt_do_undo(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); + pop_space_text(st); do_draw= 1; } break; /* BREAK U */ @@ -1813,20 +3112,28 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } /* Support for both Alt-V and Ctrl-V for Paste, for backward compatibility reasons */ else if (G.qual & LR_ALTKEY || G.qual & LR_CTRLKEY) { + if (text && text->id.lib) { + error_libdata(); + break; + } /* Throwing in the Shift modifier Paste from the OS clipboard */ if (G.qual & LR_SHIFTKEY) txt_paste_clipboard(text); else txt_paste_clipboard(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); do_draw= 1; pop_space_text(st); } break; /* BREAK V */ case XKEY: if (G.qual == LR_ALTKEY || G.qual == LR_CTRLKEY) { + if (text && text->id.lib) { + error_libdata(); + break; + } txt_cut_sel(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); do_draw= 1; pop_space_text(st); } @@ -1838,31 +3145,40 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } else { txt_do_undo(text); } - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); + pop_space_text(st); do_draw= 1; } break; case TABKEY: - if (G.qual & LR_SHIFTKEY) { - if (txt_has_sel(text)) { - txt_order_cursors(text); - unindent(text); - - } + if (text && text->id.lib) { + error_libdata(); + break; } else { - if ( txt_has_sel(text)) { - txt_order_cursors(text); - indent(text); + if (txt_has_sel(text)) { + if (G.qual & LR_SHIFTKEY) { + txt_order_cursors(text); + unindent(text); + if (st->showsyntax) txt_format_text(st); + } else { + txt_order_cursors(text); + indent(text); + if (st->showsyntax) txt_format_text(st); + } } else { txt_add_char(text, '\t'); + if (st->showsyntax) txt_format_line(st, text->curl, 1); } } - if (st->showsyntax) get_format_string(st); pop_space_text(st); do_draw= 1; st->currtab_set = setcurr_tab(text); break; case RETKEY: + if (text && text->id.lib) { + error_libdata(); + break; + } //double check tabs before splitting the line st->currtab_set = setcurr_tab(text); txt_split_curline(text); @@ -1876,33 +3192,52 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } } - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) { + if (text->curl->prev) txt_format_line(st, text->curl->prev, 0); + txt_format_line(st, text->curl, 1); + } do_draw= 1; pop_space_text(st); break; case BACKSPACEKEY: - txt_backspace_char(text); + if (text && text->id.lib) { + error_libdata(); + break; + } + if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { + txt_backspace_word(text); + } else { + txt_backspace_char(text); + } set_tabs(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_line(st, text->curl, 1); do_draw= 1; pop_space_text(st); break; case DELKEY: - txt_delete_char(text); - if (st->showsyntax) get_format_string(st); + if (text && text->id.lib) { + error_libdata(); + break; + } + if (G.qual & (LR_ALTKEY | LR_CTRLKEY)) { + txt_delete_word(text); + } else { + txt_delete_char(text); + } + if (st->showsyntax) txt_format_line(st, text->curl, 1); do_draw= 1; pop_space_text(st); st->currtab_set = setcurr_tab(text); break; - case DOWNARROWKEY: - txt_move_down(text, G.qual & LR_SHIFTKEY); - set_tabs(text); + case INSERTKEY: + st->overwrite= !st->overwrite; do_draw= 1; - pop_space_text(st); break; case LEFTARROWKEY: if (G.qual & LR_COMMANDKEY) txt_move_bol(text, G.qual & LR_SHIFTKEY); + else if (G.qual & LR_ALTKEY) + txt_jump_left(text, G.qual & LR_SHIFTKEY); else txt_move_left(text, G.qual & LR_SHIFTKEY); set_tabs(text); @@ -1912,6 +3247,8 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) case RIGHTARROWKEY: if (G.qual & LR_COMMANDKEY) txt_move_eol(text, G.qual & LR_SHIFTKEY); + else if (G.qual & LR_ALTKEY) + txt_jump_right(text, G.qual & LR_SHIFTKEY); else txt_move_right(text, G.qual & LR_SHIFTKEY); set_tabs(text); @@ -1919,26 +3256,38 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) pop_space_text(st); break; case UPARROWKEY: - txt_move_up(text, G.qual & LR_SHIFTKEY); + if (st->wordwrap) wrap_move_up(st, G.qual & LR_SHIFTKEY); + else txt_move_up(text, G.qual & LR_SHIFTKEY); + set_tabs(text); + do_draw= 1; + pop_space_text(st); + break; + case DOWNARROWKEY: + if (st->wordwrap) wrap_move_down(st, G.qual & LR_SHIFTKEY); + else txt_move_down(text, G.qual & LR_SHIFTKEY); set_tabs(text); do_draw= 1; pop_space_text(st); break; case PAGEDOWNKEY: - screen_skip(st, st->viewlines); + cursor_skip(st, st->viewlines, G.qual & LR_SHIFTKEY); + pop_space_text(st); do_draw= 1; break; case PAGEUPKEY: - screen_skip(st, -st->viewlines); + cursor_skip(st, -st->viewlines, G.qual & LR_SHIFTKEY); + pop_space_text(st); do_draw= 1; break; case HOMEKEY: - txt_move_bol(text, G.qual & LR_SHIFTKEY); + if (st->wordwrap) wrap_move_bol(st, G.qual & LR_SHIFTKEY); + else txt_move_bol(text, G.qual & LR_SHIFTKEY); do_draw= 1; pop_space_text(st); break; case ENDKEY: - txt_move_eol(text, G.qual & LR_SHIFTKEY); + if (st->wordwrap) wrap_move_eol(st, G.qual & LR_SHIFTKEY); + else txt_move_eol(text, G.qual & LR_SHIFTKEY); do_draw= 1; pop_space_text(st); break; @@ -1953,6 +3302,15 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } + /* Run text plugin scripts if enabled */ + if (st->doplugins && event && val) { + if (BPY_menu_do_shortcut(PYMENU_TEXTPLUGIN, event, G.qual)) { + do_draw= 1; + } + } + + if (do_modification_check(st)) do_draw= 1; + if (do_draw) { ScrArea *sa; @@ -1966,179 +3324,150 @@ void winqreadtextspace(ScrArea *sa, void *spacedata, BWinEvent *evt) } } -void do_brackets(void) +void draw_brackets(SpaceText *st) { - SpaceText *st = curarea->spacedata.first; + char ch; + int b, c, startc, endc, find, stack; + int viewc, viewl, offl, offc, x, y; + TextLine *startl, *endl, *linep; Text *text = st->text; - TextLine *tmp, *start; - char test[2]; - int d, pos, open, x, y, x2, y2, h=0; - - if(!text) return; - - tmp = text->curl; - start = text->curl; - test[0] = (unsigned char) tmp->line[text->curc]; - test[1] = '\0'; - - d = check_bracket(test); - if (!d) /* If not pri char */ - { - test[0] = (unsigned char) tmp->line[text->curc-1]; - test[1] = '\0'; - d = check_bracket(test); - if(!d) { - return; /*If the current char or prev is not a bracket then return*/ - } else { /* current char */ - h= txt_get_span(text->lines.first, start) - st->top; - x = text_draw(st, start->line, st->left, text->curc-1, 0, 0, 0, NULL); - y = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL); - if (d < 4) { - pos = text->curc; - } else { - pos = text->curc-2; - } - } - } else { /* is pri char */ - h= txt_get_span(text->lines.first, start) - st->top; - x = text_draw(st, start->line, st->left, text->curc, 0, 0, 0, NULL); - y = text_draw(st, start->line, st->left, text->curc+1, 0, 0, 0, NULL); - if (d < 4) { - pos = text->curc+1; - } else { - pos = text->curc-1; - } - } - - if (d < 4) /*reading forward*/ - { - open = 1; - while ( tmp ) { - while (pos <= tmp->len) { - test[0] = (unsigned char) tmp->line[pos]; - test[1] = '\0'; - if(check_bracket(test) == d) { - open++; - } else if (check_bracket(test) == d+3) { - open--; - if (open == 0) { - BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5); - glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2); + if (!text || !text->curl) return; - h= txt_get_span(text->lines.first, tmp) - st->top; - x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL); - y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL); - glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2); - BIF_ThemeColor(TH_TEXT); - return; + startl= text->curl; + startc= text->curc; + b= check_bracket(startl->line[startc]); + if (b==0 && startc>0) b = check_bracket(startl->line[--startc]); + if (b==0) return; + + linep= startl; + c= startc; + endl= NULL; + endc= -1; + find= -b; + stack= 0; + + /* Opening bracket, search forward for close */ + if (b>0) { + c++; + while (linep) { + while (clen) { + b= check_bracket(linep->line[c]); + if (b==find) { + if (stack==0) { + endl= linep; + endc= c; + break; } + stack--; + } else if (b==-find) { + stack++; } - pos++; + c++; } - tmp = tmp->next; - pos = 0; + if (endl) break; + linep= linep->next; + c= 0; } - } else { /* reading back */ - open = 1; - while ( tmp ) { - while (pos >= 0) { - test[0] = (unsigned char) tmp->line[pos]; - test[1] = '\0'; - if(check_bracket(test) == d) { - open++; - } else if (check_bracket(test) == d-3) { - open--; - if (open == 0) { - BIF_ThemeColorBlend(TH_BACK, TH_SHADE2, 0.5); - glRecti(x, curarea->winy-st->lheight*(h)-2, y, curarea->winy-st->lheight*(h+1)-2); - - h= txt_get_span(text->lines.first, tmp) - st->top; - x2= text_draw(st, tmp->line, st->left, pos, 0, 0, 0, NULL); - y2= text_draw(st, tmp->line, st->left, pos+1, 0, 0, 0, NULL); - glRecti(x2, curarea->winy-st->lheight*(h)-2, y2, curarea->winy-st->lheight*(h+1)-2); - BIF_ThemeColor(TH_TEXT); - return; + } + /* Closing bracket, search backward for open */ + else { + c--; + while (linep) { + while (c>=0) { + b= check_bracket(linep->line[c]); + if (b==find) { + if (stack==0) { + endl= linep; + endc= c; + break; } + stack--; + } else if (b==-find) { + stack++; } - pos--; - } - tmp = tmp->prev; - if (tmp) { - pos = tmp->len; + c--; } + if (endl) break; + linep= linep->prev; + if (linep) c= linep->len-1; } } - + + if (!endl || endc==-1) return; + + BIF_ThemeColor(TH_HILITE); + x= st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + y= curarea->winy - st->lheight; + + ch= startl->line[startc]; + wrap_offset(st, startl, startc, &offl, &offc); + viewc= get_char_pos(st, startl->line, startc) - st->left + offc; + if (viewc >= 0){ + viewl= txt_get_span(text->lines.first, startl) - st->top + offl; + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st), y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st)+1, y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + } + ch= endl->line[endc]; + wrap_offset(st, endl, endc, &offl, &offc); + viewc= get_char_pos(st, endl->line, endc) - st->left + offc; + if (viewc >= 0) { + viewl= txt_get_span(text->lines.first, endl) - st->top + offl; + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st), y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + glRasterPos2i(x+viewc*spacetext_get_fontwidth(st)+1, y-viewl*st->lheight); + BMF_DrawCharacter(spacetext_get_font(st), ch); + } } -int check_bracket(char *string) +static int check_bracket(char ch) { - int number, a = 0; - char other[][3] = {"(", "[", "{", ")", "]", "}"}; + int a; + char opens[] = "([{"; + char close[] = ")]}"; - number = 6; - - while(a < number) { - if(strcmp(other[a], string) == 0) - { + for (a=0; a<3; a++) { + if(ch==opens[a]) return a+1; - } - a++; + else if (ch==close[a]) + return -(a+1); } return 0; } -static int check_builtinfuncs(char *string) +static int check_delim(char ch) { - int number = 30, a = 0; + int a; + char delims[] = "():\"\' ~!%^&*-+=[]{};/<>|.#\t,"; - char builtinfuncs[][11] = {"and", "as", "assert", "break", "class", "continue", "def", - "del", "elif", "else", "except", "exec", "finally", - "for", "from", "global", "if", "import", "in", - "is", "lambda", "not", "or", "pass", "print", - "raise", "return", "try", "while", "yield"}; - - for( a = 0; a < number; a++) { - if(!strcmp(builtinfuncs[a], string)) + for (a=0; a<28; a++) { + if (ch==delims[a]) return 1; } return 0; } -static int check_specialvars(char *string) -{ - int number = 2, a = 0; - char specialvars[][7] = {"def", "class"}; - - for( a = 0; a < number; a++) { - if(!strcmp(specialvars[a], string)) - return a+1; - } +static int check_digit(char ch) { + if (ch < '0') return 0; + if (ch <= '9') return 1; return 0; } -static int check_delim(char *string) -{ - int number = 28, a = 0; - char other[][3] = {"(", ")", ":", "\"", "\'", " ", "~", "!", "%", "^", "&", "*", "-", "+", "=", "[", "]", "{", "}", ";", "/", "<", ">", "|", ".", "#", "\t", ","}; - - for( a = 0; a < number; a++) { - if(!strcmp(other[a], string)) - return 1; - } +static int check_identifier(char ch) { + if (ch < '0') return 0; + if (ch <= '9') return 1; + if (ch < 'A') return 0; + if (ch <= 'Z' || ch == '_') return 1; + if (ch < 'a') return 0; + if (ch <= 'z') return 1; return 0; } -static int check_numbers(char *string) -{ - int number = 10, a = 0; - char other[][2] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; - - for( a = 0; a < number; a++) { - if(!strcmp(other[a], string)) - return 1; - } +static int check_whitespace(char ch) { + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') + return 1; return 0; } @@ -2146,7 +3475,7 @@ void convert_tabs (struct SpaceText *st, int tab) { Text *text = st->text; TextLine *tmp; - char *check_line, *new_line, *format; + char *check_line, *new_line; int extra, number; //unknown for now size_t a, j; @@ -2158,7 +3487,6 @@ void convert_tabs (struct SpaceText *st, int tab) while(tmp) { check_line = tmp->line; new_line = MEM_mallocN(render_string(st, check_line)+1, "Converted_Line"); - format = MEM_mallocN(render_string(st, check_line)+1, "Converted_Syntax_format"); j = 0; for (a=0; a < strlen(check_line); a++) { //foreach char in line if(check_line[a] == '\t') { //checking for tabs @@ -2185,7 +3513,7 @@ void convert_tabs (struct SpaceText *st, int tab) tmp->line = new_line; tmp->len = strlen(new_line); - tmp->format = format; + tmp->format = NULL; tmp = tmp->next; } @@ -2213,7 +3541,6 @@ void convert_tabs (struct SpaceText *st, int tab) if ( extra > 0 ) { //got tabs make malloc and do what you have to do new_line = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Line"); - format = MEM_mallocN(strlen(check_line)-(((st->tabnumber*extra)-extra)-1), "Converted_Syntax_format"); extra = 0; //reuse vars for (a = 0; a < strlen(check_line); a++) { number = 0; @@ -2241,9 +3568,11 @@ void convert_tabs (struct SpaceText *st, int tab) tmp->line = new_line; tmp->len = strlen(new_line); - tmp->format = format; + tmp->format = NULL; } tmp = tmp->next; } } + + if (st->showsyntax) txt_format_text(st); } diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index 2030eb658de..42576c901d7 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -64,6 +64,7 @@ #include "DNA_gpencil_types.h" #include "DNA_image_types.h" #include "DNA_key_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -134,6 +135,7 @@ #include "BIF_verse.h" #endif +#include "BDR_drawaction.h" #include "BDR_drawmesh.h" #include "BDR_drawobject.h" #include "BDR_editobject.h" @@ -162,6 +164,9 @@ #include "RE_pipeline.h" // make_stars +#include "GPU_draw.h" +#include "GPU_material.h" + #include "multires.h" /* For MULTISAMPLE_ARB #define. @@ -193,132 +198,6 @@ static void star_stuff_term_func(void) glEnd(); } -void default_gl_light(void) -{ - int a; - - /* initialize */ - if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { - U.light[0].flag= 1; - U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9; - U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8; - U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5; - U.light[0].spec[3]= 1.0; - - U.light[1].flag= 0; - U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1; - U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8; - U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5; - U.light[1].spec[3]= 1.0; - - U.light[2].flag= 0; - U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2; - U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4; - U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3; - U.light[2].spec[3]= 1.0; - } - - - glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); - glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); - glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); - - glLightfv(GL_LIGHT1, GL_POSITION, U.light[1].vec); - glLightfv(GL_LIGHT1, GL_DIFFUSE, U.light[1].col); - glLightfv(GL_LIGHT1, GL_SPECULAR, U.light[1].spec); - - glLightfv(GL_LIGHT2, GL_POSITION, U.light[2].vec); - glLightfv(GL_LIGHT2, GL_DIFFUSE, U.light[2].col); - glLightfv(GL_LIGHT2, GL_SPECULAR, U.light[2].spec); - - for(a=0; a<8; a++) { - if(a<3) { - if(U.light[a].flag) glEnable(GL_LIGHT0+a); - else glDisable(GL_LIGHT0+a); - - // clear stuff from other opengl lamp usage - glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0); - glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0); - glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0); - } - else glDisable(GL_LIGHT0+a); - } - - glDisable(GL_LIGHTING); - - glDisable(GL_COLOR_MATERIAL); -} - -/* also called when render 'ogl' - keep synced with Myinit_gl_stuff in the game engine! */ -void init_gl_stuff(void) -{ - float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; - float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - float mat_shininess[] = { 35.0 }; - int a, x, y; - GLubyte pat[32*32]; - const GLubyte *patc= pat; - - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - - default_gl_light(); - - /* no local viewer, looks ugly in ortho mode */ - /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ - - glDepthFunc(GL_LEQUAL); - /* scaling matrices */ - glEnable(GL_NORMALIZE); - - glShadeModel(GL_FLAT); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - glDisable(GL_LIGHTING); - glDisable(GL_LOGIC_OP); - glDisable(GL_STENCIL_TEST); - glDisable(GL_TEXTURE_1D); - glDisable(GL_TEXTURE_2D); - - /* default on, disable/enable should be local per function */ - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glPixelTransferi(GL_MAP_COLOR, GL_FALSE); - glPixelTransferi(GL_RED_SCALE, 1); - glPixelTransferi(GL_RED_BIAS, 0); - glPixelTransferi(GL_GREEN_SCALE, 1); - glPixelTransferi(GL_GREEN_BIAS, 0); - glPixelTransferi(GL_BLUE_SCALE, 1); - glPixelTransferi(GL_BLUE_BIAS, 0); - glPixelTransferi(GL_ALPHA_SCALE, 1); - glPixelTransferi(GL_ALPHA_BIAS, 0); - - glPixelTransferi(GL_DEPTH_BIAS, 0); - glPixelTransferi(GL_DEPTH_SCALE, 1); - glDepthRange(0.0, 1.0); - - a= 0; - for(x=0; x<32; x++) { - for(y=0; y<4; y++) { - if( (x) & 1) pat[a++]= 0x88; - else pat[a++]= 0x22; - } - } - - glPolygonStipple(patc); - - - init_realtime_GL(); -} - void circf(float x, float y, float rad) { GLUquadricObj *qobj = gluNewQuadric(); @@ -1329,60 +1208,196 @@ void drawname(Object *ob) BMF_DrawString(G.font, ob->id.name+2); } +static char *get_cfra_marker_name() +{ + ListBase *markers= &G.scene->markers; + TimeMarker *m1, *m2; + + /* search through markers for match */ + for (m1=markers->first, m2=markers->last; m1 && m2; m1=m1->next, m2=m2->prev) { + if (m1->frame==CFRA) + return m1->name; + if (m2->frame==CFRA) + return m2->name; + + if (m1 == m2) + break; + } + + return NULL; +} +// TODO: move this func into some keyframing API +short ob_cfra_has_keyframe (Object *ob) +{ + // fixme... this is slow! + if (ob) { + ListBase keys = {NULL, NULL}; + ActKeyColumn *ak, *akn; + Key *key= ob_get_key(ob); + int cfra, found= 0; + + /* check active action */ + if (ob->action) { + /* get keyframes of action */ + action_to_keylist(ob->action, &keys, NULL, NULL); + + cfra= frame_to_float(CFRA); + cfra= get_action_frame(ob, cfra); + + /* check if a keyframe occurs on current frame */ + for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { + if (cfra == ak->cfra) { + found= 1; + break; + } + else if (cfra == akn->cfra) { + found= 1; + break; + } + + if (ak == akn) + break; + } + + /* free temp list */ + BLI_freelistN(&keys); + keys.first= keys.last= NULL; + + /* return if found */ + if (found) return 1; + } + + /* accumulate keyframes for available ipo's */ + if (ob->ipo) + ipo_to_keylist(ob->ipo, &keys, NULL, NULL); + if (key) + ipo_to_keylist(key->ipo, &keys, NULL, NULL); + + if (keys.first) { + cfra= frame_to_float(CFRA); + found= 0; + + /* check if a keyframe occurs on current frame */ + for (ak=keys.first, akn=keys.last; ak && akn; ak=ak->next, akn=akn->prev) { + if (IS_EQ(cfra, ak->cfra)) { + found= 1; + break; + } + else if (IS_EQ(cfra, akn->cfra)) { + found= 1; + break; + } + + if (ak == akn) + break; + } + + /* free temp list */ + BLI_freelistN(&keys); + keys.first= keys.last= NULL; + + /* return if found */ + if (found) return 1; + } + } + + /* couldn't find a keyframe */ + return 0; +} + +/* draw info beside axes in bottom left-corner: + * framenum, object name, bone name (if available), marker name (if available) + */ static void draw_selected_name(Object *ob) { - char info[128]; + char info[256], *markern; short offset=30; - - if(ob->type==OB_ARMATURE) { - bArmature *arm= ob->data; - char *name= NULL; - - if(ob==G.obedit) { - EditBone *ebo; - for (ebo=G.edbo.first; ebo; ebo=ebo->next){ - if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { - name= ebo->name; - break; + + /* get name of marker on current frame (if available) */ + markern= get_cfra_marker_name(); + + /* check if there is an object */ + if(ob) { + /* name(s) to display depends on type of object */ + if(ob->type==OB_ARMATURE) { + bArmature *arm= ob->data; + char *name= NULL; + + /* show name of active bone too (if possible) */ + if(ob==G.obedit) { + EditBone *ebo; + for (ebo=G.edbo.first; ebo; ebo=ebo->next){ + if ((ebo->flag & BONE_ACTIVE) && (ebo->layer & arm->layer)) { + name= ebo->name; + break; + } } } - } - else if(ob->pose && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { - name= pchan->name; - break; + else if(ob->pose && (ob->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if((pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer)) { + name= pchan->name; + break; + } } } + if(name && markern) + sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, name, markern); + else if(name) + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); } - if(name) - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, name); + else if(ELEM3(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) { + Key *key= NULL; + KeyBlock *kb = NULL; + char shapes[75]; + + /* try to display active shapekey too */ + shapes[0] = 0; + key = ob_get_key(ob); + if(key){ + kb = BLI_findlink(&key->block, ob->shapenr-1); + if(kb){ + sprintf(shapes, ": %s ", kb->name); + if(ob->shapeflag == OB_SHAPE_LOCK){ + sprintf(shapes, "%s (Pinned)",shapes); + } + } + } + + if(markern) + sprintf(info, "(%d) %s %s <%s>", CFRA, ob->id.name+2, shapes, markern); + else + sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + } + else { + /* standard object */ + if (markern) + sprintf(info, "(%d) %s <%s>", CFRA, ob->id.name+2, markern); + else + sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + } + + /* colour depends on whether there is a keyframe */ + if (ob_cfra_has_keyframe(ob)) + BIF_ThemeColor(TH_VERTEX_SELECT); else - sprintf(info, "(%d) %s", CFRA, ob->id.name+2); + BIF_ThemeColor(TH_TEXT_HI); } - else if(ob->type==OB_MESH) { - Key *key= NULL; - KeyBlock *kb = NULL; - char shapes[75]; + else { + /* no object */ + if (markern) + sprintf(info, "(%d) <%s>", CFRA, markern); + else + sprintf(info, "(%d)", CFRA); - shapes[0] = 0; - key = ob_get_key(ob); - if(key){ - kb = BLI_findlink(&key->block, ob->shapenr-1); - if(kb){ - sprintf(shapes, ": %s ", kb->name); - if(ob->shapeflag == OB_SHAPE_LOCK){ - sprintf(shapes, "%s (Pinned)",shapes); - } - } - } - sprintf(info, "(%d) %s %s", CFRA, ob->id.name+2, shapes); + /* colour is always white */ + BIF_ThemeColor(TH_TEXT_HI); } - else sprintf(info, "(%d) %s", CFRA, ob->id.name+2); - - BIF_ThemeColor(TH_TEXT_HI); + if (U.uiflag & USER_SHOW_ROTVIEWICON) offset = 14 + (U.rvisize * 2); @@ -2737,7 +2752,7 @@ void add_view3d_after(View3D *v3d, Base *base, int type, int flag) } /* clears zbuffer and draws it over */ -static void view3d_draw_xray(View3D *v3d) +static void view3d_draw_xray(View3D *v3d, int clear) { View3DAfter *v3da, *next; int doit= 0; @@ -2746,7 +2761,7 @@ static void view3d_draw_xray(View3D *v3d) if(v3da->type==V3D_XRAY) doit= 1; if(doit) { - if(v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); + if(clear && v3d->zbuf) glClear(GL_DEPTH_BUFFER_BIT); v3d->xray= TRUE; for(v3da= v3d->afterdraw.first; v3da; v3da= next) { @@ -2768,7 +2783,7 @@ static void view3d_draw_transp(View3D *v3d) glDepthMask(0); v3d->transp= TRUE; - + for(v3da= v3d->afterdraw.first; v3da; v3da= next) { next= v3da->next; if(v3da->type==V3D_TRANSP) { @@ -2811,7 +2826,8 @@ static void draw_dupli_objects_color(View3D *v3d, Base *base, int color) tbase.object= dob->ob; /* extra service: draw the duplicator in drawtype of parent */ - dt= tbase.object->dt; tbase.object->dt= base->object->dt; + /* MIN2 for the drawtype to allow bounding box objects in groups for lods */ + dt= tbase.object->dt; tbase.object->dt= MIN2(tbase.object->dt, base->object->dt); dtx= tbase.object->dtx; tbase.object->dtx= base->object->dtx; /* negative scale flag has to propagate */ @@ -2946,7 +2962,7 @@ static void draw_sculpt_depths(View3D *v3d) } } -void draw_depth(ScrArea *sa, void *spacedata) +void draw_depth(ScrArea *sa, void *spacedata, int (* func)(void *)) { View3D *v3d= spacedata; Base *base; @@ -2986,9 +3002,11 @@ void draw_depth(ScrArea *sa, void *spacedata) if(G.scene->set) { for(SETLOOPER(G.scene->set, base)) { if(v3d->lay & base->lay) { - draw_object(base, 0); - if(base->object->transflag & OB_DUPLI) { - draw_dupli_objects_color(v3d, base, TH_WIRE); + if (func == NULL || func(base)) { + draw_object(base, 0); + if(base->object->transflag & OB_DUPLI) { + draw_dupli_objects_color(v3d, base, TH_WIRE); + } } } } @@ -2996,12 +3014,13 @@ void draw_depth(ScrArea *sa, void *spacedata) for(base= G.scene->base.first; base; base= base->next) { if(v3d->lay & base->lay) { - - /* dupli drawing */ - if(base->object->transflag & OB_DUPLI) { - draw_dupli_objects(v3d, base); + if (func == NULL || func(base)) { + /* dupli drawing */ + if(base->object->transflag & OB_DUPLI) { + draw_dupli_objects(v3d, base); + } + draw_object(base, 0); } - draw_object(base, 0); } } @@ -3046,6 +3065,84 @@ void draw_depth(ScrArea *sa, void *spacedata) static void draw_viewport_fps(ScrArea *sa); +typedef struct View3DShadow{ + struct View3DShadow*next, *prev; + GPULamp *lamp; +} View3DShadow; + +static void gpu_render_lamp_update(View3D *v3d, Object *ob, Object *par, float obmat[][4], ListBase *shadows) +{ + GPULamp *lamp; + View3DShadow *shadow; + + lamp = GPU_lamp_from_blender(G.scene, ob, par); + + if(lamp) { + GPU_lamp_update(lamp, ob->lay, obmat); + + if((ob->lay & v3d->lay) && GPU_lamp_has_shadow_buffer(lamp)) { + shadow= MEM_callocN(sizeof(View3DShadow), "View3DShadow"); + shadow->lamp = lamp; + BLI_addtail(shadows, shadow); + } + } +} + +static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) +{ + ListBase shadows; + View3DShadow *shadow; + Scene *sce; + Base *base; + Object *ob; + + shadows.first= shadows.last= NULL; + + /* update lamp transform and gather shadow lamps */ + for(SETLOOPER(G.scene, base)) { + ob= base->object; + + if(ob->type == OB_LAMP) + gpu_render_lamp_update(v3d, ob, NULL, ob->obmat, &shadows); + + if (ob->transflag & OB_DUPLI) { + DupliObject *dob; + ListBase *lb = object_duplilist(G.scene, ob); + + for(dob=lb->first; dob; dob=dob->next) + if(dob->ob->type==OB_LAMP) + gpu_render_lamp_update(v3d, dob->ob, ob, dob->mat, &shadows); + + free_object_duplilist(lb); + } + } + + /* render shadows after updating all lamps, nested object_duplilist + * don't work correct since it's replacing object matrices */ + for(shadow=shadows.first; shadow; shadow=shadow->next) { + /* this needs to be done better .. */ + float viewmat[4][4], winmat[4][4]; + int drawtype, lay, winsize, flag2; + + drawtype= v3d->drawtype; + lay= v3d->lay; + flag2= v3d->flag2 & V3D_SOLID_TEX; + + v3d->drawtype = OB_SOLID; + v3d->lay &= GPU_lamp_shadow_layer(shadow->lamp); + v3d->flag2 &= ~V3D_SOLID_TEX; + + GPU_lamp_shadow_buffer_bind(shadow->lamp, viewmat, &winsize, winmat); + drawview3d_render(v3d, viewmat, winsize, winsize, winmat, 1); + GPU_lamp_shadow_buffer_unbind(shadow->lamp); + + v3d->drawtype= drawtype; + v3d->lay= lay; + v3d->flag2 |= flag2; + } + + BLI_freelistN(&shadows); +} void drawview3dspace(ScrArea *sa, void *spacedata) { @@ -3063,9 +3160,16 @@ void drawview3dspace(ScrArea *sa, void *spacedata) for(SETLOOPER(G.scene->set, base)) object_handle_update(base->object); // bke_object.h } - - for(base= G.scene->base.first; base; base= base->next) + + v3d->lay_used = 0; + for(base= G.scene->base.first; base; base= base->next) { object_handle_update(base->object); // bke_object.h + v3d->lay_used |= base->lay; + } + + /* shadow buffers, before we setup matrices */ + if(draw_glsl_material(NULL, v3d->drawtype)) + gpu_update_lamps_shadows(G.scene, v3d); setwinmatrixview3d(sa->winx, sa->winy, NULL); /* 0= no pick rect */ setviewmatrixview3d(); /* note: calls where_is_object for camera... */ @@ -3208,8 +3312,8 @@ void drawview3dspace(ScrArea *sa, void *spacedata) if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID); /* Transp and X-ray afterdraw stuff */ - view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); + view3d_draw_xray(v3d, 1); // clears zbuffer if it is used! if(!retopo && sculptparticle && (obact && (OBACT->dtx & OB_DRAWXRAY))) { if(G.f & G_SCULPTMODE) @@ -3290,7 +3394,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } ob= OBACT; - if(ob && (U.uiflag & USER_DRAWVIEWINFO)) + if(U.uiflag & USER_DRAWVIEWINFO) draw_selected_name(ob); draw_area_emboss(sa); @@ -3328,18 +3432,29 @@ void drawview3dspace(ScrArea *sa, void *spacedata) } - -void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4]) +void drawview3d_render(struct View3D *v3d, float viewmat[][4], int winx, int winy, float winmat[][4], int shadow) { Base *base; Scene *sce; - float v3dwinmat[4][4]; + float v3dviewmat[4][4], v3dwinmat[4][4]; + + /* shadow buffers, before we setup matrices */ + if(!shadow && draw_glsl_material(NULL, v3d->drawtype)) + gpu_update_lamps_shadows(G.scene, v3d); if(!winmat) setwinmatrixview3d(winx, winy, NULL); - setviewmatrixview3d(); - myloadmatrix(v3d->viewmat); + if(viewmat) { + Mat4CpyMat4(v3dviewmat, viewmat); + Mat4CpyMat4(v3d->viewmat, viewmat); + } + else { + setviewmatrixview3d(); + Mat4CpyMat4(v3dviewmat, v3d->viewmat); + } + + myloadmatrix(v3dviewmat); /* when winmat is not NULL, it overrides the regular window matrix */ glMatrixMode(GL_PROJECTION); @@ -3348,12 +3463,14 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] mygetmatrix(v3dwinmat); glMatrixMode(GL_MODELVIEW); - Mat4MulMat4(v3d->persmat, v3d->viewmat, v3dwinmat); + Mat4MulMat4(v3d->persmat, v3dviewmat, v3dwinmat); Mat4Invert(v3d->persinv, v3d->persmat); Mat4Invert(v3d->viewinv, v3d->viewmat); - free_all_realtime_images(); - reshadeall_displist(); + if(!shadow) { + GPU_free_images(); + reshadeall_displist(); + } if(v3d->drawtype > OB_WIRE) { v3d->zbuf= TRUE; @@ -3431,8 +3548,8 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] if(G.scene->radio) RAD_drawall(v3d->drawtype>=OB_SOLID); /* Transp and X-ray afterdraw stuff */ - view3d_draw_xray(v3d); // clears zbuffer if it is used! view3d_draw_transp(v3d); + view3d_draw_xray(v3d, !shadow); // clears zbuffer if it is used! if(v3d->flag & V3D_CLIPPING) view3d_clr_clipping(); @@ -3451,11 +3568,12 @@ void drawview3d_render(struct View3D *v3d, int winx, int winy, float winmat[][4] G.f &= ~G_SIMULATION; - glFlush(); + if(!shadow) { + glFlush(); + GPU_free_images(); + } glLoadIdentity(); - - free_all_realtime_images(); } diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index c454715b1df..220265fcbaf 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -74,6 +74,7 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -2101,7 +2102,7 @@ void paste_actdata () /* from selected channels */ for (ale= act_data.first; ale; ale= ale->next) { - Ipo *ipo_src=NULL, *ipo_dst=ale->key_data; + Ipo *ipo_src=NULL; bActionChannel *achan; IpoCurve *ico, *icu; BezTriple *bezt; @@ -2148,12 +2149,12 @@ void paste_actdata () } /* this shouldn't happen, but it might */ - if (ELEM(NULL, ipo_src, ipo_dst)) + if (ipo_src == NULL) continue; /* loop over curves, pasting keyframes */ for (ico= ipo_src->curve.first; ico; ico= ico->next) { - icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode); + icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, NULL, ico->adrcode, 1); if (icu) { /* just start pasting, with the the first keyframe on the current frame, and so on */ diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c index 35986fcff4a..5e50c8117cc 100644 --- a/source/blender/src/editarmature.c +++ b/source/blender/src/editarmature.c @@ -439,6 +439,109 @@ void docenter_armature (Object *ob, int centermode) } } +/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */ +static void applyarmature_fix_boneparents (Object *armob) +{ + Object *ob; + + /* go through all objects in database */ + for (ob= G.main->object.first; ob; ob= ob->id.next) { + /* if parent is bone in this armature, apply corrections */ + if ((ob->parent == armob) && (ob->partype == PARBONE)) { + /* apply current transform from parent (not yet destroyed), + * then calculate new parent inverse matrix + */ + apply_obmat(ob); + + what_does_parent(ob); + Mat4Invert(ob->parentinv, workob.obmat); + } + } +} + +/* set the current pose as the restpose */ +void apply_armature_pose2bones(void) +{ + Object *ob; + bArmature *arm; + bPose *pose; + bPoseChannel *pchan; + EditBone *curbone; + + /* don't check if editmode (should be done by caller) */ + ob= OBACT; + if (ob->type!=OB_ARMATURE) return; + if (object_data_is_libdata(ob)) { + error_libdata(); + return; + } + arm= get_armature(ob); + + /* helpful warnings... */ + // TODO: add warnings to be careful about actions, applying deforms first, etc. + + /* Get editbones of active armature to alter */ + if (G.edbo.first) BLI_freelistN(&G.edbo); + make_boneList(&G.edbo, &arm->bonebase, NULL); + + /* get pose of active object and move it out of posemode */ + pose= ob->pose; + + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { + curbone= editbone_name_exists(&G.edbo, pchan->name); + + /* simply copy the head/tail values from pchan over to curbone */ + VECCOPY(curbone->head, pchan->pose_head); + VECCOPY(curbone->tail, pchan->pose_tail); + + /* fix roll: + * 1. find auto-calculated roll value for this bone now + * 2. remove this from the 'visual' y-rotation + */ + { + float premat[3][3], imat[3][3],pmat[3][3], tmat[3][3]; + float delta[3], eul[3]; + + /* obtain new auto y-rotation */ + VecSubf(delta, curbone->tail, curbone->head); + vec_roll_to_mat3(delta, 0.0, premat); + Mat3Inv(imat, premat); + + /* get pchan 'visual' matrix */ + Mat3CpyMat4(pmat, pchan->pose_mat); + + /* remove auto from visual and get euler rotation */ + Mat3MulMat3(tmat, imat, pmat); + Mat3ToEul(tmat, eul); + + /* just use this euler-y as new roll value */ + curbone->roll= eul[1]; + } + + /* clear transform values for pchan */ + pchan->loc[0]= pchan->loc[1]= pchan->loc[2]= 0; + pchan->quat[1]= pchan->quat[2]= pchan->quat[3]= 0; + pchan->quat[0]= pchan->size[0]= pchan->size[1]= pchan->size[2]= 1; + + /* set anim lock */ + curbone->flag |= BONE_UNKEYED; + } + + /* convert editbones back to bones */ + editbones_to_armature(&G.edbo, ob); + if (G.edbo.first) BLI_freelistN(&G.edbo); + + /* flush positions of posebones */ + where_is_pose(ob); + + /* fix parenting of objects which are bone-parented */ + applyarmature_fix_boneparents(ob); + + BIF_undo_push("Apply new restpose"); + allqueue(REDRAWVIEW3D, 0); +} + + /* Helper function for armature joining - link fixing */ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone) { diff --git a/source/blender/src/editdeform.c b/source/blender/src/editdeform.c index 5de4c6ed23c..3f178e1ea2b 100644 --- a/source/blender/src/editdeform.c +++ b/source/blender/src/editdeform.c @@ -270,7 +270,7 @@ static void del_defgroup_update_users(Object *ob, int id) int a; /* these cases don't use names to refer to vertex groups, so when - * they get deleted the numbers get out of synce, this corrects that */ + * they get deleted the numbers get out of sync, this corrects that */ if(ob->soft) { if(ob->soft->vertgroup == id) diff --git a/source/blender/src/editface.c b/source/blender/src/editface.c index 781210cd373..008ddf3b5f0 100644 --- a/source/blender/src/editface.c +++ b/source/blender/src/editface.c @@ -82,13 +82,14 @@ #include "BIF_space.h" /* for allqueue */ #include "BIF_drawimage.h" /* for allqueue */ -#include "BDR_drawmesh.h" #include "BDR_editface.h" #include "BDR_vpaint.h" #include "BDR_editface.h" #include "BDR_vpaint.h" +#include "GPU_draw.h" + #include "mydevice.h" #include "blendef.h" #include "butspace.h" @@ -1315,7 +1316,7 @@ void set_texturepaint() /* toggle */ if(G.f & G_TEXTUREPAINT) { G.f &= ~G_TEXTUREPAINT; - texpaint_enable_mipmap(); + GPU_paint_set_mipmap(1); } else if (me) { G.f |= G_TEXTUREPAINT; @@ -1324,7 +1325,7 @@ void set_texturepaint() /* toggle */ make_tfaces(me); brush_check_exists(&G.scene->toolsettings->imapaint.brush); - texpaint_disable_mipmap(); + GPU_paint_set_mipmap(0); } allqueue(REDRAWVIEW3D, 0); diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index cd6aefdb87c..09862636085 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -97,6 +97,7 @@ #include "BIF_editseq.h" #include "BIF_editview.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -1776,113 +1777,129 @@ void do_ipo_selectbuttons(void) - if bonename, the constname is the ipo to the constraint */ -/* note; check header_ipo.c, spaceipo_assign_ipo() too */ -Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename) +/* note: check header_ipo.c, spaceipo_assign_ipo() too */ +Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename, short add) { - - if(from==NULL || from->lib) return NULL; + /* lib-linked data is not appropriate here */ + if ((from==NULL) || (from->lib)) + return NULL; /* first check action ipos */ - if(actname && actname[0]) { + if (actname && actname[0]) { Object *ob= (Object *)from; bActionChannel *achan; - if(GS(from->name)!=ID_OB) { + if (GS(from->name)!=ID_OB) { printf("called ipo system for action with wrong base pointer\n"); return NULL; } - if(ob->action==NULL) + if ((ob->action==NULL) && (add)) ob->action= add_empty_action("Action"); - achan= verify_action_channel(ob->action, actname); + if (add) + achan= verify_action_channel(ob->action, actname); + else + achan= get_action_channel(ob->action, actname); - if(achan) { + if (achan) { /* automatically assign achan to act-group based on pchan's grouping */ - if (blocktype == ID_PO) + if ((blocktype == ID_PO) && (add)) verify_pchan2achan_grouping(ob->action, ob->pose, actname); /* constraint exception */ - if(blocktype==ID_CO) { - bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname); - if(conchan->ipo==NULL) { - conchan->ipo= add_ipo("CoIpo", ID_CO); + if (blocktype==ID_CO) { + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&achan->constraintChannels, constname); + else + conchan= get_constraint_channel(&achan->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; } - return conchan->ipo; } else { - if(achan->ipo==NULL) { + if ((achan->ipo==NULL) && (add)) achan->ipo= add_ipo("ActIpo", blocktype); - } - return achan->ipo; } } } else { - - switch(GS(from->name)) { + switch (GS(from->name)) { case ID_OB: { Object *ob= (Object *)from; /* constraint exception */ - if(blocktype==ID_CO) { + if (blocktype==ID_CO) { /* check the local constraint ipo */ - if(bonename && bonename[0] && ob->pose) { + if (bonename && bonename[0] && ob->pose) { bPoseChannel *pchan= get_pose_channel(ob->pose, bonename); bConstraint *con; - for(con= pchan->constraints.first; con; con= con->next) - if(strcmp(con->name, constname)==0) + + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(con->name, constname)==0) break; - if(con) { - if(con->ipo==NULL) { + } + + if (con) { + if ((con->ipo==NULL) && (add)) con->ipo= add_ipo("CoIpo", ID_CO); - } return con->ipo; } } else { /* the actionchannel */ - bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname); - if(conchan->ipo==NULL) { - conchan->ipo= add_ipo("CoIpo", ID_CO); + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&ob->constraintChannels, constname); + else + conchan= get_constraint_channel(&ob->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; } - return conchan->ipo; } } - else if(blocktype==ID_OB) { - if(ob->ipo==NULL) { + else if (blocktype==ID_OB) { + if ((ob->ipo==NULL) && (add)) ob->ipo= add_ipo("ObIpo", ID_OB); - } return ob->ipo; } - else if(blocktype==ID_KE) { + else if (blocktype==ID_KE) { Key *key= ob_get_key((Object *)from); - if(key) { - if(key->ipo==NULL) { + if (key) { + if ((key->ipo==NULL) && (add)) key->ipo= add_ipo("KeyIpo", ID_KE); - } return key->ipo; } return NULL; } - else if(blocktype== ID_FLUIDSIM) { + else if (blocktype== ID_FLUIDSIM) { Object *ob= (Object *)from; - if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { + + if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { FluidsimSettings *fss= ob->fluidsimSettings; - if(fss->ipo==NULL) { + + if ((fss->ipo==NULL) && (add)) fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM); - //fprintf(stderr,"FSIPO NEW!\n"); - } return fss->ipo; } } - else if(blocktype== ID_PA){ + else if(blocktype== ID_PA) { Object *ob= (Object *)from; ParticleSystem *psys= psys_get_current(ob); - if(psys){ - if(psys->part->ipo==0) + + if (psys) { + if ((psys->part->ipo==NULL) && (add)) psys->part->ipo= add_ipo("ParticleIpo", ID_PA); return psys->part->ipo; } @@ -1893,30 +1910,27 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char case ID_MA: { Material *ma= (Material *)from; - - if(ma->ipo==NULL) { + + if ((ma->ipo==NULL) && (add)) ma->ipo= add_ipo("MatIpo", ID_MA); - } return ma->ipo; } break; case ID_TE: { Tex *tex= (Tex *)from; - - if(tex->ipo==NULL) { + + if ((tex->ipo==NULL) && (add)) tex->ipo= add_ipo("TexIpo", ID_TE); - } return tex->ipo; } break; case ID_SEQ: { Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */ - - if(seq->ipo==NULL) { + + if ((seq->ipo==NULL) && (add)) seq->ipo= add_ipo("SeqIpo", ID_SEQ); - } update_seq_ipo_rect(seq); return seq->ipo; } @@ -1925,19 +1939,17 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Curve *cu= (Curve *)from; - if(cu->ipo==NULL) { + if ((cu->ipo==NULL) && (add)) cu->ipo= add_ipo("CuIpo", ID_CU); - } return cu->ipo; } break; case ID_WO: { World *wo= (World *)from; - - if(wo->ipo==NULL) { + + if ((wo->ipo==NULL) && (add)) wo->ipo= add_ipo("WoIpo", ID_WO); - } return wo->ipo; } break; @@ -1945,29 +1957,26 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Lamp *la= (Lamp *)from; - if(la->ipo==NULL) { + if ((la->ipo==NULL) && (add)) la->ipo= add_ipo("LaIpo", ID_LA); - } return la->ipo; } break; case ID_CA: { Camera *ca= (Camera *)from; - - if(ca->ipo==NULL) { + + if ((ca->ipo==NULL) && (add)) ca->ipo= add_ipo("CaIpo", ID_CA); - } return ca->ipo; } break; case ID_SO: { bSound *snd= (bSound *)from; - - if(snd->ipo==NULL) { + + if ((snd->ipo==NULL) && (add)) snd->ipo= add_ipo("SndIpo", ID_SO); - } return snd->ipo; } } @@ -1979,32 +1988,36 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char /* returns and creates * Make sure functions check for NULL or they will crash! * */ -IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode) +IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode, short add) { Ipo *ipo; IpoCurve *icu= NULL; /* return 0 if lib */ - /* creates ipo too */ - ipo= verify_ipo(from, blocktype, actname, constname, bonename); + /* creates ipo too (if add) */ + ipo= verify_ipo(from, blocktype, actname, constname, bonename, add); - if(ipo && ipo->id.lib==NULL && from->lib==NULL) { - - for(icu= ipo->curve.first; icu; icu= icu->next) { - if(icu->adrcode==adrcode) break; + if (ipo && ipo->id.lib==NULL && from->lib==NULL) { + /* try to find matching curve */ + for (icu= ipo->curve.first; icu; icu= icu->next) { + if (icu->adrcode==adrcode) + break; } - if(icu==NULL) { + + /* make a new one if none found (and can add) */ + if ((icu==NULL) && (add)) { icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); - icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ; - if(ipo->curve.first==NULL) icu->flag |= IPO_ACTIVE; /* first one added active */ + icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ); + if (ipo->curve.first==NULL) + icu->flag |= IPO_ACTIVE; /* first one added active */ icu->blocktype= blocktype; icu->adrcode= adrcode; set_icu_vars(icu); - BLI_addtail( &(ipo->curve), icu); + BLI_addtail(&ipo->curve, icu); switch (GS(from->name)) { case ID_SEQ: { @@ -2016,190 +2029,12 @@ IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constn } } } - + + /* return ipo-curve */ return icu; } -/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ -#define BEZT_INSERT_THRESH 0.00001 - -/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) - * Returns the index to insert at (data already at that index will be offset if replace is 0) - */ -static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) -{ - int start=0, end=arraylen; - int loopbreaker= 0, maxloop= arraylen * 2; - const float frame= (item)? item->vec[1][0] : 0.0f; - - /* initialise replace-flag first */ - *replace= 0; - - /* sneaky optimisations (don't go through searching process if...): - * - keyframe to be added is to be added out of current bounds - * - keyframe to be added would replace one of the existing ones on bounds - */ - if ((arraylen <= 0) || ELEM(NULL, array, item)) { - printf("Warning: binarysearch_bezt_index encountered invalid array \n"); - return 0; - } - else { - /* check whether to add before/after/on */ - float framenum; - - /* 'First' Keyframe (when only one keyframe, this case is used) */ - framenum= array[0].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace = 1; - return 0; - } - else if (frame < framenum) - return 0; - - /* 'Last' Keyframe */ - framenum= array[(arraylen-1)].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace= 1; - return (arraylen - 1); - } - else if (frame > framenum) - return arraylen; - } - - - /* most of the time, this loop is just to find where to put it - * 'loopbreaker' is just here to prevent infinite loops - */ - for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { - /* compute and get midpoint */ - int mid = (start + end) / 2; - float midfra= array[mid].vec[1][0]; - - /* check if exactly equal to midpoint */ - if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { - *replace = 1; - return mid; - } - - /* repeat in upper/lower half */ - if (frame > midfra) - start= mid + 1; - else if (frame < midfra) - end= mid - 1; - } - - /* print error if loop-limit exceeded */ - if (loopbreaker == (maxloop-1)) { - printf("Error: binarysearch_bezt_index was taking too long \n"); - - // include debug info - printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); - } - - /* not found, so return where to place it */ - return start; -} - -/* This function adds a given BezTriple to an IPO-Curve. It will allocate - * memory for the array if needed, and will insert the BezTriple into a - * suitable place in chronological order. - * - * NOTE: any recalculate of the IPO-Curve that needs to be done will need to - * be done by the caller. - */ -int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) -{ - BezTriple *newb; - int i= 0; - - if (icu->bezt == NULL) { - icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); - *(icu->bezt)= *bezt; - icu->totvert= 1; - } - else { - short replace = -1; - i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); - - if (replace) { - /* sanity check: 'i' may in rare cases exceed arraylen */ - if ((i >= 0) && (i < icu->totvert)) - *(icu->bezt + i) = *bezt; - } - else { - /* add new */ - newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); - - /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ - if (i > 0) - memcpy(newb, icu->bezt, i*sizeof(BezTriple)); - - /* add beztriple to paste at index i */ - *(newb + i)= *bezt; - - /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ - if (i < icu->totvert) - memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); - - /* replace (+ free) old with new */ - MEM_freeN(icu->bezt); - icu->bezt= newb; - - icu->totvert++; - } - } - - /* we need to return the index, so that some tools which do post-processing can - * detect where we added the BezTriple in the array - */ - return i; -} - -/* This function is a wrapper for insert_bezt_icu, and should be used when - * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere - * else yet. - * - * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. - */ -void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) -{ - BezTriple beztr; - int a, h1, h2; - - /* set all three points, for nicer start position */ - memset(&beztr, 0, sizeof(BezTriple)); - beztr.vec[0][0]= x; - beztr.vec[0][1]= y; - beztr.vec[1][0]= x; - beztr.vec[1][1]= y; - beztr.vec[2][0]= x; - beztr.vec[2][1]= y; - beztr.hide= IPO_BEZ; - beztr.f1= beztr.f2= beztr.f3= SELECT; - beztr.h1= beztr.h2= HD_AUTO; - - /* add temp beztriple to keyframes */ - a= insert_bezt_icu(icu, &beztr); - if (!fast) calchandles_ipocurve(icu); - - /* set handletype */ - if (icu->totvert > 2) { - BezTriple *bezt; - - h1= h2= HD_AUTO; - bezt= (icu->bezt + a); - - if (a > 0) h1= (bezt-1)->h2; - if (a < icu->totvert-1) h2= (bezt+1)->h1; - - bezt->h1= h1; - bezt->h2= h2; - - if (!fast) calchandles_ipocurve(icu); - } -} - void add_vert_ipo(void) { EditIpo *ei; @@ -2233,7 +2068,7 @@ void add_vert_ipo(void) if(ei->icu==NULL) { if(G.sipo->from) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu) ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ; /* new curve could have been added, weak... */ else @@ -2259,525 +2094,6 @@ void add_vert_ipo(void) BIF_undo_push("Add Ipo vertex"); } -static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) -{ - if (blocktype==ID_PO) { - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - *vartype= IPO_FLOAT; - return get_pchan_ipo_poin(pchan, icu->adrcode); - } - else - return NULL; - } - return NULL; - } - else if (blocktype==ID_CO) { - if ((GS(id->name)==ID_OB) && (constname && constname[0])) { - Object *ob= (Object *)id; - bConstraint *con; - - /* assume that we only want the influence (as only used for Constraint Channels) */ - if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { - for (con= ob->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - else if (ob->pose) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - for (con= pchan->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - } - } - return NULL; - } - else - return get_ipo_poin(id, icu, vartype); - -} - -#define KEYNEEDED_DONTADD 0 -#define KEYNEEDED_JUSTADD 1 -#define KEYNEEDED_DELPREV 2 -#define KEYNEEDED_DELNEXT 3 - -static int new_key_needed(IpoCurve *icu, float cFrame, float nValue) -{ - /* This function determines whether a new keyframe is needed */ - /* Cases where keyframes should not be added: - * 1. Keyframe to be added bewteen two keyframes with similar values - * 2. Keyframe to be added on frame where two keyframes are already situated - * 3. Keyframe lies at point that intersects the linear line between two keyframes - */ - - BezTriple *bezt=NULL, *prev=NULL; - int totCount, i; - float valA = 0.0f, valB = 0.0f; - - /* safety checking */ - if (!icu) return KEYNEEDED_JUSTADD; - totCount= icu->totvert; - if (totCount==0) return KEYNEEDED_JUSTADD; - - /* loop through checking if any are the same */ - bezt= icu->bezt; - for (i=0; ivec[1][0]; - beztVal= bezt->vec[1][1]; - - if (prev) { - /* there is a keyframe before the one currently being examined */ - - /* get previous time+value */ - prevPosi= prev->vec[1][0]; - prevVal= prev->vec[1][1]; - - /* keyframe to be added at point where there are already two similar points? */ - if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { - return KEYNEEDED_DONTADD; - } - - /* keyframe between prev+current points ? */ - if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { - /* is the value of keyframe to be added the same as keyframes on either side ? */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { - return KEYNEEDED_DONTADD; - } - else { - float realVal; - - /* get real value of curve at that point */ - realVal= eval_icu(icu, cFrame); - - /* compare whether it's the same as proposed */ - if (IS_EQ(realVal, nValue)) - return KEYNEEDED_DONTADD; - else - return KEYNEEDED_JUSTADD; - } - } - - /* new keyframe before prev beztriple? */ - if (cFrame < prevPosi) { - /* A new keyframe will be added. However, whether the previous beztriple - * stays around or not depends on whether the values of previous/current - * beztriples and new keyframe are the same. - */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) - return KEYNEEDED_DELNEXT; - else - return KEYNEEDED_JUSTADD; - } - } - else { - /* just add a keyframe if there's only one keyframe - * and the new one occurs before the exisiting one does. - */ - if ((cFrame < beztPosi) && (totCount==1)) - return KEYNEEDED_JUSTADD; - } - - /* continue. frame to do not yet passed (or other conditions not met) */ - if (i < (totCount-1)) { - prev= bezt; - bezt++; - } - else - break; - } - - /* Frame in which to add a new-keyframe occurs after all other keys - * -> If there are at least two existing keyframes, then if the values of the - * last two keyframes and the new-keyframe match, the last existing keyframe - * gets deleted as it is no longer required. - * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last - * keyframe is not equal to last keyframe. - */ - bezt= (icu->bezt + (icu->totvert - 1)); - valA= bezt->vec[1][1]; - - if (prev) - valB= prev->vec[1][1]; - else - valB= bezt->vec[1][1] + 1.0f; - - if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) - return KEYNEEDED_DELPREV; - else - return KEYNEEDED_JUSTADD; -} - -/* a duplicate of insertkey that does not check for routing to insertmatrixkey - to avoid recursion problems */ -static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int matset=0; - - if (matset==0) { - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - insert_vert_icu(icu, cfra, curval, 0); - } - } - } -} - -int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - int matindex=0; - /* branch on adrcode and blocktype, generating the proper matrix-based - values to send to insertfloatkey */ - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - - if ( blocktype==ID_OB ){ //working with an object - if ((ob)&&!(ob->parent)) { - if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)) { //get a rotation - float eul[3]; - switch (adrcode) { - case OB_ROT_X: - matindex=0; - break; - case OB_ROT_Y: - matindex=1; - break; - case OB_ROT_Z: - matindex=2; - break; - } - Mat4ToEul(ob->obmat, eul); - insertfloatkey(id, ID_OB, actname, NULL, adrcode, eul[matindex]*(5.72958)); - return 1; - } else if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)) {//get a translation - switch (adrcode) { - case OB_LOC_X: - matindex=0; - break; - case OB_LOC_Y: - matindex=1; - break; - case OB_LOC_Z: - matindex=2; - break; - } - insertfloatkey(id, ID_OB, actname, NULL, adrcode, ob->obmat[3][matindex]); - return 1; - } - } - } else if ( blocktype==ID_PO) { //working with a pose channel - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - if (pchan) { - if ((adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { - switch (adrcode) { - case AC_LOC_X: - matindex=0; - break; - case AC_LOC_Y: - matindex=1; - break; - case AC_LOC_Z: - matindex=2; - break; - } - if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_CONNECTED))) { /* don't use for non-connected child bones */ - float delta_mat[4][4]; - armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat); - insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, delta_mat[3][matindex]); - return 1; - } - } else if ((adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { - float tmat[4][4], trimat[3][3], localQuat[4]; - - switch (adrcode) { - case AC_QUAT_W: - matindex=0; - break; - case AC_QUAT_X: - matindex=1; - break; - case AC_QUAT_Y: - matindex=2; - break; - case AC_QUAT_Z: - matindex=3; - break; - } - - /* it should be reasonable to assume that we are keyframing on the active object, although it is not - * strictly required for this particular space conversion, arg1 must not be null for this to work - */ - Mat4CpyMat4(tmat, pchan->pose_mat); - constraint_mat_convertspace(OBACT, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); - - Mat3CpyMat4(trimat, tmat); - Mat3ToQuat_is_ok(trimat, localQuat); - insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, localQuat[matindex]); - - return 1; - } - } - } - } - /* failed to set a matrix key -- use traditional, but the non-recursing version */ - insertkey_nonrecurs(id,blocktype,actname,constname,adrcode); - return 0; -} - -static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrcode) -{ /* This function matches constraint blocks with adrcodes to see if the - visual keying method should be used. For example, an object looking to key - location and having a CopyLoc constraint would return true. */ - - Object *ob=NULL; - int foundmatch=0; - int searchtype=0; - bConstraint *conref=NULL, *con=NULL; - - /*Retrieve constraint list*/ - if( GS(id->name)==ID_OB ) - ob= (Object *)id; - if (ob) { - if (blocktype==ID_PO) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - conref=pchan->constraints.first; - } else if (blocktype==ID_OB) { - conref=ob->constraints.first; - } - - if (conref) { - /*Set search type: 1 is for translation contraints, 2 is for rotation*/ - if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)||(adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { - searchtype=1; - } else if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)||(adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { - searchtype=2; - } - - if (searchtype>0) { - for (con=conref; (con)&&(foundmatch==0); con=con->next) { - switch (con->type) { - /* match constraint types to which kinds of keying they would affect */ - case CONSTRAINT_TYPE_CHILDOF: - foundmatch=1; - break; - case CONSTRAINT_TYPE_TRACKTO: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_FOLLOWPATH: - foundmatch=1; - break; - case CONSTRAINT_TYPE_ROTLIMIT: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCLIMIT: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_ROTLIKE: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCLIKE: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCKTRACK: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_DISTLIMIT: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_MINMAX: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_TRANSFORM: - foundmatch=1; - break; - default: - break; - } - } - } - } - } - - return foundmatch; - -} - -void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int matset=0; - - if ((IS_AUTOKEY_FLAG(AUTOMATKEY))&&(match_adr_constraint(id, blocktype, actname, adrcode))) { - matset=insertmatrixkey(id, blocktype, actname, constname, adrcode); - } - if (matset==0) { - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - insert_vert_icu(icu, cfra, curval, fast); - } - } - } -} - - - -/* This function is a 'smarter' version of the insert key code. - * It uses an auxilliary function to check whether a keyframe is really needed */ -void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int insert_mode; - - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* check whether this curve really needs a new keyframe */ - insert_mode= new_key_needed(icu, cfra, curval); - - /* insert new keyframe at current frame */ - if (insert_mode) - insert_vert_icu(icu, cfra, curval, 0); - - /* delete keyframe immediately before/after newly added */ - switch (insert_mode) { - case KEYNEEDED_DELPREV: - delete_icu_key(icu, icu->totvert-2, 1); - break; - case KEYNEEDED_DELNEXT: - delete_icu_key(icu, 1, 1); - break; - } - } - } -} - -/* For inserting keys based on an arbitrary float value */ -void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float cfra; - int vartype; - - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* insert new keyframe at current frame */ - insert_vert_icu(icu, cfra, floatkey, 0); - } - } -} void insertkey_editipo(void) { @@ -2909,598 +2225,6 @@ void insertkey_editipo(void) } -void common_insertkey(void) -{ - Base *base; - Object *ob; - Material *ma; - ID *id; - IpoCurve *icu; - World *wo; - Lamp *la; - Tex *te; - int tlay, map, event; - char menustr[256]; - - if(curarea->spacetype==SPACE_IPO) { - insertkey_editipo(); - } - else if(curarea->spacetype==SPACE_ACTION) { - insertkey_action(); - } - else if(curarea->spacetype==SPACE_BUTS) { - if(G.buts->mainb==CONTEXT_SHADING) { - int tab= G.buts->tab[CONTEXT_SHADING]; - - if(tab==TAB_SHADING_MAT) { - ma = G.buts->lockpoin; - ma = editnode_get_active_material(ma); - id = (ID *)ma; - - if(id) { - event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|Halo Size%x2|Mode %x3|All Color%x10|All Mirror%x14|Ofs%x12|Size%x13|All Mapping%x11"); - if(event== -1) return; - - map= texchannel_to_adrcode(ma->texact); - - if(event==0 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_COL_R, 0); - insertkey(id, ID_MA, NULL, NULL, MA_COL_G, 0); - insertkey(id, ID_MA, NULL, NULL, MA_COL_B, 0); - } - if(event==1 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_ALPHA, 0); - } - if(event==2 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_HASIZE, 0); - } - if(event==3 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); - } - if(event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B, 0); - insertkey(id, ID_MA, NULL, NULL, MA_REF, 0); - insertkey(id, ID_MA, NULL, NULL, MA_EMIT, 0); - insertkey(id, ID_MA, NULL, NULL, MA_AMB, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC, 0); - insertkey(id, ID_MA, NULL, NULL, MA_HARD, 0); - insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); - insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU, 0); - insertkey(id, ID_MA, NULL, NULL, MA_ADD, 0); - } - if(event==14) { - insertkey(id, ID_MA, NULL, NULL, MA_RAYM, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI, 0); - } - if(event==12 || event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13 || event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z, 0); - } - if(event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_R, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_G, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_B, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP, 0); - } - } - } - else if(tab==TAB_SHADING_WORLD) { - id= G.buts->lockpoin; - wo= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13"); - if(event== -1) return; - - map= texchannel_to_adrcode(wo->texact); - - if(event==0) { - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B, 0); - } - if(event==1) { - insertkey(id, ID_WO, NULL, NULL, WO_HOR_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_HOR_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_HOR_B, 0); - } - if(event==2) { - insertkey(id, ID_WO, NULL, NULL, WO_MISI, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTDI, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTHI, 0); - } - if(event==3) { - insertkey(id, ID_WO, NULL, NULL, WO_STAR_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STAR_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STAR_B, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STARDIST, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE, 0); - } - if(event==12) { - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13) { - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z, 0); - } - } - } - else if(tab==TAB_SHADING_LAMP) { - id= G.buts->lockpoin; - la= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13"); - if(event== -1) return; - - map= texchannel_to_adrcode(la->texact); - - if(event==0) { - insertkey(id, ID_LA, NULL, NULL, LA_COL_R, 0); - insertkey(id, ID_LA, NULL, NULL, LA_COL_G, 0); - insertkey(id, ID_LA, NULL, NULL, LA_COL_B, 0); - } - if(event==1) { - insertkey(id, ID_LA, NULL, NULL, LA_ENERGY, 0); - } - if(event==2) { - insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI, 0); - } - if(event==12) { - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13) { - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z, 0); - } - - } - } - else if(tab==TAB_SHADING_TEX) { - id= G.buts->lockpoin; - te= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Clouds%x0|Marble%x1|Stucci%x2|Wood%x3|Magic%x4|Blend%x5|Musgrave%x6|Voronoi%x7|DistortedNoise%x8|ColorFilter%x9"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - } - if(event==1) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); - } - if(event==2) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - } - if(event==3) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); - } - if(event==4) { - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - } - if(event==5) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - } - if(event==6) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MGH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_LAC, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); - } - if(event==7) { - insertkey(id, ID_TE, NULL, NULL, TE_VNW1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW2, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW3, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW4, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNMEXP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VN_DISTM, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VN_COLT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_ISCA, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - } - if(event==8) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); - insertkey(id, ID_TE, NULL, NULL, TE_DISTA, 0); - } - if(event==9) { - insertkey(id, ID_TE, NULL, NULL, TE_COL_R, 0); - insertkey(id, ID_TE, NULL, NULL, TE_COL_G, 0); - insertkey(id, ID_TE, NULL, NULL, TE_COL_B, 0); - insertkey(id, ID_TE, NULL, NULL, TE_BRIGHT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_CONTRA, 0); - } - } - } - } - else if(G.buts->mainb==CONTEXT_OBJECT) { - ob= OBACT; - if(ob) { - id= (ID *) (ob); - if(id) { - if(ob->type==OB_MESH) - event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4"); - else - event= pupmenu("Insert Key %t|Force Strength%x3|Force Falloff%x4"); - if(event == -1) return; - - if(event==0) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_SDAMP, 0); - } - if(event==1) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_RDAMP, 0); - } - if(event==2) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_PERM, 0); - } - if(event==3) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FSTR, 0); - } - if(event==4) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL, 0); - } - if(event==5) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FMAXD, 0); - } - } - } - } - else if(G.buts->mainb==CONTEXT_EDITING) { - ob= OBACT; - if(ob && ob->type==OB_CAMERA) { - id= G.buts->lockpoin; - if(id) { - /* yafray: insert key extended with aperture and focal distance */ - /* qdn: FocalDistance now enabled for Blender as wel, for use with defocus node */ - if (G.scene->r.renderer==R_INTERN) - event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|FocalDistance%x3|Viewplane Shift%x4"); - else - event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|Aperture%x2|FocalDistance%x3"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_CA, NULL, NULL, CAM_LENS, 0); - } - else if(event==1) { - insertkey(id, ID_CA, NULL, NULL, CAM_STA, 0); - insertkey(id, ID_CA, NULL, NULL, CAM_END, 0); - } - else if(event==2) { - insertkey(id, ID_CA, NULL, NULL, CAM_YF_APERT, 0); - } - else if(event==3) { - insertkey(id, ID_CA, NULL, NULL, CAM_YF_FDIST, 0); - } - else if(event==4) { - insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_X, 0); - insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_Y, 0); - } - } - } - } - else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) { - if(G.ssound) { - id= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_SO, NULL, NULL, SND_VOLUME, 0); - } - if(event==1) { - insertkey(id, ID_SO, NULL, NULL, SND_PITCH, 0); - } - if(event==2) { - insertkey(id, ID_SO, NULL, NULL, SND_PANNING, 0); - } - if(event==3) { - insertkey(id, ID_SO, NULL, NULL, SND_ATTEN, 0); - } - } - } - } - - BIF_undo_push("Insert Key Buttons"); - - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - allspace(REMAKEIPO, 0); - - } - else if(curarea->spacetype==SPACE_VIEW3D) { - ob= OBACT; - - if (ob && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - - set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) - if (pchan->flag & POSE_KEY) - break; - if(pchan==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); - } - else { - base= FIRSTBASE; - while(base) { - if (TESTBASELIB(base)) break; - base= base->next; - } - if(base==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Layer%x5|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); - } - - if(ob) { - if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7"); - else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7"); - else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7"); - else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7"); - } - - event= pupmenu(menustr); - if(event== -1) return; - - if(event==7) { // ob != NULL - insert_shapekey(ob); - return; - } - - if (ob && (ob->flag & OB_POSEMODE)){ - bPoseChannel *pchan; - short recalc_bonepaths= 0; - - if (ob->action && ob->action->id.lib) { - error ("Can't key libactions"); - return; - } - - id= &ob->id; - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { - if (pchan->flag & POSE_KEY) { - /* insert relevant keyframes */ - if(event==0 || event==3 ||event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - if(event==1 || event==3 || event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - } - if(event==2 || event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); - } - if (event==9 && ob->action) { - bActionChannel *achan; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - insertkey(id, ID_PO, achan->name, NULL, icu->adrcode, 0); - } - break; - } - } - } - if(event==11 || event==13) { - int matok=0; - /* check one to make sure we're not trying to set visual loc keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - } - if(event==12 || event==13) { - int matok=0; - /* check one to make sure we're not trying to set visual rot keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - } - } - if (event==15 && ob->action) { - bActionChannel *achan; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - insertkey_smarter(id, ID_PO, achan->name, NULL, icu->adrcode); - } - break; - } - } - } - - /* clear unkeyed flag (it doesn't matter if it's set or not) */ - if (pchan->bone) - pchan->bone->flag &= ~BONE_UNKEYED; - - /* check if bone has a path */ - if (pchan->path) - recalc_bonepaths = 1; - } - } - - /* recalculate ipo handles, etc. */ - if(ob->action) - remake_action_ipos(ob->action); - - /* recalculate bone-paths on adding new keyframe? */ - // TODO: currently, there is no setting to turn this on/off globally - if (recalc_bonepaths) - pose_recalculate_paths(ob); - - - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } - else { - base= FIRSTBASE; - while(base) { - if (TESTBASELIB(base)) { - char *actname= NULL; - - id= (ID *)(base->object); - - if(base->object->ipoflag & OB_ACTION_OB) - actname= "Object"; - - /* all curves in ipo deselect */ - if(base->object->ipo || base->object->action) { - if (base->object->ipo) { - icu= base->object->ipo->curve.first; - } - else { - bActionChannel *achan; - achan= get_action_channel(base->object->action, actname); - - if (achan && achan->ipo) - icu= achan->ipo->curve.first; - else - icu= NULL; - } - - while(icu) { - icu->flag &= ~IPO_SELECT; - - switch (event) { - case 9: - insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); - break; - case 15: - insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); - break; - } - icu= icu->next; - } - } - - if(event==0 || event==3 ||event==4) { - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); - } - if(event==1 || event==3 ||event==4) { - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); - } - if(event==2 || event==4) { - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); - } - if(event==5) { - /* remove localview */ - tlay= base->object->lay; - base->object->lay &= 0xFFFFFF; - insertkey(id, ID_OB, actname, NULL, OB_LAY, 0); - base->object->lay= tlay; - } - if(event==11 || event==13) { - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_X); - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Y); - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Z); - } - if(event==12 || event==13) { - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_X); - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Y); - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Z); - } - base->object->recalc |= OB_RECALC_OB; - } - base= base->next; - } - } - - if(event==0) BIF_undo_push("Insert Loc Key"); - else if(event==1) BIF_undo_push("Insert Rot Key"); - else if(event==2) BIF_undo_push("Insert Scale Key"); - else if(event==3) BIF_undo_push("Insert LocRot Key"); - else if(event==4) BIF_undo_push("Insert LocRotScale Key"); - else if(event==5) BIF_undo_push("Insert Layer Key"); - else if(event==7) BIF_undo_push("Insert Vertex Key"); - else if(event==9) BIF_undo_push("Insert Avail Key"); - else if(event==11) BIF_undo_push("Insert VisualLoc Key"); - else if(event==12) BIF_undo_push("Insert VisualRot Key"); - else if(event==13) BIF_undo_push("Insert VisualLocRot Key"); - else if(event==15) BIF_undo_push("Insert Needed Key"); - - DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); - - allspace(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } - -} - /* ****************************************************************************** */ void add_duplicate_editipo(void) @@ -3651,6 +2375,7 @@ void remove_doubles_ipo(void) } deselectall_editipo(); + BIF_undo_push("Remove Doubles (IPO)"); } @@ -4473,7 +3198,7 @@ void paste_editipo(void) int i; /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu == NULL) return; /* Copy selected beztriples from source icu onto this edit-icu, @@ -4514,7 +3239,7 @@ void paste_editipo(void) else { /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu==NULL) return; /* clear exisiting dynamic memory (keyframes, driver) */ @@ -5629,7 +4354,7 @@ void ipo_record(void) /* make curves ready, start values */ if(ei1->icu==NULL) - ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode); + ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode, 1); if(ei1->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei1->icu, &type); @@ -5639,7 +4364,7 @@ void ipo_record(void) if(ei2) { if(ei2->icu==NULL) - ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode); + ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode, 1); if(ei2->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei2->icu, &type); diff --git a/source/blender/src/editipo_lib.c b/source/blender/src/editipo_lib.c index e1e286e10cf..7bfd097b87f 100644 --- a/source/blender/src/editipo_lib.c +++ b/source/blender/src/editipo_lib.c @@ -392,7 +392,15 @@ int texchannel_to_adrcode(int channel) case 6: return MA_MAP7; case 7: return MA_MAP8; case 8: return MA_MAP9; - case 9: return MA_MAP10; + case 9: return MA_MAP10; + case 10: return MA_MAP11; + case 11: return MA_MAP12; + case 12: return MA_MAP13; + case 13: return MA_MAP14; + case 14: return MA_MAP15; + case 15: return MA_MAP16; + case 16: return MA_MAP17; + case 17: return MA_MAP18; default: return 0; } } diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index f03de1ff383..24bb111c8d1 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -237,7 +237,6 @@ void deselectall_editipo(void) } } - BIF_undo_push("(De)select all Ipo"); scrarea_queue_winredraw(curarea); } diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index ce798064632..dbabf9d19fb 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -70,6 +70,7 @@ #include "BIF_editkey.h" #include "BIF_editview.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -170,9 +171,9 @@ static void rvk_slider_func(void *voidob, void *voidkeynum) /* ipo on action or ob? */ if(ob->ipoflag & OB_ACTION_KEY) - icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum); + icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum, 1); else - icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum); + icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum, 1); if (icu) { /* if the ipocurve exists, try to get a bezier diff --git a/source/blender/src/editlattice.c b/source/blender/src/editlattice.c index 0782e012f68..06b092a30ac 100644 --- a/source/blender/src/editlattice.c +++ b/source/blender/src/editlattice.c @@ -131,7 +131,7 @@ void make_editLatt(void) copy_dverts(editLatt->dvert, lt->dvert, tot); } - BIF_undo_push("original"); + BIF_undo_push("Original"); } diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 188f7476728..b75f7e07143 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -1683,6 +1683,10 @@ void separate_mesh(void) efa= em->faces.first; while(efa) { vl1= efa->next; + if (efa == G.editMesh->act_face && (efa->f & SELECT)) { + EM_set_actFace(NULL); + } + if((efa->f & SELECT)==0) { BLI_remlink(&em->faces, efa); BLI_addtail(&edvl, efa); diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index 9516f39b05c..71e04541643 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -869,6 +869,152 @@ int confirm_objectExists( Mesh **me, float mat[][3] ) return newob; } +// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker +// this hack is only used so that scons+mingw + split-sources hack works + // ------------------------------- start copied code +/* these are not the monkeys you are looking for */ +int monkeyo= 4; +int monkeynv= 271; +int monkeynf= 250; +signed char monkeyv[271][3]= { +{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92}, +{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83}, +{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102}, +{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92}, +{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74}, +{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99}, +{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105}, +{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100}, +{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100}, +{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73}, +{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45}, +{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68}, +{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68}, +{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80}, +{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96}, +{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90}, +{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85}, +{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94}, +{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96}, +{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95}, +{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84}, +{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109}, +{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88}, +{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82}, +{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96}, +{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96}, +{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100}, +{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104}, +{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71}, +{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88}, +{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84}, +{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81}, +{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99}, +{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87}, +{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100}, +{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97}, +{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86}, +{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96}, +{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79}, +{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59}, +{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37}, +{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59}, +{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7}, +{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9}, +{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52}, +{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51}, +{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55}, +{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34}, +{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30}, +{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7}, +{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57}, +{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26}, +{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16}, +{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54}, +{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52}, +{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28}, +{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57}, +{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27}, +{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35}, +{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24}, +{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41}, +{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41}, +{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62}, +{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42}, +{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48}, +{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62}, +{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63}, +{-26,-16,-42},{-17,49,-49}, +}; + +signed char monkeyf[250][4]= { +{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, +{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, +{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, +{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, +{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, +{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, +{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, +{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, +{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, +{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, +{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, +{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, +{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, +{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, +{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, +{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, +{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, +{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, +{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, +{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, +{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, +{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, +{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, +{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, +{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, +{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, +{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, +{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, +{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, +{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, +{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, +{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, +{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, +{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, +{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, +{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, +{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, +{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, +{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, +{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, +{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, +{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, +{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, +{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, +{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, +{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, +{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, +{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, +{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, +{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, +{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, +{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, +{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, +{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, +{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, +{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, +{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, +{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, +{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, +{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, +{-68,-67,24,-33}, +}; + // ------------------------------- end copied code + + void make_prim(int type, float imat[3][3], int tot, int seg, int subdiv, float dia, float d, int ext, int fill, float cent[3]) @@ -1022,9 +1168,9 @@ void make_prim(int type, float imat[3][3], int tot, int seg, break; case 13: /* Monkey */ { - extern int monkeyo, monkeynv, monkeynf; - extern signed char monkeyf[][4]; - extern signed char monkeyv[][3]; + //extern int monkeyo, monkeynv, monkeynf; + //extern signed char monkeyf[][4]; + //extern signed char monkeyv[][3]; EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); EditFace *efa; int i; diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c index 4d9679b6b8a..bafc9dda7d6 100644 --- a/source/blender/src/editmesh_lib.c +++ b/source/blender/src/editmesh_lib.c @@ -1914,6 +1914,10 @@ void flip_editnormals(void) } efa= efa->next; } + + /* update vertex normals too */ + recalc_editnormals(); + #ifdef WITH_VERSE if(G.editMesh->vnode) sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode); diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c index 4ac5072b212..138dd93e490 100644 --- a/source/blender/src/editmesh_loop.c +++ b/source/blender/src/editmesh_loop.c @@ -519,6 +519,7 @@ static CutCurve *get_mouse_trail(int *len, char mode, char cutmode, struct GHash glDrawBuffer(GL_FRONT); headerprint("(LMB) draw, (MMB) constrain to x/y screen axis, (Enter) cut (with Ctrl to select cut line), (Esc) cancel"); } + bglFlush(); persp(PERSP_WIN); @@ -620,14 +621,14 @@ static CutCurve *get_mouse_trail(int *len, char mode, char cutmode, struct GHash if ((i>1)&&(i!=lasti)) { /*Draw recorded part of curve */ sdrawline((int)curve[i-2].x, (int)curve[i-2].y, (int)curve[i-1].x, (int)curve[i-1].y); - glFlush(); + bglFlush(); } if ((i==lasti)&&(i>0)) { /*Draw rubberband */ glLineWidth(2.0); sdrawXORline((int)curve[i-1].x, (int)curve[i-1].y,(int)mval[0], (int)mval[1]); glLineWidth(1.0); - glFlush(); + bglFlush(); rubberband=1; } lasti=i; @@ -745,9 +746,9 @@ void KnifeSubdivide(char mode) eed= eed->next; } - if (mode==KNIFE_EXACT) esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); - else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); + if(mode==KNIFE_EXACT) esubdivideflag(SELECT, 0, B_KNIFE|B_PERCENTSUBD,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MIDPOINT) esubdivideflag(SELECT, 0, B_KNIFE,1,SUBDIV_SELECT_ORIG); + else if (mode==KNIFE_MULTICUT) esubdivideflag(SELECT, 0, B_KNIFE,numcuts,SUBDIV_SELECT_ORIG); eed=em->edges.first; while(eed){ diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index c162c904776..81d0ffeeb3b 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -4202,7 +4202,7 @@ void editmesh_align_view_to_selected(View3D *v3d, int axis) void vertexsmooth(void) { EditMesh *em = G.editMesh; - EditVert *eve; + EditVert *eve, *eve_mir = NULL; EditEdge *eed; float *adror, *adr, fac; float fvec[3]; @@ -4285,13 +4285,19 @@ void vertexsmooth(void) while(eve) { if(eve->f & SELECT) { if(eve->f1) { + + if (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR) { + eve_mir= editmesh_get_x_mirror_vert(G.obedit, eve->co); + } + adr = eve->tmp.p; fac= 0.5/(float)eve->f1; eve->co[0]= 0.5*eve->co[0]+fac*adr[0]; eve->co[1]= 0.5*eve->co[1]+fac*adr[1]; eve->co[2]= 0.5*eve->co[2]+fac*adr[2]; - + + /* clip if needed by mirror modifier */ if (eve->f2) { if (eve->f2 & 1) { @@ -4304,6 +4310,13 @@ void vertexsmooth(void) eve->co[2]= 0.0f; } } + + if (eve_mir) { + eve_mir->co[0]=-eve->co[0]; + eve_mir->co[1]= eve->co[1]; + eve_mir->co[2]= eve->co[2]; + } + } eve->tmp.p= NULL; } diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 3615a4ad851..4cf3b410393 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -2698,16 +2698,21 @@ void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype) free_tagged_edges_faces(em->edges.first, em->faces.first); if(seltype == SUBDIV_SELECT_ORIG && G.qual != LR_CTRLKEY) { + /* bugfix: vertex could get flagged as "not-selected" + // solution: clear flags before, not at the same time as setting SELECT flag -dg + */ for(eed = em->edges.first;eed;eed = eed->next) { - if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { - eed->f |= flag; - EM_select_edge(eed,1); - - }else{ + if(!(eed->f2 & EDGENEW || eed->f2 & EDGEOLD)) { eed->f &= !flag; EM_select_edge(eed,0); } - } + } + for(eed = em->edges.first;eed;eed = eed->next) { + if(eed->f2 & EDGENEW || eed->f2 & EDGEOLD) { + eed->f |= flag; + EM_select_edge(eed,1); + } + } } else if ((seltype == SUBDIV_SELECT_INNER || seltype == SUBDIV_SELECT_INNER_SEL)|| G.qual == LR_CTRLKEY) { for(eed = em->edges.first;eed;eed = eed->next) { if(eed->f2 & EDGEINNER) { @@ -4648,6 +4653,12 @@ void bevel_menu_old() } /* *********** END BEVEL *********/ +typedef struct SlideUv { + float origuv[2]; + float *uv_up, *uv_down; + //float *fuv[4]; + LinkNode *fuv_list; +} SlideUv; typedef struct SlideVert { EditEdge *up,*down; @@ -4655,9 +4666,19 @@ typedef struct SlideVert { } SlideVert; int EdgeLoopDelete(void) { + + /* temporal flag setting so we keep UVs when deleting edge loops, + * this is a bit of a hack but it works how you would want in almost all cases */ + short uvcalc_flag_orig = G.scene->toolsettings->uvcalc_flag; + G.scene->toolsettings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; + if(!EdgeSlide(1, 1)) { return 0; } + + /* restore uvcalc flag */ + G.scene->toolsettings->uvcalc_flag = uvcalc_flag_orig; + EM_select_more(); removedoublesflag(1,0, 0.001); EM_select_flush(); @@ -4667,22 +4688,35 @@ int EdgeLoopDelete(void) { int EdgeSlide(short immediate, float imperc) { + NumInput num; EditMesh *em = G.editMesh; EditFace *efa; EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL; EditVert *ev, *nearest; LinkNode *edgelist = NULL, *vertlist=NULL, *look; GHash *vertgh; + SlideVert *tempsv; float perc = 0, percp = 0,vertdist, projectMat[4][4], viewMat[4][4]; float shiftlabda= 0.0f,len = 0.0f; int i = 0,j, numsel, numadded=0, timesthrough = 0, vertsel=0, prop=1, cancel = 0,flip=0; int wasshift = 0; + + /* UV correction vars */ + GHash **uvarray= NULL; + int uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE); + int uvlay_idx; + SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; + float uv_tmp[2]; + LinkNode *fuv_link; + short event, draw=1; short mval[2], mvalo[2]; char str[128]; float labda = 0.0f; + initNumInput(&num); + view3d_get_object_project_mat(curarea, G.obedit, projectMat, viewMat); mvalo[0] = -1; mvalo[1] = -1; @@ -4982,6 +5016,99 @@ int EdgeSlide(short immediate, float imperc) look = look->next; } + + + if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + int maxnum = 0; + uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); + suv_last = slideuvs = MEM_callocN( uvlay_tot * (numadded+1) * sizeof(SlideUv), "SlideUVs"); /* uvLayers * verts */ + suv = NULL; + + for (uvlay_idx=0; uvlay_idxverts.first;ev;ev=ev->next) { + ev->tmp.l = 0; + } + look = vertlist; + while(look) { + float *uv_new; + tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link); + + ev = look->link; + suv = NULL; + for(efa = em->faces.first;efa;efa=efa->next) { + if (ev->tmp.l != -1) { /* test for self, in this case its invalid */ + int k=-1; /* face corner */ + + /* Is this vert in the faces corner? */ + if (efa->v1==ev) k=0; + else if (efa->v2==ev) k=1; + else if (efa->v3==ev) k=2; + else if (efa->v4 && efa->v4==ev) k=3; + + if (k != -1) { + MTFace *tf = CustomData_em_get_n(&em->fdata, efa->data, CD_MTFACE, uvlay_idx); + EditVert *ev_up, *ev_down; + + uv_new = tf->uv[k]; + + if (ev->tmp.l) { + if (fabs(suv->origuv[0]-uv_new[0]) > 0.0001 || fabs(suv->origuv[1]-uv_new[1])) { + ev->tmp.l = -1; /* Tag as invalid */ + BLI_linklist_free(suv->fuv_list,NULL); + suv->fuv_list = NULL; + BLI_ghash_remove(uvarray[uvlay_idx],ev, NULL, NULL); + suv = NULL; + break; + } + } else { + ev->tmp.l = 1; + suv = suv_last; + + suv->fuv_list = NULL; + suv->uv_up = suv->uv_down = NULL; + suv->origuv[0] = uv_new[0]; + suv->origuv[1] = uv_new[1]; + + BLI_linklist_prepend(&suv->fuv_list, uv_new); + BLI_ghash_insert(uvarray[uvlay_idx],ev,suv); + + suv_last++; /* advance to next slide UV */ + maxnum++; + } + + /* Now get the uvs along the up or down edge if we can */ + if (suv) { + if (!suv->uv_up) { + ev_up = editedge_getOtherVert(tempsv->up,ev); + if (efa->v1==ev_up) suv->uv_up = tf->uv[0]; + else if (efa->v2==ev_up) suv->uv_up = tf->uv[1]; + else if (efa->v3==ev_up) suv->uv_up = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_up) suv->uv_up = tf->uv[3]; + } + if (!suv->uv_down) { /* if the first face was apart of the up edge, it cant be apart of the down edge */ + ev_down = editedge_getOtherVert(tempsv->down,ev); + if (efa->v1==ev_down) suv->uv_down = tf->uv[0]; + else if (efa->v2==ev_down) suv->uv_down = tf->uv[1]; + else if (efa->v3==ev_down) suv->uv_down = tf->uv[2]; + else if (efa->v4 && efa->v4==ev_down) suv->uv_down = tf->uv[3]; + } + + /* Copy the pointers to the face UV's */ + BLI_linklist_prepend(&suv->fuv_list, uv_new); + } + } + } + } + look = look->next; + } + } /* end uv layer loop */ + } /* end uvlay_tot */ + + + // we should have enough info now to slide len = 0.0f; @@ -4994,88 +5121,22 @@ int EdgeSlide(short immediate, float imperc) float v2[2], v3[2]; EditVert *centerVert, *upVert, *downVert; - - getmouseco_areawin(mval); if (!immediate && (mval[0] == mvalo[0] && mval[1] == mvalo[1])) { PIL_sleep_ms(10); } else { + char *p = str;; mvalo[0] = mval[0]; mvalo[1] = mval[1]; - //Adjust Edgeloop - if(immediate) { - perc = imperc; - } - percp = perc; - if(prop) { - look = vertlist; - while(look) { - EditVert *tempev; - ev = look->link; - tempsv = BLI_ghash_lookup(vertgh,ev); - - tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); - VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); - - look = look->next; - } - } - else { - //Non prop code - look = vertlist; - while(look) { - float newlen; - ev = look->link; - tempsv = BLI_ghash_lookup(vertgh,ev); - newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); - if(newlen > 1.0) {newlen = 1.0;} - if(newlen < 0.0) {newlen = 0.0;} - if(flip == 0) { - VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); - } else{ - VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); - } - look = look->next; - } - } - tempsv = BLI_ghash_lookup(vertgh,nearest); centerVert = editedge_getSharedVert(tempsv->up, tempsv->down); upVert = editedge_getOtherVert(tempsv->up, centerVert); downVert = editedge_getOtherVert(tempsv->down, centerVert); - // Highlight the Control Edges - - scrarea_do_windraw(curarea); - persp(PERSP_VIEW); - glPushMatrix(); - mymultmatrix(G.obedit->obmat); - - glColor3ub(0, 255, 0); - glBegin(GL_LINES); - glVertex3fv(upVert->co); - glVertex3fv(downVert->co); - glEnd(); - - if(prop == 0) { - // draw start edge for non-prop - glPointSize(5); - glBegin(GL_POINTS); - glColor3ub(255,0,255); - if(flip) { - glVertex3fv(upVert->co); - } else { - glVertex3fv(downVert->co); - } - glEnd(); - } - - - glPopMatrix(); view3d_project_float(curarea, upVert->co, v2, projectMat); view3d_project_float(curarea, downVert->co, v3, projectMat); @@ -5114,18 +5175,169 @@ int EdgeSlide(short immediate, float imperc) perc = floor(perc); perc /= 10; } - if(prop) { - sprintf(str, "(P)ercentage: %f", perc); - } else { + + if(prop == 0) { len = VecLenf(upVert->co,downVert->co)*((perc+1)/2); if(flip == 1) { len = VecLenf(upVert->co,downVert->co) - len; } - sprintf(str, "Non (P)rop Length: %f, Press (F) to flip control side", len); + } + + if (hasNumInput(&num)) + { + applyNumInput(&num, &perc); + + if (prop) + { + perc = MIN2(perc, 1); + perc = MAX2(perc, -1); + } + else + { + len = MIN2(perc, VecLenf(upVert->co,downVert->co)); + len = MAX2(len, 0); + } } + //Adjust Edgeloop + if(immediate) { + perc = imperc; + } + percp = perc; + if(prop) { + look = vertlist; + while(look) { + EditVert *tempev; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + + tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); + VecLerpf(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); + + if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->origuv, (perc>=0)?suv->uv_up:suv->uv_down, fabs(perc)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + + look = look->next; + } + } + else { + //Non prop code + look = vertlist; + while(look) { + float newlen; + ev = look->link; + tempsv = BLI_ghash_lookup(vertgh,ev); + newlen = (len / VecLenf(editedge_getOtherVert(tempsv->up,ev)->co,editedge_getOtherVert(tempsv->down,ev)->co)); + if(newlen > 1.0) {newlen = 1.0;} + if(newlen < 0.0) {newlen = 0.0;} + if(flip == 0) { + VecLerpf(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); + if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_down, suv->uv_up, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } else{ + VecLerpf(ev->co, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); + + if (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + /* dont do anything if no UVs */ + for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { + Vec2Lerpf(uv_tmp, suv->uv_up, suv->uv_down, fabs(newlen)); + fuv_link = suv->fuv_list; + while (fuv_link) { + VECCOPY2D(((float *)fuv_link->link), uv_tmp); + fuv_link = fuv_link->next; + } + } + } + } + } + look = look->next; + } + + } + + // Highlight the Control Edges + scrarea_do_windraw(curarea); + persp(PERSP_VIEW); + glPushMatrix(); + mymultmatrix(G.obedit->obmat); + + glColor3ub(0, 255, 0); + glBegin(GL_LINES); + glVertex3fv(upVert->co); + glVertex3fv(downVert->co); + glEnd(); + + if(prop == 0) { + // draw start edge for non-prop + glPointSize(5); + glBegin(GL_POINTS); + glColor3ub(255,0,255); + if(flip) { + glVertex3fv(upVert->co); + } else { + glVertex3fv(downVert->co); + } + glEnd(); + } + glPopMatrix(); + + if(prop) { + p += sprintf(str, "(P)ercentage: "); + } else { + p += sprintf(str, "Non (P)rop Length: "); + } + + if (hasNumInput(&num)) + { + char num_str[20]; + + outputNumInput(&num, num_str); + p += sprintf(p, "%s", num_str); + } + else + { + if (prop) + { + p += sprintf(p, "%f", perc); + } + else + { + p += sprintf(p, "%f", len); + } + } + + + if (prop == 0) { + p += sprintf(p, ", Press (F) to flip control side"); + } + headerprint(str); screen_swapbuffers(); } @@ -5148,7 +5360,14 @@ int EdgeSlide(short immediate, float imperc) perc = 0; immediate = 1; } else if(event==PKEY) { - (prop == 1) ? (prop = 0):(prop = 1); + initNumInput(&num); /* reset num input */ + if (prop) { + prop = 0; + num.flag |= NUM_NO_NEGATIVE; + } + else { + prop = 1; + } mvalo[0] = -1; } else if(event==FKEY) { (flip == 1) ? (flip = 0):(flip = 1); @@ -5186,7 +5405,13 @@ int EdgeSlide(short immediate, float imperc) look = look->next; } } + + if (handleNumInput(&num, event)) + { + mvalo[0] = -1; /* NEED A BETTER WAY TO TRIGGER REDRAW */ + } } + } } else { draw = 0; @@ -5218,6 +5443,24 @@ int EdgeSlide(short immediate, float imperc) BLI_ghash_free(vertgh, NULL, (GHashValFreeFP)MEM_freeN); BLI_linklist_free(vertlist,NULL); BLI_linklist_free(edgelist,NULL); + + if (uvlay_tot && (G.scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + for (uvlay_idx=0; uvlay_idx= slideuvs) { + if (suv->fuv_list) { + BLI_linklist_free(suv->fuv_list,NULL); + } + suv--; + } + + allqueue(REDRAWIMAGE, 0); + } if(cancel == 1) { return -1; diff --git a/source/blender/src/editmode_undo.c b/source/blender/src/editmode_undo.c index d0a44360ad5..7893dac2408 100644 --- a/source/blender/src/editmode_undo.c +++ b/source/blender/src/editmode_undo.c @@ -107,6 +107,7 @@ typedef struct UndoElem { Object *ob; // pointer to edited object int type; // type of edited object void *undodata; + uintptr_t undosize; char name[MAXUNDONAME]; void (*freedata)(void *); void (*to_editmode)(void *); @@ -138,6 +139,7 @@ void undo_editmode_push(char *name, void (*freedata)(void *), { UndoElem *uel; int nr; + uintptr_t memused, totmem, maxmem; /* at first here was code to prevent an "original" key to be insterted twice this was giving conflicts for example when mesh changed due to keys or apply */ @@ -145,9 +147,8 @@ void undo_editmode_push(char *name, void (*freedata)(void *), /* remove all undos after (also when curundo==NULL) */ while(undobase.last != curundo) { uel= undobase.last; - BLI_remlink(&undobase, uel); uel->freedata(uel->undodata); - MEM_freeN(uel); + BLI_freelinkN(&undobase, uel); } /* make new */ @@ -160,7 +161,7 @@ void undo_editmode_push(char *name, void (*freedata)(void *), uel->from_editmode= from_editmode; uel->validate_undo= validate_undo; - /* and limit amount to the maximum */ + /* limit amount to the maximum amount*/ nr= 0; uel= undobase.last; while(uel) { @@ -171,19 +172,43 @@ void undo_editmode_push(char *name, void (*freedata)(void *), if(uel) { while(undobase.first!=uel) { UndoElem *first= undobase.first; - BLI_remlink(&undobase, first); first->freedata(first->undodata); - MEM_freeN(first); + BLI_freelinkN(&undobase, first); } } /* copy */ + memused= MEM_get_memory_in_use(); curundo->undodata= curundo->from_editmode(); + curundo->undosize= MEM_get_memory_in_use() - memused; curundo->ob= G.obedit; curundo->id= G.obedit->id; curundo->type= G.obedit->type; -} + if(U.undomemory != 0) { + /* limit to maximum memory (afterwards, we can't know in advance) */ + totmem= 0; + maxmem= ((uintptr_t)U.undomemory)*1024*1024; + + uel= undobase.last; + while(uel && uel->prev) { + totmem+= uel->undosize; + if(totmem>maxmem) break; + uel= uel->prev; + } + + if(uel) { + if(uel->prev && uel->prev->prev) + uel= uel->prev; + + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + first->freedata(first->undodata); + BLI_freelinkN(&undobase, first); + } + } + } +} /* helper to remove clean other objects from undo stack */ static void undo_clean_stack(void) @@ -205,9 +230,8 @@ static void undo_clean_stack(void) } else { mixed= 1; - BLI_remlink(&undobase, uel); uel->freedata(uel->undodata); - MEM_freeN(uel); + BLI_freelinkN(&undobase, uel); } uel= next; diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 98f4f1bb46f..d3ba153e600 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -2001,7 +2001,10 @@ void node_hide(SpaceNode *snode) void node_insert_key(SpaceNode *snode) { bNode *node= editnode_get_active(snode->edittree); - + + if(node == NULL) + return; + if(node->type==CMP_NODE_TIME) { if(node->custom1custom2) { @@ -2110,6 +2113,7 @@ static void node_border_link_delete(SpaceNode *snode) mval[1]= rect.ymax; areamouseco_to_ipoco(&snode->v2d, mval, &rectf.xmax, &rectf.ymax); + glLoadIdentity(); myortho2(rectf.xmin, rectf.xmax, rectf.ymin, rectf.ymax); glSelectBuffer(256, buffer); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index fee967bcd9a..2459f7ed23c 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -172,6 +172,7 @@ #include "BDR_drawobject.h" #include "BDR_editcurve.h" #include "BDR_unwrapper.h" +#include "BDR_gpencil.h" #include #include "mydevice.h" @@ -2827,7 +2828,7 @@ void convertmenu(void) if(G.scene->id.lib) return; obact= OBACT; - if(obact==0) return; + if (obact == NULL) return; if(!obact->flag & SELECT) return; if(G.obedit) return; @@ -3022,6 +3023,10 @@ void convertmenu(void) basedel = NULL; } + /* delete object should renew depsgraph */ + if(nr==2) + DAG_scene_sort(G.scene); + /* texspace and normals */ if(!basen) BASACT= base; @@ -3278,6 +3283,9 @@ static void copymenu_logicbricks(Object *ob) base->object->scavisflag= ob->scavisflag; base->object->scaflag= ob->scaflag; + /* set the initial state */ + base->object->state= ob->state; + base->object->init_state= ob->init_state; } } base= base->next; @@ -3514,6 +3522,7 @@ void copy_attr(short event) if (ob->gameflag & OB_BOUNDS) { base->object->boundtype = ob->boundtype; } + base->object->margin= ob->margin; } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); @@ -4130,15 +4139,27 @@ void apply_object( void ) } allqueue(REDRAWVIEW3D, 0); - } else { + } + else { + ob= OBACT; + if(ob==0) return; - evt = pupmenu("Apply Object%t|Scale and Rotation to ObData|Visual Transform to Objects Loc/Scale/Rot"); + if ((ob->pose) && (ob->flag & OB_POSEMODE)) + evt = pupmenu("Apply Object%t|Current Pose as RestPose%x3"); + else + evt = pupmenu("Apply Object%t|Scale and Rotation to ObData%x1|Visual Transform to Objects Loc/Scale/Rot%x2"); if (evt==-1) return; - if (evt==1) { - apply_objects_locrot(); - } else if (evt==2) { - apply_objects_visual_tx(); + switch (evt) { + case 1: + apply_objects_locrot(); + break; + case 2: + apply_objects_visual_tx(); + break; + case 3: + apply_armature_pose2bones(); + break; } } } diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 1cd8733a7ea..2557894d0e0 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -1023,8 +1023,11 @@ int blender_test_break(void) return (G.afbreek==1); } -void reset_autosave(void) { - window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); +void reset_autosave(void) +{ + if(U.flag & USER_AUTOSAVE) { + window_set_timer(mainwin, U.savetime*60*1000, AUTOSAVE_FILE); + } } /* ************ handlers ************** */ @@ -1977,7 +1980,7 @@ static void testareas(void) /* test for header, if removed, or moved */ /* test for window, if removed, or moved */ - for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { + for(sa= G.curscreen->areabase.first; sa; sa= next) { rcti oldhr= sa->headrct; rcti oldwr= sa->winrct; diff --git a/source/blender/src/editsound.c b/source/blender/src/editsound.c index 05eb094a7c2..2d70525f971 100644 --- a/source/blender/src/editsound.c +++ b/source/blender/src/editsound.c @@ -275,6 +275,12 @@ void sound_initialize_sounds(void) bSound *sound; if(ghSoundScene) { + for(sound=G.main->sound.first; sound; sound=sound->id.next) { + if(sound->snd_sound) { + SND_RemoveSound(ghSoundScene, sound->snd_sound); + sound->snd_sound = NULL; + } + } /* clear the soundscene */ SND_RemoveAllSounds(ghSoundScene); @@ -908,7 +914,16 @@ void sound_stop_all_sounds(void) void sound_end_all_sounds(void) { #if GAMEBLENDER == 1 + bSound *sound; + if(ghSoundScene) { + for(sound=G.main->sound.first; sound; sound=sound->id.next) { + if(sound->snd_sound) { + SND_RemoveSound(ghSoundScene, sound->snd_sound); + sound->snd_sound = NULL; + } + } + sound_stop_all_sounds(); SND_RemoveAllSounds(ghSoundScene); } diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index a3fcad7885c..f95b56fe5b0 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -89,6 +89,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_previewrender.h" /* use only so fly mode can preview when its done */ #include "BIF_space.h" @@ -1631,7 +1632,7 @@ void mouse_select(void) /* ------------------------------------------------------------------------- */ -static int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2) +int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2) { int radsq= rad*rad; float v1[2], v2[2], v3[2]; @@ -2247,7 +2248,7 @@ void view3d_border_zoom(void) /* Get Z Depths, needed for perspective, nice for ortho */ bgl_get_mats(&mats); - draw_depth(curarea, (void *)v3d); + draw_depth(curarea, (void *)v3d, NULL); /* force updating */ if (v3d->depths) { diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 2ba5745b19b..cdb001d9193 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -2062,18 +2062,20 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case XKEY: - test = get_hilited_entry(sfile); + if(sfile->type==FILE_BLENDER) { + test = get_hilited_entry(sfile); - if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ - BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); + if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ + BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); - if( okee("Remove %s", str) ) { - ret = BLI_delete(str, 0, 0); - if (ret) { - error("Command failed, see console"); - } else { - freefilelist(sfile); - do_draw= 1; + if( okee("Remove %s", str) ) { + ret = BLI_delete(str, 0, 0); + if (ret) { + error("Command failed, see console"); + } else { + freefilelist(sfile); + do_draw= 1; + } } } } diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c index c4a7b32bf8c..69e3d4c7aac 100644 --- a/source/blender/src/glutil.c +++ b/source/blender/src/glutil.c @@ -290,17 +290,66 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } +#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) { - unsigned char *uc_rect= (unsigned char*) rect; - float *f_rect= (float *)rect; - float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y); - int ltexid= glaGetOneInteger(GL_TEXTURE_2D); - int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); - int subpart_x, subpart_y, tex_w, tex_h; - int texid= get_cached_work_texture(&tex_w, &tex_h); - int nsubparts_x= (img_w+(tex_w-1))/tex_w; - int nsubparts_y= (img_h+(tex_h-1))/tex_h; + float *f_rect; + float xzoom, yzoom; + unsigned char *uc_rect; + int ltexid, lrowlength, texid, tex_w, tex_h; + int subpart_x, subpart_y, nsubparts_x, nsubparts_y; + + uc_rect= (unsigned char*) rect; + f_rect= (float *)rect; + +#ifdef __APPLE__ + /* On Nvidia, Mac OS X 10.5 this function doesn't work correct and + * can crash even, use glDrawPixels instead of textures then */ + if(is_a_really_crappy_nvidia_card()) { + float col[4], modcol[4]; + unsigned char *srect = rect; + int a; + + /* modulate with current color */ + glGetFloatv(GL_CURRENT_COLOR, col); + if(col[0]!=1.0f || col[1]!=1.0f ||col[2]!=1.0f ||col[3]!=1.0f) { + srect = MEM_callocN(4*img_w*img_h, "glDrawPixelsTexSafe"); + for(a=0; a=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf) { float *rf; @@ -717,6 +765,17 @@ int is_a_really_crappy_intel_card(void) return well_is_it; } +int is_a_really_crappy_nvidia_card(void) +{ + static int well_is_it= -1; + + /* Do you understand the implication? Do you? */ + if (well_is_it==-1) + well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); + + return well_is_it; +} + void bglFlush(void) { glFlush(); diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index 9b250fc3ec0..e51636b6748 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -46,7 +46,10 @@ #include "BLI_blenlib.h" #include "DNA_listBase.h" +#include "DNA_armature_types.h" +#include "DNA_curve_types.h" #include "DNA_gpencil_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -57,10 +60,15 @@ #include "BKE_global.h" #include "BKE_utildefines.h" #include "BKE_blender.h" +#include "BKE_armature.h" +#include "BKE_curve.h" +#include "BKE_image.h" #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_butspace.h" +#include "BIF_drawseq.h" +#include "BIF_editarmature.h" #include "BIF_editview.h" #include "BIF_graphics.h" #include "BIF_interface.h" @@ -74,6 +82,8 @@ #include "BDR_gpencil.h" #include "BIF_drawgpencil.h" +#include "BDR_editobject.h" + #include "BSE_drawipo.h" #include "BSE_headerbuttons.h" #include "BSE_view.h" @@ -214,8 +224,8 @@ bGPDlayer *gpencil_layer_addnew (bGPdata *gpd) BLI_addtail(&gpd->layers, gpl); /* set basic settings */ - gpl->color[3]= 1.0f; - gpl->thickness = 1; + gpl->color[3]= 0.9f; + gpl->thickness = 3; /* auto-name */ sprintf(gpl->info, "GP_Layer"); @@ -237,8 +247,7 @@ bGPdata *gpencil_data_addnew (void) gpd= MEM_callocN(sizeof(bGPdata), "GreasePencilData"); /* initial settings */ - /* it is quite useful to be able to see this info, so on by default */ - gpd->flag = GP_DATA_DISPINFO; + gpd->flag = (GP_DATA_DISPINFO|GP_DATA_EXPAND); return gpd; } @@ -678,6 +687,302 @@ void gpencil_delete_menu (void) gpencil_delete_operation(mode); } +/* --------- Data Conversion ---------- */ + +/* convert the coordinates from the given stroke point into 3d-coordinates */ +static void gp_strokepoint_convertcoords (bGPDstroke *gps, bGPDspoint *pt, float p3d[3]) +{ + if (gps->flag & GP_STROKE_3DSPACE) { + /* directly use 3d-coordinates */ + VecCopyf(p3d, &pt->x); + } + else { + short mval[2], mx, my; + float *fp= give_cursor(); + float dvec[3]; + + /* get screen coordinate */ + if (gps->flag & GP_STROKE_2DSPACE) { + View2D *v2d= spacelink_get_view2d(curarea->spacedata.first); + ipoco_to_areaco_noclip(v2d, &pt->x, mval); + } + else { + mval[0]= (pt->x / 1000 * curarea->winx); + mval[1]= (pt->y / 1000 * curarea->winy); + } + mx= mval[0]; + my= mval[1]; + + /* convert screen coordinate to 3d coordinates + * - method taken from editview.c - mouse_cursor() + */ + project_short_noclip(fp, mval); + window_to_3d(dvec, mval[0]-mx, mval[1]-my); + VecSubf(p3d, fp, dvec); + } +} + +/* --- */ + +/* convert stroke to 3d path */ +static void gp_stroke_to_path (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu) +{ + bGPDspoint *pt; + Nurb *nu; + BPoint *bp; + int i; + + /* create new 'nurb' within the curve */ + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + + nu->pntsu= gps->totpoints; + nu->pntsv= 1; + nu->orderu= gps->totpoints; + nu->flagu= 2; /* endpoint */ + nu->resolu= 32; + + nu->bp= (BPoint *)MEM_callocN(sizeof(BPoint)*gps->totpoints, "bpoints"); + + /* add points */ + for (i=0, pt=gps->points, bp=nu->bp; i < gps->totpoints; i++, pt++, bp++) { + float p3d[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3d); + VecCopyf(bp->vec, p3d); + + /* set settings */ + bp->f1= SELECT; + bp->radius = bp->weight = pt->pressure * gpl->thickness; + } + + /* add nurb to curve */ + BLI_addtail(&cu->nurb, nu); +} + +/* convert stroke to 3d bezier */ +static void gp_stroke_to_bezier (bGPDlayer *gpl, bGPDstroke *gps, Curve *cu) +{ + bGPDspoint *pt; + Nurb *nu; + BezTriple *bezt; + int i; + + /* create new 'nurb' within the curve */ + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + + nu->pntsu= gps->totpoints; + nu->resolu= 12; + nu->resolv= 12; + nu->type= CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints*sizeof(BezTriple), "bezts"); + + /* add points */ + for (i=0, pt=gps->points, bezt=nu->bezt; i < gps->totpoints; i++, pt++, bezt++) { + float p3d[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3d); + + /* TODO: maybe in future the handles shouldn't be in same place */ + VecCopyf(bezt->vec[0], p3d); + VecCopyf(bezt->vec[1], p3d); + VecCopyf(bezt->vec[2], p3d); + + /* set settings */ + bezt->h1= bezt->h2= HD_FREE; + bezt->f1= bezt->f2= bezt->f3= SELECT; + bezt->radius = bezt->weight = pt->pressure * gpl->thickness; + } + + /* must calculate handles or else we crash */ + calchandlesNurb(nu); + + /* add nurb to curve */ + BLI_addtail(&cu->nurb, nu); +} + +/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ +static void gp_layer_to_curve (bGPdata *gpd, bGPDlayer *gpl, short mode) +{ + bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps; + Object *ob; + Curve *cu; + + /* error checking */ + if (ELEM3(NULL, gpd, gpl, gpf)) + return; + + /* only convert if there are any strokes on this layer's frame to convert */ + if (gpf->strokes.first == NULL) + return; + + /* initialise the curve */ + cu= add_curve(gpl->info, 1); + cu->flag |= CU_3D; + + /* init the curve object (remove rotation and assign curve data to it) */ + add_object_draw(OB_CURVE); + ob= OBACT; + ob->loc[0]= ob->loc[1]= ob->loc[2]= 0; + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; + ob->data= cu; + + /* add points to curve */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + switch (mode) { + case 1: + gp_stroke_to_path(gpl, gps, cu); + break; + case 2: + gp_stroke_to_bezier(gpl, gps, cu); + break; + } + } +} + +/* --- */ + +/* convert a stroke to a bone chain */ +static void gp_stroke_to_bonechain (bGPDlayer *gpl, bGPDstroke *gps, bArmature *arm, ListBase *bones) +{ + EditBone *ebo, *prev=NULL; + bGPDspoint *pt, *ptn; + int i; + + /* add each segment separately */ + for (i=0, pt=gps->points, ptn=gps->points+1; i < (gps->totpoints-1); prev=ebo, i++, pt++, ptn++) { + float p3da[3], p3db[3]; + + /* get coordinates to add at */ + gp_strokepoint_convertcoords(gps, pt, p3da); + gp_strokepoint_convertcoords(gps, ptn, p3db); + + /* allocate new bone */ + ebo= MEM_callocN(sizeof(EditBone), "eBone"); + + VecCopyf(ebo->head, p3da); + VecCopyf(ebo->tail, p3db); + + /* add new bone - note: sync with editarmature.c::add_editbone() */ + BLI_strncpy(ebo->name, "Stroke", 32); + unique_editbone_name(bones, ebo->name); + + BLI_addtail(bones, ebo); + + ebo->flag |= BONE_CONNECTED; + ebo->weight= 1.0F; + ebo->dist= 0.25F; + ebo->xwidth= 0.1; + ebo->zwidth= 0.1; + ebo->ease1= 1.0; + ebo->ease2= 1.0; + ebo->rad_head= pt->pressure * gpl->thickness * 0.1; + ebo->rad_tail= ptn->pressure * gpl->thickness * 0.1; + ebo->segments= 1; + ebo->layer= arm->layer; + + /* set parenting */ + // TODO: also adjust roll.... + ebo->parent= prev; + } +} + +/* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ +static void gp_layer_to_armature (bGPdata *gpd, bGPDlayer *gpl, short mode) +{ + bGPDframe *gpf= gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps; + Object *ob; + bArmature *arm; + ListBase bones = {0,0}; + + /* error checking */ + if (ELEM3(NULL, gpd, gpl, gpf)) + return; + + /* only convert if there are any strokes on this layer's frame to convert */ + if (gpf->strokes.first == NULL) + return; + + /* initialise the armature */ + arm= add_armature(gpl->info); + + /* init the armature object (remove rotation and assign armature data to it) */ + add_object_draw(OB_ARMATURE); + ob= OBACT; + ob->loc[0]= ob->loc[1]= ob->loc[2]= 0; + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0; + ob->data= arm; + + /* convert segments to bones, strokes to bone chains */ + for (gps= gpf->strokes.first; gps; gps= gps->next) { + gp_stroke_to_bonechain(gpl, gps, arm, &bones); + } + + /* flush editbones to armature */ + editbones_to_armature(&bones, ob); + if (bones.first) BLI_freelistN(&bones); +} + +/* --- */ + +/* convert grease-pencil strokes to another representation + * mode: 1 - Active layer to path + * 2 - Active layer to bezier + * 3 - Active layer to armature + */ +void gpencil_convert_operation (short mode) +{ + bGPdata *gpd; + float *fp= give_cursor(); + + /* get datablock to work on */ + gpd= gpencil_data_getactive(NULL); + if (gpd == NULL) return; + + /* initialise 3d-cursor correction globals */ + initgrabz(fp[0], fp[1], fp[2]); + + /* handle selection modes */ + switch (mode) { + case 1: /* active layer only (to path) */ + case 2: /* active layer only (to bezier) */ + { + bGPDlayer *gpl= gpencil_layer_getactive(gpd); + gp_layer_to_curve(gpd, gpl, mode); + } + break; + case 3: /* active layer only (to armature) */ + { + bGPDlayer *gpl= gpencil_layer_getactive(gpd); + gp_layer_to_armature(gpd, gpl, mode); + } + break; + } + + /* redraw and undo-push */ + BIF_undo_push("GPencil Convert"); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWOOPS, 0); +} + +/* display a menu for converting grease-pencil strokes */ +void gpencil_convert_menu (void) +{ + bGPdata *gpd= gpencil_data_getactive(NULL); + short mode; + + /* only show menu if it will be relevant */ + if (gpd == NULL) return; + + mode= pupmenu("Grease Pencil Convert %t|Active Layer To Path%x1|Active Layer to Bezier%x2|Active Layer to Armature%x3"); + if (mode <= 0) return; + + gpencil_convert_operation(mode); +} + /* ************************************************** */ /* GREASE-PENCIL EDITING MODE - Painting */ @@ -687,11 +992,12 @@ void gpencil_delete_menu (void) #define GP_STROKE_BUFFER_MAX 5000 /* Hardcoded sensitivity thresholds... */ -// TODO: one day, these might be added to the UI if it is necessary /* minimum number of pixels mouse should move before new point created */ -#define MIN_MANHATTEN_PX 3 +//#define MIN_MANHATTEN_PX 3 +#define MIN_MANHATTEN_PX U.gp_manhattendist /* minimum length of new segment before new point can be added */ -#define MIN_EUCLIDEAN_PX 20 +//#define MIN_EUCLIDEAN_PX 20 +#define MIN_EUCLIDEAN_PX U.gp_euclideandist /* ------ */ @@ -707,6 +1013,10 @@ typedef struct tGPsdata { short status; /* current status of painting */ short paintmode; /* mode for painting */ + + short mval[2]; /* current mouse-position */ + short mvalo[2]; /* previous recorded mouse-position */ + short radius; /* radius of influence for eraser */ } tGPsdata; /* values for tGPsdata->status */ @@ -828,7 +1138,7 @@ static void gp_session_initpaint (tGPsdata *p) /* set the current area */ p->sa= curarea; p->v2d= &sima->v2d; - //p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); + p->ibuf= BKE_image_get_ibuf(sima->image, &sima->iuser); } break; /* unsupported views */ @@ -936,24 +1246,45 @@ static void gp_stroke_convertcoords (tGPsdata *p, short mval[], float out[]) out[1]= y; } - /* 2d - on image 'canvas' (asume that p->v2d is set) */ - else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && - (p->v2d) && (p->ibuf) ) + /* 2d - on image 'canvas' (assume that p->v2d is set) */ + else if ( (gpd->sbuffer_sflag & GP_STROKE_2DIMAGE) && (p->v2d) ) { - ImBuf *ibuf= p->ibuf; - float x, y; - - /* convert to 'canvas' coordinates, then adjust for view */ - areamouseco_to_ipoco(p->v2d, mval, &x, &y); - - if (ibuf) { - out[0]= x*ibuf->x; - out[1]= y*ibuf->y; - } - else { - out[0]= x; - out[1]= y; - } + /* for now - space specific */ + switch (p->sa->spacetype) { + case SPACE_SEQ: /* sequencer */ + { + SpaceSeq *sseq= (SpaceSeq *)p->sa->spacedata.first; + int sizex, sizey, offsx, offsy, rectx, recty; + float zoom, zoomx, zoomy; + + /* calculate zoom factor */ + zoom= SEQ_ZOOM_FAC(sseq->zoom); + if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) { + zoomx = zoom * ((float)G.scene->r.xasp / (float)G.scene->r.yasp); + zoomy = zoom; + } + else + zoomx = zoomy = zoom; + + /* calculate rect size */ + rectx= (G.scene->r.size*G.scene->r.xsch)/100; + recty= (G.scene->r.size*G.scene->r.ysch)/100; + sizex= zoomx * rectx; + sizey= zoomy * recty; + offsx= (p->sa->winx-sizex)/2 + sseq->xof; + offsy= (p->sa->winy-sizey)/2 + sseq->yof; + + /* calculate new points */ + out[0]= (float)(mval[0] - offsx) / (float)sizex; + out[1]= (float)(mval[1] - offsy) / (float)sizey; + } + break; + + default: /* just use raw mouse coordinates - BAD! */ + out[0]= mval[0]; + out[1]= mval[1]; + break; + } } /* 2d - relative to screen (viewport area) */ @@ -999,9 +1330,18 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) bGPDspoint *pt; tGPspoint *ptc; int i, totelem; + + /* macro to test if only converting endpoints */ + #define GP_BUFFER2STROKE_ENDPOINTS ((gpd->flag & GP_DATA_EDITPAINT) && (G.qual & LR_CTRLKEY)) - /* get total number of points to allocate space for */ - totelem = gpd->sbuffer_size; + /* get total number of points to allocate space for: + * - in 'Draw Mode', holding the Ctrl-Modifier will only take endpoints + * - otherwise, do whole stroke + */ + if (GP_BUFFER2STROKE_ENDPOINTS) + totelem = (gpd->sbuffer_size >= 2) ? 2: gpd->sbuffer_size; + else + totelem = gpd->sbuffer_size; /* exit with error if no valid points from this stroke */ if (totelem == 0) { @@ -1022,45 +1362,53 @@ static void gp_stroke_newfrombuffer (tGPsdata *p) gps->flag= gpd->sbuffer_sflag; /* copy points from the buffer to the stroke */ - for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { - /* convert screen-coordinates to appropriate coordinates (and store them) */ - gp_stroke_convertcoords(p, &ptc->x, &pt->x); - - /* copy pressure */ - pt->pressure= ptc->pressure; - - pt++; + if (GP_BUFFER2STROKE_ENDPOINTS) { + /* 'Draw Mode' + Ctrl-Modifier - only endpoints */ + { + /* first point */ + ptc= gpd->sbuffer; + + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + + pt++; + } + + if (totelem == 2) { + /* last point if applicable */ + ptc= ((tGPspoint *)gpd->sbuffer) + (gpd->sbuffer_size - 1); + + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + } + } + else { + /* convert all points (normal behaviour) */ + for (i=0, ptc=gpd->sbuffer; i < gpd->sbuffer_size && ptc; i++, ptc++) { + /* convert screen-coordinates to appropriate coordinates (and store them) */ + gp_stroke_convertcoords(p, &ptc->x, &pt->x); + + /* copy pressure */ + pt->pressure= ptc->pressure; + + pt++; + } } /* add stroke to frame */ BLI_addtail(&p->gpf->strokes, gps); + + /* undefine macro to test if only converting endpoints */ + #undef GP_BUFFER2STROKE_ENDPOINTS } /* --- 'Eraser' for 'Paint' Tool ------ */ -/* User should draw 'circles' around the parts of the sketches they wish to - * delete instead of drawing squiggles over existing lines. This should be - * easier to manage than if it was done otherwise. - */ - -/* convert gp-buffer stroke into mouse-coordinates array */ -static short (*gp_stroke_eraser_2mco (bGPdata *gpd))[2] -{ - tGPspoint *pt; - short (*mcoords)[2]; - int i; - - /* allocate memory for coordinates array */ - mcoords= MEM_mallocN(sizeof(*mcoords)*gpd->sbuffer_size,"gp_buf_mcords"); - - /* copy coordinates */ - for (pt=gpd->sbuffer, i=0; i < gpd->sbuffer_size; i++, pt++) { - mcoords[i][0]= pt->x; - mcoords[i][1]= pt->y; - } - - /* return */ - return mcoords; -} /* eraser tool - remove segment from stroke/split stroke (after lasso inside) */ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) @@ -1130,8 +1478,19 @@ static short gp_stroke_eraser_splitdel (bGPDframe *gpf, bGPDstroke *gps, int i) } } +/* eraser tool - check if part of stroke occurs within last segment drawn by eraser */ +static short gp_stroke_eraser_strokeinside (short mval[], short mvalo[], short rad, short x0, short y0, short x1, short y1) +{ + /* simple within-radius check for now */ + if (edge_inside_circle(mval[0], mval[1], rad, x0, y0, x1, y1)) + return 1; + + /* not inside */ + return 0; +} + /* eraser tool - evaluation per stroke */ -static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short moves, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) +static void gp_stroke_eraser_dostroke (tGPsdata *p, short mval[], short mvalo[], short rad, rcti *rect, bGPDframe *gpf, bGPDstroke *gps) { bGPDspoint *pt1, *pt2; short x0=0, y0=0, x1=0, y1=0; @@ -1147,16 +1506,20 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo else if (gps->totpoints == 1) { /* get coordinates */ if (gps->flag & GP_STROKE_3DSPACE) { - // FIXME: this may not be the correct correction project_short(&gps->points->x, xyval); x0= xyval[0]; - x1= xyval[1]; + y0= xyval[1]; } else if (gps->flag & GP_STROKE_2DSPACE) { ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); x0= xyval[0]; y0= xyval[1]; } + else if (gps->flag & GP_STROKE_2DIMAGE) { + ipoco_to_areaco_noclip(p->v2d, &gps->points->x, xyval); + x0= xyval[0]; + y0= xyval[1]; + } else { x0= (gps->points->x / 1000 * p->sa->winx); y0= (gps->points->y / 1000 * p->sa->winy); @@ -1165,7 +1528,7 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo /* do boundbox check first */ if (BLI_in_rcti(rect, x0, y0)) { /* only check if point is inside */ - if (lasso_inside(mcoords, moves, x0, y0)) { + if ( ((x0-mval[0])*(x0-mval[0]) + (y0-mval[1])*(y0-mval[1])) <= rad*rad ) { /* free stroke */ MEM_freeN(gps->points); BLI_freelinkN(&gpf->strokes, gps); @@ -1183,10 +1546,13 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo /* get coordinates */ if (gps->flag & GP_STROKE_3DSPACE) { - // FIXME: may not be correct correction - project_short(&gps->points->x, xyval); + project_short(&pt1->x, xyval); x0= xyval[0]; - x1= xyval[1]; + y0= xyval[1]; + + project_short(&pt2->x, xyval); + x1= xyval[0]; + y1= xyval[1]; } else if (gps->flag & GP_STROKE_2DSPACE) { ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); @@ -1197,6 +1563,15 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo x1= xyval[0]; y1= xyval[1]; } + else if (gps->flag & GP_STROKE_2DIMAGE) { + ipoco_to_areaco_noclip(p->v2d, &pt1->x, xyval); + x0= xyval[0]; + y0= xyval[1]; + + ipoco_to_areaco_noclip(p->v2d, &pt2->x, xyval); + x1= xyval[0]; + y1= xyval[1]; + } else { x0= (pt1->x / 1000 * p->sa->winx); y0= (pt1->y / 1000 * p->sa->winy); @@ -1209,9 +1584,8 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo /* check if point segment of stroke had anything to do with * eraser region (either within stroke painted, or on its lines) * - this assumes that linewidth is irrelevant - * - handled using the lasso-select checking code */ - if (lasso_inside_edge(mcoords, moves, x0, y0, x1, x1)) { + if (gp_stroke_eraser_strokeinside(mval, mvalo, rad, x0, y0, x1, y1)) { /* if function returns true, break this loop (as no more point to check) */ if (gp_stroke_eraser_splitdel(gpf, gps, i)) break; @@ -1221,29 +1595,24 @@ static void gp_stroke_eraser_dostroke (tGPsdata *p, short mcoords[][2], short mo } } -/* -------- */ - /* erase strokes which fall under the eraser strokes */ static void gp_stroke_doeraser (tGPsdata *p) { - bGPdata *gpd= p->gpd; bGPDframe *gpf= p->gpf; bGPDstroke *gps, *gpn; - short (*mcoords)[2]; rcti rect; - /* get buffer-stroke coordinates as shorts array, and then get bounding box */ - mcoords= gp_stroke_eraser_2mco(gpd); - lasso_select_boundbox(&rect, mcoords, gpd->sbuffer_size); + /* rect is rectangle of eraser */ + rect.xmin= p->mval[0] - p->radius; + rect.ymin= p->mval[1] - p->radius; + rect.xmax= p->mval[0] + p->radius; + rect.ymax= p->mval[1] + p->radius; /* loop over strokes, checking segments for intersections */ for (gps= gpf->strokes.first; gps; gps= gpn) { gpn= gps->next; - gp_stroke_eraser_dostroke(p, mcoords, gpd->sbuffer_size, &rect, gpf, gps); + gp_stroke_eraser_dostroke(p, p->mval, p->mvalo, p->radius, &rect, gpf, gps); } - - /* free mcoords array */ - MEM_freeN(mcoords); } /* ---------- 'Paint' Tool ------------ */ @@ -1297,6 +1666,14 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) case SPACE_SEQ: { /* for now, this is not applicable here... */ + p->gpd->sbuffer_sflag |= GP_STROKE_2DIMAGE; + } + break; + case SPACE_IMAGE: + { + /* check if any ibuf available */ + if (p->ibuf) + p->gpd->sbuffer_sflag |= GP_STROKE_2DSPACE; } break; } @@ -1307,11 +1684,7 @@ static void gp_paint_initstroke (tGPsdata *p, short paintmode) static void gp_paint_strokeend (tGPsdata *p) { /* check if doing eraser or not */ - if (p->gpd->sbuffer_sflag & GP_STROKE_ERASER) { - /* get rid of relevant sections of strokes */ - gp_stroke_doeraser(p); - } - else { + if ((p->gpd->sbuffer_sflag & GP_STROKE_ERASER) == 0) { /* transfer stroke to frame */ gp_stroke_newfrombuffer(p); } @@ -1345,7 +1718,6 @@ static void gp_paint_cleanup (tGPsdata *p) short gpencil_paint (short mousebutton, short paintmode) { tGPsdata p; - short prevmval[2], mval[2]; float opressure, pressure; short ok = GP_STROKEADD_NORMAL; @@ -1365,31 +1737,51 @@ short gpencil_paint (short mousebutton, short paintmode) setcursor_space(p.sa->spacetype, CURSOR_VPAINT); /* init drawing-device settings */ - getmouseco_areawin(mval); + getmouseco_areawin(p.mval); pressure = get_pressure(); - prevmval[0]= mval[0]; - prevmval[1]= mval[1]; + p.mvalo[0]= p.mval[0]; + p.mvalo[1]= p.mval[1]; opressure= pressure; + /* radius for eraser circle is thickness^2 */ + p.radius= p.gpl->thickness * p.gpl->thickness; + + /* start drawing eraser-circle (if applicable) */ + if (paintmode == GP_PAINTMODE_ERASER) + draw_sel_circle(p.mval, NULL, p.radius, p.radius, 0); // draws frontbuffer, but sets backbuf again + /* only allow painting of single 'dots' if: * - pressure is not excessive (as it can be on some windows tablets) * - draw-mode for active datablock is turned on + * - not erasing */ - if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { - gp_stroke_addpoint(&p, mval, pressure); + if (paintmode != GP_PAINTMODE_ERASER) { + if (!(pressure >= 0.99f) || (p.gpd->flag & GP_DATA_EDITPAINT)) { + gp_stroke_addpoint(&p, p.mval, pressure); + } } /* paint loop */ do { /* get current user input */ - getmouseco_areawin(mval); + getmouseco_areawin(p.mval); pressure = get_pressure(); /* only add current point to buffer if mouse moved (otherwise wait until it does) */ - if (gp_stroke_filtermval(&p, mval, prevmval)) { + if (paintmode == GP_PAINTMODE_ERASER) { + /* do 'live' erasing now */ + gp_stroke_doeraser(&p); + + draw_sel_circle(p.mval, p.mvalo, p.radius, p.radius, 0); + force_draw(0); + + p.mvalo[0]= p.mval[0]; + p.mvalo[1]= p.mval[1]; + } + else if (gp_stroke_filtermval(&p, p.mval, p.mvalo)) { /* try to add point */ - ok= gp_stroke_addpoint(&p, mval, pressure); + ok= gp_stroke_addpoint(&p, p.mval, pressure); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { @@ -1397,8 +1789,8 @@ short gpencil_paint (short mousebutton, short paintmode) gp_paint_strokeend(&p); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(&p, prevmval, opressure); - ok= gp_stroke_addpoint(&p, mval, pressure); + gp_stroke_addpoint(&p, p.mvalo, opressure); + ok= gp_stroke_addpoint(&p, p.mval, pressure); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1411,8 +1803,8 @@ short gpencil_paint (short mousebutton, short paintmode) } force_draw(0); - prevmval[0]= mval[0]; - prevmval[1]= mval[1]; + p.mvalo[0]= p.mval[0]; + p.mvalo[1]= p.mval[1]; opressure= pressure; } else @@ -1430,8 +1822,10 @@ short gpencil_paint (short mousebutton, short paintmode) setcursor_space(p.sa->spacetype, CURSOR_STD); /* check size of buffer before cleanup, to determine if anything happened here */ - if (paintmode == GP_PAINTMODE_ERASER) - ok= (p.gpd->sbuffer_size > 1); + if (paintmode == GP_PAINTMODE_ERASER) { + ok= 1; // fixme + draw_sel_circle(NULL, p.mvalo, 0, p.radius, 0); + } else ok= p.gpd->sbuffer_size; @@ -1458,7 +1852,8 @@ short gpencil_do_paint (ScrArea *sa, short mbut) /* currently, we will only 'paint' if: * 1. draw-mode on gpd is set (for accessibility reasons) - * (single 'dots' are only available via this method) + * a) single dots are only available by this method if a single click is made + * b) a straight line is drawn if ctrl-modifier is held (check is done when stroke is converted!) * 2. if shift-modifier is held + lmb -> 'quick paint' * * OR diff --git a/source/blender/src/header_image.c b/source/blender/src/header_image.c index fac9e3af1af..4ca287d81c5 100644 --- a/source/blender/src/header_image.c +++ b/source/blender/src/header_image.c @@ -239,8 +239,10 @@ void do_image_buttons(unsigned short event) if(ima->twsta>=nr) ima->twsta= 1; if(ima->twend>=nr) ima->twend= nr-1; if(ima->twsta>ima->twend) ima->twsta= 1; - allqueue(REDRAWIMAGE, 0); } + + allqueue(REDRAWIMAGE, 0); + allqueue(REDRAWVIEW3D, 0); } break; } @@ -475,6 +477,9 @@ static void do_image_viewmenu(void *arg, int event) G.sima->flag ^= SI_LOCAL_UV; allqueue(REDRAWIMAGE, 0); break; + case 15: /* Grease Pencil... */ + add_blockhandler(curarea, IMAGE_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -497,6 +502,8 @@ static uiBlock *image_viewmenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Curves Tool...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 11, ""); uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Composite Preview...|Shift P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 12, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL, "Grease Pencil...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + if(G.sima->flag & SI_LOCAL_UV) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "UV Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); else uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "UV Local View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); if(!(G.sima->flag & SI_LOCAL_UV)) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "UV Global View|NumPad /", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 14, ""); @@ -1293,7 +1300,7 @@ void image_buttons(void) uiBlockEndAlign(block); xco+= 166; } - uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enables painting textures on the image with left mouse button"); + uiDefIconButBitI(block, TOG, SI_DRAWTOOL, B_SIMAGEPAINTTOOL, ICON_TPAINT_HLT, xco,0,XIC,YIC, &G.sima->flag, 0, 0, 0, 0, "Enable image painting"); xco+= XIC+8; diff --git a/source/blender/src/header_info.c b/source/blender/src/header_info.c index 8b8fd9ef266..9bacc2b6351 100644 --- a/source/blender/src/header_info.c +++ b/source/blender/src/header_info.c @@ -39,8 +39,6 @@ #include #endif -#include "BLO_sys_types.h" // for intptr_t support - #include "DNA_group_types.h" #include "DNA_ID.h" #include "DNA_image_types.h" @@ -120,6 +118,9 @@ #include "BPY_extern.h" #include "BPY_menus.h" +#include "GPU_extensions.h" +#include "GPU_material.h" + #include "blendef.h" #include "interface.h" #include "mydevice.h" @@ -926,7 +927,7 @@ static void do_info_filemenu(void *arg, int event) winqueue_break= 1; /* leave queues everywhere */ BKE_reset_undo(); - BKE_write_undo("original"); /* save current state */ + BKE_write_undo("Original"); /* save current state */ refresh_interface_font(); } break; @@ -1591,20 +1592,83 @@ static uiBlock *info_addmenu(void *arg_unused) /************************** GAME *****************************/ +void do_info_game_glslmenu(void *arg, int event) +{ + switch (event) { + case G_FILE_GLSL_NO_LIGHTS: + case G_FILE_GLSL_NO_SHADERS: + case G_FILE_GLSL_NO_SHADOWS: + case G_FILE_GLSL_NO_RAMPS: + case G_FILE_GLSL_NO_NODES: + case G_FILE_GLSL_NO_EXTRA_TEX: + G.fileflags ^= event; + GPU_materials_free(); + allqueue(REDRAWINFO, 0); + allqueue(REDRAWVIEW3D, 0); + break; + default: + break; + } +} + +static uiBlock *info_game_glslmenu(void *arg_unused) +{ + uiBlock *block; + short yco= 0, menuwidth=160; + int check; + block= uiNewBlock(&curarea->uiblocks, "game_glslmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_info_game_glslmenu, NULL); + + check = (G.fileflags & G_FILE_GLSL_NO_LIGHTS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Lights", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_LIGHTS, + "Enable using lights in GLSL materials."); + check = (G.fileflags & G_FILE_GLSL_NO_SHADERS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Shaders", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_SHADERS, + "Enable using shaders other than Lambert in GLSL materials"); + check = (G.fileflags & G_FILE_GLSL_NO_SHADOWS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Shadows", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_SHADOWS, + "Enable using shadows in GLSL materials"); + check = (G.fileflags & G_FILE_GLSL_NO_RAMPS)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Ramps", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_RAMPS, + "Enable using ramps in GLSL materials"); + check = (G.fileflags & G_FILE_GLSL_NO_NODES)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Nodes", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_NODES, + "Enable using nodes in GLSL materials."); + check = (G.fileflags & G_FILE_GLSL_NO_EXTRA_TEX)? ICON_CHECKBOX_DEHLT: ICON_CHECKBOX_HLT; + uiDefIconTextBut(block, BUTM, 1, check, "Enable Extra Textures", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GLSL_NO_EXTRA_TEX, + "Enable using texture channels other than Col and Alpha in GLSL materials."); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 50); + + return block; +} + static void do_info_gamemenu(void *arg, int event) { switch (event) { case G_FILE_ENABLE_ALL_FRAMES: - case G_FILE_DIAPLAY_LISTS: + case G_FILE_DISPLAY_LISTS: case G_FILE_SHOW_FRAMERATE: case G_FILE_SHOW_DEBUG_PROPS: case G_FILE_AUTOPLAY: case G_FILE_GAME_TO_IPO: - case G_FILE_GAME_MAT: case G_FILE_SHOW_PHYSICS: G.fileflags ^= event; break; + case G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL: + G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + break; + case G_FILE_GAME_MAT: + G.fileflags |= G_FILE_GAME_MAT; + G.fileflags &= ~G_FILE_GAME_MAT_GLSL; + break; + case G_FILE_GAME_MAT_GLSL: + if(!GPU_extensions_minimum_support()) + error("GLSL not supported with this graphics card or driver."); + G.fileflags |= (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + break; default: ; /* ignore the rest */ } @@ -1635,22 +1699,14 @@ static uiBlock *info_gamemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } else { - if(G.fileflags & G_FILE_DIAPLAY_LISTS) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DIAPLAY_LISTS, ""); + if(G.fileflags & G_FILE_DISPLAY_LISTS) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, ""); } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DIAPLAY_LISTS, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Generate Display Lists", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_DISPLAY_LISTS, ""); } uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, ""); } - if(G.fileflags & G_FILE_GAME_MAT) { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); - } else { - uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); - } - - - if(G.fileflags & G_FILE_SHOW_FRAMERATE) { uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Show Framerate and Profile", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_FRAMERATE, ""); } else { @@ -1669,6 +1725,28 @@ static uiBlock *info_gamemenu(void *arg_unused) } else { uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Show Debug Properties", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_SHOW_DEBUG_PROPS, ""); } + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); + + if(!(G.fileflags & G_FILE_GAME_MAT)) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Texture Face Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Texture Face Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL, ""); + } + + if((G.fileflags & G_FILE_GAME_MAT) && !(G.fileflags & G_FILE_GAME_MAT_GLSL)) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Blender Multitexture Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Blender Multitexture Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, ""); + } + + if((G.fileflags & G_FILE_GAME_MAT) && (G.fileflags & G_FILE_GAME_MAT_GLSL)) { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Blender GLSL Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 0, ""); + } else { + uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Blender GLSL Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT_GLSL, ""); + } + + uiDefIconTextBlockBut(block, info_game_glslmenu, NULL, ICON_RIGHTARROW_THIN, "GLSL Material Settings", 0, yco-=20, menuwidth, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 1, 0, ""); @@ -2108,13 +2186,16 @@ static void info_text(int x, int y) { Object *ob= OBACT; extern float hashvectf[]; - extern uintptr_t mem_in_use, mmap_in_use; + uintptr_t mem_in_use, mmap_in_use; unsigned int swatch_color; float fac1, fac2, fac3; char infostr[300], memstr[64]; char *headerstr, *s; int hsize; + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + s= memstr + sprintf(memstr," | Mem:%.2fM ", ((mem_in_use-mmap_in_use)>>10)/1024.0); if(mmap_in_use) sprintf(s,"(%.2fM) ", ((mmap_in_use)>>10)/1024.0); diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 59d542e72ec..130ffa1e49f 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -1414,7 +1414,7 @@ void ipo_buttons(void) uiClearButLock(); /* ZOOMBORDER */ - uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area"); + uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area (Shift B)"); xco+=XIC/2; diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index 4c7b4aa80bc..d27a41c59f5 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -112,7 +112,7 @@ static void do_node_viewmenu(void *arg, int event) break; case 4: /* Grease Pencil */ add_blockhandler(curarea, NODES_HANDLER_GREASEPENCIL, UI_PNL_UNSTOW); - break; + break; } allqueue(REDRAWNODE, 0); } @@ -602,11 +602,11 @@ static uiBlock *node_nodemenu(void *arg_unused) if(snode->treetype==NTREE_COMPOSIT) { uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Execute Composite|E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Render Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Read Saved Full Sample Results|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 13, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl LMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Connect Node to Viewer|Ctrl RMB", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 14, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c index cf6d21ff264..eeea43ec57a 100644 --- a/source/blender/src/header_text.c +++ b/source/blender/src/header_text.c @@ -42,6 +42,7 @@ #include "BMF_Api.h" #include "BIF_language.h" +#include "MEM_guardedalloc.h" #include "BSE_headerbuttons.h" @@ -52,6 +53,7 @@ #include "DNA_constraint_types.h" #include "DNA_action_types.h" +#include "BIF_gl.h" /* for glRasterPos2i */ #include "BIF_drawtext.h" #include "BIF_interface.h" #include "BIF_resources.h" @@ -128,7 +130,7 @@ void do_text_buttons(unsigned short event) st->top= 0; pop_space_text(st); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); } @@ -194,14 +196,20 @@ void do_text_buttons(unsigned short event) break; case B_TAB_NUMBERS: - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); break; case B_SYNTAX: - if (st->showsyntax) { - get_format_string(st); - } + if (st->showsyntax) txt_format_text(st); + allqueue(REDRAWTEXT, 0); + allqueue(REDRAWHEADERS, 0); + break; + case B_TEXTPLUGINS: + allqueue(REDRAWHEADERS, 0); + break; + case B_WORDWRAP: + st->left= 0; allqueue(REDRAWTEXT, 0); allqueue(REDRAWHEADERS, 0); break; @@ -239,6 +247,37 @@ static uiBlock *text_template_scriptsmenu (void *args_unused) return block; } +static void do_text_plugin_scriptsmenu(void *arg, int event) +{ + BPY_menu_do_python(PYMENU_TEXTPLUGIN, event); + + allqueue(REDRAWIMAGE, 0); +} + +static uiBlock *text_plugin_scriptsmenu (void *args_unused) +{ + uiBlock *block; + BPyMenu *pym; + int i= 0; + short yco = 20, menuwidth = 120; + + block= uiNewBlock(&curarea->uiblocks, "text_plugin_scriptsmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_text_plugin_scriptsmenu, NULL); + + /* note that we acount for the N previous entries with i+20: */ + for (pym = BPyMenuTable[PYMENU_TEXTPLUGIN]; pym; pym = pym->next, i++) { + + uiDefIconTextBut(block, BUTM, 1, ICON_PYTHON, pym->name, 0, yco-=20, menuwidth, 19, + NULL, 0.0, 0.0, 1, i, + pym->tooltip?pym->tooltip:pym->filename); + } + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 60); + + return block; +} + /* action executed after clicking in File menu */ static void do_text_filemenu(void *arg, int event) { @@ -268,7 +307,7 @@ static void do_text_filemenu(void *arg, int event) if (!reopen_text(text)) { error("Could not reopen file"); } - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); } break; case 5: @@ -277,9 +316,14 @@ static void do_text_filemenu(void *arg, int event) txt_write_file(text); break; case 6: - run_python_script(st); + text->flags |= TXT_ISMEM | TXT_ISDIRTY | TXT_ISTMP; + MEM_freeN(text->name); + text->name= NULL; break; case 7: + run_python_script(st); + break; + case 8: { Object *ob; bConstraint *con; @@ -340,11 +384,17 @@ static void do_text_editmenu(void *arg, int event) switch(event) { case 1: txt_do_undo(text); + pop_space_text(st); break; case 2: txt_do_redo(text); + pop_space_text(st); break; case 3: + if (text && text->id.lib) { + error_libdata(); + break; + } txt_copy_clipboard(text); txt_cut_sel(text); pop_space_text(st); @@ -354,8 +404,12 @@ static void do_text_editmenu(void *arg, int event) txt_copy_clipboard(text); break; case 5: + if (text && text->id.lib) { + error_libdata(); + break; + } txt_paste_clipboard(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; case 6: txt_print_cutbuffer(); @@ -364,10 +418,11 @@ static void do_text_editmenu(void *arg, int event) jumptoline_interactive(st); break; case 8: - txt_find_panel(st,1); - break; case 9: - txt_find_panel(st,0); + find_and_replace(st, 0); + break; + case 10: + find_and_replace(st, 1); break; default: break; @@ -443,6 +498,57 @@ static void do_text_editmenu_selectmenu(void *arg, int event) } } +/* action executed after clicking in Markers menu */ +static void do_text_editmenu_markermenu(void *arg, int event) +{ + SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */ + Text *text; + TextMarker *mrk; + ScrArea *sa; + int lineno; + + if (st==NULL || st->spacetype != SPACE_TEXT) return; + + text = st->text; + + switch(event) { + case 1: + txt_clear_markers(text, 0, 0); + break; + case 2: + lineno= txt_get_span(text->lines.first, text->curl); + mrk= text->markers.first; + while (mrk && (mrk->linenolineno==lineno && mrk->start <= text->curc))) + mrk= mrk->next; + if (!mrk) mrk= text->markers.first; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + } + break; + case 3: + lineno= txt_get_span(text->lines.first, text->curl); + mrk= text->markers.last; + while (mrk && (mrk->lineno>lineno || (mrk->lineno==lineno && mrk->end > text->curc))) + mrk= mrk->prev; + if (!mrk) mrk= text->markers.last; + if (mrk) { + txt_move_to(text, mrk->lineno, mrk->start, 0); + txt_move_to(text, mrk->lineno, mrk->end, 1); + } + break; + default: + break; + } + + for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { + SpaceText *st= sa->spacedata.first; + if (st && st->spacetype==SPACE_TEXT) { + scrarea_queue_redraw(sa); + } + } +} + /* action executed after clicking in Format menu */ static void do_text_formatmenu(void *arg, int event) { @@ -456,6 +562,10 @@ static void do_text_formatmenu(void *arg, int event) switch(event) { case 3: + if (text && text->id.lib) { + error_libdata(); + break; + } if (txt_has_sel(text)) { txt_order_cursors(text); indent(text); @@ -466,6 +576,10 @@ static void do_text_formatmenu(void *arg, int event) break; } case 4: + if (text && text->id.lib) { + error_libdata(); + break; + } if ( txt_has_sel(text)) { txt_order_cursors(text); unindent(text); @@ -473,18 +587,26 @@ static void do_text_formatmenu(void *arg, int event) } break; case 5: + if (text && text->id.lib) { + error_libdata(); + break; + } if ( txt_has_sel(text)) { txt_order_cursors(text); comment(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; } break; case 6: + if (text && text->id.lib) { + error_libdata(); + break; + } if ( txt_has_sel(text)) { txt_order_cursors(text); uncomment(text); - if (st->showsyntax) get_format_string(st); + if (st->showsyntax) txt_format_text(st); break; } break; @@ -536,6 +658,25 @@ static uiBlock *text_editmenu_selectmenu(void *arg_unused) return block; } +/* Select menu */ +static uiBlock *text_editmenu_markermenu(void *arg_unused) +{ + uiBlock *block; + short yco = 20, menuwidth = 120; + + block= uiNewBlock(&curarea->uiblocks, "text_editmenu_markermenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); + uiBlockSetButmFunc(block, do_text_editmenu_markermenu, NULL); + + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear All", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Next Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Previous Marker", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, ""); + + uiBlockSetDirection(block, UI_RIGHT); + uiTextBoundsBlock(block, 60); + + return block; +} + void do_text_formatmenu_convert(void *arg, int event) { SpaceText *st= curarea->spacedata.first; /* bad but cant pass as an arg here */ @@ -649,10 +790,12 @@ static uiBlock *text_editmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, text_editmenu_viewmenu, NULL, ICON_RIGHTARROW_THIN, "View|Alt Shift V ", 0, yco-=20, 120, 19, ""); uiDefIconTextBlockBut(block, text_editmenu_selectmenu, NULL, ICON_RIGHTARROW_THIN, "Select|Alt Shift S ", 0, yco-=20, 120, 19, ""); + uiDefIconTextBlockBut(block, text_editmenu_markermenu, NULL, ICON_RIGHTARROW_THIN, "Markers", 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, "Jump...|Alt J", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find...|Alt Ctrl F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Again|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find And Replace...|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Find Next|Alt F", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 9, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Replace|Alt H", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 10, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBlockBut(block, text_editmenu_to3dmenu, NULL, ICON_RIGHTARROW_THIN, "Text to 3d Object", 0, yco-=20, 120, 19, ""); @@ -690,17 +833,21 @@ static uiBlock *text_filemenu(void *arg_unused) uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save|Alt S", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Save As...", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, ""); + if (text->name) + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Make Internal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Run Python Script|Alt P", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); if (BPY_is_pyconstraint(text)) - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 7, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Refresh All PyConstraints", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 8, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); } uiDefIconTextBlockBut(block, text_template_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Script Templates", 0, yco-=20, 120, 19, ""); + uiDefIconTextBlockBut(block, text_plugin_scriptsmenu, NULL, ICON_RIGHTARROW_THIN, "Text Plugins", 0, yco-=20, 120, 19, ""); if(curarea->headertype==HEADERTOP) { uiBlockSetDirection(block, UI_DOWN); @@ -715,13 +862,15 @@ static uiBlock *text_filemenu(void *arg_unused) } /* header */ +#define HEADER_PATH_MAX 260 void text_buttons(void) { uiBlock *block; SpaceText *st= curarea->spacedata.first; Text *text; short xco, xmax; - char naam[256]; + char naam[256], fname[HEADER_PATH_MAX], headtxt[HEADER_PATH_MAX+17]; + int len; if (st==NULL || st->spacetype != SPACE_TEXT) return; @@ -779,8 +928,9 @@ void text_buttons(void) else uiDefIconBut(block, BUT,B_FULL, ICON_FULLSCREEN, xco,0,XIC,YIC, 0, 0, 0, 0, 0, "Makes current window full screen (CTRL+Down arrow)"); uiDefIconButI(block, ICONTOG, B_TEXTLINENUM, ICON_LONGDISPLAY, xco+=XIC,0,XIC,YIC, &st->showlinenrs, 0, 0, 0, 0, "Displays line numbers"); - - uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables Syntax Highlighting"); + uiDefIconButI(block, ICONTOG, B_WORDWRAP, ICON_WORDWRAP, xco+=XIC,0,XIC,YIC, &st->wordwrap, 0, 0, 0, 0, "Enables word wrap"); + uiDefIconButI(block, ICONTOG, B_SYNTAX, ICON_SYNTAX, xco+=XIC,0,XIC,YIC, &st->showsyntax, 0, 0, 0, 0, "Enables syntax highlighting"); + uiDefIconButI(block, ICONTOG, B_TEXTPLUGINS, ICON_PYTHON, xco+=XIC,0,XIC,YIC, &st->doplugins, 0, 0, 0, 0, "Enables Python text plugins"); uiBlockEndAlign(block); /* STD TEXT BUTTONS */ @@ -804,9 +954,30 @@ void text_buttons(void) uiDefButI(block, MENU, B_TEXTFONT, "Screen 12 %x0|Screen 15%x1", xco,0,100,YIC, &st->font_id, 0, 0, 0, 0, "Displays available fonts"); xco+=110; - uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab"); + uiDefButI(block, NUM, B_TAB_NUMBERS, "Tab:", xco, 0, XIC+50, YIC, &st->tabnumber, 2, 8, 0, 0, "Set spacing of Tab"); xco+= XIC+50; - + + /* File info */ + if (text) { + if (text->name) { + len = strlen(text->name); + if (len > HEADER_PATH_MAX-1) + len = HEADER_PATH_MAX-1; + strncpy(fname, text->name, len); + fname[len]='\0'; + if (text->flags & TXT_ISDIRTY) + sprintf(headtxt, "File: *%s (unsaved)", fname); + else + sprintf(headtxt, "File: %s", fname); + } else { + sprintf(headtxt, text->id.lib?"Text: External":"Text: Internal"); + } + BIF_ThemeColor(TH_MENU_TEXT); + glRasterPos2i(xco+=XIC, 5); + BMF_DrawString(G.font, headtxt); + xco += BMF_GetStringWidth(G.font, headtxt); + } + /* always as last */ curarea->headbutlen= xco+2*XIC; diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index fcf4caf4522..36ba819b3f1 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -106,6 +106,7 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_meshtools.h" #include "BIF_poselib.h" @@ -2522,6 +2523,9 @@ static void do_view3d_edit_objectmenu(void *arg, int event) if(session) b_verse_push_object(session, ob); break; #endif + case 18: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -2558,6 +2562,7 @@ static uiBlock *view3d_edit_objectmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3150,6 +3155,9 @@ static void do_view3d_edit_meshmenu(void *arg, int event) case 15: uv_autocalc_tface(); break; + case 16: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -3185,6 +3193,7 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3416,6 +3425,9 @@ static void do_view3d_edit_curvemenu(void *arg, int event) case 15: uv_autocalc_tface(); break; + case 16: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -3440,6 +3452,7 @@ static uiBlock *view3d_edit_curvemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3760,6 +3773,9 @@ static void do_view3d_edit_latticemenu(void *arg, int event) case 6: uv_autocalc_tface(); break; + case 7: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -3783,6 +3799,7 @@ static uiBlock *view3d_edit_latticemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -4170,7 +4187,7 @@ static uiBlock *view3d_pose_armature_ikmenu(void *arg_unused) uiBlockSetButmFunc(block, do_view3d_pose_armature_ikmenu, NULL); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add IK to Bone...|Shift I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear IK...|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear IK...|Ctrl Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); @@ -4370,6 +4387,12 @@ static void do_view3d_pose_armaturemenu(void *arg, int event) case 18: pose_autoside_names(event-16); break; + case 19: /* assign pose as restpose */ + apply_armature_pose2bones(); + break; + case 20: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); @@ -4391,10 +4414,12 @@ static uiBlock *view3d_pose_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Relax Pose|W", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 15, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Apply Pose as Restpose|Ctrl A", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 19, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -4508,7 +4533,7 @@ static void do_view3d_tpaintmenu(void *arg, int event) { switch(event) { case 0: /* undo image painting */ - imagepaint_undo(); + undo_imagepaint_step(1); break; } @@ -5383,7 +5408,11 @@ void do_view3d_buttons(short event) case B_MAN_MODE: allqueue(REDRAWVIEW3D, 1); break; - + case B_VIEW_BUTSEDIT: + allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWBUTSEDIT, 1); + break; + default: if(event>=B_LAY && eventlocalview==0) { + int ob_lay = ob ? ob->lay : 0; uiBlockBeginAlign(block); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); - for(a=0; a<5; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - + for(a=0; a<5; a++) { + uiDefIconButBitI(block, TOG, 1<lay_used), (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } + for(a=0; a<5; a++) { + uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, G.vd->lay_used), (short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } xco+= 5; uiBlockBeginAlign(block); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<lay), 0, 0, 0, 0, "Toggles Layer visibility (Num, Shift Num)"); - for(a=5; a<10; a++) - uiDefButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, "",(short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); - + for(a=5; a<10; a++) { + uiDefIconButBitI(block, TOG, 1<lay_used), (short)(xco+a*(XIC/2)), (short)(YIC/2),(short)(XIC/2),(short)(YIC/2), &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } + for(a=5; a<10; a++) { + uiDefIconButBitI(block, TOG, 1<<(a+10), B_LAY+10+a, view3d_layer_icon(1<<(a+10), ob_lay, G.vd->lay_used), (short)(xco+a*(XIC/2)), 0, XIC/2, (YIC)/2, &(G.vd->lay), 0, 0, 0, 0, "Toggles Layer visibility (Alt Num, Alt Shift Num)"); + } uiBlockEndAlign(block); xco+= (a-2)*(XIC/2)+3; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 1a91ada1562..44044841a99 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -154,7 +154,6 @@ #include "BSE_editipo.h" #include "BSE_drawipo.h" -#include "BDR_drawmesh.h" #include "BDR_vpaint.h" #include "BDR_editface.h" #include "BDR_editobject.h" @@ -165,6 +164,8 @@ #include "BPY_extern.h" #include "BPY_menus.h" +#include "GPU_draw.h" + #include "mydevice.h" #include "blendef.h" #include "interface.h" @@ -1425,11 +1426,11 @@ void do_global_buttons(unsigned short event) show_splash(); break; case B_MIPMAPCHANGED: - set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); allqueue(REDRAWVIEW3D, 0); break; case B_GLRESLIMITCHANGED: - free_all_realtime_images(); /* force reloading with new res limit */ + GPU_free_images(); /* force reloading with new res limit */ allqueue(REDRAWVIEW3D, 0); break; case B_NEWSPACE: diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 15c289cc21c..164c368b6fa 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -44,6 +44,8 @@ #include "BLI_winstuff.h" #endif #include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" #include "PIL_time.h" #include "IMB_imbuf.h" @@ -64,10 +66,12 @@ #include "BKE_brush.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_main.h" #include "BKE_mesh.h" #include "BKE_node.h" #include "BKE_utildefines.h" +#include "BIF_interface.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" @@ -78,10 +82,11 @@ #include "BSE_trans_types.h" #include "BSE_view.h" -#include "BDR_drawmesh.h" #include "BDR_imagepaint.h" #include "BDR_vpaint.h" +#include "GPU_draw.h" + #include "GHOST_Types.h" #include "blendef.h" @@ -103,6 +108,8 @@ #define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) #define IMAPAINT_TILE_NUMBER(size) (((size)+IMAPAINT_TILE_SIZE-1) >> IMAPAINT_TILE_BITS) +#define MAXUNDONAME 64 + typedef struct ImagePaintState { Brush *brush; short tool, blend; @@ -120,48 +127,206 @@ typedef struct ImagePaintState { float uv[2]; } ImagePaintState; -typedef struct ImagePaintUndo { - Image *image; - ImBuf *tilebuf; - void **tiles; - int xtiles, ytiles; -} ImagePaintUndo; +typedef struct UndoTile { + struct UndoTile *next, *prev; + ID id; + void *rect; + int x, y; +} UndoTile; + +typedef struct UndoElem { + struct UndoElem *next, *prev; + char name[MAXUNDONAME]; + unsigned long undosize; + + ImBuf *ibuf; + ListBase tiles; +} UndoElem; typedef struct ImagePaintPartialRedraw { int x1, y1, x2, y2; int enabled; } ImagePaintPartialRedraw; -static ImagePaintUndo imapaintundo = {NULL, NULL, NULL, 0, 0}; +static ListBase undobase = {NULL, NULL}; +static UndoElem *curundo = NULL; static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0}; -static void init_imagapaint_undo(Image *ima, ImBuf *ibuf) +/* UNDO */ + +/* internal functions */ + +static void undo_copy_tile(UndoTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore) { - int xt, yt; + /* copy or swap contents of tile->rect and region in ibuf->rect */ + IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x*IMAPAINT_TILE_SIZE, + tile->y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); - imapaintundo.image = ima; - imapaintundo.xtiles = xt = IMAPAINT_TILE_NUMBER(ibuf->x); - imapaintundo.ytiles = yt = IMAPAINT_TILE_NUMBER(ibuf->y); - imapaintundo.tiles = MEM_callocN(sizeof(void*)*xt*yt, "ImagePaintUndoTiles"); - imapaintundo.tilebuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, - ibuf->depth, (ibuf->rect_float)? IB_rectfloat: IB_rect, 0); -} - -static void imapaint_copy_tile(ImBuf *ibuf, int tile, int x, int y, int swapundo) -{ - IMB_rectcpy(imapaintundo.tilebuf, ibuf, 0, 0, x*IMAPAINT_TILE_SIZE, - y*IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); - - if (imapaintundo.tilebuf->rect_float) - SWAP(void*, imapaintundo.tilebuf->rect_float, imapaintundo.tiles[tile]) - else - SWAP(void*, imapaintundo.tilebuf->rect, imapaintundo.tiles[tile]) + if(ibuf->rect_float) SWAP(void*, tmpibuf->rect_float, tile->rect) + else SWAP(void*, tmpibuf->rect, tile->rect) - if (swapundo) - IMB_rectcpy(ibuf, imapaintundo.tilebuf, x*IMAPAINT_TILE_SIZE, - y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); + if(restore) + IMB_rectcpy(ibuf, tmpibuf, tile->x*IMAPAINT_TILE_SIZE, + tile->y*IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } +static void undo_restore(UndoElem *undo) +{ + Image *ima = NULL; + ImBuf *ibuf, *tmpibuf; + UndoTile *tile; + + if(!undo) + return; + + tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, + IB_rectfloat|IB_rect, 0); + + for(tile=undo->tiles.first; tile; tile=tile->next) { + /* find image based on name, pointer becomes invalid with global undo */ + if(ima && strcmp(tile->id.name, ima->id.name)==0); + else { + for(ima=G.main->image.first; ima; ima=ima->id.next) + if(strcmp(tile->id.name, ima->id.name)==0) + break; + } + + ibuf= BKE_image_get_ibuf(ima, NULL); + + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) + continue; + + undo_copy_tile(tile, tmpibuf, ibuf, 1); + + GPU_free_image(ima); /* force OpenGL reload */ + if(ibuf->rect_float) + imb_freerectImBuf(ibuf); /* force recreate of char rect */ + } + + IMB_freeImBuf(tmpibuf); +} + +static void undo_free(UndoElem *undo) +{ + UndoTile *tile; + + for(tile=undo->tiles.first; tile; tile=tile->next) + MEM_freeN(tile->rect); + BLI_freelistN(&undo->tiles); +} + +static void undo_imagepaint_push_begin(char *name) +{ + UndoElem *uel; + int nr; + + /* Undo push is split up in begin and end, the reason is that as painting + * happens more tiles are added to the list, and at the very end we know + * how much memory the undo used to remove old undo elements */ + + /* remove all undos after (also when curundo==NULL) */ + while(undobase.last != curundo) { + uel= undobase.last; + undo_free(uel); + BLI_freelinkN(&undobase, uel); + } + + /* make new */ + curundo= uel= MEM_callocN(sizeof(UndoElem), "undo file"); + BLI_addtail(&undobase, uel); + + /* name can be a dynamic string */ + strncpy(uel->name, name, MAXUNDONAME-1); + + /* limit amount to the maximum amount*/ + nr= 0; + uel= undobase.last; + while(uel) { + nr++; + if(nr==U.undosteps) break; + uel= uel->prev; + } + if(uel) { + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + undo_free(first); + BLI_freelinkN(&undobase, first); + } + } +} + +static void undo_imagepaint_push_end() +{ + UndoElem *uel; + unsigned long totmem, maxmem; + + if(U.undomemory != 0) { + /* limit to maximum memory (afterwards, we can't know in advance) */ + totmem= 0; + maxmem= ((unsigned long)U.undomemory)*1024*1024; + + uel= undobase.last; + while(uel) { + totmem+= uel->undosize; + if(totmem>maxmem) break; + uel= uel->prev; + } + + if(uel) { + while(undobase.first!=uel) { + UndoElem *first= undobase.first; + undo_free(first); + BLI_freelinkN(&undobase, first); + } + } + } +} + +/* external functions */ + +/* 1= an undo, -1 is a redo. */ +void undo_imagepaint_step(int step) +{ + UndoElem *undo; + + if(step==1) { + if(curundo==NULL) error("No more steps to undo"); + else { + if(G.f & G_DEBUG) printf("undo %s\n", curundo->name); + undo_restore(curundo); + curundo= curundo->prev; + } + } + else if(step==-1) { + if((curundo!=NULL && curundo->next==NULL) || undobase.first==NULL) error("No more steps to redo"); + else { + undo= (curundo && curundo->next)? curundo->next: undobase.first; + undo_restore(undo); + curundo= undo; + if(G.f & G_DEBUG) printf("redo %s\n", undo->name); + } + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWIMAGE, 0); +} + +void undo_imagepaint_clear(void) +{ + UndoElem *uel; + + uel= undobase.first; + while(uel) { + undo_free(uel); + uel= uel->next; + } + + BLI_freelistN(&undobase); + curundo= NULL; +} + +/* Imagepaint Partial Redraw & Dirty Region */ + static void imapaint_clear_partial_redraw() { memset(&imapaintpartial, 0, sizeof(imapaintpartial)); @@ -169,7 +334,9 @@ static void imapaint_clear_partial_redraw() static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) { - int srcx= 0, srcy= 0, origx, tile, allocsize; + ImBuf *tmpibuf; + UndoTile *tile; + int srcx= 0, srcy= 0, origx, allocsize; IMB_rectclip(ibuf, NULL, &x, &y, &srcx, &srcy, &w, &h); @@ -195,24 +362,36 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, origx = (x >> IMAPAINT_TILE_BITS); y = (y >> IMAPAINT_TILE_BITS); + tmpibuf= IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, + IB_rectfloat|IB_rect, 0); + for (; y <= h; y++) { for (x=origx; x <= w; x++) { - if (ima != imapaintundo.image) { - free_imagepaint(); - init_imagapaint_undo(ima, ibuf); - } + for(tile=curundo->tiles.first; tile; tile=tile->next) + if(tile->x == x && tile->y == y && strcmp(tile->id.name, ima->id.name)==0) + break; - tile = y*imapaintundo.xtiles + x; - if (!imapaintundo.tiles[tile]) { - allocsize= (ibuf->rect_float)? sizeof(float): sizeof(char); - imapaintundo.tiles[tile]= MEM_mapallocN(allocsize*4* - IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE, "ImagePaintUndoTile"); - imapaint_copy_tile(ibuf, tile, x, y, 0); + if(!tile) { + tile= MEM_callocN(sizeof(UndoTile), "ImaUndoTile"); + tile->id= ima->id; + tile->x= x; + tile->y= y; + + allocsize= IMAPAINT_TILE_SIZE*IMAPAINT_TILE_SIZE*4; + allocsize *= (ibuf->rect_float)? sizeof(float): sizeof(char); + tile->rect= MEM_mapallocN(allocsize, "ImaUndoRect"); + + undo_copy_tile(tile, tmpibuf, ibuf, 0); + curundo->undosize += allocsize; + + BLI_addtail(&curundo->tiles, tile); } } } ibuf->userflags |= IB_BITMAPDIRTY; + + IMB_freeImBuf(tmpibuf); } static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) @@ -226,7 +405,7 @@ static void imapaint_image_update(Image *image, ImBuf *ibuf, short texpaint) if(texpaint || G.sima->lock) { int w = imapaintpartial.x2 - imapaintpartial.x1; int h = imapaintpartial.y2 - imapaintpartial.y1; - update_realtime_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); + GPU_paint_update_image(image, imapaintpartial.x1, imapaintpartial.y1, w, h); } } @@ -239,7 +418,7 @@ static void imapaint_redraw(int final, int texpaint, Image *image) allqueue(REDRAWIMAGE, 0); else if(!G.sima->lock) { if(image) - free_realtime_image(image); /* force OpenGL reload */ + GPU_free_image(image); /* force OpenGL reload */ allqueue(REDRAWVIEW3D, 0); } allqueue(REDRAWHEADERS, 0); @@ -269,46 +448,6 @@ static void imapaint_redraw(int final, int texpaint, Image *image) force_draw(0); } -void imagepaint_undo() -{ - Image *ima= imapaintundo.image; - ImBuf *ibuf= BKE_image_get_ibuf(ima, G.sima?&G.sima->iuser:NULL); - int x, y, tile; - - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) - return; - - for (tile = 0, y = 0; y < imapaintundo.ytiles; y++) - for (x = 0; x < imapaintundo.xtiles; x++, tile++) - if (imapaintundo.tiles[tile]) - imapaint_copy_tile(ibuf, tile, x, y, 1); - - free_realtime_image(ima); /* force OpenGL reload */ - if(ibuf->rect_float) - imb_freerectImBuf(ibuf); /* force recreate of char rect */ - - allqueue(REDRAWIMAGE, 0); - allqueue(REDRAWVIEW3D, 0); -} - -void free_imagepaint() -{ - /* todo: does this need to be in the same places as editmode_undo_clear, - vertex paint isn't? */ - int i, size = imapaintundo.xtiles*imapaintundo.ytiles; - - if (imapaintundo.tiles) { - for (i = 0; i < size; i++) - if (imapaintundo.tiles[i]) - MEM_freeN(imapaintundo.tiles[i]); - MEM_freeN(imapaintundo.tiles); - } - if (imapaintundo.tilebuf) - IMB_freeImBuf(imapaintundo.tilebuf); - - memset(&imapaintundo, 0, sizeof(imapaintundo)); -} - /* Image Paint Operations */ static void imapaint_ibuf_get_set_rgb(ImBuf *ibuf, int x, int y, short torus, short set, float *rgb) @@ -580,7 +719,6 @@ static void imapaint_paint_stroke(ImagePaintState *s, BrushPainter *painter, sho int breakstroke = 0, redraw = 0; if (texpaint) { - /* pick new face and image */ if (facesel_face_pick(s->me, mval, &newfaceindex, 0)) { ImBuf *ibuf; @@ -692,7 +830,7 @@ void imagepaint_paint(short mousebutton, short texpaint) } settings->imapaint.flag |= IMAGEPAINT_DRAWING; - free_imagepaint(); + undo_imagepaint_push_begin("Image Paint"); /* create painter and paint once */ painter= brush_painter_new(s.brush); @@ -741,6 +879,7 @@ void imagepaint_paint(short mousebutton, short texpaint) brush_painter_free(painter); imapaint_redraw(1, texpaint, s.image); + undo_imagepaint_push_end(); if (texpaint) { if (s.warnmultifile) diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c new file mode 100644 index 00000000000..c62032cd9d6 --- /dev/null +++ b/source/blender/src/keyframing.c @@ -0,0 +1,1839 @@ +/** + * $Id: keyframing.c 14881 2008-05-18 10:41:42Z aligorith $ + * + * ***** 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 + * This is a new part of Blender (with some old code) + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" + +#include "DNA_listBase.h" +#include "DNA_ID.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" +#include "DNA_lamp_types.h" +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" +#include "DNA_vec_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" +#include "BKE_blender.h" +#include "BKE_main.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_ipo.h" +#include "BKE_object.h" + +#include "BIF_keyframing.h" +#include "BIF_butspace.h" +#include "BIF_editaction.h" +#include "BIF_editkey.h" +#include "BIF_interface.h" +#include "BIF_mywindow.h" +#include "BIF_poseobject.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_toolbox.h" +#include "BIF_toets.h" + +#include "BSE_editipo.h" +#include "BSE_node.h" +#include "BSE_time.h" +#include "BSE_view.h" + +#include "blendef.h" + +#include "PIL_time.h" /* sleep */ +#include "mydevice.h" + +/* ************************************************** */ +/* LOCAL TYPES AND DEFINES */ + +/* -------------- Keying Sets ------------------- */ + +/* keying set - a set of channels that will be keyframed together */ +// TODO: move this to a header to allow custom sets someday? +typedef struct bKeyingSet { + /* callback func to consider if keyingset should be included + * (by default, if this is undefined, item will be shown) + */ + short (*include_cb)(struct bKeyingSet *, const char *); + + char name[48]; /* name of keyingset */ + int blocktype; /* blocktype that all channels belong to */ // in future, this may be eliminated + short flag; /* flags to use when setting keyframes */ + + short chan_num; /* number of channels to insert keyframe in */ + short adrcodes[32]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */ +} bKeyingSet; + +/* keying set context - an array of keying sets and the number of them */ +typedef struct bKeyingContext { + bKeyingSet *keyingsets; /* array containing the keyingsets of interest */ + bKeyingSet *lastused; /* item that was chosen last time*/ + int tot; /* number of keyingsets in */ +} bKeyingContext; + + +/* ----------- Common KeyData Sources ------------ */ + +/* temporary struct to gather data combos to keyframe */ +typedef struct bCommonKeySrc { + struct bCommonKeySrc *next, *prev; + + /* general data/destination-source settings */ + ID *id; /* id-block this comes from */ + char *actname; /* name of action channel */ + char *constname; /* name of constraint channel */ + + /* general destination source settings */ + Ipo *ipo; /* ipo-block that id-block has (optional) */ + bAction *act; /* action-block that id-block has (optional) */ + + /* pose-level settings */ + bPoseChannel *pchan; /* pose channel */ + + /* buttons-window settings */ + int map; /* offset to apply to certain adrcodes */ +} bCommonKeySrc; + +/* ************************************************** */ +/* KEYFRAME INSERTION */ + +/* -------------- BezTriple Insertion -------------------- */ + +/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ +#define BEZT_INSERT_THRESH 0.00001 + +/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + const float frame= (item)? item->vec[1][0] : 0.0f; + + /* initialise replace-flag first */ + *replace= 0; + + /* sneaky optimisations (don't go through searching process if...): + * - keyframe to be added is to be added out of current bounds + * - keyframe to be added would replace one of the existing ones on bounds + */ + if ((arraylen <= 0) || ELEM(NULL, array, item)) { + printf("Warning: binarysearch_bezt_index encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum= array[0].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Keyframe */ + framenum= array[(arraylen-1)].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace= 1; + return (arraylen - 1); + } + else if (frame > framenum) + return arraylen; + } + + + /* most of the time, this loop is just to find where to put it + * 'loopbreaker' is just here to prevent infinite loops + */ + for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { + /* compute and get midpoint */ + int mid = (start + end) / 2; + float midfra= array[mid].vec[1][0]; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { + *replace = 1; + return mid; + } + + /* repeat in upper/lower half */ + if (frame > midfra) + start= mid + 1; + else if (frame < midfra) + end= mid - 1; + } + + /* print error if loop-limit exceeded */ + if (loopbreaker == (maxloop-1)) { + printf("Error: binarysearch_bezt_index was taking too long \n"); + + // include debug info + printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); + } + + /* not found, so return where to place it */ + return start; +} + +/* This function adds a given BezTriple to an IPO-Curve. It will allocate + * memory for the array if needed, and will insert the BezTriple into a + * suitable place in chronological order. + * + * NOTE: any recalculate of the IPO-Curve that needs to be done will need to + * be done by the caller. + */ +int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) +{ + BezTriple *newb; + int i= 0; + + if (icu->bezt == NULL) { + icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); + *(icu->bezt)= *bezt; + icu->totvert= 1; + } + else { + short replace = -1; + i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); + + if (replace) { + /* sanity check: 'i' may in rare cases exceed arraylen */ + if ((i >= 0) && (i < icu->totvert)) + *(icu->bezt + i) = *bezt; + } + else { + /* add new */ + newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); + + /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ + if (i > 0) + memcpy(newb, icu->bezt, i*sizeof(BezTriple)); + + /* add beztriple to paste at index i */ + *(newb + i)= *bezt; + + /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ + if (i < icu->totvert) + memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); + + /* replace (+ free) old with new */ + MEM_freeN(icu->bezt); + icu->bezt= newb; + + icu->totvert++; + } + } + + /* we need to return the index, so that some tools which do post-processing can + * detect where we added the BezTriple in the array + */ + return i; +} + +/* This function is a wrapper for insert_bezt_icu, and should be used when + * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere + * else yet. + * + * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. + */ +void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) +{ + BezTriple beztr; + int a, h1, h2; + + /* set all three points, for nicer start position */ + memset(&beztr, 0, sizeof(BezTriple)); + beztr.vec[0][0]= x; + beztr.vec[0][1]= y; + beztr.vec[1][0]= x; + beztr.vec[1][1]= y; + beztr.vec[2][0]= x; + beztr.vec[2][1]= y; + beztr.hide= IPO_BEZ; + beztr.f1= beztr.f2= beztr.f3= SELECT; + beztr.h1= beztr.h2= HD_AUTO; + + /* add temp beztriple to keyframes */ + a= insert_bezt_icu(icu, &beztr); + if (!fast) calchandles_ipocurve(icu); + + /* set handletype */ + if (icu->totvert > 2) { + BezTriple *bezt; + + h1= h2= HD_AUTO; + bezt= (icu->bezt + a); + + if (a > 0) h1= (bezt-1)->h2; + if (a < icu->totvert-1) h2= (bezt+1)->h1; + + bezt->h1= h1; + bezt->h2= h2; + + if (!fast) calchandles_ipocurve(icu); + } +} + +/* ------------------- Get Data ------------------------ */ + +/* Get pointer to use to get values from */ +// FIXME: this should not be possible with Data-API +static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) +{ + switch (blocktype) { + case ID_PO: /* posechannel */ + if (GS(id->name)==ID_OB) { + Object *ob= (Object *)id; + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + *vartype= IPO_FLOAT; + return get_pchan_ipo_poin(pchan, icu->adrcode); + } + } + break; + + case ID_CO: /* constraint */ + if ((GS(id->name)==ID_OB) && (constname && constname[0])) { + Object *ob= (Object *)id; + bConstraint *con; + + /* assume that we only want the influence (as only used for Constraint Channels) */ + if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { + for (con= ob->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + else if (ob->pose) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + } + } + break; + + case ID_OB: /* object */ + /* hack: layer channels for object need to be keyed WITHOUT localview flag... + * tsk... tsk... why must we just dump bitflags upon users :/ + */ + if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) { + Object *ob= (Object *)id; + static int layer = 0; + + /* init layer to be the object's layer var, then remove local view from it */ + layer = ob->lay; + layer &= 0xFFFFFF; + *vartype= IPO_INT_BIT; + + /* return pointer to this static var + * - assumes that this pointer won't be stored for use later, so may not be threadsafe + * if multiple keyframe calls are made, but that is unlikely to happen in the near future + */ + return (void *)(&layer); + } + /* no break here for other ob channel-types - as they can be done normally */ + + default: /* normal data-source */ + return get_ipo_poin(id, icu, vartype); + } + + /* not valid... */ + return NULL; +} + + +/* -------------- 'Smarter' Keyframing Functions -------------------- */ +/* return codes for new_key_needed */ +enum { + KEYNEEDED_DONTADD = 0, + KEYNEEDED_JUSTADD, + KEYNEEDED_DELPREV, + KEYNEEDED_DELNEXT +} eKeyNeededStatus; + +/* This helper function determines whether a new keyframe is needed */ +/* Cases where keyframes should not be added: + * 1. Keyframe to be added bewteen two keyframes with similar values + * 2. Keyframe to be added on frame where two keyframes are already situated + * 3. Keyframe lies at point that intersects the linear line between two keyframes + */ +static short new_key_needed (IpoCurve *icu, float cFrame, float nValue) +{ + BezTriple *bezt=NULL, *prev=NULL; + int totCount, i; + float valA = 0.0f, valB = 0.0f; + + /* safety checking */ + if (icu == NULL) return KEYNEEDED_JUSTADD; + totCount= icu->totvert; + if (totCount == 0) return KEYNEEDED_JUSTADD; + + /* loop through checking if any are the same */ + bezt= icu->bezt; + for (i=0; ivec[1][0]; + beztVal= bezt->vec[1][1]; + + if (prev) { + /* there is a keyframe before the one currently being examined */ + + /* get previous time+value */ + prevPosi= prev->vec[1][0]; + prevVal= prev->vec[1][1]; + + /* keyframe to be added at point where there are already two similar points? */ + if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { + return KEYNEEDED_DONTADD; + } + + /* keyframe between prev+current points ? */ + if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { + /* is the value of keyframe to be added the same as keyframes on either side ? */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { + return KEYNEEDED_DONTADD; + } + else { + float realVal; + + /* get real value of curve at that point */ + realVal= eval_icu(icu, cFrame); + + /* compare whether it's the same as proposed */ + if (IS_EQ(realVal, nValue)) + return KEYNEEDED_DONTADD; + else + return KEYNEEDED_JUSTADD; + } + } + + /* new keyframe before prev beztriple? */ + if (cFrame < prevPosi) { + /* A new keyframe will be added. However, whether the previous beztriple + * stays around or not depends on whether the values of previous/current + * beztriples and new keyframe are the same. + */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) + return KEYNEEDED_DELNEXT; + else + return KEYNEEDED_JUSTADD; + } + } + else { + /* just add a keyframe if there's only one keyframe + * and the new one occurs before the exisiting one does. + */ + if ((cFrame < beztPosi) && (totCount==1)) + return KEYNEEDED_JUSTADD; + } + + /* continue. frame to do not yet passed (or other conditions not met) */ + if (i < (totCount-1)) { + prev= bezt; + bezt++; + } + else + break; + } + + /* Frame in which to add a new-keyframe occurs after all other keys + * -> If there are at least two existing keyframes, then if the values of the + * last two keyframes and the new-keyframe match, the last existing keyframe + * gets deleted as it is no longer required. + * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last + * keyframe is not equal to last keyframe. + */ + bezt= (icu->bezt + (icu->totvert - 1)); + valA= bezt->vec[1][1]; + + if (prev) + valB= prev->vec[1][1]; + else + valB= bezt->vec[1][1] + 1.0f; + + if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) + return KEYNEEDED_DELPREV; + else + return KEYNEEDED_JUSTADD; +} + +/* ------------------ 'Visual' Keyframing Functions ------------------ */ + +/* internal status codes for visualkey_can_use */ +enum { + VISUALKEY_NONE = 0, + VISUALKEY_LOC, + VISUALKEY_ROT +}; + +/* This helper function determines if visual-keyframing should be used when + * inserting keyframes for the given channel. As visual-keyframing only works + * on Object and Pose-Channel blocks, this should only get called for those + * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying + * settings is on. + */ +static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode) +{ + Object *ob= NULL; + bConstraint *con= NULL; + short searchtype= VISUALKEY_NONE; + + /* validate data */ + if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO))) + return 0; + + /* get first constraint and determine type of keyframe constraints to check for*/ + ob= (Object *)id; + + if (blocktype == ID_OB) { + con= ob->constraints.first; + + if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) + searchtype= VISUALKEY_LOC; + else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) + searchtype= VISUALKEY_ROT; + } + else if (blocktype == ID_PO) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + con= pchan->constraints.first; + + if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) + searchtype= VISUALKEY_LOC; + else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) + searchtype= VISUALKEY_ROT; + } + + /* only search if a searchtype and initial constraint are available */ + if (searchtype && con) { + for (; con; con= con->next) { + /* only consider constraint if it is not disabled, and has influence */ + if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->enforce == 0.0f) continue; + + /* some constraints may alter these transforms */ + switch (con->type) { + /* multi-transform constraints */ + case CONSTRAINT_TYPE_CHILDOF: + return 1; + case CONSTRAINT_TYPE_TRANSFORM: + return 1; + case CONSTRAINT_TYPE_FOLLOWPATH: + return 1; + + /* single-transform constraits */ + case CONSTRAINT_TYPE_TRACKTO: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_ROTLIMIT: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_LOCLIMIT: + if (searchtype==VISUALKEY_LOC) return 1; + break; + case CONSTRAINT_TYPE_ROTLIKE: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_LOCLIKE: + if (searchtype==VISUALKEY_LOC) return 1; + break; + case CONSTRAINT_TYPE_LOCKTRACK: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_MINMAX: + if (searchtype==VISUALKEY_LOC) return 1; + break; + + default: + break; + } + } + } + + /* when some condition is met, this function returns, so here it can be 0 */ + return 0; +} + +/* This helper function extracts the value to use for visual-keyframing + * In the event that it is not possible to perform visual keying, try to fall-back + * to using the poin method. Assumes that all data it has been passed is valid. + */ +static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu) +{ + Object *ob; + void *poin = NULL; + int index, vartype; + + /* validate situtation */ + if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0)) + return 0.0f; + + /* get object */ + ob= (Object *)id; + + /* only valid for objects or posechannels */ + if (blocktype == ID_OB) { + /* parented objects are not supported, as the effects of the parent + * are included in the matrix, which kindof beats the point + */ + if ((ob) && (ob->parent==NULL)) { + /* only Location or Rotation keyframes are supported now */ + if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) { + /* assumes that OB_LOC_Z > OB_LOC_Y > OB_LOC_X */ + index= adrcode - OB_LOC_X; + + return ob->obmat[3][index]; + } + else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) { + float eul[3]; + + /* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */ + index= adrcode - OB_ROT_X; + + Mat4ToEul(ob->obmat, eul); + return eul[index]*(5.72958); + } + } + } + else if (blocktype == ID_PO) { + bPoseChannel *pchan; + float tmat[4][4]; + + /* get data to use */ + pchan= get_pose_channel(ob->pose, actname); + + /* Although it is not strictly required for this particular space conversion, + * arg1 must not be null, as there is a null check for the other conversions to + * be safe. Therefore, the active object is passed here, and in many cases, this + * will be what owns the pose-channel that is getting this anyway. + */ + Mat4CpyMat4(tmat, pchan->pose_mat); + constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + + /* Loc, Rot/Quat keyframes are supported... */ + if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) { + /* assumes that AC_LOC_Z > AC_LOC_Y > AC_LOC_X */ + index= adrcode - AC_LOC_X; + + /* only use for non-connected bones */ + if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED)) + return tmat[3][index]; + else if (pchan->bone->parent == NULL) + return tmat[3][index]; + } + else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) { + float tmat[4][4], trimat[3][3], quat[4]; + + /* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */ + index= adrcode - AC_QUAT_W; + + Mat3CpyMat4(trimat, tmat); + Mat3ToQuat_is_ok(trimat, quat); + + return quat[index]; + } + } + + /* as the function hasn't returned yet, try reading from poin */ + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + if (poin) + return read_ipo_poin(poin, vartype); + else + return 0.0; +} + + +/* ------------------------- Insert Key API ------------------------- */ + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, + * and extra keyframe filtering. + */ +short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) +{ + IpoCurve *icu; + + /* get ipo-curve */ + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1); + + /* only continue if we have an ipo-curve to add keyframe to */ + if (icu) { + float cfra = frame_to_float(CFRA); + float curval= 0.0f; + void *poin = NULL; + int vartype; + + /* apply special time tweaking */ + if (GS(id->name) == ID_OB) { + Object *ob= (Object *)id; + + /* apply NLA-scaling (if applicable) */ + if (actname && actname[0]) + cfra= get_action_frame(ob, cfra); + + /* ancient time-offset cruft */ + if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* get pointer to data to read from */ + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + if (poin == NULL) return 0; + + /* obtain value to give keyframe */ + if ( (flag & INSERTKEY_MATRIX) && + (visualkey_can_use(id, blocktype, actname, constname, adrcode)) ) + { + /* visual-keying is only available for object and pchan datablocks, as + * it works by keyframing using a value extracted from the final matrix + * instead of using the kt system to extract a value. + */ + curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu); + } + else { + /* use kt's read_poin function to extract value (kt->read_poin should + * exist in all cases, but it never hurts to check) + */ + curval= read_ipo_poin(poin, vartype); + } + + /* only insert keyframes where they are needed */ + if (flag & INSERTKEY_NEEDED) { + short insert_mode; + + /* check whether this curve really needs a new keyframe */ + insert_mode= new_key_needed(icu, cfra, curval); + + /* insert new keyframe at current frame */ + if (insert_mode) + insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); + + /* delete keyframe immediately before/after newly added */ + switch (insert_mode) { + case KEYNEEDED_DELPREV: + delete_icu_key(icu, icu->totvert-2, 1); + break; + case KEYNEEDED_DELNEXT: + delete_icu_key(icu, 1, 1); + break; + } + } + else { + /* just insert keyframe */ + insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); + } + + /* return success */ + return 1; + } + + /* return failure */ + return 0; +} + + +/* ************************************************** */ +/* KEYFRAME DELETION */ + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will delete a keyframe at the current frame. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe deletion. These include the quick refresh options. + */ +short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) +{ + Ipo *ipo; + IpoCurve *icu; + + /* get ipo-curve + * Note: here is one of the places where we don't want new ipo + ipo-curve added! + * so 'add' var must be 0 + */ + ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0); + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0); + + /* only continue if we have an ipo-curve to remove keyframes from */ + if (icu) { + BezTriple bezt; + float cfra = frame_to_float(CFRA); + short found = -1; + int i; + + /* apply special time tweaking */ + if (GS(id->name) == ID_OB) { + Object *ob= (Object *)id; + + /* apply NLA-scaling (if applicable) */ + if (actname && actname[0]) + cfra= get_action_frame(ob, cfra); + + /* ancient time-offset cruft */ + if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* only need to set bezt->vec[1][0], as that's all binarysearch uses */ + memset(&bezt, 0, sizeof(BezTriple)); + bezt.vec[1][0]= cfra; + + /* try to find index of beztriple to get rid of */ + i = binarysearch_bezt_index(icu->bezt, &bezt, icu->totvert, &found); + if (found) { + /* delete the key at the index (will sanity check + do recalc afterwards ) */ + delete_icu_key(icu, i, 1); + + /* Only delete curve too if there isn't an ipo-driver still hanging around on an empty curve */ + if (icu->totvert==0 && icu->driver==NULL) { + BLI_remlink(&ipo->curve, icu); + free_ipo_curve(icu); + } + + /* return success */ + return 1; + } + } + + /* return failure */ + return 0; +} + +/* ************************************************** */ +/* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */ + + +/* ------------- KeyingSet Defines ------------ */ +/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */ + +/* macro for defining keyingset contexts */ +#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)} + +/* --- */ + +/* check if option not available for deleting keys */ +static short incl_non_del_keys (bKeyingSet *ks, const char mode[]) +{ + /* as optimisation, assume that it is sufficient to check only first letter + * of mode (int comparison should be faster than string!) + */ + //if (strcmp(mode, "Delete")==0) + if (mode && mode[0]=='D') + return 0; + + return 1; +} + +/* Object KeyingSets ------ */ + +/* check if include shapekey entry */ +static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[]) +{ + Object *ob= (G.obedit)? (G.obedit) : (OBACT); + char *newname= NULL; + + /* not available for delete mode */ + if (strcmp(mode, "Delete")==0) + return 0; + + /* check if is geom object that can get shapekeys */ + switch (ob->type) { + /* geometry? */ + case OB_MESH: newname= "Mesh"; break; + case OB_CURVE: newname= "Curve"; break; + case OB_SURF: newname= "Surface"; break; + case OB_LATTICE: newname= "Lattice"; break; + + /* not geometry! */ + default: + return 0; + } + + /* if ks is shapekey entry (this could be callled for separator before too!) */ + if (ks->flag == -3) + sprintf(ks->name, newname); + + /* if it gets here, it's ok */ + return 1; +} + +/* array for object keyingset defines */ +bKeyingSet defks_v3d_object[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "LocRot", ID_OB, 0, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "LocScale", ID_OB, 0, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "LocRotScale", ID_OB, 0, 9, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "RotScale", ID_OB, 0, 6, + {OB_ROT_X,OB_ROT_Y,OB_ROT_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator + + {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option... + {NULL, "Available", ID_OB, -2, 0, {0}}, + + {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry) + {incl_v3d_ob_shapekey, "", ID_OB, -3, 0, {0}} +}; + +/* PoseChannel KeyingSets ------ */ + +/* array for posechannel keyingset defines */ +bKeyingSet defks_v3d_pchan[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "LocRot", ID_PO, 0, 7, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, + AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "LocScale", ID_PO, 0, 6, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, + AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "LocRotScale", ID_PO, 0, 10, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,AC_QUAT_X, + AC_QUAT_Y,AC_QUAT_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "RotScale", ID_PO, 0, 7, + {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z, + AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator + + {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, + AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_PO, -2, 0, {0}} +}; + +/* Material KeyingSets ------ */ + +/* array for material keyingset defines */ +bKeyingSet defks_buts_shading_mat[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}}, + {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}}, + {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}}, + {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "All Color", ID_MA, 0, 18, + {MA_COL_R,MA_COL_G,MA_COL_B, + MA_ALPHA,MA_HASIZE, MA_MODE, + MA_SPEC_R,MA_SPEC_G,MA_SPEC_B, + MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD, + MA_MODE,MA_TRANSLU,MA_ADD}}, + + {NULL, "All Mirror", ID_MA, 0, 5, + {MA_RAYM,MA_FRESMIR,MA_FRESMIRI, + MA_FRESTRA,MA_FRESTRAI}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Ofs", ID_MA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_MA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_MA, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_MA, -2, 0, {0}} +}; + +/* World KeyingSets ------ */ + +/* array for world keyingset defines */ +bKeyingSet defks_buts_shading_wo[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}}, + {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}}, + {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}}, + + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Ofs", ID_WO, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_WO, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_WO, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_WO, -2, 0, {0}} +}; + +/* Lamp KeyingSets ------ */ + +/* array for lamp keyingset defines */ +bKeyingSet defks_buts_shading_la[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}}, + {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}}, + {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Ofs", ID_LA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_LA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_LA, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_LA, -2, 0, {0}} +}; + +/* Texture KeyingSets ------ */ + +/* array for texture keyingset defines */ +bKeyingSet defks_buts_shading_tex[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Clouds", ID_TE, 0, 5, + {TE_NSIZE,TE_NDEPTH,TE_NTYPE, + TE_MG_TYP,TE_N_BAS1}}, + + {NULL, "Marble", ID_TE, 0, 7, + {TE_NSIZE,TE_NDEPTH,TE_NTYPE, + TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, + + {NULL, "Stucci", ID_TE, 0, 5, + {TE_NSIZE,TE_NTYPE,TE_TURB, + TE_MG_TYP,TE_N_BAS1}}, + + {NULL, "Wood", ID_TE, 0, 6, + {TE_NSIZE,TE_NTYPE,TE_TURB, + TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, + + {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}}, + + {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}}, + + {NULL, "Musgrave", ID_TE, 0, 6, + {TE_MG_TYP,TE_MGH,TE_MG_LAC, + TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}}, + + {NULL, "Voronoi", ID_TE, 0, 9, + {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4, + TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT, + TE_ISCA,TE_NSIZE}}, + + {NULL, "Distorted Noise", ID_TE, 0, 4, + {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}}, + + {NULL, "Color Filter", ID_TE, 0, 5, + {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_TE, -2, 0, {0}} +}; + +/* Object Buttons KeyingSets ------ */ + +/* check if include particles entry */ +static short incl_buts_ob (bKeyingSet *ks, const char mode[]) +{ + Object *ob= OBACT; + /* only if object is mesh type */ + return (ob->type == OB_MESH); +} + +/* array for texture keyingset defines */ +bKeyingSet defks_buts_object[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}}, + {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}}, + {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}}, + {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too! +}; + +/* Camera Buttons KeyingSets ------ */ + +/* check if include internal-renderer entry */ +static short incl_buts_cam1 (bKeyingSet *ks, const char mode[]) +{ + /* only if renderer is internal renderer */ + return (G.scene->r.renderer==R_INTERN); +} + +/* check if include external-renderer entry */ +static short incl_buts_cam2 (bKeyingSet *ks, const char mode[]) +{ + /* only if renderer is internal renderer */ + return (G.scene->r.renderer!=R_INTERN); +} + +/* array for camera keyingset defines */ +bKeyingSet defks_buts_cam[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}}, + {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}}, + {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + + {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}}, + {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}}, + + {NULL, "%l", 0, -1, 0, {0}}, // separator + + {NULL, "Available", ID_CA, -2, 0, {0}} +}; + +/* --- */ + +/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */ +bKeyingContext ks_contexts[] = +{ + KSC_TEMPLATE(v3d_object), + KSC_TEMPLATE(v3d_pchan), + + KSC_TEMPLATE(buts_shading_mat), + KSC_TEMPLATE(buts_shading_wo), + KSC_TEMPLATE(buts_shading_la), + KSC_TEMPLATE(buts_shading_tex), + + KSC_TEMPLATE(buts_object), + KSC_TEMPLATE(buts_cam) +}; + +/* Keying Context Enumeration - Must keep in sync with definitions*/ +typedef enum eKS_Contexts { + KSC_V3D_OBJECT = 0, + KSC_V3D_PCHAN, + + KSC_BUTS_MAT, + KSC_BUTS_WO, + KSC_BUTS_LA, + KSC_BUTS_TEX, + + KSC_BUTS_OB, + KSC_BUTS_CAM, + + /* make sure this last one remains untouched! */ + KSC_TOT_TYPES +} eKS_Contexts; + + +/* ---------------- KeyingSet Tools ------------------- */ + +/* helper for commonkey_context_get() - get keyingsets for 3d-view */ +static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) +{ + Object *ob; + IpoCurve *icu; + + if ((OBACT) && (OBACT->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + + /* pose-level */ + ob= OBACT; + *ksc= &ks_contexts[KSC_V3D_PCHAN]; + set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ + + /* loop through posechannels */ + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { + if (pchan->flag & POSE_KEY) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to, and action */ + cks->id= (ID *)ob; + cks->act= ob->action; + + /* set pchan */ + cks->pchan= pchan; + cks->actname= pchan->name; + } + } + } + else { + Base *base; + + /* object-level */ + *ksc= &ks_contexts[KSC_V3D_OBJECT]; + + /* loop through bases */ + for (base= FIRSTBASE; base; base= base->next) { + if (TESTBASELIB(base)) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + ob= base->object; + cks->id= (ID *)ob; + + /* when ob's keyframes are in an action, default to using 'Object' as achan name */ + if (ob->ipoflag & OB_ACTION_OB) + cks->actname= "Object"; + + /* set ipo-flags */ + // TODO: add checks for lib-linked data + if ((ob->ipo) || (ob->action)) { + if (ob->ipo) { + cks->ipo= ob->ipo; + } + else { + bActionChannel *achan; + + cks->act= ob->action; + achan= get_action_channel(ob->action, cks->actname); + + if (achan && achan->ipo) + cks->ipo= achan->ipo; + } + + /* deselect all ipo-curves */ + for (icu= cks->ipo->curve.first; icu; icu= icu->next) { + icu->flag &= ~IPO_SELECT; + } + } + } + } + } +} + +/* helper for commonkey_context_get() - get keyingsets for buttons window */ +static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) +{ + bCommonKeySrc *cks; + + /* check on tab-type */ + switch (G.buts->mainb) { + case CONTEXT_SHADING: /* ------------- Shading buttons ---------------- */ + /* subtabs include "Material", "Texture", "Lamp", "World"*/ + switch (G.buts->tab[CONTEXT_SHADING]) { + case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */ + { + Material *ma= editnode_get_active_material(G.buts->lockpoin); + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)ma; + cks->ipo= ma->ipo; + cks->map= texchannel_to_adrcode(ma->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_MAT]; + return; + } + break; + case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */ + { + World *wo= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)wo; + cks->ipo= wo->ipo; + cks->map= texchannel_to_adrcode(wo->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_WO]; + return; + } + break; + case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */ + { + Lamp *la= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)la; + cks->ipo= la->ipo; + cks->map= texchannel_to_adrcode(la->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_LA]; + return; + } + break; + case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */ + { + Tex *tex= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)tex; + cks->ipo= tex->ipo; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_TEX]; + return; + } + break; + } + break; + + case CONTEXT_OBJECT: /* ------------- Object buttons ---------------- */ + { + Object *ob= OBACT; + + if (ob) { + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + cks->id= (ID *)ob; + cks->ipo= ob->ipo; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_OB]; + return; + } + } + break; + + case CONTEXT_EDITING: /* ------------- Editing buttons ---------------- */ + { + Object *ob= OBACT; + + if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */ + Camera *ca= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + cks->id= (ID *)ca; + cks->ipo= ca->ipo; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_CAM]; + return; + } + } + break; + } + + /* if nothing happened... */ + *ksc= NULL; +} + + +/* get keyingsets for appropriate context */ +static void commonkey_context_get (ListBase *sources, bKeyingContext **ksc) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + commonkey_context_getv3d(sources, ksc); + break; + + /* buttons view */ + case SPACE_BUTS: + commonkey_context_getsbuts(sources, ksc); + break; + } +} + +/* flush updates after all operations */ +static void commonkey_context_finish (ListBase *sources) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + { + /* either pose or object level */ + if (OBACT && (OBACT->pose)) { + Object *ob= OBACT; + + /* recalculate ipo handles, etc. */ + if (ob->action) + remake_action_ipos(ob->action); + + /* recalculate bone-paths on adding new keyframe? */ + // TODO: currently, there is no setting to turn this on/off globally + if (ob->pose->flag & POSE_RECALCPATHS) + pose_recalculate_paths(ob); + } + else { + bCommonKeySrc *cks; + + /* loop over bases (as seen in sources) */ + for (cks= sources->first; cks; cks= cks->next) { + Object *ob= (Object *)cks->id; + + /* simply set recalc flag */ + ob->recalc |= OB_RECALC_OB; + } + } + } + break; + } +} + +/* flush refreshes after undo */ +static void commonkey_context_refresh (void) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + { + /* do refreshes */ + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); + + allspace(REMAKEIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWMARKER, 0); + } + break; + } +} + +/* --- */ + +/* Build menu-string of available keying-sets (allocates memory for string) + * NOTE: mode must not be longer than 64 chars + */ +static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48]) +{ + DynStr *pupds= BLI_dynstr_new(); + bKeyingSet *ks; + char buf[64]; + char *str; + int i, n; + + /* add title first */ + BLI_snprintf(buf, 64, "%s Key %%t|", mode); + BLI_dynstr_append(pupds, buf); + + /* loop through keyingsets, adding them */ + for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) { + /* check if keyingset can be used */ + if (ks->flag == -1) { + /* optional separator? */ + if (ks->include_cb) { + if (ks->include_cb(ks, mode)) { + BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + else { + BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) { + /* entry can be included */ + BLI_dynstr_append(pupds, ks->name); + + /* check if special "shapekey" entry */ + if (ks->flag == -3) + BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") ); + else + BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + + /* convert to normal MEM_malloc'd string */ + str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); + + return str; +} + +/* Get the keying set that was chosen by the user from the menu */ +static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index) +{ + /* check if index is valid */ + if (ELEM(NULL, ksc, ksc->keyingsets)) + return NULL; + if ((index < 1) || (index > ksc->tot)) + return NULL; + + /* index starts from 1, and should directly correspond to keyingset in array */ + return (bKeyingSet *)(ksc->keyingsets + (index - 1)); +} + +/* ---------------- Keyframe Management API -------------------- */ + +/* mode for common_modifykey */ +enum { + COMMONKEY_MODE_INSERT = 0, + COMMONKEY_MODE_DELETE, +} eCommonModifyKey_Modes; + +/* Display a menu for handling the insertion of keyframes based on the active view */ +// TODO: add back an option for repeating last keytype +void common_modifykey (short mode) +{ + ListBase dsources = {NULL, NULL}; + bKeyingContext *ksc= NULL; + bCommonKeySrc *cks; + bKeyingSet *ks = NULL; + char *menustr, buf[64]; + short menu_nr; + + /* check if mode is valid */ + if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0) + return; + + /* delegate to other functions or get keyingsets to use */ + switch (curarea->spacetype) { + /* spaces with their own methods */ + case SPACE_IPO: + if (mode == COMMONKEY_MODE_INSERT) + insertkey_editipo(); + return; + case SPACE_ACTION: + if (mode == COMMONKEY_MODE_INSERT) + insertkey_action(); + return; + + /* TODO: based on UI elements? will that even be handled here??? */ + + /* default - check per view */ + default: + /* get the keyingsets and the data to add keyframes to */ + commonkey_context_get(&dsources, &ksc); + break; + } + + /* check that there is data to operate on */ + if (ELEM(NULL, dsources.first, ksc)) { + BLI_freelistN(&dsources); + return; + } + + /* get menu and process it */ + if (mode == COMMONKEY_MODE_DELETE) + menustr= build_keyingsets_menu(ksc, "Delete"); + else + menustr= build_keyingsets_menu(ksc, "Insert"); + menu_nr= pupmenu(menustr); + if (menustr) MEM_freeN(menustr); + + /* no item selected or shapekey entry? */ + if (menu_nr < 1) { + /* free temp sources */ + BLI_freelistN(&dsources); + + /* check if insert new shapekey */ + if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT)) + insert_shapekey(OBACT); + else + ksc->lastused= NULL; + + return; + } + else { + /* try to get keyingset */ + ks= get_keyingset_fromcontext(ksc, menu_nr); + + if (ks == NULL) { + BLI_freelistN(&dsources); + return; + } + } + + /* loop over each destination, applying the keying set */ + for (cks= dsources.first; cks; cks= cks->next) { + short success= 0; + + /* special hacks for 'available' option */ + if (ks->flag == -2) { + IpoCurve *icu= NULL, *icn= NULL; + + /* get first IPO-curve */ + if (cks->act && cks->actname) { + bActionChannel *achan= get_action_channel(cks->act, cks->actname); + + // FIXME: what about constraint channels? + if (achan && achan->ipo) + icu= achan->ipo->curve.first; + } + else + icu= cks->ipo->curve.first; + + /* we get adrcodes directly from IPO curves (see method below...) */ + for (; icu; icu= icn) { + short flag; + + /* get next ipo-curve in case current is deleted */ + icn= icu->next; + + /* insert mode or delete mode */ + if (mode == COMMONKEY_MODE_DELETE) { + /* local flags only add on to global flags */ + flag = 0; + + /* delete keyframe */ + success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); + } + else { + /* local flags only add on to global flags */ + flag = ks->flag; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframe */ + success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); + } + } + } + else { + int i; + + /* loop over channels available in keyingset */ + for (i=0; i < ks->chan_num; i++) { + short flag, adrcode; + + /* get adrcode + * - certain adrcodes (for MTEX channels need special offsets) // BAD CRUFT!!! + */ + adrcode= ks->adrcodes[i]; + if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) { + switch (adrcode) { + case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z: + case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z: + case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR: + case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP: + adrcode += cks->map; + break; + } + } + + /* insert mode or delete mode */ + if (mode == COMMONKEY_MODE_DELETE) { + /* local flags only add on to global flags */ + flag = 0; + + /* delete keyframe */ + success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); + } + else { + /* local flags only add on to global flags */ + flag = ks->flag; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframe */ + success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); + } + } + } + + /* special handling for some key-sources */ + if (success) { + /* set pose recalc-paths flag */ + if (cks->pchan) { + Object *ob= (Object *)cks->id; + bPoseChannel *pchan= cks->pchan; + + /* set flag to trigger path recalc */ + if (pchan->path) + ob->pose->flag |= POSE_RECALCPATHS; + + /* clear unkeyed flag (it doesn't matter if it's set or not) */ + if (pchan->bone) + pchan->bone->flag &= ~BONE_UNKEYED; + } + } + } + + /* apply post-keying flushes for this data sources */ + commonkey_context_finish(&dsources); + ksc->lastused= ks; + + /* free temp data */ + BLI_freelistN(&dsources); + + /* undo pushes */ + if (mode == COMMONKEY_MODE_DELETE) + BLI_snprintf(buf, 64, "Delete %s Key", ks->name); + else + BLI_snprintf(buf, 64, "Insert %s Key", ks->name); + BIF_undo_push(buf); + + /* queue updates for contexts */ + commonkey_context_refresh(); +} + +/* ---- */ + +/* used to insert keyframes from any view */ +void common_insertkey (void) +{ + common_modifykey(COMMONKEY_MODE_INSERT); +} + +/* used to insert keyframes from any view */ +void common_deletekey (void) +{ + common_modifykey(COMMONKEY_MODE_DELETE); +} + +/* ************************************************** */ diff --git a/source/blender/src/keyval.c b/source/blender/src/keyval.c index dab4b4ae839..5a2ba531821 100644 --- a/source/blender/src/keyval.c +++ b/source/blender/src/keyval.c @@ -27,6 +27,11 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "stdio.h" +#include "ctype.h" +#include "string.h" + +#include "BKE_global.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "BIF_keyval.h" @@ -349,3 +354,193 @@ char *key_event_to_string(unsigned short event) return ""; } + +/* + * Decodes key combination strings [qual1+[qual2+[...]]]keyname + * The '+'s may be replaced by '-' or ' ' characters to support different + * formats. No additional whitespace is allowed. The keyname may be an internal + * name, like "RETKEY", or a more common name, like "Return". Decoding is case- + * insensitive. + * + * Example strings: "Ctrl+L", "ALT-ESC", "Shift A" + * + * Returns 1 if successful. + */ +int decode_key_string(char *str, unsigned short *key, unsigned short *qual) +{ + int i, prev, len, invalid=0; + + len= strlen(str); + *key= *qual= 0; + + /* Convert to upper case */ + for (i=0; i='A' && str[prev]<='Z') { + *key= str[prev]-'A'+AKEY; + } else if (str[prev]>='0' && str[prev]<='9') { + *key= str[prev]-'0'+ZEROKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev, "ZEROKEY", len-prev) || !strncmp(str+prev, "ZERO", len-prev)) { + *key= ZEROKEY; + } else if (!strncmp(str+prev, "ONEKEY", len-prev) || !strncmp(str+prev, "ONE", len-prev)) { + *key= ONEKEY; + } else if (!strncmp(str+prev, "TWOKEY", len-prev) || !strncmp(str+prev, "TWO", len-prev)) { + *key= TWOKEY; + } else if (!strncmp(str+prev, "THREEKEY", len-prev) || !strncmp(str+prev, "THREE", len-prev)) { + *key= THREEKEY; + } else if (!strncmp(str+prev, "FOURKEY", len-prev) || !strncmp(str+prev, "FOUR", len-prev)) { + *key= FOURKEY; + } else if (!strncmp(str+prev, "FIVEKEY", len-prev) || !strncmp(str+prev, "FIVE", len-prev)) { + *key= FIVEKEY; + } else if (!strncmp(str+prev, "SIZEKEY", len-prev) || !strncmp(str+prev, "SIX", len-prev)) { + *key= SIXKEY; + } else if (!strncmp(str+prev, "SEVENKEY", len-prev) || !strncmp(str+prev, "SEVEN", len-prev)) { + *key= SEVENKEY; + } else if (!strncmp(str+prev, "EIGHTKEY", len-prev) || !strncmp(str+prev, "EIGHT", len-prev)) { + *key= EIGHTKEY; + } else if (!strncmp(str+prev, "NINEKEY", len-prev) || !strncmp(str+prev, "NINE", len-prev)) { + *key= NINEKEY; + + } else if (!strncmp(str+prev, "ESCKEY", len-prev) || !strncmp(str+prev, "ESC", len-prev)) { + *key= ESCKEY; + } else if (!strncmp(str+prev, "TABKEY", len-prev) || !strncmp(str+prev, "TAB", len-prev)) { + *key= TABKEY; + } else if (!strncmp(str+prev, "RETKEY", len-prev) || !strncmp(str+prev, "RETURN", len-prev) || !strncmp(str+prev, "ENTER", len-prev)) { + *key= RETKEY; + } else if (!strncmp(str+prev, "SPACEKEY", len-prev) || !strncmp(str+prev, "SPACE", len-prev)) { + *key= SPACEKEY; + } else if (!strncmp(str+prev, "LINEFEEDKEY", len-prev) || !strncmp(str+prev, "LINEFEED", len-prev)) { + *key= LINEFEEDKEY; + } else if (!strncmp(str+prev, "BACKSPACEKEY", len-prev) || !strncmp(str+prev, "BACKSPACE", len-prev)) { + *key= BACKSPACEKEY; + } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { + *key= DELKEY; + + } else if (!strncmp(str+prev, "SEMICOLONKEY", len-prev) || !strncmp(str+prev, "SEMICOLON", len-prev)) { + *key= SEMICOLONKEY; + } else if (!strncmp(str+prev, "PERIODKEY", len-prev) || !strncmp(str+prev, "PERIOD", len-prev)) { + *key= PERIODKEY; + } else if (!strncmp(str+prev, "COMMAKEY", len-prev) || !strncmp(str+prev, "COMMA", len-prev)) { + *key= COMMAKEY; + } else if (!strncmp(str+prev, "QUOTEKEY", len-prev) || !strncmp(str+prev, "QUOTE", len-prev)) { + *key= QUOTEKEY; + } else if (!strncmp(str+prev, "ACCENTGRAVEKEY", len-prev) || !strncmp(str+prev, "ACCENTGRAVE", len-prev)) { + *key= ACCENTGRAVEKEY; + } else if (!strncmp(str+prev, "MINUSKEY", len-prev) || !strncmp(str+prev, "MINUS", len-prev)) { + *key= MINUSKEY; + } else if (!strncmp(str+prev, "SLASHKEY", len-prev) || !strncmp(str+prev, "SLASH", len-prev)) { + *key= SLASHKEY; + } else if (!strncmp(str+prev, "BACKSLASHKEY", len-prev) || !strncmp(str+prev, "BACKSLASH", len-prev)) { + *key= BACKSLASHKEY; + } else if (!strncmp(str+prev, "EQUALKEY", len-prev) || !strncmp(str+prev, "EQUAL", len-prev)) { + *key= EQUALKEY; + } else if (!strncmp(str+prev, "LEFTBRACKETKEY", len-prev) || !strncmp(str+prev, "LEFTBRACKET", len-prev)) { + *key= LEFTBRACKETKEY; + } else if (!strncmp(str+prev, "RIGHTBRACKETKEY", len-prev) || !strncmp(str+prev, "RIGHTBRACKET", len-prev)) { + *key= RIGHTBRACKETKEY; + } else if (!strncmp(str+prev, "DELKEY", len-prev) || !strncmp(str+prev, "DELETE", len-prev)) { + *key= DELKEY; + + } else if (!strncmp(str+prev, "LEFTARROWKEY", len-prev) || !strncmp(str+prev, "LEFTARROW", len-prev)) { + *key= LEFTARROWKEY; + } else if (!strncmp(str+prev, "DOWNARROWKEY", len-prev) || !strncmp(str+prev, "DOWNARROW", len-prev)) { + *key= DOWNARROWKEY; + } else if (!strncmp(str+prev, "RIGHTARROWKEY", len-prev) || !strncmp(str+prev, "RIGHTARROW", len-prev)) { + *key= RIGHTARROWKEY; + } else if (!strncmp(str+prev, "UPARROWKEY", len-prev) || !strncmp(str+prev, "UPARROW", len-prev)) { + *key= UPARROWKEY; + + } else if (!strncmp(str+prev, "PAD", 3)) { + + if (len-prev<=4) { + + if (str[prev]>='0' && str[prev]<='9') { + *key= str[prev]-'0'+ZEROKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev+3, "PERIODKEY", len-prev-3) || !strncmp(str+prev+3, "PERIOD", len-prev-3)) { + *key= PADPERIOD; + } else if (!strncmp(str+prev+3, "SLASHKEY", len-prev-3) || !strncmp(str+prev+3, "SLASH", len-prev-3)) { + *key= PADSLASHKEY; + } else if (!strncmp(str+prev+3, "ASTERKEY", len-prev-3) || !strncmp(str+prev+3, "ASTERISK", len-prev-3)) { + *key= PADASTERKEY; + } else if (!strncmp(str+prev+3, "MINUSKEY", len-prev-3) || !strncmp(str+prev+3, "MINUS", len-prev-3)) { + *key= PADMINUS; + } else if (!strncmp(str+prev+3, "ENTERKEY", len-prev-3) || !strncmp(str+prev+3, "ENTER", len-prev-3)) { + *key= PADENTER; + } else if (!strncmp(str+prev+3, "PLUSKEY", len-prev-3) || !strncmp(str+prev+3, "PLUS", len-prev-3)) { + *key= PADPLUSKEY; + } else { + invalid= 1; + } + + } else if (!strncmp(str+prev, "F1KEY", len-prev) || !strncmp(str+prev, "F1", len-prev)) { + *key= F1KEY; + } else if (!strncmp(str+prev, "F2KEY", len-prev) || !strncmp(str+prev, "F2", len-prev)) { + *key= F2KEY; + } else if (!strncmp(str+prev, "F3KEY", len-prev) || !strncmp(str+prev, "F3", len-prev)) { + *key= F3KEY; + } else if (!strncmp(str+prev, "F4KEY", len-prev) || !strncmp(str+prev, "F4", len-prev)) { + *key= F4KEY; + } else if (!strncmp(str+prev, "F5KEY", len-prev) || !strncmp(str+prev, "F5", len-prev)) { + *key= F5KEY; + } else if (!strncmp(str+prev, "F6KEY", len-prev) || !strncmp(str+prev, "F6", len-prev)) { + *key= F6KEY; + } else if (!strncmp(str+prev, "F7KEY", len-prev) || !strncmp(str+prev, "F7", len-prev)) { + *key= F7KEY; + } else if (!strncmp(str+prev, "F8KEY", len-prev) || !strncmp(str+prev, "F8", len-prev)) { + *key= F8KEY; + } else if (!strncmp(str+prev, "F9KEY", len-prev) || !strncmp(str+prev, "F9", len-prev)) { + *key= F9KEY; + } else if (!strncmp(str+prev, "F10KEY", len-prev) || !strncmp(str+prev, "F10", len-prev)) { + *key= F10KEY; + } else if (!strncmp(str+prev, "F11KEY", len-prev) || !strncmp(str+prev, "F11", len-prev)) { + *key= F11KEY; + } else if (!strncmp(str+prev, "F12KEY", len-prev) || !strncmp(str+prev, "F12", len-prev)) { + *key= F12KEY; + + } else if (!strncmp(str+prev, "PAUSEKEY", len-prev) || !strncmp(str+prev, "PAUSE", len-prev)) { + *key= PAUSEKEY; + } else if (!strncmp(str+prev, "INSERTKEY", len-prev) || !strncmp(str+prev, "INSERT", len-prev)) { + *key= INSERTKEY; + } else if (!strncmp(str+prev, "HOMEKEY", len-prev) || !strncmp(str+prev, "HOME", len-prev)) { + *key= HOMEKEY; + } else if (!strncmp(str+prev, "PAGEUPKEY", len-prev) || !strncmp(str+prev, "PAGEUP", len-prev)) { + *key= PAGEUPKEY; + } else if (!strncmp(str+prev, "PAGEDOWNKEY", len-prev) || !strncmp(str+prev, "PAGEDOWN", len-prev)) { + *key= PAGEDOWNKEY; + } else if (!strncmp(str+prev, "ENDKEY", len-prev) || !strncmp(str+prev, "END", len-prev)) { + *key= ENDKEY; + + } else { + invalid= 1; + } + + if (!invalid && *key) { + return 1; + } + + return 0; +} diff --git a/source/blender/src/meshlaplacian.c b/source/blender/src/meshlaplacian.c index 2de6367c9ad..96349e8fb98 100644 --- a/source/blender/src/meshlaplacian.c +++ b/source/blender/src/meshlaplacian.c @@ -204,7 +204,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int v3= sys->verts[i3]; /* instead of *0.5 we divided by the number of faces of the edge, it still - needs to be varified that this is indeed the correct thing to do! */ + needs to be verified that this is indeed the correct thing to do! */ t1= cotan_weight(v1, v2, v3)/laplacian_edge_count(sys->edgehash, i2, i3); t2= cotan_weight(v2, v3, v1)/laplacian_edge_count(sys->edgehash, i3, i1); t3= cotan_weight(v3, v1, v2)/laplacian_edge_count(sys->edgehash, i1, i2); @@ -229,7 +229,7 @@ static void laplacian_triangle_weights(LaplacianSystem *sys, int f, int i1, int } } -LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) +LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface, int lsq) { LaplacianSystem *sys; @@ -248,6 +248,8 @@ LaplacianSystem *laplacian_system_construct_begin(int totvert, int totface) /* create opennl context */ nlNewContext(); nlSolverParameteri(NL_NB_VARIABLES, totvert); + if(lsq) + nlSolverParameteri(NL_LEAST_SQUARES, NL_TRUE); sys->context= nlGetCurrent(); @@ -631,7 +633,7 @@ void heat_bone_weighting(Object *ob, Mesh *me, float (*verts)[3], int numbones, } /* create laplacian */ - sys = laplacian_system_construct_begin(me->totvert, totface); + sys = laplacian_system_construct_begin(me->totvert, totface, 1); sys->heat.mesh= me; sys->heat.verts= verts; @@ -933,7 +935,7 @@ void rigid_deform_begin(EditMesh *em) } /* create laplacian */ - sys = laplacian_system_construct_begin(totvert, totface); + sys = laplacian_system_construct_begin(totvert, totface, 0); sys->rigid.mesh= em; sys->rigid.R = MEM_callocN(sizeof(float)*3*3*totvert, "RigidDeformR"); diff --git a/source/blender/src/meshtools.c b/source/blender/src/meshtools.c index 99833625baa..eed7737c26d 100644 --- a/source/blender/src/meshtools.c +++ b/source/blender/src/meshtools.c @@ -84,7 +84,6 @@ void sort_faces(void); #include "BIF_toolbox.h" #include "BIF_editconstraint.h" -#include "BDR_drawmesh.h" #include "BDR_editobject.h" #include "BDR_editface.h" #include "BDR_sculptmode.h" @@ -107,6 +106,8 @@ void sort_faces(void); #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" +#include "GPU_draw.h" + #include "BLO_sys_types.h" // for intptr_t support /* from rendercode.c */ @@ -1130,7 +1131,7 @@ void objects_bake_render(short event, char **error_msg) if(ima->ok==IMA_OK_LOADED) { ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); if(ibuf && (ibuf->userflags & IB_BITMAPDIRTY)) { - free_realtime_image(ima); + GPU_free_image(ima); imb_freemipmapImBuf(ibuf); } } diff --git a/source/blender/src/mywindow.c b/source/blender/src/mywindow.c index cb8d233c341..6166ab18766 100644 --- a/source/blender/src/mywindow.c +++ b/source/blender/src/mywindow.c @@ -604,18 +604,6 @@ int framebuffer_to_index(unsigned int col) /* ********** END MY WINDOW ************** */ -#ifdef WIN32 -static int is_a_really_crappy_nvidia_card(void) { - static int well_is_it= -1; - - /* Do you understand the implication? Do you? */ - if (well_is_it==-1) - well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); - - return well_is_it; -} -#endif - void myswapbuffers(void) { ScrArea *sa; diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 3f328a0cfb2..52c5592be38 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -1640,7 +1640,8 @@ static int tree_element_active_ipo(SpaceOops *soops, TreeElement *te, int set) if(chan->ipo) a++; } deselect_actionchannels(ob->action, 0); - select_channel(ob->action, chan, SELECT_ADD); + if (chan) + select_channel(ob->action, chan, SELECT_ADD); allqueue(REDRAWACTION, ob->ipowin); allqueue(REDRAWVIEW3D, ob->ipowin); } diff --git a/source/blender/src/playanim.c b/source/blender/src/playanim.c index 7a61368b4cd..8421101f66c 100644 --- a/source/blender/src/playanim.c +++ b/source/blender/src/playanim.c @@ -45,15 +45,6 @@ #endif #include "MEM_guardedalloc.h" -#ifdef WITH_QUICKTIME -#ifdef _WIN32 -#include -#include -#elif defined(__APPLE__) -#include -#endif /* __APPLE__ */ -#endif /* WITH_QUICKTIME */ - #include "PIL_time.h" #include @@ -77,6 +68,15 @@ #include "BMF_Api.h" +#ifdef WITH_QUICKTIME +#ifdef _WIN32 +#include +#include +#elif defined(__APPLE__) +#include +#endif /* __APPLE__ */ +#endif /* WITH_QUICKTIME */ + #include "playanim_ext.h" #include "mydevice.h" #include "blendef.h" @@ -346,6 +346,7 @@ void playanim(int argc, char **argv) int start_x= 0, start_y= 0; int sfra= -1; int efra= -1; + int totblock; while (argc > 1) { if (argv[1][0] == '-'){ @@ -823,6 +824,7 @@ void playanim(int argc, char **argv) free_blender(); window_destroy(g_window); + totblock= MEM_get_memory_blocks_in_use(); if(totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_printmemlist(); diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 6aeef7c75c2..ff54ad31e22 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -61,7 +61,7 @@ #include "BKE_global.h" #include "BKE_utildefines.h" -//#include "BIF_keyframing.h" +#include "BIF_keyframing.h" #include "BSE_editipo.h" #include "BDR_drawaction.h" diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 28b8729a247..19fb8dc2ecd 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -69,6 +69,7 @@ #include "BIF_gl.h" #include "BIF_graphics.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_space.h" #include "BIF_toolbox.h" @@ -406,6 +407,7 @@ void pose_recalculate_paths(Object *ob) waitcursor(0); CFRA= cfra; + ob->pose->flag &= ~POSE_RECALCPATHS; allqueue(REDRAWVIEW3D, 0); /* recalc tags are still there */ allqueue(REDRAWBUTSEDIT, 0); } diff --git a/source/blender/src/previewrender.c b/source/blender/src/previewrender.c index 0be63197dd1..1730bb890bc 100644 --- a/source/blender/src/previewrender.c +++ b/source/blender/src/previewrender.c @@ -97,6 +97,8 @@ #include "RE_pipeline.h" #include "BLO_readfile.h" +#include "GPU_material.h" + #include "blendef.h" /* CLAMP */ #include "interface.h" /* ui_graphics_to_window(), SOLVE! (ton) */ #include "mydevice.h" @@ -221,6 +223,36 @@ void BIF_preview_changed(short id_code) } } } + + if(ELEM4(id_code, ID_MA, ID_TE, ID_LA, ID_WO)) { + Object *ob; + Material *ma; + + if(id_code == ID_WO) { + for(ma=G.main->mat.first; ma; ma=ma->id.next) { + if(ma->gpumaterial.first) { + GPU_material_free(ma); + allqueue(REDRAWVIEW3D, 0); + } + } + } + else if(id_code == ID_LA) { + for(ob=G.main->object.first; ob; ob=ob->id.next) { + if(ob->gpulamp.first) { + GPU_lamp_free(ob); + allqueue(REDRAWVIEW3D, 0); + } + } + } else if(OBACT) { + Object *ob = OBACT; + + ma= give_current_material(ob, ob->actcol); + if(ma && ma->gpumaterial.first) { + GPU_material_free(ma); + allqueue(REDRAWVIEW3D, 0); + } + } + } } /* *************************** Preview for buttons *********************** */ diff --git a/source/blender/src/renderwin.c b/source/blender/src/renderwin.c index 88f5f6efe15..c26eedd26fd 100644 --- a/source/blender/src/renderwin.c +++ b/source/blender/src/renderwin.c @@ -50,8 +50,6 @@ #endif -#include "BLO_sys_types.h" // for intptr_t support - #include #include "BLI_blenlib.h" @@ -102,6 +100,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_draw.h" + #include "blendef.h" #include "mydevice.h" #include "winlay.h" @@ -676,7 +676,7 @@ static void open_renderwin(int winpos[2], int winsize[2], int imagesize[2]) /* mywindow has to know about it too */ mywindow_build_and_set_renderwin(winpos[0], winpos[1], winsize[0], winsize[1]+RW_HEADERY); /* and we should be able to draw 3d in it */ - init_gl_stuff(); + GPU_state_init(); renderwin_draw(render_win, 1); renderwin_draw(render_win, 1); @@ -903,10 +903,13 @@ static void renderwin_progress_display_cb(RenderResult *rr, volatile rcti *rect) void make_renderinfo_string(RenderStats *rs, char *str) { extern char info_time_str[32]; // header_info.c - extern uintptr_t mem_in_use, mmap_in_use; + uintptr_t mem_in_use, mmap_in_use; float megs_used_memory, mmap_used_memory; char *spos= str; + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + megs_used_memory= (mem_in_use-mmap_in_use)/(1024.0*1024.0); mmap_used_memory= (mmap_in_use)/(1024.0*1024.0); @@ -1271,16 +1274,9 @@ void BIF_store_spare(void) /* set up display, render an image or scene */ void BIF_do_render(int anim) { - int slink_flag = 0; + if (G.f & G_DOSCRIPTLINKS) + BPY_do_all_scripts(SCRIPT_RENDER, anim); - if (G.f & G_DOSCRIPTLINKS) { - BPY_do_all_scripts(SCRIPT_RENDER); - if (!anim) { /* avoid FRAMECHANGED slink in render callback */ - G.f &= ~G_DOSCRIPTLINKS; - slink_flag = 1; - } - } - BIF_store_spare(); do_render(anim); @@ -1291,8 +1287,8 @@ void BIF_do_render(int anim) } if(G.scene->r.dither_intensity != 0.0f) BIF_redraw_render_rect(); - if (slink_flag) G.f |= G_DOSCRIPTLINKS; - if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_POSTRENDER); + + if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_POSTRENDER, anim); } void do_ogl_view3d_render(Render *re, View3D *v3d, int winx, int winy) @@ -1304,10 +1300,10 @@ void do_ogl_view3d_render(Render *re, View3D *v3d, int winx, int winy) if(v3d->persp==V3D_CAMOB && v3d->camera) { /* in camera view, use actual render winmat */ RE_GetCameraWindow(re, v3d->camera, CFRA, winmat); - drawview3d_render(v3d, winx, winy, winmat); + drawview3d_render(v3d, NULL, winx, winy, winmat, 0); } else - drawview3d_render(v3d, winx, winy, NULL); + drawview3d_render(v3d, NULL, winx, winy, NULL, 0); } /* set up display, render the current area view in an image */ @@ -1336,7 +1332,7 @@ void BIF_do_ogl_render(View3D *v3d, int anim) if(render_win) render_win->flags &= ~RW_FLAGS_ESCAPE; - init_gl_stuff(); + GPU_state_init(); waitcursor(1); diff --git a/source/blender/src/resources.c b/source/blender/src/resources.c index acd14aae7a5..1bef10d0415 100644 --- a/source/blender/src/resources.c +++ b/source/blender/src/resources.c @@ -753,6 +753,8 @@ char *BIF_ThemeColorsPup(int spacetype) str += sprintf(str, "Transition Strip %%x%d|", TH_SEQ_TRANSITION); str += sprintf(str, "Meta Strip %%x%d|", TH_SEQ_META); str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); + str += sprintf(str, "Keyframe %%x%d|", TH_VERTEX_SELECT); + str += sprintf(str, "Draw Action %%x%d|", TH_BONE_POSE); break; case SPACE_SOUND: str += sprintf(str, "Grid %%x%d|", TH_GRID); diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 24f4100efdb..31d5ae4610d 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -82,7 +82,6 @@ #include "BIF_space.h" #include "BIF_toolbox.h" -#include "BDR_drawobject.h" #include "BDR_sculptmode.h" #include "BSE_drawview.h" @@ -98,6 +97,8 @@ #include "RE_render_ext.h" #include "RE_shader_ext.h" /*for multitex_ext*/ +#include "GPU_draw.h" + #include #include #include @@ -1514,7 +1515,7 @@ void sculptmode_draw_mesh(int only_damaged) mymultmatrix(OBACT->obmat); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); - init_gl_materials(OBACT, 0); + GPU_set_object_materials(G.scene, OBACT, 0, NULL); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); @@ -1532,7 +1533,7 @@ void sculptmode_draw_mesh(int only_damaged) int new_matnr= f->mat_nr + 1; if(new_matnr != matnr) - drawCurrentMat= set_gl_material(matnr = new_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 */ diff --git a/source/blender/src/seqaudio.c b/source/blender/src/seqaudio.c index 7c27f32c242..2c86ac92c7f 100644 --- a/source/blender/src/seqaudio.c +++ b/source/blender/src/seqaudio.c @@ -27,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ + #include #include #include @@ -118,6 +119,7 @@ void makewavstring (char *string) void audio_mixdown() { +#ifndef DISABLE_SDL int file, c, totlen, totframe, i, oldcfra; char *buf; @@ -203,6 +205,7 @@ void audio_mixdown() MEM_freeN(buf); return; +#endif } void audiostream_fill(Uint8 *mixdown, int len) @@ -211,7 +214,7 @@ void audiostream_fill(Uint8 *mixdown, int len) int i; memset(mixdown, 0, len); - +#ifndef DISABLE_SDL for (i = 0; i < len; i += 64) { CFRA = (int) ( ((float)(audio_pos-64) /( G.scene->audio.mixrate*4 )) @@ -222,6 +225,7 @@ void audiostream_fill(Uint8 *mixdown, int len) } CFRA = oldcfra; +#endif } @@ -288,6 +292,7 @@ void audio_makestream(bSound *sound) } } +#ifndef DISABLE_SDL static void audio_fill_ram_sound(Sequence *seq, void * mixdown, Uint8 * sstream, int len) { @@ -318,7 +323,9 @@ static void audio_fill_ram_sound(Sequence *seq, void * mixdown, } seq->curpos += len; } +#endif +#ifndef DISABLE_SDL static void audio_fill_hd_sound(Sequence *seq, void * mixdown, Uint8 * sstream, int len) @@ -354,7 +361,9 @@ static void audio_fill_hd_sound(Sequence *seq, } seq->curpos += len; } +#endif +#ifndef DISABLE_SDL static void audio_fill_seq(Sequence * seq, void * mixdown, Uint8 *sstream, int len, int advance_only) { @@ -407,7 +416,9 @@ static void audio_fill_seq(Sequence * seq, void * mixdown, seq = seq->next; } } +#endif +#ifndef DISABLE_SDL void audio_fill(void *mixdown, Uint8 *sstream, int len) { Editing *ed; @@ -427,7 +438,9 @@ void audio_fill(void *mixdown, Uint8 *sstream, int len) } } } +#endif +#ifndef DISABLE_SDL static int audio_init(SDL_AudioSpec *desired) { SDL_AudioSpec *obtained, *hardware_spec; @@ -452,6 +465,7 @@ static int audio_init(SDL_AudioSpec *desired) SDL_PauseAudio(0); return 1; } +#endif static int audiostream_play_seq(Sequence * seq, Uint32 startframe) { @@ -498,6 +512,7 @@ static int audiostream_play_seq(Sequence * seq, Uint32 startframe) void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown) { +#ifndef DISABLE_SDL static SDL_AudioSpec desired; Editing *ed; int have_sound = 0; @@ -539,6 +554,7 @@ void audiostream_play(Uint32 startframe, Uint32 duration, int mixdown) SDL_PauseAudio(0); audio_playing++; } +#endif } void audiostream_start(Uint32 frame) @@ -553,8 +569,10 @@ void audiostream_scrub(Uint32 frame) void audiostream_stop(void) { +#ifndef DISABLE_SDL SDL_PauseAudio(1); audio_playing=0; +#endif } int audiostream_pos(void) diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 7e2ffc3ba63..5be11a724f1 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2949,13 +2949,16 @@ void do_render_seq(RenderResult *rr, int cfra) (schlaile) */ { - extern int mem_in_use; - extern int mmap_in_use; + uintptr_t mem_in_use; + uintptr_t mmap_in_use; + uintptr_t max; + + mem_in_use= MEM_get_memory_in_use(); + mmap_in_use= MEM_get_mapped_memory_in_use(); + max = MEM_CacheLimiter_get_maximum(); - int max = MEM_CacheLimiter_get_maximum(); if (max != 0 && mem_in_use + mmap_in_use > max) { - fprintf(stderr, "mem_in_use = %d, max = %d\n", - mem_in_use + mmap_in_use, max); + fprintf(stderr, "Memory in use > maximum memory\n"); fprintf(stderr, "Cleaning up, please wait...\n" "If this happens very often,\n" "consider " diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 8787cf9efc4..fb86620201b 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -182,6 +182,9 @@ #include "SYS_System.h" /* for the user def menu ... should move elsewhere. */ +#include "GPU_extensions.h" +#include "GPU_draw.h" + #include "BLO_sys_types.h" // for intptr_t support /* maybe we need this defined somewhere else */ @@ -386,7 +389,7 @@ void space_set_commmandline_options(void) { SYS_WriteCommandLineInt(syshandle, "noaudio", a); a= (U.gameflags & USER_DISABLE_MIPMAP); - set_mipmap(!a); + GPU_set_mipmap(!a); SYS_WriteCommandLineInt(syshandle, "nomipmap", a); /* File specific settings: */ @@ -415,7 +418,9 @@ void space_set_commmandline_options(void) { a=(G.fileflags & G_FILE_GAME_MAT); SYS_WriteCommandLineInt(syshandle, "blender_material", a); - a=(G.fileflags & G_FILE_DIAPLAY_LISTS); + a=(G.fileflags & G_FILE_GAME_MAT_GLSL); + SYS_WriteCommandLineInt(syshandle, "blender_glsl_material", a); + a=(G.fileflags & G_FILE_DISPLAY_LISTS); SYS_WriteCommandLineInt(syshandle, "displaylists", a); @@ -432,11 +437,10 @@ static void SaveState(void) { glPushAttrib(GL_ALL_ATTRIB_BITS); - init_realtime_GL(); - init_gl_stuff(); + GPU_state_init(); if(G.f & G_TEXTUREPAINT) - texpaint_enable_mipmap(); + GPU_paint_set_mipmap(1); waitcursor(1); } @@ -444,7 +448,7 @@ static void SaveState(void) static void RestoreState(void) { if(G.f & G_TEXTUREPAINT) - texpaint_disable_mipmap(); + GPU_paint_set_mipmap(0); curarea->win_swap = 0; curarea->head_swap=0; @@ -1024,9 +1028,9 @@ void BIF_undo(void) } else { if(G.f & G_TEXTUREPAINT) - imagepaint_undo(); + undo_imagepaint_step(1); else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL)) - imagepaint_undo(); + undo_imagepaint_step(1); else if(G.f & G_PARTICLEEDIT) PE_undo(); else { @@ -1048,9 +1052,9 @@ void BIF_redo(void) } else { if(G.f & G_TEXTUREPAINT) - imagepaint_undo(); + undo_imagepaint_step(-1); else if(curarea->spacetype==SPACE_IMAGE && (G.sima->flag & SI_DRAWTOOL)) - imagepaint_undo(); + undo_imagepaint_step(-1); else if(G.f & G_PARTICLEEDIT) PE_redo(); else { @@ -1906,6 +1910,8 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else copy_attr_menu(); } + else if(G.qual==(LR_ALTKEY|LR_SHIFTKEY)) + gpencil_convert_menu(); /* gpencil.c */ else if(G.qual==LR_ALTKEY) { if(ob && (ob->flag & OB_POSEMODE)) pose_clear_constraints(); /* poseobject.c */ @@ -1964,7 +1970,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) G.vd->drawtype= pupval; doredraw= 1; } - } + } break; case EKEY: @@ -2056,6 +2062,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) if (G.f & (G_VERTEXPAINT|G_WEIGHTPAINT|G_TEXTUREPAINT)){ G.f ^= G_FACESELECT; allqueue(REDRAWVIEW3D, 1); + allqueue(REDRAWBUTSEDIT, 1); } else if(G.f & G_PARTICLEEDIT) { PE_radialcontrol_start(RADIALCONTROL_SIZE); @@ -2211,7 +2218,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else selectswap(); } - else if(G.qual==LR_ALTKEY) { + else if(G.qual==(LR_CTRLKEY|LR_ALTKEY)) { if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE) pose_clear_IK(); } @@ -2641,10 +2648,9 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if(G.f & G_VERTEXPAINT) BIF_undo(); else if(G.f & G_TEXTUREPAINT) - imagepaint_undo(); - else { + undo_imagepaint_step(1); + else single_user(); - } } break; @@ -3097,6 +3103,9 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if (G.qual==LR_CTRLKEY) { borderselect_markers(); } + else if (G.qual==LR_SHIFTKEY) { + do_ipo_buttons(B_IPOBORDER); + } break; case CKEY: if (G.qual == LR_SHIFTKEY) @@ -3257,7 +3266,7 @@ void initipo(ScrArea *sa) /* ******************** SPACE: INFO ********************** */ void space_mipmap_button_function(int event) { - set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); + GPU_set_mipmap(!(U.gameflags & USER_DISABLE_MIPMAP)); allqueue(REDRAWVIEW3D, 0); } @@ -3733,6 +3742,11 @@ void drawinfospace(ScrArea *sa, void *spacedata) "Snap objects and sub-objects to grid units when scaling"); uiBlockEndAlign(block); + uiDefButBitI(block, TOG, USER_ORBIT_ZBUF, B_DRAWINFO, "Auto Depth", + (xpos+edgsp+mpref+spref+(2*midsp)),y2,spref,buth, + &(U.uiflag), 0, 0, 0, 0, + "Use the depth under the mouse to improve view pan/rotate/zoom functionality"); + uiDefButBitI(block, TOG, USER_LOCKAROUND, B_DRAWINFO, "Global Pivot", (xpos+edgsp+mpref+spref+(2*midsp)),y1,spref,buth, &(U.uiflag), 0, 0, 0, 0, @@ -3947,20 +3961,23 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefBut(block, LABEL,0,"Transform:", - (xpos+(2*edgsp)+mpref),y5label, mpref,buth, + (xpos+(2*edgsp)+mpref),y6label, mpref,buth, 0, 0, 0, 0, 0, ""); uiDefButBitI(block, TOG, USER_DRAGIMMEDIATE, B_DRAWINFO, "Drag Immediately", - (xpos+edgsp+mpref+midsp),y4,mpref,buth, + (xpos+edgsp+mpref+midsp),y5,mpref,buth, &(U.flag), 0, 0, 0, 0, "Moving things with a mouse drag doesn't require a click to confirm (Best for tablet users)"); uiBlockEndAlign(block); uiDefBut(block, LABEL,0,"Undo:", - (xpos+(2*edgsp)+mpref),y3label, mpref,buth, + (xpos+(2*edgsp)+mpref),y4label, mpref,buth, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); uiDefButS(block, NUMSLI, B_DRAWINFO, "Steps: ", - (xpos+edgsp+mpref+midsp),y2,mpref,buth, + (xpos+edgsp+mpref+midsp),y3,mpref,buth, &(U.undosteps), 0, 64, 0, 0, "Number of undo steps available (smaller values conserve memory)"); + uiDefButS(block, NUM, B_DRAWINFO, "Memory Limit: ", + (xpos+edgsp+mpref+midsp),y2,mpref,buth, + &(U.undomemory), 0, 32767, -1, 0, "Maximum memory usage in megabytes (0 means unlimited)"); uiDefButBitI(block, TOG, USER_GLOBALUNDO, B_DRAWINFO, "Global Undo", (xpos+edgsp+mpref+midsp),y1,mpref,buth, @@ -4038,6 +4055,19 @@ void drawinfospace(ScrArea *sa, void *spacedata) (xpos+edgsp+(8*midsp)+(3*mpref)+(5*spref)),y1,(spref+edgsp),buth, &(U.dupflag), 0, 0, 0, 0, "Causes ipo data to be duplicated with Shift+D"); uiBlockEndAlign(block); + + uiDefBut(block, LABEL,0,"Grease Pencil:", + (xpos+(2*edgsp)+(3*midsp)+(3*mpref)+spref),y6label,mpref,buth, + 0, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + uiDefButS(block, NUM, 0, "Manhatten Dist:", + (xpos+(4*midsp)+(3*mpref)+mpref),y5,mpref,buth, + &(U.gp_manhattendist), 0, 100, 0, 0, "Pixels moved by mouse per axis when drawing stroke"); + uiDefButS(block, NUM, 0, "Euclidean Dist:", + (xpos+(5*midsp)+(3*mpref)+(2*mpref)),y5,mpref,buth, + &(U.gp_euclideandist), 0, 100, 0, 0, "Distance moved by mouse when drawing stroke (in pixels) to include"); + uiBlockEndAlign(block); } else if(U.userpref == 2) { /* language & colors */ @@ -4295,6 +4325,7 @@ void drawinfospace(ScrArea *sa, void *spacedata) uiDefButI(block, NUM, 0, "Collect Rate ", (xpos+edgsp+(5*mpref)+(5*midsp)), y2, mpref, buth, &U.texcollectrate, 1.0, 3600.0, 30, 2, "Number of seconds between each run of the GL texture garbage collector."); + uiBlockEndAlign(block); /* *** */ uiDefBut(block, LABEL,0,"Color range for weight paint", @@ -4531,7 +4562,7 @@ static void winqreadinfospace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) U.light[0].flag= 1; - default_gl_light(); + GPU_default_lights(); addqueue(sa->win, REDRAW, 1); allqueue(REDRAWVIEW3D, 0); } @@ -5171,8 +5202,8 @@ static void init_seqspace(ScrArea *sa) sseq->v2d.max[0]= MAXFRAMEF; sseq->v2d.max[1]= MAXSEQ; - sseq->v2d.minzoom= 0.1f; - sseq->v2d.maxzoom= 10.0; + sseq->v2d.minzoom= 0.01f; + sseq->v2d.maxzoom= 100.0; sseq->v2d.scroll= L_SCROLL+B_SCROLL; sseq->v2d.keepaspect= 0; @@ -5327,7 +5358,15 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) if(val==0) return; if(uiDoBlocks(&sa->uiblocks, event, 1)!=UI_NOTHING ) event= 0; - + + /* grease-pencil drawing before draw-tool */ + if (event == LEFTMOUSE) { + if (gpencil_do_paint(sa, L_MOUSE)) return; + } + else if (event == RIGHTMOUSE) { + if (gpencil_do_paint(sa, R_MOUSE)) return; + } + if (sima->image && (sima->flag & SI_DRAWTOOL)) { switch(event) { case CKEY: @@ -5350,7 +5389,7 @@ static void winqreadimagespace(ScrArea *sa, void *spacedata, BWinEvent *evt) event = LEFTMOUSE; } } - + /* Draw tool is inactive, editmode is enabled and the image is not a render or composite */ if (EM_texFaceCheck() && (G.sima->image==0 || (G.sima->image->type != IMA_TYPE_R_RESULT && G.sima->image->type != IMA_TYPE_COMPOSITE))) { switch(event) { @@ -5987,7 +6026,7 @@ static void init_oopsspace(ScrArea *sa) soops= MEM_callocN(sizeof(SpaceOops), "initoopsspace"); BLI_addhead(&sa->spacedata, soops); - soops->visiflag= OOPS_OB+OOPS_MA+OOPS_ME+OOPS_TE+OOPS_CU+OOPS_IP; + soops->visiflag= OOPS_OB|OOPS_MA|OOPS_ME|OOPS_TE|OOPS_CU|OOPS_IP; /* new oops is default an outliner */ soops->type= SO_OUTLINER; @@ -6058,6 +6097,10 @@ static void init_textspace(ScrArea *sa) st->lheight= 12; st->showlinenrs= 0; st->tabnumber = 4; + st->showsyntax= 0; + st->doplugins= 0; + st->overwrite= 0; + st->wordwrap= 0; st->currtab_set = 0; st->top= 0; @@ -6327,6 +6370,8 @@ void freespacelist(ScrArea *sa) SpaceImage *sima= (SpaceImage *)sl; if(sima->cumap) curvemapping_free(sima->cumap); + if(sima->gpd) + free_gpencil_data(sima->gpd); } else if(sl->spacetype==SPACE_NODE) { SpaceNode *snode= (SpaceNode *)sl; @@ -6394,6 +6439,10 @@ void duplicatespacelist(ScrArea *newarea, ListBase *lb1, ListBase *lb2) SpaceSeq *sseq= (SpaceSeq *)sl; sseq->gpd= gpencil_data_duplicate(sseq->gpd); } + else if(sl->spacetype==SPACE_IMAGE) { + SpaceImage *sima= (SpaceImage *)sl; + sima->gpd= gpencil_data_duplicate(sima->gpd); + } sl= sl->next; } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 5f80f14d069..df0a2921578 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -75,6 +75,7 @@ #include "BIF_imasel.h" #include "BIF_editparticle.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" #include "BIF_renderwin.h" @@ -104,6 +105,8 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "GPU_draw.h" + #include "mydevice.h" #include "transform.h" @@ -790,6 +793,10 @@ int blenderqread(unsigned short event, short val) ob= OBACT; if(G.f & G_SCULPTMODE) return 1; + else if(G.qual==LR_ALTKEY) { + common_deletekey(); + return 0; + } else if(G.qual==0) { common_insertkey(); return 0; @@ -964,7 +971,7 @@ int blenderqread(unsigned short event, short val) /* Reset lights * This isn't done when reading userdef, do it now * */ - default_gl_light(); + GPU_default_lights(); } return 0; } diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index c8a20cdc951..f38affde418 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -93,6 +93,7 @@ #include "BIF_graphics.h" #include "BIF_imasel.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" #include "BIF_renderwin.h" @@ -2282,7 +2283,7 @@ void toolbox_generic( TBitem *generic_menu ) uiBlock *block; uiBut *but; TBitem *menu; - int dx=96; + int dx=96, first=1, len; short event, mval[2]; intptr_t ypos = -5; @@ -2303,11 +2304,17 @@ void toolbox_generic( TBitem *generic_menu ) /* Add the menu */ for (menu = generic_menu; menu->icon != -1; menu++) { - if(strcmp(menu->name, "SEPR")==0) { + if (first && (len=strlen(menu->name)) > 2 && menu->name[len-2]=='%' && menu->name[len-1]=='t') { + menu->name[len-2] = '\0'; + uiSetCurFont(block, UI_HELVB); + uiDefIconTextBut(block, LABEL, 0, ICON_BLANK1, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, NULL, 0.0, 0.0, 0, 0, ""); + uiSetCurFont(block, UI_HELV); + ypos-=20; + } else if(strcmp(menu->name, "SEPR")==0) { uiDefBut(block, SEPR, 0, "", mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 6, NULL, 0.0, 0.0, 0, 0, ""); ypos-=6; } else { - if (menu->poin) { + if (menu->poin) { but=uiDefIconTextBlockBut(block, tb_makemenu, menu->poin, ICON_RIGHTARROW_THIN, menu->name, mval[0]+tb_mainx,mval[1]+tb_mainy+ypos+5, dx, 19, ""); uiButSetFlag(but, UI_MAKE_RIGHT); @@ -2318,6 +2325,7 @@ void toolbox_generic( TBitem *generic_menu ) } ypos-=20; } + first= 0; } uiBlockSetButmFunc(block, menu->poin, NULL); diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index efb86b59ed1..210a81927c8 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -108,6 +108,7 @@ #include "BIF_editsima.h" #include "BIF_editparticle.h" #include "BIF_gl.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" @@ -3562,22 +3563,25 @@ short autokeyframe_cfra_can_key(Object *ob) */ void autokeyframe_ob_cb_func(Object *ob, int tmode) { + ID *id= (ID *)(ob); IpoCurve *icu; if (autokeyframe_cfra_can_key(ob)) { char *actname = NULL; + short flag = 0; if (ob->ipoflag & OB_ACTION_OB) actname= "Object"; + + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { + /* only key on available channels */ if ((ob->ipo) || (ob->action)) { - ID *id= (ID *)(ob); - - if (ob->ipo) { - icu= ob->ipo->curve.first; - } - else { + if (ob->action && actname) { bActionChannel *achan; achan= get_action_channel(ob->action, actname); @@ -3586,19 +3590,16 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) else icu= NULL; } + else + icu= ob->ipo->curve.first; - while (icu) { + for (; icu; icu= icu->next) { icu->flag &= ~IPO_SELECT; - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); - else - insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); - icu= icu->next; + insertkey(id, ID_OB, actname, NULL, icu->adrcode, flag); } } } else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) { - ID *id= (ID *)(ob); short doLoc=0, doRot=0, doScale=0; /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ @@ -3629,35 +3630,33 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) } if (doLoc) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Z); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); } if (doRot) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Z); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); } if (doScale) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Z); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); } } else { - ID *id= (ID *)(ob); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); - - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); } remake_object_ipos(ob); @@ -3683,8 +3682,15 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) act= ob->action; if (autokeyframe_cfra_can_key(ob)) { + short flag= 0; + if (act == NULL) act= ob->action= add_empty_action("Action"); + + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { if (pchan->bone->flag & BONE_TRANSFORM) { @@ -3695,17 +3701,10 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { bActionChannel *achan; - for (achan = act->chanbase.first; achan; achan=achan->next) { - if ((achan->ipo) && !strcmp(achan->name, pchan->name)) { - for (icu = achan->ipo->curve.first; icu; icu=icu->next) { - /* only insert keyframe if needed? */ - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); - else - insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0); - } - break; - } + achan= get_action_channel(act, pchan->name); + if (achan && achan->ipo) { + for (icu= achan->ipo->curve.first; icu; icu= icu->next) + insertkey(id, ID_PO, pchan->name, NULL, icu->adrcode, flag); } } /* only insert keyframe if needed? */ @@ -3735,36 +3734,36 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } if (doLoc) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); } if (doRot) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); } if (doScale) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); } } /* insert keyframe in any channel that's appropriate */ else { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); } } } @@ -3913,13 +3912,10 @@ void special_aftertrans_update(TransInfo *t) if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 && (cancelled == 0) ) { - if (NLA_IPO_SCALED) { - actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 1); - posttrans_ipo_clean(G.sipo->ipo); - actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 1); - } - else - posttrans_ipo_clean(G.sipo->ipo); + /* NOTE: no need to do NLA scaling stuff here, as when there is NLA scaling, + * the transformed handles will get moved wrong (seem to match wrong repeat cycle) + */ + posttrans_ipo_clean(G.sipo->ipo); } } diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index 656fca3cad8..a1440b8cbce 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -583,39 +583,6 @@ void recalcData(TransInfo *t) reshadeall_displist(); } -void initTransModeFlags(TransInfo *t, int mode) -{ - t->mode = mode; - t->num.flag = 0; - - /* REMOVING RESTRICTIONS FLAGS */ - t->flag &= ~T_ALL_RESTRICTIONS; - - switch (mode) { - case TFM_RESIZE: - t->flag |= T_NULL_ONE; - t->num.flag |= NUM_NULL_ONE; - t->num.flag |= NUM_AFFECT_ALL; - if (!G.obedit) { - t->flag |= T_NO_ZERO; - t->num.flag |= NUM_NO_ZERO; - } - break; - case TFM_TOSPHERE: - t->num.flag |= NUM_NULL_ONE; - t->num.flag |= NUM_NO_NEGATIVE; - t->flag |= T_NO_CONSTRAINT; - break; - case TFM_SHEAR: - case TFM_CREASE: - case TFM_BONE_ENVELOPE: - case TFM_CURVE_SHRINKFATTEN: - case TFM_BONE_ROLL: - t->flag |= T_NO_CONSTRAINT; - break; - } -} - void drawLine(float *center, float *dir, char axis, short options) { extern void make_axis_color(char *col, char *col2, char axis); // drawview.c @@ -674,19 +641,10 @@ void initTrans (TransInfo *t) t->transform = NULL; t->handleEvent = NULL; - t->total = - t->num.idx = - t->num.idx_max = - t->num.ctrl[0] = - t->num.ctrl[1] = - t->num.ctrl[2] = 0; + t->total = 0; t->val = 0.0f; - t->num.val[0] = - t->num.val[1] = - t->num.val[2] = 0.0f; - t->vec[0] = t->vec[1] = t->vec[2] = 0.0f; @@ -708,7 +666,8 @@ void initTrans (TransInfo *t) t->around = V3D_CENTER; setTransformViewMatrices(t); - initNDofInput(&(t->ndof)); + initNumInput(&t->num); + initNDofInput(&t->ndof); } /* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */ diff --git a/source/blender/src/transform_numinput.c b/source/blender/src/transform_numinput.c index 9b811595a9a..89a76c097e0 100644 --- a/source/blender/src/transform_numinput.c +++ b/source/blender/src/transform_numinput.c @@ -41,6 +41,20 @@ /* ************************** NUMINPUT **************************** */ +void initNumInput(NumInput *n) +{ + n->flag = + n->idx = + n->idx_max = + n->ctrl[0] = + n->ctrl[1] = + n->ctrl[2] = 0; + + n->val[0] = + n->val[1] = + n->val[2] = 0.0f; +} + void outputNumInput(NumInput *n, char *str) { char cur; diff --git a/source/blender/src/transform_orientations.c b/source/blender/src/transform_orientations.c index 9c7a2f67b89..fc9dfbb902e 100644 --- a/source/blender/src/transform_orientations.c +++ b/source/blender/src/transform_orientations.c @@ -352,7 +352,7 @@ char * BIF_menustringTransformOrientation(char *title) { char *str_menu, *p; - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); + str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + 40 * BIF_countTransformOrientation(), "UserTransSpace from matrix"); p = str_menu; p += sprintf(str_menu, "%s", title); diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 3c17d0c1da8..8c5e1f85a3d 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -1173,7 +1173,7 @@ int snapObjects(int *dist, float *loc, float *no, int mode) { base= FIRSTBASE; for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( BASE_SELECTABLE(base) && ((mode == NOT_SELECTED && (base->flag & SELECT) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { + if ( BASE_SELECTABLE(base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { Object *ob = base->object; if (ob->transflag & OB_DUPLI) diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index 15c2664a9d8..88cdc558f2b 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -34,8 +34,6 @@ #include #include -#include "GL/glew.h" - #ifdef WIN32 #include /* need to include windows.h so _WIN32_IE is defined */ #ifndef _WIN32_IE @@ -69,6 +67,7 @@ #include "DNA_sound_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_text_types.h" #include "BKE_blender.h" #include "BKE_curve.h" @@ -81,6 +80,7 @@ #include "BKE_mball.h" #include "BKE_node.h" #include "BKE_packedFile.h" +#include "BKE_suggestions.h" #include "BKE_texture.h" #include "BKE_utildefines.h" #include "BKE_pointcache.h" @@ -147,6 +147,9 @@ #include "PIL_time.h" +#include "GPU_extensions.h" +#include "GPU_draw.h" + /***/ /* define for setting colors in theme below */ @@ -477,13 +480,31 @@ static void init_userdef_file(void) if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 16)) { U.flag |= USER_ADD_VIEWALIGNED|USER_ADD_EDITMODE; } - if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile < 1)) { + if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile <= 2)) { bTheme *btheme; - for(btheme= U.themes.first; btheme; btheme= btheme->next) { - SETCOL(btheme->tipo.handle_vertex, 0xff, 0x70, 0xff, 255); - SETCOL(btheme->tipo.handle_vertex_select, 0xff, 0xff, 0x70, 255); - btheme->tipo.handle_vertex_size= 3; + + /* adjust themes */ + for (btheme= U.themes.first; btheme; btheme= btheme->next) { + char *col; + + /* IPO Editor: Handles/Vertices */ + col = btheme->tipo.vertex; + SETCOL(btheme->tipo.handle_vertex, col[0], col[1], col[2], 255); + col = btheme->tipo.vertex_select; + SETCOL(btheme->tipo.handle_vertex_select, col[0], col[1], col[2], 255); + btheme->tipo.handle_vertex_size= btheme->tipo.vertex_size; + + /* Sequence/Image Editor: colors for GPencil text */ + col = btheme->tv3d.bone_pose; + SETCOL(btheme->tseq.bone_pose, col[0], col[1], col[2], 255); + SETCOL(btheme->tima.bone_pose, col[0], col[1], col[2], 255); + col = btheme->tv3d.vertex_select; + SETCOL(btheme->tseq.vertex_select, col[0], col[1], col[2], 255); } + + /* define grease-pencil distances */ + U.gp_manhattendist= 3; + U.gp_euclideandist= 20; } /* GL Texture Garbage Collection (variable abused above!) */ @@ -575,8 +596,9 @@ void BIF_read_file(char *name) if (retval!=0) G.relbase_valid = 1; undo_editmode_clear(); + undo_imagepaint_clear(); BKE_reset_undo(); - BKE_write_undo("original"); /* save current state */ + BKE_write_undo("Original"); /* save current state */ refresh_interface_font(); } @@ -648,8 +670,9 @@ int BIF_read_homefile(int from_memory) init_userdef_file(); undo_editmode_clear(); + undo_imagepaint_clear(); BKE_reset_undo(); - BKE_write_undo("original"); /* save current state */ + BKE_write_undo("Original"); /* save current state */ /* if from memory, need to refresh python scripts */ if (from_memory) { @@ -1047,8 +1070,9 @@ void BIF_init(void) BIF_filelist_init_icons(); - init_gl_stuff(); /* drawview.c, after homefile */ - glewInit(); + GPU_state_init(); + GPU_extensions_init(); + readBlog(); BLI_strncpy(G.lib, G.sce, FILE_MAX); } @@ -1061,6 +1085,7 @@ extern ListBase editelems; void exit_usiblender(void) { struct TmpFont *tf; + int totblock; BIF_clear_tempfiles(); @@ -1106,7 +1131,7 @@ void exit_usiblender(void) free_ipocopybuf(); free_actcopybuf(); free_vertexpaint(); - free_imagepaint(); + free_texttools(); /* editnurb can remain to exist outside editmode */ freeNurblist(&editNurb); @@ -1124,6 +1149,7 @@ void exit_usiblender(void) sound_exit_audio(); if(G.listener) MEM_freeN(G.listener); + GPU_extensions_exit(); libtiff_exit(); @@ -1133,6 +1159,7 @@ void exit_usiblender(void) /* undo free stuff */ undo_editmode_clear(); + undo_imagepaint_clear(); BKE_undo_save_quit(); // saves quit.blend if global undo is on BKE_reset_undo(); @@ -1158,6 +1185,7 @@ void exit_usiblender(void) BLI_freelistN(&U.themes); BIF_preview_free_dbase(); + totblock= MEM_get_memory_blocks_in_use(); if(totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_printmemlist(); diff --git a/source/blender/src/verse_image.c b/source/blender/src/verse_image.c index fe9e6137091..edb3a0a9f2c 100644 --- a/source/blender/src/verse_image.c +++ b/source/blender/src/verse_image.c @@ -43,6 +43,8 @@ #include "BIF_verse.h" #include "BIF_space.h" +#include "GPU_draw.h" + /* * unsubscribe from verse bitmap */ @@ -327,7 +329,7 @@ void post_bitmap_tile_set(VBitmapLayer *vblayer, unsigned int xs, unsigned int y rect[channel] = (char)vuint8[i]; } - free_realtime_image(image); + GPU_free_image(image); /* redraw preview of image ... uncommented, because rendering * was computed too often */ diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 12450bee9de..4c56e5ce64e 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -793,6 +793,82 @@ void viewmoveNDOFfly(int mode) BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); } +int view_autodist( float mouse_worldloc[3] ) //, float *autodist ) +{ + View3D *v3d = G.vd; + + /* Zooms in on a border drawn by the user */ + short mval[2]; + rcti rect; + + /* ZBuffer depth vars */ + bglMats mats; + float depth, depth_close= MAXFLOAT; + int had_depth = 0; + double cent[2], p[3]; + int xs, ys; + + getmouseco_areawin(mval); + + persp(PERSP_VIEW); + + rect.xmax = mval[0] + 4; + rect.ymax = mval[1] + 4; + + rect.xmin = mval[0] - 4; + rect.ymin = mval[1] - 4; + + /* Get Z Depths, needed for perspective, nice for ortho */ + bgl_get_mats(&mats); + draw_depth(curarea, (void *)v3d, NULL); + + /* force updating */ + if (v3d->depths) { + had_depth = 1; + v3d->depths->damaged = 1; + } + + view3d_update_depths(v3d); + + /* Constrain rect to depth bounds */ + if (rect.xmin < 0) rect.xmin = 0; + if (rect.ymin < 0) rect.ymin = 0; + if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1; + if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1; + + /* Find the closest Z pixel */ + for (xs=rect.xmin; xs < rect.xmax; xs++) { + for (ys=rect.ymin; ys < rect.ymax; ys++) { + depth= v3d->depths->depths[ys*v3d->depths->w+xs]; + if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) { + if (depth_close > depth) { + depth_close = depth; + } + } + } + } + + if (depth_close==MAXFLOAT) + return 0; + + if (had_depth==0) { + MEM_freeN(v3d->depths->depths); + v3d->depths->depths = NULL; + } + v3d->depths->damaged = 1; + + cent[0] = (double)mval[0]; + cent[1] = (double)mval[1]; + + if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, mats.viewport, &p[0], &p[1], &p[2])) + return 0; + + mouse_worldloc[0] = (float)p[0]; + mouse_worldloc[1] = (float)p[1]; + mouse_worldloc[2] = (float)p[2]; + return 1; +} + void viewmove(int mode) { static float lastofs[3] = {0,0,0}; @@ -825,15 +901,11 @@ void viewmove(int mode) Mat3MulVecfl(mat, upvec); VecAddf(G.vd->ofs, G.vd->ofs, upvec); } - - /* sometimes this routine is called from headerbuttons */ areawinset(curarea->win); - initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); - QUATCOPY(oldquat, G.vd->viewquat); getmouseco_areawin(mval_area); /* for zoom to mouse loc */ @@ -867,9 +939,44 @@ void viewmove(int mode) VECCOPY(obofs, lastofs); VecMulf(obofs, -1.0f); } + else if (U.uiflag & USER_ORBIT_ZBUF) { + if ((use_sel=view_autodist(obofs))) { + if (G.vd->persp==V3D_PERSP) { + float my_origin[3]; /* original G.vd->ofs */ + float my_pivot[3]; /* view */ + + VECCOPY(my_origin, G.vd->ofs); + VecMulf(my_origin, -1.0f); /* ofs is flipped */ + + /* Set the dist value to be the distance from this 3d point */ + /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */ + + /* remove dist value */ + upvec[0] = upvec[1] = 0; + upvec[2] = G.vd->dist; + Mat3CpyMat4(mat, G.vd->viewinv); + Mat3MulVecfl(mat, upvec); + VecSubf(my_pivot, G.vd->ofs, upvec); + VecMulf(my_pivot, -1.0f); /* ofs is flipped */ + + /* find a new ofs value that is allong the view axis (rather then the mouse location) */ + lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec); + dist0 = G.vd->dist = VecLenf(my_pivot, dvec); + + VecMulf(dvec, -1.0f); + VECCOPY(G.vd->ofs, dvec); + } + VecMulf(obofs, -1.0f); + VECCOPY(ofs, G.vd->ofs); + } else { + ofs[0] = ofs[1] = ofs[2] = 0.0f; + } + } else ofs[0] = ofs[1] = ofs[2] = 0.0f; - + + initgrabz(-G.vd->ofs[0], -G.vd->ofs[1], -G.vd->ofs[2]); + reverse= 1.0f; if (G.vd->persmat[2][1] < 0.0f) reverse= -1.0f; @@ -1046,9 +1153,20 @@ void viewmove(int mode) zfac*G.vd->dist < 10.0*G.vd->far) view_zoom_mouseloc(zfac, mval_area); - /* these limits are in toets.c too */ - if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; - if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; + + if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (G.vd->persp==V3D_PERSP)) { + /* Secret apricot feature, translate the view when in continues mode */ + upvec[0] = upvec[1] = 0; + upvec[2] = (dist0 - G.vd->dist) * G.vd->grid; + G.vd->dist = dist0; + Mat3CpyMat4(mat, G.vd->viewinv); + Mat3MulVecfl(mat, upvec); + VecAddf(G.vd->ofs, G.vd->ofs, upvec); + } else { + /* these limits are in toets.c too */ + if(G.vd->dist<0.001*G.vd->grid) G.vd->dist= 0.001*G.vd->grid; + if(G.vd->dist>10.0*G.vd->far) G.vd->dist=10.0*G.vd->far; + } if(G.vd->persp==V3D_ORTHO || G.vd->persp==V3D_CAMOB) preview3d_event= 0; } @@ -2353,3 +2471,4 @@ void smooth_view_to_camera(View3D *v3d) v3d->persp= V3D_CAMOB; } } + diff --git a/source/blender/yafray/intern/export_File.cpp b/source/blender/yafray/intern/export_File.cpp index f8bbdad5f65..f42e00daf6d 100644 --- a/source/blender/yafray/intern/export_File.cpp +++ b/source/blender/yafray/intern/export_File.cpp @@ -881,7 +881,7 @@ void yafrayFileRender_t::writeShader(const string &shader_name, Material* matr, ostr << "\t\t\n"; // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[9] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen"}; + const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; ostr << "\t\tblendtype] << "\" />\n"; // texture color (for use with MUL and/or no_rgb etc..) diff --git a/source/blender/yafray/intern/export_Plugin.cpp b/source/blender/yafray/intern/export_Plugin.cpp index 77d53c4ed96..a7d5653892f 100644 --- a/source/blender/yafray/intern/export_Plugin.cpp +++ b/source/blender/yafray/intern/export_Plugin.cpp @@ -782,7 +782,7 @@ void yafrayPluginRender_t::writeShader(const string &shader_name, Material* matr mparams["input"] = yafray::parameter_t(shader_name + temp); // blendtype, would have been nice if the order would have been the same as for ramps... - const string blendtype[9] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen"}; + const string blendtype[MTEX_NUM_BLENDTYPES] = {"mix", "mul", "add", "sub", "divide", "darken", "difference", "lighten", "screen", "hue", "sat", "val", "color"}; mparams["mode"] = yafray::parameter_t(blendtype[(int)mtex->blendtype]); // texture color (for use with MUL and/or no_rgb etc..) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index d17b94c631d..93cc0e8afb5 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -37,8 +37,10 @@ INCLUDE_DIRECTORIES(../../intern/guardedalloc ../blender/render/extern/include ../blender/python ../blender/makesdna + ../blender/gpu ../kernel/gen_messaging ../kernel/gen_system + ../../extern/glew/include ) @@ -189,7 +191,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} src blender_python blender_render blender_radiosity blender_IK bf_elbeem) +SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} src blender_python blender_render blender_radiosity bf_elbeem) IF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(BLENDER_LINK_LIBS ${BLENDER_LINK_LIBS} extern_binreloc) @@ -210,6 +212,7 @@ IF(UNIX) blender_python bf_blenkernel bf_nodes + bf_gpu bf_blenloader bf_blenpluginapi bf_imbuf @@ -223,7 +226,7 @@ IF(UNIX) bf_decimation bf_elbeem bf_yafray - blender_IK + bf_IK bf_memutil bf_guardedalloc blender_CTR diff --git a/source/creator/Makefile b/source/creator/Makefile index 8a0d20264ea..158aee1a647 100644 --- a/source/creator/Makefile +++ b/source/creator/Makefile @@ -49,9 +49,11 @@ CPPFLAGS += -I../blender/renderconverter CPPFLAGS += -I../blender/blenkernel CPPFLAGS += -I../blender/python CPPFLAGS += -I../blender/blenloader +CPPFLAGS += -I../blender/gpu CPPFLAGS += -I../kernel/gen_system CPPFLAGS += -I../kernel/gen_messaging CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_GLEW)/include ifeq ($(WITH_QUICKTIME), true) CPPFLAGS += -I$(NAN_QUICKTIME)/include -DWITH_QUICKTIME diff --git a/source/creator/SConscript b/source/creator/SConscript index cac9e895a97..a4c218f89d6 100644 --- a/source/creator/SConscript +++ b/source/creator/SConscript @@ -7,7 +7,7 @@ incs = '#/intern/guardedalloc ../blender/blenlib ../blender/blenkernel' incs += ' ../blender/include ../blender/blenloader ../blender/imbuf' incs += ' ../blender/renderconverter ../blender/render/extern/include' incs += ' ../blender/python ../blender/makesdna ../kernel/gen_messaging' -incs += ' ../kernel/gen_system' +incs += ' ../kernel/gen_system #/extern/glew/include ../blender/gpu' incs += ' ' + env['BF_OPENGL_INC'] defs = [] diff --git a/source/creator/creator.c b/source/creator/creator.c index e17b0f66977..ac81557110f 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -70,14 +70,14 @@ #include "BLO_writefile.h" #include "BLO_readfile.h" -#include "BDR_drawmesh.h" - #include "IMB_imbuf.h" // for quicktime_init #include "BPY_extern.h" #include "RE_pipeline.h" +#include "GPU_draw.h" + #include "playanim_ext.h" #include "mydevice.h" #include "nla.h" @@ -267,7 +267,7 @@ static void main_init_screen( void ) int main(int argc, char **argv) { - int a, i, stax=0, stay=0, sizx, sizy, scr_init = 0; + int a, i, stax, stay, sizx, sizy, scr_init = 0; SYS_SystemHandle syshandle; #if defined(WIN32) || defined (__linux__) @@ -301,10 +301,10 @@ int main(int argc, char **argv) setprefsize(left +10,scr_y - bottom +10,right-left -20,bottom - 64, 0); } else { - winlay_get_screensize(&scr_x, &scr_y); + winlay_get_screensize(&scr_x, &scr_y); - /* 40 + 684 + (headers) 22 + 22 = 768, the powerbook screen height */ - setprefsize(120, 40, 850, 684, 0); + /* 40 + 684 + (headers) 22 + 22 = 768, the powerbook screen height */ + setprefsize(120, 40, 850, 684, 0); } winlay_process_events(0); @@ -430,11 +430,11 @@ int main(int argc, char **argv) init_def_material(); - winlay_get_screensize(&sizx, &sizy); - stax=0; - stay=0; - if(G.background==0) { + winlay_get_screensize(&sizx, &sizy); + stax=0; + stay=0; + for(a=1; aid.name); - if (G.f & G_DOSCRIPTLINKS) { - BPY_do_all_scripts(SCRIPT_RENDER); - /* avoid FRAMECHANGED slink event - * (should only be triggered in anims): */ - G.f &= ~G_DOSCRIPTLINKS; - slink_flag= 1; - } + if (G.f & G_DOSCRIPTLINKS) + BPY_do_all_scripts(SCRIPT_RENDER, 0); RE_BlenderAnim(re, G.scene, frame, frame); - if (slink_flag) { - G.f |= G_DOSCRIPTLINKS; - BPY_do_all_scripts(SCRIPT_POSTRENDER); - } + BPY_do_all_scripts(SCRIPT_POSTRENDER, 0); } } else { printf("\nError: no blend loaded. cannot use '-f'.\n"); @@ -645,12 +636,12 @@ int main(int argc, char **argv) Render *re= RE_NewRender(G.scene->id.name); if (G.f & G_DOSCRIPTLINKS) - BPY_do_all_scripts(SCRIPT_RENDER); + BPY_do_all_scripts(SCRIPT_RENDER, 1); RE_BlenderAnim(re, G.scene, G.scene->r.sfra, G.scene->r.efra); if (G.f & G_DOSCRIPTLINKS) - BPY_do_all_scripts(SCRIPT_POSTRENDER); + BPY_do_all_scripts(SCRIPT_POSTRENDER, 1); } else { printf("\nError: no blend loaded. cannot use '-a'.\n"); } @@ -772,44 +763,10 @@ int main(int argc, char **argv) else { /* Make the path absolute because its needed for relative linked blends to be found */ - int abs = 0; - int filelen; - char cwd[FILE_MAXDIR + FILE_MAXFILE]; char filename[FILE_MAXDIR + FILE_MAXFILE]; - cwd[0] = filename[0] = '\0'; BLI_strncpy(filename, argv[a], sizeof(filename)); - filelen = strlen(filename); - - /* relative path checks, could do more tests here... */ -#ifdef WIN32 - /* Account for X:/ and X:\ - should be enough */ - if (filelen >= 3 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/')) - abs = 1; -#else - if (filelen >= 2 && filename[0] == '/') - abs = 1 ; -#endif - if (!abs) { - BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ - - if (cwd[0] == '\0') { - printf( - "Could not get the current working directory - $PWD for an unknown reason.\n\t" - "Relative linked files will not load if the entire blend path is not used.\n\t" - "The 'Play' button may also fail.\n" - ); - } else { - /* uses the blend path relative to cwd important for loading relative linked files. - * - * cwd should contain c:\ etc on win32 so the relbase can be NULL - * relbase being NULL also prevents // being misunderstood as relative to the current - * blend file which isnt a feature we want to use in this case since were dealing - * with a path from the command line, rather then from inside Blender */ - - BLI_make_file_string(NULL, filename, cwd, argv[a]); - } - } + BLI_convertstringcwd(filename); if (G.background) { int retval = BKE_read_file(filename, NULL); diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 16f8ae0095a..74fe6c68863 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -79,6 +79,8 @@ #include "DNA_scene_types.h" /***/ +#include "GPU_extensions.h" + #ifdef __cplusplus extern "C" { #endif @@ -136,7 +138,12 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool usemat = false, useglslmat = false; if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) - usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0); + usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); + + if(GPU_extensions_minimum_support()) + useglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); + else if(G.fileflags & G_FILE_GAME_MAT_GLSL) + usemat = false; // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -191,6 +198,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, // some blender stuff MT_CmMatrix4x4 projmat; MT_CmMatrix4x4 viewmat; + float camzoom; int i; for (i = 0; i < 16; i++) @@ -204,8 +212,13 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, projmat.setElem(i, projmat_linear[i]); } - float camzoom = (1.41421 + (v3d->camzoom / 50.0)); - camzoom *= camzoom; + if(v3d->persp==V3D_CAMOB) { + camzoom = (1.41421 + (v3d->camzoom / 50.0)); + camzoom *= camzoom; + } + else + camzoom = 2.0; + camzoom = 4.0 / camzoom; ketsjiengine->SetDrawType(v3d->drawtype); @@ -286,6 +299,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(projmat); ketsjiengine->SetCameraOverrideViewMatrix(viewmat); + ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } // create a scene converter, create and convert the startingscene @@ -294,23 +308,24 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); - - if(usemat) + + if(usemat && (G.fileflags & G_FILE_GAME_MAT)) sceneconverter->SetMaterials(true); - if(useglslmat) + if(useglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(keyboarddevice, mousedevice, networkdevice, audiodevice, - startscenename); + startscenename, + blscene); // some python things PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest); ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module. PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. initGameKeys(); @@ -526,8 +541,6 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, // create the ketsjiengine KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem); - int i; - Scene *blscene = NULL; if (!bfd) { @@ -543,7 +556,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, } else { blscene = bfd->curscene; } - int cframe,startFrame; + int cframe = 1, startFrame; if (blscene) { cframe=blscene->r.cfra; @@ -574,12 +587,14 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, mousedevice, networkdevice, audiodevice, - startscenename); + startscenename, + blscene); + // some python things PyObject* dictionaryobject = initGamePythonScripting("Ketsji", psl_Lowest); ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 1d72fb9cde1..340a1ae310b 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -31,6 +31,7 @@ SET(INC ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader + ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ../../../extern/glew/include diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index da52be56d1b..669e7bd1b3f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -26,7 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "GL/glew.h" #include "KX_BlenderGL.h" #ifdef HAVE_CONFIG_H @@ -93,80 +92,6 @@ void BL_SwapBuffers() myswapbuffers(); } -void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface, - unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]) -{ - Image* ima; - - if(mode & TF_BMFONT) { - //char string[MAX_PROPSTRING]; - int characters, index, character; - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - -// bProperty *prop; - - // string = "Frank van Beek"; - - characters = textlen; - - ima = (struct Image*) tface->tpage; - if (ima == NULL) { - characters = 0; - } - - /* When OBCOL flag is on the color is set in IndexPrimitives_3DText */ - if (tface->mode & TF_OBCOL) { /* Color has been set */ - col= NULL; - } else { - if(!col) glColor3f(1.0f, 1.0f, 1.0f); - } - - glPushMatrix(); - for (index = 0; index < characters; index++) { - // lets calculate offset stuff - character = textstr[index]; - - // space starts at offset 1 - // character = character - ' ' + 1; - - matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - - glBegin(GL_POLYGON); - // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], ); - // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - - if(col) spack(col[0]); - // glVertex3fv(v1); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); - if(col) spack(col[1]); - // glVertex3fv(v2); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - - glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); - if(col) spack(col[2]); - // glVertex3fv(v3); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(v4) { - // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy); - glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); - if(col) spack(col[3]); - // glVertex3fv(v4); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - glEnd(); - - glTranslatef(advance, 0.0, 0.0); - } - glPopMatrix(); - - } -} - - void DisableForText() { if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.h b/source/gameengine/BlenderRoutines/KX_BlenderGL.h index c8e0d47afb6..b891a7343c2 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.h @@ -46,9 +46,6 @@ void BL_HideMouse(); void BL_NormalMouse(); void BL_WaitMouse(); -void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface, - unsigned int *col,float v1[3],float v2[3],float v3[3],float v4[3]); - void BL_print_gamedebug_line(char* text, int xco, int yco, int width, int height); void BL_print_gamedebug_line_padded(char* text, int xco, int yco, int width, int height); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index e4eff163d5b..1797d6c1a0f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -26,8 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include "KX_BlenderRenderTools.h" - #include "GL/glew.h" #include "RAS_IRenderTools.h" @@ -36,23 +34,22 @@ #include "RAS_ICanvas.h" #include "RAS_GLExtensionManager.h" -// next two includes/dependencies come from the shadow feature -// it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" - #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" - -#include "Value.h" - -#include "KX_BlenderGL.h" // for text printing -#include "STR_String.h" -#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting) - #include "KX_RayCast.h" #include "KX_IPhysicsController.h" + #include "PHY_IPhysicsEnvironment.h" -#include "KX_Scene.h" + +#include "STR_String.h" + +#include "GPU_draw.h" + +#include "KX_BlenderGL.h" // for text printing +#include "KX_BlenderRenderTools.h" + +unsigned int KX_BlenderRenderTools::m_numgllights; KX_BlenderRenderTools::KX_BlenderRenderTools() { @@ -61,81 +58,98 @@ KX_BlenderRenderTools::KX_BlenderRenderTools() m_numgllights = 8; } -/** -ProcessLighting performs lighting on objects. the layer is a bitfield that contains layer information. -There are 20 'official' layers in blender. -A light is applied on an object only when they are in the same layer. -OpenGL has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in a scene. -*/ - -int KX_BlenderRenderTools::ProcessLighting(int layer) +KX_BlenderRenderTools::~KX_BlenderRenderTools() { - - int result = false; - - if (layer < 0) - { - DisableOpenGLLights(); - result = false; - } else - { - if (m_clientobject) - { - if (layer == RAS_LIGHT_OBJECT_LAYER) - { - layer = static_cast(m_clientobject)->GetLayer(); - } - if (applyLights(layer)) - { - EnableOpenGLLights(); - result = true; - } else - { - DisableOpenGLLights(); - result = false; - } - } - } - return result; - - } - void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) { m_clientobject = NULL; - m_lastblenderobject = NULL; - m_lastblenderlights = false; - m_lastlayer = -1; + m_lastlightlayer = -1; m_lastlighting = false; - m_modified = true; DisableOpenGLLights(); - - } -void KX_BlenderRenderTools::SetClientObject(void* obj) +void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) +{ +} + +/* ProcessLighting performs lighting on objects. the layer is a bitfield that + * contains layer information. There are 20 'official' layers in blender. A + * light is applied on an object only when they are in the same layer. OpenGL + * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in + * a scene. */ + +void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) +{ + if(m_lastlightlayer == layer) + return; + + m_lastlightlayer = layer; + + bool enable = false; + + if (layer >= 0) + { + if (m_clientobject) + { + if (layer == RAS_LIGHT_OBJECT_LAYER) + layer = static_cast(m_clientobject)->GetLayer(); + + enable = applyLights(layer, viewmat); + } + } + + if(enable) + EnableOpenGLLights(); + else + DisableOpenGLLights(); +} + +void KX_BlenderRenderTools::EnableOpenGLLights() +{ + if(m_lastlighting == true) + return; + + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); + if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) + glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + + m_lastlighting = true; +} + +void KX_BlenderRenderTools::DisableOpenGLLights() +{ + if(m_lastlighting == false) + return; + + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + + m_lastlighting = false; +} + + +void KX_BlenderRenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) { if (m_clientobject != obj) { - if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) - { - glFrontFace(GL_CCW); - } else - { - glFrontFace(GL_CW); - } + bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); + rasty->SetFrontFace(ccw); + m_clientobject = obj; - m_modified = true; } } -bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_BlenderRenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { double* const oglmatrix = (double* const) data; - MT_Point3 resultpoint(hit_point); - MT_Vector3 resultnormal(hit_normal); + MT_Point3 resultpoint(result->m_hitPoint); + MT_Vector3 resultnormal(result->m_hitNormal); MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); left = (dir.cross(resultnormal)).safe_normalized(); @@ -182,7 +196,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat MT_Vector3 dir = (campos - objpos).safe_normalized(); MT_Vector3 up(0,0,1.0); - KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; + KX_GameObject* gameobj = (KX_GameObject*)m_clientobject; // get scaling of halo object MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); @@ -218,7 +232,7 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat { // shadow must be cast to the ground, physics system needed here! MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; + KX_GameObject *gameobj = (KX_GameObject*)m_clientobject; MT_Vector3 direction = MT_Vector3(0,0,-1); direction.normalize(); @@ -236,9 +250,8 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat if (parent) parent->Release(); - MT_Point3 resultpoint; - MT_Vector3 resultnormal; - if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this, oglmatrix))) + KX_RayCast::Callback callback(this, physics_controller, oglmatrix); + if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) { // couldn't find something to cast the shadow on... glMultMatrixd(oglmatrix); @@ -253,13 +266,29 @@ void KX_BlenderRenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmat } -/** -Render Text renders text into a (series of) polygon, using a texture font, -Each character consists of one polygon (one quad or two triangles) -*/ -void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float v1[3],float v2[3],float v3[3],float v4[3]) +void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height) +{ + STR_String tmpstr(text); + + if(mode == RAS_IRenderTools::RAS_TEXT_PADDED) + BL_print_gamedebug_line_padded(tmpstr.Ptr(), xco, yco, width, height); + else + BL_print_gamedebug_line(tmpstr.Ptr(), xco, yco, width, height); +} + +/* Render Text renders text into a (series of) polygon, using a texture font, + * Each character consists of one polygon (one quad or two triangles) */ + +void KX_BlenderRenderTools::RenderText( + int mode, + RAS_IPolyMaterial* polymat, + float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { - STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); @@ -276,68 +305,10 @@ void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float col = blenderpoly->GetMCol(); } - BL_RenderText( mode,mytext,mytext.Length(),tface,col,v1,v2,v3,v4); - + GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); } - -KX_BlenderRenderTools::~KX_BlenderRenderTools() -{ -}; - - -void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty) -{ -} - - - -void KX_BlenderRenderTools::DisableOpenGLLights() -{ - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); -} - - -void KX_BlenderRenderTools::EnableOpenGLLights() -{ - glEnable(GL_LIGHTING); - - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); - if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) - glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); - -} - - -/** - * Rendering text using 2D bitmap functionality. - */ -void KX_BlenderRenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height) -{ - switch (mode) { - case RAS_IRenderTools::RAS_TEXT_PADDED: { - STR_String tmpstr(text); - BL_print_gamedebug_line_padded(tmpstr.Ptr(),xco,yco,width,height); - break; - } - default: { - STR_String tmpstr(text); - BL_print_gamedebug_line(tmpstr.Ptr(),xco,yco,width,height); - } - } -} - - - void KX_BlenderRenderTools::PushMatrix() { glPushMatrix(); @@ -349,14 +320,13 @@ void KX_BlenderRenderTools::PopMatrix() } - -int KX_BlenderRenderTools::applyLights(int objectlayer) +int KX_BlenderRenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) { -// taken from blender source, incompatibility between Blender Object / GameObject - + // taken from blender source, incompatibility between Blender Object / GameObject + float glviewmat[16]; unsigned int count; float vec[4]; - + vec[3]= 1.0; for(count=0; count m_lights; std::vector::iterator lit = m_lights.begin(); + + viewmat.getValue(glviewmat); glPushMatrix(); - glLoadMatrixf(m_viewmat); + glLoadMatrixf(glviewmat); for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) { RAS_LightObject* lightdata = (*lit); @@ -434,7 +406,6 @@ int KX_BlenderRenderTools::applyLights(int objectlayer) glEnable((GLenum)(GL_LIGHT0+count)); count++; - } } glPopMatrix(); @@ -443,22 +414,6 @@ int KX_BlenderRenderTools::applyLights(int objectlayer) } - - -RAS_IPolyMaterial* KX_BlenderRenderTools::CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant,bool zsort, int lightlayer - ,bool bIsTriangle,void* clientobject,void* tface) -{ - assert(!"Deprecated"); -/* return new KX_BlenderPolyMaterial( - - texname, - ba,matname,tile,tilexrep,tileyrep,mode,transparant,zsort, lightlayer - ,bIsTriangle,clientobject,(struct MTFace*)tface);*/ - return NULL; -} - void KX_BlenderRenderTools::MotionBlur(RAS_IRasterizer* rasterizer) { int state = rasterizer->GetMotionBlurState(); @@ -492,4 +447,3 @@ void KX_BlenderRenderTools::Render2DFilters(RAS_ICanvas* canvas) m_filtermanager.RenderFilters(canvas); } -unsigned int KX_BlenderRenderTools::m_numgllights; diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h index 8abce1b8c3e..a7618462c9b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.h @@ -26,6 +26,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ + #ifndef __KX_BLENDERRENDERTOOLS #define __KX_BLENDERRENDERTOOLS @@ -37,67 +38,54 @@ #include "RAS_IRenderTools.h" struct KX_ClientObjectInfo; +class KX_RayCast; -/** -BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which are not -part of the (polygon) Rasterizer. -Effects like 2D text, 3D (polygon) text, lighting. -*/ +/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which + * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon) + * text, lighting. + * + * Most of this code is duplicated in GPC_RenderTools, so this should be + * moved to some common location to avoid duplication. */ class KX_BlenderRenderTools : public RAS_IRenderTools { - bool m_lastblenderlights; - void* m_lastblenderobject; - int m_lastlayer; + int m_lastlightlayer; bool m_lastlighting; static unsigned int m_numgllights; - - + public: - KX_BlenderRenderTools(); virtual ~KX_BlenderRenderTools(); - virtual void EndFrame(class RAS_IRasterizer* rasty); - virtual void BeginFrame(class RAS_IRasterizer* rasty); - void DisableOpenGLLights(); - void EnableOpenGLLights(); - int ProcessLighting(int layer); + void EndFrame(RAS_IRasterizer* rasty); + void BeginFrame(RAS_IRasterizer* rasty); - virtual void RenderText2D(RAS_TEXT_RENDER_MODE mode, + void EnableOpenGLLights(); + void DisableOpenGLLights(); + void ProcessLighting(int layer, const MT_Transform& viewmat); + + void RenderText2D(RAS_TEXT_RENDER_MODE mode, const char* text, int xco, int yco, int width, int height); - virtual void RenderText(int mode, + void RenderText(int mode, class RAS_IPolyMaterial* polymat, float v1[3], float v2[3], float v3[3], - float v4[3]); - void applyTransform(class RAS_IRasterizer* rasty, - double* oglmatrix, - int objectdrawmode ); - int applyLights(int objectlayer); - virtual void PushMatrix(); - virtual void PopMatrix(); + float v4[3], + int glattrib); - virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - void* tface); - - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); + int applyLights(int objectlayer, const MT_Transform& viewmat); + + void PushMatrix(); + void PopMatrix(); + + bool RayHit(KX_ClientObjectInfo* client, class KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo*) { return true; } virtual void MotionBlur(RAS_IRasterizer* rasterizer); @@ -105,8 +93,7 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); - virtual void SetClientObject(void* obj); - + virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); }; #endif //__KX_BLENDERRENDERTOOLS diff --git a/source/gameengine/BlenderRoutines/Makefile b/source/gameengine/BlenderRoutines/Makefile index a7394158a20..4b9a2a3af17 100644 --- a/source/gameengine/BlenderRoutines/Makefile +++ b/source/gameengine/BlenderRoutines/Makefile @@ -54,6 +54,7 @@ CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/render/extern/include CPPFLAGS += -I../../blender/blenloader CPPFLAGS += -I../../blender/blenkernel +CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I../Converter CPPFLAGS += -I../Expressions CPPFLAGS += -I../GameLogic @@ -72,9 +73,5 @@ ifeq ($(OS),windows) CPPFLAGS += -I../../blender endif -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 327f4798e04..78adbc83d9b 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -15,7 +15,7 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common' incs += ' #source/gameengine/Physics/Bullet #source/gameengine/Physics/Sumo' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' incs += ' #intern/SoundSystem #source/blender/misc #source/blender/blenloader' -incs += ' #extern/glew/include' +incs += ' #extern/glew/include #source/blender/gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SOLID_INC'] @@ -26,7 +26,4 @@ cxxflags = [] if env['OURPLATFORM']=='win32-vc': cxxflags.append ('/GR') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - env.BlenderLib ( 'bf_bloutines', sources, Split(incs), [], libtype=['game', 'game2', 'player'], priority=[0, 0, 55] , compileflags=cxxflags) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index d8b2e063a9d..c08427c6d27 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -50,6 +50,7 @@ #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" #include "FloatValue.h" +#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include @@ -58,11 +59,11 @@ BL_ActionActuator::~BL_ActionActuator() { if (m_pose) - free_pose(m_pose); + game_free_pose(m_pose); if (m_userpose) - free_pose(m_userpose); + game_free_pose(m_userpose); if (m_blendpose) - free_pose(m_blendpose); + game_free_pose(m_blendpose); } void BL_ActionActuator::ProcessReplica(){ @@ -151,6 +152,8 @@ bool BL_ActionActuator::Update(double curtime, bool frame) bool apply=true; int priority; float newweight; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); // result = true if animation has to be continued, false if animation stops // maybe there are events for us in the queue ! diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index 09f1d9d4d87..d2001212f7d 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -45,7 +45,6 @@ #include #endif - BL_ArmatureObject::BL_ArmatureObject( void* sgReplicationInfo, SG_Callbacks callbacks, @@ -53,15 +52,20 @@ BL_ArmatureObject::BL_ArmatureObject( : KX_GameObject(sgReplicationInfo,callbacks), m_objArma(armature), - m_mrdPose(NULL), - m_lastframe(0.), + m_framePose(NULL), + m_lastframe(0.0), m_activeAct(NULL), - m_activePriority(999) + m_activePriority(999), + m_lastapplyframe(0.0) { m_armature = get_armature(m_objArma); - m_pose = m_objArma->pose; -} + /* we make a copy of blender object's pose, and then always swap it with + * the original pose before calling into blender functions, to deal with + * replica's or other objects using the same blender object */ + m_pose = NULL; + game_copy_pose(&m_pose, m_objArma->pose); +} CValue* BL_ArmatureObject::GetReplica() { @@ -78,34 +82,37 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) { KX_GameObject::ProcessReplica(replica); + replica->m_pose = NULL; + game_copy_pose(&replica->m_pose, m_pose); } BL_ArmatureObject::~BL_ArmatureObject() { - if (m_mrdPose) - free_pose(m_mrdPose); + if (m_pose) + game_free_pose(m_pose); } -/* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */ -/* there is only 1 unique Pose per Armature */ void BL_ArmatureObject::ApplyPose() { - if (m_pose) { - // copy to armature object - if (m_objArma->pose != m_pose)/* This should never happen but it does - Campbell */ - extract_pose_from_pose(m_objArma->pose, m_pose); - - // is this needed anymore? - //if (!m_mrdPose) - // copy_pose (&m_mrdPose, m_pose, 0); - //else - // extract_pose_from_pose(m_mrdPose, m_pose); + m_armpose = m_objArma->pose; + m_objArma->pose = m_pose; + + if(m_lastapplyframe != m_lastframe) { + where_is_pose(m_objArma); + m_lastapplyframe = m_lastframe; } } +void BL_ArmatureObject::RestorePose() +{ + m_objArma->pose = m_armpose; + m_armpose = NULL; +} + void BL_ArmatureObject::SetPose(bPose *pose) { - m_pose = pose; + extract_pose_from_pose(m_pose, pose); + m_lastapplyframe = -1.0; } bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, double curtime) @@ -114,10 +121,15 @@ bool BL_ArmatureObject::SetActiveAction(BL_ActionActuator *act, short priority, m_activePriority = 9999; m_lastframe= curtime; m_activeAct = NULL; + // remember the pose at the start of the frame + m_framePose = m_pose; } if (priority<=m_activePriority) { + if (prioritySetBlendTime(0.0); /* Reset the blend timer */ m_activeAct = act; @@ -149,13 +161,13 @@ void BL_ArmatureObject::GetPose(bPose **pose) a crash and memory leakage when &BL_ActionActuator::m_pose is freed */ - int copy_constraint_channels_hack = 1; - copy_pose(pose, m_pose, copy_constraint_channels_hack); + game_copy_pose(pose, m_pose); } else { if (*pose == m_pose) // no need to copy if the pointers are the same return; + extract_pose_from_pose(*pose, m_pose); } } @@ -165,21 +177,10 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) /* If the caller supplies a null pose, create a new one. */ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */ - // is this needed anymore? - //if (!m_mrdPose){ - // copy_pose (&m_mrdPose, m_pose, 0); - //} - - if (!*pose) { - // must duplicate the constraints too otherwise we have corruption in free_pose_channels() - // because it will free the blender constraints. - // Ideally, blender should rememeber that the constraints were not copied so that - // free_pose_channels() would not free them. - copy_pose(pose, m_objArma->pose, 1); - } + if (!*pose) + game_copy_pose(pose, m_pose); else - extract_pose_from_pose(*pose, m_objArma->pose); - + extract_pose_from_pose(*pose, m_pose); } short BL_ArmatureObject::GetActivePriority() @@ -192,17 +193,17 @@ double BL_ArmatureObject::GetLastFrame() return m_lastframe; } -bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const +bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) { - Object* par_arma = m_objArma; - where_is_pose(par_arma); - bPoseChannel *pchan= get_pose_channel(par_arma->pose, bone->name); + bPoseChannel *pchan; - if(pchan) { + ApplyPose(); + pchan = get_pose_channel(m_objArma->pose, bone->name); + if(pchan) matrix.setValue(&pchan->pose_mat[0][0]); - return true; - } - return false; + RestorePose(); + + return (pchan != NULL); } float BL_ArmatureObject::GetBoneLength(Bone* bone) const diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 752bd5eb365..d68e37d9e37 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -59,7 +59,10 @@ public: void GetMRDPose(struct bPose **pose); void GetPose(struct bPose **pose); void SetPose (struct bPose *pose); + void ApplyPose(); + void RestorePose(); + bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime); struct bArmature * GetArmature() { return m_armature; } @@ -69,7 +72,7 @@ public: /// Retrieve the pose matrix for the specified bone. /// Returns true on success. - bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const; + bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix); /// Returns the bone length. The end of the bone is in the local y direction. float GetBoneLength(Bone* bone) const; @@ -79,10 +82,13 @@ protected: Object *m_objArma; struct bArmature *m_armature; struct bPose *m_pose; - struct bPose *m_mrdPose; + struct bPose *m_armpose; + struct bPose *m_framePose; double m_lastframe; class BL_ActionActuator *m_activeAct; short m_activePriority; + + double m_lastapplyframe; }; #endif diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index edc14dabc70..425e07a257c 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -377,6 +377,7 @@ BL_Material* ConvertMaterial( material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; + material->flag[i] |= MIPMAP; if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; @@ -601,7 +602,6 @@ BL_Material* ConvertMaterial( (tface->mode & TF_INVISIBLE) )?POLY_VIS:0; - material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; material->tile = tface->tile; material->mode = tface->mode; @@ -617,7 +617,7 @@ BL_Material* ConvertMaterial( } else { // nothing at all - material->ras_mode |= (COLLIDER|POLY_VIS| (validmat?0:USE_LIGHT)); + material->ras_mode |= (POLY_VIS| (validmat?0:USE_LIGHT)); material->mode = default_face_mode; material->transp = TF_SOLID; material->tile = 0; @@ -627,13 +627,19 @@ BL_Material* ConvertMaterial( if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID)) material->transp = TF_ALPHA; - // always zsort alpha + add - if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) - && (material->transp != TF_CLIP)) { + // always zsort alpha + add + if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) { material->ras_mode |= ALPHA; material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; } + // collider or not? + material->ras_mode |= (material->mode & TF_DYNAMIC)? COLLIDER: 0; + + // these flags are irrelevant at this point, remove so they + // don't hurt material bucketing + material->mode &= ~(TF_DYNAMIC|TF_ALPHASORT|TF_TEX); + // get uv sets if(validmat) { @@ -644,6 +650,7 @@ BL_Material* ConvertMaterial( for (int vind = 0; vindnum_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; + if (map.uvCoName.IsEmpty()) isFirstSet = false; else @@ -673,7 +680,7 @@ BL_Material* ConvertMaterial( isFirstSet = false; uvName = layer.name; } - else + else if(strcmp(layer.name, uvName) != 0) { uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; @@ -702,7 +709,6 @@ BL_Material* ConvertMaterial( material->SetConversionUV(uvName, uv); material->SetConversionUV2(uv2Name, uv2); - material->ras_mode |= (mface->v4==0)?TRIANGLE:0; if(validmat) material->matname =(mat->id.name); @@ -767,7 +773,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); + meshobj->m_sharedvertex_map.resize(totvert); for (int f=0;fv1].co); @@ -801,8 +807,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* NormalShortToFloat(n3, mvert[mface->v4].no); no3 = n3; } - else - no3 = MT_Vector3(0.0, 0.0, 0.0); } else { float fno[3]; @@ -830,7 +834,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* ma = give_current_material(blenderobj, mface->mat_nr+1); { - bool polyvisible = true; + bool visible = true; RAS_IPolyMaterial* polymat = NULL; BL_Material *bl_mat = NULL; @@ -845,7 +849,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* bl_mat->material_index = (int)mface->mat_nr; - polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); + visible = ((bl_mat->ras_mode & POLY_VIS)!=0); collider = ((bl_mat->ras_mode & COLLIDER)!=0); /* vertex colors and uv's were stored in bl_mat temporarily */ @@ -862,7 +866,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* uv22 = uv[2]; uv23 = uv[3]; /* then the KX_BlenderMaterial */ - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer); } else { /* do Texture Face materials */ @@ -886,7 +890,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* tile = tface->tile; mode = tface->mode; - polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + visible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); uv0 = MT_Point2(tface->uv[0]); uv1 = MT_Point2(tface->uv[1]); @@ -940,15 +944,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rgb3 = KX_rgbaint2uint_new(color); } - bool istriangle = (mface->v4==0); - // only zsort alpha + add bool alpha = (transp == TF_ALPHA || transp == TF_ADD); bool zsort = (mode & TF_ALPHASORT)? alpha: 0; polymat = new KX_PolygonMaterial(imastr, ma, tile, tilexrep, tileyrep, - mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol); + mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol); if (ma) { polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; @@ -961,6 +963,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } } + /* mark face as flat, so vertices are split */ + bool flat = (mface->flag & ME_SMOOTH) == 0; + // see if a bucket was reused or a new one was created // this way only one KX_BlenderMaterial object has to exist per bucket bool bucketCreated; @@ -981,49 +986,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* polymat = bucket->GetPolyMaterial(); } - int nverts = mface->v4?4:3; - int vtxarray = meshobj->FindVertexArray(nverts,polymat); - RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); + int nverts = (mface->v4)? 4: 3; + RAS_Polygon *poly = meshobj->AddPolygon(bucket, nverts); - bool flat; - - if (skinMesh) { - /* If the face is set to solid, all fnors are the same */ - if (mface->flag & ME_SMOOTH) - flat = false; - else - flat = true; - } - else - flat = false; - - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); - - meshobj->AddPolygon(poly); - if (poly->IsCollider()) - { - RAS_TriangleIndex idx; - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v2; - idx.m_index[2] = mface->v3; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - if (nverts==4) - { - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v3; - idx.m_index[2] = mface->v4; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - } - } - -// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetVisible(visible); poly->SetCollider(collider); + //poly->SetEdgeCode(mface->edcode); + + meshobj->AddVertex(poly,0,pt0,uv0,uv20,tan0,rgb0,no0,flat,mface->v1); + meshobj->AddVertex(poly,1,pt1,uv1,uv21,tan1,rgb1,no1,flat,mface->v2); + meshobj->AddVertex(poly,2,pt2,uv2,uv22,tan2,rgb2,no2,flat,mface->v3); + + if (nverts==4) + meshobj->AddVertex(poly,3,pt3,uv3,uv23,tan3,rgb3,no3,flat,mface->v4); } if (tface) @@ -1039,13 +1014,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* layer.face++; } } - meshobj->m_xyz_index_to_vertex_index_mapping.clear(); - meshobj->UpdateMaterialList(); + meshobj->m_sharedvertex_map.clear(); // pre calculate texture generation - for(RAS_MaterialBucket::Set::iterator mit = meshobj->GetFirstMaterial(); + for(list::iterator mit = meshobj->GetFirstMaterial(); mit != meshobj->GetLastMaterial(); ++ mit) { - (*mit)->GetPolyMaterial()->OnConstruction(); + mit->m_bucket->GetPolyMaterial()->OnConstruction(); } if (layers) @@ -1305,6 +1279,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, //int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0); //bool bRigidBody = (userigidbody == 0); + // object has physics representation? + if (!(blenderobject->gameflag & OB_COLLISION)) + return; + // get Root Parent of blenderobject struct Object* parent= blenderobject->parent; while(parent && parent->parent) { @@ -1336,6 +1314,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_isCompoundChild = isCompoundChild; objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; + objprop.m_margin = blenderobject->margin; if ((objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0)) { @@ -1490,14 +1469,9 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l lightobj.m_type = RAS_LightObject::LIGHT_NORMAL; } -#ifdef BLENDER_GLSL - if(converter->GetGLSLMaterials()) - GPU_lamp_from_blender(ob, la); - - gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, ob->gpulamp); -#else - gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, lightobj, NULL); -#endif + gamelight = new KX_LightObject(kxscene, KX_Scene::m_callbacks, rendertools, + lightobj, converter->GetGLSLMaterials()); + BL_ConvertLampIpos(la, gamelight, converter); return gamelight; @@ -1534,7 +1508,7 @@ static KX_GameObject *gameobject_from_blenderobject( gamelight->AddRef(); kxscene->GetLightList()->Add(gamelight); - + break; } @@ -1643,20 +1617,6 @@ struct parentChildLink { SG_Node* m_gamechildnode; }; - /** - * Find the specified scene by name, or the first - * scene if nothing matches (shouldn't happen). - */ -static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scenename) { - Scene *sce; - - for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) - if (scenename == (sce->id.name+2)) - return sce; - - return (Scene*) maggie->scene.first; -} - #include "DNA_constraint_types.h" #include "BIF_editconstraint.h" @@ -1755,7 +1715,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, ) { - Scene *blenderscene = GetSceneForName(maggie, scenename); + Scene *blenderscene = converter->GetBlenderSceneForName(scenename); // for SETLOOPER Scene *sce; Base *base; @@ -1990,7 +1950,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //tf.Add(gameobj->GetSGNode()); gameobj->NodeUpdateGS(0,true); - gameobj->Bucketize(); + gameobj->AddMeshUser(); } else @@ -2187,8 +2147,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //tf.Add(gameobj->GetSGNode()); gameobj->NodeUpdateGS(0,true); - gameobj->Bucketize(); - + gameobj->AddMeshUser(); } else { @@ -2230,16 +2189,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for(oit=allblobj.begin(); oit!=allblobj.end(); oit++) { Object* blenderobj = *oit; - if (blenderobj->type==OB_MESH){ + if (blenderobj->type==OB_MESH) { Mesh *me = (Mesh*)blenderobj->data; if (me->dvert){ - KX_GameObject *obj = converter->FindGameObject(blenderobj); + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)converter->FindGameObject(blenderobj); if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ KX_GameObject *par = converter->FindGameObject(blenderobj->parent); - if (par) - ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); + if (par && obj->m_pDeformer) + ((BL_SkinDeformer*)obj->m_pDeformer)->SetArmature((BL_ArmatureObject*) par); } } } @@ -2253,6 +2212,41 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { struct Object* blenderchild = pcit->m_blenderchild; + struct Object* blenderparent = blenderchild->parent; + KX_GameObject* parentobj = converter->FindGameObject(blenderparent); + KX_GameObject* childobj = converter->FindGameObject(blenderchild); + + assert(childobj); + + if (!parentobj || objectlist->SearchValue(childobj) != objectlist->SearchValue(parentobj)) + { + // special case: the parent and child object are not in the same layer. + // This weird situation is used in Apricot for test purposes. + // Resolve it by not converting the child + childobj->GetSGNode()->DisconnectFromParent(); + delete pcit->m_gamechildnode; + // Now destroy the child object but also all its descendent that may already be linked + // Remove the child reference in the local list! + // Note: there may be descendents already if the children of the child were processed + // by this loop before the child. In that case, we must remove the children also + CListValue* childrenlist = (CListValue*)childobj->PyGetChildrenRecursive(childobj); + childrenlist->Add(childobj->AddRef()); + for ( i=0;iGetCount();i++) + { + KX_GameObject* obj = static_cast(childrenlist->GetValue(i)); + if (templist->RemoveValue(obj)) + obj->Release(); + if (sumolist->RemoveValue(obj)) + obj->Release(); + if (logicbrick_conversionlist->RemoveValue(obj)) + obj->Release(); + } + childrenlist->Release(); + // now destroy recursively + kxscene->RemoveObject(childobj); + continue; + } + switch (blenderchild->partype) { case PARVERT1: @@ -2273,8 +2267,11 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { // parent this to a bone Bone *parent_bone = get_named_bone(get_armature(blenderchild->parent), blenderchild->parsubstr); - KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); - pcit->m_gamechildnode->SetParentRelation(bone_parent_relation); + + if(parent_bone) { + KX_BoneParentRelation *bone_parent_relation = KX_BoneParentRelation::New(parent_bone); + pcit->m_gamechildnode->SetParentRelation(bone_parent_relation); + } break; } @@ -2289,12 +2286,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, break; } - struct Object* blenderparent = blenderchild->parent; - KX_GameObject* parentobj = converter->FindGameObject(blenderparent); - if (parentobj) - { - parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode); - } + parentobj-> GetSGNode()->AddChild(pcit->m_gamechildnode); } vec_parent_child.clear(); @@ -2479,7 +2471,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, struct Object* blenderobj = converter->FindBlenderObject(gameobj); int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; - BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); + BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); // set the init state to all objects gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); } @@ -2511,5 +2503,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie, kxscene->DupliGroupRecurse(gameobj, 0); } } + + KX_Camera *activecam = kxscene->GetActiveCamera(); + MT_Scalar distance = (activecam)? activecam->GetCameraFar() - activecam->GetCameraNear(): 100.0f; + RAS_BucketManager *bucketmanager = kxscene->GetBucketManager(); + bucketmanager->OptimizeBuckets(distance); } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index d23274324ee..1d62a41cce9 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -41,12 +41,14 @@ BL_DeformableGameObject::~BL_DeformableGameObject() delete m_pDeformer; // __NLA : Temporary until we decide where to put this } -void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) +void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) { + BL_MeshDeformer *deformer; KX_GameObject::ProcessReplica(replica); - if (m_pDeformer){ - ((BL_DeformableGameObject*)replica)->m_pDeformer = m_pDeformer->GetReplica(); + if (m_pDeformer) { + deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(); + ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer; } } diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index 39d66a90e92..fa3b8185fe2 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -50,26 +50,26 @@ bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { - size_t i, j; + size_t i; float *co; // only apply once per frame if the mesh is actually modified if(m_pMeshObject->MeshModified() && m_lastDeformUpdate != m_gameobj->GetLastFrame()) { // For each material - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + for(list::iterator mit= m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + if(!mit->m_slots[(void*)m_gameobj]) + continue; - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - - // For each array - for (i=0; im_slots[(void*)m_gameobj]; + RAS_MeshSlot::iterator it; + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { // For each vertex - for (j=0; jmvert[v.getOrigIndex()].co; v.SetXYZ(MT_Point3(co)); } @@ -90,7 +90,17 @@ BL_MeshDeformer::~BL_MeshDeformer() delete [] m_transverts; if (m_transnors) delete [] m_transnors; -}; +} + +void BL_MeshDeformer::Relink(GEN_Map*map) +{ + void **h_obj = (*map)[m_gameobj]; + + if (h_obj) + m_gameobj = (BL_DeformableGameObject*)(*h_obj); + else + m_gameobj = NULL; +} /** * @warning This function is expensive! @@ -101,41 +111,41 @@ void BL_MeshDeformer::RecalcNormals() * gives area-weight normals which often look better anyway, and use * GL_NORMALIZE so we don't have to do per vertex normalization either * since the GPU can do it faster */ - size_t i, j; + list::iterator mit; + RAS_MeshSlot::iterator it; + size_t i; /* set vertex normals to zero */ memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert); /* add face normals to vertices. */ - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + for(mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + if(!mit->m_slots[(void*)m_gameobj]) + continue; - const vecIndexArrays& indexarrays = m_pMeshObject->GetIndexCache(mat); - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; - for (i=0; iUsesTriangles()? 3: 4; + for(slot->begin(it); !slot->end(it); slot->next(it)) { + int nvert = (int)it.array->m_type; - for(j=0; jgetLocalXYZ(); + v4 = &it.vertex[it.index[i+3]]; + co4 = v4->getXYZ(); n1[0]= co1[0]-co3[0]; n1[1]= co1[1]-co3[1]; @@ -174,7 +184,7 @@ void BL_MeshDeformer::RecalcNormals() } /* in case of flat - just assign, the vertices are split */ - if(v1.getFlag() & TV_CALCFACENORMAL) { + if(v1.getFlag() & RAS_TexVert::FLAT) { v1.SetNormal(fnor); v2.SetNormal(fnor); v3.SetNormal(fnor); @@ -186,19 +196,18 @@ void BL_MeshDeformer::RecalcNormals() } /* assign smooth vertex normals */ - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); + for(mit = m_pMeshObject->GetFirstMaterial(); mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + if(!mit->m_slots[(void*)m_gameobj]) + continue; - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj]; - for (i=0; ibegin(it); !slot->end(it); slot->next(it)) { + for(i=it.startvertex; itotvert; } } - + diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index e9f7f0b192f..9d3d2e78123 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -47,7 +47,7 @@ class BL_MeshDeformer : public RAS_Deformer public: void VerifyStorage(); void RecalcNormals(); - virtual void Relink(GEN_Map*map){}; + virtual void Relink(GEN_Map*map); BL_MeshDeformer(BL_DeformableGameObject *gameobj, struct Object* obj, class BL_SkinMeshObject *meshobj ): @@ -67,6 +67,7 @@ public: virtual RAS_Deformer* GetReplica(){return NULL;}; struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; + protected: class BL_SkinMeshObject* m_pMeshObject; struct Mesh* m_bmesh; diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 942e3b502e0..da5ca1e7c95 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -49,6 +49,7 @@ #include "BLI_arithb.h" #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" +#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include @@ -134,7 +135,6 @@ void BL_ShapeActionActuator::BlendShape(Key* key, float srcweight) { vector::const_iterator it; float dstweight; - int i; KeyBlock *kb; dstweight = 1.0F - srcweight; @@ -155,6 +155,8 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) bool apply=true; int priority; float newweight; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); // result = true if animation has to be continued, false if animation stops // maybe there are events for us in the queue ! diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index b2e54539b19..dfd33e45fef 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -109,12 +109,10 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) vector::iterator it; void *poin; int type; + // the shape drivers use the bone matrix as input. Must // update the matrix now - Object* par_arma = m_armobj->GetArmatureObject(); m_armobj->ApplyPose(); - where_is_pose( par_arma ); - PoseApplied(true); for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { // no need to set a specific time: this curve has a driver @@ -124,7 +122,10 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) if (poin) write_ipo_poin(poin, type, icu->curval); } + ForceUpdate(); + m_armobj->RestorePose(); + return true; } return false; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 5f0188e3a42..1465bb01e22 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -43,17 +43,6 @@ struct IpoCurve; class BL_ShapeDeformer : public BL_SkinDeformer { public: - virtual void Relink(GEN_Map*map) - { - void **h_obj = (*map)[m_gameobj]; - if (h_obj){ - m_gameobj = (BL_DeformableGameObject*)(*h_obj); - } - else - m_gameobj=NULL; - // relink the underlying skin deformer - BL_SkinDeformer::Relink(map); - }; BL_ShapeDeformer(BL_DeformableGameObject *gameobj, Object *bmeshobj, BL_SkinMeshObject *mesh) diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index f96c40c098f..b7b39ad7fbf 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -99,9 +99,26 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } +void BL_SkinDeformer::Relink(GEN_Map*map) +{ + if (m_armobj) { + void **h_obj = (*map)[m_armobj]; + + if (h_obj) + SetArmature( (BL_ArmatureObject*)(*h_obj) ); + else + m_armobj=NULL; + } + + BL_MeshDeformer::Relink(map); +} + bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) { - size_t i, j; + RAS_MeshSlot::iterator it; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + size_t i; // update the vertex in m_transverts Update(); @@ -110,16 +127,18 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) // share the same mesh (=the same cache). As the rendering is done per polymaterial // cycling through the objects, the entire mesh cache cannot be updated in one shot. - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + mmat = m_pMeshObject->GetMeshMaterial(mat); + if(!mmat->m_slots[(void*)m_gameobj]) + return true; - // For each array - for (i=0; im_slots[(void*)m_gameobj]; - // For each vertex + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { + // for each vertex // copy the untransformed data from the original mvert - for (j=0; jGetArmatureObject(); - if (!PoseApplied()){ - m_armobj->ApplyPose(); - where_is_pose( par_arma ); - } /* store verts locally */ VerifyStorage(); @@ -163,6 +178,8 @@ bool BL_SkinDeformer::Update(void) for (int v =0; vtotvert; v++) VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); + m_armobj->ApplyPose(); + // save matrix first Mat4CpyMat4(obmat, m_objMesh->obmat); // set reference matrix @@ -179,11 +196,13 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); - /* reset for next frame */ - PoseApplied(false); + + m_armobj->RestorePose(); + /* indicate that the m_transverts and normals are up to date */ return true; } + return false; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index d3fc5ae2a81..e08de8c478a 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -50,17 +50,7 @@ class BL_SkinDeformer : public BL_MeshDeformer { public: // void SetArmatureController (BL_ArmatureController *cont); - virtual void Relink(GEN_Map*map) - { - if (m_armobj){ - void **h_obj = (*map)[m_armobj]; - if (h_obj){ - SetArmature( (BL_ArmatureObject*)(*h_obj) ); - } - else - m_armobj=NULL; - } - } + virtual void Relink(GEN_Map*map); void SetArmature (class BL_ArmatureObject *armobj); BL_SkinDeformer(BL_DeformableGameObject *gameobj, @@ -81,10 +71,6 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); - bool PoseApplied() - { return m_poseApplied; } - void PoseApplied(bool applied) - { m_poseApplied = applied; } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp index fa215df1e1c..4f9f1a434b5 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.cpp +++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp @@ -28,42 +28,69 @@ * Deformer that supports armature skinning */ -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 -#include "RAS_IPolygonMaterial.h" -#include "BL_SkinMeshObject.h" -#include "BL_DeformableGameObject.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_key_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" -#include "KX_GameObject.h" + #include "RAS_BucketManager.h" +#include "RAS_IPolygonMaterial.h" -//void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,RAS_BucketManager* bucketmgr) -void BL_SkinMeshObject::Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec) -{ +#include "KX_GameObject.h" - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_bObjectColor = useObjectColor; - ms.m_RGBAcolor = rgbavec; - ms.m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();it++) +#include "BL_SkinMeshObject.h" +#include "BL_DeformableGameObject.h" + +BL_SkinMeshObject::BL_SkinMeshObject(Mesh* mesh, int lightlayer) + : RAS_MeshObject (mesh, lightlayer) +{ + m_bDeformed = true; + + if (m_mesh && m_mesh->key) { + KeyBlock *kb; + int count=0; + // initialize weight cache for shape objects + // count how many keys in this mesh + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) + count++; + m_cacheWeightIndex.resize(count,-1); + } +} - RAS_MaterialBucket* materialbucket = (*it); +BL_SkinMeshObject::~BL_SkinMeshObject() +{ + if (m_mesh && m_mesh->key) + { + KeyBlock *kb; + // remove the weight cache to avoid memory leak + for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { + if(kb->weights) + MEM_freeN(kb->weights); + kb->weights= NULL; + } + } +} -// KX_ArrayOptimizer* oa = GetArrayOptimizer(materialbucket->GetPolyMaterial()); - materialbucket->SetMeshSlot(ms); +void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool useObjectColor,const MT_Vector4& rgbavec, bool visible, bool culled) +{ + list::iterator it; + list::iterator sit; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + if(!it->m_slots[clientobj]) + continue; + + RAS_MeshSlot *slot = *it->m_slots[clientobj]; + slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; } + RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled); } static int get_def_index(Object* ob, const char* vgroup) @@ -74,6 +101,7 @@ static int get_def_index(Object* ob, const char* vgroup) for (curdef = (bDeformGroup*)ob->defbase.first; curdef; curdef=(bDeformGroup*)curdef->next, index++) if (!strcmp(curdef->name, vgroup)) return index; + return -1; } diff --git a/source/gameengine/Converter/BL_SkinMeshObject.h b/source/gameengine/Converter/BL_SkinMeshObject.h index c21fb64204b..8544a2b958c 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.h +++ b/source/gameengine/Converter/BL_SkinMeshObject.h @@ -33,62 +33,27 @@ #ifdef WIN32 #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 -#include "MEM_guardedalloc.h" + #include "RAS_MeshObject.h" #include "RAS_Deformer.h" #include "RAS_IPolygonMaterial.h" #include "BL_MeshDeformer.h" -#include "DNA_mesh_types.h" -#include "DNA_key_types.h" -#include "DNA_meshdata_types.h" - class BL_SkinMeshObject : public RAS_MeshObject { - -// enum { BUCKET_MAX_INDICES = 16384};//2048};//8192}; -// enum { BUCKET_MAX_TRIANGLES = 4096}; - protected: vector m_cacheWeightIndex; public: - void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec); -// void Bucketize(double* oglmatrix,void* clientobj,bool useObjectColor,const MT_Vector4& rgbavec,class RAS_BucketManager* bucketmgr); + BL_SkinMeshObject(Mesh* mesh, int lightlayer); + ~BL_SkinMeshObject(); - BL_SkinMeshObject(Mesh* mesh, int lightlayer) : RAS_MeshObject (mesh, lightlayer) - { - m_class = 1; - if (m_mesh && m_mesh->key) - { - KeyBlock *kb; - int count=0; - // initialize weight cache for shape objects - // count how many keys in this mesh - for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) - count++; - m_cacheWeightIndex.resize(count,-1); - } - }; - - virtual ~BL_SkinMeshObject() - { - if (m_mesh && m_mesh->key) - { - KeyBlock *kb; - // remove the weight cache to avoid memory leak - for(kb= (KeyBlock*)m_mesh->key->block.first; kb; kb= (KeyBlock*)kb->next) { - if(kb->weights) - MEM_freeN(kb->weights); - kb->weights= NULL; - } - } - }; + void UpdateBuckets(void* clientobj, double* oglmatrix, + bool useObjectColor, const MT_Vector4& rgbavec, bool visible, bool culled); // for shape keys, void CheckWeightCache(struct Object* obj); - }; #endif diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index adb7304b10e..217bdb30907 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -64,6 +64,7 @@ SET(INC ../../../source/gameengine/Network/LoopBackNetwork ../../../source/blender/misc ../../../source/blender/blenloader + ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ${PYTHON_INC} diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index de91bce2ab1..7eec93dc402 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -184,20 +184,21 @@ bool KX_BlenderSceneConverter::TryAndLoadNewFile() return result; } - +Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) +{ + Scene *sce; /** * Find the specified scene by name, or the first * scene if nothing matches (shouldn't happen). */ -static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& scenename) { - Scene *sce; - for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next) - if (scenename == (sce->id.name+2)) + for (sce= (Scene*) m_maggie->scene.first; sce; sce= (Scene*) sce->id.next) + if (name == (sce->id.name+2)) return sce; - return (Scene*) maggie->scene.first; + return (Scene*)m_maggie->scene.first; + } #include "KX_PythonInit.h" @@ -245,6 +246,11 @@ struct BlenderDebugDraw : public btIDebugDraw { return m_debugMode; } + ///todo: find out if Blender can do this + virtual void draw3dText(const btVector3& location,const char* textString) + { + + } }; @@ -258,7 +264,7 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename, class RAS_ICanvas* canvas) { //find out which physics engine - Scene *blenderscene = GetSceneForName2(m_maggie, scenename); + Scene *blenderscene = GetBlenderSceneForName(scenename); e_PhysicsEngine physics_engine = UseBullet; // hook for registration function during conversion. @@ -495,7 +501,17 @@ void KX_BlenderSceneConverter::RegisterGameObject( void KX_BlenderSceneConverter::UnregisterGameObject( KX_GameObject *gameobject) { - m_map_gameobject_to_blender.remove(CHashedPtr(gameobject)); + CHashedPtr gptr(gameobject); + struct Object **bobp= m_map_gameobject_to_blender[gptr]; + if (bobp) { + CHashedPtr bptr(*bobp); + KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; + if (gobp && *gobp == gameobject) + // also maintain m_map_blender_to_gameobject if the gameobject + // being removed is matching the blender object + m_map_blender_to_gameobject.remove(bptr); + m_map_gameobject_to_blender.remove(gptr); + } } @@ -644,13 +660,13 @@ extern "C" { Ipo *add_ipo( char *name, int idcode ); char *getIpoCurveName( IpoCurve * icu ); - struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); + struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); void testhandles_ipocurve(struct IpoCurve *icu); + void insert_vert_icu(struct IpoCurve *, float, float, short); void Mat3ToEul(float tmat[][3], float *eul); - } -IpoCurve* findIpoCurve(IpoCurve* first,char* searchName) +IpoCurve* findIpoCurve(IpoCurve* first, const char* searchName) { IpoCurve* icu1; for( icu1 = first; icu1; icu1 = icu1->next ) @@ -818,7 +834,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { - KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); + //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); if (blenderObject) @@ -846,7 +862,7 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) - const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); + //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Point3& position = gameObj->NodeGetWorldPosition(); Ipo* ipo = blenderObject->ipo; @@ -857,27 +873,27 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); @@ -974,7 +990,7 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); if (gameObj->IsDynamic()) { - KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); + //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); if (blenderObject) @@ -1002,8 +1018,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() - const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); + //const MT_Point3& position = gameObj->NodeGetWorldPosition(); Ipo* ipo = blenderObject->ipo; if (ipo) @@ -1013,27 +1029,27 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index e5d6ccc5caf..2317e952a0a 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -45,6 +45,7 @@ class BL_Material; struct IpoCurve; struct Main; struct SpaceIpo; +struct Scene; class KX_BlenderSceneConverter : public KX_ISceneConverter { @@ -151,6 +152,7 @@ public: virtual void SetGLSLMaterials(bool val); virtual bool GetGLSLMaterials(); + struct Scene* GetBlenderSceneForName(const STR_String& name); }; #endif //__KX_BLENDERSCENECONVERTER_H diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index b1f86afa4ee..e8be8de95ed 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -74,6 +74,8 @@ #include "BKE_text.h" #include "BLI_blenlib.h" +#define FILE_MAX 240 // repeated here to avoid dependency from BKE_utildefines.h + #include "KX_NetworkMessageActuator.h" #ifdef WIN32 @@ -355,22 +357,26 @@ void BL_ConvertActuators(char* maggiename, if (soundActuatorType != KX_SoundActuator::KX_SOUNDACT_NODEF) { - SND_SoundObject* sndobj = NULL; + SND_Scene* soundscene = scene->GetSoundScene(); + STR_String samplename = ""; + bool sampleisloaded = false; - if (soundact->sound) - { - SND_Scene* soundscene = scene->GetSoundScene(); - STR_String samplename = soundact->sound->name; + if (soundact->sound) { + /* Need to convert the samplename into absolute path + * before checking if its loaded */ + char fullpath[FILE_MAX]; - bool sampleisloaded = false; + /* dont modify soundact->sound->name, only change a copy */ + BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); + BLI_convertstringcode(fullpath, maggiename); + samplename = fullpath; /* let's see if the sample was already loaded */ if (soundscene->IsSampleLoaded(samplename)) { sampleisloaded = true; } - else - { + else { /* if not, make it so */ PackedFile* pf = soundact->sound->newpackedfile; @@ -383,25 +389,33 @@ void BL_ConvertActuators(char* maggiename, /* or else load it from disk */ else { - /* but we need to convert the samplename into absolute pathname first */ - char fullpath[sizeof(soundact->sound->name)]; - - /* dont modify soundact->sound->name, only change a copy */ - BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); - BLI_convertstringcode(fullpath, maggiename); - samplename = fullpath; - - /* and now we can load it */ - if (soundscene->LoadSample(samplename, NULL, 0) > -1) + if (soundscene->LoadSample(samplename, NULL, 0) > -1) { sampleisloaded = true; + } + else { + std::cout << "WARNING: Sound actuator \"" << bact->name << + "\" from object \"" << blenderobject->id.name+2 << + "\" failed to load sample." << std::endl; + } } } - - if (sampleisloaded) - { - sndobj = new SND_SoundObject(); - sndobj->SetSampleName(samplename.Ptr()); - sndobj->SetObjectName(bact->name); + } else { + std::cout << "WARNING: Sound actuator \"" << bact->name << + "\" from object \"" << blenderobject->id.name+2 << + "\" has no sound datablock." << std::endl; + } + + /* Note, allowing actuators for sounds that are not there was added since 2.47 + * This is because python may expect the actuator and raise an exception if it dosnt find it + * better just to add a dummy sound actuator. */ + SND_SoundObject* sndobj = NULL; + if (sampleisloaded) + { + /* setup the SND_SoundObject */ + sndobj = new SND_SoundObject(); + sndobj->SetSampleName(samplename.Ptr()); + sndobj->SetObjectName(bact->name); + if (soundact->sound) { sndobj->SetRollOffFactor(soundact->sound->attenuation); sndobj->SetGain(soundact->sound->volume); sndobj->SetPitch(exp((soundact->sound->pitch / 12.0) * log(2.0))); @@ -414,8 +428,9 @@ void BL_ConvertActuators(char* maggiename, else sndobj->SetLoopMode(SND_LOOP_NORMAL); } - else + else { sndobj->SetLoopMode(SND_LOOP_OFF); + } if (soundact->sound->flags & SOUND_FLAGS_PRIORITY) sndobj->SetHighPriority(true); @@ -426,22 +441,30 @@ void BL_ConvertActuators(char* maggiename, sndobj->Set3D(true); else sndobj->Set3D(false); - - KX_SoundActuator* tmpsoundact = - new KX_SoundActuator(gameobj, - sndobj, - scene->GetSoundScene(), // needed for replication! - soundActuatorType, - startFrame, - stopFrame); - - tmpsoundact->SetName(bact->name); - baseact = tmpsoundact; - soundscene->AddObject(sndobj); - } else { - std::cout << "WARNING: Sound actuator " << bact->name << " failed to load sample." << std::endl; + } + else { + /* dummy values for a NULL sound + * see editsound.c - defaults are unlikely to change soon */ + sndobj->SetRollOffFactor(1.0); + sndobj->SetGain(1.0); + sndobj->SetPitch(1.0); + sndobj->SetLoopMode(SND_LOOP_OFF); + sndobj->SetHighPriority(false); + sndobj->Set3D(false); } } + KX_SoundActuator* tmpsoundact = + new KX_SoundActuator(gameobj, + sndobj, + scene->GetSoundScene(), // needed for replication! + soundActuatorType, + startFrame, + stopFrame); + + tmpsoundact->SetName(bact->name); + baseact = tmpsoundact; + if (sndobj) + soundscene->AddObject(sndobj); } break; } @@ -554,10 +577,16 @@ void BL_ConvertActuators(char* maggiename, originalval = converter->FindGameObject(editobact->ob); } } - MT_Vector3 linvelvec ( KX_BLENDERTRUNC(editobact->linVelocity[0]), + MT_Vector3 linvelvec ( + KX_BLENDERTRUNC(editobact->linVelocity[0]), KX_BLENDERTRUNC(editobact->linVelocity[1]), KX_BLENDERTRUNC(editobact->linVelocity[2])); - + + MT_Vector3 angvelvec ( + KX_BLENDERTRUNC(editobact->angVelocity[0]), + KX_BLENDERTRUNC(editobact->angVelocity[1]), + KX_BLENDERTRUNC(editobact->angVelocity[2])); + KX_SCA_AddObjectActuator* tmpaddact = new KX_SCA_AddObjectActuator( gameobj, @@ -565,7 +594,9 @@ void BL_ConvertActuators(char* maggiename, editobact->time, scene, linvelvec.getValue(), - editobact->localflag!=0 + (editobact->localflag & ACT_EDOB_LOCAL_LINV)!=0, + angvelvec.getValue(), + (editobact->localflag & ACT_EDOB_LOCAL_ANGV)!=0 ); //editobact->ob to gameobj @@ -847,6 +878,16 @@ void BL_ConvertActuators(char* maggiename, mode = KX_GameActuator::KX_GAME_QUIT; break; } + case ACT_GAME_SAVECFG: + { + mode = KX_GameActuator::KX_GAME_SAVECFG; + break; + } + case ACT_GAME_LOADCFG: + { + mode = KX_GameActuator::KX_GAME_LOADCFG; + break; + } default: ; /* flag error */ } @@ -933,10 +974,9 @@ void BL_ConvertActuators(char* maggiename, bVisibilityActuator *vis_act = (bVisibilityActuator *) bact->data; KX_VisibilityActuator * tmp_vis_act = NULL; bool v = ((vis_act->flag & ACT_VISIBILITY_INVISIBLE) != 0); + bool recursive = ((vis_act->flag & ACT_VISIBILITY_RECURSIVE) != 0); - tmp_vis_act = - new KX_VisibilityActuator(gameobj, - !v); + tmp_vis_act = new KX_VisibilityActuator(gameobj, !v, recursive); baseact = tmp_vis_act; } @@ -1035,7 +1075,7 @@ void BL_ConvertActuators(char* maggiename, { bParentActuator *parAct = (bParentActuator *) bact->data; int mode = KX_ParentActuator::KX_PARENT_NODEF; - KX_GameObject *tmpgob; + KX_GameObject *tmpgob = NULL; switch(parAct->type) { diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 4806df36090..be0bb8103c0 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -92,6 +92,7 @@ void BL_ConvertSensors(struct Object* blenderobject, class KX_GameObject* gameobj, SCA_LogicManager* logicmgr, KX_Scene* kxscene, + KX_KetsjiEngine* kxengine, SCA_IInputDevice* keydev, int & executePriority, int activeLayerBitInfo, @@ -508,6 +509,7 @@ void BL_ConvertSensors(struct Object* blenderobject, trackfocus, canvas, kxscene, + kxengine, gameobj); } } else { @@ -633,6 +635,7 @@ void BL_ConvertSensors(struct Object* blenderobject, if (eventmgr) { bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); @@ -645,6 +648,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gameobj, checkname, bFindMaterial, + bXRay, distance, axis, kxscene); @@ -711,6 +715,7 @@ void BL_ConvertSensors(struct Object* blenderobject, gamesensor = new SCA_JoystickSensor( eventmgr, gameobj, + bjoy->joyindex, joysticktype, axis,axisf, prec, @@ -765,19 +770,26 @@ void BL_ConvertSensors(struct Object* blenderobject, logicmgr->RegisterToSensor(gamecont,gamesensor); } else { printf( - "Warning, sensor \"%s\" could not find its controller" - "(link %d of %d)\n" + "Warning, sensor \"%s\" could not find its controller " + "(link %d of %d) from object \"%s\"\n" "\tthere has been an error converting the blender controller for the game engine," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks); + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } else { printf( - "Warning, sensor \"%s\" has lost a link to a controller" - "(link %d of %d)\n" + "Warning, sensor \"%s\" has lost a link to a controller " + "(link %d of %d) from object \"%s\"\n" "\tpossible causes are partially appended objects or an error reading the file," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks); + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); } } + // special case: Keyboard sensor with no link + // this combination is usually used for key logging. + if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { + // Force the registration so that the sensor runs + gamesensor->IncLink(); + } + // done with gamesensor gamesensor->Release(); diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h index 73da51f47f0..b18ffc10a2a 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.h +++ b/source/gameengine/Converter/KX_ConvertSensors.h @@ -33,6 +33,7 @@ void BL_ConvertSensors(struct Object* blenderobject, class KX_GameObject* gameobj, class SCA_LogicManager* logicmgr, class KX_Scene* kxscene, + class KX_KetsjiEngine* kxengine, class SCA_IInputDevice* keydev, int & executePriority , int activeLayerBitInfo, diff --git a/source/gameengine/Converter/Makefile b/source/gameengine/Converter/Makefile index f312fc13221..4dd63e428bd 100644 --- a/source/gameengine/Converter/Makefile +++ b/source/gameengine/Converter/Makefile @@ -51,6 +51,7 @@ CPPFLAGS += -I../../blender/include CPPFLAGS += -I../../blender/blenlib CPPFLAGS += -I../../blender/blenkernel CPPFLAGS += -I../../blender/render/extern/include +CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../Expressions -I../Rasterizer -I../GameLogic CPPFLAGS += -I../Ketsji -I../BlenderRoutines -I../SceneGraph diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index f5e382b471e..3be352c568b 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -16,7 +16,7 @@ incs += ' #source/gameengine/Expressions #source/gameengine/Network #source/game incs += ' #source/gameengine/Physics/common #source/gameengine/Physics/Bullet #source/gameengine/Physics/BlOde' incs += ' #source/gameengine/Physics/Dummy #source/gameengine/Physics/Sumo' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' -incs += ' #source/blender/misc #source/blender/blenloader' +incs += ' #source/blender/misc #source/blender/blenloader #source/blender/gpu' incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SOLID_INC'] diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile index e9c02eedcf2..6736149bbcd 100644 --- a/source/gameengine/Expressions/Makefile +++ b/source/gameengine/Expressions/Makefile @@ -36,6 +36,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I../../blender/makesdna 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 8937f481922..1eca527151a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -119,6 +119,7 @@ PyObject *PyObjectPlus::_getattr(const STR_String& attr) int PyObjectPlus::_delattr(const STR_String& attr) { + PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); return 1; } @@ -126,7 +127,8 @@ int PyObjectPlus::_setattr(const STR_String& attr, PyObject *value) { //return PyObject::_setattr(attr,value); //cerr << "Unknown attribute" << endl; - return 1; + PyErr_SetString(PyExc_AttributeError, "attribute cant be set"); + return 1; } /*------------------------------ diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index f433a08faba..ccc9af2ed79 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -43,6 +43,33 @@ * Python defines ------------------------------*/ +/* + Py_RETURN_NONE + Python 2.4 macro. + defined here until we switch to 2.4 + also in api2_2x/gen_utils.h +*/ +#ifndef Py_RETURN_NONE +#define Py_RETURN_NONE return Py_BuildValue("O", Py_None) +#endif +#ifndef Py_RETURN_FALSE +#define Py_RETURN_FALSE return PyBool_FromLong(0) +#endif +#ifndef Py_RETURN_TRUE +#define Py_RETURN_TRUE return PyBool_FromLong(1) +#endif + +/* for pre Py 2.5 */ +#if PY_VERSION_HEX < 0x02050000 +typedef int Py_ssize_t; +#define PY_SSIZE_T_MAX INT_MAX +#define PY_SSIZE_T_MIN INT_MIN +#else +/* Py 2.5 and later */ +#define intargfunc ssizeargfunc +#define intintargfunc ssizessizeargfunc +#endif + // some basic python macros #define Py_Return { Py_INCREF(Py_None); return Py_None;} @@ -102,6 +129,12 @@ static inline void Py_Fatal(char *M) { return ((class_name*) self)->Py##method_name(self, args, kwds); \ }; \ +#define KX_PYMETHOD_VARARGS(class_name, method_name) \ + PyObject* Py##method_name(PyObject* self, PyObject* args); \ + static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ + return ((class_name*) self)->Py##method_name(self, args); \ + }; \ + #define KX_PYMETHOD_NOARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* self); \ static PyObject* sPy##method_name( PyObject* self) { \ @@ -150,6 +183,9 @@ static inline void Py_Fatal(char *M) { #define KX_PYMETHODTABLE(class_name, method_name) \ {#method_name , (PyCFunction) class_name::sPy##method_name, METH_VARARGS, class_name::method_name##_doc} +#define KX_PYMETHODTABLE_NOARG(class_name, method_name) \ + {#method_name , (PyCFunction) class_name::sPy##method_name, METH_NOARGS, class_name::method_name##_doc} + /** * Function implementation macro */ @@ -157,6 +193,9 @@ static inline void Py_Fatal(char *M) { char class_name::method_name##_doc[] = doc_string; \ PyObject* class_name::Py##method_name(PyObject*, PyObject* args, PyObject*) +#define KX_PYMETHODDEF_DOC_NOARG(class_name, method_name, doc_string) \ +char class_name::method_name##_doc[] = doc_string; \ +PyObject* class_name::Py##method_name(PyObject*) /*------------------------------ * PyObjectPlus diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 7bcb45228db..7296dfbec10 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -391,16 +391,23 @@ float CValue::GetPropertyNumber(const STR_String& inName,float defnumber) bool CValue::RemoveProperty(const STR_String & inName) { // Check if there are properties at all which can be removed - if (m_pNamedPropertyArray == NULL) - return false; - - CValue* val = GetProperty(inName); - if (NULL != val) - { - val->Release(); - m_pNamedPropertyArray->erase(inName); - return true; - } + if (m_pNamedPropertyArray) { + CValue* val = GetProperty(inName); + if (NULL != val) + { + val->Release(); + m_pNamedPropertyArray->erase(inName); + return true; + } + } + + char err[128]; + if (m_pNamedPropertyArray) + sprintf(err, "attribute \"%s\" dosnt exist", inName.ReadPtr()); + else + sprintf(err, "attribute \"%s\" dosnt exist (no property array)", inName.ReadPtr()); + + PyErr_SetString(PyExc_AttributeError, err); return false; } @@ -755,7 +762,8 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) int CValue::_delattr(const STR_String& attr) { - RemoveProperty(attr); + if (!RemoveProperty(attr)) /* sets error */ + return 1; return 0; } diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index 18d7b6ffcd0..06002060bf1 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -29,9 +29,9 @@ #include "SCA_Joystick.h" #include "SCA_JoystickPrivate.h" - -SCA_Joystick::SCA_Joystick() +SCA_Joystick::SCA_Joystick(short int index) : + m_joyindex(index), m_axis10(0), m_axis11(0), m_axis20(0), @@ -52,82 +52,53 @@ SCA_Joystick::~SCA_Joystick() delete m_private; } -SCA_Joystick *SCA_Joystick::m_instance = NULL; +SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX]; int SCA_Joystick::m_refCount = 0; -SCA_Joystick *SCA_Joystick::GetInstance() +SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) { - if (m_instance == 0) + if (joyindex < 0 || joyindex >= JOYINDEX_MAX) { + echo("Error-invalid joystick index: " << joyindex); + return NULL; + } + + if (m_refCount == 0) { - m_instance = new SCA_Joystick(); - m_instance->CreateJoystickDevice(); + int i; + // do this once only + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){ + echo("Error-Initializing-SDL: " << SDL_GetError()); + return NULL; + } + for (i=0; iCreateJoystickDevice(); + } m_refCount = 1; } else { m_refCount++; } - return m_instance; + return m_instance[joyindex]; } void SCA_Joystick::ReleaseInstance() { if (--m_refCount == 0) { - DestroyJoystickDevice(); - delete m_instance; - m_instance = NULL; - } -} - - -bool SCA_Joystick::CreateJoystickDevice() -{ - bool init = false; - init = pCreateJoystickDevice(); - return init; -} - - -void SCA_Joystick::DestroyJoystickDevice() -{ - if(m_isinit) - pDestroyJoystickDevice(); -} - - -void SCA_Joystick::HandleEvents() -{ - if(m_isinit) - { - if(SDL_PollEvent(&m_private->m_event)) - { - switch(m_private->m_event.type) - { - case SDL_JOYAXISMOTION: - HANDLE_AXISMOTION(OnAxisMotion); - break; - case SDL_JOYHATMOTION: - HANDLE_HATMOTION(OnHatMotion); - break; - case SDL_JOYBUTTONUP: - HANDLE_BUTTONUP(OnButtonUp); - break; - case SDL_JOYBUTTONDOWN: - HANDLE_BUTTONDOWN(OnButtonDown); - break; - case SDL_JOYBALLMOTION: - HANDLE_BALLMOTION(OnBallMotion); - break; - default: - HANDLE_NOEVENT(OnNothing); - break; + int i; + for (i=0; iDestroyJoystickDevice(); + delete m_instance[i]; } + m_instance[i]= NULL; } + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ); } } - void SCA_Joystick::cSetPrecision(int val) { m_prec = val; @@ -226,76 +197,6 @@ int SCA_Joystick::pGetHat(int direction) return 0; } - -bool SCA_Joystick::GetJoyAxisMotion() -{ - bool result = false; - if(m_isinit){ - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYAXISMOTION: - result = true; - break; - } - } - } - return result; -} - - -bool SCA_Joystick::GetJoyButtonPress() -{ - bool result = false; - if(m_isinit){ - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYBUTTONDOWN: - result = true; - break; - } - } - } - return result; -} - - -bool SCA_Joystick::GetJoyButtonRelease() -{ - bool result = false; - if(m_isinit) - { - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYBUTTONUP: - result = true; - break; - } - } - } - return result; -} - - -bool SCA_Joystick::GetJoyHatMotion() -{ - bool result = false; - if(m_isinit){ - if(SDL_PollEvent(&m_private->m_event)){ - switch(m_private->m_event.type) - { - case SDL_JOYHATMOTION: - result = true; - break; - } - } - } - return 0; -} - - int SCA_Joystick::GetNumberOfAxes() { int number; @@ -334,42 +235,46 @@ int SCA_Joystick::GetNumberOfHats() return -1; } -bool SCA_Joystick::pCreateJoystickDevice() +bool SCA_Joystick::CreateJoystickDevice(void) { if(m_isinit == false){ - if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ) == -1 ){ - echo("Error-Initializing-SDL: " << SDL_GetError()); - return false; - } - if(SDL_NumJoysticks() > 0){ - for(int i=0; im_joystick = SDL_JoystickOpen(i); - SDL_JoystickEventState(SDL_ENABLE); - m_numjoys = i; - } - echo("Joystick-initialized"); - m_isinit = true; - return true; - }else{ - echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); + if (m_joyindex>=SDL_NumJoysticks()) { + // don't print a message, because this is done anyway + //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); return false; } + + m_private->m_joystick = SDL_JoystickOpen(m_joyindex); + SDL_JoystickEventState(SDL_ENABLE); + + echo("Joystick " << m_joyindex << " initialized"); + m_isinit = true; } - return false; + return true; } -void SCA_Joystick::pDestroyJoystickDevice() +void SCA_Joystick::DestroyJoystickDevice(void) { - echo("Closing-"); - for(int i=0; im_joystick); } + m_isinit = false; } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO ); } +int SCA_Joystick::Connected(void) +{ + if (m_isinit){ + if(SDL_JoystickOpened(m_joyindex)){ + return 1; + } + } + + return 0; +} void SCA_Joystick::pFillAxes() { diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h index 1e853070b09..bcbb43241c2 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h @@ -1,72 +1,37 @@ /** - * ***** 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): snailrose. - * - * ***** END GPL LICENSE BLOCK ***** - */ #ifndef _SCA_JOYSTICK_H_ - #define _SCA_JOYSTICK_H_ - - #include "SCA_JoystickDefines.h" - - - - +#include "SDL.h" /* - * Basic Joystick class * I will make this class a singleton because there should be only one joystick * even if there are more than one scene using it and count how many scene are using it. @@ -76,7 +41,7 @@ class SCA_Joystick { - static SCA_Joystick *m_instance; + static SCA_Joystick *m_instance[JOYINDEX_MAX]; static int m_refCount; class PrivateData; @@ -85,226 +50,135 @@ class SCA_Joystick int m_joyindex; - /*! - - * the number of avail joysticks - - */ - - int m_numjoys; - /* - *support for 2 axes - */ int m_axis10,m_axis11; - int m_axis20,m_axis21; - /* - + /* * Precision or range of the axes - */ - int m_prec; /* - * multiple axis values stored here - */ - int m_axisnum; - int m_axisvalue; /* - * max # of axes avail - */ - /*disabled - int m_axismax; - */ /* - * button values stored here - */ - int m_buttonnum; /* - * max # of buttons avail - */ int m_buttonmax; - /* - * hat values stored here - */ - int m_hatnum; - int m_hatdir; /* * max # of hats avail - disabled - int m_hatmax; - */ - /* is the joystick initialized ?*/ - bool m_isinit; - /* is triggered */ - bool m_istrig; /* - - * Open the joystick - - */ - - bool pCreateJoystickDevice(void); - - /* - - * Close the joystick - - */ - - void pDestroyJoystickDevice(void); - - - - /* - * event callbacks - */ - - void OnAxisMotion(void); - - void OnHatMotion(void); - - void OnButtonUp(void); - - void OnButtonDown(void); - - void OnNothing(void); - - void OnBallMotion(void){} + void OnAxisMotion(SDL_Event *sdl_event); + void OnHatMotion(SDL_Event *sdl_event); + void OnButtonUp(SDL_Event *sdl_event); + void OnButtonDown(SDL_Event *sdl_event); + void OnNothing(SDL_Event *sdl_event); + void OnBallMotion(SDL_Event *sdl_event){} /* - - * fills the axis mnember values - + * Open the joystick */ + bool CreateJoystickDevice(void); + /* + * Close the joystick + */ + void DestroyJoystickDevice(void); + + /* + * fills the axis mnember values + */ void pFillAxes(void); - - - void pFillButtons(void); /* - * returns m_axis10,m_axis11... - */ - int pGetAxis(int axisnum, int udlr); - + /* - * gets the current button - */ int pGetButtonPress(int button); /* - * returns if no button is pressed - */ - int pGetButtonRelease(int button); /* - * gets the current hat direction - */ - int pGetHat(int direction); - SCA_Joystick(); + SCA_Joystick(short int index); ~SCA_Joystick(); - bool CreateJoystickDevice(void); - - void DestroyJoystickDevice(void); - - public: - static SCA_Joystick *GetInstance(); - + static SCA_Joystick *GetInstance( short int joyindex ); + static void HandleEvents( void ); void ReleaseInstance(); - void HandleEvents(); - /* - */ bool aUpAxisIsPositive(int axis); - bool aDownAxisIsPositive(int axis); - bool aLeftAxisIsPositive(int axis); - bool aRightAxisIsPositive(int axis); - bool aButtonPressIsPositive(int button); - bool aButtonReleaseIsPositive(int button); - bool aHatIsPositive(int dir); /* - * precision is default '3200' which is overridden by input - */ void cSetPrecision(int val); - - int GetAxis10(void){ return m_axis10; @@ -312,80 +186,48 @@ public: } int GetAxis11(void){ - return m_axis11; - } int GetAxis20(void){ - return m_axis20; - } int GetAxis21(void){ - return m_axis21; - } int GetButton(void){ - return m_buttonnum; - } int GetHat(void){ - return m_hatdir; - } int GetThreshold(void){ - return m_prec; - } bool IsTrig(void){ - return m_istrig; - } - - /* - - * returns true if an event is being processed - - */ - - bool GetJoyAxisMotion(void); - - bool GetJoyButtonPress(void); - - bool GetJoyButtonRelease(void); - - bool GetJoyHatMotion(void); - - /* - * returns the # of... - */ int GetNumberOfAxes(void); - int GetNumberOfButtons(void); - int GetNumberOfHats(void); - - + /* + * Test if the joystick is connected + */ + int Connected(void); }; - +void Joystick_HandleEvents( void ); #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h index 15a421188b9..73ffe1406d9 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h @@ -38,12 +38,6 @@ #define echo(x) std::cout << x << std::endl; #endif -/* function callbacks */ -#define HANDLE_AXISMOTION(fn) ((fn)(), 0L) -#define HANDLE_HATMOTION(fn) ((fn)(), 0L) -#define HANDLE_BUTTONUP(fn) ((fn)(), 0L) -#define HANDLE_BUTTONDOWN(fn) ((fn)(), 0L) -#define HANDLE_BALLMOTION(fn) ((fn)(), 0L) -#define HANDLE_NOEVENT(fn) ((fn)(), 0L) +#define JOYINDEX_MAX 8 #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp index ab523470e21..1e064f55397 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp @@ -30,41 +30,75 @@ -void SCA_Joystick::OnAxisMotion(void) +void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event) { pFillAxes(); - m_axisnum = m_private->m_event.jaxis.axis; - m_axisvalue = m_private->m_event.jaxis.value; + m_axisnum = sdl_event->jaxis.axis; + m_axisvalue = sdl_event->jaxis.value; m_istrig = 1; } -void SCA_Joystick::OnHatMotion(void) +void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event) { - m_hatdir = m_private->m_event.jhat.value; - m_hatnum = m_private->m_event.jhat.hat; + m_hatdir = sdl_event->jhat.value; + m_hatnum = sdl_event->jhat.hat; m_istrig = 1; } -void SCA_Joystick::OnButtonUp(void) +void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event) { m_buttonnum = -2; } -void SCA_Joystick::OnButtonDown(void) +void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event) { m_buttonmax = GetNumberOfButtons(); - if(m_private->m_event.jbutton.button >= 1 || m_private->m_event.jbutton.button <= m_buttonmax) + if(sdl_event->jbutton.button >= 1 || sdl_event->jbutton.button <= m_buttonmax) { m_istrig = 1; - m_buttonnum = m_private->m_event.jbutton.button; + m_buttonnum = sdl_event->jbutton.button; } } -void SCA_Joystick::OnNothing(void) +void SCA_Joystick::OnNothing(SDL_Event* sdl_event) { m_istrig = 0; } + +/* only handle events for 1 joystick */ + +void SCA_Joystick::HandleEvents(void) +{ + SDL_Event sdl_event; + + if(SDL_PollEvent(&sdl_event)) + { + /* Note! m_instance[sdl_event.jaxis.which] + * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */ + switch(sdl_event.type) + { + case SDL_JOYAXISMOTION: + SCA_Joystick::m_instance[sdl_event.jaxis.which]->OnAxisMotion(&sdl_event); + break; + case SDL_JOYHATMOTION: + SCA_Joystick::m_instance[sdl_event.jhat.which]->OnHatMotion(&sdl_event); + break; + case SDL_JOYBUTTONUP: + SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonUp(&sdl_event); + break; + case SDL_JOYBUTTONDOWN: + SCA_Joystick::m_instance[sdl_event.jbutton.which]->OnButtonDown(&sdl_event); + break; + case SDL_JOYBALLMOTION: + SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event); + break; + default: + printf("SCA_Joystick::HandleEvents, Unknown SDL event, this should not happen\n"); + break; + } + } +} diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h index 23fad3cd55d..bb6bfe2d4cc 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickPrivate.h @@ -32,10 +32,6 @@ class SCA_Joystick::PrivateData { public: - /* - * SDL events structure - */ - SDL_Event m_event; /* * The Joystick */ diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile index b3eae5d67dc..355ece6e8bd 100644 --- a/source/gameengine/GameLogic/Makefile +++ b/source/gameengine/GameLogic/Makefile @@ -42,6 +42,7 @@ CPPFLAGS += -I../Expressions CPPFLAGS += -I../Rasterizer CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += $(NAN_SDLCFLAGS) diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 96a770a553f..9ec4ea00337 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -23,8 +23,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( : SCA_IActuator(gameobj, T), m_type(type), m_flag(flag), - m_int_arg(int_arg), m_float_arg(float_arg), + m_int_arg(int_arg), m_rasterizer(rasterizer), m_rendertools(rendertools) { @@ -64,13 +64,11 @@ bool SCA_2DFilterActuator::Update() if( m_type == RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR ) { if(!m_flag) - { m_rasterizer->EnableMotionBlur(m_float_arg); - } else - { m_rasterizer->DisableMotionBlur(); - } + + return false; } else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS) { diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index 8f156cc63e7..0bd20117f31 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -188,6 +188,8 @@ void SCA_IController::ApplyState(unsigned int state) for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { (*sensit)->IncLink(); + // remember that this controller just activated that sensor + (*sensit)->AddNewController(this); } SetActive(true); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index f5512664d8f..abd049e9d64 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -27,6 +27,7 @@ */ #include "SCA_ILogicBrick.h" +#include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H #include diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index f99b9b789d7..084b1395159 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -32,6 +32,8 @@ #include "SCA_ISensor.h" #include "SCA_EventManager.h" #include "SCA_LogicManager.h" +// needed for IsTriggered() +#include "SCA_PythonController.h" #ifdef HAVE_CONFIG_H #include @@ -132,10 +134,8 @@ void SCA_ISensor::DecLink() { } if (!m_links) { - // sensor is detached from all controllers, initialize it so that it - // is fresh as at startup when it is reattached again. + // sensor is detached from all controllers, remove it from manager UnregisterToManager(); - Init(); } } @@ -168,7 +168,9 @@ PyParentObject SCA_ISensor::Parents[] = { }; PyMethodDef SCA_ISensor::Methods[] = { {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, - METH_VARARGS, IsPositive_doc}, + METH_NOARGS, IsPositive_doc}, + {"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered, + METH_VARARGS, IsTriggered_doc}, {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, METH_NOARGS, GetUsePosPulseMode_doc}, {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, @@ -204,6 +206,9 @@ SCA_ISensor::_getattr(const STR_String& attr) void SCA_ISensor::RegisterToManager() { + // sensor is just activated, initialize it + Init(); + m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); m_eventmgr->RegisterSensor(this); } @@ -221,6 +226,9 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) bool result = this->Evaluate(event); if (result) { logicmgr->AddActivatedSensor(this); + // reset these counters so that pulse are synchronized with transition + m_pos_ticks = 0; + m_neg_ticks = 0; } else { /* First, the pulsing behaviour, if pulse mode is @@ -249,19 +257,47 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) } } } + if (!m_newControllers.empty()) + { + if (!IsActive() && m_level) + { + // This level sensor is connected to at least one controller that was just made + // active but it did not generate an event yet, do it now to those controllers only + for (std::vector::iterator ci=m_newControllers.begin(); + ci != m_newControllers.end(); ci++) + { + logicmgr->AddTriggeredController(*ci, this); + } + } + // clear the list. Instead of using clear, which also release the memory, + // use erase, which keeps the memory available for next time. + m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); + } } } /* Python functions: */ char SCA_ISensor::IsPositive_doc[] = "isPositive()\n" -"\tReturns whether the sensor is registered a positive event.\n"; -PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds) +"\tReturns whether the sensor is in an active state.\n"; +PyObject* SCA_ISensor::PyIsPositive(PyObject* self) { int retval = IsPositiveTrigger(); return PyInt_FromLong(retval); } +char SCA_ISensor::IsTriggered_doc[] = +"isTriggered()\n" +"\tReturns whether the sensor has triggered the current controller.\n"; +PyObject* SCA_ISensor::PyIsTriggered(PyObject* self) +{ + // check with the current controller + int retval = 0; + if (SCA_PythonController::m_sCurrentController) + retval = SCA_PythonController::m_sCurrentController->IsTriggered(this); + return PyInt_FromLong(retval); +} + /** * getUsePulseMode: getter for the pulse mode (KX_TRUE = on) */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index fc8f0bd0011..0d65270dc7b 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -34,6 +34,8 @@ #include "SCA_ILogicBrick.h" +#include + /** * Interface Class for all logic Sensors. Implements * pulsemode,pulsefrequency */ @@ -73,9 +75,9 @@ class SCA_ISensor : public SCA_ILogicBrick /** number of connections to controller */ int m_links; - /** Pass the activation on to the logic manager.*/ - void SignalActivation(class SCA_LogicManager* logicmgr); - + /** list of controllers that have just activated this sensor because of a state change */ + std::vector m_newControllers; + public: SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, @@ -128,6 +130,8 @@ public: /** Resume sensing. */ void Resume(); + void AddNewController(class SCA_IController* controller) + { m_newControllers.push_back(controller); } void ClrLink() { m_links = 0; } void IncLink() @@ -137,7 +141,8 @@ public: { return !m_links; } /* Python functions: */ - KX_PYMETHOD_DOC(SCA_ISensor,IsPositive); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode); KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode); KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency); diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index 8ff28ba0b51..a86770a6e0a 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -40,35 +40,48 @@ SCA_JoystickManager::SCA_JoystickManager(class SCA_LogicManager* logicmgr) : SCA_EventManager(JOY_EVENTMGR), m_logicmgr(logicmgr) { - m_joystick = SCA_Joystick::GetInstance(); + int i; + for (i=0; iReleaseInstance(); + int i; + for (i=0; iReleaseInstance(); + } } void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - set::iterator it; - for (it = m_sensors.begin(); it != m_sensors.end(); it++) - { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); - if(!joysensor->IsSuspended()) + if (m_sensors.size()==0) { + return; + } + else { + set::iterator it; + + SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */ + + for (it = m_sensors.begin(); it != m_sensors.end(); it++) { - m_joystick->HandleEvents(); - joysensor->Activate(m_logicmgr, NULL); + SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); + if(!joysensor->IsSuspended()) + { + joysensor->Activate(m_logicmgr, NULL); + } } } } -SCA_Joystick *SCA_JoystickManager::GetJoystickDevice() +SCA_Joystick *SCA_JoystickManager::GetJoystickDevice( short int joyindex) { /* *Return the instance of SCA_Joystick for use */ - return m_joystick; + return m_joystick[joyindex]; } diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.h b/source/gameengine/GameLogic/SCA_JoystickManager.h index f2bb27965fa..d3a7ac95bea 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.h +++ b/source/gameengine/GameLogic/SCA_JoystickManager.h @@ -40,12 +40,12 @@ class SCA_JoystickManager : public SCA_EventManager /** * SDL Joystick Class Instance */ - SCA_Joystick *m_joystick; + SCA_Joystick *m_joystick[JOYINDEX_MAX]; public: SCA_JoystickManager(class SCA_LogicManager* logicmgr); virtual ~SCA_JoystickManager(); virtual void NextFrame(double curtime,double deltatime); - SCA_Joystick* GetJoystickDevice(void); + SCA_Joystick* GetJoystickDevice(short int joyindex); }; diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 3fb439eb25b..3c08710c6ce 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -30,8 +30,11 @@ #include "SCA_EventManager.h" #include "SCA_LogicManager.h" +#include "PyObjectPlus.h" + #include + #ifdef HAVE_CONFIG_H #include #endif @@ -39,6 +42,7 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, SCA_IObject* gameobj, + short int joyindex, short int joymode, int axis, int axisf,int prec, int button, int buttonf, @@ -53,7 +57,8 @@ SCA_JoystickSensor::SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, m_hat(hat), m_hatf(hatf), m_precision(prec), - m_joymode(joymode) + m_joymode(joymode), + m_joyindex(joyindex) { /* std::cout << " axis " << m_axis << std::endl; @@ -99,10 +104,13 @@ bool SCA_JoystickSensor::IsPositiveTrigger() bool SCA_JoystickSensor::Evaluate(CValue* event) { - SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(); + SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex); bool result = false; bool reset = m_reset && m_level; + if(js==NULL) + return false; + m_reset = false; switch(m_joymode) { @@ -118,7 +126,7 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) js->cSetPrecision(m_precision); if(m_axisf == 1){ if(js->aUpAxisIsPositive(m_axis)){ - m_istrig =1; + m_istrig = 1; result = true; }else{ if(m_istrig){ @@ -241,11 +249,31 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) printf("Error invalid switch statement\n"); break; } - if(!js->IsTrig()){ + + if (js->IsTrig()) { + /* The if below detects changes with the joystick trigger state. + * js->IsTrig() will stay true as long as the key is held. + * even though the event from SDL will only be sent once. + * (js->IsTrig() && m_istrig_lastjs) - when true it means this sensor + * had the same joystick trigger state last time, + * Setting the result false this time means it wont run the sensors + * controller every time (like a pulse sensor) + * + * This is not done with the joystick its self incase other sensors use + * it or become active. + */ + if (m_istrig_lastjs) { + result = false; + } + m_istrig_lastjs = true; + } else { m_istrig = 0; + m_istrig_lastjs = false; } + if (reset) result = true; + return result; } @@ -293,6 +321,8 @@ PyParentObject SCA_JoystickSensor::Parents[] = { PyMethodDef SCA_JoystickSensor::Methods[] = { + {"getIndex", (PyCFunction) SCA_JoystickSensor::sPyGetIndex, METH_NOARGS, GetIndex_doc}, + {"setIndex", (PyCFunction) SCA_JoystickSensor::sPySetIndex, METH_O, SetIndex_doc}, {"getAxis", (PyCFunction) SCA_JoystickSensor::sPyGetAxis, METH_NOARGS, GetAxis_doc}, {"setAxis", (PyCFunction) SCA_JoystickSensor::sPySetAxis, METH_VARARGS, SetAxis_doc}, {"getAxisValue", (PyCFunction) SCA_JoystickSensor::sPyGetRealAxis, METH_NOARGS, GetRealAxis_doc}, @@ -305,6 +335,7 @@ PyMethodDef SCA_JoystickSensor::Methods[] = { {"getNumAxes", (PyCFunction) SCA_JoystickSensor::sPyNumberOfAxes, METH_NOARGS, NumberOfAxes_doc}, {"getNumButtons",(PyCFunction) SCA_JoystickSensor::sPyNumberOfButtons,METH_NOARGS, NumberOfButtons_doc}, {"getNumHats", (PyCFunction) SCA_JoystickSensor::sPyNumberOfHats, METH_NOARGS, NumberOfHats_doc}, + {"isConnected", (PyCFunction) SCA_JoystickSensor::sPyConnected, METH_NOARGS, Connected_doc}, {NULL,NULL} //Sentinel }; @@ -314,14 +345,36 @@ PyObject* SCA_JoystickSensor::_getattr(const STR_String& attr) { } +/* get index ---------------------------------------------------------- */ +char SCA_JoystickSensor::GetIndex_doc[] = +"getIndex\n" +"\tReturns the joystick index to use.\n"; +PyObject* SCA_JoystickSensor::PyGetIndex( PyObject* self ) { + return PyInt_FromLong(m_joyindex); +} + + +/* set index ---------------------------------------------------------- */ +char SCA_JoystickSensor::SetIndex_doc[] = +"setIndex\n" +"\tSets the joystick index to use.\n"; +PyObject* SCA_JoystickSensor::PySetIndex( PyObject* self, PyObject* value ) { + int index = PyInt_AsLong( 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; + } + + m_joyindex = index; + Py_RETURN_NONE; +} + /* get axis ---------------------------------------------------------- */ char SCA_JoystickSensor::GetAxis_doc[] = "getAxis\n" "\tReturns the current state of the axis.\n"; -PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self, - PyObject* args, - PyObject* kwds) { - return Py_BuildValue("[ii]",m_axis, m_axisf); +PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self) { + return PyInt_FromLong(m_joyindex); } @@ -329,9 +382,7 @@ PyObject* SCA_JoystickSensor::PyGetAxis( PyObject* self, char SCA_JoystickSensor::SetAxis_doc[] = "setAxis\n" "\tSets the current state of the axis.\n"; -PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, PyObject* args ) { int axis,axisflag; if(!PyArg_ParseTuple(args, "ii", &axis, &axisflag)){ @@ -339,7 +390,7 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, } m_axis = axis; m_axisf = axisflag; - Py_Return; + Py_RETURN_NONE; } @@ -347,16 +398,12 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* self, char SCA_JoystickSensor::GetRealAxis_doc[] = "getAxisValue\n" "\tReturns a list of the values for each axis .\n"; -PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self, - PyObject* args, - PyObject* kwds) { - int a,b,c,d; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - a = joy->GetAxis10(); - b = joy->GetAxis11(); - c = joy->GetAxis20(); - d = joy->GetAxis21(); - return Py_BuildValue("[iiii]",a,b,c,d); +PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + if(joy) + return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); + else + return Py_BuildValue("[iiii]", 0, 0, 0, 0); } @@ -364,10 +411,8 @@ PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self, char SCA_JoystickSensor::GetThreshold_doc[] = "getThreshold\n" "\tReturns the threshold of the axis.\n"; -PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self, - PyObject* args, - PyObject* kwds) { - return Py_BuildValue("i", m_precision); +PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self) { + return PyInt_FromLong(m_precision); } @@ -375,15 +420,13 @@ PyObject* SCA_JoystickSensor::PyGetThreshold( PyObject* self, char SCA_JoystickSensor::SetThreshold_doc[] = "setThreshold\n" "\tSets the threshold of the axis.\n"; -PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, PyObject* args ) { int thresh; if(!PyArg_ParseTuple(args, "i", &thresh)){ return NULL; } m_precision = thresh; - Py_Return; + Py_RETURN_NONE; } @@ -391,9 +434,7 @@ PyObject* SCA_JoystickSensor::PySetThreshold( PyObject* self, char SCA_JoystickSensor::GetButton_doc[] = "getButton\n" "\tReturns the currently pressed button.\n"; -PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self) { return Py_BuildValue("[ii]",m_button, m_buttonf); } @@ -402,16 +443,14 @@ PyObject* SCA_JoystickSensor::PyGetButton( PyObject* self, char SCA_JoystickSensor::SetButton_doc[] = "setButton\n" "\tSets the button the sensor reacts to.\n"; -PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, PyObject* args ) { int button,buttonflag; if(!PyArg_ParseTuple(args, "ii", &button, &buttonflag)){ return NULL; } m_button = button; m_buttonf = buttonflag; - Py_Return; + Py_RETURN_NONE; } @@ -419,9 +458,7 @@ PyObject* SCA_JoystickSensor::PySetButton( PyObject* self, char SCA_JoystickSensor::GetHat_doc[] = "getHat\n" "\tReturns the current direction of the hat.\n"; -PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self ) { return Py_BuildValue("[ii]",m_hat, m_hatf); } @@ -430,16 +467,14 @@ PyObject* SCA_JoystickSensor::PyGetHat( PyObject* self, char SCA_JoystickSensor::SetHat_doc[] = "setHat\n" "\tSets the hat the sensor reacts to.\n"; -PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, PyObject* args ) { int hat,hatflag; if(!PyArg_ParseTuple(args, "ii", &hat, &hatflag)){ return NULL; } m_hat = hat; m_hatf = hatflag; - Py_Return; + Py_RETURN_NONE; } @@ -447,37 +482,34 @@ PyObject* SCA_JoystickSensor::PySetHat( PyObject* self, char SCA_JoystickSensor::NumberOfAxes_doc[] = "getNumAxes\n" "\tReturns the number of axes .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self, - PyObject* args, - PyObject* kwds) { - int num; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - num = joy->GetNumberOfAxes(); - return Py_BuildValue("i",num); +PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { + 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 ); } char SCA_JoystickSensor::NumberOfButtons_doc[] = "getNumButtons\n" "\tReturns the number of buttons .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self, - PyObject* args, - PyObject* kwds) { - int num; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - num = joy->GetNumberOfButtons(); - return Py_BuildValue("i",num); +PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } char SCA_JoystickSensor::NumberOfHats_doc[] = "getNumHats\n" "\tReturns the number of hats .\n"; -PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self, - PyObject* args, - PyObject* kwds) { - int num; - SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(); - num = joy->GetNumberOfHats(); - return Py_BuildValue("i",num); +PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); +} + +char SCA_JoystickSensor::Connected_doc[] = +"getConnected\n" +"\tReturns True if a joystick is connected at this joysticks index.\n"; +PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) { + SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); + return PyBool_FromLong( joy ? joy->Connected() : 0 ); } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index 69068da6494..8b74f6e0296 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -68,10 +68,20 @@ class SCA_JoystickSensor :public SCA_ISensor * Is an event triggered ? */ bool m_istrig; + /** + * Last trigger state for this sensors joystick, + * Otherwise it will trigger all the time + * this is used to see if the trigger state changes. + */ + bool m_istrig_lastjs; /** * The mode to determine axis,button or hat */ short int m_joymode; + /** + * Select which joystick to use + */ + short int m_joyindex; enum KX_JOYSENSORMODE { KX_JOYSENSORMODE_NODEF = 0, @@ -85,6 +95,7 @@ class SCA_JoystickSensor :public SCA_ISensor public: SCA_JoystickSensor(class SCA_JoystickManager* eventmgr, SCA_IObject* gameobj, + short int joyindex, short int joymode, int axis, int axisf,int prec, int button, int buttonf, @@ -97,28 +108,36 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); + short int GetJoyIndex(void){ + return m_joyindex; + } + /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* _getattr(const STR_String& attr); + /* Joystick Index */ + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetIndex); + KX_PYMETHOD_DOC_O(SCA_JoystickSensor,SetIndex); /* Axes*/ - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetAxis); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetAxis); - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetRealAxis); - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetThreshold); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetThreshold); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetAxis); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetAxis); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetRealAxis); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetThreshold); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetThreshold); /* Buttons */ - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetButton); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetButton); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetButton); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetButton); /* Hats */ - KX_PYMETHOD_DOC(SCA_JoystickSensor,GetHat); - KX_PYMETHOD_DOC(SCA_JoystickSensor,SetHat); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,GetHat); + KX_PYMETHOD_DOC_VARARGS(SCA_JoystickSensor,SetHat); /* number of */ - KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfAxes); - KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfButtons); - KX_PYMETHOD_DOC(SCA_JoystickSensor,NumberOfHats); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfAxes); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfButtons); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,NumberOfHats); + KX_PYMETHOD_DOC_NOARGS(SCA_JoystickSensor,Connected); }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index a7a6fa93db4..fba1162993d 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -505,7 +505,7 @@ PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self, PyObject* kwds) { // printf("sPyIsPositive\n"); - return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds); + return ((SCA_KeyboardSensor*) self)->PyIsPositive(self); } diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 91e66aea359..b584b37180f 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -33,6 +33,7 @@ #include "SCA_IController.h" #include "SCA_IActuator.h" #include "SCA_EventManager.h" +#include "SCA_PythonController.h" #include #ifdef HAVE_CONFIG_H @@ -232,8 +233,6 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) // for this frame, look up for activated sensors, and build the collection of triggered controllers // int numsensors = this->m_activatedsensors.size(); /*unused*/ - set triggeredControllerSet; - for (vector::const_iterator is=m_activatedsensors.begin(); !(is==m_activatedsensors.end());is++) { @@ -244,19 +243,28 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) { SCA_IController* contr = *c;//controllerarray->at(c); if (contr->IsActive()) - triggeredControllerSet.insert(SmartControllerPtr(contr,0)); + { + m_triggeredControllerSet.insert(SmartControllerPtr(contr,0)); + // So that the controller knows which sensor has activited it. + // Only needed for the python controller though. + if (contr->GetType() == &SCA_PythonController::Type) + { + SCA_PythonController* pythonController = (SCA_PythonController*)contr; + pythonController->AddTriggeredSensor(sensor); + } + } } //sensor->SetActive(false); } // int numtriggered = triggeredControllerSet.size(); /*unused*/ - for (set::iterator tit=triggeredControllerSet.begin(); - !(tit==triggeredControllerSet.end());tit++) + for (set::iterator tit=m_triggeredControllerSet.begin(); + !(tit==m_triggeredControllerSet.end());tit++) { (*tit)->Trigger(this); } - triggeredControllerSet.clear(); + m_triggeredControllerSet.clear(); } @@ -382,6 +390,17 @@ void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor) } } +void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor) +{ + m_triggeredControllerSet.insert(SmartControllerPtr(controller,0)); + // so that the controller knows which sensor has activited it + // only needed for python controller + if (controller->GetType() == &SCA_PythonController::Type) + { + SCA_PythonController* pythonController = (SCA_PythonController*)controller; + pythonController->AddTriggeredSensor(sensor); + } +} void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event) diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index e0d3d506702..50383879d8f 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -99,6 +99,7 @@ class SCA_LogicManager vector m_activatedsensors; set m_activeActuators; + set m_triggeredControllerSet; map m_sensorcontrollermapje; @@ -127,6 +128,7 @@ public: void EndFrame(); void AddActivatedSensor(SCA_ISensor* sensor); void AddActiveActuator(SCA_IActuator* sensor,class CValue* event); + void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor); SCA_EventManager* FindEventManager(int eventmgrtype); void RemoveGameObject(const STR_String& gameobjname); diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index f9081c90288..6e9a0a7c6b6 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -33,8 +33,11 @@ #include "SCA_LogicManager.h" #include "SCA_ISensor.h" #include "SCA_IActuator.h" +#include "PyObjectPlus.h" #include "compile.h" #include "eval.h" +#include + #ifdef HAVE_CONFIG_H #include @@ -139,6 +142,14 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */ } +int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) +{ + if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) != + m_triggeredSensors.end()) + return 1; + return 0; +} + #if 0 static char* sPyGetCurrentController__doc__; #endif @@ -294,7 +305,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) // something in this dictionary and crash? PyDict_Clear(excdict); Py_DECREF(excdict); - + m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end()); m_sCurrentController = NULL; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index 39b6c68c359..1b62e7ecb53 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -36,6 +36,8 @@ #include "SCA_LogicManager.h" #include "BoolValue.h" +#include + class SCA_IObject; class SCA_PythonController : public SCA_IController { @@ -47,6 +49,7 @@ class SCA_PythonController : public SCA_IController STR_String m_scriptText; STR_String m_scriptName; PyObject* m_pythondictionary; + std::vector m_triggeredSensors; public: static SCA_PythonController* m_sCurrentController; // protected !!! @@ -64,6 +67,9 @@ class SCA_PythonController : public SCA_IController void SetScriptText(const STR_String& text); void SetScriptName(const STR_String& name); void SetDictionary(PyObject* pythondictionary); + void AddTriggeredSensor(class SCA_ISensor* sensor) + { m_triggeredSensors.push_back(sensor); } + int IsTriggered(class SCA_ISensor* sensor); static char* sPyGetCurrentController__doc__; static PyObject* sPyGetCurrentController(PyObject* self); diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt index ff1040bfb40..fc5912155cf 100644 --- a/source/gameengine/GamePlayer/CMakeLists.txt +++ b/source/gameengine/GamePlayer/CMakeLists.txt @@ -25,3 +25,7 @@ # ***** END GPL LICENSE BLOCK ***** SUBDIRS(common ghost) + +IF(WITH_WEBPLUGIN) + SUBDIRS(xembed) +ENDIF(WITH_WEBPLUGIN) diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt index e26f8b9d69a..0c6c4179e2d 100644 --- a/source/gameengine/GamePlayer/common/CMakeLists.txt +++ b/source/gameengine/GamePlayer/common/CMakeLists.txt @@ -30,7 +30,6 @@ SET(SRC GPC_Engine.cpp GPC_KeyboardDevice.cpp GPC_MouseDevice.cpp - GPC_PolygonMaterial.cpp GPC_RawImage.cpp GPC_RawLoadDotBlendArray.cpp GPC_RawLogoArrays.cpp @@ -69,6 +68,7 @@ SET(INC ../../../../source/gameengine/GamePlayer/ghost ../../../../source/blender/misc ../../../../source/blender/blenloader + ../../../../source/blender/gpu ../../../../extern/glew/include ${PYTHON_INC} ${SOLID_INC} diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index 8b828393c67..78d8eaf2aa3 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -27,141 +27,256 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include - -#ifdef WIN32 -#pragma warning (disable : 4786) -#include -#endif - #include "GL/glew.h" -#include - -#include "GPC_RenderTools.h" - #include "RAS_IRenderTools.h" #include "RAS_IRasterizer.h" #include "RAS_LightObject.h" #include "RAS_ICanvas.h" #include "RAS_GLExtensionManager.h" -// next two includes/dependencies come from the shadow feature -// it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" - -#include "GPC_PolygonMaterial.h" #include "KX_PolygonMaterial.h" -#include "Value.h" - -//#include "KX_BlenderGL.h" // for text printing -//#include "KX_BlenderClientObject.h" -#include "STR_String.h" -#include "RAS_BucketManager.h" // for polymaterial (needed for textprinting) - - -// Blender includes -/* This list includes only data type definitions */ -#include "DNA_object_types.h" -#include "DNA_material_types.h" -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_group_types.h" -#include "DNA_scene_types.h" -#include "DNA_camera_types.h" -#include "DNA_property_types.h" -#include "DNA_text_types.h" -#include "DNA_sensor_types.h" -#include "DNA_controller_types.h" -#include "DNA_actuator_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" - -#include "BKE_global.h" -#include "BKE_image.h" -#include "BKE_bmfont.h" -#include "BKE_bmfont_types.h" -#include "BKE_main.h" - -#include "IMB_imbuf_types.h" -// End of Blender includes - -#include "KX_Scene.h" +#include "KX_BlenderMaterial.h" #include "KX_RayCast.h" #include "KX_IPhysicsController.h" + #include "PHY_IPhysicsEnvironment.h" -#include "KX_BlenderMaterial.h" + +#include "STR_String.h" + +#include "GPU_draw.h" + +#include "BKE_bmfont.h" // for text printing +#include "BKE_bmfont_types.h" + +#include "GPC_RenderTools.h" + +unsigned int GPC_RenderTools::m_numgllights; GPC_RenderTools::GPC_RenderTools() { m_font = BMF_GetFont(BMF_kHelvetica10); + glGetIntegerv(GL_MAX_LIGHTS, (GLint*) &m_numgllights); if (m_numgllights < 8) m_numgllights = 8; } - GPC_RenderTools::~GPC_RenderTools() { } +void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) +{ + m_clientobject = NULL; + m_lastlightlayer = -1; + m_lastlighting = false; + DisableOpenGLLights(); +} void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty) { } +/* ProcessLighting performs lighting on objects. the layer is a bitfield that + * contains layer information. There are 20 'official' layers in blender. A + * light is applied on an object only when they are in the same layer. OpenGL + * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in + * a scene. */ -void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) +void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) { - m_clientobject=NULL; - m_modified=true; - DisableOpenGLLights(); + if(m_lastlightlayer == layer) + return; -} + m_lastlightlayer = layer; -int GPC_RenderTools::ProcessLighting(int layer) -{ - int result = false; + bool enable = false; - if (layer < 0) - { - DisableOpenGLLights(); - result = false; - } else + if (layer >= 0) { if (m_clientobject) - { - if (applyLights(layer)) - { - EnableOpenGLLights(); - result = true; - } else - { - DisableOpenGLLights(); - result = false; - } + { + if (layer == RAS_LIGHT_OBJECT_LAYER) + layer = static_cast(m_clientobject)->GetLayer(); + + enable = applyLights(layer, viewmat); } } - return result; + + if(enable) + EnableOpenGLLights(); + else + DisableOpenGLLights(); } void GPC_RenderTools::EnableOpenGLLights() { + if(m_lastlighting == true) + return; + glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); + + m_lastlighting = true; } -void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height) +void GPC_RenderTools::DisableOpenGLLights() +{ + if(m_lastlighting == false) + return; + + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + + m_lastlighting = false; +} + + +void GPC_RenderTools::SetClientObject(RAS_IRasterizer *rasty, void* obj) +{ + if (m_clientobject != obj) + { + bool ccw = (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()); + rasty->SetFrontFace(ccw); + + m_clientobject = obj; + } +} + +bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) +{ + double* const oglmatrix = (double* const) data; + MT_Point3 resultpoint(result->m_hitPoint); + MT_Vector3 resultnormal(result->m_hitNormal); + MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); + MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); + left = (dir.cross(resultnormal)).safe_normalized(); + // for the up vector, we take the 'resultnormal' returned by the physics + + double maat[16]={ + left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + resultnormal[0],resultnormal[1],resultnormal[2], 0, + 0, 0, 0, 1}; + glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); + //glMultMatrixd(oglmatrix); + glMultMatrixd(maat); + return true; +} + +void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) +{ + /* FIXME: + blender: intern/moto/include/MT_Vector3.inl:42: MT_Vector3 operator/(const + MT_Vector3&, double): Assertion `!MT_fuzzyZero(s)' failed. + + Program received signal SIGABRT, Aborted. + [Switching to Thread 16384 (LWP 1519)] + 0x40477571 in kill () from /lib/libc.so.6 + (gdb) bt + #7 0x08334368 in MT_Vector3::normalized() const () + #8 0x0833e6ec in GPC_RenderTools::applyTransform(RAS_IRasterizer*, double*, int) () + */ + + if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || + objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) + { + // rotate the billboard/halo + //page 360/361 3D Game Engine Design, David Eberly for a discussion + // on screen aligned and axis aligned billboards + // assumed is that the preprocessor transformed all billboard polygons + // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) + // when new parenting for objects is done, this rotation + // will be moved into the object + + MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); + MT_Point3 campos = rasty->GetCameraPosition(); + MT_Vector3 dir = (campos - objpos).safe_normalized(); + MT_Vector3 up(0,0,1.0); + + KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; + // get scaling of halo object + MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); + + bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned + if (screenaligned) + { + up = (up - up.dot(dir) * dir).safe_normalized(); + } else + { + dir = (dir - up.dot(dir)*up).safe_normalized(); + } + + MT_Vector3 left = dir.normalized(); + dir = (left.cross(up)).normalized(); + + // we have calculated the row vectors, now we keep + // local scaling into account: + + left *= size[0]; + dir *= size[1]; + up *= size[2]; + double maat[16]={ + left[0], left[1],left[2], 0, + dir[0], dir[1],dir[2],0, + up[0],up[1],up[2],0, + 0,0,0,1}; + glTranslated(objpos[0],objpos[1],objpos[2]); + glMultMatrixd(maat); + + } else + { + if (objectdrawmode & RAS_IPolyMaterial::SHADOW) + { + // shadow must be cast to the ground, physics system needed here! + MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); + KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; + MT_Vector3 direction = MT_Vector3(0,0,-1); + + direction.normalize(); + direction *= 100000; + + MT_Point3 topoint = frompoint + direction; + + KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; + PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); + KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); + + KX_GameObject *parent = gameobj->GetParent(); + if (!physics_controller && parent) + physics_controller = parent->GetPhysicsController(); + if (parent) + parent->Release(); + + KX_RayCast::Callback callback(this, physics_controller, oglmatrix); + if (!KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback)) + { + // couldn't find something to cast the shadow on... + glMultMatrixd(oglmatrix); + } + } else + { + + // 'normal' object + glMultMatrixd(oglmatrix); + } + } +} + + +void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height) { STR_String tmpstr(text); int lines; @@ -234,21 +349,19 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, glDisable(GL_LIGHTING); } -/** - * Copied from KX_BlenderRenderTools.cpp in KX_blenderhook - * Renders text into a (series of) polygon(s), using a texture font, - * Each character consists of one polygon (one quad or two triangles) - */ +/* Render Text renders text into a (series of) polygon, using a texture font, + * Each character consists of one polygon (one quad or two triangles) */ + void GPC_RenderTools::RenderText( int mode, RAS_IPolyMaterial* polymat, - float v1[3], float v2[3], float v3[3], float v4[3]) + float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); struct MTFace* tface = 0; - unsigned int* col = 0; + unsigned int *col = 0; if(flag & RAS_BLENDERMAT) { KX_BlenderMaterial *bl_mat = static_cast(polymat); @@ -259,110 +372,29 @@ void GPC_RenderTools::RenderText( tface = blenderpoly->GetMTFace(); col = blenderpoly->GetMCol(); } - - BL_RenderText(mode, mytext, mytext.Length(), tface, col, v1, v2, v3, v4); -} - - - -/** - * Copied from KX_BlenderGL.cpp in KX_blenderhook - */ -void GPC_RenderTools::BL_RenderText( - int mode, - const char* textstr, - int textlen, - struct MTFace* tface, - unsigned int* col, - float v1[3],float v2[3],float v3[3],float v4[3]) -{ - struct Image* ima; - - if (mode & TF_BMFONT) { - //char string[MAX_PROPSTRING]; -// float tmat[4][4]; - int characters, index, character; - float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance; - -// bProperty *prop; - - // string = "Frank van Beek"; - - characters = textlen; - - ima = (struct Image*) tface->tpage; - if (ima == NULL) { - characters = 0; - } - - if(!col) glColor3f(1.0f, 1.0f, 1.0f); - - glPushMatrix(); - for (index = 0; index < characters; index++) { - // lets calculate offset stuff - character = textstr[index]; - - // space starts at offset 1 - // character = character - ' ' + 1; - - matrixGlyph((ImBuf *)ima->ibufs.first, character, & centerx, ¢ery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance); - - glBegin(GL_POLYGON); - // printf(" %c %f %f %f %f\n", character, tface->uv[0][0], tface->uv[0][1], ); - // glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy); - - if(col) BL_spack(col[0]); - // glVertex3fv(v1); - glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]); - - glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy); - if(col) BL_spack(col[1]); - // glVertex3fv(v2); - glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]); - glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy); - if(col) BL_spack(col[2]); - // glVertex3fv(v3); - glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]); - - if(v4) { - // glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, 1.0 - (1.0 - tface->uv[3][1]) * sizey - transy); - glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy); - if(col) BL_spack(col[3]); - // glVertex3fv(v4); - glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]); - } - glEnd(); - - glTranslatef(advance, 0.0, 0.0); - } - glPopMatrix(); - - } + GPU_render_text(tface, mode, mytext, mytext.Length(), col, v1, v2, v3, v4, glattrib); } -RAS_IPolyMaterial* GPC_RenderTools::CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba,const STR_String& matname,int tile,int tilexrep,int tileyrep,int mode,bool transparant, bool zsort, - int lightlayer,bool bIsTriangle,void* clientobject,void* tface) +void GPC_RenderTools::PushMatrix() { - assert(!"Deprecated"); -/* return new GPC_PolygonMaterial(texname, ba,matname,tile,tilexrep,tileyrep, - mode,transparant,zsort,lightlayer,bIsTriangle,clientobject,tface); - */ - return NULL; + glPushMatrix(); +} + +void GPC_RenderTools::PopMatrix() +{ + glPopMatrix(); } -int GPC_RenderTools::applyLights(int objectlayer) +int GPC_RenderTools::applyLights(int objectlayer, const MT_Transform& viewmat) { -// taken from blender source, incompatibility between Blender Object / GameObject - - int count; + // taken from blender source, incompatibility between Blender Object / GameObject + float glviewmat[16]; + unsigned int count; float vec[4]; - + vec[3]= 1.0; for(count=0; count m_lights; std::vector::iterator lit = m_lights.begin(); + viewmat.getValue(glviewmat); + glPushMatrix(); + glLoadMatrixf(glviewmat); for (lit = m_lights.begin(), count = 0; !(lit==m_lights.end()) && count < m_numgllights; ++lit) { RAS_LightObject* lightdata = (*lit); if (lightdata->m_layer & objectlayer) { - - glPushMatrix(); - glLoadMatrixf(m_viewmat); - - vec[0] = (*(lightdata->m_worldmatrix))(0,3); vec[1] = (*(lightdata->m_worldmatrix))(1,3); vec[2] = (*(lightdata->m_worldmatrix))(2,3); vec[3] = 1; - if(lightdata->m_type==RAS_LightObject::LIGHT_SUN) { vec[0] = (*(lightdata->m_worldmatrix))(0,2); @@ -443,142 +472,16 @@ int GPC_RenderTools::applyLights(int objectlayer) } glLightfv((GLenum)(GL_LIGHT0+count), GL_SPECULAR, vec); glEnable((GLenum)(GL_LIGHT0+count)); - - count++; - glPopMatrix(); + count++; } } + glPopMatrix(); return count; } -void GPC_RenderTools::SetClientObject(void* obj) -{ - if (m_clientobject != obj) - { - if (obj == NULL || !((KX_GameObject*)obj)->IsNegativeScaling()) - { - glFrontFace(GL_CCW); - } else - { - glFrontFace(GL_CW); - } - m_clientobject = obj; - m_modified = true; - } -} - -bool GPC_RenderTools::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) -{ - double* const oglmatrix = (double* const) data; - MT_Point3 resultpoint(hit_point); - MT_Vector3 resultnormal(hit_normal); - MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); - MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); - left = (dir.cross(resultnormal)).safe_normalized(); - // for the up vector, we take the 'resultnormal' returned by the physics - - double maat[16]={ - left[0], left[1], left[2], 0, - dir[0], dir[1], dir[2], 0, - resultnormal[0],resultnormal[1],resultnormal[2], 0, - 0, 0, 0, 1}; - glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); - //glMultMatrixd(oglmatrix); - glMultMatrixd(maat); - return true; -} - -void GPC_RenderTools::applyTransform(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode ) -{ - if (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED || - objectdrawmode & RAS_IPolyMaterial::BILLBOARD_AXISALIGNED) - { - // rotate the billboard/halo - //page 360/361 3D Game Engine Design, David Eberly for a discussion - // on screen aligned and axis aligned billboards - // assumed is that the preprocessor transformed all billboard polygons - // so that their normal points into the positive x direction (1.0 , 0.0 , 0.0) - // when new parenting for objects is done, this rotation - // will be moved into the object - - MT_Point3 objpos (oglmatrix[12],oglmatrix[13],oglmatrix[14]); - MT_Point3 campos = rasty->GetCameraPosition(); - MT_Vector3 dir = (campos - objpos).safe_normalized(); - MT_Vector3 up(0,0,1.0); - - KX_GameObject* gameobj = (KX_GameObject*) this->m_clientobject; - // get scaling of halo object - MT_Vector3 size = gameobj->GetSGNode()->GetLocalScale(); - - bool screenaligned = (objectdrawmode & RAS_IPolyMaterial::BILLBOARD_SCREENALIGNED)!=0;//false; //either screen or axisaligned - if (screenaligned) - { - up = (up - up.dot(dir) * dir).safe_normalized(); - } else - { - dir = (dir - up.dot(dir)*up).safe_normalized(); - } - - MT_Vector3 left = dir.normalized(); - dir = (left.cross(up)).normalized(); - - // we have calculated the row vectors, now we keep - // local scaling into account: - - left *= size[0]; - dir *= size[1]; - up *= size[2]; - double maat[16]={ - left[0], left[1],left[2], 0, - dir[0], dir[1],dir[2],0, - up[0],up[1],up[2],0, - 0,0,0,1}; - glTranslated(objpos[0],objpos[1],objpos[2]); - glMultMatrixd(maat); - - } else - { - if (objectdrawmode & RAS_IPolyMaterial::SHADOW) - { - // shadow must be cast to the ground, physics system needed here! - MT_Point3 frompoint(oglmatrix[12],oglmatrix[13],oglmatrix[14]); - KX_GameObject *gameobj = (KX_GameObject*) this->m_clientobject; - MT_Vector3 direction = MT_Vector3(0,0,-1); - - direction.normalize(); - direction *= 100000; - - MT_Point3 topoint = frompoint + direction; - - KX_Scene* kxscene = (KX_Scene*) m_auxilaryClientInfo; - PHY_IPhysicsEnvironment* physics_environment = kxscene->GetPhysicsEnvironment(); - KX_IPhysicsController* physics_controller = gameobj->GetPhysicsController(); - - KX_GameObject *parent = gameobj->GetParent(); - if (!physics_controller && parent) - physics_controller = parent->GetPhysicsController(); - if (parent) - parent->Release(); - - MT_Point3 resultpoint; - MT_Vector3 resultnormal; - if (!KX_RayCast::RayTest(physics_controller, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this, oglmatrix))) - { - // couldn't find something to cast the shadow on... - glMultMatrixd(oglmatrix); - } - } else - { - - // 'normal' object - glMultMatrixd(oglmatrix); - } - } -} - void GPC_RenderTools::MotionBlur(RAS_IRasterizer* rasterizer) { int state = rasterizer->GetMotionBlurState(); @@ -609,7 +512,6 @@ void GPC_RenderTools::Update2DFilter(vector& propNames, void* gameOb void GPC_RenderTools::Render2DFilters(RAS_ICanvas* canvas) { - m_filtermanager.RenderFilters( canvas); + m_filtermanager.RenderFilters(canvas); } -unsigned int GPC_RenderTools::m_numgllights; diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.h b/source/gameengine/GamePlayer/common/GPC_RenderTools.h index 8fae3d2b305..382956e73ea 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.h +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.h @@ -31,114 +31,67 @@ #define __GPC_RENDERTOOLS_H #ifdef WIN32 - #include +// don't show stl-warnings +#pragma warning (disable:4786) +#include #endif // WIN32 -#include "GL/glew.h" - #include "RAS_IRenderTools.h" #include "BMF_Api.h" struct KX_ClientObjectInfo; +class KX_RayCast; +/* BlenderRenderTools are a set of tools to apply 2D/3D graphics effects, which + * are not part of the (polygon) Rasterizer. Effects like 2D text, 3D (polygon) + * text, lighting. + * + * Most of this code is duplicated in KX_BlenderRenderTools, so this should be + * moved to some common location to avoid duplication. */ class GPC_RenderTools : public RAS_IRenderTools { + int m_lastlightlayer; + bool m_lastlighting; + static unsigned int m_numgllights; + + BMF_Font* m_font; + public: - GPC_RenderTools(); - virtual ~GPC_RenderTools(); + GPC_RenderTools(); + virtual ~GPC_RenderTools(); - virtual void EndFrame(RAS_IRasterizer* rasty); - virtual void BeginFrame(RAS_IRasterizer* rasty); + void EndFrame(RAS_IRasterizer* rasty); + void BeginFrame(RAS_IRasterizer* rasty); - void DisableOpenGLLights() - { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - } + void EnableOpenGLLights(); + void DisableOpenGLLights(); + void ProcessLighting(int layer, const MT_Transform& viewmat); - void EnableOpenGLLights(); + /* @attention mode is ignored here */ + void RenderText2D(RAS_TEXT_RENDER_MODE mode, + const char* text, + int xco, + int yco, + int width, + int height); + void RenderText(int mode, + class RAS_IPolyMaterial* polymat, + float v1[3], + float v2[3], + float v3[3], + float v4[3], + int glattrib); - int ProcessLighting(int layer); + void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); + int applyLights(int objectlayer, const MT_Transform& viewmat); - void Perspective(int a, int width, int height, float mat[4][4], float viewmat[4][4]) - { - if(a== 0) - { - glMatrixMode(GL_PROJECTION); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - } - else - { - if(a== 1) - { - glMatrixMode(GL_PROJECTION); - glMatrixMode(GL_MODELVIEW); - } - } - } + void PushMatrix(); + void PopMatrix(); - /** - * @attention mode is ignored here - */ - virtual void RenderText2D( - RAS_TEXT_RENDER_MODE mode, - const char* text, - int xco, - int yco, - int width, - int height); - - /** - * Renders text into a (series of) polygon(s), using a texture font, - * Each character consists of one polygon (one quad or two triangles) - */ - virtual void RenderText( - int mode, - RAS_IPolyMaterial* polymat, - float v1[3], - float v2[3], - float v3[3], - float v4[3]); - - void Render(RAS_IRasterizer* rasty,double* oglmatrix,int objectdrawmode) - { - glPopMatrix(); - glPushMatrix(); - glMultMatrixd(oglmatrix); - } - - void applyTransform(RAS_IRasterizer* rasty, double* oglmatrix, int objectdrawmode); - - virtual void PushMatrix() - { - glPushMatrix(); - } - - virtual void PopMatrix() - { - glPopMatrix(); - } - - virtual class RAS_IPolyMaterial* CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep,int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - void* tface); - - int applyLights(int objectlayer); - - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } virtual void MotionBlur(RAS_IRasterizer* rasterizer); @@ -146,28 +99,7 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas); - virtual void SetClientObject(void* obj); - -protected: - /** - * Copied from KX_BlenderGL.cpp in KX_blenderhook - */ - void BL_RenderText( - int mode, - const char* textstr, - int textlen, - struct MTFace* tface, - unsigned int* col, - float v1[3],float v2[3],float v3[3],float v4[3]); - void BL_spack(unsigned int ucol) - { - char *cp = (char *)&ucol; - glColor3ub(cp[3], cp[2], cp[1]); - } - - - BMF_Font* m_font; - static unsigned int m_numgllights; + virtual void SetClientObject(RAS_IRasterizer *rasty, void* obj); }; #endif // __GPC_RENDERTOOLS_H diff --git a/source/gameengine/GamePlayer/common/Makefile b/source/gameengine/GamePlayer/common/Makefile index 19d792ddbdb..6a12e659be6 100644 --- a/source/gameengine/GamePlayer/common/Makefile +++ b/source/gameengine/GamePlayer/common/Makefile @@ -43,6 +43,7 @@ CPPFLAGS += -I../../../blender/blenloader CPPFLAGS += -I../../../blender/blenlib CPPFLAGS += -I../../../blender/imbuf CPPFLAGS += -I../../../blender/makesdna +CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include @@ -72,10 +73,6 @@ CPPFLAGS += -I../../../gameengine/Rasterizer/RAS_OpenGLRasterizer CPPFLAGS += -I../../../gameengine/Physics/Sumo CPPFLAGS += -I../../../gameengine/Physics/common -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - ############################### SOURCEDIR = source/gameengine/GamePlayer/common diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index 3b2367d2592..30f20a670d3 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -8,7 +8,6 @@ source_files = ['bmfont.cpp', 'GPC_Engine.cpp', 'GPC_KeyboardDevice.cpp', 'GPC_MouseDevice.cpp', - 'GPC_PolygonMaterial.cpp', 'GPC_RawImage.cpp', 'GPC_RawLoadDotBlendArray.cpp', 'GPC_RawLogoArrays.cpp', @@ -46,6 +45,7 @@ incs = ['.', '#source/gameengine/GamePlayer/ghost', '#source/blender/misc', '#source/blender/blenloader', + '#source/blender/gpu', '#extern/glew/include'] #This is all plugin stuff! diff --git a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h index fee729a84ac..e5ed7f39811 100644 --- a/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h +++ b/source/gameengine/GamePlayer/common/unix/GPU_PolygonMaterial.h @@ -37,9 +37,9 @@ class GPU_PolygonMaterial : public BP_PolygonMaterial public: GPUPolygonMaterial(const STR_String& texname, bool ba,const STR_String& matname, int tile, int tileXrep, int tileYrep, int mode, int transparant, - int lightlayer,bool bIsTriangle,void* clientobject,void* tpage) : + int lightlayer,,void* tpage) : BP_PolygonMaterial(texname, ba,matname, tile, tileXrep, tileYrep, - mode, transparant, lightlayer, bIsTriangle, clientobject), + mode, transparant, lightlayer), m_tface(tpage) { } diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index d9f0675001f..5e0ca93ac06 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -64,6 +64,7 @@ SET(INC ../../../../source/gameengine/GamePlayer/common ../../../../source/blender/misc ../../../../source/blender/blenloader + ../../../../source/blender/gpu ../../../../extern/solid ../../../../extern/glew/include ${PYTHON_INC} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index f859193ef7a..4cd5184fee1 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -38,6 +38,7 @@ #endif #include "GL/glew.h" +#include "GPU_extensions.h" #include "GPG_Application.h" @@ -97,16 +98,16 @@ extern "C" #include "GHOST_IEventConsumer.h" #include "GHOST_IWindow.h" #include "GHOST_Rect.h" -#include "marshal.h" static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time); static GHOST_ISystem* fSystem = 0; static const int kTimerFreq = 10; -GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName) - : m_startSceneName(startSceneName), - m_maggie(maggie), +GPG_Application::GPG_Application(GHOST_ISystem* system) + : m_startSceneName(""), + m_startScene(0), + m_maggie(0), m_exitRequested(0), m_system(system), m_mainWindow(0), @@ -114,6 +115,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR m_cursor(GHOST_kStandardCursorFirstCursor), m_engineInitialized(0), m_engineRunning(0), + m_isEmbedded(false), m_ketsjiengine(0), m_kxsystem(0), m_keyboard(0), @@ -136,21 +138,28 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR GPG_Application::~GPG_Application(void) { + if(m_pyGlobalDictString) { + delete [] m_pyGlobalDictString; + m_pyGlobalDictString = 0; + m_pyGlobalDictString_Length = 0; + } + exitEngine(); fSystem->disposeWindow(m_mainWindow); } -bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSceneName) +bool GPG_Application::SetGameEngineData(struct Main* maggie, Scene *scene) { bool result = false; - if (maggie != NULL && startSceneName != "") + if (maggie != NULL && scene != NULL) { - G.scene = (Scene*)maggie->scene.first; + G.scene = scene; m_maggie = maggie; - m_startSceneName = startSceneName; + m_startSceneName = scene->id.name+2; + m_startScene = scene; result = true; } @@ -322,6 +331,26 @@ bool GPG_Application::startWindow(STR_String& title, return success; } +bool GPG_Application::startEmbeddedWindow(STR_String& title, + const GHOST_TEmbedderWindowID parentWindow, + const bool stereoVisual, + const int stereoMode) { + + m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, GHOST_kWindowStateNormal, + GHOST_kDrawingContextTypeOpenGL, stereoVisual, parentWindow); + + if (!m_mainWindow) { + printf("error: could not create main window\n"); + exit(-1); + } + m_isEmbedded = true; + + bool success = initEngine(m_mainWindow, stereoMode); + if (success) { + success = startEngine(); + } + return success; +} bool GPG_Application::startFullScreen( @@ -480,7 +509,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) { if (!m_engineInitialized) { - glewInit(); + GPU_extensions_init(); bgl::InitExtensions(true); // get and set the preferences @@ -499,13 +528,16 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool fixed_framerate= (SYS_GetCommandLineInt(syshandle, "fixed_framerate", fixedFr) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); - bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DIAPLAY_LISTS) != 0); + bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DISPLAY_LISTS) != 0); + + if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) + m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); + + if(GPU_extensions_minimum_support()) + m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); + else if(G.fileflags & G_FILE_GAME_MAT_GLSL) + m_blendermat = false; - if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) { - int gameflag =(G.fileflags & G_FILE_GAME_MAT); - m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0); - } - // create the canvas, rasterizer and rendertools m_canvas = new GPG_Canvas(window); if (!m_canvas) @@ -628,41 +660,35 @@ bool GPG_Application::startEngine(void) { STR_String startscenename = m_startSceneName.Ptr(); m_ketsjiengine->SetSceneConverter(m_sceneconverter); - + // if (always_use_expand_framing) // sceneconverter->SetAlwaysUseExpandFraming(true); - if(m_blendermat) + if(m_blendermat && (G.fileflags & G_FILE_GAME_MAT)) m_sceneconverter->SetMaterials(true); - if(m_blenderglslmat) + if(m_blenderglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) m_sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(m_keyboard, m_mouse, m_networkdevice, m_audiodevice, - startscenename); + startscenename, + m_startScene); // some python things PyObject* dictionaryobject = initGamePlayerPythonScripting("Ketsji", psl_Lowest); m_ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(m_rasterizer, m_canvas); - PyObject *gameLogic = initGameLogic(startscene); + PyObject *gameLogic = initGameLogic(m_ketsjiengine, startscene); PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module initGameKeys(); initPythonConstraintBinding(); initMathutils(); - /* Restore the dict */ - if (m_pyGlobalDictString) { - PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length); - if (pyGlobalDict) { - PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. - } else { - PyErr_Clear(); - printf("Error could not marshall string\n"); - } - } + // Set the GameLogic.globalDict from marshal'd data, so we can + // load new blend files and keep data in GameLogic.globalDict + loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); m_sceneconverter->ConvertScene( startscenename, @@ -699,31 +725,15 @@ bool GPG_Application::startEngine(void) void GPG_Application::stopEngine() { - // get the python dict and convert to a string for future use - { - SetPyGlobalDictMarshal(NULL, 0); - - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); - if (gameLogic) { - PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module - if (pyGlobalDict) { - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 - if (pyGlobalDictMarshal) { - m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal); - PyObject_Print(pyGlobalDictMarshal, stderr, 0); - m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); - memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length); - } else { - printf("Error, GameLogic.globalDict could not be marshal'd\n"); - } - } else { - printf("Error, GameLogic.globalDict was removed\n"); - } - } else { - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); - } - } - + // GameLogic.globalDict gets converted into a buffer, and sorted in + // m_pyGlobalDictString so we can restore after python has stopped + // and started between .blend file loads. + if(m_pyGlobalDictString) { + delete [] m_pyGlobalDictString; + m_pyGlobalDictString = 0; + } + + m_pyGlobalDictString_Length = saveGamePythonConfig(&m_pyGlobalDictString); // when exiting the mainloop exitGamePythonScripting(); @@ -744,6 +754,8 @@ void GPG_Application::stopEngine() void GPG_Application::exitEngine() { + GPU_extensions_exit(); + if (m_ketsjiengine) { stopEngine(); @@ -870,7 +882,7 @@ bool GPG_Application::handleKey(GHOST_IEvent* event, bool isDown) GHOST_TEventKeyData* keyData = static_cast(eventData); //no need for this test //if (fSystem->getFullScreen()) { - if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc) { + if (keyData->key == GHOST_kKeyEsc && !m_keyboard->m_hookesc && !m_isEmbedded) { m_exitRequested = KX_EXIT_REQUEST_OUTSIDE; } //} diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 31f5eb75e52..38408f919b4 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -50,17 +50,19 @@ class GPG_Canvas; class GPG_KeyboardDevice; class GPG_System; struct Main; +struct Scene; class GPG_Application : public GHOST_IEventConsumer { public: - GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR_String startSceneName); + GPG_Application(GHOST_ISystem* system); ~GPG_Application(void); - bool SetGameEngineData(struct Main* maggie,STR_String startSceneName); + bool SetGameEngineData(struct Main* maggie, struct Scene* scene); bool startWindow(STR_String& title, int windowLeft, int windowTop, int windowWidth, int windowHeight, const bool stereoVisual, const int stereoMode); bool startFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); + bool startEmbeddedWindow(STR_String& title, const GHOST_TEmbedderWindowID parent_window, const bool stereoVisual, const int stereoMode); #ifdef WIN32 bool startScreenSaverFullScreen(int width, int height, int bpp, int frequency, const bool stereoVisual, const int stereoMode); bool startScreenSaverPreview(HWND parentWindow, const bool stereoVisual, const int stereoMode); @@ -72,29 +74,6 @@ public: bool StartGameEngine(int stereoMode); void StopGameEngine(); - char* - GetPyGlobalDictMarshal() - { - return m_pyGlobalDictString; - }; - - void - SetPyGlobalDictMarshal( char* pyGlobalDictString, int length ) - { - if (m_pyGlobalDictString && m_pyGlobalDictString != pyGlobalDictString) - free(m_pyGlobalDictString); - - m_pyGlobalDictString = pyGlobalDictString; - m_pyGlobalDictString_Length = length; - }; - - int - GetPyGlobalDictMarshalLength() - { - return m_pyGlobalDictString_Length; - }; - - protected: bool handleWheel(GHOST_IEvent* event); bool handleButton(GHOST_IEvent* event, bool isDown); @@ -123,6 +102,7 @@ protected: /* The game data */ STR_String m_startSceneName; + struct Scene* m_startScene; struct Main* m_maggie; /* Exit state. */ @@ -141,6 +121,8 @@ protected: bool m_engineInitialized; /** Engine state. */ bool m_engineRunning; + /** Running on embedded window */ + bool m_isEmbedded; /** the gameengine itself */ KX_KetsjiEngine* m_ketsjiengine; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 26a85128025..01774a68cc4 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -52,8 +52,10 @@ extern "C" { #endif // __cplusplus +#include "MEM_guardedalloc.h" #include "BKE_global.h" #include "BKE_icons.h" +#include "BKE_node.h" #include "BLI_blenlib.h" #include "DNA_scene_types.h" #include "BLO_readfile.h" @@ -64,13 +66,15 @@ extern "C" #ifdef __cplusplus } #endif // __cplusplus + +#include "GPU_draw.h" + /********************************** * End Blender include block **********************************/ #include "SYS_System.h" #include "GPG_Application.h" -#include "GPC_PolygonMaterial.h" #include "GHOST_ISystem.h" #include "RAS_IRasterizer.h" @@ -176,9 +180,13 @@ void usage(char* program) printf(" anaglyph (Red-Blue glasses)\n"); printf(" vinterlace (Vertical interlace for autostereo display)\n"); printf(" depending on the type of stereo you want\n"); +#ifndef _WIN32 + printf(" -i: parent windows ID \n"); +#endif #ifdef _WIN32 printf(" -c: keep console window open\n"); #endif + printf(" -d: turn debugging on\n"); printf(" -g: game engine options:\n"); printf(" Name Default Description\n"); printf(" ----------------------------------------\n"); @@ -193,7 +201,8 @@ void usage(char* program) printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } -char *get_filename(int argc, char **argv) { +static void get_filename(int argc, char **argv, char *filename) +{ #ifdef __APPLE__ /* On Mac we park the game file (called game.blend) in the application bundle. * The executable is located in the bundle as well. @@ -201,22 +210,18 @@ char *get_filename(int argc, char **argv) { */ int srclen = ::strlen(argv[0]); int len = 0; - char *filename = NULL; + char *gamefile = NULL; + filename[0] = '\0'; + if (argc > 1) { if (BLI_exists(argv[argc-1])) { - len = ::strlen(argv[argc-1]); - filename = new char [len + 1]; - ::strcpy(filename, argv[argc-1]); - return(filename); + BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); } if (::strncmp(argv[argc-1], "-psn_", 5)==0) { static char firstfilebuf[512]; if (GHOST_HACK_getFirstFile(firstfilebuf)) { - len = ::strlen(firstfilebuf); - filename = new char [len + 1]; - ::strcpy(filename, firstfilebuf); - return(filename); + BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE); } } } @@ -224,23 +229,26 @@ char *get_filename(int argc, char **argv) { srclen -= ::strlen("MacOS/blenderplayer"); if (srclen > 0) { len = srclen + ::strlen("Resources/game.blend"); - filename = new char [len + 1]; - ::strcpy(filename, argv[0]); - ::strcpy(filename + srclen, "Resources/game.blend"); + gamefile = new char [len + 1]; + ::strcpy(gamefile, argv[0]); + ::strcpy(gamefile + srclen, "Resources/game.blend"); //::printf("looking for file: %s\n", filename); - if (BLI_exists(filename)) { - return (filename); - } + if (BLI_exists(gamefile)) + BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE); + + delete gamefile; } - return(NULL); #else - return (argc>1)?argv[argc-1]:NULL; + filename[0] = '\0'; + + if(argc > 1) + BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); #endif // !_APPLE } -static BlendFileData *load_game_data(char *progname, char *filename = NULL) { +static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL) { BlendReadError error; BlendFileData *bfd = NULL; @@ -282,7 +290,7 @@ int main(int argc, char** argv) bool fullScreenParFound = false; bool windowParFound = false; bool closeConsole = true; - RAS_IRasterizer::StereoMode stereomode; + RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; bool stereoWindow = false; bool stereoParFound = false; int windowLeft = 100; @@ -293,8 +301,9 @@ int main(int argc, char** argv) GHOST_TUns32 fullScreenHeight= 0; int fullScreenBpp = 32; int fullScreenFrequency = 60; - char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */ - int pyGlobalDictString_Length = 0; + GHOST_TEmbedderWindowID parentWindow = 0; + + #ifdef __linux__ #ifdef __alpha__ @@ -323,6 +332,8 @@ int main(int argc, char** argv) ::DisposeNibReference(nibRef); */ #endif // __APPLE__ + + init_nodesystem(); GEN_init_messaging_system(); @@ -403,6 +414,12 @@ int main(int argc, char** argv) } } break; + + case 'd': + i++; + G.f |= G_DEBUG; /* std output printf's */ + MEM_set_memory_debug(); + break; case 'p': // Parse window position and size options @@ -455,6 +472,16 @@ int main(int argc, char** argv) usage(argv[0]); return 0; break; +#ifndef _WIN32 + case 'i': + i++; + if ( (i + 1) < argc ) + parentWindow = atoi(argv[i++]); +#ifndef NDEBUG + printf("XWindows ID = %d\n", parentWindow); +#endif //NDEBUG + +#endif // _WIN32 case 'c': i++; closeConsole = false; @@ -525,21 +552,19 @@ int main(int argc, char** argv) return 0; } - if (!stereoParFound) stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; - #ifdef WIN32 if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION) #endif { #ifdef __APPLE__ //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1); - SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); + //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); //fullScreen = false; // Can't use full screen #endif if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) { - GPC_PolygonMaterial::SetMipMappingEnabled(0); + GPU_set_mipmap(0); } // Create the system @@ -561,11 +586,15 @@ int main(int argc, char** argv) { int exitcode = KX_EXIT_REQUEST_NO_REQUEST; STR_String exitstring = ""; - GPG_Application app(system, NULL, exitstring); + GPG_Application app(system); bool firstTimeRunning = true; - char *filename = get_filename(argc, argv); + char filename[FILE_MAXDIR + FILE_MAXFILE]; char *titlename; char pathname[160]; + + get_filename(argc, argv, filename); + if(filename[0]) + BLI_convertstringcwd(filename); do { @@ -597,7 +626,7 @@ int main(int argc, char** argv) } else { - bfd = load_game_data(argv[0], filename); + bfd = load_game_data(bprogname, filename[0]? filename: NULL); } //::printf("game data loaded from %s\n", filename); @@ -619,7 +648,7 @@ int main(int argc, char** argv) #endif // WIN32 Main *maggie = bfd->main; Scene *scene = bfd->curscene; - char *startscenename = scene->id.name + 2; + G.main = maggie; G.fileflags = bfd->fileflags; //Seg Fault; icon.c gIcons == 0 @@ -627,10 +656,6 @@ int main(int argc, char** argv) titlename = maggie->name; - // Set the GameLogic.globalDict from marshal'd data, so we can load new blend files - // abd keep data in GameLogic.globalDict - app.SetPyGlobalDictMarshal(pyGlobalDictString, pyGlobalDictString_Length); - // Check whether the game should be displayed full-screen if ((!fullScreenParFound) && (!windowParFound)) { @@ -661,7 +686,7 @@ int main(int argc, char** argv) } // GPG_Application app (system, maggie, startscenename); - app.SetGameEngineData(maggie, startscenename); + app.SetGameEngineData(maggie, scene); if (firstTimeRunning) { @@ -729,7 +754,10 @@ int main(int argc, char** argv) else #endif { - app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, + if (parentWindow != 0) + app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode); + else + app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, stereoWindow, stereomode); } } @@ -756,19 +784,8 @@ int main(int argc, char** argv) } } app.StopGameEngine(); - - // GameLogic.globalDict has been converted into a buffer - // store in pyGlobalDictString so we can restore after python has stopped and started. - pyGlobalDictString = app.GetPyGlobalDictMarshal(); - pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength(); - + BLO_blendfiledata_free(bfd); - -#ifdef __APPLE__ - if (filename) { - delete [] filename; - } -#endif // __APPLE__ } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); } @@ -784,11 +801,8 @@ int main(int argc, char** argv) } } - if (pyGlobalDictString) { - free(pyGlobalDictString); - pyGlobalDictString = NULL; - } - + free_nodesystem(); + return error ? -1 : 0; } diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile index 13940ac3fc8..52e219db8f2 100644 --- a/source/gameengine/GamePlayer/ghost/Makefile +++ b/source/gameengine/GamePlayer/ghost/Makefile @@ -41,6 +41,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_BMFONT)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../GamePlayer/common @@ -69,6 +70,7 @@ CPPFLAGS += -I../../../blender/blenloader CPPFLAGS += -I../../../blender/imbuf CPPFLAGS += -I../../../blender/makesdna CPPFLAGS += -I../../../blender/readblenfile +CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../../gameengine/BlenderRoutines @@ -80,7 +82,3 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_GHOST)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index f3cce6c7443..33cf07b6211 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -40,6 +40,7 @@ incs = ['.', '#source/gameengine/GamePlayer/common', '#source/blender/misc', '#source/blender/blenloader', + '#source/blender/gpu', '#extern/glew/include'] incs += Split(env['BF_PYTHON_INC']) @@ -48,8 +49,5 @@ cflags = [] if env['OURPLATFORM']=='win32-vc': cflags = ['/GR'] -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - env.BlenderLib (libname='gp_ghost', sources=source_files, includes = incs, defines = [], libtype='player',priority=0, compileflags=cflags) diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index a9a0771936c..8ec463be6ff 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -9,108 +9,64 @@ #include "BL_BlenderShader.h" #include "BL_Material.h" -#ifdef BLENDER_GLSL #include "GPU_extensions.h" #include "GPU_material.h" -#endif #include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" - /* this is evil, but we need the scene to create materials with - * lights from the correct scene .. */ -static struct Scene *GetSceneForName(const STR_String& scenename) -{ - Scene *sce; - - for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next) - if (scenename == (sce->id.name+2)) - return sce; - - return (Scene*)G.main->scene.first; -} - -bool BL_BlenderShader::Ok() -{ -#ifdef BLENDER_GLSL - VerifyShader(); - - return (mMat && mMat->gpumaterial); -#else - return 0; -#endif -} - BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) : -#ifdef BLENDER_GLSL mScene(scene), mMat(ma), - mGPUMat(NULL), -#endif - mBound(false), mLightLayer(lightlayer) { -#ifdef BLENDER_GLSL - mBlenderScene = GetSceneForName(scene->GetName()); + mBlenderScene = scene->GetBlenderScene(); mBlendMode = GPU_BLEND_SOLID; - if(mMat) { + if(mMat) GPU_material_from_blender(mBlenderScene, mMat); - mGPUMat = mMat->gpumaterial; - } -#endif } BL_BlenderShader::~BL_BlenderShader() { -#ifdef BLENDER_GLSL - if(mMat && mMat->gpumaterial) - GPU_material_unbind(mMat->gpumaterial); -#endif + if(mMat && GPU_material_from_blender(mBlenderScene, mMat)) + GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); +} + +bool BL_BlenderShader::Ok() +{ + return VerifyShader(); } bool BL_BlenderShader::VerifyShader() { -#ifdef BLENDER_GLSL - if(mMat && !mMat->gpumaterial) - GPU_material_from_blender(mBlenderScene, mMat); - - mGPUMat = mMat->gpumaterial; - - return (mMat && mGPUMat); -#else - return false; -#endif + if(mMat) + return (GPU_material_from_blender(mBlenderScene, mMat) != 0); + else + return false; } -void BL_BlenderShader::SetProg(bool enable) +void BL_BlenderShader::SetProg(bool enable, double time) { -#ifdef BLENDER_GLSL if(VerifyShader()) { - if(enable) { - GPU_material_bind(mGPUMat, mLightLayer); - mBound = true; - } - else { - GPU_material_unbind(mGPUMat); - mBound = false; - } + if(enable) + GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, ~0, time); + else + GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); } -#endif } int BL_BlenderShader::GetAttribNum() { -#ifdef BLENDER_GLSL GPUVertexAttribs attribs; int i, enabled = 0; if(!VerifyShader()) return enabled; - GPU_material_vertex_attributes(mGPUMat, &attribs); + GPU_material_vertex_attributes(GPU_material_from_blender(mBlenderScene, mMat), &attribs); for(i = 0; i < attribs.totlayer; i++) if(attribs.layer[i].glindex+1 > enabled) @@ -120,24 +76,23 @@ int BL_BlenderShader::GetAttribNum() enabled = BL_MAX_ATTRIB; return enabled; -#else - return 0; -#endif } void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) { -#ifdef BLENDER_GLSL GPUVertexAttribs attribs; + GPUMaterial *gpumat; int i, attrib_num; ras->SetAttribNum(0); if(!VerifyShader()) return; + + gpumat = GPU_material_from_blender(mBlenderScene, mMat); if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { - GPU_material_vertex_attributes(mGPUMat, &attribs); + GPU_material_vertex_attributes(gpumat, &attribs); attrib_num = GetAttribNum(); ras->SetTexCoordNum(0); @@ -168,44 +123,37 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) else ras->SetAttrib(RAS_IRasterizer::RAS_TEXCO_DISABLE, attribs.layer[i].glindex); } - - ras->EnableTextures(true); } - else - ras->EnableTextures(false); -#endif } -void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) +void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { -#ifdef BLENDER_GLSL float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; + GPUMaterial *gpumat; - VerifyShader(); + gpumat = GPU_material_from_blender(mBlenderScene, mMat); - if(!mGPUMat) // || !mBound) + if(!gpumat || !GPU_material_bound(gpumat)) return; MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - MT_Matrix4x4 view; - rasty->GetViewMatrix(view); + const MT_Matrix4x4& view = rasty->GetViewMatrix(); + const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); + // note: getValue gives back column major as needed by OpenGL model.getValue((float*)obmat); view.getValue((float*)viewmat); - - view.invert(); - view.getValue((float*)viewinvmat); + viewinv.getValue((float*)viewinvmat); if(ms.m_bObjectColor) ms.m_RGBAcolor.getValue((float*)obcol); else obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; - GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol); + GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol); - mBlendMode = GPU_material_blend_mode(mGPUMat, obcol); -#endif + mBlendMode = GPU_material_blend_mode(gpumat, obcol); } int BL_BlenderShader::GetBlendMode() @@ -215,12 +163,8 @@ int BL_BlenderShader::GetBlendMode() bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) { -#ifdef BLENDER_GLSL /* to avoid unneeded state switches */ - return (blshader && mGPUMat == blshader->mGPUMat && mLightLayer == blshader->mLightLayer); -#else - return true; -#endif + return (blshader && mMat == blshader->mMat && mLightLayer == blshader->mLightLayer); } // eof diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index da9765dafa4..5c1f59f94ad 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -2,9 +2,7 @@ #ifndef __BL_GPUSHADER_H__ #define __BL_GPUSHADER_H__ -#ifdef BLENDER_GLSL #include "GPU_material.h" -#endif #include "MT_Matrix4x4.h" #include "MT_Matrix3x3.h" @@ -29,13 +27,9 @@ class BL_Material; class BL_BlenderShader { private: -#ifdef BLENDER_GLSL KX_Scene *mScene; struct Scene *mBlenderScene; struct Material *mMat; - GPUMaterial *mGPUMat; -#endif - bool mBound; int mLightLayer; int mBlendMode; @@ -46,11 +40,11 @@ public: virtual ~BL_BlenderShader(); bool Ok(); - void SetProg(bool enable); + void SetProg(bool enable, double time=0.0); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); - void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index dcb66ea2579..0eaa234566c 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -18,9 +18,9 @@ struct EnvMap; this will default to users available units to build with more available, just increment this value although the more you add the slower the search time will be. - we will go for three, which should be enough + we will go for eight, which should be enough */ -#define MAXTEX 3 //match in RAS_TexVert & RAS_OpenGLRasterizer +#define MAXTEX 8 //match in RAS_TexVert & RAS_OpenGLRasterizer // different mapping modes class BL_Mapping @@ -139,7 +139,7 @@ enum BL_ras_mode COLLIDER=2, ZSORT=4, ALPHA=8, - TRIANGLE=16, + // TRIANGLE=16, USE_LIGHT=32, WIRE=64 }; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 57d0fe4140f..f28d3fa2912 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -433,7 +433,7 @@ void BL_Shader::SetProg(bool enable) } } -void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) +void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { if(!Ok() || !mPreDef.size()) return; @@ -445,8 +445,7 @@ void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - MT_Matrix4x4 view; - rasty->GetViewMatrix(view); + const MT_Matrix4x4& view = rasty->GetViewMatrix(); if(mAttr==SHD_TANGENT) ms.m_mesh->SetMeshModified(true); @@ -525,13 +524,15 @@ void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) } case VIEWMATRIX_INVERSE: { - view.invert(); + MT_Matrix4x4 viewinv = view; + viewinv.invert(); SetUniform(uni->mLoc, view); break; } case VIEWMATRIX_INVERSETRANSPOSE: { - view.invert(); + MT_Matrix4x4 viewinv = view; + viewinv.invert(); SetUniform(uni->mLoc, view, true); break; } @@ -670,6 +671,7 @@ void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose) ) { float value[16]; + // note: getValue gives back column major as needed by OpenGL vec.getValue(value); glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value); } diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 8f303454087..c7fae31ba03 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -177,7 +177,7 @@ public: void UnloadShader(); // Update predefined uniforms each render call - void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); //// Set sampler units (copied) //void InitializeSampler(int unit, BL_Texture* texture ); diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index be009d94701..58411f6d25e 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -69,6 +69,7 @@ SET(INC ../../../intern/SoundSystem ../../../source/blender/misc ../../../source/blender/blenloader + ../../../source/blender/gpu ../../../extern/bullet2/src ../../../extern/solid ../../../extern/glew/include diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 0c66ac1fde3..a35ab8b15e8 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -196,19 +196,19 @@ PyParentObject KX_NetworkMessageSensor::Parents[] = { PyMethodDef KX_NetworkMessageSensor::Methods[] = { {"setSubjectFilterText", (PyCFunction) - KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS, + KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O, SetSubjectFilterText_doc}, {"getFrameMessageCount", (PyCFunction) - KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_NOARGS, GetFrameMessageCount_doc}, {"getBodies", (PyCFunction) - KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetBodies, METH_NOARGS, GetBodies_doc}, {"getSubject", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetSubject, METH_NOARGS, GetSubject_doc}, {"getSubjects", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubjects, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS, GetSubjects_doc}, {NULL,NULL} //Sentinel }; @@ -222,22 +222,16 @@ char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = "\tsetSubjectFilterText(value)\n" "\tChange the message subject text that this sensor is listening to.\n"; -PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value) { - char* Subject; - - if (PyArg_ParseTuple(args, "s", &Subject)) - { - m_subject = Subject; - } - else { + char* Subject = PyString_AsString(value); + if (Subject==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string message"); return NULL; } - - Py_Return; + + m_subject = Subject; + Py_RETURN_NONE; } // 2. Get the number of messages received since the last frame @@ -245,10 +239,7 @@ char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = "\tgetFrameMessageCount()\n" "\tGet the number of messages received since the last frame.\n"; -PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* ) { return PyInt_FromLong(long(m_frame_message_count)); } @@ -258,16 +249,13 @@ char KX_NetworkMessageSensor::GetBodies_doc[] = "\tgetBodies()\n" "\tGet the list of message bodies.\n"; -PyObject* KX_NetworkMessageSensor::PyGetBodies( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* ) { if (m_BodyList) { return ((PyObject*) m_BodyList->AddRef()); + } else { + return ((PyObject*) new CListValue()); } - - Py_Return; } // 4. Get the message subject: field of the message sensor @@ -275,16 +263,9 @@ char KX_NetworkMessageSensor::GetSubject_doc[] = "\tgetSubject()\n" "\tGet the subject: field of the message sensor.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubject( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* ) { - if (m_subject) { - return PyString_FromString(m_subject); - } - - Py_Return; + return PyString_FromString(m_subject ? m_subject : ""); } // 5. Get the message subjects @@ -292,14 +273,11 @@ char KX_NetworkMessageSensor::GetSubjects_doc[] = "\tgetSubjects()\n" "\tGet list of message subjects.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubjects( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* ) { if (m_SubjectList) { - return ((PyObject*) m_SubjectList->AddRef()); - } - - Py_Return; + return ((PyObject*) m_SubjectList->AddRef()); + } else { + return ((PyObject*) new CListValue()); + } } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 6fd92d17be3..8cdfd6cdb5a 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -74,11 +74,11 @@ public: virtual PyObject* _getattr(const STR_String& attr); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, SetSubjectFilterText); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetFrameMessageCount); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetBodies); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubject); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubjects); + KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetBodies); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubject); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubjects); }; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index a67e5b26667..f92200780d5 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -19,13 +19,12 @@ #include "MT_Vector4.h" #include "MT_Matrix4x4.h" +#include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" -extern "C" { -#include "BDR_drawmesh.h" -} +#include "GPU_draw.h" #include "STR_HashedString.h" @@ -48,7 +47,6 @@ KX_BlenderMaterial::KX_BlenderMaterial( BL_Material *data, bool skin, int lightlayer, - void *clientobject, PyTypeObject *T ) : PyObjectPlus(T), @@ -62,9 +60,7 @@ KX_BlenderMaterial::KX_BlenderMaterial( data->transp, ((data->ras_mode &ALPHA)!=0), ((data->ras_mode &ZSORT)!=0), - lightlayer, - ((data->ras_mode &TRIANGLE)!=0), - clientobject + lightlayer ), mMaterial(data), mShader(0), @@ -78,9 +74,10 @@ KX_BlenderMaterial::KX_BlenderMaterial( { // -------------------------------- // RAS_IPolyMaterial variables... - m_flag |=RAS_BLENDERMAT; - m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; - m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; + m_flag |= RAS_BLENDERMAT; + m_flag |= (mMaterial->IdMode>=ONETEX)? RAS_MULTITEX: 0; + m_flag |= ((mMaterial->ras_mode & USE_LIGHT)!=0)? RAS_MULTILIGHT: 0; + m_flag |= (mMaterial->glslmat)? RAS_BLENDERGLSL: 0; // figure max int enabled = mMaterial->num_enabled; @@ -97,7 +94,7 @@ KX_BlenderMaterial::KX_BlenderMaterial( mMaterial->blend_mode[i] ); } - m_multimode += mMaterial->IdMode+mMaterial->ras_mode; + m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT)); } @@ -204,7 +201,7 @@ void KX_BlenderMaterial::OnExit() } if( mMaterial->tface ) - set_tpage(mMaterial->tface); + GPU_set_tpage(mMaterial->tface); } @@ -256,25 +253,28 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras) { if( !enable || !mBlenderShader->Ok() ) { + ras->SetBlendingMode(TF_SOLID); + // frame cleanup. if(mLastBlenderShader) { mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; } + else + BL_Texture::DisableAllTextures(); - ras->SetBlendingMode(TF_SOLID); - BL_Texture::DisableAllTextures(); return; } if(!mBlenderShader->Equals(mLastBlenderShader)) { ras->SetBlendingMode(mMaterial->transp); - BL_Texture::DisableAllTextures(); if(mLastBlenderShader) mLastBlenderShader->SetProg(false); + else + BL_Texture::DisableAllTextures(); - mBlenderShader->SetProg(true); + mBlenderShader->SetProg(true, ras->GetTime()); mLastBlenderShader= mBlenderShader; } } @@ -354,21 +354,22 @@ KX_BlenderMaterial::ActivatShaders( if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - tmp->setShaderData( false, rasty); + tmp->setShaderData(false, rasty); cachingInfo = GetCachingInfo(); if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - tmp->setShaderData( true, rasty); + tmp->setShaderData(true, rasty); else - tmp->setShaderData( false, rasty); + tmp->setShaderData(false, rasty); if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) + if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -394,31 +395,24 @@ KX_BlenderMaterial::ActivateBlenderShaders( mLastShader= NULL; } - // reset... - if(tmp->mMaterial->IsShared()) - cachingInfo =0; - if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) tmp->setBlenderShaderData(false, rasty); cachingInfo = GetCachingInfo(); - if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { + if(rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) tmp->setBlenderShaderData(true, rasty); - rasty->EnableTextures(true); - } - else { + else tmp->setBlenderShaderData(false, rasty); - rasty->EnableTextures(false); - } if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE) rasty->SetCullFace(false); else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) + if (((mMaterial->ras_mode & WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -426,10 +420,10 @@ KX_BlenderMaterial::ActivateBlenderShaders( } else rasty->SetLines(false); - } - ActivatGLMaterials(rasty); - mBlenderShader->SetAttribs(rasty, mMaterial); + ActivatGLMaterials(rasty); + mBlenderShader->SetAttribs(rasty, mMaterial); + } } void @@ -466,7 +460,8 @@ KX_BlenderMaterial::ActivateMat( else rasty->SetCullFace(true); - if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES) + if (((mMaterial->ras_mode &WIRE)!=0) || (mMaterial->mode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) { if((mMaterial->ras_mode &WIRE)!=0) rasty->SetCullFace(false); @@ -486,12 +481,10 @@ KX_BlenderMaterial::Activate( TCachingInfo& cachingInfo )const { - bool dopass = false; - if( GLEW_ARB_shader_objects && ( mShader && mShader->Ok() ) ) { - if( (mPass++) < mShader->getNumPass() ) { + if(GLEW_ARB_shader_objects && (mShader && mShader->Ok())) { + if((mPass++) < mShader->getNumPass() ) { ActivatShaders(rasty, cachingInfo); - dopass = true; - return dopass; + return true; } else { if(mShader == mLastShader) { @@ -499,36 +492,29 @@ KX_BlenderMaterial::Activate( mLastShader = NULL; } mPass = 0; - dopass = false; - return dopass; + return false; } } - else if( GLEW_ARB_shader_objects && ( mBlenderShader && mBlenderShader->Ok() ) ) { - if( (mPass++) == 0 ) { + else if( GLEW_ARB_shader_objects && (mBlenderShader && mBlenderShader->Ok() ) ) { + if(mPass++ == 0) { ActivateBlenderShaders(rasty, cachingInfo); - dopass = true; - return dopass; + return true; } else { mPass = 0; - dopass = false; - return dopass; + return false; } } else { - switch (mPass++) - { - case 0: - ActivateMat(rasty, cachingInfo); - dopass = true; - break; - default: - mPass = 0; - dopass = false; - break; + if(mPass++ == 0) { + ActivateMat(rasty, cachingInfo); + return true; + } + else { + mPass = 0; + return false; } } - return dopass; } bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const @@ -536,14 +522,15 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const if(!RAS_IPolyMaterial::UsesLighting(rasty)) return false; - if(mShader && mShader->Ok()); + if(mShader && mShader->Ok()) + return true; else if(mBlenderShader && mBlenderShader->Ok()) return false; - - return true; + else + return true; } -void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const +void KX_BlenderMaterial::ActivateMeshSlot(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const { if(mShader && GLEW_ARB_shader_objects) { mShader->Update(ms, rasty); @@ -554,7 +541,7 @@ void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterize mBlenderShader->Update(ms, rasty); /* we do blend modes here, because they can change per object - * with the same material due to obcolor */ + * with the same material due to obcolor/obalpha */ blendmode = mBlenderShader->GetBlendMode(); if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) blendmode = mMaterial->transp; @@ -633,11 +620,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const else ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_DISABLE, i); } - - ras->EnableTextures(true); } - else - ras->EnableTextures(false); } void KX_BlenderMaterial::setTexMatrixData(int i) @@ -712,8 +695,7 @@ void KX_BlenderMaterial::setObjectMatrixData(int i, RAS_IRasterizer *ras) glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); - MT_Matrix4x4 mvmat; - ras->GetViewMatrix(mvmat); + const MT_Matrix4x4& mvmat = ras->GetViewMatrix(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); @@ -835,7 +817,9 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") } if(mShader && !mShader->GetError()) { + m_flag &= ~RAS_BLENDERGLSL; mMaterial->SetSharedMaterial(true); + mScene->GetBucketManager()->ReleaseDisplayLists(this); Py_INCREF(mShader); return mShader; }else @@ -870,8 +854,6 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(void) delete mBlenderShader; mBlenderShader = 0; } - else - m_flag |= RAS_BLENDERGLSL; } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 0d7657b8cdb..4ddf5a924df 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -28,7 +28,6 @@ public: BL_Material* mat, bool skin, int lightlayer, - void* clientobject, PyTypeObject* T=&Type ); @@ -47,7 +46,7 @@ public: virtual void ActivateMeshSlot( - const KX_MeshSlot & ms, + const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) const; diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 42b909927fd..4948c0ea174 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -35,6 +35,8 @@ #include #include "KX_GameObject.h" +#include "PyObjectPlus.h" + STR_String KX_CameraActuator::X_AXIS_STRING = "x"; STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index e00ec68ad33..e0c9af5ae60 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -109,16 +109,11 @@ KX_ConstraintActuator::~KX_ConstraintActuator() // there's nothing to be done here, really.... } /* end of destructor */ -bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } bool bFound = false; if (m_property[0] == 0) @@ -139,8 +134,26 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_p bFound = hitKXObj->GetProperty(m_property) != NULL; } } + // update the hit status + result->m_hitFound = bFound; + // stop looking + return true; +} - return bFound; +/* this function is used to pre-filter the object before casting the ray on them. + This is useful for "X-Ray" option when we want to see "through" unwanted object. + */ +bool KX_ConstraintActuator::NeedRayCast(KX_ClientObjectInfo* client) +{ + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // Unknown type of object, skip it. + // Should not occur as the sensor objects are filtered in RayTest() + printf("Invalid client type %d found in ray casting\n", client->m_type); + return false; + } + // no X-Ray function yet + return true; } bool KX_ConstraintActuator::Update(double curtime, bool frame) @@ -287,8 +300,6 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) direction.normalize(); { MT_Point3 topoint = position + (m_maximumBound) * direction; - MT_Point3 resultpoint; - MT_Vector3 resultnormal; PHY_IPhysicsEnvironment* pe = obj->GetPhysicsEnvironment(); KX_IPhysicsController *spc = obj->GetPhysicsController(); @@ -304,9 +315,10 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) parent->Release(); } } - result = KX_RayCast::RayTest(spc, pe, position, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this)); - + KX_RayCast::Callback callback(this,spc); + result = KX_RayCast::RayTest(pe, position, topoint, callback); if (result) { + MT_Vector3 newnormal = callback.m_hitNormal; // compute new position & orientation if ((m_option & (KX_ACT_CONSTRAINT_NORMAL|KX_ACT_CONSTRAINT_DISTANCE)) == 0) { // if none option is set, the actuator does nothing but detect ray @@ -316,27 +328,27 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) if (m_option & KX_ACT_CONSTRAINT_NORMAL) { // the new orientation must be so that the axis is parallel to normal if (sign) - resultnormal = -resultnormal; + newnormal = -newnormal; // apply damping on the direction if (m_rotDampTime) { MT_Scalar rotFilter = 1.0/(1.0+m_rotDampTime); - resultnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*resultnormal; + newnormal = (-m_rotDampTime*rotFilter)*direction + rotFilter*newnormal; } else if (m_posDampTime) { - resultnormal = -filter*direction + (1.0-filter)*resultnormal; + newnormal = -filter*direction + (1.0-filter)*newnormal; } - obj->AlignAxisToVect(resultnormal, axis); - direction = -resultnormal; + obj->AlignAxisToVect(newnormal, axis); + direction = -newnormal; } if (m_option & KX_ACT_CONSTRAINT_DISTANCE) { if (m_posDampTime) { - newdistance = filter*(position-resultpoint).length()+(1.0-filter)*m_minimumBound; + newdistance = filter*(position-callback.m_hitPoint).length()+(1.0-filter)*m_minimumBound; } else { newdistance = m_minimumBound; } } else { - newdistance = (position-resultpoint).length(); + newdistance = (position-callback.m_hitPoint).length(); } - newposition = resultpoint-newdistance*direction; + newposition = callback.m_hitPoint-newdistance*direction; } else if (m_option & KX_ACT_CONSTRAINT_PERMANENT) { // no contact but still keep running result = true; @@ -347,7 +359,7 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) case KX_ACT_CONSTRAINT_LOCX: case KX_ACT_CONSTRAINT_LOCY: case KX_ACT_CONSTRAINT_LOCZ: - newposition = position; + newposition = position = obj->GetSGNode()->GetLocalPosition(); switch (m_locrot) { case KX_ACT_CONSTRAINT_LOCX: Clamp(newposition[0], m_minimumBound, m_maximumBound); @@ -363,7 +375,8 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) if (m_posDampTime) { newposition = filter*position + (1.0-filter)*newposition; } - break; + obj->NodeSetLocalPosition(newposition); + goto CHECK_TIME; } if (result) { // set the new position but take into account parent if any diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index d9f39124cac..6ec4de9aad9 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -37,6 +37,8 @@ #include "MT_Vector3.h" #include "KX_ClientObjectInfo.h" +class KX_RayCast; + class KX_ConstraintActuator : public SCA_IActuator { Py_Header; @@ -100,7 +102,8 @@ protected: KX_ACT_CONSTRAINT_DISTANCE = 512 }; bool IsValidMode(KX_CONSTRAINTTYPE m); - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo*); KX_ConstraintActuator(SCA_IObject* gameobj, int posDamptime, diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index b54da6eb753..c9095ff34f6 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -27,6 +27,7 @@ * ***** END GPL LICENSE BLOCK ***** */ #include +#include "PyObjectPlus.h" #include "KX_ConstraintWrapper.h" #include "PHY_IPhysicsEnvironment.h" diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 6653026f28a..248d2f49b0b 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -86,6 +86,7 @@ struct KX_ObjectProperties bool m_disableSleeping; bool m_hasCompoundChildren; bool m_isCompoundChild; + double m_margin; KX_BoundBoxClass m_boundclass; union { KX_BoxBounds box; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index d6997ee29a8..b3f24d97281 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -76,16 +76,16 @@ struct KX_PhysicsInstance { DT_VertexBaseHandle m_vertexbase; - int m_vtxarray; + RAS_DisplayArray* m_darray; RAS_IPolyMaterial* m_material; - - KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, int vtxarray, RAS_IPolyMaterial* mat) + + KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat) : m_vertexbase(vertex_base), - m_vtxarray(vtxarray), - m_material(mat) + m_darray(darray), + m_material(mat) { } - + ~KX_PhysicsInstance() { DT_DeleteVertexBase(m_vertexbase); @@ -100,11 +100,11 @@ static void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoSce 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) + RAS_MeshObject* meshobj, + KX_Scene* kxscene, + PHY_ShapeProps* kxshapeprops, + PHY_MaterialProps* kxmaterial, + struct KX_ObjectProperties* objprop) { @@ -150,23 +150,23 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, 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]); + 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); + 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); + 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. */ + /* Dynamic mesh objects. WARNING! slow. */ case KX_BOUNDPOLYTOPE: polytope = true; // fall through @@ -186,15 +186,15 @@ void KX_ConvertSumoObject( KX_GameObject* gameobj, 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 @@ -320,12 +320,11 @@ static void BL_RegisterSumoObject( physicscontroller->SetObject(gameobj->GetSGNode()); } -static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat) +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 = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]); - //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray]; - DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert)); + 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); @@ -337,15 +336,19 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarr // only add polygons that have the collisionflag set if (poly->IsCollider()) { - DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray); + 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->GetVertexIndexBase().m_indexarray[0]); - DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]); - DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[3]); + DT_VertexIndex(poly->GetVertexOffset(0)); + DT_VertexIndex(poly->GetVertexOffset(2)); + DT_VertexIndex(poly->GetVertexOffset(3)); DT_End(); } } @@ -354,16 +357,15 @@ static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarr //DT_VertexIndices(indices.size(), &indices[0]); DT_EndComplexShape(); - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat)); + map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); return shape; } -static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat) +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 = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]); - //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray]; - DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert)); + 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++) @@ -373,12 +375,12 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxar // only add polygons that have the collisionflag set if (poly->IsCollider()) { - indices.push_back(poly->GetVertexIndexBase().m_indexarray[0]); - indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]); - indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]); + 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->GetVertexIndexBase().m_indexarray[3]); + indices.push_back(poly->GetVertexOffset(3)); } } @@ -386,7 +388,7 @@ static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxar DT_VertexIndices(indices.size(), &indices[0]); DT_EndPolytope(); - map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat)); + map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat)); return shape; } @@ -398,8 +400,8 @@ bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj) KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)]; if (instance) { - const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(instance->m_material)[instance->m_vtxarray])[0]); - DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getLocalXYZ()); + const RAS_TexVert *vertex_array = &instance->m_darray->m_vertex[0]; + DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getXYZ()); return true; } return false; @@ -425,7 +427,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope // Count the number of collision polygons and check they all come from the same // vertex array int numvalidpolys = 0; - int vtxarray = -1; + RAS_DisplayArray *darray = NULL; RAS_IPolyMaterial *poly_material = NULL; bool reinstance = true; @@ -437,14 +439,14 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->IsCollider()) { // check polygon is from the same vertex array - if (poly->GetVertexIndexBase().m_vtxarray != vtxarray) + if (poly->GetDisplayArray() != darray) { - if (vtxarray < 0) - vtxarray = poly->GetVertexIndexBase().m_vtxarray; + if (darray == NULL) + darray = poly->GetDisplayArray(); else { reinstance = false; - vtxarray = -1; + darray = NULL; } } @@ -478,9 +480,9 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (reinstance) { if (polytope) - shape = InstancePhysicsPolytope(meshobj, vtxarray, poly_material); + shape = InstancePhysicsPolytope(meshobj, darray, poly_material); else - shape = InstancePhysicsComplex(meshobj, vtxarray, poly_material); + shape = InstancePhysicsComplex(meshobj, darray, poly_material); } else { @@ -489,7 +491,7 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl; if (!poly_material) std::cout << " Check mesh materials." << std::endl; - if (vtxarray < 0) + if (darray == NULL) std::cout << " Check number of vertices." << std::endl; } @@ -505,18 +507,10 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->IsCollider()) { /* We have to tesselate here because SOLID can only raycast triangles */ DT_Begin(); - /* V1 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V2 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[1], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V3 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V1, V2, V3 */ + DT_Vertex(poly->GetVertex(2)->getXYZ()); + DT_Vertex(poly->GetVertex(1)->getXYZ()); + DT_Vertex(poly->GetVertex(0)->getXYZ()); numvalidpolys++; DT_End(); @@ -524,18 +518,10 @@ static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope if (poly->VertexCount() == 4) { DT_Begin(); - /* V1 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[3], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V3 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); - /* V4 */ - DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ()); + /* V1, V3, V4 */ + DT_Vertex(poly->GetVertex(3)->getXYZ()); + DT_Vertex(poly->GetVertex(2)->getXYZ()); + DT_Vertex(poly->GetVertex(0)->getXYZ()); numvalidpolys++; DT_End(); @@ -713,6 +699,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_gravity = btVector3(0,0,0); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; + ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; @@ -800,7 +787,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, return; } - bm->setMargin(0.06); + bm->setMargin(ci.m_margin); if (objprop->m_isCompoundChild) @@ -815,11 +802,29 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; - MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition(); - MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation(); - MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale(); + // compute the local transform from parent, this may include a parent inverse node + SG_Node* gameNode = gameobj->GetSGNode(); + SG_Node* parentInverseNode = gameNode->GetSGParent(); + if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL) + // this is not a parent inverse node, cancel it + parentInverseNode = NULL; + // now combine the parent inverse node and the game node + MT_Point3 childPos = gameNode->GetLocalPosition(); + MT_Matrix3x3 childRot = gameNode->GetLocalOrientation(); + MT_Vector3 childScale = gameNode->GetLocalScale(); + if (parentInverseNode) + { + const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition(); + const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation(); + const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale(); + childRot = parentInverseRot * childRot; + childScale = parentInverseScale * childScale; + childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos); + } - bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z())); + shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z()); + bm->setLocalScaling(shapeInfo->m_childScale); + shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z())); float rotval[12]; childRot.getValue(rotval); diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index fcd32d5f4fe..91ddbbbfbc9 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -34,6 +34,7 @@ //#include #include "KX_Scene.h" #include "KX_KetsjiEngine.h" +#include "KX_PythonInit.h" /* for config load/saving */ #ifdef HAVE_CONFIG_H #include @@ -125,6 +126,71 @@ bool KX_GameActuator::Update() } break; } + case KX_GAME_SAVECFG: + { + if (m_ketsjiengine) + { + char mashal_path[512]; + char *marshal_buffer = NULL; + int marshal_length; + FILE *fp = NULL; + + pathGamePythonConfig(mashal_path); + marshal_length = saveGamePythonConfig(&marshal_buffer); + + if (marshal_length && marshal_buffer) { + fp = fopen(mashal_path, "wb"); + if (fp) { + if (fwrite(marshal_buffer, 1, marshal_length, fp) != marshal_length) { + printf("Warning: could not write marshal data\n"); + } + fclose(fp); + } else { + printf("Warning: could not open marshal file\n"); + } + } else { + printf("Warning: could not create marshal buffer\n"); + } + } + break; + } + case KX_GAME_LOADCFG: + { + if (m_ketsjiengine) + { + char mashal_path[512]; + char *marshal_buffer; + int marshal_length; + FILE *fp = NULL; + int result; + + pathGamePythonConfig(mashal_path); + + fp = fopen(mashal_path, "rb"); + if (fp) { + // obtain file size: + fseek (fp , 0 , SEEK_END); + marshal_length = ftell(fp); + rewind(fp); + + marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); + + result = fread (marshal_buffer, 1, marshal_length, fp); + + if (result == marshal_length) { + loadGamePythonConfig(marshal_buffer, marshal_length); + } else { + printf("warning: could not read all of '%s'\n", mashal_path); + } + + free(marshal_buffer); + fclose(fp); + } else { + printf("warning: could not open '%s'\n", mashal_path); + } + } + break; + } default: ; /* do nothing? this is an internal error !!! */ } diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index 8565dc46caa..bb3448995dc 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -54,6 +54,8 @@ protected: KX_GAME_START, KX_GAME_RESTART, KX_GAME_QUIT, + KX_GAME_SAVECFG, + KX_GAME_LOADCFG, KX_GAME_MAX }; diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 700cc00e996..252741754ec 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -51,6 +51,7 @@ typedef unsigned long uint_ptr; #include "KX_GameObject.h" #include "RAS_MeshObject.h" #include "KX_MeshProxy.h" +#include "KX_PolyProxy.h" #include // printf #include "SG_Controller.h" #include "KX_IPhysicsController.h" @@ -64,6 +65,8 @@ typedef unsigned long uint_ptr; #include "SCA_IActuator.h" #include "SCA_ISensor.h" +#include "PyObjectPlus.h" /* python stuff */ + // This file defines relationships between parents and children // in the game engine. @@ -78,12 +81,15 @@ KX_GameObject::KX_GameObject( m_bDyna(false), m_layer(0), m_pBlenderObject(NULL), + m_pBlenderGroupObject(NULL), m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_bVisible(true), + m_bCulled(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), + m_xray(false), m_pHitObject(NULL), m_isDeformable(false) { @@ -99,8 +105,11 @@ KX_GameObject::KX_GameObject( }; + KX_GameObject::~KX_GameObject() { + RemoveMeshes(); + // is this delete somewhere ? //if (m_sumoObj) // delete m_sumoObj; @@ -162,7 +171,6 @@ STR_String KX_GameObject::GetName() void KX_GameObject::SetName(STR_String name) { m_name = name; - }; // Set the name of the value @@ -227,11 +235,12 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) m_pPhysicsController1->SuspendDynamics(true); } // Set us to our new scale, position, and orientation - scale1[0] = scale1[0]/scale2[0]; - scale1[1] = scale1[1]/scale2[1]; - scale1[2] = scale1[2]/scale2[2]; + scale2[0] = 1.0/scale2[0]; + scale2[1] = 1.0/scale2[1]; + scale2[2] = 1.0/scale2[2]; + scale1 = scale1 * scale2; MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse(); - MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1; + MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; NodeSetLocalScale(scale1); NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); @@ -283,11 +292,11 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica) CValue* KX_GameObject::GetReplica() { KX_GameObject* replica = new KX_GameObject(*this); - + // this will copy properties and so on... CValue::AddDataToReplica(replica); ProcessReplica(replica); - + return replica; } @@ -353,24 +362,47 @@ double* KX_GameObject::GetOpenGLMatrix() return fl; } +void KX_GameObject::AddMeshUser() +{ + for (size_t i=0;iAddMeshUser(this); + + UpdateBuckets(false); +} +static void UpdateBuckets_recursive(SG_Node* node) +{ + NodeList& children = node->GetSGChildren(); -void KX_GameObject::Bucketize() + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->UpdateBuckets(0); + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + UpdateBuckets_recursive(childnode); + } +} + +void KX_GameObject::UpdateBuckets( bool recursive ) { double* fl = GetOpenGLMatrix(); for (size_t i=0;iBucketize(fl, this, m_bUseObjectColor, m_objectColor); + m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); + + if (recursive) { + UpdateBuckets_recursive(m_pSGNode); + } } - - void KX_GameObject::RemoveMeshes() { - double* fl = GetOpenGLMatrix(); - for (size_t i=0;iRemoveFromBuckets(fl, this); + m_meshes[i]->RemoveFromBuckets(this); //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter @@ -453,13 +485,14 @@ KX_GameObject::UpdateMaterialData( ) { int mesh = 0; - if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { - RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial(); + list::iterator mit = m_meshes[mesh]->GetFirstMaterial(); + for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) { - RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial(); - if(poly->GetFlag() & RAS_BLENDERMAT) + RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial(); + + if(poly->GetFlag() & RAS_BLENDERMAT ) { KX_BlenderMaterial *m = static_cast(poly); @@ -467,8 +500,7 @@ KX_GameObject::UpdateMaterialData( { m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) - if(!(poly->GetFlag() & RAS_BLENDERGLSL)) - SetObjectColor(rgba); + SetObjectColor(rgba); } else { @@ -494,14 +526,52 @@ KX_GameObject::GetVisible( return m_bVisible; } +static void setVisible_recursive(SG_Node* node, bool v) +{ + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->SetVisible(v, 0); + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + setVisible_recursive(childnode, v); + } +} + + void KX_GameObject::SetVisible( - bool v + bool v, + bool recursive ) { m_bVisible = v; + if (recursive) + setVisible_recursive(m_pSGNode, v); } +bool +KX_GameObject::GetCulled( + void + ) +{ + return m_bCulled; +} + +void +KX_GameObject::SetCulled( + bool c + ) +{ + m_bCulled = c; +} + + void KX_GameObject::SetLayer( int l @@ -518,48 +588,13 @@ KX_GameObject::GetLayer( return m_layer; } -// used by Python, and the actuatorshould _not_ be misused by the -// scene! -void -KX_GameObject::MarkVisible( - bool visible - ) -{ - /* If explicit visibility settings are used, this is - * determined on this level. Maybe change this to mesh level - * later on? */ - - double* fl = GetOpenGLMatrixPtr()->getPointer(); - for (size_t i=0;iMarkVisible(fl,this,visible,m_bUseObjectColor,m_objectColor); - } -} - - -// Always use the flag? -void -KX_GameObject::MarkVisible( - void - ) -{ - double* fl = GetOpenGLMatrixPtr()->getPointer(); - for (size_t i=0;iMarkVisible(fl, - this, - m_bVisible, - m_bUseObjectColor, - m_objectColor - ); - } -} - - void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local) { - if (m_pPhysicsController1) - m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local); + if (m_pPhysicsController1) + { + MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel; + m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0); + } } @@ -883,15 +918,18 @@ void KX_GameObject::Suspend() PyMethodDef KX_GameObject::Methods[] = { {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, + {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"getLinearVelocity", (PyCFunction) KX_GameObject::sPyGetLinearVelocity, METH_VARARGS}, {"setLinearVelocity", (PyCFunction) KX_GameObject::sPySetLinearVelocity, METH_VARARGS}, + {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, + {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS}, {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS}, {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS}, {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS}, - {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_O}, + {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS}, {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, @@ -1032,18 +1070,23 @@ PyObject* KX_GameObject::_getattr(const STR_String& attr) int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr method { - if (attr == "mass") + if (attr == "mass") { + PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only"); return 1; + } - if (attr == "parent") + if (attr == "parent") { + PyErr_SetString(PyExc_AttributeError, "attribute \"mass\" is read only\nUse setParent()"); return 1; + } if (PyInt_Check(value)) { int val = PyInt_AsLong(value); if (attr == "visible") { - SetVisible(val != 0); + SetVisible(val != 0, false); + UpdateBuckets(false); return 0; } } @@ -1102,7 +1145,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr } return 1; } - + PyErr_SetString(PyExc_AttributeError, "could not set the orientation from a 3x3 matrix, quaternion or euler sequence"); return 1; } @@ -1146,9 +1189,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr } -PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... int local = 0; @@ -1162,9 +1203,7 @@ PyObject* KX_GameObject::PyGetLinearVelocity(PyObject* self, } } -PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, PyObject* args) { int local = 0; PyObject* pyvect; @@ -1179,17 +1218,43 @@ PyObject* KX_GameObject::PySetLinearVelocity(PyObject* self, return NULL; } -PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* value) +PyObject* KX_GameObject::PyGetAngularVelocity(PyObject* self, PyObject* args) { - int visible = PyInt_AsLong(value); - - if (visible==-1 && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "expected 0 or 1"); + // only can get the velocity if we have a physics object connected to us... + int local = 0; + if (PyArg_ParseTuple(args,"|i",&local)) + { + return PyObjectFrom(GetAngularVelocity((local!=0))); + } + else + { return NULL; } +} + +PyObject* KX_GameObject::PySetAngularVelocity(PyObject* self, PyObject* args) +{ + int local = 0; + PyObject* pyvect; - MarkVisible(visible!=0); - m_bVisible = (visible!=0); + if (PyArg_ParseTuple(args,"O|i",&pyvect,&local)) { + MT_Vector3 velocity; + if (PyVecTo(pyvect, velocity)) { + setAngularVelocity(velocity, (local!=0)); + Py_RETURN_NONE; + } + } + return NULL; +} + +PyObject* KX_GameObject::PySetVisible(PyObject* self, PyObject* args) +{ + int visible, recursive = 0; + if (!PyArg_ParseTuple(args,"i|i",&visible, &recursive)) + return NULL; + + SetVisible(visible ? true:false, recursive ? true:false); + UpdateBuckets(recursive ? true:false); Py_RETURN_NONE; } @@ -1228,9 +1293,7 @@ PyObject* KX_GameObject::PySetState(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyGetVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyGetVelocity(PyObject* self, PyObject* args) { // only can get the velocity if we have a physics object connected to us... MT_Vector3 velocity(0.0,0.0,0.0); @@ -1362,9 +1425,7 @@ PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self) return list; } -PyObject* KX_GameObject::PyGetMesh(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args) { int mesh = 0; @@ -1404,9 +1465,7 @@ PyObject* KX_GameObject::PySetCollisionMargin(PyObject* self, PyObject* value) -PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyApplyImpulse(PyObject* self, PyObject* args) { PyObject* pyattach; PyObject* pyimpulse; @@ -1477,9 +1536,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self, PyObject* value) return NULL; } -PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, PyObject* args) { PyObject* pyvect; int axis = 2; //z axis is the default @@ -1524,6 +1581,19 @@ PyObject* KX_GameObject::PySetPosition(PyObject* self, PyObject* value) return NULL; } +PyObject* KX_GameObject::PySetWorldPosition(PyObject* self, PyObject* value) +{ + MT_Point3 pos; + if (PyVecTo(value, pos)) + { + NodeSetWorldPosition(pos); + NodeUpdateGS(0.f,true); + Py_RETURN_NONE; + } + + return NULL; +} + PyObject* KX_GameObject::PyGetPhysicsId(PyObject* self) { KX_IPhysicsController* ctrl = GetPhysicsController(); @@ -1609,25 +1679,45 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, return returnValue; } -bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { - KX_GameObject* hitKXObj = client->m_gameobject; - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } - - if (m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) + // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit + // if not, all objects were tested and the front one may not be the correct one. + if (m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) { m_pHitObject = hitKXObj; return true; } + // return true to stop RayCast::RayTest from looping, the above test was decisive + // We would want to loop only if we want to get more than one hit point + return true; +} - return false; +/* this function is used to pre-filter the object before casting the ray on them. + This is useful for "X-Ray" option when we want to see "through" unwanted object. + */ +bool KX_GameObject::NeedRayCast(KX_ClientObjectInfo* client) +{ + KX_GameObject* hitKXObj = client->m_gameobject; + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // Unknown type of object, skip it. + // Should not occur as the sensor objects are filtered in RayTest() + printf("Invalid client type %d found in ray casting\n", client->m_type); + return false; + } + + // if X-Ray option is selected, skip object that don't match the criteria as we see through them + // if not, test all objects because we don't know yet which one will be on front + if (!m_xray || m_testPropName.Length() == 0 || hitKXObj->GetProperty(m_testPropName) != NULL) + { + return true; + } + // skip the object + return false; } KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, @@ -1667,8 +1757,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, toPoint = fromPoint + (dist) * toDir; } - MT_Point3 resultPoint; - MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); @@ -1682,7 +1770,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, m_testPropName = propName; else m_testPropName.SetLength(0); - KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback(this)); + KX_RayCast::Callback callback(this,spc); + KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); if (m_pHitObject) { @@ -1693,13 +1782,24 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, } KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, - "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n" -" prop = property name that object must have; can be omitted => detect any object\n" -" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" + "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n" + " If no hit, return (None,None,None) or (None,None,None,None).\n" +" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" " Can be None or omitted => start from self object center\n" -" to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" -"Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n") +" dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" +" prop = property name that object must have; can be omitted => detect any object\n" +" face = normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin\n" +" xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n" +" poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n" +" which can be None if hit object has no mesh or if there is no hit\n" +" If 0 or omitted, return value is a 3-tuple\n" +"Note: The object on which you call this method matters: the ray will ignore it.\n" +" prop and xray option interact as follow:\n" +" prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray\n" +" prop off, xray on : idem\n" +" prop on, xray off: return closest hit if it matches prop, no hit otherwise\n" +" prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n") { MT_Point3 toPoint; MT_Point3 fromPoint; @@ -1708,8 +1808,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, float dist = 0.0f; char *propName = NULL; KX_GameObject *other; + int face=0, xray=0, poly=0; - if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) { + if (!PyArg_ParseTuple(args,"O|Ofsiii", &pyto, &pyfrom, &dist, &propName, &face, &xray, &poly)) { return NULL; // Python sets a simple error } @@ -1755,8 +1856,6 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } - MT_Point3 resultPoint; - MT_Vector3 resultNormal; PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); KX_IPhysicsController *spc = GetPhysicsController(); KX_GameObject *parent = GetParent(); @@ -1770,20 +1869,41 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, m_testPropName = propName; else m_testPropName.SetLength(0); - KX_RayCast::RayTest(spc, pe, fromPoint, toPoint, resultPoint, resultNormal, KX_RayCast::Callback(this)); + m_xray = xray; + // to get the hit results + KX_RayCast::Callback callback(this,spc,NULL,face); + KX_RayCast::RayTest(pe, fromPoint, toPoint, callback); - if (m_pHitObject) + if (m_pHitObject) { - PyObject* returnValue = PyTuple_New(3); + PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3); if (returnValue) { // unlikely this would ever fail, if it does python sets an error PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); - PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); - PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(callback.m_hitNormal)); + if (poly) + { + if (callback.m_hitMesh) + { + // if this field is set, then we can trust that m_hitPolygon is a valid polygon + RAS_Polygon* poly = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); + KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, poly); + PyTuple_SET_ITEM(returnValue, 3, polyproxy); + } + else + { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(returnValue, 3, Py_None); + } + } } return returnValue; } - return Py_BuildValue("OOO", Py_None, Py_None, Py_None); - //Py_RETURN_NONE; + // no hit + if (poly) + return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None); + else + return Py_BuildValue("OOO", Py_None, Py_None, Py_None); } /* --------------------------------------------------------------------- diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index a7ac2d75a93..2da0be4df25 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -54,6 +54,7 @@ //Forward declarations. struct KX_ClientObjectInfo; +class KX_RayCast; class RAS_MeshObject; class KX_IPhysicsController; class PHY_IPhysicsEnvironment; @@ -74,20 +75,23 @@ protected: int m_layer; std::vector m_meshes; struct Object* m_pBlenderObject; + struct Object* m_pBlenderGroupObject; bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; - // Is this object set to be visible? Only useful for the - // visibility subsystem right now. - bool m_bVisible; + // visible = user setting + // culled = while rendering, depending on camera + bool m_bVisible; + bool m_bCulled; KX_IPhysicsController* m_pPhysicsController1; // used for ray casting PHY_IPhysicsEnvironment* m_pPhysicsEnvironment; STR_String m_testPropName; + bool m_xray; KX_GameObject* m_pHitObject; SG_Node* m_pSGNode; @@ -393,6 +397,16 @@ public: { m_pBlenderObject = obj; } + + struct Object* GetBlenderGroupObject( ) + { + return m_pBlenderGroupObject; + } + + void SetBlenderGroupObject( struct Object* obj) + { + m_pBlenderGroupObject = obj; + } bool IsDupliGroup() { @@ -428,7 +442,8 @@ public: return (m_pSGNode && m_pSGNode->GetSGParent() && m_pSGNode->GetSGParent()->IsVertexParent()); } - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client); /** @@ -535,18 +550,23 @@ public: /** * @section Mesh accessor functions. */ - + /** - * Run through the meshes associated with this - * object and bucketize them. See RAS_Mesh for - * more details on this function. Interesting to - * note that polygon bucketizing seems to happen on a per - * object basis. Which may explain why there is such - * a big performance gain when all static objects - * are joined into 1. + * Update buckets to indicate that there is a new + * user of this object's meshes. */ void - Bucketize( + AddMeshUser( + ); + + /** + * Update buckets with data about the mesh after + * creating or duplicating the object, changing + * visibility, object color, .. . + */ + void + UpdateBuckets( + bool recursive ); /** @@ -607,25 +627,8 @@ public: ResetDebugColor( ); - /** - * Set the visibility of the meshes associated with this - * object. - */ - void - MarkVisible( - bool visible - ); - - /** - * Set the visibility according to the visibility flag. - */ - void - MarkVisible( - void - ); - /** - * Was this object marked visible? (only for the ewxplicit + * Was this object marked visible? (only for the explicit * visibility system). */ bool @@ -638,7 +641,24 @@ public: */ void SetVisible( - bool b + bool b, + bool recursive + ); + + /** + * Was this object culled? + */ + bool + GetCulled( + void + ); + + /** + * Set culled flag of this object + */ + void + SetCulled( + bool c ); /** @@ -666,6 +686,14 @@ public: void ) { return m_bIsNegativeScaling; } + /** + * Is this a light? + */ + virtual bool + IsLight( + void + ) { return false; } + /** * @section Logic bubbling methods. */ @@ -726,31 +754,34 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,GetPosition); KX_PYMETHOD_O(KX_GameObject,SetPosition); - KX_PYMETHOD(KX_GameObject,GetLinearVelocity); - KX_PYMETHOD(KX_GameObject,SetLinearVelocity); - KX_PYMETHOD(KX_GameObject,GetVelocity); + KX_PYMETHOD_O(KX_GameObject,SetWorldPosition); + KX_PYMETHOD_VARARGS(KX_GameObject,GetLinearVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,SetLinearVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity); KX_PYMETHOD_NOARGS(KX_GameObject,GetMass); KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce); KX_PYMETHOD_NOARGS(KX_GameObject,GetOrientation); KX_PYMETHOD_O(KX_GameObject,SetOrientation); KX_PYMETHOD_NOARGS(KX_GameObject,GetVisible); - KX_PYMETHOD_O(KX_GameObject,SetVisible); + KX_PYMETHOD_VARARGS(KX_GameObject,SetVisible); KX_PYMETHOD_NOARGS(KX_GameObject,GetState); KX_PYMETHOD_O(KX_GameObject,SetState); - KX_PYMETHOD(KX_GameObject,AlignAxisToVect); + KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); - KX_PYMETHOD(KX_GameObject,ApplyImpulse); + KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse); KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin); KX_PYMETHOD_NOARGS(KX_GameObject,GetParent); KX_PYMETHOD_O(KX_GameObject,SetParent); KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive); - KX_PYMETHOD(KX_GameObject,GetMesh); + KX_PYMETHOD_VARARGS(KX_GameObject,GetMesh); KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId); KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames); KX_PYMETHOD_NOARGS(KX_GameObject,EndObject); diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index d3aa924665e..6223643f75a 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -143,7 +143,7 @@ bool KX_IpoSGController::Update(double currentTime) { if (m_ipo_as_force == true) { - if (m_game_object && ob) + if (m_game_object && ob && m_game_object->GetPhysicsController()) { m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ? ob->GetWorldOrientation() * m_ipo_xform.GetPosition() : diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index f069048cd3d..3709fa8c784 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -32,6 +32,8 @@ #include "STR_String.h" #include "KX_Python.h" +struct Scene; + class KX_ISceneConverter { @@ -77,6 +79,8 @@ public: // use blender glsl materials virtual void SetGLSLMaterials(bool val) =0; virtual bool GetGLSLMaterials()=0; + + virtual struct Scene* GetBlenderSceneForName(const STR_String& name)=0; }; #endif //__KX_ISCENECONVERTER_H diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index a203ea6a6ff..75e4ade6574 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -130,7 +130,6 @@ void KX_IpoActuator::SetStartTime(float curtime) { float direction = m_startframe < m_endframe ? 1.0f : -1.0f; - curtime = curtime - KX_KetsjiEngine::GetSuspendedDelta(); if (m_direction > 0) m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate(); else @@ -139,7 +138,7 @@ void KX_IpoActuator::SetStartTime(float curtime) void KX_IpoActuator::SetLocalTime(float curtime) { - float delta_time = ((curtime - m_starttime) - KX_KetsjiEngine::GetSuspendedDelta())*KX_KetsjiEngine::GetAnimFrameRate(); + float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate(); // negative delta_time is caused by floating point inaccuracy // perhaps the inaccuracy could be reduced a bit @@ -165,6 +164,8 @@ bool KX_IpoActuator::Update(double curtime, bool frame) int numevents = 0; bool bIpoStart = false; + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + if (frame) { numevents = m_events.size(); @@ -180,7 +181,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) if (m_starttime < -2.0f*start_smaller_then_end*(m_endframe - m_startframe)) { // start for all Ipo, initial start for LOOP_STOP - m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta(); + m_starttime = curtime; m_bIpoPlaying = true; bIpoStart = true; } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 1d6cc975ab5..c7b0d7b3ea3 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -96,6 +96,7 @@ double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE; double KX_KetsjiEngine::m_anim_framerate = 25.0; double KX_KetsjiEngine::m_suspendedtime = 0.0; double KX_KetsjiEngine::m_suspendeddelta = 0.0; +double KX_KetsjiEngine::m_average_framerate = 0.0; /** @@ -134,6 +135,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_overrideCam(false), m_overrideCamUseOrtho(false), + m_overrideCamNear(0.0), + m_overrideCamFar(0.0), m_stereo(false), m_curreye(0), @@ -275,30 +278,73 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) } +void KX_KetsjiEngine::ClearFrame() +{ + // clear unless we're drawing overlapping stereo + if(m_rasterizer->InterlacedStereo() && + m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE) + return; + + // clear the viewports with the background color of the first scene + bool doclear = false; + KX_SceneList::iterator sceneit; + RAS_Rect clearvp, area, viewport; + + for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++) + { + KX_Scene* scene = *sceneit; + //const RAS_FrameSettings &framesettings = scene->GetFramingType(); + list* cameras = scene->GetCameras(); + + list::iterator it; + for(it = cameras->begin(); it != cameras->end(); it++) + { + GetSceneViewport(scene, (*it), area, viewport); + + if(!doclear) { + clearvp = viewport; + doclear = true; + } + else { + if(viewport.GetLeft() < clearvp.GetLeft()) + clearvp.SetLeft(viewport.GetLeft()); + if(viewport.GetBottom() < clearvp.GetBottom()) + clearvp.SetBottom(viewport.GetBottom()); + if(viewport.GetRight() > clearvp.GetRight()) + clearvp.SetRight(viewport.GetRight()); + if(viewport.GetTop() > clearvp.GetTop()) + clearvp.SetTop(viewport.GetTop()); + + } + } + } + + if(doclear) { + KX_Scene* firstscene = *m_scenes.begin(); + SetBackGround(firstscene->GetWorldInfo()); + + m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), + clearvp.GetRight(), clearvp.GetTop()); + m_rasterizer->ClearColorBuffer(); + } +} + bool KX_KetsjiEngine::BeginFrame() { - bool result = false; - - RAS_Rect vp; - KX_Scene* firstscene = *m_scenes.begin(); - const RAS_FrameSettings &framesettings = firstscene->GetFramingType(); - - // set the area used for rendering + // set the area used for rendering (stereo can assign only a subset) m_rasterizer->SetRenderArea(); - RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp); - if (m_canvas->BeginDraw()) { - result = true; + ClearFrame(); - m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop()); - SetBackGround( firstscene->GetWorldInfo() ); - m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds()); - m_rendertools->BeginFrame( m_rasterizer); + m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds()); + m_rendertools->BeginFrame(m_rasterizer); + + return true; } - return result; + return false; } @@ -310,6 +356,12 @@ void KX_KetsjiEngine::EndFrame() { RenderDebugProperties(); } + + m_average_framerate = m_logger->GetAverage(); + if (m_average_framerate < 1e-6) + m_average_framerate = 1e-6; + m_average_framerate = 1.0/m_average_framerate; + // Go to next profiling measurement, time spend after this call is shown in the next frame. m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds()); @@ -321,8 +373,6 @@ void KX_KetsjiEngine::EndFrame() m_canvas->EndDraw(); - - } //#include "PIL_time.h" @@ -601,7 +651,7 @@ void KX_KetsjiEngine::Render() ); } // clear the -whole- viewport - m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); } m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); @@ -630,9 +680,6 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - SetupRenderFrame(scene, cam); - // do the rendering RenderFrame(scene, cam); } @@ -650,9 +697,6 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - SetupRenderFrame(scene, (*it)); - // do the rendering RenderFrame(scene, (*it)); } @@ -685,10 +729,6 @@ void KX_KetsjiEngine::Render() //pass the scene, for picking and raycasting (shadows) m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - //SetupRenderFrame(scene); - SetupRenderFrame(scene, cam); - // do the rendering //RenderFrame(scene); RenderFrame(scene, cam); @@ -848,8 +888,13 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat) m_overrideCamViewMat = mat; } - -void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) +void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far) +{ + m_overrideCamNear = near; + m_overrideCamFar = far; +} + +void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) { // In this function we make sure the rasterizer settings are upto // date. We compute the viewport so that logic @@ -857,17 +902,26 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) // Note we postpone computation of the projection matrix // so that we are using the latest camera position. - - RAS_Rect viewport; - - if (!cam) - return; - if (cam->GetViewport()) { - viewport.SetLeft(cam->GetViewportLeft()); - viewport.SetBottom(cam->GetViewportBottom()); - viewport.SetRight(cam->GetViewportRight()); - viewport.SetTop(cam->GetViewportTop()); + RAS_Rect userviewport; + + userviewport.SetLeft(cam->GetViewportLeft()); + userviewport.SetBottom(cam->GetViewportBottom()); + userviewport.SetRight(cam->GetViewportRight()); + userviewport.SetTop(cam->GetViewportTop()); + + // Don't do bars on user specified viewport + RAS_FrameSettings settings = scene->GetFramingType(); + if(settings.FrameType() == RAS_FrameSettings::e_frame_bars) + settings.SetFrameType(RAS_FrameSettings::e_frame_extend); + + RAS_FramingManager::ComputeViewport( + scene->GetFramingType(), + userviewport, + viewport + ); + + area = userviewport; } else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { RAS_FramingManager::ComputeViewport( @@ -875,33 +929,32 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) m_canvas->GetDisplayArea(), viewport ); + + area = m_canvas->GetDisplayArea(); } else { viewport.SetLeft(0); viewport.SetBottom(0); viewport.SetRight(int(m_canvas->GetWidth())); viewport.SetTop(int(m_canvas->GetHeight())); + + area = m_canvas->GetDisplayArea(); } - // store the computed viewport in the scene - - scene->SetSceneViewport(viewport); - - // set the viewport for this frame and scene - m_canvas->SetViewPort( - viewport.GetLeft(), - viewport.GetBottom(), - viewport.GetRight(), - viewport.GetTop() - ); - } void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) { - CListValue *lightlist = scene->GetLightList(); + CListValue *objectlist = scene->GetObjectList(); int i, drawmode; - for(i=0; iGetCount(); i++) { - KX_LightObject *light = (KX_LightObject*)lightlist->GetValue(i); + m_rendertools->SetAuxilaryClientInfo(scene); + + for(i=0; iGetCount(); i++) { + KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i); + + if(!gameobj->IsLight()) + continue; + + KX_LightObject *light = (KX_LightObject*)gameobj; light->Update(); @@ -939,18 +992,32 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { + bool override_camera; + RAS_Rect viewport, area; float left, right, bottom, top, nearfrust, farfrust, focallength; const float ortho = 100.0; // KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; + + GetSceneViewport(scene, cam, area, viewport); + + // store the computed viewport in the scene + scene->SetSceneViewport(viewport); + + // set the viewport for this frame and scene + m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(), + viewport.GetRight(), viewport.GetTop()); // see KX_BlenderMaterial::Activate //m_rasterizer->SetAmbient(); m_rasterizer->DisplayFog(); - if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) { + override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName); + override_camera = override_camera && (cam->GetName() == "__default__cam__"); + + if (override_camera && m_overrideCamUseOrtho) { MT_CmMatrix4x4 projmat = m_overrideCamProjMat; m_rasterizer->SetProjectionMatrix(projmat); } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) @@ -960,12 +1027,17 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { RAS_FrameFrustum frustum; float lens = cam->GetLens(); + bool orthographic = !cam->GetCameraData()->m_perspective; nearfrust = cam->GetCameraNear(); farfrust = cam->GetCameraFar(); focallength = cam->GetFocalLength(); - if (!cam->GetCameraData()->m_perspective) - { + if(override_camera) { + nearfrust = m_overrideCamNear; + farfrust = m_overrideCamFar; + } + + if (orthographic) { lens *= ortho; nearfrust = (nearfrust + 1.0)*ortho; farfrust *= ortho; @@ -973,8 +1045,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) RAS_FramingManager::ComputeFrustum( scene->GetFramingType(), - m_canvas->GetDisplayArea(), - scene->GetSceneViewport(), + area, + viewport, lens, nearfrust, farfrust, @@ -990,7 +1062,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( left, right, bottom, top, nearfrust, farfrust, focallength); - + cam->SetProjectionMatrix(projmat); // Otherwise the projection matrix for each eye will be the same... @@ -1281,12 +1353,13 @@ void KX_KetsjiEngine::RemoveScheduledScenes() KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename) { - + Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename); KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice, m_mousedevice, m_networkdevice, m_audiodevice, - scenename); + scenename, + scene); m_sceneconverter->ConvertScene(scenename, tmpscene, @@ -1442,6 +1515,11 @@ void KX_KetsjiEngine::SetAnimFrameRate(double framerate) m_anim_framerate = framerate; } +double KX_KetsjiEngine::GetAverageFrameRate() +{ + return m_average_framerate; +} + void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties) { m_show_framerate = frameRate; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 77b69ec2d9e..1aa067a9962 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -124,6 +124,8 @@ private: bool m_overrideCamUseOrtho; MT_CmMatrix4x4 m_overrideCamProjMat; MT_CmMatrix4x4 m_overrideCamViewMat; + float m_overrideCamNear; + float m_overrideCamFar; bool m_stereo; int m_curreye; @@ -149,6 +151,8 @@ private: /** Labels for profiling display. */ static const char m_profileLabels[tc_numCategories][15]; + /** Last estimated framerate */ + static double m_average_framerate; /** Show the framerate on the game display? */ bool m_show_framerate; /** Show profiling info on the game display? */ @@ -175,7 +179,6 @@ private: /** Blue component of framing bar color. */ float m_overrideFrameColorB; - void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); void RenderFrame(KX_Scene* scene, KX_Camera* cam); void PostRenderFrame(); void RenderDebugProperties(); @@ -226,6 +229,8 @@ public: void SuspendScene(const STR_String& scenename); void ResumeScene(const STR_String& scenename); + void GetSceneViewport(KX_Scene* scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); + void SetDrawType(int drawingtype); void SetCameraZoom(float camzoom); @@ -234,6 +239,7 @@ public: void SetCameraOverrideUseOrtho(bool useOrtho); void SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat); void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat); + void SetCameraOverrideClipping(float near, float far); /** * Sets display of all frames. @@ -271,6 +277,11 @@ public: */ static void SetAnimFrameRate(double framerate); + /** + * Gets the last estimated average framerate + */ + static double GetAverageFrameRate(); + /** * Activates or deactivates timing information display. * @param frameRate Display for frame rate on or off. @@ -348,6 +359,7 @@ protected: KX_Scene* CreateScene(const STR_String& scenename); bool BeginFrame(); + void ClearFrame(); void EndFrame(); }; diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 4e3d6180d22..e0f171e78e0 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -42,14 +42,13 @@ #include "KX_PyMath.h" -#ifdef BLENDER_GLSL +#include "DNA_object_types.h" #include "GPU_material.h" -#endif KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, class RAS_IRenderTools* rendertools, const RAS_LightObject& lightobj, - struct GPULamp *gpulamp, + bool glsl, PyTypeObject* T ) : @@ -59,12 +58,20 @@ KX_LightObject::KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks, m_lightobj = lightobj; m_lightobj.m_worldmatrix = GetOpenGLMatrixPtr(); m_rendertools->AddLight(&m_lightobj); - m_gpulamp = gpulamp; + m_glsl = glsl; + m_blenderscene = ((KX_Scene*)sgReplicationInfo)->GetBlenderScene(); }; KX_LightObject::~KX_LightObject() { + GPULamp *lamp; + + if((lamp = GetGPULamp())) { + float obmat[4][4] = {{0}}; + GPU_lamp_update(lamp, 0, obmat); + } + m_rendertools->RemoveLight(&m_lightobj); } @@ -73,7 +80,7 @@ CValue* KX_LightObject::GetReplica() { KX_LightObject* replica = new KX_LightObject(*this); - + // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -81,13 +88,23 @@ CValue* KX_LightObject::GetReplica() replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr(); m_rendertools->AddLight(&replica->m_lightobj); + return replica; } +GPULamp *KX_LightObject::GetGPULamp() +{ + if(m_glsl) + return GPU_lamp_from_blender(m_blenderscene, GetBlenderObject(), GetBlenderGroupObject()); + else + return false; +} + void KX_LightObject::Update() { -#ifdef BLENDER_GLSL - if(m_gpulamp) { + GPULamp *lamp; + + if((lamp = GetGPULamp())) { float obmat[4][4]; double *dobmat = GetOpenGLMatrixPtr()->getPointer(); @@ -95,38 +112,39 @@ void KX_LightObject::Update() for(int j=0; j<4; j++, dobmat++) obmat[i][j] = (float)*dobmat; - GPU_lamp_update(m_gpulamp, obmat); + GPU_lamp_update(lamp, m_lightobj.m_layer, obmat); } -#endif } bool KX_LightObject::HasShadowBuffer() { -#ifdef BLENDER_GLSL - return (m_gpulamp && GPU_lamp_has_shadow_buffer(m_gpulamp)); -#else - return false; -#endif + GPULamp *lamp; + + if((lamp = GetGPULamp())) + return GPU_lamp_has_shadow_buffer(lamp); + else + return false; } int KX_LightObject::GetShadowLayer() { -#ifdef BLENDER_GLSL - if(m_gpulamp) - return GPU_lamp_shadow_layer(m_gpulamp); + GPULamp *lamp; + + if((lamp = GetGPULamp())) + return GPU_lamp_shadow_layer(lamp); else -#endif return 0; } void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_Transform& camtrans) { -#ifdef BLENDER_GLSL + GPULamp *lamp; float viewmat[4][4], winmat[4][4]; int winsize; /* bind framebuffer */ - GPU_lamp_shadow_buffer_bind(m_gpulamp, viewmat, &winsize, winmat); + lamp = GetGPULamp(); + GPU_lamp_shadow_buffer_bind(lamp, viewmat, &winsize, winmat); /* setup camera transformation */ MT_Matrix4x4 modelviewmat((float*)viewmat); @@ -146,14 +164,12 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T ras->SetProjectionMatrix(projectionmat); ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(), cam->GetCameraLocation(), cam->GetCameraOrientation()); -#endif } void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) { -#ifdef BLENDER_GLSL - GPU_lamp_shadow_buffer_unbind(m_gpulamp); -#endif + GPULamp *lamp = GetGPULamp(); + GPU_lamp_shadow_buffer_unbind(lamp); } PyObject* KX_LightObject::_getattr(const STR_String& attr) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 62eb26c61a8..e5dbf0b7f4a 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -33,6 +33,7 @@ #include "KX_GameObject.h" struct GPULamp; +struct Scene; class KX_Camera; class RAS_IRasterizer; class RAS_IRenderTools; @@ -44,16 +45,18 @@ class KX_LightObject : public KX_GameObject protected: RAS_LightObject m_lightobj; class RAS_IRenderTools* m_rendertools; //needed for registering and replication of lightobj - struct GPULamp *m_gpulamp; - static char doc[]; + bool m_glsl; + Scene* m_blenderscene; + static char doc[]; public: - KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, struct GPULamp *gpulamp, PyTypeObject *T = &Type); + KX_LightObject(void* sgReplicationInfo,SG_Callbacks callbacks,class RAS_IRenderTools* rendertools,const struct RAS_LightObject& lightobj, bool glsl, PyTypeObject *T = &Type); virtual ~KX_LightObject(); virtual CValue* GetReplica(); RAS_LightObject* GetLightData() { return &m_lightobj;} /* GLSL shadow */ + struct GPULamp *GetGPULamp(); bool HasShadowBuffer(); int GetShadowLayer(); void BindShadowBuffer(class RAS_IRasterizer *ras, class KX_Camera *cam, class MT_Transform& camtrans); @@ -62,6 +65,8 @@ public: virtual PyObject* _getattr(const STR_String& attr); /* lens, near, far, projection_matrix */ virtual int _setattr(const STR_String& attr, PyObject *pyvalue); + + virtual bool IsLight(void) { return true; } }; #endif //__KX_LIGHT diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index a0ac9cfd4ff..5cc102248f2 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -35,6 +35,7 @@ #include "RAS_MeshObject.h" #include "KX_VertexProxy.h" +#include "KX_PolyProxy.h" #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" @@ -42,6 +43,8 @@ #include "KX_PyMath.h" #include "KX_ConvertPhysicsObject.h" +#include "PyObjectPlus.h" + PyTypeObject KX_MeshProxy::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -71,10 +74,12 @@ PyParentObject KX_MeshProxy::Parents[] = { PyMethodDef KX_MeshProxy::Methods[] = { {"getNumMaterials", (PyCFunction)KX_MeshProxy::sPyGetNumMaterials,METH_VARARGS}, +{"getNumPolygons", (PyCFunction)KX_MeshProxy::sPyGetNumPolygons,METH_NOARGS}, {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, +{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, KX_PYMETHODTABLE(KX_MeshProxy, reinstancePhysicsMesh), //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, @@ -93,10 +98,11 @@ KX_MeshProxy::_getattr(const STR_String& attr) if (attr == "materials") { PyObject *materials = PyList_New(0); - RAS_MaterialBucket::Set::iterator mit = m_meshobj->GetFirstMaterial(); + list::iterator mit = m_meshobj->GetFirstMaterial(); for(; mit != m_meshobj->GetLastMaterial(); ++mit) { - RAS_IPolyMaterial *polymat = (*mit)->GetPolyMaterial(); + RAS_IPolyMaterial *polymat = mit->m_bucket->GetPolyMaterial(); + if(polymat->GetFlag() & RAS_BLENDERMAT) { KX_BlenderMaterial *mat = static_cast(polymat); @@ -146,6 +152,12 @@ PyObject* KX_MeshProxy::PyGetNumMaterials(PyObject* self, return PyInt_FromLong(num); } +PyObject* KX_MeshProxy::PyGetNumPolygons(PyObject* self) +{ + int num = m_meshobj->NumPolygons(); + return PyInt_FromLong(num); +} + PyObject* KX_MeshProxy::PyGetMaterialName(PyObject* self, PyObject* args, PyObject* kwds) @@ -195,11 +207,11 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* self, if (PyArg_ParseTuple(args,"i",&matid)) { - RAS_IPolyMaterial* mat = m_meshobj->GetMaterialBucket(matid)->GetPolyMaterial(); + RAS_MeshMaterial *mmat = m_meshobj->GetMeshMaterial(matid); + RAS_IPolyMaterial* mat = mmat->m_bucket->GetPolyMaterial(); + if (mat) - { - length = m_meshobj->GetVertexArrayLength(mat); - } + length = m_meshobj->NumVertices(mat); } else { return NULL; @@ -234,6 +246,28 @@ PyObject* KX_MeshProxy::PyGetVertex(PyObject* self, } +PyObject* KX_MeshProxy::PyGetPolygon(PyObject* self, + PyObject* args, + PyObject* kwds) +{ + int polyindex= 1; + PyObject* polyob = NULL; + + if (!PyArg_ParseTuple(args,"i",&polyindex)) + return NULL; + + RAS_Polygon* polygon = m_meshobj->GetPolygon(polyindex); + if (polygon) + { + polyob = new KX_PolyProxy(m_meshobj, polygon); + } + else + { + PyErr_SetString(PyExc_AttributeError, "Invalid polygon index"); + } + return polyob; +} + KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh, "Reinstance the physics mesh.") { diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 7c6202c15a4..3335c349673 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -57,10 +57,12 @@ public: KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); KX_PYMETHOD(KX_MeshProxy,GetMaterialName); KX_PYMETHOD(KX_MeshProxy,GetTextureName); + KX_PYMETHOD_NOARGS(KX_MeshProxy,GetNumPolygons); // both take materialid (int) KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); + KX_PYMETHOD(KX_MeshProxy,GetPolygon); KX_PYMETHOD_DOC(KX_MeshProxy, reinstancePhysicsMesh); }; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index db0bef8b7e1..6f76448707c 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -62,12 +62,14 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, int focusmode, RAS_ICanvas* canvas, KX_Scene* kxscene, + KX_KetsjiEngine *kxengine, SCA_IObject* gameobj, PyTypeObject* T) : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T), m_focusmode(focusmode), m_gp_canvas(canvas), - m_kxscene(kxscene) + m_kxscene(kxscene), + m_kxengine(kxengine) { Init(); } @@ -122,16 +124,10 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event) return result; } -bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, KX_RayCast* result, void * const data) { KX_GameObject* hitKXObj = client_info->m_gameobject; - if (client_info->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } - /* Is this me? In the ray test, there are a lot of extra checks * for aliasing artefacts from self-hits. That doesn't happen * here, so a simple test suffices. Or does the camera also get @@ -142,8 +138,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo* client_info, MT_Point3& hi if ((m_focusmode == 2) || hitKXObj == thisObj) { m_hitObject = hitKXObj; - m_hitPosition = hit_point; - m_hitNormal = hit_normal; + m_hitPosition = result->m_hitPoint; + m_hitNormal = result->m_hitNormal; return true; } @@ -158,8 +154,6 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) m_hitObject = 0; m_hitPosition = MT_Vector3(0,0,0); m_hitNormal = MT_Vector3(1,0,0); - MT_Point3 resultpoint; - MT_Vector3 resultnormal; /* All screen handling in the gameengine is done by GL, * specifically the model/view and projection parts. The viewport @@ -201,11 +195,14 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) * calculations don't bomb. Maybe we should explicitly guard for * division by 0.0...*/ - /** - * Get the scenes current viewport. - */ + KX_Camera* cam = m_kxscene->GetActiveCamera(); - const RAS_Rect & viewport = m_kxscene->GetSceneViewport(); + /* get the scenes current viewport. we recompute it because there + * may be multiple cameras and m_kxscene->GetSceneViewport() only + * has the one that was last drawn */ + + RAS_Rect area, viewport; + m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport); float height = float(viewport.m_y2 - viewport.m_y1 + 1); float width = float(viewport.m_x2 - viewport.m_x1 + 1); @@ -213,9 +210,9 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) float x_lb = float(viewport.m_x1); float y_lb = float(viewport.m_y1); - KX_Camera* cam = m_kxscene->GetActiveCamera(); /* There's some strangeness I don't fully get here... These values * _should_ be wrong! */ + /* old: */ float nearclip = 0.0; @@ -280,7 +277,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) bool result = false; - result = KX_RayCast::RayTest(physics_controller, physics_environment, frompoint3, topoint3, resultpoint, resultnormal, KX_RayCast::Callback(this)); + KX_RayCast::Callback callback(this,physics_controller); + KX_RayCast::RayTest(physics_environment, frompoint3, topoint3, callback); result = (m_hitObject!=0); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index b011ebe1288..6731444699b 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -33,6 +33,8 @@ #include "SCA_MouseSensor.h" +class KX_RayCast; + /** * The mouse focus sensor extends the basic SCA_MouseSensor. It has * been placed in KX because it needs access to the rasterizer and @@ -54,6 +56,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor int focusmode, RAS_ICanvas* canvas, KX_Scene* kxscene, + KX_KetsjiEngine* kxengine, SCA_IObject* gameobj, PyTypeObject* T=&Type ); @@ -76,7 +79,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor return result; }; - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client) { return true; } + /* --------------------------------------------------------------------- */ @@ -138,12 +143,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor MT_Vector3 m_hitNormal; - /** - * Ref to the engine, for retrieving a reference to the current - * scene. */ - class KX_KetsjiEngine* m_engine; - - /** * The active canvas. The size of this canvas determines a part of * the start position of the picking ray. */ @@ -154,6 +153,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor * determines a part of the start location of the picking ray. */ KX_Scene* m_kxscene; + /** + * The KX engine is needed for computing the viewport */ + KX_KetsjiEngine* m_kxengine; }; #endif //__KX_MOUSESENSOR diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 344e0fccc35..3ca121f63f8 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -36,6 +36,8 @@ #include "KX_GameObject.h" #include "KX_PythonInit.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index 9291199d859..da4f05ced7c 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -27,6 +27,8 @@ * ***** END GPL LICENSE BLOCK ***** */ #include +#include "PyObjectPlus.h" + #include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp new file mode 100644 index 00000000000..c6f6bc2db01 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -0,0 +1,265 @@ +/** + * $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 ***** + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "KX_PolyProxy.h" +#include "KX_MeshProxy.h" +#include "RAS_MeshObject.h" +#include "KX_BlenderMaterial.h" +#include "KX_PolygonMaterial.h" + +#include "KX_PyMath.h" + +PyTypeObject KX_PolyProxy::Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "KX_PolyProxy", + sizeof(KX_PolyProxy), + 0, + PyDestructor, + 0, + __getattr, + __setattr, + 0, //&MyPyCompare, + __repr, + 0, //&cvalue_as_number, + 0, + 0, + 0, + 0 +}; + +PyParentObject KX_PolyProxy::Parents[] = { + &KX_PolyProxy::Type, + &SCA_IObject::Type, + &CValue::Type, + NULL +}; + +PyMethodDef KX_PolyProxy::Methods[] = { + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialIndex), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getNumVertex), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isVisible), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,isCollider), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterialName), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getTextureName), + KX_PYMETHODTABLE(KX_PolyProxy,getVertexIndex), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMesh), + KX_PYMETHODTABLE_NOARG(KX_PolyProxy,getMaterial), + {NULL,NULL} //Sentinel +}; + +PyObject* +KX_PolyProxy::_getattr(const STR_String& attr) +{ + if (attr == "matname") + { + return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); + } + if (attr == "texture") + { + return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); + } + if (attr == "material") + { + RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); + if(polymat->GetFlag() & RAS_BLENDERMAT) + { + KX_BlenderMaterial* mat = static_cast(polymat); + Py_INCREF(mat); + return mat; + } + else + { + KX_PolygonMaterial* mat = static_cast(polymat); + Py_INCREF(mat); + return mat; + } + } + if (attr == "matid") + { + // we'll have to scan through the material bucket of the mes and compare with + // the one of the polygon + RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial(); + unsigned int matid; + for (matid=0; matidNumMaterials(); matid++) + { + RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid); + if (meshMat->m_bucket == polyBucket) + // found it + break; + } + return PyInt_FromLong(matid); + } + if (attr == "v1") + { + return PyInt_FromLong(m_polygon->GetVertexOffset(0)); + } + if (attr == "v2") + { + return PyInt_FromLong(m_polygon->GetVertexOffset(1)); + } + if (attr == "v3") + { + return PyInt_FromLong(m_polygon->GetVertexOffset(2)); + } + if (attr == "v4") + { + return PyInt_FromLong(((m_polygon->VertexCount()>3)?m_polygon->GetVertexOffset(3):0)); + } + if (attr == "visible") + { + return PyInt_FromLong(m_polygon->IsVisible()); + } + if (attr == "collide") + { + return PyInt_FromLong(m_polygon->IsCollider()); + } + _getattr_up(SCA_IObject); +} + +KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon) +: m_mesh((RAS_MeshObject*)mesh), + m_polygon(polygon) +{ +} + +KX_PolyProxy::~KX_PolyProxy() +{ +} + + +// stuff for cvalue related things +CValue* KX_PolyProxy::Calc(VALUE_OPERATOR, CValue *) { return NULL;} +CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { return NULL;} +STR_String sPolyName="polygone"; +const STR_String & KX_PolyProxy::GetText() {return sPolyName;}; +float KX_PolyProxy::GetNumber() { return -1;} +STR_String KX_PolyProxy::GetName() { return sPolyName;} +void KX_PolyProxy::SetName(STR_String) { }; +CValue* KX_PolyProxy::GetReplica() { return NULL;} +void KX_PolyProxy::ReplicaSetName(STR_String) {}; + + +// stuff for python integration + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialIndex, +"getMaterialIndex() : return the material index of the polygon in the mesh\n") +{ + RAS_MaterialBucket* polyBucket = m_polygon->GetMaterial(); + unsigned int matid; + for (matid=0; matidNumMaterials(); matid++) + { + RAS_MeshMaterial* meshMat = m_mesh->GetMeshMaterial(matid); + if (meshMat->m_bucket == polyBucket) + // found it + break; + } + return PyInt_FromLong(matid); +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getNumVertex, +"getNumVertex() : returns the number of vertex of the polygon, 3 or 4\n") +{ + return PyInt_FromLong(m_polygon->VertexCount()); +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isVisible, +"isVisible() : returns whether the polygon is visible or not\n") +{ + return PyInt_FromLong(m_polygon->IsVisible()); +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, isCollider, +"isCollider() : returns whether the polygon is receives collision or not\n") +{ + return PyInt_FromLong(m_polygon->IsCollider()); +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterialName, +"getMaterialName() : returns the polygon material name, \"NoMaterial\" if no material\n") +{ + return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetMaterialName()); +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getTextureName, +"getTexturelName() : returns the polygon texture name, \"NULL\" if no texture\n") +{ + return PyString_FromString(m_polygon->GetMaterial()->GetPolyMaterial()->GetTextureName()); +} + +KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, +"getVertexIndex(vertex) : returns the mesh vertex index of a polygon vertex\n" +"vertex: index of the vertex in the polygon: 0->3\n" +"return value can be used to retrieve the vertex details through mesh proxy\n" +"Note: getVertexIndex(3) on a triangle polygon returns 0\n") +{ + int index; + if (!PyArg_ParseTuple(args,"i",&index)) + { + return NULL; + } + if (index < 0 || index > 3) + { + PyErr_SetString(PyExc_AttributeError, "Valid range for index is 0-3"); + return NULL; + } + if (index < m_polygon->VertexCount()) + { + return PyInt_FromLong(m_polygon->GetVertexOffset(index)); + } + return PyInt_FromLong(0); +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMesh, +"getMesh() : returns a mesh proxy\n") +{ + KX_MeshProxy* meshproxy = new KX_MeshProxy((RAS_MeshObject*)m_mesh); + return meshproxy; +} + +KX_PYMETHODDEF_DOC_NOARG(KX_PolyProxy, getMaterial, +"getMaterial() : returns a material\n") +{ + RAS_IPolyMaterial *polymat = m_polygon->GetMaterial()->GetPolyMaterial(); + if(polymat->GetFlag() & RAS_BLENDERMAT) + { + KX_BlenderMaterial* mat = static_cast(polymat); + Py_INCREF(mat); + return mat; + } + else + { + KX_PolygonMaterial* mat = static_cast(polymat); + Py_INCREF(mat); + return mat; + } +} diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h new file mode 100644 index 00000000000..506e2c2a656 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -0,0 +1,71 @@ +/** + * $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_POLYROXY +#define __KX_POLYPROXY + +#include "SCA_IObject.h" + +class KX_PolyProxy : public SCA_IObject +{ + Py_Header; +protected: + class RAS_Polygon* m_polygon; + class RAS_MeshObject* m_mesh; +public: + KX_PolyProxy(const class RAS_MeshObject*mesh, class RAS_Polygon* polygon); + virtual ~KX_PolyProxy(); + + // stuff for cvalue related things + CValue* Calc(VALUE_OPERATOR op, CValue *val) ; + CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); + const STR_String & GetText(); + float GetNumber(); + STR_String GetName(); + void SetName(STR_String name); // Set the name of the value + void ReplicaSetName(STR_String name); + CValue* GetReplica(); + + +// stuff for python integration + virtual PyObject* _getattr(const STR_String& attr); + + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,isVisible) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,isCollider) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialName) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getTextureName) + KX_PYMETHOD_DOC(KX_PolyProxy,getVertexIndex) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMesh) + KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterial) + +}; + +#endif //__KX_POLYPROXY + diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 144f74a1a4c..c9180bf3a80 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -35,10 +35,6 @@ #include "BKE_global.h" #include "BKE_image.h" -extern "C" { -#include "BDR_drawmesh.h" -} - #include "DNA_material_types.h" #include "DNA_texture_types.h" #include "DNA_image_types.h" @@ -46,6 +42,8 @@ extern "C" { #include "IMB_imbuf_types.h" +#include "GPU_draw.h" + #include "MEM_guardedalloc.h" #include "RAS_LightObject.h" @@ -63,8 +61,6 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, bool alpha, bool zsort, int lightlayer, - bool bIsTriangle, - void* clientobject, struct MTFace* tface, unsigned int* mcol, PyTypeObject *T) @@ -78,9 +74,7 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, transp, alpha, zsort, - lightlayer, - bIsTriangle, - clientobject), + lightlayer), m_tface(tface), m_mcol(mcol), m_material(material), @@ -140,38 +134,29 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c if (GetCachingInfo() != cachingInfo) { if (!cachingInfo) - { - set_tpage(NULL); - } + GPU_set_tpage(NULL); + cachingInfo = GetCachingInfo(); if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)) { - update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime()); - set_tpage(m_tface); - rasty->EnableTextures(true); + Image *ima = (Image*)m_tface->tpage; + GPU_update_image_time(ima, rasty->GetTime()); + GPU_set_tpage(m_tface); } else - { - set_tpage(NULL); - rasty->EnableTextures(false); - } + GPU_set_tpage(NULL); if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) - { rasty->SetCullFace(false); - } else - { rasty->SetCullFace(true); - } - if (m_drawingmode & RAS_IRasterizer::KX_LINES) { + if ((m_drawingmode & RAS_IRasterizer::KX_LINES) || + (rasty->GetDrawingMode() <= RAS_IRasterizer::KX_WIREFRAME)) rasty->SetLines(true); - } - else { + else rasty->SetLines(false); - } } rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity); @@ -253,7 +238,8 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) if (attr == "lightlayer") return PyInt_FromLong(m_lightlayer); if (attr == "triangle") - return PyInt_FromLong(m_bIsTriangle); + // deprecated, triangle/quads shouldn't have been a material property + return 0; if (attr == "diffuse") return PyObjectFrom(m_diffuse); @@ -333,7 +319,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) // This probably won't work... if (attr == "triangle") { - m_bIsTriangle = value; + // deprecated, triangle/quads shouldn't have been a material property return 0; } } @@ -386,7 +372,9 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, updateTexture, "updateTexture(tface, rast { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); RAS_IRasterizer *rasty = (RAS_IRasterizer*) PyCObject_AsVoidPtr(pyrasty); - update_realtime_texture(tface, rasty->GetTime()); + Image *ima = (Image*)tface->tpage; + GPU_update_image_time(ima, rasty->GetTime()); + Py_Return; } @@ -399,7 +387,7 @@ KX_PYMETHODDEF_DOC(KX_PolygonMaterial, setTexture, "setTexture(tface)") if (PyArg_ParseTuple(args, "O!", &PyCObject_Type, &pytface)) { MTFace *tface = (MTFace*) PyCObject_AsVoidPtr(pytface); - set_tpage(tface); + GPU_set_tpage(tface); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 11c8baa8b1f..fe116f757db 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -68,8 +68,6 @@ public: bool alpha, bool zsort, int lightlayer, - bool bIsTriangle, - void* clientobject, struct MTFace* tface, unsigned int* mcol, PyTypeObject *T = &Type); diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 26243c7dba1..ac63e3fade5 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -34,6 +34,8 @@ #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 5d2126ca37a..09c49a15f76 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -57,21 +57,25 @@ #include "BL_ActionActuator.h" #include "RAS_IRasterizer.h" #include "RAS_ICanvas.h" +#include "RAS_BucketManager.h" #include "MT_Vector3.h" #include "MT_Point3.h" #include "ListValue.h" #include "KX_Scene.h" #include "SND_DeviceManager.h" -#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" #include "BL_Shader.h" #include "KX_PyMath.h" +#include "PyObjectPlus.h" + extern "C" { #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. } +#include "marshal.h" /* python header for loading/saving dicts */ + #include "PHY_IPhysicsEnvironment.h" // FIXME: Enable for access to blender python modules. This is disabled because // python has dependencies on a lot of other modules and is a pain to link. @@ -83,6 +87,7 @@ extern "C" { #include "BKE_utildefines.h" #include "BKE_global.h" #include "BLI_blenlib.h" +#include "GPU_material.h" static void setSandbox(TPythonSecurityLevel level); @@ -90,6 +95,7 @@ static void setSandbox(TPythonSecurityLevel level); // 'local' copy of canvas ptr, for window height/width python scripts static RAS_ICanvas* gp_Canvas = NULL; static KX_Scene* gp_KetsjiScene = NULL; +static KX_KetsjiEngine* gp_KetsjiEngine = NULL; static RAS_IRasterizer* gp_Rasterizer = NULL; void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) @@ -121,15 +127,13 @@ static PyObject* gPyGetRandomFloat(PyObject*) static PyObject* gPySetGravity(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_KetsjiScene) - gp_KetsjiScene->SetGravity(vec); - - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; + + if (gp_KetsjiScene) + gp_KetsjiScene->SetGravity(vec); - return NULL; + Py_RETURN_NONE; } static char gPyExpandPath_doc[] = @@ -147,13 +151,12 @@ static PyObject* gPyExpandPath(PyObject*, PyObject* args) char expanded[FILE_MAXDIR + FILE_MAXFILE]; char* filename; - if (PyArg_ParseTuple(args,"s",&filename)) - { - BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); - BLI_convertstringcode(expanded, G.sce); - return PyString_FromString(expanded); - } - return NULL; + if (!PyArg_ParseTuple(args,"s",&filename)) + return NULL; + + BLI_strncpy(expanded, filename, FILE_MAXDIR + FILE_MAXFILE); + BLI_convertstringcode(expanded, G.sce); + return PyString_FromString(expanded); } @@ -181,6 +184,12 @@ static PyObject* gPyGetSpectrum(PyObject*) PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index])); } } + else { + for (int index = 0; index < 512; index++) + { + PyList_SetItem(resultlist, index, PyFloat_FromDouble(0.0)); + } + } return resultlist; } @@ -191,16 +200,17 @@ static PyObject* gPyStartDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); - if (audiodevice) - { - if (!usedsp) - { - audiodevice->StartUsingDSP(); - usedsp = true; - Py_Return; - } + if (!audiodevice) { + PyErr_SetString(PyExc_RuntimeError, "no audio device available"); + return NULL; } - return NULL; + + if (!usedsp) { + audiodevice->StartUsingDSP(); + usedsp = true; + } + + Py_RETURN_NONE; } @@ -209,28 +219,27 @@ static PyObject* gPyStopDSP(PyObject*, PyObject* args) { SND_IAudioDevice* audiodevice = SND_DeviceManager::Instance(); - if (audiodevice) - { - if (usedsp) - { - audiodevice->StopUsingDSP(); - usedsp = false; - Py_Return; - } + if (!audiodevice) { + PyErr_SetString(PyExc_RuntimeError, "no audio device available"); + return NULL; } - return NULL; + + if (usedsp) { + audiodevice->StopUsingDSP(); + usedsp = true; + } + + Py_RETURN_NONE; } static PyObject* gPySetLogicTicRate(PyObject*, PyObject* args) { float ticrate; - if (PyArg_ParseTuple(args, "f", &ticrate)) - { - KX_KetsjiEngine::SetTicRate(ticrate); - Py_Return; - } + if (!PyArg_ParseTuple(args, "f", &ticrate)) + return NULL; - return NULL; + KX_KetsjiEngine::SetTicRate(ticrate); + Py_RETURN_NONE; } static PyObject* gPyGetLogicTicRate(PyObject*) @@ -241,26 +250,21 @@ static PyObject* gPyGetLogicTicRate(PyObject*) static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; - if (PyArg_ParseTuple(args, "f", &ticrate)) - { - - PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); - Py_Return; - } + if (!PyArg_ParseTuple(args, "f", &ticrate)) + return NULL; - return NULL; + PHY_GetActiveEnvironment()->setFixedTimeStep(true,ticrate); + Py_RETURN_NONE; } static PyObject* gPySetPhysicsDebug(PyObject*, PyObject* args) { int debugMode; - if (PyArg_ParseTuple(args, "i", &debugMode)) - { - PHY_GetActiveEnvironment()->setDebugMode(debugMode); - Py_Return; - } + if (!PyArg_ParseTuple(args, "i", &debugMode)) + return NULL; - return NULL; + PHY_GetActiveEnvironment()->setDebugMode(debugMode); + Py_RETURN_NONE; } @@ -270,11 +274,16 @@ static PyObject* gPyGetPhysicsTicRate(PyObject*) return PyFloat_FromDouble(PHY_GetActiveEnvironment()->getFixedTimeStep()); } +static PyObject* gPyGetAverageFrameRate(PyObject*) +{ + return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate()); +} + static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) { char cpath[sizeof(G.sce)]; char *searchpath = NULL; - PyObject* list; + PyObject* list, *value; DIR *dp; struct dirent *dirp; @@ -294,13 +303,15 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) if((dp = opendir(cpath)) == NULL) { /* todo, show the errno, this shouldnt happen anyway if the blendfile is readable */ - fprintf(stderr, "Could not read directoty () failed, code %d (%s)\n", cpath, errno, strerror(errno)); + fprintf(stderr, "Could not read directoty (%s) failed, code %d (%s)\n", cpath, errno, strerror(errno)); return list; } while ((dirp = readdir(dp)) != NULL) { if (BLI_testextensie(dirp->d_name, ".blend")) { - PyList_Append(list, PyString_FromString(dirp->d_name)); + value = PyString_FromString(dirp->d_name); + PyList_Append(list, value); + Py_DECREF(value); } } @@ -407,6 +418,7 @@ static struct PyMethodDef game_methods[] = { {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, "Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, "Gets the physics tic rate"}, {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, "Sets the physics tic rate"}, + {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, "Gets the estimated average frame rate"}, {"getBlendFileList", (PyCFunction)gPyGetBlendFileList, METH_VARARGS, "Gets a list of blend files in the same directory as the current blend file"}, {"PrintGLInfo", (PyCFunction)pyPrintExt, METH_NOARGS, "Prints GL Extension Info"}, {NULL, (PyCFunction) NULL, 0, NULL } @@ -415,22 +427,14 @@ static struct PyMethodDef game_methods[] = { static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { - int height = (gp_Canvas ? gp_Canvas->GetHeight() : 0); - - PyObject* heightval = PyInt_FromLong(height); - return heightval; + return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); } static PyObject* gPyGetWindowWidth(PyObject*, PyObject* args) { - - - int width = (gp_Canvas ? gp_Canvas->GetWidth() : 0); - - PyObject* widthval = PyInt_FromLong(width); - return widthval; + return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetWidth() : 0)); } @@ -441,15 +445,11 @@ bool gUseVisibilityTemp = false; static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) { int visible; - if (PyArg_ParseTuple(args,"i",&visible)) - { - gUseVisibilityTemp = (visible != 0); - } - else - { + if (!PyArg_ParseTuple(args,"i",&visible)) return NULL; - } - Py_Return; + + gUseVisibilityTemp = (visible != 0); + Py_RETURN_NONE; } @@ -457,23 +457,20 @@ static PyObject* gPyEnableVisibility(PyObject*, PyObject* args) static PyObject* gPyShowMouse(PyObject*, PyObject* args) { int visible; - if (PyArg_ParseTuple(args,"i",&visible)) - { - if (visible) - { - if (gp_Canvas) - gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); - } else - { - if (gp_Canvas) - gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); - } - } - else { + if (!PyArg_ParseTuple(args,"i",&visible)) return NULL; + + if (visible) + { + if (gp_Canvas) + gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); + } else + { + if (gp_Canvas) + gp_Canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); } - Py_Return; + Py_RETURN_NONE; } @@ -481,74 +478,81 @@ static PyObject* gPyShowMouse(PyObject*, PyObject* args) static PyObject* gPySetMousePosition(PyObject*, PyObject* args) { int x,y; - if (PyArg_ParseTuple(args,"ii",&x,&y)) - { - if (gp_Canvas) - gp_Canvas->SetMousePosition(x,y); - } - else { + if (!PyArg_ParseTuple(args,"ii",&x,&y)) return NULL; - } - Py_Return; + if (gp_Canvas) + gp_Canvas->SetMousePosition(x,y); + + Py_RETURN_NONE; } static PyObject* gPySetEyeSeparation(PyObject*, PyObject* args) { float sep; - if (PyArg_ParseTuple(args, "f", &sep)) - { - if (gp_Rasterizer) - gp_Rasterizer->SetEyeSeparation(sep); - - Py_Return; + if (!PyArg_ParseTuple(args, "f", &sep)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; } - return NULL; + gp_Rasterizer->SetEyeSeparation(sep); + + Py_RETURN_NONE; } static PyObject* gPyGetEyeSeparation(PyObject*, PyObject*, PyObject*) { - if (gp_Rasterizer) - return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } - return NULL; + return PyFloat_FromDouble(gp_Rasterizer->GetEyeSeparation()); } static PyObject* gPySetFocalLength(PyObject*, PyObject* args) { float focus; - if (PyArg_ParseTuple(args, "f", &focus)) - { - if (gp_Rasterizer) - gp_Rasterizer->SetFocalLength(focus); - Py_Return; - } + if (!PyArg_ParseTuple(args, "f", &focus)) + return NULL; - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + + gp_Rasterizer->SetFocalLength(focus); + + Py_RETURN_NONE; } static PyObject* gPyGetFocalLength(PyObject*, PyObject*, PyObject*) { - if (gp_Rasterizer) - return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength()); - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + + return PyFloat_FromDouble(gp_Rasterizer->GetFocalLength()); + + Py_RETURN_NONE; } static PyObject* gPySetBackgroundColor(PyObject*, PyObject* args) { MT_Vector4 vec = MT_Vector4(0., 0., 0.3, 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_Canvas) - { - gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]); - } - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; - return NULL; + if (gp_Canvas) + { + gp_Rasterizer->SetBackColor(vec[0], vec[1], vec[2], vec[3]); + } + Py_RETURN_NONE; } @@ -557,16 +561,16 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); - } - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + gp_Rasterizer->SetFogColor(vec[0], vec[1], vec[2]); + + Py_RETURN_NONE; } @@ -575,17 +579,17 @@ static PyObject* gPySetMistStart(PyObject*, PyObject* args) { float miststart; - if (PyArg_ParseTuple(args,"f",&miststart)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetFogStart(miststart); - } - } - else { + if (!PyArg_ParseTuple(args,"f",&miststart)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); return NULL; } - Py_Return; + + gp_Rasterizer->SetFogStart(miststart); + + Py_RETURN_NONE; } @@ -594,17 +598,17 @@ static PyObject* gPySetMistEnd(PyObject*, PyObject* args) { float mistend; - if (PyArg_ParseTuple(args,"f",&mistend)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetFogEnd(mistend); - } - } - else { + if (!PyArg_ParseTuple(args,"f",&mistend)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); return NULL; } - Py_Return; + + gp_Rasterizer->SetFogEnd(mistend); + + Py_RETURN_NONE; } @@ -612,16 +616,16 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) { MT_Vector3 vec = MT_Vector3(0., 0., 0.); - if (PyVecArgTo(args, vec)) - { - if (gp_Rasterizer) - { - gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); - } - Py_Return; - } + if (!PyVecArgTo(args, vec)) + return NULL; - return NULL; + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + gp_Rasterizer->SetAmbientColor(vec[0], vec[1], vec[2]); + + Py_RETURN_NONE; } @@ -630,42 +634,167 @@ static PyObject* gPySetAmbientColor(PyObject*, PyObject* args) static PyObject* gPyMakeScreenshot(PyObject*, PyObject* args) { char* filename; - if (PyArg_ParseTuple(args,"s",&filename)) - { - if (gp_Canvas) - { - gp_Canvas->MakeScreenShot(filename); - } - } - else { + if (!PyArg_ParseTuple(args,"s",&filename)) return NULL; + + if (gp_Canvas) + { + gp_Canvas->MakeScreenShot(filename); } - Py_Return; + + Py_RETURN_NONE; } static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) { float motionblurvalue; - if (PyArg_ParseTuple(args,"f",&motionblurvalue)) - { - if(gp_Rasterizer) - { - gp_Rasterizer->EnableMotionBlur(motionblurvalue); - } - } - else { + if (!PyArg_ParseTuple(args,"f",&motionblurvalue)) + return NULL; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); return NULL; } - Py_Return; + + gp_Rasterizer->EnableMotionBlur(motionblurvalue); + + Py_RETURN_NONE; } static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args) { - if(gp_Rasterizer) - { - gp_Rasterizer->DisableMotionBlur(); + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; } - Py_Return; + + gp_Rasterizer->DisableMotionBlur(); + + Py_RETURN_NONE; +} + +int getGLSLSettingFlag(char *setting) +{ + if(strcmp(setting, "lights") == 0) + return G_FILE_GLSL_NO_LIGHTS; + else if(strcmp(setting, "shaders") == 0) + return G_FILE_GLSL_NO_SHADERS; + else if(strcmp(setting, "shadows") == 0) + return G_FILE_GLSL_NO_SHADOWS; + else if(strcmp(setting, "ramps") == 0) + return G_FILE_GLSL_NO_RAMPS; + else if(strcmp(setting, "nodes") == 0) + return G_FILE_GLSL_NO_NODES; + else if(strcmp(setting, "extra_textures") == 0) + return G_FILE_GLSL_NO_EXTRA_TEX; + else + return -1; +} + +static PyObject* gPySetGLSLMaterialSetting(PyObject*, + PyObject* args, + PyObject*) +{ + char *setting; + int enable, flag, fileflags; + + if (!PyArg_ParseTuple(args,"si",&setting,&enable)) + return NULL; + + flag = getGLSLSettingFlag(setting); + + if (flag==-1) { + PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); + return NULL; + } + + fileflags = G.fileflags; + + if (enable) + G.fileflags &= ~flag; + else + G.fileflags |= flag; + + /* display lists and GLSL materials need to be remade */ + if(G.fileflags != fileflags) { + if(gp_KetsjiEngine) { + KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); + KX_SceneList::iterator it; + + for(it=scenes->begin(); it!=scenes->end(); it++) + if((*it)->GetBucketManager()) + (*it)->GetBucketManager()->ReleaseDisplayLists(); + } + + GPU_materials_free(); + } + + Py_RETURN_NONE; +} + +static PyObject* gPyGetGLSLMaterialSetting(PyObject*, + PyObject* args, + PyObject*) +{ + char *setting; + int enabled = 0, flag; + + if (!PyArg_ParseTuple(args,"s",&setting)) + return NULL; + + flag = getGLSLSettingFlag(setting); + + if (flag==-1) { + PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); + return NULL; + } + + enabled = ((G.fileflags & flag) != 0); + return PyInt_FromLong(enabled); +} + +#define KX_TEXFACE_MATERIAL 0 +#define KX_BLENDER_MULTITEX_MATERIAL 1 +#define KX_BLENDER_GLSL_MATERIAL 2 + +static PyObject* gPySetMaterialType(PyObject*, + PyObject* args, + PyObject*) +{ + int flag, type; + + if (!PyArg_ParseTuple(args,"i",&type)) + return NULL; + + if(type == KX_BLENDER_GLSL_MATERIAL) + flag = G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL; + else if(type == KX_BLENDER_MULTITEX_MATERIAL) + flag = G_FILE_GAME_MAT; + else if(type == KX_TEXFACE_MATERIAL) + flag = 0; + else { + PyErr_SetString(PyExc_ValueError, "material type is not known"); + return NULL; + } + + G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + G.fileflags |= flag; + + Py_RETURN_NONE; +} + +static PyObject* gPyGetMaterialType(PyObject*) +{ + int flag; + + if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL)) + flag = KX_BLENDER_GLSL_MATERIAL; + else if(G.fileflags & G_FILE_GAME_MAT) + flag = KX_BLENDER_MULTITEX_MATERIAL; + else + flag = KX_TEXFACE_MATERIAL; + + return PyInt_FromLong(flag); } STR_String gPyGetWindowHeight__doc__="getWindowHeight doc"; @@ -701,11 +830,17 @@ static struct PyMethodDef rasterizer_methods[] = { {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"}, {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, + {"setMaterialMode",(PyCFunction) gPySetMaterialType, + METH_VARARGS, "set the material mode to use for OpenGL rendering"}, + {"getMaterialMode",(PyCFunction) gPyGetMaterialType, + METH_NOARGS, "get the material mode being used for OpenGL rendering"}, + {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting, + METH_VARARGS, "set the state of a GLSL material setting"}, + {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, + METH_VARARGS, "get the state of a GLSL material setting"}, { NULL, (PyCFunction) NULL, 0, NULL } }; - - // Initialization function for the module (*must* be called initGameLogic) static char GameLogic_module_documentation[] = @@ -718,11 +853,12 @@ static char Rasterizer_module_documentation[] = -PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook +PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook { PyObject* m; PyObject* d; + gp_KetsjiEngine = engine; gp_KetsjiScene = scene; gUseVisibilityTemp=false; @@ -852,13 +988,30 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook // override builtin functions import() and open() -PyObject *KXpy_open(PyObject *self, PyObject *args) -{ +PyObject *KXpy_open(PyObject *self, PyObject *args) { PyErr_SetString(PyExc_RuntimeError, "Sandbox: open() function disabled!\nGame Scripts should not use this function."); return NULL; } +PyObject *KXpy_reload(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: reload() function disabled!\nGame Scripts should not use this function."); + return NULL; +} +PyObject *KXpy_file(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: file() function disabled!\nGame Scripts should not use this function."); + return NULL; +} + +PyObject *KXpy_execfile(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: execfile() function disabled!\nGame Scripts should not use this function."); + return NULL; +} + +PyObject *KXpy_compile(PyObject *self, PyObject *args) { + PyErr_SetString(PyExc_RuntimeError, "Sandbox: compile() function disabled!\nGame Scripts should not use this function."); + return NULL; +} PyObject *KXpy_import(PyObject *self, PyObject *args) { @@ -895,19 +1048,13 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) } +static PyMethodDef meth_open[] = {{ "open", KXpy_open, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_reload[] = {{ "reload", KXpy_reload, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_file[] = {{ "file", KXpy_file, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_execfile[] = {{ "execfile", KXpy_execfile, METH_VARARGS, "(disabled)"}}; +static PyMethodDef meth_compile[] = {{ "compile", KXpy_compile, METH_VARARGS, "(disabled)"}}; -static PyMethodDef meth_open[] = { - { "open", KXpy_open, METH_VARARGS, - "(disabled)"} -}; - - -static PyMethodDef meth_import[] = { - { "import", KXpy_import, METH_VARARGS, - "our own import"} -}; - - +static PyMethodDef meth_import[] = {{ "import", KXpy_import, METH_VARARGS, "our own import"}}; //static PyObject *g_oldopen = 0; //static PyObject *g_oldimport = 0; @@ -918,15 +1065,21 @@ void setSandbox(TPythonSecurityLevel level) { PyObject *m = PyImport_AddModule("__builtin__"); PyObject *d = PyModule_GetDict(m); - PyObject *meth = PyCFunction_New(meth_open, NULL); switch (level) { case psl_Highest: //if (!g_security) { //g_oldopen = PyDict_GetItemString(d, "open"); - PyDict_SetItemString(d, "open", meth); - meth = PyCFunction_New(meth_import, NULL); - PyDict_SetItemString(d, "__import__", meth); + + // functions we cant trust + PyDict_SetItemString(d, "open", PyCFunction_New(meth_open, NULL)); + PyDict_SetItemString(d, "reload", PyCFunction_New(meth_reload, NULL)); + PyDict_SetItemString(d, "file", PyCFunction_New(meth_file, NULL)); + PyDict_SetItemString(d, "execfile", PyCFunction_New(meth_execfile, NULL)); + PyDict_SetItemString(d, "compile", PyCFunction_New(meth_compile, NULL)); + + // our own import + PyDict_SetItemString(d, "__import__", PyCFunction_New(meth_import, NULL)); //g_security = level; //} break; @@ -1010,6 +1163,11 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) ErrorObject = PyString_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); + /* needed for get/setMaterialType */ + KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_GLSL_MATERIAL, KX_BLENDER_GLSL_MATERIAL); + // XXXX Add constants here // Check for errors @@ -1031,9 +1189,38 @@ static char GameKeys_module_documentation[] = "This modules provides defines for key-codes" ; +static char gPyEventToString_doc[] = +"Take a valid event from the GameKeys module or Keyboard Sensor and return a name" +; +static PyObject* gPyEventToString(PyObject*, PyObject* value) +{ + PyObject* mod, *dict, *key, *val, *ret = NULL; + Py_ssize_t pos = 0; + + mod = PyImport_ImportModule( "GameKeys" ); + if (!mod) + return NULL; + + dict = PyModule_GetDict(mod); + + while (PyDict_Next(dict, &pos, &key, &val)) { + if (PyObject_Compare(value, val)==0) { + ret = key; + break; + } + } + + PyErr_Clear(); // incase there was an error clearing + Py_DECREF(mod); + if (!ret) PyErr_SetString(PyExc_ValueError, "expected a valid int keyboard event"); + else Py_INCREF(ret); + + return ret; +} static struct PyMethodDef gamekeys_methods[] = { + {"EventToString", (PyCFunction)gPyEventToString, METH_O, gPyEventToString_doc}, { NULL, (PyCFunction) NULL, 0, NULL } }; @@ -1191,3 +1378,76 @@ class KX_Scene* PHY_GetActiveScene() { return gp_KetsjiScene; } + +// utility function for loading and saving the globalDict +int saveGamePythonConfig( char **marshal_buffer) +{ + int marshal_length = 0; + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + if (gameLogic) { + PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module + if (pyGlobalDict) { +#ifdef Py_MARSHAL_VERSION + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 +#else + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); +#endif + if (pyGlobalDictMarshal) { + // for testing only + // PyObject_Print(pyGlobalDictMarshal, stderr, 0); + + marshal_length= PyString_Size(pyGlobalDictMarshal); + *marshal_buffer = new char[marshal_length + 1]; + memcpy(*marshal_buffer, PyString_AsString(pyGlobalDictMarshal), marshal_length); + + Py_DECREF(pyGlobalDictMarshal); + } else { + printf("Error, GameLogic.globalDict could not be marshal'd\n"); + } + } else { + printf("Error, GameLogic.globalDict was removed\n"); + } + Py_DECREF(gameLogic); + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + return marshal_length; +} + +int loadGamePythonConfig(char *marshal_buffer, int marshal_length) +{ + /* Restore the dict */ + if (marshal_buffer) { + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + + if (gameLogic) { + PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); + + if (pyGlobalDict) { + PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. + Py_DECREF(gameLogic); + return 1; + } else { + Py_DECREF(gameLogic); + PyErr_Clear(); + printf("Error could not marshall string\n"); + } + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + } + return 0; +} + +void pathGamePythonConfig( char *path ) +{ + int len = strlen(G.sce); + + strncpy(path, G.sce, sizeof(G.sce)); + /* replace extension */ + if (BLI_testextensie(path, ".blend")) { + strcpy(path+(len-6), ".bgeconf"); + } else { + strcpy(path+len, ".bgeconf"); + } +} diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index f094a1ca575..28d9d72a4c3 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -40,7 +40,7 @@ typedef enum { extern bool gUseVisibilityTemp; -PyObject* initGameLogic(class KX_Scene* ketsjiscene); +PyObject* initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene* ketsjiscene); PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level); @@ -49,6 +49,10 @@ void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); void exitGamePythonScripting(); +void pathGamePythonConfig( char *path ); +int saveGamePythonConfig( char **marshal_buffer); +int loadGamePythonConfig(char *marshal_buffer, int marshal_length); + void PHY_SetActiveScene(class KX_Scene* scene); class KX_Scene* PHY_GetActiveScene(); #include "MT_Vector3.h" diff --git a/source/gameengine/Ketsji/KX_RayCast.cpp b/source/gameengine/Ketsji/KX_RayCast.cpp index 89e2d645d54..974d4b992a6 100644 --- a/source/gameengine/Ketsji/KX_RayCast.cpp +++ b/source/gameengine/Ketsji/KX_RayCast.cpp @@ -40,7 +40,21 @@ #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" -bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, MT_Point3& result_point, MT_Vector3& result_normal, const KX_RayCast& callback) +KX_RayCast::KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal) + :PHY_IRayCastFilterCallback(dynamic_cast(ignoreController), faceNormal) +{ +} + +void KX_RayCast::reportHit(PHY_RayCastResult* result) +{ + m_hitFound = true; + m_hitPoint.setValue((const float*)result->m_hitPoint); + m_hitNormal.setValue((const float*)result->m_hitNormal); + m_hitMesh = result->m_meshObject; + m_hitPolygon = result->m_polygon; +} + +bool KX_RayCast::RayTest(PHY_IPhysicsEnvironment* physics_environment, const MT_Point3& _frompoint, const MT_Point3& topoint, KX_RayCast& callback) { // Loops over all physics objects between frompoint and topoint, // calling callback.RayHit for each one. @@ -50,58 +64,51 @@ bool KX_RayCast::RayTest(KX_IPhysicsController* ignore_controller, PHY_IPhysicsE // returns true if an object was found, false if not. MT_Point3 frompoint(_frompoint); const MT_Vector3 todir( (topoint - frompoint).safe_normalized() ); + MT_Point3 prevpoint(_frompoint+todir*(-1.f)); PHY_IPhysicsController* hit_controller; - PHY__Vector3 phy_pos; - PHY__Vector3 phy_normal; - while((hit_controller = physics_environment->rayTest(dynamic_cast(ignore_controller), + while((hit_controller = physics_environment->rayTest(callback, frompoint.x(),frompoint.y(),frompoint.z(), - topoint.x(),topoint.y(),topoint.z(), - phy_pos[0],phy_pos[1],phy_pos[2], - phy_normal[0],phy_normal[1],phy_normal[2]))) + topoint.x(),topoint.y(),topoint.z())) != NULL) { - result_point = MT_Point3(phy_pos); - result_normal = MT_Vector3(phy_normal); KX_ClientObjectInfo* info = static_cast(hit_controller->getNewClientInfo()); if (!info) { printf("no info!\n"); MT_assert(info && "Physics controller with no client object info"); - return false; + break; } - if (callback.RayHit(info, result_point, result_normal)) - return true; - - // There is a bug in the code below: the delta is computed with the wrong - // sign on the face opposite to the center, resulting in infinite looping. - // In Blender 2.45 this code was never executed because callback.RayHit() always - // returned true, causing the ray sensor to stop on the first object. - // To avoid changing the behaviour will simply return false here. - // It should be discussed if we want the ray sensor to "see" through objects - // that don't have the required property/material (condition to get here) - return false; - - // skip past the object and keep tracing - /* We add 0.01 of fudge, so that if the margin && radius == 0., we don't endless loop. */ - MT_Scalar marg = 0.01 + hit_controller->GetMargin(); - marg += 2.f * hit_controller->GetMargin(); + // The biggest danger to to endless loop, prevent this by checking that the + // hit point always progresses along the ray direction.. + prevpoint -= callback.m_hitPoint; + if (prevpoint.length2() < MT_EPSILON) + break; + + if (callback.RayHit(info)) + // caller may decide to stop the loop and still cancel the hit + return callback.m_hitFound; + + // Skip past the object and keep tracing. + // Note that retrieving in a single shot multiple hit points would be possible + // but it would require some change in Bullet. + prevpoint = callback.m_hitPoint; + /* We add 0.001 of fudge, so that if the margin && radius == 0., we don't endless loop. */ + MT_Scalar marg = 0.001 + hit_controller->GetMargin(); + marg *= 2.f; /* Calculate the other side of this object */ - PHY__Vector3 hitpos; - hit_controller->getPosition(hitpos); - MT_Point3 hitObjPos(hitpos); - - MT_Vector3 hitvector = hitObjPos - result_point; - if (hitvector.dot(hitvector) > MT_EPSILON) - { - hitvector.normalize(); - marg *= 2.*todir.dot(hitvector); - } - frompoint = result_point + marg * todir; + MT_Scalar h = MT_abs(todir.dot(callback.m_hitNormal)); + if (h <= 0.01) + // the normal is almost orthogonal to the ray direction, cannot compute the other side + break; + marg /= h; + frompoint = callback.m_hitPoint + marg * todir; + // verify that we are not passed the to point + if ((topoint - frompoint).dot(todir) < 0.f) + break; } - - return hit_controller; + return false; } diff --git a/source/gameengine/Ketsji/KX_RayCast.h b/source/gameengine/Ketsji/KX_RayCast.h index 607dabd8afc..c3084c997a1 100644 --- a/source/gameengine/Ketsji/KX_RayCast.h +++ b/source/gameengine/Ketsji/KX_RayCast.h @@ -30,12 +30,14 @@ #ifndef __KX_RAYCAST_H__ #define __KX_RAYCAST_H__ -class MT_Point3; -class MT_Vector3; -class KX_IPhysicsController; -class PHY_IPhysicsEnvironment; +#include "PHY_IPhysicsEnvironment.h" +#include "PHY_IPhysicsController.h" +#include "MT_Point3.h" +#include "MT_Vector3.h" +class RAS_MeshObject; struct KX_ClientObjectInfo; +class KX_IPhysicsController; /** * Defines a function for doing a ray cast. @@ -49,17 +51,27 @@ struct KX_ClientObjectInfo; * * Returns true if a client was accepted, false if nothing found. */ -class KX_RayCast +class KX_RayCast : public PHY_IRayCastFilterCallback { -protected: - KX_RayCast() {}; public: + bool m_hitFound; + MT_Point3 m_hitPoint; + MT_Vector3 m_hitNormal; + const RAS_MeshObject* m_hitMesh; + int m_hitPolygon; + + KX_RayCast(KX_IPhysicsController* ignoreController, bool faceNormal); virtual ~KX_RayCast() {} + /** + * The physic environment returns the ray casting result through this function + */ + virtual void reportHit(PHY_RayCastResult* result); + /** ray test callback. * either override this in your class, or use a callback wrapper. */ - virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const = 0; + virtual bool RayHit(KX_ClientObjectInfo* client) = 0; /** * Callback wrapper. @@ -71,13 +83,11 @@ public: /// Public interface. /// Implement bool RayHit in your class to receive ray callbacks. - static bool RayTest(KX_IPhysicsController* physics_controller, + static bool RayTest( PHY_IPhysicsEnvironment* physics_environment, - const MT_Point3& _frompoint, + const MT_Point3& frompoint, const MT_Point3& topoint, - MT_Point3& result_point, - MT_Vector3& result_normal, - const KX_RayCast& callback); + KX_RayCast& callback); }; @@ -86,18 +96,32 @@ template class KX_RayCast::Callback : public KX_RayCast T *self; void *data; public: - Callback(T *_self, void *_data = NULL) - : self(_self), + Callback(T *_self, KX_IPhysicsController* controller=NULL, void *_data = NULL, bool faceNormal=false) + : KX_RayCast(controller, faceNormal), + self(_self), data(_data) { } ~Callback() {} - - virtual bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal) const + + virtual bool RayHit(KX_ClientObjectInfo* client) { - return self->RayHit(client, hit_point, hit_normal, data); + return self->RayHit(client, this, data); } + + virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller) + { + KX_ClientObjectInfo* info = static_cast(controller->getNewClientInfo()); + + if (!info) + { + MT_assert(info && "Physics controller with no client object info"); + return false; + } + return self->NeedRayCast(info); + } + }; diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index a416c8c9f89..8dc22fe13c1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -51,6 +51,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, bool bFindMaterial, + bool bXRay, double distance, int axis, KX_Scene* ketsjiScene, @@ -58,6 +59,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr, : SCA_ISensor(gameobj,eventmgr, T), m_propertyname(propname), m_bFindMaterial(bFindMaterial), + m_bXRay(bXRay), m_distance(distance), m_scene(ketsjiScene), m_axis(axis) @@ -104,16 +106,10 @@ bool KX_RaySensor::IsPositiveTrigger() return result; } -bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) +bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data) { KX_GameObject* hitKXObj = client->m_gameobject; - - if (client->m_type > KX_ClientObjectInfo::ACTOR) - { - // false hit - return false; - } bool bFound = false; if (m_propertyname.Length() == 0) @@ -139,16 +135,43 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_ { m_rayHit = true; m_hitObject = hitKXObj; - m_hitPosition = hit_point; - m_hitNormal = hit_normal; + m_hitPosition = result->m_hitPoint; + m_hitNormal = result->m_hitNormal; } - - return bFound; - + // no multi-hit search yet + return true; } - +/* this function is used to pre-filter the object before casting the ray on them. + This is useful for "X-Ray" option when we want to see "through" unwanted object. + */ +bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo* client) +{ + if (client->m_type > KX_ClientObjectInfo::ACTOR) + { + // Unknown type of object, skip it. + // Should not occur as the sensor objects are filtered in RayTest() + printf("Invalid client type %d found ray casting\n", client->m_type); + return false; + } + if (m_bXRay && m_propertyname.Length() != 0) + { + if (m_bFindMaterial) + { + // not quite correct: an object may have multiple material + // should check all the material and not only the first one + if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info))) + return false; + } + else + { + if (client->m_gameobject->GetProperty(m_propertyname) == NULL) + return false; + } + } + return true; +} bool KX_RaySensor::Evaluate(CValue* event) { @@ -215,8 +238,6 @@ bool KX_RaySensor::Evaluate(CValue* event) m_rayDirection = todir; MT_Point3 topoint = frompoint + (m_distance) * todir; - MT_Point3 resultpoint; - MT_Vector3 resultnormal; PHY_IPhysicsEnvironment* pe = m_scene->GetPhysicsEnvironment(); if (!pe) @@ -238,7 +259,8 @@ bool KX_RaySensor::Evaluate(CValue* event) PHY_IPhysicsEnvironment* physics_environment = this->m_scene->GetPhysicsEnvironment(); - result = KX_RayCast::RayTest(spc, physics_environment, frompoint, topoint, resultpoint, resultnormal, KX_RayCast::Callback(this)); + KX_RayCast::Callback callback(this, spc); + KX_RayCast::RayTest(physics_environment, frompoint, topoint, callback); /* now pass this result to some controller */ @@ -265,6 +287,10 @@ bool KX_RaySensor::Evaluate(CValue* event) // notify logicsystem that ray JUST left the Object result = true; } + else + { + result = false; + } } if (reset) diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index f4305b053d1..02a755fedc1 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -36,12 +36,14 @@ #include "MT_Point3.h" struct KX_ClientObjectInfo; +class KX_RayCast; class KX_RaySensor : public SCA_ISensor { Py_Header; STR_String m_propertyname; bool m_bFindMaterial; + bool m_bXRay; double m_distance; class KX_Scene* m_scene; bool m_bTriggered; @@ -56,7 +58,8 @@ public: KX_RaySensor(class SCA_EventManager* eventmgr, SCA_IObject* gameobj, const STR_String& propname, - bool fFindMaterial, + bool bFindMaterial, + bool bXRay, double distance, int axis, class KX_Scene* ketsjiScene, @@ -68,7 +71,8 @@ public: virtual bool IsPositiveTrigger(); virtual void Init(); - bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data); + bool RayHit(KX_ClientObjectInfo* client, KX_RayCast* result, void * const data); + bool NeedRayCast(KX_ClientObjectInfo* client); KX_PYMETHOD_DOC(KX_RaySensor,GetHitObject); KX_PYMETHOD_DOC(KX_RaySensor,GetHitPosition); diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index ca0106d64d9..c4c190e9fa1 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -39,6 +39,8 @@ #include "KX_GameObject.h" #include "KX_IPhysicsController.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif @@ -52,14 +54,20 @@ KX_SCA_AddObjectActuator::KX_SCA_AddObjectActuator(SCA_IObject *gameobj, int time, SCA_IScene* scene, const MT_Vector3& linvel, - bool local, + bool linv_local, + const MT_Vector3& angvel, + bool angv_local, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_OriginalObject(original), m_scene(scene), + m_linear_velocity(linvel), - m_localFlag(local) + m_localLinvFlag(linv_local), + + m_angular_velocity(angvel), + m_localAngvFlag(angv_local) { if (m_OriginalObject) m_OriginalObject->RegisterActuator(this); @@ -181,13 +189,15 @@ PyParentObject KX_SCA_AddObjectActuator::Parents[] = { }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { {"setObject", (PyCFunction) KX_SCA_AddObjectActuator::sPySetObject, METH_O, SetObject_doc}, - {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_VARARGS, SetTime_doc}, + {"setTime", (PyCFunction) KX_SCA_AddObjectActuator::sPySetTime, METH_O, SetTime_doc}, {"getObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetObject, METH_VARARGS, GetObject_doc}, - {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_VARARGS, GetTime_doc}, - {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_VARARGS, GetLinearVelocity_doc}, + {"getTime", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetTime, METH_NOARGS, GetTime_doc}, + {"getLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLinearVelocity, METH_NOARGS, GetLinearVelocity_doc}, {"setLinearVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetLinearVelocity, METH_VARARGS, SetLinearVelocity_doc}, - {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_VARARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, - {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_VARARGS,"instantAddObject() : immediately add object without delay\n"}, + {"getAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetAngularVelocity, METH_NOARGS, GetAngularVelocity_doc}, + {"setAngularVelocity", (PyCFunction) KX_SCA_AddObjectActuator::sPySetAngularVelocity, METH_VARARGS, SetAngularVelocity_doc}, + {"getLastCreatedObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyGetLastCreatedObject, METH_NOARGS,"getLastCreatedObject() : get the object handle to the last created object\n"}, + {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, {NULL,NULL} //Sentinel }; @@ -231,19 +241,18 @@ char KX_SCA_AddObjectActuator::SetTime_doc[] = "\tIf the duration is negative, it is set to 0.\n"; -PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PySetTime(PyObject* self, PyObject* value) { - int deltatime; - - if (!PyArg_ParseTuple(args, "i", &deltatime)) + int deltatime = PyInt_AsLong(value); + if (deltatime==-1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "expected an int"); return NULL; + } m_timeProp = deltatime; if (m_timeProp < 0) m_timeProp = 0; - Py_Return; + Py_RETURN_NONE; } @@ -254,9 +263,7 @@ char KX_SCA_AddObjectActuator::GetTime_doc[] = "\tReturns the lifetime of the object that will be added.\n"; -PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyGetTime(PyObject* self) { return PyInt_FromLong(m_timeProp); } @@ -290,17 +297,13 @@ char KX_SCA_AddObjectActuator::GetLinearVelocity_doc[] = "\tReturns the linear velocity that will be assigned to \n" "\tthe created object.\n"; - - -PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyGetLinearVelocity(PyObject* self) { PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); return retVal; } @@ -313,12 +316,10 @@ char KX_SCA_AddObjectActuator::SetLinearVelocity_doc[] = "\t- vx: float\n" "\t- vy: float\n" "\t- vz: float\n" +"\t- local: bool\n" "\tAssign this velocity to the created object. \n"; - -PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, PyObject* args) { float vecArg[3]; @@ -326,7 +327,46 @@ PyObject* KX_SCA_AddObjectActuator::PySetLinearVelocity(PyObject* self, return NULL; m_linear_velocity.setValue(vecArg); - Py_Return; + Py_RETURN_NONE; +} + +/* 7. getAngularVelocity */ +char KX_SCA_AddObjectActuator::GetAngularVelocity_doc[] = +"GetAngularVelocity()\n" +"\tReturns the angular velocity that will be assigned to \n" +"\tthe created object.\n"; + +PyObject* KX_SCA_AddObjectActuator::PyGetAngularVelocity(PyObject* self) +{ + PyObject *retVal = PyList_New(3); + + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2])); + + return retVal; +} + + + +/* 8. setAngularVelocity */ +char KX_SCA_AddObjectActuator::SetAngularVelocity_doc[] = +"setAngularVelocity(vx, vy, vz)\n" +"\t- vx: float\n" +"\t- vy: float\n" +"\t- vz: float\n" +"\t- local: bool\n" +"\tAssign this angular velocity to the created object. \n"; + +PyObject* KX_SCA_AddObjectActuator::PySetAngularVelocity(PyObject* self, PyObject* args) +{ + + float vecArg[3]; + if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) + return NULL; + + m_angular_velocity.setValue(vecArg); + Py_RETURN_NONE; } void KX_SCA_AddObjectActuator::InstantAddObject() @@ -337,8 +377,9 @@ void KX_SCA_AddObjectActuator::InstantAddObject() // Now it needs to be added to the current scene. SCA_IObject* replica = m_scene->AddReplicaObject(m_OriginalObject,GetParent(),m_timeProp ); KX_GameObject * game_obj = static_cast(replica); - game_obj->setLinearVelocity(m_linear_velocity,m_localFlag); - game_obj->ResolveCombinedVelocities(m_linear_velocity, MT_Vector3(0., 0., 0.), m_localFlag, false); + game_obj->setLinearVelocity(m_linear_velocity,m_localLinvFlag); + game_obj->setAngularVelocity(m_angular_velocity,m_localAngvFlag); + game_obj->ResolveCombinedVelocities(m_linear_velocity, m_angular_velocity, m_localLinvFlag, m_localAngvFlag); // keep a copy of the last object, to allow python scripters to change it if (m_lastCreatedObject) @@ -355,13 +396,11 @@ void KX_SCA_AddObjectActuator::InstantAddObject() } } -PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyInstantAddObject(PyObject* self) { InstantAddObject(); - Py_Return; + Py_RETURN_NONE; } @@ -372,16 +411,17 @@ char KX_SCA_AddObjectActuator::GetLastCreatedObject_doc[] = "\tReturn the last created object. \n"; -PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_AddObjectActuator::PyGetLastCreatedObject(PyObject* self) { SCA_IObject* result = this->GetLastCreatedObject(); - if (result) + + // if result->GetSGNode() is NULL + // it means the object has ended, The BGE python api crashes in many places if the object is returned. + if (result && (static_cast(result))->GetSGNode()) { result->AddRef(); return result; } // don't return NULL to python anymore, it gives trouble in the scripts - Py_Return; + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index e7fdb2fbfbc..278d4180284 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -60,9 +60,13 @@ class KX_SCA_AddObjectActuator : public SCA_IActuator /// Linear velocity upon creation of the object. MT_Vector3 m_linear_velocity; + + /// Angular velocity upon creation of the object. + MT_Vector3 m_angular_velocity; /// Apply the velocity locally - bool m_localFlag; + bool m_localLinvFlag; + bool m_localAngvFlag; SCA_IObject* m_lastCreatedObject; @@ -79,7 +83,9 @@ public: int time, SCA_IScene* scene, const MT_Vector3& linvel, - bool local, + bool linv_local, + const MT_Vector3& angvel, + bool angv_local, PyTypeObject* T=&Type ); @@ -115,19 +121,23 @@ public: /* 1. setObject */ KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetObject); /* 2. setTime */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetTime); + KX_PYMETHOD_DOC_O(KX_SCA_AddObjectActuator,SetTime); /* 3. getTime */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetTime); + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetTime); /* 4. getObject */ KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,GetObject); /* 5. getLinearVelocity */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLinearVelocity); + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLinearVelocity); /* 6. setLinearVelocity */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,SetLinearVelocity); - /* 7. getLastCreatedObject */ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,GetLastCreatedObject); - /* 8. instantAddObject*/ - KX_PYMETHOD_DOC(KX_SCA_AddObjectActuator,InstantAddObject); + KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetLinearVelocity); + /* 7. getAngularVelocity */ + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetAngularVelocity); + /* 8. setAngularVelocity */ + KX_PYMETHOD_DOC_VARARGS(KX_SCA_AddObjectActuator,SetAngularVelocity); + /* 9. getLastCreatedObject */ + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,GetLastCreatedObject); + /* 10. instantAddObject*/ + KX_PYMETHOD_DOC_NOARGS(KX_SCA_AddObjectActuator,InstantAddObject); }; /* end of class KX_SCA_AddObjectActuator : public KX_EditObjectActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 630df2d21d9..e1f11732085 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -37,6 +37,8 @@ #include "KX_SCA_ReplaceMeshActuator.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif @@ -80,7 +82,7 @@ PyParentObject KX_SCA_ReplaceMeshActuator::Parents[] = { PyMethodDef KX_SCA_ReplaceMeshActuator::Methods[] = { - {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_VARARGS, SetMesh_doc}, + {"setMesh", (PyCFunction) KX_SCA_ReplaceMeshActuator::sPySetMesh, METH_O, SetMesh_doc}, KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, instantReplaceMesh), KX_PYMETHODTABLE(KX_SCA_ReplaceMeshActuator, getMesh), @@ -99,28 +101,29 @@ PyObject* KX_SCA_ReplaceMeshActuator::_getattr(const STR_String& attr) /* 1. setMesh */ char KX_SCA_ReplaceMeshActuator::SetMesh_doc[] = "setMesh(name)\n" - "\t- name: string\n" + "\t- name: string or None\n" "\tSet the mesh that will be substituted for the current one.\n"; -PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_SCA_ReplaceMeshActuator::PySetMesh(PyObject* self, PyObject* value) { - char* meshname; - - if (!PyArg_ParseTuple(args, "s", &meshname)) - { - return NULL; - } - - void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); - - if (mesh) { + if (value == Py_None) { + m_mesh = NULL; + } else { + char* meshname = PyString_AsString(value); + if (!meshname) { + PyErr_SetString(PyExc_ValueError, "Expected the name of a mesh or None"); + return NULL; + } + void* mesh = SCA_ILogicBrick::m_sCurrentLogicManager->GetMeshByName(STR_String(meshname)); + + if (mesh==NULL) { + PyErr_SetString(PyExc_ValueError, "The mesh name given does not exist"); + return NULL; + } m_mesh= (class RAS_MeshObject*)mesh; - Py_Return; } - return NULL; + Py_RETURN_NONE; } KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, @@ -129,7 +132,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, getMesh, ) { if (!m_mesh) - Py_Return; + Py_RETURN_NONE; return PyString_FromString(const_cast(m_mesh->GetName().ReadPtr())); } @@ -139,7 +142,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_ReplaceMeshActuator, instantReplaceMesh, "instantReplaceMesh() : immediately replace mesh without delay\n") { InstantReplaceMesh(); - Py_Return; + Py_RETURN_NONE; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 5ba0a099b14..1da154cc222 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -76,7 +76,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator void InstantReplaceMesh(); /* 1. setMesh */ - KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,SetMesh); + KX_PYMETHOD_DOC_O(KX_SCA_ReplaceMeshActuator,SetMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,getMesh); KX_PYMETHOD_DOC(KX_SCA_ReplaceMeshActuator,instantReplaceMesh); diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index f085ff435dc..d651373869a 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -78,7 +78,7 @@ UpdateChildCoordinates( if (parent) { - const BL_ArmatureObject *armature = (const BL_ArmatureObject*)(parent->GetSGClientObject()); + BL_ArmatureObject *armature = (BL_ArmatureObject*)(parent->GetSGClientObject()); if (armature) { MT_Matrix4x4 parent_matrix; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index ab3692d2411..72875bbc039 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -68,6 +68,7 @@ #include "SG_IObject.h" #include "SG_Tree.h" #include "DNA_group_types.h" +#include "DNA_scene_types.h" #include "BKE_anim.h" #include "KX_SG_NodeRelationships.h" @@ -116,7 +117,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface *ndi, class SND_IAudioDevice* adi, - const STR_String& sceneName): + const STR_String& sceneName, + Scene *scene): PyObjectPlus(&KX_Scene::Type), m_keyboardmgr(NULL), m_mousemgr(NULL), @@ -126,7 +128,8 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0) + m_ueberExecutionPriority(0), + m_blenderScene(scene) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -453,7 +456,7 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal // this is the list of object that are send to the graphics pipeline m_objectlist->Add(newobj->AddRef()); - newobj->Bucketize(); + newobj->AddMeshUser(); // logic cannot be replicated, until the whole hierarchy is replicated. m_logicHierarchicalGameObjects.push_back(newobj); @@ -623,6 +626,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) if (blgroupobj == blenderobj) // this check is also in group_duplilist() continue; + gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj); if (gameobj == NULL) { @@ -630,6 +634,9 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // Should not happen as dupli group are created automatically continue; } + + gameobj->SetBlenderGroupObject(blgroupobj); + if ((blenderobj->lay & group->layer)==0) { // object is not visible in the 3D view, will not be instantiated @@ -944,6 +951,8 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) newobj->RemoveMeshes(); ret = 1; + if (m_lightlist->RemoveValue(newobj)) // TODO - use newobj->IsLight() test when its merged in from apricot. - Campbell + ret = newobj->Release(); if (m_objectlist->RemoveValue(newobj)) ret = newobj->Release(); if (m_tempObjectList->RemoveValue(newobj)) @@ -997,7 +1006,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) newobj->m_pDeformer = NULL; } - if (mesh->m_class == 1) + if (mesh->IsDeformed()) { // we must create a new deformer but which one? KX_GameObject* parentobj = newobj->GetParent(); @@ -1071,7 +1080,8 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) parentobj->Release(); } } - gameobj->Bucketize(); + + gameobj->AddMeshUser(); } @@ -1223,7 +1233,9 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi for (int m=0;mGetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } - gameobj->MarkVisible(visible); + + gameobj->SetCulled(!visible); + gameobj->UpdateBuckets(false); } } if (node->Left()) @@ -1240,7 +1252,8 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam // Shadow lamp layers if(layer && !(gameobj->GetLayer() & layer)) { - gameobj->MarkVisible(false); + gameobj->SetCulled(true); + gameobj->UpdateBuckets(false); return; } @@ -1286,9 +1299,11 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam } // Visibility/ non-visibility are marked // elsewhere now. - gameobj->MarkVisible(); + gameobj->SetCulled(false); + gameobj->UpdateBuckets(false); } else { - gameobj->MarkVisible(false); + gameobj->SetCulled(true); + gameobj->UpdateBuckets(false); } } diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 1c56dd1ee55..5f7e1167e27 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -54,6 +54,7 @@ */ struct SM_MaterialProps; struct SM_ShapeProps; +struct Scene; class GEN_HashedPtr; class CListValue; @@ -277,12 +278,15 @@ protected: */ PyObject* m_attrlist; + struct Scene* m_blenderScene; + public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, class NG_NetworkDeviceInterface* ndi, class SND_IAudioDevice* adi, - const STR_String& scenename ); + const STR_String& scenename, + struct Scene* scene); virtual ~KX_Scene(); @@ -582,6 +586,10 @@ public: * was running and not suspended) and the "curtime" */ double getSuspendedDelta(); + /** + * Returns the Blender scene this was made from + */ + struct Scene *GetBlenderScene() { return m_blenderScene; } }; typedef std::vector KX_SceneList; diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 34a3baec093..f75a1ee5c62 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -69,11 +69,11 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SoundActuator::~KX_SoundActuator() { - //m_soundScene->RemoveObject(this->m_soundObject); - //(this->m_soundObject)->DeleteWhenFinished(); - m_soundScene->RemoveActiveObject(m_soundObject); -// m_soundScene->DeleteObjectWhenFinished(m_soundObject); - m_soundScene->DeleteObject(m_soundObject); + if (m_soundObject) + { + m_soundScene->RemoveActiveObject(m_soundObject); + m_soundScene->DeleteObject(m_soundObject); + } } @@ -82,9 +82,12 @@ CValue* KX_SoundActuator::GetReplica() { KX_SoundActuator* replica = new KX_SoundActuator(*this); replica->ProcessReplica(); - SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); - replica->setSoundObject(soundobj); - m_soundScene->AddObject(soundobj); + if (m_soundObject) + { + SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); + replica->setSoundObject(soundobj); + m_soundScene->AddObject(soundobj); + } // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -104,6 +107,9 @@ bool KX_SoundActuator::Update(double curtime, bool frame) RemoveAllEvents(); + if (!m_soundObject) + return false; + if (m_pino) { bNegativeEvent = true; @@ -287,6 +293,10 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* self, PyObject* args, PyObje PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObject* kwds) { + if (!m_soundObject) + { + return PyString_FromString(""); + } STR_String objectname = m_soundObject->GetObjectName(); char* name = objectname.Ptr(); @@ -301,7 +311,8 @@ PyObject* KX_SoundActuator::PyGetFilename(PyObject* self, PyObject* args, PyObje PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObject* kwds) { - m_soundObject->StartSound(); + if (m_soundObject) + m_soundObject->StartSound(); Py_Return; } @@ -309,7 +320,8 @@ PyObject* KX_SoundActuator::PyStartSound(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObject* kwds) { - m_soundObject->PauseSound(); + if (m_soundObject) + m_soundObject->PauseSound(); Py_Return; } @@ -317,7 +329,8 @@ PyObject* KX_SoundActuator::PyPauseSound(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyStopSound(PyObject* self, PyObject* args, PyObject* kwds) { - m_soundObject->StopSound(); + if (m_soundObject) + m_soundObject->StopSound(); Py_Return; } @@ -329,7 +342,8 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* if (!PyArg_ParseTuple(args, "f", &gain)) return NULL; - m_soundObject->SetGain(gain); + if (m_soundObject) + m_soundObject->SetGain(gain); Py_Return; } @@ -338,7 +352,7 @@ PyObject* KX_SoundActuator::PySetGain(PyObject* self, PyObject* args, PyObject* PyObject* KX_SoundActuator::PyGetGain(PyObject* self, PyObject* args, PyObject* kwds) { - float gain = m_soundObject->GetGain(); + float gain = (m_soundObject) ? m_soundObject->GetGain() : 1.0f; PyObject* result = PyFloat_FromDouble(gain); return result; @@ -352,7 +366,8 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* if (!PyArg_ParseTuple(args, "f", &pitch)) return NULL; - m_soundObject->SetPitch(pitch); + if (m_soundObject) + m_soundObject->SetPitch(pitch); Py_Return; } @@ -361,7 +376,7 @@ PyObject* KX_SoundActuator::PySetPitch(PyObject* self, PyObject* args, PyObject* PyObject* KX_SoundActuator::PyGetPitch(PyObject* self, PyObject* args, PyObject* kwds) { - float pitch = m_soundObject->GetPitch(); + float pitch = (m_soundObject) ? m_soundObject->GetPitch() : 1.0; PyObject* result = PyFloat_FromDouble(pitch); return result; @@ -375,7 +390,8 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P if (!PyArg_ParseTuple(args, "f", &rollofffactor)) return NULL; - m_soundObject->SetRollOffFactor(rollofffactor); + if (m_soundObject) + m_soundObject->SetRollOffFactor(rollofffactor); Py_Return; } @@ -384,7 +400,7 @@ PyObject* KX_SoundActuator::PySetRollOffFactor(PyObject* self, PyObject* args, P PyObject* KX_SoundActuator::PyGetRollOffFactor(PyObject* self, PyObject* args, PyObject* kwds) { - float rollofffactor = m_soundObject->GetRollOffFactor(); + float rollofffactor = (m_soundObject) ? m_soundObject->GetRollOffFactor() : 1.0; PyObject* result = PyFloat_FromDouble(rollofffactor); return result; @@ -398,7 +414,8 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec if (!PyArg_ParseTuple(args, "i", &looping)) return NULL; - m_soundObject->SetLoopMode(looping); + if (m_soundObject) + m_soundObject->SetLoopMode(looping); Py_Return; } @@ -407,7 +424,7 @@ PyObject* KX_SoundActuator::PySetLooping(PyObject* self, PyObject* args, PyObjec PyObject* KX_SoundActuator::PyGetLooping(PyObject* self, PyObject* args, PyObject* kwds) { - int looping = m_soundObject->GetLoopMode(); + int looping = (m_soundObject) ? m_soundObject->GetLoopMode() : SND_LOOP_OFF; PyObject* result = PyInt_FromLong(looping); return result; @@ -425,7 +442,8 @@ PyObject* KX_SoundActuator::PySetPosition(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "fff", &pos[0], &pos[1], &pos[2])) return NULL; - m_soundObject->SetPosition(pos); + if (m_soundObject) + m_soundObject->SetPosition(pos); Py_Return; } @@ -442,7 +460,8 @@ PyObject* KX_SoundActuator::PySetVelocity(PyObject* self, PyObject* args, PyObje if (!PyArg_ParseTuple(args, "fff", &vel[0], &vel[1], &vel[2])) return NULL; - m_soundObject->SetVelocity(vel); + if (m_soundObject) + m_soundObject->SetVelocity(vel); Py_Return; } @@ -465,7 +484,8 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* self, PyObject* args, PyO if (!PyArg_ParseTuple(args, "fffffffff", &ori[0][0], &ori[0][1], &ori[0][2], &ori[1][0], &ori[1][1], &ori[1][2], &ori[2][0], &ori[2][1], &ori[2][2])) return NULL; - m_soundObject->SetOrientation(ori); + if (m_soundObject) + m_soundObject->SetOrientation(ori); Py_Return; } diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 67937d5c579..8b09cd4e953 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -42,6 +42,8 @@ #include #include "KX_GameObject.h" +#include "PyObjectPlus.h" + #ifdef HAVE_CONFIG_H #include #endif diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index f5a2b5e02fe..342e71c5093 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -1,6 +1,8 @@ #include +#include "PyObjectPlus.h" + #include "KX_VehicleWrapper.h" #include "PHY_IPhysicsEnvironment.h" #include "PHY_IVehicle.h" diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 5cec65dff1c..25205714308 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -82,7 +82,7 @@ PyObject* KX_VertexProxy::_getattr(const STR_String& attr) { if (attr == "XYZ") - return PyObjectFrom(MT_Vector3(m_vertex->getLocalXYZ())); + return PyObjectFrom(MT_Vector3(m_vertex->getXYZ())); if (attr == "UV") return PyObjectFrom(MT_Point2(m_vertex->getUV1())); @@ -102,11 +102,11 @@ KX_VertexProxy::_getattr(const STR_String& attr) // pos if (attr == "x") - return PyFloat_FromDouble(m_vertex->getLocalXYZ()[0]); + return PyFloat_FromDouble(m_vertex->getXYZ()[0]); if (attr == "y") - return PyFloat_FromDouble(m_vertex->getLocalXYZ()[1]); + return PyFloat_FromDouble(m_vertex->getXYZ()[1]); if (attr == "z") - return PyFloat_FromDouble(m_vertex->getLocalXYZ()[2]); + return PyFloat_FromDouble(m_vertex->getXYZ()[2]); // Col if (attr == "r") @@ -184,7 +184,7 @@ int KX_VertexProxy::_setattr(const STR_String& attr, PyObject *pyvalue) { float val = PyFloat_AsDouble(pyvalue); // pos - MT_Point3 pos(m_vertex->getLocalXYZ()); + MT_Point3 pos(m_vertex->getXYZ()); if (attr == "x") { pos.x() = val; @@ -312,7 +312,7 @@ PyObject* KX_VertexProxy::PyGetXYZ(PyObject*, PyObject*, PyObject*) { - return PyObjectFrom(MT_Point3(m_vertex->getLocalXYZ())); + return PyObjectFrom(MT_Point3(m_vertex->getXYZ())); } PyObject* KX_VertexProxy::PySetXYZ(PyObject*, @@ -426,7 +426,7 @@ PyObject* KX_VertexProxy::PySetUV2(PyObject*, { if (PyVecTo(list, vec)) { - m_vertex->SetFlag((m_vertex->getFlag()|TV_2NDUV)); + m_vertex->SetFlag((m_vertex->getFlag()|RAS_TexVert::SECOND_UV)); m_vertex->SetUnit(unit); m_vertex->SetUV2(vec); m_mesh->SetMeshModified(true); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index b4693a7a7db..e60a8d7c099 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -38,10 +38,12 @@ KX_VisibilityActuator::KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool recursive, PyTypeObject* T ) : SCA_IActuator(gameobj,T), - m_visible(visible) + m_visible(visible), + m_recursive(recursive) { // intentionally empty } @@ -75,10 +77,10 @@ KX_VisibilityActuator::Update() KX_GameObject *obj = (KX_GameObject*) GetParent(); - obj->SetVisible(m_visible); - obj->MarkVisible(); + obj->SetVisible(m_visible, m_recursive); + obj->UpdateBuckets(m_recursive); - return true; + return false; } /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index 9b4753033fb..d1b85ab998c 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -39,12 +39,14 @@ class KX_VisibilityActuator : public SCA_IActuator /** Make visible? */ bool m_visible; + bool m_recursive; public: KX_VisibilityActuator( SCA_IObject* gameobj, bool visible, + bool recursive, PyTypeObject* T=&Type ); diff --git a/source/gameengine/Ketsji/Makefile b/source/gameengine/Ketsji/Makefile index 47a4855b00c..0b48ad8b8c3 100644 --- a/source/gameengine/Ketsji/Makefile +++ b/source/gameengine/Ketsji/Makefile @@ -35,10 +35,13 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) +CPPFLAGS += $(NAN_SDLCFLAGS) CPPFLAGS += $(OGL_CPPFLAGS) CPPFLAGS += -I$(NAN_GLEW)/include CPPFLAGS += -I$(OPENGL_HEADERS) -CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) -I../../blender/python +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) +CPPFLAGS += -I../../blender/python +CPPFLAGS += -I../../blender/python/api2_2x CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include CPPFLAGS += -I$(NAN_FUZZICS)/include -I$(NAN_SUMO) -I$(NAN_MOTO)/include @@ -61,13 +64,9 @@ CPPFLAGS += -I../../blender/blenlib CPPFLAGS += -I../../blender/include CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I../../blender/imbuf +CPPFLAGS += -I../../blender/gpu CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - - ########################### SOURCEDIR = source/gameengine/Ketsji diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index f6f744b199a..02e7aed82a5 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -32,16 +32,13 @@ incs += ' #source/gameengine/SceneGraph #source/gameengine/Physics/common #sourc incs += ' #source/gameengine/Physics/BlOde #source/gameengine/Physics/Dummy' incs += ' #source/gameengine/Physics/Sumo #source/gameengine/Physics/Sumo/include' incs += ' #source/gameengine/Physics/Sumo/Fuzzics/include #source/gameengine/Network/LoopBackNetwork' -incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include' +incs += ' #source/blender/misc #source/blender/blenloader #extern/glew/include #source/blender/gpu' cflags = [] if env['OURPLATFORM'] == 'win32-vc': cflags.append('/GR') cflags.append('/Ox') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - incs += ' ' + env['BF_SOLID_INC'] incs += ' ' + env['BF_PYTHON_INC'] incs += ' ' + env['BF_SDL_INC'] diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp index a04560aaf09..2e8ee31058f 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp @@ -198,7 +198,7 @@ int ODEPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl } -void ODEPhysicsEnvironment::removeConstraint(int constraintid) +void ODEPhysicsEnvironment::removeConstraint(void *constraintid) { if (constraintid) { @@ -206,8 +206,7 @@ void ODEPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) +PHY_IPhysicsController* ODEPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { //m_OdeWorld diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index 7c61902f8e2..dcc87d614c0 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -54,8 +54,7 @@ public: float axisX,float axisY,float axisZ); virtual void removeConstraint(void * constraintid); - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index d6a32dfd9c0..b1b97b5370f 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -15,10 +15,11 @@ subject to the following restrictions: #include "CcdPhysicsController.h" #include "btBulletDynamicsCommon.h" - +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" #include "PHY_IMotionState.h" #include "CcdPhysicsEnvironment.h" #include "RAS_MeshObject.h" +#include "BulletSoftBody/btSoftBody.h" class BP_Proxy; @@ -63,11 +64,11 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) CreateRigidbody(); - - #ifdef WIN32 - if (m_body->getInvMass()) - m_body->setLinearVelocity(startVel); - #endif +///??? +#ifdef WIN32 + if (GetRigidBody() && !GetRigidBody()->isStaticObject()) + GetRigidBody()->setLinearVelocity(startVel); +#endif } @@ -119,20 +120,60 @@ public: }; +btRigidBody* CcdPhysicsController::GetRigidBody() +{ + return btRigidBody::upcast(m_object); +} +btCollisionObject* CcdPhysicsController::GetCollisionObject() +{ + return m_object; +} +btSoftBody* CcdPhysicsController::GetSoftBody() +{ + return btSoftBody::upcast(m_object); +} + + void CcdPhysicsController::CreateRigidbody() { btTransform trans = GetTransformFromMotionState(m_MotionState); - m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); - m_body = new btRigidBody(m_cci.m_mass, - m_bulletMotionState, - m_collisionShape, - m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor, - m_cci.m_linearDamping,m_cci.m_angularDamping, - m_cci.m_friction,m_cci.m_restitution); + ///either create a btCollisionObject, btRigidBody or btSoftBody + //create a collision object + if (0)//m_cci.m_mass==0.f) + { + btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + rbci.m_linearDamping = m_cci.m_linearDamping; + rbci.m_angularDamping = m_cci.m_angularDamping; + rbci.m_friction = m_cci.m_friction; + rbci.m_restitution = m_cci.m_restitution; + m_object = new btCollisionObject(); + m_object->setCollisionShape(rbci.m_collisionShape); + btTransform startTrans; + + if (rbci.m_motionState) + { + rbci.m_motionState->getWorldTransform(startTrans); + } else + { + startTrans = rbci.m_startWorldTransform; + } + m_object->setWorldTransform(startTrans); + m_object->setInterpolationWorldTransform(startTrans); + + } else + { + btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + rbci.m_linearDamping = m_cci.m_linearDamping; + rbci.m_angularDamping = m_cci.m_angularDamping; + rbci.m_friction = m_cci.m_friction; + rbci.m_restitution = m_cci.m_restitution; + m_object = new btRigidBody(rbci); + } + // // init the rigidbody properly // @@ -144,15 +185,20 @@ void CcdPhysicsController::CreateRigidbody() if ((m_cci.m_collisionFilterGroup & CcdConstructionInfo::SensorFilter) != 0) { // reset the flags that have been set so far - m_body->setCollisionFlags(0); + GetCollisionObject()->setCollisionFlags(0); } - m_body->setCollisionFlags(m_body->getCollisionFlags() | m_cci.m_collisionFlags); - m_body->setGravity( m_cci.m_gravity); - m_body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping); + GetCollisionObject()->setCollisionFlags(m_object->getCollisionFlags() | m_cci.m_collisionFlags); + btRigidBody* body = GetRigidBody(); - if (!m_cci.m_bRigid) + if (body) { - m_body->setAngularFactor(0.f); + body->setGravity( m_cci.m_gravity); + body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping); + + if (!m_cci.m_bRigid) + { + body->setAngularFactor(0.f); + } } } @@ -179,7 +225,7 @@ CcdPhysicsController::~CcdPhysicsController() delete m_MotionState; if (m_bulletMotionState) delete m_bulletMotionState; - delete m_body; + delete m_object; if (m_collisionShape) { @@ -211,12 +257,14 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) { //sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.) - if (!m_body->isStaticObject()) + btRigidBody* body = GetRigidBody(); + + if (body && !body->isStaticObject()) { - const btVector3& worldPos = m_body->getCenterOfMassPosition(); + const btVector3& worldPos = body->getCenterOfMassPosition(); m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - const btQuaternion& worldquat = m_body->getOrientation(); + const btQuaternion& worldquat = body->getOrientation(); m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]); m_MotionState->calculateWorldTransformations(); @@ -235,7 +283,7 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) btTransform oldTrans = m_body->getCenterOfMassTransform(); btTransform newTrans(worldquat,worldPos); - m_body->setCenterOfMassTransform(newTrans); + SetCenterOfMassTransform(newTrans); //need to keep track of previous position for friction effects... m_MotionState->calculateWorldTransformations(); @@ -276,21 +324,25 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta if (m_collisionShape) { // new shape has no scaling, apply initial scaling + m_collisionShape->setMargin(m_cci.m_margin); m_collisionShape->setLocalScaling(m_cci.m_scaling); + if (m_cci.m_mass) m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); } } - m_body = 0; + m_object = 0; CreateRigidbody(); - if (m_body) + btRigidBody* body = GetRigidBody(); + + if (body) { if (m_cci.m_mass) { - m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - } + body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + } } m_cci.m_physicsEnv->addCcdPhysicsController(this); @@ -325,42 +377,77 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta +} + + +void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform) +{ + btRigidBody* body = GetRigidBody(); + if (body) + { + body->setCenterOfMassTransform(xform); + } else + { + //either collision object or soft body? + if (GetSoftBody()) + { + //not yet + } else + { + + if (m_object->isStaticOrKinematicObject()) + { + m_object->setInterpolationWorldTransform(m_object->getWorldTransform()); + } else + { + m_object->setInterpolationWorldTransform(xform); + } + if (body) + { + body->setInterpolationLinearVelocity(body->getLinearVelocity()); + body->setInterpolationAngularVelocity(body->getAngularVelocity()); + body->updateInertiaTensor(); + } + m_object->setWorldTransform(xform); + } + } } // kinematic methods void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + btRigidBody* body = GetRigidBody(); btVector3 dloc(dlocX,dlocY,dlocZ); - btTransform xform = m_body->getCenterOfMassTransform(); - + btTransform xform = m_object->getWorldTransform(); + if (local) { dloc = xform.getBasis()*dloc; } xform.setOrigin(xform.getOrigin() + dloc); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); } } void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } btMatrix3x3 drotmat( rotval[0],rotval[4],rotval[8], @@ -371,16 +458,16 @@ void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local) btMatrix3x3 currentOrn; GetWorldOrientation(currentOrn); - btTransform xform = m_body->getCenterOfMassTransform(); - + btTransform xform = m_object->getWorldTransform(); + xform.setBasis(xform.getBasis()*(local ? drotmat : (currentOrn.inverse() * drotmat * currentOrn))); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); } - } + void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat) { float orn[4]; @@ -391,7 +478,7 @@ void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat) void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal) { - btQuaternion q = m_body->getCenterOfMassTransform().getRotation(); + btQuaternion q = m_object->getWorldTransform().getRotation(); quatImag0 = q[0]; quatImag1 = q[1]; quatImag2 = q[2]; @@ -399,18 +486,18 @@ void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,flo } void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } // not required //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); xform.setRotation(btQuaternion(quatImag0,quatImag1,quatImag2,quatReal)); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -419,18 +506,18 @@ void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } // not required //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); xform.setBasis(orn); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -439,18 +526,18 @@ void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) void CcdPhysicsController::setPosition(float posX,float posY,float posZ) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } // not required, this function is only used to update the physic controller //m_MotionState->setWorldPosition(posX,posY,posZ); - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); xform.setOrigin(btVector3(posX,posY,posZ)); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -463,7 +550,7 @@ void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvel void CcdPhysicsController::getPosition(PHY__Vector3& pos) const { - const btTransform& xform = m_body->getCenterOfMassTransform(); + const btTransform& xform = m_object->getWorldTransform(); pos[0] = xform.getOrigin().x(); pos[1] = xform.getOrigin().y(); pos[2] = xform.getOrigin().z(); @@ -477,15 +564,16 @@ void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) { m_cci.m_scaling = btVector3(scaleX,scaleY,scaleZ); - if (m_body && m_body->getCollisionShape()) + if (m_object && m_object->getCollisionShape()) { - m_body->getCollisionShape()->setLocalScaling(m_cci.m_scaling); + m_object->getCollisionShape()->setLocalScaling(m_cci.m_scaling); //printf("no inertia recalc for fixed objects with mass=0\n"); - if (m_cci.m_mass) + btRigidBody* body = GetRigidBody(); + if (body && m_cci.m_mass) { - m_body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); - m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); + body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); } } @@ -496,19 +584,23 @@ void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) void CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local) { btVector3 torque(torqueX,torqueY,torqueZ); - btTransform xform = m_body->getCenterOfMassTransform(); - if (m_body && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + btTransform xform = m_object->getWorldTransform(); + + + if (m_object && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(); - if (m_body->isStaticObject()) + btRigidBody* body = GetRigidBody(); + m_object->activate(); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } if (local) { torque = xform.getBasis()*torque; } - m_body->applyTorque(torque); + if (body) + body->applyTorque(torque); } } @@ -516,41 +608,47 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo { btVector3 force(forceX,forceY,forceZ); - if (m_body && force.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + + if (m_object && force.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(); - if (m_body->isStaticObject()) + m_object->activate(); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + + btRigidBody* body = GetRigidBody(); + if (body) { - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = body->getCenterOfMassTransform(); if (local) { force = xform.getBasis()*force; } + body->applyCentralForce(force); } - m_body->applyCentralForce(force); } } void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local) { btVector3 angvel(ang_velX,ang_velY,ang_velZ); - if (m_body && angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + if (m_object && angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + btRigidBody* body = GetRigidBody(); + if (body) { - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = body->getCenterOfMassTransform(); if (local) { angvel = xform.getBasis()*angvel; } + body->setAngularVelocity(angvel); } - m_body->setAngularVelocity(angvel); } } @@ -558,39 +656,41 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa { btVector3 linVel(lin_velX,lin_velY,lin_velZ); - if (m_body && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + if (m_object && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - + btRigidBody* body = GetRigidBody(); + if (body) { - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); if (local) { linVel = xform.getBasis()*linVel; } + body->setLinearVelocity(linVel); } - m_body->setLinearVelocity(linVel); } } void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ) { btVector3 impulse(impulseX,impulseY,impulseZ); - if (m_body && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + if (m_object && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(); - if (m_body->isStaticObject()) + m_object->activate(); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } btVector3 pos(attachX,attachY,attachZ); - - m_body->applyImpulse(impulse,pos); + btRigidBody* body = GetRigidBody(); + if (body) + body->applyImpulse(impulse,pos); } } @@ -600,29 +700,56 @@ void CcdPhysicsController::SetActive(bool active) // reading out information from physics void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ) { - const btVector3& linvel = this->m_body->getLinearVelocity(); - linvX = linvel.x(); - linvY = linvel.y(); - linvZ = linvel.z(); + btRigidBody* body = GetRigidBody(); + if (body) + { + const btVector3& linvel = body->getLinearVelocity(); + linvX = linvel.x(); + linvY = linvel.y(); + linvZ = linvel.z(); + } else + { + linvX = 0.f; + linvY = 0.f; + linvZ = 0.f; + } } void CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ) { - const btVector3& angvel= m_body->getAngularVelocity(); - angVelX = angvel.x(); - angVelY = angvel.y(); - angVelZ = angvel.z(); + btRigidBody* body = GetRigidBody(); + if (body) + { + const btVector3& angvel= body->getAngularVelocity(); + angVelX = angvel.x(); + angVelY = angvel.y(); + angVelZ = angvel.z(); + } else + { + angVelX = 0.f; + angVelY = 0.f; + angVelZ = 0.f; + } } void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ) { btVector3 pos(posX,posY,posZ); - btVector3 rel_pos = pos-m_body->getCenterOfMassPosition(); - btVector3 linvel = m_body->getVelocityInLocalPoint(rel_pos); - linvX = linvel.x(); - linvY = linvel.y(); - linvZ = linvel.z(); + btRigidBody* body = GetRigidBody(); + if (body) + { + btVector3 rel_pos = pos-body->getCenterOfMassPosition(); + btVector3 linvel = body->getVelocityInLocalPoint(rel_pos); + linvX = linvel.x(); + linvY = linvel.y(); + linvZ = linvel.z(); + } else + { + linvX = 0.f; + linvY = 0.f; + linvZ = 0.f; + } } void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ) { @@ -633,11 +760,15 @@ void CcdPhysicsController::setRigidBody(bool rigid) { if (!rigid) { - //fake it for now - btVector3 inertia = m_body->getInvInertiaDiagLocal(); - inertia[1] = 0.f; - m_body->setInvInertiaDiagLocal(inertia); - m_body->updateInertiaTensor(); + btRigidBody* body = GetRigidBody(); + if (body) + { + //fake it for now + btVector3 inertia = body->getInvInertiaDiagLocal(); + inertia[1] = 0.f; + body->setInvInertiaDiagLocal(inertia); + body->updateInertiaTensor(); + } } } @@ -654,13 +785,22 @@ void CcdPhysicsController::setNewClientInfo(void* clientinfo) void CcdPhysicsController::UpdateDeactivation(float timeStep) { - m_body->updateDeactivation( timeStep); + btRigidBody* body = GetRigidBody(); + if (body) + { + body->updateDeactivation( timeStep); + } } bool CcdPhysicsController::wantsSleeping() { - - return m_body->wantsSleeping(); + btRigidBody* body = GetRigidBody(); + if (body) + { + return body->wantsSleeping(); + } + //check it out + return true; } PHY_IPhysicsController* CcdPhysicsController::GetReplica() @@ -767,6 +907,8 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) // assume no shape information m_shapeType = PHY_SHAPE_NONE; m_vertexArray.clear(); + m_polygonIndexArray.clear(); + m_meshObject = NULL; if (!meshobj) return false; @@ -813,9 +955,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) { for (int i=0;iVertexCount();i++) { - const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[i], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + const float* vtx = poly->GetVertex(i)->getXYZ(); btPoint3 point(vtx[0],vtx[1],vtx[2]); m_vertexArray.push_back(point); numvalidpolys++; @@ -823,40 +963,36 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) } else { { - const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + const float* vtx = poly->GetVertex(2)->getXYZ(); btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[1], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(1)->getXYZ(); btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(0)->getXYZ(); btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); + m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); m_vertexArray.push_back(vertex2); + m_polygonIndexArray.push_back(p2); numvalidpolys++; } if (poly->VertexCount() == 4) { - const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[3], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + const float* vtx = poly->GetVertex(3)->getXYZ(); btPoint3 vertex0(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[2], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(2)->getXYZ(); btPoint3 vertex1(vtx[0],vtx[1],vtx[2]); - vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, - poly->GetVertexIndexBase().m_indexarray[0], - poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ(); + + vtx = poly->GetVertex(0)->getXYZ(); btPoint3 vertex2(vtx[0],vtx[1],vtx[2]); + m_vertexArray.push_back(vertex0); m_vertexArray.push_back(vertex1); m_vertexArray.push_back(vertex2); + m_polygonIndexArray.push_back(p2); numvalidpolys++; } } @@ -869,6 +1005,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) m_shapeType = PHY_SHAPE_NONE; return false; } + m_meshObject = meshobj; return true; } @@ -906,15 +1043,26 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() break; case PHY_SHAPE_MESH: - collisionMeshData = new btTriangleMesh(); - // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + // Let's use the latest btScaledBvhTriangleMeshShape: it allows true sharing of + // triangle mesh information between duplicates => drastic performance increase when + // duplicating complex mesh objects. + // BUT it causes a small performance decrease when sharing is not required: + // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering + // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 + // and btScaledBvhTriangleMeshShape otherwise. + if (!m_unscaledShape) { - collisionMeshData->addTriangle(*it++,*it++,*it++); + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + { + collisionMeshData->addTriangle(*it++,*it++,*it++); + } + // this shape will be shared and not deleted until shapeInfo is deleted + m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); + m_unscaledShape->recalcLocalAabb(); } - concaveShape = new btBvhTriangleMeshShape( collisionMeshData, true ); - concaveShape->recalcLocalAabb(); - collisionShape = concaveShape; + collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); break; case PHY_SHAPE_COMPOUND: @@ -926,6 +1074,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionShape = nextShapeInfo->CreateBulletShape(); if (collisionShape) { + collisionShape->setLocalScaling(nextShapeInfo->m_childScale); compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape); } } @@ -954,7 +1103,10 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() childShape->Release(); childShape = nextShape; } - + if (m_unscaledShape) + { + DeleteBulletShape(m_unscaledShape); + } m_vertexArray.clear(); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 1e1a38aa2a6..355c1d608b1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -47,7 +47,9 @@ public: m_radius(1.0), m_height(1.0), m_halfExtend(0.f,0.f,0.f), + m_childScale(1.0f,1.0f,1.0f), m_nextShape(NULL), + m_unscaledShape(NULL), m_refCount(1) { m_childTrans.setIdentity(); @@ -71,10 +73,24 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); + btTriangleMeshShape* GetMeshShape(void) + { + return m_unscaledShape; + } CcdShapeConstructionInfo* GetNextShape() { return m_nextShape; } + CcdShapeConstructionInfo* GetChildShape(int i) + { + CcdShapeConstructionInfo* shape = m_nextShape; + while (i > 0 && shape != NULL) + { + shape = shape->m_nextShape; + i--; + } + return shape; + } bool SetMesh(RAS_MeshObject* mesh, bool polytope); @@ -86,11 +102,19 @@ public: btScalar m_height; btVector3 m_halfExtend; btTransform m_childTrans; + btVector3 m_childScale; std::vector m_vertexArray; // Contains both vertex array for polytope shape and // triangle array for concave mesh shape. // In this case a triangle is made of 3 consecutive points + std::vector m_polygonIndexArray; // Contains the array of polygon index in the + // original mesh that correspond to shape triangles. + // only set for concave mesh shape. + const RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh + protected: CcdShapeConstructionInfo* m_nextShape; // for compound shape + btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, + // the actual shape is of type btScaledBvhTriangleMeshShape int m_refCount; // this class is shared between replicas // keep track of users so that we can release it }; @@ -113,13 +137,15 @@ struct CcdConstructionInfo CcdConstructionInfo() - : m_gravity(0,0,0), + : m_localInertiaTensor(1.f, 1.f, 1.f), + m_gravity(0,0,0), m_scaling(1.f,1.f,1.f), m_mass(0.f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), m_angularDamping(0.1f), + m_margin(0.06f), m_collisionFlags(0), m_bRigid(false), m_collisionFilterGroup(DefaultFilter), @@ -140,6 +166,7 @@ struct CcdConstructionInfo btScalar m_friction; btScalar m_linearDamping; btScalar m_angularDamping; + btScalar m_margin; int m_collisionFlags; bool m_bRigid; @@ -163,12 +190,15 @@ struct CcdConstructionInfo class btRigidBody; - +class btCollisionObject; +class btSoftBody; ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { - btRigidBody* m_body; + + btCollisionObject* m_object; + class PHY_IMotionState* m_MotionState; btMotionState* m_bulletMotionState; class btCollisionShape* m_collisionShape; @@ -204,11 +234,14 @@ class CcdPhysicsController : public PHY_IPhysicsController virtual ~CcdPhysicsController(); - btRigidBody* GetRigidBody() { return m_body;} + btRigidBody* GetRigidBody(); + btCollisionObject* GetCollisionObject(); + btSoftBody* GetSoftBody(); + CcdShapeConstructionInfo* GetShapeInfo() { return m_shapeInfo; } btCollisionShape* GetCollisionShape() { - return m_body->getCollisionShape(); + return m_object->getCollisionShape(); } //////////////////////////////////// // PHY_IPhysicsController interface @@ -283,6 +316,8 @@ class CcdPhysicsController : public PHY_IPhysicsController void UpdateDeactivation(float timeStep); + void SetCenterOfMassTransform(btTransform& xform); + static btTransform GetTransformFromMotionState(PHY_IMotionState* motionState); void setAabb(const btVector3& aabbMin,const btVector3& aabbMax); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index d8e05fab839..96caf885e7c 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -23,6 +23,7 @@ subject to the following restrictions: #include "btBulletDynamicsCommon.h" #include "LinearMath/btIDebugDraw.h" #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" //profiling/timings #include "LinearMath/btQuickprof.h" @@ -53,6 +54,7 @@ void DrawRasterizerLine(const float* from,const float* to,int color); #include +#include // for memset #ifdef NEW_BULLET_VEHICLE_SUPPORT class WrapperVehicle : public PHY_IVehicle @@ -329,30 +331,23 @@ m_filterCallback(NULL) { m_triggerCallbacks[i] = 0; } + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + if (!dispatcher) { - dispatcher = new btCollisionDispatcher(); + dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_ownDispatcher = dispatcher; } - if(!pairCache) - { - - //todo: calculate/let user specify this world sizes - btVector3 worldMin(-10000,-10000,-10000); - btVector3 worldMax(10000,10000,10000); - - pairCache = new btAxisSweep3(worldMin,worldMax); - // remember that this was allocated by us so that we can release it - m_ownPairCache = pairCache; - //broadphase = new btSimpleBroadphase(); - } + m_broadphase = new btDbvtBroadphase(); m_filterCallback = new CcdOverlapFilterCallBack(this); - pairCache->setOverlapFilterCallback(m_filterCallback); + m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback); setSolverType(1);//issues with quickstep and memory allocations - m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,pairCache,m_solver); +// m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_debugDrawer = 0; m_gravity = btVector3(0.f,-10.f,0.f); m_dynamicsWorld->setGravity(m_gravity); @@ -363,24 +358,43 @@ m_filterCallback(NULL) void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) { btRigidBody* body = ctrl->GetRigidBody(); + btCollisionObject* obj = ctrl->GetCollisionObject(); //this m_userPointer is just used for triggers, see CallbackTriggers - body->setUserPointer(ctrl); + obj->setUserPointer(ctrl); + if (body) + body->setGravity( m_gravity ); - body->setGravity( m_gravity ); m_controllers.insert(ctrl); - //use explicit group/filter for finer control over collision in bullet => near/radar sensor - m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); - if (body->isStaticOrKinematicObject()) + if (body) { - body->setActivationState(ISLAND_SLEEPING); + //use explicit group/filter for finer control over collision in bullet => near/radar sensor + m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); + } else + { + if (ctrl->GetSoftBody()) + { + //not yet + btAssert(0); + //m_dynamicsWorld->addSo + } else + { + if (obj->getCollisionShape()) + { + m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); + } + } + } + if (obj->isStaticOrKinematicObject()) + { + obj->setActivationState(ISLAND_SLEEPING); } //CollisionObject(body,ctrl->GetCollisionFilterGroup(),ctrl->GetCollisionFilterMask()); - assert(body->getBroadphaseHandle()); + assert(obj->getBroadphaseHandle()); btBroadphaseInterface* scene = getBroadphase(); @@ -389,7 +403,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) assert(shapeinterface); - const btTransform& t = ctrl->GetRigidBody()->getCenterOfMassTransform(); + const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform(); btPoint3 minAabb,maxAabb; @@ -401,32 +415,34 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) //extent it with the motion - btVector3 linMotion = body->getLinearVelocity()*timeStep; + if (body) + { + btVector3 linMotion = body->getLinearVelocity()*timeStep; - float maxAabbx = maxAabb.getX(); - float maxAabby = maxAabb.getY(); - float maxAabbz = maxAabb.getZ(); - float minAabbx = minAabb.getX(); - float minAabby = minAabb.getY(); - float minAabbz = minAabb.getZ(); + float maxAabbx = maxAabb.getX(); + float maxAabby = maxAabb.getY(); + float maxAabbz = maxAabb.getZ(); + float minAabbx = minAabb.getX(); + float minAabby = minAabb.getY(); + float minAabbz = minAabb.getZ(); - if (linMotion.x() > 0.f) - maxAabbx += linMotion.x(); - else - minAabbx += linMotion.x(); - if (linMotion.y() > 0.f) - maxAabby += linMotion.y(); - else - minAabby += linMotion.y(); - if (linMotion.z() > 0.f) - maxAabbz += linMotion.z(); - else - minAabbz += linMotion.z(); + if (linMotion.x() > 0.f) + maxAabbx += linMotion.x(); + else + minAabbx += linMotion.x(); + if (linMotion.y() > 0.f) + maxAabby += linMotion.y(); + else + minAabby += linMotion.y(); + if (linMotion.z() > 0.f) + maxAabbz += linMotion.z(); + else + minAabbz += linMotion.z(); - minAabb = btVector3(minAabbx,minAabby,minAabbz); - maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz); - + minAabb = btVector3(minAabbx,minAabby,minAabbz); + maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz); + } @@ -435,8 +451,22 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl) { //also remove constraint - - m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + btRigidBody* body = ctrl->GetRigidBody(); + if (body) + { + m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + } else + { + //if a softbody + if (ctrl->GetSoftBody()) + { + //not yet + btAssert(0); + } else + { + m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); + } + } m_controllers.erase(ctrl); if (ctrl->m_registerCount != 0) @@ -451,13 +481,20 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); - btVector3 inertia; - - m_dynamicsWorld->removeCollisionObject(body); - body->setCollisionFlags(newCollisionFlags); - body->getCollisionShape()->calculateLocalInertia(newMass, inertia); - body->setMassProps(newMass, inertia); - m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); + btCollisionObject* obj = ctrl->GetCollisionObject(); + if (obj) + { + btVector3 inertia(0.0,0.0,0.0); + m_dynamicsWorld->removeCollisionObject(obj); + obj->setCollisionFlags(newCollisionFlags); + if (body) + { + if (newMass) + body->getCollisionShape()->calculateLocalInertia(newMass, inertia); + body->setMassProps(newMass, inertia); + } + m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); + } // to avoid nasty interaction, we must update the property of the controller as well ctrl->m_cci.m_mass = newMass; ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup; @@ -469,9 +506,9 @@ void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctr { if (m_controllers.insert(ctrl).second) { - btRigidBody* body = ctrl->GetRigidBody(); - body->setUserPointer(ctrl); - m_dynamicsWorld->addCollisionObject(body, + btCollisionObject* obj = ctrl->GetCollisionObject(); + obj->setUserPointer(ctrl); + m_dynamicsWorld->addCollisionObject(obj, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); } } @@ -480,7 +517,19 @@ void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ct { if (m_controllers.erase(ctrl)) { - m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + btRigidBody* body = ctrl->GetRigidBody(); + if (body) + { + m_dynamicsWorld->removeRigidBody(body); + } else + { + if (ctrl->GetSoftBody()) + { + } else + { + m_dynamicsWorld->removeCollisionObject(body); + } + } } } @@ -518,6 +567,9 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) veh->SyncWheels(); } + m_dynamicsWorld->debugDrawWorld(); + + CallbackTriggers(); return true; @@ -578,7 +630,7 @@ void CcdPhysicsEnvironment::setSolverDamping(float damping) void CcdPhysicsEnvironment::setLinearAirDamping(float damping) { - gLinearAirDamping = damping; + //gLinearAirDamping = damping; } void CcdPhysicsEnvironment::setUseEpa(bool epa) @@ -597,7 +649,7 @@ void CcdPhysicsEnvironment::setSolverType(int solverType) { m_solver = new btSequentialImpulseConstraintSolver(); - ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); +// ((btSequentialImpulseConstraintSolver*)m_solver)->setSolverMode(btSequentialImpulseConstraintSolver::SOLVER_USE_WARMSTARTING | btSequentialImpulseConstraintSolver::SOLVER_RANDMIZE_ORDER); break; } } @@ -659,9 +711,10 @@ int CcdPhysicsEnvironment::createUniversalD6Constraint( { + bool useReferenceFrameA = true; genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB); + frameInA,frameInB,useReferenceFrameA); genericConstraint->setLinearLowerLimit(linearMinLimits); genericConstraint->setLinearUpperLimit(linearMaxLimits); genericConstraint->setAngularLowerLimit(angularMinLimits); @@ -709,35 +762,54 @@ void CcdPhysicsEnvironment::removeConstraint(int constraintId) struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback { - PHY_IPhysicsController* m_ignoreClient; + PHY_IRayCastFilterCallback& m_phyRayFilter; + const btCollisionShape* m_hitTriangleShape; + int m_hitTriangleIndex; - FilterClosestRayResultCallback (PHY_IPhysicsController* ignoreClient,const btVector3& rayFrom,const btVector3& rayTo) + FilterClosestRayResultCallback (PHY_IRayCastFilterCallback& phyRayFilter,const btVector3& rayFrom,const btVector3& rayTo) : btCollisionWorld::ClosestRayResultCallback(rayFrom,rayTo), - m_ignoreClient(ignoreClient) + m_phyRayFilter(phyRayFilter), + m_hitTriangleShape(NULL), + m_hitTriangleIndex(0) { - } virtual ~FilterClosestRayResultCallback() { } - virtual float AddSingleResult( btCollisionWorld::LocalRayResult& rayResult) + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask)) + return false; + if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask)) + return false; + btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject; + CcdPhysicsController* phyCtrl = static_cast(object->getUserPointer()); + if (phyCtrl == m_phyRayFilter.m_ignoreController) + return false; + return m_phyRayFilter.needBroadphaseRayCast(phyCtrl); + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) { CcdPhysicsController* curHit = static_cast(rayResult.m_collisionObject->getUserPointer()); - //ignore client... - if (curHit != m_ignoreClient) - { - //if valid - return ClosestRayResultCallback::AddSingleResult(rayResult); + // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it + if (rayResult.m_localShapeInfo) + { + m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape(); + m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex; + } else + { + m_hitTriangleShape = NULL; + m_hitTriangleIndex = 0; } - return m_closestHitFraction; + return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace); } }; -PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) +PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { @@ -751,19 +823,101 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* i //Either Ray Cast with or without filtering //btCollisionWorld::ClosestRayResultCallback rayCallback(rayFrom,rayTo); - FilterClosestRayResultCallback rayCallback(ignoreClient,rayFrom,rayTo); + FilterClosestRayResultCallback rayCallback(filterCallback,rayFrom,rayTo); - PHY_IPhysicsController* nearestHit = 0; + PHY_RayCastResult result; + memset(&result, 0, sizeof(result)); + // don't collision with sensor object - m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback, CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter); - if (rayCallback.HasHit()) - { - nearestHit = static_cast(rayCallback.m_collisionObject->getUserPointer()); - hitX = rayCallback.m_hitPointWorld.getX(); - hitY = rayCallback.m_hitPointWorld.getY(); - hitZ = rayCallback.m_hitPointWorld.getZ(); + rayCallback.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; + //, ,filterCallback.m_faceNormal); + m_dynamicsWorld->rayTest(rayFrom,rayTo,rayCallback); + if (rayCallback.hasHit()) + { + CcdPhysicsController* controller = static_cast(rayCallback.m_collisionObject->getUserPointer()); + result.m_controller = controller; + result.m_hitPoint[0] = rayCallback.m_hitPointWorld.getX(); + result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY(); + result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ(); + + if (rayCallback.m_hitTriangleShape != NULL) + { + // identify the mesh polygon + CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo; + if (shapeInfo) + { + btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape(); + if (shape->isCompound()) + { + btCompoundShape* compoundShape = (btCompoundShape*)shape; + CcdShapeConstructionInfo* compoundShapeInfo = shapeInfo; + // need to search which sub-shape has been hit + for (int i=0; igetNumChildShapes(); i++) + { + shapeInfo = compoundShapeInfo->GetChildShape(i); + shape=compoundShape->getChildShape(i); + if (shape == rayCallback.m_hitTriangleShape) + break; + } + } + if (shape == rayCallback.m_hitTriangleShape && + rayCallback.m_hitTriangleIndex < shapeInfo->m_polygonIndexArray.size()) + { + result.m_meshObject = shapeInfo->m_meshObject; + result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex); + + // Bullet returns the normal from "outside". + // If the user requests the real normal, compute it now + if (filterCallback.m_faceNormal) + { + // mesh shapes are shared and stored in the shapeInfo + btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); + if (triangleShape) + { + // this code is copied from Bullet + btVector3 triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface(); + + meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + 0); + + unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride); + const btVector3& meshScaling = shape->getLocalScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + meshInterface->unLockReadOnlyVertexBase(0); + btVector3 triangleNormal; + triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal; + } + } + } + } + } if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { rayCallback.m_hitNormalWorld.normalize(); @@ -771,14 +925,14 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IPhysicsController* i { rayCallback.m_hitNormalWorld.setValue(1,0,0); } - normalX = rayCallback.m_hitNormalWorld.getX(); - normalY = rayCallback.m_hitNormalWorld.getY(); - normalZ = rayCallback.m_hitNormalWorld.getZ(); - + result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX(); + result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY(); + result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ(); + filterCallback.reportHit(&result); } - return nearestHit; + return result.m_controller; } @@ -833,6 +987,12 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() if (NULL != m_filterCallback) delete m_filterCallback; + + if (NULL != m_collisionConfiguration) + delete m_collisionConfiguration; + + if (NULL != m_broadphase) + delete m_broadphase; } @@ -845,7 +1005,7 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float { //param = 1..12, min0,max0,min1,max1...min6,max6 btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; - genCons->SetLimit(param,value0,value1); + genCons->setLimit(param,value0,value1); break; }; default: @@ -1191,10 +1351,11 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl btTransform globalFrameA = rb0->getCenterOfMassTransform() * frameInA; frameInB = inv * globalFrameA; - + bool useReferenceFrameA = true; + genericConstraint = new btGeneric6DofConstraint( *rb0,*rb1, - frameInA,frameInB); + frameInA,frameInB,useReferenceFrameA); } else @@ -1215,9 +1376,10 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl ///frameInB in worldspace frameInB = rb0->getCenterOfMassTransform() * frameInA; + bool useReferenceFrameA = true; genericConstraint = new btGeneric6DofConstraint( *rb0,s_fixedObject2, - frameInA,frameInB); + frameInA,frameInB,useReferenceFrameA); } if (genericConstraint) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 825a5e525f2..3569cf25b68 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -56,6 +56,10 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment protected: btIDebugDraw* m_debugDrawer; + + class btDefaultCollisionConfiguration* m_collisionConfiguration; + class btBroadphaseInterface* m_broadphase; + //solver iterations int m_numIterations; @@ -157,8 +161,7 @@ protected: btTypedConstraint* getConstraintById(int constraintId); - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //Methods for gamelogic collision/physics callbacks @@ -230,13 +233,13 @@ protected: std::vector m_wrapperVehicles; - //use explicit btDiscreteDynamicsWorld* so that we have access to + //use explicit btSoftRigidDynamicsWorld/btDiscreteDynamicsWorld* so that we have access to //btDiscreteDynamicsWorld::addRigidBody(body,filter,group) //so that we can set the body collision filter/group at the time of creation //and not afterwards (breaks the collision system for radar/near sensor) //Ideally we would like to have access to this function from the btDynamicsWorld interface //class btDynamicsWorld* m_dynamicsWorld; - class btDiscreteDynamicsWorld* m_dynamicsWorld; + class btSoftRigidDynamicsWorld* m_dynamicsWorld; class btConstraintSolver* m_solver; diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile index 49259d0a67c..d5570e75833 100644 --- a/source/gameengine/Physics/Bullet/Makefile +++ b/source/gameengine/Physics/Bullet/Makefile @@ -37,5 +37,10 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_BULLET2)/include CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include +CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I../../Physics/common CPPFLAGS += -I../../Physics/Dummy +CPPFLAGS += -I../../Rasterizer + diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index f512d44c9f2..d78958b746c 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -109,8 +109,7 @@ void DummyPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ) +PHY_IPhysicsController* DummyPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { //collision detection / raytesting return NULL; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index b5a61f72e4a..975be84f2a7 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -69,8 +69,7 @@ public: return 0; } - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 65018d2523e..80e4dc4044e 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -26,6 +26,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ +#include // memset #include "SumoPhysicsEnvironment.h" #include "PHY_IMotionState.h" #include "SumoPhysicsController.h" @@ -125,37 +126,35 @@ void SumoPhysicsEnvironment::removeConstraint(int constraintid) } } -PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IPhysicsController* ignoreClientCtrl, +PHY_IPhysicsController* SumoPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, - float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ, - float& normalX,float& normalY,float& normalZ) + float toX,float toY,float toZ) { - SumoPhysicsController* ignoreCtr = static_cast (ignoreClientCtrl); + SumoPhysicsController* ignoreCtr = static_cast (filterCallback.m_ignoreController); //collision detection / raytesting MT_Point3 hit, normal; - PHY_IPhysicsController *ret = 0; + 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) { - ret = (PHY_IPhysicsController *) smOb->getPhysicsClientObject(); + 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); } - hitX = hit[0]; - hitY = hit[1]; - hitZ = hit[2]; - - normalX = normal[0]; - normalY = normal[1]; - normalZ = normal[2]; - - return ret; + return result.m_controller; } //gamelogic callbacks void SumoPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index 8b9fb463034..100adf969d5 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -75,8 +75,7 @@ public: return 0; } - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient,float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ); + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback,float fromX,float fromY,float fromZ, float toX,float toY,float toZ); //gamelogic callbacks diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 5b275066665..98496fb7f9e 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -33,6 +33,50 @@ #include #include "PHY_DynamicTypes.h" class PHY_IVehicle; +class RAS_MeshObject; +class PHY_IPhysicsController; + +/** + * pass back information from rayTest + */ +struct PHY_RayCastResult +{ + PHY_IPhysicsController* m_controller; + PHY__Vector3 m_hitPoint; + PHY__Vector3 m_hitNormal; + const RAS_MeshObject* m_meshObject; // !=NULL for mesh object (only for Bullet controllers) + int m_polygon; // index of the polygon hit by the ray, + // only if m_meshObject != NULL +}; + +/** + * This class replaces the ignoreController parameter of rayTest function. + * It allows more sophisticated filtering on the physics controller before computing the ray intersection to save CPU. + * It is only used to its full extend by the Ccd physics environement (Bullet). + */ +class PHY_IRayCastFilterCallback +{ +public: + PHY_IPhysicsController* m_ignoreController; + bool m_faceNormal; + + virtual ~PHY_IRayCastFilterCallback() + { + } + + virtual bool needBroadphaseRayCast(PHY_IPhysicsController* controller) + { + return true; + } + + virtual void reportHit(PHY_RayCastResult* result) = 0; + + PHY_IRayCastFilterCallback(PHY_IPhysicsController* ignoreController, bool faceNormal=false) + :m_ignoreController(ignoreController), + m_faceNormal(faceNormal) + { + } +}; /** * Physics Environment takes care of stepping the simulation and is a container for physics entities (rigidbodies,constraints, materials etc.) @@ -94,8 +138,7 @@ class PHY_IPhysicsEnvironment //complex constraint for vehicles virtual PHY_IVehicle* getVehicleConstraint(int constraintId) =0; - virtual PHY_IPhysicsController* rayTest(PHY_IPhysicsController* ignoreClient, float fromX,float fromY,float fromZ, float toX,float toY,float toZ, - float& hitX,float& hitY,float& hitZ,float& normalX,float& normalY,float& normalZ)=0; + virtual PHY_IPhysicsController* rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ)=0; //Methods for gamelogic collision/physics callbacks diff --git a/source/gameengine/PyDoc/GameKeys.py b/source/gameengine/PyDoc/GameKeys.py index 268fb9cc172..1a0a737718e 100644 --- a/source/gameengine/PyDoc/GameKeys.py +++ b/source/gameengine/PyDoc/GameKeys.py @@ -164,3 +164,12 @@ Example:: # Activate Right! """ + +def EventToString(event): + """ + Return the string name of a key event. Will raise a ValueError error if its invalid. + + @type event: int + @param event: key event from GameKeys or the keyboard sensor. + @rtype: string + """ diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index b65bc0f3ce8..af3d2810553 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -220,6 +220,13 @@ def setPhysicsTicRate(ticrate): @param ticrate: The new update frequency (in Hz). @type ticrate: float """ +def getAverageFrameRate(): + """ + Gets the estimated average framerate + + @return: The estimed average framerate in frames per second + @rtype: float + """ def expandPath(path): """ @@ -245,4 +252,4 @@ def getBlendFileList(path = "//"): @type path: string @return: A list of filenames, with no directory prefix @rtype: list - """ \ No newline at end of file + """ diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index a5ba5b1d634..ff9b4ffc95b 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -30,11 +30,11 @@ class KX_GameObject: Delete this object, can be used inpace of the EndObject Actuator. The actual removal of the object from the scene is delayed. """ - def getVisible(visible): + def getVisible(): """ Gets the game object's visible flag. - @type visible: boolean + @rtype: boolean """ def setVisible(visible): """ @@ -49,16 +49,25 @@ class KX_GameObject: @rtype: int @return: the objects state. """ - def setState(): + def setState(state): """ - Sets the game object's visible flag. + Sets the game object's state flag. The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29) - @type visible: boolean + @type state: integer """ def setPosition(pos): """ - Sets the game object's position. + Sets the game object's position. + Global coordinates for root object, local for child objects. + + + @type pos: [x, y, z] + @param pos: the new position, in local coordinates. + """ + def setWorldPosition(pos): + """ + Sets the game object's position in world coordinates regardless if the object is root or child. @type pos: [x, y, z] @param pos: the new position, in world coordinates. @@ -135,6 +144,26 @@ class KX_GameObject: @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - True: you get the "local" velocity ie: relative to object orientation. """ + def getAngularVelocity(local = 0): + """ + Gets the game object's angular velocity. + + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + @rtype: list [vx, vy, vz] + @return: the object's angular velocity. + """ + def setAngularVelocity(velocity, local = 0): + """ + Sets the game object's angular velocity. + + @type velocity: 3d vector. + @param velocity: angular velocity vector. + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + """ def getVelocity(point): """ Gets the game object's velocity at the specified point. @@ -280,11 +309,13 @@ class KX_GameObject: @rtype: L{KX_GameObject} @return: the first object hit or None if no object or object does not match prop """ - def rayCast(to,from,dist,prop): + def rayCast(objto,objfrom,dist,prop,face,xray,poly): """ Look from a point/object to another point/object and find first object hit within dist that matches prop. - Returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. - Ex: + if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. + if poly is 1, returns a 4-tuple with in addition a L{KX_PolyProxy} as 4th element. + + Ex:: # shoot along the axis gun-gunAim (gunAim should be collision-free) ob,point,normal = gun.rayCast(gunAim,None,50) if ob: @@ -292,21 +323,42 @@ class KX_GameObject: Notes: The ray ignores the object on which the method is called. - If is casted from/to object center or explicit [x,y,z] points. - The ray does not have X-Ray capability: the first object hit (other than self object) stops the ray - If a property was specified and the first object hit does not have that property, there is no hit - The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. + It is casted from/to object center or explicit [x,y,z] points. + + The face paremeter determines the orientation of the normal:: + 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside) + 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect) + + The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray. + The prop and xray parameters interact as follow:: + prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray. + prop off, xray on : idem. + prop on, xray off: return closest hit if it matches prop, no hit otherwise. + prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray. + The L{KX_PolyProxy} 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray. + If there is no hit or the hit object is not a static mesh, None is returned as 4th element. + + The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. - @param to: [x,y,z] or object to which the ray is casted - @type to: L{KX_GameObject} or 3-tuple - @param from: [x,y,z] or object from which the ray is casted; None or omitted => use self object center - @type from: L{KX_GameObject} or 3-tuple or None + @param objto: [x,y,z] or object to which the ray is casted + @type objto: L{KX_GameObject} or 3-tuple + @param objfrom: [x,y,z] or object from which the ray is casted; None or omitted => use self object center + @type objfrom: L{KX_GameObject} or 3-tuple or None @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to @type dist: float @param prop: property name that object must have; can be omitted => detect any object @type prop: string - @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) - @return: (object,hitpoint,hitnormal) or (None,None,None) + @param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin + @type face: int + @param xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object + @type xray: int + @param poly: polygon option: 1=>return value is a 4-tuple and the 4th element is a L{KX_PolyProxy} + @type poly: int + @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) + or 4-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz), L{KX_PolyProxy}) + @return: (object,hitpoint,hitnormal) or (object,hitpoint,hitnormal,polygon) + If no hit, returns (None,None,None) or (None,None,None,None) + If the object hit is not a static mesh, polygon is None """ diff --git a/source/gameengine/PyDoc/KX_MeshProxy.py b/source/gameengine/PyDoc/KX_MeshProxy.py index e43fa3598f0..03bc36b6ac1 100644 --- a/source/gameengine/PyDoc/KX_MeshProxy.py +++ b/source/gameengine/PyDoc/KX_MeshProxy.py @@ -95,6 +95,21 @@ class KX_MeshProxy: @rtype: L{KX_VertexProxy} @return: a vertex object. """ + def getNumPolygons(): + """ + Returns the number of polygon in the mesh. + + @rtype: integer + """ + def getPolygon(index): + """ + Gets the specified polygon from the mesh. + + @type index: integer + @param index: polygon number + @rtype: L{KX_PolyProxy} + @return: a polygon object. + """ def reinstancePhysicsMesh(): """ Updates the physics system with the changed mesh. diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py index db577d21e6f..b7b76473292 100644 --- a/source/gameengine/PyDoc/KX_ObjectActuator.py +++ b/source/gameengine/PyDoc/KX_ObjectActuator.py @@ -111,9 +111,7 @@ class KX_ObjectActuator(SCA_IActuator): For the servo control actuator, this is the target speed. @rtype: list [vx, vy, vz, local] - @return: A four item list, containing the vector velocity, and whether - the velocity is applied in local coordinates (True) or world - coordinates (False) + @return: A four item list, containing the vector velocity, and whether the velocity is applied in local coordinates (True) or world coordinates (False) """ def setLinearVelocity(vx, vy, vz, local): """ diff --git a/source/gameengine/PyDoc/KX_PolyProxy.py b/source/gameengine/PyDoc/KX_PolyProxy.py new file mode 100644 index 00000000000..bcd42c2ac2e --- /dev/null +++ b/source/gameengine/PyDoc/KX_PolyProxy.py @@ -0,0 +1,100 @@ +# $Id$ +# Documentation for the polygon proxy class + +class KX_PolyProxy: + """ + A polygon holds the index of the vertex forming the poylgon. + + Note: + The polygon attributes are read-only, you need to retrieve the vertex proxy if you want + to change the vertex settings. + + @ivar matname: The name of polygon material, empty if no material. + @type matname: string + @ivar material: The material of the polygon + @type material: L{KX_PolygonMaterial} or KX_BlenderMaterial + @ivar texture: The texture name of the polygon. + @type texture: string + @ivar matid: The material index of the polygon, use this to retrieve vertex proxy from mesh proxy + @type matid: integer + @ivar v1: vertex index of the first vertex of the polygon, use this to retrieve vertex proxy from mesh proxy + @type v1: integer + @ivar v2: vertex index of the second vertex of the polygon, use this to retrieve vertex proxy from mesh proxy + @type v2: integer + @ivar v3: vertex index of the third vertex of the polygon, use this to retrieve vertex proxy from mesh proxy + @type v3: integer + @ivar v4: vertex index of the fourth vertex of the polygon, 0 if polygon has only 3 vertex + use this to retrieve vertex proxy from mesh proxy + @type v4: integer + @ivar visible: visible state of the polygon: 1=visible, 0=invisible + @type visible: integer + @ivar collide: collide state of the polygon: 1=receives collision, 0=collision free. + @type collide: integer + """ + + def getMaterialName(): + """ + Returns the polygon material name with MA prefix + + @rtype: string + @return: material name + """ + def getMaterial(): + """ + Returns the polygon material + + @rtype: L{KX_PolygonMaterial} or KX_BlenderMaterial + """ + def getTextureName(): + """ + Returns the polygon texture name + + @rtype: string + @return: texture name + """ + def getMaterialIndex(): + """ + Returns the material bucket index of the polygon. + This index and the ones returned by getVertexIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}. + + @rtype: integer + @return: the material index in the mesh + """ + def getNumVertex(): + """ + Returns the number of vertex of the polygon. + + @rtype: integer + @return: number of vertex, 3 or 4. + """ + def isVisible(): + """ + Returns whether the polygon is visible or not + + @rtype: integer + @return: 0=invisible, 1=visible + """ + def isCollider(): + """ + Returns whether the polygon is receives collision or not + + @rtype: integer + @return: 0=collision free, 1=receives collision + """ + def getVertexIndex(vertex): + """ + Returns the mesh vertex index of a polygon vertex + This index and the one returned by getMaterialIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}. + + @type vertex: integer + @param vertex: index of the vertex in the polygon: 0->3 + @rtype: integer + @return: mesh vertex index + """ + def getMesh(): + """ + Returns a mesh proxy + + @rtype: L{KX_MeshProxy} + @return: mesh proxy + """ diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py index 4f2bf85bff3..c3b2e947ddb 100644 --- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py @@ -64,6 +64,23 @@ class KX_SCA_AddObjectActuator(SCA_IActuator): """ Returns the initial linear velocity of added objects. + @rtype: list [vx, vy, vz] + """ + def setAngularVelocity(vx, vy, vz): + """ + Sets the initial angular velocity of added objects. + + @type vx: float + @param vx: the x component of the initial angular velocity. + @type vy: float + @param vy: the y component of the initial angular velocity. + @type vz: float + @param vz: the z component of the initial angular velocity. + """ + def getAngularVelocity(): + """ + Returns the initial angular velocity of added objects. + @rtype: list [vx, vy, vz] """ def getLastCreatedObject(): diff --git a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py index eb00a91a4ce..498f6072e23 100644 --- a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py +++ b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py @@ -59,8 +59,9 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator): def setMesh(name): """ Sets the name of the mesh that will replace the current one. + When the name is None it will unset the mesh value so no action is taken. - @type name: string + @type name: string or None """ def getMesh(): """ @@ -68,6 +69,6 @@ class KX_SCA_ReplaceMeshActuator(SCA_IActuator): Returns None if no mesh has been scheduled to be added. - @rtype: string + @rtype: string or None """ diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py index 2ecd94f38ae..948302991b7 100644 --- a/source/gameengine/PyDoc/KX_TrackToActuator.py +++ b/source/gameengine/PyDoc/KX_TrackToActuator.py @@ -21,7 +21,7 @@ class KX_TrackToActuator(SCA_IActuator): @type object: L{KX_GameObject}, string or None @param object: Either a reference to a game object or the name of the object to track. """ - def getObject(): + def getObject(name_only): """ Returns the name of the object to track. diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index f0e48b6ed43..ebb5332d98d 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -37,6 +37,10 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M # Centre the mouse Rasterizer.setMousePosition(Rasterizer.getWindowWidth()/2, Rasterizer.getWindowHeight()/2) +@group Material Types: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL +@var KX_TEXFACE_MATERIAL: Materials as defined by the texture face settings. +@var KX_BLENDER_MULTITEX_MATERIAL: Materials approximating blender materials with multitexturing. +@var KX_BLENDER_BLENDER_MATERIAL: Materials approximating blender materials with GLSL. """ @@ -84,7 +88,8 @@ def setMousePosition(x, y): """ Sets the mouse cursor position. - @type x, y: integer + @type x: integer + @type y: integer """ def setBackgroundColor(rgba): @@ -145,3 +150,35 @@ def getFocalLength(): @rtype: float """ + +def setMaterialMode(mode): + """ + Set the material mode to use for OpenGL rendering. + + @type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL + @note: Changes will only affect newly created scenes. + """ + +def getMaterialMode(mode): + """ + Get the material mode to use for OpenGL rendering. + + @rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL + """ + +def setGLSLMaterialSetting(setting, enable): + """ + Enables or disables a GLSL material setting. + + @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) + @type enable: boolean + """ + +def getGLSLMaterialSetting(setting, enable): + """ + Get the state of a GLSL material setting. + + @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) + @rtype: boolean + """ + diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py index 46b74f461a7..19df589ea7b 100644 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ b/source/gameengine/PyDoc/SCA_DelaySensor.py @@ -1,6 +1,6 @@ # $Id$ # Documentation for SCA_DelaySensor -from SCA_IActuator import * +from SCA_ISensor import * class SCA_DelaySensor(SCA_ISensor): """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py index 33f0e976284..14858505e24 100644 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ b/source/gameengine/PyDoc/SCA_ISensor.py @@ -9,7 +9,12 @@ class SCA_ISensor(SCA_ILogicBrick): def isPositive(): """ - True if this sensor brick has been activated. + True if this sensor brick is in a positive state. + """ + + def isTriggered(): + """ + True if this sensor brick has triggered the current controller. """ def getUsePosPulseMode(): diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile index e3b1f274ee5..917f70c7108 100644 --- a/source/gameengine/Rasterizer/Makefile +++ b/source/gameengine/Rasterizer/Makefile @@ -49,10 +49,6 @@ ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings endif -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif - ############### SOURCEDIR = source/gameengine/Rasterizer diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 82bdce44519..f7938bb62e6 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -26,10 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 // don't show these anoying STL warnings #pragma warning (disable:4786) @@ -39,14 +35,54 @@ #include "RAS_MaterialBucket.h" #include "STR_HashedString.h" #include "RAS_MeshObject.h" -#define KX_NUM_MATERIALBUCKETS 100 #include "RAS_IRasterizer.h" #include "RAS_IRenderTools.h" #include "RAS_BucketManager.h" +#include #include +/* sorting */ + +struct RAS_BucketManager::sortedmeshslot +{ +public: + MT_Scalar m_z; /* depth */ + RAS_MeshSlot *m_ms; /* mesh slot */ + RAS_MaterialBucket *m_bucket; /* buck mesh slot came from */ + + sortedmeshslot() {} + + void set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm) + { + // would be good to use the actual bounding box center instead + MT_Point3 pos(ms->m_OpenGLMatrix[12], ms->m_OpenGLMatrix[13], ms->m_OpenGLMatrix[14]); + + m_z = MT_dot(pnorm, pos); + m_ms = ms; + m_bucket = bucket; + } +}; + +struct RAS_BucketManager::backtofront +{ + bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) + { + return (a.m_z < b.m_z) || (a.m_z == b.m_z && a.m_ms < b.m_ms); + } +}; + +struct RAS_BucketManager::fronttoback +{ + bool operator()(const sortedmeshslot &a, const sortedmeshslot &b) + { + return (a.m_z > b.m_z) || (a.m_z == b.m_z && a.m_ms > b.m_ms); + } +}; + +/* bucket manager */ + RAS_BucketManager::RAS_BucketManager() { @@ -54,153 +90,179 @@ RAS_BucketManager::RAS_BucketManager() RAS_BucketManager::~RAS_BucketManager() { - RAS_BucketManagerClearAll(); + BucketList::iterator it; + + for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) + delete (*it); + + for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) + delete(*it); + + m_SolidBuckets.clear(); + m_AlphaBuckets.clear(); } -/** - * struct alphamesh holds a mesh, (m_ms) it's depth, (m_z) and the bucket it came from (m_bucket.) - */ -struct RAS_BucketManager::alphamesh +void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector& slots, bool alpha) { -public: - MT_Scalar m_z; - RAS_MaterialBucket::T_MeshSlotList::iterator m_ms; - RAS_MaterialBucket *m_bucket; - alphamesh(MT_Scalar z, RAS_MaterialBucket::T_MeshSlotList::iterator &ms, RAS_MaterialBucket *bucket) : - m_z(z), - m_ms(ms), - m_bucket(bucket) - {} -}; + BucketList::iterator bit; + list::iterator mit; + size_t size = 0, i = 0; -struct RAS_BucketManager::backtofront -{ - bool operator()(const alphamesh &a, const alphamesh &b) - { - return a.m_z < b.m_z; - } -}; - + /* Camera's near plane equation: pnorm.dot(point) + pval, + * but we leave out pval since it's constant anyway */ + const MT_Vector3 pnorm(cameratrans.getBasis()[2]); + + for (bit = buckets.begin(); bit != buckets.end(); ++bit) + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + if (!mit->IsCulled()) + size++; + + slots.resize(size); + + for (bit = buckets.begin(); bit != buckets.end(); ++bit) + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) + if (!mit->IsCulled()) + slots[i++].set(&*mit, *bit, pnorm); + + if(alpha) + sort(slots.begin(), slots.end(), backtofront()); + else + sort(slots.begin(), slots.end(), fronttoback()); +} void RAS_BucketManager::RenderAlphaBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - BucketList::iterator bit; - std::multiset alphameshset; - RAS_MaterialBucket::T_MeshSlotList::iterator mit; + vector slots; + vector::iterator sit; + + // Having depth masks disabled/enabled gives different artifacts in + // case no sorting is done or is done inexact. For compatibility, we + // disable it. + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); + + OrderBuckets(cameratrans, m_AlphaBuckets, slots, true); - /* Camera's near plane equation: cam_norm.dot(point) + cam_origin */ - const MT_Vector3 cam_norm(cameratrans.getBasis()[2]); - const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; - for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) - { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - { - if ((*mit).m_bVisible) - { - MT_Point3 pos((*mit).m_OpenGLMatrix[12], (*mit).m_OpenGLMatrix[13], (*mit).m_OpenGLMatrix[14]); - alphameshset.insert(alphamesh(MT_dot(cam_norm, pos) + cam_origin, mit, *bit)); - } + for(sit=slots.begin(); sit!=slots.end(); ++sit) { + rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); + + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); + } + + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); +} + +void RAS_BucketManager::RenderSolidBuckets( + const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) +{ + BucketList::iterator bit; + list::iterator mit; + + rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if (mit->IsCulled()) + continue; + + rendertools->SetClientObject(rasty, mit->m_clientObj); + + while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) + (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit); } } - // It shouldn't be strictly necessary to disable depth writes; but - // it is needed for compatibility. - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_DISABLED); + /* this code draws meshes order front-to-back instead to reduce overdraw. + * it turned out slower due to much material state switching, a more clever + * algorithm might do better. */ +#if 0 + vector slots; + vector::iterator sit; - RAS_IRasterizer::DrawMode drawingmode; - std::multiset< alphamesh, backtofront>::iterator msit = alphameshset.begin(); - for (; msit != alphameshset.end(); ++msit) - { - rendertools->SetClientObject((*(*msit).m_ms).m_clientObj); - while ((*msit).m_bucket->ActivateMaterial(cameratrans, rasty, rendertools, drawingmode)) - (*msit).m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(*msit).m_ms, drawingmode); + OrderBuckets(cameratrans, m_SolidBuckets, slots, false); + + for(sit=slots.begin(); sit!=slots.end(); ++sit) { + rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); + + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); } - - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); +#endif } void RAS_BucketManager::Renderbuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - BucketList::iterator bucket; - - rasty->EnableTextures(false); - rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); - - // beginning each frame, clear (texture/material) caching information + /* beginning each frame, clear (texture/material) caching information */ rasty->ClearCachingInfo(); - RAS_MaterialBucket::StartFrame(); - - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - (*bucket)->Render(cameratrans,rasty,rendertools); - + RenderSolidBuckets(cameratrans, rasty, rendertools); RenderAlphaBuckets(cameratrans, rasty, rendertools); - RAS_MaterialBucket::EndFrame(); + + rendertools->SetClientObject(rasty, NULL); } RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { - bucketCreated = false; BucketList::iterator it; - for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) - { + + bucketCreated = false; + + for (it = m_SolidBuckets.begin(); it != m_SolidBuckets.end(); it++) if (*(*it)->GetPolyMaterial() == *material) return *it; - } for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - { if (*(*it)->GetPolyMaterial() == *material) return *it; - } RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; + if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else - m_MaterialBuckets.push_back(bucket); + m_SolidBuckets.push_back(bucket); return bucket; } -void RAS_BucketManager::RAS_BucketManagerClearAll() -{ - BucketList::iterator it; - for (it = m_MaterialBuckets.begin(); it != m_MaterialBuckets.end(); it++) - { - delete (*it); - } - for (it = m_AlphaBuckets.begin(); it != m_AlphaBuckets.end(); it++) - { - delete(*it); - } - - m_MaterialBuckets.clear(); - m_AlphaBuckets.clear(); -} - -void RAS_BucketManager::ReleaseDisplayLists() +void RAS_BucketManager::OptimizeBuckets(MT_Scalar distance) { BucketList::iterator bit; - RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + distance = 10.0; - for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if(mit->m_DisplayList) { - mit->m_DisplayList->Release(); - mit->m_DisplayList = NULL; + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) + (*bit)->Optimize(distance); + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) + (*bit)->Optimize(distance); +} + +void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat) +{ + BucketList::iterator bit; + list::iterator mit; + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } } } } for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { - if(mit->m_DisplayList) { - mit->m_DisplayList->Release(); - mit->m_DisplayList = NULL; + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } } } } diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 08b67ed022f..74526f365a0 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -39,32 +39,33 @@ class RAS_BucketManager { - //GEN_Map m_MaterialBuckets; - typedef std::vector BucketList; - BucketList m_MaterialBuckets; + BucketList m_SolidBuckets; BucketList m_AlphaBuckets; - struct alphamesh; + struct sortedmeshslot; struct backtofront; + struct fronttoback; public: RAS_BucketManager(); virtual ~RAS_BucketManager(); - void RenderAlphaBuckets(const MT_Transform& cameratrans, - RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); void Renderbuckets(const MT_Transform & cameratrans, - RAS_IRasterizer* rasty, - class RAS_IRenderTools* rendertools); + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + void OptimizeBuckets(MT_Scalar distance); - void ReleaseDisplayLists(); + void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL); private: - void RAS_BucketManagerClearAll(); + void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector& slots, bool alpha); + void RenderSolidBuckets(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); + void RenderAlphaBuckets(const MT_Transform& cameratrans, + RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools); }; #endif //__RAS_BUCKETMANAGER diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index dcb48c1c2a0..9cb59f300f7 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -108,6 +108,13 @@ public : ) const { return m_frame_type; }; + + void + SetFrameType( + RAS_FrameType type + ) { + m_frame_type = type; + }; float BarRed( @@ -140,14 +147,6 @@ public : }; private : - - /** - * private to force use of public constructor - */ - - RAS_FrameSettings( - const RAS_FrameSettings & - ); RAS_FrameType m_frame_type; float m_bar_r; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 4ee06d96603..fb3607f89f4 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -42,11 +42,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int transp, bool alpha, bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject=NULL) : - - m_texturename(texname), + int lightlayer) + : m_texturename(texname), m_materialname(matname), m_tile(tile), m_tilexrep(tilexrep), @@ -56,7 +53,6 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_alpha(alpha), m_zsort(zsort), m_lightlayer(lightlayer), - m_bIsTriangle(bIsTriangle), m_polymatid(m_newpolymatid++), m_flag(0), m_multimode(0) @@ -72,15 +68,16 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const { if(m_flag &RAS_BLENDERMAT) { - return ( + bool test = ( this->m_multimode == lhs.m_multimode && this->m_flag == lhs.m_flag && this->m_drawingmode == lhs.m_drawingmode && this->m_transp == lhs.m_transp && - this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() ); + + return test; } else { @@ -92,8 +89,6 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && this->m_drawingmode == lhs.m_drawingmode && - this->m_bIsTriangle == lhs.m_bIsTriangle && - this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() ); @@ -123,11 +118,6 @@ bool RAS_IPolyMaterial::IsZSort() const return m_zsort; } -bool RAS_IPolyMaterial::UsesTriangles() const -{ - return m_bIsTriangle; -} - unsigned int RAS_IPolyMaterial::hash() const { return m_texturename.hash(); @@ -172,5 +162,10 @@ bool RAS_IPolyMaterial::UsesLighting(RAS_IRasterizer *rasty) const return dolights; } +bool RAS_IPolyMaterial::UsesObjectColor() const +{ + return !(m_flag & RAS_BLENDERGLSL); +} + unsigned int RAS_IPolyMaterial::m_newpolymatid = 0; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 8fc53e6b038..218dd91cb30 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -71,7 +71,6 @@ protected: bool m_alpha; bool m_zsort; int m_lightlayer; - bool m_bIsTriangle; unsigned int m_polymatid; static unsigned int m_newpolymatid; @@ -106,9 +105,7 @@ public: int transp, bool alpha, bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject); + int lightlayer); virtual ~RAS_IPolyMaterial() {}; /** @@ -129,14 +126,13 @@ public: { return false; } - virtual void ActivateMeshSlot(const class KX_MeshSlot & ms, RAS_IRasterizer* rasty) const {} + virtual void ActivateMeshSlot(const class RAS_MeshSlot & ms, RAS_IRasterizer* rasty) const {} virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; int GetLightLayer() const; bool IsAlpha() const; bool IsZSort() const; - bool UsesTriangles() const; unsigned int hash() const; int GetDrawingMode() const; const STR_String& GetMaterialName() const; @@ -145,6 +141,7 @@ public: const unsigned int GetFlag() const; virtual bool UsesLighting(RAS_IRasterizer *rasty) const; + virtual bool UsesObjectColor() const; /* * PreCalculate texture gen diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 9e03212283e..411b28fa3b7 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -168,6 +168,10 @@ public: * BeginFrame is called at the start of each frame. */ virtual bool BeginFrame(int drawingmode, double time)=0; + /** + * ClearColorBuffer clears the color buffer. + */ + virtual void ClearColorBuffer()=0; /** * ClearDepthBuffer clears the depth buffer. */ @@ -181,7 +185,8 @@ public: */ virtual void EndFrame()=0; /** - * SetRenderArea sets the render area from the 2d canvas + * SetRenderArea sets the render area from the 2d canvas. + * Returns true if only of subset of the canvas is used. */ virtual void SetRenderArea()=0; @@ -195,6 +200,7 @@ public: * @return true if stereo mode is enabled. */ virtual bool Stereo()=0; + virtual bool InterlacedStereo()=0; /** * Sets which eye buffer subsequent primitives will be rendered to. */ @@ -217,39 +223,18 @@ public: // Drawing Functions /** - * IndexPrimitives: Renders primitives. - * @param vertexarrays is an array of vertex arrays - * @param indexarrays is an array of index arrays - * @param mode determines the type of primitive stored in the vertex/index arrays - * @param useObjectColor will render the object using @param rgbacolor instead of - * vertex colors. + * IndexPrimitives: Renders primitives from mesh slot. */ - virtual void IndexPrimitives( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot)=0; - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot)=0; + virtual void IndexPrimitives(class RAS_MeshSlot& ms)=0; + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms)=0; /** * IndexPrimitives_3DText will render text into the polygons. * The text to be rendered is from @param rendertools client object's text property. */ - virtual void IndexPrimitives_3DText( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, + virtual void IndexPrimitives_3DText(class RAS_MeshSlot& ms, class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, - bool useObjectColor, - const MT_Vector4& rgbacolor)=0; + class RAS_IRenderTools* rendertools)=0; virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat)=0; /* This one should become our final version, methinks. */ @@ -269,9 +254,6 @@ public: /** */ virtual const MT_Point3& GetCameraPosition()=0; - /** - */ - virtual void LoadViewMatrix()=0; /** */ virtual void SetFog(float start, @@ -308,9 +290,6 @@ public: * @return the current drawing mode: KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED. */ virtual int GetDrawingMode()=0; - /** - */ - virtual void EnableTextures(bool enable)=0; /** * Sets face culling */ @@ -385,7 +364,9 @@ public: virtual void SetAttribNum(int num) = 0; virtual void SetTexCoord(TexCoGen coords, int unit) = 0; virtual void SetAttrib(TexCoGen coords, int unit) = 0; - virtual void GetViewMatrix(MT_Matrix4x4 &mat) const = 0; + + virtual const MT_Matrix4x4& GetViewMatrix() const = 0; + virtual const MT_Matrix4x4& GetViewInvMatrix() const = 0; virtual bool QueryLists(){return false;} virtual bool QueryArrays(){return false;} @@ -398,6 +379,7 @@ public: virtual void SetMotionBlurState(int newstate)=0; virtual void SetBlendingMode(int blendmode)=0; + virtual void SetFrontFace(bool ccw)=0; }; #endif //__RAS_IRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp index 2be9bb75ebf..555a3520bb4 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.cpp +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.cpp @@ -28,42 +28,22 @@ #include "RAS_IRenderTools.h" -#ifdef HAVE_CONFIG_H -#include -#endif - -void RAS_IRenderTools::SetViewMat(const MT_Transform& trans) -{ - trans.getValue(m_viewmat); -} - - - -void RAS_IRenderTools::SetClientObject(void* obj) +void RAS_IRenderTools::SetClientObject(RAS_IRasterizer* rasty, void *obj) { if (m_clientobject != obj) - { m_clientobject = obj; - m_modified = true; - } } - - void RAS_IRenderTools::SetAuxilaryClientInfo(void* inf) { m_auxilaryClientInfo = inf; } - - void RAS_IRenderTools::AddLight(struct RAS_LightObject* lightobject) { m_lights.push_back(lightobject); } - - void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject) { std::vector::iterator lit = @@ -71,5 +51,5 @@ void RAS_IRenderTools::RemoveLight(struct RAS_LightObject* lightobject) if (!(lit==m_lights.end())) m_lights.erase(lit); - } + diff --git a/source/gameengine/Rasterizer/RAS_IRenderTools.h b/source/gameengine/Rasterizer/RAS_IRenderTools.h index 54a663ba111..57f331e64cb 100644 --- a/source/gameengine/Rasterizer/RAS_IRenderTools.h +++ b/source/gameengine/Rasterizer/RAS_IRenderTools.h @@ -44,12 +44,9 @@ class RAS_IRenderTools { protected: - float m_viewmat[16]; void* m_clientobject; void* m_auxilaryClientInfo; - bool m_modified; - std::vector m_lights; RAS_2DFilterManager m_filtermanager; @@ -68,8 +65,7 @@ public: RAS_IRenderTools( ) : - m_clientobject(NULL), - m_modified(true) + m_clientobject(NULL) { }; @@ -131,24 +127,21 @@ public: float v1[3], float v2[3], float v3[3], - float v4[3] + float v4[3], + int glattrib )=0; virtual - void - SetViewMat( - const MT_Transform& trans - ); - - virtual - int + void ProcessLighting( - int layer + int layer, + const MT_Transform& trans )=0; virtual void SetClientObject( + RAS_IRasterizer* rasty, void* obj ); @@ -190,24 +183,6 @@ public: virtual void Render2DFilters(RAS_ICanvas* canvas)=0; - - virtual - class RAS_IPolyMaterial* - CreateBlenderPolyMaterial( - const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - void* tface - )=0; }; #endif //__RAS_IRENDERTOOLS diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 0015b6a251f..2b129f51609 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -28,10 +28,6 @@ #include "RAS_MaterialBucket.h" -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 #pragma warning (disable:4786) #include @@ -44,81 +40,425 @@ #include "RAS_MeshObject.h" #include "RAS_Deformer.h" // __NLA +/* mesh slot */ - -KX_VertexIndex::KX_VertexIndex(int size) +RAS_MeshSlot::RAS_MeshSlot() { - m_size = size; + m_clientObj = NULL; + m_pDeformer = NULL; + m_OpenGLMatrix = NULL; + m_mesh = NULL; + m_bucket = NULL; + m_bVisible = false; + m_bCulled = true; + m_bObjectColor = false; + m_RGBAcolor = MT_Vector4(0.0, 0.0, 0.0, 0.0); + m_DisplayList = NULL; + m_bDisplayList = true; + m_joinSlot = NULL; } - - -void KX_VertexIndex::SetIndex(short loc,unsigned int index) +RAS_MeshSlot::~RAS_MeshSlot() { - m_indexarray[loc]=index; -} + vector::iterator it; -bool KX_MeshSlot::Less(const KX_MeshSlot& lhs) const -{ - bool result = ((m_mesh < lhs.m_mesh ) || - ((m_mesh == lhs.m_mesh)&&(m_OpenGLMatrix < lhs.m_OpenGLMatrix))); - - return result; -} + Split(true); -KX_MeshSlot::~KX_MeshSlot() -{ - if (m_DisplayList) + while(m_joinedSlots.size()) + m_joinedSlots.front()->Split(true); + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + (*it)->m_users--; + if((*it)->m_users == 0) + delete *it; + } + + if (m_DisplayList) { m_DisplayList->Release(); + m_DisplayList = NULL; + } } +RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) +{ + vector::iterator it; + + m_clientObj = NULL; + m_pDeformer = NULL; + m_OpenGLMatrix = NULL; + m_mesh = slot.m_mesh; + m_bucket = slot.m_bucket; + m_bVisible = slot.m_bVisible; + m_bCulled = slot.m_bCulled; + m_bObjectColor = slot.m_bObjectColor; + m_RGBAcolor = slot.m_RGBAcolor; + m_DisplayList = NULL; + m_bDisplayList = slot.m_bDisplayList; + m_joinSlot = NULL; + m_currentArray = slot.m_currentArray; + m_displayArrays = slot.m_displayArrays; + m_joinedSlots = slot.m_joinedSlots; + + m_startarray = slot.m_startarray; + m_startvertex = slot.m_startvertex; + m_startindex = slot.m_startindex; + m_endarray = slot.m_endarray; + m_endvertex = slot.m_endvertex; + m_endindex = slot.m_endindex; + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + // don't copy display arrays for now because it breaks python + // access to vertices, but we'll need a solution if we want to + // join display arrays for reducing draw calls. + //*it = new RAS_DisplayArray(**it); + //(*it)->m_users = 1; + + (*it)->m_users++; + } +} + +void RAS_MeshSlot::init(RAS_MaterialBucket *bucket, int numverts) +{ + m_bucket = bucket; + + SetDisplayArray(numverts); + + m_startarray = 0; + m_startvertex = 0; + m_startindex = 0; + m_endarray = 0; + m_endvertex = 0; + m_endindex = 0; +} + +void RAS_MeshSlot::begin(RAS_MeshSlot::iterator& it) +{ + int startvertex, endvertex; + int startindex, endindex; + + it.array = (m_displayArrays.size() > 0)? m_displayArrays[m_startarray]: NULL; + + if(it.array == NULL || it.array->m_index.size() == 0 || it.array->m_vertex.size() == 0) { + it.array = NULL; + it.vertex = NULL; + it.index = NULL; + it.startvertex = 0; + it.endvertex = 0; + it.totindex = 0; + } + else { + startvertex = m_startvertex; + endvertex = (m_startarray == m_endarray)? m_endvertex: it.array->m_vertex.size(); + startindex = m_startindex; + endindex = (m_startarray == m_endarray)? m_endindex: it.array->m_index.size(); + + it.vertex = &it.array->m_vertex[0]; + it.index = &it.array->m_index[startindex]; + it.startvertex = startvertex; + it.endvertex = endvertex; + it.totindex = endindex-startindex; + it.arraynum = m_startarray; + } +} + +void RAS_MeshSlot::next(RAS_MeshSlot::iterator& it) +{ + int startvertex, endvertex; + int startindex, endindex; + + if(it.arraynum == (size_t)m_endarray) { + it.array = NULL; + it.vertex = NULL; + it.index = NULL; + it.startvertex = 0; + it.endvertex = 0; + it.totindex = 0; + } + else { + it.arraynum++; + it.array = m_displayArrays[it.arraynum]; + + startindex = 0; + endindex = (it.arraynum == (size_t)m_endarray)? m_endindex: it.array->m_index.size(); + startvertex = 0; + endvertex = (it.arraynum == (size_t)m_endarray)? m_endvertex: it.array->m_vertex.size(); + + it.vertex = &it.array->m_vertex[0]; + it.index = &it.array->m_index[startindex]; + it.startvertex = startvertex; + it.endvertex = endvertex; + it.totindex = endindex-startindex; + } +} + +bool RAS_MeshSlot::end(RAS_MeshSlot::iterator& it) +{ + return (it.array == NULL); +} + +RAS_DisplayArray *RAS_MeshSlot::CurrentDisplayArray() +{ + return m_currentArray; +} + +void RAS_MeshSlot::SetDisplayArray(int numverts) +{ + vector::iterator it; + RAS_DisplayArray *darray = NULL; + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + darray = *it; + + if(darray->m_type == numverts) { + if(darray->m_index.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_INDEX) + darray = NULL; + else if(darray->m_vertex.size()+numverts >= RAS_DisplayArray::BUCKET_MAX_VERTEX) + darray = NULL; + else + break; + } + else + darray = NULL; + } + + if(!darray) { + darray = new RAS_DisplayArray(); + darray->m_users = 1; + + if(numverts == 2) darray->m_type = RAS_DisplayArray::LINE; + else if(numverts == 3) darray->m_type = RAS_DisplayArray::TRIANGLE; + else darray->m_type = RAS_DisplayArray::QUAD; + + m_displayArrays.push_back(darray); + + if(numverts == 2) + darray->m_type = RAS_DisplayArray::LINE; + else if(numverts == 3) + darray->m_type = RAS_DisplayArray::TRIANGLE; + else if(numverts == 4) + darray->m_type = RAS_DisplayArray::QUAD; + + m_endarray = m_displayArrays.size()-1; + m_endvertex = 0; + m_endindex = 0; + } + + m_currentArray = darray; +} + +void RAS_MeshSlot::AddPolygon(int numverts) +{ + SetDisplayArray(numverts); +} + +int RAS_MeshSlot::AddVertex(const RAS_TexVert& tv) +{ + RAS_DisplayArray *darray; + int offset; + + darray = m_currentArray; + darray->m_vertex.push_back(tv); + offset = darray->m_vertex.size()-1; + + if(darray == m_displayArrays[m_endarray]) + m_endvertex++; + + return offset; +} + +void RAS_MeshSlot::AddPolygonVertex(int offset) +{ + RAS_DisplayArray *darray; + + darray = m_currentArray; + darray->m_index.push_back(offset); + + if(darray == m_displayArrays[m_endarray]) + m_endindex++; +} + +bool RAS_MeshSlot::Equals(RAS_MeshSlot *target) +{ + if(!m_OpenGLMatrix || !target->m_OpenGLMatrix) + return false; + if(m_pDeformer || target->m_pDeformer) + return false; + if(m_bVisible != target->m_bVisible) + return false; + if(m_bObjectColor != target->m_bObjectColor) + return false; + if(m_bObjectColor && !(m_RGBAcolor == target->m_RGBAcolor)) + return false; + + return true; +} + +bool RAS_MeshSlot::Join(RAS_MeshSlot *target, MT_Scalar distance) +{ + vector::iterator it; + iterator mit; + size_t i; + + // verify if we can join + if(m_joinSlot || m_joinedSlots.size() || target->m_joinSlot) + return false; + + if(!Equals(target)) + return false; + + MT_Vector3 co(&m_OpenGLMatrix[12]); + MT_Vector3 targetco(&target->m_OpenGLMatrix[12]); + + if((co - targetco).length() > distance) + return false; + + MT_Matrix4x4 mat(m_OpenGLMatrix); + MT_Matrix4x4 targetmat(target->m_OpenGLMatrix); + targetmat.invert(); + + MT_Matrix4x4 transform = targetmat*mat; + + // m_mesh, clientobj + m_joinSlot = target; + m_joinInvTransform = transform; + m_joinInvTransform.invert(); + target->m_joinedSlots.push_back(this); + + MT_Matrix4x4 ntransform = m_joinInvTransform.transposed(); + ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; + + for(begin(mit); !end(mit); next(mit)) + for(i=mit.startvertex; im_displayArrays.push_back(*it); + target->m_endarray++; + target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); + target->m_endindex = target->m_displayArrays.back()->m_index.size(); + } + + if (m_DisplayList) { + m_DisplayList->Release(); + m_DisplayList = NULL; + } + if (target->m_DisplayList) { + target->m_DisplayList->Release(); + target->m_DisplayList = NULL; + } + + return true; +#if 0 + return false; +#endif +} + +bool RAS_MeshSlot::Split(bool force) +{ + list::iterator jit; + RAS_MeshSlot *target = m_joinSlot; + vector::iterator it, jt; + iterator mit; + size_t i, found0 = 0, found1 = 0; + + if(target && (force || !Equals(target))) { + m_joinSlot = NULL; + + for(jit=target->m_joinedSlots.begin(); jit!=target->m_joinedSlots.end(); jit++) { + if(*jit == this) { + target->m_joinedSlots.erase(jit); + found0 = 1; + break; + } + } + + if(!found0) + abort(); + + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + found1 = 0; + for(jt=target->m_displayArrays.begin(); jt!=target->m_displayArrays.end(); jt++) { + if(*jt == *it) { + target->m_displayArrays.erase(jt); + target->m_endarray--; + found1 = 1; + break; + } + } + + if(!found1) + abort(); + } + + if(target->m_displayArrays.size()) { + target->m_endvertex = target->m_displayArrays.back()->m_vertex.size(); + target->m_endindex = target->m_displayArrays.back()->m_index.size(); + } + else { + target->m_endvertex = 0; + target->m_endindex = 0; + } + + MT_Matrix4x4 ntransform = m_joinInvTransform.inverse().transposed(); + ntransform[0][3]= ntransform[1][3]= ntransform[2][3]= 0.0f; + + for(begin(mit); !end(mit); next(mit)) + for(i=mit.startvertex; im_DisplayList) { + target->m_DisplayList->Release(); + target->m_DisplayList = NULL; + } + + return true; + } + + return false; +} + +bool RAS_MeshSlot::IsCulled() +{ + list::iterator it; + + if(m_joinSlot) + return true; + if(!m_bCulled) + return false; + + for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++) + if(!(*it)->m_bCulled) + return false; + + return true; +} + +/* material bucket sorting */ + +struct RAS_MaterialBucket::less +{ + bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const + { + return *x->GetPolyMaterial() < *y->GetPolyMaterial(); + } +}; + +/* material bucket */ RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) - :m_bModified(true) { m_material = mat; } - +RAS_MaterialBucket::~RAS_MaterialBucket() +{ +} RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const { return m_material; } - - -void RAS_MaterialBucket::SetMeshSlot(KX_MeshSlot& ms) -{ - m_meshSlots.insert(ms); -} - - - -void RAS_MaterialBucket::RemoveMeshSlot(KX_MeshSlot& ms) -{ - T_MeshSlotList::iterator it = m_meshSlots.find(ms); - - if (!(it == m_meshSlots.end())) - m_meshSlots.erase(it); - -} - - - -void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms, - bool visible, - bool color, - const MT_Vector4& rgbavec) -{ - T_MeshSlotList::iterator it = m_meshSlots.find(ms); - - assert (!(it == m_meshSlots.end())); - (*it).m_bVisible = visible; - (*it).m_bObjectColor = color; - (*it).m_RGBAcolor= rgbavec; -} - bool RAS_MaterialBucket::IsAlpha() const { return (m_material->IsAlpha()); @@ -129,162 +469,129 @@ bool RAS_MaterialBucket::IsZSort() const return (m_material->IsZSort()); } - - -void RAS_MaterialBucket::StartFrame() +RAS_MeshSlot* RAS_MaterialBucket::AddMesh(int numverts) { + RAS_MeshSlot *ms; + + m_meshSlots.push_back(RAS_MeshSlot()); + + ms = &m_meshSlots.back(); + ms->init(this, numverts); + + return ms; } - - -void RAS_MaterialBucket::EndFrame() +RAS_MeshSlot* RAS_MaterialBucket::CopyMesh(RAS_MeshSlot *ms) { + m_meshSlots.push_back(RAS_MeshSlot(*ms)); + + return &m_meshSlots.back(); } -unsigned int RAS_MaterialBucket::NumMeshSlots() +void RAS_MaterialBucket::RemoveMesh(RAS_MeshSlot* ms) { - return m_meshSlots.size(); + list::iterator it; + + for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) { + if(&*it == ms) { + m_meshSlots.erase(it); + return; + } + } } -RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msBegin() +list::iterator RAS_MaterialBucket::msBegin() { return m_meshSlots.begin(); } -RAS_MaterialBucket::T_MeshSlotList::iterator RAS_MaterialBucket::msEnd() +list::iterator RAS_MaterialBucket::msEnd() { return m_meshSlots.end(); } bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode &drawmode) + RAS_IRenderTools *rendertools) { - rendertools->SetViewMat(cameratrans); - if (!rasty->SetMaterial(*m_material)) return false; if (m_material->UsesLighting(rasty)) - rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER/*m_material->GetLightLayer()*/); + rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); else - rendertools->ProcessLighting(-1); - - if(rasty->GetDrawingMode() < RAS_IRasterizer::KX_SOLID) - drawmode = RAS_IRasterizer::KX_MODE_LINES; - else if(m_material->UsesTriangles()) - drawmode = RAS_IRasterizer::KX_MODE_TRIANGLES; - else - drawmode = RAS_IRasterizer::KX_MODE_QUADS; + rendertools->ProcessLighting(-1, cameratrans); return true; } void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode) + RAS_IRenderTools* rendertools, RAS_MeshSlot &ms) { - if (!ms.m_bVisible) - return; - m_material->ActivateMeshSlot(ms, rasty); - /* __NLA Do the deformation */ if (ms.m_pDeformer) { ms.m_pDeformer->Apply(m_material); // KX_ReInstanceShapeFromMesh(ms.m_mesh); // Recompute the physics mesh. (Can't call KX_* from RAS_) } - /* End __NLA */ - if (rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - ms.m_mesh->SortPolygons(cameratrans*MT_Transform(ms.m_OpenGLMatrix)); + if(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) + ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix)); rendertools->PushMatrix(); rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); if(rasty->QueryLists()) - { if(ms.m_DisplayList) ms.m_DisplayList->SetModified(ms.m_mesh->MeshModified()); - } // verify if we can use display list, not for deformed object, and // also don't create a new display list when drawing shadow buffers, - // then it won't have texture coordinates for actual drawing - KX_ListSlot **displaylist; + // then it won't have texture coordinates for actual drawing. also + // for zsort we can't make a display list, since the polygon order + // changes all the time. if(ms.m_pDeformer) - displaylist = 0; + ms.m_bDisplayList = false; else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) - displaylist = 0; + ms.m_bDisplayList = false; + else if (IsZSort()) + ms.m_bDisplayList = false; + else if(m_material->UsesObjectColor() && ms.m_bObjectColor) + ms.m_bDisplayList = false; else - displaylist = &ms.m_DisplayList; + ms.m_bDisplayList = true; - // Use the text-specific IndexPrimitives for text faces + // for text drawing using faces if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) - { - rasty->IndexPrimitives_3DText( - ms.m_mesh->GetVertexCache(m_material), - ms.m_mesh->GetIndexCache(m_material), - drawmode, - m_material, - rendertools, // needed for textprinting on polys - ms.m_bObjectColor, - ms.m_RGBAcolor); - } - - // for using glMultiTexCoord - else if((m_material->GetFlag() & RAS_MULTITEX)) - { - rasty->IndexPrimitivesMulti( - ms.m_mesh->GetVertexCache(m_material), - ms.m_mesh->GetIndexCache(m_material), - drawmode, - ms.m_bObjectColor, - ms.m_RGBAcolor, - displaylist); - } - - // Use the normal IndexPrimitives + rasty->IndexPrimitives_3DText(ms, m_material, rendertools); + // for multitexturing + else if((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL))) + rasty->IndexPrimitivesMulti(ms); + // use normal IndexPrimitives else - { - rasty->IndexPrimitives( - ms.m_mesh->GetVertexCache(m_material), - ms.m_mesh->GetIndexCache(m_material), - drawmode, - ms.m_bObjectColor, - ms.m_RGBAcolor, - displaylist); - } + rasty->IndexPrimitives(ms); - if(rasty->QueryLists()) { + if(rasty->QueryLists()) if(ms.m_DisplayList) ms.m_mesh->SetMeshModified(false); - } rendertools->PopMatrix(); } -void RAS_MaterialBucket::Render(const MT_Transform& cameratrans, - RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools) +void RAS_MaterialBucket::Optimize(MT_Scalar distance) { - if (m_meshSlots.begin()== m_meshSlots.end()) - return; - - //rendertools->SetViewMat(cameratrans); - - //rasty->SetMaterial(*m_material); + /* TODO: still have to check before this works correct: + * - lightlayer, frontface, text, billboard + * - make it work with physics */ - RAS_IRasterizer::DrawMode drawmode; - for (T_MeshSlotList::const_iterator it = m_meshSlots.begin(); - ! (it == m_meshSlots.end()); ++it) - { - rendertools->SetClientObject((*it).m_clientObj); - while (ActivateMaterial(cameratrans, rasty, rendertools, drawmode)) { - RenderMeshSlot(cameratrans, rasty, rendertools, *it, drawmode); - } - } - // to reset the eventual GL_CW mode - rendertools->SetClientObject(NULL); +#if 0 + list::iterator it; + list::iterator jt; + + // greed joining on all following buckets + for(it=m_meshSlots.begin(); it!=m_meshSlots.end(); it++) + for(jt=it, jt++; jt!=m_meshSlots.end(); jt++) + jt->Join(&*it, distance); +#endif } - diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 4eef889c533..475f01d549a 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -36,30 +36,15 @@ #include "MT_Transform.h" #include "RAS_IPolygonMaterial.h" #include "RAS_IRasterizer.h" -#include "RAS_Deformer.h" // __NLA +#include "RAS_Deformer.h" + #include -#include #include +#include using namespace std; -/** - * KX_VertexIndex - */ -struct KX_VertexIndex { -public: - KX_VertexIndex(int size); - void SetIndex(short loc,unsigned int index); - - // The vertex array - short m_vtxarray; - // An index into the vertex array for up to 4 verticies - unsigned short m_indexarray[4]; - short m_size; -}; +/* Display List Slot */ -/** - * KX_ListSlot. - */ class KX_ListSlot { protected: @@ -80,91 +65,149 @@ public: virtual void SetModified(bool mod)=0; }; -/** - * KX_MeshSlot. - */ -class KX_MeshSlot +class RAS_DisplayArray; +class RAS_MeshSlot; +class RAS_MeshMaterial; +class RAS_MaterialBucket; + +/* An array with data used for OpenGL drawing */ + +class RAS_DisplayArray { public: - void* m_clientObj; - RAS_Deformer* m_pDeformer; // __NLA - double* m_OpenGLMatrix; - class RAS_MeshObject* m_mesh; - mutable bool m_bVisible; // for visibility - mutable bool m_bObjectColor; - mutable MT_Vector4 m_RGBAcolor; - mutable KX_ListSlot* m_DisplayList; // for lists - KX_MeshSlot() : - m_pDeformer(NULL), - m_bVisible(true), - m_DisplayList(0) - { - } - ~KX_MeshSlot(); - bool Less(const KX_MeshSlot& lhs) const; + vector m_vertex; + vector m_index; + enum { LINE = 2, TRIANGLE = 3, QUAD = 4 } m_type; + //RAS_MeshSlot *m_origSlot; + int m_users; + + enum { BUCKET_MAX_INDEX = 65535 }; + enum { BUCKET_MAX_VERTEX = 65535 }; }; +/* Entry of a RAS_MeshObject into RAS_MaterialBucket */ -inline bool operator <( const KX_MeshSlot& rhs,const KX_MeshSlot& lhs) +class RAS_MeshSlot { - return ( rhs.Less(lhs)); -} +private: + // indices into display arrays + int m_startarray; + int m_endarray; + int m_startindex; + int m_endindex; + int m_startvertex; + int m_endvertex; + vector m_displayArrays; + + // for construction only + RAS_DisplayArray* m_currentArray; + +public: + // for rendering + RAS_MaterialBucket* m_bucket; + RAS_MeshObject* m_mesh; + void* m_clientObj; + RAS_Deformer* m_pDeformer; + double* m_OpenGLMatrix; + // visibility + bool m_bVisible; + bool m_bCulled; + // object color + bool m_bObjectColor; + MT_Vector4 m_RGBAcolor; + // display lists + KX_ListSlot* m_DisplayList; + bool m_bDisplayList; + // joined mesh slots + RAS_MeshSlot* m_joinSlot; + MT_Matrix4x4 m_joinInvTransform; + list m_joinedSlots; + + RAS_MeshSlot(); + RAS_MeshSlot(const RAS_MeshSlot& slot); + virtual ~RAS_MeshSlot(); + + void init(RAS_MaterialBucket *bucket, int numverts); + + struct iterator { + RAS_DisplayArray *array; + RAS_TexVert *vertex; + unsigned short *index; + size_t startvertex; + size_t endvertex; + size_t totindex; + size_t arraynum; + }; + + void begin(iterator& it); + void next(iterator& it); + bool end(iterator& it); + + /* used during construction */ + void SetDisplayArray(int numverts); + RAS_DisplayArray *CurrentDisplayArray(); + + void AddPolygon(int numverts); + int AddVertex(const RAS_TexVert& tv); + void AddPolygonVertex(int offset); + + /* optimization */ + bool Split(bool force=false); + bool Join(RAS_MeshSlot *target, MT_Scalar distance); + bool Equals(RAS_MeshSlot *target); + bool IsCulled(); +}; + +/* Used by RAS_MeshObject, to point to it's slots in a bucket */ + +class RAS_MeshMaterial +{ +public: + RAS_MeshSlot *m_baseslot; + class RAS_MaterialBucket *m_bucket; + + GEN_Map m_slots; +}; + +/* Contains a list of display arrays with the same material, + * and a mesh slot for each mesh that uses display arrays in + * this bucket */ -/** - * Contains a list of meshs with the same material properties. - */ class RAS_MaterialBucket { public: - typedef std::set T_MeshSlotList; - RAS_MaterialBucket(RAS_IPolyMaterial* mat); - virtual ~RAS_MaterialBucket() {} - - void Render(const MT_Transform& cameratrans, - class RAS_IRasterizer* rasty, - class RAS_IRenderTools* rendertools); - - RAS_IPolyMaterial* GetPolyMaterial() const; - bool IsAlpha() const; - bool IsZSort() const; - - static void StartFrame(); - static void EndFrame(); - - void SetMeshSlot(KX_MeshSlot& ms); - void RemoveMeshSlot(KX_MeshSlot& ms); - void MarkVisibleMeshSlot(KX_MeshSlot& ms, - bool visible, - bool color, - const MT_Vector4& rgbavec); - - void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools* rendertools, const KX_MeshSlot &ms, RAS_IRasterizer::DrawMode drawmode); - bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, - RAS_IRenderTools *rendertools, RAS_IRasterizer::DrawMode& drawmode); - - unsigned int NumMeshSlots(); - T_MeshSlotList::iterator msBegin(); - T_MeshSlotList::iterator msEnd(); - - struct less - { - bool operator()(const RAS_MaterialBucket* x, const RAS_MaterialBucket* y) const - { - return *x->GetPolyMaterial() < *y->GetPolyMaterial(); - } - }; + virtual ~RAS_MaterialBucket(); + /* Bucket Sorting */ + struct less; typedef set Set; -private: + + /* Material Properties */ + RAS_IPolyMaterial* GetPolyMaterial() const; + bool IsAlpha() const; + bool IsZSort() const; + + /* Rendering */ + bool ActivateMaterial(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools *rendertools); + void RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRasterizer* rasty, + RAS_IRenderTools* rendertools, RAS_MeshSlot &ms); - T_MeshSlotList m_meshSlots; - bool m_bModified; + /* Mesh Slot Access */ + list::iterator msBegin(); + list::iterator msEnd(); + + class RAS_MeshSlot* AddMesh(int numverts); + class RAS_MeshSlot* CopyMesh(class RAS_MeshSlot *ms); + void RemoveMesh(class RAS_MeshSlot* ms); + void Optimize(MT_Scalar distance); + +private: + list m_meshSlots; RAS_IPolyMaterial* m_material; - double* m_pOGLMatrix; }; -#endif //__KX_BUCKET +#endif //__RAS_MATERIAL_BUCKET diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index af5228e4c35..a907994bf57 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -26,10 +26,6 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include -#endif - #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "MT_MinMax.h" @@ -37,544 +33,7 @@ #include - -STR_String RAS_MeshObject::s_emptyname = ""; - - - -KX_ArrayOptimizer::~KX_ArrayOptimizer() -{ - for (vector::iterator itv = m_VertexArrayCache1.begin(); - !(itv == m_VertexArrayCache1.end());++itv) - { - delete (*itv); - } - - for (vector::iterator iti = m_IndexArrayCache1.begin(); - !(iti == m_IndexArrayCache1.end());++iti) - { - delete (*iti); - } - - m_TriangleArrayCount.clear(); - m_VertexArrayCache1.clear(); - m_IndexArrayCache1.clear(); - - -} - - - -RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) - : m_bModified(true), - m_lightlayer(lightlayer), - m_zsort(false), - m_MeshMod(true), - m_mesh(mesh), - m_class(0) -{ -} - - -bool RAS_MeshObject::MeshModified() -{ - return m_MeshMod; -} - - -RAS_MeshObject::~RAS_MeshObject() -{ - for (vector::iterator it=m_Polygons.begin();!(it==m_Polygons.end());it++) - { - delete (*it); - } - - ClearArrayData(); -} - - - -unsigned int RAS_MeshObject::GetLightLayer() -{ - return m_lightlayer; -} - - - -int RAS_MeshObject::NumMaterials() -{ - return m_materials.size(); -} - -const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) -{ - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); - - return bucket?bucket->GetPolyMaterial()->GetMaterialName():s_emptyname; -} - -RAS_MaterialBucket* RAS_MeshObject::GetMaterialBucket(unsigned int matid) -{ - if (m_materials.size() > 0 && (matid < m_materials.size())) - { - RAS_MaterialBucket::Set::const_iterator it = m_materials.begin(); - while (matid--) ++it; - return *it; - } - - return NULL; -} - - - -int RAS_MeshObject::NumPolygons() -{ - return m_Polygons.size(); -} - - - -RAS_Polygon* RAS_MeshObject::GetPolygon(int num) -{ - return m_Polygons[num]; -} - - - -RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetFirstMaterial() -{ - return m_materials.begin(); -} - - - -RAS_MaterialBucket::Set::iterator RAS_MeshObject::GetLastMaterial() -{ - return m_materials.end(); -} - - - -void RAS_MeshObject::SetName(STR_String name) -{ - m_name = name; -} - - - -const STR_String& RAS_MeshObject::GetName() -{ - return m_name; -} - - - -const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) -{ - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); - - return bucket?bucket->GetPolyMaterial()->GetTextureName():s_emptyname; -} - - - -void RAS_MeshObject::AddPolygon(RAS_Polygon* poly) -{ - m_Polygons.push_back(poly); -} - - - -void RAS_MeshObject::DebugColor(unsigned int abgr) -{ -/* - int numpolys = NumPolygons(); - for (int i=0;iVertexCount();v++) - { - RAS_TexVert* vtx = poly->GetVertex(v); - vtx->setDebugRGBA(abgr); - } - } - */ - - m_debugcolor = abgr; -} - -void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) -{ - const vecVertexArray & vertexvec = GetVertexCache(mat); - - for (vector::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) - { - KX_VertexArray::iterator vit; - for (vit=(*it)->begin(); vit != (*it)->end(); vit++) - { - vit->SetRGBA(rgba); - } - } -} - -void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); - - if (!mat->UsesTriangles()) - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); -} - - -void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat) -{ - //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; - int edgetrace = 1<<(numverts-1); - bool drawedge = (edgecode & edgetrace)!=0; - edgetrace = 1; - int prevvert = idx.m_indexarray[numverts-1]; - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - for (int v = 0; v < numverts; v++) - { - unsigned int curvert = idx.m_indexarray[v]; - if (drawedge) - { - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(prevvert); - ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(curvert); - } - prevvert = curvert; - drawedge = (edgecode & edgetrace)!=0; - edgetrace*=2; - } - //m_IndexArrayCount[idx.m_vtxarray] = indexpos; -} - -int RAS_MeshObject::FindOrAddVertex(int vtxarray, - const MT_Point3& xyz, - const MT_Point2& uv, - const MT_Point2& uv2, - const MT_Vector4& tangent, - const unsigned int rgbacolor, - const MT_Vector3& normal, - bool flat, - RAS_IPolyMaterial* mat, - int origindex) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - int numverts = ao->m_VertexArrayCache1[vtxarray]->size();//m_VertexArrayCount[vtxarray]; - RAS_TexVert newvert(xyz,uv,uv2,tangent,rgbacolor,normal, flat? TV_CALCFACENORMAL: 0,origindex); - -#define KX_FIND_SHARED_VERTICES -#ifdef KX_FIND_SHARED_VERTICES - if(!flat) { - for (std::vector::iterator it = m_xyz_index_to_vertex_index_mapping[origindex].begin(); - it != m_xyz_index_to_vertex_index_mapping[origindex].end(); - it++) - { - if ((*it).m_arrayindex1 == ao->m_index1 && - (*it).m_array == vtxarray && - *(*it).m_matid == *mat && - (*ao->m_VertexArrayCache1[vtxarray])[(*it).m_index].closeTo(&newvert) - ) - { - return (*it).m_index; - } - } - } -#endif // KX_FIND_SHARED_VERTICES - - // no vertex found, add one - ao->m_VertexArrayCache1[vtxarray]->push_back(newvert); - // printf("(%f,%f,%f) ",xyz[0],xyz[1],xyz[2]); - RAS_MatArrayIndex idx; - idx.m_arrayindex1 = ao->m_index1; - idx.m_array = vtxarray; - idx.m_index = numverts; - idx.m_matid = mat; - m_xyz_index_to_vertex_index_mapping[origindex].push_back(idx); - - return numverts; -} - -vecVertexArray& RAS_MeshObject::GetVertexCache (RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - return ao->m_VertexArrayCache1; -} - -int RAS_MeshObject::GetVertexArrayLength(RAS_IPolyMaterial* mat) -{ - int len = 0; - - const vecVertexArray & vertexvec = GetVertexCache(mat); - vector::const_iterator it = vertexvec.begin(); - - for (; it != vertexvec.end(); ++it) - { - len += (*it)->size(); - } - - return len; -} - - - -RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, - unsigned int index) -{ - RAS_TexVert* vertex = NULL; - - RAS_MaterialBucket* bucket = GetMaterialBucket(matid); - if (bucket) - { - RAS_IPolyMaterial* mat = bucket->GetPolyMaterial(); - if (mat) - { - const vecVertexArray & vertexvec = GetVertexCache(mat); - vector::const_iterator it = vertexvec.begin(); - - for (unsigned int len = 0; it != vertexvec.end(); ++it) - { - if (index < len + (*it)->size()) - { - vertex = &(*(*it))[index-len]; - break; - } - else - { - len += (*it)->size(); - } - } - } - } - - return vertex; -} - - - -const vecIndexArrays& RAS_MeshObject::GetIndexCache (RAS_IPolyMaterial* mat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); - - return ao->m_IndexArrayCache1; -} - - - -KX_ArrayOptimizer* RAS_MeshObject::GetArrayOptimizer(RAS_IPolyMaterial* polymat) -{ - KX_ArrayOptimizer** aop = m_matVertexArrayS[polymat]; - - if(aop) - return *aop; - - // didn't find array, but an array might already exist - // for a material equal to this one - for(int i=0;igetValue()); - if(*mat == *polymat) { - m_matVertexArrayS.insert(polymat, *m_matVertexArrayS.at(i)); - return *m_matVertexArrayS.at(i); - } - } - - // create new array - int numelements = m_matVertexArrayS.size(); - m_sortedMaterials.push_back(polymat); - - KX_ArrayOptimizer* ao = new KX_ArrayOptimizer(numelements); - m_matVertexArrayS.insert(polymat, ao); - - return ao; -} - - - -void RAS_MeshObject::Bucketize(double* oglmatrix, - void* clientobj, - bool useObjectColor, - const MT_Vector4& rgbavec) -{ - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_bObjectColor = useObjectColor; - ms.m_RGBAcolor = rgbavec; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; -// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); - bucket->SetMeshSlot(ms); - } - -} - - - -void RAS_MeshObject::MarkVisible(double* oglmatrix, - void* clientobj, - bool visible, - bool useObjectColor, - const MT_Vector4& rgbavec) -{ - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - ms.m_RGBAcolor = rgbavec; - ms.m_bObjectColor= useObjectColor; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; -// KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); - bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); - } -} - - -void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, - void* clientobj) -{ - KX_MeshSlot ms; - ms.m_clientObj = clientobj; - ms.m_mesh = this; - ms.m_OpenGLMatrix = oglmatrix; - - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; -// RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); - //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); - bucket->RemoveMeshSlot(ms); - } - -} - - - -/* - * RAS_MeshObject::GetVertex returns the vertex located somewhere in the vertexpool - * it is the clients responsibility to make sure the array and index are valid - */ -RAS_TexVert* RAS_MeshObject::GetVertex(short array, - unsigned int index, - RAS_IPolyMaterial* polymat) -{ - KX_ArrayOptimizer* ao = GetArrayOptimizer(polymat); - return &((*(ao->m_VertexArrayCache1)[array])[index]); -} - - - -void RAS_MeshObject::ClearArrayData() -{ - for (int i=0;im_VertexArrayCache1.size();i++) - { - if ( (ao->m_TriangleArrayCount[i] + (numverts-2)) < BUCKET_MAX_TRIANGLES) - { - if((ao->m_VertexArrayCache1[i]->size()+numverts < BUCKET_MAX_INDICES)) - { - array = i; - ao->m_TriangleArrayCount[array]+=numverts-2; - break; - } - } - } - - if (array == -1) - { - array = ao->m_VertexArrayCache1.size(); - vector* va = new vector; - ao->m_VertexArrayCache1.push_back(va); - KX_IndexArray *ia = new KX_IndexArray(); - ao->m_IndexArrayCache1.push_back(ia); - ao->m_TriangleArrayCount.push_back(numverts-2); - } - - return array; -} - - - - -//void RAS_MeshObject::Transform(const MT_Transform& trans) -//{ - //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); - -// for (int i=0;iTransform(trans); -// } -//} - - -/* -void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) -{ - for (int i=0;iRelativeTransform(vec); - } -} -*/ - - - -void RAS_MeshObject::UpdateMaterialList() -{ - m_materials.clear(); - unsigned int numpolys = m_Polygons.size(); - // for all polygons, find out which material they use, and add it to the set of materials - for (unsigned int i=0;iGetMaterial()); - } -} +/* polygon sorting */ struct RAS_MeshObject::polygonSlot { @@ -585,7 +44,7 @@ struct RAS_MeshObject::polygonSlot /* pnorm is the normal from the plane equation that the distance from is * used to sort again. */ - void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray, + void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray, int offset, int nvert, const MT_Vector3& pnorm) { MT_Vector3 center(0, 0, 0); @@ -593,7 +52,7 @@ struct RAS_MeshObject::polygonSlot for(i=0; i::iterator it; + + for(it=m_Polygons.begin(); it!=m_Polygons.end(); it++) + delete (*it); +} + +bool RAS_MeshObject::MeshModified() +{ + return m_bMeshModified; +} + +unsigned int RAS_MeshObject::GetLightLayer() +{ + return m_lightlayer; +} + + + +int RAS_MeshObject::NumMaterials() +{ + return m_materials.size(); +} + +const STR_String& RAS_MeshObject::GetMaterialName(unsigned int matid) +{ + RAS_MeshMaterial* mmat = GetMeshMaterial(matid); + + if(mmat) + return mmat->m_bucket->GetPolyMaterial()->GetMaterialName(); + + return s_emptyname; +} + +RAS_MeshMaterial* RAS_MeshObject::GetMeshMaterial(unsigned int matid) +{ + if (m_materials.size() > 0 && (matid < m_materials.size())) + { + list::iterator it = m_materials.begin(); + while (matid--) ++it; + return &*it; + } + + return NULL; +} + + + +int RAS_MeshObject::NumPolygons() +{ + return m_Polygons.size(); +} + + + +RAS_Polygon* RAS_MeshObject::GetPolygon(int num) const +{ + return m_Polygons[num]; +} + + + + + list::iterator GetFirstMaterial(); + list::iterator GetLastMaterial(); +list::iterator RAS_MeshObject::GetFirstMaterial() +{ + return m_materials.begin(); +} + + + +list::iterator RAS_MeshObject::GetLastMaterial() +{ + return m_materials.end(); +} + + + +void RAS_MeshObject::SetName(STR_String name) +{ + m_name = name; +} + + + +const STR_String& RAS_MeshObject::GetName() +{ + return m_name; +} + + + +const STR_String& RAS_MeshObject::GetTextureName(unsigned int matid) +{ + RAS_MeshMaterial* mmat = GetMeshMaterial(matid); + + if(mmat) + return mmat->m_bucket->GetPolyMaterial()->GetTextureName(); + + return s_emptyname; +} + +RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat) +{ + list::iterator mit; + + /* find a mesh material */ + for(mit = m_materials.begin(); mit != m_materials.end(); mit++) + if(mit->m_bucket->GetPolyMaterial() == mat) + return &*mit; + + return NULL; +} + +RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts) +{ + RAS_MeshMaterial *mmat; + RAS_Polygon *poly; + RAS_MeshSlot *slot; + + /* find a mesh material */ + mmat = GetMeshMaterial(bucket->GetPolyMaterial()); + + /* none found, create a new one */ + if(!mmat) { + RAS_MeshMaterial meshmat; + meshmat.m_bucket = bucket; + meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts); + m_materials.push_back(meshmat); + mmat = &m_materials.back(); + } + + /* add it to the bucket, this also adds new display arrays */ + slot = mmat->m_baseslot; + slot->AddPolygon(numverts); + + /* create a new polygon */ + RAS_DisplayArray *darray = slot->CurrentDisplayArray(); + poly = new RAS_Polygon(bucket, darray, numverts); + m_Polygons.push_back(poly); + + return poly; +} + +void RAS_MeshObject::DebugColor(unsigned int abgr) +{ + /*int numpolys = NumPolygons(); + + for (int i=0;iVertexCount();v++) + RAS_TexVert* vtx = poly->GetVertex(v)->setDebugRGBA(abgr); + } + */ + + /* m_debugcolor = abgr; */ +} + +void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) +{ + RAS_MeshMaterial *mmat = GetMeshMaterial(mat); + RAS_MeshSlot *slot = mmat->m_baseslot; + RAS_MeshSlot::iterator it; + size_t i; + + for(slot->begin(it); !slot->end(it); slot->next(it)) + for(i=it.startvertex; iGetMaterial()->GetPolyMaterial()); + slot = mmat->m_baseslot; + darray = slot->CurrentDisplayArray(); + + if(!flat) { + /* find vertices shared between faces, with the restriction + * that they exist in the same display array, and have the + * same uv coordinate etc */ + vector& sharedmap = m_sharedvertex_map[origindex]; + vector::iterator it; + + for(it = sharedmap.begin(); it != sharedmap.end(); it++) + { + if(it->m_darray != darray) + continue; + if(!it->m_darray->m_vertex[it->m_offset].closeTo(&texvert)) + continue; + + /* found one, add it and we're done */ + if(poly->IsVisible()) + slot->AddPolygonVertex(it->m_offset); + poly->SetVertexOffset(i, it->m_offset); + return; + } + } + + /* no shared vertex found, add a new one */ + offset = slot->AddVertex(texvert); + if(poly->IsVisible()) + slot->AddPolygonVertex(offset); + poly->SetVertexOffset(i, offset); + + if(!flat) { + SharedVertex shared; + shared.m_darray = darray; + shared.m_offset = offset; + m_sharedvertex_map[origindex].push_back(shared); + } +} + +int RAS_MeshObject::NumVertices(RAS_IPolyMaterial* mat) +{ + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + RAS_MeshSlot::iterator it; + size_t len = 0; + + mmat = GetMeshMaterial(mat); + slot = mmat->m_baseslot; + for(slot->begin(it); !slot->end(it); slot->next(it)) + len += it.endvertex - it.startvertex; + + return len; +} + + +RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, + unsigned int index) +{ + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + RAS_MeshSlot::iterator it; + size_t len; + + mmat = GetMeshMaterial(matid); + + if(!mmat) + return NULL; + + slot = mmat->m_baseslot; + len = 0; + for(slot->begin(it); !slot->end(it); slot->next(it)) { + if(index >= len + it.endvertex - it.startvertex) + len += it.endvertex - it.startvertex; + else + return &it.vertex[index - len]; + } + + return NULL; +} + +void RAS_MeshObject::AddMeshUser(void *clientobj) +{ + list::iterator it; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + /* always copy from the base slot, which is never removed + * since new objects can be created with the same mesh data */ + RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot); + ms->m_clientObj = clientobj; + it->m_slots.insert(clientobj, ms); + } +} + +void RAS_MeshObject::UpdateBuckets(void* clientobj, + double* oglmatrix, + bool useObjectColor, + const MT_Vector4& rgbavec, + bool visible, + bool culled) +{ + list::iterator it; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + RAS_MeshSlot **msp = it->m_slots[clientobj]; + + if(!msp) + continue; + + RAS_MeshSlot *ms = *msp; + + ms->m_mesh = this; + ms->m_OpenGLMatrix = oglmatrix; + ms->m_bObjectColor = useObjectColor; + ms->m_RGBAcolor = rgbavec; + ms->m_bVisible = visible; + ms->m_bCulled = culled || !visible; + + /* split if necessary */ + ms->Split(); + } +} + +void RAS_MeshObject::RemoveFromBuckets(void *clientobj) +{ + list::iterator it; + + for(it = m_materials.begin();it!=m_materials.end();++it) { + RAS_MeshSlot **msp = it->m_slots[clientobj]; + + if(!msp) + continue; + + RAS_MeshSlot *ms = *msp; + + it->m_bucket->RemoveMesh(ms); + it->m_slots.remove(clientobj); + } +} + +//void RAS_MeshObject::Transform(const MT_Transform& trans) +//{ + //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); + +// for (int i=0;iTransform(trans); +// } +//} + + +/* +void RAS_MeshObject::RelativeTransform(const MT_Vector3& vec) +{ + for (int i=0;iRelativeTransform(vec); + } +} +*/ + +void RAS_MeshObject::SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform) { // Limitations: sorting is quite simple, and handles many // cases wrong, partially due to polygons being sorted per @@ -645,43 +466,34 @@ void RAS_MeshObject::SortPolygons(const MT_Transform &transform) // to avoid excessive state changes while drawing. e) would // require splitting polygons. - if (!m_zsort) - return; + RAS_MeshSlot::iterator it; + size_t j; - // Extract camera Z plane... - const MT_Vector3 pnorm(transform.getBasis()[2]); - // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + for(ms.begin(it); !ms.end(it); ms.next(it)) { + unsigned int nvert = (int)it.array->m_type; + unsigned int totpoly = it.totindex/nvert; - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - if(!(*it)->IsZSort()) + if(totpoly <= 1) + continue; + if(it.array->m_type == RAS_DisplayArray::LINE) continue; - RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial(); - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + // Extract camera Z plane... + const MT_Vector3 pnorm(transform.getBasis()[2]); + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; - vecIndexArrays& indexarrays = ao->m_IndexArrayCache1; - vecVertexArray& vertexarrays = ao->m_VertexArrayCache1; - unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4; + vector slots(totpoly); - for(i=0; i slots(totpoly); + /* sort (stable_sort might be better, if flickering happens?) */ + std::sort(slots.begin(), slots.end(), backtofront()); - /* get indices and z into temporary array */ - for(j=0; jIsZSort()) - m_zsort = true; - - if (drawingmode == RAS_IRasterizer::KX_WIREFRAME) - { - for (i=0;iIsVisible()) - ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(), - poly->GetMaterial()->GetPolyMaterial()); - - } - m_zsort = false; - } - else - { - for (i=0;iIsVisible()) - SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(), - poly->GetMaterial()->GetPolyMaterial()); - } - } - m_bModified = false; - m_MeshMod = true; + m_bMeshModified = true; } } diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 99806666fa6..0d35a2f402b 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -36,6 +36,7 @@ #include #include +#include #include "RAS_Polygon.h" #include "RAS_MaterialBucket.h" @@ -44,194 +45,71 @@ #include "GEN_HashedPtr.h" struct Mesh; -/** - * This class holds an array of vertices and indicies. - */ -class KX_ArrayOptimizer -{ -public: - KX_ArrayOptimizer(int index) - : m_index1(index) - {}; - virtual ~KX_ArrayOptimizer(); - - vector m_VertexArrayCache1; - vector m_TriangleArrayCount; - vector m_IndexArrayCache1; - /** - order in which they are stored into the mesh - */ - int m_index1; -}; +/* RAS_MeshObject is a mesh used for rendering. It stores polygons, + * but the actual vertices and index arrays are stored in material + * buckets, referenced by the list of RAS_MeshMaterials. */ -/** - * This struct holds a triangle. - */ -struct RAS_TriangleIndex -{ -public: - int m_index[3]; - int m_array; - RAS_IPolyMaterial* m_matid; - bool m_collider; -}; - -/** - * This class looks horribly broken. Only m_matid is used, and - * m_matid is a (int) RAS_IPolyMaterial*. - * --> m_matid == lhs.m_matid should be *m_matid == *lhs.m_matid - */ -class RAS_MatArrayIndex -{ -public: - - int m_arrayindex1; - RAS_IPolyMaterial* m_matid; - int m_array; - int m_index; - -/* - inline bool Less(const RAS_MatArrayIndex& lhs) const { - bool result = - ( (m_matid < lhs.m_matid) || - ((m_matid == lhs.m_matid)&&(m_array < lhs.m_array)) || - ((m_matid == lhs.m_matid) && (m_array == lhs.m_array) && - (m_index < lhs.m_index)) - - ); - return result; - - } -*/ - -}; -/* -inline bool operator <( const RAS_MatArrayIndex& rhs,const RAS_MatArrayIndex& lhs) -{ - return ( rhs.Less(lhs)); -}*/ - -/** - * RAS_MeshObject stores mesh data for the renderer. - */ class RAS_MeshObject { - - // GEN_Map m_matVertexArrayS; - //vector m_vertexArrays; - virtual KX_ArrayOptimizer* GetArrayOptimizer(RAS_IPolyMaterial* polymat); - //vector m_polygons; - +private: unsigned int m_debugcolor; - bool m_bModified; int m_lightlayer; - - vector m_Polygons; + + bool m_bModified; + bool m_bMeshModified; + STR_String m_name; static STR_String s_emptyname; - bool m_zsort; - bool m_MeshMod; + vector m_Polygons; + + /* polygon sorting */ struct polygonSlot; struct backtofront; struct fronttoback; - void SchedulePoly( - const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat - ); - - void ScheduleWireframePoly( - const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat - ); - protected: - enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192}; - enum { BUCKET_MAX_TRIANGLES = 65535 }; - - GEN_Map m_matVertexArrayS; - - RAS_MaterialBucket::Set m_materials; + list m_materials; Mesh* m_mesh; + bool m_bDeformed; + public: // for now, meshes need to be in a certain layer (to avoid sorting on lights in realtime) RAS_MeshObject(Mesh* mesh, int lightlayer); virtual ~RAS_MeshObject(); - vector m_sortedMaterials; - vector > m_xyz_index_to_vertex_index_mapping; - vector m_triangle_indices; - - int m_class; - unsigned int GetLightLayer(); + bool IsDeformed() { return m_bDeformed; } + + /* materials */ int NumMaterials(); const STR_String& GetMaterialName(unsigned int matid); - RAS_MaterialBucket* GetMaterialBucket(unsigned int matid); const STR_String& GetTextureName(unsigned int matid); - virtual void AddPolygon(RAS_Polygon* poly); - void UpdateMaterialList(); - - int NumPolygons(); - RAS_Polygon* GetPolygon(int num); - - virtual void Bucketize( - double* oglmatrix, - void* clientobj, - bool useObjectColor, - const MT_Vector4& rgbavec - ); - void RemoveFromBuckets( - double* oglmatrix, - void* clientobj - ); + RAS_MeshMaterial* GetMeshMaterial(unsigned int matid); + RAS_MeshMaterial* GetMeshMaterial(RAS_IPolyMaterial *mat); - void MarkVisible( - double* oglmatrix, - void* clientobj, - bool visible, - bool useObjectColor, - const MT_Vector4& rgbavec - ); + list::iterator GetFirstMaterial(); + list::iterator GetLastMaterial(); - void DebugColor(unsigned int abgr); - void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); - - /** - * Sorts the polygons by their transformed z values. - */ - void SortPolygons(const MT_Transform &transform); + unsigned int GetLightLayer(); - void SchedulePolygons(int drawingmode); + /* name */ + void SetName(STR_String name); + const STR_String& GetName(); - void ClearArrayData(); - - RAS_MaterialBucket::Set::iterator GetFirstMaterial(); - RAS_MaterialBucket::Set::iterator GetLastMaterial(); - - virtual RAS_TexVert* GetVertex( - short array, - unsigned int index, - RAS_IPolyMaterial* polymat - ); - - virtual int FindVertexArray( - int numverts, - RAS_IPolyMaterial* polymat - ); + /* modification state */ + bool MeshModified(); + void SetMeshModified(bool v){m_bMeshModified = v;} + /* original blender mesh */ + Mesh* GetMesh() { return m_mesh; } + + /* mesh construction */ - // find (and share) or add vertices - // for some speedup, only the last 20 added vertices are searched for equality - - virtual int FindOrAddVertex( - int vtxarray, + virtual RAS_Polygon* AddPolygon(RAS_MaterialBucket *bucket, int numverts); + virtual void AddVertex(RAS_Polygon *poly, int i, const MT_Point3& xyz, const MT_Point2& uv, const MT_Point2& uv2, @@ -239,27 +117,43 @@ public: const unsigned int rgbacolor, const MT_Vector3& normal, bool flat, - RAS_IPolyMaterial* mat, - int origindex - ); + int origindex); + + void SchedulePolygons(int drawingmode); + + /* vertex and polygon acces */ + int NumVertices(RAS_IPolyMaterial* mat); + RAS_TexVert* GetVertex(unsigned int matid, unsigned int index); + + int NumPolygons(); + RAS_Polygon* GetPolygon(int num) const; - vecVertexArray& GetVertexCache (RAS_IPolyMaterial* mat); + /* buckets */ + virtual void AddMeshUser(void *clientobj); + virtual void UpdateBuckets( + void* clientobj, + double* oglmatrix, + bool useObjectColor, + const MT_Vector4& rgbavec, + bool visible, + bool culled); + + void RemoveFromBuckets(void *clientobj); + + /* colors */ + void DebugColor(unsigned int abgr); + void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); - int GetVertexArrayLength(RAS_IPolyMaterial* mat); + /* polygon sorting by Z for alpha */ + void SortPolygons(RAS_MeshSlot& ms, const MT_Transform &transform); - RAS_TexVert* GetVertex( - unsigned int matid, - unsigned int index - ); - - const vecIndexArrays& GetIndexCache (RAS_IPolyMaterial* mat); - void SetName(STR_String name); - const STR_String& GetName(); - - bool MeshModified(); - void SetMeshModified(bool v){m_MeshMod = v;} - Mesh* GetMesh() { return m_mesh; } + /* for construction to find shared vertices */ + struct SharedVertex { + RAS_DisplayArray *m_darray; + int m_offset; + }; + vector > m_sharedvertex_map; }; #endif //__RAS_MESHOBJECT diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index 2a6d64ecc73..e4403ace69f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -32,6 +32,7 @@ SET(INC ../../../../intern/moto/include ../../../../source/gameengine/Rasterizer ../../../../extern/glew/include + ../../../../source/blender/gpu ) BLENDERLIB(bf_oglrasterizer "${SRC}" "${INC}") diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile index f01978b8eb1..aee485a22be 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile @@ -41,12 +41,11 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../../kernel/gen_system +CPPFLAGS += -I../../../blender/gpu CPPFLAGS += -I../../BlenderRoutines CPPFLAGS += -I.. + ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings endif -ifeq ($(WITH_BF_GLEXT),true) - CPPFLAGS += -DWITH_GLEXT -endif diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index c2687319717..2c4b55ff964 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -9,6 +9,7 @@ #include "GL/glew.h" +#include "RAS_MaterialBucket.h" #include "RAS_TexVert.h" #include "MT_assert.h" @@ -125,20 +126,20 @@ void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) } } -RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot) +RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) { /* Keep a copy of constant lists submitted for rendering, this guards against (replicated)new...delete every frame, and we can reuse lists! - :: sorted by vertex array + :: sorted by mesh slot */ - RAS_ListSlot* localSlot = (RAS_ListSlot*)*slot; + RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList; if(!localSlot) { - RAS_Lists::iterator it = mLists.find(vertexarrays); + RAS_Lists::iterator it = mLists.find(&ms); if(it == mLists.end()) { localSlot = new RAS_ListSlot(this); - mLists.insert(std::pair(vertexarrays, localSlot)); + mLists.insert(std::pair(&ms, localSlot)); } else { localSlot = static_cast(it->second->AddRef()); } @@ -157,69 +158,45 @@ void RAS_ListRasterizer::ReleaseAlloc() mLists.clear(); } - -void RAS_ListRasterizer::IndexPrimitives( - const vecVertexArray & vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) +void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) { RAS_ListSlot* localSlot =0; - // useObjectColor(are we updating every frame?) - if(!useObjectColor && slot) { - localSlot = FindOrAdd(vertexarrays, slot); + if(ms.m_bDisplayList) { + localSlot = FindOrAdd(ms); localSlot->DrawList(); if(localSlot->End()) { // save slot here too, needed for replicas and object using same mesh // => they have the same vertexarray but different mesh slot - *slot = localSlot; + ms.m_DisplayList = localSlot; return; } } - if (mUseVertexArrays) { - RAS_VAOpenGLRasterizer::IndexPrimitives( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } else { - RAS_OpenGLRasterizer::IndexPrimitives( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } + if (mUseVertexArrays) + RAS_VAOpenGLRasterizer::IndexPrimitives(ms); + else + RAS_OpenGLRasterizer::IndexPrimitives(ms); - if(!useObjectColor && slot) { + if(ms.m_bDisplayList) { localSlot->EndList(); - *slot = localSlot; + ms.m_DisplayList = localSlot; } } -void RAS_ListRasterizer::IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) +void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) { RAS_ListSlot* localSlot =0; - // useObjectColor(are we updating every frame?) - if(!useObjectColor && slot) { - localSlot = FindOrAdd(vertexarrays, slot); + if(ms.m_bDisplayList) { + localSlot = FindOrAdd(ms); localSlot->DrawList(); if(localSlot->End()) { // save slot here too, needed for replicas and object using same mesh // => they have the same vertexarray but different mesh slot - *slot = localSlot; + ms.m_DisplayList = localSlot; return; } } @@ -227,23 +204,14 @@ void RAS_ListRasterizer::IndexPrimitivesMulti( // workaround: note how we do not use vertex arrays for making display // lists, since glVertexAttribPointerARB doesn't seem to work correct // in display lists on ATI? either a bug in the driver or in Blender .. - if (mUseVertexArrays && !localSlot) { - RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } else { - RAS_OpenGLRasterizer::IndexPrimitivesMulti( - vertexarrays, indexarrays, - mode, useObjectColor, - rgbacolor,slot - ); - } + if (mUseVertexArrays && !localSlot) + RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms); + else + RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); - if(!useObjectColor && slot) { + if(ms.m_bDisplayList) { localSlot->EndList(); - *slot = localSlot; + ms.m_DisplayList = localSlot; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index b1b19144c12..96d6d2a995d 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -4,6 +4,7 @@ #include "RAS_MaterialBucket.h" #include "RAS_VAOpenGLRasterizer.h" #include +#include class RAS_ListRasterizer; class RAS_ListSlot : public KX_ListSlot @@ -34,14 +35,14 @@ enum RAS_ListSlotFlags { LIST_REGEN =64 }; -typedef std::map RAS_Lists; +typedef std::map RAS_Lists; class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer { bool mUseVertexArrays; RAS_Lists mLists; - RAS_ListSlot* FindOrAdd(const vecVertexArray& vertexarrays, KX_ListSlot** slot); + RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms); void ReleaseAlloc(); public: @@ -49,23 +50,8 @@ public: RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays=false, bool lock=false); virtual ~RAS_ListRasterizer(); - virtual void IndexPrimitives( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ); - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ); + virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); virtual bool Init(); virtual void Exit(); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 1dcc6e70934..87a0a1d8b9e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -38,6 +38,9 @@ #include "MT_CmMatrix4x4.h" #include "RAS_IRenderTools.h" // rendering text +#include "GPU_draw.h" +#include "GPU_material.h" + /** * 32x32 bit masks for vinterlace stereo mode */ @@ -67,10 +70,12 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), - m_last_blendmode(0), + m_last_blendmode(GPU_BLEND_SOLID), + m_last_frontface(true), m_materialCachingInfo(0) { - m_viewmatrix.Identity(); + m_viewmatrix.setIdentity(); + m_viewinvmatrix.setIdentity(); for (int i = 0; i < 32; i++) { @@ -87,81 +92,9 @@ RAS_OpenGLRasterizer::~RAS_OpenGLRasterizer() { } - - -static void Myinit_gl_stuff(void) -{ - float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - float mat_shininess[] = { 35.0 }; -/* float one= 1.0; */ - int a, x, y; - GLubyte pat[32*32]; - const GLubyte *patc= pat; - - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); - - -#if defined(__FreeBSD) || defined(__linux__) - glDisable(GL_DITHER); /* op sgi/sun hardware && 12 bits */ -#endif - - /* no local viewer, looks ugly in ortho mode */ - /* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */ - - glDepthFunc(GL_LEQUAL); - /* scaling matrices */ - glEnable(GL_NORMALIZE); - - glShadeModel(GL_FLAT); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - glDisable(GL_LIGHTING); - glDisable(GL_LOGIC_OP); - glDisable(GL_STENCIL_TEST); - glDisable(GL_TEXTURE_1D); - glDisable(GL_TEXTURE_2D); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - glPixelTransferi(GL_MAP_COLOR, GL_FALSE); - glPixelTransferi(GL_RED_SCALE, 1); - glPixelTransferi(GL_RED_BIAS, 0); - glPixelTransferi(GL_GREEN_SCALE, 1); - glPixelTransferi(GL_GREEN_BIAS, 0); - glPixelTransferi(GL_BLUE_SCALE, 1); - glPixelTransferi(GL_BLUE_BIAS, 0); - glPixelTransferi(GL_ALPHA_SCALE, 1); - glPixelTransferi(GL_ALPHA_BIAS, 0); - - a = 0; - for(x=0; x<32; x++) - { - for(y=0; y<4; y++) - { - if( (x) & 1) pat[a++]= 0x88; - else pat[a++]= 0x22; - } - } - - glPolygonStipple(patc); - - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glEnable(GL_CULL_FACE); -} - - - bool RAS_OpenGLRasterizer::Init() { - - Myinit_gl_stuff(); + GPU_state_init(); m_redback = 0.4375; m_greenback = 0.4375; @@ -172,7 +105,12 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; - SetBlendingMode(0); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + m_last_blendmode = GPU_BLEND_SOLID; + + glFrontFace(GL_CCW); + m_last_frontface = true; glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -316,21 +254,10 @@ void RAS_OpenGLRasterizer::Exit() EndFrame(); } -bool RAS_OpenGLRasterizer::InterlacedStereo() const -{ - return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; -} - bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) { m_time = time; m_drawingmode = drawingmode; - - if (!InterlacedStereo() || m_curreye == RAS_STEREO_LEFTEYE) - { - m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); - m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); - } // Blender camera routine destroys the settings if (m_drawingmode < KX_SOLID) @@ -344,7 +271,12 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } - SetBlendingMode(0); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + m_last_blendmode = GPU_BLEND_SOLID; + + glFrontFace(GL_CCW); + m_last_frontface = true; glShadeModel(GL_SMOOTH); @@ -359,34 +291,28 @@ void RAS_OpenGLRasterizer::SetDrawingMode(int drawingmode) { m_drawingmode = drawingmode; - switch (m_drawingmode) - { - case KX_WIREFRAME: - { - glDisable (GL_CULL_FACE); - break; - } - default: - { - } - } + if(m_drawingmode == KX_WIREFRAME) + glDisable(GL_CULL_FACE); } - - int RAS_OpenGLRasterizer::GetDrawingMode() { return m_drawingmode; } - void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask) { glDepthMask(depthmask == KX_DEPTHMASK_DISABLED ? GL_FALSE : GL_TRUE); } +void RAS_OpenGLRasterizer::ClearColorBuffer() +{ + m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); + m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); +} + void RAS_OpenGLRasterizer::ClearDepthBuffer() { @@ -497,6 +423,10 @@ bool RAS_OpenGLRasterizer::Stereo() return true; } +bool RAS_OpenGLRasterizer::InterlacedStereo() +{ + return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; +} void RAS_OpenGLRasterizer::SetEye(const StereoEye eye) { @@ -573,294 +503,84 @@ void RAS_OpenGLRasterizer::SwapBuffers() -void RAS_OpenGLRasterizer::GetViewMatrix(MT_Matrix4x4 &mat) const +const MT_Matrix4x4& RAS_OpenGLRasterizer::GetViewMatrix() const { - float viewmat[16]; - glGetFloatv(GL_MODELVIEW_MATRIX, viewmat); - mat.setValue(viewmat); + return m_viewmatrix; } - - -void RAS_OpenGLRasterizer::IndexPrimitives(const vecVertexArray & vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ) -{ - const RAS_TexVert* vertexarray; - unsigned int numindices, vt; - - for (vt=0;vtm_type; + + if(it.array->m_type == RAS_DisplayArray::LINE) { + // line drawing, no text + glBegin(GL_LINES); + + for(i=0; igetXYZ()); + + vertex = &it.vertex[it.index[i+1]]; + glVertex3fv(vertex->getXYZ()); + } + + glEnd(); + } + else { + // triangle and quad text drawing + for(i=0; igetXYZ()[0]; + v[j][1] = vertex->getXYZ()[1]; + v[j][2] = vertex->getXYZ()[2]; + } + + // find the right opengl attribute + glattrib = -1; + if(GLEW_ARB_vertex_program) + for(unit=0; unitRenderText(polymat->GetDrawingMode(), polymat, + v[0], v[1], v[2], (numvert == 4)? v[3]: NULL, glattrib); + + ClearCachingInfo(); + } + } } - - for (vt=0;vtRenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,v4); - ClearCachingInfo(); - } - break; - } - case KX_MODE_TRIANGLES: - { - glBegin(GL_TRIANGLES); - vindex=0; - for (unsigned int i=0;iRenderText(polymat->GetDrawingMode(),polymat,v1,v2,v3,NULL); - ClearCachingInfo(); - } - glEnd(); - break; - } - default: - { - } - } //switch - } //for each vertexarray + + glDisableClientState(GL_COLOR_ARRAY); } void RAS_OpenGLRasterizer::SetTexCoordNum(int num) @@ -897,14 +617,14 @@ void RAS_OpenGLRasterizer::TexCoord(const RAS_TexVert &tv) if(GLEW_ARB_multitexture) { for(unit=0; unitm_type; - for (vt=0;vtm_type == RAS_DisplayArray::LINE) { + // line drawing + glBegin(GL_LINES); - if (!numindices) - break; - - int vindex=0; - switch (mode) - { - case KX_MODE_LINES: + for(i=0; igetXYZ()); + + vertex = &it.vertex[it.index[i+1]]; + glVertex3fv(vertex->getXYZ()); } - break; - case KX_MODE_QUADS: - { - glBegin(GL_QUADS); - vindex=0; - if (useObjectColor) - { - for (unsigned int i=0;im_type == RAS_DisplayArray::TRIANGLE) glBegin(GL_TRIANGLES); - vindex=0; - if (useObjectColor) - { - for (unsigned int i=0;igetRGBA())); + + glNormal3fv(vertex->getNormal()); + + if(multi) + TexCoord(*vertex); + else + glTexCoord2fv(vertex->getUV1()); + } + + glVertex3fv(vertex->getXYZ()); + } } - } // switch - } // for each vertexarray + + glEnd(); + } + } } void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat) @@ -1232,7 +821,7 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos, const MT_Point3 &, const MT_Quaternion &camOrientQuat) { - MT_Matrix4x4 viewMat = mat; + m_viewmatrix = mat; // correction for stereo if(m_stereomode != RAS_STEREO_NOSTEREO) @@ -1259,7 +848,7 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto MT_Transform transform; transform.setIdentity(); transform.translate(-(eyeline * m_eyeseparation / 2.0)); - viewMat *= transform; + m_viewmatrix *= transform; } break; case RAS_STEREO_RIGHTEYE: @@ -1268,20 +857,21 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto MT_Transform transform; transform.setIdentity(); transform.translate(eyeline * m_eyeseparation / 2.0); - viewMat *= transform; + m_viewmatrix *= transform; } break; } } - // convert row major matrix 'viewMat' to column major for OpenGL - MT_Scalar cammat[16]; - viewMat.getValue(cammat); - MT_CmMatrix4x4 viewCmmat = cammat; + m_viewinvmatrix = m_viewmatrix; + m_viewinvmatrix.invert(); + + // note: getValue gives back column major as needed by OpenGL + MT_Scalar glviewmat[16]; + m_viewmatrix.getValue(glviewmat); glMatrixMode(GL_MODELVIEW); - m_viewmatrix = viewCmmat; - glLoadMatrixd(&m_viewmatrix(0,0)); + glLoadMatrixd(glviewmat); m_campos = campos; } @@ -1292,20 +882,6 @@ const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition() } - -void RAS_OpenGLRasterizer::LoadViewMatrix() -{ - glLoadMatrixd(&m_viewmatrix(0,0)); -} - - - -void RAS_OpenGLRasterizer::EnableTextures(bool enable) -{ -} - - - void RAS_OpenGLRasterizer::SetCullFace(bool enable) { if (enable) @@ -1373,7 +949,10 @@ void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add) void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue) { - m_motionblur = 1; + /* don't just set m_motionblur to 1, but check if it is 0 so + * we don't reset a motion blur that is already enabled */ + if(m_motionblur == 0) + m_motionblur = 1; m_motionblurvalue = motionblurvalue; } @@ -1388,23 +967,23 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) if(blendmode == m_last_blendmode) return; - if(blendmode == 0) { + if(blendmode == GPU_BLEND_SOLID) { glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else if(blendmode == 1) { + else if(blendmode == GPU_BLEND_ADD) { glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); glDisable(GL_ALPHA_TEST); } - else if(blendmode == 2) { + else if(blendmode == GPU_BLEND_ALPHA) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0f); } - else if(blendmode == 4) { + else if(blendmode == GPU_BLEND_CLIP) { glDisable(GL_BLEND); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5f); @@ -1413,3 +992,16 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) m_last_blendmode = blendmode; } +void RAS_OpenGLRasterizer::SetFrontFace(bool ccw) +{ + if(m_last_frontface == ccw) + return; + + if(ccw) + glFrontFace(GL_CCW); + else + glFrontFace(GL_CW); + + m_last_frontface = ccw; +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 02056cce446..0717cce0ce8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -41,7 +41,7 @@ using namespace std; #include "RAS_MaterialBucket.h" #include "RAS_ICanvas.h" -#define RAS_MAX_TEXCO 3 // match in BL_Material +#define RAS_MAX_TEXCO 8 // match in BL_Material #define RAS_MAX_ATTRIB 16 // match in BL_BlenderShader struct OglDebugLine @@ -77,7 +77,8 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_ambb; double m_time; - MT_CmMatrix4x4 m_viewmatrix; + MT_Matrix4x4 m_viewmatrix; + MT_Matrix4x4 m_viewinvmatrix; MT_Point3 m_campos; StereoMode m_stereomode; @@ -87,7 +88,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_focallength; bool m_setfocallength; int m_noOfScanlines; - bool InterlacedStereo() const; //motion blur int m_motionblur; @@ -100,6 +100,7 @@ protected: int m_texco_num; int m_attrib_num; int m_last_blendmode; + bool m_last_frontface; /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; @@ -129,6 +130,7 @@ public: virtual bool Init(); virtual void Exit(); virtual bool BeginFrame(int drawingmode, double time); + virtual void ClearColorBuffer(); virtual void ClearDepthBuffer(); virtual void ClearCachingInfo(void); virtual void EndFrame(); @@ -136,6 +138,7 @@ public: virtual void SetStereoMode(const StereoMode stereomode); virtual bool Stereo(); + virtual bool InterlacedStereo(); virtual void SetEye(const StereoEye eye); virtual StereoEye GetEye(); virtual void SetEyeSeparation(const float eyeseparation); @@ -144,33 +147,15 @@ public: virtual float GetFocalLength(); virtual void SwapBuffers(); - virtual void IndexPrimitives( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot - ); + virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); virtual void IndexPrimitives_3DText( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, + class RAS_MeshSlot& ms, class RAS_IPolyMaterial* polymat, - class RAS_IRenderTools* rendertools, - bool useObjectColor, - const MT_Vector4& rgbacolor - ); - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot); + class RAS_IRenderTools* rendertools); + void IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi); virtual void SetProjectionMatrix(MT_CmMatrix4x4 & mat); virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat); @@ -182,7 +167,6 @@ public: ); virtual const MT_Point3& GetCameraPosition(); - virtual void LoadViewMatrix(); virtual void SetFog( float start, @@ -214,7 +198,6 @@ public: virtual void SetDrawingMode(int drawingmode); virtual int GetDrawingMode(); - virtual void EnableTextures(bool enable); virtual void SetCullFace(bool enable); virtual void SetLines(bool enable); @@ -270,13 +253,10 @@ public: virtual void SetTexCoord(TexCoGen coords, int unit); virtual void SetAttrib(TexCoGen coords, int unit); - void TexCoord(const RAS_TexVert &tv); - virtual void GetViewMatrix(MT_Matrix4x4 &mat) const; + void TexCoord(const RAS_TexVert &tv); - void Tangent(const RAS_TexVert& v1, - const RAS_TexVert& v2, - const RAS_TexVert& v3, - const MT_Vector3 &no); + const MT_Matrix4x4& GetViewMatrix() const; + const MT_Matrix4x4& GetViewInvMatrix() const; virtual void EnableMotionBlur(float motionblurvalue); virtual void DisableMotionBlur(); @@ -293,6 +273,7 @@ public: }; virtual void SetBlendingMode(int blendmode); + virtual void SetFrontFace(bool ccw); }; #endif //__RAS_OPENGLRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp index c78a97ad7be..2cb3b52adfb 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp @@ -33,6 +33,7 @@ #include #include "GL/glew.h" +#include "GPU_extensions.h" #include "STR_String.h" #include "RAS_TexVert.h" @@ -77,16 +78,16 @@ void RAS_VAOpenGLRasterizer::SetDrawingMode(int drawingmode) { case KX_BOUNDINGBOX: case KX_WIREFRAME: - glDisableClientState(GL_COLOR_ARRAY); - glDisable(GL_CULL_FACE); + //glDisableClientState(GL_COLOR_ARRAY); + //glDisable(GL_CULL_FACE); break; case KX_SOLID: - glDisableClientState(GL_COLOR_ARRAY); + //glDisableClientState(GL_COLOR_ARRAY); break; case KX_TEXTURED: case KX_SHADED: case KX_SHADOW: - glEnableClientState(GL_COLOR_ARRAY); + //glEnableClientState(GL_COLOR_ARRAY); default: break; } @@ -98,141 +99,121 @@ void RAS_VAOpenGLRasterizer::Exit() glEnableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - EnableTextures(false); RAS_OpenGLRasterizer::Exit(); } -void RAS_VAOpenGLRasterizer::IndexPrimitives( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) +void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) { - static const GLsizei vtxstride = sizeof(RAS_TexVert); + static const GLsizei stride = sizeof(RAS_TexVert); + bool wireframe = m_drawingmode <= KX_WIREFRAME; + RAS_MeshSlot::iterator it; GLenum drawmode; - if(mode == KX_MODE_TRIANGLES) - drawmode = GL_TRIANGLES; - else if(mode == KX_MODE_QUADS) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - const RAS_TexVert* vertexarray; - unsigned int numindices, vt; - - if (drawmode != GL_LINES) - { - if (useObjectColor) - { - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); - } else - { - glColor4d(0,0,0,1.0); - glEnableClientState(GL_COLOR_ARRAY); - } - } - else - { - glColor3d(0,0,0); - } - - EnableTextures(false); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + if(!wireframe) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); // use glDrawElements to draw each vertexarray - for (vt=0;vtgetLocalXYZ()); - glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); - glTexCoordPointer(2,GL_FLOAT,vtxstride,vertexarray->getUV1()); - if(glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); - //if(m_Lock) - // local->Begin(vertexarrays[vt]->size()); + // drawing mode + if(it.array->m_type == RAS_DisplayArray::TRIANGLE) + drawmode = GL_TRIANGLES; + else if(it.array->m_type == RAS_DisplayArray::QUAD) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; - // here the actual drawing takes places - glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0])); + // colors + if (drawmode != GL_LINES && !wireframe) { + if (ms.m_bObjectColor) { + const MT_Vector4& rgba = ms.m_RGBAcolor; - //if(m_Lock) - // local->End(); - } - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); -} - -void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot) -{ - static const GLsizei vtxstride = sizeof(RAS_TexVert); - - GLenum drawmode; - if(mode == KX_MODE_TRIANGLES) - drawmode = GL_TRIANGLES; - else if(mode == KX_MODE_QUADS) - drawmode = GL_QUADS; - else - drawmode = GL_LINES; - - const RAS_TexVert* vertexarray; - unsigned int numindices, vt; - - if (drawmode != GL_LINES) - { - if (useObjectColor) - { - glDisableClientState(GL_COLOR_ARRAY); - glColor4d(rgbacolor[0], rgbacolor[1], rgbacolor[2], rgbacolor[3]); + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + } + else { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glEnableClientState(GL_COLOR_ARRAY); + } } else - { - glColor4d(0,0,0,1.0); - glEnableClientState(GL_COLOR_ARRAY); + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); + glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); + if(!wireframe) { + glTexCoordPointer(2, GL_FLOAT, stride, it.vertex->getUV1()); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); } - } - else - { - glColor3d(0,0,0); - } - - // use glDrawElements to draw each vertexarray - for (vt=0;vtgetLocalXYZ()); - glNormalPointer(GL_FLOAT,vtxstride,vertexarray->getNormal()); - TexCoordPtr(vertexarray); - if(glIsEnabled(GL_COLOR_ARRAY)) - glColorPointer(4,GL_UNSIGNED_BYTE,vtxstride,vertexarray->getRGBA()); - - //if(m_Lock) - // local->Begin(vertexarrays[vt]->size()); // here the actual drawing takes places - glDrawElements(drawmode,numindices,GL_UNSIGNED_SHORT,&(indexarray[0])); - - //if(m_Lock) - // local->End(); + glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + + if(!wireframe) { + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } +} + +void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) +{ + static const GLsizei stride = sizeof(RAS_TexVert); + bool wireframe = m_drawingmode <= KX_WIREFRAME; + RAS_MeshSlot::iterator it; + GLenum drawmode; + + if(!wireframe) + EnableTextures(true); + + // use glDrawElements to draw each vertexarray + for(ms.begin(it); !ms.end(it); ms.next(it)) { + if(it.totindex == 0) + continue; + + // drawing mode + if(it.array->m_type == RAS_DisplayArray::TRIANGLE) + drawmode = GL_TRIANGLES; + else if(it.array->m_type == RAS_DisplayArray::QUAD) + drawmode = GL_QUADS; + else + drawmode = GL_LINES; + + // colors + if (drawmode != GL_LINES && !wireframe) { + if (ms.m_bObjectColor) { + const MT_Vector4& rgba = ms.m_RGBAcolor; + + glDisableClientState(GL_COLOR_ARRAY); + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + } + else { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + glEnableClientState(GL_COLOR_ARRAY); + } + } + else + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + + glVertexPointer(3, GL_FLOAT, stride, it.vertex->getXYZ()); + glNormalPointer(GL_FLOAT, stride, it.vertex->getNormal()); + if(!wireframe) { + TexCoordPtr(it.vertex); + if(glIsEnabled(GL_COLOR_ARRAY)) + glColorPointer(4, GL_UNSIGNED_BYTE, stride, it.vertex->getRGBA()); + } + + // here the actual drawing takes places + glDrawElements(drawmode, it.totindex, GL_UNSIGNED_SHORT, it.index); + } + + if(!wireframe) { + glDisableClientState(GL_COLOR_ARRAY); + EnableTextures(false); } } @@ -248,7 +229,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) for(unit=0; unitgetFlag() & TV_2NDUV && (int)tv->getUnit() == unit) { + if(tv->getFlag() & RAS_TexVert::SECOND_UV && (int)tv->getUnit() == unit) { glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert), tv->getUV2()); continue; @@ -257,7 +238,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getLocalXYZ()); + glTexCoordPointer(3, GL_FLOAT, sizeof(RAS_TexVert),tv->getXYZ()); break; case RAS_TEXCO_UV1: glTexCoordPointer(2, GL_FLOAT, sizeof(RAS_TexVert),tv->getUV1()); @@ -284,7 +265,7 @@ void RAS_VAOpenGLRasterizer::TexCoordPtr(const RAS_TexVert *tv) switch(m_attrib[unit]) { case RAS_TEXCO_ORCO: case RAS_TEXCO_GLOB: - glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getLocalXYZ()); + glVertexAttribPointerARB(unit, 3, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getXYZ()); break; case RAS_TEXCO_UV1: glVertexAttribPointerARB(unit, 2, GL_FLOAT, GL_FALSE, sizeof(RAS_TexVert), tv->getUV1()); @@ -313,11 +294,6 @@ void RAS_VAOpenGLRasterizer::EnableTextures(bool enable) TexCoGen *texco, *attrib; int unit, texco_num, attrib_num; - /* disable previously enabled texture coordinates and attributes. ideally - * this shouldn't be necessary .. */ - if(enable) - EnableTextures(false); - /* we cache last texcoords and attribs to ensure we disable the ones that * were actually last set */ if(enable) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h index e4cc4ace0e8..766bbfbed0e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h @@ -50,22 +50,10 @@ public: virtual void SetDrawingMode(int drawingmode); - virtual void IndexPrimitives( const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot); - - virtual void IndexPrimitivesMulti( - const vecVertexArray& vertexarrays, - const vecIndexArrays & indexarrays, - DrawMode mode, - bool useObjectColor, - const MT_Vector4& rgbacolor, - class KX_ListSlot** slot); - + virtual void IndexPrimitives(class RAS_MeshSlot& ms); + virtual void IndexPrimitivesMulti(class RAS_MeshSlot& ms); +private: virtual void EnableTextures(bool enable); //virtual bool QueryArrays(){return true;} //virtual bool QueryLists(){return m_Lock;} diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 0cf9c326370..8d46528f7f0 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -1,12 +1,9 @@ #!/usr/bin/python Import ('env') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - sources = env.Glob('*.cpp') incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' -incs += ' #extern/glew/include ' + env['BF_OPENGL_INC'] +incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] env.BlenderLib ( 'bf_oglrasterizer', Split(sources), Split(incs), [], libtype=['game','player'], priority=[40, 120] ) diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index b74cb9cfcac..50331d7a664 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -26,99 +26,82 @@ * ***** END GPL LICENSE BLOCK ***** */ -#ifdef HAVE_CONFIG_H -#include -#endif - #ifdef WIN32 - #pragma warning (disable:4786) #endif #include "RAS_Polygon.h" -RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, - bool visible, - int numverts, - int vtxarrayindex) - :m_bucket(bucket), - m_vertexindexbase(numverts), - m_numverts(numverts), - m_edgecode(65535) +RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray *darray, int numvert) { - m_vertexindexbase.m_vtxarray = vtxarrayindex ;//m_bucket->FindVertexArray(numverts); - m_polyFlags.Visible = visible; + m_bucket = bucket; + m_darray = darray; + m_offset[0]= m_offset[1]= m_offset[2]= m_offset[3]= 0; + m_numvert = numvert; + + m_edgecode = 255; + m_polyflags = 0; } - - int RAS_Polygon::VertexCount() { - return m_numverts; + return m_numvert; } - - -void RAS_Polygon::SetVertex(int i, - unsigned int vertexindex ) //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal) +void RAS_Polygon::SetVertexOffset(int i, unsigned short offset) { - m_vertexindexbase.SetIndex(i,vertexindex); //m_bucket->FindOrAddVertex(m_vertexindexbase.m_vtxarray, - //xyz,uv,rgbacolor,normal)); + m_offset[i] = offset; } - - -const KX_VertexIndex& RAS_Polygon::GetIndexBase() +RAS_TexVert *RAS_Polygon::GetVertex(int i) { - return m_vertexindexbase; + return &m_darray->m_vertex[m_offset[i]]; } - - -void RAS_Polygon::SetVisibleWireframeEdges(int edgecode) +int RAS_Polygon::GetVertexOffset(int i) { - m_edgecode = edgecode; + return m_offset[i]; } - - -// each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. int RAS_Polygon::GetEdgeCode() { return m_edgecode; } +void RAS_Polygon::SetEdgeCode(int edgecode) +{ + m_edgecode = edgecode; +} bool RAS_Polygon::IsVisible() { - return m_polyFlags.Visible; + return (m_polyflags & VISIBLE) != 0; } - +void RAS_Polygon::SetVisible(bool visible) +{ + if(visible) m_polyflags |= VISIBLE; + else m_polyflags &= ~VISIBLE; +} bool RAS_Polygon::IsCollider() { - return m_polyFlags.Collider; + return (m_polyflags & COLLIDER) != 0; } - - -void RAS_Polygon::SetCollider(bool col) +void RAS_Polygon::SetCollider(bool visible) { - m_polyFlags.Collider = col; + if(visible) m_polyflags |= COLLIDER; + else m_polyflags &= ~COLLIDER; } - - -KX_VertexIndex& RAS_Polygon::GetVertexIndexBase() -{ - return m_vertexindexbase; -} - - - -RAS_MaterialBucket* RAS_Polygon::GetMaterial() +RAS_MaterialBucket* RAS_Polygon::GetMaterial() { return m_bucket; } + +RAS_DisplayArray* RAS_Polygon::GetDisplayArray() +{ + return m_darray; +} diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h index 7ce7926a816..18526ba45f7 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.h +++ b/source/gameengine/Rasterizer/RAS_Polygon.h @@ -35,55 +35,47 @@ #include using namespace std; - -// -// Bitfield that stores the flags for each CValue derived class -// -struct PolygonFlags { - PolygonFlags() : - Visible(true), - Collider(true) - { - } - unsigned char Visible : 1; - unsigned char Collider : 1; - //int Visible : 1; - //int Collider : 1; -}; +/* polygon flags */ class RAS_Polygon { + /* location */ RAS_MaterialBucket* m_bucket; - KX_VertexIndex m_vertexindexbase; - int m_numverts; - int m_edgecode; - PolygonFlags m_polyFlags; - + RAS_DisplayArray* m_darray; + unsigned short m_offset[4]; + unsigned short m_numvert; + + /* flags */ + unsigned char m_edgecode; + unsigned char m_polyflags; public: - RAS_Polygon(RAS_MaterialBucket* bucket, - bool visible, - int numverts, - int vtxarrayindex) ; + enum { + VISIBLE = 1, + COLLIDER = 2 + }; + + RAS_Polygon(RAS_MaterialBucket* bucket, RAS_DisplayArray* darray, int numvert); virtual ~RAS_Polygon() {}; -// RAS_TexVert* GetVertex(int index); int VertexCount(); - void SetVertex(int i, unsigned int vertexindex); //const MT_Point3& xyz,const MT_Point2& uv,const unsigned int rgbacolor,const MT_Vector3& normal) - - const KX_VertexIndex& GetIndexBase(); + RAS_TexVert* GetVertex(int i); - void SetVisibleWireframeEdges(int edgecode); + void SetVertexOffset(int i, unsigned short offset); + int GetVertexOffset(int i); + // each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. int GetEdgeCode(); + void SetEdgeCode(int edgecode); bool IsVisible(); + void SetVisible(bool visible); + bool IsCollider(); - void SetCollider(bool col); + void SetCollider(bool collider); - KX_VertexIndex& GetVertexIndexBase(); RAS_MaterialBucket* GetMaterial(); - + RAS_DisplayArray* GetDisplayArray(); }; #endif diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 935633dc636..d6f1fe912be 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -27,12 +27,7 @@ */ #include "RAS_TexVert.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -#define SHORT(x) short(x*32767.0) +#include "MT_Matrix4x4.h" RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Point2& uv, @@ -40,7 +35,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const short flag, + const bool flat, const unsigned int origindex) { xyz.getValue(m_localxyz); @@ -49,7 +44,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, SetRGBA(rgba); SetNormal(normal); tangent.getValue(m_tangent); - m_flag = flag; + m_flag = (flat)? FLAT: 0; m_origindex = origindex; m_unit = 2; } @@ -101,7 +96,7 @@ void RAS_TexVert::SetFlag(const short flag) void RAS_TexVert::SetUnit(const unsigned int u) { - m_unit = u<=TV_MAX?u:TV_MAX; + m_unit = u<=MAX_UNIT?u:MAX_UNIT; } void RAS_TexVert::SetNormal(const MT_Vector3& normal) @@ -109,12 +104,18 @@ void RAS_TexVert::SetNormal(const MT_Vector3& normal) normal.getValue(m_normal); } +void RAS_TexVert::SetTangent(const MT_Vector3& tangent) +{ + tangent.getValue(m_tangent); +} + // compare two vertices, and return TRUE if both are almost identical (they can be shared) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { return (m_flag == other->m_flag && m_rgba == other->m_rgba && MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) && + MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) && MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) && MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) && // p -- MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))) ; @@ -131,11 +132,10 @@ unsigned int RAS_TexVert::getUnit() const return m_unit; } - -void RAS_TexVert::getOffsets(void* &xyz, void* &uv1, void* &rgba, void* &normal) const +void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) { - xyz = (void *) m_localxyz; - uv1 = (void *) m_uv1; - rgba = (void *) &m_rgba; - normal = (void *) m_normal; + SetXYZ((mat*MT_Vector4(m_localxyz[0], m_localxyz[1], m_localxyz[2], 1.0)).getValue()); + SetNormal((nmat*MT_Vector4(m_normal[0], m_normal[1], m_normal[2], 1.0)).getValue()); + SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } + diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index bf092b4b230..4ec4db19e53 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -37,11 +37,6 @@ static MT_Point3 g_pt3; static MT_Point2 g_pt2; -#define TV_CALCFACENORMAL 0x0001 -#define TV_2NDUV 0x0002 - -#define TV_MAX 3//match Def in BL_Material.h - class RAS_TexVert { @@ -59,6 +54,12 @@ class RAS_TexVert // 32 bytes total size, fits nice = 56 = not fit nice. // We'll go for 64 bytes total size - 24 bytes left. public: + enum { + FLAT = 1, + SECOND_UV = 2, + MAX_UNIT = 8 + }; + short getFlag() const; unsigned int getUnit() const; @@ -70,7 +71,7 @@ public: const MT_Vector4& tangent, const unsigned int rgba, const MT_Vector3& normal, - const short flag, + const bool flat, const unsigned int origindex); ~RAS_TexVert() {}; @@ -82,7 +83,7 @@ public: return m_uv2; }; - const float* getLocalXYZ() const { + const float* getXYZ() const { return m_localxyz; }; @@ -108,20 +109,19 @@ public: void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); + void SetTangent(const MT_Vector3& tangent); void SetFlag(const short flag); void SetUnit(const unsigned u); void SetRGBA(const MT_Vector4& rgba); const MT_Point3& xyz(); - // compare two vertices, and return TRUE if both are almost identical (they can be shared) - bool closeTo(const RAS_TexVert* other); + void Transform(const class MT_Matrix4x4& mat, + const class MT_Matrix4x4& nmat); - bool closeTo(const MT_Point3& otherxyz, - const MT_Point2& otheruv, - const unsigned int otherrgba, - short othernormal[3]) const; - void getOffsets(void*&xyz, void *&uv1, void *&rgba, void *&normal) const; + // compare two vertices, to test if they can be shared, used for + // splitting up based on uv's, colors, etc + bool closeTo(const RAS_TexVert* other); }; #endif //__RAS_TEXVERT diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index e6bc657ed6d..a024f7e0ee6 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -3,11 +3,8 @@ Import ('env') sources = env.Glob('*.cpp') -if env['WITH_BF_GLEXT'] == 1: - env['CPPFLAGS'].append('-DWITH_GLEXT') - -incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions' +incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna' incs += ' ' + env['BF_PYTHON_INC'] if env['OURPLATFORM']=='win32-vc': diff --git a/source/kernel/gen_system/GEN_Map.h b/source/kernel/gen_system/GEN_Map.h index 37c75d8293a..88c79293223 100644 --- a/source/kernel/gen_system/GEN_Map.h +++ b/source/kernel/gen_system/GEN_Map.h @@ -50,6 +50,19 @@ public: m_buckets[i] = 0; } } + + GEN_Map(const GEN_Map& map) + { + m_num_buckets = map.m_num_buckets; + m_buckets = new Entry *[m_num_buckets]; + + for (int i = 0; i < m_num_buckets; ++i) { + m_buckets[i] = 0; + + for(Entry *entry = map.m_buckets[i]; entry; entry=entry->m_next) + insert(entry->m_key, entry->m_value); + } + } int size() { int count=0; diff --git a/source/nan_definitions.mk b/source/nan_definitions.mk index 9c1a28de999..424a7c558d7 100644 --- a/source/nan_definitions.mk +++ b/source/nan_definitions.mk @@ -56,9 +56,6 @@ all debug:: # Object Config_Guess DIRectory export OCGDIR = $(NAN_OBJDIR)/$(CONFIG_GUESS) - export WITH_GLEXT?=true - export WITH_BF_GLEXT?=$(WITH_GLEXT) - # Determines what targets are built export WITH_BF_DYNAMICOPENGL ?= true export WITH_BF_STATICOPENGL ?= false @@ -287,7 +284,7 @@ endif export FREEDESKTOP ?= true export NAN_PYTHON ?= /usr/local - export NAN_PYTHON_VERSION ?= 2.3 + export NAN_PYTHON_VERSION ?= 2.5 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 ?= /usr/local @@ -302,9 +299,9 @@ endif export NAN_NSPR ?= /usr/local export NAN_FREETYPE ?= $(LCGDIR)/freetype export NAN_GETTEXT ?= $(LCGDIR)/gettext - export NAN_SDL ?= $(shell sdl11-config --prefix) - export NAN_SDLLIBS ?= $(shell sdl11-config --libs) - export NAN_SDLCFLAGS ?= $(shell sdl11-config --cflags) + 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 diff --git a/tools/Blender.py b/tools/Blender.py index 2c982a0a46f..8f565174b0e 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -111,24 +111,35 @@ def setup_staticlibs(lenv): '/usr/lib', lenv['BF_PYTHON_LIBPATH'], lenv['BF_OPENGL_LIBPATH'], - lenv['BF_SDL_LIBPATH'], lenv['BF_JPEG_LIBPATH'], lenv['BF_PNG_LIBPATH'], lenv['BF_ZLIB_LIBPATH'], lenv['BF_ICONV_LIBPATH'] ] - libincs += Split(lenv['BF_OPENEXR_LIBPATH']) - libincs += Split(lenv['BF_FFMPEG_LIBPATH']) + if lenv['WITH_BF_SDL']: + libincs += Split(lenv['BF_SDL_LIBPATH']) + if lenv['WITH_BF_FFMPEG']: + libincs += Split(lenv['BF_FFMPEG_LIBPATH']) + if lenv['WITH_BF_STATICCXX']: + statlibs += Split(lenv['BF_CXX_LIB_STATIC']) + if lenv['WITH_BF_OPENEXR']: + libincs += Split(lenv['BF_OPENEXR_LIBPATH']) + if lenv['WITH_BF_STATICOPENEXR']: + statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC']) if lenv['WITH_BF_INTERNATIONAL']: libincs += Split(lenv['BF_GETTEXT_LIBPATH']) libincs += Split(lenv['BF_FREETYPE_LIBPATH']) if lenv['WITH_BF_OPENAL']: libincs += Split(lenv['BF_OPENAL_LIBPATH']) - + if lenv['WITH_BF_STATICOPENAL']: + statlibs += Split(lenv['BF_OPENAL_LIB_STATIC']) if lenv['WITH_BF_STATICOPENGL']: statlibs += Split(lenv['BF_OPENGL_LIB_STATIC']) + if lenv['WITH_BF_STATICPYTHON']: + statlibs += Split(lenv['BF_PYTHON_LIB_STATIC']) + if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'): libincs += Split(lenv['BF_PTHREADS_LIBPATH']) @@ -141,24 +152,29 @@ def setup_syslibs(lenv): lenv['BF_PNG_LIB'], lenv['BF_ZLIB_LIB'] ] - if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): - syslibs.append(lenv['BF_PYTHON_LIB']+'_d') - else: - syslibs.append(lenv['BF_PYTHON_LIB']) + + if not lenv['WITH_BF_STATICPYTHON']: + if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): + syslibs.append(lenv['BF_PYTHON_LIB']+'_d') + else: + syslibs.append(lenv['BF_PYTHON_LIB']) if lenv['WITH_BF_INTERNATIONAL']: syslibs += Split(lenv['BF_FREETYPE_LIB']) syslibs += Split(lenv['BF_GETTEXT_LIB']) if lenv['WITH_BF_OPENAL']: - syslibs += Split(lenv['BF_OPENAL_LIB']) + if not lenv['WITH_BF_STATICOPENAL']: + syslibs += Split(lenv['BF_OPENAL_LIB']) if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc': syslibs += ['gomp'] if lenv['WITH_BF_ICONV']: syslibs += Split(lenv['BF_ICONV_LIB']) if lenv['WITH_BF_OPENEXR']: - syslibs += Split(lenv['BF_OPENEXR_LIB']) + if not lenv['WITH_BF_STATICOPENEXR']: + syslibs += Split(lenv['BF_OPENEXR_LIB']) if lenv['WITH_BF_FFMPEG']: syslibs += Split(lenv['BF_FFMPEG_LIB']) - syslibs += Split(lenv['BF_SDL_LIB']) + if lenv['WITH_BF_SDL']: + syslibs += Split(lenv['BF_SDL_LIB']) if not lenv['WITH_BF_STATICOPENGL']: syslibs += Split(lenv['BF_OPENGL_LIB']) if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross'): diff --git a/tools/btools.py b/tools/btools.py index a25120f6c4b..8fb38646432 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -27,12 +27,12 @@ def print_arguments(args, bc): def validate_arguments(args, bc): opts_list = [ - 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', - 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', + 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', + 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', 'WITH_BF_FMOD', - 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', + 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC', 'WITH_BF_DDS', 'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC', 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', @@ -51,13 +51,13 @@ def validate_arguments(args, bc): 'WITH_BF_STATICOPENGL', 'BF_OPENGL', 'BF_OPENGL_INC', 'BF_OPENGL_LIB', 'BF_OPENGL_LIBPATH', 'BF_OPENGL_LIB_STATIC', 'BF_OPENGL_LINKFLAGS', 'WITH_BF_FTGL', 'BF_FTGL', 'BF_FTGL_INC', 'BF_FTGL_LIB', 'WITH_BF_PLAYER', - 'WITH_BF_GLEXT', 'WITH_BF_BINRELOC', 'CFLAGS', 'CCFLAGS', 'CPPFLAGS', 'REL_CFLAGS', 'REL_CCFLAGS', 'C_WARN', 'CC_WARN', 'LLIBS', 'PLATFORM_LINKFLAGS', - 'BF_PROFILE_FLAGS', 'LCGDIR', 'WITH_BF_VERSE', - 'BF_VERSE_INCLUDE', + 'BF_PROFILE_FLAGS', 'LCGDIR', + 'BF_CXX', 'WITH_BF_STATICCXX', 'BF_CXX_LIB_STATIC' + 'WITH_BF_VERSE', 'BF_VERSE_INCLUDE', 'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO', 'BF_TWEAK_MODE', 'BF_SPLIT_SRC', 'WITHOUT_BF_INSTALL', @@ -95,7 +95,7 @@ def print_targets(targs, bc): def validate_targets(targs, bc): valid_list = ['.', 'blender', 'blenderstatic', 'blenderplayer', 'webplugin', - 'blendernogame', 'blenderstaticnogame', 'release', + 'blendernogame', 'blenderstaticnogame', 'blenderlite', 'release', 'everything', 'clean', 'install-bin', 'install', 'nsis'] oklist = [] for t in targs: @@ -140,20 +140,27 @@ def read_opts(cfg, args): ('VERSE_BUILD_DIR', 'Target directory for intermediate files.', "${BF_BUILDDIR}/extern/verse"), ('VERSE_REGEN_PROTO', 'Whether to regenerate the protocol files', 'yes'), ('BF_DEBUG_LIBS', 'list of libraries to build with debug symbols'), + ('BF_PYTHON', 'base path for python', ''), ('BF_PYTHON_VERSION', 'Python version to use', ''), ('BF_PYTHON_INC', 'include path for Python headers', ''), ('BF_PYTHON_BINARY', 'Path to the Python interpreter', ''), ('BF_PYTHON_LIB', 'Python library', ''), + ('BF_PYTHON_LIB_STATIC', 'Python static libraries', ''), ('BF_PYTHON_LIBPATH', 'Library path', ''), ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), + (BoolOption('WITH_BF_STATICPYTHON', 'Staticly link to python', 'false')), + (BoolOption('BF_NO_ELBEEM', 'Disable Fluid Sim', 'false')), (BoolOption('WITH_BF_YAFRAY', 'Enable Yafray', 'true')), + (BoolOption('WITH_BF_OPENAL', 'Use OpenAL if true', '')), ('BF_OPENAL', 'base path for OpenAL', ''), ('BF_OPENAL_INC', 'include path for python headers', ''), ('BF_OPENAL_LIB', 'Path to OpenAL library', ''), + ('BF_OPENAL_LIB_STATIC', 'Path to OpenAL static library', ''), ('BF_OPENAL_LIBPATH', 'Path to OpenAL library', ''), + (BoolOption('WITH_BF_STATICOPENAL', 'Staticly link to openal', 'false')), (BoolOption('WITH_BF_SDL', 'Use SDL if true', '')), ('BF_SDL', 'SDL base path', ''), @@ -170,10 +177,12 @@ def read_opts(cfg, args): # BF_FMOD = $(LCGDIR)/fmod (BoolOption('WITH_BF_OPENEXR', 'Use OPENEXR if true', 'true')), + (BoolOption('WITH_BF_STATICOPENEXR', 'Staticly link to OpenEXR', 'false')), ('BF_OPENEXR', 'OPENEXR base path', ''), ('BF_OPENEXR_INC', 'OPENEXR include path', ''), ('BF_OPENEXR_LIB', 'OPENEXR library', ''), ('BF_OPENEXR_LIBPATH', 'OPENEXR library path', ''), + ('BF_OPENEXR_LIB_STATIC', 'OPENEXR static library', ''), (BoolOption('WITH_BF_DDS', 'Use DDS if true', 'true')), @@ -248,6 +257,9 @@ def read_opts(cfg, args): ('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', ''), + (BoolOption('WITH_BF_STATICCXX', 'static link to stdc++', 'false')), + ('BF_CXX_LIB_STATIC', 'static library path for stdc++', ''), ## ##WITH_BF_NSPR = 'true' ##BF_NSPR = $(LCGDIR)/nspr @@ -292,7 +304,6 @@ def read_opts(cfg, args): ('BF_FTGL_INC', 'FTGL include path', ''), ('BF_FTGL_LIB', 'FTGL libraries', ''), - (BoolOption('WITH_BF_GLEXT', 'Enable GL Extensions', 'true')), (BoolOption('WITH_BF_PLAYER', 'Build blenderplayer if true', 'false')), ('CFLAGS', 'C-compiler flags', ''), From 2911df487ede413fb6b83b2de199f50657cc5cfe Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Mon, 22 Sep 2008 22:48:44 +0000 Subject: [PATCH 06/10] Fixed shrinkwrap constraint handling of matrixs. Also since contraint uses BVHCache its now usable and fast. Being possible to shrinkwrap constraint several objects to another and only have one BVHTree being build. --- source/blender/blenkernel/intern/constraint.c | 49 ++++++++----------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index db173126375..6e94fc255ac 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3263,9 +3263,6 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr { bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data; - if (ct) - Mat4CpyMat4(ct->matrix, cob->startmat); - if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) ) { int fail = FALSE; @@ -3274,13 +3271,10 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr float dist; SpaceTransform transform; - DerivedMesh *target = CDDM_copy( object_get_derived_final(ct->tar, CD_MASK_BAREMESH) ); + DerivedMesh *target = object_get_derived_final(ct->tar, CD_MASK_BAREMESH); BVHTreeRayHit hit; BVHTreeNearest nearest; - //TODO - //Its stupid to create a bvhtree.. if we are only going to project one vertex - //But lets do it this way.. (so that in future maybe bvhtree gets a cache system and then the tree would already be build) BVHTreeFromMesh treeData; memset( &treeData, 0, sizeof(treeData) ); @@ -3290,15 +3284,22 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr hit.index = -1; hit.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it + Mat4One(ct->matrix); + if(target != NULL) { - - space_transform_from_matrixs(&transform, cob->startmat, ct->tar->obmat); + space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat); switch(scon->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: - bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6); + case MOD_SHRINKWRAP_NEAREST_VERTEX: + + if(scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) + bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6); + else + bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6); + if(treeData.tree == NULL) { fail = TRUE; @@ -3314,23 +3315,6 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr space_transform_invert(&transform, co); break; - case MOD_SHRINKWRAP_NEAREST_VERTEX: - bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6); - if(treeData.tree == NULL) - { - fail = TRUE; - break; - } - - space_transform_apply_normal(&transform, no); - - BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData); - - dist = VecLenf(co, nearest.co); - VecLerpf(co, co, nearest.co, (dist - scon->dist)/dist); //linear interpolation - space_transform_invert(&transform, co); - break; - case MOD_SHRINKWRAP_PROJECT: if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f; if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f; @@ -3365,8 +3349,15 @@ static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr target->release(target); - if(fail == FALSE) - VECADD(ct->matrix[3], ct->matrix[3], co); + if(fail == TRUE) + { + //Don't move the point + co[0] = co[1] = co[2] = 0.0f; + } + + //co is in local object coordinates, change it to global and update target position + VecMat4MulVecfl(co, cob->matrix, co); + VECCOPY(ct->matrix[3], co); } } } From 2ad14ba223916f07801a024b608a1c92e9f16d8f Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Tue, 23 Sep 2008 14:32:14 +0000 Subject: [PATCH 07/10] Changed SimpleDeform to be a single modifier with (Twist|Bend|Taper|Strech) options available on the modifier painel/options. --- source/blender/src/buttons_editing.c | 50 ++++------------------------ 1 file changed, 6 insertions(+), 44 deletions(-) diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 5aec47965fc..1df31d57649 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -960,39 +960,6 @@ static void modifiers_add(void *ob_v, int type) BIF_undo_push("Add modifier"); } -static void do_modifiers_select_simpledeform_typemenu(void *ob_v, int event) -{ - static const char *default_name[] = { "", "Twist", "Bend", "Taper", "Strech" }; - SimpleDeformModifierData *smd = (SimpleDeformModifierData*)modifier_new(eModifierType_SimpleDeform); - smd->mode = event; - - if(smd->mode >= 0 && smd->mode < sizeof(default_name)/sizeof(*default_name)) - strncpy( smd->modifier.name, default_name[ smd->mode ], sizeof(smd->modifier.name)); - - object_add_modifier((Object*) ob_v, (ModifierData*)smd); - BIF_undo_push("Add modifier"); - do_modifier_panels(B_MODIFIER_RECALC); -} - -static uiBlock *modifiers_select_simpledeform_typemenu(void *ob_v) -{ - uiBlock *block; - short yco = 20, menuwidth = 120; - - block= uiNewBlock(&curarea->uiblocks, "modifiers_select_simpledeform_typemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin); - uiBlockSetButmFunc(block, do_modifiers_select_simpledeform_typemenu, ob_v); - - uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Twist", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_TWIST, ""); - uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Bend", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_BEND, ""); - uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Taper", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_TAPER, ""); - uiDefBut(block, BUTM, B_MODIFIER_RECALC, "Stretch", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, MOD_SIMPLEDEFORM_MODE_STRETCH, ""); - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 50); - return block; -} - - typedef struct MenuEntry { char *name; int ID; @@ -1037,16 +1004,8 @@ static uiBlock *modifiers_add_menu(void *ob_v) for(i = 0; i < numEntries; ++i) { - if(entries[i].ID == eModifierType_SimpleDeform) - { - //TODO: this menu has a left space.. which loooks ugly :S - uiDefIconTextBlockBut(block, modifiers_select_simpledeform_typemenu, ob_v, ICON_RIGHTARROW_THIN, entries[i].name, 0, yco-=20, 160, 19, ""); - } - else - { - uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name, - 0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, ""); - } + uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name, + 0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, ""); } uiTextBoundsBlock(block, 50); @@ -1896,7 +1855,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco } else if (md->type==eModifierType_SimpleDeform) { SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md; - height += 19*4; + height += 19*5; if(smd->origin != NULL) height += 19; if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER ) @@ -2570,7 +2529,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco } else if (md->type==eModifierType_SimpleDeform) { SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md; + char simpledeform_modemenu[] = "Deform type%t|Twist %x1|Bend %x2|Taper %x3|Strech %x4"; + uiDefButC(block, MENU, B_MODIFIER_RECALC, simpledeform_modemenu, lx,(cy-=19),buttonWidth,19, &smd->mode, 0, 0, 0, 0, "Selects type of deform to apply to object."); + but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &smd->vgroup_name, 0, 31, 0, 0, "Vertex Group name"); uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob); From 09e17ac87623c8c790bb34dcca009932ae820a70 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 26 Sep 2008 02:02:02 +0000 Subject: [PATCH 08/10] SimpleDeform now initializes limit values to the BB when its added to an object --- source/blender/blenkernel/intern/modifier.c | 4 +- .../blender/blenkernel/intern/simple_deform.c | 116 ++++++++++-------- 2 files changed, 66 insertions(+), 54 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 16287d360b5..a48a3890398 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7364,8 +7364,8 @@ static void simpledeformModifier_initData(ModifierData *md) smd->origin = NULL; smd->factor = 0.35; - smd->limit[0] = -1000.0f; - smd->limit[1] = 1000.0f; + smd->limit[0] = FLT_MAX; + smd->limit[1] = -FLT_MAX; } static void simpledeformModifier_copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/blenkernel/intern/simple_deform.c b/source/blender/blenkernel/intern/simple_deform.c index 2984b8fe9d8..738cd53f581 100644 --- a/source/blender/blenkernel/intern/simple_deform.c +++ b/source/blender/blenkernel/intern/simple_deform.c @@ -35,6 +35,7 @@ #include "BKE_deform.h" #include "BKE_utildefines.h" #include "BLI_arithb.h" +#include "BKE_shrinkwrap.h" #include #include @@ -140,89 +141,100 @@ static void simpleDeform_bend(const float factor, const float dcut[3], float *co /* simple deform modifier */ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { - int i; - float (*ob2mod)[4] = NULL, (*mod2ob)[4] = NULL; - float tmp_matrix[2][4][4]; static const float lock_axis[2] = {0.0f, 0.0f}; + int i; + int limit_axis = 0; + SpaceTransform *transf = NULL, tmp_transf; + void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL; //Mode callback int vgroup = get_named_vertexgroup_num(ob, smd->vgroup_name); - MDeformVert *dvert = NULL; + //Safe-check + if(smd->origin == ob) smd->origin = NULL; //No self references + smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]); //Upper limit >= than lower limit + //Calculate matrixs do convert between coordinate spaces if(smd->origin) { - //inverse is outdated - + transf = &tmp_transf; + if(smd->originOpts & MOD_SIMPLEDEFORM_ORIGIN_LOCAL) { - Mat4Invert(smd->origin->imat, smd->origin->obmat); - Mat4Invert(ob->imat, ob->obmat); - - ob2mod = tmp_matrix[0]; - mod2ob = tmp_matrix[1]; - Mat4MulSerie(ob2mod, smd->origin->imat, ob->obmat, 0, 0, 0, 0, 0, 0); - Mat4Invert(mod2ob, ob2mod); + space_transform_from_matrixs(transf, ob->obmat, smd->origin->obmat); } else { - Mat4Invert(smd->origin->imat, smd->origin->obmat); - ob2mod = smd->origin->obmat; - mod2ob = smd->origin->imat; + Mat4CpyMat4(transf->local2target, smd->origin->obmat); + Mat4Invert(transf->target2local, transf->local2target); + } + } + + //Setup vars + limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z + + //Update limits if needed + if(smd->limit[1] == -FLT_MAX + || smd->limit[0] == FLT_MAX) + { + float lower = FLT_MAX; + float upper = -FLT_MAX; + + for(i=0; ilimit[1] = upper; + smd->limit[0] = lower; } if(dm) dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + + switch(smd->mode) + { + case MOD_SIMPLEDEFORM_MODE_TWIST: simpleDeform_callback = simpleDeform_twist; break; + case MOD_SIMPLEDEFORM_MODE_BEND: simpleDeform_callback = simpleDeform_bend; break; + case MOD_SIMPLEDEFORM_MODE_TAPER: simpleDeform_callback = simpleDeform_taper; break; + case MOD_SIMPLEDEFORM_MODE_STRETCH: simpleDeform_callback = simpleDeform_stretch; break; + default: + return; //No simpledeform mode? + } + for(i=0; ifactor; - if(weight == 0) continue; - - if(ob2mod) - Mat4MulVecfl(ob2mod, vertexCos[i]); - - VECCOPY(co, vertexCos[i]); - - dcut[0] = dcut[1] = dcut[2] = 0.0f; - if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut); - if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut); - - switch(smd->mode) + if(weight != 0.0f) { - case MOD_SIMPLEDEFORM_MODE_TWIST: - axis_limit(2, smd->limit, co, dcut); - simpleDeform_twist(factor, dcut, co); - break; + float co[3], dcut[3] = {0.0f, 0.0f, 0.0f}; - case MOD_SIMPLEDEFORM_MODE_BEND: - axis_limit(0, smd->limit, co, dcut); - simpleDeform_bend(factor, dcut, co); - break; + if(transf) space_transform_apply(transf, vertexCos[i]); - case MOD_SIMPLEDEFORM_MODE_TAPER: - axis_limit(2, smd->limit, co, dcut); - simpleDeform_taper(factor, dcut, co); - break; + VECCOPY(co, vertexCos[i]); + //Apply axis limits + if(smd->mode != MOD_SIMPLEDEFORM_MODE_BEND) //Bend mode shoulnt have any lock axis + { + if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut); + if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut); + } + axis_limit(limit_axis, smd->limit, co, dcut); - case MOD_SIMPLEDEFORM_MODE_STRETCH: - axis_limit(2, smd->limit, co, dcut); - simpleDeform_stretch(factor, dcut, co); - break; + simpleDeform_callback(smd->factor, dcut, co); //Apply deform + VecLerpf(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation + + if(transf) space_transform_invert(transf, vertexCos[i]); } - - //linear interpolation - VecLerpf(vertexCos[i], vertexCos[i], co, weight); - - if(mod2ob) - Mat4MulVecfl(mod2ob, vertexCos[i]); } } From 03f26fa6e4539c95e347587b38510ba8da747f2a Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 26 Sep 2008 13:47:41 +0000 Subject: [PATCH 09/10] Fixed a UI bug on shrinkwrap constraint Fixed vertexs weights on simpledeform modifier (they weren't working if the modifier was the first on stack, since it wasnt receiving a DerivedMesh with vertex weights) --- source/blender/blenkernel/intern/modifier.c | 61 +++++++++++++++++---- source/blender/src/buttons_object.c | 2 +- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a48a3890398..2bdcebdbb93 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7380,16 +7380,6 @@ static void simpledeformModifier_copyData(ModifierData *md, ModifierData *target memcpy(tsmd->limit, smd->limit, sizeof(tsmd->limit)); } -static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) -{ - SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, derivedData, vertexCos, numVerts); -} - -static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) -{ - SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, derivedData, vertexCos, numVerts); -} - static CustomDataMask simpledeformModifier_requiredDataMask(ModifierData *md) { SimpleDeformModifierData *smd = (SimpleDeformModifierData *)md; @@ -7416,6 +7406,57 @@ static void simpledeformModifier_updateDepgraph(ModifierData *md, DagForest *for dag_add_relation(forest, dag_get_node(forest, smd->origin), obNode, DAG_RL_OB_DATA, "SimpleDeform Modifier"); } +static void simpledeformModifier_deformVerts(ModifierData *md, Object *ob, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); + + /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + if(dataMask) + { + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_mesh(ob->data, ob); + else return; + + if(dataMask & CD_MVERT) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + } + + SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); + +} + +static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, EditMesh *editData, DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts) +{ + DerivedMesh *dm = NULL; + CustomDataMask dataMask = simpledeformModifier_requiredDataMask(md); + + /* We implement requiredDataMask but thats not really usefull since mesh_calc_modifiers pass a NULL derivedData or without the modified vertexs applied */ + if(dataMask) + { + if(derivedData) dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) dm = CDDM_from_editmesh(editData, ob->data); + else return; + + if(dataMask & CD_MVERT) + { + CDDM_apply_vert_coords(dm, vertexCos); + CDDM_calc_normals(dm); + } + } + + SimpleDeformModifier_do((SimpleDeformModifierData*)md, ob, dm, vertexCos, numVerts); + + if(dm) + dm->release(dm); +} + /***/ static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES]; diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index a18950157b2..2023144aebd 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -1747,7 +1747,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s bShrinkwrapConstraint *data = con->data; char shrinktypemenu[]="Shrinkwrap type%t|nearest surface point %x0|projection %x1|nearest vertex %x2"; - height = 60; + height = 78; if(data->shrinkType == MOD_SHRINKWRAP_PROJECT) height += 18; From b542721f329304f2dc582436b3a5de92dc045956 Mon Sep 17 00:00:00 2001 From: Andre Susano Pinto Date: Fri, 26 Sep 2008 16:14:35 +0000 Subject: [PATCH 10/10] Made simple deform limits be relative to BV of object --- source/blender/blenkernel/intern/modifier.c | 8 +++--- .../blender/blenkernel/intern/simple_deform.c | 25 ++++++++++++------- source/blender/src/buttons_editing.c | 4 +-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2bdcebdbb93..6f52f923a08 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -7360,12 +7360,12 @@ static void simpledeformModifier_initData(ModifierData *md) SimpleDeformModifierData *smd = (SimpleDeformModifierData*) md; smd->mode = MOD_SIMPLEDEFORM_MODE_TWIST; - smd->axis = 0; + smd->axis = 0; smd->origin = NULL; - smd->factor = 0.35; - smd->limit[0] = FLT_MAX; - smd->limit[1] = -FLT_MAX; + smd->factor = 0.35f; + smd->limit[0] = 0.0f; + smd->limit[1] = 1.0f; } static void simpledeformModifier_copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/blenkernel/intern/simple_deform.c b/source/blender/blenkernel/intern/simple_deform.c index 738cd53f581..0eb710fa48e 100644 --- a/source/blender/blenkernel/intern/simple_deform.c +++ b/source/blender/blenkernel/intern/simple_deform.c @@ -144,7 +144,8 @@ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, s static const float lock_axis[2] = {0.0f, 0.0f}; int i; - int limit_axis = 0; + int limit_axis = 0; + float smd_limit[2], smd_factor; SpaceTransform *transf = NULL, tmp_transf; void (*simpleDeform_callback)(const float factor, const float dcut[3], float *co) = NULL; //Mode callback int vgroup = get_named_vertexgroup_num(ob, smd->vgroup_name); @@ -152,6 +153,10 @@ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, s //Safe-check if(smd->origin == ob) smd->origin = NULL; //No self references + + if(smd->limit[0] < 0.0) smd->limit[0] = 0.0f; + if(smd->limit[0] > 1.0) smd->limit[0] = 1.0f; + smd->limit[0] = MIN2(smd->limit[0], smd->limit[1]); //Upper limit >= than lower limit //Calculate matrixs do convert between coordinate spaces @@ -174,8 +179,6 @@ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, s limit_axis = (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) ? 0 : 2; //Bend limits on X.. all other modes limit on Z //Update limits if needed - if(smd->limit[1] == -FLT_MAX - || smd->limit[0] == FLT_MAX) { float lower = FLT_MAX; float upper = -FLT_MAX; @@ -183,16 +186,20 @@ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, s for(i=0; ilimit[1] = upper; - smd->limit[0] = lower; + + //SMD values are normalized to the BV, calculate the absolut values + smd_limit[1] = lower + (upper-lower)*smd->limit[1]; + smd_limit[0] = lower + (upper-lower)*smd->limit[0]; + + smd_factor = smd->factor / MAX2(FLT_EPSILON, smd_limit[1]-smd_limit[0]); } @@ -228,9 +235,9 @@ void SimpleDeformModifier_do(SimpleDeformModifierData *smd, struct Object *ob, s if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_X) axis_limit(0, lock_axis, co, dcut); if(smd->axis & MOD_SIMPLEDEFORM_LOCK_AXIS_Y) axis_limit(1, lock_axis, co, dcut); } - axis_limit(limit_axis, smd->limit, co, dcut); + axis_limit(limit_axis, smd_limit, co, dcut); - simpleDeform_callback(smd->factor, dcut, co); //Apply deform + simpleDeform_callback(smd_factor, dcut, co); //Apply deform VecLerpf(vertexCos[i], vertexCos[i], co, weight); //Use vertex weight has coef of linear interpolation if(transf) space_transform_invert(transf, vertexCos[i]); diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 1df31d57649..339a4ea6714 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -2542,8 +2542,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefButF(block, NUM, B_MODIFIER_RECALC, "Factor:", lx,(cy-=19),buttonWidth,19, &smd->factor, -10.0f, 10.0f, 0.5f, 0, "Deform Factor"); - uiDefButF(block, NUM, B_MODIFIER_RECALC, "Upper Limit:", lx,(cy-=19),buttonWidth,19, &smd->limit[1], -1000.0f, 1000.0f, 5.0f, 0, "Upper Limit Bend on X"); - uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lower Limit:", lx,(cy-=19),buttonWidth,19, &smd->limit[0], -1000.0f, 1000.0f, 5.0f, 0, "Lower Limit Bend on X"); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "Upper Limit:", lx,(cy-=19),buttonWidth,19, &smd->limit[1], 0.0f, 1.0f, 5.0f, 0, "Upper Limit for deform"); + uiDefButF(block, NUM, B_MODIFIER_RECALC, "Lower Limit:", lx,(cy-=19),buttonWidth,19, &smd->limit[0], 0.0f, 1.0f, 5.0f, 0, "Lower Limit for deform"); if(smd->mode == MOD_SIMPLEDEFORM_MODE_STRETCH || smd->mode == MOD_SIMPLEDEFORM_MODE_TAPER )